Merge branch 'irq-urgent-for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/tip/tip

Pull irq fixes from Thomas Gleixner:
 "A small set of irq chip driver fixes and updates:

   - Update the SIFIVE PLIC interrupt driver to use the fasteoi handler
     to address the shortcomings of the existing flow handling which was
     prone to lose interrupts

   - Use the proper limit for GIC interrupt line numbers

   - Add retrigger support for the recently merged Anapurna Labs Fabric
     interrupt controller to make it complete

   - Enable the ATMEL AIC5 interrupt controller driver on the new
     SAM9X60 SoC"

* 'irq-urgent-for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/tip/tip:
  irqchip/sifive-plic: Switch to fasteoi flow
  irqchip/gic-v3: Fix GIC_LINE_NR accessor
  irqchip/atmel-aic5: Add support for sam9x60 irqchip
  irqchip/al-fic: Add support for irq retrigger
This commit is contained in:
Linus Torvalds 2019-10-20 06:27:54 -04:00
commit 81c4bc31c4
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);
} }