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: meson: t7: add support for the T7 SoC PLL clock

Add PLL clock controller driver for the Amlogic T7 SoC family.

Signed-off-by: Jian Hu <jian.hu@amlogic.com>
Link: https://lore.kernel.org/r/20251212022619.3072132-5-jian.hu@amlogic.com
Signed-off-by: Jerome Brunet <jbrunet@baylibre.com>

authored by

Jian Hu and committed by
Jerome Brunet
140f074c b4156204

+1090
+15
drivers/clk/meson/Kconfig
··· 201 201 help 202 202 Support for the peripherals clock controller on Amlogic S805X2 and S905Y4 203 203 devices, AKA S4. Say Y if you want S4 peripherals clock controller to work. 204 + 205 + config COMMON_CLK_T7_PLL 206 + tristate "Amlogic T7 SoC PLL controller support" 207 + depends on ARM64 208 + default ARCH_MESON 209 + select COMMON_CLK_MESON_REGMAP 210 + select COMMON_CLK_MESON_CLKC_UTILS 211 + select COMMON_CLK_MESON_MPLL 212 + select COMMON_CLK_MESON_PLL 213 + imply COMMON_CLK_SCMI 214 + help 215 + Support for the PLL clock controller on Amlogic A311D2 based 216 + device, AKA T7. PLLs are required by most peripheral to operate. 217 + Say Y if you want T7 PLL clock controller to work. 218 + 204 219 endmenu
+1
drivers/clk/meson/Makefile
··· 26 26 obj-$(CONFIG_COMMON_CLK_MESON8B) += meson8b.o meson8-ddr.o 27 27 obj-$(CONFIG_COMMON_CLK_S4_PLL) += s4-pll.o 28 28 obj-$(CONFIG_COMMON_CLK_S4_PERIPHERALS) += s4-peripherals.o 29 + obj-$(CONFIG_COMMON_CLK_T7_PLL) += t7-pll.o
+1074
drivers/clk/meson/t7-pll.c
··· 1 + // SPDX-License-Identifier: (GPL-2.0-only OR MIT) 2 + /* 3 + * Copyright (C) 2024-2025 Amlogic, Inc. All rights reserved. 4 + * Author: Jian Hu <jian.hu@amlogic.com> 5 + */ 6 + 7 + #include <linux/clk-provider.h> 8 + #include <linux/platform_device.h> 9 + #include "clk-regmap.h" 10 + #include "clk-pll.h" 11 + #include "clk-mpll.h" 12 + #include "meson-clkc-utils.h" 13 + #include <dt-bindings/clock/amlogic,t7-pll-clkc.h> 14 + 15 + #define GP0PLL_CTRL0 0x00 16 + #define GP0PLL_CTRL1 0x04 17 + #define GP0PLL_CTRL2 0x08 18 + #define GP0PLL_CTRL3 0x0c 19 + #define GP0PLL_CTRL4 0x10 20 + #define GP0PLL_CTRL5 0x14 21 + #define GP0PLL_CTRL6 0x18 22 + #define GP0PLL_STS 0x1c 23 + 24 + #define GP1PLL_CTRL0 0x00 25 + #define GP1PLL_CTRL1 0x04 26 + #define GP1PLL_CTRL2 0x08 27 + #define GP1PLL_CTRL3 0x0c 28 + #define GP1PLL_STS 0x1c 29 + 30 + #define HIFIPLL_CTRL0 0x00 31 + #define HIFIPLL_CTRL1 0x04 32 + #define HIFIPLL_CTRL2 0x08 33 + #define HIFIPLL_CTRL3 0x0c 34 + #define HIFIPLL_CTRL4 0x10 35 + #define HIFIPLL_CTRL5 0x14 36 + #define HIFIPLL_CTRL6 0x18 37 + #define HIFIPLL_STS 0x1c 38 + 39 + #define PCIEPLL_CTRL0 0x00 40 + #define PCIEPLL_CTRL1 0x04 41 + #define PCIEPLL_CTRL2 0x08 42 + #define PCIEPLL_CTRL3 0x0c 43 + #define PCIEPLL_CTRL4 0x10 44 + #define PCIEPLL_CTRL5 0x14 45 + #define PCIEPLL_STS 0x18 46 + 47 + #define MPLL_CTRL0 0x00 48 + #define MPLL_CTRL1 0x04 49 + #define MPLL_CTRL2 0x08 50 + #define MPLL_CTRL3 0x0c 51 + #define MPLL_CTRL4 0x10 52 + #define MPLL_CTRL5 0x14 53 + #define MPLL_CTRL6 0x18 54 + #define MPLL_CTRL7 0x1c 55 + #define MPLL_CTRL8 0x20 56 + #define MPLL_STS 0x24 57 + 58 + #define HDMIPLL_CTRL0 0x00 59 + #define HDMIPLL_CTRL1 0x04 60 + #define HDMIPLL_CTRL2 0x08 61 + #define HDMIPLL_CTRL3 0x0c 62 + #define HDMIPLL_CTRL4 0x10 63 + #define HDMIPLL_CTRL5 0x14 64 + #define HDMIPLL_CTRL6 0x18 65 + #define HDMIPLL_STS 0x1c 66 + 67 + #define MCLK_PLL_CNTL0 0x00 68 + #define MCLK_PLL_CNTL1 0x04 69 + #define MCLK_PLL_CNTL2 0x08 70 + #define MCLK_PLL_CNTL3 0x0c 71 + #define MCLK_PLL_CNTL4 0x10 72 + #define MCLK_PLL_STS 0x14 73 + 74 + static const struct pll_mult_range t7_media_pll_mult_range = { 75 + .min = 125, 76 + .max = 250, 77 + }; 78 + 79 + static const struct reg_sequence t7_gp0_init_regs[] = { 80 + { .reg = GP0PLL_CTRL1, .def = 0x00000000 }, 81 + { .reg = GP0PLL_CTRL2, .def = 0x00000000 }, 82 + { .reg = GP0PLL_CTRL3, .def = 0x48681c00 }, 83 + { .reg = GP0PLL_CTRL4, .def = 0x88770290 }, 84 + { .reg = GP0PLL_CTRL5, .def = 0x3927200a }, 85 + { .reg = GP0PLL_CTRL6, .def = 0x56540000 }, 86 + }; 87 + 88 + static struct clk_regmap t7_gp0_pll_dco = { 89 + .data = &(struct meson_clk_pll_data){ 90 + .en = { 91 + .reg_off = GP0PLL_CTRL0, 92 + .shift = 28, 93 + .width = 1, 94 + }, 95 + .m = { 96 + .reg_off = GP0PLL_CTRL0, 97 + .shift = 0, 98 + .width = 8, 99 + }, 100 + .n = { 101 + .reg_off = GP0PLL_CTRL0, 102 + .shift = 10, 103 + .width = 5, 104 + }, 105 + .l = { 106 + .reg_off = GP0PLL_STS, 107 + .shift = 31, 108 + .width = 1, 109 + }, 110 + .rst = { 111 + .reg_off = GP0PLL_CTRL0, 112 + .shift = 29, 113 + .width = 1, 114 + }, 115 + .range = &t7_media_pll_mult_range, 116 + .init_regs = t7_gp0_init_regs, 117 + .init_count = ARRAY_SIZE(t7_gp0_init_regs), 118 + }, 119 + .hw.init = &(struct clk_init_data){ 120 + .name = "gp0_pll_dco", 121 + .ops = &meson_clk_pll_ops, 122 + .parent_data = &(const struct clk_parent_data) { 123 + .fw_name = "in0", 124 + }, 125 + .num_parents = 1, 126 + }, 127 + }; 128 + 129 + static struct clk_regmap t7_gp0_pll = { 130 + .data = &(struct clk_regmap_div_data){ 131 + .offset = GP0PLL_CTRL0, 132 + .shift = 16, 133 + .width = 3, 134 + .flags = CLK_DIVIDER_POWER_OF_TWO, 135 + }, 136 + .hw.init = &(struct clk_init_data) { 137 + .name = "gp0_pll", 138 + .ops = &clk_regmap_divider_ops, 139 + .parent_hws = (const struct clk_hw *[]) { 140 + &t7_gp0_pll_dco.hw 141 + }, 142 + .num_parents = 1, 143 + .flags = CLK_SET_RATE_PARENT, 144 + }, 145 + }; 146 + 147 + /* 148 + * Compared with GP0 PLL, GP1 PLL is a newly designed PLL with 149 + * a DCO range of 1.6GHz to 3.2GHz. 150 + */ 151 + static const struct pll_mult_range t7_gp1_pll_mult_range = { 152 + .min = 67, 153 + .max = 133, 154 + }; 155 + 156 + static const struct reg_sequence t7_gp1_init_regs[] = { 157 + { .reg = GP1PLL_CTRL1, .def = 0x1420500f }, 158 + { .reg = GP1PLL_CTRL2, .def = 0x00023001 }, 159 + { .reg = GP1PLL_CTRL3, .def = 0x00000000 }, 160 + }; 161 + 162 + static struct clk_regmap t7_gp1_pll_dco = { 163 + .data = &(struct meson_clk_pll_data){ 164 + .en = { 165 + .reg_off = GP1PLL_CTRL0, 166 + .shift = 28, 167 + .width = 1, 168 + }, 169 + .m = { 170 + .reg_off = GP1PLL_CTRL0, 171 + .shift = 0, 172 + .width = 8, 173 + }, 174 + .n = { 175 + .reg_off = GP1PLL_CTRL0, 176 + .shift = 16, 177 + .width = 5, 178 + }, 179 + .l = { 180 + .reg_off = GP1PLL_STS, 181 + .shift = 31, 182 + .width = 1, 183 + }, 184 + .rst = { 185 + .reg_off = GP1PLL_CTRL0, 186 + .shift = 29, 187 + .width = 1, 188 + }, 189 + .range = &t7_gp1_pll_mult_range, 190 + .init_regs = t7_gp1_init_regs, 191 + .init_count = ARRAY_SIZE(t7_gp1_init_regs), 192 + }, 193 + .hw.init = &(struct clk_init_data){ 194 + .name = "gp1_pll_dco", 195 + .ops = &meson_clk_pll_ops, 196 + .parent_data = &(const struct clk_parent_data) { 197 + .fw_name = "in0", 198 + }, 199 + .num_parents = 1, 200 + }, 201 + }; 202 + 203 + static struct clk_regmap t7_gp1_pll = { 204 + .data = &(struct clk_regmap_div_data){ 205 + .offset = GP1PLL_CTRL0, 206 + .shift = 12, 207 + .width = 3, 208 + .flags = CLK_DIVIDER_POWER_OF_TWO, 209 + }, 210 + .hw.init = &(struct clk_init_data) { 211 + .name = "gp1_pll", 212 + .ops = &clk_regmap_divider_ops, 213 + .parent_hws = (const struct clk_hw *[]) { 214 + &t7_gp1_pll_dco.hw 215 + }, 216 + .num_parents = 1, 217 + .flags = CLK_SET_RATE_PARENT, 218 + }, 219 + }; 220 + 221 + static const struct reg_sequence t7_hifi_init_regs[] = { 222 + { .reg = HIFIPLL_CTRL1, .def = 0x00000000 }, 223 + { .reg = HIFIPLL_CTRL2, .def = 0x00000000 }, 224 + { .reg = HIFIPLL_CTRL3, .def = 0x6a285c00 }, 225 + { .reg = HIFIPLL_CTRL4, .def = 0x65771290 }, 226 + { .reg = HIFIPLL_CTRL5, .def = 0x3927200a }, 227 + { .reg = HIFIPLL_CTRL6, .def = 0x56540000 } 228 + }; 229 + 230 + static struct clk_regmap t7_hifi_pll_dco = { 231 + .data = &(struct meson_clk_pll_data){ 232 + .en = { 233 + .reg_off = HIFIPLL_CTRL0, 234 + .shift = 28, 235 + .width = 1, 236 + }, 237 + .m = { 238 + .reg_off = HIFIPLL_CTRL0, 239 + .shift = 0, 240 + .width = 8, 241 + }, 242 + .n = { 243 + .reg_off = HIFIPLL_CTRL0, 244 + .shift = 10, 245 + .width = 5, 246 + }, 247 + .frac = { 248 + .reg_off = HIFIPLL_CTRL1, 249 + .shift = 0, 250 + .width = 17, 251 + }, 252 + .l = { 253 + .reg_off = HIFIPLL_STS, 254 + .shift = 31, 255 + .width = 1, 256 + }, 257 + .rst = { 258 + .reg_off = HIFIPLL_CTRL0, 259 + .shift = 29, 260 + .width = 1, 261 + }, 262 + .range = &t7_media_pll_mult_range, 263 + .init_regs = t7_hifi_init_regs, 264 + .init_count = ARRAY_SIZE(t7_hifi_init_regs), 265 + .frac_max = 100000, 266 + }, 267 + .hw.init = &(struct clk_init_data){ 268 + .name = "hifi_pll_dco", 269 + .ops = &meson_clk_pll_ops, 270 + .parent_data = &(const struct clk_parent_data) { 271 + .fw_name = "in0", 272 + }, 273 + .num_parents = 1, 274 + }, 275 + }; 276 + 277 + static struct clk_regmap t7_hifi_pll = { 278 + .data = &(struct clk_regmap_div_data){ 279 + .offset = HIFIPLL_CTRL0, 280 + .shift = 16, 281 + .width = 2, 282 + .flags = CLK_DIVIDER_POWER_OF_TWO, 283 + }, 284 + .hw.init = &(struct clk_init_data) { 285 + .name = "hifi_pll", 286 + .ops = &clk_regmap_divider_ops, 287 + .parent_hws = (const struct clk_hw *[]) { 288 + &t7_hifi_pll_dco.hw 289 + }, 290 + .num_parents = 1, 291 + .flags = CLK_SET_RATE_PARENT, 292 + }, 293 + }; 294 + 295 + /* 296 + * The T7 PCIE PLL is fined tuned to deliver a very precise 297 + * 100MHz reference clock for the PCIe Analog PHY, and thus requires 298 + * a strict register sequence to enable the PLL. 299 + */ 300 + static const struct reg_sequence t7_pcie_pll_init_regs[] = { 301 + { .reg = PCIEPLL_CTRL0, .def = 0x200c04c8 }, 302 + { .reg = PCIEPLL_CTRL0, .def = 0x300c04c8 }, 303 + { .reg = PCIEPLL_CTRL1, .def = 0x30000000 }, 304 + { .reg = PCIEPLL_CTRL2, .def = 0x00001100 }, 305 + { .reg = PCIEPLL_CTRL3, .def = 0x10058e00 }, 306 + { .reg = PCIEPLL_CTRL4, .def = 0x000100c0 }, 307 + { .reg = PCIEPLL_CTRL5, .def = 0x68000048 }, 308 + { .reg = PCIEPLL_CTRL5, .def = 0x68000068, .delay_us = 20 }, 309 + { .reg = PCIEPLL_CTRL4, .def = 0x008100c0, .delay_us = 20 }, 310 + { .reg = PCIEPLL_CTRL0, .def = 0x340c04c8 }, 311 + { .reg = PCIEPLL_CTRL0, .def = 0x140c04c8, .delay_us = 20 }, 312 + { .reg = PCIEPLL_CTRL2, .def = 0x00001000 } 313 + }; 314 + 315 + static struct clk_regmap t7_pcie_pll_dco = { 316 + .data = &(struct meson_clk_pll_data){ 317 + .en = { 318 + .reg_off = PCIEPLL_CTRL0, 319 + .shift = 28, 320 + .width = 1, 321 + }, 322 + .m = { 323 + .reg_off = PCIEPLL_CTRL0, 324 + .shift = 0, 325 + .width = 8, 326 + }, 327 + .n = { 328 + .reg_off = PCIEPLL_CTRL0, 329 + .shift = 10, 330 + .width = 5, 331 + }, 332 + .l = { 333 + .reg_off = PCIEPLL_CTRL0, 334 + .shift = 31, 335 + .width = 1, 336 + }, 337 + .rst = { 338 + .reg_off = PCIEPLL_CTRL0, 339 + .shift = 29, 340 + .width = 1, 341 + }, 342 + .init_regs = t7_pcie_pll_init_regs, 343 + .init_count = ARRAY_SIZE(t7_pcie_pll_init_regs), 344 + }, 345 + .hw.init = &(struct clk_init_data){ 346 + .name = "pcie_pll_dco", 347 + .ops = &meson_clk_pcie_pll_ops, 348 + .parent_data = &(const struct clk_parent_data) { 349 + .fw_name = "in0", 350 + }, 351 + .num_parents = 1, 352 + }, 353 + }; 354 + 355 + static struct clk_fixed_factor t7_pcie_pll_dco_div2 = { 356 + .mult = 1, 357 + .div = 2, 358 + .hw.init = &(struct clk_init_data){ 359 + .name = "pcie_pll_dco_div2", 360 + .ops = &clk_fixed_factor_ops, 361 + .parent_hws = (const struct clk_hw *[]) { 362 + &t7_pcie_pll_dco.hw 363 + }, 364 + .num_parents = 1, 365 + .flags = CLK_SET_RATE_PARENT, 366 + }, 367 + }; 368 + 369 + static struct clk_regmap t7_pcie_pll_od = { 370 + .data = &(struct clk_regmap_div_data){ 371 + .offset = PCIEPLL_CTRL0, 372 + .shift = 16, 373 + .width = 5, 374 + /* the divisor is 32 when [16:21] = 0 */ 375 + .flags = CLK_DIVIDER_MAX_AT_ZERO, 376 + }, 377 + .hw.init = &(struct clk_init_data){ 378 + .name = "pcie_pll_od", 379 + .ops = &clk_regmap_divider_ops, 380 + .parent_hws = (const struct clk_hw *[]) { 381 + &t7_pcie_pll_dco_div2.hw 382 + }, 383 + .num_parents = 1, 384 + .flags = CLK_SET_RATE_PARENT, 385 + }, 386 + }; 387 + 388 + static struct clk_fixed_factor t7_pcie_pll = { 389 + .mult = 1, 390 + .div = 2, 391 + .hw.init = &(struct clk_init_data){ 392 + .name = "pcie_pll", 393 + .ops = &clk_fixed_factor_ops, 394 + .parent_hws = (const struct clk_hw *[]) { 395 + &t7_pcie_pll_od.hw 396 + }, 397 + .num_parents = 1, 398 + .flags = CLK_SET_RATE_PARENT, 399 + }, 400 + }; 401 + 402 + static struct clk_fixed_factor t7_mpll_prediv = { 403 + .mult = 1, 404 + .div = 2, 405 + .hw.init = &(struct clk_init_data){ 406 + .name = "mpll_prediv", 407 + .ops = &clk_fixed_factor_ops, 408 + .parent_data = &(const struct clk_parent_data) { 409 + .fw_name = "in0", 410 + }, 411 + .num_parents = 1, 412 + }, 413 + }; 414 + 415 + static const struct reg_sequence t7_mpll0_init_regs[] = { 416 + { .reg = MPLL_CTRL2, .def = 0x40000033 } 417 + }; 418 + 419 + static struct clk_regmap t7_mpll0_div = { 420 + .data = &(struct meson_clk_mpll_data){ 421 + .sdm = { 422 + .reg_off = MPLL_CTRL1, 423 + .shift = 0, 424 + .width = 14, 425 + }, 426 + .sdm_en = { 427 + .reg_off = MPLL_CTRL1, 428 + .shift = 30, 429 + .width = 1, 430 + }, 431 + .n2 = { 432 + .reg_off = MPLL_CTRL1, 433 + .shift = 20, 434 + .width = 9, 435 + }, 436 + .ssen = { 437 + .reg_off = MPLL_CTRL1, 438 + .shift = 29, 439 + .width = 1, 440 + }, 441 + .init_regs = t7_mpll0_init_regs, 442 + .init_count = ARRAY_SIZE(t7_mpll0_init_regs), 443 + }, 444 + .hw.init = &(struct clk_init_data){ 445 + .name = "mpll0_div", 446 + .ops = &meson_clk_mpll_ops, 447 + .parent_hws = (const struct clk_hw *[]) { 448 + &t7_mpll_prediv.hw 449 + }, 450 + .num_parents = 1, 451 + }, 452 + }; 453 + 454 + static struct clk_regmap t7_mpll0 = { 455 + .data = &(struct clk_regmap_gate_data){ 456 + .offset = MPLL_CTRL1, 457 + .bit_idx = 31, 458 + }, 459 + .hw.init = &(struct clk_init_data){ 460 + .name = "mpll0", 461 + .ops = &clk_regmap_gate_ops, 462 + .parent_hws = (const struct clk_hw *[]) { &t7_mpll0_div.hw }, 463 + .num_parents = 1, 464 + .flags = CLK_SET_RATE_PARENT, 465 + }, 466 + }; 467 + 468 + static const struct reg_sequence t7_mpll1_init_regs[] = { 469 + { .reg = MPLL_CTRL4, .def = 0x40000033 } 470 + }; 471 + 472 + static struct clk_regmap t7_mpll1_div = { 473 + .data = &(struct meson_clk_mpll_data){ 474 + .sdm = { 475 + .reg_off = MPLL_CTRL3, 476 + .shift = 0, 477 + .width = 14, 478 + }, 479 + .sdm_en = { 480 + .reg_off = MPLL_CTRL3, 481 + .shift = 30, 482 + .width = 1, 483 + }, 484 + .n2 = { 485 + .reg_off = MPLL_CTRL3, 486 + .shift = 20, 487 + .width = 9, 488 + }, 489 + .ssen = { 490 + .reg_off = MPLL_CTRL3, 491 + .shift = 29, 492 + .width = 1, 493 + }, 494 + .init_regs = t7_mpll1_init_regs, 495 + .init_count = ARRAY_SIZE(t7_mpll1_init_regs), 496 + }, 497 + .hw.init = &(struct clk_init_data){ 498 + .name = "mpll1_div", 499 + .ops = &meson_clk_mpll_ops, 500 + .parent_hws = (const struct clk_hw *[]) { 501 + &t7_mpll_prediv.hw 502 + }, 503 + .num_parents = 1, 504 + }, 505 + }; 506 + 507 + static struct clk_regmap t7_mpll1 = { 508 + .data = &(struct clk_regmap_gate_data){ 509 + .offset = MPLL_CTRL3, 510 + .bit_idx = 31, 511 + }, 512 + .hw.init = &(struct clk_init_data){ 513 + .name = "mpll1", 514 + .ops = &clk_regmap_gate_ops, 515 + .parent_hws = (const struct clk_hw *[]) { &t7_mpll1_div.hw }, 516 + .num_parents = 1, 517 + .flags = CLK_SET_RATE_PARENT, 518 + }, 519 + }; 520 + 521 + static const struct reg_sequence t7_mpll2_init_regs[] = { 522 + { .reg = MPLL_CTRL6, .def = 0x40000033 } 523 + }; 524 + 525 + static struct clk_regmap t7_mpll2_div = { 526 + .data = &(struct meson_clk_mpll_data){ 527 + .sdm = { 528 + .reg_off = MPLL_CTRL5, 529 + .shift = 0, 530 + .width = 14, 531 + }, 532 + .sdm_en = { 533 + .reg_off = MPLL_CTRL5, 534 + .shift = 30, 535 + .width = 1, 536 + }, 537 + .n2 = { 538 + .reg_off = MPLL_CTRL5, 539 + .shift = 20, 540 + .width = 9, 541 + }, 542 + .ssen = { 543 + .reg_off = MPLL_CTRL5, 544 + .shift = 29, 545 + .width = 1, 546 + }, 547 + .init_regs = t7_mpll2_init_regs, 548 + .init_count = ARRAY_SIZE(t7_mpll2_init_regs), 549 + }, 550 + .hw.init = &(struct clk_init_data){ 551 + .name = "mpll2_div", 552 + .ops = &meson_clk_mpll_ops, 553 + .parent_hws = (const struct clk_hw *[]) { 554 + &t7_mpll_prediv.hw 555 + }, 556 + .num_parents = 1, 557 + }, 558 + }; 559 + 560 + static struct clk_regmap t7_mpll2 = { 561 + .data = &(struct clk_regmap_gate_data){ 562 + .offset = MPLL_CTRL5, 563 + .bit_idx = 31, 564 + }, 565 + .hw.init = &(struct clk_init_data){ 566 + .name = "mpll2", 567 + .ops = &clk_regmap_gate_ops, 568 + .parent_hws = (const struct clk_hw *[]) { &t7_mpll2_div.hw }, 569 + .num_parents = 1, 570 + .flags = CLK_SET_RATE_PARENT, 571 + }, 572 + }; 573 + 574 + static const struct reg_sequence t7_mpll3_init_regs[] = { 575 + { .reg = MPLL_CTRL8, .def = 0x40000033 } 576 + }; 577 + 578 + static struct clk_regmap t7_mpll3_div = { 579 + .data = &(struct meson_clk_mpll_data){ 580 + .sdm = { 581 + .reg_off = MPLL_CTRL7, 582 + .shift = 0, 583 + .width = 14, 584 + }, 585 + .sdm_en = { 586 + .reg_off = MPLL_CTRL7, 587 + .shift = 30, 588 + .width = 1, 589 + }, 590 + .n2 = { 591 + .reg_off = MPLL_CTRL7, 592 + .shift = 20, 593 + .width = 9, 594 + }, 595 + .ssen = { 596 + .reg_off = MPLL_CTRL7, 597 + .shift = 29, 598 + .width = 1, 599 + }, 600 + .init_regs = t7_mpll3_init_regs, 601 + .init_count = ARRAY_SIZE(t7_mpll3_init_regs), 602 + }, 603 + .hw.init = &(struct clk_init_data){ 604 + .name = "mpll3_div", 605 + .ops = &meson_clk_mpll_ops, 606 + .parent_hws = (const struct clk_hw *[]) { 607 + &t7_mpll_prediv.hw 608 + }, 609 + .num_parents = 1, 610 + }, 611 + }; 612 + 613 + static struct clk_regmap t7_mpll3 = { 614 + .data = &(struct clk_regmap_gate_data){ 615 + .offset = MPLL_CTRL7, 616 + .bit_idx = 31, 617 + }, 618 + .hw.init = &(struct clk_init_data){ 619 + .name = "mpll3", 620 + .ops = &clk_regmap_gate_ops, 621 + .parent_hws = (const struct clk_hw *[]) { &t7_mpll3_div.hw }, 622 + .num_parents = 1, 623 + .flags = CLK_SET_RATE_PARENT, 624 + }, 625 + }; 626 + 627 + static const struct reg_sequence t7_hdmi_init_regs[] = { 628 + { .reg = HDMIPLL_CTRL1, .def = 0x00000000 }, 629 + { .reg = HDMIPLL_CTRL2, .def = 0x00000000 }, 630 + { .reg = HDMIPLL_CTRL3, .def = 0x6a28dc00 }, 631 + { .reg = HDMIPLL_CTRL4, .def = 0x65771290 }, 632 + { .reg = HDMIPLL_CTRL5, .def = 0x39272000 }, 633 + { .reg = HDMIPLL_CTRL6, .def = 0x56540000 } 634 + }; 635 + 636 + static struct clk_regmap t7_hdmi_pll_dco = { 637 + .data = &(struct meson_clk_pll_data){ 638 + .en = { 639 + .reg_off = HDMIPLL_CTRL0, 640 + .shift = 28, 641 + .width = 1, 642 + }, 643 + .m = { 644 + .reg_off = HDMIPLL_CTRL0, 645 + .shift = 0, 646 + .width = 9, 647 + }, 648 + .n = { 649 + .reg_off = HDMIPLL_CTRL0, 650 + .shift = 10, 651 + .width = 5, 652 + }, 653 + .l = { 654 + .reg_off = HDMIPLL_CTRL0, 655 + .shift = 31, 656 + .width = 1, 657 + }, 658 + .rst = { 659 + .reg_off = HDMIPLL_CTRL0, 660 + .shift = 29, 661 + .width = 1, 662 + }, 663 + .range = &t7_media_pll_mult_range, 664 + .init_regs = t7_hdmi_init_regs, 665 + .init_count = ARRAY_SIZE(t7_hdmi_init_regs), 666 + }, 667 + .hw.init = &(struct clk_init_data){ 668 + .name = "hdmi_pll_dco", 669 + .ops = &meson_clk_pll_ops, 670 + .parent_data = (const struct clk_parent_data []) { 671 + { .fw_name = "in0", } 672 + }, 673 + .num_parents = 1, 674 + }, 675 + }; 676 + 677 + static struct clk_regmap t7_hdmi_pll_od = { 678 + .data = &(struct clk_regmap_div_data){ 679 + .offset = HDMIPLL_CTRL0, 680 + .shift = 16, 681 + .width = 4, 682 + .flags = CLK_DIVIDER_POWER_OF_TWO, 683 + }, 684 + .hw.init = &(struct clk_init_data){ 685 + .name = "hdmi_pll_od", 686 + .ops = &clk_regmap_divider_ops, 687 + .parent_hws = (const struct clk_hw *[]) { 688 + &t7_hdmi_pll_dco.hw 689 + }, 690 + .num_parents = 1, 691 + .flags = CLK_SET_RATE_PARENT, 692 + }, 693 + }; 694 + 695 + static struct clk_regmap t7_hdmi_pll = { 696 + .data = &(struct clk_regmap_div_data){ 697 + .offset = HDMIPLL_CTRL0, 698 + .shift = 20, 699 + .width = 2, 700 + .flags = CLK_DIVIDER_POWER_OF_TWO, 701 + }, 702 + .hw.init = &(struct clk_init_data){ 703 + .name = "hdmi_pll", 704 + .ops = &clk_regmap_divider_ops, 705 + .parent_hws = (const struct clk_hw *[]) { 706 + &t7_hdmi_pll_od.hw 707 + }, 708 + .num_parents = 1, 709 + .flags = CLK_SET_RATE_PARENT, 710 + }, 711 + }; 712 + 713 + static const struct pll_mult_range t7_mclk_pll_mult_range = { 714 + .min = 67, 715 + .max = 133, 716 + }; 717 + 718 + static const struct reg_sequence t7_mclk_init_regs[] = { 719 + { .reg = MCLK_PLL_CNTL1, .def = 0x1470500f }, 720 + { .reg = MCLK_PLL_CNTL2, .def = 0x00023001 }, 721 + { .reg = MCLK_PLL_CNTL3, .def = 0x18180000 }, 722 + { .reg = MCLK_PLL_CNTL4, .def = 0x00180303 }, 723 + }; 724 + 725 + static struct clk_regmap t7_mclk_pll_dco = { 726 + .data = &(struct meson_clk_pll_data){ 727 + .en = { 728 + .reg_off = MCLK_PLL_CNTL0, 729 + .shift = 28, 730 + .width = 1, 731 + }, 732 + .m = { 733 + .reg_off = MCLK_PLL_CNTL0, 734 + .shift = 0, 735 + .width = 8, 736 + }, 737 + .n = { 738 + .reg_off = MCLK_PLL_CNTL0, 739 + .shift = 16, 740 + .width = 5, 741 + }, 742 + .l = { 743 + .reg_off = MCLK_PLL_CNTL0, 744 + .shift = 31, 745 + .width = 1, 746 + }, 747 + .rst = { 748 + .reg_off = MCLK_PLL_CNTL0, 749 + .shift = 29, 750 + .width = 1, 751 + }, 752 + .l_detect = { 753 + .reg_off = MCLK_PLL_CNTL2, 754 + .shift = 6, 755 + .width = 1, 756 + }, 757 + .range = &t7_mclk_pll_mult_range, 758 + .init_regs = t7_mclk_init_regs, 759 + .init_count = ARRAY_SIZE(t7_mclk_init_regs), 760 + }, 761 + .hw.init = &(struct clk_init_data){ 762 + .name = "mclk_pll_dco", 763 + .ops = &meson_clk_pll_ops, 764 + .parent_data = &(const struct clk_parent_data) { 765 + .fw_name = "in0", 766 + }, 767 + .num_parents = 1, 768 + }, 769 + }; 770 + 771 + /* max div is 16 */ 772 + static const struct clk_div_table t7_mclk_div[] = { 773 + { .val = 0, .div = 1 }, 774 + { .val = 1, .div = 2 }, 775 + { .val = 2, .div = 4 }, 776 + { .val = 3, .div = 8 }, 777 + { .val = 4, .div = 16 }, 778 + { /* sentinel */ } 779 + }; 780 + 781 + static struct clk_regmap t7_mclk_pre_od = { 782 + .data = &(struct clk_regmap_div_data){ 783 + .offset = MCLK_PLL_CNTL0, 784 + .shift = 12, 785 + .width = 3, 786 + .table = t7_mclk_div, 787 + }, 788 + .hw.init = &(struct clk_init_data){ 789 + .name = "mclk_pre_od", 790 + .ops = &clk_regmap_divider_ops, 791 + .parent_hws = (const struct clk_hw *[]) { 792 + &t7_mclk_pll_dco.hw 793 + }, 794 + .num_parents = 1, 795 + .flags = CLK_SET_RATE_PARENT, 796 + }, 797 + }; 798 + 799 + static struct clk_regmap t7_mclk_pll = { 800 + .data = &(struct clk_regmap_div_data){ 801 + .offset = MCLK_PLL_CNTL4, 802 + .shift = 16, 803 + .width = 5, 804 + .flags = CLK_DIVIDER_ONE_BASED, 805 + }, 806 + .hw.init = &(struct clk_init_data){ 807 + .name = "mclk_pll", 808 + .ops = &clk_regmap_divider_ops, 809 + .parent_hws = (const struct clk_hw *[]) { 810 + &t7_mclk_pre_od.hw 811 + }, 812 + .num_parents = 1, 813 + .flags = CLK_SET_RATE_PARENT, 814 + }, 815 + }; 816 + 817 + static struct clk_regmap t7_mclk_0_sel = { 818 + .data = &(struct clk_regmap_mux_data){ 819 + .offset = MCLK_PLL_CNTL4, 820 + .mask = 0x3, 821 + .shift = 4, 822 + }, 823 + .hw.init = &(struct clk_init_data){ 824 + .name = "mclk_0_sel", 825 + .ops = &clk_regmap_mux_ops, 826 + .parent_data = (const struct clk_parent_data []) { 827 + { .hw = &t7_mclk_pll.hw }, 828 + { .fw_name = "in1", }, 829 + { .fw_name = "in2", }, 830 + }, 831 + .num_parents = 3, 832 + }, 833 + }; 834 + 835 + static struct clk_fixed_factor t7_mclk_0_div2 = { 836 + .mult = 1, 837 + .div = 2, 838 + .hw.init = &(struct clk_init_data){ 839 + .name = "mclk_0_div2", 840 + .ops = &clk_fixed_factor_ops, 841 + .parent_hws = (const struct clk_hw *[]) { &t7_mclk_0_sel.hw }, 842 + .num_parents = 1, 843 + .flags = CLK_SET_RATE_PARENT, 844 + }, 845 + }; 846 + 847 + static struct clk_regmap t7_mclk_0_pre = { 848 + .data = &(struct clk_regmap_gate_data){ 849 + .offset = MCLK_PLL_CNTL4, 850 + .bit_idx = 2, 851 + }, 852 + .hw.init = &(struct clk_init_data) { 853 + .name = "mclk_0_pre", 854 + .ops = &clk_regmap_gate_ops, 855 + .parent_hws = (const struct clk_hw *[]) { 856 + &t7_mclk_0_div2.hw 857 + }, 858 + .num_parents = 1, 859 + .flags = CLK_SET_RATE_PARENT, 860 + }, 861 + }; 862 + 863 + static struct clk_regmap t7_mclk_0 = { 864 + .data = &(struct clk_regmap_gate_data){ 865 + .offset = MCLK_PLL_CNTL4, 866 + .bit_idx = 0, 867 + }, 868 + .hw.init = &(struct clk_init_data) { 869 + .name = "mclk_0", 870 + .ops = &clk_regmap_gate_ops, 871 + .parent_hws = (const struct clk_hw *[]) { 872 + &t7_mclk_0_pre.hw 873 + }, 874 + .num_parents = 1, 875 + .flags = CLK_SET_RATE_PARENT, 876 + }, 877 + }; 878 + 879 + static struct clk_regmap t7_mclk_1_sel = { 880 + .data = &(struct clk_regmap_mux_data){ 881 + .offset = MCLK_PLL_CNTL4, 882 + .mask = 0x3, 883 + .shift = 12, 884 + }, 885 + .hw.init = &(struct clk_init_data){ 886 + .name = "mclk_1_sel", 887 + .ops = &clk_regmap_mux_ops, 888 + .parent_data = (const struct clk_parent_data []) { 889 + { .hw = &t7_mclk_pll.hw }, 890 + { .fw_name = "in1", }, 891 + { .fw_name = "in2", }, 892 + }, 893 + .num_parents = 3, 894 + }, 895 + }; 896 + 897 + static struct clk_fixed_factor t7_mclk_1_div2 = { 898 + .mult = 1, 899 + .div = 2, 900 + .hw.init = &(struct clk_init_data){ 901 + .name = "mclk_1_div2", 902 + .ops = &clk_fixed_factor_ops, 903 + .parent_hws = (const struct clk_hw *[]) { &t7_mclk_1_sel.hw }, 904 + .num_parents = 1, 905 + .flags = CLK_SET_RATE_PARENT, 906 + }, 907 + }; 908 + 909 + static struct clk_regmap t7_mclk_1_pre = { 910 + .data = &(struct clk_regmap_gate_data){ 911 + .offset = MCLK_PLL_CNTL4, 912 + .bit_idx = 10, 913 + }, 914 + .hw.init = &(struct clk_init_data) { 915 + .name = "mclk_1_pre", 916 + .ops = &clk_regmap_gate_ops, 917 + .parent_hws = (const struct clk_hw *[]) { 918 + &t7_mclk_1_div2.hw 919 + }, 920 + .num_parents = 1, 921 + .flags = CLK_SET_RATE_PARENT, 922 + }, 923 + }; 924 + 925 + static struct clk_regmap t7_mclk_1 = { 926 + .data = &(struct clk_regmap_gate_data){ 927 + .offset = MCLK_PLL_CNTL4, 928 + .bit_idx = 8, 929 + }, 930 + .hw.init = &(struct clk_init_data) { 931 + .name = "mclk_1", 932 + .ops = &clk_regmap_gate_ops, 933 + .parent_hws = (const struct clk_hw *[]) { 934 + &t7_mclk_1_pre.hw 935 + }, 936 + .num_parents = 1, 937 + .flags = CLK_SET_RATE_PARENT, 938 + }, 939 + }; 940 + 941 + static struct clk_hw *t7_gp0_hw_clks[] = { 942 + [CLKID_GP0_PLL_DCO] = &t7_gp0_pll_dco.hw, 943 + [CLKID_GP0_PLL] = &t7_gp0_pll.hw, 944 + }; 945 + 946 + static struct clk_hw *t7_gp1_hw_clks[] = { 947 + [CLKID_GP1_PLL_DCO] = &t7_gp1_pll_dco.hw, 948 + [CLKID_GP1_PLL] = &t7_gp1_pll.hw, 949 + }; 950 + 951 + static struct clk_hw *t7_hifi_hw_clks[] = { 952 + [CLKID_HIFI_PLL_DCO] = &t7_hifi_pll_dco.hw, 953 + [CLKID_HIFI_PLL] = &t7_hifi_pll.hw, 954 + }; 955 + 956 + static struct clk_hw *t7_pcie_hw_clks[] = { 957 + [CLKID_PCIE_PLL_DCO] = &t7_pcie_pll_dco.hw, 958 + [CLKID_PCIE_PLL_DCO_DIV2] = &t7_pcie_pll_dco_div2.hw, 959 + [CLKID_PCIE_PLL_OD] = &t7_pcie_pll_od.hw, 960 + [CLKID_PCIE_PLL] = &t7_pcie_pll.hw, 961 + }; 962 + 963 + static struct clk_hw *t7_mpll_hw_clks[] = { 964 + [CLKID_MPLL_PREDIV] = &t7_mpll_prediv.hw, 965 + [CLKID_MPLL0_DIV] = &t7_mpll0_div.hw, 966 + [CLKID_MPLL0] = &t7_mpll0.hw, 967 + [CLKID_MPLL1_DIV] = &t7_mpll1_div.hw, 968 + [CLKID_MPLL1] = &t7_mpll1.hw, 969 + [CLKID_MPLL2_DIV] = &t7_mpll2_div.hw, 970 + [CLKID_MPLL2] = &t7_mpll2.hw, 971 + [CLKID_MPLL3_DIV] = &t7_mpll3_div.hw, 972 + [CLKID_MPLL3] = &t7_mpll3.hw, 973 + }; 974 + 975 + static struct clk_hw *t7_hdmi_hw_clks[] = { 976 + [CLKID_HDMI_PLL_DCO] = &t7_hdmi_pll_dco.hw, 977 + [CLKID_HDMI_PLL_OD] = &t7_hdmi_pll_od.hw, 978 + [CLKID_HDMI_PLL] = &t7_hdmi_pll.hw, 979 + }; 980 + 981 + static struct clk_hw *t7_mclk_hw_clks[] = { 982 + [CLKID_MCLK_PLL_DCO] = &t7_mclk_pll_dco.hw, 983 + [CLKID_MCLK_PRE] = &t7_mclk_pre_od.hw, 984 + [CLKID_MCLK_PLL] = &t7_mclk_pll.hw, 985 + [CLKID_MCLK_0_SEL] = &t7_mclk_0_sel.hw, 986 + [CLKID_MCLK_0_DIV2] = &t7_mclk_0_div2.hw, 987 + [CLKID_MCLK_0_PRE] = &t7_mclk_0_pre.hw, 988 + [CLKID_MCLK_0] = &t7_mclk_0.hw, 989 + [CLKID_MCLK_1_SEL] = &t7_mclk_1_sel.hw, 990 + [CLKID_MCLK_1_DIV2] = &t7_mclk_1_div2.hw, 991 + [CLKID_MCLK_1_PRE] = &t7_mclk_1_pre.hw, 992 + [CLKID_MCLK_1] = &t7_mclk_1.hw, 993 + }; 994 + 995 + static const struct meson_clkc_data t7_gp0_data = { 996 + .hw_clks = { 997 + .hws = t7_gp0_hw_clks, 998 + .num = ARRAY_SIZE(t7_gp0_hw_clks), 999 + }, 1000 + }; 1001 + 1002 + static const struct meson_clkc_data t7_gp1_data = { 1003 + .hw_clks = { 1004 + .hws = t7_gp1_hw_clks, 1005 + .num = ARRAY_SIZE(t7_gp1_hw_clks), 1006 + }, 1007 + }; 1008 + 1009 + static const struct meson_clkc_data t7_hifi_data = { 1010 + .hw_clks = { 1011 + .hws = t7_hifi_hw_clks, 1012 + .num = ARRAY_SIZE(t7_hifi_hw_clks), 1013 + }, 1014 + }; 1015 + 1016 + static const struct meson_clkc_data t7_pcie_data = { 1017 + .hw_clks = { 1018 + .hws = t7_pcie_hw_clks, 1019 + .num = ARRAY_SIZE(t7_pcie_hw_clks), 1020 + }, 1021 + }; 1022 + 1023 + static const struct reg_sequence t7_mpll_init_regs[] = { 1024 + { .reg = MPLL_CTRL0, .def = 0x00000543 } 1025 + }; 1026 + 1027 + static const struct meson_clkc_data t7_mpll_data = { 1028 + .hw_clks = { 1029 + .hws = t7_mpll_hw_clks, 1030 + .num = ARRAY_SIZE(t7_mpll_hw_clks), 1031 + }, 1032 + .init_regs = t7_mpll_init_regs, 1033 + .init_count = ARRAY_SIZE(t7_mpll_init_regs), 1034 + }; 1035 + 1036 + static const struct meson_clkc_data t7_hdmi_data = { 1037 + .hw_clks = { 1038 + .hws = t7_hdmi_hw_clks, 1039 + .num = ARRAY_SIZE(t7_hdmi_hw_clks), 1040 + }, 1041 + }; 1042 + 1043 + static const struct meson_clkc_data t7_mclk_data = { 1044 + .hw_clks = { 1045 + .hws = t7_mclk_hw_clks, 1046 + .num = ARRAY_SIZE(t7_mclk_hw_clks), 1047 + }, 1048 + }; 1049 + 1050 + static const struct of_device_id t7_pll_clkc_match_table[] = { 1051 + { .compatible = "amlogic,t7-gp0-pll", .data = &t7_gp0_data, }, 1052 + { .compatible = "amlogic,t7-gp1-pll", .data = &t7_gp1_data, }, 1053 + { .compatible = "amlogic,t7-hifi-pll", .data = &t7_hifi_data, }, 1054 + { .compatible = "amlogic,t7-pcie-pll", .data = &t7_pcie_data, }, 1055 + { .compatible = "amlogic,t7-mpll", .data = &t7_mpll_data, }, 1056 + { .compatible = "amlogic,t7-hdmi-pll", .data = &t7_hdmi_data, }, 1057 + { .compatible = "amlogic,t7-mclk-pll", .data = &t7_mclk_data, }, 1058 + {} 1059 + }; 1060 + MODULE_DEVICE_TABLE(of, t7_pll_clkc_match_table); 1061 + 1062 + static struct platform_driver t7_pll_clkc_driver = { 1063 + .probe = meson_clkc_mmio_probe, 1064 + .driver = { 1065 + .name = "t7-pll-clkc", 1066 + .of_match_table = t7_pll_clkc_match_table, 1067 + }, 1068 + }; 1069 + module_platform_driver(t7_pll_clkc_driver); 1070 + 1071 + MODULE_DESCRIPTION("Amlogic T7 PLL Clock Controller driver"); 1072 + MODULE_AUTHOR("Jian Hu <jian.hu@amlogic.com>"); 1073 + MODULE_LICENSE("GPL"); 1074 + MODULE_IMPORT_NS("CLK_MESON");