Linux clock framework development
 help / color / mirror / Atom feed
* [PATCH v7 0/7] clk: nuvoton: ma35d1: Fix mux parenting and peripheral clock rates
@ 2026-10-02 15:01 Miquel Raynal
  2026-10-02 15:01 ` [PATCH v7 1/7] clk: nuvoton: ma35d1: Use clk_hw pointers as mux parents Miquel Raynal
                   ` (6 more replies)
  0 siblings, 7 replies; 9+ messages in thread
From: Miquel Raynal @ 2026-10-02 15:01 UTC (permalink / raw)
  To: Jacky Huang, Shan-Chun Hung, Michael Turquette, Stephen Boyd,
	Richard Cochran, Arnd Bergmann, Brian Masney, Jerome Brunet,
	Rob Herring, Krzysztof Kozlowski, Conor Dooley, Andrew Jeffery,
	Avi Fishman, Tomer Maimon, Tali Perry, Patrick Venture,
	Nancy Yuen, Benjamin Fair
  Cc: Thomas Petazzoni, Steam Lin, linux-arm-kernel, linux-clk,
	linux-kernel, Krzysztof Kozlowski, devicetree, openbmc,
	Miquel Raynal, stable

I am in possession of an MA35D1 NuMaker board. The SPI controller has
been contributed, but at this stage it does not work with the current
clock driver.

The clock controller registers its muxes with .fw_name parent data,
which requires every internal clock name to be declared in the DT. As
the DT does not declare them, all parent lookups fail: muxes end up
registered as root clocks and most peripherals read a zero rate.

This conversion exposed a first issue with the WDT/WWDT parents which
were actually missing in the clock driver. I am not using these clocks
myself but it is worth fixing.

The second round of reviews raised another problem with the
crystals. HXT and LXT are external crystal oscillators wired on the
board, while HIRC and LIRC are on-chip RC oscillators. HXT was described
whereas LXT was not. The series now also takes the two crystal inputs
from the DT: they get documented in the bindings, described in the
boards and looked up by the driver (with a fallback for backward
compatibility).

Finally, I was still unsatisfied by the clock tree because there were
too many root clocks. Many "gates" were wrongly set aside from the
downstream clocks they would gate, and SYSPLL was simply not parented at
all (?).

The clock tree now looks much more accurate.

Signed-off-by: Miquel Raynal <miquel.raynal@bootlin.com>
---
Changes in v7:
- Avoid opencoding core helpers, replace them with existing helpers
  (mentioned by Jerome)
- Rebased on top of clk-next since the first patches have been applied
- Link to v6: https://lore.kernel.org/r/20260930-perso-ma35d1-upstream-clk-v6-0-48937ee6c9bb@bootlin.com

Changes in v6:
- Drop the clock output names entirely, they are not relevant.
- Error out when the crystal providers defer probing.
- Make sure gates are correctly parented.
- Make sure SYSPLL is parented.
- Link to v5: https://lore.kernel.org/r/20260929-perso-ma35d1-upstream-clk-v5-0-68533e935ee4@bootlin.com

Changes in v5:
- Fix the bindings wrt HXT and LXT.
- Fix the DT descriptions of HXT and LXT.
- Collect tags.
- Link to v4: https://lore.kernel.org/r/20260925-perso-ma35d1-upstream-clk-v4-0-f3697553391f@bootlin.com

Changes in v4:
- I forgot to bump the clock counter in the driver after adding the two
  new clocks in the bindings. Sashiko will keep complaining about the
  incoherency though. Since binding and driver changes should be kept
  separated, I cannot do both at the same time.
- Link to v3: https://lore.kernel.org/r/20260925-perso-ma35d1-upstream-clk-v3-0-ffbae7e020a8@bootlin.com

Changes in v3:
- Drop the number of clocks from the binding, set it in the driver only
- Split the binding/driver patches completely
- Link to v2: https://lore.kernel.org/r/20260921-perso-ma35d1-upstream-clk-v2-0-209fd32a8b00@bootlin.com

Changes in v2:
- New patch 1/3: register the missing WDT/WWDT parent clocks
- New patch 3/3: harden the code
- Link to v1: https://lore.kernel.org/r/20260813-perso-ma35d1-upstream-clk-v1-1-e78e5e6172ea@bootlin.com

---
Miquel Raynal (7):
      clk: nuvoton: ma35d1: Use clk_hw pointers as mux parents
      clk: nuvoton: ma35d1: Avoid possible error pointer dereferencing
      clk: nuvoton: ma35d1: Retrieve HXT/LXT from DT when possible
      clk: nuvoton: ma35d1: Reparent the gates correctly
      clk: nuvoton: ma35d1: Reparent SYSPLL correctly
      arm64: dts: nuvoton: ma35d1: Drop HXT clock output name
      arm64: dts: nuvoton: ma35d1: Add LXT crystal and clock-names

 arch/arm64/boot/dts/nuvoton/ma35d1-iot-512m.dts |   7 +-
 arch/arm64/boot/dts/nuvoton/ma35d1-som-256m.dts |   7 +-
 arch/arm64/boot/dts/nuvoton/ma35d1.dtsi         |   3 +-
 drivers/clk/nuvoton/clk-ma35d1-divider.c        |   3 +
 drivers/clk/nuvoton/clk-ma35d1-pll.c            |   3 +
 drivers/clk/nuvoton/clk-ma35d1.c                | 707 ++++++++----------------
 6 files changed, 264 insertions(+), 466 deletions(-)
---
base-commit: 6b78cda327cc2dbcd0e60f411ae014997a684b55
change-id: 20260813-perso-ma35d1-upstream-clk-65cacfc1a86b

Best regards,
-- 
Miquel Raynal <miquel.raynal@bootlin.com>


^ permalink raw reply	[flat|nested] 9+ messages in thread

* [PATCH v7 1/7] clk: nuvoton: ma35d1: Use clk_hw pointers as mux parents
  2026-10-02 15:01 [PATCH v7 0/7] clk: nuvoton: ma35d1: Fix mux parenting and peripheral clock rates Miquel Raynal
@ 2026-10-02 15:01 ` Miquel Raynal
  2026-10-02 15:01 ` [PATCH v7 2/7] clk: nuvoton: ma35d1: Avoid possible error pointer dereferencing Miquel Raynal
                   ` (5 subsequent siblings)
  6 siblings, 0 replies; 9+ messages in thread
From: Miquel Raynal @ 2026-10-02 15:01 UTC (permalink / raw)
  To: Jacky Huang, Shan-Chun Hung, Michael Turquette, Stephen Boyd,
	Richard Cochran, Arnd Bergmann, Brian Masney, Jerome Brunet,
	Rob Herring, Krzysztof Kozlowski, Conor Dooley, Andrew Jeffery,
	Avi Fishman, Tomer Maimon, Tali Perry, Patrick Venture,
	Nancy Yuen, Benjamin Fair
  Cc: Thomas Petazzoni, Steam Lin, linux-arm-kernel, linux-clk,
	linux-kernel, Krzysztof Kozlowski, devicetree, openbmc,
	Miquel Raynal, stable

The MA35D1 clock provider registers its muxes with parent data
structures filling .fw_name. This is not the ideal approach since that
would require a massive amount of internal clock names declaration in
the DT. Since the DT does not play the game of exposing all these names,
none of the parent lookups performed when instantiating the muxes
succeed. As a result, these muxes get registered as root clocks, leading
to a sadly flat clock tree and no frequency assigned to most of the
peripheral clocks:

                                 enable  prepare  protect
   clock                          count    count    count        rate

 usbphy1                             0       0        0        480000000
 usbphy0                             0       0        0        480000000
    husbh1_gate                      0       0        0        480000000
    husbh0_gate                      0       0        0        480000000
    usbh_gate                        0       0        0        480000000
    usbd_gate                        0       0        0        480000000
 syspll                              0       0        0        180000000
 lirc                                0       0        0        32000
    lirc_gate                        0       0        0        32000
 hirc                                0       0        0        12000000
    gtmr_gate                        0       0        0        12000000
    hirc_gate                        0       0        0        12000000
 lxt                                 0       0        0        32768
    rtc_gate                         0       0        0        32768
    lxt_gate                         0       0        0        32768
 hxt                                 0       0        0        24000000
    vpll                             0       0        0        1224000000
       dcup_div                      0       0        0        612000000
    epll                             0       0        0        6000000000
       epll_div8                     0       0        0        750000000

       epll_div4                     0       0        0        1500000000
       epll_div2                     0       0        0        3000000000
          emac1_gate                 0       0        0        3000000000

          emac0_gate                 0       0        0        3000000000

    apll                             0       0        0        6048000000
    ddrpll                           0       0        0        266460000
       ddr_gate                      0       0        0        266460000
       ddr6_gate                     0       0        0        266460000
       ddr0_gate                     0       0        0        266460000
    capll                            0       0        0        2400000000
    hxt_gate                         0       0        0        24000000
 clk_hxt                             0       0        0        24000000
 spi3_mux                            0       0        0        0
    spi3_gate                        0       0        0        0
 spi2_mux                            0       0        0        0
    spi2_gate                        0       0        0        0
 spi1_mux                            0       0        0        0
    spi1_gate                        0       0        0        0
 spi0_mux                            0       0        0        0
    spi0_gate                        0       0        0        0
 i2s1_mux                            0       0        0        0
    i2s1_gate                        0       0        0        0
 i2s0_mux                            0       0        0        0
    i2s0_gate                        0       0        0        0
...

Apart from the wrong clock tree representation, it means that none of
the device drivers (spi & i2c in the excerpt above) can actually query
their clock rate, or they would get 0Hz.

Instead of declaring the parents in the clk_parent_data structure, use
the actual HW clocks to lookup the parents directly: parents are
described by an array of indices into the controller's main clock table
(like in other clock controller drivers), which the "new" mux helper now
resolves.

The WDT and WWDT muxes list the /4096 children of PCLK3 and PCLK4 among
their possible parents. Those two clocks are now registered by the
previous commit, so their entries in the parent tables are restored
instead of being turned into invalid slots.

                                 enable  prepare  protect
   clock                          count    count    count        rate

 usbphy1                             0       0        0        480000000
 usbphy0                             0       0        0        480000000
    husbh1_gate                      0       0        0        480000000
    husbh0_gate                      0       0        0        480000000
    usbh_gate                        0       0        0        480000000
    usbd_gate                        0       0        0        480000000
 syspll                              1       1        0        180000000
    dbg_mux                          0       0        0        180000000
    sdh1_mux                         0       0        0        180000000
       sdh1_gate                     0       0        0        180000000
    sdh0_mux                         0       0        0        180000000
       sdh0_gate                     0       0        0        180000000
    sysclk1_mux                      2       2        0        180000000
       pclk4                         0       0        0        90000000
       pclk3                         0       0        0        90000000
          sspcc_gate                 0       0        0        90000000
          ssmcc_gate                 0       0        0        90000000
       hclk3                         0       0        0        90000000
       pclk2                         0       0        0        180000000
          eadc_div                   0       0        0        90000000
             eadc_gate               0       0        0        90000000
          qei1_gate                  0       0        0        180000000
          ecap1_gate                 0       0        0        180000000
          spi3_mux                   0       0        0        180000000
             spi3_gate               0       0        0        180000000
          spi1_mux                   0       0        0        180000000
             spi1_gate               0       0        0        180000000
          epwm1_gate                 0       0        0        180000000
          i2c5_gate                  0       0        0        180000000
          i2c2_gate                  0       0        0        180000000
       pclk1                         0       0        0        180000000
          qei2_gate                  0       0        0        180000000
          qei0_gate                  0       0        0        180000000
          ecap2_gate                 0       0        0        180000000
          ecap0_gate                 0       0        0        180000000
          spi2_mux                   0       0        0        180000000
             spi2_gate               0       0        0        180000000
          spi0_mux                   0       0        0        180000000
             spi0_gate               0       0        0        180000000
          epwm2_gate                 0       0        0        180000000
          epwm0_gate                 0       0        0        180000000
          i2c4_gate                  0       0        0        180000000
          i2c1_gate                  0       0        0        180000000
       pclk0                         1       1        0        180000000
          adc_div                    0       0        0        90000000
             adc_gate                0       0        0        90000000
          qspi1_mux                  0       0        0        180000000
             qspi1_gate              0       0        0        180000000
          qspi0_mux                  1       1        0        180000000
             qspi0_gate              1       1        0        180000000

          i2c3_gate                  0       0        0        180000000
          i2c0_gate                  0       0        0        180000000

Fixes: f50a000b4219 ("clk: nuvoton: Use clk_parent_data instead of string for parent clock")
Cc: stable@vger.kernel.org
Signed-off-by: Miquel Raynal <miquel.raynal@bootlin.com>
---
 drivers/clk/nuvoton/clk-ma35d1.c | 626 +++++++++++----------------------------
 1 file changed, 177 insertions(+), 449 deletions(-)

diff --git a/drivers/clk/nuvoton/clk-ma35d1.c b/drivers/clk/nuvoton/clk-ma35d1.c
index c914079cee2d..1a857f28310f 100644
--- a/drivers/clk/nuvoton/clk-ma35d1.c
+++ b/drivers/clk/nuvoton/clk-ma35d1.c
@@ -63,300 +63,49 @@ static DEFINE_SPINLOCK(ma35d1_lock);
 #define PLL_MODE_FRAC           1
 #define PLL_MODE_SS             2
 
-static const struct clk_parent_data ca35clk_sel_clks[] = {
-	{ .fw_name = "hxt", },
-	{ .fw_name = "capll", },
-	{ .fw_name = "ddrpll", },
-};
+#define MA35D1_MUX_MAX_PARENTS	10
 
-static const struct clk_parent_data sysclk0_sel_clks[] = {
-	{ .fw_name = "epll_div2", },
-	{ .fw_name = "syspll", },
-};
-
-static const struct clk_parent_data sysclk1_sel_clks[] = {
-	{ .fw_name = "hxt", },
-	{ .fw_name = "syspll", },
-};
-
-static const struct clk_parent_data axiclk_sel_clks[] = {
-	{ .fw_name = "capll_div2", },
-	{ .fw_name = "capll_div4", },
-};
-
-static const struct clk_parent_data ccap_sel_clks[] = {
-	{ .fw_name = "hxt", },
-	{ .fw_name = "vpll", },
-	{ .fw_name = "apll", },
-	{ .fw_name = "syspll", },
-};
-
-static const struct clk_parent_data sdh_sel_clks[] = {
-	{ .fw_name = "syspll", },
-	{ .fw_name = "apll", },
-};
-
-static const struct clk_parent_data dcu_sel_clks[] = {
-	{ .fw_name = "epll_div2", },
-	{ .fw_name = "syspll", },
-};
-
-static const struct clk_parent_data gfx_sel_clks[] = {
-	{ .fw_name = "epll", },
-	{ .fw_name = "syspll", },
-};
-
-static const struct clk_parent_data dbg_sel_clks[] = {
-	{ .fw_name = "hirc", },
-	{ .fw_name = "syspll", },
-};
-
-static const struct clk_parent_data timer0_sel_clks[] = {
-	{ .fw_name = "hxt", },
-	{ .fw_name = "lxt", },
-	{ .fw_name = "pclk0", },
-	{ .index = -1, },
-	{ .index = -1, },
-	{ .fw_name = "lirc", },
-	{ .index = -1, },
-	{ .fw_name = "hirc", },
-};
-
-static const struct clk_parent_data timer1_sel_clks[] = {
-	{ .fw_name = "hxt", },
-	{ .fw_name = "lxt", },
-	{ .fw_name = "pclk0", },
-	{ .index = -1, },
-	{ .index = -1, },
-	{ .fw_name = "lirc", },
-	{ .index = -1, },
-	{ .fw_name = "hirc", },
-};
-
-static const struct clk_parent_data timer2_sel_clks[] = {
-	{ .fw_name = "hxt", },
-	{ .fw_name = "lxt", },
-	{ .fw_name = "pclk1", },
-	{ .index = -1, },
-	{ .index = -1, },
-	{ .fw_name = "lirc", },
-	{ .index = -1, },
-	{ .fw_name = "hirc", },
-};
-
-static const struct clk_parent_data timer3_sel_clks[] = {
-	{ .fw_name = "hxt", },
-	{ .fw_name = "lxt", },
-	{ .fw_name = "pclk1", },
-	{ .index = -1, },
-	{ .index = -1, },
-	{ .fw_name = "lirc", },
-	{ .index = -1, },
-	{ .fw_name = "hirc", },
-};
-
-static const struct clk_parent_data timer4_sel_clks[] = {
-	{ .fw_name = "hxt", },
-	{ .fw_name = "lxt", },
-	{ .fw_name = "pclk2", },
-	{ .index = -1, },
-	{ .index = -1, },
-	{ .fw_name = "lirc", },
-	{ .index = -1, },
-	{ .fw_name = "hirc", },
-};
-
-static const struct clk_parent_data timer5_sel_clks[] = {
-	{ .fw_name = "hxt", },
-	{ .fw_name = "lxt", },
-	{ .fw_name = "pclk2", },
-	{ .index = -1, },
-	{ .index = -1, },
-	{ .fw_name = "lirc", },
-	{ .index = -1, },
-	{ .fw_name = "hirc", },
-};
-
-static const struct clk_parent_data timer6_sel_clks[] = {
-	{ .fw_name = "hxt", },
-	{ .fw_name = "lxt", },
-	{ .fw_name = "pclk0", },
-	{ .index = -1, },
-	{ .index = -1, },
-	{ .fw_name = "lirc", },
-	{ .index = -1, },
-	{ .fw_name = "hirc", },
-};
-
-static const struct clk_parent_data timer7_sel_clks[] = {
-	{ .fw_name = "hxt", },
-	{ .fw_name = "lxt", },
-	{ .fw_name = "pclk0", },
-	{ .index = -1, },
-	{ .index = -1, },
-	{ .fw_name = "lirc", },
-	{ .index = -1, },
-	{ .fw_name = "hirc", },
-};
-
-static const struct clk_parent_data timer8_sel_clks[] = {
-	{ .fw_name = "hxt", },
-	{ .fw_name = "lxt", },
-	{ .fw_name = "pclk1", },
-	{ .index = -1, },
-	{ .index = -1, },
-	{ .fw_name = "lirc", },
-	{ .index = -1, },
-	{ .fw_name = "hirc", },
-};
-
-static const struct clk_parent_data timer9_sel_clks[] = {
-	{ .fw_name = "hxt", },
-	{ .fw_name = "lxt", },
-	{ .fw_name = "pclk1", },
-	{ .index = -1, },
-	{ .index = -1, },
-	{ .fw_name = "lirc", },
-	{ .index = -1, },
-	{ .fw_name = "hirc", },
-};
-
-static const struct clk_parent_data timer10_sel_clks[] = {
-	{ .fw_name = "hxt", },
-	{ .fw_name = "lxt", },
-	{ .fw_name = "pclk2", },
-	{ .index = -1, },
-	{ .index = -1, },
-	{ .fw_name = "lirc", },
-	{ .index = -1, },
-	{ .fw_name = "hirc", },
-};
-
-static const struct clk_parent_data timer11_sel_clks[] = {
-	{ .fw_name = "hxt", },
-	{ .fw_name = "lxt", },
-	{ .fw_name = "pclk2", },
-	{ .index = -1, },
-	{ .index = -1, },
-	{ .fw_name = "lirc", },
-	{ .index = -1, },
-	{ .fw_name = "hirc", },
-};
-
-static const struct clk_parent_data uart_sel_clks[] = {
-	{ .fw_name = "hxt", },
-	{ .fw_name = "sysclk1_div2", },
-};
-
-static const struct clk_parent_data wdt0_sel_clks[] = {
-	{ .index = -1, },
-	{ .fw_name = "lxt", },
-	{ .fw_name = "pclk3_div4096", },
-	{ .fw_name = "lirc", },
-};
-
-static const struct clk_parent_data wdt1_sel_clks[] = {
-	{ .index = -1, },
-	{ .fw_name = "lxt", },
-	{ .fw_name = "pclk3_div4096", },
-	{ .fw_name = "lirc", },
-};
-
-static const struct clk_parent_data wdt2_sel_clks[] = {
-	{ .index = -1, },
-	{ .fw_name = "lxt", },
-	{ .fw_name = "pclk4_div4096", },
-	{ .fw_name = "lirc", },
-};
-
-static const struct clk_parent_data wwdt0_sel_clks[] = {
-	{ .index = -1, },
-	{ .index = -1, },
-	{ .fw_name = "pclk3_div4096", },
-	{ .fw_name = "lirc", },
-};
-
-static const struct clk_parent_data wwdt1_sel_clks[] = {
-	{ .index = -1, },
-	{ .index = -1, },
-	{ .fw_name = "pclk3_div4096", },
-	{ .fw_name = "lirc", },
-};
-
-static const struct clk_parent_data wwdt2_sel_clks[] = {
-	{ .index = -1, },
-	{ .index = -1, },
-	{ .fw_name = "pclk4_div4096", },
-	{ .fw_name = "lirc", },
-};
-
-static const struct clk_parent_data spi0_sel_clks[] = {
-	{ .fw_name = "pclk1", },
-	{ .fw_name = "apll", },
-};
-
-static const struct clk_parent_data spi1_sel_clks[] = {
-	{ .fw_name = "pclk2", },
-	{ .fw_name = "apll", },
-};
-
-static const struct clk_parent_data spi2_sel_clks[] = {
-	{ .fw_name = "pclk1", },
-	{ .fw_name = "apll", },
-};
-
-static const struct clk_parent_data spi3_sel_clks[] = {
-	{ .fw_name = "pclk2", },
-	{ .fw_name = "apll", },
-};
-
-static const struct clk_parent_data qspi0_sel_clks[] = {
-	{ .fw_name = "pclk0", },
-	{ .fw_name = "apll", },
-};
-
-static const struct clk_parent_data qspi1_sel_clks[] = {
-	{ .fw_name = "pclk0", },
-	{ .fw_name = "apll", },
-};
-
-static const struct clk_parent_data i2s0_sel_clks[] = {
-	{ .fw_name = "apll", },
-	{ .fw_name = "sysclk1_div2", },
-};
-
-static const struct clk_parent_data i2s1_sel_clks[] = {
-	{ .fw_name = "apll", },
-	{ .fw_name = "sysclk1_div2", },
-};
-
-static const struct clk_parent_data can_sel_clks[] = {
-	{ .fw_name = "apll", },
-	{ .fw_name = "vpll", },
-};
-
-static const struct clk_parent_data cko_sel_clks[] = {
-	{ .fw_name = "hxt", },
-	{ .fw_name = "lxt", },
-	{ .fw_name = "hirc", },
-	{ .fw_name = "lirc", },
-	{ .fw_name = "capll_div4", },
-	{ .fw_name = "syspll", },
-	{ .fw_name = "ddrpll", },
-	{ .fw_name = "epll_div2", },
-	{ .fw_name = "apll", },
-	{ .fw_name = "vpll", },
-};
-
-static const struct clk_parent_data smc_sel_clks[] = {
-	{ .fw_name = "hxt", },
-	{ .fw_name = "pclk4", },
-};
-
-static const struct clk_parent_data kpi_sel_clks[] = {
-	{ .fw_name = "hxt", },
-	{ .fw_name = "lxt", },
-};
+/* Mux parent selection, by index into the controller's clock table */
+static const int ca35clk_parent_idx[] = { HXT, CAPLL, DDRPLL };
+static const int sysclk0_parent_idx[] = { EPLL_DIV2, SYSPLL };
+static const int sysclk1_parent_idx[] = { HXT, SYSPLL };
+static const int axiclk_parent_idx[] = { AXICLK_DIV2, AXICLK_DIV4 };
+static const int ccap_parent_idx[] = { HXT, VPLL, APLL, SYSPLL };
+static const int sdh_parent_idx[] = { SYSPLL, APLL };
+static const int dcu_parent_idx[] = { EPLL_DIV2, SYSPLL };
+static const int gfx_parent_idx[] = { EPLL, SYSPLL };
+static const int dbg_parent_idx[] = { HIRC, SYSPLL };
+static const int timer0_parent_idx[] = { HXT, LXT, PCLK0, -1, -1, LIRC, -1, HIRC };
+static const int timer1_parent_idx[] = { HXT, LXT, PCLK0, -1, -1, LIRC, -1, HIRC };
+static const int timer2_parent_idx[] = { HXT, LXT, PCLK1, -1, -1, LIRC, -1, HIRC };
+static const int timer3_parent_idx[] = { HXT, LXT, PCLK1, -1, -1, LIRC, -1, HIRC };
+static const int timer4_parent_idx[] = { HXT, LXT, PCLK2, -1, -1, LIRC, -1, HIRC };
+static const int timer5_parent_idx[] = { HXT, LXT, PCLK2, -1, -1, LIRC, -1, HIRC };
+static const int timer6_parent_idx[] = { HXT, LXT, PCLK0, -1, -1, LIRC, -1, HIRC };
+static const int timer7_parent_idx[] = { HXT, LXT, PCLK0, -1, -1, LIRC, -1, HIRC };
+static const int timer8_parent_idx[] = { HXT, LXT, PCLK1, -1, -1, LIRC, -1, HIRC };
+static const int timer9_parent_idx[] = { HXT, LXT, PCLK1, -1, -1, LIRC, -1, HIRC };
+static const int timer10_parent_idx[] = { HXT, LXT, PCLK2, -1, -1, LIRC, -1, HIRC };
+static const int timer11_parent_idx[] = { HXT, LXT, PCLK2, -1, -1, LIRC, -1, HIRC };
+static const int uart_parent_idx[] = { HXT, SYSCLK1_DIV2 };
+static const int wdt0_parent_idx[] = { -1, LXT, PCLK3_DIV4096, LIRC };
+static const int wdt1_parent_idx[] = { -1, LXT, PCLK3_DIV4096, LIRC };
+static const int wdt2_parent_idx[] = { -1, LXT, PCLK4_DIV4096, LIRC };
+static const int wwdt0_parent_idx[] = { -1, -1, PCLK3_DIV4096, LIRC };
+static const int wwdt1_parent_idx[] = { -1, -1, PCLK3_DIV4096, LIRC };
+static const int wwdt2_parent_idx[] = { -1, -1, PCLK4_DIV4096, LIRC };
+static const int spi0_parent_idx[] = { PCLK1, APLL };
+static const int spi1_parent_idx[] = { PCLK2, APLL };
+static const int spi2_parent_idx[] = { PCLK1, APLL };
+static const int spi3_parent_idx[] = { PCLK2, APLL };
+static const int qspi_parent_idx[] = { PCLK0, APLL };
+static const int i2s_parent_idx[] = { APLL, SYSCLK1_DIV2 };
+static const int can_parent_idx[] = { APLL, VPLL };
+static const int cko_parent_idx[] = { HXT, LXT, HIRC, LIRC,
+				      AXICLK_DIV4, SYSPLL, DDRPLL,
+				      EPLL_DIV2, APLL, VPLL };
+static const int smc_parent_idx[] = { HXT, PCLK4 };
+static const int kpi_parent_idx[] = { HXT, LXT };
 
 static const struct clk_div_table ip_div_table[] = {
 	{0, 2}, {1, 4}, {2, 6}, {3, 8}, {4, 10},
@@ -375,24 +124,20 @@ static struct clk_hw *ma35d1_clk_fixed(const char *name, int rate)
 	return clk_hw_register_fixed_rate(NULL, name, NULL, 0, rate);
 }
 
-static struct clk_hw *ma35d1_clk_mux_parent(struct device *dev, const char *name,
-					    void __iomem *reg, u8 shift, u8 width,
-					    const struct clk_parent_data *pdata,
-					    int num_pdata)
-{
-	return clk_hw_register_mux_parent_data(dev, name, pdata, num_pdata,
-					       CLK_SET_RATE_NO_REPARENT, reg, shift,
-					       width, 0, &ma35d1_lock);
-}
-
 static struct clk_hw *ma35d1_clk_mux(struct device *dev, const char *name,
 				     void __iomem *reg, u8 shift, u8 width,
-				     const struct clk_parent_data *pdata,
-				     int num_pdata)
+				     struct clk_hw **hws,
+				     const int *parent_idx, int num_parents)
 {
-	return clk_hw_register_mux_parent_data(dev, name, pdata, num_pdata,
-					       CLK_SET_RATE_NO_REPARENT, reg, shift,
-					       width, 0, &ma35d1_lock);
+	const struct clk_hw *parent_hws[MA35D1_MUX_MAX_PARENTS] = {};
+	int i;
+
+	for (i = 0; i < num_parents; i++)
+		parent_hws[i] = (parent_idx[i] >= 0) ? hws[parent_idx[i]] : NULL;
+
+	return clk_hw_register_mux_hws(dev, name, parent_hws, num_parents,
+				       CLK_SET_RATE_NO_REPARENT, reg, shift,
+				       width, 0, &ma35d1_lock);
 }
 
 static struct clk_hw *ma35d1_clk_divider(struct device *dev, const char *name,
@@ -515,22 +260,17 @@ static int ma35d1_clocks_probe(struct platform_device *pdev)
 	hws[EPLL_DIV4] = ma35d1_clk_fixed_factor(dev, "epll_div4", "epll", 1, 4);
 	hws[EPLL_DIV8] = ma35d1_clk_fixed_factor(dev, "epll_div8", "epll", 1, 8);
 
-	hws[CA35CLK_MUX] = ma35d1_clk_mux_parent(dev, "ca35clk_mux",
-						 clk_base + REG_CLK_CLKSEL0, 0, 2,
-						 ca35clk_sel_clks,
-						 ARRAY_SIZE(ca35clk_sel_clks));
+	hws[CA35CLK_MUX] = ma35d1_clk_mux(dev, "ca35clk_mux", clk_base + REG_CLK_CLKSEL0, 0, 2, hws,
+					  ca35clk_parent_idx, ARRAY_SIZE(ca35clk_parent_idx));
 	hws[AXICLK_DIV2] = ma35d1_clk_fixed_factor(dev, "capll_div2", "ca35clk_mux", 1, 2);
 	hws[AXICLK_DIV4] = ma35d1_clk_fixed_factor(dev, "capll_div4", "ca35clk_mux", 1, 4);
 
-	hws[AXICLK_MUX] = ma35d1_clk_mux(dev, "axiclk_mux", clk_base + REG_CLK_CLKDIV0,
-					 26, 1, axiclk_sel_clks,
-					 ARRAY_SIZE(axiclk_sel_clks));
-	hws[SYSCLK0_MUX] = ma35d1_clk_mux(dev, "sysclk0_mux", clk_base + REG_CLK_CLKSEL0,
-					  2, 1, sysclk0_sel_clks,
-					  ARRAY_SIZE(sysclk0_sel_clks));
-	hws[SYSCLK1_MUX] = ma35d1_clk_mux(dev, "sysclk1_mux", clk_base + REG_CLK_CLKSEL0,
-					  4, 1, sysclk1_sel_clks,
-					  ARRAY_SIZE(sysclk1_sel_clks));
+	hws[AXICLK_MUX] = ma35d1_clk_mux(dev, "axiclk_mux", clk_base + REG_CLK_CLKDIV0, 26, 1, hws,
+					 axiclk_parent_idx, ARRAY_SIZE(axiclk_parent_idx));
+	hws[SYSCLK0_MUX] = ma35d1_clk_mux(dev, "sysclk0_mux", clk_base + REG_CLK_CLKSEL0, 2, 1, hws,
+					  sysclk0_parent_idx, ARRAY_SIZE(sysclk0_parent_idx));
+	hws[SYSCLK1_MUX] = ma35d1_clk_mux(dev, "sysclk1_mux", clk_base + REG_CLK_CLKSEL0, 4, 1, hws,
+					  sysclk1_parent_idx, ARRAY_SIZE(sysclk1_parent_idx));
 	hws[SYSCLK1_DIV2] = ma35d1_clk_fixed_factor(dev, "sysclk1_div2", "sysclk1_mux", 1, 2);
 
 	/* HCLK0~3 & PCLK0~4 */
@@ -556,41 +296,41 @@ static int ma35d1_clocks_probe(struct platform_device *pdev)
 	hws[DDR6_GATE] = ma35d1_clk_gate(dev, "ddr6_gate", "ddrpll",
 					 clk_base + REG_CLK_SYSCLK0, 5);
 
-	hws[CAN0_MUX] = ma35d1_clk_mux(dev, "can0_mux", clk_base + REG_CLK_CLKSEL4,
-				       16, 1, can_sel_clks, ARRAY_SIZE(can_sel_clks));
+	hws[CAN0_MUX] = ma35d1_clk_mux(dev, "can0_mux", clk_base + REG_CLK_CLKSEL4, 16, 1, hws,
+				       can_parent_idx, ARRAY_SIZE(can_parent_idx));
 	hws[CAN0_DIV] = ma35d1_clk_divider_table(dev, "can0_div", "can0_mux",
 						 clk_base + REG_CLK_CLKDIV0,
 						 0, 3, ip_div_table);
 	hws[CAN0_GATE] = ma35d1_clk_gate(dev, "can0_gate", "can0_div",
 					 clk_base + REG_CLK_SYSCLK0, 8);
-	hws[CAN1_MUX] = ma35d1_clk_mux(dev, "can1_mux", clk_base + REG_CLK_CLKSEL4,
-				       17, 1, can_sel_clks, ARRAY_SIZE(can_sel_clks));
+	hws[CAN1_MUX] = ma35d1_clk_mux(dev, "can1_mux", clk_base + REG_CLK_CLKSEL4, 17, 1, hws,
+				       can_parent_idx, ARRAY_SIZE(can_parent_idx));
 	hws[CAN1_DIV] = ma35d1_clk_divider_table(dev, "can1_div", "can1_mux",
 						 clk_base + REG_CLK_CLKDIV0,
 						 4, 3, ip_div_table);
 	hws[CAN1_GATE] = ma35d1_clk_gate(dev, "can1_gate", "can1_div",
 					 clk_base + REG_CLK_SYSCLK0, 9);
-	hws[CAN2_MUX] = ma35d1_clk_mux(dev, "can2_mux", clk_base + REG_CLK_CLKSEL4,
-				       18, 1, can_sel_clks, ARRAY_SIZE(can_sel_clks));
+	hws[CAN2_MUX] = ma35d1_clk_mux(dev, "can2_mux", clk_base + REG_CLK_CLKSEL4, 18, 1, hws,
+				       can_parent_idx, ARRAY_SIZE(can_parent_idx));
 	hws[CAN2_DIV] = ma35d1_clk_divider_table(dev, "can2_div", "can2_mux",
 						 clk_base + REG_CLK_CLKDIV0,
 						 8, 3, ip_div_table);
 	hws[CAN2_GATE] = ma35d1_clk_gate(dev, "can2_gate", "can2_div",
 					 clk_base + REG_CLK_SYSCLK0, 10);
-	hws[CAN3_MUX] = ma35d1_clk_mux(dev, "can3_mux", clk_base + REG_CLK_CLKSEL4,
-				       19, 1, can_sel_clks, ARRAY_SIZE(can_sel_clks));
+	hws[CAN3_MUX] = ma35d1_clk_mux(dev, "can3_mux", clk_base + REG_CLK_CLKSEL4, 19, 1, hws,
+				       can_parent_idx, ARRAY_SIZE(can_parent_idx));
 	hws[CAN3_DIV] = ma35d1_clk_divider_table(dev, "can3_div", "can3_mux",
 						 clk_base + REG_CLK_CLKDIV0,
 						 12, 3, ip_div_table);
 	hws[CAN3_GATE] = ma35d1_clk_gate(dev, "can3_gate", "can3_div",
 					 clk_base + REG_CLK_SYSCLK0, 11);
 
-	hws[SDH0_MUX] = ma35d1_clk_mux(dev, "sdh0_mux", clk_base + REG_CLK_CLKSEL0,
-				       16, 2, sdh_sel_clks, ARRAY_SIZE(sdh_sel_clks));
+	hws[SDH0_MUX] = ma35d1_clk_mux(dev, "sdh0_mux", clk_base + REG_CLK_CLKSEL0, 16, 2, hws,
+				       sdh_parent_idx, ARRAY_SIZE(sdh_parent_idx));
 	hws[SDH0_GATE] = ma35d1_clk_gate(dev, "sdh0_gate", "sdh0_mux",
 					 clk_base + REG_CLK_SYSCLK0, 16);
-	hws[SDH1_MUX] = ma35d1_clk_mux(dev, "sdh1_mux", clk_base + REG_CLK_CLKSEL0,
-				       18, 2, sdh_sel_clks, ARRAY_SIZE(sdh_sel_clks));
+	hws[SDH1_MUX] = ma35d1_clk_mux(dev, "sdh1_mux", clk_base + REG_CLK_CLKSEL0, 18, 2, hws,
+				       sdh_parent_idx, ARRAY_SIZE(sdh_parent_idx));
 	hws[SDH1_GATE] = ma35d1_clk_gate(dev, "sdh1_gate", "sdh1_mux",
 					 clk_base + REG_CLK_SYSCLK0, 17);
 
@@ -606,14 +346,14 @@ static int ma35d1_clocks_probe(struct platform_device *pdev)
 	hws[HUSBH1_GATE] = ma35d1_clk_gate(dev, "husbh1_gate", "usbphy0",
 					   clk_base + REG_CLK_SYSCLK0, 22);
 
-	hws[GFX_MUX] = ma35d1_clk_mux(dev, "gfx_mux", clk_base + REG_CLK_CLKSEL0,
-				      26, 1, gfx_sel_clks, ARRAY_SIZE(gfx_sel_clks));
+	hws[GFX_MUX] = ma35d1_clk_mux(dev, "gfx_mux", clk_base + REG_CLK_CLKSEL0, 26, 1, hws,
+				      gfx_parent_idx, ARRAY_SIZE(gfx_parent_idx));
 	hws[GFX_GATE] = ma35d1_clk_gate(dev, "gfx_gate", "gfx_mux",
 					clk_base + REG_CLK_SYSCLK0, 24);
 	hws[VC8K_GATE] = ma35d1_clk_gate(dev, "vc8k_gate", "sysclk0_mux",
 					 clk_base + REG_CLK_SYSCLK0, 25);
-	hws[DCU_MUX] = ma35d1_clk_mux(dev, "dcu_mux", clk_base + REG_CLK_CLKSEL0,
-				      24, 1, dcu_sel_clks, ARRAY_SIZE(dcu_sel_clks));
+	hws[DCU_MUX] = ma35d1_clk_mux(dev, "dcu_mux", clk_base + REG_CLK_CLKSEL0, 24, 1, hws,
+				      dcu_parent_idx, ARRAY_SIZE(dcu_parent_idx));
 	hws[DCU_GATE] = ma35d1_clk_gate(dev, "dcu_gate", "dcu_mux",
 					clk_base + REG_CLK_SYSCLK0, 26);
 	hws[DCUP_DIV] = ma35d1_clk_divider_table(dev, "dcup_div", "vpll",
@@ -625,14 +365,14 @@ static int ma35d1_clocks_probe(struct platform_device *pdev)
 	hws[EMAC1_GATE] = ma35d1_clk_gate(dev, "emac1_gate", "epll_div2",
 					  clk_base + REG_CLK_SYSCLK0, 28);
 
-	hws[CCAP0_MUX] = ma35d1_clk_mux(dev, "ccap0_mux", clk_base + REG_CLK_CLKSEL0,
-					12, 1, ccap_sel_clks, ARRAY_SIZE(ccap_sel_clks));
+	hws[CCAP0_MUX] = ma35d1_clk_mux(dev, "ccap0_mux", clk_base + REG_CLK_CLKSEL0, 12, 1, hws,
+					ccap_parent_idx, ARRAY_SIZE(ccap_parent_idx));
 	hws[CCAP0_DIV] = ma35d1_clk_divider(dev, "ccap0_div", "ccap0_mux",
 					    clk_base + REG_CLK_CLKDIV1, 8, 4);
 	hws[CCAP0_GATE] = ma35d1_clk_gate(dev, "ccap0_gate", "ccap0_div",
 					  clk_base + REG_CLK_SYSCLK0, 29);
-	hws[CCAP1_MUX] = ma35d1_clk_mux(dev, "ccap1_mux", clk_base + REG_CLK_CLKSEL0,
-					14, 1, ccap_sel_clks, ARRAY_SIZE(ccap_sel_clks));
+	hws[CCAP1_MUX] = ma35d1_clk_mux(dev, "ccap1_mux", clk_base + REG_CLK_CLKSEL0, 14, 1, hws,
+					ccap_parent_idx, ARRAY_SIZE(ccap_parent_idx));
 	hws[CCAP1_DIV] = ma35d1_clk_divider(dev, "ccap1_div", "ccap1_mux",
 					    clk_base + REG_CLK_CLKDIV1,
 					    12, 4);
@@ -670,13 +410,13 @@ static int ma35d1_clocks_probe(struct platform_device *pdev)
 	hws[TRA_GATE] = ma35d1_clk_gate(dev, "tra_gate", "hclk0",
 					clk_base + REG_CLK_SYSCLK1, 11);
 
-	hws[DBG_MUX] = ma35d1_clk_mux(dev, "dbg_mux", clk_base + REG_CLK_CLKSEL0,
-				      27, 1, dbg_sel_clks, ARRAY_SIZE(dbg_sel_clks));
+	hws[DBG_MUX] = ma35d1_clk_mux(dev, "dbg_mux", clk_base + REG_CLK_CLKSEL0, 27, 1, hws,
+				      dbg_parent_idx, ARRAY_SIZE(dbg_parent_idx));
 	hws[DBG_GATE] = ma35d1_clk_gate(dev, "dbg_gate", "hclk0",
 					clk_base + REG_CLK_SYSCLK1, 12);
 
-	hws[CKO_MUX] = ma35d1_clk_mux(dev, "cko_mux", clk_base + REG_CLK_CLKSEL4,
-				      24, 4, cko_sel_clks, ARRAY_SIZE(cko_sel_clks));
+	hws[CKO_MUX] = ma35d1_clk_mux(dev, "cko_mux", clk_base + REG_CLK_CLKSEL4, 24, 4, hws,
+				      cko_parent_idx, ARRAY_SIZE(cko_parent_idx));
 	hws[CKO_DIV] = ma35d1_clk_divider_pow2(dev, "cko_div", "cko_mux",
 					       clk_base + REG_CLK_CLKOCTL, 0, 4);
 	hws[CKO_GATE] = ma35d1_clk_gate(dev, "cko_gate", "cko_div",
@@ -714,181 +454,169 @@ static int ma35d1_clocks_probe(struct platform_device *pdev)
 	hws[GPN_GATE] = ma35d1_clk_gate(dev, "gpn_gate", "hclk0",
 					clk_base + REG_CLK_SYSCLK1, 29);
 
-	hws[TMR0_MUX] = ma35d1_clk_mux(dev, "tmr0_mux", clk_base + REG_CLK_CLKSEL1,
-				       0, 3, timer0_sel_clks,
-				       ARRAY_SIZE(timer0_sel_clks));
+	hws[TMR0_MUX] = ma35d1_clk_mux(dev, "tmr0_mux", clk_base + REG_CLK_CLKSEL1, 0, 3, hws,
+				       timer0_parent_idx, ARRAY_SIZE(timer0_parent_idx));
 	hws[TMR0_GATE] = ma35d1_clk_gate(dev, "tmr0_gate", "tmr0_mux",
 					 clk_base + REG_CLK_APBCLK0, 0);
-	hws[TMR1_MUX] = ma35d1_clk_mux(dev, "tmr1_mux", clk_base + REG_CLK_CLKSEL1,
-				       4, 3, timer1_sel_clks,
-				       ARRAY_SIZE(timer1_sel_clks));
+	hws[TMR1_MUX] = ma35d1_clk_mux(dev, "tmr1_mux", clk_base + REG_CLK_CLKSEL1, 4, 3, hws,
+				       timer1_parent_idx, ARRAY_SIZE(timer1_parent_idx));
 	hws[TMR1_GATE] = ma35d1_clk_gate(dev, "tmr1_gate", "tmr1_mux",
 					 clk_base + REG_CLK_APBCLK0, 1);
-	hws[TMR2_MUX] = ma35d1_clk_mux(dev, "tmr2_mux", clk_base + REG_CLK_CLKSEL1,
-				       8, 3, timer2_sel_clks,
-				       ARRAY_SIZE(timer2_sel_clks));
+	hws[TMR2_MUX] = ma35d1_clk_mux(dev, "tmr2_mux", clk_base + REG_CLK_CLKSEL1, 8, 3, hws,
+				       timer2_parent_idx, ARRAY_SIZE(timer2_parent_idx));
 	hws[TMR2_GATE] = ma35d1_clk_gate(dev, "tmr2_gate", "tmr2_mux",
 					 clk_base + REG_CLK_APBCLK0, 2);
-	hws[TMR3_MUX] = ma35d1_clk_mux(dev, "tmr3_mux", clk_base + REG_CLK_CLKSEL1,
-				       12, 3, timer3_sel_clks,
-				       ARRAY_SIZE(timer3_sel_clks));
+	hws[TMR3_MUX] = ma35d1_clk_mux(dev, "tmr3_mux", clk_base + REG_CLK_CLKSEL1, 12, 3, hws,
+				       timer3_parent_idx, ARRAY_SIZE(timer3_parent_idx));
 	hws[TMR3_GATE] = ma35d1_clk_gate(dev, "tmr3_gate", "tmr3_mux",
 					 clk_base + REG_CLK_APBCLK0, 3);
-	hws[TMR4_MUX] = ma35d1_clk_mux(dev, "tmr4_mux", clk_base + REG_CLK_CLKSEL1,
-				       16, 3, timer4_sel_clks,
-				       ARRAY_SIZE(timer4_sel_clks));
+	hws[TMR4_MUX] = ma35d1_clk_mux(dev, "tmr4_mux", clk_base + REG_CLK_CLKSEL1, 16, 3, hws,
+				       timer4_parent_idx, ARRAY_SIZE(timer4_parent_idx));
 	hws[TMR4_GATE] = ma35d1_clk_gate(dev, "tmr4_gate", "tmr4_mux",
 					 clk_base + REG_CLK_APBCLK0, 4);
-	hws[TMR5_MUX] = ma35d1_clk_mux(dev, "tmr5_mux", clk_base + REG_CLK_CLKSEL1,
-				       20, 3, timer5_sel_clks,
-				       ARRAY_SIZE(timer5_sel_clks));
+	hws[TMR5_MUX] = ma35d1_clk_mux(dev, "tmr5_mux", clk_base + REG_CLK_CLKSEL1, 20, 3, hws,
+				       timer5_parent_idx, ARRAY_SIZE(timer5_parent_idx));
 	hws[TMR5_GATE] = ma35d1_clk_gate(dev, "tmr5_gate", "tmr5_mux",
 					 clk_base + REG_CLK_APBCLK0, 5);
-	hws[TMR6_MUX] = ma35d1_clk_mux(dev, "tmr6_mux", clk_base + REG_CLK_CLKSEL1,
-				       24, 3, timer6_sel_clks,
-				       ARRAY_SIZE(timer6_sel_clks));
+	hws[TMR6_MUX] = ma35d1_clk_mux(dev, "tmr6_mux", clk_base + REG_CLK_CLKSEL1, 24, 3, hws,
+				       timer6_parent_idx, ARRAY_SIZE(timer6_parent_idx));
 	hws[TMR6_GATE] = ma35d1_clk_gate(dev, "tmr6_gate", "tmr6_mux",
 					 clk_base + REG_CLK_APBCLK0, 6);
-	hws[TMR7_MUX] = ma35d1_clk_mux(dev, "tmr7_mux", clk_base + REG_CLK_CLKSEL1,
-				       28, 3, timer7_sel_clks,
-				       ARRAY_SIZE(timer7_sel_clks));
+	hws[TMR7_MUX] = ma35d1_clk_mux(dev, "tmr7_mux", clk_base + REG_CLK_CLKSEL1, 28, 3, hws,
+				       timer7_parent_idx, ARRAY_SIZE(timer7_parent_idx));
 	hws[TMR7_GATE] = ma35d1_clk_gate(dev, "tmr7_gate", "tmr7_mux",
 					 clk_base + REG_CLK_APBCLK0, 7);
-	hws[TMR8_MUX] = ma35d1_clk_mux(dev, "tmr8_mux", clk_base + REG_CLK_CLKSEL2,
-				       0, 3, timer8_sel_clks,
-				       ARRAY_SIZE(timer8_sel_clks));
+	hws[TMR8_MUX] = ma35d1_clk_mux(dev, "tmr8_mux", clk_base + REG_CLK_CLKSEL2, 0, 3, hws,
+				       timer8_parent_idx, ARRAY_SIZE(timer8_parent_idx));
 	hws[TMR8_GATE] = ma35d1_clk_gate(dev, "tmr8_gate", "tmr8_mux",
 					 clk_base + REG_CLK_APBCLK0, 8);
-	hws[TMR9_MUX] = ma35d1_clk_mux(dev, "tmr9_mux", clk_base + REG_CLK_CLKSEL2,
-				       4, 3, timer9_sel_clks,
-				       ARRAY_SIZE(timer9_sel_clks));
+	hws[TMR9_MUX] = ma35d1_clk_mux(dev, "tmr9_mux", clk_base + REG_CLK_CLKSEL2, 4, 3, hws,
+				       timer9_parent_idx, ARRAY_SIZE(timer9_parent_idx));
 	hws[TMR9_GATE] = ma35d1_clk_gate(dev, "tmr9_gate", "tmr9_mux",
 					 clk_base + REG_CLK_APBCLK0, 9);
-	hws[TMR10_MUX] = ma35d1_clk_mux(dev, "tmr10_mux", clk_base + REG_CLK_CLKSEL2,
-					8, 3, timer10_sel_clks,
-					ARRAY_SIZE(timer10_sel_clks));
+	hws[TMR10_MUX] = ma35d1_clk_mux(dev, "tmr10_mux", clk_base + REG_CLK_CLKSEL2, 8, 3, hws,
+					timer10_parent_idx, ARRAY_SIZE(timer10_parent_idx));
 	hws[TMR10_GATE] = ma35d1_clk_gate(dev, "tmr10_gate", "tmr10_mux",
 					  clk_base + REG_CLK_APBCLK0, 10);
-	hws[TMR11_MUX] = ma35d1_clk_mux(dev, "tmr11_mux", clk_base + REG_CLK_CLKSEL2,
-					12, 3, timer11_sel_clks,
-					ARRAY_SIZE(timer11_sel_clks));
+	hws[TMR11_MUX] = ma35d1_clk_mux(dev, "tmr11_mux", clk_base + REG_CLK_CLKSEL2, 12, 3, hws,
+					timer11_parent_idx, ARRAY_SIZE(timer11_parent_idx));
 	hws[TMR11_GATE] = ma35d1_clk_gate(dev, "tmr11_gate", "tmr11_mux",
 					  clk_base + REG_CLK_APBCLK0, 11);
 
-	hws[UART0_MUX] = ma35d1_clk_mux(dev, "uart0_mux", clk_base + REG_CLK_CLKSEL2,
-					16, 2, uart_sel_clks, ARRAY_SIZE(uart_sel_clks));
+	hws[UART0_MUX] = ma35d1_clk_mux(dev, "uart0_mux", clk_base + REG_CLK_CLKSEL2, 16, 2, hws,
+					uart_parent_idx, ARRAY_SIZE(uart_parent_idx));
 	hws[UART0_DIV] = ma35d1_clk_divider(dev, "uart0_div", "uart0_mux",
 					    clk_base + REG_CLK_CLKDIV1,
 					    16, 4);
 	hws[UART0_GATE] = ma35d1_clk_gate(dev, "uart0_gate", "uart0_div",
 					  clk_base + REG_CLK_APBCLK0, 12);
-	hws[UART1_MUX] = ma35d1_clk_mux(dev, "uart1_mux", clk_base + REG_CLK_CLKSEL2,
-					18, 2, uart_sel_clks, ARRAY_SIZE(uart_sel_clks));
+	hws[UART1_MUX] = ma35d1_clk_mux(dev, "uart1_mux", clk_base + REG_CLK_CLKSEL2, 18, 2, hws,
+					uart_parent_idx, ARRAY_SIZE(uart_parent_idx));
 	hws[UART1_DIV] = ma35d1_clk_divider(dev, "uart1_div", "uart1_mux",
 					    clk_base + REG_CLK_CLKDIV1,
 					    20, 4);
 	hws[UART1_GATE] = ma35d1_clk_gate(dev, "uart1_gate", "uart1_div",
 					  clk_base + REG_CLK_APBCLK0, 13);
-	hws[UART2_MUX] = ma35d1_clk_mux(dev, "uart2_mux", clk_base + REG_CLK_CLKSEL2,
-					20, 2, uart_sel_clks, ARRAY_SIZE(uart_sel_clks));
+	hws[UART2_MUX] = ma35d1_clk_mux(dev, "uart2_mux", clk_base + REG_CLK_CLKSEL2, 20, 2, hws,
+					uart_parent_idx, ARRAY_SIZE(uart_parent_idx));
 	hws[UART2_DIV] = ma35d1_clk_divider(dev, "uart2_div", "uart2_mux",
 					    clk_base + REG_CLK_CLKDIV1,
 					    24, 4);
 	hws[UART2_GATE] = ma35d1_clk_gate(dev, "uart2_gate", "uart2_div",
 					  clk_base + REG_CLK_APBCLK0, 14);
-	hws[UART3_MUX] = ma35d1_clk_mux(dev, "uart3_mux", clk_base + REG_CLK_CLKSEL2,
-					22, 2, uart_sel_clks, ARRAY_SIZE(uart_sel_clks));
+	hws[UART3_MUX] = ma35d1_clk_mux(dev, "uart3_mux", clk_base + REG_CLK_CLKSEL2, 22, 2, hws,
+					uart_parent_idx, ARRAY_SIZE(uart_parent_idx));
 	hws[UART3_DIV] = ma35d1_clk_divider(dev, "uart3_div", "uart3_mux",
 					    clk_base + REG_CLK_CLKDIV1,
 					    28, 4);
 	hws[UART3_GATE] = ma35d1_clk_gate(dev, "uart3_gate", "uart3_div",
 					  clk_base + REG_CLK_APBCLK0, 15);
-	hws[UART4_MUX] = ma35d1_clk_mux(dev, "uart4_mux", clk_base + REG_CLK_CLKSEL2,
-					24, 2, uart_sel_clks, ARRAY_SIZE(uart_sel_clks));
+	hws[UART4_MUX] = ma35d1_clk_mux(dev, "uart4_mux", clk_base + REG_CLK_CLKSEL2, 24, 2, hws,
+					uart_parent_idx, ARRAY_SIZE(uart_parent_idx));
 	hws[UART4_DIV] = ma35d1_clk_divider(dev, "uart4_div", "uart4_mux",
 					    clk_base + REG_CLK_CLKDIV2,
 					    0, 4);
 	hws[UART4_GATE] = ma35d1_clk_gate(dev, "uart4_gate", "uart4_div",
 					  clk_base + REG_CLK_APBCLK0, 16);
-	hws[UART5_MUX] = ma35d1_clk_mux(dev, "uart5_mux", clk_base + REG_CLK_CLKSEL2,
-					26, 2, uart_sel_clks, ARRAY_SIZE(uart_sel_clks));
+	hws[UART5_MUX] = ma35d1_clk_mux(dev, "uart5_mux", clk_base + REG_CLK_CLKSEL2, 26, 2, hws,
+					uart_parent_idx, ARRAY_SIZE(uart_parent_idx));
 	hws[UART5_DIV] = ma35d1_clk_divider(dev, "uart5_div", "uart5_mux",
 					    clk_base + REG_CLK_CLKDIV2,
 					    4, 4);
 	hws[UART5_GATE] = ma35d1_clk_gate(dev, "uart5_gate", "uart5_div",
 					  clk_base + REG_CLK_APBCLK0, 17);
-	hws[UART6_MUX] = ma35d1_clk_mux(dev, "uart6_mux", clk_base + REG_CLK_CLKSEL2,
-					28, 2, uart_sel_clks, ARRAY_SIZE(uart_sel_clks));
+	hws[UART6_MUX] = ma35d1_clk_mux(dev, "uart6_mux", clk_base + REG_CLK_CLKSEL2, 28, 2, hws,
+					uart_parent_idx, ARRAY_SIZE(uart_parent_idx));
 	hws[UART6_DIV] = ma35d1_clk_divider(dev, "uart6_div", "uart6_mux",
 					    clk_base + REG_CLK_CLKDIV2,
 					    8, 4);
 	hws[UART6_GATE] = ma35d1_clk_gate(dev, "uart6_gate", "uart6_div",
 					  clk_base + REG_CLK_APBCLK0, 18);
-	hws[UART7_MUX] = ma35d1_clk_mux(dev, "uart7_mux", clk_base + REG_CLK_CLKSEL2,
-					30, 2, uart_sel_clks, ARRAY_SIZE(uart_sel_clks));
+	hws[UART7_MUX] = ma35d1_clk_mux(dev, "uart7_mux", clk_base + REG_CLK_CLKSEL2, 30, 2, hws,
+					uart_parent_idx, ARRAY_SIZE(uart_parent_idx));
 	hws[UART7_DIV] = ma35d1_clk_divider(dev, "uart7_div", "uart7_mux",
 					    clk_base + REG_CLK_CLKDIV2,
 					    12, 4);
 	hws[UART7_GATE] = ma35d1_clk_gate(dev, "uart7_gate", "uart7_div",
 					  clk_base + REG_CLK_APBCLK0, 19);
-	hws[UART8_MUX] = ma35d1_clk_mux(dev, "uart8_mux", clk_base + REG_CLK_CLKSEL3,
-					0, 2, uart_sel_clks, ARRAY_SIZE(uart_sel_clks));
+	hws[UART8_MUX] = ma35d1_clk_mux(dev, "uart8_mux", clk_base + REG_CLK_CLKSEL3, 0, 2, hws,
+					uart_parent_idx, ARRAY_SIZE(uart_parent_idx));
 	hws[UART8_DIV] = ma35d1_clk_divider(dev, "uart8_div", "uart8_mux",
 					    clk_base + REG_CLK_CLKDIV2,
 					    16, 4);
 	hws[UART8_GATE] = ma35d1_clk_gate(dev, "uart8_gate", "uart8_div",
 					  clk_base + REG_CLK_APBCLK0, 20);
-	hws[UART9_MUX] = ma35d1_clk_mux(dev, "uart9_mux", clk_base + REG_CLK_CLKSEL3,
-					2, 2, uart_sel_clks, ARRAY_SIZE(uart_sel_clks));
+	hws[UART9_MUX] = ma35d1_clk_mux(dev, "uart9_mux", clk_base + REG_CLK_CLKSEL3, 2, 2, hws,
+					uart_parent_idx, ARRAY_SIZE(uart_parent_idx));
 	hws[UART9_DIV] = ma35d1_clk_divider(dev, "uart9_div", "uart9_mux",
 					    clk_base + REG_CLK_CLKDIV2,
 					    20, 4);
 	hws[UART9_GATE] = ma35d1_clk_gate(dev, "uart9_gate", "uart9_div",
 					  clk_base + REG_CLK_APBCLK0, 21);
-	hws[UART10_MUX] = ma35d1_clk_mux(dev, "uart10_mux", clk_base + REG_CLK_CLKSEL3,
-					 4, 2, uart_sel_clks, ARRAY_SIZE(uart_sel_clks));
+	hws[UART10_MUX] = ma35d1_clk_mux(dev, "uart10_mux", clk_base + REG_CLK_CLKSEL3, 4, 2, hws,
+					 uart_parent_idx, ARRAY_SIZE(uart_parent_idx));
 	hws[UART10_DIV] = ma35d1_clk_divider(dev, "uart10_div", "uart10_mux",
 					     clk_base + REG_CLK_CLKDIV2,
 					     24, 4);
 	hws[UART10_GATE] = ma35d1_clk_gate(dev, "uart10_gate", "uart10_div",
 					   clk_base + REG_CLK_APBCLK0, 22);
-	hws[UART11_MUX] = ma35d1_clk_mux(dev, "uart11_mux", clk_base + REG_CLK_CLKSEL3,
-					 6, 2, uart_sel_clks, ARRAY_SIZE(uart_sel_clks));
+	hws[UART11_MUX] = ma35d1_clk_mux(dev, "uart11_mux", clk_base + REG_CLK_CLKSEL3, 6, 2, hws,
+					 uart_parent_idx, ARRAY_SIZE(uart_parent_idx));
 	hws[UART11_DIV] = ma35d1_clk_divider(dev, "uart11_div", "uart11_mux",
 					     clk_base + REG_CLK_CLKDIV2,
 					     28, 4);
 	hws[UART11_GATE] = ma35d1_clk_gate(dev, "uart11_gate", "uart11_div",
 					   clk_base + REG_CLK_APBCLK0, 23);
-	hws[UART12_MUX] = ma35d1_clk_mux(dev, "uart12_mux", clk_base + REG_CLK_CLKSEL3,
-					 8, 2, uart_sel_clks, ARRAY_SIZE(uart_sel_clks));
+	hws[UART12_MUX] = ma35d1_clk_mux(dev, "uart12_mux", clk_base + REG_CLK_CLKSEL3, 8, 2, hws,
+					 uart_parent_idx, ARRAY_SIZE(uart_parent_idx));
 	hws[UART12_DIV] = ma35d1_clk_divider(dev, "uart12_div", "uart12_mux",
 					     clk_base + REG_CLK_CLKDIV3,
 					     0, 4);
 	hws[UART12_GATE] = ma35d1_clk_gate(dev, "uart12_gate", "uart12_div",
 					   clk_base + REG_CLK_APBCLK0, 24);
-	hws[UART13_MUX] = ma35d1_clk_mux(dev, "uart13_mux", clk_base + REG_CLK_CLKSEL3,
-					 10, 2, uart_sel_clks, ARRAY_SIZE(uart_sel_clks));
+	hws[UART13_MUX] = ma35d1_clk_mux(dev, "uart13_mux", clk_base + REG_CLK_CLKSEL3, 10, 2, hws,
+					 uart_parent_idx, ARRAY_SIZE(uart_parent_idx));
 	hws[UART13_DIV] = ma35d1_clk_divider(dev, "uart13_div", "uart13_mux",
 					     clk_base + REG_CLK_CLKDIV3,
 					     4, 4);
 	hws[UART13_GATE] = ma35d1_clk_gate(dev, "uart13_gate", "uart13_div",
 					   clk_base + REG_CLK_APBCLK0, 25);
-	hws[UART14_MUX] = ma35d1_clk_mux(dev, "uart14_mux", clk_base + REG_CLK_CLKSEL3,
-					 12, 2, uart_sel_clks, ARRAY_SIZE(uart_sel_clks));
+	hws[UART14_MUX] = ma35d1_clk_mux(dev, "uart14_mux", clk_base + REG_CLK_CLKSEL3, 12, 2, hws,
+					 uart_parent_idx, ARRAY_SIZE(uart_parent_idx));
 	hws[UART14_DIV] = ma35d1_clk_divider(dev, "uart14_div", "uart14_mux",
 					     clk_base + REG_CLK_CLKDIV3,
 					     8, 4);
 	hws[UART14_GATE] = ma35d1_clk_gate(dev, "uart14_gate", "uart14_div",
 					   clk_base + REG_CLK_APBCLK0, 26);
-	hws[UART15_MUX] = ma35d1_clk_mux(dev, "uart15_mux", clk_base + REG_CLK_CLKSEL3,
-					 14, 2, uart_sel_clks, ARRAY_SIZE(uart_sel_clks));
+	hws[UART15_MUX] = ma35d1_clk_mux(dev, "uart15_mux", clk_base + REG_CLK_CLKSEL3, 14, 2, hws,
+					 uart_parent_idx, ARRAY_SIZE(uart_parent_idx));
 	hws[UART15_DIV] = ma35d1_clk_divider(dev, "uart15_div", "uart15_mux",
 					     clk_base + REG_CLK_CLKDIV3,
 					     12, 4);
 	hws[UART15_GATE] = ma35d1_clk_gate(dev, "uart15_gate", "uart15_div",
 					   clk_base + REG_CLK_APBCLK0, 27);
-	hws[UART16_MUX] = ma35d1_clk_mux(dev, "uart16_mux", clk_base + REG_CLK_CLKSEL3,
-					 16, 2, uart_sel_clks, ARRAY_SIZE(uart_sel_clks));
+	hws[UART16_MUX] = ma35d1_clk_mux(dev, "uart16_mux", clk_base + REG_CLK_CLKSEL3, 16, 2, hws,
+					 uart_parent_idx, ARRAY_SIZE(uart_parent_idx));
 	hws[UART16_DIV] = ma35d1_clk_divider(dev, "uart16_div", "uart16_mux",
 					     clk_base + REG_CLK_CLKDIV3,
 					     16, 4);
@@ -900,8 +628,8 @@ static int ma35d1_clocks_probe(struct platform_device *pdev)
 	hws[DDR_GATE] = ma35d1_clk_gate(dev, "ddr_gate", "ddrpll",
 					clk_base + REG_CLK_APBCLK0, 30);
 
-	hws[KPI_MUX] = ma35d1_clk_mux(dev, "kpi_mux", clk_base + REG_CLK_CLKSEL4,
-				      30, 1, kpi_sel_clks, ARRAY_SIZE(kpi_sel_clks));
+	hws[KPI_MUX] = ma35d1_clk_mux(dev, "kpi_mux", clk_base + REG_CLK_CLKSEL4, 30, 1, hws,
+				      kpi_parent_idx, ARRAY_SIZE(kpi_parent_idx));
 	hws[KPI_DIV] = ma35d1_clk_divider(dev, "kpi_div", "kpi_mux",
 					  clk_base + REG_CLK_CLKDIV4,
 					  24, 8);
@@ -921,49 +649,49 @@ static int ma35d1_clocks_probe(struct platform_device *pdev)
 	hws[I2C5_GATE] = ma35d1_clk_gate(dev, "i2c5_gate", "pclk2",
 					 clk_base + REG_CLK_APBCLK1, 5);
 
-	hws[QSPI0_MUX] = ma35d1_clk_mux(dev, "qspi0_mux", clk_base + REG_CLK_CLKSEL4,
-					8, 2, qspi0_sel_clks, ARRAY_SIZE(qspi0_sel_clks));
+	hws[QSPI0_MUX] = ma35d1_clk_mux(dev, "qspi0_mux", clk_base + REG_CLK_CLKSEL4, 8, 2, hws,
+					qspi_parent_idx, ARRAY_SIZE(qspi_parent_idx));
 	hws[QSPI0_GATE] = ma35d1_clk_gate(dev, "qspi0_gate", "qspi0_mux",
 					  clk_base + REG_CLK_APBCLK1, 6);
-	hws[QSPI1_MUX] = ma35d1_clk_mux(dev, "qspi1_mux", clk_base + REG_CLK_CLKSEL4,
-					10, 2, qspi1_sel_clks, ARRAY_SIZE(qspi1_sel_clks));
+	hws[QSPI1_MUX] = ma35d1_clk_mux(dev, "qspi1_mux", clk_base + REG_CLK_CLKSEL4, 10, 2, hws,
+					qspi_parent_idx, ARRAY_SIZE(qspi_parent_idx));
 	hws[QSPI1_GATE] = ma35d1_clk_gate(dev, "qspi1_gate", "qspi1_mux",
 					  clk_base + REG_CLK_APBCLK1, 7);
 
-	hws[SMC0_MUX] = ma35d1_clk_mux(dev, "smc0_mux", clk_base + REG_CLK_CLKSEL4,
-					28, 1, smc_sel_clks, ARRAY_SIZE(smc_sel_clks));
+	hws[SMC0_MUX] = ma35d1_clk_mux(dev, "smc0_mux", clk_base + REG_CLK_CLKSEL4, 28, 1, hws,
+				       smc_parent_idx, ARRAY_SIZE(smc_parent_idx));
 	hws[SMC0_DIV] = ma35d1_clk_divider(dev, "smc0_div", "smc0_mux",
 					   clk_base + REG_CLK_CLKDIV1,
 					   0, 4);
 	hws[SMC0_GATE] = ma35d1_clk_gate(dev, "smc0_gate", "smc0_div",
 					 clk_base + REG_CLK_APBCLK1, 12);
-	hws[SMC1_MUX] = ma35d1_clk_mux(dev, "smc1_mux", clk_base + REG_CLK_CLKSEL4,
-					 29, 1, smc_sel_clks, ARRAY_SIZE(smc_sel_clks));
+	hws[SMC1_MUX] = ma35d1_clk_mux(dev, "smc1_mux", clk_base + REG_CLK_CLKSEL4, 29, 1, hws,
+				       smc_parent_idx, ARRAY_SIZE(smc_parent_idx));
 	hws[SMC1_DIV] = ma35d1_clk_divider(dev, "smc1_div", "smc1_mux",
 					   clk_base + REG_CLK_CLKDIV1,
 					   4, 4);
 	hws[SMC1_GATE] = ma35d1_clk_gate(dev, "smc1_gate", "smc1_div",
 					 clk_base + REG_CLK_APBCLK1, 13);
 
-	hws[WDT0_MUX] = ma35d1_clk_mux(dev, "wdt0_mux", clk_base + REG_CLK_CLKSEL3,
-				       20, 2, wdt0_sel_clks, ARRAY_SIZE(wdt0_sel_clks));
+	hws[WDT0_MUX] = ma35d1_clk_mux(dev, "wdt0_mux", clk_base + REG_CLK_CLKSEL3, 20, 2, hws,
+				       wdt0_parent_idx, ARRAY_SIZE(wdt0_parent_idx));
 	hws[WDT0_GATE] = ma35d1_clk_gate(dev, "wdt0_gate", "wdt0_mux",
 					 clk_base + REG_CLK_APBCLK1, 16);
-	hws[WDT1_MUX] = ma35d1_clk_mux(dev, "wdt1_mux", clk_base + REG_CLK_CLKSEL3,
-				       24, 2, wdt1_sel_clks, ARRAY_SIZE(wdt1_sel_clks));
+	hws[WDT1_MUX] = ma35d1_clk_mux(dev, "wdt1_mux", clk_base + REG_CLK_CLKSEL3, 24, 2, hws,
+				       wdt1_parent_idx, ARRAY_SIZE(wdt1_parent_idx));
 	hws[WDT1_GATE] = ma35d1_clk_gate(dev, "wdt1_gate", "wdt1_mux",
 					 clk_base + REG_CLK_APBCLK1, 17);
-	hws[WDT2_MUX] = ma35d1_clk_mux(dev, "wdt2_mux", clk_base + REG_CLK_CLKSEL3,
-				       28, 2, wdt2_sel_clks, ARRAY_SIZE(wdt2_sel_clks));
+	hws[WDT2_MUX] = ma35d1_clk_mux(dev, "wdt2_mux", clk_base + REG_CLK_CLKSEL3, 28, 2, hws,
+				       wdt2_parent_idx, ARRAY_SIZE(wdt2_parent_idx));
 	hws[WDT2_GATE] = ma35d1_clk_gate(dev, "wdt2_gate", "wdt2_mux",
 				       clk_base + REG_CLK_APBCLK1, 18);
 
-	hws[WWDT0_MUX] = ma35d1_clk_mux(dev, "wwdt0_mux", clk_base + REG_CLK_CLKSEL3,
-					22, 2, wwdt0_sel_clks, ARRAY_SIZE(wwdt0_sel_clks));
-	hws[WWDT1_MUX] = ma35d1_clk_mux(dev, "wwdt1_mux", clk_base + REG_CLK_CLKSEL3,
-					26, 2, wwdt1_sel_clks, ARRAY_SIZE(wwdt1_sel_clks));
-	hws[WWDT2_MUX] = ma35d1_clk_mux(dev, "wwdt2_mux", clk_base + REG_CLK_CLKSEL3,
-					30, 2, wwdt2_sel_clks, ARRAY_SIZE(wwdt2_sel_clks));
+	hws[WWDT0_MUX] = ma35d1_clk_mux(dev, "wwdt0_mux", clk_base + REG_CLK_CLKSEL3, 22, 2, hws,
+					wwdt0_parent_idx, ARRAY_SIZE(wwdt0_parent_idx));
+	hws[WWDT1_MUX] = ma35d1_clk_mux(dev, "wwdt1_mux", clk_base + REG_CLK_CLKSEL3, 26, 2, hws,
+					wwdt1_parent_idx, ARRAY_SIZE(wwdt1_parent_idx));
+	hws[WWDT2_MUX] = ma35d1_clk_mux(dev, "wwdt2_mux", clk_base + REG_CLK_CLKSEL3, 30, 2, hws,
+					wwdt2_parent_idx, ARRAY_SIZE(wwdt2_parent_idx));
 
 	hws[EPWM0_GATE] = ma35d1_clk_gate(dev, "epwm0_gate", "pclk1",
 					  clk_base + REG_CLK_APBCLK1, 24);
@@ -972,12 +700,12 @@ static int ma35d1_clocks_probe(struct platform_device *pdev)
 	hws[EPWM2_GATE] = ma35d1_clk_gate(dev, "epwm2_gate", "pclk1",
 					  clk_base + REG_CLK_APBCLK1, 26);
 
-	hws[I2S0_MUX] = ma35d1_clk_mux(dev, "i2s0_mux", clk_base + REG_CLK_CLKSEL4,
-				       12, 2, i2s0_sel_clks, ARRAY_SIZE(i2s0_sel_clks));
+	hws[I2S0_MUX] = ma35d1_clk_mux(dev, "i2s0_mux", clk_base + REG_CLK_CLKSEL4, 12, 2, hws,
+				       i2s_parent_idx, ARRAY_SIZE(i2s_parent_idx));
 	hws[I2S0_GATE] = ma35d1_clk_gate(dev, "i2s0_gate", "i2s0_mux",
 					 clk_base + REG_CLK_APBCLK2, 0);
-	hws[I2S1_MUX] = ma35d1_clk_mux(dev, "i2s1_mux", clk_base + REG_CLK_CLKSEL4,
-				       14, 2, i2s1_sel_clks, ARRAY_SIZE(i2s1_sel_clks));
+	hws[I2S1_MUX] = ma35d1_clk_mux(dev, "i2s1_mux", clk_base + REG_CLK_CLKSEL4, 14, 2, hws,
+				       i2s_parent_idx, ARRAY_SIZE(i2s_parent_idx));
 	hws[I2S1_GATE] = ma35d1_clk_gate(dev, "i2s1_gate", "i2s1_mux",
 					 clk_base + REG_CLK_APBCLK2, 1);
 
@@ -986,20 +714,20 @@ static int ma35d1_clocks_probe(struct platform_device *pdev)
 	hws[SSPCC_GATE] = ma35d1_clk_gate(dev, "sspcc_gate", "pclk3",
 					  clk_base + REG_CLK_APBCLK2, 3);
 
-	hws[SPI0_MUX] = ma35d1_clk_mux(dev, "spi0_mux", clk_base + REG_CLK_CLKSEL4,
-				       0, 2, spi0_sel_clks, ARRAY_SIZE(spi0_sel_clks));
+	hws[SPI0_MUX] = ma35d1_clk_mux(dev, "spi0_mux", clk_base + REG_CLK_CLKSEL4, 0, 2, hws,
+				       spi0_parent_idx, ARRAY_SIZE(spi0_parent_idx));
 	hws[SPI0_GATE] = ma35d1_clk_gate(dev, "spi0_gate", "spi0_mux",
 					 clk_base + REG_CLK_APBCLK2, 4);
-	hws[SPI1_MUX] = ma35d1_clk_mux(dev, "spi1_mux", clk_base + REG_CLK_CLKSEL4,
-				       2, 2, spi1_sel_clks, ARRAY_SIZE(spi1_sel_clks));
+	hws[SPI1_MUX] = ma35d1_clk_mux(dev, "spi1_mux", clk_base + REG_CLK_CLKSEL4, 2, 2, hws,
+				       spi1_parent_idx, ARRAY_SIZE(spi1_parent_idx));
 	hws[SPI1_GATE] = ma35d1_clk_gate(dev, "spi1_gate", "spi1_mux",
 					 clk_base + REG_CLK_APBCLK2, 5);
-	hws[SPI2_MUX] = ma35d1_clk_mux(dev, "spi2_mux", clk_base + REG_CLK_CLKSEL4,
-				       4, 2, spi2_sel_clks, ARRAY_SIZE(spi2_sel_clks));
+	hws[SPI2_MUX] = ma35d1_clk_mux(dev, "spi2_mux", clk_base + REG_CLK_CLKSEL4, 4, 2, hws,
+				       spi2_parent_idx, ARRAY_SIZE(spi2_parent_idx));
 	hws[SPI2_GATE] = ma35d1_clk_gate(dev, "spi2_gate", "spi2_mux",
 					 clk_base + REG_CLK_APBCLK2, 6);
-	hws[SPI3_MUX] = ma35d1_clk_mux(dev, "spi3_mux", clk_base + REG_CLK_CLKSEL4,
-				       6, 2, spi3_sel_clks, ARRAY_SIZE(spi3_sel_clks));
+	hws[SPI3_MUX] = ma35d1_clk_mux(dev, "spi3_mux", clk_base + REG_CLK_CLKSEL4, 6, 2, hws,
+				       spi3_parent_idx, ARRAY_SIZE(spi3_parent_idx));
 	hws[SPI3_GATE] = ma35d1_clk_gate(dev, "spi3_gate", "spi3_mux",
 					 clk_base + REG_CLK_APBCLK2, 7);
 

-- 
2.55.0


^ permalink raw reply related	[flat|nested] 9+ messages in thread

* [PATCH v7 2/7] clk: nuvoton: ma35d1: Avoid possible error pointer dereferencing
  2026-10-02 15:01 [PATCH v7 0/7] clk: nuvoton: ma35d1: Fix mux parenting and peripheral clock rates Miquel Raynal
  2026-10-02 15:01 ` [PATCH v7 1/7] clk: nuvoton: ma35d1: Use clk_hw pointers as mux parents Miquel Raynal
@ 2026-10-02 15:01 ` Miquel Raynal
  2026-10-02 15:01 ` [PATCH v7 3/7] clk: nuvoton: ma35d1: Retrieve HXT/LXT from DT when possible Miquel Raynal
                   ` (4 subsequent siblings)
  6 siblings, 0 replies; 9+ messages in thread
From: Miquel Raynal @ 2026-10-02 15:01 UTC (permalink / raw)
  To: Jacky Huang, Shan-Chun Hung, Michael Turquette, Stephen Boyd,
	Richard Cochran, Arnd Bergmann, Brian Masney, Jerome Brunet,
	Rob Herring, Krzysztof Kozlowski, Conor Dooley, Andrew Jeffery,
	Avi Fishman, Tomer Maimon, Tali Perry, Patrick Venture,
	Nancy Yuen, Benjamin Fair
  Cc: Thomas Petazzoni, Steam Lin, linux-arm-kernel, linux-clk,
	linux-kernel, Krzysztof Kozlowski, devicetree, openbmc,
	Miquel Raynal

MA35D1 registration helpers store their parent_hw argument straight into
the parent data, without checking it first. In case of registration
failure an error pointer will be stored in the table, which is then
forwarded to the clk core, which treats any non-NULL parent as valid
handles.

Bail out early when the parent is an error pointer, instead of building
the parent data.

This issue is mostly theoretical in practice, since reaching such an
error would involve a very early -ENOMEM.

Signed-off-by: Miquel Raynal <miquel.raynal@bootlin.com>
---
 drivers/clk/nuvoton/clk-ma35d1-divider.c |  3 +++
 drivers/clk/nuvoton/clk-ma35d1-pll.c     |  3 +++
 drivers/clk/nuvoton/clk-ma35d1.c         | 13 +++++++++++--
 3 files changed, 17 insertions(+), 2 deletions(-)

diff --git a/drivers/clk/nuvoton/clk-ma35d1-divider.c b/drivers/clk/nuvoton/clk-ma35d1-divider.c
index e992e7c30341..57a7b4ed3b5e 100644
--- a/drivers/clk/nuvoton/clk-ma35d1-divider.c
+++ b/drivers/clk/nuvoton/clk-ma35d1-divider.c
@@ -90,6 +90,9 @@ struct clk_hw *ma35d1_reg_adc_clkdiv(struct device *dev, const char *name,
 	int ret;
 	int i;
 
+	if (IS_ERR(parent_hw))
+		return parent_hw;
+
 	div = devm_kzalloc(dev, sizeof(*div), GFP_KERNEL);
 	if (!div)
 		return ERR_PTR(-ENOMEM);
diff --git a/drivers/clk/nuvoton/clk-ma35d1-pll.c b/drivers/clk/nuvoton/clk-ma35d1-pll.c
index c7c0dc91a012..92424e9c669d 100644
--- a/drivers/clk/nuvoton/clk-ma35d1-pll.c
+++ b/drivers/clk/nuvoton/clk-ma35d1-pll.c
@@ -336,6 +336,9 @@ struct clk_hw *ma35d1_reg_clk_pll(struct device *dev, u32 id, u8 u8mode, const c
 	struct clk_hw *hw;
 	int ret;
 
+	if (IS_ERR(parent_hw))
+		return parent_hw;
+
 	pll = devm_kzalloc(dev, sizeof(*pll), GFP_KERNEL);
 	if (!pll)
 		return ERR_PTR(-ENOMEM);
diff --git a/drivers/clk/nuvoton/clk-ma35d1.c b/drivers/clk/nuvoton/clk-ma35d1.c
index 1a857f28310f..ceebcbd8c18b 100644
--- a/drivers/clk/nuvoton/clk-ma35d1.c
+++ b/drivers/clk/nuvoton/clk-ma35d1.c
@@ -130,10 +130,19 @@ static struct clk_hw *ma35d1_clk_mux(struct device *dev, const char *name,
 				     const int *parent_idx, int num_parents)
 {
 	const struct clk_hw *parent_hws[MA35D1_MUX_MAX_PARENTS] = {};
+	struct clk_hw *parent;
 	int i;
 
-	for (i = 0; i < num_parents; i++)
-		parent_hws[i] = (parent_idx[i] >= 0) ? hws[parent_idx[i]] : NULL;
+	for (i = 0; i < num_parents; i++) {
+		if (parent_idx[i] < 0)
+			continue;
+
+		parent = hws[parent_idx[i]];
+		if (IS_ERR(parent))
+			return parent;
+
+		parent_hws[i] = parent;
+	}
 
 	return clk_hw_register_mux_hws(dev, name, parent_hws, num_parents,
 				       CLK_SET_RATE_NO_REPARENT, reg, shift,

-- 
2.55.0


^ permalink raw reply related	[flat|nested] 9+ messages in thread

* [PATCH v7 3/7] clk: nuvoton: ma35d1: Retrieve HXT/LXT from DT when possible
  2026-10-02 15:01 [PATCH v7 0/7] clk: nuvoton: ma35d1: Fix mux parenting and peripheral clock rates Miquel Raynal
  2026-10-02 15:01 ` [PATCH v7 1/7] clk: nuvoton: ma35d1: Use clk_hw pointers as mux parents Miquel Raynal
  2026-10-02 15:01 ` [PATCH v7 2/7] clk: nuvoton: ma35d1: Avoid possible error pointer dereferencing Miquel Raynal
@ 2026-10-02 15:01 ` Miquel Raynal
  2026-10-02 15:01 ` [PATCH v7 4/7] clk: nuvoton: ma35d1: Reparent the gates correctly Miquel Raynal
                   ` (3 subsequent siblings)
  6 siblings, 0 replies; 9+ messages in thread
From: Miquel Raynal @ 2026-10-02 15:01 UTC (permalink / raw)
  To: Jacky Huang, Shan-Chun Hung, Michael Turquette, Stephen Boyd,
	Richard Cochran, Arnd Bergmann, Brian Masney, Jerome Brunet,
	Rob Herring, Krzysztof Kozlowski, Conor Dooley, Andrew Jeffery,
	Avi Fishman, Tomer Maimon, Tali Perry, Patrick Venture,
	Nancy Yuen, Benjamin Fair
  Cc: Thomas Petazzoni, Steam Lin, linux-arm-kernel, linux-clk,
	linux-kernel, Krzysztof Kozlowski, devicetree, openbmc,
	Miquel Raynal, stable

HXT and LXT are crystal oscillator inputs of the clock controller. As
such, they are external clock sources which should not be registered by
this driver.

HXT is already described in the DT, but is not named. In order to point
to this parent from its direct child which is HXT_GATE, we must provide
a fw_name (when it is named, new DTs) and a .name (for when it's not
named, but the fixed clock node name is used).

LXT is missing in old DTs, so we must create that clock and register it
for backward compatibility reasons. It should however be described and
pointed at in updated DTs.

describe LXT at all, we assume that HXT must be present, and fallback to
creating a fixed clock for LXT if it is not described (for backward
compatibility purposes).

Fixes: 691521a367cf ("clk: nuvoton: Add clock driver for ma35d1 clock controller")
Cc: stable@vger.kernel.org
Signed-off-by: Miquel Raynal <miquel.raynal@bootlin.com>
---
 drivers/clk/nuvoton/clk-ma35d1.c | 37 ++++++++++++++++++++++++++++++-------
 1 file changed, 30 insertions(+), 7 deletions(-)

diff --git a/drivers/clk/nuvoton/clk-ma35d1.c b/drivers/clk/nuvoton/clk-ma35d1.c
index ceebcbd8c18b..ed61a990870e 100644
--- a/drivers/clk/nuvoton/clk-ma35d1.c
+++ b/drivers/clk/nuvoton/clk-ma35d1.c
@@ -65,6 +65,14 @@ static DEFINE_SPINLOCK(ma35d1_lock);
 
 #define MA35D1_MUX_MAX_PARENTS	10
 
+static const struct clk_parent_data hxtg_parent_data[] = {
+	{ .fw_name = "hxt", .name = "clk_hxt" },
+};
+
+static const struct clk_parent_data lxtg_parent_data[] = {
+	{ .fw_name = "lxt", .name = "lxt" },
+};
+
 /* Mux parent selection, by index into the controller's clock table */
 static const int ca35clk_parent_idx[] = { HXT, CAPLL, DDRPLL };
 static const int sysclk0_parent_idx[] = { EPLL_DIV2, SYSPLL };
@@ -191,6 +199,15 @@ static struct clk_hw *ma35d1_clk_gate(struct device *dev, const char *name, cons
 				    reg, shift, 0, &ma35d1_lock);
 }
 
+static struct clk_hw *ma35d1_clk_gate_parent_data(struct device *dev, const char *name,
+						  const struct clk_parent_data *parent_data,
+						  void __iomem *reg, u8 shift)
+{
+	return devm_clk_hw_register_gate_parent_data(dev, name, parent_data,
+						     CLK_SET_RATE_PARENT,
+						     reg, shift, 0, &ma35d1_lock);
+}
+
 static int ma35d1_get_pll_setting(struct device_node *clk_node, u32 *pllmode)
 {
 	const char *of_str;
@@ -219,7 +236,7 @@ static int ma35d1_clocks_probe(struct platform_device *pdev)
 	static struct clk_hw **hws;
 	static struct clk_hw_onecell_data *ma35d1_hw_data;
 	u32 pllmode[PLL_MAX_NUM];
-	int ret;
+	int ret, num_clks;
 
 	ma35d1_hw_data = devm_kzalloc(dev,
 				      struct_size(ma35d1_hw_data, hws, MA35D1_CLK_COUNT),
@@ -240,12 +257,18 @@ static int ma35d1_clocks_probe(struct platform_device *pdev)
 		return -EINVAL;
 	}
 
-	hws[HXT] = ma35d1_clk_fixed("hxt", 24000000);
-	hws[HXT_GATE] = ma35d1_clk_gate(dev, "hxt_gate", "hxt",
-					clk_base + REG_CLK_PWRCTL, 0);
-	hws[LXT] = ma35d1_clk_fixed("lxt", 32768);
-	hws[LXT_GATE] = ma35d1_clk_gate(dev, "lxt_gate", "lxt",
-					clk_base + REG_CLK_PWRCTL, 1);
+	num_clks = of_clk_get_parent_count(clk_node);
+	if (num_clks < 1 || num_clks > 2)
+		return -EINVAL;
+
+	/* Old DTs do not describe the low-speed crystal */
+	if (num_clks == 1)
+		hws[LXT] = ma35d1_clk_fixed("lxt", 32768);
+
+	hws[HXT_GATE] = ma35d1_clk_gate_parent_data(dev, "hxt_gate", hxtg_parent_data,
+						    clk_base + REG_CLK_PWRCTL, 0);
+	hws[LXT_GATE] = ma35d1_clk_gate_parent_data(dev, "lxt_gate", lxtg_parent_data,
+						    clk_base + REG_CLK_PWRCTL, 1);
 	hws[HIRC] = ma35d1_clk_fixed("hirc", 12000000);
 	hws[HIRC_GATE] = ma35d1_clk_gate(dev, "hirc_gate", "hirc",
 					 clk_base + REG_CLK_PWRCTL, 2);

-- 
2.55.0


^ permalink raw reply related	[flat|nested] 9+ messages in thread

* [PATCH v7 4/7] clk: nuvoton: ma35d1: Reparent the gates correctly
  2026-10-02 15:01 [PATCH v7 0/7] clk: nuvoton: ma35d1: Fix mux parenting and peripheral clock rates Miquel Raynal
                   ` (2 preceding siblings ...)
  2026-10-02 15:01 ` [PATCH v7 3/7] clk: nuvoton: ma35d1: Retrieve HXT/LXT from DT when possible Miquel Raynal
@ 2026-10-02 15:01 ` Miquel Raynal
  2026-10-02 15:01 ` [PATCH v7 5/7] clk: nuvoton: ma35d1: Reparent SYSPLL correctly Miquel Raynal
                   ` (2 subsequent siblings)
  6 siblings, 0 replies; 9+ messages in thread
From: Miquel Raynal @ 2026-10-02 15:01 UTC (permalink / raw)
  To: Jacky Huang, Shan-Chun Hung, Michael Turquette, Stephen Boyd,
	Richard Cochran, Arnd Bergmann, Brian Masney, Jerome Brunet,
	Rob Herring, Krzysztof Kozlowski, Conor Dooley, Andrew Jeffery,
	Avi Fishman, Tomer Maimon, Tali Perry, Patrick Venture,
	Nancy Yuen, Benjamin Fair
  Cc: Thomas Petazzoni, Steam Lin, linux-arm-kernel, linux-clk,
	linux-kernel, Krzysztof Kozlowski, devicetree, openbmc,
	Miquel Raynal, stable

The clock tree is still incorrect. There are four main clocks in this
system:
- HXT: external high-speed crystal oscillator
- LXT: external low-speed crystal oscillator
- HIRC: internal high-speed RC oscillator
- LIRC: internal low-speed RC oscillator
Each clock has a 'gate' control to disable it. While in the TRM the
'gate' appears aside, in the CCF topology, the gates should be
below. This is because if we gate one of those clocks, none of the
children clocks continue ticking.

Reparent hxt_gate under hxt, and all hxt children under hxt_gate.
Do the same for the three other clock sources listed above.

After this change, the frequencies are identical, but the clock tree
looks much closer to the reality.

Fixes: 691521a367cf ("clk: nuvoton: Add clock driver for ma35d1 clock controller")
Cc: stable@vger.kernel.org
Signed-off-by: Miquel Raynal <miquel.raynal@bootlin.com>
---
 drivers/clk/nuvoton/clk-ma35d1.c | 78 +++++++++++++++++++++++-----------------
 1 file changed, 45 insertions(+), 33 deletions(-)

diff --git a/drivers/clk/nuvoton/clk-ma35d1.c b/drivers/clk/nuvoton/clk-ma35d1.c
index ed61a990870e..2e6e1c65d01e 100644
--- a/drivers/clk/nuvoton/clk-ma35d1.c
+++ b/drivers/clk/nuvoton/clk-ma35d1.c
@@ -74,34 +74,46 @@ static const struct clk_parent_data lxtg_parent_data[] = {
 };
 
 /* Mux parent selection, by index into the controller's clock table */
-static const int ca35clk_parent_idx[] = { HXT, CAPLL, DDRPLL };
+static const int ca35clk_parent_idx[] = { HXT_GATE, CAPLL, DDRPLL };
 static const int sysclk0_parent_idx[] = { EPLL_DIV2, SYSPLL };
-static const int sysclk1_parent_idx[] = { HXT, SYSPLL };
+static const int sysclk1_parent_idx[] = { HXT_GATE, SYSPLL };
 static const int axiclk_parent_idx[] = { AXICLK_DIV2, AXICLK_DIV4 };
-static const int ccap_parent_idx[] = { HXT, VPLL, APLL, SYSPLL };
+static const int ccap_parent_idx[] = { HXT_GATE, VPLL, APLL, SYSPLL };
 static const int sdh_parent_idx[] = { SYSPLL, APLL };
 static const int dcu_parent_idx[] = { EPLL_DIV2, SYSPLL };
 static const int gfx_parent_idx[] = { EPLL, SYSPLL };
-static const int dbg_parent_idx[] = { HIRC, SYSPLL };
-static const int timer0_parent_idx[] = { HXT, LXT, PCLK0, -1, -1, LIRC, -1, HIRC };
-static const int timer1_parent_idx[] = { HXT, LXT, PCLK0, -1, -1, LIRC, -1, HIRC };
-static const int timer2_parent_idx[] = { HXT, LXT, PCLK1, -1, -1, LIRC, -1, HIRC };
-static const int timer3_parent_idx[] = { HXT, LXT, PCLK1, -1, -1, LIRC, -1, HIRC };
-static const int timer4_parent_idx[] = { HXT, LXT, PCLK2, -1, -1, LIRC, -1, HIRC };
-static const int timer5_parent_idx[] = { HXT, LXT, PCLK2, -1, -1, LIRC, -1, HIRC };
-static const int timer6_parent_idx[] = { HXT, LXT, PCLK0, -1, -1, LIRC, -1, HIRC };
-static const int timer7_parent_idx[] = { HXT, LXT, PCLK0, -1, -1, LIRC, -1, HIRC };
-static const int timer8_parent_idx[] = { HXT, LXT, PCLK1, -1, -1, LIRC, -1, HIRC };
-static const int timer9_parent_idx[] = { HXT, LXT, PCLK1, -1, -1, LIRC, -1, HIRC };
-static const int timer10_parent_idx[] = { HXT, LXT, PCLK2, -1, -1, LIRC, -1, HIRC };
-static const int timer11_parent_idx[] = { HXT, LXT, PCLK2, -1, -1, LIRC, -1, HIRC };
-static const int uart_parent_idx[] = { HXT, SYSCLK1_DIV2 };
-static const int wdt0_parent_idx[] = { -1, LXT, PCLK3_DIV4096, LIRC };
-static const int wdt1_parent_idx[] = { -1, LXT, PCLK3_DIV4096, LIRC };
-static const int wdt2_parent_idx[] = { -1, LXT, PCLK4_DIV4096, LIRC };
-static const int wwdt0_parent_idx[] = { -1, -1, PCLK3_DIV4096, LIRC };
-static const int wwdt1_parent_idx[] = { -1, -1, PCLK3_DIV4096, LIRC };
-static const int wwdt2_parent_idx[] = { -1, -1, PCLK4_DIV4096, LIRC };
+static const int dbg_parent_idx[] = { HIRC_GATE, SYSPLL };
+static const int timer0_parent_idx[] = { HXT_GATE, LXT_GATE, PCLK0, -1, -1,
+					 LIRC_GATE, -1, HIRC_GATE };
+static const int timer1_parent_idx[] = { HXT_GATE, LXT_GATE, PCLK0, -1, -1,
+					 LIRC_GATE, -1, HIRC_GATE };
+static const int timer2_parent_idx[] = { HXT_GATE, LXT_GATE, PCLK1, -1, -1,
+					 LIRC_GATE, -1, HIRC_GATE };
+static const int timer3_parent_idx[] = { HXT_GATE, LXT_GATE, PCLK1, -1, -1,
+					 LIRC_GATE, -1, HIRC_GATE };
+static const int timer4_parent_idx[] = { HXT_GATE, LXT_GATE, PCLK2, -1, -1,
+					 LIRC_GATE, -1, HIRC_GATE };
+static const int timer5_parent_idx[] = { HXT_GATE, LXT_GATE, PCLK2, -1, -1,
+					 LIRC_GATE, -1, HIRC_GATE };
+static const int timer6_parent_idx[] = { HXT_GATE, LXT_GATE, PCLK0, -1, -1,
+					 LIRC_GATE, -1, HIRC_GATE };
+static const int timer7_parent_idx[] = { HXT_GATE, LXT_GATE, PCLK0, -1, -1,
+					 LIRC_GATE, -1, HIRC_GATE };
+static const int timer8_parent_idx[] = { HXT_GATE, LXT_GATE, PCLK1, -1, -1,
+					 LIRC_GATE, -1, HIRC_GATE };
+static const int timer9_parent_idx[] = { HXT_GATE, LXT_GATE, PCLK1, -1, -1,
+					 LIRC_GATE, -1, HIRC_GATE };
+static const int timer10_parent_idx[] = { HXT_GATE, LXT_GATE, PCLK2, -1, -1,
+					  LIRC_GATE, -1, HIRC_GATE };
+static const int timer11_parent_idx[] = { HXT_GATE, LXT_GATE, PCLK2, -1, -1,
+					  LIRC_GATE, -1, HIRC_GATE };
+static const int uart_parent_idx[] = { HXT_GATE, SYSCLK1_DIV2 };
+static const int wdt0_parent_idx[] = { -1, LXT_GATE, PCLK3_DIV4096, LIRC_GATE };
+static const int wdt1_parent_idx[] = { -1, LXT_GATE, PCLK3_DIV4096, LIRC_GATE };
+static const int wdt2_parent_idx[] = { -1, LXT_GATE, PCLK4_DIV4096, LIRC_GATE };
+static const int wwdt0_parent_idx[] = { -1, -1, PCLK3_DIV4096, LIRC_GATE };
+static const int wwdt1_parent_idx[] = { -1, -1, PCLK3_DIV4096, LIRC_GATE };
+static const int wwdt2_parent_idx[] = { -1, -1, PCLK4_DIV4096, LIRC_GATE };
 static const int spi0_parent_idx[] = { PCLK1, APLL };
 static const int spi1_parent_idx[] = { PCLK2, APLL };
 static const int spi2_parent_idx[] = { PCLK1, APLL };
@@ -109,11 +121,11 @@ static const int spi3_parent_idx[] = { PCLK2, APLL };
 static const int qspi_parent_idx[] = { PCLK0, APLL };
 static const int i2s_parent_idx[] = { APLL, SYSCLK1_DIV2 };
 static const int can_parent_idx[] = { APLL, VPLL };
-static const int cko_parent_idx[] = { HXT, LXT, HIRC, LIRC,
+static const int cko_parent_idx[] = { HXT_GATE, LXT_GATE, HIRC_GATE, LIRC_GATE,
 				      AXICLK_DIV4, SYSPLL, DDRPLL,
 				      EPLL_DIV2, APLL, VPLL };
-static const int smc_parent_idx[] = { HXT, PCLK4 };
-static const int kpi_parent_idx[] = { HXT, LXT };
+static const int smc_parent_idx[] = { HXT_GATE, PCLK4 };
+static const int kpi_parent_idx[] = { HXT_GATE, LXT_GATE };
 
 static const struct clk_div_table ip_div_table[] = {
 	{0, 2}, {1, 4}, {2, 6}, {3, 8}, {4, 10},
@@ -277,16 +289,16 @@ static int ma35d1_clocks_probe(struct platform_device *pdev)
 					 clk_base + REG_CLK_PWRCTL, 3);
 
 	hws[CAPLL] = ma35d1_reg_clk_pll(dev, CAPLL, pllmode[0], "capll",
-					hws[HXT], clk_base + REG_CLK_PLL0CTL0);
+					hws[HXT_GATE], clk_base + REG_CLK_PLL0CTL0);
 	hws[SYSPLL] = ma35d1_clk_fixed("syspll", 180000000);
 	hws[DDRPLL] = ma35d1_reg_clk_pll(dev, DDRPLL, pllmode[1], "ddrpll",
-					hws[HXT], clk_base + REG_CLK_PLL2CTL0);
+					hws[HXT_GATE], clk_base + REG_CLK_PLL2CTL0);
 	hws[APLL] = ma35d1_reg_clk_pll(dev, APLL, pllmode[2], "apll",
-				       hws[HXT], clk_base + REG_CLK_PLL3CTL0);
+				       hws[HXT_GATE], clk_base + REG_CLK_PLL3CTL0);
 	hws[EPLL] = ma35d1_reg_clk_pll(dev, EPLL, pllmode[3], "epll",
-				       hws[HXT], clk_base + REG_CLK_PLL4CTL0);
+				       hws[HXT_GATE], clk_base + REG_CLK_PLL4CTL0);
 	hws[VPLL] = ma35d1_reg_clk_pll(dev, VPLL, pllmode[4], "vpll",
-				       hws[HXT], clk_base + REG_CLK_PLL5CTL0);
+				       hws[HXT_GATE], clk_base + REG_CLK_PLL5CTL0);
 
 	hws[EPLL_DIV2] = ma35d1_clk_fixed_factor(dev, "epll_div2", "epll", 1, 2);
 	hws[EPLL_DIV4] = ma35d1_clk_fixed_factor(dev, "epll_div4", "epll", 1, 4);
@@ -454,7 +466,7 @@ static int ma35d1_clocks_probe(struct platform_device *pdev)
 	hws[CKO_GATE] = ma35d1_clk_gate(dev, "cko_gate", "cko_div",
 					clk_base + REG_CLK_SYSCLK1, 13);
 
-	hws[GTMR_GATE] = ma35d1_clk_gate(dev, "gtmr_gate", "hirc",
+	hws[GTMR_GATE] = ma35d1_clk_gate(dev, "gtmr_gate", "hirc_gate",
 					 clk_base + REG_CLK_SYSCLK1, 14);
 
 	hws[GPA_GATE] = ma35d1_clk_gate(dev, "gpa_gate", "hclk0",
@@ -655,7 +667,7 @@ static int ma35d1_clocks_probe(struct platform_device *pdev)
 	hws[UART16_GATE] = ma35d1_clk_gate(dev, "uart16_gate", "uart16_div",
 					   clk_base + REG_CLK_APBCLK0, 28);
 
-	hws[RTC_GATE] = ma35d1_clk_gate(dev, "rtc_gate", "lxt",
+	hws[RTC_GATE] = ma35d1_clk_gate(dev, "rtc_gate", "lxt_gate",
 					clk_base + REG_CLK_APBCLK0, 29);
 	hws[DDR_GATE] = ma35d1_clk_gate(dev, "ddr_gate", "ddrpll",
 					clk_base + REG_CLK_APBCLK0, 30);

-- 
2.55.0


^ permalink raw reply related	[flat|nested] 9+ messages in thread

* [PATCH v7 5/7] clk: nuvoton: ma35d1: Reparent SYSPLL correctly
  2026-10-02 15:01 [PATCH v7 0/7] clk: nuvoton: ma35d1: Fix mux parenting and peripheral clock rates Miquel Raynal
                   ` (3 preceding siblings ...)
  2026-10-02 15:01 ` [PATCH v7 4/7] clk: nuvoton: ma35d1: Reparent the gates correctly Miquel Raynal
@ 2026-10-02 15:01 ` Miquel Raynal
  2026-10-03  1:33   ` sashiko-bot
  2026-10-02 15:01 ` [PATCH v7 6/7] arm64: dts: nuvoton: ma35d1: Drop HXT clock output name Miquel Raynal
  2026-10-02 15:01 ` [PATCH v7 7/7] arm64: dts: nuvoton: ma35d1: Add LXT crystal and clock-names Miquel Raynal
  6 siblings, 1 reply; 9+ messages in thread
From: Miquel Raynal @ 2026-10-02 15:01 UTC (permalink / raw)
  To: Jacky Huang, Shan-Chun Hung, Michael Turquette, Stephen Boyd,
	Richard Cochran, Arnd Bergmann, Brian Masney, Jerome Brunet,
	Rob Herring, Krzysztof Kozlowski, Conor Dooley, Andrew Jeffery,
	Avi Fishman, Tomer Maimon, Tali Perry, Patrick Venture,
	Nancy Yuen, Benjamin Fair
  Cc: Thomas Petazzoni, Steam Lin, linux-arm-kernel, linux-clk,
	linux-kernel, Krzysztof Kozlowski, devicetree, openbmc,
	Miquel Raynal, stable

The clock tree is still incorrect. SYSPLL is derived from HXT_GATE, very
much like CAPLL, DDRPLL, VPLL, APLL and EPLL. SYSPLL has a fixed
frequency, but if HXT gets gated, SYSPLL stops running.

Reparent SYSPLL under HXT_GATE to properly define the clock tree
topology. After this change, the frequencies are identical, but the
clock tree looks (again) much closer to the reality.

Since the TRM does not explicitly shows that HIRC and LIRC are
internally sourced from HXT and LXT, respectively, I haven't reparented
them (even though that was tempting). This can be done later anyway.

Side effect: since I am moving to a devm_* clk helper for SYSPLL, I can
reuse this helper to register the other fixed clocks, so they are also
become device managed.

Fixes: 691521a367cf ("clk: nuvoton: Add clock driver for ma35d1 clock controller")
Cc: stable@vger.kernel.org
Signed-off-by: Miquel Raynal <miquel.raynal@bootlin.com>
---
 drivers/clk/nuvoton/clk-ma35d1.c | 25 +++++++++++++++++--------
 1 file changed, 17 insertions(+), 8 deletions(-)

diff --git a/drivers/clk/nuvoton/clk-ma35d1.c b/drivers/clk/nuvoton/clk-ma35d1.c
index 2e6e1c65d01e..0baaa93f1380 100644
--- a/drivers/clk/nuvoton/clk-ma35d1.c
+++ b/drivers/clk/nuvoton/clk-ma35d1.c
@@ -73,6 +73,8 @@ static const struct clk_parent_data lxtg_parent_data[] = {
 	{ .fw_name = "lxt", .name = "lxt" },
 };
 
+static struct clk_parent_data syspll_parent_data[] = {};
+
 /* Mux parent selection, by index into the controller's clock table */
 static const int ca35clk_parent_idx[] = { HXT_GATE, CAPLL, DDRPLL };
 static const int sysclk0_parent_idx[] = { EPLL_DIV2, SYSPLL };
@@ -139,9 +141,15 @@ static const struct clk_div_table eadc_div_table[] = {
 	{13, 28}, {14, 30}, {15, 32}, {0, 0},
 };
 
-static struct clk_hw *ma35d1_clk_fixed(const char *name, int rate)
+static struct clk_hw *ma35d1_clk_fixed_parent_data(struct device *dev, const char *name, int rate,
+						   const struct clk_parent_data *parent_data)
 {
-	return clk_hw_register_fixed_rate(NULL, name, NULL, 0, rate);
+	return devm_clk_hw_register_fixed_rate_parent_data(dev, name, parent_data, 0, rate);
+}
+
+static struct clk_hw *ma35d1_clk_fixed(struct device *dev, const char *name, int rate)
+{
+	return ma35d1_clk_fixed_parent_data(dev, name, rate, NULL);
 }
 
 static struct clk_hw *ma35d1_clk_mux(struct device *dev, const char *name,
@@ -275,22 +283,23 @@ static int ma35d1_clocks_probe(struct platform_device *pdev)
 
 	/* Old DTs do not describe the low-speed crystal */
 	if (num_clks == 1)
-		hws[LXT] = ma35d1_clk_fixed("lxt", 32768);
+		hws[LXT] = ma35d1_clk_fixed(dev, "lxt", 32768);
 
 	hws[HXT_GATE] = ma35d1_clk_gate_parent_data(dev, "hxt_gate", hxtg_parent_data,
 						    clk_base + REG_CLK_PWRCTL, 0);
 	hws[LXT_GATE] = ma35d1_clk_gate_parent_data(dev, "lxt_gate", lxtg_parent_data,
 						    clk_base + REG_CLK_PWRCTL, 1);
-	hws[HIRC] = ma35d1_clk_fixed("hirc", 12000000);
+	hws[HIRC] = ma35d1_clk_fixed(dev, "hirc", 12000000);
 	hws[HIRC_GATE] = ma35d1_clk_gate(dev, "hirc_gate", "hirc",
 					 clk_base + REG_CLK_PWRCTL, 2);
-	hws[LIRC] = ma35d1_clk_fixed("lirc", 32000);
+	hws[LIRC] = ma35d1_clk_fixed(dev, "lirc", 32000);
 	hws[LIRC_GATE] = ma35d1_clk_gate(dev, "lirc_gate", "lirc",
 					 clk_base + REG_CLK_PWRCTL, 3);
 
 	hws[CAPLL] = ma35d1_reg_clk_pll(dev, CAPLL, pllmode[0], "capll",
 					hws[HXT_GATE], clk_base + REG_CLK_PLL0CTL0);
-	hws[SYSPLL] = ma35d1_clk_fixed("syspll", 180000000);
+	syspll_parent_data[0].hw = hws[HXT_GATE];
+	hws[SYSPLL] = ma35d1_clk_fixed_parent_data(dev, "syspll", 180000000, syspll_parent_data);
 	hws[DDRPLL] = ma35d1_reg_clk_pll(dev, DDRPLL, pllmode[1], "ddrpll",
 					hws[HXT_GATE], clk_base + REG_CLK_PLL2CTL0);
 	hws[APLL] = ma35d1_reg_clk_pll(dev, APLL, pllmode[2], "apll",
@@ -331,8 +340,8 @@ static int ma35d1_clocks_probe(struct platform_device *pdev)
 	hws[PCLK3_DIV4096] = ma35d1_clk_fixed_factor(dev, "pclk3_div4096", "pclk3", 1, 4096);
 	hws[PCLK4_DIV4096] = ma35d1_clk_fixed_factor(dev, "pclk4_div4096", "pclk4", 1, 4096);
 
-	hws[USBPHY0] = ma35d1_clk_fixed("usbphy0", 480000000);
-	hws[USBPHY1] = ma35d1_clk_fixed("usbphy1", 480000000);
+	hws[USBPHY0] = ma35d1_clk_fixed(dev, "usbphy0", 480000000);
+	hws[USBPHY1] = ma35d1_clk_fixed(dev, "usbphy1", 480000000);
 
 	/* DDR */
 	hws[DDR0_GATE] = ma35d1_clk_gate(dev, "ddr0_gate", "ddrpll",

-- 
2.55.0


^ permalink raw reply related	[flat|nested] 9+ messages in thread

* [PATCH v7 6/7] arm64: dts: nuvoton: ma35d1: Drop HXT clock output name
  2026-10-02 15:01 [PATCH v7 0/7] clk: nuvoton: ma35d1: Fix mux parenting and peripheral clock rates Miquel Raynal
                   ` (4 preceding siblings ...)
  2026-10-02 15:01 ` [PATCH v7 5/7] clk: nuvoton: ma35d1: Reparent SYSPLL correctly Miquel Raynal
@ 2026-10-02 15:01 ` Miquel Raynal
  2026-10-02 15:01 ` [PATCH v7 7/7] arm64: dts: nuvoton: ma35d1: Add LXT crystal and clock-names Miquel Raynal
  6 siblings, 0 replies; 9+ messages in thread
From: Miquel Raynal @ 2026-10-02 15:01 UTC (permalink / raw)
  To: Jacky Huang, Shan-Chun Hung, Michael Turquette, Stephen Boyd,
	Richard Cochran, Arnd Bergmann, Brian Masney, Jerome Brunet,
	Rob Herring, Krzysztof Kozlowski, Conor Dooley, Andrew Jeffery,
	Avi Fishman, Tomer Maimon, Tali Perry, Patrick Venture,
	Nancy Yuen, Benjamin Fair
  Cc: Thomas Petazzoni, Steam Lin, linux-arm-kernel, linux-clk,
	linux-kernel, Krzysztof Kozlowski, devicetree, openbmc,
	Miquel Raynal

The clock-output-names property is not useful since there is only one
output clock, and the naming of that clock would already be clock-hxt
after the node name if we were not providing that property (so very
similar). Just drop it.

I want to clean this name before introducing another very similar fixed
clock in the DT: LXT

Another solution could have been to rename it "hxt", which would have
been more aligned with the other clock names. Sashiko complained that
this could break DT compatibility with an -EEXIST error because of
the colliding names.

Signed-off-by: Miquel Raynal <miquel.raynal@bootlin.com>
---
 arch/arm64/boot/dts/nuvoton/ma35d1-iot-512m.dts | 1 -
 arch/arm64/boot/dts/nuvoton/ma35d1-som-256m.dts | 1 -
 2 files changed, 2 deletions(-)

diff --git a/arch/arm64/boot/dts/nuvoton/ma35d1-iot-512m.dts b/arch/arm64/boot/dts/nuvoton/ma35d1-iot-512m.dts
index 78534d613486..d7670afb0a63 100644
--- a/arch/arm64/boot/dts/nuvoton/ma35d1-iot-512m.dts
+++ b/arch/arm64/boot/dts/nuvoton/ma35d1-iot-512m.dts
@@ -35,7 +35,6 @@ clk_hxt: clock-hxt {
 		compatible = "fixed-clock";
 		#clock-cells = <0>;
 		clock-frequency = <24000000>;
-		clock-output-names = "clk_hxt";
 	};
 };
 
diff --git a/arch/arm64/boot/dts/nuvoton/ma35d1-som-256m.dts b/arch/arm64/boot/dts/nuvoton/ma35d1-som-256m.dts
index a029b660e8dc..8f3cb18d39b6 100644
--- a/arch/arm64/boot/dts/nuvoton/ma35d1-som-256m.dts
+++ b/arch/arm64/boot/dts/nuvoton/ma35d1-som-256m.dts
@@ -35,7 +35,6 @@ clk_hxt: clock-hxt {
 		compatible = "fixed-clock";
 		#clock-cells = <0>;
 		clock-frequency = <24000000>;
-		clock-output-names = "clk_hxt";
 	};
 };
 

-- 
2.55.0


^ permalink raw reply related	[flat|nested] 9+ messages in thread

* [PATCH v7 7/7] arm64: dts: nuvoton: ma35d1: Add LXT crystal and clock-names
  2026-10-02 15:01 [PATCH v7 0/7] clk: nuvoton: ma35d1: Fix mux parenting and peripheral clock rates Miquel Raynal
                   ` (5 preceding siblings ...)
  2026-10-02 15:01 ` [PATCH v7 6/7] arm64: dts: nuvoton: ma35d1: Drop HXT clock output name Miquel Raynal
@ 2026-10-02 15:01 ` Miquel Raynal
  6 siblings, 0 replies; 9+ messages in thread
From: Miquel Raynal @ 2026-10-02 15:01 UTC (permalink / raw)
  To: Jacky Huang, Shan-Chun Hung, Michael Turquette, Stephen Boyd,
	Richard Cochran, Arnd Bergmann, Brian Masney, Jerome Brunet,
	Rob Herring, Krzysztof Kozlowski, Conor Dooley, Andrew Jeffery,
	Avi Fishman, Tomer Maimon, Tali Perry, Patrick Venture,
	Nancy Yuen, Benjamin Fair
  Cc: Thomas Petazzoni, Steam Lin, linux-arm-kernel, linux-clk,
	linux-kernel, Krzysztof Kozlowski, devicetree, openbmc,
	Miquel Raynal, stable

The clock controller takes its two crystal oscillator inputs from the
board: HXT and LXT. The LXT crystal is not described at all: add the
fixed clock node for it and reference both inputs from the clock
controller node, with their respective clock-names.

Fixes: 691521a367cf ("clk: nuvoton: Add clock driver for ma35d1 clock controller")
Fixes: b69af0984732 ("arm64: dts: nuvoton: Add initial ma35d1 device tree")
Cc: stable@vger.kernel.org
Signed-off-by: Miquel Raynal <miquel.raynal@bootlin.com>
---
---
 arch/arm64/boot/dts/nuvoton/ma35d1-iot-512m.dts | 6 ++++++
 arch/arm64/boot/dts/nuvoton/ma35d1-som-256m.dts | 6 ++++++
 arch/arm64/boot/dts/nuvoton/ma35d1.dtsi         | 3 ++-
 3 files changed, 14 insertions(+), 1 deletion(-)

diff --git a/arch/arm64/boot/dts/nuvoton/ma35d1-iot-512m.dts b/arch/arm64/boot/dts/nuvoton/ma35d1-iot-512m.dts
index d7670afb0a63..7752e85734ac 100644
--- a/arch/arm64/boot/dts/nuvoton/ma35d1-iot-512m.dts
+++ b/arch/arm64/boot/dts/nuvoton/ma35d1-iot-512m.dts
@@ -36,6 +36,12 @@ clk_hxt: clock-hxt {
 		#clock-cells = <0>;
 		clock-frequency = <24000000>;
 	};
+
+	clk_lxt: clock-lxt {
+		compatible = "fixed-clock";
+		#clock-cells = <0>;
+		clock-frequency = <32768>;
+	};
 };
 
 &clk {
diff --git a/arch/arm64/boot/dts/nuvoton/ma35d1-som-256m.dts b/arch/arm64/boot/dts/nuvoton/ma35d1-som-256m.dts
index 8f3cb18d39b6..5c65f1fe5da9 100644
--- a/arch/arm64/boot/dts/nuvoton/ma35d1-som-256m.dts
+++ b/arch/arm64/boot/dts/nuvoton/ma35d1-som-256m.dts
@@ -36,6 +36,12 @@ clk_hxt: clock-hxt {
 		#clock-cells = <0>;
 		clock-frequency = <24000000>;
 	};
+
+	clk_lxt: clock-lxt {
+		compatible = "fixed-clock";
+		#clock-cells = <0>;
+		clock-frequency = <32768>;
+	};
 };
 
 &clk {
diff --git a/arch/arm64/boot/dts/nuvoton/ma35d1.dtsi b/arch/arm64/boot/dts/nuvoton/ma35d1.dtsi
index 7228ad4735b5..9a341c2b1397 100644
--- a/arch/arm64/boot/dts/nuvoton/ma35d1.dtsi
+++ b/arch/arm64/boot/dts/nuvoton/ma35d1.dtsi
@@ -92,7 +92,8 @@ clk: clock-controller@40460200 {
 			compatible = "nuvoton,ma35d1-clk";
 			reg = <0x00000000 0x40460200 0x0 0x100>;
 			#clock-cells = <1>;
-			clocks = <&clk_hxt>;
+			clocks = <&clk_hxt>, <&clk_lxt>;
+			clock-names = "hxt", "lxt";
 		};
 
 		pinctrl: pinctrl@40040000 {

-- 
2.55.0


^ permalink raw reply related	[flat|nested] 9+ messages in thread

* Re: [PATCH v7 5/7] clk: nuvoton: ma35d1: Reparent SYSPLL correctly
  2026-10-02 15:01 ` [PATCH v7 5/7] clk: nuvoton: ma35d1: Reparent SYSPLL correctly Miquel Raynal
@ 2026-10-03  1:33   ` sashiko-bot
  0 siblings, 0 replies; 9+ messages in thread
From: sashiko-bot @ 2026-10-03  1:33 UTC (permalink / raw)
  To: Miquel Raynal; +Cc: robh, conor+dt, devicetree, linux-clk

Thank you for your contribution! Sashiko AI review found 2 potential issue(s) to consider:
- [Critical] clk: buffer overflow via zero-length syspll_parent_data array
- [High] clk: unhandled ERR_PTR dereference in syspll_parent_data
--

commit 5e6e98e9249c8ddf8953662fc83c357de699a523
Author: Miquel Raynal <miquel.raynal@bootlin.com>

clk: nuvoton: ma35d1: Reparent SYSPLL correctly

The clock tree is still incorrect. SYSPLL is derived from HXT_GATE, very
much like CAPLL, DDRPLL, VPLL, APLL and EPLL. SYSPLL has a fixed
frequency, but if HXT gets gated, SYSPLL stops running.

> diff --git a/drivers/clk/nuvoton/clk-ma35d1.c b/drivers/clk/nuvoton/clk-ma35d1.c
> index 2e6e1c65d01e5..0baaa93f13805 100644
> --- a/drivers/clk/nuvoton/clk-ma35d1.c
> +++ b/drivers/clk/nuvoton/clk-ma35d1.c
> @@ -73,6 +73,8 @@ static const struct clk_parent_data lxtg_parent_data[] = {
>  	{ .fw_name = "lxt", .name = "lxt" },
>  };
>  
> +static struct clk_parent_data syspll_parent_data[] = {};
> +

[Severity: Critical]
Does this code allocate a zero-length array in the .bss section?

Later in ma35d1_clocks_probe(), there is an unconditional write to
syspll_parent_data[0].hw, which seems to write entirely out-of-bounds
and corrupt 8 bytes of adjacent static memory.

[ ... ]

> @@ -275,22 +283,23 @@ static int ma35d1_clocks_probe(struct platform_device *pdev)
>  
>  	/* Old DTs do not describe the low-speed crystal */
>  	if (num_clks == 1)
> -		hws[LXT] = ma35d1_clk_fixed("lxt", 32768);
> +		hws[LXT] = ma35d1_clk_fixed(dev, "lxt", 32768);
>  
>  	hws[HXT_GATE] = ma35d1_clk_gate_parent_data(dev, "hxt_gate", hxtg_parent_data,
>  						    clk_base + REG_CLK_PWRCTL, 0);

[ ... ]

>  	hws[CAPLL] = ma35d1_reg_clk_pll(dev, CAPLL, pllmode[0], "capll",
>  					hws[HXT_GATE], clk_base + REG_CLK_PLL0CTL0);
> -	hws[SYSPLL] = ma35d1_clk_fixed("syspll", 180000000);
> +	syspll_parent_data[0].hw = hws[HXT_GATE];
> +	hws[SYSPLL] = ma35d1_clk_fixed_parent_data(dev, "syspll", 180000000, syspll_parent_data);

[Severity: High]
If ma35d1_clk_gate_parent_data() fails when allocating hws[HXT_GATE],
it returns an ERR_PTR. Could this ERR_PTR be blindly assigned to
syspll_parent_data[0].hw and registered via ma35d1_clk_fixed_parent_data()?

Without validating the pointer with IS_ERR(), the common clock framework
might dereference this ERR_PTR in clk_core_fill_parent_index() causing
a kernel panic.

-- 
Sashiko AI review · https://sashiko.dev/#/patchset/20261002-perso-ma35d1-upstream-clk-v7-0-cbd991fa6270@bootlin.com?part=5

^ permalink raw reply	[flat|nested] 9+ messages in thread

end of thread, other threads:[~2026-10-03  1:33 UTC | newest]

Thread overview: 9+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2026-10-02 15:01 [PATCH v7 0/7] clk: nuvoton: ma35d1: Fix mux parenting and peripheral clock rates Miquel Raynal
2026-10-02 15:01 ` [PATCH v7 1/7] clk: nuvoton: ma35d1: Use clk_hw pointers as mux parents Miquel Raynal
2026-10-02 15:01 ` [PATCH v7 2/7] clk: nuvoton: ma35d1: Avoid possible error pointer dereferencing Miquel Raynal
2026-10-02 15:01 ` [PATCH v7 3/7] clk: nuvoton: ma35d1: Retrieve HXT/LXT from DT when possible Miquel Raynal
2026-10-02 15:01 ` [PATCH v7 4/7] clk: nuvoton: ma35d1: Reparent the gates correctly Miquel Raynal
2026-10-02 15:01 ` [PATCH v7 5/7] clk: nuvoton: ma35d1: Reparent SYSPLL correctly Miquel Raynal
2026-10-03  1:33   ` sashiko-bot
2026-10-02 15:01 ` [PATCH v7 6/7] arm64: dts: nuvoton: ma35d1: Drop HXT clock output name Miquel Raynal
2026-10-02 15:01 ` [PATCH v7 7/7] arm64: dts: nuvoton: ma35d1: Add LXT crystal and clock-names Miquel Raynal

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox