Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux

clk: imx8m: fix clock tree update of TF-A managed clocks

On the i.MX8M*, the TF-A exposes a SiP (Silicon Provider) service
for DDR frequency scaling. The imx8m-ddrc-devfreq driver calls the
SiP and then does clk_set_parent on the DDR muxes to synchronize
the clock tree.

Since 936c383673b9 ("clk: imx: fix composite peripheral flags"),
these TF-A managed muxes have SET_PARENT_GATE set, which results
in imx8m-ddrc-devfreq's clk_set_parent after SiP failing with -EBUSY:

echo 25000000 > userspace/set_freq
imx8m-ddrc-devfreq 3d400000.memory-controller: failed to set
dram_apb parent: -16

Fix this by adding a new i.MX composite flag for firmware managed
clocks, which clears SET_PARENT_GATE.

This is safe to do, because updating the Linux clock tree to reflect
reality will always be glitch-free.

Fixes: 936c383673b9 ("clk: imx: fix composite peripheral flags")
Signed-off-by: Ahmad Fatoum <a.fatoum@pengutronix.de>
Reviewed-by: Abel Vesa <abel.vesa@nxp.com>
Link: https://lore.kernel.org/r/20210810151432.9228-1-a.fatoum@pengutronix.de
Signed-off-by: Abel Vesa <abel.vesa@nxp.com>

authored by

Ahmad Fatoum and committed by
Abel Vesa
d36207b8 fb549644

+28 -12
+2 -1
drivers/clk/imx/clk-composite-8m.c
··· 216 216 div->width = PCG_PREDIV_WIDTH; 217 217 divider_ops = &imx8m_clk_composite_divider_ops; 218 218 mux_ops = &clk_mux_ops; 219 - flags |= CLK_SET_PARENT_GATE; 219 + if (!(composite_flags & IMX_COMPOSITE_FW_MANAGED)) 220 + flags |= CLK_SET_PARENT_GATE; 220 221 } 221 222 222 223 div->lock = &imx_ccm_lock;
+4 -3
drivers/clk/imx/clk-imx8mm.c
··· 470 470 471 471 /* 472 472 * DRAM clocks are manipulated from TF-A outside clock framework. 473 - * Mark with GET_RATE_NOCACHE to always read div value from hardware 473 + * The fw_managed helper sets GET_RATE_NOCACHE and clears SET_PARENT_GATE 474 + * as div value should always be read from hardware 474 475 */ 475 - hws[IMX8MM_CLK_DRAM_ALT] = __imx8m_clk_hw_composite("dram_alt", imx8mm_dram_alt_sels, base + 0xa000, CLK_GET_RATE_NOCACHE); 476 - hws[IMX8MM_CLK_DRAM_APB] = __imx8m_clk_hw_composite("dram_apb", imx8mm_dram_apb_sels, base + 0xa080, CLK_IS_CRITICAL | CLK_GET_RATE_NOCACHE); 476 + hws[IMX8MM_CLK_DRAM_ALT] = imx8m_clk_hw_fw_managed_composite("dram_alt", imx8mm_dram_alt_sels, base + 0xa000); 477 + hws[IMX8MM_CLK_DRAM_APB] = imx8m_clk_hw_fw_managed_composite_critical("dram_apb", imx8mm_dram_apb_sels, base + 0xa080); 477 478 478 479 /* IP */ 479 480 hws[IMX8MM_CLK_VPU_G1] = imx8m_clk_hw_composite("vpu_g1", imx8mm_vpu_g1_sels, base + 0xa100);
+4 -3
drivers/clk/imx/clk-imx8mn.c
··· 453 453 454 454 /* 455 455 * DRAM clocks are manipulated from TF-A outside clock framework. 456 - * Mark with GET_RATE_NOCACHE to always read div value from hardware 456 + * The fw_managed helper sets GET_RATE_NOCACHE and clears SET_PARENT_GATE 457 + * as div value should always be read from hardware 457 458 */ 458 - hws[IMX8MN_CLK_DRAM_ALT] = __imx8m_clk_hw_composite("dram_alt", imx8mn_dram_alt_sels, base + 0xa000, CLK_GET_RATE_NOCACHE); 459 - hws[IMX8MN_CLK_DRAM_APB] = __imx8m_clk_hw_composite("dram_apb", imx8mn_dram_apb_sels, base + 0xa080, CLK_IS_CRITICAL | CLK_GET_RATE_NOCACHE); 459 + hws[IMX8MN_CLK_DRAM_ALT] = imx8m_clk_hw_fw_managed_composite("dram_alt", imx8mn_dram_alt_sels, base + 0xa000); 460 + hws[IMX8MN_CLK_DRAM_APB] = imx8m_clk_hw_fw_managed_composite_critical("dram_apb", imx8mn_dram_apb_sels, base + 0xa080); 460 461 461 462 hws[IMX8MN_CLK_DISP_PIXEL] = imx8m_clk_hw_composite("disp_pixel", imx8mn_disp_pixel_sels, base + 0xa500); 462 463 hws[IMX8MN_CLK_SAI2] = imx8m_clk_hw_composite("sai2", imx8mn_sai2_sels, base + 0xa600);
+4 -3
drivers/clk/imx/clk-imx8mq.c
··· 449 449 450 450 /* 451 451 * DRAM clocks are manipulated from TF-A outside clock framework. 452 - * Mark with GET_RATE_NOCACHE to always read div value from hardware 452 + * The fw_managed helper sets GET_RATE_NOCACHE and clears SET_PARENT_GATE 453 + * as div value should always be read from hardware 453 454 */ 454 455 hws[IMX8MQ_CLK_DRAM_CORE] = imx_clk_hw_mux2_flags("dram_core_clk", base + 0x9800, 24, 1, imx8mq_dram_core_sels, ARRAY_SIZE(imx8mq_dram_core_sels), CLK_IS_CRITICAL); 455 - hws[IMX8MQ_CLK_DRAM_ALT] = __imx8m_clk_hw_composite("dram_alt", imx8mq_dram_alt_sels, base + 0xa000, CLK_GET_RATE_NOCACHE); 456 - hws[IMX8MQ_CLK_DRAM_APB] = __imx8m_clk_hw_composite("dram_apb", imx8mq_dram_apb_sels, base + 0xa080, CLK_IS_CRITICAL | CLK_GET_RATE_NOCACHE); 456 + hws[IMX8MQ_CLK_DRAM_ALT] = imx8m_clk_hw_fw_managed_composite("dram_alt", imx8mq_dram_alt_sels, base + 0xa000); 457 + hws[IMX8MQ_CLK_DRAM_APB] = imx8m_clk_hw_fw_managed_composite_critical("dram_apb", imx8mq_dram_apb_sels, base + 0xa080); 457 458 458 459 /* IP */ 459 460 hws[IMX8MQ_CLK_VPU_G1] = imx8m_clk_hw_composite("vpu_g1", imx8mq_vpu_g1_sels, base + 0xa100);
+14 -2
drivers/clk/imx/clk.h
··· 530 530 struct clk *div, struct clk *mux, struct clk *pll, 531 531 struct clk *step); 532 532 533 - #define IMX_COMPOSITE_CORE BIT(0) 534 - #define IMX_COMPOSITE_BUS BIT(1) 533 + #define IMX_COMPOSITE_CORE BIT(0) 534 + #define IMX_COMPOSITE_BUS BIT(1) 535 + #define IMX_COMPOSITE_FW_MANAGED BIT(2) 535 536 536 537 struct clk_hw *imx8m_clk_hw_composite_flags(const char *name, 537 538 const char * const *parent_names, ··· 567 566 imx8m_clk_hw_composite_flags(name, parent_names, \ 568 567 ARRAY_SIZE(parent_names), reg, 0, \ 569 568 flags | CLK_SET_RATE_NO_REPARENT | CLK_OPS_PARENT_ENABLE) 569 + 570 + #define __imx8m_clk_hw_fw_managed_composite(name, parent_names, reg, flags) \ 571 + imx8m_clk_hw_composite_flags(name, parent_names, \ 572 + ARRAY_SIZE(parent_names), reg, IMX_COMPOSITE_FW_MANAGED, \ 573 + flags | CLK_GET_RATE_NOCACHE | CLK_SET_RATE_NO_REPARENT | CLK_OPS_PARENT_ENABLE) 574 + 575 + #define imx8m_clk_hw_fw_managed_composite(name, parent_names, reg) \ 576 + __imx8m_clk_hw_fw_managed_composite(name, parent_names, reg, 0) 577 + 578 + #define imx8m_clk_hw_fw_managed_composite_critical(name, parent_names, reg) \ 579 + __imx8m_clk_hw_fw_managed_composite(name, parent_names, reg, CLK_IS_CRITICAL) 570 580 571 581 #define __imx8m_clk_composite(name, parent_names, reg, flags) \ 572 582 to_clk(__imx8m_clk_hw_composite(name, parent_names, reg, flags))