rockchip: clk: add rk3188_plus type pll enable/disable
authordkl <dkl@rock-chips.com>
Wed, 5 Nov 2014 06:30:39 +0000 (14:30 +0800)
committerdkl <dkl@rock-chips.com>
Mon, 17 Nov 2014 02:43:20 +0000 (10:43 +0800)
Add rk3188_plus type pll enable/disable ops. Disable unused plls
when display is off in rk3288.

arch/arm/boot/dts/rk3288-clocks.dtsi
arch/arm/boot/dts/rk3288.dtsi
arch/arm/mach-rockchip/rk3288.c
drivers/clk/rockchip/clk-pll.c

index 4d7a7591f5ced8f21be682e6756308bd6ea3b692..9a1769372ac618162b4f7608f6bf7a7f2a32013c 100755 (executable)
                                        hclk_vio: hclk_vio_div {
                                                compatible = "rockchip,rk3188-div-con";
                                                rockchip,bits = <8 5>;
-                                               clocks = <&aclk_vio0>;
+                                               clocks = <&clk_gates15 11>;
                                                clock-output-names = "hclk_vio";
                                                rockchip,div-type = <CLK_DIVIDER_PLUS_ONE>;
                                                #clock-cells = <0>;
                                        reg = <0x019c 0x4>;
                                        clocks =
                                                <&aclk_rga>,            <&hclk_vio>,
-                                               <&aclk_vio0>,           <&hclk_vio>,
+                                               <&clk_gates15 11>,      <&hclk_vio>,
 
-                                               <&dummy>,               <&aclk_vio0>,
-                                               <&hclk_vio>,            <&aclk_vio1>,
+                                               <&dummy>,               <&clk_gates15 11>,
+                                               <&hclk_vio>,            <&clk_gates15 12>,
 
-                                               <&hclk_vio>,            <&hclk_vio>,
-                                               <&hclk_vio>,            <&aclk_vio0>,
+                                               <&hclk_vio>,            <&dummy>,
+                                               <&dummy>,               <&aclk_vio0>,
 
                                                <&aclk_vio1>,           <&aclk_rga>,
-                                               <&aclk_vio0>,           <&hclk_vio>;
+                                               <&clk_gates15 11>,      <&hclk_vio>;
 
                                        clock-output-names =
-                                               "reserved", /*"g_aclk_rga",*/   "g_hclk_rga",
+                                               "reserved", /*"g_aclk_rga"*/    "g_hclk_rga",
                                                "g_aclk_iep",           "g_hclk_iep",
 
                                                "g_aclk_lcdc_iep",              "g_aclk_lcdc0",
                                                "g_hclk_lcdc0",         "g_aclk_lcdc1",
 
-                                               "g_hclk_lcdc1",         "g_h_vio_ahb",
-                                               "g_hclk_vio_niu",               "g_aclk_vio0_niu",
+                                               "g_hclk_lcdc1",         "reserved", /* "g_h_vio_ahb" */
+                                               "reserved",/*"g_hclk_vio_niu"*/         "g_aclk_vio0_niu",
 
-                                               "g_aclk_vio1_niu",              "reserved",/*"g_aclk_rga_niu",*/
+                                               "g_aclk_vio1_niu",              "reserved",/*"g_aclk_rga_niu"*/
                                                "g_aclk_vip",           "g_hclk_vip";
                                                 rockchip,suspend-clkgating-setting=<0x0 0x0>;
 
                                        reg = <0x01a0 0x4>;
                                        clocks =
                                                <&pclkin_cif>,          <&hclk_vio>,
-                                               <&aclk_vio1>,           <&pclkin_isp>,
+                                               <&clk_gates15 12>,      <&pclkin_isp>,
 
                                                <&hclk_vio>,            <&hclk_vio>,
                                                <&hclk_vio>,            <&hclk_vio>,
 
                                                <&hclk_vio>,            <&hclk_vio>,
-                                               <&hclk_vio>,            <&hclk_vio>,
+                                               <&dummy>,               <&dummy>,
 
                                                <&dummy>,               <&dummy>,
                                                <&dummy>,               <&dummy>;
                                                "g_p_mipi_csi",         "g_pclk_lvds_phy",
 
                                                "g_pclk_edp_ctrl",              "g_p_hdmi_ctrl",
-                                               "g_hclk_vio2_h2p",              "g_pclk_vio2_h2p",
+                                               "reserved",             "reserved", /* bit10:"g_hclk_vio2_h2p" bit11: "g_pclk_vio2_h2p" */
 
                                                "reserved",             "reserved",
                                                "reserved",             "reserved";
index 481063dc96bcd15feb495b090310da458113a2a5..a15825a4e90eac07f675d6c894ae299630318ba7 100755 (executable)
        clocks-enable {
                compatible = "rockchip,clocks-enable";
                clocks =
+                               /*PLL*/
+                               <&clk_dpll>, <&clk_gpll>,
+
                                /*PD_CORE*/
                                <&clk_gates0 2>, <&clk_core0>,
                                <&clk_core1>, <&clk_core2>,
                                <&clk_gates17 2>,/*pclk_pmu_niu*/
                                <&clk_gates17 3>,/*pclk_sgrf*/
 
-                               /*hclk_vio*/
-                               <&clk_gates15 9>,/*hclk_vio_ahb_arbi*/
-                               <&clk_gates15 10>,/*hclk_vio_niu*/
-                               <&clk_gates16 10>,/*hclk_vio2_h2p*/
-                               <&clk_gates16 11>,/*pclk_vio2_h2p*/
-
-                               /*aclk_vio0*/
-                               <&clk_gates15 11>,/*aclk_vio0_niu*/
-
-                               /*aclk_vio1*/
-                               <&clk_gates15 12>,/*aclk_vio1_niu*/
-
-                               /*HDMI*/
-                               //<&clk_gates5 12>,/*hdmi_hdcp_clk*/
-
                                /*UART*/
                                <&clk_gates11 9>,/*pclk_uart2*/
 
index abcdb16e7c78dbb65275c24f67cf27e216338978..71fd7ff4467d58993173563f692300e45decf187 100755 (executable)
@@ -30,6 +30,7 @@
 #include <linux/rockchip/grf.h>
 #include <linux/rockchip/iomap.h>
 #include <linux/rockchip/pmu.h>
+#include <linux/fb.h>
 #include <asm/cpuidle.h>
 #include <asm/cputype.h>
 #include <asm/mach/arch.h>
@@ -490,6 +491,40 @@ static void __init rk3288_init_cpuidle(void)
        if (ret)
                pr_err("%s: failed to register cpuidle driver: %d\n", __func__, ret);
 }
+
+static int rk3288_pll_early_suspend_notifier_call(struct notifier_block *self,
+                               unsigned long action, void *data)
+{
+       struct fb_event *event = data;
+       int blank_mode = *((int *)event->data);
+
+       if (action == FB_EARLY_EVENT_BLANK) {
+               switch (blank_mode) {
+               case FB_BLANK_UNBLANK:
+                       clk_prepare_enable(clk_get_sys(NULL, "clk_cpll"));
+                       clk_prepare_enable(clk_get_sys(NULL, "clk_npll"));
+                       break;
+               default:
+                       break;
+               }
+       } else if (action == FB_EVENT_BLANK) {
+               switch (blank_mode) {
+               case FB_BLANK_POWERDOWN:
+                       clk_disable_unprepare(clk_get_sys(NULL, "clk_cpll"));
+                       clk_disable_unprepare(clk_get_sys(NULL, "clk_npll"));
+                       break;
+               default:
+                       break;
+               }
+       }
+
+       return NOTIFY_OK;
+}
+
+static struct notifier_block rk3288_pll_early_suspend_notifier = {
+       .notifier_call = rk3288_pll_early_suspend_notifier_call,
+};
+
 #ifdef CONFIG_PM
 static void __init rk3288_init_suspend(void);
 #endif
@@ -596,10 +631,11 @@ void inline rkpm_periph_pd_dn(bool on)
 static void __init rk3288_init_suspend(void)
 {
     printk("%s\n",__FUNCTION__);
+    fb_register_client(&rk3288_pll_early_suspend_notifier);
     rockchip_suspend_init();       
     rkpm_pie_init();
     rk3288_suspend_init();
-   rkpm_set_ops_pwr_dmns(rk_pm_soc_pd_suspend,rk_pm_soc_pd_resume);  
+   rkpm_set_ops_pwr_dmns(rk_pm_soc_pd_suspend,rk_pm_soc_pd_resume);
 }
 
 #if 0
index ce8496577766b1e043ef13135c95bbef84d92c5e..63f1b295fe405f34d6d4f32e272b63a7f3093f12 100755 (executable)
@@ -820,10 +820,113 @@ static int clk_pll_set_rate_3188plus(struct clk_hw *hw, unsigned long rate,
        return ret;
 }
 
+static int clk_pll_is_enabled_3188plus(struct clk_hw *hw)
+{
+       unsigned long flags;
+       struct clk_pll *pll = to_clk_pll(hw);
+       int ret;
+
+       if(pll->lock)
+               spin_lock_irqsave(pll->lock, flags);
+
+       if (_RK3188_PLL_MODE_IS_NORM(pll->mode_offset, pll->mode_shift))
+               ret = 1;
+       else
+               ret = 0;
+
+       if (pll->lock)
+               spin_unlock_irqrestore(pll->lock, flags);
+
+       return ret;
+}
+
+static int clk_pll_enable_3188plus(struct clk_hw *hw)
+{
+       struct clk_pll *pll = to_clk_pll(hw);
+       unsigned long flags;
+       unsigned long rst_dly;
+       u32 nr;
+
+       clk_debug("%s enter\n", __func__);
+
+       if (clk_pll_is_enabled_3188plus(hw)) {
+               clk_debug("pll has been enabled\n");
+               return 0;
+       }
+
+       if(pll->lock)
+               spin_lock_irqsave(pll->lock, flags);
+
+       //enter slowmode
+       cru_writel(_RK3188_PLL_MODE_SLOW_SET(pll->mode_shift), pll->mode_offset);
+
+       //power up
+       cru_writel(_RK3188PLUS_PLL_POWERDOWN_SET(0), pll->reg + RK3188_PLL_CON(3));
+
+       //enter reset
+       cru_writel(_RK3188PLUS_PLL_RESET_SET(1), pll->reg + RK3188_PLL_CON(3));
+
+       //cru_writel(clk_set->pllcon0, pll->reg + RK3188_PLL_CON(0));
+       //cru_writel(clk_set->pllcon1, pll->reg + RK3188_PLL_CON(1));
+       //cru_writel(clk_set->pllcon2, pll->reg + RK3188_PLL_CON(2));
+
+       udelay(5);
+
+       //return from reset
+       cru_writel(_RK3188PLUS_PLL_RESET_SET(0), pll->reg + RK3188_PLL_CON(3));
+
+       //wating lock state
+       nr = RK3188PLUS_PLL_NR(cru_readl(pll->reg + RK3188_PLL_CON(0)));
+       rst_dly = ((nr*500)/24+1);
+       udelay(rst_dly);
+
+       pll_wait_lock(hw);
+
+       //return from slow
+       cru_writel(_RK3188_PLL_MODE_NORM_SET(pll->mode_shift), pll->mode_offset);
+
+       if (pll->lock)
+               spin_unlock_irqrestore(pll->lock, flags);
+
+       clk_debug("pll %s dump reg:\n con0=0x%08x,\n con1=0x%08x,\n con2=0x%08x,\n"
+                       "con3=0x%08x,\n mode=0x%08x\n",
+                       __clk_get_name(hw->clk),
+                       cru_readl(pll->reg + RK3188_PLL_CON(0)),
+                       cru_readl(pll->reg + RK3188_PLL_CON(1)),
+                       cru_readl(pll->reg + RK3188_PLL_CON(2)),
+                       cru_readl(pll->reg + RK3188_PLL_CON(3)),
+                       cru_readl(pll->mode_offset));
+
+       return 0;
+}
+
+static void clk_pll_disable_3188plus(struct clk_hw *hw)
+{
+       struct clk_pll *pll = to_clk_pll(hw);
+       unsigned long flags;
+
+       clk_debug("%s enter\n", __func__);
+
+       if(pll->lock)
+               spin_lock_irqsave(pll->lock, flags);
+
+       //enter slowmode
+       cru_writel(_RK3188_PLL_MODE_SLOW_SET(pll->mode_shift), pll->mode_offset);
+
+       //power down
+       cru_writel(_RK3188PLUS_PLL_POWERDOWN_SET(1), pll->reg + RK3188_PLL_CON(3));
+
+       if (pll->lock)
+               spin_unlock_irqrestore(pll->lock, flags);
+}
+
 static const struct clk_ops clk_pll_ops_3188plus = {
        .recalc_rate = clk_pll_recalc_rate_3188plus,
        .round_rate = clk_pll_round_rate_3188plus,
        .set_rate = clk_pll_set_rate_3188plus,
+       .enable = clk_pll_enable_3188plus,
+       .disable = clk_pll_disable_3188plus,
+       .is_enabled = clk_pll_is_enabled_3188plus,
 };
 
 /* CLK_PLL_3188PLUS_AUTO type ops */
@@ -999,6 +1102,9 @@ static const struct clk_ops clk_pll_ops_3188plus_auto = {
        .recalc_rate = clk_pll_recalc_rate_3188plus_auto,
        .round_rate = clk_pll_round_rate_3188plus_auto,
        .set_rate = clk_pll_set_rate_3188plus_auto,
+       .enable = clk_pll_enable_3188plus,
+       .disable = clk_pll_disable_3188plus,
+       .is_enabled = clk_pll_is_enabled_3188plus,
 };