irqchip fixes for 6.1, take #1
- Fix IMX-MU Kconfig, keeping it private to IMX - Fix a register offset for the same IMX-MU driver - Fix the ls-extirq irqchip driver that would use the wrong flavour of spinlocks -----BEGIN PGP SIGNATURE----- iQJDBAABCgAtFiEEn9UcU+C1Yxj9lZw9I9DQutE9ekMFAmNGcOgPHG1hekBrZXJu ZWwub3JnAAoJECPQ0LrRPXpD7tkQAIhKj+FZBE1/IaHnedA3LKRcSyIFnrKZmppU He1770wXkBtnQps/J3ibgKsrtvRYpqf4k+vTkxWJVYF2qMZNG0JkzwCOP3DCFkVR QBpgytUgtBn9z3Pbf9TE3yKjq/v3+VcrKzmXpv+UgrSKkHNmB1reU3Cb4U5oEtvO ByvrdFi3Wu/bV636u5XoWyxjExqBXFiOCK6h3iKrlD6380dQfmOUyArhTLn4SZ6v EmW732xJeGeZ4bOnbeB+6p41METkTdzD7X7ZtYhfBr+aE7xaBUZ0xLwetXaI6tf2 uiBlMaxifL2LCgbHYSurjBlZ5SBG9TfgvXoUJJeOvp0rN/NrKllzUmJOVD+kwwWI QHM9nAI/haTBy3ty8B7Qyc1QxPpaMi0rHAXf/BiUpgDRSrLoDOIt0Pgl5mykkZhl dYPFDbmb0po9VcW0T3C+uDRWe4COcukPPWDbbNNig0escxtC7+Cogyi2w3BZPvw2 LlwCa1tVc2h6xVKzy/fYy89kOuE3+sWnlUbZF2KfL60MTd/bbQp9yALl4gfx3ncq LkF+9GYZUPxBgVVlFzy2MkzyaLFh3K462peDshPLVtwG01DIxhBDTdtykHIgYpO2 XDl6FTUE1NtOUbVRxeKuRDi8i4Lxtrz1h5yCbZHkLFaaJ9HRDza3IdY25p2sfExw tVDrjTwl =6gxA -----END PGP SIGNATURE----- Merge tag 'irqchip-fixes-6.1-1' of git://git.kernel.org/pub/scm/linux/kernel/git/maz/arm-platforms into irq/core Pull irqchip fixes from Marc Zyngier: - Fix IMX-MU Kconfig, keeping it private to IMX - Fix a register offset for the same IMX-MU driver - Fix the ls-extirq irqchip driver that would use the wrong flavour of spinlocks Link: https://lore.kernel.org/r/20221012075125.1244143-1-maz@kernel.org
This commit is contained in:
commit
b8d49bcd8f
|
@ -484,14 +484,15 @@ config IMX_INTMUX
|
|||
config IMX_MU_MSI
|
||||
tristate "i.MX MU used as MSI controller"
|
||||
depends on OF && HAS_IOMEM
|
||||
depends on ARCH_MXC || COMPILE_TEST
|
||||
default m if ARCH_MXC
|
||||
select IRQ_DOMAIN
|
||||
select IRQ_DOMAIN_HIERARCHY
|
||||
select GENERIC_MSI_IRQ_DOMAIN
|
||||
help
|
||||
Provide a driver for the MU block used as a CPU-to-CPU MSI
|
||||
controller. This requires a specially crafted DT to make use
|
||||
of this driver.
|
||||
Provide a driver for the i.MX Messaging Unit block used as a
|
||||
CPU-to-CPU MSI controller. This requires a specially crafted DT
|
||||
to make use of this driver.
|
||||
|
||||
If unsure, say N
|
||||
|
||||
|
|
|
@ -292,7 +292,7 @@ static const struct imx_mu_dcfg imx_mu_cfg_imx8ulp = {
|
|||
.xSR = {
|
||||
[IMX_MU_SR] = 0xC,
|
||||
[IMX_MU_GSR] = 0x118,
|
||||
[IMX_MU_GSR] = 0x124,
|
||||
[IMX_MU_TSR] = 0x124,
|
||||
[IMX_MU_RSR] = 0x12C,
|
||||
},
|
||||
.xCR = {
|
||||
|
|
|
@ -6,8 +6,7 @@
|
|||
#include <linux/irqchip.h>
|
||||
#include <linux/irqdomain.h>
|
||||
#include <linux/of.h>
|
||||
#include <linux/mfd/syscon.h>
|
||||
#include <linux/regmap.h>
|
||||
#include <linux/of_address.h>
|
||||
#include <linux/slab.h>
|
||||
|
||||
#include <dt-bindings/interrupt-controller/arm-gic.h>
|
||||
|
@ -16,13 +15,41 @@
|
|||
#define LS1021A_SCFGREVCR 0x200
|
||||
|
||||
struct ls_extirq_data {
|
||||
struct regmap *syscon;
|
||||
u32 intpcr;
|
||||
void __iomem *intpcr;
|
||||
raw_spinlock_t lock;
|
||||
bool big_endian;
|
||||
bool is_ls1021a_or_ls1043a;
|
||||
u32 nirq;
|
||||
struct irq_fwspec map[MAXIRQ];
|
||||
};
|
||||
|
||||
static void ls_extirq_intpcr_rmw(struct ls_extirq_data *priv, u32 mask,
|
||||
u32 value)
|
||||
{
|
||||
u32 intpcr;
|
||||
|
||||
/*
|
||||
* Serialize concurrent calls to ls_extirq_set_type() from multiple
|
||||
* IRQ descriptors, making sure the read-modify-write is atomic.
|
||||
*/
|
||||
raw_spin_lock(&priv->lock);
|
||||
|
||||
if (priv->big_endian)
|
||||
intpcr = ioread32be(priv->intpcr);
|
||||
else
|
||||
intpcr = ioread32(priv->intpcr);
|
||||
|
||||
intpcr &= ~mask;
|
||||
intpcr |= value;
|
||||
|
||||
if (priv->big_endian)
|
||||
iowrite32be(intpcr, priv->intpcr);
|
||||
else
|
||||
iowrite32(intpcr, priv->intpcr);
|
||||
|
||||
raw_spin_unlock(&priv->lock);
|
||||
}
|
||||
|
||||
static int
|
||||
ls_extirq_set_type(struct irq_data *data, unsigned int type)
|
||||
{
|
||||
|
@ -51,7 +78,8 @@ ls_extirq_set_type(struct irq_data *data, unsigned int type)
|
|||
default:
|
||||
return -EINVAL;
|
||||
}
|
||||
regmap_update_bits(priv->syscon, priv->intpcr, mask, value);
|
||||
|
||||
ls_extirq_intpcr_rmw(priv, mask, value);
|
||||
|
||||
return irq_chip_set_type_parent(data, type);
|
||||
}
|
||||
|
@ -143,7 +171,6 @@ ls_extirq_parse_map(struct ls_extirq_data *priv, struct device_node *node)
|
|||
static int __init
|
||||
ls_extirq_of_init(struct device_node *node, struct device_node *parent)
|
||||
{
|
||||
|
||||
struct irq_domain *domain, *parent_domain;
|
||||
struct ls_extirq_data *priv;
|
||||
int ret;
|
||||
|
@ -151,40 +178,52 @@ ls_extirq_of_init(struct device_node *node, struct device_node *parent)
|
|||
parent_domain = irq_find_host(parent);
|
||||
if (!parent_domain) {
|
||||
pr_err("Cannot find parent domain\n");
|
||||
return -ENODEV;
|
||||
ret = -ENODEV;
|
||||
goto err_irq_find_host;
|
||||
}
|
||||
|
||||
priv = kzalloc(sizeof(*priv), GFP_KERNEL);
|
||||
if (!priv)
|
||||
return -ENOMEM;
|
||||
|
||||
priv->syscon = syscon_node_to_regmap(node->parent);
|
||||
if (IS_ERR(priv->syscon)) {
|
||||
ret = PTR_ERR(priv->syscon);
|
||||
pr_err("Failed to lookup parent regmap\n");
|
||||
goto out;
|
||||
if (!priv) {
|
||||
ret = -ENOMEM;
|
||||
goto err_alloc_priv;
|
||||
}
|
||||
ret = of_property_read_u32(node, "reg", &priv->intpcr);
|
||||
if (ret) {
|
||||
pr_err("Missing INTPCR offset value\n");
|
||||
goto out;
|
||||
|
||||
/*
|
||||
* All extirq OF nodes are under a scfg/syscon node with
|
||||
* the 'ranges' property
|
||||
*/
|
||||
priv->intpcr = of_iomap(node, 0);
|
||||
if (!priv->intpcr) {
|
||||
pr_err("Cannot ioremap OF node %pOF\n", node);
|
||||
ret = -ENOMEM;
|
||||
goto err_iomap;
|
||||
}
|
||||
|
||||
ret = ls_extirq_parse_map(priv, node);
|
||||
if (ret)
|
||||
goto out;
|
||||
goto err_parse_map;
|
||||
|
||||
priv->big_endian = of_device_is_big_endian(parent);
|
||||
priv->is_ls1021a_or_ls1043a = of_device_is_compatible(node, "fsl,ls1021a-extirq") ||
|
||||
of_device_is_compatible(node, "fsl,ls1043a-extirq");
|
||||
raw_spin_lock_init(&priv->lock);
|
||||
|
||||
domain = irq_domain_add_hierarchy(parent_domain, 0, priv->nirq, node,
|
||||
&extirq_domain_ops, priv);
|
||||
if (!domain)
|
||||
if (!domain) {
|
||||
ret = -ENOMEM;
|
||||
goto err_add_hierarchy;
|
||||
}
|
||||
|
||||
out:
|
||||
if (ret)
|
||||
kfree(priv);
|
||||
return 0;
|
||||
|
||||
err_add_hierarchy:
|
||||
err_parse_map:
|
||||
iounmap(priv->intpcr);
|
||||
err_iomap:
|
||||
kfree(priv);
|
||||
err_alloc_priv:
|
||||
err_irq_find_host:
|
||||
return ret;
|
||||
}
|
||||
|
||||
|
|
Loading…
Reference in New Issue