};
};
+ 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>;
<&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 {
#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)
#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;
#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)
+++ /dev/null
-#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
#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) \
#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) \
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);
obj-y += clk.o
obj-y += clk-ops.o
obj-y += clk-pll.o
+obj-y += clk-pd.o
--- /dev/null
+#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;
+}
+
--- /dev/null
+#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 */
#include "clk-ops.h"
#include "clk-pll.h"
+#include "clk-pd.h"
struct rkclk_muxinfo {
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;
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;
};
#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)
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;
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;
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:
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;
}
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__);
}
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;
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",
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) {}
#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;
{.name = "clk_core", .rate = 500000000},
};
+
void rk_clk_test(void)
{
const char *clk_name;
rk_dump_cru();
}
+ rk_clk_pd_test();
}
#else
void rk_clk_test(void) {}
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__);
}
rkclk_init_clks(node_init);
rk_clk_test();
+
}
CLK_OF_DECLARE(rk_clocks, "rockchip,rk-clocks", rk_clk_tree_init);
#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 */
--- /dev/null
+#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