linux-kernel.vger.kernel.org archive mirror
 help / color / mirror / Atom feed
* [PATCH V2 0/8] clk: imx93: new gate API and composite update
@ 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)
                   ` (7 more replies)
  0 siblings, 8 replies; 19+ messages in thread
From: Peng Fan (OSS) @ 2022-08-15  1:30 UTC (permalink / raw)
  To: robh+dt, krzysztof.kozlowski+dt, shawnguo, s.hauer, abelvesa,
	abel.vesa, mturquette, sboyd
  Cc: kernel, festevam, linux-imx, devicetree, linux-arm-kernel,
	linux-kernel, linux-clk, Peng Fan

From: Peng Fan <peng.fan@nxp.com>

V2:
 Add A-b from Rob
 Add a new patch 2 reported by intel test robot
 Use Abel's new address for sending mail

The current clk driver use gate API as i.MX8M*, the gate2 API use 0x3 as
val/mask, however i.MX93 LPCG DIRECT use BIT0 as on/off gate. So clk
disable unused actually not gate off the LPCG clocks.
And i.MX93 has AUTHEN feature, so add a new API to support i.MX93 clk gate.

i.MX93 CCM ROOT has slice busy check bit when updating register value, add
check. CCM ROOT also has AUTHEN whitelist, so add DID check.

Besides the gate/composite update, add MU[X] and SAI IPG clk in this
patchset

This patchset has got reviewed in NXP internal, so I keep R-b tag here.
For those that have some change compared with downstream, R-b tag dropped.

Peng Fan (8):
  dt-bindings: clock: imx93-clock: add more MU/SAI clocks
  clk: imx93: guard imx93_clk_of_match with CONFIG_OF
  clk: imx: clk-composite-93: check slice busy
  clk: imx: clk-composite-93: check white_list
  clk: imx: add i.MX93 clk gate
  clk: imx93: switch to use new clk gate API
  clk: imx93: add MU1/2 clock
  clk: imx93: add SAI IPG clk

 drivers/clk/imx/Makefile                |   2 +-
 drivers/clk/imx/clk-composite-93.c      | 171 +++++++++++++++++++-
 drivers/clk/imx/clk-gate-93.c           | 199 ++++++++++++++++++++++++
 drivers/clk/imx/clk-imx93.c             |  32 ++--
 drivers/clk/imx/clk.h                   |   9 +-
 include/dt-bindings/clock/imx93-clock.h |   9 +-
 6 files changed, 403 insertions(+), 19 deletions(-)
 create mode 100644 drivers/clk/imx/clk-gate-93.c

-- 
2.37.1


^ permalink raw reply	[flat|nested] 19+ messages in thread

* [PATCH V2 1/8] dt-bindings: clock: imx93-clock: add more MU/SAI clocks
  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  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)
                   ` (6 subsequent siblings)
  7 siblings, 1 reply; 19+ messages in thread
From: Peng Fan (OSS) @ 2022-08-15  1:30 UTC (permalink / raw)
  To: robh+dt, krzysztof.kozlowski+dt, shawnguo, s.hauer, abelvesa,
	abel.vesa, mturquette, sboyd
  Cc: kernel, festevam, linux-imx, devicetree, linux-arm-kernel,
	linux-kernel, linux-clk, Peng Fan, Rob Herring

From: Peng Fan <peng.fan@nxp.com>

Add MU[1,2]_[A,B] clock entries.
Add SAI IPG clock entries.

Acked-by: Rob Herring <robh@kernel.org>
Signed-off-by: Peng Fan <peng.fan@nxp.com>
---
 include/dt-bindings/clock/imx93-clock.h | 9 ++++++++-
 1 file changed, 8 insertions(+), 1 deletion(-)

diff --git a/include/dt-bindings/clock/imx93-clock.h b/include/dt-bindings/clock/imx93-clock.h
index 21fda9c5cb5e..19bc32788d81 100644
--- a/include/dt-bindings/clock/imx93-clock.h
+++ b/include/dt-bindings/clock/imx93-clock.h
@@ -196,6 +196,13 @@
 #define IMX93_CLK_TMC_GATE		187
 #define IMX93_CLK_PMRO_GATE		188
 #define IMX93_CLK_32K			189
-#define IMX93_CLK_END			190
+#define IMX93_CLK_SAI1_IPG		190
+#define IMX93_CLK_SAI2_IPG		191
+#define IMX93_CLK_SAI3_IPG		192
+#define IMX93_CLK_MU1_A_GATE		193
+#define IMX93_CLK_MU1_B_GATE		194
+#define IMX93_CLK_MU2_A_GATE		195
+#define IMX93_CLK_MU2_B_GATE		196
+#define IMX93_CLK_END			197
 
 #endif
-- 
2.37.1


^ permalink raw reply related	[flat|nested] 19+ messages in thread

* [PATCH V2 2/8] clk: imx93: guard imx93_clk_of_match with CONFIG_OF
  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 ` [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:16   ` Abel Vesa
  2022-08-15  1:30 ` [PATCH V2 3/8] clk: imx: clk-composite-93: check slice busy Peng Fan (OSS)
                   ` (5 subsequent siblings)
  7 siblings, 1 reply; 19+ messages in thread
From: Peng Fan (OSS) @ 2022-08-15  1:30 UTC (permalink / raw)
  To: robh+dt, krzysztof.kozlowski+dt, shawnguo, s.hauer, abelvesa,
	abel.vesa, mturquette, sboyd
  Cc: kernel, festevam, linux-imx, devicetree, linux-arm-kernel,
	linux-kernel, linux-clk, Peng Fan, kernel test robot

From: Peng Fan <peng.fan@nxp.com>

There is build warning when CONFIG_OF is not selected.
>> drivers/clk/imx/clk-imx93.c:324:34: warning: 'imx93_clk_of_match'
>> defined but not used [-Wunused-const-variable=]
     324 | static const struct of_device_id imx93_clk_of_match[] = {
         |                                  ^~~~~~~~~~~~~~~~~~

Use CONFIG_OF to guard imx93_clk_of_match to avoid build warning.

Fixes: 24defbe194b6 ("clk: imx: add i.MX93 clk")
Reported-by: kernel test robot <lkp@intel.com>
Signed-off-by: Peng Fan <peng.fan@nxp.com>
---
 drivers/clk/imx/clk-imx93.c | 2 ++
 1 file changed, 2 insertions(+)

diff --git a/drivers/clk/imx/clk-imx93.c b/drivers/clk/imx/clk-imx93.c
index f5c9fa40491c..5099048b7916 100644
--- a/drivers/clk/imx/clk-imx93.c
+++ b/drivers/clk/imx/clk-imx93.c
@@ -321,11 +321,13 @@ static int imx93_clocks_probe(struct platform_device *pdev)
 	return ret;
 }
 
+#ifdef CONFIG_OF
 static const struct of_device_id imx93_clk_of_match[] = {
 	{ .compatible = "fsl,imx93-ccm" },
 	{ /* Sentinel */ },
 };
 MODULE_DEVICE_TABLE(of, imx93_clk_of_match);
+#endif
 
 static struct platform_driver imx93_clk_driver = {
 	.probe = imx93_clocks_probe,
-- 
2.37.1


^ permalink raw reply related	[flat|nested] 19+ messages in thread

* [PATCH V2 3/8] clk: imx: clk-composite-93: check slice busy
  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 ` [PATCH V2 1/8] dt-bindings: clock: imx93-clock: add more MU/SAI clocks Peng Fan (OSS)
  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:54   ` Abel Vesa
  2022-08-15  1:30 ` [PATCH V2 4/8] clk: imx: clk-composite-93: check white_list Peng Fan (OSS)
                   ` (4 subsequent siblings)
  7 siblings, 1 reply; 19+ messages in thread
From: Peng Fan (OSS) @ 2022-08-15  1:30 UTC (permalink / raw)
  To: robh+dt, krzysztof.kozlowski+dt, shawnguo, s.hauer, abelvesa,
	abel.vesa, mturquette, sboyd
  Cc: kernel, festevam, linux-imx, devicetree, linux-arm-kernel,
	linux-kernel, linux-clk, Peng Fan, Ye Li, Jacky Bai

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>
---
 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


^ permalink raw reply related	[flat|nested] 19+ messages in thread

* [PATCH V2 4/8] clk: imx: clk-composite-93: check white_list
  2022-08-15  1:30 [PATCH V2 0/8] clk: imx93: new gate API and composite update Peng Fan (OSS)
                   ` (2 preceding siblings ...)
  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:56   ` Abel Vesa
  2022-08-15  1:30 ` [PATCH V2 5/8] clk: imx: add i.MX93 clk gate Peng Fan (OSS)
                   ` (3 subsequent siblings)
  7 siblings, 1 reply; 19+ messages in thread
From: Peng Fan (OSS) @ 2022-08-15  1:30 UTC (permalink / raw)
  To: robh+dt, krzysztof.kozlowski+dt, shawnguo, s.hauer, abelvesa,
	abel.vesa, mturquette, sboyd
  Cc: kernel, festevam, linux-imx, devicetree, linux-arm-kernel,
	linux-kernel, linux-clk, Peng Fan, Ye Li, Jacky Bai

From: Peng Fan <peng.fan@nxp.com>

The CCM ROOT AUTHEN register WHITE_LIST indicate:
Each bit in this field represent for one domain. Bit16~Bit31 represent
for DOMAIN0~DOMAIN15 respectively. Only corresponding bit of the domains
is set to 1 can change the registers of this Clock Root.

i.MX93 DID is 3, so if BIT(3 + WHITE_LIST_SHIFT) is 0, the clk should be
set to read only. To make the imx93_clk_composite_flags be reusable,
add a new parameter named did(domain id);

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>
---
 drivers/clk/imx/clk-composite-93.c | 8 ++++++--
 drivers/clk/imx/clk-imx93.c        | 2 +-
 drivers/clk/imx/clk.h              | 5 +++--
 3 files changed, 10 insertions(+), 5 deletions(-)

diff --git a/drivers/clk/imx/clk-composite-93.c b/drivers/clk/imx/clk-composite-93.c
index 19f4037e6cca..74a66b0203e4 100644
--- a/drivers/clk/imx/clk-composite-93.c
+++ b/drivers/clk/imx/clk-composite-93.c
@@ -28,6 +28,8 @@
 #define TZ_NS_SHIFT	9
 #define TZ_NS_MASK	BIT(9)
 
+#define WHITE_LIST_SHIFT	16
+
 static int imx93_clk_composite_wait_ready(struct clk_hw *hw, void __iomem *reg)
 {
 	int ret;
@@ -180,7 +182,7 @@ static const struct clk_ops imx93_clk_composite_mux_ops = {
 };
 
 struct clk_hw *imx93_clk_composite_flags(const char *name, const char * const *parent_names,
-					 int num_parents, void __iomem *reg,
+					 int num_parents, void __iomem *reg, u32 domain_id,
 					 unsigned long flags)
 {
 	struct clk_hw *hw = ERR_PTR(-ENOMEM), *mux_hw;
@@ -189,6 +191,7 @@ struct clk_hw *imx93_clk_composite_flags(const char *name, const char * const *p
 	struct clk_gate *gate = NULL;
 	struct clk_mux *mux = NULL;
 	bool clk_ro = false;
+	u32 authen;
 
 	mux = kzalloc(sizeof(*mux), GFP_KERNEL);
 	if (!mux)
@@ -211,7 +214,8 @@ struct clk_hw *imx93_clk_composite_flags(const char *name, const char * const *p
 	div->lock = &imx_ccm_lock;
 	div->flags = CLK_DIVIDER_ROUND_CLOSEST;
 
-	if (!(readl(reg + AUTHEN_OFFSET) & TZ_NS_MASK))
+	authen = readl(reg + AUTHEN_OFFSET);
+	if (!(authen & TZ_NS_MASK) || !(authen & BIT(WHITE_LIST_SHIFT + domain_id)))
 		clk_ro = true;
 
 	if (clk_ro) {
diff --git a/drivers/clk/imx/clk-imx93.c b/drivers/clk/imx/clk-imx93.c
index 5099048b7916..0d5c11bb3659 100644
--- a/drivers/clk/imx/clk-imx93.c
+++ b/drivers/clk/imx/clk-imx93.c
@@ -293,7 +293,7 @@ static int imx93_clocks_probe(struct platform_device *pdev)
 		root = &root_array[i];
 		clks[root->clk] = imx93_clk_composite_flags(root->name,
 							    parent_names[root->sel],
-							    4, base + root->off,
+							    4, base + root->off, 3,
 							    root->flags);
 	}
 
diff --git a/drivers/clk/imx/clk.h b/drivers/clk/imx/clk.h
index 5061a06468df..396a5ea75083 100644
--- a/drivers/clk/imx/clk.h
+++ b/drivers/clk/imx/clk.h
@@ -445,9 +445,10 @@ struct clk_hw *imx93_clk_composite_flags(const char *name,
 					 const char * const *parent_names,
 					 int num_parents,
 					 void __iomem *reg,
+					 u32 domain_id,
 					 unsigned long flags);
-#define imx93_clk_composite(name, parent_names, num_parents, reg) \
-	imx93_clk_composite_flags(name, parent_names, num_parents, reg, \
+#define imx93_clk_composite(name, parent_names, num_parents, reg, domain_id) \
+	imx93_clk_composite_flags(name, parent_names, num_parents, reg, domain_id \
 				  CLK_SET_RATE_NO_REPARENT | CLK_OPS_PARENT_ENABLE)
 
 struct clk_hw *imx_clk_hw_divider_gate(const char *name, const char *parent_name,
-- 
2.37.1


^ permalink raw reply related	[flat|nested] 19+ messages in thread

* [PATCH V2 5/8] clk: imx: add i.MX93 clk gate
  2022-08-15  1:30 [PATCH V2 0/8] clk: imx93: new gate API and composite update Peng Fan (OSS)
                   ` (3 preceding siblings ...)
  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  9:07   ` Abel Vesa
  2022-08-15  1:30 ` [PATCH V2 6/8] clk: imx93: switch to use new clk gate API Peng Fan (OSS)
                   ` (2 subsequent siblings)
  7 siblings, 1 reply; 19+ messages in thread
From: Peng Fan (OSS) @ 2022-08-15  1:30 UTC (permalink / raw)
  To: robh+dt, krzysztof.kozlowski+dt, shawnguo, s.hauer, abelvesa,
	abel.vesa, mturquette, sboyd
  Cc: kernel, festevam, linux-imx, devicetree, linux-arm-kernel,
	linux-kernel, linux-clk, Peng Fan, Ye Li, Jacky Bai

From: Peng Fan <peng.fan@nxp.com>

i.MX93 LPCG is different from i.MX8M CCGR. Although imx_clk_hw_gate4_flags
is used here, it not strictly match i.MX93. i.MX93 has such design:
 - LPCG_DIRECT use BIT0 as on/off gate when LPCG_AUTHEN CPU_LPM is 0
 - LPCG_LPM_CUR use BIT[2:0] as on/off gate when LPCG_AUTHEN CPU_LPM is 1

The current implementation suppose CPU_LPM is 0, and use LPCG_DIRECT
BIT[1:0] as on/off gate. Although BIT1 is touched, actually BIT1 is
reserved.

And imx_clk_hw_gate4_flags use mask 0x3 to determine whether the clk
is enabled or not, but i.MX93 LPCG only use BIT0 to control when CPU_LPM
is 0. So clk disabled unused during kernel boot not able to gate off
the unused clocks.

To match i.MX93 LPCG, introduce imx93_clk_gate.

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>
---
 drivers/clk/imx/Makefile      |   2 +-
 drivers/clk/imx/clk-gate-93.c | 199 ++++++++++++++++++++++++++++++++++
 drivers/clk/imx/clk.h         |   4 +
 3 files changed, 204 insertions(+), 1 deletion(-)
 create mode 100644 drivers/clk/imx/clk-gate-93.c

diff --git a/drivers/clk/imx/Makefile b/drivers/clk/imx/Makefile
index 88b9b9285d22..89fe72327788 100644
--- a/drivers/clk/imx/Makefile
+++ b/drivers/clk/imx/Makefile
@@ -28,7 +28,7 @@ obj-$(CONFIG_CLK_IMX8MN) += clk-imx8mn.o
 obj-$(CONFIG_CLK_IMX8MP) += clk-imx8mp.o
 obj-$(CONFIG_CLK_IMX8MQ) += clk-imx8mq.o
 
-obj-$(CONFIG_CLK_IMX93) += clk-imx93.o
+obj-$(CONFIG_CLK_IMX93) += clk-imx93.o clk-gate-93.o
 
 obj-$(CONFIG_MXC_CLK_SCU) += clk-imx-scu.o clk-imx-lpcg-scu.o
 clk-imx-scu-$(CONFIG_CLK_IMX8QXP) += clk-scu.o clk-imx8qxp.o \
diff --git a/drivers/clk/imx/clk-gate-93.c b/drivers/clk/imx/clk-gate-93.c
new file mode 100644
index 000000000000..ceb56b290394
--- /dev/null
+++ b/drivers/clk/imx/clk-gate-93.c
@@ -0,0 +1,199 @@
+// SPDX-License-Identifier: GPL-2.0+
+/*
+ * Copyright 2022 NXP
+ *
+ * Peng Fan <peng.fan@nxp.com>
+ */
+
+#include <linux/clk-provider.h>
+#include <linux/errno.h>
+#include <linux/export.h>
+#include <linux/io.h>
+#include <linux/iopoll.h>
+#include <linux/slab.h>
+
+#include "clk.h"
+
+#define DIRECT_OFFSET		0x0
+
+/*
+ * 0b000 - LPCG will be OFF in any CPU mode.
+ * 0b100 - LPCG will be ON in any CPU mode.
+ */
+#define LPM_SETTING_OFF		0x0
+#define LPM_SETTING_ON		0x4
+
+#define LPM_CUR_OFFSET		0x1c
+
+#define AUTHEN_OFFSET		0x30
+#define CPULPM_EN		BIT(2)
+#define TZ_NS_SHIFT		9
+#define TZ_NS_MASK		BIT(9)
+
+#define WHITE_LIST_SHIFT	16
+
+struct imx93_clk_gate {
+	struct clk_hw hw;
+	void __iomem	*reg;
+	u32		bit_idx;
+	u32		val;
+	u32		mask;
+	spinlock_t	*lock;
+	unsigned int	*share_count;
+};
+
+#define to_imx93_clk_gate(_hw) container_of(_hw, struct imx93_clk_gate, hw)
+
+static void imx93_clk_gate_do_hardware(struct clk_hw *hw, bool enable)
+{
+	struct imx93_clk_gate *gate = to_imx93_clk_gate(hw);
+	u32 val;
+
+	val = readl(gate->reg + AUTHEN_OFFSET);
+	if (val & CPULPM_EN) {
+		val = enable ? LPM_SETTING_ON : LPM_SETTING_OFF;
+		writel(val, gate->reg + LPM_CUR_OFFSET);
+	} else {
+		val = readl(gate->reg + DIRECT_OFFSET);
+		val &= ~(gate->mask << gate->bit_idx);
+		if (enable)
+			val |= (gate->val & gate->mask) << gate->bit_idx;
+		writel(val, gate->reg + DIRECT_OFFSET);
+	}
+}
+
+static int imx93_clk_gate_enable(struct clk_hw *hw)
+{
+	struct imx93_clk_gate *gate = to_imx93_clk_gate(hw);
+	unsigned long flags;
+
+	spin_lock_irqsave(gate->lock, flags);
+
+	if (gate->share_count && (*gate->share_count)++ > 0)
+		goto out;
+
+	imx93_clk_gate_do_hardware(hw, true);
+out:
+	spin_unlock_irqrestore(gate->lock, flags);
+
+	return 0;
+}
+
+static void imx93_clk_gate_disable(struct clk_hw *hw)
+{
+	struct imx93_clk_gate *gate = to_imx93_clk_gate(hw);
+	unsigned long flags;
+
+	spin_lock_irqsave(gate->lock, flags);
+
+	if (gate->share_count) {
+		if (WARN_ON(*gate->share_count == 0))
+			goto out;
+		else if (--(*gate->share_count) > 0)
+			goto out;
+	}
+
+	imx93_clk_gate_do_hardware(hw, false);
+out:
+	spin_unlock_irqrestore(gate->lock, flags);
+}
+
+static int imx93_clk_gate_reg_is_enabled(struct imx93_clk_gate *gate)
+{
+	u32 val = readl(gate->reg + AUTHEN_OFFSET);
+
+	if (val & CPULPM_EN) {
+		val = readl(gate->reg + LPM_CUR_OFFSET);
+		if (val == LPM_SETTING_ON)
+			return 1;
+	} else {
+		val = readl(gate->reg);
+		if (((val >> gate->bit_idx) & gate->mask) == gate->val)
+			return 1;
+	}
+
+	return 0;
+}
+
+static int imx93_clk_gate_is_enabled(struct clk_hw *hw)
+{
+	struct imx93_clk_gate *gate = to_imx93_clk_gate(hw);
+	unsigned long flags;
+	int ret;
+
+	spin_lock_irqsave(gate->lock, flags);
+
+	ret = imx93_clk_gate_reg_is_enabled(gate);
+
+	spin_unlock_irqrestore(gate->lock, flags);
+
+	return ret;
+}
+
+static void imx93_clk_gate_disable_unused(struct clk_hw *hw)
+{
+	struct imx93_clk_gate *gate = to_imx93_clk_gate(hw);
+	unsigned long flags;
+
+	spin_lock_irqsave(gate->lock, flags);
+
+	if (!gate->share_count || *gate->share_count == 0)
+		imx93_clk_gate_do_hardware(hw, false);
+
+	spin_unlock_irqrestore(gate->lock, flags);
+}
+
+static const struct clk_ops imx93_clk_gate_ops = {
+	.enable = imx93_clk_gate_enable,
+	.disable = imx93_clk_gate_disable,
+	.disable_unused = imx93_clk_gate_disable_unused,
+	.is_enabled = imx93_clk_gate_is_enabled,
+};
+
+static const struct clk_ops imx93_clk_gate_ro_ops = {
+	.is_enabled = imx93_clk_gate_is_enabled,
+};
+
+struct clk_hw *imx93_clk_gate(struct device *dev, const char *name, const char *parent_name,
+			      unsigned long flags, void __iomem *reg, u32 bit_idx, u32 val,
+			      u32 mask, u32 domain_id, unsigned int *share_count)
+{
+	struct imx93_clk_gate *gate;
+	struct clk_hw *hw;
+	struct clk_init_data init;
+	int ret;
+	u32 authen;
+
+	gate = kzalloc(sizeof(struct imx93_clk_gate), GFP_KERNEL);
+	if (!gate)
+		return ERR_PTR(-ENOMEM);
+
+	gate->reg = reg;
+	gate->lock = &imx_ccm_lock;
+	gate->bit_idx = bit_idx;
+	gate->val = val;
+	gate->mask = mask;
+	gate->share_count = share_count;
+
+	init.name = name;
+	init.ops = &imx93_clk_gate_ops;
+	init.flags = flags | CLK_SET_RATE_PARENT | CLK_OPS_PARENT_ENABLE;
+	init.parent_names = parent_name ? &parent_name : NULL;
+	init.num_parents = parent_name ? 1 : 0;
+
+	gate->hw.init = &init;
+	hw = &gate->hw;
+
+	authen = readl(reg + AUTHEN_OFFSET);
+	if (!(authen & TZ_NS_MASK) || !(authen & BIT(WHITE_LIST_SHIFT + domain_id)))
+		init.ops = &imx93_clk_gate_ro_ops;
+
+	ret = clk_hw_register(dev, hw);
+	if (ret) {
+		kfree(gate);
+		return ERR_PTR(ret);
+	}
+
+	return hw;
+}
+EXPORT_SYMBOL_GPL(imx93_clk_gate);
diff --git a/drivers/clk/imx/clk.h b/drivers/clk/imx/clk.h
index 396a5ea75083..dd49f90110e8 100644
--- a/drivers/clk/imx/clk.h
+++ b/drivers/clk/imx/clk.h
@@ -451,6 +451,10 @@ struct clk_hw *imx93_clk_composite_flags(const char *name,
 	imx93_clk_composite_flags(name, parent_names, num_parents, reg, domain_id \
 				  CLK_SET_RATE_NO_REPARENT | CLK_OPS_PARENT_ENABLE)
 
+struct clk_hw *imx93_clk_gate(struct device *dev, const char *name, const char *parent_name,
+			      unsigned long flags, void __iomem *reg, u32 bit_idx, u32 val,
+			      u32 mask, u32 domain_id, unsigned int *share_count);
+
 struct clk_hw *imx_clk_hw_divider_gate(const char *name, const char *parent_name,
 		unsigned long flags, void __iomem *reg, u8 shift, u8 width,
 		u8 clk_divider_flags, const struct clk_div_table *table,
-- 
2.37.1


^ permalink raw reply related	[flat|nested] 19+ messages in thread

* [PATCH V2 6/8] clk: imx93: switch to use new clk gate API
  2022-08-15  1:30 [PATCH V2 0/8] clk: imx93: new gate API and composite update Peng Fan (OSS)
                   ` (4 preceding siblings ...)
  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  1:30 ` [PATCH V2 7/8] clk: imx93: add MU1/2 clock Peng Fan (OSS)
  2022-08-15  1:30 ` [PATCH V2 8/8] clk: imx93: add SAI IPG clk Peng Fan (OSS)
  7 siblings, 0 replies; 19+ messages in thread
From: Peng Fan (OSS) @ 2022-08-15  1:30 UTC (permalink / raw)
  To: robh+dt, krzysztof.kozlowski+dt, shawnguo, s.hauer, abelvesa,
	abel.vesa, mturquette, sboyd
  Cc: kernel, festevam, linux-imx, devicetree, linux-arm-kernel,
	linux-kernel, linux-clk, Peng Fan, Ye Li, Jacky Bai

From: Peng Fan <peng.fan@nxp.com>

Use i.MX93 specific clk gate API

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>
---
 drivers/clk/imx/clk-imx93.c | 8 ++++----
 1 file changed, 4 insertions(+), 4 deletions(-)

diff --git a/drivers/clk/imx/clk-imx93.c b/drivers/clk/imx/clk-imx93.c
index 0d5c11bb3659..73d30a2e64b0 100644
--- a/drivers/clk/imx/clk-imx93.c
+++ b/drivers/clk/imx/clk-imx93.c
@@ -146,6 +146,7 @@ static const struct imx93_clk_ccgr {
 	char *parent_name;
 	u32 off;
 	unsigned long flags;
+	u32 *shared_count;
 } ccgr_array[] = {
 	{ IMX93_CLK_A55_GATE,		"a55",		"a55_root",		0x8000, },
 	/* M33 critical clk for system run */
@@ -299,10 +300,9 @@ static int imx93_clocks_probe(struct platform_device *pdev)
 
 	for (i = 0; i < ARRAY_SIZE(ccgr_array); i++) {
 		ccgr = &ccgr_array[i];
-		clks[ccgr->clk] = imx_clk_hw_gate4_flags(ccgr->name,
-							 ccgr->parent_name,
-							 base + ccgr->off, 0,
-							 ccgr->flags);
+		clks[ccgr->clk] = imx93_clk_gate(NULL, ccgr->name, ccgr->parent_name,
+						 ccgr->flags, base + ccgr->off, 0, 1, 1, 3,
+						 ccgr->shared_count);
 	}
 
 	imx_check_clk_hws(clks, IMX93_CLK_END);
-- 
2.37.1


^ permalink raw reply related	[flat|nested] 19+ messages in thread

* [PATCH V2 7/8] clk: imx93: add MU1/2 clock
  2022-08-15  1:30 [PATCH V2 0/8] clk: imx93: new gate API and composite update Peng Fan (OSS)
                   ` (5 preceding siblings ...)
  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  9:09   ` Abel Vesa
  2022-08-15  1:30 ` [PATCH V2 8/8] clk: imx93: add SAI IPG clk Peng Fan (OSS)
  7 siblings, 1 reply; 19+ messages in thread
From: Peng Fan (OSS) @ 2022-08-15  1:30 UTC (permalink / raw)
  To: robh+dt, krzysztof.kozlowski+dt, shawnguo, s.hauer, abelvesa,
	abel.vesa, mturquette, sboyd
  Cc: kernel, festevam, linux-imx, devicetree, linux-arm-kernel,
	linux-kernel, linux-clk, Peng Fan, Ye Li, Jacky Bai

From: Peng Fan <peng.fan@nxp.com>

The clk tree should be as:
bus_aon_root------>\               /--->MU1_B IP
                    -->MU_B gate-->
bus_wakeup_root--->/               \--->MU2_B IP

bus_aon_root------>\               /--->MU1_A IP
                    -->MU_A gate-->
bus_wakeup_root--->/               \--->MU2_A IP

So need use shared count gate. And linux use MU_B,
so set MU_A clk as CLK_IGNORE_UNUSED.

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>
---
 drivers/clk/imx/clk-imx93.c | 8 ++++++--
 1 file changed, 6 insertions(+), 2 deletions(-)

diff --git a/drivers/clk/imx/clk-imx93.c b/drivers/clk/imx/clk-imx93.c
index 73d30a2e64b0..4008ab075dfe 100644
--- a/drivers/clk/imx/clk-imx93.c
+++ b/drivers/clk/imx/clk-imx93.c
@@ -28,6 +28,8 @@ enum clk_sel {
 	MAX_SEL
 };
 
+static u32 share_count_mub;
+
 static const char *parent_names[MAX_SEL][4] = {
 	{"osc_24m", "sys_pll_pfd0_div2", "sys_pll_pfd1_div2", "video_pll"},
 	{"osc_24m", "sys_pll_pfd0_div2", "sys_pll_pfd1_div2", "sys_pll_pfd2_div2"},
@@ -159,8 +161,10 @@ static const struct imx93_clk_ccgr {
 	{ IMX93_CLK_WDOG5_GATE,		"wdog5",	"osc_24m",		0x8400, },
 	{ IMX93_CLK_SEMA1_GATE,		"sema1",	"bus_aon_root",		0x8440, },
 	{ IMX93_CLK_SEMA2_GATE,		"sema2",	"bus_wakeup_root",	0x8480, },
-	{ IMX93_CLK_MU_A_GATE,		"mu_a",		"bus_aon_root",		0x84c0, },
-	{ IMX93_CLK_MU_B_GATE,		"mu_b",		"bus_aon_root",		0x8500, },
+	{ IMX93_CLK_MU1_A_GATE,		"mu1_a",	"bus_aon_root",		0x84c0, CLK_IGNORE_UNUSED },
+	{ IMX93_CLK_MU2_A_GATE,		"mu2_a",	"bus_wakeup_root",	0x84c0, CLK_IGNORE_UNUSED },
+	{ IMX93_CLK_MU1_B_GATE,		"mu1_b",	"bus_aon_root",		0x8500, 0, &share_count_mub },
+	{ IMX93_CLK_MU2_B_GATE,		"mu2_b",	"bus_wakeup_root",	0x8500, 0, &share_count_mub },
 	{ IMX93_CLK_EDMA1_GATE,		"edma1",	"m33_root",		0x8540, },
 	{ IMX93_CLK_EDMA2_GATE,		"edma2",	"wakeup_axi_root",	0x8580, },
 	{ IMX93_CLK_FLEXSPI1_GATE,	"flexspi",	"flexspi_root",		0x8640, },
-- 
2.37.1


^ permalink raw reply related	[flat|nested] 19+ messages in thread

* [PATCH V2 8/8] clk: imx93: add SAI IPG clk
  2022-08-15  1:30 [PATCH V2 0/8] clk: imx93: new gate API and composite update Peng Fan (OSS)
                   ` (6 preceding siblings ...)
  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:12   ` Abel Vesa
  7 siblings, 1 reply; 19+ messages in thread
From: Peng Fan (OSS) @ 2022-08-15  1:30 UTC (permalink / raw)
  To: robh+dt, krzysztof.kozlowski+dt, shawnguo, s.hauer, abelvesa,
	abel.vesa, mturquette, sboyd
  Cc: kernel, festevam, linux-imx, devicetree, linux-arm-kernel,
	linux-kernel, linux-clk, Peng Fan

From: Peng Fan <peng.fan@nxp.com>

The clk topology is as below:
bus_aon_root------>\                  /--->SAI IPG
                    -->SAI LPCG gate-->
sai[x]_clk_root--->/                  \--->SAI MCLK

So use shared count as i.MX93 MU_B gate.

Signed-off-by: Peng Fan <peng.fan@nxp.com>
---
 drivers/clk/imx/clk-imx93.c | 12 +++++++++---
 1 file changed, 9 insertions(+), 3 deletions(-)

diff --git a/drivers/clk/imx/clk-imx93.c b/drivers/clk/imx/clk-imx93.c
index 4008ab075dfe..6a76b9fdf18d 100644
--- a/drivers/clk/imx/clk-imx93.c
+++ b/drivers/clk/imx/clk-imx93.c
@@ -28,6 +28,9 @@ enum clk_sel {
 	MAX_SEL
 };
 
+static u32 share_count_sai1;
+static u32 share_count_sai2;
+static u32 share_count_sai3;
 static u32 share_count_mub;
 
 static const char *parent_names[MAX_SEL][4] = {
@@ -215,9 +218,12 @@ static const struct imx93_clk_ccgr {
 	{ IMX93_CLK_USDHC1_GATE,	"usdhc1",	"usdhc1_root",		0x9380, },
 	{ IMX93_CLK_USDHC2_GATE,	"usdhc2",	"usdhc2_root",		0x93c0, },
 	{ IMX93_CLK_USDHC3_GATE,	"usdhc3",	"usdhc3_root",		0x9400, },
-	{ IMX93_CLK_SAI1_GATE,		"sai1",		"sai1_root",		0x9440, },
-	{ IMX93_CLK_SAI2_GATE,		"sai2",		"sai2_root",		0x9480, },
-	{ IMX93_CLK_SAI3_GATE,		"sai3",		"sai3_root",		0x94c0, },
+	{ IMX93_CLK_SAI1_GATE,          "sai1",         "sai1_root",            0x9440, 0, &share_count_sai1},
+	{ IMX93_CLK_SAI1_IPG,		"sai1_ipg_clk", "bus_aon_root",		0x9440, 0, &share_count_sai1},
+	{ IMX93_CLK_SAI2_GATE,          "sai2",         "sai2_root",            0x9480, 0, &share_count_sai2},
+	{ IMX93_CLK_SAI2_IPG,		"sai2_ipg_clk", "bus_wakeup_root",	0x9480, 0, &share_count_sai2},
+	{ IMX93_CLK_SAI3_GATE,          "sai3",         "sai3_root",            0x94c0, 0, &share_count_sai3},
+	{ IMX93_CLK_SAI3_IPG,		"sai3_ipg_clk", "bus_wakeup_root",	0x94c0, 0, &share_count_sai3},
 	{ IMX93_CLK_MIPI_CSI_GATE,	"mipi_csi",	"media_apb_root",	0x9580, },
 	{ IMX93_CLK_MIPI_DSI_GATE,	"mipi_dsi",	"media_apb_root",	0x95c0, },
 	{ IMX93_CLK_LVDS_GATE,		"lvds",		"media_ldb_root",	0x9600, },
-- 
2.37.1


^ permalink raw reply related	[flat|nested] 19+ messages in thread

* Re: [PATCH V2 2/8] clk: imx93: guard imx93_clk_of_match with CONFIG_OF
  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  8:16   ` Abel Vesa
  2022-08-15  8:19     ` Peng Fan
  0 siblings, 1 reply; 19+ messages in thread
From: Abel Vesa @ 2022-08-15  8:16 UTC (permalink / raw)
  To: Peng Fan (OSS), Stephen Boyd
  Cc: robh+dt, krzysztof.kozlowski+dt, shawnguo, s.hauer, abelvesa,
	mturquette, sboyd, kernel, festevam, linux-imx, devicetree,
	linux-arm-kernel, linux-kernel, linux-clk, Peng Fan,
	kernel test robot

On 22-08-15 09:30:33, Peng Fan (OSS) wrote:
> From: Peng Fan <peng.fan@nxp.com>
> 
> There is build warning when CONFIG_OF is not selected.
> >> drivers/clk/imx/clk-imx93.c:324:34: warning: 'imx93_clk_of_match'
> >> defined but not used [-Wunused-const-variable=]
>      324 | static const struct of_device_id imx93_clk_of_match[] = {
>          |                                  ^~~~~~~~~~~~~~~~~~
> 
> Use CONFIG_OF to guard imx93_clk_of_match to avoid build warning.
> 
> Fixes: 24defbe194b6 ("clk: imx: add i.MX93 clk")
> Reported-by: kernel test robot <lkp@intel.com>
> Signed-off-by: Peng Fan <peng.fan@nxp.com>
> ---
>  drivers/clk/imx/clk-imx93.c | 2 ++
>  1 file changed, 2 insertions(+)
> 
> diff --git a/drivers/clk/imx/clk-imx93.c b/drivers/clk/imx/clk-imx93.c
> index f5c9fa40491c..5099048b7916 100644
> --- a/drivers/clk/imx/clk-imx93.c
> +++ b/drivers/clk/imx/clk-imx93.c
> @@ -321,11 +321,13 @@ static int imx93_clocks_probe(struct platform_device *pdev)
>  	return ret;
>  }
>  
> +#ifdef CONFIG_OF

Hmm, I'm not sure if we should do this or rather should we make this driver
depend somehow on CONFIG_OF in Kconfig.

Looking at the other i.MX clock drivers, it would seem we need this for
all them too.

I fairly OK with this, but maybe Stephen suggests something different.

Reviewed-by: Abel Vesa <abel.vesa@nxp.com>

>  static const struct of_device_id imx93_clk_of_match[] = {
>  	{ .compatible = "fsl,imx93-ccm" },
>  	{ /* Sentinel */ },
>  };
>  MODULE_DEVICE_TABLE(of, imx93_clk_of_match);
> +#endif
>  
>  static struct platform_driver imx93_clk_driver = {
>  	.probe = imx93_clocks_probe,
> -- 
> 2.37.1
> 

^ permalink raw reply	[flat|nested] 19+ messages in thread

* RE: [PATCH V2 2/8] clk: imx93: guard imx93_clk_of_match with CONFIG_OF
  2022-08-15  8:16   ` Abel Vesa
@ 2022-08-15  8:19     ` Peng Fan
  2022-08-15  8:23       ` Abel Vesa
  0 siblings, 1 reply; 19+ messages in thread
From: Peng Fan @ 2022-08-15  8:19 UTC (permalink / raw)
  To: Abel Vesa, Peng Fan (OSS), Stephen Boyd
  Cc: robh+dt, krzysztof.kozlowski+dt, shawnguo, s.hauer, abelvesa,
	mturquette, sboyd, kernel, festevam, dl-linux-imx, devicetree,
	linux-arm-kernel, linux-kernel, linux-clk, kernel test robot

> Subject: Re: [PATCH V2 2/8] clk: imx93: guard imx93_clk_of_match with
> CONFIG_OF
> 
> On 22-08-15 09:30:33, Peng Fan (OSS) wrote:
> > From: Peng Fan <peng.fan@nxp.com>
> >
> > There is build warning when CONFIG_OF is not selected.
> > >> drivers/clk/imx/clk-imx93.c:324:34: warning: 'imx93_clk_of_match'
> > >> defined but not used [-Wunused-const-variable=]
> >      324 | static const struct of_device_id imx93_clk_of_match[] = {
> >          |                                  ^~~~~~~~~~~~~~~~~~
> >
> > Use CONFIG_OF to guard imx93_clk_of_match to avoid build warning.
> >
> > Fixes: 24defbe194b6 ("clk: imx: add i.MX93 clk")
> > Reported-by: kernel test robot <lkp@intel.com>
> > Signed-off-by: Peng Fan <peng.fan@nxp.com>
> > ---
> >  drivers/clk/imx/clk-imx93.c | 2 ++
> >  1 file changed, 2 insertions(+)
> >
> > diff --git a/drivers/clk/imx/clk-imx93.c b/drivers/clk/imx/clk-imx93.c
> > index f5c9fa40491c..5099048b7916 100644
> > --- a/drivers/clk/imx/clk-imx93.c
> > +++ b/drivers/clk/imx/clk-imx93.c
> > @@ -321,11 +321,13 @@ static int imx93_clocks_probe(struct
> platform_device *pdev)
> >  	return ret;
> >  }
> >
> > +#ifdef CONFIG_OF
> 
> Hmm, I'm not sure if we should do this or rather should we make this driver
> depend somehow on CONFIG_OF in Kconfig.
> 
> Looking at the other i.MX clock drivers, it would seem we need this for all
> them too.

No. It is i.MX93 use of_match_ptr, I could drop it as i.MX8M.

Thanks,
Peng.

> 
> I fairly OK with this, but maybe Stephen suggests something different.
> 
> Reviewed-by: Abel Vesa <abel.vesa@nxp.com>
> 
> >  static const struct of_device_id imx93_clk_of_match[] = {
> >  	{ .compatible = "fsl,imx93-ccm" },
> >  	{ /* Sentinel */ },
> >  };
> >  MODULE_DEVICE_TABLE(of, imx93_clk_of_match);
> > +#endif
> >
> >  static struct platform_driver imx93_clk_driver = {
> >  	.probe = imx93_clocks_probe,
> > --
> > 2.37.1
> >

^ permalink raw reply	[flat|nested] 19+ messages in thread

* Re: [PATCH V2 2/8] clk: imx93: guard imx93_clk_of_match with CONFIG_OF
  2022-08-15  8:19     ` Peng Fan
@ 2022-08-15  8:23       ` Abel Vesa
  0 siblings, 0 replies; 19+ messages in thread
From: Abel Vesa @ 2022-08-15  8:23 UTC (permalink / raw)
  To: Peng Fan
  Cc: Peng Fan (OSS),
	Stephen Boyd, robh+dt, krzysztof.kozlowski+dt, shawnguo, s.hauer,
	abelvesa, mturquette, kernel, festevam, dl-linux-imx, devicetree,
	linux-arm-kernel, linux-kernel, linux-clk, kernel test robot

On 22-08-15 08:19:52, Peng Fan wrote:
> > Subject: Re: [PATCH V2 2/8] clk: imx93: guard imx93_clk_of_match with
> > CONFIG_OF
> > 
> > On 22-08-15 09:30:33, Peng Fan (OSS) wrote:
> > > From: Peng Fan <peng.fan@nxp.com>
> > >
> > > There is build warning when CONFIG_OF is not selected.
> > > >> drivers/clk/imx/clk-imx93.c:324:34: warning: 'imx93_clk_of_match'
> > > >> defined but not used [-Wunused-const-variable=]
> > >      324 | static const struct of_device_id imx93_clk_of_match[] = {
> > >          |                                  ^~~~~~~~~~~~~~~~~~
> > >
> > > Use CONFIG_OF to guard imx93_clk_of_match to avoid build warning.
> > >
> > > Fixes: 24defbe194b6 ("clk: imx: add i.MX93 clk")
> > > Reported-by: kernel test robot <lkp@intel.com>
> > > Signed-off-by: Peng Fan <peng.fan@nxp.com>
> > > ---
> > >  drivers/clk/imx/clk-imx93.c | 2 ++
> > >  1 file changed, 2 insertions(+)
> > >
> > > diff --git a/drivers/clk/imx/clk-imx93.c b/drivers/clk/imx/clk-imx93.c
> > > index f5c9fa40491c..5099048b7916 100644
> > > --- a/drivers/clk/imx/clk-imx93.c
> > > +++ b/drivers/clk/imx/clk-imx93.c
> > > @@ -321,11 +321,13 @@ static int imx93_clocks_probe(struct
> > platform_device *pdev)
> > >  	return ret;
> > >  }
> > >
> > > +#ifdef CONFIG_OF
> > 
> > Hmm, I'm not sure if we should do this or rather should we make this driver
> > depend somehow on CONFIG_OF in Kconfig.
> > 
> > Looking at the other i.MX clock drivers, it would seem we need this for all
> > them too.
> 
> No. It is i.MX93 use of_match_ptr, I could drop it as i.MX8M.
> 
> Thanks,
> Peng.

Right. Thanks for pointing that out.

> 
> > 
> > I fairly OK with this, but maybe Stephen suggests something different.
> > 
> > Reviewed-by: Abel Vesa <abel.vesa@nxp.com>
> > 

Oups, wrong address here too.

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

> > >  static const struct of_device_id imx93_clk_of_match[] = {
> > >  	{ .compatible = "fsl,imx93-ccm" },
> > >  	{ /* Sentinel */ },
> > >  };
> > >  MODULE_DEVICE_TABLE(of, imx93_clk_of_match);
> > > +#endif
> > >
> > >  static struct platform_driver imx93_clk_driver = {
> > >  	.probe = imx93_clocks_probe,
> > > --
> > > 2.37.1
> > >

^ permalink raw reply	[flat|nested] 19+ messages in thread

* Re: [PATCH V2 1/8] dt-bindings: clock: imx93-clock: add more MU/SAI clocks
  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  8:40   ` Abel Vesa
  0 siblings, 0 replies; 19+ messages in thread
From: Abel Vesa @ 2022-08-15  8:40 UTC (permalink / raw)
  To: Peng Fan (OSS)
  Cc: robh+dt, krzysztof.kozlowski+dt, shawnguo, s.hauer, abelvesa,
	mturquette, sboyd, kernel, festevam, linux-imx, devicetree,
	linux-arm-kernel, linux-kernel, linux-clk, Peng Fan, Rob Herring

On 22-08-15 09:30:32, Peng Fan (OSS) wrote:
> From: Peng Fan <peng.fan@nxp.com>
> 
> Add MU[1,2]_[A,B] clock entries.
> Add SAI IPG clock entries.
> 
> Acked-by: Rob Herring <robh@kernel.org>
> Signed-off-by: Peng Fan <peng.fan@nxp.com>

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

> ---
>  include/dt-bindings/clock/imx93-clock.h | 9 ++++++++-
>  1 file changed, 8 insertions(+), 1 deletion(-)
> 
> diff --git a/include/dt-bindings/clock/imx93-clock.h b/include/dt-bindings/clock/imx93-clock.h
> index 21fda9c5cb5e..19bc32788d81 100644
> --- a/include/dt-bindings/clock/imx93-clock.h
> +++ b/include/dt-bindings/clock/imx93-clock.h
> @@ -196,6 +196,13 @@
>  #define IMX93_CLK_TMC_GATE		187
>  #define IMX93_CLK_PMRO_GATE		188
>  #define IMX93_CLK_32K			189
> -#define IMX93_CLK_END			190
> +#define IMX93_CLK_SAI1_IPG		190
> +#define IMX93_CLK_SAI2_IPG		191
> +#define IMX93_CLK_SAI3_IPG		192
> +#define IMX93_CLK_MU1_A_GATE		193
> +#define IMX93_CLK_MU1_B_GATE		194
> +#define IMX93_CLK_MU2_A_GATE		195
> +#define IMX93_CLK_MU2_B_GATE		196
> +#define IMX93_CLK_END			197
>  
>  #endif
> -- 
> 2.37.1
> 

^ permalink raw reply	[flat|nested] 19+ messages in thread

* Re: [PATCH V2 3/8] clk: imx: clk-composite-93: check slice busy
  2022-08-15  1:30 ` [PATCH V2 3/8] clk: imx: clk-composite-93: check slice busy Peng Fan (OSS)
@ 2022-08-15  8:54   ` Abel Vesa
  0 siblings, 0 replies; 19+ messages in thread
From: Abel Vesa @ 2022-08-15  8:54 UTC (permalink / raw)
  To: Peng Fan (OSS)
  Cc: robh+dt, krzysztof.kozlowski+dt, shawnguo, s.hauer, abelvesa,
	mturquette, sboyd, kernel, festevam, linux-imx, devicetree,
	linux-arm-kernel, linux-kernel, linux-clk, Peng Fan, Ye Li,
	Jacky Bai

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
> 

^ permalink raw reply	[flat|nested] 19+ messages in thread

* Re: [PATCH V2 4/8] clk: imx: clk-composite-93: check white_list
  2022-08-15  1:30 ` [PATCH V2 4/8] clk: imx: clk-composite-93: check white_list Peng Fan (OSS)
@ 2022-08-15  8:56   ` Abel Vesa
  0 siblings, 0 replies; 19+ messages in thread
From: Abel Vesa @ 2022-08-15  8:56 UTC (permalink / raw)
  To: Peng Fan (OSS)
  Cc: robh+dt, krzysztof.kozlowski+dt, shawnguo, s.hauer, abelvesa,
	mturquette, sboyd, kernel, festevam, linux-imx, devicetree,
	linux-arm-kernel, linux-kernel, linux-clk, Peng Fan, Ye Li,
	Jacky Bai

On 22-08-15 09:30:35, Peng Fan (OSS) wrote:
> From: Peng Fan <peng.fan@nxp.com>
> 
> The CCM ROOT AUTHEN register WHITE_LIST indicate:
> Each bit in this field represent for one domain. Bit16~Bit31 represent
> for DOMAIN0~DOMAIN15 respectively. Only corresponding bit of the domains
> is set to 1 can change the registers of this Clock Root.
> 
> i.MX93 DID is 3, so if BIT(3 + WHITE_LIST_SHIFT) is 0, the clk should be
> set to read only. To make the imx93_clk_composite_flags be reusable,
> add a new parameter named did(domain id);
> 
> 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 | 8 ++++++--
>  drivers/clk/imx/clk-imx93.c        | 2 +-
>  drivers/clk/imx/clk.h              | 5 +++--
>  3 files changed, 10 insertions(+), 5 deletions(-)
> 
> diff --git a/drivers/clk/imx/clk-composite-93.c b/drivers/clk/imx/clk-composite-93.c
> index 19f4037e6cca..74a66b0203e4 100644
> --- a/drivers/clk/imx/clk-composite-93.c
> +++ b/drivers/clk/imx/clk-composite-93.c
> @@ -28,6 +28,8 @@
>  #define TZ_NS_SHIFT	9
>  #define TZ_NS_MASK	BIT(9)
>  
> +#define WHITE_LIST_SHIFT	16
> +
>  static int imx93_clk_composite_wait_ready(struct clk_hw *hw, void __iomem *reg)
>  {
>  	int ret;
> @@ -180,7 +182,7 @@ static const struct clk_ops imx93_clk_composite_mux_ops = {
>  };
>  
>  struct clk_hw *imx93_clk_composite_flags(const char *name, const char * const *parent_names,
> -					 int num_parents, void __iomem *reg,
> +					 int num_parents, void __iomem *reg, u32 domain_id,
>  					 unsigned long flags)
>  {
>  	struct clk_hw *hw = ERR_PTR(-ENOMEM), *mux_hw;
> @@ -189,6 +191,7 @@ struct clk_hw *imx93_clk_composite_flags(const char *name, const char * const *p
>  	struct clk_gate *gate = NULL;
>  	struct clk_mux *mux = NULL;
>  	bool clk_ro = false;
> +	u32 authen;
>  
>  	mux = kzalloc(sizeof(*mux), GFP_KERNEL);
>  	if (!mux)
> @@ -211,7 +214,8 @@ struct clk_hw *imx93_clk_composite_flags(const char *name, const char * const *p
>  	div->lock = &imx_ccm_lock;
>  	div->flags = CLK_DIVIDER_ROUND_CLOSEST;
>  
> -	if (!(readl(reg + AUTHEN_OFFSET) & TZ_NS_MASK))
> +	authen = readl(reg + AUTHEN_OFFSET);
> +	if (!(authen & TZ_NS_MASK) || !(authen & BIT(WHITE_LIST_SHIFT + domain_id)))
>  		clk_ro = true;
>  
>  	if (clk_ro) {
> diff --git a/drivers/clk/imx/clk-imx93.c b/drivers/clk/imx/clk-imx93.c
> index 5099048b7916..0d5c11bb3659 100644
> --- a/drivers/clk/imx/clk-imx93.c
> +++ b/drivers/clk/imx/clk-imx93.c
> @@ -293,7 +293,7 @@ static int imx93_clocks_probe(struct platform_device *pdev)
>  		root = &root_array[i];
>  		clks[root->clk] = imx93_clk_composite_flags(root->name,
>  							    parent_names[root->sel],
> -							    4, base + root->off,
> +							    4, base + root->off, 3,
>  							    root->flags);
>  	}
>  
> diff --git a/drivers/clk/imx/clk.h b/drivers/clk/imx/clk.h
> index 5061a06468df..396a5ea75083 100644
> --- a/drivers/clk/imx/clk.h
> +++ b/drivers/clk/imx/clk.h
> @@ -445,9 +445,10 @@ struct clk_hw *imx93_clk_composite_flags(const char *name,
>  					 const char * const *parent_names,
>  					 int num_parents,
>  					 void __iomem *reg,
> +					 u32 domain_id,
>  					 unsigned long flags);
> -#define imx93_clk_composite(name, parent_names, num_parents, reg) \
> -	imx93_clk_composite_flags(name, parent_names, num_parents, reg, \
> +#define imx93_clk_composite(name, parent_names, num_parents, reg, domain_id) \
> +	imx93_clk_composite_flags(name, parent_names, num_parents, reg, domain_id \
>  				  CLK_SET_RATE_NO_REPARENT | CLK_OPS_PARENT_ENABLE)
>  
>  struct clk_hw *imx_clk_hw_divider_gate(const char *name, const char *parent_name,
> -- 
> 2.37.1
> 

^ permalink raw reply	[flat|nested] 19+ messages in thread

* Re: [PATCH V2 5/8] clk: imx: add i.MX93 clk gate
  2022-08-15  1:30 ` [PATCH V2 5/8] clk: imx: add i.MX93 clk gate Peng Fan (OSS)
@ 2022-08-15  9:07   ` Abel Vesa
  2022-08-15  9:21     ` Peng Fan
  0 siblings, 1 reply; 19+ messages in thread
From: Abel Vesa @ 2022-08-15  9:07 UTC (permalink / raw)
  To: Peng Fan (OSS)
  Cc: robh+dt, krzysztof.kozlowski+dt, shawnguo, s.hauer, abelvesa,
	mturquette, sboyd, kernel, festevam, linux-imx, devicetree,
	linux-arm-kernel, linux-kernel, linux-clk, Peng Fan, Ye Li,
	Jacky Bai

On 22-08-15 09:30:36, Peng Fan (OSS) wrote:
> From: Peng Fan <peng.fan@nxp.com>
> 
> i.MX93 LPCG is different from i.MX8M CCGR. Although imx_clk_hw_gate4_flags
> is used here, it not strictly match i.MX93. i.MX93 has such design:
>  - LPCG_DIRECT use BIT0 as on/off gate when LPCG_AUTHEN CPU_LPM is 0
>  - LPCG_LPM_CUR use BIT[2:0] as on/off gate when LPCG_AUTHEN CPU_LPM is 1
> 
> The current implementation suppose CPU_LPM is 0, and use LPCG_DIRECT
> BIT[1:0] as on/off gate. Although BIT1 is touched, actually BIT1 is
> reserved.
> 
> And imx_clk_hw_gate4_flags use mask 0x3 to determine whether the clk
> is enabled or not, but i.MX93 LPCG only use BIT0 to control when CPU_LPM
> is 0. So clk disabled unused during kernel boot not able to gate off
> the unused clocks.
> 
> To match i.MX93 LPCG, introduce imx93_clk_gate.
> 
> 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>
> ---
>  drivers/clk/imx/Makefile      |   2 +-
>  drivers/clk/imx/clk-gate-93.c | 199 ++++++++++++++++++++++++++++++++++
>  drivers/clk/imx/clk.h         |   4 +
>  3 files changed, 204 insertions(+), 1 deletion(-)
>  create mode 100644 drivers/clk/imx/clk-gate-93.c
> 
> diff --git a/drivers/clk/imx/Makefile b/drivers/clk/imx/Makefile
> index 88b9b9285d22..89fe72327788 100644
> --- a/drivers/clk/imx/Makefile
> +++ b/drivers/clk/imx/Makefile
> @@ -28,7 +28,7 @@ obj-$(CONFIG_CLK_IMX8MN) += clk-imx8mn.o
>  obj-$(CONFIG_CLK_IMX8MP) += clk-imx8mp.o
>  obj-$(CONFIG_CLK_IMX8MQ) += clk-imx8mq.o
>  
> -obj-$(CONFIG_CLK_IMX93) += clk-imx93.o
> +obj-$(CONFIG_CLK_IMX93) += clk-imx93.o clk-gate-93.o
>  
>  obj-$(CONFIG_MXC_CLK_SCU) += clk-imx-scu.o clk-imx-lpcg-scu.o
>  clk-imx-scu-$(CONFIG_CLK_IMX8QXP) += clk-scu.o clk-imx8qxp.o \
> diff --git a/drivers/clk/imx/clk-gate-93.c b/drivers/clk/imx/clk-gate-93.c
> new file mode 100644
> index 000000000000..ceb56b290394
> --- /dev/null
> +++ b/drivers/clk/imx/clk-gate-93.c
> @@ -0,0 +1,199 @@
> +// SPDX-License-Identifier: GPL-2.0+
> +/*
> + * Copyright 2022 NXP
> + *
> + * Peng Fan <peng.fan@nxp.com>
> + */
> +
> +#include <linux/clk-provider.h>
> +#include <linux/errno.h>
> +#include <linux/export.h>
> +#include <linux/io.h>
> +#include <linux/iopoll.h>
> +#include <linux/slab.h>
> +
> +#include "clk.h"
> +
> +#define DIRECT_OFFSET		0x0
> +
> +/*
> + * 0b000 - LPCG will be OFF in any CPU mode.
> + * 0b100 - LPCG will be ON in any CPU mode.
> + */
> +#define LPM_SETTING_OFF		0x0
> +#define LPM_SETTING_ON		0x4
> +
> +#define LPM_CUR_OFFSET		0x1c
> +
> +#define AUTHEN_OFFSET		0x30
> +#define CPULPM_EN		BIT(2)
> +#define TZ_NS_SHIFT		9
> +#define TZ_NS_MASK		BIT(9)
> +
> +#define WHITE_LIST_SHIFT	16
> +
> +struct imx93_clk_gate {
> +	struct clk_hw hw;
> +	void __iomem	*reg;
> +	u32		bit_idx;
> +	u32		val;
> +	u32		mask;
> +	spinlock_t	*lock;
> +	unsigned int	*share_count;
> +};
> +
> +#define to_imx93_clk_gate(_hw) container_of(_hw, struct imx93_clk_gate, hw)
> +
> +static void imx93_clk_gate_do_hardware(struct clk_hw *hw, bool enable)
> +{
> +	struct imx93_clk_gate *gate = to_imx93_clk_gate(hw);
> +	u32 val;
> +
> +	val = readl(gate->reg + AUTHEN_OFFSET);
> +	if (val & CPULPM_EN) {
> +		val = enable ? LPM_SETTING_ON : LPM_SETTING_OFF;
> +		writel(val, gate->reg + LPM_CUR_OFFSET);
> +	} else {
> +		val = readl(gate->reg + DIRECT_OFFSET);
> +		val &= ~(gate->mask << gate->bit_idx);
> +		if (enable)
> +			val |= (gate->val & gate->mask) << gate->bit_idx;
> +		writel(val, gate->reg + DIRECT_OFFSET);
> +	}
> +}
> +
> +static int imx93_clk_gate_enable(struct clk_hw *hw)
> +{
> +	struct imx93_clk_gate *gate = to_imx93_clk_gate(hw);
> +	unsigned long flags;
> +
> +	spin_lock_irqsave(gate->lock, flags);
> +
> +	if (gate->share_count && (*gate->share_count)++ > 0)
> +		goto out;
> +
> +	imx93_clk_gate_do_hardware(hw, true);
> +out:
> +	spin_unlock_irqrestore(gate->lock, flags);
> +
> +	return 0;
> +}

Just wondering if we could use the existing clk-gate2 since we would
only have to implement the ops that are different there.

Also, would the next i.MX9 platforms also use this? Or will we have one
similar driver for each new platform?

> +
> +static void imx93_clk_gate_disable(struct clk_hw *hw)
> +{
> +	struct imx93_clk_gate *gate = to_imx93_clk_gate(hw);
> +	unsigned long flags;
> +
> +	spin_lock_irqsave(gate->lock, flags);
> +
> +	if (gate->share_count) {
> +		if (WARN_ON(*gate->share_count == 0))
> +			goto out;
> +		else if (--(*gate->share_count) > 0)
> +			goto out;
> +	}
> +
> +	imx93_clk_gate_do_hardware(hw, false);
> +out:
> +	spin_unlock_irqrestore(gate->lock, flags);
> +}
> +
> +static int imx93_clk_gate_reg_is_enabled(struct imx93_clk_gate *gate)
> +{
> +	u32 val = readl(gate->reg + AUTHEN_OFFSET);
> +
> +	if (val & CPULPM_EN) {
> +		val = readl(gate->reg + LPM_CUR_OFFSET);
> +		if (val == LPM_SETTING_ON)
> +			return 1;
> +	} else {
> +		val = readl(gate->reg);
> +		if (((val >> gate->bit_idx) & gate->mask) == gate->val)
> +			return 1;
> +	}
> +
> +	return 0;
> +}
> +
> +static int imx93_clk_gate_is_enabled(struct clk_hw *hw)
> +{
> +	struct imx93_clk_gate *gate = to_imx93_clk_gate(hw);
> +	unsigned long flags;
> +	int ret;
> +
> +	spin_lock_irqsave(gate->lock, flags);
> +
> +	ret = imx93_clk_gate_reg_is_enabled(gate);
> +
> +	spin_unlock_irqrestore(gate->lock, flags);
> +
> +	return ret;
> +}
> +
> +static void imx93_clk_gate_disable_unused(struct clk_hw *hw)
> +{
> +	struct imx93_clk_gate *gate = to_imx93_clk_gate(hw);
> +	unsigned long flags;
> +
> +	spin_lock_irqsave(gate->lock, flags);
> +
> +	if (!gate->share_count || *gate->share_count == 0)
> +		imx93_clk_gate_do_hardware(hw, false);
> +
> +	spin_unlock_irqrestore(gate->lock, flags);
> +}
> +
> +static const struct clk_ops imx93_clk_gate_ops = {
> +	.enable = imx93_clk_gate_enable,
> +	.disable = imx93_clk_gate_disable,
> +	.disable_unused = imx93_clk_gate_disable_unused,
> +	.is_enabled = imx93_clk_gate_is_enabled,
> +};
> +
> +static const struct clk_ops imx93_clk_gate_ro_ops = {
> +	.is_enabled = imx93_clk_gate_is_enabled,
> +};
> +
> +struct clk_hw *imx93_clk_gate(struct device *dev, const char *name, const char *parent_name,
> +			      unsigned long flags, void __iomem *reg, u32 bit_idx, u32 val,
> +			      u32 mask, u32 domain_id, unsigned int *share_count)
> +{
> +	struct imx93_clk_gate *gate;
> +	struct clk_hw *hw;
> +	struct clk_init_data init;
> +	int ret;
> +	u32 authen;
> +
> +	gate = kzalloc(sizeof(struct imx93_clk_gate), GFP_KERNEL);
> +	if (!gate)
> +		return ERR_PTR(-ENOMEM);
> +
> +	gate->reg = reg;
> +	gate->lock = &imx_ccm_lock;
> +	gate->bit_idx = bit_idx;
> +	gate->val = val;
> +	gate->mask = mask;
> +	gate->share_count = share_count;
> +
> +	init.name = name;
> +	init.ops = &imx93_clk_gate_ops;
> +	init.flags = flags | CLK_SET_RATE_PARENT | CLK_OPS_PARENT_ENABLE;
> +	init.parent_names = parent_name ? &parent_name : NULL;
> +	init.num_parents = parent_name ? 1 : 0;
> +
> +	gate->hw.init = &init;
> +	hw = &gate->hw;
> +
> +	authen = readl(reg + AUTHEN_OFFSET);
> +	if (!(authen & TZ_NS_MASK) || !(authen & BIT(WHITE_LIST_SHIFT + domain_id)))
> +		init.ops = &imx93_clk_gate_ro_ops;
> +
> +	ret = clk_hw_register(dev, hw);
> +	if (ret) {
> +		kfree(gate);
> +		return ERR_PTR(ret);
> +	}
> +
> +	return hw;
> +}
> +EXPORT_SYMBOL_GPL(imx93_clk_gate);
> diff --git a/drivers/clk/imx/clk.h b/drivers/clk/imx/clk.h
> index 396a5ea75083..dd49f90110e8 100644
> --- a/drivers/clk/imx/clk.h
> +++ b/drivers/clk/imx/clk.h
> @@ -451,6 +451,10 @@ struct clk_hw *imx93_clk_composite_flags(const char *name,
>  	imx93_clk_composite_flags(name, parent_names, num_parents, reg, domain_id \
>  				  CLK_SET_RATE_NO_REPARENT | CLK_OPS_PARENT_ENABLE)
>  
> +struct clk_hw *imx93_clk_gate(struct device *dev, const char *name, const char *parent_name,
> +			      unsigned long flags, void __iomem *reg, u32 bit_idx, u32 val,
> +			      u32 mask, u32 domain_id, unsigned int *share_count);
> +
>  struct clk_hw *imx_clk_hw_divider_gate(const char *name, const char *parent_name,
>  		unsigned long flags, void __iomem *reg, u8 shift, u8 width,
>  		u8 clk_divider_flags, const struct clk_div_table *table,
> -- 
> 2.37.1
> 

^ permalink raw reply	[flat|nested] 19+ messages in thread

* Re: [PATCH V2 7/8] clk: imx93: add MU1/2 clock
  2022-08-15  1:30 ` [PATCH V2 7/8] clk: imx93: add MU1/2 clock Peng Fan (OSS)
@ 2022-08-15  9:09   ` Abel Vesa
  0 siblings, 0 replies; 19+ messages in thread
From: Abel Vesa @ 2022-08-15  9:09 UTC (permalink / raw)
  To: Peng Fan (OSS)
  Cc: robh+dt, krzysztof.kozlowski+dt, shawnguo, s.hauer, abelvesa,
	mturquette, sboyd, kernel, festevam, linux-imx, devicetree,
	linux-arm-kernel, linux-kernel, linux-clk, Peng Fan, Ye Li,
	Jacky Bai

On 22-08-15 09:30:38, Peng Fan (OSS) wrote:
> From: Peng Fan <peng.fan@nxp.com>
> 
> The clk tree should be as:
> bus_aon_root------>\               /--->MU1_B IP
>                     -->MU_B gate-->
> bus_wakeup_root--->/               \--->MU2_B IP
> 
> bus_aon_root------>\               /--->MU1_A IP
>                     -->MU_A gate-->
> bus_wakeup_root--->/               \--->MU2_A IP
> 
> So need use shared count gate. And linux use MU_B,
> so set MU_A clk as CLK_IGNORE_UNUSED.
> 
> 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-imx93.c | 8 ++++++--
>  1 file changed, 6 insertions(+), 2 deletions(-)
> 
> diff --git a/drivers/clk/imx/clk-imx93.c b/drivers/clk/imx/clk-imx93.c
> index 73d30a2e64b0..4008ab075dfe 100644
> --- a/drivers/clk/imx/clk-imx93.c
> +++ b/drivers/clk/imx/clk-imx93.c
> @@ -28,6 +28,8 @@ enum clk_sel {
>  	MAX_SEL
>  };
>  
> +static u32 share_count_mub;
> +
>  static const char *parent_names[MAX_SEL][4] = {
>  	{"osc_24m", "sys_pll_pfd0_div2", "sys_pll_pfd1_div2", "video_pll"},
>  	{"osc_24m", "sys_pll_pfd0_div2", "sys_pll_pfd1_div2", "sys_pll_pfd2_div2"},
> @@ -159,8 +161,10 @@ static const struct imx93_clk_ccgr {
>  	{ IMX93_CLK_WDOG5_GATE,		"wdog5",	"osc_24m",		0x8400, },
>  	{ IMX93_CLK_SEMA1_GATE,		"sema1",	"bus_aon_root",		0x8440, },
>  	{ IMX93_CLK_SEMA2_GATE,		"sema2",	"bus_wakeup_root",	0x8480, },
> -	{ IMX93_CLK_MU_A_GATE,		"mu_a",		"bus_aon_root",		0x84c0, },
> -	{ IMX93_CLK_MU_B_GATE,		"mu_b",		"bus_aon_root",		0x8500, },
> +	{ IMX93_CLK_MU1_A_GATE,		"mu1_a",	"bus_aon_root",		0x84c0, CLK_IGNORE_UNUSED },
> +	{ IMX93_CLK_MU2_A_GATE,		"mu2_a",	"bus_wakeup_root",	0x84c0, CLK_IGNORE_UNUSED },
> +	{ IMX93_CLK_MU1_B_GATE,		"mu1_b",	"bus_aon_root",		0x8500, 0, &share_count_mub },
> +	{ IMX93_CLK_MU2_B_GATE,		"mu2_b",	"bus_wakeup_root",	0x8500, 0, &share_count_mub },
>  	{ IMX93_CLK_EDMA1_GATE,		"edma1",	"m33_root",		0x8540, },
>  	{ IMX93_CLK_EDMA2_GATE,		"edma2",	"wakeup_axi_root",	0x8580, },
>  	{ IMX93_CLK_FLEXSPI1_GATE,	"flexspi",	"flexspi_root",		0x8640, },
> -- 
> 2.37.1
> 

^ permalink raw reply	[flat|nested] 19+ messages in thread

* Re: [PATCH V2 8/8] clk: imx93: add SAI IPG clk
  2022-08-15  1:30 ` [PATCH V2 8/8] clk: imx93: add SAI IPG clk Peng Fan (OSS)
@ 2022-08-15  9:12   ` Abel Vesa
  0 siblings, 0 replies; 19+ messages in thread
From: Abel Vesa @ 2022-08-15  9:12 UTC (permalink / raw)
  To: Peng Fan (OSS)
  Cc: robh+dt, krzysztof.kozlowski+dt, shawnguo, s.hauer, abelvesa,
	mturquette, sboyd, kernel, festevam, linux-imx, devicetree,
	linux-arm-kernel, linux-kernel, linux-clk, Peng Fan

On 22-08-15 09:30:39, Peng Fan (OSS) wrote:
> From: Peng Fan <peng.fan@nxp.com>
> 
> The clk topology is as below:
> bus_aon_root------>\                  /--->SAI IPG
>                     -->SAI LPCG gate-->
> sai[x]_clk_root--->/                  \--->SAI MCLK
> 
> So use shared count as i.MX93 MU_B gate.
> 
> Signed-off-by: Peng Fan <peng.fan@nxp.com>

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

> ---
>  drivers/clk/imx/clk-imx93.c | 12 +++++++++---
>  1 file changed, 9 insertions(+), 3 deletions(-)
> 
> diff --git a/drivers/clk/imx/clk-imx93.c b/drivers/clk/imx/clk-imx93.c
> index 4008ab075dfe..6a76b9fdf18d 100644
> --- a/drivers/clk/imx/clk-imx93.c
> +++ b/drivers/clk/imx/clk-imx93.c
> @@ -28,6 +28,9 @@ enum clk_sel {
>  	MAX_SEL
>  };
>  
> +static u32 share_count_sai1;
> +static u32 share_count_sai2;
> +static u32 share_count_sai3;
>  static u32 share_count_mub;
>  
>  static const char *parent_names[MAX_SEL][4] = {
> @@ -215,9 +218,12 @@ static const struct imx93_clk_ccgr {
>  	{ IMX93_CLK_USDHC1_GATE,	"usdhc1",	"usdhc1_root",		0x9380, },
>  	{ IMX93_CLK_USDHC2_GATE,	"usdhc2",	"usdhc2_root",		0x93c0, },
>  	{ IMX93_CLK_USDHC3_GATE,	"usdhc3",	"usdhc3_root",		0x9400, },
> -	{ IMX93_CLK_SAI1_GATE,		"sai1",		"sai1_root",		0x9440, },
> -	{ IMX93_CLK_SAI2_GATE,		"sai2",		"sai2_root",		0x9480, },
> -	{ IMX93_CLK_SAI3_GATE,		"sai3",		"sai3_root",		0x94c0, },
> +	{ IMX93_CLK_SAI1_GATE,          "sai1",         "sai1_root",            0x9440, 0, &share_count_sai1},
> +	{ IMX93_CLK_SAI1_IPG,		"sai1_ipg_clk", "bus_aon_root",		0x9440, 0, &share_count_sai1},
> +	{ IMX93_CLK_SAI2_GATE,          "sai2",         "sai2_root",            0x9480, 0, &share_count_sai2},
> +	{ IMX93_CLK_SAI2_IPG,		"sai2_ipg_clk", "bus_wakeup_root",	0x9480, 0, &share_count_sai2},
> +	{ IMX93_CLK_SAI3_GATE,          "sai3",         "sai3_root",            0x94c0, 0, &share_count_sai3},
> +	{ IMX93_CLK_SAI3_IPG,		"sai3_ipg_clk", "bus_wakeup_root",	0x94c0, 0, &share_count_sai3},
>  	{ IMX93_CLK_MIPI_CSI_GATE,	"mipi_csi",	"media_apb_root",	0x9580, },
>  	{ IMX93_CLK_MIPI_DSI_GATE,	"mipi_dsi",	"media_apb_root",	0x95c0, },
>  	{ IMX93_CLK_LVDS_GATE,		"lvds",		"media_ldb_root",	0x9600, },
> -- 
> 2.37.1
> 

^ permalink raw reply	[flat|nested] 19+ messages in thread

* RE: [PATCH V2 5/8] clk: imx: add i.MX93 clk gate
  2022-08-15  9:07   ` Abel Vesa
@ 2022-08-15  9:21     ` Peng Fan
  0 siblings, 0 replies; 19+ messages in thread
From: Peng Fan @ 2022-08-15  9:21 UTC (permalink / raw)
  To: Abel Vesa, Peng Fan (OSS)
  Cc: robh+dt, krzysztof.kozlowski+dt, shawnguo, s.hauer, abelvesa,
	mturquette, sboyd, kernel, festevam, dl-linux-imx, devicetree,
	linux-arm-kernel, linux-kernel, linux-clk, Ye Li, Jacky Bai

Hi Abel,

> Subject: Re: [PATCH V2 5/8] clk: imx: add i.MX93 clk gate
> 
> On 22-08-15 09:30:36, Peng Fan (OSS) wrote:
> > From: Peng Fan <peng.fan@nxp.com>
> >
> > i.MX93 LPCG is different from i.MX8M CCGR. Although
> > imx_clk_hw_gate4_flags is used here, it not strictly match i.MX93. i.MX93
> has such design:
> >  - LPCG_DIRECT use BIT0 as on/off gate when LPCG_AUTHEN CPU_LPM is 0
> >  - LPCG_LPM_CUR use BIT[2:0] as on/off gate when LPCG_AUTHEN
> CPU_LPM
> > is 1
> >
> > The current implementation suppose CPU_LPM is 0, and use LPCG_DIRECT
> > BIT[1:0] as on/off gate. Although BIT1 is touched, actually BIT1 is
> > reserved.
> >
> > And imx_clk_hw_gate4_flags use mask 0x3 to determine whether the clk
> > is enabled or not, but i.MX93 LPCG only use BIT0 to control when
> > CPU_LPM is 0. So clk disabled unused during kernel boot not able to
> > gate off the unused clocks.
> >
> > To match i.MX93 LPCG, introduce imx93_clk_gate.
> >
> > 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>
> > ---
> >  drivers/clk/imx/Makefile      |   2 +-
> >  drivers/clk/imx/clk-gate-93.c | 199
> ++++++++++++++++++++++++++++++++++
> >  drivers/clk/imx/clk.h         |   4 +
> >  3 files changed, 204 insertions(+), 1 deletion(-)  create mode 100644
> > drivers/clk/imx/clk-gate-93.c
> >
> > diff --git a/drivers/clk/imx/Makefile b/drivers/clk/imx/Makefile index
> > 88b9b9285d22..89fe72327788 100644
> > --- a/drivers/clk/imx/Makefile
> > +++ b/drivers/clk/imx/Makefile
> > @@ -28,7 +28,7 @@ obj-$(CONFIG_CLK_IMX8MN) += clk-imx8mn.o
> >  obj-$(CONFIG_CLK_IMX8MP) += clk-imx8mp.o
> >  obj-$(CONFIG_CLK_IMX8MQ) += clk-imx8mq.o
> >
> > -obj-$(CONFIG_CLK_IMX93) += clk-imx93.o
> > +obj-$(CONFIG_CLK_IMX93) += clk-imx93.o clk-gate-93.o
> >
> >  obj-$(CONFIG_MXC_CLK_SCU) += clk-imx-scu.o clk-imx-lpcg-scu.o
> >  clk-imx-scu-$(CONFIG_CLK_IMX8QXP) += clk-scu.o clk-imx8qxp.o \ diff
> > --git a/drivers/clk/imx/clk-gate-93.c b/drivers/clk/imx/clk-gate-93.c
> > new file mode 100644 index 000000000000..ceb56b290394
> > --- /dev/null
> > +++ b/drivers/clk/imx/clk-gate-93.c
> > @@ -0,0 +1,199 @@
> > +// SPDX-License-Identifier: GPL-2.0+
> > +/*
> > + * Copyright 2022 NXP
> > + *
> > + * Peng Fan <peng.fan@nxp.com>
> > + */
> > +
> > +#include <linux/clk-provider.h>
> > +#include <linux/errno.h>
> > +#include <linux/export.h>
> > +#include <linux/io.h>
> > +#include <linux/iopoll.h>
> > +#include <linux/slab.h>
> > +
> > +#include "clk.h"
> > +
> > +#define DIRECT_OFFSET		0x0
> > +
> > +/*
> > + * 0b000 - LPCG will be OFF in any CPU mode.
> > + * 0b100 - LPCG will be ON in any CPU mode.
> > + */
> > +#define LPM_SETTING_OFF		0x0
> > +#define LPM_SETTING_ON		0x4
> > +
> > +#define LPM_CUR_OFFSET		0x1c
> > +
> > +#define AUTHEN_OFFSET		0x30
> > +#define CPULPM_EN		BIT(2)
> > +#define TZ_NS_SHIFT		9
> > +#define TZ_NS_MASK		BIT(9)
> > +
> > +#define WHITE_LIST_SHIFT	16
> > +
> > +struct imx93_clk_gate {
> > +	struct clk_hw hw;
> > +	void __iomem	*reg;
> > +	u32		bit_idx;
> > +	u32		val;
> > +	u32		mask;
> > +	spinlock_t	*lock;
> > +	unsigned int	*share_count;
> > +};
> > +
> > +#define to_imx93_clk_gate(_hw) container_of(_hw, struct
> > +imx93_clk_gate, hw)
> > +
> > +static void imx93_clk_gate_do_hardware(struct clk_hw *hw, bool
> > +enable) {
> > +	struct imx93_clk_gate *gate = to_imx93_clk_gate(hw);
> > +	u32 val;
> > +
> > +	val = readl(gate->reg + AUTHEN_OFFSET);
> > +	if (val & CPULPM_EN) {
> > +		val = enable ? LPM_SETTING_ON : LPM_SETTING_OFF;
> > +		writel(val, gate->reg + LPM_CUR_OFFSET);
> > +	} else {
> > +		val = readl(gate->reg + DIRECT_OFFSET);
> > +		val &= ~(gate->mask << gate->bit_idx);
> > +		if (enable)
> > +			val |= (gate->val & gate->mask) << gate->bit_idx;
> > +		writel(val, gate->reg + DIRECT_OFFSET);
> > +	}
> > +}
> > +
> > +static int imx93_clk_gate_enable(struct clk_hw *hw) {
> > +	struct imx93_clk_gate *gate = to_imx93_clk_gate(hw);
> > +	unsigned long flags;
> > +
> > +	spin_lock_irqsave(gate->lock, flags);
> > +
> > +	if (gate->share_count && (*gate->share_count)++ > 0)
> > +		goto out;
> > +
> > +	imx93_clk_gate_do_hardware(hw, true);
> > +out:
> > +	spin_unlock_irqrestore(gate->lock, flags);
> > +
> > +	return 0;
> > +}
> 
> Just wondering if we could use the existing clk-gate2 since we would only
> have to implement the ops that are different there.
> 

I thought about this, but i.MX9 LPCG gate has a different design, it is
not i.MX8M CCGR gate. Although the first version of the i.MX93 clk
driver use clk-gate2, but it could not support i.MX93 well.

You could see i.MX93 gate API use different input parameters.

Clk-gate2 not support LPM(low power mode), AUTHEN(authentication), 
WHITE_LIST(domain control list).

i.MX93 LPCG has two working modes, DIRECT mode, LPM mode.
DIRECT mode is a 1 bit control bit if LPM is not enabled.
If LPM enabled, LPCG use a similar way as CCGR domain bits

> Also, would the next i.MX9 platforms also use this? Or will we have one
> similar driver for each new platform?

i.MX9 series use same LPCG design per my understanding. I hope
there are no big changes in hardware in future, so we could reuse
same driver.

Thanks,
Peng.
> 
> > +
> > +static void imx93_clk_gate_disable(struct clk_hw *hw) {
> > +	struct imx93_clk_gate *gate = to_imx93_clk_gate(hw);
> > +	unsigned long flags;
> > +
> > +	spin_lock_irqsave(gate->lock, flags);
> > +
> > +	if (gate->share_count) {
> > +		if (WARN_ON(*gate->share_count == 0))
> > +			goto out;
> > +		else if (--(*gate->share_count) > 0)
> > +			goto out;
> > +	}
> > +
> > +	imx93_clk_gate_do_hardware(hw, false);
> > +out:
> > +	spin_unlock_irqrestore(gate->lock, flags); }
> > +
> > +static int imx93_clk_gate_reg_is_enabled(struct imx93_clk_gate *gate)
> > +{
> > +	u32 val = readl(gate->reg + AUTHEN_OFFSET);
> > +
> > +	if (val & CPULPM_EN) {
> > +		val = readl(gate->reg + LPM_CUR_OFFSET);
> > +		if (val == LPM_SETTING_ON)
> > +			return 1;
> > +	} else {
> > +		val = readl(gate->reg);
> > +		if (((val >> gate->bit_idx) & gate->mask) == gate->val)
> > +			return 1;
> > +	}
> > +
> > +	return 0;
> > +}
> > +
> > +static int imx93_clk_gate_is_enabled(struct clk_hw *hw) {
> > +	struct imx93_clk_gate *gate = to_imx93_clk_gate(hw);
> > +	unsigned long flags;
> > +	int ret;
> > +
> > +	spin_lock_irqsave(gate->lock, flags);
> > +
> > +	ret = imx93_clk_gate_reg_is_enabled(gate);
> > +
> > +	spin_unlock_irqrestore(gate->lock, flags);
> > +
> > +	return ret;
> > +}
> > +
> > +static void imx93_clk_gate_disable_unused(struct clk_hw *hw) {
> > +	struct imx93_clk_gate *gate = to_imx93_clk_gate(hw);
> > +	unsigned long flags;
> > +
> > +	spin_lock_irqsave(gate->lock, flags);
> > +
> > +	if (!gate->share_count || *gate->share_count == 0)
> > +		imx93_clk_gate_do_hardware(hw, false);
> > +
> > +	spin_unlock_irqrestore(gate->lock, flags); }
> > +
> > +static const struct clk_ops imx93_clk_gate_ops = {
> > +	.enable = imx93_clk_gate_enable,
> > +	.disable = imx93_clk_gate_disable,
> > +	.disable_unused = imx93_clk_gate_disable_unused,
> > +	.is_enabled = imx93_clk_gate_is_enabled, };
> > +
> > +static const struct clk_ops imx93_clk_gate_ro_ops = {
> > +	.is_enabled = imx93_clk_gate_is_enabled, };
> > +
> > +struct clk_hw *imx93_clk_gate(struct device *dev, const char *name,
> const char *parent_name,
> > +			      unsigned long flags, void __iomem *reg, u32
> bit_idx, u32 val,
> > +			      u32 mask, u32 domain_id, unsigned int
> *share_count) {
> > +	struct imx93_clk_gate *gate;
> > +	struct clk_hw *hw;
> > +	struct clk_init_data init;
> > +	int ret;
> > +	u32 authen;
> > +
> > +	gate = kzalloc(sizeof(struct imx93_clk_gate), GFP_KERNEL);
> > +	if (!gate)
> > +		return ERR_PTR(-ENOMEM);
> > +
> > +	gate->reg = reg;
> > +	gate->lock = &imx_ccm_lock;
> > +	gate->bit_idx = bit_idx;
> > +	gate->val = val;
> > +	gate->mask = mask;
> > +	gate->share_count = share_count;
> > +
> > +	init.name = name;
> > +	init.ops = &imx93_clk_gate_ops;
> > +	init.flags = flags | CLK_SET_RATE_PARENT |
> CLK_OPS_PARENT_ENABLE;
> > +	init.parent_names = parent_name ? &parent_name : NULL;
> > +	init.num_parents = parent_name ? 1 : 0;
> > +
> > +	gate->hw.init = &init;
> > +	hw = &gate->hw;
> > +
> > +	authen = readl(reg + AUTHEN_OFFSET);
> > +	if (!(authen & TZ_NS_MASK) || !(authen & BIT(WHITE_LIST_SHIFT +
> domain_id)))
> > +		init.ops = &imx93_clk_gate_ro_ops;
> > +
> > +	ret = clk_hw_register(dev, hw);
> > +	if (ret) {
> > +		kfree(gate);
> > +		return ERR_PTR(ret);
> > +	}
> > +
> > +	return hw;
> > +}
> > +EXPORT_SYMBOL_GPL(imx93_clk_gate);
> > diff --git a/drivers/clk/imx/clk.h b/drivers/clk/imx/clk.h index
> > 396a5ea75083..dd49f90110e8 100644
> > --- a/drivers/clk/imx/clk.h
> > +++ b/drivers/clk/imx/clk.h
> > @@ -451,6 +451,10 @@ struct clk_hw *imx93_clk_composite_flags(const
> char *name,
> >  	imx93_clk_composite_flags(name, parent_names, num_parents,
> reg, domain_id \
> >  				  CLK_SET_RATE_NO_REPARENT |
> CLK_OPS_PARENT_ENABLE)
> >
> > +struct clk_hw *imx93_clk_gate(struct device *dev, const char *name,
> const char *parent_name,
> > +			      unsigned long flags, void __iomem *reg, u32
> bit_idx, u32 val,
> > +			      u32 mask, u32 domain_id, unsigned int
> *share_count);
> > +
> >  struct clk_hw *imx_clk_hw_divider_gate(const char *name, const char
> *parent_name,
> >  		unsigned long flags, void __iomem *reg, u8 shift, u8 width,
> >  		u8 clk_divider_flags, const struct clk_div_table *table,
> > --
> > 2.37.1
> >

^ permalink raw reply	[flat|nested] 19+ messages in thread

end of thread, other threads:[~2022-08-15  9:22 UTC | newest]

Thread overview: 19+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
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 ` [PATCH V2 1/8] dt-bindings: clock: imx93-clock: add more MU/SAI clocks Peng Fan (OSS)
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  8:16   ` Abel Vesa
2022-08-15  8:19     ` Peng Fan
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  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  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  9:07   ` Abel Vesa
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 ` [PATCH V2 7/8] clk: imx93: add MU1/2 clock Peng Fan (OSS)
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  9:12   ` Abel Vesa

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).