1 // SPDX-License-Identifier: GPL-2.0-only 2 /* 3 * Copyright (c) 2014, The Linux Foundation. All rights reserved. 4 */ 5 6 #include <linux/kernel.h> 7 #include <linux/bitops.h> 8 #include <linux/err.h> 9 #include <linux/platform_device.h> 10 #include <linux/module.h> 11 #include <linux/of.h> 12 #include <linux/of_device.h> 13 #include <linux/clk-provider.h> 14 #include <linux/regmap.h> 15 16 #include <dt-bindings/clock/qcom,lcc-msm8960.h> 17 18 #include "common.h" 19 #include "clk-regmap.h" 20 #include "clk-pll.h" 21 #include "clk-rcg.h" 22 #include "clk-branch.h" 23 #include "clk-regmap-divider.h" 24 #include "clk-regmap-mux.h" 25 26 static struct clk_pll pll4 = { 27 .l_reg = 0x4, 28 .m_reg = 0x8, 29 .n_reg = 0xc, 30 .config_reg = 0x14, 31 .mode_reg = 0x0, 32 .status_reg = 0x18, 33 .status_bit = 16, 34 .clkr.hw.init = &(struct clk_init_data){ 35 .name = "pll4", 36 .parent_data = (const struct clk_parent_data[]){ 37 { .fw_name = "pxo", .name = "pxo_board" }, 38 }, 39 .num_parents = 1, 40 .ops = &clk_pll_ops, 41 }, 42 }; 43 44 enum { 45 P_PXO, 46 P_PLL4, 47 }; 48 49 static const struct parent_map lcc_pxo_pll4_map[] = { 50 { P_PXO, 0 }, 51 { P_PLL4, 2 } 52 }; 53 54 static const struct clk_parent_data lcc_pxo_pll4[] = { 55 { .fw_name = "pxo", .name = "pxo_board" }, 56 { .fw_name = "pll4_vote", .name = "pll4_vote" }, 57 }; 58 59 static struct freq_tbl clk_tbl_aif_osr_492[] = { 60 { 512000, P_PLL4, 4, 1, 240 }, 61 { 768000, P_PLL4, 4, 1, 160 }, 62 { 1024000, P_PLL4, 4, 1, 120 }, 63 { 1536000, P_PLL4, 4, 1, 80 }, 64 { 2048000, P_PLL4, 4, 1, 60 }, 65 { 3072000, P_PLL4, 4, 1, 40 }, 66 { 4096000, P_PLL4, 4, 1, 30 }, 67 { 6144000, P_PLL4, 4, 1, 20 }, 68 { 8192000, P_PLL4, 4, 1, 15 }, 69 { 12288000, P_PLL4, 4, 1, 10 }, 70 { 24576000, P_PLL4, 4, 1, 5 }, 71 { 27000000, P_PXO, 1, 0, 0 }, 72 { } 73 }; 74 75 static struct freq_tbl clk_tbl_aif_osr_393[] = { 76 { 512000, P_PLL4, 4, 1, 192 }, 77 { 768000, P_PLL4, 4, 1, 128 }, 78 { 1024000, P_PLL4, 4, 1, 96 }, 79 { 1536000, P_PLL4, 4, 1, 64 }, 80 { 2048000, P_PLL4, 4, 1, 48 }, 81 { 3072000, P_PLL4, 4, 1, 32 }, 82 { 4096000, P_PLL4, 4, 1, 24 }, 83 { 6144000, P_PLL4, 4, 1, 16 }, 84 { 8192000, P_PLL4, 4, 1, 12 }, 85 { 12288000, P_PLL4, 4, 1, 8 }, 86 { 24576000, P_PLL4, 4, 1, 4 }, 87 { 27000000, P_PXO, 1, 0, 0 }, 88 { } 89 }; 90 91 #define CLK_AIF_OSR_SRC(prefix, _ns, _md) \ 92 static struct clk_rcg prefix##_osr_src = { \ 93 .ns_reg = _ns, \ 94 .md_reg = _md, \ 95 .mn = { \ 96 .mnctr_en_bit = 8, \ 97 .mnctr_reset_bit = 7, \ 98 .mnctr_mode_shift = 5, \ 99 .n_val_shift = 24, \ 100 .m_val_shift = 8, \ 101 .width = 8, \ 102 }, \ 103 .p = { \ 104 .pre_div_shift = 3, \ 105 .pre_div_width = 2, \ 106 }, \ 107 .s = { \ 108 .src_sel_shift = 0, \ 109 .parent_map = lcc_pxo_pll4_map, \ 110 }, \ 111 .freq_tbl = clk_tbl_aif_osr_393, \ 112 .clkr = { \ 113 .enable_reg = _ns, \ 114 .enable_mask = BIT(9), \ 115 .hw.init = &(struct clk_init_data){ \ 116 .name = #prefix "_osr_src", \ 117 .parent_data = lcc_pxo_pll4, \ 118 .num_parents = ARRAY_SIZE(lcc_pxo_pll4), \ 119 .ops = &clk_rcg_ops, \ 120 .flags = CLK_SET_RATE_GATE, \ 121 }, \ 122 }, \ 123 }; \ 124 125 #define CLK_AIF_OSR_CLK(prefix, _ns, hr, en_bit) \ 126 static struct clk_branch prefix##_osr_clk = { \ 127 .halt_reg = hr, \ 128 .halt_bit = 1, \ 129 .halt_check = BRANCH_HALT_ENABLE, \ 130 .clkr = { \ 131 .enable_reg = _ns, \ 132 .enable_mask = BIT(en_bit), \ 133 .hw.init = &(struct clk_init_data){ \ 134 .name = #prefix "_osr_clk", \ 135 .parent_hws = (const struct clk_hw*[]){ \ 136 &prefix##_osr_src.clkr.hw, \ 137 }, \ 138 .num_parents = 1, \ 139 .ops = &clk_branch_ops, \ 140 .flags = CLK_SET_RATE_PARENT, \ 141 }, \ 142 }, \ 143 }; \ 144 145 #define CLK_AIF_OSR_DIV_CLK(prefix, _ns, _width) \ 146 static struct clk_regmap_div prefix##_div_clk = { \ 147 .reg = _ns, \ 148 .shift = 10, \ 149 .width = _width, \ 150 .clkr = { \ 151 .hw.init = &(struct clk_init_data){ \ 152 .name = #prefix "_div_clk", \ 153 .parent_hws = (const struct clk_hw*[]){ \ 154 &prefix##_osr_src.clkr.hw, \ 155 }, \ 156 .num_parents = 1, \ 157 .ops = &clk_regmap_div_ops, \ 158 }, \ 159 }, \ 160 }; \ 161 162 #define CLK_AIF_OSR_BIT_DIV_CLK(prefix, _ns, hr, en_bit) \ 163 static struct clk_branch prefix##_bit_div_clk = { \ 164 .halt_reg = hr, \ 165 .halt_bit = 0, \ 166 .halt_check = BRANCH_HALT_ENABLE, \ 167 .clkr = { \ 168 .enable_reg = _ns, \ 169 .enable_mask = BIT(en_bit), \ 170 .hw.init = &(struct clk_init_data){ \ 171 .name = #prefix "_bit_div_clk", \ 172 .parent_hws = (const struct clk_hw*[]){ \ 173 &prefix##_div_clk.clkr.hw, \ 174 }, \ 175 .num_parents = 1, \ 176 .ops = &clk_branch_ops, \ 177 .flags = CLK_SET_RATE_PARENT, \ 178 }, \ 179 }, \ 180 }; \ 181 182 #define CLK_AIF_OSR_BIT_CLK(prefix, _ns, _shift) \ 183 static struct clk_regmap_mux prefix##_bit_clk = { \ 184 .reg = _ns, \ 185 .shift = _shift, \ 186 .width = 1, \ 187 .clkr = { \ 188 .hw.init = &(struct clk_init_data){ \ 189 .name = #prefix "_bit_clk", \ 190 .parent_data = (const struct clk_parent_data[]){ \ 191 { .hw = &prefix##_bit_div_clk.clkr.hw, }, \ 192 { .fw_name = #prefix "_codec_clk", \ 193 .name = #prefix "_codec_clk", }, \ 194 }, \ 195 .num_parents = 2, \ 196 .ops = &clk_regmap_mux_closest_ops, \ 197 .flags = CLK_SET_RATE_PARENT, \ 198 }, \ 199 }, \ 200 }; 201 202 CLK_AIF_OSR_SRC(mi2s, 0x48, 0x4c) 203 CLK_AIF_OSR_CLK(mi2s, 0x48, 0x50, 17) 204 CLK_AIF_OSR_DIV_CLK(mi2s, 0x48, 4) 205 CLK_AIF_OSR_BIT_DIV_CLK(mi2s, 0x48, 0x50, 15) 206 CLK_AIF_OSR_BIT_CLK(mi2s, 0x48, 14) 207 208 #define CLK_AIF_OSR_DIV(prefix, _ns, _md, hr) \ 209 CLK_AIF_OSR_SRC(prefix, _ns, _md) \ 210 CLK_AIF_OSR_CLK(prefix, _ns, hr, 21) \ 211 CLK_AIF_OSR_DIV_CLK(prefix, _ns, 8) \ 212 CLK_AIF_OSR_BIT_DIV_CLK(prefix, _ns, hr, 19) \ 213 CLK_AIF_OSR_BIT_CLK(prefix, _ns, 18) 214 215 CLK_AIF_OSR_DIV(codec_i2s_mic, 0x60, 0x64, 0x68); 216 CLK_AIF_OSR_DIV(spare_i2s_mic, 0x78, 0x7c, 0x80); 217 CLK_AIF_OSR_DIV(codec_i2s_spkr, 0x6c, 0x70, 0x74); 218 CLK_AIF_OSR_DIV(spare_i2s_spkr, 0x84, 0x88, 0x8c); 219 220 static struct freq_tbl clk_tbl_pcm_492[] = { 221 { 256000, P_PLL4, 4, 1, 480 }, 222 { 512000, P_PLL4, 4, 1, 240 }, 223 { 768000, P_PLL4, 4, 1, 160 }, 224 { 1024000, P_PLL4, 4, 1, 120 }, 225 { 1536000, P_PLL4, 4, 1, 80 }, 226 { 2048000, P_PLL4, 4, 1, 60 }, 227 { 3072000, P_PLL4, 4, 1, 40 }, 228 { 4096000, P_PLL4, 4, 1, 30 }, 229 { 6144000, P_PLL4, 4, 1, 20 }, 230 { 8192000, P_PLL4, 4, 1, 15 }, 231 { 12288000, P_PLL4, 4, 1, 10 }, 232 { 24576000, P_PLL4, 4, 1, 5 }, 233 { 27000000, P_PXO, 1, 0, 0 }, 234 { } 235 }; 236 237 static struct freq_tbl clk_tbl_pcm_393[] = { 238 { 256000, P_PLL4, 4, 1, 384 }, 239 { 512000, P_PLL4, 4, 1, 192 }, 240 { 768000, P_PLL4, 4, 1, 128 }, 241 { 1024000, P_PLL4, 4, 1, 96 }, 242 { 1536000, P_PLL4, 4, 1, 64 }, 243 { 2048000, P_PLL4, 4, 1, 48 }, 244 { 3072000, P_PLL4, 4, 1, 32 }, 245 { 4096000, P_PLL4, 4, 1, 24 }, 246 { 6144000, P_PLL4, 4, 1, 16 }, 247 { 8192000, P_PLL4, 4, 1, 12 }, 248 { 12288000, P_PLL4, 4, 1, 8 }, 249 { 24576000, P_PLL4, 4, 1, 4 }, 250 { 27000000, P_PXO, 1, 0, 0 }, 251 { } 252 }; 253 254 static struct clk_rcg pcm_src = { 255 .ns_reg = 0x54, 256 .md_reg = 0x58, 257 .mn = { 258 .mnctr_en_bit = 8, 259 .mnctr_reset_bit = 7, 260 .mnctr_mode_shift = 5, 261 .n_val_shift = 16, 262 .m_val_shift = 16, 263 .width = 16, 264 }, 265 .p = { 266 .pre_div_shift = 3, 267 .pre_div_width = 2, 268 }, 269 .s = { 270 .src_sel_shift = 0, 271 .parent_map = lcc_pxo_pll4_map, 272 }, 273 .freq_tbl = clk_tbl_pcm_393, 274 .clkr = { 275 .enable_reg = 0x54, 276 .enable_mask = BIT(9), 277 .hw.init = &(struct clk_init_data){ 278 .name = "pcm_src", 279 .parent_data = lcc_pxo_pll4, 280 .num_parents = ARRAY_SIZE(lcc_pxo_pll4), 281 .ops = &clk_rcg_ops, 282 .flags = CLK_SET_RATE_GATE, 283 }, 284 }, 285 }; 286 287 static struct clk_branch pcm_clk_out = { 288 .halt_reg = 0x5c, 289 .halt_bit = 0, 290 .halt_check = BRANCH_HALT_ENABLE, 291 .clkr = { 292 .enable_reg = 0x54, 293 .enable_mask = BIT(11), 294 .hw.init = &(struct clk_init_data){ 295 .name = "pcm_clk_out", 296 .parent_hws = (const struct clk_hw*[]){ 297 &pcm_src.clkr.hw 298 }, 299 .num_parents = 1, 300 .ops = &clk_branch_ops, 301 .flags = CLK_SET_RATE_PARENT, 302 }, 303 }, 304 }; 305 306 static struct clk_regmap_mux pcm_clk = { 307 .reg = 0x54, 308 .shift = 10, 309 .width = 1, 310 .clkr = { 311 .hw.init = &(struct clk_init_data){ 312 .name = "pcm_clk", 313 .parent_data = (const struct clk_parent_data[]){ 314 { .hw = &pcm_clk_out.clkr.hw }, 315 { .fw_name = "pcm_codec_clk", .name = "pcm_codec_clk" }, 316 }, 317 .num_parents = 2, 318 .ops = &clk_regmap_mux_closest_ops, 319 .flags = CLK_SET_RATE_PARENT, 320 }, 321 }, 322 }; 323 324 static struct clk_rcg slimbus_src = { 325 .ns_reg = 0xcc, 326 .md_reg = 0xd0, 327 .mn = { 328 .mnctr_en_bit = 8, 329 .mnctr_reset_bit = 7, 330 .mnctr_mode_shift = 5, 331 .n_val_shift = 24, 332 .m_val_shift = 8, 333 .width = 8, 334 }, 335 .p = { 336 .pre_div_shift = 3, 337 .pre_div_width = 2, 338 }, 339 .s = { 340 .src_sel_shift = 0, 341 .parent_map = lcc_pxo_pll4_map, 342 }, 343 .freq_tbl = clk_tbl_aif_osr_393, 344 .clkr = { 345 .enable_reg = 0xcc, 346 .enable_mask = BIT(9), 347 .hw.init = &(struct clk_init_data){ 348 .name = "slimbus_src", 349 .parent_data = lcc_pxo_pll4, 350 .num_parents = ARRAY_SIZE(lcc_pxo_pll4), 351 .ops = &clk_rcg_ops, 352 .flags = CLK_SET_RATE_GATE, 353 }, 354 }, 355 }; 356 357 static struct clk_branch audio_slimbus_clk = { 358 .halt_reg = 0xd4, 359 .halt_bit = 0, 360 .halt_check = BRANCH_HALT_ENABLE, 361 .clkr = { 362 .enable_reg = 0xcc, 363 .enable_mask = BIT(10), 364 .hw.init = &(struct clk_init_data){ 365 .name = "audio_slimbus_clk", 366 .parent_hws = (const struct clk_hw*[]){ 367 &slimbus_src.clkr.hw, 368 }, 369 .num_parents = 1, 370 .ops = &clk_branch_ops, 371 .flags = CLK_SET_RATE_PARENT, 372 }, 373 }, 374 }; 375 376 static struct clk_branch sps_slimbus_clk = { 377 .halt_reg = 0xd4, 378 .halt_bit = 1, 379 .halt_check = BRANCH_HALT_ENABLE, 380 .clkr = { 381 .enable_reg = 0xcc, 382 .enable_mask = BIT(12), 383 .hw.init = &(struct clk_init_data){ 384 .name = "sps_slimbus_clk", 385 .parent_hws = (const struct clk_hw*[]){ 386 &slimbus_src.clkr.hw, 387 }, 388 .num_parents = 1, 389 .ops = &clk_branch_ops, 390 .flags = CLK_SET_RATE_PARENT, 391 }, 392 }, 393 }; 394 395 static struct clk_regmap *lcc_msm8960_clks[] = { 396 [PLL4] = &pll4.clkr, 397 [MI2S_OSR_SRC] = &mi2s_osr_src.clkr, 398 [MI2S_OSR_CLK] = &mi2s_osr_clk.clkr, 399 [MI2S_DIV_CLK] = &mi2s_div_clk.clkr, 400 [MI2S_BIT_DIV_CLK] = &mi2s_bit_div_clk.clkr, 401 [MI2S_BIT_CLK] = &mi2s_bit_clk.clkr, 402 [PCM_SRC] = &pcm_src.clkr, 403 [PCM_CLK_OUT] = &pcm_clk_out.clkr, 404 [PCM_CLK] = &pcm_clk.clkr, 405 [SLIMBUS_SRC] = &slimbus_src.clkr, 406 [AUDIO_SLIMBUS_CLK] = &audio_slimbus_clk.clkr, 407 [SPS_SLIMBUS_CLK] = &sps_slimbus_clk.clkr, 408 [CODEC_I2S_MIC_OSR_SRC] = &codec_i2s_mic_osr_src.clkr, 409 [CODEC_I2S_MIC_OSR_CLK] = &codec_i2s_mic_osr_clk.clkr, 410 [CODEC_I2S_MIC_DIV_CLK] = &codec_i2s_mic_div_clk.clkr, 411 [CODEC_I2S_MIC_BIT_DIV_CLK] = &codec_i2s_mic_bit_div_clk.clkr, 412 [CODEC_I2S_MIC_BIT_CLK] = &codec_i2s_mic_bit_clk.clkr, 413 [SPARE_I2S_MIC_OSR_SRC] = &spare_i2s_mic_osr_src.clkr, 414 [SPARE_I2S_MIC_OSR_CLK] = &spare_i2s_mic_osr_clk.clkr, 415 [SPARE_I2S_MIC_DIV_CLK] = &spare_i2s_mic_div_clk.clkr, 416 [SPARE_I2S_MIC_BIT_DIV_CLK] = &spare_i2s_mic_bit_div_clk.clkr, 417 [SPARE_I2S_MIC_BIT_CLK] = &spare_i2s_mic_bit_clk.clkr, 418 [CODEC_I2S_SPKR_OSR_SRC] = &codec_i2s_spkr_osr_src.clkr, 419 [CODEC_I2S_SPKR_OSR_CLK] = &codec_i2s_spkr_osr_clk.clkr, 420 [CODEC_I2S_SPKR_DIV_CLK] = &codec_i2s_spkr_div_clk.clkr, 421 [CODEC_I2S_SPKR_BIT_DIV_CLK] = &codec_i2s_spkr_bit_div_clk.clkr, 422 [CODEC_I2S_SPKR_BIT_CLK] = &codec_i2s_spkr_bit_clk.clkr, 423 [SPARE_I2S_SPKR_OSR_SRC] = &spare_i2s_spkr_osr_src.clkr, 424 [SPARE_I2S_SPKR_OSR_CLK] = &spare_i2s_spkr_osr_clk.clkr, 425 [SPARE_I2S_SPKR_DIV_CLK] = &spare_i2s_spkr_div_clk.clkr, 426 [SPARE_I2S_SPKR_BIT_DIV_CLK] = &spare_i2s_spkr_bit_div_clk.clkr, 427 [SPARE_I2S_SPKR_BIT_CLK] = &spare_i2s_spkr_bit_clk.clkr, 428 }; 429 430 static const struct regmap_config lcc_msm8960_regmap_config = { 431 .reg_bits = 32, 432 .reg_stride = 4, 433 .val_bits = 32, 434 .max_register = 0xfc, 435 .fast_io = true, 436 }; 437 438 static const struct qcom_cc_desc lcc_msm8960_desc = { 439 .config = &lcc_msm8960_regmap_config, 440 .clks = lcc_msm8960_clks, 441 .num_clks = ARRAY_SIZE(lcc_msm8960_clks), 442 }; 443 444 static const struct of_device_id lcc_msm8960_match_table[] = { 445 { .compatible = "qcom,lcc-msm8960" }, 446 { .compatible = "qcom,lcc-apq8064" }, 447 { } 448 }; 449 MODULE_DEVICE_TABLE(of, lcc_msm8960_match_table); 450 451 static int lcc_msm8960_probe(struct platform_device *pdev) 452 { 453 u32 val; 454 struct regmap *regmap; 455 456 regmap = qcom_cc_map(pdev, &lcc_msm8960_desc); 457 if (IS_ERR(regmap)) 458 return PTR_ERR(regmap); 459 460 /* Use the correct frequency plan depending on speed of PLL4 */ 461 regmap_read(regmap, 0x4, &val); 462 if (val == 0x12) { 463 slimbus_src.freq_tbl = clk_tbl_aif_osr_492; 464 mi2s_osr_src.freq_tbl = clk_tbl_aif_osr_492; 465 codec_i2s_mic_osr_src.freq_tbl = clk_tbl_aif_osr_492; 466 spare_i2s_mic_osr_src.freq_tbl = clk_tbl_aif_osr_492; 467 codec_i2s_spkr_osr_src.freq_tbl = clk_tbl_aif_osr_492; 468 spare_i2s_spkr_osr_src.freq_tbl = clk_tbl_aif_osr_492; 469 pcm_src.freq_tbl = clk_tbl_pcm_492; 470 } 471 /* Enable PLL4 source on the LPASS Primary PLL Mux */ 472 regmap_write(regmap, 0xc4, 0x1); 473 474 return qcom_cc_really_probe(pdev, &lcc_msm8960_desc, regmap); 475 } 476 477 static struct platform_driver lcc_msm8960_driver = { 478 .probe = lcc_msm8960_probe, 479 .driver = { 480 .name = "lcc-msm8960", 481 .of_match_table = lcc_msm8960_match_table, 482 }, 483 }; 484 module_platform_driver(lcc_msm8960_driver); 485 486 MODULE_DESCRIPTION("QCOM LCC MSM8960 Driver"); 487 MODULE_LICENSE("GPL v2"); 488 MODULE_ALIAS("platform:lcc-msm8960"); 489