diff options
author | Marc Zyngier <maz@kernel.org> | 2023-04-21 16:05:31 +0300 |
---|---|---|
committer | Marc Zyngier <maz@kernel.org> | 2023-04-21 16:05:31 +0300 |
commit | 2ff1b0839ddd514be4752c64c1c6facf91ff3a56 (patch) | |
tree | 652cadcc3bc467ca66eefc43ce53c7e6d83380b4 /drivers/irqchip | |
parent | 275232c0b4064b85fd48532dff1a9b2764d67617 (diff) | |
parent | 0989ffb31cff794506f5d3dd109574ddbb9b983a (diff) | |
download | linux-2ff1b0839ddd514be4752c64c1c6facf91ff3a56.tar.xz |
Merge branch irq/misc-6.4 into irq/irqchip-next
* irq/misc-6.4:
: .
: Misc irqchip changes for 6.4:
:
: - Replace uses of of_find_property() with the more
: appropriate of_property_read_bool()
:
: - Make bcm-6345-l1 request its MMIO region
:
: - Add suspend support to the SiFive PLIC
:
: - Drop support for stih415, stih416 and stid127 platforms
: .
irqchip/st: Remove stih415/stih416 and stid127 platforms support
irqchip/irq-sifive-plic: Add syscore callbacks for hibernation
irqchip: Use of_property_read_bool() for boolean properties
irqchip/bcm-6345-l1: Request memory region
Signed-off-by: Marc Zyngier <maz@kernel.org>
Diffstat (limited to 'drivers/irqchip')
-rw-r--r-- | drivers/irqchip/irq-bcm6345-l1.c | 6 | ||||
-rw-r--r-- | drivers/irqchip/irq-csky-apb-intc.c | 2 | ||||
-rw-r--r-- | drivers/irqchip/irq-gic-v2m.c | 2 | ||||
-rw-r--r-- | drivers/irqchip/irq-sifive-plic.c | 93 | ||||
-rw-r--r-- | drivers/irqchip/irq-st.c | 15 |
5 files changed, 97 insertions, 21 deletions
diff --git a/drivers/irqchip/irq-bcm6345-l1.c b/drivers/irqchip/irq-bcm6345-l1.c index 6899e37810a8..fa113cb2529a 100644 --- a/drivers/irqchip/irq-bcm6345-l1.c +++ b/drivers/irqchip/irq-bcm6345-l1.c @@ -257,6 +257,9 @@ static int __init bcm6345_l1_init_one(struct device_node *dn, if (!cpu->map_base) return -ENOMEM; + if (!request_mem_region(res.start, sz, res.name)) + pr_err("failed to request intc memory"); + for (i = 0; i < n_words; i++) { cpu->enable_cache[i] = 0; __raw_writel(0, cpu->map_base + reg_enable(intc, i)); @@ -335,8 +338,7 @@ static int __init bcm6345_l1_of_init(struct device_node *dn, for_each_cpu(idx, &intc->cpumask) { struct bcm6345_l1_cpu *cpu = intc->cpus[idx]; - pr_info(" CPU%u at MMIO 0x%p (irq = %d)\n", idx, - cpu->map_base, cpu->parent_irq); + pr_info(" CPU%u (irq = %d)\n", idx, cpu->parent_irq); } return 0; diff --git a/drivers/irqchip/irq-csky-apb-intc.c b/drivers/irqchip/irq-csky-apb-intc.c index 42d8a2438ebc..6710691e4c25 100644 --- a/drivers/irqchip/irq-csky-apb-intc.c +++ b/drivers/irqchip/irq-csky-apb-intc.c @@ -68,7 +68,7 @@ static void __init ck_set_gc(struct device_node *node, void __iomem *reg_base, gc->chip_types[0].chip.irq_mask = irq_gc_mask_clr_bit; gc->chip_types[0].chip.irq_unmask = irq_gc_mask_set_bit; - if (of_find_property(node, "csky,support-pulse-signal", NULL)) + if (of_property_read_bool(node, "csky,support-pulse-signal")) gc->chip_types[0].chip.irq_unmask = irq_ck_mask_set_bit; } diff --git a/drivers/irqchip/irq-gic-v2m.c b/drivers/irqchip/irq-gic-v2m.c index f1e75b35a52a..f2ff4387870d 100644 --- a/drivers/irqchip/irq-gic-v2m.c +++ b/drivers/irqchip/irq-gic-v2m.c @@ -421,7 +421,7 @@ static int __init gicv2m_of_init(struct fwnode_handle *parent_handle, u32 spi_start = 0, nr_spis = 0; struct resource res; - if (!of_find_property(child, "msi-controller", NULL)) + if (!of_property_read_bool(child, "msi-controller")) continue; ret = of_address_to_resource(child, 0, &res); diff --git a/drivers/irqchip/irq-sifive-plic.c b/drivers/irqchip/irq-sifive-plic.c index ff47bd0dec45..e1484905b7bd 100644 --- a/drivers/irqchip/irq-sifive-plic.c +++ b/drivers/irqchip/irq-sifive-plic.c @@ -17,6 +17,7 @@ #include <linux/of_irq.h> #include <linux/platform_device.h> #include <linux/spinlock.h> +#include <linux/syscore_ops.h> #include <asm/smp.h> /* @@ -67,6 +68,8 @@ struct plic_priv { struct irq_domain *irqdomain; void __iomem *regs; unsigned long plic_quirks; + unsigned int nr_irqs; + unsigned long *prio_save; }; struct plic_handler { @@ -78,6 +81,7 @@ struct plic_handler { */ raw_spinlock_t enable_lock; void __iomem *enable_base; + u32 *enable_save; struct plic_priv *priv; }; static int plic_parent_irq __ro_after_init; @@ -229,6 +233,71 @@ static int plic_irq_set_type(struct irq_data *d, unsigned int type) return IRQ_SET_MASK_OK; } +static int plic_irq_suspend(void) +{ + unsigned int i, cpu; + u32 __iomem *reg; + struct plic_priv *priv; + + priv = per_cpu_ptr(&plic_handlers, smp_processor_id())->priv; + + for (i = 0; i < priv->nr_irqs; i++) + if (readl(priv->regs + PRIORITY_BASE + i * PRIORITY_PER_ID)) + __set_bit(i, priv->prio_save); + else + __clear_bit(i, priv->prio_save); + + for_each_cpu(cpu, cpu_present_mask) { + struct plic_handler *handler = per_cpu_ptr(&plic_handlers, cpu); + + if (!handler->present) + continue; + + raw_spin_lock(&handler->enable_lock); + for (i = 0; i < DIV_ROUND_UP(priv->nr_irqs, 32); i++) { + reg = handler->enable_base + i * sizeof(u32); + handler->enable_save[i] = readl(reg); + } + raw_spin_unlock(&handler->enable_lock); + } + + return 0; +} + +static void plic_irq_resume(void) +{ + unsigned int i, index, cpu; + u32 __iomem *reg; + struct plic_priv *priv; + + priv = per_cpu_ptr(&plic_handlers, smp_processor_id())->priv; + + for (i = 0; i < priv->nr_irqs; i++) { + index = BIT_WORD(i); + writel((priv->prio_save[index] & BIT_MASK(i)) ? 1 : 0, + priv->regs + PRIORITY_BASE + i * PRIORITY_PER_ID); + } + + for_each_cpu(cpu, cpu_present_mask) { + struct plic_handler *handler = per_cpu_ptr(&plic_handlers, cpu); + + if (!handler->present) + continue; + + raw_spin_lock(&handler->enable_lock); + for (i = 0; i < DIV_ROUND_UP(priv->nr_irqs, 32); i++) { + reg = handler->enable_base + i * sizeof(u32); + writel(handler->enable_save[i], reg); + } + raw_spin_unlock(&handler->enable_lock); + } +} + +static struct syscore_ops plic_irq_syscore_ops = { + .suspend = plic_irq_suspend, + .resume = plic_irq_resume, +}; + static int plic_irqdomain_map(struct irq_domain *d, unsigned int irq, irq_hw_number_t hwirq) { @@ -345,6 +414,7 @@ static int __init __plic_init(struct device_node *node, u32 nr_irqs; struct plic_priv *priv; struct plic_handler *handler; + unsigned int cpu; priv = kzalloc(sizeof(*priv), GFP_KERNEL); if (!priv) @@ -363,15 +433,21 @@ static int __init __plic_init(struct device_node *node, if (WARN_ON(!nr_irqs)) goto out_iounmap; + priv->nr_irqs = nr_irqs; + + priv->prio_save = bitmap_alloc(nr_irqs, GFP_KERNEL); + if (!priv->prio_save) + goto out_free_priority_reg; + nr_contexts = of_irq_count(node); if (WARN_ON(!nr_contexts)) - goto out_iounmap; + goto out_free_priority_reg; error = -ENOMEM; priv->irqdomain = irq_domain_add_linear(node, nr_irqs + 1, &plic_irqdomain_ops, priv); if (WARN_ON(!priv->irqdomain)) - goto out_iounmap; + goto out_free_priority_reg; for (i = 0; i < nr_contexts; i++) { struct of_phandle_args parent; @@ -441,6 +517,11 @@ static int __init __plic_init(struct device_node *node, handler->enable_base = priv->regs + CONTEXT_ENABLE_BASE + i * CONTEXT_ENABLE_SIZE; handler->priv = priv; + + handler->enable_save = kcalloc(DIV_ROUND_UP(nr_irqs, 32), + sizeof(*handler->enable_save), GFP_KERNEL); + if (!handler->enable_save) + goto out_free_enable_reg; done: for (hwirq = 1; hwirq <= nr_irqs; hwirq++) { plic_toggle(handler, hwirq, 0); @@ -461,11 +542,19 @@ done: plic_starting_cpu, plic_dying_cpu); plic_cpuhp_setup_done = true; } + register_syscore_ops(&plic_irq_syscore_ops); pr_info("%pOFP: mapped %d interrupts with %d handlers for" " %d contexts.\n", node, nr_irqs, nr_handlers, nr_contexts); return 0; +out_free_enable_reg: + for_each_cpu(cpu, cpu_present_mask) { + handler = per_cpu_ptr(&plic_handlers, cpu); + kfree(handler->enable_save); + } +out_free_priority_reg: + kfree(priv->prio_save); out_iounmap: iounmap(priv->regs); out_free_priv: diff --git a/drivers/irqchip/irq-st.c b/drivers/irqchip/irq-st.c index 1b83512b29c6..819a12297b58 100644 --- a/drivers/irqchip/irq-st.c +++ b/drivers/irqchip/irq-st.c @@ -15,10 +15,7 @@ #include <linux/regmap.h> #include <linux/slab.h> -#define STIH415_SYSCFG_642 0x0a8 -#define STIH416_SYSCFG_7543 0x87c #define STIH407_SYSCFG_5102 0x198 -#define STID127_SYSCFG_734 0x088 #define ST_A9_IRQ_MASK 0x001FFFFF #define ST_A9_IRQ_MAX_CHANS 2 @@ -45,21 +42,9 @@ struct st_irq_syscfg { static const struct of_device_id st_irq_syscfg_match[] = { { - .compatible = "st,stih415-irq-syscfg", - .data = (void *)STIH415_SYSCFG_642, - }, - { - .compatible = "st,stih416-irq-syscfg", - .data = (void *)STIH416_SYSCFG_7543, - }, - { .compatible = "st,stih407-irq-syscfg", .data = (void *)STIH407_SYSCFG_5102, }, - { - .compatible = "st,stid127-irq-syscfg", - .data = (void *)STID127_SYSCFG_734, - }, {} }; |