Merge remote-tracking branch 'origin/develop-3.10-next' into develop-3.10
[firefly-linux-kernel-4.4.55.git] / arch / arm / mach-rockchip / rk3036.c
1 /*
2  * Device Tree support for Rockchip RK3036
3  *
4  * Copyright (C) 2014 ROCKCHIP, Inc.
5  *
6  * This program is free software; you can redistribute it and/or modify
7  * it under the terms of the GNU General Public License as published by
8  * the Free Software Foundation; either version 2 of the License, or
9  * (at your option) any later version.
10  *
11  * This program is distributed in the hope that it will be useful,
12  * but WITHOUT ANY WARRANTY; without even the implied warranty of
13  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
14  * GNU General Public License for more details.
15  */
16
17 #include <linux/clk-provider.h>
18 #include <linux/clocksource.h>
19 #include <linux/cpuidle.h>
20 #include <linux/delay.h>
21 #include <linux/init.h>
22 #include <linux/irqchip.h>
23 #include <linux/kernel.h>
24 #include <linux/of_address.h>
25 #include <linux/of_platform.h>
26 #include <linux/wakeup_reason.h>
27 #include <linux/rockchip/common.h>
28 #include <linux/rockchip/cpu.h>
29 #include <linux/rockchip/cru.h>
30 #include <linux/rockchip/dvfs.h>
31 #include <linux/rockchip/grf.h>
32 #include <linux/rockchip/iomap.h>
33 #include <linux/rockchip/pmu.h>
34 #include <asm/cpuidle.h>
35 #include <asm/cputype.h>
36 #include <asm/mach/arch.h>
37 #include <asm/mach/map.h>
38 #include "cpu_axi.h"
39 #include "loader.h"
40 #define CPU 3036
41 #include "sram.h"
42 #include "pm.h"
43
44 #define RK3036_DEVICE(name) \
45         { \
46                 .virtual        = (unsigned long) RK_##name##_VIRT, \
47                 .pfn            = __phys_to_pfn(RK3036_##name##_PHYS), \
48                 .length         = RK3036_##name##_SIZE, \
49                 .type           = MT_DEVICE, \
50         }
51
52 #define RK3036_IMEM_VIRT (RK_BOOTRAM_VIRT + SZ_32K)
53 #define RK3036_TIMER5_VIRT (RK_TIMER_VIRT + 0xa0)
54
55 static struct map_desc rk3036_io_desc[] __initdata = {
56         RK3036_DEVICE(CRU),
57         RK3036_DEVICE(GRF),
58         RK3036_DEVICE(ROM),
59         RK3036_DEVICE(EFUSE),
60         RK_DEVICE(RK_DDR_VIRT, RK3036_DDR_PCTL_PHYS, RK3036_DDR_PCTL_SIZE),
61         RK_DEVICE(RK_DDR_VIRT + RK3036_DDR_PCTL_SIZE, RK3036_DDR_PHY_PHYS,
62                   RK3036_DDR_PHY_SIZE),
63         RK_DEVICE(RK_GPIO_VIRT(0), RK3036_GPIO0_PHYS, RK3036_GPIO_SIZE),
64         RK_DEVICE(RK_GPIO_VIRT(1), RK3036_GPIO1_PHYS, RK3036_GPIO_SIZE),
65         RK_DEVICE(RK_GPIO_VIRT(2), RK3036_GPIO2_PHYS, RK3036_GPIO_SIZE),
66         RK_DEVICE(RK_DEBUG_UART_VIRT, RK3036_UART2_PHYS, RK3036_UART_SIZE),
67         RK_DEVICE(RK_GIC_VIRT, RK3036_GIC_DIST_PHYS, RK3036_GIC_DIST_SIZE),
68         RK_DEVICE(RK_GIC_VIRT + RK3036_GIC_DIST_SIZE, RK3036_GIC_CPU_PHYS,
69                   RK3036_GIC_CPU_SIZE),
70         RK_DEVICE(RK3036_IMEM_VIRT, RK3036_IMEM_PHYS, SZ_4K),
71         RK_DEVICE(RK_TIMER_VIRT, RK3036_TIMER_PHYS, RK3036_TIMER_SIZE),
72 };
73
74 static void __init rk3036_boot_mode_init(void)
75 {
76         u32 flag = readl_relaxed(RK_GRF_VIRT + RK3036_GRF_OS_REG4);
77         u32 mode = readl_relaxed(RK_GRF_VIRT + RK3036_GRF_OS_REG5);
78         u32 rst_st = readl_relaxed(RK_CRU_VIRT + RK3036_CRU_RST_ST);
79
80         if (flag == (SYS_KERNRL_REBOOT_FLAG | BOOT_RECOVER))
81                 mode = BOOT_MODE_RECOVERY;
82         if (rst_st & ((1 << 2) | (1 << 3)))
83                 mode = BOOT_MODE_WATCHDOG;
84         rockchip_boot_mode_init(flag, mode);
85 }
86
87 static void usb_uart_init(void)
88 {
89 #ifdef CONFIG_RK_USB_UART
90         u32 soc_status0 = readl_relaxed(RK_GRF_VIRT + RK3036_GRF_SOC_STATUS0);
91 #endif
92         writel_relaxed(0x34000000, RK_GRF_VIRT + RK3036_GRF_UOC1_CON4);
93 #ifdef CONFIG_RK_USB_UART
94         if (!(soc_status0 & (1 << 14)) && (soc_status0 & (1 << 17))) {
95                 /* software control usb phy enable */
96                 writel_relaxed(0x007f0055, RK_GRF_VIRT + RK3036_GRF_UOC0_CON5);
97                 writel_relaxed(0x34003000, RK_GRF_VIRT + RK3036_GRF_UOC1_CON4);
98         }
99 #endif
100
101         writel_relaxed(0x07, RK_DEBUG_UART_VIRT + 0x88);
102         writel_relaxed(0x00, RK_DEBUG_UART_VIRT + 0x04);
103         writel_relaxed(0x83, RK_DEBUG_UART_VIRT + 0x0c);
104         writel_relaxed(0x0d, RK_DEBUG_UART_VIRT + 0x00);
105         writel_relaxed(0x00, RK_DEBUG_UART_VIRT + 0x04);
106         writel_relaxed(0x03, RK_DEBUG_UART_VIRT + 0x0c);
107 }
108
109 static void __init rk3036_dt_map_io(void)
110 {
111         rockchip_soc_id = ROCKCHIP_SOC_RK3036;
112
113         iotable_init(rk3036_io_desc, ARRAY_SIZE(rk3036_io_desc));
114         debug_ll_io_init();
115         usb_uart_init();
116
117         /* enable timer5 for core */
118         writel_relaxed(0, RK3036_TIMER5_VIRT + 0x10);
119         dsb();
120         writel_relaxed(0xFFFFFFFF, RK3036_TIMER5_VIRT + 0x00);
121         writel_relaxed(0xFFFFFFFF, RK3036_TIMER5_VIRT + 0x04);
122         dsb();
123         writel_relaxed(1, RK3036_TIMER5_VIRT + 0x10);
124         dsb();
125
126         rk3036_boot_mode_init();
127 }
128
129 extern void secondary_startup(void);
130 static int rk3036_sys_set_power_domain(enum pmu_power_domain pd, bool on)
131 {
132         if (on) {
133 #ifdef CONFIG_SMP
134                 if (PD_CPU_1 == pd) {
135                         writel_relaxed(0x20000,
136                                        RK_CRU_VIRT + RK3036_CRU_SOFTRST0_CON);
137                         dsb();
138                         udelay(10);
139                         writel_relaxed(virt_to_phys(secondary_startup),
140                                        RK3036_IMEM_VIRT + 8);
141                         writel_relaxed(0xDEADBEAF, RK3036_IMEM_VIRT + 4);
142                         dsb_sev();
143                 }
144 #endif
145         } else {
146 #ifdef CONFIG_SMP
147                 if (PD_CPU_1 == pd) {
148                         writel_relaxed(0x20002,
149                                        RK_CRU_VIRT + RK3036_CRU_SOFTRST0_CON);
150                         dsb();
151                 }
152 #endif
153         }
154
155         return 0;
156 }
157
158 static bool rk3036_pmu_power_domain_is_on(enum pmu_power_domain pd)
159 {
160         return 1;
161 }
162
163 static int rk3036_pmu_set_idle_request(enum pmu_idle_req req, bool idle)
164 {
165         return 0;
166 }
167
168 static void __init rk3036_dt_init_timer(void)
169 {
170         rockchip_pmu_ops.set_power_domain = rk3036_sys_set_power_domain;
171         rockchip_pmu_ops.power_domain_is_on = rk3036_pmu_power_domain_is_on;
172         rockchip_pmu_ops.set_idle_request = rk3036_pmu_set_idle_request;
173         of_clk_init(NULL);
174         clocksource_of_init();
175 }
176
177 #ifdef CONFIG_PM
178 static inline void rk3036_uart_printch(char byte)
179 {
180 write_uart:
181         writel_relaxed(byte, RK_DEBUG_UART_VIRT);
182         dsb();
183
184         /* loop check LSR[6], Transmitter Empty bit */
185         while (!(readl_relaxed(RK_DEBUG_UART_VIRT + 0x14) & 0x40))
186                 barrier();
187
188         if (byte == '\n') {
189                 byte = '\r';
190                 goto write_uart;
191         }
192 }
193
194 static void rk3036_ddr_printch(char byte)
195 {
196         rk3036_uart_printch(byte);
197
198         rk_last_log_text(&byte, 1);
199
200         if (byte == '\n') {
201                 byte = '\r';
202                 rk_last_log_text(&byte, 1);
203         }
204 }
205
206 #define GPIO_INTEN              0x30
207 #define GPIO_INT_STATUS         0x40
208 #define GIC_DIST_PENDING_SET    0x200
209 static void rk3036_pm_dump_irq(void)
210 {
211         u32 irq_gpio =
212             (readl_relaxed(RK_GIC_VIRT + GIC_DIST_PENDING_SET + 8) >> 4) & 7;
213         u32 irq[4];
214         int i;
215
216         for (i = 0; i < ARRAY_SIZE(irq); i++) {
217                 irq[i] = readl_relaxed(RK_GIC_VIRT + GIC_DIST_PENDING_SET +
218                                        (1 + i) * 4);
219                 if (irq[i])
220                         log_wakeup_reason(32 * (i + 1) + fls(irq[i]) - 1);
221         }
222         pr_info("wakeup irq: %08x %08x %08x %08x\n",
223                 irq[0], irq[1], irq[2], irq[3]);
224         for (i = 0; i <= 2; i++) {
225                 if (irq_gpio & (1 << i))
226                         pr_info("wakeup gpio%d: %08x\n", i,
227                                 readl_relaxed(RK_GPIO_VIRT(i) +
228                                               GPIO_INT_STATUS));
229         }
230 }
231
232 #define DUMP_GPIO_INTEN(ID) \
233         do { \
234                 u32 en = readl_relaxed(RK_GPIO_VIRT(ID) + GPIO_INTEN); \
235                 if (en) { \
236                         pr_info("GPIO%d_INTEN: %08x\n", ID, en); \
237                 } \
238         } while (0)
239
240 static void rk3036_pm_dump_inten(void)
241 {
242         DUMP_GPIO_INTEN(0);
243         DUMP_GPIO_INTEN(1);
244         DUMP_GPIO_INTEN(2);
245 }
246
247 static void __init rk3036_suspend_init(void)
248 {
249         rkpm_set_ops_prepare_finish(rk3036_pm_dump_inten, rk3036_pm_dump_irq);
250         rkpm_set_ops_printch(rk3036_ddr_printch);
251         rockchip_suspend_init();
252 }
253 #endif
254
255 static void __init rk3036_init_late(void)
256 {
257 #ifdef CONFIG_PM
258         rk3036_suspend_init();
259 #endif
260 }
261
262 static void __init rk3036_reserve(void)
263 {
264         /* reserve memory for ION */
265         rockchip_ion_reserve();
266 }
267
268 static void rk3036_restart(char mode, const char *cmd)
269 {
270         u32 boot_flag, boot_mode;
271
272         rockchip_restart_get_boot_mode(cmd, &boot_flag, &boot_mode);
273
274         writel_relaxed(boot_flag, RK_GRF_VIRT + RK3036_GRF_OS_REG4);    // for loader
275         writel_relaxed(boot_mode, RK_GRF_VIRT + RK3036_GRF_OS_REG5);    // for linux
276         dsb();
277
278         /* pll enter slow mode */
279         writel_relaxed(0x30110000, RK_CRU_VIRT + RK3036_CRU_MODE_CON);
280         dsb();
281         writel_relaxed(0xeca8, RK_CRU_VIRT + RK3036_CRU_GLB_SRST_SND_VALUE);
282         dsb();
283 }
284
285 static const char *const rk3036_dt_compat[] __initconst = {
286         "rockchip,rk3036",
287         NULL,
288 };
289
290 DT_MACHINE_START(RK3036_DT, "Rockchip RK3036")
291         .dt_compat      = rk3036_dt_compat,
292         .smp            = smp_ops(rockchip_smp_ops),
293         .reserve        = rk3036_reserve,
294         .map_io         = rk3036_dt_map_io,
295         .init_time      = rk3036_dt_init_timer,
296         .init_late      = rk3036_init_late,
297         .reserve        = rk3036_reserve,
298         .restart        = rk3036_restart,
299 MACHINE_END