This patch set trys to convert GIC to ACPI which based on patches from Amit, I rework two patches from him and fix two minor bugs :)
In MADT table, there are GIC cpu interface base address and GIC distributor base address, use them to convert GIC to ACPI.
GIC should be converted after all the devices refer to GIC are converted. So I hack some code to test this patch set.
Amit Daniel Kachhap (2): irqdomain: Add a new API irq_create_acpi_mapping ACPI: ARM: Update acpi_register_gsi to register with the core IRQ subsystem
Hanjun Guo (3): irqchip / GIC: do not set default host for GIC domain multi-times when ACPI enabled ARM / GIC: convert GIC to ACPI using the information in MADT ACPI / timer: hack to test GIC in ACPI mode
arch/arm64/kernel/irq.c | 4 ++ drivers/acpi/plat/arm/boot.c | 100 +++++++++++++++++++++++++++++----- drivers/clocksource/arm_arch_timer.c | 11 +++- drivers/irqchip/irq-gic.c | 9 ++- include/linux/acpi.h | 3 + kernel/irq/irqdomain.c | 27 +++++++++ 6 files changed, 133 insertions(+), 21 deletions(-)
If there are multi-GICs in the system, default host for GIC domain will be set for several times, fix it.
Signed-off-by: Hanjun Guo hanjun.guo@linaro.org --- drivers/irqchip/irq-gic.c | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-)
diff --git a/drivers/irqchip/irq-gic.c b/drivers/irqchip/irq-gic.c index 039b4a0..b158c6f 100644 --- a/drivers/irqchip/irq-gic.c +++ b/drivers/irqchip/irq-gic.c @@ -958,7 +958,10 @@ void __init gic_init_bases(unsigned int gic_nr, int irq_start, return;
#ifdef CONFIG_ACPI - irq_set_default_host(gic->domain); + /* do not set default host for GIC domain multi-times. + * TODO: we should consider more when multi GICs supported */ + if (!gic_nr) + irq_set_default_host(gic->domain); #endif
#ifdef CONFIG_SMP
From: Amit Daniel Kachhap amit.daniel@samsung.com
This patch introduces a new API for acpi based irq mapping, which is based on the patch posted by Amit, but I delete the reference to gic_irq_domain_xlate() which can simplify the code a lot.
Signed-off-by: Amit Daniel Kachhap amit.daniel@samsung.com Signed-off-by: Hanjun Guo hanjun.guo@linaro.org --- include/linux/acpi.h | 2 ++ kernel/irq/irqdomain.c | 27 +++++++++++++++++++++++++++ 2 files changed, 29 insertions(+)
diff --git a/include/linux/acpi.h b/include/linux/acpi.h index 6324f8b..1dbfa2c 100644 --- a/include/linux/acpi.h +++ b/include/linux/acpi.h @@ -121,6 +121,8 @@ int acpi_map_lsapic(acpi_handle handle, int *pcpu); int acpi_unmap_lsapic(int cpu); #endif /* CONFIG_ACPI_HOTPLUG_CPU */
+unsigned int irq_create_acpi_mapping(irq_hw_number_t hwirq, + unsigned int type); int acpi_register_ioapic(acpi_handle handle, u64 phys_addr, u32 gsi_base); int acpi_unregister_ioapic(acpi_handle handle, u32 gsi_base); void acpi_irq_stats_init(void); diff --git a/kernel/irq/irqdomain.c b/kernel/irq/irqdomain.c index 706724e..1d791ff 100644 --- a/kernel/irq/irqdomain.c +++ b/kernel/irq/irqdomain.c @@ -502,6 +502,33 @@ unsigned int irq_create_of_mapping(struct device_node *controller, } EXPORT_SYMBOL_GPL(irq_create_of_mapping);
+#ifdef CONFIG_ACPI +unsigned int irq_create_acpi_mapping(irq_hw_number_t hwirq, + unsigned int type) +{ + struct irq_domain *domain; + unsigned int virq; + + domain = irq_default_domain; + if (!domain) { + pr_warn("no irq domain found !\n"); + return 0; + } + + /* Create mapping */ + virq = irq_create_mapping(domain, hwirq); + if (!virq) + return virq; + + /* Set type if specified and different than the current one */ + if (type != IRQ_TYPE_NONE && + type != irq_get_trigger_type(virq)) + irq_set_irq_type(virq, type); + return virq; +} +EXPORT_SYMBOL_GPL(irq_create_acpi_mapping); +#endif + /** * irq_dispose_mapping() - Unmap an interrupt * @virq: linux irq number of the interrupt to unmap
From: Amit Daniel Kachhap amit.daniel@samsung.com
This API is similar to DT based irq_of_parse_and_map but does link parent/child IRQ controllers. This is tested for primary GIC PPI and GIC SPI interrupts and not for secondary child irq controllers.
[Hanjun: Add some comments for interrupt mapping from DT to ACPI, and rework it according to the API of irq_create_acpi_mapping()]
Signed-off-by: Amit Daniel Kachhap amit.daniel@samsung.com Signed-off-by: Hanjun Guo hanjun.guo@linaro.org --- drivers/acpi/plat/arm/boot.c | 34 +++++++++++++++++++++++++++++----- 1 file changed, 29 insertions(+), 5 deletions(-)
diff --git a/drivers/acpi/plat/arm/boot.c b/drivers/acpi/plat/arm/boot.c index 4fcdd9f..38a6a9d 100644 --- a/drivers/acpi/plat/arm/boot.c +++ b/drivers/acpi/plat/arm/boot.c @@ -254,12 +254,36 @@ int (*__acpi_register_gsi)(struct device *dev, u32 gsi, int acpi_register_gsi(struct device *dev, u32 gsi, int trigger, int polarity) { unsigned int irq; - unsigned int plat_gsi = gsi; - - plat_gsi = (*__acpi_register_gsi)(dev, gsi, trigger, polarity); - - irq = gsi_to_irq(plat_gsi); + unsigned int irq_type; + irq_hw_number_t hwirq = gsi; + + /* ACPI hae no bindings to indicate SPI or PPI, so we + * use following mapping from DT to ACPI: + * + * PPI interrupt: the same as DT, in the range [0, 15]; + * SPI interrupt: are in the range [32, 1019]; + */ + if (gsi < 32) { + /* PPI interrupts, add 16 to skip over SGIs */ + hwirq = gsi + 16; + }
+ if (trigger == ACPI_EDGE_SENSITIVE && + polarity == ACPI_ACTIVE_LOW) + irq_type = IRQ_TYPE_EDGE_FALLING; + else if (trigger == ACPI_EDGE_SENSITIVE && + polarity == ACPI_ACTIVE_HIGH) + irq_type = IRQ_TYPE_EDGE_RISING; + else if (trigger == ACPI_LEVEL_SENSITIVE && + polarity == ACPI_ACTIVE_LOW) + irq_type = IRQ_TYPE_LEVEL_LOW; + else if (trigger == ACPI_LEVEL_SENSITIVE && + polarity == ACPI_ACTIVE_HIGH) + irq_type = IRQ_TYPE_LEVEL_HIGH; + else + irq_type = IRQ_TYPE_NONE; + + irq = irq_create_acpi_mapping(hwirq, irq_type); return irq; } EXPORT_SYMBOL_GPL(acpi_register_gsi);
In MADT table, there are GIC cpu interface base address and GIC distributor base address, use them to convert GIC to ACPI.
Signed-off-by: Hanjun Guo hanjun.guo@linaro.org --- arch/arm64/kernel/irq.c | 4 +++ drivers/acpi/plat/arm/boot.c | 66 +++++++++++++++++++++++++++++++++++------- include/linux/acpi.h | 1 + 3 files changed, 61 insertions(+), 10 deletions(-)
diff --git a/arch/arm64/kernel/irq.c b/arch/arm64/kernel/irq.c index 473e5db..f27af5f 100644 --- a/arch/arm64/kernel/irq.c +++ b/arch/arm64/kernel/irq.c @@ -25,6 +25,7 @@ #include <linux/irq.h> #include <linux/smp.h> #include <linux/init.h> +#include <linux/acpi.h> #include <linux/irqchip.h> #include <linux/seq_file.h> #include <linux/ratelimit.h> @@ -79,6 +80,9 @@ void __init init_IRQ(void) { irqchip_init(); if (!handle_arch_irq) + acpi_gic_init(); + + if (!handle_arch_irq) panic("No interrupt controller found."); }
diff --git a/drivers/acpi/plat/arm/boot.c b/drivers/acpi/plat/arm/boot.c index 38a6a9d..2a59d70 100644 --- a/drivers/acpi/plat/arm/boot.c +++ b/drivers/acpi/plat/arm/boot.c @@ -37,6 +37,7 @@ #include <linux/bootmem.h> #include <linux/ioport.h> #include <linux/pci.h> +#include <linux/irqchip/arm-gic.h>
#include <asm/pgtable.h> #include <asm/io.h> @@ -80,6 +81,8 @@ int acpi_sci_override_gsi __initdata; int acpi_skip_timer_override __initdata; int acpi_use_timer_override __initdata; int acpi_fix_pin2_polarity __initdata; + +/* GIC cpu interface base address on ARM */ static u64 acpi_lapic_addr __initdata;
struct acpi_arm_root acpi_arm_rsdp_info; /* info about RSDP from FDT */ @@ -198,11 +201,22 @@ acpi_parse_gic(struct acpi_subtable_header *header, const unsigned long end) return 0; }
+#ifdef CONFIG_ARM_GIC +/* + * Hard code here, we can not get memory size from MADT (but FDT does), + * this size is described in ARMv8 foudation model's User Guide + */ +#define GIC_DISTRIBUTOR_MEMORY_SIZE (SZ_8K) +#define GIC_CPU_INTERFACE_MEMORY_SIZE (SZ_4K) + +/* GIC distributor is something like IOAPIC on x86 */ static int __init acpi_parse_gic_distributor(struct acpi_subtable_header *header, const unsigned long end) { struct acpi_madt_generic_distributor *distributor = NULL; + void __iomem *dist_base = NULL; + void __iomem *cpu_base = NULL;
distributor = (struct acpi_madt_generic_distributor *)header;
@@ -211,10 +225,36 @@ acpi_parse_gic_distributor(struct acpi_subtable_header *header,
acpi_table_print_madt_entry(header);
- /* TODO: handle with the base_address and irq_base for irq system */ + dist_base = ioremap(distributor->base_address, + GIC_CPU_INTERFACE_MEMORY_SIZE); + if (!dist_base) { + pr_warn("unable to map gic dist registers\n"); + return -ENOMEM; + } + + /* acpi_lapic_addr is stored in early_acpi_boot_init(), + * we can use it here with no worries + */ + cpu_base = ioremap(acpi_lapic_addr, GIC_CPU_INTERFACE_MEMORY_SIZE); + if (!cpu_base) { + pr_warn("unable to map gic cpu registers\n"); + return -ENOMEM; + } + + pr_debug("gic debug: cpu_base is %p, dist_base is %p\n", cpu_base, dist_base); + + gic_init(distributor->gic_id, -1, dist_base, cpu_base);
return 0; } +#else +static int __init +acpi_parse_gic_distributor(struct acpi_subtable_header *header, + const unsigned long end) +{ + return -ENODEV; +} +#endif /* CONFIG_ARM_GIC */
int acpi_gsi_to_irq(u32 gsi, unsigned int *irq) { @@ -654,16 +694,8 @@ static void __init acpi_process_madt(void) * Parse MADT LAPIC entries */ error = acpi_parse_madt_lapic_entries(); - if (!error) { + if (!error) acpi_lapic = 1; - - /* - * Parse MADT IO-APIC entries - */ - error = acpi_parse_madt_ioapic_entries(); - if (!error) - acpi_set_irq_model_gic(); - } }
/* @@ -793,6 +825,20 @@ void __init arm_acpi_reserve_memory() memblock_remove(addr - section_offset, num_sections * SECTION_SIZE); }
+int __init acpi_gic_init(void) +{ + int error; + + /* + * Parse MADT GIC distributor entries + */ + error = acpi_parse_madt_ioapic_entries(); + if (!error) + acpi_set_irq_model_gic(); + + return error; +} + static int __init parse_acpi(char *arg) { if (!arg) diff --git a/include/linux/acpi.h b/include/linux/acpi.h index 1dbfa2c..13b737e 100644 --- a/include/linux/acpi.h +++ b/include/linux/acpi.h @@ -92,6 +92,7 @@ char *__acpi_map_table(phys_addr_t phys_addr, unsigned long size); void __acpi_unmap_table(char *map, unsigned long size); int early_acpi_boot_init(void); int acpi_boot_init (void); +int acpi_gic_init(void); void acpi_boot_table_init (void); int acpi_mps_check (void); int acpi_numa_init (void);
Hack the arch timer and comment out the GIC in OF way to test the GIC. patch set for arch timer will send out soon.
It can boot Foudation model pretty fine with this patch set.
Signed-off-by: Hanjun Guo hanjun.guo@linaro.org --- drivers/clocksource/arm_arch_timer.c | 11 ++++++++--- drivers/irqchip/irq-gic.c | 4 ++-- 2 files changed, 10 insertions(+), 5 deletions(-)
diff --git a/drivers/clocksource/arm_arch_timer.c b/drivers/clocksource/arm_arch_timer.c index fbd9ccd..7563895 100644 --- a/drivers/clocksource/arm_arch_timer.c +++ b/drivers/clocksource/arm_arch_timer.c @@ -19,6 +19,7 @@ #include <linux/of_address.h> #include <linux/io.h> #include <linux/slab.h> +#include <linux/acpi.h>
#include <asm/arch_timer.h> #include <asm/virt.h> @@ -589,9 +590,13 @@ static void __init arch_timer_init(struct device_node *np) }
arch_timers_present |= ARCH_CP15_TIMER; - for (i = PHYS_SECURE_PPI; i < MAX_TIMER_PPI; i++) - arch_timer_ppi[i] = irq_of_parse_and_map(np, i); - arch_timer_detect_rate(NULL, np); + //for (i = PHYS_SECURE_PPI; i < MAX_TIMER_PPI; i++) + arch_timer_ppi[0] = irq_create_acpi_mapping(13+16, IRQ_TYPE_EDGE_RISING); + arch_timer_ppi[1] = irq_create_acpi_mapping(14+16, IRQ_TYPE_EDGE_RISING); + arch_timer_ppi[2] = irq_create_acpi_mapping(11+16, IRQ_TYPE_EDGE_RISING); + arch_timer_ppi[3] = irq_create_acpi_mapping(10+16, IRQ_TYPE_EDGE_RISING); + //arch_timer_detect_rate(NULL, np); + arch_timer_rate = 100000000;
/* * If HYP mode is available, we know that the physical timer diff --git a/drivers/irqchip/irq-gic.c b/drivers/irqchip/irq-gic.c index b158c6f..c6b6c87 100644 --- a/drivers/irqchip/irq-gic.c +++ b/drivers/irqchip/irq-gic.c @@ -1010,8 +1010,8 @@ int __init gic_of_init(struct device_node *node, struct device_node *parent) gic_cnt++; return 0; } -IRQCHIP_DECLARE(cortex_a15_gic, "arm,cortex-a15-gic", gic_of_init); -IRQCHIP_DECLARE(cortex_a9_gic, "arm,cortex-a9-gic", gic_of_init); +//IRQCHIP_DECLARE(cortex_a15_gic, "arm,cortex-a15-gic", gic_of_init); +//IRQCHIP_DECLARE(cortex_a9_gic, "arm,cortex-a9-gic", gic_of_init); IRQCHIP_DECLARE(msm_8660_qgic, "qcom,msm-8660-qgic", gic_of_init); IRQCHIP_DECLARE(msm_qgic2, "qcom,msm-qgic2", gic_of_init);
On 11/11/2013 06:05 AM, Hanjun Guo wrote:
This patch set trys to convert GIC to ACPI which based on patches from Amit, I rework two patches from him and fix two minor bugs :)
In MADT table, there are GIC cpu interface base address and GIC distributor base address, use them to convert GIC to ACPI.
GIC should be converted after all the devices refer to GIC are converted. So I hack some code to test this patch set.
Amit Daniel Kachhap (2): irqdomain: Add a new API irq_create_acpi_mapping ACPI: ARM: Update acpi_register_gsi to register with the core IRQ subsystem
Hanjun Guo (3): irqchip / GIC: do not set default host for GIC domain multi-times when ACPI enabled ARM / GIC: convert GIC to ACPI using the information in MADT ACPI / timer: hack to test GIC in ACPI mode
arch/arm64/kernel/irq.c | 4 ++ drivers/acpi/plat/arm/boot.c | 100 +++++++++++++++++++++++++++++----- drivers/clocksource/arm_arch_timer.c | 11 +++- drivers/irqchip/irq-gic.c | 9 ++- include/linux/acpi.h | 3 + kernel/irq/irqdomain.c | 27 +++++++++ 6 files changed, 133 insertions(+), 21 deletions(-)
Oh, I *like* these since GPIO needs a GIC to work right :).
Is this for GICv2 only? There are discussions about changing the MADT for GICv3 but it's not clear to me these patches would need to change until that discussion is finished.
Otherwise, I like it! Go for it.
Reviewed-by: Al Stone al.stone@linaro.org
On 11/15/13, Al Stone al.stone@linaro.org wrote:
On 11/11/2013 06:05 AM, Hanjun Guo wrote:
This patch set trys to convert GIC to ACPI which based on patches from Amit, I rework two patches from him and fix two minor bugs :)
In MADT table, there are GIC cpu interface base address and GIC distributor base address, use them to convert GIC to ACPI.
GIC should be converted after all the devices refer to GIC are converted. So I hack some code to test this patch set.
Amit Daniel Kachhap (2): irqdomain: Add a new API irq_create_acpi_mapping ACPI: ARM: Update acpi_register_gsi to register with the core IRQ subsystem
Hanjun Guo (3): irqchip / GIC: do not set default host for GIC domain multi-times when ACPI enabled ARM / GIC: convert GIC to ACPI using the information in MADT ACPI / timer: hack to test GIC in ACPI mode
arch/arm64/kernel/irq.c | 4 ++ drivers/acpi/plat/arm/boot.c | 100 +++++++++++++++++++++++++++++----- drivers/clocksource/arm_arch_timer.c | 11 +++- drivers/irqchip/irq-gic.c | 9 ++- include/linux/acpi.h | 3 + kernel/irq/irqdomain.c | 27 +++++++++ 6 files changed, 133 insertions(+), 21 deletions(-)
Oh, I *like* these since GPIO needs a GIC to work right :).
Is this for GICv2 only? There are discussions about changing the MADT for GICv3 but it's not clear to me these patches would need to change until that discussion is finished.
The patch series looks good to me also. This information is useful that GICV3 will have modifications for ACPI. Any link or pointer for this discussion?
Thanks, Amit
Otherwise, I like it! Go for it.
Reviewed-by: Al Stone al.stone@linaro.org
-- ciao, al
Al Stone Software Engineer Linaro Enterprise Group al.stone@linaro.org
Linaro-acpi mailing list Linaro-acpi@lists.linaro.org http://lists.linaro.org/mailman/listinfo/linaro-acpi
On 2013-11-15 5:57, Al Stone wrote:
On 11/11/2013 06:05 AM, Hanjun Guo wrote:
This patch set trys to convert GIC to ACPI which based on patches from Amit, I rework two patches from him and fix two minor bugs :)
In MADT table, there are GIC cpu interface base address and GIC distributor base address, use them to convert GIC to ACPI.
GIC should be converted after all the devices refer to GIC are converted. So I hack some code to test this patch set.
Amit Daniel Kachhap (2): irqdomain: Add a new API irq_create_acpi_mapping ACPI: ARM: Update acpi_register_gsi to register with the core IRQ subsystem
Hanjun Guo (3): irqchip / GIC: do not set default host for GIC domain multi-times when ACPI enabled ARM / GIC: convert GIC to ACPI using the information in MADT ACPI / timer: hack to test GIC in ACPI mode
arch/arm64/kernel/irq.c | 4 ++ drivers/acpi/plat/arm/boot.c | 100 +++++++++++++++++++++++++++++----- drivers/clocksource/arm_arch_timer.c | 11 +++- drivers/irqchip/irq-gic.c | 9 ++- include/linux/acpi.h | 3 + kernel/irq/irqdomain.c | 27 +++++++++ 6 files changed, 133 insertions(+), 21 deletions(-)
Oh, I *like* these since GPIO needs a GIC to work right :).
Is this for GICv2 only? There are discussions about changing the
Yes, GICv2 only. I think we can implement ACPI 5.0 first which can be upstream-able, and implement new version of code to support GICv3 when the new version spec come out, what's your opinion for this?
Thanks Hanjun
On 11/18/2013 11:18 PM, Hanjun Guo wrote:
On 2013-11-15 5:57, Al Stone wrote:
On 11/11/2013 06:05 AM, Hanjun Guo wrote:
This patch set trys to convert GIC to ACPI which based on patches from Amit, I rework two patches from him and fix two minor bugs :)
In MADT table, there are GIC cpu interface base address and GIC distributor base address, use them to convert GIC to ACPI.
GIC should be converted after all the devices refer to GIC are converted. So I hack some code to test this patch set.
Amit Daniel Kachhap (2): irqdomain: Add a new API irq_create_acpi_mapping ACPI: ARM: Update acpi_register_gsi to register with the core IRQ subsystem
Hanjun Guo (3): irqchip / GIC: do not set default host for GIC domain multi-times when ACPI enabled ARM / GIC: convert GIC to ACPI using the information in MADT ACPI / timer: hack to test GIC in ACPI mode
arch/arm64/kernel/irq.c | 4 ++ drivers/acpi/plat/arm/boot.c | 100 +++++++++++++++++++++++++++++----- drivers/clocksource/arm_arch_timer.c | 11 +++- drivers/irqchip/irq-gic.c | 9 ++- include/linux/acpi.h | 3 + kernel/irq/irqdomain.c | 27 +++++++++ 6 files changed, 133 insertions(+), 21 deletions(-)
Oh, I *like* these since GPIO needs a GIC to work right :).
Is this for GICv2 only? There are discussions about changing the
Yes, GICv2 only. I think we can implement ACPI 5.0 first which can be upstream-able, and implement new version of code to support GICv3 when the new version spec come out, what's your opinion for this?
Thanks Hanjun
That would be perfect; I assumed that is what you were thinking but I thought I should ask to be sure. Thanks, Hanjun; this is excellent.