Merge branch 'irq/gic-4.5' of git://git.kernel.org/pub/scm/linux/kernel/git/maz/arm-platforms into irq/core
Pull the GIC related updates from Marc Zyngier: "Not a lot this time (what a relief!), but an interesting series from Linus Walleij coming out of his work converting the ARM RealView platforms to DT, and a couple of mundane fixes."
This commit is contained in:
commit
4e8dbe9e93
|
@ -18,6 +18,7 @@ Main node required properties:
|
||||||
"arm,cortex-a9-gic"
|
"arm,cortex-a9-gic"
|
||||||
"arm,gic-400"
|
"arm,gic-400"
|
||||||
"arm,pl390"
|
"arm,pl390"
|
||||||
|
"arm,tc11mp-gic"
|
||||||
"brcm,brahma-b15-gic"
|
"brcm,brahma-b15-gic"
|
||||||
"qcom,msm-8660-qgic"
|
"qcom,msm-8660-qgic"
|
||||||
"qcom,msm-qgic2"
|
"qcom,msm-qgic2"
|
||||||
|
|
|
@ -8,6 +8,11 @@ config ARM_GIC
|
||||||
select IRQ_DOMAIN_HIERARCHY
|
select IRQ_DOMAIN_HIERARCHY
|
||||||
select MULTI_IRQ_HANDLER
|
select MULTI_IRQ_HANDLER
|
||||||
|
|
||||||
|
config ARM_GIC_MAX_NR
|
||||||
|
int
|
||||||
|
default 2 if ARCH_REALVIEW
|
||||||
|
default 1
|
||||||
|
|
||||||
config ARM_GIC_V2M
|
config ARM_GIC_V2M
|
||||||
bool
|
bool
|
||||||
depends on ARM_GIC
|
depends on ARM_GIC
|
||||||
|
|
|
@ -21,6 +21,7 @@ obj-$(CONFIG_ARCH_SUNXI) += irq-sun4i.o
|
||||||
obj-$(CONFIG_ARCH_SUNXI) += irq-sunxi-nmi.o
|
obj-$(CONFIG_ARCH_SUNXI) += irq-sunxi-nmi.o
|
||||||
obj-$(CONFIG_ARCH_SPEAR3XX) += spear-shirq.o
|
obj-$(CONFIG_ARCH_SPEAR3XX) += spear-shirq.o
|
||||||
obj-$(CONFIG_ARM_GIC) += irq-gic.o irq-gic-common.o
|
obj-$(CONFIG_ARM_GIC) += irq-gic.o irq-gic-common.o
|
||||||
|
obj-$(CONFIG_REALVIEW_DT) += irq-gic-realview.o
|
||||||
obj-$(CONFIG_ARM_GIC_V2M) += irq-gic-v2m.o
|
obj-$(CONFIG_ARM_GIC_V2M) += irq-gic-v2m.o
|
||||||
obj-$(CONFIG_ARM_GIC_V3) += irq-gic-v3.o irq-gic-common.o
|
obj-$(CONFIG_ARM_GIC_V3) += irq-gic-v3.o irq-gic-common.o
|
||||||
obj-$(CONFIG_ARM_GIC_V3_ITS) += irq-gic-v3-its.o irq-gic-v3-its-pci-msi.o irq-gic-v3-its-platform-msi.o
|
obj-$(CONFIG_ARM_GIC_V3_ITS) += irq-gic-v3-its.o irq-gic-v3-its-pci-msi.o irq-gic-v3-its-platform-msi.o
|
||||||
|
|
|
@ -0,0 +1,43 @@
|
||||||
|
/*
|
||||||
|
* Special GIC quirks for the ARM RealView
|
||||||
|
* Copyright (C) 2015 Linus Walleij
|
||||||
|
*/
|
||||||
|
#include <linux/of.h>
|
||||||
|
#include <linux/regmap.h>
|
||||||
|
#include <linux/mfd/syscon.h>
|
||||||
|
#include <linux/bitops.h>
|
||||||
|
#include <linux/irqchip.h>
|
||||||
|
#include <linux/irqchip/arm-gic.h>
|
||||||
|
|
||||||
|
#define REALVIEW_SYS_LOCK_OFFSET 0x20
|
||||||
|
#define REALVIEW_PB11MP_SYS_PLD_CTRL1 0x74
|
||||||
|
#define VERSATILE_LOCK_VAL 0xA05F
|
||||||
|
#define PLD_INTMODE_MASK BIT(22)|BIT(23)|BIT(24)
|
||||||
|
#define PLD_INTMODE_LEGACY 0x0
|
||||||
|
#define PLD_INTMODE_NEW_DCC BIT(22)
|
||||||
|
#define PLD_INTMODE_NEW_NO_DCC BIT(23)
|
||||||
|
#define PLD_INTMODE_FIQ_ENABLE BIT(24)
|
||||||
|
|
||||||
|
static int __init
|
||||||
|
realview_gic_of_init(struct device_node *node, struct device_node *parent)
|
||||||
|
{
|
||||||
|
static struct regmap *map;
|
||||||
|
|
||||||
|
/* The PB11MPCore GIC needs to be configured in the syscon */
|
||||||
|
map = syscon_regmap_lookup_by_compatible("arm,realview-pb11mp-syscon");
|
||||||
|
if (!IS_ERR(map)) {
|
||||||
|
/* new irq mode with no DCC */
|
||||||
|
regmap_write(map, REALVIEW_SYS_LOCK_OFFSET,
|
||||||
|
VERSATILE_LOCK_VAL);
|
||||||
|
regmap_update_bits(map, REALVIEW_PB11MP_SYS_PLD_CTRL1,
|
||||||
|
PLD_INTMODE_NEW_NO_DCC,
|
||||||
|
PLD_INTMODE_MASK);
|
||||||
|
regmap_write(map, REALVIEW_SYS_LOCK_OFFSET, 0x0000);
|
||||||
|
pr_info("TC11MP GIC: set up interrupt controller to NEW mode, no DCC\n");
|
||||||
|
} else {
|
||||||
|
pr_err("TC11MP GIC setup: could not find syscon\n");
|
||||||
|
return -ENXIO;
|
||||||
|
}
|
||||||
|
return gic_of_init(node, parent);
|
||||||
|
}
|
||||||
|
IRQCHIP_DECLARE(armtc11mp_gic, "arm,tc11mp-gic", realview_gic_of_init);
|
|
@ -389,7 +389,7 @@ int __init gicv2m_of_init(struct device_node *node, struct irq_domain *parent)
|
||||||
|
|
||||||
ret = gicv2m_init_one(child, parent);
|
ret = gicv2m_init_one(child, parent);
|
||||||
if (ret) {
|
if (ret) {
|
||||||
of_node_put(node);
|
of_node_put(child);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -69,6 +69,7 @@ union gic_base {
|
||||||
};
|
};
|
||||||
|
|
||||||
struct gic_chip_data {
|
struct gic_chip_data {
|
||||||
|
struct irq_chip chip;
|
||||||
union gic_base dist_base;
|
union gic_base dist_base;
|
||||||
union gic_base cpu_base;
|
union gic_base cpu_base;
|
||||||
#ifdef CONFIG_CPU_PM
|
#ifdef CONFIG_CPU_PM
|
||||||
|
@ -99,11 +100,7 @@ static u8 gic_cpu_map[NR_GIC_CPU_IF] __read_mostly;
|
||||||
|
|
||||||
static struct static_key supports_deactivate = STATIC_KEY_INIT_TRUE;
|
static struct static_key supports_deactivate = STATIC_KEY_INIT_TRUE;
|
||||||
|
|
||||||
#ifndef MAX_GIC_NR
|
static struct gic_chip_data gic_data[CONFIG_ARM_GIC_MAX_NR] __read_mostly;
|
||||||
#define MAX_GIC_NR 1
|
|
||||||
#endif
|
|
||||||
|
|
||||||
static struct gic_chip_data gic_data[MAX_GIC_NR] __read_mostly;
|
|
||||||
|
|
||||||
#ifdef CONFIG_GIC_NON_BANKED
|
#ifdef CONFIG_GIC_NON_BANKED
|
||||||
static void __iomem *gic_get_percpu_base(union gic_base *base)
|
static void __iomem *gic_get_percpu_base(union gic_base *base)
|
||||||
|
@ -336,7 +333,7 @@ static void __exception_irq_entry gic_handle_irq(struct pt_regs *regs)
|
||||||
irqstat = readl_relaxed(cpu_base + GIC_CPU_INTACK);
|
irqstat = readl_relaxed(cpu_base + GIC_CPU_INTACK);
|
||||||
irqnr = irqstat & GICC_IAR_INT_ID_MASK;
|
irqnr = irqstat & GICC_IAR_INT_ID_MASK;
|
||||||
|
|
||||||
if (likely(irqnr > 15 && irqnr < 1021)) {
|
if (likely(irqnr > 15 && irqnr < 1020)) {
|
||||||
if (static_key_true(&supports_deactivate))
|
if (static_key_true(&supports_deactivate))
|
||||||
writel_relaxed(irqstat, cpu_base + GIC_CPU_EOI);
|
writel_relaxed(irqstat, cpu_base + GIC_CPU_EOI);
|
||||||
handle_domain_irq(gic->domain, irqnr, regs);
|
handle_domain_irq(gic->domain, irqnr, regs);
|
||||||
|
@ -383,7 +380,6 @@ static void gic_handle_cascade_irq(struct irq_desc *desc)
|
||||||
}
|
}
|
||||||
|
|
||||||
static struct irq_chip gic_chip = {
|
static struct irq_chip gic_chip = {
|
||||||
.name = "GIC",
|
|
||||||
.irq_mask = gic_mask_irq,
|
.irq_mask = gic_mask_irq,
|
||||||
.irq_unmask = gic_unmask_irq,
|
.irq_unmask = gic_unmask_irq,
|
||||||
.irq_eoi = gic_eoi_irq,
|
.irq_eoi = gic_eoi_irq,
|
||||||
|
@ -417,8 +413,7 @@ static struct irq_chip gic_eoimode1_chip = {
|
||||||
|
|
||||||
void __init gic_cascade_irq(unsigned int gic_nr, unsigned int irq)
|
void __init gic_cascade_irq(unsigned int gic_nr, unsigned int irq)
|
||||||
{
|
{
|
||||||
if (gic_nr >= MAX_GIC_NR)
|
BUG_ON(gic_nr >= CONFIG_ARM_GIC_MAX_NR);
|
||||||
BUG();
|
|
||||||
irq_set_chained_handler_and_data(irq, gic_handle_cascade_irq,
|
irq_set_chained_handler_and_data(irq, gic_handle_cascade_irq,
|
||||||
&gic_data[gic_nr]);
|
&gic_data[gic_nr]);
|
||||||
}
|
}
|
||||||
|
@ -524,7 +519,7 @@ int gic_cpu_if_down(unsigned int gic_nr)
|
||||||
void __iomem *cpu_base;
|
void __iomem *cpu_base;
|
||||||
u32 val = 0;
|
u32 val = 0;
|
||||||
|
|
||||||
if (gic_nr >= MAX_GIC_NR)
|
if (gic_nr >= CONFIG_ARM_GIC_MAX_NR)
|
||||||
return -EINVAL;
|
return -EINVAL;
|
||||||
|
|
||||||
cpu_base = gic_data_cpu_base(&gic_data[gic_nr]);
|
cpu_base = gic_data_cpu_base(&gic_data[gic_nr]);
|
||||||
|
@ -548,8 +543,7 @@ static void gic_dist_save(unsigned int gic_nr)
|
||||||
void __iomem *dist_base;
|
void __iomem *dist_base;
|
||||||
int i;
|
int i;
|
||||||
|
|
||||||
if (gic_nr >= MAX_GIC_NR)
|
BUG_ON(gic_nr >= CONFIG_ARM_GIC_MAX_NR);
|
||||||
BUG();
|
|
||||||
|
|
||||||
gic_irqs = gic_data[gic_nr].gic_irqs;
|
gic_irqs = gic_data[gic_nr].gic_irqs;
|
||||||
dist_base = gic_data_dist_base(&gic_data[gic_nr]);
|
dist_base = gic_data_dist_base(&gic_data[gic_nr]);
|
||||||
|
@ -587,8 +581,7 @@ static void gic_dist_restore(unsigned int gic_nr)
|
||||||
unsigned int i;
|
unsigned int i;
|
||||||
void __iomem *dist_base;
|
void __iomem *dist_base;
|
||||||
|
|
||||||
if (gic_nr >= MAX_GIC_NR)
|
BUG_ON(gic_nr >= CONFIG_ARM_GIC_MAX_NR);
|
||||||
BUG();
|
|
||||||
|
|
||||||
gic_irqs = gic_data[gic_nr].gic_irqs;
|
gic_irqs = gic_data[gic_nr].gic_irqs;
|
||||||
dist_base = gic_data_dist_base(&gic_data[gic_nr]);
|
dist_base = gic_data_dist_base(&gic_data[gic_nr]);
|
||||||
|
@ -634,8 +627,7 @@ static void gic_cpu_save(unsigned int gic_nr)
|
||||||
void __iomem *dist_base;
|
void __iomem *dist_base;
|
||||||
void __iomem *cpu_base;
|
void __iomem *cpu_base;
|
||||||
|
|
||||||
if (gic_nr >= MAX_GIC_NR)
|
BUG_ON(gic_nr >= CONFIG_ARM_GIC_MAX_NR);
|
||||||
BUG();
|
|
||||||
|
|
||||||
dist_base = gic_data_dist_base(&gic_data[gic_nr]);
|
dist_base = gic_data_dist_base(&gic_data[gic_nr]);
|
||||||
cpu_base = gic_data_cpu_base(&gic_data[gic_nr]);
|
cpu_base = gic_data_cpu_base(&gic_data[gic_nr]);
|
||||||
|
@ -664,8 +656,7 @@ static void gic_cpu_restore(unsigned int gic_nr)
|
||||||
void __iomem *dist_base;
|
void __iomem *dist_base;
|
||||||
void __iomem *cpu_base;
|
void __iomem *cpu_base;
|
||||||
|
|
||||||
if (gic_nr >= MAX_GIC_NR)
|
BUG_ON(gic_nr >= CONFIG_ARM_GIC_MAX_NR);
|
||||||
BUG();
|
|
||||||
|
|
||||||
dist_base = gic_data_dist_base(&gic_data[gic_nr]);
|
dist_base = gic_data_dist_base(&gic_data[gic_nr]);
|
||||||
cpu_base = gic_data_cpu_base(&gic_data[gic_nr]);
|
cpu_base = gic_data_cpu_base(&gic_data[gic_nr]);
|
||||||
|
@ -703,7 +694,7 @@ 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 < CONFIG_ARM_GIC_MAX_NR; i++) {
|
||||||
#ifdef CONFIG_GIC_NON_BANKED
|
#ifdef CONFIG_GIC_NON_BANKED
|
||||||
/* Skip over unused GICs */
|
/* Skip over unused GICs */
|
||||||
if (!gic_data[i].get_base)
|
if (!gic_data[i].get_base)
|
||||||
|
@ -835,8 +826,7 @@ void gic_migrate_target(unsigned int new_cpu_id)
|
||||||
int i, ror_val, cpu = smp_processor_id();
|
int i, ror_val, cpu = smp_processor_id();
|
||||||
u32 val, cur_target_mask, active_mask;
|
u32 val, cur_target_mask, active_mask;
|
||||||
|
|
||||||
if (gic_nr >= MAX_GIC_NR)
|
BUG_ON(gic_nr >= CONFIG_ARM_GIC_MAX_NR);
|
||||||
BUG();
|
|
||||||
|
|
||||||
dist_base = gic_data_dist_base(&gic_data[gic_nr]);
|
dist_base = gic_data_dist_base(&gic_data[gic_nr]);
|
||||||
if (!dist_base)
|
if (!dist_base)
|
||||||
|
@ -925,20 +915,15 @@ void __init gic_init_physaddr(struct device_node *node)
|
||||||
static int gic_irq_domain_map(struct irq_domain *d, unsigned int irq,
|
static int gic_irq_domain_map(struct irq_domain *d, unsigned int irq,
|
||||||
irq_hw_number_t hw)
|
irq_hw_number_t hw)
|
||||||
{
|
{
|
||||||
struct irq_chip *chip = &gic_chip;
|
struct gic_chip_data *gic = d->host_data;
|
||||||
|
|
||||||
if (static_key_true(&supports_deactivate)) {
|
|
||||||
if (d->host_data == (void *)&gic_data[0])
|
|
||||||
chip = &gic_eoimode1_chip;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (hw < 32) {
|
if (hw < 32) {
|
||||||
irq_set_percpu_devid(irq);
|
irq_set_percpu_devid(irq);
|
||||||
irq_domain_set_info(d, irq, hw, chip, d->host_data,
|
irq_domain_set_info(d, irq, hw, &gic->chip, d->host_data,
|
||||||
handle_percpu_devid_irq, NULL, NULL);
|
handle_percpu_devid_irq, NULL, NULL);
|
||||||
irq_set_status_flags(irq, IRQ_NOAUTOEN);
|
irq_set_status_flags(irq, IRQ_NOAUTOEN);
|
||||||
} else {
|
} else {
|
||||||
irq_domain_set_info(d, irq, hw, chip, d->host_data,
|
irq_domain_set_info(d, irq, hw, &gic->chip, d->host_data,
|
||||||
handle_fasteoi_irq, NULL, NULL);
|
handle_fasteoi_irq, NULL, NULL);
|
||||||
irq_set_probe(irq);
|
irq_set_probe(irq);
|
||||||
}
|
}
|
||||||
|
@ -1040,11 +1025,20 @@ static void __init __gic_init_bases(unsigned int gic_nr, int irq_start,
|
||||||
struct gic_chip_data *gic;
|
struct gic_chip_data *gic;
|
||||||
int gic_irqs, irq_base, i;
|
int gic_irqs, irq_base, i;
|
||||||
|
|
||||||
BUG_ON(gic_nr >= MAX_GIC_NR);
|
BUG_ON(gic_nr >= CONFIG_ARM_GIC_MAX_NR);
|
||||||
|
|
||||||
gic_check_cpu_features();
|
gic_check_cpu_features();
|
||||||
|
|
||||||
gic = &gic_data[gic_nr];
|
gic = &gic_data[gic_nr];
|
||||||
|
|
||||||
|
/* Initialize irq_chip */
|
||||||
|
if (static_key_true(&supports_deactivate) && gic_nr == 0) {
|
||||||
|
gic->chip = gic_eoimode1_chip;
|
||||||
|
} else {
|
||||||
|
gic->chip = gic_chip;
|
||||||
|
gic->chip.name = kasprintf(GFP_KERNEL, "GIC-%d", gic_nr);
|
||||||
|
}
|
||||||
|
|
||||||
#ifdef CONFIG_GIC_NON_BANKED
|
#ifdef CONFIG_GIC_NON_BANKED
|
||||||
if (percpu_offset) { /* Frankein-GIC without banked registers... */
|
if (percpu_offset) { /* Frankein-GIC without banked registers... */
|
||||||
unsigned int cpu;
|
unsigned int cpu;
|
||||||
|
@ -1196,7 +1190,7 @@ static bool gic_check_eoimode(struct device_node *node, void __iomem **base)
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
static int __init
|
int __init
|
||||||
gic_of_init(struct device_node *node, struct device_node *parent)
|
gic_of_init(struct device_node *node, struct device_node *parent)
|
||||||
{
|
{
|
||||||
void __iomem *cpu_base;
|
void __iomem *cpu_base;
|
||||||
|
|
|
@ -103,6 +103,16 @@ struct device_node;
|
||||||
void gic_cascade_irq(unsigned int gic_nr, unsigned int irq);
|
void gic_cascade_irq(unsigned int gic_nr, unsigned int irq);
|
||||||
int gic_cpu_if_down(unsigned int gic_nr);
|
int gic_cpu_if_down(unsigned int gic_nr);
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Subdrivers that need some preparatory work can initialize their
|
||||||
|
* chips and call this to register their GICs.
|
||||||
|
*/
|
||||||
|
int gic_of_init(struct device_node *node, struct device_node *parent);
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Legacy platforms not converted to DT yet must use this to init
|
||||||
|
* their GIC
|
||||||
|
*/
|
||||||
void gic_init(unsigned int nr, int start,
|
void gic_init(unsigned int nr, int start,
|
||||||
void __iomem *dist , void __iomem *cpu);
|
void __iomem *dist , void __iomem *cpu);
|
||||||
|
|
||||||
|
|
Loading…
Reference in New Issue