Loading Documentation/arm/memory.txt +5 −6 Original line number Original line Diff line number Diff line Loading @@ -51,15 +51,14 @@ ffc00000 ffefffff DMA memory mapping region. Memory returned ff000000 ffbfffff Reserved for future expansion of DMA ff000000 ffbfffff Reserved for future expansion of DMA mapping region. mapping region. VMALLOC_END feffffff Free for platform use, recommended. VMALLOC_END must be aligned to a 2MB boundary. VMALLOC_START VMALLOC_END-1 vmalloc() / ioremap() space. VMALLOC_START VMALLOC_END-1 vmalloc() / ioremap() space. Memory returned by vmalloc/ioremap will Memory returned by vmalloc/ioremap will be dynamically placed in this region. be dynamically placed in this region. VMALLOC_START may be based upon the value Machine specific static mappings are also of the high_memory variable. located here through iotable_init(). VMALLOC_START is based upon the value of the high_memory variable, and VMALLOC_END is equal to 0xff000000. PAGE_OFFSET high_memory-1 Kernel direct-mapped RAM region. PAGE_OFFSET high_memory-1 Kernel direct-mapped RAM region. This maps the platforms RAM, and typically This maps the platforms RAM, and typically Loading Documentation/devicetree/bindings/arm/gic.txt +4 −0 Original line number Original line Diff line number Diff line Loading @@ -42,6 +42,10 @@ Optional - interrupts : Interrupt source of the parent interrupt controller. Only - interrupts : Interrupt source of the parent interrupt controller. Only present on secondary GICs. present on secondary GICs. - cpu-offset : per-cpu offset within the distributor and cpu interface regions, used when the GIC doesn't have banked registers. The offset is cpu-offset * cpu-nr. Example: Example: intc: interrupt-controller@fff11000 { intc: interrupt-controller@fff11000 { Loading Documentation/devicetree/bindings/arm/vic.txt 0 → 100644 +29 −0 Original line number Original line Diff line number Diff line * ARM Vectored Interrupt Controller One or more Vectored Interrupt Controllers (VIC's) can be connected in an ARM system for interrupt routing. For multiple controllers they can either be nested or have the outputs wire-OR'd together. Required properties: - compatible : should be one of "arm,pl190-vic" "arm,pl192-vic" - interrupt-controller : Identifies the node as an interrupt controller - #interrupt-cells : The number of cells to define the interrupts. Must be 1 as the VIC has no configuration options for interrupt sources. The cell is a u32 and defines the interrupt number. - reg : The register bank for the VIC. Optional properties: - interrupts : Interrupt source for parent controllers if the VIC is nested. Example: vic0: interrupt-controller@60000 { compatible = "arm,pl192-vic"; interrupt-controller; #interrupt-cells = <1>; reg = <0x60000 0x1000>; }; arch/arm/common/Kconfig +6 −0 Original line number Original line Diff line number Diff line config ARM_GIC config ARM_GIC select IRQ_DOMAIN select IRQ_DOMAIN select MULTI_IRQ_HANDLER bool config GIC_NON_BANKED bool bool config ARM_VIC config ARM_VIC select IRQ_DOMAIN select MULTI_IRQ_HANDLER bool bool config ARM_VIC_NR config ARM_VIC_NR Loading arch/arm/common/gic.c +141 −24 Original line number Original line Diff line number Diff line Loading @@ -40,13 +40,36 @@ #include <linux/slab.h> #include <linux/slab.h> #include <asm/irq.h> #include <asm/irq.h> #include <asm/exception.h> #include <asm/mach/irq.h> #include <asm/mach/irq.h> #include <asm/hardware/gic.h> #include <asm/hardware/gic.h> static DEFINE_RAW_SPINLOCK(irq_controller_lock); union gic_base { void __iomem *common_base; void __percpu __iomem **percpu_base; }; struct gic_chip_data { unsigned int irq_offset; union gic_base dist_base; union gic_base cpu_base; #ifdef CONFIG_CPU_PM u32 saved_spi_enable[DIV_ROUND_UP(1020, 32)]; u32 saved_spi_conf[DIV_ROUND_UP(1020, 16)]; u32 saved_spi_target[DIV_ROUND_UP(1020, 4)]; u32 __percpu *saved_ppi_enable; u32 __percpu *saved_ppi_conf; #endif #ifdef CONFIG_IRQ_DOMAIN struct irq_domain domain; #endif unsigned int gic_irqs; #ifdef CONFIG_GIC_NON_BANKED void __iomem *(*get_base)(union gic_base *); #endif }; /* Address of GIC 0 CPU interface */ static DEFINE_RAW_SPINLOCK(irq_controller_lock); void __iomem *gic_cpu_base_addr __read_mostly; /* /* * Supported arch specific GIC irq extension. * Supported arch specific GIC irq extension. Loading @@ -67,16 +90,48 @@ struct irq_chip gic_arch_extn = { static struct gic_chip_data gic_data[MAX_GIC_NR] __read_mostly; static struct gic_chip_data gic_data[MAX_GIC_NR] __read_mostly; #ifdef CONFIG_GIC_NON_BANKED static void __iomem *gic_get_percpu_base(union gic_base *base) { return *__this_cpu_ptr(base->percpu_base); } static void __iomem *gic_get_common_base(union gic_base *base) { return base->common_base; } static inline void __iomem *gic_data_dist_base(struct gic_chip_data *data) { return data->get_base(&data->dist_base); } static inline void __iomem *gic_data_cpu_base(struct gic_chip_data *data) { return data->get_base(&data->cpu_base); } static inline void gic_set_base_accessor(struct gic_chip_data *data, void __iomem *(*f)(union gic_base *)) { data->get_base = f; } #else #define gic_data_dist_base(d) ((d)->dist_base.common_base) #define gic_data_cpu_base(d) ((d)->cpu_base.common_base) #define gic_set_base_accessor(d,f) #endif static inline void __iomem *gic_dist_base(struct irq_data *d) static inline void __iomem *gic_dist_base(struct irq_data *d) { { struct gic_chip_data *gic_data = irq_data_get_irq_chip_data(d); struct gic_chip_data *gic_data = irq_data_get_irq_chip_data(d); return gic_data->dist_base; return gic_data_dist_base(gic_data); } } static inline void __iomem *gic_cpu_base(struct irq_data *d) static inline void __iomem *gic_cpu_base(struct irq_data *d) { { struct gic_chip_data *gic_data = irq_data_get_irq_chip_data(d); struct gic_chip_data *gic_data = irq_data_get_irq_chip_data(d); return gic_data->cpu_base; return gic_data_cpu_base(gic_data); } } static inline unsigned int gic_irq(struct irq_data *d) static inline unsigned int gic_irq(struct irq_data *d) Loading Loading @@ -215,6 +270,32 @@ static int gic_set_wake(struct irq_data *d, unsigned int on) #define gic_set_wake NULL #define gic_set_wake NULL #endif #endif asmlinkage void __exception_irq_entry gic_handle_irq(struct pt_regs *regs) { u32 irqstat, irqnr; struct gic_chip_data *gic = &gic_data[0]; void __iomem *cpu_base = gic_data_cpu_base(gic); do { irqstat = readl_relaxed(cpu_base + GIC_CPU_INTACK); irqnr = irqstat & ~0x1c00; if (likely(irqnr > 15 && irqnr < 1021)) { irqnr = irq_domain_to_irq(&gic->domain, irqnr); handle_IRQ(irqnr, regs); continue; } if (irqnr < 16) { writel_relaxed(irqstat, cpu_base + GIC_CPU_EOI); #ifdef CONFIG_SMP handle_IPI(irqnr, regs); #endif continue; } break; } while (1); } static void gic_handle_cascade_irq(unsigned int irq, struct irq_desc *desc) static void gic_handle_cascade_irq(unsigned int irq, struct irq_desc *desc) { { struct gic_chip_data *chip_data = irq_get_handler_data(irq); struct gic_chip_data *chip_data = irq_get_handler_data(irq); Loading @@ -225,7 +306,7 @@ static void gic_handle_cascade_irq(unsigned int irq, struct irq_desc *desc) chained_irq_enter(chip, desc); chained_irq_enter(chip, desc); raw_spin_lock(&irq_controller_lock); raw_spin_lock(&irq_controller_lock); status = readl_relaxed(chip_data->cpu_base + GIC_CPU_INTACK); status = readl_relaxed(gic_data_cpu_base(chip_data) + GIC_CPU_INTACK); raw_spin_unlock(&irq_controller_lock); raw_spin_unlock(&irq_controller_lock); gic_irq = (status & 0x3ff); gic_irq = (status & 0x3ff); Loading Loading @@ -270,7 +351,7 @@ static void __init gic_dist_init(struct gic_chip_data *gic) u32 cpumask; u32 cpumask; unsigned int gic_irqs = gic->gic_irqs; unsigned int gic_irqs = gic->gic_irqs; struct irq_domain *domain = &gic->domain; struct irq_domain *domain = &gic->domain; void __iomem *base = gic->dist_base; void __iomem *base = gic_data_dist_base(gic); u32 cpu = 0; u32 cpu = 0; #ifdef CONFIG_SMP #ifdef CONFIG_SMP Loading Loading @@ -330,8 +411,8 @@ static void __init gic_dist_init(struct gic_chip_data *gic) static void __cpuinit gic_cpu_init(struct gic_chip_data *gic) static void __cpuinit gic_cpu_init(struct gic_chip_data *gic) { { void __iomem *dist_base = gic->dist_base; void __iomem *dist_base = gic_data_dist_base(gic); void __iomem *base = gic->cpu_base; void __iomem *base = gic_data_cpu_base(gic); int i; int i; /* /* Loading Loading @@ -368,7 +449,7 @@ static void gic_dist_save(unsigned int gic_nr) BUG(); BUG(); gic_irqs = gic_data[gic_nr].gic_irqs; gic_irqs = gic_data[gic_nr].gic_irqs; dist_base = gic_data[gic_nr].dist_base; dist_base = gic_data_dist_base(&gic_data[gic_nr]); if (!dist_base) if (!dist_base) return; return; Loading Loading @@ -403,7 +484,7 @@ static void gic_dist_restore(unsigned int gic_nr) BUG(); BUG(); gic_irqs = gic_data[gic_nr].gic_irqs; gic_irqs = gic_data[gic_nr].gic_irqs; dist_base = gic_data[gic_nr].dist_base; dist_base = gic_data_dist_base(&gic_data[gic_nr]); if (!dist_base) if (!dist_base) return; return; Loading Loading @@ -439,8 +520,8 @@ static void gic_cpu_save(unsigned int gic_nr) if (gic_nr >= MAX_GIC_NR) if (gic_nr >= MAX_GIC_NR) BUG(); BUG(); dist_base = gic_data[gic_nr].dist_base; dist_base = gic_data_dist_base(&gic_data[gic_nr]); cpu_base = gic_data[gic_nr].cpu_base; cpu_base = gic_data_cpu_base(&gic_data[gic_nr]); if (!dist_base || !cpu_base) if (!dist_base || !cpu_base) return; return; Loading @@ -465,8 +546,8 @@ static void gic_cpu_restore(unsigned int gic_nr) if (gic_nr >= MAX_GIC_NR) if (gic_nr >= MAX_GIC_NR) BUG(); BUG(); dist_base = gic_data[gic_nr].dist_base; dist_base = gic_data_dist_base(&gic_data[gic_nr]); cpu_base = gic_data[gic_nr].cpu_base; cpu_base = gic_data_cpu_base(&gic_data[gic_nr]); if (!dist_base || !cpu_base) if (!dist_base || !cpu_base) return; return; Loading @@ -491,6 +572,11 @@ static int gic_notifier(struct notifier_block *self, unsigned long cmd, void *v) int i; int i; for (i = 0; i < MAX_GIC_NR; i++) { for (i = 0; i < MAX_GIC_NR; i++) { #ifdef CONFIG_GIC_NON_BANKED /* Skip over unused GICs */ if (!gic_data[i].get_base) continue; #endif switch (cmd) { switch (cmd) { case CPU_PM_ENTER: case CPU_PM_ENTER: gic_cpu_save(i); gic_cpu_save(i); Loading Loading @@ -564,8 +650,9 @@ const struct irq_domain_ops gic_irq_domain_ops = { #endif #endif }; }; void __init gic_init(unsigned int gic_nr, int irq_start, void __init gic_init_bases(unsigned int gic_nr, int irq_start, void __iomem *dist_base, void __iomem *cpu_base) void __iomem *dist_base, void __iomem *cpu_base, u32 percpu_offset) { { struct gic_chip_data *gic; struct gic_chip_data *gic; struct irq_domain *domain; struct irq_domain *domain; Loading @@ -575,8 +662,36 @@ void __init gic_init(unsigned int gic_nr, int irq_start, gic = &gic_data[gic_nr]; gic = &gic_data[gic_nr]; domain = &gic->domain; domain = &gic->domain; gic->dist_base = dist_base; #ifdef CONFIG_GIC_NON_BANKED gic->cpu_base = cpu_base; if (percpu_offset) { /* Frankein-GIC without banked registers... */ unsigned int cpu; gic->dist_base.percpu_base = alloc_percpu(void __iomem *); gic->cpu_base.percpu_base = alloc_percpu(void __iomem *); if (WARN_ON(!gic->dist_base.percpu_base || !gic->cpu_base.percpu_base)) { free_percpu(gic->dist_base.percpu_base); free_percpu(gic->cpu_base.percpu_base); return; } for_each_possible_cpu(cpu) { unsigned long offset = percpu_offset * cpu_logical_map(cpu); *per_cpu_ptr(gic->dist_base.percpu_base, cpu) = dist_base + offset; *per_cpu_ptr(gic->cpu_base.percpu_base, cpu) = cpu_base + offset; } gic_set_base_accessor(gic, gic_get_percpu_base); } else #endif { /* Normal, sane GIC... */ WARN(percpu_offset, "GIC_NON_BANKED not enabled, ignoring %08x offset!", percpu_offset); gic->dist_base.common_base = dist_base; gic->cpu_base.common_base = cpu_base; gic_set_base_accessor(gic, gic_get_common_base); } /* /* * For primary GICs, skip over SGIs. * For primary GICs, skip over SGIs. Loading @@ -584,8 +699,6 @@ void __init gic_init(unsigned int gic_nr, int irq_start, */ */ domain->hwirq_base = 32; domain->hwirq_base = 32; if (gic_nr == 0) { if (gic_nr == 0) { gic_cpu_base_addr = cpu_base; if ((irq_start & 31) > 0) { if ((irq_start & 31) > 0) { domain->hwirq_base = 16; domain->hwirq_base = 16; if (irq_start != -1) if (irq_start != -1) Loading @@ -597,7 +710,7 @@ void __init gic_init(unsigned int gic_nr, int irq_start, * Find out how many interrupts are supported. * Find out how many interrupts are supported. * The GIC only supports up to 1020 interrupt sources. * The GIC only supports up to 1020 interrupt sources. */ */ gic_irqs = readl_relaxed(dist_base + GIC_DIST_CTR) & 0x1f; gic_irqs = readl_relaxed(gic_data_dist_base(gic) + GIC_DIST_CTR) & 0x1f; gic_irqs = (gic_irqs + 1) * 32; gic_irqs = (gic_irqs + 1) * 32; if (gic_irqs > 1020) if (gic_irqs > 1020) gic_irqs = 1020; gic_irqs = 1020; Loading Loading @@ -645,7 +758,7 @@ void gic_raise_softirq(const struct cpumask *mask, unsigned int irq) dsb(); dsb(); /* this always happens on GIC0 */ /* this always happens on GIC0 */ writel_relaxed(map << 16 | irq, gic_data[0].dist_base + GIC_DIST_SOFTINT); writel_relaxed(map << 16 | irq, gic_data_dist_base(&gic_data[0]) + GIC_DIST_SOFTINT); } } #endif #endif Loading @@ -656,6 +769,7 @@ int __init gic_of_init(struct device_node *node, struct device_node *parent) { { void __iomem *cpu_base; void __iomem *cpu_base; void __iomem *dist_base; void __iomem *dist_base; u32 percpu_offset; int irq; int irq; struct irq_domain *domain = &gic_data[gic_cnt].domain; struct irq_domain *domain = &gic_data[gic_cnt].domain; Loading @@ -668,9 +782,12 @@ int __init gic_of_init(struct device_node *node, struct device_node *parent) cpu_base = of_iomap(node, 1); cpu_base = of_iomap(node, 1); WARN(!cpu_base, "unable to map gic cpu registers\n"); WARN(!cpu_base, "unable to map gic cpu registers\n"); if (of_property_read_u32(node, "cpu-offset", &percpu_offset)) percpu_offset = 0; domain->of_node = of_node_get(node); domain->of_node = of_node_get(node); gic_init(gic_cnt, -1, dist_base, cpu_base); gic_init_bases(gic_cnt, -1, dist_base, cpu_base, percpu_offset); if (parent) { if (parent) { irq = irq_of_parse_and_map(node, 0); irq = irq_of_parse_and_map(node, 0); Loading Loading
Documentation/arm/memory.txt +5 −6 Original line number Original line Diff line number Diff line Loading @@ -51,15 +51,14 @@ ffc00000 ffefffff DMA memory mapping region. Memory returned ff000000 ffbfffff Reserved for future expansion of DMA ff000000 ffbfffff Reserved for future expansion of DMA mapping region. mapping region. VMALLOC_END feffffff Free for platform use, recommended. VMALLOC_END must be aligned to a 2MB boundary. VMALLOC_START VMALLOC_END-1 vmalloc() / ioremap() space. VMALLOC_START VMALLOC_END-1 vmalloc() / ioremap() space. Memory returned by vmalloc/ioremap will Memory returned by vmalloc/ioremap will be dynamically placed in this region. be dynamically placed in this region. VMALLOC_START may be based upon the value Machine specific static mappings are also of the high_memory variable. located here through iotable_init(). VMALLOC_START is based upon the value of the high_memory variable, and VMALLOC_END is equal to 0xff000000. PAGE_OFFSET high_memory-1 Kernel direct-mapped RAM region. PAGE_OFFSET high_memory-1 Kernel direct-mapped RAM region. This maps the platforms RAM, and typically This maps the platforms RAM, and typically Loading
Documentation/devicetree/bindings/arm/gic.txt +4 −0 Original line number Original line Diff line number Diff line Loading @@ -42,6 +42,10 @@ Optional - interrupts : Interrupt source of the parent interrupt controller. Only - interrupts : Interrupt source of the parent interrupt controller. Only present on secondary GICs. present on secondary GICs. - cpu-offset : per-cpu offset within the distributor and cpu interface regions, used when the GIC doesn't have banked registers. The offset is cpu-offset * cpu-nr. Example: Example: intc: interrupt-controller@fff11000 { intc: interrupt-controller@fff11000 { Loading
Documentation/devicetree/bindings/arm/vic.txt 0 → 100644 +29 −0 Original line number Original line Diff line number Diff line * ARM Vectored Interrupt Controller One or more Vectored Interrupt Controllers (VIC's) can be connected in an ARM system for interrupt routing. For multiple controllers they can either be nested or have the outputs wire-OR'd together. Required properties: - compatible : should be one of "arm,pl190-vic" "arm,pl192-vic" - interrupt-controller : Identifies the node as an interrupt controller - #interrupt-cells : The number of cells to define the interrupts. Must be 1 as the VIC has no configuration options for interrupt sources. The cell is a u32 and defines the interrupt number. - reg : The register bank for the VIC. Optional properties: - interrupts : Interrupt source for parent controllers if the VIC is nested. Example: vic0: interrupt-controller@60000 { compatible = "arm,pl192-vic"; interrupt-controller; #interrupt-cells = <1>; reg = <0x60000 0x1000>; };
arch/arm/common/Kconfig +6 −0 Original line number Original line Diff line number Diff line config ARM_GIC config ARM_GIC select IRQ_DOMAIN select IRQ_DOMAIN select MULTI_IRQ_HANDLER bool config GIC_NON_BANKED bool bool config ARM_VIC config ARM_VIC select IRQ_DOMAIN select MULTI_IRQ_HANDLER bool bool config ARM_VIC_NR config ARM_VIC_NR Loading
arch/arm/common/gic.c +141 −24 Original line number Original line Diff line number Diff line Loading @@ -40,13 +40,36 @@ #include <linux/slab.h> #include <linux/slab.h> #include <asm/irq.h> #include <asm/irq.h> #include <asm/exception.h> #include <asm/mach/irq.h> #include <asm/mach/irq.h> #include <asm/hardware/gic.h> #include <asm/hardware/gic.h> static DEFINE_RAW_SPINLOCK(irq_controller_lock); union gic_base { void __iomem *common_base; void __percpu __iomem **percpu_base; }; struct gic_chip_data { unsigned int irq_offset; union gic_base dist_base; union gic_base cpu_base; #ifdef CONFIG_CPU_PM u32 saved_spi_enable[DIV_ROUND_UP(1020, 32)]; u32 saved_spi_conf[DIV_ROUND_UP(1020, 16)]; u32 saved_spi_target[DIV_ROUND_UP(1020, 4)]; u32 __percpu *saved_ppi_enable; u32 __percpu *saved_ppi_conf; #endif #ifdef CONFIG_IRQ_DOMAIN struct irq_domain domain; #endif unsigned int gic_irqs; #ifdef CONFIG_GIC_NON_BANKED void __iomem *(*get_base)(union gic_base *); #endif }; /* Address of GIC 0 CPU interface */ static DEFINE_RAW_SPINLOCK(irq_controller_lock); void __iomem *gic_cpu_base_addr __read_mostly; /* /* * Supported arch specific GIC irq extension. * Supported arch specific GIC irq extension. Loading @@ -67,16 +90,48 @@ struct irq_chip gic_arch_extn = { static struct gic_chip_data gic_data[MAX_GIC_NR] __read_mostly; static struct gic_chip_data gic_data[MAX_GIC_NR] __read_mostly; #ifdef CONFIG_GIC_NON_BANKED static void __iomem *gic_get_percpu_base(union gic_base *base) { return *__this_cpu_ptr(base->percpu_base); } static void __iomem *gic_get_common_base(union gic_base *base) { return base->common_base; } static inline void __iomem *gic_data_dist_base(struct gic_chip_data *data) { return data->get_base(&data->dist_base); } static inline void __iomem *gic_data_cpu_base(struct gic_chip_data *data) { return data->get_base(&data->cpu_base); } static inline void gic_set_base_accessor(struct gic_chip_data *data, void __iomem *(*f)(union gic_base *)) { data->get_base = f; } #else #define gic_data_dist_base(d) ((d)->dist_base.common_base) #define gic_data_cpu_base(d) ((d)->cpu_base.common_base) #define gic_set_base_accessor(d,f) #endif static inline void __iomem *gic_dist_base(struct irq_data *d) static inline void __iomem *gic_dist_base(struct irq_data *d) { { struct gic_chip_data *gic_data = irq_data_get_irq_chip_data(d); struct gic_chip_data *gic_data = irq_data_get_irq_chip_data(d); return gic_data->dist_base; return gic_data_dist_base(gic_data); } } static inline void __iomem *gic_cpu_base(struct irq_data *d) static inline void __iomem *gic_cpu_base(struct irq_data *d) { { struct gic_chip_data *gic_data = irq_data_get_irq_chip_data(d); struct gic_chip_data *gic_data = irq_data_get_irq_chip_data(d); return gic_data->cpu_base; return gic_data_cpu_base(gic_data); } } static inline unsigned int gic_irq(struct irq_data *d) static inline unsigned int gic_irq(struct irq_data *d) Loading Loading @@ -215,6 +270,32 @@ static int gic_set_wake(struct irq_data *d, unsigned int on) #define gic_set_wake NULL #define gic_set_wake NULL #endif #endif asmlinkage void __exception_irq_entry gic_handle_irq(struct pt_regs *regs) { u32 irqstat, irqnr; struct gic_chip_data *gic = &gic_data[0]; void __iomem *cpu_base = gic_data_cpu_base(gic); do { irqstat = readl_relaxed(cpu_base + GIC_CPU_INTACK); irqnr = irqstat & ~0x1c00; if (likely(irqnr > 15 && irqnr < 1021)) { irqnr = irq_domain_to_irq(&gic->domain, irqnr); handle_IRQ(irqnr, regs); continue; } if (irqnr < 16) { writel_relaxed(irqstat, cpu_base + GIC_CPU_EOI); #ifdef CONFIG_SMP handle_IPI(irqnr, regs); #endif continue; } break; } while (1); } static void gic_handle_cascade_irq(unsigned int irq, struct irq_desc *desc) static void gic_handle_cascade_irq(unsigned int irq, struct irq_desc *desc) { { struct gic_chip_data *chip_data = irq_get_handler_data(irq); struct gic_chip_data *chip_data = irq_get_handler_data(irq); Loading @@ -225,7 +306,7 @@ static void gic_handle_cascade_irq(unsigned int irq, struct irq_desc *desc) chained_irq_enter(chip, desc); chained_irq_enter(chip, desc); raw_spin_lock(&irq_controller_lock); raw_spin_lock(&irq_controller_lock); status = readl_relaxed(chip_data->cpu_base + GIC_CPU_INTACK); status = readl_relaxed(gic_data_cpu_base(chip_data) + GIC_CPU_INTACK); raw_spin_unlock(&irq_controller_lock); raw_spin_unlock(&irq_controller_lock); gic_irq = (status & 0x3ff); gic_irq = (status & 0x3ff); Loading Loading @@ -270,7 +351,7 @@ static void __init gic_dist_init(struct gic_chip_data *gic) u32 cpumask; u32 cpumask; unsigned int gic_irqs = gic->gic_irqs; unsigned int gic_irqs = gic->gic_irqs; struct irq_domain *domain = &gic->domain; struct irq_domain *domain = &gic->domain; void __iomem *base = gic->dist_base; void __iomem *base = gic_data_dist_base(gic); u32 cpu = 0; u32 cpu = 0; #ifdef CONFIG_SMP #ifdef CONFIG_SMP Loading Loading @@ -330,8 +411,8 @@ static void __init gic_dist_init(struct gic_chip_data *gic) static void __cpuinit gic_cpu_init(struct gic_chip_data *gic) static void __cpuinit gic_cpu_init(struct gic_chip_data *gic) { { void __iomem *dist_base = gic->dist_base; void __iomem *dist_base = gic_data_dist_base(gic); void __iomem *base = gic->cpu_base; void __iomem *base = gic_data_cpu_base(gic); int i; int i; /* /* Loading Loading @@ -368,7 +449,7 @@ static void gic_dist_save(unsigned int gic_nr) BUG(); BUG(); gic_irqs = gic_data[gic_nr].gic_irqs; gic_irqs = gic_data[gic_nr].gic_irqs; dist_base = gic_data[gic_nr].dist_base; dist_base = gic_data_dist_base(&gic_data[gic_nr]); if (!dist_base) if (!dist_base) return; return; Loading Loading @@ -403,7 +484,7 @@ static void gic_dist_restore(unsigned int gic_nr) BUG(); BUG(); gic_irqs = gic_data[gic_nr].gic_irqs; gic_irqs = gic_data[gic_nr].gic_irqs; dist_base = gic_data[gic_nr].dist_base; dist_base = gic_data_dist_base(&gic_data[gic_nr]); if (!dist_base) if (!dist_base) return; return; Loading Loading @@ -439,8 +520,8 @@ static void gic_cpu_save(unsigned int gic_nr) if (gic_nr >= MAX_GIC_NR) if (gic_nr >= MAX_GIC_NR) BUG(); BUG(); dist_base = gic_data[gic_nr].dist_base; dist_base = gic_data_dist_base(&gic_data[gic_nr]); cpu_base = gic_data[gic_nr].cpu_base; cpu_base = gic_data_cpu_base(&gic_data[gic_nr]); if (!dist_base || !cpu_base) if (!dist_base || !cpu_base) return; return; Loading @@ -465,8 +546,8 @@ static void gic_cpu_restore(unsigned int gic_nr) if (gic_nr >= MAX_GIC_NR) if (gic_nr >= MAX_GIC_NR) BUG(); BUG(); dist_base = gic_data[gic_nr].dist_base; dist_base = gic_data_dist_base(&gic_data[gic_nr]); cpu_base = gic_data[gic_nr].cpu_base; cpu_base = gic_data_cpu_base(&gic_data[gic_nr]); if (!dist_base || !cpu_base) if (!dist_base || !cpu_base) return; return; Loading @@ -491,6 +572,11 @@ static int gic_notifier(struct notifier_block *self, unsigned long cmd, void *v) int i; int i; for (i = 0; i < MAX_GIC_NR; i++) { for (i = 0; i < MAX_GIC_NR; i++) { #ifdef CONFIG_GIC_NON_BANKED /* Skip over unused GICs */ if (!gic_data[i].get_base) continue; #endif switch (cmd) { switch (cmd) { case CPU_PM_ENTER: case CPU_PM_ENTER: gic_cpu_save(i); gic_cpu_save(i); Loading Loading @@ -564,8 +650,9 @@ const struct irq_domain_ops gic_irq_domain_ops = { #endif #endif }; }; void __init gic_init(unsigned int gic_nr, int irq_start, void __init gic_init_bases(unsigned int gic_nr, int irq_start, void __iomem *dist_base, void __iomem *cpu_base) void __iomem *dist_base, void __iomem *cpu_base, u32 percpu_offset) { { struct gic_chip_data *gic; struct gic_chip_data *gic; struct irq_domain *domain; struct irq_domain *domain; Loading @@ -575,8 +662,36 @@ void __init gic_init(unsigned int gic_nr, int irq_start, gic = &gic_data[gic_nr]; gic = &gic_data[gic_nr]; domain = &gic->domain; domain = &gic->domain; gic->dist_base = dist_base; #ifdef CONFIG_GIC_NON_BANKED gic->cpu_base = cpu_base; if (percpu_offset) { /* Frankein-GIC without banked registers... */ unsigned int cpu; gic->dist_base.percpu_base = alloc_percpu(void __iomem *); gic->cpu_base.percpu_base = alloc_percpu(void __iomem *); if (WARN_ON(!gic->dist_base.percpu_base || !gic->cpu_base.percpu_base)) { free_percpu(gic->dist_base.percpu_base); free_percpu(gic->cpu_base.percpu_base); return; } for_each_possible_cpu(cpu) { unsigned long offset = percpu_offset * cpu_logical_map(cpu); *per_cpu_ptr(gic->dist_base.percpu_base, cpu) = dist_base + offset; *per_cpu_ptr(gic->cpu_base.percpu_base, cpu) = cpu_base + offset; } gic_set_base_accessor(gic, gic_get_percpu_base); } else #endif { /* Normal, sane GIC... */ WARN(percpu_offset, "GIC_NON_BANKED not enabled, ignoring %08x offset!", percpu_offset); gic->dist_base.common_base = dist_base; gic->cpu_base.common_base = cpu_base; gic_set_base_accessor(gic, gic_get_common_base); } /* /* * For primary GICs, skip over SGIs. * For primary GICs, skip over SGIs. Loading @@ -584,8 +699,6 @@ void __init gic_init(unsigned int gic_nr, int irq_start, */ */ domain->hwirq_base = 32; domain->hwirq_base = 32; if (gic_nr == 0) { if (gic_nr == 0) { gic_cpu_base_addr = cpu_base; if ((irq_start & 31) > 0) { if ((irq_start & 31) > 0) { domain->hwirq_base = 16; domain->hwirq_base = 16; if (irq_start != -1) if (irq_start != -1) Loading @@ -597,7 +710,7 @@ void __init gic_init(unsigned int gic_nr, int irq_start, * Find out how many interrupts are supported. * Find out how many interrupts are supported. * The GIC only supports up to 1020 interrupt sources. * The GIC only supports up to 1020 interrupt sources. */ */ gic_irqs = readl_relaxed(dist_base + GIC_DIST_CTR) & 0x1f; gic_irqs = readl_relaxed(gic_data_dist_base(gic) + GIC_DIST_CTR) & 0x1f; gic_irqs = (gic_irqs + 1) * 32; gic_irqs = (gic_irqs + 1) * 32; if (gic_irqs > 1020) if (gic_irqs > 1020) gic_irqs = 1020; gic_irqs = 1020; Loading Loading @@ -645,7 +758,7 @@ void gic_raise_softirq(const struct cpumask *mask, unsigned int irq) dsb(); dsb(); /* this always happens on GIC0 */ /* this always happens on GIC0 */ writel_relaxed(map << 16 | irq, gic_data[0].dist_base + GIC_DIST_SOFTINT); writel_relaxed(map << 16 | irq, gic_data_dist_base(&gic_data[0]) + GIC_DIST_SOFTINT); } } #endif #endif Loading @@ -656,6 +769,7 @@ int __init gic_of_init(struct device_node *node, struct device_node *parent) { { void __iomem *cpu_base; void __iomem *cpu_base; void __iomem *dist_base; void __iomem *dist_base; u32 percpu_offset; int irq; int irq; struct irq_domain *domain = &gic_data[gic_cnt].domain; struct irq_domain *domain = &gic_data[gic_cnt].domain; Loading @@ -668,9 +782,12 @@ int __init gic_of_init(struct device_node *node, struct device_node *parent) cpu_base = of_iomap(node, 1); cpu_base = of_iomap(node, 1); WARN(!cpu_base, "unable to map gic cpu registers\n"); WARN(!cpu_base, "unable to map gic cpu registers\n"); if (of_property_read_u32(node, "cpu-offset", &percpu_offset)) percpu_offset = 0; domain->of_node = of_node_get(node); domain->of_node = of_node_get(node); gic_init(gic_cnt, -1, dist_base, cpu_base); gic_init_bases(gic_cnt, -1, dist_base, cpu_base, percpu_offset); if (parent) { if (parent) { irq = irq_of_parse_and_map(node, 0); irq = irq_of_parse_and_map(node, 0); Loading