aboutsummaryrefslogtreecommitdiff
path: root/drivers/clk/clk-mux.c
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/clk/clk-mux.c')
-rw-r--r--drivers/clk/clk-mux.c34
1 files changed, 29 insertions, 5 deletions
diff --git a/drivers/clk/clk-mux.c b/drivers/clk/clk-mux.c
index 25b1734560d..4f96ff3ba72 100644
--- a/drivers/clk/clk-mux.c
+++ b/drivers/clk/clk-mux.c
@@ -42,7 +42,7 @@ static u8 clk_mux_get_parent(struct clk_hw *hw)
* OTOH, pmd_trace_clk_mux_ck uses a separate bit for each clock, so
* val = 0x4 really means "bit 2, index starts at bit 0"
*/
- val = readl(mux->reg) >> mux->shift;
+ val = clk_readl(mux->reg) >> mux->shift;
val &= mux->mask;
if (mux->table) {
@@ -86,10 +86,14 @@ static int clk_mux_set_parent(struct clk_hw *hw, u8 index)
if (mux->lock)
spin_lock_irqsave(mux->lock, flags);
- val = readl(mux->reg);
- val &= ~(mux->mask << mux->shift);
+ if (mux->flags & CLK_MUX_HIWORD_MASK) {
+ val = mux->mask << (mux->shift + 16);
+ } else {
+ val = clk_readl(mux->reg);
+ val &= ~(mux->mask << mux->shift);
+ }
val |= index << mux->shift;
- writel(val, mux->reg);
+ clk_writel(val, mux->reg);
if (mux->lock)
spin_unlock_irqrestore(mux->lock, flags);
@@ -100,9 +104,15 @@ static int clk_mux_set_parent(struct clk_hw *hw, u8 index)
const struct clk_ops clk_mux_ops = {
.get_parent = clk_mux_get_parent,
.set_parent = clk_mux_set_parent,
+ .determine_rate = __clk_mux_determine_rate,
};
EXPORT_SYMBOL_GPL(clk_mux_ops);
+const struct clk_ops clk_mux_ro_ops = {
+ .get_parent = clk_mux_get_parent,
+};
+EXPORT_SYMBOL_GPL(clk_mux_ro_ops);
+
struct clk *clk_register_mux_table(struct device *dev, const char *name,
const char **parent_names, u8 num_parents, unsigned long flags,
void __iomem *reg, u8 shift, u32 mask,
@@ -111,6 +121,15 @@ struct clk *clk_register_mux_table(struct device *dev, const char *name,
struct clk_mux *mux;
struct clk *clk;
struct clk_init_data init;
+ u8 width = 0;
+
+ if (clk_mux_flags & CLK_MUX_HIWORD_MASK) {
+ width = fls(mask) - ffs(mask) + 1;
+ if (width + shift > 16) {
+ pr_err("mux value exceeds LOWORD field\n");
+ return ERR_PTR(-EINVAL);
+ }
+ }
/* allocate the mux */
mux = kzalloc(sizeof(struct clk_mux), GFP_KERNEL);
@@ -120,7 +139,10 @@ struct clk *clk_register_mux_table(struct device *dev, const char *name,
}
init.name = name;
- init.ops = &clk_mux_ops;
+ if (clk_mux_flags & CLK_MUX_READ_ONLY)
+ init.ops = &clk_mux_ro_ops;
+ else
+ init.ops = &clk_mux_ops;
init.flags = flags | CLK_IS_BASIC;
init.parent_names = parent_names;
init.num_parents = num_parents;
@@ -141,6 +163,7 @@ struct clk *clk_register_mux_table(struct device *dev, const char *name,
return clk;
}
+EXPORT_SYMBOL_GPL(clk_register_mux_table);
struct clk *clk_register_mux(struct device *dev, const char *name,
const char **parent_names, u8 num_parents, unsigned long flags,
@@ -153,3 +176,4 @@ struct clk *clk_register_mux(struct device *dev, const char *name,
flags, reg, shift, mask, clk_mux_flags,
NULL, lock);
}
+EXPORT_SYMBOL_GPL(clk_register_mux);