feat(imx8ulp): update the upower config for power optimization

Enable the AFBB by default for active mode when APD side wakeup
from low power mode to align with the first time boot up.

Update the power mode configs to force shutdown all the
necessary power switches to optimize the power consumption.

To reduce the pad power consumption, put all the pad into
OFF mode to save more power. the PTD's compensation should
also be disabled in low power mode to save more power.

when APD enters PD mode, the LDO1(used by DDR) can be shutdown
to save power. when APD enters DPD mode, the BUCK3(supply for
APD/LPAV) can be shutdown to save power.

In single boot mode, When APD enters DPD mode, buck3 will
shutdown, LDO1 should be off to save more power as the DDR
controller has lost power.

In dualboot mode, the LPAV is owned by RTD side. When APD enters
low power mode, APD side should not config those PMIC regulators
that used by the resource owned by RTD side.

Signed-off-by: Jacky Bai <ping.bai@nxp.com>
Change-Id: Ie5e9b428f85345b81744313a8fb93bfc27e0dd71
This commit is contained in:
Jacky Bai 2021-10-20 11:25:30 +08:00
parent ea1f7a2e10
commit 36af80c2b4
2 changed files with 113 additions and 13 deletions

View file

@ -142,6 +142,22 @@ struct iomuxc_section iomuxc_sections[IOMUXC_SECTION_NUM] = {
}; };
static uint32_t iomuxc_ctx[258]; static uint32_t iomuxc_ctx[258];
#define PORTS_NUM 3U
void apd_io_pad_off(void)
{
unsigned int i, j;
/* off the PTD/E/F, need to be customized based on actual user case */
for (i = 0; i < PORTS_NUM; i++) {
for (j = 0; j < iomuxc_sections[i].reg_num; j++) {
mmio_write_32(iomuxc_sections[i].offset + j * 4, 0);
}
}
/* disable the PTD compensation */
mmio_write_32(IMX_SIM1_BASE + 0x48, 0x800);
}
void iomuxc_save(void) void iomuxc_save(void)
{ {
unsigned int i, j; unsigned int i, j;
@ -152,6 +168,8 @@ void iomuxc_save(void)
iomuxc_ctx[index++] = mmio_read_32(iomuxc_sections[i].offset + j * 4); iomuxc_ctx[index++] = mmio_read_32(iomuxc_sections[i].offset + j * 4);
} }
} }
apd_io_pad_off();
} }
void iomuxc_restore(void) void iomuxc_restore(void)

View file

@ -21,6 +21,10 @@ extern void cgc1_restore(void);
extern void imx_apd_ctx_save(unsigned int cpu); extern void imx_apd_ctx_save(unsigned int cpu);
extern void imx_apd_ctx_restore(unsigned int cpu); extern void imx_apd_ctx_restore(unsigned int cpu);
extern void usb_wakeup_enable(bool enable); extern void usb_wakeup_enable(bool enable);
extern void upower_wait_resp(void);
extern bool is_lpav_owned_by_apd(void);
extern void apd_io_pad_off(void);
extern int upower_pmic_i2c_read(uint32_t reg_addr, uint32_t *reg_val);
static uintptr_t secure_entrypoint; static uintptr_t secure_entrypoint;
@ -69,8 +73,6 @@ static uintptr_t secure_entrypoint;
.mask = (m), \ .mask = (m), \
} }
extern void upower_wait_resp(void);
static int imx_pwr_set_cpu_entry(unsigned int cpu, unsigned int entry) static int imx_pwr_set_cpu_entry(unsigned int cpu, unsigned int entry)
{ {
mmio_write_32(RVBARADDRx(cpu), entry); mmio_write_32(RVBARADDRx(cpu), entry);
@ -134,8 +136,8 @@ ps_apd_pwr_mode_cfgs_t apd_pwr_mode_cfgs = {
[DPD_PWR_MODE] = { [DPD_PWR_MODE] = {
.swt_board_offs = 0x180, .swt_board_offs = 0x180,
.swt_mem_offs = 0x188, .swt_mem_offs = 0x188,
.pmic_cfg = PMIC_CFG(0x23, 0xa, 0x2), .pmic_cfg = PMIC_CFG(0x23, 0x0, 0x2),
.pad_cfg = PAD_CFG(0xc, 0x0, 0x01e80a02), .pad_cfg = PAD_CFG(0x0, 0xc, 0x01e80a02),
.bias_cfg = BIAS_CFG(0x0, 0x2, 0x2, 0x0), .bias_cfg = BIAS_CFG(0x0, 0x2, 0x2, 0x0),
}, },
@ -143,8 +145,8 @@ ps_apd_pwr_mode_cfgs_t apd_pwr_mode_cfgs = {
[PD_PWR_MODE] = { [PD_PWR_MODE] = {
.swt_board_offs = 0x170, .swt_board_offs = 0x170,
.swt_mem_offs = 0x178, .swt_mem_offs = 0x178,
.pmic_cfg = PMIC_CFG(0x23, 0x2, 0x2), .pmic_cfg = PMIC_CFG(0x23, 0x0, 0x2),
.pad_cfg = PAD_CFG(0x0, 0x0, 0x01e80a00), .pad_cfg = PAD_CFG(0x0, 0xc, 0x01e80a00),
.bias_cfg = BIAS_CFG(0x0, 0x2, 0x2, 0x0), .bias_cfg = BIAS_CFG(0x0, 0x2, 0x2, 0x0),
}, },
@ -153,49 +155,107 @@ ps_apd_pwr_mode_cfgs_t apd_pwr_mode_cfgs = {
.swt_mem_offs = 0x128, .swt_mem_offs = 0x128,
.pmic_cfg = PMIC_CFG(0x23, 0x0, 0x2), .pmic_cfg = PMIC_CFG(0x23, 0x0, 0x2),
.pad_cfg = PAD_CFG(0x0, 0x0, 0x0deb7a00), .pad_cfg = PAD_CFG(0x0, 0x0, 0x0deb7a00),
.bias_cfg = BIAS_CFG(0x0, 0x2, 0x2, 0x0), .bias_cfg = BIAS_CFG(0x2, 0x2, 0x2, 0x0),
}, },
[ACT_PWR_MODE] = { [ACT_PWR_MODE] = {
.swt_board_offs = 0x110, .swt_board_offs = 0x110,
.swt_mem_offs = 0x118, .swt_mem_offs = 0x118,
.pmic_cfg = PMIC_CFG(0x23, 0x2, 0x2), .pmic_cfg = PMIC_CFG(0x23, 0x0, 0x2),
.pad_cfg = PAD_CFG(0x0, 0x0, 0x0deb7a00), .pad_cfg = PAD_CFG(0x0, 0x0, 0x0deb7a00),
.bias_cfg = BIAS_CFG(0x0, 0x2, 0x2, 0x0), .bias_cfg = BIAS_CFG(0x2, 0x2, 0x2, 0x0),
}, },
}; };
/* APD power switch config */ /* APD power switch config */
ps_apd_swt_cfgs_t apd_swt_cfgs = { ps_apd_swt_cfgs_t apd_swt_cfgs = {
[DPD_PWR_MODE] = { [DPD_PWR_MODE] = {
.swt_board[0] = SWT_BOARD(0x00060003, 0x7c), .swt_board[0] = SWT_BOARD(0x0, 0x1fffc),
.swt_mem[0] = SWT_MEM(0x0, 0x0, 0x1ffff), .swt_mem[0] = SWT_MEM(0x0, 0x0, 0x1ffff),
.swt_mem[1] = SWT_MEM(0x003fffff, 0x003fffff, 0x0), .swt_mem[1] = SWT_MEM(0x003fffff, 0x003fffff, 0x0),
}, },
[PD_PWR_MODE] = { [PD_PWR_MODE] = {
.swt_board[0] = SWT_BOARD(0x00060003, 0x00001e74), .swt_board[0] = SWT_BOARD(0x0, 0x00001fffc),
.swt_mem[0] = SWT_MEM(0x00010c00, 0x0, 0x1ffff), .swt_mem[0] = SWT_MEM(0x00010c00, 0x0, 0x1ffff),
.swt_mem[1] = SWT_MEM(0x003fffff, 0x003f0000, 0x0), .swt_mem[1] = SWT_MEM(0x003fffff, 0x003f0000, 0x0),
}, },
[ADMA_PWR_MODE] = { [ADMA_PWR_MODE] = {
.swt_board[0] = SWT_BOARD(0x0006ff77, 0x0006ff7c), .swt_board[0] = SWT_BOARD(0x15f74, 0x15f74),
.swt_mem[0] = SWT_MEM(0x0001fffd, 0x0001fffd, 0x1ffff), .swt_mem[0] = SWT_MEM(0x0001fffd, 0x0001fffd, 0x1ffff),
.swt_mem[1] = SWT_MEM(0x003fffff, 0x003fffff, 0x0), .swt_mem[1] = SWT_MEM(0x003fffff, 0x003fffff, 0x0),
}, },
[ACT_PWR_MODE] = { [ACT_PWR_MODE] = {
.swt_board[0] = SWT_BOARD(0x0006ff77, 0x0000ff7c), .swt_board[0] = SWT_BOARD(0x15f74, 0x15f74),
.swt_mem[0] = SWT_MEM(0x0001fffd, 0x0001fffd, 0x1ffff), .swt_mem[0] = SWT_MEM(0x0001fffd, 0x0001fffd, 0x1ffff),
.swt_mem[1] = SWT_MEM(0x003fffff, 0x003fffff, 0x0), .swt_mem[1] = SWT_MEM(0x003fffff, 0x003fffff, 0x0),
}, },
}; };
/* PMIC config for power down, LDO1 should be OFF */
ps_apd_pmic_reg_data_cfgs_t pd_pmic_reg_cfgs = {
[0] = {
.tag = PMIC_REG_VALID_TAG,
.power_mode = PD_PWR_MODE,
.i2c_addr = 0x30,
.i2c_data = 0x9c,
},
[1] = {
.tag = PMIC_REG_VALID_TAG,
.power_mode = PD_PWR_MODE,
.i2c_addr = 0x22,
.i2c_data = 0xb,
},
[2] = {
.tag = PMIC_REG_VALID_TAG,
.power_mode = ACT_PWR_MODE,
.i2c_addr = 0x30,
.i2c_data = 0x9d,
},
[3] = {
.tag = PMIC_REG_VALID_TAG,
.power_mode = ACT_PWR_MODE,
.i2c_addr = 0x22,
.i2c_data = 0x28,
},
};
/* PMIC config for deep power down, BUCK3 should be OFF */
ps_apd_pmic_reg_data_cfgs_t dpd_pmic_reg_cfgs = {
[0] = {
.tag = PMIC_REG_VALID_TAG,
.power_mode = DPD_PWR_MODE,
.i2c_addr = 0x21,
.i2c_data = 0x78,
},
[1] = {
.tag = PMIC_REG_VALID_TAG,
.power_mode = DPD_PWR_MODE,
.i2c_addr = 0x30,
.i2c_data = 0x9c,
},
[2] = {
.tag = PMIC_REG_VALID_TAG,
.power_mode = ACT_PWR_MODE,
.i2c_addr = 0x21,
.i2c_data = 0x79,
},
[3] = {
.tag = PMIC_REG_VALID_TAG,
.power_mode = ACT_PWR_MODE,
.i2c_addr = 0x30,
.i2c_data = 0x9d,
},
};
struct ps_pwr_mode_cfg_t *pwr_sys_cfg = (struct ps_pwr_mode_cfg_t *)UPWR_DRAM_SHARED_BASE_ADDR; struct ps_pwr_mode_cfg_t *pwr_sys_cfg = (struct ps_pwr_mode_cfg_t *)UPWR_DRAM_SHARED_BASE_ADDR;
void imx_set_pwr_mode_cfg(abs_pwr_mode_t mode) void imx_set_pwr_mode_cfg(abs_pwr_mode_t mode)
{ {
uint32_t volt;
if (mode >= NUM_PWR_MODES) { if (mode >= NUM_PWR_MODES) {
return; return;
} }
@ -206,6 +266,25 @@ void imx_set_pwr_mode_cfg(abs_pwr_mode_t mode)
/* apd power switch config */ /* apd power switch config */
memcpy(&pwr_sys_cfg->ps_apd_swt_cfg[mode], &apd_swt_cfgs[mode], sizeof(swt_config_t)); memcpy(&pwr_sys_cfg->ps_apd_swt_cfg[mode], &apd_swt_cfgs[mode], sizeof(swt_config_t));
/*
* BUCK3 & LDO1 can only be shutdown when LPAV is owned by APD side
* otherwise RTD side is responsible to control them in low power mode.
*/
if (is_lpav_owned_by_apd()) {
/* power off the BUCK3 in DPD mode */
if (mode == DPD_PWR_MODE) {
memcpy(&pwr_sys_cfg->ps_apd_pmic_reg_data_cfg, &dpd_pmic_reg_cfgs,
sizeof(ps_apd_pmic_reg_data_cfgs_t));
/* LDO1 should be power off in PD mode */
} else if (mode == PD_PWR_MODE) {
/* overwrite the buck3 voltage setting in active mode */
upower_pmic_i2c_read(0x22, &volt);
pd_pmic_reg_cfgs[3].i2c_data = volt;
memcpy(&pwr_sys_cfg->ps_apd_pmic_reg_data_cfg, &pd_pmic_reg_cfgs,
sizeof(ps_apd_pmic_reg_data_cfgs_t));
}
}
} }
void imx_domain_suspend(const psci_power_state_t *target_state) void imx_domain_suspend(const psci_power_state_t *target_state)
@ -395,6 +474,9 @@ void __dead2 imx_system_off(void)
plat_gic_cpuif_disable(); plat_gic_cpuif_disable();
/* power off all the pad */
apd_io_pad_off();
/* Config the power mode info for entering DPD mode and ACT mode */ /* Config the power mode info for entering DPD mode and ACT mode */
imx_set_pwr_mode_cfg(ADMA_PWR_MODE); imx_set_pwr_mode_cfg(ADMA_PWR_MODE);
imx_set_pwr_mode_cfg(ACT_PWR_MODE); imx_set_pwr_mode_cfg(ACT_PWR_MODE);