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

clk: rockchip: rk3528: Add SD/SDIO tuning clocks in GRF region

These clocks locate in VO and VPU GRF, serving for SD/SDIO controller
tuning purpose. Add their definitions and register them in driver if
corresponding GRF is available.

GRFs are looked up by compatible to simplify devicetree binding.

Signed-off-by: Yao Zi <ziyao@disroot.org>
Link: https://lore.kernel.org/r/20250506092206.46143-4-ziyao@disroot.org
Signed-off-by: Heiko Stuebner <heiko@sntech.de>

authored by

Yao Zi and committed by
Heiko Stuebner
306d2f5d 621ba4d9

+81 -6
+76 -6
drivers/clk/rockchip/clk-rk3528.c
··· 10 10 #include <linux/of.h> 11 11 #include <linux/of_device.h> 12 12 #include <linux/platform_device.h> 13 + #include <linux/mfd/syscon.h> 14 + #include <linux/minmax.h> 13 15 14 16 #include <dt-bindings/clock/rockchip,rk3528-cru.h> 15 17 ··· 1063 1061 0, 1, 1), 1064 1062 }; 1065 1063 1064 + static struct rockchip_clk_branch rk3528_vo_clk_branches[] __initdata = { 1065 + MMC_GRF(SCLK_SDMMC_DRV, "sdmmc_drv", "cclk_src_sdmmc0", 1066 + RK3528_SDMMC_CON(0), 1, grf_type_vo), 1067 + MMC_GRF(SCLK_SDMMC_SAMPLE, "sdmmc_sample", "cclk_src_sdmmc0", 1068 + RK3528_SDMMC_CON(1), 1, grf_type_vo), 1069 + }; 1070 + 1071 + static struct rockchip_clk_branch rk3528_vpu_clk_branches[] __initdata = { 1072 + MMC_GRF(SCLK_SDIO0_DRV, "sdio0_drv", "cclk_src_sdio0", 1073 + RK3528_SDIO0_CON(0), 1, grf_type_vpu), 1074 + MMC_GRF(SCLK_SDIO0_SAMPLE, "sdio0_sample", "cclk_src_sdio0", 1075 + RK3528_SDIO0_CON(1), 1, grf_type_vpu), 1076 + MMC_GRF(SCLK_SDIO1_DRV, "sdio1_drv", "cclk_src_sdio1", 1077 + RK3528_SDIO1_CON(0), 1, grf_type_vpu), 1078 + MMC_GRF(SCLK_SDIO1_SAMPLE, "sdio1_sample", "cclk_src_sdio1", 1079 + RK3528_SDIO1_CON(1), 1, grf_type_vpu), 1080 + }; 1081 + 1066 1082 static int __init clk_rk3528_probe(struct platform_device *pdev) 1067 1083 { 1068 - struct rockchip_clk_provider *ctx; 1084 + unsigned long nr_vpu_branches = ARRAY_SIZE(rk3528_vpu_clk_branches); 1085 + unsigned long nr_vo_branches = ARRAY_SIZE(rk3528_vo_clk_branches); 1086 + unsigned long nr_branches = ARRAY_SIZE(rk3528_clk_branches); 1087 + unsigned long nr_clks, nr_vo_clks, nr_vpu_clks; 1088 + struct rockchip_aux_grf *vo_grf_e, *vpu_grf_e; 1089 + struct regmap *vo_grf, *vpu_grf; 1069 1090 struct device *dev = &pdev->dev; 1070 1091 struct device_node *np = dev->of_node; 1071 - unsigned long nr_branches = ARRAY_SIZE(rk3528_clk_branches); 1072 - unsigned long nr_clks; 1092 + struct rockchip_clk_provider *ctx; 1073 1093 void __iomem *reg_base; 1074 - 1075 - nr_clks = rockchip_clk_find_max_clk_id(rk3528_clk_branches, 1076 - nr_branches) + 1; 1077 1094 1078 1095 reg_base = devm_platform_ioremap_resource(pdev, 0); 1079 1096 if (IS_ERR(reg_base)) 1080 1097 return dev_err_probe(dev, PTR_ERR(reg_base), 1081 1098 "could not map cru region"); 1099 + 1100 + nr_clks = rockchip_clk_find_max_clk_id(rk3528_clk_branches, 1101 + nr_branches) + 1; 1102 + 1103 + vo_grf = syscon_regmap_lookup_by_compatible("rockchip,rk3528-vo-grf"); 1104 + if (!IS_ERR(vo_grf)) { 1105 + nr_vo_clks = rockchip_clk_find_max_clk_id(rk3528_vo_clk_branches, 1106 + nr_vo_branches) + 1; 1107 + nr_clks = max(nr_clks, nr_vo_clks); 1108 + } else if (PTR_ERR(vo_grf) != -ENODEV) { 1109 + return dev_err_probe(dev, PTR_ERR(vo_grf), 1110 + "failed to look up VO GRF\n"); 1111 + } 1112 + 1113 + vpu_grf = syscon_regmap_lookup_by_compatible("rockchip,rk3528-vpu-grf"); 1114 + if (!IS_ERR(vpu_grf)) { 1115 + nr_vpu_clks = rockchip_clk_find_max_clk_id(rk3528_vpu_clk_branches, 1116 + nr_vpu_branches) + 1; 1117 + nr_clks = max(nr_clks, nr_vpu_clks); 1118 + } else if (PTR_ERR(vpu_grf) != -ENODEV) { 1119 + return dev_err_probe(dev, PTR_ERR(vpu_grf), 1120 + "failed to look up VPU GRF\n"); 1121 + } 1082 1122 1083 1123 ctx = rockchip_clk_init(np, reg_base, nr_clks); 1084 1124 if (IS_ERR(ctx)) ··· 1135 1091 &rk3528_cpuclk_data, rk3528_cpuclk_rates, 1136 1092 ARRAY_SIZE(rk3528_cpuclk_rates)); 1137 1093 rockchip_clk_register_branches(ctx, rk3528_clk_branches, nr_branches); 1094 + 1095 + if (!IS_ERR(vo_grf)) { 1096 + vo_grf_e = devm_kzalloc(dev, sizeof(*vo_grf_e), GFP_KERNEL); 1097 + if (!vo_grf_e) 1098 + return -ENOMEM; 1099 + 1100 + vo_grf_e->grf = vo_grf; 1101 + vo_grf_e->type = grf_type_vo; 1102 + hash_add(ctx->aux_grf_table, &vo_grf_e->node, grf_type_vo); 1103 + 1104 + rockchip_clk_register_branches(ctx, rk3528_vo_clk_branches, 1105 + nr_vo_branches); 1106 + } 1107 + 1108 + if (!IS_ERR(vpu_grf)) { 1109 + vpu_grf_e = devm_kzalloc(dev, sizeof(*vpu_grf_e), GFP_KERNEL); 1110 + if (!vpu_grf_e) 1111 + return -ENOMEM; 1112 + 1113 + vpu_grf_e->grf = vpu_grf; 1114 + vpu_grf_e->type = grf_type_vpu; 1115 + hash_add(ctx->aux_grf_table, &vpu_grf_e->node, grf_type_vpu); 1116 + 1117 + rockchip_clk_register_branches(ctx, rk3528_vpu_clk_branches, 1118 + nr_vpu_branches); 1119 + } 1138 1120 1139 1121 rk3528_rst_init(np, reg_base); 1140 1122
+5
drivers/clk/rockchip/clk.h
··· 218 218 #define RK3528_CLKSEL_CON(x) ((x) * 0x4 + 0x300) 219 219 #define RK3528_CLKGATE_CON(x) ((x) * 0x4 + 0x800) 220 220 #define RK3528_SOFTRST_CON(x) ((x) * 0x4 + 0xa00) 221 + #define RK3528_SDMMC_CON(x) ((x) * 0x4 + 0x24) 222 + #define RK3528_SDIO0_CON(x) ((x) * 0x4 + 0x4) 223 + #define RK3528_SDIO1_CON(x) ((x) * 0x4 + 0xc) 221 224 #define RK3528_PMU_CLKSEL_CON(x) ((x) * 0x4 + 0x300 + RK3528_PMU_CRU_BASE) 222 225 #define RK3528_PMU_CLKGATE_CON(x) ((x) * 0x4 + 0x800 + RK3528_PMU_CRU_BASE) 223 226 #define RK3528_PCIE_CLKSEL_CON(x) ((x) * 0x4 + 0x300 + RK3528_PCIE_CRU_BASE) ··· 449 446 grf_type_pmu0, 450 447 grf_type_pmu1, 451 448 grf_type_ioc, 449 + grf_type_vo, 450 + grf_type_vpu, 452 451 }; 453 452 454 453 /* ceil(sqrt(enums in rockchip_grf_type - 1)) */