Commit 4bd1d3fa authored by Derek Basehore's avatar Derek Basehore Committed by Xing Zheng
Browse files

rockchip: rk3399: add support for ddrfreq suspend/resume



This patch sets the frequency configuration of the next DRAM DFS index
to the configuration of the current index. This does not perform a
frequency transition. It just configures registers so the training on
resume for both indices will be correct.
Signed-off-by: default avatarDerek Basehore <dbasehore@chromium.org>
Signed-off-by: default avatarXing Zheng <zhengxing@rock-chips.com>
parent 977001aa
...@@ -62,12 +62,20 @@ static const struct pll_div dpll_rates_table[] = { ...@@ -62,12 +62,20 @@ static const struct pll_div dpll_rates_table[] = {
struct rk3399_dram_status { struct rk3399_dram_status {
uint32_t current_index; uint32_t current_index;
uint32_t index_freq[2]; uint32_t index_freq[2];
uint32_t boot_freq;
uint32_t low_power_stat; uint32_t low_power_stat;
struct timing_related_config timing_config; struct timing_related_config timing_config;
struct drv_odt_lp_config drv_odt_lp_cfg; struct drv_odt_lp_config drv_odt_lp_cfg;
}; };
struct rk3399_saved_status {
uint32_t freq;
uint32_t low_power_stat;
uint32_t odt;
};
static struct rk3399_dram_status rk3399_dram_status; static struct rk3399_dram_status rk3399_dram_status;
static struct rk3399_saved_status rk3399_suspend_status;
static uint32_t wrdqs_delay_val[2][2][4]; static uint32_t wrdqs_delay_val[2][2][4];
static struct rk3399_sdram_default_config ddr3_default_config = { static struct rk3399_sdram_default_config ddr3_default_config = {
...@@ -226,6 +234,7 @@ static void sdram_timing_cfg_init(struct timing_related_config *ptiming_config, ...@@ -226,6 +234,7 @@ static void sdram_timing_cfg_init(struct timing_related_config *ptiming_config,
ptiming_config->dramds = drv_config->dram_side_drv; ptiming_config->dramds = drv_config->dram_side_drv;
ptiming_config->dramodt = drv_config->dram_side_dq_odt; ptiming_config->dramodt = drv_config->dram_side_dq_odt;
ptiming_config->caodt = drv_config->dram_side_ca_odt; ptiming_config->caodt = drv_config->dram_side_ca_odt;
ptiming_config->odt = (mmio_read_32(PHY_REG(0, 5)) >> 16) & 0x1;
} }
struct lat_adj_pair { struct lat_adj_pair {
...@@ -1847,7 +1856,7 @@ static void dram_low_power_config(void) ...@@ -1847,7 +1856,7 @@ static void dram_low_power_config(void)
void dram_dfs_init(void) void dram_dfs_init(void)
{ {
uint32_t trefi0, trefi1; uint32_t trefi0, trefi1, boot_freq;
/* get sdram config for os reg */ /* get sdram config for os reg */
get_dram_drv_odt_val(sdram_config.dramtype, get_dram_drv_odt_val(sdram_config.dramtype,
...@@ -1867,8 +1876,15 @@ void dram_dfs_init(void) ...@@ -1867,8 +1876,15 @@ void dram_dfs_init(void)
rk3399_dram_status.index_freq[0] /= 2; rk3399_dram_status.index_freq[0] /= 2;
rk3399_dram_status.index_freq[1] /= 2; rk3399_dram_status.index_freq[1] /= 2;
} }
rk3399_dram_status.index_freq[(rk3399_dram_status.current_index + 1) boot_freq =
& 0x1] = 0; rk3399_dram_status.index_freq[rk3399_dram_status.current_index];
boot_freq = dpll_rates_table[to_get_clk_index(boot_freq)].mhz;
rk3399_dram_status.boot_freq = boot_freq;
rk3399_dram_status.index_freq[rk3399_dram_status.current_index] =
boot_freq;
rk3399_dram_status.index_freq[(rk3399_dram_status.current_index + 1) &
0x1] = 0;
rk3399_dram_status.low_power_stat = 0;
/* /*
* following register decide if NOC stall the access request * following register decide if NOC stall the access request
* or return error when NOC being idled. when doing ddr frequency * or return error when NOC being idled. when doing ddr frequency
...@@ -1883,6 +1899,10 @@ void dram_dfs_init(void) ...@@ -1883,6 +1899,10 @@ void dram_dfs_init(void)
mmio_write_32(GRF_BASE + GRF_SOC_CON(3), 0xffffffff); mmio_write_32(GRF_BASE + GRF_SOC_CON(3), 0xffffffff);
mmio_write_32(GRF_BASE + GRF_SOC_CON(4), 0x70007000); mmio_write_32(GRF_BASE + GRF_SOC_CON(4), 0x70007000);
/* Disable multicast */
mmio_clrbits_32(PHY_REG(0, 896), 1);
mmio_clrbits_32(PHY_REG(1, 896), 1);
dram_low_power_config(); dram_low_power_config();
} }
...@@ -1974,7 +1994,7 @@ static uint32_t prepare_ddr_timing(uint32_t mhz) ...@@ -1974,7 +1994,7 @@ static uint32_t prepare_ddr_timing(uint32_t mhz)
index = (rk3399_dram_status.current_index + 1) & 0x1; index = (rk3399_dram_status.current_index + 1) & 0x1;
if (rk3399_dram_status.index_freq[index] == mhz) if (rk3399_dram_status.index_freq[index] == mhz)
goto out; return index;
/* /*
* checking if having available gate traiing timing for * checking if having available gate traiing timing for
...@@ -1990,9 +2010,6 @@ static uint32_t prepare_ddr_timing(uint32_t mhz) ...@@ -1990,9 +2010,6 @@ static uint32_t prepare_ddr_timing(uint32_t mhz)
&dram_timing, index); &dram_timing, index);
rk3399_dram_status.index_freq[index] = mhz; rk3399_dram_status.index_freq[index] = mhz;
out:
gen_rk3399_enable_training(rk3399_dram_status.timing_config.ch_cnt,
mhz);
return index; return index;
} }
...@@ -2024,6 +2041,8 @@ uint32_t ddr_set_rate(uint32_t hz) ...@@ -2024,6 +2041,8 @@ uint32_t ddr_set_rate(uint32_t hz)
mhz = dpll_rates_table[index].mhz; mhz = dpll_rates_table[index].mhz;
ddr_index = prepare_ddr_timing(mhz); ddr_index = prepare_ddr_timing(mhz);
gen_rk3399_enable_training(rk3399_dram_status.timing_config.ch_cnt,
mhz);
if (ddr_index > 1) if (ddr_index > 1)
goto out; goto out;
...@@ -2051,3 +2070,57 @@ uint32_t ddr_round_rate(uint32_t hz) ...@@ -2051,3 +2070,57 @@ uint32_t ddr_round_rate(uint32_t hz)
return dpll_rates_table[index].mhz * 1000 * 1000; return dpll_rates_table[index].mhz * 1000 * 1000;
} }
void ddr_prepare_for_sys_suspend(void)
{
uint32_t mhz =
rk3399_dram_status.index_freq[rk3399_dram_status.current_index];
/*
* If we're not currently at the boot (assumed highest) frequency, we
* need to change frequencies to configure out current index.
*/
rk3399_suspend_status.freq = mhz;
exit_low_power();
rk3399_suspend_status.low_power_stat =
rk3399_dram_status.low_power_stat;
rk3399_suspend_status.odt = rk3399_dram_status.timing_config.odt;
rk3399_dram_status.low_power_stat = 0;
rk3399_dram_status.timing_config.odt = 1;
if (mhz != rk3399_dram_status.boot_freq)
ddr_set_rate(rk3399_dram_status.boot_freq * 1000 * 1000);
/*
* This will configure the other index to be the same frequency as the
* current one. We retrain both indices on resume, so both have to be
* setup for the same frequency.
*/
prepare_ddr_timing(rk3399_dram_status.boot_freq);
}
void ddr_prepare_for_sys_resume(void)
{
/* Disable multicast */
mmio_clrbits_32(PHY_REG(0, 896), 1);
mmio_clrbits_32(PHY_REG(1, 896), 1);
/* The suspend code changes the current index, so reset it now. */
rk3399_dram_status.current_index =
(mmio_read_32(CTL_REG(0, 111)) >> 16) & 0x3;
rk3399_dram_status.low_power_stat =
rk3399_suspend_status.low_power_stat;
rk3399_dram_status.timing_config.odt = rk3399_suspend_status.odt;
/*
* Set the saved frequency from suspend if it's different than the
* current frequency.
*/
if (rk3399_suspend_status.freq !=
rk3399_dram_status.index_freq[rk3399_dram_status.current_index]) {
ddr_set_rate(rk3399_suspend_status.freq * 1000 * 1000);
return;
}
gen_rk3399_set_odt(rk3399_dram_status.timing_config.odt);
resume_low_power(rk3399_dram_status.low_power_stat);
}
...@@ -66,4 +66,7 @@ uint32_t ddr_round_rate(uint32_t hz); ...@@ -66,4 +66,7 @@ uint32_t ddr_round_rate(uint32_t hz);
uint32_t ddr_get_rate(void); uint32_t ddr_get_rate(void);
uint32_t dram_set_odt_pd(uint32_t arg0, uint32_t arg1, uint32_t arg2); uint32_t dram_set_odt_pd(uint32_t arg0, uint32_t arg1, uint32_t arg2);
void dram_dfs_init(void); void dram_dfs_init(void);
void ddr_prepare_for_sys_suspend(void);
void ddr_prepare_for_sys_resume(void);
#endif #endif
...@@ -571,14 +571,15 @@ static __sramfunc void pctl_cfg(uint32_t ch, ...@@ -571,14 +571,15 @@ static __sramfunc void pctl_cfg(uint32_t ch,
sram_regcpy(PHY_REG(ch, 768), (uintptr_t)&params_phy[768], 38); sram_regcpy(PHY_REG(ch, 768), (uintptr_t)&params_phy[768], 38);
} }
static __sramfunc int dram_switch_to_phy_index1( static __sramfunc int dram_switch_to_next_index(
struct rk3399_sdram_params *sdram_params) struct rk3399_sdram_params *sdram_params)
{ {
uint32_t ch, ch_count; uint32_t ch, ch_count;
uint32_t fn = ((mmio_read_32(CTL_REG(0, 111)) >> 16) + 1) & 0x1;
mmio_write_32(CIC_BASE + CIC_CTRL0, mmio_write_32(CIC_BASE + CIC_CTRL0,
(((0x3 << 4) | (1 << 2) | 1) << 16) | (((0x3 << 4) | (1 << 2) | 1) << 16) |
(1 << 4) | (1 << 2) | 1); (fn << 4) | (1 << 2) | 1);
while (!(mmio_read_32(CIC_BASE + CIC_STATUS0) & (1 << 2))) while (!(mmio_read_32(CIC_BASE + CIC_STATUS0) & (1 << 2)))
; ;
...@@ -591,7 +592,7 @@ static __sramfunc int dram_switch_to_phy_index1( ...@@ -591,7 +592,7 @@ static __sramfunc int dram_switch_to_phy_index1(
/* LPDDR4 f2 cann't do training, all training will fail */ /* LPDDR4 f2 cann't do training, all training will fail */
for (ch = 0; ch < ch_count; ch++) { for (ch = 0; ch < ch_count; ch++) {
mmio_clrsetbits_32(PHY_REG(ch, 896), (0x3 << 8) | 1, mmio_clrsetbits_32(PHY_REG(ch, 896), (0x3 << 8) | 1,
1 << 8); fn << 8);
/* data_training failed */ /* data_training failed */
if (data_training(ch, sdram_params, PI_FULL_TRAINING)) if (data_training(ch, sdram_params, PI_FULL_TRAINING))
...@@ -754,5 +755,5 @@ retry: ...@@ -754,5 +755,5 @@ retry:
dram_all_config(sdram_params); dram_all_config(sdram_params);
/* Switch to index 1 and prepare for DDR frequency switch. */ /* Switch to index 1 and prepare for DDR frequency switch. */
dram_switch_to_phy_index1(sdram_params); dram_switch_to_next_index(sdram_params);
} }
...@@ -33,6 +33,7 @@ ...@@ -33,6 +33,7 @@
#include <bakery_lock.h> #include <bakery_lock.h>
#include <debug.h> #include <debug.h>
#include <delay_timer.h> #include <delay_timer.h>
#include <dfs.h>
#include <errno.h> #include <errno.h>
#include <gpio.h> #include <gpio.h>
#include <mmio.h> #include <mmio.h>
...@@ -1076,6 +1077,7 @@ static int sys_pwr_domain_suspend(void) ...@@ -1076,6 +1077,7 @@ static int sys_pwr_domain_suspend(void)
uint32_t wait_cnt = 0; uint32_t wait_cnt = 0;
uint32_t status = 0; uint32_t status = 0;
ddr_prepare_for_sys_suspend();
dmc_save(); dmc_save();
pmu_scu_b_pwrdn(); pmu_scu_b_pwrdn();
...@@ -1219,6 +1221,8 @@ static int sys_pwr_domain_resume(void) ...@@ -1219,6 +1221,8 @@ static int sys_pwr_domain_resume(void)
m0_stop(); m0_stop();
ddr_prepare_for_sys_resume();
return 0; return 0;
} }
......
Markdown is supported
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment