FILE
clk-th1520-ap.c
File preview with syntax highlighting.
linux-6.19.14/drivers/clk/thead/clk-th1520-ap.c
1// SPDX-License-Identifier: GPL-2.0 2/* 3 * Copyright (C) 2023 Jisheng Zhang <jszhang@kernel.org> 4 * Copyright (C) 2023 Vivo Communication Technology Co. Ltd. 5 * Authors: Yangtao Li <frank.li@vivo.com> 6 */ 7 8#include <dt-bindings/clock/thead,th1520-clk-ap.h> 9#include <linux/bitfield.h> 10#include <linux/clk-provider.h> 11#include <linux/delay.h> 12#include <linux/device.h> 13#include <linux/module.h> 14#include <linux/platform_device.h> 15#include <linux/regmap.h> 16 17#define TH1520_PLL_STS 0x80 18 19#define TH1520_PLL_POSTDIV2 GENMASK(26, 24) 20#define TH1520_PLL_POSTDIV1 GENMASK(22, 20) 21#define TH1520_PLL_FBDIV GENMASK(19, 8) 22#define TH1520_PLL_REFDIV GENMASK(5, 0) 23#define TH1520_PLL_BYPASS BIT(30) 24#define TH1520_PLL_VCO_RST BIT(29) 25#define TH1520_PLL_DSMPD BIT(24) 26#define TH1520_PLL_FRAC GENMASK(23, 0) 27#define TH1520_PLL_FRAC_BITS 24 28 29/* 30 * All PLLs in TH1520 take 21250ns at maximum to lock, let's take its double 31 * for safety. 32 */ 33#define TH1520_PLL_LOCK_TIMEOUT_US 44 34#define TH1520_PLL_STABLE_DELAY_US 30 35 36struct ccu_internal { 37 u8 shift; 38 u8 width; 39}; 40 41struct ccu_div_internal { 42 u8 shift; 43 u8 width; 44 u32 flags; 45}; 46 47struct ccu_common { 48 int clkid; 49 struct regmap *map; 50 u16 cfg0; 51 u16 cfg1; 52 struct clk_hw hw; 53}; 54 55struct ccu_mux { 56 int clkid; 57 u32 reg; 58 struct clk_mux mux; 59}; 60 61struct ccu_gate { 62 int clkid; 63 u32 reg; 64 struct clk_gate gate; 65}; 66 67struct ccu_div { 68 u32 enable; 69 u32 div_en; 70 struct ccu_div_internal div; 71 struct ccu_internal mux; 72 struct ccu_common common; 73}; 74 75struct ccu_pll { 76 struct ccu_common common; 77 u32 lock_sts_mask; 78}; 79 80#define TH_CCU_ARG(_shift, _width) \ 81 { \ 82 .shift = _shift, \ 83 .width = _width, \ 84 } 85 86#define TH_CCU_DIV_FLAGS(_shift, _width, _flags) \ 87 { \ 88 .shift = _shift, \ 89 .width = _width, \ 90 .flags = _flags, \ 91 } 92 93#define TH_CCU_MUX(_name, _parents, _shift, _width) \ 94 { \ 95 .mask = GENMASK(_width - 1, 0), \ 96 .shift = _shift, \ 97 .hw.init = CLK_HW_INIT_PARENTS_DATA( \ 98 _name, \ 99 _parents, \ 100 &clk_mux_ops, \ 101 0), \ 102 } 103 104#define CCU_GATE(_clkid, _struct, _name, _parent, _reg, _bit, _flags) \ 105 struct ccu_gate _struct = { \ 106 .clkid = _clkid, \ 107 .reg = _reg, \ 108 .gate = { \ 109 .bit_idx = _bit, \ 110 .hw.init = CLK_HW_INIT_PARENTS_DATA( \ 111 _name, \ 112 _parent, \ 113 &clk_gate_ops, \ 114 _flags), \ 115 } \ 116 } 117 118static inline struct ccu_common *hw_to_ccu_common(struct clk_hw *hw) 119{ 120 return container_of(hw, struct ccu_common, hw); 121} 122 123static inline struct ccu_pll *hw_to_ccu_pll(struct clk_hw *hw) 124{ 125 struct ccu_common *common = hw_to_ccu_common(hw); 126 127 return container_of(common, struct ccu_pll, common); 128} 129 130static inline struct ccu_div *hw_to_ccu_div(struct clk_hw *hw) 131{ 132 struct ccu_common *common = hw_to_ccu_common(hw); 133 134 return container_of(common, struct ccu_div, common); 135} 136 137static u8 ccu_get_parent_helper(struct ccu_common *common, 138 struct ccu_internal *mux) 139{ 140 unsigned int val; 141 u8 parent; 142 143 regmap_read(common->map, common->cfg0, &val); 144 parent = val >> mux->shift; 145 parent &= GENMASK(mux->width - 1, 0); 146 147 return parent; 148} 149 150static int ccu_set_parent_helper(struct ccu_common *common, 151 struct ccu_internal *mux, 152 u8 index) 153{ 154 return regmap_update_bits(common->map, common->cfg0, 155 GENMASK(mux->width - 1, 0) << mux->shift, 156 index << mux->shift); 157} 158 159static void ccu_disable_helper(struct ccu_common *common, u32 gate) 160{ 161 if (!gate) 162 return; 163 regmap_update_bits(common->map, common->cfg0, 164 gate, ~gate); 165} 166 167static int ccu_enable_helper(struct ccu_common *common, u32 gate) 168{ 169 unsigned int val; 170 int ret; 171 172 if (!gate) 173 return 0; 174 175 ret = regmap_update_bits(common->map, common->cfg0, gate, gate); 176 regmap_read(common->map, common->cfg0, &val); 177 return ret; 178} 179 180static int ccu_is_enabled_helper(struct ccu_common *common, u32 gate) 181{ 182 unsigned int val; 183 184 if (!gate) 185 return true; 186 187 regmap_read(common->map, common->cfg0, &val); 188 return val & gate; 189} 190 191static unsigned long ccu_div_recalc_rate(struct clk_hw *hw, 192 unsigned long parent_rate) 193{ 194 struct ccu_div *cd = hw_to_ccu_div(hw); 195 unsigned long rate; 196 unsigned int val; 197 198 regmap_read(cd->common.map, cd->common.cfg0, &val); 199 val = val >> cd->div.shift; 200 val &= GENMASK(cd->div.width - 1, 0); 201 rate = divider_recalc_rate(hw, parent_rate, val, NULL, 202 cd->div.flags, cd->div.width); 203 204 return rate; 205} 206 207static int ccu_div_determine_rate(struct clk_hw *hw, 208 struct clk_rate_request *req) 209{ 210 struct ccu_div *cd = hw_to_ccu_div(hw); 211 unsigned int val; 212 213 if (cd->div_en) 214 return divider_determine_rate(hw, req, NULL, 215 cd->div.width, cd->div.flags); 216 217 regmap_read(cd->common.map, cd->common.cfg0, &val); 218 val = val >> cd->div.shift; 219 val &= GENMASK(cd->div.width - 1, 0); 220 return divider_ro_determine_rate(hw, req, NULL, cd->div.width, 221 cd->div.flags, val); 222} 223 224static int ccu_div_set_rate(struct clk_hw *hw, unsigned long rate, 225 unsigned long parent_rate) 226{ 227 struct ccu_div *cd = hw_to_ccu_div(hw); 228 int val = divider_get_val(rate, parent_rate, NULL, 229 cd->div.width, cd->div.flags); 230 unsigned int curr_val, reg_val; 231 232 if (val < 0) 233 return val; 234 235 regmap_read(cd->common.map, cd->common.cfg0, ®_val); 236 curr_val = reg_val >> cd->div.shift; 237 curr_val &= GENMASK(cd->div.width - 1, 0); 238 239 if (!cd->div_en && curr_val != val) 240 return -EINVAL; 241 242 reg_val &= ~cd->div_en; 243 regmap_write(cd->common.map, cd->common.cfg0, reg_val); 244 udelay(1); 245 246 reg_val &= ~GENMASK(cd->div.width + cd->div.shift - 1, cd->div.shift); 247 reg_val |= val << cd->div.shift; 248 regmap_write(cd->common.map, cd->common.cfg0, reg_val); 249 250 reg_val |= cd->div_en; 251 regmap_write(cd->common.map, cd->common.cfg0, reg_val); 252 253 return 0; 254} 255 256static u8 ccu_div_get_parent(struct clk_hw *hw) 257{ 258 struct ccu_div *cd = hw_to_ccu_div(hw); 259 260 return ccu_get_parent_helper(&cd->common, &cd->mux); 261} 262 263static int ccu_div_set_parent(struct clk_hw *hw, u8 index) 264{ 265 struct ccu_div *cd = hw_to_ccu_div(hw); 266 267 return ccu_set_parent_helper(&cd->common, &cd->mux, index); 268} 269 270static void ccu_div_disable(struct clk_hw *hw) 271{ 272 struct ccu_div *cd = hw_to_ccu_div(hw); 273 274 ccu_disable_helper(&cd->common, cd->enable); 275} 276 277static int ccu_div_enable(struct clk_hw *hw) 278{ 279 struct ccu_div *cd = hw_to_ccu_div(hw); 280 281 return ccu_enable_helper(&cd->common, cd->enable); 282} 283 284static int ccu_div_is_enabled(struct clk_hw *hw) 285{ 286 struct ccu_div *cd = hw_to_ccu_div(hw); 287 288 return ccu_is_enabled_helper(&cd->common, cd->enable); 289} 290 291static const struct clk_ops ccu_div_ops = { 292 .disable = ccu_div_disable, 293 .enable = ccu_div_enable, 294 .is_enabled = ccu_div_is_enabled, 295 .get_parent = ccu_div_get_parent, 296 .set_parent = ccu_div_set_parent, 297 .recalc_rate = ccu_div_recalc_rate, 298 .set_rate = ccu_div_set_rate, 299 .determine_rate = ccu_div_determine_rate, 300}; 301 302static void ccu_pll_disable(struct clk_hw *hw) 303{ 304 struct ccu_pll *pll = hw_to_ccu_pll(hw); 305 306 regmap_set_bits(pll->common.map, pll->common.cfg1, 307 TH1520_PLL_VCO_RST); 308} 309 310static int ccu_pll_enable(struct clk_hw *hw) 311{ 312 struct ccu_pll *pll = hw_to_ccu_pll(hw); 313 u32 reg; 314 int ret; 315 316 regmap_clear_bits(pll->common.map, pll->common.cfg1, 317 TH1520_PLL_VCO_RST); 318 319 ret = regmap_read_poll_timeout_atomic(pll->common.map, TH1520_PLL_STS, 320 reg, reg & pll->lock_sts_mask, 321 5, TH1520_PLL_LOCK_TIMEOUT_US); 322 if (ret) 323 return ret; 324 325 udelay(TH1520_PLL_STABLE_DELAY_US); 326 327 return 0; 328} 329 330static int ccu_pll_is_enabled(struct clk_hw *hw) 331{ 332 struct ccu_pll *pll = hw_to_ccu_pll(hw); 333 334 return !regmap_test_bits(pll->common.map, pll->common.cfg1, 335 TH1520_PLL_VCO_RST); 336} 337 338static unsigned long th1520_pll_vco_recalc_rate(struct clk_hw *hw, 339 unsigned long parent_rate) 340{ 341 struct ccu_pll *pll = hw_to_ccu_pll(hw); 342 unsigned long div, mul, frac; 343 unsigned int cfg0, cfg1; 344 u64 rate = parent_rate; 345 346 regmap_read(pll->common.map, pll->common.cfg0, &cfg0); 347 regmap_read(pll->common.map, pll->common.cfg1, &cfg1); 348 349 mul = FIELD_GET(TH1520_PLL_FBDIV, cfg0); 350 div = FIELD_GET(TH1520_PLL_REFDIV, cfg0); 351 if (!(cfg1 & TH1520_PLL_DSMPD)) { 352 mul <<= TH1520_PLL_FRAC_BITS; 353 frac = FIELD_GET(TH1520_PLL_FRAC, cfg1); 354 mul += frac; 355 div <<= TH1520_PLL_FRAC_BITS; 356 } 357 rate = parent_rate * mul; 358 rate = rate / div; 359 return rate; 360} 361 362static unsigned long th1520_pll_postdiv_recalc_rate(struct clk_hw *hw, 363 unsigned long parent_rate) 364{ 365 struct ccu_pll *pll = hw_to_ccu_pll(hw); 366 unsigned long div, rate = parent_rate; 367 unsigned int cfg0, cfg1; 368 369 regmap_read(pll->common.map, pll->common.cfg0, &cfg0); 370 regmap_read(pll->common.map, pll->common.cfg1, &cfg1); 371 372 if (cfg1 & TH1520_PLL_BYPASS) 373 return rate; 374 375 div = FIELD_GET(TH1520_PLL_POSTDIV1, cfg0) * 376 FIELD_GET(TH1520_PLL_POSTDIV2, cfg0); 377 378 rate = rate / div; 379 380 return rate; 381} 382 383static unsigned long ccu_pll_recalc_rate(struct clk_hw *hw, 384 unsigned long parent_rate) 385{ 386 unsigned long rate = parent_rate; 387 388 rate = th1520_pll_vco_recalc_rate(hw, rate); 389 rate = th1520_pll_postdiv_recalc_rate(hw, rate); 390 391 return rate; 392} 393 394static const struct clk_ops clk_pll_ops = { 395 .disable = ccu_pll_disable, 396 .enable = ccu_pll_enable, 397 .is_enabled = ccu_pll_is_enabled, 398 .recalc_rate = ccu_pll_recalc_rate, 399}; 400 401static const struct clk_parent_data osc_24m_clk[] = { 402 { .index = 0 } 403}; 404 405static struct ccu_pll cpu_pll0_clk = { 406 .common = { 407 .clkid = CLK_CPU_PLL0, 408 .cfg0 = 0x000, 409 .cfg1 = 0x004, 410 .hw.init = CLK_HW_INIT_PARENTS_DATA("cpu-pll0", 411 osc_24m_clk, 412 &clk_pll_ops, 413 CLK_IS_CRITICAL), 414 }, 415 .lock_sts_mask = BIT(1), 416}; 417 418static struct ccu_pll cpu_pll1_clk = { 419 .common = { 420 .clkid = CLK_CPU_PLL1, 421 .cfg0 = 0x010, 422 .cfg1 = 0x014, 423 .hw.init = CLK_HW_INIT_PARENTS_DATA("cpu-pll1", 424 osc_24m_clk, 425 &clk_pll_ops, 426 CLK_IS_CRITICAL), 427 }, 428 .lock_sts_mask = BIT(4), 429}; 430 431static struct ccu_pll gmac_pll_clk = { 432 .common = { 433 .clkid = CLK_GMAC_PLL, 434 .cfg0 = 0x020, 435 .cfg1 = 0x024, 436 .hw.init = CLK_HW_INIT_PARENTS_DATA("gmac-pll", 437 osc_24m_clk, 438 &clk_pll_ops, 439 CLK_IS_CRITICAL), 440 }, 441 .lock_sts_mask = BIT(3), 442}; 443 444static const struct clk_hw *gmac_pll_clk_parent[] = { 445 &gmac_pll_clk.common.hw 446}; 447 448static const struct clk_parent_data gmac_pll_clk_pd[] = { 449 { .hw = &gmac_pll_clk.common.hw } 450}; 451 452static struct ccu_pll video_pll_clk = { 453 .common = { 454 .clkid = CLK_VIDEO_PLL, 455 .cfg0 = 0x030, 456 .cfg1 = 0x034, 457 .hw.init = CLK_HW_INIT_PARENTS_DATA("video-pll", 458 osc_24m_clk, 459 &clk_pll_ops, 460 CLK_IS_CRITICAL), 461 }, 462 .lock_sts_mask = BIT(7), 463}; 464 465static const struct clk_hw *video_pll_clk_parent[] = { 466 &video_pll_clk.common.hw 467}; 468 469static const struct clk_parent_data video_pll_clk_pd[] = { 470 { .hw = &video_pll_clk.common.hw } 471}; 472 473static struct ccu_pll dpu0_pll_clk = { 474 .common = { 475 .clkid = CLK_DPU0_PLL, 476 .cfg0 = 0x040, 477 .cfg1 = 0x044, 478 .hw.init = CLK_HW_INIT_PARENTS_DATA("dpu0-pll", 479 osc_24m_clk, 480 &clk_pll_ops, 481 0), 482 }, 483 .lock_sts_mask = BIT(8), 484}; 485 486static const struct clk_hw *dpu0_pll_clk_parent[] = { 487 &dpu0_pll_clk.common.hw 488}; 489 490static struct ccu_pll dpu1_pll_clk = { 491 .common = { 492 .clkid = CLK_DPU1_PLL, 493 .cfg0 = 0x050, 494 .cfg1 = 0x054, 495 .hw.init = CLK_HW_INIT_PARENTS_DATA("dpu1-pll", 496 osc_24m_clk, 497 &clk_pll_ops, 498 0), 499 }, 500 .lock_sts_mask = BIT(9), 501}; 502 503static const struct clk_hw *dpu1_pll_clk_parent[] = { 504 &dpu1_pll_clk.common.hw 505}; 506 507static struct ccu_pll tee_pll_clk = { 508 .common = { 509 .clkid = CLK_TEE_PLL, 510 .cfg0 = 0x060, 511 .cfg1 = 0x064, 512 .hw.init = CLK_HW_INIT_PARENTS_DATA("tee-pll", 513 osc_24m_clk, 514 &clk_pll_ops, 515 CLK_IS_CRITICAL), 516 }, 517 .lock_sts_mask = BIT(10), 518}; 519 520static const struct clk_parent_data c910_i0_parents[] = { 521 { .hw = &cpu_pll0_clk.common.hw }, 522 { .index = 0 } 523}; 524 525static struct ccu_mux c910_i0_clk = { 526 .clkid = CLK_C910_I0, 527 .reg = 0x100, 528 .mux = TH_CCU_MUX("c910-i0", c910_i0_parents, 1, 1), 529}; 530 531static const struct clk_parent_data c910_parents[] = { 532 { .hw = &c910_i0_clk.mux.hw }, 533 { .hw = &cpu_pll1_clk.common.hw } 534}; 535 536static struct ccu_mux c910_clk = { 537 .clkid = CLK_C910, 538 .reg = 0x100, 539 .mux = TH_CCU_MUX("c910", c910_parents, 0, 1), 540}; 541 542static const struct clk_parent_data ahb2_cpusys_parents[] = { 543 { .hw = &gmac_pll_clk.common.hw }, 544 { .index = 0 } 545}; 546 547static struct ccu_div ahb2_cpusys_hclk = { 548 .div = TH_CCU_DIV_FLAGS(0, 3, CLK_DIVIDER_ONE_BASED), 549 .mux = TH_CCU_ARG(5, 1), 550 .common = { 551 .clkid = CLK_AHB2_CPUSYS_HCLK, 552 .cfg0 = 0x120, 553 .hw.init = CLK_HW_INIT_PARENTS_DATA("ahb2-cpusys-hclk", 554 ahb2_cpusys_parents, 555 &ccu_div_ops, 556 0), 557 }, 558}; 559 560static const struct clk_parent_data ahb2_cpusys_hclk_pd[] = { 561 { .hw = &ahb2_cpusys_hclk.common.hw } 562}; 563 564static const struct clk_hw *ahb2_cpusys_hclk_parent[] = { 565 &ahb2_cpusys_hclk.common.hw, 566}; 567 568static struct ccu_div apb3_cpusys_pclk = { 569 .div = TH_CCU_ARG(0, 3), 570 .common = { 571 .clkid = CLK_APB3_CPUSYS_PCLK, 572 .cfg0 = 0x130, 573 .hw.init = CLK_HW_INIT_PARENTS_HW("apb3-cpusys-pclk", 574 ahb2_cpusys_hclk_parent, 575 &ccu_div_ops, 576 0), 577 }, 578}; 579 580static const struct clk_parent_data apb3_cpusys_pclk_pd[] = { 581 { .hw = &apb3_cpusys_pclk.common.hw } 582}; 583 584static struct ccu_div axi4_cpusys2_aclk = { 585 .div = TH_CCU_DIV_FLAGS(0, 3, CLK_DIVIDER_ONE_BASED), 586 .common = { 587 .clkid = CLK_AXI4_CPUSYS2_ACLK, 588 .cfg0 = 0x134, 589 .hw.init = CLK_HW_INIT_PARENTS_HW("axi4-cpusys2-aclk", 590 gmac_pll_clk_parent, 591 &ccu_div_ops, 592 CLK_IS_CRITICAL), 593 }, 594}; 595 596static const struct clk_parent_data axi4_cpusys2_aclk_pd[] = { 597 { .hw = &axi4_cpusys2_aclk.common.hw } 598}; 599 600static const struct clk_parent_data axi_parents[] = { 601 { .hw = &video_pll_clk.common.hw }, 602 { .index = 0 } 603}; 604 605static struct ccu_div axi_aclk = { 606 .div = TH_CCU_DIV_FLAGS(0, 4, CLK_DIVIDER_ONE_BASED), 607 .mux = TH_CCU_ARG(5, 1), 608 .common = { 609 .clkid = CLK_AXI_ACLK, 610 .cfg0 = 0x138, 611 .hw.init = CLK_HW_INIT_PARENTS_DATA("axi-aclk", 612 axi_parents, 613 &ccu_div_ops, 614 CLK_IS_CRITICAL), 615 }, 616}; 617 618static const struct clk_parent_data axi_aclk_pd[] = { 619 { .hw = &axi_aclk.common.hw } 620}; 621 622static const struct clk_parent_data perisys_ahb_hclk_parents[] = { 623 { .hw = &gmac_pll_clk.common.hw }, 624 { .index = 0 }, 625}; 626 627static struct ccu_div perisys_ahb_hclk = { 628 .enable = BIT(6), 629 .div = TH_CCU_DIV_FLAGS(0, 4, CLK_DIVIDER_ONE_BASED), 630 .mux = TH_CCU_ARG(5, 1), 631 .common = { 632 .clkid = CLK_PERI_AHB_HCLK, 633 .cfg0 = 0x140, 634 .hw.init = CLK_HW_INIT_PARENTS_DATA("perisys-ahb-hclk", 635 perisys_ahb_hclk_parents, 636 &ccu_div_ops, 637 0), 638 }, 639}; 640 641static const struct clk_parent_data perisys_ahb_hclk_pd[] = { 642 { .hw = &perisys_ahb_hclk.common.hw } 643}; 644 645static const struct clk_hw *perisys_ahb_hclk_parent[] = { 646 &perisys_ahb_hclk.common.hw 647}; 648 649static struct ccu_div perisys_apb_pclk = { 650 .div = TH_CCU_ARG(0, 3), 651 .common = { 652 .clkid = CLK_PERI_APB_PCLK, 653 .cfg0 = 0x150, 654 .hw.init = CLK_HW_INIT_PARENTS_HW("perisys-apb-pclk", 655 perisys_ahb_hclk_parent, 656 &ccu_div_ops, 657 0), 658 }, 659}; 660 661static const struct clk_parent_data perisys_apb_pclk_pd[] = { 662 { .hw = &perisys_apb_pclk.common.hw } 663}; 664 665static struct ccu_div peri2sys_apb_pclk = { 666 .div = TH_CCU_DIV_FLAGS(4, 3, CLK_DIVIDER_ONE_BASED), 667 .common = { 668 .clkid = CLK_PERI2APB_PCLK, 669 .cfg0 = 0x150, 670 .hw.init = CLK_HW_INIT_PARENTS_HW("peri2sys-apb-pclk", 671 gmac_pll_clk_parent, 672 &ccu_div_ops, 673 0), 674 }, 675}; 676 677static const struct clk_parent_data peri2sys_apb_pclk_pd[] = { 678 { .hw = &peri2sys_apb_pclk.common.hw } 679}; 680 681static struct clk_fixed_factor osc12m_clk = { 682 .div = 2, 683 .mult = 1, 684 .hw.init = CLK_HW_INIT_PARENTS_DATA("osc_12m", 685 osc_24m_clk, 686 &clk_fixed_factor_ops, 687 0), 688}; 689 690static const char * const out_parents[] = { "osc_24m", "osc_12m" }; 691 692static struct ccu_div out1_clk = { 693 .enable = BIT(5), 694 .div = TH_CCU_DIV_FLAGS(0, 3, CLK_DIVIDER_ONE_BASED), 695 .mux = TH_CCU_ARG(4, 1), 696 .common = { 697 .clkid = CLK_OUT1, 698 .cfg0 = 0x1b4, 699 .hw.init = CLK_HW_INIT_PARENTS("out1", 700 out_parents, 701 &ccu_div_ops, 702 0), 703 }, 704}; 705 706static struct ccu_div out2_clk = { 707 .enable = BIT(5), 708 .div = TH_CCU_DIV_FLAGS(0, 3, CLK_DIVIDER_ONE_BASED), 709 .mux = TH_CCU_ARG(4, 1), 710 .common = { 711 .clkid = CLK_OUT2, 712 .cfg0 = 0x1b8, 713 .hw.init = CLK_HW_INIT_PARENTS("out2", 714 out_parents, 715 &ccu_div_ops, 716 0), 717 }, 718}; 719 720static struct ccu_div out3_clk = { 721 .enable = BIT(5), 722 .div = TH_CCU_DIV_FLAGS(0, 3, CLK_DIVIDER_ONE_BASED), 723 .mux = TH_CCU_ARG(4, 1), 724 .common = { 725 .clkid = CLK_OUT3, 726 .cfg0 = 0x1bc, 727 .hw.init = CLK_HW_INIT_PARENTS("out3", 728 out_parents, 729 &ccu_div_ops, 730 0), 731 }, 732}; 733 734static struct ccu_div out4_clk = { 735 .enable = BIT(5), 736 .div = TH_CCU_DIV_FLAGS(0, 3, CLK_DIVIDER_ONE_BASED), 737 .mux = TH_CCU_ARG(4, 1), 738 .common = { 739 .clkid = CLK_OUT4, 740 .cfg0 = 0x1c0, 741 .hw.init = CLK_HW_INIT_PARENTS("out4", 742 out_parents, 743 &ccu_div_ops, 744 0), 745 }, 746}; 747 748static const struct clk_parent_data apb_parents[] = { 749 { .hw = &gmac_pll_clk.common.hw }, 750 { .index = 0 }, 751}; 752 753static struct ccu_div apb_pclk = { 754 .enable = BIT(5), 755 .div = TH_CCU_DIV_FLAGS(0, 4, CLK_DIVIDER_ONE_BASED), 756 .mux = TH_CCU_ARG(7, 1), 757 .common = { 758 .clkid = CLK_APB_PCLK, 759 .cfg0 = 0x1c4, 760 .hw.init = CLK_HW_INIT_PARENTS_DATA("apb-pclk", 761 apb_parents, 762 &ccu_div_ops, 763 CLK_IS_CRITICAL), 764 }, 765}; 766 767static const struct clk_hw *npu_parents[] = { 768 &gmac_pll_clk.common.hw, 769 &video_pll_clk.common.hw 770}; 771 772static struct ccu_div npu_clk = { 773 .enable = BIT(4), 774 .div = TH_CCU_DIV_FLAGS(0, 3, CLK_DIVIDER_ONE_BASED), 775 .mux = TH_CCU_ARG(6, 1), 776 .common = { 777 .clkid = CLK_NPU, 778 .cfg0 = 0x1c8, 779 .hw.init = CLK_HW_INIT_PARENTS_HW("npu", 780 npu_parents, 781 &ccu_div_ops, 782 0), 783 }, 784}; 785 786static struct ccu_div vi_clk = { 787 .div = TH_CCU_DIV_FLAGS(16, 4, CLK_DIVIDER_ONE_BASED), 788 .common = { 789 .clkid = CLK_VI, 790 .cfg0 = 0x1d0, 791 .hw.init = CLK_HW_INIT_PARENTS_HW("vi", 792 video_pll_clk_parent, 793 &ccu_div_ops, 794 CLK_IS_CRITICAL), 795 }, 796}; 797 798static struct ccu_div vi_ahb_clk = { 799 .div = TH_CCU_DIV_FLAGS(0, 4, CLK_DIVIDER_ONE_BASED), 800 .common = { 801 .clkid = CLK_VI_AHB, 802 .cfg0 = 0x1d0, 803 .hw.init = CLK_HW_INIT_PARENTS_HW("vi-ahb", 804 video_pll_clk_parent, 805 &ccu_div_ops, 806 0), 807 }, 808}; 809 810static struct ccu_div vo_axi_clk = { 811 .enable = BIT(5), 812 .div = TH_CCU_DIV_FLAGS(0, 4, CLK_DIVIDER_ONE_BASED), 813 .common = { 814 .clkid = CLK_VO_AXI, 815 .cfg0 = 0x1dc, 816 .hw.init = CLK_HW_INIT_PARENTS_HW("vo-axi", 817 video_pll_clk_parent, 818 &ccu_div_ops, 819 CLK_IS_CRITICAL), 820 }, 821}; 822 823static struct ccu_div vp_apb_clk = { 824 .div = TH_CCU_DIV_FLAGS(0, 3, CLK_DIVIDER_ONE_BASED), 825 .common = { 826 .clkid = CLK_VP_APB, 827 .cfg0 = 0x1e0, 828 .hw.init = CLK_HW_INIT_PARENTS_HW("vp-apb", 829 gmac_pll_clk_parent, 830 &ccu_div_ops, 831 0), 832 }, 833}; 834 835static struct ccu_div vp_axi_clk = { 836 .enable = BIT(15), 837 .div = TH_CCU_DIV_FLAGS(8, 4, CLK_DIVIDER_ONE_BASED), 838 .common = { 839 .clkid = CLK_VP_AXI, 840 .cfg0 = 0x1e0, 841 .hw.init = CLK_HW_INIT_PARENTS_HW("vp-axi", 842 video_pll_clk_parent, 843 &ccu_div_ops, 844 CLK_IS_CRITICAL), 845 }, 846}; 847 848static struct ccu_div venc_clk = { 849 .enable = BIT(5), 850 .div = TH_CCU_DIV_FLAGS(0, 3, CLK_DIVIDER_ONE_BASED), 851 .common = { 852 .clkid = CLK_VENC, 853 .cfg0 = 0x1e4, 854 .hw.init = CLK_HW_INIT_PARENTS_HW("venc", 855 gmac_pll_clk_parent, 856 &ccu_div_ops, 857 0), 858 }, 859}; 860 861static struct ccu_div dpu0_clk = { 862 .div_en = BIT(8), 863 .div = TH_CCU_DIV_FLAGS(0, 8, CLK_DIVIDER_ONE_BASED), 864 .common = { 865 .clkid = CLK_DPU0, 866 .cfg0 = 0x1e8, 867 .hw.init = CLK_HW_INIT_PARENTS_HW("dpu0", 868 dpu0_pll_clk_parent, 869 &ccu_div_ops, 870 CLK_SET_RATE_UNGATE), 871 }, 872}; 873 874static const struct clk_parent_data dpu0_clk_pd[] = { 875 { .hw = &dpu0_clk.common.hw } 876}; 877 878static struct ccu_div dpu1_clk = { 879 .div_en = BIT(8), 880 .div = TH_CCU_DIV_FLAGS(0, 8, CLK_DIVIDER_ONE_BASED), 881 .common = { 882 .clkid = CLK_DPU1, 883 .cfg0 = 0x1ec, 884 .hw.init = CLK_HW_INIT_PARENTS_HW("dpu1", 885 dpu1_pll_clk_parent, 886 &ccu_div_ops, 887 CLK_SET_RATE_UNGATE), 888 }, 889}; 890 891static const struct clk_parent_data dpu1_clk_pd[] = { 892 { .hw = &dpu1_clk.common.hw } 893}; 894 895static CLK_FIXED_FACTOR_HW(emmc_sdio_ref_clk, "emmc-sdio-ref", 896 &video_pll_clk.common.hw, 4, 1, 0); 897 898static const struct clk_parent_data emmc_sdio_ref_clk_pd[] = { 899 { .hw = &emmc_sdio_ref_clk.hw }, 900}; 901 902static CCU_GATE(CLK_BROM, brom_clk, "brom", ahb2_cpusys_hclk_pd, 0x100, 4, 0); 903static CCU_GATE(CLK_BMU, bmu_clk, "bmu", axi4_cpusys2_aclk_pd, 0x100, 5, 0); 904static CCU_GATE(CLK_AON2CPU_A2X, aon2cpu_a2x_clk, "aon2cpu-a2x", axi4_cpusys2_aclk_pd, 905 0x134, 8, CLK_IS_CRITICAL); 906static CCU_GATE(CLK_X2X_CPUSYS, x2x_cpusys_clk, "x2x-cpusys", axi4_cpusys2_aclk_pd, 907 0x134, 7, CLK_IS_CRITICAL); 908static CCU_GATE(CLK_CPU2AON_X2H, cpu2aon_x2h_clk, "cpu2aon-x2h", axi_aclk_pd, 909 0x138, 8, CLK_IS_CRITICAL); 910static CCU_GATE(CLK_CPU2PERI_X2H, cpu2peri_x2h_clk, "cpu2peri-x2h", axi4_cpusys2_aclk_pd, 911 0x140, 9, CLK_IS_CRITICAL); 912static CCU_GATE(CLK_PERISYS_APB1_HCLK, perisys_apb1_hclk, "perisys-apb1-hclk", perisys_ahb_hclk_pd, 913 0x150, 9, CLK_IS_CRITICAL); 914static CCU_GATE(CLK_PERISYS_APB2_HCLK, perisys_apb2_hclk, "perisys-apb2-hclk", perisys_ahb_hclk_pd, 915 0x150, 10, CLK_IS_CRITICAL); 916static CCU_GATE(CLK_PERISYS_APB3_HCLK, perisys_apb3_hclk, "perisys-apb3-hclk", perisys_ahb_hclk_pd, 917 0x150, 11, CLK_IS_CRITICAL); 918static CCU_GATE(CLK_PERISYS_APB4_HCLK, perisys_apb4_hclk, "perisys-apb4-hclk", perisys_ahb_hclk_pd, 919 0x150, 12, 0); 920static const struct clk_parent_data perisys_apb4_hclk_pd[] = { 921 { .hw = &perisys_apb4_hclk.gate.hw }, 922}; 923 924static CCU_GATE(CLK_NPU_AXI, npu_axi_clk, "npu-axi", axi_aclk_pd, 0x1c8, 5, CLK_IS_CRITICAL); 925static CCU_GATE(CLK_CPU2VP, cpu2vp_clk, "cpu2vp", axi_aclk_pd, 0x1e0, 13, CLK_IS_CRITICAL); 926static CCU_GATE(CLK_EMMC_SDIO, emmc_sdio_clk, "emmc-sdio", emmc_sdio_ref_clk_pd, 0x204, 30, 0); 927static CCU_GATE(CLK_GMAC1, gmac1_clk, "gmac1", gmac_pll_clk_pd, 0x204, 26, 0); 928static CCU_GATE(CLK_PADCTRL1, padctrl1_clk, "padctrl1", perisys_apb_pclk_pd, 0x204, 24, 0); 929static CCU_GATE(CLK_DSMART, dsmart_clk, "dsmart", perisys_apb_pclk_pd, 0x204, 23, 0); 930static CCU_GATE(CLK_PADCTRL0, padctrl0_clk, "padctrl0", perisys_apb4_hclk_pd, 0x204, 22, 0); 931static CCU_GATE(CLK_GMAC_AXI, gmac_axi_clk, "gmac-axi", axi4_cpusys2_aclk_pd, 0x204, 21, 0); 932static CCU_GATE(CLK_GPIO3, gpio3_clk, "gpio3-clk", peri2sys_apb_pclk_pd, 0x204, 20, 0); 933static CCU_GATE(CLK_GMAC0, gmac0_clk, "gmac0", gmac_pll_clk_pd, 0x204, 19, 0); 934static CCU_GATE(CLK_PWM, pwm_clk, "pwm", perisys_apb_pclk_pd, 0x204, 18, 0); 935static CCU_GATE(CLK_QSPI0, qspi0_clk, "qspi0", video_pll_clk_pd, 0x204, 17, 0); 936static CCU_GATE(CLK_QSPI1, qspi1_clk, "qspi1", video_pll_clk_pd, 0x204, 16, 0); 937static CCU_GATE(CLK_SPI, spi_clk, "spi", video_pll_clk_pd, 0x204, 15, 0); 938static CCU_GATE(CLK_UART0_PCLK, uart0_pclk, "uart0-pclk", perisys_apb_pclk_pd, 0x204, 14, 0); 939static CCU_GATE(CLK_UART1_PCLK, uart1_pclk, "uart1-pclk", perisys_apb_pclk_pd, 0x204, 13, 0); 940static CCU_GATE(CLK_UART2_PCLK, uart2_pclk, "uart2-pclk", perisys_apb_pclk_pd, 0x204, 12, 0); 941static CCU_GATE(CLK_UART3_PCLK, uart3_pclk, "uart3-pclk", perisys_apb_pclk_pd, 0x204, 11, 0); 942static CCU_GATE(CLK_UART4_PCLK, uart4_pclk, "uart4-pclk", perisys_apb_pclk_pd, 0x204, 10, 0); 943static CCU_GATE(CLK_UART5_PCLK, uart5_pclk, "uart5-pclk", perisys_apb_pclk_pd, 0x204, 9, 0); 944static CCU_GATE(CLK_GPIO0, gpio0_clk, "gpio0-clk", perisys_apb_pclk_pd, 0x204, 8, 0); 945static CCU_GATE(CLK_GPIO1, gpio1_clk, "gpio1-clk", perisys_apb_pclk_pd, 0x204, 7, 0); 946static CCU_GATE(CLK_GPIO2, gpio2_clk, "gpio2-clk", peri2sys_apb_pclk_pd, 0x204, 6, 0); 947static CCU_GATE(CLK_I2C0, i2c0_clk, "i2c0", perisys_apb_pclk_pd, 0x204, 5, 0); 948static CCU_GATE(CLK_I2C1, i2c1_clk, "i2c1", perisys_apb_pclk_pd, 0x204, 4, 0); 949static CCU_GATE(CLK_I2C2, i2c2_clk, "i2c2", perisys_apb_pclk_pd, 0x204, 3, 0); 950static CCU_GATE(CLK_I2C3, i2c3_clk, "i2c3", perisys_apb_pclk_pd, 0x204, 2, 0); 951static CCU_GATE(CLK_I2C4, i2c4_clk, "i2c4", perisys_apb_pclk_pd, 0x204, 1, 0); 952static CCU_GATE(CLK_I2C5, i2c5_clk, "i2c5", perisys_apb_pclk_pd, 0x204, 0, 0); 953static CCU_GATE(CLK_SPINLOCK, spinlock_clk, "spinlock", ahb2_cpusys_hclk_pd, 0x208, 10, 0); 954static CCU_GATE(CLK_DMA, dma_clk, "dma", axi4_cpusys2_aclk_pd, 0x208, 8, 0); 955static CCU_GATE(CLK_MBOX0, mbox0_clk, "mbox0", apb3_cpusys_pclk_pd, 0x208, 7, 0); 956static CCU_GATE(CLK_MBOX1, mbox1_clk, "mbox1", apb3_cpusys_pclk_pd, 0x208, 6, 0); 957static CCU_GATE(CLK_MBOX2, mbox2_clk, "mbox2", apb3_cpusys_pclk_pd, 0x208, 5, 0); 958static CCU_GATE(CLK_MBOX3, mbox3_clk, "mbox3", apb3_cpusys_pclk_pd, 0x208, 4, 0); 959static CCU_GATE(CLK_WDT0, wdt0_clk, "wdt0", apb3_cpusys_pclk_pd, 0x208, 3, 0); 960static CCU_GATE(CLK_WDT1, wdt1_clk, "wdt1", apb3_cpusys_pclk_pd, 0x208, 2, 0); 961static CCU_GATE(CLK_TIMER0, timer0_clk, "timer0", apb3_cpusys_pclk_pd, 0x208, 1, 0); 962static CCU_GATE(CLK_TIMER1, timer1_clk, "timer1", apb3_cpusys_pclk_pd, 0x208, 0, 0); 963static CCU_GATE(CLK_SRAM0, sram0_clk, "sram0", axi_aclk_pd, 0x20c, 4, 0); 964static CCU_GATE(CLK_SRAM1, sram1_clk, "sram1", axi_aclk_pd, 0x20c, 3, 0); 965static CCU_GATE(CLK_SRAM2, sram2_clk, "sram2", axi_aclk_pd, 0x20c, 2, 0); 966static CCU_GATE(CLK_SRAM3, sram3_clk, "sram3", axi_aclk_pd, 0x20c, 1, 0); 967 968static CCU_GATE(CLK_AXI4_VO_ACLK, axi4_vo_aclk, "axi4-vo-aclk", 969 video_pll_clk_pd, 0x0, 0, CLK_IS_CRITICAL); 970static CCU_GATE(CLK_GPU_CORE, gpu_core_clk, "gpu-core-clk", video_pll_clk_pd, 971 0x0, 3, 0); 972static CCU_GATE(CLK_GPU_CFG_ACLK, gpu_cfg_aclk, "gpu-cfg-aclk", 973 video_pll_clk_pd, 0x0, 4, CLK_IS_CRITICAL); 974static CCU_GATE(CLK_DPU_PIXELCLK0, dpu0_pixelclk, "dpu0-pixelclk", 975 dpu0_clk_pd, 0x0, 5, CLK_SET_RATE_PARENT); 976static CCU_GATE(CLK_DPU_PIXELCLK1, dpu1_pixelclk, "dpu1-pixelclk", 977 dpu1_clk_pd, 0x0, 6, CLK_SET_RATE_PARENT); 978static CCU_GATE(CLK_DPU_HCLK, dpu_hclk, "dpu-hclk", video_pll_clk_pd, 0x0, 979 7, 0); 980static CCU_GATE(CLK_DPU_ACLK, dpu_aclk, "dpu-aclk", video_pll_clk_pd, 0x0, 981 8, 0); 982static CCU_GATE(CLK_DPU_CCLK, dpu_cclk, "dpu-cclk", video_pll_clk_pd, 0x0, 983 9, 0); 984static CCU_GATE(CLK_HDMI_SFR, hdmi_sfr_clk, "hdmi-sfr-clk", video_pll_clk_pd, 985 0x0, 10, 0); 986static CCU_GATE(CLK_HDMI_PCLK, hdmi_pclk, "hdmi-pclk", video_pll_clk_pd, 0x0, 987 11, 0); 988static CCU_GATE(CLK_HDMI_CEC, hdmi_cec_clk, "hdmi-cec-clk", video_pll_clk_pd, 989 0x0, 12, 0); 990static CCU_GATE(CLK_MIPI_DSI0_PCLK, mipi_dsi0_pclk, "mipi-dsi0-pclk", 991 video_pll_clk_pd, 0x0, 13, 0); 992static CCU_GATE(CLK_MIPI_DSI1_PCLK, mipi_dsi1_pclk, "mipi-dsi1-pclk", 993 video_pll_clk_pd, 0x0, 14, 0); 994static CCU_GATE(CLK_MIPI_DSI0_CFG, mipi_dsi0_cfg_clk, "mipi-dsi0-cfg-clk", 995 video_pll_clk_pd, 0x0, 15, 0); 996static CCU_GATE(CLK_MIPI_DSI1_CFG, mipi_dsi1_cfg_clk, "mipi-dsi1-cfg-clk", 997 video_pll_clk_pd, 0x0, 16, 0); 998static CCU_GATE(CLK_MIPI_DSI0_REFCLK, mipi_dsi0_refclk, "mipi-dsi0-refclk", 999 video_pll_clk_pd, 0x0, 17, 0); 1000static CCU_GATE(CLK_MIPI_DSI1_REFCLK, mipi_dsi1_refclk, "mipi-dsi1-refclk", 1001 video_pll_clk_pd, 0x0, 18, 0); 1002static CCU_GATE(CLK_HDMI_I2S, hdmi_i2s_clk, "hdmi-i2s-clk", video_pll_clk_pd, 1003 0x0, 19, 0); 1004static CCU_GATE(CLK_X2H_DPU1_ACLK, x2h_dpu1_aclk, "x2h-dpu1-aclk", 1005 video_pll_clk_pd, 0x0, 20, CLK_IS_CRITICAL); 1006static CCU_GATE(CLK_X2H_DPU_ACLK, x2h_dpu_aclk, "x2h-dpu-aclk", 1007 video_pll_clk_pd, 0x0, 21, CLK_IS_CRITICAL); 1008static CCU_GATE(CLK_AXI4_VO_PCLK, axi4_vo_pclk, "axi4-vo-pclk", 1009 video_pll_clk_pd, 0x0, 22, 0); 1010static CCU_GATE(CLK_IOPMP_VOSYS_DPU_PCLK, iopmp_vosys_dpu_pclk, 1011 "iopmp-vosys-dpu-pclk", video_pll_clk_pd, 0x0, 23, 0); 1012static CCU_GATE(CLK_IOPMP_VOSYS_DPU1_PCLK, iopmp_vosys_dpu1_pclk, 1013 "iopmp-vosys-dpu1-pclk", video_pll_clk_pd, 0x0, 24, 0); 1014static CCU_GATE(CLK_IOPMP_VOSYS_GPU_PCLK, iopmp_vosys_gpu_pclk, 1015 "iopmp-vosys-gpu-pclk", video_pll_clk_pd, 0x0, 25, 0); 1016static CCU_GATE(CLK_IOPMP_DPU1_ACLK, iopmp_dpu1_aclk, "iopmp-dpu1-aclk", 1017 video_pll_clk_pd, 0x0, 27, CLK_IS_CRITICAL); 1018static CCU_GATE(CLK_IOPMP_DPU_ACLK, iopmp_dpu_aclk, "iopmp-dpu-aclk", 1019 video_pll_clk_pd, 0x0, 28, CLK_IS_CRITICAL); 1020static CCU_GATE(CLK_IOPMP_GPU_ACLK, iopmp_gpu_aclk, "iopmp-gpu-aclk", 1021 video_pll_clk_pd, 0x0, 29, CLK_IS_CRITICAL); 1022static CCU_GATE(CLK_MIPIDSI0_PIXCLK, mipi_dsi0_pixclk, "mipi-dsi0-pixclk", 1023 video_pll_clk_pd, 0x0, 30, 0); 1024static CCU_GATE(CLK_MIPIDSI1_PIXCLK, mipi_dsi1_pixclk, "mipi-dsi1-pixclk", 1025 video_pll_clk_pd, 0x0, 31, 0); 1026static CCU_GATE(CLK_HDMI_PIXCLK, hdmi_pixclk, "hdmi-pixclk", video_pll_clk_pd, 1027 0x4, 0, 0); 1028 1029static CLK_FIXED_FACTOR_HW(gmac_pll_clk_100m, "gmac-pll-clk-100m", 1030 &gmac_pll_clk.common.hw, 10, 1, 0); 1031 1032static const struct clk_parent_data uart_sclk_parents[] = { 1033 { .hw = &gmac_pll_clk_100m.hw }, 1034 { .index = 0 }, 1035}; 1036 1037static struct ccu_mux uart_sclk = { 1038 .clkid = CLK_UART_SCLK, 1039 .reg = 0x210, 1040 .mux = TH_CCU_MUX("uart-sclk", uart_sclk_parents, 0, 1), 1041}; 1042 1043static struct ccu_common *th1520_pll_clks[] = { 1044 &cpu_pll0_clk.common, 1045 &cpu_pll1_clk.common, 1046 &gmac_pll_clk.common, 1047 &video_pll_clk.common, 1048 &dpu0_pll_clk.common, 1049 &dpu1_pll_clk.common, 1050 &tee_pll_clk.common, 1051}; 1052 1053static struct ccu_common *th1520_div_clks[] = { 1054 &ahb2_cpusys_hclk.common, 1055 &apb3_cpusys_pclk.common, 1056 &axi4_cpusys2_aclk.common, 1057 &perisys_ahb_hclk.common, 1058 &perisys_apb_pclk.common, 1059 &axi_aclk.common, 1060 &peri2sys_apb_pclk.common, 1061 &out1_clk.common, 1062 &out2_clk.common, 1063 &out3_clk.common, 1064 &out4_clk.common, 1065 &apb_pclk.common, 1066 &npu_clk.common, 1067 &vi_clk.common, 1068 &vi_ahb_clk.common, 1069 &vo_axi_clk.common, 1070 &vp_apb_clk.common, 1071 &vp_axi_clk.common, 1072 &venc_clk.common, 1073 &dpu0_clk.common, 1074 &dpu1_clk.common, 1075}; 1076 1077static struct ccu_mux *th1520_mux_clks[] = { 1078 &c910_i0_clk, 1079 &c910_clk, 1080 &uart_sclk, 1081}; 1082 1083static struct ccu_gate *th1520_gate_clks[] = { 1084 &emmc_sdio_clk, 1085 &aon2cpu_a2x_clk, 1086 &x2x_cpusys_clk, 1087 &brom_clk, 1088 &bmu_clk, 1089 &cpu2aon_x2h_clk, 1090 &cpu2peri_x2h_clk, 1091 &cpu2vp_clk, 1092 &perisys_apb1_hclk, 1093 &perisys_apb2_hclk, 1094 &perisys_apb3_hclk, 1095 &perisys_apb4_hclk, 1096 &npu_axi_clk, 1097 &gmac1_clk, 1098 &padctrl1_clk, 1099 &dsmart_clk, 1100 &padctrl0_clk, 1101 &gmac_axi_clk, 1102 &gpio3_clk, 1103 &gmac0_clk, 1104 &pwm_clk, 1105 &qspi0_clk, 1106 &qspi1_clk, 1107 &spi_clk, 1108 &uart0_pclk, 1109 &uart1_pclk, 1110 &uart2_pclk, 1111 &uart3_pclk, 1112 &uart4_pclk, 1113 &uart5_pclk, 1114 &gpio0_clk, 1115 &gpio1_clk, 1116 &gpio2_clk, 1117 &i2c0_clk, 1118 &i2c1_clk, 1119 &i2c2_clk, 1120 &i2c3_clk, 1121 &i2c4_clk, 1122 &i2c5_clk, 1123 &spinlock_clk, 1124 &dma_clk, 1125 &mbox0_clk, 1126 &mbox1_clk, 1127 &mbox2_clk, 1128 &mbox3_clk, 1129 &wdt0_clk, 1130 &wdt1_clk, 1131 &timer0_clk, 1132 &timer1_clk, 1133 &sram0_clk, 1134 &sram1_clk, 1135 &sram2_clk, 1136 &sram3_clk, 1137}; 1138 1139static struct ccu_gate *th1520_vo_gate_clks[] = { 1140 &axi4_vo_aclk, 1141 &gpu_core_clk, 1142 &gpu_cfg_aclk, 1143 &dpu0_pixelclk, 1144 &dpu1_pixelclk, 1145 &dpu_hclk, 1146 &dpu_aclk, 1147 &dpu_cclk, 1148 &hdmi_sfr_clk, 1149 &hdmi_pclk, 1150 &hdmi_cec_clk, 1151 &mipi_dsi0_pclk, 1152 &mipi_dsi1_pclk, 1153 &mipi_dsi0_cfg_clk, 1154 &mipi_dsi1_cfg_clk, 1155 &mipi_dsi0_refclk, 1156 &mipi_dsi1_refclk, 1157 &hdmi_i2s_clk, 1158 &x2h_dpu1_aclk, 1159 &x2h_dpu_aclk, 1160 &axi4_vo_pclk, 1161 &iopmp_vosys_dpu_pclk, 1162 &iopmp_vosys_dpu1_pclk, 1163 &iopmp_vosys_gpu_pclk, 1164 &iopmp_dpu1_aclk, 1165 &iopmp_dpu_aclk, 1166 &iopmp_gpu_aclk, 1167 &mipi_dsi0_pixclk, 1168 &mipi_dsi1_pixclk, 1169 &hdmi_pixclk 1170}; 1171 1172static const struct regmap_config th1520_clk_regmap_config = { 1173 .reg_bits = 32, 1174 .val_bits = 32, 1175 .reg_stride = 4, 1176}; 1177 1178struct th1520_plat_data { 1179 struct ccu_common **th1520_pll_clks; 1180 struct ccu_common **th1520_div_clks; 1181 struct ccu_mux **th1520_mux_clks; 1182 struct ccu_gate **th1520_gate_clks; 1183 1184 int nr_clks; 1185 int nr_pll_clks; 1186 int nr_div_clks; 1187 int nr_mux_clks; 1188 int nr_gate_clks; 1189}; 1190 1191static const struct th1520_plat_data th1520_ap_platdata = { 1192 .th1520_pll_clks = th1520_pll_clks, 1193 .th1520_div_clks = th1520_div_clks, 1194 .th1520_mux_clks = th1520_mux_clks, 1195 .th1520_gate_clks = th1520_gate_clks, 1196 1197 .nr_clks = CLK_UART_SCLK + 1, 1198 1199 .nr_pll_clks = ARRAY_SIZE(th1520_pll_clks), 1200 .nr_div_clks = ARRAY_SIZE(th1520_div_clks), 1201 .nr_mux_clks = ARRAY_SIZE(th1520_mux_clks), 1202 .nr_gate_clks = ARRAY_SIZE(th1520_gate_clks), 1203}; 1204 1205static const struct th1520_plat_data th1520_vo_platdata = { 1206 .th1520_gate_clks = th1520_vo_gate_clks, 1207 1208 .nr_clks = CLK_HDMI_PIXCLK + 1, 1209 1210 .nr_gate_clks = ARRAY_SIZE(th1520_vo_gate_clks), 1211}; 1212 1213static int th1520_clk_probe(struct platform_device *pdev) 1214{ 1215 const struct th1520_plat_data *plat_data; 1216 struct device *dev = &pdev->dev; 1217 struct clk_hw_onecell_data *priv; 1218 1219 struct regmap *map; 1220 void __iomem *base; 1221 int ret, i; 1222 1223 plat_data = device_get_match_data(&pdev->dev); 1224 if (!plat_data) 1225 return dev_err_probe(&pdev->dev, -ENODEV, 1226 "No device match data found\n"); 1227 1228 priv = devm_kzalloc(dev, struct_size(priv, hws, plat_data->nr_clks), GFP_KERNEL); 1229 if (!priv) 1230 return -ENOMEM; 1231 1232 priv->num = plat_data->nr_clks; 1233 1234 base = devm_platform_ioremap_resource(pdev, 0); 1235 if (IS_ERR(base)) 1236 return PTR_ERR(base); 1237 1238 map = devm_regmap_init_mmio(dev, base, &th1520_clk_regmap_config); 1239 if (IS_ERR(map)) 1240 return PTR_ERR(map); 1241 1242 for (i = 0; i < plat_data->nr_pll_clks; i++) { 1243 struct ccu_pll *cp = hw_to_ccu_pll(&plat_data->th1520_pll_clks[i]->hw); 1244 1245 plat_data->th1520_pll_clks[i]->map = map; 1246 1247 ret = devm_clk_hw_register(dev, &plat_data->th1520_pll_clks[i]->hw); 1248 if (ret) 1249 return ret; 1250 1251 priv->hws[cp->common.clkid] = &cp->common.hw; 1252 } 1253 1254 for (i = 0; i < plat_data->nr_div_clks; i++) { 1255 struct ccu_div *cd = hw_to_ccu_div(&plat_data->th1520_div_clks[i]->hw); 1256 1257 plat_data->th1520_div_clks[i]->map = map; 1258 1259 ret = devm_clk_hw_register(dev, &plat_data->th1520_div_clks[i]->hw); 1260 if (ret) 1261 return ret; 1262 1263 priv->hws[cd->common.clkid] = &cd->common.hw; 1264 } 1265 1266 for (i = 0; i < plat_data->nr_mux_clks; i++) { 1267 struct ccu_mux *cm = plat_data->th1520_mux_clks[i]; 1268 1269 cm->mux.reg = base + cm->reg; 1270 1271 ret = devm_clk_hw_register(dev, &cm->mux.hw); 1272 if (ret) 1273 return ret; 1274 1275 priv->hws[cm->clkid] = &cm->mux.hw; 1276 } 1277 1278 for (i = 0; i < plat_data->nr_gate_clks; i++) { 1279 struct ccu_gate *cg = plat_data->th1520_gate_clks[i]; 1280 1281 cg->gate.reg = base + cg->reg; 1282 1283 ret = devm_clk_hw_register(dev, &cg->gate.hw); 1284 if (ret) 1285 return ret; 1286 1287 priv->hws[cg->clkid] = &cg->gate.hw; 1288 } 1289 1290 if (plat_data == &th1520_ap_platdata) { 1291 ret = devm_clk_hw_register(dev, &osc12m_clk.hw); 1292 if (ret) 1293 return ret; 1294 priv->hws[CLK_OSC12M] = &osc12m_clk.hw; 1295 1296 ret = devm_clk_hw_register(dev, &gmac_pll_clk_100m.hw); 1297 if (ret) 1298 return ret; 1299 priv->hws[CLK_PLL_GMAC_100M] = &gmac_pll_clk_100m.hw; 1300 1301 ret = devm_clk_hw_register(dev, &emmc_sdio_ref_clk.hw); 1302 if (ret) 1303 return ret; 1304 } 1305 1306 ret = devm_of_clk_add_hw_provider(dev, of_clk_hw_onecell_get, priv); 1307 if (ret) 1308 return ret; 1309 1310 return 0; 1311} 1312 1313static const struct of_device_id th1520_clk_match[] = { 1314 { 1315 .compatible = "thead,th1520-clk-ap", 1316 .data = &th1520_ap_platdata, 1317 }, 1318 { 1319 .compatible = "thead,th1520-clk-vo", 1320 .data = &th1520_vo_platdata, 1321 }, 1322 { /* sentinel */ }, 1323}; 1324MODULE_DEVICE_TABLE(of, th1520_clk_match); 1325 1326static struct platform_driver th1520_clk_driver = { 1327 .probe = th1520_clk_probe, 1328 .driver = { 1329 .name = "th1520-clk", 1330 .of_match_table = th1520_clk_match, 1331 }, 1332}; 1333module_platform_driver(th1520_clk_driver); 1334 1335MODULE_DESCRIPTION("T-HEAD TH1520 AP Clock driver"); 1336MODULE_AUTHOR("Yangtao Li <frank.li@vivo.com>"); 1337MODULE_AUTHOR("Jisheng Zhang <jszhang@kernel.org>"); 1338MODULE_LICENSE("GPL");
~/
Read-only file preview.