pd: rockchip: add clk_pd type and rk3288 clk_pd support
authordkl <dkl@rock-chips.com>
Mon, 14 Apr 2014 08:25:02 +0000 (16:25 +0800)
committerdkl <dkl@rock-chips.com>
Mon, 14 Apr 2014 08:59:23 +0000 (16:59 +0800)
14 files changed:
arch/arm/boot/dts/rk3288-clocks.dtsi
arch/arm/boot/dts/rk3288.dtsi
arch/arm/mach-rockchip/common.c
arch/arm/mach-rockchip/hotplug.c
arch/arm/mach-rockchip/platsmp.c
arch/arm/mach-rockchip/pmu.h [deleted file]
arch/arm/mach-rockchip/rk3188.c
arch/arm/mach-rockchip/rk3288.c
drivers/clk/rockchip/Makefile
drivers/clk/rockchip/clk-pd.c [new file with mode: 0644]
drivers/clk/rockchip/clk-pd.h [new file with mode: 0644]
drivers/clk/rockchip/clk.c
include/dt-bindings/clock/rockchip.h
include/linux/rockchip/pmu.h [new file with mode: 0755]

index cc0554064665e46d7cab322044e5ad7d15faf81c..8f3ba98f019df03d29f1757ee5862d38069b1199 100755 (executable)
                        };
                };
 
+               pd_cons {
+                       compatible = "rockchip,rk-pd-cons";
+
+                       pd_gpu: pd_gpu {
+                               compatible = "rockchip,rk-pd-clock";
+                               clock-output-names = "pd_gpu";
+                               rockchip,pd-id = <CLK_PD_GPU>;
+                               #clock-cells = <0>;
+                       };
+
+                       pd_video: pd_video {
+                               compatible = "rockchip,rk-pd-clock";
+                               clock-output-names = "pd_video";
+                               rockchip,pd-id = <CLK_PD_VIDEO>;
+                               #clock-cells = <0>;
+                       };
+
+                       pd_vio: pd_vio {
+                               compatible = "rockchip,rk-pd-clock";
+                               clock-output-names = "pd_vio";
+                               rockchip,pd-id = <CLK_PD_VIO>;
+                               #clock-cells = <0>;
+                       };
+
+                       pd_hevc: pd_hevc {
+                               compatible = "rockchip,rk-pd-clock";
+                               clock-output-names = "pd_hevc";
+                               rockchip,pd-id = <CLK_PD_HEVC>;
+                               #clock-cells = <0>;
+                       };
+
+               };
+
+
                clock_regs {
                        compatible = "rockchip,rk-clock-regs";
                        #address-cells = <1>;
index 07b9de0d692259ff53dd266bd88b925e18fb3b78..93137ab9a72c08d1a7a3105b87edd6d86d3fbbaf 100755 (executable)
                                <&clk_gates5 12>,/*hdmi_hdcp_clk*/
 
                                /*UART*/
-                               <&clk_gates11 9>;/*pclk_uart2*/
+                               <&clk_gates11 9>,/*pclk_uart2*/
+
+                               /*PD*/
+                               <&pd_gpu>,
+                               <&pd_video>,
+                               <&pd_vio>,
+                               <&pd_hevc>;
        };
 
        i2c0: i2c@ff650000 {
index 97d37532b5db4e7e03a43283e518ad354b1af2c6..44abfc4fa7c66c80833c93fbd267d1ba38090e57 100755 (executable)
@@ -23,9 +23,9 @@
 #include <asm/cputype.h>
 #include <asm/hardware/cache-l2x0.h>
 #include <linux/rockchip/common.h>
+#include <linux/rockchip/pmu.h>
 #include "cpu_axi.h"
 #include "loader.h"
-#include "pmu.h"
 #include "sram.h"
 
 static int __init rockchip_cpu_axi_init(void)
index 82612ff32fabb8997112efdc798768c704f7d1b6..bb2f7dcc6044bf64ce976037fc8c6a3714796048 100644 (file)
 #include <linux/smp.h>
 #include <linux/delay.h>
 #include <linux/rockchip/common.h>
+#include <linux/rockchip/pmu.h>
 
 #include <asm/cacheflush.h>
 #include <asm/cp15.h>
 #include <asm/smp_plat.h>
 #include <asm/system.h>
 
-#include "pmu.h"
 
 static cpumask_t dead_cpus;
 
index 9444a1c5e54111d0af0c8d791928f97ab10771d6..db66d50bcadcbeeb5d36728fef1297d5e81249d4 100644 (file)
 #include <linux/of.h>
 #include <linux/of_address.h>
 #include <linux/rockchip/common.h>
+#include <linux/rockchip/pmu.h>
 
 #include <asm/cacheflush.h>
 #include <asm/smp_scu.h>
 #include <asm/smp_plat.h>
 #include <asm/mach/map.h>
 
-#include "pmu.h"
 
 #define SCU_CTRL               0x00
 #define   SCU_STANDBY_EN       (1 << 5)
diff --git a/arch/arm/mach-rockchip/pmu.h b/arch/arm/mach-rockchip/pmu.h
deleted file mode 100755 (executable)
index 19a10a5..0000000
+++ /dev/null
@@ -1,110 +0,0 @@
-#ifndef __MACH_ROCKCHIP_PMU_H
-#define __MACH_ROCKCHIP_PMU_H
-
-#define RK3188_PMU_WAKEUP_CFG0          0x00
-#define RK3188_PMU_WAKEUP_CFG1          0x04
-#define RK3188_PMU_PWRDN_CON            0x08
-#define RK3188_PMU_PWRDN_ST             0x0c
-#define RK3188_PMU_INT_CON              0x10
-#define RK3188_PMU_INT_ST               0x14
-#define RK3188_PMU_MISC_CON             0x18
-#define RK3188_PMU_OSC_CNT              0x1c
-#define RK3188_PMU_PLL_CNT              0x20
-#define RK3188_PMU_PMU_CNT              0x24
-#define RK3188_PMU_DDRIO_PWRON_CNT      0x28
-#define RK3188_PMU_WAKEUP_RST_CLR_CNT   0x2c
-#define RK3188_PMU_SCU_PWRDWN_CNT       0x30
-#define RK3188_PMU_SCU_PWRUP_CNT        0x34
-#define RK3188_PMU_MISC_CON1            0x38
-#define RK3188_PMU_GPIO0_CON            0x3c
-#define RK3188_PMU_SYS_REG0             0x40
-#define RK3188_PMU_SYS_REG1             0x44
-#define RK3188_PMU_SYS_REG2             0x48
-#define RK3188_PMU_SYS_REG3             0x4c
-#define RK3188_PMU_STOP_INT_DLY         0x60
-#define RK3188_PMU_GPIO0A_PULL          0x64
-#define RK3188_PMU_GPIO0B_PULL          0x68
-
-#define RK3288_PMU_WAKEUP_CFG0          0x00
-#define RK3288_PMU_WAKEUP_CFG1          0x04
-#define RK3288_PMU_PWRDN_CON            0x08
-#define RK3288_PMU_PWRDN_ST             0x0c
-#define RK3288_PMU_IDLE_REQ             0x10
-#define RK3288_PMU_IDLE_ST              0x14
-#define RK3288_PMU_PWRMODE_CON          0x18
-#define RK3288_PMU_PWR_STATE            0x1c
-#define RK3288_PMU_OSC_CNT              0x20
-#define RK3288_PMU_PLL_CNT              0x24
-#define RK3288_PMU_STABL_CNT            0x28
-#define RK3288_PMU_DDR0IO_PWRON_CNT     0x2c
-#define RK3288_PMU_DDR1IO_PWRON_CNT     0x30
-#define RK3288_PMU_CORE_PWRDWN_CNT      0x34
-#define RK3288_PMU_CORE_PWRUP_CNT       0x38
-#define RK3288_PMU_GPU_PWRDWN_CNT       0x3c
-#define RK3288_PMU_GPU_PWRUP_CNT        0x40
-#define RK3288_PMU_WAKEUP_RST_CLR_CNT   0x44
-#define RK3288_PMU_SFT_CON              0x48
-#define RK3288_PMU_DDR_SREF_ST          0x4c
-#define RK3288_PMU_INT_CON              0x50
-#define RK3288_PMU_INT_ST               0x54
-#define RK3288_PMU_BOOT_ADDR_SEL        0x58
-#define RK3288_PMU_GRF_CON              0x5c
-#define RK3288_PMU_GPIO_SR              0x60
-#define RK3288_PMU_GPIO0_A_PULL         0x64
-#define RK3288_PMU_GPIO0_B_PULL         0x68
-#define RK3288_PMU_GPIO0_C_PULL         0x6c
-#define RK3288_PMU_GPIO0_A_DRV          0x70
-#define RK3288_PMU_GPIO0_B_DRV          0x74
-#define RK3288_PMU_GPIO0_C_DRV          0x78
-#define RK3288_PMU_GPIO_OP              0x7c
-#define RK3288_PMU_GPIO0_SEL18          0x80
-#define RK3288_PMU_GPIO0_A_IOMUX        0x84
-#define RK3288_PMU_GPIO0_B_IOMUX        0x88
-#define RK3288_PMU_GPIO0_C_IOMUX        0x8c
-#define RK3288_PMU_PWRMODE_CON1        0x90
-#define RK3288_PMU_SYS_REG0             0x94
-#define RK3288_PMU_SYS_REG1             0x98
-#define RK3288_PMU_SYS_REG2             0x9c
-#define RK3288_PMU_SYS_REG3             0xa0
-
-enum pmu_power_domain {
-       PD_BCPU,
-       PD_BDSP,
-       PD_BUS,
-       PD_CPU_0,
-       PD_CPU_1,
-       PD_CPU_2,
-       PD_CPU_3,
-       PD_CS,
-       PD_GPU,
-       PD_HEVC,
-       PD_PERI,
-       PD_SCU,
-       PD_VIDEO,
-       PD_VIO,
-};
-
-enum pmu_idle_req {
-       IDLE_REQ_ALIVE,
-       IDLE_REQ_AP2BP,
-       IDLE_REQ_BP2AP,
-       IDLE_REQ_BUS,
-       IDLE_REQ_CORE,
-       IDLE_REQ_CPUP,
-       IDLE_REQ_DMA,
-       IDLE_REQ_GPU,
-       IDLE_REQ_HEVC,
-       IDLE_REQ_PERI,
-       IDLE_REQ_VIDEO,
-       IDLE_REQ_VIO,
-};
-
-struct rockchip_pmu_operations {
-       int (*set_power_domain)(enum pmu_power_domain pd, bool on);
-       bool (*power_domain_is_on)(enum pmu_power_domain pd);
-       int (*set_idle_request)(enum pmu_idle_req req, bool idle);
-};
-
-extern struct rockchip_pmu_operations rockchip_pmu_ops;
-
-#endif
index 18b1dd296fb3afd1b26f6fb40e5fc8ccdc8f113c..b6288b3f4b9aef51d1d2dd67e684c432961cbffd 100644 (file)
 #include <linux/rockchip/cru.h>
 #include <linux/rockchip/grf.h>
 #include <linux/rockchip/iomap.h>
+#include <linux/rockchip/pmu.h>
 #include <asm/mach/arch.h>
 #include <asm/mach/map.h>
 #include "cpu_axi.h"
 #include "loader.h"
-#include "pmu.h"
 #include "sram.h"
 
 #define RK3188_DEVICE(name) \
index 407f5112a8d59a674e458281ec402226bf8424f7..23dc1fd555ca4915b3b31b2692fc28a986917013 100644 (file)
 #include <linux/rockchip/dvfs.h>
 #include <linux/rockchip/grf.h>
 #include <linux/rockchip/iomap.h>
+#include <linux/rockchip/pmu.h>
 #include <asm/cpuidle.h>
 #include <asm/cputype.h>
 #include <asm/mach/arch.h>
 #include <asm/mach/map.h>
 #include "cpu_axi.h"
 #include "loader.h"
-#include "pmu.h"
 #include "sram.h"
 
 #define RK3288_DEVICE(name) \
@@ -341,9 +341,11 @@ out:
        return 0;
 }
 
+int rk3288_sys_set_power_domain(enum pmu_power_domain pd, bool on);
+
 static void __init rk3288_dt_init_timer(void)
 {
-       rockchip_pmu_ops.set_power_domain = rk3288_pmu_set_power_domain;
+       rockchip_pmu_ops.set_power_domain = rk3288_sys_set_power_domain;
        rockchip_pmu_ops.power_domain_is_on = rk3288_pmu_power_domain_is_on;
        rockchip_pmu_ops.set_idle_request = rk3288_pmu_set_idle_request;
        of_clk_init(NULL);
index 090212d780082228fc2b4a240cf1dbd8463f098c..5ee45b65db56b74e5a9b8ee7694ac78730f5f8ae 100644 (file)
@@ -1,3 +1,4 @@
 obj-y  += clk.o
 obj-y  += clk-ops.o
 obj-y  += clk-pll.o
+obj-y  += clk-pd.o
diff --git a/drivers/clk/rockchip/clk-pd.c b/drivers/clk/rockchip/clk-pd.c
new file mode 100644 (file)
index 0000000..6c76fcb
--- /dev/null
@@ -0,0 +1,82 @@
+#include <linux/slab.h>
+
+#include "clk-ops.h"
+#include "clk-pd.h"
+
+
+static int clk_pd_endisable(struct clk_hw *hw, bool enable)
+{
+       struct clk_pd *pd = to_clk_pd(hw);
+       unsigned long flags = 0;
+       int ret;
+
+       if (pd->lock)
+               spin_lock_irqsave(pd->lock, flags);
+
+       ret = rockchip_pmu_ops.set_power_domain(pd->id, enable);
+
+       if (pd->lock)
+               spin_unlock_irqrestore(pd->lock, flags);
+
+       return ret;     
+}
+
+static int clk_pd_enable(struct clk_hw *hw)
+{
+       return clk_pd_endisable(hw, true);
+}
+
+static void clk_pd_disable(struct clk_hw *hw)
+{
+       clk_pd_endisable(hw, false);
+}
+
+static int clk_pd_is_enabled(struct clk_hw *hw)
+{
+       struct clk_pd *pd = to_clk_pd(hw);
+
+       return rockchip_pmu_ops.power_domain_is_on(pd->id);
+}
+
+const struct clk_ops clk_pd_ops = {
+       .enable = clk_pd_enable,
+       .disable = clk_pd_disable,
+       .is_enabled = clk_pd_is_enabled,
+};
+
+struct clk *rk_clk_register_pd(struct device *dev, const char *name,
+               const char *parent_name, unsigned long flags, 
+               u32 pd_id, spinlock_t *lock)
+{
+       struct clk_pd *pd;
+       struct clk *clk;
+       struct clk_init_data init;
+
+
+       /* allocate the pd */
+       pd = kzalloc(sizeof(struct clk_pd), GFP_KERNEL);
+       if (!pd) {
+               clk_err("%s: could not allocate pd clk\n", __func__);
+               return ERR_PTR(-ENOMEM);
+       }
+
+       init.name = name;
+       init.flags = flags | CLK_IS_BASIC;
+       init.parent_names = (parent_name ? &parent_name: NULL);
+       init.num_parents = (parent_name ? 1 : 0);
+       init.ops = &clk_pd_ops;
+
+       /* struct clk_pd assignments */
+       pd->id= pd_id;
+       pd->lock = lock;
+       pd->hw.init = &init;
+
+       /* register the clock */
+       clk = clk_register(dev, &pd->hw);
+
+       if (IS_ERR(clk))
+               kfree(pd);
+
+       return clk;
+}
+
diff --git a/drivers/clk/rockchip/clk-pd.h b/drivers/clk/rockchip/clk-pd.h
new file mode 100644 (file)
index 0000000..7f94516
--- /dev/null
@@ -0,0 +1,22 @@
+#ifndef __RK_CLK_PD_H
+#define __RK_CLK_PD_H
+
+#include <linux/clk-provider.h>
+#include <linux/rockchip/pmu.h>
+
+
+
+#define to_clk_pd(_hw) container_of(_hw, struct clk_pd, hw)
+
+struct clk_pd {
+       struct clk_hw   hw;
+       u32             id;
+       spinlock_t      *lock;
+};
+
+struct clk *rk_clk_register_pd(struct device *dev, const char *name,
+               const char *parent_name, unsigned long flags, 
+               u32 pd_id, spinlock_t *lock);
+
+
+#endif /* __RK_CLK_PD_H */
index c05687927cfdfbf51d338366fc77209b96e26c6a..72c8b04a522300d224d5ff4dc12c4d9ac68f5312 100755 (executable)
@@ -23,6 +23,7 @@
 
 #include "clk-ops.h"
 #include "clk-pll.h"
+#include "clk-pd.h"
 
 
 struct rkclk_muxinfo {
@@ -82,6 +83,14 @@ struct rkclk_fixed_factor_info {
        const char              *parent_name;
 };
 
+struct rkclk_pd_info {
+       const char              *clk_name;
+       struct device_node      *np;
+       struct clk_pd           *pd;
+       const char              *parent_name;
+};
+
+
 struct rkclk {
        const char              *clk_name;
        //struct device_node    *np;
@@ -94,6 +103,7 @@ struct rkclk {
        struct rkclk_gateinfo   *gate_info;
        struct rkclk_fixed_rate_info *fixed_rate_info;
        struct rkclk_fixed_factor_info *fixed_factor_info;
+       struct rkclk_pd_info    *pd_info;
        struct list_head        node;
 };
 
@@ -107,6 +117,7 @@ LIST_HEAD(rk_clks);
 #define RKCLK_GATE_TYPE                (1 << 4)
 #define RKCLK_FIXED_RATE_TYPE  (1 << 5)
 #define RKCLK_FIXED_FACTOR_TYPE        (1 << 6)
+#define RKCLK_PD_TYPE          (1 << 7)
 
 
 static int rkclk_init_muxinfo(struct device_node *np, void __iomem *addr)
@@ -1043,6 +1054,85 @@ out:
        return ret;
 }
 
+static int __init rkclk_init_pd(struct device_node *np)
+{
+       struct device_node *node = NULL;
+       struct rkclk_pd_info *pd_info = NULL;
+       struct clk_pd *pd = NULL;
+       int ret = 0;
+       u8 found = 0;
+       struct rkclk *rkclk = NULL;
+
+
+       for_each_available_child_of_node(np, node) {
+               pd_info = kzalloc(sizeof(struct rkclk_pd_info), GFP_KERNEL);
+               if (!pd_info) {
+                       ret = -ENOMEM;
+                       goto out;
+               }
+
+               pd_info->pd = kzalloc(sizeof(struct clk_pd), GFP_KERNEL);
+               if (!pd_info->pd) {
+                       ret = -ENOMEM;
+                       goto out;
+               }
+               pd = pd_info->pd;
+
+               pd_info->np = node;
+
+               ret = of_property_read_string_index(node, "clock-output-names",
+                               0, &pd_info->clk_name);
+               if (ret)
+                       goto out;
+
+               pd_info->parent_name = of_clk_get_parent_name(node, 0);
+
+               ret = of_property_read_u32(node, "rockchip,pd-id", &pd->id);
+               if (ret != 0) {
+                       clk_err("%s: can not get pd-id\n", __func__);
+                       goto out;
+               }
+
+               found = 0;
+               list_for_each_entry(rkclk, &rk_clks, node) {
+                       if (strcmp(pd_info->clk_name, rkclk->clk_name) == 0) {
+                               clk_err("%s %d:\n", __func__, __LINE__);
+                               clk_err("This clk (%s) has been used, error!\n",
+                                       rkclk->clk_name);
+                               goto out;
+                       }
+               }
+
+               if (!found) {
+                       rkclk = kzalloc(sizeof(struct rkclk), GFP_KERNEL);
+                       if (!rkclk) {
+                               ret = -ENOMEM;
+                               goto out;
+                       }
+                       rkclk->clk_name = pd_info->clk_name;
+                       rkclk->pd_info = pd_info;
+                       rkclk->clk_type = RKCLK_PD_TYPE;
+                       rkclk->flags = CLK_IS_ROOT;
+                       clk_debug("%s: creat %s\n", __func__, rkclk->clk_name);
+                       list_add_tail(&rkclk->node, &rk_clks);
+               }
+       }
+
+out:
+       if (ret) {
+               clk_err("%s error, ret = %d\n", __func__, ret);
+               if (pd_info) {
+                       if (pd_info->pd)
+                               kfree(pd_info->pd);
+                       kfree(pd_info);
+               }
+               if (rkclk)
+                       kfree(rkclk);
+       }
+
+       return ret;
+}
+
 static int rkclk_register(struct rkclk *rkclk)
 {
        struct clk              *clk = NULL;
@@ -1053,6 +1143,7 @@ static int rkclk_register(struct rkclk *rkclk)
        struct clk_divider      *frac = NULL;
        struct clk_fixed_rate   *fixed_rate = NULL;
        struct clk_fixed_factor *fixed_factor = NULL;
+       struct clk_pd           *pd = NULL;
 
        struct clk_hw           *mux_hw = NULL;
        const struct clk_ops    *mux_ops = NULL;
@@ -1089,6 +1180,9 @@ static int rkclk_register(struct rkclk *rkclk)
                fixed_rate = rkclk->fixed_rate_info->fixed_rate;
        if (rkclk->fixed_factor_info && rkclk->fixed_factor_info->fixed_factor)
                fixed_factor = rkclk->fixed_factor_info->fixed_factor;
+       if (rkclk->pd_info && rkclk->pd_info->pd)
+               pd = rkclk->pd_info->pd;
+
 
        switch (rkclk->clk_type) {
                case RKCLK_MUX_TYPE:
@@ -1150,6 +1244,12 @@ static int rkclk_register(struct rkclk *rkclk)
                                        rkclk->flags, fixed_factor->mult,
                                        fixed_factor->div);
                        goto add_lookup;
+               case RKCLK_PD_TYPE:
+                       clk_debug("use rk_clk_register_pd\n");
+                       clk = rk_clk_register_pd(NULL, rkclk->clk_name,
+                                       rkclk->pd_info->parent_name, rkclk->flags,
+                                       pd->id, &clk_lock);
+                       goto add_lookup;
                default:
                        goto rgs_comp;
        }
@@ -1377,6 +1477,10 @@ static void rkclk_add_provider(struct device_node *np)
                                        clk_err("%s: unknown\n", __func__);
                                }
                        }
+               } else if (strcmp(compatible, "rockchip,rk-pd-cons") == 0) {
+                       for_each_available_child_of_node(node, node_prd) {
+                                _rkclk_add_provider(node_prd);
+                       }
                } else {
                        clk_err("%s: unknown\n", __func__);
                }
@@ -1446,6 +1550,7 @@ void rkclk_dump_info(struct rkclk *rkclk)
        struct clk_divider      *frac = NULL;
        struct clk_fixed_rate   *fixed_rate = NULL;
        struct clk_fixed_factor *fixed_factor = NULL;
+       struct clk_pd           *pd = NULL;
        int i;
 
 
@@ -1467,6 +1572,9 @@ void rkclk_dump_info(struct rkclk *rkclk)
                fixed_rate = rkclk->fixed_rate_info->fixed_rate;
        if (rkclk->fixed_factor_info && rkclk->fixed_factor_info->fixed_factor)
                fixed_factor = rkclk->fixed_factor_info->fixed_factor;
+       if (rkclk->pd_info && rkclk->pd_info->pd)
+               pd = rkclk->pd_info->pd;
+
 
        if (rkclk->mux_info) {
                clk_debug("\t\tmux_info: name=%s, clkops_idx=%u\n",
@@ -1554,6 +1662,15 @@ void rkclk_dump_info(struct rkclk *rkclk)
                                fixed_factor->mult, fixed_factor->div);
                }
        }
+
+       if (rkclk->pd_info) {
+               clk_debug("\t\tpd_info: name=%s, parent=%s\n",
+                               rkclk->pd_info->clk_name,
+                               rkclk->pd_info->parent_name);
+               if (pd) {
+                       clk_debug("\t\tpd: id=%u\n", pd->id);
+               }
+       }
 }
 #else
 void rkclk_dump_info(struct rkclk *rkclk) {}
@@ -1561,6 +1678,44 @@ void rkclk_dump_info(struct rkclk *rkclk) {}
 
 
 #ifdef RKCLK_TEST
+char* pd_table[] = {
+       "pd_gpu",
+       "pd_video",
+       "pd_vio",
+       "pd_hevc",
+};
+
+void rk_clk_pd_test(void)
+{
+       struct clk *clk;
+       bool state;
+       int j, ret;
+
+
+       for (j = 0; j < ARRAY_SIZE(pd_table); j++) {
+
+               clk = clk_get(NULL, pd_table[j]);
+
+               ret = clk_prepare_enable(clk);
+               printk("%s: clk_prepare_enable %s, ret=%d\n", __func__,
+                       __clk_get_name(clk), ret);
+
+               state = __clk_is_enabled(clk);
+               printk("%s: clk_pd %s is %s\n", __func__, __clk_get_name(clk),
+                       state ? "enable" : "disable");
+
+               clk_disable_unprepare(clk);
+               printk("%s: clk_disable_unprepare %s\n", __func__,
+                       __clk_get_name(clk));
+
+               state = __clk_is_enabled(clk);
+               printk("%s: clk_pd %s is %s\n", __func__, __clk_get_name(clk),
+                       state ? "enable" : "disable");
+
+               printk("\n");
+       }
+}
+
 struct test_table {
        const char *name;
        u32 rate;
@@ -1598,6 +1753,7 @@ struct test_table t_table[] = {
        {.name = "clk_core",    .rate = 500000000},
 };
 
+
 void rk_clk_test(void)
 {
        const char *clk_name;
@@ -1652,6 +1808,7 @@ void rk_clk_test(void)
                rk_dump_cru();
        }
 
+       rk_clk_pd_test();
 }
 #else
 void rk_clk_test(void) {}
@@ -1697,6 +1854,11 @@ static void __init rk_clk_tree_init(struct device_node *np)
                                clk_err("%s: init reg cons err\n", __func__);
                                return ;
                        }
+               } else if (strcmp(compatible, "rockchip,rk-pd-cons") == 0) {
+                       if (rkclk_init_pd(node) != 0) {
+                               clk_err("%s: init pd err\n", __func__);
+                               return ;
+                       }
                } else {
                        clk_err("%s: unknown\n", __func__);
                }
@@ -1720,6 +1882,7 @@ static void __init rk_clk_tree_init(struct device_node *np)
        rkclk_init_clks(node_init);
 
        rk_clk_test();
+
 }
 CLK_OF_DECLARE(rk_clocks, "rockchip,rk-clocks", rk_clk_tree_init);
 
index d05d846d84067b763109622775c54c84a154fed9..7e4a970e4912709885c40ef4fb98314904406e40 100644 (file)
 #define CLKOPS_RATE_RK3288_I2S         14
 #define CLKOPS_TABLE_END               (~0)
 
+/* pd id */
+#define CLK_PD_BCPU            0
+#define CLK_PD_BDSP            1
+#define CLK_PD_BUS             2
+#define CLK_PD_CPU_0           3
+#define CLK_PD_CPU_1           4
+#define CLK_PD_CPU_2           5
+#define CLK_PD_CPU_3           6
+#define CLK_PD_CS              7
+#define CLK_PD_GPU             8
+#define CLK_PD_HEVC            9
+#define CLK_PD_PERI            10
+#define CLK_PD_SCU             11
+#define CLK_PD_VIDEO           12
+#define CLK_PD_VIO             13
+
+
 #endif /* _DT_BINDINGS_CLOCK_ROCKCHIP_H */
diff --git a/include/linux/rockchip/pmu.h b/include/linux/rockchip/pmu.h
new file mode 100755 (executable)
index 0000000..19a10a5
--- /dev/null
@@ -0,0 +1,110 @@
+#ifndef __MACH_ROCKCHIP_PMU_H
+#define __MACH_ROCKCHIP_PMU_H
+
+#define RK3188_PMU_WAKEUP_CFG0          0x00
+#define RK3188_PMU_WAKEUP_CFG1          0x04
+#define RK3188_PMU_PWRDN_CON            0x08
+#define RK3188_PMU_PWRDN_ST             0x0c
+#define RK3188_PMU_INT_CON              0x10
+#define RK3188_PMU_INT_ST               0x14
+#define RK3188_PMU_MISC_CON             0x18
+#define RK3188_PMU_OSC_CNT              0x1c
+#define RK3188_PMU_PLL_CNT              0x20
+#define RK3188_PMU_PMU_CNT              0x24
+#define RK3188_PMU_DDRIO_PWRON_CNT      0x28
+#define RK3188_PMU_WAKEUP_RST_CLR_CNT   0x2c
+#define RK3188_PMU_SCU_PWRDWN_CNT       0x30
+#define RK3188_PMU_SCU_PWRUP_CNT        0x34
+#define RK3188_PMU_MISC_CON1            0x38
+#define RK3188_PMU_GPIO0_CON            0x3c
+#define RK3188_PMU_SYS_REG0             0x40
+#define RK3188_PMU_SYS_REG1             0x44
+#define RK3188_PMU_SYS_REG2             0x48
+#define RK3188_PMU_SYS_REG3             0x4c
+#define RK3188_PMU_STOP_INT_DLY         0x60
+#define RK3188_PMU_GPIO0A_PULL          0x64
+#define RK3188_PMU_GPIO0B_PULL          0x68
+
+#define RK3288_PMU_WAKEUP_CFG0          0x00
+#define RK3288_PMU_WAKEUP_CFG1          0x04
+#define RK3288_PMU_PWRDN_CON            0x08
+#define RK3288_PMU_PWRDN_ST             0x0c
+#define RK3288_PMU_IDLE_REQ             0x10
+#define RK3288_PMU_IDLE_ST              0x14
+#define RK3288_PMU_PWRMODE_CON          0x18
+#define RK3288_PMU_PWR_STATE            0x1c
+#define RK3288_PMU_OSC_CNT              0x20
+#define RK3288_PMU_PLL_CNT              0x24
+#define RK3288_PMU_STABL_CNT            0x28
+#define RK3288_PMU_DDR0IO_PWRON_CNT     0x2c
+#define RK3288_PMU_DDR1IO_PWRON_CNT     0x30
+#define RK3288_PMU_CORE_PWRDWN_CNT      0x34
+#define RK3288_PMU_CORE_PWRUP_CNT       0x38
+#define RK3288_PMU_GPU_PWRDWN_CNT       0x3c
+#define RK3288_PMU_GPU_PWRUP_CNT        0x40
+#define RK3288_PMU_WAKEUP_RST_CLR_CNT   0x44
+#define RK3288_PMU_SFT_CON              0x48
+#define RK3288_PMU_DDR_SREF_ST          0x4c
+#define RK3288_PMU_INT_CON              0x50
+#define RK3288_PMU_INT_ST               0x54
+#define RK3288_PMU_BOOT_ADDR_SEL        0x58
+#define RK3288_PMU_GRF_CON              0x5c
+#define RK3288_PMU_GPIO_SR              0x60
+#define RK3288_PMU_GPIO0_A_PULL         0x64
+#define RK3288_PMU_GPIO0_B_PULL         0x68
+#define RK3288_PMU_GPIO0_C_PULL         0x6c
+#define RK3288_PMU_GPIO0_A_DRV          0x70
+#define RK3288_PMU_GPIO0_B_DRV          0x74
+#define RK3288_PMU_GPIO0_C_DRV          0x78
+#define RK3288_PMU_GPIO_OP              0x7c
+#define RK3288_PMU_GPIO0_SEL18          0x80
+#define RK3288_PMU_GPIO0_A_IOMUX        0x84
+#define RK3288_PMU_GPIO0_B_IOMUX        0x88
+#define RK3288_PMU_GPIO0_C_IOMUX        0x8c
+#define RK3288_PMU_PWRMODE_CON1        0x90
+#define RK3288_PMU_SYS_REG0             0x94
+#define RK3288_PMU_SYS_REG1             0x98
+#define RK3288_PMU_SYS_REG2             0x9c
+#define RK3288_PMU_SYS_REG3             0xa0
+
+enum pmu_power_domain {
+       PD_BCPU,
+       PD_BDSP,
+       PD_BUS,
+       PD_CPU_0,
+       PD_CPU_1,
+       PD_CPU_2,
+       PD_CPU_3,
+       PD_CS,
+       PD_GPU,
+       PD_HEVC,
+       PD_PERI,
+       PD_SCU,
+       PD_VIDEO,
+       PD_VIO,
+};
+
+enum pmu_idle_req {
+       IDLE_REQ_ALIVE,
+       IDLE_REQ_AP2BP,
+       IDLE_REQ_BP2AP,
+       IDLE_REQ_BUS,
+       IDLE_REQ_CORE,
+       IDLE_REQ_CPUP,
+       IDLE_REQ_DMA,
+       IDLE_REQ_GPU,
+       IDLE_REQ_HEVC,
+       IDLE_REQ_PERI,
+       IDLE_REQ_VIDEO,
+       IDLE_REQ_VIO,
+};
+
+struct rockchip_pmu_operations {
+       int (*set_power_domain)(enum pmu_power_domain pd, bool on);
+       bool (*power_domain_is_on)(enum pmu_power_domain pd);
+       int (*set_idle_request)(enum pmu_idle_req req, bool idle);
+};
+
+extern struct rockchip_pmu_operations rockchip_pmu_ops;
+
+#endif