forked from Minki/linux
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:
commit
81c4bc31c4
@ -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
Block a user