irqchip fixes for 5.4, take #1
- Add retrigger support to Amazon's al-fic driver - Add SAM9X60 support to Atmel's AIC5 irqchip - Fix GICv3 maximum interrupt calculation - Convert SiFive's PLIC to the fasteoi IRQ flow -----BEGIN PGP SIGNATURE----- iQJDBAABCgAtFiEEn9UcU+C1Yxj9lZw9I9DQutE9ekMFAl2TG74PHG1hekBrZXJu ZWwub3JnAAoJECPQ0LrRPXpDaCsQAJNOv7mE6d52LPA5e9Vx/HP2shKjTNdpyD4C vi5tE7bvQ7VKZuoQ7S7zF3RrrG4z/Fth7Qe0v2T+2OecXBlejB64z642CIY0aVhh SPWf1pUimHCosQnY2xEi/8Db6i0ZzlaYo5FlhTK+OKnaEuhXdoGVRVxyk+AhSq5n jruA+GO/V2OfbbEkmXwJViEF6w0jzuQEaJIm9M2Z0S5QG3tsnC2+OrsBDJZqxT9/ 7Jvx6IB/dk3yuQC7byT7bBLlEnw8nPe8yVua8N8LtTiZi/JjpfIl3qgXJx/h9iyc jkuOZn2GpWwzi/i6SFQLTVKxeChqPTa61tTX67Y4LnCF8iOhzNY/Ev9OqLztTW+J tVYaW6zp/shKOze1GmDXcG/9OMgQ7prR05nK2hnbGaI+dRHiw+zvgS0Sd6pPilDx V/FtdCCD3JkKUgu+O6qBkJZb1RXbwGs7RdpkWHaxuYu3F47lGkoWpKPc689DWXyI FL9bqcr3i4hPfWn4a/fVjYBvov91SCWRLWhhB5ViZ59ldE7WG2A5g62X9f6+mUk8 PrPFT0eldnCzeEf81suj7X0Phv8ftzigTm9ByJh8AV1/uuBi+AKjsYxDsp7CxMPj 9YYozRHakyp0c9hpwXRjozlVGKC6JpZLBBFga5+zI62IoIdEJCdnGFfdbxcqPRJE oCXSSXXG =AV7P -----END PGP SIGNATURE----- Merge tag 'irqchip-fixes-5.4-1' of git://git.kernel.org/pub/scm/linux/kernel/git/maz/arm-platforms into irq/urgent Pull irqchip fixes from Marc Zyngier: - Add retrigger support to Amazon's al-fic driver - Add SAM9X60 support to Atmel's AIC5 irqchip - Fix GICv3 maximum interrupt calculation - Convert SiFive's PLIC to the fasteoi IRQ flow
This commit is contained in:
commit
c9b59181c2
|
@ -1,8 +1,11 @@
|
||||||
* Advanced Interrupt Controller (AIC)
|
* Advanced Interrupt Controller (AIC)
|
||||||
|
|
||||||
Required properties:
|
Required properties:
|
||||||
- compatible: Should be "atmel,<chip>-aic"
|
- compatible: Should be:
|
||||||
<chip> can be "at91rm9200", "sama5d2", "sama5d3" or "sama5d4"
|
- "atmel,<chip>-aic" where <chip> can be "at91rm9200", "sama5d2",
|
||||||
|
"sama5d3" or "sama5d4"
|
||||||
|
- "microchip,<chip>-aic" where <chip> can be "sam9x60"
|
||||||
|
|
||||||
- interrupt-controller: Identifies the node as an interrupt controller.
|
- interrupt-controller: Identifies the node as an interrupt controller.
|
||||||
- #interrupt-cells: The number of cells to define the interrupts. It should be 3.
|
- #interrupt-cells: The number of cells to define the interrupts. It should be 3.
|
||||||
The first cell is the IRQ number (aka "Peripheral IDentifier" on datasheet).
|
The first cell is the IRQ number (aka "Peripheral IDentifier" on datasheet).
|
||||||
|
|
|
@ -15,6 +15,7 @@
|
||||||
|
|
||||||
/* FIC Registers */
|
/* FIC Registers */
|
||||||
#define AL_FIC_CAUSE 0x00
|
#define AL_FIC_CAUSE 0x00
|
||||||
|
#define AL_FIC_SET_CAUSE 0x08
|
||||||
#define AL_FIC_MASK 0x10
|
#define AL_FIC_MASK 0x10
|
||||||
#define AL_FIC_CONTROL 0x28
|
#define AL_FIC_CONTROL 0x28
|
||||||
|
|
||||||
|
@ -126,6 +127,16 @@ static void al_fic_irq_handler(struct irq_desc *desc)
|
||||||
chained_irq_exit(irqchip, desc);
|
chained_irq_exit(irqchip, desc);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static int al_fic_irq_retrigger(struct irq_data *data)
|
||||||
|
{
|
||||||
|
struct irq_chip_generic *gc = irq_data_get_irq_chip_data(data);
|
||||||
|
struct al_fic *fic = gc->private;
|
||||||
|
|
||||||
|
writel_relaxed(BIT(data->hwirq), fic->base + AL_FIC_SET_CAUSE);
|
||||||
|
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
static int al_fic_register(struct device_node *node,
|
static int al_fic_register(struct device_node *node,
|
||||||
struct al_fic *fic)
|
struct al_fic *fic)
|
||||||
{
|
{
|
||||||
|
@ -159,6 +170,7 @@ static int al_fic_register(struct device_node *node,
|
||||||
gc->chip_types->chip.irq_unmask = irq_gc_mask_clr_bit;
|
gc->chip_types->chip.irq_unmask = irq_gc_mask_clr_bit;
|
||||||
gc->chip_types->chip.irq_ack = irq_gc_ack_clr_bit;
|
gc->chip_types->chip.irq_ack = irq_gc_ack_clr_bit;
|
||||||
gc->chip_types->chip.irq_set_type = al_fic_irq_set_type;
|
gc->chip_types->chip.irq_set_type = al_fic_irq_set_type;
|
||||||
|
gc->chip_types->chip.irq_retrigger = al_fic_irq_retrigger;
|
||||||
gc->chip_types->chip.flags = IRQCHIP_SKIP_SET_WAKE;
|
gc->chip_types->chip.flags = IRQCHIP_SKIP_SET_WAKE;
|
||||||
gc->private = fic;
|
gc->private = fic;
|
||||||
|
|
||||||
|
|
|
@ -313,6 +313,7 @@ static void __init sama5d3_aic_irq_fixup(void)
|
||||||
static const struct of_device_id aic5_irq_fixups[] __initconst = {
|
static const struct of_device_id aic5_irq_fixups[] __initconst = {
|
||||||
{ .compatible = "atmel,sama5d3", .data = sama5d3_aic_irq_fixup },
|
{ .compatible = "atmel,sama5d3", .data = sama5d3_aic_irq_fixup },
|
||||||
{ .compatible = "atmel,sama5d4", .data = sama5d3_aic_irq_fixup },
|
{ .compatible = "atmel,sama5d4", .data = sama5d3_aic_irq_fixup },
|
||||||
|
{ .compatible = "microchip,sam9x60", .data = sama5d3_aic_irq_fixup },
|
||||||
{ /* sentinel */ },
|
{ /* sentinel */ },
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -390,3 +391,12 @@ static int __init sama5d4_aic5_of_init(struct device_node *node,
|
||||||
return aic5_of_init(node, parent, NR_SAMA5D4_IRQS);
|
return aic5_of_init(node, parent, NR_SAMA5D4_IRQS);
|
||||||
}
|
}
|
||||||
IRQCHIP_DECLARE(sama5d4_aic5, "atmel,sama5d4-aic", sama5d4_aic5_of_init);
|
IRQCHIP_DECLARE(sama5d4_aic5, "atmel,sama5d4-aic", sama5d4_aic5_of_init);
|
||||||
|
|
||||||
|
#define NR_SAM9X60_IRQS 50
|
||||||
|
|
||||||
|
static int __init sam9x60_aic5_of_init(struct device_node *node,
|
||||||
|
struct device_node *parent)
|
||||||
|
{
|
||||||
|
return aic5_of_init(node, parent, NR_SAM9X60_IRQS);
|
||||||
|
}
|
||||||
|
IRQCHIP_DECLARE(sam9x60_aic5, "microchip,sam9x60-aic", sam9x60_aic5_of_init);
|
||||||
|
|
|
@ -59,7 +59,7 @@ static struct gic_chip_data gic_data __read_mostly;
|
||||||
static DEFINE_STATIC_KEY_TRUE(supports_deactivate_key);
|
static DEFINE_STATIC_KEY_TRUE(supports_deactivate_key);
|
||||||
|
|
||||||
#define GIC_ID_NR (1U << GICD_TYPER_ID_BITS(gic_data.rdists.gicd_typer))
|
#define GIC_ID_NR (1U << GICD_TYPER_ID_BITS(gic_data.rdists.gicd_typer))
|
||||||
#define GIC_LINE_NR max(GICD_TYPER_SPIS(gic_data.rdists.gicd_typer), 1020U)
|
#define GIC_LINE_NR min(GICD_TYPER_SPIS(gic_data.rdists.gicd_typer), 1020U)
|
||||||
#define GIC_ESPI_NR GICD_TYPER_ESPIS(gic_data.rdists.gicd_typer)
|
#define GIC_ESPI_NR GICD_TYPER_ESPIS(gic_data.rdists.gicd_typer)
|
||||||
|
|
||||||
/*
|
/*
|
||||||
|
|
|
@ -97,7 +97,7 @@ static inline void plic_irq_toggle(const struct cpumask *mask,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
static void plic_irq_enable(struct irq_data *d)
|
static void plic_irq_unmask(struct irq_data *d)
|
||||||
{
|
{
|
||||||
unsigned int cpu = cpumask_any_and(irq_data_get_affinity_mask(d),
|
unsigned int cpu = cpumask_any_and(irq_data_get_affinity_mask(d),
|
||||||
cpu_online_mask);
|
cpu_online_mask);
|
||||||
|
@ -106,7 +106,7 @@ static void plic_irq_enable(struct irq_data *d)
|
||||||
plic_irq_toggle(cpumask_of(cpu), d->hwirq, 1);
|
plic_irq_toggle(cpumask_of(cpu), d->hwirq, 1);
|
||||||
}
|
}
|
||||||
|
|
||||||
static void plic_irq_disable(struct irq_data *d)
|
static void plic_irq_mask(struct irq_data *d)
|
||||||
{
|
{
|
||||||
plic_irq_toggle(cpu_possible_mask, d->hwirq, 0);
|
plic_irq_toggle(cpu_possible_mask, d->hwirq, 0);
|
||||||
}
|
}
|
||||||
|
@ -125,10 +125,8 @@ static int plic_set_affinity(struct irq_data *d,
|
||||||
if (cpu >= nr_cpu_ids)
|
if (cpu >= nr_cpu_ids)
|
||||||
return -EINVAL;
|
return -EINVAL;
|
||||||
|
|
||||||
if (!irqd_irq_disabled(d)) {
|
plic_irq_toggle(cpu_possible_mask, d->hwirq, 0);
|
||||||
plic_irq_toggle(cpu_possible_mask, d->hwirq, 0);
|
plic_irq_toggle(cpumask_of(cpu), d->hwirq, 1);
|
||||||
plic_irq_toggle(cpumask_of(cpu), d->hwirq, 1);
|
|
||||||
}
|
|
||||||
|
|
||||||
irq_data_update_effective_affinity(d, cpumask_of(cpu));
|
irq_data_update_effective_affinity(d, cpumask_of(cpu));
|
||||||
|
|
||||||
|
@ -136,14 +134,18 @@ static int plic_set_affinity(struct irq_data *d,
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
static void plic_irq_eoi(struct irq_data *d)
|
||||||
|
{
|
||||||
|
struct plic_handler *handler = this_cpu_ptr(&plic_handlers);
|
||||||
|
|
||||||
|
writel(d->hwirq, handler->hart_base + CONTEXT_CLAIM);
|
||||||
|
}
|
||||||
|
|
||||||
static struct irq_chip plic_chip = {
|
static struct irq_chip plic_chip = {
|
||||||
.name = "SiFive PLIC",
|
.name = "SiFive PLIC",
|
||||||
/*
|
.irq_mask = plic_irq_mask,
|
||||||
* There is no need to mask/unmask PLIC interrupts. They are "masked"
|
.irq_unmask = plic_irq_unmask,
|
||||||
* by reading claim and "unmasked" when writing it back.
|
.irq_eoi = plic_irq_eoi,
|
||||||
*/
|
|
||||||
.irq_enable = plic_irq_enable,
|
|
||||||
.irq_disable = plic_irq_disable,
|
|
||||||
#ifdef CONFIG_SMP
|
#ifdef CONFIG_SMP
|
||||||
.irq_set_affinity = plic_set_affinity,
|
.irq_set_affinity = plic_set_affinity,
|
||||||
#endif
|
#endif
|
||||||
|
@ -152,7 +154,7 @@ static struct irq_chip plic_chip = {
|
||||||
static int plic_irqdomain_map(struct irq_domain *d, unsigned int irq,
|
static int plic_irqdomain_map(struct irq_domain *d, unsigned int irq,
|
||||||
irq_hw_number_t hwirq)
|
irq_hw_number_t hwirq)
|
||||||
{
|
{
|
||||||
irq_set_chip_and_handler(irq, &plic_chip, handle_simple_irq);
|
irq_set_chip_and_handler(irq, &plic_chip, handle_fasteoi_irq);
|
||||||
irq_set_chip_data(irq, NULL);
|
irq_set_chip_data(irq, NULL);
|
||||||
irq_set_noprobe(irq);
|
irq_set_noprobe(irq);
|
||||||
return 0;
|
return 0;
|
||||||
|
@ -188,7 +190,6 @@ static void plic_handle_irq(struct pt_regs *regs)
|
||||||
hwirq);
|
hwirq);
|
||||||
else
|
else
|
||||||
generic_handle_irq(irq);
|
generic_handle_irq(irq);
|
||||||
writel(hwirq, claim);
|
|
||||||
}
|
}
|
||||||
csr_set(sie, SIE_SEIE);
|
csr_set(sie, SIE_SEIE);
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in New Issue