rockchip/rk3399: save and restore pd_alive register
authorLin Huang <hl@rock-chips.com>
Thu, 18 May 2017 10:04:25 +0000 (18:04 +0800)
committerCaesar Wang <wxt@rock-chips.com>
Tue, 29 Aug 2017 07:00:40 +0000 (15:00 +0800)
pd_alive control cru, grf, timer, gpio and wdt, when
turn off logic power rail, these register value will
back to reset value, we need to save them value in suspend
and restore them when resuem, since timer will reinitial
in kernel, so it not need to save/restore.

Change-Id: I0fc2a011d3cdc04b66ffbf728e769eb28b51ee38
Signed-off-by: Lin Huang <hl@rock-chips.com>
plat/rockchip/common/include/plat_private.h
plat/rockchip/rk3399/drivers/gpio/rk3399_gpio.c
plat/rockchip/rk3399/drivers/pmu/pmu.c
plat/rockchip/rk3399/drivers/soc/soc.h
plat/rockchip/rk3399/include/shared/addressmap_shared.h

index 290811a2657b546331b70414a645ff15ba7c9a42..545677352f099ba64417bcb6ae2f03d84aeab7c2 100644 (file)
@@ -90,6 +90,8 @@ struct gpio_info *plat_get_rockchip_gpio_poweroff(void);
 struct gpio_info *plat_get_rockchip_suspend_gpio(uint32_t *count);
 struct apio_info *plat_get_rockchip_suspend_apio(void);
 void plat_rockchip_gpio_init(void);
+void plat_rockchip_save_gpio(void);
+void plat_rockchip_restore_gpio(void);
 
 int rockchip_soc_cores_pwr_dm_on(unsigned long mpidr, uint64_t entrypoint);
 int rockchip_soc_hlvl_pwr_dm_off(uint32_t lvl,
index d5a26609321d681a274b809255621f31aec7cbe6..e74c4d91a7de2cf85e781c0b467c782c1984cb6d 100644 (file)
@@ -22,10 +22,29 @@ uint32_t gpio_port[] = {
        GPIO4_BASE,
 };
 
+struct {
+       uint32_t swporta_dr;
+       uint32_t swporta_ddr;
+       uint32_t inten;
+       uint32_t intmask;
+       uint32_t inttype_level;
+       uint32_t int_polarity;
+       uint32_t debounce;
+       uint32_t ls_sync;
+} store_gpio[3];
+
+static uint32_t store_grf_gpio[(GRF_GPIO2D_HE - GRF_GPIO2A_IOMUX) / 4 + 1];
+
 #define SWPORTA_DR     0x00
 #define SWPORTA_DDR    0x04
-#define EXT_PORTA      0x50
+#define INTEN          0x30
+#define INTMASK                0x34
+#define INTTYPE_LEVEL  0x38
+#define INT_POLARITY   0x3c
+#define DEBOUNCE       0x48
+#define LS_SYNC                0x60
 
+#define EXT_PORTA      0x50
 #define PMU_GPIO_PORT0 0
 #define PMU_GPIO_PORT1 1
 #define GPIO_PORT2     2
@@ -290,6 +309,99 @@ static void set_value(int gpio, int value)
        gpio_put_clock(gpio, clock_state);
 }
 
+void plat_rockchip_save_gpio(void)
+{
+       int i;
+       uint32_t cru_gate_save;
+
+       cru_gate_save = mmio_read_32(CRU_BASE + CRU_CLKGATE_CON(31));
+
+       /*
+        * when shutdown logic, we need to save gpio2 ~ gpio4 register,
+        * we need to enable gpio2 ~ gpio4 clock here, since it may be gating,
+        * and we do not care gpio0 and gpio1 clock gate, since we never
+        * gating them
+        */
+       mmio_write_32(CRU_BASE + CRU_CLKGATE_CON(31),
+                     BITS_WITH_WMASK(0, 0x07, PCLK_GPIO2_GATE_SHIFT));
+
+       /*
+        * since gpio0, gpio1 are pmugpio, they will keep ther value
+        * when shutdown logic power rail, so only need to save gpio2 ~ gpio4
+        * register value
+        */
+       for (i = 2; i < 5; i++) {
+               store_gpio[i - 2].swporta_dr =
+                       mmio_read_32(gpio_port[i] + SWPORTA_DR);
+               store_gpio[i - 2].swporta_ddr =
+                       mmio_read_32(gpio_port[i] + SWPORTA_DDR);
+               store_gpio[i - 2].inten =
+                       mmio_read_32(gpio_port[i] + INTEN);
+               store_gpio[i - 2].intmask =
+                       mmio_read_32(gpio_port[i] + INTMASK);
+               store_gpio[i - 2].inttype_level =
+                       mmio_read_32(gpio_port[i] + INTTYPE_LEVEL);
+               store_gpio[i - 2].int_polarity =
+                       mmio_read_32(gpio_port[i] + INT_POLARITY);
+               store_gpio[i - 2].debounce =
+                       mmio_read_32(gpio_port[i] + DEBOUNCE);
+               store_gpio[i - 2].ls_sync =
+                       mmio_read_32(gpio_port[i] + LS_SYNC);
+       }
+       mmio_write_32(CRU_BASE + CRU_CLKGATE_CON(31),
+                       cru_gate_save | REG_SOC_WMSK);
+
+       /*
+        * gpio0, gpio1 in pmuiomux, they will keep ther value
+        * when shutdown logic power rail, so only need to save gpio2 ~ gpio4
+        * iomux register value
+        */
+       for (i = 0; i < ARRAY_SIZE(store_grf_gpio); i++)
+               store_grf_gpio[i] =
+                       mmio_read_32(GRF_BASE + GRF_GPIO2A_IOMUX + i * 4);
+}
+
+void plat_rockchip_restore_gpio(void)
+{
+       int i;
+       uint32_t cru_gate_save;
+
+       for (i = 0; i < ARRAY_SIZE(store_grf_gpio); i++)
+               mmio_write_32(GRF_BASE + GRF_GPIO2A_IOMUX + i * 4,
+                     REG_SOC_WMSK | store_grf_gpio[i]);
+
+       cru_gate_save = mmio_read_32(CRU_BASE + CRU_CLKGATE_CON(31));
+
+       /*
+        * when shutdown logic, we need to save gpio2 ~ gpio4 register,
+        * we need to enable gpio2 ~ gpio4 clock here, since it may be gating,
+        * and we do not care gpio0 and gpio1 clock gate, since we never
+        * gating them
+        */
+       mmio_write_32(CRU_BASE + CRU_CLKGATE_CON(31),
+                     BITS_WITH_WMASK(0, 0x07, PCLK_GPIO2_GATE_SHIFT));
+
+       for (i = 2; i < 5; i++) {
+               mmio_write_32(gpio_port[i] + SWPORTA_DR,
+                               store_gpio[i - 2].swporta_dr);
+               mmio_write_32(gpio_port[i] + SWPORTA_DDR,
+                               store_gpio[i - 2].swporta_ddr);
+               mmio_write_32(gpio_port[i] + INTEN, store_gpio[i - 2].inten);
+               mmio_write_32(gpio_port[i] + INTMASK,
+                               store_gpio[i - 2].intmask);
+               mmio_write_32(gpio_port[i] + INTTYPE_LEVEL,
+                               store_gpio[i - 2].inttype_level);
+               mmio_write_32(gpio_port[i] + INT_POLARITY,
+                               store_gpio[i - 2].int_polarity);
+               mmio_write_32(gpio_port[i] + DEBOUNCE,
+                               store_gpio[i - 2].debounce);
+               mmio_write_32(gpio_port[i] + LS_SYNC,
+                               store_gpio[i - 2].ls_sync);
+       }
+       mmio_write_32(CRU_BASE + CRU_CLKGATE_CON(31),
+                       cru_gate_save | REG_SOC_WMSK);
+}
+
 const gpio_ops_t rk3399_gpio_ops = {
        .get_direction = get_direction,
        .set_direction = set_direction,
index d97b0463b171b5d082ded73c32ba171a110a282b..7f246c2fd4a0fb32352ea3ab177d0aaa3850b063 100644 (file)
@@ -32,6 +32,19 @@ DEFINE_BAKERY_LOCK(rockchip_pd_lock);
 
 static uint32_t cpu_warm_boot_addr;
 static char store_sram[SRAM_BIN_LIMIT + SRAM_TEXT_LIMIT + SRAM_DATA_LIMIT];
+static uint32_t store_cru[CRU_SDIO0_CON1 / 4];
+static uint32_t store_usbphy0[7];
+static uint32_t store_usbphy1[7];
+static uint32_t store_grf_io_vsel;
+static uint32_t store_grf_soc_con0;
+static uint32_t store_grf_soc_con1;
+static uint32_t store_grf_soc_con2;
+static uint32_t store_grf_soc_con3;
+static uint32_t store_grf_soc_con4;
+static uint32_t store_grf_soc_con7;
+static uint32_t store_grf_ddrc_con[4];
+static uint32_t store_wdt0[2];
+static uint32_t store_wdt1[2];
 
 /*
  * There are two ways to powering on or off on core.
@@ -1132,6 +1145,161 @@ void resume_uart(void)
        mmio_write_32(PLAT_RK_UART_BASE + UART_MCR, uart_save.uart_mcr);
 }
 
+void save_usbphy(void)
+{
+       store_usbphy0[0] = mmio_read_32(GRF_BASE + GRF_USBPHY0_CTRL0);
+       store_usbphy0[1] = mmio_read_32(GRF_BASE + GRF_USBPHY0_CTRL2);
+       store_usbphy0[2] = mmio_read_32(GRF_BASE + GRF_USBPHY0_CTRL3);
+       store_usbphy0[3] = mmio_read_32(GRF_BASE + GRF_USBPHY0_CTRL12);
+       store_usbphy0[4] = mmio_read_32(GRF_BASE + GRF_USBPHY0_CTRL13);
+       store_usbphy0[5] = mmio_read_32(GRF_BASE + GRF_USBPHY0_CTRL15);
+       store_usbphy0[6] = mmio_read_32(GRF_BASE + GRF_USBPHY0_CTRL16);
+
+       store_usbphy1[0] = mmio_read_32(GRF_BASE + GRF_USBPHY1_CTRL0);
+       store_usbphy1[1] = mmio_read_32(GRF_BASE + GRF_USBPHY1_CTRL2);
+       store_usbphy1[2] = mmio_read_32(GRF_BASE + GRF_USBPHY1_CTRL3);
+       store_usbphy1[3] = mmio_read_32(GRF_BASE + GRF_USBPHY1_CTRL12);
+       store_usbphy1[4] = mmio_read_32(GRF_BASE + GRF_USBPHY1_CTRL13);
+       store_usbphy1[5] = mmio_read_32(GRF_BASE + GRF_USBPHY1_CTRL15);
+       store_usbphy1[6] = mmio_read_32(GRF_BASE + GRF_USBPHY1_CTRL16);
+}
+
+void restore_usbphy(void)
+{
+       mmio_write_32(GRF_BASE + GRF_USBPHY0_CTRL0,
+                     REG_SOC_WMSK | store_usbphy0[0]);
+       mmio_write_32(GRF_BASE + GRF_USBPHY0_CTRL2,
+                     REG_SOC_WMSK | store_usbphy0[1]);
+       mmio_write_32(GRF_BASE + GRF_USBPHY0_CTRL3,
+                     REG_SOC_WMSK | store_usbphy0[2]);
+       mmio_write_32(GRF_BASE + GRF_USBPHY0_CTRL12,
+                     REG_SOC_WMSK | store_usbphy0[3]);
+       mmio_write_32(GRF_BASE + GRF_USBPHY0_CTRL13,
+                     REG_SOC_WMSK | store_usbphy0[4]);
+       mmio_write_32(GRF_BASE + GRF_USBPHY0_CTRL15,
+                     REG_SOC_WMSK | store_usbphy0[5]);
+       mmio_write_32(GRF_BASE + GRF_USBPHY0_CTRL16,
+                     REG_SOC_WMSK | store_usbphy0[6]);
+
+       mmio_write_32(GRF_BASE + GRF_USBPHY1_CTRL0,
+                     REG_SOC_WMSK | store_usbphy1[0]);
+       mmio_write_32(GRF_BASE + GRF_USBPHY1_CTRL2,
+                     REG_SOC_WMSK | store_usbphy1[1]);
+       mmio_write_32(GRF_BASE + GRF_USBPHY1_CTRL3,
+                     REG_SOC_WMSK | store_usbphy1[2]);
+       mmio_write_32(GRF_BASE + GRF_USBPHY1_CTRL12,
+                     REG_SOC_WMSK | store_usbphy1[3]);
+       mmio_write_32(GRF_BASE + GRF_USBPHY1_CTRL13,
+                     REG_SOC_WMSK | store_usbphy1[4]);
+       mmio_write_32(GRF_BASE + GRF_USBPHY1_CTRL15,
+                     REG_SOC_WMSK | store_usbphy1[5]);
+       mmio_write_32(GRF_BASE + GRF_USBPHY1_CTRL16,
+                     REG_SOC_WMSK | store_usbphy1[6]);
+}
+
+void grf_register_save(void)
+{
+       int i;
+
+       store_grf_soc_con0 = mmio_read_32(GRF_BASE + GRF_SOC_CON(0));
+       store_grf_soc_con1 = mmio_read_32(GRF_BASE + GRF_SOC_CON(1));
+       store_grf_soc_con2 = mmio_read_32(GRF_BASE + GRF_SOC_CON(2));
+       store_grf_soc_con3 = mmio_read_32(GRF_BASE + GRF_SOC_CON(3));
+       store_grf_soc_con4 = mmio_read_32(GRF_BASE + GRF_SOC_CON(4));
+       store_grf_soc_con7 = mmio_read_32(GRF_BASE + GRF_SOC_CON(7));
+
+       for (i = 0; i < 4; i++)
+               store_grf_ddrc_con[i] =
+                       mmio_read_32(GRF_BASE + GRF_DDRC0_CON0 + i * 4);
+
+       store_grf_io_vsel = mmio_read_32(GRF_BASE + GRF_IO_VSEL);
+}
+
+void grf_register_restore(void)
+{
+       int i;
+
+       mmio_write_32(GRF_BASE + GRF_SOC_CON(0),
+                     REG_SOC_WMSK | store_grf_soc_con0);
+       mmio_write_32(GRF_BASE + GRF_SOC_CON(1),
+                     REG_SOC_WMSK | store_grf_soc_con1);
+       mmio_write_32(GRF_BASE + GRF_SOC_CON(2),
+                     REG_SOC_WMSK | store_grf_soc_con2);
+       mmio_write_32(GRF_BASE + GRF_SOC_CON(3),
+                     REG_SOC_WMSK | store_grf_soc_con3);
+       mmio_write_32(GRF_BASE + GRF_SOC_CON(4),
+                     REG_SOC_WMSK | store_grf_soc_con4);
+       mmio_write_32(GRF_BASE + GRF_SOC_CON(7),
+                     REG_SOC_WMSK | store_grf_soc_con7);
+
+       for (i = 0; i < 4; i++)
+               mmio_write_32(GRF_BASE + GRF_DDRC0_CON0 + i * 4,
+                             REG_SOC_WMSK | store_grf_ddrc_con[i]);
+
+       mmio_write_32(GRF_BASE + GRF_IO_VSEL, REG_SOC_WMSK | store_grf_io_vsel);
+}
+
+void cru_register_save(void)
+{
+       int i;
+
+       for (i = 0; i <= CRU_SDIO0_CON1; i = i + 4)
+               store_cru[i / 4] = mmio_read_32(CRU_BASE + i);
+}
+
+void cru_register_restore(void)
+{
+       int i;
+
+       for (i = 0; i <= CRU_SDIO0_CON1; i = i + 4) {
+
+               /*
+                * since DPLL, CRU_CLKSEL_CON6 have been restore in
+                * dmc_resume, ABPLL will resote later, so skip them
+                */
+               if ((i == CRU_CLKSEL_CON6) ||
+                   (i >= CRU_PLL_CON(ABPLL_ID, 0) &&
+                    i <= CRU_PLL_CON(DPLL_ID, 5)))
+                       continue;
+
+               if ((i == CRU_PLL_CON(ALPLL_ID, 2)) ||
+                   (i == CRU_PLL_CON(CPLL_ID, 2)) ||
+                   (i == CRU_PLL_CON(GPLL_ID, 2)) ||
+                   (i == CRU_PLL_CON(NPLL_ID, 2)) ||
+                   (i == CRU_PLL_CON(VPLL_ID, 2)))
+                       mmio_write_32(CRU_BASE + i, store_cru[i / 4]);
+               /*
+                * CRU_GLB_CNT_TH and CRU_CLKSEL_CON97~CRU_CLKSEL_CON107
+                * not need do high 16bit mask
+                */
+               else if ((i > 0x27c && i < 0x2b0) || (i == 0x508))
+                       mmio_write_32(CRU_BASE + i, store_cru[i / 4]);
+               else
+                       mmio_write_32(CRU_BASE + i,
+                                     REG_SOC_WMSK | store_cru[i / 4]);
+       }
+}
+
+void wdt_register_save(void)
+{
+       int i;
+
+       for (i = 0; i < 2; i++) {
+               store_wdt0[i] = mmio_read_32(WDT0_BASE + i * 4);
+               store_wdt1[i] = mmio_read_32(WDT1_BASE + i * 4);
+       }
+}
+
+void wdt_register_restore(void)
+{
+       int i;
+
+       for (i = 0; i < 2; i++) {
+               mmio_write_32(WDT0_BASE + i * 4, store_wdt0[i]);
+               mmio_write_32(WDT1_BASE + i * 4, store_wdt1[i]);
+       }
+}
+
 int rockchip_soc_sys_pwr_dm_suspend(void)
 {
        uint32_t wait_cnt = 0;
@@ -1141,6 +1309,9 @@ int rockchip_soc_sys_pwr_dm_suspend(void)
        dmc_suspend();
        pmu_scu_b_pwrdn();
 
+       /* need to save usbphy before shutdown PERIHP PD */
+       save_usbphy();
+
        pmu_power_domains_suspend();
        set_hw_idle(BIT(PMU_CLR_CENTER1) |
                    BIT(PMU_CLR_ALIVE) |
@@ -1196,8 +1367,12 @@ int rockchip_soc_sys_pwr_dm_suspend(void)
        suspend_apio();
        suspend_gpio();
        suspend_uart();
-
+       grf_register_save();
+       cru_register_save();
+       wdt_register_save();
        sram_save();
+       plat_rockchip_save_gpio();
+
        return 0;
 }
 
@@ -1206,6 +1381,10 @@ int rockchip_soc_sys_pwr_dm_resume(void)
        uint32_t wait_cnt = 0;
        uint32_t status = 0;
 
+       plat_rockchip_restore_gpio();
+       wdt_register_restore();
+       cru_register_restore();
+       grf_register_restore();
        resume_uart();
        resume_apio();
        resume_gpio();
@@ -1285,6 +1464,8 @@ int rockchip_soc_sys_pwr_dm_resume(void)
        plat_rockchip_gic_cpuif_enable();
        m0_stop();
 
+       restore_usbphy();
+
        ddr_prepare_for_sys_resume();
 
        return 0;
index 9680beab5b871025bfa6270aec9ab7dbebb49127..c418337313353eca9c05bb759e18846071cbb40b 100644 (file)
@@ -189,14 +189,35 @@ struct deepsleep_data_s {
 #define PWM_ENABLE                     (1 << 0)
 
 /* grf reg offset */
+#define GRF_USBPHY0_CTRL0      0x4480
+#define GRF_USBPHY0_CTRL2      0x4488
+#define GRF_USBPHY0_CTRL3      0x448c
+#define GRF_USBPHY0_CTRL12     0x44b0
+#define GRF_USBPHY0_CTRL13     0x44b4
+#define GRF_USBPHY0_CTRL15     0x44bc
+#define GRF_USBPHY0_CTRL16     0x44c0
+
+#define GRF_USBPHY1_CTRL0      0x4500
+#define GRF_USBPHY1_CTRL2      0x4508
+#define GRF_USBPHY1_CTRL3      0x450c
+#define GRF_USBPHY1_CTRL12     0x4530
+#define GRF_USBPHY1_CTRL13     0x4534
+#define GRF_USBPHY1_CTRL15     0x453c
+#define GRF_USBPHY1_CTRL16     0x4540
+
+#define GRF_GPIO2A_IOMUX       0xe000
+#define GRF_GPIO2D_HE          0xe18c
 #define GRF_DDRC0_CON0         0xe380
 #define GRF_DDRC0_CON1         0xe384
 #define GRF_DDRC1_CON0         0xe388
 #define GRF_DDRC1_CON1         0xe38c
 #define GRF_SOC_CON_BASE       0xe200
 #define GRF_SOC_CON(n)         (GRF_SOC_CON_BASE + (n) * 4)
+#define GRF_IO_VSEL            0xe640
 
+#define CRU_CLKSEL_CON0                0x0100
 #define CRU_CLKSEL_CON6                0x0118
+#define CRU_SDIO0_CON1         0x058c
 #define PMUCRU_CLKSEL_CON0     0x0080
 #define PMUCRU_CLKGATE_CON2    0x0108
 #define PMUCRU_SOFTRST_CON0    0x0110
index fe23e56909d362a741f68b3659f1c0c8b95a112a..dc5c8d5685d3a190b209e7e8a71c013e6210991e 100644 (file)
@@ -40,6 +40,9 @@
 #define GPIO2_BASE             (MMIO_BASE + 0x07780000)
 #define GPIO3_BASE             (MMIO_BASE + 0x07788000)
 #define GPIO4_BASE             (MMIO_BASE + 0x07790000)
+#define WDT1_BASE              (MMIO_BASE + 0x07840000)
+#define WDT0_BASE              (MMIO_BASE + 0x07848000)
+#define TIMER_BASE             (MMIO_BASE + 0x07850000)
 #define STIME_BASE             (MMIO_BASE + 0x07860000)
 #define SRAM_BASE              (MMIO_BASE + 0x078C0000)
 #define SERVICE_NOC_0_BASE     (MMIO_BASE + 0x07A50000)