X-Git-Url: http://plrg.eecs.uci.edu/git/?a=blobdiff_plain;ds=sidebyside;f=arch%2Farm%2Fmach-rockchip%2Frk3036.c;h=89b3850da268bba9d6d8a829800ff05b31dec45b;hb=d91ca21f9ac06733b3895deab952e016ed20c2a1;hp=65a3d8d552b160a9913f94e333128618dfcd5ac1;hpb=77ddfc9d50214cb453dc280580419fc551e77ffe;p=firefly-linux-kernel-4.4.55.git diff --git a/arch/arm/mach-rockchip/rk3036.c b/arch/arm/mach-rockchip/rk3036.c index 65a3d8d552b1..89b3850da268 100755 --- a/arch/arm/mach-rockchip/rk3036.c +++ b/arch/arm/mach-rockchip/rk3036.c @@ -23,8 +23,10 @@ #include #include #include +#include #include #include +#include #include #include #include @@ -34,7 +36,6 @@ #include #include #include -#include "cpu_axi.h" #include "loader.h" #define CPU 3036 #include "sram.h" @@ -51,166 +52,652 @@ #define RK3036_IMEM_VIRT (RK_BOOTRAM_VIRT + SZ_32K) #define RK3036_TIMER5_VIRT (RK_TIMER_VIRT + 0xa0) - static struct map_desc rk3036_io_desc[] __initdata = { - RK3036_DEVICE(CRU), - RK3036_DEVICE(GRF), - RK3036_DEVICE(ROM), - RK3036_DEVICE(EFUSE), - RK_DEVICE(RK_DDR_VIRT, RK3036_DDR_PCTL_PHYS, RK3036_DDR_PCTL_SIZE), - RK_DEVICE(RK_DDR_VIRT + RK3036_DDR_PCTL_SIZE, RK3036_DDR_PHY_PHYS, RK3036_DDR_PHY_SIZE), - RK_DEVICE(RK_GPIO_VIRT(0), RK3036_GPIO0_PHYS, RK3036_GPIO_SIZE), - RK_DEVICE(RK_GPIO_VIRT(1), RK3036_GPIO1_PHYS, RK3036_GPIO_SIZE), - RK_DEVICE(RK_GPIO_VIRT(2), RK3036_GPIO2_PHYS, RK3036_GPIO_SIZE), - RK_DEVICE(RK_DEBUG_UART_VIRT, RK3036_UART2_PHYS, RK3036_UART_SIZE), - RK_DEVICE(RK_GIC_VIRT, RK3036_GIC_DIST_PHYS, RK3036_GIC_DIST_SIZE), - RK_DEVICE(RK_GIC_VIRT + RK3036_GIC_DIST_SIZE,RK3036_GIC_CPU_PHYS, RK3036_GIC_CPU_SIZE), - RK_DEVICE(RK3036_IMEM_VIRT, RK3036_IMEM_PHYS, SZ_4K), - RK_DEVICE(RK_TIMER_VIRT, RK3036_TIMER_PHYS, RK3036_TIMER_SIZE), + RK3036_DEVICE(CRU), + RK3036_DEVICE(GRF), + RK3036_DEVICE(ROM), + RK3036_DEVICE(EFUSE), + RK3036_DEVICE(CPU_AXI_BUS), + RK_DEVICE(RK_DDR_VIRT, RK3036_DDR_PCTL_PHYS, RK3036_DDR_PCTL_SIZE), + RK_DEVICE(RK_DDR_VIRT + RK3036_DDR_PCTL_SIZE, RK3036_DDR_PHY_PHYS, + RK3036_DDR_PHY_SIZE), + RK_DEVICE(RK_GPIO_VIRT(0), RK3036_GPIO0_PHYS, RK3036_GPIO_SIZE), + RK_DEVICE(RK_GPIO_VIRT(1), RK3036_GPIO1_PHYS, RK3036_GPIO_SIZE), + RK_DEVICE(RK_GPIO_VIRT(2), RK3036_GPIO2_PHYS, RK3036_GPIO_SIZE), + RK_DEVICE(RK_DEBUG_UART_VIRT, RK3036_UART2_PHYS, RK3036_UART_SIZE), + RK_DEVICE(RK_GIC_VIRT, RK3036_GIC_DIST_PHYS, RK3036_GIC_DIST_SIZE), + RK_DEVICE(RK_GIC_VIRT + RK3036_GIC_DIST_SIZE, RK3036_GIC_CPU_PHYS, + RK3036_GIC_CPU_SIZE), + RK_DEVICE(RK3036_IMEM_VIRT, RK3036_IMEM_PHYS, SZ_4K), + RK_DEVICE(RK_TIMER_VIRT, RK3036_TIMER_PHYS, RK3036_TIMER_SIZE), + RK_DEVICE(RK_PWM_VIRT, RK3036_PWM_PHYS, RK3036_PWM_SIZE), }; static void __init rk3036_boot_mode_init(void) { - u32 flag = readl_relaxed(RK_GRF_VIRT + RK3036_GRF_OS_REG0); - u32 mode = readl_relaxed(RK_GRF_VIRT + RK3036_GRF_OS_REG1); - u32 rst_st = readl_relaxed(RK_CRU_VIRT + RK3036_CRU_RST_ST); + u32 flag = readl_relaxed(RK_GRF_VIRT + RK3036_GRF_OS_REG4); + u32 mode = readl_relaxed(RK_GRF_VIRT + RK3036_GRF_OS_REG5); + u32 rst_st = readl_relaxed(RK_CRU_VIRT + RK3036_CRU_RST_ST); - if (flag == (SYS_KERNRL_REBOOT_FLAG | BOOT_RECOVER)) - mode = BOOT_MODE_RECOVERY; - if (rst_st & ((1 << 2) | (1 << 3))) - mode = BOOT_MODE_WATCHDOG; - rockchip_boot_mode_init(flag, mode); + if (flag == (SYS_KERNRL_REBOOT_FLAG | BOOT_RECOVER)) + mode = BOOT_MODE_RECOVERY; + if (rst_st & ((1 << 2) | (1 << 3))) + mode = BOOT_MODE_WATCHDOG; + rockchip_boot_mode_init(flag, mode); } static void usb_uart_init(void) { - u32 soc_status0 = readl_relaxed(RK_GRF_VIRT + RK3036_GRF_SOC_STATUS0); - writel_relaxed(0x34000000, RK_GRF_VIRT + RK3036_GRF_UOC1_CON4); #ifdef CONFIG_RK_USB_UART - if (!(soc_status0 & (1 << 14)) && (soc_status0 & (1 << 17))) { - /* software control usb phy enable */ - writel_relaxed(0x007f0055, RK_GRF_VIRT + RK3036_GRF_UOC0_CON5); - writel_relaxed(0x34003000, RK_GRF_VIRT + RK3036_GRF_UOC1_CON4); - } + u32 soc_status0 = readl_relaxed(RK_GRF_VIRT + RK3036_GRF_SOC_STATUS0); +#endif + writel_relaxed(0x34000000, RK_GRF_VIRT + RK3036_GRF_UOC1_CON4); +#ifdef CONFIG_RK_USB_UART + if (!(soc_status0 & (1 << 14)) && (soc_status0 & (1 << 17))) { + /* software control usb phy enable */ + writel_relaxed(0x007f0055, RK_GRF_VIRT + RK3036_GRF_UOC0_CON5); + writel_relaxed(0x34003000, RK_GRF_VIRT + RK3036_GRF_UOC1_CON4); + } #endif -#ifdef RK_DEBUG_UART_VIRT - writel_relaxed(0x07, RK_DEBUG_UART_VIRT + 0x88); - writel_relaxed(0x07, RK_DEBUG_UART_VIRT + 0x88); - writel_relaxed(0x00, RK_DEBUG_UART_VIRT + 0x04); - writel_relaxed(0x83, RK_DEBUG_UART_VIRT + 0x0c); - writel_relaxed(0x0d, RK_DEBUG_UART_VIRT + 0x00); - writel_relaxed(0x00, RK_DEBUG_UART_VIRT + 0x04); - writel_relaxed(0x03, RK_DEBUG_UART_VIRT + 0x0c); -#endif //end of DEBUG_UART_BASE + + writel_relaxed(0x07, RK_DEBUG_UART_VIRT + 0x88); + writel_relaxed(0x00, RK_DEBUG_UART_VIRT + 0x04); + writel_relaxed(0x83, RK_DEBUG_UART_VIRT + 0x0c); + writel_relaxed(0x0d, RK_DEBUG_UART_VIRT + 0x00); + writel_relaxed(0x00, RK_DEBUG_UART_VIRT + 0x04); + writel_relaxed(0x03, RK_DEBUG_UART_VIRT + 0x0c); } static void __init rk3036_dt_map_io(void) { - rockchip_soc_id = ROCKCHIP_SOC_RK3036; + rockchip_soc_id = ROCKCHIP_SOC_RK3036; - iotable_init(rk3036_io_desc, ARRAY_SIZE(rk3036_io_desc)); - debug_ll_io_init(); - usb_uart_init(); + iotable_init(rk3036_io_desc, ARRAY_SIZE(rk3036_io_desc)); + debug_ll_io_init(); + usb_uart_init(); - /* enable timer5 for core */ - writel_relaxed(0, RK3036_TIMER5_VIRT + 0x10); - dsb(); - writel_relaxed(0xFFFFFFFF, RK3036_TIMER5_VIRT + 0x00); - writel_relaxed(0xFFFFFFFF, RK3036_TIMER5_VIRT + 0x04); - dsb(); - writel_relaxed(1, RK3036_TIMER5_VIRT + 0x10); - dsb(); + /* enable timer5 for core */ + writel_relaxed(0, RK3036_TIMER5_VIRT + 0x10); + dsb(); + writel_relaxed(0xFFFFFFFF, RK3036_TIMER5_VIRT + 0x00); + writel_relaxed(0xFFFFFFFF, RK3036_TIMER5_VIRT + 0x04); + dsb(); + writel_relaxed(1, RK3036_TIMER5_VIRT + 0x10); + dsb(); - rk3036_boot_mode_init(); + rk3036_boot_mode_init(); } extern void secondary_startup(void); static int rk3036_sys_set_power_domain(enum pmu_power_domain pd, bool on) { - if (on) { + if (on) { #ifdef CONFIG_SMP - if(PD_CPU_1 == pd) { - writel_relaxed(0x20000, RK_CRU_VIRT + RK3036_CRU_SOFTRST0_CON); - dsb(); - udelay(10); - writel_relaxed(virt_to_phys(secondary_startup), RK3036_IMEM_VIRT + 8); - writel_relaxed(0xDEADBEAF, RK3036_IMEM_VIRT + 4); - dsb_sev(); - } + if (PD_CPU_1 == pd) { + writel_relaxed(0x20000 + , RK_CRU_VIRT + RK3036_CRU_SOFTRST0_CON); + dsb(); + udelay(10); + writel_relaxed(virt_to_phys(secondary_startup), + RK3036_IMEM_VIRT + 8); + writel_relaxed(0xDEADBEAF, RK3036_IMEM_VIRT + 4); + dsb_sev(); + } #endif - } else { + } else { #ifdef CONFIG_SMP - if(PD_CPU_1 == pd) { - writel_relaxed(0x20002, RK_CRU_VIRT + RK3036_CRU_SOFTRST0_CON); - dsb(); - } + if (PD_CPU_1 == pd) { + writel_relaxed(0x20002 + , RK_CRU_VIRT + RK3036_CRU_SOFTRST0_CON); + dsb(); + } #endif - } + } - return 0; + return 0; } static bool rk3036_pmu_power_domain_is_on(enum pmu_power_domain pd) { - return 1; + return 1; } static int rk3036_pmu_set_idle_request(enum pmu_idle_req req, bool idle) { - return 0; + return 0; } static void __init rk3036_dt_init_timer(void) { - rockchip_pmu_ops.set_power_domain = rk3036_sys_set_power_domain; - rockchip_pmu_ops.power_domain_is_on = rk3036_pmu_power_domain_is_on; - rockchip_pmu_ops.set_idle_request = rk3036_pmu_set_idle_request; - of_clk_init(NULL); - clocksource_of_init(); + rockchip_pmu_ops.set_power_domain = rk3036_sys_set_power_domain; + rockchip_pmu_ops.power_domain_is_on = rk3036_pmu_power_domain_is_on; + rockchip_pmu_ops.set_idle_request = rk3036_pmu_set_idle_request; + of_clk_init(NULL); + clocksource_of_init(); +} + +#ifdef CONFIG_PM +static inline void rk3036_uart_printch(char byte) +{ +write_uart: + 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(); + + if (byte == '\n') { + byte = '\r'; + goto write_uart; + } +} + +static void rk3036_ddr_printch(char byte) +{ + rk3036_uart_printch(byte); + + rk_last_log_text(&byte, 1); + + if (byte == '\n') { + byte = '\r'; + rk_last_log_text(&byte, 1); + } +} + +enum rk_plls_id { + APLL_ID = 0, + DPLL_ID, + GPLL_ID, + RK3036_END_PLL_ID, +}; + +#define GPIO_INTEN 0x30 +#define GPIO_INT_STATUS 0x40 +#define GIC_DIST_PENDING_SET 0x200 +static void rk3036_pm_dump_irq(void) +{ + u32 irq_gpio = (readl_relaxed(RK_GIC_VIRT + + GIC_DIST_PENDING_SET + 8) >> 4) & 7; + u32 irq[4]; + int i; + + for (i = 0; i < ARRAY_SIZE(irq); i++) { + irq[i] = readl_relaxed(RK_GIC_VIRT + GIC_DIST_PENDING_SET + + (1 + i) * 4); + if (irq[i]) + log_wakeup_reason(32 * (i + 1) + fls(irq[i]) - 1); + } + pr_info("wakeup irq: %08x %08x %08x %08x\n", + irq[0], irq[1], irq[2], irq[3]); + for (i = 0; i <= 2; i++) { + if (irq_gpio & (1 << i)) + pr_info("wakeup gpio%d: %08x\n", i, + readl_relaxed(RK_GPIO_VIRT(i) + + GPIO_INT_STATUS)); + } +} + +#define DUMP_GPIO_INTEN(ID) \ + do { \ + u32 en = readl_relaxed(RK_GPIO_VIRT(ID) + GPIO_INTEN); \ + if (en) { \ + pr_info("GPIO%d_INTEN: %08x\n", ID, en); \ + } \ + } while (0) + +static void rk3036_pm_dump_inten(void) +{ + DUMP_GPIO_INTEN(0); + DUMP_GPIO_INTEN(1); + DUMP_GPIO_INTEN(2); +} + +static void rkpm_prepare(void) +{ + rk3036_pm_dump_inten(); +} +static void rkpm_finish(void) +{ + rk3036_pm_dump_irq(); +} + +static u32 clk_ungt_msk[RK3036_CRU_CLKGATES_CON_CNT]; +/*first clk gating setting*/ + +static u32 clk_ungt_msk_1[RK3036_CRU_CLKGATES_CON_CNT]; +/* first clk gating setting*/ + +static u32 clk_ungt_save[RK3036_CRU_CLKGATES_CON_CNT]; +/*first clk gating value saveing*/ + +static u32 *p_rkpm_clkgt_last_set; +#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 void gtclks_suspend(void) +{ + int i; + + for (i = 0; i < RK3036_CRU_CLKGATES_CON_CNT; i++) { + clk_ungt_save[i] = cru_readl(RK3036_CRU_CLKGATES_CON(i)); + if (i != 10) + CLK_MSK_UNGATING(clk_ungt_msk[i] + , RK3036_CRU_CLKGATES_CON(i)); + else + cru_writel(clk_ungt_msk[i], RK3036_CRU_CLKGATES_CON(i)); + } + + /*gpio0_a1 clk gate should be disable for volt adjust*/ + if (cru_readl(RK3036_CRU_CLKGATES_CON(8)) & 0x200) + cru_writel(0x02000000, RK3036_CRU_CLKGATES_CON(8)); +} + +static void gtclks_resume(void) +{ + int i; + + for (i = 0; i < RK3036_CRU_CLKGATES_CON_CNT; i++) { + if (i != 10) + cru_writel(clk_ungt_save[i] | 0xffff0000 + , RK3036_CRU_CLKGATES_CON(i)); + else + cru_writel(clk_ungt_save[i] + , RK3036_CRU_CLKGATES_CON(i)); + } +} + +static void clks_gating_suspend_init(void) +{ + p_rkpm_clkgt_last_set = &clk_ungt_msk_1[0]; + if (clk_suspend_clkgt_info_get(clk_ungt_msk, p_rkpm_clkgt_last_set + , RK3036_CRU_CLKGATES_CON_CNT) == RK3036_CRU_CLKGATES_CON(0)) + rkpm_set_ops_gtclks(gtclks_suspend, gtclks_resume); +} + +#define RK3036_PLL_BYPASS CRU_W_MSK_SETBITS(1, 0xF, 0x01) +#define RK3036_PLL_NOBYPASS CRU_W_MSK_SETBITS(0, 0xF, 0x01) +#define RK3036_PLL_POWERDOWN CRU_W_MSK_SETBITS(1, 0xD, 0x01) +#define RK3036_PLL_POWERON CRU_W_MSK_SETBITS(0, 0xD, 0x01) + +#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 gpio0_readl(offset) readl_relaxed(RK_GPIO_VIRT(0) + offset) +#define gpio0_writel(v, offset) do { writel_relaxed(v, RK_GPIO_VIRT(0) \ + + offset); dsb(); } while (0) + +static u32 plls_con0_save[RK3036_END_PLL_ID]; +static u32 plls_con1_save[RK3036_END_PLL_ID]; +static u32 plls_con2_save[RK3036_END_PLL_ID]; + +static u32 cru_mode_con; +static u32 clk_sel0, clk_sel1, clk_sel10; +static void pm_pll_wait_lock(u32 pll_idx) +{ + u32 delay = 600000U; + + dsb(); + dsb(); + dsb(); + dsb(); + dsb(); + dsb(); + while (delay > 0) { + if ((cru_readl(RK3036_PLL_CONS(pll_idx, 1)) & (0x1 << 10))) + break; + delay--; + } + if (delay == 0) { + rkpm_ddr_printascii("unlock-pll:"); + rkpm_ddr_printhex(pll_idx); + rkpm_ddr_printch('\n'); + } +} + +static void pll_udelay(u32 udelay) +{ + u32 mode; + + mode = cru_readl(RK3036_CRU_MODE_CON); + cru_writel(RK3036_PLL_MODE_SLOW(APLL_ID), RK3036_CRU_MODE_CON); + rkpm_udelay(udelay * 5); + cru_writel(mode|(RK3036_PLL_MODE_MSK(APLL_ID) + << 16), RK3036_CRU_MODE_CON); +} + +static inline void plls_suspend(u32 pll_id) +{ + plls_con0_save[pll_id] = cru_readl(RK3036_PLL_CONS((pll_id), 0)); + plls_con1_save[pll_id] = cru_readl(RK3036_PLL_CONS((pll_id), 1)); + plls_con2_save[pll_id] = cru_readl(RK3036_PLL_CONS((pll_id), 2)); + + /*cru_writel(RK3036_PLL_BYPASS, RK3036_PLL_CONS((pll_id), 0));*/ + cru_writel(RK3036_PLL_POWERDOWN, RK3036_PLL_CONS((pll_id), 1)); +} +static inline void plls_resume(u32 pll_id) +{ + u32 pllcon0, pllcon1, pllcon2; + + pllcon0 = plls_con0_save[pll_id]; + pllcon1 = plls_con1_save[pll_id]; + pllcon2 = plls_con2_save[pll_id]; +/* + cru_writel(pllcon0 | 0xffff0000, RK3036_PLL_CONS(pll_id, 0)); + cru_writel(pllcon1 | 0xf5ff0000, RK3036_PLL_CONS(pll_id, 1)); + cru_writel(pllcon2, RK3036_PLL_CONS(pll_id, 2)); +*/ + cru_writel(RK3036_PLL_POWERON, RK3036_PLL_CONS((pll_id), 1)); + + pll_udelay(5); + + pll_udelay(168); + pm_pll_wait_lock(pll_id); +} + +static void pm_plls_suspend(void) +{ + cru_mode_con = cru_readl(RK3036_CRU_MODE_CON); + + clk_sel0 = cru_readl(RK3036_CRU_CLKSELS_CON(0)); + clk_sel1 = cru_readl(RK3036_CRU_CLKSELS_CON(1)); + clk_sel10 = cru_readl(RK3036_CRU_CLKSELS_CON(10)); + + cru_writel(RK3036_PLL_MODE_SLOW(GPLL_ID), RK3036_CRU_MODE_CON); + cru_writel(0 + |CRU_W_MSK_SETBITS(0, 0, 0x1f) + |CRU_W_MSK_SETBITS(0, 8, 0x3) + |CRU_W_MSK_SETBITS(0, 12, 0x3) + , RK3036_CRU_CLKSELS_CON(10)); + plls_suspend(GPLL_ID); + + + cru_writel(RK3036_PLL_MODE_SLOW(APLL_ID), RK3036_CRU_MODE_CON); + + cru_writel(0 + |CRU_W_MSK_SETBITS(0, 0, 0x1f) + |CRU_W_MSK_SETBITS(0, 8, 0x1f) + , RK3036_CRU_CLKSELS_CON(0)); + + cru_writel(0 + |CRU_W_MSK_SETBITS(0, 0, 0xf) + |CRU_W_MSK_SETBITS(0, 4, 0x7) + |CRU_W_MSK_SETBITS(0, 8, 0x3) + |CRU_W_MSK_SETBITS(0, 12, 0x7) + , RK3036_CRU_CLKSELS_CON(1)); + + plls_suspend(APLL_ID); +} + +static void pm_plls_resume(void) +{ + plls_resume(APLL_ID); + cru_writel(clk_sel0 | (CRU_W_MSK(0, 0x1f) | CRU_W_MSK(8, 0x1f)) + , RK3036_CRU_CLKSELS_CON(0)); + cru_writel(clk_sel1 | (CRU_W_MSK(0, 0xf) | CRU_W_MSK(4, 0x7) + |CRU_W_MSK(8, 0x3) | CRU_W_MSK(12, 0x7)) + , RK3036_CRU_CLKSELS_CON(1)); + cru_writel(cru_mode_con | (RK3036_PLL_MODE_MSK(APLL_ID) << 16) + , RK3036_CRU_MODE_CON); + + plls_resume(GPLL_ID); + cru_writel(clk_sel10 | (CRU_W_MSK(0, 0x1f) | CRU_W_MSK(8, 0x3) + | CRU_W_MSK(12, 0x3)), RK3036_CRU_CLKSELS_CON(10)); + cru_writel(cru_mode_con | (RK3036_PLL_MODE_MSK(GPLL_ID) + << 16), RK3036_CRU_MODE_CON); +} + +#include "ddr_rk3036.c" +#include "pm-pie.c" + +char PIE_DATA(sram_stack)[1024]; +EXPORT_PIE_SYMBOL(DATA(sram_stack)); + +static int __init rk3036_pie_init(void) +{ + int err; + + if (!cpu_is_rk3036()) + return 0; + + err = rockchip_pie_init(); + if (err) + return err; + + rockchip_pie_chunk = pie_load_sections(rockchip_sram_pool, rk3036); + if (IS_ERR(rockchip_pie_chunk)) { + err = PTR_ERR(rockchip_pie_chunk); + pr_err("%s: failed to load section %d\n", __func__, err); + rockchip_pie_chunk = NULL; + return err; + } + + rockchip_sram_virt = kern_to_pie(rockchip_pie_chunk + , &__pie_common_start[0]); + rockchip_sram_stack = kern_to_pie(rockchip_pie_chunk + , (char *)DATA(sram_stack) + sizeof(DATA(sram_stack))); + + return 0; +} +arch_initcall(rk3036_pie_init); + +static void reg_pread(void) +{ + volatile u32 n; + int i; + + volatile u32 *temp = (volatile unsigned int *)rockchip_sram_virt; + + flush_cache_all(); + outer_flush_all(); + local_flush_tlb_all(); + + for (i = 0; i < 2; i++) { + n = temp[1024 * i]; + barrier(); + } + + n = readl_relaxed(RK_GPIO_VIRT(0)); + n = readl_relaxed(RK_GPIO_VIRT(1)); + n = readl_relaxed(RK_GPIO_VIRT(2)); + + n = readl_relaxed(RK_DEBUG_UART_VIRT); + n = readl_relaxed(RK_CPU_AXI_BUS_VIRT); + n = readl_relaxed(RK_DDR_VIRT); + n = readl_relaxed(RK_GRF_VIRT); + n = readl_relaxed(RK_CRU_VIRT); + n = readl_relaxed(RK_PWM_VIRT); +} + +#define RK3036_CRU_UNGATING_OPS(id) cru_writel(\ + CRU_W_MSK_SETBITS(0, (id), 0x1), RK3036_CRU_UART_GATE) +#define RK3036_CRU_GATING_OPS(id) cru_writel(\ + CRU_W_MSK_SETBITS(1, (id), 0x1), RK3036_CRU_UART_GATE) + +static inline void uart_printch(char bbyte) +{ + u32 reg_save; + u32 u_clk_id = (RK3036_CLKGATE_UART0_SRC + CONFIG_RK_DEBUG_UART * 2); + u32 u_pclk_id = (RK3036_CLKGATE_UART0_PCLK + CONFIG_RK_DEBUG_UART * 2); + + reg_save = cru_readl(RK3036_CRU_UART_GATE); + RK3036_CRU_UNGATING_OPS(u_clk_id); + RK3036_CRU_UNGATING_OPS(u_pclk_id); + rkpm_udelay(1); + + +write_uart: + writel_relaxed(bbyte, RK_DEBUG_UART_VIRT); + dsb(); + + while (!(readl_relaxed(RK_DEBUG_UART_VIRT + 0x14) & 0x40)) + barrier(); + + if (bbyte == '\n') { + bbyte = '\r'; + goto write_uart; + } + + cru_writel(reg_save | CRU_W_MSK(u_clk_id + , 0x1), RK3036_CRU_UART_GATE); + cru_writel(reg_save | CRU_W_MSK(u_pclk_id + , 0x1), RK3036_CRU_UART_GATE); + + + if (0) { +write_uart1: + writel_relaxed(bbyte, RK_DEBUG_UART_VIRT); + dsb(); + + while (!(readl_relaxed(RK_DEBUG_UART_VIRT + 0x14) & 0x40)) + barrier(); + if (bbyte == '\n') { + bbyte = '\r'; + goto write_uart1; + } + } +} + + +void PIE_FUNC(sram_printch)(char byte) +{ + uart_printch(byte); +} + +static __sramdata u32 rkpm_pwm_duty0; +static __sramdata u32 rkpm_pwm_duty1; +static __sramdata u32 rkpm_pwm_duty2; +#define PWM_VOLTAGE 0x600 + +void PIE_FUNC(pwm_regulator_suspend)(void) +{ + if (rkpm_chk_sram_ctrbit(RKPM_CTR_VOL_PWM0)) { + rkpm_pwm_duty0 = readl_relaxed(RK_PWM_VIRT + 0x08); + writel_relaxed(PWM_VOLTAGE, RK_PWM_VIRT + 0x08); + } + + if (rkpm_chk_sram_ctrbit(RKPM_CTR_VOL_PWM1)) { + rkpm_pwm_duty1 = readl_relaxed(RK_PWM_VIRT + 0x18); + writel_relaxed(PWM_VOLTAGE, RK_PWM_VIRT + 0x18); + } + + if (rkpm_chk_sram_ctrbit(RKPM_CTR_VOL_PWM2)) { + rkpm_pwm_duty2 = readl_relaxed(RK_PWM_VIRT + 0x28); + writel_relaxed(PWM_VOLTAGE, RK_PWM_VIRT + 0x28); + } + //rkpm_udelay(30); +} + +void PIE_FUNC(pwm_regulator_resume)(void) +{ + rkpm_udelay(30); + + + if (rkpm_chk_sram_ctrbit(RKPM_CTR_VOL_PWM0)) + writel_relaxed(rkpm_pwm_duty0, RK_PWM_VIRT + 0x08); + + if (rkpm_chk_sram_ctrbit(RKPM_CTR_VOL_PWM1)) + writel_relaxed(rkpm_pwm_duty1, RK_PWM_VIRT + 0x18); + + if (rkpm_chk_sram_ctrbit(RKPM_CTR_VOL_PWM2)) + writel_relaxed(rkpm_pwm_duty2, RK_PWM_VIRT + 0x28); + rkpm_udelay(30); +} + +static void __init rk3036_suspend_init(void) +{ + struct device_node *parent; + u32 pm_ctrbits; + + PM_LOG("%s enter\n", __func__); + + parent = of_find_node_by_name(NULL, "rockchip_suspend"); + + if (IS_ERR_OR_NULL(parent)) { + PM_ERR("%s dev node err\n", __func__); + return; + } + + if (of_property_read_u32_array(parent, "rockchip,ctrbits" + , &pm_ctrbits, 1)) { + PM_ERR("%s:get pm ctr error\n", __func__); + return; + } + PM_LOG("%s: pm_ctrbits =%x\n", __func__, pm_ctrbits); + rkpm_set_ctrbits(pm_ctrbits); + + clks_gating_suspend_init(); + rkpm_set_ops_prepare_finish(rkpm_prepare, rkpm_finish); + rkpm_set_ops_plls(pm_plls_suspend, pm_plls_resume); + + rkpm_set_ops_regs_pread(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_volt(fn_to_pie(rockchip_pie_chunk + , &FUNC(pwm_regulator_suspend)) + , fn_to_pie(rockchip_pie_chunk, &FUNC(pwm_regulator_resume))); + + + rkpm_set_sram_ops_printch(fn_to_pie(rockchip_pie_chunk + , &FUNC(sram_printch))); + rkpm_set_ops_printch(rk3036_ddr_printch); +} +#endif + +static void __init rk3036_init_suspend(void) +{ + pr_info("%s\n", __func__); + rockchip_suspend_init(); + rkpm_pie_init(); + rk3036_suspend_init(); } static void __init rk3036_init_late(void) { - return; +#ifdef CONFIG_PM + rk3036_init_suspend(); +#endif } static void __init rk3036_reserve(void) { - /* reserve memory for ION */ - //rockchip_ion_reserve(); - - return; + /* reserve memory for ION */ + rockchip_ion_reserve(); } static void rk3036_restart(char mode, const char *cmd) { - u32 boot_flag, boot_mode; - - rockchip_restart_get_boot_mode(cmd, &boot_flag, &boot_mode); + u32 boot_flag, boot_mode; - writel_relaxed(boot_flag, RK_GRF_VIRT + RK3036_GRF_OS_REG0); // for loader - writel_relaxed(boot_mode, RK_GRF_VIRT + RK3036_GRF_OS_REG1); // for linux - dsb(); + rockchip_restart_get_boot_mode(cmd, &boot_flag, &boot_mode); + /* for loader */ + writel_relaxed(boot_flag, RK_GRF_VIRT + RK3036_GRF_OS_REG4); + /* for linux */ + writel_relaxed(boot_mode, RK_GRF_VIRT + RK3036_GRF_OS_REG5); + dsb(); - /* pll enter slow mode */ - writel_relaxed(0x30110000, RK_CRU_VIRT + RK3036_CRU_MODE_CON); - dsb(); - writel_relaxed(0xeca8, RK_CRU_VIRT + RK3036_CRU_GLB_SRST_SND_VALUE); - dsb(); + /* pll enter slow mode */ + writel_relaxed(0x30110000, RK_CRU_VIRT + RK3036_CRU_MODE_CON); + dsb(); + writel_relaxed(0xeca8, RK_CRU_VIRT + RK3036_CRU_GLB_SRST_SND_VALUE); + dsb(); } -static const char * const rk3036_dt_compat[] __initconst = { - "rockchip,rk3036", - NULL, +static const char *const rk3036_dt_compat[] __initconst = { + "rockchip,rk3036", + NULL, }; DT_MACHINE_START(RK3036_DT, "Rockchip RK3036") - .dt_compat = rk3036_dt_compat, - .smp = smp_ops(rockchip_smp_ops), - .reserve = rk3036_reserve, - .map_io = rk3036_dt_map_io, - .init_time = rk3036_dt_init_timer, - .init_late = rk3036_init_late, - .reserve = rk3036_reserve, - .restart = rk3036_restart, + .dt_compat = rk3036_dt_compat, + .smp = smp_ops(rockchip_smp_ops), + .reserve = rk3036_reserve, + .map_io = rk3036_dt_map_io, + .init_time = rk3036_dt_init_timer, + .init_late = rk3036_init_late, + .reserve = rk3036_reserve, + .restart = rk3036_restart, MACHINE_END