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.
+----------------+-----------------+-----------------+-----------------------------+
| Hisilicon | Hip0{6,7} | #161010701 | N/A |
+----------------+-----------------+-----------------+-----------------------------+
| Hisilicon | Hip0{6,7} | #161010803 | N/A |
+----------------+-----------------+-----------------+-----------------------------+
| Hisilicon | Hip07 | #161600802 | HISILICON_ERRATUM_161600802 |
+----------------+-----------------+-----------------+-----------------------------+
| Hisilicon | Hip08 SMMU PMCG | #162001800 | N/A |
......
......@@ -16,6 +16,7 @@ Required properties:
"amlogic,meson-gxl-gpio-intc" for GXL SoCs (S905X, S912)
"amlogic,meson-axg-gpio-intc" for AXG SoCs (A113D, A113X)
"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.
- interrupt-controller : Identifies the node as an interrupt controller.
- #interrupt-cells : Specifies the number of cells needed to encode an
......
......@@ -44,11 +44,13 @@ properties:
be at least 4.
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.
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:
bits[3:0] trigger type and level flags.
......
......@@ -11,6 +11,9 @@
#define ICU_VIRT_BASE (AXI_VIRT_BASE + 0x82000)
#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_MASK (0xf)
......
......@@ -400,7 +400,7 @@ static int ixp4xx_gpio_probe(struct platform_device *pdev)
g->fwnode = of_node_to_fwnode(np);
} else {
parent = ixp4xx_get_irq_domain();
g->fwnode = irq_domain_alloc_fwnode(g->base);
g->fwnode = irq_domain_alloc_fwnode(&res->start);
if (!g->fwnode) {
dev_err(dev, "no domain base\n");
return -ENODEV;
......
......@@ -41,6 +41,8 @@ void gic_enable_quirks(u32 iidr, const struct gic_quirk *quirks,
void *data)
{
for (; quirks->desc; quirks++) {
if (quirks->compatible)
continue;
if (quirks->iidr != (quirks->mask & iidr))
continue;
if (quirks->init(data))
......@@ -63,7 +65,7 @@ int gic_configure_irq(unsigned int irq, unsigned int type,
* for "irq", depending on "type".
*/
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)
val &= ~confmask;
else if (type & IRQ_TYPE_EDGE_BOTH)
......@@ -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
* non-secure mode, and hence it may not be catastrophic.
*/
writel_relaxed(val, base + GIC_DIST_CONFIG + confoff);
if (readl_relaxed(base + GIC_DIST_CONFIG + confoff) != val) {
if (WARN_ON(irq >= 32))
ret = -EINVAL;
else
pr_warn("GIC: PPI%d is secure or misconfigured\n",
irq - 16);
}
writel_relaxed(val, base + confoff);
if (readl_relaxed(base + confoff) != val)
ret = -EINVAL;
raw_spin_unlock_irqrestore(&irq_controller_lock, flags);
if (sync_access)
......@@ -132,26 +130,31 @@ void gic_dist_config(void __iomem *base, int gic_irqs,
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;
/*
* Deal with the banked PPI and SGI interrupts - disable all
* PPI interrupts, ensure all SGI interrupts are enabled.
* Make sure everything is deactivated.
* private interrupts. Make sure everything is deactivated.
*/
writel_relaxed(GICD_INT_EN_CLR_X32, base + GIC_DIST_ACTIVE_CLEAR);
writel_relaxed(GICD_INT_EN_CLR_PPI, base + GIC_DIST_ENABLE_CLEAR);
writel_relaxed(GICD_INT_EN_SET_SGI, base + GIC_DIST_ENABLE_SET);
for (i = 0; i < nr; i += 32) {
writel_relaxed(GICD_INT_EN_CLR_X32,
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
*/
for (i = 0; i < 32; i += 4)
for (i = 0; i < nr; i += 4)
writel_relaxed(GICD_INT_DEF_PRI_X4,
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)
sync_access();
}
......@@ -22,7 +22,7 @@ int gic_configure_irq(unsigned int irq, unsigned int type,
void __iomem *base, void (*sync_access)(void));
void gic_dist_config(void __iomem *base, int gic_irqs,
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 *data);
void gic_enable_of_quirks(const struct device_node *np,
......
......@@ -525,7 +525,7 @@ acpi_parse_madt_msi(union acpi_subtable_headers *header,
spi_start, nr_spis);
}
fwnode = irq_domain_alloc_fwnode((void *)m->base_address);
fwnode = irq_domain_alloc_fwnode(&res.start);
if (!fwnode) {
pr_err("Unable to allocate GICv2m domain token\n");
return -EINVAL;
......
......@@ -2464,6 +2464,7 @@ static int its_alloc_device_irq(struct its_device *dev, int nvecs, irq_hw_number
{
int idx;
/* Find a free LPI region in lpi_map and allocate them. */
idx = bitmap_find_free_region(dev->event_map.lpi_map,
dev->event_map.nr_lpis,
get_count_order(nvecs));
......@@ -2471,7 +2472,6 @@ static int its_alloc_device_irq(struct its_device *dev, int nvecs, irq_hw_number
return -ENOSPC;
*hwirq = dev->event_map.lpi_base + idx;
set_bit(idx, dev->event_map.lpi_map);
return 0;
}
......@@ -2641,14 +2641,13 @@ static void its_irq_domain_free(struct irq_domain *domain, unsigned int virq,
struct its_node *its = its_dev->its;
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++) {
struct irq_data *data = irq_domain_get_irq_data(domain,
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 */
irq_domain_reset_irq_data(data);
}
......@@ -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.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) {
pr_err("ITS@%pa: Unable to allocate GICv3 ITS domain token\n",
&res.start);
......
This diff is collapsed.
......@@ -291,6 +291,7 @@ static int gic_set_type(struct irq_data *d, unsigned int type)
{
void __iomem *base = gic_dist_base(d);
unsigned int gicirq = gic_irq(d);
int ret;
/* Interrupt configuration for SGIs can't be changed */
if (gicirq < 16)
......@@ -301,7 +302,14 @@ static int gic_set_type(struct irq_data *d, unsigned int type)
type != IRQ_TYPE_EDGE_RISING)
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)
......@@ -535,7 +543,7 @@ static int gic_cpu_init(struct gic_chip_data *gic)
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);
gic_cpu_if_up(gic);
......@@ -1627,7 +1635,7 @@ static int __init gic_v2_acpi_init(struct acpi_subtable_header *header,
/*
* 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) {
pr_err("Unable to allocate domain handle\n");
gic_teardown(gic);
......
......@@ -130,7 +130,12 @@ static int hip04_irq_set_type(struct irq_data *d, unsigned int type)
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);
......@@ -268,7 +273,7 @@ static void hip04_irq_cpu_init(struct hip04_irq_data *intc)
if (i != cpu)
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(1, base + GIC_CPU_CTRL);
......
......@@ -362,10 +362,8 @@ static int pdc_intc_probe(struct platform_device *pdev)
}
for (i = 0; i < priv->nr_perips; ++i) {
irq = platform_get_irq(pdev, 1 + i);
if (irq < 0) {
dev_err(&pdev->dev, "cannot find perip IRQ #%u\n", i);
if (irq < 0)
return irq;
}
priv->perip_irqs[i] = irq;
}
/* check if too many were provided */
......@@ -376,10 +374,8 @@ static int pdc_intc_probe(struct platform_device *pdev)
/* Get syswake IRQ number */
irq = platform_get_irq(pdev, 0);
if (irq < 0) {
dev_err(&pdev->dev, "cannot find syswake IRQ\n");
if (irq < 0)
return irq;
}
priv->syswake_irq = irq;
/* Set up an IRQ domain */
......
......@@ -319,7 +319,7 @@ void __init ixp4xx_irq_init(resource_size_t irqbase,
pr_crit("IXP4XX: could not ioremap interrupt controller\n");
return;
}
fwnode = irq_domain_alloc_fwnode(base);
fwnode = irq_domain_alloc_fwnode(&irqbase);
if (!fwnode) {
pr_crit("IXP4XX: no domain handle\n");
return;
......
......@@ -164,10 +164,8 @@ static int keystone_irq_probe(struct platform_device *pdev)
}
kirq->irq = platform_get_irq(pdev, 0);
if (kirq->irq < 0) {
dev_err(dev, "no irq resource %d\n", kirq->irq);
if (kirq->irq < 0)
return kirq->irq;
}
kirq->dev = dev;
kirq->mask = ~0x0;
......
......@@ -24,14 +24,25 @@
#define REG_PIN_47_SEL 0x08
#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_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_FILTER_SEL_SHIFT(x) ((x) * 4)
struct meson_gpio_irq_params {
unsigned int nr_hwirq;
bool support_edge_both;
};
static const struct meson_gpio_irq_params meson8_params = {
......@@ -54,6 +65,11 @@ static const struct meson_gpio_irq_params axg_params = {
.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[] = {
{ .compatible = "amlogic,meson8-gpio-intc", .data = &meson8_params },
{ .compatible = "amlogic,meson8b-gpio-intc", .data = &meson8b_params },
......@@ -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-axg-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 {
unsigned int nr_hwirq;
const struct meson_gpio_irq_params *params;
void __iomem *base;
u32 channel_irqs[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,
*/
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_EDGE_POL_EDGE(idx);
val |= REG_BOTH_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))
val |= REG_EDGE_POL_LOW(idx);
if (type & (IRQ_TYPE_LEVEL_LOW | IRQ_TYPE_EDGE_FALLING))
val |= REG_EDGE_POL_LOW(idx);
}
spin_lock(&ctl->lock);
......@@ -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))
type |= IRQ_TYPE_LEVEL_HIGH;
else if (sense & (IRQ_TYPE_EDGE_RISING | IRQ_TYPE_EDGE_FALLING))
else
type |= IRQ_TYPE_EDGE_RISING;
return type;
......@@ -328,15 +353,13 @@ static int __init meson_gpio_irq_parse_dt(struct device_node *node,
struct meson_gpio_irq_controller *ctl)
{
const struct of_device_id *match;
const struct meson_gpio_irq_params *params;
int ret;
match = of_match_node(meson_irq_gpio_matches, node);
if (!match)
return -ENODEV;
params = match->data;
ctl->nr_hwirq = params->nr_hwirq;
ctl->params = match->data;
ret = of_property_read_variable_u32_array(node,
"amlogic,channel-interrupts",
......@@ -385,7 +408,8 @@ static int __init meson_gpio_irq_of_init(struct device_node *node,
if (ret)
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),
&meson_gpio_irq_domain_ops,
ctl);
......@@ -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",
ctl->nr_hwirq, NUM_CHANNEL);
ctl->params->nr_hwirq, NUM_CHANNEL);
return 0;
......
......@@ -13,6 +13,7 @@
#include <linux/init.h>
#include <linux/irq.h>
#include <linux/irqchip.h>
#include <linux/irqchip/chained_irq.h>
#include <linux/irqdomain.h>
#include <linux/io.h>
#include <linux/ioport.h>
......@@ -43,6 +44,7 @@ struct icu_chip_data {
unsigned int conf_enable;
unsigned int conf_disable;
unsigned int conf_mask;
unsigned int conf2_mask;
unsigned int clr_mfp_irq_base;
unsigned int clr_mfp_hwirq;
struct irq_domain *domain;
......@@ -52,9 +54,11 @@ struct mmp_intc_conf {
unsigned int conf_enable;
unsigned int conf_disable;
unsigned int conf_mask;
unsigned int conf2_mask;
};
static void __iomem *mmp_icu_base;
static void __iomem *mmp_icu2_base;
static struct icu_chip_data icu_data[MAX_ICU_NR];
static int max_icu_nr;
......@@ -97,6 +101,16 @@ static void icu_mask_irq(struct irq_data *d)
r &= ~data->conf_mask;
r |= data->conf_disable;
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 {
r = readl_relaxed(data->reg_mask) | (1 << hwirq);
writel_relaxed(r, data->reg_mask);
......@@ -132,11 +146,14 @@ struct irq_chip icu_irq_chip = {
static void icu_mux_irq_demux(struct irq_desc *desc)
{
unsigned int irq = irq_desc_get_irq(desc);
struct irq_chip *chip = irq_desc_get_chip(desc);
struct irq_domain *domain;
struct icu_chip_data *data;
int i;
unsigned long mask, status, n;
chained_irq_enter(chip, desc);
for (i = 1; i < max_icu_nr; i++) {
if (irq == icu_data[i].cascade_irq) {
domain = icu_data[i].domain;
......@@ -146,7 +163,7 @@ static void icu_mux_irq_demux(struct irq_desc *desc)
}
if (i >= max_icu_nr) {
pr_err("Spurious irq %d in MMP INTC\n", irq);
return;
goto out;
}
mask = readl_relaxed(data->reg_mask);
......@@ -158,6 +175,9 @@ static void icu_mux_irq_demux(struct irq_desc *desc)
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,
......@@ -194,6 +214,14 @@ static const struct mmp_intc_conf mmp2_conf = {
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)
{
int hwirq;
......@@ -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_disable = mmp_conf.conf_disable;
icu_data[0].conf_mask = mmp_conf.conf_mask;
irq_set_default_host(icu_data[0].domain);
set_handle_irq(mmp_handle_irq);
max_icu_nr = 1;
return 0;
......@@ -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_disable = mmp2_conf.conf_disable;
icu_data[0].conf_mask = mmp2_conf.conf_mask;
irq_set_default_host(icu_data[0].domain);
set_handle_irq(mmp2_handle_irq);
max_icu_nr = 1;
return 0;
}
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,
struct device_node *parent)
{
struct resource res;
int i, ret, irq, j = 0;
u32 nr_irqs, mfp_irq;
u32 reg[4];
if (!parent)
return -ENODEV;
......@@ -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");
return -EINVAL;
}
ret = of_address_to_resource(node, 0, &res);
if (ret < 0) {
pr_err("Not found reg property\n");
return -EINVAL;
}
icu_data[i].reg_status = mmp_icu_base + res.start;
ret = of_address_to_resource(node, 1, &res);
/*
* For historical reasons, the "regs" property of the
* mrvl,mmp2-mux-intc is not a regular "regs" property containing
* addresses on the parent bus, but offsets from the intc's base.
* That is why we can't use of_address_to_resource() here.
*/
ret = of_property_read_variable_u32_array(node, "reg", reg,
ARRAY_SIZE(reg),
ARRAY_SIZE(reg));
if (ret < 0) {
pr_err("Not found reg property\n");
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);
if (!icu_data[i].cascade_irq)
return -EINVAL;
......
......@@ -166,7 +166,6 @@ static int uniphier_aidet_probe(struct platform_device *pdev)
struct device_node *parent_np;
struct irq_domain *parent_domain;
struct uniphier_aidet_priv *priv;
struct resource *res;
parent_np = of_irq_find_parent(dev->of_node);
if (!parent_np)
......@@ -181,8 +180,7 @@ static int uniphier_aidet_probe(struct platform_device *pdev)
if (!priv)
return -ENOMEM;
res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
priv->reg_base = devm_ioremap_resource(dev, res);
priv->reg_base = devm_platform_ioremap_resource(pdev, 0);
if (IS_ERR(priv->reg_base))
return PTR_ERR(priv->reg_base);
......
......@@ -248,10 +248,8 @@ static int __init combiner_probe(struct platform_device *pdev)
return err;
combiner->parent_irq = platform_get_irq(pdev, 0);
if (combiner->parent_irq <= 0) {
dev_err(&pdev->dev, "Error getting IRQ resource\n");
if (combiner->parent_irq <= 0)
return -EPROBE_DEFER;
}
combiner->domain = irq_domain_create_linear(pdev->dev.fwnode, combiner->nirqs,
&domain_ops, combiner);
......
......@@ -2521,6 +2521,7 @@ static int hv_pci_probe(struct hv_device *hdev,
const struct hv_vmbus_device_id *dev_id)
{
struct hv_pcibus_device *hbus;
char *name;
int ret;
/*
......@@ -2589,7 +2590,14 @@ static int hv_pci_probe(struct hv_device *hdev,
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) {
ret = -ENOMEM;
goto unmap;
......
......@@ -30,10 +30,22 @@
#define GICD_ICFGR 0x0C00
#define GICD_IGRPMODR 0x0D00
#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_IROUTERnE 0x8000
#define GICD_IDREGS 0xFFD0
#define GICD_PIDR2 0xFFE8
#define ESPI_BASE_INTID 4096
/*
* 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).
......@@ -69,10 +81,13 @@
#define GICD_TYPER_RSS (1U << 26)
#define GICD_TYPER_LPIS (1U << 17)
#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_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_ANY (1U << 31)
......@@ -109,6 +124,18 @@
#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_ChildrenAsleep (1U << 2)
......@@ -469,6 +496,7 @@
#define ICC_CTLR_EL1_A3V_SHIFT 15
#define ICC_CTLR_EL1_A3V_MASK (0x1 << ICC_CTLR_EL1_A3V_SHIFT)
#define ICC_CTLR_EL1_RSS (0x1 << 18)
#define ICC_CTLR_EL1_ExtRange (0x1 << 19)
#define ICC_PMR_EL1_SHIFT 0
#define ICC_PMR_EL1_MASK (0xff << ICC_PMR_EL1_SHIFT)
#define ICC_BPR0_EL1_SHIFT 0
......
......@@ -4,6 +4,9 @@
* 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/cpumask.h>
#include <linux/irqdomain.h>
......@@ -46,3 +49,5 @@ struct irq_domain *partition_get_domain(struct partition_desc *dsc)
return NULL;
}
#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)
#ifdef CONFIG_IRQ_DOMAIN
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 {
IRQCHIP_FWNODE_REAL,
......@@ -241,9 +241,9 @@ struct fwnode_handle *irq_domain_alloc_named_id_fwnode(const char *name, int id)
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);
......
......@@ -31,7 +31,7 @@ struct irqchip_fwid {
struct fwnode_handle fwnode;
unsigned int type;
char *name;
void *data;
phys_addr_t *pa;
};
#ifdef CONFIG_GENERIC_IRQ_DEBUGFS
......@@ -62,7 +62,8 @@ EXPORT_SYMBOL_GPL(irqchip_fwnode_ops);
* domain struct.
*/
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;
char *n;
......@@ -77,7 +78,7 @@ struct fwnode_handle *__irq_domain_alloc_fwnode(unsigned int type, int id,
n = kasprintf(GFP_KERNEL, "%s-%d", name, id);
break;
default:
n = kasprintf(GFP_KERNEL, "irqchip@%p", data);
n = kasprintf(GFP_KERNEL, "irqchip@%pa", pa);
break;
}
......@@ -89,7 +90,7 @@ struct fwnode_handle *__irq_domain_alloc_fwnode(unsigned int type, int id,
fwid->type = type;
fwid->name = n;
fwid->data = data;
fwid->pa = pa;
fwid->fwnode.ops = &irqchip_fwnode_ops;
return &fwid->fwnode;
}
......@@ -148,6 +149,7 @@ struct irq_domain *__irq_domain_add(struct fwnode_handle *fwnode, int size,
switch (fwid->type) {
case IRQCHIP_FWNODE_NAMED:
case IRQCHIP_FWNODE_NAMED_ID:
domain->fwnode = fwnode;
domain->name = kstrdup(fwid->name, GFP_KERNEL);
if (!domain->name) {
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