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.c35
1 files changed, 24 insertions, 11 deletions
diff --git a/drivers/clk/clk-divider.c b/drivers/clk/clk-divider.c
index 7b1bdde1ce..d9d3407e75 100644
--- a/drivers/clk/clk-divider.c
+++ b/drivers/clk/clk-divider.c
@@ -203,8 +203,12 @@ static int clk_divider_bestdiv(struct clk *clk, unsigned long rate,
static long clk_divider_round_rate(struct clk *clk, unsigned long rate,
unsigned long *parent_rate)
{
+ struct clk_divider *divider = container_of(clk, struct clk_divider, clk);
int div;
+ if (divider->flags & CLK_DIVIDER_READ_ONLY)
+ return clk_divider_recalc_rate(clk, *parent_rate);
+
div = clk_divider_bestdiv(clk, rate, parent_rate);
return *parent_rate / div;
@@ -217,6 +221,9 @@ static int clk_divider_set_rate(struct clk *clk, unsigned long rate,
unsigned int div, value;
u32 val;
+ if (divider->flags & CLK_DIVIDER_READ_ONLY)
+ return 0;
+
if (clk->flags & CLK_SET_RATE_PARENT) {
unsigned long best_parent_rate = parent_rate;
div = clk_divider_bestdiv(clk, rate, &best_parent_rate);
@@ -249,7 +256,8 @@ struct clk_ops clk_divider_ops = {
};
struct clk *clk_divider_alloc(const char *name, const char *parent,
- void __iomem *reg, u8 shift, u8 width, unsigned flags)
+ unsigned clk_flags, void __iomem *reg, u8 shift,
+ u8 width, unsigned div_flags)
{
struct clk_divider *div = xzalloc(sizeof(*div));
@@ -257,9 +265,10 @@ struct clk *clk_divider_alloc(const char *name, const char *parent,
div->reg = reg;
div->width = width;
div->parent = parent;
+ div->flags = div_flags;
div->clk.ops = &clk_divider_ops;
div->clk.name = name;
- div->clk.flags = flags;
+ div->clk.flags = clk_flags;
div->clk.parent_names = &div->parent;
div->clk.num_parents = 1;
@@ -273,13 +282,14 @@ void clk_divider_free(struct clk *clk)
free(d);
}
-struct clk *clk_divider(const char *name, const char *parent,
- void __iomem *reg, u8 shift, u8 width, unsigned flags)
+struct clk *clk_divider(const char *name, const char *parent, unsigned clk_flags,
+ void __iomem *reg, u8 shift, u8 width, unsigned div_flags)
{
struct clk *d;
int ret;
- d = clk_divider_alloc(name , parent, reg, shift, width, flags);
+ d = clk_divider_alloc(name , parent, clk_flags, reg, shift, width,
+ div_flags);
ret = clk_register(d);
if (ret) {
@@ -291,12 +301,13 @@ struct clk *clk_divider(const char *name, const char *parent,
}
struct clk *clk_divider_one_based(const char *name, const char *parent,
- void __iomem *reg, u8 shift, u8 width, unsigned flags)
+ unsigned clk_flags, void __iomem *reg, u8 shift,
+ u8 width, unsigned div_flags)
{
struct clk_divider *div;
struct clk *clk;
- clk = clk_divider(name, parent, reg, shift, width, flags);
+ clk = clk_divider(name, parent, clk_flags, reg, shift, width, div_flags);
if (IS_ERR(clk))
return clk;
@@ -306,9 +317,10 @@ struct clk *clk_divider_one_based(const char *name, const char *parent,
return clk;
}
-struct clk *clk_divider_table(const char *name,
- const char *parent, void __iomem *reg, u8 shift, u8 width,
- const struct clk_div_table *table, unsigned flags)
+struct clk *clk_divider_table(const char *name, const char *parent,
+ unsigned clk_flags, void __iomem *reg, u8 shift,
+ u8 width, const struct clk_div_table *table,
+ unsigned div_flags)
{
struct clk_divider *div = xzalloc(sizeof(*div));
const struct clk_div_table *clkt;
@@ -318,9 +330,10 @@ struct clk *clk_divider_table(const char *name,
div->reg = reg;
div->width = width;
div->parent = parent;
+ div->flags = div_flags;
div->clk.ops = &clk_divider_ops;
div->clk.name = name;
- div->clk.flags = flags;
+ div->clk.flags = clk_flags;
div->clk.parent_names = &div->parent;
div->clk.num_parents = 1;
div->table = table;