Commit e5fa173f authored by Linus Torvalds's avatar Linus Torvalds

Merge tag 'clk-fixes-for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/clk/linux

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
parents c816f2e9 daaa2fbe
...@@ -726,6 +726,7 @@ void iproc_pll_clk_setup(struct device_node *node, ...@@ -726,6 +726,7 @@ void iproc_pll_clk_setup(struct device_node *node,
const char *parent_name; const char *parent_name;
struct iproc_clk *iclk_array; struct iproc_clk *iclk_array;
struct clk_hw_onecell_data *clk_data; struct clk_hw_onecell_data *clk_data;
const char *clk_name;
if (WARN_ON(!pll_ctrl) || WARN_ON(!clk_ctrl)) if (WARN_ON(!pll_ctrl) || WARN_ON(!clk_ctrl))
return; return;
...@@ -773,7 +774,12 @@ void iproc_pll_clk_setup(struct device_node *node, ...@@ -773,7 +774,12 @@ void iproc_pll_clk_setup(struct device_node *node,
iclk = &iclk_array[0]; iclk = &iclk_array[0];
iclk->pll = pll; 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.ops = &iproc_pll_ops;
init.flags = 0; init.flags = 0;
parent_name = of_clk_get_parent_name(node, 0); parent_name = of_clk_get_parent_name(node, 0);
...@@ -793,13 +799,11 @@ void iproc_pll_clk_setup(struct device_node *node, ...@@ -793,13 +799,11 @@ void iproc_pll_clk_setup(struct device_node *node,
goto err_pll_register; goto err_pll_register;
clk_data->hws[0] = &iclk->hw; clk_data->hws[0] = &iclk->hw;
parent_name = clk_name;
/* now initialize and register all leaf clocks */ /* now initialize and register all leaf clocks */
for (i = 1; i < num_clks; i++) { for (i = 1; i < num_clks; i++) {
const char *clk_name;
memset(&init, 0, sizeof(init)); memset(&init, 0, sizeof(init));
parent_name = node->name;
ret = of_property_read_string_index(node, "clock-output-names", ret = of_property_read_string_index(node, "clock-output-names",
i, &clk_name); i, &clk_name);
......
...@@ -280,13 +280,13 @@ static void __init imx6sx_clocks_init(struct device_node *ccm_node) ...@@ -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_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_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_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_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_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_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_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_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_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_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)); 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));
......
...@@ -332,7 +332,7 @@ static struct platform_driver imx93_clk_driver = { ...@@ -332,7 +332,7 @@ static struct platform_driver imx93_clk_driver = {
.driver = { .driver = {
.name = "imx93-ccm", .name = "imx93-ccm",
.suppress_bind_attrs = true, .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); module_platform_driver(imx93_clk_driver);
......
...@@ -101,15 +101,11 @@ static bool ingenic_tcu_enable_regs(struct clk_hw *hw) ...@@ -101,15 +101,11 @@ static bool ingenic_tcu_enable_regs(struct clk_hw *hw)
bool enabled = false; bool enabled = false;
/* /*
* If the SoC has no global TCU clock, we must ungate the channel's * According to the programming manual, a timer channel's registers can
* clock to be able to access its registers. * only be accessed when the channel's stop bit is clear.
* If we have a TCU clock, it will be enabled automatically as it has
* been attached to the regmap.
*/ */
if (!tcu->clk) { enabled = !!ingenic_tcu_is_enabled(hw);
enabled = !!ingenic_tcu_is_enabled(hw); regmap_write(tcu->map, TCU_REG_TSCR, BIT(info->gate_bit));
regmap_write(tcu->map, TCU_REG_TSCR, BIT(info->gate_bit));
}
return enabled; return enabled;
} }
...@@ -120,8 +116,7 @@ static void ingenic_tcu_disable_regs(struct clk_hw *hw) ...@@ -120,8 +116,7 @@ static void ingenic_tcu_disable_regs(struct clk_hw *hw)
const struct ingenic_tcu_clk_info *info = tcu_clk->info; const struct ingenic_tcu_clk_info *info = tcu_clk->info;
struct ingenic_tcu *tcu = tcu_clk->tcu; 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) static u8 ingenic_tcu_get_parent(struct clk_hw *hw)
......
...@@ -239,6 +239,11 @@ static const struct clk_ops mpfs_clk_cfg_ops = { ...@@ -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), \ .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[] = { 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, CLK_CFG(CLK_CPU, "clk_cpu", "clk_msspll", 0, 2, mpfs_div_cpu_axi_table, 0,
REG_CLOCK_CONFIG_CR), REG_CLOCK_CONFIG_CR),
...@@ -362,7 +367,7 @@ static const struct clk_ops mpfs_periph_clk_ops = { ...@@ -362,7 +367,7 @@ static const struct clk_ops mpfs_periph_clk_ops = {
_flags), \ _flags), \
} }
#define PARENT_CLK(PARENT) (&mpfs_cfg_clks[CLK_##PARENT].hw) #define PARENT_CLK(PARENT) (&mpfs_cfg_clks[CLK_##PARENT##_OFFSET].hw)
/* /*
* Critical clocks: * Critical clocks:
...@@ -370,6 +375,8 @@ static const struct clk_ops mpfs_periph_clk_ops = { ...@@ -370,6 +375,8 @@ static const struct clk_ops mpfs_periph_clk_ops = {
* trap handler * trap handler
* - CLK_MMUART0: reserved by the hss * - CLK_MMUART0: reserved by the hss
* - CLK_DDRC: provides clock to the ddr subsystem * - 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) * - 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 * clock domain crossers which provide the interface to the FPGA fabric. Disabling them
* causes the FPGA fabric to go into reset. * causes the FPGA fabric to go into reset.
...@@ -394,7 +401,7 @@ static struct mpfs_periph_hw_clock mpfs_periph_clks[] = { ...@@ -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_CAN0, "clk_periph_can0", PARENT_CLK(AHB), 14, 0),
CLK_PERIPH(CLK_CAN1, "clk_periph_can1", PARENT_CLK(AHB), 15, 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_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_QSPI, "clk_periph_qspi", PARENT_CLK(AHB), 19, 0),
CLK_PERIPH(CLK_GPIO0, "clk_periph_gpio0", PARENT_CLK(AHB), 20, 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), CLK_PERIPH(CLK_GPIO1, "clk_periph_gpio1", PARENT_CLK(AHB), 21, 0),
......
...@@ -1191,9 +1191,13 @@ static int sun50i_h6_ccu_probe(struct platform_device *pdev) ...@@ -1191,9 +1191,13 @@ static int sun50i_h6_ccu_probe(struct platform_device *pdev)
if (IS_ERR(reg)) if (IS_ERR(reg))
return PTR_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 = 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); writel(val, reg + SUN50I_H6_PLL_GPU_REG);
/* Force GPU_CLK divider bits to 0 */ /* Force GPU_CLK divider bits to 0 */
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment