/*
- * Device Tree support for Rockchip RK3288
- *
* Copyright (C) 2014 ROCKCHIP, Inc.
*
* This program is free software; you can redistribute it and/or modify
#include <linux/of_platform.h>
#include <linux/rockchip/common.h>
#include <linux/rockchip/cpu.h>
+#include <linux/rockchip/cpu_axi.h>
#include <linux/rockchip/cru.h>
#include <linux/rockchip/dvfs.h>
#include <linux/rockchip/grf.h>
#include <asm/cputype.h>
#include <asm/mach/arch.h>
#include <asm/mach/map.h>
-#include "cpu_axi.h"
#include "loader.h"
+#include "rk3126b.h"
#define CPU 312x
#include "sram.h"
#include "pm.h"
#include "pm-rk312x.c"
+#include <linux/rockchip/cpu.h>
#define RK312X_DEVICE(name) \
{ \
.virtual = (unsigned long) RK_##name##_VIRT, \
RK312X_DEVICE(PMU),
RK312X_DEVICE(EFUSE),
RK312X_DEVICE(TIMER),
+ RK312X_DEVICE(CPU_AXI_BUS),
RK_DEVICE(RK_DEBUG_UART_VIRT, RK312X_UART2_PHYS, RK312X_UART_SIZE),
RK_DEVICE(RK_DDR_VIRT, RK312X_DDR_PCTL_PHYS, RK312X_DDR_PCTL_SIZE),
RK_DEVICE(RK_DDR_VIRT + RK312X_DDR_PCTL_SIZE, RK312X_DDR_PHY_PHYS, RK312X_DDR_PHY_SIZE),
RK_DEVICE(RK_GIC_VIRT, RK312X_GIC_DIST_PHYS, RK312X_GIC_DIST_SIZE),
RK_DEVICE(RK_GIC_VIRT + RK312X_GIC_DIST_SIZE, RK312X_GIC_CPU_PHYS, RK312X_GIC_CPU_SIZE),
RK_DEVICE(RK312X_IMEM_VIRT, RK312X_IMEM_PHYS, RK312X_IMEM_SIZE),
+ RK_DEVICE(RK_PWM_VIRT, RK312X_PWM_PHYS, RK312X_PWM_SIZE),
};
+
+static void __init rk312x_boot_mode_init(void)
+{
+ u32 flag = readl_relaxed(RK_PMU_VIRT + RK312X_PMU_SYS_REG0);
+ u32 mode = readl_relaxed(RK_PMU_VIRT + RK312X_PMU_SYS_REG1);
+ u32 rst_st = readl_relaxed(RK_CRU_VIRT + RK312X_CRU_GLB_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);
+}
+
static void usb_uart_init(void)
{
#ifdef CONFIG_RK_USB_UART
static void __init rk312x_dt_map_io(void)
{
+ u32 v;
+
iotable_init(rk312x_io_desc, ARRAY_SIZE(rk312x_io_desc));
debug_ll_io_init();
usb_uart_init();
+ /* pmu reset by second global soft reset */
+ v = readl_relaxed(RK_CRU_VIRT + RK312X_CRU_GLB_CNT_TH);
+ v &= ~(3 << 12);
+ v |= 1 << 12;
+ writel_relaxed(v, RK_CRU_VIRT + RK312X_CRU_GLB_CNT_TH);
+
/* enable timer5 for core */
writel_relaxed(0, RK312X_TIMER5_VIRT + 0x10);
dsb();
dsb();
writel_relaxed(1, RK312X_TIMER5_VIRT + 0x10);
dsb();
+ writel_relaxed(0x80000000, RK_CRU_VIRT + RK312X_CRU_MISC_CON);
+ dsb();
+
+ rk312x_boot_mode_init();
+ rockchip_efuse_init();
}
static void __init rk3126_dt_map_io(void)
rockchip_soc_id = ROCKCHIP_SOC_RK3126;
rk312x_dt_map_io();
+
+ if (readl_relaxed(RK_GRF_VIRT + RK312X_GRF_CHIP_TAG) == 0x3136)
+ rockchip_soc_id = ROCKCHIP_SOC_RK3126B;
}
static void __init rk3128_dt_map_io(void)
u32 bit = pmu_idle_map[req];
u32 idle_mask = BIT(bit) | BIT(bit + 16);
u32 idle_target = (idle << bit) | (idle << (bit + 16));
+ u32 mask = BIT(bit);
spin_lock_irqsave(&pmu_idle_lock, flags);
val = pmu_readl(RK312X_PMU_IDLE_REQ);
if (idle)
- val |= idle_mask;
+ val |= mask;
else
- val &= ~idle_mask;
+ val &= ~mask;
pmu_writel(val, RK312X_PMU_IDLE_REQ);
dsb();
[PD_VIO] = 3,
};
-#if 1
static noinline void rk312x_do_pmu_set_power_domain(enum pmu_power_domain domain
, bool on)
{
while ((pmu_readl(RK312X_PMU_PWRDN_ST) & BIT(pmu_st_map[domain])) == on)
;
}
-#endif
+
static bool rk312x_pmu_power_domain_is_on(enum pmu_power_domain pd)
{
/*1"b0: power on, 1'b1: power off*/
return !(pmu_readl(RK312X_PMU_PWRDN_ST) & BIT(pmu_st_map[pd]));
}
static DEFINE_SPINLOCK(pmu_pd_lock);
+static u32 rga_qos[RK312X_CPU_AXI_QOS_NUM_REGS];
+static u32 ebc_qos[RK312X_CPU_AXI_QOS_NUM_REGS];
+static u32 iep_qos[RK312X_CPU_AXI_QOS_NUM_REGS];
+static u32 lcdc0_qos[RK312X_CPU_AXI_QOS_NUM_REGS];
+static u32 vip0_qos[RK312X_CPU_AXI_QOS_NUM_REGS];
+static u32 gpu_qos[RK312X_CPU_AXI_QOS_NUM_REGS];
+static u32 video_qos[RK312X_CPU_AXI_QOS_NUM_REGS];
+
+#define SAVE_QOS(array, NAME) RK312X_CPU_AXI_SAVE_QOS(array, RK312X_CPU_AXI_##NAME##_QOS_VIRT)
+#define RESTORE_QOS(array, NAME) RK312X_CPU_AXI_RESTORE_QOS(array, RK312X_CPU_AXI_##NAME##_QOS_VIRT)
static int rk312x_pmu_set_power_domain(enum pmu_power_domain pd, bool on)
{
if (rk312x_pmu_power_domain_is_on(pd) == on)
goto out;
if (!on) {
- if (pd == PD_GPU)
+ if (pd == PD_GPU) {
+ SAVE_QOS(gpu_qos, GPU);
rk312x_pmu_set_idle_request(IDLE_REQ_GPU, true);
- else if (pd == PD_VIO)
+ } else if (pd == PD_VIO) {
+ SAVE_QOS(rga_qos, VIO_RGA);
+ if (!soc_is_rk3126b())
+ SAVE_QOS(ebc_qos, VIO_EBC);
+ SAVE_QOS(iep_qos, VIO_IEP);
+ SAVE_QOS(lcdc0_qos, VIO_LCDC0);
+ SAVE_QOS(vip0_qos, VIO_VIP0);
rk312x_pmu_set_idle_request(IDLE_REQ_VIO, true);
- else if (pd == PD_VIDEO)
+ } else if (pd == PD_VIDEO) {
+ SAVE_QOS(video_qos, VIDEO);
rk312x_pmu_set_idle_request(IDLE_REQ_VIDEO, true);
+ }
}
rk312x_do_pmu_set_power_domain(pd, on);
if (on) {
- if (pd == PD_GPU)
+ if (pd == PD_GPU) {
rk312x_pmu_set_idle_request(IDLE_REQ_GPU, false);
- else if (pd == PD_VIO)
+ RESTORE_QOS(gpu_qos, GPU);
+ } else if (pd == PD_VIO) {
rk312x_pmu_set_idle_request(IDLE_REQ_VIO, false);
- else if (pd == PD_VIDEO)
+ RESTORE_QOS(rga_qos, VIO_RGA);
+ if (!soc_is_rk3126b())
+ RESTORE_QOS(ebc_qos, VIO_EBC);
+ RESTORE_QOS(iep_qos, VIO_IEP);
+ RESTORE_QOS(lcdc0_qos, VIO_LCDC0);
+ RESTORE_QOS(vip0_qos, VIO_VIP0);
+ } else if (pd == PD_VIDEO) {
rk312x_pmu_set_idle_request(IDLE_REQ_VIDEO, false);
+ RESTORE_QOS(video_qos, VIDEO);
+ }
}
out:
spin_unlock_irqrestore(&pmu_pd_lock, flags);
}
for (i = 0; i < RK312X_CRU_CLKGATES_CON_CNT; i++)
cru_writel(0xffff0000, RK312X_CRU_CLKGATES_CON(i));
- if (0) {
- if (on) {
+
+ if (on) {
#ifdef CONFIG_SMP
- if (pd >= PD_CPU_1 && pd <= PD_CPU_3) {
- writel_relaxed(0x20000 << (pd - PD_CPU_1),
- RK_CRU_VIRT + RK312X_CRU_SOFTRSTS_CON(0));
- dsb();
- udelay(10);
- writel_relaxed(virt_to_phys(secondary_startup),
- RK312X_IMEM_VIRT + 8);
- writel_relaxed(0xDEADBEAF, RK312X_IMEM_VIRT + 4);
- dsb_sev();
- }
+ if (pd >= PD_CPU_1 && pd <= PD_CPU_3) {
+ writel_relaxed(0x20000 << (pd - PD_CPU_1),
+ RK_CRU_VIRT + RK312X_CRU_SOFTRSTS_CON(0));
+ dsb();
+ udelay(10);
+ writel_relaxed(virt_to_phys(secondary_startup),
+ RK312X_IMEM_VIRT + 8);
+ writel_relaxed(0xDEADBEAF, RK312X_IMEM_VIRT + 4);
+ dsb_sev();
+ }
#endif
} else {
#ifdef CONFIG_SMP
- if (pd >= PD_CPU_1 && pd <= PD_CPU_3) {
- writel_relaxed(0x20002 << (pd - PD_CPU_1),
- RK_CRU_VIRT + RK312X_CRU_SOFTRSTS_CON(0));
- dsb();
- }
-#endif
+ if (pd >= PD_CPU_1 && pd <= PD_CPU_3) {
+ writel_relaxed(0x20002 << (pd - PD_CPU_1),
+ RK_CRU_VIRT + RK312X_CRU_SOFTRSTS_CON(0));
+ dsb();
}
+#endif
}
- if ((pd == PD_GPU) || (pd == PD_VIDEO) || (pd == PD_VIO))
+
+ if (((pd == PD_GPU) || (pd == PD_VIO) || (pd == PD_VIDEO)))
ret = rk312x_pmu_set_power_domain(pd, on);
for (i = 0; i < RK312X_CRU_CLKGATES_CON_CNT; i++) {
static void __init rk312x_reserve(void)
{
+ /* reserve memory for uboot */
+ rockchip_uboot_mem_reserve();
+
/* reserve memory for ION */
rockchip_ion_reserve();
}
+
#ifdef CONFIG_PM
-static void __init rk321x_init_suspend(void);
+static u32 rk_pmu_pwrdn_st;
+
+static void rk_pm_soc_pd_suspend(void)
+{
+ rk_pmu_pwrdn_st = pmu_readl(RK312X_PMU_PWRDN_ST);
+ if (!(rk_pmu_pwrdn_st & BIT(pmu_st_map[PD_GPU])))
+ rk312x_sys_set_power_domain(PD_GPU, false);
+
+ if (!(rk_pmu_pwrdn_st & BIT(pmu_st_map[PD_VIO])))
+ rk312x_sys_set_power_domain(PD_VIO, false);
+
+ if (!(rk_pmu_pwrdn_st & BIT(pmu_st_map[PD_VIDEO])))
+ rk312x_sys_set_power_domain(PD_VIDEO, false);
+}
+
+static void rk_pm_soc_pd_resume(void)
+{
+ if (!(rk_pmu_pwrdn_st & BIT(pmu_st_map[PD_VIDEO])))
+ rk312x_sys_set_power_domain(PD_VIDEO, true);
+
+ if (!(rk_pmu_pwrdn_st & BIT(pmu_st_map[PD_VIO])))
+ rk312x_sys_set_power_domain(PD_VIO, true);
+
+ if (!(rk_pmu_pwrdn_st & BIT(pmu_st_map[PD_GPU])))
+ rk312x_sys_set_power_domain(PD_GPU, true);
+}
+
+static void __init rk312x_init_suspend(void)
+{
+ pr_info("%s\n", __func__);
+ rkpm_pie_init();
+ rk312x_suspend_init();
+}
#endif
+
static void __init rk312x_init_late(void)
{
#ifdef CONFIG_PM
- rk321x_init_suspend();
+ rockchip_suspend_init();
+ if (soc_is_rk3126b())
+ rk3126b_init_suspend();
+ else
+ rk312x_init_suspend();
+ rkpm_set_ops_pwr_dmns(rk_pm_soc_pd_suspend, rk_pm_soc_pd_resume);
#endif
+ if (rockchip_jtag_enabled)
+ clk_prepare_enable(clk_get_sys(NULL, "clk_jtag"));
}
static void rk312x_restart(char mode, const char *cmd)
rockchip_restart_get_boot_mode(cmd, &boot_flag, &boot_mode);
- writel_relaxed(boot_flag, RK_GRF_VIRT + RK312X_GRF_OS_REG4); // for loader
- writel_relaxed(boot_mode, RK_GRF_VIRT + RK312X_GRF_OS_REG5); // for linux
+ /* for loader */
+ writel_relaxed(boot_flag, RK_PMU_VIRT + RK312X_PMU_SYS_REG0);
+ /* for linux */
+ writel_relaxed(boot_mode, RK_PMU_VIRT + RK312X_PMU_SYS_REG1);
+
dsb();
/* pll enter slow mode */
- writel_relaxed(0x30110000, RK_CRU_VIRT + RK312X_CRU_MODE_CON);
+ writel_relaxed(0x11010000, RK_CRU_VIRT + RK312X_CRU_MODE_CON);
dsb();
writel_relaxed(0xeca8, RK_CRU_VIRT + RK312X_CRU_GLB_SRST_SND_VALUE);
dsb();
if (!cpu_is_rk312x())
return 0;
+ if (soc_is_rk3126b())
+ return 0;
err = rockchip_pie_init();
if (err)
return 0;
}
arch_initcall(rk312x_pie_init);
-#ifdef CONFIG_PM
-static u32 rk_pmu_pwrdn_st;
-static inline void rk_pm_soc_pd_suspend(void)
-{
- pmu_writel(0x00, RK312X_PMU_IDLE_REQ);
- rk_pmu_pwrdn_st = pmu_readl(RK312X_PMU_PWRDN_ST);
-
- if (!(rk_pmu_pwrdn_st & BIT(pmu_st_map[PD_GPU])))
- rk312x_sys_set_power_domain(PD_GPU, false);
- if (!(rk_pmu_pwrdn_st & BIT(pmu_st_map[PD_VIO])))
- rk312x_sys_set_power_domain(PD_VIO, false);
-
- if (!(rk_pmu_pwrdn_st & BIT(pmu_st_map[PD_VIDEO])))
- rk312x_sys_set_power_domain(PD_VIDEO, false);
- pmu_writel(0x00, RK312X_PMU_IDLE_REQ);
-}
-static inline void rk_pm_soc_pd_resume(void)
+#include "ddr_rk3126.c"
+static int __init rk312x_ddr_init(void)
{
- if (!(rk_pmu_pwrdn_st & BIT(pmu_st_map[PD_VIDEO])))
- rk312x_sys_set_power_domain(PD_VIDEO, true);
-
- if (!(rk_pmu_pwrdn_st & BIT(pmu_st_map[PD_VIO])))
- rk312x_sys_set_power_domain(PD_VIO, true);
+ if (soc_is_rk3128() || soc_is_rk3126()) {
+ ddr_change_freq = _ddr_change_freq;
+ ddr_round_rate = _ddr_round_rate;
+ ddr_set_auto_self_refresh = _ddr_set_auto_self_refresh;
+ ddr_bandwidth_get = _ddr_bandwidth_get;
+ ddr_init(DDR3_DEFAULT, 0);
+ }
- if (!(rk_pmu_pwrdn_st & BIT(pmu_st_map[PD_GPU])))
- rk312x_sys_set_power_domain(PD_GPU, true);
-}
-static void __init rk321x_init_suspend(void)
-{
- pr_info("%s\n", __func__);
- rockchip_suspend_init();
- rk312x_suspend_init();
- rkpm_set_ops_pwr_dmns(rk_pm_soc_pd_suspend, rk_pm_soc_pd_resume);
+ return 0;
}
-#endif
+arch_initcall_sync(rk312x_ddr_init);