summaryrefslogtreecommitdiff
path: root/drivers/clk/clk-qoriq.c
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/clk/clk-qoriq.c')
-rw-r--r--drivers/clk/clk-qoriq.c250
1 files changed, 210 insertions, 40 deletions
diff --git a/drivers/clk/clk-qoriq.c b/drivers/clk/clk-qoriq.c
index 5baa9e051110..a560edeb4b55 100644
--- a/drivers/clk/clk-qoriq.c
+++ b/drivers/clk/clk-qoriq.c
@@ -1,15 +1,15 @@
+// SPDX-License-Identifier: GPL-2.0-only
/*
* Copyright 2013 Freescale Semiconductor, Inc.
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License version 2 as
- * published by the Free Software Foundation.
+ * Copyright 2021 NXP
*
* clock driver for Freescale QorIQ SoCs.
*/
#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
+#include <dt-bindings/clock/fsl,qoriq-clockgen.h>
+#include <linux/cleanup.h>
#include <linux/clk.h>
#include <linux/clk-provider.h>
#include <linux/clkdev.h>
@@ -18,8 +18,8 @@
#include <linux/kernel.h>
#include <linux/module.h>
#include <linux/of_address.h>
-#include <linux/of_platform.h>
#include <linux/of.h>
+#include <linux/platform_device.h>
#include <linux/slab.h>
#define PLL_DIV1 0
@@ -34,6 +34,7 @@
#define CGA_PLL4 4 /* only on clockgen-1.0, which lacks CGB */
#define CGB_PLL1 4
#define CGB_PLL2 5
+#define MAX_PLL_DIV 32
struct clockgen_pll_div {
struct clk *clk;
@@ -41,7 +42,7 @@ struct clockgen_pll_div {
};
struct clockgen_pll {
- struct clockgen_pll_div div[8];
+ struct clockgen_pll_div div[MAX_PLL_DIV];
};
#define CLKSEL_VALID 1
@@ -79,7 +80,7 @@ struct clockgen_chipinfo {
const struct clockgen_muxinfo *cmux_groups[2];
const struct clockgen_muxinfo *hwaccel[NUM_HWACCEL];
void (*init_periph)(struct clockgen *cg);
- int cmux_to_group[NUM_CMUX]; /* -1 terminates if fewer than NUM_CMUX */
+ int cmux_to_group[NUM_CMUX + 1]; /* array should be -1 terminated */
u32 pll_mask; /* 1 << n bit set if PLL n is valid */
u32 flags; /* CG_xxx */
};
@@ -97,6 +98,7 @@ struct clockgen {
};
static struct clockgen clockgen;
+static bool add_cpufreq_dev __initdata;
static void cg_out(struct clockgen *cg, u32 val, u32 __iomem *reg)
{
@@ -245,6 +247,66 @@ static const struct clockgen_muxinfo clockgen2_cmux_cgb = {
},
};
+static const struct clockgen_muxinfo ls1021a_cmux = {
+ {
+ { CLKSEL_VALID, CGA_PLL1, PLL_DIV1 },
+ { CLKSEL_VALID, CGA_PLL1, PLL_DIV2 },
+ { CLKSEL_VALID, CGA_PLL1, PLL_DIV4 },
+ }
+};
+
+static const struct clockgen_muxinfo ls1028a_hwa1 = {
+ {
+ { CLKSEL_VALID, PLATFORM_PLL, PLL_DIV1 },
+ { CLKSEL_VALID, CGA_PLL1, PLL_DIV1 },
+ { CLKSEL_VALID, CGA_PLL1, PLL_DIV2 },
+ { CLKSEL_VALID, CGA_PLL1, PLL_DIV3 },
+ { CLKSEL_VALID, CGA_PLL1, PLL_DIV4 },
+ {},
+ { CLKSEL_VALID, CGA_PLL2, PLL_DIV2 },
+ { CLKSEL_VALID, CGA_PLL2, PLL_DIV3 },
+ },
+};
+
+static const struct clockgen_muxinfo ls1028a_hwa2 = {
+ {
+ { CLKSEL_VALID, PLATFORM_PLL, PLL_DIV1 },
+ { CLKSEL_VALID, CGA_PLL2, PLL_DIV1 },
+ { CLKSEL_VALID, CGA_PLL2, PLL_DIV2 },
+ { CLKSEL_VALID, CGA_PLL2, PLL_DIV3 },
+ { CLKSEL_VALID, CGA_PLL2, PLL_DIV4 },
+ {},
+ { CLKSEL_VALID, CGA_PLL1, PLL_DIV2 },
+ { CLKSEL_VALID, CGA_PLL1, PLL_DIV3 },
+ },
+};
+
+static const struct clockgen_muxinfo ls1028a_hwa3 = {
+ {
+ { CLKSEL_VALID, PLATFORM_PLL, PLL_DIV1 },
+ { CLKSEL_VALID, CGA_PLL1, PLL_DIV1 },
+ { CLKSEL_VALID, CGA_PLL1, PLL_DIV2 },
+ { CLKSEL_VALID, CGA_PLL1, PLL_DIV3 },
+ { CLKSEL_VALID, CGA_PLL1, PLL_DIV4 },
+ {},
+ { CLKSEL_VALID, CGA_PLL2, PLL_DIV2 },
+ { CLKSEL_VALID, CGA_PLL2, PLL_DIV3 },
+ },
+};
+
+static const struct clockgen_muxinfo ls1028a_hwa4 = {
+ {
+ { CLKSEL_VALID, PLATFORM_PLL, PLL_DIV1 },
+ { CLKSEL_VALID, CGA_PLL2, PLL_DIV1 },
+ { CLKSEL_VALID, CGA_PLL2, PLL_DIV2 },
+ { CLKSEL_VALID, CGA_PLL2, PLL_DIV3 },
+ { CLKSEL_VALID, CGA_PLL2, PLL_DIV4 },
+ {},
+ { CLKSEL_VALID, CGA_PLL1, PLL_DIV2 },
+ { CLKSEL_VALID, CGA_PLL1, PLL_DIV3 },
+ },
+};
+
static const struct clockgen_muxinfo ls1043a_hwa1 = {
{
{},
@@ -292,6 +354,32 @@ static const struct clockgen_muxinfo ls1046a_hwa2 = {
},
};
+static const struct clockgen_muxinfo ls1088a_hwa1 = {
+ {
+ {},
+ { CLKSEL_VALID, CGA_PLL1, PLL_DIV1 },
+ { CLKSEL_VALID, CGA_PLL1, PLL_DIV2 },
+ { CLKSEL_VALID, CGA_PLL1, PLL_DIV3 },
+ { CLKSEL_VALID, CGA_PLL1, PLL_DIV4 },
+ {},
+ { CLKSEL_VALID, CGA_PLL2, PLL_DIV2 },
+ { CLKSEL_VALID, CGA_PLL2, PLL_DIV3 },
+ },
+};
+
+static const struct clockgen_muxinfo ls1088a_hwa2 = {
+ {
+ {},
+ { CLKSEL_VALID, CGA_PLL2, PLL_DIV1 },
+ { CLKSEL_VALID, CGA_PLL2, PLL_DIV2 },
+ { CLKSEL_VALID, CGA_PLL2, PLL_DIV3 },
+ { CLKSEL_VALID, CGA_PLL2, PLL_DIV4 },
+ {},
+ { CLKSEL_VALID, CGA_PLL1, PLL_DIV2 },
+ { CLKSEL_VALID, CGA_PLL1, PLL_DIV3 },
+ },
+};
+
static const struct clockgen_muxinfo ls1012a_cmux = {
{
[0] = { CLKSEL_VALID, CGA_PLL1, PLL_DIV1 },
@@ -478,7 +566,9 @@ static const struct clockgen_chipinfo chipinfo[] = {
.cmux_to_group = {
0, 1, 1, 1, -1
},
- .pll_mask = 0x3f,
+ .pll_mask = BIT(PLATFORM_PLL) |
+ BIT(CGA_PLL1) | BIT(CGA_PLL2) | BIT(CGA_PLL3) |
+ BIT(CGB_PLL1) | BIT(CGB_PLL2),
.flags = CG_PLL_8BIT,
},
{
@@ -494,18 +584,37 @@ static const struct clockgen_chipinfo chipinfo[] = {
.cmux_to_group = {
0, 1, 1, 1, -1
},
- .pll_mask = 0x3f,
+ .pll_mask = BIT(PLATFORM_PLL) |
+ BIT(CGA_PLL1) | BIT(CGA_PLL2) | BIT(CGA_PLL3) |
+ BIT(CGB_PLL1) | BIT(CGB_PLL2),
.flags = CG_PLL_8BIT,
},
{
.compat = "fsl,ls1021a-clockgen",
.cmux_groups = {
- &t1023_cmux
+ &ls1021a_cmux
},
.cmux_to_group = {
0, -1
},
- .pll_mask = 0x03,
+ .pll_mask = BIT(PLATFORM_PLL) |
+ BIT(CGA_PLL1) | BIT(CGA_PLL2),
+ },
+ {
+ .compat = "fsl,ls1028a-clockgen",
+ .cmux_groups = {
+ &clockgen2_cmux_cga12
+ },
+ .hwaccel = {
+ &ls1028a_hwa1, &ls1028a_hwa2,
+ &ls1028a_hwa3, &ls1028a_hwa4
+ },
+ .cmux_to_group = {
+ 0, 0, 0, 0, -1
+ },
+ .pll_mask = BIT(PLATFORM_PLL) |
+ BIT(CGA_PLL1) | BIT(CGA_PLL2),
+ .flags = CG_VER3 | CG_LITTLE_ENDIAN,
},
{
.compat = "fsl,ls1043a-clockgen",
@@ -519,7 +628,8 @@ static const struct clockgen_chipinfo chipinfo[] = {
.cmux_to_group = {
0, -1
},
- .pll_mask = 0x07,
+ .pll_mask = BIT(PLATFORM_PLL) |
+ BIT(CGA_PLL1) | BIT(CGA_PLL2),
.flags = CG_PLL_8BIT,
},
{
@@ -534,7 +644,8 @@ static const struct clockgen_chipinfo chipinfo[] = {
.cmux_to_group = {
0, -1
},
- .pll_mask = 0x07,
+ .pll_mask = BIT(PLATFORM_PLL) |
+ BIT(CGA_PLL1) | BIT(CGA_PLL2),
.flags = CG_PLL_8BIT,
},
{
@@ -542,10 +653,14 @@ static const struct clockgen_chipinfo chipinfo[] = {
.cmux_groups = {
&clockgen2_cmux_cga12
},
+ .hwaccel = {
+ &ls1088a_hwa1, &ls1088a_hwa2
+ },
.cmux_to_group = {
0, 0, -1
},
- .pll_mask = 0x07,
+ .pll_mask = BIT(PLATFORM_PLL) |
+ BIT(CGA_PLL1) | BIT(CGA_PLL2),
.flags = CG_VER3 | CG_LITTLE_ENDIAN,
},
{
@@ -556,7 +671,7 @@ static const struct clockgen_chipinfo chipinfo[] = {
.cmux_to_group = {
0, -1
},
- .pll_mask = 0x03,
+ .pll_mask = BIT(PLATFORM_PLL) | BIT(CGA_PLL1),
},
{
.compat = "fsl,ls2080a-clockgen",
@@ -566,7 +681,22 @@ static const struct clockgen_chipinfo chipinfo[] = {
.cmux_to_group = {
0, 0, 1, 1, -1
},
- .pll_mask = 0x37,
+ .pll_mask = BIT(PLATFORM_PLL) |
+ BIT(CGA_PLL1) | BIT(CGA_PLL2) |
+ BIT(CGB_PLL1) | BIT(CGB_PLL2),
+ .flags = CG_VER3 | CG_LITTLE_ENDIAN,
+ },
+ {
+ .compat = "fsl,lx2160a-clockgen",
+ .cmux_groups = {
+ &clockgen2_cmux_cga12, &clockgen2_cmux_cgb
+ },
+ .cmux_to_group = {
+ 0, 0, 0, 0, 1, 1, 1, 1, -1
+ },
+ .pll_mask = BIT(PLATFORM_PLL) |
+ BIT(CGA_PLL1) | BIT(CGA_PLL2) |
+ BIT(CGB_PLL1) | BIT(CGB_PLL2),
.flags = CG_VER3 | CG_LITTLE_ENDIAN,
},
{
@@ -579,7 +709,8 @@ static const struct clockgen_chipinfo chipinfo[] = {
.cmux_to_group = {
0, 0, 1, 1, -1
},
- .pll_mask = 0x07,
+ .pll_mask = BIT(PLATFORM_PLL) |
+ BIT(CGA_PLL1) | BIT(CGA_PLL2),
},
{
.compat = "fsl,p3041-clockgen",
@@ -591,7 +722,8 @@ static const struct clockgen_chipinfo chipinfo[] = {
.cmux_to_group = {
0, 0, 1, 1, -1
},
- .pll_mask = 0x07,
+ .pll_mask = BIT(PLATFORM_PLL) |
+ BIT(CGA_PLL1) | BIT(CGA_PLL2),
},
{
.compat = "fsl,p4080-clockgen",
@@ -601,21 +733,24 @@ static const struct clockgen_chipinfo chipinfo[] = {
&p4080_cmux_grp1, &p4080_cmux_grp2
},
.cmux_to_group = {
- 0, 0, 0, 0, 1, 1, 1, 1
+ 0, 0, 0, 0, 1, 1, 1, 1, -1
},
- .pll_mask = 0x1f,
+ .pll_mask = BIT(PLATFORM_PLL) |
+ BIT(CGA_PLL1) | BIT(CGA_PLL2) |
+ BIT(CGA_PLL3) | BIT(CGA_PLL4),
},
{
.compat = "fsl,p5020-clockgen",
.guts_compat = "fsl,qoriq-device-config-1.0",
.init_periph = p5020_init_periph,
.cmux_groups = {
- &p2041_cmux_grp1, &p2041_cmux_grp2
+ &p5020_cmux_grp1, &p5020_cmux_grp2
},
.cmux_to_group = {
0, 1, -1
},
- .pll_mask = 0x07,
+ .pll_mask = BIT(PLATFORM_PLL) |
+ BIT(CGA_PLL1) | BIT(CGA_PLL2),
},
{
.compat = "fsl,p5040-clockgen",
@@ -627,7 +762,8 @@ static const struct clockgen_chipinfo chipinfo[] = {
.cmux_to_group = {
0, 0, 1, 1, -1
},
- .pll_mask = 0x0f,
+ .pll_mask = BIT(PLATFORM_PLL) |
+ BIT(CGA_PLL1) | BIT(CGA_PLL2) | BIT(CGA_PLL3),
},
{
.compat = "fsl,t1023-clockgen",
@@ -642,7 +778,7 @@ static const struct clockgen_chipinfo chipinfo[] = {
.cmux_to_group = {
0, 0, -1
},
- .pll_mask = 0x03,
+ .pll_mask = BIT(PLATFORM_PLL) | BIT(CGA_PLL1),
.flags = CG_PLL_8BIT,
},
{
@@ -655,7 +791,8 @@ static const struct clockgen_chipinfo chipinfo[] = {
.cmux_to_group = {
0, 0, 0, 0, -1
},
- .pll_mask = 0x07,
+ .pll_mask = BIT(PLATFORM_PLL) |
+ BIT(CGA_PLL1) | BIT(CGA_PLL2),
.flags = CG_PLL_8BIT,
},
{
@@ -671,7 +808,8 @@ static const struct clockgen_chipinfo chipinfo[] = {
.cmux_to_group = {
0, -1
},
- .pll_mask = 0x07,
+ .pll_mask = BIT(PLATFORM_PLL) |
+ BIT(CGA_PLL1) | BIT(CGA_PLL2),
.flags = CG_PLL_8BIT,
},
{
@@ -687,7 +825,9 @@ static const struct clockgen_chipinfo chipinfo[] = {
.cmux_to_group = {
0, 0, 1, -1
},
- .pll_mask = 0x3f,
+ .pll_mask = BIT(PLATFORM_PLL) |
+ BIT(CGA_PLL1) | BIT(CGA_PLL2) | BIT(CGA_PLL3) |
+ BIT(CGB_PLL1) | BIT(CGB_PLL2),
.flags = CG_PLL_8BIT,
},
{},
@@ -739,6 +879,7 @@ static u8 mux_get_parent(struct clk_hw *hw)
}
static const struct clk_ops cmux_ops = {
+ .determine_rate = clk_hw_determine_rate_no_reparent,
.get_parent = mux_get_parent,
.set_parent = mux_set_parent,
};
@@ -914,7 +1055,7 @@ static void __init create_muxes(struct clockgen *cg)
}
}
-static void __init clockgen_init(struct device_node *np);
+static void __init _clockgen_init(struct device_node *np, bool legacy);
/*
* Legacy nodes may get probed before the parent clockgen node.
@@ -924,8 +1065,10 @@ static void __init clockgen_init(struct device_node *np);
*/
static void __init legacy_init_clockgen(struct device_node *np)
{
- if (!clockgen.node)
- clockgen_init(of_get_parent(np));
+ if (!clockgen.node) {
+ struct device_node *parent_np __free(device_node) = of_get_parent(np);
+ _clockgen_init(parent_np, true);
+ }
}
/* Legacy node */
@@ -1020,6 +1163,7 @@ static struct clk * __init create_sysclk(const char *name)
sysclk = of_get_child_by_name(clockgen.node, "sysclk");
if (sysclk) {
clk = sysclk_from_fixed(sysclk, name);
+ of_node_put(sysclk);
if (!IS_ERR(clk))
return clk;
}
@@ -1128,7 +1272,7 @@ static void __init create_one_pll(struct clockgen *cg, int idx)
int ret;
/*
- * For platform PLL, there are 8 divider clocks.
+ * For platform PLL, there are MAX_PLL_DIV divider clocks.
* For core PLL, there are 4 divider clocks at most.
*/
if (idx != PLATFORM_PLL && i >= 4)
@@ -1148,8 +1292,8 @@ static void __init create_one_pll(struct clockgen *cg, int idx)
pll->div[i].clk = clk;
ret = clk_register_clkdev(clk, pll->div[i].name, NULL);
if (ret != 0)
- pr_err("%s: %s: register to lookup table failed %ld\n",
- __func__, pll->div[i].name, PTR_ERR(clk));
+ pr_err("%s: %s: register to lookup table failed %d\n",
+ __func__, pll->div[i].name, ret);
}
}
@@ -1254,33 +1398,33 @@ static struct clk *clockgen_clk_get(struct of_phandle_args *clkspec, void *data)
idx = clkspec->args[1];
switch (type) {
- case 0:
+ case QORIQ_CLK_SYSCLK:
if (idx != 0)
goto bad_args;
clk = cg->sysclk;
break;
- case 1:
+ case QORIQ_CLK_CMUX:
if (idx >= ARRAY_SIZE(cg->cmux))
goto bad_args;
clk = cg->cmux[idx];
break;
- case 2:
+ case QORIQ_CLK_HWACCEL:
if (idx >= ARRAY_SIZE(cg->hwaccel))
goto bad_args;
clk = cg->hwaccel[idx];
break;
- case 3:
+ case QORIQ_CLK_FMAN:
if (idx >= ARRAY_SIZE(cg->fman))
goto bad_args;
clk = cg->fman[idx];
break;
- case 4:
+ case QORIQ_CLK_PLATFORM_PLL:
pll = &cg->pll[PLATFORM_PLL];
if (idx >= ARRAY_SIZE(pll->div))
goto bad_args;
clk = pll->div[idx].clk;
break;
- case 5:
+ case QORIQ_CLK_CORECLK:
if (idx != 0)
goto bad_args;
clk = cg->coreclk;
@@ -1342,7 +1486,7 @@ static bool __init has_erratum_a4510(void)
}
#endif
-static void __init clockgen_init(struct device_node *np)
+static void __init _clockgen_init(struct device_node *np, bool legacy)
{
int i, ret;
bool is_old_ls1021a = false;
@@ -1389,6 +1533,7 @@ static void __init clockgen_init(struct device_node *np)
pr_err("%s: Couldn't map %pOF regs\n", __func__,
guts);
}
+ of_node_put(guts);
}
}
@@ -1410,22 +1555,47 @@ static void __init clockgen_init(struct device_node *np)
__func__, np, ret);
}
+ /* Don't create cpufreq device for legacy clockgen blocks */
+ add_cpufreq_dev = !legacy;
+
return;
err:
iounmap(clockgen.regs);
clockgen.regs = NULL;
}
+static void __init clockgen_init(struct device_node *np)
+{
+ _clockgen_init(np, false);
+}
+
+static int __init clockgen_cpufreq_init(void)
+{
+ struct platform_device *pdev;
+
+ if (add_cpufreq_dev) {
+ pdev = platform_device_register_simple("qoriq-cpufreq", -1,
+ NULL, 0);
+ if (IS_ERR(pdev))
+ pr_err("Couldn't register qoriq-cpufreq err=%ld\n",
+ PTR_ERR(pdev));
+ }
+ return 0;
+}
+device_initcall(clockgen_cpufreq_init);
+
CLK_OF_DECLARE(qoriq_clockgen_1, "fsl,qoriq-clockgen-1.0", clockgen_init);
CLK_OF_DECLARE(qoriq_clockgen_2, "fsl,qoriq-clockgen-2.0", clockgen_init);
CLK_OF_DECLARE(qoriq_clockgen_b4420, "fsl,b4420-clockgen", clockgen_init);
CLK_OF_DECLARE(qoriq_clockgen_b4860, "fsl,b4860-clockgen", clockgen_init);
CLK_OF_DECLARE(qoriq_clockgen_ls1012a, "fsl,ls1012a-clockgen", clockgen_init);
CLK_OF_DECLARE(qoriq_clockgen_ls1021a, "fsl,ls1021a-clockgen", clockgen_init);
+CLK_OF_DECLARE(qoriq_clockgen_ls1028a, "fsl,ls1028a-clockgen", clockgen_init);
CLK_OF_DECLARE(qoriq_clockgen_ls1043a, "fsl,ls1043a-clockgen", clockgen_init);
CLK_OF_DECLARE(qoriq_clockgen_ls1046a, "fsl,ls1046a-clockgen", clockgen_init);
CLK_OF_DECLARE(qoriq_clockgen_ls1088a, "fsl,ls1088a-clockgen", clockgen_init);
CLK_OF_DECLARE(qoriq_clockgen_ls2080a, "fsl,ls2080a-clockgen", clockgen_init);
+CLK_OF_DECLARE(qoriq_clockgen_lx2160a, "fsl,lx2160a-clockgen", clockgen_init);
CLK_OF_DECLARE(qoriq_clockgen_p2041, "fsl,p2041-clockgen", clockgen_init);
CLK_OF_DECLARE(qoriq_clockgen_p3041, "fsl,p3041-clockgen", clockgen_init);
CLK_OF_DECLARE(qoriq_clockgen_p4080, "fsl,p4080-clockgen", clockgen_init);