1 // SPDX-License-Identifier: (GPL-2.0-only OR MIT) 2 /* 3 * Amlogic S4 PLL Clock Controller Driver 4 * 5 * Copyright (c) 2022-2023 Amlogic, inc. All rights reserved 6 * Author: Yu Tu <yu.tu@amlogic.com> 7 */ 8 9 #include <linux/clk-provider.h> 10 #include <linux/of_device.h> 11 #include <linux/platform_device.h> 12 13 #include "clk-mpll.h" 14 #include "clk-pll.h" 15 #include "clk-regmap.h" 16 #include "meson-clkc-utils.h" 17 #include <dt-bindings/clock/amlogic,s4-pll-clkc.h> 18 19 #define ANACTRL_FIXPLL_CTRL0 0x040 20 #define ANACTRL_FIXPLL_CTRL1 0x044 21 #define ANACTRL_FIXPLL_CTRL3 0x04c 22 #define ANACTRL_GP0PLL_CTRL0 0x080 23 #define ANACTRL_GP0PLL_CTRL1 0x084 24 #define ANACTRL_GP0PLL_CTRL2 0x088 25 #define ANACTRL_GP0PLL_CTRL3 0x08c 26 #define ANACTRL_GP0PLL_CTRL4 0x090 27 #define ANACTRL_GP0PLL_CTRL5 0x094 28 #define ANACTRL_GP0PLL_CTRL6 0x098 29 #define ANACTRL_HIFIPLL_CTRL0 0x100 30 #define ANACTRL_HIFIPLL_CTRL1 0x104 31 #define ANACTRL_HIFIPLL_CTRL2 0x108 32 #define ANACTRL_HIFIPLL_CTRL3 0x10c 33 #define ANACTRL_HIFIPLL_CTRL4 0x110 34 #define ANACTRL_HIFIPLL_CTRL5 0x114 35 #define ANACTRL_HIFIPLL_CTRL6 0x118 36 #define ANACTRL_MPLL_CTRL0 0x180 37 #define ANACTRL_MPLL_CTRL1 0x184 38 #define ANACTRL_MPLL_CTRL2 0x188 39 #define ANACTRL_MPLL_CTRL3 0x18c 40 #define ANACTRL_MPLL_CTRL4 0x190 41 #define ANACTRL_MPLL_CTRL5 0x194 42 #define ANACTRL_MPLL_CTRL6 0x198 43 #define ANACTRL_MPLL_CTRL7 0x19c 44 #define ANACTRL_MPLL_CTRL8 0x1a0 45 #define ANACTRL_HDMIPLL_CTRL0 0x1c0 46 47 /* 48 * These clock are a fixed value (fixed_pll is 2GHz) that is initialized by ROMcode. 49 * The chip was changed fixed pll for security reasons. Fixed PLL registers are not writable 50 * in the kernel phase. Write of fixed PLL-related register will cause the system to crash. 51 * Meanwhile, these clock won't ever change at runtime. 52 * For the above reasons, we can only use ro_ops for fixed PLL related clocks. 53 */ 54 static struct clk_regmap s4_fixed_pll_dco = { 55 .data = &(struct meson_clk_pll_data){ 56 .en = { 57 .reg_off = ANACTRL_FIXPLL_CTRL0, 58 .shift = 28, 59 .width = 1, 60 }, 61 .m = { 62 .reg_off = ANACTRL_FIXPLL_CTRL0, 63 .shift = 0, 64 .width = 8, 65 }, 66 .frac = { 67 .reg_off = ANACTRL_FIXPLL_CTRL1, 68 .shift = 0, 69 .width = 17, 70 }, 71 .n = { 72 .reg_off = ANACTRL_FIXPLL_CTRL0, 73 .shift = 10, 74 .width = 5, 75 }, 76 .l = { 77 .reg_off = ANACTRL_FIXPLL_CTRL0, 78 .shift = 31, 79 .width = 1, 80 }, 81 .rst = { 82 .reg_off = ANACTRL_FIXPLL_CTRL0, 83 .shift = 29, 84 .width = 1, 85 }, 86 }, 87 .hw.init = &(struct clk_init_data){ 88 .name = "fixed_pll_dco", 89 .ops = &meson_clk_pll_ro_ops, 90 .parent_data = (const struct clk_parent_data []) { 91 { .fw_name = "xtal", } 92 }, 93 .num_parents = 1, 94 }, 95 }; 96 97 static struct clk_regmap s4_fixed_pll = { 98 .data = &(struct clk_regmap_div_data){ 99 .offset = ANACTRL_FIXPLL_CTRL0, 100 .shift = 16, 101 .width = 2, 102 .flags = CLK_DIVIDER_POWER_OF_TWO, 103 }, 104 .hw.init = &(struct clk_init_data){ 105 .name = "fixed_pll", 106 .ops = &clk_regmap_divider_ro_ops, 107 .parent_hws = (const struct clk_hw *[]) { 108 &s4_fixed_pll_dco.hw 109 }, 110 .num_parents = 1, 111 /* 112 * This clock won't ever change at runtime so 113 * CLK_SET_RATE_PARENT is not required 114 */ 115 }, 116 }; 117 118 static struct clk_fixed_factor s4_fclk_div2_div = { 119 .mult = 1, 120 .div = 2, 121 .hw.init = &(struct clk_init_data){ 122 .name = "fclk_div2_div", 123 .ops = &clk_fixed_factor_ops, 124 .parent_hws = (const struct clk_hw *[]) { &s4_fixed_pll.hw }, 125 .num_parents = 1, 126 }, 127 }; 128 129 static struct clk_regmap s4_fclk_div2 = { 130 .data = &(struct clk_regmap_gate_data){ 131 .offset = ANACTRL_FIXPLL_CTRL1, 132 .bit_idx = 24, 133 }, 134 .hw.init = &(struct clk_init_data){ 135 .name = "fclk_div2", 136 .ops = &clk_regmap_gate_ro_ops, 137 .parent_hws = (const struct clk_hw *[]) { 138 &s4_fclk_div2_div.hw 139 }, 140 .num_parents = 1, 141 }, 142 }; 143 144 static struct clk_fixed_factor s4_fclk_div3_div = { 145 .mult = 1, 146 .div = 3, 147 .hw.init = &(struct clk_init_data){ 148 .name = "fclk_div3_div", 149 .ops = &clk_fixed_factor_ops, 150 .parent_hws = (const struct clk_hw *[]) { &s4_fixed_pll.hw }, 151 .num_parents = 1, 152 }, 153 }; 154 155 static struct clk_regmap s4_fclk_div3 = { 156 .data = &(struct clk_regmap_gate_data){ 157 .offset = ANACTRL_FIXPLL_CTRL1, 158 .bit_idx = 20, 159 }, 160 .hw.init = &(struct clk_init_data){ 161 .name = "fclk_div3", 162 .ops = &clk_regmap_gate_ro_ops, 163 .parent_hws = (const struct clk_hw *[]) { 164 &s4_fclk_div3_div.hw 165 }, 166 .num_parents = 1, 167 }, 168 }; 169 170 static struct clk_fixed_factor s4_fclk_div4_div = { 171 .mult = 1, 172 .div = 4, 173 .hw.init = &(struct clk_init_data){ 174 .name = "fclk_div4_div", 175 .ops = &clk_fixed_factor_ops, 176 .parent_hws = (const struct clk_hw *[]) { &s4_fixed_pll.hw }, 177 .num_parents = 1, 178 }, 179 }; 180 181 static struct clk_regmap s4_fclk_div4 = { 182 .data = &(struct clk_regmap_gate_data){ 183 .offset = ANACTRL_FIXPLL_CTRL1, 184 .bit_idx = 21, 185 }, 186 .hw.init = &(struct clk_init_data){ 187 .name = "fclk_div4", 188 .ops = &clk_regmap_gate_ro_ops, 189 .parent_hws = (const struct clk_hw *[]) { 190 &s4_fclk_div4_div.hw 191 }, 192 .num_parents = 1, 193 }, 194 }; 195 196 static struct clk_fixed_factor s4_fclk_div5_div = { 197 .mult = 1, 198 .div = 5, 199 .hw.init = &(struct clk_init_data){ 200 .name = "fclk_div5_div", 201 .ops = &clk_fixed_factor_ops, 202 .parent_hws = (const struct clk_hw *[]) { &s4_fixed_pll.hw }, 203 .num_parents = 1, 204 }, 205 }; 206 207 static struct clk_regmap s4_fclk_div5 = { 208 .data = &(struct clk_regmap_gate_data){ 209 .offset = ANACTRL_FIXPLL_CTRL1, 210 .bit_idx = 22, 211 }, 212 .hw.init = &(struct clk_init_data){ 213 .name = "fclk_div5", 214 .ops = &clk_regmap_gate_ro_ops, 215 .parent_hws = (const struct clk_hw *[]) { 216 &s4_fclk_div5_div.hw 217 }, 218 .num_parents = 1, 219 }, 220 }; 221 222 static struct clk_fixed_factor s4_fclk_div7_div = { 223 .mult = 1, 224 .div = 7, 225 .hw.init = &(struct clk_init_data){ 226 .name = "fclk_div7_div", 227 .ops = &clk_fixed_factor_ops, 228 .parent_hws = (const struct clk_hw *[]) { &s4_fixed_pll.hw }, 229 .num_parents = 1, 230 }, 231 }; 232 233 static struct clk_regmap s4_fclk_div7 = { 234 .data = &(struct clk_regmap_gate_data){ 235 .offset = ANACTRL_FIXPLL_CTRL1, 236 .bit_idx = 23, 237 }, 238 .hw.init = &(struct clk_init_data){ 239 .name = "fclk_div7", 240 .ops = &clk_regmap_gate_ro_ops, 241 .parent_hws = (const struct clk_hw *[]) { 242 &s4_fclk_div7_div.hw 243 }, 244 .num_parents = 1, 245 }, 246 }; 247 248 static struct clk_fixed_factor s4_fclk_div2p5_div = { 249 .mult = 2, 250 .div = 5, 251 .hw.init = &(struct clk_init_data){ 252 .name = "fclk_div2p5_div", 253 .ops = &clk_fixed_factor_ops, 254 .parent_hws = (const struct clk_hw *[]) { 255 &s4_fixed_pll.hw 256 }, 257 .num_parents = 1, 258 }, 259 }; 260 261 static struct clk_regmap s4_fclk_div2p5 = { 262 .data = &(struct clk_regmap_gate_data){ 263 .offset = ANACTRL_FIXPLL_CTRL1, 264 .bit_idx = 25, 265 }, 266 .hw.init = &(struct clk_init_data){ 267 .name = "fclk_div2p5", 268 .ops = &clk_regmap_gate_ro_ops, 269 .parent_hws = (const struct clk_hw *[]) { 270 &s4_fclk_div2p5_div.hw 271 }, 272 .num_parents = 1, 273 }, 274 }; 275 276 static const struct pll_mult_range s4_gp0_pll_mult_range = { 277 .min = 125, 278 .max = 250, 279 }; 280 281 /* 282 * Internal gp0 pll emulation configuration parameters 283 */ 284 static const struct reg_sequence s4_gp0_pll_init_regs[] = { 285 { .reg = ANACTRL_GP0PLL_CTRL1, .def = 0x00000000 }, 286 { .reg = ANACTRL_GP0PLL_CTRL2, .def = 0x00000000 }, 287 { .reg = ANACTRL_GP0PLL_CTRL3, .def = 0x48681c00 }, 288 { .reg = ANACTRL_GP0PLL_CTRL4, .def = 0x88770290 }, 289 { .reg = ANACTRL_GP0PLL_CTRL5, .def = 0x39272000 }, 290 { .reg = ANACTRL_GP0PLL_CTRL6, .def = 0x56540000 } 291 }; 292 293 static struct clk_regmap s4_gp0_pll_dco = { 294 .data = &(struct meson_clk_pll_data){ 295 .en = { 296 .reg_off = ANACTRL_GP0PLL_CTRL0, 297 .shift = 28, 298 .width = 1, 299 }, 300 .m = { 301 .reg_off = ANACTRL_GP0PLL_CTRL0, 302 .shift = 0, 303 .width = 8, 304 }, 305 .n = { 306 .reg_off = ANACTRL_GP0PLL_CTRL0, 307 .shift = 10, 308 .width = 5, 309 }, 310 .l = { 311 .reg_off = ANACTRL_GP0PLL_CTRL0, 312 .shift = 31, 313 .width = 1, 314 }, 315 .rst = { 316 .reg_off = ANACTRL_GP0PLL_CTRL0, 317 .shift = 29, 318 .width = 1, 319 }, 320 .range = &s4_gp0_pll_mult_range, 321 .init_regs = s4_gp0_pll_init_regs, 322 .init_count = ARRAY_SIZE(s4_gp0_pll_init_regs), 323 }, 324 .hw.init = &(struct clk_init_data){ 325 .name = "gp0_pll_dco", 326 .ops = &meson_clk_pll_ops, 327 .parent_data = (const struct clk_parent_data []) { 328 { .fw_name = "xtal", } 329 }, 330 .num_parents = 1, 331 }, 332 }; 333 334 static struct clk_regmap s4_gp0_pll = { 335 .data = &(struct clk_regmap_div_data){ 336 .offset = ANACTRL_GP0PLL_CTRL0, 337 .shift = 16, 338 .width = 3, 339 .flags = (CLK_DIVIDER_POWER_OF_TWO | 340 CLK_DIVIDER_ROUND_CLOSEST), 341 }, 342 .hw.init = &(struct clk_init_data){ 343 .name = "gp0_pll", 344 .ops = &clk_regmap_divider_ops, 345 .parent_hws = (const struct clk_hw *[]) { 346 &s4_gp0_pll_dco.hw 347 }, 348 .num_parents = 1, 349 .flags = CLK_SET_RATE_PARENT, 350 }, 351 }; 352 353 /* 354 * Internal hifi pll emulation configuration parameters 355 */ 356 static const struct reg_sequence s4_hifi_pll_init_regs[] = { 357 { .reg = ANACTRL_HIFIPLL_CTRL2, .def = 0x00000000 }, 358 { .reg = ANACTRL_HIFIPLL_CTRL3, .def = 0x6a285c00 }, 359 { .reg = ANACTRL_HIFIPLL_CTRL4, .def = 0x65771290 }, 360 { .reg = ANACTRL_HIFIPLL_CTRL5, .def = 0x39272000 }, 361 { .reg = ANACTRL_HIFIPLL_CTRL6, .def = 0x56540000 } 362 }; 363 364 static struct clk_regmap s4_hifi_pll_dco = { 365 .data = &(struct meson_clk_pll_data){ 366 .en = { 367 .reg_off = ANACTRL_HIFIPLL_CTRL0, 368 .shift = 28, 369 .width = 1, 370 }, 371 .m = { 372 .reg_off = ANACTRL_HIFIPLL_CTRL0, 373 .shift = 0, 374 .width = 8, 375 }, 376 .n = { 377 .reg_off = ANACTRL_HIFIPLL_CTRL0, 378 .shift = 10, 379 .width = 5, 380 }, 381 .frac = { 382 .reg_off = ANACTRL_HIFIPLL_CTRL1, 383 .shift = 0, 384 .width = 17, 385 }, 386 .l = { 387 .reg_off = ANACTRL_HIFIPLL_CTRL0, 388 .shift = 31, 389 .width = 1, 390 }, 391 .rst = { 392 .reg_off = ANACTRL_HIFIPLL_CTRL0, 393 .shift = 29, 394 .width = 1, 395 }, 396 .range = &s4_gp0_pll_mult_range, 397 .init_regs = s4_hifi_pll_init_regs, 398 .init_count = ARRAY_SIZE(s4_hifi_pll_init_regs), 399 .frac_max = 100000, 400 .flags = CLK_MESON_PLL_ROUND_CLOSEST, 401 }, 402 .hw.init = &(struct clk_init_data){ 403 .name = "hifi_pll_dco", 404 .ops = &meson_clk_pll_ops, 405 .parent_data = (const struct clk_parent_data []) { 406 { .fw_name = "xtal", } 407 }, 408 .num_parents = 1, 409 }, 410 }; 411 412 static struct clk_regmap s4_hifi_pll = { 413 .data = &(struct clk_regmap_div_data){ 414 .offset = ANACTRL_HIFIPLL_CTRL0, 415 .shift = 16, 416 .width = 2, 417 .flags = (CLK_DIVIDER_POWER_OF_TWO | 418 CLK_DIVIDER_ROUND_CLOSEST), 419 }, 420 .hw.init = &(struct clk_init_data){ 421 .name = "hifi_pll", 422 .ops = &clk_regmap_divider_ops, 423 .parent_hws = (const struct clk_hw *[]) { 424 &s4_hifi_pll_dco.hw 425 }, 426 .num_parents = 1, 427 .flags = CLK_SET_RATE_PARENT, 428 }, 429 }; 430 431 static struct clk_regmap s4_hdmi_pll_dco = { 432 .data = &(struct meson_clk_pll_data){ 433 .en = { 434 .reg_off = ANACTRL_HDMIPLL_CTRL0, 435 .shift = 28, 436 .width = 1, 437 }, 438 .m = { 439 .reg_off = ANACTRL_HDMIPLL_CTRL0, 440 .shift = 0, 441 .width = 8, 442 }, 443 .n = { 444 .reg_off = ANACTRL_HDMIPLL_CTRL0, 445 .shift = 10, 446 .width = 5, 447 }, 448 .l = { 449 .reg_off = ANACTRL_HDMIPLL_CTRL0, 450 .shift = 31, 451 .width = 1, 452 }, 453 .rst = { 454 .reg_off = ANACTRL_HDMIPLL_CTRL0, 455 .shift = 29, 456 .width = 1, 457 }, 458 .range = &s4_gp0_pll_mult_range, 459 }, 460 .hw.init = &(struct clk_init_data){ 461 .name = "hdmi_pll_dco", 462 .ops = &meson_clk_pll_ops, 463 .parent_data = (const struct clk_parent_data []) { 464 { .fw_name = "xtal", } 465 }, 466 .num_parents = 1, 467 }, 468 }; 469 470 static struct clk_regmap s4_hdmi_pll_od = { 471 .data = &(struct clk_regmap_div_data){ 472 .offset = ANACTRL_HDMIPLL_CTRL0, 473 .shift = 16, 474 .width = 4, 475 .flags = CLK_DIVIDER_POWER_OF_TWO, 476 }, 477 .hw.init = &(struct clk_init_data){ 478 .name = "hdmi_pll_od", 479 .ops = &clk_regmap_divider_ops, 480 .parent_hws = (const struct clk_hw *[]) { 481 &s4_hdmi_pll_dco.hw 482 }, 483 .num_parents = 1, 484 .flags = CLK_SET_RATE_PARENT, 485 }, 486 }; 487 488 static struct clk_regmap s4_hdmi_pll = { 489 .data = &(struct clk_regmap_div_data){ 490 .offset = ANACTRL_HDMIPLL_CTRL0, 491 .shift = 20, 492 .width = 2, 493 .flags = CLK_DIVIDER_POWER_OF_TWO, 494 }, 495 .hw.init = &(struct clk_init_data){ 496 .name = "hdmi_pll", 497 .ops = &clk_regmap_divider_ops, 498 .parent_hws = (const struct clk_hw *[]) { 499 &s4_hdmi_pll_od.hw 500 }, 501 .num_parents = 1, 502 .flags = CLK_SET_RATE_PARENT, 503 }, 504 }; 505 506 static struct clk_fixed_factor s4_mpll_50m_div = { 507 .mult = 1, 508 .div = 80, 509 .hw.init = &(struct clk_init_data){ 510 .name = "mpll_50m_div", 511 .ops = &clk_fixed_factor_ops, 512 .parent_hws = (const struct clk_hw *[]) { 513 &s4_fixed_pll_dco.hw 514 }, 515 .num_parents = 1, 516 }, 517 }; 518 519 static struct clk_regmap s4_mpll_50m = { 520 .data = &(struct clk_regmap_mux_data){ 521 .offset = ANACTRL_FIXPLL_CTRL3, 522 .mask = 0x1, 523 .shift = 5, 524 }, 525 .hw.init = &(struct clk_init_data){ 526 .name = "mpll_50m", 527 .ops = &clk_regmap_mux_ro_ops, 528 .parent_data = (const struct clk_parent_data []) { 529 { .fw_name = "xtal", }, 530 { .hw = &s4_mpll_50m_div.hw }, 531 }, 532 .num_parents = 2, 533 }, 534 }; 535 536 static struct clk_fixed_factor s4_mpll_prediv = { 537 .mult = 1, 538 .div = 2, 539 .hw.init = &(struct clk_init_data){ 540 .name = "mpll_prediv", 541 .ops = &clk_fixed_factor_ops, 542 .parent_hws = (const struct clk_hw *[]) { 543 &s4_fixed_pll_dco.hw 544 }, 545 .num_parents = 1, 546 }, 547 }; 548 549 static const struct reg_sequence s4_mpll0_init_regs[] = { 550 { .reg = ANACTRL_MPLL_CTRL2, .def = 0x40000033 } 551 }; 552 553 static struct clk_regmap s4_mpll0_div = { 554 .data = &(struct meson_clk_mpll_data){ 555 .sdm = { 556 .reg_off = ANACTRL_MPLL_CTRL1, 557 .shift = 0, 558 .width = 14, 559 }, 560 .sdm_en = { 561 .reg_off = ANACTRL_MPLL_CTRL1, 562 .shift = 30, 563 .width = 1, 564 }, 565 .n2 = { 566 .reg_off = ANACTRL_MPLL_CTRL1, 567 .shift = 20, 568 .width = 9, 569 }, 570 .ssen = { 571 .reg_off = ANACTRL_MPLL_CTRL1, 572 .shift = 29, 573 .width = 1, 574 }, 575 .init_regs = s4_mpll0_init_regs, 576 .init_count = ARRAY_SIZE(s4_mpll0_init_regs), 577 }, 578 .hw.init = &(struct clk_init_data){ 579 .name = "mpll0_div", 580 .ops = &meson_clk_mpll_ops, 581 .parent_hws = (const struct clk_hw *[]) { 582 &s4_mpll_prediv.hw 583 }, 584 .num_parents = 1, 585 }, 586 }; 587 588 static struct clk_regmap s4_mpll0 = { 589 .data = &(struct clk_regmap_gate_data){ 590 .offset = ANACTRL_MPLL_CTRL1, 591 .bit_idx = 31, 592 }, 593 .hw.init = &(struct clk_init_data){ 594 .name = "mpll0", 595 .ops = &clk_regmap_gate_ops, 596 .parent_hws = (const struct clk_hw *[]) { &s4_mpll0_div.hw }, 597 .num_parents = 1, 598 .flags = CLK_SET_RATE_PARENT, 599 }, 600 }; 601 602 static const struct reg_sequence s4_mpll1_init_regs[] = { 603 { .reg = ANACTRL_MPLL_CTRL4, .def = 0x40000033 } 604 }; 605 606 static struct clk_regmap s4_mpll1_div = { 607 .data = &(struct meson_clk_mpll_data){ 608 .sdm = { 609 .reg_off = ANACTRL_MPLL_CTRL3, 610 .shift = 0, 611 .width = 14, 612 }, 613 .sdm_en = { 614 .reg_off = ANACTRL_MPLL_CTRL3, 615 .shift = 30, 616 .width = 1, 617 }, 618 .n2 = { 619 .reg_off = ANACTRL_MPLL_CTRL3, 620 .shift = 20, 621 .width = 9, 622 }, 623 .ssen = { 624 .reg_off = ANACTRL_MPLL_CTRL3, 625 .shift = 29, 626 .width = 1, 627 }, 628 .init_regs = s4_mpll1_init_regs, 629 .init_count = ARRAY_SIZE(s4_mpll1_init_regs), 630 }, 631 .hw.init = &(struct clk_init_data){ 632 .name = "mpll1_div", 633 .ops = &meson_clk_mpll_ops, 634 .parent_hws = (const struct clk_hw *[]) { 635 &s4_mpll_prediv.hw 636 }, 637 .num_parents = 1, 638 }, 639 }; 640 641 static struct clk_regmap s4_mpll1 = { 642 .data = &(struct clk_regmap_gate_data){ 643 .offset = ANACTRL_MPLL_CTRL3, 644 .bit_idx = 31, 645 }, 646 .hw.init = &(struct clk_init_data){ 647 .name = "mpll1", 648 .ops = &clk_regmap_gate_ops, 649 .parent_hws = (const struct clk_hw *[]) { &s4_mpll1_div.hw }, 650 .num_parents = 1, 651 .flags = CLK_SET_RATE_PARENT, 652 }, 653 }; 654 655 static const struct reg_sequence s4_mpll2_init_regs[] = { 656 { .reg = ANACTRL_MPLL_CTRL6, .def = 0x40000033 } 657 }; 658 659 static struct clk_regmap s4_mpll2_div = { 660 .data = &(struct meson_clk_mpll_data){ 661 .sdm = { 662 .reg_off = ANACTRL_MPLL_CTRL5, 663 .shift = 0, 664 .width = 14, 665 }, 666 .sdm_en = { 667 .reg_off = ANACTRL_MPLL_CTRL5, 668 .shift = 30, 669 .width = 1, 670 }, 671 .n2 = { 672 .reg_off = ANACTRL_MPLL_CTRL5, 673 .shift = 20, 674 .width = 9, 675 }, 676 .ssen = { 677 .reg_off = ANACTRL_MPLL_CTRL5, 678 .shift = 29, 679 .width = 1, 680 }, 681 .init_regs = s4_mpll2_init_regs, 682 .init_count = ARRAY_SIZE(s4_mpll2_init_regs), 683 }, 684 .hw.init = &(struct clk_init_data){ 685 .name = "mpll2_div", 686 .ops = &meson_clk_mpll_ops, 687 .parent_hws = (const struct clk_hw *[]) { 688 &s4_mpll_prediv.hw 689 }, 690 .num_parents = 1, 691 }, 692 }; 693 694 static struct clk_regmap s4_mpll2 = { 695 .data = &(struct clk_regmap_gate_data){ 696 .offset = ANACTRL_MPLL_CTRL5, 697 .bit_idx = 31, 698 }, 699 .hw.init = &(struct clk_init_data){ 700 .name = "mpll2", 701 .ops = &clk_regmap_gate_ops, 702 .parent_hws = (const struct clk_hw *[]) { &s4_mpll2_div.hw }, 703 .num_parents = 1, 704 .flags = CLK_SET_RATE_PARENT, 705 }, 706 }; 707 708 static const struct reg_sequence s4_mpll3_init_regs[] = { 709 { .reg = ANACTRL_MPLL_CTRL8, .def = 0x40000033 } 710 }; 711 712 static struct clk_regmap s4_mpll3_div = { 713 .data = &(struct meson_clk_mpll_data){ 714 .sdm = { 715 .reg_off = ANACTRL_MPLL_CTRL7, 716 .shift = 0, 717 .width = 14, 718 }, 719 .sdm_en = { 720 .reg_off = ANACTRL_MPLL_CTRL7, 721 .shift = 30, 722 .width = 1, 723 }, 724 .n2 = { 725 .reg_off = ANACTRL_MPLL_CTRL7, 726 .shift = 20, 727 .width = 9, 728 }, 729 .ssen = { 730 .reg_off = ANACTRL_MPLL_CTRL7, 731 .shift = 29, 732 .width = 1, 733 }, 734 .init_regs = s4_mpll3_init_regs, 735 .init_count = ARRAY_SIZE(s4_mpll3_init_regs), 736 }, 737 .hw.init = &(struct clk_init_data){ 738 .name = "mpll3_div", 739 .ops = &meson_clk_mpll_ops, 740 .parent_hws = (const struct clk_hw *[]) { 741 &s4_mpll_prediv.hw 742 }, 743 .num_parents = 1, 744 }, 745 }; 746 747 static struct clk_regmap s4_mpll3 = { 748 .data = &(struct clk_regmap_gate_data){ 749 .offset = ANACTRL_MPLL_CTRL7, 750 .bit_idx = 31, 751 }, 752 .hw.init = &(struct clk_init_data){ 753 .name = "mpll3", 754 .ops = &clk_regmap_gate_ops, 755 .parent_hws = (const struct clk_hw *[]) { &s4_mpll3_div.hw }, 756 .num_parents = 1, 757 .flags = CLK_SET_RATE_PARENT, 758 }, 759 }; 760 761 /* Array of all clocks provided by this provider */ 762 static struct clk_hw *s4_pll_hw_clks[] = { 763 [CLKID_FIXED_PLL_DCO] = &s4_fixed_pll_dco.hw, 764 [CLKID_FIXED_PLL] = &s4_fixed_pll.hw, 765 [CLKID_FCLK_DIV2_DIV] = &s4_fclk_div2_div.hw, 766 [CLKID_FCLK_DIV2] = &s4_fclk_div2.hw, 767 [CLKID_FCLK_DIV3_DIV] = &s4_fclk_div3_div.hw, 768 [CLKID_FCLK_DIV3] = &s4_fclk_div3.hw, 769 [CLKID_FCLK_DIV4_DIV] = &s4_fclk_div4_div.hw, 770 [CLKID_FCLK_DIV4] = &s4_fclk_div4.hw, 771 [CLKID_FCLK_DIV5_DIV] = &s4_fclk_div5_div.hw, 772 [CLKID_FCLK_DIV5] = &s4_fclk_div5.hw, 773 [CLKID_FCLK_DIV7_DIV] = &s4_fclk_div7_div.hw, 774 [CLKID_FCLK_DIV7] = &s4_fclk_div7.hw, 775 [CLKID_FCLK_DIV2P5_DIV] = &s4_fclk_div2p5_div.hw, 776 [CLKID_FCLK_DIV2P5] = &s4_fclk_div2p5.hw, 777 [CLKID_GP0_PLL_DCO] = &s4_gp0_pll_dco.hw, 778 [CLKID_GP0_PLL] = &s4_gp0_pll.hw, 779 [CLKID_HIFI_PLL_DCO] = &s4_hifi_pll_dco.hw, 780 [CLKID_HIFI_PLL] = &s4_hifi_pll.hw, 781 [CLKID_HDMI_PLL_DCO] = &s4_hdmi_pll_dco.hw, 782 [CLKID_HDMI_PLL_OD] = &s4_hdmi_pll_od.hw, 783 [CLKID_HDMI_PLL] = &s4_hdmi_pll.hw, 784 [CLKID_MPLL_50M_DIV] = &s4_mpll_50m_div.hw, 785 [CLKID_MPLL_50M] = &s4_mpll_50m.hw, 786 [CLKID_MPLL_PREDIV] = &s4_mpll_prediv.hw, 787 [CLKID_MPLL0_DIV] = &s4_mpll0_div.hw, 788 [CLKID_MPLL0] = &s4_mpll0.hw, 789 [CLKID_MPLL1_DIV] = &s4_mpll1_div.hw, 790 [CLKID_MPLL1] = &s4_mpll1.hw, 791 [CLKID_MPLL2_DIV] = &s4_mpll2_div.hw, 792 [CLKID_MPLL2] = &s4_mpll2.hw, 793 [CLKID_MPLL3_DIV] = &s4_mpll3_div.hw, 794 [CLKID_MPLL3] = &s4_mpll3.hw, 795 }; 796 797 static const struct reg_sequence s4_pll_init_regs[] = { 798 { .reg = ANACTRL_MPLL_CTRL0, .def = 0x00000543 }, 799 }; 800 801 static const struct meson_clkc_data s4_pll_clkc_data = { 802 .hw_clks = { 803 .hws = s4_pll_hw_clks, 804 .num = ARRAY_SIZE(s4_pll_hw_clks), 805 }, 806 .init_regs = s4_pll_init_regs, 807 .init_count = ARRAY_SIZE(s4_pll_init_regs), 808 }; 809 810 static const struct of_device_id s4_pll_clkc_match_table[] = { 811 { 812 .compatible = "amlogic,s4-pll-clkc", 813 .data = &s4_pll_clkc_data, 814 }, 815 {} 816 }; 817 MODULE_DEVICE_TABLE(of, s4_pll_clkc_match_table); 818 819 static struct platform_driver s4_pll_clkc_driver = { 820 .probe = meson_clkc_mmio_probe, 821 .driver = { 822 .name = "s4-pll-clkc", 823 .of_match_table = s4_pll_clkc_match_table, 824 }, 825 }; 826 module_platform_driver(s4_pll_clkc_driver); 827 828 MODULE_DESCRIPTION("Amlogic S4 PLL Clock Controller driver"); 829 MODULE_AUTHOR("Yu Tu <yu.tu@amlogic.com>"); 830 MODULE_LICENSE("GPL"); 831 MODULE_IMPORT_NS("CLK_MESON"); 832