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
next prev parent 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.