Merge tag 'clk-fixes-for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git...
authorLinus Torvalds <torvalds@linux-foundation.org>
Fri, 30 Sep 2022 23:19:41 +0000 (16:19 -0700)
committerLinus Torvalds <torvalds@linux-foundation.org>
Fri, 30 Sep 2022 23:19:41 +0000 (16:19 -0700)
Pull clk driver fixes from Stephen Boyd:
 "Here's the last batch of clk driver fixes for this release.

  These patches fix serious problems, for example, i.MX has an issue
  where changing the NAND clk frequency hangs the system. On Allwinner
  H6 the GPU is being overclocked which could lead to long term hardware
  damage.

  And finally on some Broadcom SoCs the serial console stopped working
  because the clk tree hierarchy description got broken by an
  inadvertant DT node name change. That's fixed by using
  'clock-output-names' to generate a stable and unique name for clks so
  the framework can properly link things up.

  There's also a couple build fixes in here. One to fix CONFIG_OF=n
  builds and one to avoid an array out of bounds bug that happens during
  clk registration on microchip. I hope that KASAN would have found that
  OOB problem, but probably KASAN wasn't attempted. Instead LLVM/clang
  compilation caused an oops, while GCC didn't"

* tag 'clk-fixes-for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/clk/linux:
  clk: imx93: drop of_match_ptr
  clk: iproc: Do not rely on node name for correct PLL setup
  clk: sunxi-ng: h6: Fix default PLL GPU rate
  clk: imx: imx6sx: remove the SET_RATE_PARENT flag for QSPI clocks
  clk: microchip: mpfs: make the rtc's ahb clock critical
  clk: microchip: mpfs: fix clk_cfg array bounds violation
  clk: ingenic-tcu: Properly enable registers before accessing timers

drivers/clk/bcm/clk-iproc-pll.c
drivers/clk/imx/clk-imx6sx.c
drivers/clk/imx/clk-imx93.c
drivers/clk/ingenic/tcu.c
drivers/clk/microchip/clk-mpfs.c
drivers/clk/sunxi-ng/ccu-sun50i-h6.c

index 1a098db..680f9d8 100644 (file)
@@ -726,6 +726,7 @@ void iproc_pll_clk_setup(struct device_node *node,
        const char *parent_name;
        struct iproc_clk *iclk_array;
        struct clk_hw_onecell_data *clk_data;
+       const char *clk_name;
 
        if (WARN_ON(!pll_ctrl) || WARN_ON(!clk_ctrl))
                return;
@@ -773,7 +774,12 @@ void iproc_pll_clk_setup(struct device_node *node,
        iclk = &iclk_array[0];
        iclk->pll = pll;
 
-       init.name = node->name;
+       ret = of_property_read_string_index(node, "clock-output-names",
+                                           0, &clk_name);
+       if (WARN_ON(ret))
+               goto err_pll_register;
+
+       init.name = clk_name;
        init.ops = &iproc_pll_ops;
        init.flags = 0;
        parent_name = of_clk_get_parent_name(node, 0);
@@ -793,13 +799,11 @@ void iproc_pll_clk_setup(struct device_node *node,
                goto err_pll_register;
 
        clk_data->hws[0] = &iclk->hw;
+       parent_name = clk_name;
 
        /* now initialize and register all leaf clocks */
        for (i = 1; i < num_clks; i++) {
-               const char *clk_name;
-
                memset(&init, 0, sizeof(init));
-               parent_name = node->name;
 
                ret = of_property_read_string_index(node, "clock-output-names",
                                                    i, &clk_name);
index fc1bd23..598f3cf 100644 (file)
@@ -280,13 +280,13 @@ static void __init imx6sx_clocks_init(struct device_node *ccm_node)
        hws[IMX6SX_CLK_SSI3_SEL]           = imx_clk_hw_mux("ssi3_sel",         base + 0x1c,  14,     2,      ssi_sels,          ARRAY_SIZE(ssi_sels));
        hws[IMX6SX_CLK_SSI2_SEL]           = imx_clk_hw_mux("ssi2_sel",         base + 0x1c,  12,     2,      ssi_sels,          ARRAY_SIZE(ssi_sels));
        hws[IMX6SX_CLK_SSI1_SEL]           = imx_clk_hw_mux("ssi1_sel",         base + 0x1c,  10,     2,      ssi_sels,          ARRAY_SIZE(ssi_sels));
-       hws[IMX6SX_CLK_QSPI1_SEL]          = imx_clk_hw_mux_flags("qspi1_sel", base + 0x1c,  7, 3, qspi1_sels, ARRAY_SIZE(qspi1_sels), CLK_SET_RATE_PARENT);
+       hws[IMX6SX_CLK_QSPI1_SEL]          = imx_clk_hw_mux("qspi1_sel",        base + 0x1c,  7,      3,      qspi1_sels,        ARRAY_SIZE(qspi1_sels));
        hws[IMX6SX_CLK_PERCLK_SEL]         = imx_clk_hw_mux("perclk_sel",       base + 0x1c,  6,      1,      perclk_sels,       ARRAY_SIZE(perclk_sels));
        hws[IMX6SX_CLK_VID_SEL]            = imx_clk_hw_mux("vid_sel",          base + 0x20,  21,     3,      vid_sels,          ARRAY_SIZE(vid_sels));
        hws[IMX6SX_CLK_ESAI_SEL]           = imx_clk_hw_mux("esai_sel",         base + 0x20,  19,     2,      audio_sels,        ARRAY_SIZE(audio_sels));
        hws[IMX6SX_CLK_CAN_SEL]            = imx_clk_hw_mux("can_sel",          base + 0x20,  8,      2,      can_sels,          ARRAY_SIZE(can_sels));
        hws[IMX6SX_CLK_UART_SEL]           = imx_clk_hw_mux("uart_sel",         base + 0x24,  6,      1,      uart_sels,         ARRAY_SIZE(uart_sels));
-       hws[IMX6SX_CLK_QSPI2_SEL]          = imx_clk_hw_mux_flags("qspi2_sel", base + 0x2c, 15, 3, qspi2_sels, ARRAY_SIZE(qspi2_sels), CLK_SET_RATE_PARENT);
+       hws[IMX6SX_CLK_QSPI2_SEL]          = imx_clk_hw_mux("qspi2_sel",        base + 0x2c,  15,     3,      qspi2_sels,        ARRAY_SIZE(qspi2_sels));
        hws[IMX6SX_CLK_SPDIF_SEL]          = imx_clk_hw_mux("spdif_sel",        base + 0x30,  20,     2,      audio_sels,        ARRAY_SIZE(audio_sels));
        hws[IMX6SX_CLK_AUDIO_SEL]          = imx_clk_hw_mux("audio_sel",        base + 0x30,  7,      2,      audio_sels,        ARRAY_SIZE(audio_sels));
        hws[IMX6SX_CLK_ENET_PRE_SEL]       = imx_clk_hw_mux("enet_pre_sel",     base + 0x34,  15,     3,      enet_pre_sels,     ARRAY_SIZE(enet_pre_sels));
index f5c9fa4..dcc41d1 100644 (file)
@@ -332,7 +332,7 @@ static struct platform_driver imx93_clk_driver = {
        .driver = {
                .name = "imx93-ccm",
                .suppress_bind_attrs = true,
-               .of_match_table = of_match_ptr(imx93_clk_of_match),
+               .of_match_table = imx93_clk_of_match,
        },
 };
 module_platform_driver(imx93_clk_driver);
index 201bf6e..d5544cb 100644 (file)
@@ -101,15 +101,11 @@ static bool ingenic_tcu_enable_regs(struct clk_hw *hw)
        bool enabled = false;
 
        /*
-        * If the SoC has no global TCU clock, we must ungate the channel's
-        * clock to be able to access its registers.
-        * If we have a TCU clock, it will be enabled automatically as it has
-        * been attached to the regmap.
+        * According to the programming manual, a timer channel's registers can
+        * only be accessed when the channel's stop bit is clear.
         */
-       if (!tcu->clk) {
-               enabled = !!ingenic_tcu_is_enabled(hw);
-               regmap_write(tcu->map, TCU_REG_TSCR, BIT(info->gate_bit));
-       }
+       enabled = !!ingenic_tcu_is_enabled(hw);
+       regmap_write(tcu->map, TCU_REG_TSCR, BIT(info->gate_bit));
 
        return enabled;
 }
@@ -120,8 +116,7 @@ static void ingenic_tcu_disable_regs(struct clk_hw *hw)
        const struct ingenic_tcu_clk_info *info = tcu_clk->info;
        struct ingenic_tcu *tcu = tcu_clk->tcu;
 
-       if (!tcu->clk)
-               regmap_write(tcu->map, TCU_REG_TSSR, BIT(info->gate_bit));
+       regmap_write(tcu->map, TCU_REG_TSSR, BIT(info->gate_bit));
 }
 
 static u8 ingenic_tcu_get_parent(struct clk_hw *hw)
index 070c3b8..b6b8941 100644 (file)
@@ -239,6 +239,11 @@ static const struct clk_ops mpfs_clk_cfg_ops = {
        .hw.init = CLK_HW_INIT(_name, _parent, &mpfs_clk_cfg_ops, 0),                   \
 }
 
+#define CLK_CPU_OFFSET         0u
+#define CLK_AXI_OFFSET         1u
+#define CLK_AHB_OFFSET         2u
+#define CLK_RTCREF_OFFSET      3u
+
 static struct mpfs_cfg_hw_clock mpfs_cfg_clks[] = {
        CLK_CFG(CLK_CPU, "clk_cpu", "clk_msspll", 0, 2, mpfs_div_cpu_axi_table, 0,
                REG_CLOCK_CONFIG_CR),
@@ -362,7 +367,7 @@ static const struct clk_ops mpfs_periph_clk_ops = {
                                  _flags),                                      \
 }
 
-#define PARENT_CLK(PARENT) (&mpfs_cfg_clks[CLK_##PARENT].hw)
+#define PARENT_CLK(PARENT) (&mpfs_cfg_clks[CLK_##PARENT##_OFFSET].hw)
 
 /*
  * Critical clocks:
@@ -370,6 +375,8 @@ static const struct clk_ops mpfs_periph_clk_ops = {
  *   trap handler
  * - CLK_MMUART0: reserved by the hss
  * - CLK_DDRC: provides clock to the ddr subsystem
+ * - CLK_RTC: the onboard RTC's AHB bus clock must be kept running as the rtc will stop
+ *   if the AHB interface clock is disabled
  * - CLK_FICx: these provide the processor side clocks to the "FIC" (Fabric InterConnect)
  *   clock domain crossers which provide the interface to the FPGA fabric. Disabling them
  *   causes the FPGA fabric to go into reset.
@@ -394,7 +401,7 @@ static struct mpfs_periph_hw_clock mpfs_periph_clks[] = {
        CLK_PERIPH(CLK_CAN0, "clk_periph_can0", PARENT_CLK(AHB), 14, 0),
        CLK_PERIPH(CLK_CAN1, "clk_periph_can1", PARENT_CLK(AHB), 15, 0),
        CLK_PERIPH(CLK_USB, "clk_periph_usb", PARENT_CLK(AHB), 16, 0),
-       CLK_PERIPH(CLK_RTC, "clk_periph_rtc", PARENT_CLK(AHB), 18, 0),
+       CLK_PERIPH(CLK_RTC, "clk_periph_rtc", PARENT_CLK(AHB), 18, CLK_IS_CRITICAL),
        CLK_PERIPH(CLK_QSPI, "clk_periph_qspi", PARENT_CLK(AHB), 19, 0),
        CLK_PERIPH(CLK_GPIO0, "clk_periph_gpio0", PARENT_CLK(AHB), 20, 0),
        CLK_PERIPH(CLK_GPIO1, "clk_periph_gpio1", PARENT_CLK(AHB), 21, 0),
index 30056da..42568c6 100644 (file)
@@ -1191,9 +1191,13 @@ static int sun50i_h6_ccu_probe(struct platform_device *pdev)
        if (IS_ERR(reg))
                return PTR_ERR(reg);
 
-       /* Force PLL_GPU output divider bits to 0 */
+       /*
+        * Force PLL_GPU output divider bits to 0 and adjust
+        * multiplier to sensible default value of 432 MHz.
+        */
        val = readl(reg + SUN50I_H6_PLL_GPU_REG);
-       val &= ~BIT(0);
+       val &= ~(GENMASK(15, 8) | BIT(0));
+       val |= 17 << 8;
        writel(val, reg + SUN50I_H6_PLL_GPU_REG);
 
        /* Force GPU_CLK divider bits to 0 */