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
diff --git a/plat/imx/imx8ulp/apd_context.c b/plat/imx/imx8ulp/apd_context.c
index 8f179e7..b484a66 100644
--- a/plat/imx/imx8ulp/apd_context.c
+++ b/plat/imx/imx8ulp/apd_context.c
@@ -142,6 +142,22 @@
 };
 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)
 {
 	unsigned int i, j;
@@ -152,6 +168,8 @@
 			iomuxc_ctx[index++] = mmio_read_32(iomuxc_sections[i].offset + j * 4);
 		}
 	}
+
+	apd_io_pad_off();
 }
 
 void iomuxc_restore(void)
diff --git a/plat/imx/imx8ulp/imx8ulp_psci.c b/plat/imx/imx8ulp/imx8ulp_psci.c
index b2559af..78078d5 100644
--- a/plat/imx/imx8ulp/imx8ulp_psci.c
+++ b/plat/imx/imx8ulp/imx8ulp_psci.c
@@ -21,6 +21,10 @@
 extern void imx_apd_ctx_save(unsigned int cpu);
 extern void imx_apd_ctx_restore(unsigned int cpu);
 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;
 
@@ -69,8 +73,6 @@
 		.mask = (m),	\
 	}
 
-extern void upower_wait_resp(void);
-
 static int imx_pwr_set_cpu_entry(unsigned int cpu, unsigned int entry)
 {
 	mmio_write_32(RVBARADDRx(cpu), entry);
@@ -134,8 +136,8 @@
 	[DPD_PWR_MODE] = {
 		.swt_board_offs = 0x180,
 		.swt_mem_offs = 0x188,
-		.pmic_cfg = PMIC_CFG(0x23, 0xa, 0x2),
-		.pad_cfg = PAD_CFG(0xc, 0x0, 0x01e80a02),
+		.pmic_cfg = PMIC_CFG(0x23, 0x0, 0x2),
+		.pad_cfg = PAD_CFG(0x0, 0xc, 0x01e80a02),
 		.bias_cfg = BIAS_CFG(0x0, 0x2, 0x2, 0x0),
 	},
 
@@ -143,8 +145,8 @@
 	[PD_PWR_MODE] = {
 		.swt_board_offs = 0x170,
 		.swt_mem_offs = 0x178,
-		.pmic_cfg = PMIC_CFG(0x23, 0x2, 0x2),
-		.pad_cfg = PAD_CFG(0x0, 0x0, 0x01e80a00),
+		.pmic_cfg = PMIC_CFG(0x23, 0x0, 0x2),
+		.pad_cfg = PAD_CFG(0x0, 0xc, 0x01e80a00),
 		.bias_cfg = BIAS_CFG(0x0, 0x2, 0x2, 0x0),
 	},
 
@@ -153,49 +155,107 @@
 		.swt_mem_offs = 0x128,
 		.pmic_cfg = PMIC_CFG(0x23, 0x0, 0x2),
 		.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] = {
 		.swt_board_offs = 0x110,
 		.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),
-		.bias_cfg = BIAS_CFG(0x0, 0x2, 0x2, 0x0),
+		.bias_cfg = BIAS_CFG(0x2, 0x2, 0x2, 0x0),
 	},
 };
 
 /* APD power switch config */
 ps_apd_swt_cfgs_t apd_swt_cfgs = {
 	[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[1] = SWT_MEM(0x003fffff, 0x003fffff, 0x0),
 	},
 
 	[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[1] = SWT_MEM(0x003fffff, 0x003f0000, 0x0),
 	},
 
 	[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[1] = SWT_MEM(0x003fffff, 0x003fffff, 0x0),
 	},
 
 	[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[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;
 
 void imx_set_pwr_mode_cfg(abs_pwr_mode_t mode)
 {
+	uint32_t volt;
+
 	if (mode >= NUM_PWR_MODES) {
 		return;
 	}
@@ -206,6 +266,25 @@
 
 	/* apd power switch config */
 	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)
@@ -395,6 +474,9 @@
 
 	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 */
 	imx_set_pwr_mode_cfg(ADMA_PWR_MODE);
 	imx_set_pwr_mode_cfg(ACT_PWR_MODE);