* [PATCH v3 1/4] of: add __of_device_is_status() and makes more generic status check
2023-11-30 2:14 [PATCH v3 0/4] drivers: clk: renesas: ignore all clocks which is assinged to non Linux system Kuninori Morimoto
@ 2023-11-30 2:14 ` Kuninori Morimoto
2023-11-30 14:36 ` Geert Uytterhoeven
2023-11-30 2:15 ` [PATCH v3 2/4] of: add of_get_next_status_child() and makes more generic of_get_next Kuninori Morimoto
` (2 subsequent siblings)
3 siblings, 1 reply; 9+ messages in thread
From: Kuninori Morimoto @ 2023-11-30 2:14 UTC (permalink / raw)
To: Frank Rowand, Geert Uytterhoeven, Michael Turquette, Rob Herring,
Stephen Boyd
Cc: Rob Herring, devicetree, linux-clk, linux-renesas-soc,
Aymeric Aillet, Yusuke Goda
Linux Kernel has __of_device_is_available() / __of_device_is_fail(),
these are checking if the status was "okay" / "ok" / "fail" / "fail-".
Add more generic __of_device_is_status() function for these.
Signed-off-by: Kuninori Morimoto <kuninori.morimoto.gx@renesas.com>
Tested-by: Yusuke Goda <yusuke.goda.sx@renesas.com>
Reviewed-by: Rob Herring <robh@kernel.org>
---
drivers/of/base.c | 57 ++++++++++++++++++++++++++++++-----------------
1 file changed, 36 insertions(+), 21 deletions(-)
diff --git a/drivers/of/base.c b/drivers/of/base.c
index 8d93cb6ea9cd..3cb467a7e747 100644
--- a/drivers/of/base.c
+++ b/drivers/of/base.c
@@ -415,15 +415,8 @@ int of_machine_is_compatible(const char *compat)
}
EXPORT_SYMBOL(of_machine_is_compatible);
-/**
- * __of_device_is_available - check if a device is available for use
- *
- * @device: Node to check for availability, with locks already held
- *
- * Return: True if the status property is absent or set to "okay" or "ok",
- * false otherwise
- */
-static bool __of_device_is_available(const struct device_node *device)
+static bool __of_device_is_status(const struct device_node *device,
+ const char * const*strings)
{
const char *status;
int statlen;
@@ -433,16 +426,45 @@ static bool __of_device_is_available(const struct device_node *device)
status = __of_get_property(device, "status", &statlen);
if (status == NULL)
- return true;
+ return false;
if (statlen > 0) {
- if (!strcmp(status, "okay") || !strcmp(status, "ok"))
- return true;
+ while (*strings) {
+ unsigned int len = strlen(*strings);
+
+ if ((*strings)[len - 1] == '-') {
+ if (!strncmp(status, *strings, len))
+ return true;
+ } else {
+ if (!strcmp(status, *strings))
+ return true;
+ }
+ strings++;
+ }
}
return false;
}
+/**
+ * __of_device_is_available - check if a device is available for use
+ *
+ * @device: Node to check for availability, with locks already held
+ *
+ * Return: True if the status property is absent or set to "okay" or "ok",
+ * false otherwise
+ */
+static bool __of_device_is_available(const struct device_node *device)
+{
+ static const char * const ok[] = {"okay", "ok", NULL};
+
+ if (!device)
+ return false;
+
+ return !__of_get_property(device, "status", NULL) ||
+ __of_device_is_status(device, ok);
+}
+
/**
* of_device_is_available - check if a device is available for use
*
@@ -474,16 +496,9 @@ EXPORT_SYMBOL(of_device_is_available);
*/
static bool __of_device_is_fail(const struct device_node *device)
{
- const char *status;
-
- if (!device)
- return false;
-
- status = __of_get_property(device, "status", NULL);
- if (status == NULL)
- return false;
+ static const char * const fail[] = {"fail", "fail-", NULL};
- return !strcmp(status, "fail") || !strncmp(status, "fail-", 5);
+ return __of_device_is_status(device, fail);
}
/**
--
2.25.1
^ permalink raw reply related [flat|nested] 9+ messages in thread* Re: [PATCH v3 1/4] of: add __of_device_is_status() and makes more generic status check
2023-11-30 2:14 ` [PATCH v3 1/4] of: add __of_device_is_status() and makes more generic status check Kuninori Morimoto
@ 2023-11-30 14:36 ` Geert Uytterhoeven
0 siblings, 0 replies; 9+ messages in thread
From: Geert Uytterhoeven @ 2023-11-30 14:36 UTC (permalink / raw)
To: Kuninori Morimoto
Cc: Frank Rowand, Geert Uytterhoeven, Michael Turquette, Rob Herring,
Stephen Boyd, Rob Herring, devicetree, linux-clk,
linux-renesas-soc, Aymeric Aillet, Yusuke Goda
On Thu, Nov 30, 2023 at 3:15 AM Kuninori Morimoto
<kuninori.morimoto.gx@renesas.com> wrote:
> Linux Kernel has __of_device_is_available() / __of_device_is_fail(),
> these are checking if the status was "okay" / "ok" / "fail" / "fail-".
>
> Add more generic __of_device_is_status() function for these.
>
> Signed-off-by: Kuninori Morimoto <kuninori.morimoto.gx@renesas.com>
> Tested-by: Yusuke Goda <yusuke.goda.sx@renesas.com>
> Reviewed-by: Rob Herring <robh@kernel.org>
Reviewed-by: Geert Uytterhoeven <geert+renesas@glider.be>
Gr{oetje,eeting}s,
Geert
--
Geert Uytterhoeven -- There's lots of Linux beyond ia32 -- geert@linux-m68k.org
In personal conversations with technical people, I call myself a hacker. But
when I'm talking to journalists I just say "programmer" or something like that.
-- Linus Torvalds
^ permalink raw reply [flat|nested] 9+ messages in thread
* [PATCH v3 2/4] of: add of_get_next_status_child() and makes more generic of_get_next
2023-11-30 2:14 [PATCH v3 0/4] drivers: clk: renesas: ignore all clocks which is assinged to non Linux system Kuninori Morimoto
2023-11-30 2:14 ` [PATCH v3 1/4] of: add __of_device_is_status() and makes more generic status check Kuninori Morimoto
@ 2023-11-30 2:15 ` Kuninori Morimoto
2023-11-30 14:37 ` Geert Uytterhoeven
2023-11-30 2:15 ` [PATCH v3 3/4] of: add for_each_reserved_child_of_node() Kuninori Morimoto
2023-11-30 2:15 ` [PATCH v3 4/4] drivers: clk: renesas: ignore all clocks which is assinged to non Linux system Kuninori Morimoto
3 siblings, 1 reply; 9+ messages in thread
From: Kuninori Morimoto @ 2023-11-30 2:15 UTC (permalink / raw)
To: Frank Rowand, Geert Uytterhoeven, Michael Turquette, Rob Herring,
Stephen Boyd
Cc: Rob Herring, devicetree, linux-clk, linux-renesas-soc,
Aymeric Aillet, Yusuke Goda
Linux Kernel has of_get_next_available_child().
Add more generic of_get_next_status_child() to enable to use same
logic for other status.
Signed-off-by: Kuninori Morimoto <kuninori.morimoto.gx@renesas.com>
Tested-by: Yusuke Goda <yusuke.goda.sx@renesas.com>
Reviewed-by: Rob Herring <robh@kernel.org>
---
drivers/of/base.c | 29 ++++++++++++++++++-----------
1 file changed, 18 insertions(+), 11 deletions(-)
diff --git a/drivers/of/base.c b/drivers/of/base.c
index 3cb467a7e747..25c841a3882f 100644
--- a/drivers/of/base.c
+++ b/drivers/of/base.c
@@ -612,16 +612,9 @@ struct device_node *of_get_next_child(const struct device_node *node,
}
EXPORT_SYMBOL(of_get_next_child);
-/**
- * of_get_next_available_child - Find the next available child node
- * @node: parent node
- * @prev: previous child of the parent node, or NULL to get first
- *
- * This function is like of_get_next_child(), except that it
- * automatically skips any disabled nodes (i.e. status = "disabled").
- */
-struct device_node *of_get_next_available_child(const struct device_node *node,
- struct device_node *prev)
+static struct device_node *of_get_next_status_child(const struct device_node *node,
+ struct device_node *prev,
+ bool (*checker)(const struct device_node *))
{
struct device_node *next;
unsigned long flags;
@@ -632,7 +625,7 @@ struct device_node *of_get_next_available_child(const struct device_node *node,
raw_spin_lock_irqsave(&devtree_lock, flags);
next = prev ? prev->sibling : node->child;
for (; next; next = next->sibling) {
- if (!__of_device_is_available(next))
+ if (!checker(next))
continue;
if (of_node_get(next))
break;
@@ -641,6 +634,20 @@ struct device_node *of_get_next_available_child(const struct device_node *node,
raw_spin_unlock_irqrestore(&devtree_lock, flags);
return next;
}
+
+/**
+ * of_get_next_available_child - Find the next available child node
+ * @node: parent node
+ * @prev: previous child of the parent node, or NULL to get first
+ *
+ * This function is like of_get_next_child(), except that it
+ * automatically skips any disabled nodes (i.e. status = "disabled").
+ */
+struct device_node *of_get_next_available_child(const struct device_node *node,
+ struct device_node *prev)
+{
+ return of_get_next_status_child(node, prev, __of_device_is_available);
+}
EXPORT_SYMBOL(of_get_next_available_child);
/**
--
2.25.1
^ permalink raw reply related [flat|nested] 9+ messages in thread* Re: [PATCH v3 2/4] of: add of_get_next_status_child() and makes more generic of_get_next
2023-11-30 2:15 ` [PATCH v3 2/4] of: add of_get_next_status_child() and makes more generic of_get_next Kuninori Morimoto
@ 2023-11-30 14:37 ` Geert Uytterhoeven
0 siblings, 0 replies; 9+ messages in thread
From: Geert Uytterhoeven @ 2023-11-30 14:37 UTC (permalink / raw)
To: Kuninori Morimoto
Cc: Frank Rowand, Michael Turquette, Rob Herring, Stephen Boyd,
Rob Herring, devicetree, linux-clk, linux-renesas-soc,
Aymeric Aillet, Yusuke Goda
On Thu, Nov 30, 2023 at 3:15 AM Kuninori Morimoto
<kuninori.morimoto.gx@renesas.com> wrote:
> Linux Kernel has of_get_next_available_child().
> Add more generic of_get_next_status_child() to enable to use same
> logic for other status.
>
> Signed-off-by: Kuninori Morimoto <kuninori.morimoto.gx@renesas.com>
> Tested-by: Yusuke Goda <yusuke.goda.sx@renesas.com>
> Reviewed-by: Rob Herring <robh@kernel.org>
Reviewed-by: Geert Uytterhoeven <geert+renesas@glider.be>
Gr{oetje,eeting}s,
Geert
--
Geert Uytterhoeven -- There's lots of Linux beyond ia32 -- geert@linux-m68k.org
In personal conversations with technical people, I call myself a hacker. But
when I'm talking to journalists I just say "programmer" or something like that.
-- Linus Torvalds
^ permalink raw reply [flat|nested] 9+ messages in thread
* [PATCH v3 3/4] of: add for_each_reserved_child_of_node()
2023-11-30 2:14 [PATCH v3 0/4] drivers: clk: renesas: ignore all clocks which is assinged to non Linux system Kuninori Morimoto
2023-11-30 2:14 ` [PATCH v3 1/4] of: add __of_device_is_status() and makes more generic status check Kuninori Morimoto
2023-11-30 2:15 ` [PATCH v3 2/4] of: add of_get_next_status_child() and makes more generic of_get_next Kuninori Morimoto
@ 2023-11-30 2:15 ` Kuninori Morimoto
2023-11-30 15:46 ` Geert Uytterhoeven
2023-11-30 2:15 ` [PATCH v3 4/4] drivers: clk: renesas: ignore all clocks which is assinged to non Linux system Kuninori Morimoto
3 siblings, 1 reply; 9+ messages in thread
From: Kuninori Morimoto @ 2023-11-30 2:15 UTC (permalink / raw)
To: Frank Rowand, Geert Uytterhoeven, Michael Turquette, Rob Herring,
Stephen Boyd
Cc: Rob Herring, devicetree, linux-clk, linux-renesas-soc,
Aymeric Aillet, Yusuke Goda
We would like to use for_each loop for status = "reserved" nodes.
Add for_each_reserved_child_of_node() for it.
Signed-off-by: Kuninori Morimoto <kuninori.morimoto.gx@renesas.com>
Tested-by: Yusuke Goda <yusuke.goda.sx@renesas.com>
---
drivers/of/base.c | 29 +++++++++++++++++++++++++++++
include/linux/of.h | 11 +++++++++++
2 files changed, 40 insertions(+)
diff --git a/drivers/of/base.c b/drivers/of/base.c
index 25c841a3882f..b1ecfcfbb90f 100644
--- a/drivers/of/base.c
+++ b/drivers/of/base.c
@@ -465,6 +465,20 @@ static bool __of_device_is_available(const struct device_node *device)
__of_device_is_status(device, ok);
}
+/**
+ * __of_device_is_reserved - check if a device is reserved
+ *
+ * @device: Node to check for availability, with locks already held
+ *
+ * Return: True if the status property is set to "reserved", false otherwise
+ */
+static bool __of_device_is_reserved(const struct device_node *device)
+{
+ static const char * const reserved[] = {"reserved", NULL};
+
+ return __of_device_is_status(device, reserved);
+}
+
/**
* of_device_is_available - check if a device is available for use
*
@@ -650,6 +664,21 @@ struct device_node *of_get_next_available_child(const struct device_node *node,
}
EXPORT_SYMBOL(of_get_next_available_child);
+/**
+ * of_get_next_reserved_child - Find the next reserved child node
+ * @node: parent node
+ * @prev: previous child of the parent node, or NULL to get first
+ *
+ * This function is like of_get_next_child(), except that it
+ * automatically skips any disabled nodes (i.e. status = "disabled").
+ */
+struct device_node *of_get_next_reserved_child(const struct device_node *node,
+ struct device_node *prev)
+{
+ return of_get_next_status_child(node, prev, __of_device_is_reserved);
+}
+EXPORT_SYMBOL(of_get_next_reserved_child);
+
/**
* of_get_next_cpu_node - Iterate on cpu nodes
* @prev: previous child of the /cpus node, or NULL to get first
diff --git a/include/linux/of.h b/include/linux/of.h
index 6a9ddf20e79a..331e05918f11 100644
--- a/include/linux/of.h
+++ b/include/linux/of.h
@@ -294,6 +294,8 @@ extern struct device_node *of_get_next_child(const struct device_node *node,
struct device_node *prev);
extern struct device_node *of_get_next_available_child(
const struct device_node *node, struct device_node *prev);
+extern struct device_node *of_get_next_reserved_child(
+ const struct device_node *node, struct device_node *prev);
extern struct device_node *of_get_compatible_child(const struct device_node *parent,
const char *compatible);
@@ -541,6 +543,12 @@ static inline struct device_node *of_get_next_available_child(
return NULL;
}
+static inline struct device_node *of_get_next_reserved_child(
+ const struct device_node *node, struct device_node *prev)
+{
+ return NULL;
+}
+
static inline struct device_node *of_find_node_with_property(
struct device_node *from, const char *prop_name)
{
@@ -1431,6 +1439,9 @@ static inline int of_property_read_s32(const struct device_node *np,
#define for_each_available_child_of_node(parent, child) \
for (child = of_get_next_available_child(parent, NULL); child != NULL; \
child = of_get_next_available_child(parent, child))
+#define for_each_reserved_child_of_node(parent, child) \
+ for (child = of_get_next_reserved_child(parent, NULL); child != NULL; \
+ child = of_get_next_reserved_child(parent, child))
#define for_each_of_cpu_node(cpu) \
for (cpu = of_get_next_cpu_node(NULL); cpu != NULL; \
--
2.25.1
^ permalink raw reply related [flat|nested] 9+ messages in thread* Re: [PATCH v3 3/4] of: add for_each_reserved_child_of_node()
2023-11-30 2:15 ` [PATCH v3 3/4] of: add for_each_reserved_child_of_node() Kuninori Morimoto
@ 2023-11-30 15:46 ` Geert Uytterhoeven
0 siblings, 0 replies; 9+ messages in thread
From: Geert Uytterhoeven @ 2023-11-30 15:46 UTC (permalink / raw)
To: Kuninori Morimoto
Cc: Frank Rowand, Michael Turquette, Rob Herring, Stephen Boyd,
Rob Herring, devicetree, linux-clk, linux-renesas-soc,
Aymeric Aillet, Yusuke Goda
On Thu, Nov 30, 2023 at 3:15 AM Kuninori Morimoto
<kuninori.morimoto.gx@renesas.com> wrote:
> We would like to use for_each loop for status = "reserved" nodes.
> Add for_each_reserved_child_of_node() for it.
>
> Signed-off-by: Kuninori Morimoto <kuninori.morimoto.gx@renesas.com>
> Tested-by: Yusuke Goda <yusuke.goda.sx@renesas.com>
Reviewed-by: Geert Uytterhoeven <geert+renesas@glider.be>
Gr{oetje,eeting}s,
Geert
--
Geert Uytterhoeven -- There's lots of Linux beyond ia32 -- geert@linux-m68k.org
In personal conversations with technical people, I call myself a hacker. But
when I'm talking to journalists I just say "programmer" or something like that.
-- Linus Torvalds
^ permalink raw reply [flat|nested] 9+ messages in thread
* [PATCH v3 4/4] drivers: clk: renesas: ignore all clocks which is assinged to non Linux system
2023-11-30 2:14 [PATCH v3 0/4] drivers: clk: renesas: ignore all clocks which is assinged to non Linux system Kuninori Morimoto
` (2 preceding siblings ...)
2023-11-30 2:15 ` [PATCH v3 3/4] of: add for_each_reserved_child_of_node() Kuninori Morimoto
@ 2023-11-30 2:15 ` Kuninori Morimoto
2023-12-05 10:55 ` Geert Uytterhoeven
3 siblings, 1 reply; 9+ messages in thread
From: Kuninori Morimoto @ 2023-11-30 2:15 UTC (permalink / raw)
To: Frank Rowand, Geert Uytterhoeven, Michael Turquette, Rob Herring,
Stephen Boyd
Cc: Rob Herring, devicetree, linux-clk, linux-renesas-soc,
Aymeric Aillet, Yusuke Goda
Some board might use Linux and another OS in the same time. In such
case, current Linux will stop necessary module clock when booting
which is not used on Linux side, but is used on another OS side.
To avoid such situation, renesas-cpg-mssr try to find
status = "reserved" devices (A), and add CLK_IGNORE_UNUSED flag to its
<&cgp CPG_MOD xxx> clock (B).
Table 2.4: Values for status property
https://github.com/devicetree-org/devicetree-specification/releases/download/v0.4/devicetree-specification-v0.4.pdf
"reserved"
Indicates that the device is operational, but should not be
used. Typically this is used for devices that are controlled
by another software component, such as platform firmware.
ex)
scif5: serial@e6f30000 {
...
(B) clocks = <&cpg CPG_MOD 202>,
<&cpg CPG_CORE R8A7795_CLK_S3D1>,
<&scif_clk>;
...
(A) status = "reserved";
};
Cc: Aymeric Aillet <aymeric.aillet@iot.bzh>
Signed-off-by: Kuninori Morimoto <kuninori.morimoto.gx@renesas.com>
Tested-by: Yusuke Goda <yusuke.goda.sx@renesas.com>
---
drivers/clk/renesas/renesas-cpg-mssr.c | 118 +++++++++++++++++++++++--
1 file changed, 109 insertions(+), 9 deletions(-)
diff --git a/drivers/clk/renesas/renesas-cpg-mssr.c b/drivers/clk/renesas/renesas-cpg-mssr.c
index cb80d1bf6c7c..26098b7f4323 100644
--- a/drivers/clk/renesas/renesas-cpg-mssr.c
+++ b/drivers/clk/renesas/renesas-cpg-mssr.c
@@ -142,6 +142,8 @@ static const u16 srstclr_for_gen4[] = {
* @reset_clear_regs: Pointer to reset clearing registers array
* @smstpcr_saved: [].mask: Mask of SMSTPCR[] bits under our control
* [].val: Saved values of SMSTPCR[]
+ * @reserved_ids: Temporary used, reserved id list
+ * @num_reserved_ids: Temporary used, number of reserved id list
* @clks: Array containing all Core and Module Clocks
*/
struct cpg_mssr_priv {
@@ -168,6 +170,9 @@ struct cpg_mssr_priv {
u32 val;
} smstpcr_saved[ARRAY_SIZE(mstpsr_for_gen4)];
+ unsigned int *reserved_ids;
+ unsigned int num_reserved_ids;
+
struct clk *clks[];
};
@@ -453,6 +458,19 @@ static void __init cpg_mssr_register_mod_clk(const struct mssr_mod_clk *mod,
break;
}
+ /*
+ * Ignore reserved device.
+ * see
+ * cpg_mssr_reserved_init()
+ */
+ for (i = 0; i < priv->num_reserved_ids; i++) {
+ if (id == priv->reserved_ids[i]) {
+ dev_info(dev, "Ignore Linux non-assigned mod (%s)\n", mod->name);
+ init.flags |= CLK_IGNORE_UNUSED;
+ break;
+ }
+ }
+
clk = clk_register(NULL, &clock->hw);
if (IS_ERR(clk))
goto fail;
@@ -949,6 +967,75 @@ static const struct dev_pm_ops cpg_mssr_pm = {
#define DEV_PM_OPS NULL
#endif /* CONFIG_PM_SLEEP && CONFIG_ARM_PSCI_FW */
+static void __init cpg_mssr_reserved_exit(struct cpg_mssr_priv *priv)
+{
+ kfree(priv->reserved_ids);
+}
+
+static int __init cpg_mssr_reserved_init(struct cpg_mssr_priv *priv,
+ const struct cpg_mssr_info *info)
+{
+ struct device_node *root = of_find_node_by_path("/soc");
+ struct device_node *node = NULL;
+ struct of_phandle_args clkspec;
+ unsigned int *ids = NULL;
+ unsigned int num = 0;
+
+ /*
+ * Because cpg_mssr_info has .num_hw_mod_clks which indicates number of all Module Clocks,
+ * and clk_disable_unused() will disable all unused clocks, the device which is assigned to
+ * non-Linux system will be disabled when Linux was booted.
+ *
+ * To avoid such situation, renesas-cpg-mssr assumes the device which has
+ * status = "reserved" is assigned to non-Linux system, and add CLK_IGNORE_UNUSED flag
+ * to its clocks if it was CPG_MOD.
+ * see also
+ * cpg_mssr_register_mod_clk()
+ *
+ * scif5: serial@e6f30000 {
+ * ...
+ * => clocks = <&cpg CPG_MOD 202>,
+ * <&cpg CPG_CORE R8A7795_CLK_S3D1>,
+ * <&scif_clk>;
+ * ...
+ * status = "reserved";
+ * };
+ */
+ for_each_reserved_child_of_node(root, node) {
+ unsigned int i = 0;
+
+ while (!of_parse_phandle_with_args(node, "clocks", "#clock-cells", i++, &clkspec)) {
+
+ of_node_put(clkspec.np);
+
+ if (clkspec.np == priv->dev->of_node &&
+ clkspec.args[0] == CPG_MOD) {
+
+ ids = krealloc_array(ids, (num + 1), sizeof(*ids), GFP_KERNEL);
+ if (!ids)
+ return -ENOMEM;
+
+ ids[num] = info->num_total_core_clks +
+ MOD_CLK_PACK(clkspec.args[1]);
+
+ num++;
+ }
+ }
+ }
+
+ priv->num_reserved_ids = num;
+ priv->reserved_ids = ids;
+
+ return 0;
+}
+
+static void __init cpg_mssr_common_exit(struct cpg_mssr_priv *priv)
+{
+ if (priv->base)
+ iounmap(priv->base);
+ kfree(priv);
+}
+
static int __init cpg_mssr_common_init(struct device *dev,
struct device_node *np,
const struct cpg_mssr_info *info)
@@ -1012,9 +1099,7 @@ static int __init cpg_mssr_common_init(struct device *dev,
return 0;
out_err:
- if (priv->base)
- iounmap(priv->base);
- kfree(priv);
+ cpg_mssr_common_exit(priv);
return error;
}
@@ -1029,6 +1114,10 @@ void __init cpg_mssr_early_init(struct device_node *np,
if (error)
return;
+ error = cpg_mssr_reserved_init(cpg_mssr_priv, info);
+ if (error)
+ goto err;
+
for (i = 0; i < info->num_early_core_clks; i++)
cpg_mssr_register_core_clk(&info->early_core_clks[i], info,
cpg_mssr_priv);
@@ -1037,6 +1126,12 @@ void __init cpg_mssr_early_init(struct device_node *np,
cpg_mssr_register_mod_clk(&info->early_mod_clks[i], info,
cpg_mssr_priv);
+ cpg_mssr_reserved_exit(cpg_mssr_priv);
+
+ return;
+
+err:
+ cpg_mssr_common_exit(cpg_mssr_priv);
}
static int __init cpg_mssr_probe(struct platform_device *pdev)
@@ -1060,6 +1155,10 @@ static int __init cpg_mssr_probe(struct platform_device *pdev)
priv->dev = dev;
dev_set_drvdata(dev, priv);
+ error = cpg_mssr_reserved_init(priv, info);
+ if (error)
+ return error;
+
for (i = 0; i < info->num_core_clks; i++)
cpg_mssr_register_core_clk(&info->core_clks[i], info, priv);
@@ -1070,22 +1169,23 @@ static int __init cpg_mssr_probe(struct platform_device *pdev)
cpg_mssr_del_clk_provider,
np);
if (error)
- return error;
+ goto reserve_err;
error = cpg_mssr_add_clk_domain(dev, info->core_pm_clks,
info->num_core_pm_clks);
if (error)
- return error;
+ goto reserve_err;
/* Reset Controller not supported for Standby Control SoCs */
if (priv->reg_layout == CLK_REG_LAYOUT_RZ_A)
- return 0;
+ goto reserve_err;
error = cpg_mssr_reset_controller_register(priv);
- if (error)
- return error;
- return 0;
+reserve_err:
+ cpg_mssr_reserved_exit(priv);
+
+ return error;
}
static struct platform_driver cpg_mssr_driver = {
--
2.25.1
^ permalink raw reply related [flat|nested] 9+ messages in thread* Re: [PATCH v3 4/4] drivers: clk: renesas: ignore all clocks which is assinged to non Linux system
2023-11-30 2:15 ` [PATCH v3 4/4] drivers: clk: renesas: ignore all clocks which is assinged to non Linux system Kuninori Morimoto
@ 2023-12-05 10:55 ` Geert Uytterhoeven
0 siblings, 0 replies; 9+ messages in thread
From: Geert Uytterhoeven @ 2023-12-05 10:55 UTC (permalink / raw)
To: Kuninori Morimoto
Cc: Frank Rowand, Geert Uytterhoeven, Michael Turquette, Rob Herring,
Stephen Boyd, Rob Herring, devicetree, linux-clk,
linux-renesas-soc, Aymeric Aillet, Yusuke Goda
Hi Morimoto-san,
Thanks for the update!
s/is assigned/are assigned/
s/non Linux/non-Linux/
On Thu, Nov 30, 2023 at 3:15 AM Kuninori Morimoto
<kuninori.morimoto.gx@renesas.com> wrote:
> Some board might use Linux and another OS in the same time. In such
boards ... at the same
> case, current Linux will stop necessary module clock when booting
> which is not used on Linux side, but is used on another OS side.
... currently, during booting, Linux will stop necessary module clocks
which are not used on the Linux side, but are used by another OS.
> To avoid such situation, renesas-cpg-mssr try to find
tries
> status = "reserved" devices (A), and add CLK_IGNORE_UNUSED flag to its
adds
> <&cgp CPG_MOD xxx> clock (B).
>
> Table 2.4: Values for status property
> https://github.com/devicetree-org/devicetree-specification/releases/download/v0.4/devicetree-specification-v0.4.pdf
>
> "reserved"
> Indicates that the device is operational, but should not be
> used. Typically this is used for devices that are controlled
> by another software component, such as platform firmware.
>
> ex)
> scif5: serial@e6f30000 {
> ...
> (B) clocks = <&cpg CPG_MOD 202>,
> <&cpg CPG_CORE R8A7795_CLK_S3D1>,
> <&scif_clk>;
> ...
> (A) status = "reserved";
> };
>
> Cc: Aymeric Aillet <aymeric.aillet@iot.bzh>
> Signed-off-by: Kuninori Morimoto <kuninori.morimoto.gx@renesas.com>
> Tested-by: Yusuke Goda <yusuke.goda.sx@renesas.com>
> --- a/drivers/clk/renesas/renesas-cpg-mssr.c
> +++ b/drivers/clk/renesas/renesas-cpg-mssr.c
@@ -453,6 +458,19 @@ static void __init
cpg_mssr_register_mod_clk(const struct mssr_mod_clk *mod,
> break;
> }
>
> + /*
> + * Ignore reserved device.
> + * see
> + * cpg_mssr_reserved_init()
> + */
> + for (i = 0; i < priv->num_reserved_ids; i++) {
> + if (id == priv->reserved_ids[i]) {
> + dev_info(dev, "Ignore Linux non-assigned mod (%s)\n", mod->name);
> + init.flags |= CLK_IGNORE_UNUSED;
> + break;
> + }
> + }
> +
> clk = clk_register(NULL, &clock->hw);
> if (IS_ERR(clk))
> goto fail;
> @@ -949,6 +967,75 @@ static const struct dev_pm_ops cpg_mssr_pm = {
> #define DEV_PM_OPS NULL
> #endif /* CONFIG_PM_SLEEP && CONFIG_ARM_PSCI_FW */
>
> +static void __init cpg_mssr_reserved_exit(struct cpg_mssr_priv *priv)
> +{
> + kfree(priv->reserved_ids);
> +}
> +
> +static int __init cpg_mssr_reserved_init(struct cpg_mssr_priv *priv,
> + const struct cpg_mssr_info *info)
> +{
> + struct device_node *root = of_find_node_by_path("/soc");
s/root/soc/
> + struct device_node *node = NULL;
No need to initialize node.
> + struct of_phandle_args clkspec;
> + unsigned int *ids = NULL;
> + unsigned int num = 0;
> +
> + /*
> + * Because cpg_mssr_info has .num_hw_mod_clks which indicates number of all Module Clocks,
> + * and clk_disable_unused() will disable all unused clocks, the device which is assigned to
"Because clk_disable_unused() will disable all unused clocks, ..."?
> + * non-Linux system will be disabled when Linux was booted.
a non-Linux
s/was/is/
> + *
> + * To avoid such situation, renesas-cpg-mssr assumes the device which has
> + * status = "reserved" is assigned to non-Linux system, and add CLK_IGNORE_UNUSED flag
a non-Linux ... adds
> + * to its clocks if it was CPG_MOD.
to its CPG_MOD clocks
> + * see also
> + * cpg_mssr_register_mod_clk()
> + *
> + * scif5: serial@e6f30000 {
> + * ...
> + * => clocks = <&cpg CPG_MOD 202>,
> + * <&cpg CPG_CORE R8A7795_CLK_S3D1>,
> + * <&scif_clk>;
> + * ...
> + * status = "reserved";
> + * };
> + */
> + for_each_reserved_child_of_node(root, node) {
> + unsigned int i = 0;
> +
> + while (!of_parse_phandle_with_args(node, "clocks", "#clock-cells", i++, &clkspec)) {
Looks like you missed Rob's comment on v2 to use of_for_each_phandle() instead?
> +
Please drop this blank line.
> + of_node_put(clkspec.np);
> +
> + if (clkspec.np == priv->dev->of_node &&
> + clkspec.args[0] == CPG_MOD) {
> +
Please drop this blank line.
> + ids = krealloc_array(ids, (num + 1), sizeof(*ids), GFP_KERNEL);
> + if (!ids)
> + return -ENOMEM;
> +
> + ids[num] = info->num_total_core_clks +
> + MOD_CLK_PACK(clkspec.args[1]);
This should use MOD_CLK_PACK_10() in case priv->reg_layout ==
CLK_REG_LAYOUT_RZ_A.
> +
> + num++;
> + }
> + }
> + }
> +
> + priv->num_reserved_ids = num;
> + priv->reserved_ids = ids;
> +
> + return 0;
> +}
> @@ -1029,6 +1114,10 @@ void __init cpg_mssr_early_init(struct device_node *np,
> if (error)
> return;
>
> + error = cpg_mssr_reserved_init(cpg_mssr_priv, info);
> + if (error)
> + goto err;
Please move this into cpg_mssr_common_init(), which is called above.
After that, there is no longer a need to factor out
cpg_mssr_common_exit().
> +
> for (i = 0; i < info->num_early_core_clks; i++)
> cpg_mssr_register_core_clk(&info->early_core_clks[i], info,
> cpg_mssr_priv);
> @@ -1037,6 +1126,12 @@ void __init cpg_mssr_early_init(struct device_node *np,
> cpg_mssr_register_mod_clk(&info->early_mod_clks[i], info,
> cpg_mssr_priv);
>
> + cpg_mssr_reserved_exit(cpg_mssr_priv);
Please drop this, as you still need this data when cpg_mssr_probe()
is called later (yes, when a driver uses cpg_mssr_early_init(),
cpg_mssr_probe() is still called later to register the non-early
clocks).
> +
> + return;
> +
> +err:
> + cpg_mssr_common_exit(cpg_mssr_priv);
> }
>
> static int __init cpg_mssr_probe(struct platform_device *pdev)
> @@ -1060,6 +1155,10 @@ static int __init cpg_mssr_probe(struct platform_device *pdev)
> priv->dev = dev;
> dev_set_drvdata(dev, priv);
>
> + error = cpg_mssr_reserved_init(priv, info);
> + if (error)
> + return error;
When a driver uses cpg_mssr_early_init(), this causes the reserved
clock list to be created a second time. Moving this handling into
cpg_mssr_common_init() would fix that.
> +
> for (i = 0; i < info->num_core_clks; i++)
> cpg_mssr_register_core_clk(&info->core_clks[i], info, priv);
>
Gr{oetje,eeting}s,
Geert
--
Geert Uytterhoeven -- There's lots of Linux beyond ia32 -- geert@linux-m68k.org
In personal conversations with technical people, I call myself a hacker. But
when I'm talking to journalists I just say "programmer" or something like that.
-- Linus Torvalds
^ permalink raw reply [flat|nested] 9+ messages in thread