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.

at v5.3-rc8 651 lines 17 kB view raw
1// SPDX-License-Identifier: GPL-2.0 2/* 3 * Copyright (C) 2011 Sascha Hauer, Pengutronix <s.hauer@pengutronix.de> 4 * Copyright (C) 2011 Richard Zhao, Linaro <richard.zhao@linaro.org> 5 * Copyright (C) 2011-2012 Mike Turquette, Linaro Ltd <mturquette@linaro.org> 6 * 7 * Adjustable divider clock implementation 8 */ 9 10#include <linux/clk-provider.h> 11#include <linux/module.h> 12#include <linux/slab.h> 13#include <linux/io.h> 14#include <linux/err.h> 15#include <linux/string.h> 16#include <linux/log2.h> 17 18/* 19 * DOC: basic adjustable divider clock that cannot gate 20 * 21 * Traits of this clock: 22 * prepare - clk_prepare only ensures that parents are prepared 23 * enable - clk_enable only ensures that parents are enabled 24 * rate - rate is adjustable. clk->rate = ceiling(parent->rate / divisor) 25 * parent - fixed parent. No clk_set_parent support 26 */ 27 28static inline u32 clk_div_readl(struct clk_divider *divider) 29{ 30 if (divider->flags & CLK_DIVIDER_BIG_ENDIAN) 31 return ioread32be(divider->reg); 32 33 return readl(divider->reg); 34} 35 36static inline void clk_div_writel(struct clk_divider *divider, u32 val) 37{ 38 if (divider->flags & CLK_DIVIDER_BIG_ENDIAN) 39 iowrite32be(val, divider->reg); 40 else 41 writel(val, divider->reg); 42} 43 44static unsigned int _get_table_maxdiv(const struct clk_div_table *table, 45 u8 width) 46{ 47 unsigned int maxdiv = 0, mask = clk_div_mask(width); 48 const struct clk_div_table *clkt; 49 50 for (clkt = table; clkt->div; clkt++) 51 if (clkt->div > maxdiv && clkt->val <= mask) 52 maxdiv = clkt->div; 53 return maxdiv; 54} 55 56static unsigned int _get_table_mindiv(const struct clk_div_table *table) 57{ 58 unsigned int mindiv = UINT_MAX; 59 const struct clk_div_table *clkt; 60 61 for (clkt = table; clkt->div; clkt++) 62 if (clkt->div < mindiv) 63 mindiv = clkt->div; 64 return mindiv; 65} 66 67static unsigned int _get_maxdiv(const struct clk_div_table *table, u8 width, 68 unsigned long flags) 69{ 70 if (flags & CLK_DIVIDER_ONE_BASED) 71 return clk_div_mask(width); 72 if (flags & CLK_DIVIDER_POWER_OF_TWO) 73 return 1 << clk_div_mask(width); 74 if (table) 75 return _get_table_maxdiv(table, width); 76 return clk_div_mask(width) + 1; 77} 78 79static unsigned int _get_table_div(const struct clk_div_table *table, 80 unsigned int val) 81{ 82 const struct clk_div_table *clkt; 83 84 for (clkt = table; clkt->div; clkt++) 85 if (clkt->val == val) 86 return clkt->div; 87 return 0; 88} 89 90static unsigned int _get_div(const struct clk_div_table *table, 91 unsigned int val, unsigned long flags, u8 width) 92{ 93 if (flags & CLK_DIVIDER_ONE_BASED) 94 return val; 95 if (flags & CLK_DIVIDER_POWER_OF_TWO) 96 return 1 << val; 97 if (flags & CLK_DIVIDER_MAX_AT_ZERO) 98 return val ? val : clk_div_mask(width) + 1; 99 if (table) 100 return _get_table_div(table, val); 101 return val + 1; 102} 103 104static unsigned int _get_table_val(const struct clk_div_table *table, 105 unsigned int div) 106{ 107 const struct clk_div_table *clkt; 108 109 for (clkt = table; clkt->div; clkt++) 110 if (clkt->div == div) 111 return clkt->val; 112 return 0; 113} 114 115static unsigned int _get_val(const struct clk_div_table *table, 116 unsigned int div, unsigned long flags, u8 width) 117{ 118 if (flags & CLK_DIVIDER_ONE_BASED) 119 return div; 120 if (flags & CLK_DIVIDER_POWER_OF_TWO) 121 return __ffs(div); 122 if (flags & CLK_DIVIDER_MAX_AT_ZERO) 123 return (div == clk_div_mask(width) + 1) ? 0 : div; 124 if (table) 125 return _get_table_val(table, div); 126 return div - 1; 127} 128 129unsigned long divider_recalc_rate(struct clk_hw *hw, unsigned long parent_rate, 130 unsigned int val, 131 const struct clk_div_table *table, 132 unsigned long flags, unsigned long width) 133{ 134 unsigned int div; 135 136 div = _get_div(table, val, flags, width); 137 if (!div) { 138 WARN(!(flags & CLK_DIVIDER_ALLOW_ZERO), 139 "%s: Zero divisor and CLK_DIVIDER_ALLOW_ZERO not set\n", 140 clk_hw_get_name(hw)); 141 return parent_rate; 142 } 143 144 return DIV_ROUND_UP_ULL((u64)parent_rate, div); 145} 146EXPORT_SYMBOL_GPL(divider_recalc_rate); 147 148static unsigned long clk_divider_recalc_rate(struct clk_hw *hw, 149 unsigned long parent_rate) 150{ 151 struct clk_divider *divider = to_clk_divider(hw); 152 unsigned int val; 153 154 val = clk_div_readl(divider) >> divider->shift; 155 val &= clk_div_mask(divider->width); 156 157 return divider_recalc_rate(hw, parent_rate, val, divider->table, 158 divider->flags, divider->width); 159} 160 161static bool _is_valid_table_div(const struct clk_div_table *table, 162 unsigned int div) 163{ 164 const struct clk_div_table *clkt; 165 166 for (clkt = table; clkt->div; clkt++) 167 if (clkt->div == div) 168 return true; 169 return false; 170} 171 172static bool _is_valid_div(const struct clk_div_table *table, unsigned int div, 173 unsigned long flags) 174{ 175 if (flags & CLK_DIVIDER_POWER_OF_TWO) 176 return is_power_of_2(div); 177 if (table) 178 return _is_valid_table_div(table, div); 179 return true; 180} 181 182static int _round_up_table(const struct clk_div_table *table, int div) 183{ 184 const struct clk_div_table *clkt; 185 int up = INT_MAX; 186 187 for (clkt = table; clkt->div; clkt++) { 188 if (clkt->div == div) 189 return clkt->div; 190 else if (clkt->div < div) 191 continue; 192 193 if ((clkt->div - div) < (up - div)) 194 up = clkt->div; 195 } 196 197 return up; 198} 199 200static int _round_down_table(const struct clk_div_table *table, int div) 201{ 202 const struct clk_div_table *clkt; 203 int down = _get_table_mindiv(table); 204 205 for (clkt = table; clkt->div; clkt++) { 206 if (clkt->div == div) 207 return clkt->div; 208 else if (clkt->div > div) 209 continue; 210 211 if ((div - clkt->div) < (div - down)) 212 down = clkt->div; 213 } 214 215 return down; 216} 217 218static int _div_round_up(const struct clk_div_table *table, 219 unsigned long parent_rate, unsigned long rate, 220 unsigned long flags) 221{ 222 int div = DIV_ROUND_UP_ULL((u64)parent_rate, rate); 223 224 if (flags & CLK_DIVIDER_POWER_OF_TWO) 225 div = __roundup_pow_of_two(div); 226 if (table) 227 div = _round_up_table(table, div); 228 229 return div; 230} 231 232static int _div_round_closest(const struct clk_div_table *table, 233 unsigned long parent_rate, unsigned long rate, 234 unsigned long flags) 235{ 236 int up, down; 237 unsigned long up_rate, down_rate; 238 239 up = DIV_ROUND_UP_ULL((u64)parent_rate, rate); 240 down = parent_rate / rate; 241 242 if (flags & CLK_DIVIDER_POWER_OF_TWO) { 243 up = __roundup_pow_of_two(up); 244 down = __rounddown_pow_of_two(down); 245 } else if (table) { 246 up = _round_up_table(table, up); 247 down = _round_down_table(table, down); 248 } 249 250 up_rate = DIV_ROUND_UP_ULL((u64)parent_rate, up); 251 down_rate = DIV_ROUND_UP_ULL((u64)parent_rate, down); 252 253 return (rate - up_rate) <= (down_rate - rate) ? up : down; 254} 255 256static int _div_round(const struct clk_div_table *table, 257 unsigned long parent_rate, unsigned long rate, 258 unsigned long flags) 259{ 260 if (flags & CLK_DIVIDER_ROUND_CLOSEST) 261 return _div_round_closest(table, parent_rate, rate, flags); 262 263 return _div_round_up(table, parent_rate, rate, flags); 264} 265 266static bool _is_best_div(unsigned long rate, unsigned long now, 267 unsigned long best, unsigned long flags) 268{ 269 if (flags & CLK_DIVIDER_ROUND_CLOSEST) 270 return abs(rate - now) < abs(rate - best); 271 272 return now <= rate && now > best; 273} 274 275static int _next_div(const struct clk_div_table *table, int div, 276 unsigned long flags) 277{ 278 div++; 279 280 if (flags & CLK_DIVIDER_POWER_OF_TWO) 281 return __roundup_pow_of_two(div); 282 if (table) 283 return _round_up_table(table, div); 284 285 return div; 286} 287 288static int clk_divider_bestdiv(struct clk_hw *hw, struct clk_hw *parent, 289 unsigned long rate, 290 unsigned long *best_parent_rate, 291 const struct clk_div_table *table, u8 width, 292 unsigned long flags) 293{ 294 int i, bestdiv = 0; 295 unsigned long parent_rate, best = 0, now, maxdiv; 296 unsigned long parent_rate_saved = *best_parent_rate; 297 298 if (!rate) 299 rate = 1; 300 301 maxdiv = _get_maxdiv(table, width, flags); 302 303 if (!(clk_hw_get_flags(hw) & CLK_SET_RATE_PARENT)) { 304 parent_rate = *best_parent_rate; 305 bestdiv = _div_round(table, parent_rate, rate, flags); 306 bestdiv = bestdiv == 0 ? 1 : bestdiv; 307 bestdiv = bestdiv > maxdiv ? maxdiv : bestdiv; 308 return bestdiv; 309 } 310 311 /* 312 * The maximum divider we can use without overflowing 313 * unsigned long in rate * i below 314 */ 315 maxdiv = min(ULONG_MAX / rate, maxdiv); 316 317 for (i = _next_div(table, 0, flags); i <= maxdiv; 318 i = _next_div(table, i, flags)) { 319 if (rate * i == parent_rate_saved) { 320 /* 321 * It's the most ideal case if the requested rate can be 322 * divided from parent clock without needing to change 323 * parent rate, so return the divider immediately. 324 */ 325 *best_parent_rate = parent_rate_saved; 326 return i; 327 } 328 parent_rate = clk_hw_round_rate(parent, rate * i); 329 now = DIV_ROUND_UP_ULL((u64)parent_rate, i); 330 if (_is_best_div(rate, now, best, flags)) { 331 bestdiv = i; 332 best = now; 333 *best_parent_rate = parent_rate; 334 } 335 } 336 337 if (!bestdiv) { 338 bestdiv = _get_maxdiv(table, width, flags); 339 *best_parent_rate = clk_hw_round_rate(parent, 1); 340 } 341 342 return bestdiv; 343} 344 345long divider_round_rate_parent(struct clk_hw *hw, struct clk_hw *parent, 346 unsigned long rate, unsigned long *prate, 347 const struct clk_div_table *table, 348 u8 width, unsigned long flags) 349{ 350 int div; 351 352 div = clk_divider_bestdiv(hw, parent, rate, prate, table, width, flags); 353 354 return DIV_ROUND_UP_ULL((u64)*prate, div); 355} 356EXPORT_SYMBOL_GPL(divider_round_rate_parent); 357 358long divider_ro_round_rate_parent(struct clk_hw *hw, struct clk_hw *parent, 359 unsigned long rate, unsigned long *prate, 360 const struct clk_div_table *table, u8 width, 361 unsigned long flags, unsigned int val) 362{ 363 int div; 364 365 div = _get_div(table, val, flags, width); 366 367 /* Even a read-only clock can propagate a rate change */ 368 if (clk_hw_get_flags(hw) & CLK_SET_RATE_PARENT) { 369 if (!parent) 370 return -EINVAL; 371 372 *prate = clk_hw_round_rate(parent, rate * div); 373 } 374 375 return DIV_ROUND_UP_ULL((u64)*prate, div); 376} 377EXPORT_SYMBOL_GPL(divider_ro_round_rate_parent); 378 379 380static long clk_divider_round_rate(struct clk_hw *hw, unsigned long rate, 381 unsigned long *prate) 382{ 383 struct clk_divider *divider = to_clk_divider(hw); 384 385 /* if read only, just return current value */ 386 if (divider->flags & CLK_DIVIDER_READ_ONLY) { 387 u32 val; 388 389 val = clk_div_readl(divider) >> divider->shift; 390 val &= clk_div_mask(divider->width); 391 392 return divider_ro_round_rate(hw, rate, prate, divider->table, 393 divider->width, divider->flags, 394 val); 395 } 396 397 return divider_round_rate(hw, rate, prate, divider->table, 398 divider->width, divider->flags); 399} 400 401int divider_get_val(unsigned long rate, unsigned long parent_rate, 402 const struct clk_div_table *table, u8 width, 403 unsigned long flags) 404{ 405 unsigned int div, value; 406 407 div = DIV_ROUND_UP_ULL((u64)parent_rate, rate); 408 409 if (!_is_valid_div(table, div, flags)) 410 return -EINVAL; 411 412 value = _get_val(table, div, flags, width); 413 414 return min_t(unsigned int, value, clk_div_mask(width)); 415} 416EXPORT_SYMBOL_GPL(divider_get_val); 417 418static int clk_divider_set_rate(struct clk_hw *hw, unsigned long rate, 419 unsigned long parent_rate) 420{ 421 struct clk_divider *divider = to_clk_divider(hw); 422 int value; 423 unsigned long flags = 0; 424 u32 val; 425 426 value = divider_get_val(rate, parent_rate, divider->table, 427 divider->width, divider->flags); 428 if (value < 0) 429 return value; 430 431 if (divider->lock) 432 spin_lock_irqsave(divider->lock, flags); 433 else 434 __acquire(divider->lock); 435 436 if (divider->flags & CLK_DIVIDER_HIWORD_MASK) { 437 val = clk_div_mask(divider->width) << (divider->shift + 16); 438 } else { 439 val = clk_div_readl(divider); 440 val &= ~(clk_div_mask(divider->width) << divider->shift); 441 } 442 val |= (u32)value << divider->shift; 443 clk_div_writel(divider, val); 444 445 if (divider->lock) 446 spin_unlock_irqrestore(divider->lock, flags); 447 else 448 __release(divider->lock); 449 450 return 0; 451} 452 453const struct clk_ops clk_divider_ops = { 454 .recalc_rate = clk_divider_recalc_rate, 455 .round_rate = clk_divider_round_rate, 456 .set_rate = clk_divider_set_rate, 457}; 458EXPORT_SYMBOL_GPL(clk_divider_ops); 459 460const struct clk_ops clk_divider_ro_ops = { 461 .recalc_rate = clk_divider_recalc_rate, 462 .round_rate = clk_divider_round_rate, 463}; 464EXPORT_SYMBOL_GPL(clk_divider_ro_ops); 465 466static struct clk_hw *_register_divider(struct device *dev, const char *name, 467 const char *parent_name, unsigned long flags, 468 void __iomem *reg, u8 shift, u8 width, 469 u8 clk_divider_flags, const struct clk_div_table *table, 470 spinlock_t *lock) 471{ 472 struct clk_divider *div; 473 struct clk_hw *hw; 474 struct clk_init_data init; 475 int ret; 476 477 if (clk_divider_flags & CLK_DIVIDER_HIWORD_MASK) { 478 if (width + shift > 16) { 479 pr_warn("divider value exceeds LOWORD field\n"); 480 return ERR_PTR(-EINVAL); 481 } 482 } 483 484 /* allocate the divider */ 485 div = kzalloc(sizeof(*div), GFP_KERNEL); 486 if (!div) 487 return ERR_PTR(-ENOMEM); 488 489 init.name = name; 490 if (clk_divider_flags & CLK_DIVIDER_READ_ONLY) 491 init.ops = &clk_divider_ro_ops; 492 else 493 init.ops = &clk_divider_ops; 494 init.flags = flags; 495 init.parent_names = (parent_name ? &parent_name: NULL); 496 init.num_parents = (parent_name ? 1 : 0); 497 498 /* struct clk_divider assignments */ 499 div->reg = reg; 500 div->shift = shift; 501 div->width = width; 502 div->flags = clk_divider_flags; 503 div->lock = lock; 504 div->hw.init = &init; 505 div->table = table; 506 507 /* register the clock */ 508 hw = &div->hw; 509 ret = clk_hw_register(dev, hw); 510 if (ret) { 511 kfree(div); 512 hw = ERR_PTR(ret); 513 } 514 515 return hw; 516} 517 518/** 519 * clk_register_divider - register a divider clock with the clock framework 520 * @dev: device registering this clock 521 * @name: name of this clock 522 * @parent_name: name of clock's parent 523 * @flags: framework-specific flags 524 * @reg: register address to adjust divider 525 * @shift: number of bits to shift the bitfield 526 * @width: width of the bitfield 527 * @clk_divider_flags: divider-specific flags for this clock 528 * @lock: shared register lock for this clock 529 */ 530struct clk *clk_register_divider(struct device *dev, const char *name, 531 const char *parent_name, unsigned long flags, 532 void __iomem *reg, u8 shift, u8 width, 533 u8 clk_divider_flags, spinlock_t *lock) 534{ 535 struct clk_hw *hw; 536 537 hw = _register_divider(dev, name, parent_name, flags, reg, shift, 538 width, clk_divider_flags, NULL, lock); 539 if (IS_ERR(hw)) 540 return ERR_CAST(hw); 541 return hw->clk; 542} 543EXPORT_SYMBOL_GPL(clk_register_divider); 544 545/** 546 * clk_hw_register_divider - register a divider clock with the clock framework 547 * @dev: device registering this clock 548 * @name: name of this clock 549 * @parent_name: name of clock's parent 550 * @flags: framework-specific flags 551 * @reg: register address to adjust divider 552 * @shift: number of bits to shift the bitfield 553 * @width: width of the bitfield 554 * @clk_divider_flags: divider-specific flags for this clock 555 * @lock: shared register lock for this clock 556 */ 557struct clk_hw *clk_hw_register_divider(struct device *dev, const char *name, 558 const char *parent_name, unsigned long flags, 559 void __iomem *reg, u8 shift, u8 width, 560 u8 clk_divider_flags, spinlock_t *lock) 561{ 562 return _register_divider(dev, name, parent_name, flags, reg, shift, 563 width, clk_divider_flags, NULL, lock); 564} 565EXPORT_SYMBOL_GPL(clk_hw_register_divider); 566 567/** 568 * clk_register_divider_table - register a table based divider clock with 569 * the clock framework 570 * @dev: device registering this clock 571 * @name: name of this clock 572 * @parent_name: name of clock's parent 573 * @flags: framework-specific flags 574 * @reg: register address to adjust divider 575 * @shift: number of bits to shift the bitfield 576 * @width: width of the bitfield 577 * @clk_divider_flags: divider-specific flags for this clock 578 * @table: array of divider/value pairs ending with a div set to 0 579 * @lock: shared register lock for this clock 580 */ 581struct clk *clk_register_divider_table(struct device *dev, const char *name, 582 const char *parent_name, unsigned long flags, 583 void __iomem *reg, u8 shift, u8 width, 584 u8 clk_divider_flags, const struct clk_div_table *table, 585 spinlock_t *lock) 586{ 587 struct clk_hw *hw; 588 589 hw = _register_divider(dev, name, parent_name, flags, reg, shift, 590 width, clk_divider_flags, table, lock); 591 if (IS_ERR(hw)) 592 return ERR_CAST(hw); 593 return hw->clk; 594} 595EXPORT_SYMBOL_GPL(clk_register_divider_table); 596 597/** 598 * clk_hw_register_divider_table - register a table based divider clock with 599 * the clock framework 600 * @dev: device registering this clock 601 * @name: name of this clock 602 * @parent_name: name of clock's parent 603 * @flags: framework-specific flags 604 * @reg: register address to adjust divider 605 * @shift: number of bits to shift the bitfield 606 * @width: width of the bitfield 607 * @clk_divider_flags: divider-specific flags for this clock 608 * @table: array of divider/value pairs ending with a div set to 0 609 * @lock: shared register lock for this clock 610 */ 611struct clk_hw *clk_hw_register_divider_table(struct device *dev, 612 const char *name, const char *parent_name, unsigned long flags, 613 void __iomem *reg, u8 shift, u8 width, 614 u8 clk_divider_flags, const struct clk_div_table *table, 615 spinlock_t *lock) 616{ 617 return _register_divider(dev, name, parent_name, flags, reg, shift, 618 width, clk_divider_flags, table, lock); 619} 620EXPORT_SYMBOL_GPL(clk_hw_register_divider_table); 621 622void clk_unregister_divider(struct clk *clk) 623{ 624 struct clk_divider *div; 625 struct clk_hw *hw; 626 627 hw = __clk_get_hw(clk); 628 if (!hw) 629 return; 630 631 div = to_clk_divider(hw); 632 633 clk_unregister(clk); 634 kfree(div); 635} 636EXPORT_SYMBOL_GPL(clk_unregister_divider); 637 638/** 639 * clk_hw_unregister_divider - unregister a clk divider 640 * @hw: hardware-specific clock data to unregister 641 */ 642void clk_hw_unregister_divider(struct clk_hw *hw) 643{ 644 struct clk_divider *div; 645 646 div = to_clk_divider(hw); 647 648 clk_hw_unregister(hw); 649 kfree(div); 650} 651EXPORT_SYMBOL_GPL(clk_hw_unregister_divider);