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

Configure Feed

Select the types of activity you want to include in your feed.

clk: mediatek: Add MT8196 vlpckgen clock support

Add support for the MT8196 vlpckgen clock controller, which provides
muxes and dividers for clock selection in other IP blocks.

Reviewed-by: Chen-Yu Tsai <wenst@chromium.org>
Reviewed-by: AngeloGioacchino Del Regno <angelogioacchino.delregno@collabora.com>
Signed-off-by: Laura Nao <laura.nao@collabora.com>
Signed-off-by: Stephen Boyd <sboyd@kernel.org>

authored by

Laura Nao and committed by
Stephen Boyd
2f8b3ae6 b093e0f1

+726 -1
+1 -1
drivers/clk/mediatek/Makefile
··· 151 151 obj-$(CONFIG_COMMON_CLK_MT8195_VPPSYS) += clk-mt8195-vpp0.o clk-mt8195-vpp1.o 152 152 obj-$(CONFIG_COMMON_CLK_MT8195_WPESYS) += clk-mt8195-wpe.o 153 153 obj-$(CONFIG_COMMON_CLK_MT8196) += clk-mt8196-apmixedsys.o clk-mt8196-topckgen.o \ 154 - clk-mt8196-topckgen2.o 154 + clk-mt8196-topckgen2.o clk-mt8196-vlpckgen.o 155 155 obj-$(CONFIG_COMMON_CLK_MT8365) += clk-mt8365-apmixedsys.o clk-mt8365.o 156 156 obj-$(CONFIG_COMMON_CLK_MT8365_APU) += clk-mt8365-apu.o 157 157 obj-$(CONFIG_COMMON_CLK_MT8365_CAM) += clk-mt8365-cam.o
+725
drivers/clk/mediatek/clk-mt8196-vlpckgen.c
··· 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");