rk29: reset: reset GRF_MEM_CON while reboot to bootloader
[firefly-linux-kernel-4.4.55.git] / arch / arm / mach-rk29 / reset.c
1 #include <linux/kernel.h>\r
2 #include <linux/reboot.h>\r
3 \r
4 #include <asm/io.h>\r
5 #include <asm/proc-fns.h>\r
6 #include <asm/cacheflush.h>\r
7 #include <asm/tlb.h>\r
8 #include <asm/traps.h>\r
9 #include <asm/sections.h>\r
10 #include <asm/mach/arch.h>\r
11 #include <asm/mach/map.h>\r
12 #include <asm/stacktrace.h>\r
13 \r
14 #include <mach/rk29_iomap.h>\r
15 #include <mach/cru.h>\r
16 #include <mach/memory.h>\r
17 #include <mach/sram.h>\r
18 #include <mach/pmu.h>\r
19 #include <mach/loader.h>\r
20 #include <mach/board.h>\r
21 \r
22 #include <asm/delay.h>\r
23 #include <asm/tlbflush.h>\r
24 #include <asm/cacheflush.h>\r
25 \r
26 static void  pwm2gpiodefault(void)\r
27 {\r
28         #define     REG_FILE_BASE_ADDR         RK29_GRF_BASE\r
29         volatile unsigned int * pGRF_GPIO2L_IOMUX =  (volatile unsigned int *)(REG_FILE_BASE_ADDR + 0x58);\r
30         #define     GPIO2_BASE_ADDR            RK29_GPIO2_BASE\r
31         volatile unsigned int *pGPIO2_DIR = (volatile unsigned int *)(GPIO2_BASE_ADDR + 0x4);\r
32 \r
33         // iomux pwm2 to gpio2_a[3]\r
34         *pGRF_GPIO2L_IOMUX &= ~(0x3<<6);\r
35         // set gpio to input\r
36         *pGPIO2_DIR &= ~(0x1<<3);\r
37 \r
38         memset((void *)RK29_PWM_BASE, 0, 0x40);\r
39\r
40 \r
41 #if 0\r
42 extern void __rb( void*  );\r
43 static void rb( void )\r
44 {\r
45     void(*cb)(void* ) ;\r
46     \r
47     void * uart_base = (unsigned int *)ioremap( RK29_UART1_PHYS , RK29_UART1_SIZE );\r
48     local_irq_disable();\r
49     cb =  (void(*)(void* ))__pa(__rb);\r
50     __cpuc_flush_kern_all();\r
51     __cpuc_flush_user_all();\r
52     //printk("begin to jump to reboot,uart1 va=0x%p\n" , uart_base);\r
53     //while(testflag);    \r
54     cb( uart_base );\r
55 }\r
56 #endif\r
57 \r
58 static volatile u32 __sramdata reboot_reason = 0;\r
59 static void __sramfunc __noreturn rk29_rb_with_softreset(void)\r
60 {\r
61         u32 reg;\r
62         u32 reason = __raw_readl((u32)&reboot_reason - SRAM_CODE_OFFSET + 0x10130000);\r
63 \r
64         asm volatile (\r
65             "mrc        p15, 0, %0, c1, c0, 0\n\t"\r
66             "bic        %0, %0, #(1 << 0)       @disable MMU\n\t"\r
67             "bic        %0, %0, #(1 << 13)      @set vector to 0x00000000\n\t"\r
68             "bic        %0, %0, #(1 << 12)      @disable I CACHE\n\t"\r
69             "bic        %0, %0, #(1 << 2)       @disable D DACHE\n\t"\r
70             "bic        %0, %0, #(1 << 11)      @disable Branch prediction\n\t"\r
71             "bic        %0, %0, #(1 << 28)      @disable TEX Remap\n\t"\r
72             "mcr        p15, 0, %0, c1, c0, 0\n\t"\r
73             "mov        %0, #0\n\t"\r
74             "mcr        p15, 0, %0, c8, c7, 0   @invalidate whole TLB\n\t"\r
75             "mcr        p15, 0, %0, c7, c5, 6   @invalidate BTC\n\t"\r
76             "dsb\n\t"\r
77             "isb\n\t"\r
78             "b          1f\n\t"\r
79             ".align 5\n\t"\r
80             "1:\n\t"\r
81             : "=r" (reg));\r
82 \r
83         writel(0x00019a00, RK29_CRU_PHYS + CRU_SOFTRST2_CON);\r
84         dsb();\r
85         LOOP(10 * LOOPS_PER_USEC);\r
86 \r
87         writel(0xffffffff, RK29_CRU_PHYS + CRU_SOFTRST2_CON);\r
88         writel(0xffffffff, RK29_CRU_PHYS + CRU_SOFTRST1_CON);\r
89         writel(0xd9fdfdc0, RK29_CRU_PHYS + CRU_SOFTRST0_CON);\r
90         dsb();\r
91 \r
92         LOOP(100 * LOOPS_PER_USEC);\r
93 \r
94         writel(0, RK29_CRU_PHYS + CRU_SOFTRST0_CON);\r
95         writel(0, RK29_CRU_PHYS + CRU_SOFTRST1_CON);\r
96         writel(0x00019a00, RK29_CRU_PHYS + CRU_SOFTRST2_CON);\r
97         dsb();\r
98         LOOP(10 * LOOPS_PER_USEC);\r
99         writel(0, RK29_CRU_PHYS + CRU_SOFTRST2_CON);\r
100         dsb();\r
101         LOOP(10 * LOOPS_PER_USEC);\r
102 \r
103         /* reset GRF_MEM_CON, else bootloader usb function may not work properly */\r
104         writel(0, RK29_GRF_PHYS + 0xac);\r
105         dsb();\r
106 \r
107         if (reason) {\r
108                 __raw_writel(0, RK29_TIMER0_PHYS + 0x8);\r
109                 __raw_writel(reason, RK29_TIMER0_PHYS + 0x0);\r
110         }\r
111 \r
112         asm volatile (\r
113             "b 1f\n\t"\r
114             ".align 5\n\t"\r
115             "1:\n\t"\r
116             "dsb\n\t"\r
117             "isb\n\t"\r
118             "mov        pc, #0");\r
119 \r
120         while (1);\r
121 }\r
122 \r
123 void rk29_arch_reset(int mode, const char *cmd)\r
124 {\r
125         void (*rb2)(void);\r
126         u32 boot_mode = BOOT_MODE_REBOOT;\r
127 \r
128         if (cmd) {\r
129                 if (!strcmp(cmd, "loader") || !strcmp(cmd, "bootloader")) {\r
130                         reboot_reason = SYS_LOADER_ERR_FLAG;\r
131                 } else if (!strcmp(cmd, "recovery")) {\r
132                         reboot_reason = SYS_LOADER_REBOOT_FLAG + BOOT_RECOVER;\r
133                         boot_mode = BOOT_MODE_RECOVERY;\r
134                 } else if (!strcmp(cmd, "charge")) {\r
135                         boot_mode = BOOT_MODE_CHARGE;\r
136                 }\r
137         } else {\r
138                 if (system_state != SYSTEM_RESTART)\r
139                         boot_mode = BOOT_MODE_PANIC;\r
140         }\r
141         writel(boot_mode, RK29_GRF_BASE + 0xdc); // GRF_OS_REG3\r
142 \r
143         rb2 = (void(*)(void))((u32)rk29_rb_with_softreset - SRAM_CODE_OFFSET + 0x10130000);\r
144 \r
145         local_irq_disable();\r
146         local_fiq_disable();\r
147 \r
148 #ifdef CONFIG_MACH_RK29SDK\r
149         /* from panic? loop for debug */\r
150         if (system_state != SYSTEM_RESTART) {\r
151                 printk("\nLoop for debug...\n");\r
152                 while (1);\r
153         }\r
154 #endif\r
155 \r
156         cru_writel((cru_readl(CRU_MODE_CON) & ~CRU_CPU_MODE_MASK) | CRU_CPU_MODE_SLOW, CRU_MODE_CON);\r
157         LOOP(LOOPS_PER_USEC);\r
158 \r
159         pwm2gpiodefault();\r
160 \r
161         cru_writel((cru_readl(CRU_MODE_CON) & ~CRU_GENERAL_MODE_MASK) | CRU_GENERAL_MODE_SLOW, CRU_MODE_CON);\r
162         LOOP(LOOPS_PER_USEC);\r
163 \r
164         cru_writel((cru_readl(CRU_MODE_CON) & ~CRU_CODEC_MODE_MASK) | CRU_CODEC_MODE_SLOW, CRU_MODE_CON);\r
165         LOOP(LOOPS_PER_USEC);\r
166 \r
167         cru_writel(0, CRU_CLKGATE0_CON);\r
168         cru_writel(0, CRU_CLKGATE1_CON);\r
169         cru_writel(0, CRU_CLKGATE2_CON);\r
170         cru_writel(0, CRU_CLKGATE3_CON);\r
171         LOOP(LOOPS_PER_USEC);\r
172 \r
173         cru_writel(0, CRU_SOFTRST0_CON);\r
174         cru_writel(0, CRU_SOFTRST1_CON);\r
175         cru_writel(0, CRU_SOFTRST2_CON);\r
176         LOOP(LOOPS_PER_USEC);\r
177 \r
178         cru_writel(1 << 16 | 1 << 13 | 1 << 11 | 1 << 1, CRU_CLKGATE3_CON);\r
179         LOOP(LOOPS_PER_USEC);\r
180 \r
181         writel(readl(RK29_PMU_BASE + PMU_PD_CON) & ~(1 << PD_VCODEC), RK29_PMU_BASE + PMU_PD_CON);\r
182         dsb();\r
183         while (readl(RK29_PMU_BASE + PMU_PD_ST) & (1 << PD_VCODEC))\r
184                 ;\r
185         LOOP(10 * LOOPS_PER_MSEC);\r
186 \r
187         writel(readl(RK29_PMU_BASE + PMU_PD_CON) & ~(1 << PD_DISPLAY), RK29_PMU_BASE + PMU_PD_CON);\r
188         dsb();\r
189         while (readl(RK29_PMU_BASE + PMU_PD_ST) & (1 << PD_DISPLAY))\r
190                 ;\r
191         LOOP(10 * LOOPS_PER_MSEC);\r
192 \r
193         writel(readl(RK29_PMU_BASE + PMU_PD_CON) & ~(1 << PD_GPU), RK29_PMU_BASE + PMU_PD_CON);\r
194         dsb();\r
195         while (readl(RK29_PMU_BASE + PMU_PD_ST) & (1 << PD_GPU))\r
196                 ;\r
197         LOOP(10 * LOOPS_PER_MSEC);\r
198 \r
199         cru_writel(0, CRU_CLKGATE3_CON);\r
200         LOOP(LOOPS_PER_USEC);\r
201 \r
202         //SPI0 clock source = periph_pll_clk, SPI0 divider=8\r
203         cru_writel((cru_readl(CRU_CLKSEL6_CON) & ~0x1FF) | (7 << 2), CRU_CLKSEL6_CON);\r
204 \r
205         //eMMC divider=0x17, SD/MMC0 clock source=arm_pll_clk\r
206         cru_writel((cru_readl(CRU_CLKSEL7_CON) & ~(3 | (0x3f << 18))) | (0x17 << 18), CRU_CLKSEL7_CON);\r
207 \r
208         //UART1 clock divider=0, UART1 clk =24MHz , UART0 and UART1 clock source=periph_pll_clk\r
209         cru_writel((cru_readl(CRU_CLKSEL8_CON) & ~(7 | (0x3f << 14) | (3 << 20))) | (2 << 20), CRU_CLKSEL8_CON);\r
210 \r
211         // remap bit control = 0, normal mode\r
212         writel(readl(RK29_GRF_BASE + 0xc0) & ~(1 << 21), RK29_GRF_BASE + 0xc0);\r
213         // emmc_and_boot_en control=0, normal mode\r
214         writel(readl(RK29_GRF_BASE + 0xbc) & ~(1 << 9), RK29_GRF_BASE + 0xbc);\r
215         dsb();\r
216 \r
217         writel(0, RK29_CPU_AXI_BUS0_PHYS);\r
218         writel(0, RK29_AXI1_PHYS);\r
219         dsb();\r
220 \r
221         // SDMMC_CLKSRC=0, clk_source=clock divider 0\r
222         writel(0, RK29_EMMC_PHYS + 0x0c);\r
223         // SDMMC_CTYPE=0, card_width=1 bit mode\r
224         writel(0, RK29_EMMC_PHYS + 0x18);\r
225         // SDMMC_BLKSIZ=0x200, Block size=512\r
226         writel(0x200, RK29_EMMC_PHYS + 0x1c);\r
227         dsb();\r
228 \r
229         __cpuc_flush_kern_all();\r
230         __cpuc_flush_user_all();\r
231         \r
232         rb2();\r
233 }\r
234 \r
235 \r