mirror of https://lore.kernel.org/lkml/
 help / color / mirror / Atom feed
* [PATCH v2 0/3] clk: nuvoton: ma35d1: Fix mux parenting and peripheral clock rates
@ 2026-09-21  6:44 Miquel Raynal
  2026-09-21  6:44 ` [PATCH v2 1/3] clk: nuvoton: ma35d1: Add missing WDT/WWDT parent clocks Miquel Raynal
                   ` (2 more replies)
  0 siblings, 3 replies; 8+ messages in thread
From: Miquel Raynal @ 2026-09-21  6:44 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
  Cc: Thomas Petazzoni, Steam Lin, linux-arm-kernel, linux-clk,
	linux-kernel, Krzysztof Kozlowski, devicetree, Miquel Raynal,
	Jacky Huang, 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 an 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.

Signed-off-by: Miquel Raynal <miquel.raynal@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 (3):
      clk: nuvoton: ma35d1: Add missing WDT/WWDT parent clocks
      clk: nuvoton: ma35d1: Use clk_hw pointers as mux parents
      clk: nuvoton: ma35d1: Avoid possible error pointer dereferencing

 drivers/clk/nuvoton/clk-ma35d1-divider.c       |   3 +
 drivers/clk/nuvoton/clk-ma35d1-pll.c           |   3 +
 drivers/clk/nuvoton/clk-ma35d1.c               | 637 ++++++++-----------------
 include/dt-bindings/clock/nuvoton,ma35d1-clk.h |   4 +-
 4 files changed, 197 insertions(+), 450 deletions(-)
---
base-commit: cee9395acd8043be0644b25c34bfa86623f2b935
change-id: 20260813-perso-ma35d1-upstream-clk-65cacfc1a86b

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


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

* [PATCH v2 1/3] clk: nuvoton: ma35d1: Add missing WDT/WWDT parent clocks
  2026-09-21  6:44 [PATCH v2 0/3] clk: nuvoton: ma35d1: Fix mux parenting and peripheral clock rates Miquel Raynal
@ 2026-09-21  6:44 ` Miquel Raynal
  2026-09-24 13:25   ` Krzysztof Kozlowski
  2026-09-21  6:44 ` [PATCH v2 2/3] clk: nuvoton: ma35d1: Use clk_hw pointers as mux parents Miquel Raynal
  2026-09-21  6:44 ` [PATCH v2 3/3] clk: nuvoton: ma35d1: Avoid possible error pointer dereferencing Miquel Raynal
  2 siblings, 1 reply; 8+ messages in thread
From: Miquel Raynal @ 2026-09-21  6:44 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
  Cc: Thomas Petazzoni, Steam Lin, linux-arm-kernel, linux-clk,
	linux-kernel, Krzysztof Kozlowski, devicetree, Miquel Raynal,
	Jacky Huang, stable

The WDT and WWDT muxes list PCLK3/4096 and PCLK4/4096 among their
possible parents, but the driver never registers the corresponding
clocks, so these parents could never be used.

Add pclk3_div4096 and pclk4_div4096 as fixed factor children of pclk3
and pclk4 and expose them through the clock provider.

Reported-by: Jacky Huang <ychuang570808@gmail.com>
Closes: https://lore.kernel.org/linux-clk/b8a8a65b-e302-4747-bc90-4920fc48795a@gmail.com/
Suggested-by: Jacky Huang <ychuang570808@gmail.com>
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               | 2 ++
 include/dt-bindings/clock/nuvoton,ma35d1-clk.h | 4 +++-
 2 files changed, 5 insertions(+), 1 deletion(-)

diff --git a/drivers/clk/nuvoton/clk-ma35d1.c b/drivers/clk/nuvoton/clk-ma35d1.c
index 9f65d0623517..9d57de6a1e56 100644
--- a/drivers/clk/nuvoton/clk-ma35d1.c
+++ b/drivers/clk/nuvoton/clk-ma35d1.c
@@ -543,6 +543,8 @@ static int ma35d1_clocks_probe(struct platform_device *pdev)
 	hws[HCLK3] = ma35d1_clk_fixed_factor(dev, "hclk3", "sysclk1_mux", 1, 2);
 	hws[PCLK3] = ma35d1_clk_fixed_factor(dev, "pclk3", "sysclk1_mux", 1, 2);
 	hws[PCLK4] = ma35d1_clk_fixed_factor(dev, "pclk4", "sysclk1_mux", 1, 2);
+	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);
diff --git a/include/dt-bindings/clock/nuvoton,ma35d1-clk.h b/include/dt-bindings/clock/nuvoton,ma35d1-clk.h
index ba2d70f776a6..d3fd8251c806 100644
--- a/include/dt-bindings/clock/nuvoton,ma35d1-clk.h
+++ b/include/dt-bindings/clock/nuvoton,ma35d1-clk.h
@@ -248,6 +248,8 @@
 #define ADC_GATE	233
 #define EADC_DIV	234
 #define EADC_GATE	235
-#define	CLK_MAX_IDX	236
+#define PCLK3_DIV4096	236
+#define PCLK4_DIV4096	237
+#define	CLK_MAX_IDX	238
 
 #endif /* __DT_BINDINGS_CLOCK_NUVOTON_MA35D1_CLK_H */

-- 
2.55.0


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

* [PATCH v2 2/3] clk: nuvoton: ma35d1: Use clk_hw pointers as mux parents
  2026-09-21  6:44 [PATCH v2 0/3] clk: nuvoton: ma35d1: Fix mux parenting and peripheral clock rates Miquel Raynal
  2026-09-21  6:44 ` [PATCH v2 1/3] clk: nuvoton: ma35d1: Add missing WDT/WWDT parent clocks Miquel Raynal
@ 2026-09-21  6:44 ` Miquel Raynal
  2026-09-21  6:44 ` [PATCH v2 3/3] clk: nuvoton: ma35d1: Avoid possible error pointer dereferencing Miquel Raynal
  2 siblings, 0 replies; 8+ messages in thread
From: Miquel Raynal @ 2026-09-21  6:44 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
  Cc: Thomas Petazzoni, Steam Lin, linux-arm-kernel, linux-clk,
	linux-kernel, Krzysztof Kozlowski, devicetree, 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 9d57de6a1e56..e45b3b12f359 100644
--- a/drivers/clk/nuvoton/clk-ma35d1.c
+++ b/drivers/clk/nuvoton/clk-ma35d1.c
@@ -62,300 +62,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},
@@ -374,24 +123,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,
@@ -514,22 +259,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 */
@@ -555,41 +295,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);
 
@@ -605,14 +345,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",
@@ -624,14 +364,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);
@@ -669,13 +409,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",
@@ -713,181 +453,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);
@@ -899,8 +627,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);
@@ -920,49 +648,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);
@@ -971,12 +699,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);
 
@@ -985,20 +713,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	[flat|nested] 8+ messages in thread

* [PATCH v2 3/3] clk: nuvoton: ma35d1: Avoid possible error pointer dereferencing
  2026-09-21  6:44 [PATCH v2 0/3] clk: nuvoton: ma35d1: Fix mux parenting and peripheral clock rates Miquel Raynal
  2026-09-21  6:44 ` [PATCH v2 1/3] clk: nuvoton: ma35d1: Add missing WDT/WWDT parent clocks Miquel Raynal
  2026-09-21  6:44 ` [PATCH v2 2/3] clk: nuvoton: ma35d1: Use clk_hw pointers as mux parents Miquel Raynal
@ 2026-09-21  6:44 ` Miquel Raynal
  2 siblings, 0 replies; 8+ messages in thread
From: Miquel Raynal @ 2026-09-21  6:44 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
  Cc: Thomas Petazzoni, Steam Lin, linux-arm-kernel, linux-clk,
	linux-kernel, Krzysztof Kozlowski, devicetree, 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 e45b3b12f359..f13e7040f71e 100644
--- a/drivers/clk/nuvoton/clk-ma35d1.c
+++ b/drivers/clk/nuvoton/clk-ma35d1.c
@@ -129,10 +129,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	[flat|nested] 8+ messages in thread

* Re: [PATCH v2 1/3] clk: nuvoton: ma35d1: Add missing WDT/WWDT parent clocks
  2026-09-21  6:44 ` [PATCH v2 1/3] clk: nuvoton: ma35d1: Add missing WDT/WWDT parent clocks Miquel Raynal
@ 2026-09-24 13:25   ` Krzysztof Kozlowski
  2026-09-25 10:18     ` Miquel Raynal
  0 siblings, 1 reply; 8+ messages in thread
From: Krzysztof Kozlowski @ 2026-09-24 13:25 UTC (permalink / raw)
  To: Miquel Raynal
  Cc: Jacky Huang, Shan-Chun Hung, Michael Turquette, Stephen Boyd,
	Richard Cochran, Arnd Bergmann, Brian Masney, Jerome Brunet,
	Rob Herring, Krzysztof Kozlowski, Conor Dooley, Thomas Petazzoni,
	Steam Lin, linux-arm-kernel, linux-clk, linux-kernel, devicetree,
	Jacky Huang, stable

On Mon, Sep 21, 2026 at 08:44:45AM +0200, Miquel Raynal wrote:
> The WDT and WWDT muxes list PCLK3/4096 and PCLK4/4096 among their
> possible parents, but the driver never registers the corresponding
> clocks, so these parents could never be used.
> 
> Add pclk3_div4096 and pclk4_div4096 as fixed factor children of pclk3
> and pclk4 and expose them through the clock provider.
> 
> Reported-by: Jacky Huang <ychuang570808@gmail.com>
> Closes: https://lore.kernel.org/linux-clk/b8a8a65b-e302-4747-bc90-4920fc48795a@gmail.com/
> Suggested-by: Jacky Huang <ychuang570808@gmail.com>
> 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               | 2 ++
>  include/dt-bindings/clock/nuvoton,ma35d1-clk.h | 4 +++-

Please do not combine patches.

>  2 files changed, 5 insertions(+), 1 deletion(-)
> 
> diff --git a/drivers/clk/nuvoton/clk-ma35d1.c b/drivers/clk/nuvoton/clk-ma35d1.c
> index 9f65d0623517..9d57de6a1e56 100644
> --- a/drivers/clk/nuvoton/clk-ma35d1.c
> +++ b/drivers/clk/nuvoton/clk-ma35d1.c
> @@ -543,6 +543,8 @@ static int ma35d1_clocks_probe(struct platform_device *pdev)
>  	hws[HCLK3] = ma35d1_clk_fixed_factor(dev, "hclk3", "sysclk1_mux", 1, 2);
>  	hws[PCLK3] = ma35d1_clk_fixed_factor(dev, "pclk3", "sysclk1_mux", 1, 2);
>  	hws[PCLK4] = ma35d1_clk_fixed_factor(dev, "pclk4", "sysclk1_mux", 1, 2);
> +	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);
> diff --git a/include/dt-bindings/clock/nuvoton,ma35d1-clk.h b/include/dt-bindings/clock/nuvoton,ma35d1-clk.h
> index ba2d70f776a6..d3fd8251c806 100644
> --- a/include/dt-bindings/clock/nuvoton,ma35d1-clk.h
> +++ b/include/dt-bindings/clock/nuvoton,ma35d1-clk.h
> @@ -248,6 +248,8 @@
>  #define ADC_GATE	233
>  #define EADC_DIV	234
>  #define EADC_GATE	235
> -#define	CLK_MAX_IDX	236
> +#define PCLK3_DIV4096	236
> +#define PCLK4_DIV4096	237
> +#define	CLK_MAX_IDX	238

This cannot be updated. If it has to, then not a binding and should be
first dropped from the bindings like we did for most of the platforms
having similar issue.

Best regards,
Krzysztof


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

* Re: [PATCH v2 1/3] clk: nuvoton: ma35d1: Add missing WDT/WWDT parent clocks
  2026-09-24 13:25   ` Krzysztof Kozlowski
@ 2026-09-25 10:18     ` Miquel Raynal
  2026-09-25 12:58       ` Krzysztof Kozlowski
  0 siblings, 1 reply; 8+ messages in thread
From: Miquel Raynal @ 2026-09-25 10:18 UTC (permalink / raw)
  To: Krzysztof Kozlowski
  Cc: Jacky Huang, Shan-Chun Hung, Michael Turquette, Stephen Boyd,
	Richard Cochran, Arnd Bergmann, Brian Masney, Jerome Brunet,
	Rob Herring, Krzysztof Kozlowski, Conor Dooley, Thomas Petazzoni,
	Steam Lin, linux-arm-kernel, linux-clk, linux-kernel, devicetree,
	Jacky Huang, stable

Hello Krzysztof,

>> Reported-by: Jacky Huang <ychuang570808@gmail.com>
>> Closes: https://lore.kernel.org/linux-clk/b8a8a65b-e302-4747-bc90-4920fc48795a@gmail.com/
>> Suggested-by: Jacky Huang <ychuang570808@gmail.com>
>> 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               | 2 ++
>>  include/dt-bindings/clock/nuvoton,ma35d1-clk.h | 4 +++-
>
> Please do not combine patches.

I thought splitting these changes would not make sense in this (= a fix)
case, but fine.

[...]

>> @@ -248,6 +248,8 @@
>>  #define ADC_GATE	233
>>  #define EADC_DIV	234
>>  #define EADC_GATE	235
>> -#define	CLK_MAX_IDX	236
>> +#define PCLK3_DIV4096	236
>> +#define PCLK4_DIV4096	237
>> +#define	CLK_MAX_IDX	238
>
> This cannot be updated. If it has to, then not a binding and should be
> first dropped from the bindings like we did for most of the platforms
> having similar issue.

When you say "This cannot be updated", do we agree that you mean
"CLK_MAX_IDX cannot be updated"?

I'm not sure I fully understand the reasoning behind, because the whole
point of defining this CLK_MAX_IDX value is to let drivers know the
number of clocks, so it must obviously follow the updates in this
file. I cannot just drop it, the driver does not work without it. If we
enlarge that number, what is the problem as long as we keep the other
numbers identical?

Maybe one way to fix that mess is to:
1- Add the 2 new values (238 and 239) + a new define:
   NUVOTON_MA35D1_MAX_IDX 240
   238 would then have two definitions for a short period of time.
2- Replace CLK_MAX_IDX by NUVOTON_MA35D1_MAX_IDX in the driver
3- Drop CLK_MAX_IDX in the bindings.
or
3bis- Keep CLK_MAX_IDX in the bindings, but add a comment stating that
      it is a stale definition in step 2. This solution looks horrible
      :-)

Let me know what is the best way forward here, the goal being to merge
the big fix that I do care about (currently PATCH 2/3). Fixing the
missing watchdog clock definition has been asked by Jacky in v1, but I
will drop this part and keep v1 if it turns out to be too much churn.

Thanks,
Miquèl

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

* Re: [PATCH v2 1/3] clk: nuvoton: ma35d1: Add missing WDT/WWDT parent clocks
  2026-09-25 10:18     ` Miquel Raynal
@ 2026-09-25 12:58       ` Krzysztof Kozlowski
  2026-09-25 13:24         ` Miquel Raynal
  0 siblings, 1 reply; 8+ messages in thread
From: Krzysztof Kozlowski @ 2026-09-25 12:58 UTC (permalink / raw)
  To: Miquel Raynal
  Cc: Jacky Huang, Shan-Chun Hung, Michael Turquette, Stephen Boyd,
	Richard Cochran, Arnd Bergmann, Brian Masney, Jerome Brunet,
	Rob Herring, Krzysztof Kozlowski, Conor Dooley, Thomas Petazzoni,
	Steam Lin, linux-arm-kernel, linux-clk, linux-kernel, devicetree,
	Jacky Huang, stable

On Fri, Sep 25, 2026 at 12:18:43PM +0200, Miquel Raynal wrote:
> Hello Krzysztof,
> 
> >> Reported-by: Jacky Huang <ychuang570808@gmail.com>
> >> Closes: https://lore.kernel.org/linux-clk/b8a8a65b-e302-4747-bc90-4920fc48795a@gmail.com/
> >> Suggested-by: Jacky Huang <ychuang570808@gmail.com>
> >> 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               | 2 ++
> >>  include/dt-bindings/clock/nuvoton,ma35d1-clk.h | 4 +++-
> >
> > Please do not combine patches.
> 
> I thought splitting these changes would not make sense in this (= a fix)
> case, but fine.
> 
> [...]
> 
> >> @@ -248,6 +248,8 @@
> >>  #define ADC_GATE	233
> >>  #define EADC_DIV	234
> >>  #define EADC_GATE	235
> >> -#define	CLK_MAX_IDX	236
> >> +#define PCLK3_DIV4096	236
> >> +#define PCLK4_DIV4096	237
> >> +#define	CLK_MAX_IDX	238
> >
> > This cannot be updated. If it has to, then not a binding and should be
> > first dropped from the bindings like we did for most of the platforms
> > having similar issue.
> 
> When you say "This cannot be updated", do we agree that you mean
> "CLK_MAX_IDX cannot be updated"?

Yes, the MAX ID.

> 
> I'm not sure I fully understand the reasoning behind, because the whole
> point of defining this CLK_MAX_IDX value is to let drivers know the
> number of clocks, so it must obviously follow the updates in this
> file. I cannot just drop it, the driver does not work without it. If we

It's not a binding if it has to change, because bindings should not
change - otherwise they break its users, because  since it is ABI there
is an outside user expecting EXACTLY this number of clocks and it cannot
grow. Obviously, this is not a binding just like FOR EVERY other case so
can be safely dropped.

> enlarge that number, what is the problem as long as we keep the other
> numbers identical?
> 
> Maybe one way to fix that mess is to:
> 1- Add the 2 new values (238 and 239) + a new define:
>    NUVOTON_MA35D1_MAX_IDX 240
>    238 would then have two definitions for a short period of time.
> 2- Replace CLK_MAX_IDX by NUVOTON_MA35D1_MAX_IDX in the driver
> 3- Drop CLK_MAX_IDX in the bindings.

Why we can't fix it like we did everywhere else?
git lg -- include/dt-bindings/clock/
and search for "number" which leads to recent commits like
d10f26a7abbd3dd5d59bac1acdca117385b54ea9
but there was same work for Samsung and many others (Renesas, maybe
NXP?). You add define to the driver, then drop it from the binding. Can
be a few commits like we did for many cases, but recent change from
Linus I think went acked while combined binding and driver.

Best regards,
Krzysztof


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

* Re: [PATCH v2 1/3] clk: nuvoton: ma35d1: Add missing WDT/WWDT parent clocks
  2026-09-25 12:58       ` Krzysztof Kozlowski
@ 2026-09-25 13:24         ` Miquel Raynal
  0 siblings, 0 replies; 8+ messages in thread
From: Miquel Raynal @ 2026-09-25 13:24 UTC (permalink / raw)
  To: Krzysztof Kozlowski
  Cc: Jacky Huang, Shan-Chun Hung, Michael Turquette, Stephen Boyd,
	Richard Cochran, Arnd Bergmann, Brian Masney, Jerome Brunet,
	Rob Herring, Krzysztof Kozlowski, Conor Dooley, Thomas Petazzoni,
	Steam Lin, linux-arm-kernel, linux-clk, linux-kernel, devicetree,
	Jacky Huang, stable


>> Maybe one way to fix that mess is to:
>> 1- Add the 2 new values (238 and 239) + a new define:
>>    NUVOTON_MA35D1_MAX_IDX 240
>>    238 would then have two definitions for a short period of time.
>> 2- Replace CLK_MAX_IDX by NUVOTON_MA35D1_MAX_IDX in the driver
>> 3- Drop CLK_MAX_IDX in the bindings.
>
> Why we can't fix it like we did everywhere else?
> git lg -- include/dt-bindings/clock/
> and search for "number" which leads to recent commits like
> d10f26a7abbd3dd5d59bac1acdca117385b54ea9
> but there was same work for Samsung and many others (Renesas, maybe
> NXP?). You add define to the driver, then drop it from the
> binding. Can

Aaah, ok, got it. Now I get what you mean by "the max is not a
binding". While true, I find it much less obvious to have it somewhere
outside of the file defining the clocks. I would have "preferred" to
consider the name of the definition immutable, rather than its value,
but if that's the way, I'll comply :-)

> be a few commits like we did for many cases, but recent change from
> Linus I think went acked while combined binding and driver.

Thanks for the pointers, I'll "move" that number away from the bindings,
since the driver is the only consumer of that.

Thanks,
Miquèl

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

end of thread, other threads:[~2026-09-25 13:24 UTC | newest]

Thread overview: 8+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2026-09-21  6:44 [PATCH v2 0/3] clk: nuvoton: ma35d1: Fix mux parenting and peripheral clock rates Miquel Raynal
2026-09-21  6:44 ` [PATCH v2 1/3] clk: nuvoton: ma35d1: Add missing WDT/WWDT parent clocks Miquel Raynal
2026-09-24 13:25   ` Krzysztof Kozlowski
2026-09-25 10:18     ` Miquel Raynal
2026-09-25 12:58       ` Krzysztof Kozlowski
2026-09-25 13:24         ` Miquel Raynal
2026-09-21  6:44 ` [PATCH v2 2/3] clk: nuvoton: ma35d1: Use clk_hw pointers as mux parents Miquel Raynal
2026-09-21  6:44 ` [PATCH v2 3/3] clk: nuvoton: ma35d1: Avoid possible error pointer dereferencing Miquel Raynal

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

all inboxes | Powered by JetHome®