From b992ababc8e57707bbcd102be6f539bc750a65b8 Mon Sep 17 00:00:00 2001 From: xxx Date: Thu, 13 Mar 2014 15:24:12 +0800 Subject: [PATCH] rk3188 pm support --- arch/arm/boot/dts/rk3188-clocks.dtsi | 13 + arch/arm/boot/dts/rk3188.dtsi | 21 +- arch/arm/mach-rockchip/pm-rk3188.c | 652 ++++++++++++++++++ arch/arm/mach-rockchip/rk3188.c | 4 + include/dt-bindings/pinctrl/rockchip-rk3188.h | 3 + 5 files changed, 692 insertions(+), 1 deletion(-) create mode 100755 arch/arm/mach-rockchip/pm-rk3188.c diff --git a/arch/arm/boot/dts/rk3188-clocks.dtsi b/arch/arm/boot/dts/rk3188-clocks.dtsi index f4927b18936b..3910ed29e671 100755 --- a/arch/arm/boot/dts/rk3188-clocks.dtsi +++ b/arch/arm/boot/dts/rk3188-clocks.dtsi @@ -84,6 +84,7 @@ clock_regs { compatible = "rockchip,rk-clock-regs"; + reg = <0x0000 0x3ff>; #address-cells = <1>; #size-cells = <1>; ranges; @@ -1180,6 +1181,7 @@ "reserved", "clk_spdif_div", "clk_spdif_frac", "g_testclk"; + rockchip,suspend-clkgating-setting=<0x00bf 0x00bf>; #clock-cells = <1>; }; @@ -1211,6 +1213,7 @@ "clk_uart2_div", "clk_uart2_frac", "clk_uart3_div", "clk_uart3_frac"; + rockchip,suspend-clkgating-setting=<0x0 0x0>; #clock-cells = <1>; }; @@ -1242,6 +1245,8 @@ "g_mac_lbtest", "clk_sdio", "clk_emmc", "reserved"; + //rockchip,suspend-clkgating-setting=<0x1f 0x1b>; + rockchip,suspend-clkgating-setting=<0x1f 0x1b>; #clock-cells = <1>; }; @@ -1277,6 +1282,7 @@ "g_h_vdpu", "reserved", "timer6", "clk_gpu"; + rockchip,suspend-clkgating-setting=<0x0 0x0>; #clock-cells = <1>; }; @@ -1314,6 +1320,8 @@ "g_a_intmem", "reserved", "g_h_imem1", "g_h_imem0"; + //rockchip,suspend-clkgating-setting=<0xd75e 0xd75e>; + rockchip,suspend-clkgating-setting=<0xd75e 0xd75e>; #clock-cells = <1>; }; @@ -1342,6 +1350,7 @@ "g_h_sdmmc0", "g_h_sdio", "g_h_emmc", "g_h_otg0"; + rockchip,suspend-clkgating-setting=<0x80 0x80>; #clock-cells = <1>; }; @@ -1372,6 +1381,7 @@ "g_h_vio_bus", "g_a_vio0"; + rockchip,suspend-clkgating-setting=<0x0 0x0>; #clock-cells = <1>; }; @@ -1402,6 +1412,7 @@ "g_p_spi0", "g_p_spi1", "g_p_saradc", "g_p_wdt"; + rockchip,suspend-clkgating-setting=<0x0 0x0>; #clock-cells = <1>; }; @@ -1431,6 +1442,7 @@ "g_p_gpio1", "g_p_gpio2", "g_p_gpio3", "g_a_gps"; + rockchip,suspend-clkgating-setting=<0x200 0x200>; #clock-cells = <1>; }; @@ -1450,6 +1462,7 @@ "g_clk_l2c", "g_a_vio1", "g_p_ddrpubl", "g_a_gpu"; + rockchip,suspend-clkgating-setting=<0x50 0x50>; #clock-cells = <1>; }; diff --git a/arch/arm/boot/dts/rk3188.dtsi b/arch/arm/boot/dts/rk3188.dtsi index 70880db67d48..6ec40efe08ad 100755 --- a/arch/arm/boot/dts/rk3188.dtsi +++ b/arch/arm/boot/dts/rk3188.dtsi @@ -2,6 +2,7 @@ #include "skeleton.dtsi" #include "rk3188-pinctrl.dtsi" #include +#include #include "rk3188_io_vol_domain.dtsi" #include @@ -441,7 +442,25 @@ <&clk_gpu 200000000>, <&aclk_lcdc0 300000000>, <&aclk_lcdc1 300000000>; }; - + rkpm_suspend { + compatible = "rockchip,rkpm_suspend"; + + // define value is in dt-bindint/suspend/rockchip-pm.h + rockchip,ctrbits = < + ( + RKPM_CTR_PWR_DMNS + |RKPM_CTR_GTCLKS + |RKPM_CTR_PLLS + |RKPM_CTR_SYSCLK_DIV + |RKPM_CTR_NORIDLE_MD + ) + >; + rockchip,pmic-gpios=< + RKPM_GPIOS_SETTING(GPIO0_A0,RKPM_GPIOS_OUTPUT,RKPM_GPIOS_OUT_H) + RKPM_GPIOS_SETTING(GPIO0_A1,RKPM_GPIOS_OUTPUT,RKPM_GPIOS_OUT_H) + >; + + }; fb: fb{ compatible = "rockchip,rk-fb"; rockchip,disp-mode = ; diff --git a/arch/arm/mach-rockchip/pm-rk3188.c b/arch/arm/mach-rockchip/pm-rk3188.c new file mode 100755 index 000000000000..2f69c4404ca9 --- /dev/null +++ b/arch/arm/mach-rockchip/pm-rk3188.c @@ -0,0 +1,652 @@ + +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include +#include +#include +#include + +#include +//#include +#include +#include +#include "pm.h" + + + +#define CPU 3188 +#include "sram.h" +#include "pm-pie.c" + + +#define PM_ERR(fmt, args...) printk(KERN_ERR fmt, ##args) +#define PM_LOG(fmt, args...) printk(KERN_ERR fmt, ##args) +#define PM_WARNING(fmt, args...) printk(KERN_WARNING fmt, ##args) + +#define cru_readl(offset) readl_relaxed(RK_CRU_VIRT + offset) +#define cru_writel(v, offset) do { writel_relaxed(v, RK_CRU_VIRT + offset); dsb(); } while (0) + +#define pmu_readl(offset) readl_relaxed(RK_PMU_VIRT + offset) +#define pmu_writel(v,offset) do { writel_relaxed(v, RK_PMU_VIRT + offset); dsb(); } while (0) + +#define grf_readl(offset) readl_relaxed(RK_GRF_VIRT + offset) +#define grf_writel(v, offset) do { writel_relaxed(v, RK_GRF_VIRT + offset); dsb(); } while (0) + +#define reg_readl(base) readl_relaxed(base) +#define reg_writel(v, base) do { writel_relaxed(v, base); dsb(); } while (0) + + +#define RK3188_CLK_GATING_OPS(ID) cru_writel((0x1<<((ID%16)+16))|(0x1<<(ID%16)),RK3188_CLK_GATEID_TO_CON(ID)) +#define RK3188_CLK_UNGATING_OPS(ID) cru_writel(0x1<<((ID%16)+16),RK3188_CLK_GATEID_TO_CON(ID)) + +/*************************cru define********************************************/ +/*******************CRU BITS*******************************/ +#define CRU_W_MSK(bits_shift, msk) ((msk) << ((bits_shift) + 16)) +#define CRU_SET_BITS(val, bits_shift, msk) (((val)&(msk)) << (bits_shift)) +#define CRU_W_MSK_SETBITS(val, bits_shift,msk) \ + (CRU_W_MSK(bits_shift, msk) | CRU_SET_BITS(val, bits_shift, msk)) + +#define RK3188_CRU_GET_REG_BITS_VAL(reg,bits_shift, msk) (((reg) >> (bits_shift))&(msk)) +#define RK3188_CRU_W_MSK(bits_shift, msk) ((msk) << ((bits_shift) + 16)) +#define RK3188_CRU_SET_BITS(val,bits_shift, msk) (((val)&(msk)) << (bits_shift)) + +#define RK3188_CRU_W_MSK_SETBITS(val,bits_shift,msk) \ + (RK3188_CRU_W_MSK(bits_shift, msk)|RK3188_CRU_SET_BITS(val,bits_shift, msk)) + + +/*******************RK3188_PLL CON3 BITS***************************/ + +#define RK3188_PLL_PWR_DN_MSK (1 << 1) +#define RK3188_PLL_PWR_DN_W_MSK (RK3188_PLL_PWR_DN_MSK << 16) +#define RK3188_PLL_PWR_DN (1 << 1) +#define RK3188_PLL_PWR_ON (0 << 1) + + + +/*******************CLKSEL0 BITS***************************/ +//RK3188_CORE_preiph div +#define RK3188_CORE_PERIPH_W_MSK (3 << 22) +#define RK3188_CORE_PERIPH_MSK (3 << 6) +#define RK3188_CORE_PERIPH_2 (0 << 6) +#define RK3188_CORE_PERIPH_4 (1 << 6) +#define RK3188_CORE_PERIPH_8 (2 << 6) +#define RK3188_CORE_PERIPH_16 (3 << 6) + +//clk_RK3188_CORE +#define RK3188_CORE_SEL_PLL_MSK (1 << 8) +#define RK3188_CORE_SEL_PLL_W_MSK (1 << 24) +#define RK3188_CORE_SEL_APLL (0 << 8) +#define RK3188_CORE_SEL_GPLL (1 << 8) + +#define RK3188_CORE_CLK_DIV_W_MSK (0x1F << 25) +#define RK3188_CORE_CLK_DIV_MSK (0x1F << 9) +#define RK3188_CORE_CLK_DIV(i) ((((i) - 1) & 0x1F) << 9) +#define RK3188_CORE_CLK_MAX_DIV 32 + +#define RK3188_CPU_SEL_PLL_MSK (1 << 5) +#define RK3188_CPU_SEL_PLL_W_MSK (1 << 21) +#define RK3188_CPU_SEL_APLL (0 << 5) +#define RK3188_CPU_SEL_GPLL (1 << 5) + +#define RK3188_CPU_CLK_DIV_W_MSK (0x1F << 16) +#define RK3188_CPU_CLK_DIV_MSK (0x1F) +#define RK3188_CPU_CLK_DIV(i) (((i) - 1) & 0x1F) + +/*******************CLKSEL1 BITS***************************/ +//aclk div +#define RK3188_GET_CORE_ACLK_VAL(reg) ((reg)>=4 ?8:((reg)+1)) + +#define RK3188_CORE_ACLK_W_MSK (7 << 19) +#define RK3188_CORE_ACLK_MSK (7 << 3) +#define RK3188_CORE_ACLK_11 (0 << 3) +#define RK3188_CORE_ACLK_21 (1 << 3) +#define RK3188_CORE_ACLK_31 (2 << 3) +#define RK3188_CORE_ACLK_41 (3 << 3) +#define RK3188_CORE_ACLK_81 (4 << 3) +//hclk div +#define RK3188_ACLK_HCLK_W_MSK (3 << 24) +#define RK3188_ACLK_HCLK_MSK (3 << 8) +#define RK3188_ACLK_HCLK_11 (0 << 8) +#define RK3188_ACLK_HCLK_21 (1 << 8) +#define RK3188_ACLK_HCLK_41 (2 << 8) +// pclk div +#define RK3188_ACLK_PCLK_W_MSK (3 << 28) +#define RK3188_ACLK_PCLK_MSK (3 << 12) +#define RK3188_ACLK_PCLK_11 (0 << 12) +#define RK3188_ACLK_PCLK_21 (1 << 12) +#define RK3188_ACLK_PCLK_41 (2 << 12) +#define RK3188_ACLK_PCLK_81 (3 << 12) +// ahb2apb div +#define RK3188_AHB2APB_W_MSK (3 << 30) +#define RK3188_AHB2APB_MSK (3 << 14) +#define RK3188_AHB2APB_11 (0 << 14) +#define RK3188_AHB2APB_21 (1 << 14) +#define RK3188_AHB2APB_41 (2 << 14) + +/*******************clksel10***************************/ + +#define RK3188_PERI_ACLK_DIV_MASK 0x1f +#define RK3188_PERI_ACLK_DIV_W_MSK (RK3188_PERI_ACLK_DIV_MASK << 16) +#define RK3188_PERI_ACLK_DIV(i) (((i) - 1) & RK3188_PERI_ACLK_DIV_MASK) +#define RK3188_PERI_ACLK_DIV_OFF 0 + +#define RK3188_PERI_HCLK_DIV_MASK 0x3 +#define RK3188_PERI_HCLK_DIV_OFF 8 + +#define RK3188_PERI_PCLK_DIV_MASK 0x3 +#define RK3188_PERI_PCLK_DIV_OFF 12 + + + +/*************************gate id**************************************/ +#define RK3188_CLK_GATEID(i) (16 * (i)) + +#define RK3188_CLK_GATEID_TO_CON(ID) RK3188_CRU_CLKGATES_CON((ID)/16) + +enum cru_clk_gate { + /* SCU CLK GATE 0 CON */ + RK3188_CLKGATE_CORE_PERIPH = RK3188_CLK_GATEID(0), + + RK3188_CLKGATE_TIMER0 = RK3188_CLK_GATEID(1), + RK3188_CLKGATE_UART0_SRC=RK3188_CLK_GATEID(1)+8, + RK3188_CLKGATE_UART0_FRAC_SRC, + + RK3188_CLKGATE_PCLK_UART0 = RK3188_CLK_GATEID(8), + + + RK3188_CLKGATE_CLK_CORE_DBG = RK3188_CLK_GATEID(9), + + RK3188_CLKGATE_MAX= RK3188_CLK_GATEID(10), +}; +/*******************************gpio define **********************************************/ +#define GPIO_INTEN 0x30 +#define GPIO_INTMASK 0x34 +#define GPIO_INTTYPE_LEVEL 0x38 +#define GPIO_INT_POLARITY 0x3c +#define GPIO_INT_STATUS 0x40 + +/*******************************common code for rkxxx*********************************/ + +static void inline uart_printch(char byte) +{ + u32 reg_save[2]; + u32 u_clk_id=(RK3188_CLKGATE_UART0_SRC+CONFIG_RK_DEBUG_UART); + u32 u_pclk_id=(RK3188_CLKGATE_PCLK_UART0+CONFIG_RK_DEBUG_UART); + + reg_save[0]=cru_readl(RK3188_CLK_GATEID_TO_CON(u_clk_id)); + reg_save[1]=cru_readl(RK3188_CLK_GATEID_TO_CON(u_pclk_id)); + RK3188_CLK_UNGATING_OPS(u_clk_id); + RK3188_CLK_UNGATING_OPS(u_pclk_id); + + rkpm_udelay(1); + + writel_relaxed(byte, RK_DEBUG_UART_VIRT); + dsb(); + + /* loop check LSR[6], Transmitter Empty bit */ + while (!(readl_relaxed(RK_DEBUG_UART_VIRT + 0x14) & 0x40)) + barrier(); + + cru_writel(reg_save[0]|0x1<<((u_pclk_id%16)+16),RK3188_CLK_GATEID_TO_CON(u_clk_id)); + cru_writel(reg_save[1]|0x1<<((u_pclk_id%16)+16),RK3188_CLK_GATEID_TO_CON(u_pclk_id)); + + if (byte == '\n') + uart_printch('\r'); +} + +void PIE_FUNC(sram_printch)(char byte) +{ + uart_printch(byte); +} + +static void ddr_printch(char byte) +{ + uart_printch(byte); +} +/*******************************clk gating config*******************************************/ +#define CLK_MSK_GATING(msk, con) cru_writel((msk << 16) | 0xffff, con) +#define CLK_MSK_UNGATING(msk, con) cru_writel(((~msk) << 16) | 0xffff, con) + + +static u32 clk_ungt_msk[RK3188_CRU_CLKGATES_CON_CNT];// first clk gating setting +static u32 clk_ungt_save[RK3188_CRU_CLKGATES_CON_CNT]; //first clk gating value saveing + + +u32 DEFINE_PIE_DATA(rkpm_clkgt_last_set[RK3188_CRU_CLKGATES_CON_CNT]); +static u32 *p_rkpm_clkgt_last_set; + +u32 DEFINE_PIE_DATA(rkpm_clkgt_last_save[RK3188_CRU_CLKGATES_CON_CNT]); +static u32 *p_rkpm_clkgt_last_save; + +void PIE_FUNC(gtclks_sram_suspend)(void) +{ + int i; + // u32 u_clk_id=(RK3188_CLKGATE_UART0_SRC+CONFIG_RK_DEBUG_UART); + // u32 u_pclk_id=(RK3188_CLKGATE_PCLK_UART0+CONFIG_RK_DEBUG_UART); + + for(i=0;i 0) { + if (grf_readl(RK3188_GRF_SOC_STATUS0) & bit) + break; + delay--; + } + if (delay == 0) { + //CRU_PRINTK_ERR("wait pll bit 0x%x time out!\n", bit); + rkpm_ddr_printch('p'); + rkpm_ddr_printch('l'); + rkpm_ddr_printch('l'); + rkpm_ddr_printhex(pll_idx); + rkpm_ddr_printch('\n'); + } +} +static void power_on_pll(u32 pll_id) +{ + cru_writel(RK3188_PLL_PWR_DN_W_MSK | RK3188_PLL_PWR_ON, RK3188_PLL_CONS((pll_id), 3)); + pm_pll_wait_lock((pll_id)); +} + +static u32 clk_sel0, clk_sel1, clk_sel10; +static u32 cpll_con3; +static u32 cru_mode_con; + +void plls_suspend(void) +{ + cru_mode_con = cru_readl(RK3188_CRU_MODE_CON); + cru_writel(RK3188_PLL_MODE_SLOW(RK3188_CPLL_ID), RK3188_CRU_MODE_CON); + + cpll_con3 = cru_readl(RK3188_PLL_CONS(RK3188_CPLL_ID, 3)); + power_off_pll(RK3188_CPLL_ID); + + + //apll + clk_sel0 = cru_readl(RK3188_CRU_CLKSELS_CON(0)); + clk_sel1 = cru_readl(RK3188_CRU_CLKSELS_CON(1)); + + cru_writel(RK3188_PLL_MODE_SLOW(RK3188_APLL_ID), RK3188_CRU_MODE_CON); + + /* To make sure aclk_cpu select apll before div effect */ + cru_writel(RK3188_CPU_SEL_PLL_W_MSK | RK3188_CPU_SEL_APLL + | RK3188_CORE_SEL_PLL_W_MSK | RK3188_CORE_SEL_APLL + , RK3188_CRU_CLKSELS_CON(0)); + cru_writel(RK3188_CORE_PERIPH_W_MSK | RK3188_CORE_PERIPH_2 + | RK3188_CORE_CLK_DIV_W_MSK | RK3188_CORE_CLK_DIV(1) + | RK3188_CPU_CLK_DIV_W_MSK | RK3188_CPU_CLK_DIV(1) + , RK3188_CRU_CLKSELS_CON(0)); + cru_writel(RK3188_CORE_ACLK_W_MSK | RK3188_CORE_ACLK_11 + | RK3188_ACLK_HCLK_W_MSK | RK3188_ACLK_HCLK_11 + | RK3188_ACLK_PCLK_W_MSK | RK3188_ACLK_PCLK_11 + | RK3188_AHB2APB_W_MSK | RK3188_AHB2APB_11 + , RK3188_CRU_CLKSELS_CON(1)); + power_off_pll(RK3188_APLL_ID); + cru_writel(RK3188_PLL_MODE_SLOW(RK3188_GPLL_ID), RK3188_CRU_MODE_CON); + + + clk_sel10 = cru_readl(RK3188_CRU_CLKSELS_CON(10)); + cru_writel(RK3188_CRU_W_MSK_SETBITS(0, RK3188_PERI_ACLK_DIV_OFF, RK3188_PERI_ACLK_DIV_MASK) + | RK3188_CRU_W_MSK_SETBITS(0,RK3188_PERI_HCLK_DIV_OFF, RK3188_PERI_HCLK_DIV_MASK) + | RK3188_CRU_W_MSK_SETBITS(0, RK3188_PERI_PCLK_DIV_OFF, RK3188_PERI_PCLK_DIV_MASK) + , RK3188_CRU_CLKSELS_CON(10)); + + power_off_pll(RK3188_GPLL_ID); + +} + +void plls_resume(void) +{ + //gpll + + cru_writel(0xffff0000 | clk_sel10, RK3188_CRU_CLKSELS_CON(10)); + + power_on_pll(RK3188_GPLL_ID); + cru_writel((RK3188_PLL_MODE_MSK(RK3188_GPLL_ID) << 16) + | (RK3188_PLL_MODE_MSK(RK3188_GPLL_ID) & cru_mode_con) + , RK3188_CRU_MODE_CON); + + //apll + cru_writel(0xffff0000 | clk_sel1, RK3188_CRU_CLKSELS_CON(1)); + /* To make sure aclk_cpu select gpll after div effect */ + cru_writel((0xffff0000 & ~RK3188_CPU_SEL_PLL_W_MSK & ~RK3188_CORE_SEL_PLL_W_MSK) + | clk_sel0 + , RK3188_CRU_CLKSELS_CON(0)); + + cru_writel(RK3188_CPU_SEL_PLL_W_MSK + | RK3188_CORE_SEL_PLL_W_MSK + | clk_sel0 + , RK3188_CRU_CLKSELS_CON(0)); + + power_on_pll(RK3188_APLL_ID); + cru_writel((RK3188_PLL_MODE_MSK(RK3188_APLL_ID) << 16) + | (RK3188_PLL_MODE_MSK(RK3188_APLL_ID) & cru_mode_con) + , RK3188_CRU_MODE_CON); + + + // it was power off ,don't need to power up + if (((cpll_con3 & RK3188_PLL_PWR_DN_MSK) == RK3188_PLL_PWR_ON) + &&((RK3188_PLL_MODE_NORM(RK3188_CPLL_ID) & RK3188_PLL_MODE_MSK(RK3188_CPLL_ID)) + == (cru_mode_con & RK3188_PLL_MODE_MSK(RK3188_CPLL_ID)))) { + power_on_pll(RK3188_CPLL_ID); + } + cru_writel((RK3188_PLL_MODE_MSK(RK3188_CPLL_ID) << 16) + | (RK3188_PLL_MODE_MSK(RK3188_CPLL_ID) & cru_mode_con) + , RK3188_CRU_MODE_CON); +} + +u32 DEFINE_PIE_DATA(sysclk_cru_clksel0_con); +u32 DEFINE_PIE_DATA(sysclk_cru_clksel10_con); +u32 DEFINE_PIE_DATA(sysclk_cru_mode_con); + +void PIE_FUNC(sysclk_suspend)(u32 sel_clk) +{ + DATA(sysclk_cru_clksel0_con) = cru_readl(RK3188_CRU_CLKSELS_CON(0)); + if(sel_clk&(RKPM_CTR_SYSCLK_32K)) + { + DATA(sysclk_cru_mode_con) = cru_readl(RK3188_CRU_MODE_CON); + DATA(sysclk_cru_clksel10_con) = cru_readl(RK3188_CRU_CLKSELS_CON(10)); + + cru_writel(RK3188_PERI_ACLK_DIV_W_MSK | RK3188_PERI_ACLK_DIV(4), RK3188_CRU_CLKSELS_CON(10)); + cru_writel(RK3188_CORE_CLK_DIV_W_MSK | RK3188_CORE_CLK_DIV(4) + | RK3188_CPU_CLK_DIV_W_MSK | RK3188_CPU_CLK_DIV(4) + , RK3188_CRU_CLKSELS_CON(0)); + + cru_writel(0 + | RK3188_PLL_MODE_DEEP(RK3188_APLL_ID) + //| RK3188_PLL_MODE_DEEP(RK3188_DPLL_ID) + | RK3188_PLL_MODE_DEEP(RK3188_CPLL_ID) + | RK3188_PLL_MODE_DEEP(RK3188_GPLL_ID) + , RK3188_CRU_MODE_CON); + rkpm_sram_printch('8'); + } + else if(sel_clk&(RKPM_CTR_SYSCLK_DIV)) + { + //set core_clk_div and cpu_clk_div to the largest + cru_writel(RK3188_CORE_CLK_DIV_W_MSK | RK3188_CORE_CLK_DIV_MSK + | RK3188_CPU_CLK_DIV_W_MSK | RK3188_CPU_CLK_DIV_MSK, RK3188_CRU_CLKSELS_CON(0)); + } +} + +void PIE_FUNC(sysclk_resume)(u32 sel_clk) +{ + + if(sel_clk&(RKPM_CTR_SYSCLK_32K)) + { + cru_writel((0xffff<<16) | DATA(sysclk_cru_mode_con), RK3188_CRU_MODE_CON); + cru_writel(RK3188_CORE_CLK_DIV_W_MSK | RK3188_CPU_CLK_DIV_W_MSK + | DATA(sysclk_cru_clksel0_con), RK3188_CRU_CLKSELS_CON(0)); + cru_writel(RK3188_PERI_ACLK_DIV_W_MSK | DATA(sysclk_cru_clksel10_con), + RK3188_CRU_CLKSELS_CON(10)); + + rkpm_sram_printch('8'); + } + else if(sel_clk&(RKPM_CTR_SYSCLK_DIV)) + { + cru_writel(RK3188_CORE_CLK_DIV_W_MSK | RK3188_CPU_CLK_DIV_W_MSK + | DATA(sysclk_cru_clksel0_con), RK3188_CRU_CLKSELS_CON(0)); + } + +} + +void clks_gating_suspend_init(void) +{ + // get clk gating info + p_rkpm_clkgt_last_set= kern_to_pie(rockchip_pie_chunk, &DATA(rkpm_clkgt_last_set[0])); + p_rkpm_clkgt_last_save= kern_to_pie(rockchip_pie_chunk, &DATA(rkpm_clkgt_last_save[0])); + + if(clk_suspend_clkgt_info_get(clk_ungt_msk,p_rkpm_clkgt_last_set, RK3188_CRU_CLKGATES_CON_CNT) + ==RK3188_CRU_CLKGATES_CON(0)) + { + rkpm_set_ops_gtclks(gtclks_suspend,gtclks_resume); + rkpm_set_sram_ops_gtclks(fn_to_pie(rockchip_pie_chunk, &FUNC(gtclks_sram_suspend)), + fn_to_pie(rockchip_pie_chunk, &FUNC(gtclks_sram_resume))); + + PM_LOG("%s:clkgt info ok\n",__FUNCTION__); + + } + rkpm_set_sram_ops_sysclk(fn_to_pie(rockchip_pie_chunk, &FUNC(sysclk_suspend)) + ,fn_to_pie(rockchip_pie_chunk, &FUNC(sysclk_resume))); +} + +/***************************prepare and finish reg_pread***********************************/ + +static noinline void rk30_pm_dump_irq(void) +{ +#if 0 + u32 irq_gpio = (readl_relaxed(RK30_GICD_BASE + GIC_DIST_PENDING_SET + 8) >> 22) & 0x7F; + printk("wakeup irq: %08x %08x %08x %08x\n", + readl_relaxed(RK30_GICD_BASE + GIC_DIST_PENDING_SET + 4), + readl_relaxed(RK30_GICD_BASE + GIC_DIST_PENDING_SET + 8), + readl_relaxed(RK30_GICD_BASE + GIC_DIST_PENDING_SET + 12), + readl_relaxed(RK30_GICD_BASE + GIC_DIST_PENDING_SET + 16)); + DUMP_GPIO_INT_STATUS(0); + DUMP_GPIO_INT_STATUS(1); + DUMP_GPIO_INT_STATUS(2); + DUMP_GPIO_INT_STATUS(3); + #if GPIO_BANKS > 4 + DUMP_GPIO_INT_STATUS(4); + #endif + #if GPIO_BANKS > 5 + DUMP_GPIO_INT_STATUS(6); + #endif + #endif +} + + +#define DUMP_GPIO_INTEN(ID) \ +do { \ + u32 en = readl_relaxed(RK_GPIO_VIRT(ID) + GPIO_INTEN); \ + if (en) { \ + rkpm_ddr_printascii("GPIO" #ID "_INTEN: "); \ + rkpm_ddr_printhex(en); \ + rkpm_ddr_printch('\n'); \ + printk(KERN_DEBUG "GPIO%d_INTEN: %08x\n", ID, en); \ + } \ +} while (0) +static noinline void rk30_pm_dump_inten(void) +{ + DUMP_GPIO_INTEN(0); + DUMP_GPIO_INTEN(1); + DUMP_GPIO_INTEN(2); + DUMP_GPIO_INTEN(3); +} + + +static void rkpm_prepare(void) +{ + #if 1 + u32 temp =reg_readl(RK_GPIO_VIRT(0)+0x30); + + // rkpm_ddr_printhex(temp); + reg_writel(temp|0x1<<4,RK_GPIO_VIRT(0)+0x30); + temp =reg_readl(RK_GPIO_VIRT(0)+0x30); + // rkpm_ddr_printhex(temp); +#endif + + // dump GPIO INTEN for debug + rk30_pm_dump_inten(); + #ifdef CONFIG_DDR_TEST + // memory tester + ddr_testmode(); + #endif +} + +static void rkpm_finish(void) +{ + rk30_pm_dump_irq(); +} + + +static void interface_ctr_reg_pread(void) +{ + //u32 addr; + flush_cache_all(); + outer_flush_all(); + local_flush_tlb_all(); + #if 0 // do it in ddr suspend + for (addr = (u32)SRAM_CODE_OFFSET; addr < (u32)(SRAM_CODE_OFFSET+rockchip_sram_size); addr += PAGE_SIZE) + readl_relaxed(addr); + #endif + readl_relaxed(RK_PMU_VIRT); + readl_relaxed(RK_GRF_VIRT); + readl_relaxed(RK_DDR_VIRT); + readl_relaxed(RK_GPIO_VIRT(0)); + //readl_relaxed(RK30_I2C1_BASE+SZ_4K); + //readl_relaxed(RK_GPIO_VIRT(3)); +} + +static u32 gpios_data[2]; + + + + +static int rk_pm_probe(struct platform_device *pdev) +{ + struct device_node *parent; + u32 pm_ctrbits; + + + parent=pdev->dev.of_node; + + PM_LOG("%s enter\n",__FUNCTION__); + + if(of_property_read_u32_array(parent,"rockchip,ctrbits",&pm_ctrbits,1)) + { + PM_ERR("%s:get pm ctr error\n",__FUNCTION__); + return -1; + } + PM_LOG("%s: pm_ctrbits =%x\n",__FUNCTION__,pm_ctrbits); + + if(of_property_read_u32_array(parent,"rockchip,pmic-gpios",gpios_data,ARRAY_SIZE(gpios_data))) + { + PM_ERR("%s:get pm ctr error\n",__FUNCTION__); + return -1; + } + + + rkpm_set_ctrbits(pm_ctrbits); + + rkpm_pie_init(); + + clks_gating_suspend_init(); + rkpm_set_ops_plls(plls_suspend,plls_resume); + rkpm_set_ops_prepare_finish(rkpm_prepare,rkpm_finish); + rkpm_set_ops_regs_pread(interface_ctr_reg_pread); + + //rkpm_set_sram_ops_ddr(fn_to_pie(rockchip_pie_chunk, &FUNC(ddr_suspend)) + // ,fn_to_pie(rockchip_pie_chunk, &FUNC(ddr_resume))); + + rkpm_set_sram_ops_printch(fn_to_pie(rockchip_pie_chunk, &FUNC(sram_printch))); + rkpm_set_ops_printch(ddr_printch); + + return 0; +} + +static int rk_pm_remove(struct platform_device *pdev) +{ + return 0; +} + +static const struct of_device_id rk_pm_of_match[] = { + {.compatible = "rockchip,rkpm_suspend",}, + { }, +}; + +static struct platform_driver rk_pm_platdrv = { + .driver = { + .name = "rkpm_suspend", + .owner = THIS_MODULE, + .of_match_table = rk_pm_of_match, + }, + .probe = rk_pm_probe, + .remove = rk_pm_remove, +}; +module_platform_driver(rk_pm_platdrv); + +MODULE_AUTHOR("Shawn Guo "); +MODULE_DESCRIPTION("Generic rk pm plat drv"); +MODULE_LICENSE("GPL"); diff --git a/arch/arm/mach-rockchip/rk3188.c b/arch/arm/mach-rockchip/rk3188.c index ebcb004b7a92..087cf2887d82 100755 --- a/arch/arm/mach-rockchip/rk3188.c +++ b/arch/arm/mach-rockchip/rk3188.c @@ -354,3 +354,7 @@ static int __init rk3188_ddr_init(void) return 0; } arch_initcall_sync(rk3188_ddr_init); + +#include "pm-rk3188.c" + + diff --git a/include/dt-bindings/pinctrl/rockchip-rk3188.h b/include/dt-bindings/pinctrl/rockchip-rk3188.h index 0b4a142471e6..58bba225d1de 100755 --- a/include/dt-bindings/pinctrl/rockchip-rk3188.h +++ b/include/dt-bindings/pinctrl/rockchip-rk3188.h @@ -20,6 +20,9 @@ /* GPIO0_A */ +#define GPIO0_A0 0x0A00 +#define GPIO0_A1 0x0A10 + /* GPIO0_B */ /* GPIO0_C */ #define GPIO0_C0 0x0c00 -- 2.34.1