ARM: EXYNOS: convert cpuidle driver to be a platform driver
[deliverable/linux.git] / arch / arm / mach-exynos / common.c
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>
13 #include <linux/bitops.h>
14 #include <linux/interrupt.h>
15 #include <linux/irq.h>
16 #include <linux/irqchip.h>
17 #include <linux/io.h>
18 #include <linux/device.h>
19 #include <linux/gpio.h>
20 #include <clocksource/samsung_pwm.h>
21 #include <linux/sched.h>
22 #include <linux/serial_core.h>
23 #include <linux/of.h>
24 #include <linux/of_fdt.h>
25 #include <linux/of_irq.h>
26 #include <linux/export.h>
27 #include <linux/irqdomain.h>
28 #include <linux/of_address.h>
29 #include <linux/clocksource.h>
30 #include <linux/clk-provider.h>
31 #include <linux/irqchip/arm-gic.h>
32 #include <linux/irqchip/chained_irq.h>
33 #include <linux/platform_device.h>
34
35 #include <asm/proc-fns.h>
36 #include <asm/exception.h>
37 #include <asm/hardware/cache-l2x0.h>
38 #include <asm/mach/map.h>
39 #include <asm/mach/irq.h>
40 #include <asm/cacheflush.h>
41
42 #include <mach/regs-irq.h>
43 #include <mach/regs-pmu.h>
44
45 #include <plat/cpu.h>
46 #include <plat/pm.h>
47 #include <plat/regs-serial.h>
48
49 #include "common.h"
50 #define L2_AUX_VAL 0x7C470001
51 #define L2_AUX_MASK 0xC200ffff
52
53 static const char name_exynos4210[] = "EXYNOS4210";
54 static const char name_exynos4212[] = "EXYNOS4212";
55 static const char name_exynos4412[] = "EXYNOS4412";
56 static const char name_exynos5250[] = "EXYNOS5250";
57 static const char name_exynos5420[] = "EXYNOS5420";
58 static const char name_exynos5440[] = "EXYNOS5440";
59
60 static void exynos4_map_io(void);
61 static void exynos5_map_io(void);
62 static int exynos_init(void);
63
64 static struct cpu_table cpu_ids[] __initdata = {
65 {
66 .idcode = EXYNOS4210_CPU_ID,
67 .idmask = EXYNOS4_CPU_MASK,
68 .map_io = exynos4_map_io,
69 .init = exynos_init,
70 .name = name_exynos4210,
71 }, {
72 .idcode = EXYNOS4212_CPU_ID,
73 .idmask = EXYNOS4_CPU_MASK,
74 .map_io = exynos4_map_io,
75 .init = exynos_init,
76 .name = name_exynos4212,
77 }, {
78 .idcode = EXYNOS4412_CPU_ID,
79 .idmask = EXYNOS4_CPU_MASK,
80 .map_io = exynos4_map_io,
81 .init = exynos_init,
82 .name = name_exynos4412,
83 }, {
84 .idcode = EXYNOS5250_SOC_ID,
85 .idmask = EXYNOS5_SOC_MASK,
86 .map_io = exynos5_map_io,
87 .init = exynos_init,
88 .name = name_exynos5250,
89 }, {
90 .idcode = EXYNOS5420_SOC_ID,
91 .idmask = EXYNOS5_SOC_MASK,
92 .map_io = exynos5_map_io,
93 .init = exynos_init,
94 .name = name_exynos5420,
95 }, {
96 .idcode = EXYNOS5440_SOC_ID,
97 .idmask = EXYNOS5_SOC_MASK,
98 .init = exynos_init,
99 .name = name_exynos5440,
100 },
101 };
102
103 /* Initial IO mappings */
104
105 static struct map_desc exynos4_iodesc[] __initdata = {
106 {
107 .virtual = (unsigned long)S3C_VA_SYS,
108 .pfn = __phys_to_pfn(EXYNOS4_PA_SYSCON),
109 .length = SZ_64K,
110 .type = MT_DEVICE,
111 }, {
112 .virtual = (unsigned long)S3C_VA_TIMER,
113 .pfn = __phys_to_pfn(EXYNOS4_PA_TIMER),
114 .length = SZ_16K,
115 .type = MT_DEVICE,
116 }, {
117 .virtual = (unsigned long)S3C_VA_WATCHDOG,
118 .pfn = __phys_to_pfn(EXYNOS4_PA_WATCHDOG),
119 .length = SZ_4K,
120 .type = MT_DEVICE,
121 }, {
122 .virtual = (unsigned long)S5P_VA_SROMC,
123 .pfn = __phys_to_pfn(EXYNOS4_PA_SROMC),
124 .length = SZ_4K,
125 .type = MT_DEVICE,
126 }, {
127 .virtual = (unsigned long)S5P_VA_SYSTIMER,
128 .pfn = __phys_to_pfn(EXYNOS4_PA_SYSTIMER),
129 .length = SZ_4K,
130 .type = MT_DEVICE,
131 }, {
132 .virtual = (unsigned long)S5P_VA_PMU,
133 .pfn = __phys_to_pfn(EXYNOS4_PA_PMU),
134 .length = SZ_64K,
135 .type = MT_DEVICE,
136 }, {
137 .virtual = (unsigned long)S5P_VA_COMBINER_BASE,
138 .pfn = __phys_to_pfn(EXYNOS4_PA_COMBINER),
139 .length = SZ_4K,
140 .type = MT_DEVICE,
141 }, {
142 .virtual = (unsigned long)S5P_VA_GIC_CPU,
143 .pfn = __phys_to_pfn(EXYNOS4_PA_GIC_CPU),
144 .length = SZ_64K,
145 .type = MT_DEVICE,
146 }, {
147 .virtual = (unsigned long)S5P_VA_GIC_DIST,
148 .pfn = __phys_to_pfn(EXYNOS4_PA_GIC_DIST),
149 .length = SZ_64K,
150 .type = MT_DEVICE,
151 }, {
152 .virtual = (unsigned long)S5P_VA_CMU,
153 .pfn = __phys_to_pfn(EXYNOS4_PA_CMU),
154 .length = SZ_128K,
155 .type = MT_DEVICE,
156 }, {
157 .virtual = (unsigned long)S5P_VA_COREPERI_BASE,
158 .pfn = __phys_to_pfn(EXYNOS4_PA_COREPERI),
159 .length = SZ_8K,
160 .type = MT_DEVICE,
161 }, {
162 .virtual = (unsigned long)S5P_VA_L2CC,
163 .pfn = __phys_to_pfn(EXYNOS4_PA_L2CC),
164 .length = SZ_4K,
165 .type = MT_DEVICE,
166 }, {
167 .virtual = (unsigned long)S5P_VA_DMC0,
168 .pfn = __phys_to_pfn(EXYNOS4_PA_DMC0),
169 .length = SZ_64K,
170 .type = MT_DEVICE,
171 }, {
172 .virtual = (unsigned long)S5P_VA_DMC1,
173 .pfn = __phys_to_pfn(EXYNOS4_PA_DMC1),
174 .length = SZ_64K,
175 .type = MT_DEVICE,
176 }, {
177 .virtual = (unsigned long)S3C_VA_USB_HSPHY,
178 .pfn = __phys_to_pfn(EXYNOS4_PA_HSPHY),
179 .length = SZ_4K,
180 .type = MT_DEVICE,
181 },
182 };
183
184 static struct map_desc exynos4_iodesc0[] __initdata = {
185 {
186 .virtual = (unsigned long)S5P_VA_SYSRAM,
187 .pfn = __phys_to_pfn(EXYNOS4_PA_SYSRAM0),
188 .length = SZ_4K,
189 .type = MT_DEVICE,
190 },
191 };
192
193 static struct map_desc exynos4_iodesc1[] __initdata = {
194 {
195 .virtual = (unsigned long)S5P_VA_SYSRAM,
196 .pfn = __phys_to_pfn(EXYNOS4_PA_SYSRAM1),
197 .length = SZ_4K,
198 .type = MT_DEVICE,
199 },
200 };
201
202 static struct map_desc exynos4210_iodesc[] __initdata = {
203 {
204 .virtual = (unsigned long)S5P_VA_SYSRAM_NS,
205 .pfn = __phys_to_pfn(EXYNOS4210_PA_SYSRAM_NS),
206 .length = SZ_4K,
207 .type = MT_DEVICE,
208 },
209 };
210
211 static struct map_desc exynos4x12_iodesc[] __initdata = {
212 {
213 .virtual = (unsigned long)S5P_VA_SYSRAM_NS,
214 .pfn = __phys_to_pfn(EXYNOS4x12_PA_SYSRAM_NS),
215 .length = SZ_4K,
216 .type = MT_DEVICE,
217 },
218 };
219
220 static struct map_desc exynos5250_iodesc[] __initdata = {
221 {
222 .virtual = (unsigned long)S5P_VA_SYSRAM_NS,
223 .pfn = __phys_to_pfn(EXYNOS5250_PA_SYSRAM_NS),
224 .length = SZ_4K,
225 .type = MT_DEVICE,
226 },
227 };
228
229 static struct map_desc exynos5_iodesc[] __initdata = {
230 {
231 .virtual = (unsigned long)S3C_VA_SYS,
232 .pfn = __phys_to_pfn(EXYNOS5_PA_SYSCON),
233 .length = SZ_64K,
234 .type = MT_DEVICE,
235 }, {
236 .virtual = (unsigned long)S3C_VA_TIMER,
237 .pfn = __phys_to_pfn(EXYNOS5_PA_TIMER),
238 .length = SZ_16K,
239 .type = MT_DEVICE,
240 }, {
241 .virtual = (unsigned long)S3C_VA_WATCHDOG,
242 .pfn = __phys_to_pfn(EXYNOS5_PA_WATCHDOG),
243 .length = SZ_4K,
244 .type = MT_DEVICE,
245 }, {
246 .virtual = (unsigned long)S5P_VA_SROMC,
247 .pfn = __phys_to_pfn(EXYNOS5_PA_SROMC),
248 .length = SZ_4K,
249 .type = MT_DEVICE,
250 }, {
251 .virtual = (unsigned long)S5P_VA_SYSRAM,
252 .pfn = __phys_to_pfn(EXYNOS5_PA_SYSRAM),
253 .length = SZ_4K,
254 .type = MT_DEVICE,
255 }, {
256 .virtual = (unsigned long)S5P_VA_CMU,
257 .pfn = __phys_to_pfn(EXYNOS5_PA_CMU),
258 .length = 144 * SZ_1K,
259 .type = MT_DEVICE,
260 }, {
261 .virtual = (unsigned long)S5P_VA_PMU,
262 .pfn = __phys_to_pfn(EXYNOS5_PA_PMU),
263 .length = SZ_64K,
264 .type = MT_DEVICE,
265 },
266 };
267
268 void exynos4_restart(enum reboot_mode mode, const char *cmd)
269 {
270 __raw_writel(0x1, S5P_SWRESET);
271 }
272
273 void exynos5_restart(enum reboot_mode mode, const char *cmd)
274 {
275 struct device_node *np;
276 u32 val;
277 void __iomem *addr;
278
279 val = 0x1;
280 addr = EXYNOS_SWRESET;
281
282 if (of_machine_is_compatible("samsung,exynos5440")) {
283 u32 status;
284 np = of_find_compatible_node(NULL, NULL, "samsung,exynos5440-clock");
285
286 addr = of_iomap(np, 0) + 0xbc;
287 status = __raw_readl(addr);
288
289 addr = of_iomap(np, 0) + 0xcc;
290 val = __raw_readl(addr);
291
292 val = (val & 0xffff0000) | (status & 0xffff);
293 }
294
295 __raw_writel(val, addr);
296 }
297
298 static struct platform_device exynos_cpuidle = {
299 .name = "exynos_cpuidle",
300 .id = -1,
301 };
302
303 void __init exynos_cpuidle_init(void)
304 {
305 platform_device_register(&exynos_cpuidle);
306 }
307
308 void __init exynos_init_late(void)
309 {
310 if (of_machine_is_compatible("samsung,exynos5440"))
311 /* to be supported later */
312 return;
313
314 exynos_pm_late_initcall();
315 }
316
317 static int __init exynos_fdt_map_chipid(unsigned long node, const char *uname,
318 int depth, void *data)
319 {
320 struct map_desc iodesc;
321 __be32 *reg;
322 unsigned long len;
323
324 if (!of_flat_dt_is_compatible(node, "samsung,exynos4210-chipid") &&
325 !of_flat_dt_is_compatible(node, "samsung,exynos5440-clock"))
326 return 0;
327
328 reg = of_get_flat_dt_prop(node, "reg", &len);
329 if (reg == NULL || len != (sizeof(unsigned long) * 2))
330 return 0;
331
332 iodesc.pfn = __phys_to_pfn(be32_to_cpu(reg[0]));
333 iodesc.length = be32_to_cpu(reg[1]) - 1;
334 iodesc.virtual = (unsigned long)S5P_VA_CHIPID;
335 iodesc.type = MT_DEVICE;
336 iotable_init(&iodesc, 1);
337 return 1;
338 }
339
340 /*
341 * exynos_map_io
342 *
343 * register the standard cpu IO areas
344 */
345
346 void __init exynos_init_io(void)
347 {
348 debug_ll_io_init();
349
350 of_scan_flat_dt(exynos_fdt_map_chipid, NULL);
351
352 /* detect cpu id and rev. */
353 s5p_init_cpu(S5P_VA_CHIPID);
354
355 s3c_init_cpu(samsung_cpu_id, cpu_ids, ARRAY_SIZE(cpu_ids));
356 }
357
358 static void __init exynos4_map_io(void)
359 {
360 iotable_init(exynos4_iodesc, ARRAY_SIZE(exynos4_iodesc));
361
362 if (soc_is_exynos4210() && samsung_rev() == EXYNOS4210_REV_0)
363 iotable_init(exynos4_iodesc0, ARRAY_SIZE(exynos4_iodesc0));
364 else
365 iotable_init(exynos4_iodesc1, ARRAY_SIZE(exynos4_iodesc1));
366
367 if (soc_is_exynos4210())
368 iotable_init(exynos4210_iodesc, ARRAY_SIZE(exynos4210_iodesc));
369 if (soc_is_exynos4212() || soc_is_exynos4412())
370 iotable_init(exynos4x12_iodesc, ARRAY_SIZE(exynos4x12_iodesc));
371 }
372
373 static void __init exynos5_map_io(void)
374 {
375 iotable_init(exynos5_iodesc, ARRAY_SIZE(exynos5_iodesc));
376
377 if (soc_is_exynos5250())
378 iotable_init(exynos5250_iodesc, ARRAY_SIZE(exynos5250_iodesc));
379 }
380
381 void __init exynos_init_time(void)
382 {
383 of_clk_init(NULL);
384 clocksource_of_init();
385 }
386
387 struct bus_type exynos_subsys = {
388 .name = "exynos-core",
389 .dev_name = "exynos-core",
390 };
391
392 static struct device exynos4_dev = {
393 .bus = &exynos_subsys,
394 };
395
396 static int __init exynos_core_init(void)
397 {
398 return subsys_system_register(&exynos_subsys, NULL);
399 }
400 core_initcall(exynos_core_init);
401
402 static int __init exynos4_l2x0_cache_init(void)
403 {
404 int ret;
405
406 ret = l2x0_of_init(L2_AUX_VAL, L2_AUX_MASK);
407 if (ret)
408 return ret;
409
410 l2x0_regs_phys = virt_to_phys(&l2x0_saved_regs);
411 clean_dcache_area(&l2x0_regs_phys, sizeof(unsigned long));
412 return 0;
413 }
414 early_initcall(exynos4_l2x0_cache_init);
415
416 static int __init exynos_init(void)
417 {
418 printk(KERN_INFO "EXYNOS: Initializing architecture\n");
419
420 return device_register(&exynos4_dev);
421 }
This page took 0.063138 seconds and 5 git commands to generate.