pinebuds/platform/drivers/ana/best2300p/pmu_best2300p.c

4224 lines
117 KiB
C

/***************************************************************************
*
* 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) {}