0001
0002
0003
0004
0005
0006
0007
0008 #include <linux/kernel.h>
0009 #include <linux/bitops.h>
0010 #include <linux/err.h>
0011 #include <linux/platform_device.h>
0012 #include <linux/module.h>
0013 #include <linux/of.h>
0014 #include <linux/of_device.h>
0015 #include <linux/clk-provider.h>
0016 #include <linux/regmap.h>
0017
0018 #include <dt-bindings/clock/qcom,lcc-mdm9615.h>
0019
0020 #include "common.h"
0021 #include "clk-regmap.h"
0022 #include "clk-pll.h"
0023 #include "clk-rcg.h"
0024 #include "clk-branch.h"
0025 #include "clk-regmap-divider.h"
0026 #include "clk-regmap-mux.h"
0027
0028 static struct clk_pll pll4 = {
0029 .l_reg = 0x4,
0030 .m_reg = 0x8,
0031 .n_reg = 0xc,
0032 .config_reg = 0x14,
0033 .mode_reg = 0x0,
0034 .status_reg = 0x18,
0035 .status_bit = 16,
0036 .clkr.hw.init = &(struct clk_init_data){
0037 .name = "pll4",
0038 .parent_names = (const char *[]){ "cxo" },
0039 .num_parents = 1,
0040 .ops = &clk_pll_ops,
0041 },
0042 };
0043
0044 enum {
0045 P_CXO,
0046 P_PLL4,
0047 };
0048
0049 static const struct parent_map lcc_cxo_pll4_map[] = {
0050 { P_CXO, 0 },
0051 { P_PLL4, 2 }
0052 };
0053
0054 static const char * const lcc_cxo_pll4[] = {
0055 "cxo",
0056 "pll4_vote",
0057 };
0058
0059 static struct freq_tbl clk_tbl_aif_osr_492[] = {
0060 { 512000, P_PLL4, 4, 1, 240 },
0061 { 768000, P_PLL4, 4, 1, 160 },
0062 { 1024000, P_PLL4, 4, 1, 120 },
0063 { 1536000, P_PLL4, 4, 1, 80 },
0064 { 2048000, P_PLL4, 4, 1, 60 },
0065 { 3072000, P_PLL4, 4, 1, 40 },
0066 { 4096000, P_PLL4, 4, 1, 30 },
0067 { 6144000, P_PLL4, 4, 1, 20 },
0068 { 8192000, P_PLL4, 4, 1, 15 },
0069 { 12288000, P_PLL4, 4, 1, 10 },
0070 { 24576000, P_PLL4, 4, 1, 5 },
0071 { 27000000, P_CXO, 1, 0, 0 },
0072 { }
0073 };
0074
0075 static struct freq_tbl clk_tbl_aif_osr_393[] = {
0076 { 512000, P_PLL4, 4, 1, 192 },
0077 { 768000, P_PLL4, 4, 1, 128 },
0078 { 1024000, P_PLL4, 4, 1, 96 },
0079 { 1536000, P_PLL4, 4, 1, 64 },
0080 { 2048000, P_PLL4, 4, 1, 48 },
0081 { 3072000, P_PLL4, 4, 1, 32 },
0082 { 4096000, P_PLL4, 4, 1, 24 },
0083 { 6144000, P_PLL4, 4, 1, 16 },
0084 { 8192000, P_PLL4, 4, 1, 12 },
0085 { 12288000, P_PLL4, 4, 1, 8 },
0086 { 24576000, P_PLL4, 4, 1, 4 },
0087 { 27000000, P_CXO, 1, 0, 0 },
0088 { }
0089 };
0090
0091 static struct clk_rcg mi2s_osr_src = {
0092 .ns_reg = 0x48,
0093 .md_reg = 0x4c,
0094 .mn = {
0095 .mnctr_en_bit = 8,
0096 .mnctr_reset_bit = 7,
0097 .mnctr_mode_shift = 5,
0098 .n_val_shift = 24,
0099 .m_val_shift = 8,
0100 .width = 8,
0101 },
0102 .p = {
0103 .pre_div_shift = 3,
0104 .pre_div_width = 2,
0105 },
0106 .s = {
0107 .src_sel_shift = 0,
0108 .parent_map = lcc_cxo_pll4_map,
0109 },
0110 .freq_tbl = clk_tbl_aif_osr_393,
0111 .clkr = {
0112 .enable_reg = 0x48,
0113 .enable_mask = BIT(9),
0114 .hw.init = &(struct clk_init_data){
0115 .name = "mi2s_osr_src",
0116 .parent_names = lcc_cxo_pll4,
0117 .num_parents = 2,
0118 .ops = &clk_rcg_ops,
0119 .flags = CLK_SET_RATE_GATE,
0120 },
0121 },
0122 };
0123
0124 static const char * const lcc_mi2s_parents[] = {
0125 "mi2s_osr_src",
0126 };
0127
0128 static struct clk_branch mi2s_osr_clk = {
0129 .halt_reg = 0x50,
0130 .halt_bit = 1,
0131 .halt_check = BRANCH_HALT_ENABLE,
0132 .clkr = {
0133 .enable_reg = 0x48,
0134 .enable_mask = BIT(17),
0135 .hw.init = &(struct clk_init_data){
0136 .name = "mi2s_osr_clk",
0137 .parent_names = lcc_mi2s_parents,
0138 .num_parents = 1,
0139 .ops = &clk_branch_ops,
0140 .flags = CLK_SET_RATE_PARENT,
0141 },
0142 },
0143 };
0144
0145 static struct clk_regmap_div mi2s_div_clk = {
0146 .reg = 0x48,
0147 .shift = 10,
0148 .width = 4,
0149 .clkr = {
0150 .enable_reg = 0x48,
0151 .enable_mask = BIT(15),
0152 .hw.init = &(struct clk_init_data){
0153 .name = "mi2s_div_clk",
0154 .parent_names = lcc_mi2s_parents,
0155 .num_parents = 1,
0156 .ops = &clk_regmap_div_ops,
0157 },
0158 },
0159 };
0160
0161 static struct clk_branch mi2s_bit_div_clk = {
0162 .halt_reg = 0x50,
0163 .halt_bit = 0,
0164 .halt_check = BRANCH_HALT_ENABLE,
0165 .clkr = {
0166 .enable_reg = 0x48,
0167 .enable_mask = BIT(15),
0168 .hw.init = &(struct clk_init_data){
0169 .name = "mi2s_bit_div_clk",
0170 .parent_names = (const char *[]){ "mi2s_div_clk" },
0171 .num_parents = 1,
0172 .ops = &clk_branch_ops,
0173 .flags = CLK_SET_RATE_PARENT,
0174 },
0175 },
0176 };
0177
0178 static struct clk_regmap_mux mi2s_bit_clk = {
0179 .reg = 0x48,
0180 .shift = 14,
0181 .width = 1,
0182 .clkr = {
0183 .hw.init = &(struct clk_init_data){
0184 .name = "mi2s_bit_clk",
0185 .parent_names = (const char *[]){
0186 "mi2s_bit_div_clk",
0187 "mi2s_codec_clk",
0188 },
0189 .num_parents = 2,
0190 .ops = &clk_regmap_mux_closest_ops,
0191 .flags = CLK_SET_RATE_PARENT,
0192 },
0193 },
0194 };
0195
0196 #define CLK_AIF_OSR_DIV(prefix, _ns, _md, hr) \
0197 static struct clk_rcg prefix##_osr_src = { \
0198 .ns_reg = _ns, \
0199 .md_reg = _md, \
0200 .mn = { \
0201 .mnctr_en_bit = 8, \
0202 .mnctr_reset_bit = 7, \
0203 .mnctr_mode_shift = 5, \
0204 .n_val_shift = 24, \
0205 .m_val_shift = 8, \
0206 .width = 8, \
0207 }, \
0208 .p = { \
0209 .pre_div_shift = 3, \
0210 .pre_div_width = 2, \
0211 }, \
0212 .s = { \
0213 .src_sel_shift = 0, \
0214 .parent_map = lcc_cxo_pll4_map, \
0215 }, \
0216 .freq_tbl = clk_tbl_aif_osr_393, \
0217 .clkr = { \
0218 .enable_reg = _ns, \
0219 .enable_mask = BIT(9), \
0220 .hw.init = &(struct clk_init_data){ \
0221 .name = #prefix "_osr_src", \
0222 .parent_names = lcc_cxo_pll4, \
0223 .num_parents = 2, \
0224 .ops = &clk_rcg_ops, \
0225 .flags = CLK_SET_RATE_GATE, \
0226 }, \
0227 }, \
0228 }; \
0229 \
0230 static const char * const lcc_##prefix##_parents[] = { \
0231 #prefix "_osr_src", \
0232 }; \
0233 \
0234 static struct clk_branch prefix##_osr_clk = { \
0235 .halt_reg = hr, \
0236 .halt_bit = 1, \
0237 .halt_check = BRANCH_HALT_ENABLE, \
0238 .clkr = { \
0239 .enable_reg = _ns, \
0240 .enable_mask = BIT(21), \
0241 .hw.init = &(struct clk_init_data){ \
0242 .name = #prefix "_osr_clk", \
0243 .parent_names = lcc_##prefix##_parents, \
0244 .num_parents = 1, \
0245 .ops = &clk_branch_ops, \
0246 .flags = CLK_SET_RATE_PARENT, \
0247 }, \
0248 }, \
0249 }; \
0250 \
0251 static struct clk_regmap_div prefix##_div_clk = { \
0252 .reg = _ns, \
0253 .shift = 10, \
0254 .width = 8, \
0255 .clkr = { \
0256 .hw.init = &(struct clk_init_data){ \
0257 .name = #prefix "_div_clk", \
0258 .parent_names = lcc_##prefix##_parents, \
0259 .num_parents = 1, \
0260 .ops = &clk_regmap_div_ops, \
0261 }, \
0262 }, \
0263 }; \
0264 \
0265 static struct clk_branch prefix##_bit_div_clk = { \
0266 .halt_reg = hr, \
0267 .halt_bit = 0, \
0268 .halt_check = BRANCH_HALT_ENABLE, \
0269 .clkr = { \
0270 .enable_reg = _ns, \
0271 .enable_mask = BIT(19), \
0272 .hw.init = &(struct clk_init_data){ \
0273 .name = #prefix "_bit_div_clk", \
0274 .parent_names = (const char *[]){ \
0275 #prefix "_div_clk" \
0276 }, \
0277 .num_parents = 1, \
0278 .ops = &clk_branch_ops, \
0279 .flags = CLK_SET_RATE_PARENT, \
0280 }, \
0281 }, \
0282 }; \
0283 \
0284 static struct clk_regmap_mux prefix##_bit_clk = { \
0285 .reg = _ns, \
0286 .shift = 18, \
0287 .width = 1, \
0288 .clkr = { \
0289 .hw.init = &(struct clk_init_data){ \
0290 .name = #prefix "_bit_clk", \
0291 .parent_names = (const char *[]){ \
0292 #prefix "_bit_div_clk", \
0293 #prefix "_codec_clk", \
0294 }, \
0295 .num_parents = 2, \
0296 .ops = &clk_regmap_mux_closest_ops, \
0297 .flags = CLK_SET_RATE_PARENT, \
0298 }, \
0299 }, \
0300 }
0301
0302 CLK_AIF_OSR_DIV(codec_i2s_mic, 0x60, 0x64, 0x68);
0303 CLK_AIF_OSR_DIV(spare_i2s_mic, 0x78, 0x7c, 0x80);
0304 CLK_AIF_OSR_DIV(codec_i2s_spkr, 0x6c, 0x70, 0x74);
0305 CLK_AIF_OSR_DIV(spare_i2s_spkr, 0x84, 0x88, 0x8c);
0306
0307 static struct freq_tbl clk_tbl_pcm_492[] = {
0308 { 256000, P_PLL4, 4, 1, 480 },
0309 { 512000, P_PLL4, 4, 1, 240 },
0310 { 768000, P_PLL4, 4, 1, 160 },
0311 { 1024000, P_PLL4, 4, 1, 120 },
0312 { 1536000, P_PLL4, 4, 1, 80 },
0313 { 2048000, P_PLL4, 4, 1, 60 },
0314 { 3072000, P_PLL4, 4, 1, 40 },
0315 { 4096000, P_PLL4, 4, 1, 30 },
0316 { 6144000, P_PLL4, 4, 1, 20 },
0317 { 8192000, P_PLL4, 4, 1, 15 },
0318 { 12288000, P_PLL4, 4, 1, 10 },
0319 { 24576000, P_PLL4, 4, 1, 5 },
0320 { 27000000, P_CXO, 1, 0, 0 },
0321 { }
0322 };
0323
0324 static struct freq_tbl clk_tbl_pcm_393[] = {
0325 { 256000, P_PLL4, 4, 1, 384 },
0326 { 512000, P_PLL4, 4, 1, 192 },
0327 { 768000, P_PLL4, 4, 1, 128 },
0328 { 1024000, P_PLL4, 4, 1, 96 },
0329 { 1536000, P_PLL4, 4, 1, 64 },
0330 { 2048000, P_PLL4, 4, 1, 48 },
0331 { 3072000, P_PLL4, 4, 1, 32 },
0332 { 4096000, P_PLL4, 4, 1, 24 },
0333 { 6144000, P_PLL4, 4, 1, 16 },
0334 { 8192000, P_PLL4, 4, 1, 12 },
0335 { 12288000, P_PLL4, 4, 1, 8 },
0336 { 24576000, P_PLL4, 4, 1, 4 },
0337 { 27000000, P_CXO, 1, 0, 0 },
0338 { }
0339 };
0340
0341 static struct clk_rcg pcm_src = {
0342 .ns_reg = 0x54,
0343 .md_reg = 0x58,
0344 .mn = {
0345 .mnctr_en_bit = 8,
0346 .mnctr_reset_bit = 7,
0347 .mnctr_mode_shift = 5,
0348 .n_val_shift = 16,
0349 .m_val_shift = 16,
0350 .width = 16,
0351 },
0352 .p = {
0353 .pre_div_shift = 3,
0354 .pre_div_width = 2,
0355 },
0356 .s = {
0357 .src_sel_shift = 0,
0358 .parent_map = lcc_cxo_pll4_map,
0359 },
0360 .freq_tbl = clk_tbl_pcm_393,
0361 .clkr = {
0362 .enable_reg = 0x54,
0363 .enable_mask = BIT(9),
0364 .hw.init = &(struct clk_init_data){
0365 .name = "pcm_src",
0366 .parent_names = lcc_cxo_pll4,
0367 .num_parents = 2,
0368 .ops = &clk_rcg_ops,
0369 .flags = CLK_SET_RATE_GATE,
0370 },
0371 },
0372 };
0373
0374 static struct clk_branch pcm_clk_out = {
0375 .halt_reg = 0x5c,
0376 .halt_bit = 0,
0377 .halt_check = BRANCH_HALT_ENABLE,
0378 .clkr = {
0379 .enable_reg = 0x54,
0380 .enable_mask = BIT(11),
0381 .hw.init = &(struct clk_init_data){
0382 .name = "pcm_clk_out",
0383 .parent_names = (const char *[]){ "pcm_src" },
0384 .num_parents = 1,
0385 .ops = &clk_branch_ops,
0386 .flags = CLK_SET_RATE_PARENT,
0387 },
0388 },
0389 };
0390
0391 static struct clk_regmap_mux pcm_clk = {
0392 .reg = 0x54,
0393 .shift = 10,
0394 .width = 1,
0395 .clkr = {
0396 .hw.init = &(struct clk_init_data){
0397 .name = "pcm_clk",
0398 .parent_names = (const char *[]){
0399 "pcm_clk_out",
0400 "pcm_codec_clk",
0401 },
0402 .num_parents = 2,
0403 .ops = &clk_regmap_mux_closest_ops,
0404 .flags = CLK_SET_RATE_PARENT,
0405 },
0406 },
0407 };
0408
0409 static struct clk_rcg slimbus_src = {
0410 .ns_reg = 0xcc,
0411 .md_reg = 0xd0,
0412 .mn = {
0413 .mnctr_en_bit = 8,
0414 .mnctr_reset_bit = 7,
0415 .mnctr_mode_shift = 5,
0416 .n_val_shift = 24,
0417 .m_val_shift = 8,
0418 .width = 8,
0419 },
0420 .p = {
0421 .pre_div_shift = 3,
0422 .pre_div_width = 2,
0423 },
0424 .s = {
0425 .src_sel_shift = 0,
0426 .parent_map = lcc_cxo_pll4_map,
0427 },
0428 .freq_tbl = clk_tbl_aif_osr_393,
0429 .clkr = {
0430 .enable_reg = 0xcc,
0431 .enable_mask = BIT(9),
0432 .hw.init = &(struct clk_init_data){
0433 .name = "slimbus_src",
0434 .parent_names = lcc_cxo_pll4,
0435 .num_parents = 2,
0436 .ops = &clk_rcg_ops,
0437 .flags = CLK_SET_RATE_GATE,
0438 },
0439 },
0440 };
0441
0442 static const char * const lcc_slimbus_parents[] = {
0443 "slimbus_src",
0444 };
0445
0446 static struct clk_branch audio_slimbus_clk = {
0447 .halt_reg = 0xd4,
0448 .halt_bit = 0,
0449 .halt_check = BRANCH_HALT_ENABLE,
0450 .clkr = {
0451 .enable_reg = 0xcc,
0452 .enable_mask = BIT(10),
0453 .hw.init = &(struct clk_init_data){
0454 .name = "audio_slimbus_clk",
0455 .parent_names = lcc_slimbus_parents,
0456 .num_parents = 1,
0457 .ops = &clk_branch_ops,
0458 .flags = CLK_SET_RATE_PARENT,
0459 },
0460 },
0461 };
0462
0463 static struct clk_branch sps_slimbus_clk = {
0464 .halt_reg = 0xd4,
0465 .halt_bit = 1,
0466 .halt_check = BRANCH_HALT_ENABLE,
0467 .clkr = {
0468 .enable_reg = 0xcc,
0469 .enable_mask = BIT(12),
0470 .hw.init = &(struct clk_init_data){
0471 .name = "sps_slimbus_clk",
0472 .parent_names = lcc_slimbus_parents,
0473 .num_parents = 1,
0474 .ops = &clk_branch_ops,
0475 .flags = CLK_SET_RATE_PARENT,
0476 },
0477 },
0478 };
0479
0480 static struct clk_regmap *lcc_mdm9615_clks[] = {
0481 [PLL4] = &pll4.clkr,
0482 [MI2S_OSR_SRC] = &mi2s_osr_src.clkr,
0483 [MI2S_OSR_CLK] = &mi2s_osr_clk.clkr,
0484 [MI2S_DIV_CLK] = &mi2s_div_clk.clkr,
0485 [MI2S_BIT_DIV_CLK] = &mi2s_bit_div_clk.clkr,
0486 [MI2S_BIT_CLK] = &mi2s_bit_clk.clkr,
0487 [PCM_SRC] = &pcm_src.clkr,
0488 [PCM_CLK_OUT] = &pcm_clk_out.clkr,
0489 [PCM_CLK] = &pcm_clk.clkr,
0490 [SLIMBUS_SRC] = &slimbus_src.clkr,
0491 [AUDIO_SLIMBUS_CLK] = &audio_slimbus_clk.clkr,
0492 [SPS_SLIMBUS_CLK] = &sps_slimbus_clk.clkr,
0493 [CODEC_I2S_MIC_OSR_SRC] = &codec_i2s_mic_osr_src.clkr,
0494 [CODEC_I2S_MIC_OSR_CLK] = &codec_i2s_mic_osr_clk.clkr,
0495 [CODEC_I2S_MIC_DIV_CLK] = &codec_i2s_mic_div_clk.clkr,
0496 [CODEC_I2S_MIC_BIT_DIV_CLK] = &codec_i2s_mic_bit_div_clk.clkr,
0497 [CODEC_I2S_MIC_BIT_CLK] = &codec_i2s_mic_bit_clk.clkr,
0498 [SPARE_I2S_MIC_OSR_SRC] = &spare_i2s_mic_osr_src.clkr,
0499 [SPARE_I2S_MIC_OSR_CLK] = &spare_i2s_mic_osr_clk.clkr,
0500 [SPARE_I2S_MIC_DIV_CLK] = &spare_i2s_mic_div_clk.clkr,
0501 [SPARE_I2S_MIC_BIT_DIV_CLK] = &spare_i2s_mic_bit_div_clk.clkr,
0502 [SPARE_I2S_MIC_BIT_CLK] = &spare_i2s_mic_bit_clk.clkr,
0503 [CODEC_I2S_SPKR_OSR_SRC] = &codec_i2s_spkr_osr_src.clkr,
0504 [CODEC_I2S_SPKR_OSR_CLK] = &codec_i2s_spkr_osr_clk.clkr,
0505 [CODEC_I2S_SPKR_DIV_CLK] = &codec_i2s_spkr_div_clk.clkr,
0506 [CODEC_I2S_SPKR_BIT_DIV_CLK] = &codec_i2s_spkr_bit_div_clk.clkr,
0507 [CODEC_I2S_SPKR_BIT_CLK] = &codec_i2s_spkr_bit_clk.clkr,
0508 [SPARE_I2S_SPKR_OSR_SRC] = &spare_i2s_spkr_osr_src.clkr,
0509 [SPARE_I2S_SPKR_OSR_CLK] = &spare_i2s_spkr_osr_clk.clkr,
0510 [SPARE_I2S_SPKR_DIV_CLK] = &spare_i2s_spkr_div_clk.clkr,
0511 [SPARE_I2S_SPKR_BIT_DIV_CLK] = &spare_i2s_spkr_bit_div_clk.clkr,
0512 [SPARE_I2S_SPKR_BIT_CLK] = &spare_i2s_spkr_bit_clk.clkr,
0513 };
0514
0515 static const struct regmap_config lcc_mdm9615_regmap_config = {
0516 .reg_bits = 32,
0517 .reg_stride = 4,
0518 .val_bits = 32,
0519 .max_register = 0xfc,
0520 .fast_io = true,
0521 };
0522
0523 static const struct qcom_cc_desc lcc_mdm9615_desc = {
0524 .config = &lcc_mdm9615_regmap_config,
0525 .clks = lcc_mdm9615_clks,
0526 .num_clks = ARRAY_SIZE(lcc_mdm9615_clks),
0527 };
0528
0529 static const struct of_device_id lcc_mdm9615_match_table[] = {
0530 { .compatible = "qcom,lcc-mdm9615" },
0531 { }
0532 };
0533 MODULE_DEVICE_TABLE(of, lcc_mdm9615_match_table);
0534
0535 static int lcc_mdm9615_probe(struct platform_device *pdev)
0536 {
0537 u32 val;
0538 struct regmap *regmap;
0539
0540 regmap = qcom_cc_map(pdev, &lcc_mdm9615_desc);
0541 if (IS_ERR(regmap))
0542 return PTR_ERR(regmap);
0543
0544
0545 regmap_read(regmap, 0x4, &val);
0546 if (val == 0x12) {
0547 slimbus_src.freq_tbl = clk_tbl_aif_osr_492;
0548 mi2s_osr_src.freq_tbl = clk_tbl_aif_osr_492;
0549 codec_i2s_mic_osr_src.freq_tbl = clk_tbl_aif_osr_492;
0550 spare_i2s_mic_osr_src.freq_tbl = clk_tbl_aif_osr_492;
0551 codec_i2s_spkr_osr_src.freq_tbl = clk_tbl_aif_osr_492;
0552 spare_i2s_spkr_osr_src.freq_tbl = clk_tbl_aif_osr_492;
0553 pcm_src.freq_tbl = clk_tbl_pcm_492;
0554 }
0555
0556 regmap_write(regmap, 0xc4, 0x1);
0557
0558 return qcom_cc_really_probe(pdev, &lcc_mdm9615_desc, regmap);
0559 }
0560
0561 static struct platform_driver lcc_mdm9615_driver = {
0562 .probe = lcc_mdm9615_probe,
0563 .driver = {
0564 .name = "lcc-mdm9615",
0565 .of_match_table = lcc_mdm9615_match_table,
0566 },
0567 };
0568 module_platform_driver(lcc_mdm9615_driver);
0569
0570 MODULE_DESCRIPTION("QCOM LCC MDM9615 Driver");
0571 MODULE_LICENSE("GPL v2");
0572 MODULE_ALIAS("platform:lcc-mdm9615");