/*************************************************************************** * * Copyright 2015-2019 BES. * All rights reserved. All unpublished rights reserved. * * No part of this work may be used or reproduced in any form or by any * means, or stored in a database or retrieval system, without prior written * permission of BES. * * Use of this work is governed by a license granted by BES. * This work contains confidential and proprietary information of * BES. which is protected by copyright, trade secret, * trademark and other intellectual property rights. * ****************************************************************************/ #include "analog.h" #include "cmsis.h" #include "cmsis_nvic.h" #include "hal_aud.h" #include "hal_cache.h" #include "hal_chipid.h" #include "hal_cmu.h" #include "hal_location.h" #include "hal_psc.h" #include "hal_sysfreq.h" #include "hal_timer.h" #include "hal_trace.h" #include "pmu.h" #include "tgt_hardware.h" #include "usbphy.h" #define PMU_LED_VIA_PWM #define DCDC_ULP_LP_ON // LDO soft start interval is about 1000 us #define PMU_LDO_PU_STABLE_TIME_US 1800 #define PMU_DCDC_PU_STABLE_TIME_US 100 #define PMU_VANA_STABLE_TIME_US 10 #define PMU_VCORE_STABLE_TIME_US 10 #ifdef __PMU_VIO_DYNAMIC_CTRL_MODE__ #define IO_VOLT_ACTIVE_NORMAL PMU_IO_2_6V #else #define IO_VOLT_ACTIVE_NORMAL PMU_IO_2_6V #endif #ifdef DIGMIC_HIGH_VOLT #define IO_VOLT_ACTIVE_RISE PMU_IO_3_0V #else #define IO_VOLT_ACTIVE_RISE PMU_IO_2_8V #endif #define IO_VOLT_SLEEP PMU_IO_2_6V #define HPPA_RAMP_UP_VOLT_MV 1950 #define PMU_DCDC_ANA_2_1V 0xF0 #define PMU_DCDC_ANA_2_0V 0xE0 #define PMU_DCDC_ANA_1_9V 0xD0 #define PMU_DCDC_ANA_1_8V 0xC0 #define PMU_DCDC_ANA_1_7V 0xB0 #define PMU_DCDC_ANA_1_6V 0xA0 #define PMU_DCDC_ANA_1_5V 0x90 #define PMU_DCDC_ANA_1_4V 0x80 #define PMU_DCDC_ANA_1_35V 0x77 #define PMU_DCDC_ANA_1_3V 0x70 #define PMU_DCDC_ANA_1_2V 0x60 #define PMU_DCDC_ANA_1_1V 0x50 #define PMU_DCDC_ANA_1_0V 0x40 #define PMU_DCDC_ANA_SLEEP_1_3V PMU_DCDC_ANA_1_3V #define PMU_DCDC_ANA_SLEEP_1_2V PMU_DCDC_ANA_1_2V #define PMU_DCDC_ANA_SLEEP_1_1V PMU_DCDC_ANA_1_1V #define PMU_DCDC_ANA_SLEEP_1_0V PMU_DCDC_ANA_1_0V #define PMU_VBUCK2ANA_1_5V 0x30 #define PMU_VBUCK2ANA_1_4V 0x2C #define PMU_VBUCK2ANA_1_3V 0x28 #define PMU_VBUCK2ANA_1_2V 0x24 #define PMU_VBUCK2ANA_1_1V 0x20 #define PMU_VBUCK2ANA_1_0V 0x1C #define PMU_DCDC_DIG_1_1V 0xFF #define PMU_DCDC_DIG_1_05V 0xF0 #define PMU_DCDC_DIG_1_0V 0xE0 #define PMU_DCDC_DIG_0_95V 0xD0 #define PMU_DCDC_DIG_0_9V 0xC0 #define PMU_DCDC_DIG_0_85V 0xB0 #define PMU_DCDC_DIG_0_8V 0xA0 #define PMU_DCDC_DIG_0_75V 0x90 #define PMU_DCDC_DIG_0_7V 0x80 #define PMU_DCDC_DIG_0_65V 0x70 #define PMU_DCDC_DIG_0_6V 0x60 #define PMU_DCDC_DIG_0_55V 0x50 #define PMU_DCDC_DIG_0_5V 0x40 #define PMU_DCDC_DIG_0_45V 0x30 #define PMU_DCDC_DIG_0_4V 0x20 #define PMU_VDIG_1_2V 0x24 #define PMU_VDIG_1_1V 0x20 #define PMU_VDIG_1_05V 0x1E #define PMU_VDIG_1_0V 0x1C #define PMU_VDIG_0_95V 0x1A #define PMU_VDIG_0_9V 0x18 #define PMU_VDIG_0_85V 0x16 #define PMU_VDIG_0_8V 0x14 #define PMU_VDIG_0_75V 0x12 #define PMU_VDIG_0_7V 0x10 #define PMU_VDIG_0_65V 0x0E #define PMU_VDIG_0_6V 0x0C #define PMU_VDIG_0_55V 0x0A #define PMU_VDIG_0_5V 0x08 #define PMU_VDIG_0_45V 0x06 #define PMU_VDIG_0_4V 0x04 #define PMU_VDIG_MAX PMU_VDIG_1_2V #define PMU_IO_3_3V 0x15 #define PMU_IO_3_2V 0x14 #define PMU_IO_3_1V 0x13 #define PMU_IO_3_0V 0x12 #define PMU_IO_2_9V 0x11 #define PMU_IO_2_8V 0x10 #define PMU_IO_2_7V 0xF #define PMU_IO_2_6V 0xE #define PMU_IO_2_5V 0xD #define PMU_IO_2_4V 0xC #define PMU_IO_2_3V 0xB #define PMU_IO_2_2V 0xA #define PMU_IO_2_1V 0x9 #define PMU_IO_2_0V 0x8 #define PMU_IO_1_9V 0x7 #define PMU_IO_1_8V 0x6 #define PMU_IO_1_7V 0x5 #define PMU_VMEM_2_8V 0x10 #define PMU_VMEM_2_0V 0x8 #define PMU_VMEM_1_9V 0x7 #define PMU_VMEM_1_8V 0x6 #define PMU_VMEM_1_7V 0x5 #define PMU_VMEM_1_6V 0x4 #define PMU_CODEC_2_7V 0xF #define PMU_CODEC_2_6V 0xE #define PMU_CODEC_2_5V 0xD #define PMU_CODEC_2_4V 0xC #define PMU_CODEC_2_3V 0xB #define PMU_CODEC_2_2V 0xA #define PMU_CODEC_2_1V 0x9 #define PMU_CODEC_2_0V 0x8 #define PMU_CODEC_1_9V 0x7 #define PMU_CODEC_1_8V 0x6 #define PMU_CODEC_1_7V 0x5 #define PMU_CODEC_1_6V 0x4 #define PMU_CODEC_1_5V 0x3 #define PMU_HPPA2CODEC_2_3V 0x1C #define PMU_HPPA2CODEC_2_2V 0x18 #define PMU_HPPA2CODEC_2_1V 0x14 #define PMU_HPPA2CODEC_2_0V 0x10 #define PMU_HPPA2CODEC_1_95V 0xE #define PMU_HPPA2CODEC_1_9V 0xC #define PMU_HPPA2CODEC_1_8V 0x8 #define PMU_HPPA2CODEC_1_7V 0x4 #define PMU_HPPA2CODEC_1_6V 0x0 #define PMU_USB_3_4V 0xA #define PMU_USB_3_3V 0x9 #define PMU_USB_3_2V 0x8 #define PMU_USB_3_1V 0x7 #define PMU_USB_3_0V 0x6 #define PMU_USB_2_9V 0x5 #define PMU_USB_2_8V 0x4 #define PMU_USB_2_7V 0x3 #define PMU_USB_2_6V 0x2 #define PMU_VHPPA_2_0V 0x8 #define PMU_VHPPA_1_9V 0x7 #define PMU_VHPPA_1_8V 0x6 #define PMU_VHPPA_1_7V 0x5 #define PMU_VHPPA_1_6V 0x4 #define PMU_VHPPA_1_5V 0x3 #define PMU_DCDC_HPPA_2_1V 0xF0 #define PMU_DCDC_HPPA_2_0V 0xE0 #define PMU_DCDC_HPPA_1_95V 0xD8 #define PMU_DCDC_HPPA_1_9V 0xD0 #define PMU_DCDC_HPPA_1_8V 0xC0 #define PMU_DCDC_HPPA_1_7V 0xB0 #define PMU_DCDC_HPPA_1_6V 0xA0 #define PMU_DCDC_HPPA_1_5V 0x90 #define PMU_DCDC_HPPA_1_4V 0x80 #define PMU_DCDC_HPPA_1_3V 0x70 #define PMU_DCDC_HPPA_1_2V 0x60 #define PMU_VMIC_3_3V 0x14 #define PMU_VMIC_3_2V 0x13 #define PMU_VMIC_3_1V 0x12 #define PMU_VMIC_3_0V 0x11 #define PMU_VMIC_2_9V 0x10 #define PMU_VMIC_2_8V 0xF #define PMU_VMIC_2_7V 0xF #define PMU_VMIC_2_6V 0xE #define PMU_VMIC_2_5V 0xD #define PMU_VMIC_2_4V 0xC #define PMU_VMIC_2_3V 0xB #define PMU_VMIC_2_2V 0xA #define PMU_VMIC_2_1V 0x9 #define PMU_VMIC_2_0V 0x8 #define PMU_VMIC_1_9V 0x7 #define PMU_VMIC_1_8V 0x6 #define PMU_VMIC_1_7V 0x5 #define PMU_VMIC_1_6V 0x4 #define PMU_VMIC_RES_3_3V 0xF #define PMU_VMIC_RES_2_8V 0xA #define PMU_VMIC_RES_2_2V 0x4 // 00 PMU_REG_METAL_ID #define PMU_METAL_ID_SHIFT 0 #define PMU_METAL_ID_MASK (0xF << PMU_METAL_ID_SHIFT) #define PMU_METAL_ID(n) (((n)&0xF) << PMU_METAL_ID_SHIFT) // 02 PMU_REG_POWER_KEY_CFG #define REG_PU_VBAT_DIV (1 << 15) #define PU_LPO_DR (1 << 14) #define PU_LPO_REG (1 << 13) #define POWERKEY_WAKEUP_OSC_EN (1 << 12) #define RTC_POWER_ON_EN (1 << 11) #define PU_ALL_REG (1 << 10) #define CLK_32K_SEL_SHIFT 8 #define CLK_32K_SEL_MASK (0x3 << CLK_32K_SEL_SHIFT) #define CLK_32K_SEL(n) BITFIELD_VAL(CLK_32K_SEL, n) #define DEEPSLEEP_MODE_DIGI_DR (1 << 7) #define DEEPSLEEP_MODE_DIGI_REG (1 << 6) #define REG_VCORE_SSTIME_MODE_SHIFT 4 #define REG_VCORE_SSTIME_MODE_MASK (0x3 << REG_VCORE_SSTIME_MODE_SHIFT) #define REG_VCORE_SSTIME_MODE(n) BITFIELD_VAL(REG_VCORE_SSTIME_MODE, n) #define REG_LDO_SS_BIAS_EN_DR (1 << 3) #define REG_LDO_SS_BIAS_EN (1 << 2) #define REG_LP_EN_VHPPA_DSLEEP (1 << 1) #define REG_LP_EN_VHPPA_NORMAL (1 << 0) // 03 PMU_REG_BIAS_CFG #define REG_VSENSE_SEL_VMEM (1 << 15) #define PU_LP_BIAS_LDO_DSLEEP (1 << 14) #define PU_LP_BIAS_LDO_DR (1 << 13) #define PU_LP_BIAS_LDO_REG (1 << 12) #define PU_BIAS_LDO_DR (1 << 11) #define PU_BIAS_LDO_REG (1 << 10) #define BG_VBG_SEL_DR (1 << 9) #define BG_VBG_SEL_REG (1 << 8) #define BG_CONSTANT_GM_BIAS_DR (1 << 7) #define BG_CONSTANT_GM_BIAS_REG (1 << 6) #define BG_CORE_EN_DR (1 << 5) #define BG_CORE_EN_REG (1 << 4) #define REG_PU_LDO_VANA_DR (1 << 3) #define REG_PU_LDO_VANA (1 << 2) #define BG_NOTCH_EN_DR (1 << 1) #define BG_NOTCH_EN_REG (1 << 0) #define REG_PU_LDO_VANA_REG REG_PU_LDO_VANA // 05 PMU_REG_CHARGER_CFG #define REG_PU_LDO_VRTC_RF_DSLEEP (1 << 15) #define REG_PU_LDO_VRTC_RF_DR (1 << 14) #define REG_PU_LDO_VRTC_RF_REG (1 << 13) #define REG_CHARGE_OUT_INTR_MSK (1 << 12) #define REG_CHARGE_IN_INTR_MSK (1 << 11) #define REG_AC_ON_OUT_EN (1 << 10) #define REG_AC_ON_IN_EN (1 << 9) #define REG_CHARGE_INTR_EN (1 << 8) #define REG_AC_ON_DB_VALUE_SHIFT 0 #define REG_AC_ON_DB_VALUE_MASK (0xFF << REG_AC_ON_DB_VALUE_SHIFT) #define REG_AC_ON_DB_VALUE(n) BITFIELD_VAL(REG_AC_ON_DB_VALUE, n) // 07 PMU_REG_ANA_CFG #define REG_LIGHT_LOAD_VANA_BUCK_LDO (1 << 15) #define REG_PULLDOWN_VANA_LDO (1 << 14) #define LP_EN_VANA_LDO_DSLEEP (1 << 13) #define LP_EN_VANA_LDO_DR (1 << 12) #define LP_EN_VANA_LDO_REG (1 << 11) #define REG_PU_LDO_VANA_DSLEEP (1 << 10) #define LDO_ANA_VBIT_DSLEEP_SHIFT 5 #define LDO_ANA_VBIT_DSLEEP_MASK (0x1F << LDO_ANA_VBIT_DSLEEP_SHIFT) #define LDO_ANA_VBIT_DSLEEP(n) BITFIELD_VAL(LDO_ANA_VBIT_DSLEEP, n) #define LDO_ANA_VBIT_NORMAL_SHIFT 0 #define LDO_ANA_VBIT_NORMAL_MASK (0x1F << LDO_ANA_VBIT_NORMAL_SHIFT) #define LDO_ANA_VBIT_NORMAL(n) BITFIELD_VAL(LDO_ANA_VBIT_NORMAL, n) #define LDO_VANA_VBIT_DSLEEP_SHIFT LDO_ANA_VBIT_DSLEEP_SHIFT #define LDO_VANA_VBIT_DSLEEP_MASK LDO_ANA_VBIT_DSLEEP_MASK #define LDO_VANA_VBIT_NORMAL_SHIFT LDO_ANA_VBIT_NORMAL_SHIFT #define LDO_VANA_VBIT_NORMAL_MASK LDO_ANA_VBIT_NORMAL_MASK // 08 PMU_REG_DIG_CFG #define REG_DCDC_CLK_SE_EN (1 << 15) #define LP_EN_VCORE_LDO_DSLEEP (1 << 14) #define LP_EN_VCORE_LDO_DR (1 << 13) #define LP_EN_VCORE_LDO_REG (1 << 12) #define LDO_DIG_VBIT_DSLEEP_SHIFT 6 #define LDO_DIG_VBIT_DSLEEP_MASK (0x3F << LDO_DIG_VBIT_DSLEEP_SHIFT) #define LDO_DIG_VBIT_DSLEEP(n) BITFIELD_VAL(LDO_DIG_VBIT_DSLEEP, n) #define LDO_DIG_VBIT_NORMAL_SHIFT 0 #define LDO_DIG_VBIT_NORMAL_MASK (0x3F << LDO_DIG_VBIT_NORMAL_SHIFT) #define LDO_DIG_VBIT_NORMAL(n) BITFIELD_VAL(LDO_DIG_VBIT_NORMAL, n) #define LDO_VCORE_VBIT_DSLEEP_SHIFT LDO_DIG_VBIT_DSLEEP_SHIFT #define LDO_VCORE_VBIT_DSLEEP_MASK LDO_DIG_VBIT_DSLEEP_MASK #define LDO_VCORE_VBIT_NORMAL_SHIFT LDO_DIG_VBIT_NORMAL_SHIFT #define LDO_VCORE_VBIT_NORMAL_MASK LDO_DIG_VBIT_NORMAL_MASK // Real bit is in REG_101 -- but we never change the default value #define REG_PU_LDO_VCORE_DSLEEP 0 // 09 PMU_REG_IO_CFG #define LP_EN_VIO_LDO_DSLEEP (1 << 15) #define LP_EN_VIO_LDO_DR (1 << 14) #define LP_EN_VIO_LDO_REG (1 << 13) #define REG_PU_LDO_VIO_DSLEEP (1 << 12) #define REG_PU_LDO_VIO_DR (1 << 11) #define REG_PU_LDO_VIO (1 << 10) #define LDO_VIO_VBIT_NORMAL_SHIFT 5 #define LDO_VIO_VBIT_NORMAL_MASK (0x1F << LDO_VIO_VBIT_NORMAL_SHIFT) #define LDO_VIO_VBIT_NORMAL(n) BITFIELD_VAL(LDO_VIO_VBIT_NORMAL, n) #define LDO_VIO_VBIT_DSLEEP_SHIFT 0 #define LDO_VIO_VBIT_DSLEEP_MASK (0x1F << LDO_VIO_VBIT_DSLEEP_SHIFT) #define LDO_VIO_VBIT_DSLEEP(n) BITFIELD_VAL(LDO_VIO_VBIT_DSLEEP, n) #define REG_PU_LDO_VIO_REG REG_PU_LDO_VIO // 0A PMU_REG_MEM_CFG #define LP_EN_VMEM_LDO_DSLEEP (1 << 15) #define LP_EN_VMEM_LDO_DR (1 << 14) #define LP_EN_VMEM_LDO_REG (1 << 13) #define REG_PU_LDO_VMEM_DSLEEP (1 << 12) #define REG_PU_LDO_VMEM_DR (1 << 11) #define REG_PU_LDO_VMEM_REG (1 << 10) #define LDO_VMEM_VBIT_NORMAL_SHIFT 5 #define LDO_VMEM_VBIT_NORMAL_MASK (0x1F << LDO_VMEM_VBIT_NORMAL_SHIFT) #define LDO_VMEM_VBIT_NORMAL(n) BITFIELD_VAL(LDO_VMEM_VBIT_NORMAL, n) #define LDO_VMEM_VBIT_DSLEEP_SHIFT 0 #define LDO_VMEM_VBIT_DSLEEP_MASK (0x1F << LDO_VMEM_VBIT_DSLEEP_SHIFT) #define LDO_VMEM_VBIT_DSLEEP(n) BITFIELD_VAL(LDO_VMEM_VBIT_DSLEEP, n) // 0B PMU_REG_GP_CFG #define LP_EN_VGP_LDO_DSLEEP (1 << 15) #define LP_EN_VGP_LDO_DR (1 << 14) #define LP_EN_VGP_LDO_REG (1 << 13) #define REG_PU_LDO_VGP_DSLEEP (1 << 12) #define REG_PU_LDO_VGP_DR (1 << 11) #define REG_PU_LDO_VGP_REG (1 << 10) #define LDO_VGP_VBIT_NORMAL_SHIFT 5 #define LDO_VGP_VBIT_NORMAL_MASK (0x1F << LDO_VGP_VBIT_NORMAL_SHIFT) #define LDO_VGP_VBIT_NORMAL(n) BITFIELD_VAL(LDO_VGP_VBIT_NORMAL, n) #define LDO_VGP_VBIT_DSLEEP_SHIFT 0 #define LDO_VGP_VBIT_DSLEEP_MASK (0x1F << LDO_VGP_VBIT_DSLEEP_SHIFT) #define LDO_VGP_VBIT_DSLEEP(n) BITFIELD_VAL(LDO_VGP_VBIT_DSLEEP, n) // 0C PMU_REG_USB_CFG #define REG_LDO_VANA_LV_MODE (1 << 15) #define REG_PULLDOWN_VUSB (1 << 14) #define LP_EN_VUSB_LDO_DSLEEP (1 << 13) #define LP_EN_VUSB_LDO_DR (1 << 12) #define LP_EN_VUSB_LDO_REG (1 << 11) #define PU_LDO_VUSB_DSLEEP (1 << 10) #define PU_LDO_VUSB_DR (1 << 9) #define PU_LDO_VUSB_REG (1 << 8) #define LDO_VUSB_VBIT_NORMAL_SHIFT 4 #define LDO_VUSB_VBIT_NORMAL_MASK (0xF << LDO_VUSB_VBIT_NORMAL_SHIFT) #define LDO_VUSB_VBIT_NORMAL(n) BITFIELD_VAL(LDO_VUSB_VBIT_NORMAL, n) #define LDO_VUSB_VBIT_DSLEEP_SHIFT 0 #define LDO_VUSB_VBIT_DSLEEP_MASK (0xF << LDO_VUSB_VBIT_DSLEEP_SHIFT) #define LDO_VUSB_VBIT_DSLEEP(n) BITFIELD_VAL(LDO_VUSB_VBIT_DSLEEP, n) #define REG_PU_LDO_VUSB_DSLEEP PU_LDO_VUSB_DSLEEP #define REG_PU_LDO_VUSB_DR PU_LDO_VUSB_DR #define REG_PU_LDO_VUSB_REG PU_LDO_VUSB_REG // 0D PMU_REG_BAT2DIG_CFG #define LP_EN_VBAT2VCORE_LDO_DR (1 << 15) #define LP_EN_VBAT2VCORE_LDO (1 << 14) #define REG_PU_VBAT2VCORE_LDO_DR (1 << 13) #define REG_PU_VBAT2VCORE_LDO (1 << 12) #define LDO_VBAT2VCORE_VBIT_DSLEEP_SHIFT 6 #define LDO_VBAT2VCORE_VBIT_DSLEEP_MASK \ (0x3F << LDO_VBAT2VCORE_VBIT_DSLEEP_SHIFT) #define LDO_VBAT2VCORE_VBIT_DSLEEP(n) \ BITFIELD_VAL(LDO_VBAT2VCORE_VBIT_DSLEEP, n) #define LDO_VBAT2VCORE_VBIT_NORMAL_SHIFT 0 #define LDO_VBAT2VCORE_VBIT_NORMAL_MASK \ (0x3F << LDO_VBAT2VCORE_VBIT_NORMAL_SHIFT) #define LDO_VBAT2VCORE_VBIT_NORMAL(n) \ BITFIELD_VAL(LDO_VBAT2VCORE_VBIT_NORMAL, n) #define LP_EN_VBAT2VCORE_LDO_REG LP_EN_VBAT2VCORE_LDO #define REG_PU_LDO_VBAT2VCORE_DR REG_PU_VBAT2VCORE_LDO_DR #define REG_PU_LDO_VBAT2VCORE_REG REG_PU_VBAT2VCORE_LDO // Real bit is in REG_101 -- but we never change the default value #define REG_PU_LDO_VBAT2VCORE_DSLEEP 0 // 0E PMU_REG_HPPA_LDO_EN #define REG_PULL_DOWN_VHPPA (1 << 15) #define REG_PU_LDO_VHPPA_DSLEEP (1 << 14) #define REG_PU_LDO_VHPPA_EN (1 << 13) #define REG_RES_SEL_VHPPA_SHIFT 8 #define REG_RES_SEL_VHPPA_MASK (0x1F << REG_RES_SEL_VHPPA_SHIFT) #define REG_RES_SEL_VHPPA(n) BITFIELD_VAL(REG_RES_SEL_VHPPA, n) #define REG_LP_BIAS_SEL_LDO_SHIFT 6 #define REG_LP_BIAS_SEL_LDO_MASK (0x3 << REG_LP_BIAS_SEL_LDO_SHIFT) #define REG_LP_BIAS_SEL_LDO(n) BITFIELD_VAL(REG_LP_BIAS_SEL_LDO, n) #define REG_BYPASS_VBUCK2ANA (1 << 5) #define REG_PULLDOWN_VBUCK2ANA (1 << 4) #define REG_PULLDOWN_VIO (1 << 3) #define REG_PULLDOWN_VMEM (1 << 2) #define REG_PULLDOWN_VCORE (1 << 1) #define REG_PULLDOWN_VHPPA2VCODEC (1 << 0) // 0F PMU_REG_HPPA2CODEC_CFG #define PU_LDO_VCODEC_DSLEEP (1 << 15) #define REG_BYPASS_VCORE (1 << 14) #define REG_PU_LDO_VHPPA2VCODEC_DR (1 << 13) #define REG_PU_LDO_VHPPA2VCODEC (1 << 12) #define LP_EN_VHPPA2VCODEC_LDO_DR (1 << 11) #define LP_EN_VHPPA2VCODEC_LDO (1 << 10) #define LDO_VHPPA2VCODEC_VBIT_DSLEEP_SHIFT 5 #define LDO_VHPPA2VCODEC_VBIT_DSLEEP_MASK \ (0x1F << LDO_VHPPA2VCODEC_VBIT_DSLEEP_SHIFT) #define LDO_VHPPA2VCODEC_VBIT_DSLEEP(n) \ BITFIELD_VAL(LDO_VHPPA2VCODEC_VBIT_DSLEEP, n) #define LDO_VHPPA2VCODEC_VBIT_NORMAL_SHIFT 0 #define LDO_VHPPA2VCODEC_VBIT_NORMAL_MASK \ (0x1F << LDO_VHPPA2VCODEC_VBIT_NORMAL_SHIFT) #define LDO_VHPPA2VCODEC_VBIT_NORMAL(n) \ BITFIELD_VAL(LDO_VHPPA2VCODEC_VBIT_NORMAL, n) #define REG_PU_LDO_VHPPA2VCODEC_REG REG_PU_LDO_VHPPA2VCODEC #define LP_EN_VHPPA2VCODEC_LDO_REG LP_EN_VHPPA2VCODEC_LDO #define REG_PU_LDO_VCODEC_DSLEEP PU_LDO_VCODEC_DSLEEP // 10 PMU_REG_CODEC_CFG #define PU_LDO_VCODEC_DR (1 << 15) #define PU_LDO_VCODEC_REG (1 << 14) #define LP_EN_VCODEC_LDO_DSLEEP (1 << 13) #define LP_EN_VCODEC_LDO_DR (1 << 12) #define LP_EN_VCODEC_LDO_REG (1 << 11) #define REG_PULLDOWN_VCODEC (1 << 10) #define LDO_VCODEC_VBIT_NORMAL_SHIFT 5 #define LDO_VCODEC_VBIT_NORMAL_MASK (0x1F << LDO_VCODEC_VBIT_NORMAL_SHIFT) #define LDO_VCODEC_VBIT_NORMAL(n) BITFIELD_VAL(LDO_VCODEC_VBIT_NORMAL, n) #define LDO_VCODEC_VBIT_DSLEEP_SHIFT 0 #define LDO_VCODEC_VBIT_DSLEEP_MASK (0x1F << LDO_VCODEC_VBIT_DSLEEP_SHIFT) #define LDO_VCODEC_VBIT_DSLEEP(n) BITFIELD_VAL(LDO_VCODEC_VBIT_DSLEEP, n) #define REG_PU_LDO_VCODEC_DR PU_LDO_VCODEC_DR #define REG_PU_LDO_VCODEC_REG PU_LDO_VCODEC_REG // 15 PMU_REG_DCDC_DIG_EN #define REG_UVLO_SEL_SHIFT 14 #define REG_UVLO_SEL_MASK (0x3 << REG_UVLO_SEL_SHIFT) #define REG_UVLO_SEL(n) BITFIELD_VAL(REG_UVLO_SEL, n) #define REG_PU_LDO_DIG_DR (1 << 13) #define REG_PU_LDO_DIG_REG (1 << 12) #define REG_DCDC1_PFM_SEL_DSLEEP (1 << 11) #define REG_DCDC1_PFM_SEL_NORMAL (1 << 10) #define REG_DCDC1_ULP_MODE_DSLEEP (1 << 9) #define REG_DCDC1_ULP_MODE_NORMAL (1 << 8) #define REG_DCDC1_BURST_MODE_SEL_DSLEEP (1 << 7) #define REG_DCDC1_BURST_MODE_SEL_NORMAL (1 << 6) #define REG_DCDC1_VREF_SEL_DSLEEP_SHIFT 4 #define REG_DCDC1_VREF_SEL_DSLEEP_MASK (0x3 << REG_DCDC1_VREF_SEL_DSLEEP_SHIFT) #define REG_DCDC1_VREF_SEL_DSLEEP(n) BITFIELD_VAL(REG_DCDC1_VREF_SEL_DSLEEP, n) #define REG_DCDC1_VREF_SEL_NORMAL_SHIFT 2 #define REG_DCDC1_VREF_SEL_NORMAL_MASK (0x3 << REG_DCDC1_VREF_SEL_NORMAL_SHIFT) #define REG_DCDC1_VREF_SEL_NORMAL(n) BITFIELD_VAL(REG_DCDC1_VREF_SEL_NORMAL, n) #define REG_PU_DCDC1_DR (1 << 1) #define REG_PU_DCDC1 (1 << 0) #define REG_PU_LDO_VCORE_DR REG_PU_LDO_DIG_DR #define REG_PU_LDO_VCORE_REG REG_PU_LDO_DIG_REG // 19 PMU_REG_DCDC_ANA_CFG_19 #define DCDC2_IX2_ERR (1 << 15) #define DCDC2_IX2_IRCOMP (1 << 14) #define DCDC2_LP_ERR (1 << 13) #define DCDC2_LP_VCOMP (1 << 12) #define DCDC2_PULLDOWN_EN (1 << 11) #define DCDC2_SLOPE_DOUBLE (1 << 10) #define DCDC2_SLOPE_EN_BURST (1 << 9) #define DCDC2_SOFT_START_EN (1 << 8) #define DCDC2_SS_TIME_SEL (1 << 7) #define DCDC2_SYNC_DISABLE (1 << 6) #define DCDC2_TEST_MODE_EN (1 << 5) #define DCDC2_ZCD_CAL_BIT_SHIFT 1 #define DCDC2_ZCD_CAL_BIT_MASK (0xF << DCDC2_ZCD_CAL_BIT_SHIFT) #define DCDC2_ZCD_CAL_BIT(n) BITFIELD_VAL(DCDC2_ZCD_CAL_BIT, n) #define DCDC2_REG_BYPASS (1 << 0) // 1D PMU_REG_DCDC_HPPA_CFG_1D #define DCDC3_IX2_ERR (1 << 15) #define DCDC3_IX2_IRCOMP (1 << 14) #define DCDC3_LP_ERR (1 << 13) #define DCDC3_LP_VCOMP (1 << 12) #define DCDC3_PULLDOWN_EN (1 << 11) #define DCDC3_SLOPE_DOUBLE (1 << 10) #define DCDC3_SLOPE_EN_BURST (1 << 9) #define DCDC3_SOFT_START_EN (1 << 8) #define DCDC3_SS_TIME_SEL (1 << 7) #define DCDC3_SYNC_DISABLE (1 << 6) #define DCDC3_TEST_MODE_EN (1 << 5) #define DCDC3_ZCD_CAL_BIT_SHIFT 1 #define DCDC3_ZCD_CAL_BIT_MASK (0xF << DCDC3_ZCD_CAL_BIT_SHIFT) #define DCDC3_ZCD_CAL_BIT(n) BITFIELD_VAL(DCDC3_ZCD_CAL_BIT, n) #define DCDC3_REG_BYPASS (1 << 0) // 21 PMU_REG_PWR_SEL #define REG_PMU_VSEL1_SHIFT 13 #define REG_PMU_VSEL1_MASK (0x7 << REG_PMU_VSEL1_SHIFT) #define REG_PMU_VSEL1(n) BITFIELD_VAL(REG_PMU_VSEL1, n) #define REG_POWER_SEL_CNT_SHIFT 8 #define REG_POWER_SEL_CNT_MASK (0x1F << REG_POWER_SEL_CNT_SHIFT) #define REG_POWER_SEL_CNT(n) BITFIELD_VAL(REG_POWER_SEL_CNT, n) #define REG_PWR_SEL_DR (1 << 7) #define REG_PWR_SEL (1 << 6) #define CLK_BG_EN (1 << 5) #define CLK_BG_DIV_VALUE_SHIFT 0 #define CLK_BG_DIV_VALUE_MASK (0x1F << CLK_BG_DIV_VALUE_SHIFT) #define CLK_BG_DIV_VALUE(n) BITFIELD_VAL(CLK_BG_DIV_VALUE, n) // 26 PMU_REG_INT_MASK #define RESET_EN_VCORE_LOW (1 << 15) #define RTC_INT1_MSK (1 << 14) #define RTC_INT0_MSK (1 << 13) #define KEY_ERR1_INTR_MSK (1 << 12) #define KEY_ERR0_INTR_MSK (1 << 11) #define KEY_PRESS_INTR_MSK (1 << 10) #define KEY_RELEASE_INTR_MSK (1 << 9) #define SAMPLE_DONE_INTR_MSK (1 << 8) #define CHAN_DATA_INTR_MSK_SHIFT 0 #define CHAN_DATA_INTR_MSK_MASK (0xFF << CHAN_DATA_INTR_MSK_SHIFT) #define CHAN_DATA_INTR_MSK(n) BITFIELD_VAL(CHAN_DATA_INTR_MSK, n) // 27 PMU_REG_INT_EN #define REG_BG_SLEEP_MSK (1 << 15) #define RTC_INT_EN_1 (1 << 14) #define RTC_INT_EN_0 (1 << 13) #define KEY_ERR1_INTR_EN (1 << 12) #define KEY_ERR0_INTR_EN (1 << 11) #define KEY_PRESS_INTR_EN (1 << 10) #define KEY_RELEASE_INTR_EN (1 << 9) #define SAMPLE_DONE_INTR_EN (1 << 8) #define CHAN_DATA_INTR_EN_SHIFT 0 #define CHAN_DATA_INTR_EN_MASK (0xFF << CHAN_DATA_INTR_EN_SHIFT) #define CHAN_DATA_INTR_EN(n) BITFIELD_VAL(CHAN_DATA_INTR_EN, n) // 36 PMU_REG_DCDC_DIG_CFG_36 #define DCDC1_IX2_ERR (1 << 15) #define DCDC1_IX2_IRCOMP (1 << 14) #define DCDC1_LP_ERR (1 << 13) #define DCDC1_LP_VCOMP (1 << 12) #define DCDC1_PULLDOWN_EN (1 << 11) #define DCDC1_SLOPE_DOUBLE (1 << 10) #define DCDC1_SLOPE_EN_BURST (1 << 9) #define DCDC1_SOFT_START_EN (1 << 8) #define DCDC1_SS_TIME_SEL (1 << 7) #define DCDC1_SYNC_DISABLE (1 << 6) #define DCDC1_TEST_MODE_EN (1 << 5) #define DCDC1_ZCD_CAL_BIT_SHIFT 1 #define DCDC1_ZCD_CAL_BIT_MASK (0xF << DCDC1_ZCD_CAL_BIT_SHIFT) #define DCDC1_ZCD_CAL_BIT(n) BITFIELD_VAL(DCDC1_ZCD_CAL_BIT, n) #define DCDC1_REG_BYPASS (1 << 0) // 38 PMU_REG_MIC_BIAS_E #define REG_MIC_BIASE_CHANSEL_SHIFT 14 #define REG_MIC_BIASE_CHANSEL_MASK (0x3 << REG_MIC_BIASE_CHANSEL_SHIFT) #define REG_MIC_BIASE_CHANSEL(n) BITFIELD_VAL(REG_MIC_BIASE_CHANSEL, n) #define REG_MIC_BIASE_EN (1 << 13) #define REG_MIC_BIASE_ENLPF (1 << 12) #define REG_MIC_BIASE_LPFSEL_SHIFT 10 #define REG_MIC_BIASE_LPFSEL_MASK (0x3 << REG_MIC_BIASE_LPFSEL_SHIFT) #define REG_MIC_BIASE_LPFSEL(n) BITFIELD_VAL(REG_MIC_BIASE_LPFSEL, n) #define REG_MIC_BIASE_VSEL_SHIFT 5 #define REG_MIC_BIASE_VSEL_MASK (0x1F << REG_MIC_BIASE_VSEL_SHIFT) #define REG_MIC_BIASE_VSEL(n) BITFIELD_VAL(REG_MIC_BIASE_VSEL, n) #define REG_MIC_LDOE_RES_SHIFT 1 #define REG_MIC_LDOE_RES_MASK (0xF << REG_MIC_LDOE_RES_SHIFT) #define REG_MIC_LDOE_RES(n) BITFIELD_VAL(REG_MIC_LDOE_RES, n) #define REG_MIC_LDOE_LOOPCTRL (1 << 0) // 39 PMU_REG_MIC_LDO_EN #define REG_LED_IO1_AIO_EN (1 << 15) #define REG_LED_IO2_AIO_EN (1 << 14) #define REG_LED_IO1_RX_EN (1 << 13) #define REG_LED_IO2_RX_EN (1 << 12) #define REG_MIC_LDOA_EN (1 << 11) #define REG_MIC_LDOB_EN (1 << 10) #define REG_MIC_LDOC_EN (1 << 9) #define REG_MIC_LDOD_EN (1 << 8) #define REG_MIC_LDOE_EN (1 << 7) #define DCDC1_OFFSET_CURRENT_EN (1 << 6) #define DCDC2_OFFSET_CURRENT_EN (1 << 5) #define DCDC3_OFFSET_CURRENT_EN (1 << 4) #define DCDC4_OFFSET_CURRENT_EN (1 << 3) // 3A PMU_REG_LED_CFG #define REG_LED_IO1_IBIT_SHIFT 14 #define REG_LED_IO1_IBIT_MASK (0x3 << REG_LED_IO1_IBIT_SHIFT) #define REG_LED_IO1_IBIT(n) BITFIELD_VAL(REG_LED_IO1_IBIT, n) #define REG_LED_IO1_OENB (1 << 13) #define REG_LED_IO1_PDEN (1 << 12) #define REG_LED_IO1_PU (1 << 11) #define REG_LED_IO1_PUEN (1 << 10) #define REG_LED_IO1_SEL_SHIFT 8 #define REG_LED_IO1_SEL_MASK (0x3 << REG_LED_IO1_SEL_SHIFT) #define REG_LED_IO1_SEL(n) BITFIELD_VAL(REG_LED_IO1_SEL, n) #define REG_LED_IO2_IBIT_SHIFT 6 #define REG_LED_IO2_IBIT_MASK (0x3 << REG_LED_IO2_IBIT_SHIFT) #define REG_LED_IO2_IBIT(n) BITFIELD_VAL(REG_LED_IO2_IBIT, n) #define REG_LED_IO2_OENB (1 << 5) #define REG_LED_IO2_PDEN (1 << 4) #define REG_LED_IO2_PU (1 << 3) #define REG_LED_IO2_PUEN (1 << 2) #define REG_LED_IO2_SEL_SHIFT 0 #define REG_LED_IO2_SEL_MASK (0x3 << REG_LED_IO2_SEL_SHIFT) #define REG_LED_IO2_SEL(n) BITFIELD_VAL(REG_LED_IO2_SEL, n) // 3B PMU_REG_MIC_BIAS_A #define REG_MIC_BIASA_CHANSEL_SHIFT 14 #define REG_MIC_BIASA_CHANSEL_MASK (0x3 << REG_MIC_BIASA_CHANSEL_SHIFT) #define REG_MIC_BIASA_CHANSEL(n) BITFIELD_VAL(REG_MIC_BIASA_CHANSEL, n) #define REG_MIC_BIASA_EN (1 << 13) #define REG_MIC_BIASA_ENLPF (1 << 12) #define REG_MIC_BIASA_LPFSEL_SHIFT 10 #define REG_MIC_BIASA_LPFSEL_MASK (0x3 << REG_MIC_BIASA_LPFSEL_SHIFT) #define REG_MIC_BIASA_LPFSEL(n) BITFIELD_VAL(REG_MIC_BIASA_LPFSEL, n) #define REG_MIC_BIASA_VSEL_SHIFT 5 #define REG_MIC_BIASA_VSEL_MASK (0x1F << REG_MIC_BIASA_VSEL_SHIFT) #define REG_MIC_BIASA_VSEL(n) BITFIELD_VAL(REG_MIC_BIASA_VSEL, n) #define REG_MIC_LDOA_RES_SHIFT 1 #define REG_MIC_LDOA_RES_MASK (0xF << REG_MIC_LDOA_RES_SHIFT) #define REG_MIC_LDOA_RES(n) BITFIELD_VAL(REG_MIC_LDOA_RES, n) #define REG_MIC_LDOA_LOOPCTRL (1 << 0) // 3C PMU_REG_MIC_BIAS_B #define REG_MIC_BIASB_CHANSEL_SHIFT 14 #define REG_MIC_BIASB_CHANSEL_MASK (0x3 << REG_MIC_BIASB_CHANSEL_SHIFT) #define REG_MIC_BIASB_CHANSEL(n) BITFIELD_VAL(REG_MIC_BIASB_CHANSEL, n) #define REG_MIC_BIASB_EN (1 << 13) #define REG_MIC_BIASB_ENLPF (1 << 12) #define REG_MIC_BIASB_LPFSEL_SHIFT 10 #define REG_MIC_BIASB_LPFSEL_MASK (0x3 << REG_MIC_BIASB_LPFSEL_SHIFT) #define REG_MIC_BIASB_LPFSEL(n) BITFIELD_VAL(REG_MIC_BIASB_LPFSEL, n) #define REG_MIC_BIASB_VSEL_SHIFT 5 #define REG_MIC_BIASB_VSEL_MASK (0x1F << REG_MIC_BIASB_VSEL_SHIFT) #define REG_MIC_BIASB_VSEL(n) BITFIELD_VAL(REG_MIC_BIASB_VSEL, n) #define REG_MIC_LDOB_RES_SHIFT 1 #define REG_MIC_LDOB_RES_MASK (0xF << REG_MIC_LDOB_RES_SHIFT) #define REG_MIC_LDOB_RES(n) BITFIELD_VAL(REG_MIC_LDOB_RES, n) #define REG_MIC_LDOB_LOOPCTRL (1 << 0) // 3D PMU_REG_MIC_BIAS_C #define REG_MIC_BIASC_CHANSEL_SHIFT 14 #define REG_MIC_BIASC_CHANSEL_MASK (0x3 << REG_MIC_BIASC_CHANSEL_SHIFT) #define REG_MIC_BIASC_CHANSEL(n) BITFIELD_VAL(REG_MIC_BIASC_CHANSEL, n) #define REG_MIC_BIASC_EN (1 << 13) #define REG_MIC_BIASC_ENLPF (1 << 12) #define REG_MIC_BIASC_LPFSEL_SHIFT 10 #define REG_MIC_BIASC_LPFSEL_MASK (0x3 << REG_MIC_BIASC_LPFSEL_SHIFT) #define REG_MIC_BIASC_LPFSEL(n) BITFIELD_VAL(REG_MIC_BIASC_LPFSEL, n) #define REG_MIC_BIASC_VSEL_SHIFT 5 #define REG_MIC_BIASC_VSEL_MASK (0x1F << REG_MIC_BIASC_VSEL_SHIFT) #define REG_MIC_BIASC_VSEL(n) BITFIELD_VAL(REG_MIC_BIASC_VSEL, n) #define REG_MIC_LDOC_RES_SHIFT 1 #define REG_MIC_LDOC_RES_MASK (0xF << REG_MIC_LDOC_RES_SHIFT) #define REG_MIC_LDOC_RES(n) BITFIELD_VAL(REG_MIC_LDOC_RES, n) #define REG_MIC_LDOC_LOOPCTRL (1 << 0) // 3E PMU_REG_MIC_BIAS_D #define REG_MIC_BIASD_CHANSEL_SHIFT 14 #define REG_MIC_BIASD_CHANSEL_MASK (0x3 << REG_MIC_BIASD_CHANSEL_SHIFT) #define REG_MIC_BIASD_CHANSEL(n) BITFIELD_VAL(REG_MIC_BIASD_CHANSEL, n) #define REG_MIC_BIASD_EN (1 << 13) #define REG_MIC_BIASD_ENLPF (1 << 12) #define REG_MIC_BIASD_LPFSEL_SHIFT 10 #define REG_MIC_BIASD_LPFSEL_MASK (0x3 << REG_MIC_BIASD_LPFSEL_SHIFT) #define REG_MIC_BIASD_LPFSEL(n) BITFIELD_VAL(REG_MIC_BIASD_LPFSEL, n) #define REG_MIC_BIASD_VSEL_SHIFT 5 #define REG_MIC_BIASD_VSEL_MASK (0x1F << REG_MIC_BIASD_VSEL_SHIFT) #define REG_MIC_BIASD_VSEL(n) BITFIELD_VAL(REG_MIC_BIASD_VSEL, n) #define REG_MIC_LDOD_RES_SHIFT 1 #define REG_MIC_LDOD_RES_MASK (0xF << REG_MIC_LDOD_RES_SHIFT) #define REG_MIC_LDOD_RES(n) BITFIELD_VAL(REG_MIC_LDOD_RES, n) #define REG_MIC_LDOD_LOOPCTRL (1 << 0) // 3F PMU_REG_EFUSE_CTRL #define TSMC_EFUSE_A_SHIFT 0 #define TSMC_EFUSE_A_MASK (0x3F << TSMC_EFUSE_A_SHIFT) #define TSMC_EFUSE_A(n) BITFIELD_VAL(TSMC_EFUSE_A, n) #define TSMC_EFUSE_CLK_EN (1 << 8) #define TSMC_EFUSE_NR (1 << 9) #define TSMC_EFUSE_MR (1 << 10) #define MANUAL_MODE (1 << 11) #define TSMC_EFUSE_PGENB (1 << 12) #define REG_MARGIN_READ (1 << 13) // 40 PMU_REG_EFUSE_SEL #define TSMC_EFUSE_STROBE_TRIG (1 << 0) #define TSMC_EFUSE_STROBE_WIDTH_SHIFT 1 #define TSMC_EFUSE_STROBE_WIDTH_MASK (0xFF << TSMC_EFUSE_STROBE_WIDTH_SHIFT) #define TSMC_EFUSE_STROBE_WIDTH(n) BITFIELD_VAL(TSMC_EFUSE_STROBE_WIDTH, n) #define REG_READ_STROBE_WIDTH_SHIFT 9 #define REG_READ_STROBE_WIDTH_MASK (0xF << REG_READ_STROBE_WIDTH_SHIFT) #define REG_READ_STROBE_WIDTH(n) BITFIELD_VAL(REG_READ_STROBE_WIDTH, n) #define EFUSE_SEL_SHIFT 13 #define EFUSE_SEL_MASK (0x7 << EFUSE_SEL_SHIFT) #define EFUSE_SEL(n) BITFIELD_VAL(EFUSE_SEL, n) // 41 PMU_REG_DCDC1_OFFSET #define DCDC1_OFFSET_BIT_SHIFT 8 #define DCDC1_OFFSET_BIT_MASK (0xFF << DCDC1_OFFSET_BIT_SHIFT) #define DCDC1_OFFSET_BIT(n) BITFIELD_VAL(DCDC1_OFFSET_BIT, n) #define DCDC2_OFFSET_BIT_SHIFT 0 #define DCDC2_OFFSET_BIT_MASK (0xFF << DCDC2_OFFSET_BIT_SHIFT) #define DCDC2_OFFSET_BIT(n) BITFIELD_VAL(DCDC2_OFFSET_BIT, n) // 43 PMU_REG_BUCK2ANA_CFG #define REG_PU_VBUCK2ANA_LDO_DR (1 << 15) #define REG_PU_VBUCK2ANA_LDO (1 << 14) #define LP_EN_VBUCK2ANA_LDO_DR (1 << 13) #define LP_EN_VBUCK2ANA_LDO (1 << 12) #define LDO_VBUCK2ANA_VBIT_DSLEEP_SHIFT 6 #define LDO_VBUCK2ANA_VBIT_DSLEEP_MASK (0x3F << LDO_VBUCK2ANA_VBIT_DSLEEP_SHIFT) #define LDO_VBUCK2ANA_VBIT_DSLEEP(n) BITFIELD_VAL(LDO_VBUCK2ANA_VBIT_DSLEEP, n) #define LDO_VBUCK2ANA_VBIT_NORMAL_SHIFT 0 #define LDO_VBUCK2ANA_VBIT_NORMAL_MASK (0x3F << LDO_VBUCK2ANA_VBIT_NORMAL_SHIFT) #define LDO_VBUCK2ANA_VBIT_NORMAL(n) BITFIELD_VAL(LDO_VBUCK2ANA_VBIT_NORMAL, n) #define REG_PU_LDO_VBUCK2ANA_DR REG_PU_VBUCK2ANA_LDO_DR #define REG_PU_LDO_VBUCK2ANA_REG REG_PU_VBUCK2ANA_LDO #define LP_EN_VBUCK2ANA_LDO_REG LP_EN_VBUCK2ANA_LDO // No pu dsleep cfg #define REG_PU_LDO_VBUCK2ANA_DSLEEP 0 // 44 PMU_REG_SLEEP_CFG #define PMIC_TMODE_1300_SHIFT 0 #define PMIC_TMODE_1300_MASK (0x7 << PMIC_TMODE_1300_SHIFT) #define PMIC_TMODE_1300(n) BITFIELD_VAL(PMIC_TMODE_1300, n) #define POWERON_PRESS_EN (1 << 3) #define POWERON_RELEASE_EN (1 << 4) #define SLEEP_ALLOW (1 << 5) #define REG_VHPPA2VCODEC_SLP_ON (1 << 6) #define REG_PU_LDO_VHPPA2VCODEC_DSLEEP REG_VHPPA2VCODEC_SLP_ON // 46 PMU_REG_DCDC_DIG_VOLT #define REG_DCDC1_VBIT_DSLEEP_SHIFT 8 #define REG_DCDC1_VBIT_DSLEEP_MASK (0xFF << REG_DCDC1_VBIT_DSLEEP_SHIFT) #define REG_DCDC1_VBIT_DSLEEP(n) BITFIELD_VAL(REG_DCDC1_VBIT_DSLEEP, n) #define REG_DCDC1_VBIT_NORMAL_SHIFT 0 #define REG_DCDC1_VBIT_NORMAL_MASK (0xFF << REG_DCDC1_VBIT_NORMAL_SHIFT) #define REG_DCDC1_VBIT_NORMAL(n) BITFIELD_VAL(REG_DCDC1_VBIT_NORMAL, n) #define MAX_DCDC1_VBIT_VAL \ (REG_DCDC1_VBIT_NORMAL_MASK >> REG_DCDC1_VBIT_NORMAL_SHIFT) // 47 PMU_REG_DCDC_ANA_VOLT #define REG_DCDC2_VBIT_DSLEEP_SHIFT 8 #define REG_DCDC2_VBIT_DSLEEP_MASK (0xFF << REG_DCDC2_VBIT_DSLEEP_SHIFT) #define REG_DCDC2_VBIT_DSLEEP(n) BITFIELD_VAL(REG_DCDC2_VBIT_DSLEEP, n) #define REG_DCDC2_VBIT_NORMAL_SHIFT 0 #define REG_DCDC2_VBIT_NORMAL_MASK (0xFF << REG_DCDC2_VBIT_NORMAL_SHIFT) #define REG_DCDC2_VBIT_NORMAL(n) BITFIELD_VAL(REG_DCDC2_VBIT_NORMAL, n) #define MAX_DCDC2_VBIT_VAL \ (REG_DCDC2_VBIT_NORMAL_MASK >> REG_DCDC2_VBIT_NORMAL_SHIFT) // 48 PMU_REG_DCDC_HPPA_VOLT #define REG_DCDC3_VBIT_DSLEEP_SHIFT 8 #define REG_DCDC3_VBIT_DSLEEP_MASK (0xFF << REG_DCDC3_VBIT_DSLEEP_SHIFT) #define REG_DCDC3_VBIT_DSLEEP(n) BITFIELD_VAL(REG_DCDC3_VBIT_DSLEEP, n) #define REG_DCDC3_VBIT_NORMAL_SHIFT 0 #define REG_DCDC3_VBIT_NORMAL_MASK (0xFF << REG_DCDC3_VBIT_NORMAL_SHIFT) #define REG_DCDC3_VBIT_NORMAL(n) BITFIELD_VAL(REG_DCDC3_VBIT_NORMAL, n) #define MAX_DCDC3_VBIT_VAL \ (REG_DCDC3_VBIT_NORMAL_MASK >> REG_DCDC3_VBIT_NORMAL_SHIFT) // 49 PMU_REG_DCDC4_VOLT #define REG_DCDC4_VBIT_DSLEEP_SHIFT 8 #define REG_DCDC4_VBIT_DSLEEP_MASK (0xFF << REG_DCDC4_VBIT_DSLEEP_SHIFT) #define REG_DCDC4_VBIT_DSLEEP(n) BITFIELD_VAL(REG_DCDC4_VBIT_DSLEEP, n) #define REG_DCDC4_VBIT_NORMAL_SHIFT 0 #define REG_DCDC4_VBIT_NORMAL_MASK (0xFF << REG_DCDC4_VBIT_NORMAL_SHIFT) #define REG_DCDC4_VBIT_NORMAL(n) BITFIELD_VAL(REG_DCDC4_VBIT_NORMAL, n) // 4A PMU_REG_DCDC_ANA_EN #define REG_DCDC2_PFM_SEL_DSLEEP (1 << 11) #define REG_DCDC2_PFM_SEL_NORMAL (1 << 10) #define REG_DCDC2_ULP_MODE_DSLEEP (1 << 9) #define REG_DCDC2_ULP_MODE_NORMAL (1 << 8) #define REG_DCDC2_BURST_MODE_SEL_DSLEEP (1 << 7) #define REG_DCDC2_BURST_MODE_SEL_NORMAL (1 << 6) #define REG_DCDC2_VREF_SEL_DSLEEP_SHIFT 4 #define REG_DCDC2_VREF_SEL_DSLEEP_MASK (0x3 << REG_DCDC2_VREF_SEL_DSLEEP_SHIFT) #define REG_DCDC2_VREF_SEL_DSLEEP(n) BITFIELD_VAL(REG_DCDC2_VREF_SEL_DSLEEP, n) #define REG_DCDC2_VREF_SEL_NORMAL_SHIFT 2 #define REG_DCDC2_VREF_SEL_NORMAL_MASK (0x3 << REG_DCDC2_VREF_SEL_NORMAL_SHIFT) #define REG_DCDC2_VREF_SEL_NORMAL(n) BITFIELD_VAL(REG_DCDC2_VREF_SEL_NORMAL, n) #define REG_PU_DCDC2_DR (1 << 1) #define REG_PU_DCDC2 (1 << 0) // 4B PMU_REG_DCDC_HPPA_EN #define REG_DCDC3_PFM_SEL_DSLEEP (1 << 11) #define REG_DCDC3_PFM_SEL_NORMAL (1 << 10) #define REG_DCDC3_ULP_MODE_DSLEEP (1 << 9) #define REG_DCDC3_ULP_MODE_NORMAL (1 << 8) #define REG_DCDC3_BURST_MODE_SEL_DSLEEP (1 << 7) #define REG_DCDC3_BURST_MODE_SEL_NORMAL (1 << 6) #define REG_DCDC3_VREF_SEL_DSLEEP_SHIFT 4 #define REG_DCDC3_VREF_SEL_DSLEEP_MASK (0x3 << REG_DCDC3_VREF_SEL_DSLEEP_SHIFT) #define REG_DCDC3_VREF_SEL_DSLEEP(n) BITFIELD_VAL(REG_DCDC3_VREF_SEL_DSLEEP, n) #define REG_DCDC3_VREF_SEL_NORMAL_SHIFT 2 #define REG_DCDC3_VREF_SEL_NORMAL_MASK (0x3 << REG_DCDC3_VREF_SEL_NORMAL_SHIFT) #define REG_DCDC3_VREF_SEL_NORMAL(n) BITFIELD_VAL(REG_DCDC3_VREF_SEL_NORMAL, n) #define REG_PU_DCDC3_DR (1 << 1) #define REG_PU_DCDC3 (1 << 0) // 4C PMU_REG_DCDC4_EN #define REG_DCDC4_PFM_SEL_DSLEEP (1 << 11) #define REG_DCDC4_PFM_SEL_NORMAL (1 << 10) #define REG_DCDC4_ULP_MODE_DSLEEP (1 << 9) #define REG_DCDC4_ULP_MODE_NORMAL (1 << 8) #define REG_DCDC4_BURST_MODE_SEL_DSLEEP (1 << 7) #define REG_DCDC4_BURST_MODE_SEL_NORMAL (1 << 6) #define REG_DCDC4_VREF_SEL_DSLEEP_SHIFT 4 #define REG_DCDC4_VREF_SEL_DSLEEP_MASK (0x3 << REG_DCDC4_VREF_SEL_DSLEEP_SHIFT) #define REG_DCDC4_VREF_SEL_DSLEEP(n) BITFIELD_VAL(REG_DCDC4_VREF_SEL_DSLEEP, n) #define REG_DCDC4_VREF_SEL_NORMAL_SHIFT 2 #define REG_DCDC4_VREF_SEL_NORMAL_MASK (0x3 << REG_DCDC4_VREF_SEL_NORMAL_SHIFT) #define REG_DCDC4_VREF_SEL_NORMAL(n) BITFIELD_VAL(REG_DCDC4_VREF_SEL_NORMAL, n) #define REG_PU_DCDC4_DR (1 << 1) #define REG_PU_DCDC4 (1 << 0) // 4F PMU_REG_POWER_OFF #define SOFT_POWER_OFF (1 << 0) #define HARDWARE_POWER_OFF_EN (1 << 1) #define AC_ON_EN (1 << 2) #define RC_CAL_READY (1 << 3) #define KEY_START (1 << 4) #define GPADC_START (1 << 5) #define EFUSE_READ_DONE (1 << 6) #define EFUSE_READ_BUSY (1 << 7) #define VBAT_OVP (1 << 8) #define VCORE_LOW (1 << 9) #define REG_LED_IO1_DATA_IN (1 << 10) #define REG_LED_IO2_DATA_IN (1 << 11) #define RD_EFUSE_REG (1 << 12) #define REG_WDT_LOAD (1 << 13) #define EFUSE_READ_TRIG_SHIFT (12) #define EFUSE_READ_TRIG_MASK (0xF << EFUSE_READ_TRIG_SHIFT) #define EFUSE_READ_TRIG(n) BITFIELD_VAL(EFUSE_READ_TRIG, n) #define EFUSE_READ_TRIG_WORD (0xA) // 52 PMU_REG_INT_STATUS #define RD_RES1 (1 << 15) #define RTC_INT_1 (1 << 14) #define RTC_INT_0 (1 << 13) #define KEY_ERR1_INTR (1 << 12) #define KEY_ERR0_INTR (1 << 11) #define KEY_PRESS_INTR (1 << 10) #define KEY_RELEASE_INTR (1 << 9) #define SAMPLE_PERIOD_DONE_INTR (1 << 8) #define CHAN_DATA_VALID_INTR_SHIFT 0 #define CHAN_DATA_VALID_INTR_MASK (0xFF << CHAN_DATA_VALID_INTR_SHIFT) #define CHAN_DATA_VALID_INTR(n) BITFIELD_VAL(CHAN_DATA_VALID_INTR, n) // 53 PMU_REG_INT_MSKED_STATUS // 51 PMU_REG_INT_CLR #define PMIC_CODEC_PWM (1 << 15) #define RTC_INT1_MSKED (1 << 14) #define RTC_INT0_MSKED (1 << 13) #define KEY_ERR1_INTR_MSKED (1 << 12) #define KEY_ERR0_INTR_MSKED (1 << 11) #define KEY_PRESS_INTR_MSKED (1 << 10) #define KEY_RELEASE_INTR_MSKED (1 << 9) #define SAMPLE_DONE_INTR_MSKED (1 << 8) #define CHAN_DATA_INTR_MSKED_SHIFT 0 #define CHAN_DATA_INTR_MSKED_MASK (0xFF << CHAN_DATA_INTR_MSKED_SHIFT) #define CHAN_DATA_INTR_MSKED(n) BITFIELD_VAL(CHAN_DATA_INTR_MSKED, n) // 5E PMU_REG_CHARGER_STATUS #define DIG_PU_VHPPA (1 << 15) #define DIG_PU_VRTC_RF (1 << 14) #define DIG_PU_VCODEC (1 << 13) #define DIG_PU_VUSB (1 << 12) #define POWER_ON_RELEASE (1 << 11) #define POWER_ON_PRESS (1 << 10) #define POWER_ON (1 << 9) #define DEEPSLEEP_MODE (1 << 8) // #define PMU_LDO_ON (1 << 7) #define PU_OSC_OUT (1 << 6) #define UVLO_LV (1 << 5) #define AC_ON_DET_OUT_MASKED (1 << 4) #define AC_ON_DET_IN_MASKED (1 << 3) #define AC_ON (1 << 2) #define AC_ON_DET_OUT (1 << 1) #define AC_ON_DET_IN (1 << 0) // 77 PMU_REG_ANA_77 #define REG_AUDPLL_DIVN_SHIFT 0 #define REG_AUDPLL_DIVN_MASK (0x1F << REG_AUDPLL_DIVN_SHIFT) #define REG_AUDPLL_DIVN(n) BITFIELD_VAL(REG_AUDPLL_DIVN, n) #define REG_AUDPLL_DIVN_RST (1 << 5) #define REG_AUDPLL_DIV_DR (1 << 6) #define REG_AUDPLL_EN_CLKA (1 << 7) #define REG_AUDPLL_EN_CLKD (1 << 8) #define REG_AUDPLL_FORCE_LK (1 << 9) #define REG_AUDPLL_LK_ERR23 (1 << 10) #define REG_AUDPLL_LK_LONG (1 << 11) #define REG_AUDPLL_LK_RSTB (1 << 12) #define REG_AUDPLL_LK_WIN_SHIFT 13 #define REG_AUDPLL_LK_WIN_MASK (0x7 << REG_AUDPLL_LK_WIN_SHIFT) #define REG_AUDPLL_LK_WIN(n) BITFIELD_VAL(REG_AUDPLL_LK_WIN, n) // 101 PMU_REG_DCDC_RAMP_EN #define REG_MIC_BIASA_IX2 (1 << 15) #define REG_MIC_BIASB_IX2 (1 << 14) #define REG_MIC_BIASC_IX2 (1 << 13) #define REG_MIC_BIASD_IX2 (1 << 12) #define REG_MIC_BIASE_IX2 (1 << 11) #define REG_PULLDOWN_VGP (1 << 10) #define REG_PU_LDO_DIG_DSLEEP (1 << 9) #define LDO_VHPPA2VCODEC_BYPASS (1 << 8) #define LDO_VGP_LV_MODE (1 << 7) #define IPTAT_EN (1 << 6) #define REG_PU_AVDD25_ANA (1 << 5) #define REG_DCDC1_RAMP_EN (1 << 4) #define REG_DCDC2_RAMP_EN (1 << 3) #define REG_DCDC3_RAMP_EN (1 << 2) #define REG_PU_VMEM_DELAY_DR (1 << 1) #define REG_PU_VMEM_DELAY (1 << 0) // 107 PMU_REG_SUBCNT_DATA #define SUBCNT_DATA2_SHIFT 8 #define SUBCNT_DATA2_MASK (0xFF << SUBCNT_DATA2_SHIFT) #define SUBCNT_DATA2(n) BITFIELD_VAL(SUBCNT_DATA2, n) #define SUBCNT_DATA3_SHIFT 0 #define SUBCNT_DATA3_MASK (0xFF << SUBCNT_DATA3_SHIFT) #define SUBCNT_DATA3(n) BITFIELD_VAL(SUBCNT_DATA3, n) // 108 PMU_REG_PWM_BR_EN #define TG_SUBCNT_D2_ST_SHIFT 9 #define TG_SUBCNT_D2_ST_MASK (0x7F << TG_SUBCNT_D2_ST_SHIFT) #define TG_SUBCNT_D2_ST(n) BITFIELD_VAL(TG_SUBCNT_D2_ST, n) #define REG_PWM2_BR_EN (1 << 8) #define TG_SUBCNT_D3_ST_SHIFT 1 #define TG_SUBCNT_D3_ST_MASK (0x7F << TG_SUBCNT_D3_ST_SHIFT) #define TG_SUBCNT_D3_ST(n) BITFIELD_VAL(TG_SUBCNT_D3_ST, n) #define REG_PWM3_BR_EN (1 << 0) // 109 PMU_REG_PWM_EN #define REG_LED0_OUT (1 << 15) #define REG_LED1_OUT (1 << 14) #define PWM_SELECT_EN_SHIFT 12 #define PWM_SELECT_EN_MASK (0x3 << PWM_SELECT_EN_SHIFT) #define PWM_SELECT_EN(n) BITFIELD_VAL(PWM_SELECT_EN, n) #define PWM_SELECT_INV_SHIFT 10 #define PWM_SELECT_INV_MASK (0x3 << PWM_SELECT_INV_SHIFT) #define PWM_SELECT_INV(n) BITFIELD_VAL(PWM_SELECT_INV, n) #define REG_CLK_PWM_DIV_SHIFT 5 #define REG_CLK_PWM_DIV_MASK (0x1F << REG_CLK_PWM_DIV_SHIFT) #define REG_CLK_PWM_DIV(n) BITFIELD_VAL(REG_CLK_PWM_DIV, n) // 10B PMU_REG_WDT_TIMER #define REG_WDT_TIMER_SHIFT 0 #define REG_WDT_TIMER_MASK (0xFFFF << REG_WDT_TIMER_SHIFT) #define REG_WDT_TIMER(n) BITFIELD_VAL(REG_WDT_TIMER, n) // 10C PMU_REG_WDT_CFG #define REG_HW_RESET_TIME_SHIFT 10 #define REG_HW_RESET_TIME_MASK (0x3F << REG_HW_RESET_TIME_SHIFT) #define REG_HW_RESET_TIME(n) BITFIELD_VAL(REG_HW_RESET_TIME, n) #define REG_HW_RESET_EN (1 << 9) #define REG_WDT_RESET_EN (1 << 8) #define REG_WDT_EN (1 << 7) #define BG_R_TEMP_SHIFT 4 #define BG_R_TEMP_MASK (0x7 << BG_R_TEMP_SHIFT) #define BG_R_TEMP(n) BITFIELD_VAL(BG_R_TEMP, n) #define BG_TRIM_VBG_SHIFT 1 #define BG_TRIM_VBG_MASK (0x7 << BG_TRIM_VBG_SHIFT) #define BG_TRIM_VBG(n) BITFIELD_VAL(BG_TRIM_VBG, n) #define SAR_PU_OVP (1 << 0) // 80 PMU_REG_RF_80 #define RF_80_PAGE_IDX (1 << 15) #define RF_80_S_DONE_SHIFT 4 #define RF_80_S_DONE_MASK (0x7FF << RF_80_S_DONE_SHIFT) #define RF_80_S_DONE(n) BITFIELD_VAL(RF_80_S_DONE, n) #define RF_80_REVID_SHIFT 0 #define RF_80_REVID_MASK (0xF << RF_80_REVID_SHIFT) #define RF_80_REVID(n) BITFIELD_VAL(RF_80_REVID, n) // BD PMU_REG_RF_BD #define REG_BBPLL_FREQ_34_32_SHIFT 0 #define REG_BBPLL_FREQ_34_32_MASK (0x7 << REG_BBPLL_FREQ_34_32_SHIFT) #define REG_BBPLL_FREQ_34_32(n) BITFIELD_VAL(REG_BBPLL_FREQ_34_32, n) #define REG_BBPLL_FREQ_EN (1 << 3) enum PMU_REG_T { PMU_REG_METAL_ID = 0x00, PMU_REG_POWER_KEY_CFG = 0x02, PMU_REG_BIAS_CFG = 0x03, PMU_REG_CHARGER_CFG = 0x05, PMU_REG_ANA_CFG = 0x07, PMU_REG_DIG_CFG = 0x08, PMU_REG_IO_CFG = 0x09, PMU_REG_MEM_CFG = 0x0A, PMU_REG_GP_CFG = 0x0B, PMU_REG_USB_CFG = 0x0C, PMU_REG_BAT2DIG_CFG = 0x0D, PMU_REG_HPPA_LDO_EN = 0x0E, PMU_REG_HPPA2CODEC_CFG = 0x0F, PMU_REG_CODEC_CFG = 0x10, PMU_REG_DCDC_DIG_EN = 0x15, PMU_REG_DCDC_ANA_CFG_16 = 0x16, PMU_REG_DCDC_ANA_CFG_17 = 0x17, PMU_REG_DCDC_ANA_CFG_18 = 0x18, PMU_REG_DCDC_ANA_CFG_19 = 0x19, PMU_REG_DCDC_HPPA_CFG_1A = 0x1A, PMU_REG_DCDC_HPPA_CFG_1B = 0x1B, PMU_REG_DCDC_HPPA_CFG_1C = 0x1C, PMU_REG_DCDC_HPPA_CFG_1D = 0x1D, PMU_REG_PWR_SEL = 0x21, PMU_REG_INT_MASK = 0x26, PMU_REG_INT_EN = 0x27, PMU_REG_RTC_LOAD_LOW = 0x2D, PMU_REG_RTC_LOAD_HIGH = 0x2E, PMU_REG_RTC_MATCH1_LOW = 0x31, PMU_REG_RTC_MATCH1_HIGH = 0x32, PMU_REG_DCDC_DIG_CFG_33 = 0x33, PMU_REG_DCDC_DIG_CFG_34 = 0x34, PMU_REG_DCDC_DIG_CFG_35 = 0x35, PMU_REG_DCDC_DIG_CFG_36 = 0x36, PMU_REG_RTC_DIV_1HZ = 0x37, PMU_REG_MIC_BIAS_E = 0x38, PMU_REG_MIC_LDO_EN = 0x39, PMU_REG_LED_CFG = 0x3A, PMU_REG_MIC_BIAS_A = 0x3B, PMU_REG_MIC_BIAS_B = 0x3C, PMU_REG_MIC_BIAS_C = 0x3D, PMU_REG_MIC_BIAS_D = 0x3E, PMU_REG_EFUSE_CTRL = 0x3F, PMU_REG_EFUSE_SEL = 0x40, PMU_REG_DCDC1_OFFSET = 0x41, PMU_REG_BUCK2ANA_CFG = 0x43, PMU_REG_SLEEP_CFG = 0x44, PMU_REG_DCDC_DIG_VOLT = 0x46, PMU_REG_DCDC_ANA_VOLT = 0x47, PMU_REG_DCDC_HPPA_VOLT = 0x48, PMU_REG_DCDC4_VOLT = 0x49, PMU_REG_DCDC_ANA_EN = 0x4A, PMU_REG_DCDC_HPPA_EN = 0x4B, PMU_REG_POWER_OFF = 0x4F, PMU_REG_INT_CLR = 0x51, PMU_REG_INT_STATUS = 0x52, PMU_REG_INT_MSKED_STATUS = 0x53, PMU_REG_RTC_VAL_LOW = 0x54, PMU_REG_RTC_VAL_HIGH = 0x55, PMU_REG_CHARGER_STATUS = 0x5E, PMU_REG_DCDC_RAMP_EN = 0x101, PMU_REG_PWM2_TOGGLE = 0x103, PMU_REG_PWM3_TOGGLE = 0x104, PMU_REG_PWM2_ST1 = 0x105, PMU_REG_PWM3_ST1 = 0x106, PMU_REG_SUBCNT_DATA = 0x107, PMU_REG_PWM_BR_EN = 0x108, PMU_REG_PWM_EN = 0x109, PMU_REG_WDT_TIMER = 0x10B, PMU_REG_WDT_CFG = 0x10C, PMU_REG_MODULE_START = PMU_REG_ANA_CFG, PMU_REG_EFUSE_VAL_START = 0x148, PMU_REG_ANA_60 = 0x60, PMU_REG_ANA_77 = 0x77, PMU_REG_RF_80 = 0x80, PMU_REG_RF_B5 = 0xB5, PMU_REG_RF_BB = 0xBB, PMU_REG_RF_BC = 0xBC, PMU_REG_RF_BD = 0xBD, }; enum PMU_VCORE_REQ_T { PMU_VCORE_FLASH_WRITE_ENABLED = (1 << 0), PMU_VCORE_FLASH_FREQ_HIGH = (1 << 1), PMU_VCORE_PSRAM_FREQ_HIGH = (1 << 2), PMU_VCORE_USB_HS_ENABLED = (1 << 3), PMU_VCORE_RS_FREQ_HIGH = (1 << 4), PMU_VCORE_SYS_FREQ_MEDIUM = (1 << 5), PMU_VCORE_SYS_FREQ_HIGH = (1 << 6), }; enum PMU_VUSB_REQ_T { PMU_VUSB_REQ_INIT = (1 << 0), PMU_VUSB_REQ_USB = (1 << 1), PMU_VUSB_REQ_LBRT = (1 << 2), }; union BOOT_SETTINGS_T { struct { unsigned short usb_dld_dis : 1; unsigned short uart_dld_en : 1; unsigned short uart_trace_en : 1; unsigned short pll_dis : 1; unsigned short uart_baud_div2 : 1; unsigned short sec_freq_div2 : 1; unsigned short crystal_freq : 2; unsigned short reserved : 4; unsigned short chksum : 4; }; unsigned short reg; }; enum PMU_MODUAL_T { PMU_ANA, PMU_DIG, PMU_IO, PMU_MEM, PMU_GP, PMU_USB, PMU_BAT2DIG, PMU_HPPA2CODEC, PMU_CODEC, PMU_BUCK2ANA, }; struct PMU_MODULE_CFG_T { unsigned short pu_dr; unsigned short pu; unsigned short lp_en_dr; unsigned short lp_en; unsigned short pu_dsleep; unsigned short vbit_dsleep_mask; unsigned short vbit_dsleep_shift; unsigned short vbit_normal_mask; unsigned short vbit_normal_shift; }; #define PMU_MOD_CFG_VAL(m) \ { \ REG_PU_LDO_V##m##_DR, REG_PU_LDO_V##m##_REG, LP_EN_V##m##_LDO_DR, \ LP_EN_V##m##_LDO_REG, REG_PU_LDO_V##m##_DSLEEP, \ LDO_V##m##_VBIT_DSLEEP_MASK, LDO_V##m##_VBIT_DSLEEP_SHIFT, \ LDO_V##m##_VBIT_NORMAL_MASK, LDO_V##m##_VBIT_NORMAL_SHIFT \ } static const struct PMU_MODULE_CFG_T pmu_module_cfg[] = { PMU_MOD_CFG_VAL(ANA), PMU_MOD_CFG_VAL(CORE), PMU_MOD_CFG_VAL(IO), PMU_MOD_CFG_VAL(MEM), PMU_MOD_CFG_VAL(GP), PMU_MOD_CFG_VAL(USB), PMU_MOD_CFG_VAL(BAT2VCORE), PMU_MOD_CFG_VAL(HPPA2VCODEC), PMU_MOD_CFG_VAL(CODEC), PMU_MOD_CFG_VAL(BUCK2ANA), }; #ifdef ANC_PROD_TEST #define OPT_TYPE #else #define OPT_TYPE const #endif static OPT_TYPE bool vcodec_off = #ifdef VCODEC_OFF true; #else false; #endif static OPT_TYPE uint8_t ana_act_dcdc = #ifdef VANA_1P2V PMU_DCDC_ANA_1_2V; #elif defined(VANA_1P35V) PMU_DCDC_ANA_1_35V; #elif defined(VANA_1P4V) PMU_DCDC_ANA_1_4V; #elif defined(VANA_1P5V) PMU_DCDC_ANA_1_5V; #elif defined(VANA_1P6V) PMU_DCDC_ANA_1_6V; #else PMU_DCDC_ANA_1_3V; #endif static OPT_TYPE POSSIBLY_UNUSED uint16_t vcodec_mv = (uint16_t)(VCODEC_VOLT * 1000); static OPT_TYPE POSSIBLY_UNUSED uint16_t vhppa_mv = (uint16_t)(VHPPA_VOLT * 1000); static enum HAL_CHIP_METAL_ID_T BOOT_BSS_LOC pmu_metal_id; static enum PMU_POWER_MODE_T BOOT_BSS_LOC pmu_power_mode = PMU_POWER_MODE_NONE; static enum PMU_VCORE_REQ_T BOOT_BSS_LOC pmu_vcore_req; // Move all the data/bss invovled in pmu_open() to .sram_data/.sram_bss, // so that pmu_open() can be called at the end of BootInit(), // for data/bss is initialized after BootInit(). static enum PMU_VUSB_REQ_T SRAM_BSS_DEF(pmu_vusb_req); static uint16_t SRAM_BSS_DEF(dcdc_ramp_map); static PMU_CHARGER_IRQ_HANDLER_T charger_irq_handler; static PMU_IRQ_UNIFIED_HANDLER_T pmu_irq_hdlrs[PMU_IRQ_TYPE_QTY]; static uint8_t SRAM_BSS_DEF(vio_risereq_map); STATIC_ASSERT(sizeof(vio_risereq_map) * 8 >= PMU_VIORISE_REQ_USER_QTY, "vio_risereq_map size too small"); static uint8_t SRAM_DATA_DEF(vio_act_normal) = IO_VOLT_ACTIVE_NORMAL; static uint8_t SRAM_DATA_DEF(vio_act_rise) = IO_VOLT_ACTIVE_RISE; static uint8_t SRAM_DATA_DEF(vio_lp) = IO_VOLT_SLEEP; static const uint8_t ana_lp_dcdc = PMU_DCDC_ANA_SLEEP_1_3V; // BT might have connection drop issues if dig_lp is lower than 0.8V static const uint8_t dig_lp_ldo = PMU_VDIG_0_8V; static const uint8_t dig_lp_dcdc = PMU_DCDC_DIG_0_8V; static uint8_t BOOT_DATA_DEF(audpll_codec_div) = 16; #ifdef HIGH_VCORE static const bool high_vcore = true; #else static bool BOOT_BSS_DEF(high_vcore); #endif static uint16_t wdt_timer; #if defined(MCU_HIGH_PERFORMANCE_MODE) static const uint16_t high_perf_freq_mhz = #if defined(MTEST_ENABLED) && defined(MTEST_CLK_MHZ) MTEST_CLK_MHZ; #else 300; #endif static bool high_perf_on; #endif void pmu_wdt_save_context(void); void pmu_wdt_restore_context(void); void pmu_charger_save_context(void); void pmu_charger_shutdown_config(void); #if defined(PMU_INIT) || (!defined(PROGRAMMER)) static void pmu_hppa_dcdc_to_ldo(void); #endif #if defined(_AUTO_TEST_) static bool at_skip_shutdown = false; void pmu_at_skip_shutdown(bool enable) { at_skip_shutdown = enable; } #endif #ifdef RTC_ENABLE struct PMU_RTC_CTX_T { bool enabled; bool alarm_set; uint32_t alarm_val; }; static struct PMU_RTC_CTX_T BOOT_BSS_LOC rtc_ctx; static PMU_RTC_IRQ_HANDLER_T rtc_irq_handler; static void BOOT_TEXT_SRAM_LOC pmu_rtc_save_context(void) { if (pmu_rtc_enabled()) { rtc_ctx.enabled = true; if (pmu_rtc_alarm_status_set()) { rtc_ctx.alarm_set = true; rtc_ctx.alarm_val = pmu_rtc_get_alarm(); } } else { rtc_ctx.enabled = false; } } static void pmu_rtc_restore_context(void) { uint32_t rtc_val; if (rtc_ctx.enabled) { pmu_rtc_enable(); if (rtc_ctx.alarm_set) { rtc_val = pmu_rtc_get(); if (rtc_val - rtc_ctx.alarm_val <= 1 || rtc_ctx.alarm_val - rtc_val < 5) { rtc_ctx.alarm_val = rtc_val + 5; } pmu_rtc_set_alarm(rtc_ctx.alarm_val); } } } #endif #ifdef PMU_DCDC_CALIB union VOLT_COMP_T { struct VOLT_COMP_FIELD_T { uint16_t dcdc1_v : 5; // bit[4:0]: 0 ~ 31 uint16_t dcdc1_f : 1; // bit[5] : 1: negative, 0: positive; uint16_t dcdc2_v : 4; // bit[9:6]: 0 ~ 15 uint16_t dcdc2_f : 1; // bit[10] : uint16_t dcdc3_v : 4; // bit[14:11]: 0 ~ 15 uint16_t dcdc3_f : 1; // bit[15] } f; uint16_t v; }; static int8_t pmu_dcdc_dig_comp = 0; static int8_t pmu_dcdc_ana_comp = 0; static int8_t pmu_dcdc_hppa_comp = 0; static POSSIBLY_UNUSED void pmu_get_dcdc_calib_value(void) { union VOLT_COMP_T cv; pmu_get_efuse(PMU_EFUSE_PAGE_RESERVED_7, &cv.v); if (cv.f.dcdc1_f) { // digital pmu_dcdc_dig_comp = -(int8_t)(cv.f.dcdc1_v); } else { pmu_dcdc_dig_comp = (int8_t)(cv.f.dcdc1_v); } if (cv.f.dcdc2_f) { // ana pmu_dcdc_ana_comp = -(int8_t)(cv.f.dcdc2_v); } else { pmu_dcdc_ana_comp = (int8_t)(cv.f.dcdc2_v); } if (cv.f.dcdc3_f) { // hppa pmu_dcdc_hppa_comp = -(int8_t)(cv.f.dcdc3_v); } else { pmu_dcdc_hppa_comp = (int8_t)(cv.f.dcdc3_v); } } static POSSIBLY_UNUSED unsigned short pmu_reg_val_add(unsigned short val, int delta, unsigned short max) { int result = val + delta; if (result > max) { result = max; } else if (result < 0) { result = 0; } return (unsigned short)result; } #endif static unsigned int NOINLINE BOOT_TEXT_SRAM_LOC pmu_count_zeros(unsigned int val, unsigned int bits) { int cnt = 0; int i; for (i = 0; i < bits; i++) { if ((val & (1 << i)) == 0) { cnt++; } } return cnt; } static int BOOT_TEXT_FLASH_LOC pmu_read_efuse_block(unsigned int block) { int ret; unsigned short val; uint32_t start; uint32_t timeout = MS_TO_TICKS(50); val = TSMC_EFUSE_PGENB | TSMC_EFUSE_CLK_EN; ret = pmu_write(PMU_REG_EFUSE_CTRL, val); if (ret) { return ret; } val = TSMC_EFUSE_STROBE_WIDTH(20) | REG_READ_STROBE_WIDTH(4) | EFUSE_SEL(block); ret = pmu_write(PMU_REG_EFUSE_SEL, val); if (ret) { return ret; } ret = pmu_read(PMU_REG_POWER_OFF, &val); if (ret) { return ret; } val = SET_BITFIELD(val, EFUSE_READ_TRIG, EFUSE_READ_TRIG_WORD); ret = pmu_write(PMU_REG_POWER_OFF, val); if (ret) { return ret; } hal_sys_timer_delay(US_TO_TICKS(500)); start = hal_sys_timer_get(); do { ret = pmu_read(PMU_REG_POWER_OFF, &val); if (ret) { return ret; } if (hal_sys_timer_get() - start > timeout) { return -2; } } while ((val & (EFUSE_READ_DONE | EFUSE_READ_BUSY)) != EFUSE_READ_DONE); val = TSMC_EFUSE_PGENB; ret = pmu_write(PMU_REG_EFUSE_CTRL, val); if (ret) { return ret; } return 0; } void BOOT_TEXT_FLASH_LOC bbpll_freq_pll_config(uint32_t freq) { int ret; uint64_t PLL_cfg_val; uint16_t v[3]; uint16_t val; uint32_t crystal = hal_cmu_get_crystal_freq(); PLL_cfg_val = ((uint64_t)(1 << 28) * (freq / 2) + crystal / 2) / crystal; v[0] = PLL_cfg_val & 0xFFFF; v[1] = (PLL_cfg_val >> 16) & 0xFFFF; v[2] = (PLL_cfg_val >> 32) & 0xFFFF; ret = pmu_write(PMU_REG_RF_BB, v[0]); if (ret) { return; } ret = pmu_write(PMU_REG_RF_BC, v[1]); if (ret) { return; } ret = pmu_read(PMU_REG_RF_BD, &val); if (ret) { return; } val = SET_BITFIELD(val, REG_BBPLL_FREQ_34_32, v[2]) | REG_BBPLL_FREQ_EN; ret = pmu_write(PMU_REG_RF_BD, val); if (ret) { return; } // Delay at least for 7us hal_sys_timer_delay(US_TO_TICKS(100)); } uint32_t BOOT_TEXT_FLASH_LOC read_hw_metal_id(void) { int ret; uint16_t val; uint32_t metal_id; int i; union BOOT_SETTINGS_T boot; #ifdef RTC_ENABLE // RTC will be restored in pmu_open() pmu_rtc_save_context(); #endif pmu_wdt_save_context(); pmu_charger_save_context(); // Reset PMU (to recover from a possible insane state, e.g., ESD reset) pmu_write(PMU_REG_METAL_ID, 0xCAFE); pmu_write(PMU_REG_METAL_ID, 0x5FEE); hal_sys_timer_delay(US_TO_TICKS(500)); #if defined(PMU_FULL_INIT) || (!defined(PROGRAMMER)) // Reset RF pmu_write(PMU_REG_RF_80, 0xCAFE); pmu_write(PMU_REG_RF_80, 0x5FEE); hal_sys_timer_delay(US_TO_TICKS(500)); // Reset ANA pmu_write(PMU_REG_ANA_60, 0xCAFE); pmu_write(PMU_REG_ANA_60, 0x5FEE); hal_sys_timer_delay(US_TO_TICKS(500)); #endif #ifdef __WATCHER_DOG_RESET__ pmu_wdt_restore_context(); #endif #ifndef EFUSE_BLOCK_NUM #define EFUSE_BLOCK_NUM 6 #endif for (i = 0; i < EFUSE_BLOCK_NUM; i++) { ret = pmu_read_efuse_block(i); if (ret) { SAFE_PROGRAM_STOP(); } } ret = pmu_get_efuse(PMU_EFUSE_PAGE_BOOT, &boot.reg); if (ret) { boot.reg = 0; } else { if (pmu_count_zeros(boot.reg, 12) != boot.chksum) { boot.reg = 0; } } hal_cmu_set_crystal_freq_index(boot.crystal_freq); // Update ISPI cfg ret = hal_analogif_open(); if (ret) { SAFE_PROGRAM_STOP(); } #if !defined(PROGRAMMER) && !defined(MCU_HIGH_PERFORMANCE_MODE) if (hal_cmu_get_crystal_freq() != hal_cmu_get_default_crystal_freq()) { // Update bbpll freq after resetting RF and getting crystal freq bbpll_freq_pll_config(384000000); } #endif #if 0 #ifndef HIGH_VCORE pmu_get_efuse(PMU_EFUSE_PAGE_SW_CFG, &val); if ((val & (3 << 13)) == (3 << 13)) { high_vcore = true; } #endif #endif // enhance xtal drv pmu_write(0x9d, 0x886c); // Enable 26M doubler (52M) pmu_write(0xB5, 0x8000); #ifdef ANA_26M_X4_ENABLE pmu_write(0xBF, 0x0400); #endif // Power up bbpll and audpll clk buf // Clk buf bits: // 0-rfpll 1-bt_dac 2-codec_resample&audpll_prechr 3-bbpll 4-audpll 5-usbhspll // 6-lbrt 7-dig pmu_read(0xC4, &val); val &= ~0xFF; val |= (1 << 2) | (1 << 3) | (1 << 4) | (1 << 7); #if defined(USB_HIGH_SPEED) || defined(USB_USE_USBPLL) val |= (1 << 5); #endif pmu_write(0xC4, val); // Cfg bbpll pmu_write(0x9F, 0xC22F); pmu_write(0xA0, 0x2788); // Cfg audpll pmu_write(0x79, 0x0011); pmu_write(0x77, 0x71B1); // Set audpll to 24.576M*17 pmu_write(0x7C, 0x4F16); pmu_write(0x7B, 0x011A); pmu_write(0x7A, 0x2008); // Clear reg_bt_tst_buf_sel_in/out to avoid impacting P00-P03 and P30-P33 pins pmu_write(0xA2, 0x01C2); // Enable SWD debug mode pmu_read(PMU_REG_SLEEP_CFG, &val); val = SET_BITFIELD(val, PMIC_TMODE_1300, 2); pmu_write(PMU_REG_SLEEP_CFG, val); pmu_read(PMU_REG_METAL_ID, &val); pmu_metal_id = GET_BITFIELD(val, PMU_METAL_ID); metal_id = hal_cmu_get_aon_revision_id(); if (metal_id == HAL_CHIP_METAL_ID_1) { uint32_t data; hal_psc_bt_enable(); hal_cmu_bt_clock_enable(); hal_cmu_bt_reset_clear(); data = *(volatile uint32_t *)0xA0000004; hal_cmu_bt_reset_set(); hal_cmu_bt_clock_disable(); hal_psc_bt_disable(); if (data == 0xA0007471) { metal_id = HAL_CHIP_METAL_ID_2; } } // Init pll dividers pmu_read(PMU_REG_ANA_77, &val); val = SET_BITFIELD(val, REG_AUDPLL_DIVN, audpll_codec_div); pmu_write(PMU_REG_ANA_77, val); return metal_id; } void BOOT_TEXT_SRAM_LOC pmu_pll_div_reset_set(enum HAL_CMU_PLL_T pll) { uint32_t lock; uint16_t val; lock = int_lock(); if (pll == HAL_CMU_PLL_AUD) { pmu_read(PMU_REG_ANA_77, &val); val |= REG_AUDPLL_DIVN_MASK | REG_AUDPLL_DIVN_RST; pmu_write(PMU_REG_ANA_77, val); } else if (pll == HAL_CMU_PLL_USB) { // In fact bbpll #ifdef AUDIO_USE_BBPLL // 0xD2, bit13 (reset) // 0xF5, bit[4:0] (div) #endif } else if (pll == HAL_CMU_PLL_QTY) { // In fact usbhspll } int_unlock(lock); } void BOOT_TEXT_SRAM_LOC pmu_pll_div_reset_clear(enum HAL_CMU_PLL_T pll) { uint32_t lock; uint16_t val; lock = int_lock(); if (pll == HAL_CMU_PLL_AUD) { pmu_read(PMU_REG_ANA_77, &val); val &= ~REG_AUDPLL_DIVN_RST; pmu_write(PMU_REG_ANA_77, val); val = SET_BITFIELD(val, REG_AUDPLL_DIVN, audpll_codec_div); pmu_write(PMU_REG_ANA_77, val); } else if (pll == HAL_CMU_PLL_USB) { // In fact bbpll #ifdef AUDIO_USE_BBPLL #endif } else if (pll == HAL_CMU_PLL_QTY) { // In fact usbhspll } int_unlock(lock); } void pmu_pll_div_set(enum HAL_CMU_PLL_T pll, enum PMU_PLL_DIV_TYPE_T type, uint32_t div) { uint32_t lock; uint16_t val; if (type != PMU_PLL_DIV_CODEC) { return; } lock = int_lock(); if (pll == HAL_CMU_PLL_AUD) { if (div != audpll_codec_div) { audpll_codec_div = div; pmu_read(PMU_REG_ANA_77, &val); val |= REG_AUDPLL_DIVN_MASK; pmu_write(PMU_REG_ANA_77, val); if (div != (REG_AUDPLL_DIVN_MASK >> REG_AUDPLL_DIVN_SHIFT)) { val = SET_BITFIELD(val, REG_AUDPLL_DIVN, audpll_codec_div); pmu_write(PMU_REG_ANA_77, val); } } } else if (pll == HAL_CMU_PLL_USB) { // In fact bbpll #ifdef AUDIO_USE_BBPLL #endif } else if (pll == HAL_CMU_PLL_QTY) { // In fact usbhspll } int_unlock(lock); } #if defined(USE_CYBERON) static uint32_t BOOT_BSS_LOC cyb_hack_efuse_check = 0; void cyb_efuse_check_enable(int enabled) { cyb_hack_efuse_check = enabled; } int cyb_efuse_check_status(void) { return cyb_hack_efuse_check; } #if 1 int BOOT_TEXT_SRAM_LOC Cyb_pmu_get_efuse(enum PMU_EFUSE_PAGE_T page, unsigned short *efuse) { // PMU_DEBUG_TRACE(2,"page %x, efuse %x", page, efuse); if (page == 0XE) { *efuse = 0x1B9C; } if (page == 0xF) { *efuse = 0x098B; } return 0; } #endif #endif int BOOT_TEXT_SRAM_LOC pmu_get_efuse(enum PMU_EFUSE_PAGE_T page, unsigned short *efuse) { int ret; // #if defined(USE_CYBERON) #if 0 if (cyb_efuse_check_status()) { PMU_DEBUG_TRACE(2,"page %x, efuse %x", page, efuse); if((int)page==0xE){ *efuse=0x1B9C; return 0; } if((int)page==0xF){ *efuse = 0x098B; return 0; } } #endif ret = pmu_read(PMU_REG_EFUSE_VAL_START + page, efuse); return ret; } int pmu_get_security_value(union SECURITY_VALUE_T *val) { int ret; ret = pmu_get_efuse(PMU_EFUSE_PAGE_SECURITY, &val->reg); if (ret) { // Error goto _no_security; } if (!val->security_en) { // OK goto _no_security; } ret = 1; if (pmu_count_zeros(val->key_id, 3) != val->key_chksum) { // Error goto _no_security; } if (pmu_count_zeros(val->vendor_id, 6) != val->vendor_chksum) { // Error goto _no_security; } if ((pmu_count_zeros(val->reg, 15) & 1) != val->chksum) { // Error goto _no_security; } // OK return 0; _no_security: val->reg = 0; return ret; } static void pmu_sys_ctrl(bool shutdown) { uint16_t val; uint32_t lock = int_lock(); PMU_INFO_TRACE_IMM(0, "Start pmu %s", shutdown ? "shutdown" : "reboot"); #if defined(PMU_INIT) || (!defined(PROGRAMMER)) #if defined(MCU_HIGH_PERFORMANCE_MODE) // Default vcore might not be high enough to support high performance mode pmu_high_performance_mode_enable(false); hal_cmu_sys_set_freq(HAL_CMU_FREQ_26M); #endif pmu_hppa_dcdc_to_ldo(); pmu_mode_change(PMU_POWER_MODE_LDO); hal_sys_timer_delay(MS_TO_TICKS(1)); #endif #ifdef RTC_ENABLE pmu_rtc_save_context(); #endif // Reset PMU pmu_write(PMU_REG_METAL_ID, 0xCAFE); pmu_write(PMU_REG_METAL_ID, 0x5FEE); hal_sys_timer_delay(4); #ifdef RTC_ENABLE pmu_rtc_restore_context(); #endif if (shutdown) { #if defined(_AUTO_TEST_) if (at_skip_shutdown) { hal_cmu_sys_reboot(); return; } #endif #if defined(PMU_INIT) || (!defined(PROGRAMMER)) pmu_wdt_config(3 * 1000, 3 * 1000); pmu_wdt_start(); pmu_charger_shutdown_config(); #endif // Power off pmu_read(PMU_REG_POWER_OFF, &val); val |= SOFT_POWER_OFF; for (int i = 0; i < 100; i++) { pmu_write(PMU_REG_POWER_OFF, val); hal_sys_timer_delay(MS_TO_TICKS(5)); } hal_sys_timer_delay(MS_TO_TICKS(50)); // can't reach here PMU_INFO_TRACE_IMM(0, "\nError: pmu shutdown failed!\n"); hal_sys_timer_delay(MS_TO_TICKS(5)); } else { #if defined(PMU_FULL_INIT) || (!defined(PROGRAMMER)) // CAUTION: // 1) Never reset RF because system or flash might be using X2/X4, which are // off by default 2) Never reset RF/ANA because system or flash might be // using PLL, and the reset might cause clock glitch // TODO: // Restore BBPLL settings in RF #endif } hal_cmu_sys_reboot(); int_unlock(lock); } void pmu_shutdown(void) { pmu_sys_ctrl(true); } void pmu_reboot(void) { pmu_sys_ctrl(false); } static inline uint16_t pmu_get_module_addr(enum PMU_MODUAL_T module) { if (module == PMU_HPPA2CODEC || module == PMU_CODEC) { return PMU_REG_MODULE_START + module + 1; } else if (module == PMU_BUCK2ANA) { return PMU_REG_BUCK2ANA_CFG; } else { return PMU_REG_MODULE_START + module; } } void pmu_module_config(enum PMU_MODUAL_T module, unsigned short is_manual, unsigned short ldo_on, unsigned short lp_mode, unsigned short dpmode) { unsigned short val; unsigned char module_address; const struct PMU_MODULE_CFG_T *module_cfg_p = &pmu_module_cfg[module]; module_address = pmu_get_module_addr(module); if (module == PMU_ANA) { pmu_read(PMU_REG_BIAS_CFG, &val); if (is_manual) { val |= module_cfg_p->pu_dr; } else { val &= ~module_cfg_p->pu_dr; } if (ldo_on) { val |= module_cfg_p->pu; } else { val &= ~module_cfg_p->pu; } pmu_write(PMU_REG_BIAS_CFG, val); } else if (module == PMU_DIG) { pmu_read(PMU_REG_DCDC_DIG_EN, &val); if (is_manual) { val |= module_cfg_p->pu_dr; } else { val &= ~module_cfg_p->pu_dr; } if (ldo_on) { val |= module_cfg_p->pu; } else { val &= ~module_cfg_p->pu; } pmu_write(PMU_REG_DCDC_DIG_EN, val); } else if (module == PMU_HPPA2CODEC) { pmu_read(PMU_REG_SLEEP_CFG, &val); if (dpmode) { val |= module_cfg_p->pu_dsleep; } else { val &= ~module_cfg_p->pu_dsleep; } pmu_write(PMU_REG_SLEEP_CFG, val); } else if (module == PMU_CODEC) { pmu_read(PMU_REG_HPPA2CODEC_CFG, &val); if (dpmode) { val |= module_cfg_p->pu_dsleep; } else { val &= ~module_cfg_p->pu_dsleep; } pmu_write(PMU_REG_HPPA2CODEC_CFG, val); } pmu_read(module_address, &val); if (module != PMU_ANA && module != PMU_DIG) { if (is_manual) { val |= module_cfg_p->pu_dr; } else { val &= ~module_cfg_p->pu_dr; } if (ldo_on) { val |= module_cfg_p->pu; } else { val &= ~module_cfg_p->pu; } } if (lp_mode) { val &= ~module_cfg_p->lp_en_dr; } else { val = (val & ~module_cfg_p->lp_en) | module_cfg_p->lp_en_dr; } if (module != PMU_HPPA2CODEC && module != PMU_CODEC) { if (dpmode) { val |= module_cfg_p->pu_dsleep; } else { val &= ~module_cfg_p->pu_dsleep; } } pmu_write(module_address, val); } void pmu_module_set_volt(unsigned char module, unsigned short sleep_v, unsigned short normal_v) { unsigned short val; unsigned char module_address; const struct PMU_MODULE_CFG_T *module_cfg_p = &pmu_module_cfg[module]; module_address = pmu_get_module_addr(module); pmu_read(module_address, &val); val &= ~module_cfg_p->vbit_normal_mask; val |= (normal_v << module_cfg_p->vbit_normal_shift) & module_cfg_p->vbit_normal_mask; val &= ~module_cfg_p->vbit_dsleep_mask; val |= (sleep_v << module_cfg_p->vbit_dsleep_shift) & module_cfg_p->vbit_dsleep_mask; pmu_write(module_address, val); } int pmu_module_get_volt(unsigned char module, unsigned short *sleep_vp, unsigned short *normal_vp) { unsigned short val; unsigned char module_address; const struct PMU_MODULE_CFG_T *module_cfg_p = &pmu_module_cfg[module]; module_address = pmu_get_module_addr(module); pmu_read(module_address, &val); if (normal_vp) { *normal_vp = (val & module_cfg_p->vbit_normal_mask) >> module_cfg_p->vbit_normal_shift; } if (sleep_vp) { *sleep_vp = (val & module_cfg_p->vbit_dsleep_mask) >> module_cfg_p->vbit_dsleep_shift; } return 0; } static void pmu_module_ramp_volt(unsigned char module, unsigned short sleep_v, unsigned short normal_v) { uint16_t old_normal_v; uint16_t old_sleep_v; pmu_module_get_volt(module, &old_sleep_v, &old_normal_v); if (old_normal_v < normal_v) { while (old_normal_v++ < normal_v) { pmu_module_set_volt(module, sleep_v, old_normal_v); } } else if (old_normal_v != normal_v || old_sleep_v != sleep_v) { pmu_module_set_volt(module, sleep_v, normal_v); } } static void pmu_dcdc_ana_get_volt(unsigned short *normal_vp, unsigned short *dsleep_vp) { unsigned short val; pmu_read(PMU_REG_DCDC_ANA_VOLT, &val); if (normal_vp) { *normal_vp = GET_BITFIELD(val, REG_DCDC2_VBIT_NORMAL); } if (dsleep_vp) { *dsleep_vp = GET_BITFIELD(val, REG_DCDC2_VBIT_DSLEEP); } #ifdef PMU_DCDC_CALIB if (normal_vp) { *normal_vp = pmu_reg_val_add(*normal_vp, -pmu_dcdc_ana_comp, MAX_DCDC2_VBIT_VAL); } if (dsleep_vp) { *dsleep_vp = pmu_reg_val_add(*dsleep_vp, -pmu_dcdc_ana_comp, MAX_DCDC2_VBIT_VAL); } #endif } static void pmu_dcdc_ana_set_volt(unsigned short normal_v, unsigned short dsleep_v) { unsigned short val; #ifdef PMU_DCDC_CALIB normal_v = pmu_reg_val_add(normal_v, pmu_dcdc_ana_comp, MAX_DCDC2_VBIT_VAL); dsleep_v = pmu_reg_val_add(dsleep_v, pmu_dcdc_ana_comp, MAX_DCDC2_VBIT_VAL); #endif pmu_read(PMU_REG_DCDC_ANA_VOLT, &val); val &= ~REG_DCDC2_VBIT_DSLEEP_MASK; val &= ~REG_DCDC2_VBIT_NORMAL_MASK; val |= REG_DCDC2_VBIT_DSLEEP(dsleep_v); val |= REG_DCDC2_VBIT_NORMAL(normal_v); pmu_write(PMU_REG_DCDC_ANA_VOLT, val); if (normal_v > dsleep_v) { dcdc_ramp_map |= REG_DCDC2_RAMP_EN; } else { dcdc_ramp_map &= ~REG_DCDC2_RAMP_EN; } } static void pmu_ana_set_volt(int mode_change, enum PMU_POWER_MODE_T mode) { uint16_t old_act_dcdc; uint16_t old_lp_dcdc; uint16_t new_act_dcdc; if (mode == PMU_POWER_MODE_ANA_DCDC || mode == PMU_POWER_MODE_DIG_DCDC) { pmu_dcdc_ana_get_volt(&old_act_dcdc, &old_lp_dcdc); new_act_dcdc = ana_act_dcdc; if (old_act_dcdc < new_act_dcdc) { while (old_act_dcdc++ < new_act_dcdc) { pmu_dcdc_ana_set_volt(old_act_dcdc, ana_lp_dcdc); } hal_sys_timer_delay_us(PMU_VANA_STABLE_TIME_US); } else if (old_act_dcdc != new_act_dcdc || old_lp_dcdc != ana_lp_dcdc) { pmu_dcdc_ana_set_volt(new_act_dcdc, ana_lp_dcdc); } } } static void pmu_dcdc_dig_get_volt(unsigned short *normal_vp, unsigned short *dsleep_vp) { unsigned short val; pmu_read(PMU_REG_DCDC_DIG_VOLT, &val); if (normal_vp) { *normal_vp = GET_BITFIELD(val, REG_DCDC1_VBIT_NORMAL); } if (dsleep_vp) { *dsleep_vp = GET_BITFIELD(val, REG_DCDC1_VBIT_DSLEEP); } #ifdef PMU_DCDC_CALIB if (normal_vp) { *normal_vp = pmu_reg_val_add(*normal_vp, -pmu_dcdc_dig_comp, MAX_DCDC1_VBIT_VAL); } if (dsleep_vp) { *dsleep_vp = pmu_reg_val_add(*dsleep_vp, -pmu_dcdc_dig_comp, MAX_DCDC1_VBIT_VAL); } #endif } static void pmu_dcdc_dig_set_volt(unsigned short normal_v, unsigned short dsleep_v) { unsigned short val; #ifdef PMU_DCDC_CALIB normal_v = pmu_reg_val_add(normal_v, pmu_dcdc_dig_comp, MAX_DCDC1_VBIT_VAL); dsleep_v = pmu_reg_val_add(dsleep_v, pmu_dcdc_dig_comp, MAX_DCDC1_VBIT_VAL); #endif pmu_read(PMU_REG_DCDC_DIG_VOLT, &val); val &= ~REG_DCDC1_VBIT_DSLEEP_MASK; val &= ~REG_DCDC1_VBIT_NORMAL_MASK; val |= REG_DCDC1_VBIT_DSLEEP(dsleep_v); val |= REG_DCDC1_VBIT_NORMAL(normal_v); pmu_write(PMU_REG_DCDC_DIG_VOLT, val); if (normal_v > dsleep_v) { dcdc_ramp_map |= REG_DCDC1_RAMP_EN; } else { dcdc_ramp_map &= ~REG_DCDC1_RAMP_EN; } } static void BOOT_TEXT_SRAM_LOC pmu_dig_get_target_volt(uint16_t *ldo, uint16_t *dcdc) { uint16_t ldo_volt; uint16_t dcdc_volt; if (0) { #if defined(MCU_HIGH_PERFORMANCE_MODE) } else if (pmu_vcore_req & (PMU_VCORE_SYS_FREQ_HIGH)) { if (high_perf_freq_mhz <= 260) { ldo_volt = PMU_VDIG_1_05V; dcdc_volt = PMU_DCDC_DIG_1_05V; } else if (high_perf_freq_mhz <= 300) { ldo_volt = PMU_VDIG_1_1V; dcdc_volt = PMU_DCDC_DIG_1_1V; } else { ldo_volt = PMU_VDIG_1_2V; dcdc_volt = PMU_DCDC_DIG_1_1V; } #endif } else if (pmu_vcore_req & (PMU_VCORE_USB_HS_ENABLED | PMU_VCORE_RS_FREQ_HIGH | PMU_VCORE_SYS_FREQ_MEDIUM)) { ldo_volt = PMU_VDIG_0_9V; dcdc_volt = PMU_DCDC_DIG_0_9V; } else if (pmu_vcore_req & (PMU_VCORE_FLASH_FREQ_HIGH | PMU_VCORE_PSRAM_FREQ_HIGH | PMU_VCORE_FLASH_WRITE_ENABLED)) { ldo_volt = PMU_VDIG_0_8V; dcdc_volt = PMU_DCDC_DIG_0_8V; } else { // Common cases if (high_vcore) { ldo_volt = PMU_VDIG_0_8V; dcdc_volt = PMU_DCDC_DIG_0_8V; } else { ldo_volt = PMU_VDIG_0_75V; dcdc_volt = PMU_DCDC_DIG_0_75V; } #ifdef __SAVE_POWER_MODE__ ldo_volt = PMU_VDIG_0_75V; dcdc_volt = PMU_DCDC_DIG_0_75V; #endif } #if defined(PROGRAMMER) || defined(__BES_OTA_MODE__) && !defined(PMU_FULL_INIT) // Try to keep the same vcore voltage as ROM (hardware default) if (ldo_volt < PMU_VDIG_0_9V) { ldo_volt = PMU_VDIG_0_9V; } if (dcdc_volt < PMU_DCDC_DIG_0_9V) { dcdc_volt = PMU_DCDC_DIG_0_9V; } #endif #if defined(MTEST_ENABLED) && defined(MTEST_VOLT) #ifdef DIG_DCDC_MODE dcdc_volt = MTEST_VOLT; #else ldo_volt = MTEST_VOLT; #endif #endif if (ldo) { *ldo = ldo_volt; } if (dcdc) { *dcdc = dcdc_volt; } } static void pmu_dig_set_volt(int mode_change, enum PMU_POWER_MODE_T mode) { uint32_t lock; uint16_t dcdc_volt, old_act_dcdc, old_lp_dcdc; uint16_t ldo_volt, old_act_ldo, old_lp_ldo; uint16_t ldo_real, dcdc_real; bool volt_inc = false; lock = int_lock(); if (mode == PMU_POWER_MODE_NONE) { mode = pmu_power_mode; } pmu_dig_get_target_volt(&ldo_volt, &dcdc_volt); pmu_module_get_volt(PMU_DIG, &old_lp_ldo, &old_act_ldo); pmu_dcdc_dig_get_volt(&old_act_dcdc, &old_lp_dcdc); if (mode_change) { // Both DCDC and LDO might have been enabled ldo_real = (old_act_ldo - PMU_VDIG_0_4V) / 0x2; dcdc_real = (old_act_dcdc - PMU_DCDC_DIG_0_4V) / 0x10; if (dcdc_real < ldo_real) { dcdc_real = ldo_real; } ldo_real = PMU_VDIG_0_4V + dcdc_real * 0x2; dcdc_real = PMU_DCDC_DIG_0_4V + dcdc_real * 0x10; // Set the voltage to current real voltage if (old_act_ldo < ldo_real) { old_act_ldo = ldo_real; old_lp_ldo = dig_lp_ldo; pmu_module_set_volt(PMU_DIG, old_lp_ldo, old_act_ldo); } if (old_act_dcdc < dcdc_real) { old_act_dcdc = dcdc_real; old_lp_dcdc = dig_lp_dcdc; pmu_dcdc_dig_set_volt(old_act_dcdc, old_lp_dcdc); } } if (mode_change || mode == PMU_POWER_MODE_DIG_DCDC) { if (old_act_dcdc < dcdc_volt) { volt_inc = true; while (old_act_dcdc++ < dcdc_volt) { pmu_dcdc_dig_set_volt(old_act_dcdc, dig_lp_dcdc); } } else if (old_act_dcdc != dcdc_volt || old_lp_dcdc != dig_lp_dcdc) { pmu_dcdc_dig_set_volt(dcdc_volt, dig_lp_dcdc); } } if (mode_change || mode != PMU_POWER_MODE_DIG_DCDC) { if (old_act_ldo < ldo_volt) { volt_inc = true; } pmu_module_ramp_volt(PMU_DIG, dig_lp_ldo, ldo_volt); } if (mode_change == 0) { // Update the voltage of the other mode if (mode == PMU_POWER_MODE_DIG_DCDC) { pmu_module_set_volt(PMU_DIG, dig_lp_ldo, ldo_volt); } else { pmu_dcdc_dig_set_volt(dcdc_volt, dig_lp_dcdc); } } if (volt_inc) { hal_sys_timer_delay_us(PMU_VCORE_STABLE_TIME_US); } int_unlock(lock); } static void pmu_ldo_mode_en(void) { unsigned short val; // Enable vana ldo pmu_module_config(PMU_ANA, PMU_AUTO_MODE, PMU_LDO_ON, PMU_LP_MODE_ON, PMU_DSLEEP_MODE_ON); // Enable vcore ldo pmu_module_config(PMU_DIG, PMU_AUTO_MODE, PMU_LDO_ON, PMU_LP_MODE_ON, PMU_DSLEEP_MODE_ON); pmu_ana_set_volt(1, PMU_POWER_MODE_LDO); pmu_dig_set_volt(1, PMU_POWER_MODE_LDO); hal_sys_timer_delay_us(PMU_LDO_PU_STABLE_TIME_US); // Disable vcore dcdc pmu_read(PMU_REG_DCDC_DIG_EN, &val); val = (val & ~REG_PU_DCDC1) | REG_PU_DCDC1_DR; pmu_write(PMU_REG_DCDC_DIG_EN, val); // Disable vana dcdc pmu_read(PMU_REG_DCDC_ANA_EN, &val); val = (val & ~REG_PU_DCDC2) | REG_PU_DCDC2_DR; pmu_write(PMU_REG_DCDC_ANA_EN, val); } static void pmu_dcdc_ana_mode_en(void) { unsigned short val; if (pmu_power_mode == PMU_POWER_MODE_DIG_DCDC) { // Enable vcore ldo pmu_module_config(PMU_DIG, PMU_AUTO_MODE, PMU_LDO_ON, PMU_LP_MODE_ON, PMU_DSLEEP_MODE_ON); pmu_ana_set_volt(1, PMU_POWER_MODE_ANA_DCDC); pmu_dig_set_volt(1, PMU_POWER_MODE_ANA_DCDC); hal_sys_timer_delay_us(PMU_LDO_PU_STABLE_TIME_US); // Disable vcore dcdc pmu_read(PMU_REG_DCDC_DIG_EN, &val); val = (val & ~REG_PU_DCDC1) | REG_PU_DCDC1_DR; pmu_write(PMU_REG_DCDC_DIG_EN, val); } else { pmu_read(PMU_REG_DCDC_ANA_CFG_19, &val); val |= DCDC2_REG_BYPASS; pmu_write(PMU_REG_DCDC_ANA_CFG_19, val); // Enable vana dcdc pmu_read(PMU_REG_DCDC_ANA_EN, &val); #ifdef DCDC_ULP_LP_ON val = (val & ~REG_DCDC2_ULP_MODE_NORMAL) | REG_DCDC2_ULP_MODE_DSLEEP | REG_PU_DCDC2_DR | REG_PU_DCDC2; #else val = (val & ~REG_DCDC2_ULP_MODE_NORMAL) | REG_PU_DCDC2_DR | REG_PU_DCDC2; #endif pmu_write(PMU_REG_DCDC_ANA_EN, val); pmu_ana_set_volt(1, PMU_POWER_MODE_ANA_DCDC); pmu_dig_set_volt(1, PMU_POWER_MODE_ANA_DCDC); hal_sys_timer_delay_us(PMU_DCDC_PU_STABLE_TIME_US); // Disable vana ldo pmu_module_config(PMU_ANA, PMU_MANUAL_MODE, PMU_LDO_OFF, PMU_LP_MODE_ON, PMU_DSLEEP_MODE_OFF); pmu_read(PMU_REG_DCDC_ANA_CFG_19, &val); val &= ~DCDC2_REG_BYPASS; pmu_write(PMU_REG_DCDC_ANA_CFG_19, val); } } static void pmu_dcdc_dual_mode_en(void) { unsigned short val; pmu_read(PMU_REG_DCDC_ANA_CFG_19, &val); val |= DCDC2_REG_BYPASS; pmu_write(PMU_REG_DCDC_ANA_CFG_19, val); pmu_read(PMU_REG_DCDC_DIG_CFG_36, &val); val |= DCDC1_REG_BYPASS; pmu_write(PMU_REG_DCDC_DIG_CFG_36, val); // Enable vana dcdc pmu_read(PMU_REG_DCDC_ANA_EN, &val); #ifdef DCDC_ULP_LP_ON val = (val & ~REG_DCDC2_ULP_MODE_NORMAL) | REG_DCDC2_ULP_MODE_DSLEEP | REG_PU_DCDC2_DR | REG_PU_DCDC2; #else val = (val & ~(REG_DCDC2_ULP_MODE_NORMAL | REG_DCDC2_ULP_MODE_DSLEEP)) | REG_PU_DCDC2_DR | REG_PU_DCDC2; #endif pmu_write(PMU_REG_DCDC_ANA_EN, val); // Enable vcore dcdc pmu_read(PMU_REG_DCDC_DIG_EN, &val); #ifdef DCDC_ULP_LP_ON val = (val & ~REG_DCDC1_ULP_MODE_NORMAL) | REG_DCDC1_ULP_MODE_DSLEEP | REG_PU_DCDC1_DR | REG_PU_DCDC1; #else val = (val & ~(REG_DCDC1_ULP_MODE_NORMAL | REG_DCDC1_ULP_MODE_DSLEEP)) | REG_PU_DCDC1_DR | REG_PU_DCDC1; #endif pmu_write(PMU_REG_DCDC_DIG_EN, val); pmu_ana_set_volt(1, PMU_POWER_MODE_DIG_DCDC); pmu_dig_set_volt(1, PMU_POWER_MODE_DIG_DCDC); hal_sys_timer_delay_us(PMU_DCDC_PU_STABLE_TIME_US); // Disable vana ldo pmu_module_config(PMU_ANA, PMU_MANUAL_MODE, PMU_LDO_OFF, PMU_LP_MODE_ON, PMU_DSLEEP_MODE_OFF); // Disable vcore ldo pmu_module_config(PMU_DIG, PMU_MANUAL_MODE, PMU_LDO_OFF, PMU_LP_MODE_ON, PMU_DSLEEP_MODE_OFF); pmu_read(PMU_REG_DCDC_ANA_CFG_19, &val); val &= ~DCDC2_REG_BYPASS; pmu_write(PMU_REG_DCDC_ANA_CFG_19, val); pmu_read(PMU_REG_DCDC_DIG_CFG_36, &val); val &= ~DCDC1_REG_BYPASS; pmu_write(PMU_REG_DCDC_DIG_CFG_36, val); } void pmu_mode_change(enum PMU_POWER_MODE_T mode) { uint32_t lock; if (pmu_power_mode == mode || mode == PMU_POWER_MODE_NONE) { return; } lock = int_lock(); if (mode == PMU_POWER_MODE_ANA_DCDC) { pmu_dcdc_ana_mode_en(); } else if (mode == PMU_POWER_MODE_DIG_DCDC) { pmu_dcdc_dual_mode_en(); } else if (mode == PMU_POWER_MODE_LDO) { pmu_ldo_mode_en(); } pmu_power_mode = mode; int_unlock(lock); } void pmu_sleep_en(unsigned char sleep_en) { unsigned short val; pmu_read(PMU_REG_SLEEP_CFG, &val); if (sleep_en) { val |= SLEEP_ALLOW; } else { val &= ~SLEEP_ALLOW; } pmu_write(PMU_REG_SLEEP_CFG, val); } #if defined(PMU_INIT) || (!defined(PROGRAMMER)) static uint32_t pmu_vcodec_mv_to_val(uint16_t mv) { uint32_t val; #ifdef VHPPA2VCODEC if (mv == 1900) { val = PMU_HPPA2CODEC_1_9V; } else if (mv >= 1950) { val = PMU_HPPA2CODEC_1_95V; } else { val = PMU_HPPA2CODEC_1_7V; } #else if (mv == 1900) { val = PMU_CODEC_1_9V; } else if (mv >= 1950) { val = PMU_CODEC_1_9V; } else { val = PMU_CODEC_1_7V; } #endif return val; } static uint32_t pmu_ldo_hppa_mv_to_val(uint16_t mv) { uint32_t val; if (mv == 1600) { val = PMU_VHPPA_1_6V; } else if (mv == 1700) { val = PMU_VHPPA_1_7V; } else if (mv >= 1900) { val = PMU_VHPPA_1_9V; } else { val = PMU_VHPPA_1_8V; } return val; } static void POSSIBLY_UNUSED pmu_ldo_hppa_get_volt(unsigned short *normal_vp, unsigned short *dsleep_vp) { uint16_t val; pmu_read(PMU_REG_HPPA_LDO_EN, &val); val = GET_BITFIELD(val, REG_RES_SEL_VHPPA); if (normal_vp) { *normal_vp = val; } if (dsleep_vp) { *dsleep_vp = val; } } static void pmu_ldo_hppa_set_volt(unsigned short normal_v, unsigned short dsleep_v) { uint16_t val; pmu_read(PMU_REG_HPPA_LDO_EN, &val); val = SET_BITFIELD(val, REG_RES_SEL_VHPPA, normal_v); pmu_write(PMU_REG_HPPA_LDO_EN, val); } static void pmu_ldo_hppa_en(int enable) { uint16_t val; pmu_read(PMU_REG_HPPA_LDO_EN, &val); if (enable) { val |= (REG_PU_LDO_VHPPA_DSLEEP | REG_PU_LDO_VHPPA_EN); } else { val &= ~(REG_PU_LDO_VHPPA_DSLEEP | REG_PU_LDO_VHPPA_EN); } pmu_write(PMU_REG_HPPA_LDO_EN, val); } #ifndef HPPA_LDO_ON static uint32_t pmu_dcdc_hppa_mv_to_val(uint16_t mv) { uint32_t val; if (mv == 1600) { val = PMU_DCDC_HPPA_1_6V; } else if (mv == 1700) { val = PMU_DCDC_HPPA_1_7V; } else if (mv == 1900) { val = PMU_DCDC_HPPA_1_9V; } else if (mv >= 1950) { val = PMU_DCDC_HPPA_1_95V; } else { val = PMU_DCDC_HPPA_1_8V; } return val; } static void pmu_dcdc_hppa_get_volt(unsigned short *normal_vp, unsigned short *dsleep_vp) { unsigned short val; pmu_read(PMU_REG_DCDC_HPPA_VOLT, &val); if (normal_vp) { *normal_vp = GET_BITFIELD(val, REG_DCDC3_VBIT_NORMAL); } if (dsleep_vp) { *dsleep_vp = GET_BITFIELD(val, REG_DCDC3_VBIT_DSLEEP); } #ifdef PMU_DCDC_CALIB if (normal_vp) { *normal_vp = pmu_reg_val_add(*normal_vp, -pmu_dcdc_hppa_comp, MAX_DCDC3_VBIT_VAL); } if (dsleep_vp) { *dsleep_vp = pmu_reg_val_add(*dsleep_vp, -pmu_dcdc_hppa_comp, MAX_DCDC3_VBIT_VAL); } #endif } static void pmu_dcdc_hppa_set_volt(unsigned short normal_v, unsigned short dsleep_v) { unsigned short val; #ifdef PMU_DCDC_CALIB normal_v = pmu_reg_val_add(normal_v, pmu_dcdc_hppa_comp, MAX_DCDC3_VBIT_VAL); dsleep_v = pmu_reg_val_add(dsleep_v, pmu_dcdc_hppa_comp, MAX_DCDC3_VBIT_VAL); #endif pmu_read(PMU_REG_DCDC_HPPA_VOLT, &val); val &= ~REG_DCDC3_VBIT_DSLEEP_MASK; val &= ~REG_DCDC3_VBIT_NORMAL_MASK; val |= REG_DCDC3_VBIT_DSLEEP(dsleep_v); val |= REG_DCDC3_VBIT_NORMAL(normal_v); pmu_write(PMU_REG_DCDC_HPPA_VOLT, val); if (normal_v > dsleep_v) { dcdc_ramp_map |= REG_DCDC3_RAMP_EN; } else { dcdc_ramp_map &= ~REG_DCDC3_RAMP_EN; } } static void pmu_dcdc_hppa_en(int enable) { uint16_t val; if (enable) { pmu_read(PMU_REG_DCDC_HPPA_CFG_1D, &val); val |= DCDC3_REG_BYPASS; pmu_write(PMU_REG_DCDC_HPPA_CFG_1D, val); } pmu_read(PMU_REG_DCDC_HPPA_EN, &val); if (enable) { #ifdef DCDC_ULP_LP_ON val = (val & ~REG_DCDC3_ULP_MODE_NORMAL) | REG_DCDC3_ULP_MODE_DSLEEP | REG_PU_DCDC3_DR | REG_PU_DCDC3; #else val = (val & ~REG_DCDC3_ULP_MODE_NORMAL) | REG_PU_DCDC3_DR | REG_PU_DCDC3; #endif } else { val = (val & ~(REG_DCDC3_ULP_MODE_NORMAL | REG_PU_DCDC3)) | REG_PU_DCDC3_DR; } pmu_write(PMU_REG_DCDC_HPPA_EN, val); if (enable) { hal_sys_timer_delay_us(PMU_DCDC_PU_STABLE_TIME_US); pmu_read(PMU_REG_DCDC_HPPA_CFG_1D, &val); val &= ~DCDC3_REG_BYPASS; pmu_write(PMU_REG_DCDC_HPPA_CFG_1D, val); } } #endif static uint32_t pmu_vhppa_mv_to_val(uint16_t mv) { #ifdef HPPA_LDO_ON return pmu_ldo_hppa_mv_to_val(mv); #else return pmu_dcdc_hppa_mv_to_val(mv); #endif } static void POSSIBLY_UNUSED pmu_hppa_get_volt(unsigned short *normal_vp, unsigned short *dsleep_vp) { #ifdef HPPA_LDO_ON pmu_ldo_hppa_get_volt(normal_vp, dsleep_vp); #else pmu_dcdc_hppa_get_volt(normal_vp, dsleep_vp); #endif } static void pmu_hppa_set_volt(unsigned short normal_v, unsigned short dsleep_v) { #ifdef HPPA_LDO_ON pmu_ldo_hppa_set_volt(normal_v, dsleep_v); #else pmu_dcdc_hppa_set_volt(normal_v, dsleep_v); #endif } static void pmu_hppa_en(int enable) { #ifdef HPPA_LDO_ON pmu_ldo_hppa_en(enable); #else pmu_dcdc_hppa_en(enable); #endif } static void pmu_hppa_dcdc_to_ldo(void) { #ifndef HPPA_LDO_ON uint16_t val; uint16_t act_volt; pmu_ldo_hppa_en(true); val = pmu_dcdc_hppa_mv_to_val(vhppa_mv); pmu_dcdc_hppa_get_volt(&act_volt, NULL); if (val < act_volt) { val = pmu_ldo_hppa_mv_to_val(HPPA_RAMP_UP_VOLT_MV); } else { val = pmu_ldo_hppa_mv_to_val(vhppa_mv); } pmu_ldo_hppa_set_volt(val, val); hal_sys_timer_delay_us(PMU_LDO_PU_STABLE_TIME_US); #endif } static void BOOT_TEXT_FLASH_LOC pmu_dig_init_volt(void) { uint16_t ldo_volt; uint16_t val; pmu_dig_get_target_volt(&ldo_volt, NULL); pmu_read(PMU_REG_DIG_CFG, &val); if (GET_BITFIELD(val, LDO_DIG_VBIT_NORMAL) < ldo_volt) { val = SET_BITFIELD(val, LDO_DIG_VBIT_NORMAL, ldo_volt); pmu_write(PMU_REG_DIG_CFG, val); } } int pmu_codec_volt_ramp_up(void) { #ifndef VMEM_ON unsigned short normal, dsleep; unsigned short target; const unsigned short step = #ifdef HPPA_LDO_ON 1; #else 8; #endif if (vcodec_off) { target = pmu_vhppa_mv_to_val(HPPA_RAMP_UP_VOLT_MV); pmu_hppa_get_volt(&normal, &dsleep); if (normal < target) { if (normal + step < target) { normal += step; } else { normal = target; } pmu_hppa_set_volt(normal, dsleep); return 1; } } return 0; #endif } int pmu_codec_volt_ramp_down(void) { #ifndef VMEM_ON unsigned short normal, dsleep; unsigned short target; const unsigned short step = #ifdef HPPA_LDO_ON 1; #else 8; #endif if (vcodec_off) { target = pmu_vhppa_mv_to_val(vhppa_mv); pmu_hppa_get_volt(&normal, &dsleep); if (normal > target) { if (normal - step > target) { normal -= step; } else { normal = target; } pmu_hppa_set_volt(normal, dsleep); return 1; } } return 0; #endif } #endif int BOOT_TEXT_FLASH_LOC pmu_open(void) { #if defined(PMU_INIT) || (!defined(PROGRAMMER)) uint16_t val; enum PMU_POWER_MODE_T mode; enum PMU_MODUAL_T codec; ASSERT(!vcodec_off || vcodec_mv == vhppa_mv, "Invalid vcodec/vhppa cfg: vcodec_off=%d vcodec_mv=%u vhppa_mv=%u", vcodec_off, vcodec_mv, vhppa_mv); ASSERT(vcodec_mv == 1600 || vcodec_mv == 1700 || vcodec_mv == 1800 || vcodec_mv == 1900 || vcodec_mv == 1950, "Invalid vcodec cfg: vcodec_mv=%u", vcodec_mv); ASSERT(vhppa_mv == 1600 || vhppa_mv == 1700 || vhppa_mv == 1800 || vhppa_mv == 1900 || vhppa_mv == 1950, "Invalid vhppa cfg: vhppa_mv=%u", vhppa_mv); // Disable and clear all PMU irqs by default pmu_write(PMU_REG_INT_MASK, 0); pmu_write(PMU_REG_INT_EN, 0); // PMU irqs cannot be cleared by PMU soft reset pmu_read(PMU_REG_CHARGER_STATUS, &val); pmu_write(PMU_REG_CHARGER_STATUS, val); pmu_read(PMU_REG_INT_STATUS, &val); pmu_write(PMU_REG_INT_CLR, val); pmu_read(PMU_REG_POWER_KEY_CFG, &val); // Allow PMU to sleep when power key is pressed val &= ~POWERKEY_WAKEUP_OSC_EN; // Increase big bandgap startup time (stable time) val = SET_BITFIELD(val, REG_VCORE_SSTIME_MODE, 2); pmu_write(PMU_REG_POWER_KEY_CFG, val); #ifdef FORCE_BIG_BANDGAP // Force big bandgap pmu_read(PMU_REG_INT_EN, &val); val |= REG_BG_SLEEP_MSK; pmu_write(PMU_REG_INT_EN, val); pmu_read(PMU_REG_BIAS_CFG, &val); val |= BG_CONSTANT_GM_BIAS_DR | BG_CONSTANT_GM_BIAS_REG; val |= BG_CORE_EN_DR | BG_CORE_EN_REG; pmu_write(PMU_REG_BIAS_CFG, val); hal_sys_timer_delay_us(20); val |= BG_VBG_SEL_DR | BG_VBG_SEL_REG; pmu_write(PMU_REG_BIAS_CFG, val); #else // Allow low power bandgap pmu_read(PMU_REG_BIAS_CFG, &val); val &= ~BG_VBG_SEL_DR; pmu_write(PMU_REG_BIAS_CFG, val); #endif // Init DCDC settings part 1 if (pmu_metal_id >= HAL_CHIP_METAL_ID_1) { pmu_write(PMU_REG_DCDC_ANA_CFG_16, 0x8E0F); pmu_write(PMU_REG_DCDC_ANA_CFG_17, 0x0211); pmu_write(PMU_REG_DCDC_ANA_CFG_18, 0xA484); pmu_write(PMU_REG_DCDC_ANA_CFG_19, 0xE210); pmu_write(PMU_REG_DCDC_HPPA_CFG_1A, 0x8E0F); pmu_write(PMU_REG_DCDC_HPPA_CFG_1B, 0x0211); pmu_write(PMU_REG_DCDC_HPPA_CFG_1C, 0xA484); pmu_write(PMU_REG_DCDC_HPPA_CFG_1D, 0xE210); pmu_write(PMU_REG_DCDC_DIG_CFG_33, 0x8E0F); pmu_write(PMU_REG_DCDC_DIG_CFG_34, 0x0211); pmu_write(PMU_REG_DCDC_DIG_CFG_35, 0xA484); pmu_write(PMU_REG_DCDC_DIG_CFG_36, 0xE210); pmu_read(PMU_REG_MIC_LDO_EN, &val); val |= DCDC1_OFFSET_CURRENT_EN; pmu_write(PMU_REG_MIC_LDO_EN, val); pmu_read(PMU_REG_DCDC1_OFFSET, &val); val = SET_BITFIELD(val, DCDC1_OFFSET_BIT, 0xE0); pmu_write(PMU_REG_DCDC1_OFFSET, val); } #ifdef PMU_DCDC_CALIB pmu_get_dcdc_calib_value(); #endif #ifndef NO_SLEEP pmu_sleep_en(true); #endif // Disable vbat2vcore pmu_module_config(PMU_BAT2DIG, PMU_MANUAL_MODE, PMU_LDO_OFF, PMU_LP_MODE_ON, PMU_DSLEEP_MODE_OFF); #ifdef LBRT // Enable vbuck2ana pmu_module_config(PMU_BUCK2ANA, PMU_MANUAL_MODE, PMU_LDO_ON, PMU_LP_MODE_ON, PMU_DSLEEP_MODE_ON); pmu_module_set_volt(PMU_BUCK2ANA, PMU_VBUCK2ANA_1_3V, PMU_VBUCK2ANA_1_3V); // Disable vana dcdc pmu_read(PMU_REG_HPPA_LDO_EN, &val); val &= ~REG_BYPASS_VBUCK2ANA; pmu_write(PMU_REG_HPPA_LDO_EN, val); #else // Disable vbuck2ana pmu_module_config(PMU_BUCK2ANA, PMU_MANUAL_MODE, PMU_LDO_OFF, PMU_LP_MODE_ON, PMU_DSLEEP_MODE_OFF); #endif // Disable vhppa ldo pmu_ldo_hppa_en(false); #ifdef VMEM_ON pmu_module_config(PMU_MEM, PMU_MANUAL_MODE, PMU_LDO_ON, PMU_LP_MODE_ON, PMU_DSLEEP_MODE_ON); pmu_module_ramp_volt(PMU_MEM, PMU_VMEM_1_8V, PMU_VMEM_1_8V); pmu_hppa_en(false); // VHPPA will be enabled/disabled dynamically. Enable soft start. pmu_read(PMU_REG_DCDC_HPPA_CFG_1D, &val); val |= DCDC3_SOFT_START_EN; pmu_write(PMU_REG_DCDC_HPPA_CFG_1D, val); #else // vmem and vhppa is shorted -- enable vhppa dcdc and disable vmem ldo val = pmu_vhppa_mv_to_val(1800); pmu_hppa_set_volt(val, val); pmu_hppa_en(true); pmu_module_config(PMU_MEM, PMU_MANUAL_MODE, PMU_LDO_OFF, PMU_LP_MODE_ON, PMU_DSLEEP_MODE_OFF); #endif pmu_module_config(PMU_GP, PMU_MANUAL_MODE, PMU_LDO_OFF, PMU_LP_MODE_ON, PMU_DSLEEP_MODE_OFF); #ifndef PROGRAMMER #ifdef VUSB_ON pmu_vusb_req |= PMU_VUSB_REQ_INIT; #endif // Disable usbphy power, and vusb if possible pmu_usb_config(PMU_USB_CONFIG_TYPE_NONE); #ifdef VUSB_ON pmu_vusb_req &= ~PMU_VUSB_REQ_INIT; #endif #endif #ifdef __BEST_FLASH_VIA_ANA__ pmu_module_config(PMU_IO, PMU_AUTO_MODE, PMU_LDO_ON, PMU_LP_MODE_ON, PMU_DSLEEP_MODE_OFF); #else pmu_module_config(PMU_IO, PMU_AUTO_MODE, PMU_LDO_ON, PMU_LP_MODE_ON, PMU_DSLEEP_MODE_ON); #endif pmu_module_ramp_volt(PMU_IO, vio_lp, vio_act_normal); // Disable vcodec pmu_module_config(PMU_CODEC, PMU_MANUAL_MODE, PMU_LDO_OFF, PMU_LP_MODE_ON, PMU_DSLEEP_MODE_OFF); // Disable vhppa2vcodec pmu_module_config(PMU_HPPA2CODEC, PMU_MANUAL_MODE, PMU_LDO_OFF, PMU_LP_MODE_ON, PMU_DSLEEP_MODE_OFF); #ifdef VHPPA2VCODEC codec = PMU_HPPA2CODEC; #else codec = PMU_CODEC; #endif val = pmu_vcodec_mv_to_val(vcodec_mv); // No need to ramp because the LDO is disabled (and its soft start is enabled) pmu_module_set_volt(codec, val, val); val = pmu_vhppa_mv_to_val(vhppa_mv); #ifdef VMEM_ON // No need to ramp because VHPPA is disabled (and its soft start is enabled) pmu_hppa_set_volt(val, val); #else uint16_t old_act_volt; uint16_t old_lp_volt; // VHPPA is on. Ramp is needed. pmu_hppa_get_volt(&old_act_volt, &old_lp_volt); if (old_act_volt < val) { while (old_act_volt++ < val) { pmu_hppa_set_volt(old_act_volt, val); } } else if (old_act_volt != val || old_lp_volt != val) { pmu_hppa_set_volt(val, val); } #endif #ifdef DIG_DCDC_MODE mode = PMU_POWER_MODE_DIG_DCDC; #elif defined(ANA_DCDC_MODE) mode = PMU_POWER_MODE_ANA_DCDC; #else // LDO_MODE mode = PMU_POWER_MODE_LDO; #endif pmu_mode_change(mode); #ifdef RTC_ENABLE pmu_rtc_restore_context(); #endif #if defined(MCU_HIGH_PERFORMANCE_MODE) // Increase bbpll voltage pmu_write(0xA0, 0x3FE8); // div=2 (bit14=0) pmu_write(0xA1, 0xF918); pmu_high_performance_mode_enable(true); #endif // Init DCDC settings part 2 if (pmu_metal_id >= HAL_CHIP_METAL_ID_1) { hal_sys_timer_delay_us(5000); pmu_write(PMU_REG_DCDC_ANA_CFG_16, 0x8E1F); pmu_write(PMU_REG_DCDC_HPPA_CFG_1A, 0x8E1F); pmu_write(PMU_REG_DCDC_DIG_CFG_33, 0x8E1F); } #endif // PMU_INIT || (!PROGRAMMER) return 0; } void pmu_codec_vad_save_power(void) { uint16_t val; // reduce ldo power supply pmu_read(PMU_REG_DCDC_RAMP_EN, &val); val &= ~REG_MIC_BIASA_IX2; pmu_write(PMU_REG_DCDC_RAMP_EN, val); // enable dcdc1 low power mode pmu_read(PMU_REG_DCDC_DIG_EN, &val); val |= REG_DCDC1_ULP_MODE_NORMAL; pmu_write(PMU_REG_DCDC_DIG_EN, val); // enable dcdc2 low power mode pmu_read(PMU_REG_DCDC_ANA_EN, &val); val |= REG_DCDC2_ULP_MODE_NORMAL; pmu_write(PMU_REG_DCDC_ANA_EN, val); // enable dcdc3 low power mode pmu_read(PMU_REG_DCDC_HPPA_EN, &val); val |= REG_DCDC3_ULP_MODE_NORMAL; pmu_write(PMU_REG_DCDC_HPPA_EN, val); } void pmu_codec_vad_restore_power(void) { uint16_t val; // restore ldo power supply pmu_read(PMU_REG_DCDC_RAMP_EN, &val); val |= REG_MIC_BIASA_IX2; pmu_write(PMU_REG_DCDC_RAMP_EN, val); // disable dcdc1 low power mode pmu_read(PMU_REG_DCDC_DIG_EN, &val); val &= ~REG_DCDC1_ULP_MODE_NORMAL; pmu_write(PMU_REG_DCDC_DIG_EN, val); // disable dcdc2 low power mode pmu_read(PMU_REG_DCDC_ANA_EN, &val); val &= ~REG_DCDC2_ULP_MODE_NORMAL; pmu_write(PMU_REG_DCDC_ANA_EN, val); // disable dcdc3 low power mode pmu_read(PMU_REG_DCDC_HPPA_EN, &val); val &= ~REG_DCDC3_ULP_MODE_NORMAL; pmu_write(PMU_REG_DCDC_HPPA_EN, val); } void pmu_sleep(void) { uint16_t val; if (dcdc_ramp_map) { // Enable DCDC ramp pmu_read(PMU_REG_DCDC_RAMP_EN, &val); val |= dcdc_ramp_map; pmu_write(PMU_REG_DCDC_RAMP_EN, val); } return; } void pmu_wakeup(void) { uint16_t val; if (dcdc_ramp_map) { // Disable DCDC ramp so that s/w can control the voltages freely pmu_read(PMU_REG_DCDC_RAMP_EN, &val); val &= ~dcdc_ramp_map; pmu_write(PMU_REG_DCDC_RAMP_EN, val); } return; } void pmu_codec_config(int enable) { enum PMU_MODUAL_T codec; #ifdef VHPPA2VCODEC codec = PMU_HPPA2CODEC; #else codec = PMU_CODEC; #endif if (vcodec_off) { #ifdef VMEM_ON pmu_hppa_en(enable); #endif } else { if (enable) { pmu_module_config(codec, PMU_MANUAL_MODE, PMU_LDO_ON, PMU_LP_MODE_ON, PMU_DSLEEP_MODE_OFF); } else { pmu_module_config(codec, PMU_MANUAL_MODE, PMU_LDO_OFF, PMU_LP_MODE_ON, PMU_DSLEEP_MODE_OFF); } } } void pmu_codec_hppa_enable(int enable) { if (!vcodec_off) { #ifdef VMEM_ON pmu_hppa_en(enable); #endif } } static uint32_t mic_bias_remap(uint32_t map) { // The vmic1 pin has been replaced by the vmic3 pin in package bonding for all // chip models since ver-B if (hal_get_chip_metal_id() >= HAL_CHIP_METAL_ID_1) { if (map & AUD_VMIC_MAP_VMIC1) { map = (map & ~AUD_VMIC_MAP_VMIC1) | AUD_VMIC_MAP_VMIC3; } } return map; } void pmu_codec_mic_bias_enable(uint32_t map) { uint16_t val; int i; enum PMU_REG_T bias_reg; uint16_t ldo_en; uint8_t volt; uint8_t res; static const uint16_t ldo_mask = REG_MIC_LDOA_EN | REG_MIC_LDOB_EN | REG_MIC_LDOC_EN | REG_MIC_LDOD_EN | REG_MIC_LDOE_EN; map = mic_bias_remap(map); #ifdef DIGMIC_HIGH_VOLT volt = PMU_VMIC_3_3V; #else volt = PMU_VMIC_2_2V; #endif if (vcodec_mv < 1900) { if (volt >= 0x1F) { volt = 0x1F; } else { volt += 1; } } res = PMU_VMIC_RES_3_3V; ldo_en = 0; for (i = 0; i < MAX_ANA_MIC_CH_NUM; i++) { if (i == MAX_ANA_MIC_CH_NUM - 1) { bias_reg = PMU_REG_MIC_BIAS_E; } else { bias_reg = PMU_REG_MIC_BIAS_A + i; } pmu_read(bias_reg, &val); if (map & (AUD_VMIC_MAP_VMIC1 << i)) { ldo_en |= (REG_MIC_LDOA_EN >> i); val = (val & ~(REG_MIC_BIASA_VSEL_MASK | REG_MIC_LDOA_RES_MASK)) | REG_MIC_BIASA_VSEL(volt) | REG_MIC_LDOA_RES(res) | REG_MIC_BIASA_EN; } else { val &= ~REG_MIC_BIASA_EN; } pmu_write(bias_reg, val); } pmu_read(PMU_REG_MIC_LDO_EN, &val); val = (val & ~ldo_mask) | ldo_en; pmu_write(PMU_REG_MIC_LDO_EN, val); } void pmu_codec_mic_bias_lowpower_mode(uint32_t map) { uint16_t val; map = mic_bias_remap(map); if (map & AUD_VMIC_MAP_VMIC3) { pmu_read(PMU_REG_DCDC_RAMP_EN, &val); val &= ~REG_MIC_BIASC_IX2; pmu_write(PMU_REG_DCDC_RAMP_EN, val); pmu_read(PMU_REG_MIC_BIAS_C, &val); val = SET_BITFIELD(val, REG_MIC_BIASC_CHANSEL, 0x3); pmu_write(PMU_REG_MIC_BIAS_C, val); } } void pmu_codec_adc_pre_start(void) {} void pmu_codec_adc_post_start(void (*delay_ms)(uint32_t)) {} void pmu_codec_dac_pre_start(void) {} void pmu_codec_dac_post_start(void (*delay_ms)(uint32_t)) {} SRAM_TEXT_LOC void pmu_flash_write_config(void) { #ifdef FLASH_WRITE_AT_HIGH_VCORE uint32_t lock; if (pmu_vcore_req & PMU_VCORE_FLASH_WRITE_ENABLED) { return; } #if defined(__PMU_VIO_DYNAMIC_CTRL_MODE__) pmu_viorise_req(PMU_VIORISE_REQ_USER_FLASH, true); #endif lock = int_lock(); pmu_vcore_req |= PMU_VCORE_FLASH_WRITE_ENABLED; int_unlock(lock); pmu_dig_set_volt(0, PMU_POWER_MODE_NONE); #endif } SRAM_TEXT_LOC void pmu_flash_read_config(void) { #ifdef FLASH_WRITE_AT_HIGH_VCORE uint32_t lock; if ((pmu_vcore_req & PMU_VCORE_FLASH_WRITE_ENABLED) == 0) { return; } lock = int_lock(); pmu_vcore_req &= ~PMU_VCORE_FLASH_WRITE_ENABLED; int_unlock(lock); pmu_dig_set_volt(0, PMU_POWER_MODE_NONE); #if defined(__PMU_VIO_DYNAMIC_CTRL_MODE__) pmu_viorise_req(PMU_VIORISE_REQ_USER_FLASH, false); #endif #endif } void BOOT_TEXT_FLASH_LOC pmu_flash_freq_config(uint32_t freq) { #if defined(PMU_INIT) || (!defined(PROGRAMMER)) uint32_t lock; lock = int_lock(); if (freq > 52000000) { // The real max freq is 120M // pmu_vcore_req |= PMU_VCORE_FLASH_FREQ_HIGH; } else { pmu_vcore_req &= ~PMU_VCORE_FLASH_FREQ_HIGH; } int_unlock(lock); if (pmu_power_mode == PMU_POWER_MODE_NONE) { // PMU not init yet pmu_dig_init_volt(); return; } pmu_dig_set_volt(0, PMU_POWER_MODE_NONE); #endif } void BOOT_TEXT_FLASH_LOC pmu_psram_freq_config(uint32_t freq) { #if defined(PMU_INIT) || (!defined(PROGRAMMER)) uint32_t lock; lock = int_lock(); if (freq > 52000000) { pmu_vcore_req |= PMU_VCORE_PSRAM_FREQ_HIGH; } else { pmu_vcore_req &= ~PMU_VCORE_PSRAM_FREQ_HIGH; } int_unlock(lock); if (pmu_power_mode == PMU_POWER_MODE_NONE) { // PMU not init yet pmu_dig_init_volt(); return; } pmu_dig_set_volt(0, PMU_POWER_MODE_NONE); #endif } void pmu_anc_config(int enable) {} void pmu_fir_high_speed_config(int enable) {} void pmu_iir_freq_config(uint32_t freq) {} void pmu_rs_freq_config(uint32_t freq) { uint32_t lock; lock = int_lock(); if (freq >= 60000000) { pmu_vcore_req |= PMU_VCORE_RS_FREQ_HIGH; } else { pmu_vcore_req &= ~PMU_VCORE_RS_FREQ_HIGH; } int_unlock(lock); pmu_dig_set_volt(0, PMU_POWER_MODE_NONE); } void BOOT_TEXT_SRAM_LOC pmu_sys_freq_config(enum HAL_CMU_FREQ_T freq) { #if defined(PMU_INIT) || (!defined(PROGRAMMER)) #if defined(MCU_HIGH_PERFORMANCE_MODE) || defined(ULTRA_LOW_POWER) || \ !defined(OSC_26M_X4_AUD2BB) uint32_t lock; enum PMU_VCORE_REQ_T old_req; bool update = false; lock = int_lock(); old_req = pmu_vcore_req; pmu_vcore_req &= ~(PMU_VCORE_SYS_FREQ_HIGH | PMU_VCORE_SYS_FREQ_MEDIUM); #if defined(MCU_HIGH_PERFORMANCE_MODE) if (freq > HAL_CMU_FREQ_104M) { if (high_perf_on) { // The real freq is 350M pmu_vcore_req |= PMU_VCORE_SYS_FREQ_HIGH; } else { pmu_vcore_req |= PMU_VCORE_SYS_FREQ_MEDIUM; } } else { #ifndef OSC_26M_X4_AUD2BB if (freq == HAL_CMU_FREQ_104M) { // The real freq is 200M pmu_vcore_req |= PMU_VCORE_SYS_FREQ_MEDIUM; } #endif } #else if (freq > HAL_CMU_FREQ_104M) { pmu_vcore_req |= PMU_VCORE_SYS_FREQ_MEDIUM; } #endif if (old_req != pmu_vcore_req) { update = true; } int_unlock(lock); if (!update) { // Nothing changes return; } if (pmu_power_mode == PMU_POWER_MODE_NONE) { // PMU not init yet pmu_dig_init_volt(); return; } pmu_dig_set_volt(0, PMU_POWER_MODE_NONE); #endif #endif } void pmu_high_performance_mode_enable(bool enable) { #if defined(MCU_HIGH_PERFORMANCE_MODE) uint16_t val; if (high_perf_on == enable) { return; } high_perf_on = enable; if (!enable) { if (high_perf_freq_mhz > 300) { // Switch to 52M to avoid using PLL hal_cmu_sys_set_freq(HAL_CMU_FREQ_52M); // Restore the default div pmu_read(0xA0, &val); val &= ~(1 << 14); // div=2 (bit14=0) pmu_write(0xA0, val); // Restore the sys freq hal_cmu_sys_set_freq(hal_sysfreq_get_hw_freq()); } // Restore the default PLL freq (384M) bbpll_freq_pll_config(192 * 1000000 * 2); } pmu_sys_freq_config(hal_sysfreq_get_hw_freq()); if (enable) { uint32_t pll_freq; // Change freq first, and then change divider. // Otherwise there will be an instant very high freq sent to digital domain. if (high_perf_freq_mhz <= 300) { pll_freq = high_perf_freq_mhz * 1000000 * 2; } else { pll_freq = high_perf_freq_mhz * 1000000; } bbpll_freq_pll_config(pll_freq); if (high_perf_freq_mhz > 300) { // Switch to 52M to avoid using PLL hal_cmu_sys_set_freq(HAL_CMU_FREQ_52M); pmu_read(0xA0, &val); val |= (1 << 14); // div=1 (bit14=1) pmu_write(0xA0, val); // Restore the sys freq hal_cmu_sys_set_freq(hal_sysfreq_get_hw_freq()); } } #endif } void pmu_usb_config(enum PMU_USB_CONFIG_TYPE_T type) { uint32_t lock; bool update; unsigned short ldo_on, deep_sleep_on; update = false; if (type == PMU_USB_CONFIG_TYPE_NONE) { usbphy_ldo_config(false); ldo_on = PMU_LDO_OFF; deep_sleep_on = PMU_DSLEEP_MODE_OFF; } else { ldo_on = PMU_LDO_ON; deep_sleep_on = PMU_DSLEEP_MODE_ON; } lock = int_lock(); if (type == PMU_USB_CONFIG_TYPE_NONE) { pmu_vusb_req &= ~PMU_VUSB_REQ_USB; if (pmu_vusb_req == 0) { update = true; } } else { if (pmu_vusb_req == 0) { update = true; } pmu_vusb_req |= PMU_VUSB_REQ_USB; } if (update) { pmu_module_config(PMU_USB, PMU_MANUAL_MODE, ldo_on, PMU_LP_MODE_ON, deep_sleep_on); } #ifdef USB_HIGH_SPEED if (type == PMU_USB_CONFIG_TYPE_NONE) { pmu_vcore_req &= ~PMU_VCORE_USB_HS_ENABLED; } else { pmu_vcore_req |= PMU_VCORE_USB_HS_ENABLED; } #endif int_unlock(lock); if (pmu_power_mode != PMU_POWER_MODE_NONE) { // PMU has been inited pmu_dig_set_volt(0, PMU_POWER_MODE_NONE); } if (type != PMU_USB_CONFIG_TYPE_NONE) { usbphy_ldo_config(true); } } void pmu_lbrt_config(int enable) { uint32_t lock; bool update; unsigned short ldo_on, deep_sleep_on; update = false; if (enable) { ldo_on = PMU_LDO_ON; deep_sleep_on = PMU_DSLEEP_MODE_ON; } else { ldo_on = PMU_LDO_OFF; deep_sleep_on = PMU_DSLEEP_MODE_OFF; } lock = int_lock(); if (enable) { if (pmu_vusb_req == 0) { update = true; } pmu_vusb_req |= PMU_VUSB_REQ_LBRT; } else { pmu_vusb_req &= ~PMU_VUSB_REQ_LBRT; if (pmu_vusb_req == 0) { update = true; } } if (update) { pmu_module_config(PMU_USB, PMU_MANUAL_MODE, ldo_on, PMU_LP_MODE_ON, deep_sleep_on); } int_unlock(lock); } struct PMU_CHG_CTX_T { uint16_t pmu_chg_status; }; struct PMU_CHG_CTX_T BOOT_BSS_LOC pmu_chg_ctx; void BOOT_TEXT_SRAM_LOC pmu_charger_save_context(void) { pmu_read(PMU_REG_CHARGER_STATUS, &pmu_chg_ctx.pmu_chg_status); } enum PMU_POWER_ON_CAUSE_T pmu_charger_poweron_status(void) { enum PMU_POWER_ON_CAUSE_T pmu_power_on_cause = PMU_POWER_ON_CAUSE_NONE; if (pmu_chg_ctx.pmu_chg_status & AC_ON_DET_OUT) { pmu_power_on_cause = PMU_POWER_ON_CAUSE_CHARGER_ACOFF; } else if (pmu_chg_ctx.pmu_chg_status & AC_ON) { pmu_power_on_cause = PMU_POWER_ON_CAUSE_CHARGER_ACON; } return pmu_power_on_cause; } void pmu_charger_init(void) { unsigned short readval_cfg; uint32_t lock; lock = int_lock(); pmu_read(PMU_REG_CHARGER_CFG, &readval_cfg); readval_cfg &= ~(REG_CHARGE_IN_INTR_MSK | REG_CHARGE_OUT_INTR_MSK | REG_AC_ON_OUT_EN | REG_AC_ON_IN_EN | REG_CHARGE_INTR_EN); pmu_write(PMU_REG_CHARGER_CFG, readval_cfg); int_unlock(lock); // PMU irqs cannot be cleared by PMU soft reset pmu_read(PMU_REG_CHARGER_STATUS, &readval_cfg); pmu_write(PMU_REG_CHARGER_STATUS, readval_cfg); pmu_read(PMU_REG_INT_STATUS, &readval_cfg); pmu_write(PMU_REG_INT_CLR, readval_cfg); hal_sys_timer_delay(MS_TO_TICKS(1)); lock = int_lock(); pmu_read(PMU_REG_CHARGER_CFG, &readval_cfg); readval_cfg |= REG_AC_ON_OUT_EN | REG_AC_ON_IN_EN | REG_CHARGE_INTR_EN; readval_cfg = SET_BITFIELD(readval_cfg, REG_AC_ON_DB_VALUE, 8); pmu_write(PMU_REG_CHARGER_CFG, readval_cfg); int_unlock(lock); #ifdef PMU_ACON_CAUSE_POWER_UP pmu_read(0x102, &readval_cfg); readval_cfg |= 1; pmu_write(0x102, readval_cfg); #endif } void pmu_charger_shutdown_config(void) { #ifdef PMU_ACON_CAUSE_POWER_UP pmu_wdt_stop(); pmu_charger_init(); #endif } static void pmu_charger_irq_handler(uint16_t irq_status) { enum PMU_CHARGER_STATUS_T status = PMU_CHARGER_UNKNOWN; PMU_DEBUG_TRACE(3, "%s REG_%02X=0x%04X", __func__, PMU_REG_CHARGER_STATUS, irq_status); if ((irq_status & (AC_ON_DET_IN_MASKED | AC_ON_DET_OUT_MASKED)) == 0) { PMU_DEBUG_TRACE(1, "%s SKIP", __func__); return; } else if ((irq_status & (AC_ON_DET_IN_MASKED | AC_ON_DET_OUT_MASKED)) == (AC_ON_DET_IN_MASKED | AC_ON_DET_OUT_MASKED)) { PMU_DEBUG_TRACE(1, "%s DITHERING", __func__); hal_sys_timer_delay(2); } else { PMU_DEBUG_TRACE(1, "%s NORMAL", __func__); } status = pmu_charger_get_status(); if (charger_irq_handler) { charger_irq_handler(status); } } void pmu_charger_set_irq_handler(PMU_CHARGER_IRQ_HANDLER_T handler) { uint32_t lock; uint16_t val; charger_irq_handler = handler; lock = int_lock(); pmu_read(PMU_REG_CHARGER_CFG, &val); if (handler) { val |= REG_CHARGE_IN_INTR_MSK | REG_CHARGE_OUT_INTR_MSK; } else { val &= ~(REG_CHARGE_IN_INTR_MSK | REG_CHARGE_OUT_INTR_MSK); } pmu_write(PMU_REG_CHARGER_CFG, val); pmu_set_irq_unified_handler(PMU_IRQ_TYPE_CHARGER, handler ? pmu_charger_irq_handler : NULL); int_unlock(lock); } void pmu_charger_plugin_config(void) { if (IO_VOLT_ACTIVE_RISE < PMU_IO_3_1V) { vio_act_rise = PMU_IO_3_1V; } if (IO_VOLT_SLEEP < PMU_IO_3_2V) { vio_lp = PMU_IO_3_2V; } pmu_viorise_req(PMU_VIORISE_REQ_USER_CHARGER, true); } void pmu_charger_plugout_config(void) { vio_act_rise = IO_VOLT_ACTIVE_RISE; vio_lp = IO_VOLT_SLEEP; pmu_viorise_req(PMU_VIORISE_REQ_USER_CHARGER, false); } enum PMU_CHARGER_STATUS_T pmu_charger_get_status(void) { unsigned short readval; enum PMU_CHARGER_STATUS_T status; pmu_read(PMU_REG_CHARGER_STATUS, &readval); if (readval & AC_ON) status = PMU_CHARGER_PLUGIN; else status = PMU_CHARGER_PLUGOUT; return status; } #ifdef RTC_ENABLE void pmu_rtc_enable(void) { uint16_t readval; uint32_t lock; #ifdef SIMU // Set RTC counter to 1KHz pmu_write(PMU_REG_RTC_DIV_1HZ, 32 - 2); #else // Set RTC counter to 1Hz pmu_write(PMU_REG_RTC_DIV_1HZ, CONFIG_SYSTICK_HZ * 2 - 2); #endif lock = int_lock(); pmu_read(PMU_REG_POWER_KEY_CFG, &readval); readval |= RTC_POWER_ON_EN | PU_LPO_DR | PU_LPO_REG; pmu_write(PMU_REG_POWER_KEY_CFG, readval); int_unlock(lock); } void pmu_rtc_disable(void) { uint16_t readval; uint32_t lock; pmu_rtc_clear_alarm(); lock = int_lock(); pmu_read(PMU_REG_POWER_KEY_CFG, &readval); readval &= ~(RTC_POWER_ON_EN | PU_LPO_DR); pmu_write(PMU_REG_POWER_KEY_CFG, readval); int_unlock(lock); } int BOOT_TEXT_SRAM_LOC pmu_rtc_enabled(void) { uint16_t readval; pmu_read(PMU_REG_POWER_KEY_CFG, &readval); return !!(readval & RTC_POWER_ON_EN); } void pmu_rtc_set(uint32_t seconds) { uint16_t high, low; // Need 3 seconds to load a new value seconds += 3; high = seconds >> 16; low = seconds & 0xFFFF; pmu_write(PMU_REG_RTC_LOAD_LOW, low); pmu_write(PMU_REG_RTC_LOAD_HIGH, high); } uint32_t pmu_rtc_get(void) { uint16_t high, low, high2; pmu_read(PMU_REG_RTC_VAL_HIGH, &high); pmu_read(PMU_REG_RTC_VAL_LOW, &low); // Handle counter wrap pmu_read(PMU_REG_RTC_VAL_HIGH, &high2); if (high != high2) { high = high2; pmu_read(PMU_REG_RTC_VAL_LOW, &low); } return (high << 16) | low; } void pmu_rtc_set_alarm(uint32_t seconds) { uint16_t readval; uint16_t high, low; uint32_t lock; // Need 1 second to raise the interrupt if (seconds > 0) { seconds -= 1; } high = seconds >> 16; low = seconds & 0xFFFF; pmu_write(PMU_REG_INT_CLR, RTC_INT1_MSKED); pmu_write(PMU_REG_RTC_MATCH1_LOW, low); pmu_write(PMU_REG_RTC_MATCH1_HIGH, high); lock = int_lock(); pmu_read(PMU_REG_INT_EN, &readval); readval |= RTC_INT_EN_1; pmu_write(PMU_REG_INT_EN, readval); int_unlock(lock); } uint32_t BOOT_TEXT_SRAM_LOC pmu_rtc_get_alarm(void) { uint16_t high, low; pmu_read(PMU_REG_RTC_MATCH1_LOW, &low); pmu_read(PMU_REG_RTC_MATCH1_HIGH, &high); // Compensate the alarm offset return (uint32_t)((high << 16) | low) + 1; } void pmu_rtc_clear_alarm(void) { uint16_t readval; uint32_t lock; lock = int_lock(); pmu_read(PMU_REG_INT_EN, &readval); readval &= ~RTC_INT_EN_1; pmu_write(PMU_REG_INT_EN, readval); int_unlock(lock); pmu_write(PMU_REG_INT_CLR, RTC_INT1_MSKED); } int BOOT_TEXT_SRAM_LOC pmu_rtc_alarm_status_set(void) { uint16_t readval; pmu_read(PMU_REG_INT_EN, &readval); return !!(readval & RTC_INT_EN_1); } int pmu_rtc_alarm_alerted() { uint16_t readval; pmu_read(PMU_REG_INT_STATUS, &readval); return !!(readval & RTC_INT_1); } static void pmu_rtc_irq_handler(uint16_t irq_status) { uint32_t seconds; if (irq_status & RTC_INT1_MSKED) { pmu_rtc_clear_alarm(); if (rtc_irq_handler) { seconds = pmu_rtc_get(); rtc_irq_handler(seconds); } } } void pmu_rtc_set_irq_handler(PMU_RTC_IRQ_HANDLER_T handler) { uint16_t readval; uint32_t lock; rtc_irq_handler = handler; lock = int_lock(); pmu_read(PMU_REG_INT_MASK, &readval); if (handler) { readval |= RTC_INT1_MSK; } else { readval &= ~RTC_INT1_MSK; } pmu_write(PMU_REG_INT_MASK, readval); pmu_set_irq_unified_handler(PMU_IRQ_TYPE_RTC, handler ? pmu_rtc_irq_handler : NULL); int_unlock(lock); } #endif int pmu_pwrkey_set_irq(enum HAL_PWRKEY_IRQ_T type) { uint16_t val; uint16_t int_en; if (type == HAL_PWRKEY_IRQ_NONE) { // Clear existing IRQs pmu_write(PMU_REG_CHARGER_STATUS, (POWER_ON_PRESS | POWER_ON_RELEASE)); // Disable future IRQs int_en = 0; } else if (type == HAL_PWRKEY_IRQ_FALLING_EDGE) { int_en = POWERON_PRESS_EN; } else if (type == HAL_PWRKEY_IRQ_RISING_EDGE) { int_en = POWERON_RELEASE_EN; } else if (type == HAL_PWRKEY_IRQ_BOTH_EDGE) { int_en = POWERON_PRESS_EN | POWERON_RELEASE_EN; } else { return 1; } pmu_read(PMU_REG_SLEEP_CFG, &val); val = (val & ~(POWERON_PRESS_EN | POWERON_RELEASE_EN)) | int_en; pmu_write(PMU_REG_SLEEP_CFG, val); return 0; } int hal_pwrkey_set_irq(enum HAL_PWRKEY_IRQ_T type) __attribute__((alias("pmu_pwrkey_set_irq"))); bool pmu_pwrkey_pressed(void) { uint16_t val; pmu_read(PMU_REG_CHARGER_STATUS, &val); return !!(val & POWER_ON); } bool hal_pwrkey_pressed(void) __attribute__((alias("pmu_pwrkey_pressed"))); enum HAL_PWRKEY_IRQ_T pmu_pwrkey_irq_value_to_state(uint16_t irq_status) { enum HAL_PWRKEY_IRQ_T state = HAL_PWRKEY_IRQ_NONE; if (irq_status & POWER_ON_PRESS) { state |= HAL_PWRKEY_IRQ_FALLING_EDGE; } if (irq_status & POWER_ON_RELEASE) { state |= HAL_PWRKEY_IRQ_RISING_EDGE; } return state; } static void pmu_general_irq_handler(void) { uint32_t lock; uint16_t val; bool pwrkey, charger, gpadc, rtc; pwrkey = false; charger = false; gpadc = false; rtc = false; lock = int_lock(); pmu_read(PMU_REG_CHARGER_STATUS, &val); if (val & (POWER_ON_PRESS | POWER_ON_RELEASE)) { pwrkey = true; } if (val & (AC_ON_DET_OUT_MASKED | AC_ON_DET_IN_MASKED)) { charger = true; } if (pwrkey || charger) { pmu_write(PMU_REG_CHARGER_STATUS, val); } int_unlock(lock); if (pwrkey) { if (pmu_irq_hdlrs[PMU_IRQ_TYPE_PWRKEY]) { pmu_irq_hdlrs[PMU_IRQ_TYPE_PWRKEY](val); } } if (charger) { if (pmu_irq_hdlrs[PMU_IRQ_TYPE_CHARGER]) { pmu_irq_hdlrs[PMU_IRQ_TYPE_CHARGER](val); } } lock = int_lock(); pmu_read(PMU_REG_INT_MSKED_STATUS, &val); if (val & (KEY_ERR1_INTR_MSKED | KEY_ERR0_INTR_MSKED | KEY_PRESS_INTR_MSKED | KEY_RELEASE_INTR_MSKED | SAMPLE_DONE_INTR_MSKED | CHAN_DATA_INTR_MSKED_MASK)) { gpadc = true; } if (val & (RTC_INT1_MSKED | RTC_INT0_MSKED)) { rtc = true; } if (gpadc || rtc) { pmu_write(PMU_REG_INT_CLR, val); } int_unlock(lock); if (gpadc) { if (pmu_irq_hdlrs[PMU_IRQ_TYPE_GPADC]) { pmu_irq_hdlrs[PMU_IRQ_TYPE_GPADC](val); } } if (rtc) { if (pmu_irq_hdlrs[PMU_IRQ_TYPE_RTC]) { pmu_irq_hdlrs[PMU_IRQ_TYPE_RTC](val); } } } int pmu_set_irq_unified_handler(enum PMU_IRQ_TYPE_T type, PMU_IRQ_UNIFIED_HANDLER_T hdlr) { bool update; uint32_t lock; int i; if (type >= PMU_IRQ_TYPE_QTY) { return 1; } update = false; lock = int_lock(); for (i = 0; i < PMU_IRQ_TYPE_QTY; i++) { if (pmu_irq_hdlrs[i]) { break; } } pmu_irq_hdlrs[type] = hdlr; if (hdlr) { update = (i >= PMU_IRQ_TYPE_QTY); } else { if (i == type) { for (; i < PMU_IRQ_TYPE_QTY; i++) { if (pmu_irq_hdlrs[i]) { break; } } update = (i >= PMU_IRQ_TYPE_QTY); } } if (update) { if (hdlr) { NVIC_SetVector(PMU_IRQn, (uint32_t)pmu_general_irq_handler); NVIC_SetPriority(PMU_IRQn, IRQ_PRIORITY_NORMAL); NVIC_ClearPendingIRQ(PMU_IRQn); NVIC_EnableIRQ(PMU_IRQn); } else { NVIC_DisableIRQ(PMU_IRQn); } } int_unlock(lock); return 0; } enum PMU_POWER_ON_CAUSE_T pmu_get_power_on_cause(void) { enum PMU_POWER_ON_CAUSE_T pmu_power_on_cause = PMU_POWER_ON_CAUSE_NONE; pmu_power_on_cause = pmu_charger_poweron_status(); if (pmu_power_on_cause == PMU_POWER_ON_CAUSE_NONE) { pmu_power_on_cause = PMU_POWER_ON_CAUSE_POWER_KEY; } return pmu_power_on_cause; } void pmu_viorise_req(enum PMU_VIORISE_REQ_USER_T user, bool rise) { uint32_t lock; lock = int_lock(); if (rise) { if (vio_risereq_map == 0) { pmu_module_ramp_volt(PMU_IO, vio_lp, vio_act_rise); } vio_risereq_map |= (1 << user); } else { vio_risereq_map &= ~(1 << user); if (vio_risereq_map == 0) { pmu_module_ramp_volt(PMU_IO, vio_lp, vio_act_normal); } } int_unlock(lock); } int pmu_debug_config_ana(uint16_t volt) { return 0; } int pmu_debug_config_codec(uint16_t volt) { #ifdef ANC_PROD_TEST if (volt == 1600 || volt == 1700 || volt == 1800 || volt == 1900 || volt == 1950) { vhppa_mv = vcodec_mv = volt; vcodec_off = true; } else { vcodec_off = false; return 1; } #endif return 0; } int pmu_debug_config_vcrystal(bool on) { return 0; } int pmu_debug_config_audio_output(bool diff) { return 0; } void pmu_debug_reliability_test(int stage) { uint16_t volt; if (stage == 0) { volt = PMU_DCDC_ANA_1_2V; } else { volt = PMU_DCDC_ANA_1_3V; } pmu_dcdc_ana_set_volt(volt, ana_lp_dcdc); } void pmu_led_set_hiz(enum HAL_GPIO_PIN_T pin) { uint16_t val1, val2; uint32_t lock; if (pin == HAL_GPIO_PIN_LED1 || pin == HAL_GPIO_PIN_LED2) { lock = int_lock(); pmu_read(PMU_REG_MIC_LDO_EN, &val1); pmu_read(PMU_REG_LED_CFG, &val2); if (pin == HAL_GPIO_PIN_LED1) { val1 &= ~REG_LED_IO1_RX_EN; val2 = (val2 | REG_LED_IO1_PU | REG_LED_IO1_OENB) & ~(REG_LED_IO1_PUEN | REG_LED_IO1_PDEN); } else { val1 &= ~REG_LED_IO2_RX_EN; val2 = (val2 | REG_LED_IO2_PU | REG_LED_IO2_OENB) & ~(REG_LED_IO2_PUEN | REG_LED_IO2_PDEN); } pmu_write(PMU_REG_MIC_LDO_EN, val1); pmu_write(PMU_REG_LED_CFG, val2); int_unlock(lock); } } void pmu_led_set_direction(enum HAL_GPIO_PIN_T pin, enum HAL_GPIO_DIR_T dir) { uint16_t val; uint16_t val_rx; uint32_t lock; if (pin == HAL_GPIO_PIN_LED1 || pin == HAL_GPIO_PIN_LED2) { lock = int_lock(); pmu_read(PMU_REG_LED_CFG, &val); pmu_read(PMU_REG_MIC_LDO_EN, &val_rx); if (pin == HAL_GPIO_PIN_LED1) { val |= REG_LED_IO1_PU; if (dir == HAL_GPIO_DIR_IN) { val |= REG_LED_IO1_OENB; val_rx |= REG_LED_IO1_RX_EN; } else { val &= ~REG_LED_IO1_OENB; val_rx &= ~REG_LED_IO1_RX_EN; } } else { val |= REG_LED_IO2_PU; if (dir == HAL_GPIO_DIR_IN) { val |= REG_LED_IO2_OENB; val_rx |= REG_LED_IO2_RX_EN; } else { val &= ~REG_LED_IO2_OENB; val_rx &= ~REG_LED_IO2_RX_EN; } } pmu_write(PMU_REG_LED_CFG, val); pmu_write(PMU_REG_MIC_LDO_EN, val_rx); ; int_unlock(lock); } } enum HAL_GPIO_DIR_T pmu_led_get_direction(enum HAL_GPIO_PIN_T pin) { uint16_t val; if (pin == HAL_GPIO_PIN_LED1 || pin == HAL_GPIO_PIN_LED2) { pmu_read(PMU_REG_LED_CFG, &val); if (pin == HAL_GPIO_PIN_LED1) { return (val & REG_LED_IO1_OENB) ? HAL_GPIO_DIR_IN : HAL_GPIO_DIR_OUT; } else { return (val & REG_LED_IO2_OENB) ? HAL_GPIO_DIR_IN : HAL_GPIO_DIR_OUT; } } else { return HAL_GPIO_DIR_IN; } } void pmu_led_set_voltage_domains(enum HAL_IOMUX_PIN_T pin, enum HAL_IOMUX_PIN_VOLTAGE_DOMAINS_T volt) { enum PMU_LED_VOLT_T { PMU_LED_VOLT_VBAT, PMU_LED_VOLT_VMEM, PMU_LED_VOLT_VIO, }; enum PMU_LED_VOLT_T sel; uint16_t val; uint32_t lock; if (pin == HAL_IOMUX_PIN_LED1 || pin == HAL_IOMUX_PIN_LED2) { if (volt == HAL_IOMUX_PIN_VOLTAGE_VIO) { sel = PMU_LED_VOLT_VIO; } else if (volt == HAL_IOMUX_PIN_VOLTAGE_MEM) { sel = PMU_LED_VOLT_VMEM; } else { sel = PMU_LED_VOLT_VBAT; } lock = int_lock(); pmu_read(PMU_REG_LED_CFG, &val); if (pin == HAL_IOMUX_PIN_LED1) { val = SET_BITFIELD(val, REG_LED_IO1_SEL, sel); } else { val = SET_BITFIELD(val, REG_LED_IO2_SEL, sel); } pmu_write(PMU_REG_LED_CFG, val); int_unlock(lock); } } void pmu_led_set_pull_select(enum HAL_IOMUX_PIN_T pin, enum HAL_IOMUX_PIN_PULL_SELECT_T pull_sel) { uint16_t val; uint32_t lock; if (pin == HAL_IOMUX_PIN_LED1 || pin == HAL_IOMUX_PIN_LED2) { lock = int_lock(); pmu_read(PMU_REG_LED_CFG, &val); if (pin == HAL_IOMUX_PIN_LED1) { val &= ~(REG_LED_IO1_PDEN | REG_LED_IO1_PUEN); if (pull_sel == HAL_IOMUX_PIN_PULLUP_ENABLE) { val |= REG_LED_IO1_PUEN; } else if (pull_sel == HAL_IOMUX_PIN_PULLDOWN_ENABLE) { val |= REG_LED_IO1_PDEN; } } else { val &= ~(REG_LED_IO2_PDEN | REG_LED_IO2_PUEN); if (pull_sel == HAL_IOMUX_PIN_PULLUP_ENABLE) { val |= REG_LED_IO2_PUEN; } else if (pull_sel == HAL_IOMUX_PIN_PULLDOWN_ENABLE) { val |= REG_LED_IO2_PDEN; } } pmu_write(PMU_REG_LED_CFG, val); int_unlock(lock); } } void pmu_led_set_value(enum HAL_GPIO_PIN_T pin, int data) { uint16_t val; uint32_t lock; #ifdef PMU_LED_VIA_PWM uint16_t br_val; #endif if (pin == HAL_GPIO_PIN_LED1 || pin == HAL_GPIO_PIN_LED2) { lock = int_lock(); #ifdef PMU_LED_VIA_PWM pmu_read(PMU_REG_PWM_BR_EN, &br_val); #endif pmu_read(PMU_REG_PWM_EN, &val); if (pin == HAL_GPIO_PIN_LED1) { #ifdef PMU_LED_VIA_PWM pmu_write(PMU_REG_PWM2_TOGGLE, 0xFFFF); br_val &= ~REG_PWM2_BR_EN; val |= PWM_SELECT_EN(1 << 0); if (data) { val &= ~PWM_SELECT_INV(1 << 0); } else { val |= PWM_SELECT_INV(1 << 0); } #else if (data) { val |= REG_LED0_OUT; } else { val &= ~REG_LED0_OUT; } #endif } else { #ifdef PMU_LED_VIA_PWM pmu_write(PMU_REG_PWM3_TOGGLE, 0xFFFF); br_val &= ~REG_PWM3_BR_EN; val |= PWM_SELECT_EN(1 << 1); if (data) { val &= ~PWM_SELECT_INV(1 << 1); } else { val |= PWM_SELECT_INV(1 << 1); } #else if (data) { val |= REG_LED1_OUT; } else { val &= ~REG_LED1_OUT; } #endif } #ifdef PMU_LED_VIA_PWM pmu_write(PMU_REG_PWM_BR_EN, br_val); #endif pmu_write(PMU_REG_PWM_EN, val); int_unlock(lock); } } int pmu_led_get_value(enum HAL_GPIO_PIN_T pin) { uint16_t val; int data = 0; if (pin == HAL_GPIO_PIN_LED1 || pin == HAL_GPIO_PIN_LED2) { pmu_read(PMU_REG_POWER_OFF, &val); if (pin == HAL_GPIO_PIN_LED1) { data = REG_LED_IO1_DATA_IN; } else { data = REG_LED_IO2_DATA_IN; } data &= val; } return !!data; } struct PMU_WDT_CTX_T { bool enabled; uint16_t wdt_timer; uint16_t wdt_cfg; }; static struct PMU_WDT_CTX_T BOOT_BSS_LOC wdt_ctx; void BOOT_TEXT_SRAM_LOC pmu_wdt_save_context(void) { uint16_t wdt_cfg = 0, wdt_timer = 0; pmu_read(PMU_REG_WDT_CFG, &wdt_cfg); if (wdt_cfg & (REG_WDT_RESET_EN | REG_WDT_EN)) { wdt_ctx.enabled = true; wdt_ctx.wdt_cfg = wdt_cfg; pmu_read(PMU_REG_WDT_TIMER, &wdt_timer); wdt_ctx.wdt_timer = wdt_timer; } } void BOOT_TEXT_SRAM_LOC pmu_wdt_restore_context(void) { if (wdt_ctx.enabled) { pmu_write(PMU_REG_WDT_TIMER, wdt_ctx.wdt_timer); pmu_write(PMU_REG_WDT_CFG, wdt_ctx.wdt_cfg); } } void pmu_wdt_set_irq_handler(PMU_WDT_IRQ_HANDLER_T handler) {} int pmu_wdt_config(uint32_t irq_ms, uint32_t reset_ms) { // No wdt irq on best2300 if (irq_ms + reset_ms > 0xFFFF) { return 1; } wdt_timer = irq_ms + reset_ms; pmu_write(PMU_REG_WDT_TIMER, wdt_timer); return 0; } void pmu_wdt_start(void) { uint16_t val; if (wdt_timer == 0) { return; } pmu_read(PMU_REG_WDT_CFG, &val); val |= (REG_WDT_RESET_EN | REG_WDT_EN); pmu_write(PMU_REG_WDT_CFG, val); } void pmu_wdt_stop(void) { uint16_t val; if (wdt_timer == 0) { return; } pmu_read(PMU_REG_WDT_CFG, &val); val &= ~(REG_WDT_RESET_EN | REG_WDT_EN); pmu_write(PMU_REG_WDT_CFG, val); } void pmu_wdt_feed(void) { if (wdt_timer == 0) { return; } pmu_write(PMU_REG_WDT_TIMER, wdt_timer); } void pmu_ntc_capture_enable(void) {} void pmu_ntc_capture_disable(void) {}