On Mon, May 11, 2026 at 12:49:50AM +0300, Stefan Dösinger wrote: > These SoCs have 3 clock and reset controllers. The "top" controller - > all names follow ZTE's naming - controls core devices like the AHB bus, > most timers and the Cortex M0 that brings up the board. The register > layout is fairly chaotic. Some patterns can be found, but nothing that > holds true for all devices it controls. > > Generally every device has two clocks (one work clock, and one that > connects it to the bus, I call it PCLK), two reset bits (I don't know > what the difference is - sometimes asserting one is enough to reset the > device, sometimes both need to be asserted) and one mux. Some devices, > like the GPIO controller, only have reset bits and no clocks. > > The top clock controller is fed by a 26mhz external oscillator and has 4 > PLLs to generate other clock rates. ZTE's kernel does not manipulate the > PLLs at all and relies on BROM and the boot loader to set them up. The > bitfields in the control registers are somewhat documented in a > Lauterback TRACE32 debug file in the kernel sources though. At the > moment, my driver extracts clock rates from the PLLs, but cannot change > them. A proper PLL clk is on my TODO list before I remove the [RFC] tag > from the submission. It will be necessary for the LTE hardware with > replacement boot loaders because BROM does not set up the LTE-related > PLL. > > The "matrix" controller controls the main Cortex A53 CPU, the LTE ZSP, > SDIO and a few others. It is even more chaotic than the "top" > controller. > > The "LSP" controller - I suspect it stands for "low speed peripherals" - > is very regular. One 32 bit register for 2 clock gates, two resets, one > mux (1-3 bit) and in some cases a 4 bit divider. > > Not all clocks will have an explicit user in the end. I am defining a > lot of them simply to shut them off. The boot loader sets up a few of > the proprietary timers, which will send regular IRQs (although the > kernel of course doesn't need to listen to them). I don't plan to add a > driver for the proprietary timer as I see no use for them - the ARM arch > timer works just fine. I will add a driver for the very similar > proprietary watchdog though. > > The top and matrix list is not exhaustive. There are other bits > that are enabled, but I couldn't deduce what they are controlling by > trial and error. Some of them seem to do nothing. Others cause an > instant hang of the board when disabled. I isolated a few (SRAM PCLK, > arm arch timer clock) where I don't see a reason to manipulate them. It > is quite likely that a handful more clocks will be added in the future, > but not a large number. > > Signed-off-by: Stefan Dösinger > --- > .../bindings/clock/zte,zx297520v3-clk.yaml | 173 ++++++++++++++++++++ > include/dt-bindings/clock/zte,zx297520v3-clk.h | 179 +++++++++++++++++++++ > 2 files changed, 352 insertions(+) > > diff --git a/Documentation/devicetree/bindings/clock/zte,zx297520v3-clk.yaml b/Documentation/devicetree/bindings/clock/zte,zx297520v3-clk.yaml > new file mode 100644 > index 000000000000..3b7084a18a97 > --- /dev/null > +++ b/Documentation/devicetree/bindings/clock/zte,zx297520v3-clk.yaml > @@ -0,0 +1,173 @@ > +# SPDX-License-Identifier: (GPL-2.0-only OR BSD-2-Clause) > +%YAML 1.2 > +--- > +$id: http://devicetree.org/schemas/clock/zte,zx297520v3-clk.yaml# > +$schema: http://devicetree.org/meta-schemas/core.yaml# > + > +title: ZTE zx297520v3 SoC clock and reset controller > + > +maintainers: > + - Stefan Dösinger > + > +description: | > + The zx297520v3's clock controller consists of 3 controllers, which generate > + clocks for internal SoC devices. In addition to clocks it also has reset > + controls for most, but not all, devices. > + > + While there is a certain hierarchy among the controllers ("top" controlls core > + parts like the boot-up Cortex M0, "matrix" controls the main CPU and LTE DSP, > + "lsp" controls peripherals"), in practise all 3 are required to reasonably > + operate the SoC. > + > + The top controller has two inputs: a 26 MHz and a 32 KHz external oscillator. > + They need to be provided as input clocks. The matrix controller controlls 10 > + clock lines that get fed into the LSP controller. The LSP device node needs > + to list these input clocks. > + > + The matrix controller consumes clocks generated by PLLs in the top > + controller, but there are no controls in the top controller to sever this > + link. The interface between these controllers is not expressed in the device > + tree, but the matrix controller cannot work without the clock handles > + registered by the top controller. > + > + All available clocks are defined as preprocessor macros in > + 'dt-bindings/clock/zte,zx297520v3-clk.h' header. > + > +properties: > + compatible: > + enum: > + - zte,zx297520v3-topclk > + - zte,zx297520v3-matrixclk How come the "matrixclk" has no constraints on clock properties? > + - zte,zx297520v3-lspclk > + > + clocks: > + minItems: 2 > + maxItems: 10 > + > + clock-names: > + minItems: 2 > + maxItems: 10 > + > + "#clock-cells": > + const: 1 > + > + "#reset-cells": > + const: 1 > + > + reg: > + maxItems: 1 > + > +allOf: > + - if: > + properties: > + compatible: > + contains: > + const: zte,zx297520v3-topclk > + then: > + properties: > + clocks: > + items: > + - description: External reference clock (26 MHz) > + - description: External reference clock (32 KHz) > + clock-names: > + items: > + - const: osc26m > + - const: osc32k > + required: > + - clocks > + - clock-names > + > + - if: > + properties: > + compatible: > + contains: > + const: zte,zx297520v3-lspclk Although, these two devices seem too different to be in the same dt-binding. Do they have anyhting in common other than the SoC they are part of? Cheers, Conor. > + then: > + properties: > + clocks: > + items: > + - description: Main PLL divided by 5 output from matrixclk (124.8 MHz) > + - description: Main PLL divided by 4 output from matrixclk (156 MHz) > + - description: Main PLL divided by 6 output from matrixclk (104 MHz) > + - description: Main PLL divided by 8 output from matrixclk (78 MHz) > + - description: Main PLL divided by 12 output from matrixclk (52 MHz) > + - description: Main oscillator output from matrixclk (26 MHz) > + - description: Timer oscillator output from matrixclk (32 KHz) > + - description: LSP pclk output from matrixclk (26 MHz) > + - description: TDM wclk mux output from matrixclk > + - description: DPLL divided by 4 output from matrixclk (122.88 MHz) > + clock-names: > + items: > + - const: mpll_d5 > + - const: mpll_d4 > + - const: mpll_d6 > + - const: mpll_d8 > + - const: mpll_d12 > + - const: osc26m > + - const: osc32k > + - const: pclk > + - const: tdm_wclk > + - const: dpll_d4 > + required: > + - clocks > + - clock-names > + > +additionalProperties: false > + > +required: > + - compatible > + - '#clock-cells' > + - reg > + - '#reset-cells' > + > +examples: > + - | > + #include > + > + osc26m: osc26m { > + compatible = "fixed-clock"; > + clock-output-names = "osc26m"; > + #clock-cells = <0>; > + }; > + > + osc32k: osc32k { > + compatible = "fixed-clock"; > + clock-output-names = "osc32k"; > + #clock-cells = <0>; > + }; > + > + topclk: topclk@13b000 { > + compatible = "zte,zx297520v3-topclk"; > + reg = <0x0013b000 0x400>; > + #clock-cells = <1>; > + #reset-cells = <1>; > + clocks = <&osc26m>, <&osc32k>; > + clock-names = "osc26m", "osc32k"; > + }; > + > + matrixclk: matrixclk@1306000 { > + compatible = "zte,zx297520v3-matrixclk"; > + reg = <0x01306000 0x400>; > + #clock-cells = <1>; > + #reset-cells = <1>; > + }; > + > + lspclk: lspclk@1400000 { > + compatible = "zte,zx297520v3-lspclk"; > + reg = <0x01400000 0x100>; > + #clock-cells = <1>; > + #reset-cells = <1>; > + > + clocks = <&matrixclk ZX297520V3_LSP_MPLL_D5_WCLK>, > + <&matrixclk ZX297520V3_LSP_MPLL_D4_WCLK>, > + <&matrixclk ZX297520V3_LSP_MPLL_D6_WCLK>, > + <&matrixclk ZX297520V3_LSP_MPLL_D8_WCLK>, > + <&matrixclk ZX297520V3_LSP_MPLL_D12_WCLK>, > + <&matrixclk ZX297520V3_LSP_OSC26M_WCLK>, > + <&matrixclk ZX297520V3_LSP_OSC32K_WCLK>, > + <&matrixclk ZX297520V3_LSP_PCLK>, > + <&matrixclk ZX297520V3_LSP_TDM_WCLK>, > + <&matrixclk ZX297520V3_LSP_DPLL_D4_WCLK>; > + clock-names = "mpll_d5", "mpll_d4", "mpll_d6", "mpll_d8", "mpll_d12", > + "osc26m", "osc32k", "pclk", "tdm_wclk", "dpll_d4"; > + }; > diff --git a/include/dt-bindings/clock/zte,zx297520v3-clk.h b/include/dt-bindings/clock/zte,zx297520v3-clk.h > new file mode 100644 > index 000000000000..322b53be8b12 > --- /dev/null > +++ b/include/dt-bindings/clock/zte,zx297520v3-clk.h > @@ -0,0 +1,179 @@ > +/* SPDX-License-Identifier: (GPL-2.0-only OR BSD-2-Clause) */ > +/* > + * Copyright (C) Stefan Dösinger. > + */ > + > +#ifndef __DT_BINDINGS_CLOCK_ZX297520V3_H > +#define __DT_BINDINGS_CLOCK_ZX297520V3_H > + > +#define ZX297520V3_AHB_WCLK 0 > +#define ZX297520V3_AHB_PCLK 1 > +#define ZX297520V3_PMM_WCLK 2 > +#define ZX297520V3_PMM_PCLK 3 > +#define ZX297520V3_USB_24M 4 > +#define ZX297520V3_USB_AHB 5 > +#define ZX297520V3_TIMER_T08_WCLK 6 > +#define ZX297520V3_TIMER_T08_PCLK 7 > +#define ZX297520V3_TIMER_T09_WCLK 8 > +#define ZX297520V3_TIMER_T09_PCLK 9 > +#define ZX297520V3_TIMER_T12_WCLK 10 > +#define ZX297520V3_TIMER_T12_PCLK 11 > +#define ZX297520V3_TIMER_T13_WCLK 12 > +#define ZX297520V3_TIMER_T13_PCLK 13 > +#define ZX297520V3_TIMER_T14_WCLK 14 > +#define ZX297520V3_TIMER_T14_PCLK 15 > +#define ZX297520V3_TIMER_T15_WCLK 16 > +#define ZX297520V3_TIMER_T15_PCLK 17 > +#define ZX297520V3_TIMER_T16_WCLK 18 > +#define ZX297520V3_TIMER_T16_PCLK 19 > +#define ZX297520V3_TIMER_T17_WCLK 20 > +#define ZX297520V3_TIMER_T17_PCLK 21 > +#define ZX297520V3_WDT_T18_WCLK 22 > +#define ZX297520V3_WDT_T18_PCLK 23 > +#define ZX297520V3_UART0_WCLK 24 > +#define ZX297520V3_UART0_PCLK 25 > +#define ZX297520V3_I2C0_WCLK 26 > +#define ZX297520V3_I2C0_PCLK 27 > +#define ZX297520V3_RTC_WCLK 28 > +#define ZX297520V3_RTC_PCLK 29 > +#define ZX297520V3_LPM_GSM_WCLK 30 > +#define ZX297520V3_LPM_GSM_PCLK 31 > +#define ZX297520V3_LPM_LTE_WCLK 32 > +#define ZX297520V3_LPM_LTE_PCLK 33 > +#define ZX297520V3_LPM_TD_WCLK 34 > +#define ZX297520V3_LPM_TD_PCLK 35 > +#define ZX297520V3_LPM_W_WCLK 36 > +#define ZX297520V3_LPM_W_PCLK 37 > +#define ZX297520V3_USIM1_WCLK 38 > +#define ZX297520V3_USIM1_PCLK 39 > +#define ZX297520V3_M0_WCLK 40 > +#define ZX297520V3_TOPCLK_END 41 > + > +#define ZX297520V3_AHB_RESET 0 > +#define ZX297520V3_TIMER_T08_RESET 1 > +#define ZX297520V3_TIMER_T09_RESET 2 > +#define ZX297520V3_TIMER_T12_RESET 3 > +#define ZX297520V3_TIMER_T13_RESET 4 > +#define ZX297520V3_TIMER_T14_RESET 5 > +#define ZX297520V3_TIMER_T15_RESET 6 > +#define ZX297520V3_TIMER_T16_RESET 7 > +#define ZX297520V3_TIMER_T17_RESET 8 > +#define ZX297520V3_WDT_T18_RESET 9 > +#define ZX297520V3_UART0_RESET 10 > +#define ZX297520V3_I2C0_RESET 11 > +#define ZX297520V3_RTC_RESET 12 > +#define ZX297520V3_USIM1_RESET 13 > +#define ZX297520V3_PMM_RESET 14 > +#define ZX297520V3_GPIO8_RESET 15 > +#define ZX297520V3_GPIO_RESET 16 > +#define ZX297520V3_ZSP_RESET 17 > +#define ZX297520V3_USB_RESET 18 > +#define ZX297520V3_TOPRST_END 19 > + > +#define ZX297520V3_CPU_WCLK 0 > +#define ZX297520V3_CPU_PCLK 1 > +#define ZX297520V3_SD0_WCLK 2 > +#define ZX297520V3_SD0_PCLK 3 > +#define ZX297520V3_SD1_WCLK 4 > +#define ZX297520V3_SD1_PCLK 5 > +#define ZX297520V3_SD1_CDET 6 > +#define ZX297520V3_NAND_WCLK 7 > +#define ZX297520V3_NAND_PCLK 8 > +#define ZX297520V3_SSC_WCLK 9 > +#define ZX297520V3_SSC_PCLK 10 > +#define ZX297520V3_EDCP_WCLK 11 > +#define ZX297520V3_EDCP_PCLK 12 > +#define ZX297520V3_EDCP_SYNCAXI 13 > +#define ZX297520V3_VOU_WCLK 14 > +#define ZX297520V3_VOU_PCLK 15 > +#define ZX297520V3_PDCFG_WCLK 16 > +#define ZX297520V3_PDCFG_PCLK 17 > +#define ZX297520V3_GMAC_WCLK 18 > +#define ZX297520V3_GMAC_RMII 19 > +#define ZX297520V3_GMAC_PCLK 20 > +#define ZX297520V3_ZSP_WCLK 21 > +#define ZX297520V3_MBOX_PCLK 22 > +#define ZX297520V3_DMA_PCLK 23 > +#define ZX297520V3_LSP_MPLL_D5_WCLK 24 > +#define ZX297520V3_LSP_MPLL_D4_WCLK 25 > +#define ZX297520V3_LSP_MPLL_D6_WCLK 26 > +#define ZX297520V3_LSP_MPLL_D8_WCLK 27 > +#define ZX297520V3_LSP_MPLL_D12_WCLK 28 > +#define ZX297520V3_LSP_OSC26M_WCLK 29 > +#define ZX297520V3_LSP_OSC32K_WCLK 30 > +#define ZX297520V3_LSP_PCLK 31 > +#define ZX297520V3_LSP_TDM_WCLK 32 > +#define ZX297520V3_LSP_DPLL_D4_WCLK 33 > +#define ZX297520V3_MATRIXCLK_END 34 > + > +#define ZX297520V3_CPU_RESET 0 > +#define ZX297520V3_SD0_RESET 1 > +#define ZX297520V3_SD1_RESET 2 > +#define ZX297520V3_NAND_RESET 3 > +#define ZX297520V3_SSC_RESET 4 > +#define ZX297520V3_EDCP_RESET 5 > +#define ZX297520V3_VOU_RESET 6 > +#define ZX297520V3_PDCFG_RESET 7 > +#define ZX297520V3_GMAC_RESET 8 > +#define ZX297520V3_DMA_RESET 9 > +#define ZX297520V3_MATRIXRST_END 10 > + > +#define ZX297520V3_TIMER_L1_WCLK 0 > +#define ZX297520V3_TIMER_L1_PCLK 1 > +#define ZX297520V3_WDT_L2_WCLK 2 > +#define ZX297520V3_WDT_L2_PCLK 3 > +#define ZX297520V3_WDT_L3_WCLK 4 > +#define ZX297520V3_WDT_L3_PCLK 5 > +#define ZX297520V3_I2C1_WCLK 6 > +#define ZX297520V3_I2C1_PCLK 7 > +#define ZX297520V3_I2S0_WCLK 8 > +#define ZX297520V3_I2S0_PCLK 9 > +#define ZX297520V3_I2S1_WCLK 10 > +#define ZX297520V3_I2S1_PCLK 11 > +#define ZX297520V3_QSPI_WCLK 12 > +#define ZX297520V3_QSPI_PCLK 13 > +#define ZX297520V3_UART1_WCLK 14 > +#define ZX297520V3_UART1_PCLK 15 > +#define ZX297520V3_I2C2_WCLK 16 > +#define ZX297520V3_I2C2_PCLK 17 > +#define ZX297520V3_SPI0_WCLK 18 > +#define ZX297520V3_SPI0_PCLK 19 > +#define ZX297520V3_TIMER_LB_WCLK 20 > +#define ZX297520V3_TIMER_LB_PCLK 21 > +#define ZX297520V3_TIMER_LC_WCLK 22 > +#define ZX297520V3_TIMER_LC_PCLK 23 > +#define ZX297520V3_UART2_WCLK 24 > +#define ZX297520V3_UART2_PCLK 25 > +#define ZX297520V3_WDT_LE_WCLK 26 > +#define ZX297520V3_WDT_LE_PCLK 27 > +#define ZX297520V3_TIMER_LF_WCLK 28 > +#define ZX297520V3_TIMER_LF_PCLK 29 > +#define ZX297520V3_SPI1_WCLK 30 > +#define ZX297520V3_SPI1_PCLK 31 > +#define ZX297520V3_TIMER_L11_WCLK 32 > +#define ZX297520V3_TIMER_L11_PCLK 33 > +#define ZX297520V3_TDM_WCLK 34 > +#define ZX297520V3_TDM_PCLK 35 > +#define ZX297520V3_LSPCLK_END 36 > + > +#define ZX297520V3_TIMER_L1_RESET 0 > +#define ZX297520V3_WDT_L2_RESET 1 > +#define ZX297520V3_WDT_L3_RESET 2 > +#define ZX297520V3_I2C1_RESET 3 > +#define ZX297520V3_I2S0_RESET 4 > +#define ZX297520V3_I2S1_RESET 5 > +#define ZX297520V3_QSPI_RESET 6 > +#define ZX297520V3_UART1_RESET 7 > +#define ZX297520V3_I2C2_RESET 8 > +#define ZX297520V3_SPI0_RESET 9 > +#define ZX297520V3_TIMER_LB_RESET 10 > +#define ZX297520V3_TIMER_LC_RESET 11 > +#define ZX297520V3_UART2_RESET 12 > +#define ZX297520V3_WDT_LE_RESET 13 > +#define ZX297520V3_TIMER_LF_RESET 14 > +#define ZX297520V3_SPI1_RESET 15 > +#define ZX297520V3_TIMER_L11_RESET 16 > +#define ZX297520V3_TDM_RESET 17 > +#define ZX297520V3_LSPRST_END 18 > + > +#endif /* __DT_BINDINGS_CLOCK_ZX297520V3_H */ > > -- > 2.53.0 >