1 // SPDX-License-Identifier: GPL-2.0-only 2 /* 3 * Copyright (c) 2025 MediaTek Inc. 4 * Guangjie Song <guangjie.song@mediatek.com> 5 * Copyright (c) 2025 Collabora Ltd. 6 * Laura Nao <laura.nao@collabora.com> 7 */ 8 #include <dt-bindings/clock/mediatek,mt8196-clock.h> 9 10 #include <linux/clk.h> 11 #include <linux/module.h> 12 #include <linux/of.h> 13 #include <linux/of_address.h> 14 #include <linux/of_device.h> 15 #include <linux/platform_device.h> 16 #include <linux/regmap.h> 17 18 #include "clk-mtk.h" 19 #include "clk-mux.h" 20 #include "clk-pll.h" 21 22 /* MUX SEL REG */ 23 #define VLP_CLK_CFG_UPDATE 0x0004 24 #define VLP_CLK_CFG_UPDATE1 0x0008 25 #define VLP_CLK_CFG_0 0x0010 26 #define VLP_CLK_CFG_0_SET 0x0014 27 #define VLP_CLK_CFG_0_CLR 0x0018 28 #define VLP_CLK_CFG_1 0x0020 29 #define VLP_CLK_CFG_1_SET 0x0024 30 #define VLP_CLK_CFG_1_CLR 0x0028 31 #define VLP_CLK_CFG_2 0x0030 32 #define VLP_CLK_CFG_2_SET 0x0034 33 #define VLP_CLK_CFG_2_CLR 0x0038 34 #define VLP_CLK_CFG_3 0x0040 35 #define VLP_CLK_CFG_3_SET 0x0044 36 #define VLP_CLK_CFG_3_CLR 0x0048 37 #define VLP_CLK_CFG_4 0x0050 38 #define VLP_CLK_CFG_4_SET 0x0054 39 #define VLP_CLK_CFG_4_CLR 0x0058 40 #define VLP_CLK_CFG_5 0x0060 41 #define VLP_CLK_CFG_5_SET 0x0064 42 #define VLP_CLK_CFG_5_CLR 0x0068 43 #define VLP_CLK_CFG_6 0x0070 44 #define VLP_CLK_CFG_6_SET 0x0074 45 #define VLP_CLK_CFG_6_CLR 0x0078 46 #define VLP_CLK_CFG_7 0x0080 47 #define VLP_CLK_CFG_7_SET 0x0084 48 #define VLP_CLK_CFG_7_CLR 0x0088 49 #define VLP_CLK_CFG_8 0x0090 50 #define VLP_CLK_CFG_8_SET 0x0094 51 #define VLP_CLK_CFG_8_CLR 0x0098 52 #define VLP_CLK_CFG_9 0x00a0 53 #define VLP_CLK_CFG_9_SET 0x00a4 54 #define VLP_CLK_CFG_9_CLR 0x00a8 55 #define VLP_CLK_CFG_10 0x00b0 56 #define VLP_CLK_CFG_10_SET 0x00b4 57 #define VLP_CLK_CFG_10_CLR 0x00b8 58 #define VLP_OCIC_FENC_STATUS_MON_0 0x039c 59 #define VLP_OCIC_FENC_STATUS_MON_1 0x03a0 60 61 /* MUX SHIFT */ 62 #define TOP_MUX_SCP_SHIFT 0 63 #define TOP_MUX_SCP_SPI_SHIFT 1 64 #define TOP_MUX_SCP_IIC_SHIFT 2 65 #define TOP_MUX_SCP_IIC_HS_SHIFT 3 66 #define TOP_MUX_PWRAP_ULPOSC_SHIFT 4 67 #define TOP_MUX_SPMI_M_TIA_32K_SHIFT 5 68 #define TOP_MUX_APXGPT_26M_B_SHIFT 6 69 #define TOP_MUX_DPSW_SHIFT 7 70 #define TOP_MUX_DPSW_CENTRAL_SHIFT 8 71 #define TOP_MUX_SPMI_M_MST_SHIFT 9 72 #define TOP_MUX_DVFSRC_SHIFT 10 73 #define TOP_MUX_PWM_VLP_SHIFT 11 74 #define TOP_MUX_AXI_VLP_SHIFT 12 75 #define TOP_MUX_SYSTIMER_26M_SHIFT 13 76 #define TOP_MUX_SSPM_SHIFT 14 77 #define TOP_MUX_SRCK_SHIFT 15 78 #define TOP_MUX_CAMTG0_SHIFT 16 79 #define TOP_MUX_CAMTG1_SHIFT 17 80 #define TOP_MUX_CAMTG2_SHIFT 18 81 #define TOP_MUX_CAMTG3_SHIFT 19 82 #define TOP_MUX_CAMTG4_SHIFT 20 83 #define TOP_MUX_CAMTG5_SHIFT 21 84 #define TOP_MUX_CAMTG6_SHIFT 22 85 #define TOP_MUX_CAMTG7_SHIFT 23 86 #define TOP_MUX_SSPM_26M_SHIFT 25 87 #define TOP_MUX_ULPOSC_SSPM_SHIFT 26 88 #define TOP_MUX_VLP_PBUS_26M_SHIFT 27 89 #define TOP_MUX_DEBUG_ERR_FLAG_VLP_26M_SHIFT 28 90 #define TOP_MUX_DPMSRDMA_SHIFT 29 91 #define TOP_MUX_VLP_PBUS_156M_SHIFT 30 92 #define TOP_MUX_SPM_SHIFT 0 93 #define TOP_MUX_MMINFRA_VLP_SHIFT 1 94 #define TOP_MUX_USB_TOP_SHIFT 2 95 #define TOP_MUX_SSUSB_XHCI_SHIFT 3 96 #define TOP_MUX_NOC_VLP_SHIFT 4 97 #define TOP_MUX_AUDIO_H_SHIFT 5 98 #define TOP_MUX_AUD_ENGEN1_SHIFT 6 99 #define TOP_MUX_AUD_ENGEN2_SHIFT 7 100 #define TOP_MUX_AUD_INTBUS_SHIFT 8 101 #define TOP_MUX_SPU_VLP_26M_SHIFT 9 102 #define TOP_MUX_SPU0_VLP_SHIFT 10 103 #define TOP_MUX_SPU1_VLP_SHIFT 11 104 105 /* CKSTA REG */ 106 #define VLP_CKSTA_REG0 0x0250 107 #define VLP_CKSTA_REG1 0x0254 108 109 /* HW Voter REG */ 110 #define HWV_CG_9_SET 0x0048 111 #define HWV_CG_9_CLR 0x004c 112 #define HWV_CG_9_DONE 0x2c24 113 #define HWV_CG_10_SET 0x0050 114 #define HWV_CG_10_CLR 0x0054 115 #define HWV_CG_10_DONE 0x2c28 116 117 /* PLL REG */ 118 #define VLP_AP_PLL_CON3 0x264 119 #define VLP_APLL1_TUNER_CON0 0x2a4 120 #define VLP_APLL2_TUNER_CON0 0x2a8 121 #define VLP_APLL1_CON0 0x274 122 #define VLP_APLL1_CON1 0x278 123 #define VLP_APLL1_CON2 0x27c 124 #define VLP_APLL1_CON3 0x280 125 #define VLP_APLL2_CON0 0x28c 126 #define VLP_APLL2_CON1 0x290 127 #define VLP_APLL2_CON2 0x294 128 #define VLP_APLL2_CON3 0x298 129 130 /* vlp apll1 tuner default value*/ 131 #define VLP_APLL1_TUNER_CON0_VALUE 0x6f28bd4d 132 /* vlp apll2 tuner default value + 1*/ 133 #define VLP_APLL2_TUNER_CON0_VALUE 0x78fd5265 134 135 #define VLP_PLLEN_ALL 0x080 136 #define VLP_PLLEN_ALL_SET 0x084 137 #define VLP_PLLEN_ALL_CLR 0x088 138 139 #define MT8196_PLL_FMAX (3800UL * MHZ) 140 #define MT8196_PLL_FMIN (1500UL * MHZ) 141 #define MT8196_INTEGER_BITS 8 142 143 #define PLL_FENC(_id, _name, _reg, _fenc_sta_ofs, _fenc_sta_bit,\ 144 _flags, _pd_reg, _pd_shift, \ 145 _pcw_reg, _pcw_shift, _pcwbits, \ 146 _pll_en_bit) { \ 147 .id = _id, \ 148 .name = _name, \ 149 .reg = _reg, \ 150 .fenc_sta_ofs = _fenc_sta_ofs, \ 151 .fenc_sta_bit = _fenc_sta_bit, \ 152 .flags = _flags, \ 153 .fmax = MT8196_PLL_FMAX, \ 154 .fmin = MT8196_PLL_FMIN, \ 155 .pd_reg = _pd_reg, \ 156 .pd_shift = _pd_shift, \ 157 .pcw_reg = _pcw_reg, \ 158 .pcw_shift = _pcw_shift, \ 159 .pcwbits = _pcwbits, \ 160 .pcwibits = MT8196_INTEGER_BITS, \ 161 .en_reg = VLP_PLLEN_ALL, \ 162 .en_set_reg = VLP_PLLEN_ALL_SET, \ 163 .en_clr_reg = VLP_PLLEN_ALL_CLR, \ 164 .pll_en_bit = _pll_en_bit, \ 165 .ops = &mtk_pll_fenc_clr_set_ops, \ 166 } 167 168 static DEFINE_SPINLOCK(mt8196_clk_vlp_lock); 169 170 static const struct mtk_fixed_factor vlp_divs[] = { 171 FACTOR(CLK_VLP_CLK26M, "vlp_clk26m", "clk26m", 1, 1), 172 FACTOR(CLK_VLP_APLL1_D4, "apll1_d4", "vlp_apll1", 1, 4), 173 FACTOR(CLK_VLP_APLL1_D8, "apll1_d8", "vlp_apll1", 1, 8), 174 FACTOR(CLK_VLP_APLL2_D4, "apll2_d4", "vlp_apll2", 1, 4), 175 FACTOR(CLK_VLP_APLL2_D8, "apll2_d8", "vlp_apll2", 1, 8), 176 }; 177 178 static const char * const vlp_scp_parents[] = { 179 "clk26m", 180 "osc_d20", 181 "mainpll_d6", 182 "mainpll_d4", 183 "mainpll_d3", 184 "vlp_apll1" 185 }; 186 187 static const char * const vlp_scp_spi_parents[] = { 188 "clk26m", 189 "osc_d20", 190 "mainpll_d7_d2", 191 "mainpll_d5_d2" 192 }; 193 194 static const char * const vlp_scp_iic_parents[] = { 195 "clk26m", 196 "osc_d20", 197 "mainpll_d5_d4", 198 "mainpll_d7_d2" 199 }; 200 201 static const char * const vlp_scp_iic_hs_parents[] = { 202 "clk26m", 203 "osc_d20", 204 "mainpll_d5_d4", 205 "mainpll_d7_d2", 206 "mainpll_d7" 207 }; 208 209 static const char * const vlp_pwrap_ulposc_parents[] = { 210 "clk26m", 211 "osc_d20", 212 "osc_d14", 213 "osc_d10" 214 }; 215 216 static const char * const vlp_spmi_32k_parents[] = { 217 "clk26m", 218 "clk32k", 219 "osc_d20", 220 "osc_d14", 221 "osc_d10" 222 }; 223 224 static const char * const vlp_apxgpt_26m_b_parents[] = { 225 "clk26m", 226 "osc_d20" 227 }; 228 229 static const char * const vlp_dpsw_parents[] = { 230 "clk26m", 231 "osc_d10", 232 "osc_d7", 233 "mainpll_d7_d4" 234 }; 235 236 static const char * const vlp_dpsw_central_parents[] = { 237 "clk26m", 238 "osc_d10", 239 "osc_d7", 240 "mainpll_d7_d4" 241 }; 242 243 static const char * const vlp_spmi_m_parents[] = { 244 "clk26m", 245 "osc_d20", 246 "osc_d14", 247 "osc_d10" 248 }; 249 250 static const char * const vlp_dvfsrc_parents[] = { 251 "clk26m", 252 "osc_d20" 253 }; 254 255 static const char * const vlp_pwm_vlp_parents[] = { 256 "clk26m", 257 "clk32k", 258 "osc_d20", 259 "osc_d8", 260 "mainpll_d4_d8" 261 }; 262 263 static const char * const vlp_axi_vlp_parents[] = { 264 "clk26m", 265 "osc_d20", 266 "mainpll_d7_d4", 267 "osc_d4", 268 "mainpll_d7_d2" 269 }; 270 271 static const char * const vlp_systimer_26m_parents[] = { 272 "clk26m", 273 "osc_d20" 274 }; 275 276 static const char * const vlp_sspm_parents[] = { 277 "clk26m", 278 "osc_d20", 279 "mainpll_d5_d2", 280 "osc_d2", 281 "mainpll_d6" 282 }; 283 284 static const char * const vlp_srck_parents[] = { 285 "clk26m", 286 "osc_d20" 287 }; 288 289 static const char * const vlp_camtg0_1_parents[] = { 290 "clk26m", 291 "univpll_192m_d32", 292 "univpll_192m_d16", 293 "clk13m", 294 "osc_d40", 295 "osc_d32", 296 "univpll_192m_d10", 297 "univpll_192m_d8", 298 "univpll_d6_d16", 299 "ulposc3", 300 "osc_d20", 301 "ck2_tvdpll1_d16", 302 "univpll_d6_d8" 303 }; 304 305 static const char * const vlp_camtg2_7_parents[] = { 306 "clk26m", 307 "univpll_192m_d32", 308 "univpll_192m_d16", 309 "clk13m", 310 "osc_d40", 311 "osc_d32", 312 "univpll_192m_d10", 313 "univpll_192m_d8", 314 "univpll_d6_d16", 315 "osc_d20", 316 "ck2_tvdpll1_d16", 317 "univpll_d6_d8" 318 }; 319 320 static const char * const vlp_sspm_26m_parents[] = { 321 "clk26m", 322 "osc_d20" 323 }; 324 325 static const char * const vlp_ulposc_sspm_parents[] = { 326 "clk26m", 327 "osc_d2", 328 "mainpll_d4_d2" 329 }; 330 331 static const char * const vlp_vlp_pbus_26m_parents[] = { 332 "clk26m", 333 "osc_d20" 334 }; 335 336 static const char * const vlp_debug_err_flag_parents[] = { 337 "clk26m", 338 "osc_d20" 339 }; 340 341 static const char * const vlp_dpmsrdma_parents[] = { 342 "clk26m", 343 "mainpll_d7_d2" 344 }; 345 346 static const char * const vlp_vlp_pbus_156m_parents[] = { 347 "clk26m", 348 "osc_d2", 349 "mainpll_d7_d2", 350 "mainpll_d7" 351 }; 352 353 static const char * const vlp_spm_parents[] = { 354 "clk26m", 355 "mainpll_d7_d4" 356 }; 357 358 static const char * const vlp_mminfra_parents[] = { 359 "clk26m", 360 "osc_d4", 361 "mainpll_d3" 362 }; 363 364 static const char * const vlp_usb_parents[] = { 365 "clk26m", 366 "mainpll_d9" 367 }; 368 369 static const char * const vlp_noc_vlp_parents[] = { 370 "clk26m", 371 "osc_d20", 372 "mainpll_d9" 373 }; 374 375 static const char * const vlp_audio_h_parents[] = { 376 "vlp_clk26m", 377 "vlp_apll1", 378 "vlp_apll2" 379 }; 380 381 static const char * const vlp_aud_engen1_parents[] = { 382 "vlp_clk26m", 383 "apll1_d8", 384 "apll1_d4" 385 }; 386 387 static const char * const vlp_aud_engen2_parents[] = { 388 "vlp_clk26m", 389 "apll2_d8", 390 "apll2_d4" 391 }; 392 393 static const char * const vlp_aud_intbus_parents[] = { 394 "vlp_clk26m", 395 "mainpll_d7_d4", 396 "mainpll_d4_d4" 397 }; 398 399 static const u8 vlp_aud_parent_index[] = { 1, 2, 3 }; 400 401 static const char * const vlp_spvlp_26m_parents[] = { 402 "clk26m", 403 "osc_d20" 404 }; 405 406 static const char * const vlp_spu0_vlp_parents[] = { 407 "clk26m", 408 "osc_d20", 409 "mainpll_d4_d4", 410 "mainpll_d4_d2", 411 "mainpll_d7", 412 "mainpll_d6", 413 "mainpll_d5" 414 }; 415 416 static const char * const vlp_spu1_vlp_parents[] = { 417 "clk26m", 418 "osc_d20", 419 "mainpll_d4_d4", 420 "mainpll_d4_d2", 421 "mainpll_d7", 422 "mainpll_d6", 423 "mainpll_d5" 424 }; 425 426 static const struct mtk_mux vlp_muxes[] = { 427 /* VLP_CLK_CFG_0 */ 428 MUX_GATE_FENC_CLR_SET_UPD(CLK_VLP_SCP, "vlp_scp", vlp_scp_parents, 429 VLP_CLK_CFG_0, VLP_CLK_CFG_0_SET, VLP_CLK_CFG_0_CLR, 430 0, 3, 7, VLP_CLK_CFG_UPDATE, TOP_MUX_SCP_SHIFT, 431 VLP_OCIC_FENC_STATUS_MON_0, 31), 432 MUX_CLR_SET_UPD(CLK_VLP_SCP_SPI, "vlp_scp_spi", 433 vlp_scp_spi_parents, VLP_CLK_CFG_0, VLP_CLK_CFG_0_SET, 434 VLP_CLK_CFG_0_CLR, 8, 2, 435 VLP_CLK_CFG_UPDATE, TOP_MUX_SCP_SPI_SHIFT), 436 MUX_CLR_SET_UPD(CLK_VLP_SCP_IIC, "vlp_scp_iic", 437 vlp_scp_iic_parents, VLP_CLK_CFG_0, VLP_CLK_CFG_0_SET, 438 VLP_CLK_CFG_0_CLR, 16, 2, 439 VLP_CLK_CFG_UPDATE, TOP_MUX_SCP_IIC_SHIFT), 440 MUX_CLR_SET_UPD(CLK_VLP_SCP_IIC_HS, "vlp_scp_iic_hs", 441 vlp_scp_iic_hs_parents, VLP_CLK_CFG_0, VLP_CLK_CFG_0_SET, 442 VLP_CLK_CFG_0_CLR, 24, 3, 443 VLP_CLK_CFG_UPDATE, TOP_MUX_SCP_IIC_HS_SHIFT), 444 /* VLP_CLK_CFG_1 */ 445 MUX_CLR_SET_UPD(CLK_VLP_PWRAP_ULPOSC, "vlp_pwrap_ulposc", 446 vlp_pwrap_ulposc_parents, VLP_CLK_CFG_1, VLP_CLK_CFG_1_SET, 447 VLP_CLK_CFG_1_CLR, 0, 2, 448 VLP_CLK_CFG_UPDATE, TOP_MUX_PWRAP_ULPOSC_SHIFT), 449 MUX_CLR_SET_UPD(CLK_VLP_SPMI_M_TIA_32K, "vlp_spmi_32k", 450 vlp_spmi_32k_parents, VLP_CLK_CFG_1, VLP_CLK_CFG_1_SET, 451 VLP_CLK_CFG_1_CLR, 8, 3, 452 VLP_CLK_CFG_UPDATE, TOP_MUX_SPMI_M_TIA_32K_SHIFT), 453 MUX_CLR_SET_UPD(CLK_VLP_APXGPT_26M_B, "vlp_apxgpt_26m_b", 454 vlp_apxgpt_26m_b_parents, VLP_CLK_CFG_1, VLP_CLK_CFG_1_SET, 455 VLP_CLK_CFG_1_CLR, 16, 1, 456 VLP_CLK_CFG_UPDATE, TOP_MUX_APXGPT_26M_B_SHIFT), 457 MUX_CLR_SET_UPD(CLK_VLP_DPSW, "vlp_dpsw", 458 vlp_dpsw_parents, VLP_CLK_CFG_1, VLP_CLK_CFG_1_SET, 459 VLP_CLK_CFG_1_CLR, 24, 2, 460 VLP_CLK_CFG_UPDATE, TOP_MUX_DPSW_SHIFT), 461 /* VLP_CLK_CFG_2 */ 462 MUX_CLR_SET_UPD(CLK_VLP_DPSW_CENTRAL, "vlp_dpsw_central", 463 vlp_dpsw_central_parents, VLP_CLK_CFG_2, VLP_CLK_CFG_2_SET, 464 VLP_CLK_CFG_2_CLR, 0, 2, 465 VLP_CLK_CFG_UPDATE, TOP_MUX_DPSW_CENTRAL_SHIFT), 466 MUX_CLR_SET_UPD(CLK_VLP_SPMI_M_MST, "vlp_spmi_m", 467 vlp_spmi_m_parents, VLP_CLK_CFG_2, VLP_CLK_CFG_2_SET, 468 VLP_CLK_CFG_2_CLR, 8, 2, 469 VLP_CLK_CFG_UPDATE, TOP_MUX_SPMI_M_MST_SHIFT), 470 MUX_CLR_SET_UPD(CLK_VLP_DVFSRC, "vlp_dvfsrc", 471 vlp_dvfsrc_parents, VLP_CLK_CFG_2, VLP_CLK_CFG_2_SET, 472 VLP_CLK_CFG_2_CLR, 16, 1, 473 VLP_CLK_CFG_UPDATE, TOP_MUX_DVFSRC_SHIFT), 474 MUX_GATE_FENC_CLR_SET_UPD(CLK_VLP_PWM_VLP, "vlp_pwm_vlp", vlp_pwm_vlp_parents, 475 VLP_CLK_CFG_2, VLP_CLK_CFG_2_SET, VLP_CLK_CFG_2_CLR, 476 24, 3, 31, VLP_CLK_CFG_UPDATE, TOP_MUX_PWM_VLP_SHIFT, 477 VLP_OCIC_FENC_STATUS_MON_0, 20), 478 /* VLP_CLK_CFG_3 */ 479 MUX_CLR_SET_UPD(CLK_VLP_AXI_VLP, "vlp_axi_vlp", 480 vlp_axi_vlp_parents, VLP_CLK_CFG_3, VLP_CLK_CFG_3_SET, 481 VLP_CLK_CFG_3_CLR, 0, 3, 482 VLP_CLK_CFG_UPDATE, TOP_MUX_AXI_VLP_SHIFT), 483 MUX_CLR_SET_UPD(CLK_VLP_SYSTIMER_26M, "vlp_systimer_26m", 484 vlp_systimer_26m_parents, VLP_CLK_CFG_3, VLP_CLK_CFG_3_SET, 485 VLP_CLK_CFG_3_CLR, 8, 1, 486 VLP_CLK_CFG_UPDATE, TOP_MUX_SYSTIMER_26M_SHIFT), 487 MUX_CLR_SET_UPD(CLK_VLP_SSPM, "vlp_sspm", 488 vlp_sspm_parents, VLP_CLK_CFG_3, VLP_CLK_CFG_3_SET, 489 VLP_CLK_CFG_3_CLR, 16, 3, 490 VLP_CLK_CFG_UPDATE, TOP_MUX_SSPM_SHIFT), 491 MUX_CLR_SET_UPD(CLK_VLP_SRCK, "vlp_srck", 492 vlp_srck_parents, VLP_CLK_CFG_3, VLP_CLK_CFG_3_SET, 493 VLP_CLK_CFG_3_CLR, 24, 1, 494 VLP_CLK_CFG_UPDATE, TOP_MUX_SRCK_SHIFT), 495 /* VLP_CLK_CFG_4 */ 496 MUX_GATE_HWV_FENC_CLR_SET_UPD(CLK_VLP_CAMTG0, "vlp_camtg0", vlp_camtg0_1_parents, 497 VLP_CLK_CFG_4, VLP_CLK_CFG_4_SET, VLP_CLK_CFG_4_CLR, 498 HWV_CG_9_DONE, HWV_CG_9_SET, HWV_CG_9_CLR, 499 0, 4, 7, VLP_CLK_CFG_UPDATE, TOP_MUX_CAMTG0_SHIFT, 500 VLP_OCIC_FENC_STATUS_MON_0, 15), 501 MUX_GATE_HWV_FENC_CLR_SET_UPD(CLK_VLP_CAMTG1, "vlp_camtg1", vlp_camtg0_1_parents, 502 VLP_CLK_CFG_4, VLP_CLK_CFG_4_SET, VLP_CLK_CFG_4_CLR, 503 HWV_CG_9_DONE, HWV_CG_9_SET, HWV_CG_9_CLR, 504 8, 4, 15, VLP_CLK_CFG_UPDATE, TOP_MUX_CAMTG1_SHIFT, 505 VLP_OCIC_FENC_STATUS_MON_0, 14), 506 MUX_GATE_HWV_FENC_CLR_SET_UPD(CLK_VLP_CAMTG2, "vlp_camtg2", vlp_camtg2_7_parents, 507 VLP_CLK_CFG_4, VLP_CLK_CFG_4_SET, VLP_CLK_CFG_4_CLR, 508 HWV_CG_9_DONE, HWV_CG_9_SET, HWV_CG_9_CLR, 509 16, 4, 23, VLP_CLK_CFG_UPDATE, TOP_MUX_CAMTG2_SHIFT, 510 VLP_OCIC_FENC_STATUS_MON_0, 13), 511 MUX_GATE_HWV_FENC_CLR_SET_UPD(CLK_VLP_CAMTG3, "vlp_camtg3", vlp_camtg2_7_parents, 512 VLP_CLK_CFG_4, VLP_CLK_CFG_4_SET, VLP_CLK_CFG_4_CLR, 513 HWV_CG_9_DONE, HWV_CG_9_SET, HWV_CG_9_CLR, 514 24, 4, 31, VLP_CLK_CFG_UPDATE, TOP_MUX_CAMTG3_SHIFT, 515 VLP_OCIC_FENC_STATUS_MON_0, 12), 516 /* VLP_CLK_CFG_5 */ 517 MUX_GATE_HWV_FENC_CLR_SET_UPD(CLK_VLP_CAMTG4, "vlp_camtg4", vlp_camtg2_7_parents, 518 VLP_CLK_CFG_5, VLP_CLK_CFG_5_SET, VLP_CLK_CFG_5_CLR, 519 HWV_CG_10_DONE, HWV_CG_10_SET, HWV_CG_10_CLR, 520 0, 4, 7, VLP_CLK_CFG_UPDATE, TOP_MUX_CAMTG4_SHIFT, 521 VLP_OCIC_FENC_STATUS_MON_0, 11), 522 MUX_GATE_HWV_FENC_CLR_SET_UPD(CLK_VLP_CAMTG5, "vlp_camtg5", vlp_camtg2_7_parents, 523 VLP_CLK_CFG_5, VLP_CLK_CFG_5_SET, VLP_CLK_CFG_5_CLR, 524 HWV_CG_10_DONE, HWV_CG_10_SET, HWV_CG_10_CLR, 525 8, 4, 15, VLP_CLK_CFG_UPDATE, TOP_MUX_CAMTG5_SHIFT, 526 VLP_OCIC_FENC_STATUS_MON_0, 10), 527 MUX_GATE_HWV_FENC_CLR_SET_UPD(CLK_VLP_CAMTG6, "vlp_camtg6", vlp_camtg2_7_parents, 528 VLP_CLK_CFG_5, VLP_CLK_CFG_5_SET, VLP_CLK_CFG_5_CLR, 529 HWV_CG_10_DONE, HWV_CG_10_SET, HWV_CG_10_CLR, 530 16, 4, 23, VLP_CLK_CFG_UPDATE, TOP_MUX_CAMTG6_SHIFT, 531 VLP_OCIC_FENC_STATUS_MON_0, 9), 532 MUX_GATE_HWV_FENC_CLR_SET_UPD(CLK_VLP_CAMTG7, "vlp_camtg7", vlp_camtg2_7_parents, 533 VLP_CLK_CFG_5, VLP_CLK_CFG_5_SET, VLP_CLK_CFG_5_CLR, 534 HWV_CG_10_DONE, HWV_CG_10_SET, HWV_CG_10_CLR, 535 24, 4, 31, VLP_CLK_CFG_UPDATE, TOP_MUX_CAMTG7_SHIFT, 536 VLP_OCIC_FENC_STATUS_MON_0, 8), 537 /* VLP_CLK_CFG_6 */ 538 MUX_CLR_SET_UPD(CLK_VLP_SSPM_26M, "vlp_sspm_26m", 539 vlp_sspm_26m_parents, VLP_CLK_CFG_6, VLP_CLK_CFG_6_SET, 540 VLP_CLK_CFG_6_CLR, 8, 1, 541 VLP_CLK_CFG_UPDATE, TOP_MUX_SSPM_26M_SHIFT), 542 MUX_CLR_SET_UPD(CLK_VLP_ULPOSC_SSPM, "vlp_ulposc_sspm", 543 vlp_ulposc_sspm_parents, VLP_CLK_CFG_6, VLP_CLK_CFG_6_SET, 544 VLP_CLK_CFG_6_CLR, 16, 2, 545 VLP_CLK_CFG_UPDATE, TOP_MUX_ULPOSC_SSPM_SHIFT), 546 MUX_CLR_SET_UPD(CLK_VLP_VLP_PBUS_26M, "vlp_vlp_pbus_26m", 547 vlp_vlp_pbus_26m_parents, VLP_CLK_CFG_6, VLP_CLK_CFG_6_SET, 548 VLP_CLK_CFG_6_CLR, 24, 1, 549 VLP_CLK_CFG_UPDATE, TOP_MUX_VLP_PBUS_26M_SHIFT), 550 /* VLP_CLK_CFG_7 */ 551 MUX_CLR_SET_UPD(CLK_VLP_DEBUG_ERR_FLAG, "vlp_debug_err_flag", 552 vlp_debug_err_flag_parents, VLP_CLK_CFG_7, VLP_CLK_CFG_7_SET, 553 VLP_CLK_CFG_7_CLR, 0, 1, 554 VLP_CLK_CFG_UPDATE, TOP_MUX_DEBUG_ERR_FLAG_VLP_26M_SHIFT), 555 MUX_CLR_SET_UPD(CLK_VLP_DPMSRDMA, "vlp_dpmsrdma", 556 vlp_dpmsrdma_parents, VLP_CLK_CFG_7, VLP_CLK_CFG_7_SET, 557 VLP_CLK_CFG_7_CLR, 8, 1, 558 VLP_CLK_CFG_UPDATE, TOP_MUX_DPMSRDMA_SHIFT), 559 MUX_CLR_SET_UPD(CLK_VLP_VLP_PBUS_156M, "vlp_vlp_pbus_156m", 560 vlp_vlp_pbus_156m_parents, VLP_CLK_CFG_7, VLP_CLK_CFG_7_SET, 561 VLP_CLK_CFG_7_CLR, 16, 2, 562 VLP_CLK_CFG_UPDATE, TOP_MUX_VLP_PBUS_156M_SHIFT), 563 MUX_CLR_SET_UPD(CLK_VLP_SPM, "vlp_spm", 564 vlp_spm_parents, VLP_CLK_CFG_7, VLP_CLK_CFG_7_SET, 565 VLP_CLK_CFG_7_CLR, 24, 1, 566 VLP_CLK_CFG_UPDATE1, TOP_MUX_SPM_SHIFT), 567 /* VLP_CLK_CFG_8 */ 568 MUX_GATE_FENC_CLR_SET_UPD(CLK_VLP_MMINFRA, "vlp_mminfra", vlp_mminfra_parents, 569 VLP_CLK_CFG_8, VLP_CLK_CFG_8_SET, VLP_CLK_CFG_8_CLR, 570 0, 2, 7, VLP_CLK_CFG_UPDATE1, TOP_MUX_MMINFRA_VLP_SHIFT, 571 VLP_OCIC_FENC_STATUS_MON_1, 31), 572 MUX_GATE_FENC_CLR_SET_UPD(CLK_VLP_USB_TOP, "vlp_usb", vlp_usb_parents, 573 VLP_CLK_CFG_8, VLP_CLK_CFG_8_SET, VLP_CLK_CFG_8_CLR, 574 8, 1, 15, VLP_CLK_CFG_UPDATE1, TOP_MUX_USB_TOP_SHIFT, 575 VLP_OCIC_FENC_STATUS_MON_1, 30), 576 MUX_GATE_FENC_CLR_SET_UPD(CLK_VLP_USB_XHCI, "vlp_usb_xhci", vlp_usb_parents, 577 VLP_CLK_CFG_8, VLP_CLK_CFG_8_SET, VLP_CLK_CFG_8_CLR, 578 16, 1, 23, VLP_CLK_CFG_UPDATE1, TOP_MUX_SSUSB_XHCI_SHIFT, 579 VLP_OCIC_FENC_STATUS_MON_1, 29), 580 MUX_CLR_SET_UPD(CLK_VLP_NOC_VLP, "vlp_noc_vlp", 581 vlp_noc_vlp_parents, VLP_CLK_CFG_8, VLP_CLK_CFG_8_SET, 582 VLP_CLK_CFG_8_CLR, 24, 2, 583 VLP_CLK_CFG_UPDATE1, TOP_MUX_NOC_VLP_SHIFT), 584 /* VLP_CLK_CFG_9 */ 585 MUX_GATE_FENC_CLR_SET_UPD_INDEXED(CLK_VLP_AUDIO_H, "vlp_audio_h", 586 vlp_audio_h_parents, vlp_aud_parent_index, 587 VLP_CLK_CFG_9, VLP_CLK_CFG_9_SET, VLP_CLK_CFG_9_CLR, 588 0, 2, 7, VLP_CLK_CFG_UPDATE1, TOP_MUX_AUDIO_H_SHIFT, 589 VLP_OCIC_FENC_STATUS_MON_1, 27), 590 MUX_GATE_FENC_CLR_SET_UPD_INDEXED(CLK_VLP_AUD_ENGEN1, "vlp_aud_engen1", 591 vlp_aud_engen1_parents, vlp_aud_parent_index, 592 VLP_CLK_CFG_9, VLP_CLK_CFG_9_SET, VLP_CLK_CFG_9_CLR, 593 8, 2, 15, VLP_CLK_CFG_UPDATE1, TOP_MUX_AUD_ENGEN1_SHIFT, 594 VLP_OCIC_FENC_STATUS_MON_1, 26), 595 MUX_GATE_FENC_CLR_SET_UPD_INDEXED(CLK_VLP_AUD_ENGEN2, "vlp_aud_engen2", 596 vlp_aud_engen2_parents, vlp_aud_parent_index, 597 VLP_CLK_CFG_9, VLP_CLK_CFG_9_SET, VLP_CLK_CFG_9_CLR, 598 16, 2, 23, VLP_CLK_CFG_UPDATE1, TOP_MUX_AUD_ENGEN2_SHIFT, 599 VLP_OCIC_FENC_STATUS_MON_1, 25), 600 MUX_GATE_FENC_CLR_SET_UPD_INDEXED(CLK_VLP_AUD_INTBUS, "vlp_aud_intbus", 601 vlp_aud_intbus_parents, vlp_aud_parent_index, 602 VLP_CLK_CFG_9, VLP_CLK_CFG_9_SET, VLP_CLK_CFG_9_CLR, 603 24, 2, 31, VLP_CLK_CFG_UPDATE1, TOP_MUX_AUD_INTBUS_SHIFT, 604 VLP_OCIC_FENC_STATUS_MON_1, 24), 605 /* VLP_CLK_CFG_10 */ 606 MUX_CLR_SET_UPD(CLK_VLP_SPVLP_26M, "vlp_spvlp_26m", 607 vlp_spvlp_26m_parents, VLP_CLK_CFG_10, VLP_CLK_CFG_10_SET, 608 VLP_CLK_CFG_10_CLR, 0, 1, 609 VLP_CLK_CFG_UPDATE1, TOP_MUX_SPU_VLP_26M_SHIFT), 610 MUX_CLR_SET_UPD(CLK_VLP_SPU0_VLP, "vlp_spu0_vlp", 611 vlp_spu0_vlp_parents, VLP_CLK_CFG_10, VLP_CLK_CFG_10_SET, 612 VLP_CLK_CFG_10_CLR, 8, 3, 613 VLP_CLK_CFG_UPDATE1, TOP_MUX_SPU0_VLP_SHIFT), 614 MUX_CLR_SET_UPD(CLK_VLP_SPU1_VLP, "vlp_spu1_vlp", 615 vlp_spu1_vlp_parents, VLP_CLK_CFG_10, VLP_CLK_CFG_10_SET, 616 VLP_CLK_CFG_10_CLR, 16, 3, 617 VLP_CLK_CFG_UPDATE1, TOP_MUX_SPU1_VLP_SHIFT), 618 }; 619 620 static const struct mtk_pll_data vlp_plls[] = { 621 PLL_FENC(CLK_VLP_APLL1, "vlp_apll1", VLP_APLL1_CON0, 0x0358, 1, 0, 622 VLP_APLL1_CON1, 24, VLP_APLL1_CON2, 0, 32, 0), 623 PLL_FENC(CLK_VLP_APLL2, "vlp_apll2", VLP_APLL2_CON0, 0x0358, 0, 0, 624 VLP_APLL2_CON1, 24, VLP_APLL2_CON2, 0, 32, 1), 625 }; 626 627 static const struct regmap_config vlpckgen_regmap_config = { 628 .reg_bits = 32, 629 .val_bits = 32, 630 .reg_stride = 4, 631 .max_register = 0x1000, 632 .fast_io = true, 633 }; 634 635 static int clk_mt8196_vlp_probe(struct platform_device *pdev) 636 { 637 static void __iomem *base; 638 struct clk_hw_onecell_data *clk_data; 639 int r; 640 struct device_node *node = pdev->dev.of_node; 641 struct device *dev = &pdev->dev; 642 struct regmap *regmap; 643 644 clk_data = mtk_alloc_clk_data(ARRAY_SIZE(vlp_muxes) + 645 ARRAY_SIZE(vlp_plls) + 646 ARRAY_SIZE(vlp_divs)); 647 if (!clk_data) 648 return -ENOMEM; 649 650 base = devm_platform_ioremap_resource(pdev, 0); 651 if (IS_ERR(base)) 652 return PTR_ERR(base); 653 654 regmap = devm_regmap_init_mmio(dev, base, &vlpckgen_regmap_config); 655 if (IS_ERR(regmap)) 656 return PTR_ERR(regmap); 657 658 r = mtk_clk_register_factors(vlp_divs, ARRAY_SIZE(vlp_divs), clk_data); 659 if (r) 660 goto free_clk_data; 661 662 r = mtk_clk_register_muxes(&pdev->dev, vlp_muxes, ARRAY_SIZE(vlp_muxes), 663 node, &mt8196_clk_vlp_lock, clk_data); 664 if (r) 665 goto unregister_factors; 666 667 r = mtk_clk_register_plls(node, vlp_plls, ARRAY_SIZE(vlp_plls), 668 clk_data); 669 if (r) 670 goto unregister_muxes; 671 672 r = of_clk_add_hw_provider(node, of_clk_hw_onecell_get, clk_data); 673 if (r) 674 goto unregister_plls; 675 676 platform_set_drvdata(pdev, clk_data); 677 678 /* Initialize APLL tuner registers */ 679 regmap_write(regmap, VLP_APLL1_TUNER_CON0, VLP_APLL1_TUNER_CON0_VALUE); 680 regmap_write(regmap, VLP_APLL2_TUNER_CON0, VLP_APLL2_TUNER_CON0_VALUE); 681 682 return r; 683 684 unregister_plls: 685 mtk_clk_unregister_plls(vlp_plls, ARRAY_SIZE(vlp_plls), clk_data); 686 unregister_muxes: 687 mtk_clk_unregister_muxes(vlp_muxes, ARRAY_SIZE(vlp_muxes), clk_data); 688 unregister_factors: 689 mtk_clk_unregister_factors(vlp_divs, ARRAY_SIZE(vlp_divs), clk_data); 690 free_clk_data: 691 mtk_free_clk_data(clk_data); 692 693 return r; 694 } 695 696 static void clk_mt8196_vlp_remove(struct platform_device *pdev) 697 { 698 struct clk_hw_onecell_data *clk_data = platform_get_drvdata(pdev); 699 struct device_node *node = pdev->dev.of_node; 700 701 of_clk_del_provider(node); 702 mtk_clk_unregister_plls(vlp_plls, ARRAY_SIZE(vlp_plls), clk_data); 703 mtk_clk_unregister_muxes(vlp_muxes, ARRAY_SIZE(vlp_muxes), clk_data); 704 mtk_clk_unregister_factors(vlp_divs, ARRAY_SIZE(vlp_divs), clk_data); 705 mtk_free_clk_data(clk_data); 706 } 707 708 static const struct of_device_id of_match_clk_mt8196_vlp_ck[] = { 709 { .compatible = "mediatek,mt8196-vlpckgen" }, 710 { /* sentinel */ } 711 }; 712 MODULE_DEVICE_TABLE(of, of_match_clk_mt8196_vlp_ck); 713 714 static struct platform_driver clk_mt8196_vlp_drv = { 715 .probe = clk_mt8196_vlp_probe, 716 .remove = clk_mt8196_vlp_remove, 717 .driver = { 718 .name = "clk-mt8196-vlpck", 719 .of_match_table = of_match_clk_mt8196_vlp_ck, 720 }, 721 }; 722 723 MODULE_DESCRIPTION("MediaTek MT8196 VLP clock generator driver"); 724 module_platform_driver(clk_mt8196_vlp_drv); 725 MODULE_LICENSE("GPL"); 726