| .. | .. |
|---|
| 1 | +// SPDX-License-Identifier: GPL-2.0 |
|---|
| 1 | 2 | /* |
|---|
| 2 | 3 | * Copyright (C) 2011 Sascha Hauer, Pengutronix <s.hauer@pengutronix.de> |
|---|
| 3 | 4 | * Copyright (C) 2011 Richard Zhao, Linaro <richard.zhao@linaro.org> |
|---|
| 4 | 5 | * Copyright (C) 2011-2012 Mike Turquette, Linaro Ltd <mturquette@linaro.org> |
|---|
| 5 | | - * |
|---|
| 6 | | - * This program is free software; you can redistribute it and/or modify |
|---|
| 7 | | - * it under the terms of the GNU General Public License version 2 as |
|---|
| 8 | | - * published by the Free Software Foundation. |
|---|
| 9 | 6 | * |
|---|
| 10 | 7 | * Adjustable divider clock implementation |
|---|
| 11 | 8 | */ |
|---|
| .. | .. |
|---|
| 27 | 24 | * rate - rate is adjustable. clk->rate = ceiling(parent->rate / divisor) |
|---|
| 28 | 25 | * parent - fixed parent. No clk_set_parent support |
|---|
| 29 | 26 | */ |
|---|
| 27 | + |
|---|
| 28 | +static 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 | + |
|---|
| 36 | +static 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 | +} |
|---|
| 30 | 43 | |
|---|
| 31 | 44 | static unsigned int _get_table_maxdiv(const struct clk_div_table *table, |
|---|
| 32 | 45 | u8 width) |
|---|
| .. | .. |
|---|
| 138 | 151 | struct clk_divider *divider = to_clk_divider(hw); |
|---|
| 139 | 152 | unsigned int val; |
|---|
| 140 | 153 | |
|---|
| 141 | | - val = clk_readl(divider->reg) >> divider->shift; |
|---|
| 154 | + val = clk_div_readl(divider) >> divider->shift; |
|---|
| 142 | 155 | val &= clk_div_mask(divider->width); |
|---|
| 143 | 156 | |
|---|
| 144 | 157 | return divider_recalc_rate(hw, parent_rate, val, divider->table, |
|---|
| .. | .. |
|---|
| 373 | 386 | if (divider->flags & CLK_DIVIDER_READ_ONLY) { |
|---|
| 374 | 387 | u32 val; |
|---|
| 375 | 388 | |
|---|
| 376 | | - val = clk_readl(divider->reg) >> divider->shift; |
|---|
| 389 | + val = clk_div_readl(divider) >> divider->shift; |
|---|
| 377 | 390 | val &= clk_div_mask(divider->width); |
|---|
| 378 | 391 | |
|---|
| 379 | 392 | return divider_ro_round_rate(hw, rate, prate, divider->table, |
|---|
| .. | .. |
|---|
| 423 | 436 | if (divider->flags & CLK_DIVIDER_HIWORD_MASK) { |
|---|
| 424 | 437 | val = clk_div_mask(divider->width) << (divider->shift + 16); |
|---|
| 425 | 438 | } else { |
|---|
| 426 | | - val = clk_readl(divider->reg); |
|---|
| 439 | + val = clk_div_readl(divider); |
|---|
| 427 | 440 | val &= ~(clk_div_mask(divider->width) << divider->shift); |
|---|
| 428 | 441 | } |
|---|
| 429 | 442 | val |= (u32)value << divider->shift; |
|---|
| 430 | | - clk_writel(val, divider->reg); |
|---|
| 443 | + clk_div_writel(divider, val); |
|---|
| 431 | 444 | |
|---|
| 432 | 445 | if (divider->lock) |
|---|
| 433 | 446 | spin_unlock_irqrestore(divider->lock, flags); |
|---|
| .. | .. |
|---|
| 450 | 463 | }; |
|---|
| 451 | 464 | EXPORT_SYMBOL_GPL(clk_divider_ro_ops); |
|---|
| 452 | 465 | |
|---|
| 453 | | -static struct clk_hw *_register_divider(struct device *dev, const char *name, |
|---|
| 454 | | - const char *parent_name, unsigned long flags, |
|---|
| 455 | | - void __iomem *reg, u8 shift, u8 width, |
|---|
| 456 | | - u8 clk_divider_flags, const struct clk_div_table *table, |
|---|
| 457 | | - spinlock_t *lock) |
|---|
| 466 | +struct clk_hw *__clk_hw_register_divider(struct device *dev, |
|---|
| 467 | + struct device_node *np, const char *name, |
|---|
| 468 | + const char *parent_name, const struct clk_hw *parent_hw, |
|---|
| 469 | + const struct clk_parent_data *parent_data, unsigned long flags, |
|---|
| 470 | + void __iomem *reg, u8 shift, u8 width, u8 clk_divider_flags, |
|---|
| 471 | + const struct clk_div_table *table, spinlock_t *lock) |
|---|
| 458 | 472 | { |
|---|
| 459 | 473 | struct clk_divider *div; |
|---|
| 460 | 474 | struct clk_hw *hw; |
|---|
| .. | .. |
|---|
| 478 | 492 | init.ops = &clk_divider_ro_ops; |
|---|
| 479 | 493 | else |
|---|
| 480 | 494 | init.ops = &clk_divider_ops; |
|---|
| 481 | | - init.flags = flags | CLK_IS_BASIC; |
|---|
| 482 | | - init.parent_names = (parent_name ? &parent_name: NULL); |
|---|
| 483 | | - init.num_parents = (parent_name ? 1 : 0); |
|---|
| 495 | + init.flags = flags; |
|---|
| 496 | + init.parent_names = parent_name ? &parent_name : NULL; |
|---|
| 497 | + init.parent_hws = parent_hw ? &parent_hw : NULL; |
|---|
| 498 | + init.parent_data = parent_data; |
|---|
| 499 | + if (parent_name || parent_hw || parent_data) |
|---|
| 500 | + init.num_parents = 1; |
|---|
| 501 | + else |
|---|
| 502 | + init.num_parents = 0; |
|---|
| 484 | 503 | |
|---|
| 485 | 504 | /* struct clk_divider assignments */ |
|---|
| 486 | 505 | div->reg = reg; |
|---|
| .. | .. |
|---|
| 501 | 520 | |
|---|
| 502 | 521 | return hw; |
|---|
| 503 | 522 | } |
|---|
| 504 | | - |
|---|
| 505 | | -/** |
|---|
| 506 | | - * clk_register_divider - register a divider clock with the clock framework |
|---|
| 507 | | - * @dev: device registering this clock |
|---|
| 508 | | - * @name: name of this clock |
|---|
| 509 | | - * @parent_name: name of clock's parent |
|---|
| 510 | | - * @flags: framework-specific flags |
|---|
| 511 | | - * @reg: register address to adjust divider |
|---|
| 512 | | - * @shift: number of bits to shift the bitfield |
|---|
| 513 | | - * @width: width of the bitfield |
|---|
| 514 | | - * @clk_divider_flags: divider-specific flags for this clock |
|---|
| 515 | | - * @lock: shared register lock for this clock |
|---|
| 516 | | - */ |
|---|
| 517 | | -struct clk *clk_register_divider(struct device *dev, const char *name, |
|---|
| 518 | | - const char *parent_name, unsigned long flags, |
|---|
| 519 | | - void __iomem *reg, u8 shift, u8 width, |
|---|
| 520 | | - u8 clk_divider_flags, spinlock_t *lock) |
|---|
| 521 | | -{ |
|---|
| 522 | | - struct clk_hw *hw; |
|---|
| 523 | | - |
|---|
| 524 | | - hw = _register_divider(dev, name, parent_name, flags, reg, shift, |
|---|
| 525 | | - width, clk_divider_flags, NULL, lock); |
|---|
| 526 | | - if (IS_ERR(hw)) |
|---|
| 527 | | - return ERR_CAST(hw); |
|---|
| 528 | | - return hw->clk; |
|---|
| 529 | | -} |
|---|
| 530 | | -EXPORT_SYMBOL_GPL(clk_register_divider); |
|---|
| 531 | | - |
|---|
| 532 | | -/** |
|---|
| 533 | | - * clk_hw_register_divider - register a divider clock with the clock framework |
|---|
| 534 | | - * @dev: device registering this clock |
|---|
| 535 | | - * @name: name of this clock |
|---|
| 536 | | - * @parent_name: name of clock's parent |
|---|
| 537 | | - * @flags: framework-specific flags |
|---|
| 538 | | - * @reg: register address to adjust divider |
|---|
| 539 | | - * @shift: number of bits to shift the bitfield |
|---|
| 540 | | - * @width: width of the bitfield |
|---|
| 541 | | - * @clk_divider_flags: divider-specific flags for this clock |
|---|
| 542 | | - * @lock: shared register lock for this clock |
|---|
| 543 | | - */ |
|---|
| 544 | | -struct clk_hw *clk_hw_register_divider(struct device *dev, const char *name, |
|---|
| 545 | | - const char *parent_name, unsigned long flags, |
|---|
| 546 | | - void __iomem *reg, u8 shift, u8 width, |
|---|
| 547 | | - u8 clk_divider_flags, spinlock_t *lock) |
|---|
| 548 | | -{ |
|---|
| 549 | | - return _register_divider(dev, name, parent_name, flags, reg, shift, |
|---|
| 550 | | - width, clk_divider_flags, NULL, lock); |
|---|
| 551 | | -} |
|---|
| 552 | | -EXPORT_SYMBOL_GPL(clk_hw_register_divider); |
|---|
| 523 | +EXPORT_SYMBOL_GPL(__clk_hw_register_divider); |
|---|
| 553 | 524 | |
|---|
| 554 | 525 | /** |
|---|
| 555 | 526 | * clk_register_divider_table - register a table based divider clock with |
|---|
| .. | .. |
|---|
| 573 | 544 | { |
|---|
| 574 | 545 | struct clk_hw *hw; |
|---|
| 575 | 546 | |
|---|
| 576 | | - hw = _register_divider(dev, name, parent_name, flags, reg, shift, |
|---|
| 577 | | - width, clk_divider_flags, table, lock); |
|---|
| 547 | + hw = __clk_hw_register_divider(dev, NULL, name, parent_name, NULL, |
|---|
| 548 | + NULL, flags, reg, shift, width, clk_divider_flags, |
|---|
| 549 | + table, lock); |
|---|
| 578 | 550 | if (IS_ERR(hw)) |
|---|
| 579 | 551 | return ERR_CAST(hw); |
|---|
| 580 | 552 | return hw->clk; |
|---|
| 581 | 553 | } |
|---|
| 582 | 554 | EXPORT_SYMBOL_GPL(clk_register_divider_table); |
|---|
| 583 | | - |
|---|
| 584 | | -/** |
|---|
| 585 | | - * clk_hw_register_divider_table - register a table based divider clock with |
|---|
| 586 | | - * the clock framework |
|---|
| 587 | | - * @dev: device registering this clock |
|---|
| 588 | | - * @name: name of this clock |
|---|
| 589 | | - * @parent_name: name of clock's parent |
|---|
| 590 | | - * @flags: framework-specific flags |
|---|
| 591 | | - * @reg: register address to adjust divider |
|---|
| 592 | | - * @shift: number of bits to shift the bitfield |
|---|
| 593 | | - * @width: width of the bitfield |
|---|
| 594 | | - * @clk_divider_flags: divider-specific flags for this clock |
|---|
| 595 | | - * @table: array of divider/value pairs ending with a div set to 0 |
|---|
| 596 | | - * @lock: shared register lock for this clock |
|---|
| 597 | | - */ |
|---|
| 598 | | -struct clk_hw *clk_hw_register_divider_table(struct device *dev, |
|---|
| 599 | | - const char *name, const char *parent_name, unsigned long flags, |
|---|
| 600 | | - void __iomem *reg, u8 shift, u8 width, |
|---|
| 601 | | - u8 clk_divider_flags, const struct clk_div_table *table, |
|---|
| 602 | | - spinlock_t *lock) |
|---|
| 603 | | -{ |
|---|
| 604 | | - return _register_divider(dev, name, parent_name, flags, reg, shift, |
|---|
| 605 | | - width, clk_divider_flags, table, lock); |
|---|
| 606 | | -} |
|---|
| 607 | | -EXPORT_SYMBOL_GPL(clk_hw_register_divider_table); |
|---|
| 608 | 555 | |
|---|
| 609 | 556 | void clk_unregister_divider(struct clk *clk) |
|---|
| 610 | 557 | { |
|---|