1 // SPDX-License-Identifier: GPL-2.0 2 /* 3 * Copyright (c) 2018, The Linux Foundation. All rights reserved. 4 * Copyright (c) 2025, Qualcomm Innovation Center, Inc. All rights reserved. 5 */ 6 7 #include <linux/clk.h> 8 #include <linux/clk-provider.h> 9 #include <linux/err.h> 10 #include <linux/interconnect-provider.h> 11 #include <linux/kernel.h> 12 #include <linux/module.h> 13 #include <linux/platform_device.h> 14 #include <linux/regmap.h> 15 16 #include <dt-bindings/arm/qcom,ids.h> 17 #include <dt-bindings/clock/qcom,apss-ipq.h> 18 #include <dt-bindings/interconnect/qcom,ipq5424.h> 19 20 #include "clk-alpha-pll.h" 21 #include "clk-branch.h" 22 #include "clk-rcg.h" 23 #include "clk-regmap.h" 24 #include "common.h" 25 26 enum { 27 DT_XO, 28 DT_CLK_REF, 29 }; 30 31 enum { 32 P_XO, 33 P_GPLL0, 34 P_APSS_PLL_EARLY, 35 P_L3_PLL, 36 }; 37 38 struct apss_clk { 39 struct notifier_block cpu_clk_notifier; 40 struct clk_hw *hw; 41 struct device *dev; 42 struct clk *l3_clk; 43 }; 44 45 static const struct alpha_pll_config apss_pll_config = { 46 .l = 0x3b, 47 .config_ctl_val = 0x08200920, 48 .config_ctl_hi_val = 0x05008001, 49 .config_ctl_hi1_val = 0x04000000, 50 .user_ctl_val = 0xf, 51 }; 52 53 static struct clk_alpha_pll ipq5424_apss_pll = { 54 .offset = 0x0, 55 .config = &apss_pll_config, 56 .regs = clk_alpha_pll_regs[CLK_ALPHA_PLL_TYPE_HUAYRA_2290], 57 .flags = SUPPORTS_DYNAMIC_UPDATE, 58 .clkr = { 59 .enable_reg = 0x0, 60 .enable_mask = BIT(0), 61 .hw.init = &(struct clk_init_data){ 62 .name = "apss_pll", 63 .parent_data = &(const struct clk_parent_data) { 64 .index = DT_XO, 65 }, 66 .num_parents = 1, 67 .ops = &clk_alpha_pll_huayra_ops, 68 }, 69 }, 70 }; 71 72 static const struct clk_parent_data parents_apss_silver_clk_src[] = { 73 { .index = DT_XO }, 74 { .index = DT_CLK_REF }, 75 { .hw = &ipq5424_apss_pll.clkr.hw }, 76 }; 77 78 static const struct parent_map parents_apss_silver_clk_src_map[] = { 79 { P_XO, 0 }, 80 { P_GPLL0, 4 }, 81 { P_APSS_PLL_EARLY, 5 }, 82 }; 83 84 static const struct freq_tbl ftbl_apss_clk_src[] = { 85 F(816000000, P_APSS_PLL_EARLY, 1, 0, 0), 86 F(1416000000, P_APSS_PLL_EARLY, 1, 0, 0), 87 F(1800000000, P_APSS_PLL_EARLY, 1, 0, 0), 88 { } 89 }; 90 91 static struct clk_rcg2 apss_silver_clk_src = { 92 .cmd_rcgr = 0x0080, 93 .freq_tbl = ftbl_apss_clk_src, 94 .hid_width = 5, 95 .parent_map = parents_apss_silver_clk_src_map, 96 .clkr.hw.init = &(struct clk_init_data) { 97 .name = "apss_silver_clk_src", 98 .parent_data = parents_apss_silver_clk_src, 99 .num_parents = ARRAY_SIZE(parents_apss_silver_clk_src), 100 .ops = &clk_rcg2_ops, 101 .flags = CLK_SET_RATE_PARENT, 102 }, 103 }; 104 105 static struct clk_branch apss_silver_core_clk = { 106 .halt_reg = 0x008c, 107 .clkr = { 108 .enable_reg = 0x008c, 109 .enable_mask = BIT(0), 110 .hw.init = &(struct clk_init_data) { 111 .name = "apss_silver_core_clk", 112 .parent_hws = (const struct clk_hw *[]) { 113 &apss_silver_clk_src.clkr.hw 114 }, 115 .num_parents = 1, 116 .flags = CLK_SET_RATE_PARENT | CLK_IS_CRITICAL, 117 .ops = &clk_branch2_ops, 118 }, 119 }, 120 }; 121 122 static const struct alpha_pll_config l3_pll_config = { 123 .l = 0x29, 124 .config_ctl_val = 0x08200920, 125 .config_ctl_hi_val = 0x05008001, 126 .config_ctl_hi1_val = 0x04000000, 127 .user_ctl_val = 0xf, 128 }; 129 130 static struct clk_alpha_pll ipq5424_l3_pll = { 131 .offset = 0x10000, 132 .config = &l3_pll_config, 133 .regs = clk_alpha_pll_regs[CLK_ALPHA_PLL_TYPE_HUAYRA_2290], 134 .flags = SUPPORTS_DYNAMIC_UPDATE, 135 .clkr = { 136 .enable_reg = 0x0, 137 .enable_mask = BIT(0), 138 .hw.init = &(struct clk_init_data) { 139 .name = "l3_pll", 140 .parent_data = &(const struct clk_parent_data) { 141 .index = DT_XO, 142 }, 143 .num_parents = 1, 144 .ops = &clk_alpha_pll_huayra_ops, 145 }, 146 }, 147 }; 148 149 static const struct clk_parent_data parents_l3_clk_src[] = { 150 { .index = DT_XO }, 151 { .index = DT_CLK_REF }, 152 { .hw = &ipq5424_l3_pll.clkr.hw }, 153 }; 154 155 static const struct parent_map parents_l3_clk_src_map[] = { 156 { P_XO, 0 }, 157 { P_GPLL0, 4 }, 158 { P_L3_PLL, 5 }, 159 }; 160 161 static const struct freq_tbl ftbl_l3_clk_src[] = { 162 F(816000000, P_L3_PLL, 1, 0, 0), 163 F(984000000, P_L3_PLL, 1, 0, 0), 164 F(1272000000, P_L3_PLL, 1, 0, 0), 165 { } 166 }; 167 168 static struct clk_rcg2 l3_clk_src = { 169 .cmd_rcgr = 0x10080, 170 .freq_tbl = ftbl_l3_clk_src, 171 .hid_width = 5, 172 .parent_map = parents_l3_clk_src_map, 173 .clkr.hw.init = &(struct clk_init_data) { 174 .name = "l3_clk_src", 175 .parent_data = parents_l3_clk_src, 176 .num_parents = ARRAY_SIZE(parents_l3_clk_src), 177 .ops = &clk_rcg2_ops, 178 .flags = CLK_SET_RATE_PARENT, 179 }, 180 }; 181 182 static struct clk_branch l3_core_clk = { 183 .halt_reg = 0x1008c, 184 .clkr = { 185 .enable_reg = 0x1008c, 186 .enable_mask = BIT(0), 187 .hw.init = &(struct clk_init_data) { 188 .name = "l3_clk", 189 .parent_hws = (const struct clk_hw *[]) { 190 &l3_clk_src.clkr.hw 191 }, 192 .num_parents = 1, 193 .flags = CLK_SET_RATE_PARENT | CLK_IS_CRITICAL, 194 .ops = &clk_branch2_ops, 195 }, 196 }, 197 }; 198 199 static const struct regmap_config apss_ipq5424_regmap_config = { 200 .reg_bits = 32, 201 .reg_stride = 4, 202 .val_bits = 32, 203 .max_register = 0x20000, 204 .fast_io = true, 205 }; 206 207 static struct clk_regmap *apss_ipq5424_clks[] = { 208 [APSS_PLL_EARLY] = &ipq5424_apss_pll.clkr, 209 [APSS_SILVER_CLK_SRC] = &apss_silver_clk_src.clkr, 210 [APSS_SILVER_CORE_CLK] = &apss_silver_core_clk.clkr, 211 [L3_PLL] = &ipq5424_l3_pll.clkr, 212 [L3_CLK_SRC] = &l3_clk_src.clkr, 213 [L3_CORE_CLK] = &l3_core_clk.clkr, 214 }; 215 216 static struct clk_alpha_pll *ipa5424_apss_plls[] = { 217 &ipq5424_l3_pll, 218 &ipq5424_apss_pll, 219 }; 220 221 static struct qcom_cc_driver_data ipa5424_apss_driver_data = { 222 .alpha_plls = ipa5424_apss_plls, 223 .num_alpha_plls = ARRAY_SIZE(ipa5424_apss_plls), 224 }; 225 226 #define IPQ_APPS_PLL_ID (5424 * 3) /* some unique value */ 227 228 static const struct qcom_icc_hws_data icc_ipq5424_cpu_l3[] = { 229 { MASTER_CPU, SLAVE_L3, L3_CORE_CLK }, 230 }; 231 232 static const struct qcom_cc_desc apss_ipq5424_desc = { 233 .config = &apss_ipq5424_regmap_config, 234 .clks = apss_ipq5424_clks, 235 .num_clks = ARRAY_SIZE(apss_ipq5424_clks), 236 .icc_hws = icc_ipq5424_cpu_l3, 237 .num_icc_hws = ARRAY_SIZE(icc_ipq5424_cpu_l3), 238 .icc_first_node_id = IPQ_APPS_PLL_ID, 239 .driver_data = &ipa5424_apss_driver_data, 240 }; 241 242 static int apss_ipq5424_probe(struct platform_device *pdev) 243 { 244 return qcom_cc_probe(pdev, &apss_ipq5424_desc); 245 } 246 247 static const struct of_device_id apss_ipq5424_match_table[] = { 248 { .compatible = "qcom,ipq5424-apss-clk" }, 249 { } 250 }; 251 MODULE_DEVICE_TABLE(of, apss_ipq5424_match_table); 252 253 static struct platform_driver apss_ipq5424_driver = { 254 .probe = apss_ipq5424_probe, 255 .driver = { 256 .name = "apss-ipq5424-clk", 257 .of_match_table = apss_ipq5424_match_table, 258 .sync_state = icc_sync_state, 259 }, 260 }; 261 262 module_platform_driver(apss_ipq5424_driver); 263 264 MODULE_DESCRIPTION("QCOM APSS IPQ5424 CLK Driver"); 265 MODULE_LICENSE("GPL"); 266