Skip to content

Commit 15a02c1

Browse files
bebarinoMichael Turquette
authored andcommitted
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>
1 parent 52bba98 commit 15a02c1

File tree

2 files changed

+45
-10
lines changed

2 files changed

+45
-10
lines changed

drivers/clk/clk.c

Lines changed: 38 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -690,14 +690,20 @@ struct clk *__clk_lookup(const char *name)
690690
return NULL;
691691
}
692692

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)
701707
{
702708
struct clk *clk = hw->clk, *parent, *best_parent = NULL;
703709
int i, num_parents;
@@ -725,7 +731,7 @@ long __clk_mux_determine_rate(struct clk_hw *hw, unsigned long rate,
725731
parent_rate = __clk_round_rate(parent, rate);
726732
else
727733
parent_rate = __clk_get_rate(parent);
728-
if (parent_rate <= rate && parent_rate > best) {
734+
if (mux_is_better_rate(rate, parent_rate, best, flags)) {
729735
best_parent = parent;
730736
best = parent_rate;
731737
}
@@ -738,8 +744,31 @@ long __clk_mux_determine_rate(struct clk_hw *hw, unsigned long rate,
738744

739745
return best;
740746
}
747+
748+
/*
749+
* Helper for finding best parent to provide a given frequency. This can be used
750+
* directly as a determine_rate callback (e.g. for a mux), or from a more
751+
* complex clock that may combine a mux with other operations.
752+
*/
753+
long __clk_mux_determine_rate(struct clk_hw *hw, unsigned long rate,
754+
unsigned long *best_parent_rate,
755+
struct clk_hw **best_parent_p)
756+
{
757+
return clk_mux_determine_rate_flags(hw, rate, best_parent_rate,
758+
best_parent_p, 0);
759+
}
741760
EXPORT_SYMBOL_GPL(__clk_mux_determine_rate);
742761

762+
long __clk_mux_determine_rate_closest(struct clk_hw *hw, unsigned long rate,
763+
unsigned long *best_parent_rate,
764+
struct clk_hw **best_parent_p)
765+
{
766+
return clk_mux_determine_rate_flags(hw, rate, best_parent_rate,
767+
best_parent_p,
768+
CLK_MUX_ROUND_CLOSEST);
769+
}
770+
EXPORT_SYMBOL_GPL(__clk_mux_determine_rate_closest);
771+
743772
/*** clk api ***/
744773

745774
void __clk_unprepare(struct clk *clk)

include/linux/clk-provider.h

Lines changed: 7 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -384,6 +384,8 @@ void clk_unregister_divider(struct clk *clk);
384384
* register, and mask of mux bits are in higher 16-bit of this register.
385385
* While setting the mux bits, higher 16-bit should also be updated to
386386
* indicate changing mux bits.
387+
* CLK_MUX_ROUND_CLOSEST - Use the parent rate that is closest to the desired
388+
* frequency.
387389
*/
388390
struct clk_mux {
389391
struct clk_hw hw;
@@ -398,7 +400,8 @@ struct clk_mux {
398400
#define CLK_MUX_INDEX_ONE BIT(0)
399401
#define CLK_MUX_INDEX_BIT BIT(1)
400402
#define CLK_MUX_HIWORD_MASK BIT(2)
401-
#define CLK_MUX_READ_ONLY BIT(3) /* mux setting cannot be changed */
403+
#define CLK_MUX_READ_ONLY BIT(3) /* mux can't be changed */
404+
#define CLK_MUX_ROUND_CLOSEST BIT(4)
402405

403406
extern const struct clk_ops clk_mux_ops;
404407
extern const struct clk_ops clk_mux_ro_ops;
@@ -556,6 +559,9 @@ struct clk *__clk_lookup(const char *name);
556559
long __clk_mux_determine_rate(struct clk_hw *hw, unsigned long rate,
557560
unsigned long *best_parent_rate,
558561
struct clk_hw **best_parent_p);
562+
long __clk_mux_determine_rate_closest(struct clk_hw *hw, unsigned long rate,
563+
unsigned long *best_parent_rate,
564+
struct clk_hw **best_parent_p);
559565

560566
/*
561567
* FIXME clock api without lock protection

0 commit comments

Comments
 (0)