]> git.baikalelectronics.ru Git - arm-tf.git/commitdiff
rockchip: rk3399: add support for ddrfreq suspend/resume
authorDerek Basehore <dbasehore@chromium.org>
Fri, 24 Feb 2017 06:31:36 +0000 (14:31 +0800)
committerXing Zheng <zhengxing@rock-chips.com>
Fri, 24 Feb 2017 12:07:44 +0000 (20:07 +0800)
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: Derek Basehore <dbasehore@chromium.org>
Signed-off-by: Xing Zheng <zhengxing@rock-chips.com>
plat/rockchip/rk3399/drivers/dram/dfs.c
plat/rockchip/rk3399/drivers/dram/dfs.h
plat/rockchip/rk3399/drivers/dram/suspend.c
plat/rockchip/rk3399/drivers/pmu/pmu.c

index c093621d4f6628465d462d28090c5e94922578ab..1d7f0206d7de25f1b5babed266c6e075b21e275d 100644 (file)
@@ -62,12 +62,20 @@ static const struct pll_div dpll_rates_table[] = {
 struct rk3399_dram_status {
        uint32_t current_index;
        uint32_t index_freq[2];
+       uint32_t boot_freq;
        uint32_t low_power_stat;
        struct timing_related_config timing_config;
        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_saved_status rk3399_suspend_status;
 static uint32_t wrdqs_delay_val[2][2][4];
 
 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,
        ptiming_config->dramds = drv_config->dram_side_drv;
        ptiming_config->dramodt = drv_config->dram_side_dq_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 {
@@ -1847,7 +1856,7 @@ static void dram_low_power_config(void)
 
 void dram_dfs_init(void)
 {
-       uint32_t trefi0, trefi1;
+       uint32_t trefi0, trefi1, boot_freq;
 
        /* get sdram config for os reg */
        get_dram_drv_odt_val(sdram_config.dramtype,
@@ -1867,8 +1876,15 @@ void dram_dfs_init(void)
                rk3399_dram_status.index_freq[0] /= 2;
                rk3399_dram_status.index_freq[1] /= 2;
        }
-       rk3399_dram_status.index_freq[(rk3399_dram_status.current_index + 1)
-                                     & 0x1] = 0;
+       boot_freq =
+               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
         * or return error when NOC being idled. when doing ddr frequency
@@ -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(4), 0x70007000);
 
+       /* Disable multicast */
+       mmio_clrbits_32(PHY_REG(0, 896), 1);
+       mmio_clrbits_32(PHY_REG(1, 896), 1);
+
        dram_low_power_config();
 }
 
@@ -1974,7 +1994,7 @@ static uint32_t prepare_ddr_timing(uint32_t mhz)
 
        index = (rk3399_dram_status.current_index + 1) & 0x1;
        if (rk3399_dram_status.index_freq[index] == mhz)
-               goto out;
+               return index;
 
        /*
         * checking if having available gate traiing timing for
@@ -1990,9 +2010,6 @@ static uint32_t prepare_ddr_timing(uint32_t mhz)
                              &dram_timing, index);
        rk3399_dram_status.index_freq[index] = mhz;
 
-out:
-       gen_rk3399_enable_training(rk3399_dram_status.timing_config.ch_cnt,
-                                  mhz);
        return index;
 }
 
@@ -2024,6 +2041,8 @@ uint32_t ddr_set_rate(uint32_t hz)
        mhz = dpll_rates_table[index].mhz;
 
        ddr_index = prepare_ddr_timing(mhz);
+       gen_rk3399_enable_training(rk3399_dram_status.timing_config.ch_cnt,
+                                  mhz);
        if (ddr_index > 1)
                goto out;
 
@@ -2051,3 +2070,57 @@ uint32_t ddr_round_rate(uint32_t hz)
 
        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);
+}
index ab7276fa63468c9f99db249450d9b85672c33b58..3204ae74c82268b134d63c1be7e2f261c195338c 100644 (file)
@@ -66,4 +66,7 @@ uint32_t ddr_round_rate(uint32_t hz);
 uint32_t ddr_get_rate(void);
 uint32_t dram_set_odt_pd(uint32_t arg0, uint32_t arg1, uint32_t arg2);
 void dram_dfs_init(void);
+void ddr_prepare_for_sys_suspend(void);
+void ddr_prepare_for_sys_resume(void);
+
 #endif
index f408d676c64cb81ad2f5257ad766e1c3be23f358..02768fd64d360d917de4fdc9abafcea1873c46f2 100644 (file)
@@ -571,14 +571,15 @@ static __sramfunc void pctl_cfg(uint32_t ch,
        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)
 {
        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,
                      (((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)))
                ;
 
@@ -591,7 +592,7 @@ static __sramfunc int dram_switch_to_phy_index1(
        /* LPDDR4 f2 cann't do training, all training will fail */
        for (ch = 0; ch < ch_count; ch++) {
                mmio_clrsetbits_32(PHY_REG(ch, 896), (0x3 << 8) | 1,
-                                  1 << 8);
+                                  fn << 8);
 
                /* data_training failed */
                if (data_training(ch, sdram_params, PI_FULL_TRAINING))
@@ -754,5 +755,5 @@ retry:
        dram_all_config(sdram_params);
 
        /* Switch to index 1 and prepare for DDR frequency switch. */
-       dram_switch_to_phy_index1(sdram_params);
+       dram_switch_to_next_index(sdram_params);
 }
index 6aeabfe5b5587d0d592579606460fb2704afc598..b8afd387acf3f5768f5f1fff9aeba18d71ca342f 100644 (file)
@@ -33,6 +33,7 @@
 #include <bakery_lock.h>
 #include <debug.h>
 #include <delay_timer.h>
+#include <dfs.h>
 #include <errno.h>
 #include <gpio.h>
 #include <mmio.h>
@@ -1076,6 +1077,7 @@ static int sys_pwr_domain_suspend(void)
        uint32_t wait_cnt = 0;
        uint32_t status = 0;
 
+       ddr_prepare_for_sys_suspend();
        dmc_save();
        pmu_scu_b_pwrdn();
 
@@ -1219,6 +1221,8 @@ static int sys_pwr_domain_resume(void)
 
        m0_stop();
 
+       ddr_prepare_for_sys_resume();
+
        return 0;
 }