]> git.karo-electronics.de Git - karo-tx-linux.git/blob - arch/arm/mach-exynos/common.c
Merge remote-tracking branch 'gpio/for-next'
[karo-tx-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 }