From: Claudiu Beznea <[email protected]>
Hi,
Series adds support for IA55 available on RZ/G3S SoC.
Patches are split as follows:
- 1/7 updates documentation
- 2/7 adds IA55 clock
- 3/7 minor cleanup on the way TITSR fields are populated
- 4/7 implement restriction described in HW manual for ISCR register
- 5/7 adds support for suspend to RAM
- 6/7 minor cleanup that replaces spaces with tabs on macro definition
- 7/7 adds IA55 device tree node
Thank you,
Claudiu Beznea
Claudiu Beznea (7):
dt-bindings: interrupt-controller: renesas,rzg2l-irqc: document RZ/G3S
clk: renesas: r9a08g045: add IA55 pclk and its reset
irqchip/renesas-rzg2l: add macros to retrieve TITSR index and
associated selector
irqchip/renesas-rzg2l: implement restriction when writing ISCR
register
irqchip/renesas-rzg2l: cache registers on suspend/resume
irqchip/renesas-rzg2l: use tabs instead of spaces
arm64: dts: renesas: r9108g045: add irqc
.../renesas,rzg2l-irqc.yaml | 5 +-
arch/arm64/boot/dts/renesas/r9a08g045.dtsi | 68 +++++++++++
drivers/clk/renesas/r9a08g045-cpg.c | 3 +
drivers/irqchip/irq-renesas-rzg2l.c | 111 ++++++++++++------
4 files changed, 152 insertions(+), 35 deletions(-)
--
2.39.2
From: Claudiu Beznea <[email protected]>
Document RZ/G3S (R9108G045) interrupt controller. This has few extra
functionalities compared with RZ/G2UL but the already existing driver
could still be used.
Signed-off-by: Claudiu Beznea <[email protected]>
---
.../bindings/interrupt-controller/renesas,rzg2l-irqc.yaml | 5 ++++-
1 file changed, 4 insertions(+), 1 deletion(-)
diff --git a/Documentation/devicetree/bindings/interrupt-controller/renesas,rzg2l-irqc.yaml b/Documentation/devicetree/bindings/interrupt-controller/renesas,rzg2l-irqc.yaml
index 2ef3081eaaf3..d3b5aec0a3f7 100644
--- a/Documentation/devicetree/bindings/interrupt-controller/renesas,rzg2l-irqc.yaml
+++ b/Documentation/devicetree/bindings/interrupt-controller/renesas,rzg2l-irqc.yaml
@@ -26,6 +26,7 @@ properties:
- renesas,r9a07g043u-irqc # RZ/G2UL
- renesas,r9a07g044-irqc # RZ/G2{L,LC}
- renesas,r9a07g054-irqc # RZ/V2L
+ - renesas,r9a08g045-irqc # RZ/G3S
- const: renesas,rzg2l-irqc
'#interrupt-cells':
@@ -167,7 +168,9 @@ allOf:
properties:
compatible:
contains:
- const: renesas,r9a07g043u-irqc
+ enum:
+ - renesas,r9a07g043u-irqc
+ - renesas,r9a08g045-irqc
then:
properties:
interrupts:
--
2.39.2
From: Claudiu Beznea <[email protected]>
Add macros to retrieve TITSR register index and associated selector.
Signed-off-by: Claudiu Beznea <[email protected]>
---
drivers/irqchip/irq-renesas-rzg2l.c | 26 +++++++++++---------------
1 file changed, 11 insertions(+), 15 deletions(-)
diff --git a/drivers/irqchip/irq-renesas-rzg2l.c b/drivers/irqchip/irq-renesas-rzg2l.c
index fe8d516f3614..9ce0d6d67486 100644
--- a/drivers/irqchip/irq-renesas-rzg2l.c
+++ b/drivers/irqchip/irq-renesas-rzg2l.c
@@ -28,8 +28,7 @@
#define ISCR 0x10
#define IITSR 0x14
#define TSCR 0x20
-#define TITSR0 0x24
-#define TITSR1 0x28
+#define TITSR(n) (0x24 + (n) * 4)
#define TITSR0_MAX_INT 16
#define TITSEL_WIDTH 0x2
#define TSSR(n) (0x30 + ((n) * 4))
@@ -45,6 +44,8 @@
#define TITSR_TITSEL_EDGE_FALLING 1
#define TITSR_TITSEL_LEVEL_HIGH 2
#define TITSR_TITSEL_LEVEL_LOW 3
+#define TITSR_HWIRQ_TO_INDEX(hwirq) ((hwirq) >> TITSR0_MAX_INT)
+#define TITSR_HWIRQ_TO_SEL(hwirq) ((hwirq) & 0xF) /* 0xF = TITSR0_MAX_INT - 1*/
#define IITSR_IITSEL(n, sense) ((sense) << ((n) * 2))
#define IITSR_IITSEL_LEVEL_LOW 0
@@ -185,12 +186,10 @@ static int rzg2l_irq_set_type(struct irq_data *d, unsigned int type)
static int rzg2l_tint_set_edge(struct irq_data *d, unsigned int type)
{
+ unsigned int hwirq = irqd_to_hwirq(d) - IRQC_TINT_START;
struct rzg2l_irqc_priv *priv = irq_data_to_priv(d);
- unsigned int hwirq = irqd_to_hwirq(d);
- u32 titseln = hwirq - IRQC_TINT_START;
- u32 offset;
+ u32 index, sel, reg;
u8 sense;
- u32 reg;
switch (type & IRQ_TYPE_SENSE_MASK) {
case IRQ_TYPE_EDGE_RISING:
@@ -205,17 +204,14 @@ static int rzg2l_tint_set_edge(struct irq_data *d, unsigned int type)
return -EINVAL;
}
- offset = TITSR0;
- if (titseln >= TITSR0_MAX_INT) {
- titseln -= TITSR0_MAX_INT;
- offset = TITSR1;
- }
+ index = TITSR_HWIRQ_TO_INDEX(hwirq);
+ sel = TITSR_HWIRQ_TO_SEL(hwirq);
raw_spin_lock(&priv->lock);
- reg = readl_relaxed(priv->base + offset);
- reg &= ~(IRQ_MASK << (titseln * TITSEL_WIDTH));
- reg |= sense << (titseln * TITSEL_WIDTH);
- writel_relaxed(reg, priv->base + offset);
+ reg = readl_relaxed(priv->base + TITSR(index));
+ reg &= ~(IRQ_MASK << (sel * TITSEL_WIDTH));
+ reg |= sense << (sel * TITSEL_WIDTH);
+ writel_relaxed(reg, priv->base + TITSR(index));
raw_spin_unlock(&priv->lock);
return 0;
--
2.39.2
From: Claudiu Beznea <[email protected]>
Cache registers content when going to suspend and restore them in resume
as these may be lost when switching to deep sleep states. With this
driver data has been marked as static to be able to play with it
in struct syscon_ops::{suspend, resume}. Because IA55 input is from
pin controller and IA55 resumes before pin controller we don't restore
interrupt enable bits here but let the pinctrl to do it on IA55 behalf
after pins are in proper state to avoid invalid interrupts.
Signed-off-by: Claudiu Beznea <[email protected]>
---
drivers/irqchip/irq-renesas-rzg2l.c | 67 +++++++++++++++++++++++------
1 file changed, 54 insertions(+), 13 deletions(-)
diff --git a/drivers/irqchip/irq-renesas-rzg2l.c b/drivers/irqchip/irq-renesas-rzg2l.c
index 1ed9cb7178fa..e5e158bf028d 100644
--- a/drivers/irqchip/irq-renesas-rzg2l.c
+++ b/drivers/irqchip/irq-renesas-rzg2l.c
@@ -18,6 +18,7 @@
#include <linux/pm_runtime.h>
#include <linux/reset.h>
#include <linux/spinlock.h>
+#include <linux/syscore_ops.h>
#define IRQC_IRQ_START 1
#define IRQC_IRQ_COUNT 8
@@ -39,6 +40,7 @@
#define TSSR_OFFSET(n) ((n) % 4)
#define TSSR_INDEX(n) ((n) / 4)
+#define TSSR_MAX_INDEX 8
#define TITSR_TITSEL_EDGE_RISING 0
#define TITSR_TITSEL_EDGE_FALLING 1
@@ -57,11 +59,22 @@
#define TINT_EXTRACT_HWIRQ(x) FIELD_GET(GENMASK(15, 0), (x))
#define TINT_EXTRACT_GPIOINT(x) FIELD_GET(GENMASK(31, 16), (x))
-struct rzg2l_irqc_priv {
+/**
+ * struct rzg2l_irqc_reg_cache - register cache
+ * @iitsr: IITSR register
+ * @titsr: TITSR registers
+ */
+struct rzg2l_irqc_reg_cache {
+ u32 iitsr;
+ u32 titsr[2];
+};
+
+static struct rzg2l_irqc_priv {
void __iomem *base;
struct irq_fwspec fwspec[IRQC_NUM_IRQ];
raw_spinlock_t lock;
-};
+ struct rzg2l_irqc_reg_cache cache;
+} priv;
static struct rzg2l_irqc_priv *irq_data_to_priv(struct irq_data *data)
{
@@ -238,6 +251,37 @@ static int rzg2l_irqc_set_type(struct irq_data *d, unsigned int type)
return irq_chip_set_type_parent(d, IRQ_TYPE_LEVEL_HIGH);
}
+static int rzg2l_irqc_irq_suspend(void)
+{
+ struct rzg2l_irqc_reg_cache *cache = &priv.cache;
+
+ cache->iitsr = readl_relaxed(priv.base + IITSR);
+ for (u8 i = 0; i < 2; i++)
+ cache->titsr[i] = readl_relaxed(priv.base + TITSR(i));
+
+ return 0;
+}
+
+static void rzg2l_irqc_irq_resume(void)
+{
+ struct rzg2l_irqc_reg_cache *cache = &priv.cache;
+ u8 i;
+
+ /*
+ * Restore only interrupt type. TSSRx will be restored at the
+ * request of pin controller to avoid spurious interrupts due
+ * to invalid PIN states.
+ */
+ for (i = 0; i < 2; i++)
+ writel_relaxed(cache->titsr[i], priv.base + TITSR(i));
+ writel_relaxed(cache->iitsr, priv.base + IITSR);
+}
+
+static struct syscore_ops rzg2l_irqc_syscore_ops = {
+ .suspend = rzg2l_irqc_irq_suspend,
+ .resume = rzg2l_irqc_irq_resume,
+};
+
static const struct irq_chip irqc_chip = {
.name = "rzg2l-irqc",
.irq_eoi = rzg2l_irqc_eoi,
@@ -323,7 +367,6 @@ static int rzg2l_irqc_init(struct device_node *node, struct device_node *parent)
struct irq_domain *irq_domain, *parent_domain;
struct platform_device *pdev;
struct reset_control *resetn;
- struct rzg2l_irqc_priv *priv;
int ret;
pdev = of_find_device_by_node(node);
@@ -336,15 +379,11 @@ static int rzg2l_irqc_init(struct device_node *node, struct device_node *parent)
return -ENODEV;
}
- priv = devm_kzalloc(&pdev->dev, sizeof(*priv), GFP_KERNEL);
- if (!priv)
- return -ENOMEM;
+ priv.base = devm_of_iomap(&pdev->dev, pdev->dev.of_node, 0, NULL);
+ if (IS_ERR(priv.base))
+ return PTR_ERR(priv.base);
- priv->base = devm_of_iomap(&pdev->dev, pdev->dev.of_node, 0, NULL);
- if (IS_ERR(priv->base))
- return PTR_ERR(priv->base);
-
- ret = rzg2l_irqc_parse_interrupts(priv, node);
+ ret = rzg2l_irqc_parse_interrupts(&priv, node);
if (ret) {
dev_err(&pdev->dev, "cannot parse interrupts: %d\n", ret);
return ret;
@@ -367,17 +406,19 @@ static int rzg2l_irqc_init(struct device_node *node, struct device_node *parent)
goto pm_disable;
}
- raw_spin_lock_init(&priv->lock);
+ raw_spin_lock_init(&priv.lock);
irq_domain = irq_domain_add_hierarchy(parent_domain, 0, IRQC_NUM_IRQ,
node, &rzg2l_irqc_domain_ops,
- priv);
+ &priv);
if (!irq_domain) {
dev_err(&pdev->dev, "failed to add irq domain\n");
ret = -ENOMEM;
goto pm_put;
}
+ register_syscore_ops(&rzg2l_irqc_syscore_ops);
+
return 0;
pm_put:
--
2.39.2
From: Claudiu Beznea <[email protected]>
Use tabs instead of spaces in definition of TINT_EXTRACT_HWIRQ()
and TINT_EXTRACT_GPIOINT() macros.
Signed-off-by: Claudiu Beznea <[email protected]>
---
drivers/irqchip/irq-renesas-rzg2l.c | 4 ++--
1 file changed, 2 insertions(+), 2 deletions(-)
diff --git a/drivers/irqchip/irq-renesas-rzg2l.c b/drivers/irqchip/irq-renesas-rzg2l.c
index e5e158bf028d..ce50745bba87 100644
--- a/drivers/irqchip/irq-renesas-rzg2l.c
+++ b/drivers/irqchip/irq-renesas-rzg2l.c
@@ -56,8 +56,8 @@
#define IITSR_IITSEL_EDGE_BOTH 3
#define IITSR_IITSEL_MASK(n) IITSR_IITSEL((n), 3)
-#define TINT_EXTRACT_HWIRQ(x) FIELD_GET(GENMASK(15, 0), (x))
-#define TINT_EXTRACT_GPIOINT(x) FIELD_GET(GENMASK(31, 16), (x))
+#define TINT_EXTRACT_HWIRQ(x) FIELD_GET(GENMASK(15, 0), (x))
+#define TINT_EXTRACT_GPIOINT(x) FIELD_GET(GENMASK(31, 16), (x))
/**
* struct rzg2l_irqc_reg_cache - register cache
--
2.39.2
From: Claudiu Beznea <[email protected]>
In hardware manual of RZ/G2L (r01uh0914ej0130-rzg2l-rzg2lc.pdf)
is available the following statement with regards to clearing interrupts
though ISCR register:
[Write operation]
When "Falling-edge detection", "Rising-edge detection" or
"Falling/Rising-edge detection" is set in ISCR.:
- In case ISTAT is 1
0: IRQn interrupt detection status is cleared.
1: Invalid to write.
- In case ISTAT is 0
Invalid to write.
When “Low-level detection” is set in IITSR.:
Invalid to write.
Thus, take into account interrupt type when clearing interrupts though
ISCR register.
Signed-off-by: Claudiu Beznea <[email protected]>
---
drivers/irqchip/irq-renesas-rzg2l.c | 14 ++++++++++----
1 file changed, 10 insertions(+), 4 deletions(-)
diff --git a/drivers/irqchip/irq-renesas-rzg2l.c b/drivers/irqchip/irq-renesas-rzg2l.c
index 9ce0d6d67486..1ed9cb7178fa 100644
--- a/drivers/irqchip/irq-renesas-rzg2l.c
+++ b/drivers/irqchip/irq-renesas-rzg2l.c
@@ -73,11 +73,17 @@ static void rzg2l_irq_eoi(struct irq_data *d)
unsigned int hw_irq = irqd_to_hwirq(d) - IRQC_IRQ_START;
struct rzg2l_irqc_priv *priv = irq_data_to_priv(d);
u32 bit = BIT(hw_irq);
- u32 reg;
+ u32 iitsr, iscr;
- reg = readl_relaxed(priv->base + ISCR);
- if (reg & bit)
- writel_relaxed(reg & ~bit, priv->base + ISCR);
+ iscr = readl_relaxed(priv->base + ISCR);
+ iitsr = readl_relaxed(priv->base + IITSR);
+
+ /*
+ * ISCR could be cleared only if type is falling-edge, rising-edge or
+ * falling/rising-edge.
+ */
+ if ((iscr & bit) && (iitsr & IITSR_IITSEL_MASK(hw_irq)))
+ writel_relaxed(iscr & ~bit, priv->base + ISCR);
}
static void rzg2l_tint_eoi(struct irq_data *d)
--
2.39.2
From: Claudiu Beznea <[email protected]>
Add IA55 pclk and its reset.
Signed-off-by: Claudiu Beznea <[email protected]>
---
drivers/clk/renesas/r9a08g045-cpg.c | 3 +++
1 file changed, 3 insertions(+)
diff --git a/drivers/clk/renesas/r9a08g045-cpg.c b/drivers/clk/renesas/r9a08g045-cpg.c
index 4394cb241d99..ea3beca8b4e0 100644
--- a/drivers/clk/renesas/r9a08g045-cpg.c
+++ b/drivers/clk/renesas/r9a08g045-cpg.c
@@ -188,6 +188,7 @@ static const struct cpg_core_clk r9a08g045_core_clks[] __initconst = {
static const struct rzg2l_mod_clk r9a08g045_mod_clks[] = {
DEF_MOD("gic_gicclk", R9A08G045_GIC600_GICCLK, R9A08G045_CLK_P1, 0x514, 0),
+ DEF_MOD("ia55_pclk", R9A08G045_IA55_PCLK, R9A08G045_CLK_P2, 0x518, 0),
DEF_MOD("ia55_clk", R9A08G045_IA55_CLK, R9A08G045_CLK_P1, 0x518, 1),
DEF_MOD("dmac_aclk", R9A08G045_DMAC_ACLK, R9A08G045_CLK_P3, 0x52c, 0),
DEF_MOD("sdhi0_imclk", R9A08G045_SDHI0_IMCLK, CLK_SD0_DIV4, 0x554, 0),
@@ -209,6 +210,7 @@ static const struct rzg2l_mod_clk r9a08g045_mod_clks[] = {
static const struct rzg2l_reset r9a08g045_resets[] = {
DEF_RST(R9A08G045_GIC600_GICRESET_N, 0x814, 0),
DEF_RST(R9A08G045_GIC600_DBG_GICRESET_N, 0x814, 1),
+ DEF_RST(R9A08G045_IA55_RESETN, 0x818, 0),
DEF_RST(R9A08G045_SDHI0_IXRST, 0x854, 0),
DEF_RST(R9A08G045_SDHI1_IXRST, 0x854, 1),
DEF_RST(R9A08G045_SDHI2_IXRST, 0x854, 2),
@@ -220,6 +222,7 @@ static const struct rzg2l_reset r9a08g045_resets[] = {
static const unsigned int r9a08g045_crit_mod_clks[] __initconst = {
MOD_CLK_BASE + R9A08G045_GIC600_GICCLK,
+ MOD_CLK_BASE + R9A08G045_IA55_PCLK,
MOD_CLK_BASE + R9A08G045_IA55_CLK,
MOD_CLK_BASE + R9A08G045_DMAC_ACLK,
};
--
2.39.2
From: Claudiu Beznea <[email protected]>
Add irqc node and set it as interrupt parent for pin controller.
Signed-off-by: Claudiu Beznea <[email protected]>
---
arch/arm64/boot/dts/renesas/r9a08g045.dtsi | 68 ++++++++++++++++++++++
1 file changed, 68 insertions(+)
diff --git a/arch/arm64/boot/dts/renesas/r9a08g045.dtsi b/arch/arm64/boot/dts/renesas/r9a08g045.dtsi
index 6c7b29b69d0e..010bca626855 100644
--- a/arch/arm64/boot/dts/renesas/r9a08g045.dtsi
+++ b/arch/arm64/boot/dts/renesas/r9a08g045.dtsi
@@ -96,6 +96,7 @@ pinctrl: pinctrl@11030000 {
#gpio-cells = <2>;
interrupt-controller;
#interrupt-cells = <2>;
+ interrupt-parent = <&irqc>;
gpio-ranges = <&pinctrl 0 0 152>;
clocks = <&cpg CPG_MOD R9A08G045_GPIO_HCLK>;
power-domains = <&cpg>;
@@ -104,6 +105,73 @@ pinctrl: pinctrl@11030000 {
<&cpg R9A08G045_GPIO_SPARE_RESETN>;
};
+ irqc: interrupt-controller@11050000 {
+ compatible = "renesas,r9a08g045-irqc", "renesas,rzg2l-irqc";
+ #interrupt-cells = <2>;
+ #address-cells = <0>;
+ interrupt-controller;
+ reg = <0 0x11050000 0 0x10000>;
+ interrupts = <GIC_SPI 0 IRQ_TYPE_LEVEL_HIGH>,
+ <GIC_SPI 1 IRQ_TYPE_LEVEL_HIGH>,
+ <GIC_SPI 2 IRQ_TYPE_LEVEL_HIGH>,
+ <GIC_SPI 3 IRQ_TYPE_LEVEL_HIGH>,
+ <GIC_SPI 4 IRQ_TYPE_LEVEL_HIGH>,
+ <GIC_SPI 5 IRQ_TYPE_LEVEL_HIGH>,
+ <GIC_SPI 6 IRQ_TYPE_LEVEL_HIGH>,
+ <GIC_SPI 7 IRQ_TYPE_LEVEL_HIGH>,
+ <GIC_SPI 8 IRQ_TYPE_LEVEL_HIGH>,
+ <GIC_SPI 429 IRQ_TYPE_LEVEL_HIGH>,
+ <GIC_SPI 430 IRQ_TYPE_LEVEL_HIGH>,
+ <GIC_SPI 431 IRQ_TYPE_LEVEL_HIGH>,
+ <GIC_SPI 432 IRQ_TYPE_LEVEL_HIGH>,
+ <GIC_SPI 433 IRQ_TYPE_LEVEL_HIGH>,
+ <GIC_SPI 434 IRQ_TYPE_LEVEL_HIGH>,
+ <GIC_SPI 435 IRQ_TYPE_LEVEL_HIGH>,
+ <GIC_SPI 436 IRQ_TYPE_LEVEL_HIGH>,
+ <GIC_SPI 437 IRQ_TYPE_LEVEL_HIGH>,
+ <GIC_SPI 438 IRQ_TYPE_LEVEL_HIGH>,
+ <GIC_SPI 439 IRQ_TYPE_LEVEL_HIGH>,
+ <GIC_SPI 440 IRQ_TYPE_LEVEL_HIGH>,
+ <GIC_SPI 441 IRQ_TYPE_LEVEL_HIGH>,
+ <GIC_SPI 442 IRQ_TYPE_LEVEL_HIGH>,
+ <GIC_SPI 443 IRQ_TYPE_LEVEL_HIGH>,
+ <GIC_SPI 444 IRQ_TYPE_LEVEL_HIGH>,
+ <GIC_SPI 445 IRQ_TYPE_LEVEL_HIGH>,
+ <GIC_SPI 446 IRQ_TYPE_LEVEL_HIGH>,
+ <GIC_SPI 447 IRQ_TYPE_LEVEL_HIGH>,
+ <GIC_SPI 448 IRQ_TYPE_LEVEL_HIGH>,
+ <GIC_SPI 449 IRQ_TYPE_LEVEL_HIGH>,
+ <GIC_SPI 450 IRQ_TYPE_LEVEL_HIGH>,
+ <GIC_SPI 451 IRQ_TYPE_LEVEL_HIGH>,
+ <GIC_SPI 452 IRQ_TYPE_LEVEL_HIGH>,
+ <GIC_SPI 453 IRQ_TYPE_LEVEL_HIGH>,
+ <GIC_SPI 454 IRQ_TYPE_LEVEL_HIGH>,
+ <GIC_SPI 455 IRQ_TYPE_LEVEL_HIGH>,
+ <GIC_SPI 456 IRQ_TYPE_LEVEL_HIGH>,
+ <GIC_SPI 457 IRQ_TYPE_LEVEL_HIGH>,
+ <GIC_SPI 458 IRQ_TYPE_LEVEL_HIGH>,
+ <GIC_SPI 459 IRQ_TYPE_LEVEL_HIGH>,
+ <GIC_SPI 460 IRQ_TYPE_LEVEL_HIGH>,
+ <GIC_SPI 29 IRQ_TYPE_LEVEL_HIGH>;
+ interrupt-names = "nmi",
+ "irq0", "irq1", "irq2", "irq3",
+ "irq4", "irq5", "irq6", "irq7",
+ "tint0", "tint1", "tint2", "tint3",
+ "tint4", "tint5", "tint6", "tint7",
+ "tint8", "tint9", "tint10", "tint11",
+ "tint12", "tint13", "tint14", "tint15",
+ "tint16", "tint17", "tint18", "tint19",
+ "tint20", "tint21", "tint22", "tint23",
+ "tint24", "tint25", "tint26", "tint27",
+ "tint28", "tint29", "tint30", "tint31",
+ "bus-err";
+ clocks = <&cpg CPG_MOD R9A08G045_IA55_CLK>,
+ <&cpg CPG_MOD R9A08G045_IA55_PCLK>;
+ clock-names = "clk", "pclk";
+ power-domains = <&cpg>;
+ resets = <&cpg R9A08G045_IA55_RESETN>;
+ };
+
sdhi0: mmc@11c00000 {
compatible = "renesas,sdhi-r9a08g045", "renesas,rcar-gen3-sdhi";
reg = <0x0 0x11c00000 0 0x10000>;
--
2.39.2
On Mon, Oct 23, 2023 at 01:22:17PM +0300, Claudiu wrote:
> From: Claudiu Beznea <[email protected]>
>
> Document RZ/G3S (R9108G045) interrupt controller. This has few extra
> functionalities compared with RZ/G2UL but the already existing driver
> could still be used.
>
> Signed-off-by: Claudiu Beznea <[email protected]>
Acked-by: Conor Dooley <[email protected]>
Thanks,
Conor.
> ---
> .../bindings/interrupt-controller/renesas,rzg2l-irqc.yaml | 5 ++++-
> 1 file changed, 4 insertions(+), 1 deletion(-)
>
> diff --git a/Documentation/devicetree/bindings/interrupt-controller/renesas,rzg2l-irqc.yaml b/Documentation/devicetree/bindings/interrupt-controller/renesas,rzg2l-irqc.yaml
> index 2ef3081eaaf3..d3b5aec0a3f7 100644
> --- a/Documentation/devicetree/bindings/interrupt-controller/renesas,rzg2l-irqc.yaml
> +++ b/Documentation/devicetree/bindings/interrupt-controller/renesas,rzg2l-irqc.yaml
> @@ -26,6 +26,7 @@ properties:
> - renesas,r9a07g043u-irqc # RZ/G2UL
> - renesas,r9a07g044-irqc # RZ/G2{L,LC}
> - renesas,r9a07g054-irqc # RZ/V2L
> + - renesas,r9a08g045-irqc # RZ/G3S
> - const: renesas,rzg2l-irqc
>
> '#interrupt-cells':
> @@ -167,7 +168,9 @@ allOf:
> properties:
> compatible:
> contains:
> - const: renesas,r9a07g043u-irqc
> + enum:
> + - renesas,r9a07g043u-irqc
> + - renesas,r9a08g045-irqc
> then:
> properties:
> interrupts:
> --
> 2.39.2
>
On Mon, Oct 23 2023 at 13:22, Claudiu wrote:
> From: Claudiu Beznea <[email protected]>
>
> Cache registers content when going to suspend and restore them in resume
> as these may be lost when switching to deep sleep states. With this
> driver data has been marked as static to be able to play with it
> in struct syscon_ops::{suspend, resume}.
I have no idea what you are trying to tell me here. Why do the
suspend/resume callbacks need a static data structure and cannot operate
on a pointer which wastes less builtin memory when the driver is not
used?
Also "play with it" is definitely not a technical term. See
Documentation/process/* which has lots of explanations how to write
proper change logs.
> Because IA55 input is from pin controller and IA55 resumes before pin
> controller we don't restore interrupt enable bits here but let the
> pinctrl to do it on IA55 behalf after pins are in proper state to
> avoid invalid interrupts.
> +
> +static struct rzg2l_irqc_priv {
> void __iomem *base;
> struct irq_fwspec fwspec[IRQC_NUM_IRQ];
> raw_spinlock_t lock;
> -};
> + struct rzg2l_irqc_reg_cache cache;
> +} priv;
https://www.kernel.org/doc/html/latest/process/maintainer-tip.html#struct-declarations-and-initializers
>
> static struct rzg2l_irqc_priv *irq_data_to_priv(struct irq_data *data)
> {
> @@ -238,6 +251,37 @@ static int rzg2l_irqc_set_type(struct irq_data *d, unsigned int type)
> return irq_chip_set_type_parent(d, IRQ_TYPE_LEVEL_HIGH);
> }
>
> +static int rzg2l_irqc_irq_suspend(void)
> +{
> + struct rzg2l_irqc_reg_cache *cache = &priv.cache;
> +
> + cache->iitsr = readl_relaxed(priv.base + IITSR);
> + for (u8 i = 0; i < 2; i++)
> + cache->titsr[i] = readl_relaxed(priv.base + TITSR(i));
> +
> + return 0;
> +}
> +
> +static void rzg2l_irqc_irq_resume(void)
> +{
> + struct rzg2l_irqc_reg_cache *cache = &priv.cache;
> + u8 i;
> +
> + /*
> + * Restore only interrupt type. TSSRx will be restored at the
> + * request of pin controller to avoid spurious interrupts due
> + * to invalid PIN states.
> + */
> + for (i = 0; i < 2; i++)
> + writel_relaxed(cache->titsr[i], priv.base + TITSR(i));
> + writel_relaxed(cache->iitsr, priv.base + IITSR);
> +}
> +
> +static struct syscore_ops rzg2l_irqc_syscore_ops = {
> + .suspend = rzg2l_irqc_irq_suspend,
> + .resume = rzg2l_irqc_irq_resume,
> +};
Ditto.
> static const struct irq_chip irqc_chip = {
> .name = "rzg2l-irqc",
> .irq_eoi = rzg2l_irqc_eoi,
> @@ -323,7 +367,6 @@ static int rzg2l_irqc_init(struct device_node *node, struct device_node *parent)
> struct irq_domain *irq_domain, *parent_domain;
> struct platform_device *pdev;
> struct reset_control *resetn;
> - struct rzg2l_irqc_priv *priv;
Make this pointer static at the top level and leave the rest of the code
alone and please give it a proper name. "priv" at the file level is
really non-descriptive.
Thanks,
tglx
On Mon, Oct 23 2023 at 13:22, Claudiu wrote:
> From: Claudiu Beznea <[email protected]>
>
> Use tabs instead of spaces in definition of TINT_EXTRACT_HWIRQ()
> and TINT_EXTRACT_GPIOINT() macros.
Wrong ordering. Cleanups first, features last.
> Signed-off-by: Claudiu Beznea <[email protected]>
> ---
> drivers/irqchip/irq-renesas-rzg2l.c | 4 ++--
> 1 file changed, 2 insertions(+), 2 deletions(-)
>
> diff --git a/drivers/irqchip/irq-renesas-rzg2l.c b/drivers/irqchip/irq-renesas-rzg2l.c
> index e5e158bf028d..ce50745bba87 100644
> --- a/drivers/irqchip/irq-renesas-rzg2l.c
> +++ b/drivers/irqchip/irq-renesas-rzg2l.c
> @@ -56,8 +56,8 @@
> #define IITSR_IITSEL_EDGE_BOTH 3
> #define IITSR_IITSEL_MASK(n) IITSR_IITSEL((n), 3)
>
> -#define TINT_EXTRACT_HWIRQ(x) FIELD_GET(GENMASK(15, 0), (x))
> -#define TINT_EXTRACT_GPIOINT(x) FIELD_GET(GENMASK(31, 16), (x))
> +#define TINT_EXTRACT_HWIRQ(x) FIELD_GET(GENMASK(15, 0), (x))
> +#define TINT_EXTRACT_GPIOINT(x) FIELD_GET(GENMASK(31, 16), (x))
>
> /**
> * struct rzg2l_irqc_reg_cache - register cache
On Mon, Oct 23 2023 at 13:22, Claudiu wrote:
> From: Claudiu Beznea <[email protected]>
>
> Add macros to retrieve TITSR register index and associated selector.
This is not what the patch actually does. Also please explain the WHY
and not the WHAT.
On Mon, Oct 23 2023 at 13:22, Claudiu wrote:
> In hardware manual of RZ/G2L (r01uh0914ej0130-rzg2l-rzg2lc.pdf)
This filename is completely useless.
> is available the following statement with regards to clearing
> interrupts
The RZ/G2L manual describes the operation to clear interrupts
> though ISCR register:
through the ISCR ...
>
> [Write operation]
> When "Falling-edge detection", "Rising-edge detection" or
> "Falling/Rising-edge detection" is set in ISCR.:
> - In case ISTAT is 1
> 0: IRQn interrupt detection status is cleared.
> 1: Invalid to write.
> - In case ISTAT is 0
> Invalid to write.
> When “Low-level detection” is set in IITSR.:
> Invalid to write.
>
> Thus, take into account interrupt type when clearing interrupts though
take the interrupt type into account... through the ISCR ...
> ISCR register.
>
> Signed-off-by: Claudiu Beznea <[email protected]>
> ---
> drivers/irqchip/irq-renesas-rzg2l.c | 14 ++++++++++----
> 1 file changed, 10 insertions(+), 4 deletions(-)
>
> diff --git a/drivers/irqchip/irq-renesas-rzg2l.c b/drivers/irqchip/irq-renesas-rzg2l.c
> index 9ce0d6d67486..1ed9cb7178fa 100644
> --- a/drivers/irqchip/irq-renesas-rzg2l.c
> +++ b/drivers/irqchip/irq-renesas-rzg2l.c
> @@ -73,11 +73,17 @@ static void rzg2l_irq_eoi(struct irq_data *d)
> unsigned int hw_irq = irqd_to_hwirq(d) - IRQC_IRQ_START;
> struct rzg2l_irqc_priv *priv = irq_data_to_priv(d);
> u32 bit = BIT(hw_irq);
> - u32 reg;
> + u32 iitsr, iscr;
>
> - reg = readl_relaxed(priv->base + ISCR);
> - if (reg & bit)
> - writel_relaxed(reg & ~bit, priv->base + ISCR);
> + iscr = readl_relaxed(priv->base + ISCR);
> + iitsr = readl_relaxed(priv->base + IITSR);
> +
> + /*
> + * ISCR could be cleared only if type is falling-edge, rising-edge or
ISCR can only be cleared if the type is ...
> + * falling/rising-edge.
> + */
> + if ((iscr & bit) && (iitsr & IITSR_IITSEL_MASK(hw_irq)))
> + writel_relaxed(iscr & ~bit, priv->base + ISCR);
> }
>
> static void rzg2l_tint_eoi(struct irq_data *d)