From 47ec5ac9d4e9b7e99102a282a79c47c3c6ca8b5c Mon Sep 17 00:00:00 2001 From: Claudiu Beznea Date: Fri, 3 Apr 2026 17:13:37 +0300 Subject: [PATCH 1/9] soc: renesas: r9a08g045-sysc: Move common code to a helper Move common code from rzg3s_regmap_{readable,writeable}_reg() to a helper and use it to avoid code duplication. Signed-off-by: Claudiu Beznea Reviewed-by: Geert Uytterhoeven Link: https://patch.msgid.link/20260403141341.2851926-2-claudiu.beznea.uj@bp.reneasas.com Signed-off-by: Geert Uytterhoeven --- drivers/soc/renesas/r9a08g045-sysc.c | 41 ++++++++++++---------------- 1 file changed, 18 insertions(+), 23 deletions(-) diff --git a/drivers/soc/renesas/r9a08g045-sysc.c b/drivers/soc/renesas/r9a08g045-sysc.c index 03d653d5cde5..63e4aa6a7cd0 100644 --- a/drivers/soc/renesas/r9a08g045-sysc.c +++ b/drivers/soc/renesas/r9a08g045-sysc.c @@ -37,18 +37,14 @@ static const struct rz_sysc_soc_id_init_data rzg3s_sysc_soc_id_init_data __initc .specific_id_mask = GENMASK(27, 0), }; -static bool rzg3s_regmap_readable_reg(struct device *dev, unsigned int reg) +static bool rzg3s_regmap_readable_writeable_reg(unsigned int reg) { switch (reg) { case SYS_XSPI_MAP_STAADD_CS0: case SYS_XSPI_MAP_ENDADD_CS0: case SYS_XSPI_MAP_STAADD_CS1: case SYS_XSPI_MAP_ENDADD_CS1: - case SYS_GETH0_CFG: - case SYS_GETH1_CFG: case SYS_PCIE_CFG: - case SYS_PCIE_MON: - case SYS_PCIE_ERR_MON: case SYS_PCIE_PHY: case SYS_I2C0_CFG: case SYS_I2C1_CFG: @@ -63,26 +59,25 @@ static bool rzg3s_regmap_readable_reg(struct device *dev, unsigned int reg) } } +static bool rzg3s_regmap_readable_reg(struct device *dev, unsigned int reg) +{ + if (rzg3s_regmap_readable_writeable_reg(reg)) + return true; + + switch (reg) { + case SYS_GETH0_CFG: + case SYS_GETH1_CFG: + case SYS_PCIE_MON: + case SYS_PCIE_ERR_MON: + return true; + default: + return false; + } +} + static bool rzg3s_regmap_writeable_reg(struct device *dev, unsigned int reg) { - switch (reg) { - case SYS_XSPI_MAP_STAADD_CS0: - case SYS_XSPI_MAP_ENDADD_CS0: - case SYS_XSPI_MAP_STAADD_CS1: - case SYS_XSPI_MAP_ENDADD_CS1: - case SYS_PCIE_CFG: - case SYS_PCIE_PHY: - case SYS_I2C0_CFG: - case SYS_I2C1_CFG: - case SYS_I2C2_CFG: - case SYS_I2C3_CFG: - case SYS_I3C_CFG: - case SYS_USB_PWRRDY: - case SYS_PCIE_RST_RSM_B: - return true; - default: - return false; - } + return rzg3s_regmap_readable_writeable_reg(reg); } const struct rz_sysc_init_data rzg3s_sysc_init_data __initconst = { From f47cc240848124d739a6441df962cee7a0af6514 Mon Sep 17 00:00:00 2001 From: Claudiu Beznea Date: Fri, 3 Apr 2026 17:13:38 +0300 Subject: [PATCH 2/9] soc: renesas: r9a08g046-sysc: Move common code to a helper Move common code from rzg3l_regmap_{readable,writeable}_reg() to a helper and use it to avoid code duplication. Signed-off-by: Claudiu Beznea Reviewed-by: Geert Uytterhoeven Link: https://patch.msgid.link/20260403141341.2851926-3-claudiu.beznea.uj@bp.reneasas.com Signed-off-by: Geert Uytterhoeven --- drivers/soc/renesas/r9a08g046-sysc.c | 31 ++++++++++++---------------- 1 file changed, 13 insertions(+), 18 deletions(-) diff --git a/drivers/soc/renesas/r9a08g046-sysc.c b/drivers/soc/renesas/r9a08g046-sysc.c index fd98df196d0a..90db9d383539 100644 --- a/drivers/soc/renesas/r9a08g046-sysc.c +++ b/drivers/soc/renesas/r9a08g046-sysc.c @@ -28,17 +28,14 @@ #define SYS_PWRRDY_N 0xd70 #define SYS_IPCONT_SEL_CLONECH 0xe2c -static bool rzg3l_regmap_readable_reg(struct device *dev, unsigned int reg) +static bool rzg3l_regmap_readable_writeable_reg(unsigned int reg) { switch (reg) { case SYS_XSPI_MAP_STAADD_CS0: case SYS_XSPI_MAP_ENDADD_CS0: case SYS_XSPI_MAP_STAADD_CS1: case SYS_XSPI_MAP_ENDADD_CS1: - case SYS_GETH0_CFG: - case SYS_GETH1_CFG: case SYS_PCIE_CFG: - case SYS_PCIE_MON: case SYS_PCIE_PHY: case SYS_I2C0_CFG: case SYS_I2C1_CFG: @@ -53,28 +50,26 @@ static bool rzg3l_regmap_readable_reg(struct device *dev, unsigned int reg) } } -static bool rzg3l_regmap_writeable_reg(struct device *dev, unsigned int reg) +static bool rzg3l_regmap_readable_reg(struct device *dev, unsigned int reg) { + if (rzg3l_regmap_readable_writeable_reg(reg)) + return true; + switch (reg) { - case SYS_XSPI_MAP_STAADD_CS0: - case SYS_XSPI_MAP_ENDADD_CS0: - case SYS_XSPI_MAP_STAADD_CS1: - case SYS_XSPI_MAP_ENDADD_CS1: - case SYS_PCIE_CFG: - case SYS_PCIE_PHY: - case SYS_I2C0_CFG: - case SYS_I2C1_CFG: - case SYS_I2C2_CFG: - case SYS_I2C3_CFG: - case SYS_I3C_CFG: - case SYS_PWRRDY_N: - case SYS_IPCONT_SEL_CLONECH: + case SYS_GETH0_CFG: + case SYS_GETH1_CFG: + case SYS_PCIE_MON: return true; default: return false; } } +static bool rzg3l_regmap_writeable_reg(struct device *dev, unsigned int reg) +{ + return rzg3l_regmap_readable_writeable_reg(reg); +} + static const struct rz_sysc_soc_id_init_data rzg3l_sysc_soc_id_init_data __initconst = { .family = "RZ/G3L", .id = 0x87d9447, From 3e9f1b1f771c686fcd0a46ee6a9155e398ed7afe Mon Sep 17 00:00:00 2001 From: Claudiu Beznea Date: Fri, 3 Apr 2026 17:13:39 +0300 Subject: [PATCH 3/9] soc: renesas: r9a09g047-sys: Move common code to a helper Move common code from rzg3e_regmap_{readable,writeable}_reg() to a helper and use it to avoid code duplication. Signed-off-by: Claudiu Beznea Reviewed-by: Geert Uytterhoeven Link: https://patch.msgid.link/20260403141341.2851926-4-claudiu.beznea.uj@bp.reneasas.com Signed-off-by: Geert Uytterhoeven --- drivers/soc/renesas/r9a09g047-sys.c | 42 +++++++++++------------------ 1 file changed, 16 insertions(+), 26 deletions(-) diff --git a/drivers/soc/renesas/r9a09g047-sys.c b/drivers/soc/renesas/r9a09g047-sys.c index ea3ca10fcc33..b617fb0bde7b 100644 --- a/drivers/soc/renesas/r9a09g047-sys.c +++ b/drivers/soc/renesas/r9a09g047-sys.c @@ -83,11 +83,9 @@ static const struct rz_sysc_soc_id_init_data rzg3e_sys_soc_id_init_data __initco .print_id = rzg3e_sys_print_id, }; -static bool rzg3e_regmap_readable_reg(struct device *dev, unsigned int reg) +static bool rzg3e_regmap_readable_writeable_reg(unsigned int reg) { switch (reg) { - case SYS_LSI_OTPTSU1TRMVAL0: - case SYS_LSI_OTPTSU1TRMVAL1: case SYS_SPI_STAADDCS0: case SYS_SPI_ENDADDCS0: case SYS_SPI_STAADDCS1: @@ -112,31 +110,23 @@ static bool rzg3e_regmap_readable_reg(struct device *dev, unsigned int reg) } } +static bool rzg3e_regmap_readable_reg(struct device *dev, unsigned int reg) +{ + if (rzg3e_regmap_readable_writeable_reg(reg)) + return true; + + switch (reg) { + case SYS_LSI_OTPTSU1TRMVAL0: + case SYS_LSI_OTPTSU1TRMVAL1: + return true; + default: + return false; + } +} + static bool rzg3e_regmap_writeable_reg(struct device *dev, unsigned int reg) { - switch (reg) { - case SYS_SPI_STAADDCS0: - case SYS_SPI_ENDADDCS0: - case SYS_SPI_STAADDCS1: - case SYS_SPI_ENDADDCS1: - case SYS_VSP_CLK: - case SYS_GBETH0_CFG: - case SYS_GBETH1_CFG: - case SYS_PCIE_INTX_CH0: - case SYS_PCIE_MSI1_CH0: - case SYS_PCIE_MSI2_CH0: - case SYS_PCIE_MSI3_CH0: - case SYS_PCIE_MSI4_CH0: - case SYS_PCIE_MSI5_CH0: - case SYS_PCIE_PME_CH0: - case SYS_PCIE_ACK_CH0: - case SYS_PCIE_MISC_CH0: - case SYS_PCIE_MODE_CH0: - case SYS_ADC_CFG: - return true; - default: - return false; - } + return rzg3e_regmap_readable_writeable_reg(reg); } const struct rz_sysc_init_data rzg3e_sys_init_data __initconst = { From ac8fae64acd105f4943a635f2a9f7c6e3328c58b Mon Sep 17 00:00:00 2001 From: Claudiu Beznea Date: Fri, 3 Apr 2026 17:13:40 +0300 Subject: [PATCH 4/9] soc: renesas: r9a09g056-sys: Move common code to a helper Move common code from rzv2n_regmap_{readable,writeable}_reg() to a helper and use it to avoid code duplication. Signed-off-by: Claudiu Beznea Reviewed-by: Geert Uytterhoeven Link: https://patch.msgid.link/20260403141341.2851926-5-claudiu.beznea.uj@bp.reneasas.com Signed-off-by: Geert Uytterhoeven --- drivers/soc/renesas/r9a09g056-sys.c | 41 +++++++++++++---------------- 1 file changed, 18 insertions(+), 23 deletions(-) diff --git a/drivers/soc/renesas/r9a09g056-sys.c b/drivers/soc/renesas/r9a09g056-sys.c index 2a8ebc209961..e6a66688423f 100644 --- a/drivers/soc/renesas/r9a09g056-sys.c +++ b/drivers/soc/renesas/r9a09g056-sys.c @@ -88,13 +88,9 @@ static const struct rz_sysc_soc_id_init_data rzv2n_sys_soc_id_init_data __initco .print_id = rzv2n_sys_print_id, }; -static bool rzv2n_regmap_readable_reg(struct device *dev, unsigned int reg) +static bool rzv2n_regmap_readable_writeable_reg(unsigned int reg) { switch (reg) { - case SYS_LSI_OTPTSU0TRMVAL0: - case SYS_LSI_OTPTSU0TRMVAL1: - case SYS_LSI_OTPTSU1TRMVAL0: - case SYS_LSI_OTPTSU1TRMVAL1: case SYS_GBETH0_CFG: case SYS_GBETH1_CFG: case SYS_PCIE_INTX_CH0: @@ -114,26 +110,25 @@ static bool rzv2n_regmap_readable_reg(struct device *dev, unsigned int reg) } } +static bool rzv2n_regmap_readable_reg(struct device *dev, unsigned int reg) +{ + if (rzv2n_regmap_readable_writeable_reg(reg)) + return true; + + switch (reg) { + case SYS_LSI_OTPTSU0TRMVAL0: + case SYS_LSI_OTPTSU0TRMVAL1: + case SYS_LSI_OTPTSU1TRMVAL0: + case SYS_LSI_OTPTSU1TRMVAL1: + return true; + default: + return false; + } +} + static bool rzv2n_regmap_writeable_reg(struct device *dev, unsigned int reg) { - switch (reg) { - case SYS_GBETH0_CFG: - case SYS_GBETH1_CFG: - case SYS_PCIE_INTX_CH0: - case SYS_PCIE_MSI1_CH0: - case SYS_PCIE_MSI2_CH0: - case SYS_PCIE_MSI3_CH0: - case SYS_PCIE_MSI4_CH0: - case SYS_PCIE_MSI5_CH0: - case SYS_PCIE_PME_CH0: - case SYS_PCIE_ACK_CH0: - case SYS_PCIE_MISC_CH0: - case SYS_PCIE_MODE_CH0: - case SYS_ADC_CFG: - return true; - default: - return false; - } + return rzv2n_regmap_readable_writeable_reg(reg); } const struct rz_sysc_init_data rzv2n_sys_init_data __initconst = { From 269337466db3649abea4c294b4154a916e0e3a99 Mon Sep 17 00:00:00 2001 From: Claudiu Beznea Date: Fri, 3 Apr 2026 17:13:41 +0300 Subject: [PATCH 5/9] soc: renesas: r9a09g057-sys: Move common code to a helper Move common code from rzv2h_regmap_{readable,writeable}_reg() to a helper and use it to avoid code duplication. Signed-off-by: Claudiu Beznea Reviewed-by: Geert Uytterhoeven Link: https://patch.msgid.link/20260403141341.2851926-6-claudiu.beznea.uj@bp.reneasas.com Signed-off-by: Geert Uytterhoeven --- drivers/soc/renesas/r9a09g057-sys.c | 52 ++++++++++------------------- 1 file changed, 18 insertions(+), 34 deletions(-) diff --git a/drivers/soc/renesas/r9a09g057-sys.c b/drivers/soc/renesas/r9a09g057-sys.c index f3e054206acb..308492c31acb 100644 --- a/drivers/soc/renesas/r9a09g057-sys.c +++ b/drivers/soc/renesas/r9a09g057-sys.c @@ -91,13 +91,9 @@ static const struct rz_sysc_soc_id_init_data rzv2h_sys_soc_id_init_data __initco .print_id = rzv2h_sys_print_id, }; -static bool rzv2h_regmap_readable_reg(struct device *dev, unsigned int reg) +static bool rzv2h_regmap_readable_writeable_reg(unsigned int reg) { switch (reg) { - case SYS_LSI_OTPTSU0TRMVAL0: - case SYS_LSI_OTPTSU0TRMVAL1: - case SYS_LSI_OTPTSU1TRMVAL0: - case SYS_LSI_OTPTSU1TRMVAL1: case SYS_GBETH0_CFG: case SYS_GBETH1_CFG: case SYS_PCIE_INTX_CH0: @@ -128,37 +124,25 @@ static bool rzv2h_regmap_readable_reg(struct device *dev, unsigned int reg) } } +static bool rzv2h_regmap_readable_reg(struct device *dev, unsigned int reg) +{ + if (rzv2h_regmap_readable_writeable_reg(reg)) + return true; + + switch (reg) { + case SYS_LSI_OTPTSU0TRMVAL0: + case SYS_LSI_OTPTSU0TRMVAL1: + case SYS_LSI_OTPTSU1TRMVAL0: + case SYS_LSI_OTPTSU1TRMVAL1: + return true; + default: + return false; + } +} + static bool rzv2h_regmap_writeable_reg(struct device *dev, unsigned int reg) { - switch (reg) { - case SYS_GBETH0_CFG: - case SYS_GBETH1_CFG: - case SYS_PCIE_INTX_CH0: - case SYS_PCIE_MSI1_CH0: - case SYS_PCIE_MSI2_CH0: - case SYS_PCIE_MSI3_CH0: - case SYS_PCIE_MSI4_CH0: - case SYS_PCIE_MSI5_CH0: - case SYS_PCIE_PME_CH0: - case SYS_PCIE_ACK_CH0: - case SYS_PCIE_MISC_CH0: - case SYS_PCIE_MODE_CH0: - case SYS_PCIE_INTX_CH1: - case SYS_PCIE_MSI1_CH1: - case SYS_PCIE_MSI2_CH1: - case SYS_PCIE_MSI3_CH1: - case SYS_PCIE_MSI4_CH1: - case SYS_PCIE_MSI5_CH1: - case SYS_PCIE_PME_CH1: - case SYS_PCIE_ACK_CH1: - case SYS_PCIE_MISC_CH1: - case SYS_PCIE_MODE_CH1: - case SYS_PCIE_MODE: - case SYS_ADC_CFG: - return true; - default: - return false; - } + return rzv2h_regmap_readable_writeable_reg(reg); } const struct rz_sysc_init_data rzv2h_sys_init_data __initconst = { From 0f63ba15dde8748ed3818fa6553c81b5296318f1 Mon Sep 17 00:00:00 2001 From: Wolfram Sang Date: Thu, 2 Apr 2026 13:27:05 +0200 Subject: [PATCH 6/9] dt-bindings: soc: renesas: Document MFIS IP core Document the Renesas Multifunctional Interface (MFIS) as found on the Renesas R-Car X5H (r8a78000) SoC. MFIS includes features like Mailbox/HW Spinlock/Product Register/Error Injection/Error Detection and the likes. Family-compatible values are not introduced here because MFIS is usually very different per SoC. Signed-off-by: Wolfram Sang Reviewed-by: Krzysztof Kozlowski Reviewed-by: Geert Uytterhoeven Link: https://patch.msgid.link/20260402112709.13002-2-wsa+renesas@sang-engineering.com Signed-off-by: Geert Uytterhoeven --- .../soc/renesas/renesas,r8a78000-mfis.yaml | 187 ++++++++++++++++++ .../dt-bindings/soc/renesas,r8a78000-mfis.h | 28 +++ 2 files changed, 215 insertions(+) create mode 100644 Documentation/devicetree/bindings/soc/renesas/renesas,r8a78000-mfis.yaml create mode 100644 include/dt-bindings/soc/renesas,r8a78000-mfis.h diff --git a/Documentation/devicetree/bindings/soc/renesas/renesas,r8a78000-mfis.yaml b/Documentation/devicetree/bindings/soc/renesas/renesas,r8a78000-mfis.yaml new file mode 100644 index 000000000000..eef8c0a59e9c --- /dev/null +++ b/Documentation/devicetree/bindings/soc/renesas/renesas,r8a78000-mfis.yaml @@ -0,0 +1,187 @@ +# SPDX-License-Identifier: (GPL-2.0-only OR BSD-2-Clause) +%YAML 1.2 +--- +$id: http://devicetree.org/schemas/soc/renesas/renesas,r8a78000-mfis.yaml# +$schema: http://devicetree.org/meta-schemas/core.yaml# + +title: Renesas MFIS (Multifunctional Interface) controller + +maintainers: + - Wolfram Sang + +description: + The Renesas Multifunctional Interface (MFIS) provides various functionality + like mailboxes, hardware spinlocks, product identification, error injection, + error detection and such. Parts of it can be used for communication between + different CPU cores. Those cores can be in various domains like AP, RT, or + SCP. Often multiple domain-specific MFIS instances exist in one SoC. + +properties: + compatible: + enum: + - renesas,r8a78000-mfis # R-Car X5H (AP<->AP, with PRR) + - renesas,r8a78000-mfis-scp # R-Car X5H (AP<->SCP, without PRR) + + reg: + maxItems: 2 + + reg-names: + items: + - const: common + - const: mboxes + + interrupts: + minItems: 32 + maxItems: 128 + description: + The interrupts raised by the remote doorbells. + + interrupt-names: + minItems: 32 + maxItems: 128 + description: + An interrupt name is constructed with the prefix 'ch'. Then, the + channel number as specified in the documentation of the SoC. Finally, + the letter 'i' if the interrupt is raised by the IICR register. Or 'e' + if it is raised by the EICR register. + + "#hwlock-cells": + const: 1 + + "#mbox-cells": + const: 2 + description: + The first cell is the channel number as specified in the documentation + of the SoC. The second cell may specify flags as described in the file + . + +allOf: + - if: + properties: + compatible: + contains: + const: renesas,r8a78000-mfis + then: + properties: + interrupts: + minItems: 128 + interrupt-names: + minItems: 128 + items: + pattern: "^ch[0-9]+[ie]$" + + - if: + properties: + compatible: + contains: + const: renesas,r8a78000-mfis-scp + then: + properties: + interrupts: + maxItems: 32 + interrupt-names: + maxItems: 32 + items: + pattern: "^ch[0-9]+i$" + +required: + - compatible + - reg + - reg-names + - interrupts + - interrupt-names + - "#hwlock-cells" + - "#mbox-cells" + +additionalProperties: false + +examples: + - | + #include + system-controller@189e0000 { + compatible = "renesas,r8a78000-mfis"; + reg = <0x189e0000 0x1000>, <0x18800000 0x40000>; + reg-names = "common", "mboxes"; + interrupts = , , + , , + , , + , , + , , + , , + , , + , , + , , + , , + , , + , , + , , + , , + , , + , , + , , + , , + , , + , , + , , + , , + , , + , , + , , + , , + , , + , , + , , + , , + , , + , , + , , + , , + , , + , , + , , + , , + , , + , , + , , + , , + , , + , , + , , + , , + , , + , , + , , + , , + , , + , , + , , + , , + , , + , , + , , + , , + , , + , , + , , + , , + , , + , ; + interrupt-names = "ch0i", "ch0e", "ch1i", "ch1e", "ch2i", "ch2e", "ch3i", "ch3e", + "ch4i", "ch4e", "ch5i", "ch5e", "ch6i", "ch6e", "ch7i", "ch7e", + "ch8i", "ch8e", "ch9i", "ch9e", "ch10i", "ch10e", "ch11i", "ch11e", + "ch12i", "ch12e", "ch13i", "ch13e", "ch14i", "ch14e", "ch15i", "ch15e", + "ch16i", "ch16e", "ch17i", "ch17e", "ch18i", "ch18e", "ch19i", "ch19e", + "ch20i", "ch20e", "ch21i", "ch21e", "ch22i", "ch22e", "ch23i", "ch23e", + "ch24i", "ch24e", "ch25i", "ch25e", "ch26i", "ch26e", "ch27i", "ch27e", + "ch28i", "ch28e", "ch29i", "ch29e", "ch30i", "ch30e", "ch31i", "ch31e", + "ch32i", "ch32e", "ch33i", "ch33e", "ch34i", "ch34e", "ch35i", "ch35e", + "ch36i", "ch36e", "ch37i", "ch37e", "ch38i", "ch38e", "ch39i", "ch39e", + "ch40i", "ch40e", "ch41i", "ch41e", "ch42i", "ch42e", "ch43i", "ch43e", + "ch44i", "ch44e", "ch45i", "ch45e", "ch46i", "ch46e", "ch47i", "ch47e", + "ch48i", "ch48e", "ch49i", "ch49e", "ch50i", "ch50e", "ch51i", "ch51e", + "ch52i", "ch52e", "ch53i", "ch53e", "ch54i", "ch54e", "ch55i", "ch55e", + "ch56i", "ch56e", "ch57i", "ch57e", "ch58i", "ch58e", "ch59i", "ch59e", + "ch60i", "ch60e", "ch61i", "ch61e", "ch62i", "ch62e", "ch63i", "ch63e"; + #hwlock-cells = <1>; + #mbox-cells = <2>; + }; diff --git a/include/dt-bindings/soc/renesas,r8a78000-mfis.h b/include/dt-bindings/soc/renesas,r8a78000-mfis.h new file mode 100644 index 000000000000..147a8aefc643 --- /dev/null +++ b/include/dt-bindings/soc/renesas,r8a78000-mfis.h @@ -0,0 +1,28 @@ +/* SPDX-License-Identifier: (GPL-2.0-only OR BSD-2-Clause) */ +#ifndef _DT_BINDINGS_SOC_RENESAS_R8A78000_MFIS_H +#define _DT_BINDINGS_SOC_RENESAS_R8A78000_MFIS_H + +/* + * Constants for the second mbox-cell of the Renesas MFIS IP core. To be treated + * as bit flags which can be ORed. + */ + +/* + * MFIS HW design before r8a78001 requires a channel to be marked as either + * TX or RX. + */ +#define MFIS_CHANNEL_TX (0 << 0) +#define MFIS_CHANNEL_RX (1 << 0) + +/* + * MFIS variants before r8a78001 work with pairs of IICR and EICR registers. + * Usually, it is specified in the datasheets which of the two a specific core + * should use. Then, it does not need extra description in DT. For plain MFIS + * of r8a78000, this is selectable, though. According to the system design and + * the firmware in use, these channels need to be marked. This is not needed + * with other versions of the MFIS, not even with MFIS-SCP of r8a78000. + */ +#define MFIS_CHANNEL_IICR (0 << 1) +#define MFIS_CHANNEL_EICR (1 << 1) + +#endif /* _DT_BINDINGS_SOC_RENESAS_R8A78000_MFIS_H */ From 005fa59aeb86aa70815104d3d0c65ac0ea80513b Mon Sep 17 00:00:00 2001 From: Wolfram Sang Date: Thu, 2 Apr 2026 13:27:06 +0200 Subject: [PATCH 7/9] soc: renesas: Add Renesas R-Car MFIS driver Renesas R-Car MFIS offers multiple features but most importantly mailboxes and hwspinlocks. Because they share a common register space and a common register unprotection mechanism, a single driver was chosen to handle all dependencies. (MFD and auxiliary bus have been tried as well, but they failed because of circular dependencies.) In this first step, the driver implements common register access and a mailbox controller. hwspinlock support will be added incrementally, once the subsystem allows out-of-directory drivers. Signed-off-by: Kuninori Morimoto Signed-off-by: Wolfram Sang Acked-by: Jassi Brar Reviewed-by: Geert Uytterhoeven Tested-by: Geert Uytterhoeven Link: https://patch.msgid.link/20260402112709.13002-3-wsa+renesas@sang-engineering.com Signed-off-by: Geert Uytterhoeven --- drivers/soc/renesas/Kconfig | 9 + drivers/soc/renesas/Makefile | 1 + drivers/soc/renesas/rcar-mfis.c | 344 ++++++++++++++++++++++++++++++++ 3 files changed, 354 insertions(+) create mode 100644 drivers/soc/renesas/rcar-mfis.c diff --git a/drivers/soc/renesas/Kconfig b/drivers/soc/renesas/Kconfig index 26bed0fdceb0..2ab150d04bb1 100644 --- a/drivers/soc/renesas/Kconfig +++ b/drivers/soc/renesas/Kconfig @@ -465,6 +465,15 @@ config ARCH_R9A07G043 endif # RISCV +config RCAR_MFIS + tristate "Renesas R-Car MFIS driver" + depends on ARCH_RENESAS || COMPILE_TEST + depends on MAILBOX + help + Select this option to enable the Renesas R-Car MFIS core driver for + the MFIS device found on SoCs like R-Car. On families like Gen5, this + is needed to communicate with the SCP. + config PWC_RZV2M bool "Renesas RZ/V2M PWC support" if COMPILE_TEST diff --git a/drivers/soc/renesas/Makefile b/drivers/soc/renesas/Makefile index 655dbcb08747..81bde85c2178 100644 --- a/drivers/soc/renesas/Makefile +++ b/drivers/soc/renesas/Makefile @@ -14,6 +14,7 @@ obj-$(CONFIG_SYS_R9A09G057) += r9a09g057-sys.o # Family obj-$(CONFIG_PWC_RZV2M) += pwc-rzv2m.o +obj-$(CONFIG_RCAR_MFIS) += rcar-mfis.o obj-$(CONFIG_RST_RCAR) += rcar-rst.o obj-$(CONFIG_RZN1_IRQMUX) += rzn1_irqmux.o obj-$(CONFIG_SYSC_RZ) += rz-sysc.o diff --git a/drivers/soc/renesas/rcar-mfis.c b/drivers/soc/renesas/rcar-mfis.c new file mode 100644 index 000000000000..b334b35306ae --- /dev/null +++ b/drivers/soc/renesas/rcar-mfis.c @@ -0,0 +1,344 @@ +// SPDX-License-Identifier: GPL-2.0-only +/* + * Renesas R-Car MFIS (Multifunctional Interface) driver + * + * Copyright (C) Renesas Solutions Corp. + * Kuninori Morimoto + * Wolfram Sang + */ +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#define MFISWPCNTR 0x0900 +#define MFISWACNTR 0x0904 + +#define MFIS_X5H_IICR(i) ((i) * 0x1000 + 0x00) +#define MFIS_X5H_EICR(i) ((i) * 0x1000 + 0x04) + +#define MFIS_UNPROTECT_KEY 0xACCE0000 + +struct mfis_priv; + +struct mfis_reg { + void __iomem *base; + resource_size_t start; + struct mfis_priv *priv; +}; + +struct mfis_info { + u32 unprotect_mask; + unsigned int mb_num_channels; + unsigned int mb_reg_comes_from_dt:1; + unsigned int mb_tx_uses_eicr:1; + unsigned int mb_channels_are_unidir:1; +}; + +struct mfis_chan_priv { + u32 reg; + int irq; +}; + +struct mfis_priv { + spinlock_t unprotect_lock; /* guards access to the unprotection reg */ + struct device *dev; + struct mfis_reg common_reg; + struct mfis_reg mbox_reg; + const struct mfis_info *info; + + /* mailbox private data */ + struct mbox_controller mbox; + struct mfis_chan_priv *chan_privs; +}; + +static u32 mfis_read(struct mfis_reg *mreg, unsigned int reg) +{ + return ioread32(mreg->base + reg); +} + +static void mfis_write(struct mfis_reg *mreg, u32 reg, u32 val) +{ + struct mfis_priv *priv = mreg->priv; + u32 unprotect_mask = priv->info->unprotect_mask; + unsigned long flags; + u32 unprotect_code; + + /* + * [Gen4] key: 0xACCE0000, mask: 0x0000FFFF + * [Gen5] key: 0xACC00000, mask: 0x000FFFFF + */ + unprotect_code = (MFIS_UNPROTECT_KEY & ~unprotect_mask) | + ((mreg->start + reg) & unprotect_mask); + + spin_lock_irqsave(&priv->unprotect_lock, flags); + iowrite32(unprotect_code, priv->common_reg.base + MFISWACNTR); + iowrite32(val, mreg->base + reg); + spin_unlock_irqrestore(&priv->unprotect_lock, flags); +} + +/******************************************************** + * Mailbox * + ********************************************************/ + +#define mfis_mb_mbox_to_priv(_m) container_of((_m), struct mfis_priv, mbox) + +static irqreturn_t mfis_mb_iicr_interrupt(int irq, void *data) +{ + struct mbox_chan *chan = data; + struct mfis_priv *priv = mfis_mb_mbox_to_priv(chan->mbox); + struct mfis_chan_priv *chan_priv = chan->con_priv; + + mbox_chan_received_data(chan, NULL); + /* Stop remote(!) doorbell */ + mfis_write(&priv->mbox_reg, chan_priv->reg, 0); + + return IRQ_HANDLED; +} + +static int mfis_mb_startup(struct mbox_chan *chan) +{ + struct mfis_chan_priv *chan_priv = chan->con_priv; + + if (!chan_priv->irq) + return 0; + + return request_irq(chan_priv->irq, mfis_mb_iicr_interrupt, 0, + dev_name(chan->mbox->dev), chan); +} + +static void mfis_mb_shutdown(struct mbox_chan *chan) +{ + struct mfis_chan_priv *chan_priv = chan->con_priv; + + if (chan_priv->irq) + free_irq(chan_priv->irq, chan); +} + +static int mfis_mb_iicr_send_data(struct mbox_chan *chan, void *data) +{ + struct mfis_priv *priv = mfis_mb_mbox_to_priv(chan->mbox); + struct mfis_chan_priv *chan_priv = chan->con_priv; + + /* Our doorbell still active? */ + if (mfis_read(&priv->mbox_reg, chan_priv->reg) & BIT(0)) + return -EBUSY; + + /* Start our doorbell */ + mfis_write(&priv->mbox_reg, chan_priv->reg, BIT(0)); + + return 0; +} + +static bool mfis_mb_iicr_last_tx_done(struct mbox_chan *chan) +{ + struct mfis_priv *priv = mfis_mb_mbox_to_priv(chan->mbox); + struct mfis_chan_priv *chan_priv = chan->con_priv; + + /* Our doorbell still active? */ + return !(mfis_read(&priv->mbox_reg, chan_priv->reg) & BIT(0)); +} + +/* For MFIS variants using the IICR/EICR register pair */ +static const struct mbox_chan_ops mfis_iicr_ops = { + .startup = mfis_mb_startup, + .shutdown = mfis_mb_shutdown, + .send_data = mfis_mb_iicr_send_data, + .last_tx_done = mfis_mb_iicr_last_tx_done, +}; + +static struct mbox_chan *mfis_mb_of_xlate(struct mbox_controller *mbox, + const struct of_phandle_args *sp) +{ + struct mfis_priv *priv = mfis_mb_mbox_to_priv(mbox); + struct mfis_chan_priv *chan_priv; + bool tx_uses_eicr, is_only_rx; + u32 chan_num, chan_flags; + struct mbox_chan *chan; + + if (sp->args_count != 2) + return ERR_PTR(-EINVAL); + + chan_num = sp->args[0]; + chan_flags = sp->args[1]; + + if (chan_num >= priv->info->mb_num_channels) + return ERR_PTR(-EINVAL); + + /* Channel layout is described in mfis_mb_probe() */ + if (priv->info->mb_channels_are_unidir) { + is_only_rx = chan_flags & MFIS_CHANNEL_RX; + chan = mbox->chans + 2 * chan_num + is_only_rx; + } else { + is_only_rx = false; + chan = mbox->chans + chan_num; + } + + if (priv->info->mb_reg_comes_from_dt) { + tx_uses_eicr = chan_flags & MFIS_CHANNEL_EICR; + if (tx_uses_eicr) + chan += mbox->num_chans / 2; + } else { + tx_uses_eicr = priv->info->mb_tx_uses_eicr; + } + + chan_priv = chan->con_priv; + chan_priv->reg = (tx_uses_eicr ^ is_only_rx) ? MFIS_X5H_EICR(chan_num) : + MFIS_X5H_IICR(chan_num); + + if (!priv->info->mb_channels_are_unidir || is_only_rx) { + char irqname[8]; + char suffix = tx_uses_eicr ? 'i' : 'e'; + + /* "ch0i" or "ch0e" */ + scnprintf(irqname, sizeof(irqname), "ch%u%c", chan_num, suffix); + + chan_priv->irq = of_irq_get_byname(mbox->dev->of_node, irqname); + if (chan_priv->irq < 0) + return ERR_PTR(chan_priv->irq); + if (chan_priv->irq == 0) + return ERR_PTR(-ENOENT); + } + + return chan; +} + +static int mfis_mb_probe(struct mfis_priv *priv) +{ + unsigned int num_chan = priv->info->mb_num_channels; + struct device *dev = priv->dev; + struct mbox_controller *mbox; + struct mbox_chan *chan; + + if (priv->info->mb_channels_are_unidir) { + /* Channel layout: Ch0-TX, Ch0-RX, Ch1-TX... */ + num_chan *= 2; + } + + if (priv->info->mb_reg_comes_from_dt) { + /* Channel layout: IICR channels, EICR channels */ + num_chan *= 2; + } + + chan = devm_kcalloc(dev, num_chan, sizeof(*chan), GFP_KERNEL); + if (!chan) + return -ENOMEM; + + priv->chan_privs = devm_kcalloc(dev, num_chan, sizeof(*priv->chan_privs), + GFP_KERNEL); + if (!priv->chan_privs) + return -ENOMEM; + + mbox = &priv->mbox; + + for (unsigned int i = 0; i < num_chan; i++) + chan[i].con_priv = &priv->chan_privs[i]; + + mbox->chans = chan; + mbox->num_chans = num_chan; + mbox->txdone_poll = true; + mbox->ops = &mfis_iicr_ops; + mbox->dev = dev; + mbox->of_xlate = mfis_mb_of_xlate; + + return devm_mbox_controller_register(dev, mbox); +} + +/******************************************************** + * Common * + ********************************************************/ +static int mfis_reg_probe(struct platform_device *pdev, struct mfis_priv *priv, + struct mfis_reg *mreg, const char *name, bool required) +{ + struct resource *res; + void __iomem *base; + + res = platform_get_resource_byname(pdev, IORESOURCE_MEM, name); + + /* If there is no mailbox resource, registers are in the common space */ + if (!res && !required) { + *mreg = priv->common_reg; + } else { + base = devm_ioremap_resource(&pdev->dev, res); + if (IS_ERR(base)) + return PTR_ERR(base); + + mreg->base = base; + mreg->start = res->start; + mreg->priv = priv; + } + + return 0; +} + +static int mfis_probe(struct platform_device *pdev) +{ + struct device *dev = &pdev->dev; + struct mfis_priv *priv; + int ret; + + priv = devm_kzalloc(dev, sizeof(*priv), GFP_KERNEL); + if (!priv) + return -ENOMEM; + + priv->dev = dev; + priv->info = of_device_get_match_data(dev); + if (!priv->info) + return -ENOENT; + + spin_lock_init(&priv->unprotect_lock); + + ret = mfis_reg_probe(pdev, priv, &priv->common_reg, "common", true); + if (ret) + return ret; + + ret = mfis_reg_probe(pdev, priv, &priv->mbox_reg, "mboxes", false); + if (ret) + return ret; + + return mfis_mb_probe(priv); +} + +static const struct mfis_info mfis_info_r8a78000 = { + .unprotect_mask = 0x000fffff, + .mb_num_channels = 64, + .mb_reg_comes_from_dt = true, + .mb_channels_are_unidir = true, +}; + +static const struct mfis_info mfis_info_r8a78000_scp = { + .unprotect_mask = 0x000fffff, + .mb_num_channels = 32, + .mb_tx_uses_eicr = true, + .mb_channels_are_unidir = true, +}; + +static const struct of_device_id mfis_mfd_of_match[] = { + { .compatible = "renesas,r8a78000-mfis", .data = &mfis_info_r8a78000, }, + { .compatible = "renesas,r8a78000-mfis-scp", .data = &mfis_info_r8a78000_scp, }, + {} +}; +MODULE_DEVICE_TABLE(of, mfis_mfd_of_match); + +static struct platform_driver mfis_driver = { + .driver = { + .name = "rcar-mfis", + .of_match_table = mfis_mfd_of_match, + .suppress_bind_attrs = true, + }, + .probe = mfis_probe, +}; +module_platform_driver(mfis_driver); + +MODULE_AUTHOR("Kuninori Morimoto "); +MODULE_AUTHOR("Wolfram Sang "); +MODULE_LICENSE("GPL"); +MODULE_DESCRIPTION("Renesas R-Car MFIS driver"); From 39abbc2f7a7036af4a59d00e7748961683845c6f Mon Sep 17 00:00:00 2001 From: Wolfram Sang Date: Thu, 2 Apr 2026 13:27:07 +0200 Subject: [PATCH 8/9] soc: renesas: Add R-Car X5H PRR support On R-Car X5H, PRR is inside the MFIS memory block, so we need to access it similar to e.g. RZ/G2L. Suggested-by: Geert Uytterhoeven Signed-off-by: Wolfram Sang Reviewed-by: Geert Uytterhoeven Link: https://patch.msgid.link/20260402112709.13002-4-wsa+renesas@sang-engineering.com Signed-off-by: Geert Uytterhoeven --- drivers/soc/renesas/renesas-soc.c | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) diff --git a/drivers/soc/renesas/renesas-soc.c b/drivers/soc/renesas/renesas-soc.c index 38ff0b823bda..60b09020c935 100644 --- a/drivers/soc/renesas/renesas-soc.c +++ b/drivers/soc/renesas/renesas-soc.c @@ -442,8 +442,14 @@ static const struct renesas_id id_prr __initconst = { .mask = 0xff00, }; +static const struct renesas_id id_mfis __initconst = { + .offset = 0x44, + .mask = 0xff00, +}; + static const struct of_device_id renesas_ids[] __initconst = { { .compatible = "renesas,bsid", .data = &id_bsid }, + { .compatible = "renesas,r8a78000-mfis", .data = &id_mfis }, { .compatible = "renesas,r9a07g043-sysc", .data = &id_rzg2l }, { .compatible = "renesas,r9a07g044-sysc", .data = &id_rzg2l }, { .compatible = "renesas,r9a07g054-sysc", .data = &id_rzg2l }, @@ -501,7 +507,7 @@ static int __init renesas_soc_init(void) product = readl(chipid + id->offset); iounmap(chipid); - if (id == &id_prr) { + if (id == &id_prr || id == &id_mfis) { /* R-Car M3-W ES1.1 incorrectly identifies as ES2.0 */ if ((product & 0x7fff) == 0x5210) product ^= 0x11; From 17e48e7e5f18b45fd4a9411090148aae3b74f7f3 Mon Sep 17 00:00:00 2001 From: Geert Uytterhoeven Date: Mon, 2 Mar 2026 17:29:11 +0100 Subject: [PATCH 9/9] soc: renesas: Convert to of_machine_get_match() Use the of_machine_get_match() helper to avoid accessing of_root directly, which is planned to become private. Signed-off-by: Geert Uytterhoeven Acked-by: Viresh Kumar Link: https://patch.msgid.link/10876b30a8bdb7d1cfcc2f23fb859f2ffea335fe.1772468323.git.geert+renesas@glider.be --- drivers/soc/renesas/renesas-soc.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/soc/renesas/renesas-soc.c b/drivers/soc/renesas/renesas-soc.c index 60b09020c935..dedb2a0be586 100644 --- a/drivers/soc/renesas/renesas-soc.c +++ b/drivers/soc/renesas/renesas-soc.c @@ -474,7 +474,7 @@ static int __init renesas_soc_init(void) const char *soc_id; int ret; - match = of_match_node(renesas_socs, of_root); + match = of_machine_get_match(renesas_socs); if (!match) return -ENODEV;