Skip to content

Commit

Permalink
Merge tag 'irqchip-5.9' of git://git.kernel.org/pub/scm/linux/kernel/…
Browse files Browse the repository at this point in the history
…git/maz/arm-platforms into irq/core

Pull irqchip updates from Marc Zyngier:

 - Add infrastructure to allow DT irqchip platform drivers to
   be built as modules
 - Allow qcom-pdc, mtk-cirq and mtk-sysirq to be built as module
 - Fix ACPI probing to avoid abusing function pointer casting
 - Allow bcm7120-l2 and brcmstb-l2 to be used as wake-up sources
 - Teach NXP's IMX INTMUX some power management
 - Allow stm32-exti to be used as a hierarchical irqchip
 - Let stm32-exti use the hw spinlock API in its full glory
 - A couple of GICv4.1 fixes
 - Tons of cleanups (mtk-sysirq, aic5, bcm7038-l1, imx-intmux,
   brcmstb-l2, ativic32, ti-sci-inta, lonsoon, MIPS GIC, GICv3)
  • Loading branch information
Thomas Gleixner committed Aug 3, 2020
2 parents 8fa88a8 + ac62460 commit 3d5128c
Show file tree
Hide file tree
Showing 32 changed files with 346 additions and 210 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,10 @@ Broadcom Generic Level 2 Interrupt Controller

Required properties:

- compatible: should be "brcm,l2-intc" for latched interrupt controllers
- compatible: should be one of:
"brcm,hif-spi-l2-intc" or
"brcm,upg-aux-aon-l2-intc" or
"brcm,l2-intc" for latched interrupt controllers
should be "brcm,bcm7271-l2-intc" for level interrupt controllers
- reg: specifies the base physical address and size of the registers
- interrupt-controller: identifies the node as an interrupt controller
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -22,8 +22,8 @@ properties:

interrupts:
minItems: 1
maxItems: 4
description: Four parent interrupts that receive chained interrupts.
maxItems: 8
description: Eight parent interrupts that receive chained interrupts.

interrupt-controller: true

Expand Down
3 changes: 1 addition & 2 deletions drivers/irqchip/Kconfig
Original file line number Diff line number Diff line change
Expand Up @@ -425,7 +425,7 @@ config GOLDFISH_PIC
for Goldfish based virtual platforms.

config QCOM_PDC
bool "QCOM PDC"
tristate "QCOM PDC"
depends on ARCH_QCOM
select IRQ_DOMAIN_HIERARCHY
help
Expand Down Expand Up @@ -541,7 +541,6 @@ config LOONGSON_HTPIC
default y
select IRQ_DOMAIN
select GENERIC_IRQ_CHIP
select I8259
help
Support for the Loongson-3 HyperTransport PIC Controller.

Expand Down
2 changes: 1 addition & 1 deletion drivers/irqchip/irq-ativic32.c
Original file line number Diff line number Diff line change
Expand Up @@ -92,7 +92,7 @@ static int ativic32_irq_domain_map(struct irq_domain *id, unsigned int virq,
return 0;
}

static struct irq_domain_ops ativic32_ops = {
static const struct irq_domain_ops ativic32_ops = {
.map = ativic32_irq_domain_map,
.xlate = irq_domain_xlate_onecell
};
Expand Down
8 changes: 7 additions & 1 deletion drivers/irqchip/irq-atmel-aic5.c
Original file line number Diff line number Diff line change
Expand Up @@ -310,10 +310,16 @@ static void __init sama5d3_aic_irq_fixup(void)
aic_common_rtc_irq_fixup();
}

static void __init sam9x60_aic_irq_fixup(void)
{
aic_common_rtc_irq_fixup();
aic_common_rtt_irq_fixup();
}

static const struct of_device_id aic5_irq_fixups[] __initconst = {
{ .compatible = "atmel,sama5d3", .data = sama5d3_aic_irq_fixup },
{ .compatible = "atmel,sama5d4", .data = sama5d3_aic_irq_fixup },
{ .compatible = "microchip,sam9x60", .data = sama5d3_aic_irq_fixup },
{ .compatible = "microchip,sam9x60", .data = sam9x60_aic_irq_fixup },
{ /* sentinel */ },
};

Expand Down
11 changes: 11 additions & 0 deletions drivers/irqchip/irq-bcm7038-l1.c
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,9 @@
#include <linux/irqchip.h>
#include <linux/irqchip/chained_irq.h>
#include <linux/syscore_ops.h>
#ifdef CONFIG_ARM
#include <asm/smp_plat.h>
#endif

#define IRQS_PER_WORD 32
#define REG_BYTES_PER_IRQ_WORD (sizeof(u32) * 4)
Expand Down Expand Up @@ -327,7 +330,11 @@ static int bcm7038_l1_suspend(void)
u32 val;

/* Wakeup interrupt should only come from the boot cpu */
#ifdef CONFIG_SMP
boot_cpu = cpu_logical_map(0);
#else
boot_cpu = 0;
#endif

list_for_each_entry(intc, &bcm7038_l1_intcs_list, list) {
for (word = 0; word < intc->n_words; word++) {
Expand All @@ -347,7 +354,11 @@ static void bcm7038_l1_resume(void)
struct bcm7038_l1_chip *intc;
int boot_cpu, word;

#ifdef CONFIG_SMP
boot_cpu = cpu_logical_map(0);
#else
boot_cpu = 0;
#endif

list_for_each_entry(intc, &bcm7038_l1_intcs_list, list) {
for (word = 0; word < intc->n_words; word++) {
Expand Down
8 changes: 5 additions & 3 deletions drivers/irqchip/irq-bcm7120-l2.c
Original file line number Diff line number Diff line change
Expand Up @@ -143,6 +143,9 @@ static int bcm7120_l2_intc_init_one(struct device_node *dn,

irq_set_chained_handler_and_data(parent_irq,
bcm7120_l2_intc_irq_handle, l1_data);
if (data->can_wake)
enable_irq_wake(parent_irq);

return 0;
}

Expand Down Expand Up @@ -247,6 +250,8 @@ static int __init bcm7120_l2_intc_probe(struct device_node *dn,
if (ret < 0)
goto out_free_l1_data;

data->can_wake = of_property_read_bool(dn, "brcm,irq-can-wake");

for (irq = 0; irq < data->num_parent_irqs; irq++) {
ret = bcm7120_l2_intc_init_one(dn, data, irq, valid_mask);
if (ret)
Expand Down Expand Up @@ -274,9 +279,6 @@ static int __init bcm7120_l2_intc_probe(struct device_node *dn,
goto out_free_domain;
}

if (of_property_read_bool(dn, "brcm,irq-can-wake"))
data->can_wake = true;

for (idx = 0; idx < data->n_words; idx++) {
irq = idx * IRQS_PER_WORD;
gc = irq_get_domain_generic_chip(data->domain, irq);
Expand Down
5 changes: 5 additions & 0 deletions drivers/irqchip/irq-brcmstb-l2.c
Original file line number Diff line number Diff line change
Expand Up @@ -254,6 +254,7 @@ static int __init brcmstb_l2_intc_of_init(struct device_node *np,
*/
data->gc->wake_enabled = 0xffffffff;
ct->chip.irq_set_wake = irq_gc_set_wake;
enable_irq_wake(parent_irq);
}

pr_info("registered L2 intc (%pOF, parent irq: %d)\n", np, parent_irq);
Expand All @@ -275,6 +276,10 @@ static int __init brcmstb_l2_edge_intc_of_init(struct device_node *np,
return brcmstb_l2_intc_of_init(np, parent, &l2_edge_intc_init);
}
IRQCHIP_DECLARE(brcmstb_l2_intc, "brcm,l2-intc", brcmstb_l2_edge_intc_of_init);
IRQCHIP_DECLARE(brcmstb_hif_spi_l2_intc, "brcm,hif-spi-l2-intc",
brcmstb_l2_edge_intc_of_init);
IRQCHIP_DECLARE(brcmstb_upg_aux_aon_l2_intc, "brcm,upg-aux-aon-l2-intc",
brcmstb_l2_edge_intc_of_init);

static int __init brcmstb_l2_lvl_intc_of_init(struct device_node *np,
struct device_node *parent)
Expand Down
14 changes: 9 additions & 5 deletions drivers/irqchip/irq-gic-v3-its.c
Original file line number Diff line number Diff line change
Expand Up @@ -2814,7 +2814,7 @@ static int allocate_vpe_l1_table(void)
if (val & GICR_VPROPBASER_4_1_VALID)
goto out;

gic_data_rdist()->vpe_table_mask = kzalloc(sizeof(cpumask_t), GFP_KERNEL);
gic_data_rdist()->vpe_table_mask = kzalloc(sizeof(cpumask_t), GFP_ATOMIC);
if (!gic_data_rdist()->vpe_table_mask)
return -ENOMEM;

Expand Down Expand Up @@ -2881,7 +2881,7 @@ static int allocate_vpe_l1_table(void)

pr_debug("np = %d, npg = %lld, psz = %d, epp = %d, esz = %d\n",
np, npg, psz, epp, esz);
page = alloc_pages(GFP_KERNEL | __GFP_ZERO, get_order(np * PAGE_SIZE));
page = alloc_pages(GFP_ATOMIC | __GFP_ZERO, get_order(np * PAGE_SIZE));
if (!page)
return -ENOMEM;

Expand Down Expand Up @@ -4079,18 +4079,22 @@ static void its_vpe_4_1_deschedule(struct its_vpe *vpe,
static void its_vpe_4_1_invall(struct its_vpe *vpe)
{
void __iomem *rdbase;
unsigned long flags;
u64 val;
int cpu;

val = GICR_INVALLR_V;
val |= FIELD_PREP(GICR_INVALLR_VPEID, vpe->vpe_id);

/* Target the redistributor this vPE is currently known on */
raw_spin_lock(&gic_data_rdist_cpu(vpe->col_idx)->rd_lock);
rdbase = per_cpu_ptr(gic_rdists->rdist, vpe->col_idx)->rd_base;
cpu = vpe_to_cpuid_lock(vpe, &flags);
raw_spin_lock(&gic_data_rdist_cpu(cpu)->rd_lock);
rdbase = per_cpu_ptr(gic_rdists->rdist, cpu)->rd_base;
gic_write_lpir(val, rdbase + GICR_INVALLR);

wait_for_syncr(rdbase);
raw_spin_unlock(&gic_data_rdist_cpu(vpe->col_idx)->rd_lock);
raw_spin_unlock(&gic_data_rdist_cpu(cpu)->rd_lock);
vpe_to_cpuid_unlock(vpe, flags);
}

static int its_vpe_4_1_set_vcpu_affinity(struct irq_data *d, void *vcpu_info)
Expand Down
2 changes: 1 addition & 1 deletion drivers/irqchip/irq-gic-v3.c
Original file line number Diff line number Diff line change
Expand Up @@ -2116,7 +2116,7 @@ static void __init gic_acpi_setup_kvm_info(void)
}

static int __init
gic_acpi_init(struct acpi_subtable_header *header, const unsigned long end)
gic_acpi_init(union acpi_subtable_headers *header, const unsigned long end)
{
struct acpi_madt_generic_distributor *dist;
struct fwnode_handle *domain_handle;
Expand Down
2 changes: 1 addition & 1 deletion drivers/irqchip/irq-gic.c
Original file line number Diff line number Diff line change
Expand Up @@ -1592,7 +1592,7 @@ static void __init gic_acpi_setup_kvm_info(void)
gic_set_kvm_info(&gic_v2_kvm_info);
}

static int __init gic_v2_acpi_init(struct acpi_subtable_header *header,
static int __init gic_v2_acpi_init(union acpi_subtable_headers *header,
const unsigned long end)
{
struct acpi_madt_generic_distributor *dist;
Expand Down
70 changes: 66 additions & 4 deletions drivers/irqchip/irq-imx-intmux.c
Original file line number Diff line number Diff line change
Expand Up @@ -53,13 +53,16 @@
#include <linux/of_irq.h>
#include <linux/of_platform.h>
#include <linux/spinlock.h>
#include <linux/pm_runtime.h>

#define CHANIER(n) (0x10 + (0x40 * n))
#define CHANIPR(n) (0x20 + (0x40 * n))

#define CHAN_MAX_NUM 0x8

struct intmux_irqchip_data {
struct irq_chip chip;
u32 saved_reg;
int chanidx;
int irq;
struct irq_domain *domain;
Expand Down Expand Up @@ -120,8 +123,10 @@ static struct irq_chip imx_intmux_irq_chip = {
static int imx_intmux_irq_map(struct irq_domain *h, unsigned int irq,
irq_hw_number_t hwirq)
{
irq_set_chip_data(irq, h->host_data);
irq_set_chip_and_handler(irq, &imx_intmux_irq_chip, handle_level_irq);
struct intmux_irqchip_data *data = h->host_data;

irq_set_chip_data(irq, data);
irq_set_chip_and_handler(irq, &data->chip, handle_level_irq);

return 0;
}
Expand Down Expand Up @@ -210,8 +215,7 @@ static int imx_intmux_probe(struct platform_device *pdev)
return -EINVAL;
}

data = devm_kzalloc(&pdev->dev, sizeof(*data) +
channum * sizeof(data->irqchip_data[0]), GFP_KERNEL);
data = devm_kzalloc(&pdev->dev, struct_size(data, irqchip_data, channum), GFP_KERNEL);
if (!data)
return -ENOMEM;

Expand All @@ -232,13 +236,19 @@ static int imx_intmux_probe(struct platform_device *pdev)
data->channum = channum;
raw_spin_lock_init(&data->lock);

pm_runtime_get_noresume(&pdev->dev);
pm_runtime_set_active(&pdev->dev);
pm_runtime_enable(&pdev->dev);

ret = clk_prepare_enable(data->ipg_clk);
if (ret) {
dev_err(&pdev->dev, "failed to enable ipg clk: %d\n", ret);
return ret;
}

for (i = 0; i < channum; i++) {
data->irqchip_data[i].chip = imx_intmux_irq_chip;
data->irqchip_data[i].chip.parent_device = &pdev->dev;
data->irqchip_data[i].chanidx = i;

data->irqchip_data[i].irq = irq_of_parse_and_map(np, i);
Expand Down Expand Up @@ -267,6 +277,12 @@ static int imx_intmux_probe(struct platform_device *pdev)

platform_set_drvdata(pdev, data);

/*
* Let pm_runtime_put() disable clock.
* If CONFIG_PM is not enabled, the clock will stay powered.
*/
pm_runtime_put(&pdev->dev);

return 0;
out:
clk_disable_unprepare(data->ipg_clk);
Expand All @@ -288,11 +304,56 @@ static int imx_intmux_remove(struct platform_device *pdev)
irq_domain_remove(data->irqchip_data[i].domain);
}

pm_runtime_disable(&pdev->dev);

return 0;
}

#ifdef CONFIG_PM
static int imx_intmux_runtime_suspend(struct device *dev)
{
struct intmux_data *data = dev_get_drvdata(dev);
struct intmux_irqchip_data *irqchip_data;
int i;

for (i = 0; i < data->channum; i++) {
irqchip_data = &data->irqchip_data[i];
irqchip_data->saved_reg = readl_relaxed(data->regs + CHANIER(i));
}

clk_disable_unprepare(data->ipg_clk);

return 0;
}

static int imx_intmux_runtime_resume(struct device *dev)
{
struct intmux_data *data = dev_get_drvdata(dev);
struct intmux_irqchip_data *irqchip_data;
int ret, i;

ret = clk_prepare_enable(data->ipg_clk);
if (ret) {
dev_err(dev, "failed to enable ipg clk: %d\n", ret);
return ret;
}

for (i = 0; i < data->channum; i++) {
irqchip_data = &data->irqchip_data[i];
writel_relaxed(irqchip_data->saved_reg, data->regs + CHANIER(i));
}

return 0;
}
#endif

static const struct dev_pm_ops imx_intmux_pm_ops = {
SET_NOIRQ_SYSTEM_SLEEP_PM_OPS(pm_runtime_force_suspend,
pm_runtime_force_resume)
SET_RUNTIME_PM_OPS(imx_intmux_runtime_suspend,
imx_intmux_runtime_resume, NULL)
};

static const struct of_device_id imx_intmux_id[] = {
{ .compatible = "fsl,imx-intmux", },
{ /* sentinel */ },
Expand All @@ -302,6 +363,7 @@ static struct platform_driver imx_intmux_driver = {
.driver = {
.name = "imx-intmux",
.of_match_table = imx_intmux_id,
.pm = &imx_intmux_pm_ops,
},
.probe = imx_intmux_probe,
.remove = imx_intmux_remove,
Expand Down
6 changes: 2 additions & 4 deletions drivers/irqchip/irq-loongson-htpic.c
Original file line number Diff line number Diff line change
Expand Up @@ -93,10 +93,8 @@ int __init htpic_of_init(struct device_node *node, struct device_node *parent)
}

htpic = kzalloc(sizeof(*htpic), GFP_KERNEL);
if (!htpic) {
err = -ENOMEM;
goto out_free;
}
if (!htpic)
return -ENOMEM;

htpic->base = of_iomap(node, 0);
if (!htpic->base) {
Expand Down
Loading

0 comments on commit 3d5128c

Please sign in to comment.