diff options
38 files changed, 660 insertions, 95 deletions
diff --git a/Documentation/devicetree/bindings/clock/allwinner,sun8i-a83t-de2-clk.yaml b/Documentation/devicetree/bindings/clock/allwinner,sun8i-a83t-de2-clk.yaml index 70369bd633e4..7fcd55d468d4 100644 --- a/Documentation/devicetree/bindings/clock/allwinner,sun8i-a83t-de2-clk.yaml +++ b/Documentation/devicetree/bindings/clock/allwinner,sun8i-a83t-de2-clk.yaml @@ -25,6 +25,7 @@ properties: - const: allwinner,sun50i-a64-de2-clk - const: allwinner,sun50i-h5-de2-clk - const: allwinner,sun50i-h6-de3-clk + - const: allwinner,sun50i-h616-de33-clk - items: - const: allwinner,sun8i-r40-de2-clk - const: allwinner,sun8i-h3-de2-clk diff --git a/Documentation/devicetree/bindings/clock/qcom,videocc.yaml b/Documentation/devicetree/bindings/clock/qcom,videocc.yaml index 340c7e5cf980..5f7738d6835c 100644 --- a/Documentation/devicetree/bindings/clock/qcom,videocc.yaml +++ b/Documentation/devicetree/bindings/clock/qcom,videocc.yaml @@ -14,6 +14,7 @@ description: | domains on Qualcomm SoCs. See also:: + include/dt-bindings/clock/qcom,sm6350-videocc.h include/dt-bindings/clock/qcom,videocc-sc7180.h include/dt-bindings/clock/qcom,videocc-sc7280.h include/dt-bindings/clock/qcom,videocc-sdm845.h @@ -26,6 +27,7 @@ properties: - qcom,sc7180-videocc - qcom,sc7280-videocc - qcom,sdm845-videocc + - qcom,sm6350-videocc - qcom,sm8150-videocc - qcom,sm8250-videocc @@ -91,6 +93,24 @@ allOf: properties: compatible: enum: + - qcom,sm6350-videocc + then: + properties: + clocks: + items: + - description: Video AHB clock from GCC + - description: Board XO source + - description: Sleep Clock source + clock-names: + items: + - const: iface + - const: bi_tcxo + - const: sleep_clk + + - if: + properties: + compatible: + enum: - qcom,sm8150-videocc then: properties: diff --git a/drivers/clk/meson/Kconfig b/drivers/clk/meson/Kconfig index be2e3a5f8336..ff003dc5ab20 100644 --- a/drivers/clk/meson/Kconfig +++ b/drivers/clk/meson/Kconfig @@ -55,7 +55,7 @@ config COMMON_CLK_MESON_CPU_DYNDIV config COMMON_CLK_MESON8B bool "Meson8 SoC Clock controller support" depends on ARM - default y + default ARCH_MESON select COMMON_CLK_MESON_REGMAP select COMMON_CLK_MESON_CLKC_UTILS select COMMON_CLK_MESON_MPLL @@ -70,7 +70,7 @@ config COMMON_CLK_MESON8B config COMMON_CLK_GXBB tristate "GXBB and GXL SoC clock controllers support" depends on ARM64 - default y + default ARCH_MESON select COMMON_CLK_MESON_REGMAP select COMMON_CLK_MESON_DUALDIV select COMMON_CLK_MESON_VID_PLL_DIV @@ -86,7 +86,7 @@ config COMMON_CLK_GXBB config COMMON_CLK_AXG tristate "AXG SoC clock controllers support" depends on ARM64 - default y + default ARCH_MESON select COMMON_CLK_MESON_REGMAP select COMMON_CLK_MESON_DUALDIV select COMMON_CLK_MESON_MPLL @@ -136,7 +136,7 @@ config COMMON_CLK_A1_PERIPHERALS config COMMON_CLK_C3_PLL tristate "Amlogic C3 PLL clock controller" depends on ARM64 - default y + default ARCH_MESON select COMMON_CLK_MESON_REGMAP select COMMON_CLK_MESON_PLL select COMMON_CLK_MESON_CLKC_UTILS @@ -149,7 +149,7 @@ config COMMON_CLK_C3_PLL config COMMON_CLK_C3_PERIPHERALS tristate "Amlogic C3 peripherals clock controller" depends on ARM64 - default y + default ARCH_MESON select COMMON_CLK_MESON_REGMAP select COMMON_CLK_MESON_DUALDIV select COMMON_CLK_MESON_CLKC_UTILS @@ -163,7 +163,7 @@ config COMMON_CLK_C3_PERIPHERALS config COMMON_CLK_G12A tristate "G12 and SM1 SoC clock controllers support" depends on ARM64 - default y + default ARCH_MESON select COMMON_CLK_MESON_REGMAP select COMMON_CLK_MESON_DUALDIV select COMMON_CLK_MESON_MPLL @@ -181,7 +181,7 @@ config COMMON_CLK_G12A config COMMON_CLK_S4_PLL tristate "S4 SoC PLL clock controllers support" depends on ARM64 - default y + default ARCH_MESON select COMMON_CLK_MESON_CLKC_UTILS select COMMON_CLK_MESON_MPLL select COMMON_CLK_MESON_PLL @@ -194,7 +194,7 @@ config COMMON_CLK_S4_PLL config COMMON_CLK_S4_PERIPHERALS tristate "S4 SoC peripherals clock controllers support" depends on ARM64 - default y + default ARCH_MESON select COMMON_CLK_MESON_CLKC_UTILS select COMMON_CLK_MESON_REGMAP select COMMON_CLK_MESON_DUALDIV diff --git a/drivers/clk/meson/g12a.c b/drivers/clk/meson/g12a.c index ceabebb1863d..d9e546e006d7 100644 --- a/drivers/clk/meson/g12a.c +++ b/drivers/clk/meson/g12a.c @@ -4093,6 +4093,7 @@ static const struct clk_parent_data spicc_sclk_parent_data[] = { { .hw = &g12a_clk81.hw }, { .hw = &g12a_fclk_div4.hw }, { .hw = &g12a_fclk_div3.hw }, + { .hw = &g12a_fclk_div2.hw }, { .hw = &g12a_fclk_div5.hw }, { .hw = &g12a_fclk_div7.hw }, }; diff --git a/drivers/clk/qcom/apcs-sdx55.c b/drivers/clk/qcom/apcs-sdx55.c index 76ece6c4a969..3ba01622d8f0 100644 --- a/drivers/clk/qcom/apcs-sdx55.c +++ b/drivers/clk/qcom/apcs-sdx55.c @@ -111,7 +111,11 @@ static int qcom_apcs_sdx55_clk_probe(struct platform_device *pdev) * driver, there seems to be no better place to do this. So do it here! */ cpu_dev = get_cpu_device(0); - dev_pm_domain_attach(cpu_dev, true); + ret = dev_pm_domain_attach(cpu_dev, true); + if (ret) { + dev_err_probe(dev, ret, "can't get PM domain: %d\n", ret); + goto err; + } return 0; diff --git a/drivers/clk/qcom/camcc-sa8775p.c b/drivers/clk/qcom/camcc-sa8775p.c index 11bd2e234811..50e5a131261b 100644 --- a/drivers/clk/qcom/camcc-sa8775p.c +++ b/drivers/clk/qcom/camcc-sa8775p.c @@ -10,7 +10,7 @@ #include <linux/pm_runtime.h> #include <linux/regmap.h> -#include <dt-bindings/clock/qcom,sa8775p-camcc.h> +#include <dt-bindings/clock/qcom,qcs8300-camcc.h> #include "clk-alpha-pll.h" #include "clk-branch.h" @@ -1681,6 +1681,24 @@ static struct clk_branch cam_cc_sm_obs_clk = { }, }; +static struct clk_branch cam_cc_titan_top_accu_shift_clk = { + .halt_reg = 0x131f0, + .halt_check = BRANCH_HALT_VOTED, + .clkr = { + .enable_reg = 0x131f0, + .enable_mask = BIT(0), + .hw.init = &(const struct clk_init_data) { + .name = "cam_cc_titan_top_accu_shift_clk", + .parent_hws = (const struct clk_hw*[]) { + &cam_cc_xo_clk_src.clkr.hw, + }, + .num_parents = 1, + .flags = CLK_SET_RATE_PARENT, + .ops = &clk_branch2_ops, + }, + }, +}; + static struct gdsc cam_cc_titan_top_gdsc = { .gdscr = 0x131bc, .en_rest_wait_val = 0x2, @@ -1775,6 +1793,7 @@ static struct clk_regmap *cam_cc_sa8775p_clocks[] = { [CAM_CC_SLEEP_CLK_SRC] = &cam_cc_sleep_clk_src.clkr, [CAM_CC_SLOW_AHB_CLK_SRC] = &cam_cc_slow_ahb_clk_src.clkr, [CAM_CC_SM_OBS_CLK] = &cam_cc_sm_obs_clk.clkr, + [CAM_CC_TITAN_TOP_ACCU_SHIFT_CLK] = NULL, [CAM_CC_XO_CLK_SRC] = &cam_cc_xo_clk_src.clkr, [CAM_CC_QDSS_DEBUG_XO_CLK] = &cam_cc_qdss_debug_xo_clk.clkr, }; @@ -1811,6 +1830,7 @@ static const struct qcom_cc_desc cam_cc_sa8775p_desc = { }; static const struct of_device_id cam_cc_sa8775p_match_table[] = { + { .compatible = "qcom,qcs8300-camcc" }, { .compatible = "qcom,sa8775p-camcc" }, { } }; @@ -1841,10 +1861,83 @@ static int cam_cc_sa8775p_probe(struct platform_device *pdev) clk_lucid_evo_pll_configure(&cam_cc_pll4, regmap, &cam_cc_pll4_config); clk_lucid_evo_pll_configure(&cam_cc_pll5, regmap, &cam_cc_pll5_config); - /* Keep some clocks always enabled */ - qcom_branch_set_clk_en(regmap, 0x13194); /* CAM_CC_CAMNOC_XO_CLK */ - qcom_branch_set_clk_en(regmap, 0x131ec); /* CAM_CC_GDSC_CLK */ - qcom_branch_set_clk_en(regmap, 0x13208); /* CAM_CC_SLEEP_CLK */ + if (device_is_compatible(&pdev->dev, "qcom,qcs8300-camcc")) { + cam_cc_camnoc_axi_clk_src.cmd_rcgr = 0x13154; + cam_cc_camnoc_axi_clk.halt_reg = 0x1316c; + cam_cc_camnoc_axi_clk.clkr.enable_reg = 0x1316c; + cam_cc_camnoc_dcd_xo_clk.halt_reg = 0x13174; + cam_cc_camnoc_dcd_xo_clk.clkr.enable_reg = 0x13174; + + cam_cc_csi0phytimer_clk_src.cmd_rcgr = 0x15054; + cam_cc_csi1phytimer_clk_src.cmd_rcgr = 0x15078; + cam_cc_csi2phytimer_clk_src.cmd_rcgr = 0x15098; + cam_cc_csid_clk_src.cmd_rcgr = 0x13134; + + cam_cc_mclk0_clk_src.cmd_rcgr = 0x15000; + cam_cc_mclk1_clk_src.cmd_rcgr = 0x1501c; + cam_cc_mclk2_clk_src.cmd_rcgr = 0x15038; + + cam_cc_fast_ahb_clk_src.cmd_rcgr = 0x13104; + cam_cc_slow_ahb_clk_src.cmd_rcgr = 0x1311c; + cam_cc_xo_clk_src.cmd_rcgr = 0x131b8; + cam_cc_sleep_clk_src.cmd_rcgr = 0x131d4; + + cam_cc_core_ahb_clk.halt_reg = 0x131b4; + cam_cc_core_ahb_clk.clkr.enable_reg = 0x131b4; + + cam_cc_cpas_ahb_clk.halt_reg = 0x130f4; + cam_cc_cpas_ahb_clk.clkr.enable_reg = 0x130f4; + cam_cc_cpas_fast_ahb_clk.halt_reg = 0x130fc; + cam_cc_cpas_fast_ahb_clk.clkr.enable_reg = 0x130fc; + + cam_cc_csi0phytimer_clk.halt_reg = 0x1506c; + cam_cc_csi0phytimer_clk.clkr.enable_reg = 0x1506c; + cam_cc_csi1phytimer_clk.halt_reg = 0x15090; + cam_cc_csi1phytimer_clk.clkr.enable_reg = 0x15090; + cam_cc_csi2phytimer_clk.halt_reg = 0x150b0; + cam_cc_csi2phytimer_clk.clkr.enable_reg = 0x150b0; + cam_cc_csid_clk.halt_reg = 0x1314c; + cam_cc_csid_clk.clkr.enable_reg = 0x1314c; + cam_cc_csid_csiphy_rx_clk.halt_reg = 0x15074; + cam_cc_csid_csiphy_rx_clk.clkr.enable_reg = 0x15074; + cam_cc_csiphy0_clk.halt_reg = 0x15070; + cam_cc_csiphy0_clk.clkr.enable_reg = 0x15070; + cam_cc_csiphy1_clk.halt_reg = 0x15094; + cam_cc_csiphy1_clk.clkr.enable_reg = 0x15094; + cam_cc_csiphy2_clk.halt_reg = 0x150b4; + cam_cc_csiphy2_clk.clkr.enable_reg = 0x150b4; + + cam_cc_mclk0_clk.halt_reg = 0x15018; + cam_cc_mclk0_clk.clkr.enable_reg = 0x15018; + cam_cc_mclk1_clk.halt_reg = 0x15034; + cam_cc_mclk1_clk.clkr.enable_reg = 0x15034; + cam_cc_mclk2_clk.halt_reg = 0x15050; + cam_cc_mclk2_clk.clkr.enable_reg = 0x15050; + cam_cc_qdss_debug_xo_clk.halt_reg = 0x1319c; + cam_cc_qdss_debug_xo_clk.clkr.enable_reg = 0x1319c; + + cam_cc_titan_top_gdsc.gdscr = 0x131a0; + + cam_cc_sa8775p_clocks[CAM_CC_CCI_3_CLK] = NULL; + cam_cc_sa8775p_clocks[CAM_CC_CCI_3_CLK_SRC] = NULL; + cam_cc_sa8775p_clocks[CAM_CC_CSI3PHYTIMER_CLK] = NULL; + cam_cc_sa8775p_clocks[CAM_CC_CSI3PHYTIMER_CLK_SRC] = NULL; + cam_cc_sa8775p_clocks[CAM_CC_CSIPHY3_CLK] = NULL; + cam_cc_sa8775p_clocks[CAM_CC_MCLK3_CLK] = NULL; + cam_cc_sa8775p_clocks[CAM_CC_MCLK3_CLK_SRC] = NULL; + cam_cc_sa8775p_clocks[CAM_CC_TITAN_TOP_ACCU_SHIFT_CLK] = + &cam_cc_titan_top_accu_shift_clk.clkr; + + /* Keep some clocks always enabled */ + qcom_branch_set_clk_en(regmap, 0x13178); /* CAM_CC_CAMNOC_XO_CLK */ + qcom_branch_set_clk_en(regmap, 0x131d0); /* CAM_CC_GDSC_CLK */ + qcom_branch_set_clk_en(regmap, 0x131ec); /* CAM_CC_SLEEP_CLK */ + } else { + /* Keep some clocks always enabled */ + qcom_branch_set_clk_en(regmap, 0x13194); /* CAM_CC_CAMNOC_XO_CLK */ + qcom_branch_set_clk_en(regmap, 0x131ec); /* CAM_CC_GDSC_CLK */ + qcom_branch_set_clk_en(regmap, 0x13208); /* CAM_CC_SLEEP_CLK */ + } ret = qcom_cc_really_probe(&pdev->dev, &cam_cc_sa8775p_desc, regmap); diff --git a/drivers/clk/qcom/camcc-sm6350.c b/drivers/clk/qcom/camcc-sm6350.c index 1871970fb046..8aac97d29ce3 100644 --- a/drivers/clk/qcom/camcc-sm6350.c +++ b/drivers/clk/qcom/camcc-sm6350.c @@ -1695,6 +1695,9 @@ static struct clk_branch camcc_sys_tmr_clk = { static struct gdsc bps_gdsc = { .gdscr = 0x6004, + .en_rest_wait_val = 0x2, + .en_few_wait_val = 0x2, + .clk_dis_wait_val = 0xf, .pd = { .name = "bps_gdsc", }, @@ -1704,6 +1707,9 @@ static struct gdsc bps_gdsc = { static struct gdsc ipe_0_gdsc = { .gdscr = 0x7004, + .en_rest_wait_val = 0x2, + .en_few_wait_val = 0x2, + .clk_dis_wait_val = 0xf, .pd = { .name = "ipe_0_gdsc", }, @@ -1713,6 +1719,9 @@ static struct gdsc ipe_0_gdsc = { static struct gdsc ife_0_gdsc = { .gdscr = 0x9004, + .en_rest_wait_val = 0x2, + .en_few_wait_val = 0x2, + .clk_dis_wait_val = 0xf, .pd = { .name = "ife_0_gdsc", }, @@ -1721,6 +1730,9 @@ static struct gdsc ife_0_gdsc = { static struct gdsc ife_1_gdsc = { .gdscr = 0xa004, + .en_rest_wait_val = 0x2, + .en_few_wait_val = 0x2, + .clk_dis_wait_val = 0xf, .pd = { .name = "ife_1_gdsc", }, @@ -1729,6 +1741,9 @@ static struct gdsc ife_1_gdsc = { static struct gdsc ife_2_gdsc = { .gdscr = 0xb004, + .en_rest_wait_val = 0x2, + .en_few_wait_val = 0x2, + .clk_dis_wait_val = 0xf, .pd = { .name = "ife_2_gdsc", }, @@ -1737,6 +1752,9 @@ static struct gdsc ife_2_gdsc = { static struct gdsc titan_top_gdsc = { .gdscr = 0x14004, + .en_rest_wait_val = 0x2, + .en_few_wait_val = 0x2, + .clk_dis_wait_val = 0xf, .pd = { .name = "titan_top_gdsc", }, diff --git a/drivers/clk/qcom/clk-rpmh.c b/drivers/clk/qcom/clk-rpmh.c index c7675930fde1..00fb3e53a388 100644 --- a/drivers/clk/qcom/clk-rpmh.c +++ b/drivers/clk/qcom/clk-rpmh.c @@ -66,6 +66,8 @@ struct clk_rpmh { struct clk_rpmh_desc { struct clk_hw **clks; size_t num_clks; + /* RPMh clock clkaN are optional for this platform */ + bool clka_optional; }; static DEFINE_MUTEX(rpmh_clk_lock); @@ -648,6 +650,7 @@ static struct clk_hw *sm8550_rpmh_clocks[] = { static const struct clk_rpmh_desc clk_rpmh_sm8550 = { .clks = sm8550_rpmh_clocks, .num_clks = ARRAY_SIZE(sm8550_rpmh_clocks), + .clka_optional = true, }; static struct clk_hw *sm8650_rpmh_clocks[] = { @@ -679,6 +682,7 @@ static struct clk_hw *sm8650_rpmh_clocks[] = { static const struct clk_rpmh_desc clk_rpmh_sm8650 = { .clks = sm8650_rpmh_clocks, .num_clks = ARRAY_SIZE(sm8650_rpmh_clocks), + .clka_optional = true, }; static struct clk_hw *sc7280_rpmh_clocks[] = { @@ -847,6 +851,7 @@ static struct clk_hw *sm8750_rpmh_clocks[] = { static const struct clk_rpmh_desc clk_rpmh_sm8750 = { .clks = sm8750_rpmh_clocks, .num_clks = ARRAY_SIZE(sm8750_rpmh_clocks), + .clka_optional = true, }; static struct clk_hw *of_clk_rpmh_hw_get(struct of_phandle_args *clkspec, @@ -890,6 +895,12 @@ static int clk_rpmh_probe(struct platform_device *pdev) rpmh_clk = to_clk_rpmh(hw_clks[i]); res_addr = cmd_db_read_addr(rpmh_clk->res_name); if (!res_addr) { + hw_clks[i] = NULL; + + if (desc->clka_optional && + !strncmp(rpmh_clk->res_name, "clka", sizeof("clka") - 1)) + continue; + dev_err(&pdev->dev, "missing RPMh resource address for %s\n", rpmh_clk->res_name); return -ENODEV; diff --git a/drivers/clk/qcom/dispcc-sm6350.c b/drivers/clk/qcom/dispcc-sm6350.c index e703ecf00e44..b0bd163a449c 100644 --- a/drivers/clk/qcom/dispcc-sm6350.c +++ b/drivers/clk/qcom/dispcc-sm6350.c @@ -681,6 +681,9 @@ static struct clk_branch disp_cc_xo_clk = { static struct gdsc mdss_gdsc = { .gdscr = 0x1004, + .en_rest_wait_val = 0x2, + .en_few_wait_val = 0x2, + .clk_dis_wait_val = 0xf, .pd = { .name = "mdss_gdsc", }, diff --git a/drivers/clk/qcom/gcc-msm8939.c b/drivers/clk/qcom/gcc-msm8939.c index 7431c9a65044..45193b3d714b 100644 --- a/drivers/clk/qcom/gcc-msm8939.c +++ b/drivers/clk/qcom/gcc-msm8939.c @@ -432,7 +432,7 @@ static const struct parent_map gcc_xo_gpll0_gpll1a_gpll6_sleep_map[] = { { P_XO, 0 }, { P_GPLL0, 1 }, { P_GPLL1_AUX, 2 }, - { P_GPLL6, 2 }, + { P_GPLL6, 3 }, { P_SLEEP_CLK, 6 }, }; @@ -1113,7 +1113,7 @@ static struct clk_rcg2 jpeg0_clk_src = { }; static const struct freq_tbl ftbl_gcc_camss_mclk0_1_clk[] = { - F(24000000, P_GPLL0, 1, 1, 45), + F(24000000, P_GPLL6, 1, 1, 45), F(66670000, P_GPLL0, 12, 0, 0), { } }; diff --git a/drivers/clk/qcom/gcc-sm6350.c b/drivers/clk/qcom/gcc-sm6350.c index 74346dc02606..a4d6dff9d0f7 100644 --- a/drivers/clk/qcom/gcc-sm6350.c +++ b/drivers/clk/qcom/gcc-sm6350.c @@ -2320,6 +2320,9 @@ static struct clk_branch gcc_video_xo_clk = { static struct gdsc usb30_prim_gdsc = { .gdscr = 0x1a004, + .en_rest_wait_val = 0x2, + .en_few_wait_val = 0x2, + .clk_dis_wait_val = 0xf, .pd = { .name = "usb30_prim_gdsc", }, @@ -2328,6 +2331,9 @@ static struct gdsc usb30_prim_gdsc = { static struct gdsc ufs_phy_gdsc = { .gdscr = 0x3a004, + .en_rest_wait_val = 0x2, + .en_few_wait_val = 0x2, + .clk_dis_wait_val = 0xf, .pd = { .name = "ufs_phy_gdsc", }, diff --git a/drivers/clk/qcom/gcc-sm8650.c b/drivers/clk/qcom/gcc-sm8650.c index fa1672c4e7d8..24f98062b9dd 100644 --- a/drivers/clk/qcom/gcc-sm8650.c +++ b/drivers/clk/qcom/gcc-sm8650.c @@ -3817,7 +3817,9 @@ static int gcc_sm8650_probe(struct platform_device *pdev) qcom_branch_set_clk_en(regmap, 0x32004); /* GCC_VIDEO_AHB_CLK */ qcom_branch_set_clk_en(regmap, 0x32030); /* GCC_VIDEO_XO_CLK */ + /* FORCE_MEM_CORE_ON for ufs phy ice core and gcc ufs phy axi clocks */ qcom_branch_set_force_mem_core(regmap, gcc_ufs_phy_ice_core_clk, true); + qcom_branch_set_force_mem_core(regmap, gcc_ufs_phy_axi_clk, true); /* Clear GDSC_SLEEP_ENA_VOTE to stop votes being auto-removed in sleep. */ regmap_write(regmap, 0x52150, 0x0); diff --git a/drivers/clk/qcom/gcc-sm8750.c b/drivers/clk/qcom/gcc-sm8750.c index b36d70976095..8092dd6b37b5 100644 --- a/drivers/clk/qcom/gcc-sm8750.c +++ b/drivers/clk/qcom/gcc-sm8750.c @@ -3244,8 +3244,9 @@ static int gcc_sm8750_probe(struct platform_device *pdev) regmap_update_bits(regmap, 0x52010, BIT(20), BIT(20)); regmap_update_bits(regmap, 0x52010, BIT(21), BIT(21)); - /* FORCE_MEM_CORE_ON for ufs phy ice core clocks */ + /* FORCE_MEM_CORE_ON for ufs phy ice core and gcc ufs phy axi clocks */ qcom_branch_set_force_mem_core(regmap, gcc_ufs_phy_ice_core_clk, true); + qcom_branch_set_force_mem_core(regmap, gcc_ufs_phy_axi_clk, true); return qcom_cc_really_probe(&pdev->dev, &gcc_sm8750_desc, regmap); } diff --git a/drivers/clk/qcom/gcc-x1e80100.c b/drivers/clk/qcom/gcc-x1e80100.c index 009f39139b64..3e44757e25d3 100644 --- a/drivers/clk/qcom/gcc-x1e80100.c +++ b/drivers/clk/qcom/gcc-x1e80100.c @@ -6753,6 +6753,10 @@ static int gcc_x1e80100_probe(struct platform_device *pdev) /* Clear GDSC_SLEEP_ENA_VOTE to stop votes being auto-removed in sleep. */ regmap_write(regmap, 0x52224, 0x0); + /* FORCE_MEM_CORE_ON for ufs phy ice core and gcc ufs phy axi clocks */ + qcom_branch_set_force_mem_core(regmap, gcc_ufs_phy_ice_core_clk, true); + qcom_branch_set_force_mem_core(regmap, gcc_ufs_phy_axi_clk, true); + return qcom_cc_really_probe(&pdev->dev, &gcc_x1e80100_desc, regmap); } diff --git a/drivers/clk/qcom/gpucc-sm6350.c b/drivers/clk/qcom/gpucc-sm6350.c index 35ed0500bc59..ee89c42413f8 100644 --- a/drivers/clk/qcom/gpucc-sm6350.c +++ b/drivers/clk/qcom/gpucc-sm6350.c @@ -413,6 +413,9 @@ static struct clk_branch gpu_cc_gx_vsense_clk = { static struct gdsc gpu_cx_gdsc = { .gdscr = 0x106c, .gds_hw_ctrl = 0x1540, + .en_rest_wait_val = 0x2, + .en_few_wait_val = 0x2, + .clk_dis_wait_val = 0x8, .pd = { .name = "gpu_cx_gdsc", }, @@ -423,6 +426,9 @@ static struct gdsc gpu_cx_gdsc = { static struct gdsc gpu_gx_gdsc = { .gdscr = 0x100c, .clamp_io_ctrl = 0x1508, + .en_rest_wait_val = 0x2, + .en_few_wait_val = 0x2, + .clk_dis_wait_val = 0x2, .pd = { .name = "gpu_gx_gdsc", .power_on = gdsc_gx_do_nothing_enable, diff --git a/drivers/clk/rockchip/Makefile b/drivers/clk/rockchip/Makefile index e8ece20aebfd..c281a9738d9f 100644 --- a/drivers/clk/rockchip/Makefile +++ b/drivers/clk/rockchip/Makefile @@ -8,6 +8,7 @@ obj-$(CONFIG_COMMON_CLK_ROCKCHIP) += clk-rockchip.o clk-rockchip-y += clk.o clk-rockchip-y += clk-pll.o clk-rockchip-y += clk-cpu.o +clk-rockchip-y += clk-gate-grf.o clk-rockchip-y += clk-half-divider.o clk-rockchip-y += clk-inverter.o clk-rockchip-y += clk-mmc-phase.o diff --git a/drivers/clk/rockchip/clk-gate-grf.c b/drivers/clk/rockchip/clk-gate-grf.c new file mode 100644 index 000000000000..8122f471f391 --- /dev/null +++ b/drivers/clk/rockchip/clk-gate-grf.c @@ -0,0 +1,105 @@ +// SPDX-License-Identifier: GPL-2.0-or-later +/* + * Copyright (c) 2025 Collabora Ltd. + * Author: Nicolas Frattaroli <nicolas.frattaroli@collabora.com> + * + * Certain clocks on Rockchip are "gated" behind an additional register bit + * write in a GRF register, such as the SAI MCLKs on RK3576. This code + * implements a clock driver for these types of gates, based on regmaps. + */ + +#include <linux/clk.h> +#include <linux/clk-provider.h> +#include <linux/regmap.h> +#include <linux/slab.h> +#include "clk.h" + +struct rockchip_gate_grf { + struct clk_hw hw; + struct regmap *regmap; + unsigned int reg; + unsigned int shift; + u8 flags; +}; + +#define to_gate_grf(_hw) container_of(_hw, struct rockchip_gate_grf, hw) + +static int rockchip_gate_grf_enable(struct clk_hw *hw) +{ + struct rockchip_gate_grf *gate = to_gate_grf(hw); + u32 val = !(gate->flags & CLK_GATE_SET_TO_DISABLE) ? BIT(gate->shift) : 0; + u32 hiword = ((gate->flags & CLK_GATE_HIWORD_MASK) ? 1 : 0) << (gate->shift + 16); + int ret; + + ret = regmap_update_bits(gate->regmap, gate->reg, + hiword | BIT(gate->shift), hiword | val); + + return ret; +} + +static void rockchip_gate_grf_disable(struct clk_hw *hw) +{ + struct rockchip_gate_grf *gate = to_gate_grf(hw); + u32 val = !(gate->flags & CLK_GATE_SET_TO_DISABLE) ? 0 : BIT(gate->shift); + u32 hiword = ((gate->flags & CLK_GATE_HIWORD_MASK) ? 1 : 0) << (gate->shift + 16); + + regmap_update_bits(gate->regmap, gate->reg, + hiword | BIT(gate->shift), hiword | val); +} + +static int rockchip_gate_grf_is_enabled(struct clk_hw *hw) +{ + struct rockchip_gate_grf *gate = to_gate_grf(hw); + bool invert = !!(gate->flags & CLK_GATE_SET_TO_DISABLE); + int ret; + + ret = regmap_test_bits(gate->regmap, gate->reg, BIT(gate->shift)); + if (ret < 0) + ret = 0; + + return invert ? 1 - ret : ret; + +} + +static const struct clk_ops rockchip_gate_grf_ops = { + .enable = rockchip_gate_grf_enable, + .disable = rockchip_gate_grf_disable, + .is_enabled = rockchip_gate_grf_is_enabled, +}; + +struct clk *rockchip_clk_register_gate_grf(const char *name, + const char *parent_name, unsigned long flags, + struct regmap *regmap, unsigned int reg, unsigned int shift, + u8 gate_flags) +{ + struct rockchip_gate_grf *gate; + struct clk_init_data init; + struct clk *clk; + + if (IS_ERR(regmap)) { + pr_err("%s: regmap not available\n", __func__); + return ERR_PTR(-EOPNOTSUPP); + } + + gate = kzalloc(sizeof(*gate), GFP_KERNEL); + if (!gate) + return ERR_PTR(-ENOMEM); + + init.name = name; + init.flags = flags; + init.num_parents = parent_name ? 1 : 0; + init.parent_names = parent_name ? &parent_name : NULL; + init.ops = &rockchip_gate_grf_ops; + + gate->hw.init = &init; + gate->regmap = regmap; + gate->reg = reg; + gate->shift = shift; + gate->flags = gate_flags; + + clk = clk_register(NULL, &gate->hw); + if (IS_ERR(clk)) + kfree(gate); + + return clk; +} diff --git a/drivers/clk/rockchip/clk-mmc-phase.c b/drivers/clk/rockchip/clk-mmc-phase.c index 91012078681b..b3ed8e7523e5 100644 --- a/drivers/clk/rockchip/clk-mmc-phase.c +++ b/drivers/clk/rockchip/clk-mmc-phase.c @@ -9,11 +9,14 @@ #include <linux/clk-provider.h> #include <linux/io.h> #include <linux/kernel.h> +#include <linux/regmap.h> #include "clk.h" struct rockchip_mmc_clock { struct clk_hw hw; void __iomem *reg; + struct regmap *grf; + int grf_reg; int shift; int cached_phase; struct notifier_block clk_rate_change_nb; @@ -54,7 +57,12 @@ static int rockchip_mmc_get_phase(struct clk_hw *hw) if (!rate) return 0; - raw_value = readl(mmc_clock->reg) >> (mmc_clock->shift); + if (mmc_clock->grf) + regmap_read(mmc_clock->grf, mmc_clock->grf_reg, &raw_value); + else + raw_value = readl(mmc_clock->reg); + + raw_value >>= mmc_clock->shift; degrees = (raw_value & ROCKCHIP_MMC_DEGREE_MASK) * 90; @@ -134,8 +142,12 @@ static int rockchip_mmc_set_phase(struct clk_hw *hw, int degrees) raw_value = delay_num ? ROCKCHIP_MMC_DELAY_SEL : 0; raw_value |= delay_num << ROCKCHIP_MMC_DELAYNUM_OFFSET; raw_value |= nineties; - writel(HIWORD_UPDATE(raw_value, 0x07ff, mmc_clock->shift), - mmc_clock->reg); + raw_value = HIWORD_UPDATE(raw_value, 0x07ff, mmc_clock->shift); + + if (mmc_clock->grf) + regmap_write(mmc_clock->grf, mmc_clock->grf_reg, raw_value); + else + writel(raw_value, mmc_clock->reg); pr_debug("%s->set_phase(%d) delay_nums=%u reg[0x%p]=0x%03x actual_degrees=%d\n", clk_hw_get_name(hw), degrees, delay_num, @@ -189,7 +201,9 @@ static int rockchip_mmc_clk_rate_notify(struct notifier_block *nb, struct clk *rockchip_clk_register_mmc(const char *name, const char *const *parent_names, u8 num_parents, - void __iomem *reg, int shift) + void __iomem *reg, + struct regmap *grf, int grf_reg, + int shift) { struct clk_init_data init; struct rockchip_mmc_clock *mmc_clock; @@ -208,6 +222,8 @@ struct clk *rockchip_clk_register_mmc(const char *name, mmc_clock->hw.init = &init; mmc_clock->reg = reg; + mmc_clock->grf = grf; + mmc_clock->grf_reg = grf_reg; mmc_clock->shift = shift; clk = clk_register(NULL, &mmc_clock->hw); diff --git a/drivers/clk/rockchip/clk-pll.c b/drivers/clk/rockchip/clk-pll.c index 2c2abb3b4210..af74439a7457 100644 --- a/drivers/clk/rockchip/clk-pll.c +++ b/drivers/clk/rockchip/clk-pll.c @@ -1027,16 +1027,6 @@ static int rockchip_rk3588_pll_is_enabled(struct clk_hw *hw) return !(pllcon & RK3588_PLLCON1_PWRDOWN); } -static int rockchip_rk3588_pll_init(struct clk_hw *hw) -{ - struct rockchip_clk_pll *pll = to_rockchip_clk_pll(hw); - - if (!(pll->flags & ROCKCHIP_PLL_SYNC_RATE)) - return 0; - - return 0; -} - static const struct clk_ops rockchip_rk3588_pll_clk_norate_ops = { .recalc_rate = rockchip_rk3588_pll_recalc_rate, .enable = rockchip_rk3588_pll_enable, @@ -1051,7 +1041,6 @@ static const struct clk_ops rockchip_rk3588_pll_clk_ops = { .enable = rockchip_rk3588_pll_enable, .disable = rockchip_rk3588_pll_disable, .is_enabled = rockchip_rk3588_pll_is_enabled, - .init = rockchip_rk3588_pll_init, }; /* diff --git a/drivers/clk/rockchip/clk-rk3036.c b/drivers/clk/rockchip/clk-rk3036.c index d341ce0708aa..df9330958c83 100644 --- a/drivers/clk/rockchip/clk-rk3036.c +++ b/drivers/clk/rockchip/clk-rk3036.c @@ -123,6 +123,7 @@ PNAME(mux_timer_p) = { "xin24m", "pclk_peri_src" }; PNAME(mux_pll_src_apll_dpll_gpll_usb480m_p) = { "apll", "dpll", "gpll", "usb480m" }; PNAME(mux_pll_src_dmyapll_dpll_gpll_xin24_p) = { "dummy_apll", "dpll", "gpll", "xin24m" }; +PNAME(mux_usb480m_p) = { "usb480m_phy", "xin24m" }; PNAME(mux_mmc_src_p) = { "apll", "dpll", "gpll", "xin24m" }; PNAME(mux_i2s_pre_p) = { "i2s_src", "i2s_frac", "ext_i2s", "xin12m" }; PNAME(mux_i2s_clkout_p) = { "i2s_pre", "xin12m" }; @@ -423,6 +424,9 @@ static struct rockchip_clk_branch rk3036_clk_branches[] __initdata = { GATE(PCLK_GPIO0, "pclk_gpio0", "pclk_peri", 0, RK2928_CLKGATE_CON(8), 9, GFLAGS), GATE(PCLK_GPIO1, "pclk_gpio1", "pclk_peri", 0, RK2928_CLKGATE_CON(8), 10, GFLAGS), GATE(PCLK_GPIO2, "pclk_gpio2", "pclk_peri", 0, RK2928_CLKGATE_CON(8), 11, GFLAGS), + + MUX(SCLK_USB480M, "usb480m", mux_usb480m_p, CLK_SET_RATE_PARENT, + RK2928_MISC_CON, 15, 1, MFLAGS), }; static const char *const rk3036_critical_clocks[] __initconst = { @@ -431,6 +435,7 @@ static const char *const rk3036_critical_clocks[] __initconst = { "hclk_peri", "pclk_peri", "pclk_ddrupctl", + "ddrphy", }; static void __init rk3036_clk_init(struct device_node *np) @@ -438,7 +443,6 @@ static void __init rk3036_clk_init(struct device_node *np) struct rockchip_clk_provider *ctx; unsigned long clk_nr_clks; void __iomem *reg_base; - struct clk *clk; reg_base = of_iomap(np, 0); if (!reg_base) { @@ -462,11 +466,6 @@ static void __init rk3036_clk_init(struct device_node *np) return; } - clk = clk_register_fixed_factor(NULL, "usb480m", "xin24m", 0, 20, 1); - if (IS_ERR(clk)) - pr_warn("%s: could not register clock usb480m: %ld\n", - __func__, PTR_ERR(clk)); - rockchip_clk_register_plls(ctx, rk3036_pll_clks, ARRAY_SIZE(rk3036_pll_clks), RK3036_GRF_SOC_STATUS0); diff --git a/drivers/clk/rockchip/clk-rk3288.c b/drivers/clk/rockchip/clk-rk3288.c index 90d329216064..0a1e017df7c6 100644 --- a/drivers/clk/rockchip/clk-rk3288.c +++ b/drivers/clk/rockchip/clk-rk3288.c @@ -418,7 +418,7 @@ static struct rockchip_clk_branch rk3288_clk_branches[] __initdata = { RK3288_CLKSEL_CON(32), 14, 2, MFLAGS, 8, 5, DFLAGS, RK3288_CLKGATE_CON(3), 11, GFLAGS), MUXGRF(0, "aclk_vcodec_pre", mux_aclk_vcodec_pre_p, CLK_SET_RATE_PARENT, - RK3288_GRF_SOC_CON(0), 7, 1, MFLAGS), + RK3288_GRF_SOC_CON(0), 7, 1, MFLAGS, grf_type_sys), GATE(ACLK_VCODEC, "aclk_vcodec", "aclk_vcodec_pre", 0, RK3288_CLKGATE_CON(9), 0, GFLAGS), diff --git a/drivers/clk/rockchip/clk-rk3328.c b/drivers/clk/rockchip/clk-rk3328.c index cf60fcf2fa5c..cd5f65b6cdf5 100644 --- a/drivers/clk/rockchip/clk-rk3328.c +++ b/drivers/clk/rockchip/clk-rk3328.c @@ -677,9 +677,9 @@ static struct rockchip_clk_branch rk3328_clk_branches[] __initdata = { RK3328_CLKSEL_CON(27), 15, 1, MFLAGS, 8, 5, DFLAGS, RK3328_CLKGATE_CON(3), 5, GFLAGS), MUXGRF(SCLK_MAC2IO, "clk_mac2io", mux_mac2io_src_p, CLK_SET_RATE_NO_REPARENT, - RK3328_GRF_MAC_CON1, 10, 1, MFLAGS), + RK3328_GRF_MAC_CON1, 10, 1, MFLAGS, grf_type_sys), MUXGRF(SCLK_MAC2IO_EXT, "clk_mac2io_ext", mux_mac2io_ext_p, CLK_SET_RATE_NO_REPARENT, - RK3328_GRF_SOC_CON4, 14, 1, MFLAGS), + RK3328_GRF_SOC_CON4, 14, 1, MFLAGS, grf_type_sys), COMPOSITE(SCLK_MAC2PHY_SRC, "clk_mac2phy_src", mux_2plls_p, 0, RK3328_CLKSEL_CON(26), 7, 1, MFLAGS, 0, 5, DFLAGS, @@ -692,7 +692,7 @@ static struct rockchip_clk_branch rk3328_clk_branches[] __initdata = { RK3328_CLKSEL_CON(26), 8, 2, DFLAGS, RK3328_CLKGATE_CON(9), 2, GFLAGS), MUXGRF(SCLK_MAC2PHY, "clk_mac2phy", mux_mac2phy_src_p, CLK_SET_RATE_NO_REPARENT, - RK3328_GRF_MAC_CON2, 10, 1, MFLAGS), + RK3328_GRF_MAC_CON2, 10, 1, MFLAGS, grf_type_sys), FACTOR(0, "xin12m", "xin24m", 0, 1, 2), diff --git a/drivers/clk/rockchip/clk-rk3528.c b/drivers/clk/rockchip/clk-rk3528.c index b8b577b902a0..a5ff64b93f8f 100644 --- a/drivers/clk/rockchip/clk-rk3528.c +++ b/drivers/clk/rockchip/clk-rk3528.c @@ -10,6 +10,9 @@ #include <linux/of.h> #include <linux/of_device.h> #include <linux/platform_device.h> +#include <linux/mfd/syscon.h> +#include <linux/minmax.h> +#include <linux/slab.h> #include <dt-bindings/clock/rockchip,rk3528-cru.h> @@ -1061,23 +1064,65 @@ static struct rockchip_clk_branch rk3528_clk_branches[] __initdata = { 0, 1, 1), }; +static struct rockchip_clk_branch rk3528_vo_clk_branches[] __initdata = { + MMC_GRF(SCLK_SDMMC_DRV, "sdmmc_drv", "cclk_src_sdmmc0", + RK3528_SDMMC_CON(0), 1, grf_type_vo), + MMC_GRF(SCLK_SDMMC_SAMPLE, "sdmmc_sample", "cclk_src_sdmmc0", + RK3528_SDMMC_CON(1), 1, grf_type_vo), +}; + +static struct rockchip_clk_branch rk3528_vpu_clk_branches[] __initdata = { + MMC_GRF(SCLK_SDIO0_DRV, "sdio0_drv", "cclk_src_sdio0", + RK3528_SDIO0_CON(0), 1, grf_type_vpu), + MMC_GRF(SCLK_SDIO0_SAMPLE, "sdio0_sample", "cclk_src_sdio0", + RK3528_SDIO0_CON(1), 1, grf_type_vpu), + MMC_GRF(SCLK_SDIO1_DRV, "sdio1_drv", "cclk_src_sdio1", + RK3528_SDIO1_CON(0), 1, grf_type_vpu), + MMC_GRF(SCLK_SDIO1_SAMPLE, "sdio1_sample", "cclk_src_sdio1", + RK3528_SDIO1_CON(1), 1, grf_type_vpu), +}; + static int __init clk_rk3528_probe(struct platform_device *pdev) { - struct rockchip_clk_provider *ctx; + unsigned long nr_vpu_branches = ARRAY_SIZE(rk3528_vpu_clk_branches); + unsigned long nr_vo_branches = ARRAY_SIZE(rk3528_vo_clk_branches); + unsigned long nr_branches = ARRAY_SIZE(rk3528_clk_branches); + unsigned long nr_clks, nr_vo_clks, nr_vpu_clks; + struct rockchip_aux_grf *vo_grf_e, *vpu_grf_e; + struct regmap *vo_grf, *vpu_grf; struct device *dev = &pdev->dev; struct device_node *np = dev->of_node; - unsigned long nr_branches = ARRAY_SIZE(rk3528_clk_branches); - unsigned long nr_clks; + struct rockchip_clk_provider *ctx; void __iomem *reg_base; - nr_clks = rockchip_clk_find_max_clk_id(rk3528_clk_branches, - nr_branches) + 1; - reg_base = devm_platform_ioremap_resource(pdev, 0); if (IS_ERR(reg_base)) return dev_err_probe(dev, PTR_ERR(reg_base), "could not map cru region"); + nr_clks = rockchip_clk_find_max_clk_id(rk3528_clk_branches, + nr_branches) + 1; + + vo_grf = syscon_regmap_lookup_by_compatible("rockchip,rk3528-vo-grf"); + if (!IS_ERR(vo_grf)) { + nr_vo_clks = rockchip_clk_find_max_clk_id(rk3528_vo_clk_branches, + nr_vo_branches) + 1; + nr_clks = max(nr_clks, nr_vo_clks); + } else if (PTR_ERR(vo_grf) != -ENODEV) { + return dev_err_probe(dev, PTR_ERR(vo_grf), + "failed to look up VO GRF\n"); + } + + vpu_grf = syscon_regmap_lookup_by_compatible("rockchip,rk3528-vpu-grf"); + if (!IS_ERR(vpu_grf)) { + nr_vpu_clks = rockchip_clk_find_max_clk_id(rk3528_vpu_clk_branches, + nr_vpu_branches) + 1; + nr_clks = max(nr_clks, nr_vpu_clks); + } else if (PTR_ERR(vpu_grf) != -ENODEV) { + return dev_err_probe(dev, PTR_ERR(vpu_grf), + "failed to look up VPU GRF\n"); + } + ctx = rockchip_clk_init(np, reg_base, nr_clks); if (IS_ERR(ctx)) return dev_err_probe(dev, PTR_ERR(ctx), @@ -1092,6 +1137,32 @@ static int __init clk_rk3528_probe(struct platform_device *pdev) ARRAY_SIZE(rk3528_cpuclk_rates)); rockchip_clk_register_branches(ctx, rk3528_clk_branches, nr_branches); + if (!IS_ERR(vo_grf)) { + vo_grf_e = devm_kzalloc(dev, sizeof(*vo_grf_e), GFP_KERNEL); + if (!vo_grf_e) + return -ENOMEM; + + vo_grf_e->grf = vo_grf; + vo_grf_e->type = grf_type_vo; + hash_add(ctx->aux_grf_table, &vo_grf_e->node, grf_type_vo); + + rockchip_clk_register_branches(ctx, rk3528_vo_clk_branches, + nr_vo_branches); + } + + if (!IS_ERR(vpu_grf)) { + vpu_grf_e = devm_kzalloc(dev, sizeof(*vpu_grf_e), GFP_KERNEL); + if (!vpu_grf_e) + return -ENOMEM; + + vpu_grf_e->grf = vpu_grf; + vpu_grf_e->type = grf_type_vpu; + hash_add(ctx->aux_grf_table, &vpu_grf_e->node, grf_type_vpu); + + rockchip_clk_register_branches(ctx, rk3528_vpu_clk_branches, + nr_vpu_branches); + } + rk3528_rst_init(np, reg_base); rockchip_register_restart_notifier(ctx, RK3528_GLB_SRST_FST, NULL); diff --git a/drivers/clk/rockchip/clk-rk3568.c b/drivers/clk/rockchip/clk-rk3568.c index 7d9279291e76..d48ab9d6c064 100644 --- a/drivers/clk/rockchip/clk-rk3568.c +++ b/drivers/clk/rockchip/clk-rk3568.c @@ -89,6 +89,7 @@ static struct rockchip_pll_rate_table rk3568_pll_rates[] = { RK3036_PLL_RATE(96000000, 1, 96, 6, 4, 1, 0), RK3036_PLL_RATE(78750000, 4, 315, 6, 4, 1, 0), RK3036_PLL_RATE(74250000, 2, 99, 4, 4, 1, 0), + RK3036_PLL_RATE(33300000, 4, 111, 5, 4, 1, 0), { /* sentinel */ }, }; @@ -590,7 +591,7 @@ static struct rockchip_clk_branch rk3568_clk_branches[] __initdata = { RK3568_CLKSEL_CON(9), 6, 2, MFLAGS, 0, 5, DFLAGS, RK3568_CLKGATE_CON(4), 0, GFLAGS), MUXGRF(CLK_DDR1X, "clk_ddr1x", clk_ddr1x_p, CLK_SET_RATE_PARENT, - RK3568_CLKSEL_CON(9), 15, 1, MFLAGS), + RK3568_CLKSEL_CON(9), 15, 1, MFLAGS, grf_type_sys), COMPOSITE_NOMUX(CLK_MSCH, "clk_msch", "clk_ddr1x", CLK_IGNORE_UNUSED, RK3568_CLKSEL_CON(10), 0, 2, DFLAGS, diff --git a/drivers/clk/rockchip/clk-rk3576.c b/drivers/clk/rockchip/clk-rk3576.c index 595e010341f7..1f4547af5acf 100644 --- a/drivers/clk/rockchip/clk-rk3576.c +++ b/drivers/clk/rockchip/clk-rk3576.c @@ -10,11 +10,13 @@ #include <linux/platform_device.h> #include <linux/syscore_ops.h> #include <linux/mfd/syscon.h> +#include <linux/slab.h> #include <dt-bindings/clock/rockchip,rk3576-cru.h> #include "clk.h" #define RK3576_GRF_SOC_STATUS0 0x600 #define RK3576_PMU0_GRF_OSC_CON6 0x18 +#define RK3576_VCCIO_IOC_MISC_CON0 0x6400 enum rk3576_plls { bpll, lpll, vpll, aupll, cpll, gpll, ppll, @@ -1479,6 +1481,14 @@ static struct rockchip_clk_branch rk3576_clk_branches[] __initdata = { RK3576_CLKGATE_CON(10), 0, GFLAGS), GATE(CLK_SAI0_MCLKOUT, "clk_sai0_mclkout", "mclk_sai0_8ch", 0, RK3576_CLKGATE_CON(10), 1, GFLAGS), + GATE_GRF(CLK_SAI0_MCLKOUT_TO_IO, "mclk_sai0_to_io", "clk_sai0_mclkout", + 0, RK3576_VCCIO_IOC_MISC_CON0, 0, GFLAGS, grf_type_ioc), + GATE_GRF(CLK_SAI1_MCLKOUT_TO_IO, "mclk_sai1_to_io", "clk_sai1_mclkout", + 0, RK3576_VCCIO_IOC_MISC_CON0, 1, GFLAGS, grf_type_ioc), + GATE_GRF(CLK_SAI2_MCLKOUT_TO_IO, "mclk_sai2_to_io", "clk_sai2_mclkout", + 0, RK3576_VCCIO_IOC_MISC_CON0, 2, GFLAGS, grf_type_ioc), + GATE_GRF(CLK_SAI3_MCLKOUT_TO_IO, "mclk_sai3_to_io", "clk_sai3_mclkout", + 0, RK3576_VCCIO_IOC_MISC_CON0, 3, GFLAGS, grf_type_ioc), /* sdgmac */ COMPOSITE_NODIV(HCLK_SDGMAC_ROOT, "hclk_sdgmac_root", mux_200m_100m_50m_24m_p, 0, @@ -1676,13 +1686,13 @@ static struct rockchip_clk_branch rk3576_clk_branches[] __initdata = { /* phy ref */ MUXGRF(CLK_PHY_REF_SRC, "clk_phy_ref_src", clk_phy_ref_src_p, 0, - RK3576_PMU0_GRF_OSC_CON6, 4, 1, MFLAGS), + RK3576_PMU0_GRF_OSC_CON6, 4, 1, MFLAGS, grf_type_pmu0), MUXGRF(CLK_USBPHY_REF_SRC, "clk_usbphy_ref_src", clk_usbphy_ref_src_p, 0, - RK3576_PMU0_GRF_OSC_CON6, 2, 1, MFLAGS), + RK3576_PMU0_GRF_OSC_CON6, 2, 1, MFLAGS, grf_type_pmu0), MUXGRF(CLK_CPLL_REF_SRC, "clk_cpll_ref_src", clk_cpll_ref_src_p, 0, - RK3576_PMU0_GRF_OSC_CON6, 1, 1, MFLAGS), + RK3576_PMU0_GRF_OSC_CON6, 1, 1, MFLAGS, grf_type_pmu0), MUXGRF(CLK_AUPLL_REF_SRC, "clk_aupll_ref_src", clk_aupll_ref_src_p, 0, - RK3576_PMU0_GRF_OSC_CON6, 0, 1, MFLAGS), + RK3576_PMU0_GRF_OSC_CON6, 0, 1, MFLAGS, grf_type_pmu0), /* secure ns */ COMPOSITE_NODIV(ACLK_SECURE_NS, "aclk_secure_ns", mux_350m_175m_116m_24m_p, CLK_IS_CRITICAL, @@ -1725,17 +1735,26 @@ static void __init rk3576_clk_init(struct device_node *np) struct rockchip_clk_provider *ctx; unsigned long clk_nr_clks; void __iomem *reg_base; - struct regmap *grf; + struct rockchip_aux_grf *ioc_grf_e; + struct rockchip_aux_grf *pmu0_grf_e; + struct regmap *ioc_grf; + struct regmap *pmu0_grf; clk_nr_clks = rockchip_clk_find_max_clk_id(rk3576_clk_branches, ARRAY_SIZE(rk3576_clk_branches)) + 1; - grf = syscon_regmap_lookup_by_compatible("rockchip,rk3576-pmu0-grf"); - if (IS_ERR(grf)) { + pmu0_grf = syscon_regmap_lookup_by_compatible("rockchip,rk3576-pmu0-grf"); + if (IS_ERR(pmu0_grf)) { pr_err("%s: could not get PMU0 GRF syscon\n", __func__); return; } + ioc_grf = syscon_regmap_lookup_by_compatible("rockchip,rk3576-ioc-grf"); + if (IS_ERR(ioc_grf)) { + pr_err("%s: could not get IOC GRF syscon\n", __func__); + return; + } + reg_base = of_iomap(np, 0); if (!reg_base) { pr_err("%s: could not map cru region\n", __func__); @@ -1745,11 +1764,24 @@ static void __init rk3576_clk_init(struct device_node *np) ctx = rockchip_clk_init(np, reg_base, clk_nr_clks); if (IS_ERR(ctx)) { pr_err("%s: rockchip clk init failed\n", __func__); - iounmap(reg_base); - return; + goto err_unmap; } - ctx->grf = grf; + pmu0_grf_e = kzalloc(sizeof(*pmu0_grf_e), GFP_KERNEL); + if (!pmu0_grf_e) + goto err_unmap; + + pmu0_grf_e->grf = pmu0_grf; + pmu0_grf_e->type = grf_type_pmu0; + hash_add(ctx->aux_grf_table, &pmu0_grf_e->node, grf_type_pmu0); + + ioc_grf_e = kzalloc(sizeof(*ioc_grf_e), GFP_KERNEL); + if (!ioc_grf_e) + goto err_free_pmu0; + + ioc_grf_e->grf = ioc_grf; + ioc_grf_e->type = grf_type_ioc; + hash_add(ctx->aux_grf_table, &ioc_grf_e->node, grf_type_ioc); rockchip_clk_register_plls(ctx, rk3576_pll_clks, ARRAY_SIZE(rk3576_pll_clks), @@ -1772,6 +1804,14 @@ static void __init rk3576_clk_init(struct device_node *np) rockchip_register_restart_notifier(ctx, RK3576_GLB_SRST_FST, NULL); rockchip_clk_of_add_provider(np, ctx); + + return; + +err_free_pmu0: + kfree(pmu0_grf_e); +err_unmap: + iounmap(reg_base); + return; } CLK_OF_DECLARE(rk3576_cru, "rockchip,rk3576-cru", rk3576_clk_init); diff --git a/drivers/clk/rockchip/clk-rk3588.c b/drivers/clk/rockchip/clk-rk3588.c index 4031733def4e..1694223f4f84 100644 --- a/drivers/clk/rockchip/clk-rk3588.c +++ b/drivers/clk/rockchip/clk-rk3588.c @@ -64,6 +64,7 @@ static struct rockchip_pll_rate_table rk3588_pll_rates[] = { RK3588_PLL_RATE(1560000000, 2, 260, 1, 0), RK3588_PLL_RATE(1536000000, 2, 256, 1, 0), RK3588_PLL_RATE(1512000000, 2, 252, 1, 0), + RK3588_PLL_RATE(1500000000, 2, 250, 1, 0), RK3588_PLL_RATE(1488000000, 2, 248, 1, 0), RK3588_PLL_RATE(1464000000, 2, 244, 1, 0), RK3588_PLL_RATE(1440000000, 2, 240, 1, 0), diff --git a/drivers/clk/rockchip/clk-rv1126.c b/drivers/clk/rockchip/clk-rv1126.c index fc19c5522490..15e7bfe84506 100644 --- a/drivers/clk/rockchip/clk-rv1126.c +++ b/drivers/clk/rockchip/clk-rv1126.c @@ -857,7 +857,7 @@ static struct rockchip_clk_branch rv1126_clk_branches[] __initdata = { RV1126_GMAC_CON, 5, 1, MFLAGS), MUXGRF(CLK_GMAC_SRC, "clk_gmac_src", mux_clk_gmac_src_p, CLK_SET_RATE_PARENT | CLK_SET_RATE_NO_REPARENT, - RV1126_GRF_IOFUNC_CON1, 12, 1, MFLAGS), + RV1126_GRF_IOFUNC_CON1, 12, 1, MFLAGS, grf_type_sys), GATE(CLK_GMAC_REF, "clk_gmac_ref", "clk_gmac_src", 0, RV1126_CLKGATE_CON(20), 7, GFLAGS), diff --git a/drivers/clk/rockchip/clk.c b/drivers/clk/rockchip/clk.c index cbf93ea119a9..19caf26c991b 100644 --- a/drivers/clk/rockchip/clk.c +++ b/drivers/clk/rockchip/clk.c @@ -382,6 +382,8 @@ static struct rockchip_clk_provider *rockchip_clk_init_base( ctx->cru_node = np; spin_lock_init(&ctx->lock); + hash_init(ctx->aux_grf_table); + ctx->grf = syscon_regmap_lookup_by_phandle(ctx->cru_node, "rockchip,grf"); @@ -496,6 +498,8 @@ void rockchip_clk_register_branches(struct rockchip_clk_provider *ctx, struct rockchip_clk_branch *list, unsigned int nr_clk) { + struct regmap *grf = ctx->grf; + struct rockchip_aux_grf *agrf; struct clk *clk; unsigned int idx; unsigned long flags; @@ -504,6 +508,19 @@ void rockchip_clk_register_branches(struct rockchip_clk_provider *ctx, flags = list->flags; clk = NULL; + /* for GRF-dependent branches, choose the right grf first */ + if ((list->branch_type == branch_grf_mux || + list->branch_type == branch_grf_gate || + list->branch_type == branch_grf_mmc) && + list->grf_type != grf_type_sys) { + hash_for_each_possible(ctx->aux_grf_table, agrf, node, list->grf_type) { + if (agrf->type == list->grf_type) { + grf = agrf->grf; + break; + } + } + } + /* catch simple muxes */ switch (list->branch_type) { case branch_mux: @@ -523,10 +540,10 @@ void rockchip_clk_register_branches(struct rockchip_clk_provider *ctx, list->mux_shift, list->mux_width, list->mux_flags, &ctx->lock); break; - case branch_muxgrf: + case branch_grf_mux: clk = rockchip_clk_register_muxgrf(list->name, list->parent_names, list->num_parents, - flags, ctx->grf, list->muxdiv_offset, + flags, grf, list->muxdiv_offset, list->mux_shift, list->mux_width, list->mux_flags); break; @@ -573,6 +590,13 @@ void rockchip_clk_register_branches(struct rockchip_clk_provider *ctx, ctx->reg_base + list->gate_offset, list->gate_shift, list->gate_flags, &ctx->lock); break; + case branch_grf_gate: + flags |= CLK_SET_RATE_PARENT; + clk = rockchip_clk_register_gate_grf(list->name, + list->parent_names[0], flags, grf, + list->gate_offset, list->gate_shift, + list->gate_flags); + break; case branch_composite: clk = rockchip_clk_register_branch(list->name, list->parent_names, list->num_parents, @@ -590,6 +614,16 @@ void rockchip_clk_register_branches(struct rockchip_clk_provider *ctx, list->name, list->parent_names, list->num_parents, ctx->reg_base + list->muxdiv_offset, + NULL, 0, + list->div_shift + ); + break; + case branch_grf_mmc: + clk = rockchip_clk_register_mmc( + list->name, + list->parent_names, list->num_parents, + NULL, + grf, list->muxdiv_offset, list->div_shift ); break; diff --git a/drivers/clk/rockchip/clk.h b/drivers/clk/rockchip/clk.h index df2b2d706450..1e9c3c0d31e3 100644 --- a/drivers/clk/rockchip/clk.h +++ b/drivers/clk/rockchip/clk.h @@ -19,6 +19,7 @@ #include <linux/io.h> #include <linux/clk-provider.h> +#include <linux/hashtable.h> struct clk; @@ -217,6 +218,9 @@ struct clk; #define RK3528_CLKSEL_CON(x) ((x) * 0x4 + 0x300) #define RK3528_CLKGATE_CON(x) ((x) * 0x4 + 0x800) #define RK3528_SOFTRST_CON(x) ((x) * 0x4 + 0xa00) +#define RK3528_SDMMC_CON(x) ((x) * 0x4 + 0x24) +#define RK3528_SDIO0_CON(x) ((x) * 0x4 + 0x4) +#define RK3528_SDIO1_CON(x) ((x) * 0x4 + 0xc) #define RK3528_PMU_CLKSEL_CON(x) ((x) * 0x4 + 0x300 + RK3528_PMU_CRU_BASE) #define RK3528_PMU_CLKGATE_CON(x) ((x) * 0x4 + 0x800 + RK3528_PMU_CRU_BASE) #define RK3528_PCIE_CLKSEL_CON(x) ((x) * 0x4 + 0x300 + RK3528_PCIE_CRU_BASE) @@ -440,12 +444,37 @@ enum rockchip_pll_type { .k = _k, \ } +enum rockchip_grf_type { + grf_type_sys = 0, + grf_type_pmu0, + grf_type_pmu1, + grf_type_ioc, + grf_type_vo, + grf_type_vpu, +}; + +/* ceil(sqrt(enums in rockchip_grf_type - 1)) */ +#define GRF_HASH_ORDER 2 + +/** + * struct rockchip_aux_grf - entry for the aux_grf_table hashtable + * @grf: pointer to the grf this entry references + * @type: what type of GRF this is + * @node: hlist node + */ +struct rockchip_aux_grf { + struct regmap *grf; + enum rockchip_grf_type type; + struct hlist_node node; +}; + /** * struct rockchip_clk_provider - information about clock provider * @reg_base: virtual address for the register base. * @clk_data: holds clock related data like clk* and number of clocks. * @cru_node: device-node of the clock-provider * @grf: regmap of the general-register-files syscon + * @aux_grf_table: hashtable of auxiliary GRF regmaps, indexed by grf_type * @lock: maintains exclusion between callbacks for a given clock-provider. */ struct rockchip_clk_provider { @@ -453,6 +482,7 @@ struct rockchip_clk_provider { struct clk_onecell_data clk_data; struct device_node *cru_node; struct regmap *grf; + DECLARE_HASHTABLE(aux_grf_table, GRF_HASH_ORDER); spinlock_t lock; }; @@ -594,7 +624,9 @@ struct clk *rockchip_clk_register_cpuclk(const char *name, struct clk *rockchip_clk_register_mmc(const char *name, const char *const *parent_names, u8 num_parents, - void __iomem *reg, int shift); + void __iomem *reg, + struct regmap *grf, int grf_reg, + int shift); /* * DDRCLK flags, including method of setting the rate @@ -622,17 +654,24 @@ struct clk *rockchip_clk_register_muxgrf(const char *name, int flags, struct regmap *grf, int reg, int shift, int width, int mux_flags); +struct clk *rockchip_clk_register_gate_grf(const char *name, + const char *parent_name, unsigned long flags, + struct regmap *regmap, unsigned int reg, + unsigned int shift, u8 gate_flags); + #define PNAME(x) static const char *const x[] __initconst enum rockchip_clk_branch_type { branch_composite, branch_mux, - branch_muxgrf, + branch_grf_mux, branch_divider, branch_fraction_divider, branch_gate, + branch_grf_gate, branch_linked_gate, branch_mmc, + branch_grf_mmc, branch_inverter, branch_factor, branch_ddrclk, @@ -660,6 +699,7 @@ struct rockchip_clk_branch { u8 gate_shift; u8 gate_flags; unsigned int linked_clk_id; + enum rockchip_grf_type grf_type; struct rockchip_clk_branch *child; }; @@ -900,10 +940,10 @@ struct rockchip_clk_branch { .mux_table = mt, \ } -#define MUXGRF(_id, cname, pnames, f, o, s, w, mf) \ +#define MUXGRF(_id, cname, pnames, f, o, s, w, mf, gt) \ { \ .id = _id, \ - .branch_type = branch_muxgrf, \ + .branch_type = branch_grf_mux, \ .name = cname, \ .parent_names = pnames, \ .num_parents = ARRAY_SIZE(pnames), \ @@ -913,6 +953,7 @@ struct rockchip_clk_branch { .mux_width = w, \ .mux_flags = mf, \ .gate_offset = -1, \ + .grf_type = gt, \ } #define DIV(_id, cname, pname, f, o, s, w, df) \ @@ -958,6 +999,20 @@ struct rockchip_clk_branch { .gate_flags = gf, \ } +#define GATE_GRF(_id, cname, pname, f, o, b, gf, gt) \ + { \ + .id = _id, \ + .branch_type = branch_grf_gate, \ + .name = cname, \ + .parent_names = (const char *[]){ pname }, \ + .num_parents = 1, \ + .flags = f, \ + .gate_offset = o, \ + .gate_shift = b, \ + .gate_flags = gf, \ + .grf_type = gt, \ + } + #define GATE_LINK(_id, cname, pname, linkedclk, f, o, b, gf) \ { \ .id = _id, \ @@ -983,6 +1038,18 @@ struct rockchip_clk_branch { .div_shift = shift, \ } +#define MMC_GRF(_id, cname, pname, offset, shift, grftype) \ + { \ + .id = _id, \ + .branch_type = branch_grf_mmc, \ + .name = cname, \ + .parent_names = (const char *[]){ pname }, \ + .num_parents = 1, \ + .muxdiv_offset = offset, \ + .div_shift = shift, \ + .grf_type = grftype, \ + } + #define INVERTER(_id, cname, pname, io, is, if) \ { \ .id = _id, \ diff --git a/drivers/clk/sunxi-ng/Kconfig b/drivers/clk/sunxi-ng/Kconfig index 5830a9d87bf2..8896fd052ef1 100644 --- a/drivers/clk/sunxi-ng/Kconfig +++ b/drivers/clk/sunxi-ng/Kconfig @@ -9,123 +9,123 @@ if SUNXI_CCU config SUNIV_F1C100S_CCU tristate "Support for the Allwinner newer F1C100s CCU" - default y + default ARCH_SUNXI depends on MACH_SUNIV || COMPILE_TEST config SUN20I_D1_CCU tristate "Support for the Allwinner D1/R528/T113 CCU" - default y + default ARCH_SUNXI depends on MACH_SUN8I || RISCV || COMPILE_TEST config SUN20I_D1_R_CCU tristate "Support for the Allwinner D1/R528/T113 PRCM CCU" - default y + default ARCH_SUNXI depends on MACH_SUN8I || RISCV || COMPILE_TEST config SUN50I_A64_CCU tristate "Support for the Allwinner A64 CCU" - default y + default ARCH_SUNXI depends on ARM64 || COMPILE_TEST config SUN50I_A100_CCU tristate "Support for the Allwinner A100 CCU" - default y + default ARCH_SUNXI depends on ARM64 || COMPILE_TEST config SUN50I_A100_R_CCU tristate "Support for the Allwinner A100 PRCM CCU" - default y + default ARCH_SUNXI depends on ARM64 || COMPILE_TEST config SUN50I_H6_CCU tristate "Support for the Allwinner H6 CCU" - default y + default ARCH_SUNXI depends on ARM64 || COMPILE_TEST config SUN50I_H616_CCU tristate "Support for the Allwinner H616 CCU" - default y + default ARCH_SUNXI depends on ARM64 || COMPILE_TEST config SUN50I_H6_R_CCU tristate "Support for the Allwinner H6 and H616 PRCM CCU" - default y + default ARCH_SUNXI depends on ARM64 || COMPILE_TEST config SUN55I_A523_CCU tristate "Support for the Allwinner A523/T527 CCU" - default y + default ARCH_SUNXI depends on ARM64 || COMPILE_TEST config SUN55I_A523_R_CCU tristate "Support for the Allwinner A523/T527 PRCM CCU" - default y + default ARCH_SUNXI depends on ARM64 || COMPILE_TEST config SUN4I_A10_CCU tristate "Support for the Allwinner A10/A20 CCU" - default y + default ARCH_SUNXI depends on MACH_SUN4I || MACH_SUN7I || COMPILE_TEST config SUN5I_CCU bool "Support for the Allwinner sun5i family CCM" - default y + default ARCH_SUNXI depends on MACH_SUN5I || COMPILE_TEST depends on SUNXI_CCU=y config SUN6I_A31_CCU tristate "Support for the Allwinner A31/A31s CCU" - default y + default ARCH_SUNXI depends on MACH_SUN6I || COMPILE_TEST config SUN6I_RTC_CCU tristate "Support for the Allwinner H616/R329 RTC CCU" - default y + default ARCH_SUNXI depends on MACH_SUN8I || ARM64 || RISCV || COMPILE_TEST config SUN8I_A23_CCU tristate "Support for the Allwinner A23 CCU" - default y + default ARCH_SUNXI depends on MACH_SUN8I || COMPILE_TEST config SUN8I_A33_CCU tristate "Support for the Allwinner A33 CCU" - default y + default ARCH_SUNXI depends on MACH_SUN8I || COMPILE_TEST config SUN8I_A83T_CCU tristate "Support for the Allwinner A83T CCU" - default y + default ARCH_SUNXI depends on MACH_SUN8I || COMPILE_TEST config SUN8I_H3_CCU tristate "Support for the Allwinner H3 CCU" - default y + default ARCH_SUNXI depends on MACH_SUN8I || ARM64 || COMPILE_TEST config SUN8I_V3S_CCU tristate "Support for the Allwinner V3s CCU" - default y + default ARCH_SUNXI depends on MACH_SUN8I || COMPILE_TEST config SUN8I_DE2_CCU tristate "Support for the Allwinner SoCs DE2 CCU" - default y + default ARCH_SUNXI depends on MACH_SUN8I || ARM64 || RISCV || COMPILE_TEST config SUN8I_R40_CCU tristate "Support for the Allwinner R40 CCU" - default y + default ARCH_SUNXI depends on MACH_SUN8I || COMPILE_TEST config SUN9I_A80_CCU tristate "Support for the Allwinner A80 CCU" - default y + default ARCH_SUNXI depends on MACH_SUN9I || COMPILE_TEST config SUN8I_R_CCU tristate "Support for Allwinner SoCs' PRCM CCUs" - default y + default ARCH_SUNXI depends on MACH_SUN8I || ARM64 || COMPILE_TEST endif diff --git a/drivers/clk/sunxi-ng/ccu-sun50i-h616.c b/drivers/clk/sunxi-ng/ccu-sun50i-h616.c index daa462c7d477..955c614830fa 100644 --- a/drivers/clk/sunxi-ng/ccu-sun50i-h616.c +++ b/drivers/clk/sunxi-ng/ccu-sun50i-h616.c @@ -1094,6 +1094,7 @@ static const struct ccu_reset_map sun50i_h616_ccu_resets[] = { [RST_BUS_TCON_LCD1] = { 0xb7c, BIT(17) }, [RST_BUS_TCON_TV0] = { 0xb9c, BIT(16) }, [RST_BUS_TCON_TV1] = { 0xb9c, BIT(17) }, + [RST_BUS_LVDS] = { 0xbac, BIT(16) }, [RST_BUS_TVE_TOP] = { 0xbbc, BIT(16) }, [RST_BUS_TVE0] = { 0xbbc, BIT(17) }, [RST_BUS_HDCP] = { 0xc4c, BIT(16) }, diff --git a/drivers/clk/sunxi-ng/ccu-sun8i-de2.c b/drivers/clk/sunxi-ng/ccu-sun8i-de2.c index f2aa71206bc2..a6cd0f988859 100644 --- a/drivers/clk/sunxi-ng/ccu-sun8i-de2.c +++ b/drivers/clk/sunxi-ng/ccu-sun8i-de2.c @@ -5,6 +5,7 @@ #include <linux/clk.h> #include <linux/clk-provider.h> +#include <linux/io.h> #include <linux/module.h> #include <linux/of.h> #include <linux/platform_device.h> @@ -239,6 +240,16 @@ static const struct sunxi_ccu_desc sun50i_h5_de2_clk_desc = { .num_resets = ARRAY_SIZE(sun50i_h5_de2_resets), }; +static const struct sunxi_ccu_desc sun50i_h616_de33_clk_desc = { + .ccu_clks = sun8i_de2_ccu_clks, + .num_ccu_clks = ARRAY_SIZE(sun8i_de2_ccu_clks), + + .hw_clks = &sun8i_h3_de2_hw_clks, + + .resets = sun50i_h5_de2_resets, + .num_resets = ARRAY_SIZE(sun50i_h5_de2_resets), +}; + static int sunxi_de2_clk_probe(struct platform_device *pdev) { struct clk *bus_clk, *mod_clk; @@ -291,6 +302,16 @@ static int sunxi_de2_clk_probe(struct platform_device *pdev) goto err_disable_mod_clk; } + /* + * The DE33 requires these additional (unknown) registers set + * during initialisation. + */ + if (of_device_is_compatible(pdev->dev.of_node, + "allwinner,sun50i-h616-de33-clk")) { + writel(0, reg + 0x24); + writel(0x0000a980, reg + 0x28); + } + ret = devm_sunxi_ccu_probe(&pdev->dev, reg, ccu_desc); if (ret) goto err_assert_reset; @@ -335,6 +356,10 @@ static const struct of_device_id sunxi_de2_clk_ids[] = { .compatible = "allwinner,sun50i-h6-de3-clk", .data = &sun50i_h5_de2_clk_desc, }, + { + .compatible = "allwinner,sun50i-h616-de33-clk", + .data = &sun50i_h616_de33_clk_desc, + }, { } }; MODULE_DEVICE_TABLE(of, sunxi_de2_clk_ids); diff --git a/drivers/clk/sunxi/Kconfig b/drivers/clk/sunxi/Kconfig index 1c4e543366dd..5e2f92bfe412 100644 --- a/drivers/clk/sunxi/Kconfig +++ b/drivers/clk/sunxi/Kconfig @@ -2,13 +2,13 @@ menuconfig CLK_SUNXI bool "Legacy clock support for Allwinner SoCs" depends on (ARM && ARCH_SUNXI) || COMPILE_TEST - default y + default (ARM && ARCH_SUNXI) if CLK_SUNXI config CLK_SUNXI_CLOCKS bool "Legacy clock drivers" - default y + default ARCH_SUNXI help Legacy clock drivers being used on older (A10, A13, A20, A23, A31, A80) SoCs. These drivers are kept around for @@ -19,14 +19,14 @@ config CLK_SUNXI_CLOCKS config CLK_SUNXI_PRCM_SUN6I bool "Legacy A31 PRCM driver" - default y + default ARCH_SUNXI help Legacy clock driver for the A31 PRCM clocks. Those are usually needed for the PMIC communication, mostly. config CLK_SUNXI_PRCM_SUN8I bool "Legacy sun8i PRCM driver" - default y + default ARCH_SUNXI help Legacy clock driver for the sun8i family PRCM clocks. Those are usually needed for the PMIC communication, @@ -34,7 +34,7 @@ config CLK_SUNXI_PRCM_SUN8I config CLK_SUNXI_PRCM_SUN9I bool "Legacy A80 PRCM driver" - default y + default ARCH_SUNXI help Legacy clock driver for the A80 PRCM clocks. Those are usually needed for the PMIC communication, mostly. diff --git a/include/dt-bindings/clock/qcom,sm6350-videocc.h b/include/dt-bindings/clock/qcom,sm6350-videocc.h new file mode 100644 index 000000000000..2af7f91fa023 --- /dev/null +++ b/include/dt-bindings/clock/qcom,sm6350-videocc.h @@ -0,0 +1,27 @@ +/* SPDX-License-Identifier: (GPL-2.0-only OR BSD-2-Clause) */ +/* + * Copyright (c) 2021, The Linux Foundation. All rights reserved. + * Copyright (c) 2021, Konrad Dybcio <konrad.dybcio@somainline.org> + */ + +#ifndef _DT_BINDINGS_CLK_QCOM_VIDEO_CC_SM6350_H +#define _DT_BINDINGS_CLK_QCOM_VIDEO_CC_SM6350_H + +/* VIDEO_CC clocks */ +#define VIDEO_PLL0 0 +#define VIDEO_PLL0_OUT_EVEN 1 +#define VIDEO_CC_IRIS_AHB_CLK 2 +#define VIDEO_CC_IRIS_CLK_SRC 3 +#define VIDEO_CC_MVS0_AXI_CLK 4 +#define VIDEO_CC_MVS0_CORE_CLK 5 +#define VIDEO_CC_MVSC_CORE_CLK 6 +#define VIDEO_CC_MVSC_CTL_AXI_CLK 7 +#define VIDEO_CC_SLEEP_CLK 8 +#define VIDEO_CC_SLEEP_CLK_SRC 9 +#define VIDEO_CC_VENUS_AHB_CLK 10 + +/* GDSCs */ +#define MVSC_GDSC 0 +#define MVS0_GDSC 1 + +#endif diff --git a/include/dt-bindings/clock/rk3036-cru.h b/include/dt-bindings/clock/rk3036-cru.h index 99cc617e1e54..5cbc0e2b08ff 100644 --- a/include/dt-bindings/clock/rk3036-cru.h +++ b/include/dt-bindings/clock/rk3036-cru.h @@ -47,6 +47,7 @@ #define SCLK_MACREF 152 #define SCLK_MACPLL 153 #define SCLK_SFC 160 +#define SCLK_USB480M 161 /* aclk gates */ #define ACLK_DMAC2 194 diff --git a/include/dt-bindings/clock/rockchip,rk3528-cru.h b/include/dt-bindings/clock/rockchip,rk3528-cru.h index 55a448f5ed6d..0245a53fc334 100644 --- a/include/dt-bindings/clock/rockchip,rk3528-cru.h +++ b/include/dt-bindings/clock/rockchip,rk3528-cru.h @@ -414,6 +414,12 @@ #define MCLK_I2S2_2CH_SAI_SRC_PRE 402 #define MCLK_I2S3_8CH_SAI_SRC_PRE 403 #define MCLK_SDPDIF_SRC_PRE 404 +#define SCLK_SDMMC_DRV 405 +#define SCLK_SDMMC_SAMPLE 406 +#define SCLK_SDIO0_DRV 407 +#define SCLK_SDIO0_SAMPLE 408 +#define SCLK_SDIO1_DRV 409 +#define SCLK_SDIO1_SAMPLE 410 /* scmi-clocks indices */ #define SCMI_PCLK_KEYREADER 0 diff --git a/include/dt-bindings/clock/rockchip,rk3576-cru.h b/include/dt-bindings/clock/rockchip,rk3576-cru.h index f576e61bec70..ded5ce42e62a 100644 --- a/include/dt-bindings/clock/rockchip,rk3576-cru.h +++ b/include/dt-bindings/clock/rockchip,rk3576-cru.h @@ -594,4 +594,14 @@ #define SCMI_ARMCLK_B 11 #define SCMI_CLK_GPU 456 +/* IOC-controlled output clocks */ +#define CLK_SAI0_MCLKOUT_TO_IO 571 +#define CLK_SAI1_MCLKOUT_TO_IO 572 +#define CLK_SAI2_MCLKOUT_TO_IO 573 +#define CLK_SAI3_MCLKOUT_TO_IO 574 +#define CLK_SAI4_MCLKOUT_TO_IO 575 +#define CLK_SAI4_MCLKOUT_TO_IO 575 +#define CLK_FSPI0_TO_IO 576 +#define CLK_FSPI1_TO_IO 577 + #endif diff --git a/include/dt-bindings/reset/sun50i-h616-ccu.h b/include/dt-bindings/reset/sun50i-h616-ccu.h index 81b1eba2a7f7..ba626f7015b5 100644 --- a/include/dt-bindings/reset/sun50i-h616-ccu.h +++ b/include/dt-bindings/reset/sun50i-h616-ccu.h @@ -69,5 +69,6 @@ #define RST_BUS_GPADC 60 #define RST_BUS_TCON_LCD0 61 #define RST_BUS_TCON_LCD1 62 +#define RST_BUS_LVDS 63 #endif /* _DT_BINDINGS_RESET_SUN50I_H616_H_ */ |