2 #include <linux/kernel.h>
3 #include <mach/system.h>
4 #include <linux/string.h>
7 #include <mach/loader.h>
8 #include <mach/board.h>
10 //#define DEBUG // for jtag debug
12 #define cru_readl(offset) readl_relaxed(RK30_CRU_BASE + offset)
13 #define cru_writel(v, offset) do { writel_relaxed(v, RK30_CRU_BASE + offset); } while (0)
14 #define grf_readl(offset) readl_relaxed(RK30_GRF_BASE + offset)
15 #define grf_writel(v, offset) do { writel_relaxed(v, RK30_GRF_BASE + offset); dsb(); } while (0)
17 static bool is_panic = false;
19 static int panic_event(struct notifier_block *this, unsigned long event, void *ptr)
25 static struct notifier_block panic_block = {
26 .notifier_call = panic_event,
29 static int __init arch_reset_init(void)
31 atomic_notifier_chain_register(&panic_notifier_list, &panic_block);
34 core_initcall(arch_reset_init);
37 __sramdata volatile int reset_loop = 1;
40 static void __sramfunc __noreturn soft_reset(void)
42 /* pll enter slow mode */
43 cru_writel(0xffff0000, CRU_MODE_CON);
46 /* restore clock select and divide */
47 cru_writel(0xffff0200, CRU_CLKSELS_CON(0));
48 cru_writel(0xffff3113, CRU_CLKSELS_CON(1));
49 cru_writel(0xfff00000, CRU_CLKSELS_CON(2)); // 3:0 reserved
50 cru_writel(0xffff0200, CRU_CLKSELS_CON(3));
51 cru_writel(0x003f0000, CRU_CLKSELS_CON(4)); // 15:6 reserved
52 cru_writel(0x003f0000, CRU_CLKSELS_CON(5)); // 15:6 reserved
53 cru_writel(0x0bb8ea60, CRU_CLKSELS_CON(6));
54 cru_writel(0x0bb8ea60, CRU_CLKSELS_CON(7));
55 cru_writel(0xffff2100, CRU_CLKSELS_CON(10));
56 cru_writel(0x007f0017, CRU_CLKSELS_CON(11)); // 15:7 reserved
57 cru_writel(0xffff1717, CRU_CLKSELS_CON(12));
58 cru_writel(0xffff0200, CRU_CLKSELS_CON(13));
59 cru_writel(0xffff0200, CRU_CLKSELS_CON(14));
60 cru_writel(0xffff0200, CRU_CLKSELS_CON(15));
61 cru_writel(0x0bb8ea60, CRU_CLKSELS_CON(17));
62 cru_writel(0x0bb8ea60, CRU_CLKSELS_CON(18));
63 cru_writel(0x0bb8ea60, CRU_CLKSELS_CON(19));
64 cru_writel(0x0bb8ea60, CRU_CLKSELS_CON(23));
65 cru_writel(0xffff1700, CRU_CLKSELS_CON(24));
66 cru_writel(0x017f0107, CRU_CLKSELS_CON(25)); // 15:9 7 reserved
67 cru_writel(0xffff0000, CRU_CLKSELS_CON(26));
68 cru_writel(0xffff0700, CRU_CLKSELS_CON(27));
69 cru_writel(0xffff0700, CRU_CLKSELS_CON(28));
70 cru_writel(0xffff0012, CRU_CLKSELS_CON(29));
71 cru_writel(0xffff0300, CRU_CLKSELS_CON(30));
72 cru_writel(0xffff0001, CRU_CLKSELS_CON(31));
73 cru_writel(0xffff0303, CRU_CLKSELS_CON(32));
74 cru_writel(0xffff0003, CRU_CLKSELS_CON(34));
77 /* idle request PERI/VIO/VPU/GPU */
78 grf_writel(0x1e00ffff, GRF_SOC_CON2);
79 while ((grf_readl(GRF_SOC_STATUS0) & (0x1e << 16)) != (0x1e << 16))
81 while ((grf_readl(GRF_SOC_STATUS0) & (0x1e << 22)) != (0x1e << 22))
84 /* software reset modules */
86 cru_writel(0xfff3ffff, CRU_SOFTRSTS_CON(8)); // CORE_DBG/DBG_APB
88 cru_writel(0xffffffff, CRU_SOFTRSTS_CON(8));
90 cru_writel(0xffffffff, CRU_SOFTRSTS_CON(7));
91 cru_writel(0xffffffff, CRU_SOFTRSTS_CON(6));
92 cru_writel(0xffffffff, CRU_SOFTRSTS_CON(5));
93 cru_writel(0x7fffffff, CRU_SOFTRSTS_CON(4)); // DDRMSCH
95 cru_writel(0xff63ffff, CRU_SOFTRSTS_CON(3)); // DAP_PO/DAP/DAP_SYS
97 cru_writel(0xff7fffff, CRU_SOFTRSTS_CON(3)); // GRF
99 cru_writel(0xfff0ffff, CRU_SOFTRSTS_CON(2)); // GPIO0/1/2/3
100 cru_writel(0xffdfffff, CRU_SOFTRSTS_CON(1)); // INTMEM
102 cru_writel(0x1e60ffff, CRU_SOFTRSTS_CON(0)); // MCORE_DBG/CORE0_DBG
104 cru_writel(0x1fe0ffff, CRU_SOFTRSTS_CON(0)); // CORE_SRST_WDT_SEL/MCORE/CORE0/CORE1/ACLK_CORE/STRC_SYS_AXI/L2C
110 cru_writel(0xffff0000, CRU_SOFTRSTS_CON(0));
111 cru_writel(0xffff0000, CRU_SOFTRSTS_CON(1));
112 cru_writel(0xffff0000, CRU_SOFTRSTS_CON(2));
113 cru_writel(0xffff0000, CRU_SOFTRSTS_CON(3));
114 cru_writel(0xffff0000, CRU_SOFTRSTS_CON(4));
115 cru_writel(0xffff0000, CRU_SOFTRSTS_CON(5));
116 cru_writel(0xffff0000, CRU_SOFTRSTS_CON(6));
117 cru_writel(0xffff0000, CRU_SOFTRSTS_CON(7));
118 cru_writel(0xffff0000, CRU_SOFTRSTS_CON(8));
121 /* disable idle request */
122 grf_writel(0x3f000000, GRF_SOC_CON2);
123 while (grf_readl(GRF_SOC_STATUS0) & (0x3f << 16))
125 while (grf_readl(GRF_SOC_STATUS0) & (0x3f << 22))
129 // while (reset_loop);
132 cru_writel(0x801cffff, CRU_SOFTRSTS_CON(0)); // MCORE/CORE0/CORE1/L2C
138 static void rk30_arch_reset(char mode, const char *cmd)
142 u32 boot_mode = BOOT_MODE_REBOOT;
145 if (!strcmp(cmd, "loader") || !strcmp(cmd, "bootloader"))
146 boot_flag = SYS_LOADER_REBOOT_FLAG + BOOT_LOADER;
147 else if(!strcmp(cmd, "recovery"))
148 boot_flag = SYS_LOADER_REBOOT_FLAG + BOOT_RECOVER;
149 else if (!strcmp(cmd, "charge"))
150 boot_mode = BOOT_MODE_CHARGE;
153 boot_mode = BOOT_MODE_PANIC;
155 grf_writel(boot_flag, GRF_OS_REG4); // for loader
156 grf_writel(boot_mode, GRF_OS_REG5); // for linux
158 /* enable all clock */
159 for (i = 0; i < CRU_CLKGATES_CON_CNT; i++)
160 cru_writel(0xffff0000, CRU_CLKGATES_CON(i));
163 grf_writel(1 << (12 + 16), GRF_SOC_CON0);
165 ((void(*)(void))((u32)soft_reset - (u32)RK30_IMEM_BASE + (u32)RK30_IMEM_NONCACHED))();
168 void (*arch_reset)(char, const char *) = rk30_arch_reset;