summaryrefslogtreecommitdiff
path: root/drivers/clk/mediatek/clk-mux.c
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/clk/mediatek/clk-mux.c')
-rw-r--r--drivers/clk/mediatek/clk-mux.c89
1 files changed, 29 insertions, 60 deletions
diff --git a/drivers/clk/mediatek/clk-mux.c b/drivers/clk/mediatek/clk-mux.c
index dcc1352bf13c..b0c61709bacc 100644
--- a/drivers/clk/mediatek/clk-mux.c
+++ b/drivers/clk/mediatek/clk-mux.c
@@ -17,29 +17,36 @@ static inline struct mtk_clk_mux *to_mtk_clk_mux(struct clk_hw *hw)
return container_of(hw, struct mtk_clk_mux, hw);
}
-static int mtk_clk_mux_enable(struct clk_hw *hw)
+static int mtk_clk_mux_enable_setclr(struct clk_hw *hw)
{
struct mtk_clk_mux *mux = to_mtk_clk_mux(hw);
- u32 mask = BIT(mux->data->gate_shift);
-
- return regmap_update_bits(mux->regmap, mux->data->mux_ofs,
- mask, ~mask);
-}
+ unsigned long flags = 0;
-static void mtk_clk_mux_disable(struct clk_hw *hw)
-{
- struct mtk_clk_mux *mux = to_mtk_clk_mux(hw);
- u32 mask = BIT(mux->data->gate_shift);
+ if (mux->lock)
+ spin_lock_irqsave(mux->lock, flags);
+ else
+ __acquire(mux->lock);
- regmap_update_bits(mux->regmap, mux->data->mux_ofs, mask, mask);
-}
+ regmap_write(mux->regmap, mux->data->clr_ofs,
+ BIT(mux->data->gate_shift));
+
+ /*
+ * If the parent has been changed when the clock was disabled, it will
+ * not be effective yet. Set the update bit to ensure the mux gets
+ * updated.
+ */
+ if (mux->reparent && mux->data->upd_shift >= 0) {
+ regmap_write(mux->regmap, mux->data->upd_ofs,
+ BIT(mux->data->upd_shift));
+ mux->reparent = false;
+ }
-static int mtk_clk_mux_enable_setclr(struct clk_hw *hw)
-{
- struct mtk_clk_mux *mux = to_mtk_clk_mux(hw);
+ if (mux->lock)
+ spin_unlock_irqrestore(mux->lock, flags);
+ else
+ __release(mux->lock);
- return regmap_write(mux->regmap, mux->data->clr_ofs,
- BIT(mux->data->gate_shift));
+ return 0;
}
static void mtk_clk_mux_disable_setclr(struct clk_hw *hw)
@@ -72,28 +79,6 @@ static u8 mtk_clk_mux_get_parent(struct clk_hw *hw)
return val;
}
-static int mtk_clk_mux_set_parent_lock(struct clk_hw *hw, u8 index)
-{
- struct mtk_clk_mux *mux = to_mtk_clk_mux(hw);
- u32 mask = GENMASK(mux->data->mux_width - 1, 0);
- unsigned long flags = 0;
-
- if (mux->lock)
- spin_lock_irqsave(mux->lock, flags);
- else
- __acquire(mux->lock);
-
- regmap_update_bits(mux->regmap, mux->data->mux_ofs, mask,
- index << mux->data->mux_shift);
-
- if (mux->lock)
- spin_unlock_irqrestore(mux->lock, flags);
- else
- __release(mux->lock);
-
- return 0;
-}
-
static int mtk_clk_mux_set_parent_setclr_lock(struct clk_hw *hw, u8 index)
{
struct mtk_clk_mux *mux = to_mtk_clk_mux(hw);
@@ -116,9 +101,11 @@ static int mtk_clk_mux_set_parent_setclr_lock(struct clk_hw *hw, u8 index)
regmap_write(mux->regmap, mux->data->set_ofs,
index << mux->data->mux_shift);
- if (mux->data->upd_shift >= 0)
+ if (mux->data->upd_shift >= 0) {
regmap_write(mux->regmap, mux->data->upd_ofs,
BIT(mux->data->upd_shift));
+ mux->reparent = true;
+ }
}
if (mux->lock)
@@ -129,25 +116,7 @@ static int mtk_clk_mux_set_parent_setclr_lock(struct clk_hw *hw, u8 index)
return 0;
}
-const struct clk_ops mtk_mux_ops = {
- .get_parent = mtk_clk_mux_get_parent,
- .set_parent = mtk_clk_mux_set_parent_lock,
-};
-
-const struct clk_ops mtk_mux_clr_set_upd_ops = {
- .get_parent = mtk_clk_mux_get_parent,
- .set_parent = mtk_clk_mux_set_parent_setclr_lock,
-};
-
-const struct clk_ops mtk_mux_gate_ops = {
- .enable = mtk_clk_mux_enable,
- .disable = mtk_clk_mux_disable,
- .is_enabled = mtk_clk_mux_is_enabled,
- .get_parent = mtk_clk_mux_get_parent,
- .set_parent = mtk_clk_mux_set_parent_lock,
-};
-
-const struct clk_ops mtk_mux_gate_clr_set_upd_ops = {
+static const struct clk_ops mtk_mux_ops = {
.enable = mtk_clk_mux_enable_setclr,
.disable = mtk_clk_mux_disable_setclr,
.is_enabled = mtk_clk_mux_is_enabled,
@@ -171,7 +140,7 @@ static struct clk *mtk_clk_register_mux(const struct mtk_mux *mux,
init.flags = mux->flags | CLK_SET_RATE_PARENT;
init.parent_names = mux->parent_names;
init.num_parents = mux->num_parents;
- init.ops = mux->ops;
+ init.ops = &mtk_mux_ops;
clk_mux->regmap = regmap;
clk_mux->data = mux;