1 /* 2 * drivers/clk/clk-axm5516.c 3 * 4 * Provides clock implementations for three different types of clock devices on 5 * the Axxia device: PLL clock, a clock divider and a clock mux. 6 * 7 * Copyright (C) 2014 LSI Corporation 8 * 9 * This program is free software; you can redistribute it and/or modify it 10 * under the terms of the GNU General Public License version 2 as published by 11 * the Free Software Foundation. 12 */ 13 #include <linux/module.h> 14 #include <linux/kernel.h> 15 #include <linux/slab.h> 16 #include <linux/platform_device.h> 17 #include <linux/of.h> 18 #include <linux/of_address.h> 19 #include <linux/clk-provider.h> 20 #include <linux/regmap.h> 21 #include <dt-bindings/clock/lsi,axm5516-clks.h> 22 23 24 /** 25 * struct axxia_clk - Common struct to all Axxia clocks. 26 * @hw: clk_hw for the common clk framework 27 * @regmap: Regmap for the clock control registers 28 */ 29 struct axxia_clk { 30 struct clk_hw hw; 31 struct regmap *regmap; 32 }; 33 #define to_axxia_clk(_hw) container_of(_hw, struct axxia_clk, hw) 34 35 /** 36 * struct axxia_pllclk - Axxia PLL generated clock. 37 * @aclk: Common struct 38 * @reg: Offset into regmap for PLL control register 39 */ 40 struct axxia_pllclk { 41 struct axxia_clk aclk; 42 u32 reg; 43 }; 44 #define to_axxia_pllclk(_aclk) container_of(_aclk, struct axxia_pllclk, aclk) 45 46 /** 47 * axxia_pllclk_recalc - Calculate the PLL generated clock rate given the 48 * parent clock rate. 49 */ 50 static unsigned long 51 axxia_pllclk_recalc(struct clk_hw *hw, unsigned long parent_rate) 52 { 53 struct axxia_clk *aclk = to_axxia_clk(hw); 54 struct axxia_pllclk *pll = to_axxia_pllclk(aclk); 55 unsigned long rate, fbdiv, refdiv, postdiv; 56 u32 control; 57 58 regmap_read(aclk->regmap, pll->reg, &control); 59 postdiv = ((control >> 0) & 0xf) + 1; 60 fbdiv = ((control >> 4) & 0xfff) + 3; 61 refdiv = ((control >> 16) & 0x1f) + 1; 62 rate = (parent_rate / (refdiv * postdiv)) * fbdiv; 63 64 return rate; 65 } 66 67 static const struct clk_ops axxia_pllclk_ops = { 68 .recalc_rate = axxia_pllclk_recalc, 69 }; 70 71 /** 72 * struct axxia_divclk - Axxia clock divider 73 * @aclk: Common struct 74 * @reg: Offset into regmap for PLL control register 75 * @shift: Bit position for divider value 76 * @width: Number of bits in divider value 77 */ 78 struct axxia_divclk { 79 struct axxia_clk aclk; 80 u32 reg; 81 u32 shift; 82 u32 width; 83 }; 84 #define to_axxia_divclk(_aclk) container_of(_aclk, struct axxia_divclk, aclk) 85 86 /** 87 * axxia_divclk_recalc_rate - Calculate clock divider output rage 88 */ 89 static unsigned long 90 axxia_divclk_recalc_rate(struct clk_hw *hw, unsigned long parent_rate) 91 { 92 struct axxia_clk *aclk = to_axxia_clk(hw); 93 struct axxia_divclk *divclk = to_axxia_divclk(aclk); 94 u32 ctrl, div; 95 96 regmap_read(aclk->regmap, divclk->reg, &ctrl); 97 div = 1 + ((ctrl >> divclk->shift) & ((1 << divclk->width)-1)); 98 99 return parent_rate / div; 100 } 101 102 static const struct clk_ops axxia_divclk_ops = { 103 .recalc_rate = axxia_divclk_recalc_rate, 104 }; 105 106 /** 107 * struct axxia_clkmux - Axxia clock mux 108 * @aclk: Common struct 109 * @reg: Offset into regmap for PLL control register 110 * @shift: Bit position for selection value 111 * @width: Number of bits in selection value 112 */ 113 struct axxia_clkmux { 114 struct axxia_clk aclk; 115 u32 reg; 116 u32 shift; 117 u32 width; 118 }; 119 #define to_axxia_clkmux(_aclk) container_of(_aclk, struct axxia_clkmux, aclk) 120 121 /** 122 * axxia_clkmux_get_parent - Return the index of selected parent clock 123 */ 124 static u8 axxia_clkmux_get_parent(struct clk_hw *hw) 125 { 126 struct axxia_clk *aclk = to_axxia_clk(hw); 127 struct axxia_clkmux *mux = to_axxia_clkmux(aclk); 128 u32 ctrl, parent; 129 130 regmap_read(aclk->regmap, mux->reg, &ctrl); 131 parent = (ctrl >> mux->shift) & ((1 << mux->width) - 1); 132 133 return (u8) parent; 134 } 135 136 static const struct clk_ops axxia_clkmux_ops = { 137 .get_parent = axxia_clkmux_get_parent, 138 }; 139 140 141 /* 142 * PLLs 143 */ 144 145 static struct axxia_pllclk clk_fab_pll = { 146 .aclk.hw.init = &(struct clk_init_data){ 147 .name = "clk_fab_pll", 148 .parent_names = (const char *[]){ 149 "clk_ref0" 150 }, 151 .num_parents = 1, 152 .ops = &axxia_pllclk_ops, 153 }, 154 .reg = 0x01800, 155 }; 156 157 static struct axxia_pllclk clk_cpu_pll = { 158 .aclk.hw.init = &(struct clk_init_data){ 159 .name = "clk_cpu_pll", 160 .parent_names = (const char *[]){ 161 "clk_ref0" 162 }, 163 .num_parents = 1, 164 .ops = &axxia_pllclk_ops, 165 }, 166 .reg = 0x02000, 167 }; 168 169 static struct axxia_pllclk clk_sys_pll = { 170 .aclk.hw.init = &(struct clk_init_data){ 171 .name = "clk_sys_pll", 172 .parent_names = (const char *[]){ 173 "clk_ref0" 174 }, 175 .num_parents = 1, 176 .ops = &axxia_pllclk_ops, 177 }, 178 .reg = 0x02800, 179 }; 180 181 static struct axxia_pllclk clk_sm0_pll = { 182 .aclk.hw.init = &(struct clk_init_data){ 183 .name = "clk_sm0_pll", 184 .parent_names = (const char *[]){ 185 "clk_ref2" 186 }, 187 .num_parents = 1, 188 .ops = &axxia_pllclk_ops, 189 }, 190 .reg = 0x03000, 191 }; 192 193 static struct axxia_pllclk clk_sm1_pll = { 194 .aclk.hw.init = &(struct clk_init_data){ 195 .name = "clk_sm1_pll", 196 .parent_names = (const char *[]){ 197 "clk_ref1" 198 }, 199 .num_parents = 1, 200 .ops = &axxia_pllclk_ops, 201 }, 202 .reg = 0x03800, 203 }; 204 205 /* 206 * Clock dividers 207 */ 208 209 static struct axxia_divclk clk_cpu0_div = { 210 .aclk.hw.init = &(struct clk_init_data){ 211 .name = "clk_cpu0_div", 212 .parent_names = (const char *[]){ 213 "clk_cpu_pll" 214 }, 215 .num_parents = 1, 216 .ops = &axxia_divclk_ops, 217 }, 218 .reg = 0x10008, 219 .shift = 0, 220 .width = 4, 221 }; 222 223 static struct axxia_divclk clk_cpu1_div = { 224 .aclk.hw.init = &(struct clk_init_data){ 225 .name = "clk_cpu1_div", 226 .parent_names = (const char *[]){ 227 "clk_cpu_pll" 228 }, 229 .num_parents = 1, 230 .ops = &axxia_divclk_ops, 231 }, 232 .reg = 0x10008, 233 .shift = 4, 234 .width = 4, 235 }; 236 237 static struct axxia_divclk clk_cpu2_div = { 238 .aclk.hw.init = &(struct clk_init_data){ 239 .name = "clk_cpu2_div", 240 .parent_names = (const char *[]){ 241 "clk_cpu_pll" 242 }, 243 .num_parents = 1, 244 .ops = &axxia_divclk_ops, 245 }, 246 .reg = 0x10008, 247 .shift = 8, 248 .width = 4, 249 }; 250 251 static struct axxia_divclk clk_cpu3_div = { 252 .aclk.hw.init = &(struct clk_init_data){ 253 .name = "clk_cpu3_div", 254 .parent_names = (const char *[]){ 255 "clk_cpu_pll" 256 }, 257 .num_parents = 1, 258 .ops = &axxia_divclk_ops, 259 }, 260 .reg = 0x10008, 261 .shift = 12, 262 .width = 4, 263 }; 264 265 static struct axxia_divclk clk_nrcp_div = { 266 .aclk.hw.init = &(struct clk_init_data){ 267 .name = "clk_nrcp_div", 268 .parent_names = (const char *[]){ 269 "clk_sys_pll" 270 }, 271 .num_parents = 1, 272 .ops = &axxia_divclk_ops, 273 }, 274 .reg = 0x1000c, 275 .shift = 0, 276 .width = 4, 277 }; 278 279 static struct axxia_divclk clk_sys_div = { 280 .aclk.hw.init = &(struct clk_init_data){ 281 .name = "clk_sys_div", 282 .parent_names = (const char *[]){ 283 "clk_sys_pll" 284 }, 285 .num_parents = 1, 286 .ops = &axxia_divclk_ops, 287 }, 288 .reg = 0x1000c, 289 .shift = 4, 290 .width = 4, 291 }; 292 293 static struct axxia_divclk clk_fab_div = { 294 .aclk.hw.init = &(struct clk_init_data){ 295 .name = "clk_fab_div", 296 .parent_names = (const char *[]){ 297 "clk_fab_pll" 298 }, 299 .num_parents = 1, 300 .ops = &axxia_divclk_ops, 301 }, 302 .reg = 0x1000c, 303 .shift = 8, 304 .width = 4, 305 }; 306 307 static struct axxia_divclk clk_per_div = { 308 .aclk.hw.init = &(struct clk_init_data){ 309 .name = "clk_per_div", 310 .parent_names = (const char *[]){ 311 "clk_sm1_pll" 312 }, 313 .num_parents = 1, 314 .ops = &axxia_divclk_ops, 315 }, 316 .reg = 0x1000c, 317 .shift = 12, 318 .width = 4, 319 }; 320 321 static struct axxia_divclk clk_mmc_div = { 322 .aclk.hw.init = &(struct clk_init_data){ 323 .name = "clk_mmc_div", 324 .parent_names = (const char *[]){ 325 "clk_sm1_pll" 326 }, 327 .num_parents = 1, 328 .ops = &axxia_divclk_ops, 329 }, 330 .reg = 0x1000c, 331 .shift = 16, 332 .width = 4, 333 }; 334 335 /* 336 * Clock MUXes 337 */ 338 339 static struct axxia_clkmux clk_cpu0_mux = { 340 .aclk.hw.init = &(struct clk_init_data){ 341 .name = "clk_cpu0", 342 .parent_names = (const char *[]){ 343 "clk_ref0", 344 "clk_cpu_pll", 345 "clk_cpu0_div", 346 "clk_cpu0_div" 347 }, 348 .num_parents = 4, 349 .ops = &axxia_clkmux_ops, 350 }, 351 .reg = 0x10000, 352 .shift = 0, 353 .width = 2, 354 }; 355 356 static struct axxia_clkmux clk_cpu1_mux = { 357 .aclk.hw.init = &(struct clk_init_data){ 358 .name = "clk_cpu1", 359 .parent_names = (const char *[]){ 360 "clk_ref0", 361 "clk_cpu_pll", 362 "clk_cpu1_div", 363 "clk_cpu1_div" 364 }, 365 .num_parents = 4, 366 .ops = &axxia_clkmux_ops, 367 }, 368 .reg = 0x10000, 369 .shift = 2, 370 .width = 2, 371 }; 372 373 static struct axxia_clkmux clk_cpu2_mux = { 374 .aclk.hw.init = &(struct clk_init_data){ 375 .name = "clk_cpu2", 376 .parent_names = (const char *[]){ 377 "clk_ref0", 378 "clk_cpu_pll", 379 "clk_cpu2_div", 380 "clk_cpu2_div" 381 }, 382 .num_parents = 4, 383 .ops = &axxia_clkmux_ops, 384 }, 385 .reg = 0x10000, 386 .shift = 4, 387 .width = 2, 388 }; 389 390 static struct axxia_clkmux clk_cpu3_mux = { 391 .aclk.hw.init = &(struct clk_init_data){ 392 .name = "clk_cpu3", 393 .parent_names = (const char *[]){ 394 "clk_ref0", 395 "clk_cpu_pll", 396 "clk_cpu3_div", 397 "clk_cpu3_div" 398 }, 399 .num_parents = 4, 400 .ops = &axxia_clkmux_ops, 401 }, 402 .reg = 0x10000, 403 .shift = 6, 404 .width = 2, 405 }; 406 407 static struct axxia_clkmux clk_nrcp_mux = { 408 .aclk.hw.init = &(struct clk_init_data){ 409 .name = "clk_nrcp", 410 .parent_names = (const char *[]){ 411 "clk_ref0", 412 "clk_sys_pll", 413 "clk_nrcp_div", 414 "clk_nrcp_div" 415 }, 416 .num_parents = 4, 417 .ops = &axxia_clkmux_ops, 418 }, 419 .reg = 0x10004, 420 .shift = 0, 421 .width = 2, 422 }; 423 424 static struct axxia_clkmux clk_sys_mux = { 425 .aclk.hw.init = &(struct clk_init_data){ 426 .name = "clk_sys", 427 .parent_names = (const char *[]){ 428 "clk_ref0", 429 "clk_sys_pll", 430 "clk_sys_div", 431 "clk_sys_div" 432 }, 433 .num_parents = 4, 434 .ops = &axxia_clkmux_ops, 435 }, 436 .reg = 0x10004, 437 .shift = 2, 438 .width = 2, 439 }; 440 441 static struct axxia_clkmux clk_fab_mux = { 442 .aclk.hw.init = &(struct clk_init_data){ 443 .name = "clk_fab", 444 .parent_names = (const char *[]){ 445 "clk_ref0", 446 "clk_fab_pll", 447 "clk_fab_div", 448 "clk_fab_div" 449 }, 450 .num_parents = 4, 451 .ops = &axxia_clkmux_ops, 452 }, 453 .reg = 0x10004, 454 .shift = 4, 455 .width = 2, 456 }; 457 458 static struct axxia_clkmux clk_per_mux = { 459 .aclk.hw.init = &(struct clk_init_data){ 460 .name = "clk_per", 461 .parent_names = (const char *[]){ 462 "clk_ref1", 463 "clk_per_div" 464 }, 465 .num_parents = 2, 466 .ops = &axxia_clkmux_ops, 467 }, 468 .reg = 0x10004, 469 .shift = 6, 470 .width = 1, 471 }; 472 473 static struct axxia_clkmux clk_mmc_mux = { 474 .aclk.hw.init = &(struct clk_init_data){ 475 .name = "clk_mmc", 476 .parent_names = (const char *[]){ 477 "clk_ref1", 478 "clk_mmc_div" 479 }, 480 .num_parents = 2, 481 .ops = &axxia_clkmux_ops, 482 }, 483 .reg = 0x10004, 484 .shift = 9, 485 .width = 1, 486 }; 487 488 /* Table of all supported clocks indexed by the clock identifiers from the 489 * device tree binding 490 */ 491 static struct axxia_clk *axmclk_clocks[] = { 492 [AXXIA_CLK_FAB_PLL] = &clk_fab_pll.aclk, 493 [AXXIA_CLK_CPU_PLL] = &clk_cpu_pll.aclk, 494 [AXXIA_CLK_SYS_PLL] = &clk_sys_pll.aclk, 495 [AXXIA_CLK_SM0_PLL] = &clk_sm0_pll.aclk, 496 [AXXIA_CLK_SM1_PLL] = &clk_sm1_pll.aclk, 497 [AXXIA_CLK_FAB_DIV] = &clk_fab_div.aclk, 498 [AXXIA_CLK_SYS_DIV] = &clk_sys_div.aclk, 499 [AXXIA_CLK_NRCP_DIV] = &clk_nrcp_div.aclk, 500 [AXXIA_CLK_CPU0_DIV] = &clk_cpu0_div.aclk, 501 [AXXIA_CLK_CPU1_DIV] = &clk_cpu1_div.aclk, 502 [AXXIA_CLK_CPU2_DIV] = &clk_cpu2_div.aclk, 503 [AXXIA_CLK_CPU3_DIV] = &clk_cpu3_div.aclk, 504 [AXXIA_CLK_PER_DIV] = &clk_per_div.aclk, 505 [AXXIA_CLK_MMC_DIV] = &clk_mmc_div.aclk, 506 [AXXIA_CLK_FAB] = &clk_fab_mux.aclk, 507 [AXXIA_CLK_SYS] = &clk_sys_mux.aclk, 508 [AXXIA_CLK_NRCP] = &clk_nrcp_mux.aclk, 509 [AXXIA_CLK_CPU0] = &clk_cpu0_mux.aclk, 510 [AXXIA_CLK_CPU1] = &clk_cpu1_mux.aclk, 511 [AXXIA_CLK_CPU2] = &clk_cpu2_mux.aclk, 512 [AXXIA_CLK_CPU3] = &clk_cpu3_mux.aclk, 513 [AXXIA_CLK_PER] = &clk_per_mux.aclk, 514 [AXXIA_CLK_MMC] = &clk_mmc_mux.aclk, 515 }; 516 517 static struct clk_hw * 518 of_clk_axmclk_get(struct of_phandle_args *clkspec, void *unused) 519 { 520 unsigned int idx = clkspec->args[0]; 521 522 if (idx >= ARRAY_SIZE(axmclk_clocks)) { 523 pr_err("%s: invalid index %u\n", __func__, idx); 524 return ERR_PTR(-EINVAL); 525 } 526 527 return &axmclk_clocks[idx]->hw; 528 } 529 530 static const struct regmap_config axmclk_regmap_config = { 531 .reg_bits = 32, 532 .reg_stride = 4, 533 .val_bits = 32, 534 .max_register = 0x1fffc, 535 .fast_io = true, 536 }; 537 538 static const struct of_device_id axmclk_match_table[] = { 539 { .compatible = "lsi,axm5516-clks" }, 540 { } 541 }; 542 MODULE_DEVICE_TABLE(of, axmclk_match_table); 543 544 static int axmclk_probe(struct platform_device *pdev) 545 { 546 void __iomem *base; 547 struct resource *res; 548 int i, ret; 549 struct device *dev = &pdev->dev; 550 struct regmap *regmap; 551 size_t num_clks; 552 553 res = platform_get_resource(pdev, IORESOURCE_MEM, 0); 554 base = devm_ioremap_resource(dev, res); 555 if (IS_ERR(base)) 556 return PTR_ERR(base); 557 558 regmap = devm_regmap_init_mmio(dev, base, &axmclk_regmap_config); 559 if (IS_ERR(regmap)) 560 return PTR_ERR(regmap); 561 562 num_clks = ARRAY_SIZE(axmclk_clocks); 563 pr_info("axmclk: supporting %zu clocks\n", num_clks); 564 565 /* Update each entry with the allocated regmap and register the clock 566 * with the common clock framework 567 */ 568 for (i = 0; i < num_clks; i++) { 569 axmclk_clocks[i]->regmap = regmap; 570 ret = devm_clk_hw_register(dev, &axmclk_clocks[i]->hw); 571 if (ret) 572 return ret; 573 } 574 575 return of_clk_add_hw_provider(dev->of_node, of_clk_axmclk_get, NULL); 576 } 577 578 static int axmclk_remove(struct platform_device *pdev) 579 { 580 of_clk_del_provider(pdev->dev.of_node); 581 return 0; 582 } 583 584 static struct platform_driver axmclk_driver = { 585 .probe = axmclk_probe, 586 .remove = axmclk_remove, 587 .driver = { 588 .name = "clk-axm5516", 589 .of_match_table = axmclk_match_table, 590 }, 591 }; 592 593 static int __init axmclk_init(void) 594 { 595 return platform_driver_register(&axmclk_driver); 596 } 597 core_initcall(axmclk_init); 598 599 static void __exit axmclk_exit(void) 600 { 601 platform_driver_unregister(&axmclk_driver); 602 } 603 module_exit(axmclk_exit); 604 605 MODULE_DESCRIPTION("AXM5516 clock driver"); 606 MODULE_LICENSE("GPL v2"); 607 MODULE_ALIAS("platform:clk-axm5516"); 608