summaryrefslogtreecommitdiffstats
path: root/drivers/clk/clk-divider.c
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/clk/clk-divider.c')
-rw-r--r--drivers/clk/clk-divider.c30
1 files changed, 22 insertions, 8 deletions
diff --git a/drivers/clk/clk-divider.c b/drivers/clk/clk-divider.c
index 791e10ea99..7b1bdde1ce 100644
--- a/drivers/clk/clk-divider.c
+++ b/drivers/clk/clk-divider.c
@@ -20,6 +20,7 @@
#include <linux/clk.h>
#include <linux/err.h>
#include <linux/log2.h>
+#include <asm-generic/div64.h>
#define div_mask(d) ((1 << ((d)->width)) - 1)
@@ -56,17 +57,17 @@ static unsigned int _get_table_div(const struct clk_div_table *table,
return 0;
}
-static unsigned int _get_div(struct clk_divider *divider, unsigned int val)
+static unsigned int _get_div(const struct clk_div_table *table,
+ unsigned int val, unsigned long flags, u8 width)
{
- if (divider->flags & CLK_DIVIDER_ONE_BASED)
+ if (flags & CLK_DIVIDER_ONE_BASED)
return val;
- if (divider->flags & CLK_DIVIDER_POWER_OF_TWO)
+ if (flags & CLK_DIVIDER_POWER_OF_TWO)
return 1 << val;
- if (divider->table)
- return _get_table_div(divider->table, val);
+ if (table)
+ return _get_table_div(table, val);
return val + 1;
}
-
static unsigned int _get_table_val(const struct clk_div_table *table,
unsigned int div)
{
@@ -89,6 +90,18 @@ static unsigned int _get_val(struct clk_divider *divider, unsigned int div)
return div - 1;
}
+unsigned long divider_recalc_rate(struct clk *clk, unsigned long parent_rate,
+ unsigned int val,
+ const struct clk_div_table *table,
+ unsigned long flags, unsigned long width)
+{
+ unsigned int div;
+
+ div = _get_div(table, val, flags, width);
+
+ return DIV_ROUND_UP_ULL((u64)parent_rate, div);
+}
+
static unsigned long clk_divider_recalc_rate(struct clk *clk,
unsigned long parent_rate)
{
@@ -98,9 +111,10 @@ static unsigned long clk_divider_recalc_rate(struct clk *clk,
val = readl(divider->reg) >> divider->shift;
val &= div_mask(divider);
- div = _get_div(divider, val);
+ div = _get_div(divider->table, val, divider->flags, divider->width);
- return parent_rate / div;
+ return divider_recalc_rate(clk, parent_rate, val, divider->table,
+ divider->flags, divider->width);
}
/*