[PATCH 00/16] Add support for the Renesas RZ/G2L SMARC EVK

These patches add initial support for the RZ/G2L SMARC Evaluation board kit (EVK), consisting of the RZ/G2L System-on-Module (SOM) based on the R9A07G044L2 SoC, and a common SMARC carrier board. Support is included for the CPG (clock & reset control module), PFC (pinctrl & gpio module), SDHI (eMMC & SD card interfaces) & SCIF (serial port) modules. Enough functionality is included to boot a modern Linux kernel from the eMMC or SD card interfaces.
The first patch in the series is an updated version of a patch I've sent previously [1]. It's included here as the later patch to enable RZ/G2L SCIF support depends on it.
Further work will follow in time to add support for other interfaces on the RZ/G2L (such as Ethernet) and other SoCs in the RZ/G2L family (including the RZ/G2UL, RZ/G2LC, RZ/V2L & RZ/Five).
[1]: https://lore.kernel.org/all/20230822181025.339748-2-paul.barker.ct@bp.renesa...
Paul Barker (16): serial: sh: Fix compile error when lacking HSCIF support dt-bindings: Add RZ/G2L CPG bindings dt-bindings: Add RZ/G2L PFC bindings dt-bindings: Add RZ/G2L IRQC bindings arm: rmobile: Add basic RZ/G2L family support arm: rmobile: Add basic R9A07G044L SoC support clk: renesas: Add RZ/G2L CPG driver arm: rmobile: Restrict PINCTRL_PFC selection to R-Car gen3/gen4 pinctrl: renesas: Add RZ/G2L PFC driver serial: sh: Add RZ/G2L SCIF support mmc: renesas-sdhi: Initialize module on RZ/G2L arm: rmobile: Include <asm/types.h> in header arm: rmobile: Add CPU detection for RZ/G2L arm: rmobile: Support RZ/G2L memory map arm: dts: Import RZ/G2L SMARC EVK device tree board: rzg2l: Add RZ/G2L SMARC EVK board
arch/arm/dts/Makefile | 3 + arch/arm/dts/r9a07g044.dtsi | 1273 +++++++++++++++++ arch/arm/dts/r9a07g044l2-smarc.dts | 18 + arch/arm/dts/r9a07g044l2.dtsi | 13 + arch/arm/dts/rz-smarc-common.dtsi | 183 +++ arch/arm/dts/rzg2l-smarc-pinfunction.dtsi | 137 ++ arch/arm/dts/rzg2l-smarc-som.dtsi | 353 +++++ arch/arm/dts/rzg2l-smarc.dtsi | 144 ++ arch/arm/mach-rmobile/Kconfig | 19 +- arch/arm/mach-rmobile/Kconfig.rzg2l | 32 + arch/arm/mach-rmobile/Makefile | 5 +- arch/arm/mach-rmobile/cpu_info-rzg2l.c | 63 + arch/arm/mach-rmobile/include/mach/rmobile.h | 5 + arch/arm/mach-rmobile/include/mach/rzg2l.h | 13 + arch/arm/mach-rmobile/memmap-rzg2l.c | 115 ++ board/renesas/rzg2l/Kconfig | 18 + board/renesas/rzg2l/MAINTAINERS | 6 + board/renesas/rzg2l/Makefile | 4 + board/renesas/rzg2l/rzg2l.c | 76 + configs/renesas_rzg2l_smarc_defconfig | 52 + drivers/clk/renesas/Kconfig | 9 + drivers/clk/renesas/Makefile | 2 + drivers/clk/renesas/r9a07g044-cpg.c | 384 +++++ drivers/clk/renesas/rzg2l-cpg.c | 502 +++++++ drivers/clk/renesas/rzg2l-cpg.h | 318 ++++ drivers/mmc/renesas-sdhi.c | 61 + drivers/pinctrl/renesas/Kconfig | 9 + drivers/pinctrl/renesas/Makefile | 1 + drivers/pinctrl/renesas/rzg2l-pfc.c | 906 ++++++++++++ drivers/serial/serial_sh.c | 34 +- drivers/serial/serial_sh.h | 19 +- include/configs/rzg2l-smarc.h | 14 + include/dt-bindings/clock/r9a07g044-cpg.h | 220 +++ .../interrupt-controller/irqc-rzg2l.h | 25 + include/dt-bindings/pinctrl/rzg2l-pinctrl.h | 23 + 35 files changed, 5054 insertions(+), 5 deletions(-) create mode 100644 arch/arm/dts/r9a07g044.dtsi create mode 100644 arch/arm/dts/r9a07g044l2-smarc.dts create mode 100644 arch/arm/dts/r9a07g044l2.dtsi create mode 100644 arch/arm/dts/rz-smarc-common.dtsi create mode 100644 arch/arm/dts/rzg2l-smarc-pinfunction.dtsi create mode 100644 arch/arm/dts/rzg2l-smarc-som.dtsi create mode 100644 arch/arm/dts/rzg2l-smarc.dtsi create mode 100644 arch/arm/mach-rmobile/Kconfig.rzg2l create mode 100644 arch/arm/mach-rmobile/cpu_info-rzg2l.c create mode 100644 arch/arm/mach-rmobile/include/mach/rzg2l.h create mode 100644 arch/arm/mach-rmobile/memmap-rzg2l.c create mode 100644 board/renesas/rzg2l/Kconfig create mode 100644 board/renesas/rzg2l/MAINTAINERS create mode 100644 board/renesas/rzg2l/Makefile create mode 100644 board/renesas/rzg2l/rzg2l.c create mode 100644 configs/renesas_rzg2l_smarc_defconfig create mode 100644 drivers/clk/renesas/r9a07g044-cpg.c create mode 100644 drivers/clk/renesas/rzg2l-cpg.c create mode 100644 drivers/clk/renesas/rzg2l-cpg.h create mode 100644 drivers/pinctrl/renesas/rzg2l-pfc.c create mode 100644 include/configs/rzg2l-smarc.h create mode 100644 include/dt-bindings/clock/r9a07g044-cpg.h create mode 100644 include/dt-bindings/interrupt-controller/irqc-rzg2l.h create mode 100644 include/dt-bindings/pinctrl/rzg2l-pinctrl.h
base-commit: b9b83a86f0e84e837191db120c279a9cc0e3434b

If we attempt to compile serial_sh.c for a system which lacks HSCIF support (e.g. R8A7740), we see the following compilation error:
In file included from drivers/serial/serial_sh.c:20: drivers/serial/serial_sh.c: In function ‘sh_serial_init_generic’: drivers/serial/serial_sh.h:429:35: warning: implicit declaration of function ‘sci_HSSRR_out’; did you mean ‘sci_SCSCR_out’? [-Wimplicit-function-declaration] 429 | #define sci_out(port, reg, value) sci_##reg##_out(port, value) | ^~~~ drivers/serial/serial_sh.c:62:17: note: in expansion of macro ‘sci_out’ 62 | sci_out(port, HSSRR, HSSRR_SRE | HSSRR_SRCYC8); | ^~~~~~~
To fix this, only try to support access to the HSSRR register for SoCs where it actually exists.
Fixes: bbe36e29ca2c ('serial: sh: Add HSCIF support for R-Car SoC') Signed-off-by: Paul Barker paul.barker.ct@bp.renesas.com Reviewed-by: Biju Das biju.das.jz@bp.renesas.com Cc: Hai Pham hai.pham.ud@renesas.com Cc: Marek Vasut marek.vasut+renesas@mailbox.org Cc: Simon Glass sjg@chromium.org --- drivers/serial/serial_sh.c | 2 ++ 1 file changed, 2 insertions(+)
diff --git a/drivers/serial/serial_sh.c b/drivers/serial/serial_sh.c index 20cda5dbe272..5e543dbf3d58 100644 --- a/drivers/serial/serial_sh.c +++ b/drivers/serial/serial_sh.c @@ -58,8 +58,10 @@ static void sh_serial_init_generic(struct uart_port *port) sci_out(port, SCSPTR, 0x0003); #endif
+#if IS_ENABLED(CONFIG_RCAR_GEN2) || IS_ENABLED(CONFIG_RCAR_GEN3) || IS_ENABLED(CONFIG_RCAR_GEN4) if (port->type == PORT_HSCIF) sci_out(port, HSSRR, HSSRR_SRE | HSSRR_SRCYC8); +#endif }
static void

On 9/20/23 14:41, Paul Barker wrote:
If we attempt to compile serial_sh.c for a system which lacks HSCIF support (e.g. R8A7740), we see the following compilation error:
In file included from drivers/serial/serial_sh.c:20: drivers/serial/serial_sh.c: In function ‘sh_serial_init_generic’: drivers/serial/serial_sh.h:429:35: warning: implicit declaration of function ‘sci_HSSRR_out’; did you mean ‘sci_SCSCR_out’? [-Wimplicit-function-declaration] 429 | #define sci_out(port, reg, value) sci_##reg##_out(port, value) | ^~~~ drivers/serial/serial_sh.c:62:17: note: in expansion of macro ‘sci_out’ 62 | sci_out(port, HSSRR, HSSRR_SRE | HSSRR_SRCYC8); | ^~~~~~~
To fix this, only try to support access to the HSSRR register for SoCs where it actually exists.
Fixes: bbe36e29ca2c ('serial: sh: Add HSCIF support for R-Car SoC') Signed-off-by: Paul Barker paul.barker.ct@bp.renesas.com Reviewed-by: Biju Das biju.das.jz@bp.renesas.com Cc: Hai Pham hai.pham.ud@renesas.com Cc: Marek Vasut marek.vasut+renesas@mailbox.org Cc: Simon Glass sjg@chromium.org
drivers/serial/serial_sh.c | 2 ++ 1 file changed, 2 insertions(+)
diff --git a/drivers/serial/serial_sh.c b/drivers/serial/serial_sh.c index 20cda5dbe272..5e543dbf3d58 100644 --- a/drivers/serial/serial_sh.c +++ b/drivers/serial/serial_sh.c @@ -58,8 +58,10 @@ static void sh_serial_init_generic(struct uart_port *port) sci_out(port, SCSPTR, 0x0003); #endif
+#if IS_ENABLED(CONFIG_RCAR_GEN2) || IS_ENABLED(CONFIG_RCAR_GEN3) || IS_ENABLED(CONFIG_RCAR_GEN4)
There should be CONFIG_RCAR_64 for GEN3+GEN4, please use it.
With that fixed:
Reviewed-by: Marek Vasut marek.vasut+renesas@mailbox.org

On 03/10/2023 13:42, Marek Vasut wrote:
On 9/20/23 14:41, Paul Barker wrote:
If we attempt to compile serial_sh.c for a system which lacks HSCIF support (e.g. R8A7740), we see the following compilation error:
In file included from drivers/serial/serial_sh.c:20: drivers/serial/serial_sh.c: In function ‘sh_serial_init_generic’: drivers/serial/serial_sh.h:429:35: warning: implicit declaration of function ‘sci_HSSRR_out’; did you mean ‘sci_SCSCR_out’? [-Wimplicit-function-declaration] 429 | #define sci_out(port, reg, value) sci_##reg##_out(port, value) | ^~~~ drivers/serial/serial_sh.c:62:17: note: in expansion of macro ‘sci_out’ 62 | sci_out(port, HSSRR, HSSRR_SRE | HSSRR_SRCYC8); | ^~~~~~~
To fix this, only try to support access to the HSSRR register for SoCs where it actually exists.
Fixes: bbe36e29ca2c ('serial: sh: Add HSCIF support for R-Car SoC') Signed-off-by: Paul Barker paul.barker.ct@bp.renesas.com Reviewed-by: Biju Das biju.das.jz@bp.renesas.com Cc: Hai Pham hai.pham.ud@renesas.com Cc: Marek Vasut marek.vasut+renesas@mailbox.org Cc: Simon Glass sjg@chromium.org
drivers/serial/serial_sh.c | 2 ++ 1 file changed, 2 insertions(+)
diff --git a/drivers/serial/serial_sh.c b/drivers/serial/serial_sh.c index 20cda5dbe272..5e543dbf3d58 100644 --- a/drivers/serial/serial_sh.c +++ b/drivers/serial/serial_sh.c @@ -58,8 +58,10 @@ static void sh_serial_init_generic(struct uart_port *port) sci_out(port, SCSPTR, 0x0003); #endif
+#if IS_ENABLED(CONFIG_RCAR_GEN2) || IS_ENABLED(CONFIG_RCAR_GEN3) || IS_ENABLED(CONFIG_RCAR_GEN4)
There should be CONFIG_RCAR_64 for GEN3+GEN4, please use it.
In patch 5 of this series I add CONFIG_RZG2L, which selects CONFIG_RCAR_64 but doesn't have HSCIF support.
An alternative would be to use this here:
#if IS_ENABLED(CONFIG_RCAR_GEN2) || IS_ENABLED(CONFIG_RCAR_64)
Then in patch 5 modify it to
#if IS_ENABLED(CONFIG_RCAR_GEN2) || IS_ENABLED(CONFIG_RCAR_64) && !IS_ENABLED(CONFIG_RZG2L)
I don't have any strong preference on which one to use.
Thanks, Paul

On 10/4/23 09:49, Paul Barker wrote:
On 03/10/2023 13:42, Marek Vasut wrote:
On 9/20/23 14:41, Paul Barker wrote:
If we attempt to compile serial_sh.c for a system which lacks HSCIF support (e.g. R8A7740), we see the following compilation error:
In file included from drivers/serial/serial_sh.c:20: drivers/serial/serial_sh.c: In function ‘sh_serial_init_generic’: drivers/serial/serial_sh.h:429:35: warning: implicit declaration of function ‘sci_HSSRR_out’; did you mean ‘sci_SCSCR_out’? [-Wimplicit-function-declaration] 429 | #define sci_out(port, reg, value) sci_##reg##_out(port, value) | ^~~~ drivers/serial/serial_sh.c:62:17: note: in expansion of macro ‘sci_out’ 62 | sci_out(port, HSSRR, HSSRR_SRE | HSSRR_SRCYC8); | ^~~~~~~
To fix this, only try to support access to the HSSRR register for SoCs where it actually exists.
Fixes: bbe36e29ca2c ('serial: sh: Add HSCIF support for R-Car SoC') Signed-off-by: Paul Barker paul.barker.ct@bp.renesas.com Reviewed-by: Biju Das biju.das.jz@bp.renesas.com Cc: Hai Pham hai.pham.ud@renesas.com Cc: Marek Vasut marek.vasut+renesas@mailbox.org Cc: Simon Glass sjg@chromium.org
drivers/serial/serial_sh.c | 2 ++ 1 file changed, 2 insertions(+)
diff --git a/drivers/serial/serial_sh.c b/drivers/serial/serial_sh.c index 20cda5dbe272..5e543dbf3d58 100644 --- a/drivers/serial/serial_sh.c +++ b/drivers/serial/serial_sh.c @@ -58,8 +58,10 @@ static void sh_serial_init_generic(struct uart_port *port) sci_out(port, SCSPTR, 0x0003); #endif
+#if IS_ENABLED(CONFIG_RCAR_GEN2) || IS_ENABLED(CONFIG_RCAR_GEN3) || IS_ENABLED(CONFIG_RCAR_GEN4)
There should be CONFIG_RCAR_64 for GEN3+GEN4, please use it.
In patch 5 of this series I add CONFIG_RZG2L, which selects CONFIG_RCAR_64 but doesn't have HSCIF support.
An alternative would be to use this here:
#if IS_ENABLED(CONFIG_RCAR_GEN2) || IS_ENABLED(CONFIG_RCAR_64)
Then in patch 5 modify it to
#if IS_ENABLED(CONFIG_RCAR_GEN2) || IS_ENABLED(CONFIG_RCAR_64) &&
!IS_ENABLED(CONFIG_RZG2L)
I don't have any strong preference on which one to use.
I think, just keep the patch as-is and note the reason for not using RCAR_64 in the commit message (G2L has no HSCIF).

Import bindings for the Clock Pulse Generator (CPG) module in the Renesas RZ/G2L SoC family.
This patch is based on the dt-bindings in Linux v6.5.
Signed-off-by: Paul Barker paul.barker.ct@bp.renesas.com Reviewed-by: Biju Das biju.das.jz@bp.renesas.com Reviewed-by: Lad Prabhakar prabhakar.mahadev-lad.rj@bp.renesas.com --- include/dt-bindings/clock/r9a07g044-cpg.h | 220 ++++++++++++++++++++++ 1 file changed, 220 insertions(+) create mode 100644 include/dt-bindings/clock/r9a07g044-cpg.h
diff --git a/include/dt-bindings/clock/r9a07g044-cpg.h b/include/dt-bindings/clock/r9a07g044-cpg.h new file mode 100644 index 000000000000..0bb17ff1a01a --- /dev/null +++ b/include/dt-bindings/clock/r9a07g044-cpg.h @@ -0,0 +1,220 @@ +/* SPDX-License-Identifier: (GPL-2.0-only OR BSD-2-Clause) + * + * Copyright (C) 2021 Renesas Electronics Corp. + */ +#ifndef __DT_BINDINGS_CLOCK_R9A07G044_CPG_H__ +#define __DT_BINDINGS_CLOCK_R9A07G044_CPG_H__ + +#include <dt-bindings/clock/renesas-cpg-mssr.h> + +/* R9A07G044 CPG Core Clocks */ +#define R9A07G044_CLK_I 0 +#define R9A07G044_CLK_I2 1 +#define R9A07G044_CLK_G 2 +#define R9A07G044_CLK_S0 3 +#define R9A07G044_CLK_S1 4 +#define R9A07G044_CLK_SPI0 5 +#define R9A07G044_CLK_SPI1 6 +#define R9A07G044_CLK_SD0 7 +#define R9A07G044_CLK_SD1 8 +#define R9A07G044_CLK_M0 9 +#define R9A07G044_CLK_M1 10 +#define R9A07G044_CLK_M2 11 +#define R9A07G044_CLK_M3 12 +#define R9A07G044_CLK_M4 13 +#define R9A07G044_CLK_HP 14 +#define R9A07G044_CLK_TSU 15 +#define R9A07G044_CLK_ZT 16 +#define R9A07G044_CLK_P0 17 +#define R9A07G044_CLK_P1 18 +#define R9A07G044_CLK_P2 19 +#define R9A07G044_CLK_AT 20 +#define R9A07G044_OSCCLK 21 +#define R9A07G044_CLK_P0_DIV2 22 + +/* R9A07G044 Module Clocks */ +#define R9A07G044_CA55_SCLK 0 +#define R9A07G044_CA55_PCLK 1 +#define R9A07G044_CA55_ATCLK 2 +#define R9A07G044_CA55_GICCLK 3 +#define R9A07G044_CA55_PERICLK 4 +#define R9A07G044_CA55_ACLK 5 +#define R9A07G044_CA55_TSCLK 6 +#define R9A07G044_GIC600_GICCLK 7 +#define R9A07G044_IA55_CLK 8 +#define R9A07G044_IA55_PCLK 9 +#define R9A07G044_MHU_PCLK 10 +#define R9A07G044_SYC_CNT_CLK 11 +#define R9A07G044_DMAC_ACLK 12 +#define R9A07G044_DMAC_PCLK 13 +#define R9A07G044_OSTM0_PCLK 14 +#define R9A07G044_OSTM1_PCLK 15 +#define R9A07G044_OSTM2_PCLK 16 +#define R9A07G044_MTU_X_MCK_MTU3 17 +#define R9A07G044_POE3_CLKM_POE 18 +#define R9A07G044_GPT_PCLK 19 +#define R9A07G044_POEG_A_CLKP 20 +#define R9A07G044_POEG_B_CLKP 21 +#define R9A07G044_POEG_C_CLKP 22 +#define R9A07G044_POEG_D_CLKP 23 +#define R9A07G044_WDT0_PCLK 24 +#define R9A07G044_WDT0_CLK 25 +#define R9A07G044_WDT1_PCLK 26 +#define R9A07G044_WDT1_CLK 27 +#define R9A07G044_WDT2_PCLK 28 +#define R9A07G044_WDT2_CLK 29 +#define R9A07G044_SPI_CLK2 30 +#define R9A07G044_SPI_CLK 31 +#define R9A07G044_SDHI0_IMCLK 32 +#define R9A07G044_SDHI0_IMCLK2 33 +#define R9A07G044_SDHI0_CLK_HS 34 +#define R9A07G044_SDHI0_ACLK 35 +#define R9A07G044_SDHI1_IMCLK 36 +#define R9A07G044_SDHI1_IMCLK2 37 +#define R9A07G044_SDHI1_CLK_HS 38 +#define R9A07G044_SDHI1_ACLK 39 +#define R9A07G044_GPU_CLK 40 +#define R9A07G044_GPU_AXI_CLK 41 +#define R9A07G044_GPU_ACE_CLK 42 +#define R9A07G044_ISU_ACLK 43 +#define R9A07G044_ISU_PCLK 44 +#define R9A07G044_H264_CLK_A 45 +#define R9A07G044_H264_CLK_P 46 +#define R9A07G044_CRU_SYSCLK 47 +#define R9A07G044_CRU_VCLK 48 +#define R9A07G044_CRU_PCLK 49 +#define R9A07G044_CRU_ACLK 50 +#define R9A07G044_MIPI_DSI_PLLCLK 51 +#define R9A07G044_MIPI_DSI_SYSCLK 52 +#define R9A07G044_MIPI_DSI_ACLK 53 +#define R9A07G044_MIPI_DSI_PCLK 54 +#define R9A07G044_MIPI_DSI_VCLK 55 +#define R9A07G044_MIPI_DSI_LPCLK 56 +#define R9A07G044_LCDC_CLK_A 57 +#define R9A07G044_LCDC_CLK_P 58 +#define R9A07G044_LCDC_CLK_D 59 +#define R9A07G044_SSI0_PCLK2 60 +#define R9A07G044_SSI0_PCLK_SFR 61 +#define R9A07G044_SSI1_PCLK2 62 +#define R9A07G044_SSI1_PCLK_SFR 63 +#define R9A07G044_SSI2_PCLK2 64 +#define R9A07G044_SSI2_PCLK_SFR 65 +#define R9A07G044_SSI3_PCLK2 66 +#define R9A07G044_SSI3_PCLK_SFR 67 +#define R9A07G044_SRC_CLKP 68 +#define R9A07G044_USB_U2H0_HCLK 69 +#define R9A07G044_USB_U2H1_HCLK 70 +#define R9A07G044_USB_U2P_EXR_CPUCLK 71 +#define R9A07G044_USB_PCLK 72 +#define R9A07G044_ETH0_CLK_AXI 73 +#define R9A07G044_ETH0_CLK_CHI 74 +#define R9A07G044_ETH1_CLK_AXI 75 +#define R9A07G044_ETH1_CLK_CHI 76 +#define R9A07G044_I2C0_PCLK 77 +#define R9A07G044_I2C1_PCLK 78 +#define R9A07G044_I2C2_PCLK 79 +#define R9A07G044_I2C3_PCLK 80 +#define R9A07G044_SCIF0_CLK_PCK 81 +#define R9A07G044_SCIF1_CLK_PCK 82 +#define R9A07G044_SCIF2_CLK_PCK 83 +#define R9A07G044_SCIF3_CLK_PCK 84 +#define R9A07G044_SCIF4_CLK_PCK 85 +#define R9A07G044_SCI0_CLKP 86 +#define R9A07G044_SCI1_CLKP 87 +#define R9A07G044_IRDA_CLKP 88 +#define R9A07G044_RSPI0_CLKB 89 +#define R9A07G044_RSPI1_CLKB 90 +#define R9A07G044_RSPI2_CLKB 91 +#define R9A07G044_CANFD_PCLK 92 +#define R9A07G044_GPIO_HCLK 93 +#define R9A07G044_ADC_ADCLK 94 +#define R9A07G044_ADC_PCLK 95 +#define R9A07G044_TSU_PCLK 96 + +/* R9A07G044 Resets */ +#define R9A07G044_CA55_RST_1_0 0 +#define R9A07G044_CA55_RST_1_1 1 +#define R9A07G044_CA55_RST_3_0 2 +#define R9A07G044_CA55_RST_3_1 3 +#define R9A07G044_CA55_RST_4 4 +#define R9A07G044_CA55_RST_5 5 +#define R9A07G044_CA55_RST_6 6 +#define R9A07G044_CA55_RST_7 7 +#define R9A07G044_CA55_RST_8 8 +#define R9A07G044_CA55_RST_9 9 +#define R9A07G044_CA55_RST_10 10 +#define R9A07G044_CA55_RST_11 11 +#define R9A07G044_CA55_RST_12 12 +#define R9A07G044_GIC600_GICRESET_N 13 +#define R9A07G044_GIC600_DBG_GICRESET_N 14 +#define R9A07G044_IA55_RESETN 15 +#define R9A07G044_MHU_RESETN 16 +#define R9A07G044_DMAC_ARESETN 17 +#define R9A07G044_DMAC_RST_ASYNC 18 +#define R9A07G044_SYC_RESETN 19 +#define R9A07G044_OSTM0_PRESETZ 20 +#define R9A07G044_OSTM1_PRESETZ 21 +#define R9A07G044_OSTM2_PRESETZ 22 +#define R9A07G044_MTU_X_PRESET_MTU3 23 +#define R9A07G044_POE3_RST_M_REG 24 +#define R9A07G044_GPT_RST_C 25 +#define R9A07G044_POEG_A_RST 26 +#define R9A07G044_POEG_B_RST 27 +#define R9A07G044_POEG_C_RST 28 +#define R9A07G044_POEG_D_RST 29 +#define R9A07G044_WDT0_PRESETN 30 +#define R9A07G044_WDT1_PRESETN 31 +#define R9A07G044_WDT2_PRESETN 32 +#define R9A07G044_SPI_RST 33 +#define R9A07G044_SDHI0_IXRST 34 +#define R9A07G044_SDHI1_IXRST 35 +#define R9A07G044_GPU_RESETN 36 +#define R9A07G044_GPU_AXI_RESETN 37 +#define R9A07G044_GPU_ACE_RESETN 38 +#define R9A07G044_ISU_ARESETN 39 +#define R9A07G044_ISU_PRESETN 40 +#define R9A07G044_H264_X_RESET_VCP 41 +#define R9A07G044_H264_CP_PRESET_P 42 +#define R9A07G044_CRU_CMN_RSTB 43 +#define R9A07G044_CRU_PRESETN 44 +#define R9A07G044_CRU_ARESETN 45 +#define R9A07G044_MIPI_DSI_CMN_RSTB 46 +#define R9A07G044_MIPI_DSI_ARESET_N 47 +#define R9A07G044_MIPI_DSI_PRESET_N 48 +#define R9A07G044_LCDC_RESET_N 49 +#define R9A07G044_SSI0_RST_M2_REG 50 +#define R9A07G044_SSI1_RST_M2_REG 51 +#define R9A07G044_SSI2_RST_M2_REG 52 +#define R9A07G044_SSI3_RST_M2_REG 53 +#define R9A07G044_SRC_RST 54 +#define R9A07G044_USB_U2H0_HRESETN 55 +#define R9A07G044_USB_U2H1_HRESETN 56 +#define R9A07G044_USB_U2P_EXL_SYSRST 57 +#define R9A07G044_USB_PRESETN 58 +#define R9A07G044_ETH0_RST_HW_N 59 +#define R9A07G044_ETH1_RST_HW_N 60 +#define R9A07G044_I2C0_MRST 61 +#define R9A07G044_I2C1_MRST 62 +#define R9A07G044_I2C2_MRST 63 +#define R9A07G044_I2C3_MRST 64 +#define R9A07G044_SCIF0_RST_SYSTEM_N 65 +#define R9A07G044_SCIF1_RST_SYSTEM_N 66 +#define R9A07G044_SCIF2_RST_SYSTEM_N 67 +#define R9A07G044_SCIF3_RST_SYSTEM_N 68 +#define R9A07G044_SCIF4_RST_SYSTEM_N 69 +#define R9A07G044_SCI0_RST 70 +#define R9A07G044_SCI1_RST 71 +#define R9A07G044_IRDA_RST 72 +#define R9A07G044_RSPI0_RST 73 +#define R9A07G044_RSPI1_RST 74 +#define R9A07G044_RSPI2_RST 75 +#define R9A07G044_CANFD_RSTP_N 76 +#define R9A07G044_CANFD_RSTC_N 77 +#define R9A07G044_GPIO_RSTN 78 +#define R9A07G044_GPIO_PORT_RESETN 79 +#define R9A07G044_GPIO_SPARE_RESETN 80 +#define R9A07G044_ADC_PRESETN 81 +#define R9A07G044_ADC_ADRST_N 82 +#define R9A07G044_TSU_PRESETN 83 + +#endif /* __DT_BINDINGS_CLOCK_R9A07G044_CPG_H__ */

On 9/20/23 14:41, Paul Barker wrote:
Import bindings for the Clock Pulse Generator (CPG) module in the Renesas RZ/G2L SoC family.
This patch is based on the dt-bindings in Linux v6.5.
Please also include the exact commit ID in the remote project when importing files from it, see example in e.g.:
a7be3fb54a65 ("ARM: dts: renesas: Synchronize R-Car R8A77990 E3 DTs with Linux 6.5.3")
With that fixed:
Reviewed-by: Marek Vasut marek.vasut+renesas@mailbox.org

Import bindings for the Port Function Control (PFC) module in the Renesas RZ/G2L SoC family.
This patch is based on the dt-bindings in Linux v6.5.
Signed-off-by: Paul Barker paul.barker.ct@bp.renesas.com Reviewed-by: Biju Das biju.das.jz@bp.renesas.com Reviewed-by: Lad Prabhakar prabhakar.mahadev-lad.rj@bp.renesas.com --- include/dt-bindings/pinctrl/rzg2l-pinctrl.h | 23 +++++++++++++++++++++ 1 file changed, 23 insertions(+) create mode 100644 include/dt-bindings/pinctrl/rzg2l-pinctrl.h
diff --git a/include/dt-bindings/pinctrl/rzg2l-pinctrl.h b/include/dt-bindings/pinctrl/rzg2l-pinctrl.h new file mode 100644 index 000000000000..c78ed5e5efb7 --- /dev/null +++ b/include/dt-bindings/pinctrl/rzg2l-pinctrl.h @@ -0,0 +1,23 @@ +/* SPDX-License-Identifier: (GPL-2.0-only OR BSD-2-Clause) */ +/* + * This header provides constants for Renesas RZ/G2L family pinctrl bindings. + * + * Copyright (C) 2021 Renesas Electronics Corp. + * + */ + +#ifndef __DT_BINDINGS_RZG2L_PINCTRL_H +#define __DT_BINDINGS_RZG2L_PINCTRL_H + +#define RZG2L_PINS_PER_PORT 8 + +/* + * Create the pin index from its bank and position numbers and store in + * the upper 16 bits the alternate function identifier + */ +#define RZG2L_PORT_PINMUX(b, p, f) ((b) * RZG2L_PINS_PER_PORT + (p) | ((f) << 16)) + +/* Convert a port and pin label to its global pin index */ +#define RZG2L_GPIO(port, pin) ((port) * RZG2L_PINS_PER_PORT + (pin)) + +#endif /* __DT_BINDINGS_RZG2L_PINCTRL_H */

On 9/20/23 14:41, Paul Barker wrote:
Import bindings for the Port Function Control (PFC) module in the Renesas RZ/G2L SoC family.
This patch is based on the dt-bindings in Linux v6.5.
Signed-off-by: Paul Barker paul.barker.ct@bp.renesas.com Reviewed-by: Biju Das biju.das.jz@bp.renesas.com Reviewed-by: Lad Prabhakar prabhakar.mahadev-lad.rj@bp.renesas.com
Please also include the exact commit ID in the remote project when importing files from it, see example in e.g.:
a7be3fb54a65 ("ARM: dts: renesas: Synchronize R-Car R8A77990 E3 DTs with Linux 6.5.3")
With that fixed:
Reviewed-by: Marek Vasut marek.vasut+renesas@mailbox.org

Import bindings for the Interrupt Controller (IRQC) module in the Renesas RZ/G2L SoC family.
This patch is based on the dt-bindings in Linux v6.5.
Signed-off-by: Paul Barker paul.barker.ct@bp.renesas.com Reviewed-by: Biju Das biju.das.jz@bp.renesas.com Reviewed-by: Lad Prabhakar prabhakar.mahadev-lad.rj@bp.renesas.com --- .../interrupt-controller/irqc-rzg2l.h | 25 +++++++++++++++++++ 1 file changed, 25 insertions(+) create mode 100644 include/dt-bindings/interrupt-controller/irqc-rzg2l.h
diff --git a/include/dt-bindings/interrupt-controller/irqc-rzg2l.h b/include/dt-bindings/interrupt-controller/irqc-rzg2l.h new file mode 100644 index 000000000000..34ce778885a1 --- /dev/null +++ b/include/dt-bindings/interrupt-controller/irqc-rzg2l.h @@ -0,0 +1,25 @@ +/* SPDX-License-Identifier: (GPL-2.0-only OR BSD-2-Clause) */ +/* + * This header provides constants for Renesas RZ/G2L family IRQC bindings. + * + * Copyright (C) 2022 Renesas Electronics Corp. + * + */ + +#ifndef __DT_BINDINGS_IRQC_RZG2L_H +#define __DT_BINDINGS_IRQC_RZG2L_H + +/* NMI maps to SPI0 */ +#define RZG2L_NMI 0 + +/* IRQ0-7 map to SPI1-8 */ +#define RZG2L_IRQ0 1 +#define RZG2L_IRQ1 2 +#define RZG2L_IRQ2 3 +#define RZG2L_IRQ3 4 +#define RZG2L_IRQ4 5 +#define RZG2L_IRQ5 6 +#define RZG2L_IRQ6 7 +#define RZG2L_IRQ7 8 + +#endif /* __DT_BINDINGS_IRQC_RZG2L_H */

On 9/20/23 14:42, Paul Barker wrote:
Import bindings for the Interrupt Controller (IRQC) module in the Renesas RZ/G2L SoC family.
This patch is based on the dt-bindings in Linux v6.5.
Please also include the exact commit ID in the remote project when importing files from it, see example in e.g.:
a7be3fb54a65 ("ARM: dts: renesas: Synchronize R-Car R8A77990 E3 DTs with Linux 6.5.3")
With that fixed:
Reviewed-by: Marek Vasut marek.vasut+renesas@mailbox.org

The Renesas RZ/G2L family includes the following ARM SoCs:
* RZ/G2L (r9a07g044l) * RZ/G2LC (r9a07g044c) * RZ/G2UL (r9a07g043u) * RZ/V2L (r9a07g054l)
Support for individual SoCs and evaluation boards will be added in separate patches.
Signed-off-by: Paul Barker paul.barker.ct@bp.renesas.com Reviewed-by: Biju Das biju.das.jz@bp.renesas.com Reviewed-by: Lad Prabhakar prabhakar.mahadev-lad.rj@bp.renesas.com --- arch/arm/mach-rmobile/Kconfig | 13 +++++++++++++ arch/arm/mach-rmobile/Kconfig.rzg2l | 12 ++++++++++++ arch/arm/mach-rmobile/include/mach/rmobile.h | 2 ++ arch/arm/mach-rmobile/include/mach/rzg2l.h | 13 +++++++++++++ 4 files changed, 40 insertions(+) create mode 100644 arch/arm/mach-rmobile/Kconfig.rzg2l create mode 100644 arch/arm/mach-rmobile/include/mach/rzg2l.h
diff --git a/arch/arm/mach-rmobile/Kconfig b/arch/arm/mach-rmobile/Kconfig index 3061ccd34c8b..fd240832d83d 100644 --- a/arch/arm/mach-rmobile/Kconfig +++ b/arch/arm/mach-rmobile/Kconfig @@ -66,6 +66,18 @@ config RZN1 select SYSRESET_SYSCON imply CMD_DM
+config RZG2L + prompt "Renesas RZ/G2L Family ARM SoCs" + select RCAR_64 + select GICV3 + imply MULTI_DTB_FIT + imply MULTI_DTB_FIT_USER_DEFINED_AREA + imply SYS_MALLOC_F + imply RENESAS_SDHI + help + Enable support for the Renesas RZ/G2L family of SoCs, including the + the RZ/G2L itself (based on the R9A07G044 SoC). + endchoice
config SYS_SOC @@ -75,5 +87,6 @@ source "arch/arm/mach-rmobile/Kconfig.32" source "arch/arm/mach-rmobile/Kconfig.64" source "arch/arm/mach-rmobile/Kconfig.rza1" source "arch/arm/mach-rmobile/Kconfig.rzn1" +source "arch/arm/mach-rmobile/Kconfig.rzg2l"
endif diff --git a/arch/arm/mach-rmobile/Kconfig.rzg2l b/arch/arm/mach-rmobile/Kconfig.rzg2l new file mode 100644 index 000000000000..37ff6cd34160 --- /dev/null +++ b/arch/arm/mach-rmobile/Kconfig.rzg2l @@ -0,0 +1,12 @@ +# Copyright (C) 2023 Renesas Electronics Corporation +# SPDX-License-Identifier: GPL-2.0+ + +if RZG2L + +config MULTI_DTB_FIT_UNCOMPRESS_SZ + default 0x80000 if TARGET_RZG2L_SMARC_EVK + +config MULTI_DTB_FIT_USER_DEF_ADDR + default 0x49000000 if TARGET_RZG2L_SMARC_EVK + +endif diff --git a/arch/arm/mach-rmobile/include/mach/rmobile.h b/arch/arm/mach-rmobile/include/mach/rmobile.h index a14c2aad0a68..d326d5545a6f 100644 --- a/arch/arm/mach-rmobile/include/mach/rmobile.h +++ b/arch/arm/mach-rmobile/include/mach/rmobile.h @@ -19,6 +19,8 @@ #elif defined(CONFIG_RCAR_GEN4) #include <asm/arch/rcar-gen4-base.h> #elif defined(CONFIG_R7S72100) +#elif defined(CONFIG_RZG2L) +#include <asm/arch/rzg2l.h> #else #error "SOC Name not defined" #endif diff --git a/arch/arm/mach-rmobile/include/mach/rzg2l.h b/arch/arm/mach-rmobile/include/mach/rzg2l.h new file mode 100644 index 000000000000..057df5cb9d46 --- /dev/null +++ b/arch/arm/mach-rmobile/include/mach/rzg2l.h @@ -0,0 +1,13 @@ +/* SPDX-License-Identifier: GPL-2.0+ */ +/* + * RZ/G2L SoC Family support. + * Copyright (C) 2023 Renesas Electronics Corporation + */ + +#ifndef __ASM_ARCH_RZG2L_H +#define __ASM_ARCH_RZG2L_H + +#define GICD_BASE 0x11900000 +#define GICR_BASE 0x11960000 + +#endif /* __ASM_ARCH_RZG2L_H */

On 9/20/23 14:42, Paul Barker wrote:
The Renesas RZ/G2L family includes the following ARM SoCs:
- RZ/G2L (r9a07g044l)
- RZ/G2LC (r9a07g044c)
- RZ/G2UL (r9a07g043u)
- RZ/V2L (r9a07g054l)
Support for individual SoCs and evaluation boards will be added in separate patches.
Signed-off-by: Paul Barker paul.barker.ct@bp.renesas.com Reviewed-by: Biju Das biju.das.jz@bp.renesas.com Reviewed-by: Lad Prabhakar prabhakar.mahadev-lad.rj@bp.renesas.com
arch/arm/mach-rmobile/Kconfig | 13 +++++++++++++ arch/arm/mach-rmobile/Kconfig.rzg2l | 12 ++++++++++++ arch/arm/mach-rmobile/include/mach/rmobile.h | 2 ++ arch/arm/mach-rmobile/include/mach/rzg2l.h | 13 +++++++++++++ 4 files changed, 40 insertions(+) create mode 100644 arch/arm/mach-rmobile/Kconfig.rzg2l create mode 100644 arch/arm/mach-rmobile/include/mach/rzg2l.h
diff --git a/arch/arm/mach-rmobile/Kconfig b/arch/arm/mach-rmobile/Kconfig index 3061ccd34c8b..fd240832d83d 100644 --- a/arch/arm/mach-rmobile/Kconfig +++ b/arch/arm/mach-rmobile/Kconfig @@ -66,6 +66,18 @@ config RZN1 select SYSRESET_SYSCON imply CMD_DM
+config RZG2L
- prompt "Renesas RZ/G2L Family ARM SoCs"
- select RCAR_64
- select GICV3
- imply MULTI_DTB_FIT
- imply MULTI_DTB_FIT_USER_DEFINED_AREA
- imply SYS_MALLOC_F
- imply RENESAS_SDHI
Keep the list sorted
- help
Enable support for the Renesas RZ/G2L family of SoCs, including the
the RZ/G2L itself (based on the R9A07G044 SoC).
Including the RZ/G2L itself ... and what else (you likely want to add answer to that into this paragraph) ?
endchoice
config SYS_SOC @@ -75,5 +87,6 @@ source "arch/arm/mach-rmobile/Kconfig.32" source "arch/arm/mach-rmobile/Kconfig.64" source "arch/arm/mach-rmobile/Kconfig.rza1" source "arch/arm/mach-rmobile/Kconfig.rzn1" +source "arch/arm/mach-rmobile/Kconfig.rzg2l"
endif
With that fixed:
Reviewed-by: Marek Vasut marek.vasut+renesas@mailbox.org

On 03/10/2023 13:45, Marek Vasut wrote:
On 9/20/23 14:42, Paul Barker wrote:
- help
Enable support for the Renesas RZ/G2L family of SoCs, including the
the RZ/G2L itself (based on the R9A07G044 SoC).
Including the RZ/G2L itself ... and what else (you likely want to add answer to that into this paragraph) ?
The intention is to expand this list as support for the other boards is added in future patches, rather than advertising support in the help message which isn't available yet.
The family of boards is: * RZ/G2L * RZ/G2LC * RZ/G2UL * RZ/V2L * RZ/Five
RZ/Five will be handled separately as that's RISC-V architecture so won't belong in a Kconfig under arch/arm.
The family has no "official" name, but all share the same core set of IP blocks so drivers will be reused across them. Typically the drivers have 'rzg2l' in the name in Linux (e.g. drivers/clk/renesas/rzg2l-cpg.c), so I'm doing the same here. We tend to refer to the group of SoCs as the "RZ/G2L family", and the RZ/G2L itself is a member of that family.
Thanks, Paul

On 10/4/23 09:58, Paul Barker wrote:
On 03/10/2023 13:45, Marek Vasut wrote:
On 9/20/23 14:42, Paul Barker wrote:
- help
Enable support for the Renesas RZ/G2L family of SoCs, including the
the RZ/G2L itself (based on the R9A07G044 SoC).
Including the RZ/G2L itself ... and what else (you likely want to add answer to that into this paragraph) ?
The intention is to expand this list as support for the other boards is added in future patches, rather than advertising support in the help message which isn't available yet.
The family of boards is:
- RZ/G2L
- RZ/G2LC
- RZ/G2UL
- RZ/V2L
- RZ/Five
RZ/Five will be handled separately as that's RISC-V architecture so won't belong in a Kconfig under arch/arm.
The family has no "official" name, but all share the same core set of IP blocks so drivers will be reused across them. Typically the drivers have 'rzg2l' in the name in Linux (e.g. drivers/clk/renesas/rzg2l-cpg.c), so I'm doing the same here. We tend to refer to the group of SoCs as the "RZ/G2L family", and the RZ/G2L itself is a member of that family.
So maybe just add "Additional SoC support is currently not implemented." or something along those lines into the paragraph.

Add a config option for the R9A07G044L SoC used in the RZ/G2L so that we can make use of this in the subsequent driver patches.
Signed-off-by: Paul Barker paul.barker.ct@bp.renesas.com Reviewed-by: Biju Das biju.das.jz@bp.renesas.com Reviewed-by: Lad Prabhakar prabhakar.mahadev-lad.rj@bp.renesas.com --- arch/arm/mach-rmobile/Kconfig.rzg2l | 5 +++++ 1 file changed, 5 insertions(+)
diff --git a/arch/arm/mach-rmobile/Kconfig.rzg2l b/arch/arm/mach-rmobile/Kconfig.rzg2l index 37ff6cd34160..266f82c18085 100644 --- a/arch/arm/mach-rmobile/Kconfig.rzg2l +++ b/arch/arm/mach-rmobile/Kconfig.rzg2l @@ -3,6 +3,11 @@
if RZG2L
+config R9A07G044L + bool "Renesas R9A07G044L SoC" + help + Enable support for the R9A07G044L SoC used in the RZ/G2L. + config MULTI_DTB_FIT_UNCOMPRESS_SZ default 0x80000 if TARGET_RZG2L_SMARC_EVK

On 9/20/23 14:42, Paul Barker wrote:
Add a config option for the R9A07G044L SoC used in the RZ/G2L so that we can make use of this in the subsequent driver patches.
Signed-off-by: Paul Barker paul.barker.ct@bp.renesas.com Reviewed-by: Biju Das biju.das.jz@bp.renesas.com Reviewed-by: Lad Prabhakar prabhakar.mahadev-lad.rj@bp.renesas.com
arch/arm/mach-rmobile/Kconfig.rzg2l | 5 +++++ 1 file changed, 5 insertions(+)
diff --git a/arch/arm/mach-rmobile/Kconfig.rzg2l b/arch/arm/mach-rmobile/Kconfig.rzg2l index 37ff6cd34160..266f82c18085 100644 --- a/arch/arm/mach-rmobile/Kconfig.rzg2l +++ b/arch/arm/mach-rmobile/Kconfig.rzg2l @@ -3,6 +3,11 @@
if RZG2L
+config R9A07G044L
- bool "Renesas R9A07G044L SoC"
- help
Enable support for the R9A07G044L SoC used in the RZ/G2L.
I was under the impression that RZ/G2L is a SoC family, so the R9A07G044L is part of that SoC family ? Maybe just reword this paragraph and the commit message a bit to make it less confusing.

On 03/10/2023 13:46, Marek Vasut wrote:
On 9/20/23 14:42, Paul Barker wrote:
Add a config option for the R9A07G044L SoC used in the RZ/G2L so that we can make use of this in the subsequent driver patches.
Signed-off-by: Paul Barker paul.barker.ct@bp.renesas.com Reviewed-by: Biju Das biju.das.jz@bp.renesas.com Reviewed-by: Lad Prabhakar prabhakar.mahadev-lad.rj@bp.renesas.com
arch/arm/mach-rmobile/Kconfig.rzg2l | 5 +++++ 1 file changed, 5 insertions(+)
diff --git a/arch/arm/mach-rmobile/Kconfig.rzg2l b/arch/arm/mach-rmobile/Kconfig.rzg2l index 37ff6cd34160..266f82c18085 100644 --- a/arch/arm/mach-rmobile/Kconfig.rzg2l +++ b/arch/arm/mach-rmobile/Kconfig.rzg2l @@ -3,6 +3,11 @@
if RZG2L
+config R9A07G044L
- bool "Renesas R9A07G044L SoC"
- help
Enable support for the R9A07G044L SoC used in the RZ/G2L.
I was under the impression that RZ/G2L is a SoC family, so the R9A07G044L is part of that SoC family ? Maybe just reword this paragraph and the commit message a bit to make it less confusing.
The confusion is hard to avoid (see my reply re patch 5 of this series), but I'll see if I can improve this a bit in v2.
Thanks, Paul

On 10/4/23 09:59, Paul Barker wrote:
On 03/10/2023 13:46, Marek Vasut wrote:
On 9/20/23 14:42, Paul Barker wrote:
Add a config option for the R9A07G044L SoC used in the RZ/G2L so that we can make use of this in the subsequent driver patches.
Signed-off-by: Paul Barker paul.barker.ct@bp.renesas.com Reviewed-by: Biju Das biju.das.jz@bp.renesas.com Reviewed-by: Lad Prabhakar prabhakar.mahadev-lad.rj@bp.renesas.com
arch/arm/mach-rmobile/Kconfig.rzg2l | 5 +++++ 1 file changed, 5 insertions(+)
diff --git a/arch/arm/mach-rmobile/Kconfig.rzg2l b/arch/arm/mach-rmobile/Kconfig.rzg2l index 37ff6cd34160..266f82c18085 100644 --- a/arch/arm/mach-rmobile/Kconfig.rzg2l +++ b/arch/arm/mach-rmobile/Kconfig.rzg2l @@ -3,6 +3,11 @@
if RZG2L
+config R9A07G044L
- bool "Renesas R9A07G044L SoC"
- help
Enable support for the R9A07G044L SoC used in the RZ/G2L.
I was under the impression that RZ/G2L is a SoC family, so the R9A07G044L is part of that SoC family ? Maybe just reword this paragraph and the commit message a bit to make it less confusing.
The confusion is hard to avoid (see my reply re patch 5 of this series), but I'll see if I can improve this a bit in v2.
So uh ... RZ/G2L is both the name of R9A07G044L SoC (what's the R9... model number of e.g. RZ/G2LC?) and a family name ?

On Wed, Oct 04, 2023 at 02:15:24PM +0200, Marek Vasut wrote:
On 10/4/23 09:59, Paul Barker wrote:
On 03/10/2023 13:46, Marek Vasut wrote:
On 9/20/23 14:42, Paul Barker wrote:
Add a config option for the R9A07G044L SoC used in the RZ/G2L so that we can make use of this in the subsequent driver patches.
Signed-off-by: Paul Barker paul.barker.ct@bp.renesas.com Reviewed-by: Biju Das biju.das.jz@bp.renesas.com Reviewed-by: Lad Prabhakar prabhakar.mahadev-lad.rj@bp.renesas.com
arch/arm/mach-rmobile/Kconfig.rzg2l | 5 +++++ 1 file changed, 5 insertions(+)
diff --git a/arch/arm/mach-rmobile/Kconfig.rzg2l b/arch/arm/mach-rmobile/Kconfig.rzg2l index 37ff6cd34160..266f82c18085 100644 --- a/arch/arm/mach-rmobile/Kconfig.rzg2l +++ b/arch/arm/mach-rmobile/Kconfig.rzg2l @@ -3,6 +3,11 @@ if RZG2L +config R9A07G044L
- bool "Renesas R9A07G044L SoC"
- help
Enable support for the R9A07G044L SoC used in the RZ/G2L.
I was under the impression that RZ/G2L is a SoC family, so the R9A07G044L is part of that SoC family ? Maybe just reword this paragraph and the commit message a bit to make it less confusing.
The confusion is hard to avoid (see my reply re patch 5 of this series), but I'll see if I can improve this a bit in v2.
So uh ... RZ/G2L is both the name of R9A07G044L SoC (what's the R9... model number of e.g. RZ/G2LC?) and a family name ?
Yes. Definitely easy to confuse!
We have (with differences from the RZ/G2L model numbers highlighted): * RZ/G2L (R9A07G044L1 or R9A07G044L2) * RZ/G2LC (R9A07G044*C*1 or R9A07G044*C*2) * RZ/G2UL (R9A07G04*3U1*) * RZ/V2L (R9A07G0*5*4L1 or R9A07G0*5*4L2) * RZ/Five (R9A07G04*3F0*)
The last digit indicates the number of cores (1 or 2), except for on the RZ/Five which has one core but the model number ends in a zero.
Thanks, Paul

On 10/4/23 15:26, Paul Barker wrote:
On Wed, Oct 04, 2023 at 02:15:24PM +0200, Marek Vasut wrote:
On 10/4/23 09:59, Paul Barker wrote:
On 03/10/2023 13:46, Marek Vasut wrote:
On 9/20/23 14:42, Paul Barker wrote:
Add a config option for the R9A07G044L SoC used in the RZ/G2L so that we can make use of this in the subsequent driver patches.
Signed-off-by: Paul Barker paul.barker.ct@bp.renesas.com Reviewed-by: Biju Das biju.das.jz@bp.renesas.com Reviewed-by: Lad Prabhakar prabhakar.mahadev-lad.rj@bp.renesas.com
arch/arm/mach-rmobile/Kconfig.rzg2l | 5 +++++ 1 file changed, 5 insertions(+)
diff --git a/arch/arm/mach-rmobile/Kconfig.rzg2l b/arch/arm/mach-rmobile/Kconfig.rzg2l index 37ff6cd34160..266f82c18085 100644 --- a/arch/arm/mach-rmobile/Kconfig.rzg2l +++ b/arch/arm/mach-rmobile/Kconfig.rzg2l @@ -3,6 +3,11 @@ if RZG2L +config R9A07G044L
- bool "Renesas R9A07G044L SoC"
- help
Enable support for the R9A07G044L SoC used in the RZ/G2L.
I was under the impression that RZ/G2L is a SoC family, so the R9A07G044L is part of that SoC family ? Maybe just reword this paragraph and the commit message a bit to make it less confusing.
The confusion is hard to avoid (see my reply re patch 5 of this series), but I'll see if I can improve this a bit in v2.
So uh ... RZ/G2L is both the name of R9A07G044L SoC (what's the R9... model number of e.g. RZ/G2LC?) and a family name ?
Yes. Definitely easy to confuse!
We have (with differences from the RZ/G2L model numbers highlighted):
- RZ/G2L (R9A07G044L1 or R9A07G044L2)
- RZ/G2LC (R9A07G044*C*1 or R9A07G044*C*2)
- RZ/G2UL (R9A07G04*3U1*)
- RZ/V2L (R9A07G0*5*4L1 or R9A07G0*5*4L2)
- RZ/Five (R9A07G04*3F0*)
The last digit indicates the number of cores (1 or 2), except for on the RZ/Five which has one core but the model number ends in a zero.
OK, got it, thanks !

This driver provides clock and reset control for the Renesas RZ/G2L (R9A07G044) SoC. It consists of two parts:
* driver code which is applicable to all SoCs in the RZ/G2L family
* static data describing the clocks and resets which are specific to the R9A07G044 SoC.
clk_set_rate() and clk_get_rate() are implemented only for the clocks that are actually used in u-boot.
The CPG driver is marked with DM_FLAG_PRE_RELOC to ensure that its bind function is called before the SCIF (serial port) driver is probed. This is required so that we can de-assert the relevant reset signal during the serial driver probe function.
This patch is based on the corresponding Linux v6.5 driver.
Signed-off-by: Paul Barker paul.barker.ct@bp.renesas.com Reviewed-by: Biju Das biju.das.jz@bp.renesas.com Reviewed-by: Lad Prabhakar prabhakar.mahadev-lad.rj@bp.renesas.com --- arch/arm/mach-rmobile/Kconfig | 1 + arch/arm/mach-rmobile/Kconfig.rzg2l | 1 + drivers/clk/renesas/Kconfig | 9 + drivers/clk/renesas/Makefile | 2 + drivers/clk/renesas/r9a07g044-cpg.c | 384 +++++++++++++++++++++ drivers/clk/renesas/rzg2l-cpg.c | 502 ++++++++++++++++++++++++++++ drivers/clk/renesas/rzg2l-cpg.h | 318 ++++++++++++++++++ 7 files changed, 1217 insertions(+) create mode 100644 drivers/clk/renesas/r9a07g044-cpg.c create mode 100644 drivers/clk/renesas/rzg2l-cpg.c create mode 100644 drivers/clk/renesas/rzg2l-cpg.h
diff --git a/arch/arm/mach-rmobile/Kconfig b/arch/arm/mach-rmobile/Kconfig index fd240832d83d..fc37f6c79e50 100644 --- a/arch/arm/mach-rmobile/Kconfig +++ b/arch/arm/mach-rmobile/Kconfig @@ -74,6 +74,7 @@ config RZG2L imply MULTI_DTB_FIT_USER_DEFINED_AREA imply SYS_MALLOC_F imply RENESAS_SDHI + imply CLK_RZG2L help Enable support for the Renesas RZ/G2L family of SoCs, including the the RZ/G2L itself (based on the R9A07G044 SoC). diff --git a/arch/arm/mach-rmobile/Kconfig.rzg2l b/arch/arm/mach-rmobile/Kconfig.rzg2l index 266f82c18085..7d268e8c366a 100644 --- a/arch/arm/mach-rmobile/Kconfig.rzg2l +++ b/arch/arm/mach-rmobile/Kconfig.rzg2l @@ -5,6 +5,7 @@ if RZG2L
config R9A07G044L bool "Renesas R9A07G044L SoC" + imply CLK_R9A07G044 help Enable support for the R9A07G044L SoC used in the RZ/G2L.
diff --git a/drivers/clk/renesas/Kconfig b/drivers/clk/renesas/Kconfig index 437a82cd48be..927d62cf99a3 100644 --- a/drivers/clk/renesas/Kconfig +++ b/drivers/clk/renesas/Kconfig @@ -156,3 +156,12 @@ config CLK_R9A06G032 depends on CLK_RENESAS help Enable this to support the clocks on Renesas R9A06G032 SoC. + +config CLK_RZG2L + bool "Renesas RZ/G2L family clock support" + depends on CLK_RENESAS + select DM_RESET + +config CLK_R9A07G044 + bool "RZ/G2L (R9A07G044L) clock support" + depends on CLK_RZG2L diff --git a/drivers/clk/renesas/Makefile b/drivers/clk/renesas/Makefile index 48373e61b901..df7e225e9ca4 100644 --- a/drivers/clk/renesas/Makefile +++ b/drivers/clk/renesas/Makefile @@ -23,3 +23,5 @@ obj-$(CONFIG_CLK_R8A779A0) += r8a779a0-cpg-mssr.o obj-$(CONFIG_CLK_R8A779F0) += r8a779f0-cpg-mssr.o obj-$(CONFIG_CLK_R8A779G0) += r8a779g0-cpg-mssr.o obj-$(CONFIG_CLK_R9A06G032) += r9a06g032-clocks.o +obj-$(CONFIG_CLK_RZG2L) += rzg2l-cpg.o +obj-$(CONFIG_CLK_R9A07G044) += r9a07g044-cpg.o diff --git a/drivers/clk/renesas/r9a07g044-cpg.c b/drivers/clk/renesas/r9a07g044-cpg.c new file mode 100644 index 000000000000..e215db7caf15 --- /dev/null +++ b/drivers/clk/renesas/r9a07g044-cpg.c @@ -0,0 +1,384 @@ +// SPDX-License-Identifier: GPL-2.0 +/* + * RZ/G2L CPG driver + * + * Copyright (C) 2021-2023 Renesas Electronics Corp. + */ + +#include <common.h> +#include <dm/device.h> +#include <dt-bindings/clock/r9a07g044-cpg.h> +#include <linux/clk-provider.h> + +#include "rzg2l-cpg.h" + +/* Divider tables */ +static const struct clk_div_table dtable_1_8[] = { + {0, 1}, + {1, 2}, + {2, 4}, + {3, 8}, + {0, 0}, +}; + +static const struct clk_div_table dtable_1_32[] = { + {0, 1}, + {1, 2}, + {2, 4}, + {3, 8}, + {4, 32}, + {0, 0}, +}; + +static const struct clk_div_table dtable_16_128[] = { + {0, 16}, + {1, 32}, + {2, 64}, + {3, 128}, + {0, 0}, +}; + +/* Mux clock tables */ +static const char * const sel_pll3_3[] = { ".pll3_533", ".pll3_400" }; +static const char * const sel_pll5_4[] = { ".pll5_foutpostdiv", ".pll5_fout1ph0" }; +static const char * const sel_pll6_2[] = { ".pll6_250", ".pll5_250" }; +static const char * const sel_shdi[] = { ".clk_533", ".clk_400", ".clk_266" }; +static const char * const sel_gpu2[] = { ".pll6", ".pll3_div2_2" }; + +static const struct { + struct cpg_core_clk common[56]; +} core_clks = { + .common = { + /* External Clock Inputs */ + DEF_INPUT("extal", CLK_EXTAL), + + /* Internal Core Clocks */ + DEF_FIXED(".osc", R9A07G044_OSCCLK, CLK_EXTAL, 1, 1), + DEF_FIXED(".osc_div1000", CLK_OSC_DIV1000, CLK_EXTAL, 1, 1000), + DEF_SAMPLL(".pll1", CLK_PLL1, CLK_EXTAL, PLL146_CONF(0)), + DEF_FIXED(".pll2", CLK_PLL2, CLK_EXTAL, 200, 3), + DEF_FIXED(".pll2_533", CLK_PLL2_533, CLK_PLL2, 1, 3), + DEF_FIXED(".pll3", CLK_PLL3, CLK_EXTAL, 200, 3), + DEF_FIXED(".pll3_400", CLK_PLL3_400, CLK_PLL3, 1, 4), + DEF_FIXED(".pll3_533", CLK_PLL3_533, CLK_PLL3, 1, 3), + + DEF_FIXED(".pll5", CLK_PLL5, CLK_EXTAL, 125, 1), + DEF_FIXED(".pll5_fout3", CLK_PLL5_FOUT3, CLK_PLL5, 1, 6), + + DEF_FIXED(".pll6", CLK_PLL6, CLK_EXTAL, 125, 6), + + DEF_FIXED(".pll2_div2", CLK_PLL2_DIV2, CLK_PLL2, 1, 2), + DEF_FIXED(".clk_800", CLK_PLL2_800, CLK_PLL2, 1, 2), + DEF_FIXED(".clk_533", CLK_PLL2_SDHI_533, CLK_PLL2, 1, 3), + DEF_FIXED(".clk_400", CLK_PLL2_SDHI_400, CLK_PLL2_800, 1, 2), + DEF_FIXED(".clk_266", CLK_PLL2_SDHI_266, CLK_PLL2_SDHI_533, 1, 2), + + DEF_FIXED(".pll2_div2_8", CLK_PLL2_DIV2_8, CLK_PLL2_DIV2, 1, 8), + DEF_FIXED(".pll2_div2_10", CLK_PLL2_DIV2_10, CLK_PLL2_DIV2, 1, 10), + + DEF_FIXED(".pll2_533_div2", CLK_PLL2_533_DIV2, CLK_PLL2_533, 1, 2), + + DEF_FIXED(".pll3_div2", CLK_PLL3_DIV2, CLK_PLL3, 1, 2), + DEF_FIXED(".pll3_div2_2", CLK_PLL3_DIV2_2, CLK_PLL3_DIV2, 1, 2), + DEF_FIXED(".pll3_div2_4", CLK_PLL3_DIV2_4, CLK_PLL3_DIV2, 1, 4), + DEF_FIXED(".pll3_div2_4_2", CLK_PLL3_DIV2_4_2, CLK_PLL3_DIV2_4, 1, 2), + DEF_MUX_RO(".sel_pll3_3", CLK_SEL_PLL3_3, SEL_PLL3_3, sel_pll3_3), + DEF_DIV("divpl3c", CLK_DIV_PLL3_C, CLK_SEL_PLL3_3, DIVPL3C, dtable_1_32), + + DEF_FIXED(".pll5_250", CLK_PLL5_250, CLK_PLL5_FOUT3, 1, 2), + DEF_FIXED(".pll6_250", CLK_PLL6_250, CLK_PLL6, 1, 2), + DEF_MUX_RO(".sel_gpu2", CLK_SEL_GPU2, SEL_GPU2, sel_gpu2), + DEF_PLL5_FOUTPOSTDIV(".pll5_foutpostdiv", CLK_PLL5_FOUTPOSTDIV, CLK_EXTAL), + DEF_FIXED(".pll5_fout1ph0", CLK_PLL5_FOUT1PH0, CLK_PLL5_FOUTPOSTDIV, 1, 2), + DEF_PLL5_4_MUX(".sel_pll5_4", CLK_SEL_PLL5_4, SEL_PLL5_4, sel_pll5_4), + DEF_DIV(".div_dsi_lpclk", CLK_DIV_DSI_LPCLK, CLK_PLL2_533_DIV2, + DIVDSILPCLK, dtable_16_128), + + /* Core output clk */ + DEF_DIV("I", R9A07G044_CLK_I, CLK_PLL1, DIVPL1A, dtable_1_8), + DEF_DIV("P0", R9A07G044_CLK_P0, CLK_PLL2_DIV2_8, DIVPL2A, dtable_1_32), + DEF_FIXED("P0_DIV2", R9A07G044_CLK_P0_DIV2, R9A07G044_CLK_P0, 1, 2), + DEF_FIXED("TSU", R9A07G044_CLK_TSU, CLK_PLL2_DIV2_10, 1, 1), + DEF_DIV("P1", R9A07G044_CLK_P1, CLK_PLL3_DIV2_4, DIVPL3B, dtable_1_32), + DEF_FIXED("P1_DIV2", CLK_P1_DIV2, R9A07G044_CLK_P1, 1, 2), + DEF_DIV("P2", R9A07G044_CLK_P2, CLK_PLL3_DIV2_4_2, DIVPL3A, dtable_1_32), + DEF_FIXED("M0", R9A07G044_CLK_M0, CLK_PLL3_DIV2_4, 1, 1), + DEF_FIXED("ZT", R9A07G044_CLK_ZT, CLK_PLL3_DIV2_4_2, 1, 1), + DEF_MUX("HP", R9A07G044_CLK_HP, SEL_PLL6_2, sel_pll6_2), + DEF_FIXED("SPI0", R9A07G044_CLK_SPI0, CLK_DIV_PLL3_C, 1, 2), + DEF_FIXED("SPI1", R9A07G044_CLK_SPI1, CLK_DIV_PLL3_C, 1, 4), + DEF_SD_MUX("SD0", R9A07G044_CLK_SD0, SEL_SDHI0, sel_shdi), + DEF_SD_MUX("SD1", R9A07G044_CLK_SD1, SEL_SDHI1, sel_shdi), + DEF_FIXED("SD0_DIV4", CLK_SD0_DIV4, R9A07G044_CLK_SD0, 1, 4), + DEF_FIXED("SD1_DIV4", CLK_SD1_DIV4, R9A07G044_CLK_SD1, 1, 4), + DEF_DIV("G", R9A07G044_CLK_G, CLK_SEL_GPU2, DIVGPU, dtable_1_8), + DEF_FIXED("M1", R9A07G044_CLK_M1, CLK_PLL5_FOUTPOSTDIV, 1, 1), + DEF_FIXED("M2", R9A07G044_CLK_M2, CLK_PLL3_533, 1, 2), + DEF_FIXED("M2_DIV2", CLK_M2_DIV2, R9A07G044_CLK_M2, 1, 2), + DEF_DSI_DIV("DSI_DIV", CLK_DSI_DIV, CLK_SEL_PLL5_4, CLK_SET_RATE_PARENT), + DEF_FIXED("M3", R9A07G044_CLK_M3, CLK_DSI_DIV, 1, 1), + DEF_FIXED("M4", R9A07G044_CLK_M4, CLK_DIV_DSI_LPCLK, 1, 1), + }, +}; + +static const struct { + struct rzg2l_mod_clk common[79]; +} mod_clks = { + .common = { + DEF_MOD("gic", R9A07G044_GIC600_GICCLK, R9A07G044_CLK_P1, + 0x514, 0), + DEF_MOD("ia55_pclk", R9A07G044_IA55_PCLK, R9A07G044_CLK_P2, + 0x518, 0), + DEF_MOD("ia55_clk", R9A07G044_IA55_CLK, R9A07G044_CLK_P1, + 0x518, 1), + DEF_MOD("dmac_aclk", R9A07G044_DMAC_ACLK, R9A07G044_CLK_P1, + 0x52c, 0), + DEF_MOD("dmac_pclk", R9A07G044_DMAC_PCLK, CLK_P1_DIV2, + 0x52c, 1), + DEF_MOD("ostm0_pclk", R9A07G044_OSTM0_PCLK, R9A07G044_CLK_P0, + 0x534, 0), + DEF_MOD("ostm1_pclk", R9A07G044_OSTM1_PCLK, R9A07G044_CLK_P0, + 0x534, 1), + DEF_MOD("ostm2_pclk", R9A07G044_OSTM2_PCLK, R9A07G044_CLK_P0, + 0x534, 2), + DEF_MOD("mtu_x_mck", R9A07G044_MTU_X_MCK_MTU3, R9A07G044_CLK_P0, + 0x538, 0), + DEF_MOD("gpt_pclk", R9A07G044_GPT_PCLK, R9A07G044_CLK_P0, + 0x540, 0), + DEF_MOD("poeg_a_clkp", R9A07G044_POEG_A_CLKP, R9A07G044_CLK_P0, + 0x544, 0), + DEF_MOD("poeg_b_clkp", R9A07G044_POEG_B_CLKP, R9A07G044_CLK_P0, + 0x544, 1), + DEF_MOD("poeg_c_clkp", R9A07G044_POEG_C_CLKP, R9A07G044_CLK_P0, + 0x544, 2), + DEF_MOD("poeg_d_clkp", R9A07G044_POEG_D_CLKP, R9A07G044_CLK_P0, + 0x544, 3), + DEF_MOD("wdt0_pclk", R9A07G044_WDT0_PCLK, R9A07G044_CLK_P0, + 0x548, 0), + DEF_MOD("wdt0_clk", R9A07G044_WDT0_CLK, R9A07G044_OSCCLK, + 0x548, 1), + DEF_MOD("wdt1_pclk", R9A07G044_WDT1_PCLK, R9A07G044_CLK_P0, + 0x548, 2), + DEF_MOD("wdt1_clk", R9A07G044_WDT1_CLK, R9A07G044_OSCCLK, + 0x548, 3), + DEF_MOD("spi_clk2", R9A07G044_SPI_CLK2, R9A07G044_CLK_SPI1, + 0x550, 0), + DEF_MOD("spi_clk", R9A07G044_SPI_CLK, R9A07G044_CLK_SPI0, + 0x550, 1), + DEF_MOD("sdhi0_imclk", R9A07G044_SDHI0_IMCLK, CLK_SD0_DIV4, + 0x554, 0), + DEF_MOD("sdhi0_imclk2", R9A07G044_SDHI0_IMCLK2, CLK_SD0_DIV4, + 0x554, 1), + DEF_MOD("sdhi0_clk_hs", R9A07G044_SDHI0_CLK_HS, R9A07G044_CLK_SD0, + 0x554, 2), + DEF_MOD("sdhi0_aclk", R9A07G044_SDHI0_ACLK, R9A07G044_CLK_P1, + 0x554, 3), + DEF_MOD("sdhi1_imclk", R9A07G044_SDHI1_IMCLK, CLK_SD1_DIV4, + 0x554, 4), + DEF_MOD("sdhi1_imclk2", R9A07G044_SDHI1_IMCLK2, CLK_SD1_DIV4, + 0x554, 5), + DEF_MOD("sdhi1_clk_hs", R9A07G044_SDHI1_CLK_HS, R9A07G044_CLK_SD1, + 0x554, 6), + DEF_MOD("sdhi1_aclk", R9A07G044_SDHI1_ACLK, R9A07G044_CLK_P1, + 0x554, 7), + DEF_MOD("gpu_clk", R9A07G044_GPU_CLK, R9A07G044_CLK_G, + 0x558, 0), + DEF_MOD("gpu_axi_clk", R9A07G044_GPU_AXI_CLK, R9A07G044_CLK_P1, + 0x558, 1), + DEF_MOD("gpu_ace_clk", R9A07G044_GPU_ACE_CLK, R9A07G044_CLK_P1, + 0x558, 2), + DEF_MOD("cru_sysclk", R9A07G044_CRU_SYSCLK, CLK_M2_DIV2, + 0x564, 0), + DEF_MOD("cru_vclk", R9A07G044_CRU_VCLK, R9A07G044_CLK_M2, + 0x564, 1), + DEF_MOD("cru_pclk", R9A07G044_CRU_PCLK, R9A07G044_CLK_ZT, + 0x564, 2), + DEF_MOD("cru_aclk", R9A07G044_CRU_ACLK, R9A07G044_CLK_M0, + 0x564, 3), + DEF_MOD("dsi_pll_clk", R9A07G044_MIPI_DSI_PLLCLK, R9A07G044_CLK_M1, + 0x568, 0), + DEF_MOD("dsi_sys_clk", R9A07G044_MIPI_DSI_SYSCLK, CLK_M2_DIV2, + 0x568, 1), + DEF_MOD("dsi_aclk", R9A07G044_MIPI_DSI_ACLK, R9A07G044_CLK_P1, + 0x568, 2), + DEF_MOD("dsi_pclk", R9A07G044_MIPI_DSI_PCLK, R9A07G044_CLK_P2, + 0x568, 3), + DEF_MOD("dsi_vclk", R9A07G044_MIPI_DSI_VCLK, R9A07G044_CLK_M3, + 0x568, 4), + DEF_MOD("dsi_lpclk", R9A07G044_MIPI_DSI_LPCLK, R9A07G044_CLK_M4, + 0x568, 5), + DEF_COUPLED("lcdc_a", R9A07G044_LCDC_CLK_A, R9A07G044_CLK_M0, + 0x56c, 0), + DEF_COUPLED("lcdc_p", R9A07G044_LCDC_CLK_P, R9A07G044_CLK_ZT, + 0x56c, 0), + DEF_MOD("lcdc_clk_d", R9A07G044_LCDC_CLK_D, R9A07G044_CLK_M3, + 0x56c, 1), + DEF_MOD("ssi0_pclk", R9A07G044_SSI0_PCLK2, R9A07G044_CLK_P0, + 0x570, 0), + DEF_MOD("ssi0_sfr", R9A07G044_SSI0_PCLK_SFR, R9A07G044_CLK_P0, + 0x570, 1), + DEF_MOD("ssi1_pclk", R9A07G044_SSI1_PCLK2, R9A07G044_CLK_P0, + 0x570, 2), + DEF_MOD("ssi1_sfr", R9A07G044_SSI1_PCLK_SFR, R9A07G044_CLK_P0, + 0x570, 3), + DEF_MOD("ssi2_pclk", R9A07G044_SSI2_PCLK2, R9A07G044_CLK_P0, + 0x570, 4), + DEF_MOD("ssi2_sfr", R9A07G044_SSI2_PCLK_SFR, R9A07G044_CLK_P0, + 0x570, 5), + DEF_MOD("ssi3_pclk", R9A07G044_SSI3_PCLK2, R9A07G044_CLK_P0, + 0x570, 6), + DEF_MOD("ssi3_sfr", R9A07G044_SSI3_PCLK_SFR, R9A07G044_CLK_P0, + 0x570, 7), + DEF_MOD("usb0_host", R9A07G044_USB_U2H0_HCLK, R9A07G044_CLK_P1, + 0x578, 0), + DEF_MOD("usb1_host", R9A07G044_USB_U2H1_HCLK, R9A07G044_CLK_P1, + 0x578, 1), + DEF_MOD("usb0_func", R9A07G044_USB_U2P_EXR_CPUCLK, R9A07G044_CLK_P1, + 0x578, 2), + DEF_MOD("usb_pclk", R9A07G044_USB_PCLK, R9A07G044_CLK_P1, + 0x578, 3), + DEF_COUPLED("eth0_axi", R9A07G044_ETH0_CLK_AXI, R9A07G044_CLK_M0, + 0x57c, 0), + DEF_COUPLED("eth0_chi", R9A07G044_ETH0_CLK_CHI, R9A07G044_CLK_ZT, + 0x57c, 0), + DEF_COUPLED("eth1_axi", R9A07G044_ETH1_CLK_AXI, R9A07G044_CLK_M0, + 0x57c, 1), + DEF_COUPLED("eth1_chi", R9A07G044_ETH1_CLK_CHI, R9A07G044_CLK_ZT, + 0x57c, 1), + DEF_MOD("i2c0", R9A07G044_I2C0_PCLK, R9A07G044_CLK_P0, + 0x580, 0), + DEF_MOD("i2c1", R9A07G044_I2C1_PCLK, R9A07G044_CLK_P0, + 0x580, 1), + DEF_MOD("i2c2", R9A07G044_I2C2_PCLK, R9A07G044_CLK_P0, + 0x580, 2), + DEF_MOD("i2c3", R9A07G044_I2C3_PCLK, R9A07G044_CLK_P0, + 0x580, 3), + DEF_MOD("scif0", R9A07G044_SCIF0_CLK_PCK, R9A07G044_CLK_P0, + 0x584, 0), + DEF_MOD("scif1", R9A07G044_SCIF1_CLK_PCK, R9A07G044_CLK_P0, + 0x584, 1), + DEF_MOD("scif2", R9A07G044_SCIF2_CLK_PCK, R9A07G044_CLK_P0, + 0x584, 2), + DEF_MOD("scif3", R9A07G044_SCIF3_CLK_PCK, R9A07G044_CLK_P0, + 0x584, 3), + DEF_MOD("scif4", R9A07G044_SCIF4_CLK_PCK, R9A07G044_CLK_P0, + 0x584, 4), + DEF_MOD("sci0", R9A07G044_SCI0_CLKP, R9A07G044_CLK_P0, + 0x588, 0), + DEF_MOD("sci1", R9A07G044_SCI1_CLKP, R9A07G044_CLK_P0, + 0x588, 1), + DEF_MOD("rspi0", R9A07G044_RSPI0_CLKB, R9A07G044_CLK_P0, + 0x590, 0), + DEF_MOD("rspi1", R9A07G044_RSPI1_CLKB, R9A07G044_CLK_P0, + 0x590, 1), + DEF_MOD("rspi2", R9A07G044_RSPI2_CLKB, R9A07G044_CLK_P0, + 0x590, 2), + DEF_MOD("canfd", R9A07G044_CANFD_PCLK, R9A07G044_CLK_P0, + 0x594, 0), + DEF_MOD("gpio", R9A07G044_GPIO_HCLK, R9A07G044_OSCCLK, + 0x598, 0), + DEF_MOD("adc_adclk", R9A07G044_ADC_ADCLK, R9A07G044_CLK_TSU, + 0x5a8, 0), + DEF_MOD("adc_pclk", R9A07G044_ADC_PCLK, R9A07G044_CLK_P0, + 0x5a8, 1), + DEF_MOD("tsu_pclk", R9A07G044_TSU_PCLK, R9A07G044_CLK_TSU, + 0x5ac, 0), + }, +}; + +static const struct rzg2l_reset r9a07g044_resets[] = { + DEF_RST(R9A07G044_GIC600_GICRESET_N, 0x814, 0), + DEF_RST(R9A07G044_GIC600_DBG_GICRESET_N, 0x814, 1), + DEF_RST(R9A07G044_IA55_RESETN, 0x818, 0), + DEF_RST(R9A07G044_DMAC_ARESETN, 0x82c, 0), + DEF_RST(R9A07G044_DMAC_RST_ASYNC, 0x82c, 1), + DEF_RST(R9A07G044_OSTM0_PRESETZ, 0x834, 0), + DEF_RST(R9A07G044_OSTM1_PRESETZ, 0x834, 1), + DEF_RST(R9A07G044_OSTM2_PRESETZ, 0x834, 2), + DEF_RST(R9A07G044_MTU_X_PRESET_MTU3, 0x838, 0), + DEF_RST(R9A07G044_GPT_RST_C, 0x840, 0), + DEF_RST(R9A07G044_POEG_A_RST, 0x844, 0), + DEF_RST(R9A07G044_POEG_B_RST, 0x844, 1), + DEF_RST(R9A07G044_POEG_C_RST, 0x844, 2), + DEF_RST(R9A07G044_POEG_D_RST, 0x844, 3), + DEF_RST(R9A07G044_WDT0_PRESETN, 0x848, 0), + DEF_RST(R9A07G044_WDT1_PRESETN, 0x848, 1), + DEF_RST(R9A07G044_SPI_RST, 0x850, 0), + DEF_RST(R9A07G044_SDHI0_IXRST, 0x854, 0), + DEF_RST(R9A07G044_SDHI1_IXRST, 0x854, 1), + DEF_RST(R9A07G044_GPU_RESETN, 0x858, 0), + DEF_RST(R9A07G044_GPU_AXI_RESETN, 0x858, 1), + DEF_RST(R9A07G044_GPU_ACE_RESETN, 0x858, 2), + DEF_RST(R9A07G044_CRU_CMN_RSTB, 0x864, 0), + DEF_RST(R9A07G044_CRU_PRESETN, 0x864, 1), + DEF_RST(R9A07G044_CRU_ARESETN, 0x864, 2), + DEF_RST(R9A07G044_MIPI_DSI_CMN_RSTB, 0x868, 0), + DEF_RST(R9A07G044_MIPI_DSI_ARESET_N, 0x868, 1), + DEF_RST(R9A07G044_MIPI_DSI_PRESET_N, 0x868, 2), + DEF_RST(R9A07G044_LCDC_RESET_N, 0x86c, 0), + DEF_RST(R9A07G044_SSI0_RST_M2_REG, 0x870, 0), + DEF_RST(R9A07G044_SSI1_RST_M2_REG, 0x870, 1), + DEF_RST(R9A07G044_SSI2_RST_M2_REG, 0x870, 2), + DEF_RST(R9A07G044_SSI3_RST_M2_REG, 0x870, 3), + DEF_RST(R9A07G044_USB_U2H0_HRESETN, 0x878, 0), + DEF_RST(R9A07G044_USB_U2H1_HRESETN, 0x878, 1), + DEF_RST(R9A07G044_USB_U2P_EXL_SYSRST, 0x878, 2), + DEF_RST(R9A07G044_USB_PRESETN, 0x878, 3), + DEF_RST(R9A07G044_ETH0_RST_HW_N, 0x87c, 0), + DEF_RST(R9A07G044_ETH1_RST_HW_N, 0x87c, 1), + DEF_RST(R9A07G044_I2C0_MRST, 0x880, 0), + DEF_RST(R9A07G044_I2C1_MRST, 0x880, 1), + DEF_RST(R9A07G044_I2C2_MRST, 0x880, 2), + DEF_RST(R9A07G044_I2C3_MRST, 0x880, 3), + DEF_RST(R9A07G044_SCIF0_RST_SYSTEM_N, 0x884, 0), + DEF_RST(R9A07G044_SCIF1_RST_SYSTEM_N, 0x884, 1), + DEF_RST(R9A07G044_SCIF2_RST_SYSTEM_N, 0x884, 2), + DEF_RST(R9A07G044_SCIF3_RST_SYSTEM_N, 0x884, 3), + DEF_RST(R9A07G044_SCIF4_RST_SYSTEM_N, 0x884, 4), + DEF_RST(R9A07G044_SCI0_RST, 0x888, 0), + DEF_RST(R9A07G044_SCI1_RST, 0x888, 1), + DEF_RST(R9A07G044_RSPI0_RST, 0x890, 0), + DEF_RST(R9A07G044_RSPI1_RST, 0x890, 1), + DEF_RST(R9A07G044_RSPI2_RST, 0x890, 2), + DEF_RST(R9A07G044_CANFD_RSTP_N, 0x894, 0), + DEF_RST(R9A07G044_CANFD_RSTC_N, 0x894, 1), + DEF_RST(R9A07G044_GPIO_RSTN, 0x898, 0), + DEF_RST(R9A07G044_GPIO_PORT_RESETN, 0x898, 1), + DEF_RST(R9A07G044_GPIO_SPARE_RESETN, 0x898, 2), + DEF_RST(R9A07G044_ADC_PRESETN, 0x8a8, 0), + DEF_RST(R9A07G044_ADC_ADRST_N, 0x8a8, 1), + DEF_RST(R9A07G044_TSU_PRESETN, 0x8ac, 0), +}; + +const struct rzg2l_cpg_info r9a07g044_cpg_info = { + /* Core Clocks */ + .core_clks = core_clks.common, + .num_core_clks = ARRAY_SIZE(core_clks.common), + + /* Module Clocks */ + .mod_clks = mod_clks.common, + .num_mod_clks = ARRAY_SIZE(mod_clks.common), + .num_hw_mod_clks = R9A07G044_TSU_PCLK + 1, + + /* Resets */ + .resets = r9a07g044_resets, + .num_resets = R9A07G044_TSU_PRESETN + 1, /* Last reset ID + 1 */ + + .has_clk_mon_regs = true, +}; + +static const struct udevice_id r9a07g044_cpg_ids[] = { + { + .compatible = "renesas,r9a07g044-cpg", + .data = (unsigned long)&r9a07g044_cpg_info, + }, + { /* sentinel */ } +}; + +U_BOOT_DRIVER(r9a07g044_cpg) = { + .name = "r9a07g044-cpg", + .id = UCLASS_NOP, + .of_match = r9a07g044_cpg_ids, + .bind = rzg2l_cpg_bind, + .flags = DM_FLAG_PRE_RELOC, +}; diff --git a/drivers/clk/renesas/rzg2l-cpg.c b/drivers/clk/renesas/rzg2l-cpg.c new file mode 100644 index 000000000000..1e8ea109b5ca --- /dev/null +++ b/drivers/clk/renesas/rzg2l-cpg.c @@ -0,0 +1,502 @@ +// SPDX-License-Identifier: GPL-2.0 +/* + * RZ/G2L Clock Pulse Generator + * + * Copyright (C) 2021-2023 Renesas Electronics Corp. + * + * Based on renesas-cpg-mssr.c + * + * Copyright (C) 2015 Glider bvba + * Copyright (C) 2013 Ideas On Board SPRL + * Copyright (C) 2015 Renesas Electronics Corp. + */ + +#include <common.h> +#include <asm/io.h> +#include <clk-uclass.h> +#include <dm.h> +#include <dm/device-internal.h> +#include <dm/device_compat.h> +#include <dm/devres.h> +#include <dm/lists.h> +#include <dt-bindings/clock/renesas-cpg-mssr.h> +#include <linux/clk-provider.h> +#include <linux/iopoll.h> +#include <reset-uclass.h> +#include <reset.h> + +#include "rzg2l-cpg.h" + +#define CLK_MON_R(reg) (0x180 + (reg)) + +static ulong rzg2l_cpg_clk_get_rate_by_id(struct udevice *dev, unsigned int id); +static ulong rzg2l_cpg_clk_get_rate_by_name(struct udevice *dev, const char *name); + +struct rzg2l_cpg_data { + void __iomem *base; + struct rzg2l_cpg_info *info; +}; + +/* The top 16 bits of the clock ID are used to identify if it is a core clock or + * a module clock. + */ +#define CPG_CLK_TYPE_SHIFT 16 +#define CPG_CLK_ID_MASK 0xffff +#define CPG_CLK_ID(x) ((x) & CPG_CLK_ID_MASK) +#define CPG_CLK_PACK(type, id) (((type) << CPG_CLK_TYPE_SHIFT) | CPG_CLK_ID(id)) + +static inline bool is_mod_clk(unsigned int id) +{ + return (id >> CPG_CLK_TYPE_SHIFT) == CPG_MOD; +} + +static int rzg2l_cpg_clk_set(struct clk *clk, bool enable) +{ + struct rzg2l_cpg_data *data = + (struct rzg2l_cpg_data *)dev_get_driver_data(clk->dev); + unsigned int cpg_clk_id = CPG_CLK_ID(clk->id); + const struct rzg2l_mod_clk *mod_clk = NULL; + u32 value; + unsigned int i; + + dev_dbg(clk->dev, "%s %s clock %u\n", enable ? "enable" : "disable", + is_mod_clk(clk->id) ? "module" : "core", cpg_clk_id); + if (!is_mod_clk(clk->id)) { + dev_err(clk->dev, "ID %lu is not a module clock\n", clk->id); + return -EINVAL; + } + + for (i = 0; i < data->info->num_mod_clks; i++) { + if (data->info->mod_clks[i].id == cpg_clk_id) { + mod_clk = &data->info->mod_clks[i]; + break; + } + } + + if (!mod_clk) { + dev_err(clk->dev, "Module clock %u not found\n", cpg_clk_id); + return -ENODEV; + } + + value = (BIT(mod_clk->bit) << 16); + if (enable) + value |= BIT(mod_clk->bit); + writel(value, data->base + mod_clk->off); + + if (enable && readl_poll_timeout(data->base + CLK_MON_R(mod_clk->off), + value, (value & BIT(mod_clk->bit)), + 10)) { + dev_err(clk->dev, "Timeout\n"); + return -ETIMEDOUT; + } + + return 0; +} + +static int rzg2l_cpg_clk_enable(struct clk *clk) +{ + return rzg2l_cpg_clk_set(clk, true); +} + +static int rzg2l_cpg_clk_disable(struct clk *clk) +{ + return rzg2l_cpg_clk_set(clk, false); +} + +static int rzg2l_cpg_clk_of_xlate(struct clk *clk, + struct ofnode_phandle_args *args) +{ + struct rzg2l_cpg_data *data = + (struct rzg2l_cpg_data *)dev_get_driver_data(clk->dev); + u32 cpg_clk_type, cpg_clk_id; + bool found = false; + unsigned int i; + + if (args->args_count != 2) { + dev_dbg(clk->dev, "Invalid args_count: %d\n", args->args_count); + return -EINVAL; + } + + cpg_clk_type = args->args[0]; + cpg_clk_id = args->args[1]; + + switch (cpg_clk_type) { + case CPG_CORE: + for (i = 0; i < data->info->num_core_clks; i++) { + if (data->info->core_clks[i].id == cpg_clk_id) { + found = true; + break; + } + } + if (!found) { + dev_dbg(clk->dev, + "Invalid second argument %u: Must be a valid core clock ID\n", + cpg_clk_id); + return -EINVAL; + } + break; + case CPG_MOD: + for (i = 0; i < data->info->num_mod_clks; i++) { + if (data->info->mod_clks[i].id == cpg_clk_id) { + found = true; + break; + } + } + if (!found) { + dev_dbg(clk->dev, + "Invalid second argument %u: Must be a valid module clock ID\n", + cpg_clk_id); + return -EINVAL; + } + break; + default: + dev_dbg(clk->dev, + "Invalid first argument %u: Must be CPG_CORE or CPG_MOD\n", + cpg_clk_type); + return -EINVAL; + } + + clk->id = CPG_CLK_PACK(cpg_clk_type, cpg_clk_id); + + return 0; +} + +static ulong rzg2l_sdhi_clk_get_rate(struct udevice *dev, const struct cpg_core_clk *cc) +{ + struct rzg2l_cpg_data *data = + (struct rzg2l_cpg_data *)dev_get_driver_data(dev); + ulong offset = CPG_CONF_OFFSET(cc->conf); + int shift = CPG_CONF_BITPOS(cc->conf); + u32 mask = CPG_CONF_BITMASK(cc->conf); + unsigned int sel; + + sel = (readl(data->base + offset) >> shift) & mask; + + if (!sel || sel > cc->num_parents) { + dev_err(dev, "Invalid SEL_SDHI%d_SET value %u\n", shift / 4, sel); + return -EIO; + } + return rzg2l_cpg_clk_get_rate_by_name(dev, cc->parent_names[sel - 1]); +} + +static ulong rzg2l_div_clk_get_rate(struct udevice *dev, const struct cpg_core_clk *cc) +{ + struct rzg2l_cpg_data *data = + (struct rzg2l_cpg_data *)dev_get_driver_data(dev); + ulong offset = CPG_CONF_OFFSET(cc->conf); + int shift = CPG_CONF_BITPOS(cc->conf); + u32 mask = CPG_CONF_BITMASK(cc->conf); + unsigned int sel, i; + + sel = (readl(data->base + offset) >> shift) & mask; + + for (i = 0; cc->dtable[i].div; i++) { + if (cc->dtable[i].val == sel) + return rzg2l_cpg_clk_get_rate_by_id(dev, cc->parent) / cc->dtable[i].div; + } + dev_err(dev, "Invalid selector value %u for clock %s\n", sel, cc->name); + return -EINVAL; +} + +static ulong rzg2l_core_clk_get_rate(struct udevice *dev, const struct cpg_core_clk *cc) +{ + switch (cc->type) { + case CLK_TYPE_FF: + ulong parent_rate = rzg2l_cpg_clk_get_rate_by_id(dev, cc->parent); + return parent_rate * cc->mult / cc->div; + case CLK_TYPE_IN: + struct clk clk_in; + clk_get_by_name(dev, cc->name, &clk_in); + return clk_get_rate(&clk_in); + case CLK_TYPE_SD_MUX: + return rzg2l_sdhi_clk_get_rate(dev, cc); + case CLK_TYPE_DIV: + return rzg2l_div_clk_get_rate(dev, cc); + default: + dev_err(dev, "get_rate needed for clock %u, type %d\n", cc->id, cc->type); + return -ENOSYS; + } +} + +static ulong rzg2l_cpg_clk_get_rate_by_id(struct udevice *dev, unsigned int id) +{ + struct rzg2l_cpg_data *data = + (struct rzg2l_cpg_data *)dev_get_driver_data(dev); + unsigned int cpg_clk_id = CPG_CLK_ID(id); + unsigned int i; + + if (is_mod_clk(id)) { + for (i = 0; i < data->info->num_mod_clks; i++) { + if (data->info->mod_clks[i].id == cpg_clk_id) + return rzg2l_cpg_clk_get_rate_by_id(dev, + data->info->mod_clks[i].parent); + } + + dev_err(dev, "Module clock ID %u not found\n", cpg_clk_id); + return -ENODEV; + } + + for (i = 0; i < data->info->num_core_clks; i++) { + if (data->info->core_clks[i].id == cpg_clk_id) + return rzg2l_core_clk_get_rate(dev, &data->info->core_clks[i]); + } + + dev_err(dev, "Core clock ID %u not found\n", cpg_clk_id); + return -ENODEV; +} + +static ulong rzg2l_cpg_clk_get_rate_by_name(struct udevice *dev, const char *name) +{ + struct rzg2l_cpg_data *data = + (struct rzg2l_cpg_data *)dev_get_driver_data(dev); + unsigned int i; + + for (i = 0; i < data->info->num_mod_clks; i++) { + if (!strcmp(name, data->info->mod_clks[i].name)) + return rzg2l_cpg_clk_get_rate_by_id(dev, data->info->mod_clks[i].parent); + } + for (i = 0; i < data->info->num_core_clks; i++) { + if (!strcmp(name, data->info->core_clks[i].name)) + return rzg2l_core_clk_get_rate(dev, &data->info->core_clks[i]); + } + + dev_err(dev, "Clock name %s not found\n", name); + return -EINVAL; +} + +static ulong rzg2l_cpg_clk_get_rate(struct clk *clk) +{ + return rzg2l_cpg_clk_get_rate_by_id(clk->dev, clk->id); +} + +static ulong rzg2l_sdhi_clk_set_rate(struct udevice *dev, const struct cpg_core_clk *cc, ulong rate) +{ + struct rzg2l_cpg_data *data = + (struct rzg2l_cpg_data *)dev_get_driver_data(dev); + ulong offset = CPG_CONF_OFFSET(cc->conf); + int shift = CPG_CONF_BITPOS(cc->conf); + int channel, new_sel, prev_sel; + ulong target_rate; + unsigned int i; + u32 value; + + prev_sel = (readl(data->base + offset) >> shift) & 0x3; + channel = shift / 4; + + /* Round the requested rate down, unless it is below the minimum + * supported rate. Assume that the parent clock names are listed in + * order of descending rate. + */ + for (i = 0; i < cc->num_parents; i++) { + target_rate = rzg2l_cpg_clk_get_rate_by_name(dev, cc->parent_names[i]); + if (rate >= target_rate) { + new_sel = i + 1; + break; + } + } + if (!new_sel) + new_sel = cc->num_parents - 1; + + if (new_sel == prev_sel) + return target_rate; + dev_dbg(dev, "sdhi set_rate rate=%lu target_rate=%lu sel=%d\n", + rate, target_rate, new_sel); + + /* + * As per the HW manual, we should not directly switch from 533 MHz to + * 400 MHz and vice versa. To change the setting from 2’b01 (533 MHz) + * to 2’b10 (400 MHz) or vice versa, Switch to 2’b11 (266 MHz) first, + * and then switch to the target setting (2’b01 (533 MHz) or 2’b10 + * (400 MHz)). + */ + if (new_sel != SEL_SDHI_266MHz && prev_sel != SEL_SDHI_266MHz) { + u32 waitbit; + int ret; + + dev_dbg(dev, "sdhi set_rate via 266MHz\n"); + value = (SEL_SDHI_WRITE_ENABLE | SEL_SDHI_266MHz) << shift; + writel(value, data->base + offset); + + /* Wait for the switch to complete. */ + waitbit = channel ? CPG_CLKSTATUS_SELSDHI1_STS : CPG_CLKSTATUS_SELSDHI0_STS; + ret = readl_poll_timeout(data->base + CPG_CLKSTATUS, value, + !(value & waitbit), + CPG_SDHI_CLK_SWITCH_STATUS_TIMEOUT_US); + if (ret) { + dev_err(dev, "Failed to switch SDHI%d clock source\n", channel); + return -EIO; + } + } + + value = (SEL_SDHI_WRITE_ENABLE | new_sel) << shift; + writel(value, data->base + offset); + + return target_rate; +} + +static ulong rzg2l_core_clk_set_rate(struct udevice *dev, const struct cpg_core_clk *cc, ulong rate) +{ + if (cc->type == CLK_TYPE_SD_MUX) + return rzg2l_sdhi_clk_set_rate(dev, cc, rate); + + /* The sdhi driver calls clk_set_rate for SD0_DIV4 and SD1_DIV4, even + * though they're in a fixed relationship with SD0 and SD1 respectively. + * To allow the driver to proceed, simply return the current rates + * without making any change. + */ + if (cc->id == CLK_SD0_DIV4 || cc->id == CLK_SD1_DIV4) + return rzg2l_core_clk_get_rate(dev, cc); + + dev_err(dev, "set_rate needed for clock %u, type %d\n", cc->id, cc->type); + return -ENOSYS; +} + +static ulong rzg2l_cpg_clk_set_rate_by_id(struct udevice *dev, unsigned int id, ulong rate) +{ + struct rzg2l_cpg_data *data = + (struct rzg2l_cpg_data *)dev_get_driver_data(dev); + unsigned int cpg_clk_id = CPG_CLK_ID(id); + unsigned int i; + + if (is_mod_clk(id)) { + for (i = 0; i < data->info->num_mod_clks; i++) { + if (data->info->mod_clks[i].id == cpg_clk_id) + return rzg2l_cpg_clk_set_rate_by_id(dev, + data->info->mod_clks[i].parent, + rate); + } + + dev_err(dev, "Module clock ID %u not found\n", cpg_clk_id); + return -ENODEV; + } + + for (i = 0; i < data->info->num_core_clks; i++) { + if (data->info->core_clks[i].id == cpg_clk_id) + return rzg2l_core_clk_set_rate(dev, &data->info->core_clks[i], rate); + } + + dev_err(dev, "Core clock ID %u not found\n", cpg_clk_id); + return -ENODEV; +} + +static ulong rzg2l_cpg_clk_set_rate(struct clk *clk, ulong rate) +{ + return rzg2l_cpg_clk_set_rate_by_id(clk->dev, clk->id, rate); +} + +static const struct clk_ops rzg2l_cpg_clk_ops = { + .enable = rzg2l_cpg_clk_enable, + .disable = rzg2l_cpg_clk_disable, + .of_xlate = rzg2l_cpg_clk_of_xlate, + .get_rate = rzg2l_cpg_clk_get_rate, + .set_rate = rzg2l_cpg_clk_set_rate, +}; + +U_BOOT_DRIVER(rzg2l_cpg_clk) = { + .name = "rzg2l-cpg-clk", + .id = UCLASS_CLK, + .ops = &rzg2l_cpg_clk_ops, + .flags = DM_FLAG_VITAL, +}; + +static int rzg2l_cpg_rst_set(struct reset_ctl *reset_ctl, bool asserted) +{ + struct rzg2l_cpg_data *data = + (struct rzg2l_cpg_data *)dev_get_driver_data(reset_ctl->dev); + const struct rzg2l_reset *rst; + u32 value; + + dev_dbg(reset_ctl->dev, "%s %lu\n", asserted ? "assert" : "deassert", reset_ctl->id); + if (reset_ctl->id >= data->info->num_resets) { + dev_err(reset_ctl->dev, "Invalid reset id %lu\n", reset_ctl->id); + return -EINVAL; + } + rst = &data->info->resets[reset_ctl->id]; + + value = BIT(rst->bit) << 16; + if (!asserted) + value |= BIT(rst->bit); + writel(value, data->base + rst->off); + + return 0; +} + +static int rzg2l_cpg_rst_assert(struct reset_ctl *reset_ctl) +{ + return rzg2l_cpg_rst_set(reset_ctl, true); +} + +static int rzg2l_cpg_rst_deassert(struct reset_ctl *reset_ctl) +{ + return rzg2l_cpg_rst_set(reset_ctl, false); +} + +static int rzg2l_cpg_rst_of_xlate(struct reset_ctl *reset_ctl, + struct ofnode_phandle_args *args) +{ + struct rzg2l_cpg_data *data = + (struct rzg2l_cpg_data *)dev_get_driver_data(reset_ctl->dev); + + if (args->args[0] >= data->info->num_resets) + return -EINVAL; + + reset_ctl->id = args->args[0]; + return 0; +} + +static const struct reset_ops rzg2l_cpg_rst_ops = { + .rst_assert = rzg2l_cpg_rst_assert, + .rst_deassert = rzg2l_cpg_rst_deassert, + .of_xlate = rzg2l_cpg_rst_of_xlate, +}; + +U_BOOT_DRIVER(rzg2l_cpg_rst) = { + .name = "rzg2l-cpg-rst", + .id = UCLASS_RESET, + .ops = &rzg2l_cpg_rst_ops, + .flags = DM_FLAG_VITAL, +}; + +int rzg2l_cpg_bind(struct udevice *parent) +{ + struct udevice *cdev, *rdev; + struct rzg2l_cpg_data *data; + struct driver *drv; + int ret; + + data = devm_kmalloc(parent, sizeof(*data), 0); + if (!data) + return -ENOMEM; + + data->base = dev_read_addr_ptr(parent); + if (!data->base) + return -EINVAL; + + data->info = (struct rzg2l_cpg_info *)dev_get_driver_data(parent); + if (!data->info) + return -EINVAL; + + drv = lists_driver_lookup_name("rzg2l-cpg-clk"); + if (!drv) + return -ENOENT; + + ret = device_bind_with_driver_data(parent, drv, parent->name, + (ulong)data, dev_ofnode(parent), + &cdev); + if (ret) + return ret; + + drv = lists_driver_lookup_name("rzg2l-cpg-rst"); + if (!drv) { + device_unbind(cdev); + return -ENOENT; + } + + ret = device_bind_with_driver_data(parent, drv, parent->name, + (ulong)data, dev_ofnode(parent), + &rdev); + if (ret) + device_unbind(cdev); + + return ret; +} diff --git a/drivers/clk/renesas/rzg2l-cpg.h b/drivers/clk/renesas/rzg2l-cpg.h new file mode 100644 index 000000000000..f7a9a2156319 --- /dev/null +++ b/drivers/clk/renesas/rzg2l-cpg.h @@ -0,0 +1,318 @@ +/* SPDX-License-Identifier: GPL-2.0 */ +/* + * RZ/G2L Clock Pulse Generator + * + * Copyright (C) 2021-2023 Renesas Electronics Corp. + * + */ + +#ifndef __RENESAS_RZG2L_CPG_H__ +#define __RENESAS_RZG2L_CPG_H__ + +#define CPG_SIPLL5_STBY (0x140) +#define CPG_SIPLL5_CLK1 (0x144) +#define CPG_SIPLL5_CLK3 (0x14C) +#define CPG_SIPLL5_CLK4 (0x150) +#define CPG_SIPLL5_CLK5 (0x154) +#define CPG_SIPLL5_MON (0x15C) +#define CPG_PL1_DDIV (0x200) +#define CPG_PL2_DDIV (0x204) +#define CPG_PL3A_DDIV (0x208) +#define CPG_PL6_DDIV (0x210) +#define CPG_PL2SDHI_DSEL (0x218) +#define CPG_CLKSTATUS (0x280) +#define CPG_PL3_SSEL (0x408) +#define CPG_PL6_SSEL (0x414) +#define CPG_PL6_ETH_SSEL (0x418) +#define CPG_PL5_SDIV (0x420) +#define CPG_RST_MON (0x680) +#define CPG_OTHERFUNC1_REG (0xBE8) + +#define CPG_SIPLL5_STBY_RESETB BIT(0) +#define CPG_SIPLL5_STBY_RESETB_WEN BIT(16) +#define CPG_SIPLL5_STBY_SSCG_EN_WEN BIT(18) +#define CPG_SIPLL5_STBY_DOWNSPREAD_WEN BIT(20) +#define CPG_SIPLL5_CLK4_RESV_LSB (0xFF) +#define CPG_SIPLL5_MON_PLL5_LOCK BIT(4) + +#define CPG_OTHERFUNC1_REG_RES0_ON_WEN BIT(16) + +#define CPG_PL5_SDIV_DIV_DSI_A_WEN BIT(16) +#define CPG_PL5_SDIV_DIV_DSI_B_WEN BIT(24) + +#define CPG_CLKSTATUS_SELSDHI0_STS BIT(28) +#define CPG_CLKSTATUS_SELSDHI1_STS BIT(29) + +#define CPG_SDHI_CLK_SWITCH_STATUS_TIMEOUT_US 20000 + +/* n = 0/1/2 for PLL1/4/6 */ +#define CPG_SAMPLL_CLK1(n) (0x04 + (16 * n)) +#define CPG_SAMPLL_CLK2(n) (0x08 + (16 * n)) + +#define PLL146_CONF(n) (CPG_SAMPLL_CLK1(n) << 22 | CPG_SAMPLL_CLK2(n) << 12) + +#define DDIV_PACK(offset, bitpos, size) \ + (((offset) << 20) | ((bitpos) << 12) | ((size) << 8)) +#define DIVPL1A DDIV_PACK(CPG_PL1_DDIV, 0, 2) +#define DIVPL2A DDIV_PACK(CPG_PL2_DDIV, 0, 3) +#define DIVDSILPCLK DDIV_PACK(CPG_PL2_DDIV, 12, 2) +#define DIVPL3A DDIV_PACK(CPG_PL3A_DDIV, 0, 3) +#define DIVPL3B DDIV_PACK(CPG_PL3A_DDIV, 4, 3) +#define DIVPL3C DDIV_PACK(CPG_PL3A_DDIV, 8, 3) +#define DIVGPU DDIV_PACK(CPG_PL6_DDIV, 0, 2) + +#define SEL_PLL_PACK(offset, bitpos, size) \ + (((offset) << 20) | ((bitpos) << 12) | ((size) << 8)) + +#define SEL_PLL3_3 SEL_PLL_PACK(CPG_PL3_SSEL, 8, 1) +#define SEL_PLL5_4 SEL_PLL_PACK(CPG_OTHERFUNC1_REG, 0, 1) +#define SEL_PLL6_2 SEL_PLL_PACK(CPG_PL6_ETH_SSEL, 0, 1) +#define SEL_GPU2 SEL_PLL_PACK(CPG_PL6_SSEL, 12, 1) + +#define SEL_SDHI0 DDIV_PACK(CPG_PL2SDHI_DSEL, 0, 2) +#define SEL_SDHI1 DDIV_PACK(CPG_PL2SDHI_DSEL, 4, 2) + +#define SEL_SDHI_533MHz 1 +#define SEL_SDHI_400MHz 2 +#define SEL_SDHI_266MHz 3 +#define SEL_SDHI_WRITE_ENABLE 0x10000 + +/* Unpack CPG conf value create by DDIV_PACK() or SEL_PLL_PACK(). */ +#define CPG_CONF_OFFSET(x) ((x) >> 20) +#define CPG_CONF_BITPOS(x) (((x) >> 12) & 0xff) +#define CPG_CONF_SIZE(x) (((x) >> 8) & 0xf) +#define CPG_CONF_BITMASK(x) GENMASK(CPG_CONF_SIZE(x) - 1, 0) + +#define EXTAL_FREQ_IN_MEGA_HZ (24) + +/** + * Definitions of CPG Core Clocks + * + * These include: + * - Clock outputs exported to DT + * - External input clocks + * - Internal CPG clocks + */ +struct cpg_core_clk { + const char *name; + unsigned int id; + unsigned int parent; + unsigned int div; + unsigned int mult; + unsigned int type; + unsigned int conf; + const struct clk_div_table *dtable; + const char * const *parent_names; + int flag; + int mux_flags; + int num_parents; +}; + +enum clk_types { + /* Generic */ + CLK_TYPE_IN, /* External Clock Input */ + CLK_TYPE_FF, /* Fixed Factor Clock */ + CLK_TYPE_SAM_PLL, + + /* Clock with divider */ + CLK_TYPE_DIV, + + /* Clock with clock source selector */ + CLK_TYPE_MUX, + + /* Clock with SD clock source selector */ + CLK_TYPE_SD_MUX, + + /* Clock for SIPLL5 */ + CLK_TYPE_SIPLL5, + + /* Clock for PLL5_4 clock source selector */ + CLK_TYPE_PLL5_4_MUX, + + /* Clock for DSI divider */ + CLK_TYPE_DSI_DIV, + +}; + +#define DEF_TYPE(_name, _id, _type...) \ + { .name = _name, .id = _id, .type = _type } +#define DEF_BASE(_name, _id, _type, _parent...) \ + DEF_TYPE(_name, _id, _type, .parent = _parent) +#define DEF_SAMPLL(_name, _id, _parent, _conf) \ + DEF_TYPE(_name, _id, CLK_TYPE_SAM_PLL, .parent = _parent, .conf = _conf) +#define DEF_INPUT(_name, _id) \ + DEF_TYPE(_name, _id, CLK_TYPE_IN) +#define DEF_FIXED(_name, _id, _parent, _mult, _div) \ + DEF_BASE(_name, _id, CLK_TYPE_FF, _parent, .div = _div, .mult = _mult) +#define DEF_DIV(_name, _id, _parent, _conf, _dtable) \ + DEF_TYPE(_name, _id, CLK_TYPE_DIV, .conf = _conf, \ + .parent = _parent, .dtable = _dtable, \ + .flag = CLK_DIVIDER_HIWORD_MASK) +#define DEF_DIV_RO(_name, _id, _parent, _conf, _dtable) \ + DEF_TYPE(_name, _id, CLK_TYPE_DIV, .conf = _conf, \ + .parent = _parent, .dtable = _dtable, \ + .flag = CLK_DIVIDER_READ_ONLY) +#define DEF_MUX(_name, _id, _conf, _parent_names) \ + DEF_TYPE(_name, _id, CLK_TYPE_MUX, .conf = _conf, \ + .parent_names = _parent_names, \ + .num_parents = ARRAY_SIZE(_parent_names), \ + .mux_flags = CLK_MUX_HIWORD_MASK) +#define DEF_MUX_RO(_name, _id, _conf, _parent_names) \ + DEF_TYPE(_name, _id, CLK_TYPE_MUX, .conf = _conf, \ + .parent_names = _parent_names, \ + .num_parents = ARRAY_SIZE(_parent_names), \ + .mux_flags = CLK_MUX_READ_ONLY) +#define DEF_SD_MUX(_name, _id, _conf, _parent_names) \ + DEF_TYPE(_name, _id, CLK_TYPE_SD_MUX, .conf = _conf, \ + .parent_names = _parent_names, \ + .num_parents = ARRAY_SIZE(_parent_names)) +#define DEF_PLL5_FOUTPOSTDIV(_name, _id, _parent) \ + DEF_TYPE(_name, _id, CLK_TYPE_SIPLL5, .parent = _parent) +#define DEF_PLL5_4_MUX(_name, _id, _conf, _parent_names) \ + DEF_TYPE(_name, _id, CLK_TYPE_PLL5_4_MUX, .conf = _conf, \ + .parent_names = _parent_names, \ + .num_parents = ARRAY_SIZE(_parent_names)) +#define DEF_DSI_DIV(_name, _id, _parent, _flag) \ + DEF_TYPE(_name, _id, CLK_TYPE_DSI_DIV, .parent = _parent, .flag = _flag) + +/** + * struct rzg2l_mod_clk - Module Clocks definitions + * + * @name: handle between common and hardware-specific interfaces + * @id: clock index in array containing all Core and Module Clocks + * @parent: id of parent clock + * @off: register offset + * @bit: ON/MON bit + * @is_coupled: flag to indicate coupled clock + */ +struct rzg2l_mod_clk { + const char *name; + unsigned int id; + unsigned int parent; + u16 off; + u8 bit; + bool is_coupled; +}; + +#define DEF_MOD_BASE(_name, _id, _parent, _off, _bit, _is_coupled) \ + { \ + .name = (_name), \ + .id = (_id), \ + .parent = (_parent), \ + .off = (_off), \ + .bit = (_bit), \ + .is_coupled = (_is_coupled), \ + } + +#define DEF_MOD(_name, _id, _parent, _off, _bit) \ + DEF_MOD_BASE(_name, _id, _parent, _off, _bit, false) + +#define DEF_COUPLED(_name, _id, _parent, _off, _bit) \ + DEF_MOD_BASE(_name, _id, _parent, _off, _bit, true) + +/** + * struct rzg2l_reset - Reset definitions + * + * @off: register offset + * @bit: reset bit + * @monbit: monitor bit in CPG_RST_MON register, -1 if none + */ +struct rzg2l_reset { + u16 off; + u8 bit; + s8 monbit; +}; + +#define DEF_RST_MON(_id, _off, _bit, _monbit) \ + [_id] = { \ + .off = (_off), \ + .bit = (_bit), \ + .monbit = (_monbit) \ + } +#define DEF_RST(_id, _off, _bit) \ + DEF_RST_MON(_id, _off, _bit, -1) + +/** + * struct rzg2l_cpg_info - SoC-specific CPG Description + * + * @core_clks: Array of Core Clock definitions + * @num_core_clks: Number of entries in core_clks[] + * + * @mod_clks: Array of Module Clock definitions + * @num_mod_clks: Number of entries in mod_clks[] + * @num_hw_mod_clks: Number of Module Clocks supported by the hardware + * + * @resets: Array of Module Reset definitions + * @num_resets: Number of entries in resets[] + * + * @has_clk_mon_regs: Flag indicating whether the SoC has CLK_MON registers + */ +struct rzg2l_cpg_info { + /* Core Clocks */ + const struct cpg_core_clk *core_clks; + unsigned int num_core_clks; + + /* Module Clocks */ + const struct rzg2l_mod_clk *mod_clks; + unsigned int num_mod_clks; + unsigned int num_hw_mod_clks; + + /* Resets */ + const struct rzg2l_reset *resets; + unsigned int num_resets; + + bool has_clk_mon_regs; +}; + +extern const struct rzg2l_cpg_info r9a07g044_cpg_info; + +int rzg2l_cpg_bind(struct udevice *parent); + +/* Clock IDs start at an offset to avoid overlapping with core & module clock + * IDs defined in the dt-bindings headers. + */ +enum clk_ids { + /* External Input Clocks */ + CLK_EXTAL = 0x100, + + /* Internal Core Clocks */ + CLK_OSC_DIV1000 = 0x200, + CLK_PLL1, + CLK_PLL2, + CLK_PLL2_DIV2, + CLK_PLL2_DIV2_8, + CLK_PLL2_DIV2_10, + CLK_PLL3, + CLK_PLL3_400, + CLK_PLL3_533, + CLK_M2_DIV2, + CLK_PLL3_DIV2, + CLK_PLL3_DIV2_2, + CLK_PLL3_DIV2_4, + CLK_PLL3_DIV2_4_2, + CLK_SEL_PLL3_3, + CLK_DIV_PLL3_C, + CLK_PLL4, + CLK_PLL5, + CLK_PLL5_FOUTPOSTDIV, + CLK_PLL5_FOUT1PH0, + CLK_PLL5_FOUT3, + CLK_PLL5_250, + CLK_PLL6, + CLK_PLL6_250, + CLK_P1_DIV2, + CLK_PLL2_800, + CLK_PLL2_SDHI_533, + CLK_PLL2_SDHI_400, + CLK_PLL2_SDHI_266, + CLK_SD0_DIV4, + CLK_SD1_DIV4, + CLK_SEL_GPU2, + CLK_SEL_PLL5_4, + CLK_DSI_DIV, + CLK_PLL2_533, + CLK_PLL2_533_DIV2, + CLK_DIV_DSI_LPCLK, +}; + +#endif

On 9/20/23 14:42, Paul Barker wrote:
This driver provides clock and reset control for the Renesas RZ/G2L (R9A07G044) SoC. It consists of two parts:
driver code which is applicable to all SoCs in the RZ/G2L family
static data describing the clocks and resets which are specific to the R9A07G044 SoC.
clk_set_rate() and clk_get_rate() are implemented only for the clocks that are actually used in u-boot.
The CPG driver is marked with DM_FLAG_PRE_RELOC to ensure that its bind function is called before the SCIF (serial port) driver is probed. This is required so that we can de-assert the relevant reset signal during the serial driver probe function.
This patch is based on the corresponding Linux v6.5 driver.
Same thing as 02/16..04/16 applies here.
Signed-off-by: Paul Barker paul.barker.ct@bp.renesas.com Reviewed-by: Biju Das biju.das.jz@bp.renesas.com Reviewed-by: Lad Prabhakar prabhakar.mahadev-lad.rj@bp.renesas.com
arch/arm/mach-rmobile/Kconfig | 1 + arch/arm/mach-rmobile/Kconfig.rzg2l | 1 + drivers/clk/renesas/Kconfig | 9 + drivers/clk/renesas/Makefile | 2 + drivers/clk/renesas/r9a07g044-cpg.c | 384 +++++++++++++++++++++ drivers/clk/renesas/rzg2l-cpg.c | 502 ++++++++++++++++++++++++++++ drivers/clk/renesas/rzg2l-cpg.h | 318 ++++++++++++++++++ 7 files changed, 1217 insertions(+) create mode 100644 drivers/clk/renesas/r9a07g044-cpg.c create mode 100644 drivers/clk/renesas/rzg2l-cpg.c create mode 100644 drivers/clk/renesas/rzg2l-cpg.h
diff --git a/arch/arm/mach-rmobile/Kconfig b/arch/arm/mach-rmobile/Kconfig index fd240832d83d..fc37f6c79e50 100644 --- a/arch/arm/mach-rmobile/Kconfig +++ b/arch/arm/mach-rmobile/Kconfig @@ -74,6 +74,7 @@ config RZG2L imply MULTI_DTB_FIT_USER_DEFINED_AREA imply SYS_MALLOC_F imply RENESAS_SDHI
- imply CLK_RZG2L
Keep the list sorted
help Enable support for the Renesas RZ/G2L family of SoCs, including the the RZ/G2L itself (based on the R9A07G044 SoC). diff --git a/arch/arm/mach-rmobile/Kconfig.rzg2l b/arch/arm/mach-rmobile/Kconfig.rzg2l index 266f82c18085..7d268e8c366a 100644 --- a/arch/arm/mach-rmobile/Kconfig.rzg2l +++ b/arch/arm/mach-rmobile/Kconfig.rzg2l @@ -5,6 +5,7 @@ if RZG2L
config R9A07G044L bool "Renesas R9A07G044L SoC"
- imply CLK_R9A07G044
Why not CLK_R9A07G044L (with L at the end) ?
help Enable support for the R9A07G044L SoC used in the RZ/G2L.
diff --git a/drivers/clk/renesas/Kconfig b/drivers/clk/renesas/Kconfig index 437a82cd48be..927d62cf99a3 100644 --- a/drivers/clk/renesas/Kconfig +++ b/drivers/clk/renesas/Kconfig @@ -156,3 +156,12 @@ config CLK_R9A06G032 depends on CLK_RENESAS help Enable this to support the clocks on Renesas R9A06G032 SoC.
+config CLK_RZG2L
- bool "Renesas RZ/G2L family clock support"
- depends on CLK_RENESAS
- select DM_RESET
+config CLK_R9A07G044
- bool "RZ/G2L (R9A07G044L) clock support"
- depends on CLK_RZG2L
diff --git a/drivers/clk/renesas/Makefile b/drivers/clk/renesas/Makefile index 48373e61b901..df7e225e9ca4 100644 --- a/drivers/clk/renesas/Makefile +++ b/drivers/clk/renesas/Makefile @@ -23,3 +23,5 @@ obj-$(CONFIG_CLK_R8A779A0) += r8a779a0-cpg-mssr.o obj-$(CONFIG_CLK_R8A779F0) += r8a779f0-cpg-mssr.o obj-$(CONFIG_CLK_R8A779G0) += r8a779g0-cpg-mssr.o obj-$(CONFIG_CLK_R9A06G032) += r9a06g032-clocks.o +obj-$(CONFIG_CLK_RZG2L) += rzg2l-cpg.o +obj-$(CONFIG_CLK_R9A07G044) += r9a07g044-cpg.o diff --git a/drivers/clk/renesas/r9a07g044-cpg.c b/drivers/clk/renesas/r9a07g044-cpg.c new file mode 100644 index 000000000000..e215db7caf15 --- /dev/null +++ b/drivers/clk/renesas/r9a07g044-cpg.c @@ -0,0 +1,384 @@ +// SPDX-License-Identifier: GPL-2.0 +/*
- RZ/G2L CPG driver
- Copyright (C) 2021-2023 Renesas Electronics Corp.
- */
+#include <common.h> +#include <dm/device.h> +#include <dt-bindings/clock/r9a07g044-cpg.h> +#include <linux/clk-provider.h>
+#include "rzg2l-cpg.h"
+/* Divider tables */ +static const struct clk_div_table dtable_1_8[] = {
- {0, 1},
- {1, 2},
- {2, 4},
- {3, 8},
- {0, 0},
+};
+static const struct clk_div_table dtable_1_32[] = {
- {0, 1},
- {1, 2},
- {2, 4},
- {3, 8},
- {4, 32},
- {0, 0},
+};
+static const struct clk_div_table dtable_16_128[] = {
- {0, 16},
- {1, 32},
- {2, 64},
- {3, 128},
- {0, 0},
+};
+/* Mux clock tables */ +static const char * const sel_pll3_3[] = { ".pll3_533", ".pll3_400" }; +static const char * const sel_pll5_4[] = { ".pll5_foutpostdiv", ".pll5_fout1ph0" }; +static const char * const sel_pll6_2[] = { ".pll6_250", ".pll5_250" };
Is this mixed tabs and spaces here ?
(please fix this in Linux too)
+static const char * const sel_shdi[] = { ".clk_533", ".clk_400", ".clk_266" }; +static const char * const sel_gpu2[] = { ".pll6", ".pll3_div2_2" };
[...]
diff --git a/drivers/clk/renesas/rzg2l-cpg.c b/drivers/clk/renesas/rzg2l-cpg.c
[...]
+static int rzg2l_cpg_clk_set(struct clk *clk, bool enable) +{
- struct rzg2l_cpg_data *data =
(struct rzg2l_cpg_data *)dev_get_driver_data(clk->dev);
- unsigned int cpg_clk_id = CPG_CLK_ID(clk->id);
- const struct rzg2l_mod_clk *mod_clk = NULL;
- u32 value;
- unsigned int i;
- dev_dbg(clk->dev, "%s %s clock %u\n", enable ? "enable" : "disable",
is_mod_clk(clk->id) ? "module" : "core", cpg_clk_id);
- if (!is_mod_clk(clk->id)) {
dev_err(clk->dev, "ID %lu is not a module clock\n", clk->id);
return -EINVAL;
- }
- for (i = 0; i < data->info->num_mod_clks; i++) {
if (data->info->mod_clks[i].id == cpg_clk_id) {
mod_clk = &data->info->mod_clks[i];
break;
}
- }
- if (!mod_clk) {
dev_err(clk->dev, "Module clock %u not found\n", cpg_clk_id);
return -ENODEV;
- }
- value = (BIT(mod_clk->bit) << 16);
Parenthesis not needed around this statement.
- if (enable)
value |= BIT(mod_clk->bit);
- writel(value, data->base + mod_clk->off);
- if (enable && readl_poll_timeout(data->base + CLK_MON_R(mod_clk->off),
value, (value & BIT(mod_clk->bit)),
10)) {
dev_err(clk->dev, "Timeout\n");
return -ETIMEDOUT;
- }
- return 0;
+}
+static int rzg2l_cpg_clk_enable(struct clk *clk) +{
- return rzg2l_cpg_clk_set(clk, true);
+}
+static int rzg2l_cpg_clk_disable(struct clk *clk) +{
- return rzg2l_cpg_clk_set(clk, false);
+}
+static int rzg2l_cpg_clk_of_xlate(struct clk *clk,
struct ofnode_phandle_args *args)
+{
- struct rzg2l_cpg_data *data =
(struct rzg2l_cpg_data *)dev_get_driver_data(clk->dev);
- u32 cpg_clk_type, cpg_clk_id;
- bool found = false;
- unsigned int i;
- if (args->args_count != 2) {
dev_dbg(clk->dev, "Invalid args_count: %d\n", args->args_count);
return -EINVAL;
- }
- cpg_clk_type = args->args[0];
- cpg_clk_id = args->args[1];
- switch (cpg_clk_type) {
- case CPG_CORE:
Is this copied from RCAR clock driver ?
Can this be deduplicated someohw ?
for (i = 0; i < data->info->num_core_clks; i++) {
if (data->info->core_clks[i].id == cpg_clk_id) {
found = true;
break;
}
}
if (!found) {
dev_dbg(clk->dev,
"Invalid second argument %u: Must be a valid core clock ID\n",
cpg_clk_id);
return -EINVAL;
}
break;
- case CPG_MOD:
for (i = 0; i < data->info->num_mod_clks; i++) {
if (data->info->mod_clks[i].id == cpg_clk_id) {
found = true;
break;
}
}
if (!found) {
dev_dbg(clk->dev,
"Invalid second argument %u: Must be a valid module clock ID\n",
cpg_clk_id);
return -EINVAL;
}
break;
- default:
dev_dbg(clk->dev,
"Invalid first argument %u: Must be CPG_CORE or CPG_MOD\n",
cpg_clk_type);
return -EINVAL;
- }
- clk->id = CPG_CLK_PACK(cpg_clk_type, cpg_clk_id);
- return 0;
+}
+static ulong rzg2l_sdhi_clk_get_rate(struct udevice *dev, const struct cpg_core_clk *cc) +{
- struct rzg2l_cpg_data *data =
(struct rzg2l_cpg_data *)dev_get_driver_data(dev);
- ulong offset = CPG_CONF_OFFSET(cc->conf);
- int shift = CPG_CONF_BITPOS(cc->conf);
- u32 mask = CPG_CONF_BITMASK(cc->conf);
- unsigned int sel;
- sel = (readl(data->base + offset) >> shift) & mask;
- if (!sel || sel > cc->num_parents) {
dev_err(dev, "Invalid SEL_SDHI%d_SET value %u\n", shift / 4, sel);
return -EIO;
- }
- return rzg2l_cpg_clk_get_rate_by_name(dev, cc->parent_names[sel - 1]);
+}
+static ulong rzg2l_div_clk_get_rate(struct udevice *dev, const struct cpg_core_clk *cc) +{
- struct rzg2l_cpg_data *data =
(struct rzg2l_cpg_data *)dev_get_driver_data(dev);
- ulong offset = CPG_CONF_OFFSET(cc->conf);
- int shift = CPG_CONF_BITPOS(cc->conf);
- u32 mask = CPG_CONF_BITMASK(cc->conf);
Can these be 'const' too ?
Fix globally please.
- unsigned int sel, i;
- sel = (readl(data->base + offset) >> shift) & mask;
- for (i = 0; cc->dtable[i].div; i++) {
if (cc->dtable[i].val == sel)
return rzg2l_cpg_clk_get_rate_by_id(dev, cc->parent) / cc->dtable[i].div;
- }
- dev_err(dev, "Invalid selector value %u for clock %s\n", sel, cc->name);
- return -EINVAL;
+}
[...]
+static ulong rzg2l_core_clk_set_rate(struct udevice *dev, const struct cpg_core_clk *cc, ulong rate) +{
- if (cc->type == CLK_TYPE_SD_MUX)
return rzg2l_sdhi_clk_set_rate(dev, cc, rate);
No netdev style comments please, use full block comment starting with /* and newline.
- /* The sdhi driver calls clk_set_rate for SD0_DIV4 and SD1_DIV4, even
* though they're in a fixed relationship with SD0 and SD1 respectively.
* To allow the driver to proceed, simply return the current rates
* without making any change.
*/
- if (cc->id == CLK_SD0_DIV4 || cc->id == CLK_SD1_DIV4)
return rzg2l_core_clk_get_rate(dev, cc);
- dev_err(dev, "set_rate needed for clock %u, type %d\n", cc->id, cc->type);
- return -ENOSYS;
+}
[...]
diff --git a/drivers/clk/renesas/rzg2l-cpg.h b/drivers/clk/renesas/rzg2l-cpg.h new file mode 100644 index 000000000000..f7a9a2156319 --- /dev/null +++ b/drivers/clk/renesas/rzg2l-cpg.h @@ -0,0 +1,318 @@ +/* SPDX-License-Identifier: GPL-2.0 */ +/*
- RZ/G2L Clock Pulse Generator
- Copyright (C) 2021-2023 Renesas Electronics Corp.
- */
+#ifndef __RENESAS_RZG2L_CPG_H__ +#define __RENESAS_RZG2L_CPG_H__
+#define CPG_SIPLL5_STBY (0x140)
Parenthesis not needed, fix globally.
+#define CPG_SIPLL5_CLK1 (0x144) +#define CPG_SIPLL5_CLK3 (0x14C) +#define CPG_SIPLL5_CLK4 (0x150) +#define CPG_SIPLL5_CLK5 (0x154) +#define CPG_SIPLL5_MON (0x15C) +#define CPG_PL1_DDIV (0x200) +#define CPG_PL2_DDIV (0x204) +#define CPG_PL3A_DDIV (0x208) +#define CPG_PL6_DDIV (0x210) +#define CPG_PL2SDHI_DSEL (0x218) +#define CPG_CLKSTATUS (0x280) +#define CPG_PL3_SSEL (0x408) +#define CPG_PL6_SSEL (0x414) +#define CPG_PL6_ETH_SSEL (0x418) +#define CPG_PL5_SDIV (0x420) +#define CPG_RST_MON (0x680) +#define CPG_OTHERFUNC1_REG (0xBE8)
+#define CPG_SIPLL5_STBY_RESETB BIT(0) +#define CPG_SIPLL5_STBY_RESETB_WEN BIT(16) +#define CPG_SIPLL5_STBY_SSCG_EN_WEN BIT(18) +#define CPG_SIPLL5_STBY_DOWNSPREAD_WEN BIT(20) +#define CPG_SIPLL5_CLK4_RESV_LSB (0xFF) +#define CPG_SIPLL5_MON_PLL5_LOCK BIT(4)
+#define CPG_OTHERFUNC1_REG_RES0_ON_WEN BIT(16)
+#define CPG_PL5_SDIV_DIV_DSI_A_WEN BIT(16) +#define CPG_PL5_SDIV_DIV_DSI_B_WEN BIT(24)
+#define CPG_CLKSTATUS_SELSDHI0_STS BIT(28) +#define CPG_CLKSTATUS_SELSDHI1_STS BIT(29)
+#define CPG_SDHI_CLK_SWITCH_STATUS_TIMEOUT_US 20000
+/* n = 0/1/2 for PLL1/4/6 */ +#define CPG_SAMPLL_CLK1(n) (0x04 + (16 * n)) +#define CPG_SAMPLL_CLK2(n) (0x08 + (16 * n))
Parenthesis around 'n' need to be added.
+#define PLL146_CONF(n) (CPG_SAMPLL_CLK1(n) << 22 | CPG_SAMPLL_CLK2(n) << 12)
+#define DDIV_PACK(offset, bitpos, size) \
(((offset) << 20) | ((bitpos) << 12) | ((size) << 8))
+#define DIVPL1A DDIV_PACK(CPG_PL1_DDIV, 0, 2) +#define DIVPL2A DDIV_PACK(CPG_PL2_DDIV, 0, 3) +#define DIVDSILPCLK DDIV_PACK(CPG_PL2_DDIV, 12, 2) +#define DIVPL3A DDIV_PACK(CPG_PL3A_DDIV, 0, 3) +#define DIVPL3B DDIV_PACK(CPG_PL3A_DDIV, 4, 3) +#define DIVPL3C DDIV_PACK(CPG_PL3A_DDIV, 8, 3) +#define DIVGPU DDIV_PACK(CPG_PL6_DDIV, 0, 2)
+#define SEL_PLL_PACK(offset, bitpos, size) \
(((offset) << 20) | ((bitpos) << 12) | ((size) << 8))
+#define SEL_PLL3_3 SEL_PLL_PACK(CPG_PL3_SSEL, 8, 1) +#define SEL_PLL5_4 SEL_PLL_PACK(CPG_OTHERFUNC1_REG, 0, 1) +#define SEL_PLL6_2 SEL_PLL_PACK(CPG_PL6_ETH_SSEL, 0, 1) +#define SEL_GPU2 SEL_PLL_PACK(CPG_PL6_SSEL, 12, 1)
+#define SEL_SDHI0 DDIV_PACK(CPG_PL2SDHI_DSEL, 0, 2) +#define SEL_SDHI1 DDIV_PACK(CPG_PL2SDHI_DSEL, 4, 2)
+#define SEL_SDHI_533MHz 1 +#define SEL_SDHI_400MHz 2 +#define SEL_SDHI_266MHz 3 +#define SEL_SDHI_WRITE_ENABLE 0x10000
+/* Unpack CPG conf value create by DDIV_PACK() or SEL_PLL_PACK(). */ +#define CPG_CONF_OFFSET(x) ((x) >> 20) +#define CPG_CONF_BITPOS(x) (((x) >> 12) & 0xff) +#define CPG_CONF_SIZE(x) (((x) >> 8) & 0xf) +#define CPG_CONF_BITMASK(x) GENMASK(CPG_CONF_SIZE(x) - 1, 0)
+#define EXTAL_FREQ_IN_MEGA_HZ (24)
Drop parenthesis around integer value please.
[...]

On 03/10/2023 13:56, Marek Vasut wrote:
On 9/20/23 14:42, Paul Barker wrote:
This driver provides clock and reset control for the Renesas RZ/G2L (R9A07G044) SoC. It consists of two parts:
driver code which is applicable to all SoCs in the RZ/G2L family
static data describing the clocks and resets which are specific to the R9A07G044 SoC.
clk_set_rate() and clk_get_rate() are implemented only for the clocks that are actually used in u-boot.
The CPG driver is marked with DM_FLAG_PRE_RELOC to ensure that its bind function is called before the SCIF (serial port) driver is probed. This is required so that we can de-assert the relevant reset signal during the serial driver probe function.
This patch is based on the corresponding Linux v6.5 driver.
Same thing as 02/16..04/16 applies here.
Signed-off-by: Paul Barker paul.barker.ct@bp.renesas.com Reviewed-by: Biju Das biju.das.jz@bp.renesas.com Reviewed-by: Lad Prabhakar prabhakar.mahadev-lad.rj@bp.renesas.com
arch/arm/mach-rmobile/Kconfig | 1 + arch/arm/mach-rmobile/Kconfig.rzg2l | 1 + drivers/clk/renesas/Kconfig | 9 + drivers/clk/renesas/Makefile | 2 + drivers/clk/renesas/r9a07g044-cpg.c | 384 +++++++++++++++++++++ drivers/clk/renesas/rzg2l-cpg.c | 502 ++++++++++++++++++++++++++++ drivers/clk/renesas/rzg2l-cpg.h | 318 ++++++++++++++++++ 7 files changed, 1217 insertions(+) create mode 100644 drivers/clk/renesas/r9a07g044-cpg.c create mode 100644 drivers/clk/renesas/rzg2l-cpg.c create mode 100644 drivers/clk/renesas/rzg2l-cpg.h
diff --git a/arch/arm/mach-rmobile/Kconfig b/arch/arm/mach-rmobile/Kconfig index fd240832d83d..fc37f6c79e50 100644 --- a/arch/arm/mach-rmobile/Kconfig +++ b/arch/arm/mach-rmobile/Kconfig @@ -74,6 +74,7 @@ config RZG2L imply MULTI_DTB_FIT_USER_DEFINED_AREA imply SYS_MALLOC_F imply RENESAS_SDHI
- imply CLK_RZG2L
Keep the list sorted
help Enable support for the Renesas RZ/G2L family of SoCs, including the the RZ/G2L itself (based on the R9A07G044 SoC). diff --git a/arch/arm/mach-rmobile/Kconfig.rzg2l b/arch/arm/mach-rmobile/Kconfig.rzg2l index 266f82c18085..7d268e8c366a 100644 --- a/arch/arm/mach-rmobile/Kconfig.rzg2l +++ b/arch/arm/mach-rmobile/Kconfig.rzg2l @@ -5,6 +5,7 @@ if RZG2L
config R9A07G044L bool "Renesas R9A07G044L SoC"
- imply CLK_R9A07G044
Why not CLK_R9A07G044L (with L at the end) ?
The driver will also support the RZ/G2LC (R9A07G044C) when support for that SoC is added in a later patch series.
help Enable support for the R9A07G044L SoC used in the RZ/G2L.
diff --git a/drivers/clk/renesas/Kconfig b/drivers/clk/renesas/Kconfig index 437a82cd48be..927d62cf99a3 100644 --- a/drivers/clk/renesas/Kconfig +++ b/drivers/clk/renesas/Kconfig @@ -156,3 +156,12 @@ config CLK_R9A06G032 depends on CLK_RENESAS help Enable this to support the clocks on Renesas R9A06G032 SoC.
+config CLK_RZG2L
- bool "Renesas RZ/G2L family clock support"
- depends on CLK_RENESAS
- select DM_RESET
+config CLK_R9A07G044
- bool "RZ/G2L (R9A07G044L) clock support"
- depends on CLK_RZG2L
diff --git a/drivers/clk/renesas/Makefile b/drivers/clk/renesas/Makefile index 48373e61b901..df7e225e9ca4 100644 --- a/drivers/clk/renesas/Makefile +++ b/drivers/clk/renesas/Makefile @@ -23,3 +23,5 @@ obj-$(CONFIG_CLK_R8A779A0) += r8a779a0-cpg-mssr.o obj-$(CONFIG_CLK_R8A779F0) += r8a779f0-cpg-mssr.o obj-$(CONFIG_CLK_R8A779G0) += r8a779g0-cpg-mssr.o obj-$(CONFIG_CLK_R9A06G032) += r9a06g032-clocks.o +obj-$(CONFIG_CLK_RZG2L) += rzg2l-cpg.o +obj-$(CONFIG_CLK_R9A07G044) += r9a07g044-cpg.o diff --git a/drivers/clk/renesas/r9a07g044-cpg.c b/drivers/clk/renesas/r9a07g044-cpg.c new file mode 100644 index 000000000000..e215db7caf15 --- /dev/null +++ b/drivers/clk/renesas/r9a07g044-cpg.c @@ -0,0 +1,384 @@ +// SPDX-License-Identifier: GPL-2.0 +/*
- RZ/G2L CPG driver
- Copyright (C) 2021-2023 Renesas Electronics Corp.
- */
+#include <common.h> +#include <dm/device.h> +#include <dt-bindings/clock/r9a07g044-cpg.h> +#include <linux/clk-provider.h>
+#include "rzg2l-cpg.h"
+/* Divider tables */ +static const struct clk_div_table dtable_1_8[] = {
- {0, 1},
- {1, 2},
- {2, 4},
- {3, 8},
- {0, 0},
+};
+static const struct clk_div_table dtable_1_32[] = {
- {0, 1},
- {1, 2},
- {2, 4},
- {3, 8},
- {4, 32},
- {0, 0},
+};
+static const struct clk_div_table dtable_16_128[] = {
- {0, 16},
- {1, 32},
- {2, 64},
- {3, 128},
- {0, 0},
+};
+/* Mux clock tables */ +static const char * const sel_pll3_3[] = { ".pll3_533", ".pll3_400" }; +static const char * const sel_pll5_4[] = { ".pll5_foutpostdiv", ".pll5_fout1ph0" }; +static const char * const sel_pll6_2[] = { ".pll6_250", ".pll5_250" };
Is this mixed tabs and spaces here ?
(please fix this in Linux too)
I've tried to minimize changes between the u-boot and Linux drivers, so this mixed tabs/spaces issue, parenthesis around numbers in defines, etc, is an exact copy of what was accepted into the mainline kernel. The hope is that we can more easily port fixes from Linux to u-boot if the code remains as similar as possible.
+static const char * const sel_shdi[] = { ".clk_533", ".clk_400", ".clk_266" }; +static const char * const sel_gpu2[] = { ".pll6", ".pll3_div2_2" };
[...]
diff --git a/drivers/clk/renesas/rzg2l-cpg.c b/drivers/clk/renesas/rzg2l-cpg.c
[...]
+static int rzg2l_cpg_clk_set(struct clk *clk, bool enable) +{
- struct rzg2l_cpg_data *data =
(struct rzg2l_cpg_data *)dev_get_driver_data(clk->dev);
- unsigned int cpg_clk_id = CPG_CLK_ID(clk->id);
- const struct rzg2l_mod_clk *mod_clk = NULL;
- u32 value;
- unsigned int i;
- dev_dbg(clk->dev, "%s %s clock %u\n", enable ? "enable" : "disable",
is_mod_clk(clk->id) ? "module" : "core", cpg_clk_id);
- if (!is_mod_clk(clk->id)) {
dev_err(clk->dev, "ID %lu is not a module clock\n", clk->id);
return -EINVAL;
- }
- for (i = 0; i < data->info->num_mod_clks; i++) {
if (data->info->mod_clks[i].id == cpg_clk_id) {
mod_clk = &data->info->mod_clks[i];
break;
}
- }
- if (!mod_clk) {
dev_err(clk->dev, "Module clock %u not found\n", cpg_clk_id);
return -ENODEV;
- }
- value = (BIT(mod_clk->bit) << 16);
Parenthesis not needed around this statement.
This one is my mistake - I forgot to remove the brackets when I simplified this expression. Will fix in v2.
- if (enable)
value |= BIT(mod_clk->bit);
- writel(value, data->base + mod_clk->off);
- if (enable && readl_poll_timeout(data->base + CLK_MON_R(mod_clk->off),
value, (value & BIT(mod_clk->bit)),
10)) {
dev_err(clk->dev, "Timeout\n");
return -ETIMEDOUT;
- }
- return 0;
+}
+static int rzg2l_cpg_clk_enable(struct clk *clk) +{
- return rzg2l_cpg_clk_set(clk, true);
+}
+static int rzg2l_cpg_clk_disable(struct clk *clk) +{
- return rzg2l_cpg_clk_set(clk, false);
+}
+static int rzg2l_cpg_clk_of_xlate(struct clk *clk,
struct ofnode_phandle_args *args)
+{
- struct rzg2l_cpg_data *data =
(struct rzg2l_cpg_data *)dev_get_driver_data(clk->dev);
- u32 cpg_clk_type, cpg_clk_id;
- bool found = false;
- unsigned int i;
- if (args->args_count != 2) {
dev_dbg(clk->dev, "Invalid args_count: %d\n", args->args_count);
return -EINVAL;
- }
- cpg_clk_type = args->args[0];
- cpg_clk_id = args->args[1];
- switch (cpg_clk_type) {
- case CPG_CORE:
Is this copied from RCAR clock driver ?
Can this be deduplicated someohw ?
This isn't copied from the RCAR driver. In Linux the RZ/G2L family CPG drivers are separate to the RCAR clock drivers as there are too many differences to easily combine them.
Thanks, Paul

On 10/4/23 10:15, Paul Barker wrote:
[...]
config R9A07G044L bool "Renesas R9A07G044L SoC"
- imply CLK_R9A07G044
Why not CLK_R9A07G044L (with L at the end) ?
The driver will also support the RZ/G2LC (R9A07G044C) when support for that SoC is added in a later patch series.
Ah, please, do add this explanation into the commit message.
This is really valuable piece of information to de-confuse whoever is looking at this naming scheme, really.
+/* Mux clock tables */ +static const char * const sel_pll3_3[] = { ".pll3_533", ".pll3_400" }; +static const char * const sel_pll5_4[] = { ".pll5_foutpostdiv", ".pll5_fout1ph0" }; +static const char * const sel_pll6_2[] = { ".pll6_250", ".pll5_250" };
Is this mixed tabs and spaces here ?
(please fix this in Linux too)
I've tried to minimize changes between the u-boot and Linux drivers, so this mixed tabs/spaces issue, parenthesis around numbers in defines, etc, is an exact copy of what was accepted into the mainline kernel. The hope is that we can more easily port fixes from Linux to u-boot if the code remains as similar as possible.
Send patch to Geert on Linux side too and problem should be solved.

The RZ/G2L family uses CONFIG_RCAR_64 but does not share a common PFC driver with the R-Car gen3 & gen4 boards.
Signed-off-by: Paul Barker paul.barker.ct@bp.renesas.com Reviewed-by: Biju Das biju.das.jz@bp.renesas.com Reviewed-by: Lad Prabhakar prabhakar.mahadev-lad.rj@bp.renesas.com --- arch/arm/mach-rmobile/Kconfig | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-)
diff --git a/arch/arm/mach-rmobile/Kconfig b/arch/arm/mach-rmobile/Kconfig index fc37f6c79e50..91f544c78337 100644 --- a/arch/arm/mach-rmobile/Kconfig +++ b/arch/arm/mach-rmobile/Kconfig @@ -9,7 +9,6 @@ config RCAR_64 select PHY select PINCONF select PINCTRL - select PINCTRL_PFC select POSITION_INDEPENDENT imply CMD_FS_UUID imply CMD_GPT @@ -29,6 +28,7 @@ config RCAR_GEN3 bool "Renesas ARM SoCs R-Car Gen3 (64bit)" select RCAR_64 select SUPPORT_SPL + select PINCTRL_PFC imply SPL imply SPL_BOARD_INIT imply SPL_GZIP @@ -43,6 +43,7 @@ config RCAR_GEN3 config RCAR_GEN4 bool "Renesas ARM SoCs R-Car Gen4 (64bit)" select RCAR_64 + select PINCTRL_PFC
config RZA1 prompt "Renesas ARM SoCs RZ/A1 (32bit)"

On 9/20/23 14:42, Paul Barker wrote:
The RZ/G2L family uses CONFIG_RCAR_64 but does not share a common PFC driver with the R-Car gen3 & gen4 boards.
Signed-off-by: Paul Barker paul.barker.ct@bp.renesas.com Reviewed-by: Biju Das biju.das.jz@bp.renesas.com Reviewed-by: Lad Prabhakar prabhakar.mahadev-lad.rj@bp.renesas.com
arch/arm/mach-rmobile/Kconfig | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-)
diff --git a/arch/arm/mach-rmobile/Kconfig b/arch/arm/mach-rmobile/Kconfig index fc37f6c79e50..91f544c78337 100644 --- a/arch/arm/mach-rmobile/Kconfig +++ b/arch/arm/mach-rmobile/Kconfig @@ -9,7 +9,6 @@ config RCAR_64 select PHY select PINCONF select PINCTRL
- select PINCTRL_PFC select POSITION_INDEPENDENT imply CMD_FS_UUID imply CMD_GPT
@@ -29,6 +28,7 @@ config RCAR_GEN3 bool "Renesas ARM SoCs R-Car Gen3 (64bit)" select RCAR_64 select SUPPORT_SPL
- select PINCTRL_PFC imply SPL imply SPL_BOARD_INIT imply SPL_GZIP
@@ -43,6 +43,7 @@ config RCAR_GEN3 config RCAR_GEN4 bool "Renesas ARM SoCs R-Car Gen4 (64bit)" select RCAR_64
- select PINCTRL_PFC
Reviewed-by: Marek Vasut marek.vasut+renesas@mailbox.org

This driver provides pinctrl and gpio control for the Renesas RZ/G2L (R9A07G044) SoC.
This patch is based on the corresponding Linux v6.5 driver.
Signed-off-by: Paul Barker paul.barker.ct@bp.renesas.com Reviewed-by: Biju Das biju.das.jz@bp.renesas.com Reviewed-by: Lad Prabhakar prabhakar.mahadev-lad.rj@bp.renesas.com --- arch/arm/mach-rmobile/Kconfig | 1 + drivers/pinctrl/renesas/Kconfig | 9 + drivers/pinctrl/renesas/Makefile | 1 + drivers/pinctrl/renesas/rzg2l-pfc.c | 906 ++++++++++++++++++++++++++++ 4 files changed, 917 insertions(+) create mode 100644 drivers/pinctrl/renesas/rzg2l-pfc.c
diff --git a/arch/arm/mach-rmobile/Kconfig b/arch/arm/mach-rmobile/Kconfig index 91f544c78337..973e84fcf7ba 100644 --- a/arch/arm/mach-rmobile/Kconfig +++ b/arch/arm/mach-rmobile/Kconfig @@ -76,6 +76,7 @@ config RZG2L imply SYS_MALLOC_F imply RENESAS_SDHI imply CLK_RZG2L + imply PINCTRL_RZG2L help Enable support for the Renesas RZ/G2L family of SoCs, including the the RZ/G2L itself (based on the R9A07G044 SoC). diff --git a/drivers/pinctrl/renesas/Kconfig b/drivers/pinctrl/renesas/Kconfig index 0ea39b4a3f11..b58a6990befe 100644 --- a/drivers/pinctrl/renesas/Kconfig +++ b/drivers/pinctrl/renesas/Kconfig @@ -138,6 +138,15 @@ config PINCTRL_PFC_R7S72100 help Support pin multiplexing control on Renesas RZ/A1 R7S72100 SoCs.
+config PINCTRL_RZG2L + bool "Renesas RZ/G2L family pin control driver" + depends on PINCTRL + depends on PINCTRL_GENERIC + depends on PINCONF + help + Support the pin function controller (PFC) on the Renesas RZ/G2L SoC + family. + endif
config PINCTRL_RZN1 diff --git a/drivers/pinctrl/renesas/Makefile b/drivers/pinctrl/renesas/Makefile index 1a61c39d8471..9e1cdd42769a 100644 --- a/drivers/pinctrl/renesas/Makefile +++ b/drivers/pinctrl/renesas/Makefile @@ -21,3 +21,4 @@ obj-$(CONFIG_PINCTRL_PFC_R8A779F0) += pfc-r8a779f0.o obj-$(CONFIG_PINCTRL_PFC_R8A779G0) += pfc-r8a779g0.o obj-$(CONFIG_PINCTRL_PFC_R7S72100) += pfc-r7s72100.o obj-$(CONFIG_PINCTRL_RZN1) += pinctrl-rzn1.o +obj-$(CONFIG_PINCTRL_RZG2L) += rzg2l-pfc.o diff --git a/drivers/pinctrl/renesas/rzg2l-pfc.c b/drivers/pinctrl/renesas/rzg2l-pfc.c new file mode 100644 index 000000000000..59c037ba944a --- /dev/null +++ b/drivers/pinctrl/renesas/rzg2l-pfc.c @@ -0,0 +1,906 @@ +// SPDX-License-Identifier: GPL-2.0 +/* + * RZ/G2L Pin Function Controller + * + * Copyright (C) 2021-2023 Renesas Electronics Corp. + */ + +#include <common.h> +#include <asm-generic/gpio.h> +#include <asm/io.h> +#include <asm/types.h> +#include <dm.h> +#include <dm/device-internal.h> +#include <dm/device.h> +#include <dm/device_compat.h> +#include <dm/devres.h> +#include <dm/lists.h> +#include <dm/pinctrl.h> +#include <clk.h> +#include <reset.h> + +/* PIN capabilities */ +#define PIN_CFG_IOLH_A BIT(0) +#define PIN_CFG_IOLH_B BIT(1) +#define PIN_CFG_SR BIT(2) +#define PIN_CFG_IEN BIT(3) +#define PIN_CFG_PUPD BIT(4) +#define PIN_CFG_IO_VMC_SD0 BIT(5) +#define PIN_CFG_IO_VMC_SD1 BIT(6) +#define PIN_CFG_IO_VMC_QSPI BIT(7) +#define PIN_CFG_IO_VMC_ETH0 BIT(8) +#define PIN_CFG_IO_VMC_ETH1 BIT(9) +#define PIN_CFG_FILONOFF BIT(10) +#define PIN_CFG_FILNUM BIT(11) +#define PIN_CFG_FILCLKSEL BIT(12) + +#define RZG2L_MPXED_PIN_FUNCS (PIN_CFG_IOLH_A | \ + PIN_CFG_SR | \ + PIN_CFG_PUPD | \ + PIN_CFG_FILONOFF | \ + PIN_CFG_FILNUM | \ + PIN_CFG_FILCLKSEL) + +#define RZG2L_MPXED_ETH_PIN_FUNCS(x) ((x) | \ + PIN_CFG_FILONOFF | \ + PIN_CFG_FILNUM | \ + PIN_CFG_FILCLKSEL) + +/* GPIO port data macros: + * n indicates number of pins in the port, a is the register index + * and f is pin configuration capabilities supported. + */ +#define RZG2L_GPIO_PORT_PACK(n, a, f) (((n) << 28) | ((a) << 20) | (f)) +#define RZG2L_GPIO_PORT_GET_PINCNT(x) (((x) & GENMASK(30, 28)) >> 28) +#define RZG2L_GPIO_PORT_GET_INDEX(x) (((x) & GENMASK(26, 20)) >> 20) +#define RZG2L_GPIO_PORT_GET_CFGS(x) ((x) & GENMASK(19, 0)) + +/* Dedicated pin data macros: + * BIT(31) indicates dedicated pin, p is the register index while + * referencing to SR/IEN/IOLH/FILxx registers, b is the register bits + * (b * 8) and f is the pin configuration capabilities supported. + */ +#define RZG2L_SINGLE_PIN BIT(31) +#define RZG2L_SINGLE_PIN_PACK(p, b, f) (RZG2L_SINGLE_PIN | \ + ((p) << 24) | ((b) << 20) | (f)) +#define RZG2L_SINGLE_PIN_GET_PORT_OFFSET(x) (((x) & GENMASK(30, 24)) >> 24) +#define RZG2L_SINGLE_PIN_GET_BIT(x) (((x) & GENMASK(22, 20)) >> 20) +#define RZG2L_SINGLE_PIN_GET_CFGS(x) ((x) & GENMASK(19, 0)) + +/* Pinmux data encoded in the device tree uses: + * 16 lower bits [15:0] for pin identifier + * 16 higher bits [31:16] for pin mux function + */ +#define MUX_PIN_ID_MASK GENMASK(15, 0) +#define MUX_FUNC_MASK GENMASK(31, 16) +#define RZG2L_PINS_PER_PORT 8 +#define RZG2L_PINMUX_TO_PORT(conf) (((conf) & MUX_PIN_ID_MASK) / RZG2L_PINS_PER_PORT) +#define RZG2L_PINMUX_TO_PIN(conf) (((conf) & MUX_PIN_ID_MASK) % RZG2L_PINS_PER_PORT) +#define RZG2L_PINMUX_TO_FUNC(conf) (((conf) & MUX_FUNC_MASK) >> 16) + +/* Register offsets and values. */ +#define P(n) (0x0000 + 0x10 + (n)) +#define PM(n) (0x0100 + 0x20 + (n) * 2) +#define PMC(n) (0x0200 + 0x10 + (n)) +#define PFC(n) (0x0400 + 0x40 + (n) * 4) +#define PIN(n) (0x0800 + 0x10 + (n)) +#define IOLH(n) (0x1000 + (n) * 8) +#define IEN(n) (0x1800 + (n) * 8) +#define PWPR (0x3014) +#define SD_CH(n) (0x3000 + (n) * 4) +#define QSPI (0x3008) + +#define PVDD_1800 1 /* I/O domain voltage <= 1.8V */ +#define PVDD_3300 0 /* I/O domain voltage >= 3.3V */ + +#define PWPR_B0WI BIT(7) /* Bit Write Disable */ +#define PWPR_PFCWE BIT(6) /* PFC Register Write Enable */ + +#define PM_MASK 0x03 +#define PVDD_MASK 0x01 +#define PFC_MASK 0x07 +#define IEN_MASK 0x01 +#define IOLH_MASK 0x03 + +#define PM_HIGH_Z 0x0 +#define PM_INPUT 0x1 +#define PM_OUTPUT 0x2 +#define PM_OUTPUT_IEN 0x3 + +struct rzg2l_pfc_driver_data { + uint num_dedicated_pins; + uint num_ports; + const u32 *gpio_configs; +}; + +struct rzg2l_pfc_data { + void __iomem *base; + uint num_dedicated_pins; + uint num_ports; + uint num_pins; + const u32 *gpio_configs; + bool pfc_enabled; +}; + +struct rzg2l_dedicated_configs { + const char *name; + u32 config; +}; + +/* + * We need to ensure that the module clock is enabled and all resets are + * de-asserted before using either the gpio or pinctrl functionality. Error + * handling can be quite simple here as if the PFC cannot be enabled then we + * will not be able to progress with the boot anyway. + */ +static int rzg2l_pfc_enable(struct udevice *dev) +{ + struct rzg2l_pfc_data *data = + (struct rzg2l_pfc_data *)dev_get_driver_data(dev); + struct reset_ctl_bulk rsts; + struct clk clk; + int ret; + + if (data->pfc_enabled) + return 0; + + ret = clk_get_by_index(dev, 0, &clk); + if (ret < 0) { + dev_err(dev, "failed to get gpio module clock\n"); + return ret; + } + + ret = clk_enable(&clk); + if (ret < 0) { + dev_err(dev, "failed to enable gpio module clock\n"); + return ret; + } + + ret = reset_get_bulk(dev, &rsts); + if (ret < 0) { + dev_err(dev, "failed to get reset lines\n"); + return ret; + } + + ret = reset_deassert_bulk(&rsts); + if (ret < 0) { + dev_err(dev, "failed to de-assert reset lines\n"); + return ret; + } + + data->pfc_enabled = true; + return 0; +} + +static inline bool rzg2l_port_validate(struct rzg2l_pfc_data *data, + u32 port, u8 pin) +{ + return (port < data->num_ports) && + (pin < RZG2L_GPIO_PORT_GET_PINCNT(data->gpio_configs[port])); +} + +/* Decode a pin selector, returning the port index and setting *pin to the pin + * index. Returns -1 on error, which can be checked directly or by calling + * rzg2l_port_validate(). + */ +static int rzg2l_selector_decode(struct rzg2l_pfc_data *data, + unsigned int selector, + u8 *pin) +{ + int port; + + selector -= data->num_dedicated_pins; + for (port = 0; port < data->num_ports; port++) { + u8 num_pins = RZG2L_GPIO_PORT_GET_PINCNT(data->gpio_configs[port]); + if (selector < num_pins) { + *pin = (u8)selector; + return port; + } + selector -= num_pins; + } + return -EINVAL; +} + +static unsigned int rzg2l_selector_encode(struct rzg2l_pfc_data *data, + u32 port, u8 pin) +{ + unsigned int selector = data->num_dedicated_pins + pin; + u32 i; + + for (i = 0; i < port; i++) + selector += RZG2L_GPIO_PORT_GET_PINCNT(data->gpio_configs[i]); + + return selector; +} + +static void rzg2l_gpio_set(struct rzg2l_pfc_data *data, + u32 port, u8 pin, bool value) +{ + u8 reg8 = readb(data->base + P(port)); + + if (value) + writeb(reg8 | BIT(pin), data->base + P(port)); + else + writeb(reg8 & ~BIT(pin), data->base + P(port)); +} + +static int rzg2l_gpio_get_value(struct udevice *dev, unsigned int offset) +{ + struct rzg2l_pfc_data *data = + (struct rzg2l_pfc_data *)dev_get_driver_data(dev); + u32 port = RZG2L_PINMUX_TO_PORT(offset); + u8 pin = RZG2L_PINMUX_TO_PIN(offset); + u16 pm_state; + + pm_state = (readw(data->base + PM(port)) >> (pin * 2)) & PM_MASK; + switch (pm_state) { + case PM_INPUT: + return !!(readb(data->base + PIN(port)) & BIT(pin)); + case PM_OUTPUT: + case PM_OUTPUT_IEN: + return !!(readb(data->base + P(port)) & BIT(pin)); + default: /* PM_HIGH_Z */ + return 0; + } +} + +static int rzg2l_gpio_set_value(struct udevice *dev, unsigned int offset, + int value) +{ + struct rzg2l_pfc_data *data = + (struct rzg2l_pfc_data *)dev_get_driver_data(dev); + u32 port = RZG2L_PINMUX_TO_PORT(offset); + u8 pin = RZG2L_PINMUX_TO_PIN(offset); + + rzg2l_gpio_set(data, port, pin, (bool)value); + return 0; +} + +static void rzg2l_gpio_set_direction(struct rzg2l_pfc_data *data, + u32 port, u8 pin, bool output) +{ + u16 reg16; + + reg16 = readw(data->base + PM(port)); + reg16 &= ~(PM_MASK << (pin * 2)); + + reg16 |= (output ? PM_OUTPUT : PM_INPUT) << (pin * 2); + writew(reg16, data->base + PM(port)); +} + +static int rzg2l_gpio_direction_input(struct udevice *dev, unsigned int offset) +{ + struct rzg2l_pfc_data *data = + (struct rzg2l_pfc_data *)dev_get_driver_data(dev); + u32 port = RZG2L_PINMUX_TO_PORT(offset); + u8 pin = RZG2L_PINMUX_TO_PIN(offset); + + rzg2l_gpio_set_direction(data, port, pin, false); + return 0; +} + +static int rzg2l_gpio_direction_output(struct udevice *dev, unsigned int offset, + int value) +{ + struct rzg2l_pfc_data *data = + (struct rzg2l_pfc_data *)dev_get_driver_data(dev); + u32 port = RZG2L_PINMUX_TO_PORT(offset); + u8 pin = RZG2L_PINMUX_TO_PIN(offset); + + rzg2l_gpio_set(data, port, pin, (bool)value); + rzg2l_gpio_set_direction(data, port, pin, true); + return 0; +} + +static int rzg2l_gpio_request(struct udevice *dev, unsigned int offset, + const char *label) +{ + struct rzg2l_pfc_data *data = + (struct rzg2l_pfc_data *)dev_get_driver_data(dev); + u32 port = RZG2L_PINMUX_TO_PORT(offset); + u8 pin = RZG2L_PINMUX_TO_PIN(offset); + u8 reg8; + + if (!rzg2l_port_validate(data, port, pin)) { + dev_err(dev, "Invalid GPIO %u:%u\n", port, pin); + return -EINVAL; + } + + /* Select GPIO mode in PMC Register */ + reg8 = readb(data->base + PMC(port)); + reg8 &= ~BIT(pin); + writeb(reg8, data->base + PMC(port)); + + return 0; +} + +static int rzg2l_gpio_get_function(struct udevice *dev, unsigned int offset) +{ + struct rzg2l_pfc_data *data = + (struct rzg2l_pfc_data *)dev_get_driver_data(dev); + u32 port = RZG2L_PINMUX_TO_PORT(offset); + u8 pin = RZG2L_PINMUX_TO_PIN(offset); + u16 pm_state; + u8 pmc_state; + + if (!rzg2l_port_validate(data, port, pin)) { + /* Running `gpio status -a` at the u-boot command line will + * iterate through all GPIO offsets with no understanding of + * which are valid and which are not. So we need to return + * something meaningful even for the invalid GPIOs. + */ + return GPIOF_UNKNOWN; + } + + /* Check if the pin is in GPIO or function mode. */ + pmc_state = readb(data->base + PMC(port)) & BIT(pin); + if (pmc_state) + return GPIOF_FUNC; + + /* Check the pin direction. */ + pm_state = (readw(data->base + PM(port)) >> (pin * 2)) & PM_MASK; + switch (pm_state) { + case PM_INPUT: + return GPIOF_INPUT; + case PM_OUTPUT: + case PM_OUTPUT_IEN: + return GPIOF_OUTPUT; + default: /* PM_HIGH_Z */ + return GPIOF_UNUSED; + } +} + +static const struct dm_gpio_ops rzg2l_gpio_ops = { + .direction_input = rzg2l_gpio_direction_input, + .direction_output = rzg2l_gpio_direction_output, + .get_value = rzg2l_gpio_get_value, + .set_value = rzg2l_gpio_set_value, + .request = rzg2l_gpio_request, + .get_function = rzg2l_gpio_get_function, +}; + +static int rzg2l_gpio_probe(struct udevice *dev) +{ + struct gpio_dev_priv *uc_priv = dev_get_uclass_priv(dev); + struct ofnode_phandle_args args; + int ret; + + uc_priv->bank_name = "rzg2l-pfc-gpio"; + ret = ofnode_parse_phandle_with_args(dev_ofnode(dev), "gpio-ranges", + NULL, 3, 0, &args); + if (ret < 0) { + dev_err(dev, "Failed to parse gpio-ranges\n"); + return -EINVAL; + } + + uc_priv->gpio_count = args.args[2]; + return rzg2l_pfc_enable(dev); +} + +U_BOOT_DRIVER(rzg2l_pfc_gpio) = { + .name = "rzg2l-pfc-gpio", + .id = UCLASS_GPIO, + .ops = &rzg2l_gpio_ops, + .probe = rzg2l_gpio_probe, +}; + +static const char * const rzg2l_gpio_names[] = { + "P0_0", "P0_1", "P0_2", "P0_3", "P0_4", "P0_5", "P0_6", "P0_7", + "P1_0", "P1_1", "P1_2", "P1_3", "P1_4", "P1_5", "P1_6", "P1_7", + "P2_0", "P2_1", "P2_2", "P2_3", "P2_4", "P2_5", "P2_6", "P2_7", + "P3_0", "P3_1", "P3_2", "P3_3", "P3_4", "P3_5", "P3_6", "P3_7", + "P4_0", "P4_1", "P4_2", "P4_3", "P4_4", "P4_5", "P4_6", "P4_7", + "P5_0", "P5_1", "P5_2", "P5_3", "P5_4", "P5_5", "P5_6", "P5_7", + "P6_0", "P6_1", "P6_2", "P6_3", "P6_4", "P6_5", "P6_6", "P6_7", + "P7_0", "P7_1", "P7_2", "P7_3", "P7_4", "P7_5", "P7_6", "P7_7", + "P8_0", "P8_1", "P8_2", "P8_3", "P8_4", "P8_5", "P8_6", "P8_7", + "P9_0", "P9_1", "P9_2", "P9_3", "P9_4", "P9_5", "P9_6", "P9_7", + "P10_0", "P10_1", "P10_2", "P10_3", "P10_4", "P10_5", "P10_6", "P10_7", + "P11_0", "P11_1", "P11_2", "P11_3", "P11_4", "P11_5", "P11_6", "P11_7", + "P12_0", "P12_1", "P12_2", "P12_3", "P12_4", "P12_5", "P12_6", "P12_7", + "P13_0", "P13_1", "P13_2", "P13_3", "P13_4", "P13_5", "P13_6", "P13_7", + "P14_0", "P14_1", "P14_2", "P14_3", "P14_4", "P14_5", "P14_6", "P14_7", + "P15_0", "P15_1", "P15_2", "P15_3", "P15_4", "P15_5", "P15_6", "P15_7", + "P16_0", "P16_1", "P16_2", "P16_3", "P16_4", "P16_5", "P16_6", "P16_7", + "P17_0", "P17_1", "P17_2", "P17_3", "P17_4", "P17_5", "P17_6", "P17_7", + "P18_0", "P18_1", "P18_2", "P18_3", "P18_4", "P18_5", "P18_6", "P18_7", + "P19_0", "P19_1", "P19_2", "P19_3", "P19_4", "P19_5", "P19_6", "P19_7", + "P20_0", "P20_1", "P20_2", "P20_3", "P20_4", "P20_5", "P20_6", "P20_7", + "P21_0", "P21_1", "P21_2", "P21_3", "P21_4", "P21_5", "P21_6", "P21_7", + "P22_0", "P22_1", "P22_2", "P22_3", "P22_4", "P22_5", "P22_6", "P22_7", + "P23_0", "P23_1", "P23_2", "P23_3", "P23_4", "P23_5", "P23_6", "P23_7", + "P24_0", "P24_1", "P24_2", "P24_3", "P24_4", "P24_5", "P24_6", "P24_7", + "P25_0", "P25_1", "P25_2", "P25_3", "P25_4", "P25_5", "P25_6", "P25_7", + "P26_0", "P26_1", "P26_2", "P26_3", "P26_4", "P26_5", "P26_6", "P26_7", + "P27_0", "P27_1", "P27_2", "P27_3", "P27_4", "P27_5", "P27_6", "P27_7", + "P28_0", "P28_1", "P28_2", "P28_3", "P28_4", "P28_5", "P28_6", "P28_7", + "P29_0", "P29_1", "P29_2", "P29_3", "P29_4", "P29_5", "P29_6", "P29_7", + "P30_0", "P30_1", "P30_2", "P30_3", "P30_4", "P30_5", "P30_6", "P30_7", + "P31_0", "P31_1", "P31_2", "P31_3", "P31_4", "P31_5", "P31_6", "P31_7", + "P32_0", "P32_1", "P32_2", "P32_3", "P32_4", "P32_5", "P32_6", "P32_7", + "P33_0", "P33_1", "P33_2", "P33_3", "P33_4", "P33_5", "P33_6", "P33_7", + "P34_0", "P34_1", "P34_2", "P34_3", "P34_4", "P34_5", "P34_6", "P34_7", + "P35_0", "P35_1", "P35_2", "P35_3", "P35_4", "P35_5", "P35_6", "P35_7", + "P36_0", "P36_1", "P36_2", "P36_3", "P36_4", "P36_5", "P36_6", "P36_7", + "P37_0", "P37_1", "P37_2", "P37_3", "P37_4", "P37_5", "P37_6", "P37_7", + "P38_0", "P38_1", "P38_2", "P38_3", "P38_4", "P38_5", "P38_6", "P38_7", + "P39_0", "P39_1", "P39_2", "P39_3", "P39_4", "P39_5", "P39_6", "P39_7", + "P40_0", "P40_1", "P40_2", "P40_3", "P40_4", "P40_5", "P40_6", "P40_7", + "P41_0", "P41_1", "P41_2", "P41_3", "P41_4", "P41_5", "P41_6", "P41_7", + "P42_0", "P42_1", "P42_2", "P42_3", "P42_4", "P42_5", "P42_6", "P42_7", + "P43_0", "P43_1", "P43_2", "P43_3", "P43_4", "P43_5", "P43_6", "P43_7", + "P44_0", "P44_1", "P44_2", "P44_3", "P44_4", "P44_5", "P44_6", "P44_7", + "P45_0", "P45_1", "P45_2", "P45_3", "P45_4", "P45_5", "P45_6", "P45_7", + "P46_0", "P46_1", "P46_2", "P46_3", "P46_4", "P46_5", "P46_6", "P46_7", + "P47_0", "P47_1", "P47_2", "P47_3", "P47_4", "P47_5", "P47_6", "P47_7", + "P48_0", "P48_1", "P48_2", "P48_3", "P48_4", "P48_5", "P48_6", "P48_7", +}; + +static const u32 r9a07g044_gpio_configs[] = { + RZG2L_GPIO_PORT_PACK(2, 0x10, RZG2L_MPXED_PIN_FUNCS), + RZG2L_GPIO_PORT_PACK(2, 0x11, RZG2L_MPXED_PIN_FUNCS), + RZG2L_GPIO_PORT_PACK(2, 0x12, RZG2L_MPXED_PIN_FUNCS), + RZG2L_GPIO_PORT_PACK(2, 0x13, RZG2L_MPXED_PIN_FUNCS), + RZG2L_GPIO_PORT_PACK(2, 0x14, RZG2L_MPXED_PIN_FUNCS), + RZG2L_GPIO_PORT_PACK(3, 0x15, RZG2L_MPXED_PIN_FUNCS), + RZG2L_GPIO_PORT_PACK(2, 0x16, RZG2L_MPXED_PIN_FUNCS), + RZG2L_GPIO_PORT_PACK(3, 0x17, RZG2L_MPXED_PIN_FUNCS), + RZG2L_GPIO_PORT_PACK(3, 0x18, RZG2L_MPXED_PIN_FUNCS), + RZG2L_GPIO_PORT_PACK(2, 0x19, RZG2L_MPXED_PIN_FUNCS), + RZG2L_GPIO_PORT_PACK(2, 0x1a, RZG2L_MPXED_PIN_FUNCS), + RZG2L_GPIO_PORT_PACK(2, 0x1b, RZG2L_MPXED_PIN_FUNCS), + RZG2L_GPIO_PORT_PACK(2, 0x1c, RZG2L_MPXED_PIN_FUNCS), + RZG2L_GPIO_PORT_PACK(3, 0x1d, RZG2L_MPXED_PIN_FUNCS), + RZG2L_GPIO_PORT_PACK(2, 0x1e, RZG2L_MPXED_PIN_FUNCS), + RZG2L_GPIO_PORT_PACK(2, 0x1f, RZG2L_MPXED_PIN_FUNCS), + RZG2L_GPIO_PORT_PACK(2, 0x20, RZG2L_MPXED_PIN_FUNCS), + RZG2L_GPIO_PORT_PACK(3, 0x21, RZG2L_MPXED_PIN_FUNCS), + RZG2L_GPIO_PORT_PACK(2, 0x22, RZG2L_MPXED_PIN_FUNCS), + RZG2L_GPIO_PORT_PACK(2, 0x23, RZG2L_MPXED_PIN_FUNCS), + RZG2L_GPIO_PORT_PACK(3, 0x24, RZG2L_MPXED_ETH_PIN_FUNCS(PIN_CFG_IO_VMC_ETH0)), + RZG2L_GPIO_PORT_PACK(2, 0x25, RZG2L_MPXED_ETH_PIN_FUNCS(PIN_CFG_IO_VMC_ETH0)), + RZG2L_GPIO_PORT_PACK(2, 0x26, RZG2L_MPXED_ETH_PIN_FUNCS(PIN_CFG_IO_VMC_ETH0)), + RZG2L_GPIO_PORT_PACK(2, 0x27, RZG2L_MPXED_ETH_PIN_FUNCS(PIN_CFG_IO_VMC_ETH0)), + RZG2L_GPIO_PORT_PACK(2, 0x28, RZG2L_MPXED_ETH_PIN_FUNCS(PIN_CFG_IO_VMC_ETH0)), + RZG2L_GPIO_PORT_PACK(2, 0x29, RZG2L_MPXED_ETH_PIN_FUNCS(PIN_CFG_IO_VMC_ETH0)), + RZG2L_GPIO_PORT_PACK(2, 0x2a, RZG2L_MPXED_ETH_PIN_FUNCS(PIN_CFG_IO_VMC_ETH0)), + RZG2L_GPIO_PORT_PACK(2, 0x2b, RZG2L_MPXED_ETH_PIN_FUNCS(PIN_CFG_IO_VMC_ETH0)), + RZG2L_GPIO_PORT_PACK(2, 0x2c, RZG2L_MPXED_ETH_PIN_FUNCS(PIN_CFG_IO_VMC_ETH0)), + RZG2L_GPIO_PORT_PACK(2, 0x2d, RZG2L_MPXED_ETH_PIN_FUNCS(PIN_CFG_IO_VMC_ETH1)), + RZG2L_GPIO_PORT_PACK(2, 0x2e, RZG2L_MPXED_ETH_PIN_FUNCS(PIN_CFG_IO_VMC_ETH1)), + RZG2L_GPIO_PORT_PACK(2, 0x2f, RZG2L_MPXED_ETH_PIN_FUNCS(PIN_CFG_IO_VMC_ETH1)), + RZG2L_GPIO_PORT_PACK(2, 0x30, RZG2L_MPXED_ETH_PIN_FUNCS(PIN_CFG_IO_VMC_ETH1)), + RZG2L_GPIO_PORT_PACK(2, 0x31, RZG2L_MPXED_ETH_PIN_FUNCS(PIN_CFG_IO_VMC_ETH1)), + RZG2L_GPIO_PORT_PACK(2, 0x32, RZG2L_MPXED_ETH_PIN_FUNCS(PIN_CFG_IO_VMC_ETH1)), + RZG2L_GPIO_PORT_PACK(2, 0x33, RZG2L_MPXED_ETH_PIN_FUNCS(PIN_CFG_IO_VMC_ETH1)), + RZG2L_GPIO_PORT_PACK(2, 0x34, RZG2L_MPXED_ETH_PIN_FUNCS(PIN_CFG_IO_VMC_ETH1)), + RZG2L_GPIO_PORT_PACK(3, 0x35, RZG2L_MPXED_ETH_PIN_FUNCS(PIN_CFG_IO_VMC_ETH1)), + RZG2L_GPIO_PORT_PACK(2, 0x36, RZG2L_MPXED_PIN_FUNCS), + RZG2L_GPIO_PORT_PACK(3, 0x37, RZG2L_MPXED_PIN_FUNCS), + RZG2L_GPIO_PORT_PACK(3, 0x38, RZG2L_MPXED_PIN_FUNCS), + RZG2L_GPIO_PORT_PACK(2, 0x39, RZG2L_MPXED_PIN_FUNCS), + RZG2L_GPIO_PORT_PACK(5, 0x3a, RZG2L_MPXED_PIN_FUNCS), + RZG2L_GPIO_PORT_PACK(4, 0x3b, RZG2L_MPXED_PIN_FUNCS), + RZG2L_GPIO_PORT_PACK(4, 0x3c, RZG2L_MPXED_PIN_FUNCS), + RZG2L_GPIO_PORT_PACK(4, 0x3d, RZG2L_MPXED_PIN_FUNCS), + RZG2L_GPIO_PORT_PACK(4, 0x3e, RZG2L_MPXED_PIN_FUNCS), + RZG2L_GPIO_PORT_PACK(4, 0x3f, RZG2L_MPXED_PIN_FUNCS), + RZG2L_GPIO_PORT_PACK(5, 0x40, RZG2L_MPXED_PIN_FUNCS), +}; + +static const struct { + struct rzg2l_dedicated_configs common[35]; + struct rzg2l_dedicated_configs rzg2l_pins[7]; +} rzg2l_dedicated_pins = { + .common = { + { "NMI", RZG2L_SINGLE_PIN_PACK(0x1, 0, + (PIN_CFG_FILONOFF | PIN_CFG_FILNUM | PIN_CFG_FILCLKSEL)) }, + { "TMS/SWDIO", RZG2L_SINGLE_PIN_PACK(0x2, 0, + (PIN_CFG_IOLH_A | PIN_CFG_SR | PIN_CFG_IEN)) }, + { "TDO", RZG2L_SINGLE_PIN_PACK(0x3, 0, + (PIN_CFG_IOLH_A | PIN_CFG_SR | PIN_CFG_IEN)) }, + { "AUDIO_CLK1", RZG2L_SINGLE_PIN_PACK(0x4, 0, PIN_CFG_IEN) }, + { "AUDIO_CLK2", RZG2L_SINGLE_PIN_PACK(0x4, 1, PIN_CFG_IEN) }, + { "SD0_CLK", RZG2L_SINGLE_PIN_PACK(0x6, 0, + (PIN_CFG_IOLH_B | PIN_CFG_SR | PIN_CFG_IO_VMC_SD0)) }, + { "SD0_CMD", RZG2L_SINGLE_PIN_PACK(0x6, 1, + (PIN_CFG_IOLH_B | PIN_CFG_SR | PIN_CFG_IEN | PIN_CFG_IO_VMC_SD0)) }, + { "SD0_RST#", RZG2L_SINGLE_PIN_PACK(0x6, 2, + (PIN_CFG_IOLH_B | PIN_CFG_SR | PIN_CFG_IO_VMC_SD0)) }, + { "SD0_DATA0", RZG2L_SINGLE_PIN_PACK(0x7, 0, + (PIN_CFG_IOLH_B | PIN_CFG_SR | PIN_CFG_IEN | PIN_CFG_IO_VMC_SD0)) }, + { "SD0_DATA1", RZG2L_SINGLE_PIN_PACK(0x7, 1, + (PIN_CFG_IOLH_B | PIN_CFG_SR | PIN_CFG_IEN | PIN_CFG_IO_VMC_SD0)) }, + { "SD0_DATA2", RZG2L_SINGLE_PIN_PACK(0x7, 2, + (PIN_CFG_IOLH_B | PIN_CFG_SR | PIN_CFG_IEN | PIN_CFG_IO_VMC_SD0)) }, + { "SD0_DATA3", RZG2L_SINGLE_PIN_PACK(0x7, 3, + (PIN_CFG_IOLH_B | PIN_CFG_SR | PIN_CFG_IEN | PIN_CFG_IO_VMC_SD0)) }, + { "SD0_DATA4", RZG2L_SINGLE_PIN_PACK(0x7, 4, + (PIN_CFG_IOLH_B | PIN_CFG_SR | PIN_CFG_IEN | PIN_CFG_IO_VMC_SD0)) }, + { "SD0_DATA5", RZG2L_SINGLE_PIN_PACK(0x7, 5, + (PIN_CFG_IOLH_B | PIN_CFG_SR | PIN_CFG_IEN | PIN_CFG_IO_VMC_SD0)) }, + { "SD0_DATA6", RZG2L_SINGLE_PIN_PACK(0x7, 6, + (PIN_CFG_IOLH_B | PIN_CFG_SR | PIN_CFG_IEN | PIN_CFG_IO_VMC_SD0)) }, + { "SD0_DATA7", RZG2L_SINGLE_PIN_PACK(0x7, 7, + (PIN_CFG_IOLH_B | PIN_CFG_SR | PIN_CFG_IEN | PIN_CFG_IO_VMC_SD0)) }, + { "SD1_CLK", RZG2L_SINGLE_PIN_PACK(0x8, 0, + (PIN_CFG_IOLH_B | PIN_CFG_SR | PIN_CFG_IO_VMC_SD1)) }, + { "SD1_CMD", RZG2L_SINGLE_PIN_PACK(0x8, 1, + (PIN_CFG_IOLH_B | PIN_CFG_SR | PIN_CFG_IEN | PIN_CFG_IO_VMC_SD1)) }, + { "SD1_DATA0", RZG2L_SINGLE_PIN_PACK(0x9, 0, + (PIN_CFG_IOLH_B | PIN_CFG_SR | PIN_CFG_IEN | PIN_CFG_IO_VMC_SD1)) }, + { "SD1_DATA1", RZG2L_SINGLE_PIN_PACK(0x9, 1, + (PIN_CFG_IOLH_B | PIN_CFG_SR | PIN_CFG_IEN | PIN_CFG_IO_VMC_SD1)) }, + { "SD1_DATA2", RZG2L_SINGLE_PIN_PACK(0x9, 2, + (PIN_CFG_IOLH_B | PIN_CFG_SR | PIN_CFG_IEN | PIN_CFG_IO_VMC_SD1)) }, + { "SD1_DATA3", RZG2L_SINGLE_PIN_PACK(0x9, 3, + (PIN_CFG_IOLH_B | PIN_CFG_SR | PIN_CFG_IEN | PIN_CFG_IO_VMC_SD1)) }, + { "QSPI0_SPCLK", RZG2L_SINGLE_PIN_PACK(0xa, 0, + (PIN_CFG_IOLH_B | PIN_CFG_SR | PIN_CFG_IO_VMC_QSPI)) }, + { "QSPI0_IO0", RZG2L_SINGLE_PIN_PACK(0xa, 1, + (PIN_CFG_IOLH_B | PIN_CFG_SR | PIN_CFG_IO_VMC_QSPI)) }, + { "QSPI0_IO1", RZG2L_SINGLE_PIN_PACK(0xa, 2, + (PIN_CFG_IOLH_B | PIN_CFG_SR | PIN_CFG_IO_VMC_QSPI)) }, + { "QSPI0_IO2", RZG2L_SINGLE_PIN_PACK(0xa, 3, + (PIN_CFG_IOLH_B | PIN_CFG_SR | PIN_CFG_IO_VMC_QSPI)) }, + { "QSPI0_IO3", RZG2L_SINGLE_PIN_PACK(0xa, 4, + (PIN_CFG_IOLH_B | PIN_CFG_SR | PIN_CFG_IO_VMC_QSPI)) }, + { "QSPI0_SSL", RZG2L_SINGLE_PIN_PACK(0xa, 5, + (PIN_CFG_IOLH_B | PIN_CFG_SR | PIN_CFG_IO_VMC_QSPI)) }, + { "QSPI_RESET#", RZG2L_SINGLE_PIN_PACK(0xc, 0, + (PIN_CFG_IOLH_B | PIN_CFG_SR | PIN_CFG_IO_VMC_QSPI)) }, + { "QSPI_WP#", RZG2L_SINGLE_PIN_PACK(0xc, 1, + (PIN_CFG_IOLH_B | PIN_CFG_SR | PIN_CFG_IO_VMC_QSPI)) }, + { "WDTOVF_PERROUT#", RZG2L_SINGLE_PIN_PACK(0xd, 0, (PIN_CFG_IOLH_A | PIN_CFG_SR)) }, + { "RIIC0_SDA", RZG2L_SINGLE_PIN_PACK(0xe, 0, PIN_CFG_IEN) }, + { "RIIC0_SCL", RZG2L_SINGLE_PIN_PACK(0xe, 1, PIN_CFG_IEN) }, + { "RIIC1_SDA", RZG2L_SINGLE_PIN_PACK(0xe, 2, PIN_CFG_IEN) }, + { "RIIC1_SCL", RZG2L_SINGLE_PIN_PACK(0xe, 3, PIN_CFG_IEN) }, + }, + .rzg2l_pins = { + { "QSPI_INT#", RZG2L_SINGLE_PIN_PACK(0xc, 2, (PIN_CFG_SR | PIN_CFG_IO_VMC_QSPI)) }, + { "QSPI1_SPCLK", RZG2L_SINGLE_PIN_PACK(0xb, 0, + (PIN_CFG_IOLH_B | PIN_CFG_SR | PIN_CFG_IO_VMC_QSPI)) }, + { "QSPI1_IO0", RZG2L_SINGLE_PIN_PACK(0xb, 1, + (PIN_CFG_IOLH_B | PIN_CFG_SR | PIN_CFG_IO_VMC_QSPI)) }, + { "QSPI1_IO1", RZG2L_SINGLE_PIN_PACK(0xb, 2, + (PIN_CFG_IOLH_B | PIN_CFG_SR | PIN_CFG_IO_VMC_QSPI)) }, + { "QSPI1_IO2", RZG2L_SINGLE_PIN_PACK(0xb, 3, + (PIN_CFG_IOLH_B | PIN_CFG_SR | PIN_CFG_IO_VMC_QSPI)) }, + { "QSPI1_IO3", RZG2L_SINGLE_PIN_PACK(0xb, 4, + (PIN_CFG_IOLH_B | PIN_CFG_SR | PIN_CFG_IO_VMC_QSPI)) }, + { "QSPI1_SSL", RZG2L_SINGLE_PIN_PACK(0xb, 5, + (PIN_CFG_IOLH_B | PIN_CFG_SR | PIN_CFG_IO_VMC_QSPI)) }, + } +}; + +static void rzg2l_rmw_pin_config(struct rzg2l_pfc_data *data, u32 offset, + u8 pin, u32 mask, u32 val) +{ + void __iomem *addr = data->base + offset; + u32 reg; + + /* handle _L/_H for 32-bit register read/write */ + if (pin >= 4) { + pin -= 4; + addr += 4; + } + + reg = readl(addr) & ~(mask << (pin * 8)); + writel(reg | (val << (pin * 8)), addr); +} + +static int rzg2l_get_pins_count(struct udevice *dev) +{ + struct rzg2l_pfc_data *data = + (struct rzg2l_pfc_data *)dev_get_driver_data(dev); + + return data->num_dedicated_pins + data->num_pins; +} + +static const char *rzg2l_get_pin_name(struct udevice *dev, unsigned int selector) +{ + struct rzg2l_pfc_data *data = + (struct rzg2l_pfc_data *)dev_get_driver_data(dev); + int port; + u8 pin; + + if (selector < data->num_dedicated_pins) { + if (selector >= ARRAY_SIZE(rzg2l_dedicated_pins.common)) { + unsigned int u = selector - ARRAY_SIZE(rzg2l_dedicated_pins.common); + return rzg2l_dedicated_pins.rzg2l_pins[u].name; + } else { + return rzg2l_dedicated_pins.common[selector].name; + } + } + + port = rzg2l_selector_decode(data, selector, &pin); + if (port < 0) + return "(invalid pin)"; + return rzg2l_gpio_names[pin + 8 * port]; +} + +static int rzg2l_pinconf_set(struct udevice *dev, unsigned int pin_selector, + unsigned int param, unsigned int argument) +{ + struct rzg2l_pfc_data *data = + (struct rzg2l_pfc_data *)dev_get_driver_data(dev); + u32 cfg, port_offset; + u8 pin; + + if (pin_selector >= data->num_dedicated_pins) { + /* The pin selector refers to a multiplexed pin */ + int port = rzg2l_selector_decode(data, pin_selector, &pin); + if (port < 0) { + dev_err(dev, "Invalid pin selector %u:%u\n", port, pin); + return port; + } + + cfg = data->gpio_configs[port]; + port_offset = port + 0x10; + } else { + /* The pin selector refers to a dedicated function pin */ + const struct rzg2l_dedicated_configs *dedicated_config; + + if (pin_selector >= data->num_dedicated_pins) { + dev_err(dev, "Invalid dedicated pin %u\n", pin_selector); + return -EINVAL; + } + + if (pin_selector >= ARRAY_SIZE(rzg2l_dedicated_pins.common)) { + pin_selector -= ARRAY_SIZE(rzg2l_dedicated_pins.common); + dedicated_config = &rzg2l_dedicated_pins.rzg2l_pins[pin_selector]; + } else { + dedicated_config = &rzg2l_dedicated_pins.common[pin_selector]; + } + + port_offset = RZG2L_SINGLE_PIN_GET_PORT_OFFSET(dedicated_config->config); + pin = RZG2L_SINGLE_PIN_GET_BIT(dedicated_config->config); + cfg = RZG2L_SINGLE_PIN_GET_CFGS(dedicated_config->config); + } + + switch (param) { + case PIN_CONFIG_INPUT_ENABLE: { + if (!(cfg & PIN_CFG_IEN)) { + dev_err(dev, "pin does not support IEN\n"); + return -EINVAL; + } + + dev_dbg(dev, "port off %u:%u set IEN=%u\n", + port_offset, pin, argument); + rzg2l_rmw_pin_config(data, IEN(port_offset), pin, IEN_MASK, !!argument); + break; + } + + case PIN_CONFIG_POWER_SOURCE: { + void __iomem *addr; + u32 pwr_reg = 0x0; + + /* argument is in mV */ + if (argument != 1800 && argument != 3300) { + dev_err(dev, "Invalid mV %u\n", argument); + return -EINVAL; + } + + if (cfg & PIN_CFG_IO_VMC_SD0) { + dev_dbg(dev, "port off %u:%u set SD_CH 0 PVDD=%u\n", + port_offset, pin, argument); + pwr_reg = SD_CH(0); + } else if (cfg & PIN_CFG_IO_VMC_SD1) { + dev_dbg(dev, "port off %u:%u set SD_CH 1 PVDD=%u\n", + port_offset, pin, argument); + pwr_reg = SD_CH(1); + } else if (cfg & PIN_CFG_IO_VMC_QSPI) { + dev_dbg(dev, "port off %u:%u set QSPI PVDD=%u\n", + port_offset, pin, argument); + pwr_reg = QSPI; + } else { + dev_dbg(dev, "pin power source is not selectable\n"); + return -EINVAL; + } + + addr = data->base + pwr_reg; + writel((argument == 1800) ? PVDD_1800 : PVDD_3300, addr); + break; + } + + default: + dev_err(dev, "Invalid pinconf parameter\n"); + return -EOPNOTSUPP; + } + + return 0; +} + +static int rzg2l_pinmux_property_set(struct udevice *dev, u32 pinmux_group) +{ + struct rzg2l_pfc_data *data = + (struct rzg2l_pfc_data *)dev_get_driver_data(dev); + u32 port, pin, func, pfc_state, reg; + u8 pmc_state; + + func = RZG2L_PINMUX_TO_FUNC(pinmux_group); + if (func > 5) { + dev_err(dev, "Invalid pin function %u\n", func); + return -EINVAL; + } + + port = RZG2L_PINMUX_TO_PORT(pinmux_group); + pin = RZG2L_PINMUX_TO_PIN(pinmux_group); + if (!rzg2l_port_validate(data, port, pin)) { + dev_err(dev, "Invalid pin selector %u:%u\n", port, pin); + return -EINVAL; + } + + /* Check current PMC & PFC to decide if we need to change anything. */ + pmc_state = readb(data->base + PMC(port)) & BIT(pin); + pfc_state = (readl(data->base + PFC(port)) >> (pin * 4)) & PFC_MASK; + if (pmc_state && pfc_state == func) + return 0; + + dev_dbg(dev, "pinmux port %u pin %u func %u\n", port, pin, func); + + /* Set pin to 'Non-use (Hi-Z input protection)' */ + reg = readw(data->base + PM(port)); + reg &= ~(PM_MASK << (pin * 2)); + writew(reg, data->base + PM(port)); + + /* Temporarily switch to GPIO mode with PMC register */ + reg = readb(data->base + PMC(port)); + writeb(reg & ~BIT(pin), data->base + PMC(port)); + + /* Set the PWPR register to allow PFC register to write */ + writel(0x0, data->base + PWPR); /* B0WI=0, PFCWE=0 */ + writel(PWPR_PFCWE, data->base + PWPR); /* B0WI=0, PFCWE=1 */ + + /* Select Pin function mode with PFC register */ + reg = readl(data->base + PFC(port)); + reg &= ~(PFC_MASK << (pin * 4)); + writel(reg | (func << (pin * 4)), data->base + PFC(port)); + + /* Set the PWPR register to be write-protected */ + writel(0x0, data->base + PWPR); /* B0WI=0, PFCWE=0 */ + writel(PWPR_B0WI, data->base + PWPR); /* B0WI=1, PFCWE=0 */ + + /* Switch to Peripheral pin function with PMC register */ + reg = readb(data->base + PMC(port)); + writeb(reg | BIT(pin), data->base + PMC(port)); + + return rzg2l_selector_encode(data, port, pin); +} + +static int rzg2l_get_pin_muxing(struct udevice *dev, unsigned int selector, + char *buf, int size) +{ + struct rzg2l_pfc_data *data = + (struct rzg2l_pfc_data *)dev_get_driver_data(dev); + u32 pmc_state; + int port; + u8 pin; + + if (selector < data->num_dedicated_pins) { + snprintf(buf, size, rzg2l_get_pin_name(dev, selector)); + return 0; + } + + port = rzg2l_selector_decode(data, selector, &pin); + if (port < 0) { + dev_err(dev, "Invalid pin selector %u:%u\n", port, pin); + return port; + } + + pmc_state = readb(data->base + PMC(port)) & BIT(pin); + if (pmc_state) { + u32 pfc_state = (readl(data->base + PFC(port)) >> (pin * 4)) & PFC_MASK; + snprintf(buf, size, "Function %d", pfc_state); + return 0; + } + + snprintf(buf, size, "GPIO"); + return 0; +} + +static const struct pinconf_param rzg2l_pinconf_params[] = { + { "input-enable", PIN_CONFIG_INPUT_ENABLE, 1 }, + { "power-source", PIN_CONFIG_POWER_SOURCE, 3300 /* mV */ }, +}; + +static const struct pinctrl_ops rzg2l_pinctrl_ops = { + .get_pins_count = rzg2l_get_pins_count, + .get_pin_name = rzg2l_get_pin_name, + + .pinconf_num_params = ARRAY_SIZE(rzg2l_pinconf_params), + .pinconf_params = rzg2l_pinconf_params, + .pinconf_set = rzg2l_pinconf_set, + + .pinmux_property_set = rzg2l_pinmux_property_set, + .set_state = pinctrl_generic_set_state, + .get_pin_muxing = rzg2l_get_pin_muxing, +}; + +static int rzg2l_pinctrl_probe(struct udevice *dev) +{ + return rzg2l_pfc_enable(dev); +} + +U_BOOT_DRIVER(rzg2l_pfc_pinctrl) = { + .name = "rzg2l-pfc-pinctrl", + .id = UCLASS_PINCTRL, + .ops = &rzg2l_pinctrl_ops, + .probe = rzg2l_pinctrl_probe, +}; + +static const struct rzg2l_pfc_driver_data r9a07g044_driver_data = { + .num_dedicated_pins = ARRAY_SIZE(rzg2l_dedicated_pins.common) + + ARRAY_SIZE(rzg2l_dedicated_pins.rzg2l_pins), + .num_ports = ARRAY_SIZE(r9a07g044_gpio_configs), + .gpio_configs = r9a07g044_gpio_configs, +}; + +static const struct udevice_id rzg2l_pfc_ids[] = { + { .compatible = "renesas,r9a07g044-pinctrl", .data = (ulong)&r9a07g044_driver_data }, + { /* sentinel */ } +}; + +static int rzg2l_pfc_bind(struct udevice *parent) +{ + struct rzg2l_pfc_driver_data *driver_data; + struct udevice *gpio_dev, *pinctrl_dev; + struct rzg2l_pfc_data *data; + struct driver *drv; + unsigned int i; + int ret; + + driver_data = + (struct rzg2l_pfc_driver_data *)dev_get_driver_data(parent); + if (!driver_data) + return -EINVAL; + data = devm_kmalloc(parent, sizeof(*data), 0); + if (!data) + return -ENOMEM; + + data->base = dev_read_addr_ptr(parent); + if (!data->base) + return -EINVAL; + data->num_dedicated_pins = driver_data->num_dedicated_pins; + data->num_ports = driver_data->num_ports; + data->gpio_configs = driver_data->gpio_configs; + data->pfc_enabled = false; + + data->num_pins = 0; + for (i = 0; i < data->num_ports; i++) + data->num_pins += RZG2L_GPIO_PORT_GET_PINCNT(data->gpio_configs[i]); + dev_dbg(parent, "%u dedicated pins, %u muxed ports, %u muxed pins\n", + data->num_dedicated_pins, data->num_ports, data->num_pins); + + drv = lists_driver_lookup_name("rzg2l-pfc-gpio"); + if (!drv) + return -ENOENT; + + ret = device_bind_with_driver_data(parent, drv, parent->name, + (ulong)data, dev_ofnode(parent), + &gpio_dev); + if (ret) + return ret; + + drv = lists_driver_lookup_name("rzg2l-pfc-pinctrl"); + if (!drv) { + device_unbind(gpio_dev); + return -ENOENT; + } + + ret = device_bind_with_driver_data(parent, drv, parent->name, + (ulong)data, dev_ofnode(parent), + &pinctrl_dev); + if (ret) + device_unbind(gpio_dev); + + return ret; +} + +U_BOOT_DRIVER(rzg2l_pfc) = { + .name = "rzg2l-pfc", + .id = UCLASS_NOP, + .of_match = rzg2l_pfc_ids, + .bind = rzg2l_pfc_bind, +};

On 9/20/23 14:42, Paul Barker wrote:
This driver provides pinctrl and gpio control for the Renesas RZ/G2L (R9A07G044) SoC.
This patch is based on the corresponding Linux v6.5 driver.
Signed-off-by: Paul Barker paul.barker.ct@bp.renesas.com Reviewed-by: Biju Das biju.das.jz@bp.renesas.com Reviewed-by: Lad Prabhakar prabhakar.mahadev-lad.rj@bp.renesas.com
arch/arm/mach-rmobile/Kconfig | 1 + drivers/pinctrl/renesas/Kconfig | 9 + drivers/pinctrl/renesas/Makefile | 1 + drivers/pinctrl/renesas/rzg2l-pfc.c | 906 ++++++++++++++++++++++++++++ 4 files changed, 917 insertions(+) create mode 100644 drivers/pinctrl/renesas/rzg2l-pfc.c
diff --git a/arch/arm/mach-rmobile/Kconfig b/arch/arm/mach-rmobile/Kconfig index 91f544c78337..973e84fcf7ba 100644 --- a/arch/arm/mach-rmobile/Kconfig +++ b/arch/arm/mach-rmobile/Kconfig @@ -76,6 +76,7 @@ config RZG2L imply SYS_MALLOC_F imply RENESAS_SDHI imply CLK_RZG2L
- imply PINCTRL_RZG2L
Keep the list sorted
[...]
Drop the parenthesis around values please, fix globally and in other patches too.
+#define PWPR (0x3014) +#define SD_CH(n) (0x3000 + (n) * 4) +#define QSPI (0x3008)
+#define PVDD_1800 1 /* I/O domain voltage <= 1.8V */ +#define PVDD_3300 0 /* I/O domain voltage >= 3.3V */
+#define PWPR_B0WI BIT(7) /* Bit Write Disable */ +#define PWPR_PFCWE BIT(6) /* PFC Register Write Enable */
+#define PM_MASK 0x03 +#define PVDD_MASK 0x01 +#define PFC_MASK 0x07 +#define IEN_MASK 0x01 +#define IOLH_MASK 0x03
+#define PM_HIGH_Z 0x0 +#define PM_INPUT 0x1 +#define PM_OUTPUT 0x2 +#define PM_OUTPUT_IEN 0x3
+struct rzg2l_pfc_driver_data {
- uint num_dedicated_pins;
- uint num_ports;
- const u32 *gpio_configs;
+};
+struct rzg2l_pfc_data {
- void __iomem *base;
- uint num_dedicated_pins;
- uint num_ports;
- uint num_pins;
- const u32 *gpio_configs;
- bool pfc_enabled;
+};
+struct rzg2l_dedicated_configs {
- const char *name;
- u32 config;
+};
+/*
- We need to ensure that the module clock is enabled and all resets are
- de-asserted before using either the gpio or pinctrl functionality. Error
- handling can be quite simple here as if the PFC cannot be enabled then we
- will not be able to progress with the boot anyway.
- */
+static int rzg2l_pfc_enable(struct udevice *dev) +{
- struct rzg2l_pfc_data *data =
(struct rzg2l_pfc_data *)dev_get_driver_data(dev);
- struct reset_ctl_bulk rsts;
- struct clk clk;
- int ret;
- if (data->pfc_enabled)
When does this get triggered ?
return 0;
[...]
+static int rzg2l_gpio_set_value(struct udevice *dev, unsigned int offset,
int value)
+{
- struct rzg2l_pfc_data *data =
(struct rzg2l_pfc_data *)dev_get_driver_data(dev);
- u32 port = RZG2L_PINMUX_TO_PORT(offset);
- u8 pin = RZG2L_PINMUX_TO_PIN(offset);
A lot of this can also be const
- rzg2l_gpio_set(data, port, pin, (bool)value);
- return 0;
+}
+static void rzg2l_gpio_set_direction(struct rzg2l_pfc_data *data,
u32 port, u8 pin, bool output)
+{
- u16 reg16;
- reg16 = readw(data->base + PM(port));
- reg16 &= ~(PM_MASK << (pin * 2));
See clrsetbits_le32() function and co .
- reg16 |= (output ? PM_OUTPUT : PM_INPUT) << (pin * 2);
- writew(reg16, data->base + PM(port));
+}
+static int rzg2l_gpio_direction_input(struct udevice *dev, unsigned int offset) +{
- struct rzg2l_pfc_data *data =
(struct rzg2l_pfc_data *)dev_get_driver_data(dev);
- u32 port = RZG2L_PINMUX_TO_PORT(offset);
- u8 pin = RZG2L_PINMUX_TO_PIN(offset);
- rzg2l_gpio_set_direction(data, port, pin, false);
- return 0;
+}
+static int rzg2l_gpio_direction_output(struct udevice *dev, unsigned int offset,
int value)
+{
- struct rzg2l_pfc_data *data =
(struct rzg2l_pfc_data *)dev_get_driver_data(dev);
- u32 port = RZG2L_PINMUX_TO_PORT(offset);
- u8 pin = RZG2L_PINMUX_TO_PIN(offset);
- rzg2l_gpio_set(data, port, pin, (bool)value);
- rzg2l_gpio_set_direction(data, port, pin, true);
- return 0;
+}
+static int rzg2l_gpio_request(struct udevice *dev, unsigned int offset,
const char *label)
+{
- struct rzg2l_pfc_data *data =
(struct rzg2l_pfc_data *)dev_get_driver_data(dev);
- u32 port = RZG2L_PINMUX_TO_PORT(offset);
- u8 pin = RZG2L_PINMUX_TO_PIN(offset);
- u8 reg8;
- if (!rzg2l_port_validate(data, port, pin)) {
dev_err(dev, "Invalid GPIO %u:%u\n", port, pin);
return -EINVAL;
- }
- /* Select GPIO mode in PMC Register */
- reg8 = readb(data->base + PMC(port));
- reg8 &= ~BIT(pin);
- writeb(reg8, data->base + PMC(port));
clrbits here too
- return 0;
+}
+static int rzg2l_gpio_get_function(struct udevice *dev, unsigned int offset) +{
- struct rzg2l_pfc_data *data =
(struct rzg2l_pfc_data *)dev_get_driver_data(dev);
- u32 port = RZG2L_PINMUX_TO_PORT(offset);
- u8 pin = RZG2L_PINMUX_TO_PIN(offset);
- u16 pm_state;
- u8 pmc_state;
- if (!rzg2l_port_validate(data, port, pin)) {
/* Running `gpio status -a` at the u-boot command line will
* iterate through all GPIO offsets with no understanding of
* which are valid and which are not. So we need to return
* something meaningful even for the invalid GPIOs.
*/
return GPIOF_UNKNOWN;
Would it make sense to add some GPIOF_SKIP flag and handle it in the command to avoid displaying invalid GPIOs ?
- }
- /* Check if the pin is in GPIO or function mode. */
- pmc_state = readb(data->base + PMC(port)) & BIT(pin);
- if (pmc_state)
return GPIOF_FUNC;
- /* Check the pin direction. */
- pm_state = (readw(data->base + PM(port)) >> (pin * 2)) & PM_MASK;
- switch (pm_state) {
- case PM_INPUT:
return GPIOF_INPUT;
- case PM_OUTPUT:
- case PM_OUTPUT_IEN:
return GPIOF_OUTPUT;
- default: /* PM_HIGH_Z */
return GPIOF_UNUSED;
- }
+}
+static const struct dm_gpio_ops rzg2l_gpio_ops = {
- .direction_input = rzg2l_gpio_direction_input,
- .direction_output = rzg2l_gpio_direction_output,
- .get_value = rzg2l_gpio_get_value,
- .set_value = rzg2l_gpio_set_value,
- .request = rzg2l_gpio_request,
- .get_function = rzg2l_gpio_get_function,
+};
+static int rzg2l_gpio_probe(struct udevice *dev) +{
- struct gpio_dev_priv *uc_priv = dev_get_uclass_priv(dev);
- struct ofnode_phandle_args args;
- int ret;
- uc_priv->bank_name = "rzg2l-pfc-gpio";
- ret = ofnode_parse_phandle_with_args(dev_ofnode(dev), "gpio-ranges",
NULL, 3, 0, &args);
- if (ret < 0) {
dev_err(dev, "Failed to parse gpio-ranges\n");
It is a good idea to include the return value in error message to ease debugging.
return -EINVAL;
- }
- uc_priv->gpio_count = args.args[2];
- return rzg2l_pfc_enable(dev);
+}
+U_BOOT_DRIVER(rzg2l_pfc_gpio) = {
- .name = "rzg2l-pfc-gpio",
- .id = UCLASS_GPIO,
- .ops = &rzg2l_gpio_ops,
- .probe = rzg2l_gpio_probe,
+};
Can you please split the GPIO and PFC drivers into separate files ?
+static const char * const rzg2l_gpio_names[] = {
- "P0_0", "P0_1", "P0_2", "P0_3", "P0_4", "P0_5", "P0_6", "P0_7",
- "P1_0", "P1_1", "P1_2", "P1_3", "P1_4", "P1_5", "P1_6", "P1_7",
- "P2_0", "P2_1", "P2_2", "P2_3", "P2_4", "P2_5", "P2_6", "P2_7",
- "P3_0", "P3_1", "P3_2", "P3_3", "P3_4", "P3_5", "P3_6", "P3_7",
- "P4_0", "P4_1", "P4_2", "P4_3", "P4_4", "P4_5", "P4_6", "P4_7",
- "P5_0", "P5_1", "P5_2", "P5_3", "P5_4", "P5_5", "P5_6", "P5_7",
- "P6_0", "P6_1", "P6_2", "P6_3", "P6_4", "P6_5", "P6_6", "P6_7",
- "P7_0", "P7_1", "P7_2", "P7_3", "P7_4", "P7_5", "P7_6", "P7_7",
- "P8_0", "P8_1", "P8_2", "P8_3", "P8_4", "P8_5", "P8_6", "P8_7",
- "P9_0", "P9_1", "P9_2", "P9_3", "P9_4", "P9_5", "P9_6", "P9_7",
- "P10_0", "P10_1", "P10_2", "P10_3", "P10_4", "P10_5", "P10_6", "P10_7",
- "P11_0", "P11_1", "P11_2", "P11_3", "P11_4", "P11_5", "P11_6", "P11_7",
- "P12_0", "P12_1", "P12_2", "P12_3", "P12_4", "P12_5", "P12_6", "P12_7",
- "P13_0", "P13_1", "P13_2", "P13_3", "P13_4", "P13_5", "P13_6", "P13_7",
- "P14_0", "P14_1", "P14_2", "P14_3", "P14_4", "P14_5", "P14_6", "P14_7",
- "P15_0", "P15_1", "P15_2", "P15_3", "P15_4", "P15_5", "P15_6", "P15_7",
- "P16_0", "P16_1", "P16_2", "P16_3", "P16_4", "P16_5", "P16_6", "P16_7",
- "P17_0", "P17_1", "P17_2", "P17_3", "P17_4", "P17_5", "P17_6", "P17_7",
- "P18_0", "P18_1", "P18_2", "P18_3", "P18_4", "P18_5", "P18_6", "P18_7",
- "P19_0", "P19_1", "P19_2", "P19_3", "P19_4", "P19_5", "P19_6", "P19_7",
- "P20_0", "P20_1", "P20_2", "P20_3", "P20_4", "P20_5", "P20_6", "P20_7",
- "P21_0", "P21_1", "P21_2", "P21_3", "P21_4", "P21_5", "P21_6", "P21_7",
- "P22_0", "P22_1", "P22_2", "P22_3", "P22_4", "P22_5", "P22_6", "P22_7",
- "P23_0", "P23_1", "P23_2", "P23_3", "P23_4", "P23_5", "P23_6", "P23_7",
- "P24_0", "P24_1", "P24_2", "P24_3", "P24_4", "P24_5", "P24_6", "P24_7",
- "P25_0", "P25_1", "P25_2", "P25_3", "P25_4", "P25_5", "P25_6", "P25_7",
- "P26_0", "P26_1", "P26_2", "P26_3", "P26_4", "P26_5", "P26_6", "P26_7",
- "P27_0", "P27_1", "P27_2", "P27_3", "P27_4", "P27_5", "P27_6", "P27_7",
- "P28_0", "P28_1", "P28_2", "P28_3", "P28_4", "P28_5", "P28_6", "P28_7",
- "P29_0", "P29_1", "P29_2", "P29_3", "P29_4", "P29_5", "P29_6", "P29_7",
- "P30_0", "P30_1", "P30_2", "P30_3", "P30_4", "P30_5", "P30_6", "P30_7",
- "P31_0", "P31_1", "P31_2", "P31_3", "P31_4", "P31_5", "P31_6", "P31_7",
- "P32_0", "P32_1", "P32_2", "P32_3", "P32_4", "P32_5", "P32_6", "P32_7",
- "P33_0", "P33_1", "P33_2", "P33_3", "P33_4", "P33_5", "P33_6", "P33_7",
- "P34_0", "P34_1", "P34_2", "P34_3", "P34_4", "P34_5", "P34_6", "P34_7",
- "P35_0", "P35_1", "P35_2", "P35_3", "P35_4", "P35_5", "P35_6", "P35_7",
- "P36_0", "P36_1", "P36_2", "P36_3", "P36_4", "P36_5", "P36_6", "P36_7",
- "P37_0", "P37_1", "P37_2", "P37_3", "P37_4", "P37_5", "P37_6", "P37_7",
- "P38_0", "P38_1", "P38_2", "P38_3", "P38_4", "P38_5", "P38_6", "P38_7",
- "P39_0", "P39_1", "P39_2", "P39_3", "P39_4", "P39_5", "P39_6", "P39_7",
- "P40_0", "P40_1", "P40_2", "P40_3", "P40_4", "P40_5", "P40_6", "P40_7",
- "P41_0", "P41_1", "P41_2", "P41_3", "P41_4", "P41_5", "P41_6", "P41_7",
- "P42_0", "P42_1", "P42_2", "P42_3", "P42_4", "P42_5", "P42_6", "P42_7",
- "P43_0", "P43_1", "P43_2", "P43_3", "P43_4", "P43_5", "P43_6", "P43_7",
- "P44_0", "P44_1", "P44_2", "P44_3", "P44_4", "P44_5", "P44_6", "P44_7",
- "P45_0", "P45_1", "P45_2", "P45_3", "P45_4", "P45_5", "P45_6", "P45_7",
- "P46_0", "P46_1", "P46_2", "P46_3", "P46_4", "P46_5", "P46_6", "P46_7",
- "P47_0", "P47_1", "P47_2", "P47_3", "P47_4", "P47_5", "P47_6", "P47_7",
- "P48_0", "P48_1", "P48_2", "P48_3", "P48_4", "P48_5", "P48_6", "P48_7",
+};
+static const u32 r9a07g044_gpio_configs[] = {
- RZG2L_GPIO_PORT_PACK(2, 0x10, RZG2L_MPXED_PIN_FUNCS),
- RZG2L_GPIO_PORT_PACK(2, 0x11, RZG2L_MPXED_PIN_FUNCS),
- RZG2L_GPIO_PORT_PACK(2, 0x12, RZG2L_MPXED_PIN_FUNCS),
- RZG2L_GPIO_PORT_PACK(2, 0x13, RZG2L_MPXED_PIN_FUNCS),
- RZG2L_GPIO_PORT_PACK(2, 0x14, RZG2L_MPXED_PIN_FUNCS),
- RZG2L_GPIO_PORT_PACK(3, 0x15, RZG2L_MPXED_PIN_FUNCS),
- RZG2L_GPIO_PORT_PACK(2, 0x16, RZG2L_MPXED_PIN_FUNCS),
- RZG2L_GPIO_PORT_PACK(3, 0x17, RZG2L_MPXED_PIN_FUNCS),
- RZG2L_GPIO_PORT_PACK(3, 0x18, RZG2L_MPXED_PIN_FUNCS),
- RZG2L_GPIO_PORT_PACK(2, 0x19, RZG2L_MPXED_PIN_FUNCS),
- RZG2L_GPIO_PORT_PACK(2, 0x1a, RZG2L_MPXED_PIN_FUNCS),
- RZG2L_GPIO_PORT_PACK(2, 0x1b, RZG2L_MPXED_PIN_FUNCS),
- RZG2L_GPIO_PORT_PACK(2, 0x1c, RZG2L_MPXED_PIN_FUNCS),
- RZG2L_GPIO_PORT_PACK(3, 0x1d, RZG2L_MPXED_PIN_FUNCS),
- RZG2L_GPIO_PORT_PACK(2, 0x1e, RZG2L_MPXED_PIN_FUNCS),
- RZG2L_GPIO_PORT_PACK(2, 0x1f, RZG2L_MPXED_PIN_FUNCS),
- RZG2L_GPIO_PORT_PACK(2, 0x20, RZG2L_MPXED_PIN_FUNCS),
- RZG2L_GPIO_PORT_PACK(3, 0x21, RZG2L_MPXED_PIN_FUNCS),
- RZG2L_GPIO_PORT_PACK(2, 0x22, RZG2L_MPXED_PIN_FUNCS),
- RZG2L_GPIO_PORT_PACK(2, 0x23, RZG2L_MPXED_PIN_FUNCS),
- RZG2L_GPIO_PORT_PACK(3, 0x24, RZG2L_MPXED_ETH_PIN_FUNCS(PIN_CFG_IO_VMC_ETH0)),
- RZG2L_GPIO_PORT_PACK(2, 0x25, RZG2L_MPXED_ETH_PIN_FUNCS(PIN_CFG_IO_VMC_ETH0)),
- RZG2L_GPIO_PORT_PACK(2, 0x26, RZG2L_MPXED_ETH_PIN_FUNCS(PIN_CFG_IO_VMC_ETH0)),
- RZG2L_GPIO_PORT_PACK(2, 0x27, RZG2L_MPXED_ETH_PIN_FUNCS(PIN_CFG_IO_VMC_ETH0)),
- RZG2L_GPIO_PORT_PACK(2, 0x28, RZG2L_MPXED_ETH_PIN_FUNCS(PIN_CFG_IO_VMC_ETH0)),
- RZG2L_GPIO_PORT_PACK(2, 0x29, RZG2L_MPXED_ETH_PIN_FUNCS(PIN_CFG_IO_VMC_ETH0)),
- RZG2L_GPIO_PORT_PACK(2, 0x2a, RZG2L_MPXED_ETH_PIN_FUNCS(PIN_CFG_IO_VMC_ETH0)),
- RZG2L_GPIO_PORT_PACK(2, 0x2b, RZG2L_MPXED_ETH_PIN_FUNCS(PIN_CFG_IO_VMC_ETH0)),
- RZG2L_GPIO_PORT_PACK(2, 0x2c, RZG2L_MPXED_ETH_PIN_FUNCS(PIN_CFG_IO_VMC_ETH0)),
- RZG2L_GPIO_PORT_PACK(2, 0x2d, RZG2L_MPXED_ETH_PIN_FUNCS(PIN_CFG_IO_VMC_ETH1)),
- RZG2L_GPIO_PORT_PACK(2, 0x2e, RZG2L_MPXED_ETH_PIN_FUNCS(PIN_CFG_IO_VMC_ETH1)),
- RZG2L_GPIO_PORT_PACK(2, 0x2f, RZG2L_MPXED_ETH_PIN_FUNCS(PIN_CFG_IO_VMC_ETH1)),
- RZG2L_GPIO_PORT_PACK(2, 0x30, RZG2L_MPXED_ETH_PIN_FUNCS(PIN_CFG_IO_VMC_ETH1)),
- RZG2L_GPIO_PORT_PACK(2, 0x31, RZG2L_MPXED_ETH_PIN_FUNCS(PIN_CFG_IO_VMC_ETH1)),
- RZG2L_GPIO_PORT_PACK(2, 0x32, RZG2L_MPXED_ETH_PIN_FUNCS(PIN_CFG_IO_VMC_ETH1)),
- RZG2L_GPIO_PORT_PACK(2, 0x33, RZG2L_MPXED_ETH_PIN_FUNCS(PIN_CFG_IO_VMC_ETH1)),
- RZG2L_GPIO_PORT_PACK(2, 0x34, RZG2L_MPXED_ETH_PIN_FUNCS(PIN_CFG_IO_VMC_ETH1)),
- RZG2L_GPIO_PORT_PACK(3, 0x35, RZG2L_MPXED_ETH_PIN_FUNCS(PIN_CFG_IO_VMC_ETH1)),
- RZG2L_GPIO_PORT_PACK(2, 0x36, RZG2L_MPXED_PIN_FUNCS),
- RZG2L_GPIO_PORT_PACK(3, 0x37, RZG2L_MPXED_PIN_FUNCS),
- RZG2L_GPIO_PORT_PACK(3, 0x38, RZG2L_MPXED_PIN_FUNCS),
- RZG2L_GPIO_PORT_PACK(2, 0x39, RZG2L_MPXED_PIN_FUNCS),
- RZG2L_GPIO_PORT_PACK(5, 0x3a, RZG2L_MPXED_PIN_FUNCS),
- RZG2L_GPIO_PORT_PACK(4, 0x3b, RZG2L_MPXED_PIN_FUNCS),
- RZG2L_GPIO_PORT_PACK(4, 0x3c, RZG2L_MPXED_PIN_FUNCS),
- RZG2L_GPIO_PORT_PACK(4, 0x3d, RZG2L_MPXED_PIN_FUNCS),
- RZG2L_GPIO_PORT_PACK(4, 0x3e, RZG2L_MPXED_PIN_FUNCS),
- RZG2L_GPIO_PORT_PACK(4, 0x3f, RZG2L_MPXED_PIN_FUNCS),
- RZG2L_GPIO_PORT_PACK(5, 0x40, RZG2L_MPXED_PIN_FUNCS),
+};
+static const struct {
- struct rzg2l_dedicated_configs common[35];
- struct rzg2l_dedicated_configs rzg2l_pins[7];
+} rzg2l_dedicated_pins = {
- .common = {
{ "NMI", RZG2L_SINGLE_PIN_PACK(0x1, 0,
(PIN_CFG_FILONOFF | PIN_CFG_FILNUM | PIN_CFG_FILCLKSEL)) },
{ "TMS/SWDIO", RZG2L_SINGLE_PIN_PACK(0x2, 0,
(PIN_CFG_IOLH_A | PIN_CFG_SR | PIN_CFG_IEN)) },
{ "TDO", RZG2L_SINGLE_PIN_PACK(0x3, 0,
(PIN_CFG_IOLH_A | PIN_CFG_SR | PIN_CFG_IEN)) },
{ "AUDIO_CLK1", RZG2L_SINGLE_PIN_PACK(0x4, 0, PIN_CFG_IEN) },
{ "AUDIO_CLK2", RZG2L_SINGLE_PIN_PACK(0x4, 1, PIN_CFG_IEN) },
{ "SD0_CLK", RZG2L_SINGLE_PIN_PACK(0x6, 0,
(PIN_CFG_IOLH_B | PIN_CFG_SR | PIN_CFG_IO_VMC_SD0)) },
{ "SD0_CMD", RZG2L_SINGLE_PIN_PACK(0x6, 1,
(PIN_CFG_IOLH_B | PIN_CFG_SR | PIN_CFG_IEN | PIN_CFG_IO_VMC_SD0)) },
{ "SD0_RST#", RZG2L_SINGLE_PIN_PACK(0x6, 2,
(PIN_CFG_IOLH_B | PIN_CFG_SR | PIN_CFG_IO_VMC_SD0)) },
{ "SD0_DATA0", RZG2L_SINGLE_PIN_PACK(0x7, 0,
(PIN_CFG_IOLH_B | PIN_CFG_SR | PIN_CFG_IEN | PIN_CFG_IO_VMC_SD0)) },
{ "SD0_DATA1", RZG2L_SINGLE_PIN_PACK(0x7, 1,
(PIN_CFG_IOLH_B | PIN_CFG_SR | PIN_CFG_IEN | PIN_CFG_IO_VMC_SD0)) },
{ "SD0_DATA2", RZG2L_SINGLE_PIN_PACK(0x7, 2,
(PIN_CFG_IOLH_B | PIN_CFG_SR | PIN_CFG_IEN | PIN_CFG_IO_VMC_SD0)) },
{ "SD0_DATA3", RZG2L_SINGLE_PIN_PACK(0x7, 3,
(PIN_CFG_IOLH_B | PIN_CFG_SR | PIN_CFG_IEN | PIN_CFG_IO_VMC_SD0)) },
{ "SD0_DATA4", RZG2L_SINGLE_PIN_PACK(0x7, 4,
(PIN_CFG_IOLH_B | PIN_CFG_SR | PIN_CFG_IEN | PIN_CFG_IO_VMC_SD0)) },
{ "SD0_DATA5", RZG2L_SINGLE_PIN_PACK(0x7, 5,
(PIN_CFG_IOLH_B | PIN_CFG_SR | PIN_CFG_IEN | PIN_CFG_IO_VMC_SD0)) },
{ "SD0_DATA6", RZG2L_SINGLE_PIN_PACK(0x7, 6,
(PIN_CFG_IOLH_B | PIN_CFG_SR | PIN_CFG_IEN | PIN_CFG_IO_VMC_SD0)) },
{ "SD0_DATA7", RZG2L_SINGLE_PIN_PACK(0x7, 7,
(PIN_CFG_IOLH_B | PIN_CFG_SR | PIN_CFG_IEN | PIN_CFG_IO_VMC_SD0)) },
{ "SD1_CLK", RZG2L_SINGLE_PIN_PACK(0x8, 0,
(PIN_CFG_IOLH_B | PIN_CFG_SR | PIN_CFG_IO_VMC_SD1)) },
{ "SD1_CMD", RZG2L_SINGLE_PIN_PACK(0x8, 1,
(PIN_CFG_IOLH_B | PIN_CFG_SR | PIN_CFG_IEN | PIN_CFG_IO_VMC_SD1)) },
{ "SD1_DATA0", RZG2L_SINGLE_PIN_PACK(0x9, 0,
(PIN_CFG_IOLH_B | PIN_CFG_SR | PIN_CFG_IEN | PIN_CFG_IO_VMC_SD1)) },
{ "SD1_DATA1", RZG2L_SINGLE_PIN_PACK(0x9, 1,
(PIN_CFG_IOLH_B | PIN_CFG_SR | PIN_CFG_IEN | PIN_CFG_IO_VMC_SD1)) },
{ "SD1_DATA2", RZG2L_SINGLE_PIN_PACK(0x9, 2,
(PIN_CFG_IOLH_B | PIN_CFG_SR | PIN_CFG_IEN | PIN_CFG_IO_VMC_SD1)) },
{ "SD1_DATA3", RZG2L_SINGLE_PIN_PACK(0x9, 3,
(PIN_CFG_IOLH_B | PIN_CFG_SR | PIN_CFG_IEN | PIN_CFG_IO_VMC_SD1)) },
{ "QSPI0_SPCLK", RZG2L_SINGLE_PIN_PACK(0xa, 0,
(PIN_CFG_IOLH_B | PIN_CFG_SR | PIN_CFG_IO_VMC_QSPI)) },
{ "QSPI0_IO0", RZG2L_SINGLE_PIN_PACK(0xa, 1,
(PIN_CFG_IOLH_B | PIN_CFG_SR | PIN_CFG_IO_VMC_QSPI)) },
{ "QSPI0_IO1", RZG2L_SINGLE_PIN_PACK(0xa, 2,
(PIN_CFG_IOLH_B | PIN_CFG_SR | PIN_CFG_IO_VMC_QSPI)) },
{ "QSPI0_IO2", RZG2L_SINGLE_PIN_PACK(0xa, 3,
(PIN_CFG_IOLH_B | PIN_CFG_SR | PIN_CFG_IO_VMC_QSPI)) },
{ "QSPI0_IO3", RZG2L_SINGLE_PIN_PACK(0xa, 4,
(PIN_CFG_IOLH_B | PIN_CFG_SR | PIN_CFG_IO_VMC_QSPI)) },
{ "QSPI0_SSL", RZG2L_SINGLE_PIN_PACK(0xa, 5,
(PIN_CFG_IOLH_B | PIN_CFG_SR | PIN_CFG_IO_VMC_QSPI)) },
{ "QSPI_RESET#", RZG2L_SINGLE_PIN_PACK(0xc, 0,
(PIN_CFG_IOLH_B | PIN_CFG_SR | PIN_CFG_IO_VMC_QSPI)) },
{ "QSPI_WP#", RZG2L_SINGLE_PIN_PACK(0xc, 1,
(PIN_CFG_IOLH_B | PIN_CFG_SR | PIN_CFG_IO_VMC_QSPI)) },
{ "WDTOVF_PERROUT#", RZG2L_SINGLE_PIN_PACK(0xd, 0, (PIN_CFG_IOLH_A | PIN_CFG_SR)) },
{ "RIIC0_SDA", RZG2L_SINGLE_PIN_PACK(0xe, 0, PIN_CFG_IEN) },
{ "RIIC0_SCL", RZG2L_SINGLE_PIN_PACK(0xe, 1, PIN_CFG_IEN) },
{ "RIIC1_SDA", RZG2L_SINGLE_PIN_PACK(0xe, 2, PIN_CFG_IEN) },
{ "RIIC1_SCL", RZG2L_SINGLE_PIN_PACK(0xe, 3, PIN_CFG_IEN) },
- },
- .rzg2l_pins = {
{ "QSPI_INT#", RZG2L_SINGLE_PIN_PACK(0xc, 2, (PIN_CFG_SR | PIN_CFG_IO_VMC_QSPI)) },
{ "QSPI1_SPCLK", RZG2L_SINGLE_PIN_PACK(0xb, 0,
(PIN_CFG_IOLH_B | PIN_CFG_SR | PIN_CFG_IO_VMC_QSPI)) },
{ "QSPI1_IO0", RZG2L_SINGLE_PIN_PACK(0xb, 1,
(PIN_CFG_IOLH_B | PIN_CFG_SR | PIN_CFG_IO_VMC_QSPI)) },
{ "QSPI1_IO1", RZG2L_SINGLE_PIN_PACK(0xb, 2,
(PIN_CFG_IOLH_B | PIN_CFG_SR | PIN_CFG_IO_VMC_QSPI)) },
{ "QSPI1_IO2", RZG2L_SINGLE_PIN_PACK(0xb, 3,
(PIN_CFG_IOLH_B | PIN_CFG_SR | PIN_CFG_IO_VMC_QSPI)) },
{ "QSPI1_IO3", RZG2L_SINGLE_PIN_PACK(0xb, 4,
(PIN_CFG_IOLH_B | PIN_CFG_SR | PIN_CFG_IO_VMC_QSPI)) },
{ "QSPI1_SSL", RZG2L_SINGLE_PIN_PACK(0xb, 5,
(PIN_CFG_IOLH_B | PIN_CFG_SR | PIN_CFG_IO_VMC_QSPI)) },
- }
+};
+static void rzg2l_rmw_pin_config(struct rzg2l_pfc_data *data, u32 offset,
u8 pin, u32 mask, u32 val)
+{
- void __iomem *addr = data->base + offset;
- u32 reg;
- /* handle _L/_H for 32-bit register read/write */
- if (pin >= 4) {
pin -= 4;
addr += 4;
- }
- reg = readl(addr) & ~(mask << (pin * 8));
- writel(reg | (val << (pin * 8)), addr);
clkbits_le32()
+}
+static int rzg2l_get_pins_count(struct udevice *dev) +{
- struct rzg2l_pfc_data *data =
(struct rzg2l_pfc_data *)dev_get_driver_data(dev);
- return data->num_dedicated_pins + data->num_pins;
+}
+static const char *rzg2l_get_pin_name(struct udevice *dev, unsigned int selector) +{
- struct rzg2l_pfc_data *data =
(struct rzg2l_pfc_data *)dev_get_driver_data(dev);
- int port;
- u8 pin;
- if (selector < data->num_dedicated_pins) {
if (selector >= ARRAY_SIZE(rzg2l_dedicated_pins.common)) {
unsigned int u = selector - ARRAY_SIZE(rzg2l_dedicated_pins.common);
return rzg2l_dedicated_pins.rzg2l_pins[u].name;
} else {
return rzg2l_dedicated_pins.common[selector].name;
}
- }
- port = rzg2l_selector_decode(data, selector, &pin);
- if (port < 0)
return "(invalid pin)";
- return rzg2l_gpio_names[pin + 8 * port];
+}
+static int rzg2l_pinconf_set(struct udevice *dev, unsigned int pin_selector,
unsigned int param, unsigned int argument)
+{
- struct rzg2l_pfc_data *data =
(struct rzg2l_pfc_data *)dev_get_driver_data(dev);
- u32 cfg, port_offset;
- u8 pin;
- if (pin_selector >= data->num_dedicated_pins) {
/* The pin selector refers to a multiplexed pin */
int port = rzg2l_selector_decode(data, pin_selector, &pin);
if (port < 0) {
dev_err(dev, "Invalid pin selector %u:%u\n", port, pin);
return port;
}
cfg = data->gpio_configs[port];
port_offset = port + 0x10;
What does 0x10 mean ? A macro would help .
- } else {
/* The pin selector refers to a dedicated function pin */
const struct rzg2l_dedicated_configs *dedicated_config;
if (pin_selector >= data->num_dedicated_pins) {
dev_err(dev, "Invalid dedicated pin %u\n", pin_selector);
return -EINVAL;
}
if (pin_selector >= ARRAY_SIZE(rzg2l_dedicated_pins.common)) {
pin_selector -= ARRAY_SIZE(rzg2l_dedicated_pins.common);
dedicated_config = &rzg2l_dedicated_pins.rzg2l_pins[pin_selector];
} else {
dedicated_config = &rzg2l_dedicated_pins.common[pin_selector];
}
port_offset = RZG2L_SINGLE_PIN_GET_PORT_OFFSET(dedicated_config->config);
pin = RZG2L_SINGLE_PIN_GET_BIT(dedicated_config->config);
cfg = RZG2L_SINGLE_PIN_GET_CFGS(dedicated_config->config);
- }
- switch (param) {
- case PIN_CONFIG_INPUT_ENABLE: {
if (!(cfg & PIN_CFG_IEN)) {
dev_err(dev, "pin does not support IEN\n");
return -EINVAL;
}
dev_dbg(dev, "port off %u:%u set IEN=%u\n",
port_offset, pin, argument);
rzg2l_rmw_pin_config(data, IEN(port_offset), pin, IEN_MASK, !!argument);
break;
- }
- case PIN_CONFIG_POWER_SOURCE: {
void __iomem *addr;
u32 pwr_reg = 0x0;
/* argument is in mV */
if (argument != 1800 && argument != 3300) {
dev_err(dev, "Invalid mV %u\n", argument);
return -EINVAL;
}
if (cfg & PIN_CFG_IO_VMC_SD0) {
dev_dbg(dev, "port off %u:%u set SD_CH 0 PVDD=%u\n",
port_offset, pin, argument);
pwr_reg = SD_CH(0);
} else if (cfg & PIN_CFG_IO_VMC_SD1) {
dev_dbg(dev, "port off %u:%u set SD_CH 1 PVDD=%u\n",
port_offset, pin, argument);
pwr_reg = SD_CH(1);
} else if (cfg & PIN_CFG_IO_VMC_QSPI) {
dev_dbg(dev, "port off %u:%u set QSPI PVDD=%u\n",
port_offset, pin, argument);
pwr_reg = QSPI;
} else {
dev_dbg(dev, "pin power source is not selectable\n");
return -EINVAL;
}
addr = data->base + pwr_reg;
writel((argument == 1800) ? PVDD_1800 : PVDD_3300, addr);
Does RZG2L not do 2V5 IO ? If not, please ignore the comment .
break;
- }
- default:
dev_err(dev, "Invalid pinconf parameter\n");
return -EOPNOTSUPP;
- }
- return 0;
+}
+static int rzg2l_pinmux_property_set(struct udevice *dev, u32 pinmux_group) +{
- struct rzg2l_pfc_data *data =
(struct rzg2l_pfc_data *)dev_get_driver_data(dev);
- u32 port, pin, func, pfc_state, reg;
- u8 pmc_state;
- func = RZG2L_PINMUX_TO_FUNC(pinmux_group);
- if (func > 5) {
dev_err(dev, "Invalid pin function %u\n", func);
return -EINVAL;
- }
- port = RZG2L_PINMUX_TO_PORT(pinmux_group);
- pin = RZG2L_PINMUX_TO_PIN(pinmux_group);
- if (!rzg2l_port_validate(data, port, pin)) {
dev_err(dev, "Invalid pin selector %u:%u\n", port, pin);
return -EINVAL;
- }
- /* Check current PMC & PFC to decide if we need to change anything. */
- pmc_state = readb(data->base + PMC(port)) & BIT(pin);
- pfc_state = (readl(data->base + PFC(port)) >> (pin * 4)) & PFC_MASK;
- if (pmc_state && pfc_state == func)
return 0;
- dev_dbg(dev, "pinmux port %u pin %u func %u\n", port, pin, func);
- /* Set pin to 'Non-use (Hi-Z input protection)' */
- reg = readw(data->base + PM(port));
- reg &= ~(PM_MASK << (pin * 2));
- writew(reg, data->base + PM(port));
- /* Temporarily switch to GPIO mode with PMC register */
- reg = readb(data->base + PMC(port));
- writeb(reg & ~BIT(pin), data->base + PMC(port));
- /* Set the PWPR register to allow PFC register to write */
- writel(0x0, data->base + PWPR); /* B0WI=0, PFCWE=0 */
- writel(PWPR_PFCWE, data->base + PWPR); /* B0WI=0, PFCWE=1 */
- /* Select Pin function mode with PFC register */
- reg = readl(data->base + PFC(port));
- reg &= ~(PFC_MASK << (pin * 4));
- writel(reg | (func << (pin * 4)), data->base + PFC(port));
clrbits_le32() , please fix globally .
- /* Set the PWPR register to be write-protected */
- writel(0x0, data->base + PWPR); /* B0WI=0, PFCWE=0 */
- writel(PWPR_B0WI, data->base + PWPR); /* B0WI=1, PFCWE=0 */
- /* Switch to Peripheral pin function with PMC register */
- reg = readb(data->base + PMC(port));
- writeb(reg | BIT(pin), data->base + PMC(port));
- return rzg2l_selector_encode(data, port, pin);
+}
[...]

On 03/10/2023 14:20, Marek Vasut wrote:
On 9/20/23 14:42, Paul Barker wrote:
This driver provides pinctrl and gpio control for the Renesas RZ/G2L (R9A07G044) SoC.
This patch is based on the corresponding Linux v6.5 driver.
Signed-off-by: Paul Barker paul.barker.ct@bp.renesas.com Reviewed-by: Biju Das biju.das.jz@bp.renesas.com Reviewed-by: Lad Prabhakar prabhakar.mahadev-lad.rj@bp.renesas.com
arch/arm/mach-rmobile/Kconfig | 1 + drivers/pinctrl/renesas/Kconfig | 9 + drivers/pinctrl/renesas/Makefile | 1 + drivers/pinctrl/renesas/rzg2l-pfc.c | 906 ++++++++++++++++++++++++++++ 4 files changed, 917 insertions(+) create mode 100644 drivers/pinctrl/renesas/rzg2l-pfc.c
diff --git a/arch/arm/mach-rmobile/Kconfig b/arch/arm/mach-rmobile/Kconfig index 91f544c78337..973e84fcf7ba 100644 --- a/arch/arm/mach-rmobile/Kconfig +++ b/arch/arm/mach-rmobile/Kconfig @@ -76,6 +76,7 @@ config RZG2L imply SYS_MALLOC_F imply RENESAS_SDHI imply CLK_RZG2L
- imply PINCTRL_RZG2L
Keep the list sorted
[...]
Drop the parenthesis around values please, fix globally and in other patches too.
+#define PWPR (0x3014) +#define SD_CH(n) (0x3000 + (n) * 4) +#define QSPI (0x3008)
+#define PVDD_1800 1 /* I/O domain voltage <= 1.8V */ +#define PVDD_3300 0 /* I/O domain voltage >= 3.3V */
+#define PWPR_B0WI BIT(7) /* Bit Write Disable */ +#define PWPR_PFCWE BIT(6) /* PFC Register Write Enable */
+#define PM_MASK 0x03 +#define PVDD_MASK 0x01 +#define PFC_MASK 0x07 +#define IEN_MASK 0x01 +#define IOLH_MASK 0x03
+#define PM_HIGH_Z 0x0 +#define PM_INPUT 0x1 +#define PM_OUTPUT 0x2 +#define PM_OUTPUT_IEN 0x3
+struct rzg2l_pfc_driver_data {
- uint num_dedicated_pins;
- uint num_ports;
- const u32 *gpio_configs;
+};
+struct rzg2l_pfc_data {
- void __iomem *base;
- uint num_dedicated_pins;
- uint num_ports;
- uint num_pins;
- const u32 *gpio_configs;
- bool pfc_enabled;
+};
+struct rzg2l_dedicated_configs {
- const char *name;
- u32 config;
+};
+/*
- We need to ensure that the module clock is enabled and all resets are
- de-asserted before using either the gpio or pinctrl functionality. Error
- handling can be quite simple here as if the PFC cannot be enabled then we
- will not be able to progress with the boot anyway.
- */
+static int rzg2l_pfc_enable(struct udevice *dev) +{
- struct rzg2l_pfc_data *data =
(struct rzg2l_pfc_data *)dev_get_driver_data(dev);
- struct reset_ctl_bulk rsts;
- struct clk clk;
- int ret;
- if (data->pfc_enabled)
When does this get triggered ?
This is initialised to false in rzg2l_pfc_bind(), then this function rzg2l_pfc_enable() sets it to true before a successful return. The effect is that the PFC is enabled just once, regardless of whether the pinctrl or gpio driver is probed first.
return 0;
[...]
+static int rzg2l_gpio_set_value(struct udevice *dev, unsigned int offset,
int value)
+{
- struct rzg2l_pfc_data *data =
(struct rzg2l_pfc_data *)dev_get_driver_data(dev);
- u32 port = RZG2L_PINMUX_TO_PORT(offset);
- u8 pin = RZG2L_PINMUX_TO_PIN(offset);
A lot of this can also be const
This is aligned with the Linux driver to make it easier to port any future fixes across.
- rzg2l_gpio_set(data, port, pin, (bool)value);
- return 0;
+}
+static void rzg2l_gpio_set_direction(struct rzg2l_pfc_data *data,
u32 port, u8 pin, bool output)
+{
- u16 reg16;
- reg16 = readw(data->base + PM(port));
- reg16 &= ~(PM_MASK << (pin * 2));
See clrsetbits_le32() function and co .
This is also aligned with the Linux driver.
- reg16 |= (output ? PM_OUTPUT : PM_INPUT) << (pin * 2);
- writew(reg16, data->base + PM(port));
+}
+static int rzg2l_gpio_direction_input(struct udevice *dev, unsigned int offset) +{
- struct rzg2l_pfc_data *data =
(struct rzg2l_pfc_data *)dev_get_driver_data(dev);
- u32 port = RZG2L_PINMUX_TO_PORT(offset);
- u8 pin = RZG2L_PINMUX_TO_PIN(offset);
- rzg2l_gpio_set_direction(data, port, pin, false);
- return 0;
+}
+static int rzg2l_gpio_direction_output(struct udevice *dev, unsigned int offset,
int value)
+{
- struct rzg2l_pfc_data *data =
(struct rzg2l_pfc_data *)dev_get_driver_data(dev);
- u32 port = RZG2L_PINMUX_TO_PORT(offset);
- u8 pin = RZG2L_PINMUX_TO_PIN(offset);
- rzg2l_gpio_set(data, port, pin, (bool)value);
- rzg2l_gpio_set_direction(data, port, pin, true);
- return 0;
+}
+static int rzg2l_gpio_request(struct udevice *dev, unsigned int offset,
const char *label)
+{
- struct rzg2l_pfc_data *data =
(struct rzg2l_pfc_data *)dev_get_driver_data(dev);
- u32 port = RZG2L_PINMUX_TO_PORT(offset);
- u8 pin = RZG2L_PINMUX_TO_PIN(offset);
- u8 reg8;
- if (!rzg2l_port_validate(data, port, pin)) {
dev_err(dev, "Invalid GPIO %u:%u\n", port, pin);
return -EINVAL;
- }
- /* Select GPIO mode in PMC Register */
- reg8 = readb(data->base + PMC(port));
- reg8 &= ~BIT(pin);
- writeb(reg8, data->base + PMC(port));
clrbits here too
- return 0;
+}
+static int rzg2l_gpio_get_function(struct udevice *dev, unsigned int offset) +{
- struct rzg2l_pfc_data *data =
(struct rzg2l_pfc_data *)dev_get_driver_data(dev);
- u32 port = RZG2L_PINMUX_TO_PORT(offset);
- u8 pin = RZG2L_PINMUX_TO_PIN(offset);
- u16 pm_state;
- u8 pmc_state;
- if (!rzg2l_port_validate(data, port, pin)) {
/* Running `gpio status -a` at the u-boot command line will
* iterate through all GPIO offsets with no understanding of
* which are valid and which are not. So we need to return
* something meaningful even for the invalid GPIOs.
*/
return GPIOF_UNKNOWN;
Would it make sense to add some GPIOF_SKIP flag and handle it in the command to avoid displaying invalid GPIOs ?
That is definitely a good idea, I'll look into it.
- }
- /* Check if the pin is in GPIO or function mode. */
- pmc_state = readb(data->base + PMC(port)) & BIT(pin);
- if (pmc_state)
return GPIOF_FUNC;
- /* Check the pin direction. */
- pm_state = (readw(data->base + PM(port)) >> (pin * 2)) & PM_MASK;
- switch (pm_state) {
- case PM_INPUT:
return GPIOF_INPUT;
- case PM_OUTPUT:
- case PM_OUTPUT_IEN:
return GPIOF_OUTPUT;
- default: /* PM_HIGH_Z */
return GPIOF_UNUSED;
- }
+}
+static const struct dm_gpio_ops rzg2l_gpio_ops = {
- .direction_input = rzg2l_gpio_direction_input,
- .direction_output = rzg2l_gpio_direction_output,
- .get_value = rzg2l_gpio_get_value,
- .set_value = rzg2l_gpio_set_value,
- .request = rzg2l_gpio_request,
- .get_function = rzg2l_gpio_get_function,
+};
+static int rzg2l_gpio_probe(struct udevice *dev) +{
- struct gpio_dev_priv *uc_priv = dev_get_uclass_priv(dev);
- struct ofnode_phandle_args args;
- int ret;
- uc_priv->bank_name = "rzg2l-pfc-gpio";
- ret = ofnode_parse_phandle_with_args(dev_ofnode(dev), "gpio-ranges",
NULL, 3, 0, &args);
- if (ret < 0) {
dev_err(dev, "Failed to parse gpio-ranges\n");
It is a good idea to include the return value in error message to ease debugging.
return -EINVAL;
- }
- uc_priv->gpio_count = args.args[2];
- return rzg2l_pfc_enable(dev);
+}
+U_BOOT_DRIVER(rzg2l_pfc_gpio) = {
- .name = "rzg2l-pfc-gpio",
- .id = UCLASS_GPIO,
- .ops = &rzg2l_gpio_ops,
- .probe = rzg2l_gpio_probe,
+};
Can you please split the GPIO and PFC drivers into separate files ?
I assume you mean gpio and pinctrl here - the PFC handles both. I can move the gpio driver out to drivers/gpio.
+static const char * const rzg2l_gpio_names[] = {
- "P0_0", "P0_1", "P0_2", "P0_3", "P0_4", "P0_5", "P0_6", "P0_7",
- "P1_0", "P1_1", "P1_2", "P1_3", "P1_4", "P1_5", "P1_6", "P1_7",
- "P2_0", "P2_1", "P2_2", "P2_3", "P2_4", "P2_5", "P2_6", "P2_7",
- "P3_0", "P3_1", "P3_2", "P3_3", "P3_4", "P3_5", "P3_6", "P3_7",
- "P4_0", "P4_1", "P4_2", "P4_3", "P4_4", "P4_5", "P4_6", "P4_7",
- "P5_0", "P5_1", "P5_2", "P5_3", "P5_4", "P5_5", "P5_6", "P5_7",
- "P6_0", "P6_1", "P6_2", "P6_3", "P6_4", "P6_5", "P6_6", "P6_7",
- "P7_0", "P7_1", "P7_2", "P7_3", "P7_4", "P7_5", "P7_6", "P7_7",
- "P8_0", "P8_1", "P8_2", "P8_3", "P8_4", "P8_5", "P8_6", "P8_7",
- "P9_0", "P9_1", "P9_2", "P9_3", "P9_4", "P9_5", "P9_6", "P9_7",
- "P10_0", "P10_1", "P10_2", "P10_3", "P10_4", "P10_5", "P10_6", "P10_7",
- "P11_0", "P11_1", "P11_2", "P11_3", "P11_4", "P11_5", "P11_6", "P11_7",
- "P12_0", "P12_1", "P12_2", "P12_3", "P12_4", "P12_5", "P12_6", "P12_7",
- "P13_0", "P13_1", "P13_2", "P13_3", "P13_4", "P13_5", "P13_6", "P13_7",
- "P14_0", "P14_1", "P14_2", "P14_3", "P14_4", "P14_5", "P14_6", "P14_7",
- "P15_0", "P15_1", "P15_2", "P15_3", "P15_4", "P15_5", "P15_6", "P15_7",
- "P16_0", "P16_1", "P16_2", "P16_3", "P16_4", "P16_5", "P16_6", "P16_7",
- "P17_0", "P17_1", "P17_2", "P17_3", "P17_4", "P17_5", "P17_6", "P17_7",
- "P18_0", "P18_1", "P18_2", "P18_3", "P18_4", "P18_5", "P18_6", "P18_7",
- "P19_0", "P19_1", "P19_2", "P19_3", "P19_4", "P19_5", "P19_6", "P19_7",
- "P20_0", "P20_1", "P20_2", "P20_3", "P20_4", "P20_5", "P20_6", "P20_7",
- "P21_0", "P21_1", "P21_2", "P21_3", "P21_4", "P21_5", "P21_6", "P21_7",
- "P22_0", "P22_1", "P22_2", "P22_3", "P22_4", "P22_5", "P22_6", "P22_7",
- "P23_0", "P23_1", "P23_2", "P23_3", "P23_4", "P23_5", "P23_6", "P23_7",
- "P24_0", "P24_1", "P24_2", "P24_3", "P24_4", "P24_5", "P24_6", "P24_7",
- "P25_0", "P25_1", "P25_2", "P25_3", "P25_4", "P25_5", "P25_6", "P25_7",
- "P26_0", "P26_1", "P26_2", "P26_3", "P26_4", "P26_5", "P26_6", "P26_7",
- "P27_0", "P27_1", "P27_2", "P27_3", "P27_4", "P27_5", "P27_6", "P27_7",
- "P28_0", "P28_1", "P28_2", "P28_3", "P28_4", "P28_5", "P28_6", "P28_7",
- "P29_0", "P29_1", "P29_2", "P29_3", "P29_4", "P29_5", "P29_6", "P29_7",
- "P30_0", "P30_1", "P30_2", "P30_3", "P30_4", "P30_5", "P30_6", "P30_7",
- "P31_0", "P31_1", "P31_2", "P31_3", "P31_4", "P31_5", "P31_6", "P31_7",
- "P32_0", "P32_1", "P32_2", "P32_3", "P32_4", "P32_5", "P32_6", "P32_7",
- "P33_0", "P33_1", "P33_2", "P33_3", "P33_4", "P33_5", "P33_6", "P33_7",
- "P34_0", "P34_1", "P34_2", "P34_3", "P34_4", "P34_5", "P34_6", "P34_7",
- "P35_0", "P35_1", "P35_2", "P35_3", "P35_4", "P35_5", "P35_6", "P35_7",
- "P36_0", "P36_1", "P36_2", "P36_3", "P36_4", "P36_5", "P36_6", "P36_7",
- "P37_0", "P37_1", "P37_2", "P37_3", "P37_4", "P37_5", "P37_6", "P37_7",
- "P38_0", "P38_1", "P38_2", "P38_3", "P38_4", "P38_5", "P38_6", "P38_7",
- "P39_0", "P39_1", "P39_2", "P39_3", "P39_4", "P39_5", "P39_6", "P39_7",
- "P40_0", "P40_1", "P40_2", "P40_3", "P40_4", "P40_5", "P40_6", "P40_7",
- "P41_0", "P41_1", "P41_2", "P41_3", "P41_4", "P41_5", "P41_6", "P41_7",
- "P42_0", "P42_1", "P42_2", "P42_3", "P42_4", "P42_5", "P42_6", "P42_7",
- "P43_0", "P43_1", "P43_2", "P43_3", "P43_4", "P43_5", "P43_6", "P43_7",
- "P44_0", "P44_1", "P44_2", "P44_3", "P44_4", "P44_5", "P44_6", "P44_7",
- "P45_0", "P45_1", "P45_2", "P45_3", "P45_4", "P45_5", "P45_6", "P45_7",
- "P46_0", "P46_1", "P46_2", "P46_3", "P46_4", "P46_5", "P46_6", "P46_7",
- "P47_0", "P47_1", "P47_2", "P47_3", "P47_4", "P47_5", "P47_6", "P47_7",
- "P48_0", "P48_1", "P48_2", "P48_3", "P48_4", "P48_5", "P48_6", "P48_7",
+};
+static const u32 r9a07g044_gpio_configs[] = {
- RZG2L_GPIO_PORT_PACK(2, 0x10, RZG2L_MPXED_PIN_FUNCS),
- RZG2L_GPIO_PORT_PACK(2, 0x11, RZG2L_MPXED_PIN_FUNCS),
- RZG2L_GPIO_PORT_PACK(2, 0x12, RZG2L_MPXED_PIN_FUNCS),
- RZG2L_GPIO_PORT_PACK(2, 0x13, RZG2L_MPXED_PIN_FUNCS),
- RZG2L_GPIO_PORT_PACK(2, 0x14, RZG2L_MPXED_PIN_FUNCS),
- RZG2L_GPIO_PORT_PACK(3, 0x15, RZG2L_MPXED_PIN_FUNCS),
- RZG2L_GPIO_PORT_PACK(2, 0x16, RZG2L_MPXED_PIN_FUNCS),
- RZG2L_GPIO_PORT_PACK(3, 0x17, RZG2L_MPXED_PIN_FUNCS),
- RZG2L_GPIO_PORT_PACK(3, 0x18, RZG2L_MPXED_PIN_FUNCS),
- RZG2L_GPIO_PORT_PACK(2, 0x19, RZG2L_MPXED_PIN_FUNCS),
- RZG2L_GPIO_PORT_PACK(2, 0x1a, RZG2L_MPXED_PIN_FUNCS),
- RZG2L_GPIO_PORT_PACK(2, 0x1b, RZG2L_MPXED_PIN_FUNCS),
- RZG2L_GPIO_PORT_PACK(2, 0x1c, RZG2L_MPXED_PIN_FUNCS),
- RZG2L_GPIO_PORT_PACK(3, 0x1d, RZG2L_MPXED_PIN_FUNCS),
- RZG2L_GPIO_PORT_PACK(2, 0x1e, RZG2L_MPXED_PIN_FUNCS),
- RZG2L_GPIO_PORT_PACK(2, 0x1f, RZG2L_MPXED_PIN_FUNCS),
- RZG2L_GPIO_PORT_PACK(2, 0x20, RZG2L_MPXED_PIN_FUNCS),
- RZG2L_GPIO_PORT_PACK(3, 0x21, RZG2L_MPXED_PIN_FUNCS),
- RZG2L_GPIO_PORT_PACK(2, 0x22, RZG2L_MPXED_PIN_FUNCS),
- RZG2L_GPIO_PORT_PACK(2, 0x23, RZG2L_MPXED_PIN_FUNCS),
- RZG2L_GPIO_PORT_PACK(3, 0x24, RZG2L_MPXED_ETH_PIN_FUNCS(PIN_CFG_IO_VMC_ETH0)),
- RZG2L_GPIO_PORT_PACK(2, 0x25, RZG2L_MPXED_ETH_PIN_FUNCS(PIN_CFG_IO_VMC_ETH0)),
- RZG2L_GPIO_PORT_PACK(2, 0x26, RZG2L_MPXED_ETH_PIN_FUNCS(PIN_CFG_IO_VMC_ETH0)),
- RZG2L_GPIO_PORT_PACK(2, 0x27, RZG2L_MPXED_ETH_PIN_FUNCS(PIN_CFG_IO_VMC_ETH0)),
- RZG2L_GPIO_PORT_PACK(2, 0x28, RZG2L_MPXED_ETH_PIN_FUNCS(PIN_CFG_IO_VMC_ETH0)),
- RZG2L_GPIO_PORT_PACK(2, 0x29, RZG2L_MPXED_ETH_PIN_FUNCS(PIN_CFG_IO_VMC_ETH0)),
- RZG2L_GPIO_PORT_PACK(2, 0x2a, RZG2L_MPXED_ETH_PIN_FUNCS(PIN_CFG_IO_VMC_ETH0)),
- RZG2L_GPIO_PORT_PACK(2, 0x2b, RZG2L_MPXED_ETH_PIN_FUNCS(PIN_CFG_IO_VMC_ETH0)),
- RZG2L_GPIO_PORT_PACK(2, 0x2c, RZG2L_MPXED_ETH_PIN_FUNCS(PIN_CFG_IO_VMC_ETH0)),
- RZG2L_GPIO_PORT_PACK(2, 0x2d, RZG2L_MPXED_ETH_PIN_FUNCS(PIN_CFG_IO_VMC_ETH1)),
- RZG2L_GPIO_PORT_PACK(2, 0x2e, RZG2L_MPXED_ETH_PIN_FUNCS(PIN_CFG_IO_VMC_ETH1)),
- RZG2L_GPIO_PORT_PACK(2, 0x2f, RZG2L_MPXED_ETH_PIN_FUNCS(PIN_CFG_IO_VMC_ETH1)),
- RZG2L_GPIO_PORT_PACK(2, 0x30, RZG2L_MPXED_ETH_PIN_FUNCS(PIN_CFG_IO_VMC_ETH1)),
- RZG2L_GPIO_PORT_PACK(2, 0x31, RZG2L_MPXED_ETH_PIN_FUNCS(PIN_CFG_IO_VMC_ETH1)),
- RZG2L_GPIO_PORT_PACK(2, 0x32, RZG2L_MPXED_ETH_PIN_FUNCS(PIN_CFG_IO_VMC_ETH1)),
- RZG2L_GPIO_PORT_PACK(2, 0x33, RZG2L_MPXED_ETH_PIN_FUNCS(PIN_CFG_IO_VMC_ETH1)),
- RZG2L_GPIO_PORT_PACK(2, 0x34, RZG2L_MPXED_ETH_PIN_FUNCS(PIN_CFG_IO_VMC_ETH1)),
- RZG2L_GPIO_PORT_PACK(3, 0x35, RZG2L_MPXED_ETH_PIN_FUNCS(PIN_CFG_IO_VMC_ETH1)),
- RZG2L_GPIO_PORT_PACK(2, 0x36, RZG2L_MPXED_PIN_FUNCS),
- RZG2L_GPIO_PORT_PACK(3, 0x37, RZG2L_MPXED_PIN_FUNCS),
- RZG2L_GPIO_PORT_PACK(3, 0x38, RZG2L_MPXED_PIN_FUNCS),
- RZG2L_GPIO_PORT_PACK(2, 0x39, RZG2L_MPXED_PIN_FUNCS),
- RZG2L_GPIO_PORT_PACK(5, 0x3a, RZG2L_MPXED_PIN_FUNCS),
- RZG2L_GPIO_PORT_PACK(4, 0x3b, RZG2L_MPXED_PIN_FUNCS),
- RZG2L_GPIO_PORT_PACK(4, 0x3c, RZG2L_MPXED_PIN_FUNCS),
- RZG2L_GPIO_PORT_PACK(4, 0x3d, RZG2L_MPXED_PIN_FUNCS),
- RZG2L_GPIO_PORT_PACK(4, 0x3e, RZG2L_MPXED_PIN_FUNCS),
- RZG2L_GPIO_PORT_PACK(4, 0x3f, RZG2L_MPXED_PIN_FUNCS),
- RZG2L_GPIO_PORT_PACK(5, 0x40, RZG2L_MPXED_PIN_FUNCS),
+};
+static const struct {
- struct rzg2l_dedicated_configs common[35];
- struct rzg2l_dedicated_configs rzg2l_pins[7];
+} rzg2l_dedicated_pins = {
- .common = {
{ "NMI", RZG2L_SINGLE_PIN_PACK(0x1, 0,
(PIN_CFG_FILONOFF | PIN_CFG_FILNUM | PIN_CFG_FILCLKSEL)) },
{ "TMS/SWDIO", RZG2L_SINGLE_PIN_PACK(0x2, 0,
(PIN_CFG_IOLH_A | PIN_CFG_SR | PIN_CFG_IEN)) },
{ "TDO", RZG2L_SINGLE_PIN_PACK(0x3, 0,
(PIN_CFG_IOLH_A | PIN_CFG_SR | PIN_CFG_IEN)) },
{ "AUDIO_CLK1", RZG2L_SINGLE_PIN_PACK(0x4, 0, PIN_CFG_IEN) },
{ "AUDIO_CLK2", RZG2L_SINGLE_PIN_PACK(0x4, 1, PIN_CFG_IEN) },
{ "SD0_CLK", RZG2L_SINGLE_PIN_PACK(0x6, 0,
(PIN_CFG_IOLH_B | PIN_CFG_SR | PIN_CFG_IO_VMC_SD0)) },
{ "SD0_CMD", RZG2L_SINGLE_PIN_PACK(0x6, 1,
(PIN_CFG_IOLH_B | PIN_CFG_SR | PIN_CFG_IEN | PIN_CFG_IO_VMC_SD0)) },
{ "SD0_RST#", RZG2L_SINGLE_PIN_PACK(0x6, 2,
(PIN_CFG_IOLH_B | PIN_CFG_SR | PIN_CFG_IO_VMC_SD0)) },
{ "SD0_DATA0", RZG2L_SINGLE_PIN_PACK(0x7, 0,
(PIN_CFG_IOLH_B | PIN_CFG_SR | PIN_CFG_IEN | PIN_CFG_IO_VMC_SD0)) },
{ "SD0_DATA1", RZG2L_SINGLE_PIN_PACK(0x7, 1,
(PIN_CFG_IOLH_B | PIN_CFG_SR | PIN_CFG_IEN | PIN_CFG_IO_VMC_SD0)) },
{ "SD0_DATA2", RZG2L_SINGLE_PIN_PACK(0x7, 2,
(PIN_CFG_IOLH_B | PIN_CFG_SR | PIN_CFG_IEN | PIN_CFG_IO_VMC_SD0)) },
{ "SD0_DATA3", RZG2L_SINGLE_PIN_PACK(0x7, 3,
(PIN_CFG_IOLH_B | PIN_CFG_SR | PIN_CFG_IEN | PIN_CFG_IO_VMC_SD0)) },
{ "SD0_DATA4", RZG2L_SINGLE_PIN_PACK(0x7, 4,
(PIN_CFG_IOLH_B | PIN_CFG_SR | PIN_CFG_IEN | PIN_CFG_IO_VMC_SD0)) },
{ "SD0_DATA5", RZG2L_SINGLE_PIN_PACK(0x7, 5,
(PIN_CFG_IOLH_B | PIN_CFG_SR | PIN_CFG_IEN | PIN_CFG_IO_VMC_SD0)) },
{ "SD0_DATA6", RZG2L_SINGLE_PIN_PACK(0x7, 6,
(PIN_CFG_IOLH_B | PIN_CFG_SR | PIN_CFG_IEN | PIN_CFG_IO_VMC_SD0)) },
{ "SD0_DATA7", RZG2L_SINGLE_PIN_PACK(0x7, 7,
(PIN_CFG_IOLH_B | PIN_CFG_SR | PIN_CFG_IEN | PIN_CFG_IO_VMC_SD0)) },
{ "SD1_CLK", RZG2L_SINGLE_PIN_PACK(0x8, 0,
(PIN_CFG_IOLH_B | PIN_CFG_SR | PIN_CFG_IO_VMC_SD1)) },
{ "SD1_CMD", RZG2L_SINGLE_PIN_PACK(0x8, 1,
(PIN_CFG_IOLH_B | PIN_CFG_SR | PIN_CFG_IEN | PIN_CFG_IO_VMC_SD1)) },
{ "SD1_DATA0", RZG2L_SINGLE_PIN_PACK(0x9, 0,
(PIN_CFG_IOLH_B | PIN_CFG_SR | PIN_CFG_IEN | PIN_CFG_IO_VMC_SD1)) },
{ "SD1_DATA1", RZG2L_SINGLE_PIN_PACK(0x9, 1,
(PIN_CFG_IOLH_B | PIN_CFG_SR | PIN_CFG_IEN | PIN_CFG_IO_VMC_SD1)) },
{ "SD1_DATA2", RZG2L_SINGLE_PIN_PACK(0x9, 2,
(PIN_CFG_IOLH_B | PIN_CFG_SR | PIN_CFG_IEN | PIN_CFG_IO_VMC_SD1)) },
{ "SD1_DATA3", RZG2L_SINGLE_PIN_PACK(0x9, 3,
(PIN_CFG_IOLH_B | PIN_CFG_SR | PIN_CFG_IEN | PIN_CFG_IO_VMC_SD1)) },
{ "QSPI0_SPCLK", RZG2L_SINGLE_PIN_PACK(0xa, 0,
(PIN_CFG_IOLH_B | PIN_CFG_SR | PIN_CFG_IO_VMC_QSPI)) },
{ "QSPI0_IO0", RZG2L_SINGLE_PIN_PACK(0xa, 1,
(PIN_CFG_IOLH_B | PIN_CFG_SR | PIN_CFG_IO_VMC_QSPI)) },
{ "QSPI0_IO1", RZG2L_SINGLE_PIN_PACK(0xa, 2,
(PIN_CFG_IOLH_B | PIN_CFG_SR | PIN_CFG_IO_VMC_QSPI)) },
{ "QSPI0_IO2", RZG2L_SINGLE_PIN_PACK(0xa, 3,
(PIN_CFG_IOLH_B | PIN_CFG_SR | PIN_CFG_IO_VMC_QSPI)) },
{ "QSPI0_IO3", RZG2L_SINGLE_PIN_PACK(0xa, 4,
(PIN_CFG_IOLH_B | PIN_CFG_SR | PIN_CFG_IO_VMC_QSPI)) },
{ "QSPI0_SSL", RZG2L_SINGLE_PIN_PACK(0xa, 5,
(PIN_CFG_IOLH_B | PIN_CFG_SR | PIN_CFG_IO_VMC_QSPI)) },
{ "QSPI_RESET#", RZG2L_SINGLE_PIN_PACK(0xc, 0,
(PIN_CFG_IOLH_B | PIN_CFG_SR | PIN_CFG_IO_VMC_QSPI)) },
{ "QSPI_WP#", RZG2L_SINGLE_PIN_PACK(0xc, 1,
(PIN_CFG_IOLH_B | PIN_CFG_SR | PIN_CFG_IO_VMC_QSPI)) },
{ "WDTOVF_PERROUT#", RZG2L_SINGLE_PIN_PACK(0xd, 0, (PIN_CFG_IOLH_A | PIN_CFG_SR)) },
{ "RIIC0_SDA", RZG2L_SINGLE_PIN_PACK(0xe, 0, PIN_CFG_IEN) },
{ "RIIC0_SCL", RZG2L_SINGLE_PIN_PACK(0xe, 1, PIN_CFG_IEN) },
{ "RIIC1_SDA", RZG2L_SINGLE_PIN_PACK(0xe, 2, PIN_CFG_IEN) },
{ "RIIC1_SCL", RZG2L_SINGLE_PIN_PACK(0xe, 3, PIN_CFG_IEN) },
- },
- .rzg2l_pins = {
{ "QSPI_INT#", RZG2L_SINGLE_PIN_PACK(0xc, 2, (PIN_CFG_SR | PIN_CFG_IO_VMC_QSPI)) },
{ "QSPI1_SPCLK", RZG2L_SINGLE_PIN_PACK(0xb, 0,
(PIN_CFG_IOLH_B | PIN_CFG_SR | PIN_CFG_IO_VMC_QSPI)) },
{ "QSPI1_IO0", RZG2L_SINGLE_PIN_PACK(0xb, 1,
(PIN_CFG_IOLH_B | PIN_CFG_SR | PIN_CFG_IO_VMC_QSPI)) },
{ "QSPI1_IO1", RZG2L_SINGLE_PIN_PACK(0xb, 2,
(PIN_CFG_IOLH_B | PIN_CFG_SR | PIN_CFG_IO_VMC_QSPI)) },
{ "QSPI1_IO2", RZG2L_SINGLE_PIN_PACK(0xb, 3,
(PIN_CFG_IOLH_B | PIN_CFG_SR | PIN_CFG_IO_VMC_QSPI)) },
{ "QSPI1_IO3", RZG2L_SINGLE_PIN_PACK(0xb, 4,
(PIN_CFG_IOLH_B | PIN_CFG_SR | PIN_CFG_IO_VMC_QSPI)) },
{ "QSPI1_SSL", RZG2L_SINGLE_PIN_PACK(0xb, 5,
(PIN_CFG_IOLH_B | PIN_CFG_SR | PIN_CFG_IO_VMC_QSPI)) },
- }
+};
+static void rzg2l_rmw_pin_config(struct rzg2l_pfc_data *data, u32 offset,
u8 pin, u32 mask, u32 val)
+{
- void __iomem *addr = data->base + offset;
- u32 reg;
- /* handle _L/_H for 32-bit register read/write */
- if (pin >= 4) {
pin -= 4;
addr += 4;
- }
- reg = readl(addr) & ~(mask << (pin * 8));
- writel(reg | (val << (pin * 8)), addr);
clkbits_le32()
+}
+static int rzg2l_get_pins_count(struct udevice *dev) +{
- struct rzg2l_pfc_data *data =
(struct rzg2l_pfc_data *)dev_get_driver_data(dev);
- return data->num_dedicated_pins + data->num_pins;
+}
+static const char *rzg2l_get_pin_name(struct udevice *dev, unsigned int selector) +{
- struct rzg2l_pfc_data *data =
(struct rzg2l_pfc_data *)dev_get_driver_data(dev);
- int port;
- u8 pin;
- if (selector < data->num_dedicated_pins) {
if (selector >= ARRAY_SIZE(rzg2l_dedicated_pins.common)) {
unsigned int u = selector - ARRAY_SIZE(rzg2l_dedicated_pins.common);
return rzg2l_dedicated_pins.rzg2l_pins[u].name;
} else {
return rzg2l_dedicated_pins.common[selector].name;
}
- }
- port = rzg2l_selector_decode(data, selector, &pin);
- if (port < 0)
return "(invalid pin)";
- return rzg2l_gpio_names[pin + 8 * port];
+}
+static int rzg2l_pinconf_set(struct udevice *dev, unsigned int pin_selector,
unsigned int param, unsigned int argument)
+{
- struct rzg2l_pfc_data *data =
(struct rzg2l_pfc_data *)dev_get_driver_data(dev);
- u32 cfg, port_offset;
- u8 pin;
- if (pin_selector >= data->num_dedicated_pins) {
/* The pin selector refers to a multiplexed pin */
int port = rzg2l_selector_decode(data, pin_selector, &pin);
if (port < 0) {
dev_err(dev, "Invalid pin selector %u:%u\n", port, pin);
return port;
}
cfg = data->gpio_configs[port];
port_offset = port + 0x10;
What does 0x10 mean ? A macro would help .
The registers start at offset 0x10 for port 0. I'll turn this into a macro.
- } else {
/* The pin selector refers to a dedicated function pin */
const struct rzg2l_dedicated_configs *dedicated_config;
if (pin_selector >= data->num_dedicated_pins) {
dev_err(dev, "Invalid dedicated pin %u\n", pin_selector);
return -EINVAL;
}
if (pin_selector >= ARRAY_SIZE(rzg2l_dedicated_pins.common)) {
pin_selector -= ARRAY_SIZE(rzg2l_dedicated_pins.common);
dedicated_config = &rzg2l_dedicated_pins.rzg2l_pins[pin_selector];
} else {
dedicated_config = &rzg2l_dedicated_pins.common[pin_selector];
}
port_offset = RZG2L_SINGLE_PIN_GET_PORT_OFFSET(dedicated_config->config);
pin = RZG2L_SINGLE_PIN_GET_BIT(dedicated_config->config);
cfg = RZG2L_SINGLE_PIN_GET_CFGS(dedicated_config->config);
- }
- switch (param) {
- case PIN_CONFIG_INPUT_ENABLE: {
if (!(cfg & PIN_CFG_IEN)) {
dev_err(dev, "pin does not support IEN\n");
return -EINVAL;
}
dev_dbg(dev, "port off %u:%u set IEN=%u\n",
port_offset, pin, argument);
rzg2l_rmw_pin_config(data, IEN(port_offset), pin, IEN_MASK, !!argument);
break;
- }
- case PIN_CONFIG_POWER_SOURCE: {
void __iomem *addr;
u32 pwr_reg = 0x0;
/* argument is in mV */
if (argument != 1800 && argument != 3300) {
dev_err(dev, "Invalid mV %u\n", argument);
return -EINVAL;
}
if (cfg & PIN_CFG_IO_VMC_SD0) {
dev_dbg(dev, "port off %u:%u set SD_CH 0 PVDD=%u\n",
port_offset, pin, argument);
pwr_reg = SD_CH(0);
} else if (cfg & PIN_CFG_IO_VMC_SD1) {
dev_dbg(dev, "port off %u:%u set SD_CH 1 PVDD=%u\n",
port_offset, pin, argument);
pwr_reg = SD_CH(1);
} else if (cfg & PIN_CFG_IO_VMC_QSPI) {
dev_dbg(dev, "port off %u:%u set QSPI PVDD=%u\n",
port_offset, pin, argument);
pwr_reg = QSPI;
} else {
dev_dbg(dev, "pin power source is not selectable\n");
return -EINVAL;
}
addr = data->base + pwr_reg;
writel((argument == 1800) ? PVDD_1800 : PVDD_3300, addr);
Does RZG2L not do 2V5 IO ? If not, please ignore the comment .
2V5 IO is supported on the Ethernet interfaces. Support for configuring those interfaces will be added along with the Ethernet driver in future patches.
Thanks, Paul

On 10/4/23 10:40, Paul Barker wrote:
On 03/10/2023 14:20, Marek Vasut wrote:
On 9/20/23 14:42, Paul Barker wrote:
This driver provides pinctrl and gpio control for the Renesas RZ/G2L (R9A07G044) SoC.
This patch is based on the corresponding Linux v6.5 driver.
Signed-off-by: Paul Barker paul.barker.ct@bp.renesas.com Reviewed-by: Biju Das biju.das.jz@bp.renesas.com Reviewed-by: Lad Prabhakar prabhakar.mahadev-lad.rj@bp.renesas.com
arch/arm/mach-rmobile/Kconfig | 1 + drivers/pinctrl/renesas/Kconfig | 9 + drivers/pinctrl/renesas/Makefile | 1 + drivers/pinctrl/renesas/rzg2l-pfc.c | 906 ++++++++++++++++++++++++++++ 4 files changed, 917 insertions(+) create mode 100644 drivers/pinctrl/renesas/rzg2l-pfc.c
diff --git a/arch/arm/mach-rmobile/Kconfig b/arch/arm/mach-rmobile/Kconfig index 91f544c78337..973e84fcf7ba 100644 --- a/arch/arm/mach-rmobile/Kconfig +++ b/arch/arm/mach-rmobile/Kconfig @@ -76,6 +76,7 @@ config RZG2L imply SYS_MALLOC_F imply RENESAS_SDHI imply CLK_RZG2L
- imply PINCTRL_RZG2L
Keep the list sorted
[...]
Drop the parenthesis around values please, fix globally and in other patches too.
+#define PWPR (0x3014) +#define SD_CH(n) (0x3000 + (n) * 4) +#define QSPI (0x3008)
+#define PVDD_1800 1 /* I/O domain voltage <= 1.8V */ +#define PVDD_3300 0 /* I/O domain voltage >= 3.3V */
+#define PWPR_B0WI BIT(7) /* Bit Write Disable */ +#define PWPR_PFCWE BIT(6) /* PFC Register Write Enable */
+#define PM_MASK 0x03 +#define PVDD_MASK 0x01 +#define PFC_MASK 0x07 +#define IEN_MASK 0x01 +#define IOLH_MASK 0x03
+#define PM_HIGH_Z 0x0 +#define PM_INPUT 0x1 +#define PM_OUTPUT 0x2 +#define PM_OUTPUT_IEN 0x3
+struct rzg2l_pfc_driver_data {
- uint num_dedicated_pins;
- uint num_ports;
- const u32 *gpio_configs;
+};
+struct rzg2l_pfc_data {
- void __iomem *base;
- uint num_dedicated_pins;
- uint num_ports;
- uint num_pins;
- const u32 *gpio_configs;
- bool pfc_enabled;
+};
+struct rzg2l_dedicated_configs {
- const char *name;
- u32 config;
+};
+/*
- We need to ensure that the module clock is enabled and all resets are
- de-asserted before using either the gpio or pinctrl functionality. Error
- handling can be quite simple here as if the PFC cannot be enabled then we
- will not be able to progress with the boot anyway.
- */
+static int rzg2l_pfc_enable(struct udevice *dev) +{
- struct rzg2l_pfc_data *data =
(struct rzg2l_pfc_data *)dev_get_driver_data(dev);
- struct reset_ctl_bulk rsts;
- struct clk clk;
- int ret;
- if (data->pfc_enabled)
When does this get triggered ?
This is initialised to false in rzg2l_pfc_bind(), then this function rzg2l_pfc_enable() sets it to true before a successful return. The effect is that the PFC is enabled just once, regardless of whether the pinctrl or gpio driver is probed first.
Why would be call to rzg2l_pfc_enable() a problem in the first place ? It just grabs and enables clock and ungates reset, the second time this is called the impact on harware should be no-op , right ?
return 0;
[...]
+static int rzg2l_gpio_set_value(struct udevice *dev, unsigned int offset,
int value)
+{
- struct rzg2l_pfc_data *data =
(struct rzg2l_pfc_data *)dev_get_driver_data(dev);
- u32 port = RZG2L_PINMUX_TO_PORT(offset);
- u8 pin = RZG2L_PINMUX_TO_PIN(offset);
A lot of this can also be const
This is aligned with the Linux driver to make it easier to port any future fixes across.
Maybe send patches to Geert and see what happens ?
[...]
return -EINVAL;
- }
- uc_priv->gpio_count = args.args[2];
- return rzg2l_pfc_enable(dev);
+}
+U_BOOT_DRIVER(rzg2l_pfc_gpio) = {
- .name = "rzg2l-pfc-gpio",
- .id = UCLASS_GPIO,
- .ops = &rzg2l_gpio_ops,
- .probe = rzg2l_gpio_probe,
+};
Can you please split the GPIO and PFC drivers into separate files ?
I assume you mean gpio and pinctrl here - the PFC handles both. I can move the gpio driver out to drivers/gpio.
Thanks. R-Car already does it that way.
[...]
if (cfg & PIN_CFG_IO_VMC_SD0) {
dev_dbg(dev, "port off %u:%u set SD_CH 0 PVDD=%u\n",
port_offset, pin, argument);
pwr_reg = SD_CH(0);
} else if (cfg & PIN_CFG_IO_VMC_SD1) {
dev_dbg(dev, "port off %u:%u set SD_CH 1 PVDD=%u\n",
port_offset, pin, argument);
pwr_reg = SD_CH(1);
} else if (cfg & PIN_CFG_IO_VMC_QSPI) {
dev_dbg(dev, "port off %u:%u set QSPI PVDD=%u\n",
port_offset, pin, argument);
pwr_reg = QSPI;
} else {
dev_dbg(dev, "pin power source is not selectable\n");
return -EINVAL;
}
addr = data->base + pwr_reg;
writel((argument == 1800) ? PVDD_1800 : PVDD_3300, addr);
Does RZG2L not do 2V5 IO ? If not, please ignore the comment .
2V5 IO is supported on the Ethernet interfaces. Support for configuring those interfaces will be added along with the Ethernet driver in future patches.
Add a TODO comment please.

Hi Marek and Paul,
Subject: Re: [PATCH 09/16] pinctrl: renesas: Add RZ/G2L PFC driver
On 10/4/23 10:40, Paul Barker wrote:
On 03/10/2023 14:20, Marek Vasut wrote:
On 9/20/23 14:42, Paul Barker wrote:
This driver provides pinctrl and gpio control for the Renesas RZ/G2L (R9A07G044) SoC.
This patch is based on the corresponding Linux v6.5 driver.
Signed-off-by: Paul Barker paul.barker.ct@bp.renesas.com Reviewed-by: Biju Das biju.das.jz@bp.renesas.com Reviewed-by: Lad Prabhakar prabhakar.mahadev-lad.rj@bp.renesas.com
arch/arm/mach-rmobile/Kconfig | 1 + drivers/pinctrl/renesas/Kconfig | 9 + drivers/pinctrl/renesas/Makefile | 1 + drivers/pinctrl/renesas/rzg2l-pfc.c | 906
++++++++++++++++++++++++++++
4 files changed, 917 insertions(+) create mode 100644 drivers/pinctrl/renesas/rzg2l-pfc.c
diff --git a/arch/arm/mach-rmobile/Kconfig b/arch/arm/mach-rmobile/Kconfig index 91f544c78337..973e84fcf7ba 100644 --- a/arch/arm/mach-rmobile/Kconfig +++ b/arch/arm/mach-rmobile/Kconfig @@ -76,6 +76,7 @@ config RZG2L imply SYS_MALLOC_F imply RENESAS_SDHI imply CLK_RZG2L
- imply PINCTRL_RZG2L
Keep the list sorted
[...]
Drop the parenthesis around values please, fix globally and in other patches too.
+#define PWPR (0x3014) +#define SD_CH(n) (0x3000 + (n) * 4) +#define QSPI (0x3008)
+#define PVDD_1800 1 /* I/O domain voltage <= 1.8V */ +#define PVDD_3300 0 /* I/O domain voltage >= 3.3V */
+#define PWPR_B0WI BIT(7) /* Bit Write Disable */ +#define PWPR_PFCWE BIT(6) /* PFC Register Write Enable */
+#define PM_MASK 0x03 +#define PVDD_MASK 0x01 +#define PFC_MASK 0x07 +#define IEN_MASK 0x01 +#define IOLH_MASK 0x03
+#define PM_HIGH_Z 0x0 +#define PM_INPUT 0x1 +#define PM_OUTPUT 0x2 +#define PM_OUTPUT_IEN 0x3
+struct rzg2l_pfc_driver_data {
- uint num_dedicated_pins;
- uint num_ports;
- const u32 *gpio_configs;
+};
+struct rzg2l_pfc_data {
- void __iomem *base;
- uint num_dedicated_pins;
- uint num_ports;
- uint num_pins;
- const u32 *gpio_configs;
- bool pfc_enabled;
+};
+struct rzg2l_dedicated_configs {
- const char *name;
- u32 config;
+};
+/*
- We need to ensure that the module clock is enabled and all
+resets are
- de-asserted before using either the gpio or pinctrl
+functionality. Error
- handling can be quite simple here as if the PFC cannot be
+enabled then we
- will not be able to progress with the boot anyway.
- */
+static int rzg2l_pfc_enable(struct udevice *dev) {
- struct rzg2l_pfc_data *data =
(struct rzg2l_pfc_data *)dev_get_driver_data(dev);
- struct reset_ctl_bulk rsts;
- struct clk clk;
- int ret;
- if (data->pfc_enabled)
When does this get triggered ?
This is initialised to false in rzg2l_pfc_bind(), then this function rzg2l_pfc_enable() sets it to true before a successful return. The effect is that the PFC is enabled just once, regardless of whether the pinctrl or gpio driver is probed first.
Why would be call to rzg2l_pfc_enable() a problem in the first place ? It just grabs and enables clock and ungates reset, the second time this is called the impact on harware should be no-op , right ?
return 0;
[...]
+static int rzg2l_gpio_set_value(struct udevice *dev, unsigned int
offset,
int value)
+{
- struct rzg2l_pfc_data *data =
(struct rzg2l_pfc_data *)dev_get_driver_data(dev);
- u32 port = RZG2L_PINMUX_TO_PORT(offset);
- u8 pin = RZG2L_PINMUX_TO_PIN(offset);
A lot of this can also be const
This is aligned with the Linux driver to make it easier to port any future fixes across.
Maybe send patches to Geert and see what happens ?
[...]
return -EINVAL;
- }
- uc_priv->gpio_count = args.args[2];
- return rzg2l_pfc_enable(dev);
+}
+U_BOOT_DRIVER(rzg2l_pfc_gpio) = {
- .name = "rzg2l-pfc-gpio",
- .id = UCLASS_GPIO,
- .ops = &rzg2l_gpio_ops,
- .probe = rzg2l_gpio_probe,
+};
Can you please split the GPIO and PFC drivers into separate files ?
I assume you mean gpio and pinctrl here - the PFC handles both. I can move the gpio driver out to drivers/gpio.
Thanks. R-Car already does it that way.
RCar has separate GPIO block and Pin control block So we have separate drivers.
On RZ/G2L we have only pinctrl block, ie, the reason it is integrated driver in linux.
If you make separate driver, how do you plan to share resources in u-boot. For eg: register/clock/reset??
Cheers, Biju

On Wed, Oct 04, 2023 at 12:56:14PM +0000, Biju Das wrote:
Hi Marek and Paul,
Subject: Re: [PATCH 09/16] pinctrl: renesas: Add RZ/G2L PFC driver
On 10/4/23 10:40, Paul Barker wrote:
On 03/10/2023 14:20, Marek Vasut wrote:
On 9/20/23 14:42, Paul Barker wrote:
This driver provides pinctrl and gpio control for the Renesas RZ/G2L (R9A07G044) SoC.
This patch is based on the corresponding Linux v6.5 driver.
Signed-off-by: Paul Barker paul.barker.ct@bp.renesas.com Reviewed-by: Biju Das biju.das.jz@bp.renesas.com Reviewed-by: Lad Prabhakar prabhakar.mahadev-lad.rj@bp.renesas.com
arch/arm/mach-rmobile/Kconfig | 1 + drivers/pinctrl/renesas/Kconfig | 9 + drivers/pinctrl/renesas/Makefile | 1 + drivers/pinctrl/renesas/rzg2l-pfc.c | 906
++++++++++++++++++++++++++++
4 files changed, 917 insertions(+) create mode 100644 drivers/pinctrl/renesas/rzg2l-pfc.c
diff --git a/arch/arm/mach-rmobile/Kconfig b/arch/arm/mach-rmobile/Kconfig index 91f544c78337..973e84fcf7ba 100644 --- a/arch/arm/mach-rmobile/Kconfig +++ b/arch/arm/mach-rmobile/Kconfig @@ -76,6 +76,7 @@ config RZG2L imply SYS_MALLOC_F imply RENESAS_SDHI imply CLK_RZG2L
- imply PINCTRL_RZG2L
Keep the list sorted
[...]
Drop the parenthesis around values please, fix globally and in other patches too.
+#define PWPR (0x3014) +#define SD_CH(n) (0x3000 + (n) * 4) +#define QSPI (0x3008)
+#define PVDD_1800 1 /* I/O domain voltage <= 1.8V */ +#define PVDD_3300 0 /* I/O domain voltage >= 3.3V */
+#define PWPR_B0WI BIT(7) /* Bit Write Disable */ +#define PWPR_PFCWE BIT(6) /* PFC Register Write Enable */
+#define PM_MASK 0x03 +#define PVDD_MASK 0x01 +#define PFC_MASK 0x07 +#define IEN_MASK 0x01 +#define IOLH_MASK 0x03
+#define PM_HIGH_Z 0x0 +#define PM_INPUT 0x1 +#define PM_OUTPUT 0x2 +#define PM_OUTPUT_IEN 0x3
+struct rzg2l_pfc_driver_data {
- uint num_dedicated_pins;
- uint num_ports;
- const u32 *gpio_configs;
+};
+struct rzg2l_pfc_data {
- void __iomem *base;
- uint num_dedicated_pins;
- uint num_ports;
- uint num_pins;
- const u32 *gpio_configs;
- bool pfc_enabled;
+};
+struct rzg2l_dedicated_configs {
- const char *name;
- u32 config;
+};
+/*
- We need to ensure that the module clock is enabled and all
+resets are
- de-asserted before using either the gpio or pinctrl
+functionality. Error
- handling can be quite simple here as if the PFC cannot be
+enabled then we
- will not be able to progress with the boot anyway.
- */
+static int rzg2l_pfc_enable(struct udevice *dev) {
- struct rzg2l_pfc_data *data =
(struct rzg2l_pfc_data *)dev_get_driver_data(dev);
- struct reset_ctl_bulk rsts;
- struct clk clk;
- int ret;
- if (data->pfc_enabled)
When does this get triggered ?
This is initialised to false in rzg2l_pfc_bind(), then this function rzg2l_pfc_enable() sets it to true before a successful return. The effect is that the PFC is enabled just once, regardless of whether the pinctrl or gpio driver is probed first.
Why would be call to rzg2l_pfc_enable() a problem in the first place ? It just grabs and enables clock and ungates reset, the second time this is called the impact on harware should be no-op , right ?
return 0;
[...]
+static int rzg2l_gpio_set_value(struct udevice *dev, unsigned int
offset,
int value)
+{
- struct rzg2l_pfc_data *data =
(struct rzg2l_pfc_data *)dev_get_driver_data(dev);
- u32 port = RZG2L_PINMUX_TO_PORT(offset);
- u8 pin = RZG2L_PINMUX_TO_PIN(offset);
A lot of this can also be const
This is aligned with the Linux driver to make it easier to port any future fixes across.
Maybe send patches to Geert and see what happens ?
[...]
return -EINVAL;
- }
- uc_priv->gpio_count = args.args[2];
- return rzg2l_pfc_enable(dev);
+}
+U_BOOT_DRIVER(rzg2l_pfc_gpio) = {
- .name = "rzg2l-pfc-gpio",
- .id = UCLASS_GPIO,
- .ops = &rzg2l_gpio_ops,
- .probe = rzg2l_gpio_probe,
+};
Can you please split the GPIO and PFC drivers into separate files ?
I assume you mean gpio and pinctrl here - the PFC handles both. I can move the gpio driver out to drivers/gpio.
Thanks. R-Car already does it that way.
RCar has separate GPIO block and Pin control block So we have separate drivers.
On RZ/G2L we have only pinctrl block, ie, the reason it is integrated driver in linux.
If you make separate driver, how do you plan to share resources in u-boot. For eg: register/clock/reset??
We already have this broken down into two drivers within the u-boot driver module - rzg2l_pfc_bind() calls device_bind_with_driver_data() to bind the "rzg2l-pfc-gpio" and "rzg2l-pfc-pinctrl" drivers to the device. It should be no trouble to separate the code into two .c files in the right places.
Thanks, Paul

Hi Paul Barker,
Subject: Re: [PATCH 09/16] pinctrl: renesas: Add RZ/G2L PFC driver
On Wed, Oct 04, 2023 at 12:56:14PM +0000, Biju Das wrote:
Hi Marek and Paul,
Subject: Re: [PATCH 09/16] pinctrl: renesas: Add RZ/G2L PFC driver
On 10/4/23 10:40, Paul Barker wrote:
On 03/10/2023 14:20, Marek Vasut wrote:
On 9/20/23 14:42, Paul Barker wrote:
This driver provides pinctrl and gpio control for the Renesas RZ/G2L (R9A07G044) SoC.
This patch is based on the corresponding Linux v6.5 driver.
Signed-off-by: Paul Barker paul.barker.ct@bp.renesas.com Reviewed-by: Biju Das biju.das.jz@bp.renesas.com Reviewed-by: Lad Prabhakar
prabhakar.mahadev-lad.rj@bp.renesas.com
arch/arm/mach-rmobile/Kconfig | 1 + drivers/pinctrl/renesas/Kconfig | 9 + drivers/pinctrl/renesas/Makefile | 1 + drivers/pinctrl/renesas/rzg2l-pfc.c | 906
++++++++++++++++++++++++++++
4 files changed, 917 insertions(+) create mode 100644 drivers/pinctrl/renesas/rzg2l-pfc.c
diff --git a/arch/arm/mach-rmobile/Kconfig b/arch/arm/mach-rmobile/Kconfig index 91f544c78337..973e84fcf7ba 100644 --- a/arch/arm/mach-rmobile/Kconfig +++ b/arch/arm/mach-rmobile/Kconfig @@ -76,6 +76,7 @@ config RZG2L imply SYS_MALLOC_F imply RENESAS_SDHI imply CLK_RZG2L
- imply PINCTRL_RZG2L
Keep the list sorted
[...]
Drop the parenthesis around values please, fix globally and in other patches too.
+#define PWPR (0x3014) +#define SD_CH(n) (0x3000 + (n) * 4) +#define QSPI (0x3008)
+#define PVDD_1800 1 /* I/O domain voltage <= 1.8V */ +#define PVDD_3300 0 /* I/O domain voltage >= 3.3V */
+#define PWPR_B0WI BIT(7) /* Bit Write Disable */ +#define PWPR_PFCWE BIT(6) /* PFC Register Write Enable */
+#define PM_MASK 0x03 +#define PVDD_MASK 0x01 +#define PFC_MASK 0x07 +#define IEN_MASK 0x01 +#define IOLH_MASK 0x03
+#define PM_HIGH_Z 0x0 +#define PM_INPUT 0x1 +#define PM_OUTPUT 0x2 +#define PM_OUTPUT_IEN 0x3
+struct rzg2l_pfc_driver_data {
- uint num_dedicated_pins;
- uint num_ports;
- const u32 *gpio_configs;
+};
+struct rzg2l_pfc_data {
- void __iomem *base;
- uint num_dedicated_pins;
- uint num_ports;
- uint num_pins;
- const u32 *gpio_configs;
- bool pfc_enabled;
+};
+struct rzg2l_dedicated_configs {
- const char *name;
- u32 config;
+};
+/*
- We need to ensure that the module clock is enabled and all
+resets are
- de-asserted before using either the gpio or pinctrl
+functionality. Error
- handling can be quite simple here as if the PFC cannot be
+enabled then we
- will not be able to progress with the boot anyway.
- */
+static int rzg2l_pfc_enable(struct udevice *dev) {
- struct rzg2l_pfc_data *data =
(struct rzg2l_pfc_data *)dev_get_driver_data(dev);
- struct reset_ctl_bulk rsts;
- struct clk clk;
- int ret;
- if (data->pfc_enabled)
When does this get triggered ?
This is initialised to false in rzg2l_pfc_bind(), then this function rzg2l_pfc_enable() sets it to true before a successful return. The effect is that the PFC is enabled just once, regardless of whether the pinctrl or gpio driver is probed first.
Why would be call to rzg2l_pfc_enable() a problem in the first place ? It just grabs and enables clock and ungates reset, the second time this is called the impact on harware should be no-op , right ?
return 0;
[...]
+static int rzg2l_gpio_set_value(struct udevice *dev, unsigned +int
offset,
int value)
+{
- struct rzg2l_pfc_data *data =
(struct rzg2l_pfc_data *)dev_get_driver_data(dev);
- u32 port = RZG2L_PINMUX_TO_PORT(offset);
- u8 pin = RZG2L_PINMUX_TO_PIN(offset);
A lot of this can also be const
This is aligned with the Linux driver to make it easier to port any future fixes across.
Maybe send patches to Geert and see what happens ?
[...]
return -EINVAL;
- }
- uc_priv->gpio_count = args.args[2];
- return rzg2l_pfc_enable(dev);
+}
+U_BOOT_DRIVER(rzg2l_pfc_gpio) = {
- .name = "rzg2l-pfc-gpio",
- .id = UCLASS_GPIO,
- .ops = &rzg2l_gpio_ops,
- .probe = rzg2l_gpio_probe,
+};
Can you please split the GPIO and PFC drivers into separate files ?
I assume you mean gpio and pinctrl here - the PFC handles both. I can move the gpio driver out to drivers/gpio.
Thanks. R-Car already does it that way.
RCar has separate GPIO block and Pin control block So we have separate drivers.
On RZ/G2L we have only pinctrl block, ie, the reason it is integrated driver in linux.
If you make separate driver, how do you plan to share resources in u-
boot. For eg: register/clock/reset??
We already have this broken down into two drivers within the u-boot driver module - rzg2l_pfc_bind() calls device_bind_with_driver_data() to bind the "rzg2l-pfc-gpio" and "rzg2l-pfc-pinctrl" drivers to the device. It should be no trouble to separate the code into two .c files in the right places.
Thanks for the explanation.
Cheers, Biju

On 10/4/23 14:56, Biju Das wrote:
[...]
return -EINVAL;
- }
- uc_priv->gpio_count = args.args[2];
- return rzg2l_pfc_enable(dev);
+}
+U_BOOT_DRIVER(rzg2l_pfc_gpio) = {
- .name = "rzg2l-pfc-gpio",
- .id = UCLASS_GPIO,
- .ops = &rzg2l_gpio_ops,
- .probe = rzg2l_gpio_probe,
+};
Can you please split the GPIO and PFC drivers into separate files ?
I assume you mean gpio and pinctrl here - the PFC handles both. I can move the gpio driver out to drivers/gpio.
Thanks. R-Car already does it that way.
RCar has separate GPIO block and Pin control block So we have separate drivers.
On RZ/G2L we have only pinctrl block, ie, the reason it is integrated driver in linux.
If you make separate driver, how do you plan to share resources in u-boot. For eg: register/clock/reset??
Clock and reset are easy, just grab them twice, once in each driver.
Registers, well ... have a look at gen3_cpg_bind() in drivers/clk/renesas/clk-rcar-gen3.c . Specifically, see device_bind_with_driver_data() and how one common "superdriver" can get bound to an IP, and then instantiate and bind two "subdrivers" which each obtain resources claimed by the "superdriver" via (in this case) the 'info' parameter. That should work, right ?

Hi Marek,
Subject: Re: [PATCH 09/16] pinctrl: renesas: Add RZ/G2L PFC driver
On 10/4/23 14:56, Biju Das wrote:
[...]
return -EINVAL;
- }
- uc_priv->gpio_count = args.args[2];
- return rzg2l_pfc_enable(dev);
+}
+U_BOOT_DRIVER(rzg2l_pfc_gpio) = {
- .name = "rzg2l-pfc-gpio",
- .id = UCLASS_GPIO,
- .ops = &rzg2l_gpio_ops,
- .probe = rzg2l_gpio_probe,
+};
Can you please split the GPIO and PFC drivers into separate files ?
I assume you mean gpio and pinctrl here - the PFC handles both. I can move the gpio driver out to drivers/gpio.
Thanks. R-Car already does it that way.
RCar has separate GPIO block and Pin control block So we have separate drivers.
On RZ/G2L we have only pinctrl block, ie, the reason it is integrated driver in linux.
If you make separate driver, how do you plan to share resources in u-
boot. For eg: register/clock/reset??
Clock and reset are easy, just grab them twice, once in each driver.
Registers, well ... have a look at gen3_cpg_bind() in drivers/clk/renesas/clk-rcar-gen3.c . Specifically, see device_bind_with_driver_data() and how one common "superdriver" can get bound to an IP, and then instantiate and bind two "subdrivers" which each obtain resources claimed by the "superdriver" via (in this case) the 'info' parameter. That should work, right ?
Yes, it should work.
Thanks for the explanation.
Cheers, Biju

On Wed, Oct 04, 2023 at 02:24:38PM +0200, Marek Vasut wrote:
On 10/4/23 10:40, Paul Barker wrote:
On 03/10/2023 14:20, Marek Vasut wrote:
On 9/20/23 14:42, Paul Barker wrote:
This driver provides pinctrl and gpio control for the Renesas RZ/G2L (R9A07G044) SoC.
This patch is based on the corresponding Linux v6.5 driver.
Signed-off-by: Paul Barker paul.barker.ct@bp.renesas.com Reviewed-by: Biju Das biju.das.jz@bp.renesas.com Reviewed-by: Lad Prabhakar prabhakar.mahadev-lad.rj@bp.renesas.com
arch/arm/mach-rmobile/Kconfig | 1 + drivers/pinctrl/renesas/Kconfig | 9 + drivers/pinctrl/renesas/Makefile | 1 + drivers/pinctrl/renesas/rzg2l-pfc.c | 906 ++++++++++++++++++++++++++++ 4 files changed, 917 insertions(+) create mode 100644 drivers/pinctrl/renesas/rzg2l-pfc.c
diff --git a/arch/arm/mach-rmobile/Kconfig b/arch/arm/mach-rmobile/Kconfig index 91f544c78337..973e84fcf7ba 100644 --- a/arch/arm/mach-rmobile/Kconfig +++ b/arch/arm/mach-rmobile/Kconfig @@ -76,6 +76,7 @@ config RZG2L imply SYS_MALLOC_F imply RENESAS_SDHI imply CLK_RZG2L
- imply PINCTRL_RZG2L
Keep the list sorted
[...]
Drop the parenthesis around values please, fix globally and in other patches too.
+#define PWPR (0x3014) +#define SD_CH(n) (0x3000 + (n) * 4) +#define QSPI (0x3008)
+#define PVDD_1800 1 /* I/O domain voltage <= 1.8V */ +#define PVDD_3300 0 /* I/O domain voltage >= 3.3V */
+#define PWPR_B0WI BIT(7) /* Bit Write Disable */ +#define PWPR_PFCWE BIT(6) /* PFC Register Write Enable */
+#define PM_MASK 0x03 +#define PVDD_MASK 0x01 +#define PFC_MASK 0x07 +#define IEN_MASK 0x01 +#define IOLH_MASK 0x03
+#define PM_HIGH_Z 0x0 +#define PM_INPUT 0x1 +#define PM_OUTPUT 0x2 +#define PM_OUTPUT_IEN 0x3
+struct rzg2l_pfc_driver_data {
- uint num_dedicated_pins;
- uint num_ports;
- const u32 *gpio_configs;
+};
+struct rzg2l_pfc_data {
- void __iomem *base;
- uint num_dedicated_pins;
- uint num_ports;
- uint num_pins;
- const u32 *gpio_configs;
- bool pfc_enabled;
+};
+struct rzg2l_dedicated_configs {
- const char *name;
- u32 config;
+};
+/*
- We need to ensure that the module clock is enabled and all resets are
- de-asserted before using either the gpio or pinctrl functionality. Error
- handling can be quite simple here as if the PFC cannot be enabled then we
- will not be able to progress with the boot anyway.
- */
+static int rzg2l_pfc_enable(struct udevice *dev) +{
- struct rzg2l_pfc_data *data =
(struct rzg2l_pfc_data *)dev_get_driver_data(dev);
- struct reset_ctl_bulk rsts;
- struct clk clk;
- int ret;
- if (data->pfc_enabled)
When does this get triggered ?
This is initialised to false in rzg2l_pfc_bind(), then this function rzg2l_pfc_enable() sets it to true before a successful return. The effect is that the PFC is enabled just once, regardless of whether the pinctrl or gpio driver is probed first.
Why would be call to rzg2l_pfc_enable() a problem in the first place ? It just grabs and enables clock and ungates reset, the second time this is called the impact on harware should be no-op , right ?
The hw impact is a no-op, but it wastes time unnecessarily re-reading data from the fdt and repeating the setup, e.g. in rzg2l_cpg_clk_set() we have to search the array of clocks each time to find the requested entry.
I think it's worth keeping the conditional here but can drop it if you're really against it.
Thanks, Paul

On 10/4/23 21:43, Paul Barker wrote:
[...]
+/*
- We need to ensure that the module clock is enabled and all resets are
- de-asserted before using either the gpio or pinctrl functionality. Error
- handling can be quite simple here as if the PFC cannot be enabled then we
- will not be able to progress with the boot anyway.
- */
+static int rzg2l_pfc_enable(struct udevice *dev) +{
- struct rzg2l_pfc_data *data =
(struct rzg2l_pfc_data *)dev_get_driver_data(dev);
- struct reset_ctl_bulk rsts;
- struct clk clk;
- int ret;
- if (data->pfc_enabled)
When does this get triggered ?
This is initialised to false in rzg2l_pfc_bind(), then this function rzg2l_pfc_enable() sets it to true before a successful return. The effect is that the PFC is enabled just once, regardless of whether the pinctrl or gpio driver is probed first.
Why would be call to rzg2l_pfc_enable() a problem in the first place ? It just grabs and enables clock and ungates reset, the second time this is called the impact on harware should be no-op , right ?
The hw impact is a no-op, but it wastes time unnecessarily re-reading data from the fdt and repeating the setup, e.g. in rzg2l_cpg_clk_set() we have to search the array of clocks each time to find the requested entry.
Does getting clock and enabling them have noticable overhead on this platform ? Look at CONFIG_OF_LIVE, that should mitigate the DT access overhead at least.
I think it's worth keeping the conditional here but can drop it if you're really against it.
It feels like fixing a problem at the wrong place really.

On 05/10/2023 03:24, Marek Vasut wrote:
On 10/4/23 21:43, Paul Barker wrote:
[...]
+/*
- We need to ensure that the module clock is enabled and all resets are
- de-asserted before using either the gpio or pinctrl functionality. Error
- handling can be quite simple here as if the PFC cannot be enabled then we
- will not be able to progress with the boot anyway.
- */
+static int rzg2l_pfc_enable(struct udevice *dev) +{
- struct rzg2l_pfc_data *data =
(struct rzg2l_pfc_data *)dev_get_driver_data(dev);
- struct reset_ctl_bulk rsts;
- struct clk clk;
- int ret;
- if (data->pfc_enabled)
When does this get triggered ?
This is initialised to false in rzg2l_pfc_bind(), then this function rzg2l_pfc_enable() sets it to true before a successful return. The effect is that the PFC is enabled just once, regardless of whether the pinctrl or gpio driver is probed first.
Why would be call to rzg2l_pfc_enable() a problem in the first place ? It just grabs and enables clock and ungates reset, the second time this is called the impact on harware should be no-op , right ?
The hw impact is a no-op, but it wastes time unnecessarily re-reading data from the fdt and repeating the setup, e.g. in rzg2l_cpg_clk_set() we have to search the array of clocks each time to find the requested entry.
Does getting clock and enabling them have noticable overhead on this platform ? Look at CONFIG_OF_LIVE, that should mitigate the DT access overhead at least.
I've not measured this. I was just assuming that it is sensible to only do the setup once.
I think it's worth keeping the conditional here but can drop it if you're really against it.
It feels like fixing a problem at the wrong place really.
I'll drop the pfc_enabled flag and re-test.
Thanks, Paul

On 10/5/23 11:39, Paul Barker wrote:
On 05/10/2023 03:24, Marek Vasut wrote:
On 10/4/23 21:43, Paul Barker wrote:
[...]
> +/* > + * We need to ensure that the module clock is enabled and all resets are > + * de-asserted before using either the gpio or pinctrl functionality. Error > + * handling can be quite simple here as if the PFC cannot be enabled then we > + * will not be able to progress with the boot anyway. > + */ > +static int rzg2l_pfc_enable(struct udevice *dev) > +{ > + struct rzg2l_pfc_data *data = > + (struct rzg2l_pfc_data *)dev_get_driver_data(dev); > + struct reset_ctl_bulk rsts; > + struct clk clk; > + int ret; > + > + if (data->pfc_enabled)
When does this get triggered ?
This is initialised to false in rzg2l_pfc_bind(), then this function rzg2l_pfc_enable() sets it to true before a successful return. The effect is that the PFC is enabled just once, regardless of whether the pinctrl or gpio driver is probed first.
Why would be call to rzg2l_pfc_enable() a problem in the first place ? It just grabs and enables clock and ungates reset, the second time this is called the impact on harware should be no-op , right ?
The hw impact is a no-op, but it wastes time unnecessarily re-reading data from the fdt and repeating the setup, e.g. in rzg2l_cpg_clk_set() we have to search the array of clocks each time to find the requested entry.
Does getting clock and enabling them have noticable overhead on this platform ? Look at CONFIG_OF_LIVE, that should mitigate the DT access overhead at least.
I've not measured this. I was just assuming that it is sensible to only do the setup once.
I think it's worth keeping the conditional here but can drop it if you're really against it.
It feels like fixing a problem at the wrong place really.
I'll drop the pfc_enabled flag and re-test.
You can stick get_timer() before and after the code to get a rough idea of how long it took, likely it will be 0 .
Thanks

Extend the existing driver to support the SCIF serial ports on the Renesas RZ/G2L (R9A07G044) SoC. This also requires us to ensure that the relevant reset signal is de-asserted before we try to talk to the SCIF module.
Signed-off-by: Paul Barker paul.barker.ct@bp.renesas.com Reviewed-by: Biju Das biju.das.jz@bp.renesas.com Reviewed-by: Lad Prabhakar prabhakar.mahadev-lad.rj@bp.renesas.com --- arch/arm/mach-rmobile/Kconfig | 1 + drivers/serial/serial_sh.c | 32 ++++++++++++++++++++++++++++++-- drivers/serial/serial_sh.h | 19 ++++++++++++++++++- 3 files changed, 49 insertions(+), 3 deletions(-)
diff --git a/arch/arm/mach-rmobile/Kconfig b/arch/arm/mach-rmobile/Kconfig index 973e84fcf7ba..0ab22356aee5 100644 --- a/arch/arm/mach-rmobile/Kconfig +++ b/arch/arm/mach-rmobile/Kconfig @@ -77,6 +77,7 @@ config RZG2L imply RENESAS_SDHI imply CLK_RZG2L imply PINCTRL_RZG2L + imply SCIF_CONSOLE help Enable support for the Renesas RZ/G2L family of SoCs, including the the RZ/G2L itself (based on the R9A07G044 SoC). diff --git a/drivers/serial/serial_sh.c b/drivers/serial/serial_sh.c index 5e543dbf3d58..a2e9a57137a6 100644 --- a/drivers/serial/serial_sh.c +++ b/drivers/serial/serial_sh.c @@ -17,6 +17,8 @@ #include <linux/compiler.h> #include <dm/platform_data/serial_sh.h> #include <linux/delay.h> +#include <dm/device_compat.h> +#include <reset.h> #include "serial_sh.h"
DECLARE_GLOBAL_DATA_PTR; @@ -79,8 +81,16 @@ sh_serial_setbrg_generic(struct uart_port *port, int clk, int baudrate)
static void handle_error(struct uart_port *port) { - sci_in(port, SCxSR); - sci_out(port, SCxSR, SCxSR_ERROR_CLEAR(port)); + /* The RZ/G2L datasheet says that error conditions are cleared by + * resetting the error bits in the FSR register to zero. + */ + if (IS_ENABLED(CONFIG_RZG2L)) { + unsigned short status = sci_in(port, SCxSR); + sci_out(port, SCxSR, status & ~SCIF_ERRORS); + } else { + sci_in(port, SCxSR); + sci_out(port, SCxSR, SCxSR_ERROR_CLEAR(port)); + } sci_in(port, SCLSR); sci_out(port, SCLSR, 0x00); } @@ -193,6 +203,23 @@ static int sh_serial_probe(struct udevice *dev) priv->type = plat->type; priv->clk_mode = plat->clk_mode;
+ if (IS_ENABLED(CONFIG_RZG2L)) { + struct reset_ctl rst; + int ret; + + ret = reset_get_by_index(dev, 0, &rst); + if (ret < 0) { + dev_err(dev, "failed to get reset line\n"); + return ret; + } + + ret = reset_deassert(&rst); + if (ret < 0) { + dev_err(dev, "failed to de-assert reset line\n"); + return ret; + } + } + sh_serial_init_generic(priv);
return 0; @@ -211,6 +238,7 @@ static const struct udevice_id sh_serial_id[] ={ {.compatible = "renesas,scif", .data = PORT_SCIF}, {.compatible = "renesas,scifa", .data = PORT_SCIFA}, {.compatible = "renesas,hscif", .data = PORT_HSCIF}, + {.compatible = "renesas,scif-r9a07g044", .data = PORT_SCIFA}, {} };
diff --git a/drivers/serial/serial_sh.h b/drivers/serial/serial_sh.h index 149ec1fe7397..58c2d22bc757 100644 --- a/drivers/serial/serial_sh.h +++ b/drivers/serial/serial_sh.h @@ -90,7 +90,7 @@ struct uart_port { # define SCSCR_INIT(port) 0x38 /* TIE=0,RIE=0,TE=1,RE=1,REIE=1 */ # define SCIF_ORER 0x0001 /* overrun error bit */ #elif defined(CONFIG_RCAR_GEN2) || defined(CONFIG_RCAR_64) || \ - defined(CONFIG_R7S72100) + defined(CONFIG_R7S72100) || defined(CONFIG_RZG2L) # if defined(CFG_SCIF_A) # define SCIF_ORER 0x0200 # else @@ -312,6 +312,9 @@ static inline void sci_##name##_out(struct uart_port *port,\ sh4_scif_offset, sh4_scif_size) #define SCIF_FNS(name, sh4_scif_offset, sh4_scif_size) \ CPU_SCIF_FNS(name, sh4_scif_offset, sh4_scif_size) +#elif defined(CONFIG_RZG2L) +#define SCIF_FNS(reg_name, reg_offset, reg_size) \ + CPU_SCIF_FNS(reg_name, reg_offset, reg_size) #else #define SCIx_FNS(name, sh3_sci_offset, sh3_sci_size,\ sh4_sci_offset, sh4_sci_size, \ @@ -387,6 +390,20 @@ SCIF_FNS(SCLSR, 0, 0, 0x14, 16) #else SCIF_FNS(SCLSR, 0, 0, 0x24, 16) #endif +#elif defined(CONFIG_RZG2L) +SCIF_FNS(SCSMR, 0x00, 16) +SCIF_FNS(SCBRR, 0x02, 8) +SCIF_FNS(SCSCR, 0x04, 16) +SCIF_FNS(SCxTDR, 0x06, 8) +SCIF_FNS(SCxSR, 0x08, 16) +SCIF_FNS(SCxRDR, 0x0A, 8) +SCIF_FNS(SCFCR, 0x0C, 16) +SCIF_FNS(SCFDR, 0x0E, 16) +SCIF_FNS(SCSPTR, 0x10, 16) +SCIF_FNS(SCLSR, 0x12, 16) +SCIF_FNS(SCSEMR, 0x14, 8) +SCIF_FNS(SCxTCR, 0x16, 16) +SCIF_FNS(DL, 0x00, 0) #else /* reg SCI/SH3 SCI/SH4 SCIF/SH3 SCIF/SH4 SCI/H8*/ /* name off sz off sz off sz off sz off sz*/

On 9/20/23 14:42, Paul Barker wrote:
Extend the existing driver to support the SCIF serial ports on the Renesas RZ/G2L (R9A07G044) SoC. This also requires us to ensure that the relevant reset signal is de-asserted before we try to talk to the SCIF module.
Signed-off-by: Paul Barker paul.barker.ct@bp.renesas.com Reviewed-by: Biju Das biju.das.jz@bp.renesas.com Reviewed-by: Lad Prabhakar prabhakar.mahadev-lad.rj@bp.renesas.com
arch/arm/mach-rmobile/Kconfig | 1 + drivers/serial/serial_sh.c | 32 ++++++++++++++++++++++++++++++-- drivers/serial/serial_sh.h | 19 ++++++++++++++++++- 3 files changed, 49 insertions(+), 3 deletions(-)
diff --git a/arch/arm/mach-rmobile/Kconfig b/arch/arm/mach-rmobile/Kconfig index 973e84fcf7ba..0ab22356aee5 100644 --- a/arch/arm/mach-rmobile/Kconfig +++ b/arch/arm/mach-rmobile/Kconfig @@ -77,6 +77,7 @@ config RZG2L imply RENESAS_SDHI imply CLK_RZG2L imply PINCTRL_RZG2L
- imply SCIF_CONSOLE help Enable support for the Renesas RZ/G2L family of SoCs, including the the RZ/G2L itself (based on the R9A07G044 SoC).
diff --git a/drivers/serial/serial_sh.c b/drivers/serial/serial_sh.c index 5e543dbf3d58..a2e9a57137a6 100644 --- a/drivers/serial/serial_sh.c +++ b/drivers/serial/serial_sh.c @@ -17,6 +17,8 @@ #include <linux/compiler.h> #include <dm/platform_data/serial_sh.h> #include <linux/delay.h> +#include <dm/device_compat.h> +#include <reset.h> #include "serial_sh.h"
DECLARE_GLOBAL_DATA_PTR; @@ -79,8 +81,16 @@ sh_serial_setbrg_generic(struct uart_port *port, int clk, int baudrate)
static void handle_error(struct uart_port *port) {
- sci_in(port, SCxSR);
- sci_out(port, SCxSR, SCxSR_ERROR_CLEAR(port));
- /* The RZ/G2L datasheet says that error conditions are cleared by
* resetting the error bits in the FSR register to zero.
Can you be more specific here ?
It doesn't seem Linux sh-sci.c driver does anything special for G2L, so is this special case really needed ?
*/
- if (IS_ENABLED(CONFIG_RZG2L)) {
unsigned short status = sci_in(port, SCxSR);
sci_out(port, SCxSR, status & ~SCIF_ERRORS);
- } else {
sci_in(port, SCxSR);
sci_out(port, SCxSR, SCxSR_ERROR_CLEAR(port));
- } sci_in(port, SCLSR); sci_out(port, SCLSR, 0x00); }
@@ -193,6 +203,23 @@ static int sh_serial_probe(struct udevice *dev) priv->type = plat->type; priv->clk_mode = plat->clk_mode;
- if (IS_ENABLED(CONFIG_RZG2L)) {
struct reset_ctl rst;
int ret;
ret = reset_get_by_index(dev, 0, &rst);
if (ret < 0) {
dev_err(dev, "failed to get reset line\n");
return ret;
}
ret = reset_deassert(&rst);
if (ret < 0) {
dev_err(dev, "failed to de-assert reset line\n");
return ret;
}
- }
devm_reset_control_get_optional() or something should do here too , right ?
Note that R-Car does have SCIF reset too, so this can be generic code.

On 03/10/2023 14:23, Marek Vasut wrote:
On 9/20/23 14:42, Paul Barker wrote:
Extend the existing driver to support the SCIF serial ports on the Renesas RZ/G2L (R9A07G044) SoC. This also requires us to ensure that the relevant reset signal is de-asserted before we try to talk to the SCIF module.
Signed-off-by: Paul Barker paul.barker.ct@bp.renesas.com Reviewed-by: Biju Das biju.das.jz@bp.renesas.com Reviewed-by: Lad Prabhakar prabhakar.mahadev-lad.rj@bp.renesas.com
arch/arm/mach-rmobile/Kconfig | 1 + drivers/serial/serial_sh.c | 32 ++++++++++++++++++++++++++++++-- drivers/serial/serial_sh.h | 19 ++++++++++++++++++- 3 files changed, 49 insertions(+), 3 deletions(-)
diff --git a/arch/arm/mach-rmobile/Kconfig b/arch/arm/mach-rmobile/Kconfig index 973e84fcf7ba..0ab22356aee5 100644 --- a/arch/arm/mach-rmobile/Kconfig +++ b/arch/arm/mach-rmobile/Kconfig @@ -77,6 +77,7 @@ config RZG2L imply RENESAS_SDHI imply CLK_RZG2L imply PINCTRL_RZG2L
- imply SCIF_CONSOLE help Enable support for the Renesas RZ/G2L family of SoCs, including the the RZ/G2L itself (based on the R9A07G044 SoC).
diff --git a/drivers/serial/serial_sh.c b/drivers/serial/serial_sh.c index 5e543dbf3d58..a2e9a57137a6 100644 --- a/drivers/serial/serial_sh.c +++ b/drivers/serial/serial_sh.c @@ -17,6 +17,8 @@ #include <linux/compiler.h> #include <dm/platform_data/serial_sh.h> #include <linux/delay.h> +#include <dm/device_compat.h> +#include <reset.h> #include "serial_sh.h"
DECLARE_GLOBAL_DATA_PTR; @@ -79,8 +81,16 @@ sh_serial_setbrg_generic(struct uart_port *port, int clk, int baudrate)
static void handle_error(struct uart_port *port) {
- sci_in(port, SCxSR);
- sci_out(port, SCxSR, SCxSR_ERROR_CLEAR(port));
- /* The RZ/G2L datasheet says that error conditions are cleared by
* resetting the error bits in the FSR register to zero.
Can you be more specific here ?
It doesn't seem Linux sh-sci.c driver does anything special for G2L, so is this special case really needed ?
On page 1268 of the datasheet (R01UH0914EJ0130 Rev.1.30):
"DR is cleared to 0 when DR = 1 is read and then 0 is written to the DR flag."
On page 1270:
"[Clearing condition] ● When 0 is written to ER after it has been read as 1"
So zeros must be written to clear these errors, not ones.
We have an open task to investigate the issue in the Linux driver and fix it.
*/
- if (IS_ENABLED(CONFIG_RZG2L)) {
unsigned short status = sci_in(port, SCxSR);
sci_out(port, SCxSR, status & ~SCIF_ERRORS);
- } else {
sci_in(port, SCxSR);
sci_out(port, SCxSR, SCxSR_ERROR_CLEAR(port));
- } sci_in(port, SCLSR); sci_out(port, SCLSR, 0x00); }
@@ -193,6 +203,23 @@ static int sh_serial_probe(struct udevice *dev) priv->type = plat->type; priv->clk_mode = plat->clk_mode;
- if (IS_ENABLED(CONFIG_RZG2L)) {
struct reset_ctl rst;
int ret;
ret = reset_get_by_index(dev, 0, &rst);
if (ret < 0) {
dev_err(dev, "failed to get reset line\n");
return ret;
}
ret = reset_deassert(&rst);
if (ret < 0) {
dev_err(dev, "failed to de-assert reset line\n");
return ret;
}
- }
devm_reset_control_get_optional() or something should do here too , right ?
Note that R-Car does have SCIF reset too, so this can be generic code.
For R-Car systems the current behaviour is working and well tested, we concluded that we shouldn't change it so this reset de-assert was made RZ/G2L specific.
For RZ/G2L, de-asserting the reset is not optional.
Thanks, Paul

On 10/4/23 10:48, Paul Barker wrote:
On 03/10/2023 14:23, Marek Vasut wrote:
On 9/20/23 14:42, Paul Barker wrote:
Extend the existing driver to support the SCIF serial ports on the Renesas RZ/G2L (R9A07G044) SoC. This also requires us to ensure that the relevant reset signal is de-asserted before we try to talk to the SCIF module.
Signed-off-by: Paul Barker paul.barker.ct@bp.renesas.com Reviewed-by: Biju Das biju.das.jz@bp.renesas.com Reviewed-by: Lad Prabhakar prabhakar.mahadev-lad.rj@bp.renesas.com
arch/arm/mach-rmobile/Kconfig | 1 + drivers/serial/serial_sh.c | 32 ++++++++++++++++++++++++++++++-- drivers/serial/serial_sh.h | 19 ++++++++++++++++++- 3 files changed, 49 insertions(+), 3 deletions(-)
diff --git a/arch/arm/mach-rmobile/Kconfig b/arch/arm/mach-rmobile/Kconfig index 973e84fcf7ba..0ab22356aee5 100644 --- a/arch/arm/mach-rmobile/Kconfig +++ b/arch/arm/mach-rmobile/Kconfig @@ -77,6 +77,7 @@ config RZG2L imply RENESAS_SDHI imply CLK_RZG2L imply PINCTRL_RZG2L
- imply SCIF_CONSOLE help Enable support for the Renesas RZ/G2L family of SoCs, including the the RZ/G2L itself (based on the R9A07G044 SoC).
diff --git a/drivers/serial/serial_sh.c b/drivers/serial/serial_sh.c index 5e543dbf3d58..a2e9a57137a6 100644 --- a/drivers/serial/serial_sh.c +++ b/drivers/serial/serial_sh.c @@ -17,6 +17,8 @@ #include <linux/compiler.h> #include <dm/platform_data/serial_sh.h> #include <linux/delay.h> +#include <dm/device_compat.h> +#include <reset.h> #include "serial_sh.h"
DECLARE_GLOBAL_DATA_PTR; @@ -79,8 +81,16 @@ sh_serial_setbrg_generic(struct uart_port *port, int clk, int baudrate)
static void handle_error(struct uart_port *port) {
- sci_in(port, SCxSR);
- sci_out(port, SCxSR, SCxSR_ERROR_CLEAR(port));
- /* The RZ/G2L datasheet says that error conditions are cleared by
* resetting the error bits in the FSR register to zero.
Can you be more specific here ?
It doesn't seem Linux sh-sci.c driver does anything special for G2L, so is this special case really needed ?
On page 1268 of the datasheet (R01UH0914EJ0130 Rev.1.30):
"DR is cleared to 0 when DR = 1 is read and then 0 is written to the DR flag."
On page 1270:
"[Clearing condition] ● When 0 is written to ER after it has been read as 1"
So zeros must be written to clear these errors, not ones.
We have an open task to investigate the issue in the Linux driver and fix it.
Is the G2L UART broken in Linux ? Does it misbehave in U-Boot ?
*/
- if (IS_ENABLED(CONFIG_RZG2L)) {
unsigned short status = sci_in(port, SCxSR);
sci_out(port, SCxSR, status & ~SCIF_ERRORS);
- } else {
sci_in(port, SCxSR);
sci_out(port, SCxSR, SCxSR_ERROR_CLEAR(port));
- } sci_in(port, SCLSR); sci_out(port, SCLSR, 0x00); }
@@ -193,6 +203,23 @@ static int sh_serial_probe(struct udevice *dev) priv->type = plat->type; priv->clk_mode = plat->clk_mode;
- if (IS_ENABLED(CONFIG_RZG2L)) {
struct reset_ctl rst;
int ret;
ret = reset_get_by_index(dev, 0, &rst);
if (ret < 0) {
dev_err(dev, "failed to get reset line\n");
return ret;
}
ret = reset_deassert(&rst);
if (ret < 0) {
dev_err(dev, "failed to de-assert reset line\n");
return ret;
}
- }
devm_reset_control_get_optional() or something should do here too , right ?
Note that R-Car does have SCIF reset too, so this can be generic code.
For R-Car systems the current behaviour is working and well tested, we concluded that we shouldn't change it so this reset de-assert was made RZ/G2L specific.
I can test on R-Car just fine, no worries.
SH R2Dplus is even tested in CI nightly.
For RZ/G2L, de-asserting the reset is not optional.
Let's avoid special-cases like that.

On Wed, Oct 04, 2023 at 02:26:49PM +0200, Marek Vasut wrote:
On 10/4/23 10:48, Paul Barker wrote:
On 03/10/2023 14:23, Marek Vasut wrote:
On 9/20/23 14:42, Paul Barker wrote:
Extend the existing driver to support the SCIF serial ports on the Renesas RZ/G2L (R9A07G044) SoC. This also requires us to ensure that the relevant reset signal is de-asserted before we try to talk to the SCIF module.
Signed-off-by: Paul Barker paul.barker.ct@bp.renesas.com Reviewed-by: Biju Das biju.das.jz@bp.renesas.com Reviewed-by: Lad Prabhakar prabhakar.mahadev-lad.rj@bp.renesas.com
arch/arm/mach-rmobile/Kconfig | 1 + drivers/serial/serial_sh.c | 32 ++++++++++++++++++++++++++++++-- drivers/serial/serial_sh.h | 19 ++++++++++++++++++- 3 files changed, 49 insertions(+), 3 deletions(-)
diff --git a/arch/arm/mach-rmobile/Kconfig b/arch/arm/mach-rmobile/Kconfig index 973e84fcf7ba..0ab22356aee5 100644 --- a/arch/arm/mach-rmobile/Kconfig +++ b/arch/arm/mach-rmobile/Kconfig @@ -77,6 +77,7 @@ config RZG2L imply RENESAS_SDHI imply CLK_RZG2L imply PINCTRL_RZG2L
- imply SCIF_CONSOLE help Enable support for the Renesas RZ/G2L family of SoCs, including the the RZ/G2L itself (based on the R9A07G044 SoC).
diff --git a/drivers/serial/serial_sh.c b/drivers/serial/serial_sh.c index 5e543dbf3d58..a2e9a57137a6 100644 --- a/drivers/serial/serial_sh.c +++ b/drivers/serial/serial_sh.c @@ -17,6 +17,8 @@ #include <linux/compiler.h> #include <dm/platform_data/serial_sh.h> #include <linux/delay.h> +#include <dm/device_compat.h> +#include <reset.h> #include "serial_sh.h" DECLARE_GLOBAL_DATA_PTR; @@ -79,8 +81,16 @@ sh_serial_setbrg_generic(struct uart_port *port, int clk, int baudrate) static void handle_error(struct uart_port *port) {
- sci_in(port, SCxSR);
- sci_out(port, SCxSR, SCxSR_ERROR_CLEAR(port));
- /* The RZ/G2L datasheet says that error conditions are cleared by
* resetting the error bits in the FSR register to zero.
Can you be more specific here ?
It doesn't seem Linux sh-sci.c driver does anything special for G2L, so is this special case really needed ?
On page 1268 of the datasheet (R01UH0914EJ0130 Rev.1.30):
"DR is cleared to 0 when DR = 1 is read and then 0 is written to the DR flag."
On page 1270:
"[Clearing condition] ● When 0 is written to ER after it has been read as 1"
So zeros must be written to clear these errors, not ones.
We have an open task to investigate the issue in the Linux driver and fix it.
Is the G2L UART broken in Linux ?
Likely yes, but we need to reproduce the issue.
Does it misbehave in U-Boot ?
Yes, before I changed this, if a framing error occurred it could never be cleared and the serial port stopped sending/receiving data.
The framing error was triggered by accident by unnecessarily re-doing pinmuxing for the serial port after TrustedFirmware had already set it up correctly. Since SCIF0 is wired to an FTDI USB/serial adaptor chip on the SMARC carrier board, it seems very difficult to trigger a framing error in any other way, the FTDI chip is too well behaved.
Thanks, Paul

On 10/4/23 15:43, Paul Barker wrote:
On Wed, Oct 04, 2023 at 02:26:49PM +0200, Marek Vasut wrote:
On 10/4/23 10:48, Paul Barker wrote:
On 03/10/2023 14:23, Marek Vasut wrote:
On 9/20/23 14:42, Paul Barker wrote:
Extend the existing driver to support the SCIF serial ports on the Renesas RZ/G2L (R9A07G044) SoC. This also requires us to ensure that the relevant reset signal is de-asserted before we try to talk to the SCIF module.
Signed-off-by: Paul Barker paul.barker.ct@bp.renesas.com Reviewed-by: Biju Das biju.das.jz@bp.renesas.com Reviewed-by: Lad Prabhakar prabhakar.mahadev-lad.rj@bp.renesas.com
arch/arm/mach-rmobile/Kconfig | 1 + drivers/serial/serial_sh.c | 32 ++++++++++++++++++++++++++++++-- drivers/serial/serial_sh.h | 19 ++++++++++++++++++- 3 files changed, 49 insertions(+), 3 deletions(-)
diff --git a/arch/arm/mach-rmobile/Kconfig b/arch/arm/mach-rmobile/Kconfig index 973e84fcf7ba..0ab22356aee5 100644 --- a/arch/arm/mach-rmobile/Kconfig +++ b/arch/arm/mach-rmobile/Kconfig @@ -77,6 +77,7 @@ config RZG2L imply RENESAS_SDHI imply CLK_RZG2L imply PINCTRL_RZG2L
- imply SCIF_CONSOLE help Enable support for the Renesas RZ/G2L family of SoCs, including the the RZ/G2L itself (based on the R9A07G044 SoC).
diff --git a/drivers/serial/serial_sh.c b/drivers/serial/serial_sh.c index 5e543dbf3d58..a2e9a57137a6 100644 --- a/drivers/serial/serial_sh.c +++ b/drivers/serial/serial_sh.c @@ -17,6 +17,8 @@ #include <linux/compiler.h> #include <dm/platform_data/serial_sh.h> #include <linux/delay.h> +#include <dm/device_compat.h> +#include <reset.h> #include "serial_sh.h" DECLARE_GLOBAL_DATA_PTR; @@ -79,8 +81,16 @@ sh_serial_setbrg_generic(struct uart_port *port, int clk, int baudrate) static void handle_error(struct uart_port *port) {
- sci_in(port, SCxSR);
- sci_out(port, SCxSR, SCxSR_ERROR_CLEAR(port));
- /* The RZ/G2L datasheet says that error conditions are cleared by
* resetting the error bits in the FSR register to zero.
Can you be more specific here ?
It doesn't seem Linux sh-sci.c driver does anything special for G2L, so is this special case really needed ?
On page 1268 of the datasheet (R01UH0914EJ0130 Rev.1.30):
"DR is cleared to 0 when DR = 1 is read and then 0 is written to the DR flag."
On page 1270:
"[Clearing condition] ● When 0 is written to ER after it has been read as 1"
So zeros must be written to clear these errors, not ones.
We have an open task to investigate the issue in the Linux driver and fix it.
Is the G2L UART broken in Linux ?
Likely yes, but we need to reproduce the issue.
Does it misbehave in U-Boot ?
Yes, before I changed this, if a framing error occurred it could never be cleared and the serial port stopped sending/receiving data.
The framing error was triggered by accident by unnecessarily re-doing pinmuxing for the serial port after TrustedFirmware had already set it up correctly. Since SCIF0 is wired to an FTDI USB/serial adaptor chip on the SMARC carrier board, it seems very difficult to trigger a framing error in any other way, the FTDI chip is too well behaved.
Is it possible to trigger this on RZ/G2<non-L> with SCIF on those platforms as well ?

On Wed, Oct 04, 2023 at 05:17:55PM +0200, Marek Vasut wrote:
On 10/4/23 15:43, Paul Barker wrote:
On Wed, Oct 04, 2023 at 02:26:49PM +0200, Marek Vasut wrote:
On 10/4/23 10:48, Paul Barker wrote:
On 03/10/2023 14:23, Marek Vasut wrote:
On 9/20/23 14:42, Paul Barker wrote:
Extend the existing driver to support the SCIF serial ports on the Renesas RZ/G2L (R9A07G044) SoC. This also requires us to ensure that the relevant reset signal is de-asserted before we try to talk to the SCIF module.
Signed-off-by: Paul Barker paul.barker.ct@bp.renesas.com Reviewed-by: Biju Das biju.das.jz@bp.renesas.com Reviewed-by: Lad Prabhakar prabhakar.mahadev-lad.rj@bp.renesas.com
arch/arm/mach-rmobile/Kconfig | 1 + drivers/serial/serial_sh.c | 32 ++++++++++++++++++++++++++++++-- drivers/serial/serial_sh.h | 19 ++++++++++++++++++- 3 files changed, 49 insertions(+), 3 deletions(-)
diff --git a/arch/arm/mach-rmobile/Kconfig b/arch/arm/mach-rmobile/Kconfig index 973e84fcf7ba..0ab22356aee5 100644 --- a/arch/arm/mach-rmobile/Kconfig +++ b/arch/arm/mach-rmobile/Kconfig @@ -77,6 +77,7 @@ config RZG2L imply RENESAS_SDHI imply CLK_RZG2L imply PINCTRL_RZG2L
- imply SCIF_CONSOLE help Enable support for the Renesas RZ/G2L family of SoCs, including the the RZ/G2L itself (based on the R9A07G044 SoC).
diff --git a/drivers/serial/serial_sh.c b/drivers/serial/serial_sh.c index 5e543dbf3d58..a2e9a57137a6 100644 --- a/drivers/serial/serial_sh.c +++ b/drivers/serial/serial_sh.c @@ -17,6 +17,8 @@ #include <linux/compiler.h> #include <dm/platform_data/serial_sh.h> #include <linux/delay.h> +#include <dm/device_compat.h> +#include <reset.h> #include "serial_sh.h" DECLARE_GLOBAL_DATA_PTR; @@ -79,8 +81,16 @@ sh_serial_setbrg_generic(struct uart_port *port, int clk, int baudrate) static void handle_error(struct uart_port *port) {
- sci_in(port, SCxSR);
- sci_out(port, SCxSR, SCxSR_ERROR_CLEAR(port));
- /* The RZ/G2L datasheet says that error conditions are cleared by
* resetting the error bits in the FSR register to zero.
Can you be more specific here ?
It doesn't seem Linux sh-sci.c driver does anything special for G2L, so is this special case really needed ?
On page 1268 of the datasheet (R01UH0914EJ0130 Rev.1.30):
"DR is cleared to 0 when DR = 1 is read and then 0 is written to the DR flag."
On page 1270:
"[Clearing condition] ● When 0 is written to ER after it has been read as 1"
So zeros must be written to clear these errors, not ones.
We have an open task to investigate the issue in the Linux driver and fix it.
Is the G2L UART broken in Linux ?
Likely yes, but we need to reproduce the issue.
Does it misbehave in U-Boot ?
Yes, before I changed this, if a framing error occurred it could never be cleared and the serial port stopped sending/receiving data.
The framing error was triggered by accident by unnecessarily re-doing pinmuxing for the serial port after TrustedFirmware had already set it up correctly. Since SCIF0 is wired to an FTDI USB/serial adaptor chip on the SMARC carrier board, it seems very difficult to trigger a framing error in any other way, the FTDI chip is too well behaved.
Is it possible to trigger this on RZ/G2<non-L> with SCIF on those platforms as well ?
It's not been seen or reported to my knowledge, but it's on our list to look into further.
Thanks, Paul

On 10/4/23 18:38, Paul Barker wrote:
On Wed, Oct 04, 2023 at 05:17:55PM +0200, Marek Vasut wrote:
On 10/4/23 15:43, Paul Barker wrote:
On Wed, Oct 04, 2023 at 02:26:49PM +0200, Marek Vasut wrote:
On 10/4/23 10:48, Paul Barker wrote:
On 03/10/2023 14:23, Marek Vasut wrote:
On 9/20/23 14:42, Paul Barker wrote: > Extend the existing driver to support the SCIF serial ports on the > Renesas RZ/G2L (R9A07G044) SoC. This also requires us to ensure that the > relevant reset signal is de-asserted before we try to talk to the SCIF > module. > > Signed-off-by: Paul Barker paul.barker.ct@bp.renesas.com > Reviewed-by: Biju Das biju.das.jz@bp.renesas.com > Reviewed-by: Lad Prabhakar prabhakar.mahadev-lad.rj@bp.renesas.com > --- > arch/arm/mach-rmobile/Kconfig | 1 + > drivers/serial/serial_sh.c | 32 ++++++++++++++++++++++++++++++-- > drivers/serial/serial_sh.h | 19 ++++++++++++++++++- > 3 files changed, 49 insertions(+), 3 deletions(-) > > diff --git a/arch/arm/mach-rmobile/Kconfig b/arch/arm/mach-rmobile/Kconfig > index 973e84fcf7ba..0ab22356aee5 100644 > --- a/arch/arm/mach-rmobile/Kconfig > +++ b/arch/arm/mach-rmobile/Kconfig > @@ -77,6 +77,7 @@ config RZG2L > imply RENESAS_SDHI > imply CLK_RZG2L > imply PINCTRL_RZG2L > + imply SCIF_CONSOLE > help > Enable support for the Renesas RZ/G2L family of SoCs, including the > the RZ/G2L itself (based on the R9A07G044 SoC). > diff --git a/drivers/serial/serial_sh.c b/drivers/serial/serial_sh.c > index 5e543dbf3d58..a2e9a57137a6 100644 > --- a/drivers/serial/serial_sh.c > +++ b/drivers/serial/serial_sh.c > @@ -17,6 +17,8 @@ > #include <linux/compiler.h> > #include <dm/platform_data/serial_sh.h> > #include <linux/delay.h> > +#include <dm/device_compat.h> > +#include <reset.h> > #include "serial_sh.h" > DECLARE_GLOBAL_DATA_PTR; > @@ -79,8 +81,16 @@ sh_serial_setbrg_generic(struct uart_port *port, int clk, int baudrate) > static void handle_error(struct uart_port *port) > { > - sci_in(port, SCxSR); > - sci_out(port, SCxSR, SCxSR_ERROR_CLEAR(port)); > + /* The RZ/G2L datasheet says that error conditions are cleared by > + * resetting the error bits in the FSR register to zero.
Can you be more specific here ?
It doesn't seem Linux sh-sci.c driver does anything special for G2L, so is this special case really needed ?
On page 1268 of the datasheet (R01UH0914EJ0130 Rev.1.30):
"DR is cleared to 0 when DR = 1 is read and then 0 is written to the DR flag."
On page 1270:
"[Clearing condition] ● When 0 is written to ER after it has been read as 1"
So zeros must be written to clear these errors, not ones.
We have an open task to investigate the issue in the Linux driver and fix it.
Is the G2L UART broken in Linux ?
Likely yes, but we need to reproduce the issue.
Does it misbehave in U-Boot ?
Yes, before I changed this, if a framing error occurred it could never be cleared and the serial port stopped sending/receiving data.
The framing error was triggered by accident by unnecessarily re-doing pinmuxing for the serial port after TrustedFirmware had already set it up correctly. Since SCIF0 is wired to an FTDI USB/serial adaptor chip on the SMARC carrier board, it seems very difficult to trigger a framing error in any other way, the FTDI chip is too well behaved.
Is it possible to trigger this on RZ/G2<non-L> with SCIF on those platforms as well ?
It's not been seen or reported to my knowledge, but it's on our list to look into further.
Can you give it a quick try ? I'd really like to avoid G2L specific behavior here if it can be avoided.
Is there a testcase ?

On 04/10/2023 20:41, Marek Vasut wrote:
On 10/4/23 18:38, Paul Barker wrote:
On Wed, Oct 04, 2023 at 05:17:55PM +0200, Marek Vasut wrote:
On 10/4/23 15:43, Paul Barker wrote:
On Wed, Oct 04, 2023 at 02:26:49PM +0200, Marek Vasut wrote:
On 10/4/23 10:48, Paul Barker wrote:
On 03/10/2023 14:23, Marek Vasut wrote: > On 9/20/23 14:42, Paul Barker wrote: >> Extend the existing driver to support the SCIF serial ports on the >> Renesas RZ/G2L (R9A07G044) SoC. This also requires us to ensure that the >> relevant reset signal is de-asserted before we try to talk to the SCIF >> module. >> >> Signed-off-by: Paul Barker paul.barker.ct@bp.renesas.com >> Reviewed-by: Biju Das biju.das.jz@bp.renesas.com >> Reviewed-by: Lad Prabhakar prabhakar.mahadev-lad.rj@bp.renesas.com >> --- >> arch/arm/mach-rmobile/Kconfig | 1 + >> drivers/serial/serial_sh.c | 32 ++++++++++++++++++++++++++++++-- >> drivers/serial/serial_sh.h | 19 ++++++++++++++++++- >> 3 files changed, 49 insertions(+), 3 deletions(-) >> >> diff --git a/arch/arm/mach-rmobile/Kconfig b/arch/arm/mach-rmobile/Kconfig >> index 973e84fcf7ba..0ab22356aee5 100644 >> --- a/arch/arm/mach-rmobile/Kconfig >> +++ b/arch/arm/mach-rmobile/Kconfig >> @@ -77,6 +77,7 @@ config RZG2L >> imply RENESAS_SDHI >> imply CLK_RZG2L >> imply PINCTRL_RZG2L >> + imply SCIF_CONSOLE >> help >> Enable support for the Renesas RZ/G2L family of SoCs, including the >> the RZ/G2L itself (based on the R9A07G044 SoC). >> diff --git a/drivers/serial/serial_sh.c b/drivers/serial/serial_sh.c >> index 5e543dbf3d58..a2e9a57137a6 100644 >> --- a/drivers/serial/serial_sh.c >> +++ b/drivers/serial/serial_sh.c >> @@ -17,6 +17,8 @@ >> #include <linux/compiler.h> >> #include <dm/platform_data/serial_sh.h> >> #include <linux/delay.h> >> +#include <dm/device_compat.h> >> +#include <reset.h> >> #include "serial_sh.h" >> DECLARE_GLOBAL_DATA_PTR; >> @@ -79,8 +81,16 @@ sh_serial_setbrg_generic(struct uart_port *port, int clk, int baudrate) >> static void handle_error(struct uart_port *port) >> { >> - sci_in(port, SCxSR); >> - sci_out(port, SCxSR, SCxSR_ERROR_CLEAR(port)); >> + /* The RZ/G2L datasheet says that error conditions are cleared by >> + * resetting the error bits in the FSR register to zero. > > Can you be more specific here ? > > It doesn't seem Linux sh-sci.c driver does anything special for G2L, so > is this special case really needed ?
On page 1268 of the datasheet (R01UH0914EJ0130 Rev.1.30):
"DR is cleared to 0 when DR = 1 is read and then 0 is written to the DR flag."
On page 1270:
"[Clearing condition] ● When 0 is written to ER after it has been read as 1"
So zeros must be written to clear these errors, not ones.
We have an open task to investigate the issue in the Linux driver and fix it.
Is the G2L UART broken in Linux ?
Likely yes, but we need to reproduce the issue.
Does it misbehave in U-Boot ?
Yes, before I changed this, if a framing error occurred it could never be cleared and the serial port stopped sending/receiving data.
The framing error was triggered by accident by unnecessarily re-doing pinmuxing for the serial port after TrustedFirmware had already set it up correctly. Since SCIF0 is wired to an FTDI USB/serial adaptor chip on the SMARC carrier board, it seems very difficult to trigger a framing error in any other way, the FTDI chip is too well behaved.
Is it possible to trigger this on RZ/G2<non-L> with SCIF on those platforms as well ?
It's not been seen or reported to my knowledge, but it's on our list to look into further.
Can you give it a quick try ? I'd really like to avoid G2L specific behavior here if it can be avoided.
Is there a testcase ?
The case we're interested in here is the Receive Error (ER) & Break Detect (BRK) conditions. I've done some further datasheet digging...
RZ/G2L datasheet says these are cleared by writing zero to the appropriate bits of the FSR register.
RZ/G2{H,M,N,E} datasheet says the same (pages 50-18 & 50-19 of R01UH0808EJ0111 Rev.1.11).
The R-Car Gen3 Hardware Manual says the same (pages 55-18 & 55-19 of R19UH0105EJ0230 Rev.2.30).
For R-Car S4, there is an Excel spreadsheet attached to page 105-5 of the datasheet (R19UH0161EJ0100 Rev.1.00) which again says the same.
For R-Car V4H, the relevant info is on pages 105-16 & 105-18 of the datasheet (R19UH0172EJ0081 Rev.0.81) and says the same.
On the RZ/G2L I was able to reproduce a break condition by changing pinmux settings after the SCIF interface has been configured. You could try this out on an R-Car system, but I don't think it's guaranteed to cause a break condition, it may depend on how the port input is implemented in those SoCs. From my reading, the only guaranteed way to cause a break condition is to hold the Rx signal low, and you might need to solder on some extra wires on to a board to be able to do that.
We should still fix the error handling here, even if the boards we have don't easily cause Receive Errors or Break conditions, other folks may have their own boards based on these SoCs.
If you're happy I'll go ahead and check IS_ENABLED(CONFIG_RCAR_64) here instead of IS_ENABLED(CONFIG_RZG2L).
Thanks, Paul

On 10/5/23 14:08, Paul Barker wrote:
On 04/10/2023 20:41, Marek Vasut wrote:
On 10/4/23 18:38, Paul Barker wrote:
On Wed, Oct 04, 2023 at 05:17:55PM +0200, Marek Vasut wrote:
On 10/4/23 15:43, Paul Barker wrote:
On Wed, Oct 04, 2023 at 02:26:49PM +0200, Marek Vasut wrote:
On 10/4/23 10:48, Paul Barker wrote: > On 03/10/2023 14:23, Marek Vasut wrote: >> On 9/20/23 14:42, Paul Barker wrote: >>> Extend the existing driver to support the SCIF serial ports on the >>> Renesas RZ/G2L (R9A07G044) SoC. This also requires us to ensure that the >>> relevant reset signal is de-asserted before we try to talk to the SCIF >>> module. >>> >>> Signed-off-by: Paul Barker paul.barker.ct@bp.renesas.com >>> Reviewed-by: Biju Das biju.das.jz@bp.renesas.com >>> Reviewed-by: Lad Prabhakar prabhakar.mahadev-lad.rj@bp.renesas.com >>> --- >>> arch/arm/mach-rmobile/Kconfig | 1 + >>> drivers/serial/serial_sh.c | 32 ++++++++++++++++++++++++++++++-- >>> drivers/serial/serial_sh.h | 19 ++++++++++++++++++- >>> 3 files changed, 49 insertions(+), 3 deletions(-) >>> >>> diff --git a/arch/arm/mach-rmobile/Kconfig b/arch/arm/mach-rmobile/Kconfig >>> index 973e84fcf7ba..0ab22356aee5 100644 >>> --- a/arch/arm/mach-rmobile/Kconfig >>> +++ b/arch/arm/mach-rmobile/Kconfig >>> @@ -77,6 +77,7 @@ config RZG2L >>> imply RENESAS_SDHI >>> imply CLK_RZG2L >>> imply PINCTRL_RZG2L >>> + imply SCIF_CONSOLE >>> help >>> Enable support for the Renesas RZ/G2L family of SoCs, including the >>> the RZ/G2L itself (based on the R9A07G044 SoC). >>> diff --git a/drivers/serial/serial_sh.c b/drivers/serial/serial_sh.c >>> index 5e543dbf3d58..a2e9a57137a6 100644 >>> --- a/drivers/serial/serial_sh.c >>> +++ b/drivers/serial/serial_sh.c >>> @@ -17,6 +17,8 @@ >>> #include <linux/compiler.h> >>> #include <dm/platform_data/serial_sh.h> >>> #include <linux/delay.h> >>> +#include <dm/device_compat.h> >>> +#include <reset.h> >>> #include "serial_sh.h" >>> DECLARE_GLOBAL_DATA_PTR; >>> @@ -79,8 +81,16 @@ sh_serial_setbrg_generic(struct uart_port *port, int clk, int baudrate) >>> static void handle_error(struct uart_port *port) >>> { >>> - sci_in(port, SCxSR); >>> - sci_out(port, SCxSR, SCxSR_ERROR_CLEAR(port)); >>> + /* The RZ/G2L datasheet says that error conditions are cleared by >>> + * resetting the error bits in the FSR register to zero. >> >> Can you be more specific here ? >> >> It doesn't seem Linux sh-sci.c driver does anything special for G2L, so >> is this special case really needed ? > > On page 1268 of the datasheet (R01UH0914EJ0130 Rev.1.30): > > "DR is cleared to 0 when DR = 1 is read and then 0 is written to the DR > flag." > > On page 1270: > > "[Clearing condition] > ● When 0 is written to ER after it has been read as 1" > > So zeros must be written to clear these errors, not ones. > > We have an open task to investigate the issue in the Linux driver and > fix it.
Is the G2L UART broken in Linux ?
Likely yes, but we need to reproduce the issue.
Does it misbehave in U-Boot ?
Yes, before I changed this, if a framing error occurred it could never be cleared and the serial port stopped sending/receiving data.
The framing error was triggered by accident by unnecessarily re-doing pinmuxing for the serial port after TrustedFirmware had already set it up correctly. Since SCIF0 is wired to an FTDI USB/serial adaptor chip on the SMARC carrier board, it seems very difficult to trigger a framing error in any other way, the FTDI chip is too well behaved.
Is it possible to trigger this on RZ/G2<non-L> with SCIF on those platforms as well ?
It's not been seen or reported to my knowledge, but it's on our list to look into further.
Can you give it a quick try ? I'd really like to avoid G2L specific behavior here if it can be avoided.
Is there a testcase ?
The case we're interested in here is the Receive Error (ER) & Break Detect (BRK) conditions. I've done some further datasheet digging...
RZ/G2L datasheet says these are cleared by writing zero to the appropriate bits of the FSR register.
RZ/G2{H,M,N,E} datasheet says the same (pages 50-18 & 50-19 of R01UH0808EJ0111 Rev.1.11).
The R-Car Gen3 Hardware Manual says the same (pages 55-18 & 55-19 of R19UH0105EJ0230 Rev.2.30).
For R-Car S4, there is an Excel spreadsheet attached to page 105-5 of the datasheet (R19UH0161EJ0100 Rev.1.00) which again says the same.
For R-Car V4H, the relevant info is on pages 105-16 & 105-18 of the datasheet (R19UH0172EJ0081 Rev.0.81) and says the same.
On the RZ/G2L I was able to reproduce a break condition by changing pinmux settings after the SCIF interface has been configured. You could try this out on an R-Car system, but I don't think it's guaranteed to cause a break condition, it may depend on how the port input is implemented in those SoCs. From my reading, the only guaranteed way to cause a break condition is to hold the Rx signal low, and you might need to solder on some extra wires on to a board to be able to do that.
Can't you simply send a BREAK from terminal program ? In minicom, I think that's meta-F B .
We should still fix the error handling here, even if the boards we have don't easily cause Receive Errors or Break conditions, other folks may have their own boards based on these SoCs.
If you're happy I'll go ahead and check IS_ENABLED(CONFIG_RCAR_64) here instead of IS_ENABLED(CONFIG_RZG2L).
Based on the input I am getting from you here, it seems to me we should just use the G2L case as the common case for all systems, without any special casing, right ?

On Sat, Oct 07, 2023 at 11:14:06PM +0200, Marek Vasut wrote:
On 10/5/23 14:08, Paul Barker wrote:
The case we're interested in here is the Receive Error (ER) & Break Detect (BRK) conditions. I've done some further datasheet digging...
RZ/G2L datasheet says these are cleared by writing zero to the appropriate bits of the FSR register.
RZ/G2{H,M,N,E} datasheet says the same (pages 50-18 & 50-19 of R01UH0808EJ0111 Rev.1.11).
The R-Car Gen3 Hardware Manual says the same (pages 55-18 & 55-19 of R19UH0105EJ0230 Rev.2.30).
For R-Car S4, there is an Excel spreadsheet attached to page 105-5 of the datasheet (R19UH0161EJ0100 Rev.1.00) which again says the same.
For R-Car V4H, the relevant info is on pages 105-16 & 105-18 of the datasheet (R19UH0172EJ0081 Rev.0.81) and says the same.
On the RZ/G2L I was able to reproduce a break condition by changing pinmux settings after the SCIF interface has been configured. You could try this out on an R-Car system, but I don't think it's guaranteed to cause a break condition, it may depend on how the port input is implemented in those SoCs. From my reading, the only guaranteed way to cause a break condition is to hold the Rx signal low, and you might need to solder on some extra wires on to a board to be able to do that.
Can't you simply send a BREAK from terminal program ? In minicom, I think that's meta-F B .
We should still fix the error handling here, even if the boards we have don't easily cause Receive Errors or Break conditions, other folks may have their own boards based on these SoCs.
If you're happy I'll go ahead and check IS_ENABLED(CONFIG_RCAR_64) here instead of IS_ENABLED(CONFIG_RZG2L).
Based on the input I am getting from you here, it seems to me we should just use the G2L case as the common case for all systems, without any special casing, right ?
I assumed that the code that's in place here was correct for some older SoC when it was added to u-boot. But I've just looked at the SH7751 datasheet this morning and guess what? It requires writing zeros to clear the errors.
As long as SCIF_ERRORS is correctly defined for each SoC, then yes, it looks like we can drop the conditional.
I'll include this in v2.
Thanks, Paul

On 04/10/2023 13:26, Marek Vasut wrote:
On 10/4/23 10:48, Paul Barker wrote:
On 03/10/2023 14:23, Marek Vasut wrote:
On 9/20/23 14:42, Paul Barker wrote:
- if (IS_ENABLED(CONFIG_RZG2L)) {
struct reset_ctl rst;
int ret;
ret = reset_get_by_index(dev, 0, &rst);
if (ret < 0) {
dev_err(dev, "failed to get reset line\n");
return ret;
}
ret = reset_deassert(&rst);
if (ret < 0) {
dev_err(dev, "failed to de-assert reset line\n");
return ret;
}
- }
devm_reset_control_get_optional() or something should do here too , right ?
Note that R-Car does have SCIF reset too, so this can be generic code.
For R-Car systems the current behaviour is working and well tested, we concluded that we shouldn't change it so this reset de-assert was made RZ/G2L specific.
I can test on R-Car just fine, no worries.
SH R2Dplus is even tested in CI nightly.
For RZ/G2L, de-asserting the reset is not optional.
Let's avoid special-cases like that.
Looking at this again, I don't see how we can avoid a special case here, de-asserting the reset is required for the RZ/G2L. It may be optional on other SoCs (I don't know), but it's definitely not optional here, so I don't think we should be using the devm_reset_control_get_optional() function.
Thanks, Paul

On 10/5/23 18:18, Paul Barker wrote:
On 04/10/2023 13:26, Marek Vasut wrote:
On 10/4/23 10:48, Paul Barker wrote:
On 03/10/2023 14:23, Marek Vasut wrote:
On 9/20/23 14:42, Paul Barker wrote:
- if (IS_ENABLED(CONFIG_RZG2L)) {
struct reset_ctl rst;
int ret;
ret = reset_get_by_index(dev, 0, &rst);
if (ret < 0) {
dev_err(dev, "failed to get reset line\n");
return ret;
}
ret = reset_deassert(&rst);
if (ret < 0) {
dev_err(dev, "failed to de-assert reset line\n");
return ret;
}
- }
devm_reset_control_get_optional() or something should do here too , right ?
Note that R-Car does have SCIF reset too, so this can be generic code.
For R-Car systems the current behaviour is working and well tested, we concluded that we shouldn't change it so this reset de-assert was made RZ/G2L specific.
I can test on R-Car just fine, no worries.
SH R2Dplus is even tested in CI nightly.
For RZ/G2L, de-asserting the reset is not optional.
Let's avoid special-cases like that.
Looking at this again, I don't see how we can avoid a special case here, de-asserting the reset is required for the RZ/G2L. It may be optional on other SoCs (I don't know), but it's definitely not optional here, so I don't think we should be using the devm_reset_control_get_optional() function.
I'd say let's just unconditionally assume reset is needed for all platforms. That should work, right ?

On the Renesas RZ/G2L SoC family, we must ensure that the required clock signals are enabled and the reset signal is de-asserted before we try to communicate with the SDHI module.
Signed-off-by: Paul Barker paul.barker.ct@bp.renesas.com Reviewed-by: Biju Das biju.das.jz@bp.renesas.com Reviewed-by: Lad Prabhakar prabhakar.mahadev-lad.rj@bp.renesas.com --- drivers/mmc/renesas-sdhi.c | 61 ++++++++++++++++++++++++++++++++++++++ 1 file changed, 61 insertions(+)
diff --git a/drivers/mmc/renesas-sdhi.c b/drivers/mmc/renesas-sdhi.c index 8e716f74491f..170c5dcc2ebe 100644 --- a/drivers/mmc/renesas-sdhi.c +++ b/drivers/mmc/renesas-sdhi.c @@ -20,6 +20,7 @@ #include <linux/io.h> #include <linux/sizes.h> #include <power/regulator.h> +#include <reset.h> #include <asm/unaligned.h> #include "tmio-common.h"
@@ -964,6 +965,8 @@ static int renesas_sdhi_probe(struct udevice *dev) u32 quirks = dev_get_driver_data(dev); struct fdt_resource reg_res; DECLARE_GLOBAL_DATA_PTR; + struct clk imclk2, aclk; + struct reset_ctl rst; int ret;
priv->clk_get_rate = renesas_sdhi_clk_get_rate; @@ -1012,6 +1015,49 @@ static int renesas_sdhi_probe(struct udevice *dev) goto err_clkh; }
+ if (IS_ENABLED(CONFIG_RZG2L)) { + /* + * On members of the RZ/G2L SoC family, we need to enable + * additional chip detect and bus clocks, then release the SDHI + * module from reset. + */ + ret = clk_get_by_name(dev, "cd", &imclk2); + if (ret < 0) { + dev_err(dev, "failed to get imclk2 (chip detect clk)\n"); + goto err_get_imclk2; + } + + ret = clk_get_by_name(dev, "aclk", &aclk); + if (ret < 0) { + dev_err(dev, "failed to get aclk\n"); + goto err_get_aclk; + } + + ret = clk_enable(&imclk2); + if (ret < 0) { + dev_err(dev, "failed to enable imclk2 (chip detect clk)\n"); + goto err_imclk2; + } + + ret = clk_enable(&aclk); + if (ret < 0) { + dev_err(dev, "failed to enable aclk\n"); + goto err_aclk; + } + + ret = reset_get_by_index(dev, 0, &rst); + if (ret < 0) { + dev_err(dev, "failed to get reset line\n"); + goto err_reset; + } + + ret = reset_deassert(&rst); + if (ret < 0) { + dev_err(dev, "failed to de-assert reset line\n"); + goto err_reset; + } + } + priv->quirks = quirks; ret = tmio_sd_probe(dev, quirks); if (ret) @@ -1028,6 +1074,21 @@ static int renesas_sdhi_probe(struct udevice *dev) return 0;
err_tmio_probe: + if (IS_ENABLED(CONFIG_RZG2L)) + reset_assert(&rst); +err_reset: + if (IS_ENABLED(CONFIG_RZG2L)) + clk_disable(&aclk); +err_aclk: + if (IS_ENABLED(CONFIG_RZG2L)) + clk_disable(&imclk2); +err_imclk2: + if (IS_ENABLED(CONFIG_RZG2L)) + clk_free(&aclk); +err_get_aclk: + if (IS_ENABLED(CONFIG_RZG2L)) + clk_free(&imclk2); +err_get_imclk2: clk_disable(&priv->clk); err_clkh: clk_free(&priv->clkh);

On 9/20/23 14:42, Paul Barker wrote:
On the Renesas RZ/G2L SoC family, we must ensure that the required clock signals are enabled and the reset signal is de-asserted before we try to communicate with the SDHI module.
Signed-off-by: Paul Barker paul.barker.ct@bp.renesas.com Reviewed-by: Biju Das biju.das.jz@bp.renesas.com Reviewed-by: Lad Prabhakar prabhakar.mahadev-lad.rj@bp.renesas.com
drivers/mmc/renesas-sdhi.c | 61 ++++++++++++++++++++++++++++++++++++++ 1 file changed, 61 insertions(+)
diff --git a/drivers/mmc/renesas-sdhi.c b/drivers/mmc/renesas-sdhi.c index 8e716f74491f..170c5dcc2ebe 100644 --- a/drivers/mmc/renesas-sdhi.c +++ b/drivers/mmc/renesas-sdhi.c @@ -20,6 +20,7 @@ #include <linux/io.h> #include <linux/sizes.h> #include <power/regulator.h> +#include <reset.h> #include <asm/unaligned.h> #include "tmio-common.h"
@@ -964,6 +965,8 @@ static int renesas_sdhi_probe(struct udevice *dev) u32 quirks = dev_get_driver_data(dev); struct fdt_resource reg_res; DECLARE_GLOBAL_DATA_PTR;
struct clk imclk2, aclk;
struct reset_ctl rst; int ret;
priv->clk_get_rate = renesas_sdhi_clk_get_rate;
@@ -1012,6 +1015,49 @@ static int renesas_sdhi_probe(struct udevice *dev) goto err_clkh; }
- if (IS_ENABLED(CONFIG_RZG2L)) {
/*
* On members of the RZ/G2L SoC family, we need to enable
* additional chip detect and bus clocks, then release the SDHI
* module from reset.
*/
This could use a separate function, and then, use bulk clock API via clk_get_bulk() and co .
ret = clk_get_by_name(dev, "cd", &imclk2);
if (ret < 0) {
dev_err(dev, "failed to get imclk2 (chip detect clk)\n");
goto err_get_imclk2;
}
[...]

On 03/10/2023 14:25, Marek Vasut wrote:
On 9/20/23 14:42, Paul Barker wrote:
On the Renesas RZ/G2L SoC family, we must ensure that the required clock signals are enabled and the reset signal is de-asserted before we try to communicate with the SDHI module.
Signed-off-by: Paul Barker paul.barker.ct@bp.renesas.com Reviewed-by: Biju Das biju.das.jz@bp.renesas.com Reviewed-by: Lad Prabhakar prabhakar.mahadev-lad.rj@bp.renesas.com
drivers/mmc/renesas-sdhi.c | 61 ++++++++++++++++++++++++++++++++++++++ 1 file changed, 61 insertions(+)
diff --git a/drivers/mmc/renesas-sdhi.c b/drivers/mmc/renesas-sdhi.c index 8e716f74491f..170c5dcc2ebe 100644 --- a/drivers/mmc/renesas-sdhi.c +++ b/drivers/mmc/renesas-sdhi.c @@ -20,6 +20,7 @@ #include <linux/io.h> #include <linux/sizes.h> #include <power/regulator.h> +#include <reset.h> #include <asm/unaligned.h> #include "tmio-common.h"
@@ -964,6 +965,8 @@ static int renesas_sdhi_probe(struct udevice *dev) u32 quirks = dev_get_driver_data(dev); struct fdt_resource reg_res; DECLARE_GLOBAL_DATA_PTR;
struct clk imclk2, aclk;
struct reset_ctl rst; int ret;
priv->clk_get_rate = renesas_sdhi_clk_get_rate;
@@ -1012,6 +1015,49 @@ static int renesas_sdhi_probe(struct udevice *dev) goto err_clkh; }
- if (IS_ENABLED(CONFIG_RZG2L)) {
/*
* On members of the RZ/G2L SoC family, we need to enable
* additional chip detect and bus clocks, then release the SDHI
* module from reset.
*/
This could use a separate function, and then, use bulk clock API via clk_get_bulk() and co .
There are 4 clocks defined in the dtb: "core", "clkh", "cd", "aclk".
During probe, we want to enable "core", "cd" (aka "imclk2" in the datasheet) and "aclk" but not "clkh". The driver enables "clkh" later as needed for high speed modes. So I don't think we want to bulk enable everything here.
By "separate function", are you suggesting an entire separate probe function for RZ/G2L SDHI? Or just moving what's inside the if(IS_ENABLED(CONFIG_RZG2L)) into a new function which we can call from renesas_sdhi_probe()?
Thanks, Paul

On 10/5/23 18:35, Paul Barker wrote:
On 03/10/2023 14:25, Marek Vasut wrote:
On 9/20/23 14:42, Paul Barker wrote:
On the Renesas RZ/G2L SoC family, we must ensure that the required clock signals are enabled and the reset signal is de-asserted before we try to communicate with the SDHI module.
Signed-off-by: Paul Barker paul.barker.ct@bp.renesas.com Reviewed-by: Biju Das biju.das.jz@bp.renesas.com Reviewed-by: Lad Prabhakar prabhakar.mahadev-lad.rj@bp.renesas.com
drivers/mmc/renesas-sdhi.c | 61 ++++++++++++++++++++++++++++++++++++++ 1 file changed, 61 insertions(+)
diff --git a/drivers/mmc/renesas-sdhi.c b/drivers/mmc/renesas-sdhi.c index 8e716f74491f..170c5dcc2ebe 100644 --- a/drivers/mmc/renesas-sdhi.c +++ b/drivers/mmc/renesas-sdhi.c @@ -20,6 +20,7 @@ #include <linux/io.h> #include <linux/sizes.h> #include <power/regulator.h> +#include <reset.h> #include <asm/unaligned.h> #include "tmio-common.h"
@@ -964,6 +965,8 @@ static int renesas_sdhi_probe(struct udevice *dev) u32 quirks = dev_get_driver_data(dev); struct fdt_resource reg_res; DECLARE_GLOBAL_DATA_PTR;
struct clk imclk2, aclk;
struct reset_ctl rst; int ret;
priv->clk_get_rate = renesas_sdhi_clk_get_rate;
@@ -1012,6 +1015,49 @@ static int renesas_sdhi_probe(struct udevice *dev) goto err_clkh; }
- if (IS_ENABLED(CONFIG_RZG2L)) {
/*
* On members of the RZ/G2L SoC family, we need to enable
* additional chip detect and bus clocks, then release the SDHI
* module from reset.
*/
This could use a separate function, and then, use bulk clock API via clk_get_bulk() and co .
There are 4 clocks defined in the dtb: "core", "clkh", "cd", "aclk".
During probe, we want to enable "core", "cd" (aka "imclk2" in the datasheet) and "aclk" but not "clkh". The driver enables "clkh" later as needed for high speed modes. So I don't think we want to bulk enable everything here.
Aha, OK
By "separate function", are you suggesting an entire separate probe function for RZ/G2L SDHI? Or just moving what's inside the if(IS_ENABLED(CONFIG_RZG2L)) into a new function which we can call from renesas_sdhi_probe()?
The later, to avoid this huge ifdef within the probe
if (IS_ENABLED(CONFIG_RZG2L)) rzg2l_do_whatever_extra_stuff_is_needed();
Thanks !

We don't want to rely on source files including <asm/types.h> before <asm/arch/rmobile.h>.
Signed-off-by: Paul Barker paul.barker.ct@bp.renesas.com Reviewed-by: Biju Das biju.das.jz@bp.renesas.com Reviewed-by: Lad Prabhakar prabhakar.mahadev-lad.rj@bp.renesas.com --- arch/arm/mach-rmobile/include/mach/rmobile.h | 2 ++ 1 file changed, 2 insertions(+)
diff --git a/arch/arm/mach-rmobile/include/mach/rmobile.h b/arch/arm/mach-rmobile/include/mach/rmobile.h index d326d5545a6f..053ad08add00 100644 --- a/arch/arm/mach-rmobile/include/mach/rmobile.h +++ b/arch/arm/mach-rmobile/include/mach/rmobile.h @@ -45,6 +45,8 @@ #define RMOBILE_CPU_TYPE_R8A779G0 0x5C
#ifndef __ASSEMBLY__ +#include <asm/types.h> + const u8 *rzg_get_cpu_name(void); u32 rmobile_get_cpu_type(void); u32 rmobile_get_cpu_rev_integer(void);

On 03/10/2023 14:27, Marek Vasut wrote:
On 9/20/23 14:42, Paul Barker wrote:
We don't want to rely on source files including <asm/types.h> before <asm/arch/rmobile.h>.
What kind of error does this solve ?
Without this, <asm/types.h> must be included before <asm/arch/rmobile.h>, for example in include/configs/rzg2l-smarc.h added in patch 16, to avoid the following error:
CC arch/arm/lib/asm-offsets.s In file included from include/configs/rzg2l-smarc.h:9, from include/config.h:3, from include/common.h:16, from lib/asm-offsets.c:14: ./arch/arm/include/asm/arch/rmobile.h:49:7: error: unknown type name ‘u8’ 49 | const u8 *rzg_get_cpu_name(void); | ^~ In file included from include/configs/rzg2l-smarc.h:9, from include/config.h:3, from include/common.h:16, from arch/arm/lib/asm-offsets.c:19: ./arch/arm/include/asm/arch/rmobile.h:49:7: error: unknown type name ‘u8’ 49 | const u8 *rzg_get_cpu_name(void); | ^~ ./arch/arm/include/asm/arch/rmobile.h:50:1: error: unknown type name ‘u32’ 50 | u32 rmobile_get_cpu_type(void); | ^~~ ./arch/arm/include/asm/arch/rmobile.h:50:1: error: unknown type name ‘u32’ 50 | u32 rmobile_get_cpu_type(void); | ^~~ ./arch/arm/include/asm/arch/rmobile.h:51:1: error: unknown type name ‘u32’ 51 | u32 rmobile_get_cpu_rev_integer(void); | ^~~ ./arch/arm/include/asm/arch/rmobile.h:52:1: error: unknown type name ‘u32’ 52 | u32 rmobile_get_cpu_rev_fraction(void); | ^~~ ./arch/arm/include/asm/arch/rmobile.h:51:1: error: unknown type name ‘u32’ 51 | u32 rmobile_get_cpu_rev_integer(void); | ^~~ ./arch/arm/include/asm/arch/rmobile.h:52:1: error: unknown type name ‘u32’ 52 | u32 rmobile_get_cpu_rev_fraction(void); | ^~~ make[1]: *** [scripts/Makefile.build:146: arch/arm/lib/asm-offsets.s] Error 1 make[1]: *** Waiting for unfinished jobs.... make[1]: *** [scripts/Makefile.build:146: lib/asm-offsets.s] Error 1 make: *** [Makefile:1916: prepare0] Error 2
Thanks, Paul

On 10/4/23 10:57, Paul Barker wrote:
On 03/10/2023 14:27, Marek Vasut wrote:
On 9/20/23 14:42, Paul Barker wrote:
We don't want to rely on source files including <asm/types.h> before <asm/arch/rmobile.h>.
What kind of error does this solve ?
Without this, <asm/types.h> must be included before <asm/arch/rmobile.h>, for example in include/configs/rzg2l-smarc.h added in patch 16, to avoid the following error:
CC arch/arm/lib/asm-offsets.s In file included from include/configs/rzg2l-smarc.h:9, from include/config.h:3, from include/common.h:16, from lib/asm-offsets.c:14: ./arch/arm/include/asm/arch/rmobile.h:49:7: error: unknown type name ‘u8’ 49 | const u8 *rzg_get_cpu_name(void);
Hmmm, that's weird, why am I not hitting it with the rcar CPU name function too ?

On Wed, Oct 04, 2023 at 02:27:50PM +0200, Marek Vasut wrote:
On 10/4/23 10:57, Paul Barker wrote:
On 03/10/2023 14:27, Marek Vasut wrote:
On 9/20/23 14:42, Paul Barker wrote:
We don't want to rely on source files including <asm/types.h> before <asm/arch/rmobile.h>.
What kind of error does this solve ?
Without this, <asm/types.h> must be included before <asm/arch/rmobile.h>, for example in include/configs/rzg2l-smarc.h added in patch 16, to avoid the following error:
CC arch/arm/lib/asm-offsets.s In file included from include/configs/rzg2l-smarc.h:9, from include/config.h:3, from include/common.h:16, from lib/asm-offsets.c:14: ./arch/arm/include/asm/arch/rmobile.h:49:7: error: unknown type name ‘u8’ 49 | const u8 *rzg_get_cpu_name(void);
Hmmm, that's weird, why am I not hitting it with the rcar CPU name function too ?
arch/arm/mach-rmobile/include/mach/rcar-gen3-base.h includes <asm/types.h> as it uses the `u32` type.
However, arch/arm/mach-rmobile/include/mach/rzg2l.h doesn't use anything from <asm/types.h> so doesn't include it.
Thanks, Paul

On 10/4/23 15:48, Paul Barker wrote:
On Wed, Oct 04, 2023 at 02:27:50PM +0200, Marek Vasut wrote:
On 10/4/23 10:57, Paul Barker wrote:
On 03/10/2023 14:27, Marek Vasut wrote:
On 9/20/23 14:42, Paul Barker wrote:
We don't want to rely on source files including <asm/types.h> before <asm/arch/rmobile.h>.
What kind of error does this solve ?
Without this, <asm/types.h> must be included before <asm/arch/rmobile.h>, for example in include/configs/rzg2l-smarc.h added in patch 16, to avoid the following error:
CC arch/arm/lib/asm-offsets.s
In file included from include/configs/rzg2l-smarc.h:9, from include/config.h:3, from include/common.h:16, from lib/asm-offsets.c:14: ./arch/arm/include/asm/arch/rmobile.h:49:7: error: unknown type name ‘u8’ 49 | const u8 *rzg_get_cpu_name(void);
Hmmm, that's weird, why am I not hitting it with the rcar CPU name function too ?
arch/arm/mach-rmobile/include/mach/rcar-gen3-base.h includes <asm/types.h> as it uses the `u32` type.
However, arch/arm/mach-rmobile/include/mach/rzg2l.h doesn't use anything from <asm/types.h> so doesn't include it.
Shouldn't arch/arm/mach-rmobile/include/mach/rmobile.h include the types.h then ?

On Wed, Oct 04, 2023 at 05:19:43PM +0200, Marek Vasut wrote:
On 10/4/23 15:48, Paul Barker wrote:
On Wed, Oct 04, 2023 at 02:27:50PM +0200, Marek Vasut wrote:
On 10/4/23 10:57, Paul Barker wrote:
On 03/10/2023 14:27, Marek Vasut wrote:
On 9/20/23 14:42, Paul Barker wrote:
We don't want to rely on source files including <asm/types.h> before <asm/arch/rmobile.h>.
What kind of error does this solve ?
Without this, <asm/types.h> must be included before <asm/arch/rmobile.h>, for example in include/configs/rzg2l-smarc.h added in patch 16, to avoid the following error:
CC arch/arm/lib/asm-offsets.s
In file included from include/configs/rzg2l-smarc.h:9, from include/config.h:3, from include/common.h:16, from lib/asm-offsets.c:14: ./arch/arm/include/asm/arch/rmobile.h:49:7: error: unknown type name ‘u8’ 49 | const u8 *rzg_get_cpu_name(void);
Hmmm, that's weird, why am I not hitting it with the rcar CPU name function too ?
arch/arm/mach-rmobile/include/mach/rcar-gen3-base.h includes <asm/types.h> as it uses the `u32` type.
However, arch/arm/mach-rmobile/include/mach/rzg2l.h doesn't use anything from <asm/types.h> so doesn't include it.
Shouldn't arch/arm/mach-rmobile/include/mach/rmobile.h include the types.h then ?
That's what this patch adds.
Thanks, Paul

On 10/4/23 18:41, Paul Barker wrote:
On Wed, Oct 04, 2023 at 05:19:43PM +0200, Marek Vasut wrote:
On 10/4/23 15:48, Paul Barker wrote:
On Wed, Oct 04, 2023 at 02:27:50PM +0200, Marek Vasut wrote:
On 10/4/23 10:57, Paul Barker wrote:
On 03/10/2023 14:27, Marek Vasut wrote:
On 9/20/23 14:42, Paul Barker wrote: > We don't want to rely on source files including <asm/types.h> before > <asm/arch/rmobile.h>.
What kind of error does this solve ?
Without this, <asm/types.h> must be included before <asm/arch/rmobile.h>, for example in include/configs/rzg2l-smarc.h added in patch 16, to avoid the following error:
CC arch/arm/lib/asm-offsets.s
In file included from include/configs/rzg2l-smarc.h:9, from include/config.h:3, from include/common.h:16, from lib/asm-offsets.c:14: ./arch/arm/include/asm/arch/rmobile.h:49:7: error: unknown type name ‘u8’ 49 | const u8 *rzg_get_cpu_name(void);
Hmmm, that's weird, why am I not hitting it with the rcar CPU name function too ?
arch/arm/mach-rmobile/include/mach/rcar-gen3-base.h includes <asm/types.h> as it uses the `u32` type.
However, arch/arm/mach-rmobile/include/mach/rzg2l.h doesn't use anything from <asm/types.h> so doesn't include it.
Shouldn't arch/arm/mach-rmobile/include/mach/rmobile.h include the types.h then ?
That's what this patch adds.
Then this patch is
Reviewed-by: Marek Vasut marek.vasut+renesas@mailbox.org
Sorry for the noise.

The ARM TrustedFirmware code for the Renesas RZ/G2L SoC family passes a devicetree blob to the bootloader as an argument in the same was previous R-Car gen3/gen4 SoCs. This blob contains a compatible string which can be used to identify the particular SoC we are running on.
Signed-off-by: Paul Barker paul.barker.ct@bp.renesas.com Reviewed-by: Biju Das biju.das.jz@bp.renesas.com Reviewed-by: Lad Prabhakar prabhakar.mahadev-lad.rj@bp.renesas.com --- arch/arm/mach-rmobile/Makefile | 5 +- arch/arm/mach-rmobile/cpu_info-rzg2l.c | 63 ++++++++++++++++++++ arch/arm/mach-rmobile/include/mach/rmobile.h | 1 + 3 files changed, 68 insertions(+), 1 deletion(-) create mode 100644 arch/arm/mach-rmobile/cpu_info-rzg2l.c
diff --git a/arch/arm/mach-rmobile/Makefile b/arch/arm/mach-rmobile/Makefile index 4eddba53ed2a..45d6a0e2a28a 100644 --- a/arch/arm/mach-rmobile/Makefile +++ b/arch/arm/mach-rmobile/Makefile @@ -10,8 +10,11 @@ obj-$(CONFIG_DISPLAY_BOARDINFO) += board.o obj-$(CONFIG_TMU_TIMER) += ../../sh/lib/time.o obj-$(CONFIG_R8A7740) += lowlevel_init.o cpu_info-r8a7740.o pfc-r8a7740.o obj-$(CONFIG_RCAR_GEN2) += lowlevel_init_ca15.o cpu_info-rcar.o -obj-$(CONFIG_RCAR_64) += lowlevel_init_gen3.o cpu_info-rcar.o memmap-gen3.o +obj-$(CONFIG_RCAR_64) += lowlevel_init_gen3.o memmap-gen3.o +obj-$(CONFIG_RCAR_GEN3) += cpu_info-rcar.o +obj-$(CONFIG_RCAR_GEN4) += cpu_info-rcar.o obj-$(CONFIG_RZ_G2) += cpu_info-rzg.o +obj-$(CONFIG_RZG2L) += cpu_info-rzg2l.o
ifneq ($(CONFIG_R8A779A0),) obj-$(CONFIG_ARMV8_PSCI) += psci-r8a779a0.o diff --git a/arch/arm/mach-rmobile/cpu_info-rzg2l.c b/arch/arm/mach-rmobile/cpu_info-rzg2l.c new file mode 100644 index 000000000000..de4892ee901e --- /dev/null +++ b/arch/arm/mach-rmobile/cpu_info-rzg2l.c @@ -0,0 +1,63 @@ +// SPDX-License-Identifier: GPL-2.0 +/* + * Copyright (C) 2021,2023 Renesas Electronics Corporation + * + */ + +#include <common.h> +#include <asm/io.h> +#include <linux/libfdt.h> + +#define SYSC_LSI_DEVID 0x11020A04 + +/* If the firmware passed a device tree, use it for soc identification. */ +extern u64 rcar_atf_boot_args[]; + +/* CPU information table */ +struct tfa_info { + const char *soc_name; + const char *cpu_name; + u32 cpu_type; +}; + +static const struct tfa_info tfa_info[] = { + { "renesas,r9a07g044l2", "R9A07G044L", RMOBILE_CPU_TYPE_R9A07G044L }, +}; + +static const struct tfa_info invalid_tfa_info = { NULL, "(invalid)", 0 }; + +static const struct tfa_info *get_tfa_info(void) +{ + void *atf_fdt_blob = (void *)(rcar_atf_boot_args[1]); + + if (fdt_magic(atf_fdt_blob) == FDT_MAGIC) { + unsigned int i; + for (i = 0; i < ARRAY_SIZE(tfa_info); i++) { + if (!fdt_node_check_compatible(atf_fdt_blob, 0, + tfa_info[i].soc_name)) + return &tfa_info[i]; + } + } + + return &invalid_tfa_info; +} + +const u8 *rzg_get_cpu_name(void) +{ + return get_tfa_info()->cpu_name; +} + +u32 rmobile_get_cpu_type(void) +{ + return get_tfa_info()->cpu_type; +} + +u32 rmobile_get_cpu_rev_integer(void) +{ + return (readl(SYSC_LSI_DEVID) >> 28) + 1; +} + +u32 rmobile_get_cpu_rev_fraction(void) +{ + return 0; +} diff --git a/arch/arm/mach-rmobile/include/mach/rmobile.h b/arch/arm/mach-rmobile/include/mach/rmobile.h index 053ad08add00..88b8b78671b2 100644 --- a/arch/arm/mach-rmobile/include/mach/rmobile.h +++ b/arch/arm/mach-rmobile/include/mach/rmobile.h @@ -43,6 +43,7 @@ #define RMOBILE_CPU_TYPE_R8A779A0 0x59 #define RMOBILE_CPU_TYPE_R8A779F0 0x5A #define RMOBILE_CPU_TYPE_R8A779G0 0x5C +#define RMOBILE_CPU_TYPE_R9A07G044L 0x9A070440
#ifndef __ASSEMBLY__ #include <asm/types.h>

On 9/20/23 14:42, Paul Barker wrote:
The ARM TrustedFirmware code for the Renesas RZ/G2L SoC family passes a devicetree blob to the bootloader as an argument in the same was
same way (typo)
previous R-Car gen3/gen4 SoCs.
Gen3 / Gen4
This blob contains a compatible string which can be used to identify the particular SoC we are running on.
Why not read the PRR ?
[...]

On 03/10/2023 14:28, Marek Vasut wrote:
On 9/20/23 14:42, Paul Barker wrote:
The ARM TrustedFirmware code for the Renesas RZ/G2L SoC family passes a devicetree blob to the bootloader as an argument in the same was
same way (typo)
previous R-Car gen3/gen4 SoCs.
Gen3 / Gen4
This blob contains a compatible string which can be used to identify the particular SoC we are running on.
Why not read the PRR ?
Reading the DEVID & PRR registers is not sufficient to tell the SoCs apart.
From page 204 of the datasheet (R01UH0914EJ0130 Rev.1.30) regarding the DEVID register:
"Note: RZ/G2L and RZ/G2LC are the same value. If identification between G2L and G2LC is needed, read the value of address H’0_1186_1178. The value is below. H’0000_0000: RZ/G2L H’0000_0001: RZ/G2LC"
Address 0x11861178 is in the OTP region which can only be read from the secure world (i.e. TrustedFirmware). So we have to rely on TrustedFirmware to determine the SoC and pass this information to u-boot via an fdt blob.
Thanks, Paul

On 10/4/23 11:05, Paul Barker wrote:
On 03/10/2023 14:28, Marek Vasut wrote:
On 9/20/23 14:42, Paul Barker wrote:
The ARM TrustedFirmware code for the Renesas RZ/G2L SoC family passes a devicetree blob to the bootloader as an argument in the same was
same way (typo)
previous R-Car gen3/gen4 SoCs.
Gen3 / Gen4
This blob contains a compatible string which can be used to identify the particular SoC we are running on.
Why not read the PRR ?
Reading the DEVID & PRR registers is not sufficient to tell the SoCs apart.
From page 204 of the datasheet (R01UH0914EJ0130 Rev.1.30) regarding the DEVID register:
"Note: RZ/G2L and RZ/G2LC are the same value. If identification between G2L and G2LC is needed, read the value of address H’0_1186_1178. The value is below. H’0000_0000: RZ/G2L H’0000_0001: RZ/G2LC"
Address 0x11861178 is in the OTP region which can only be read from the secure world (i.e. TrustedFirmware). So we have to rely on TrustedFirmware to determine the SoC and pass this information to u-boot via an fdt blob.
This ^ really should go into the commit message :)

The memory map for the RZ/G2L family differs from that of previous R-Car gen3/gen4 SoCs.
A high level memory map can be seen in figure 5.2 (section 5.2.1) of the RZ/G2L data sheet rev 1.30 published May 12, 2023. A summary is included here (note that this is a 34-bit address space): * 0x0_0000_0000 - 0x0_0002_FFFF SRAM area * 0x0_0003_0000 - 0x0_0FFF_FFFF Reserved area * 0x0_1000_0000 - 0x0_1FFF_FFFF I/O register area * 0x0_2000_0000 - 0x0_2FFF_FFFF SPI Multi area * 0x0_3000_0000 - 0x0_3FFF_FFFF Reserved area * 0x0_4000_0000 - 0x1_3FFF_FFFF DDR area (4 GiB) * 0x1_4000_0000 - 0x3_FFFF_FFFF Reserved area
Within the DDR area, the first 128 MiB are reserved by TrustedFirmware.
Signed-off-by: Paul Barker paul.barker.ct@bp.renesas.com Reviewed-by: Biju Das biju.das.jz@bp.renesas.com Reviewed-by: Lad Prabhakar prabhakar.mahadev-lad.rj@bp.renesas.com --- arch/arm/mach-rmobile/Makefile | 8 +- arch/arm/mach-rmobile/memmap-rzg2l.c | 115 +++++++++++++++++++++++++++ 2 files changed, 119 insertions(+), 4 deletions(-) create mode 100644 arch/arm/mach-rmobile/memmap-rzg2l.c
diff --git a/arch/arm/mach-rmobile/Makefile b/arch/arm/mach-rmobile/Makefile index 45d6a0e2a28a..ff8b0c7bae25 100644 --- a/arch/arm/mach-rmobile/Makefile +++ b/arch/arm/mach-rmobile/Makefile @@ -10,11 +10,11 @@ obj-$(CONFIG_DISPLAY_BOARDINFO) += board.o obj-$(CONFIG_TMU_TIMER) += ../../sh/lib/time.o obj-$(CONFIG_R8A7740) += lowlevel_init.o cpu_info-r8a7740.o pfc-r8a7740.o obj-$(CONFIG_RCAR_GEN2) += lowlevel_init_ca15.o cpu_info-rcar.o -obj-$(CONFIG_RCAR_64) += lowlevel_init_gen3.o memmap-gen3.o -obj-$(CONFIG_RCAR_GEN3) += cpu_info-rcar.o -obj-$(CONFIG_RCAR_GEN4) += cpu_info-rcar.o +obj-$(CONFIG_RCAR_64) += lowlevel_init_gen3.o +obj-$(CONFIG_RCAR_GEN3) += cpu_info-rcar.o memmap-gen3.o +obj-$(CONFIG_RCAR_GEN4) += cpu_info-rcar.o memmap-gen3.o obj-$(CONFIG_RZ_G2) += cpu_info-rzg.o -obj-$(CONFIG_RZG2L) += cpu_info-rzg2l.o +obj-$(CONFIG_RZG2L) += cpu_info-rzg2l.o memmap-rzg2l.o
ifneq ($(CONFIG_R8A779A0),) obj-$(CONFIG_ARMV8_PSCI) += psci-r8a779a0.o diff --git a/arch/arm/mach-rmobile/memmap-rzg2l.c b/arch/arm/mach-rmobile/memmap-rzg2l.c new file mode 100644 index 000000000000..d0509424fb73 --- /dev/null +++ b/arch/arm/mach-rmobile/memmap-rzg2l.c @@ -0,0 +1,115 @@ +// SPDX-License-Identifier: GPL-2.0+ +/* + * Renesas RZ/G2L family memory map tables + * + * Copyright (C) 2017 Marek Vasut marek.vasut@gmail.com + * Copyright (C) 2023 Renesas Electronics Corp. + */ + +#include <common.h> +#include <asm/armv8/mmu.h> +#include <asm/global_data.h> +#include <cpu_func.h> + +#define RZG2L_NR_REGIONS 16 + +/* + * RZ/G2L supports up to 4 GiB RAM starting at 0x40000000, of + * which the first 128 MiB is reserved by TF-A. + */ +static struct mm_region rzg2l_mem_map[RZG2L_NR_REGIONS] = { + { + .virt = 0x0UL, + .phys = 0x0UL, + .size = 0x40000000UL, + .attrs = PTE_BLOCK_MEMTYPE(MT_DEVICE_NGNRNE) | + PTE_BLOCK_NON_SHARE | + PTE_BLOCK_PXN | PTE_BLOCK_UXN + }, { + .virt = 0x40000000UL, + .phys = 0x40000000UL, + .size = 0x03F00000UL, + .attrs = PTE_BLOCK_MEMTYPE(MT_NORMAL) | + PTE_BLOCK_INNER_SHARE + }, { + .virt = 0x47E00000UL, + .phys = 0x47E00000UL, + .size = 0xF8200000UL, + .attrs = PTE_BLOCK_MEMTYPE(MT_NORMAL) | + PTE_BLOCK_INNER_SHARE + }, { + /* List terminator */ + 0, + } +}; + +struct mm_region *mem_map = rzg2l_mem_map; + +DECLARE_GLOBAL_DATA_PTR; + +#define debug_memmap(i, map) \ + debug("memmap %d: virt 0x%llx -> phys 0x%llx, size=0x%llx, attrs=0x%llx\n", \ + i, map[i].virt, map[i].phys, map[i].size, map[i].attrs) + +void enable_caches(void) +{ + unsigned int bank, i = 0; + u64 start, size; + + /* Create map for register access */ + rzg2l_mem_map[i].virt = 0x0ULL; + rzg2l_mem_map[i].phys = 0x0ULL; + rzg2l_mem_map[i].size = 0x40000000ULL; + rzg2l_mem_map[i].attrs = PTE_BLOCK_MEMTYPE(MT_DEVICE_NGNRNE) | + PTE_BLOCK_NON_SHARE | + PTE_BLOCK_PXN | PTE_BLOCK_UXN; + debug_memmap(i, rzg2l_mem_map); + i++; + + /* Generate entries for DRAM in 32bit address space */ + for (bank = 0; bank < CONFIG_NR_DRAM_BANKS; bank++) { + start = gd->bd->bi_dram[bank].start; + size = gd->bd->bi_dram[bank].size; + + /* Skip empty DRAM banks */ + if (!size) + continue; + + /* Mark memory reserved by ATF as cacheable too. */ + if (start == 0x48000000) { + /* Unmark protection area (0x43F00000 to 0x47DFFFFF) */ + rzg2l_mem_map[i].virt = 0x40000000ULL; + rzg2l_mem_map[i].phys = 0x40000000ULL; + rzg2l_mem_map[i].size = 0x03F00000ULL; + rzg2l_mem_map[i].attrs = PTE_BLOCK_MEMTYPE(MT_NORMAL) | + PTE_BLOCK_INNER_SHARE; + debug_memmap(i, rzg2l_mem_map); + i++; + + start = 0x47E00000ULL; + size += 0x00200000ULL; + } + + rzg2l_mem_map[i].virt = start; + rzg2l_mem_map[i].phys = start; + rzg2l_mem_map[i].size = size; + rzg2l_mem_map[i].attrs = PTE_BLOCK_MEMTYPE(MT_NORMAL) | + PTE_BLOCK_INNER_SHARE; + debug_memmap(i, rzg2l_mem_map); + i++; + } + + /* Zero out the remaining regions. */ + for (; i < RZG2L_NR_REGIONS; i++) { + rzg2l_mem_map[i].virt = 0; + rzg2l_mem_map[i].phys = 0; + rzg2l_mem_map[i].size = 0; + rzg2l_mem_map[i].attrs = 0; + debug_memmap(i, rzg2l_mem_map); + } + + if (!icache_status()) + icache_enable(); + + dcache_enable(); +}

On 9/20/23 14:42, Paul Barker wrote:
The memory map for the RZ/G2L family differs from that of previous R-Car gen3/gen4 SoCs.
Gen3 / Gen4
A high level memory map can be seen in figure 5.2 (section 5.2.1) of the RZ/G2L data sheet rev 1.30 published May 12, 2023. A summary is included here (note that this is a 34-bit address space):
- 0x0_0000_0000 - 0x0_0002_FFFF SRAM area
- 0x0_0003_0000 - 0x0_0FFF_FFFF Reserved area
- 0x0_1000_0000 - 0x0_1FFF_FFFF I/O register area
- 0x0_2000_0000 - 0x0_2FFF_FFFF SPI Multi area
- 0x0_3000_0000 - 0x0_3FFF_FFFF Reserved area
- 0x0_4000_0000 - 0x1_3FFF_FFFF DDR area (4 GiB)
- 0x1_4000_0000 - 0x3_FFFF_FFFF Reserved area
Within the DDR area, the first 128 MiB are reserved by TrustedFirmware.
Signed-off-by: Paul Barker paul.barker.ct@bp.renesas.com Reviewed-by: Biju Das biju.das.jz@bp.renesas.com Reviewed-by: Lad Prabhakar prabhakar.mahadev-lad.rj@bp.renesas.com
arch/arm/mach-rmobile/Makefile | 8 +- arch/arm/mach-rmobile/memmap-rzg2l.c | 115 +++++++++++++++++++++++++++ 2 files changed, 119 insertions(+), 4 deletions(-) create mode 100644 arch/arm/mach-rmobile/memmap-rzg2l.c
diff --git a/arch/arm/mach-rmobile/Makefile b/arch/arm/mach-rmobile/Makefile index 45d6a0e2a28a..ff8b0c7bae25 100644 --- a/arch/arm/mach-rmobile/Makefile +++ b/arch/arm/mach-rmobile/Makefile @@ -10,11 +10,11 @@ obj-$(CONFIG_DISPLAY_BOARDINFO) += board.o obj-$(CONFIG_TMU_TIMER) += ../../sh/lib/time.o obj-$(CONFIG_R8A7740) += lowlevel_init.o cpu_info-r8a7740.o pfc-r8a7740.o obj-$(CONFIG_RCAR_GEN2) += lowlevel_init_ca15.o cpu_info-rcar.o -obj-$(CONFIG_RCAR_64) += lowlevel_init_gen3.o memmap-gen3.o -obj-$(CONFIG_RCAR_GEN3) += cpu_info-rcar.o -obj-$(CONFIG_RCAR_GEN4) += cpu_info-rcar.o +obj-$(CONFIG_RCAR_64) += lowlevel_init_gen3.o +obj-$(CONFIG_RCAR_GEN3) += cpu_info-rcar.o memmap-gen3.o +obj-$(CONFIG_RCAR_GEN4) += cpu_info-rcar.o memmap-gen3.o obj-$(CONFIG_RZ_G2) += cpu_info-rzg.o -obj-$(CONFIG_RZG2L) += cpu_info-rzg2l.o +obj-$(CONFIG_RZG2L) += cpu_info-rzg2l.o memmap-rzg2l.o
ifneq ($(CONFIG_R8A779A0),) obj-$(CONFIG_ARMV8_PSCI) += psci-r8a779a0.o diff --git a/arch/arm/mach-rmobile/memmap-rzg2l.c b/arch/arm/mach-rmobile/memmap-rzg2l.c new file mode 100644 index 000000000000..d0509424fb73 --- /dev/null +++ b/arch/arm/mach-rmobile/memmap-rzg2l.c @@ -0,0 +1,115 @@ +// SPDX-License-Identifier: GPL-2.0+ +/*
- Renesas RZ/G2L family memory map tables
- Copyright (C) 2017 Marek Vasut marek.vasut@gmail.com
- Copyright (C) 2023 Renesas Electronics Corp.
- */
+#include <common.h> +#include <asm/armv8/mmu.h> +#include <asm/global_data.h> +#include <cpu_func.h>
+#define RZG2L_NR_REGIONS 16
+/*
- RZ/G2L supports up to 4 GiB RAM starting at 0x40000000, of
- which the first 128 MiB is reserved by TF-A.
- */
Are those 4 GiB continuous , or is there some "low" mem alias and then full "high" mem above the 32bit barrier ?
+static struct mm_region rzg2l_mem_map[RZG2L_NR_REGIONS] = {
- {
.virt = 0x0UL,
.phys = 0x0UL,
.size = 0x40000000UL,
.attrs = PTE_BLOCK_MEMTYPE(MT_DEVICE_NGNRNE) |
PTE_BLOCK_NON_SHARE |
PTE_BLOCK_PXN | PTE_BLOCK_UXN
- }, {
.virt = 0x40000000UL,
.phys = 0x40000000UL,
.size = 0x03F00000UL,
.attrs = PTE_BLOCK_MEMTYPE(MT_NORMAL) |
PTE_BLOCK_INNER_SHARE
- }, {
.virt = 0x47E00000UL,
What's this part about ?
.phys = 0x47E00000UL,
.size = 0xF8200000UL,
.attrs = PTE_BLOCK_MEMTYPE(MT_NORMAL) |
PTE_BLOCK_INNER_SHARE
- }, {
/* List terminator */
0,
- }
+};
+struct mm_region *mem_map = rzg2l_mem_map;
+DECLARE_GLOBAL_DATA_PTR;
+#define debug_memmap(i, map) \
- debug("memmap %d: virt 0x%llx -> phys 0x%llx, size=0x%llx, attrs=0x%llx\n", \
i, map[i].virt, map[i].phys, map[i].size, map[i].attrs)
+void enable_caches(void) +{
- unsigned int bank, i = 0;
- u64 start, size;
- /* Create map for register access */
- rzg2l_mem_map[i].virt = 0x0ULL;
- rzg2l_mem_map[i].phys = 0x0ULL;
- rzg2l_mem_map[i].size = 0x40000000ULL;
- rzg2l_mem_map[i].attrs = PTE_BLOCK_MEMTYPE(MT_DEVICE_NGNRNE) |
PTE_BLOCK_NON_SHARE |
PTE_BLOCK_PXN | PTE_BLOCK_UXN;
- debug_memmap(i, rzg2l_mem_map);
- i++;
- /* Generate entries for DRAM in 32bit address space */
- for (bank = 0; bank < CONFIG_NR_DRAM_BANKS; bank++) {
start = gd->bd->bi_dram[bank].start;
size = gd->bd->bi_dram[bank].size;
/* Skip empty DRAM banks */
if (!size)
continue;
/* Mark memory reserved by ATF as cacheable too. */
if (start == 0x48000000) {
/* Unmark protection area (0x43F00000 to 0x47DFFFFF) */
rzg2l_mem_map[i].virt = 0x40000000ULL;
rzg2l_mem_map[i].phys = 0x40000000ULL;
rzg2l_mem_map[i].size = 0x03F00000ULL;
rzg2l_mem_map[i].attrs = PTE_BLOCK_MEMTYPE(MT_NORMAL) |
PTE_BLOCK_INNER_SHARE;
debug_memmap(i, rzg2l_mem_map);
i++;
start = 0x47E00000ULL;
size += 0x00200000ULL;
}
rzg2l_mem_map[i].virt = start;
rzg2l_mem_map[i].phys = start;
rzg2l_mem_map[i].size = size;
rzg2l_mem_map[i].attrs = PTE_BLOCK_MEMTYPE(MT_NORMAL) |
PTE_BLOCK_INNER_SHARE;
debug_memmap(i, rzg2l_mem_map);
i++;
- }
Is this somehow copied from R-Car ? Can this be deduplicated ?

On 03/10/2023 14:32, Marek Vasut wrote:
On 9/20/23 14:42, Paul Barker wrote:
The memory map for the RZ/G2L family differs from that of previous R-Car gen3/gen4 SoCs.
Gen3 / Gen4
A high level memory map can be seen in figure 5.2 (section 5.2.1) of the RZ/G2L data sheet rev 1.30 published May 12, 2023. A summary is included here (note that this is a 34-bit address space):
- 0x0_0000_0000 - 0x0_0002_FFFF SRAM area
- 0x0_0003_0000 - 0x0_0FFF_FFFF Reserved area
- 0x0_1000_0000 - 0x0_1FFF_FFFF I/O register area
- 0x0_2000_0000 - 0x0_2FFF_FFFF SPI Multi area
- 0x0_3000_0000 - 0x0_3FFF_FFFF Reserved area
- 0x0_4000_0000 - 0x1_3FFF_FFFF DDR area (4 GiB)
- 0x1_4000_0000 - 0x3_FFFF_FFFF Reserved area
Within the DDR area, the first 128 MiB are reserved by TrustedFirmware.
Signed-off-by: Paul Barker paul.barker.ct@bp.renesas.com Reviewed-by: Biju Das biju.das.jz@bp.renesas.com Reviewed-by: Lad Prabhakar prabhakar.mahadev-lad.rj@bp.renesas.com
arch/arm/mach-rmobile/Makefile | 8 +- arch/arm/mach-rmobile/memmap-rzg2l.c | 115 +++++++++++++++++++++++++++ 2 files changed, 119 insertions(+), 4 deletions(-) create mode 100644 arch/arm/mach-rmobile/memmap-rzg2l.c
diff --git a/arch/arm/mach-rmobile/Makefile b/arch/arm/mach-rmobile/Makefile index 45d6a0e2a28a..ff8b0c7bae25 100644 --- a/arch/arm/mach-rmobile/Makefile +++ b/arch/arm/mach-rmobile/Makefile @@ -10,11 +10,11 @@ obj-$(CONFIG_DISPLAY_BOARDINFO) += board.o obj-$(CONFIG_TMU_TIMER) += ../../sh/lib/time.o obj-$(CONFIG_R8A7740) += lowlevel_init.o cpu_info-r8a7740.o pfc-r8a7740.o obj-$(CONFIG_RCAR_GEN2) += lowlevel_init_ca15.o cpu_info-rcar.o -obj-$(CONFIG_RCAR_64) += lowlevel_init_gen3.o memmap-gen3.o -obj-$(CONFIG_RCAR_GEN3) += cpu_info-rcar.o -obj-$(CONFIG_RCAR_GEN4) += cpu_info-rcar.o +obj-$(CONFIG_RCAR_64) += lowlevel_init_gen3.o +obj-$(CONFIG_RCAR_GEN3) += cpu_info-rcar.o memmap-gen3.o +obj-$(CONFIG_RCAR_GEN4) += cpu_info-rcar.o memmap-gen3.o obj-$(CONFIG_RZ_G2) += cpu_info-rzg.o -obj-$(CONFIG_RZG2L) += cpu_info-rzg2l.o +obj-$(CONFIG_RZG2L) += cpu_info-rzg2l.o memmap-rzg2l.o
ifneq ($(CONFIG_R8A779A0),) obj-$(CONFIG_ARMV8_PSCI) += psci-r8a779a0.o diff --git a/arch/arm/mach-rmobile/memmap-rzg2l.c b/arch/arm/mach-rmobile/memmap-rzg2l.c new file mode 100644 index 000000000000..d0509424fb73 --- /dev/null +++ b/arch/arm/mach-rmobile/memmap-rzg2l.c @@ -0,0 +1,115 @@ +// SPDX-License-Identifier: GPL-2.0+ +/*
- Renesas RZ/G2L family memory map tables
- Copyright (C) 2017 Marek Vasut marek.vasut@gmail.com
- Copyright (C) 2023 Renesas Electronics Corp.
- */
+#include <common.h> +#include <asm/armv8/mmu.h> +#include <asm/global_data.h> +#include <cpu_func.h>
+#define RZG2L_NR_REGIONS 16
+/*
- RZ/G2L supports up to 4 GiB RAM starting at 0x40000000, of
- which the first 128 MiB is reserved by TF-A.
- */
Are those 4 GiB continuous , or is there some "low" mem alias and then full "high" mem above the 32bit barrier ?
This is a contiguous 4GB region, there's no aliased region on these SoCs.
+static struct mm_region rzg2l_mem_map[RZG2L_NR_REGIONS] = {
- {
.virt = 0x0UL,
.phys = 0x0UL,
.size = 0x40000000UL,
.attrs = PTE_BLOCK_MEMTYPE(MT_DEVICE_NGNRNE) |
PTE_BLOCK_NON_SHARE |
PTE_BLOCK_PXN | PTE_BLOCK_UXN
- }, {
.virt = 0x40000000UL,
.phys = 0x40000000UL,
.size = 0x03F00000UL,
.attrs = PTE_BLOCK_MEMTYPE(MT_NORMAL) |
PTE_BLOCK_INNER_SHARE
- }, {
.virt = 0x47E00000UL,
What's this part about ?
This is copied from the RCar Gen3 memory map.
.phys = 0x47E00000UL,
.size = 0xF8200000UL,
.attrs = PTE_BLOCK_MEMTYPE(MT_NORMAL) |
PTE_BLOCK_INNER_SHARE
- }, {
/* List terminator */
0,
- }
+};
+struct mm_region *mem_map = rzg2l_mem_map;
+DECLARE_GLOBAL_DATA_PTR;
+#define debug_memmap(i, map) \
- debug("memmap %d: virt 0x%llx -> phys 0x%llx, size=0x%llx, attrs=0x%llx\n", \
i, map[i].virt, map[i].phys, map[i].size, map[i].attrs)
+void enable_caches(void) +{
- unsigned int bank, i = 0;
- u64 start, size;
- /* Create map for register access */
- rzg2l_mem_map[i].virt = 0x0ULL;
- rzg2l_mem_map[i].phys = 0x0ULL;
- rzg2l_mem_map[i].size = 0x40000000ULL;
- rzg2l_mem_map[i].attrs = PTE_BLOCK_MEMTYPE(MT_DEVICE_NGNRNE) |
PTE_BLOCK_NON_SHARE |
PTE_BLOCK_PXN | PTE_BLOCK_UXN;
- debug_memmap(i, rzg2l_mem_map);
- i++;
- /* Generate entries for DRAM in 32bit address space */
- for (bank = 0; bank < CONFIG_NR_DRAM_BANKS; bank++) {
start = gd->bd->bi_dram[bank].start;
size = gd->bd->bi_dram[bank].size;
/* Skip empty DRAM banks */
if (!size)
continue;
/* Mark memory reserved by ATF as cacheable too. */
if (start == 0x48000000) {
/* Unmark protection area (0x43F00000 to 0x47DFFFFF) */
rzg2l_mem_map[i].virt = 0x40000000ULL;
rzg2l_mem_map[i].phys = 0x40000000ULL;
rzg2l_mem_map[i].size = 0x03F00000ULL;
rzg2l_mem_map[i].attrs = PTE_BLOCK_MEMTYPE(MT_NORMAL) |
PTE_BLOCK_INNER_SHARE;
debug_memmap(i, rzg2l_mem_map);
i++;
start = 0x47E00000ULL;
size += 0x00200000ULL;
}
rzg2l_mem_map[i].virt = start;
rzg2l_mem_map[i].phys = start;
rzg2l_mem_map[i].size = size;
rzg2l_mem_map[i].attrs = PTE_BLOCK_MEMTYPE(MT_NORMAL) |
PTE_BLOCK_INNER_SHARE;
debug_memmap(i, rzg2l_mem_map);
i++;
- }
Is this somehow copied from R-Car ? Can this be deduplicated ?
This is based on the R-Car memory map. We discussed internally whether to modify memmap-gen3.c or create a separate memmap-rzg2l.c and decided that it was safer not to change the known working code for R-Car systems.
To merge the two, we'll need to add a few if(IS_ENABLED(CONFIG_RZG2L)) conditionals to memmap-gen3.c. I'm happy to do that if that's the approach you'd prefer.
Thanks, Paul

On 10/4/23 11:18, Paul Barker wrote:
[...]
+static struct mm_region rzg2l_mem_map[RZG2L_NR_REGIONS] = {
- {
.virt = 0x0UL,
.phys = 0x0UL,
.size = 0x40000000UL,
.attrs = PTE_BLOCK_MEMTYPE(MT_DEVICE_NGNRNE) |
PTE_BLOCK_NON_SHARE |
PTE_BLOCK_PXN | PTE_BLOCK_UXN
- }, {
.virt = 0x40000000UL,
.phys = 0x40000000UL,
.size = 0x03F00000UL,
.attrs = PTE_BLOCK_MEMTYPE(MT_NORMAL) |
PTE_BLOCK_INNER_SHARE
- }, {
.virt = 0x47E00000UL,
What's this part about ?
This is copied from the RCar Gen3 memory map.
I suspected as much. Please recheck the memory map instead of copy-paste and make sure it is really matching the hardware.
.phys = 0x47E00000UL,
.size = 0xF8200000UL,
.attrs = PTE_BLOCK_MEMTYPE(MT_NORMAL) |
PTE_BLOCK_INNER_SHARE
- }, {
/* List terminator */
0,
- }
+};
+struct mm_region *mem_map = rzg2l_mem_map;
+DECLARE_GLOBAL_DATA_PTR;
+#define debug_memmap(i, map) \
- debug("memmap %d: virt 0x%llx -> phys 0x%llx, size=0x%llx, attrs=0x%llx\n", \
i, map[i].virt, map[i].phys, map[i].size, map[i].attrs)
+void enable_caches(void) +{
- unsigned int bank, i = 0;
- u64 start, size;
- /* Create map for register access */
- rzg2l_mem_map[i].virt = 0x0ULL;
- rzg2l_mem_map[i].phys = 0x0ULL;
- rzg2l_mem_map[i].size = 0x40000000ULL;
- rzg2l_mem_map[i].attrs = PTE_BLOCK_MEMTYPE(MT_DEVICE_NGNRNE) |
PTE_BLOCK_NON_SHARE |
PTE_BLOCK_PXN | PTE_BLOCK_UXN;
- debug_memmap(i, rzg2l_mem_map);
- i++;
- /* Generate entries for DRAM in 32bit address space */
- for (bank = 0; bank < CONFIG_NR_DRAM_BANKS; bank++) {
start = gd->bd->bi_dram[bank].start;
size = gd->bd->bi_dram[bank].size;
/* Skip empty DRAM banks */
if (!size)
continue;
/* Mark memory reserved by ATF as cacheable too. */
if (start == 0x48000000) {
/* Unmark protection area (0x43F00000 to 0x47DFFFFF) */
rzg2l_mem_map[i].virt = 0x40000000ULL;
rzg2l_mem_map[i].phys = 0x40000000ULL;
rzg2l_mem_map[i].size = 0x03F00000ULL;
rzg2l_mem_map[i].attrs = PTE_BLOCK_MEMTYPE(MT_NORMAL) |
PTE_BLOCK_INNER_SHARE;
debug_memmap(i, rzg2l_mem_map);
i++;
start = 0x47E00000ULL;
size += 0x00200000ULL;
}
rzg2l_mem_map[i].virt = start;
rzg2l_mem_map[i].phys = start;
rzg2l_mem_map[i].size = size;
rzg2l_mem_map[i].attrs = PTE_BLOCK_MEMTYPE(MT_NORMAL) |
PTE_BLOCK_INNER_SHARE;
debug_memmap(i, rzg2l_mem_map);
i++;
- }
Is this somehow copied from R-Car ? Can this be deduplicated ?
This is based on the R-Car memory map. We discussed internally whether to modify memmap-gen3.c or create a separate memmap-rzg2l.c and decided that it was safer not to change the known working code for R-Car systems.
To merge the two, we'll need to add a few if(IS_ENABLED(CONFIG_RZG2L)) conditionals to memmap-gen3.c. I'm happy to do that if that's the approach you'd prefer.
I suspect if you really align the memmap with your hardware, there will be even more differences. All right, lets stick with this setup for now.

On Wed, Oct 04, 2023 at 02:30:53PM +0200, Marek Vasut wrote:
On 10/4/23 11:18, Paul Barker wrote:
[...]
+static struct mm_region rzg2l_mem_map[RZG2L_NR_REGIONS] = {
- {
.virt = 0x0UL,
.phys = 0x0UL,
.size = 0x40000000UL,
.attrs = PTE_BLOCK_MEMTYPE(MT_DEVICE_NGNRNE) |
PTE_BLOCK_NON_SHARE |
PTE_BLOCK_PXN | PTE_BLOCK_UXN
- }, {
.virt = 0x40000000UL,
.phys = 0x40000000UL,
.size = 0x03F00000UL,
.attrs = PTE_BLOCK_MEMTYPE(MT_NORMAL) |
PTE_BLOCK_INNER_SHARE
- }, {
.virt = 0x47E00000UL,
What's this part about ?
This is copied from the RCar Gen3 memory map.
I suspected as much. Please recheck the memory map instead of copy-paste and make sure it is really matching the hardware.
Sorry, I wasn't specific enough there.
The addition of an entry at 0x40000000 of size 0x03F00000, followed by a gap until 0x47E00000, is coped from R-Car as the way TrustedFirmware and OP-TEE use the first 128MiB of system memory is the same. The mappings here are due to the software configuration of TrustedFirmware & OP-TEE, not due to the hardware.
The hardware itself has a pretty simple memory map which is shown in the commit message. The memory map in this file is complete.
I have a note in the commit that says "Within the DDR area, the first 128 MiB are reserved by TrustedFirmware.", I probably just need to expand on why we need the mappings at 0x40000000 and 0x47E00000, instead of just using the mapping from 0x48000000 that's in the dtb.
.phys = 0x47E00000UL,
.size = 0xF8200000UL,
.attrs = PTE_BLOCK_MEMTYPE(MT_NORMAL) |
PTE_BLOCK_INNER_SHARE
- }, {
/* List terminator */
0,
- }
+};
Thanks, Paul

On 10/4/23 15:54, Paul Barker wrote:
On Wed, Oct 04, 2023 at 02:30:53PM +0200, Marek Vasut wrote:
On 10/4/23 11:18, Paul Barker wrote:
[...]
+static struct mm_region rzg2l_mem_map[RZG2L_NR_REGIONS] = {
- {
.virt = 0x0UL,
.phys = 0x0UL,
.size = 0x40000000UL,
.attrs = PTE_BLOCK_MEMTYPE(MT_DEVICE_NGNRNE) |
PTE_BLOCK_NON_SHARE |
PTE_BLOCK_PXN | PTE_BLOCK_UXN
- }, {
.virt = 0x40000000UL,
.phys = 0x40000000UL,
.size = 0x03F00000UL,
.attrs = PTE_BLOCK_MEMTYPE(MT_NORMAL) |
PTE_BLOCK_INNER_SHARE
- }, {
.virt = 0x47E00000UL,
What's this part about ?
This is copied from the RCar Gen3 memory map.
I suspected as much. Please recheck the memory map instead of copy-paste and make sure it is really matching the hardware.
Sorry, I wasn't specific enough there.
The addition of an entry at 0x40000000 of size 0x03F00000, followed by a gap until 0x47E00000, is coped from R-Car as the way TrustedFirmware and OP-TEE use the first 128MiB of system memory is the same. The mappings here are due to the software configuration of TrustedFirmware & OP-TEE, not due to the hardware.
The hardware itself has a pretty simple memory map which is shown in the commit message. The memory map in this file is complete.
I have a note in the commit that says "Within the DDR area, the first 128 MiB are reserved by TrustedFirmware.", I probably just need to expand on why we need the mappings at 0x40000000 and 0x47E00000, instead of just using the mapping from 0x48000000 that's in the dtb.
Yes please :)
The better the commit message is, the easier the long term maintenance is.

The Renesas RZ/G2L SMARC Evaluation Board Kit consists of the RZ/G2L System-on-Module (SOM) based on the R9A07G044L2 SoC, and a common SMARC carrier board.
This patch is based on the corresponding Linux v6.5 device tree.
Signed-off-by: Paul Barker paul.barker.ct@bp.renesas.com Reviewed-by: Biju Das biju.das.jz@bp.renesas.com Reviewed-by: Lad Prabhakar prabhakar.mahadev-lad.rj@bp.renesas.com --- arch/arm/dts/Makefile | 3 + arch/arm/dts/r9a07g044.dtsi | 1273 +++++++++++++++++++++ arch/arm/dts/r9a07g044l2-smarc.dts | 18 + arch/arm/dts/r9a07g044l2.dtsi | 13 + arch/arm/dts/rz-smarc-common.dtsi | 183 +++ arch/arm/dts/rzg2l-smarc-pinfunction.dtsi | 137 +++ arch/arm/dts/rzg2l-smarc-som.dtsi | 353 ++++++ arch/arm/dts/rzg2l-smarc.dtsi | 144 +++ 8 files changed, 2124 insertions(+) create mode 100644 arch/arm/dts/r9a07g044.dtsi create mode 100644 arch/arm/dts/r9a07g044l2-smarc.dts create mode 100644 arch/arm/dts/r9a07g044l2.dtsi create mode 100644 arch/arm/dts/rz-smarc-common.dtsi create mode 100644 arch/arm/dts/rzg2l-smarc-pinfunction.dtsi create mode 100644 arch/arm/dts/rzg2l-smarc-som.dtsi create mode 100644 arch/arm/dts/rzg2l-smarc.dtsi
diff --git a/arch/arm/dts/Makefile b/arch/arm/dts/Makefile index 85fd5b1157b1..863c8378c8ec 100644 --- a/arch/arm/dts/Makefile +++ b/arch/arm/dts/Makefile @@ -1099,6 +1099,9 @@ dtb-$(CONFIG_RCAR_GEN4) += \ r8a779f0-spider-u-boot.dtb \ r8a779g0-white-hawk-u-boot.dtb
+dtb-$(CONFIG_TARGET_RZG2L) += \ + r9a07g044l2-smarc.dts + ifdef CONFIG_RCAR_64 DTC_FLAGS += -R 4 -p 0x1000 endif diff --git a/arch/arm/dts/r9a07g044.dtsi b/arch/arm/dts/r9a07g044.dtsi new file mode 100644 index 000000000000..232910e07444 --- /dev/null +++ b/arch/arm/dts/r9a07g044.dtsi @@ -0,0 +1,1273 @@ +// SPDX-License-Identifier: (GPL-2.0-only OR BSD-2-Clause) +/* + * Device Tree Source for the RZ/G2L and RZ/G2LC common SoC parts + * + * Copyright (C) 2021 Renesas Electronics Corp. + */ + +#include <dt-bindings/interrupt-controller/arm-gic.h> +#include <dt-bindings/clock/r9a07g044-cpg.h> + +/ { + compatible = "renesas,r9a07g044"; + #address-cells = <2>; + #size-cells = <2>; + + audio_clk1: audio1-clk { + compatible = "fixed-clock"; + #clock-cells = <0>; + /* This value must be overridden by boards that provide it */ + clock-frequency = <0>; + }; + + audio_clk2: audio2-clk { + compatible = "fixed-clock"; + #clock-cells = <0>; + /* This value must be overridden by boards that provide it */ + clock-frequency = <0>; + }; + + /* External CAN clock - to be overridden by boards that provide it */ + can_clk: can-clk { + compatible = "fixed-clock"; + #clock-cells = <0>; + clock-frequency = <0>; + }; + + /* clock can be either from exclk or crystal oscillator (XIN/XOUT) */ + extal_clk: extal-clk { + compatible = "fixed-clock"; + #clock-cells = <0>; + /* This value must be overridden by the board */ + clock-frequency = <0>; + }; + + cluster0_opp: opp-table-0 { + compatible = "operating-points-v2"; + opp-shared; + + opp-150000000 { + opp-hz = /bits/ 64 <150000000>; + opp-microvolt = <1100000>; + clock-latency-ns = <300000>; + }; + opp-300000000 { + opp-hz = /bits/ 64 <300000000>; + opp-microvolt = <1100000>; + clock-latency-ns = <300000>; + }; + opp-600000000 { + opp-hz = /bits/ 64 <600000000>; + opp-microvolt = <1100000>; + clock-latency-ns = <300000>; + }; + opp-1200000000 { + opp-hz = /bits/ 64 <1200000000>; + opp-microvolt = <1100000>; + clock-latency-ns = <300000>; + opp-suspend; + }; + }; + + cpus { + #address-cells = <1>; + #size-cells = <0>; + + cpu-map { + cluster0 { + core0 { + cpu = <&cpu0>; + }; + core1 { + cpu = <&cpu1>; + }; + }; + }; + + cpu0: cpu@0 { + compatible = "arm,cortex-a55"; + reg = <0>; + device_type = "cpu"; + #cooling-cells = <2>; + next-level-cache = <&L3_CA55>; + enable-method = "psci"; + clocks = <&cpg CPG_CORE R9A07G044_CLK_I>; + operating-points-v2 = <&cluster0_opp>; + }; + + cpu1: cpu@100 { + compatible = "arm,cortex-a55"; + reg = <0x100>; + device_type = "cpu"; + next-level-cache = <&L3_CA55>; + enable-method = "psci"; + clocks = <&cpg CPG_CORE R9A07G044_CLK_I>; + operating-points-v2 = <&cluster0_opp>; + }; + + L3_CA55: cache-controller-0 { + compatible = "cache"; + cache-unified; + cache-size = <0x40000>; + cache-level = <3>; + }; + }; + + gpu_opp_table: opp-table-1 { + compatible = "operating-points-v2"; + + opp-500000000 { + opp-hz = /bits/ 64 <500000000>; + opp-microvolt = <1100000>; + }; + + opp-400000000 { + opp-hz = /bits/ 64 <400000000>; + opp-microvolt = <1100000>; + }; + + opp-250000000 { + opp-hz = /bits/ 64 <250000000>; + opp-microvolt = <1100000>; + }; + + opp-200000000 { + opp-hz = /bits/ 64 <200000000>; + opp-microvolt = <1100000>; + }; + + opp-125000000 { + opp-hz = /bits/ 64 <125000000>; + opp-microvolt = <1100000>; + }; + + opp-100000000 { + opp-hz = /bits/ 64 <100000000>; + opp-microvolt = <1100000>; + }; + + opp-62500000 { + opp-hz = /bits/ 64 <62500000>; + opp-microvolt = <1100000>; + }; + + opp-50000000 { + opp-hz = /bits/ 64 <50000000>; + opp-microvolt = <1100000>; + }; + }; + + pmu { + compatible = "arm,cortex-a55-pmu"; + interrupts-extended = <&gic GIC_PPI 7 IRQ_TYPE_LEVEL_LOW>; + }; + + psci { + compatible = "arm,psci-1.0", "arm,psci-0.2"; + method = "smc"; + }; + + soc: soc { + compatible = "simple-bus"; + interrupt-parent = <&gic>; + #address-cells = <2>; + #size-cells = <2>; + ranges; + + mtu3: timer@10001200 { + compatible = "renesas,r9a07g044-mtu3", + "renesas,rz-mtu3"; + reg = <0 0x10001200 0 0xb00>; + interrupts = <GIC_SPI 170 IRQ_TYPE_EDGE_RISING>, + <GIC_SPI 171 IRQ_TYPE_EDGE_RISING>, + <GIC_SPI 172 IRQ_TYPE_EDGE_RISING>, + <GIC_SPI 173 IRQ_TYPE_EDGE_RISING>, + <GIC_SPI 174 IRQ_TYPE_EDGE_RISING>, + <GIC_SPI 175 IRQ_TYPE_EDGE_RISING>, + <GIC_SPI 176 IRQ_TYPE_EDGE_RISING>, + <GIC_SPI 177 IRQ_TYPE_EDGE_RISING>, + <GIC_SPI 178 IRQ_TYPE_EDGE_RISING>, + <GIC_SPI 179 IRQ_TYPE_EDGE_RISING>, + <GIC_SPI 180 IRQ_TYPE_EDGE_RISING>, + <GIC_SPI 181 IRQ_TYPE_EDGE_RISING>, + <GIC_SPI 182 IRQ_TYPE_EDGE_RISING>, + <GIC_SPI 183 IRQ_TYPE_EDGE_RISING>, + <GIC_SPI 184 IRQ_TYPE_EDGE_RISING>, + <GIC_SPI 185 IRQ_TYPE_EDGE_RISING>, + <GIC_SPI 186 IRQ_TYPE_EDGE_RISING>, + <GIC_SPI 187 IRQ_TYPE_EDGE_RISING>, + <GIC_SPI 188 IRQ_TYPE_EDGE_RISING>, + <GIC_SPI 189 IRQ_TYPE_EDGE_RISING>, + <GIC_SPI 190 IRQ_TYPE_EDGE_RISING>, + <GIC_SPI 191 IRQ_TYPE_EDGE_RISING>, + <GIC_SPI 192 IRQ_TYPE_EDGE_RISING>, + <GIC_SPI 193 IRQ_TYPE_EDGE_RISING>, + <GIC_SPI 194 IRQ_TYPE_EDGE_RISING>, + <GIC_SPI 195 IRQ_TYPE_EDGE_RISING>, + <GIC_SPI 196 IRQ_TYPE_EDGE_RISING>, + <GIC_SPI 197 IRQ_TYPE_EDGE_RISING>, + <GIC_SPI 198 IRQ_TYPE_EDGE_RISING>, + <GIC_SPI 199 IRQ_TYPE_EDGE_RISING>, + <GIC_SPI 200 IRQ_TYPE_EDGE_RISING>, + <GIC_SPI 201 IRQ_TYPE_EDGE_RISING>, + <GIC_SPI 202 IRQ_TYPE_EDGE_RISING>, + <GIC_SPI 203 IRQ_TYPE_EDGE_RISING>, + <GIC_SPI 204 IRQ_TYPE_EDGE_RISING>, + <GIC_SPI 205 IRQ_TYPE_EDGE_RISING>, + <GIC_SPI 206 IRQ_TYPE_EDGE_RISING>, + <GIC_SPI 207 IRQ_TYPE_EDGE_RISING>, + <GIC_SPI 208 IRQ_TYPE_EDGE_RISING>, + <GIC_SPI 209 IRQ_TYPE_EDGE_RISING>, + <GIC_SPI 210 IRQ_TYPE_EDGE_RISING>, + <GIC_SPI 211 IRQ_TYPE_EDGE_RISING>, + <GIC_SPI 212 IRQ_TYPE_EDGE_RISING>, + <GIC_SPI 213 IRQ_TYPE_EDGE_RISING>; + interrupt-names = "tgia0", "tgib0", "tgic0", "tgid0", + "tgiv0", "tgie0", "tgif0", + "tgia1", "tgib1", "tgiv1", "tgiu1", + "tgia2", "tgib2", "tgiv2", "tgiu2", + "tgia3", "tgib3", "tgic3", "tgid3", + "tgiv3", + "tgia4", "tgib4", "tgic4", "tgid4", + "tgiv4", + "tgiu5", "tgiv5", "tgiw5", + "tgia6", "tgib6", "tgic6", "tgid6", + "tgiv6", + "tgia7", "tgib7", "tgic7", "tgid7", + "tgiv7", + "tgia8", "tgib8", "tgic8", "tgid8", + "tgiv8", "tgiu8"; + clocks = <&cpg CPG_MOD R9A07G044_MTU_X_MCK_MTU3>; + power-domains = <&cpg>; + resets = <&cpg R9A07G044_MTU_X_PRESET_MTU3>; + #pwm-cells = <2>; + status = "disabled"; + }; + + ssi0: ssi@10049c00 { + compatible = "renesas,r9a07g044-ssi", + "renesas,rz-ssi"; + reg = <0 0x10049c00 0 0x400>; + interrupts = <GIC_SPI 326 IRQ_TYPE_LEVEL_HIGH>, + <GIC_SPI 327 IRQ_TYPE_EDGE_RISING>, + <GIC_SPI 328 IRQ_TYPE_EDGE_RISING>; + interrupt-names = "int_req", "dma_rx", "dma_tx"; + clocks = <&cpg CPG_MOD R9A07G044_SSI0_PCLK2>, + <&cpg CPG_MOD R9A07G044_SSI0_PCLK_SFR>, + <&audio_clk1>, <&audio_clk2>; + clock-names = "ssi", "ssi_sfr", "audio_clk1", "audio_clk2"; + resets = <&cpg R9A07G044_SSI0_RST_M2_REG>; + dmas = <&dmac 0x2655>, <&dmac 0x2656>; + dma-names = "tx", "rx"; + power-domains = <&cpg>; + #sound-dai-cells = <0>; + status = "disabled"; + }; + + ssi1: ssi@1004a000 { + compatible = "renesas,r9a07g044-ssi", + "renesas,rz-ssi"; + reg = <0 0x1004a000 0 0x400>; + interrupts = <GIC_SPI 330 IRQ_TYPE_LEVEL_HIGH>, + <GIC_SPI 331 IRQ_TYPE_EDGE_RISING>, + <GIC_SPI 332 IRQ_TYPE_EDGE_RISING>; + interrupt-names = "int_req", "dma_rx", "dma_tx"; + clocks = <&cpg CPG_MOD R9A07G044_SSI1_PCLK2>, + <&cpg CPG_MOD R9A07G044_SSI1_PCLK_SFR>, + <&audio_clk1>, <&audio_clk2>; + clock-names = "ssi", "ssi_sfr", "audio_clk1", "audio_clk2"; + resets = <&cpg R9A07G044_SSI1_RST_M2_REG>; + dmas = <&dmac 0x2659>, <&dmac 0x265a>; + dma-names = "tx", "rx"; + power-domains = <&cpg>; + #sound-dai-cells = <0>; + status = "disabled"; + }; + + ssi2: ssi@1004a400 { + compatible = "renesas,r9a07g044-ssi", + "renesas,rz-ssi"; + reg = <0 0x1004a400 0 0x400>; + interrupts = <GIC_SPI 334 IRQ_TYPE_LEVEL_HIGH>, + <GIC_SPI 337 IRQ_TYPE_EDGE_RISING>; + interrupt-names = "int_req", "dma_rt"; + clocks = <&cpg CPG_MOD R9A07G044_SSI2_PCLK2>, + <&cpg CPG_MOD R9A07G044_SSI2_PCLK_SFR>, + <&audio_clk1>, <&audio_clk2>; + clock-names = "ssi", "ssi_sfr", "audio_clk1", "audio_clk2"; + resets = <&cpg R9A07G044_SSI2_RST_M2_REG>; + dmas = <&dmac 0x265f>; + dma-names = "rt"; + power-domains = <&cpg>; + #sound-dai-cells = <0>; + status = "disabled"; + }; + + ssi3: ssi@1004a800 { + compatible = "renesas,r9a07g044-ssi", + "renesas,rz-ssi"; + reg = <0 0x1004a800 0 0x400>; + interrupts = <GIC_SPI 338 IRQ_TYPE_LEVEL_HIGH>, + <GIC_SPI 339 IRQ_TYPE_EDGE_RISING>, + <GIC_SPI 340 IRQ_TYPE_EDGE_RISING>; + interrupt-names = "int_req", "dma_rx", "dma_tx"; + clocks = <&cpg CPG_MOD R9A07G044_SSI3_PCLK2>, + <&cpg CPG_MOD R9A07G044_SSI3_PCLK_SFR>, + <&audio_clk1>, <&audio_clk2>; + clock-names = "ssi", "ssi_sfr", "audio_clk1", "audio_clk2"; + resets = <&cpg R9A07G044_SSI3_RST_M2_REG>; + dmas = <&dmac 0x2661>, <&dmac 0x2662>; + dma-names = "tx", "rx"; + power-domains = <&cpg>; + #sound-dai-cells = <0>; + status = "disabled"; + }; + + spi0: spi@1004ac00 { + compatible = "renesas,r9a07g044-rspi", "renesas,rspi-rz"; + reg = <0 0x1004ac00 0 0x400>; + interrupts = <GIC_SPI 415 IRQ_TYPE_LEVEL_HIGH>, + <GIC_SPI 413 IRQ_TYPE_LEVEL_HIGH>, + <GIC_SPI 414 IRQ_TYPE_LEVEL_HIGH>; + interrupt-names = "error", "rx", "tx"; + clocks = <&cpg CPG_MOD R9A07G044_RSPI0_CLKB>; + resets = <&cpg R9A07G044_RSPI0_RST>; + dmas = <&dmac 0x2e95>, <&dmac 0x2e96>; + dma-names = "tx", "rx"; + power-domains = <&cpg>; + num-cs = <1>; + #address-cells = <1>; + #size-cells = <0>; + status = "disabled"; + }; + + spi1: spi@1004b000 { + compatible = "renesas,r9a07g044-rspi", "renesas,rspi-rz"; + reg = <0 0x1004b000 0 0x400>; + interrupts = <GIC_SPI 418 IRQ_TYPE_LEVEL_HIGH>, + <GIC_SPI 416 IRQ_TYPE_LEVEL_HIGH>, + <GIC_SPI 417 IRQ_TYPE_LEVEL_HIGH>; + interrupt-names = "error", "rx", "tx"; + clocks = <&cpg CPG_MOD R9A07G044_RSPI1_CLKB>; + resets = <&cpg R9A07G044_RSPI1_RST>; + dmas = <&dmac 0x2e99>, <&dmac 0x2e9a>; + dma-names = "tx", "rx"; + power-domains = <&cpg>; + num-cs = <1>; + #address-cells = <1>; + #size-cells = <0>; + status = "disabled"; + }; + + spi2: spi@1004b400 { + compatible = "renesas,r9a07g044-rspi", "renesas,rspi-rz"; + reg = <0 0x1004b400 0 0x400>; + interrupts = <GIC_SPI 421 IRQ_TYPE_LEVEL_HIGH>, + <GIC_SPI 419 IRQ_TYPE_LEVEL_HIGH>, + <GIC_SPI 420 IRQ_TYPE_LEVEL_HIGH>; + interrupt-names = "error", "rx", "tx"; + clocks = <&cpg CPG_MOD R9A07G044_RSPI2_CLKB>; + resets = <&cpg R9A07G044_RSPI2_RST>; + dmas = <&dmac 0x2e9d>, <&dmac 0x2e9e>; + dma-names = "tx", "rx"; + power-domains = <&cpg>; + num-cs = <1>; + #address-cells = <1>; + #size-cells = <0>; + status = "disabled"; + }; + + scif0: serial@1004b800 { + compatible = "renesas,scif-r9a07g044"; + reg = <0 0x1004b800 0 0x400>; + interrupts = <GIC_SPI 380 IRQ_TYPE_LEVEL_HIGH>, + <GIC_SPI 382 IRQ_TYPE_LEVEL_HIGH>, + <GIC_SPI 383 IRQ_TYPE_LEVEL_HIGH>, + <GIC_SPI 381 IRQ_TYPE_LEVEL_HIGH>, + <GIC_SPI 384 IRQ_TYPE_LEVEL_HIGH>, + <GIC_SPI 384 IRQ_TYPE_LEVEL_HIGH>; + interrupt-names = "eri", "rxi", "txi", + "bri", "dri", "tei"; + clocks = <&cpg CPG_MOD R9A07G044_SCIF0_CLK_PCK>; + clock-names = "fck"; + power-domains = <&cpg>; + resets = <&cpg R9A07G044_SCIF0_RST_SYSTEM_N>; + status = "disabled"; + }; + + scif1: serial@1004bc00 { + compatible = "renesas,scif-r9a07g044"; + reg = <0 0x1004bc00 0 0x400>; + interrupts = <GIC_SPI 385 IRQ_TYPE_LEVEL_HIGH>, + <GIC_SPI 387 IRQ_TYPE_LEVEL_HIGH>, + <GIC_SPI 388 IRQ_TYPE_LEVEL_HIGH>, + <GIC_SPI 386 IRQ_TYPE_LEVEL_HIGH>, + <GIC_SPI 389 IRQ_TYPE_LEVEL_HIGH>, + <GIC_SPI 389 IRQ_TYPE_LEVEL_HIGH>; + interrupt-names = "eri", "rxi", "txi", + "bri", "dri", "tei"; + clocks = <&cpg CPG_MOD R9A07G044_SCIF1_CLK_PCK>; + clock-names = "fck"; + power-domains = <&cpg>; + resets = <&cpg R9A07G044_SCIF1_RST_SYSTEM_N>; + status = "disabled"; + }; + + scif2: serial@1004c000 { + compatible = "renesas,scif-r9a07g044"; + reg = <0 0x1004c000 0 0x400>; + interrupts = <GIC_SPI 390 IRQ_TYPE_LEVEL_HIGH>, + <GIC_SPI 392 IRQ_TYPE_LEVEL_HIGH>, + <GIC_SPI 393 IRQ_TYPE_LEVEL_HIGH>, + <GIC_SPI 391 IRQ_TYPE_LEVEL_HIGH>, + <GIC_SPI 394 IRQ_TYPE_LEVEL_HIGH>, + <GIC_SPI 394 IRQ_TYPE_LEVEL_HIGH>; + interrupt-names = "eri", "rxi", "txi", + "bri", "dri", "tei"; + clocks = <&cpg CPG_MOD R9A07G044_SCIF2_CLK_PCK>; + clock-names = "fck"; + power-domains = <&cpg>; + resets = <&cpg R9A07G044_SCIF2_RST_SYSTEM_N>; + status = "disabled"; + }; + + scif3: serial@1004c400 { + compatible = "renesas,scif-r9a07g044"; + reg = <0 0x1004c400 0 0x400>; + interrupts = <GIC_SPI 395 IRQ_TYPE_LEVEL_HIGH>, + <GIC_SPI 397 IRQ_TYPE_LEVEL_HIGH>, + <GIC_SPI 398 IRQ_TYPE_LEVEL_HIGH>, + <GIC_SPI 396 IRQ_TYPE_LEVEL_HIGH>, + <GIC_SPI 399 IRQ_TYPE_LEVEL_HIGH>, + <GIC_SPI 399 IRQ_TYPE_LEVEL_HIGH>; + interrupt-names = "eri", "rxi", "txi", + "bri", "dri", "tei"; + clocks = <&cpg CPG_MOD R9A07G044_SCIF3_CLK_PCK>; + clock-names = "fck"; + power-domains = <&cpg>; + resets = <&cpg R9A07G044_SCIF3_RST_SYSTEM_N>; + status = "disabled"; + }; + + scif4: serial@1004c800 { + compatible = "renesas,scif-r9a07g044"; + reg = <0 0x1004c800 0 0x400>; + interrupts = <GIC_SPI 400 IRQ_TYPE_LEVEL_HIGH>, + <GIC_SPI 402 IRQ_TYPE_LEVEL_HIGH>, + <GIC_SPI 403 IRQ_TYPE_LEVEL_HIGH>, + <GIC_SPI 401 IRQ_TYPE_LEVEL_HIGH>, + <GIC_SPI 404 IRQ_TYPE_LEVEL_HIGH>, + <GIC_SPI 404 IRQ_TYPE_LEVEL_HIGH>; + interrupt-names = "eri", "rxi", "txi", + "bri", "dri", "tei"; + clocks = <&cpg CPG_MOD R9A07G044_SCIF4_CLK_PCK>; + clock-names = "fck"; + power-domains = <&cpg>; + resets = <&cpg R9A07G044_SCIF4_RST_SYSTEM_N>; + status = "disabled"; + }; + + sci0: serial@1004d000 { + compatible = "renesas,r9a07g044-sci", "renesas,sci"; + reg = <0 0x1004d000 0 0x400>; + interrupts = <GIC_SPI 405 IRQ_TYPE_LEVEL_HIGH>, + <GIC_SPI 406 IRQ_TYPE_EDGE_RISING>, + <GIC_SPI 407 IRQ_TYPE_EDGE_RISING>, + <GIC_SPI 408 IRQ_TYPE_LEVEL_HIGH>; + interrupt-names = "eri", "rxi", "txi", "tei"; + clocks = <&cpg CPG_MOD R9A07G044_SCI0_CLKP>; + clock-names = "fck"; + power-domains = <&cpg>; + resets = <&cpg R9A07G044_SCI0_RST>; + status = "disabled"; + }; + + sci1: serial@1004d400 { + compatible = "renesas,r9a07g044-sci", "renesas,sci"; + reg = <0 0x1004d400 0 0x400>; + interrupts = <GIC_SPI 409 IRQ_TYPE_LEVEL_HIGH>, + <GIC_SPI 410 IRQ_TYPE_EDGE_RISING>, + <GIC_SPI 411 IRQ_TYPE_EDGE_RISING>, + <GIC_SPI 412 IRQ_TYPE_LEVEL_HIGH>; + interrupt-names = "eri", "rxi", "txi", "tei"; + clocks = <&cpg CPG_MOD R9A07G044_SCI1_CLKP>; + clock-names = "fck"; + power-domains = <&cpg>; + resets = <&cpg R9A07G044_SCI1_RST>; + status = "disabled"; + }; + + canfd: can@10050000 { + compatible = "renesas,r9a07g044-canfd", "renesas,rzg2l-canfd"; + reg = <0 0x10050000 0 0x8000>; + interrupts = <GIC_SPI 426 IRQ_TYPE_LEVEL_HIGH>, + <GIC_SPI 427 IRQ_TYPE_LEVEL_HIGH>, + <GIC_SPI 422 IRQ_TYPE_LEVEL_HIGH>, + <GIC_SPI 424 IRQ_TYPE_LEVEL_HIGH>, + <GIC_SPI 428 IRQ_TYPE_LEVEL_HIGH>, + <GIC_SPI 423 IRQ_TYPE_LEVEL_HIGH>, + <GIC_SPI 425 IRQ_TYPE_LEVEL_HIGH>, + <GIC_SPI 429 IRQ_TYPE_LEVEL_HIGH>; + interrupt-names = "g_err", "g_recc", + "ch0_err", "ch0_rec", "ch0_trx", + "ch1_err", "ch1_rec", "ch1_trx"; + clocks = <&cpg CPG_MOD R9A07G044_CANFD_PCLK>, + <&cpg CPG_CORE R9A07G044_CLK_P0_DIV2>, + <&can_clk>; + clock-names = "fck", "canfd", "can_clk"; + assigned-clocks = <&cpg CPG_CORE R9A07G044_CLK_P0_DIV2>; + assigned-clock-rates = <50000000>; + resets = <&cpg R9A07G044_CANFD_RSTP_N>, + <&cpg R9A07G044_CANFD_RSTC_N>; + reset-names = "rstp_n", "rstc_n"; + power-domains = <&cpg>; + status = "disabled"; + + channel0 { + status = "disabled"; + }; + channel1 { + status = "disabled"; + }; + }; + + i2c0: i2c@10058000 { + #address-cells = <1>; + #size-cells = <0>; + compatible = "renesas,riic-r9a07g044", "renesas,riic-rz"; + reg = <0 0x10058000 0 0x400>; + interrupts = <GIC_SPI 350 IRQ_TYPE_LEVEL_HIGH>, + <GIC_SPI 348 IRQ_TYPE_EDGE_RISING>, + <GIC_SPI 349 IRQ_TYPE_EDGE_RISING>, + <GIC_SPI 352 IRQ_TYPE_LEVEL_HIGH>, + <GIC_SPI 353 IRQ_TYPE_LEVEL_HIGH>, + <GIC_SPI 351 IRQ_TYPE_LEVEL_HIGH>, + <GIC_SPI 354 IRQ_TYPE_LEVEL_HIGH>, + <GIC_SPI 355 IRQ_TYPE_LEVEL_HIGH>; + interrupt-names = "tei", "ri", "ti", "spi", "sti", + "naki", "ali", "tmoi"; + clocks = <&cpg CPG_MOD R9A07G044_I2C0_PCLK>; + clock-frequency = <100000>; + resets = <&cpg R9A07G044_I2C0_MRST>; + power-domains = <&cpg>; + status = "disabled"; + }; + + i2c1: i2c@10058400 { + #address-cells = <1>; + #size-cells = <0>; + compatible = "renesas,riic-r9a07g044", "renesas,riic-rz"; + reg = <0 0x10058400 0 0x400>; + interrupts = <GIC_SPI 358 IRQ_TYPE_LEVEL_HIGH>, + <GIC_SPI 356 IRQ_TYPE_EDGE_RISING>, + <GIC_SPI 357 IRQ_TYPE_EDGE_RISING>, + <GIC_SPI 360 IRQ_TYPE_LEVEL_HIGH>, + <GIC_SPI 361 IRQ_TYPE_LEVEL_HIGH>, + <GIC_SPI 359 IRQ_TYPE_LEVEL_HIGH>, + <GIC_SPI 362 IRQ_TYPE_LEVEL_HIGH>, + <GIC_SPI 363 IRQ_TYPE_LEVEL_HIGH>; + interrupt-names = "tei", "ri", "ti", "spi", "sti", + "naki", "ali", "tmoi"; + clocks = <&cpg CPG_MOD R9A07G044_I2C1_PCLK>; + clock-frequency = <100000>; + resets = <&cpg R9A07G044_I2C1_MRST>; + power-domains = <&cpg>; + status = "disabled"; + }; + + i2c2: i2c@10058800 { + #address-cells = <1>; + #size-cells = <0>; + compatible = "renesas,riic-r9a07g044", "renesas,riic-rz"; + reg = <0 0x10058800 0 0x400>; + interrupts = <GIC_SPI 366 IRQ_TYPE_LEVEL_HIGH>, + <GIC_SPI 364 IRQ_TYPE_EDGE_RISING>, + <GIC_SPI 365 IRQ_TYPE_EDGE_RISING>, + <GIC_SPI 368 IRQ_TYPE_LEVEL_HIGH>, + <GIC_SPI 369 IRQ_TYPE_LEVEL_HIGH>, + <GIC_SPI 367 IRQ_TYPE_LEVEL_HIGH>, + <GIC_SPI 370 IRQ_TYPE_LEVEL_HIGH>, + <GIC_SPI 371 IRQ_TYPE_LEVEL_HIGH>; + interrupt-names = "tei", "ri", "ti", "spi", "sti", + "naki", "ali", "tmoi"; + clocks = <&cpg CPG_MOD R9A07G044_I2C2_PCLK>; + clock-frequency = <100000>; + resets = <&cpg R9A07G044_I2C2_MRST>; + power-domains = <&cpg>; + status = "disabled"; + }; + + i2c3: i2c@10058c00 { + #address-cells = <1>; + #size-cells = <0>; + compatible = "renesas,riic-r9a07g044", "renesas,riic-rz"; + reg = <0 0x10058c00 0 0x400>; + interrupts = <GIC_SPI 374 IRQ_TYPE_LEVEL_HIGH>, + <GIC_SPI 372 IRQ_TYPE_EDGE_RISING>, + <GIC_SPI 373 IRQ_TYPE_EDGE_RISING>, + <GIC_SPI 376 IRQ_TYPE_LEVEL_HIGH>, + <GIC_SPI 377 IRQ_TYPE_LEVEL_HIGH>, + <GIC_SPI 375 IRQ_TYPE_LEVEL_HIGH>, + <GIC_SPI 378 IRQ_TYPE_LEVEL_HIGH>, + <GIC_SPI 379 IRQ_TYPE_LEVEL_HIGH>; + interrupt-names = "tei", "ri", "ti", "spi", "sti", + "naki", "ali", "tmoi"; + clocks = <&cpg CPG_MOD R9A07G044_I2C3_PCLK>; + clock-frequency = <100000>; + resets = <&cpg R9A07G044_I2C3_MRST>; + power-domains = <&cpg>; + status = "disabled"; + }; + + adc: adc@10059000 { + compatible = "renesas,r9a07g044-adc", "renesas,rzg2l-adc"; + reg = <0 0x10059000 0 0x400>; + interrupts = <GIC_SPI 347 IRQ_TYPE_EDGE_RISING>; + clocks = <&cpg CPG_MOD R9A07G044_ADC_ADCLK>, + <&cpg CPG_MOD R9A07G044_ADC_PCLK>; + clock-names = "adclk", "pclk"; + resets = <&cpg R9A07G044_ADC_PRESETN>, + <&cpg R9A07G044_ADC_ADRST_N>; + reset-names = "presetn", "adrst-n"; + power-domains = <&cpg>; + status = "disabled"; + + #address-cells = <1>; + #size-cells = <0>; + + channel@0 { + reg = <0>; + }; + channel@1 { + reg = <1>; + }; + channel@2 { + reg = <2>; + }; + channel@3 { + reg = <3>; + }; + channel@4 { + reg = <4>; + }; + channel@5 { + reg = <5>; + }; + channel@6 { + reg = <6>; + }; + channel@7 { + reg = <7>; + }; + }; + + tsu: thermal@10059400 { + compatible = "renesas,r9a07g044-tsu", + "renesas,rzg2l-tsu"; + reg = <0 0x10059400 0 0x400>; + clocks = <&cpg CPG_MOD R9A07G044_TSU_PCLK>; + resets = <&cpg R9A07G044_TSU_PRESETN>; + power-domains = <&cpg>; + #thermal-sensor-cells = <1>; + }; + + sbc: spi@10060000 { + compatible = "renesas,r9a07g044-rpc-if", + "renesas,rzg2l-rpc-if"; + reg = <0 0x10060000 0 0x10000>, + <0 0x20000000 0 0x10000000>, + <0 0x10070000 0 0x10000>; + reg-names = "regs", "dirmap", "wbuf"; + interrupts = <GIC_SPI 41 IRQ_TYPE_LEVEL_HIGH>; + clocks = <&cpg CPG_MOD R9A07G044_SPI_CLK2>, + <&cpg CPG_MOD R9A07G044_SPI_CLK>; + resets = <&cpg R9A07G044_SPI_RST>; + power-domains = <&cpg>; + #address-cells = <1>; + #size-cells = <0>; + status = "disabled"; + }; + + cru: video@10830000 { + compatible = "renesas,r9a07g044-cru", "renesas,rzg2l-cru"; + reg = <0 0x10830000 0 0x400>; + clocks = <&cpg CPG_MOD R9A07G044_CRU_VCLK>, + <&cpg CPG_MOD R9A07G044_CRU_PCLK>, + <&cpg CPG_MOD R9A07G044_CRU_ACLK>; + clock-names = "video", "apb", "axi"; + interrupts = <GIC_SPI 167 IRQ_TYPE_LEVEL_HIGH>, + <GIC_SPI 168 IRQ_TYPE_LEVEL_HIGH>, + <GIC_SPI 169 IRQ_TYPE_LEVEL_HIGH>; + interrupt-names = "image_conv", "image_conv_err", "axi_mst_err"; + resets = <&cpg R9A07G044_CRU_PRESETN>, + <&cpg R9A07G044_CRU_ARESETN>; + reset-names = "presetn", "aresetn"; + power-domains = <&cpg>; + status = "disabled"; + + ports { + #address-cells = <1>; + #size-cells = <0>; + + port@0 { + #address-cells = <1>; + #size-cells = <0>; + + reg = <0>; + cruparallel: endpoint@0 { + reg = <0>; + }; + }; + + port@1 { + #address-cells = <1>; + #size-cells = <0>; + + reg = <1>; + crucsi2: endpoint@0 { + reg = <0>; + remote-endpoint = <&csi2cru>; + }; + }; + }; + }; + + csi2: csi2@10830400 { + compatible = "renesas,r9a07g044-csi2", "renesas,rzg2l-csi2"; + reg = <0 0x10830400 0 0xfc00>; + interrupts = <GIC_SPI 166 IRQ_TYPE_LEVEL_HIGH>; + clocks = <&cpg CPG_MOD R9A07G044_CRU_SYSCLK>, + <&cpg CPG_MOD R9A07G044_CRU_VCLK>, + <&cpg CPG_MOD R9A07G044_CRU_PCLK>; + clock-names = "system", "video", "apb"; + resets = <&cpg R9A07G044_CRU_PRESETN>, + <&cpg R9A07G044_CRU_CMN_RSTB>; + reset-names = "presetn", "cmn-rstb"; + power-domains = <&cpg>; + status = "disabled"; + + ports { + #address-cells = <1>; + #size-cells = <0>; + + port@0 { + reg = <0>; + }; + + port@1 { + #address-cells = <1>; + #size-cells = <0>; + reg = <1>; + + csi2cru: endpoint@0 { + reg = <0>; + remote-endpoint = <&crucsi2>; + }; + }; + }; + }; + + dsi: dsi@10850000 { + compatible = "renesas,r9a07g044-mipi-dsi", + "renesas,rzg2l-mipi-dsi"; + reg = <0 0x10850000 0 0x20000>; + interrupts = <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>; + interrupt-names = "seq0", "seq1", "vin1", "rcv", + "ferr", "ppi", "debug"; + clocks = <&cpg CPG_MOD R9A07G044_MIPI_DSI_PLLCLK>, + <&cpg CPG_MOD R9A07G044_MIPI_DSI_SYSCLK>, + <&cpg CPG_MOD R9A07G044_MIPI_DSI_ACLK>, + <&cpg CPG_MOD R9A07G044_MIPI_DSI_PCLK>, + <&cpg CPG_MOD R9A07G044_MIPI_DSI_VCLK>, + <&cpg CPG_MOD R9A07G044_MIPI_DSI_LPCLK>; + clock-names = "pllclk", "sysclk", "aclk", "pclk", "vclk", "lpclk"; + resets = <&cpg R9A07G044_MIPI_DSI_CMN_RSTB>, + <&cpg R9A07G044_MIPI_DSI_ARESET_N>, + <&cpg R9A07G044_MIPI_DSI_PRESET_N>; + reset-names = "rst", "arst", "prst"; + power-domains = <&cpg>; + status = "disabled"; + }; + + vspd: vsp@10870000 { + compatible = "renesas,r9a07g044-vsp2"; + reg = <0 0x10870000 0 0x10000>; + interrupts = <GIC_SPI 149 IRQ_TYPE_LEVEL_HIGH>; + clocks = <&cpg CPG_MOD R9A07G044_LCDC_CLK_A>, + <&cpg CPG_MOD R9A07G044_LCDC_CLK_P>, + <&cpg CPG_MOD R9A07G044_LCDC_CLK_D>; + clock-names = "aclk", "pclk", "vclk"; + power-domains = <&cpg>; + resets = <&cpg R9A07G044_LCDC_RESET_N>; + renesas,fcp = <&fcpvd>; + }; + + fcpvd: fcp@10880000 { + compatible = "renesas,r9a07g044-fcpvd", + "renesas,fcpv"; + reg = <0 0x10880000 0 0x10000>; + clocks = <&cpg CPG_MOD R9A07G044_LCDC_CLK_A>, + <&cpg CPG_MOD R9A07G044_LCDC_CLK_P>, + <&cpg CPG_MOD R9A07G044_LCDC_CLK_D>; + clock-names = "aclk", "pclk", "vclk"; + power-domains = <&cpg>; + resets = <&cpg R9A07G044_LCDC_RESET_N>; + }; + + cpg: clock-controller@11010000 { + compatible = "renesas,r9a07g044-cpg"; + reg = <0 0x11010000 0 0x10000>; + clocks = <&extal_clk>; + clock-names = "extal"; + #clock-cells = <2>; + #reset-cells = <1>; + #power-domain-cells = <0>; + }; + + sysc: system-controller@11020000 { + compatible = "renesas,r9a07g044-sysc"; + reg = <0 0x11020000 0 0x10000>; + interrupts = <GIC_SPI 42 IRQ_TYPE_LEVEL_HIGH>, + <GIC_SPI 43 IRQ_TYPE_LEVEL_HIGH>, + <GIC_SPI 44 IRQ_TYPE_LEVEL_HIGH>, + <GIC_SPI 45 IRQ_TYPE_LEVEL_HIGH>; + interrupt-names = "lpm_int", "ca55stbydone_int", + "cm33stbyr_int", "ca55_deny"; + status = "disabled"; + }; + + pinctrl: pinctrl@11030000 { + compatible = "renesas,r9a07g044-pinctrl"; + reg = <0 0x11030000 0 0x10000>; + gpio-controller; + #gpio-cells = <2>; + #interrupt-cells = <2>; + interrupt-parent = <&irqc>; + interrupt-controller; + gpio-ranges = <&pinctrl 0 0 392>; + clocks = <&cpg CPG_MOD R9A07G044_GPIO_HCLK>; + power-domains = <&cpg>; + resets = <&cpg R9A07G044_GPIO_RSTN>, + <&cpg R9A07G044_GPIO_PORT_RESETN>, + <&cpg R9A07G044_GPIO_SPARE_RESETN>; + }; + + irqc: interrupt-controller@110a0000 { + compatible = "renesas,r9a07g044-irqc", + "renesas,rzg2l-irqc"; + #interrupt-cells = <2>; + #address-cells = <0>; + interrupt-controller; + reg = <0 0x110a0000 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 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 461 IRQ_TYPE_LEVEL_HIGH>, + <GIC_SPI 462 IRQ_TYPE_LEVEL_HIGH>, + <GIC_SPI 463 IRQ_TYPE_LEVEL_HIGH>, + <GIC_SPI 464 IRQ_TYPE_LEVEL_HIGH>, + <GIC_SPI 465 IRQ_TYPE_LEVEL_HIGH>, + <GIC_SPI 466 IRQ_TYPE_LEVEL_HIGH>, + <GIC_SPI 467 IRQ_TYPE_LEVEL_HIGH>, + <GIC_SPI 468 IRQ_TYPE_LEVEL_HIGH>, + <GIC_SPI 469 IRQ_TYPE_LEVEL_HIGH>, + <GIC_SPI 470 IRQ_TYPE_LEVEL_HIGH>, + <GIC_SPI 471 IRQ_TYPE_LEVEL_HIGH>, + <GIC_SPI 472 IRQ_TYPE_LEVEL_HIGH>, + <GIC_SPI 473 IRQ_TYPE_LEVEL_HIGH>, + <GIC_SPI 474 IRQ_TYPE_LEVEL_HIGH>, + <GIC_SPI 475 IRQ_TYPE_LEVEL_HIGH>; + clocks = <&cpg CPG_MOD R9A07G044_IA55_CLK>, + <&cpg CPG_MOD R9A07G044_IA55_PCLK>; + clock-names = "clk", "pclk"; + power-domains = <&cpg>; + resets = <&cpg R9A07G044_IA55_RESETN>; + }; + + dmac: dma-controller@11820000 { + compatible = "renesas,r9a07g044-dmac", + "renesas,rz-dmac"; + reg = <0 0x11820000 0 0x10000>, + <0 0x11830000 0 0x10000>; + interrupts = <GIC_SPI 141 IRQ_TYPE_EDGE_RISING>, + <GIC_SPI 125 IRQ_TYPE_EDGE_RISING>, + <GIC_SPI 126 IRQ_TYPE_EDGE_RISING>, + <GIC_SPI 127 IRQ_TYPE_EDGE_RISING>, + <GIC_SPI 128 IRQ_TYPE_EDGE_RISING>, + <GIC_SPI 129 IRQ_TYPE_EDGE_RISING>, + <GIC_SPI 130 IRQ_TYPE_EDGE_RISING>, + <GIC_SPI 131 IRQ_TYPE_EDGE_RISING>, + <GIC_SPI 132 IRQ_TYPE_EDGE_RISING>, + <GIC_SPI 133 IRQ_TYPE_EDGE_RISING>, + <GIC_SPI 134 IRQ_TYPE_EDGE_RISING>, + <GIC_SPI 135 IRQ_TYPE_EDGE_RISING>, + <GIC_SPI 136 IRQ_TYPE_EDGE_RISING>, + <GIC_SPI 137 IRQ_TYPE_EDGE_RISING>, + <GIC_SPI 138 IRQ_TYPE_EDGE_RISING>, + <GIC_SPI 139 IRQ_TYPE_EDGE_RISING>, + <GIC_SPI 140 IRQ_TYPE_EDGE_RISING>; + interrupt-names = "error", + "ch0", "ch1", "ch2", "ch3", + "ch4", "ch5", "ch6", "ch7", + "ch8", "ch9", "ch10", "ch11", + "ch12", "ch13", "ch14", "ch15"; + clocks = <&cpg CPG_MOD R9A07G044_DMAC_ACLK>, + <&cpg CPG_MOD R9A07G044_DMAC_PCLK>; + clock-names = "main", "register"; + power-domains = <&cpg>; + resets = <&cpg R9A07G044_DMAC_ARESETN>, + <&cpg R9A07G044_DMAC_RST_ASYNC>; + reset-names = "arst", "rst_async"; + #dma-cells = <1>; + dma-channels = <16>; + }; + + gpu: gpu@11840000 { + compatible = "renesas,r9a07g044-mali", + "arm,mali-bifrost"; + reg = <0x0 0x11840000 0x0 0x10000>; + interrupts = <GIC_SPI 154 IRQ_TYPE_LEVEL_HIGH>, + <GIC_SPI 155 IRQ_TYPE_LEVEL_HIGH>, + <GIC_SPI 153 IRQ_TYPE_LEVEL_HIGH>, + <GIC_SPI 156 IRQ_TYPE_LEVEL_HIGH>; + interrupt-names = "job", "mmu", "gpu", "event"; + clocks = <&cpg CPG_MOD R9A07G044_GPU_CLK>, + <&cpg CPG_MOD R9A07G044_GPU_AXI_CLK>, + <&cpg CPG_MOD R9A07G044_GPU_ACE_CLK>; + clock-names = "gpu", "bus", "bus_ace"; + power-domains = <&cpg>; + resets = <&cpg R9A07G044_GPU_RESETN>, + <&cpg R9A07G044_GPU_AXI_RESETN>, + <&cpg R9A07G044_GPU_ACE_RESETN>; + reset-names = "rst", "axi_rst", "ace_rst"; + operating-points-v2 = <&gpu_opp_table>; + }; + + gic: interrupt-controller@11900000 { + compatible = "arm,gic-v3"; + #interrupt-cells = <3>; + #address-cells = <0>; + interrupt-controller; + reg = <0x0 0x11900000 0 0x40000>, + <0x0 0x11940000 0 0x60000>; + interrupts = <GIC_PPI 9 IRQ_TYPE_LEVEL_LOW>; + }; + + sdhi0: mmc@11c00000 { + compatible = "renesas,sdhi-r9a07g044", + "renesas,rcar-gen3-sdhi"; + reg = <0x0 0x11c00000 0 0x10000>; + interrupts = <GIC_SPI 104 IRQ_TYPE_LEVEL_HIGH>, + <GIC_SPI 105 IRQ_TYPE_LEVEL_HIGH>; + clocks = <&cpg CPG_MOD R9A07G044_SDHI0_IMCLK>, + <&cpg CPG_MOD R9A07G044_SDHI0_CLK_HS>, + <&cpg CPG_MOD R9A07G044_SDHI0_IMCLK2>, + <&cpg CPG_MOD R9A07G044_SDHI0_ACLK>; + clock-names = "core", "clkh", "cd", "aclk"; + resets = <&cpg R9A07G044_SDHI0_IXRST>; + power-domains = <&cpg>; + status = "disabled"; + }; + + sdhi1: mmc@11c10000 { + compatible = "renesas,sdhi-r9a07g044", + "renesas,rcar-gen3-sdhi"; + reg = <0x0 0x11c10000 0 0x10000>; + interrupts = <GIC_SPI 106 IRQ_TYPE_LEVEL_HIGH>, + <GIC_SPI 107 IRQ_TYPE_LEVEL_HIGH>; + clocks = <&cpg CPG_MOD R9A07G044_SDHI1_IMCLK>, + <&cpg CPG_MOD R9A07G044_SDHI1_CLK_HS>, + <&cpg CPG_MOD R9A07G044_SDHI1_IMCLK2>, + <&cpg CPG_MOD R9A07G044_SDHI1_ACLK>; + clock-names = "core", "clkh", "cd", "aclk"; + resets = <&cpg R9A07G044_SDHI1_IXRST>; + power-domains = <&cpg>; + status = "disabled"; + }; + + eth0: ethernet@11c20000 { + compatible = "renesas,r9a07g044-gbeth", + "renesas,rzg2l-gbeth"; + reg = <0 0x11c20000 0 0x10000>; + interrupts = <GIC_SPI 84 IRQ_TYPE_LEVEL_HIGH>, + <GIC_SPI 85 IRQ_TYPE_LEVEL_HIGH>, + <GIC_SPI 86 IRQ_TYPE_LEVEL_HIGH>; + interrupt-names = "mux", "fil", "arp_ns"; + phy-mode = "rgmii"; + clocks = <&cpg CPG_MOD R9A07G044_ETH0_CLK_AXI>, + <&cpg CPG_MOD R9A07G044_ETH0_CLK_CHI>, + <&cpg CPG_CORE R9A07G044_CLK_HP>; + clock-names = "axi", "chi", "refclk"; + resets = <&cpg R9A07G044_ETH0_RST_HW_N>; + power-domains = <&cpg>; + #address-cells = <1>; + #size-cells = <0>; + status = "disabled"; + }; + + eth1: ethernet@11c30000 { + compatible = "renesas,r9a07g044-gbeth", + "renesas,rzg2l-gbeth"; + reg = <0 0x11c30000 0 0x10000>; + interrupts = <GIC_SPI 87 IRQ_TYPE_LEVEL_HIGH>, + <GIC_SPI 88 IRQ_TYPE_LEVEL_HIGH>, + <GIC_SPI 89 IRQ_TYPE_LEVEL_HIGH>; + interrupt-names = "mux", "fil", "arp_ns"; + phy-mode = "rgmii"; + clocks = <&cpg CPG_MOD R9A07G044_ETH1_CLK_AXI>, + <&cpg CPG_MOD R9A07G044_ETH1_CLK_CHI>, + <&cpg CPG_CORE R9A07G044_CLK_HP>; + clock-names = "axi", "chi", "refclk"; + resets = <&cpg R9A07G044_ETH1_RST_HW_N>; + power-domains = <&cpg>; + #address-cells = <1>; + #size-cells = <0>; + status = "disabled"; + }; + + phyrst: usbphy-ctrl@11c40000 { + compatible = "renesas,r9a07g044-usbphy-ctrl", + "renesas,rzg2l-usbphy-ctrl"; + reg = <0 0x11c40000 0 0x10000>; + clocks = <&cpg CPG_MOD R9A07G044_USB_PCLK>; + resets = <&cpg R9A07G044_USB_PRESETN>; + power-domains = <&cpg>; + #reset-cells = <1>; + status = "disabled"; + }; + + ohci0: usb@11c50000 { + compatible = "generic-ohci"; + reg = <0 0x11c50000 0 0x100>; + interrupts = <GIC_SPI 91 IRQ_TYPE_LEVEL_HIGH>; + clocks = <&cpg CPG_MOD R9A07G044_USB_PCLK>, + <&cpg CPG_MOD R9A07G044_USB_U2H0_HCLK>; + resets = <&phyrst 0>, + <&cpg R9A07G044_USB_U2H0_HRESETN>; + phys = <&usb2_phy0 1>; + phy-names = "usb"; + power-domains = <&cpg>; + status = "disabled"; + }; + + ohci1: usb@11c70000 { + compatible = "generic-ohci"; + reg = <0 0x11c70000 0 0x100>; + interrupts = <GIC_SPI 96 IRQ_TYPE_LEVEL_HIGH>; + clocks = <&cpg CPG_MOD R9A07G044_USB_PCLK>, + <&cpg CPG_MOD R9A07G044_USB_U2H1_HCLK>; + resets = <&phyrst 1>, + <&cpg R9A07G044_USB_U2H1_HRESETN>; + phys = <&usb2_phy1 1>; + phy-names = "usb"; + power-domains = <&cpg>; + status = "disabled"; + }; + + ehci0: usb@11c50100 { + compatible = "generic-ehci"; + reg = <0 0x11c50100 0 0x100>; + interrupts = <GIC_SPI 92 IRQ_TYPE_LEVEL_HIGH>; + clocks = <&cpg CPG_MOD R9A07G044_USB_PCLK>, + <&cpg CPG_MOD R9A07G044_USB_U2H0_HCLK>; + resets = <&phyrst 0>, + <&cpg R9A07G044_USB_U2H0_HRESETN>; + phys = <&usb2_phy0 2>; + phy-names = "usb"; + companion = <&ohci0>; + power-domains = <&cpg>; + status = "disabled"; + }; + + ehci1: usb@11c70100 { + compatible = "generic-ehci"; + reg = <0 0x11c70100 0 0x100>; + interrupts = <GIC_SPI 97 IRQ_TYPE_LEVEL_HIGH>; + clocks = <&cpg CPG_MOD R9A07G044_USB_PCLK>, + <&cpg CPG_MOD R9A07G044_USB_U2H1_HCLK>; + resets = <&phyrst 1>, + <&cpg R9A07G044_USB_U2H1_HRESETN>; + phys = <&usb2_phy1 2>; + phy-names = "usb"; + companion = <&ohci1>; + power-domains = <&cpg>; + status = "disabled"; + }; + + usb2_phy0: usb-phy@11c50200 { + compatible = "renesas,usb2-phy-r9a07g044", + "renesas,rzg2l-usb2-phy"; + reg = <0 0x11c50200 0 0x700>; + interrupts = <GIC_SPI 94 IRQ_TYPE_LEVEL_HIGH>; + clocks = <&cpg CPG_MOD R9A07G044_USB_PCLK>, + <&cpg CPG_MOD R9A07G044_USB_U2H0_HCLK>; + resets = <&phyrst 0>; + #phy-cells = <1>; + power-domains = <&cpg>; + status = "disabled"; + }; + + usb2_phy1: usb-phy@11c70200 { + compatible = "renesas,usb2-phy-r9a07g044", + "renesas,rzg2l-usb2-phy"; + reg = <0 0x11c70200 0 0x700>; + interrupts = <GIC_SPI 99 IRQ_TYPE_LEVEL_HIGH>; + clocks = <&cpg CPG_MOD R9A07G044_USB_PCLK>, + <&cpg CPG_MOD R9A07G044_USB_U2H1_HCLK>; + resets = <&phyrst 1>; + #phy-cells = <1>; + power-domains = <&cpg>; + status = "disabled"; + }; + + hsusb: usb@11c60000 { + compatible = "renesas,usbhs-r9a07g044", + "renesas,rza2-usbhs"; + reg = <0 0x11c60000 0 0x10000>; + interrupts = <GIC_SPI 100 IRQ_TYPE_EDGE_RISING>, + <GIC_SPI 101 IRQ_TYPE_LEVEL_HIGH>, + <GIC_SPI 102 IRQ_TYPE_LEVEL_HIGH>, + <GIC_SPI 103 IRQ_TYPE_LEVEL_HIGH>; + clocks = <&cpg CPG_MOD R9A07G044_USB_PCLK>, + <&cpg CPG_MOD R9A07G044_USB_U2P_EXR_CPUCLK>; + resets = <&phyrst 0>, + <&cpg R9A07G044_USB_U2P_EXL_SYSRST>; + renesas,buswait = <7>; + phys = <&usb2_phy0 3>; + phy-names = "usb"; + power-domains = <&cpg>; + status = "disabled"; + }; + + wdt0: watchdog@12800800 { + compatible = "renesas,r9a07g044-wdt", + "renesas,rzg2l-wdt"; + reg = <0 0x12800800 0 0x400>; + clocks = <&cpg CPG_MOD R9A07G044_WDT0_PCLK>, + <&cpg CPG_MOD R9A07G044_WDT0_CLK>; + clock-names = "pclk", "oscclk"; + interrupts = <GIC_SPI 49 IRQ_TYPE_LEVEL_HIGH>, + <GIC_SPI 50 IRQ_TYPE_LEVEL_HIGH>; + interrupt-names = "wdt", "perrout"; + resets = <&cpg R9A07G044_WDT0_PRESETN>; + power-domains = <&cpg>; + status = "disabled"; + }; + + wdt1: watchdog@12800c00 { + compatible = "renesas,r9a07g044-wdt", + "renesas,rzg2l-wdt"; + reg = <0 0x12800C00 0 0x400>; + clocks = <&cpg CPG_MOD R9A07G044_WDT1_PCLK>, + <&cpg CPG_MOD R9A07G044_WDT1_CLK>; + clock-names = "pclk", "oscclk"; + interrupts = <GIC_SPI 51 IRQ_TYPE_LEVEL_HIGH>, + <GIC_SPI 52 IRQ_TYPE_LEVEL_HIGH>; + interrupt-names = "wdt", "perrout"; + resets = <&cpg R9A07G044_WDT1_PRESETN>; + power-domains = <&cpg>; + status = "disabled"; + }; + + ostm0: timer@12801000 { + compatible = "renesas,r9a07g044-ostm", + "renesas,ostm"; + reg = <0x0 0x12801000 0x0 0x400>; + interrupts = <GIC_SPI 46 IRQ_TYPE_EDGE_RISING>; + clocks = <&cpg CPG_MOD R9A07G044_OSTM0_PCLK>; + resets = <&cpg R9A07G044_OSTM0_PRESETZ>; + power-domains = <&cpg>; + status = "disabled"; + }; + + ostm1: timer@12801400 { + compatible = "renesas,r9a07g044-ostm", + "renesas,ostm"; + reg = <0x0 0x12801400 0x0 0x400>; + interrupts = <GIC_SPI 47 IRQ_TYPE_EDGE_RISING>; + clocks = <&cpg CPG_MOD R9A07G044_OSTM1_PCLK>; + resets = <&cpg R9A07G044_OSTM1_PRESETZ>; + power-domains = <&cpg>; + status = "disabled"; + }; + + ostm2: timer@12801800 { + compatible = "renesas,r9a07g044-ostm", + "renesas,ostm"; + reg = <0x0 0x12801800 0x0 0x400>; + interrupts = <GIC_SPI 48 IRQ_TYPE_EDGE_RISING>; + clocks = <&cpg CPG_MOD R9A07G044_OSTM2_PCLK>; + resets = <&cpg R9A07G044_OSTM2_PRESETZ>; + power-domains = <&cpg>; + status = "disabled"; + }; + }; + + thermal-zones { + cpu-thermal { + polling-delay-passive = <250>; + polling-delay = <1000>; + thermal-sensors = <&tsu 0>; + sustainable-power = <717>; + + cooling-maps { + map0 { + trip = <&target>; + cooling-device = <&cpu0 0 2>; + contribution = <1024>; + }; + }; + + trips { + sensor_crit: sensor-crit { + temperature = <125000>; + hysteresis = <1000>; + type = "critical"; + }; + + target: trip-point { + temperature = <100000>; + hysteresis = <1000>; + type = "passive"; + }; + }; + }; + }; + + timer { + compatible = "arm,armv8-timer"; + interrupts-extended = <&gic GIC_PPI 13 IRQ_TYPE_LEVEL_LOW>, + <&gic GIC_PPI 14 IRQ_TYPE_LEVEL_LOW>, + <&gic GIC_PPI 11 IRQ_TYPE_LEVEL_LOW>, + <&gic GIC_PPI 10 IRQ_TYPE_LEVEL_LOW>; + }; +}; diff --git a/arch/arm/dts/r9a07g044l2-smarc.dts b/arch/arm/dts/r9a07g044l2-smarc.dts new file mode 100644 index 000000000000..bc2af6c92ccd --- /dev/null +++ b/arch/arm/dts/r9a07g044l2-smarc.dts @@ -0,0 +1,18 @@ +// SPDX-License-Identifier: (GPL-2.0-only OR BSD-2-Clause) +/* + * Device Tree Source for the RZ/G2L SMARC EVK board + * + * Copyright (C) 2021 Renesas Electronics Corp. + */ + +/dts-v1/; +#include "r9a07g044l2.dtsi" +#include "rzg2l-smarc-som.dtsi" +#include "rzg2l-smarc-pinfunction.dtsi" +#include "rz-smarc-common.dtsi" +#include "rzg2l-smarc.dtsi" + +/ { + model = "Renesas SMARC EVK based on r9a07g044l2"; + compatible = "renesas,smarc-evk", "renesas,r9a07g044l2", "renesas,r9a07g044"; +}; diff --git a/arch/arm/dts/r9a07g044l2.dtsi b/arch/arm/dts/r9a07g044l2.dtsi new file mode 100644 index 000000000000..91dc10b2cdbb --- /dev/null +++ b/arch/arm/dts/r9a07g044l2.dtsi @@ -0,0 +1,13 @@ +// SPDX-License-Identifier: (GPL-2.0-only OR BSD-2-Clause) +/* + * Device Tree Source for the RZ/G2L R9A07G044L2 SoC specific parts + * + * Copyright (C) 2021 Renesas Electronics Corp. + */ + +/dts-v1/; +#include "r9a07g044.dtsi" + +/ { + compatible = "renesas,r9a07g044l2", "renesas,r9a07g044"; +}; diff --git a/arch/arm/dts/rz-smarc-common.dtsi b/arch/arm/dts/rz-smarc-common.dtsi new file mode 100644 index 000000000000..3962d47b3e59 --- /dev/null +++ b/arch/arm/dts/rz-smarc-common.dtsi @@ -0,0 +1,183 @@ +// SPDX-License-Identifier: (GPL-2.0-only OR BSD-2-Clause) +/* + * Device Tree Source for the RZ/{G2L,G2LC,V2L} SMARC EVK common parts + * + * Copyright (C) 2022 Renesas Electronics Corp. + */ + +#include <dt-bindings/gpio/gpio.h> +#include <dt-bindings/pinctrl/rzg2l-pinctrl.h> + +/* + * SSI-WM8978 + * + * This command is required when Playback/Capture + * + * amixer cset name='Left Input Mixer L2 Switch' on + * amixer cset name='Right Input Mixer R2 Switch' on + * amixer cset name='Headphone Playback Volume' 100 + * amixer cset name='PCM Volume' 100% + * amixer cset name='Input PGA Volume' 25 + * + */ + +/ { + aliases { + serial0 = &scif0; + i2c0 = &i2c0; + i2c1 = &i2c1; + }; + + chosen { + stdout-path = "serial0:115200n8"; + }; + + audio_mclock: audio_mclock { + compatible = "fixed-clock"; + #clock-cells = <0>; + clock-frequency = <11289600>; + }; + + snd_rzg2l: sound { + compatible = "simple-audio-card"; + simple-audio-card,format = "i2s"; + simple-audio-card,bitclock-master = <&cpu_dai>; + simple-audio-card,frame-master = <&cpu_dai>; + simple-audio-card,mclk-fs = <256>; + + simple-audio-card,widgets = "Microphone", "Microphone Jack"; + simple-audio-card,routing = + "L2", "Mic Bias", + "R2", "Mic Bias", + "Mic Bias", "Microphone Jack"; + + cpu_dai: simple-audio-card,cpu { + }; + + codec_dai: simple-audio-card,codec { + clocks = <&audio_mclock>; + sound-dai = <&wm8978>; + }; + }; + + usb0_vbus_otg: regulator-usb0-vbus-otg { + compatible = "regulator-fixed"; + + regulator-name = "USB0_VBUS_OTG"; + regulator-min-microvolt = <5000000>; + regulator-max-microvolt = <5000000>; + }; + + vccq_sdhi1: regulator-vccq-sdhi1 { + compatible = "regulator-gpio"; + regulator-name = "SDHI1 VccQ"; + regulator-min-microvolt = <1800000>; + regulator-max-microvolt = <3300000>; + gpios-states = <1>; + states = <3300000 1>, <1800000 0>; + }; +}; + +&audio_clk1{ + clock-frequency = <11289600>; +}; + +&audio_clk2{ + clock-frequency = <12288000>; +}; + +&canfd { + pinctrl-0 = <&can0_pins &can1_pins>; + pinctrl-names = "default"; + status = "okay"; + + channel0 { + status = "okay"; + }; + + channel1 { + status = "okay"; + }; +}; + +&ehci0 { + dr_mode = "otg"; + status = "okay"; +}; + +&ehci1 { + status = "okay"; +}; + +&hsusb { + dr_mode = "otg"; + status = "okay"; +}; + +&i2c0 { + pinctrl-0 = <&i2c0_pins>; + pinctrl-names = "default"; + + status = "okay"; +}; + +&i2c1 { + pinctrl-0 = <&i2c1_pins>; + pinctrl-names = "default"; + + status = "okay"; +}; + +&ohci0 { + dr_mode = "otg"; + status = "okay"; +}; + +&ohci1 { + status = "okay"; +}; + +&phyrst { + status = "okay"; +}; + +&scif0 { + pinctrl-0 = <&scif0_pins>; + pinctrl-names = "default"; + status = "okay"; +}; + +&sdhi1 { + pinctrl-0 = <&sdhi1_pins>; + pinctrl-1 = <&sdhi1_pins_uhs>; + pinctrl-names = "default", "state_uhs"; + + vmmc-supply = <®_3p3v>; + vqmmc-supply = <&vccq_sdhi1>; + bus-width = <4>; + sd-uhs-sdr50; + sd-uhs-sdr104; + status = "okay"; +}; + +&spi1 { + pinctrl-0 = <&spi1_pins>; + pinctrl-names = "default"; + + status = "okay"; +}; + +&usb2_phy0 { + pinctrl-0 = <&usb0_pins>; + pinctrl-names = "default"; + + vbus-supply = <&usb0_vbus_otg>; + status = "okay"; +}; + +&usb2_phy1 { + pinctrl-0 = <&usb1_pins>; + pinctrl-names = "default"; + + status = "okay"; +}; diff --git a/arch/arm/dts/rzg2l-smarc-pinfunction.dtsi b/arch/arm/dts/rzg2l-smarc-pinfunction.dtsi new file mode 100644 index 000000000000..9085d8c76ce1 --- /dev/null +++ b/arch/arm/dts/rzg2l-smarc-pinfunction.dtsi @@ -0,0 +1,137 @@ +// SPDX-License-Identifier: (GPL-2.0-only OR BSD-2-Clause) +/* + * Device Tree Source for the RZ/{G2L,V2L} SMARC pincontrol parts + * + * Copyright (C) 2021 Renesas Electronics Corp. + */ + +#include <dt-bindings/gpio/gpio.h> +#include <dt-bindings/pinctrl/rzg2l-pinctrl.h> + +&pinctrl { + pinctrl-0 = <&sound_clk_pins>; + pinctrl-names = "default"; + + can0_pins: can0 { + pinmux = <RZG2L_PORT_PINMUX(10, 1, 2)>, /* TX */ + <RZG2L_PORT_PINMUX(11, 0, 2)>; /* RX */ + }; + + /* SW7 should be at position 2->3 so that GPIO8_CAN0_STB line is activated */ + can0-stb-hog { + gpio-hog; + gpios = <RZG2L_GPIO(42, 2) GPIO_ACTIVE_HIGH>; + output-low; + line-name = "can0_stb"; + }; + + can1_pins: can1 { + pinmux = <RZG2L_PORT_PINMUX(12, 1, 2)>, /* TX */ + <RZG2L_PORT_PINMUX(13, 0, 2)>; /* RX */ + }; + + /* SW8 should be at position 2->3 so that GPIO9_CAN1_STB line is activated */ + can1-stb-hog { + gpio-hog; + gpios = <RZG2L_GPIO(42, 3) GPIO_ACTIVE_HIGH>; + output-low; + line-name = "can1_stb"; + }; + + i2c0_pins: i2c0 { + pins = "RIIC0_SDA", "RIIC0_SCL"; + input-enable; + }; + + i2c1_pins: i2c1 { + pins = "RIIC1_SDA", "RIIC1_SCL"; + input-enable; + }; + + i2c3_pins: i2c3 { + pinmux = <RZG2L_PORT_PINMUX(18, 0, 3)>, /* SDA */ + <RZG2L_PORT_PINMUX(18, 1, 3)>; /* SCL */ + }; + + scif0_pins: scif0 { + pinmux = <RZG2L_PORT_PINMUX(38, 0, 1)>, /* TxD */ + <RZG2L_PORT_PINMUX(38, 1, 1)>; /* RxD */ + }; + + scif2_pins: scif2 { + pinmux = <RZG2L_PORT_PINMUX(48, 0, 1)>, /* TxD */ + <RZG2L_PORT_PINMUX(48, 1, 1)>, /* RxD */ + <RZG2L_PORT_PINMUX(48, 3, 1)>, /* CTS# */ + <RZG2L_PORT_PINMUX(48, 4, 1)>; /* RTS# */ + }; + + sd1-pwr-en-hog { + gpio-hog; + gpios = <RZG2L_GPIO(39, 2) GPIO_ACTIVE_HIGH>; + output-high; + line-name = "sd1_pwr_en"; + }; + + sdhi1_pins: sd1 { + sd1_data { + pins = "SD1_DATA0", "SD1_DATA1", "SD1_DATA2", "SD1_DATA3"; + power-source = <3300>; + }; + + sd1_ctrl { + pins = "SD1_CLK", "SD1_CMD"; + power-source = <3300>; + }; + + sd1_mux { + pinmux = <RZG2L_PORT_PINMUX(19, 0, 1)>; /* SD1_CD */ + }; + }; + + sdhi1_pins_uhs: sd1_uhs { + sd1_data_uhs { + pins = "SD1_DATA0", "SD1_DATA1", "SD1_DATA2", "SD1_DATA3"; + power-source = <1800>; + }; + + sd1_ctrl_uhs { + pins = "SD1_CLK", "SD1_CMD"; + power-source = <1800>; + }; + + sd1_mux_uhs { + pinmux = <RZG2L_PORT_PINMUX(19, 0, 1)>; /* SD1_CD */ + }; + }; + + sound_clk_pins: sound_clk { + pins = "AUDIO_CLK1", "AUDIO_CLK2"; + input-enable; + }; + + spi1_pins: spi1 { + pinmux = <RZG2L_PORT_PINMUX(44, 0, 1)>, /* CK */ + <RZG2L_PORT_PINMUX(44, 1, 1)>, /* MOSI */ + <RZG2L_PORT_PINMUX(44, 2, 1)>, /* MISO */ + <RZG2L_PORT_PINMUX(44, 3, 1)>; /* SSL */ + }; + + ssi0_pins: ssi0 { + pinmux = <RZG2L_PORT_PINMUX(45, 0, 1)>, /* BCK */ + <RZG2L_PORT_PINMUX(45, 1, 1)>, /* RCK */ + <RZG2L_PORT_PINMUX(45, 2, 1)>, /* TXD */ + <RZG2L_PORT_PINMUX(45, 3, 1)>; /* RXD */ + }; + + usb0_pins: usb0 { + pinmux = <RZG2L_PORT_PINMUX(4, 0, 1)>, /* VBUS */ + <RZG2L_PORT_PINMUX(5, 0, 1)>, /* OVC */ + <RZG2L_PORT_PINMUX(5, 1, 1)>; /* OTG_ID */ + }; + + usb1_pins: usb1 { + pinmux = <RZG2L_PORT_PINMUX(42, 0, 1)>, /* VBUS */ + <RZG2L_PORT_PINMUX(42, 1, 1)>; /* OVC */ + }; +}; + diff --git a/arch/arm/dts/rzg2l-smarc-som.dtsi b/arch/arm/dts/rzg2l-smarc-som.dtsi new file mode 100644 index 000000000000..fbbb4f03440b --- /dev/null +++ b/arch/arm/dts/rzg2l-smarc-som.dtsi @@ -0,0 +1,353 @@ +// SPDX-License-Identifier: (GPL-2.0-only OR BSD-2-Clause) +/* + * Device Tree Source for the RZ/{G2L,V2L} SMARC SOM common parts + * + * Copyright (C) 2021 Renesas Electronics Corp. + */ + +#include <dt-bindings/gpio/gpio.h> +#include <dt-bindings/interrupt-controller/irqc-rzg2l.h> +#include <dt-bindings/pinctrl/rzg2l-pinctrl.h> + +/* SW1[2] should be at position 2/OFF to enable 64 GB eMMC */ +#define EMMC 1 + +/* + * To enable uSD card on CN3, + * SW1[2] should be at position 3/ON. + * Disable eMMC by setting "#define EMMC 0" above. + */ +#define SDHI (!EMMC) + +/ { + aliases { + ethernet0 = ð0; + ethernet1 = ð1; + }; + + chosen { + bootargs = "ignore_loglevel rw root=/dev/nfs ip=on"; + }; + + memory@48000000 { + device_type = "memory"; + /* first 128MB is reserved for secure area. */ + reg = <0x0 0x48000000 0x0 0x78000000>; + }; + + reg_1p8v: regulator-1p8v { + compatible = "regulator-fixed"; + regulator-name = "fixed-1.8V"; + regulator-min-microvolt = <1800000>; + regulator-max-microvolt = <1800000>; + regulator-boot-on; + regulator-always-on; + }; + + reg_3p3v: regulator-3p3v { + compatible = "regulator-fixed"; + regulator-name = "fixed-3.3V"; + regulator-min-microvolt = <3300000>; + regulator-max-microvolt = <3300000>; + regulator-boot-on; + regulator-always-on; + }; + + reg_1p1v: regulator-vdd-core { + compatible = "regulator-fixed"; + regulator-name = "fixed-1.1V"; + regulator-min-microvolt = <1100000>; + regulator-max-microvolt = <1100000>; + regulator-boot-on; + regulator-always-on; + }; + + vccq_sdhi0: regulator-vccq-sdhi0 { + compatible = "regulator-gpio"; + + regulator-name = "SDHI0 VccQ"; + regulator-min-microvolt = <1800000>; + regulator-max-microvolt = <3300000>; + states = <3300000 1>, <1800000 0>; + regulator-boot-on; + gpios = <&pinctrl RZG2L_GPIO(39, 0) GPIO_ACTIVE_HIGH>; + regulator-always-on; + }; +}; + +&adc { + pinctrl-0 = <&adc_pins>; + pinctrl-names = "default"; + status = "okay"; + + /delete-node/ channel@6; + /delete-node/ channel@7; +}; + +ð0 { + pinctrl-0 = <ð0_pins>; + pinctrl-names = "default"; + phy-handle = <&phy0>; + phy-mode = "rgmii-id"; + status = "okay"; + + phy0: ethernet-phy@7 { + compatible = "ethernet-phy-id0022.1640", + "ethernet-phy-ieee802.3-c22"; + reg = <7>; + interrupt-parent = <&irqc>; + interrupts = <RZG2L_IRQ2 IRQ_TYPE_LEVEL_LOW>; + rxc-skew-psec = <2400>; + txc-skew-psec = <2400>; + rxdv-skew-psec = <0>; + txdv-skew-psec = <0>; + rxd0-skew-psec = <0>; + rxd1-skew-psec = <0>; + rxd2-skew-psec = <0>; + rxd3-skew-psec = <0>; + txd0-skew-psec = <0>; + txd1-skew-psec = <0>; + txd2-skew-psec = <0>; + txd3-skew-psec = <0>; + }; +}; + +ð1 { + pinctrl-0 = <ð1_pins>; + pinctrl-names = "default"; + phy-handle = <&phy1>; + phy-mode = "rgmii-id"; + status = "okay"; + + phy1: ethernet-phy@7 { + compatible = "ethernet-phy-id0022.1640", + "ethernet-phy-ieee802.3-c22"; + reg = <7>; + interrupt-parent = <&irqc>; + interrupts = <RZG2L_IRQ3 IRQ_TYPE_LEVEL_LOW>; + rxc-skew-psec = <2400>; + txc-skew-psec = <2400>; + rxdv-skew-psec = <0>; + txdv-skew-psec = <0>; + rxd0-skew-psec = <0>; + rxd1-skew-psec = <0>; + rxd2-skew-psec = <0>; + rxd3-skew-psec = <0>; + txd0-skew-psec = <0>; + txd1-skew-psec = <0>; + txd2-skew-psec = <0>; + txd3-skew-psec = <0>; + }; +}; + +&extal_clk { + clock-frequency = <24000000>; +}; + +&gpu { + mali-supply = <®_1p1v>; +}; + +&ostm1 { + status = "okay"; +}; + +&ostm2 { + status = "okay"; +}; + +&pinctrl { + adc_pins: adc { + pinmux = <RZG2L_PORT_PINMUX(9, 0, 2)>; /* ADC_TRG */ + }; + + eth0_pins: eth0 { + pinmux = <RZG2L_PORT_PINMUX(28, 1, 1)>, /* ET0_LINKSTA */ + <RZG2L_PORT_PINMUX(27, 1, 1)>, /* ET0_MDC */ + <RZG2L_PORT_PINMUX(28, 0, 1)>, /* ET0_MDIO */ + <RZG2L_PORT_PINMUX(20, 0, 1)>, /* ET0_TXC */ + <RZG2L_PORT_PINMUX(20, 1, 1)>, /* ET0_TX_CTL */ + <RZG2L_PORT_PINMUX(20, 2, 1)>, /* ET0_TXD0 */ + <RZG2L_PORT_PINMUX(21, 0, 1)>, /* ET0_TXD1 */ + <RZG2L_PORT_PINMUX(21, 1, 1)>, /* ET0_TXD2 */ + <RZG2L_PORT_PINMUX(22, 0, 1)>, /* ET0_TXD3 */ + <RZG2L_PORT_PINMUX(24, 0, 1)>, /* ET0_RXC */ + <RZG2L_PORT_PINMUX(24, 1, 1)>, /* ET0_RX_CTL */ + <RZG2L_PORT_PINMUX(25, 0, 1)>, /* ET0_RXD0 */ + <RZG2L_PORT_PINMUX(25, 1, 1)>, /* ET0_RXD1 */ + <RZG2L_PORT_PINMUX(26, 0, 1)>, /* ET0_RXD2 */ + <RZG2L_PORT_PINMUX(26, 1, 1)>, /* ET0_RXD3 */ + <RZG2L_PORT_PINMUX(1, 0, 1)>; /* IRQ2 */ + }; + + eth1_pins: eth1 { + pinmux = <RZG2L_PORT_PINMUX(37, 2, 1)>, /* ET1_LINKSTA */ + <RZG2L_PORT_PINMUX(37, 0, 1)>, /* ET1_MDC */ + <RZG2L_PORT_PINMUX(37, 1, 1)>, /* ET1_MDIO */ + <RZG2L_PORT_PINMUX(29, 0, 1)>, /* ET1_TXC */ + <RZG2L_PORT_PINMUX(29, 1, 1)>, /* ET1_TX_CTL */ + <RZG2L_PORT_PINMUX(30, 0, 1)>, /* ET1_TXD0 */ + <RZG2L_PORT_PINMUX(30, 1, 1)>, /* ET1_TXD1 */ + <RZG2L_PORT_PINMUX(31, 0, 1)>, /* ET1_TXD2 */ + <RZG2L_PORT_PINMUX(31, 1, 1)>, /* ET1_TXD3 */ + <RZG2L_PORT_PINMUX(33, 1, 1)>, /* ET1_RXC */ + <RZG2L_PORT_PINMUX(34, 0, 1)>, /* ET1_RX_CTL */ + <RZG2L_PORT_PINMUX(34, 1, 1)>, /* ET1_RXD0 */ + <RZG2L_PORT_PINMUX(35, 0, 1)>, /* ET1_RXD1 */ + <RZG2L_PORT_PINMUX(35, 1, 1)>, /* ET1_RXD2 */ + <RZG2L_PORT_PINMUX(36, 0, 1)>, /* ET1_RXD3 */ + <RZG2L_PORT_PINMUX(1, 1, 1)>; /* IRQ3 */ + }; + + gpio-sd0-pwr-en-hog { + gpio-hog; + gpios = <RZG2L_GPIO(4, 1) GPIO_ACTIVE_HIGH>; + output-high; + line-name = "gpio_sd0_pwr_en"; + }; + + qspi0_pins: qspi0 { + qspi0-data { + pins = "QSPI0_IO0", "QSPI0_IO1", "QSPI0_IO2", "QSPI0_IO3"; + power-source = <1800>; + }; + + qspi0-ctrl { + pins = "QSPI0_SPCLK", "QSPI0_SSL", "QSPI_RESET#"; + power-source = <1800>; + }; + }; + + /* + * SD0 device selection is XOR between GPIO_SD0_DEV_SEL and SW1[2] + * The below switch logic can be used to select the device between + * eMMC and microSD, after setting GPIO_SD0_DEV_SEL to high in DT. + * SW1[2] should be at position 2/OFF to enable 64 GB eMMC + * SW1[2] should be at position 3/ON to enable uSD card CN3 + */ + sd0-dev-sel-hog { + gpio-hog; + gpios = <RZG2L_GPIO(41, 1) GPIO_ACTIVE_HIGH>; + output-high; + line-name = "sd0_dev_sel"; + }; + + sdhi0_emmc_pins: sd0emmc { + sd0_emmc_data { + pins = "SD0_DATA0", "SD0_DATA1", "SD0_DATA2", "SD0_DATA3", + "SD0_DATA4", "SD0_DATA5", "SD0_DATA6", "SD0_DATA7"; + power-source = <1800>; + }; + + sd0_emmc_ctrl { + pins = "SD0_CLK", "SD0_CMD"; + power-source = <1800>; + }; + + sd0_emmc_rst { + pins = "SD0_RST#"; + power-source = <1800>; + }; + }; + + sdhi0_pins: sd0 { + sd0_data { + pins = "SD0_DATA0", "SD0_DATA1", "SD0_DATA2", "SD0_DATA3"; + power-source = <3300>; + }; + + sd0_ctrl { + pins = "SD0_CLK", "SD0_CMD"; + power-source = <3300>; + }; + + sd0_mux { + pinmux = <RZG2L_PORT_PINMUX(47, 0, 2)>; /* SD0_CD */ + }; + }; + + sdhi0_pins_uhs: sd0_uhs { + sd0_data_uhs { + pins = "SD0_DATA0", "SD0_DATA1", "SD0_DATA2", "SD0_DATA3"; + power-source = <1800>; + }; + + sd0_ctrl_uhs { + pins = "SD0_CLK", "SD0_CMD"; + power-source = <1800>; + }; + + sd0_mux_uhs { + pinmux = <RZG2L_PORT_PINMUX(47, 0, 2)>; /* SD0_CD */ + }; + }; +}; + +&sbc { + pinctrl-0 = <&qspi0_pins>; + pinctrl-names = "default"; + status = "okay"; + + flash@0 { + compatible = "micron,mt25qu512a", "jedec,spi-nor"; + reg = <0>; + m25p,fast-read; + spi-max-frequency = <50000000>; + spi-rx-bus-width = <4>; + + partitions { + compatible = "fixed-partitions"; + #address-cells = <1>; + #size-cells = <1>; + + boot@0 { + reg = <0x00000000 0x2000000>; + read-only; + }; + user@2000000 { + reg = <0x2000000 0x2000000>; + }; + }; + }; +}; + +#if SDHI +&sdhi0 { + pinctrl-0 = <&sdhi0_pins>; + pinctrl-1 = <&sdhi0_pins_uhs>; + pinctrl-names = "default", "state_uhs"; + + vmmc-supply = <®_3p3v>; + vqmmc-supply = <&vccq_sdhi0>; + bus-width = <4>; + sd-uhs-sdr50; + sd-uhs-sdr104; + status = "okay"; +}; +#endif + +#if EMMC +&sdhi0 { + pinctrl-0 = <&sdhi0_emmc_pins>; + pinctrl-1 = <&sdhi0_emmc_pins>; + pinctrl-names = "default", "state_uhs"; + + vmmc-supply = <®_3p3v>; + vqmmc-supply = <®_1p8v>; + bus-width = <8>; + mmc-hs200-1_8v; + non-removable; + fixed-emmc-driver-type = <1>; + status = "okay"; +}; +#endif + +&wdt0 { + status = "okay"; + timeout-sec = <60>; +}; + +&wdt1 { + status = "okay"; + timeout-sec = <60>; +}; diff --git a/arch/arm/dts/rzg2l-smarc.dtsi b/arch/arm/dts/rzg2l-smarc.dtsi new file mode 100644 index 000000000000..2a158a954b2f --- /dev/null +++ b/arch/arm/dts/rzg2l-smarc.dtsi @@ -0,0 +1,144 @@ +// SPDX-License-Identifier: (GPL-2.0-only OR BSD-2-Clause) +/* + * Device Tree Source for the RZ/{G2L,V2L} SMARC EVK common parts + * + * Copyright (C) 2021 Renesas Electronics Corp. + */ + +#include <dt-bindings/gpio/gpio.h> +#include <dt-bindings/pinctrl/rzg2l-pinctrl.h> + +/* comment the #define statement to disable SCIF2 (SER0) on PMOD1 (CN7) */ +#define PMOD1_SER0 1 + +/ { + aliases { + serial1 = &scif2; + i2c3 = &i2c3; + }; + + osc1: cec-clock { + compatible = "fixed-clock"; + #clock-cells = <0>; + clock-frequency = <12000000>; + }; + + hdmi-out { + compatible = "hdmi-connector"; + type = "d"; + + port { + hdmi_con_out: endpoint { + remote-endpoint = <&adv7535_out>; + }; + }; + }; +}; + +&cpu_dai { + sound-dai = <&ssi0>; +}; + +&dsi { + status = "okay"; + + ports { + #address-cells = <1>; + #size-cells = <0>; + + port@0 { + reg = <0>; + dsi0_in: endpoint { + }; + }; + + port@1 { + reg = <1>; + dsi0_out: endpoint { + data-lanes = <1 2 3 4>; + remote-endpoint = <&adv7535_in>; + }; + }; + }; +}; + +&i2c1 { + adv7535: hdmi@3d { + compatible = "adi,adv7535"; + reg = <0x3d>; + + interrupt-parent = <&pinctrl>; + interrupts = <RZG2L_GPIO(2, 1) IRQ_TYPE_EDGE_FALLING>; + clocks = <&osc1>; + clock-names = "cec"; + avdd-supply = <®_1p8v>; + dvdd-supply = <®_1p8v>; + pvdd-supply = <®_1p8v>; + a2vdd-supply = <®_1p8v>; + v3p3-supply = <®_3p3v>; + v1p2-supply = <®_1p8v>; + + adi,dsi-lanes = <4>; + + ports { + #address-cells = <1>; + #size-cells = <0>; + + port@0 { + reg = <0>; + adv7535_in: endpoint { + remote-endpoint = <&dsi0_out>; + }; + }; + + port@1 { + reg = <1>; + adv7535_out: endpoint { + remote-endpoint = <&hdmi_con_out>; + }; + }; + }; + }; +}; + +&i2c3 { + pinctrl-0 = <&i2c3_pins>; + pinctrl-names = "default"; + clock-frequency = <400000>; + + status = "okay"; + + wm8978: codec@1a { + compatible = "wlf,wm8978"; + #sound-dai-cells = <0>; + reg = <0x1a>; + }; +}; + +/* + * To enable SCIF2 (SER0) on PMOD1 (CN7) + * SW1 should be at position 2->3 so that SER0_CTS# line is activated + * SW2 should be at position 2->3 so that SER0_TX line is activated + * SW3 should be at position 2->3 so that SER0_RX line is activated + * SW4 should be at position 2->3 so that SER0_RTS# line is activated + */ +#if PMOD1_SER0 +&scif2 { + pinctrl-0 = <&scif2_pins>; + pinctrl-names = "default"; + + uart-has-rtscts; + status = "okay"; +}; +#endif + +&ssi0 { + pinctrl-0 = <&ssi0_pins>; + pinctrl-names = "default"; + + status = "okay"; +}; + +&vccq_sdhi1 { + gpios = <&pinctrl RZG2L_GPIO(39, 1) GPIO_ACTIVE_HIGH>; +};

On 9/20/23 14:42, Paul Barker wrote:
The Renesas RZ/G2L SMARC Evaluation Board Kit consists of the RZ/G2L System-on-Module (SOM) based on the R9A07G044L2 SoC, and a common SMARC carrier board.
This patch is based on the corresponding Linux v6.5 device tree.
Signed-off-by: Paul Barker paul.barker.ct@bp.renesas.com
Reviewed-by: Marek Vasut marek.vasut+renesas@mailbox.org

The Renesas RZ/G2L SMARC Evaluation Board Kit consists of the RZ/G2L System-on-Module (SOM) based on the R9A07G044L2 SoC, and a common SMARC carrier board.
The ARM TrustedFirmware code for the Renesas RZ/G2L SoC family passes a devicetree blob to the bootloader as an argument in the same was previous R-Car gen3/gen4 SoCs. This blob contains a compatible string which can be used to identify the particular SoC we are running on and this is used to select the appropriate device tree to load.
The configuration renesas_rzg2l_smarc_defconfig is added to support building for this target. In the future this defconfig will be extended to support other SoCs and evaluation boards from the RZ/G2L family.
Signed-off-by: Paul Barker paul.barker.ct@bp.renesas.com Reviewed-by: Biju Das biju.das.jz@bp.renesas.com Reviewed-by: Lad Prabhakar prabhakar.mahadev-lad.rj@bp.renesas.com --- arch/arm/mach-rmobile/Kconfig.rzg2l | 14 +++++ board/renesas/rzg2l/Kconfig | 18 +++++++ board/renesas/rzg2l/MAINTAINERS | 6 +++ board/renesas/rzg2l/Makefile | 4 ++ board/renesas/rzg2l/rzg2l.c | 76 +++++++++++++++++++++++++++ configs/renesas_rzg2l_smarc_defconfig | 52 ++++++++++++++++++ include/configs/rzg2l-smarc.h | 14 +++++ 7 files changed, 184 insertions(+) create mode 100644 board/renesas/rzg2l/Kconfig create mode 100644 board/renesas/rzg2l/MAINTAINERS create mode 100644 board/renesas/rzg2l/Makefile create mode 100644 board/renesas/rzg2l/rzg2l.c create mode 100644 configs/renesas_rzg2l_smarc_defconfig create mode 100644 include/configs/rzg2l-smarc.h
diff --git a/arch/arm/mach-rmobile/Kconfig.rzg2l b/arch/arm/mach-rmobile/Kconfig.rzg2l index 7d268e8c366a..1fe49e323300 100644 --- a/arch/arm/mach-rmobile/Kconfig.rzg2l +++ b/arch/arm/mach-rmobile/Kconfig.rzg2l @@ -9,6 +9,20 @@ config R9A07G044L help Enable support for the R9A07G044L SoC used in the RZ/G2L.
+choice + prompt "Renesas RZ/G2L Family Board selection" + default TARGET_RZG2L_SMARC_EVK + +config TARGET_RZG2L_SMARC_EVK + bool "Renesas RZ/G2L SMARC EVK" + imply R9A07G044L + help + Enable support for the RZ/G2L SMARC evaluation board. + +source "board/renesas/rzg2l/Kconfig" + +endchoice + config MULTI_DTB_FIT_UNCOMPRESS_SZ default 0x80000 if TARGET_RZG2L_SMARC_EVK
diff --git a/board/renesas/rzg2l/Kconfig b/board/renesas/rzg2l/Kconfig new file mode 100644 index 000000000000..1335fc7ae806 --- /dev/null +++ b/board/renesas/rzg2l/Kconfig @@ -0,0 +1,18 @@ +# Copyright (C) 2023 Renesas Electronics Corporation +# SPDX-License-Identifier: GPL-2.0+ + +if TARGET_RZG2L_SMARC_EVK + +config SYS_SOC + default "rmobile" + +config SYS_BOARD + default "rzg2l" + +config SYS_VENDOR + default "renesas" + +config SYS_CONFIG_NAME + default "rzg2l-smarc" + +endif diff --git a/board/renesas/rzg2l/MAINTAINERS b/board/renesas/rzg2l/MAINTAINERS new file mode 100644 index 000000000000..0a51391c1fc9 --- /dev/null +++ b/board/renesas/rzg2l/MAINTAINERS @@ -0,0 +1,6 @@ +RENESAS RZG2L BOARD FAMILY +M: Paul Barker paul.barker.ct@bp.renesas.com +S: Supported +F: arch/arm/dts/rz-smarc-common.dtsi +N: rzg2l +N: r9a07g044 diff --git a/board/renesas/rzg2l/Makefile b/board/renesas/rzg2l/Makefile new file mode 100644 index 000000000000..466935fc8158 --- /dev/null +++ b/board/renesas/rzg2l/Makefile @@ -0,0 +1,4 @@ +# Copyright (C) 2023 Renesas Electronics Corporation +# SPDX-License-Identifier: GPL-2.0+ + +obj-y := rzg2l.o diff --git a/board/renesas/rzg2l/rzg2l.c b/board/renesas/rzg2l/rzg2l.c new file mode 100644 index 000000000000..2b1bb3546c26 --- /dev/null +++ b/board/renesas/rzg2l/rzg2l.c @@ -0,0 +1,76 @@ +// SPDX-License-Identifier: GPL-2.0+ +/* + * RZ/G2L board support. + * Copyright (C) 2023 Renesas Electronics Corporation + */ + +#include <common.h> +#include <fdtdec.h> +#include <linux/libfdt.h> + +#if IS_ENABLED(CONFIG_MULTI_DTB_FIT) +/* If the firmware passed a device tree, use it for board identification. */ +extern u64 rcar_atf_boot_args[]; + +static bool is_rzg2l_board(const char *board_name) +{ + void *atf_fdt_blob = (void *)(rcar_atf_boot_args[1]); + + return fdt_node_check_compatible(atf_fdt_blob, 0, board_name) == 0; +} + +int board_fit_config_name_match(const char *name) +{ + void *atf_fdt_blob = (void *)(rcar_atf_boot_args[1]); + + if (fdt_magic(atf_fdt_blob) != FDT_MAGIC) + return -1; + + if (is_rzg2l_board("renesas,r9a07g044l2")) + return strcmp(name, "r9a07g044l2-smarc"); + + return -1; +} +#endif + +static void apply_atf_overlay(void *fdt_blob) +{ + void *atf_fdt_blob = (void *)(rcar_atf_boot_args[1]); + + if (fdt_magic(atf_fdt_blob) == FDT_MAGIC) + fdt_overlay_apply_node(fdt_blob, 0, atf_fdt_blob, 0); +} + +int fdtdec_board_setup(const void *fdt_blob) +{ + apply_atf_overlay((void *)fdt_blob); + + return 0; +} + +int ft_board_setup(void *blob, struct bd_info *bd) +{ + return 0; +} + +int __weak board_init(void) +{ + return 0; +} + +int dram_init(void) +{ + return fdtdec_setup_mem_size_base(); +} + +int dram_init_banksize(void) +{ + fdtdec_setup_memory_banksize(); + + return 0; +} + +void __weak reset_cpu(void) +{ + +} diff --git a/configs/renesas_rzg2l_smarc_defconfig b/configs/renesas_rzg2l_smarc_defconfig new file mode 100644 index 000000000000..e17d22695787 --- /dev/null +++ b/configs/renesas_rzg2l_smarc_defconfig @@ -0,0 +1,52 @@ +CONFIG_ARM=y +CONFIG_COUNTER_FREQUENCY=16666666 +CONFIG_SYS_INIT_SP_BSS_OFFSET=1048576 +CONFIG_ARCH_CPU_INIT=y +CONFIG_ARCH_RMOBILE=y +CONFIG_TEXT_BASE=0x50000000 +CONFIG_SYS_MALLOC_LEN=0x4000000 +CONFIG_SYS_MALLOC_F_LEN=0x80000 +CONFIG_ENV_SIZE=0x20000 +CONFIG_ENV_OFFSET=0xFFFE0000 +CONFIG_DM_GPIO=y +CONFIG_DEFAULT_DEVICE_TREE="r9a07g044l2-smarc" +CONFIG_RZG2L=y +CONFIG_SYS_MONITOR_LEN=1048576 +CONFIG_SYS_LOAD_ADDR=0x58000000 +CONFIG_REMAKE_ELF=y +CONFIG_FIT=y +CONFIG_SUPPORT_RAW_INITRD=y +CONFIG_USE_BOOTARGS=y +# CONFIG_BOARD_EARLY_INIT_F is not set +CONFIG_SYS_MALLOC_BOOTPARAMS=y +CONFIG_HUSH_PARSER=y +CONFIG_SYS_MAXARGS=64 +CONFIG_SYS_PBSIZE=2068 +CONFIG_CMD_CLK=y +CONFIG_CMD_GPIO=y +CONFIG_CMD_MMC=y +CONFIG_CMD_PART=y +CONFIG_CMD_EXT2=y +CONFIG_CMD_EXT4=y +CONFIG_CMD_EXT4_WRITE=y +CONFIG_CMD_FAT=y +CONFIG_CMD_FS_GENERIC=y +CONFIG_OF_CONTROL=y +CONFIG_MULTI_DTB_FIT_LZO=y +CONFIG_MULTI_DTB_FIT_USER_DEFINED_AREA=y +CONFIG_ENV_OVERWRITE=y +CONFIG_ENV_IS_IN_MMC=y +CONFIG_SYS_RELOC_GD_ENV_ADDR=y +CONFIG_SYS_MMC_ENV_PART=2 +CONFIG_VERSION_VARIABLE=y +CONFIG_REGMAP=y +CONFIG_CLK=y +CONFIG_CLK_RENESAS=y +# CONFIG_CLK_RCAR_GEN3 is not set +CONFIG_GPIO_HOG=y +CONFIG_MMC_IO_VOLTAGE=y +CONFIG_MMC_UHS_SUPPORT=y +CONFIG_MMC_HS400_SUPPORT=y +CONFIG_DM_REGULATOR=y +CONFIG_DM_REGULATOR_FIXED=y +CONFIG_DM_REGULATOR_GPIO=y diff --git a/include/configs/rzg2l-smarc.h b/include/configs/rzg2l-smarc.h new file mode 100644 index 000000000000..ea57d280cb8d --- /dev/null +++ b/include/configs/rzg2l-smarc.h @@ -0,0 +1,14 @@ +/* SPDX-License-Identifier: GPL-2.0+ */ +/* + * Copyright (C) 2023 Renesas Electronics Corporation + */ + +#ifndef __RENESAS_RZG2L_H +#define __RENESAS_RZG2L_H + +#include <asm/arch/rmobile.h> + +/* console */ +#define CFG_SYS_BAUDRATE_TABLE { 115200, 38400 } + +#endif /* __RENESAS_RZG2L_H */

On 9/20/23 14:42, Paul Barker wrote:
The Renesas RZ/G2L SMARC Evaluation Board Kit consists of the RZ/G2L System-on-Module (SOM) based on the R9A07G044L2 SoC, and a common SMARC carrier board.
The ARM TrustedFirmware code for the Renesas RZ/G2L SoC family passes a devicetree blob to the bootloader as an argument in the same was previous R-Car gen3/gen4 SoCs. This blob contains a compatible string which can be used to identify the particular SoC we are running on and this is used to select the appropriate device tree to load.
The configuration renesas_rzg2l_smarc_defconfig is added to support building for this target. In the future this defconfig will be extended to support other SoCs and evaluation boards from the RZ/G2L family.
Signed-off-by: Paul Barker paul.barker.ct@bp.renesas.com Reviewed-by: Biju Das biju.das.jz@bp.renesas.com Reviewed-by: Lad Prabhakar prabhakar.mahadev-lad.rj@bp.renesas.com
arch/arm/mach-rmobile/Kconfig.rzg2l | 14 +++++ board/renesas/rzg2l/Kconfig | 18 +++++++ board/renesas/rzg2l/MAINTAINERS | 6 +++ board/renesas/rzg2l/Makefile | 4 ++ board/renesas/rzg2l/rzg2l.c | 76 +++++++++++++++++++++++++++ configs/renesas_rzg2l_smarc_defconfig | 52 ++++++++++++++++++ include/configs/rzg2l-smarc.h | 14 +++++ 7 files changed, 184 insertions(+) create mode 100644 board/renesas/rzg2l/Kconfig create mode 100644 board/renesas/rzg2l/MAINTAINERS create mode 100644 board/renesas/rzg2l/Makefile create mode 100644 board/renesas/rzg2l/rzg2l.c create mode 100644 configs/renesas_rzg2l_smarc_defconfig create mode 100644 include/configs/rzg2l-smarc.h
diff --git a/arch/arm/mach-rmobile/Kconfig.rzg2l b/arch/arm/mach-rmobile/Kconfig.rzg2l index 7d268e8c366a..1fe49e323300 100644 --- a/arch/arm/mach-rmobile/Kconfig.rzg2l +++ b/arch/arm/mach-rmobile/Kconfig.rzg2l @@ -9,6 +9,20 @@ config R9A07G044L help Enable support for the R9A07G044L SoC used in the RZ/G2L.
+choice
- prompt "Renesas RZ/G2L Family Board selection"
- default TARGET_RZG2L_SMARC_EVK
+config TARGET_RZG2L_SMARC_EVK
- bool "Renesas RZ/G2L SMARC EVK"
- imply R9A07G044L
- help
Enable support for the RZ/G2L SMARC evaluation board.
+source "board/renesas/rzg2l/Kconfig"
+endchoice
- config MULTI_DTB_FIT_UNCOMPRESS_SZ default 0x80000 if TARGET_RZG2L_SMARC_EVK
diff --git a/board/renesas/rzg2l/Kconfig b/board/renesas/rzg2l/Kconfig new file mode 100644 index 000000000000..1335fc7ae806 --- /dev/null +++ b/board/renesas/rzg2l/Kconfig @@ -0,0 +1,18 @@ +# Copyright (C) 2023 Renesas Electronics Corporation +# SPDX-License-Identifier: GPL-2.0+
+if TARGET_RZG2L_SMARC_EVK
+config SYS_SOC
- default "rmobile"
+config SYS_BOARD
- default "rzg2l"
+config SYS_VENDOR
- default "renesas"
+config SYS_CONFIG_NAME
- default "rzg2l-smarc"
+endif diff --git a/board/renesas/rzg2l/MAINTAINERS b/board/renesas/rzg2l/MAINTAINERS new file mode 100644 index 000000000000..0a51391c1fc9 --- /dev/null +++ b/board/renesas/rzg2l/MAINTAINERS @@ -0,0 +1,6 @@ +RENESAS RZG2L BOARD FAMILY +M: Paul Barker paul.barker.ct@bp.renesas.com +S: Supported +F: arch/arm/dts/rz-smarc-common.dtsi
I suspect there should be more files here, right ? You likely want to be CCed on things like rzg2l clock, scif, and so on.
+N: rzg2l +N: r9a07g044 diff --git a/board/renesas/rzg2l/Makefile b/board/renesas/rzg2l/Makefile new file mode 100644 index 000000000000..466935fc8158 --- /dev/null +++ b/board/renesas/rzg2l/Makefile @@ -0,0 +1,4 @@ +# Copyright (C) 2023 Renesas Electronics Corporation +# SPDX-License-Identifier: GPL-2.0+
+obj-y := rzg2l.o
diff --git a/board/renesas/rzg2l/rzg2l.c b/board/renesas/rzg2l/rzg2l.c new file mode 100644 index 000000000000..2b1bb3546c26 --- /dev/null +++ b/board/renesas/rzg2l/rzg2l.c @@ -0,0 +1,76 @@ +// SPDX-License-Identifier: GPL-2.0+ +/*
- RZ/G2L board support.
- Copyright (C) 2023 Renesas Electronics Corporation
- */
+#include <common.h> +#include <fdtdec.h> +#include <linux/libfdt.h>
+#if IS_ENABLED(CONFIG_MULTI_DTB_FIT) +/* If the firmware passed a device tree, use it for board identification. */ +extern u64 rcar_atf_boot_args[];
+static bool is_rzg2l_board(const char *board_name) +{
- void *atf_fdt_blob = (void *)(rcar_atf_boot_args[1]);
- return fdt_node_check_compatible(atf_fdt_blob, 0, board_name) == 0;
+}
+int board_fit_config_name_match(const char *name) +{
- void *atf_fdt_blob = (void *)(rcar_atf_boot_args[1]);
- if (fdt_magic(atf_fdt_blob) != FDT_MAGIC)
return -1;
- if (is_rzg2l_board("renesas,r9a07g044l2"))
return strcmp(name, "r9a07g044l2-smarc");
- return -1;
+} +#endif
+static void apply_atf_overlay(void *fdt_blob) +{
- void *atf_fdt_blob = (void *)(rcar_atf_boot_args[1]);
- if (fdt_magic(atf_fdt_blob) == FDT_MAGIC)
fdt_overlay_apply_node(fdt_blob, 0, atf_fdt_blob, 0);
+}
+int fdtdec_board_setup(const void *fdt_blob) +{
- apply_atf_overlay((void *)fdt_blob);
- return 0;
+}
+int ft_board_setup(void *blob, struct bd_info *bd) +{
- return 0;
Are all these stub functions really needed or can they be removed (possibly also with removal of unnecessary config options) ?
+}
+int __weak board_init(void) +{
- return 0;
+}
+int dram_init(void) +{
- return fdtdec_setup_mem_size_base();
+}
+int dram_init_banksize(void) +{
- fdtdec_setup_memory_banksize();
This and the one function above can likely go into arch/mach-rmobile/
- return 0;
+}
+void __weak reset_cpu(void) +{
Is this platform missing a way to reset the system ? Please fix.
[...]

On 03/10/2023 14:36, Marek Vasut wrote:
On 9/20/23 14:42, Paul Barker wrote:
The Renesas RZ/G2L SMARC Evaluation Board Kit consists of the RZ/G2L System-on-Module (SOM) based on the R9A07G044L2 SoC, and a common SMARC carrier board.
The ARM TrustedFirmware code for the Renesas RZ/G2L SoC family passes a devicetree blob to the bootloader as an argument in the same was previous R-Car gen3/gen4 SoCs. This blob contains a compatible string which can be used to identify the particular SoC we are running on and this is used to select the appropriate device tree to load.
The configuration renesas_rzg2l_smarc_defconfig is added to support building for this target. In the future this defconfig will be extended to support other SoCs and evaluation boards from the RZ/G2L family.
Signed-off-by: Paul Barker paul.barker.ct@bp.renesas.com Reviewed-by: Biju Das biju.das.jz@bp.renesas.com Reviewed-by: Lad Prabhakar prabhakar.mahadev-lad.rj@bp.renesas.com
arch/arm/mach-rmobile/Kconfig.rzg2l | 14 +++++ board/renesas/rzg2l/Kconfig | 18 +++++++ board/renesas/rzg2l/MAINTAINERS | 6 +++ board/renesas/rzg2l/Makefile | 4 ++ board/renesas/rzg2l/rzg2l.c | 76 +++++++++++++++++++++++++++ configs/renesas_rzg2l_smarc_defconfig | 52 ++++++++++++++++++ include/configs/rzg2l-smarc.h | 14 +++++ 7 files changed, 184 insertions(+) create mode 100644 board/renesas/rzg2l/Kconfig create mode 100644 board/renesas/rzg2l/MAINTAINERS create mode 100644 board/renesas/rzg2l/Makefile create mode 100644 board/renesas/rzg2l/rzg2l.c create mode 100644 configs/renesas_rzg2l_smarc_defconfig create mode 100644 include/configs/rzg2l-smarc.h
diff --git a/arch/arm/mach-rmobile/Kconfig.rzg2l b/arch/arm/mach-rmobile/Kconfig.rzg2l index 7d268e8c366a..1fe49e323300 100644 --- a/arch/arm/mach-rmobile/Kconfig.rzg2l +++ b/arch/arm/mach-rmobile/Kconfig.rzg2l @@ -9,6 +9,20 @@ config R9A07G044L help Enable support for the R9A07G044L SoC used in the RZ/G2L.
+choice
- prompt "Renesas RZ/G2L Family Board selection"
- default TARGET_RZG2L_SMARC_EVK
+config TARGET_RZG2L_SMARC_EVK
- bool "Renesas RZ/G2L SMARC EVK"
- imply R9A07G044L
- help
Enable support for the RZ/G2L SMARC evaluation board.
+source "board/renesas/rzg2l/Kconfig"
+endchoice
- config MULTI_DTB_FIT_UNCOMPRESS_SZ default 0x80000 if TARGET_RZG2L_SMARC_EVK
diff --git a/board/renesas/rzg2l/Kconfig b/board/renesas/rzg2l/Kconfig new file mode 100644 index 000000000000..1335fc7ae806 --- /dev/null +++ b/board/renesas/rzg2l/Kconfig @@ -0,0 +1,18 @@ +# Copyright (C) 2023 Renesas Electronics Corporation +# SPDX-License-Identifier: GPL-2.0+
+if TARGET_RZG2L_SMARC_EVK
+config SYS_SOC
- default "rmobile"
+config SYS_BOARD
- default "rzg2l"
+config SYS_VENDOR
- default "renesas"
+config SYS_CONFIG_NAME
- default "rzg2l-smarc"
+endif diff --git a/board/renesas/rzg2l/MAINTAINERS b/board/renesas/rzg2l/MAINTAINERS new file mode 100644 index 000000000000..0a51391c1fc9 --- /dev/null +++ b/board/renesas/rzg2l/MAINTAINERS @@ -0,0 +1,6 @@ +RENESAS RZG2L BOARD FAMILY +M: Paul Barker paul.barker.ct@bp.renesas.com +S: Supported +F: arch/arm/dts/rz-smarc-common.dtsi
I suspect there should be more files here, right ? You likely want to be CCed on things like rzg2l clock, scif, and so on.
The `N:` lines after this are regexps. Checking these after applying this patch gives the expected behaviour, e.g.
./scripts/get_maintainer.pl drivers/clk/renesas/rzg2l-cpg.c Nobuhiro Iwamatsu iwamatsu@nigauri.org (maintainer:ARM RENESAS RMOBILE/R-CAR) Marek Vasut marek.vasut+renesas@mailbox.org (maintainer:ARM RENESAS RMOBILE/R-CAR) Lukasz Majewski lukma@denx.de (maintainer:CLOCK) Sean Anderson seanga2@gmail.com (maintainer:CLOCK) Paul Barker paul.barker.ct@bp.renesas.com (supporter:RENESAS RZG2L BOARD FAMILY) u-boot@lists.denx.de (open list)
+N: rzg2l +N: r9a07g044 diff --git a/board/renesas/rzg2l/Makefile b/board/renesas/rzg2l/Makefile new file mode 100644 index 000000000000..466935fc8158 --- /dev/null +++ b/board/renesas/rzg2l/Makefile @@ -0,0 +1,4 @@ +# Copyright (C) 2023 Renesas Electronics Corporation +# SPDX-License-Identifier: GPL-2.0+
+obj-y := rzg2l.o
diff --git a/board/renesas/rzg2l/rzg2l.c b/board/renesas/rzg2l/rzg2l.c new file mode 100644 index 000000000000..2b1bb3546c26 --- /dev/null +++ b/board/renesas/rzg2l/rzg2l.c @@ -0,0 +1,76 @@ +// SPDX-License-Identifier: GPL-2.0+ +/*
- RZ/G2L board support.
- Copyright (C) 2023 Renesas Electronics Corporation
- */
+#include <common.h> +#include <fdtdec.h> +#include <linux/libfdt.h>
+#if IS_ENABLED(CONFIG_MULTI_DTB_FIT) +/* If the firmware passed a device tree, use it for board identification. */ +extern u64 rcar_atf_boot_args[];
+static bool is_rzg2l_board(const char *board_name) +{
- void *atf_fdt_blob = (void *)(rcar_atf_boot_args[1]);
- return fdt_node_check_compatible(atf_fdt_blob, 0, board_name) == 0;
+}
+int board_fit_config_name_match(const char *name) +{
- void *atf_fdt_blob = (void *)(rcar_atf_boot_args[1]);
- if (fdt_magic(atf_fdt_blob) != FDT_MAGIC)
return -1;
- if (is_rzg2l_board("renesas,r9a07g044l2"))
return strcmp(name, "r9a07g044l2-smarc");
- return -1;
+} +#endif
+static void apply_atf_overlay(void *fdt_blob) +{
- void *atf_fdt_blob = (void *)(rcar_atf_boot_args[1]);
- if (fdt_magic(atf_fdt_blob) == FDT_MAGIC)
fdt_overlay_apply_node(fdt_blob, 0, atf_fdt_blob, 0);
+}
+int fdtdec_board_setup(const void *fdt_blob) +{
- apply_atf_overlay((void *)fdt_blob);
- return 0;
+}
+int ft_board_setup(void *blob, struct bd_info *bd) +{
- return 0;
Are all these stub functions really needed or can they be removed (possibly also with removal of unnecessary config options) ?
ft_board_setup() could possibly be dropped - I had a line in here to call apply_atf_overlay() but dropped it as further work is needed in TrustedFirmware first.
The empty board_init() function is the same as in board/renesas/rcar-common/common.c.
+}
+int __weak board_init(void) +{
- return 0;
+}
+int dram_init(void) +{
- return fdtdec_setup_mem_size_base();
+}
+int dram_init_banksize(void) +{
- fdtdec_setup_memory_banksize();
This and the one function above can likely go into arch/mach-rmobile/
We're not able to test every supported mach-rmobile board so we've preferred to keep changes to RZ/G2L specific code where possible. I'm happy to merge this into mach-rmobile (along with the similar code in board/renesas/rcar-common/common.c), but it will only be tested on the boards we have in our team.
- return 0;
+}
+void __weak reset_cpu(void) +{
Is this platform missing a way to reset the system ? Please fix.
Adding reset support is on my todo list. I'm prioritising Ethernet support above this right now, but we don't mind too much what order we do things. Let me know if you'd prefer us to prioritise reset support.
Thanks, Paul

On 10/4/23 11:36, Paul Barker wrote:
[...]
+int dram_init(void) +{
- return fdtdec_setup_mem_size_base();
+}
+int dram_init_banksize(void) +{
- fdtdec_setup_memory_banksize();
This and the one function above can likely go into arch/mach-rmobile/
We're not able to test every supported mach-rmobile board so we've preferred to keep changes to RZ/G2L specific code where possible. I'm happy to merge this into mach-rmobile (along with the similar code in board/renesas/rcar-common/common.c), but it will only be tested on the boards we have in our team.
Don't you already have a G2L specific file in arch/arm/mach-rmobile/ ?
(I can test whatever changes on R-Car if needed)
- return 0;
+}
+void __weak reset_cpu(void) +{
Is this platform missing a way to reset the system ? Please fix.
Adding reset support is on my todo list. I'm prioritising Ethernet support above this right now, but we don't mind too much what order we do things. Let me know if you'd prefer us to prioritise reset support.
Isn't the reset like really really simple ? Enable SYSRESET config option and do TFA/SMC reset I guess ?

On Wed, Oct 04, 2023 at 02:33:07PM +0200, Marek Vasut wrote:
On 10/4/23 11:36, Paul Barker wrote:
[...]
+int dram_init(void) +{
- return fdtdec_setup_mem_size_base();
+}
+int dram_init_banksize(void) +{
- fdtdec_setup_memory_banksize();
This and the one function above can likely go into arch/mach-rmobile/
We're not able to test every supported mach-rmobile board so we've preferred to keep changes to RZ/G2L specific code where possible. I'm happy to merge this into mach-rmobile (along with the similar code in board/renesas/rcar-common/common.c), but it will only be tested on the boards we have in our team.
Don't you already have a G2L specific file in arch/arm/mach-rmobile/ ?
(I can test whatever changes on R-Car if needed)
We could move these into arch/arm/mach-rmobile/memmap-rzg2l.c I guess.
- return 0;
+}
+void __weak reset_cpu(void) +{
Is this platform missing a way to reset the system ? Please fix.
Adding reset support is on my todo list. I'm prioritising Ethernet support above this right now, but we don't mind too much what order we do things. Let me know if you'd prefer us to prioritise reset support.
Isn't the reset like really really simple ? Enable SYSRESET config option and do TFA/SMC reset I guess ?
We don't have support for that in TF-A yet.
Thanks, Paul

On 10/4/23 15:56, Paul Barker wrote:
On Wed, Oct 04, 2023 at 02:33:07PM +0200, Marek Vasut wrote:
On 10/4/23 11:36, Paul Barker wrote:
[...]
+int dram_init(void) +{
- return fdtdec_setup_mem_size_base();
+}
+int dram_init_banksize(void) +{
- fdtdec_setup_memory_banksize();
This and the one function above can likely go into arch/mach-rmobile/
We're not able to test every supported mach-rmobile board so we've preferred to keep changes to RZ/G2L specific code where possible. I'm happy to merge this into mach-rmobile (along with the similar code in board/renesas/rcar-common/common.c), but it will only be tested on the boards we have in our team.
Don't you already have a G2L specific file in arch/arm/mach-rmobile/ ?
(I can test whatever changes on R-Car if needed)
We could move these into arch/arm/mach-rmobile/memmap-rzg2l.c I guess.
Yep, the memmap*c files are by now a total misnomer.
- return 0;
+}
+void __weak reset_cpu(void) +{
Is this platform missing a way to reset the system ? Please fix.
Adding reset support is on my todo list. I'm prioritising Ethernet support above this right now, but we don't mind too much what order we do things. Let me know if you'd prefer us to prioritise reset support.
Isn't the reset like really really simple ? Enable SYSRESET config option and do TFA/SMC reset I guess ?
We don't have support for that in TF-A yet.
Hmmm, can you whack the reset controller register maybe ? Or is the reset triggered by some PMIC I2C register write ?
There are examples of both in board/renesas/

On 03/10/2023 14:36, Marek Vasut wrote:
On 9/20/23 14:42, Paul Barker wrote:
The Renesas RZ/G2L SMARC Evaluation Board Kit consists of the RZ/G2L System-on-Module (SOM) based on the R9A07G044L2 SoC, and a common SMARC carrier board.
The ARM TrustedFirmware code for the Renesas RZ/G2L SoC family passes a devicetree blob to the bootloader as an argument in the same was previous R-Car gen3/gen4 SoCs. This blob contains a compatible string which can be used to identify the particular SoC we are running on and this is used to select the appropriate device tree to load.
The configuration renesas_rzg2l_smarc_defconfig is added to support building for this target. In the future this defconfig will be extended to support other SoCs and evaluation boards from the RZ/G2L family.
Signed-off-by: Paul Barker paul.barker.ct@bp.renesas.com Reviewed-by: Biju Das biju.das.jz@bp.renesas.com Reviewed-by: Lad Prabhakar prabhakar.mahadev-lad.rj@bp.renesas.com
arch/arm/mach-rmobile/Kconfig.rzg2l | 14 +++++ board/renesas/rzg2l/Kconfig | 18 +++++++ board/renesas/rzg2l/MAINTAINERS | 6 +++ board/renesas/rzg2l/Makefile | 4 ++ board/renesas/rzg2l/rzg2l.c | 76 +++++++++++++++++++++++++++ configs/renesas_rzg2l_smarc_defconfig | 52 ++++++++++++++++++ include/configs/rzg2l-smarc.h | 14 +++++ 7 files changed, 184 insertions(+) create mode 100644 board/renesas/rzg2l/Kconfig create mode 100644 board/renesas/rzg2l/MAINTAINERS create mode 100644 board/renesas/rzg2l/Makefile create mode 100644 board/renesas/rzg2l/rzg2l.c create mode 100644 configs/renesas_rzg2l_smarc_defconfig create mode 100644 include/configs/rzg2l-smarc.h
diff --git a/arch/arm/mach-rmobile/Kconfig.rzg2l b/arch/arm/mach-rmobile/Kconfig.rzg2l index 7d268e8c366a..1fe49e323300 100644 --- a/arch/arm/mach-rmobile/Kconfig.rzg2l +++ b/arch/arm/mach-rmobile/Kconfig.rzg2l @@ -9,6 +9,20 @@ config R9A07G044L help Enable support for the R9A07G044L SoC used in the RZ/G2L.
+choice
- prompt "Renesas RZ/G2L Family Board selection"
- default TARGET_RZG2L_SMARC_EVK
+config TARGET_RZG2L_SMARC_EVK
- bool "Renesas RZ/G2L SMARC EVK"
- imply R9A07G044L
- help
Enable support for the RZ/G2L SMARC evaluation board.
+source "board/renesas/rzg2l/Kconfig"
+endchoice
- config MULTI_DTB_FIT_UNCOMPRESS_SZ default 0x80000 if TARGET_RZG2L_SMARC_EVK
diff --git a/board/renesas/rzg2l/Kconfig b/board/renesas/rzg2l/Kconfig new file mode 100644 index 000000000000..1335fc7ae806 --- /dev/null +++ b/board/renesas/rzg2l/Kconfig @@ -0,0 +1,18 @@ +# Copyright (C) 2023 Renesas Electronics Corporation +# SPDX-License-Identifier: GPL-2.0+
+if TARGET_RZG2L_SMARC_EVK
+config SYS_SOC
- default "rmobile"
+config SYS_BOARD
- default "rzg2l"
+config SYS_VENDOR
- default "renesas"
+config SYS_CONFIG_NAME
- default "rzg2l-smarc"
+endif diff --git a/board/renesas/rzg2l/MAINTAINERS b/board/renesas/rzg2l/MAINTAINERS new file mode 100644 index 000000000000..0a51391c1fc9 --- /dev/null +++ b/board/renesas/rzg2l/MAINTAINERS @@ -0,0 +1,6 @@ +RENESAS RZG2L BOARD FAMILY +M: Paul Barker paul.barker.ct@bp.renesas.com +S: Supported +F: arch/arm/dts/rz-smarc-common.dtsi
I suspect there should be more files here, right ? You likely want to be CCed on things like rzg2l clock, scif, and so on.
+N: rzg2l +N: r9a07g044 diff --git a/board/renesas/rzg2l/Makefile b/board/renesas/rzg2l/Makefile new file mode 100644 index 000000000000..466935fc8158 --- /dev/null +++ b/board/renesas/rzg2l/Makefile @@ -0,0 +1,4 @@ +# Copyright (C) 2023 Renesas Electronics Corporation +# SPDX-License-Identifier: GPL-2.0+
+obj-y := rzg2l.o
diff --git a/board/renesas/rzg2l/rzg2l.c b/board/renesas/rzg2l/rzg2l.c new file mode 100644 index 000000000000..2b1bb3546c26 --- /dev/null +++ b/board/renesas/rzg2l/rzg2l.c @@ -0,0 +1,76 @@ +// SPDX-License-Identifier: GPL-2.0+ +/*
- RZ/G2L board support.
- Copyright (C) 2023 Renesas Electronics Corporation
- */
+#include <common.h> +#include <fdtdec.h> +#include <linux/libfdt.h>
+#if IS_ENABLED(CONFIG_MULTI_DTB_FIT) +/* If the firmware passed a device tree, use it for board identification. */ +extern u64 rcar_atf_boot_args[];
+static bool is_rzg2l_board(const char *board_name) +{
- void *atf_fdt_blob = (void *)(rcar_atf_boot_args[1]);
- return fdt_node_check_compatible(atf_fdt_blob, 0, board_name) == 0;
+}
+int board_fit_config_name_match(const char *name) +{
- void *atf_fdt_blob = (void *)(rcar_atf_boot_args[1]);
- if (fdt_magic(atf_fdt_blob) != FDT_MAGIC)
return -1;
- if (is_rzg2l_board("renesas,r9a07g044l2"))
return strcmp(name, "r9a07g044l2-smarc");
- return -1;
+} +#endif
+static void apply_atf_overlay(void *fdt_blob) +{
- void *atf_fdt_blob = (void *)(rcar_atf_boot_args[1]);
- if (fdt_magic(atf_fdt_blob) == FDT_MAGIC)
fdt_overlay_apply_node(fdt_blob, 0, atf_fdt_blob, 0);
+}
+int fdtdec_board_setup(const void *fdt_blob) +{
- apply_atf_overlay((void *)fdt_blob);
- return 0;
+}
+int ft_board_setup(void *blob, struct bd_info *bd) +{
- return 0;
Are all these stub functions really needed or can they be removed (possibly also with removal of unnecessary config options) ?
I've moved dram_init() & dram_init_banksize() out to arch/arm/mach-rmobile/memmap-rzg2l.c. However, the other three stub functions can't easily be removed:
* board_init() is always called if CONFIG_ARM is enabled. There is a similar stub in board/renesas/rcar-common/common.c so I think this is ok.
* ft_board_setup() is called if CONFIG_OF_BOARD_SETUP is enabled, which is selected by CONFIG_RCAR_64, I don't see much point messing around to break that config dependency when I'm going to be coming back to fill in this stub once support for these boards is fully upstreamed to TrustedFirmware.
* reset_cpu() is called from arch/arm/lib/reset.c, which is included unless CONFIG_SYSRESET is defined, and I don't think enabling CONFIG_SYSRESET makes any sense here. Again, I'll be filling in this stub once TrustedFirmware supports resetting this board.
I'll chat to the rest of the team tomorrow and see if there's a hacky way we can do the reset before TrustedFirmware support is complete.
Thanks, Paul

Hi Paul,
Subject: Re: [PATCH 16/16] board: rzg2l: Add RZ/G2L SMARC EVK board
On 03/10/2023 14:36, Marek Vasut wrote:
On 9/20/23 14:42, Paul Barker wrote:
The Renesas RZ/G2L SMARC Evaluation Board Kit consists of the RZ/G2L System-on-Module (SOM) based on the R9A07G044L2 SoC, and a common SMARC carrier board.
The ARM TrustedFirmware code for the Renesas RZ/G2L SoC family passes a devicetree blob to the bootloader as an argument in the same was previous R-Car gen3/gen4 SoCs. This blob contains a compatible string which can be used to identify the particular SoC we are running on and this is used to select the appropriate device tree to load.
The configuration renesas_rzg2l_smarc_defconfig is added to support building for this target. In the future this defconfig will be extended to support other SoCs and evaluation boards from the RZ/G2L
family.
Signed-off-by: Paul Barker paul.barker.ct@bp.renesas.com Reviewed-by: Biju Das biju.das.jz@bp.renesas.com Reviewed-by: Lad Prabhakar prabhakar.mahadev-lad.rj@bp.renesas.com
arch/arm/mach-rmobile/Kconfig.rzg2l | 14 +++++ board/renesas/rzg2l/Kconfig | 18 +++++++ board/renesas/rzg2l/MAINTAINERS | 6 +++ board/renesas/rzg2l/Makefile | 4 ++ board/renesas/rzg2l/rzg2l.c | 76 +++++++++++++++++++++++++++ configs/renesas_rzg2l_smarc_defconfig | 52 ++++++++++++++++++ include/configs/rzg2l-smarc.h | 14 +++++ 7 files changed, 184 insertions(+) create mode 100644 board/renesas/rzg2l/Kconfig create mode 100644 board/renesas/rzg2l/MAINTAINERS create mode 100644 board/renesas/rzg2l/Makefile create mode 100644 board/renesas/rzg2l/rzg2l.c create mode 100644 configs/renesas_rzg2l_smarc_defconfig create mode 100644 include/configs/rzg2l-smarc.h
diff --git a/arch/arm/mach-rmobile/Kconfig.rzg2l b/arch/arm/mach-rmobile/Kconfig.rzg2l index 7d268e8c366a..1fe49e323300 100644 --- a/arch/arm/mach-rmobile/Kconfig.rzg2l +++ b/arch/arm/mach-rmobile/Kconfig.rzg2l @@ -9,6 +9,20 @@ config R9A07G044L help Enable support for the R9A07G044L SoC used in the RZ/G2L.
+choice
- prompt "Renesas RZ/G2L Family Board selection"
- default TARGET_RZG2L_SMARC_EVK
+config TARGET_RZG2L_SMARC_EVK
- bool "Renesas RZ/G2L SMARC EVK"
- imply R9A07G044L
- help
Enable support for the RZ/G2L SMARC evaluation board.
+source "board/renesas/rzg2l/Kconfig"
+endchoice
- config MULTI_DTB_FIT_UNCOMPRESS_SZ default 0x80000 if TARGET_RZG2L_SMARC_EVK
diff --git a/board/renesas/rzg2l/Kconfig b/board/renesas/rzg2l/Kconfig new file mode 100644 index 000000000000..1335fc7ae806 --- /dev/null +++ b/board/renesas/rzg2l/Kconfig @@ -0,0 +1,18 @@ +# Copyright (C) 2023 Renesas Electronics Corporation # +SPDX-License-Identifier: GPL-2.0+
+if TARGET_RZG2L_SMARC_EVK
+config SYS_SOC
- default "rmobile"
+config SYS_BOARD
- default "rzg2l"
+config SYS_VENDOR
- default "renesas"
+config SYS_CONFIG_NAME
- default "rzg2l-smarc"
+endif diff --git a/board/renesas/rzg2l/MAINTAINERS b/board/renesas/rzg2l/MAINTAINERS new file mode 100644 index 000000000000..0a51391c1fc9 --- /dev/null +++ b/board/renesas/rzg2l/MAINTAINERS @@ -0,0 +1,6 @@ +RENESAS RZG2L BOARD FAMILY +M: Paul Barker paul.barker.ct@bp.renesas.com +S: Supported +F: arch/arm/dts/rz-smarc-common.dtsi
I suspect there should be more files here, right ? You likely want to be CCed on things like rzg2l clock, scif, and so on.
+N: rzg2l +N: r9a07g044 diff --git a/board/renesas/rzg2l/Makefile b/board/renesas/rzg2l/Makefile new file mode 100644 index 000000000000..466935fc8158 --- /dev/null +++ b/board/renesas/rzg2l/Makefile @@ -0,0 +1,4 @@ +# Copyright (C) 2023 Renesas Electronics Corporation # +SPDX-License-Identifier: GPL-2.0+
+obj-y := rzg2l.o
diff --git a/board/renesas/rzg2l/rzg2l.c b/board/renesas/rzg2l/rzg2l.c new file mode 100644 index 000000000000..2b1bb3546c26 --- /dev/null +++ b/board/renesas/rzg2l/rzg2l.c @@ -0,0 +1,76 @@ +// SPDX-License-Identifier: GPL-2.0+ +/*
- RZ/G2L board support.
- Copyright (C) 2023 Renesas Electronics Corporation */
+#include <common.h> +#include <fdtdec.h> +#include <linux/libfdt.h>
+#if IS_ENABLED(CONFIG_MULTI_DTB_FIT) +/* If the firmware passed a device tree, use it for board +identification. */ extern u64 rcar_atf_boot_args[];
+static bool is_rzg2l_board(const char *board_name) {
- void *atf_fdt_blob = (void *)(rcar_atf_boot_args[1]);
- return fdt_node_check_compatible(atf_fdt_blob, 0, board_name) == 0;
+}
+int board_fit_config_name_match(const char *name) {
- void *atf_fdt_blob = (void *)(rcar_atf_boot_args[1]);
- if (fdt_magic(atf_fdt_blob) != FDT_MAGIC)
return -1;
- if (is_rzg2l_board("renesas,r9a07g044l2"))
return strcmp(name, "r9a07g044l2-smarc");
- return -1;
+} +#endif
+static void apply_atf_overlay(void *fdt_blob) {
- void *atf_fdt_blob = (void *)(rcar_atf_boot_args[1]);
- if (fdt_magic(atf_fdt_blob) == FDT_MAGIC)
fdt_overlay_apply_node(fdt_blob, 0, atf_fdt_blob, 0); }
+int fdtdec_board_setup(const void *fdt_blob) {
- apply_atf_overlay((void *)fdt_blob);
- return 0;
+}
+int ft_board_setup(void *blob, struct bd_info *bd) {
- return 0;
Are all these stub functions really needed or can they be removed (possibly also with removal of unnecessary config options) ?
I've moved dram_init() & dram_init_banksize() out to arch/arm/mach- rmobile/memmap-rzg2l.c. However, the other three stub functions can't easily be removed:
board_init() is always called if CONFIG_ARM is enabled. There is a similar stub in board/renesas/rcar-common/common.c so I think this is ok.
ft_board_setup() is called if CONFIG_OF_BOARD_SETUP is enabled, which is selected by CONFIG_RCAR_64, I don't see much point messing around to break that config dependency when I'm going to be coming back to fill in this stub once support for these boards is fully upstreamed to TrustedFirmware.
reset_cpu() is called from arch/arm/lib/reset.c, which is included unless CONFIG_SYSRESET is defined, and I don't think enabling CONFIG_SYSRESET makes any sense here. Again, I'll be filling in this stub once TrustedFirmware supports resetting this board.
I'll chat to the rest of the team tomorrow and see if there's a hacky way we can do the reset before TrustedFirmware support is complete.
If you need reset other than TF-A, either you can implement
1) watchdog reset
Or
2) System reset through PMIC
Former requires watchdog driver support where as later requires I2C support.
I will go with 2) as with 2 one can distinguish Normal reset from abnormal reset due to watchdog.
Cheers, Biju

On 10/6/23 14:51, Biju Das wrote:
Hi Paul,
Subject: Re: [PATCH 16/16] board: rzg2l: Add RZ/G2L SMARC EVK board
On 03/10/2023 14:36, Marek Vasut wrote:
On 9/20/23 14:42, Paul Barker wrote:
The Renesas RZ/G2L SMARC Evaluation Board Kit consists of the RZ/G2L System-on-Module (SOM) based on the R9A07G044L2 SoC, and a common SMARC carrier board.
The ARM TrustedFirmware code for the Renesas RZ/G2L SoC family passes a devicetree blob to the bootloader as an argument in the same was previous R-Car gen3/gen4 SoCs. This blob contains a compatible string which can be used to identify the particular SoC we are running on and this is used to select the appropriate device tree to load.
The configuration renesas_rzg2l_smarc_defconfig is added to support building for this target. In the future this defconfig will be extended to support other SoCs and evaluation boards from the RZ/G2L
family.
Signed-off-by: Paul Barker paul.barker.ct@bp.renesas.com Reviewed-by: Biju Das biju.das.jz@bp.renesas.com Reviewed-by: Lad Prabhakar prabhakar.mahadev-lad.rj@bp.renesas.com
arch/arm/mach-rmobile/Kconfig.rzg2l | 14 +++++ board/renesas/rzg2l/Kconfig | 18 +++++++ board/renesas/rzg2l/MAINTAINERS | 6 +++ board/renesas/rzg2l/Makefile | 4 ++ board/renesas/rzg2l/rzg2l.c | 76 +++++++++++++++++++++++++++ configs/renesas_rzg2l_smarc_defconfig | 52 ++++++++++++++++++ include/configs/rzg2l-smarc.h | 14 +++++ 7 files changed, 184 insertions(+) create mode 100644 board/renesas/rzg2l/Kconfig create mode 100644 board/renesas/rzg2l/MAINTAINERS create mode 100644 board/renesas/rzg2l/Makefile create mode 100644 board/renesas/rzg2l/rzg2l.c create mode 100644 configs/renesas_rzg2l_smarc_defconfig create mode 100644 include/configs/rzg2l-smarc.h
diff --git a/arch/arm/mach-rmobile/Kconfig.rzg2l b/arch/arm/mach-rmobile/Kconfig.rzg2l index 7d268e8c366a..1fe49e323300 100644 --- a/arch/arm/mach-rmobile/Kconfig.rzg2l +++ b/arch/arm/mach-rmobile/Kconfig.rzg2l @@ -9,6 +9,20 @@ config R9A07G044L help Enable support for the R9A07G044L SoC used in the RZ/G2L.
+choice
- prompt "Renesas RZ/G2L Family Board selection"
- default TARGET_RZG2L_SMARC_EVK
+config TARGET_RZG2L_SMARC_EVK
- bool "Renesas RZ/G2L SMARC EVK"
- imply R9A07G044L
- help
Enable support for the RZ/G2L SMARC evaluation board.
+source "board/renesas/rzg2l/Kconfig"
+endchoice
- config MULTI_DTB_FIT_UNCOMPRESS_SZ default 0x80000 if TARGET_RZG2L_SMARC_EVK
diff --git a/board/renesas/rzg2l/Kconfig b/board/renesas/rzg2l/Kconfig new file mode 100644 index 000000000000..1335fc7ae806 --- /dev/null +++ b/board/renesas/rzg2l/Kconfig @@ -0,0 +1,18 @@ +# Copyright (C) 2023 Renesas Electronics Corporation # +SPDX-License-Identifier: GPL-2.0+
+if TARGET_RZG2L_SMARC_EVK
+config SYS_SOC
- default "rmobile"
+config SYS_BOARD
- default "rzg2l"
+config SYS_VENDOR
- default "renesas"
+config SYS_CONFIG_NAME
- default "rzg2l-smarc"
+endif diff --git a/board/renesas/rzg2l/MAINTAINERS b/board/renesas/rzg2l/MAINTAINERS new file mode 100644 index 000000000000..0a51391c1fc9 --- /dev/null +++ b/board/renesas/rzg2l/MAINTAINERS @@ -0,0 +1,6 @@ +RENESAS RZG2L BOARD FAMILY +M: Paul Barker paul.barker.ct@bp.renesas.com +S: Supported +F: arch/arm/dts/rz-smarc-common.dtsi
I suspect there should be more files here, right ? You likely want to be CCed on things like rzg2l clock, scif, and so on.
+N: rzg2l +N: r9a07g044 diff --git a/board/renesas/rzg2l/Makefile b/board/renesas/rzg2l/Makefile new file mode 100644 index 000000000000..466935fc8158 --- /dev/null +++ b/board/renesas/rzg2l/Makefile @@ -0,0 +1,4 @@ +# Copyright (C) 2023 Renesas Electronics Corporation # +SPDX-License-Identifier: GPL-2.0+
+obj-y := rzg2l.o
diff --git a/board/renesas/rzg2l/rzg2l.c b/board/renesas/rzg2l/rzg2l.c new file mode 100644 index 000000000000..2b1bb3546c26 --- /dev/null +++ b/board/renesas/rzg2l/rzg2l.c @@ -0,0 +1,76 @@ +// SPDX-License-Identifier: GPL-2.0+ +/*
- RZ/G2L board support.
- Copyright (C) 2023 Renesas Electronics Corporation */
+#include <common.h> +#include <fdtdec.h> +#include <linux/libfdt.h>
+#if IS_ENABLED(CONFIG_MULTI_DTB_FIT) +/* If the firmware passed a device tree, use it for board +identification. */ extern u64 rcar_atf_boot_args[];
+static bool is_rzg2l_board(const char *board_name) {
- void *atf_fdt_blob = (void *)(rcar_atf_boot_args[1]);
- return fdt_node_check_compatible(atf_fdt_blob, 0, board_name) == 0;
+}
+int board_fit_config_name_match(const char *name) {
- void *atf_fdt_blob = (void *)(rcar_atf_boot_args[1]);
- if (fdt_magic(atf_fdt_blob) != FDT_MAGIC)
return -1;
- if (is_rzg2l_board("renesas,r9a07g044l2"))
return strcmp(name, "r9a07g044l2-smarc");
- return -1;
+} +#endif
+static void apply_atf_overlay(void *fdt_blob) {
- void *atf_fdt_blob = (void *)(rcar_atf_boot_args[1]);
- if (fdt_magic(atf_fdt_blob) == FDT_MAGIC)
fdt_overlay_apply_node(fdt_blob, 0, atf_fdt_blob, 0); }
+int fdtdec_board_setup(const void *fdt_blob) {
- apply_atf_overlay((void *)fdt_blob);
- return 0;
+}
+int ft_board_setup(void *blob, struct bd_info *bd) {
- return 0;
Are all these stub functions really needed or can they be removed (possibly also with removal of unnecessary config options) ?
I've moved dram_init() & dram_init_banksize() out to arch/arm/mach- rmobile/memmap-rzg2l.c. However, the other three stub functions can't easily be removed:
board_init() is always called if CONFIG_ARM is enabled. There is a similar stub in board/renesas/rcar-common/common.c so I think this is ok.
ft_board_setup() is called if CONFIG_OF_BOARD_SETUP is enabled, which is selected by CONFIG_RCAR_64, I don't see much point messing around to break that config dependency when I'm going to be coming back to fill in this stub once support for these boards is fully upstreamed to TrustedFirmware.
reset_cpu() is called from arch/arm/lib/reset.c, which is included unless CONFIG_SYSRESET is defined, and I don't think enabling CONFIG_SYSRESET makes any sense here. Again, I'll be filling in this stub once TrustedFirmware supports resetting this board.
I'll chat to the rest of the team tomorrow and see if there's a hacky way we can do the reset before TrustedFirmware support is complete.
If you need reset other than TF-A, either you can implement
- watchdog reset
Or
- System reset through PMIC
Former requires watchdog driver support where as later requires I2C support.
I will go with 2) as with 2 one can distinguish Normal reset from abnormal reset due to watchdog.
Let's add a ToDo comment for now, just to be clear this is being worked on.

On 10/5/23 22:50, Paul Barker wrote:
On 03/10/2023 14:36, Marek Vasut wrote:
On 9/20/23 14:42, Paul Barker wrote:
The Renesas RZ/G2L SMARC Evaluation Board Kit consists of the RZ/G2L System-on-Module (SOM) based on the R9A07G044L2 SoC, and a common SMARC carrier board.
The ARM TrustedFirmware code for the Renesas RZ/G2L SoC family passes a devicetree blob to the bootloader as an argument in the same was previous R-Car gen3/gen4 SoCs. This blob contains a compatible string which can be used to identify the particular SoC we are running on and this is used to select the appropriate device tree to load.
The configuration renesas_rzg2l_smarc_defconfig is added to support building for this target. In the future this defconfig will be extended to support other SoCs and evaluation boards from the RZ/G2L family.
Signed-off-by: Paul Barker paul.barker.ct@bp.renesas.com Reviewed-by: Biju Das biju.das.jz@bp.renesas.com Reviewed-by: Lad Prabhakar prabhakar.mahadev-lad.rj@bp.renesas.com
arch/arm/mach-rmobile/Kconfig.rzg2l | 14 +++++ board/renesas/rzg2l/Kconfig | 18 +++++++ board/renesas/rzg2l/MAINTAINERS | 6 +++ board/renesas/rzg2l/Makefile | 4 ++ board/renesas/rzg2l/rzg2l.c | 76 +++++++++++++++++++++++++++ configs/renesas_rzg2l_smarc_defconfig | 52 ++++++++++++++++++ include/configs/rzg2l-smarc.h | 14 +++++ 7 files changed, 184 insertions(+) create mode 100644 board/renesas/rzg2l/Kconfig create mode 100644 board/renesas/rzg2l/MAINTAINERS create mode 100644 board/renesas/rzg2l/Makefile create mode 100644 board/renesas/rzg2l/rzg2l.c create mode 100644 configs/renesas_rzg2l_smarc_defconfig create mode 100644 include/configs/rzg2l-smarc.h
diff --git a/arch/arm/mach-rmobile/Kconfig.rzg2l b/arch/arm/mach-rmobile/Kconfig.rzg2l index 7d268e8c366a..1fe49e323300 100644 --- a/arch/arm/mach-rmobile/Kconfig.rzg2l +++ b/arch/arm/mach-rmobile/Kconfig.rzg2l @@ -9,6 +9,20 @@ config R9A07G044L help Enable support for the R9A07G044L SoC used in the RZ/G2L.
+choice
- prompt "Renesas RZ/G2L Family Board selection"
- default TARGET_RZG2L_SMARC_EVK
+config TARGET_RZG2L_SMARC_EVK
- bool "Renesas RZ/G2L SMARC EVK"
- imply R9A07G044L
- help
Enable support for the RZ/G2L SMARC evaluation board.
+source "board/renesas/rzg2l/Kconfig"
+endchoice
- config MULTI_DTB_FIT_UNCOMPRESS_SZ default 0x80000 if TARGET_RZG2L_SMARC_EVK
diff --git a/board/renesas/rzg2l/Kconfig b/board/renesas/rzg2l/Kconfig new file mode 100644 index 000000000000..1335fc7ae806 --- /dev/null +++ b/board/renesas/rzg2l/Kconfig @@ -0,0 +1,18 @@ +# Copyright (C) 2023 Renesas Electronics Corporation +# SPDX-License-Identifier: GPL-2.0+
+if TARGET_RZG2L_SMARC_EVK
+config SYS_SOC
- default "rmobile"
+config SYS_BOARD
- default "rzg2l"
+config SYS_VENDOR
- default "renesas"
+config SYS_CONFIG_NAME
- default "rzg2l-smarc"
+endif diff --git a/board/renesas/rzg2l/MAINTAINERS b/board/renesas/rzg2l/MAINTAINERS new file mode 100644 index 000000000000..0a51391c1fc9 --- /dev/null +++ b/board/renesas/rzg2l/MAINTAINERS @@ -0,0 +1,6 @@ +RENESAS RZG2L BOARD FAMILY +M: Paul Barker paul.barker.ct@bp.renesas.com +S: Supported +F: arch/arm/dts/rz-smarc-common.dtsi
I suspect there should be more files here, right ? You likely want to be CCed on things like rzg2l clock, scif, and so on.
+N: rzg2l +N: r9a07g044 diff --git a/board/renesas/rzg2l/Makefile b/board/renesas/rzg2l/Makefile new file mode 100644 index 000000000000..466935fc8158 --- /dev/null +++ b/board/renesas/rzg2l/Makefile @@ -0,0 +1,4 @@ +# Copyright (C) 2023 Renesas Electronics Corporation +# SPDX-License-Identifier: GPL-2.0+
+obj-y := rzg2l.o
diff --git a/board/renesas/rzg2l/rzg2l.c b/board/renesas/rzg2l/rzg2l.c new file mode 100644 index 000000000000..2b1bb3546c26 --- /dev/null +++ b/board/renesas/rzg2l/rzg2l.c @@ -0,0 +1,76 @@ +// SPDX-License-Identifier: GPL-2.0+ +/*
- RZ/G2L board support.
- Copyright (C) 2023 Renesas Electronics Corporation
- */
+#include <common.h> +#include <fdtdec.h> +#include <linux/libfdt.h>
+#if IS_ENABLED(CONFIG_MULTI_DTB_FIT) +/* If the firmware passed a device tree, use it for board identification. */ +extern u64 rcar_atf_boot_args[];
+static bool is_rzg2l_board(const char *board_name) +{
- void *atf_fdt_blob = (void *)(rcar_atf_boot_args[1]);
- return fdt_node_check_compatible(atf_fdt_blob, 0, board_name) == 0;
+}
+int board_fit_config_name_match(const char *name) +{
- void *atf_fdt_blob = (void *)(rcar_atf_boot_args[1]);
- if (fdt_magic(atf_fdt_blob) != FDT_MAGIC)
return -1;
- if (is_rzg2l_board("renesas,r9a07g044l2"))
return strcmp(name, "r9a07g044l2-smarc");
- return -1;
+} +#endif
+static void apply_atf_overlay(void *fdt_blob) +{
- void *atf_fdt_blob = (void *)(rcar_atf_boot_args[1]);
- if (fdt_magic(atf_fdt_blob) == FDT_MAGIC)
fdt_overlay_apply_node(fdt_blob, 0, atf_fdt_blob, 0);
+}
+int fdtdec_board_setup(const void *fdt_blob) +{
- apply_atf_overlay((void *)fdt_blob);
- return 0;
+}
+int ft_board_setup(void *blob, struct bd_info *bd) +{
- return 0;
Are all these stub functions really needed or can they be removed (possibly also with removal of unnecessary config options) ?
I've moved dram_init() & dram_init_banksize() out to arch/arm/mach-rmobile/memmap-rzg2l.c. However, the other three stub functions can't easily be removed:
board_init() is always called if CONFIG_ARM is enabled. There is a similar stub in board/renesas/rcar-common/common.c so I think this is ok.
ft_board_setup() is called if CONFIG_OF_BOARD_SETUP is enabled, which is selected by CONFIG_RCAR_64, I don't see much point messing around to break that config dependency when I'm going to be coming back to fill in this stub once support for these boards is fully upstreamed to TrustedFirmware.
OK
- reset_cpu() is called from arch/arm/lib/reset.c, which is included unless CONFIG_SYSRESET is defined, and I don't think enabling CONFIG_SYSRESET makes any sense here. Again, I'll be filling in this stub once TrustedFirmware supports resetting this board.
I'll chat to the rest of the team tomorrow and see if there's a hacky way we can do the reset before TrustedFirmware support is complete.
Maybe just add a ToDo comment and let's get this in before 2024.01-rc1 is out.
participants (3)
-
Biju Das
-
Marek Vasut
-
Paul Barker