aboutsummaryrefslogtreecommitdiffstats
path: root/arch/arm/mach-exynos/common.c
diff options
context:
space:
mode:
Diffstat (limited to 'arch/arm/mach-exynos/common.c')
-rw-r--r--arch/arm/mach-exynos/common.c187
1 files changed, 125 insertions, 62 deletions
diff --git a/arch/arm/mach-exynos/common.c b/arch/arm/mach-exynos/common.c
index 5ccd6e80a607..742edd3bbec3 100644
--- a/arch/arm/mach-exynos/common.c
+++ b/arch/arm/mach-exynos/common.c
@@ -19,6 +19,9 @@
19#include <linux/serial_core.h> 19#include <linux/serial_core.h>
20#include <linux/of.h> 20#include <linux/of.h>
21#include <linux/of_irq.h> 21#include <linux/of_irq.h>
22#include <linux/export.h>
23#include <linux/irqdomain.h>
24#include <linux/of_address.h>
22 25
23#include <asm/proc-fns.h> 26#include <asm/proc-fns.h>
24#include <asm/exception.h> 27#include <asm/exception.h>
@@ -265,12 +268,12 @@ static struct map_desc exynos5_iodesc[] __initdata = {
265 }, { 268 }, {
266 .virtual = (unsigned long)S5P_VA_GIC_CPU, 269 .virtual = (unsigned long)S5P_VA_GIC_CPU,
267 .pfn = __phys_to_pfn(EXYNOS5_PA_GIC_CPU), 270 .pfn = __phys_to_pfn(EXYNOS5_PA_GIC_CPU),
268 .length = SZ_64K, 271 .length = SZ_8K,
269 .type = MT_DEVICE, 272 .type = MT_DEVICE,
270 }, { 273 }, {
271 .virtual = (unsigned long)S5P_VA_GIC_DIST, 274 .virtual = (unsigned long)S5P_VA_GIC_DIST,
272 .pfn = __phys_to_pfn(EXYNOS5_PA_GIC_DIST), 275 .pfn = __phys_to_pfn(EXYNOS5_PA_GIC_DIST),
273 .length = SZ_64K, 276 .length = SZ_4K,
274 .type = MT_DEVICE, 277 .type = MT_DEVICE,
275 }, 278 },
276}; 279};
@@ -285,6 +288,11 @@ void exynos5_restart(char mode, const char *cmd)
285 __raw_writel(0x1, EXYNOS_SWRESET); 288 __raw_writel(0x1, EXYNOS_SWRESET);
286} 289}
287 290
291void __init exynos_init_late(void)
292{
293 exynos_pm_late_initcall();
294}
295
288/* 296/*
289 * exynos_map_io 297 * exynos_map_io
290 * 298 *
@@ -399,6 +407,7 @@ struct combiner_chip_data {
399 void __iomem *base; 407 void __iomem *base;
400}; 408};
401 409
410static struct irq_domain *combiner_irq_domain;
402static struct combiner_chip_data combiner_data[MAX_COMBINER_NR]; 411static struct combiner_chip_data combiner_data[MAX_COMBINER_NR];
403 412
404static inline void __iomem *combiner_base(struct irq_data *data) 413static inline void __iomem *combiner_base(struct irq_data *data)
@@ -411,14 +420,14 @@ static inline void __iomem *combiner_base(struct irq_data *data)
411 420
412static void combiner_mask_irq(struct irq_data *data) 421static void combiner_mask_irq(struct irq_data *data)
413{ 422{
414 u32 mask = 1 << (data->irq % 32); 423 u32 mask = 1 << (data->hwirq % 32);
415 424
416 __raw_writel(mask, combiner_base(data) + COMBINER_ENABLE_CLEAR); 425 __raw_writel(mask, combiner_base(data) + COMBINER_ENABLE_CLEAR);
417} 426}
418 427
419static void combiner_unmask_irq(struct irq_data *data) 428static void combiner_unmask_irq(struct irq_data *data)
420{ 429{
421 u32 mask = 1 << (data->irq % 32); 430 u32 mask = 1 << (data->hwirq % 32);
422 431
423 __raw_writel(mask, combiner_base(data) + COMBINER_ENABLE_SET); 432 __raw_writel(mask, combiner_base(data) + COMBINER_ENABLE_SET);
424} 433}
@@ -474,49 +483,131 @@ static void __init combiner_cascade_irq(unsigned int combiner_nr, unsigned int i
474 irq_set_chained_handler(irq, combiner_handle_cascade_irq); 483 irq_set_chained_handler(irq, combiner_handle_cascade_irq);
475} 484}
476 485
477static void __init combiner_init(unsigned int combiner_nr, void __iomem *base, 486static void __init combiner_init_one(unsigned int combiner_nr,
478 unsigned int irq_start) 487 void __iomem *base)
479{ 488{
480 unsigned int i;
481 unsigned int max_nr;
482
483 if (soc_is_exynos5250())
484 max_nr = EXYNOS5_MAX_COMBINER_NR;
485 else
486 max_nr = EXYNOS4_MAX_COMBINER_NR;
487
488 if (combiner_nr >= max_nr)
489 BUG();
490
491 combiner_data[combiner_nr].base = base; 489 combiner_data[combiner_nr].base = base;
492 combiner_data[combiner_nr].irq_offset = irq_start; 490 combiner_data[combiner_nr].irq_offset = irq_find_mapping(
491 combiner_irq_domain, combiner_nr * MAX_IRQ_IN_COMBINER);
493 combiner_data[combiner_nr].irq_mask = 0xff << ((combiner_nr % 4) << 3); 492 combiner_data[combiner_nr].irq_mask = 0xff << ((combiner_nr % 4) << 3);
494 493
495 /* Disable all interrupts */ 494 /* Disable all interrupts */
496
497 __raw_writel(combiner_data[combiner_nr].irq_mask, 495 __raw_writel(combiner_data[combiner_nr].irq_mask,
498 base + COMBINER_ENABLE_CLEAR); 496 base + COMBINER_ENABLE_CLEAR);
497}
498
499#ifdef CONFIG_OF
500static int combiner_irq_domain_xlate(struct irq_domain *d,
501 struct device_node *controller,
502 const u32 *intspec, unsigned int intsize,
503 unsigned long *out_hwirq,
504 unsigned int *out_type)
505{
506 if (d->of_node != controller)
507 return -EINVAL;
508
509 if (intsize < 2)
510 return -EINVAL;
511
512 *out_hwirq = intspec[0] * MAX_IRQ_IN_COMBINER + intspec[1];
513 *out_type = 0;
514
515 return 0;
516}
517#else
518static int combiner_irq_domain_xlate(struct irq_domain *d,
519 struct device_node *controller,
520 const u32 *intspec, unsigned int intsize,
521 unsigned long *out_hwirq,
522 unsigned int *out_type)
523{
524 return -EINVAL;
525}
526#endif
527
528static int combiner_irq_domain_map(struct irq_domain *d, unsigned int irq,
529 irq_hw_number_t hw)
530{
531 irq_set_chip_and_handler(irq, &combiner_chip, handle_level_irq);
532 irq_set_chip_data(irq, &combiner_data[hw >> 3]);
533 set_irq_flags(irq, IRQF_VALID | IRQF_PROBE);
534
535 return 0;
536}
537
538static struct irq_domain_ops combiner_irq_domain_ops = {
539 .xlate = combiner_irq_domain_xlate,
540 .map = combiner_irq_domain_map,
541};
542
543void __init combiner_init(void __iomem *combiner_base, struct device_node *np)
544{
545 int i, irq, irq_base;
546 unsigned int max_nr, nr_irq;
547
548 if (np) {
549 if (of_property_read_u32(np, "samsung,combiner-nr", &max_nr)) {
550 pr_warning("%s: number of combiners not specified, "
551 "setting default as %d.\n",
552 __func__, EXYNOS4_MAX_COMBINER_NR);
553 max_nr = EXYNOS4_MAX_COMBINER_NR;
554 }
555 } else {
556 max_nr = soc_is_exynos5250() ? EXYNOS5_MAX_COMBINER_NR :
557 EXYNOS4_MAX_COMBINER_NR;
558 }
559 nr_irq = max_nr * MAX_IRQ_IN_COMBINER;
499 560
500 /* Setup the Linux IRQ subsystem */ 561 irq_base = irq_alloc_descs(COMBINER_IRQ(0, 0), 1, nr_irq, 0);
562 if (IS_ERR_VALUE(irq_base)) {
563 irq_base = COMBINER_IRQ(0, 0);
564 pr_warning("%s: irq desc alloc failed. Continuing with %d as linux irq base\n", __func__, irq_base);
565 }
501 566
502 for (i = irq_start; i < combiner_data[combiner_nr].irq_offset 567 combiner_irq_domain = irq_domain_add_legacy(np, nr_irq, irq_base, 0,
503 + MAX_IRQ_IN_COMBINER; i++) { 568 &combiner_irq_domain_ops, &combiner_data);
504 irq_set_chip_and_handler(i, &combiner_chip, handle_level_irq); 569 if (WARN_ON(!combiner_irq_domain)) {
505 irq_set_chip_data(i, &combiner_data[combiner_nr]); 570 pr_warning("%s: irq domain init failed\n", __func__);
506 set_irq_flags(i, IRQF_VALID | IRQF_PROBE); 571 return;
572 }
573
574 for (i = 0; i < max_nr; i++) {
575 combiner_init_one(i, combiner_base + (i >> 2) * 0x10);
576 irq = IRQ_SPI(i);
577#ifdef CONFIG_OF
578 if (np)
579 irq = irq_of_parse_and_map(np, i);
580#endif
581 combiner_cascade_irq(i, irq);
507 } 582 }
508} 583}
509 584
510#ifdef CONFIG_OF 585#ifdef CONFIG_OF
586int __init combiner_of_init(struct device_node *np, struct device_node *parent)
587{
588 void __iomem *combiner_base;
589
590 combiner_base = of_iomap(np, 0);
591 if (!combiner_base) {
592 pr_err("%s: failed to map combiner registers\n", __func__);
593 return -ENXIO;
594 }
595
596 combiner_init(combiner_base, np);
597
598 return 0;
599}
600
511static const struct of_device_id exynos4_dt_irq_match[] = { 601static const struct of_device_id exynos4_dt_irq_match[] = {
512 { .compatible = "arm,cortex-a9-gic", .data = gic_of_init, }, 602 { .compatible = "arm,cortex-a9-gic", .data = gic_of_init, },
603 { .compatible = "samsung,exynos4210-combiner",
604 .data = combiner_of_init, },
513 {}, 605 {},
514}; 606};
515#endif 607#endif
516 608
517void __init exynos4_init_irq(void) 609void __init exynos4_init_irq(void)
518{ 610{
519 int irq;
520 unsigned int gic_bank_offset; 611 unsigned int gic_bank_offset;
521 612
522 gic_bank_offset = soc_is_exynos4412() ? 0x4000 : 0x8000; 613 gic_bank_offset = soc_is_exynos4412() ? 0x4000 : 0x8000;
@@ -528,12 +619,8 @@ void __init exynos4_init_irq(void)
528 of_irq_init(exynos4_dt_irq_match); 619 of_irq_init(exynos4_dt_irq_match);
529#endif 620#endif
530 621
531 for (irq = 0; irq < EXYNOS4_MAX_COMBINER_NR; irq++) { 622 if (!of_have_populated_dt())
532 623 combiner_init(S5P_VA_COMBINER_BASE, NULL);
533 combiner_init(irq, (void __iomem *)S5P_VA_COMBINER(irq),
534 COMBINER_IRQ(irq, 0));
535 combiner_cascade_irq(irq, IRQ_SPI(irq));
536 }
537 624
538 /* 625 /*
539 * The parameters of s5p_init_irq() are for VIC init. 626 * The parameters of s5p_init_irq() are for VIC init.
@@ -545,18 +632,9 @@ void __init exynos4_init_irq(void)
545 632
546void __init exynos5_init_irq(void) 633void __init exynos5_init_irq(void)
547{ 634{
548 int irq;
549
550#ifdef CONFIG_OF 635#ifdef CONFIG_OF
551 of_irq_init(exynos4_dt_irq_match); 636 of_irq_init(exynos4_dt_irq_match);
552#endif 637#endif
553
554 for (irq = 0; irq < EXYNOS5_MAX_COMBINER_NR; irq++) {
555 combiner_init(irq, (void __iomem *)S5P_VA_COMBINER(irq),
556 COMBINER_IRQ(irq, 0));
557 combiner_cascade_irq(irq, IRQ_SPI(irq));
558 }
559
560 /* 638 /*
561 * The parameters of s5p_init_irq() are for VIC init. 639 * The parameters of s5p_init_irq() are for VIC init.
562 * Theses parameters should be NULL and 0 because EXYNOS4 640 * Theses parameters should be NULL and 0 because EXYNOS4
@@ -565,30 +643,18 @@ void __init exynos5_init_irq(void)
565 s5p_init_irq(NULL, 0); 643 s5p_init_irq(NULL, 0);
566} 644}
567 645
568struct bus_type exynos4_subsys = { 646struct bus_type exynos_subsys = {
569 .name = "exynos4-core", 647 .name = "exynos-core",
570 .dev_name = "exynos4-core", 648 .dev_name = "exynos-core",
571};
572
573struct bus_type exynos5_subsys = {
574 .name = "exynos5-core",
575 .dev_name = "exynos5-core",
576}; 649};
577 650
578static struct device exynos4_dev = { 651static struct device exynos4_dev = {
579 .bus = &exynos4_subsys, 652 .bus = &exynos_subsys,
580};
581
582static struct device exynos5_dev = {
583 .bus = &exynos5_subsys,
584}; 653};
585 654
586static int __init exynos_core_init(void) 655static int __init exynos_core_init(void)
587{ 656{
588 if (soc_is_exynos5250()) 657 return subsys_system_register(&exynos_subsys, NULL);
589 return subsys_system_register(&exynos5_subsys, NULL);
590 else
591 return subsys_system_register(&exynos4_subsys, NULL);
592} 658}
593core_initcall(exynos_core_init); 659core_initcall(exynos_core_init);
594 660
@@ -675,10 +741,7 @@ static int __init exynos_init(void)
675{ 741{
676 printk(KERN_INFO "EXYNOS: Initializing architecture\n"); 742 printk(KERN_INFO "EXYNOS: Initializing architecture\n");
677 743
678 if (soc_is_exynos5250()) 744 return device_register(&exynos4_dev);
679 return device_register(&exynos5_dev);
680 else
681 return device_register(&exynos4_dev);
682} 745}
683 746
684/* uart registration process */ 747/* uart registration process */