rk3188 pm support
authorxxx <xxx@rock-chips.com>
Thu, 13 Mar 2014 07:24:12 +0000 (15:24 +0800)
committerxxx <xxx@rock-chips.com>
Thu, 13 Mar 2014 07:24:12 +0000 (15:24 +0800)
arch/arm/boot/dts/rk3188-clocks.dtsi
arch/arm/boot/dts/rk3188.dtsi
arch/arm/mach-rockchip/pm-rk3188.c [new file with mode: 0755]
arch/arm/mach-rockchip/rk3188.c
include/dt-bindings/pinctrl/rockchip-rk3188.h

index f4927b18936b28252fbb9a32538263178dd6e90d..3910ed29e6718d8fd9dcd6ead9f116092fff7fa6 100755 (executable)
@@ -84,6 +84,7 @@
 
                clock_regs {
                        compatible = "rockchip,rk-clock-regs";
+                       reg = <0x0000 0x3ff>;
                        #address-cells = <1>;
                        #size-cells = <1>;
                        ranges;
 
                                                "reserved",             "clk_spdif_div",
                                                "clk_spdif_frac",       "g_testclk";
+                                               rockchip,suspend-clkgating-setting=<0x00bf 0x00bf>;
 
                                        #clock-cells = <1>;
                                };
 
                                                "clk_uart2_div",        "clk_uart2_frac",
                                                "clk_uart3_div",        "clk_uart3_frac";
+                                               rockchip,suspend-clkgating-setting=<0x0 0x0>;
 
                                        #clock-cells = <1>;
                                };
 
                                                "g_mac_lbtest",         "clk_sdio",
                                                "clk_emmc",             "reserved";
+                                               //rockchip,suspend-clkgating-setting=<0x1f 0x1b>;
+                                               rockchip,suspend-clkgating-setting=<0x1f 0x1b>;
 
                                        #clock-cells = <1>;
                                };
 
                                                "g_h_vdpu",             "reserved",
                                                "timer6",               "clk_gpu";
+                                       rockchip,suspend-clkgating-setting=<0x0 0x0>;
 
                                        #clock-cells = <1>;
                                };
                                                "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>;
                                };
 
                                                "g_h_sdmmc0",           "g_h_sdio",
 
                                                "g_h_emmc",             "g_h_otg0";
+                                       rockchip,suspend-clkgating-setting=<0x80 0x80>;
 
                                        #clock-cells = <1>;
                                };
 
                                                "g_h_vio_bus",          "g_a_vio0";
 
+                                       rockchip,suspend-clkgating-setting=<0x0 0x0>;
                                        #clock-cells = <1>;
                                };
 
 
                                                "g_p_spi0",             "g_p_spi1",
                                                "g_p_saradc",           "g_p_wdt";
+                                       rockchip,suspend-clkgating-setting=<0x0 0x0>;
 
                                        #clock-cells = <1>;
                                };
                                                "g_p_gpio1",            "g_p_gpio2",
 
                                                "g_p_gpio3",            "g_a_gps";
+                                               rockchip,suspend-clkgating-setting=<0x200 0x200>;
 
                                        #clock-cells = <1>;
                                };
 
                                                "g_clk_l2c",            "g_a_vio1",
                                                "g_p_ddrpubl",          "g_a_gpu";
+                                       rockchip,suspend-clkgating-setting=<0x50 0x50>;
 
                                        #clock-cells = <1>;
                                };
index 70880db67d48a88ea4f529d18de0bb62a0950785..6ec40efe08ad2f197f7ac8aa633fc3990c18146e 100755 (executable)
@@ -2,6 +2,7 @@
 #include "skeleton.dtsi"
 #include "rk3188-pinctrl.dtsi"
 #include <dt-bindings/rkfb/rk_fb.h>
+#include <dt-bindings/suspend/rockchip-pm.h>
 #include "rk3188_io_vol_domain.dtsi"
 
 #include <dt-bindings/sensor-dev.h>
                        <&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 = <DUAL>;
diff --git a/arch/arm/mach-rockchip/pm-rk3188.c b/arch/arm/mach-rockchip/pm-rk3188.c
new file mode 100755 (executable)
index 0000000..2f69c44
--- /dev/null
@@ -0,0 +1,652 @@
+
+#include <linux/kernel.h>
+#include <linux/init.h>
+#include <asm/cacheflush.h>
+#include <asm/tlbflush.h>
+#include <asm/hardware/cache-l2x0.h>
+#include <linux/module.h>
+#include <linux/platform_device.h>
+
+#include <linux/pm.h>
+#include <linux/suspend.h>
+#include <linux/of.h>
+#include <asm/io.h>
+#include <linux/of.h>
+#include <linux/of_address.h>
+
+#include <linux/rockchip/cpu.h>
+//#include <linux/rockchip/cru.h>
+#include <linux/rockchip/grf.h>
+#include <linux/rockchip/iomap.h>
+#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<RK3188_CRU_CLKGATES_CON_CNT;i++)
+    {
+        DATA(rkpm_clkgt_last_save[i])=cru_readl(RK3188_CRU_CLKGATES_CON(i));     
+        CLK_MSK_UNGATING( DATA(rkpm_clkgt_last_set[i]), RK3188_CRU_CLKGATES_CON(i));      
+        #if 0
+        rkpm_sram_printch('\n');   
+        rkpm_sram_printhex(DATA(rkpm_clkgt_last_save[i]));
+        rkpm_sram_printch('-');   
+        rkpm_sram_printhex(DATA(rkpm_clkgt_last_set[i]));
+        rkpm_sram_printch('-');   
+        rkpm_sram_printhex(cru_readl(RK3188_CRU_CLKGATES_CON(i)));
+        if(i==(RK3188_CRU_CLKGATES_CON_CNT-1))         
+        rkpm_sram_printch('\n');   
+        #endif
+    }
+    
+        //RK3188_CLK_UNGATING_OPS(u_clk_id);
+        //RK3188_CLK_UNGATING_OPS(u_pclk_id);
+}
+
+void PIE_FUNC(gtclks_sram_resume)(void)
+{
+    int i;
+    for(i=0;i<RK3188_CRU_CLKGATES_CON_CNT;i++)
+    {
+        cru_writel(DATA(rkpm_clkgt_last_save[i])|0xffff0000, RK3188_CRU_CLKGATES_CON(i));
+    }
+}
+
+static void gtclks_suspend(void)
+{
+    int i;
+    
+    for(i=0;i<RK3188_CRU_CLKGATES_CON_CNT;i++)
+    {
+    
+        clk_ungt_save[i]=cru_readl(RK3188_CRU_CLKGATES_CON(i));    
+        //if(i!=4||i!=0)
+        CLK_MSK_UNGATING(clk_ungt_msk[i],RK3188_CRU_CLKGATES_CON(i));
+       #if 0
+        rkpm_ddr_printch('\n');   
+        rkpm_ddr_printhex(clk_ungt_save[i]);
+        rkpm_ddr_printch('-');   
+        rkpm_ddr_printhex(clk_ungt_msk[i]);
+        rkpm_ddr_printch('-');   
+        rkpm_ddr_printhex(cru_readl(RK3188_CRU_CLKGATES_CON(i))) ;  
+        if(i==(RK3188_CRU_CLKGATES_CON_CNT-1))            
+            rkpm_ddr_printch('\n');   
+        #endif
+    }
+
+}
+
+static void gtclks_resume(void)
+{
+    int i;
+     for(i=0;i<RK3188_CRU_CLKGATES_CON_CNT;i++)
+    {
+       cru_writel(clk_ungt_save[i]|0xffff0000,RK3188_CRU_CLKGATES_CON(i));
+    }
+    
+}
+
+/********************************pll power down***************************************/
+
+#define power_off_pll(id) \
+       cru_writel(RK3188_PLL_PWR_DN_W_MSK | RK3188_PLL_PWR_DN, RK3188_PLL_CONS((id), 3))
+
+static void pm_pll_wait_lock(u32 pll_idx)
+{
+       u32 pll_state[4] = { 1, 0, 2, 3 };
+       u32 bit = 0x20u << pll_state[pll_idx];
+       u32 delay = pll_idx == RK3188_APLL_ID ? 600000U : 30000000U;
+       dsb();
+       dsb();
+       dsb();
+       dsb();
+       dsb();
+       dsb();
+       while (delay > 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 <shawn.guo@linaro.org>");
+MODULE_DESCRIPTION("Generic rk pm plat drv");
+MODULE_LICENSE("GPL");
index ebcb004b7a92c25ed2707cb25e8219f408bf24b0..087cf2887d82ade5332a16577e085059c5ff123e 100755 (executable)
@@ -354,3 +354,7 @@ static int __init rk3188_ddr_init(void)
        return 0;
 }
 arch_initcall_sync(rk3188_ddr_init);
+
+#include "pm-rk3188.c"
+
+
index 0b4a142471e6a68ef5a671ee01f90f0953fb7d8b..58bba225d1deef771437becc40088c5332cfa127 100755 (executable)
@@ -20,6 +20,9 @@
 
 
 /* GPIO0_A */
+#define GPIO0_A0 0x0A00
+#define GPIO0_A1 0x0A10
+
 /* GPIO0_B */
 /* GPIO0_C */
 #define GPIO0_C0 0x0c00