mirror of
https://github.com/ARM-software/arm-trusted-firmware.git
synced 2025-04-30 07:39:24 +00:00
feat(imx8ulp): adjust the voltage when sys dvfs enabled
When system level DVFS is enabled, voltage can be changed to optimize the power consumption. Signed-off-by: Jacky Bai <ping.bai@nxp.com> Reviewed-by: Ye Li <ye.li@nxp.com> Change-Id: Idfa0e637402078f3daf6e7c4ea1abb9af7675494
This commit is contained in:
parent
caee2733ba
commit
416c4433f0
2 changed files with 73 additions and 0 deletions
|
@ -141,6 +141,7 @@ uint32_t freq_specific_reg_array[PHY_DIFF_NUM] = {
|
||||||
spinlock_t dfs_lock;
|
spinlock_t dfs_lock;
|
||||||
static volatile uint32_t core_count;
|
static volatile uint32_t core_count;
|
||||||
static volatile bool in_progress;
|
static volatile bool in_progress;
|
||||||
|
static volatile bool sys_dvfs;
|
||||||
static int num_fsp;
|
static int num_fsp;
|
||||||
|
|
||||||
static void ddr_init(void)
|
static void ddr_init(void)
|
||||||
|
@ -499,6 +500,8 @@ static void set_ddr_clk(uint32_t ddr_freq)
|
||||||
#define DDR_DFS_GET_FSP_COUNT 0x10
|
#define DDR_DFS_GET_FSP_COUNT 0x10
|
||||||
#define DDR_BYPASS_DRATE U(400)
|
#define DDR_BYPASS_DRATE U(400)
|
||||||
|
|
||||||
|
extern int upower_pmic_i2c_write(uint32_t reg_addr, uint32_t reg_val);
|
||||||
|
|
||||||
/* Normally, we only switch frequency between 1(bypass) and 2(highest) */
|
/* Normally, we only switch frequency between 1(bypass) and 2(highest) */
|
||||||
int lpddr4_dfs(uint32_t freq_index)
|
int lpddr4_dfs(uint32_t freq_index)
|
||||||
{
|
{
|
||||||
|
@ -515,6 +518,14 @@ int lpddr4_dfs(uint32_t freq_index)
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* increase the voltage to 1.1V firstly before increase frequency
|
||||||
|
* and APD enter OD mode
|
||||||
|
*/
|
||||||
|
if (freq_index == 2U && sys_dvfs) {
|
||||||
|
upower_pmic_i2c_write(0x22, 0x28);
|
||||||
|
}
|
||||||
|
|
||||||
/* Enable LPI_WAKEUP_EN */
|
/* Enable LPI_WAKEUP_EN */
|
||||||
ddr_ctl_144 = mmio_read_32(IMX_DDRC_BASE + DENALI_CTL_144);
|
ddr_ctl_144 = mmio_read_32(IMX_DDRC_BASE + DENALI_CTL_144);
|
||||||
mmio_setbits_32(IMX_DDRC_BASE + DENALI_CTL_144, LPI_WAKEUP_EN);
|
mmio_setbits_32(IMX_DDRC_BASE + DENALI_CTL_144, LPI_WAKEUP_EN);
|
||||||
|
@ -563,6 +574,13 @@ int lpddr4_dfs(uint32_t freq_index)
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* decrease the BUCK3 voltage after frequency changed to lower
|
||||||
|
* and APD in ND_MODE
|
||||||
|
*/
|
||||||
|
if (freq_index == 1U && sys_dvfs) {
|
||||||
|
upower_pmic_i2c_write(0x22, 0x20);
|
||||||
|
}
|
||||||
|
|
||||||
/* DFS done successfully */
|
/* DFS done successfully */
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
@ -606,6 +624,7 @@ int dram_dvfs_handler(uint32_t smc_fid, void *handle,
|
||||||
|
|
||||||
/* start lpddr frequency scaling */
|
/* start lpddr frequency scaling */
|
||||||
in_progress = true;
|
in_progress = true;
|
||||||
|
sys_dvfs = x3 ? true : false;
|
||||||
dsb();
|
dsb();
|
||||||
|
|
||||||
/* notify other core wait for scaling done */
|
/* notify other core wait for scaling done */
|
||||||
|
|
|
@ -145,3 +145,57 @@ int upower_read_temperature(uint32_t sensor_id, int32_t *temperature)
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
int upower_pmic_i2c_write(uint32_t reg_addr, uint32_t reg_val)
|
||||||
|
{
|
||||||
|
int ret, ret_val;
|
||||||
|
upwr_resp_t err_code;
|
||||||
|
|
||||||
|
ret = upwr_xcp_i2c_access(0x32, 1, 1, reg_addr, reg_val, NULL);
|
||||||
|
if (ret) {
|
||||||
|
WARN("pmic i2c read failed ret %d\n", ret);
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
|
upower_wait_resp();
|
||||||
|
ret = upwr_poll_req_status(UPWR_SG_EXCEPT, NULL, &err_code, &ret_val, 1000);
|
||||||
|
if (ret != UPWR_REQ_OK) {
|
||||||
|
WARN("i2c poll Failure %d, err_code %d, ret_val 0x%x\n",
|
||||||
|
ret, err_code, ret_val);
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
|
VERBOSE("PMIC write reg[0x%x], val[0x%x]\n", reg_addr, reg_val);
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
int upower_pmic_i2c_read(uint32_t reg_addr, uint32_t *reg_val)
|
||||||
|
{
|
||||||
|
int ret, ret_val;
|
||||||
|
upwr_resp_t err_code;
|
||||||
|
|
||||||
|
if (reg_val == NULL) {
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
ret = upwr_xcp_i2c_access(0x32, -1, 1, reg_addr, 0, NULL);
|
||||||
|
if (ret) {
|
||||||
|
WARN("pmic i2c read failed ret %d\n", ret);
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
|
upower_wait_resp();
|
||||||
|
ret = upwr_poll_req_status(UPWR_SG_EXCEPT, NULL, &err_code, &ret_val, 1000);
|
||||||
|
if (ret != UPWR_REQ_OK) {
|
||||||
|
WARN("i2c poll Failure %d, err_code %d, ret_val 0x%x\n",
|
||||||
|
ret, err_code, ret_val);
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
|
*reg_val = ret_val;
|
||||||
|
|
||||||
|
VERBOSE("PMIC read reg[0x%x], val[0x%x]\n", reg_addr, *reg_val);
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
Loading…
Add table
Reference in a new issue