Renesas driver updates for v7.2

- Add Multifunctional Interface (MFIS) mailbox and product register
     support for R-Car X5H,
   - Miscellaneous fixes and improvements.
 -----BEGIN PGP SIGNATURE-----
 
 iHUEABYKAB0WIQQ9qaHoIs/1I4cXmEiKwlD9ZEnxcAUCagwTtgAKCRCKwlD9ZEnx
 cLDkAQDhxksjowi3Ax4f8PUBawEnJoy8lameVXx/y6SihMh//AD+P4uMbbcCVs7j
 thXfW9l69oi/g+xc1M/fNFKrLFp8Bwk=
 =q0zd
 -----END PGP SIGNATURE-----
gpgsig -----BEGIN PGP SIGNATURE-----
 
 iQIzBAABCgAdFiEEo6/YBQwIrVS28WGKmmx57+YAGNkFAmoNipoACgkQmmx57+YA
 GNkuhg/9GWPhQQ66flfK8nP8pscy2CAsGFT5K8UeFE9rCAUIEKxm9aEDPkLTzlJW
 Yi6cYYA7b/hHMKXXBfJR59Bthh1eLOyz7XMQu08COHrqL1fNfj6+ug6RG49R10g8
 9ru9E+NxoyC9P+yQgzehsGLBeW4awFQWbwyq2RBaycwni853cPzfKQeC2rK0Pwuv
 nutLUpP0YnNG/vveACK5t7OnG90Yi9aGcfphq5Nl/VSrZ5ju7xLtkEZVRVbP6Cbt
 9dcQ4klmnQ0u5VUsYx/F7OiGfMh6LUm4oJna4SCYiWqdkujobsQ/9/IzCWPp00P5
 6k9T+l5QLGviCQxuSwAtVMheVB6bbr8gvqteHIPRhYKGVGQBsY/LQjeTwmpiUJYu
 4/uV6eGtblAbARIqxViqLrPjwlX8qWkqJ8p4MJedAreHcOt8pMjXCnMlVxbl/rOV
 LaXpIC2o+8ppyVhHCvh/tHRevQSuoefZ4gHHy8ETbA3Tq/jLrvemzIyBGNfRc7Ye
 CwjiOFPtYtFD1WEAWGyNisvZuNUS4ayxxP+rhS1C5KvywJNf7xmGkFm1PEqyfLw9
 OgBfimYrzj6VMWFj+j1OlO5B524wh83h/n9YFG1md6w4UzHgYQb4Fq1os2e1XvXS
 e2mXpqiz6TVYYicpKmLxxPlrjdIoguzZ4sir72UMYCW8n8yHddo=
 =cz+6
 -----END PGP SIGNATURE-----

Merge tag 'renesas-drivers-for-v7.2-tag1' of git://git.kernel.org/pub/scm/linux/kernel/git/geert/renesas-devel into soc/drivers

Renesas driver updates for v7.2

  - Add Multifunctional Interface (MFIS) mailbox and product register
    support for R-Car X5H,
  - Miscellaneous fixes and improvements.

* tag 'renesas-drivers-for-v7.2-tag1' of git://git.kernel.org/pub/scm/linux/kernel/git/geert/renesas-devel:
  soc: renesas: Convert to of_machine_get_match()
  soc: renesas: Add R-Car X5H PRR support
  soc: renesas: Add Renesas R-Car MFIS driver
  dt-bindings: soc: renesas: Document MFIS IP core
  soc: renesas: r9a09g057-sys: Move common code to a helper
  soc: renesas: r9a09g056-sys: Move common code to a helper
  soc: renesas: r9a09g047-sys: Move common code to a helper
  soc: renesas: r9a08g046-sysc: Move common code to a helper
  soc: renesas: r9a08g045-sysc: Move common code to a helper

Signed-off-by: Arnd Bergmann <arnd@arndb.de>
This commit is contained in:
Arnd Bergmann 2026-05-20 12:19:01 +02:00
commit b1700f8d6c
11 changed files with 660 additions and 126 deletions

View File

@ -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 <wsa+renesas@sang-engineering.com>
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
<dt-bindings/soc/renesas,r8a78000-mfis.h>.
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 <dt-bindings/interrupt-controller/arm-gic.h>
system-controller@189e0000 {
compatible = "renesas,r8a78000-mfis";
reg = <0x189e0000 0x1000>, <0x18800000 0x40000>;
reg-names = "common", "mboxes";
interrupts = <GIC_SPI 101 IRQ_TYPE_LEVEL_HIGH>, <GIC_SPI 102 IRQ_TYPE_LEVEL_HIGH>,
<GIC_SPI 103 IRQ_TYPE_LEVEL_HIGH>, <GIC_SPI 104 IRQ_TYPE_LEVEL_HIGH>,
<GIC_SPI 105 IRQ_TYPE_LEVEL_HIGH>, <GIC_SPI 106 IRQ_TYPE_LEVEL_HIGH>,
<GIC_SPI 107 IRQ_TYPE_LEVEL_HIGH>, <GIC_SPI 108 IRQ_TYPE_LEVEL_HIGH>,
<GIC_SPI 109 IRQ_TYPE_LEVEL_HIGH>, <GIC_SPI 110 IRQ_TYPE_LEVEL_HIGH>,
<GIC_SPI 111 IRQ_TYPE_LEVEL_HIGH>, <GIC_SPI 112 IRQ_TYPE_LEVEL_HIGH>,
<GIC_SPI 113 IRQ_TYPE_LEVEL_HIGH>, <GIC_SPI 114 IRQ_TYPE_LEVEL_HIGH>,
<GIC_SPI 115 IRQ_TYPE_LEVEL_HIGH>, <GIC_SPI 116 IRQ_TYPE_LEVEL_HIGH>,
<GIC_SPI 117 IRQ_TYPE_LEVEL_HIGH>, <GIC_SPI 118 IRQ_TYPE_LEVEL_HIGH>,
<GIC_SPI 119 IRQ_TYPE_LEVEL_HIGH>, <GIC_SPI 120 IRQ_TYPE_LEVEL_HIGH>,
<GIC_SPI 121 IRQ_TYPE_LEVEL_HIGH>, <GIC_SPI 122 IRQ_TYPE_LEVEL_HIGH>,
<GIC_SPI 123 IRQ_TYPE_LEVEL_HIGH>, <GIC_SPI 124 IRQ_TYPE_LEVEL_HIGH>,
<GIC_SPI 125 IRQ_TYPE_LEVEL_HIGH>, <GIC_SPI 126 IRQ_TYPE_LEVEL_HIGH>,
<GIC_SPI 127 IRQ_TYPE_LEVEL_HIGH>, <GIC_SPI 128 IRQ_TYPE_LEVEL_HIGH>,
<GIC_SPI 129 IRQ_TYPE_LEVEL_HIGH>, <GIC_SPI 130 IRQ_TYPE_LEVEL_HIGH>,
<GIC_SPI 131 IRQ_TYPE_LEVEL_HIGH>, <GIC_SPI 132 IRQ_TYPE_LEVEL_HIGH>,
<GIC_SPI 133 IRQ_TYPE_LEVEL_HIGH>, <GIC_SPI 134 IRQ_TYPE_LEVEL_HIGH>,
<GIC_SPI 135 IRQ_TYPE_LEVEL_HIGH>, <GIC_SPI 136 IRQ_TYPE_LEVEL_HIGH>,
<GIC_SPI 137 IRQ_TYPE_LEVEL_HIGH>, <GIC_SPI 138 IRQ_TYPE_LEVEL_HIGH>,
<GIC_SPI 139 IRQ_TYPE_LEVEL_HIGH>, <GIC_SPI 140 IRQ_TYPE_LEVEL_HIGH>,
<GIC_SPI 141 IRQ_TYPE_LEVEL_HIGH>, <GIC_SPI 142 IRQ_TYPE_LEVEL_HIGH>,
<GIC_SPI 143 IRQ_TYPE_LEVEL_HIGH>, <GIC_SPI 144 IRQ_TYPE_LEVEL_HIGH>,
<GIC_SPI 145 IRQ_TYPE_LEVEL_HIGH>, <GIC_SPI 146 IRQ_TYPE_LEVEL_HIGH>,
<GIC_SPI 147 IRQ_TYPE_LEVEL_HIGH>, <GIC_SPI 148 IRQ_TYPE_LEVEL_HIGH>,
<GIC_SPI 149 IRQ_TYPE_LEVEL_HIGH>, <GIC_SPI 150 IRQ_TYPE_LEVEL_HIGH>,
<GIC_SPI 151 IRQ_TYPE_LEVEL_HIGH>, <GIC_SPI 152 IRQ_TYPE_LEVEL_HIGH>,
<GIC_SPI 153 IRQ_TYPE_LEVEL_HIGH>, <GIC_SPI 154 IRQ_TYPE_LEVEL_HIGH>,
<GIC_SPI 155 IRQ_TYPE_LEVEL_HIGH>, <GIC_SPI 156 IRQ_TYPE_LEVEL_HIGH>,
<GIC_SPI 157 IRQ_TYPE_LEVEL_HIGH>, <GIC_SPI 158 IRQ_TYPE_LEVEL_HIGH>,
<GIC_SPI 159 IRQ_TYPE_LEVEL_HIGH>, <GIC_SPI 160 IRQ_TYPE_LEVEL_HIGH>,
<GIC_SPI 161 IRQ_TYPE_LEVEL_HIGH>, <GIC_SPI 162 IRQ_TYPE_LEVEL_HIGH>,
<GIC_SPI 163 IRQ_TYPE_LEVEL_HIGH>, <GIC_SPI 164 IRQ_TYPE_LEVEL_HIGH>,
<GIC_SPI 165 IRQ_TYPE_LEVEL_HIGH>, <GIC_SPI 166 IRQ_TYPE_LEVEL_HIGH>,
<GIC_SPI 167 IRQ_TYPE_LEVEL_HIGH>, <GIC_SPI 168 IRQ_TYPE_LEVEL_HIGH>,
<GIC_SPI 169 IRQ_TYPE_LEVEL_HIGH>, <GIC_SPI 170 IRQ_TYPE_LEVEL_HIGH>,
<GIC_SPI 171 IRQ_TYPE_LEVEL_HIGH>, <GIC_SPI 172 IRQ_TYPE_LEVEL_HIGH>,
<GIC_SPI 173 IRQ_TYPE_LEVEL_HIGH>, <GIC_SPI 174 IRQ_TYPE_LEVEL_HIGH>,
<GIC_SPI 175 IRQ_TYPE_LEVEL_HIGH>, <GIC_SPI 176 IRQ_TYPE_LEVEL_HIGH>,
<GIC_SPI 177 IRQ_TYPE_LEVEL_HIGH>, <GIC_SPI 178 IRQ_TYPE_LEVEL_HIGH>,
<GIC_SPI 179 IRQ_TYPE_LEVEL_HIGH>, <GIC_SPI 180 IRQ_TYPE_LEVEL_HIGH>,
<GIC_SPI 181 IRQ_TYPE_LEVEL_HIGH>, <GIC_SPI 182 IRQ_TYPE_LEVEL_HIGH>,
<GIC_SPI 183 IRQ_TYPE_LEVEL_HIGH>, <GIC_SPI 184 IRQ_TYPE_LEVEL_HIGH>,
<GIC_SPI 185 IRQ_TYPE_LEVEL_HIGH>, <GIC_SPI 186 IRQ_TYPE_LEVEL_HIGH>,
<GIC_SPI 187 IRQ_TYPE_LEVEL_HIGH>, <GIC_SPI 188 IRQ_TYPE_LEVEL_HIGH>,
<GIC_SPI 189 IRQ_TYPE_LEVEL_HIGH>, <GIC_SPI 190 IRQ_TYPE_LEVEL_HIGH>,
<GIC_SPI 191 IRQ_TYPE_LEVEL_HIGH>, <GIC_SPI 192 IRQ_TYPE_LEVEL_HIGH>,
<GIC_SPI 193 IRQ_TYPE_LEVEL_HIGH>, <GIC_SPI 194 IRQ_TYPE_LEVEL_HIGH>,
<GIC_SPI 195 IRQ_TYPE_LEVEL_HIGH>, <GIC_SPI 196 IRQ_TYPE_LEVEL_HIGH>,
<GIC_SPI 197 IRQ_TYPE_LEVEL_HIGH>, <GIC_SPI 198 IRQ_TYPE_LEVEL_HIGH>,
<GIC_SPI 199 IRQ_TYPE_LEVEL_HIGH>, <GIC_SPI 200 IRQ_TYPE_LEVEL_HIGH>,
<GIC_SPI 201 IRQ_TYPE_LEVEL_HIGH>, <GIC_SPI 202 IRQ_TYPE_LEVEL_HIGH>,
<GIC_SPI 203 IRQ_TYPE_LEVEL_HIGH>, <GIC_SPI 204 IRQ_TYPE_LEVEL_HIGH>,
<GIC_SPI 205 IRQ_TYPE_LEVEL_HIGH>, <GIC_SPI 206 IRQ_TYPE_LEVEL_HIGH>,
<GIC_SPI 207 IRQ_TYPE_LEVEL_HIGH>, <GIC_SPI 208 IRQ_TYPE_LEVEL_HIGH>,
<GIC_SPI 209 IRQ_TYPE_LEVEL_HIGH>, <GIC_SPI 210 IRQ_TYPE_LEVEL_HIGH>,
<GIC_SPI 211 IRQ_TYPE_LEVEL_HIGH>, <GIC_SPI 212 IRQ_TYPE_LEVEL_HIGH>,
<GIC_SPI 213 IRQ_TYPE_LEVEL_HIGH>, <GIC_SPI 214 IRQ_TYPE_LEVEL_HIGH>,
<GIC_SPI 215 IRQ_TYPE_LEVEL_HIGH>, <GIC_SPI 216 IRQ_TYPE_LEVEL_HIGH>,
<GIC_SPI 217 IRQ_TYPE_LEVEL_HIGH>, <GIC_SPI 218 IRQ_TYPE_LEVEL_HIGH>,
<GIC_SPI 219 IRQ_TYPE_LEVEL_HIGH>, <GIC_SPI 220 IRQ_TYPE_LEVEL_HIGH>,
<GIC_SPI 221 IRQ_TYPE_LEVEL_HIGH>, <GIC_SPI 222 IRQ_TYPE_LEVEL_HIGH>,
<GIC_SPI 223 IRQ_TYPE_LEVEL_HIGH>, <GIC_SPI 224 IRQ_TYPE_LEVEL_HIGH>,
<GIC_SPI 225 IRQ_TYPE_LEVEL_HIGH>, <GIC_SPI 226 IRQ_TYPE_LEVEL_HIGH>,
<GIC_SPI 227 IRQ_TYPE_LEVEL_HIGH>, <GIC_SPI 228 IRQ_TYPE_LEVEL_HIGH>;
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>;
};

View File

@ -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

View File

@ -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

View File

@ -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 = {

View File

@ -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,

View File

@ -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 = {

View File

@ -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 = {

View File

@ -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 = {

View File

@ -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 <kuninori.morimoto.gx@renesas.com>
* Wolfram Sang <wsa+renesas@sang-engineering.com>
*/
#include <dt-bindings/soc/renesas,r8a78000-mfis.h>
#include <linux/device.h>
#include <linux/interrupt.h>
#include <linux/io.h>
#include <linux/kernel.h>
#include <linux/mailbox_controller.h>
#include <linux/module.h>
#include <linux/of.h>
#include <linux/of_irq.h>
#include <linux/of_platform.h>
#include <linux/platform_device.h>
#include <linux/spinlock.h>
#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: <n> IICR channels, <n> 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 <kuninori.morimoto.gx@renesas.com>");
MODULE_AUTHOR("Wolfram Sang <wsa+renesas@sang-engineering.com>");
MODULE_LICENSE("GPL");
MODULE_DESCRIPTION("Renesas R-Car MFIS driver");

View File

@ -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 },
@ -468,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;
@ -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;

View File

@ -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 */