Hello Tony Xie,
I'd like you to do a code review. Please visit
https://chromium-review.googlesource.com/215780
to review the following change.
Change subject: suspend: rockchip: add suspend and resume of rk3288
......................................................................
suspend: rockchip: add suspend and resume of rk3288
This adds support for Rockchip soc suspend & resume
BUG=None
TEST=It can suspend by "echo mem > /sys/power/state", and resume by power
button
Change-Id: If5b4dc6b97414deff9f6b4719f95268c949fdf17
Signed-off-by: Chris.Zhong <
z...@rock-chips.com>
Signed-off-by: Tony.xie <
tony...@rock-chips.com>
---
M arch/arm/mach-rockchip/Makefile
A arch/arm/mach-rockchip/pm.c
A arch/arm/mach-rockchip/pm.h
M arch/arm/mach-rockchip/rockchip.c
A arch/arm/mach-rockchip/sleep.S
5 files changed, 732 insertions(+), 0 deletions(-)
diff --git a/arch/arm/mach-rockchip/Makefile
b/arch/arm/mach-rockchip/Makefile
index 4377a14..2b15094 100644
--- a/arch/arm/mach-rockchip/Makefile
+++ b/arch/arm/mach-rockchip/Makefile
@@ -1,2 +1,3 @@
obj-$(CONFIG_ARCH_ROCKCHIP) += rockchip.o
obj-$(CONFIG_SMP) += headsmp.o platsmp.o
+obj-$(CONFIG_PM_SLEEP) += pm.o sleep.o
diff --git a/arch/arm/mach-rockchip/pm.c b/arch/arm/mach-rockchip/pm.c
new file mode 100644
index 0000000..9b703a6
--- /dev/null
+++ b/arch/arm/mach-rockchip/pm.c
@@ -0,0 +1,478 @@
+/*
+ * Copyright (c) 2014, Fuzhou Rockchip Electronics Co., Ltd
+ * Author: Tony Xie <
tony...@rock-chips.com>
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms and conditions of the GNU General Public License,
+ * version 2, as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
for
+ * more details.
+ *
+ */
+
+#include <linux/kernel.h>
+#include <linux/init.h>
+#include <linux/io.h>
+#include <linux/suspend.h>
+#include <linux/of.h>
+#include <linux/of_address.h>
+#include <asm/cacheflush.h>
+#include <asm/tlbflush.h>
+#include <asm/suspend.h>
+#include "pm.h"
+
+static char bootram_save_data[RK3288_BOOTRAM_SIZE];
+static u32 bootdata_data[RKPM_BOOTDATA_ARR_SIZE];
+static void __iomem *rk3288_pmu_base;
+static void __iomem *rk3288_cru_base;
+static void __iomem *rk3288_bootram_base;
+static void __iomem *rk3288_sgrf_base;
+
+static struct rk_cpu_resume_data rk_cpu_data;
+
+void rk_cpu_resume_data_init(void)
+{
+ rk_cpu_data.bootram_save = (char *)bootram_save_data;
+ rk_cpu_data.bootram_save_size = sizeof(bootram_save_data);
+
+ rk_cpu_data.bootram_base = (char *)rk3288_bootram_base;
+ rk_cpu_data.bootram_phy = (char *)RK3288_BOOTRAM_PHYS;
+ rk_cpu_data.bootram_size = RK3288_BOOTRAM_SIZE;
+
+ rk_cpu_data.bootcode_base = rk_cpu_data.bootram_base
+ +RKPM_BOOT_CODE_OFFSET;
+
+ rk_cpu_data.bootcode_phy = rk_cpu_data.bootram_phy
+ +RKPM_BOOT_CODE_OFFSET;
+
+ rk_cpu_data.bootcode_src = (char *)rockchip_slp_cpu_resume;
+ rk_cpu_data.bootcode_size = RKPM_BOOT_CODE_SIZE;
+
+ rk_cpu_data.bootdata_base = rk_cpu_data.bootram_base
+ +RKPM_BOOT_DATA_OFFSET;
+
+ rk_cpu_data.bootdata_phy = rk_cpu_data.bootram_phy
+ +RKPM_BOOT_DATA_OFFSET;
+
+ rk_cpu_data.bootdata_src = (char *)bootdata_data;
+ rk_cpu_data.bootdata_size = sizeof(bootdata_data);
+}
+
+static void sram_data_for_sleep(struct rk_cpu_resume_data *rdata)
+{
+ unsigned long data_base, data_end;
+
+ /* save root sram data in ddr mem */
+ memcpy(rdata->bootram_save, rdata->bootram_base,
+ rdata->bootram_size);
+
+ /* move resume code and date to bootsram */
+ memcpy(rdata->bootcode_base, rdata->bootcode_src,
+ rdata->bootcode_size);
+
+ memcpy(rdata->bootdata_base, rdata->bootdata_src,
+ rdata->bootdata_size);
+
+ data_base = (unsigned long)rdata->bootram_base;
+ data_end = (unsigned long)rdata->bootram_base + rdata->bootram_size;
+ flush_icache_range(data_base, data_end);
+
+ data_base = (unsigned long)rdata->bootram_phy;
+ data_end = (unsigned long)rdata->bootram_phy + rdata->bootram_size;
+ outer_clean_range(data_base, data_end);
+}
+
+static void sram_data_resume(struct rk_cpu_resume_data *rdata)
+{
+ unsigned long data_base, data_end;
+
+ memcpy(rdata->bootram_save, rdata->bootram_base, rdata->bootram_size);
+
+ data_base = (unsigned long)rdata->bootram_base;
+ data_end = (unsigned long)rdata->bootram_base + rdata->bootram_size;
+ flush_icache_range(data_base, data_end);
+
+ data_base = (unsigned long)rdata->bootram_phy;
+ data_end = (unsigned long)rdata->bootram_phy + rdata->bootram_size;
+ outer_clean_range(data_base, data_end);
+}
+
+static inline u32 rk3288_l2_config(void)
+{
+ u32 l2ctlr;
+
+ asm("mrc p15, 1, %0, c9, c0, 2" : "=r" (l2ctlr));
+ return l2ctlr;
+}
+
+static inline u32 rk3288_armerrata_818325(void)
+{
+ u32 armerrata;
+
+ asm("mrc p15, 0, %0, c15, c0, 1" : "=r" (armerrata));
+ return armerrata;
+}
+
+static void rk3288_pmupin_setfun(u8 port, u8 bank, u8 b_gpio, u8 fun)
+{
+ u32 off_set, val;
+
+ bank -= 0xa;
+
+ if (port == 0) {
+ if (bank > 2)
+ return;
+
+ off_set = RK3288_PMU_GPIO0_A_IOMUX+bank*4;
+
+ val = readl_relaxed(rk3288_pmu_base+off_set);
+ val = RKPM_VAL_SETBITS(val, fun, b_gpio*2, 0x3);
+
+ writel_relaxed(val, rk3288_pmu_base+off_set);
+ }
+}
+
+static void rk3288_sram_data_prepare(u32 pwrmode)
+{
+ if (pwrmode&(BIT(pmu_scu_en)|BIT(pmu_a12_0_pd_en))) {
+ bootdata_data[RKPM_BOOTDATA_L2LTY_F] = 1;
+ bootdata_data[RKPM_BOOTDATA_L2LTY] = rk3288_l2_config();
+ bootdata_data[RKPM_BOOTDATA_ARM_ERRATA_818325_F] = 1;
+
+ bootdata_data[RKPM_BOOTDATA_ARM_ERRATA_818325] =
+ rk3288_armerrata_818325();
+
+ bootdata_data[RKPM_BOOTDATA_CPUSP] = RK3288_BOOTRAM_PHYS +
+ ((RK3288_BOOTRAM_SIZE-1)&~0x7);
+
+ bootdata_data[RKPM_BOOTDATA_CPUCODE] = virt_to_phys(cpu_resume);
+ } else {
+ bootdata_data[RKPM_BOOTDATA_L2LTY_F] = 0;
+ bootdata_data[RKPM_BOOTDATA_ARM_ERRATA_818325_F] = 0;
+ bootdata_data[RKPM_BOOTDATA_CPUCODE] = 0;
+ bootdata_data[RKPM_BOOTDATA_DDR_F] = 0;
+ }
+
+ sram_data_for_sleep(&rk_cpu_data);
+ flush_cache_all();
+ outer_flush_all();
+ local_flush_tlb_all();
+}
+
+static u32 rk3288_powermode;
+static u32 rk3288_sgrf_soc_con0, rk3288_pmu_wakeup_cfg0,
+ rk3288_pmu_wakeup_cfg1, rk3288_pmu_pwr_mode_con0,
+ rk3288_pmu_pwr_mode_con1;
+
+static u32 rk3288_slp_mode_set(int level)
+{
+ u32 mode_set, mode_set1;
+
+ rk3288_sgrf_soc_con0 =
+ readl_relaxed(rk3288_sgrf_base+RK3288_SGRF_SOC_CON0);
+
+ rk3288_pmu_wakeup_cfg0 =
+ readl_relaxed(rk3288_pmu_base+RK3288_PMU_WAKEUP_CFG0);
+
+ rk3288_pmu_wakeup_cfg1 =
+ readl_relaxed(rk3288_pmu_base+RK3288_PMU_WAKEUP_CFG1);
+
+ rk3288_pmu_pwr_mode_con0 =
+ readl_relaxed(rk3288_pmu_base+RK3288_PMU_PWRMODE_CON);
+
+ rk3288_pmu_pwr_mode_con1 =
+ readl_relaxed(rk3288_pmu_base+RK3288_PMU_PWRMODE_CON1);
+
+ /* setting gpio0_a0 arm off pin */
+ rk3288_pmupin_setfun(0x0, 0xa, 0x0, 0x0);
+
+ /*
+ * 0x1<<0 armint wakup ,
+ * if unused clk is gated in supend,it is Recommend.
+ * 0x1<<3, only gpio can wake up sys.
+ */
+ writel_relaxed(0x1<<3, rk3288_pmu_base+RK3288_PMU_WAKEUP_CFG1);
+ dsb();
+
+ /* enable boot ram */
+ writel_relaxed((0x1<<8)|(0x1<<(8+16)),
+ rk3288_sgrf_base+RK3288_SGRF_SOC_CON0);
+ dsb();
+
+ writel_relaxed(RK3288_BOOTRAM_PHYS,
+ rk3288_sgrf_base+RK3288_SGRF_FAST_BOOT_ADDR);
+ dsb();
+
+ mode_set = BIT(pmu_chip_pd_en) | BIT(pmu_l2flush_en)
+ | BIT(pmu_sref0_enter_en) | BIT(pmu_sref1_enter_en)
+ | BIT(pmu_ddr0_gating_en) | BIT(pmu_ddr1_gating_en)
+ ;
+
+ mode_set1 = BIT(pmu_clr_core) | BIT(pmu_clr_cpup)
+ | BIT(pmu_clr_alive) | BIT(pmu_clr_peri)
+ | BIT(pmu_clr_bus) | BIT(pmu_clr_dma)
+ ;
+
+ if (level == 0) {
+ /*
+ * arm off,logic normal
+ * if pmu_clk_core_src_gate_en is not set,
+ * wakeup will be error
+ */
+ mode_set |= BIT(pmu_scu_en) | BIT(pmu_clk_core_src_gate_en);
+
+ } else if (level == 1) {
+ /* arm off,logic dp */
+ mode_set |= BIT(pmu_scu_en) | BIT(pmu_bus_pd_en)
+ | BIT(pmu_ddr1io_ret_en) | BIT(pmu_ddr0io_ret_en)
+ | BIT(pmu_osc_24m_dis) | BIT(pmu_pmu_use_lf)
+ | BIT(pmu_alive_use_lf) | BIT(pmu_pll_pd_en)
+ ;
+ } else {
+ mode_set = 0;
+ mode_set1 = 0;
+ }
+
+ writel_relaxed(mode_set, rk3288_pmu_base + RK3288_PMU_PWRMODE_CON);
+ dsb();
+
+ writel_relaxed(mode_set1, rk3288_pmu_base + RK3288_PMU_PWRMODE_CON1);
+ dsb();
+
+ return readl_relaxed(rk3288_pmu_base + RK3288_PMU_PWRMODE_CON);
+}
+
+static void rk3288_slp_mode_set_resume(void)
+{
+ writel_relaxed(rk3288_pmu_wakeup_cfg0,
+ rk3288_pmu_base+RK3288_PMU_WAKEUP_CFG0);
+
+ writel_relaxed(rk3288_pmu_wakeup_cfg1,
+ rk3288_pmu_base+RK3288_PMU_WAKEUP_CFG1);
+
+ writel_relaxed(rk3288_pmu_pwr_mode_con0,
+ rk3288_pmu_base+RK3288_PMU_PWRMODE_CON);
+
+ writel_relaxed(rk3288_pmu_pwr_mode_con1,
+ rk3288_pmu_base+RK3288_PMU_PWRMODE_CON1);
+
+ writel_relaxed(rk3288_sgrf_soc_con0|(0x1<<(8+16)),
+ rk3288_sgrf_base+RK3288_SGRF_SOC_CON0);
+}
+
+#define RK3288_CRU_MODE_CON (0x50)
+#define RK3288_CRU_SEL0_CON (0x60)
+#define RK3288_CRU_SEL1_CON (0x64)
+#define RK3288_CRU_SEL10_CON (0x88)
+#define RK3288_CRU_SEL33_CON (0xe4)
+#define RK3288_CRU_SEL37_CON (0xf4)
+
+static u32 rk3288_cru_mode, rk3288_cru_sel0, rk3288_cru_sel1,
+ rk3288_cru_sel10, rk3288_cru_sel33, rk3288_cru_sel37;
+
+void rk3288_cru_save(void)
+{
+ /*
+ * cru will be set in fastboot by ic,
+ * so the following is save related reg
+ */
+ rk3288_cru_mode = readl_relaxed(rk3288_cru_base + RK3288_CRU_MODE_CON);
+ rk3288_cru_sel0 = readl_relaxed(rk3288_cru_base + RK3288_CRU_SEL0_CON);
+ rk3288_cru_sel1 = readl_relaxed(rk3288_cru_base + RK3288_CRU_SEL1_CON);
+
+ rk3288_cru_sel10 =
+ readl_relaxed(rk3288_cru_base + RK3288_CRU_SEL10_CON);
+
+ rk3288_cru_sel33 =
+ readl_relaxed(rk3288_cru_base + RK3288_CRU_SEL33_CON);
+
+ rk3288_cru_sel37 =
+ readl_relaxed(rk3288_cru_base + RK3288_CRU_SEL37_CON);
+
+ /* set pll into slow mode */
+ writel_relaxed(0xff0f0010, rk3288_cru_base + RK3288_CRU_MODE_CON);
+}
+
+void rk3288_cru_resume(void)
+{
+ writel_relaxed(rk3288_cru_mode | 0xffff0000,
+ rk3288_cru_base + RK3288_CRU_MODE_CON);
+
+ writel_relaxed(rk3288_cru_sel0 | 0xffff0000,
+ rk3288_cru_base + RK3288_CRU_SEL0_CON);
+
+ writel_relaxed(rk3288_cru_sel1 | 0xffff0000,
+ rk3288_cru_base + RK3288_CRU_SEL1_CON);
+
+ writel_relaxed(rk3288_cru_sel10 | 0xffff0000,
+ rk3288_cru_base + RK3288_CRU_SEL10_CON);
+
+ writel_relaxed(rk3288_cru_sel33 | 0xffff0000,
+ rk3288_cru_base + RK3288_CRU_SEL33_CON);
+
+ writel_relaxed(rk3288_cru_sel37 | 0xffff0000,
+ rk3288_cru_base + RK3288_CRU_SEL37_CON);
+}
+
+
+static void rk3288_save_setting(void)
+{
+ rk3288_powermode = rk3288_slp_mode_set(0);
+
+ if (rk3288_powermode & BIT(pmu_pwr_mode_en))
+ rk3288_sram_data_prepare(rk3288_powermode);
+
+ rk3288_cru_save();
+}
+
+static void rk3288_save_setting_resume(void)
+{
+ sram_data_resume(&rk_cpu_data);
+}
+
+static void rkpm_resume_first(void)
+{
+ rk3288_cru_resume();
+ rk3288_slp_mode_set_resume();
+}
+
+static int rockchip_lpmode_enter(unsigned long arg)
+{
+ local_flush_tlb_all();
+ flush_cache_all();
+ outer_flush_all();
+ outer_disable();
+ flush_cache_all();
+
+ dsb();
+ wfi();
+ dsb();
+ return 0;
+}
+
+static int rk3288_suspend_enter(suspend_state_t state)
+{
+ pr_info("%s\n", __func__);
+
+ local_fiq_disable();
+
+ rk3288_save_setting();
+
+ cpu_suspend(0, rockchip_lpmode_enter);
+
+ rkpm_resume_first();
+
+ rk3288_save_setting_resume();
+
+ local_fiq_enable();
+
+ pr_info("%s-out\n", __func__);
+ return 0;
+}
+
+static int rk3288_suspend_iomap(void)
+{
+ struct device_node *node;
+
+ node = of_find_compatible_node(NULL, NULL, "rockchip,rk3288-pmu");
+ if (!node) {
+ pr_err("%s: could not find pmu dt node\n", __func__);
+ return -1;
+ }
+
+ rk3288_pmu_base = of_iomap(node, 0);
+ if (!rk3288_pmu_base) {
+ pr_err("%s: could not map pmu registers\n", __func__);
+ return -1;
+ }
+
+
+ node = of_find_compatible_node(NULL, NULL, "mmio-sram");
+ if (!node) {
+ pr_err("%s: could not find bootram dt node\n", __func__);
+ return -1;
+ }
+
+ rk3288_bootram_base = of_iomap(node, 0);
+ if (!rk3288_bootram_base) {
+ pr_err("%s: could not map bootram registers\n", __func__);
+ return -1;
+ }
+ node = of_find_compatible_node(NULL, NULL, "rockchip,rk3288-cru");
+ if (!node) {
+ pr_err("%s: could not find cru dt node\n", __func__);
+ return -1;
+ }
+
+ rk3288_cru_base = of_iomap(node, 0);
+ if (!rk3288_cru_base) {
+ pr_err("%s: could not map cru registers\n", __func__);
+ return -1;
+ }
+
+
+ rk3288_bootram_base = ioremap(RK3288_BOOTRAM_PHYS, RK3288_BOOTRAM_SIZE);
+ rk3288_sgrf_base = ioremap(RK3288_SGRF_PHYS, RK3288_SGRF_SIZE);
+
+ return 0;
+}
+
+static int rk3288_suspend_init(void)
+{
+ int ret;
+
+ ret = rk3288_suspend_iomap();
+ rk_cpu_resume_data_init();
+ return ret;
+}
+
+static const struct platform_suspend_ops rk3288_suspend_ops = {
+ .enter = rk3288_suspend_enter,
+ .valid = suspend_valid_only_mem,
+};
+
+static int rockchip_suspend_init_check
+ (struct rockchip_suspend_of_device_id *matches)
+{
+ int ret = -1;
+ struct of_device_id *id = &matches->id;
+
+ if (!id->compatible && !id->data)
+ return -1;
+ if (of_machine_is_compatible(id->compatible)) {
+ ret = matches->init();
+ if (!ret)
+ suspend_set_ops(id->data);
+ }
+ return ret;
+}
+
+static struct rockchip_suspend_of_device_id rockchip_suspend_dt_match[] = {
+ {
+ .id = {
+ .compatible = "rockchip,rk3288",
+ .data = (void *)&rk3288_suspend_ops,
+ },
+ .init = rk3288_suspend_init,
+ },
+ {},
+};
+
+int __init rockchip_suspend_init(void)
+{
+ int ret = -1;
+ struct rockchip_suspend_of_device_id *matches =
+ rockchip_suspend_dt_match;
+
+ while (&matches->id && matches->init) {
+ if (rockchip_suspend_init_check(matches))
+ break;
+ matches++;
+ }
+
+ return ret;
+}
+
diff --git a/arch/arm/mach-rockchip/pm.h b/arch/arm/mach-rockchip/pm.h
new file mode 100644
index 0000000..7f9540c
--- /dev/null
+++ b/arch/arm/mach-rockchip/pm.h
@@ -0,0 +1,180 @@
+/*
+ * Copyright (c) 2014, Fuzhou Rockchip Electronics Co., Ltd
+ * Author: Tony Xie <
tony...@rock-chips.com>
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms and conditions of the GNU General Public License,
+ * version 2, as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
for
+ * more details.
+ *
+ */
+
+#ifndef __MACH_ROCKCHIP_PM_H
+#define __MACH_ROCKCHIP_PM_H
+
+/* cpu sp addr */
+#define RKPM_BOOTDATA_CPUSP (0)
+/* cpu resume fun,phy base */
+#define RKPM_BOOTDATA_CPUCODE (RKPM_BOOTDATA_CPUSP+1)
+/* ddr flag , 1 need to resume ddr ctr */
+#define RKPM_BOOTDATA_DDR_F (RKPM_BOOTDATA_CPUCODE+1)
+/* ddr pll flag, 1 need to resume dpll */
+#define RKPM_BOOTDATA_DPLL_F (RKPM_BOOTDATA_DDR_F+1)
+/* ddr resume code ,phy base */
+#define RKPM_BOOTDATA_DDRCODE (RKPM_BOOTDATA_DPLL_F+1)
+/* ddr resume data ,phy base */
+#define RKPM_BOOTDATA_DDRDATA (RKPM_BOOTDATA_DDRCODE+1)
+/* for l2 resume */
+#define RKPM_BOOTDATA_L2LTY_F (RKPM_BOOTDATA_DDRDATA+1)
+#define RKPM_BOOTDATA_L2LTY (RKPM_BOOTDATA_L2LTY_F+1)
+/* for arm errata 81835 resume */
+#define RKPM_BOOTDATA_ARM_ERRATA_818325_F (RKPM_BOOTDATA_L2LTY+1)
+#define RKPM_BOOTDATA_ARM_ERRATA_818325
(RKPM_BOOTDATA_ARM_ERRATA_818325_F+1)
+#define RKPM_BOOTDATA_ARR_SIZE (RKPM_BOOTDATA_ARM_ERRATA_818325+1)
+
+
+#define RKPM_BOOT_CODE_OFFSET (0x0)
+#define RKPM_BOOT_CODE_SIZE (0x100)
+#define RKPM_BOOT_DATA_OFFSET (RKPM_BOOT_CODE_OFFSET+RKPM_BOOT_CODE_SIZE)
+#define RKPM_BOOT_DATA_SIZE (RKPM_BOOTDATA_ARR_SIZE*4)
+#define RKPM_BOOT_DDRCODE_OFFSET
(RKPM_BOOT_DATA_OFFSET+RKPM_BOOT_DATA_SIZE)
+
+#ifndef __ASSEMBLY__
+
+struct rk_cpu_resume_data {
+ /* boot ram info*/
+ char *bootram_base;
+ char *bootram_phy;
+ u32 bootram_size;
+ /* boot ram info save*/
+ char *bootram_save;
+ u32 bootram_save_size;
+ /* code info in boot ram*/
+ char *bootcode_base;
+ char *bootcode_phy;
+ char *bootcode_src;
+ u32 bootcode_size;
+ /* code data info in boot ram*/
+ char *bootdata_base;
+ char *bootdata_phy;
+ char *bootdata_src;
+ u32 bootdata_size;
+ /* intsram info */
+ char *intsram_base;
+ char *intsram_phy;
+ u32 intsram_size;
+ char *intram_save;
+};
+
+struct rockchip_suspend_of_device_id {
+ struct of_device_id id;
+
+ int (*init)(void);
+};
+
+void rockchip_slp_cpu_resume(void);
+int __init rockchip_suspend_init(void);
+
+#define RKPM_BITS_CLR_VAL(val, bits_shift, msk) (val&~(msk<<bits_shift))
+#define RKPM_SETBITS(bits, bits_shift, msk) (((bits)&(msk)) <<
(bits_shift))
+#define RKPM_VAL_SETBITS(val, bits, bits_shift, msk) \
+ (RKPM_BITS_CLR_VAL(val, bits_shift, msk) |\
+ RKPM_SETBITS(bits, bits_shift, msk))
+
+/******fllowing is rk3288 defined**********/
+#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 rk3288_pwr_mode_con {
+ pmu_pwr_mode_en = 0,
+ pmu_clk_core_src_gate_en,
+ pmu_global_int_disable,
+ pmu_l2flush_en,
+ pmu_bus_pd_en,
+ pmu_a12_0_pd_en,
+ pmu_scu_en,
+ pmu_pll_pd_en,
+ pmu_chip_pd_en, /*power off pin enable */
+ pmu_pwroff_comb,
+ pmu_alive_use_lf,
+ pmu_pmu_use_lf,
+ pmu_osc_24m_dis,
+ pmu_input_clamp_en,
+ pmu_wakeup_reset_en,
+ pmu_sref0_enter_en,
+ pmu_sref1_enter_en,
+ pmu_ddr0io_ret_en,
+ pmu_ddr1io_ret_en,
+ pmu_ddr0_gating_en,
+ pmu_ddr1_gating_en,
+ pmu_ddr0io_ret_de_req,
+ pmu_ddr1io_ret_de_req
+};
+
+enum rk3288_pwr_mode_con1 {
+ pmu_clr_bus = 0,
+ pmu_clr_core,
+ pmu_clr_cpup,
+ pmu_clr_alive,
+ pmu_clr_dma,
+ pmu_clr_peri,
+ pmu_clr_gpu,
+ pmu_clr_video,
+ pmu_clr_hevc,
+ pmu_clr_vio,
+};
+
+#define RK3288_BOOTRAM_PHYS (0xFF720000)
+#define RK3288_BOOTRAM_SIZE SZ_4K
+
+#define RK3288_SGRF_PHYS (0xff740000)
+#define RK3288_SGRF_SIZE SZ_4K
+
+#define RK3288_SGRF_SOC_CON0 (0x0000)
+#define RK3288_SGRF_FAST_BOOT_ADDR (0x0120)
+
+#endif
+#endif
diff --git a/arch/arm/mach-rockchip/rockchip.c
b/arch/arm/mach-rockchip/rockchip.c
index dc33924..c1bc5c4 100644
--- a/arch/arm/mach-rockchip/rockchip.c
+++ b/arch/arm/mach-rockchip/rockchip.c
@@ -23,11 +23,13 @@
#include <asm/mach/map.h>
#include <asm/hardware/cache-l2x0.h>
#include "core.h"
+#include "pm.h"
static void __init rockchip_dt_init(void)
{
l2x0_of_init(0, ~0UL);
of_platform_populate(NULL, of_default_bus_match_table, NULL, NULL);
+ rockchip_suspend_init();
}
static const char * const rockchip_board_dt_compat[] = {
diff --git a/arch/arm/mach-rockchip/sleep.S b/arch/arm/mach-rockchip/sleep.S
new file mode 100644
index 0000000..12fdec6
--- /dev/null
+++ b/arch/arm/mach-rockchip/sleep.S
@@ -0,0 +1,71 @@
+/*
+ * Copyright (c) 2014, Fuzhou Rockchip Electronics Co., Ltd
+ * Author: Tony Xie <
tony...@rock-chips.com>
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms and conditions of the GNU General Public License,
+ * version 2, as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
for
+ * more details.
+ *
+ */
+
+#include <linux/linkage.h>
+#include <asm/assembler.h>
+#include <asm/memory.h>
+#include "pm.h"
+
+.data
+.align
+
+ENTRY(rockchip_slp_cpu_resume)
+9: mov r1, r1
+ setmode PSR_I_BIT | PSR_F_BIT | SVC_MODE, r1 @ set svc, irqs off
+ mrc p15, 0, r1, c0, c0, 5
+ and r1, r1, #0xf
+ cmp r1, #0
+ beq cpu0Run
+cpu1loop:
+ mov r3, #50
+ wfene
+ b cpu1loop
+cpu0Run:
+1: mov r1, r1
+ /* get boot ram base */
+ adr r1, 9b
+ /* resume data offset, from ram base */
+ ldr r5, 8f
+ /* resume data addr */
+ add r5, r5, r1
+
+ ldr r3 , [r5, #(RKPM_BOOTDATA_L2LTY_F*4)]
+ cmp r3, #1
+ bne arm_errata__818325
+ ldr r3 , [r5, #(RKPM_BOOTDATA_L2LTY*4)]
+ mcr p15, 1, r3, c9, c0, 2
+
+arm_errata__818325:
+ ldr r3 , [r5, #(RKPM_BOOTDATA_ARM_ERRATA_818325_F*4)]
+ cmp r3, #1
+ bne sp_set
+ ldr r3 , [r5, #(RKPM_BOOTDATA_ARM_ERRATA_818325*4)]
+ mcreq p15, 0, r3, c15, c0, 1
+
+sp_set:
+ ldr sp, [r5, #(RKPM_BOOTDATA_CPUSP*4)]
+ /*get SLP_DDR_NEED_RES ,if it is 1 ,ddr need to reusme*/
+ ldr r3, [r5, #(RKPM_BOOTDATA_DDR_F*4)]
+ cmp r3, #1
+ bne res
+ /* ddr resume code */
+ ldr r1, [r5, #(RKPM_BOOTDATA_DDRCODE*4)]
+ /* ddr resume data */
+ ldr r0, [r5, #(RKPM_BOOTDATA_DDRDATA*4)]
+ blx r1
+res:
+ ldr pc, [r5, #(RKPM_BOOTDATA_CPUCODE*4)]
+8: .long (RKPM_BOOT_CODE_OFFSET + RKPM_BOOT_CODE_SIZE)
+ENDPROC(rockchip_slp_cpu_resume)
--
To view, visit
https://chromium-review.googlesource.com/215780
To unsubscribe, visit
https://chromium-review.googlesource.com/settings
Gerrit-MessageType: newchange
Gerrit-Change-Id: If5b4dc6b97414deff9f6b4719f95268c949fdf17
Gerrit-PatchSet: 1
Gerrit-Project: chromiumos/third_party/kernel
Gerrit-Branch: chromeos-3.14
Gerrit-Owner: Chris Zhong <
z...@rock-chips.com>
Gerrit-Reviewer: Tony Xie <
tony...@rock-chips.com>