ARM: EXYNOS: Consolidate CPU init code
[deliverable/linux.git] / arch / arm / mach-exynos / common.c
CommitLineData
cc511b8d
KK
1/*
2 * Copyright (c) 2010-2011 Samsung Electronics Co., Ltd.
3 * http://www.samsung.com
4 *
5 * Common Codes for EXYNOS
6 *
7 * This program is free software; you can redistribute it and/or modify
8 * it under the terms of the GNU General Public License version 2 as
9 * published by the Free Software Foundation.
10 */
11
12#include <linux/kernel.h>
68a433f1 13#include <linux/bitops.h>
cc511b8d
KK
14#include <linux/interrupt.h>
15#include <linux/irq.h>
a900e5d9 16#include <linux/irqchip.h>
cc511b8d 17#include <linux/io.h>
7affca35 18#include <linux/device.h>
cc511b8d 19#include <linux/gpio.h>
68a433f1 20#include <clocksource/samsung_pwm.h>
cc511b8d
KK
21#include <linux/sched.h>
22#include <linux/serial_core.h>
237c78be 23#include <linux/of.h>
5b7897db 24#include <linux/of_fdt.h>
237c78be 25#include <linux/of_irq.h>
1fd3cbcc 26#include <linux/pm_domain.h>
1e60bc0b
TA
27#include <linux/export.h>
28#include <linux/irqdomain.h>
e873a47c 29#include <linux/of_address.h>
520f7bd7 30#include <linux/irqchip/arm-gic.h>
de88cbb7 31#include <linux/irqchip/chained_irq.h>
35baa336 32#include <linux/platform_device.h>
cc511b8d
KK
33
34#include <asm/proc-fns.h>
40ba95fd 35#include <asm/exception.h>
cc511b8d 36#include <asm/hardware/cache-l2x0.h>
cc511b8d
KK
37#include <asm/mach/map.h>
38#include <asm/mach/irq.h>
b756a50f 39#include <asm/cacheflush.h>
cc511b8d 40
cc511b8d 41#include <plat/cpu.h>
cc511b8d 42#include <plat/pm.h>
cc511b8d
KK
43#include <plat/regs-serial.h>
44
45#include "common.h"
65c9a853
KK
46#include "regs-pmu.h"
47
6cdeddcc
ADK
48#define L2_AUX_VAL 0x7C470001
49#define L2_AUX_MASK 0xC200ffff
cc511b8d 50
cc511b8d
KK
51/* Initial IO mappings */
52
94c7ca71
KK
53static struct map_desc exynos4_iodesc[] __initdata = {
54 {
cc511b8d
KK
55 .virtual = (unsigned long)S3C_VA_SYS,
56 .pfn = __phys_to_pfn(EXYNOS4_PA_SYSCON),
57 .length = SZ_64K,
58 .type = MT_DEVICE,
59 }, {
60 .virtual = (unsigned long)S3C_VA_TIMER,
61 .pfn = __phys_to_pfn(EXYNOS4_PA_TIMER),
62 .length = SZ_16K,
63 .type = MT_DEVICE,
64 }, {
65 .virtual = (unsigned long)S3C_VA_WATCHDOG,
66 .pfn = __phys_to_pfn(EXYNOS4_PA_WATCHDOG),
67 .length = SZ_4K,
68 .type = MT_DEVICE,
69 }, {
70 .virtual = (unsigned long)S5P_VA_SROMC,
71 .pfn = __phys_to_pfn(EXYNOS4_PA_SROMC),
72 .length = SZ_4K,
73 .type = MT_DEVICE,
74 }, {
75 .virtual = (unsigned long)S5P_VA_SYSTIMER,
76 .pfn = __phys_to_pfn(EXYNOS4_PA_SYSTIMER),
77 .length = SZ_4K,
78 .type = MT_DEVICE,
79 }, {
80 .virtual = (unsigned long)S5P_VA_PMU,
81 .pfn = __phys_to_pfn(EXYNOS4_PA_PMU),
82 .length = SZ_64K,
83 .type = MT_DEVICE,
84 }, {
85 .virtual = (unsigned long)S5P_VA_COMBINER_BASE,
86 .pfn = __phys_to_pfn(EXYNOS4_PA_COMBINER),
87 .length = SZ_4K,
88 .type = MT_DEVICE,
89 }, {
90 .virtual = (unsigned long)S5P_VA_GIC_CPU,
91 .pfn = __phys_to_pfn(EXYNOS4_PA_GIC_CPU),
92 .length = SZ_64K,
93 .type = MT_DEVICE,
94 }, {
95 .virtual = (unsigned long)S5P_VA_GIC_DIST,
96 .pfn = __phys_to_pfn(EXYNOS4_PA_GIC_DIST),
97 .length = SZ_64K,
98 .type = MT_DEVICE,
94c7ca71 99 }, {
cc511b8d
KK
100 .virtual = (unsigned long)S5P_VA_CMU,
101 .pfn = __phys_to_pfn(EXYNOS4_PA_CMU),
102 .length = SZ_128K,
103 .type = MT_DEVICE,
104 }, {
105 .virtual = (unsigned long)S5P_VA_COREPERI_BASE,
106 .pfn = __phys_to_pfn(EXYNOS4_PA_COREPERI),
107 .length = SZ_8K,
108 .type = MT_DEVICE,
109 }, {
110 .virtual = (unsigned long)S5P_VA_L2CC,
111 .pfn = __phys_to_pfn(EXYNOS4_PA_L2CC),
112 .length = SZ_4K,
113 .type = MT_DEVICE,
cc511b8d
KK
114 }, {
115 .virtual = (unsigned long)S5P_VA_DMC0,
116 .pfn = __phys_to_pfn(EXYNOS4_PA_DMC0),
2bde0b08
MH
117 .length = SZ_64K,
118 .type = MT_DEVICE,
119 }, {
120 .virtual = (unsigned long)S5P_VA_DMC1,
121 .pfn = __phys_to_pfn(EXYNOS4_PA_DMC1),
122 .length = SZ_64K,
cc511b8d 123 .type = MT_DEVICE,
cc511b8d
KK
124 }, {
125 .virtual = (unsigned long)S3C_VA_USB_HSPHY,
126 .pfn = __phys_to_pfn(EXYNOS4_PA_HSPHY),
127 .length = SZ_4K,
128 .type = MT_DEVICE,
129 },
130};
131
132static struct map_desc exynos4_iodesc0[] __initdata = {
133 {
134 .virtual = (unsigned long)S5P_VA_SYSRAM,
135 .pfn = __phys_to_pfn(EXYNOS4_PA_SYSRAM0),
136 .length = SZ_4K,
137 .type = MT_DEVICE,
138 },
139};
140
141static struct map_desc exynos4_iodesc1[] __initdata = {
142 {
143 .virtual = (unsigned long)S5P_VA_SYSRAM,
144 .pfn = __phys_to_pfn(EXYNOS4_PA_SYSRAM1),
145 .length = SZ_4K,
146 .type = MT_DEVICE,
147 },
148};
149
41de8986
TF
150static struct map_desc exynos4210_iodesc[] __initdata = {
151 {
152 .virtual = (unsigned long)S5P_VA_SYSRAM_NS,
153 .pfn = __phys_to_pfn(EXYNOS4210_PA_SYSRAM_NS),
154 .length = SZ_4K,
155 .type = MT_DEVICE,
156 },
157};
158
159static struct map_desc exynos4x12_iodesc[] __initdata = {
160 {
161 .virtual = (unsigned long)S5P_VA_SYSRAM_NS,
162 .pfn = __phys_to_pfn(EXYNOS4x12_PA_SYSRAM_NS),
163 .length = SZ_4K,
164 .type = MT_DEVICE,
165 },
166};
167
168static struct map_desc exynos5250_iodesc[] __initdata = {
169 {
170 .virtual = (unsigned long)S5P_VA_SYSRAM_NS,
171 .pfn = __phys_to_pfn(EXYNOS5250_PA_SYSRAM_NS),
172 .length = SZ_4K,
173 .type = MT_DEVICE,
174 },
175};
176
94c7ca71
KK
177static struct map_desc exynos5_iodesc[] __initdata = {
178 {
179 .virtual = (unsigned long)S3C_VA_SYS,
180 .pfn = __phys_to_pfn(EXYNOS5_PA_SYSCON),
181 .length = SZ_64K,
182 .type = MT_DEVICE,
183 }, {
184 .virtual = (unsigned long)S3C_VA_TIMER,
185 .pfn = __phys_to_pfn(EXYNOS5_PA_TIMER),
186 .length = SZ_16K,
187 .type = MT_DEVICE,
188 }, {
189 .virtual = (unsigned long)S3C_VA_WATCHDOG,
190 .pfn = __phys_to_pfn(EXYNOS5_PA_WATCHDOG),
191 .length = SZ_4K,
192 .type = MT_DEVICE,
193 }, {
194 .virtual = (unsigned long)S5P_VA_SROMC,
195 .pfn = __phys_to_pfn(EXYNOS5_PA_SROMC),
196 .length = SZ_4K,
197 .type = MT_DEVICE,
94c7ca71
KK
198 }, {
199 .virtual = (unsigned long)S5P_VA_SYSRAM,
200 .pfn = __phys_to_pfn(EXYNOS5_PA_SYSRAM),
201 .length = SZ_4K,
202 .type = MT_DEVICE,
203 }, {
204 .virtual = (unsigned long)S5P_VA_CMU,
205 .pfn = __phys_to_pfn(EXYNOS5_PA_CMU),
206 .length = 144 * SZ_1K,
207 .type = MT_DEVICE,
208 }, {
209 .virtual = (unsigned long)S5P_VA_PMU,
210 .pfn = __phys_to_pfn(EXYNOS5_PA_PMU),
211 .length = SZ_64K,
212 .type = MT_DEVICE,
2edb36c4
KK
213 },
214};
215
7b6d864b 216void exynos4_restart(enum reboot_mode mode, const char *cmd)
cc511b8d
KK
217{
218 __raw_writel(0x1, S5P_SWRESET);
219}
220
7b6d864b 221void exynos5_restart(enum reboot_mode mode, const char *cmd)
94c7ca71 222{
60db7e5f 223 struct device_node *np;
2edb36c4
KK
224 u32 val;
225 void __iomem *addr;
226
eff4e7c7
CK
227 val = 0x1;
228 addr = EXYNOS_SWRESET;
229
230 if (of_machine_is_compatible("samsung,exynos5440")) {
1ba830c9 231 u32 status;
60db7e5f 232 np = of_find_compatible_node(NULL, NULL, "samsung,exynos5440-clock");
1ba830c9
JL
233
234 addr = of_iomap(np, 0) + 0xbc;
235 status = __raw_readl(addr);
236
60db7e5f 237 addr = of_iomap(np, 0) + 0xcc;
1ba830c9
JL
238 val = __raw_readl(addr);
239
240 val = (val & 0xffff0000) | (status & 0xffff);
2edb36c4
KK
241 }
242
243 __raw_writel(val, addr);
94c7ca71
KK
244}
245
35baa336
BZ
246static struct platform_device exynos_cpuidle = {
247 .name = "exynos_cpuidle",
248 .id = -1,
249};
250
251void __init exynos_cpuidle_init(void)
252{
253 platform_device_register(&exynos_cpuidle);
254}
255
d568b6f7
LM
256void __init exynos_cpufreq_init(void)
257{
258 platform_device_register_simple("exynos-cpufreq", -1, NULL, 0);
259}
260
bb13fabc
SG
261void __init exynos_init_late(void)
262{
2edb36c4
KK
263 if (of_machine_is_compatible("samsung,exynos5440"))
264 /* to be supported later */
265 return;
266
1fd3cbcc 267 pm_genpd_poweroff_unused();
bb13fabc
SG
268}
269
564d06b1 270static int __init exynos_fdt_map_chipid(unsigned long node, const char *uname,
f5f83c71
TA
271 int depth, void *data)
272{
273 struct map_desc iodesc;
274 __be32 *reg;
275 unsigned long len;
276
277 if (!of_flat_dt_is_compatible(node, "samsung,exynos4210-chipid") &&
278 !of_flat_dt_is_compatible(node, "samsung,exynos5440-clock"))
279 return 0;
280
281 reg = of_get_flat_dt_prop(node, "reg", &len);
282 if (reg == NULL || len != (sizeof(unsigned long) * 2))
283 return 0;
284
285 iodesc.pfn = __phys_to_pfn(be32_to_cpu(reg[0]));
286 iodesc.length = be32_to_cpu(reg[1]) - 1;
287 iodesc.virtual = (unsigned long)S5P_VA_CHIPID;
288 iodesc.type = MT_DEVICE;
289 iotable_init(&iodesc, 1);
290 return 1;
291}
f5f83c71 292
cc511b8d
KK
293/*
294 * exynos_map_io
295 *
296 * register the standard cpu IO areas
297 */
6eb84669
SK
298static void __init exynos_map_io(void)
299{
300 if (soc_is_exynos4210() || soc_is_exynos4212() || soc_is_exynos4412())
301 iotable_init(exynos4_iodesc, ARRAY_SIZE(exynos4_iodesc));
302
303 if (soc_is_exynos5250() || soc_is_exynos5420())
304 iotable_init(exynos5_iodesc, ARRAY_SIZE(exynos5_iodesc));
305
306 if (soc_is_exynos4210()) {
307 if (samsung_rev() == EXYNOS4210_REV_0)
308 iotable_init(exynos4_iodesc0,
309 ARRAY_SIZE(exynos4_iodesc0));
310 else
311 iotable_init(exynos4_iodesc1,
312 ARRAY_SIZE(exynos4_iodesc1));
313 iotable_init(exynos4210_iodesc, ARRAY_SIZE(exynos4210_iodesc));
314 }
315 if (soc_is_exynos4212() || soc_is_exynos4412())
316 iotable_init(exynos4x12_iodesc, ARRAY_SIZE(exynos4x12_iodesc));
317 if (soc_is_exynos5250())
318 iotable_init(exynos5250_iodesc, ARRAY_SIZE(exynos5250_iodesc));
319}
cc511b8d 320
0e2238ec 321void __init exynos_init_io(void)
cc511b8d 322{
9c1fcdcc
DA
323 debug_ll_io_init();
324
04fae596 325 of_scan_flat_dt(exynos_fdt_map_chipid, NULL);
2edb36c4 326
cc511b8d
KK
327 /* detect cpu id and rev. */
328 s5p_init_cpu(S5P_VA_CHIPID);
329
6eb84669 330 exynos_map_io();
94c7ca71
KK
331}
332
9ee6af9c
TA
333struct bus_type exynos_subsys = {
334 .name = "exynos-core",
335 .dev_name = "exynos-core",
94c7ca71
KK
336};
337
94c7ca71 338static int __init exynos_core_init(void)
cc511b8d 339{
9ee6af9c 340 return subsys_system_register(&exynos_subsys, NULL);
cc511b8d 341}
94c7ca71 342core_initcall(exynos_core_init);
cc511b8d 343
cc511b8d
KK
344static int __init exynos4_l2x0_cache_init(void)
345{
e1b1994e
IH
346 int ret;
347
6cdeddcc 348 ret = l2x0_of_init(L2_AUX_VAL, L2_AUX_MASK);
87107d89
AB
349 if (ret)
350 return ret;
cc511b8d 351
87107d89
AB
352 l2x0_regs_phys = virt_to_phys(&l2x0_saved_regs);
353 clean_dcache_area(&l2x0_regs_phys, sizeof(unsigned long));
cc511b8d
KK
354 return 0;
355}
cc511b8d 356early_initcall(exynos4_l2x0_cache_init);
This page took 0.157833 seconds and 5 git commands to generate.