All of lore.kernel.org
 help / color / mirror / Atom feed
From: Abel Vesa <abel.vesa@linaro.org>
To: "Peng Fan (OSS)" <peng.fan@oss.nxp.com>
Cc: robh+dt@kernel.org, krzysztof.kozlowski+dt@linaro.org,
	shawnguo@kernel.org, s.hauer@pengutronix.de, abelvesa@kernel.org,
	mturquette@baylibre.com, sboyd@kernel.org, kernel@pengutronix.de,
	festevam@gmail.com, linux-imx@nxp.com,
	devicetree@vger.kernel.org, linux-arm-kernel@lists.infradead.org,
	linux-kernel@vger.kernel.org, linux-clk@vger.kernel.org,
	Peng Fan <peng.fan@nxp.com>, Ye Li <ye.li@nxp.com>,
	Jacky Bai <ping.bai@nxp.com>
Subject: Re: [PATCH V2 3/8] clk: imx: clk-composite-93: check slice busy
Date: Mon, 15 Aug 2022 11:54:18 +0300	[thread overview]
Message-ID: <YvoJuo5pJ0KFvFHK@linaro.org> (raw)
In-Reply-To: <20220815013039.474970-4-peng.fan@oss.nxp.com>

On 22-08-15 09:30:34, Peng Fan (OSS) wrote:
> From: Peng Fan <peng.fan@nxp.com>
> 
> i.MX93 CCM ROOT STAT register has a SLICE_BUSY bit:
> indication for clock generation logic is applying new setting.
> 0b - Clock generation logic is not busy.
> 1b - Clock generation logic is applying new setting.
> 
> So when set parent/rate/gate, need check this bit.
> 
> Introduce specific ops to do the work.
> 
> Signed-off-by: Peng Fan <peng.fan@nxp.com>
> Reviewed-by: Ye Li <ye.li@nxp.com>
> Reviewed-by: Jacky Bai <ping.bai@nxp.com>

Reviewed-by: Abel Vesa <abel.vesa@linaro.org>

> ---
>  drivers/clk/imx/clk-composite-93.c | 163 ++++++++++++++++++++++++++++-
>  1 file changed, 160 insertions(+), 3 deletions(-)
> 
> diff --git a/drivers/clk/imx/clk-composite-93.c b/drivers/clk/imx/clk-composite-93.c
> index b44619aa5ca5..19f4037e6cca 100644
> --- a/drivers/clk/imx/clk-composite-93.c
> +++ b/drivers/clk/imx/clk-composite-93.c
> @@ -9,20 +9,176 @@
>  #include <linux/errno.h>
>  #include <linux/export.h>
>  #include <linux/io.h>
> +#include <linux/iopoll.h>
>  #include <linux/slab.h>
>  
>  #include "clk.h"
>  
> +#define TIMEOUT_US	500U
> +
>  #define CCM_DIV_SHIFT	0
>  #define CCM_DIV_WIDTH	8
>  #define CCM_MUX_SHIFT	8
>  #define CCM_MUX_MASK	3
>  #define CCM_OFF_SHIFT	24
> +#define CCM_BUSY_SHIFT	28
>  
> +#define STAT_OFFSET	0x4
>  #define AUTHEN_OFFSET	0x30
>  #define TZ_NS_SHIFT	9
>  #define TZ_NS_MASK	BIT(9)
>  
> +static int imx93_clk_composite_wait_ready(struct clk_hw *hw, void __iomem *reg)
> +{
> +	int ret;
> +	u32 val;
> +
> +	ret = readl_poll_timeout_atomic(reg + STAT_OFFSET, val, !(val & BIT(CCM_BUSY_SHIFT)),
> +					0, TIMEOUT_US);
> +	if (ret)
> +		pr_err("Slice[%s] busy timeout\n", clk_hw_get_name(hw));
> +
> +	return ret;
> +}
> +
> +static void imx93_clk_composite_gate_endisable(struct clk_hw *hw, int enable)
> +{
> +	struct clk_gate *gate = to_clk_gate(hw);
> +	unsigned long flags;
> +	u32 reg;
> +
> +	if (gate->lock)
> +		spin_lock_irqsave(gate->lock, flags);
> +
> +	reg = readl(gate->reg);
> +
> +	if (enable)
> +		reg &= ~BIT(gate->bit_idx);
> +	else
> +		reg |= BIT(gate->bit_idx);
> +
> +	writel(reg, gate->reg);
> +
> +	imx93_clk_composite_wait_ready(hw, gate->reg);
> +
> +	if (gate->lock)
> +		spin_unlock_irqrestore(gate->lock, flags);
> +}
> +
> +static int imx93_clk_composite_gate_enable(struct clk_hw *hw)
> +{
> +	imx93_clk_composite_gate_endisable(hw, 1);
> +
> +	return 0;
> +}
> +
> +static void imx93_clk_composite_gate_disable(struct clk_hw *hw)
> +{
> +	imx93_clk_composite_gate_endisable(hw, 0);
> +}
> +
> +static const struct clk_ops imx93_clk_composite_gate_ops = {
> +	.enable = imx93_clk_composite_gate_enable,
> +	.disable = imx93_clk_composite_gate_disable,
> +	.is_enabled = clk_gate_is_enabled,
> +};
> +
> +static unsigned long
> +imx93_clk_composite_divider_recalc_rate(struct clk_hw *hw, unsigned long parent_rate)
> +{
> +	return clk_divider_ops.recalc_rate(hw, parent_rate);
> +}
> +
> +static long
> +imx93_clk_composite_divider_round_rate(struct clk_hw *hw, unsigned long rate, unsigned long *prate)
> +{
> +	return clk_divider_ops.round_rate(hw, rate, prate);
> +}
> +
> +static int
> +imx93_clk_composite_divider_determine_rate(struct clk_hw *hw, struct clk_rate_request *req)
> +{
> +	return clk_divider_ops.determine_rate(hw, req);
> +}
> +
> +static int imx93_clk_composite_divider_set_rate(struct clk_hw *hw, unsigned long rate,
> +						unsigned long parent_rate)
> +{
> +	struct clk_divider *divider = to_clk_divider(hw);
> +	int value;
> +	unsigned long flags = 0;
> +	u32 val;
> +	int ret;
> +
> +	value = divider_get_val(rate, parent_rate, divider->table, divider->width, divider->flags);
> +	if (value < 0)
> +		return value;
> +
> +	if (divider->lock)
> +		spin_lock_irqsave(divider->lock, flags);
> +
> +	val = readl(divider->reg);
> +	val &= ~(clk_div_mask(divider->width) << divider->shift);
> +	val |= (u32)value << divider->shift;
> +	writel(val, divider->reg);
> +
> +	ret = imx93_clk_composite_wait_ready(hw, divider->reg);
> +
> +	if (divider->lock)
> +		spin_unlock_irqrestore(divider->lock, flags);
> +
> +	return ret;
> +}
> +
> +static const struct clk_ops imx93_clk_composite_divider_ops = {
> +	.recalc_rate = imx93_clk_composite_divider_recalc_rate,
> +	.round_rate = imx93_clk_composite_divider_round_rate,
> +	.determine_rate = imx93_clk_composite_divider_determine_rate,
> +	.set_rate = imx93_clk_composite_divider_set_rate,
> +};
> +
> +static u8 imx93_clk_composite_mux_get_parent(struct clk_hw *hw)
> +{
> +	return clk_mux_ops.get_parent(hw);
> +}
> +
> +static int imx93_clk_composite_mux_set_parent(struct clk_hw *hw, u8 index)
> +{
> +	struct clk_mux *mux = to_clk_mux(hw);
> +	u32 val = clk_mux_index_to_val(mux->table, mux->flags, index);
> +	unsigned long flags = 0;
> +	u32 reg;
> +	int ret;
> +
> +	if (mux->lock)
> +		spin_lock_irqsave(mux->lock, flags);
> +
> +	reg = readl(mux->reg);
> +	reg &= ~(mux->mask << mux->shift);
> +	val = val << mux->shift;
> +	reg |= val;
> +	writel(reg, mux->reg);
> +
> +	ret = imx93_clk_composite_wait_ready(hw, mux->reg);
> +
> +	if (mux->lock)
> +		spin_unlock_irqrestore(mux->lock, flags);
> +
> +	return ret;
> +}
> +
> +static int
> +imx93_clk_composite_mux_determine_rate(struct clk_hw *hw, struct clk_rate_request *req)
> +{
> +	return clk_mux_ops.determine_rate(hw, req);
> +}
> +
> +static const struct clk_ops imx93_clk_composite_mux_ops = {
> +	.get_parent = imx93_clk_composite_mux_get_parent,
> +	.set_parent = imx93_clk_composite_mux_set_parent,
> +	.determine_rate = imx93_clk_composite_mux_determine_rate,
> +};
> +
>  struct clk_hw *imx93_clk_composite_flags(const char *name, const char * const *parent_names,
>  					 int num_parents, void __iomem *reg,
>  					 unsigned long flags)
> @@ -74,9 +230,10 @@ struct clk_hw *imx93_clk_composite_flags(const char *name, const char * const *p
>  		gate->flags = CLK_GATE_SET_TO_DISABLE;
>  
>  		hw = clk_hw_register_composite(NULL, name, parent_names, num_parents,
> -					       mux_hw, &clk_mux_ops, div_hw,
> -					       &clk_divider_ops, gate_hw,
> -					       &clk_gate_ops, flags | CLK_SET_RATE_NO_REPARENT);
> +					       mux_hw, &imx93_clk_composite_mux_ops, div_hw,
> +					       &imx93_clk_composite_divider_ops, gate_hw,
> +					       &imx93_clk_composite_gate_ops,
> +					       flags | CLK_SET_RATE_NO_REPARENT);
>  	}
>  
>  	if (IS_ERR(hw))
> -- 
> 2.37.1
> 

WARNING: multiple messages have this Message-ID (diff)
From: Abel Vesa <abel.vesa@linaro.org>
To: "Peng Fan (OSS)" <peng.fan@oss.nxp.com>
Cc: robh+dt@kernel.org, krzysztof.kozlowski+dt@linaro.org,
	shawnguo@kernel.org, s.hauer@pengutronix.de, abelvesa@kernel.org,
	mturquette@baylibre.com, sboyd@kernel.org, kernel@pengutronix.de,
	festevam@gmail.com, linux-imx@nxp.com,
	devicetree@vger.kernel.org, linux-arm-kernel@lists.infradead.org,
	linux-kernel@vger.kernel.org, linux-clk@vger.kernel.org,
	Peng Fan <peng.fan@nxp.com>, Ye Li <ye.li@nxp.com>,
	Jacky Bai <ping.bai@nxp.com>
Subject: Re: [PATCH V2 3/8] clk: imx: clk-composite-93: check slice busy
Date: Mon, 15 Aug 2022 11:54:18 +0300	[thread overview]
Message-ID: <YvoJuo5pJ0KFvFHK@linaro.org> (raw)
In-Reply-To: <20220815013039.474970-4-peng.fan@oss.nxp.com>

On 22-08-15 09:30:34, Peng Fan (OSS) wrote:
> From: Peng Fan <peng.fan@nxp.com>
> 
> i.MX93 CCM ROOT STAT register has a SLICE_BUSY bit:
> indication for clock generation logic is applying new setting.
> 0b - Clock generation logic is not busy.
> 1b - Clock generation logic is applying new setting.
> 
> So when set parent/rate/gate, need check this bit.
> 
> Introduce specific ops to do the work.
> 
> Signed-off-by: Peng Fan <peng.fan@nxp.com>
> Reviewed-by: Ye Li <ye.li@nxp.com>
> Reviewed-by: Jacky Bai <ping.bai@nxp.com>

Reviewed-by: Abel Vesa <abel.vesa@linaro.org>

> ---
>  drivers/clk/imx/clk-composite-93.c | 163 ++++++++++++++++++++++++++++-
>  1 file changed, 160 insertions(+), 3 deletions(-)
> 
> diff --git a/drivers/clk/imx/clk-composite-93.c b/drivers/clk/imx/clk-composite-93.c
> index b44619aa5ca5..19f4037e6cca 100644
> --- a/drivers/clk/imx/clk-composite-93.c
> +++ b/drivers/clk/imx/clk-composite-93.c
> @@ -9,20 +9,176 @@
>  #include <linux/errno.h>
>  #include <linux/export.h>
>  #include <linux/io.h>
> +#include <linux/iopoll.h>
>  #include <linux/slab.h>
>  
>  #include "clk.h"
>  
> +#define TIMEOUT_US	500U
> +
>  #define CCM_DIV_SHIFT	0
>  #define CCM_DIV_WIDTH	8
>  #define CCM_MUX_SHIFT	8
>  #define CCM_MUX_MASK	3
>  #define CCM_OFF_SHIFT	24
> +#define CCM_BUSY_SHIFT	28
>  
> +#define STAT_OFFSET	0x4
>  #define AUTHEN_OFFSET	0x30
>  #define TZ_NS_SHIFT	9
>  #define TZ_NS_MASK	BIT(9)
>  
> +static int imx93_clk_composite_wait_ready(struct clk_hw *hw, void __iomem *reg)
> +{
> +	int ret;
> +	u32 val;
> +
> +	ret = readl_poll_timeout_atomic(reg + STAT_OFFSET, val, !(val & BIT(CCM_BUSY_SHIFT)),
> +					0, TIMEOUT_US);
> +	if (ret)
> +		pr_err("Slice[%s] busy timeout\n", clk_hw_get_name(hw));
> +
> +	return ret;
> +}
> +
> +static void imx93_clk_composite_gate_endisable(struct clk_hw *hw, int enable)
> +{
> +	struct clk_gate *gate = to_clk_gate(hw);
> +	unsigned long flags;
> +	u32 reg;
> +
> +	if (gate->lock)
> +		spin_lock_irqsave(gate->lock, flags);
> +
> +	reg = readl(gate->reg);
> +
> +	if (enable)
> +		reg &= ~BIT(gate->bit_idx);
> +	else
> +		reg |= BIT(gate->bit_idx);
> +
> +	writel(reg, gate->reg);
> +
> +	imx93_clk_composite_wait_ready(hw, gate->reg);
> +
> +	if (gate->lock)
> +		spin_unlock_irqrestore(gate->lock, flags);
> +}
> +
> +static int imx93_clk_composite_gate_enable(struct clk_hw *hw)
> +{
> +	imx93_clk_composite_gate_endisable(hw, 1);
> +
> +	return 0;
> +}
> +
> +static void imx93_clk_composite_gate_disable(struct clk_hw *hw)
> +{
> +	imx93_clk_composite_gate_endisable(hw, 0);
> +}
> +
> +static const struct clk_ops imx93_clk_composite_gate_ops = {
> +	.enable = imx93_clk_composite_gate_enable,
> +	.disable = imx93_clk_composite_gate_disable,
> +	.is_enabled = clk_gate_is_enabled,
> +};
> +
> +static unsigned long
> +imx93_clk_composite_divider_recalc_rate(struct clk_hw *hw, unsigned long parent_rate)
> +{
> +	return clk_divider_ops.recalc_rate(hw, parent_rate);
> +}
> +
> +static long
> +imx93_clk_composite_divider_round_rate(struct clk_hw *hw, unsigned long rate, unsigned long *prate)
> +{
> +	return clk_divider_ops.round_rate(hw, rate, prate);
> +}
> +
> +static int
> +imx93_clk_composite_divider_determine_rate(struct clk_hw *hw, struct clk_rate_request *req)
> +{
> +	return clk_divider_ops.determine_rate(hw, req);
> +}
> +
> +static int imx93_clk_composite_divider_set_rate(struct clk_hw *hw, unsigned long rate,
> +						unsigned long parent_rate)
> +{
> +	struct clk_divider *divider = to_clk_divider(hw);
> +	int value;
> +	unsigned long flags = 0;
> +	u32 val;
> +	int ret;
> +
> +	value = divider_get_val(rate, parent_rate, divider->table, divider->width, divider->flags);
> +	if (value < 0)
> +		return value;
> +
> +	if (divider->lock)
> +		spin_lock_irqsave(divider->lock, flags);
> +
> +	val = readl(divider->reg);
> +	val &= ~(clk_div_mask(divider->width) << divider->shift);
> +	val |= (u32)value << divider->shift;
> +	writel(val, divider->reg);
> +
> +	ret = imx93_clk_composite_wait_ready(hw, divider->reg);
> +
> +	if (divider->lock)
> +		spin_unlock_irqrestore(divider->lock, flags);
> +
> +	return ret;
> +}
> +
> +static const struct clk_ops imx93_clk_composite_divider_ops = {
> +	.recalc_rate = imx93_clk_composite_divider_recalc_rate,
> +	.round_rate = imx93_clk_composite_divider_round_rate,
> +	.determine_rate = imx93_clk_composite_divider_determine_rate,
> +	.set_rate = imx93_clk_composite_divider_set_rate,
> +};
> +
> +static u8 imx93_clk_composite_mux_get_parent(struct clk_hw *hw)
> +{
> +	return clk_mux_ops.get_parent(hw);
> +}
> +
> +static int imx93_clk_composite_mux_set_parent(struct clk_hw *hw, u8 index)
> +{
> +	struct clk_mux *mux = to_clk_mux(hw);
> +	u32 val = clk_mux_index_to_val(mux->table, mux->flags, index);
> +	unsigned long flags = 0;
> +	u32 reg;
> +	int ret;
> +
> +	if (mux->lock)
> +		spin_lock_irqsave(mux->lock, flags);
> +
> +	reg = readl(mux->reg);
> +	reg &= ~(mux->mask << mux->shift);
> +	val = val << mux->shift;
> +	reg |= val;
> +	writel(reg, mux->reg);
> +
> +	ret = imx93_clk_composite_wait_ready(hw, mux->reg);
> +
> +	if (mux->lock)
> +		spin_unlock_irqrestore(mux->lock, flags);
> +
> +	return ret;
> +}
> +
> +static int
> +imx93_clk_composite_mux_determine_rate(struct clk_hw *hw, struct clk_rate_request *req)
> +{
> +	return clk_mux_ops.determine_rate(hw, req);
> +}
> +
> +static const struct clk_ops imx93_clk_composite_mux_ops = {
> +	.get_parent = imx93_clk_composite_mux_get_parent,
> +	.set_parent = imx93_clk_composite_mux_set_parent,
> +	.determine_rate = imx93_clk_composite_mux_determine_rate,
> +};
> +
>  struct clk_hw *imx93_clk_composite_flags(const char *name, const char * const *parent_names,
>  					 int num_parents, void __iomem *reg,
>  					 unsigned long flags)
> @@ -74,9 +230,10 @@ struct clk_hw *imx93_clk_composite_flags(const char *name, const char * const *p
>  		gate->flags = CLK_GATE_SET_TO_DISABLE;
>  
>  		hw = clk_hw_register_composite(NULL, name, parent_names, num_parents,
> -					       mux_hw, &clk_mux_ops, div_hw,
> -					       &clk_divider_ops, gate_hw,
> -					       &clk_gate_ops, flags | CLK_SET_RATE_NO_REPARENT);
> +					       mux_hw, &imx93_clk_composite_mux_ops, div_hw,
> +					       &imx93_clk_composite_divider_ops, gate_hw,
> +					       &imx93_clk_composite_gate_ops,
> +					       flags | CLK_SET_RATE_NO_REPARENT);
>  	}
>  
>  	if (IS_ERR(hw))
> -- 
> 2.37.1
> 

_______________________________________________
linux-arm-kernel mailing list
linux-arm-kernel@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/linux-arm-kernel

  reply	other threads:[~2022-08-15  8:54 UTC|newest]

Thread overview: 38+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2022-08-15  1:30 [PATCH V2 0/8] clk: imx93: new gate API and composite update Peng Fan (OSS)
2022-08-15  1:30 ` Peng Fan (OSS)
2022-08-15  1:30 ` [PATCH V2 1/8] dt-bindings: clock: imx93-clock: add more MU/SAI clocks Peng Fan (OSS)
2022-08-15  1:30   ` Peng Fan (OSS)
2022-08-15  8:40   ` Abel Vesa
2022-08-15  8:40     ` Abel Vesa
2022-08-15  1:30 ` [PATCH V2 2/8] clk: imx93: guard imx93_clk_of_match with CONFIG_OF Peng Fan (OSS)
2022-08-15  1:30   ` Peng Fan (OSS)
2022-08-15  8:16   ` Abel Vesa
2022-08-15  8:16     ` Abel Vesa
2022-08-15  8:19     ` Peng Fan
2022-08-15  8:19       ` Peng Fan
2022-08-15  8:23       ` Abel Vesa
2022-08-15  8:23         ` Abel Vesa
2022-08-15  1:30 ` [PATCH V2 3/8] clk: imx: clk-composite-93: check slice busy Peng Fan (OSS)
2022-08-15  1:30   ` Peng Fan (OSS)
2022-08-15  8:54   ` Abel Vesa [this message]
2022-08-15  8:54     ` Abel Vesa
2022-08-15  1:30 ` [PATCH V2 4/8] clk: imx: clk-composite-93: check white_list Peng Fan (OSS)
2022-08-15  1:30   ` Peng Fan (OSS)
2022-08-15  8:56   ` Abel Vesa
2022-08-15  8:56     ` Abel Vesa
2022-08-15  1:30 ` [PATCH V2 5/8] clk: imx: add i.MX93 clk gate Peng Fan (OSS)
2022-08-15  1:30   ` Peng Fan (OSS)
2022-08-15  9:07   ` Abel Vesa
2022-08-15  9:07     ` Abel Vesa
2022-08-15  9:21     ` Peng Fan
2022-08-15  9:21       ` Peng Fan
2022-08-15  1:30 ` [PATCH V2 6/8] clk: imx93: switch to use new clk gate API Peng Fan (OSS)
2022-08-15  1:30   ` Peng Fan (OSS)
2022-08-15  1:30 ` [PATCH V2 7/8] clk: imx93: add MU1/2 clock Peng Fan (OSS)
2022-08-15  1:30   ` Peng Fan (OSS)
2022-08-15  9:09   ` Abel Vesa
2022-08-15  9:09     ` Abel Vesa
2022-08-15  1:30 ` [PATCH V2 8/8] clk: imx93: add SAI IPG clk Peng Fan (OSS)
2022-08-15  1:30   ` Peng Fan (OSS)
2022-08-15  9:12   ` Abel Vesa
2022-08-15  9:12     ` Abel Vesa

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=YvoJuo5pJ0KFvFHK@linaro.org \
    --to=abel.vesa@linaro.org \
    --cc=abelvesa@kernel.org \
    --cc=devicetree@vger.kernel.org \
    --cc=festevam@gmail.com \
    --cc=kernel@pengutronix.de \
    --cc=krzysztof.kozlowski+dt@linaro.org \
    --cc=linux-arm-kernel@lists.infradead.org \
    --cc=linux-clk@vger.kernel.org \
    --cc=linux-imx@nxp.com \
    --cc=linux-kernel@vger.kernel.org \
    --cc=mturquette@baylibre.com \
    --cc=peng.fan@nxp.com \
    --cc=peng.fan@oss.nxp.com \
    --cc=ping.bai@nxp.com \
    --cc=robh+dt@kernel.org \
    --cc=s.hauer@pengutronix.de \
    --cc=sboyd@kernel.org \
    --cc=shawnguo@kernel.org \
    --cc=ye.li@nxp.com \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.