diff options
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.patch | 312 |
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 + |