From 20ff870b3c5417b88fcd049b772c17ac8fee3a37 Mon Sep 17 00:00:00 2001 From: =?utf8?q?=E9=BB=84=E6=B6=9B?= Date: Thu, 8 Aug 2013 16:22:16 +0800 Subject: [PATCH] rk3026: add reset support --- arch/arm/mach-rk3026/Makefile | 2 +- arch/arm/mach-rk3026/reset.c | 163 ++++++++++++++++++++++++++++++++++ 2 files changed, 164 insertions(+), 1 deletion(-) create mode 100644 arch/arm/mach-rk3026/reset.c diff --git a/arch/arm/mach-rk3026/Makefile b/arch/arm/mach-rk3026/Makefile index a35540cca774..55150cdc1121 100644 --- a/arch/arm/mach-rk3026/Makefile +++ b/arch/arm/mach-rk3026/Makefile @@ -2,7 +2,7 @@ ifneq ($(CONFIG_RK_FPGA),y) obj-y += ../plat-rk/clock.o obj-y += clock_data.o obj-y += ../mach-rk2928/ddr.o -obj-y += ../mach-rk30/reset.o +obj-y += reset.o obj-$(CONFIG_PM) += ../mach-rk2928/pm.o endif obj-y += common.o diff --git a/arch/arm/mach-rk3026/reset.c b/arch/arm/mach-rk3026/reset.c new file mode 100644 index 000000000000..24cce14aa85e --- /dev/null +++ b/arch/arm/mach-rk3026/reset.c @@ -0,0 +1,163 @@ +#include +#include +#include +#include +#include +#include +#include +#include + +//#define DEBUG // for jtag debug + +#define cru_readl(offset) readl_relaxed(RK30_CRU_BASE + offset) +#define cru_writel(v, offset) do { writel_relaxed(v, RK30_CRU_BASE + offset); dsb(); } while (0) +#define grf_readl(offset) readl_relaxed(RK30_GRF_BASE + offset) +#define grf_writel(v, offset) do { writel_relaxed(v, RK30_GRF_BASE + offset); dsb(); } while (0) + +static bool is_panic = false; + +static int panic_event(struct notifier_block *this, unsigned long event, void *ptr) +{ + is_panic = true; + return NOTIFY_DONE; +} + +static struct notifier_block panic_block = { + .notifier_call = panic_event, +}; + +static int __init arch_reset_init(void) +{ + atomic_notifier_chain_register(&panic_notifier_list, &panic_block); + return 0; +} +core_initcall(arch_reset_init); + +#ifdef DEBUG +__sramdata volatile int reset_loop = 1; +#endif + +static void __sramfunc __noreturn soft_reset(void) +{ + /* pll enter slow mode */ + cru_writel(0xffff0000, CRU_MODE_CON); + + /* restore clock select and divide */ + cru_writel(0xffff0200, CRU_CLKSELS_CON(0)); + cru_writel(0xffff3113, CRU_CLKSELS_CON(1)); + cru_writel(0xfff00000, CRU_CLKSELS_CON(2)); // 3:0 reserved + cru_writel(0xffff0200, CRU_CLKSELS_CON(3)); + cru_writel(0x003f0000, CRU_CLKSELS_CON(4)); // 15:6 reserved + cru_writel(0x003f0000, CRU_CLKSELS_CON(5)); // 15:6 reserved + cru_writel(0x0bb8ea60, CRU_CLKSELS_CON(6)); + cru_writel(0x0bb8ea60, CRU_CLKSELS_CON(7)); + cru_writel(0xffff2100, CRU_CLKSELS_CON(10)); + cru_writel(0x007f0017, CRU_CLKSELS_CON(11)); // 15:7 reserved + cru_writel(0xffff1717, CRU_CLKSELS_CON(12)); + cru_writel(0xffff0200, CRU_CLKSELS_CON(13)); + cru_writel(0xffff0200, CRU_CLKSELS_CON(14)); + cru_writel(0xffff0200, CRU_CLKSELS_CON(15)); + cru_writel(0x0bb8ea60, CRU_CLKSELS_CON(17)); + cru_writel(0x0bb8ea60, CRU_CLKSELS_CON(18)); + cru_writel(0x0bb8ea60, CRU_CLKSELS_CON(19)); + cru_writel(0x0bb8ea60, CRU_CLKSELS_CON(23)); + cru_writel(0xffff1700, CRU_CLKSELS_CON(24)); + cru_writel(0x017f0107, CRU_CLKSELS_CON(25)); // 15:9 7 reserved + cru_writel(0xffff0000, CRU_CLKSELS_CON(26)); + cru_writel(0xffff0700, CRU_CLKSELS_CON(27)); + cru_writel(0xffff0700, CRU_CLKSELS_CON(28)); + cru_writel(0xffff0012, CRU_CLKSELS_CON(29)); + cru_writel(0xffff0300, CRU_CLKSELS_CON(30)); + cru_writel(0xffff0001, CRU_CLKSELS_CON(31)); + cru_writel(0xffff0303, CRU_CLKSELS_CON(32)); + cru_writel(0xffff0003, CRU_CLKSELS_CON(34)); + + /* idle request PERI/VIO/VPU/GPU */ + grf_writel(0x1e00ffff, GRF_SOC_CON2); + while ((grf_readl(GRF_SOC_STATUS0) & (0x1e << 16)) != (0x1e << 16)) + ; + while ((grf_readl(GRF_SOC_STATUS0) & (0x1e << 22)) != (0x1e << 22)) + ; + + /* software reset modules */ +#ifdef DEBUG + cru_writel(0xfff3ffff, CRU_SOFTRSTS_CON(8)); // CORE_DBG/DBG_APB +#else + cru_writel(0xffffffff, CRU_SOFTRSTS_CON(8)); +#endif + cru_writel(0xffffffff, CRU_SOFTRSTS_CON(7)); + cru_writel(0xffffffff, CRU_SOFTRSTS_CON(6)); + cru_writel(0xffffffff, CRU_SOFTRSTS_CON(5)); + cru_writel(0x7fffffff, CRU_SOFTRSTS_CON(4)); // DDRMSCH +#ifdef DEBUG + cru_writel(0xff63ffff, CRU_SOFTRSTS_CON(3)); // DAP_PO/DAP/DAP_SYS +#else + cru_writel(0xff7fffff, CRU_SOFTRSTS_CON(3)); // GRF +#endif + cru_writel(0xfff0ffff, CRU_SOFTRSTS_CON(2)); // GPIO0/1/2/3 + cru_writel(0xffdfffff, CRU_SOFTRSTS_CON(1)); // INTMEM +#ifdef DEBUG + cru_writel(0x1e60ffff, CRU_SOFTRSTS_CON(0)); // MCORE_DBG/CORE0_DBG +#else + cru_writel(0x1fe0ffff, CRU_SOFTRSTS_CON(0)); // CORE_SRST_WDT_SEL/MCORE/CORE0/CORE1/ACLK_CORE/STRC_SYS_AXI/L2C +#endif + + sram_udelay(1000); + + cru_writel(0xffff0000, CRU_SOFTRSTS_CON(0)); + cru_writel(0xffff0000, CRU_SOFTRSTS_CON(1)); + cru_writel(0xffff0000, CRU_SOFTRSTS_CON(2)); + cru_writel(0xffff0000, CRU_SOFTRSTS_CON(3)); + cru_writel(0xffff0000, CRU_SOFTRSTS_CON(4)); + cru_writel(0xffff0000, CRU_SOFTRSTS_CON(5)); + cru_writel(0xffff0000, CRU_SOFTRSTS_CON(6)); + cru_writel(0xffff0000, CRU_SOFTRSTS_CON(7)); + cru_writel(0xffff0000, CRU_SOFTRSTS_CON(8)); + + /* disable idle request */ + grf_writel(0x3f000000, GRF_SOC_CON2); + while (grf_readl(GRF_SOC_STATUS0) & (0x3f << 16)) + ; + while (grf_readl(GRF_SOC_STATUS0) & (0x3f << 22)) + ; + +#ifdef DEBUG +// while (reset_loop); +#endif + + cru_writel(0x801cffff, CRU_SOFTRSTS_CON(0)); // MCORE/CORE0/CORE1/L2C + + while (1); +} + +static void rk30_arch_reset(char mode, const char *cmd) +{ + unsigned i; + u32 boot_flag = 0; + u32 boot_mode = BOOT_MODE_REBOOT; + + if (cmd) { + if (!strcmp(cmd, "loader") || !strcmp(cmd, "bootloader")) + boot_flag = SYS_LOADER_REBOOT_FLAG + BOOT_LOADER; + else if(!strcmp(cmd, "recovery")) + boot_flag = SYS_LOADER_REBOOT_FLAG + BOOT_RECOVER; + else if (!strcmp(cmd, "charge")) + boot_mode = BOOT_MODE_CHARGE; + } else { + if (is_panic) + boot_mode = BOOT_MODE_PANIC; + } + grf_writel(boot_flag, GRF_OS_REG4); // for loader + grf_writel(boot_mode, GRF_OS_REG5); // for linux + + /* enable all clock */ + for (i = 0; i < CRU_CLKGATES_CON_CNT; i++) + cru_writel(0xffff0000, CRU_CLKGATES_CON(i)); + + /* disable remap */ + grf_writel(1 << (12 + 16), GRF_SOC_CON0); + + ((void(*)(void))((u32)soft_reset - (u32)RK30_IMEM_BASE + (u32)RK30_IMEM_NONCACHED))(); +} + +void (*arch_reset)(char, const char *) = rk30_arch_reset; -- 2.34.1