* [PATCH v1 1/7] ARM: dts: aspeed: system1: Disable vuart2
From: Ninad Palsule @ 2026-04-21 22:45 UTC (permalink / raw)
To: eajames, robh, krzk+dt, conor+dt, joel, andrew, devicetree,
linux-arm-kernel, linux-aspeed, linux-kernel
Cc: Ninad Palsule
In-Reply-To: <20260421224551.1611818-1-ninad@linux.ibm.com>
system1 BMC machine does not wire vuart2 to host hence disable it to
avoid any errors in the journal.
Signed-off-by: Ninad Palsule <ninad@linux.ibm.com>
---
arch/arm/boot/dts/aspeed/aspeed-bmc-ibm-system1.dts | 4 ----
1 file changed, 4 deletions(-)
diff --git a/arch/arm/boot/dts/aspeed/aspeed-bmc-ibm-system1.dts b/arch/arm/boot/dts/aspeed/aspeed-bmc-ibm-system1.dts
index c8267c97a44e..488d0b3916a1 100644
--- a/arch/arm/boot/dts/aspeed/aspeed-bmc-ibm-system1.dts
+++ b/arch/arm/boot/dts/aspeed/aspeed-bmc-ibm-system1.dts
@@ -472,10 +472,6 @@ &vuart1 {
status = "okay";
};
-&vuart2 {
- status = "okay";
-};
-
&lpc_ctrl {
status = "okay";
memory-region = <&flash_memory>;
--
2.51.0
^ permalink raw reply related
* [PATCH v1 0/7] DTS updates for system1 BMC
From: Ninad Palsule @ 2026-04-21 22:45 UTC (permalink / raw)
To: eajames, robh, krzk+dt, conor+dt, joel, andrew, devicetree,
linux-arm-kernel, linux-aspeed, linux-kernel
Cc: Ninad Palsule
Hello,
Please review the patch set.
Andrew Geissler (1):
ARM: dts: aspeed: system1: disable NCSI net port
Manojkiran Eda (2):
ARM: dts: aspeed: system1: Enable video engine
ARM: dts: aspeed: system1: Add usb virtual hub dev
Ninad Palsule (4):
ARM: dts: aspeed: system1: Disable vuart2
ARM: dts: aspeed: system1: Enable temp sensors
ARM: dts: aspeed: system1: Added status LEDs
ARM: dts: aspeed: system1: DTS updates
.../dts/aspeed/aspeed-bmc-ibm-system1.dts | 1445 ++++++++++++++++-
1 file changed, 1423 insertions(+), 22 deletions(-)
--
2.51.0
^ permalink raw reply
* [PATCH v2] perf/arm_pmu: Skip PMCCNTR_EL0 on NVIDIA Olympus
From: Besar Wicaksono @ 2026-04-21 20:38 UTC (permalink / raw)
To: will, mark.rutland, james.clark
Cc: linux-arm-kernel, linux-kernel, linux-tegra, treding, jonathanh,
vsethi, rwiley, sdonthineni, mochs, nirmoyd, skelley,
Besar Wicaksono
The PMCCNTR_EL0 in NVIDIA Olympus CPU may increment while
in WFI/WFE, which does not align with counting CPU_CYCLES
on a programmable counter. Add a MIDR range entry and
refuse PMCCNTR_EL0 for cycle events on affected parts so
perf does not mix the two behaviors.
Signed-off-by: Besar Wicaksono <bwicaksono@nvidia.com>
---
Changes from v1:
* add CONFIG_ARM64 check to fix build error found by kernel test robot
* add explicit include of <asm/cputype.h>
v1: https://lore.kernel.org/linux-arm-kernel/20260406232034.2566133-1-bwicaksono@nvidia.com/
---
drivers/perf/arm_pmuv3.c | 44 ++++++++++++++++++++++++++++++++++++++++
1 file changed, 44 insertions(+)
diff --git a/drivers/perf/arm_pmuv3.c b/drivers/perf/arm_pmuv3.c
index 8014ff766cff..7c39d0804b9f 100644
--- a/drivers/perf/arm_pmuv3.c
+++ b/drivers/perf/arm_pmuv3.c
@@ -8,6 +8,7 @@
* This code is based heavily on the ARMv7 perf event code.
*/
+#include <asm/cputype.h>
#include <asm/irq_regs.h>
#include <asm/perf_event.h>
#include <asm/virt.h>
@@ -978,6 +979,41 @@ static int armv8pmu_get_chain_idx(struct pmu_hw_events *cpuc,
return -EAGAIN;
}
+#ifdef CONFIG_ARM64
+/*
+ * List of CPUs that should avoid using PMCCNTR_EL0.
+ */
+static struct midr_range armv8pmu_avoid_pmccntr_cpus[] = {
+ /*
+ * The PMCCNTR_EL0 in Olympus CPU may still increment while in WFI/WFE state.
+ * This is an implementation specific behavior and not an erratum.
+ *
+ * From ARM DDI0487 D14.4:
+ * It is IMPLEMENTATION SPECIFIC whether CPU_CYCLES and PMCCNTR count
+ * when the PE is in WFI or WFE state, even if the clocks are not stopped.
+ *
+ * From ARM DDI0487 D24.5.2:
+ * All counters are subject to any changes in clock frequency, including
+ * clock stopping caused by the WFI and WFE instructions.
+ * This means that it is CONSTRAINED UNPREDICTABLE whether or not
+ * PMCCNTR_EL0 continues to increment when clocks are stopped by WFI and
+ * WFE instructions.
+ */
+ MIDR_ALL_VERSIONS(MIDR_NVIDIA_OLYMPUS),
+ {}
+};
+
+static bool armv8pmu_is_in_avoid_pmccntr_cpus(void)
+{
+ return is_midr_in_range_list(armv8pmu_avoid_pmccntr_cpus);
+}
+#else
+static bool armv8pmu_is_in_avoid_pmccntr_cpus(void)
+{
+ return false;
+}
+#endif
+
static bool armv8pmu_can_use_pmccntr(struct pmu_hw_events *cpuc,
struct perf_event *event)
{
@@ -1011,6 +1047,14 @@ static bool armv8pmu_can_use_pmccntr(struct pmu_hw_events *cpuc,
if (cpu_pmu->has_smt)
return false;
+ /*
+ * On some CPUs, PMCCNTR_EL0 does not match the behavior of CPU_CYCLES
+ * programmable counter, so avoid routing cycles through PMCCNTR_EL0 to
+ * prevent inconsistency in the results.
+ */
+ if (armv8pmu_is_in_avoid_pmccntr_cpus())
+ return false;
+
return true;
}
--
2.43.0
^ permalink raw reply related
* [PATCH v5 8/8] ARM: defconfig: Add a zx29 defconfig file
From: Stefan Dösinger @ 2026-04-21 20:23 UTC (permalink / raw)
To: Jonathan Corbet, Shuah Khan, Russell King, Rob Herring,
Krzysztof Kozlowski, Conor Dooley, Arnd Bergmann,
Krzysztof Kozlowski, Alexandre Belloni, Linus Walleij,
Drew Fustini, Greg Kroah-Hartman, Jiri Slaby
Cc: linux-doc, linux-kernel, linux-arm-kernel, devicetree, soc,
linux-serial, Stefan Dösinger
In-Reply-To: <20260421-send-v5-0-ace038e63515@gmail.com>
This enables existing drivers that already are (UART) or will be (USB,
GPIO) necessary to operate this board even if they aren't declared in
the DTS yet.
Signed-off-by: Stefan Dösinger <stefandoesinger@gmail.com>
---
arch/arm/configs/zx29_defconfig | 89 +++++++++++++++++++++++++++++++++++++++++
1 file changed, 89 insertions(+)
diff --git a/arch/arm/configs/zx29_defconfig b/arch/arm/configs/zx29_defconfig
new file mode 100644
index 000000000000..a78decd1d525
--- /dev/null
+++ b/arch/arm/configs/zx29_defconfig
@@ -0,0 +1,89 @@
+CONFIG_SYSVIPC=y
+CONFIG_BLK_DEV_INITRD=y
+# CONFIG_RD_BZIP2 is not set
+# CONFIG_RD_LZMA is not set
+# CONFIG_RD_XZ is not set
+# CONFIG_RD_LZ4 is not set
+CONFIG_EXPERT=y
+CONFIG_KALLSYMS_ALL=y
+CONFIG_MMU=y
+CONFIG_ARCH_MULTI_V7=y
+CONFIG_ARCH_ZTE=y
+CONFIG_SOC_ZX297520V3=y
+# FIXME: There is no PSCI on this board, but ARM_GIC_V3 depends on it
+CONFIG_ARM_PSCI=y
+CONFIG_ARM_APPENDED_DTB=y
+CONFIG_CMDLINE="console=ttyAMA0 earlyprintk root=/dev/ram rw"
+# CONFIG_SUSPEND is not set
+CONFIG_BINFMT_FLAT=y
+# CONFIG_UEVENT_HELPER is not set
+# CONFIG_STANDALONE is not set
+# CONFIG_PREVENT_FIRMWARE_BUILD is not set
+# CONFIG_ALLOW_DEV_COREDUMP is not set
+CONFIG_BLK_DEV_RAM=y
+CONFIG_BLK_DEV_RAM_COUNT=4
+CONFIG_CPU_FREQ=y
+CONFIG_CPUFREQ_DT_PLATDEV=y
+CONFIG_PM=y
+CONFIG_PM_CLK=y
+CONFIG_PM_GENERIC_DOMAINS=y
+CONFIG_NET=y
+CONFIG_PACKET=y
+CONFIG_UNIX=y
+CONFIG_INET=y
+CONFIG_DEVTMPFS=y # FIXME: This is specific to my initrd. Remove before upstream
+CONFIG_DEVTMPFS_MOUNT=y
+# CONFIG_INPUT_MOUSEDEV is not set
+CONFIG_KEYBOARD_GPIO_POLLED=y
+CONFIG_GPIOLIB=y
+CONFIG_OF_GPIO=y
+CONFIG_GPIO_GENERIC_PLATFORM=y
+# CONFIG_INPUT_MOUSE is not set
+# CONFIG_SERIO is not set
+CONFIG_VT_HW_CONSOLE_BINDING=y
+CONFIG_SERIAL_AMBA_PL011=y
+CONFIG_SERIAL_AMBA_PL011_CONSOLE=y
+CONFIG_SERIAL_OF_PLATFORM=y
+CONFIG_SERIAL_DEV_BUS=y
+CONFIG_SERIAL_DEV_CTRL_TTYPORT=y
+# CONFIG_HW_RANDOM is not set
+CONFIG_MFD_SYSCON=y
+# CONFIG_HID is not set
+CONFIG_PINCTRL=y
+CONFIG_GENERIC_PINCTRL_GROUPS=y
+CONFIG_PINMUX=y
+CONFIG_GENERIC_PINMUX_FUNCTIONS=y
+CONFIG_PINCONF=y
+CONFIG_GENERIC_PINCONF=y
+CONFIG_RESET_CONTROLLER=y
+CONFIG_POWER_RESET=y
+CONFIG_RESET_SIMPLE=y
+CONFIG_LEDS_GPIO=y
+CONFIG_USB_DWC2=y
+CONFIG_USB_GADGET=y
+CONFIG_MTD=y
+CONFIG_MTD_OF_PARTS=y
+CONFIG_MTD_BLKDEVS=y
+CONFIG_MTD_BLOCK=y
+CONFIG_MTD_SPI_NAND=y
+CONFIG_SPI_MASTER=y
+CONFIG_MMC=y
+CONFIG_MMC_DW=y
+CONFIG_MMC_DW_PLTFM=y
+CONFIG_STMMAC_ETH=y
+CONFIG_STMMAC_PLATFORM=y
+CONFIG_MDIO_BUS=y
+CONFIG_REGULATOR=y
+CONFIG_REGULATOR_FIXED_VOLTAGE=y
+CONFIG_SRAM=y
+CONFIG_MISC_FILESYSTEMS=y
+CONFIG_JFFS2_FS=y
+CONFIG_CONFIG_TMPFS=y
+CONFIG_PRINTK_TIME=y
+CONFIG_EARLY_PRINTK=y
+CONFIG_DEBUG_LL=y
+CONFIG_DEBUG_ZTE_ZX=y
+CONFIG_DEBUG_LL_INCLUDE="debug/pl01x.S"
+CONFIG_DEBUG_UART_PL01X=y
+CONFIG_DEBUG_UART_PHYS=0x01408000
+CONFIG_DEBUG_UART_VIRT=0xf4708000
--
2.53.0
^ permalink raw reply related
* [PATCH v5 7/8] ARM: dts: Declare UARTs on zx297520v3 boards
From: Stefan Dösinger @ 2026-04-21 20:23 UTC (permalink / raw)
To: Jonathan Corbet, Shuah Khan, Russell King, Rob Herring,
Krzysztof Kozlowski, Conor Dooley, Arnd Bergmann,
Krzysztof Kozlowski, Alexandre Belloni, Linus Walleij,
Drew Fustini, Greg Kroah-Hartman, Jiri Slaby
Cc: linux-doc, linux-kernel, linux-arm-kernel, devicetree, soc,
linux-serial, Stefan Dösinger
In-Reply-To: <20260421-send-v5-0-ace038e63515@gmail.com>
Signed-off-by: Stefan Dösinger <stefandoesinger@gmail.com>
---
Changes since v4:
* Declare all uarts
* Remove the UART aliases for now. I can revisit this when I get my
hands on a board that exposes two UARTs.
---
arch/arm/boot/dts/zte/zx297520v3-dlink-dwr932m.dts | 4 +++
arch/arm/boot/dts/zte/zx297520v3.dtsi | 39 ++++++++++++++++++++++
2 files changed, 43 insertions(+)
diff --git a/arch/arm/boot/dts/zte/zx297520v3-dlink-dwr932m.dts b/arch/arm/boot/dts/zte/zx297520v3-dlink-dwr932m.dts
index ac20215fddef..1700f46aba86 100644
--- a/arch/arm/boot/dts/zte/zx297520v3-dlink-dwr932m.dts
+++ b/arch/arm/boot/dts/zte/zx297520v3-dlink-dwr932m.dts
@@ -16,3 +16,7 @@ memory@20000000 {
reg = <0x20000000 0x04000000>;
};
};
+
+&uart1 {
+ status = "okay";
+};
diff --git a/arch/arm/boot/dts/zte/zx297520v3.dtsi b/arch/arm/boot/dts/zte/zx297520v3.dtsi
index 903050c684cb..ca65797ed926 100644
--- a/arch/arm/boot/dts/zte/zx297520v3.dtsi
+++ b/arch/arm/boot/dts/zte/zx297520v3.dtsi
@@ -20,6 +20,15 @@ cpu@0 {
};
};
+ /* Base bus clock and default for the UART. It will be replaced once a clock driver has
+ * been added.
+ */
+ uartclk: uartclk: uartclk-26000000 {
+ #clock-cells = <0>;
+ compatible = "fixed-clock";
+ clock-frequency = <26000000>;
+ };
+
timer {
compatible = "arm,armv7-timer";
interrupts = <GIC_PPI 13 IRQ_TYPE_LEVEL_LOW>,
@@ -60,5 +69,35 @@ gic: interrupt-controller@f2000000 {
reg = <0xf2000000 0x10000>,
<0xf2040000 0x20000>;
};
+
+ uart0: serial@131000 {
+ compatible = "arm,primecell";
+ arm,primecell-periphid = <0x0018c011>;
+ reg = <0x00131000 0x1000>;
+ interrupts = <GIC_SPI 0 IRQ_TYPE_LEVEL_HIGH>;
+ clocks = <&uartclk>, <&uartclk>;
+ clock-names = "uartclk", "apb_pclk";
+ status = "disabled";
+ };
+
+ uart1: serial@1408000 {
+ compatible = "arm,pl011", "arm,primecell";
+ arm,primecell-periphid = <0x0018c011>;
+ reg = <0x01408000 0x1000>;
+ interrupts = <GIC_SPI 1 IRQ_TYPE_LEVEL_HIGH>;
+ clocks = <&uartclk>, <&uartclk>;
+ clock-names = "uartclk", "apb_pclk";
+ status = "disabled";
+ };
+
+ uart2: serial@140d000 {
+ compatible = "arm,primecell";
+ arm,primecell-periphid = <0x0018c011>;
+ reg = <0x0140d000 0x1000>;
+ interrupts = <GIC_SPI 2 IRQ_TYPE_LEVEL_HIGH>;
+ clocks = <&uartclk>, <&uartclk>;
+ clock-names = "uartclk", "apb_pclk";
+ status = "disabled";
+ };
};
};
--
2.53.0
^ permalink raw reply related
* [PATCH v5 6/8] amba/serial: amba-pl011: Bring back zx29 UART support
From: Stefan Dösinger @ 2026-04-21 20:23 UTC (permalink / raw)
To: Jonathan Corbet, Shuah Khan, Russell King, Rob Herring,
Krzysztof Kozlowski, Conor Dooley, Arnd Bergmann,
Krzysztof Kozlowski, Alexandre Belloni, Linus Walleij,
Drew Fustini, Greg Kroah-Hartman, Jiri Slaby
Cc: linux-doc, linux-kernel, linux-arm-kernel, devicetree, soc,
linux-serial, Stefan Dösinger
In-Reply-To: <20260421-send-v5-0-ace038e63515@gmail.com>
This is based on code removed in commit 89d4f98ae90d ("ARM: remove zte
zx platform"). I did not bring back the zx29-uart .compatible as the
arm,primecell-periphid does the job.
Signed-off-by: Stefan Dösinger <stefandoesinger@gmail.com>
---
Changes since v4:
Use ZTE's JEDEC ID instead of 0xfe for the DT-Provided AMBA ID.
---
drivers/tty/serial/amba-pl011.c | 42 +++++++++++++++++++++++++++++++++++++++++
1 file changed, 42 insertions(+)
diff --git a/drivers/tty/serial/amba-pl011.c b/drivers/tty/serial/amba-pl011.c
index 7f17d288c807..f24cc403d9e0 100644
--- a/drivers/tty/serial/amba-pl011.c
+++ b/drivers/tty/serial/amba-pl011.c
@@ -216,6 +216,38 @@ static struct vendor_data vendor_st = {
.get_fifosize = get_fifosize_st,
};
+static const u16 pl011_zte_offsets[REG_ARRAY_SIZE] = {
+ [REG_DR] = ZX_UART011_DR,
+ [REG_FR] = ZX_UART011_FR,
+ [REG_LCRH_RX] = ZX_UART011_LCRH,
+ [REG_LCRH_TX] = ZX_UART011_LCRH,
+ [REG_IBRD] = ZX_UART011_IBRD,
+ [REG_FBRD] = ZX_UART011_FBRD,
+ [REG_CR] = ZX_UART011_CR,
+ [REG_IFLS] = ZX_UART011_IFLS,
+ [REG_IMSC] = ZX_UART011_IMSC,
+ [REG_RIS] = ZX_UART011_RIS,
+ [REG_MIS] = ZX_UART011_MIS,
+ [REG_ICR] = ZX_UART011_ICR,
+ [REG_DMACR] = ZX_UART011_DMACR,
+};
+
+static unsigned int get_fifosize_zte(struct amba_device *dev)
+{
+ return 16;
+}
+
+static struct vendor_data vendor_zte = {
+ .reg_offset = pl011_zte_offsets,
+ .access_32b = true,
+ .ifls = UART011_IFLS_RX4_8 | UART011_IFLS_TX4_8,
+ .fr_busy = ZX_UART01x_FR_BUSY,
+ .fr_dsr = ZX_UART01x_FR_DSR,
+ .fr_cts = ZX_UART01x_FR_CTS,
+ .fr_ri = ZX_UART011_FR_RI,
+ .get_fifosize = get_fifosize_zte,
+};
+
/* Deals with DMA transactions */
struct pl011_dmabuf {
@@ -3081,6 +3113,16 @@ static const struct amba_id pl011_ids[] = {
.mask = 0x00ffffff,
.data = &vendor_st,
},
+ {
+ /* This is an invented ID. The actual hardware that contains
+ * these ZTE UARTs (zx29 boards) has no AMBA PIDs stored. ZTE
+ * JEDEC ID (ignoring banks) and the "011" part number as used
+ * by ARM.
+ */
+ .id = 0x0008c011,
+ .mask = 0x000fffff,
+ .data = &vendor_zte,
+ },
{ 0, 0 },
};
--
2.53.0
^ permalink raw reply related
* [PATCH v5 5/8] ARM: dts: Add an armv7 timer for zx297520v3
From: Stefan Dösinger @ 2026-04-21 20:23 UTC (permalink / raw)
To: Jonathan Corbet, Shuah Khan, Russell King, Rob Herring,
Krzysztof Kozlowski, Conor Dooley, Arnd Bergmann,
Krzysztof Kozlowski, Alexandre Belloni, Linus Walleij,
Drew Fustini, Greg Kroah-Hartman, Jiri Slaby
Cc: linux-doc, linux-kernel, linux-arm-kernel, devicetree, soc,
linux-serial, Stefan Dösinger
In-Reply-To: <20260421-send-v5-0-ace038e63515@gmail.com>
The stock kernel does not use this timer, but it seems to work fine. The
board has other board-specific timers that would need a driver and I see
no reason to bother with them since the arm standard timer works.
The caveat is the non-standard GIC setup needed to handle the timer's
level-low PPI. This is the responsibility of the boot loader and
documented in Documentation/arch/arm/zte/zx297520v3.rst.
Signed-off-by: Stefan Dösinger <stefandoesinger@gmail.com>
---
arch/arm/boot/dts/zte/zx297520v3.dtsi | 24 ++++++++++++++++++++++++
1 file changed, 24 insertions(+)
diff --git a/arch/arm/boot/dts/zte/zx297520v3.dtsi b/arch/arm/boot/dts/zte/zx297520v3.dtsi
index 0fff00f910d6..903050c684cb 100644
--- a/arch/arm/boot/dts/zte/zx297520v3.dtsi
+++ b/arch/arm/boot/dts/zte/zx297520v3.dtsi
@@ -20,6 +20,21 @@ cpu@0 {
};
};
+ timer {
+ compatible = "arm,armv7-timer";
+ interrupts = <GIC_PPI 13 IRQ_TYPE_LEVEL_LOW>,
+ <GIC_PPI 14 IRQ_TYPE_LEVEL_LOW>,
+ <GIC_PPI 11 IRQ_TYPE_LEVEL_LOW>,
+ <GIC_PPI 10 IRQ_TYPE_LEVEL_LOW>;
+ clock-frequency = <26000000>;
+ interrupt-parent = <&gic>;
+ /* I don't think uboot sets CNTVOFF and the stock kernel doesn't use the
+ * arm timer at all. Since this is a single CPU system I don't think it
+ * really matters that the offset is random though.
+ */
+ arm,cpu-registers-not-fw-configured;
+ };
+
soc {
#address-cells = <1>;
#size-cells = <1>;
@@ -27,6 +42,15 @@ soc {
interrupt-parent = <&gic>;
ranges;
+ /* The GIC has a non-standard way of configuring ints between level-low/level
+ * high or rising edge/falling edge at 0xf2202070 and onwards. See AP_INT_MODE_BASE
+ * and AP_PPI_MODE_REG in the ZTE kernel, although the offsets in the kernel source
+ * seem wrong.
+ *
+ * Everything defaults to active-high/rising edge, but the timer is active-low. We
+ * currently rely on the boot loader to change timer IRQs to active-low for us for
+ * now.
+ */
gic: interrupt-controller@f2000000 {
compatible = "arm,gic-v3";
interrupt-controller;
--
2.53.0
^ permalink raw reply related
* [PATCH v5 4/8] ARM: zte: Add support for zx29 low level debug
From: Stefan Dösinger @ 2026-04-21 20:23 UTC (permalink / raw)
To: Jonathan Corbet, Shuah Khan, Russell King, Rob Herring,
Krzysztof Kozlowski, Conor Dooley, Arnd Bergmann,
Krzysztof Kozlowski, Alexandre Belloni, Linus Walleij,
Drew Fustini, Greg Kroah-Hartman, Jiri Slaby
Cc: linux-doc, linux-kernel, linux-arm-kernel, devicetree, soc,
linux-serial, Stefan Dösinger
In-Reply-To: <20260421-send-v5-0-ace038e63515@gmail.com>
This is based on the removed zx29 code. A separate (more complicated)
patch will re-add the register map to the pl011 serial driver.
Signed-off-by: Stefan Dösinger <stefandoesinger@gmail.com>
---
I am unsure about the virtual address. It doesn't seem to matter, as
long as it is a valid address. This address is based on the old removed
code. Is there a rule-of-thumb physical to virtual mapping I can use to
give a sensible default value?
---
arch/arm/Kconfig.debug | 12 ++++++++++++
arch/arm/include/debug/pl01x.S | 7 +++++++
2 files changed, 19 insertions(+)
diff --git a/arch/arm/Kconfig.debug b/arch/arm/Kconfig.debug
index 366f162e147d..98d8a5a60048 100644
--- a/arch/arm/Kconfig.debug
+++ b/arch/arm/Kconfig.debug
@@ -1331,6 +1331,16 @@ choice
This option selects UART0 on VIA/Wondermedia System-on-a-chip
devices, including VT8500, WM8505, WM8650 and WM8850.
+ config DEBUG_ZTE_ZX
+ bool "Kernel low-level debugging via zx29 UART"
+ select DEBUG_UART_PL01X
+ depends on ARCH_ZTE
+ help
+ Say Y here if you are enabling ZTE zx297520v3 SOC and need
+ debug UART support. This UART is a PL011 with different
+ register addresses. The UART for boot messages on zx29 boards
+ is usually UART1 and is operating at 921600 8N1.
+
config DEBUG_ZYNQ_UART0
bool "Kernel low-level debugging on Xilinx Zynq using UART0"
depends on ARCH_ZYNQ
@@ -1545,6 +1555,7 @@ config DEBUG_UART_8250
config DEBUG_UART_PHYS
hex "Physical base address of debug UART"
+ default 0x01408000 if DEBUG_ZTE_ZX
default 0x01c28000 if DEBUG_SUNXI_UART0
default 0x01c28400 if DEBUG_SUNXI_UART1
default 0x01d0c000 if DEBUG_DAVINCI_DA8XX_UART1
@@ -1701,6 +1712,7 @@ config DEBUG_UART_VIRT
default 0xf31004c0 if DEBUG_MESON_UARTAO
default 0xf4090000 if DEBUG_LPC32XX
default 0xf4200000 if DEBUG_GEMINI
+ default 0xf4708000 if DEBUG_ZTE_ZX
default 0xf6200000 if DEBUG_PXA_UART1
default 0xf7000000 if DEBUG_SUN9I_UART0
default 0xf7000000 if DEBUG_S3C64XX_UART && DEBUG_S3C_UART0
diff --git a/arch/arm/include/debug/pl01x.S b/arch/arm/include/debug/pl01x.S
index c7e02d0628bf..0c7bfa4c10db 100644
--- a/arch/arm/include/debug/pl01x.S
+++ b/arch/arm/include/debug/pl01x.S
@@ -8,6 +8,13 @@
*/
#include <linux/amba/serial.h>
+#ifdef CONFIG_DEBUG_ZTE_ZX
+#undef UART01x_DR
+#undef UART01x_FR
+#define UART01x_DR 0x04
+#define UART01x_FR 0x14
+#endif
+
#ifdef CONFIG_DEBUG_UART_PHYS
.macro addruart, rp, rv, tmp
ldr \rp, =CONFIG_DEBUG_UART_PHYS
--
2.53.0
^ permalink raw reply related
* [PATCH v5 3/8] ARM: dts: Add D-Link DWR-932M support
From: Stefan Dösinger @ 2026-04-21 20:23 UTC (permalink / raw)
To: Jonathan Corbet, Shuah Khan, Russell King, Rob Herring,
Krzysztof Kozlowski, Conor Dooley, Arnd Bergmann,
Krzysztof Kozlowski, Alexandre Belloni, Linus Walleij,
Drew Fustini, Greg Kroah-Hartman, Jiri Slaby
Cc: linux-doc, linux-kernel, linux-arm-kernel, devicetree, soc,
linux-serial, Stefan Dösinger
In-Reply-To: <20260421-send-v5-0-ace038e63515@gmail.com>
This adds base DT definition for zx297520v3 and one board that consumes it.
Signed-off-by: Stefan Dösinger <stefandoesinger@gmail.com>
---
Changes in v5:
Prepend the SoC name in the device specific DTS filename.
---
MAINTAINERS | 1 +
arch/arm/boot/dts/Makefile | 1 +
arch/arm/boot/dts/zte/Makefile | 3 ++
arch/arm/boot/dts/zte/zx297520v3-dlink-dwr932m.dts | 18 ++++++++++
arch/arm/boot/dts/zte/zx297520v3.dtsi | 40 ++++++++++++++++++++++
5 files changed, 63 insertions(+)
diff --git a/MAINTAINERS b/MAINTAINERS
index bcade90ca14e..f7ca0d478e81 100644
--- a/MAINTAINERS
+++ b/MAINTAINERS
@@ -29203,6 +29203,7 @@ F: tools/testing/selftests/cgroup/test_zswap.c
ZX29
M: Stefan Dösinger <stefandoesinger@gmail.com>
F: Documentation/devicetree/bindings/arm/zte.yaml
+F: arch/arm/boot/dts/zte
F: arch/arm/mach-zte/
SENARYTECH AUDIO CODEC DRIVER
diff --git a/arch/arm/boot/dts/Makefile b/arch/arm/boot/dts/Makefile
index efe38eb25301..28fba538d552 100644
--- a/arch/arm/boot/dts/Makefile
+++ b/arch/arm/boot/dts/Makefile
@@ -39,3 +39,4 @@ subdir-y += unisoc
subdir-y += vt8500
subdir-y += xen
subdir-y += xilinx
+subdir-y += zte
diff --git a/arch/arm/boot/dts/zte/Makefile b/arch/arm/boot/dts/zte/Makefile
new file mode 100644
index 000000000000..f052cfbd636c
--- /dev/null
+++ b/arch/arm/boot/dts/zte/Makefile
@@ -0,0 +1,3 @@
+# SPDX-License-Identifier: GPL-2.0-only
+dtb-$(CONFIG_SOC_ZX297520V3) += \
+ zx297520v3-dlink-dwr932m.dtb
diff --git a/arch/arm/boot/dts/zte/zx297520v3-dlink-dwr932m.dts b/arch/arm/boot/dts/zte/zx297520v3-dlink-dwr932m.dts
new file mode 100644
index 000000000000..ac20215fddef
--- /dev/null
+++ b/arch/arm/boot/dts/zte/zx297520v3-dlink-dwr932m.dts
@@ -0,0 +1,18 @@
+// SPDX-License-Identifier: GPL-2.0-only
+/*
+ * Copyright (c) 2026 Stefan Dösinger <stefandoesinger@gmail.com>
+ */
+
+/dts-v1/;
+
+#include "zx297520v3.dtsi"
+
+/ {
+ model = "D-Link DWR-932M";
+ compatible = "dlink,dwr932m", "zte,zx297520v3";
+
+ memory@20000000 {
+ device_type = "memory";
+ reg = <0x20000000 0x04000000>;
+ };
+};
diff --git a/arch/arm/boot/dts/zte/zx297520v3.dtsi b/arch/arm/boot/dts/zte/zx297520v3.dtsi
new file mode 100644
index 000000000000..0fff00f910d6
--- /dev/null
+++ b/arch/arm/boot/dts/zte/zx297520v3.dtsi
@@ -0,0 +1,40 @@
+// SPDX-License-Identifier: GPL-2.0-only
+/*
+ * Copyright (c) 2026 Stefan Dösinger <stefandoesinger@gmail.com>
+ */
+
+#include <dt-bindings/interrupt-controller/arm-gic.h>
+
+/ {
+ #address-cells = <1>;
+ #size-cells = <1>;
+
+ cpus {
+ #address-cells = <1>;
+ #size-cells = <0>;
+
+ cpu@0 {
+ device_type = "cpu";
+ compatible = "arm,cortex-a53";
+ reg = <0>;
+ };
+ };
+
+ soc {
+ #address-cells = <1>;
+ #size-cells = <1>;
+ compatible = "simple-bus";
+ interrupt-parent = <&gic>;
+ ranges;
+
+ gic: interrupt-controller@f2000000 {
+ compatible = "arm,gic-v3";
+ interrupt-controller;
+ #interrupt-cells = <3>;
+ #address-cells = <1>;
+ #size-cells = <1>;
+ reg = <0xf2000000 0x10000>,
+ <0xf2040000 0x20000>;
+ };
+ };
+};
--
2.53.0
^ permalink raw reply related
* [PATCH v5 2/8] dt-bindings: arm: Add zx297520v3 board binding
From: Stefan Dösinger @ 2026-04-21 20:23 UTC (permalink / raw)
To: Jonathan Corbet, Shuah Khan, Russell King, Rob Herring,
Krzysztof Kozlowski, Conor Dooley, Arnd Bergmann,
Krzysztof Kozlowski, Alexandre Belloni, Linus Walleij,
Drew Fustini, Greg Kroah-Hartman, Jiri Slaby
Cc: linux-doc, linux-kernel, linux-arm-kernel, devicetree, soc,
linux-serial, Stefan Dösinger
In-Reply-To: <20260421-send-v5-0-ace038e63515@gmail.com>
Add a compatible for boards based on the ZTE zx297520v3 SoC.
Signed-off-by: Stefan Dösinger <stefandoesinger@gmail.com>
---
The list of devices is the devices I have access to for testing. There
are many more devices based on this board and it is not always easy to
identify them. Often they are sold without any branding ("4G home
router") or with mobile carrier branding.
---
Documentation/devicetree/bindings/arm/zte.yaml | 25 +++++++++++++++++++++++++
MAINTAINERS | 1 +
2 files changed, 26 insertions(+)
diff --git a/Documentation/devicetree/bindings/arm/zte.yaml b/Documentation/devicetree/bindings/arm/zte.yaml
new file mode 100644
index 000000000000..4b0d6d53402b
--- /dev/null
+++ b/Documentation/devicetree/bindings/arm/zte.yaml
@@ -0,0 +1,25 @@
+# SPDX-License-Identifier: (GPL-2.0-only OR BSD-2-Clause)
+%YAML 1.2
+---
+$id: http://devicetree.org/schemas/arm/zte.yaml#
+$schema: http://devicetree.org/meta-schemas/core.yaml#
+
+title: ZTE zx29
+
+maintainers:
+ - Stefan Dösinger <stefandoesinger@gmail.com>
+
+properties:
+ $nodename:
+ const: "/"
+ compatible:
+ oneOf:
+ - items:
+ - enum:
+ - dlink,dwr932m
+ - hgsd,r310
+ - tecno,tr118
+ - zte,k10
+ - const: zte,zx297520v3
+
+additionalProperties: true
diff --git a/MAINTAINERS b/MAINTAINERS
index 974d7a98956a..bcade90ca14e 100644
--- a/MAINTAINERS
+++ b/MAINTAINERS
@@ -29202,6 +29202,7 @@ F: tools/testing/selftests/cgroup/test_zswap.c
ZX29
M: Stefan Dösinger <stefandoesinger@gmail.com>
+F: Documentation/devicetree/bindings/arm/zte.yaml
F: arch/arm/mach-zte/
SENARYTECH AUDIO CODEC DRIVER
--
2.53.0
^ permalink raw reply related
* [PATCH v5 1/8] ARM: zte: Add zx297520v3 platform support
From: Stefan Dösinger @ 2026-04-21 20:23 UTC (permalink / raw)
To: Jonathan Corbet, Shuah Khan, Russell King, Rob Herring,
Krzysztof Kozlowski, Conor Dooley, Arnd Bergmann,
Krzysztof Kozlowski, Alexandre Belloni, Linus Walleij,
Drew Fustini, Greg Kroah-Hartman, Jiri Slaby
Cc: linux-doc, linux-kernel, linux-arm-kernel, devicetree, soc,
linux-serial, Stefan Dösinger
In-Reply-To: <20260421-send-v5-0-ace038e63515@gmail.com>
This SoC is used in low end LTE-to-WiFi routers, for example some D-Link
DWR 932 revisions, ZTE K10, ZLT S10 4G, but also models that are branded
and sold by ISPs themselves. They are widespread in Africa, China,
Russia and Eastern Europe.
This SoC is a relative of the zx296702 and zx296718 that had some
upstream support until commit 89d4f98ae90d ("ARM: remove zte zx
platform"). My eventual goal is to enable OpenWRT to run on these
devices.
Signed-off-by: Stefan Dösinger <stefandoesinger@gmail.com>
---
Documentation/arch/arm/zte/zx297520v3.rst | 158 ++++++++++++++++++++++++++++++
MAINTAINERS | 4 +
arch/arm/Kconfig | 2 +
arch/arm/Makefile | 1 +
arch/arm/mach-zte/Kconfig | 26 +++++
arch/arm/mach-zte/Makefile | 2 +
arch/arm/mach-zte/zx297520v3.c | 19 ++++
7 files changed, 212 insertions(+)
diff --git a/Documentation/arch/arm/zte/zx297520v3.rst b/Documentation/arch/arm/zte/zx297520v3.rst
new file mode 100644
index 000000000000..6621ea72769f
--- /dev/null
+++ b/Documentation/arch/arm/zte/zx297520v3.rst
@@ -0,0 +1,158 @@
+.. SPDX-License-Identifier: GPL-2.0-only
+
+====================================
+Booting Linux on ZTE zx297520v3 SoCs
+====================================
+
+...............................................................................
+
+Author: Stefan Dösinger
+
+Date : 27 Jan 2026
+
+1. Hardware description
+---------------------------
+Zx297520v3 SoCs use a 64 bit capable Cortex-A53 CPU and GICv3, although they
+run in arm32 mode only. The CPU has support EL3, but no hypervisor (EL2) and
+it seems to lack VFP and NEON.
+
+The SoC is used in a number of cheap LTE to WiFi routers, both battery powered
+MiFis and stationary CPEs. In addition to the CPU these devices usually have
+64 MB Ram (although some is shared with the LTE chip), 128 MB NAND flash, an
+SDIO connected RTL8192-type Wifi chip limited to 2.4 ghz operation, USB 2,
+and buttons. Devices with as low as 32 MB or as high as 128 MB ram exist, as
+do devices with 8 or 16 MB of NOR flash.
+
+Some devices, especially the stationary ones, have 100 mbit Ethernet and an
+Ethernet switch.
+
+Usually the devices have LEDs for status indication, although some have SPI or
+I2C connected displays
+
+Some have an SD card slot. If it exists, it is a better choice for the root
+file system because it easily outperforms the built-in NAND.
+
+The LTE interface runs on a separate DSP called ZSP880. It is probably derived
+from LSI ZSPs and has an undocumented instruction set. The ZSP communicates
+with the main CPU via SRAM and DRAM and a mailbox hardware that can generate
+IRQs on either ends.
+
+There is also a Cortex M0 CPU, which is responsible for early HW initialization
+and starting the Cortex A53 CPU. It does not have any essential purpose once
+U-Boot is started. A SRAM-Based handover protocol exists to run custom code on
+this CPU.
+
+2. Booting via USB
+---------------------------
+
+The Boot ROM has support for booting custom code via USB. This mode can be
+entered by connecting a Boot PIN to GND or by modifying the third byte on NAND
+(set it to anything other than 0x5A aka 'Z'). A free software tool to start
+custom U-Boot and kernels can be found here:
+
+https://github.com/zx297520v3-mainline/zx297520v3-loader
+
+If USB download mode is entered but no boot commands are sent through USB, the
+device will proceed to boot normally after a few seconds. It is therefore
+possible to enable USB boot permanently and still leave the default boot files
+in place.
+
+3. Building for built-in U-Boot
+---------------------------
+The devices come with an ancient U-Boot that loads legacy uImages from NAND and
+boots them without a chance for the user to interrupt. The images are stored in
+files ap_cpuap.bin and ap_recovery.bin on a jffs2 partition named imagefs,
+usually mtd4. A file named "fotaflag" switches between the two modes.
+
+In addition to the uImage header, those files have a 384 byte signature header,
+which is used for authenticating the images on some devices. Most devices have
+this authentication disabled and it is enough to pad the uImage files with 384
+zero bytes.
+
+Builtin U-Boot also poorly sets up the CPU. Read the next section for details
+on this. It has no support for loading DTBs, so CONFIG_ARM_APPENDED_DTB is
+needed.
+
+So to build an image that boots from NAND the following steps are necessary:
+
+1) Patch the assembly code from section 3 into arch/arm/kernel/head.S.
+2) make zx29_defconfig
+3) make [-j x]
+4) cat arch/arm/boot/zImage arch/arm/boot/dts/zte/[device].dtb > kernel+dtb
+5) mkimage -A arm -O linux -T kernel -C none -a 0x20008000 -d kernel+dtb uimg
+6) dd if=/dev/zero bs=1 count=384 of=ap_recovery.bin
+7) cat uimg >> ap_recovery.bin
+8) Place this file onto imagefs on the device. Delete ap_cpuap.bin if the
+free space is not enough.
+9) Create the file fotaflag: echo -n FOTA-RECOVERY > fotaflag
+
+For development, booting ap_recovery.bin is recommended because the normal boot
+mode arms the watchdog before starting the kernel.
+
+4. CPU and GIC Setup
+---------------------------
+
+Generally CPU and GICv3 need to be set up according to the requirements spelled
+out in Documentation/arch/arm64/booting.rst. For zx297520v3 this means:
+
+1. GICD_CTLR.DS=1 to disable GIC security
+2. Enable access to ICC_SRE
+3. Disable trapping IRQs into monitor mode
+4. Configure EL2 and below to run in insecure mode.
+5. Configure timer PPIs to active-low.
+
+The kernel sources provided by ZTE do not boot either (interrupts do not work
+at all). They are incomplete in other aspects too, so it is assumed that there
+is some workaround similar to the one described in this document somewhere in
+the binary blobs.
+
+The assembly code below is given as an example of how to achieve this:
+
+```
+#include <linux/irqchip/arm-gic-v3.h>
+#include <asm/assembler.h>
+#include <asm/cp15.h>
+
+@ This allows EL1 to handle ints hat are normally handled by EL2/3.
+ldr r3, =0xf2000000
+ldr r4, =(GICD_CTLR_ARE_NS | GICD_CTLR_DS)
+str r4, [r3]
+
+cps #MON_MODE
+
+@ Work in non-secure physical address space: SCR_EL3.NS = 1. At least the UART
+@ seems to respond only to non-secure addresses. I have taken insipiration from
+@ Raspberry pi's armstub7.S here.
+@
+@ ARM docs say modify this bit in monitor mode only...
+mov r3, #0x131 @ non-secure, Make F, A bits in CPSR writeable
+ @ Allow hypervisor call.
+mcr p15, 0, r3, c1, c1, 0
+
+@ AP_PPI_MODE_REG: Configure timer PPIs (10, 11, 13, 14) to active-low.
+ldr r3, =0xF22020a8
+ldr r4, =0x50
+str r4, [r3]
+ldr r3, =0xF22020ac
+ldr r4, =0x14
+str r4, [r3]
+
+@ Enable EL2 access to ICC_SRE (bit 3, ICC_SRE_EL3.Enable). Enable system reg
+@ access to GICv3 registers (bit 0, ICC_SRE_EL3.SRE) for EL1 and EL3.
+mrc p15, 6, r3, c12, c12, 5 @ ICC_SRE_EL3
+orr r3, #0x9 @ FIXME: No defines for SRE_EL3 values?
+mcr p15, 6, r3, c12, c12, 5
+mrc p15, 0, r3, c12, c12, 5 @ ICC_SRE_EL1
+orr r3, #(ICC_SRE_EL1_SRE)
+mcr p15, 0, r3, c12, c12, 5
+
+@ Like ICC_SRE_EL3, enable EL1 access to ICC_SRE and system register access
+@ for EL2.
+mrc p15, 4, r3, c12, c9, 5 @ ICC_SRE_EL2 aka ICC_HSRE
+orr r3, r3, #(ICC_SRE_EL2_ENABLE | ICC_SRE_EL2_SRE)
+mcr p15, 4, r3, c12, c9, 5
+isb
+
+@ Back to SVC mode. TODO: Doesn't safe_svcmode_maskall do this for us anyway?
+cps #SVC_MODE
+```
diff --git a/MAINTAINERS b/MAINTAINERS
index d1cc0e12fe1f..974d7a98956a 100644
--- a/MAINTAINERS
+++ b/MAINTAINERS
@@ -29200,6 +29200,10 @@ F: include/linux/zswap.h
F: mm/zswap.c
F: tools/testing/selftests/cgroup/test_zswap.c
+ZX29
+M: Stefan Dösinger <stefandoesinger@gmail.com>
+F: arch/arm/mach-zte/
+
SENARYTECH AUDIO CODEC DRIVER
M: bo liu <bo.liu@senarytech.com>
S: Maintained
diff --git a/arch/arm/Kconfig b/arch/arm/Kconfig
index ec33376f8e2b..4217ed704e48 100644
--- a/arch/arm/Kconfig
+++ b/arch/arm/Kconfig
@@ -464,6 +464,8 @@ source "arch/arm/mach-versatile/Kconfig"
source "arch/arm/mach-vt8500/Kconfig"
+source "arch/arm/mach-zte/Kconfig"
+
source "arch/arm/mach-zynq/Kconfig"
# ARMv7-M architecture
diff --git a/arch/arm/Makefile b/arch/arm/Makefile
index b7de4b6b284c..573813ef5e77 100644
--- a/arch/arm/Makefile
+++ b/arch/arm/Makefile
@@ -223,6 +223,7 @@ machine-$(CONFIG_ARCH_SUNXI) += sunxi
machine-$(CONFIG_ARCH_TEGRA) += tegra
machine-$(CONFIG_ARCH_U8500) += ux500
machine-$(CONFIG_ARCH_VT8500) += vt8500
+machine-$(CONFIG_ARCH_ZTE) += zte
machine-$(CONFIG_ARCH_ZYNQ) += zynq
machine-$(CONFIG_PLAT_VERSATILE) += versatile
machine-$(CONFIG_PLAT_SPEAR) += spear
diff --git a/arch/arm/mach-zte/Kconfig b/arch/arm/mach-zte/Kconfig
new file mode 100644
index 000000000000..2e3abee94994
--- /dev/null
+++ b/arch/arm/mach-zte/Kconfig
@@ -0,0 +1,26 @@
+# SPDX-License-Identifier: GPL-2.0-only
+menuconfig ARCH_ZTE
+ bool "ZTE zx family"
+ depends on ARCH_MULTI_V7
+ help
+ Support for ZTE zx-based family of processors.
+
+if ARCH_ZTE
+
+config SOC_ZX297520V3
+ default y if ARCH_ZTE
+ bool "zx297520v3"
+ select ARM_GIC_V3
+ select ARM_AMBA
+ select HAVE_ARM_ARCH_TIMER
+ select PM_GENERIC_DOMAINS if PM
+ help
+ Support for ZTE zx297520v3 SoC. It is a single core SoC used in cheap
+ LTE to WiFi routers. These devices can be identified by the occurrence
+ of the string "zx297520v3" in the boot output and /proc/cpuinfo of
+ their stock firmware.
+
+ Please read Documentation/arch/arm/zte/zx297520v3.rst on how to boot
+ the kernel.
+
+endif
diff --git a/arch/arm/mach-zte/Makefile b/arch/arm/mach-zte/Makefile
new file mode 100644
index 000000000000..1bfe4fddd6af
--- /dev/null
+++ b/arch/arm/mach-zte/Makefile
@@ -0,0 +1,2 @@
+# SPDX-License-Identifier: GPL-2.0-only
+obj-$(CONFIG_SOC_ZX297520V3) += zx297520v3.o
diff --git a/arch/arm/mach-zte/zx297520v3.c b/arch/arm/mach-zte/zx297520v3.c
new file mode 100644
index 000000000000..c11c7e836f91
--- /dev/null
+++ b/arch/arm/mach-zte/zx297520v3.c
@@ -0,0 +1,19 @@
+// SPDX-License-Identifier: GPL-2.0-only
+/*
+ * Copyright 2026 Stefan Dösinger
+ */
+
+#include <asm/mach/arch.h>
+#include <asm/mach/map.h>
+
+#include <linux/of_address.h>
+#include <linux/of_platform.h>
+
+static const char *const zx297520v3_dt_compat[] __initconst = {
+ "zte,zx297520v3",
+ NULL,
+};
+
+DT_MACHINE_START(ZX, "ZTE zx297520v3 (Device Tree)")
+ .dt_compat = zx297520v3_dt_compat,
+MACHINE_END
--
2.53.0
^ permalink raw reply related
* [PATCH v5 0/8] Add support for ZTE zx297520v3
From: Stefan Dösinger @ 2026-04-21 20:23 UTC (permalink / raw)
To: Jonathan Corbet, Shuah Khan, Russell King, Rob Herring,
Krzysztof Kozlowski, Conor Dooley, Arnd Bergmann,
Krzysztof Kozlowski, Alexandre Belloni, Linus Walleij,
Drew Fustini, Greg Kroah-Hartman, Jiri Slaby
Cc: linux-doc, linux-kernel, linux-arm-kernel, devicetree, soc,
linux-serial, Stefan Dösinger
Hi,
This is a follow-up on my RFC patches from January [0] for ZTE's
zx297520v3 chipset. This chipset is popular in cheap LTE-to-wifi routers
sold in developing countries. My goal is to run OpenWRT on them. I made
more progress in more work on this SoC and it is time to get serious
about code review and upstreaming.
Since my version in January I managed to get more hardware running: SPI,
I2C, PMIC with real time clock and voltage regulators, Watchdog. LTE is
not working yet, but I am able to start the coprocessor that handles it
and talk to it via mailbox + shared memory. Wifi is working on a few
more devices. Since WiFi, USB and Ethernet are working, the devices can
have actual use with OpenWRT even without LTE.
Another hacker created a free software program to talk to the USB loader
[1] and boot U-Boot and Linux without modifying the on disk files. At
the moment it needs a proprietary blob, so my documentation is
emphasising booting with the on-device U-Boot.
This patchset here is mostly unmodified from the version I sent in
January. It is the bare minimum to get an interactive shell working on
the UART. Future patches can be found on my git repository [2] for those
curious to peek ahead. The first 30 patches are in reasonable shape, but
the further you go the more cleanup is necessary. I expect all of the
patches go require a few rounds of feedback though.
My plan for upstreaming is largly this:
1) This bare minimum boot patchset
2) Add clock and pinctrl drivers
3) Add standard hardware to the device tree
4) Add zx29 specific drivers one by one: Watchdog, spi, i2c, DMA, PMIC,
battery
5) SDIO backend for rtl8xxxu
6) rproc, mailbox and rpmsg
I am willing to maintain support for the SoC within reason. My patches
add myself as maintainer. This is a hobby project for me though, keep
that in mind if you want to ship a commercial product with these SoCs
and upstreaming Linux.
Cheers,
Stefan
0: https://lists.infradead.org/pipermail/linux-arm-kernel/2026-January/1099306.html
1: https://github.com/zx297520v3-mainline/zx297520v3-loader
2: https://gitlab.com/stefandoesinger/zx297520-kernel/
Patch changelog:
v5:
Spelling fixes
Renamed dlink-dwr-932m.dts to zx297520v3-dlink-dwr932m.dts
DT binding indentation fixes
Use a manufacturer 0x8b for the UART, fix patch prefix
Declare all UARTs, remove uart aliases for now
Consistent license declarations. I made every new file except the DT
binding GPL-2.0-only but I don't particularly mind GPL-2.0-or-later
either.
v4: rename zx29.yaml to zte.yaml and add board enums
v3: Remove [RFC] tag, add defconfig
v2: checkpatch.pl fixes
Signed-off-by: Stefan Dösinger <stefandoesinger@gmail.com>
---
Changes in v5:
- EDITME: describe what is new in this series revision.
- EDITME: use bulletpoints and terse descriptions.
- Link to v4: https://lore.kernel.org/r/20260416-send-v4-0-e19d02b944ec@gmail.com
---
Stefan Dösinger (8):
ARM: zte: Add zx297520v3 platform support
dt-bindings: arm: Add zx297520v3 board binding
ARM: dts: Add D-Link DWR-932M support
ARM: zte: Add support for zx29 low level debug
ARM: dts: Add an armv7 timer for zx297520v3
amba/serial: amba-pl011: Bring back zx29 UART support
ARM: dts: Declare UARTs on zx297520v3 boards
ARM: defconfig: Add a zx29 defconfig file
Documentation/arch/arm/zte/zx297520v3.rst | 158 +++++++++++++++++++++
Documentation/devicetree/bindings/arm/zte.yaml | 25 ++++
MAINTAINERS | 6 +
arch/arm/Kconfig | 2 +
arch/arm/Kconfig.debug | 12 ++
arch/arm/Makefile | 1 +
arch/arm/boot/dts/Makefile | 1 +
arch/arm/boot/dts/zte/Makefile | 3 +
arch/arm/boot/dts/zte/zx297520v3-dlink-dwr932m.dts | 22 +++
arch/arm/boot/dts/zte/zx297520v3.dtsi | 103 ++++++++++++++
arch/arm/configs/zx29_defconfig | 89 ++++++++++++
arch/arm/include/debug/pl01x.S | 7 +
arch/arm/mach-zte/Kconfig | 26 ++++
arch/arm/mach-zte/Makefile | 2 +
arch/arm/mach-zte/zx297520v3.c | 19 +++
drivers/tty/serial/amba-pl011.c | 42 ++++++
16 files changed, 518 insertions(+)
---
base-commit: 028ef9c96e96197026887c0f092424679298aae8
change-id: 20260416-send-5c08e095e5c9
Best regards,
--
Stefan Dösinger <stefandoesinger@gmail.com>
^ permalink raw reply
* Re: [PATCH v11 2/4] arm64: dts: s32: set Ethernet channel irqs
From: Jared Kangas @ 2026-04-21 20:07 UTC (permalink / raw)
To: jan.petrous
Cc: Andrew Lunn, David S. Miller, Eric Dumazet, Jakub Kicinski,
Paolo Abeni, Maxime Coquelin, Alexandre Torgue, Chester Lin,
Matthias Brugger, Ghennadi Procopciuc, NXP S32 Linux Team,
Shawn Guo, Sascha Hauer, Pengutronix Kernel Team, Fabio Estevam,
Rob Herring, Krzysztof Kozlowski, Conor Dooley, Frank Li, netdev,
linux-stm32, linux-arm-kernel, linux-kernel, imx, devicetree,
rmk+kernel, vladimir.oltean, boon.khai.ng
In-Reply-To: <20260312-dwmac_multi_irq-v11-2-09621ccb040b@oss.nxp.com>
On Thu, Mar 12, 2026 at 09:55:28AM +0100, Jan Petrous via B4 Relay wrote:
> From: "Jan Petrous (OSS)" <jan.petrous@oss.nxp.com>
>
> The GMAC Ethernet controller found on S32G2/S32G3 and S32R45
> contains up to 5 RX and 5 TX channels.
> It can operate in two interrupt modes:
>
> 1) Sharing IRQ mode: only MAC IRQ line is used
> for all channels.
>
> 2) Multiple IRQ mode: every channel uses two IRQ lines,
> one for RX and second for TX.
>
> Specify all IRQ twins for all channels.
>
> Reviewed-by: Matthias Brugger <mbrugger@suse.com>
> Signed-off-by: Jan Petrous (OSS) <jan.petrous@oss.nxp.com>
> ---
Tested the new channels on an S32G-VNP-RDB3 while testing patch 4/4.
Tested-by: Jared Kangas <jkangas@redhat.com>
^ permalink raw reply
* Re: [PATCH v11 4/4] stmmac: s32: enable support for Multi-IRQ mode
From: Jared Kangas @ 2026-04-21 20:02 UTC (permalink / raw)
To: jan.petrous
Cc: Andrew Lunn, David S. Miller, Eric Dumazet, Jakub Kicinski,
Paolo Abeni, Maxime Coquelin, Alexandre Torgue, Chester Lin,
Matthias Brugger, Ghennadi Procopciuc, NXP S32 Linux Team,
Shawn Guo, Sascha Hauer, Pengutronix Kernel Team, Fabio Estevam,
Rob Herring, Krzysztof Kozlowski, Conor Dooley, Frank Li, netdev,
linux-stm32, linux-arm-kernel, linux-kernel, imx, devicetree,
rmk+kernel, vladimir.oltean, boon.khai.ng
In-Reply-To: <20260312-dwmac_multi_irq-v11-4-09621ccb040b@oss.nxp.com>
Hi Jan,
On Thu, Mar 12, 2026 at 09:55:30AM +0100, Jan Petrous via B4 Relay wrote:
> From: "Jan Petrous (OSS)" <jan.petrous@oss.nxp.com>
>
> Based on previous changes in platform driver, the vendor
> glue driver can enable Multi-IRQ mode, if needed.
>
> [...]
>
> If those prerequisites are met, the driver switches to Multi-IRQ mode,
> using per-queue IRQs for rx/tx data pathr:
>
> [ 1.387045] s32-dwmac 4033c000.ethernet: Multi-IRQ mode (per queue IRQs) selected
>
> Now the driver owns all queues IRQs:
>
> root@s32g399aevb3:~# grep eth /proc/interrupts
> 29: 0 0 0 0 0 0 0 0 GICv3 89 Level eth0:mac
> 30: 0 0 0 0 0 0 0 0 GICv3 91 Level eth0:rx-0
> 31: 0 0 0 0 0 0 0 0 GICv3 93 Level eth0:rx-1
> 32: 0 0 0 0 0 0 0 0 GICv3 95 Level eth0:rx-2
> 33: 0 0 0 0 0 0 0 0 GICv3 97 Level eth0:rx-3
> 34: 0 0 0 0 0 0 0 0 GICv3 99 Level eth0:rx-4
> 35: 0 0 0 0 0 0 0 0 GICv3 90 Level eth0:tx-0
> 36: 0 0 0 0 0 0 0 0 GICv3 92 Level eth0:tx-1
> 37: 0 0 0 0 0 0 0 0 GICv3 94 Level eth0:tx-2
> 38: 0 0 0 0 0 0 0 0 GICv3 96 Level eth0:tx-3
> 39: 0 0 0 0 0 0 0 0 GICv3 98 Level eth0:tx-4
I ran this series' changes on an NXP S32G-VNP-RDB3 (dwmac-s32) and
confirmed multichannel TX by doing a basic iperf3 throughput test:
# dmesg | grep Multi-IRQ
[ 37.463467] s32-dwmac 4033c000.ethernet: Multi-IRQ mode (per queue IRQs) selected
# iperf3 -s
[connection logs snipped]
# grep end0 /proc/interrupts | column -t
29: 0 0 0 0 0 0 0 0 GICv3 89 Level end0:mac
30: 968 0 0 0 0 0 0 0 GICv3 90 Level end0:tx-0
31: 0 3 0 0 0 0 0 0 GICv3 92 Level end0:tx-1
32: 0 0 3 0 0 0 0 0 GICv3 94 Level end0:tx-2
33: 0 0 0 3 0 0 0 0 GICv3 96 Level end0:tx-3
34: 0 0 0 0 3 0 0 0 GICv3 98 Level end0:tx-4
35: 67302 0 0 0 0 0 0 0 GICv3 91 Level end0:rx-0
36: 0 0 0 0 0 0 0 0 GICv3 93 Level end0:rx-1
37: 0 0 0 0 0 0 0 0 GICv3 95 Level end0:rx-2
38: 0 0 0 0 0 0 0 0 GICv3 97 Level end0:rx-3
39: 0 0 0 0 0 0 0 0 GICv3 99 Level end0:rx-4
Also tried out multichannel RX by adding 'snps,route-multi-broad' to
rx-queues-config/queue2 in the devicetree, which showed activity on
the corresponding rx-2 entry:
# grep end0 /proc/interrupts | column -t
29: 0 0 0 0 0 0 0 0 GICv3 89 Level end0:mac
30: 4 0 0 0 0 0 0 0 GICv3 90 Level end0:tx-0
31: 0 1 0 0 0 0 0 0 GICv3 92 Level end0:tx-1
32: 0 0 1 0 0 0 0 0 GICv3 94 Level end0:tx-2
33: 0 0 0 0 0 0 0 0 GICv3 96 Level end0:tx-3
34: 0 0 0 0 1 0 0 0 GICv3 98 Level end0:tx-4
35: 68 0 0 0 0 0 0 0 GICv3 91 Level end0:rx-0
36: 0 0 0 0 0 0 0 0 GICv3 93 Level end0:rx-1
37: 0 0 91 0 0 0 0 0 GICv3 95 Level end0:rx-2
38: 0 0 0 0 0 0 0 0 GICv3 97 Level end0:rx-3
39: 0 0 0 0 0 0 0 0 GICv3 99 Level end0:rx-4
I didn't see any regressions with light network usage, and both TX/RX
appear to function as expected.
Tested-by: Jared Kangas <jkangas@redhat.com>
^ permalink raw reply
* Re: [PATCH] Change manual bitfield manipulation to use FIELD_PREP()
From: Mark Brown @ 2026-04-21 19:50 UTC (permalink / raw)
To: Gabriel Jacob Perin
Cc: claudiu.beznea, andrei.simion, lgirdwood, perex, tiwai,
nicolas.ferre, alexandre.belloni, carlos.albmr, linux-sound,
linux-arm-kernel
In-Reply-To: <20260421193113.1060213-1-gabrieljp@usp.br>
[-- Attachment #1: Type: text/plain, Size: 729 bytes --]
On Tue, Apr 21, 2026 at 04:31:13PM -0300, Gabriel Jacob Perin wrote:
> Co-developed-by: Carlos Alberto Marques Rabelo <carlos.albmr@usp.br>
> Signed-off-by: Carlos Alberto Marques Rabelo <carlos.albmr@usp.br>
> Signed-off-by: Gabriel Jacob Perin <gabrieljp@usp.br>
> ---
> sound/soc/atmel/atmel-classd.c | 41 ++++++++++++++++++----------------
> 1 file changed, 22 insertions(+), 19 deletions(-)
Please submit patches using subject lines reflecting the style for the
subsystem, this makes it easier for people to identify relevant patches.
Look at what existing commits in the area you're changing are doing and
make sure your subject lines visually resemble what they're doing.
There's no need to resubmit to fix this alone.
[-- Attachment #2: signature.asc --]
[-- Type: application/pgp-signature, Size: 488 bytes --]
^ permalink raw reply
* [PATCH v3] ASoC: dt-bindings: mediatek: Convert mtk-btcvsd-snd to DT Schema
From: Luca Leonardo Scorcia @ 2026-04-21 19:38 UTC (permalink / raw)
To: linux-sound
Cc: Luca Leonardo Scorcia, Liam Girdwood, Mark Brown, Rob Herring,
Krzysztof Kozlowski, Conor Dooley, Matthias Brugger,
AngeloGioacchino Del Regno, devicetree, linux-kernel,
linux-arm-kernel, linux-mediatek
Convert the mtk-btcvsd-snd.txt DT binding to DT Schema format.
Signed-off-by: Luca Leonardo Scorcia <l.scorcia@gmail.com>
---
Changes in v3:
Sorry about the spam. A second round of dt_binding_check + dtbs_check
led me to additional improvements:
- Use reg-names in place of a non-informative description property
- Simplify the reg property in the example
Changes in v2 [2]:
- Fixed issues from make dt_binding_check
- Set myself as maintainer for the binding
Initial version [1].
[1] https://lore.kernel.org/20260420204514.1640995-1-l.scorcia@gmail.com/
[2] https://lore.kernel.org/20260421154619.227039-1-l.scorcia@gmail.com/
.../sound/mediatek,mtk-btcvsd-snd.yaml | 66 +++++++++++++++++++
.../bindings/sound/mtk-btcvsd-snd.txt | 24 -------
2 files changed, 66 insertions(+), 24 deletions(-)
create mode 100644 Documentation/devicetree/bindings/sound/mediatek,mtk-btcvsd-snd.yaml
delete mode 100644 Documentation/devicetree/bindings/sound/mtk-btcvsd-snd.txt
diff --git a/Documentation/devicetree/bindings/sound/mediatek,mtk-btcvsd-snd.yaml b/Documentation/devicetree/bindings/sound/mediatek,mtk-btcvsd-snd.yaml
new file mode 100644
index 000000000000..22ba7d0bdac6
--- /dev/null
+++ b/Documentation/devicetree/bindings/sound/mediatek,mtk-btcvsd-snd.yaml
@@ -0,0 +1,66 @@
+# SPDX-License-Identifier: (GPL-2.0-only OR BSD-2-Clause)
+%YAML 1.2
+---
+$id: http://devicetree.org/schemas/sound/mediatek,mtk-btcvsd-snd.yaml#
+$schema: http://devicetree.org/meta-schemas/core.yaml#
+
+title: Mediatek ALSA BT SCO CVSD/MSBC Driver
+
+maintainers:
+ - Luca Leonardo Scorcia <l.scorcia@gmail.com>
+
+properties:
+ compatible:
+ const: mediatek,mtk-btcvsd-snd
+
+ reg:
+ minItems: 2
+ maxItems: 2
+
+ reg-names:
+ items:
+ - const: pkv
+ - const: sram-bank2
+
+ interrupts:
+ items:
+ - description: BT-SCO interrupt
+
+ mediatek,infracfg:
+ $ref: /schemas/types.yaml#/definitions/phandle
+ description: The phandle of the infracfg controller
+
+ mediatek,offset:
+ $ref: /schemas/types.yaml#/definitions/uint32-array
+ description: Array of register offsets and masks
+ items:
+ - description: infra_misc_offset
+ - description: infra_conn_bt_cvsd_mask
+ - description: cvsd_mcu_read_offset
+ - description: cvsd_mcu_write_offset
+ - description: cvsd_packet_indicator_offset
+
+required:
+ - compatible
+ - reg
+ - reg-names
+ - interrupts
+ - mediatek,infracfg
+ - mediatek,offset
+
+additionalProperties: false
+
+examples:
+ - |
+ #include <dt-bindings/interrupt-controller/arm-gic.h>
+ #include <dt-bindings/interrupt-controller/irq.h>
+
+ mtk-btcvsd-snd@18000000 {
+ compatible = "mediatek,mtk-btcvsd-snd";
+ reg = <0x18000000 0x1000>,
+ <0x18080000 0x8000>;
+ reg-names = "pkv", "sram-bank2";
+ interrupts = <GIC_SPI 286 IRQ_TYPE_LEVEL_LOW>;
+ mediatek,infracfg = <&infrasys>;
+ mediatek,offset = <0xf00 0x800 0xfd0 0xfd4 0xfd8>;
+ };
diff --git a/Documentation/devicetree/bindings/sound/mtk-btcvsd-snd.txt b/Documentation/devicetree/bindings/sound/mtk-btcvsd-snd.txt
deleted file mode 100644
index 679e44839b48..000000000000
--- a/Documentation/devicetree/bindings/sound/mtk-btcvsd-snd.txt
+++ /dev/null
@@ -1,24 +0,0 @@
-Mediatek ALSA BT SCO CVSD/MSBC Driver
-
-Required properties:
-- compatible = "mediatek,mtk-btcvsd-snd";
-- reg: register location and size of PKV and SRAM_BANK2
-- interrupts: should contain BTSCO interrupt
-- mediatek,infracfg: the phandles of INFRASYS
-- mediatek,offset: Array contains of register offset and mask
- infra_misc_offset,
- infra_conn_bt_cvsd_mask,
- cvsd_mcu_read_offset,
- cvsd_mcu_write_offset,
- cvsd_packet_indicator_offset
-
-Example:
-
- mtk-btcvsd-snd@18000000 {
- compatible = "mediatek,mtk-btcvsd-snd";
- reg=<0 0x18000000 0 0x1000>,
- <0 0x18080000 0 0x8000>;
- interrupts = <GIC_SPI 286 IRQ_TYPE_LEVEL_LOW>;
- mediatek,infracfg = <&infrasys>;
- mediatek,offset = <0xf00 0x800 0xfd0 0xfd4 0xfd8>;
- };
--
2.43.0
^ permalink raw reply related
* [PATCH] Change manual bitfield manipulation to use FIELD_PREP()
From: Gabriel Jacob Perin @ 2026-04-21 19:31 UTC (permalink / raw)
To: claudiu.beznea, andrei.simion, lgirdwood, broonie, perex, tiwai,
nicolas.ferre, alexandre.belloni
Cc: carlos.albmr, Gabriel Jacob Perin, linux-sound, linux-arm-kernel
Co-developed-by: Carlos Alberto Marques Rabelo <carlos.albmr@usp.br>
Signed-off-by: Carlos Alberto Marques Rabelo <carlos.albmr@usp.br>
Signed-off-by: Gabriel Jacob Perin <gabrieljp@usp.br>
---
sound/soc/atmel/atmel-classd.c | 41 ++++++++++++++++++----------------
1 file changed, 22 insertions(+), 19 deletions(-)
diff --git a/sound/soc/atmel/atmel-classd.c b/sound/soc/atmel/atmel-classd.c
index 1f8c60d2d..6693bdcbb 100644
--- a/sound/soc/atmel/atmel-classd.c
+++ b/sound/soc/atmel/atmel-classd.c
@@ -11,6 +11,7 @@
#include <linux/module.h>
#include <linux/platform_device.h>
#include <linux/regmap.h>
+#include <linux/bitfield.h>
#include <linux/string_choices.h>
#include <sound/core.h>
#include <sound/dmaengine_pcm.h>
@@ -236,34 +237,34 @@ static int atmel_classd_component_probe(struct snd_soc_component *component)
u32 mask, val;
mask = CLASSD_MR_PWMTYP_MASK;
- val = pdata->pwm_type << CLASSD_MR_PWMTYP_SHIFT;
+ val = FIELD_PREP(CLASSD_MR_PWMTYP_MASK, pdata->pwm_type);
mask |= CLASSD_MR_NON_OVERLAP_MASK;
if (pdata->non_overlap_enable) {
- val |= (CLASSD_MR_NON_OVERLAP_EN
- << CLASSD_MR_NON_OVERLAP_SHIFT);
+ val |= FIELD_PREP(CLASSD_MR_NON_OVERLAP_MASK,
+ CLASSD_MR_NON_OVERLAP_EN);
mask |= CLASSD_MR_NOVR_VAL_MASK;
switch (pdata->non_overlap_time) {
case 5:
- val |= (CLASSD_MR_NOVR_VAL_5NS
- << CLASSD_MR_NOVR_VAL_SHIFT);
+ val |= FIELD_PREP(CLASSD_MR_NOVR_VAL_MASK,
+ CLASSD_MR_NOVR_VAL_5NS);
break;
case 10:
- val |= (CLASSD_MR_NOVR_VAL_10NS
- << CLASSD_MR_NOVR_VAL_SHIFT);
+ val |= FIELD_PREP(CLASSD_MR_NOVR_VAL_MASK,
+ CLASSD_MR_NOVR_VAL_10NS);
break;
case 15:
- val |= (CLASSD_MR_NOVR_VAL_15NS
- << CLASSD_MR_NOVR_VAL_SHIFT);
+ val |= FIELD_PREP(CLASSD_MR_NOVR_VAL_MASK,
+ CLASSD_MR_NOVR_VAL_15NS);
break;
case 20:
- val |= (CLASSD_MR_NOVR_VAL_20NS
- << CLASSD_MR_NOVR_VAL_SHIFT);
+ val |= FIELD_PREP(CLASSD_MR_NOVR_VAL_MASK,
+ CLASSD_MR_NOVR_VAL_20NS);
break;
default:
- val |= (CLASSD_MR_NOVR_VAL_10NS
- << CLASSD_MR_NOVR_VAL_SHIFT);
+ val |= FIELD_PREP(CLASSD_MR_NOVR_VAL_MASK,
+ CLASSD_MR_NOVR_VAL_10NS);
dev_warn(component->dev,
"non-overlapping value %d is invalid, the default value 10 is specified\n",
pdata->non_overlap_time);
@@ -370,8 +371,10 @@ atmel_classd_cpu_dai_hw_params(struct snd_pcm_substream *substream,
return ret;
mask = CLASSD_INTPMR_DSP_CLK_FREQ_MASK | CLASSD_INTPMR_FRAME_MASK;
- val = (sample_rates[best].dsp_clk << CLASSD_INTPMR_DSP_CLK_FREQ_SHIFT)
- | (sample_rates[best].sample_rate << CLASSD_INTPMR_FRAME_SHIFT);
+ val = FIELD_PREP(CLASSD_INTPMR_DSP_CLK_FREQ_MASK,
+ sample_rates[best].dsp_clk) |
+ FIELD_PREP(CLASSD_INTPMR_FRAME_MASK,
+ sample_rates[best].sample_rate);
snd_soc_component_update_bits(component, CLASSD_INTPMR, mask, val);
@@ -395,8 +398,8 @@ static int atmel_classd_cpu_dai_prepare(struct snd_pcm_substream *substream,
snd_soc_component_update_bits(component, CLASSD_MR,
CLASSD_MR_LEN_MASK | CLASSD_MR_REN_MASK,
- (CLASSD_MR_LEN_DIS << CLASSD_MR_LEN_SHIFT)
- |(CLASSD_MR_REN_DIS << CLASSD_MR_REN_SHIFT));
+ FIELD_PREP(CLASSD_MR_LEN_MASK, CLASSD_MR_LEN_DIS) |
+ FIELD_PREP(CLASSD_MR_REN_MASK, CLASSD_MR_REN_DIS));
return 0;
}
@@ -418,8 +421,8 @@ static int atmel_classd_cpu_dai_trigger(struct snd_pcm_substream *substream,
case SNDRV_PCM_TRIGGER_STOP:
case SNDRV_PCM_TRIGGER_SUSPEND:
case SNDRV_PCM_TRIGGER_PAUSE_PUSH:
- val = (CLASSD_MR_LEN_DIS << CLASSD_MR_LEN_SHIFT)
- | (CLASSD_MR_REN_DIS << CLASSD_MR_REN_SHIFT);
+ val = FIELD_PREP(CLASSD_MR_LEN_MASK, CLASSD_MR_LEN_DIS) |
+ FIELD_PREP(CLASSD_MR_REN_MASK, CLASSD_MR_REN_DIS);
break;
default:
return -EINVAL;
--
2.25.1
^ permalink raw reply related
* Re: [PATCH] dt-bindings: Remove the redundant 'type: boolean'
From: Rob Herring (Arm) @ 2026-04-21 18:41 UTC (permalink / raw)
To: phucduc.bui
Cc: linusw, zyw, zhangqing, devicetree, alexandre.belloni, heiko,
gene_chen, linux-input, nick, dmitry.torokhov, gregkh,
claudiu.beznea, linux-arm-kernel, linux-usb, nicolas.ferre,
conor+dt, krzk+dt, lee
In-Reply-To: <20260417021858.6582-1-phucduc.bui@gmail.com>
On Fri, 17 Apr 2026 09:18:58 +0700, phucduc.bui@gmail.com wrote:
> From: bui duc phuc <phucduc.bui@gmail.com>
>
> The 'wakeup-source' property already has its type defined in the core
> schema. Remove the redundant 'type: boolean' from the binding file to
> clean up the binding files.
>
> Signed-off-by: bui duc phuc <phucduc.bui@gmail.com>
> ---
> Documentation/devicetree/bindings/input/atmel,maxtouch.yaml | 3 +--
> Documentation/devicetree/bindings/mfd/rockchip,rk816.yaml | 3 +--
> Documentation/devicetree/bindings/usb/richtek,rt1711h.yaml | 3 +--
> 3 files changed, 3 insertions(+), 6 deletions(-)
>
Applied, thanks!
^ permalink raw reply
* Re: [PATCH v7 2/3] dt-bindings: mfd: aspeed,ast2x00-scu: Describe AST2700 SCU0
From: Rob Herring @ 2026-04-21 18:39 UTC (permalink / raw)
To: Billy Tsai
Cc: Lee Jones, Krzysztof Kozlowski, Conor Dooley, Joel Stanley,
Andrew Jeffery, Linus Walleij, Bartosz Golaszewski, Ryan Chen,
Andrew Jeffery, devicetree, linux-arm-kernel, linux-aspeed,
linux-kernel, openbmc, linux-gpio, linux-clk
In-Reply-To: <20260416-upstream_pinctrl-v7-2-d72762253163@aspeedtech.com>
On Thu, Apr 16, 2026 at 03:29:44PM +0800, Billy Tsai wrote:
> AST2700 consists of two interconnected SoC instances, each with its own
> System Control Unit (SCU). The SCU0 provides pin control, interrupt
> controllers, clocks, resets, and address-space mappings for the
> Secondary and Tertiary Service Processors (SSP and TSP).
>
> Describe the SSP/TSP address mappings using the standard
> memory-region and memory-region-names properties.
>
> Disallow legacy child nodes that are not present on AST2700, including
> p2a-control and smp-memram. The latter is unnecessary as software can
> access the scratch registers via the SCU syscon.
>
> Also allow the AST2700 SoC0 pin controller to be described as a child
> node of the SCU0, and add an example illustrating the SCU0 layout,
> including reserved-memory, interrupt controllers, and pinctrl.
>
> Signed-off-by: Billy Tsai <billy_tsai@aspeedtech.com>
> ---
> .../bindings/mfd/aspeed,ast2x00-scu.yaml | 113 +++++++++++++++++++++
> 1 file changed, 113 insertions(+)
>
> diff --git a/Documentation/devicetree/bindings/mfd/aspeed,ast2x00-scu.yaml b/Documentation/devicetree/bindings/mfd/aspeed,ast2x00-scu.yaml
> index a87f31fce019..215ff59b38ea 100644
> --- a/Documentation/devicetree/bindings/mfd/aspeed,ast2x00-scu.yaml
> +++ b/Documentation/devicetree/bindings/mfd/aspeed,ast2x00-scu.yaml
> @@ -46,6 +46,17 @@ properties:
> '#reset-cells':
> const: 1
>
> + memory-region:
> + items:
> + - description: Region mapped through the first SSP address window.
> + - description: Region mapped through the second SSP address window.
> + - description: Region mapped through the TSP address window.
blank line
> + memory-region-names:
> + items:
> + - const: ssp-0
> + - const: ssp-1
> + - const: tsp
> +
> patternProperties:
> '^p2a-control@[0-9a-f]+$':
> description: >
> @@ -87,6 +98,7 @@ patternProperties:
> - aspeed,ast2400-pinctrl
> - aspeed,ast2500-pinctrl
> - aspeed,ast2600-pinctrl
> + - aspeed,ast2700-soc0-pinctrl
>
> required:
> - compatible
> @@ -156,6 +168,30 @@ required:
> - '#clock-cells'
> - '#reset-cells'
>
> +allOf:
> + - if:
> + properties:
> + compatible:
> + contains:
> + anyOf:
> + - const: aspeed,ast2700-scu0
> + - const: aspeed,ast2700-scu1
More simply expressed as:
contains:
enum:
- aspeed,ast2700-scu0
- aspeed,ast2700-scu1
> + then:
> + patternProperties:
> + '^p2a-control@[0-9a-f]+$': false
> + '^smp-memram@[0-9a-f]+$': false
^ permalink raw reply
* Re: tpm: spi: do not call blocking ops when !TASK_RUNNING; during shutdown
From: Jarkko Sakkinen @ 2026-04-21 18:28 UTC (permalink / raw)
To: Peng Fan
Cc: Stefan Wahren, Peter Huewe, Jason Gunthorpe,
linux-arm-kernel@lists.infradead.org,
linux-integrity@vger.kernel.org, kernel@pengutronix.de, Frank Li,
Sascha Hauer, imx@lists.linux.dev
In-Reply-To: <PAXPR04MB84598325136E394E0A7D94D6882C2@PAXPR04MB8459.eurprd04.prod.outlook.com>
On Tue, Apr 21, 2026 at 09:04:43AM +0000, Peng Fan wrote:
> > Subject: tpm: spi: do not call blocking ops when !TASK_RUNNING;
> > during shutdown
> >
> > Hi,
> > we use a custom i.MX93 board, which based on Phytec Phycore i.MX93
> > with a TPM connected via SPI. If I enable
> > CONFIG_DEBUG_ATOMIC_SLEEP=y in our kernel config with mainline
> > kernel 6.18.23 and reboot our board, I will get the following warning:
> > ffff0000000d8000
>
> The issue seems at drivers/char/tpm/tpm_tis_core.c
> 94 rc = wait_event_interruptible_timeout(*queue,
> 95 wait_for_tpm_stat_cond(chip, sts_mask, check_cancel,
> 96 &canceled),
> 97 timeout);
>
> wait_event_interruptible_timeout set task to !TASK_RUNNING,
> but wait_for_tpm_stat_cond still calls into mutex_lock.
>
> Regards
> Peng
>
> > [ 43.422135] Call trace:
> > [ 43.424570] __might_sleep+0x74/0x7c (P)
> > [ 43.428487] mutex_lock+0x24/0x80
> > [ 43.431797] spi_bus_lock+0x20/0x50
> > [ 43.435281] tpm_tis_spi_transfer_full+0x70/0x2c4
> > [ 43.439979] tpm_tis_spi_read_bytes+0x3c/0x48
> > [ 43.444321] tpm_tis_status+0x58/0xf8
> > [ 43.447978] wait_for_tpm_stat_cond+0x30/0x90
> > [ 43.452329] wait_for_tpm_stat+0x1cc/0x2e0
> > [ 43.456419] tpm_tis_send_data+0xdc/0x334
> > [ 43.460423] tpm_tis_send_main+0x74/0x160
> > [ 43.464427] tpm_tis_send+0xd4/0x13c
> > [ 43.467998] tpm_transmit+0xc4/0x3c4
> > [ 43.471569] tpm_transmit_cmd+0x38/0xd4
> > [ 43.475399] tpm2_shutdown+0x6c/0xa4
> > [ 43.478970] tpm_class_shutdown+0x60/0x88
> > [ 43.482974] device_shutdown+0x130/0x25c
> > [ 43.486891] kernel_restart+0x44/0xa4
> > [ 43.490549] __do_sys_reboot+0x114/0x254
> > [ 43.494466] __arm64_sys_reboot+0x24/0x30
> > [ 43.498470] invoke_syscall+0x48/0x10c
> > [ 43.502214] el0_svc_common.constprop.0+0x40/0xe0
> > [ 43.506911] do_el0_svc+0x1c/0x28
> > [ 43.510222] el0_svc+0x34/0xec
> > [ 43.513273] el0t_64_sync_handler+0xa0/0xe4
> > [ 43.517441] el0t_64_sync+0x198/0x19c
> >
> > Best regards
On travel this week but thanks for the report. Investigating next weeek
In the meantime, patches are welcome (whcih I will review next week).
Br, Jarkko
^ permalink raw reply
* [PATCH/RFC 14/14] arm64: dts: renesas: ironhide: Add CPG/MDLC firmware properties
From: Geert Uytterhoeven @ 2026-04-21 18:11 UTC (permalink / raw)
To: Sudeep Holla, Cristian Marussi, Rob Herring, Krzysztof Kozlowski,
Conor Dooley, Magnus Damm, Saravana Kannan, Michael Turquette,
Stephen Boyd, Philipp Zabel, Ulf Hansson, Rafael J . Wysocki,
Kevin Hilman, Florian Fainelli, Wolfram Sang, Marek Vasut,
Kuninori Morimoto
Cc: arm-scmi, linux-arm-kernel, linux-renesas-soc, linux-clk,
devicetree, linux-pm, linux-kernel, Geert Uytterhoeven
In-Reply-To: <cover.1776793163.git.geert+renesas@glider.be>
Link the various Clock Pulse Generator (CPG) and Module Controller
(MDLC) device nodes to their SCMI provider.
Signed-off-by: Geert Uytterhoeven <geert+renesas@glider.be>
---
.../boot/dts/renesas/r8a78000-ironhide.dts | 116 ++++++++++++++++++
1 file changed, 116 insertions(+)
diff --git a/arch/arm64/boot/dts/renesas/r8a78000-ironhide.dts b/arch/arm64/boot/dts/renesas/r8a78000-ironhide.dts
index 2fb9557a7eb9dbb7..c6d1a9b5ba433c54 100644
--- a/arch/arm64/boot/dts/renesas/r8a78000-ironhide.dts
+++ b/arch/arm64/boot/dts/renesas/r8a78000-ironhide.dts
@@ -99,6 +99,10 @@ memory@1e00000000 {
};
};
+&cpg {
+ firmware = <&scmi>;
+};
+
&extal_clk {
clock-frequency = <16666600>;
};
@@ -112,6 +116,118 @@ &hscif0 {
status = "okay";
};
+&mdlc_aon {
+ firmware = <&scmi>;
+};
+
+&mdlc_cmnn {
+ firmware = <&scmi>;
+};
+
+&mdlc_cmns {
+ firmware = <&scmi>;
+};
+
+&mdlc_ddr0 {
+ firmware = <&scmi>;
+};
+
+&mdlc_ddr1 {
+ firmware = <&scmi>;
+};
+
+&mdlc_ddr2 {
+ firmware = <&scmi>;
+};
+
+&mdlc_ddr3 {
+ firmware = <&scmi>;
+};
+
+&mdlc_ddr4 {
+ firmware = <&scmi>;
+};
+
+&mdlc_ddr5 {
+ firmware = <&scmi>;
+};
+
+&mdlc_ddr6 {
+ firmware = <&scmi>;
+};
+
+&mdlc_ddr7 {
+ firmware = <&scmi>;
+};
+
+&mdlc_dsp {
+ firmware = <&scmi>;
+};
+
+&mdlc_gpc {
+ firmware = <&scmi>;
+};
+
+&mdlc_hscn {
+ firmware = <&scmi>;
+};
+
+&mdlc_hscs {
+ firmware = <&scmi>;
+};
+
+&mdlc_imn {
+ firmware = <&scmi>;
+};
+
+&mdlc_ims {
+ firmware = <&scmi>;
+};
+
+&mdlc_mm {
+ firmware = <&scmi>;
+};
+
+&mdlc_npu0 {
+ firmware = <&scmi>;
+};
+
+&mdlc_npu1 {
+ firmware = <&scmi>;
+};
+
+&mdlc_pere {
+ firmware = <&scmi>;
+};
+
+&mdlc_perw {
+ firmware = <&scmi>;
+};
+
+&mdlc_rt {
+ firmware = <&scmi>;
+};
+
+&mdlc_scp {
+ firmware = <&scmi>;
+};
+
+&mdlc_top {
+ firmware = <&scmi>;
+};
+
+&mdlc_vio {
+ firmware = <&scmi>;
+};
+
+&mdlc_vipn {
+ firmware = <&scmi>;
+};
+
+&mdlc_vips {
+ firmware = <&scmi>;
+};
+
&mfis_scp {
status = "okay";
};
--
2.43.0
^ permalink raw reply related
* [PATCH/RFC 12/14] pmdomain: renesas: Add R-Car X5H MDLC SCMI remapping driver
From: Geert Uytterhoeven @ 2026-04-21 18:11 UTC (permalink / raw)
To: Sudeep Holla, Cristian Marussi, Rob Herring, Krzysztof Kozlowski,
Conor Dooley, Magnus Damm, Saravana Kannan, Michael Turquette,
Stephen Boyd, Philipp Zabel, Ulf Hansson, Rafael J . Wysocki,
Kevin Hilman, Florian Fainelli, Wolfram Sang, Marek Vasut,
Kuninori Morimoto
Cc: arm-scmi, linux-arm-kernel, linux-renesas-soc, linux-clk,
devicetree, linux-pm, linux-kernel, Geert Uytterhoeven
In-Reply-To: <cover.1776793163.git.geert+renesas@glider.be>
Add a proof-of-concept Module Controller driver for the R-Car X5H
(R8A78000) SoC, using tables to remap from hardware power domain,
module, and reset IDs to SCMI power domains, clocks, and resets.
Note that SCMI clocks representing hardware modules are fake clocks,
with a zero clock rate, that can just be enabled and disabled.
Hence these are controlled from the clock domain's start/stop callbacks.
For now this contains preliminary support for SCP FW SDKv4.28.0,
v4.31.0, and v4.32.0:
- As the SCMI power domain IDs are idential for all three versions,
r8a78000_mdlc_*_power_fw_4_28_0[] apply to all of them,
- As the SCMI clock and reset IDs are identical for the last two
versions (except for the addition of two reset IDs in v4.32.0),
r8a78000_mdlc_fw_4_31_0[] applies to both of them.
Note that v4.32 has two new reset IDs without corresponding clock IDs,
so "/* SCMI clock and reset IDs are identical */" is no longer 100%
true. However, these new resets seem to be meant for board control, not
SoC control.
Suggested-by: Marek Vasut <marek.vasut+renesas@mailbox.org>
Signed-off-by: Geert Uytterhoeven <geert+renesas@glider.be>
---
drivers/pmdomain/renesas/Kconfig | 4 +
drivers/pmdomain/renesas/Makefile | 1 +
drivers/pmdomain/renesas/r8a78000-mdlc.c | 1021 ++++++++++++++++++++++
drivers/soc/renesas/Kconfig | 1 +
4 files changed, 1027 insertions(+)
create mode 100644 drivers/pmdomain/renesas/r8a78000-mdlc.c
diff --git a/drivers/pmdomain/renesas/Kconfig b/drivers/pmdomain/renesas/Kconfig
index b507c3e0d723efc6..f2f52d3c29a083f1 100644
--- a/drivers/pmdomain/renesas/Kconfig
+++ b/drivers/pmdomain/renesas/Kconfig
@@ -13,6 +13,10 @@ config SYSC_RMOBILE
bool "System Controller support for R-Mobile" if COMPILE_TEST
# SoC
+config MDLC_R8A78000
+ bool "Module Controller support for R8A78000 (R-Car X5H)" if COMPILE_TEST
+ select RESET_CONTROLLER
+
config SYSC_R8A7742
bool "System Controller support for R8A7742 (RZ/G1H)" if COMPILE_TEST
select SYSC_RCAR
diff --git a/drivers/pmdomain/renesas/Makefile b/drivers/pmdomain/renesas/Makefile
index 0391e6e67440a786..17849aad37a5ac4f 100644
--- a/drivers/pmdomain/renesas/Makefile
+++ b/drivers/pmdomain/renesas/Makefile
@@ -1,5 +1,6 @@
# SPDX-License-Identifier: GPL-2.0
# SoC
+obj-$(CONFIG_MDLC_R8A78000) += r8a78000-mdlc.o
obj-$(CONFIG_SYSC_R8A7742) += r8a7742-sysc.o
obj-$(CONFIG_SYSC_R8A7743) += r8a7743-sysc.o
obj-$(CONFIG_SYSC_R8A7745) += r8a7745-sysc.o
diff --git a/drivers/pmdomain/renesas/r8a78000-mdlc.c b/drivers/pmdomain/renesas/r8a78000-mdlc.c
new file mode 100644
index 0000000000000000..74d2509657e97dbf
--- /dev/null
+++ b/drivers/pmdomain/renesas/r8a78000-mdlc.c
@@ -0,0 +1,1021 @@
+// SPDX-License-Identifier: GPL-2.0
+/*
+ * R-Car X5H Module Controller
+ *
+ * Copyright (C) 2026 Glider bv
+ */
+
+#include <linux/cleanup.h>
+#include <linux/clk.h>
+#include <linux/dev_printk.h>
+#include <linux/module.h>
+#include <linux/mod_devicetable.h>
+#include <linux/of.h>
+#include <linux/platform_device.h>
+#include <linux/pm_clock.h>
+#include <linux/pm_domain.h>
+#include <linux/reset-controller.h>
+#include <linux/scmi_protocol.h>
+#include <linux/slab.h>
+
+#include <dt-bindings/power/renesas,r8a78000-mdlc.h>
+
+struct power_map_in {
+ int hw_id; /* Hardware power domain ID */
+ u32 fw_id; /* SCMI firmware power domain ID */
+};
+
+struct power_map {
+ int hw_id; /* Hardware power domain ID */
+ u32 fw_id; /* SCMI firmware power domain ID */
+ struct generic_pm_domain *genpd;
+};
+
+struct mod_map {
+ int hw_id; /* Hardware module ID */
+ u32 fw_id; /* SCMI clock and reset IDs are identical */
+};
+
+struct r8a78000_mdlc_info {
+ u32 base;
+ const struct power_map_in *power_map;
+ const struct mod_map *mod_map;
+};
+
+struct fw_map {
+ u32 impl_ver;
+ const struct r8a78000_mdlc_info *info;
+};
+
+/**
+ * struct r8a78000_mdlc_priv - Module Controller Private Data
+ *
+ * @link: Link into list of MDLC instances
+ * @genpd_data: PM domain provider data
+ * @rcdev: Reset controller entity
+ * @dev: MDLC device
+ * @np: Device node in DT representing the MDLC
+ * @scmi_power_np: Device node in DT for the SCMI firmware power protocol
+ * @scmi_clk_np: Device node in DT for the SCMI firmware clock protocol
+ * @scmi_reset_np: Device node in DT for the SCMI firmware reset protocol
+ * @scmi_rcdev: SCMI reset controller entity
+ * @power_map: Mapping from hardware power domain IDs to SCMI power domains
+ * @mod_map: Mapping from hardware module IDs to SCMI clocks and resets
+ */
+struct r8a78000_mdlc_priv {
+ struct hlist_node link;
+ struct genpd_onecell_data genpd_data;
+ struct reset_controller_dev rcdev;
+ struct device *dev;
+ struct device_node *np;
+ struct device_node *scmi_power_np;
+ struct device_node *scmi_clk_np;
+ struct device_node *scmi_reset_np;
+ struct reset_controller_dev *scmi_rcdev;
+ const struct power_map *power_map;
+ const struct mod_map *mod_map;
+};
+
+static struct generic_pm_domain *r8a78000_genpd_always_on;
+static HLIST_HEAD(r8a78000_mdlc_list);
+static DEFINE_MUTEX(r8a78000_mdlc_lock); /* protects the two above */
+
+static const struct power_map *power_map_find(const struct power_map *map,
+ u32 id)
+{
+ if (!map)
+ return NULL;
+
+ for (; map->hw_id >= 0; map++) {
+ if (map->hw_id == id)
+ return map;
+ }
+
+ return NULL;
+}
+
+static struct generic_pm_domain *r8a78000_genpd_xlate(
+ const struct of_phandle_args *spec, void *data)
+{
+ struct r8a78000_mdlc_priv *priv = container_of(data,
+ struct r8a78000_mdlc_priv, genpd_data);
+ struct generic_pm_domain *genpd;
+ struct device *dev = priv->dev;
+ const struct power_map *map;
+ u32 id;
+
+ if (spec->args_count != 2)
+ return ERR_PTR(-EINVAL);
+
+ id = spec->args[0];
+
+ if (id >= R8A78000_MDLC_PD_AON) {
+ dev_dbg(dev, "Mapping HW power domain %u to always-on domain\n",
+ id);
+ return r8a78000_genpd_always_on;
+ }
+
+ map = power_map_find(priv->power_map, id);
+ if (!map) {
+ dev_err(dev, "Unknown power domain %u\n", id);
+ return ERR_PTR(-ENOENT);
+ }
+
+ dev_dbg(dev, "Mapping HW power domain %u to SCMI power domain %u\n", id,
+ map->fw_id);
+
+ genpd = map->genpd;
+
+ return genpd;
+}
+
+#define rcdev_to_priv(_rcdev) \
+ container_of(_rcdev, struct r8a78000_mdlc_priv, rcdev)
+
+static const struct mod_map *mod_map_find(const struct mod_map *map, u32 id)
+{
+ if (!map)
+ return NULL;
+
+ for (; map->hw_id >= 0; map++) {
+ if (map->hw_id == id)
+ return map;
+ }
+
+ return NULL;
+}
+
+static int r8a78000_mdlc_reset_xlate(struct reset_controller_dev *rcdev,
+ const struct of_phandle_args *spec)
+{
+ struct r8a78000_mdlc_priv *priv = rcdev_to_priv(rcdev);
+ struct device *dev = priv->dev;
+ const struct mod_map *map;
+ u32 id;
+
+ if (spec->args_count != 1)
+ return -EINVAL;
+
+ id = spec->args[0];
+
+ map = mod_map_find(priv->mod_map, id);
+ if (!map) {
+ dev_err(dev, "Unknown reset %u\n", id);
+ return -ENOENT;
+ }
+
+ dev_dbg(dev, "Mapping HW reset %u to SCMI reset %u\n", id, map->fw_id);
+
+ return map->fw_id;
+}
+
+#define DEFINE_MDLC_RESET_WRAPPER(op) \
+ static int r8a78000_mdlc_ ## op(struct reset_controller_dev *rcdev, \
+ unsigned long id) \
+ { \
+ struct r8a78000_mdlc_priv *priv = rcdev_to_priv(rcdev); \
+ int ret; \
+ \
+ if (!priv->scmi_rcdev->ops->op) \
+ return -ENOTSUPP; \
+ \
+ ret = priv->scmi_rcdev->ops->op(priv->scmi_rcdev, id); \
+ if (ret == -EOPNOTSUPP) \
+ dev_dbg(priv->dev, \
+ "%s: Ignoring unsupported reset %lu\n", \
+ __func__, id); \
+ return ret == -EOPNOTSUPP ? 0 : ret; \
+ }
+
+DEFINE_MDLC_RESET_WRAPPER(reset)
+DEFINE_MDLC_RESET_WRAPPER(assert)
+DEFINE_MDLC_RESET_WRAPPER(deassert)
+DEFINE_MDLC_RESET_WRAPPER(status)
+
+static const struct reset_control_ops r8a78000_mdlc_reset_ops = {
+ .reset = r8a78000_mdlc_reset,
+ .assert = r8a78000_mdlc_assert,
+ .deassert = r8a78000_mdlc_deassert,
+ .status = r8a78000_mdlc_status,
+};
+
+static struct device_node *scmi_find_proto(struct device_node *scmi, u32 proto)
+{
+ for_each_available_child_of_node_scoped(scmi, child) {
+ u32 reg;
+
+ if (of_property_read_u32(child, "reg", ®))
+ continue;
+
+ if (reg == proto)
+ return_ptr(child);
+ }
+
+ return NULL;
+}
+
+static int r8a78000_mdlc_attach_dev(struct generic_pm_domain *domain,
+ struct device *dev)
+{
+ struct of_phandle_args pd_spec, scmi_spec;
+ struct device_node *np = dev->of_node;
+ struct r8a78000_mdlc_priv *priv;
+ const struct mod_map *map;
+ unsigned int id;
+ struct clk *clk;
+ int ret;
+
+ ret = of_parse_phandle_with_args(np, "power-domains",
+ "#power-domain-cells", 0, &pd_spec);
+ if (ret < 0)
+ return ret;
+
+ if (pd_spec.args_count != 2) {
+ of_node_put(pd_spec.np);
+ return -EINVAL;
+ }
+
+ scoped_guard(mutex, &r8a78000_mdlc_lock) {
+ hlist_for_each_entry(priv, &r8a78000_mdlc_list, link) {
+ if (priv->np == pd_spec.np)
+ break;
+ }
+ }
+
+ if (!priv) {
+ dev_err(dev, "%s: MDLC %pOF not found\n", __func__, pd_spec.np);
+ of_node_put(pd_spec.np);
+ return -ENODEV;
+ }
+
+ id = pd_spec.args[1];
+ of_node_put(pd_spec.np);
+
+ map = mod_map_find(priv->mod_map, id);
+ if (!map) {
+ dev_err(dev, "Unknown module %u\n", id);
+ return -ENOENT;
+ }
+
+ dev_dbg(dev, "Mapping HW module %u to SCMI clock %u\n", id, map->fw_id);
+
+ scmi_spec.np = priv->scmi_clk_np;
+ scmi_spec.args_count = 1;
+ scmi_spec.args[0] = map->fw_id;
+
+ clk = of_clk_get_from_provider(&scmi_spec);
+ if (IS_ERR(clk)) {
+ dev_err(dev, "Cannot get SCMI clock %u: %pe\n", map->fw_id,
+ clk);
+ return PTR_ERR(clk);
+ }
+
+ dev_dbg(dev, "SCMI clock %u is %pC\n", map->fw_id, clk);
+
+ if (!clk) {
+ /* Ignore missing SCMI module clocks */
+ return 0;
+ }
+
+ ret = pm_clk_create(dev);
+ if (ret)
+ goto fail_put;
+
+ ret = pm_clk_add_clk(dev, clk);
+ if (ret)
+ goto fail_destroy;
+
+ return 0;
+
+fail_destroy:
+ pm_clk_destroy(dev);
+fail_put:
+ clk_put(clk);
+ return ret;
+}
+
+static void r8a78000_mdlc_detach_dev(struct generic_pm_domain *domain,
+ struct device *dev)
+{
+ if (!pm_clk_no_clocks(dev))
+ pm_clk_destroy(dev);
+}
+
+static const struct power_map *fill_power_map(struct r8a78000_mdlc_priv *priv,
+ const struct power_map_in *map_in)
+{
+ struct of_phandle_args scmi_spec;
+ struct generic_pm_domain *genpd;
+ struct device *dev = priv->dev;
+ struct power_map *map;
+ unsigned int i;
+
+ if (!map_in)
+ return NULL;
+
+ for (i = 0; map_in[i].hw_id >= 0; i++) { }
+
+ map = devm_kcalloc(dev, i + 1, sizeof(*map), GFP_KERNEL);
+ if (!map)
+ return ERR_PTR(-ENOMEM);
+
+ for (i = 0; ; i++) {
+ map[i].hw_id = map_in[i].hw_id;
+ if (map[i].hw_id < 0)
+ break;
+
+ map[i].fw_id = map_in[i].fw_id;
+
+ scmi_spec.np = priv->scmi_power_np;
+ scmi_spec.args_count = 1;
+ scmi_spec.args[0] = map[i].fw_id;
+
+ genpd = genpd_get_from_provider(&scmi_spec);
+ if (IS_ERR(genpd))
+ return dev_err_cast_probe(dev, genpd,
+ "Failed to get SCMI power domain %u\n",
+ map[i].fw_id);
+
+ dev_dbg(dev, "SCMI power domain %u is %s\n", map[i].fw_id,
+ genpd->name);
+
+ map[i].genpd = genpd;
+
+ /* Hook up clock domain support */
+ genpd->attach_dev = r8a78000_mdlc_attach_dev;
+ genpd->detach_dev = r8a78000_mdlc_detach_dev;
+ /* Setting flags this late has no impact, but does not hurt */
+ genpd->flags |= GENPD_FLAG_PM_CLK;
+ genpd->dev_ops.stop = pm_clk_suspend;
+ genpd->dev_ops.start = pm_clk_resume;
+ }
+
+ return map;
+}
+
+static void r8a78000_mdlc_unlink(void *data)
+{
+ struct r8a78000_mdlc_priv *priv = data;
+
+ scoped_guard(mutex, &r8a78000_mdlc_lock) {
+ hlist_del(&priv->link);
+ }
+}
+
+static void r8a78000_genpd_del_provider(void *data)
+{
+ of_genpd_del_provider(data);
+}
+
+static int r8a78000_genpd_always_on_singleton(struct device *dev)
+{
+ struct generic_pm_domain *genpd;
+ int ret;
+
+ guard(mutex)(&r8a78000_mdlc_lock);
+
+ if (r8a78000_genpd_always_on)
+ return 0;
+
+ genpd = kzalloc_obj(*genpd);
+ if (!genpd)
+ return -ENOMEM;
+
+ genpd->name = "always-on";
+ genpd->attach_dev = r8a78000_mdlc_attach_dev;
+ genpd->detach_dev = r8a78000_mdlc_detach_dev;
+ genpd->flags |= GENPD_FLAG_PM_CLK;
+
+ ret = pm_genpd_init(genpd, &pm_domain_always_on_gov, false);
+ if (ret) {
+ kfree(genpd);
+ return dev_err_probe(dev, ret,
+ "Failed to create always-on domain\n");
+ }
+
+ r8a78000_genpd_always_on = genpd;
+ return 0;
+}
+
+static int r8a78000_mdlc_probe(struct platform_device *pdev)
+{
+ struct device *dev = &pdev->dev;
+ struct device_node *np = dev->of_node;
+ struct device_node *scmi __free(device_node) = NULL;
+ const struct r8a78000_mdlc_info *info;
+ struct r8a78000_mdlc_priv *priv;
+ struct scmi_base_info version;
+ const struct fw_map *fw_map;
+ struct resource *res;
+ int ret;
+
+ ret = r8a78000_genpd_always_on_singleton(dev);
+ if (ret)
+ return ret;
+
+ priv = devm_kzalloc(dev, sizeof(*priv), GFP_KERNEL);
+ if (!priv)
+ return -ENOMEM;
+
+ priv->dev = dev;
+ priv->np = np;
+
+ scmi = of_parse_phandle(dev->of_node, "firmware", 0);
+ if (!scmi) {
+ dev_err(dev, "Cannot find SCMI firmware node\n");
+ return -ENODEV;
+ }
+
+ priv->scmi_power_np = scmi_find_proto(scmi, SCMI_PROTOCOL_POWER);
+ if (!priv->scmi_power_np) {
+ dev_err(dev,
+ "Cannot find SCMI power domain management protocol\n");
+ return -ENODEV;
+ }
+
+ priv->scmi_clk_np = scmi_find_proto(scmi, SCMI_PROTOCOL_CLOCK);
+ if (!priv->scmi_clk_np) {
+ dev_err(dev, "Cannot find SCMI clock management protocol\n");
+ return -ENODEV;
+ }
+
+ priv->scmi_reset_np = scmi_find_proto(scmi, SCMI_PROTOCOL_RESET);
+ if (!priv->scmi_reset_np) {
+ dev_err(dev, "Cannot find SCMI reset management protocol\n");
+ return -ENODEV;
+ }
+
+ ret = scmi_get_base_info(scmi, &version);
+ if (ret) {
+ return dev_err_probe(dev, -EPROBE_DEFER,
+ "SCMI not yet available\n");
+ }
+
+ if (strcmp(version.vendor_id, "Renesas") ||
+ strcmp(version.sub_vendor_id, "None")) {
+ return dev_err_probe(dev, -ENODEV,
+ "Unsupported SCMI firmware %s/%s\n",
+ version.vendor_id, version.sub_vendor_id);
+ }
+
+ priv->scmi_rcdev = reset_controller_get_provider(of_fwnode_handle(priv->scmi_reset_np));
+ if (!priv->scmi_rcdev)
+ return dev_err_probe(dev, -EPROBE_DEFER,
+ "SCMI reset not yet available\n");
+
+ res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
+ if (!res)
+ return -ENODEV;
+
+ for (fw_map = of_device_get_match_data(dev); fw_map->info; fw_map++) {
+ if (fw_map->impl_ver == version.impl_ver)
+ break;
+ }
+
+ if (!fw_map->info) {
+ return dev_err_probe(dev, -ENODEV,
+ "Unsupported SCMI version 0x%08x\n",
+ version.impl_ver);
+ }
+
+ for (info = fw_map->info; info->base; info++) {
+ if (info->base == res->start)
+ break;
+ }
+
+ if (!info->base) {
+ dev_warn(dev, "Unsupported MDLC instance 0x%pa\n", &res->start);
+ return -ENODEV;
+ }
+
+ /*
+ * We cannot do lazy look-up in r8a78000_genpd_xlate(), as that
+ * function is called with of_genpd_mutex already held.
+ */
+ priv->power_map = fill_power_map(priv, info->power_map);
+ if (IS_ERR(priv->power_map))
+ return PTR_ERR(priv->power_map);
+
+ priv->mod_map = info->mod_map;
+
+ scoped_guard(mutex, &r8a78000_mdlc_lock) {
+ hlist_add_head(&priv->link, &r8a78000_mdlc_list);
+ }
+
+ ret = devm_add_action_or_reset(dev, r8a78000_mdlc_unlink, priv);
+ if (ret)
+ return dev_err_probe(dev, ret, "failed to add action\n");
+
+ // FIXME genpd_add_provider() would be sufficient, but is private
+ /* Note that no actual domains are registered, just need translation */
+ priv->genpd_data.xlate = r8a78000_genpd_xlate;
+ ret = of_genpd_add_provider_onecell(np, &priv->genpd_data);
+ if (ret)
+ return dev_err_probe(dev, ret,
+ "Failed to register genpd provider\n");
+
+ ret = devm_add_action_or_reset(dev, r8a78000_genpd_del_provider, np);
+ if (ret)
+ return dev_err_probe(dev, ret,
+ "failed to add unregister action\n");
+
+ priv->rcdev.ops = &r8a78000_mdlc_reset_ops;
+ priv->rcdev.of_node = np;
+ priv->rcdev.of_reset_n_cells = 1;
+ priv->rcdev.of_xlate = r8a78000_mdlc_reset_xlate;
+
+ ret = devm_reset_controller_register(dev, &priv->rcdev);
+ if (ret)
+ return dev_err_probe(dev, ret,
+ "Failed to register reset controller\n");
+
+ return 0;
+}
+
+// FIXME We don't need all of them from the start; only add when used/tested
+static const struct power_map_in r8a78000_mdlc_pere_power_fw_4_28_0[] = {
+ { 0, 12 }, /* PD_UFS0 */
+ { 1, 13 }, /* PD_UFS1 */
+ { -1 },
+};
+
+static const struct mod_map r8a78000_mdlc_pere_mod_fw_4_28_0[] = {
+ { 0x30, 197 }, /* PERE_GPIODM0 */
+ // No CLOCK_ATTRIBUTES { 0x31, 198 }, /* PERE_GPIODM1 */
+ // No CLOCK_ATTRIBUTES { 0x32, 199 }, /* PERE_GPIODM2 */
+ // No CLOCK_ATTRIBUTES { 0x33, 200 }, /* PERE_GPIODM3 */
+ { 0x40, 201 }, /* RPC */
+ { 0x60, 202 }, /* UFS0 */
+ { 0x61, 203 }, /* UFS1 */
+ { 0x70, 204 }, /* SDHI0 */
+ { -1 },
+};
+
+static const struct mod_map r8a78000_mdlc_perw_mod_fw_4_28_0[] = {
+ { 0x30, 205 }, /* PERW_GPIODM0 */
+ // No CLOCK_ATTRIBUTES { 0x31, 206 }, /* PERW_GPIODM1 */
+ // No CLOCK_ATTRIBUTES { 0x32, 207 }, /* PERW_GPIODM2 */
+ // No CLOCK_ATTRIBUTES { 0x33, 208 }, /* PERW_GPIODM3 */
+ { 0x40, 209 }, /* SCIF0 */
+ { 0x41, 210 }, /* SCIF1 */
+ { 0x42, 211 }, /* SCIF3 */
+ { 0x43, 212 }, /* SCIF4 */
+ { 0x44, 213 }, /* I2C1 */
+ { 0x45, 214 }, /* I2C2 */
+ { 0x46, 215 }, /* I2C3 */
+ { 0x47, 216 }, /* I2C4 */
+ { 0x48, 217 }, /* I2C5 */
+ { 0x49, 218 }, /* I2C6 */
+ { 0x4a, 219 }, /* I2C7 */
+ { 0x4b, 220 }, /* I2C8 */
+ { 0x4c, 221 }, /* I3C0 */
+ { 0x4d, 222 }, /* I3C1 */
+ { 0x4e, 223 }, /* I3C2 */
+ { 0x4f, 224 }, /* MSI4 */
+ { 0x50, 225 }, /* MSI5 */
+ { 0x51, 226 }, /* MSI6 */
+ { 0x52, 227 }, /* MSI7 */
+ /*
+ * HSCIF0 is protected:
+ * - CLOCK_ATTRIBUTES is not supported, so clk is NULL
+ * - Reset operations fail with -EOPNOTSUPP
+ */
+ { 0x54, 228 }, /* HSCIF0 */
+ { 0x55, 229 }, /* HSCIF1 */
+ { 0x56, 230 }, /* HSCIF2 */
+ { 0x57, 231 }, /* HSCIF3 */
+ { 0x58, 232 }, /* DRI00 */
+ { 0x59, 233 }, /* DRI01 */
+ { 0x5a, 234 }, /* DRI10 */
+ { 0x5b, 235 }, /* DRI11 */
+ { 0x5c, 236 }, /* DRI20 */
+ { 0x5d, 237 }, /* DRI21 */
+ { 0x5e, 238 }, /* DRI30 */
+ { 0x5f, 239 }, /* DRI31 */
+ { 0x60, 240 }, /* DRI40 */
+ { 0x61, 241 }, /* DRI41 */
+ { 0x62, 242 }, /* DRI50 */
+ { 0x63, 243 }, /* DRI51 */
+ { 0x64, 244 }, /* DRI60 */
+ { 0x65, 245 }, /* DRI61 */
+ { 0x66, 246 }, /* DRI70 */
+ { 0x67, 247 }, /* DRI71 */
+ { 0x70, 248 }, /* PWM0 */
+ { 0x72, 249 }, /* TMU1 */
+ { 0x73, 250 }, /* TMU2 */
+ { 0x74, 251 }, /* TMU3 */
+ { 0x75, 252 }, /* TMU4 */
+ { 0x76, 253 }, /* TPU0 */
+ { 0x90, 254 }, /* ADG0 */
+ { 0x91, 255 }, /* ADG1 */
+ { 0x92, 256 }, /* SSI0 */
+ { 0x93, 257 }, /* SSI00 */
+ { 0x94, 258 }, /* SSI01 */
+ { 0x95, 259 }, /* SSI02 */
+ { 0x96, 260 }, /* SSI03 */
+ { 0x97, 261 }, /* SSI04 */
+ { 0x98, 262 }, /* SSI05 */
+ { 0x99, 263 }, /* SSI06 */
+ { 0x9a, 264 }, /* SSI07 */
+ { 0x9b, 265 }, /* SSI08 */
+ { 0x9c, 266 }, /* SSI09 */
+ { 0x9d, 267 }, /* SSI1 */
+ { 0x9e, 268 }, /* SSI10 */
+ { 0x9f, 269 }, /* SSI11 */
+ { 0xa0, 270 }, /* SSI12 */
+ { 0xa1, 271 }, /* SSI13 */
+ { 0xa2, 272 }, /* SSI14 */
+ { 0xa3, 273 }, /* SSI15 */
+ { 0xa4, 274 }, /* SSI16 */
+ { 0xa5, 275 }, /* SSI17 */
+ { 0xa6, 276 }, /* SSI18 */
+ { 0xa7, 277 }, /* SSI19 */
+ { 0xa8, 278 }, /* SCU0 */
+ { 0xa9, 279 }, /* SRC00 */
+ { 0xaa, 280 }, /* SRC01 */
+ { 0xab, 281 }, /* SRC02 */
+ { 0xac, 282 }, /* SRC03 */
+ { 0xad, 283 }, /* SRC04 */
+ { 0xae, 284 }, /* SRC05 */
+ { 0xaf, 285 }, /* SRC06 */
+ { 0xb0, 286 }, /* SRC07 */
+ { 0xb1, 287 }, /* SRC08 */
+ { 0xb2, 288 }, /* SRC09 */
+ { 0xb3, 289 }, /* SCU00 */
+ { 0xb4, 290 }, /* SCU01 */
+ { 0xb5, 291 }, /* DVC00 */
+ { 0xb6, 292 }, /* DVC01 */
+ { 0xb7, 293 }, /* SCU1 */
+ { 0xb8, 294 }, /* SRC10 */
+ { 0xb9, 295 }, /* SRC11 */
+ { 0xba, 296 }, /* SRC12 */
+ { 0xbb, 297 }, /* SRC13 */
+ { 0xbc, 298 }, /* SRC14 */
+ { 0xbd, 299 }, /* SRC15 */
+ { 0xbe, 300 }, /* SRC16 */
+ { 0xbf, 301 }, /* SRC17 */
+ { 0xc0, 302 }, /* SRC18 */
+ { 0xc1, 303 }, /* SRC19 */
+ { 0xc2, 304 }, /* SCU10 */
+ { 0xc3, 305 }, /* SCU11 */
+ { 0xc4, 306 }, /* DVC10 */
+ { 0xc5, 307 }, /* DVC11 */
+ { 0xc6, 308 }, /* APD00 */
+ { 0xc7, 309 }, /* APD01 */
+ { 0xc8, 310 }, /* APD10 */
+ { 0xc9, 311 }, /* APD11 */
+ { 0xca, 312 }, /* APD02 */
+ { 0xcb, 313 }, /* APD12 */
+ { -1 },
+};
+
+static const struct r8a78000_mdlc_info r8a78000_mdlc_fw_4_28_0[] = {
+ {
+ .base = 0xc3060000 /* mdlc_vipn */,
+ /* FIXME .power_map = r8a78000_mdlc_vipn_power_fw_4_28_0, */
+ /* FIXME .mod_map = r8a78000_mdlc_vipn_mod_fw_4_28_0, */
+ }, {
+ .base = 0xc3460000 /* mdlc_vips */,
+ /* FIXME .power_map = r8a78000_mdlc_vips_power_fw_4_28_0, */
+ /* FIXME .mod_map = r8a78000_mdlc_vips_mod_fw_4_28_0, */
+ }, {
+ .base = 0xc5000000 /* mdlc_vio */,
+ /* FIXME .power_map = r8a78000_mdlc_vio_power_fw_4_28_0, */
+ /* FIXME .mod_map = r8a78000_mdlc_vio_mod_fw_4_28_0, */
+ }, {
+ .base = 0xc08f0000 /* mdlc_pere */,
+ .power_map = r8a78000_mdlc_pere_power_fw_4_28_0,
+ .mod_map = r8a78000_mdlc_pere_mod_fw_4_28_0,
+ }, {
+ .base = 0xc05d0000 /* mdlc_perw */,
+ .mod_map = r8a78000_mdlc_perw_mod_fw_4_28_0,
+// FIXME We don't need all of them from the start; only add when used/tested
+#if 0
+ }, {
+ .base = 0xe8000000 /* mdlc_ddr0 */,
+ }, {
+ .base = 0xe8080000 /* mdlc_ddr1 */,
+ }, {
+ .base = 0xe8100000 /* mdlc_ddr2 */,
+ }, {
+ .base = 0xe8180000 /* mdlc_ddr3 */,
+ }, {
+ .base = 0xe8200000 /* mdlc_ddr4 */,
+ }, {
+ .base = 0xe8280000 /* mdlc_ddr5 */,
+ }, {
+ .base = 0xe8300000 /* mdlc_ddr6 */,
+ }, {
+ .base = 0xe8380000 /* mdlc_ddr7 */,
+ }, {
+ .base = 0xc9c90000 /* mdlc_hscn */,
+ /* FIXME .power_map = r8a78000_mdlc_hscn_power_fw_4_28_0, */
+ /* FIXME .mod_map = r8a78000_mdlc_hscn_mod_fw_4_28_0, */
+ }, {
+ .base = 0x19440000 /* mdlc_rt */,
+ /* FIXME .power_map = r8a78000_mdlc_rt_power_fw_4_28_0, */
+ /* FIXME .mod_map = r8a78000_mdlc_rt_mod_fw_4_28_0, */
+ }, {
+ .base = 0xc6480000 /* mdlc_top */,
+ /* FIXME .mod_map = r8a78000_mdlc_top_mod_fw_4_28_0, */
+ }, {
+ .base = 0xde200000 /* mdlc_hscs */,
+ /* FIXME .power_map = r8a78000_mdlc_hscs_power_fw_4_28_0, */
+ /* FIXME .mod_map = r8a78000_mdlc_hscs_mod_fw_4_28_0, */
+ }, {
+ .base = 0xc1990000 /* mdlc_imn */,
+ /* FIXME .power_map = r8a78000_mdlc_imn_power_fw_4_28_0, */
+ /* FIXME .mod_map = r8a78000_mdlc_imn_mod_fw_4_28_0, */
+ }, {
+ .base = 0xc1d90000 /* mdlc_ims */,
+ /* FIXME .power_map = r8a78000_mdlc_ims_power_fw_4_28_0, */
+ /* FIXME .mod_map = r8a78000_mdlc_ims_mod_fw_4_28_0, */
+ }, {
+ .base = 0xcb510000 /* mdlc_gpc */,
+ /* FIXME .power_map = r8a78000_mdlc_gpc_power_fw_4_28_0, */
+ /* FIXME .mod_map = r8a78000_mdlc_gpc_mod_fw_4_28_0, */
+ }, {
+ .base = 0xcbe90000 /* mdlc_dsp */,
+ /* FIXME .power_map = r8a78000_mdlc_dsp_power_fw_4_28_0, */
+ /* FIXME .mod_map = r8a78000_mdlc_dsp_mod_fw_4_28_0, */
+ }, {
+ .base = 0xe9980000 /* mdlc_mm */,
+ /* FIXME .mod_map = r8a78000_mdlc_mm_mod_fw_4_28_0, */
+ }, {
+ .base = 0xd2c30000 /* mdlc_npu0 */,
+ /* FIXME .power_map = r8a78000_mdlc_npu0_power_fw_4_28_0, */
+ /* FIXME .mod_map = r8a78000_mdlc_npu0_mod_fw_4_28_0, */
+ }, {
+ .base = 0xd6c30000 /* mdlc_npu1 */,
+ /* FIXME .power_map = r8a78000_mdlc_npu1_power_fw_4_28_0, */
+ /* FIXME .mod_map = r8a78000_mdlc_npu1_mod_fw_4_28_0, */
+ }, {
+ .base = 0xca410000 /* mdlc_cmnn */,
+ /* FIXME .power_map = r8a78000_mdlc_cmnn_power_fw_4_28_0, */
+ /* FIXME .mod_map = r8a78000_mdlc_cmnn_mod_fw_4_28_0, */
+ }, {
+ .base = 0xca510000 /* mdlc_cmns */,
+ /* FIXME .power_map = r8a78000_mdlc_cmns_power_fw_4_28_0, */
+ /* FIXME .mod_map = r8a78000_mdlc_cmns_mod_fw_4_28_0, */
+ }, {
+ .base = 0xc1330000 /* mdlc_scp */,
+ /* FIXME .mod_map = r8a78000_mdlc_scp_mod_fw_4_28_0, */
+ }, {
+ .base = 0xc1338000 /* mdlc_aon */,
+ /* FIXME .mod_map = r8a78000_mdlc_aon_mod_fw_4_28_0, */
+#endif
+ },
+ { 0 }
+};
+
+static const struct mod_map r8a78000_mdlc_pere_mod_fw_4_31_0[] = {
+ { 0x30, 193 }, /* PERE_GPIODM0 */
+ // No CLOCK_ATTRIBUTES { 0x31, 194 }, /* PERE_GPIODM1 */
+ // No CLOCK_ATTRIBUTES { 0x32, 195 }, /* PERE_GPIODM2 */
+ // No CLOCK_ATTRIBUTES { 0x33, 196 }, /* PERE_GPIODM3 */
+ { 0x40, 197 }, /* RPC */
+ { 0x60, 198 }, /* UFS0 */
+ { 0x61, 199 }, /* UFS1 */
+ { 0x70, 200 }, /* SDHI0 */
+ { -1 },
+};
+
+static const struct mod_map r8a78000_mdlc_perw_mod_fw_4_31_0[] = {
+ { 0x30, 201 }, /* PERW_GPIODM0 */
+ // No CLOCK_ATTRIBUTES { 0x31, 202 }, /* PERW_GPIODM1 */
+ // No CLOCK_ATTRIBUTES { 0x32, 203 }, /* PERW_GPIODM2 */
+ // No CLOCK_ATTRIBUTES { 0x33, 204 }, /* PERW_GPIODM3 */
+ { 0x40, 205 }, /* SCIF0 */
+ { 0x41, 206 }, /* SCIF1 */
+ { 0x42, 207 }, /* SCIF3 */
+ { 0x43, 208 }, /* SCIF4 */
+ { 0x44, 209 }, /* I2C1 */
+ { 0x45, 210 }, /* I2C2 */
+ { 0x46, 211 }, /* I2C3 */
+ { 0x47, 212 }, /* I2C4 */
+ { 0x48, 213 }, /* I2C5 */
+ { 0x49, 214 }, /* I2C6 */
+ { 0x4a, 215 }, /* I2C7 */
+ { 0x4b, 216 }, /* I2C8 */
+ { 0x4c, 217 }, /* I3C0 */
+ { 0x4d, 218 }, /* I3C1 */
+ { 0x4e, 219 }, /* I3C2 */
+ { 0x4f, 220 }, /* MSI4 */
+ { 0x50, 221 }, /* MSI5 */
+ { 0x51, 222 }, /* MSI6 */
+ { 0x52, 223 }, /* MSI7 */
+ { 0x54, 224 }, /* HSCIF0 */
+ { 0x55, 225 }, /* HSCIF1 */
+ { 0x56, 226 }, /* HSCIF2 */
+ { 0x57, 227 }, /* HSCIF3 */
+ { 0x58, 228 }, /* DRI00 */
+ { 0x59, 229 }, /* DRI01 */
+ { 0x5a, 230 }, /* DRI10 */
+ { 0x5b, 231 }, /* DRI11 */
+ { 0x5c, 232 }, /* DRI20 */
+ { 0x5d, 233 }, /* DRI21 */
+ { 0x5e, 234 }, /* DRI30 */
+ { 0x5f, 235 }, /* DRI31 */
+ { 0x60, 236 }, /* DRI40 */
+ { 0x61, 237 }, /* DRI41 */
+ { 0x62, 238 }, /* DRI50 */
+ { 0x63, 239 }, /* DRI51 */
+ { 0x64, 240 }, /* DRI60 */
+ { 0x65, 241 }, /* DRI61 */
+ { 0x66, 242 }, /* DRI70 */
+ { 0x67, 243 }, /* DRI71 */
+ { 0x70, 244 }, /* PWM0 */
+ { 0x72, 245 }, /* TMU1 */
+ { 0x73, 246 }, /* TMU2 */
+ { 0x74, 247 }, /* TMU3 */
+ { 0x75, 248 }, /* TMU4 */
+ { 0x76, 249 }, /* TPU0 */
+ { 0x90, 250 }, /* ADG0 */
+ { 0x91, 251 }, /* ADG1 */
+ { 0x92, 252 }, /* SSI0 */
+ { 0x93, 253 }, /* SSI00 */
+ { 0x94, 254 }, /* SSI01 */
+ { 0x95, 255 }, /* SSI02 */
+ { 0x96, 256 }, /* SSI03 */
+ { 0x97, 257 }, /* SSI04 */
+ { 0x98, 258 }, /* SSI05 */
+ { 0x99, 259 }, /* SSI06 */
+ { 0x9a, 260 }, /* SSI07 */
+ { 0x9b, 261 }, /* SSI08 */
+ { 0x9c, 262 }, /* SSI09 */
+ { 0x9d, 263 }, /* SSI1 */
+ { 0x9e, 264 }, /* SSI10 */
+ { 0x9f, 265 }, /* SSI11 */
+ { 0xa0, 266 }, /* SSI12 */
+ { 0xa1, 267 }, /* SSI13 */
+ { 0xa2, 268 }, /* SSI14 */
+ { 0xa3, 269 }, /* SSI15 */
+ { 0xa4, 270 }, /* SSI16 */
+ { 0xa5, 271 }, /* SSI17 */
+ { 0xa6, 272 }, /* SSI18 */
+ { 0xa7, 273 }, /* SSI19 */
+ { 0xa8, 274 }, /* SCU0 */
+ { 0xa9, 275 }, /* SRC00 */
+ { 0xaa, 276 }, /* SRC01 */
+ { 0xab, 277 }, /* SRC02 */
+ { 0xac, 278 }, /* SRC03 */
+ { 0xad, 279 }, /* SRC04 */
+ { 0xae, 280 }, /* SRC05 */
+ { 0xaf, 281 }, /* SRC06 */
+ { 0xb0, 282 }, /* SRC07 */
+ { 0xb1, 283 }, /* SRC08 */
+ { 0xb2, 284 }, /* SRC09 */
+ { 0xb3, 285 }, /* SCU00 */
+ { 0xb4, 286 }, /* SCU01 */
+ { 0xb5, 287 }, /* DVC00 */
+ { 0xb6, 288 }, /* DVC01 */
+ { 0xb7, 289 }, /* SCU1 */
+ { 0xb8, 290 }, /* SRC10 */
+ { 0xb9, 291 }, /* SRC11 */
+ { 0xba, 292 }, /* SRC12 */
+ { 0xbb, 293 }, /* SRC13 */
+ { 0xbc, 294 }, /* SRC14 */
+ { 0xbd, 295 }, /* SRC15 */
+ { 0xbe, 296 }, /* SRC16 */
+ { 0xbf, 297 }, /* SRC17 */
+ { 0xc0, 298 }, /* SRC18 */
+ { 0xc1, 299 }, /* SRC19 */
+ { 0xc2, 300 }, /* SCU10 */
+ { 0xc3, 301 }, /* SCU11 */
+ { 0xc4, 302 }, /* DVC10 */
+ { 0xc5, 303 }, /* DVC11 */
+ { 0xc6, 304 }, /* APD00 */
+ { 0xc7, 305 }, /* APD01 */
+ { 0xc8, 306 }, /* APD10 */
+ { 0xc9, 307 }, /* APD11 */
+ { 0xca, 308 }, /* APD02 */
+ { 0xcb, 309 }, /* APD12 */
+ { -1 },
+};
+
+static const struct r8a78000_mdlc_info r8a78000_mdlc_fw_4_31_0[] = {
+ {
+ .base = 0xc3060000 /* mdlc_vipn */,
+ /* FIXME .power_map = r8a78000_mdlc_vipn_power_fw_4_28_0, */
+ /* FIXME .mod_map = r8a78000_mdlc_vipn_mod_fw_4_31_0, */
+ }, {
+ .base = 0xc3460000 /* mdlc_vips */,
+ /* FIXME .power_map = r8a78000_mdlc_vips_power_fw_4_28_0, */
+ /* FIXME .mod_map = r8a78000_mdlc_vips_mod_fw_4_31_0, */
+ }, {
+ .base = 0xc5000000 /* mdlc_vio */,
+ /* FIXME .power_map = r8a78000_mdlc_vio_power_fw_4_28_0, */
+ /* FIXME .mod_map = r8a78000_mdlc_vio_mod_fw_4_31_0, */
+ }, {
+ .base = 0xc08f0000 /* mdlc_pere */,
+ .power_map = r8a78000_mdlc_pere_power_fw_4_28_0,
+ .mod_map = r8a78000_mdlc_pere_mod_fw_4_31_0,
+ }, {
+ .base = 0xc05d0000 /* mdlc_perw */,
+ .mod_map = r8a78000_mdlc_perw_mod_fw_4_31_0,
+// FIXME We don't need all of them from the start; only add when used/tested
+#if 0
+ }, {
+ .base = 0xe8000000 /* mdlc_ddr0 */,
+ }, {
+ .base = 0xe8080000 /* mdlc_ddr1 */,
+ }, {
+ .base = 0xe8100000 /* mdlc_ddr2 */,
+ }, {
+ .base = 0xe8180000 /* mdlc_ddr3 */,
+ }, {
+ .base = 0xe8200000 /* mdlc_ddr4 */,
+ }, {
+ .base = 0xe8280000 /* mdlc_ddr5 */,
+ }, {
+ .base = 0xe8300000 /* mdlc_ddr6 */,
+ }, {
+ .base = 0xe8380000 /* mdlc_ddr7 */,
+ }, {
+ .base = 0xc9c90000 /* mdlc_hscn */,
+ /* FIXME .power_map = r8a78000_mdlc_hscn_power_fw_4_28_0, */
+ /* FIXME .mod_map = r8a78000_mdlc_hscn_mod_fw_4_31_0, */
+ }, {
+ .base = 0x19440000 /* mdlc_rt */,
+ /* FIXME .power_map = r8a78000_mdlc_rt_power_fw_4_28_0, */
+ /* FIXME .mod_map = r8a78000_mdlc_rt_mod_fw_4_31_0, */
+ }, {
+ .base = 0xc6480000 /* mdlc_top */,
+ /* FIXME .mod_map = r8a78000_mdlc_top_mod_fw_4_31_0, */
+ }, {
+ .base = 0xde200000 /* mdlc_hscs */,
+ /* FIXME .power_map = r8a78000_mdlc_hscs_power_fw_4_28_0, */
+ /* FIXME .mod_map = r8a78000_mdlc_hscs_mod_fw_4_31_0, */
+ }, {
+ .base = 0xc1990000 /* mdlc_imn */,
+ /* FIXME .power_map = r8a78000_mdlc_imn_power_fw_4_28_0, */
+ /* FIXME .mod_map = r8a78000_mdlc_imn_mod_fw_4_31_0, */
+ }, {
+ .base = 0xc1d90000 /* mdlc_ims */,
+ /* FIXME .power_map = r8a78000_mdlc_ims_power_fw_4_28_0, */
+ /* FIXME .mod_map = r8a78000_mdlc_ims_mod_fw_4_31_0, */
+ }, {
+ .base = 0xcb510000 /* mdlc_gpc */,
+ /* FIXME .power_map = r8a78000_mdlc_gpc_power_fw_4_28_0, */
+ /* FIXME .mod_map = r8a78000_mdlc_gpc_mod_fw_4_31_0, */
+ }, {
+ .base = 0xcbe90000 /* mdlc_dsp */,
+ /* FIXME .power_map = r8a78000_mdlc_dsp_power_fw_4_28_0, */
+ /* FIXME .mod_map = r8a78000_mdlc_dsp_mod_fw_4_31_0, */
+ }, {
+ .base = 0xe9980000 /* mdlc_mm */,
+ /* FIXME .mod_map = r8a78000_mdlc_mm_mod_fw_4_31_0, */
+ }, {
+ .base = 0xd2c30000 /* mdlc_npu0 */,
+ /* FIXME .power_map = r8a78000_mdlc_npu0_power_fw_4_28_0, */
+ /* FIXME .mod_map = r8a78000_mdlc_npu0_mod_fw_4_31_0, */
+ }, {
+ .base = 0xd6c30000 /* mdlc_npu1 */,
+ /* FIXME .power_map = r8a78000_mdlc_npu1_power_fw_4_28_0, */
+ /* FIXME .mod_map = r8a78000_mdlc_npu1_mod_fw_4_31_0, */
+ }, {
+ .base = 0xca410000 /* mdlc_cmnn */,
+ /* FIXME .power_map = r8a78000_mdlc_cmnn_power_fw_4_28_0, */
+ /* FIXME .mod_map = r8a78000_mdlc_cmnn_mod_fw_4_31_0, */
+ }, {
+ .base = 0xca510000 /* mdlc_cmns */,
+ /* FIXME .power_map = r8a78000_mdlc_cmns_power_fw_4_28_0, */
+ /* FIXME .mod_map = r8a78000_mdlc_cmns_mod_fw_4_31_0, */
+ }, {
+ .base = 0xc1330000 /* mdlc_scp */,
+ /* FIXME .mod_map = r8a78000_mdlc_scp_mod_fw_4_31_0, */
+ }, {
+ .base = 0xc1338000 /* mdlc_aon */,
+ /* FIXME .mod_map = r8a78000_mdlc_aon_mod_fw_4_31_0, */
+#endif
+ },
+ { 0 }
+};
+
+static const struct fw_map r8a78000_mdlc_fw_map[] = {
+ { 0x010a0000, r8a78000_mdlc_fw_4_28_0 }, /* SCP FW SDKv4.28.0 */
+ { 0x010d0000, r8a78000_mdlc_fw_4_31_0 }, /* SCP FW SDKv4.31.0 */
+ { 0x010e0000, r8a78000_mdlc_fw_4_31_0 }, /* SCP FW SDKv4.32.0 */
+ { 0, NULL }
+};
+
+static const struct of_device_id r8a78000_mdlc_match[] = {
+ {
+ .compatible = "renesas,r8a78000-mdlc",
+ .data = &r8a78000_mdlc_fw_map,
+ },
+ { /* sentinel */ }
+};
+
+static struct platform_driver r8a78000_mdlc_driver = {
+ .probe = r8a78000_mdlc_probe,
+ .driver = {
+ .name = "r8a78000-mdlc",
+ .of_match_table = r8a78000_mdlc_match,
+ .suppress_bind_attrs = true,
+ },
+};
+
+builtin_platform_driver(r8a78000_mdlc_driver)
+
+MODULE_DESCRIPTION("R-Car X5H MDLC Driver");
diff --git a/drivers/soc/renesas/Kconfig b/drivers/soc/renesas/Kconfig
index 2ab150d04bb1f1ef..d4055250de72f1fe 100644
--- a/drivers/soc/renesas/Kconfig
+++ b/drivers/soc/renesas/Kconfig
@@ -358,6 +358,7 @@ config ARCH_R8A78000
default y if ARCH_RENESAS
default ARCH_RENESAS
select ARCH_RCAR_GEN5
+ select MDLC_R8A78000
help
This enables support for the Renesas R-Car X5H SoC.
--
2.43.0
^ permalink raw reply related
* [PATCH/RFC 13/14] arm64: dts: renesas: r8a78000: Add CPG/MDLC nodes
From: Geert Uytterhoeven @ 2026-04-21 18:11 UTC (permalink / raw)
To: Sudeep Holla, Cristian Marussi, Rob Herring, Krzysztof Kozlowski,
Conor Dooley, Magnus Damm, Saravana Kannan, Michael Turquette,
Stephen Boyd, Philipp Zabel, Ulf Hansson, Rafael J . Wysocki,
Kevin Hilman, Florian Fainelli, Wolfram Sang, Marek Vasut,
Kuninori Morimoto
Cc: arm-scmi, linux-arm-kernel, linux-renesas-soc, linux-clk,
devicetree, linux-pm, linux-kernel, Geert Uytterhoeven
In-Reply-To: <cover.1776793163.git.geert+renesas@glider.be>
Add device nodes for the Clock Pulse Generator (CPG) and Module Control
(MDLC) blocks on the R-Car X5H (R8A78000) SoC.
Convert all (H)SCIF serial ports from dummy to CPG clocks, and link them
to an MDLC for power domains and resets.
Signed-off-by: Geert Uytterhoeven <geert+renesas@glider.be>
---
Add all MDLC nodes from the start, or only when used/tested?
---
arch/arm64/boot/dts/renesas/r8a78000.dtsi | 300 ++++++++++++++++++++--
1 file changed, 275 insertions(+), 25 deletions(-)
diff --git a/arch/arm64/boot/dts/renesas/r8a78000.dtsi b/arch/arm64/boot/dts/renesas/r8a78000.dtsi
index 11922b1ac73b3af5..640b622435569461 100644
--- a/arch/arm64/boot/dts/renesas/r8a78000.dtsi
+++ b/arch/arm64/boot/dts/renesas/r8a78000.dtsi
@@ -5,6 +5,8 @@
* Copyright (C) 2025 Renesas Electronics Corp.
*/
+#include <dt-bindings/clock/renesas,r8a78000-cpg.h>
+#include <dt-bindings/power/renesas,r8a78000-mdlc.h>
#include <dt-bindings/interrupt-controller/arm-gic.h>
/ {
@@ -636,23 +638,6 @@ L3_CA720_7: cache-controller-37 {
};
};
- /*
- * In the early phase, there is no clock control support,
- * so assume that the clocks are enabled by default.
- * Therefore, dummy clocks are used.
- */
- dummy_clk_sgasyncd16: dummy-clk-sgasyncd16 {
- compatible = "fixed-clock";
- #clock-cells = <0>;
- clock-frequency = <66666000>;
- };
-
- dummy_clk_sgasyncd4: dummy-clk-sgasyncd4 {
- compatible = "fixed-clock";
- #clock-cells = <0>;
- clock-frequency = <266660000>;
- };
-
extal_clk: extal-clk {
compatible = "fixed-clock";
#clock-cells = <0>;
@@ -813,8 +798,12 @@ scif0: serial@c0700000 {
"renesas,rcar-gen5-scif", "renesas,scif";
reg = <0 0xc0700000 0 0x40>;
interrupts = <GIC_ESPI 10 IRQ_TYPE_LEVEL_HIGH>;
- clocks = <&dummy_clk_sgasyncd16>, <&dummy_clk_sgasyncd4>, <&scif_clk>;
+ clocks = <&cpg R8A78000_CPG_SGASYNCD16_PERW_BUS>,
+ <&cpg R8A78000_CPG_SGASYNCD4_PERW_BUS>,
+ <&scif_clk>;
clock-names = "fck", "brg_int", "scif_clk";
+ power-domains = <&mdlc_perw R8A78000_MDLC_PD_APL 0x40>;
+ resets = <&mdlc_perw 0x40>;
status = "disabled";
};
@@ -823,8 +812,12 @@ scif1: serial@c0704000 {
"renesas,rcar-gen5-scif", "renesas,scif";
reg = <0 0xc0704000 0 0x40>;
interrupts = <GIC_ESPI 11 IRQ_TYPE_LEVEL_HIGH>;
- clocks = <&dummy_clk_sgasyncd16>, <&dummy_clk_sgasyncd4>, <&scif_clk>;
+ clocks = <&cpg R8A78000_CPG_SGASYNCD16_PERW_BUS>,
+ <&cpg R8A78000_CPG_SGASYNCD4_PERW_BUS>,
+ <&scif_clk>;
clock-names = "fck", "brg_int", "scif_clk";
+ power-domains = <&mdlc_perw R8A78000_MDLC_PD_APL 0x41>;
+ resets = <&mdlc_perw 0x41>;
status = "disabled";
};
@@ -833,8 +826,12 @@ scif3: serial@c0708000 {
"renesas,rcar-gen5-scif", "renesas,scif";
reg = <0 0xc0708000 0 0x40>;
interrupts = <GIC_ESPI 12 IRQ_TYPE_LEVEL_HIGH>;
- clocks = <&dummy_clk_sgasyncd16>, <&dummy_clk_sgasyncd4>, <&scif_clk>;
+ clocks = <&cpg R8A78000_CPG_SGASYNCD16_PERW_BUS>,
+ <&cpg R8A78000_CPG_SGASYNCD4_PERW_BUS>,
+ <&scif_clk>;
clock-names = "fck", "brg_int", "scif_clk";
+ power-domains = <&mdlc_perw R8A78000_MDLC_PD_APL 0x42>;
+ resets = <&mdlc_perw 0x42>;
status = "disabled";
};
@@ -843,8 +840,12 @@ scif4: serial@c070c000 {
"renesas,rcar-gen5-scif", "renesas,scif";
reg = <0 0xc070c000 0 0x40>;
interrupts = <GIC_ESPI 13 IRQ_TYPE_LEVEL_HIGH>;
- clocks = <&dummy_clk_sgasyncd16>, <&dummy_clk_sgasyncd4>, <&scif_clk>;
+ clocks = <&cpg R8A78000_CPG_SGASYNCD16_PERW_BUS>,
+ <&cpg R8A78000_CPG_SGASYNCD4_PERW_BUS>,
+ <&scif_clk>;
clock-names = "fck", "brg_int", "scif_clk";
+ power-domains = <&mdlc_perw R8A78000_MDLC_PD_APL 0x43>;
+ resets = <&mdlc_perw 0x43>;
status = "disabled";
};
@@ -853,8 +854,12 @@ hscif0: serial@c0710000 {
"renesas,rcar-gen5-hscif", "renesas,hscif";
reg = <0 0xc0710000 0 0x60>;
interrupts = <GIC_ESPI 14 IRQ_TYPE_LEVEL_HIGH>;
- clocks = <&dummy_clk_sgasyncd4>, <&dummy_clk_sgasyncd4>, <&scif_clk>;
+ clocks = <&cpg R8A78000_CPG_SGASYNCD4_PERW_BUS>,
+ <&cpg R8A78000_CPG_SGASYNCD4_PERW_BUS>,
+ <&scif_clk>;
clock-names = "fck", "brg_int", "scif_clk";
+ power-domains = <&mdlc_perw R8A78000_MDLC_PD_APL 0x54>;
+ resets = <&mdlc_perw 0x54>;
status = "disabled";
};
@@ -863,8 +868,12 @@ hscif1: serial@c0714000 {
"renesas,rcar-gen5-hscif", "renesas,hscif";
reg = <0 0xc0714000 0 0x60>;
interrupts = <GIC_ESPI 15 IRQ_TYPE_LEVEL_HIGH>;
- clocks = <&dummy_clk_sgasyncd4>, <&dummy_clk_sgasyncd4>, <&scif_clk>;
+ clocks = <&cpg R8A78000_CPG_SGASYNCD4_PERW_BUS>,
+ <&cpg R8A78000_CPG_SGASYNCD4_PERW_BUS>,
+ <&scif_clk>;
clock-names = "fck", "brg_int", "scif_clk";
+ power-domains = <&mdlc_perw R8A78000_MDLC_PD_APL 0x55>;
+ resets = <&mdlc_perw 0x55>;
status = "disabled";
};
@@ -873,8 +882,12 @@ hscif2: serial@c0718000 {
"renesas,rcar-gen5-hscif", "renesas,hscif";
reg = <0 0xc0718000 0 0x60>;
interrupts = <GIC_ESPI 16 IRQ_TYPE_LEVEL_HIGH>;
- clocks = <&dummy_clk_sgasyncd4>, <&dummy_clk_sgasyncd4>, <&scif_clk>;
+ clocks = <&cpg R8A78000_CPG_SGASYNCD4_PERW_BUS>,
+ <&cpg R8A78000_CPG_SGASYNCD4_PERW_BUS>,
+ <&scif_clk>;
clock-names = "fck", "brg_int", "scif_clk";
+ power-domains = <&mdlc_perw R8A78000_MDLC_PD_APL 0x56>;
+ resets = <&mdlc_perw 0x56>;
status = "disabled";
};
@@ -883,8 +896,12 @@ hscif3: serial@c071c000 {
"renesas,rcar-gen5-hscif", "renesas,hscif";
reg = <0 0xc071c000 0 0x60>;
interrupts = <GIC_ESPI 17 IRQ_TYPE_LEVEL_HIGH>;
- clocks = <&dummy_clk_sgasyncd4>, <&dummy_clk_sgasyncd4>, <&scif_clk>;
+ clocks = <&cpg R8A78000_CPG_SGASYNCD4_PERW_BUS>,
+ <&cpg R8A78000_CPG_SGASYNCD4_PERW_BUS>,
+ <&scif_clk>;
clock-names = "fck", "brg_int", "scif_clk";
+ power-domains = <&mdlc_perw R8A78000_MDLC_PD_APL 0x57>;
+ resets = <&mdlc_perw 0x57>;
status = "disabled";
};
@@ -897,6 +914,239 @@ scp_sram: sram@c1000000 {
/* scp-sram node must be set per board file */
};
+
+ cpg: clock-controller@c1320000 {
+ compatible = "renesas,r8a78000-cpg";
+ reg = <0 0xc1320000 0 0x10000>;
+ clocks = <&extal_clk>, <&extalr_clk>;
+ clock-names = "extal", "extalr";
+ #clock-cells = <1>;
+ bootph-all;
+ };
+
+ mdlc_vipn: system-controller@c3060000 {
+ compatible = "renesas,r8a78000-mdlc";
+ reg = <0 0xc3060000 0 0x1000>;
+ #power-domain-cells = <2>;
+ #reset-cells = <1>;
+ bootph-all;
+ };
+
+ mdlc_vips: system-controller@c3460000 {
+ compatible = "renesas,r8a78000-mdlc";
+ reg = <0 0xc3460000 0 0x1000>;
+ #power-domain-cells = <2>;
+ #reset-cells = <1>;
+ bootph-all;
+ };
+
+ mdlc_vio: system-controller@c5000000 {
+ compatible = "renesas,r8a78000-mdlc";
+ reg = <0 0xc5000000 0 0x1000>;
+ #power-domain-cells = <2>;
+ #reset-cells = <1>;
+ bootph-all;
+ };
+
+ mdlc_pere: system-controller@c08f0000 {
+ compatible = "renesas,r8a78000-mdlc";
+ reg = <0 0xc08f0000 0 0x1000>;
+ #power-domain-cells = <2>;
+ #reset-cells = <1>;
+ bootph-all;
+ };
+
+ mdlc_perw: system-controller@c05d0000 {
+ compatible = "renesas,r8a78000-mdlc";
+ reg = <0 0xc05d0000 0 0x1000>;
+ #power-domain-cells = <2>;
+ #reset-cells = <1>;
+ bootph-all;
+ };
+
+ mdlc_ddr0: system-controller@e8000000 {
+ compatible = "renesas,r8a78000-mdlc";
+ reg = <0 0xe8000000 0 0x1000>;
+ #power-domain-cells = <2>;
+ #reset-cells = <1>;
+ bootph-all;
+ };
+
+ mdlc_ddr1: system-controller@e8080000 {
+ compatible = "renesas,r8a78000-mdlc";
+ reg = <0 0xe8080000 0 0x1000>;
+ #power-domain-cells = <2>;
+ #reset-cells = <1>;
+ bootph-all;
+ };
+
+ mdlc_ddr2: system-controller@e8100000 {
+ compatible = "renesas,r8a78000-mdlc";
+ reg = <0 0xe8100000 0 0x1000>;
+ #power-domain-cells = <2>;
+ #reset-cells = <1>;
+ bootph-all;
+ };
+
+ mdlc_ddr3: system-controller@e8180000 {
+ compatible = "renesas,r8a78000-mdlc";
+ reg = <0 0xe8180000 0 0x1000>;
+ #power-domain-cells = <2>;
+ #reset-cells = <1>;
+ bootph-all;
+ };
+
+ mdlc_ddr4: system-controller@e8200000 {
+ compatible = "renesas,r8a78000-mdlc";
+ reg = <0 0xe8200000 0 0x1000>;
+ #power-domain-cells = <2>;
+ #reset-cells = <1>;
+ bootph-all;
+ };
+
+ mdlc_ddr5: system-controller@e8280000 {
+ compatible = "renesas,r8a78000-mdlc";
+ reg = <0 0xe8280000 0 0x1000>;
+ #power-domain-cells = <2>;
+ #reset-cells = <1>;
+ bootph-all;
+ };
+
+ mdlc_ddr6: system-controller@e8300000 {
+ compatible = "renesas,r8a78000-mdlc";
+ reg = <0 0xe8300000 0 0x1000>;
+ #power-domain-cells = <2>;
+ #reset-cells = <1>;
+ bootph-all;
+ };
+
+ mdlc_ddr7: system-controller@e8380000 {
+ compatible = "renesas,r8a78000-mdlc";
+ reg = <0 0xe8380000 0 0x1000>;
+ #power-domain-cells = <2>;
+ #reset-cells = <1>;
+ bootph-all;
+ };
+
+ mdlc_hscn: system-controller@c9c90000 {
+ compatible = "renesas,r8a78000-mdlc";
+ reg = <0 0xc9c90000 0 0x1000>;
+ #power-domain-cells = <2>;
+ #reset-cells = <1>;
+ bootph-all;
+ };
+
+ mdlc_rt: system-controller@19440000 {
+ compatible = "renesas,r8a78000-mdlc";
+ reg = <0 0x19440000 0 0x1000>;
+ #power-domain-cells = <2>;
+ #reset-cells = <1>;
+ bootph-all;
+ };
+
+ mdlc_top: system-controller@c6480000 {
+ compatible = "renesas,r8a78000-mdlc";
+ reg = <0 0xc6480000 0 0x1000>;
+ #power-domain-cells = <2>;
+ #reset-cells = <1>;
+ bootph-all;
+ };
+
+ mdlc_hscs: system-controller@de200000 {
+ compatible = "renesas,r8a78000-mdlc";
+ reg = <0 0xde200000 0 0x1000>;
+ #power-domain-cells = <2>;
+ #reset-cells = <1>;
+ bootph-all;
+ };
+
+ mdlc_imn: system-controller@c1990000 {
+ compatible = "renesas,r8a78000-mdlc";
+ reg = <0 0xc1990000 0 0x1000>;
+ #power-domain-cells = <2>;
+ #reset-cells = <1>;
+ bootph-all;
+ };
+
+ mdlc_ims: system-controller@c1d90000 {
+ compatible = "renesas,r8a78000-mdlc";
+ reg = <0 0xc1d90000 0 0x1000>;
+ #power-domain-cells = <2>;
+ #reset-cells = <1>;
+ bootph-all;
+ };
+
+ mdlc_gpc: system-controller@cb510000 {
+ compatible = "renesas,r8a78000-mdlc";
+ reg = <0 0xcb510000 0 0x1000>;
+ #power-domain-cells = <2>;
+ #reset-cells = <1>;
+ bootph-all;
+ };
+
+ mdlc_dsp: system-controller@cbe90000 {
+ compatible = "renesas,r8a78000-mdlc";
+ reg = <0 0xcbe90000 0 0x1000>;
+ #power-domain-cells = <2>;
+ #reset-cells = <1>;
+ bootph-all;
+ };
+
+ mdlc_mm: system-controller@e9980000 {
+ compatible = "renesas,r8a78000-mdlc";
+ reg = <0 0xe9980000 0 0x1000>;
+ #power-domain-cells = <2>;
+ #reset-cells = <1>;
+ bootph-all;
+ };
+
+ mdlc_npu0: system-controller@d2c30000 {
+ compatible = "renesas,r8a78000-mdlc";
+ reg = <0 0xd2c30000 0 0x1000>;
+ #power-domain-cells = <2>;
+ #reset-cells = <1>;
+ bootph-all;
+ };
+
+ mdlc_npu1: system-controller@d6c30000 {
+ compatible = "renesas,r8a78000-mdlc";
+ reg = <0 0xd6c30000 0 0x1000>;
+ #power-domain-cells = <2>;
+ #reset-cells = <1>;
+ bootph-all;
+ };
+
+ mdlc_cmnn: system-controller@ca410000 {
+ compatible = "renesas,r8a78000-mdlc";
+ reg = <0 0xca410000 0 0x1000>;
+ #power-domain-cells = <2>;
+ #reset-cells = <1>;
+ bootph-all;
+ };
+
+ mdlc_cmns: system-controller@ca510000 {
+ compatible = "renesas,r8a78000-mdlc";
+ reg = <0 0xca510000 0 0x1000>;
+ #power-domain-cells = <2>;
+ #reset-cells = <1>;
+ bootph-all;
+ };
+
+ mdlc_scp: system-controller@c1330000 {
+ compatible = "renesas,r8a78000-mdlc";
+ reg = <0 0xc1330000 0 0x1000>;
+ #power-domain-cells = <2>;
+ #reset-cells = <1>;
+ bootph-all;
+ };
+
+ mdlc_aon: system-controller@c1338000 {
+ compatible = "renesas,r8a78000-mdlc";
+ reg = <0 0xc1338000 0 0x1000>;
+ #power-domain-cells = <2>;
+ #reset-cells = <1>;
+ bootph-all;
+ };
};
timer {
--
2.43.0
^ permalink raw reply related
* [PATCH/RFC 11/14] clk: renesas: Add R-Car X5H CPG SCMI remapping driver
From: Geert Uytterhoeven @ 2026-04-21 18:11 UTC (permalink / raw)
To: Sudeep Holla, Cristian Marussi, Rob Herring, Krzysztof Kozlowski,
Conor Dooley, Magnus Damm, Saravana Kannan, Michael Turquette,
Stephen Boyd, Philipp Zabel, Ulf Hansson, Rafael J . Wysocki,
Kevin Hilman, Florian Fainelli, Wolfram Sang, Marek Vasut,
Kuninori Morimoto
Cc: arm-scmi, linux-arm-kernel, linux-renesas-soc, linux-clk,
devicetree, linux-pm, linux-kernel, Geert Uytterhoeven
In-Reply-To: <cover.1776793163.git.geert+renesas@glider.be>
Add a proof-of-concept Clock Pulse Generator driver for the R-Car X5H
(R8A78000) SoC, using tables to remap from hardware clock IDs to SCMI
clock IDs.
Some SCMI clocks do not support the SCMI CLOCK_ATTRIBUTES command, and
are thus not usable from Linux. Register a bunch of fixed-rate clocks,
and use them as replacements for SCMI clocks that are known to be
unusable.
For now this contains preliminary support for SCP FW SDKv4.28.0,
v4.31.0, and v4.32.0. As SCMI clock IDs are identical for SDKv4.31.0
and v4.32.0, r8a78000_cpg_fw_4_31_0[] applies to both of them.
Suggested-by: Marek Vasut <marek.vasut+renesas@mailbox.org>
Signed-off-by: Geert Uytterhoeven <geert+renesas@glider.be>
---
drivers/clk/renesas/Kconfig | 4 +
drivers/clk/renesas/Makefile | 1 +
drivers/clk/renesas/r8a78000-cpg.c | 335 +++++++++++++++++++++++++++++
3 files changed, 340 insertions(+)
create mode 100644 drivers/clk/renesas/r8a78000-cpg.c
diff --git a/drivers/clk/renesas/Kconfig b/drivers/clk/renesas/Kconfig
index 0203ecbb38825f13..f0482bdfc4616cfa 100644
--- a/drivers/clk/renesas/Kconfig
+++ b/drivers/clk/renesas/Kconfig
@@ -34,6 +34,7 @@ config CLK_RENESAS
select CLK_R8A779F0 if ARCH_R8A779F0
select CLK_R8A779G0 if ARCH_R8A779G0
select CLK_R8A779H0 if ARCH_R8A779H0
+ select CLK_R8A78000 if ARCH_R8A78000
select CLK_R9A06G032 if ARCH_R9A06G032
select CLK_R9A07G043 if ARCH_R9A07G043
select CLK_R9A07G044 if ARCH_R9A07G044
@@ -176,6 +177,9 @@ config CLK_R8A779H0
bool "R-Car V4M clock support" if COMPILE_TEST
select CLK_RCAR_GEN4_CPG
+config CLK_R8A78000
+ bool "R-Car X5H clock support" if COMPILE_TEST
+
config CLK_R9A06G032
bool "RZ/N1D clock support" if COMPILE_TEST
diff --git a/drivers/clk/renesas/Makefile b/drivers/clk/renesas/Makefile
index bd2bed91ab291d72..4f76f8c402ffe9a3 100644
--- a/drivers/clk/renesas/Makefile
+++ b/drivers/clk/renesas/Makefile
@@ -31,6 +31,7 @@ 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_R8A779H0) += r8a779h0-cpg-mssr.o
+obj-$(CONFIG_CLK_R8A78000) += r8a78000-cpg.o
obj-$(CONFIG_CLK_R9A06G032) += r9a06g032-clocks.o
obj-$(CONFIG_CLK_R9A07G043) += r9a07g043-cpg.o
obj-$(CONFIG_CLK_R9A07G044) += r9a07g044-cpg.o
diff --git a/drivers/clk/renesas/r8a78000-cpg.c b/drivers/clk/renesas/r8a78000-cpg.c
new file mode 100644
index 0000000000000000..844d909bbee2adbb
--- /dev/null
+++ b/drivers/clk/renesas/r8a78000-cpg.c
@@ -0,0 +1,335 @@
+// SPDX-License-Identifier: GPL-2.0
+/*
+ * R-Car X5H Clock Pulse Generator
+ *
+ * Copyright (C) 2026 Glider bv
+ */
+
+#include <linux/cleanup.h>
+#include <linux/clk.h>
+#include <linux/clk-provider.h>
+#include <linux/dev_printk.h>
+#include <linux/module.h>
+#include <linux/mod_devicetable.h>
+#include <linux/of.h>
+#include <linux/platform_device.h>
+#include <linux/scmi_protocol.h>
+#include <linux/slab.h>
+
+#include <dt-bindings/clock/renesas,r8a78000-cpg.h>
+
+struct clk_map_in {
+ int dt_id; /* DT binding clock ID */
+ u32 fw_id; /* SCMI firmware clock ID */
+};
+
+struct clk_map {
+ int dt_id; /* DT binding clock ID */
+ u32 fw_id; /* SCMI firmware clock ID */
+ struct clk_hw *hw;
+};
+
+struct fw_map {
+ u32 impl_ver;
+ const struct clk_map_in *map;
+};
+
+enum fixed_clk {
+ FIXED_CLK_66M,
+ FIXED_CLK_266M,
+ NUM_FIXED_CLKS
+};
+
+static const unsigned long fixed_clk_rates[NUM_FIXED_CLKS] = {
+ [FIXED_CLK_66M] = 66666000,
+ [FIXED_CLK_266M] = 266660000,
+};
+
+#define FIXED_CLK_OFFSET 0x80000000
+#define FIXED_CLK(rate) FIXED_CLK_OFFSET + FIXED_CLK_ ## rate
+
+/**
+ * struct r8a78000_cpg_priv - Clock Pulse Generator Private Data
+ *
+ * @dev: CPG device
+ * @scmi_clk_np: Device node in DT for the SCMI firmware clock protocol
+ * @map: Mapping from DT clock IDs to SCMI clocks
+ * @fixed_hws: Fixed rate clocks used to replace SCMI clocks that do not
+ * support the SCMI CLOCK_ATTRIBUTES command
+ */
+struct r8a78000_cpg_priv {
+ struct device *dev;
+ struct device_node *scmi_clk_np;
+ const struct clk_map *map;
+ struct clk_hw *fixed_hws[NUM_FIXED_CLKS];
+};
+
+static const struct clk_map *clk_map_find(const struct clk_map *map, u32 id)
+{
+ if (!map)
+ return NULL;
+
+ for (; map->dt_id >= 0; map++) {
+ if (map->dt_id == id)
+ return map;
+ }
+
+ return NULL;
+}
+
+static struct clk_hw *r8a78000_clk_get(struct of_phandle_args *spec,
+ void *data)
+{
+ struct r8a78000_cpg_priv *priv = data;
+ struct device *dev = priv->dev;
+ const struct clk_map *map;
+ struct clk_hw *hw;
+ u32 id;
+
+ if (spec->args_count != 1)
+ return ERR_PTR(-EINVAL);
+
+ id = spec->args[0];
+
+ map = clk_map_find(priv->map, id);
+ if (!map) {
+ dev_err(dev, "Unknown clock %u\n", id);
+ return ERR_PTR(-ENOENT);
+ }
+
+ if (map->fw_id < FIXED_CLK_OFFSET)
+ dev_dbg(dev, "Mapping DT clock %u to SCMI clock %u\n", id,
+ map->fw_id);
+ else
+ dev_dbg(dev, "Mapping DT clock %u to fixed clock %u\n", id,
+ map->fw_id - FIXED_CLK_OFFSET);
+
+ hw = map->hw;
+ if (!hw) {
+ /* CLOCK_ATTRIBUTES is not supported */
+ dev_err(dev, "Clock %u is not available\n", id);
+ return ERR_PTR(-ENOENT);
+ }
+
+ dev_dbg(dev, "clock %u is %s at %lu Hz\n", id, clk_hw_get_name(hw),
+ clk_hw_get_rate(hw));
+
+ return hw;
+}
+
+static struct device_node *scmi_find_proto(struct device_node *scmi, u32 proto)
+{
+ for_each_available_child_of_node_scoped(scmi, child) {
+ u32 reg;
+
+ if (of_property_read_u32(child, "reg", ®))
+ continue;
+
+ if (reg == proto)
+ return_ptr(child);
+ }
+
+ return NULL;
+}
+
+static void unregister_fixed_clks(void *data)
+{
+ struct r8a78000_cpg_priv *priv = data;
+
+ for (unsigned int i = 0; i < ARRAY_SIZE(priv->fixed_hws); i++)
+ clk_hw_unregister_fixed_rate(priv->fixed_hws[i]);
+}
+
+static int register_fixed_clks(struct r8a78000_cpg_priv *priv)
+{
+ struct device *dev = priv->dev;
+ unsigned long rate;
+ struct clk_hw *hw;
+ const char *name;
+
+ for (unsigned int i = 0; i < ARRAY_SIZE(fixed_clk_rates); i++) {
+ rate = fixed_clk_rates[i];
+ name = devm_kasprintf(dev, GFP_KERNEL, "cpg-%lu", rate);
+ if (!name)
+ return -ENOMEM;
+
+ hw = clk_hw_register_fixed_rate(dev, name, NULL, 0, rate);
+ if (IS_ERR(hw)) {
+ while (i-- > 0)
+ clk_hw_unregister_fixed_rate(priv->fixed_hws[i]);
+ return PTR_ERR(hw);
+ }
+
+ priv->fixed_hws[i] = hw;
+ }
+
+ return devm_add_action_or_reset(dev, unregister_fixed_clks, priv);
+}
+
+static const struct clk_map *fill_clk_map(struct r8a78000_cpg_priv *priv,
+ const struct clk_map_in *map_in)
+{
+ struct of_phandle_args scmi_spec;
+ struct device *dev = priv->dev;
+ struct clk_map *map;
+ struct clk_hw *hw;
+ struct clk *clk;
+ unsigned int i;
+
+ for (i = 0; map_in[i].dt_id >= 0; i++) { }
+
+ map = devm_kcalloc(dev, i + 1, sizeof(*map), GFP_KERNEL);
+ if (!map)
+ return ERR_PTR(-ENOMEM);
+
+ for (i = 0; ; i++) {
+ map[i].dt_id = map_in[i].dt_id;
+ if (map[i].dt_id < 0)
+ break;
+
+ map[i].fw_id = map_in[i].fw_id;
+ if (map[i].fw_id >= FIXED_CLK_OFFSET) {
+ enum fixed_clk idx = map[i].fw_id - FIXED_CLK_OFFSET;
+
+ map[i].hw = priv->fixed_hws[idx];
+ continue;
+ }
+
+ scmi_spec.np = priv->scmi_clk_np;
+ scmi_spec.args_count = 1;
+ scmi_spec.args[0] = map[i].fw_id;
+
+ clk = of_clk_get_from_provider(&scmi_spec);
+ if (IS_ERR(clk))
+ return dev_err_cast_probe(dev, clk,
+ "Failed to get SCMI clock %u\n",
+ map[i].fw_id);
+
+ hw = __clk_get_hw(clk);
+ if (IS_ERR(hw))
+ return dev_err_cast_probe(dev, hw,
+ "Failed to get SCMI clock hw %u\n",
+ map[i].fw_id);
+
+ if (!hw) {
+ /* CLOCK_ATTRIBUTES is not supported */
+ dev_warn(dev, "SCMI clock %u is NULL\n", map[i].fw_id);
+ continue;
+ }
+
+ dev_dbg(priv->dev, "SCMI clock %u is %s at %lu Hz\n",
+ map[i].fw_id, clk_hw_get_name(hw), clk_hw_get_rate(hw));
+
+ map[i].hw = hw;
+ }
+
+ return map;
+}
+
+static int r8a78000_cpg_probe(struct platform_device *pdev)
+{
+ struct device_node *scmi __free(device_node) = NULL;
+ struct device *dev = &pdev->dev;
+ struct scmi_base_info version;
+ const struct fw_map *fw_map;
+ struct r8a78000_cpg_priv *priv;
+ int ret;
+
+ priv = devm_kzalloc(dev, sizeof(*priv), GFP_KERNEL);
+ if (!priv)
+ return -ENOMEM;
+
+ priv->dev = dev;
+
+ scmi = of_parse_phandle(dev->of_node, "firmware", 0);
+ if (!scmi) {
+ dev_err(dev, "Cannot find SCMI firmware node\n");
+ return -ENODEV;
+ }
+
+ priv->scmi_clk_np = scmi_find_proto(scmi, SCMI_PROTOCOL_CLOCK);
+ if (!priv->scmi_clk_np) {
+ dev_err(dev, "Cannot find SCMI clock management protocol\n");
+ return -ENODEV;
+ }
+
+ ret = scmi_get_base_info(scmi, &version);
+ if (ret) {
+ return dev_err_probe(dev, -EPROBE_DEFER,
+ "SCMI not yet available\n");
+ }
+
+ if (strcmp(version.vendor_id, "Renesas") ||
+ strcmp(version.sub_vendor_id, "None")) {
+ return dev_err_probe(dev, -ENODEV,
+ "Unsupported SCMI firmware %s/%s\n",
+ version.vendor_id, version.sub_vendor_id);
+ }
+
+ for (fw_map = of_device_get_match_data(dev); fw_map->map; fw_map++) {
+ if (fw_map->impl_ver == version.impl_ver)
+ break;
+ }
+
+ if (!fw_map->map) {
+ return dev_err_probe(dev, -ENODEV,
+ "Unsupported SCMI version 0x%08x\n",
+ version.impl_ver);
+ }
+
+ ret = register_fixed_clks(priv);
+ if (ret)
+ return ret;
+
+ /*
+ * We cannot do lazy look-up in r8a78000_clk_get(), as that function is
+ * called with of_clk_mutex already held.
+ */
+ priv->map = fill_clk_map(priv, fw_map->map);
+ if (IS_ERR(priv->map))
+ return PTR_ERR(priv->map);
+
+ return devm_of_clk_add_hw_provider(dev, r8a78000_clk_get, priv);
+}
+
+static const struct clk_map_in r8a78000_cpg_fw_4_28_0[] = {
+ { R8A78000_CPG_SGASYNCD4_PERW_BUS, FIXED_CLK(266M) },
+ { R8A78000_CPG_SGASYNCD16_PERW_BUS, FIXED_CLK(66M) },
+ { R8A78000_CPG_MSOCK_PERW_BUS, 1671 },
+ { -1 }
+};
+
+static const struct clk_map_in r8a78000_cpg_fw_4_31_0[] = {
+ { R8A78000_CPG_SGASYNCD4_PERW_BUS, FIXED_CLK(266M) },
+ { R8A78000_CPG_SGASYNCD16_PERW_BUS, FIXED_CLK(66M) },
+ { R8A78000_CPG_MSOCK_PERW_BUS, 1667 },
+ { -1 }
+};
+
+static const struct fw_map r8a78000_cpg_fw_map[] = {
+ { 0x010a0000, r8a78000_cpg_fw_4_28_0 }, /* SCP FW SDKv4.28.0 */
+ { 0x010d0000, r8a78000_cpg_fw_4_31_0 }, /* SCP FW SDKv4.31.0 */
+ { 0x010e0000, r8a78000_cpg_fw_4_31_0 }, /* SCP FW SDKv4.32.0 */
+ { 0, NULL }
+};
+
+static const struct of_device_id r8a78000_cpg_match[] = {
+ {
+ .compatible = "renesas,r8a78000-cpg",
+ .data = &r8a78000_cpg_fw_map,
+ },
+ { /* sentinel */ }
+};
+
+static struct platform_driver r8a78000_cpg_driver = {
+ .probe = r8a78000_cpg_probe,
+ .driver = {
+ .name = "r8a78000-cpg",
+ .of_match_table = r8a78000_cpg_match,
+ .suppress_bind_attrs = true,
+ },
+};
+
+builtin_platform_driver(r8a78000_cpg_driver)
+
+MODULE_DESCRIPTION("R-Car X5H CPG Driver");
--
2.43.0
^ permalink raw reply related
* [PATCH/RFC 10/14] dt-bindings: power: Document Renesas R-Car X5H Module Controller
From: Geert Uytterhoeven @ 2026-04-21 18:11 UTC (permalink / raw)
To: Sudeep Holla, Cristian Marussi, Rob Herring, Krzysztof Kozlowski,
Conor Dooley, Magnus Damm, Saravana Kannan, Michael Turquette,
Stephen Boyd, Philipp Zabel, Ulf Hansson, Rafael J . Wysocki,
Kevin Hilman, Florian Fainelli, Wolfram Sang, Marek Vasut,
Kuninori Morimoto
Cc: arm-scmi, linux-arm-kernel, linux-renesas-soc, linux-clk,
devicetree, linux-pm, linux-kernel, Geert Uytterhoeven
In-Reply-To: <cover.1776793163.git.geert+renesas@glider.be>
Document support for Renesas R-Car X5H Module Controllers, and
add definitions for power domains not backed by registers.
Signed-off-by: Geert Uytterhoeven <geert+renesas@glider.be>
---
.../bindings/power/renesas,r8a78000-mdlc.yaml | 63 +++++++++++++++++++
.../dt-bindings/power/renesas,r8a78000-mdlc.h | 16 +++++
2 files changed, 79 insertions(+)
create mode 100644 Documentation/devicetree/bindings/power/renesas,r8a78000-mdlc.yaml
create mode 100644 include/dt-bindings/power/renesas,r8a78000-mdlc.h
diff --git a/Documentation/devicetree/bindings/power/renesas,r8a78000-mdlc.yaml b/Documentation/devicetree/bindings/power/renesas,r8a78000-mdlc.yaml
new file mode 100644
index 0000000000000000..c3075bb308962f59
--- /dev/null
+++ b/Documentation/devicetree/bindings/power/renesas,r8a78000-mdlc.yaml
@@ -0,0 +1,63 @@
+# SPDX-License-Identifier: (GPL-2.0-only OR BSD-2-Clause)
+%YAML 1.2
+---
+$id: http://devicetree.org/schemas/power/renesas,r8a78000-mdlc.yaml#
+$schema: http://devicetree.org/meta-schemas/core.yaml#
+
+title: Renesas R-Car X5H Module Controller
+
+maintainers:
+ - Geert Uytterhoeven <geert+renesas@glider.be>
+
+description:
+ Each instance of the R-Car X5H Module Controller (MODULE CONTROL) provides
+ Power Gating for up to 64 Power Domains, and Module Standby and Reset for up
+ to 256 modules in the Power Domain of each Module hierarchy.
+
+properties:
+ compatible:
+ const: renesas,r8a78000-mdlc
+
+ reg:
+ maxItems: 1
+
+ '#power-domain-cells':
+ description: |
+ - The first power domain specifier cell must be either the Module
+ Power Domain Gating (MPDG) register index (0x00-0x3f) from the
+ datasheet, or a Power Domain number, as defined in
+ <dt-bindings/power/renesas,r8a78000-mdlc.h>,
+ - The second power domain specifier cell must be the module number
+ (0x00-0xff), composed of the Module System Reset (MSRES) register index
+ in the high nibble, and the Module Reset Destination bitfield index in
+ the low nibble.
+ const: 2
+
+ '#reset-cells':
+ description:
+ The single reset specifier cell must be the module number (0x00-0xff).
+ const: 1
+
+ firmware:
+ $ref: /schemas/types.yaml#/definitions/phandle
+ description:
+ Reference to the SCMI firmware device node on systems where SCMI must be
+ used instead of direct hardware access.
+
+required:
+ - compatible
+ - reg
+ - '#power-domain-cells'
+ - '#reset-cells'
+
+additionalProperties: false
+
+examples:
+ - |
+ system-controller@c3060000 {
+ compatible = "renesas,r8a78000-mdlc";
+ reg = <0xc3060000 0x1000>;
+ #power-domain-cells = <2>;
+ #reset-cells = <1>;
+ firmware = <&scmi>;
+ };
diff --git a/include/dt-bindings/power/renesas,r8a78000-mdlc.h b/include/dt-bindings/power/renesas,r8a78000-mdlc.h
new file mode 100644
index 0000000000000000..31aa4935a7c5cf94
--- /dev/null
+++ b/include/dt-bindings/power/renesas,r8a78000-mdlc.h
@@ -0,0 +1,16 @@
+/* SPDX-License-Identifier: (GPL-2.0-only OR BSD-2-Clause) */
+/*
+ * Copyright (C) 2026 Glider bv
+ */
+#ifndef __DT_BINDINGS_POWER_RENESAS_R8A78000_MDLC_H__
+#define __DT_BINDINGS_POWER_RENESAS_R8A78000_MDLC_H__
+
+/* R-Car X5H MDLC Power Domains */
+
+#define R8A78000_MDLC_PD_AON 0x40
+#define R8A78000_MDLC_PD_SCP 0x41
+#define R8A78000_MDLC_PD_APL 0x42
+#define R8A78000_MDLC_PD_CMN 0x43
+#define R8A78000_MDLC_PD_ACL 0x44
+
+#endif /* __DT_BINDINGS_POWER_RENESAS_R8A78000_MDLC_H__ */
--
2.43.0
^ permalink raw reply related
page: next (older) | prev (newer) | latest
- recent:[subjects (threaded)|topics (new)|topics (active)]
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox