Commit 9cc5b7fb authored by Thomas Gleixner's avatar Thomas Gleixner

Merge tag 'irqchip-5.4' of...

Merge tag 'irqchip-5.4' of git://git.kernel.org/pub/scm/linux/kernel/git/maz/arm-platforms into irq/core

Pull irqchip updates for Linux 5.4 from Marc Zyngier:

 - Large GICv3 updates to support new PPI and SPI ranges
 - Conver all alloc_fwnode() users to use PAs instead of VAs
 - Add support for Marvell's MMP3 irqchip
 - Add support for Amlogic Meson SM1
 - Various cleanups and fixes
parents 101f85b5 c9c96e30
...@@ -115,6 +115,8 @@ stable kernels. ...@@ -115,6 +115,8 @@ stable kernels.
+----------------+-----------------+-----------------+-----------------------------+ +----------------+-----------------+-----------------+-----------------------------+
| Hisilicon | Hip0{6,7} | #161010701 | N/A | | Hisilicon | Hip0{6,7} | #161010701 | N/A |
+----------------+-----------------+-----------------+-----------------------------+ +----------------+-----------------+-----------------+-----------------------------+
| Hisilicon | Hip0{6,7} | #161010803 | N/A |
+----------------+-----------------+-----------------+-----------------------------+
| Hisilicon | Hip07 | #161600802 | HISILICON_ERRATUM_161600802 | | Hisilicon | Hip07 | #161600802 | HISILICON_ERRATUM_161600802 |
+----------------+-----------------+-----------------+-----------------------------+ +----------------+-----------------+-----------------+-----------------------------+
| Hisilicon | Hip08 SMMU PMCG | #162001800 | N/A | | Hisilicon | Hip08 SMMU PMCG | #162001800 | N/A |
......
...@@ -16,6 +16,7 @@ Required properties: ...@@ -16,6 +16,7 @@ Required properties:
"amlogic,meson-gxl-gpio-intc" for GXL SoCs (S905X, S912) "amlogic,meson-gxl-gpio-intc" for GXL SoCs (S905X, S912)
"amlogic,meson-axg-gpio-intc" for AXG SoCs (A113D, A113X) "amlogic,meson-axg-gpio-intc" for AXG SoCs (A113D, A113X)
"amlogic,meson-g12a-gpio-intc" for G12A SoCs (S905D2, S905X2, S905Y2) "amlogic,meson-g12a-gpio-intc" for G12A SoCs (S905D2, S905X2, S905Y2)
"amlogic,meson-sm1-gpio-intc" for SM1 SoCs (S905D3, S905X3, S905Y3)
- reg : Specifies base physical address and size of the registers. - reg : Specifies base physical address and size of the registers.
- interrupt-controller : Identifies the node as an interrupt controller. - interrupt-controller : Identifies the node as an interrupt controller.
- #interrupt-cells : Specifies the number of cells needed to encode an - #interrupt-cells : Specifies the number of cells needed to encode an
......
...@@ -44,11 +44,13 @@ properties: ...@@ -44,11 +44,13 @@ properties:
be at least 4. be at least 4.
The 1st cell is the interrupt type; 0 for SPI interrupts, 1 for PPI The 1st cell is the interrupt type; 0 for SPI interrupts, 1 for PPI
interrupts. Other values are reserved for future use. interrupts, 2 for interrupts in the Extended SPI range, 3 for the
Extended PPI range. Other values are reserved for future use.
The 2nd cell contains the interrupt number for the interrupt type. The 2nd cell contains the interrupt number for the interrupt type.
SPI interrupts are in the range [0-987]. PPI interrupts are in the SPI interrupts are in the range [0-987]. PPI interrupts are in the
range [0-15]. range [0-15]. Extented SPI interrupts are in the range [0-1023].
Extended PPI interrupts are in the range [0-127].
The 3rd cell is the flags, encoded as follows: The 3rd cell is the flags, encoded as follows:
bits[3:0] trigger type and level flags. bits[3:0] trigger type and level flags.
......
...@@ -11,6 +11,9 @@ ...@@ -11,6 +11,9 @@
#define ICU_VIRT_BASE (AXI_VIRT_BASE + 0x82000) #define ICU_VIRT_BASE (AXI_VIRT_BASE + 0x82000)
#define ICU_REG(x) (ICU_VIRT_BASE + (x)) #define ICU_REG(x) (ICU_VIRT_BASE + (x))
#define ICU2_VIRT_BASE (AXI_VIRT_BASE + 0x84000)
#define ICU2_REG(x) (ICU2_VIRT_BASE + (x))
#define ICU_INT_CONF(n) ICU_REG((n) << 2) #define ICU_INT_CONF(n) ICU_REG((n) << 2)
#define ICU_INT_CONF_MASK (0xf) #define ICU_INT_CONF_MASK (0xf)
......
...@@ -400,7 +400,7 @@ static int ixp4xx_gpio_probe(struct platform_device *pdev) ...@@ -400,7 +400,7 @@ static int ixp4xx_gpio_probe(struct platform_device *pdev)
g->fwnode = of_node_to_fwnode(np); g->fwnode = of_node_to_fwnode(np);
} else { } else {
parent = ixp4xx_get_irq_domain(); parent = ixp4xx_get_irq_domain();
g->fwnode = irq_domain_alloc_fwnode(g->base); g->fwnode = irq_domain_alloc_fwnode(&res->start);
if (!g->fwnode) { if (!g->fwnode) {
dev_err(dev, "no domain base\n"); dev_err(dev, "no domain base\n");
return -ENODEV; return -ENODEV;
......
...@@ -41,6 +41,8 @@ void gic_enable_quirks(u32 iidr, const struct gic_quirk *quirks, ...@@ -41,6 +41,8 @@ void gic_enable_quirks(u32 iidr, const struct gic_quirk *quirks,
void *data) void *data)
{ {
for (; quirks->desc; quirks++) { for (; quirks->desc; quirks++) {
if (quirks->compatible)
continue;
if (quirks->iidr != (quirks->mask & iidr)) if (quirks->iidr != (quirks->mask & iidr))
continue; continue;
if (quirks->init(data)) if (quirks->init(data))
...@@ -63,7 +65,7 @@ int gic_configure_irq(unsigned int irq, unsigned int type, ...@@ -63,7 +65,7 @@ int gic_configure_irq(unsigned int irq, unsigned int type,
* for "irq", depending on "type". * for "irq", depending on "type".
*/ */
raw_spin_lock_irqsave(&irq_controller_lock, flags); raw_spin_lock_irqsave(&irq_controller_lock, flags);
val = oldval = readl_relaxed(base + GIC_DIST_CONFIG + confoff); val = oldval = readl_relaxed(base + confoff);
if (type & IRQ_TYPE_LEVEL_MASK) if (type & IRQ_TYPE_LEVEL_MASK)
val &= ~confmask; val &= ~confmask;
else if (type & IRQ_TYPE_EDGE_BOTH) else if (type & IRQ_TYPE_EDGE_BOTH)
...@@ -83,14 +85,10 @@ int gic_configure_irq(unsigned int irq, unsigned int type, ...@@ -83,14 +85,10 @@ int gic_configure_irq(unsigned int irq, unsigned int type,
* does not allow us to set the configuration or we are in a * does not allow us to set the configuration or we are in a
* non-secure mode, and hence it may not be catastrophic. * non-secure mode, and hence it may not be catastrophic.
*/ */
writel_relaxed(val, base + GIC_DIST_CONFIG + confoff); writel_relaxed(val, base + confoff);
if (readl_relaxed(base + GIC_DIST_CONFIG + confoff) != val) { if (readl_relaxed(base + confoff) != val)
if (WARN_ON(irq >= 32)) ret = -EINVAL;
ret = -EINVAL;
else
pr_warn("GIC: PPI%d is secure or misconfigured\n",
irq - 16);
}
raw_spin_unlock_irqrestore(&irq_controller_lock, flags); raw_spin_unlock_irqrestore(&irq_controller_lock, flags);
if (sync_access) if (sync_access)
...@@ -132,26 +130,31 @@ void gic_dist_config(void __iomem *base, int gic_irqs, ...@@ -132,26 +130,31 @@ void gic_dist_config(void __iomem *base, int gic_irqs,
sync_access(); sync_access();
} }
void gic_cpu_config(void __iomem *base, void (*sync_access)(void)) void gic_cpu_config(void __iomem *base, int nr, void (*sync_access)(void))
{ {
int i; int i;
/* /*
* Deal with the banked PPI and SGI interrupts - disable all * Deal with the banked PPI and SGI interrupts - disable all
* PPI interrupts, ensure all SGI interrupts are enabled. * private interrupts. Make sure everything is deactivated.
* Make sure everything is deactivated.
*/ */
writel_relaxed(GICD_INT_EN_CLR_X32, base + GIC_DIST_ACTIVE_CLEAR); for (i = 0; i < nr; i += 32) {
writel_relaxed(GICD_INT_EN_CLR_PPI, base + GIC_DIST_ENABLE_CLEAR); writel_relaxed(GICD_INT_EN_CLR_X32,
writel_relaxed(GICD_INT_EN_SET_SGI, base + GIC_DIST_ENABLE_SET); base + GIC_DIST_ACTIVE_CLEAR + i / 8);
writel_relaxed(GICD_INT_EN_CLR_X32,
base + GIC_DIST_ENABLE_CLEAR + i / 8);
}
/* /*
* Set priority on PPI and SGI interrupts * Set priority on PPI and SGI interrupts
*/ */
for (i = 0; i < 32; i += 4) for (i = 0; i < nr; i += 4)
writel_relaxed(GICD_INT_DEF_PRI_X4, writel_relaxed(GICD_INT_DEF_PRI_X4,
base + GIC_DIST_PRI + i * 4 / 4); base + GIC_DIST_PRI + i * 4 / 4);
/* Ensure all SGI interrupts are now enabled */
writel_relaxed(GICD_INT_EN_SET_SGI, base + GIC_DIST_ENABLE_SET);
if (sync_access) if (sync_access)
sync_access(); sync_access();
} }
...@@ -22,7 +22,7 @@ int gic_configure_irq(unsigned int irq, unsigned int type, ...@@ -22,7 +22,7 @@ int gic_configure_irq(unsigned int irq, unsigned int type,
void __iomem *base, void (*sync_access)(void)); void __iomem *base, void (*sync_access)(void));
void gic_dist_config(void __iomem *base, int gic_irqs, void gic_dist_config(void __iomem *base, int gic_irqs,
void (*sync_access)(void)); void (*sync_access)(void));
void gic_cpu_config(void __iomem *base, void (*sync_access)(void)); void gic_cpu_config(void __iomem *base, int nr, void (*sync_access)(void));
void gic_enable_quirks(u32 iidr, const struct gic_quirk *quirks, void gic_enable_quirks(u32 iidr, const struct gic_quirk *quirks,
void *data); void *data);
void gic_enable_of_quirks(const struct device_node *np, void gic_enable_of_quirks(const struct device_node *np,
......
...@@ -525,7 +525,7 @@ acpi_parse_madt_msi(union acpi_subtable_headers *header, ...@@ -525,7 +525,7 @@ acpi_parse_madt_msi(union acpi_subtable_headers *header,
spi_start, nr_spis); spi_start, nr_spis);
} }
fwnode = irq_domain_alloc_fwnode((void *)m->base_address); fwnode = irq_domain_alloc_fwnode(&res.start);
if (!fwnode) { if (!fwnode) {
pr_err("Unable to allocate GICv2m domain token\n"); pr_err("Unable to allocate GICv2m domain token\n");
return -EINVAL; return -EINVAL;
......
...@@ -2464,6 +2464,7 @@ static int its_alloc_device_irq(struct its_device *dev, int nvecs, irq_hw_number ...@@ -2464,6 +2464,7 @@ static int its_alloc_device_irq(struct its_device *dev, int nvecs, irq_hw_number
{ {
int idx; int idx;
/* Find a free LPI region in lpi_map and allocate them. */
idx = bitmap_find_free_region(dev->event_map.lpi_map, idx = bitmap_find_free_region(dev->event_map.lpi_map,
dev->event_map.nr_lpis, dev->event_map.nr_lpis,
get_count_order(nvecs)); get_count_order(nvecs));
...@@ -2471,7 +2472,6 @@ static int its_alloc_device_irq(struct its_device *dev, int nvecs, irq_hw_number ...@@ -2471,7 +2472,6 @@ static int its_alloc_device_irq(struct its_device *dev, int nvecs, irq_hw_number
return -ENOSPC; return -ENOSPC;
*hwirq = dev->event_map.lpi_base + idx; *hwirq = dev->event_map.lpi_base + idx;
set_bit(idx, dev->event_map.lpi_map);
return 0; return 0;
} }
...@@ -2641,14 +2641,13 @@ static void its_irq_domain_free(struct irq_domain *domain, unsigned int virq, ...@@ -2641,14 +2641,13 @@ static void its_irq_domain_free(struct irq_domain *domain, unsigned int virq,
struct its_node *its = its_dev->its; struct its_node *its = its_dev->its;
int i; int i;
bitmap_release_region(its_dev->event_map.lpi_map,
its_get_event_id(irq_domain_get_irq_data(domain, virq)),
get_count_order(nr_irqs));
for (i = 0; i < nr_irqs; i++) { for (i = 0; i < nr_irqs; i++) {
struct irq_data *data = irq_domain_get_irq_data(domain, struct irq_data *data = irq_domain_get_irq_data(domain,
virq + i); virq + i);
u32 event = its_get_event_id(data);
/* Mark interrupt index as unused */
clear_bit(event, its_dev->event_map.lpi_map);
/* Nuke the entry in the domain */ /* Nuke the entry in the domain */
irq_domain_reset_irq_data(data); irq_domain_reset_irq_data(data);
} }
...@@ -3921,7 +3920,7 @@ static int __init gic_acpi_parse_madt_its(union acpi_subtable_headers *header, ...@@ -3921,7 +3920,7 @@ static int __init gic_acpi_parse_madt_its(union acpi_subtable_headers *header,
res.end = its_entry->base_address + ACPI_GICV3_ITS_MEM_SIZE - 1; res.end = its_entry->base_address + ACPI_GICV3_ITS_MEM_SIZE - 1;
res.flags = IORESOURCE_MEM; res.flags = IORESOURCE_MEM;
dom_handle = irq_domain_alloc_fwnode((void *)its_entry->base_address); dom_handle = irq_domain_alloc_fwnode(&res.start);
if (!dom_handle) { if (!dom_handle) {
pr_err("ITS@%pa: Unable to allocate GICv3 ITS domain token\n", pr_err("ITS@%pa: Unable to allocate GICv3 ITS domain token\n",
&res.start); &res.start);
......
This diff is collapsed.
...@@ -291,6 +291,7 @@ static int gic_set_type(struct irq_data *d, unsigned int type) ...@@ -291,6 +291,7 @@ static int gic_set_type(struct irq_data *d, unsigned int type)
{ {
void __iomem *base = gic_dist_base(d); void __iomem *base = gic_dist_base(d);
unsigned int gicirq = gic_irq(d); unsigned int gicirq = gic_irq(d);
int ret;
/* Interrupt configuration for SGIs can't be changed */ /* Interrupt configuration for SGIs can't be changed */
if (gicirq < 16) if (gicirq < 16)
...@@ -301,7 +302,14 @@ static int gic_set_type(struct irq_data *d, unsigned int type) ...@@ -301,7 +302,14 @@ static int gic_set_type(struct irq_data *d, unsigned int type)
type != IRQ_TYPE_EDGE_RISING) type != IRQ_TYPE_EDGE_RISING)
return -EINVAL; return -EINVAL;
return gic_configure_irq(gicirq, type, base, NULL); ret = gic_configure_irq(gicirq, type, base + GIC_DIST_CONFIG, NULL);
if (ret && gicirq < 32) {
/* Misconfigured PPIs are usually not fatal */
pr_warn("GIC: PPI%d is secure or misconfigured\n", gicirq - 16);
ret = 0;
}
return ret;
} }
static int gic_irq_set_vcpu_affinity(struct irq_data *d, void *vcpu) static int gic_irq_set_vcpu_affinity(struct irq_data *d, void *vcpu)
...@@ -535,7 +543,7 @@ static int gic_cpu_init(struct gic_chip_data *gic) ...@@ -535,7 +543,7 @@ static int gic_cpu_init(struct gic_chip_data *gic)
gic_cpu_map[i] &= ~cpu_mask; gic_cpu_map[i] &= ~cpu_mask;
} }
gic_cpu_config(dist_base, NULL); gic_cpu_config(dist_base, 32, NULL);
writel_relaxed(GICC_INT_PRI_THRESHOLD, base + GIC_CPU_PRIMASK); writel_relaxed(GICC_INT_PRI_THRESHOLD, base + GIC_CPU_PRIMASK);
gic_cpu_if_up(gic); gic_cpu_if_up(gic);
...@@ -1627,7 +1635,7 @@ static int __init gic_v2_acpi_init(struct acpi_subtable_header *header, ...@@ -1627,7 +1635,7 @@ static int __init gic_v2_acpi_init(struct acpi_subtable_header *header,
/* /*
* Initialize GIC instance zero (no multi-GIC support). * Initialize GIC instance zero (no multi-GIC support).
*/ */
domain_handle = irq_domain_alloc_fwnode(gic->raw_dist_base); domain_handle = irq_domain_alloc_fwnode(&dist->base_address);
if (!domain_handle) { if (!domain_handle) {
pr_err("Unable to allocate domain handle\n"); pr_err("Unable to allocate domain handle\n");
gic_teardown(gic); gic_teardown(gic);
......
...@@ -130,7 +130,12 @@ static int hip04_irq_set_type(struct irq_data *d, unsigned int type) ...@@ -130,7 +130,12 @@ static int hip04_irq_set_type(struct irq_data *d, unsigned int type)
raw_spin_lock(&irq_controller_lock); raw_spin_lock(&irq_controller_lock);
ret = gic_configure_irq(irq, type, base, NULL); ret = gic_configure_irq(irq, type, base + GIC_DIST_CONFIG, NULL);
if (ret && irq < 32) {
/* Misconfigured PPIs are usually not fatal */
pr_warn("GIC: PPI%d is secure or misconfigured\n", irq - 16);
ret = 0;
}
raw_spin_unlock(&irq_controller_lock); raw_spin_unlock(&irq_controller_lock);
...@@ -268,7 +273,7 @@ static void hip04_irq_cpu_init(struct hip04_irq_data *intc) ...@@ -268,7 +273,7 @@ static void hip04_irq_cpu_init(struct hip04_irq_data *intc)
if (i != cpu) if (i != cpu)
hip04_cpu_map[i] &= ~cpu_mask; hip04_cpu_map[i] &= ~cpu_mask;
gic_cpu_config(dist_base, NULL); gic_cpu_config(dist_base, 32, NULL);
writel_relaxed(0xf0, base + GIC_CPU_PRIMASK); writel_relaxed(0xf0, base + GIC_CPU_PRIMASK);
writel_relaxed(1, base + GIC_CPU_CTRL); writel_relaxed(1, base + GIC_CPU_CTRL);
......
...@@ -362,10 +362,8 @@ static int pdc_intc_probe(struct platform_device *pdev) ...@@ -362,10 +362,8 @@ static int pdc_intc_probe(struct platform_device *pdev)
} }
for (i = 0; i < priv->nr_perips; ++i) { for (i = 0; i < priv->nr_perips; ++i) {
irq = platform_get_irq(pdev, 1 + i); irq = platform_get_irq(pdev, 1 + i);
if (irq < 0) { if (irq < 0)
dev_err(&pdev->dev, "cannot find perip IRQ #%u\n", i);
return irq; return irq;
}
priv->perip_irqs[i] = irq; priv->perip_irqs[i] = irq;
} }
/* check if too many were provided */ /* check if too many were provided */
...@@ -376,10 +374,8 @@ static int pdc_intc_probe(struct platform_device *pdev) ...@@ -376,10 +374,8 @@ static int pdc_intc_probe(struct platform_device *pdev)
/* Get syswake IRQ number */ /* Get syswake IRQ number */
irq = platform_get_irq(pdev, 0); irq = platform_get_irq(pdev, 0);
if (irq < 0) { if (irq < 0)
dev_err(&pdev->dev, "cannot find syswake IRQ\n");
return irq; return irq;
}
priv->syswake_irq = irq; priv->syswake_irq = irq;
/* Set up an IRQ domain */ /* Set up an IRQ domain */
......
...@@ -319,7 +319,7 @@ void __init ixp4xx_irq_init(resource_size_t irqbase, ...@@ -319,7 +319,7 @@ void __init ixp4xx_irq_init(resource_size_t irqbase,
pr_crit("IXP4XX: could not ioremap interrupt controller\n"); pr_crit("IXP4XX: could not ioremap interrupt controller\n");
return; return;
} }
fwnode = irq_domain_alloc_fwnode(base); fwnode = irq_domain_alloc_fwnode(&irqbase);
if (!fwnode) { if (!fwnode) {
pr_crit("IXP4XX: no domain handle\n"); pr_crit("IXP4XX: no domain handle\n");
return; return;
......
...@@ -164,10 +164,8 @@ static int keystone_irq_probe(struct platform_device *pdev) ...@@ -164,10 +164,8 @@ static int keystone_irq_probe(struct platform_device *pdev)
} }
kirq->irq = platform_get_irq(pdev, 0); kirq->irq = platform_get_irq(pdev, 0);
if (kirq->irq < 0) { if (kirq->irq < 0)
dev_err(dev, "no irq resource %d\n", kirq->irq);
return kirq->irq; return kirq->irq;
}
kirq->dev = dev; kirq->dev = dev;
kirq->mask = ~0x0; kirq->mask = ~0x0;
......
...@@ -24,14 +24,25 @@ ...@@ -24,14 +24,25 @@
#define REG_PIN_47_SEL 0x08 #define REG_PIN_47_SEL 0x08
#define REG_FILTER_SEL 0x0c #define REG_FILTER_SEL 0x0c
#define REG_EDGE_POL_MASK(x) (BIT(x) | BIT(16 + (x))) /*
* Note: The S905X3 datasheet reports that BOTH_EDGE is controlled by
* bits 24 to 31. Tests on the actual HW show that these bits are
* stuck at 0. Bits 8 to 15 are responsive and have the expected
* effect.
*/
#define REG_EDGE_POL_EDGE(x) BIT(x) #define REG_EDGE_POL_EDGE(x) BIT(x)
#define REG_EDGE_POL_LOW(x) BIT(16 + (x)) #define REG_EDGE_POL_LOW(x) BIT(16 + (x))
#define REG_BOTH_EDGE(x) BIT(8 + (x))
#define REG_EDGE_POL_MASK(x) ( \
REG_EDGE_POL_EDGE(x) | \
REG_EDGE_POL_LOW(x) | \
REG_BOTH_EDGE(x))
#define REG_PIN_SEL_SHIFT(x) (((x) % 4) * 8) #define REG_PIN_SEL_SHIFT(x) (((x) % 4) * 8)
#define REG_FILTER_SEL_SHIFT(x) ((x) * 4) #define REG_FILTER_SEL_SHIFT(x) ((x) * 4)
struct meson_gpio_irq_params { struct meson_gpio_irq_params {
unsigned int nr_hwirq; unsigned int nr_hwirq;
bool support_edge_both;
}; };
static const struct meson_gpio_irq_params meson8_params = { static const struct meson_gpio_irq_params meson8_params = {
...@@ -54,6 +65,11 @@ static const struct meson_gpio_irq_params axg_params = { ...@@ -54,6 +65,11 @@ static const struct meson_gpio_irq_params axg_params = {
.nr_hwirq = 100, .nr_hwirq = 100,
}; };
static const struct meson_gpio_irq_params sm1_params = {
.nr_hwirq = 100,
.support_edge_both = true,
};
static const struct of_device_id meson_irq_gpio_matches[] = { static const struct of_device_id meson_irq_gpio_matches[] = {
{ .compatible = "amlogic,meson8-gpio-intc", .data = &meson8_params }, { .compatible = "amlogic,meson8-gpio-intc", .data = &meson8_params },
{ .compatible = "amlogic,meson8b-gpio-intc", .data = &meson8b_params }, { .compatible = "amlogic,meson8b-gpio-intc", .data = &meson8b_params },
...@@ -61,11 +77,12 @@ static const struct of_device_id meson_irq_gpio_matches[] = { ...@@ -61,11 +77,12 @@ static const struct of_device_id meson_irq_gpio_matches[] = {
{ .compatible = "amlogic,meson-gxl-gpio-intc", .data = &gxl_params }, { .compatible = "amlogic,meson-gxl-gpio-intc", .data = &gxl_params },
{ .compatible = "amlogic,meson-axg-gpio-intc", .data = &axg_params }, { .compatible = "amlogic,meson-axg-gpio-intc", .data = &axg_params },
{ .compatible = "amlogic,meson-g12a-gpio-intc", .data = &axg_params }, { .compatible = "amlogic,meson-g12a-gpio-intc", .data = &axg_params },
{ .compatible = "amlogic,meson-sm1-gpio-intc", .data = &sm1_params },
{ } { }
}; };
struct meson_gpio_irq_controller { struct meson_gpio_irq_controller {
unsigned int nr_hwirq; const struct meson_gpio_irq_params *params;
void __iomem *base; void __iomem *base;
u32 channel_irqs[NUM_CHANNEL]; u32 channel_irqs[NUM_CHANNEL];
DECLARE_BITMAP(channel_map, NUM_CHANNEL); DECLARE_BITMAP(channel_map, NUM_CHANNEL);
...@@ -168,14 +185,22 @@ static int meson_gpio_irq_type_setup(struct meson_gpio_irq_controller *ctl, ...@@ -168,14 +185,22 @@ static int meson_gpio_irq_type_setup(struct meson_gpio_irq_controller *ctl,
*/ */
type &= IRQ_TYPE_SENSE_MASK; type &= IRQ_TYPE_SENSE_MASK;
if (type == IRQ_TYPE_EDGE_BOTH) /*
return -EINVAL; * New controller support EDGE_BOTH trigger. This setting takes
* precedence over the other edge/polarity settings
*/
if (type == IRQ_TYPE_EDGE_BOTH) {
if (!ctl->params->support_edge_both)
return -EINVAL;
if (type & (IRQ_TYPE_EDGE_RISING | IRQ_TYPE_EDGE_FALLING)) val |= REG_BOTH_EDGE(idx);
val |= REG_EDGE_POL_EDGE(idx); } else {
if (type & (IRQ_TYPE_EDGE_RISING | IRQ_TYPE_EDGE_FALLING))
val |= REG_EDGE_POL_EDGE(idx);
if (type & (IRQ_TYPE_LEVEL_LOW | IRQ_TYPE_EDGE_FALLING)) if (type & (IRQ_TYPE_LEVEL_LOW | IRQ_TYPE_EDGE_FALLING))
val |= REG_EDGE_POL_LOW(idx); val |= REG_EDGE_POL_LOW(idx);
}
spin_lock(&ctl->lock); spin_lock(&ctl->lock);
...@@ -199,7 +224,7 @@ static unsigned int meson_gpio_irq_type_output(unsigned int type) ...@@ -199,7 +224,7 @@ static unsigned int meson_gpio_irq_type_output(unsigned int type)
*/ */
if (sense & (IRQ_TYPE_LEVEL_HIGH | IRQ_TYPE_LEVEL_LOW)) if (sense & (IRQ_TYPE_LEVEL_HIGH | IRQ_TYPE_LEVEL_LOW))
type |= IRQ_TYPE_LEVEL_HIGH; type |= IRQ_TYPE_LEVEL_HIGH;
else if (sense & (IRQ_TYPE_EDGE_RISING | IRQ_TYPE_EDGE_FALLING)) else
type |= IRQ_TYPE_EDGE_RISING; type |= IRQ_TYPE_EDGE_RISING;
return type; return type;
...@@ -328,15 +353,13 @@ static int __init meson_gpio_irq_parse_dt(struct device_node *node, ...@@ -328,15 +353,13 @@ static int __init meson_gpio_irq_parse_dt(struct device_node *node,
struct meson_gpio_irq_controller *ctl) struct meson_gpio_irq_controller *ctl)
{ {
const struct of_device_id *match; const struct of_device_id *match;
const struct meson_gpio_irq_params *params;
int ret; int ret;
match = of_match_node(meson_irq_gpio_matches, node); match = of_match_node(meson_irq_gpio_matches, node);
if (!match) if (!match)
return -ENODEV; return -ENODEV;
params = match->data; ctl->params = match->data;
ctl->nr_hwirq = params->nr_hwirq;
ret = of_property_read_variable_u32_array(node, ret = of_property_read_variable_u32_array(node,
"amlogic,channel-interrupts", "amlogic,channel-interrupts",
...@@ -385,7 +408,8 @@ static int __init meson_gpio_irq_of_init(struct device_node *node, ...@@ -385,7 +408,8 @@ static int __init meson_gpio_irq_of_init(struct device_node *node,
if (ret) if (ret)
goto free_channel_irqs; goto free_channel_irqs;
domain = irq_domain_create_hierarchy(parent_domain, 0, ctl->nr_hwirq, domain = irq_domain_create_hierarchy(parent_domain, 0,
ctl->params->nr_hwirq,
of_node_to_fwnode(node), of_node_to_fwnode(node),
&meson_gpio_irq_domain_ops, &meson_gpio_irq_domain_ops,
ctl); ctl);
...@@ -396,7 +420,7 @@ static int __init meson_gpio_irq_of_init(struct device_node *node, ...@@ -396,7 +420,7 @@ static int __init meson_gpio_irq_of_init(struct device_node *node,
} }
pr_info("%d to %d gpio interrupt mux initialized\n", pr_info("%d to %d gpio interrupt mux initialized\n",
ctl->nr_hwirq, NUM_CHANNEL); ctl->params->nr_hwirq, NUM_CHANNEL);
return 0; return 0;
......
...@@ -13,6 +13,7 @@ ...@@ -13,6 +13,7 @@
#include <linux/init.h> #include <linux/init.h>
#include <linux/irq.h> #include <linux/irq.h>
#include <linux/irqchip.h> #include <linux/irqchip.h>
#include <linux/irqchip/chained_irq.h>
#include <linux/irqdomain.h> #include <linux/irqdomain.h>
#include <linux/io.h> #include <linux/io.h>
#include <linux/ioport.h> #include <linux/ioport.h>
...@@ -43,6 +44,7 @@ struct icu_chip_data { ...@@ -43,6 +44,7 @@ struct icu_chip_data {
unsigned int conf_enable; unsigned int conf_enable;
unsigned int conf_disable; unsigned int conf_disable;
unsigned int conf_mask; unsigned int conf_mask;
unsigned int conf2_mask;
unsigned int clr_mfp_irq_base; unsigned int clr_mfp_irq_base;
unsigned int clr_mfp_hwirq; unsigned int clr_mfp_hwirq;
struct irq_domain *domain; struct irq_domain *domain;
...@@ -52,9 +54,11 @@ struct mmp_intc_conf { ...@@ -52,9 +54,11 @@ struct mmp_intc_conf {
unsigned int conf_enable; unsigned int conf_enable;
unsigned int conf_disable; unsigned int conf_disable;
unsigned int conf_mask; unsigned int conf_mask;
unsigned int conf2_mask;
}; };
static void __iomem *mmp_icu_base; static void __iomem *mmp_icu_base;
static void __iomem *mmp_icu2_base;
static struct icu_chip_data icu_data[MAX_ICU_NR]; static struct icu_chip_data icu_data[MAX_ICU_NR];
static int max_icu_nr; static int max_icu_nr;
...@@ -97,6 +101,16 @@ static void icu_mask_irq(struct irq_data *d) ...@@ -97,6 +101,16 @@ static void icu_mask_irq(struct irq_data *d)
r &= ~data->conf_mask; r &= ~data->conf_mask;
r |= data->conf_disable; r |= data->conf_disable;
writel_relaxed(r, mmp_icu_base + (hwirq << 2)); writel_relaxed(r, mmp_icu_base + (hwirq << 2));
if (data->conf2_mask) {
/*
* ICU1 (above) only controls PJ4 MP1; if using SMP,
* we need to also mask the MP2 and MM cores via ICU2.
*/
r = readl_relaxed(mmp_icu2_base + (hwirq << 2));
r &= ~data->conf2_mask;
writel_relaxed(r, mmp_icu2_base + (hwirq << 2));
}
} else { } else {
r = readl_relaxed(data->reg_mask) | (1 << hwirq); r = readl_relaxed(data->reg_mask) | (1 << hwirq);
writel_relaxed(r, data->reg_mask); writel_relaxed(r, data->reg_mask);
...@@ -132,11 +146,14 @@ struct irq_chip icu_irq_chip = { ...@@ -132,11 +146,14 @@ struct irq_chip icu_irq_chip = {
static void icu_mux_irq_demux(struct irq_desc *desc) static void icu_mux_irq_demux(struct irq_desc *desc)
{ {
unsigned int irq = irq_desc_get_irq(desc); unsigned int irq = irq_desc_get_irq(desc);
struct irq_chip *chip = irq_desc_get_chip(desc);
struct irq_domain *domain; struct irq_domain *domain;
struct icu_chip_data *data; struct icu_chip_data *data;
int i; int i;
unsigned long mask, status, n; unsigned long mask, status, n;
chained_irq_enter(chip, desc);
for (i = 1; i < max_icu_nr; i++) { for (i = 1; i < max_icu_nr; i++) {
if (irq == icu_data[i].cascade_irq) { if (irq == icu_data[i].cascade_irq) {
domain = icu_data[i].domain; domain = icu_data[i].domain;
...@@ -146,7 +163,7 @@ static void icu_mux_irq_demux(struct irq_desc *desc) ...@@ -146,7 +163,7 @@ static void icu_mux_irq_demux(struct irq_desc *desc)
} }
if (i >= max_icu_nr) { if (i >= max_icu_nr) {
pr_err("Spurious irq %d in MMP INTC\n", irq); pr_err("Spurious irq %d in MMP INTC\n", irq);
return; goto out;
} }
mask = readl_relaxed(data->reg_mask); mask = readl_relaxed(data->reg_mask);
...@@ -158,6 +175,9 @@ static void icu_mux_irq_demux(struct irq_desc *desc) ...@@ -158,6 +175,9 @@ static void icu_mux_irq_demux(struct irq_desc *desc)
generic_handle_irq(icu_data[i].virq_base + n); generic_handle_irq(icu_data[i].virq_base + n);
} }
} }
out:
chained_irq_exit(chip, desc);
} }
static int mmp_irq_domain_map(struct irq_domain *d, unsigned int irq, static int mmp_irq_domain_map(struct irq_domain *d, unsigned int irq,
...@@ -194,6 +214,14 @@ static const struct mmp_intc_conf mmp2_conf = { ...@@ -194,6 +214,14 @@ static const struct mmp_intc_conf mmp2_conf = {
MMP2_ICU_INT_ROUTE_PJ4_FIQ, MMP2_ICU_INT_ROUTE_PJ4_FIQ,
}; };
static struct mmp_intc_conf mmp3_conf = {
.conf_enable = 0x20,
.conf_disable = 0x0,
.conf_mask = MMP2_ICU_INT_ROUTE_PJ4_IRQ |
MMP2_ICU_INT_ROUTE_PJ4_FIQ,
.conf2_mask = 0xf0,
};
static void __exception_irq_entry mmp_handle_irq(struct pt_regs *regs) static void __exception_irq_entry mmp_handle_irq(struct pt_regs *regs)
{ {
int hwirq; int hwirq;
...@@ -395,7 +423,6 @@ static int __init mmp_of_init(struct device_node *node, ...@@ -395,7 +423,6 @@ static int __init mmp_of_init(struct device_node *node,
icu_data[0].conf_enable = mmp_conf.conf_enable; icu_data[0].conf_enable = mmp_conf.conf_enable;
icu_data[0].conf_disable = mmp_conf.conf_disable; icu_data[0].conf_disable = mmp_conf.conf_disable;
icu_data[0].conf_mask = mmp_conf.conf_mask; icu_data[0].conf_mask = mmp_conf.conf_mask;
irq_set_default_host(icu_data[0].domain);
set_handle_irq(mmp_handle_irq); set_handle_irq(mmp_handle_irq);
max_icu_nr = 1; max_icu_nr = 1;
return 0; return 0;
...@@ -414,19 +441,50 @@ static int __init mmp2_of_init(struct device_node *node, ...@@ -414,19 +441,50 @@ static int __init mmp2_of_init(struct device_node *node,
icu_data[0].conf_enable = mmp2_conf.conf_enable; icu_data[0].conf_enable = mmp2_conf.conf_enable;
icu_data[0].conf_disable = mmp2_conf.conf_disable; icu_data[0].conf_disable = mmp2_conf.conf_disable;
icu_data[0].conf_mask = mmp2_conf.conf_mask; icu_data[0].conf_mask = mmp2_conf.conf_mask;
irq_set_default_host(icu_data[0].domain);
set_handle_irq(mmp2_handle_irq); set_handle_irq(mmp2_handle_irq);
max_icu_nr = 1; max_icu_nr = 1;
return 0; return 0;
} }
IRQCHIP_DECLARE(mmp2_intc, "mrvl,mmp2-intc", mmp2_of_init); IRQCHIP_DECLARE(mmp2_intc, "mrvl,mmp2-intc", mmp2_of_init);
static int __init mmp3_of_init(struct device_node *node,
struct device_node *parent)
{
int ret;
mmp_icu2_base = of_iomap(node, 1);
if (!mmp_icu2_base) {
pr_err("Failed to get interrupt controller register #2\n");
return -ENODEV;
}
ret = mmp_init_bases(node);
if (ret < 0) {
iounmap(mmp_icu2_base);
return ret;
}
icu_data[0].conf_enable = mmp3_conf.conf_enable;
icu_data[0].conf_disable = mmp3_conf.conf_disable;
icu_data[0].conf_mask = mmp3_conf.conf_mask;
icu_data[0].conf2_mask = mmp3_conf.conf2_mask;
if (!parent) {
/* This is the main interrupt controller. */
set_handle_irq(mmp2_handle_irq);
}
max_icu_nr = 1;
return 0;
}
IRQCHIP_DECLARE(mmp3_intc, "marvell,mmp3-intc", mmp3_of_init);
static int __init mmp2_mux_of_init(struct device_node *node, static int __init mmp2_mux_of_init(struct device_node *node,
struct device_node *parent) struct device_node *parent)
{ {
struct resource res;
int i, ret, irq, j = 0; int i, ret, irq, j = 0;
u32 nr_irqs, mfp_irq; u32 nr_irqs, mfp_irq;
u32 reg[4];
if (!parent) if (!parent)
return -ENODEV; return -ENODEV;
...@@ -438,18 +496,22 @@ static int __init mmp2_mux_of_init(struct device_node *node, ...@@ -438,18 +496,22 @@ static int __init mmp2_mux_of_init(struct device_node *node,
pr_err("Not found mrvl,intc-nr-irqs property\n"); pr_err("Not found mrvl,intc-nr-irqs property\n");
return -EINVAL; return -EINVAL;
} }
ret = of_address_to_resource(node, 0, &res);
if (ret < 0) { /*
pr_err("Not found reg property\n"); * For historical reasons, the "regs" property of the
return -EINVAL; * mrvl,mmp2-mux-intc is not a regular "regs" property containing
} * addresses on the parent bus, but offsets from the intc's base.
icu_data[i].reg_status = mmp_icu_base + res.start; * That is why we can't use of_address_to_resource() here.
ret = of_address_to_resource(node, 1, &res); */
ret = of_property_read_variable_u32_array(node, "reg", reg,
ARRAY_SIZE(reg),
ARRAY_SIZE(reg));
if (ret < 0) { if (ret < 0) {
pr_err("Not found reg property\n"); pr_err("Not found reg property\n");
return -EINVAL; return -EINVAL;
} }
icu_data[i].reg_mask = mmp_icu_base + res.start; icu_data[i].reg_status = mmp_icu_base + reg[0];
icu_data[i].reg_mask = mmp_icu_base + reg[2];
icu_data[i].cascade_irq = irq_of_parse_and_map(node, 0); icu_data[i].cascade_irq = irq_of_parse_and_map(node, 0);
if (!icu_data[i].cascade_irq) if (!icu_data[i].cascade_irq)
return -EINVAL; return -EINVAL;
......
...@@ -166,7 +166,6 @@ static int uniphier_aidet_probe(struct platform_device *pdev) ...@@ -166,7 +166,6 @@ static int uniphier_aidet_probe(struct platform_device *pdev)
struct device_node *parent_np; struct device_node *parent_np;
struct irq_domain *parent_domain; struct irq_domain *parent_domain;
struct uniphier_aidet_priv *priv; struct uniphier_aidet_priv *priv;
struct resource *res;
parent_np = of_irq_find_parent(dev->of_node); parent_np = of_irq_find_parent(dev->of_node);
if (!parent_np) if (!parent_np)
...@@ -181,8 +180,7 @@ static int uniphier_aidet_probe(struct platform_device *pdev) ...@@ -181,8 +180,7 @@ static int uniphier_aidet_probe(struct platform_device *pdev)
if (!priv) if (!priv)
return -ENOMEM; return -ENOMEM;
res = platform_get_resource(pdev, IORESOURCE_MEM, 0); priv->reg_base = devm_platform_ioremap_resource(pdev, 0);
priv->reg_base = devm_ioremap_resource(dev, res);
if (IS_ERR(priv->reg_base)) if (IS_ERR(priv->reg_base))
return PTR_ERR(priv->reg_base); return PTR_ERR(priv->reg_base);
......
...@@ -248,10 +248,8 @@ static int __init combiner_probe(struct platform_device *pdev) ...@@ -248,10 +248,8 @@ static int __init combiner_probe(struct platform_device *pdev)
return err; return err;
combiner->parent_irq = platform_get_irq(pdev, 0); combiner->parent_irq = platform_get_irq(pdev, 0);
if (combiner->parent_irq <= 0) { if (combiner->parent_irq <= 0)
dev_err(&pdev->dev, "Error getting IRQ resource\n");
return -EPROBE_DEFER; return -EPROBE_DEFER;
}
combiner->domain = irq_domain_create_linear(pdev->dev.fwnode, combiner->nirqs, combiner->domain = irq_domain_create_linear(pdev->dev.fwnode, combiner->nirqs,
&domain_ops, combiner); &domain_ops, combiner);
......
...@@ -2521,6 +2521,7 @@ static int hv_pci_probe(struct hv_device *hdev, ...@@ -2521,6 +2521,7 @@ static int hv_pci_probe(struct hv_device *hdev,
const struct hv_vmbus_device_id *dev_id) const struct hv_vmbus_device_id *dev_id)
{ {
struct hv_pcibus_device *hbus; struct hv_pcibus_device *hbus;
char *name;
int ret; int ret;
/* /*
...@@ -2589,7 +2590,14 @@ static int hv_pci_probe(struct hv_device *hdev, ...@@ -2589,7 +2590,14 @@ static int hv_pci_probe(struct hv_device *hdev,
goto free_config; goto free_config;
} }
hbus->sysdata.fwnode = irq_domain_alloc_fwnode(hbus); name = kasprintf(GFP_KERNEL, "%pUL", &hdev->dev_instance);
if (!name) {
ret = -ENOMEM;
goto unmap;
}
hbus->sysdata.fwnode = irq_domain_alloc_named_fwnode(name);
kfree(name);
if (!hbus->sysdata.fwnode) { if (!hbus->sysdata.fwnode) {
ret = -ENOMEM; ret = -ENOMEM;
goto unmap; goto unmap;
......
...@@ -30,10 +30,22 @@ ...@@ -30,10 +30,22 @@
#define GICD_ICFGR 0x0C00 #define GICD_ICFGR 0x0C00
#define GICD_IGRPMODR 0x0D00 #define GICD_IGRPMODR 0x0D00
#define GICD_NSACR 0x0E00 #define GICD_NSACR 0x0E00
#define GICD_IGROUPRnE 0x1000
#define GICD_ISENABLERnE 0x1200
#define GICD_ICENABLERnE 0x1400
#define GICD_ISPENDRnE 0x1600
#define GICD_ICPENDRnE 0x1800
#define GICD_ISACTIVERnE 0x1A00
#define GICD_ICACTIVERnE 0x1C00
#define GICD_IPRIORITYRnE 0x2000
#define GICD_ICFGRnE 0x3000
#define GICD_IROUTER 0x6000 #define GICD_IROUTER 0x6000
#define GICD_IROUTERnE 0x8000
#define GICD_IDREGS 0xFFD0 #define GICD_IDREGS 0xFFD0
#define GICD_PIDR2 0xFFE8 #define GICD_PIDR2 0xFFE8
#define ESPI_BASE_INTID 4096
/* /*
* Those registers are actually from GICv2, but the spec demands that they * Those registers are actually from GICv2, but the spec demands that they
* are implemented as RES0 if ARE is 1 (which we do in KVM's emulated GICv3). * are implemented as RES0 if ARE is 1 (which we do in KVM's emulated GICv3).
...@@ -69,10 +81,13 @@ ...@@ -69,10 +81,13 @@
#define GICD_TYPER_RSS (1U << 26) #define GICD_TYPER_RSS (1U << 26)
#define GICD_TYPER_LPIS (1U << 17) #define GICD_TYPER_LPIS (1U << 17)
#define GICD_TYPER_MBIS (1U << 16) #define GICD_TYPER_MBIS (1U << 16)
#define GICD_TYPER_ESPI (1U << 8)
#define GICD_TYPER_ID_BITS(typer) ((((typer) >> 19) & 0x1f) + 1) #define GICD_TYPER_ID_BITS(typer) ((((typer) >> 19) & 0x1f) + 1)
#define GICD_TYPER_NUM_LPIS(typer) ((((typer) >> 11) & 0x1f) + 1) #define GICD_TYPER_NUM_LPIS(typer) ((((typer) >> 11) & 0x1f) + 1)
#define GICD_TYPER_IRQS(typer) ((((typer) & 0x1f) + 1) * 32) #define GICD_TYPER_SPIS(typer) ((((typer) & 0x1f) + 1) * 32)
#define GICD_TYPER_ESPIS(typer) \
(((typer) & GICD_TYPER_ESPI) ? GICD_TYPER_SPIS((typer) >> 27) : 0)
#define GICD_IROUTER_SPI_MODE_ONE (0U << 31) #define GICD_IROUTER_SPI_MODE_ONE (0U << 31)
#define GICD_IROUTER_SPI_MODE_ANY (1U << 31) #define GICD_IROUTER_SPI_MODE_ANY (1U << 31)
...@@ -109,6 +124,18 @@ ...@@ -109,6 +124,18 @@
#define GICR_TYPER_CPU_NUMBER(r) (((r) >> 8) & 0xffff) #define GICR_TYPER_CPU_NUMBER(r) (((r) >> 8) & 0xffff)
#define EPPI_BASE_INTID 1056
#define GICR_TYPER_NR_PPIS(r) \
({ \
unsigned int __ppinum = ((r) >> 27) & 0x1f; \
unsigned int __nr_ppis = 16; \
if (__ppinum == 1 || __ppinum == 2) \
__nr_ppis += __ppinum * 32; \
\
__nr_ppis; \
})
#define GICR_WAKER_ProcessorSleep (1U << 1) #define GICR_WAKER_ProcessorSleep (1U << 1)
#define GICR_WAKER_ChildrenAsleep (1U << 2) #define GICR_WAKER_ChildrenAsleep (1U << 2)
...@@ -469,6 +496,7 @@ ...@@ -469,6 +496,7 @@
#define ICC_CTLR_EL1_A3V_SHIFT 15 #define ICC_CTLR_EL1_A3V_SHIFT 15
#define ICC_CTLR_EL1_A3V_MASK (0x1 << ICC_CTLR_EL1_A3V_SHIFT) #define ICC_CTLR_EL1_A3V_MASK (0x1 << ICC_CTLR_EL1_A3V_SHIFT)
#define ICC_CTLR_EL1_RSS (0x1 << 18) #define ICC_CTLR_EL1_RSS (0x1 << 18)
#define ICC_CTLR_EL1_ExtRange (0x1 << 19)
#define ICC_PMR_EL1_SHIFT 0 #define ICC_PMR_EL1_SHIFT 0
#define ICC_PMR_EL1_MASK (0xff << ICC_PMR_EL1_SHIFT) #define ICC_PMR_EL1_MASK (0xff << ICC_PMR_EL1_SHIFT)
#define ICC_BPR0_EL1_SHIFT 0 #define ICC_BPR0_EL1_SHIFT 0
......
...@@ -4,6 +4,9 @@ ...@@ -4,6 +4,9 @@
* Author: Marc Zyngier <marc.zyngier@arm.com> * Author: Marc Zyngier <marc.zyngier@arm.com>
*/ */
#ifndef __LINUX_IRQCHIP_IRQ_PARTITION_PERCPU_H
#define __LINUX_IRQCHIP_IRQ_PARTITION_PERCPU_H
#include <linux/fwnode.h> #include <linux/fwnode.h>
#include <linux/cpumask.h> #include <linux/cpumask.h>
#include <linux/irqdomain.h> #include <linux/irqdomain.h>
...@@ -46,3 +49,5 @@ struct irq_domain *partition_get_domain(struct partition_desc *dsc) ...@@ -46,3 +49,5 @@ struct irq_domain *partition_get_domain(struct partition_desc *dsc)
return NULL; return NULL;
} }
#endif #endif
#endif /* __LINUX_IRQCHIP_IRQ_PARTITION_PERCPU_H */
...@@ -220,7 +220,7 @@ static inline struct device_node *irq_domain_get_of_node(struct irq_domain *d) ...@@ -220,7 +220,7 @@ static inline struct device_node *irq_domain_get_of_node(struct irq_domain *d)
#ifdef CONFIG_IRQ_DOMAIN #ifdef CONFIG_IRQ_DOMAIN
struct fwnode_handle *__irq_domain_alloc_fwnode(unsigned int type, int id, struct fwnode_handle *__irq_domain_alloc_fwnode(unsigned int type, int id,
const char *name, void *data); const char *name, phys_addr_t *pa);
enum { enum {
IRQCHIP_FWNODE_REAL, IRQCHIP_FWNODE_REAL,
...@@ -241,9 +241,9 @@ struct fwnode_handle *irq_domain_alloc_named_id_fwnode(const char *name, int id) ...@@ -241,9 +241,9 @@ struct fwnode_handle *irq_domain_alloc_named_id_fwnode(const char *name, int id)
NULL); NULL);
} }
static inline struct fwnode_handle *irq_domain_alloc_fwnode(void *data) static inline struct fwnode_handle *irq_domain_alloc_fwnode(phys_addr_t *pa)
{ {
return __irq_domain_alloc_fwnode(IRQCHIP_FWNODE_REAL, 0, NULL, data); return __irq_domain_alloc_fwnode(IRQCHIP_FWNODE_REAL, 0, NULL, pa);
} }
void irq_domain_free_fwnode(struct fwnode_handle *fwnode); void irq_domain_free_fwnode(struct fwnode_handle *fwnode);
......
...@@ -31,7 +31,7 @@ struct irqchip_fwid { ...@@ -31,7 +31,7 @@ struct irqchip_fwid {
struct fwnode_handle fwnode; struct fwnode_handle fwnode;
unsigned int type; unsigned int type;
char *name; char *name;
void *data; phys_addr_t *pa;
}; };
#ifdef CONFIG_GENERIC_IRQ_DEBUGFS #ifdef CONFIG_GENERIC_IRQ_DEBUGFS
...@@ -62,7 +62,8 @@ EXPORT_SYMBOL_GPL(irqchip_fwnode_ops); ...@@ -62,7 +62,8 @@ EXPORT_SYMBOL_GPL(irqchip_fwnode_ops);
* domain struct. * domain struct.
*/ */
struct fwnode_handle *__irq_domain_alloc_fwnode(unsigned int type, int id, struct fwnode_handle *__irq_domain_alloc_fwnode(unsigned int type, int id,
const char *name, void *data) const char *name,
phys_addr_t *pa)
{ {
struct irqchip_fwid *fwid; struct irqchip_fwid *fwid;
char *n; char *n;
...@@ -77,7 +78,7 @@ struct fwnode_handle *__irq_domain_alloc_fwnode(unsigned int type, int id, ...@@ -77,7 +78,7 @@ struct fwnode_handle *__irq_domain_alloc_fwnode(unsigned int type, int id,
n = kasprintf(GFP_KERNEL, "%s-%d", name, id); n = kasprintf(GFP_KERNEL, "%s-%d", name, id);
break; break;
default: default:
n = kasprintf(GFP_KERNEL, "irqchip@%p", data); n = kasprintf(GFP_KERNEL, "irqchip@%pa", pa);
break; break;
} }
...@@ -89,7 +90,7 @@ struct fwnode_handle *__irq_domain_alloc_fwnode(unsigned int type, int id, ...@@ -89,7 +90,7 @@ struct fwnode_handle *__irq_domain_alloc_fwnode(unsigned int type, int id,
fwid->type = type; fwid->type = type;
fwid->name = n; fwid->name = n;
fwid->data = data; fwid->pa = pa;
fwid->fwnode.ops = &irqchip_fwnode_ops; fwid->fwnode.ops = &irqchip_fwnode_ops;
return &fwid->fwnode; return &fwid->fwnode;
} }
...@@ -148,6 +149,7 @@ struct irq_domain *__irq_domain_add(struct fwnode_handle *fwnode, int size, ...@@ -148,6 +149,7 @@ struct irq_domain *__irq_domain_add(struct fwnode_handle *fwnode, int size,
switch (fwid->type) { switch (fwid->type) {
case IRQCHIP_FWNODE_NAMED: case IRQCHIP_FWNODE_NAMED:
case IRQCHIP_FWNODE_NAMED_ID: case IRQCHIP_FWNODE_NAMED_ID:
domain->fwnode = fwnode;
domain->name = kstrdup(fwid->name, GFP_KERNEL); domain->name = kstrdup(fwid->name, GFP_KERNEL);
if (!domain->name) { if (!domain->name) {
kfree(domain); kfree(domain);
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment