Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux

clk: Add __clk_mux_determine_rate_closest

Some clock drivers want to find the closest rate on the input of
a mux instead of a rate that's less than or equal to the desired
rate. Add a generic mux function to support this.

Signed-off-by: Stephen Boyd <sboyd@codeaurora.org>
Tested-by: Kenneth Westfield <kwestfie@codeaurora.org>
Signed-off-by: Michael Turquette <mturquette@linaro.org>

authored by

Stephen Boyd and committed by
Michael Turquette
15a02c1f 52bba980

+45 -10
+38 -9
drivers/clk/clk.c
··· 690 690 return NULL; 691 691 } 692 692 693 - /* 694 - * Helper for finding best parent to provide a given frequency. This can be used 695 - * directly as a determine_rate callback (e.g. for a mux), or from a more 696 - * complex clock that may combine a mux with other operations. 697 - */ 698 - long __clk_mux_determine_rate(struct clk_hw *hw, unsigned long rate, 699 - unsigned long *best_parent_rate, 700 - struct clk_hw **best_parent_p) 693 + static bool mux_is_better_rate(unsigned long rate, unsigned long now, 694 + unsigned long best, unsigned long flags) 695 + { 696 + if (flags & CLK_MUX_ROUND_CLOSEST) 697 + return abs(now - rate) < abs(best - rate); 698 + 699 + return now <= rate && now > best; 700 + } 701 + 702 + static long 703 + clk_mux_determine_rate_flags(struct clk_hw *hw, unsigned long rate, 704 + unsigned long *best_parent_rate, 705 + struct clk_hw **best_parent_p, 706 + unsigned long flags) 701 707 { 702 708 struct clk *clk = hw->clk, *parent, *best_parent = NULL; 703 709 int i, num_parents; ··· 731 725 parent_rate = __clk_round_rate(parent, rate); 732 726 else 733 727 parent_rate = __clk_get_rate(parent); 734 - if (parent_rate <= rate && parent_rate > best) { 728 + if (mux_is_better_rate(rate, parent_rate, best, flags)) { 735 729 best_parent = parent; 736 730 best = parent_rate; 737 731 } ··· 744 738 745 739 return best; 746 740 } 741 + 742 + /* 743 + * Helper for finding best parent to provide a given frequency. This can be used 744 + * directly as a determine_rate callback (e.g. for a mux), or from a more 745 + * complex clock that may combine a mux with other operations. 746 + */ 747 + long __clk_mux_determine_rate(struct clk_hw *hw, unsigned long rate, 748 + unsigned long *best_parent_rate, 749 + struct clk_hw **best_parent_p) 750 + { 751 + return clk_mux_determine_rate_flags(hw, rate, best_parent_rate, 752 + best_parent_p, 0); 753 + } 747 754 EXPORT_SYMBOL_GPL(__clk_mux_determine_rate); 755 + 756 + long __clk_mux_determine_rate_closest(struct clk_hw *hw, unsigned long rate, 757 + unsigned long *best_parent_rate, 758 + struct clk_hw **best_parent_p) 759 + { 760 + return clk_mux_determine_rate_flags(hw, rate, best_parent_rate, 761 + best_parent_p, 762 + CLK_MUX_ROUND_CLOSEST); 763 + } 764 + EXPORT_SYMBOL_GPL(__clk_mux_determine_rate_closest); 748 765 749 766 /*** clk api ***/ 750 767
+7 -1
include/linux/clk-provider.h
··· 384 384 * register, and mask of mux bits are in higher 16-bit of this register. 385 385 * While setting the mux bits, higher 16-bit should also be updated to 386 386 * indicate changing mux bits. 387 + * CLK_MUX_ROUND_CLOSEST - Use the parent rate that is closest to the desired 388 + * frequency. 387 389 */ 388 390 struct clk_mux { 389 391 struct clk_hw hw; ··· 400 398 #define CLK_MUX_INDEX_ONE BIT(0) 401 399 #define CLK_MUX_INDEX_BIT BIT(1) 402 400 #define CLK_MUX_HIWORD_MASK BIT(2) 403 - #define CLK_MUX_READ_ONLY BIT(3) /* mux setting cannot be changed */ 401 + #define CLK_MUX_READ_ONLY BIT(3) /* mux can't be changed */ 402 + #define CLK_MUX_ROUND_CLOSEST BIT(4) 404 403 405 404 extern const struct clk_ops clk_mux_ops; 406 405 extern const struct clk_ops clk_mux_ro_ops; ··· 557 554 bool __clk_is_enabled(struct clk *clk); 558 555 struct clk *__clk_lookup(const char *name); 559 556 long __clk_mux_determine_rate(struct clk_hw *hw, unsigned long rate, 557 + unsigned long *best_parent_rate, 558 + struct clk_hw **best_parent_p); 559 + long __clk_mux_determine_rate_closest(struct clk_hw *hw, unsigned long rate, 560 560 unsigned long *best_parent_rate, 561 561 struct clk_hw **best_parent_p); 562 562