ARM: EXYNOS: Remove static io-remapping for gic and combiner
[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>
13#include <linux/interrupt.h>
14#include <linux/irq.h>
15#include <linux/io.h>
7affca35 16#include <linux/device.h>
cc511b8d
KK
17#include <linux/gpio.h>
18#include <linux/sched.h>
19#include <linux/serial_core.h>
237c78be
AB
20#include <linux/of.h>
21#include <linux/of_irq.h>
1e60bc0b
TA
22#include <linux/export.h>
23#include <linux/irqdomain.h>
e873a47c 24#include <linux/of_address.h>
cc511b8d
KK
25
26#include <asm/proc-fns.h>
40ba95fd 27#include <asm/exception.h>
cc511b8d
KK
28#include <asm/hardware/cache-l2x0.h>
29#include <asm/hardware/gic.h>
30#include <asm/mach/map.h>
31#include <asm/mach/irq.h>
b756a50f 32#include <asm/cacheflush.h>
cc511b8d
KK
33
34#include <mach/regs-irq.h>
35#include <mach/regs-pmu.h>
36#include <mach/regs-gpio.h>
b756a50f 37#include <mach/pmu.h>
cc511b8d
KK
38
39#include <plat/cpu.h>
40#include <plat/clock.h>
41#include <plat/devs.h>
42#include <plat/pm.h>
cc511b8d
KK
43#include <plat/sdhci.h>
44#include <plat/gpio-cfg.h>
45#include <plat/adc-core.h>
46#include <plat/fb-core.h>
47#include <plat/fimc-core.h>
48#include <plat/iic-core.h>
49#include <plat/tv-core.h>
50#include <plat/regs-serial.h>
51
52#include "common.h"
6cdeddcc
ADK
53#define L2_AUX_VAL 0x7C470001
54#define L2_AUX_MASK 0xC200ffff
cc511b8d 55
cc511b8d
KK
56static const char name_exynos4210[] = "EXYNOS4210";
57static const char name_exynos4212[] = "EXYNOS4212";
58static const char name_exynos4412[] = "EXYNOS4412";
94c7ca71 59static const char name_exynos5250[] = "EXYNOS5250";
cc511b8d 60
906c789c 61static void exynos4_map_io(void);
94c7ca71 62static void exynos5_map_io(void);
906c789c 63static void exynos4_init_clocks(int xtal);
94c7ca71 64static void exynos5_init_clocks(int xtal);
920f4880 65static void exynos_init_uarts(struct s3c2410_uartcfg *cfg, int no);
906c789c 66static int exynos_init(void);
cc511b8d
KK
67
68static struct cpu_table cpu_ids[] __initdata = {
69 {
70 .idcode = EXYNOS4210_CPU_ID,
71 .idmask = EXYNOS4_CPU_MASK,
72 .map_io = exynos4_map_io,
73 .init_clocks = exynos4_init_clocks,
920f4880 74 .init_uarts = exynos_init_uarts,
cc511b8d
KK
75 .init = exynos_init,
76 .name = name_exynos4210,
77 }, {
78 .idcode = EXYNOS4212_CPU_ID,
79 .idmask = EXYNOS4_CPU_MASK,
80 .map_io = exynos4_map_io,
81 .init_clocks = exynos4_init_clocks,
920f4880 82 .init_uarts = exynos_init_uarts,
cc511b8d
KK
83 .init = exynos_init,
84 .name = name_exynos4212,
85 }, {
86 .idcode = EXYNOS4412_CPU_ID,
87 .idmask = EXYNOS4_CPU_MASK,
88 .map_io = exynos4_map_io,
89 .init_clocks = exynos4_init_clocks,
920f4880 90 .init_uarts = exynos_init_uarts,
cc511b8d
KK
91 .init = exynos_init,
92 .name = name_exynos4412,
94c7ca71
KK
93 }, {
94 .idcode = EXYNOS5250_SOC_ID,
95 .idmask = EXYNOS5_SOC_MASK,
96 .map_io = exynos5_map_io,
97 .init_clocks = exynos5_init_clocks,
98 .init_uarts = exynos_init_uarts,
99 .init = exynos_init,
100 .name = name_exynos5250,
cc511b8d
KK
101 },
102};
103
104/* Initial IO mappings */
105
106static struct map_desc exynos_iodesc[] __initdata = {
107 {
108 .virtual = (unsigned long)S5P_VA_CHIPID,
94c7ca71 109 .pfn = __phys_to_pfn(EXYNOS_PA_CHIPID),
cc511b8d
KK
110 .length = SZ_4K,
111 .type = MT_DEVICE,
94c7ca71
KK
112 },
113};
114
115static struct map_desc exynos4_iodesc[] __initdata = {
116 {
cc511b8d
KK
117 .virtual = (unsigned long)S3C_VA_SYS,
118 .pfn = __phys_to_pfn(EXYNOS4_PA_SYSCON),
119 .length = SZ_64K,
120 .type = MT_DEVICE,
121 }, {
122 .virtual = (unsigned long)S3C_VA_TIMER,
123 .pfn = __phys_to_pfn(EXYNOS4_PA_TIMER),
124 .length = SZ_16K,
125 .type = MT_DEVICE,
126 }, {
127 .virtual = (unsigned long)S3C_VA_WATCHDOG,
128 .pfn = __phys_to_pfn(EXYNOS4_PA_WATCHDOG),
129 .length = SZ_4K,
130 .type = MT_DEVICE,
131 }, {
132 .virtual = (unsigned long)S5P_VA_SROMC,
133 .pfn = __phys_to_pfn(EXYNOS4_PA_SROMC),
134 .length = SZ_4K,
135 .type = MT_DEVICE,
136 }, {
137 .virtual = (unsigned long)S5P_VA_SYSTIMER,
138 .pfn = __phys_to_pfn(EXYNOS4_PA_SYSTIMER),
139 .length = SZ_4K,
140 .type = MT_DEVICE,
141 }, {
142 .virtual = (unsigned long)S5P_VA_PMU,
143 .pfn = __phys_to_pfn(EXYNOS4_PA_PMU),
144 .length = SZ_64K,
145 .type = MT_DEVICE,
146 }, {
147 .virtual = (unsigned long)S5P_VA_COMBINER_BASE,
148 .pfn = __phys_to_pfn(EXYNOS4_PA_COMBINER),
149 .length = SZ_4K,
150 .type = MT_DEVICE,
151 }, {
152 .virtual = (unsigned long)S5P_VA_GIC_CPU,
153 .pfn = __phys_to_pfn(EXYNOS4_PA_GIC_CPU),
154 .length = SZ_64K,
155 .type = MT_DEVICE,
156 }, {
157 .virtual = (unsigned long)S5P_VA_GIC_DIST,
158 .pfn = __phys_to_pfn(EXYNOS4_PA_GIC_DIST),
159 .length = SZ_64K,
160 .type = MT_DEVICE,
161 }, {
162 .virtual = (unsigned long)S3C_VA_UART,
163 .pfn = __phys_to_pfn(EXYNOS4_PA_UART),
164 .length = SZ_512K,
165 .type = MT_DEVICE,
94c7ca71 166 }, {
cc511b8d
KK
167 .virtual = (unsigned long)S5P_VA_CMU,
168 .pfn = __phys_to_pfn(EXYNOS4_PA_CMU),
169 .length = SZ_128K,
170 .type = MT_DEVICE,
171 }, {
172 .virtual = (unsigned long)S5P_VA_COREPERI_BASE,
173 .pfn = __phys_to_pfn(EXYNOS4_PA_COREPERI),
174 .length = SZ_8K,
175 .type = MT_DEVICE,
176 }, {
177 .virtual = (unsigned long)S5P_VA_L2CC,
178 .pfn = __phys_to_pfn(EXYNOS4_PA_L2CC),
179 .length = SZ_4K,
180 .type = MT_DEVICE,
cc511b8d
KK
181 }, {
182 .virtual = (unsigned long)S5P_VA_DMC0,
183 .pfn = __phys_to_pfn(EXYNOS4_PA_DMC0),
2bde0b08
MH
184 .length = SZ_64K,
185 .type = MT_DEVICE,
186 }, {
187 .virtual = (unsigned long)S5P_VA_DMC1,
188 .pfn = __phys_to_pfn(EXYNOS4_PA_DMC1),
189 .length = SZ_64K,
cc511b8d 190 .type = MT_DEVICE,
cc511b8d
KK
191 }, {
192 .virtual = (unsigned long)S3C_VA_USB_HSPHY,
193 .pfn = __phys_to_pfn(EXYNOS4_PA_HSPHY),
194 .length = SZ_4K,
195 .type = MT_DEVICE,
196 },
197};
198
199static struct map_desc exynos4_iodesc0[] __initdata = {
200 {
201 .virtual = (unsigned long)S5P_VA_SYSRAM,
202 .pfn = __phys_to_pfn(EXYNOS4_PA_SYSRAM0),
203 .length = SZ_4K,
204 .type = MT_DEVICE,
205 },
206};
207
208static struct map_desc exynos4_iodesc1[] __initdata = {
209 {
210 .virtual = (unsigned long)S5P_VA_SYSRAM,
211 .pfn = __phys_to_pfn(EXYNOS4_PA_SYSRAM1),
212 .length = SZ_4K,
213 .type = MT_DEVICE,
214 },
215};
216
94c7ca71
KK
217static struct map_desc exynos5_iodesc[] __initdata = {
218 {
219 .virtual = (unsigned long)S3C_VA_SYS,
220 .pfn = __phys_to_pfn(EXYNOS5_PA_SYSCON),
221 .length = SZ_64K,
222 .type = MT_DEVICE,
223 }, {
224 .virtual = (unsigned long)S3C_VA_TIMER,
225 .pfn = __phys_to_pfn(EXYNOS5_PA_TIMER),
226 .length = SZ_16K,
227 .type = MT_DEVICE,
228 }, {
229 .virtual = (unsigned long)S3C_VA_WATCHDOG,
230 .pfn = __phys_to_pfn(EXYNOS5_PA_WATCHDOG),
231 .length = SZ_4K,
232 .type = MT_DEVICE,
233 }, {
234 .virtual = (unsigned long)S5P_VA_SROMC,
235 .pfn = __phys_to_pfn(EXYNOS5_PA_SROMC),
236 .length = SZ_4K,
237 .type = MT_DEVICE,
238 }, {
239 .virtual = (unsigned long)S5P_VA_SYSTIMER,
240 .pfn = __phys_to_pfn(EXYNOS5_PA_SYSTIMER),
241 .length = SZ_4K,
242 .type = MT_DEVICE,
243 }, {
244 .virtual = (unsigned long)S5P_VA_SYSRAM,
245 .pfn = __phys_to_pfn(EXYNOS5_PA_SYSRAM),
246 .length = SZ_4K,
247 .type = MT_DEVICE,
248 }, {
249 .virtual = (unsigned long)S5P_VA_CMU,
250 .pfn = __phys_to_pfn(EXYNOS5_PA_CMU),
251 .length = 144 * SZ_1K,
252 .type = MT_DEVICE,
253 }, {
254 .virtual = (unsigned long)S5P_VA_PMU,
255 .pfn = __phys_to_pfn(EXYNOS5_PA_PMU),
256 .length = SZ_64K,
257 .type = MT_DEVICE,
94c7ca71
KK
258 }, {
259 .virtual = (unsigned long)S3C_VA_UART,
260 .pfn = __phys_to_pfn(EXYNOS5_PA_UART),
261 .length = SZ_512K,
262 .type = MT_DEVICE,
94c7ca71
KK
263 },
264};
265
9eb48595 266void exynos4_restart(char mode, const char *cmd)
cc511b8d
KK
267{
268 __raw_writel(0x1, S5P_SWRESET);
269}
270
94c7ca71
KK
271void exynos5_restart(char mode, const char *cmd)
272{
273 __raw_writel(0x1, EXYNOS_SWRESET);
274}
275
bb13fabc
SG
276void __init exynos_init_late(void)
277{
278 exynos_pm_late_initcall();
279}
280
cc511b8d
KK
281/*
282 * exynos_map_io
283 *
284 * register the standard cpu IO areas
285 */
286
287void __init exynos_init_io(struct map_desc *mach_desc, int size)
288{
289 /* initialize the io descriptors we need for initialization */
290 iotable_init(exynos_iodesc, ARRAY_SIZE(exynos_iodesc));
291 if (mach_desc)
292 iotable_init(mach_desc, size);
293
294 /* detect cpu id and rev. */
295 s5p_init_cpu(S5P_VA_CHIPID);
296
297 s3c_init_cpu(samsung_cpu_id, cpu_ids, ARRAY_SIZE(cpu_ids));
298}
299
906c789c 300static void __init exynos4_map_io(void)
cc511b8d
KK
301{
302 iotable_init(exynos4_iodesc, ARRAY_SIZE(exynos4_iodesc));
303
304 if (soc_is_exynos4210() && samsung_rev() == EXYNOS4210_REV_0)
305 iotable_init(exynos4_iodesc0, ARRAY_SIZE(exynos4_iodesc0));
306 else
307 iotable_init(exynos4_iodesc1, ARRAY_SIZE(exynos4_iodesc1));
308
309 /* initialize device information early */
310 exynos4_default_sdhci0();
311 exynos4_default_sdhci1();
312 exynos4_default_sdhci2();
313 exynos4_default_sdhci3();
314
315 s3c_adc_setname("samsung-adc-v3");
316
317 s3c_fimc_setname(0, "exynos4-fimc");
318 s3c_fimc_setname(1, "exynos4-fimc");
319 s3c_fimc_setname(2, "exynos4-fimc");
320 s3c_fimc_setname(3, "exynos4-fimc");
321
8482c81c
TA
322 s3c_sdhci_setname(0, "exynos4-sdhci");
323 s3c_sdhci_setname(1, "exynos4-sdhci");
324 s3c_sdhci_setname(2, "exynos4-sdhci");
325 s3c_sdhci_setname(3, "exynos4-sdhci");
326
cc511b8d
KK
327 /* The I2C bus controllers are directly compatible with s3c2440 */
328 s3c_i2c0_setname("s3c2440-i2c");
329 s3c_i2c1_setname("s3c2440-i2c");
330 s3c_i2c2_setname("s3c2440-i2c");
331
332 s5p_fb_setname(0, "exynos4-fb");
333 s5p_hdmi_setname("exynos4-hdmi");
334}
335
94c7ca71
KK
336static void __init exynos5_map_io(void)
337{
338 iotable_init(exynos5_iodesc, ARRAY_SIZE(exynos5_iodesc));
339
bb19a751
KK
340 s3c_device_i2c0.resource[0].start = EXYNOS5_PA_IIC(0);
341 s3c_device_i2c0.resource[0].end = EXYNOS5_PA_IIC(0) + SZ_4K - 1;
342 s3c_device_i2c0.resource[1].start = EXYNOS5_IRQ_IIC;
343 s3c_device_i2c0.resource[1].end = EXYNOS5_IRQ_IIC;
344
8482c81c
TA
345 s3c_sdhci_setname(0, "exynos4-sdhci");
346 s3c_sdhci_setname(1, "exynos4-sdhci");
347 s3c_sdhci_setname(2, "exynos4-sdhci");
348 s3c_sdhci_setname(3, "exynos4-sdhci");
349
94c7ca71
KK
350 /* The I2C bus controllers are directly compatible with s3c2440 */
351 s3c_i2c0_setname("s3c2440-i2c");
352 s3c_i2c1_setname("s3c2440-i2c");
353 s3c_i2c2_setname("s3c2440-i2c");
354}
355
906c789c 356static void __init exynos4_init_clocks(int xtal)
cc511b8d
KK
357{
358 printk(KERN_DEBUG "%s: initializing clocks\n", __func__);
359
360 s3c24xx_register_baseclocks(xtal);
361 s5p_register_clocks(xtal);
362
363 if (soc_is_exynos4210())
364 exynos4210_register_clocks();
365 else if (soc_is_exynos4212() || soc_is_exynos4412())
366 exynos4212_register_clocks();
367
368 exynos4_register_clocks();
369 exynos4_setup_clocks();
370}
371
94c7ca71
KK
372static void __init exynos5_init_clocks(int xtal)
373{
374 printk(KERN_DEBUG "%s: initializing clocks\n", __func__);
375
376 s3c24xx_register_baseclocks(xtal);
377 s5p_register_clocks(xtal);
378
379 exynos5_register_clocks();
380 exynos5_setup_clocks();
381}
382
cc511b8d
KK
383#define COMBINER_ENABLE_SET 0x0
384#define COMBINER_ENABLE_CLEAR 0x4
385#define COMBINER_INT_STATUS 0xC
386
387static DEFINE_SPINLOCK(irq_controller_lock);
388
389struct combiner_chip_data {
390 unsigned int irq_offset;
391 unsigned int irq_mask;
392 void __iomem *base;
393};
394
1e60bc0b 395static struct irq_domain *combiner_irq_domain;
cc511b8d
KK
396static struct combiner_chip_data combiner_data[MAX_COMBINER_NR];
397
398static inline void __iomem *combiner_base(struct irq_data *data)
399{
400 struct combiner_chip_data *combiner_data =
401 irq_data_get_irq_chip_data(data);
402
403 return combiner_data->base;
404}
405
406static void combiner_mask_irq(struct irq_data *data)
407{
1e60bc0b 408 u32 mask = 1 << (data->hwirq % 32);
cc511b8d
KK
409
410 __raw_writel(mask, combiner_base(data) + COMBINER_ENABLE_CLEAR);
411}
412
413static void combiner_unmask_irq(struct irq_data *data)
414{
1e60bc0b 415 u32 mask = 1 << (data->hwirq % 32);
cc511b8d
KK
416
417 __raw_writel(mask, combiner_base(data) + COMBINER_ENABLE_SET);
418}
419
420static void combiner_handle_cascade_irq(unsigned int irq, struct irq_desc *desc)
421{
422 struct combiner_chip_data *chip_data = irq_get_handler_data(irq);
423 struct irq_chip *chip = irq_get_chip(irq);
424 unsigned int cascade_irq, combiner_irq;
425 unsigned long status;
426
427 chained_irq_enter(chip, desc);
428
429 spin_lock(&irq_controller_lock);
430 status = __raw_readl(chip_data->base + COMBINER_INT_STATUS);
431 spin_unlock(&irq_controller_lock);
432 status &= chip_data->irq_mask;
433
434 if (status == 0)
435 goto out;
436
437 combiner_irq = __ffs(status);
438
439 cascade_irq = combiner_irq + (chip_data->irq_offset & ~31);
440 if (unlikely(cascade_irq >= NR_IRQS))
441 do_bad_IRQ(cascade_irq, desc);
442 else
443 generic_handle_irq(cascade_irq);
444
445 out:
446 chained_irq_exit(chip, desc);
447}
448
449static struct irq_chip combiner_chip = {
450 .name = "COMBINER",
451 .irq_mask = combiner_mask_irq,
452 .irq_unmask = combiner_unmask_irq,
453};
454
455static void __init combiner_cascade_irq(unsigned int combiner_nr, unsigned int irq)
456{
bb19a751
KK
457 unsigned int max_nr;
458
459 if (soc_is_exynos5250())
460 max_nr = EXYNOS5_MAX_COMBINER_NR;
461 else
462 max_nr = EXYNOS4_MAX_COMBINER_NR;
463
464 if (combiner_nr >= max_nr)
cc511b8d
KK
465 BUG();
466 if (irq_set_handler_data(irq, &combiner_data[combiner_nr]) != 0)
467 BUG();
468 irq_set_chained_handler(irq, combiner_handle_cascade_irq);
469}
470
1e60bc0b
TA
471static void __init combiner_init_one(unsigned int combiner_nr,
472 void __iomem *base)
cc511b8d 473{
cc511b8d 474 combiner_data[combiner_nr].base = base;
1e60bc0b
TA
475 combiner_data[combiner_nr].irq_offset = irq_find_mapping(
476 combiner_irq_domain, combiner_nr * MAX_IRQ_IN_COMBINER);
cc511b8d
KK
477 combiner_data[combiner_nr].irq_mask = 0xff << ((combiner_nr % 4) << 3);
478
479 /* Disable all interrupts */
cc511b8d
KK
480 __raw_writel(combiner_data[combiner_nr].irq_mask,
481 base + COMBINER_ENABLE_CLEAR);
1e60bc0b 482}
cc511b8d 483
e873a47c
TA
484#ifdef CONFIG_OF
485static int combiner_irq_domain_xlate(struct irq_domain *d,
486 struct device_node *controller,
487 const u32 *intspec, unsigned int intsize,
488 unsigned long *out_hwirq,
489 unsigned int *out_type)
490{
491 if (d->of_node != controller)
492 return -EINVAL;
493
494 if (intsize < 2)
495 return -EINVAL;
496
497 *out_hwirq = intspec[0] * MAX_IRQ_IN_COMBINER + intspec[1];
498 *out_type = 0;
499
500 return 0;
501}
502#else
503static int combiner_irq_domain_xlate(struct irq_domain *d,
504 struct device_node *controller,
505 const u32 *intspec, unsigned int intsize,
506 unsigned long *out_hwirq,
507 unsigned int *out_type)
508{
509 return -EINVAL;
510}
511#endif
512
1e60bc0b
TA
513static int combiner_irq_domain_map(struct irq_domain *d, unsigned int irq,
514 irq_hw_number_t hw)
515{
516 irq_set_chip_and_handler(irq, &combiner_chip, handle_level_irq);
517 irq_set_chip_data(irq, &combiner_data[hw >> 3]);
518 set_irq_flags(irq, IRQF_VALID | IRQF_PROBE);
519
520 return 0;
521}
cc511b8d 522
1e60bc0b 523static struct irq_domain_ops combiner_irq_domain_ops = {
e873a47c 524 .xlate = combiner_irq_domain_xlate,
1e60bc0b
TA
525 .map = combiner_irq_domain_map,
526};
527
2a2b0e20
SK
528static void __init combiner_init(void __iomem *combiner_base,
529 struct device_node *np)
1e60bc0b 530{
e873a47c 531 int i, irq, irq_base;
1e60bc0b
TA
532 unsigned int max_nr, nr_irq;
533
e873a47c
TA
534 if (np) {
535 if (of_property_read_u32(np, "samsung,combiner-nr", &max_nr)) {
536 pr_warning("%s: number of combiners not specified, "
537 "setting default as %d.\n",
538 __func__, EXYNOS4_MAX_COMBINER_NR);
539 max_nr = EXYNOS4_MAX_COMBINER_NR;
540 }
541 } else {
542 max_nr = soc_is_exynos5250() ? EXYNOS5_MAX_COMBINER_NR :
543 EXYNOS4_MAX_COMBINER_NR;
544 }
1e60bc0b
TA
545 nr_irq = max_nr * MAX_IRQ_IN_COMBINER;
546
547 irq_base = irq_alloc_descs(COMBINER_IRQ(0, 0), 1, nr_irq, 0);
548 if (IS_ERR_VALUE(irq_base)) {
549 irq_base = COMBINER_IRQ(0, 0);
550 pr_warning("%s: irq desc alloc failed. Continuing with %d as linux irq base\n", __func__, irq_base);
551 }
552
553 combiner_irq_domain = irq_domain_add_legacy(np, nr_irq, irq_base, 0,
554 &combiner_irq_domain_ops, &combiner_data);
555 if (WARN_ON(!combiner_irq_domain)) {
556 pr_warning("%s: irq domain init failed\n", __func__);
557 return;
558 }
559
560 for (i = 0; i < max_nr; i++) {
561 combiner_init_one(i, combiner_base + (i >> 2) * 0x10);
820f3dd7
AB
562 irq = IRQ_SPI(i);
563#ifdef CONFIG_OF
564 if (np)
565 irq = irq_of_parse_and_map(np, i);
566#endif
e873a47c 567 combiner_cascade_irq(i, irq);
cc511b8d
KK
568 }
569}
570
237c78be 571#ifdef CONFIG_OF
e873a47c
TA
572int __init combiner_of_init(struct device_node *np, struct device_node *parent)
573{
574 void __iomem *combiner_base;
575
576 combiner_base = of_iomap(np, 0);
577 if (!combiner_base) {
578 pr_err("%s: failed to map combiner registers\n", __func__);
579 return -ENXIO;
580 }
581
582 combiner_init(combiner_base, np);
583
584 return 0;
585}
586
237c78be
AB
587static const struct of_device_id exynos4_dt_irq_match[] = {
588 { .compatible = "arm,cortex-a9-gic", .data = gic_of_init, },
e873a47c
TA
589 { .compatible = "samsung,exynos4210-combiner",
590 .data = combiner_of_init, },
237c78be
AB
591 {},
592};
593#endif
cc511b8d
KK
594
595void __init exynos4_init_irq(void)
596{
40ba95fd 597 unsigned int gic_bank_offset;
cc511b8d
KK
598
599 gic_bank_offset = soc_is_exynos4412() ? 0x4000 : 0x8000;
600
237c78be 601 if (!of_have_populated_dt())
75294957 602 gic_init_bases(0, IRQ_PPI(0), S5P_VA_GIC_DIST, S5P_VA_GIC_CPU, gic_bank_offset, NULL);
237c78be
AB
603#ifdef CONFIG_OF
604 else
605 of_irq_init(exynos4_dt_irq_match);
606#endif
cc511b8d 607
e873a47c
TA
608 if (!of_have_populated_dt())
609 combiner_init(S5P_VA_COMBINER_BASE, NULL);
cc511b8d
KK
610
611 /*
612 * The parameters of s5p_init_irq() are for VIC init.
613 * Theses parameters should be NULL and 0 because EXYNOS4
614 * uses GIC instead of VIC.
615 */
616 s5p_init_irq(NULL, 0);
617}
618
94c7ca71
KK
619void __init exynos5_init_irq(void)
620{
6fff5a11 621#ifdef CONFIG_OF
5699b0ca 622 of_irq_init(exynos4_dt_irq_match);
6fff5a11 623#endif
cc511b8d
KK
624 /*
625 * The parameters of s5p_init_irq() are for VIC init.
626 * Theses parameters should be NULL and 0 because EXYNOS4
627 * uses GIC instead of VIC.
628 */
629 s5p_init_irq(NULL, 0);
630}
631
9ee6af9c
TA
632struct bus_type exynos_subsys = {
633 .name = "exynos-core",
634 .dev_name = "exynos-core",
94c7ca71
KK
635};
636
7affca35 637static struct device exynos4_dev = {
9ee6af9c 638 .bus = &exynos_subsys,
94c7ca71
KK
639};
640
641static int __init exynos_core_init(void)
cc511b8d 642{
9ee6af9c 643 return subsys_system_register(&exynos_subsys, NULL);
cc511b8d 644}
94c7ca71 645core_initcall(exynos_core_init);
cc511b8d
KK
646
647#ifdef CONFIG_CACHE_L2X0
648static int __init exynos4_l2x0_cache_init(void)
649{
e1b1994e
IH
650 int ret;
651
94c7ca71
KK
652 if (soc_is_exynos5250())
653 return 0;
654
6cdeddcc
ADK
655 ret = l2x0_of_init(L2_AUX_VAL, L2_AUX_MASK);
656 if (!ret) {
657 l2x0_regs_phys = virt_to_phys(&l2x0_saved_regs);
658 clean_dcache_area(&l2x0_regs_phys, sizeof(unsigned long));
659 return 0;
660 }
cc511b8d 661
b756a50f
ADK
662 if (!(__raw_readl(S5P_VA_L2CC + L2X0_CTRL) & 0x1)) {
663 l2x0_saved_regs.phy_base = EXYNOS4_PA_L2CC;
664 /* TAG, Data Latency Control: 2 cycles */
665 l2x0_saved_regs.tag_latency = 0x110;
cc511b8d 666
b756a50f
ADK
667 if (soc_is_exynos4212() || soc_is_exynos4412())
668 l2x0_saved_regs.data_latency = 0x120;
669 else
670 l2x0_saved_regs.data_latency = 0x110;
671
672 l2x0_saved_regs.prefetch_ctrl = 0x30000007;
673 l2x0_saved_regs.pwr_ctrl =
674 (L2X0_DYNAMIC_CLK_GATING_EN | L2X0_STNDBY_MODE_EN);
cc511b8d 675
b756a50f 676 l2x0_regs_phys = virt_to_phys(&l2x0_saved_regs);
cc511b8d 677
b756a50f
ADK
678 __raw_writel(l2x0_saved_regs.tag_latency,
679 S5P_VA_L2CC + L2X0_TAG_LATENCY_CTRL);
680 __raw_writel(l2x0_saved_regs.data_latency,
681 S5P_VA_L2CC + L2X0_DATA_LATENCY_CTRL);
cc511b8d 682
b756a50f
ADK
683 /* L2X0 Prefetch Control */
684 __raw_writel(l2x0_saved_regs.prefetch_ctrl,
685 S5P_VA_L2CC + L2X0_PREFETCH_CTRL);
686
687 /* L2X0 Power Control */
688 __raw_writel(l2x0_saved_regs.pwr_ctrl,
689 S5P_VA_L2CC + L2X0_POWER_CTRL);
690
691 clean_dcache_area(&l2x0_regs_phys, sizeof(unsigned long));
692 clean_dcache_area(&l2x0_saved_regs, sizeof(struct l2x0_regs));
693 }
cc511b8d 694
6cdeddcc 695 l2x0_init(S5P_VA_L2CC, L2_AUX_VAL, L2_AUX_MASK);
cc511b8d
KK
696 return 0;
697}
cc511b8d
KK
698early_initcall(exynos4_l2x0_cache_init);
699#endif
700
906c789c 701static int __init exynos_init(void)
cc511b8d
KK
702{
703 printk(KERN_INFO "EXYNOS: Initializing architecture\n");
94c7ca71 704
9ee6af9c 705 return device_register(&exynos4_dev);
cc511b8d
KK
706}
707
cc511b8d
KK
708/* uart registration process */
709
920f4880 710static void __init exynos_init_uarts(struct s3c2410_uartcfg *cfg, int no)
cc511b8d
KK
711{
712 struct s3c2410_uartcfg *tcfg = cfg;
713 u32 ucnt;
714
237c78be
AB
715 for (ucnt = 0; ucnt < no; ucnt++, tcfg++)
716 tcfg->has_fracval = 1;
cc511b8d 717
171c067c
KK
718 if (soc_is_exynos5250())
719 s3c24xx_init_uartdevs("exynos4210-uart", exynos5_uart_resources, cfg, no);
720 else
721 s3c24xx_init_uartdevs("exynos4210-uart", exynos4_uart_resources, cfg, no);
cc511b8d
KK
722}
723
330c90a5
EK
724static void __iomem *exynos_eint_base;
725
cc511b8d
KK
726static DEFINE_SPINLOCK(eint_lock);
727
728static unsigned int eint0_15_data[16];
729
330c90a5 730static inline int exynos4_irq_to_gpio(unsigned int irq)
cc511b8d 731{
330c90a5
EK
732 if (irq < IRQ_EINT(0))
733 return -EINVAL;
cc511b8d 734
330c90a5
EK
735 irq -= IRQ_EINT(0);
736 if (irq < 8)
737 return EXYNOS4_GPX0(irq);
738
739 irq -= 8;
740 if (irq < 8)
741 return EXYNOS4_GPX1(irq);
742
743 irq -= 8;
744 if (irq < 8)
745 return EXYNOS4_GPX2(irq);
746
747 irq -= 8;
748 if (irq < 8)
749 return EXYNOS4_GPX3(irq);
750
751 return -EINVAL;
752}
753
754static inline int exynos5_irq_to_gpio(unsigned int irq)
755{
756 if (irq < IRQ_EINT(0))
757 return -EINVAL;
758
759 irq -= IRQ_EINT(0);
760 if (irq < 8)
761 return EXYNOS5_GPX0(irq);
762
763 irq -= 8;
764 if (irq < 8)
765 return EXYNOS5_GPX1(irq);
766
767 irq -= 8;
768 if (irq < 8)
769 return EXYNOS5_GPX2(irq);
cc511b8d 770
330c90a5
EK
771 irq -= 8;
772 if (irq < 8)
773 return EXYNOS5_GPX3(irq);
774
775 return -EINVAL;
cc511b8d
KK
776}
777
bb19a751
KK
778static unsigned int exynos4_eint0_15_src_int[16] = {
779 EXYNOS4_IRQ_EINT0,
780 EXYNOS4_IRQ_EINT1,
781 EXYNOS4_IRQ_EINT2,
782 EXYNOS4_IRQ_EINT3,
783 EXYNOS4_IRQ_EINT4,
784 EXYNOS4_IRQ_EINT5,
785 EXYNOS4_IRQ_EINT6,
786 EXYNOS4_IRQ_EINT7,
787 EXYNOS4_IRQ_EINT8,
788 EXYNOS4_IRQ_EINT9,
789 EXYNOS4_IRQ_EINT10,
790 EXYNOS4_IRQ_EINT11,
791 EXYNOS4_IRQ_EINT12,
792 EXYNOS4_IRQ_EINT13,
793 EXYNOS4_IRQ_EINT14,
794 EXYNOS4_IRQ_EINT15,
795};
cc511b8d 796
bb19a751
KK
797static unsigned int exynos5_eint0_15_src_int[16] = {
798 EXYNOS5_IRQ_EINT0,
799 EXYNOS5_IRQ_EINT1,
800 EXYNOS5_IRQ_EINT2,
801 EXYNOS5_IRQ_EINT3,
802 EXYNOS5_IRQ_EINT4,
803 EXYNOS5_IRQ_EINT5,
804 EXYNOS5_IRQ_EINT6,
805 EXYNOS5_IRQ_EINT7,
806 EXYNOS5_IRQ_EINT8,
807 EXYNOS5_IRQ_EINT9,
808 EXYNOS5_IRQ_EINT10,
809 EXYNOS5_IRQ_EINT11,
810 EXYNOS5_IRQ_EINT12,
811 EXYNOS5_IRQ_EINT13,
812 EXYNOS5_IRQ_EINT14,
813 EXYNOS5_IRQ_EINT15,
814};
330c90a5 815static inline void exynos_irq_eint_mask(struct irq_data *data)
cc511b8d
KK
816{
817 u32 mask;
818
819 spin_lock(&eint_lock);
330c90a5
EK
820 mask = __raw_readl(EINT_MASK(exynos_eint_base, data->irq));
821 mask |= EINT_OFFSET_BIT(data->irq);
822 __raw_writel(mask, EINT_MASK(exynos_eint_base, data->irq));
cc511b8d
KK
823 spin_unlock(&eint_lock);
824}
825
330c90a5 826static void exynos_irq_eint_unmask(struct irq_data *data)
cc511b8d
KK
827{
828 u32 mask;
829
830 spin_lock(&eint_lock);
330c90a5
EK
831 mask = __raw_readl(EINT_MASK(exynos_eint_base, data->irq));
832 mask &= ~(EINT_OFFSET_BIT(data->irq));
833 __raw_writel(mask, EINT_MASK(exynos_eint_base, data->irq));
cc511b8d
KK
834 spin_unlock(&eint_lock);
835}
836
330c90a5 837static inline void exynos_irq_eint_ack(struct irq_data *data)
cc511b8d 838{
330c90a5
EK
839 __raw_writel(EINT_OFFSET_BIT(data->irq),
840 EINT_PEND(exynos_eint_base, data->irq));
cc511b8d
KK
841}
842
330c90a5 843static void exynos_irq_eint_maskack(struct irq_data *data)
cc511b8d 844{
330c90a5
EK
845 exynos_irq_eint_mask(data);
846 exynos_irq_eint_ack(data);
cc511b8d
KK
847}
848
330c90a5 849static int exynos_irq_eint_set_type(struct irq_data *data, unsigned int type)
cc511b8d
KK
850{
851 int offs = EINT_OFFSET(data->irq);
852 int shift;
853 u32 ctrl, mask;
854 u32 newvalue = 0;
855
856 switch (type) {
857 case IRQ_TYPE_EDGE_RISING:
858 newvalue = S5P_IRQ_TYPE_EDGE_RISING;
859 break;
860
861 case IRQ_TYPE_EDGE_FALLING:
862 newvalue = S5P_IRQ_TYPE_EDGE_FALLING;
863 break;
864
865 case IRQ_TYPE_EDGE_BOTH:
866 newvalue = S5P_IRQ_TYPE_EDGE_BOTH;
867 break;
868
869 case IRQ_TYPE_LEVEL_LOW:
870 newvalue = S5P_IRQ_TYPE_LEVEL_LOW;
871 break;
872
873 case IRQ_TYPE_LEVEL_HIGH:
874 newvalue = S5P_IRQ_TYPE_LEVEL_HIGH;
875 break;
876
877 default:
878 printk(KERN_ERR "No such irq type %d", type);
879 return -EINVAL;
880 }
881
882 shift = (offs & 0x7) * 4;
883 mask = 0x7 << shift;
884
885 spin_lock(&eint_lock);
330c90a5 886 ctrl = __raw_readl(EINT_CON(exynos_eint_base, data->irq));
cc511b8d
KK
887 ctrl &= ~mask;
888 ctrl |= newvalue << shift;
330c90a5 889 __raw_writel(ctrl, EINT_CON(exynos_eint_base, data->irq));
cc511b8d
KK
890 spin_unlock(&eint_lock);
891
330c90a5
EK
892 if (soc_is_exynos5250())
893 s3c_gpio_cfgpin(exynos5_irq_to_gpio(data->irq), S3C_GPIO_SFN(0xf));
894 else
895 s3c_gpio_cfgpin(exynos4_irq_to_gpio(data->irq), S3C_GPIO_SFN(0xf));
cc511b8d
KK
896
897 return 0;
898}
899
330c90a5
EK
900static struct irq_chip exynos_irq_eint = {
901 .name = "exynos-eint",
902 .irq_mask = exynos_irq_eint_mask,
903 .irq_unmask = exynos_irq_eint_unmask,
904 .irq_mask_ack = exynos_irq_eint_maskack,
905 .irq_ack = exynos_irq_eint_ack,
906 .irq_set_type = exynos_irq_eint_set_type,
cc511b8d
KK
907#ifdef CONFIG_PM
908 .irq_set_wake = s3c_irqext_wake,
909#endif
910};
911
912/*
913 * exynos4_irq_demux_eint
914 *
915 * This function demuxes the IRQ from from EINTs 16 to 31.
916 * It is designed to be inlined into the specific handler
917 * s5p_irq_demux_eintX_Y.
918 *
919 * Each EINT pend/mask registers handle eight of them.
920 */
330c90a5 921static inline void exynos_irq_demux_eint(unsigned int start)
cc511b8d
KK
922{
923 unsigned int irq;
924
330c90a5
EK
925 u32 status = __raw_readl(EINT_PEND(exynos_eint_base, start));
926 u32 mask = __raw_readl(EINT_MASK(exynos_eint_base, start));
cc511b8d
KK
927
928 status &= ~mask;
929 status &= 0xff;
930
931 while (status) {
932 irq = fls(status) - 1;
933 generic_handle_irq(irq + start);
934 status &= ~(1 << irq);
935 }
936}
937
330c90a5 938static void exynos_irq_demux_eint16_31(unsigned int irq, struct irq_desc *desc)
cc511b8d
KK
939{
940 struct irq_chip *chip = irq_get_chip(irq);
941 chained_irq_enter(chip, desc);
330c90a5
EK
942 exynos_irq_demux_eint(IRQ_EINT(16));
943 exynos_irq_demux_eint(IRQ_EINT(24));
cc511b8d
KK
944 chained_irq_exit(chip, desc);
945}
946
bb19a751 947static void exynos_irq_eint0_15(unsigned int irq, struct irq_desc *desc)
cc511b8d
KK
948{
949 u32 *irq_data = irq_get_handler_data(irq);
950 struct irq_chip *chip = irq_get_chip(irq);
951
952 chained_irq_enter(chip, desc);
953 chip->irq_mask(&desc->irq_data);
954
955 if (chip->irq_ack)
956 chip->irq_ack(&desc->irq_data);
957
958 generic_handle_irq(*irq_data);
959
960 chip->irq_unmask(&desc->irq_data);
961 chained_irq_exit(chip, desc);
962}
963
330c90a5 964static int __init exynos_init_irq_eint(void)
cc511b8d
KK
965{
966 int irq;
967
94c7ca71 968 if (soc_is_exynos5250())
330c90a5
EK
969 exynos_eint_base = ioremap(EXYNOS5_PA_GPIO1, SZ_4K);
970 else
971 exynos_eint_base = ioremap(EXYNOS4_PA_GPIO2, SZ_4K);
972
973 if (exynos_eint_base == NULL) {
974 pr_err("unable to ioremap for EINT base address\n");
975 return -ENOMEM;
976 }
94c7ca71 977
cc511b8d 978 for (irq = 0 ; irq <= 31 ; irq++) {
330c90a5 979 irq_set_chip_and_handler(IRQ_EINT(irq), &exynos_irq_eint,
cc511b8d
KK
980 handle_level_irq);
981 set_irq_flags(IRQ_EINT(irq), IRQF_VALID);
982 }
983
330c90a5 984 irq_set_chained_handler(EXYNOS_IRQ_EINT16_31, exynos_irq_demux_eint16_31);
cc511b8d
KK
985
986 for (irq = 0 ; irq <= 15 ; irq++) {
987 eint0_15_data[irq] = IRQ_EINT(irq);
988
bb19a751
KK
989 if (soc_is_exynos5250()) {
990 irq_set_handler_data(exynos5_eint0_15_src_int[irq],
991 &eint0_15_data[irq]);
992 irq_set_chained_handler(exynos5_eint0_15_src_int[irq],
993 exynos_irq_eint0_15);
994 } else {
995 irq_set_handler_data(exynos4_eint0_15_src_int[irq],
996 &eint0_15_data[irq]);
997 irq_set_chained_handler(exynos4_eint0_15_src_int[irq],
998 exynos_irq_eint0_15);
999 }
cc511b8d
KK
1000 }
1001
1002 return 0;
1003}
330c90a5 1004arch_initcall(exynos_init_irq_eint);
This page took 0.154929 seconds and 5 git commands to generate.