2021-12-02 09:53:27

by Herve Codina

[permalink] [raw]
Subject: [PATCH 0/6] spear: Fix SPEAr3XX plgpio support

Hi,

This patch series fixes the plgpio support on SPEAr3xx SOCs.

The first four patches of this series fixes a ressources
sharing issue between the plgpio driver and the pinmux
driver.
Indeed, these two drivers can use the same IO address range
on some SPEAr3xx SOCs.
To solve the issue, a regmap (syscon managed) is used in both
drivers and the plgpio driver can reference the pinmux regmap
to use it.

The second part of this series is related to IRQs.
The plgpio on SPEAr320s SOC uses an IRQ line in the reserve
range (from SPEAr320 point of view).
This issue is fixed enabling all the 'reserved' IRQs and
adding a dtsi file for the SPEAr320s with the correct interrupt
for the plgpio node.

Best regards,
Herve

Herve Codina (6):
pinctrl: spear: spear: Convert to regmap
pinctrl: spear: plgpio: Convert to regmap
pinctrl: spear: plgpio: Introduce regmap phandle
ARM: dts: spear3xx: Use plgpio regmap in SPEAr310 and SPEAr320
irq: spear-shirq: Add support for IRQ 0..6
ARM: dts: spear3xx: Add spear320s dtsi

arch/arm/boot/dts/spear310.dtsi | 1 +
arch/arm/boot/dts/spear320.dtsi | 1 +
arch/arm/boot/dts/spear320s.dtsi | 24 ++++
drivers/irqchip/spear-shirq.c | 2 +
drivers/pinctrl/spear/pinctrl-plgpio.c | 148 +++++++++++++++----------
drivers/pinctrl/spear/pinctrl-spear.c | 10 +-
drivers/pinctrl/spear/pinctrl-spear.h | 12 +-
7 files changed, 131 insertions(+), 67 deletions(-)
create mode 100644 arch/arm/boot/dts/spear320s.dtsi

--
2.31.1



2021-12-02 09:53:40

by Herve Codina

[permalink] [raw]
Subject: [PATCH 3/6] pinctrl: spear: plgpio: Introduce regmap phandle

Resources need to be shared between pinmux and plgpio.

Introduce regmap phandle in order to retrieve the regmap
from the phandle if the property is present.
This allows to retrieve an external regmap (ie the one
used by pinmux if the phandle references the pinmux node)
from plgpio.

Signed-off-by: Herve Codina <[email protected]>
---
drivers/pinctrl/spear/pinctrl-plgpio.c | 22 +++++++++++++++++-----
1 file changed, 17 insertions(+), 5 deletions(-)

diff --git a/drivers/pinctrl/spear/pinctrl-plgpio.c b/drivers/pinctrl/spear/pinctrl-plgpio.c
index 28538ac99eed..b36449724f3f 100644
--- a/drivers/pinctrl/spear/pinctrl-plgpio.c
+++ b/drivers/pinctrl/spear/pinctrl-plgpio.c
@@ -523,6 +523,7 @@ static int plgpio_probe_dt(struct platform_device *pdev, struct plgpio *plgpio)

static int plgpio_probe(struct platform_device *pdev)
{
+ struct device_node *regmap_np;
struct plgpio *plgpio;
int ret, irq;

@@ -530,11 +531,22 @@ static int plgpio_probe(struct platform_device *pdev)
if (!plgpio)
return -ENOMEM;

- plgpio->regmap = device_node_to_regmap(pdev->dev.of_node);
- if (IS_ERR(plgpio->regmap)) {
- dev_err(&pdev->dev, "Init regmap failed (%pe)\n",
- plgpio->regmap);
- return PTR_ERR(plgpio->regmap);
+ regmap_np = of_parse_phandle(pdev->dev.of_node, "regmap", 0);
+ if (regmap_np) {
+ plgpio->regmap = device_node_to_regmap(regmap_np);
+ of_node_put(regmap_np);
+ if (IS_ERR(plgpio->regmap)) {
+ dev_err(&pdev->dev, "Retrieve regmap failed (%pe)\n",
+ plgpio->regmap);
+ return PTR_ERR(plgpio->regmap);
+ }
+ } else {
+ plgpio->regmap = device_node_to_regmap(pdev->dev.of_node);
+ if (IS_ERR(plgpio->regmap)) {
+ dev_err(&pdev->dev, "Init regmap failed (%pe)\n",
+ plgpio->regmap);
+ return PTR_ERR(plgpio->regmap);
+ }
}

ret = plgpio_probe_dt(pdev, plgpio);
--
2.31.1


2021-12-02 09:53:46

by Herve Codina

[permalink] [raw]
Subject: [PATCH 2/6] pinctrl: spear: plgpio: Convert to regmap

Resources need to be shared between pinmux and plgpio.

Use regmap (syscon) to access resources to allow an
easy way to share resources.

Signed-off-by: Herve Codina <[email protected]>
---
drivers/pinctrl/spear/pinctrl-plgpio.c | 136 ++++++++++++++-----------
1 file changed, 76 insertions(+), 60 deletions(-)

diff --git a/drivers/pinctrl/spear/pinctrl-plgpio.c b/drivers/pinctrl/spear/pinctrl-plgpio.c
index 43bb334af1e1..28538ac99eed 100644
--- a/drivers/pinctrl/spear/pinctrl-plgpio.c
+++ b/drivers/pinctrl/spear/pinctrl-plgpio.c
@@ -14,11 +14,13 @@
#include <linux/gpio/driver.h>
#include <linux/io.h>
#include <linux/init.h>
+#include <linux/mfd/syscon.h>
#include <linux/of.h>
#include <linux/of_platform.h>
#include <linux/pinctrl/consumer.h>
#include <linux/platform_device.h>
#include <linux/pm.h>
+#include <linux/regmap.h>
#include <linux/spinlock.h>

#define MAX_GPIO_PER_REG 32
@@ -64,7 +66,7 @@ struct plgpio_regs {
*/
struct plgpio {
spinlock_t lock;
- void __iomem *base;
+ struct regmap *regmap;
struct clk *clk;
struct gpio_chip chip;
int (*p2o)(int pin); /* pin_to_offset */
@@ -77,33 +79,38 @@ struct plgpio {
};

/* register manipulation inline functions */
-static inline u32 is_plgpio_set(void __iomem *base, u32 pin, u32 reg)
+static inline u32 is_plgpio_set(struct regmap *regmap, u32 pin, u32 reg)
{
u32 offset = PIN_OFFSET(pin);
- void __iomem *reg_off = REG_OFFSET(base, reg, pin);
- u32 val = readl_relaxed(reg_off);
+ u32 reg_off = REG_OFFSET(0, reg, pin);
+ u32 val;
+
+ regmap_read(regmap, reg_off, &val);

return !!(val & (1 << offset));
}

-static inline void plgpio_reg_set(void __iomem *base, u32 pin, u32 reg)
+static inline void plgpio_reg_set(struct regmap *regmap, u32 pin, u32 reg)
{
u32 offset = PIN_OFFSET(pin);
- void __iomem *reg_off = REG_OFFSET(base, reg, pin);
- u32 val = readl_relaxed(reg_off);
+ u32 reg_off = REG_OFFSET(0, reg, pin);
+ u32 mask;

- writel_relaxed(val | (1 << offset), reg_off);
+ mask = 1 << offset;
+ regmap_update_bits(regmap, reg_off, mask, mask);
}

-static inline void plgpio_reg_reset(void __iomem *base, u32 pin, u32 reg)
+static inline void plgpio_reg_reset(struct regmap *regmap, u32 pin, u32 reg)
{
u32 offset = PIN_OFFSET(pin);
- void __iomem *reg_off = REG_OFFSET(base, reg, pin);
- u32 val = readl_relaxed(reg_off);
+ u32 reg_off = REG_OFFSET(0, reg, pin);
+ u32 mask;

- writel_relaxed(val & ~(1 << offset), reg_off);
+ mask = 1 << offset;
+ regmap_update_bits(regmap, reg_off, mask, 0);
}

+
/* gpio framework specific routines */
static int plgpio_direction_input(struct gpio_chip *chip, unsigned offset)
{
@@ -118,7 +125,7 @@ static int plgpio_direction_input(struct gpio_chip *chip, unsigned offset)
}

spin_lock_irqsave(&plgpio->lock, flags);
- plgpio_reg_set(plgpio->base, offset, plgpio->regs.dir);
+ plgpio_reg_set(plgpio->regmap, offset, plgpio->regs.dir);
spin_unlock_irqrestore(&plgpio->lock, flags);

return 0;
@@ -145,13 +152,13 @@ static int plgpio_direction_output(struct gpio_chip *chip, unsigned offset,

spin_lock_irqsave(&plgpio->lock, flags);
if (value)
- plgpio_reg_set(plgpio->base, wdata_offset,
+ plgpio_reg_set(plgpio->regmap, wdata_offset,
plgpio->regs.wdata);
else
- plgpio_reg_reset(plgpio->base, wdata_offset,
+ plgpio_reg_reset(plgpio->regmap, wdata_offset,
plgpio->regs.wdata);

- plgpio_reg_reset(plgpio->base, dir_offset, plgpio->regs.dir);
+ plgpio_reg_reset(plgpio->regmap, dir_offset, plgpio->regs.dir);
spin_unlock_irqrestore(&plgpio->lock, flags);

return 0;
@@ -171,7 +178,7 @@ static int plgpio_get_value(struct gpio_chip *chip, unsigned offset)
return -EINVAL;
}

- return is_plgpio_set(plgpio->base, offset, plgpio->regs.rdata);
+ return is_plgpio_set(plgpio->regmap, offset, plgpio->regs.rdata);
}

static void plgpio_set_value(struct gpio_chip *chip, unsigned offset, int value)
@@ -189,9 +196,9 @@ static void plgpio_set_value(struct gpio_chip *chip, unsigned offset, int value)
}

if (value)
- plgpio_reg_set(plgpio->base, offset, plgpio->regs.wdata);
+ plgpio_reg_set(plgpio->regmap, offset, plgpio->regs.wdata);
else
- plgpio_reg_reset(plgpio->base, offset, plgpio->regs.wdata);
+ plgpio_reg_reset(plgpio->regmap, offset, plgpio->regs.wdata);
}

static int plgpio_request(struct gpio_chip *chip, unsigned offset)
@@ -234,7 +241,7 @@ static int plgpio_request(struct gpio_chip *chip, unsigned offset)
}

spin_lock_irqsave(&plgpio->lock, flags);
- plgpio_reg_set(plgpio->base, offset, plgpio->regs.enb);
+ plgpio_reg_set(plgpio->regmap, offset, plgpio->regs.enb);
spin_unlock_irqrestore(&plgpio->lock, flags);
return 0;

@@ -266,7 +273,7 @@ static void plgpio_free(struct gpio_chip *chip, unsigned offset)
}

spin_lock_irqsave(&plgpio->lock, flags);
- plgpio_reg_reset(plgpio->base, offset, plgpio->regs.enb);
+ plgpio_reg_reset(plgpio->regmap, offset, plgpio->regs.enb);
spin_unlock_irqrestore(&plgpio->lock, flags);

disable_clk:
@@ -292,7 +299,7 @@ static void plgpio_irq_disable(struct irq_data *d)
}

spin_lock_irqsave(&plgpio->lock, flags);
- plgpio_reg_set(plgpio->base, offset, plgpio->regs.ie);
+ plgpio_reg_set(plgpio->regmap, offset, plgpio->regs.ie);
spin_unlock_irqrestore(&plgpio->lock, flags);
}

@@ -311,7 +318,7 @@ static void plgpio_irq_enable(struct irq_data *d)
}

spin_lock_irqsave(&plgpio->lock, flags);
- plgpio_reg_reset(plgpio->base, offset, plgpio->regs.ie);
+ plgpio_reg_reset(plgpio->regmap, offset, plgpio->regs.ie);
spin_unlock_irqrestore(&plgpio->lock, flags);
}

@@ -320,7 +327,7 @@ static int plgpio_irq_set_type(struct irq_data *d, unsigned trigger)
struct gpio_chip *gc = irq_data_get_irq_chip_data(d);
struct plgpio *plgpio = gpiochip_get_data(gc);
int offset = d->hwirq;
- void __iomem *reg_off;
+ u32 reg_off;
unsigned int supported_type = 0, val;

if (offset >= plgpio->chip.ngpio)
@@ -337,14 +344,14 @@ static int plgpio_irq_set_type(struct irq_data *d, unsigned trigger)
if (plgpio->regs.eit == -1)
return 0;

- reg_off = REG_OFFSET(plgpio->base, plgpio->regs.eit, offset);
- val = readl_relaxed(reg_off);
+ reg_off = REG_OFFSET(0, plgpio->regs.eit, offset);
+ regmap_read(plgpio->regmap, reg_off, &val);

offset = PIN_OFFSET(offset);
if (trigger & IRQ_TYPE_EDGE_RISING)
- writel_relaxed(val | (1 << offset), reg_off);
+ regmap_write(plgpio->regmap, reg_off, val | (1 << offset));
else
- writel_relaxed(val & ~(1 << offset), reg_off);
+ regmap_write(plgpio->regmap, reg_off, val & ~(1 << offset));

return 0;
}
@@ -362,7 +369,8 @@ static void plgpio_irq_handler(struct irq_desc *desc)
struct plgpio *plgpio = gpiochip_get_data(gc);
struct irq_chip *irqchip = irq_desc_get_chip(desc);
int regs_count, count, pin, offset, i = 0;
- unsigned long pending;
+ u32 pending;
+ unsigned long pendingl;

count = plgpio->chip.ngpio;
regs_count = DIV_ROUND_UP(count, MAX_GPIO_PER_REG);
@@ -370,14 +378,14 @@ static void plgpio_irq_handler(struct irq_desc *desc)
chained_irq_enter(irqchip, desc);
/* check all plgpio MIS registers for a possible interrupt */
for (; i < regs_count; i++) {
- pending = readl_relaxed(plgpio->base + plgpio->regs.mis +
- i * sizeof(int *));
+ regmap_read(plgpio->regmap, plgpio->regs.mis +
+ i * sizeof(int *), &pending);
if (!pending)
continue;

/* clear interrupts */
- writel_relaxed(~pending, plgpio->base + plgpio->regs.mis +
- i * sizeof(int *));
+ regmap_write(plgpio->regmap, plgpio->regs.mis +
+ i * sizeof(int *), ~pending);
/*
* clear extra bits in last register having gpios < MAX/REG
* ex: Suppose there are max 102 plgpios. then last register
@@ -389,7 +397,8 @@ static void plgpio_irq_handler(struct irq_desc *desc)
if (count < MAX_GPIO_PER_REG)
pending &= (1 << count) - 1;

- for_each_set_bit(offset, &pending, MAX_GPIO_PER_REG) {
+ pendingl = pending;
+ for_each_set_bit(offset, &pendingl, MAX_GPIO_PER_REG) {
/* get correct pin for "offset" */
if (plgpio->o2p && (plgpio->p2o_regs & PTO_MIS_REG)) {
pin = plgpio->o2p(offset);
@@ -511,6 +520,7 @@ static int plgpio_probe_dt(struct platform_device *pdev, struct plgpio *plgpio)
end:
return ret;
}
+
static int plgpio_probe(struct platform_device *pdev)
{
struct plgpio *plgpio;
@@ -520,9 +530,12 @@ static int plgpio_probe(struct platform_device *pdev)
if (!plgpio)
return -ENOMEM;

- plgpio->base = devm_platform_ioremap_resource(pdev, 0);
- if (IS_ERR(plgpio->base))
- return PTR_ERR(plgpio->base);
+ plgpio->regmap = device_node_to_regmap(pdev->dev.of_node);
+ if (IS_ERR(plgpio->regmap)) {
+ dev_err(&pdev->dev, "Init regmap failed (%pe)\n",
+ plgpio->regmap);
+ return PTR_ERR(plgpio->regmap);
+ }

ret = plgpio_probe_dt(pdev, plgpio);
if (ret) {
@@ -607,22 +620,23 @@ static int plgpio_suspend(struct device *dev)
{
struct plgpio *plgpio = dev_get_drvdata(dev);
int i, reg_count = DIV_ROUND_UP(plgpio->chip.ngpio, MAX_GPIO_PER_REG);
- void __iomem *off;
+ u32 off;

for (i = 0; i < reg_count; i++) {
- off = plgpio->base + i * sizeof(int *);
+ off = i * sizeof(int *);

if (plgpio->regs.enb != -1)
- plgpio->csave_regs[i].enb =
- readl_relaxed(plgpio->regs.enb + off);
+ regmap_read(plgpio->regmap, plgpio->regs.enb + off,
+ &plgpio->csave_regs[i].enb);
if (plgpio->regs.eit != -1)
- plgpio->csave_regs[i].eit =
- readl_relaxed(plgpio->regs.eit + off);
- plgpio->csave_regs[i].wdata = readl_relaxed(plgpio->regs.wdata +
- off);
- plgpio->csave_regs[i].dir = readl_relaxed(plgpio->regs.dir +
- off);
- plgpio->csave_regs[i].ie = readl_relaxed(plgpio->regs.ie + off);
+ regmap_read(plgpio->regmap, plgpio->regs.eit + off,
+ &plgpio->csave_regs[i].eit);
+ regmap_read(plgpio->regmap, plgpio->regs.wdata + off,
+ &plgpio->csave_regs[i].wdata);
+ regmap_read(plgpio->regmap, plgpio->regs.dir + off,
+ &plgpio->csave_regs[i].dir);
+ regmap_read(plgpio->regmap, plgpio->regs.ie + off,
+ &plgpio->csave_regs[i].ie);
}

return 0;
@@ -636,7 +650,7 @@ static int plgpio_suspend(struct device *dev)
*/
#define plgpio_prepare_reg(__reg, _off, _mask, _tmp) \
{ \
- _tmp = readl_relaxed(plgpio->regs.__reg + _off); \
+ regmap_read(plgpio->regmap, plgpio->regs.__reg + _off, &_tmp); \
_tmp &= ~_mask; \
plgpio->csave_regs[i].__reg = \
_tmp | (plgpio->csave_regs[i].__reg & _mask); \
@@ -646,11 +660,11 @@ static int plgpio_resume(struct device *dev)
{
struct plgpio *plgpio = dev_get_drvdata(dev);
int i, reg_count = DIV_ROUND_UP(plgpio->chip.ngpio, MAX_GPIO_PER_REG);
- void __iomem *off;
+ u32 off;
u32 mask, tmp;

for (i = 0; i < reg_count; i++) {
- off = plgpio->base + i * sizeof(int *);
+ off = i * sizeof(int *);

if (i == reg_count - 1) {
mask = (1 << (plgpio->chip.ngpio - i *
@@ -667,20 +681,22 @@ static int plgpio_resume(struct device *dev)
plgpio_prepare_reg(ie, off, mask, tmp);
}

- writel_relaxed(plgpio->csave_regs[i].wdata, plgpio->regs.wdata +
- off);
- writel_relaxed(plgpio->csave_regs[i].dir, plgpio->regs.dir +
- off);
+ regmap_write(plgpio->regmap, plgpio->regs.wdata + off,
+ plgpio->csave_regs[i].wdata);
+
+ regmap_write(plgpio->regmap, plgpio->regs.dir + off,
+ plgpio->csave_regs[i].dir);

if (plgpio->regs.eit != -1)
- writel_relaxed(plgpio->csave_regs[i].eit,
- plgpio->regs.eit + off);
+ regmap_write(plgpio->regmap, plgpio->regs.eit + off,
+ plgpio->csave_regs[i].eit);

- writel_relaxed(plgpio->csave_regs[i].ie, plgpio->regs.ie + off);
+ regmap_write(plgpio->regmap, plgpio->regs.ie + off,
+ plgpio->csave_regs[i].ie);

if (plgpio->regs.enb != -1)
- writel_relaxed(plgpio->csave_regs[i].enb,
- plgpio->regs.enb + off);
+ regmap_write(plgpio->regmap, plgpio->regs.enb + off,
+ plgpio->csave_regs[i].enb);
}

return 0;
--
2.31.1


2021-12-02 09:54:04

by Herve Codina

[permalink] [raw]
Subject: [PATCH 5/6] irq: spear-shirq: Add support for IRQ 0..6

IRQ 0..7 are not supported by the driver for SPEAr320 SOC family.

IRQ 0 is not reserved in SPEAr320 SOC (assigned to GPIOINT).
Furthermore, in SPEAr320s SOC variant, IRQ 0..6 are assigned
as follow:
IRQ 6 - NGPIO_INTR: Combined status of edge programmable
interrupts from GPIO ports
IRQ 5 - TX_OR_INTR: I2S interrupt on Transmit FIFO overrun
IRQ 4 - TX_EMP_INTR: I2S interrupt on Transmit FIFO empty
IRQ 3 - RX_OR_INTR: I2S interrupt on Receive FIFO overrun
IRQ 2 - RX_DA_INTR: I2S interrupt on data available in Receive FIFO
IRQ 1 - Reserved
IRQ 0 - GPIO_INTR: Legacy interrupt from GPIO ports

Add support for these IRQs in SPEAr320 SOC family.

Signed-off-by: Herve Codina <[email protected]>
---
drivers/irqchip/spear-shirq.c | 2 ++
1 file changed, 2 insertions(+)

diff --git a/drivers/irqchip/spear-shirq.c b/drivers/irqchip/spear-shirq.c
index 1518ba31a80c..7c17a6f643ef 100644
--- a/drivers/irqchip/spear-shirq.c
+++ b/drivers/irqchip/spear-shirq.c
@@ -149,6 +149,8 @@ static struct spear_shirq spear320_shirq_ras3 = {
.offset = 0,
.nr_irqs = 7,
.mask = ((0x1 << 7) - 1) << 0,
+ .irq_chip = &dummy_irq_chip,
+ .status_reg = SPEAR320_INT_STS_MASK_REG,
};

static struct spear_shirq spear320_shirq_ras1 = {
--
2.31.1


2021-12-02 09:54:11

by Herve Codina

[permalink] [raw]
Subject: [PATCH 4/6] ARM: dts: spear3xx: Use plgpio regmap in SPEAr310 and SPEAr320

Resources used by plgpio and pinmux are conflicting on SPEAr310
and SPEAr320.

Use the newly introduced regmap property in plgpio node to use
pinmux resources from plgpio and so avoid the conflict.

Signed-off-by: Herve Codina <[email protected]>
---
arch/arm/boot/dts/spear310.dtsi | 1 +
arch/arm/boot/dts/spear320.dtsi | 1 +
2 files changed, 2 insertions(+)

diff --git a/arch/arm/boot/dts/spear310.dtsi b/arch/arm/boot/dts/spear310.dtsi
index 8ce751a1376d..77570833d46b 100644
--- a/arch/arm/boot/dts/spear310.dtsi
+++ b/arch/arm/boot/dts/spear310.dtsi
@@ -92,6 +92,7 @@ serial@b2200000 {
gpiopinctrl: gpio@b4000000 {
compatible = "st,spear-plgpio";
reg = <0xb4000000 0x1000>;
+ regmap = <&pinmux>;
#interrupt-cells = <1>;
interrupt-controller;
gpio-controller;
diff --git a/arch/arm/boot/dts/spear320.dtsi b/arch/arm/boot/dts/spear320.dtsi
index 3bc1e93a0a55..47ac4474ed96 100644
--- a/arch/arm/boot/dts/spear320.dtsi
+++ b/arch/arm/boot/dts/spear320.dtsi
@@ -120,6 +120,7 @@ serial@a4000000 {
gpiopinctrl: gpio@b3000000 {
compatible = "st,spear-plgpio";
reg = <0xb3000000 0x1000>;
+ regmap = <&pinmux>;
#interrupt-cells = <1>;
interrupt-controller;
gpio-controller;
--
2.31.1


2021-12-02 09:54:27

by Herve Codina

[permalink] [raw]
Subject: [PATCH 6/6] ARM: dts: spear3xx: Add spear320s dtsi

The SPEAr320s SOC is a SPEAr320 SOC variant.

Mostly identical to the SPEAr320 SOC variant, it has a
new interrupt routing for PL_PGIOs.

Add spear320s.dtsi to handle SPEAr320s SOC

Signed-off-by: Herve Codina <[email protected]>
---
arch/arm/boot/dts/spear320s.dtsi | 24 ++++++++++++++++++++++++
1 file changed, 24 insertions(+)
create mode 100644 arch/arm/boot/dts/spear320s.dtsi

diff --git a/arch/arm/boot/dts/spear320s.dtsi b/arch/arm/boot/dts/spear320s.dtsi
new file mode 100644
index 000000000000..133236dc190d
--- /dev/null
+++ b/arch/arm/boot/dts/spear320s.dtsi
@@ -0,0 +1,24 @@
+// SPDX-License-Identifier: GPL-2.0-or-later
+/*
+ * DTS file for SPEAr320s SoC
+ *
+ * Copyright 2021 Herve Codina <[email protected]>
+ */
+
+/include/ "spear320.dtsi"
+
+/ {
+ ahb {
+ apb {
+ gpiopinctrl: gpio@b3000000 {
+ /*
+ * The "RM0321 SPEAr320s address and map
+ * registers" document mentions interrupt 6
+ * (NPGIO_INTR) for the PL_GPIO interrupt.
+ */
+ interrupts = <6>;
+ interrupt-parent = <&shirq>;
+ };
+ };
+ };
+};
--
2.31.1


2021-12-02 09:54:57

by Herve Codina

[permalink] [raw]
Subject: [PATCH 1/6] pinctrl: spear: spear: Convert to regmap

Resources need to be shared between pinmux and plgpio.

Use regmap (syscon) to access resources to allow an
easy way to share resources.

Signed-off-by: Herve Codina <[email protected]>
---
drivers/pinctrl/spear/pinctrl-spear.c | 10 +++++++---
drivers/pinctrl/spear/pinctrl-spear.h | 12 ++++++++----
2 files changed, 15 insertions(+), 7 deletions(-)

diff --git a/drivers/pinctrl/spear/pinctrl-spear.c b/drivers/pinctrl/spear/pinctrl-spear.c
index 948f56abb9ae..e0543c1ad641 100644
--- a/drivers/pinctrl/spear/pinctrl-spear.c
+++ b/drivers/pinctrl/spear/pinctrl-spear.c
@@ -14,6 +14,7 @@
*/

#include <linux/err.h>
+#include <linux/mfd/syscon.h>
#include <linux/module.h>
#include <linux/of.h>
#include <linux/of_address.h>
@@ -367,9 +368,12 @@ int spear_pinctrl_probe(struct platform_device *pdev,
if (!pmx)
return -ENOMEM;

- pmx->vbase = devm_platform_ioremap_resource(pdev, 0);
- if (IS_ERR(pmx->vbase))
- return PTR_ERR(pmx->vbase);
+ pmx->regmap = device_node_to_regmap(np);
+ if (IS_ERR(pmx->regmap)) {
+ dev_err(&pdev->dev, "Init regmap failed (%pe).\n",
+ pmx->regmap);
+ return PTR_ERR(pmx->regmap);
+ }

pmx->dev = &pdev->dev;
pmx->machdata = machdata;
diff --git a/drivers/pinctrl/spear/pinctrl-spear.h b/drivers/pinctrl/spear/pinctrl-spear.h
index db029b148c87..63a0b5ea56ef 100644
--- a/drivers/pinctrl/spear/pinctrl-spear.h
+++ b/drivers/pinctrl/spear/pinctrl-spear.h
@@ -15,6 +15,7 @@
#include <linux/gpio/driver.h>
#include <linux/io.h>
#include <linux/pinctrl/pinctrl.h>
+#include <linux/regmap.h>
#include <linux/types.h>

struct platform_device;
@@ -172,24 +173,27 @@ struct spear_pinctrl_machdata {
* @dev: pointer to struct dev of platform_device registered
* @pctl: pointer to struct pinctrl_dev
* @machdata: pointer to SoC or machine specific structure
- * @vbase: virtual base address of pinmux controller
+ * @regmap: regmap of pinmux controller
*/
struct spear_pmx {
struct device *dev;
struct pinctrl_dev *pctl;
struct spear_pinctrl_machdata *machdata;
- void __iomem *vbase;
+ struct regmap *regmap;
};

/* exported routines */
static inline u32 pmx_readl(struct spear_pmx *pmx, u32 reg)
{
- return readl_relaxed(pmx->vbase + reg);
+ u32 val;
+
+ regmap_read(pmx->regmap, reg, &val);
+ return val;
}

static inline void pmx_writel(struct spear_pmx *pmx, u32 val, u32 reg)
{
- writel_relaxed(val, pmx->vbase + reg);
+ regmap_write(pmx->regmap, reg, val);
}

void pmx_init_addr(struct spear_pinctrl_machdata *machdata, u16 reg);
--
2.31.1


2021-12-02 11:27:09

by Viresh Kumar

[permalink] [raw]
Subject: Re: [PATCH 0/6] spear: Fix SPEAr3XX plgpio support

On 02-12-21, 10:52, Herve Codina wrote:
> Hi,
>
> This patch series fixes the plgpio support on SPEAr3xx SOCs.
>
> The first four patches of this series fixes a ressources
> sharing issue between the plgpio driver and the pinmux
> driver.
> Indeed, these two drivers can use the same IO address range
> on some SPEAr3xx SOCs.
> To solve the issue, a regmap (syscon managed) is used in both
> drivers and the plgpio driver can reference the pinmux regmap
> to use it.
>
> The second part of this series is related to IRQs.
> The plgpio on SPEAr320s SOC uses an IRQ line in the reserve
> range (from SPEAr320 point of view).
> This issue is fixed enabling all the 'reserved' IRQs and
> adding a dtsi file for the SPEAr320s with the correct interrupt
> for the plgpio node.

Are these changes backwards compatible ? I mean new kernel will work
with old DTBs ? It may be quite important to not break that here.

--
viresh

2021-12-02 11:49:24

by Herve Codina

[permalink] [raw]
Subject: Re: [PATCH 0/6] spear: Fix SPEAr3XX plgpio support

On Thu, 2 Dec 2021 16:57:00 +0530
Viresh Kumar <[email protected]> wrote:

> On 02-12-21, 10:52, Herve Codina wrote:
> > Hi,
> >
> > This patch series fixes the plgpio support on SPEAr3xx SOCs.
> >
> > The first four patches of this series fixes a ressources
> > sharing issue between the plgpio driver and the pinmux
> > driver.
> > Indeed, these two drivers can use the same IO address range
> > on some SPEAr3xx SOCs.
> > To solve the issue, a regmap (syscon managed) is used in both
> > drivers and the plgpio driver can reference the pinmux regmap
> > to use it.
> >
> > The second part of this series is related to IRQs.
> > The plgpio on SPEAr320s SOC uses an IRQ line in the reserve
> > range (from SPEAr320 point of view).
> > This issue is fixed enabling all the 'reserved' IRQs and
> > adding a dtsi file for the SPEAr320s with the correct interrupt
> > for the plgpio node.
>
> Are these changes backwards compatible ? I mean new kernel will work
> with old DTBs ? It may be quite important to not break that here.
>

Yes they are.
- the regmap reference (phandle) is optional.
- The IRQ for plgpio is used only on the new spear320s.dtsi.

I have not seen any issues on my board (spear320s SOC) when I only add support
for the 'reserved' IRQs (ie no spurious interrupts occur when I apply the patch
related to shirq).
I cannot test on SPEAr320 SOC as I haven't got any board with this SOC.

Herve

--
Hervé Codina, Bootlin
Embedded Linux and Kernel engineering
https://bootlin.com

2021-12-03 04:43:47

by Viresh Kumar

[permalink] [raw]
Subject: Re: [PATCH 0/6] spear: Fix SPEAr3XX plgpio support

On 02-12-21, 10:52, Herve Codina wrote:
> Hi,
>
> This patch series fixes the plgpio support on SPEAr3xx SOCs.
>
> The first four patches of this series fixes a ressources
> sharing issue between the plgpio driver and the pinmux
> driver.
> Indeed, these two drivers can use the same IO address range
> on some SPEAr3xx SOCs.
> To solve the issue, a regmap (syscon managed) is used in both
> drivers and the plgpio driver can reference the pinmux regmap
> to use it.
>
> The second part of this series is related to IRQs.
> The plgpio on SPEAr320s SOC uses an IRQ line in the reserve
> range (from SPEAr320 point of view).
> This issue is fixed enabling all the 'reserved' IRQs and
> adding a dtsi file for the SPEAr320s with the correct interrupt
> for the plgpio node.
>
> Best regards,
> Herve
>
> Herve Codina (6):
> pinctrl: spear: spear: Convert to regmap
> pinctrl: spear: plgpio: Convert to regmap
> pinctrl: spear: plgpio: Introduce regmap phandle
> ARM: dts: spear3xx: Use plgpio regmap in SPEAr310 and SPEAr320
> irq: spear-shirq: Add support for IRQ 0..6
> ARM: dts: spear3xx: Add spear320s dtsi

Acked-by: Viresh Kumar <[email protected]>

--
viresh

2021-12-04 23:36:59

by Linus Walleij

[permalink] [raw]
Subject: Re: [PATCH 0/6] spear: Fix SPEAr3XX plgpio support

On Thu, Dec 2, 2021 at 10:53 AM Herve Codina <[email protected]> wrote:

> Herve Codina (6):
> pinctrl: spear: spear: Convert to regmap
> pinctrl: spear: plgpio: Convert to regmap
> pinctrl: spear: plgpio: Introduce regmap phandle

These three applied to the pinctrl tree.

> ARM: dts: spear3xx: Use plgpio regmap in SPEAr310 and SPEAr320

Please apply this to the SoC tree.

> irq: spear-shirq: Add support for IRQ 0..6

Please ask Marc Zyngier to apply this to the irqchip tree.

> ARM: dts: spear3xx: Add spear320s dtsi

Please apply this to the SoC tree.

Yours,
Linus Walleij

2021-12-04 23:38:06

by Linus Walleij

[permalink] [raw]
Subject: Re: [PATCH 5/6] irq: spear-shirq: Add support for IRQ 0..6

On Thu, Dec 2, 2021 at 10:53 AM Herve Codina <[email protected]> wrote:

> IRQ 0..7 are not supported by the driver for SPEAr320 SOC family.
>
> IRQ 0 is not reserved in SPEAr320 SOC (assigned to GPIOINT).
> Furthermore, in SPEAr320s SOC variant, IRQ 0..6 are assigned
> as follow:
> IRQ 6 - NGPIO_INTR: Combined status of edge programmable
> interrupts from GPIO ports
> IRQ 5 - TX_OR_INTR: I2S interrupt on Transmit FIFO overrun
> IRQ 4 - TX_EMP_INTR: I2S interrupt on Transmit FIFO empty
> IRQ 3 - RX_OR_INTR: I2S interrupt on Receive FIFO overrun
> IRQ 2 - RX_DA_INTR: I2S interrupt on data available in Receive FIFO
> IRQ 1 - Reserved
> IRQ 0 - GPIO_INTR: Legacy interrupt from GPIO ports
>
> Add support for these IRQs in SPEAr320 SOC family.
>
> Signed-off-by: Herve Codina <[email protected]>

Acked-by: Linus Walleij <[email protected]>

Yours,
Linus Walleij

2021-12-13 16:29:34

by Arnd Bergmann

[permalink] [raw]
Subject: Re: [PATCH 5/6] irq: spear-shirq: Add support for IRQ 0..6

On Thu, Dec 2, 2021 at 10:52 AM Herve Codina <[email protected]> wrote:
>
> IRQ 0..7 are not supported by the driver for SPEAr320 SOC family.
>
> IRQ 0 is not reserved in SPEAr320 SOC (assigned to GPIOINT).
> Furthermore, in SPEAr320s SOC variant, IRQ 0..6 are assigned
> as follow:
> IRQ 6 - NGPIO_INTR: Combined status of edge programmable
> interrupts from GPIO ports
> IRQ 5 - TX_OR_INTR: I2S interrupt on Transmit FIFO overrun
> IRQ 4 - TX_EMP_INTR: I2S interrupt on Transmit FIFO empty
> IRQ 3 - RX_OR_INTR: I2S interrupt on Receive FIFO overrun
> IRQ 2 - RX_DA_INTR: I2S interrupt on data available in Receive FIFO
> IRQ 1 - Reserved
> IRQ 0 - GPIO_INTR: Legacy interrupt from GPIO ports
>
> Add support for these IRQs in SPEAr320 SOC family.
>
> Signed-off-by: Herve Codina <[email protected]>

Acked-by: Arnd Bergmann <[email protected]>

I took patches 4 and 6 into the soc tree now.

Arnd

Subject: [irqchip: irq/irqchip-next] irqchip/spear-shirq: Add support for IRQ 0..6

The following commit has been merged into the irq/irqchip-next branch of irqchip:

Commit-ID: f63c862587c9ba1c62de8c549e8f2fbe0fc88b6b
Gitweb: https://git.kernel.org/pub/scm/linux/kernel/git/maz/arm-platforms/f63c862587c9ba1c62de8c549e8f2fbe0fc88b6b
Author: Herve Codina <[email protected]>
AuthorDate: Thu, 02 Dec 2021 10:52:54 +01:00
Committer: Marc Zyngier <[email protected]>
CommitterDate: Thu, 16 Dec 2021 13:29:44

irqchip/spear-shirq: Add support for IRQ 0..6

IRQ 0..7 are not supported by the driver for SPEAr320 SOC family.

IRQ 0 is not reserved in SPEAr320 SOC (assigned to GPIOINT).
Furthermore, in SPEAr320s SOC variant, IRQ 0..6 are assigned
as follow:
IRQ 6 - NGPIO_INTR: Combined status of edge programmable
interrupts from GPIO ports
IRQ 5 - TX_OR_INTR: I2S interrupt on Transmit FIFO overrun
IRQ 4 - TX_EMP_INTR: I2S interrupt on Transmit FIFO empty
IRQ 3 - RX_OR_INTR: I2S interrupt on Receive FIFO overrun
IRQ 2 - RX_DA_INTR: I2S interrupt on data available in Receive FIFO
IRQ 1 - Reserved
IRQ 0 - GPIO_INTR: Legacy interrupt from GPIO ports

Add support for these IRQs in SPEAr320 SOC family.

Signed-off-by: Herve Codina <[email protected]>
Acked-by: Linus Walleij <[email protected]>
Acked-by: Arnd Bergmann <[email protected]>
Acked-by: Viresh Kumar <[email protected]>
Signed-off-by: Marc Zyngier <[email protected]>
Link: https://lore.kernel.org/r/[email protected]
---
drivers/irqchip/spear-shirq.c | 2 ++
1 file changed, 2 insertions(+)

diff --git a/drivers/irqchip/spear-shirq.c b/drivers/irqchip/spear-shirq.c
index 1518ba3..7c17a6f 100644
--- a/drivers/irqchip/spear-shirq.c
+++ b/drivers/irqchip/spear-shirq.c
@@ -149,6 +149,8 @@ static struct spear_shirq spear320_shirq_ras3 = {
.offset = 0,
.nr_irqs = 7,
.mask = ((0x1 << 7) - 1) << 0,
+ .irq_chip = &dummy_irq_chip,
+ .status_reg = SPEAR320_INT_STS_MASK_REG,
};

static struct spear_shirq spear320_shirq_ras1 = {