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:
Thomas Gleixner 2019-10-14 20:35:58 +02:00
commit c9b59181c2
5 changed files with 43 additions and 17 deletions

View File

@ -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).

View File

@ -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;

View File

@ -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);

View File

@ -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)
/* /*

View File

@ -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);
} }