diff options
Diffstat (limited to 'arch/arm/mach-exynos/common.c')
-rw-r--r-- | arch/arm/mach-exynos/common.c | 449 |
1 files changed, 355 insertions, 94 deletions
diff --git a/arch/arm/mach-exynos/common.c b/arch/arm/mach-exynos/common.c index d67e21e526e6..e6cc50e94a58 100644 --- a/arch/arm/mach-exynos/common.c +++ b/arch/arm/mach-exynos/common.c | |||
@@ -53,6 +53,14 @@ | |||
53 | static const char name_exynos4210[] = "EXYNOS4210"; | 53 | static const char name_exynos4210[] = "EXYNOS4210"; |
54 | static const char name_exynos4212[] = "EXYNOS4212"; | 54 | static const char name_exynos4212[] = "EXYNOS4212"; |
55 | static const char name_exynos4412[] = "EXYNOS4412"; | 55 | static const char name_exynos4412[] = "EXYNOS4412"; |
56 | static const char name_exynos5250[] = "EXYNOS5250"; | ||
57 | |||
58 | static void exynos4_map_io(void); | ||
59 | static void exynos5_map_io(void); | ||
60 | static void exynos4_init_clocks(int xtal); | ||
61 | static void exynos5_init_clocks(int xtal); | ||
62 | static void exynos_init_uarts(struct s3c2410_uartcfg *cfg, int no); | ||
63 | static int exynos_init(void); | ||
56 | 64 | ||
57 | static struct cpu_table cpu_ids[] __initdata = { | 65 | static struct cpu_table cpu_ids[] __initdata = { |
58 | { | 66 | { |
@@ -60,7 +68,7 @@ static struct cpu_table cpu_ids[] __initdata = { | |||
60 | .idmask = EXYNOS4_CPU_MASK, | 68 | .idmask = EXYNOS4_CPU_MASK, |
61 | .map_io = exynos4_map_io, | 69 | .map_io = exynos4_map_io, |
62 | .init_clocks = exynos4_init_clocks, | 70 | .init_clocks = exynos4_init_clocks, |
63 | .init_uarts = exynos4_init_uarts, | 71 | .init_uarts = exynos_init_uarts, |
64 | .init = exynos_init, | 72 | .init = exynos_init, |
65 | .name = name_exynos4210, | 73 | .name = name_exynos4210, |
66 | }, { | 74 | }, { |
@@ -68,7 +76,7 @@ static struct cpu_table cpu_ids[] __initdata = { | |||
68 | .idmask = EXYNOS4_CPU_MASK, | 76 | .idmask = EXYNOS4_CPU_MASK, |
69 | .map_io = exynos4_map_io, | 77 | .map_io = exynos4_map_io, |
70 | .init_clocks = exynos4_init_clocks, | 78 | .init_clocks = exynos4_init_clocks, |
71 | .init_uarts = exynos4_init_uarts, | 79 | .init_uarts = exynos_init_uarts, |
72 | .init = exynos_init, | 80 | .init = exynos_init, |
73 | .name = name_exynos4212, | 81 | .name = name_exynos4212, |
74 | }, { | 82 | }, { |
@@ -76,9 +84,17 @@ static struct cpu_table cpu_ids[] __initdata = { | |||
76 | .idmask = EXYNOS4_CPU_MASK, | 84 | .idmask = EXYNOS4_CPU_MASK, |
77 | .map_io = exynos4_map_io, | 85 | .map_io = exynos4_map_io, |
78 | .init_clocks = exynos4_init_clocks, | 86 | .init_clocks = exynos4_init_clocks, |
79 | .init_uarts = exynos4_init_uarts, | 87 | .init_uarts = exynos_init_uarts, |
80 | .init = exynos_init, | 88 | .init = exynos_init, |
81 | .name = name_exynos4412, | 89 | .name = name_exynos4412, |
90 | }, { | ||
91 | .idcode = EXYNOS5250_SOC_ID, | ||
92 | .idmask = EXYNOS5_SOC_MASK, | ||
93 | .map_io = exynos5_map_io, | ||
94 | .init_clocks = exynos5_init_clocks, | ||
95 | .init_uarts = exynos_init_uarts, | ||
96 | .init = exynos_init, | ||
97 | .name = name_exynos5250, | ||
82 | }, | 98 | }, |
83 | }; | 99 | }; |
84 | 100 | ||
@@ -87,10 +103,14 @@ static struct cpu_table cpu_ids[] __initdata = { | |||
87 | static struct map_desc exynos_iodesc[] __initdata = { | 103 | static struct map_desc exynos_iodesc[] __initdata = { |
88 | { | 104 | { |
89 | .virtual = (unsigned long)S5P_VA_CHIPID, | 105 | .virtual = (unsigned long)S5P_VA_CHIPID, |
90 | .pfn = __phys_to_pfn(EXYNOS4_PA_CHIPID), | 106 | .pfn = __phys_to_pfn(EXYNOS_PA_CHIPID), |
91 | .length = SZ_4K, | 107 | .length = SZ_4K, |
92 | .type = MT_DEVICE, | 108 | .type = MT_DEVICE, |
93 | }, { | 109 | }, |
110 | }; | ||
111 | |||
112 | static struct map_desc exynos4_iodesc[] __initdata = { | ||
113 | { | ||
94 | .virtual = (unsigned long)S3C_VA_SYS, | 114 | .virtual = (unsigned long)S3C_VA_SYS, |
95 | .pfn = __phys_to_pfn(EXYNOS4_PA_SYSCON), | 115 | .pfn = __phys_to_pfn(EXYNOS4_PA_SYSCON), |
96 | .length = SZ_64K, | 116 | .length = SZ_64K, |
@@ -140,11 +160,7 @@ static struct map_desc exynos_iodesc[] __initdata = { | |||
140 | .pfn = __phys_to_pfn(EXYNOS4_PA_UART), | 160 | .pfn = __phys_to_pfn(EXYNOS4_PA_UART), |
141 | .length = SZ_512K, | 161 | .length = SZ_512K, |
142 | .type = MT_DEVICE, | 162 | .type = MT_DEVICE, |
143 | }, | 163 | }, { |
144 | }; | ||
145 | |||
146 | static struct map_desc exynos4_iodesc[] __initdata = { | ||
147 | { | ||
148 | .virtual = (unsigned long)S5P_VA_CMU, | 164 | .virtual = (unsigned long)S5P_VA_CMU, |
149 | .pfn = __phys_to_pfn(EXYNOS4_PA_CMU), | 165 | .pfn = __phys_to_pfn(EXYNOS4_PA_CMU), |
150 | .length = SZ_128K, | 166 | .length = SZ_128K, |
@@ -195,11 +211,80 @@ static struct map_desc exynos4_iodesc1[] __initdata = { | |||
195 | }, | 211 | }, |
196 | }; | 212 | }; |
197 | 213 | ||
214 | static struct map_desc exynos5_iodesc[] __initdata = { | ||
215 | { | ||
216 | .virtual = (unsigned long)S3C_VA_SYS, | ||
217 | .pfn = __phys_to_pfn(EXYNOS5_PA_SYSCON), | ||
218 | .length = SZ_64K, | ||
219 | .type = MT_DEVICE, | ||
220 | }, { | ||
221 | .virtual = (unsigned long)S3C_VA_TIMER, | ||
222 | .pfn = __phys_to_pfn(EXYNOS5_PA_TIMER), | ||
223 | .length = SZ_16K, | ||
224 | .type = MT_DEVICE, | ||
225 | }, { | ||
226 | .virtual = (unsigned long)S3C_VA_WATCHDOG, | ||
227 | .pfn = __phys_to_pfn(EXYNOS5_PA_WATCHDOG), | ||
228 | .length = SZ_4K, | ||
229 | .type = MT_DEVICE, | ||
230 | }, { | ||
231 | .virtual = (unsigned long)S5P_VA_SROMC, | ||
232 | .pfn = __phys_to_pfn(EXYNOS5_PA_SROMC), | ||
233 | .length = SZ_4K, | ||
234 | .type = MT_DEVICE, | ||
235 | }, { | ||
236 | .virtual = (unsigned long)S5P_VA_SYSTIMER, | ||
237 | .pfn = __phys_to_pfn(EXYNOS5_PA_SYSTIMER), | ||
238 | .length = SZ_4K, | ||
239 | .type = MT_DEVICE, | ||
240 | }, { | ||
241 | .virtual = (unsigned long)S5P_VA_SYSRAM, | ||
242 | .pfn = __phys_to_pfn(EXYNOS5_PA_SYSRAM), | ||
243 | .length = SZ_4K, | ||
244 | .type = MT_DEVICE, | ||
245 | }, { | ||
246 | .virtual = (unsigned long)S5P_VA_CMU, | ||
247 | .pfn = __phys_to_pfn(EXYNOS5_PA_CMU), | ||
248 | .length = 144 * SZ_1K, | ||
249 | .type = MT_DEVICE, | ||
250 | }, { | ||
251 | .virtual = (unsigned long)S5P_VA_PMU, | ||
252 | .pfn = __phys_to_pfn(EXYNOS5_PA_PMU), | ||
253 | .length = SZ_64K, | ||
254 | .type = MT_DEVICE, | ||
255 | }, { | ||
256 | .virtual = (unsigned long)S5P_VA_COMBINER_BASE, | ||
257 | .pfn = __phys_to_pfn(EXYNOS5_PA_COMBINER), | ||
258 | .length = SZ_4K, | ||
259 | .type = MT_DEVICE, | ||
260 | }, { | ||
261 | .virtual = (unsigned long)S3C_VA_UART, | ||
262 | .pfn = __phys_to_pfn(EXYNOS5_PA_UART), | ||
263 | .length = SZ_512K, | ||
264 | .type = MT_DEVICE, | ||
265 | }, { | ||
266 | .virtual = (unsigned long)S5P_VA_GIC_CPU, | ||
267 | .pfn = __phys_to_pfn(EXYNOS5_PA_GIC_CPU), | ||
268 | .length = SZ_64K, | ||
269 | .type = MT_DEVICE, | ||
270 | }, { | ||
271 | .virtual = (unsigned long)S5P_VA_GIC_DIST, | ||
272 | .pfn = __phys_to_pfn(EXYNOS5_PA_GIC_DIST), | ||
273 | .length = SZ_64K, | ||
274 | .type = MT_DEVICE, | ||
275 | }, | ||
276 | }; | ||
277 | |||
198 | void exynos4_restart(char mode, const char *cmd) | 278 | void exynos4_restart(char mode, const char *cmd) |
199 | { | 279 | { |
200 | __raw_writel(0x1, S5P_SWRESET); | 280 | __raw_writel(0x1, S5P_SWRESET); |
201 | } | 281 | } |
202 | 282 | ||
283 | void exynos5_restart(char mode, const char *cmd) | ||
284 | { | ||
285 | __raw_writel(0x1, EXYNOS_SWRESET); | ||
286 | } | ||
287 | |||
203 | /* | 288 | /* |
204 | * exynos_map_io | 289 | * exynos_map_io |
205 | * | 290 | * |
@@ -219,7 +304,7 @@ void __init exynos_init_io(struct map_desc *mach_desc, int size) | |||
219 | s3c_init_cpu(samsung_cpu_id, cpu_ids, ARRAY_SIZE(cpu_ids)); | 304 | s3c_init_cpu(samsung_cpu_id, cpu_ids, ARRAY_SIZE(cpu_ids)); |
220 | } | 305 | } |
221 | 306 | ||
222 | void __init exynos4_map_io(void) | 307 | static void __init exynos4_map_io(void) |
223 | { | 308 | { |
224 | iotable_init(exynos4_iodesc, ARRAY_SIZE(exynos4_iodesc)); | 309 | iotable_init(exynos4_iodesc, ARRAY_SIZE(exynos4_iodesc)); |
225 | 310 | ||
@@ -250,7 +335,22 @@ void __init exynos4_map_io(void) | |||
250 | s5p_hdmi_setname("exynos4-hdmi"); | 335 | s5p_hdmi_setname("exynos4-hdmi"); |
251 | } | 336 | } |
252 | 337 | ||
253 | void __init exynos4_init_clocks(int xtal) | 338 | static void __init exynos5_map_io(void) |
339 | { | ||
340 | iotable_init(exynos5_iodesc, ARRAY_SIZE(exynos5_iodesc)); | ||
341 | |||
342 | s3c_device_i2c0.resource[0].start = EXYNOS5_PA_IIC(0); | ||
343 | s3c_device_i2c0.resource[0].end = EXYNOS5_PA_IIC(0) + SZ_4K - 1; | ||
344 | s3c_device_i2c0.resource[1].start = EXYNOS5_IRQ_IIC; | ||
345 | s3c_device_i2c0.resource[1].end = EXYNOS5_IRQ_IIC; | ||
346 | |||
347 | /* The I2C bus controllers are directly compatible with s3c2440 */ | ||
348 | s3c_i2c0_setname("s3c2440-i2c"); | ||
349 | s3c_i2c1_setname("s3c2440-i2c"); | ||
350 | s3c_i2c2_setname("s3c2440-i2c"); | ||
351 | } | ||
352 | |||
353 | static void __init exynos4_init_clocks(int xtal) | ||
254 | { | 354 | { |
255 | printk(KERN_DEBUG "%s: initializing clocks\n", __func__); | 355 | printk(KERN_DEBUG "%s: initializing clocks\n", __func__); |
256 | 356 | ||
@@ -266,6 +366,17 @@ void __init exynos4_init_clocks(int xtal) | |||
266 | exynos4_setup_clocks(); | 366 | exynos4_setup_clocks(); |
267 | } | 367 | } |
268 | 368 | ||
369 | static void __init exynos5_init_clocks(int xtal) | ||
370 | { | ||
371 | printk(KERN_DEBUG "%s: initializing clocks\n", __func__); | ||
372 | |||
373 | s3c24xx_register_baseclocks(xtal); | ||
374 | s5p_register_clocks(xtal); | ||
375 | |||
376 | exynos5_register_clocks(); | ||
377 | exynos5_setup_clocks(); | ||
378 | } | ||
379 | |||
269 | #define COMBINER_ENABLE_SET 0x0 | 380 | #define COMBINER_ENABLE_SET 0x0 |
270 | #define COMBINER_ENABLE_CLEAR 0x4 | 381 | #define COMBINER_ENABLE_CLEAR 0x4 |
271 | #define COMBINER_INT_STATUS 0xC | 382 | #define COMBINER_INT_STATUS 0xC |
@@ -339,7 +450,14 @@ static struct irq_chip combiner_chip = { | |||
339 | 450 | ||
340 | static void __init combiner_cascade_irq(unsigned int combiner_nr, unsigned int irq) | 451 | static void __init combiner_cascade_irq(unsigned int combiner_nr, unsigned int irq) |
341 | { | 452 | { |
342 | if (combiner_nr >= MAX_COMBINER_NR) | 453 | unsigned int max_nr; |
454 | |||
455 | if (soc_is_exynos5250()) | ||
456 | max_nr = EXYNOS5_MAX_COMBINER_NR; | ||
457 | else | ||
458 | max_nr = EXYNOS4_MAX_COMBINER_NR; | ||
459 | |||
460 | if (combiner_nr >= max_nr) | ||
343 | BUG(); | 461 | BUG(); |
344 | if (irq_set_handler_data(irq, &combiner_data[combiner_nr]) != 0) | 462 | if (irq_set_handler_data(irq, &combiner_data[combiner_nr]) != 0) |
345 | BUG(); | 463 | BUG(); |
@@ -350,8 +468,14 @@ static void __init combiner_init(unsigned int combiner_nr, void __iomem *base, | |||
350 | unsigned int irq_start) | 468 | unsigned int irq_start) |
351 | { | 469 | { |
352 | unsigned int i; | 470 | unsigned int i; |
471 | unsigned int max_nr; | ||
353 | 472 | ||
354 | if (combiner_nr >= MAX_COMBINER_NR) | 473 | if (soc_is_exynos5250()) |
474 | max_nr = EXYNOS5_MAX_COMBINER_NR; | ||
475 | else | ||
476 | max_nr = EXYNOS4_MAX_COMBINER_NR; | ||
477 | |||
478 | if (combiner_nr >= max_nr) | ||
355 | BUG(); | 479 | BUG(); |
356 | 480 | ||
357 | combiner_data[combiner_nr].base = base; | 481 | combiner_data[combiner_nr].base = base; |
@@ -394,8 +518,28 @@ void __init exynos4_init_irq(void) | |||
394 | of_irq_init(exynos4_dt_irq_match); | 518 | of_irq_init(exynos4_dt_irq_match); |
395 | #endif | 519 | #endif |
396 | 520 | ||
397 | for (irq = 0; irq < MAX_COMBINER_NR; irq++) { | 521 | for (irq = 0; irq < EXYNOS4_MAX_COMBINER_NR; irq++) { |
522 | |||
523 | combiner_init(irq, (void __iomem *)S5P_VA_COMBINER(irq), | ||
524 | COMBINER_IRQ(irq, 0)); | ||
525 | combiner_cascade_irq(irq, IRQ_SPI(irq)); | ||
526 | } | ||
527 | |||
528 | /* | ||
529 | * The parameters of s5p_init_irq() are for VIC init. | ||
530 | * Theses parameters should be NULL and 0 because EXYNOS4 | ||
531 | * uses GIC instead of VIC. | ||
532 | */ | ||
533 | s5p_init_irq(NULL, 0); | ||
534 | } | ||
535 | |||
536 | void __init exynos5_init_irq(void) | ||
537 | { | ||
538 | int irq; | ||
539 | |||
540 | gic_init(0, IRQ_PPI(0), S5P_VA_GIC_DIST, S5P_VA_GIC_CPU); | ||
398 | 541 | ||
542 | for (irq = 0; irq < EXYNOS5_MAX_COMBINER_NR; irq++) { | ||
399 | combiner_init(irq, (void __iomem *)S5P_VA_COMBINER(irq), | 543 | combiner_init(irq, (void __iomem *)S5P_VA_COMBINER(irq), |
400 | COMBINER_IRQ(irq, 0)); | 544 | COMBINER_IRQ(irq, 0)); |
401 | combiner_cascade_irq(irq, IRQ_SPI(irq)); | 545 | combiner_cascade_irq(irq, IRQ_SPI(irq)); |
@@ -414,19 +558,34 @@ struct bus_type exynos4_subsys = { | |||
414 | .dev_name = "exynos4-core", | 558 | .dev_name = "exynos4-core", |
415 | }; | 559 | }; |
416 | 560 | ||
561 | struct bus_type exynos5_subsys = { | ||
562 | .name = "exynos5-core", | ||
563 | .dev_name = "exynos5-core", | ||
564 | }; | ||
565 | |||
417 | static struct device exynos4_dev = { | 566 | static struct device exynos4_dev = { |
418 | .bus = &exynos4_subsys, | 567 | .bus = &exynos4_subsys, |
419 | }; | 568 | }; |
420 | 569 | ||
421 | static int __init exynos4_core_init(void) | 570 | static struct device exynos5_dev = { |
571 | .bus = &exynos5_subsys, | ||
572 | }; | ||
573 | |||
574 | static int __init exynos_core_init(void) | ||
422 | { | 575 | { |
423 | return subsys_system_register(&exynos4_subsys, NULL); | 576 | if (soc_is_exynos5250()) |
577 | return subsys_system_register(&exynos5_subsys, NULL); | ||
578 | else | ||
579 | return subsys_system_register(&exynos4_subsys, NULL); | ||
424 | } | 580 | } |
425 | core_initcall(exynos4_core_init); | 581 | core_initcall(exynos_core_init); |
426 | 582 | ||
427 | #ifdef CONFIG_CACHE_L2X0 | 583 | #ifdef CONFIG_CACHE_L2X0 |
428 | static int __init exynos4_l2x0_cache_init(void) | 584 | static int __init exynos4_l2x0_cache_init(void) |
429 | { | 585 | { |
586 | if (soc_is_exynos5250()) | ||
587 | return 0; | ||
588 | |||
430 | int ret; | 589 | int ret; |
431 | ret = l2x0_of_init(L2_AUX_VAL, L2_AUX_MASK); | 590 | ret = l2x0_of_init(L2_AUX_VAL, L2_AUX_MASK); |
432 | if (!ret) { | 591 | if (!ret) { |
@@ -471,19 +630,47 @@ static int __init exynos4_l2x0_cache_init(void) | |||
471 | l2x0_init(S5P_VA_L2CC, L2_AUX_VAL, L2_AUX_MASK); | 630 | l2x0_init(S5P_VA_L2CC, L2_AUX_VAL, L2_AUX_MASK); |
472 | return 0; | 631 | return 0; |
473 | } | 632 | } |
474 | |||
475 | early_initcall(exynos4_l2x0_cache_init); | 633 | early_initcall(exynos4_l2x0_cache_init); |
476 | #endif | 634 | #endif |
477 | 635 | ||
478 | int __init exynos_init(void) | 636 | static int __init exynos5_l2_cache_init(void) |
637 | { | ||
638 | unsigned int val; | ||
639 | |||
640 | if (!soc_is_exynos5250()) | ||
641 | return 0; | ||
642 | |||
643 | asm volatile("mrc p15, 0, %0, c1, c0, 0\n" | ||
644 | "bic %0, %0, #(1 << 2)\n" /* cache disable */ | ||
645 | "mcr p15, 0, %0, c1, c0, 0\n" | ||
646 | "mrc p15, 1, %0, c9, c0, 2\n" | ||
647 | : "=r"(val)); | ||
648 | |||
649 | val |= (1 << 9) | (1 << 5) | (2 << 6) | (2 << 0); | ||
650 | |||
651 | asm volatile("mcr p15, 1, %0, c9, c0, 2\n" : : "r"(val)); | ||
652 | asm volatile("mrc p15, 0, %0, c1, c0, 0\n" | ||
653 | "orr %0, %0, #(1 << 2)\n" /* cache enable */ | ||
654 | "mcr p15, 0, %0, c1, c0, 0\n" | ||
655 | : : "r"(val)); | ||
656 | |||
657 | return 0; | ||
658 | } | ||
659 | early_initcall(exynos5_l2_cache_init); | ||
660 | |||
661 | static int __init exynos_init(void) | ||
479 | { | 662 | { |
480 | printk(KERN_INFO "EXYNOS: Initializing architecture\n"); | 663 | printk(KERN_INFO "EXYNOS: Initializing architecture\n"); |
481 | return device_register(&exynos4_dev); | 664 | |
665 | if (soc_is_exynos5250()) | ||
666 | return device_register(&exynos5_dev); | ||
667 | else | ||
668 | return device_register(&exynos4_dev); | ||
482 | } | 669 | } |
483 | 670 | ||
484 | /* uart registration process */ | 671 | /* uart registration process */ |
485 | 672 | ||
486 | void __init exynos4_init_uarts(struct s3c2410_uartcfg *cfg, int no) | 673 | static void __init exynos_init_uarts(struct s3c2410_uartcfg *cfg, int no) |
487 | { | 674 | { |
488 | struct s3c2410_uartcfg *tcfg = cfg; | 675 | struct s3c2410_uartcfg *tcfg = cfg; |
489 | u32 ucnt; | 676 | u32 ucnt; |
@@ -491,69 +678,138 @@ void __init exynos4_init_uarts(struct s3c2410_uartcfg *cfg, int no) | |||
491 | for (ucnt = 0; ucnt < no; ucnt++, tcfg++) | 678 | for (ucnt = 0; ucnt < no; ucnt++, tcfg++) |
492 | tcfg->has_fracval = 1; | 679 | tcfg->has_fracval = 1; |
493 | 680 | ||
494 | s3c24xx_init_uartdevs("exynos4210-uart", s5p_uart_resources, cfg, no); | 681 | if (soc_is_exynos5250()) |
682 | s3c24xx_init_uartdevs("exynos4210-uart", exynos5_uart_resources, cfg, no); | ||
683 | else | ||
684 | s3c24xx_init_uartdevs("exynos4210-uart", exynos4_uart_resources, cfg, no); | ||
495 | } | 685 | } |
496 | 686 | ||
687 | static void __iomem *exynos_eint_base; | ||
688 | |||
497 | static DEFINE_SPINLOCK(eint_lock); | 689 | static DEFINE_SPINLOCK(eint_lock); |
498 | 690 | ||
499 | static unsigned int eint0_15_data[16]; | 691 | static unsigned int eint0_15_data[16]; |
500 | 692 | ||
501 | static unsigned int exynos4_get_irq_nr(unsigned int number) | 693 | static inline int exynos4_irq_to_gpio(unsigned int irq) |
502 | { | 694 | { |
503 | u32 ret = 0; | 695 | if (irq < IRQ_EINT(0)) |
696 | return -EINVAL; | ||
504 | 697 | ||
505 | switch (number) { | 698 | irq -= IRQ_EINT(0); |
506 | case 0 ... 3: | 699 | if (irq < 8) |
507 | ret = (number + IRQ_EINT0); | 700 | return EXYNOS4_GPX0(irq); |
508 | break; | 701 | |
509 | case 4 ... 7: | 702 | irq -= 8; |
510 | ret = (number + (IRQ_EINT4 - 4)); | 703 | if (irq < 8) |
511 | break; | 704 | return EXYNOS4_GPX1(irq); |
512 | case 8 ... 15: | 705 | |
513 | ret = (number + (IRQ_EINT8 - 8)); | 706 | irq -= 8; |
514 | break; | 707 | if (irq < 8) |
515 | default: | 708 | return EXYNOS4_GPX2(irq); |
516 | printk(KERN_ERR "number available : %d\n", number); | 709 | |
517 | } | 710 | irq -= 8; |
711 | if (irq < 8) | ||
712 | return EXYNOS4_GPX3(irq); | ||
713 | |||
714 | return -EINVAL; | ||
715 | } | ||
716 | |||
717 | static inline int exynos5_irq_to_gpio(unsigned int irq) | ||
718 | { | ||
719 | if (irq < IRQ_EINT(0)) | ||
720 | return -EINVAL; | ||
721 | |||
722 | irq -= IRQ_EINT(0); | ||
723 | if (irq < 8) | ||
724 | return EXYNOS5_GPX0(irq); | ||
725 | |||
726 | irq -= 8; | ||
727 | if (irq < 8) | ||
728 | return EXYNOS5_GPX1(irq); | ||
729 | |||
730 | irq -= 8; | ||
731 | if (irq < 8) | ||
732 | return EXYNOS5_GPX2(irq); | ||
518 | 733 | ||
519 | return ret; | 734 | irq -= 8; |
735 | if (irq < 8) | ||
736 | return EXYNOS5_GPX3(irq); | ||
737 | |||
738 | return -EINVAL; | ||
520 | } | 739 | } |
521 | 740 | ||
522 | static inline void exynos4_irq_eint_mask(struct irq_data *data) | 741 | static unsigned int exynos4_eint0_15_src_int[16] = { |
742 | EXYNOS4_IRQ_EINT0, | ||
743 | EXYNOS4_IRQ_EINT1, | ||
744 | EXYNOS4_IRQ_EINT2, | ||
745 | EXYNOS4_IRQ_EINT3, | ||
746 | EXYNOS4_IRQ_EINT4, | ||
747 | EXYNOS4_IRQ_EINT5, | ||
748 | EXYNOS4_IRQ_EINT6, | ||
749 | EXYNOS4_IRQ_EINT7, | ||
750 | EXYNOS4_IRQ_EINT8, | ||
751 | EXYNOS4_IRQ_EINT9, | ||
752 | EXYNOS4_IRQ_EINT10, | ||
753 | EXYNOS4_IRQ_EINT11, | ||
754 | EXYNOS4_IRQ_EINT12, | ||
755 | EXYNOS4_IRQ_EINT13, | ||
756 | EXYNOS4_IRQ_EINT14, | ||
757 | EXYNOS4_IRQ_EINT15, | ||
758 | }; | ||
759 | |||
760 | static unsigned int exynos5_eint0_15_src_int[16] = { | ||
761 | EXYNOS5_IRQ_EINT0, | ||
762 | EXYNOS5_IRQ_EINT1, | ||
763 | EXYNOS5_IRQ_EINT2, | ||
764 | EXYNOS5_IRQ_EINT3, | ||
765 | EXYNOS5_IRQ_EINT4, | ||
766 | EXYNOS5_IRQ_EINT5, | ||
767 | EXYNOS5_IRQ_EINT6, | ||
768 | EXYNOS5_IRQ_EINT7, | ||
769 | EXYNOS5_IRQ_EINT8, | ||
770 | EXYNOS5_IRQ_EINT9, | ||
771 | EXYNOS5_IRQ_EINT10, | ||
772 | EXYNOS5_IRQ_EINT11, | ||
773 | EXYNOS5_IRQ_EINT12, | ||
774 | EXYNOS5_IRQ_EINT13, | ||
775 | EXYNOS5_IRQ_EINT14, | ||
776 | EXYNOS5_IRQ_EINT15, | ||
777 | }; | ||
778 | static inline void exynos_irq_eint_mask(struct irq_data *data) | ||
523 | { | 779 | { |
524 | u32 mask; | 780 | u32 mask; |
525 | 781 | ||
526 | spin_lock(&eint_lock); | 782 | spin_lock(&eint_lock); |
527 | mask = __raw_readl(S5P_EINT_MASK(EINT_REG_NR(data->irq))); | 783 | mask = __raw_readl(EINT_MASK(exynos_eint_base, data->irq)); |
528 | mask |= eint_irq_to_bit(data->irq); | 784 | mask |= EINT_OFFSET_BIT(data->irq); |
529 | __raw_writel(mask, S5P_EINT_MASK(EINT_REG_NR(data->irq))); | 785 | __raw_writel(mask, EINT_MASK(exynos_eint_base, data->irq)); |
530 | spin_unlock(&eint_lock); | 786 | spin_unlock(&eint_lock); |
531 | } | 787 | } |
532 | 788 | ||
533 | static void exynos4_irq_eint_unmask(struct irq_data *data) | 789 | static void exynos_irq_eint_unmask(struct irq_data *data) |
534 | { | 790 | { |
535 | u32 mask; | 791 | u32 mask; |
536 | 792 | ||
537 | spin_lock(&eint_lock); | 793 | spin_lock(&eint_lock); |
538 | mask = __raw_readl(S5P_EINT_MASK(EINT_REG_NR(data->irq))); | 794 | mask = __raw_readl(EINT_MASK(exynos_eint_base, data->irq)); |
539 | mask &= ~(eint_irq_to_bit(data->irq)); | 795 | mask &= ~(EINT_OFFSET_BIT(data->irq)); |
540 | __raw_writel(mask, S5P_EINT_MASK(EINT_REG_NR(data->irq))); | 796 | __raw_writel(mask, EINT_MASK(exynos_eint_base, data->irq)); |
541 | spin_unlock(&eint_lock); | 797 | spin_unlock(&eint_lock); |
542 | } | 798 | } |
543 | 799 | ||
544 | static inline void exynos4_irq_eint_ack(struct irq_data *data) | 800 | static inline void exynos_irq_eint_ack(struct irq_data *data) |
545 | { | 801 | { |
546 | __raw_writel(eint_irq_to_bit(data->irq), | 802 | __raw_writel(EINT_OFFSET_BIT(data->irq), |
547 | S5P_EINT_PEND(EINT_REG_NR(data->irq))); | 803 | EINT_PEND(exynos_eint_base, data->irq)); |
548 | } | 804 | } |
549 | 805 | ||
550 | static void exynos4_irq_eint_maskack(struct irq_data *data) | 806 | static void exynos_irq_eint_maskack(struct irq_data *data) |
551 | { | 807 | { |
552 | exynos4_irq_eint_mask(data); | 808 | exynos_irq_eint_mask(data); |
553 | exynos4_irq_eint_ack(data); | 809 | exynos_irq_eint_ack(data); |
554 | } | 810 | } |
555 | 811 | ||
556 | static int exynos4_irq_eint_set_type(struct irq_data *data, unsigned int type) | 812 | static int exynos_irq_eint_set_type(struct irq_data *data, unsigned int type) |
557 | { | 813 | { |
558 | int offs = EINT_OFFSET(data->irq); | 814 | int offs = EINT_OFFSET(data->irq); |
559 | int shift; | 815 | int shift; |
@@ -590,39 +846,27 @@ static int exynos4_irq_eint_set_type(struct irq_data *data, unsigned int type) | |||
590 | mask = 0x7 << shift; | 846 | mask = 0x7 << shift; |
591 | 847 | ||
592 | spin_lock(&eint_lock); | 848 | spin_lock(&eint_lock); |
593 | ctrl = __raw_readl(S5P_EINT_CON(EINT_REG_NR(data->irq))); | 849 | ctrl = __raw_readl(EINT_CON(exynos_eint_base, data->irq)); |
594 | ctrl &= ~mask; | 850 | ctrl &= ~mask; |
595 | ctrl |= newvalue << shift; | 851 | ctrl |= newvalue << shift; |
596 | __raw_writel(ctrl, S5P_EINT_CON(EINT_REG_NR(data->irq))); | 852 | __raw_writel(ctrl, EINT_CON(exynos_eint_base, data->irq)); |
597 | spin_unlock(&eint_lock); | 853 | spin_unlock(&eint_lock); |
598 | 854 | ||
599 | switch (offs) { | 855 | if (soc_is_exynos5250()) |
600 | case 0 ... 7: | 856 | s3c_gpio_cfgpin(exynos5_irq_to_gpio(data->irq), S3C_GPIO_SFN(0xf)); |
601 | s3c_gpio_cfgpin(EINT_GPIO_0(offs & 0x7), EINT_MODE); | 857 | else |
602 | break; | 858 | s3c_gpio_cfgpin(exynos4_irq_to_gpio(data->irq), S3C_GPIO_SFN(0xf)); |
603 | case 8 ... 15: | ||
604 | s3c_gpio_cfgpin(EINT_GPIO_1(offs & 0x7), EINT_MODE); | ||
605 | break; | ||
606 | case 16 ... 23: | ||
607 | s3c_gpio_cfgpin(EINT_GPIO_2(offs & 0x7), EINT_MODE); | ||
608 | break; | ||
609 | case 24 ... 31: | ||
610 | s3c_gpio_cfgpin(EINT_GPIO_3(offs & 0x7), EINT_MODE); | ||
611 | break; | ||
612 | default: | ||
613 | printk(KERN_ERR "No such irq number %d", offs); | ||
614 | } | ||
615 | 859 | ||
616 | return 0; | 860 | return 0; |
617 | } | 861 | } |
618 | 862 | ||
619 | static struct irq_chip exynos4_irq_eint = { | 863 | static struct irq_chip exynos_irq_eint = { |
620 | .name = "exynos4-eint", | 864 | .name = "exynos-eint", |
621 | .irq_mask = exynos4_irq_eint_mask, | 865 | .irq_mask = exynos_irq_eint_mask, |
622 | .irq_unmask = exynos4_irq_eint_unmask, | 866 | .irq_unmask = exynos_irq_eint_unmask, |
623 | .irq_mask_ack = exynos4_irq_eint_maskack, | 867 | .irq_mask_ack = exynos_irq_eint_maskack, |
624 | .irq_ack = exynos4_irq_eint_ack, | 868 | .irq_ack = exynos_irq_eint_ack, |
625 | .irq_set_type = exynos4_irq_eint_set_type, | 869 | .irq_set_type = exynos_irq_eint_set_type, |
626 | #ifdef CONFIG_PM | 870 | #ifdef CONFIG_PM |
627 | .irq_set_wake = s3c_irqext_wake, | 871 | .irq_set_wake = s3c_irqext_wake, |
628 | #endif | 872 | #endif |
@@ -637,12 +881,12 @@ static struct irq_chip exynos4_irq_eint = { | |||
637 | * | 881 | * |
638 | * Each EINT pend/mask registers handle eight of them. | 882 | * Each EINT pend/mask registers handle eight of them. |
639 | */ | 883 | */ |
640 | static inline void exynos4_irq_demux_eint(unsigned int start) | 884 | static inline void exynos_irq_demux_eint(unsigned int start) |
641 | { | 885 | { |
642 | unsigned int irq; | 886 | unsigned int irq; |
643 | 887 | ||
644 | u32 status = __raw_readl(S5P_EINT_PEND(EINT_REG_NR(start))); | 888 | u32 status = __raw_readl(EINT_PEND(exynos_eint_base, start)); |
645 | u32 mask = __raw_readl(S5P_EINT_MASK(EINT_REG_NR(start))); | 889 | u32 mask = __raw_readl(EINT_MASK(exynos_eint_base, start)); |
646 | 890 | ||
647 | status &= ~mask; | 891 | status &= ~mask; |
648 | status &= 0xff; | 892 | status &= 0xff; |
@@ -654,16 +898,16 @@ static inline void exynos4_irq_demux_eint(unsigned int start) | |||
654 | } | 898 | } |
655 | } | 899 | } |
656 | 900 | ||
657 | static void exynos4_irq_demux_eint16_31(unsigned int irq, struct irq_desc *desc) | 901 | static void exynos_irq_demux_eint16_31(unsigned int irq, struct irq_desc *desc) |
658 | { | 902 | { |
659 | struct irq_chip *chip = irq_get_chip(irq); | 903 | struct irq_chip *chip = irq_get_chip(irq); |
660 | chained_irq_enter(chip, desc); | 904 | chained_irq_enter(chip, desc); |
661 | exynos4_irq_demux_eint(IRQ_EINT(16)); | 905 | exynos_irq_demux_eint(IRQ_EINT(16)); |
662 | exynos4_irq_demux_eint(IRQ_EINT(24)); | 906 | exynos_irq_demux_eint(IRQ_EINT(24)); |
663 | chained_irq_exit(chip, desc); | 907 | chained_irq_exit(chip, desc); |
664 | } | 908 | } |
665 | 909 | ||
666 | static void exynos4_irq_eint0_15(unsigned int irq, struct irq_desc *desc) | 910 | static void exynos_irq_eint0_15(unsigned int irq, struct irq_desc *desc) |
667 | { | 911 | { |
668 | u32 *irq_data = irq_get_handler_data(irq); | 912 | u32 *irq_data = irq_get_handler_data(irq); |
669 | struct irq_chip *chip = irq_get_chip(irq); | 913 | struct irq_chip *chip = irq_get_chip(irq); |
@@ -680,27 +924,44 @@ static void exynos4_irq_eint0_15(unsigned int irq, struct irq_desc *desc) | |||
680 | chained_irq_exit(chip, desc); | 924 | chained_irq_exit(chip, desc); |
681 | } | 925 | } |
682 | 926 | ||
683 | static int __init exynos4_init_irq_eint(void) | 927 | static int __init exynos_init_irq_eint(void) |
684 | { | 928 | { |
685 | int irq; | 929 | int irq; |
686 | 930 | ||
931 | if (soc_is_exynos5250()) | ||
932 | exynos_eint_base = ioremap(EXYNOS5_PA_GPIO1, SZ_4K); | ||
933 | else | ||
934 | exynos_eint_base = ioremap(EXYNOS4_PA_GPIO2, SZ_4K); | ||
935 | |||
936 | if (exynos_eint_base == NULL) { | ||
937 | pr_err("unable to ioremap for EINT base address\n"); | ||
938 | return -ENOMEM; | ||
939 | } | ||
940 | |||
687 | for (irq = 0 ; irq <= 31 ; irq++) { | 941 | for (irq = 0 ; irq <= 31 ; irq++) { |
688 | irq_set_chip_and_handler(IRQ_EINT(irq), &exynos4_irq_eint, | 942 | irq_set_chip_and_handler(IRQ_EINT(irq), &exynos_irq_eint, |
689 | handle_level_irq); | 943 | handle_level_irq); |
690 | set_irq_flags(IRQ_EINT(irq), IRQF_VALID); | 944 | set_irq_flags(IRQ_EINT(irq), IRQF_VALID); |
691 | } | 945 | } |
692 | 946 | ||
693 | irq_set_chained_handler(IRQ_EINT16_31, exynos4_irq_demux_eint16_31); | 947 | irq_set_chained_handler(EXYNOS_IRQ_EINT16_31, exynos_irq_demux_eint16_31); |
694 | 948 | ||
695 | for (irq = 0 ; irq <= 15 ; irq++) { | 949 | for (irq = 0 ; irq <= 15 ; irq++) { |
696 | eint0_15_data[irq] = IRQ_EINT(irq); | 950 | eint0_15_data[irq] = IRQ_EINT(irq); |
697 | 951 | ||
698 | irq_set_handler_data(exynos4_get_irq_nr(irq), | 952 | if (soc_is_exynos5250()) { |
699 | &eint0_15_data[irq]); | 953 | irq_set_handler_data(exynos5_eint0_15_src_int[irq], |
700 | irq_set_chained_handler(exynos4_get_irq_nr(irq), | 954 | &eint0_15_data[irq]); |
701 | exynos4_irq_eint0_15); | 955 | irq_set_chained_handler(exynos5_eint0_15_src_int[irq], |
956 | exynos_irq_eint0_15); | ||
957 | } else { | ||
958 | irq_set_handler_data(exynos4_eint0_15_src_int[irq], | ||
959 | &eint0_15_data[irq]); | ||
960 | irq_set_chained_handler(exynos4_eint0_15_src_int[irq], | ||
961 | exynos_irq_eint0_15); | ||
962 | } | ||
702 | } | 963 | } |
703 | 964 | ||
704 | return 0; | 965 | return 0; |
705 | } | 966 | } |
706 | arch_initcall(exynos4_init_irq_eint); | 967 | arch_initcall(exynos_init_irq_eint); |