From c9ce7dbdbf25d7245ead1923c11620d4c8013592 Mon Sep 17 00:00:00 2001 From: Changhwan Youn Date: Tue, 24 Apr 2012 14:31:11 -0700 Subject: ARM: EXYNOS: Modify the GIC physical address for static io-mapping Adapt to changes in GIC physical address in rev1 of EXYNOS5. Signed-off-by: Changhwan Youn Signed-off-by: Thomas Abraham Signed-off-by: Kukjin Kim --- arch/arm/mach-exynos/common.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'arch/arm/mach-exynos/common.c') diff --git a/arch/arm/mach-exynos/common.c b/arch/arm/mach-exynos/common.c index 5ccd6e8..eff4446 100644 --- a/arch/arm/mach-exynos/common.c +++ b/arch/arm/mach-exynos/common.c @@ -265,12 +265,12 @@ static struct map_desc exynos5_iodesc[] __initdata = { }, { .virtual = (unsigned long)S5P_VA_GIC_CPU, .pfn = __phys_to_pfn(EXYNOS5_PA_GIC_CPU), - .length = SZ_64K, + .length = SZ_8K, .type = MT_DEVICE, }, { .virtual = (unsigned long)S5P_VA_GIC_DIST, .pfn = __phys_to_pfn(EXYNOS5_PA_GIC_DIST), - .length = SZ_64K, + .length = SZ_4K, .type = MT_DEVICE, }, }; -- cgit v1.1 From 9ee6af9c3fad48cddc0684d0c77d3ea1329e10a1 Mon Sep 17 00:00:00 2001 From: Thomas Abraham Date: Tue, 15 May 2012 15:47:40 +0900 Subject: ARM: EXYNOS: Remove a new bus_type instance for EXYNOS5 A seperate bus_type instance is not required for EXYNOS5. The existing bus_type instance used with EXYNOS4 is sufficient for both EXYNOS4 and EXYNOS5. This also solves issue of uninitialized usage of exynos4_subsys in EXYNOS4 power management code that is reused for EXYNOS5 also. In addition to that, the existing exynos4_subsys bus_type is renamed to exynos_subsys to indicate that it is reused on both EXYNOS4 and EXYNOS5 platforms. Signed-off-by: Thomas Abraham Signed-off-by: Kukjin Kim --- arch/arm/mach-exynos/common.c | 27 ++++++--------------------- 1 file changed, 6 insertions(+), 21 deletions(-) (limited to 'arch/arm/mach-exynos/common.c') diff --git a/arch/arm/mach-exynos/common.c b/arch/arm/mach-exynos/common.c index eff4446..3302a8d 100644 --- a/arch/arm/mach-exynos/common.c +++ b/arch/arm/mach-exynos/common.c @@ -565,30 +565,18 @@ void __init exynos5_init_irq(void) s5p_init_irq(NULL, 0); } -struct bus_type exynos4_subsys = { - .name = "exynos4-core", - .dev_name = "exynos4-core", -}; - -struct bus_type exynos5_subsys = { - .name = "exynos5-core", - .dev_name = "exynos5-core", +struct bus_type exynos_subsys = { + .name = "exynos-core", + .dev_name = "exynos-core", }; static struct device exynos4_dev = { - .bus = &exynos4_subsys, -}; - -static struct device exynos5_dev = { - .bus = &exynos5_subsys, + .bus = &exynos_subsys, }; static int __init exynos_core_init(void) { - if (soc_is_exynos5250()) - return subsys_system_register(&exynos5_subsys, NULL); - else - return subsys_system_register(&exynos4_subsys, NULL); + return subsys_system_register(&exynos_subsys, NULL); } core_initcall(exynos_core_init); @@ -675,10 +663,7 @@ static int __init exynos_init(void) { printk(KERN_INFO "EXYNOS: Initializing architecture\n"); - if (soc_is_exynos5250()) - return device_register(&exynos5_dev); - else - return device_register(&exynos4_dev); + return device_register(&exynos4_dev); } /* uart registration process */ -- cgit v1.1 From 1e60bc0b5f488c8acde22adeb62118ccfdb49062 Mon Sep 17 00:00:00 2001 From: Thomas Abraham Date: Tue, 15 May 2012 16:18:35 +0900 Subject: ARM: EXYNOS: Add irq_domain support for interrupt combiner Add irq_domain support for hardware interrupts of the interrupt combiner. The hardware interrupts of all the instances of the combiner are grouped in a single irq_domain. Cc: Grant Likely Signed-off-by: Thomas Abraham Acked-by: Rob Herring Signed-off-by: Kukjin Kim --- arch/arm/mach-exynos/common.c | 88 ++++++++++++++++++++++++------------------- 1 file changed, 50 insertions(+), 38 deletions(-) (limited to 'arch/arm/mach-exynos/common.c') diff --git a/arch/arm/mach-exynos/common.c b/arch/arm/mach-exynos/common.c index 3302a8d..a688c17 100644 --- a/arch/arm/mach-exynos/common.c +++ b/arch/arm/mach-exynos/common.c @@ -19,6 +19,8 @@ #include #include #include +#include +#include #include #include @@ -399,6 +401,7 @@ struct combiner_chip_data { void __iomem *base; }; +static struct irq_domain *combiner_irq_domain; static struct combiner_chip_data combiner_data[MAX_COMBINER_NR]; static inline void __iomem *combiner_base(struct irq_data *data) @@ -411,14 +414,14 @@ static inline void __iomem *combiner_base(struct irq_data *data) static void combiner_mask_irq(struct irq_data *data) { - u32 mask = 1 << (data->irq % 32); + u32 mask = 1 << (data->hwirq % 32); __raw_writel(mask, combiner_base(data) + COMBINER_ENABLE_CLEAR); } static void combiner_unmask_irq(struct irq_data *data) { - u32 mask = 1 << (data->irq % 32); + u32 mask = 1 << (data->hwirq % 32); __raw_writel(mask, combiner_base(data) + COMBINER_ENABLE_SET); } @@ -474,36 +477,58 @@ static void __init combiner_cascade_irq(unsigned int combiner_nr, unsigned int i irq_set_chained_handler(irq, combiner_handle_cascade_irq); } -static void __init combiner_init(unsigned int combiner_nr, void __iomem *base, - unsigned int irq_start) +static void __init combiner_init_one(unsigned int combiner_nr, + void __iomem *base) { - unsigned int i; - unsigned int max_nr; - - if (soc_is_exynos5250()) - max_nr = EXYNOS5_MAX_COMBINER_NR; - else - max_nr = EXYNOS4_MAX_COMBINER_NR; - - if (combiner_nr >= max_nr) - BUG(); - combiner_data[combiner_nr].base = base; - combiner_data[combiner_nr].irq_offset = irq_start; + combiner_data[combiner_nr].irq_offset = irq_find_mapping( + combiner_irq_domain, combiner_nr * MAX_IRQ_IN_COMBINER); combiner_data[combiner_nr].irq_mask = 0xff << ((combiner_nr % 4) << 3); /* Disable all interrupts */ - __raw_writel(combiner_data[combiner_nr].irq_mask, base + COMBINER_ENABLE_CLEAR); +} + +static int combiner_irq_domain_map(struct irq_domain *d, unsigned int irq, + irq_hw_number_t hw) +{ + irq_set_chip_and_handler(irq, &combiner_chip, handle_level_irq); + irq_set_chip_data(irq, &combiner_data[hw >> 3]); + set_irq_flags(irq, IRQF_VALID | IRQF_PROBE); + + return 0; +} + +static struct irq_domain_ops combiner_irq_domain_ops = { + .map = combiner_irq_domain_map, +}; + +void __init combiner_init(void __iomem *combiner_base, struct device_node *np) +{ + int i, irq_base; + unsigned int max_nr, nr_irq; + + max_nr = soc_is_exynos5250() ? EXYNOS5_MAX_COMBINER_NR : + EXYNOS4_MAX_COMBINER_NR; + nr_irq = max_nr * MAX_IRQ_IN_COMBINER; + + irq_base = irq_alloc_descs(COMBINER_IRQ(0, 0), 1, nr_irq, 0); + if (IS_ERR_VALUE(irq_base)) { + irq_base = COMBINER_IRQ(0, 0); + pr_warning("%s: irq desc alloc failed. Continuing with %d as linux irq base\n", __func__, irq_base); + } - /* Setup the Linux IRQ subsystem */ + combiner_irq_domain = irq_domain_add_legacy(np, nr_irq, irq_base, 0, + &combiner_irq_domain_ops, &combiner_data); + if (WARN_ON(!combiner_irq_domain)) { + pr_warning("%s: irq domain init failed\n", __func__); + return; + } - for (i = irq_start; i < combiner_data[combiner_nr].irq_offset - + MAX_IRQ_IN_COMBINER; i++) { - irq_set_chip_and_handler(i, &combiner_chip, handle_level_irq); - irq_set_chip_data(i, &combiner_data[combiner_nr]); - set_irq_flags(i, IRQF_VALID | IRQF_PROBE); + for (i = 0; i < max_nr; i++) { + combiner_init_one(i, combiner_base + (i >> 2) * 0x10); + combiner_cascade_irq(i, IRQ_SPI(i)); } } @@ -516,7 +541,6 @@ static const struct of_device_id exynos4_dt_irq_match[] = { void __init exynos4_init_irq(void) { - int irq; unsigned int gic_bank_offset; gic_bank_offset = soc_is_exynos4412() ? 0x4000 : 0x8000; @@ -528,12 +552,7 @@ void __init exynos4_init_irq(void) of_irq_init(exynos4_dt_irq_match); #endif - for (irq = 0; irq < EXYNOS4_MAX_COMBINER_NR; irq++) { - - combiner_init(irq, (void __iomem *)S5P_VA_COMBINER(irq), - COMBINER_IRQ(irq, 0)); - combiner_cascade_irq(irq, IRQ_SPI(irq)); - } + combiner_init(S5P_VA_COMBINER_BASE, NULL); /* * The parameters of s5p_init_irq() are for VIC init. @@ -545,17 +564,10 @@ void __init exynos4_init_irq(void) void __init exynos5_init_irq(void) { - int irq; - #ifdef CONFIG_OF of_irq_init(exynos4_dt_irq_match); #endif - - for (irq = 0; irq < EXYNOS5_MAX_COMBINER_NR; irq++) { - combiner_init(irq, (void __iomem *)S5P_VA_COMBINER(irq), - COMBINER_IRQ(irq, 0)); - combiner_cascade_irq(irq, IRQ_SPI(irq)); - } + combiner_init(S5P_VA_COMBINER_BASE, NULL); /* * The parameters of s5p_init_irq() are for VIC init. -- cgit v1.1 From e873a47c4ef3fbb2e439a6b674e73b0c40dd8248 Mon Sep 17 00:00:00 2001 From: Thomas Abraham Date: Tue, 15 May 2012 16:25:23 +0900 Subject: ARM: EXYNOS: Add device tree support for interrupt combiner Add device tree based instantiation of the interrupt combiner controller. Signed-off-by: Thomas Abraham Acked-by: Rob Herring Acked-by: Grant Likely Signed-off-by: Kukjin Kim --- arch/arm/mach-exynos/common.c | 71 ++++++++++++++++++++++++++++++++++++++----- 1 file changed, 64 insertions(+), 7 deletions(-) (limited to 'arch/arm/mach-exynos/common.c') diff --git a/arch/arm/mach-exynos/common.c b/arch/arm/mach-exynos/common.c index a688c17..9900158 100644 --- a/arch/arm/mach-exynos/common.c +++ b/arch/arm/mach-exynos/common.c @@ -21,6 +21,7 @@ #include #include #include +#include #include #include @@ -490,6 +491,35 @@ static void __init combiner_init_one(unsigned int combiner_nr, base + COMBINER_ENABLE_CLEAR); } +#ifdef CONFIG_OF +static int combiner_irq_domain_xlate(struct irq_domain *d, + struct device_node *controller, + const u32 *intspec, unsigned int intsize, + unsigned long *out_hwirq, + unsigned int *out_type) +{ + if (d->of_node != controller) + return -EINVAL; + + if (intsize < 2) + return -EINVAL; + + *out_hwirq = intspec[0] * MAX_IRQ_IN_COMBINER + intspec[1]; + *out_type = 0; + + return 0; +} +#else +static int combiner_irq_domain_xlate(struct irq_domain *d, + struct device_node *controller, + const u32 *intspec, unsigned int intsize, + unsigned long *out_hwirq, + unsigned int *out_type) +{ + return -EINVAL; +} +#endif + static int combiner_irq_domain_map(struct irq_domain *d, unsigned int irq, irq_hw_number_t hw) { @@ -501,16 +531,26 @@ static int combiner_irq_domain_map(struct irq_domain *d, unsigned int irq, } static struct irq_domain_ops combiner_irq_domain_ops = { + .xlate = combiner_irq_domain_xlate, .map = combiner_irq_domain_map, }; void __init combiner_init(void __iomem *combiner_base, struct device_node *np) { - int i, irq_base; + int i, irq, irq_base; unsigned int max_nr, nr_irq; - max_nr = soc_is_exynos5250() ? EXYNOS5_MAX_COMBINER_NR : - EXYNOS4_MAX_COMBINER_NR; + if (np) { + if (of_property_read_u32(np, "samsung,combiner-nr", &max_nr)) { + pr_warning("%s: number of combiners not specified, " + "setting default as %d.\n", + __func__, EXYNOS4_MAX_COMBINER_NR); + max_nr = EXYNOS4_MAX_COMBINER_NR; + } + } else { + max_nr = soc_is_exynos5250() ? EXYNOS5_MAX_COMBINER_NR : + EXYNOS4_MAX_COMBINER_NR; + } nr_irq = max_nr * MAX_IRQ_IN_COMBINER; irq_base = irq_alloc_descs(COMBINER_IRQ(0, 0), 1, nr_irq, 0); @@ -528,13 +568,31 @@ void __init combiner_init(void __iomem *combiner_base, struct device_node *np) for (i = 0; i < max_nr; i++) { combiner_init_one(i, combiner_base + (i >> 2) * 0x10); - combiner_cascade_irq(i, IRQ_SPI(i)); + irq = np ? irq_of_parse_and_map(np, i) : IRQ_SPI(i); + combiner_cascade_irq(i, irq); } } #ifdef CONFIG_OF +int __init combiner_of_init(struct device_node *np, struct device_node *parent) +{ + void __iomem *combiner_base; + + combiner_base = of_iomap(np, 0); + if (!combiner_base) { + pr_err("%s: failed to map combiner registers\n", __func__); + return -ENXIO; + } + + combiner_init(combiner_base, np); + + return 0; +} + static const struct of_device_id exynos4_dt_irq_match[] = { { .compatible = "arm,cortex-a9-gic", .data = gic_of_init, }, + { .compatible = "samsung,exynos4210-combiner", + .data = combiner_of_init, }, {}, }; #endif @@ -552,7 +610,8 @@ void __init exynos4_init_irq(void) of_irq_init(exynos4_dt_irq_match); #endif - combiner_init(S5P_VA_COMBINER_BASE, NULL); + if (!of_have_populated_dt()) + combiner_init(S5P_VA_COMBINER_BASE, NULL); /* * The parameters of s5p_init_irq() are for VIC init. @@ -567,8 +626,6 @@ void __init exynos5_init_irq(void) #ifdef CONFIG_OF of_irq_init(exynos4_dt_irq_match); #endif - combiner_init(S5P_VA_COMBINER_BASE, NULL); - /* * The parameters of s5p_init_irq() are for VIC init. * Theses parameters should be NULL and 0 because EXYNOS4 -- cgit v1.1