aboutsummaryrefslogtreecommitdiffstats
path: root/target/linux/layerscape/patches-4.9/802-clk-support-layerscape.patch
diff options
context:
space:
mode:
Diffstat (limited to 'target/linux/layerscape/patches-4.9/802-clk-support-layerscape.patch')
-rw-r--r--target/linux/layerscape/patches-4.9/802-clk-support-layerscape.patch312
1 files changed, 312 insertions, 0 deletions
diff --git a/target/linux/layerscape/patches-4.9/802-clk-support-layerscape.patch b/target/linux/layerscape/patches-4.9/802-clk-support-layerscape.patch
new file mode 100644
index 0000000000..881e3848b4
--- /dev/null
+++ b/target/linux/layerscape/patches-4.9/802-clk-support-layerscape.patch
@@ -0,0 +1,312 @@
+From bd3df6d053a28d5aa630524c9087c21def30e764 Mon Sep 17 00:00:00 2001
+From: Yangbo Lu <yangbo.lu@nxp.com>
+Date: Mon, 25 Sep 2017 12:09:35 +0800
+Subject: [PATCH] clk: support layerscape
+
+This is a integrated patch for layerscape clock support.
+
+Signed-off-by: Yuantian Tang <andy.tang@nxp.com>
+Signed-off-by: Mingkai Hu <mingkai.hu@nxp.com>
+Signed-off-by: Scott Wood <oss@buserror.net>
+Signed-off-by: Yangbo Lu <yangbo.lu@nxp.com>
+---
+ drivers/clk/clk-qoriq.c | 170 ++++++++++++++++++++++++++++++++++++++++++++----
+ 1 file changed, 156 insertions(+), 14 deletions(-)
+
+diff --git a/drivers/clk/clk-qoriq.c b/drivers/clk/clk-qoriq.c
+index 80ae2a51..0e7de00a 100644
+--- a/drivers/clk/clk-qoriq.c
++++ b/drivers/clk/clk-qoriq.c
+@@ -12,6 +12,7 @@
+
+ #include <linux/clk.h>
+ #include <linux/clk-provider.h>
++#include <linux/clkdev.h>
+ #include <linux/fsl/guts.h>
+ #include <linux/io.h>
+ #include <linux/kernel.h>
+@@ -87,7 +88,7 @@ struct clockgen {
+ struct device_node *node;
+ void __iomem *regs;
+ struct clockgen_chipinfo info; /* mutable copy */
+- struct clk *sysclk;
++ struct clk *sysclk, *coreclk;
+ struct clockgen_pll pll[6];
+ struct clk *cmux[NUM_CMUX];
+ struct clk *hwaccel[NUM_HWACCEL];
+@@ -266,6 +267,39 @@ static const struct clockgen_muxinfo ls1043a_hwa2 = {
+ },
+ };
+
++static const struct clockgen_muxinfo ls1046a_hwa1 = {
++ {
++ {},
++ {},
++ { CLKSEL_VALID, CGA_PLL1, PLL_DIV2 },
++ { CLKSEL_VALID, CGA_PLL1, PLL_DIV3 },
++ { CLKSEL_VALID, CGA_PLL1, PLL_DIV4 },
++ { CLKSEL_VALID, PLATFORM_PLL, PLL_DIV1 },
++ { CLKSEL_VALID, CGA_PLL2, PLL_DIV2 },
++ { CLKSEL_VALID, CGA_PLL2, PLL_DIV3 },
++ },
++};
++
++static const struct clockgen_muxinfo ls1046a_hwa2 = {
++ {
++ {},
++ { CLKSEL_VALID, CGA_PLL2, PLL_DIV1 },
++ { CLKSEL_VALID, CGA_PLL2, PLL_DIV2 },
++ { CLKSEL_VALID, CGA_PLL2, PLL_DIV3 },
++ {},
++ {},
++ { CLKSEL_VALID, CGA_PLL1, PLL_DIV2 },
++ },
++};
++
++static const struct clockgen_muxinfo ls1012a_cmux = {
++ {
++ [0] = { CLKSEL_VALID, CGA_PLL1, PLL_DIV1 },
++ {},
++ [2] = { CLKSEL_VALID, CGA_PLL1, PLL_DIV2 },
++ }
++};
++
+ static const struct clockgen_muxinfo t1023_hwa1 = {
+ {
+ {},
+@@ -488,6 +522,42 @@ static const struct clockgen_chipinfo chipinfo[] = {
+ .pll_mask = 0x07,
+ .flags = CG_PLL_8BIT,
+ },
++ {
++ .compat = "fsl,ls1046a-clockgen",
++ .init_periph = t2080_init_periph,
++ .cmux_groups = {
++ &t1040_cmux
++ },
++ .hwaccel = {
++ &ls1046a_hwa1, &ls1046a_hwa2
++ },
++ .cmux_to_group = {
++ 0, -1
++ },
++ .pll_mask = 0x07,
++ .flags = CG_PLL_8BIT,
++ },
++ {
++ .compat = "fsl,ls1088a-clockgen",
++ .cmux_groups = {
++ &clockgen2_cmux_cga12
++ },
++ .cmux_to_group = {
++ 0, 0, -1
++ },
++ .pll_mask = 0x07,
++ .flags = CG_VER3 | CG_LITTLE_ENDIAN,
++ },
++ {
++ .compat = "fsl,ls1012a-clockgen",
++ .cmux_groups = {
++ &ls1012a_cmux
++ },
++ .cmux_to_group = {
++ 0, -1
++ },
++ .pll_mask = 0x03,
++ },
+ {
+ .compat = "fsl,ls2080a-clockgen",
+ .cmux_groups = {
+@@ -846,7 +916,12 @@ static void __init create_muxes(struct clockgen *cg)
+
+ static void __init clockgen_init(struct device_node *np);
+
+-/* Legacy nodes may get probed before the parent clockgen node */
++/*
++ * Legacy nodes may get probed before the parent clockgen node.
++ * It is assumed that device trees with legacy nodes will not
++ * contain a "clocks" property -- otherwise the input clocks may
++ * not be initialized at this point.
++ */
+ static void __init legacy_init_clockgen(struct device_node *np)
+ {
+ if (!clockgen.node)
+@@ -887,18 +962,13 @@ static struct clk __init
+ return clk_register_fixed_rate(NULL, name, NULL, 0, rate);
+ }
+
+-static struct clk *sysclk_from_parent(const char *name)
++static struct clk __init *input_clock(const char *name, struct clk *clk)
+ {
+- struct clk *clk;
+- const char *parent_name;
+-
+- clk = of_clk_get(clockgen.node, 0);
+- if (IS_ERR(clk))
+- return clk;
++ const char *input_name;
+
+ /* Register the input clock under the desired name. */
+- parent_name = __clk_get_name(clk);
+- clk = clk_register_fixed_factor(NULL, name, parent_name,
++ input_name = __clk_get_name(clk);
++ clk = clk_register_fixed_factor(NULL, name, input_name,
+ 0, 1, 1);
+ if (IS_ERR(clk))
+ pr_err("%s: Couldn't register %s: %ld\n", __func__, name,
+@@ -907,6 +977,29 @@ static struct clk *sysclk_from_parent(const char *name)
+ return clk;
+ }
+
++static struct clk __init *input_clock_by_name(const char *name,
++ const char *dtname)
++{
++ struct clk *clk;
++
++ clk = of_clk_get_by_name(clockgen.node, dtname);
++ if (IS_ERR(clk))
++ return clk;
++
++ return input_clock(name, clk);
++}
++
++static struct clk __init *input_clock_by_index(const char *name, int idx)
++{
++ struct clk *clk;
++
++ clk = of_clk_get(clockgen.node, 0);
++ if (IS_ERR(clk))
++ return clk;
++
++ return input_clock(name, clk);
++}
++
+ static struct clk * __init create_sysclk(const char *name)
+ {
+ struct device_node *sysclk;
+@@ -916,7 +1009,11 @@ static struct clk * __init create_sysclk(const char *name)
+ if (!IS_ERR(clk))
+ return clk;
+
+- clk = sysclk_from_parent(name);
++ clk = input_clock_by_name(name, "sysclk");
++ if (!IS_ERR(clk))
++ return clk;
++
++ clk = input_clock_by_index(name, 0);
+ if (!IS_ERR(clk))
+ return clk;
+
+@@ -927,7 +1024,27 @@ static struct clk * __init create_sysclk(const char *name)
+ return clk;
+ }
+
+- pr_err("%s: No input clock\n", __func__);
++ pr_err("%s: No input sysclk\n", __func__);
++ return NULL;
++}
++
++static struct clk * __init create_coreclk(const char *name)
++{
++ struct clk *clk;
++
++ clk = input_clock_by_name(name, "coreclk");
++ if (!IS_ERR(clk))
++ return clk;
++
++ /*
++ * This indicates a mix of legacy nodes with the new coreclk
++ * mechanism, which should never happen. If this error occurs,
++ * don't use the wrong input clock just because coreclk isn't
++ * ready yet.
++ */
++ if (WARN_ON(PTR_ERR(clk) == -EPROBE_DEFER))
++ return clk;
++
+ return NULL;
+ }
+
+@@ -950,11 +1067,19 @@ static void __init create_one_pll(struct clockgen *cg, int idx)
+ u32 __iomem *reg;
+ u32 mult;
+ struct clockgen_pll *pll = &cg->pll[idx];
++ const char *input = "cg-sysclk";
+ int i;
+
+ if (!(cg->info.pll_mask & (1 << idx)))
+ return;
+
++ if (cg->coreclk && idx != PLATFORM_PLL) {
++ if (IS_ERR(cg->coreclk))
++ return;
++
++ input = "cg-coreclk";
++ }
++
+ if (cg->info.flags & CG_VER3) {
+ switch (idx) {
+ case PLATFORM_PLL:
+@@ -1000,12 +1125,13 @@ static void __init create_one_pll(struct clockgen *cg, int idx)
+
+ for (i = 0; i < ARRAY_SIZE(pll->div); i++) {
+ struct clk *clk;
++ int ret;
+
+ snprintf(pll->div[i].name, sizeof(pll->div[i].name),
+ "cg-pll%d-div%d", idx, i + 1);
+
+ clk = clk_register_fixed_factor(NULL,
+- pll->div[i].name, "cg-sysclk", 0, mult, i + 1);
++ pll->div[i].name, input, 0, mult, i + 1);
+ if (IS_ERR(clk)) {
+ pr_err("%s: %s: register failed %ld\n",
+ __func__, pll->div[i].name, PTR_ERR(clk));
+@@ -1013,6 +1139,11 @@ 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));
++
+ }
+ }
+
+@@ -1142,6 +1273,13 @@ static struct clk *clockgen_clk_get(struct of_phandle_args *clkspec, void *data)
+ goto bad_args;
+ clk = pll->div[idx].clk;
+ break;
++ case 5:
++ if (idx != 0)
++ goto bad_args;
++ clk = cg->coreclk;
++ if (IS_ERR(clk))
++ clk = NULL;
++ break;
+ default:
+ goto bad_args;
+ }
+@@ -1253,6 +1391,7 @@ static void __init clockgen_init(struct device_node *np)
+ clockgen.info.flags |= CG_CMUX_GE_PLAT;
+
+ clockgen.sysclk = create_sysclk("cg-sysclk");
++ clockgen.coreclk = create_coreclk("cg-coreclk");
+ create_plls(&clockgen);
+ create_muxes(&clockgen);
+
+@@ -1273,8 +1412,11 @@ static void __init clockgen_init(struct device_node *np)
+
+ 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_ls1012a, "fsl,ls1012a-clockgen", clockgen_init);
+ CLK_OF_DECLARE(qoriq_clockgen_ls1021a, "fsl,ls1021a-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);
+
+ /* Legacy nodes */
+--
+2.14.1
+