diff mbox series

[2/2] clk: mediatek: mux: Update parent at enable time

Message ID 20210125170819.26130-3-laurent.pinchart@ideasonboard.com (mailing list archive)
State New, archived
Headers show
Series clk: mediatek: Fix mux clock re-parenting | expand

Commit Message

Laurent Pinchart Jan. 25, 2021, 5:08 p.m. UTC
The mux clocks don't always correctly take the new parent into account
when the parent is updated while the clock is disabled. Set the update
bit when enabling the clock to force an update of the mux.

Signed-off-by: Laurent Pinchart <laurent.pinchart@ideasonboard.com>
---
 drivers/clk/mediatek/clk-mux.c | 32 +++++++++++++++++++++++++++++---
 drivers/clk/mediatek/clk-mux.h |  1 +
 2 files changed, 30 insertions(+), 3 deletions(-)

Comments

Weiyi Lu Jan. 28, 2021, 4:04 a.m. UTC | #1
On Mon, 2021-01-25 at 19:08 +0200, Laurent Pinchart wrote:
> The mux clocks don't always correctly take the new parent into account
> when the parent is updated while the clock is disabled. Set the update
> bit when enabling the clock to force an update of the mux.
> 
> Signed-off-by: Laurent Pinchart <laurent.pinchart@ideasonboard.com>

Hi Laurent,

Thank you for the patch. Looks good to me.
Reviewed-by: Weiyi Lu <weiyi.lu@mediatek.com>

> ---
>  drivers/clk/mediatek/clk-mux.c | 32 +++++++++++++++++++++++++++++---
>  drivers/clk/mediatek/clk-mux.h |  1 +
>  2 files changed, 30 insertions(+), 3 deletions(-)
> 
> diff --git a/drivers/clk/mediatek/clk-mux.c b/drivers/clk/mediatek/clk-mux.c
> index 9370bebca7f8..b0c61709bacc 100644
> --- a/drivers/clk/mediatek/clk-mux.c
> +++ b/drivers/clk/mediatek/clk-mux.c
> @@ -20,9 +20,33 @@ static inline struct mtk_clk_mux *to_mtk_clk_mux(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);
> +	unsigned long flags = 0;
>  
> -	return regmap_write(mux->regmap, mux->data->clr_ofs,
> -			BIT(mux->data->gate_shift));
> +	if (mux->lock)
> +		spin_lock_irqsave(mux->lock, flags);
> +	else
> +		__acquire(mux->lock);
> +
> +	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;
> +	}
> +
> +	if (mux->lock)
> +		spin_unlock_irqrestore(mux->lock, flags);
> +	else
> +		__release(mux->lock);
> +
> +	return 0;
>  }
>  
>  static void mtk_clk_mux_disable_setclr(struct clk_hw *hw)
> @@ -77,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)
> diff --git a/drivers/clk/mediatek/clk-mux.h b/drivers/clk/mediatek/clk-mux.h
> index 15c62366ba9a..f1946161ade1 100644
> --- a/drivers/clk/mediatek/clk-mux.h
> +++ b/drivers/clk/mediatek/clk-mux.h
> @@ -14,6 +14,7 @@ struct mtk_clk_mux {
>  	struct regmap *regmap;
>  	const struct mtk_mux *data;
>  	spinlock_t *lock;
> +	bool reparent;
>  };
>  
>  struct mtk_mux {
Stephen Boyd Feb. 9, 2021, 8:02 a.m. UTC | #2
Quoting Laurent Pinchart (2021-01-25 09:08:19)
> The mux clocks don't always correctly take the new parent into account
> when the parent is updated while the clock is disabled. Set the update
> bit when enabling the clock to force an update of the mux.
> 
> Signed-off-by: Laurent Pinchart <laurent.pinchart@ideasonboard.com>
> ---

Applied to clk-next
diff mbox series

Patch

diff --git a/drivers/clk/mediatek/clk-mux.c b/drivers/clk/mediatek/clk-mux.c
index 9370bebca7f8..b0c61709bacc 100644
--- a/drivers/clk/mediatek/clk-mux.c
+++ b/drivers/clk/mediatek/clk-mux.c
@@ -20,9 +20,33 @@  static inline struct mtk_clk_mux *to_mtk_clk_mux(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);
+	unsigned long flags = 0;
 
-	return regmap_write(mux->regmap, mux->data->clr_ofs,
-			BIT(mux->data->gate_shift));
+	if (mux->lock)
+		spin_lock_irqsave(mux->lock, flags);
+	else
+		__acquire(mux->lock);
+
+	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;
+	}
+
+	if (mux->lock)
+		spin_unlock_irqrestore(mux->lock, flags);
+	else
+		__release(mux->lock);
+
+	return 0;
 }
 
 static void mtk_clk_mux_disable_setclr(struct clk_hw *hw)
@@ -77,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)
diff --git a/drivers/clk/mediatek/clk-mux.h b/drivers/clk/mediatek/clk-mux.h
index 15c62366ba9a..f1946161ade1 100644
--- a/drivers/clk/mediatek/clk-mux.h
+++ b/drivers/clk/mediatek/clk-mux.h
@@ -14,6 +14,7 @@  struct mtk_clk_mux {
 	struct regmap *regmap;
 	const struct mtk_mux *data;
 	spinlock_t *lock;
+	bool reparent;
 };
 
 struct mtk_mux {