[PATCH] clk: imx: imx93: introduce clk_bypassed module parameter

From: Peng Fan (OSS)
Date: Thu May 04 2023 - 04:50:16 EST


From: Peng Fan <peng.fan@xxxxxxx>

With the clk names specified in clk_bypassed module parameter, give
user an option to bypass the clk from managing them by Linux kernel.

This is useful when Cortex-M33 and Cortex-A55 both running, A55 may
shutdown the clocks used by M33. Although we have mcore_booted module
parameter, but it is only for composite gate, the CCGR gate could still
be shutdown by Linux.

So let's use clk_bypassed parameter to handle clk root and clk ccgr both.

Signed-off-by: Peng Fan <peng.fan@xxxxxxx>
---

V1:
Depends on: https://lore.kernel.org/all/20230504075754.372780-1-peng.fan@xxxxxxxxxxx/

drivers/clk/imx/clk-imx93.c | 55 +++++++++++++++++++++++++++++++++++++
1 file changed, 55 insertions(+)

diff --git a/drivers/clk/imx/clk-imx93.c b/drivers/clk/imx/clk-imx93.c
index 07b4a043e449..88ed824ca2ff 100644
--- a/drivers/clk/imx/clk-imx93.c
+++ b/drivers/clk/imx/clk-imx93.c
@@ -255,6 +255,51 @@ static const struct imx93_clk_ccgr {
static struct clk_hw_onecell_data *clk_hw_data;
static struct clk_hw **clks;

+#define IMX_NUM_CLK_ENTRY 64
+
+static char clk_bypassed_names[SZ_512];
+static char *clk_names[IMX_NUM_CLK_ENTRY];
+
+/* The module args format as this: clk-imx93.clk_bypassed="lpi2c8_root,spdif" */
+static int imx_clk_bypass_setup(struct device *dev, char *str)
+{
+ char *pos = str, *next;
+ int i = 0;
+
+ while (pos != NULL && (next = strchr(pos, ',')) != NULL) {
+ clk_names[i++] = devm_kstrndup(dev, pos, next - pos, GFP_KERNEL);
+ pos = ++next;
+ }
+
+ clk_names[i] = devm_kstrdup(dev, pos, GFP_KERNEL);
+
+ return 0;
+}
+
+static bool imx_clk_bypass_check(char *name)
+{
+ int i;
+
+ for (i = 0; i < IMX_NUM_CLK_ENTRY; i++) {
+ if (!clk_names[i])
+ return false;
+ if (!strcmp(name, clk_names[i]))
+ return true;
+ }
+
+ return false;
+}
+
+static int imx_clk_bypass_free(struct device *dev)
+{
+ int i;
+
+ for (i = 0; i < IMX_NUM_CLK_ENTRY; i++)
+ devm_kfree(dev, clk_names[i]);
+
+ return 0;
+}
+
static int imx93_clocks_probe(struct platform_device *pdev)
{
struct device *dev = &pdev->dev;
@@ -264,6 +309,8 @@ static int imx93_clocks_probe(struct platform_device *pdev)
void __iomem *base, *anatop_base;
int i, ret;

+ imx_clk_bypass_setup(dev, clk_bypassed_names);
+
clk_hw_data = kzalloc(struct_size(clk_hw_data, hws,
IMX93_CLK_END), GFP_KERNEL);
if (!clk_hw_data)
@@ -310,6 +357,8 @@ static int imx93_clocks_probe(struct platform_device *pdev)

for (i = 0; i < ARRAY_SIZE(root_array); i++) {
root = &root_array[i];
+ if (unlikely(imx_clk_bypass_check(root->name)))
+ continue;
clks[root->clk] = imx93_clk_composite_flags(root->name,
parent_names[root->sel],
4, base + root->off, 3,
@@ -318,6 +367,8 @@ static int imx93_clocks_probe(struct platform_device *pdev)

for (i = 0; i < ARRAY_SIZE(ccgr_array); i++) {
ccgr = &ccgr_array[i];
+ if (unlikely(imx_clk_bypass_check(ccgr->name)))
+ continue;
clks[ccgr->clk] = imx93_clk_gate(NULL, ccgr->name, ccgr->parent_name,
ccgr->flags, base + ccgr->off, 0, 1, 1, 3,
ccgr->shared_count);
@@ -341,6 +392,8 @@ static int imx93_clocks_probe(struct platform_device *pdev)

imx_register_uart_clocks();

+ imx_clk_bypass_free(dev);
+
return 0;

unregister_hws:
@@ -367,6 +420,8 @@ static struct platform_driver imx93_clk_driver = {
module_platform_driver(imx93_clk_driver);
module_param(mcore_booted, bool, 0444);
MODULE_PARM_DESC(mcore_booted, "See Cortex-M core is booted or not");
+module_param_string(clk_bypassed, clk_bypassed_names, SZ_512, 0444);
+MODULE_PARM_DESC(clk_bypassed, "The clks will not be managed by Linux");

MODULE_DESCRIPTION("NXP i.MX93 clock driver");
MODULE_LICENSE("GPL v2");
--
2.37.1