From 840e1a73ccbb2096d1286d72c18ccadd3956b0ae Mon Sep 17 00:00:00 2001 From: Jerome Brunet Date: Fri, 19 Jan 2018 16:55:21 +0100 Subject: clk: meson: check pll rate param table before using it Make sure the rate param table is available before using it. Some read-only plls don't provide it, which is ok since the table is not used by read-only clocks. R/W clocks are supposed to provide it, but it does not hurt check it. Signed-off-by: Jerome Brunet --- drivers/clk/meson/clk-pll.c | 10 ++++++++++ 1 file changed, 10 insertions(+) diff --git a/drivers/clk/meson/clk-pll.c b/drivers/clk/meson/clk-pll.c index 01341553f50b..2614341fc4ad 100644 --- a/drivers/clk/meson/clk-pll.c +++ b/drivers/clk/meson/clk-pll.c @@ -94,6 +94,13 @@ static long meson_clk_pll_round_rate(struct clk_hw *hw, unsigned long rate, const struct pll_rate_table *rate_table = pll->rate_table; int i; + /* + * if the table is missing, just return the current rate + * since we don't have the other available frequencies + */ + if (!rate_table) + return meson_clk_pll_recalc_rate(hw, *parent_rate); + for (i = 0; i < pll->rate_count; i++) { if (rate <= rate_table[i].rate) return rate_table[i].rate; @@ -109,6 +116,9 @@ static const struct pll_rate_table *meson_clk_get_pll_settings(struct meson_clk_ const struct pll_rate_table *rate_table = pll->rate_table; int i; + if (!rate_table) + return NULL; + for (i = 0; i < pll->rate_count; i++) { if (rate == rate_table[i].rate) return &rate_table[i]; -- cgit v1.2.3 From 4ed98e9572ad24a5286d80d71221372b55fa9df5 Mon Sep 17 00:00:00 2001 From: Jerome Brunet Date: Fri, 19 Jan 2018 16:55:22 +0100 Subject: clk: meson: remove useless pll rate params tables Read-only plls don't need param table to recalculate the rate. Providing them with a param table is just a waste of memory. Remove the useless tables from sys_pll on gxbb and axg. Signed-off-by: Jerome Brunet --- drivers/clk/meson/axg.c | 94 ------------------------------------------------ drivers/clk/meson/gxbb.c | 94 ------------------------------------------------ 2 files changed, 188 deletions(-) diff --git a/drivers/clk/meson/axg.c b/drivers/clk/meson/axg.c index 1294f3ad7cd5..8e37bbf305e9 100644 --- a/drivers/clk/meson/axg.c +++ b/drivers/clk/meson/axg.c @@ -21,98 +21,6 @@ static DEFINE_SPINLOCK(meson_clk_lock); -static const struct pll_rate_table sys_pll_rate_table[] = { - PLL_RATE(24000000, 56, 1, 2), - PLL_RATE(48000000, 64, 1, 2), - PLL_RATE(72000000, 72, 1, 2), - PLL_RATE(96000000, 64, 1, 2), - PLL_RATE(120000000, 80, 1, 2), - PLL_RATE(144000000, 96, 1, 2), - PLL_RATE(168000000, 56, 1, 1), - PLL_RATE(192000000, 64, 1, 1), - PLL_RATE(216000000, 72, 1, 1), - PLL_RATE(240000000, 80, 1, 1), - PLL_RATE(264000000, 88, 1, 1), - PLL_RATE(288000000, 96, 1, 1), - PLL_RATE(312000000, 52, 1, 2), - PLL_RATE(336000000, 56, 1, 2), - PLL_RATE(360000000, 60, 1, 2), - PLL_RATE(384000000, 64, 1, 2), - PLL_RATE(408000000, 68, 1, 2), - PLL_RATE(432000000, 72, 1, 2), - PLL_RATE(456000000, 76, 1, 2), - PLL_RATE(480000000, 80, 1, 2), - PLL_RATE(504000000, 84, 1, 2), - PLL_RATE(528000000, 88, 1, 2), - PLL_RATE(552000000, 92, 1, 2), - PLL_RATE(576000000, 96, 1, 2), - PLL_RATE(600000000, 50, 1, 1), - PLL_RATE(624000000, 52, 1, 1), - PLL_RATE(648000000, 54, 1, 1), - PLL_RATE(672000000, 56, 1, 1), - PLL_RATE(696000000, 58, 1, 1), - PLL_RATE(720000000, 60, 1, 1), - PLL_RATE(744000000, 62, 1, 1), - PLL_RATE(768000000, 64, 1, 1), - PLL_RATE(792000000, 66, 1, 1), - PLL_RATE(816000000, 68, 1, 1), - PLL_RATE(840000000, 70, 1, 1), - PLL_RATE(864000000, 72, 1, 1), - PLL_RATE(888000000, 74, 1, 1), - PLL_RATE(912000000, 76, 1, 1), - PLL_RATE(936000000, 78, 1, 1), - PLL_RATE(960000000, 80, 1, 1), - PLL_RATE(984000000, 82, 1, 1), - PLL_RATE(1008000000, 84, 1, 1), - PLL_RATE(1032000000, 86, 1, 1), - PLL_RATE(1056000000, 88, 1, 1), - PLL_RATE(1080000000, 90, 1, 1), - PLL_RATE(1104000000, 92, 1, 1), - PLL_RATE(1128000000, 94, 1, 1), - PLL_RATE(1152000000, 96, 1, 1), - PLL_RATE(1176000000, 98, 1, 1), - PLL_RATE(1200000000, 50, 1, 0), - PLL_RATE(1224000000, 51, 1, 0), - PLL_RATE(1248000000, 52, 1, 0), - PLL_RATE(1272000000, 53, 1, 0), - PLL_RATE(1296000000, 54, 1, 0), - PLL_RATE(1320000000, 55, 1, 0), - PLL_RATE(1344000000, 56, 1, 0), - PLL_RATE(1368000000, 57, 1, 0), - PLL_RATE(1392000000, 58, 1, 0), - PLL_RATE(1416000000, 59, 1, 0), - PLL_RATE(1440000000, 60, 1, 0), - PLL_RATE(1464000000, 61, 1, 0), - PLL_RATE(1488000000, 62, 1, 0), - PLL_RATE(1512000000, 63, 1, 0), - PLL_RATE(1536000000, 64, 1, 0), - PLL_RATE(1560000000, 65, 1, 0), - PLL_RATE(1584000000, 66, 1, 0), - PLL_RATE(1608000000, 67, 1, 0), - PLL_RATE(1632000000, 68, 1, 0), - PLL_RATE(1656000000, 68, 1, 0), - PLL_RATE(1680000000, 68, 1, 0), - PLL_RATE(1704000000, 68, 1, 0), - PLL_RATE(1728000000, 69, 1, 0), - PLL_RATE(1752000000, 69, 1, 0), - PLL_RATE(1776000000, 69, 1, 0), - PLL_RATE(1800000000, 69, 1, 0), - PLL_RATE(1824000000, 70, 1, 0), - PLL_RATE(1848000000, 70, 1, 0), - PLL_RATE(1872000000, 70, 1, 0), - PLL_RATE(1896000000, 70, 1, 0), - PLL_RATE(1920000000, 71, 1, 0), - PLL_RATE(1944000000, 71, 1, 0), - PLL_RATE(1968000000, 71, 1, 0), - PLL_RATE(1992000000, 71, 1, 0), - PLL_RATE(2016000000, 72, 1, 0), - PLL_RATE(2040000000, 72, 1, 0), - PLL_RATE(2064000000, 72, 1, 0), - PLL_RATE(2088000000, 72, 1, 0), - PLL_RATE(2112000000, 73, 1, 0), - { /* sentinel */ }, -}; - static struct meson_clk_pll axg_fixed_pll = { .m = { .reg_off = HHI_MPLL_CNTL, @@ -154,8 +62,6 @@ static struct meson_clk_pll axg_sys_pll = { .shift = 10, .width = 2, }, - .rate_table = sys_pll_rate_table, - .rate_count = ARRAY_SIZE(sys_pll_rate_table), .lock = &meson_clk_lock, .hw.init = &(struct clk_init_data){ .name = "sys_pll", diff --git a/drivers/clk/meson/gxbb.c b/drivers/clk/meson/gxbb.c index af24455af5b4..4b5229f656e3 100644 --- a/drivers/clk/meson/gxbb.c +++ b/drivers/clk/meson/gxbb.c @@ -29,98 +29,6 @@ static DEFINE_SPINLOCK(meson_clk_lock); -static const struct pll_rate_table sys_pll_rate_table[] = { - PLL_RATE(24000000, 56, 1, 2), - PLL_RATE(48000000, 64, 1, 2), - PLL_RATE(72000000, 72, 1, 2), - PLL_RATE(96000000, 64, 1, 2), - PLL_RATE(120000000, 80, 1, 2), - PLL_RATE(144000000, 96, 1, 2), - PLL_RATE(168000000, 56, 1, 1), - PLL_RATE(192000000, 64, 1, 1), - PLL_RATE(216000000, 72, 1, 1), - PLL_RATE(240000000, 80, 1, 1), - PLL_RATE(264000000, 88, 1, 1), - PLL_RATE(288000000, 96, 1, 1), - PLL_RATE(312000000, 52, 1, 2), - PLL_RATE(336000000, 56, 1, 2), - PLL_RATE(360000000, 60, 1, 2), - PLL_RATE(384000000, 64, 1, 2), - PLL_RATE(408000000, 68, 1, 2), - PLL_RATE(432000000, 72, 1, 2), - PLL_RATE(456000000, 76, 1, 2), - PLL_RATE(480000000, 80, 1, 2), - PLL_RATE(504000000, 84, 1, 2), - PLL_RATE(528000000, 88, 1, 2), - PLL_RATE(552000000, 92, 1, 2), - PLL_RATE(576000000, 96, 1, 2), - PLL_RATE(600000000, 50, 1, 1), - PLL_RATE(624000000, 52, 1, 1), - PLL_RATE(648000000, 54, 1, 1), - PLL_RATE(672000000, 56, 1, 1), - PLL_RATE(696000000, 58, 1, 1), - PLL_RATE(720000000, 60, 1, 1), - PLL_RATE(744000000, 62, 1, 1), - PLL_RATE(768000000, 64, 1, 1), - PLL_RATE(792000000, 66, 1, 1), - PLL_RATE(816000000, 68, 1, 1), - PLL_RATE(840000000, 70, 1, 1), - PLL_RATE(864000000, 72, 1, 1), - PLL_RATE(888000000, 74, 1, 1), - PLL_RATE(912000000, 76, 1, 1), - PLL_RATE(936000000, 78, 1, 1), - PLL_RATE(960000000, 80, 1, 1), - PLL_RATE(984000000, 82, 1, 1), - PLL_RATE(1008000000, 84, 1, 1), - PLL_RATE(1032000000, 86, 1, 1), - PLL_RATE(1056000000, 88, 1, 1), - PLL_RATE(1080000000, 90, 1, 1), - PLL_RATE(1104000000, 92, 1, 1), - PLL_RATE(1128000000, 94, 1, 1), - PLL_RATE(1152000000, 96, 1, 1), - PLL_RATE(1176000000, 98, 1, 1), - PLL_RATE(1200000000, 50, 1, 0), - PLL_RATE(1224000000, 51, 1, 0), - PLL_RATE(1248000000, 52, 1, 0), - PLL_RATE(1272000000, 53, 1, 0), - PLL_RATE(1296000000, 54, 1, 0), - PLL_RATE(1320000000, 55, 1, 0), - PLL_RATE(1344000000, 56, 1, 0), - PLL_RATE(1368000000, 57, 1, 0), - PLL_RATE(1392000000, 58, 1, 0), - PLL_RATE(1416000000, 59, 1, 0), - PLL_RATE(1440000000, 60, 1, 0), - PLL_RATE(1464000000, 61, 1, 0), - PLL_RATE(1488000000, 62, 1, 0), - PLL_RATE(1512000000, 63, 1, 0), - PLL_RATE(1536000000, 64, 1, 0), - PLL_RATE(1560000000, 65, 1, 0), - PLL_RATE(1584000000, 66, 1, 0), - PLL_RATE(1608000000, 67, 1, 0), - PLL_RATE(1632000000, 68, 1, 0), - PLL_RATE(1656000000, 68, 1, 0), - PLL_RATE(1680000000, 68, 1, 0), - PLL_RATE(1704000000, 68, 1, 0), - PLL_RATE(1728000000, 69, 1, 0), - PLL_RATE(1752000000, 69, 1, 0), - PLL_RATE(1776000000, 69, 1, 0), - PLL_RATE(1800000000, 69, 1, 0), - PLL_RATE(1824000000, 70, 1, 0), - PLL_RATE(1848000000, 70, 1, 0), - PLL_RATE(1872000000, 70, 1, 0), - PLL_RATE(1896000000, 70, 1, 0), - PLL_RATE(1920000000, 71, 1, 0), - PLL_RATE(1944000000, 71, 1, 0), - PLL_RATE(1968000000, 71, 1, 0), - PLL_RATE(1992000000, 71, 1, 0), - PLL_RATE(2016000000, 72, 1, 0), - PLL_RATE(2040000000, 72, 1, 0), - PLL_RATE(2064000000, 72, 1, 0), - PLL_RATE(2088000000, 72, 1, 0), - PLL_RATE(2112000000, 73, 1, 0), - { /* sentinel */ }, -}; - static const struct pll_rate_table gxbb_gp0_pll_rate_table[] = { PLL_RATE(96000000, 32, 1, 3), PLL_RATE(99000000, 33, 1, 3), @@ -356,8 +264,6 @@ static struct meson_clk_pll gxbb_sys_pll = { .shift = 10, .width = 2, }, - .rate_table = sys_pll_rate_table, - .rate_count = ARRAY_SIZE(sys_pll_rate_table), .lock = &meson_clk_lock, .hw.init = &(struct clk_init_data){ .name = "sys_pll", -- cgit v1.2.3 From 94aa8a41f1bc807db78567e7031d75998c166150 Mon Sep 17 00:00:00 2001 From: Jerome Brunet Date: Fri, 19 Jan 2018 16:55:23 +0100 Subject: clk: meson: remove unnecessary rounding in the pll clock The pll driver performs the rate calculation in Mhz, which adds an unnecessary rounding down to the Mhz of the rate. Use 64bits long integers to perform this calculation safely on meson8b and perform the calculation in Hz instead Fixes: 7a29a869434e ("clk: meson: Add support for Meson clock controller") Signed-off-by: Jerome Brunet --- drivers/clk/meson/clk-pll.c | 17 +++++++++-------- 1 file changed, 9 insertions(+), 8 deletions(-) diff --git a/drivers/clk/meson/clk-pll.c b/drivers/clk/meson/clk-pll.c index 2614341fc4ad..087dfc532ba8 100644 --- a/drivers/clk/meson/clk-pll.c +++ b/drivers/clk/meson/clk-pll.c @@ -34,6 +34,7 @@ #include #include #include +#include #include #include #include @@ -51,8 +52,7 @@ static unsigned long meson_clk_pll_recalc_rate(struct clk_hw *hw, { struct meson_clk_pll *pll = to_meson_clk_pll(hw); struct parm *p; - unsigned long parent_rate_mhz = parent_rate / 1000000; - unsigned long rate_mhz; + u64 rate; u16 n, m, frac = 0, od, od2 = 0; u32 reg; @@ -74,17 +74,18 @@ static unsigned long meson_clk_pll_recalc_rate(struct clk_hw *hw, od2 = PARM_GET(p->width, p->shift, reg); } + rate = (u64)parent_rate * m; + p = &pll->frac; if (p->width) { reg = readl(pll->base + p->reg_off); frac = PARM_GET(p->width, p->shift, reg); - rate_mhz = (parent_rate_mhz * m + \ - (parent_rate_mhz * frac >> 12)) * 2 / n; - rate_mhz = rate_mhz >> od >> od2; - } else - rate_mhz = (parent_rate_mhz * m / n) >> od >> od2; - return rate_mhz * 1000000; + rate += mul_u64_u32_shr(parent_rate, frac, 12); + rate *= 2; + } + + return div_u64(rate, n) >> od >> od2; } static long meson_clk_pll_round_rate(struct clk_hw *hw, unsigned long rate, -- cgit v1.2.3 From 4c5f67b7ea329ed8b3cf708fde4656b2d3b27dbf Mon Sep 17 00:00:00 2001 From: Jerome Brunet Date: Fri, 19 Jan 2018 16:55:24 +0100 Subject: clk: meson: use the frac parameter width instead of a constant Use the fractional part width in the calculation instead of 12, which happens to be the witdh right now. This is safer in case the field width ever change in the future Signed-off-by: Jerome Brunet --- drivers/clk/meson/clk-pll.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/clk/meson/clk-pll.c b/drivers/clk/meson/clk-pll.c index 087dfc532ba8..50923d004d96 100644 --- a/drivers/clk/meson/clk-pll.c +++ b/drivers/clk/meson/clk-pll.c @@ -81,7 +81,7 @@ static unsigned long meson_clk_pll_recalc_rate(struct clk_hw *hw, reg = readl(pll->base + p->reg_off); frac = PARM_GET(p->width, p->shift, reg); - rate += mul_u64_u32_shr(parent_rate, frac, 12); + rate += mul_u64_u32_shr(parent_rate, frac, p->width); rate *= 2; } -- cgit v1.2.3 From 7d3142e5d64a2bdcd382dac979407f6afc83d685 Mon Sep 17 00:00:00 2001 From: Jerome Brunet Date: Fri, 19 Jan 2018 16:55:25 +0100 Subject: clk: meson: add od3 to the pll driver Some meson plls, such as the hdmi pll, are using a 3rd od parameter, which is yet another "power of 2" post divider. Add it to fix the calculation of the hdmi_pll rate Fixes: 738f66d3211d ("clk: gxbb: add AmLogic GXBB clk controller driver") Signed-off-by: Jerome Brunet --- drivers/clk/meson/clk-pll.c | 19 ++++++++++++++++--- drivers/clk/meson/clkc.h | 2 ++ drivers/clk/meson/gxbb.c | 5 +++++ 3 files changed, 23 insertions(+), 3 deletions(-) diff --git a/drivers/clk/meson/clk-pll.c b/drivers/clk/meson/clk-pll.c index 50923d004d96..1595f02f610f 100644 --- a/drivers/clk/meson/clk-pll.c +++ b/drivers/clk/meson/clk-pll.c @@ -53,7 +53,7 @@ static unsigned long meson_clk_pll_recalc_rate(struct clk_hw *hw, struct meson_clk_pll *pll = to_meson_clk_pll(hw); struct parm *p; u64 rate; - u16 n, m, frac = 0, od, od2 = 0; + u16 n, m, frac = 0, od, od2 = 0, od3 = 0; u32 reg; p = &pll->n; @@ -74,7 +74,13 @@ static unsigned long meson_clk_pll_recalc_rate(struct clk_hw *hw, od2 = PARM_GET(p->width, p->shift, reg); } - rate = (u64)parent_rate * m; + p = &pll->od3; + if (p->width) { + reg = readl(pll->base + p->reg_off); + od3 = PARM_GET(p->width, p->shift, reg); + } + + rate = (u64)m * parent_rate; p = &pll->frac; if (p->width) { @@ -85,7 +91,7 @@ static unsigned long meson_clk_pll_recalc_rate(struct clk_hw *hw, rate *= 2; } - return div_u64(rate, n) >> od >> od2; + return div_u64(rate, n) >> od >> od2 >> od3; } static long meson_clk_pll_round_rate(struct clk_hw *hw, unsigned long rate, @@ -226,6 +232,13 @@ static int meson_clk_pll_set_rate(struct clk_hw *hw, unsigned long rate, writel(reg, pll->base + p->reg_off); } + p = &pll->od3; + if (p->width) { + reg = readl(pll->base + p->reg_off); + reg = PARM_SET(p->width, p->shift, reg, rate_set->od3); + writel(reg, pll->base + p->reg_off); + } + p = &pll->frac; if (p->width) { reg = readl(pll->base + p->reg_off); diff --git a/drivers/clk/meson/clkc.h b/drivers/clk/meson/clkc.h index c2ff0520ce53..4acb35bda669 100644 --- a/drivers/clk/meson/clkc.h +++ b/drivers/clk/meson/clkc.h @@ -41,6 +41,7 @@ struct pll_rate_table { u16 n; u16 od; u16 od2; + u16 od3; u16 frac; }; @@ -92,6 +93,7 @@ struct meson_clk_pll { struct parm frac; struct parm od; struct parm od2; + struct parm od3; const struct pll_setup_params params; const struct pll_rate_table *rate_table; unsigned int rate_count; diff --git a/drivers/clk/meson/gxbb.c b/drivers/clk/meson/gxbb.c index 4b5229f656e3..e83573b457fc 100644 --- a/drivers/clk/meson/gxbb.c +++ b/drivers/clk/meson/gxbb.c @@ -238,6 +238,11 @@ static struct meson_clk_pll gxbb_hdmi_pll = { .shift = 22, .width = 2, }, + .od3 = { + .reg_off = HHI_HDMI_PLL_CNTL2, + .shift = 18, + .width = 2, + }, .lock = &meson_clk_lock, .hw.init = &(struct clk_init_data){ .name = "hdmi_pll", -- cgit v1.2.3 From 69d92293274b3ae60c54271bf6e029e3d1d582e8 Mon Sep 17 00:00:00 2001 From: Jerome Brunet Date: Fri, 19 Jan 2018 16:55:26 +0100 Subject: clk: meson: add the gxl hdmi pll The hdmi pll used in the gxl family is actually different from the gxbb one. The register layout is completely different, which explain why the hdmi pll rate has always been rubbish on the gxl family. Adding the correct register field is the first part of the fix to get a correct rate out the hdmi pll Fixes: 0d48fc558d01 ("clk: meson-gxbb: Add GXL/GXM GP0 Variant") Signed-off-by: Jerome Brunet --- drivers/clk/meson/gxbb.c | 50 ++++++++++++++++++++++++++++++++++++++++++++++-- 1 file changed, 48 insertions(+), 2 deletions(-) diff --git a/drivers/clk/meson/gxbb.c b/drivers/clk/meson/gxbb.c index e83573b457fc..de1cea7a47fb 100644 --- a/drivers/clk/meson/gxbb.c +++ b/drivers/clk/meson/gxbb.c @@ -253,6 +253,52 @@ static struct meson_clk_pll gxbb_hdmi_pll = { }, }; +static struct meson_clk_pll gxl_hdmi_pll = { + .m = { + .reg_off = HHI_HDMI_PLL_CNTL, + .shift = 0, + .width = 9, + }, + .n = { + .reg_off = HHI_HDMI_PLL_CNTL, + .shift = 9, + .width = 5, + }, + .frac = { + /* + * On gxl, there is a register shift due to HHI_HDMI_PLL_CNTL1 + * which does not exist on gxbb, so we compute the register + * offset based on the PLL base to get it right + */ + .reg_off = HHI_HDMI_PLL_CNTL + 4, + .shift = 0, + .width = 12, + }, + .od = { + .reg_off = HHI_HDMI_PLL_CNTL + 8, + .shift = 21, + .width = 2, + }, + .od2 = { + .reg_off = HHI_HDMI_PLL_CNTL + 8, + .shift = 23, + .width = 2, + }, + .od3 = { + .reg_off = HHI_HDMI_PLL_CNTL + 8, + .shift = 19, + .width = 2, + }, + .lock = &meson_clk_lock, + .hw.init = &(struct clk_init_data){ + .name = "hdmi_pll", + .ops = &meson_clk_pll_ro_ops, + .parent_names = (const char *[]){ "xtal" }, + .num_parents = 1, + .flags = CLK_GET_RATE_NOCACHE, + }, +}; + static struct meson_clk_pll gxbb_sys_pll = { .m = { .reg_off = HHI_SYS_PLL_CNTL, @@ -1520,7 +1566,7 @@ static struct clk_hw_onecell_data gxbb_hw_onecell_data = { static struct clk_hw_onecell_data gxl_hw_onecell_data = { .hws = { [CLKID_SYS_PLL] = &gxbb_sys_pll.hw, - [CLKID_HDMI_PLL] = &gxbb_hdmi_pll.hw, + [CLKID_HDMI_PLL] = &gxl_hdmi_pll.hw, [CLKID_FIXED_PLL] = &gxbb_fixed_pll.hw, [CLKID_FCLK_DIV2] = &gxbb_fclk_div2.hw, [CLKID_FCLK_DIV3] = &gxbb_fclk_div3.hw, @@ -1675,7 +1721,7 @@ static struct meson_clk_pll *const gxbb_clk_plls[] = { static struct meson_clk_pll *const gxl_clk_plls[] = { &gxbb_fixed_pll, - &gxbb_hdmi_pll, + &gxl_hdmi_pll, &gxbb_sys_pll, &gxl_gp0_pll, }; -- cgit v1.2.3 From 3c4fe763d64db93c0c8ec359cf394cfc491f91f3 Mon Sep 17 00:00:00 2001 From: Jerome Brunet Date: Fri, 19 Jan 2018 16:55:27 +0100 Subject: clk: meson: fix rate calculation of plls with a fractional part The rate of the parent should not be multiplied by 2 when the pll has a fractional part. This is making the rate calculation of the gxl_hdmi_pll wrong (and others as well). This multiplication is specific to the hdmi_pll of gxbb and is most likely due to a multiplier sitting in front of this particular pll. Add a fixed factor clock in front on the gxbb pll and remove this constant from the calculation to fix the problem Fixes: 4a47295144dd ("clk: meson: fractional pll support") Signed-off-by: Jerome Brunet --- drivers/clk/meson/clk-pll.c | 1 - drivers/clk/meson/gxbb.c | 14 +++++++++++++- drivers/clk/meson/gxbb.h | 3 ++- 3 files changed, 15 insertions(+), 3 deletions(-) diff --git a/drivers/clk/meson/clk-pll.c b/drivers/clk/meson/clk-pll.c index 1595f02f610f..218c769c6d50 100644 --- a/drivers/clk/meson/clk-pll.c +++ b/drivers/clk/meson/clk-pll.c @@ -88,7 +88,6 @@ static unsigned long meson_clk_pll_recalc_rate(struct clk_hw *hw, frac = PARM_GET(p->width, p->shift, reg); rate += mul_u64_u32_shr(parent_rate, frac, p->width); - rate *= 2; } return div_u64(rate, n) >> od >> od2 >> od3; diff --git a/drivers/clk/meson/gxbb.c b/drivers/clk/meson/gxbb.c index de1cea7a47fb..119babfa8d14 100644 --- a/drivers/clk/meson/gxbb.c +++ b/drivers/clk/meson/gxbb.c @@ -212,6 +212,17 @@ static struct meson_clk_pll gxbb_fixed_pll = { }, }; +static struct clk_fixed_factor gxbb_hdmi_pll_pre_mult = { + .mult = 2, + .div = 1, + .hw.init = &(struct clk_init_data){ + .name = "hdmi_pll_pre_mult", + .ops = &clk_fixed_factor_ops, + .parent_names = (const char *[]){ "xtal" }, + .num_parents = 1, + }, +}; + static struct meson_clk_pll gxbb_hdmi_pll = { .m = { .reg_off = HHI_HDMI_PLL_CNTL, @@ -247,7 +258,7 @@ static struct meson_clk_pll gxbb_hdmi_pll = { .hw.init = &(struct clk_init_data){ .name = "hdmi_pll", .ops = &meson_clk_pll_ro_ops, - .parent_names = (const char *[]){ "xtal" }, + .parent_names = (const char *[]){ "hdmi_pll_pre_mult" }, .num_parents = 1, .flags = CLK_GET_RATE_NOCACHE, }, @@ -1558,6 +1569,7 @@ static struct clk_hw_onecell_data gxbb_hw_onecell_data = { [CLKID_VAPB_1] = &gxbb_vapb_1.hw, [CLKID_VAPB_SEL] = &gxbb_vapb_sel.hw, [CLKID_VAPB] = &gxbb_vapb.hw, + [CLKID_HDMI_PLL_PRE_MULT] = &gxbb_hdmi_pll_pre_mult.hw, [NR_CLKS] = NULL, }, .num = NR_CLKS, diff --git a/drivers/clk/meson/gxbb.h b/drivers/clk/meson/gxbb.h index aee6fbba2004..42573b28a137 100644 --- a/drivers/clk/meson/gxbb.h +++ b/drivers/clk/meson/gxbb.h @@ -194,8 +194,9 @@ #define CLKID_VPU_1_DIV 130 #define CLKID_VAPB_0_DIV 134 #define CLKID_VAPB_1_DIV 137 +#define CLKID_HDMI_PLL_PRE_MULT 141 -#define NR_CLKS 141 +#define NR_CLKS 142 /* include the CLKIDs that have been made part of the DT binding */ #include -- cgit v1.2.3 From 07f45e2ecc1ba1ce75d80768caf2267256cd135d Mon Sep 17 00:00:00 2001 From: Jerome Brunet Date: Fri, 19 Jan 2018 16:55:28 +0100 Subject: clk: meson: gxbb: add the fractional part of the fixed_pll The fixed_pll of gxbb and gxl also has a fractional parameter. This has not been a problem so far because the fractional part is actually set to 0 on these platforms, so the rate remains correct when it is ignored. Still, it is better represent the pll the way it is, so add the frac parameter now Signed-off-by: Jerome Brunet --- drivers/clk/meson/gxbb.c | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/drivers/clk/meson/gxbb.c b/drivers/clk/meson/gxbb.c index 119babfa8d14..a5f25cc1944c 100644 --- a/drivers/clk/meson/gxbb.c +++ b/drivers/clk/meson/gxbb.c @@ -202,6 +202,11 @@ static struct meson_clk_pll gxbb_fixed_pll = { .shift = 16, .width = 2, }, + .frac = { + .reg_off = HHI_MPLL_CNTL2, + .shift = 0, + .width = 12, + }, .lock = &meson_clk_lock, .hw.init = &(struct clk_init_data){ .name = "fixed_pll", -- cgit v1.2.3 From 6b71aceceb09918daf37a40a1221077599040be3 Mon Sep 17 00:00:00 2001 From: Jerome Brunet Date: Fri, 19 Jan 2018 16:55:29 +0100 Subject: clk: meson: axg: add the fractional part of the fixed_pll The fixed_pll also has a fractional part. On axg s400 board, without this parameter, the calculated rate is off by ~8Mhz (0,4%). The fixed_pll being the root of the peripheral clock tree, this error is propagated to the rest of the clocks Adding the definition of the parameter fixes the problem Fixes: 78b4af312f91 ("clk: meson-axg: add clock controller drivers") Signed-off-by: Jerome Brunet --- drivers/clk/meson/axg.c | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/drivers/clk/meson/axg.c b/drivers/clk/meson/axg.c index 8e37bbf305e9..a1ac0ff67e5f 100644 --- a/drivers/clk/meson/axg.c +++ b/drivers/clk/meson/axg.c @@ -37,6 +37,11 @@ static struct meson_clk_pll axg_fixed_pll = { .shift = 16, .width = 2, }, + .frac = { + .reg_off = HHI_MPLL_CNTL2, + .shift = 0, + .width = 12, + }, .lock = &meson_clk_lock, .hw.init = &(struct clk_init_data){ .name = "fixed_pll", -- cgit v1.2.3 From 2fa9b361e500a0e092a9525afbd6a3a363ffa5f0 Mon Sep 17 00:00:00 2001 From: Yixun Lan Date: Fri, 19 Jan 2018 10:09:26 +0800 Subject: clk: meson: axg: fix the od shift of the sys_pll According to the datasheet, the od shift of sys_pll is actually 16. Fixes: 78b4af312f91 ('clk: meson-axg: add clock controller drivers') Signed-off-by: Yixun Lan [fixed commit message] Signed-off-by: Jerome Brunet --- drivers/clk/meson/axg.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/clk/meson/axg.c b/drivers/clk/meson/axg.c index a1ac0ff67e5f..455d4d8962bb 100644 --- a/drivers/clk/meson/axg.c +++ b/drivers/clk/meson/axg.c @@ -64,7 +64,7 @@ static struct meson_clk_pll axg_sys_pll = { }, .od = { .reg_off = HHI_SYS_PLL_CNTL, - .shift = 10, + .shift = 16, .width = 2, }, .lock = &meson_clk_lock, -- cgit v1.2.3 From 6c00e7b76021fcf4ddb64191ccdf62c722adf0d1 Mon Sep 17 00:00:00 2001 From: Jerome Brunet Date: Fri, 19 Jan 2018 16:42:36 +0100 Subject: clk: meson: add axg misc bit to the mpll driver On axg, the rate of the mpll is stuck as if sdm value was 4 and could not change (expect for mpll2 strangely). Looking at the vendor kernel, it turns out a new magic bit from the undocumented HHI_PLL_TOP_MISC register is required. Setting this bit solves the problem and the mpll rates are back to normal Fixes: 78b4af312f91 ("clk: meson-axg: add clock controller drivers") Signed-off-by: Jerome Brunet --- drivers/clk/meson/axg.c | 20 ++++++++++++++++++++ drivers/clk/meson/clk-mpll.c | 7 +++++++ drivers/clk/meson/clkc.h | 1 + 3 files changed, 28 insertions(+) diff --git a/drivers/clk/meson/axg.c b/drivers/clk/meson/axg.c index 455d4d8962bb..2dc70e0e925c 100644 --- a/drivers/clk/meson/axg.c +++ b/drivers/clk/meson/axg.c @@ -292,6 +292,11 @@ static struct meson_clk_mpll axg_mpll0 = { .shift = 25, .width = 1, }, + .misc = { + .reg_off = HHI_PLL_TOP_MISC, + .shift = 0, + .width = 1, + }, .lock = &meson_clk_lock, .hw.init = &(struct clk_init_data){ .name = "mpll0", @@ -322,6 +327,11 @@ static struct meson_clk_mpll axg_mpll1 = { .shift = 14, .width = 1, }, + .misc = { + .reg_off = HHI_PLL_TOP_MISC, + .shift = 1, + .width = 1, + }, .lock = &meson_clk_lock, .hw.init = &(struct clk_init_data){ .name = "mpll1", @@ -352,6 +362,11 @@ static struct meson_clk_mpll axg_mpll2 = { .shift = 14, .width = 1, }, + .misc = { + .reg_off = HHI_PLL_TOP_MISC, + .shift = 2, + .width = 1, + }, .lock = &meson_clk_lock, .hw.init = &(struct clk_init_data){ .name = "mpll2", @@ -382,6 +397,11 @@ static struct meson_clk_mpll axg_mpll3 = { .shift = 0, .width = 1, }, + .misc = { + .reg_off = HHI_PLL_TOP_MISC, + .shift = 3, + .width = 1, + }, .lock = &meson_clk_lock, .hw.init = &(struct clk_init_data){ .name = "mpll3", diff --git a/drivers/clk/meson/clk-mpll.c b/drivers/clk/meson/clk-mpll.c index 5144360e2c80..6d79d6daadc4 100644 --- a/drivers/clk/meson/clk-mpll.c +++ b/drivers/clk/meson/clk-mpll.c @@ -173,6 +173,13 @@ static int mpll_set_rate(struct clk_hw *hw, reg = PARM_SET(p->width, p->shift, reg, n2); writel(reg, mpll->base + p->reg_off); + p = &mpll->misc; + if (p->width != 0) { + reg = readl(mpll->base + p->reg_off); + reg = PARM_SET(p->width, p->shift, reg, 1); + writel(reg, mpll->base + p->reg_off); + } + if (mpll->lock) spin_unlock_irqrestore(mpll->lock, flags); else diff --git a/drivers/clk/meson/clkc.h b/drivers/clk/meson/clkc.h index 4acb35bda669..07aaba26a857 100644 --- a/drivers/clk/meson/clkc.h +++ b/drivers/clk/meson/clkc.h @@ -121,6 +121,7 @@ struct meson_clk_mpll { struct parm n2; struct parm en; struct parm ssen; + struct parm misc; spinlock_t *lock; }; -- cgit v1.2.3 From 35615917ef027386a9acbe3cd8752f02b125b074 Mon Sep 17 00:00:00 2001 From: Chanwoo Choi Date: Mon, 27 Nov 2017 11:31:48 +0900 Subject: clk: samsung: s3c: Remove unneeded enumeration This patch just removes the unneeded enumeration for PLL index. Signed-off-by: Chanwoo Choi Signed-off-by: Sylwester Nawrocki --- drivers/clk/samsung/clk-s3c2412.c | 11 ++--------- drivers/clk/samsung/clk-s3c2443.c | 17 ++++------------- drivers/clk/samsung/clk-s3c64xx.c | 17 ++++++----------- 3 files changed, 12 insertions(+), 33 deletions(-) diff --git a/drivers/clk/samsung/clk-s3c2412.c b/drivers/clk/samsung/clk-s3c2412.c index b8340a49921b..1555e407529e 100644 --- a/drivers/clk/samsung/clk-s3c2412.c +++ b/drivers/clk/samsung/clk-s3c2412.c @@ -27,11 +27,6 @@ #define CLKSRC 0x1c #define SWRST 0x30 -/* list of PLLs to be registered */ -enum s3c2412_plls { - mpll, upll, -}; - static void __iomem *reg_base; #ifdef CONFIG_PM_SLEEP @@ -144,10 +139,8 @@ struct samsung_mux_clock s3c2412_muxes[] __initdata = { }; static struct samsung_pll_clock s3c2412_plls[] __initdata = { - [mpll] = PLL(pll_s3c2440_mpll, MPLL, "mpll", "xti", - LOCKTIME, MPLLCON, NULL), - [upll] = PLL(pll_s3c2410_upll, UPLL, "upll", "urefclk", - LOCKTIME, UPLLCON, NULL), + PLL(pll_s3c2440_mpll, MPLL, "mpll", "xti", LOCKTIME, MPLLCON, NULL), + PLL(pll_s3c2410_upll, UPLL, "upll", "urefclk", LOCKTIME, UPLLCON, NULL), }; struct samsung_gate_clock s3c2412_gates[] __initdata = { diff --git a/drivers/clk/samsung/clk-s3c2443.c b/drivers/clk/samsung/clk-s3c2443.c index d94b85a42356..9580a6baf4d7 100644 --- a/drivers/clk/samsung/clk-s3c2443.c +++ b/drivers/clk/samsung/clk-s3c2443.c @@ -41,11 +41,6 @@ enum supported_socs { S3C2450, }; -/* list of PLLs to be registered */ -enum s3c2443_plls { - mpll, epll, -}; - static void __iomem *reg_base; #ifdef CONFIG_PM_SLEEP @@ -225,10 +220,8 @@ struct samsung_clock_alias s3c2443_common_aliases[] __initdata = { /* S3C2416 specific clocks */ static struct samsung_pll_clock s3c2416_pll_clks[] __initdata = { - [mpll] = PLL(pll_6552_s3c2416, MPLL, "mpll", "mpllref", - LOCKCON0, MPLLCON, NULL), - [epll] = PLL(pll_6553, EPLL, "epll", "epllref", - LOCKCON1, EPLLCON, NULL), + PLL(pll_6552_s3c2416, MPLL, "mpll", "mpllref", LOCKCON0, MPLLCON, NULL), + PLL(pll_6553, EPLL, "epll", "epllref", LOCKCON1, EPLLCON, NULL), }; PNAME(s3c2416_hsmmc0_p) = { "sclk_hsmmc0", "sclk_hsmmcext" }; @@ -279,10 +272,8 @@ struct samsung_clock_alias s3c2416_aliases[] __initdata = { /* S3C2443 specific clocks */ static struct samsung_pll_clock s3c2443_pll_clks[] __initdata = { - [mpll] = PLL(pll_3000, MPLL, "mpll", "mpllref", - LOCKCON0, MPLLCON, NULL), - [epll] = PLL(pll_2126, EPLL, "epll", "epllref", - LOCKCON1, EPLLCON, NULL), + PLL(pll_3000, MPLL, "mpll", "mpllref", LOCKCON0, MPLLCON, NULL), + PLL(pll_2126, EPLL, "epll", "epllref", LOCKCON1, EPLLCON, NULL), }; static struct clk_div_table armdiv_s3c2443_d[] = { diff --git a/drivers/clk/samsung/clk-s3c64xx.c b/drivers/clk/samsung/clk-s3c64xx.c index 7306867a0ab8..6db01cf5ab83 100644 --- a/drivers/clk/samsung/clk-s3c64xx.c +++ b/drivers/clk/samsung/clk-s3c64xx.c @@ -56,11 +56,6 @@ #define GATE_ON(_id, cname, pname, o, b) \ GATE(_id, cname, pname, o, b, CLK_IGNORE_UNUSED, 0) -/* list of PLLs to be registered */ -enum s3c64xx_plls { - apll, mpll, epll, -}; - static void __iomem *reg_base; static bool is_s3c6400; @@ -364,12 +359,12 @@ GATE_CLOCKS(s3c6410_gate_clks) __initdata = { /* List of PLL clocks. */ static struct samsung_pll_clock s3c64xx_pll_clks[] __initdata = { - [apll] = PLL(pll_6552, FOUT_APLL, "fout_apll", "fin_pll", - APLL_LOCK, APLL_CON, NULL), - [mpll] = PLL(pll_6552, FOUT_MPLL, "fout_mpll", "fin_pll", - MPLL_LOCK, MPLL_CON, NULL), - [epll] = PLL(pll_6553, FOUT_EPLL, "fout_epll", "fin_pll", - EPLL_LOCK, EPLL_CON0, NULL), + PLL(pll_6552, FOUT_APLL, "fout_apll", "fin_pll", + APLL_LOCK, APLL_CON, NULL), + PLL(pll_6552, FOUT_MPLL, "fout_mpll", "fin_pll", + MPLL_LOCK, MPLL_CON, NULL), + PLL(pll_6553, FOUT_EPLL, "fout_epll", "fin_pll", + EPLL_LOCK, EPLL_CON0, NULL), }; /* Aliases for common s3c64xx clocks. */ -- cgit v1.2.3 From a3834c76a24c379347ea7ee316a9154178f98f4d Mon Sep 17 00:00:00 2001 From: Wei Yongjun Date: Wed, 17 Jan 2018 11:26:27 +0000 Subject: clk: samsung: Remove redundant dev_err call in exynos5433_cmu_probe() There is a error message within devm_ioremap_resource already, so remove the dev_err call to avoid redundant error message. Signed-off-by: Wei Yongjun Signed-off-by: Sylwester Nawrocki --- drivers/clk/samsung/clk-exynos5433.c | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/drivers/clk/samsung/clk-exynos5433.c b/drivers/clk/samsung/clk-exynos5433.c index db270908037a..9323e6b7eed5 100644 --- a/drivers/clk/samsung/clk-exynos5433.c +++ b/drivers/clk/samsung/clk-exynos5433.c @@ -5513,10 +5513,8 @@ static int __init exynos5433_cmu_probe(struct platform_device *pdev) res = platform_get_resource(pdev, IORESOURCE_MEM, 0); reg_base = devm_ioremap_resource(dev, res); - if (IS_ERR(reg_base)) { - dev_err(dev, "failed to map registers\n"); + if (IS_ERR(reg_base)) return PTR_ERR(reg_base); - } for (i = 0; i < info->nr_clk_ids; ++i) ctx->clk_data.hws[i] = ERR_PTR(-ENOENT); -- cgit v1.2.3 From 073f698dbe6bb37b226c22ac8dc69d567a08f4cb Mon Sep 17 00:00:00 2001 From: Wei Yongjun Date: Wed, 17 Jan 2018 11:26:18 +0000 Subject: clk: samsung: Remove redundant dev_err call in exynos_audss_clk_probe() There is a error message within devm_ioremap_resource already, so remove the dev_err call to avoid redundant error message. Signed-off-by: Wei Yongjun Signed-off-by: Sylwester Nawrocki --- drivers/clk/samsung/clk-exynos-audss.c | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/drivers/clk/samsung/clk-exynos-audss.c b/drivers/clk/samsung/clk-exynos-audss.c index 5bfc92ee3129..b4b057c7301c 100644 --- a/drivers/clk/samsung/clk-exynos-audss.c +++ b/drivers/clk/samsung/clk-exynos-audss.c @@ -143,10 +143,8 @@ static int exynos_audss_clk_probe(struct platform_device *pdev) res = platform_get_resource(pdev, IORESOURCE_MEM, 0); reg_base = devm_ioremap_resource(dev, res); - if (IS_ERR(reg_base)) { - dev_err(dev, "failed to map audss registers\n"); + if (IS_ERR(reg_base)) return PTR_ERR(reg_base); - } epll = ERR_PTR(-ENODEV); -- cgit v1.2.3 From c99fc5a352b24397f50e6e71d26d4e95c2cce776 Mon Sep 17 00:00:00 2001 From: Sylwester Nawrocki Date: Mon, 5 Feb 2018 15:41:58 +0100 Subject: clk: samsung: Add a git tree entry to MAINTAINERS Add a missing git tree entry for drivers/clk/samsung. Signed-off-by: Sylwester Nawrocki Acked-by: Krzysztof Kozlowski Acked-by: Chanwoo Choi --- MAINTAINERS | 1 + 1 file changed, 1 insertion(+) diff --git a/MAINTAINERS b/MAINTAINERS index 3bdc260e36b7..395ea06c427d 100644 --- a/MAINTAINERS +++ b/MAINTAINERS @@ -12189,6 +12189,7 @@ M: Tomasz Figa M: Chanwoo Choi S: Supported L: linux-samsung-soc@vger.kernel.org (moderated for non-subscribers) +T: git git://git.kernel.org/pub/scm/linux/kernel/git/snawrocki/clk.git F: drivers/clk/samsung/ F: include/dt-bindings/clock/exynos*.h F: Documentation/devicetree/bindings/clock/exynos*.txt -- cgit v1.2.3 From 5c7979246ead98a7269f418d81a637dd056a1be7 Mon Sep 17 00:00:00 2001 From: Sylwester Nawrocki Date: Mon, 5 Feb 2018 15:22:30 +0100 Subject: clk: exynos5433: Add CLK_IGNORE_UNUSED flag to sclk_ioclk_i2s1_bclk The sclk_ioclk_i2s1_bclk clock is not currently handled by any driver and disabling this clock by the clk core prevents proper operation of the I2S1 block. CLK_IGNORE_UNUSED flag is added as a temporary fix. Signed-off-by: Sylwester Nawrocki Reviewed-by: Chanwoo Choi --- drivers/clk/samsung/clk-exynos5433.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/clk/samsung/clk-exynos5433.c b/drivers/clk/samsung/clk-exynos5433.c index 9323e6b7eed5..c84326dc4b05 100644 --- a/drivers/clk/samsung/clk-exynos5433.c +++ b/drivers/clk/samsung/clk-exynos5433.c @@ -1672,7 +1672,7 @@ static const struct samsung_gate_clock peric_gate_clks[] __initconst = { ENABLE_SCLK_PERIC, 11, CLK_SET_RATE_PARENT, 0), GATE(CLK_SCLK_IOCLK_I2S1_BCLK, "sclk_ioclk_i2s1_bclk", "ioclk_i2s1_bclk_in", ENABLE_SCLK_PERIC, 10, - CLK_SET_RATE_PARENT, 0), + CLK_SET_RATE_PARENT | CLK_IGNORE_UNUSED, 0), GATE(CLK_SCLK_SPDIF, "sclk_spdif", "sclk_spdif_peric", ENABLE_SCLK_PERIC, 8, CLK_SET_RATE_PARENT, 0), GATE(CLK_SCLK_PCM1, "sclk_pcm1", "sclk_pcm1_peric", -- cgit v1.2.3 From 83942bdd992ff347442ec72d86c2d77fe51a0270 Mon Sep 17 00:00:00 2001 From: Sylwester Nawrocki Date: Mon, 12 Feb 2018 16:52:27 +0100 Subject: clk: exynos5433: Extend list of available AUD_PLL output frequencies Add one more entry to the exynos5433_aud_pll_rates table, this allows to support audio sample rates: 48000, 96000, 192000 Hz with minimum error. The M, P, S, K values re confirmed by the HW team. Signed-off-by: Sylwester Nawrocki Acked-by: Chanwoo Choi --- drivers/clk/samsung/clk-exynos5433.c | 1 + 1 file changed, 1 insertion(+) diff --git a/drivers/clk/samsung/clk-exynos5433.c b/drivers/clk/samsung/clk-exynos5433.c index c84326dc4b05..57a41824ee2e 100644 --- a/drivers/clk/samsung/clk-exynos5433.c +++ b/drivers/clk/samsung/clk-exynos5433.c @@ -765,6 +765,7 @@ static const struct samsung_pll_rate_table exynos5433_aud_pll_rates[] __initcons PLL_36XX_RATE(294912000U, 98, 1, 3, 19923), PLL_36XX_RATE(288000000U, 96, 1, 3, 0), PLL_36XX_RATE(252000000U, 84, 1, 3, 0), + PLL_36XX_RATE(196608001U, 197, 3, 3, -25690), { /* sentinel */ } }; -- cgit v1.2.3 From a8321e7887410a2b2e80ab89d1ef7b30562658ea Mon Sep 17 00:00:00 2001 From: Andrzej Hajda Date: Fri, 16 Feb 2018 15:57:48 +0100 Subject: clk: samsung: exynos3250: Fix PLL rates Rates declared in PLL rate tables should match exactly rates calculated from PLL coefficients. If that is not the case, rate of the PLL's child clock might be set not as expected. For instance, if in the PLL rates table we have a 393216000 Hz entry and the real value as returned by the PLL's recalc_rate callback is 393216003, after setting PLL's clk rate to 393216000 clk_get_rate will return 393216003. If we now attempt to set rate of a PLL's child divider clock to 393216000/2 its rate will be 131072001, rather than 196608000. That is, the divider will be set to 3 instead of 2, because 393216003/2 is greater than 196608000. To fix this issue declared rates are changed to exactly match rates generated by the PLL, as calculated from the P, M, S, K coefficients. In this patch an erroneous P value for 74176002 output frequency is also corrected. Signed-off-by: Andrzej Hajda Acked-by: Chanwoo Choi Acked-by: Tomasz Figa Signed-off-by: Sylwester Nawrocki --- drivers/clk/samsung/clk-exynos3250.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/drivers/clk/samsung/clk-exynos3250.c b/drivers/clk/samsung/clk-exynos3250.c index 1b81e283f605..ed36728424a2 100644 --- a/drivers/clk/samsung/clk-exynos3250.c +++ b/drivers/clk/samsung/clk-exynos3250.c @@ -698,7 +698,7 @@ static const struct samsung_pll_rate_table exynos3250_epll_rates[] __initconst = PLL_36XX_RATE(144000000, 96, 2, 3, 0), PLL_36XX_RATE( 96000000, 128, 2, 4, 0), PLL_36XX_RATE( 84000000, 112, 2, 4, 0), - PLL_36XX_RATE( 80000004, 106, 2, 4, 43691), + PLL_36XX_RATE( 80000003, 106, 2, 4, 43691), PLL_36XX_RATE( 73728000, 98, 2, 4, 19923), PLL_36XX_RATE( 67737598, 270, 3, 5, 62285), PLL_36XX_RATE( 65535999, 174, 2, 5, 49982), @@ -734,7 +734,7 @@ static const struct samsung_pll_rate_table exynos3250_vpll_rates[] __initconst = PLL_36XX_RATE(148352005, 98, 2, 3, 59070), PLL_36XX_RATE(108000000, 144, 2, 4, 0), PLL_36XX_RATE( 74250000, 99, 2, 4, 0), - PLL_36XX_RATE( 74176002, 98, 3, 4, 59070), + PLL_36XX_RATE( 74176002, 98, 2, 4, 59070), PLL_36XX_RATE( 54054000, 216, 3, 5, 14156), PLL_36XX_RATE( 54000000, 144, 2, 5, 0), { /* sentinel */ } -- cgit v1.2.3 From 2ac051eeabaa411ef89ae7cd5bb8e60cb41ad780 Mon Sep 17 00:00:00 2001 From: Andrzej Hajda Date: Fri, 16 Feb 2018 15:57:49 +0100 Subject: clk: samsung: exynos5250: Fix PLL rates Rates declared in PLL rate tables should match exactly rates calculated from PLL coefficients. If that is not the case, rate of the PLL's child clock might be set not as expected. For instance, if in the PLL rates table we have a 393216000 Hz entry and the real value as returned by the PLL's recalc_rate callback is 393216003, after setting PLL's clk rate to 393216000 clk_get_rate will return 393216003. If we now attempt to set rate of a PLL's child divider clock to 393216000/2 its rate will be 131072001, rather than 196608000. That is, the divider will be set to 3 instead of 2, because 393216003/2 is greater than 196608000. To fix this issue declared rates are changed to exactly match rates generated by the PLL, as calculated from the P, M, S, K coefficients. Signed-off-by: Andrzej Hajda Acked-by: Chanwoo Choi Acked-by: Tomasz Figa Signed-off-by: Sylwester Nawrocki --- drivers/clk/samsung/clk-exynos5250.c | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/drivers/clk/samsung/clk-exynos5250.c b/drivers/clk/samsung/clk-exynos5250.c index 9b073c98a891..923c608b1b95 100644 --- a/drivers/clk/samsung/clk-exynos5250.c +++ b/drivers/clk/samsung/clk-exynos5250.c @@ -711,13 +711,13 @@ static const struct samsung_pll_rate_table epll_24mhz_tbl[] __initconst = { /* sorted in descending order */ /* PLL_36XX_RATE(rate, m, p, s, k) */ PLL_36XX_RATE(192000000, 64, 2, 2, 0), - PLL_36XX_RATE(180633600, 90, 3, 2, 20762), + PLL_36XX_RATE(180633605, 90, 3, 2, 20762), PLL_36XX_RATE(180000000, 90, 3, 2, 0), PLL_36XX_RATE(73728000, 98, 2, 4, 19923), - PLL_36XX_RATE(67737600, 90, 2, 4, 20762), + PLL_36XX_RATE(67737602, 90, 2, 4, 20762), PLL_36XX_RATE(49152000, 98, 3, 4, 19923), - PLL_36XX_RATE(45158400, 90, 3, 4, 20762), - PLL_36XX_RATE(32768000, 131, 3, 5, 4719), + PLL_36XX_RATE(45158401, 90, 3, 4, 20762), + PLL_36XX_RATE(32768001, 131, 3, 5, 4719), { }, }; -- cgit v1.2.3 From cdb68fbd4e7962be742c4f29475220c5bf28d8a5 Mon Sep 17 00:00:00 2001 From: Andrzej Hajda Date: Fri, 16 Feb 2018 15:57:50 +0100 Subject: clk: samsung: exynos5260: Fix PLL rates Rates declared in PLL rate tables should match exactly rates calculated from the PLL coefficients. If that is not the case, rate of the PLL's child clock might be set not as expected. For instance, if in the PLL rates table we have a 393216000 Hz entry and the real value as returned by the PLL's recalc_rate callback is 393216003, after setting PLL's clk rate to 393216000 clk_get_rate will return 393216003. If we now attempt to set rate of a PLL's child divider clock to 393216000/2 its rate will be 131072001, rather than 196608000. That is, the divider will be set to 3 instead of 2, because 393216003/2 is greater than 196608000. To fix this issue declared rates are changed to exactly match rates generated by the PLL, as calculated from the P, M, S, K coefficients. Signed-off-by: Andrzej Hajda Acked-by: Tomasz Figa Acked-by: Chanwoo Choi Signed-off-by: Sylwester Nawrocki --- drivers/clk/samsung/clk-exynos5260.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/clk/samsung/clk-exynos5260.c b/drivers/clk/samsung/clk-exynos5260.c index fd1d9bfc151b..8eae1752d700 100644 --- a/drivers/clk/samsung/clk-exynos5260.c +++ b/drivers/clk/samsung/clk-exynos5260.c @@ -65,7 +65,7 @@ static const struct samsung_pll_rate_table pll2650_24mhz_tbl[] __initconst = { PLL_36XX_RATE(480000000, 160, 2, 2, 0), PLL_36XX_RATE(432000000, 144, 2, 2, 0), PLL_36XX_RATE(400000000, 200, 3, 2, 0), - PLL_36XX_RATE(394073130, 459, 7, 2, 49282), + PLL_36XX_RATE(394073128, 459, 7, 2, 49282), PLL_36XX_RATE(333000000, 111, 2, 2, 0), PLL_36XX_RATE(300000000, 100, 2, 2, 0), PLL_36XX_RATE(266000000, 266, 3, 3, 0), -- cgit v1.2.3 From ab0447845cffc0fd752df2ccd6b4e34006000ce4 Mon Sep 17 00:00:00 2001 From: Andrzej Hajda Date: Fri, 16 Feb 2018 15:57:51 +0100 Subject: clk: samsung: exynos5433: Fix PLL rates Rates declared in PLL rate tables should match exactly rates calculated from the PLL coefficients. If that is not the case, rate of the PLL's child clock might be set not as expected. For instance, if in the PLL rates table we have a 393216000 Hz entry and the real value as returned by the PLL's recalc_rate callback is 393216003, after setting PLL's clk rate to 393216000 clk_get_rate will return 393216003. If we now attempt to set rate of a PLL's child divider clock to 393216000/2 its rate will be 131072001, rather than 196608000. That is, the divider will be set to 3 instead of 2, because 393216003/2 is greater than 196608000. To fix this issue declared rates are changed to exactly match rates generated by the PLL, as calculated from the P, M, S, K coefficients. Signed-off-by: Andrzej Hajda Acked-by: Tomasz Figa Acked-by: Chanwoo Choi Signed-off-by: Sylwester Nawrocki --- drivers/clk/samsung/clk-exynos5433.c | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/drivers/clk/samsung/clk-exynos5433.c b/drivers/clk/samsung/clk-exynos5433.c index 57a41824ee2e..7985352ceb2f 100644 --- a/drivers/clk/samsung/clk-exynos5433.c +++ b/drivers/clk/samsung/clk-exynos5433.c @@ -729,7 +729,7 @@ static const struct samsung_pll_rate_table exynos5433_pll_rates[] __initconst = PLL_35XX_RATE(800000000U, 400, 6, 1), PLL_35XX_RATE(733000000U, 733, 12, 1), PLL_35XX_RATE(700000000U, 175, 3, 1), - PLL_35XX_RATE(667000000U, 222, 4, 1), + PLL_35XX_RATE(666000000U, 222, 4, 1), PLL_35XX_RATE(633000000U, 211, 4, 1), PLL_35XX_RATE(600000000U, 500, 5, 2), PLL_35XX_RATE(552000000U, 460, 5, 2), @@ -757,12 +757,12 @@ static const struct samsung_pll_rate_table exynos5433_pll_rates[] __initconst = /* AUD_PLL */ static const struct samsung_pll_rate_table exynos5433_aud_pll_rates[] __initconst = { PLL_36XX_RATE(400000000U, 200, 3, 2, 0), - PLL_36XX_RATE(393216000U, 197, 3, 2, -25690), + PLL_36XX_RATE(393216003U, 197, 3, 2, -25690), PLL_36XX_RATE(384000000U, 128, 2, 2, 0), - PLL_36XX_RATE(368640000U, 246, 4, 2, -15729), - PLL_36XX_RATE(361507200U, 181, 3, 2, -16148), - PLL_36XX_RATE(338688000U, 113, 2, 2, -6816), - PLL_36XX_RATE(294912000U, 98, 1, 3, 19923), + PLL_36XX_RATE(368639991U, 246, 4, 2, -15729), + PLL_36XX_RATE(361507202U, 181, 3, 2, -16148), + PLL_36XX_RATE(338687988U, 113, 2, 2, -6816), + PLL_36XX_RATE(294912002U, 98, 1, 3, 19923), PLL_36XX_RATE(288000000U, 96, 1, 3, 0), PLL_36XX_RATE(252000000U, 84, 1, 3, 0), PLL_36XX_RATE(196608001U, 197, 3, 3, -25690), -- cgit v1.2.3 From 7e4db0c2836e892766565965207eee051c8037b9 Mon Sep 17 00:00:00 2001 From: Andrzej Hajda Date: Fri, 16 Feb 2018 15:57:52 +0100 Subject: clk: samsung: exynos7: Fix PLL rates Rates declared in PLL rate tables should match exactly rates calculated from the PLL coefficients. If that is not the case, rate of the PLL's child clock might be set not as expected. For instance, if in the PLL rates table we have a 393216000 Hz entry and the real value as returned by the PLL's recalc_rate callback is 393216003, after setting PLL's clk rate to 393216000 clk_get_rate will return 393216003. If we now attempt to set rate of a PLL's child divider clock to 393216000/2 its rate will be 131072001, rather than 196608000. That is, the divider will be set to 3 instead of 2, because 393216003/2 is greater than 196608000. To fix this issue declared rates are changed to exactly match rates generated by the PLL, as calculated from the P, M, S, K coefficients. Signed-off-by: Andrzej Hajda Acked-by: Tomasz Figa Acked-by: Chanwoo Choi Signed-off-by: Sylwester Nawrocki --- drivers/clk/samsung/clk-exynos7.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/clk/samsung/clk-exynos7.c b/drivers/clk/samsung/clk-exynos7.c index 5931a4140c3d..bbfa57b4e017 100644 --- a/drivers/clk/samsung/clk-exynos7.c +++ b/drivers/clk/samsung/clk-exynos7.c @@ -140,7 +140,7 @@ static const struct samsung_div_clock topc_div_clks[] __initconst = { }; static const struct samsung_pll_rate_table pll1460x_24mhz_tbl[] __initconst = { - PLL_36XX_RATE(491520000, 20, 1, 0, 31457), + PLL_36XX_RATE(491519897, 20, 1, 0, 31457), {}, }; -- cgit v1.2.3 From 179db533c08431f509a3823077549773d519358b Mon Sep 17 00:00:00 2001 From: Andrzej Hajda Date: Fri, 16 Feb 2018 15:57:53 +0100 Subject: clk: samsung: s3c2410: Fix PLL rates Rates declared in PLL rate tables should match exactly rates calculated from the PLL coefficients. If that is not the case, rate of the PLL's child clock might be set not as expected. For instance, if in the PLL rates table we have a 393216000 Hz entry and the real value as returned by the PLL's recalc_rate callback is 393216003, after setting PLL's clk rate to 393216000 clk_get_rate will return 393216003. If we now attempt to set rate of a PLL's child divider clock to 393216000/2 its rate will be 131072001, rather than 196608000. That is, the divider will be set to 3 instead of 2, because 393216003/2 is greater than 196608000. To fix this issue declared rates are changed to exactly match rates generated by the PLL, as calculated from the P, M, S, K coefficients. Signed-off-by: Andrzej Hajda Acked-by: Tomasz Figa Acked-by: Chanwoo Choi Signed-off-by: Sylwester Nawrocki --- drivers/clk/samsung/clk-s3c2410.c | 16 ++++++++-------- 1 file changed, 8 insertions(+), 8 deletions(-) diff --git a/drivers/clk/samsung/clk-s3c2410.c b/drivers/clk/samsung/clk-s3c2410.c index e0650c33863b..d8e58a659467 100644 --- a/drivers/clk/samsung/clk-s3c2410.c +++ b/drivers/clk/samsung/clk-s3c2410.c @@ -168,7 +168,7 @@ static struct samsung_pll_rate_table pll_s3c2410_12mhz_tbl[] __initdata = { PLL_35XX_RATE(226000000, 105, 1, 1), PLL_35XX_RATE(210000000, 132, 2, 1), /* 2410 common */ - PLL_35XX_RATE(203000000, 161, 3, 1), + PLL_35XX_RATE(202800000, 161, 3, 1), PLL_35XX_RATE(192000000, 88, 1, 1), PLL_35XX_RATE(186000000, 85, 1, 1), PLL_35XX_RATE(180000000, 82, 1, 1), @@ -178,18 +178,18 @@ static struct samsung_pll_rate_table pll_s3c2410_12mhz_tbl[] __initdata = { PLL_35XX_RATE(147000000, 90, 2, 1), PLL_35XX_RATE(135000000, 82, 2, 1), PLL_35XX_RATE(124000000, 116, 1, 2), - PLL_35XX_RATE(118000000, 150, 2, 2), + PLL_35XX_RATE(118500000, 150, 2, 2), PLL_35XX_RATE(113000000, 105, 1, 2), - PLL_35XX_RATE(101000000, 127, 2, 2), + PLL_35XX_RATE(101250000, 127, 2, 2), PLL_35XX_RATE(90000000, 112, 2, 2), - PLL_35XX_RATE(85000000, 105, 2, 2), + PLL_35XX_RATE(84750000, 105, 2, 2), PLL_35XX_RATE(79000000, 71, 1, 2), - PLL_35XX_RATE(68000000, 82, 2, 2), - PLL_35XX_RATE(56000000, 142, 2, 3), + PLL_35XX_RATE(67500000, 82, 2, 2), + PLL_35XX_RATE(56250000, 142, 2, 3), PLL_35XX_RATE(48000000, 120, 2, 3), - PLL_35XX_RATE(51000000, 161, 3, 3), + PLL_35XX_RATE(50700000, 161, 3, 3), PLL_35XX_RATE(45000000, 82, 1, 3), - PLL_35XX_RATE(34000000, 82, 2, 3), + PLL_35XX_RATE(33750000, 82, 2, 3), { /* sentinel */ }, }; -- cgit v1.2.3 From 1d5013f1b64dbd692975be5db0e42bac291c6de9 Mon Sep 17 00:00:00 2001 From: Andrzej Hajda Date: Tue, 20 Feb 2018 08:05:39 +0100 Subject: clk: samsung: Add compile time PLL rate validators Rates declared in PLL rate tables should match exactly rates calculated from PLL coefficients. To avoid possible mistakes we can use compile time validation. The patch introduces such validators and expands all initializers with additional input frequency parameter, required to validate rates. Since S3C24xx PLLs requires different validators two new macros have been introduced to deal with it. Also, since PLLs 4502 and 4508 have different formulas PLL_45XX_RATE has been replaced with PLL_4508_RATE. As the patch adds only compile time validators it should not have impact on compiled code. Signed-off-by: Andrzej Hajda Acked-by: Krzysztof Kozlowski Acked-by: Tomasz Figa Acked-by: Chanwoo Choi Signed-off-by: Sylwester Nawrocki --- drivers/clk/samsung/clk-exynos3250.c | 114 +++++++++++++++++----------------- drivers/clk/samsung/clk-exynos4.c | 102 +++++++++++++++--------------- drivers/clk/samsung/clk-exynos5250.c | 54 ++++++++-------- drivers/clk/samsung/clk-exynos5260.c | 90 +++++++++++++-------------- drivers/clk/samsung/clk-exynos5410.c | 20 +++--- drivers/clk/samsung/clk-exynos5420.c | 62 +++++++++---------- drivers/clk/samsung/clk-exynos5433.c | 116 +++++++++++++++++------------------ drivers/clk/samsung/clk-exynos7.c | 2 +- drivers/clk/samsung/clk-pll.h | 48 ++++++++++++--- drivers/clk/samsung/clk-s3c2410.c | 108 ++++++++++++++++---------------- 10 files changed, 372 insertions(+), 344 deletions(-) diff --git a/drivers/clk/samsung/clk-exynos3250.c b/drivers/clk/samsung/clk-exynos3250.c index ed36728424a2..27c9d23657b3 100644 --- a/drivers/clk/samsung/clk-exynos3250.c +++ b/drivers/clk/samsung/clk-exynos3250.c @@ -670,73 +670,73 @@ static const struct samsung_gate_clock gate_clks[] __initconst = { /* APLL & MPLL & BPLL & UPLL */ static const struct samsung_pll_rate_table exynos3250_pll_rates[] __initconst = { - PLL_35XX_RATE(1200000000, 400, 4, 1), - PLL_35XX_RATE(1100000000, 275, 3, 1), - PLL_35XX_RATE(1066000000, 533, 6, 1), - PLL_35XX_RATE(1000000000, 250, 3, 1), - PLL_35XX_RATE( 960000000, 320, 4, 1), - PLL_35XX_RATE( 900000000, 300, 4, 1), - PLL_35XX_RATE( 850000000, 425, 6, 1), - PLL_35XX_RATE( 800000000, 200, 3, 1), - PLL_35XX_RATE( 700000000, 175, 3, 1), - PLL_35XX_RATE( 667000000, 667, 12, 1), - PLL_35XX_RATE( 600000000, 400, 4, 2), - PLL_35XX_RATE( 533000000, 533, 6, 2), - PLL_35XX_RATE( 520000000, 260, 3, 2), - PLL_35XX_RATE( 500000000, 250, 3, 2), - PLL_35XX_RATE( 400000000, 200, 3, 2), - PLL_35XX_RATE( 200000000, 200, 3, 3), - PLL_35XX_RATE( 100000000, 200, 3, 4), + PLL_35XX_RATE(24 * MHZ, 1200000000, 400, 4, 1), + PLL_35XX_RATE(24 * MHZ, 1100000000, 275, 3, 1), + PLL_35XX_RATE(24 * MHZ, 1066000000, 533, 6, 1), + PLL_35XX_RATE(24 * MHZ, 1000000000, 250, 3, 1), + PLL_35XX_RATE(24 * MHZ, 960000000, 320, 4, 1), + PLL_35XX_RATE(24 * MHZ, 900000000, 300, 4, 1), + PLL_35XX_RATE(24 * MHZ, 850000000, 425, 6, 1), + PLL_35XX_RATE(24 * MHZ, 800000000, 200, 3, 1), + PLL_35XX_RATE(24 * MHZ, 700000000, 175, 3, 1), + PLL_35XX_RATE(24 * MHZ, 667000000, 667, 12, 1), + PLL_35XX_RATE(24 * MHZ, 600000000, 400, 4, 2), + PLL_35XX_RATE(24 * MHZ, 533000000, 533, 6, 2), + PLL_35XX_RATE(24 * MHZ, 520000000, 260, 3, 2), + PLL_35XX_RATE(24 * MHZ, 500000000, 250, 3, 2), + PLL_35XX_RATE(24 * MHZ, 400000000, 200, 3, 2), + PLL_35XX_RATE(24 * MHZ, 200000000, 200, 3, 3), + PLL_35XX_RATE(24 * MHZ, 100000000, 200, 3, 4), { /* sentinel */ } }; /* EPLL */ static const struct samsung_pll_rate_table exynos3250_epll_rates[] __initconst = { - PLL_36XX_RATE(800000000, 200, 3, 1, 0), - PLL_36XX_RATE(288000000, 96, 2, 2, 0), - PLL_36XX_RATE(192000000, 128, 2, 3, 0), - PLL_36XX_RATE(144000000, 96, 2, 3, 0), - PLL_36XX_RATE( 96000000, 128, 2, 4, 0), - PLL_36XX_RATE( 84000000, 112, 2, 4, 0), - PLL_36XX_RATE( 80000003, 106, 2, 4, 43691), - PLL_36XX_RATE( 73728000, 98, 2, 4, 19923), - PLL_36XX_RATE( 67737598, 270, 3, 5, 62285), - PLL_36XX_RATE( 65535999, 174, 2, 5, 49982), - PLL_36XX_RATE( 50000000, 200, 3, 5, 0), - PLL_36XX_RATE( 49152002, 131, 2, 5, 4719), - PLL_36XX_RATE( 48000000, 128, 2, 5, 0), - PLL_36XX_RATE( 45158401, 180, 3, 5, 41524), + PLL_36XX_RATE(24 * MHZ, 800000000, 200, 3, 1, 0), + PLL_36XX_RATE(24 * MHZ, 288000000, 96, 2, 2, 0), + PLL_36XX_RATE(24 * MHZ, 192000000, 128, 2, 3, 0), + PLL_36XX_RATE(24 * MHZ, 144000000, 96, 2, 3, 0), + PLL_36XX_RATE(24 * MHZ, 96000000, 128, 2, 4, 0), + PLL_36XX_RATE(24 * MHZ, 84000000, 112, 2, 4, 0), + PLL_36XX_RATE(24 * MHZ, 80000003, 106, 2, 4, 43691), + PLL_36XX_RATE(24 * MHZ, 73728000, 98, 2, 4, 19923), + PLL_36XX_RATE(24 * MHZ, 67737598, 270, 3, 5, 62285), + PLL_36XX_RATE(24 * MHZ, 65535999, 174, 2, 5, 49982), + PLL_36XX_RATE(24 * MHZ, 50000000, 200, 3, 5, 0), + PLL_36XX_RATE(24 * MHZ, 49152002, 131, 2, 5, 4719), + PLL_36XX_RATE(24 * MHZ, 48000000, 128, 2, 5, 0), + PLL_36XX_RATE(24 * MHZ, 45158401, 180, 3, 5, 41524), { /* sentinel */ } }; /* VPLL */ static const struct samsung_pll_rate_table exynos3250_vpll_rates[] __initconst = { - PLL_36XX_RATE(600000000, 100, 2, 1, 0), - PLL_36XX_RATE(533000000, 266, 3, 2, 32768), - PLL_36XX_RATE(519230987, 173, 2, 2, 5046), - PLL_36XX_RATE(500000000, 250, 3, 2, 0), - PLL_36XX_RATE(445500000, 148, 2, 2, 32768), - PLL_36XX_RATE(445055007, 148, 2, 2, 23047), - PLL_36XX_RATE(400000000, 200, 3, 2, 0), - PLL_36XX_RATE(371250000, 123, 2, 2, 49152), - PLL_36XX_RATE(370878997, 185, 3, 2, 28803), - PLL_36XX_RATE(340000000, 170, 3, 2, 0), - PLL_36XX_RATE(335000015, 111, 2, 2, 43691), - PLL_36XX_RATE(333000000, 111, 2, 2, 0), - PLL_36XX_RATE(330000000, 110, 2, 2, 0), - PLL_36XX_RATE(320000015, 106, 2, 2, 43691), - PLL_36XX_RATE(300000000, 100, 2, 2, 0), - PLL_36XX_RATE(275000000, 275, 3, 3, 0), - PLL_36XX_RATE(222750000, 148, 2, 3, 32768), - PLL_36XX_RATE(222528007, 148, 2, 3, 23069), - PLL_36XX_RATE(160000000, 160, 3, 3, 0), - PLL_36XX_RATE(148500000, 99, 2, 3, 0), - PLL_36XX_RATE(148352005, 98, 2, 3, 59070), - PLL_36XX_RATE(108000000, 144, 2, 4, 0), - PLL_36XX_RATE( 74250000, 99, 2, 4, 0), - PLL_36XX_RATE( 74176002, 98, 2, 4, 59070), - PLL_36XX_RATE( 54054000, 216, 3, 5, 14156), - PLL_36XX_RATE( 54000000, 144, 2, 5, 0), + PLL_36XX_RATE(24 * MHZ, 600000000, 100, 2, 1, 0), + PLL_36XX_RATE(24 * MHZ, 533000000, 266, 3, 2, 32768), + PLL_36XX_RATE(24 * MHZ, 519230987, 173, 2, 2, 5046), + PLL_36XX_RATE(24 * MHZ, 500000000, 250, 3, 2, 0), + PLL_36XX_RATE(24 * MHZ, 445500000, 148, 2, 2, 32768), + PLL_36XX_RATE(24 * MHZ, 445055007, 148, 2, 2, 23047), + PLL_36XX_RATE(24 * MHZ, 400000000, 200, 3, 2, 0), + PLL_36XX_RATE(24 * MHZ, 371250000, 123, 2, 2, 49152), + PLL_36XX_RATE(24 * MHZ, 370878997, 185, 3, 2, 28803), + PLL_36XX_RATE(24 * MHZ, 340000000, 170, 3, 2, 0), + PLL_36XX_RATE(24 * MHZ, 335000015, 111, 2, 2, 43691), + PLL_36XX_RATE(24 * MHZ, 333000000, 111, 2, 2, 0), + PLL_36XX_RATE(24 * MHZ, 330000000, 110, 2, 2, 0), + PLL_36XX_RATE(24 * MHZ, 320000015, 106, 2, 2, 43691), + PLL_36XX_RATE(24 * MHZ, 300000000, 100, 2, 2, 0), + PLL_36XX_RATE(24 * MHZ, 275000000, 275, 3, 3, 0), + PLL_36XX_RATE(24 * MHZ, 222750000, 148, 2, 3, 32768), + PLL_36XX_RATE(24 * MHZ, 222528007, 148, 2, 3, 23069), + PLL_36XX_RATE(24 * MHZ, 160000000, 160, 3, 3, 0), + PLL_36XX_RATE(24 * MHZ, 148500000, 99, 2, 3, 0), + PLL_36XX_RATE(24 * MHZ, 148352005, 98, 2, 3, 59070), + PLL_36XX_RATE(24 * MHZ, 108000000, 144, 2, 4, 0), + PLL_36XX_RATE(24 * MHZ, 74250000, 99, 2, 4, 0), + PLL_36XX_RATE(24 * MHZ, 74176002, 98, 2, 4, 59070), + PLL_36XX_RATE(24 * MHZ, 54054000, 216, 3, 5, 14156), + PLL_36XX_RATE(24 * MHZ, 54000000, 144, 2, 5, 0), { /* sentinel */ } }; diff --git a/drivers/clk/samsung/clk-exynos4.c b/drivers/clk/samsung/clk-exynos4.c index 134f25f2a913..edf125525a36 100644 --- a/drivers/clk/samsung/clk-exynos4.c +++ b/drivers/clk/samsung/clk-exynos4.c @@ -1266,77 +1266,77 @@ static const struct of_device_id ext_clk_match[] __initconst = { /* PLLs PMS values */ static const struct samsung_pll_rate_table exynos4210_apll_rates[] __initconst = { - PLL_45XX_RATE(1200000000, 150, 3, 1, 28), - PLL_45XX_RATE(1000000000, 250, 6, 1, 28), - PLL_45XX_RATE( 800000000, 200, 6, 1, 28), - PLL_45XX_RATE( 666857142, 389, 14, 1, 13), - PLL_45XX_RATE( 600000000, 100, 4, 1, 13), - PLL_45XX_RATE( 533000000, 533, 24, 1, 5), - PLL_45XX_RATE( 500000000, 250, 6, 2, 28), - PLL_45XX_RATE( 400000000, 200, 6, 2, 28), - PLL_45XX_RATE( 200000000, 200, 6, 3, 28), + PLL_4508_RATE(24 * MHZ, 1200000000, 150, 3, 1, 28), + PLL_4508_RATE(24 * MHZ, 1000000000, 250, 6, 1, 28), + PLL_4508_RATE(24 * MHZ, 800000000, 200, 6, 1, 28), + PLL_4508_RATE(24 * MHZ, 666857142, 389, 14, 1, 13), + PLL_4508_RATE(24 * MHZ, 600000000, 100, 4, 1, 13), + PLL_4508_RATE(24 * MHZ, 533000000, 533, 24, 1, 5), + PLL_4508_RATE(24 * MHZ, 500000000, 250, 6, 2, 28), + PLL_4508_RATE(24 * MHZ, 400000000, 200, 6, 2, 28), + PLL_4508_RATE(24 * MHZ, 200000000, 200, 6, 3, 28), { /* sentinel */ } }; static const struct samsung_pll_rate_table exynos4210_epll_rates[] __initconst = { - PLL_4600_RATE(192000000, 48, 3, 1, 0, 0), - PLL_4600_RATE(180633605, 45, 3, 1, 10381, 0), - PLL_4600_RATE(180000000, 45, 3, 1, 0, 0), - PLL_4600_RATE( 73727996, 73, 3, 3, 47710, 1), - PLL_4600_RATE( 67737602, 90, 4, 3, 20762, 1), - PLL_4600_RATE( 49151992, 49, 3, 3, 9961, 0), - PLL_4600_RATE( 45158401, 45, 3, 3, 10381, 0), + PLL_4600_RATE(24 * MHZ, 192000000, 48, 3, 1, 0, 0), + PLL_4600_RATE(24 * MHZ, 180633605, 45, 3, 1, 10381, 0), + PLL_4600_RATE(24 * MHZ, 180000000, 45, 3, 1, 0, 0), + PLL_4600_RATE(24 * MHZ, 73727996, 73, 3, 3, 47710, 1), + PLL_4600_RATE(24 * MHZ, 67737602, 90, 4, 3, 20762, 1), + PLL_4600_RATE(24 * MHZ, 49151992, 49, 3, 3, 9961, 0), + PLL_4600_RATE(24 * MHZ, 45158401, 45, 3, 3, 10381, 0), { /* sentinel */ } }; static const struct samsung_pll_rate_table exynos4210_vpll_rates[] __initconst = { - PLL_4650_RATE(360000000, 44, 3, 0, 1024, 0, 14, 0), - PLL_4650_RATE(324000000, 53, 2, 1, 1024, 1, 1, 1), - PLL_4650_RATE(259617187, 63, 3, 1, 1950, 0, 20, 1), - PLL_4650_RATE(110000000, 53, 3, 2, 2048, 0, 17, 0), - PLL_4650_RATE( 55360351, 53, 3, 3, 2417, 0, 17, 0), + PLL_4650_RATE(24 * MHZ, 360000000, 44, 3, 0, 1024, 0, 14, 0), + PLL_4650_RATE(24 * MHZ, 324000000, 53, 2, 1, 1024, 1, 1, 1), + PLL_4650_RATE(24 * MHZ, 259617187, 63, 3, 1, 1950, 0, 20, 1), + PLL_4650_RATE(24 * MHZ, 110000000, 53, 3, 2, 2048, 0, 17, 0), + PLL_4650_RATE(24 * MHZ, 55360351, 53, 3, 3, 2417, 0, 17, 0), { /* sentinel */ } }; static const struct samsung_pll_rate_table exynos4x12_apll_rates[] __initconst = { - PLL_35XX_RATE(1704000000, 213, 3, 0), - PLL_35XX_RATE(1600000000, 200, 3, 0), - PLL_35XX_RATE(1500000000, 250, 4, 0), - PLL_35XX_RATE(1400000000, 175, 3, 0), - PLL_35XX_RATE(1300000000, 325, 6, 0), - PLL_35XX_RATE(1200000000, 200, 4, 0), - PLL_35XX_RATE(1100000000, 275, 6, 0), - PLL_35XX_RATE(1000000000, 125, 3, 0), - PLL_35XX_RATE( 900000000, 150, 4, 0), - PLL_35XX_RATE( 800000000, 100, 3, 0), - PLL_35XX_RATE( 700000000, 175, 3, 1), - PLL_35XX_RATE( 600000000, 200, 4, 1), - PLL_35XX_RATE( 500000000, 125, 3, 1), - PLL_35XX_RATE( 400000000, 100, 3, 1), - PLL_35XX_RATE( 300000000, 200, 4, 2), - PLL_35XX_RATE( 200000000, 100, 3, 2), + PLL_35XX_RATE(24 * MHZ, 1704000000, 213, 3, 0), + PLL_35XX_RATE(24 * MHZ, 1600000000, 200, 3, 0), + PLL_35XX_RATE(24 * MHZ, 1500000000, 250, 4, 0), + PLL_35XX_RATE(24 * MHZ, 1400000000, 175, 3, 0), + PLL_35XX_RATE(24 * MHZ, 1300000000, 325, 6, 0), + PLL_35XX_RATE(24 * MHZ, 1200000000, 200, 4, 0), + PLL_35XX_RATE(24 * MHZ, 1100000000, 275, 6, 0), + PLL_35XX_RATE(24 * MHZ, 1000000000, 125, 3, 0), + PLL_35XX_RATE(24 * MHZ, 900000000, 150, 4, 0), + PLL_35XX_RATE(24 * MHZ, 800000000, 100, 3, 0), + PLL_35XX_RATE(24 * MHZ, 700000000, 175, 3, 1), + PLL_35XX_RATE(24 * MHZ, 600000000, 200, 4, 1), + PLL_35XX_RATE(24 * MHZ, 500000000, 125, 3, 1), + PLL_35XX_RATE(24 * MHZ, 400000000, 100, 3, 1), + PLL_35XX_RATE(24 * MHZ, 300000000, 200, 4, 2), + PLL_35XX_RATE(24 * MHZ, 200000000, 100, 3, 2), { /* sentinel */ } }; static const struct samsung_pll_rate_table exynos4x12_epll_rates[] __initconst = { - PLL_36XX_RATE(192000000, 48, 3, 1, 0), - PLL_36XX_RATE(180633605, 45, 3, 1, 10381), - PLL_36XX_RATE(180000000, 45, 3, 1, 0), - PLL_36XX_RATE( 73727996, 73, 3, 3, 47710), - PLL_36XX_RATE( 67737602, 90, 4, 3, 20762), - PLL_36XX_RATE( 49151992, 49, 3, 3, 9961), - PLL_36XX_RATE( 45158401, 45, 3, 3, 10381), + PLL_36XX_RATE(24 * MHZ, 192000000, 48, 3, 1, 0), + PLL_36XX_RATE(24 * MHZ, 180633605, 45, 3, 1, 10381), + PLL_36XX_RATE(24 * MHZ, 180000000, 45, 3, 1, 0), + PLL_36XX_RATE(24 * MHZ, 73727996, 73, 3, 3, 47710), + PLL_36XX_RATE(24 * MHZ, 67737602, 90, 4, 3, 20762), + PLL_36XX_RATE(24 * MHZ, 49151992, 49, 3, 3, 9961), + PLL_36XX_RATE(24 * MHZ, 45158401, 45, 3, 3, 10381), { /* sentinel */ } }; static const struct samsung_pll_rate_table exynos4x12_vpll_rates[] __initconst = { - PLL_36XX_RATE(533000000, 133, 3, 1, 16384), - PLL_36XX_RATE(440000000, 110, 3, 1, 0), - PLL_36XX_RATE(350000000, 175, 3, 2, 0), - PLL_36XX_RATE(266000000, 133, 3, 2, 0), - PLL_36XX_RATE(160000000, 160, 3, 3, 0), - PLL_36XX_RATE(106031250, 53, 3, 2, 1024), - PLL_36XX_RATE( 53015625, 53, 3, 3, 1024), + PLL_36XX_RATE(24 * MHZ, 533000000, 133, 3, 1, 16384), + PLL_36XX_RATE(24 * MHZ, 440000000, 110, 3, 1, 0), + PLL_36XX_RATE(24 * MHZ, 350000000, 175, 3, 2, 0), + PLL_36XX_RATE(24 * MHZ, 266000000, 133, 3, 2, 0), + PLL_36XX_RATE(24 * MHZ, 160000000, 160, 3, 3, 0), + PLL_36XX_RATE(24 * MHZ, 106031250, 53, 3, 2, 1024), + PLL_36XX_RATE(24 * MHZ, 53015625, 53, 3, 3, 1024), { /* sentinel */ } }; diff --git a/drivers/clk/samsung/clk-exynos5250.c b/drivers/clk/samsung/clk-exynos5250.c index 923c608b1b95..1b3a8f9cd519 100644 --- a/drivers/clk/samsung/clk-exynos5250.c +++ b/drivers/clk/samsung/clk-exynos5250.c @@ -701,45 +701,45 @@ static const struct samsung_gate_clock exynos5250_gate_clks[] __initconst = { static const struct samsung_pll_rate_table vpll_24mhz_tbl[] __initconst = { /* sorted in descending order */ /* PLL_36XX_RATE(rate, m, p, s, k) */ - PLL_36XX_RATE(266000000, 266, 3, 3, 0), + PLL_36XX_RATE(24 * MHZ, 266000000, 266, 3, 3, 0), /* Not in UM, but need for eDP on snow */ - PLL_36XX_RATE(70500000, 94, 2, 4, 0), + PLL_36XX_RATE(24 * MHZ, 70500000, 94, 2, 4, 0), { }, }; static const struct samsung_pll_rate_table epll_24mhz_tbl[] __initconst = { /* sorted in descending order */ /* PLL_36XX_RATE(rate, m, p, s, k) */ - PLL_36XX_RATE(192000000, 64, 2, 2, 0), - PLL_36XX_RATE(180633605, 90, 3, 2, 20762), - PLL_36XX_RATE(180000000, 90, 3, 2, 0), - PLL_36XX_RATE(73728000, 98, 2, 4, 19923), - PLL_36XX_RATE(67737602, 90, 2, 4, 20762), - PLL_36XX_RATE(49152000, 98, 3, 4, 19923), - PLL_36XX_RATE(45158401, 90, 3, 4, 20762), - PLL_36XX_RATE(32768001, 131, 3, 5, 4719), + PLL_36XX_RATE(24 * MHZ, 192000000, 64, 2, 2, 0), + PLL_36XX_RATE(24 * MHZ, 180633605, 90, 3, 2, 20762), + PLL_36XX_RATE(24 * MHZ, 180000000, 90, 3, 2, 0), + PLL_36XX_RATE(24 * MHZ, 73728000, 98, 2, 4, 19923), + PLL_36XX_RATE(24 * MHZ, 67737602, 90, 2, 4, 20762), + PLL_36XX_RATE(24 * MHZ, 49152000, 98, 3, 4, 19923), + PLL_36XX_RATE(24 * MHZ, 45158401, 90, 3, 4, 20762), + PLL_36XX_RATE(24 * MHZ, 32768001, 131, 3, 5, 4719), { }, }; static const struct samsung_pll_rate_table apll_24mhz_tbl[] __initconst = { /* sorted in descending order */ - /* PLL_35XX_RATE(rate, m, p, s) */ - PLL_35XX_RATE(1700000000, 425, 6, 0), - PLL_35XX_RATE(1600000000, 200, 3, 0), - PLL_35XX_RATE(1500000000, 250, 4, 0), - PLL_35XX_RATE(1400000000, 175, 3, 0), - PLL_35XX_RATE(1300000000, 325, 6, 0), - PLL_35XX_RATE(1200000000, 200, 4, 0), - PLL_35XX_RATE(1100000000, 275, 6, 0), - PLL_35XX_RATE(1000000000, 125, 3, 0), - PLL_35XX_RATE(900000000, 150, 4, 0), - PLL_35XX_RATE(800000000, 100, 3, 0), - PLL_35XX_RATE(700000000, 175, 3, 1), - PLL_35XX_RATE(600000000, 200, 4, 1), - PLL_35XX_RATE(500000000, 125, 3, 1), - PLL_35XX_RATE(400000000, 100, 3, 1), - PLL_35XX_RATE(300000000, 200, 4, 2), - PLL_35XX_RATE(200000000, 100, 3, 2), + /* PLL_35XX_RATE(fin, rate, m, p, s) */ + PLL_35XX_RATE(24 * MHZ, 1700000000, 425, 6, 0), + PLL_35XX_RATE(24 * MHZ, 1600000000, 200, 3, 0), + PLL_35XX_RATE(24 * MHZ, 1500000000, 250, 4, 0), + PLL_35XX_RATE(24 * MHZ, 1400000000, 175, 3, 0), + PLL_35XX_RATE(24 * MHZ, 1300000000, 325, 6, 0), + PLL_35XX_RATE(24 * MHZ, 1200000000, 200, 4, 0), + PLL_35XX_RATE(24 * MHZ, 1100000000, 275, 6, 0), + PLL_35XX_RATE(24 * MHZ, 1000000000, 125, 3, 0), + PLL_35XX_RATE(24 * MHZ, 900000000, 150, 4, 0), + PLL_35XX_RATE(24 * MHZ, 800000000, 100, 3, 0), + PLL_35XX_RATE(24 * MHZ, 700000000, 175, 3, 1), + PLL_35XX_RATE(24 * MHZ, 600000000, 200, 4, 1), + PLL_35XX_RATE(24 * MHZ, 500000000, 125, 3, 1), + PLL_35XX_RATE(24 * MHZ, 400000000, 100, 3, 1), + PLL_35XX_RATE(24 * MHZ, 300000000, 200, 4, 2), + PLL_35XX_RATE(24 * MHZ, 200000000, 100, 3, 2), }; static struct samsung_pll_clock exynos5250_plls[nr_plls] __initdata = { diff --git a/drivers/clk/samsung/clk-exynos5260.c b/drivers/clk/samsung/clk-exynos5260.c index 8eae1752d700..2cc2583abd87 100644 --- a/drivers/clk/samsung/clk-exynos5260.c +++ b/drivers/clk/samsung/clk-exynos5260.c @@ -23,57 +23,57 @@ * DISP_PLL, EGL_PLL, KFC_PLL, MEM_PLL, BUS_PLL, MEDIA_PLL, G3D_PLL. */ static const struct samsung_pll_rate_table pll2550_24mhz_tbl[] __initconst = { - PLL_35XX_RATE(1700000000, 425, 6, 0), - PLL_35XX_RATE(1600000000, 200, 3, 0), - PLL_35XX_RATE(1500000000, 250, 4, 0), - PLL_35XX_RATE(1400000000, 175, 3, 0), - PLL_35XX_RATE(1300000000, 325, 6, 0), - PLL_35XX_RATE(1200000000, 400, 4, 1), - PLL_35XX_RATE(1100000000, 275, 3, 1), - PLL_35XX_RATE(1000000000, 250, 3, 1), - PLL_35XX_RATE(933000000, 311, 4, 1), - PLL_35XX_RATE(900000000, 300, 4, 1), - PLL_35XX_RATE(800000000, 200, 3, 1), - PLL_35XX_RATE(733000000, 733, 12, 1), - PLL_35XX_RATE(700000000, 175, 3, 1), - PLL_35XX_RATE(667000000, 667, 12, 1), - PLL_35XX_RATE(633000000, 211, 4, 1), - PLL_35XX_RATE(620000000, 310, 3, 2), - PLL_35XX_RATE(600000000, 400, 4, 2), - PLL_35XX_RATE(543000000, 362, 4, 2), - PLL_35XX_RATE(533000000, 533, 6, 2), - PLL_35XX_RATE(500000000, 250, 3, 2), - PLL_35XX_RATE(450000000, 300, 4, 2), - PLL_35XX_RATE(400000000, 200, 3, 2), - PLL_35XX_RATE(350000000, 175, 3, 2), - PLL_35XX_RATE(300000000, 400, 4, 3), - PLL_35XX_RATE(266000000, 266, 3, 3), - PLL_35XX_RATE(200000000, 200, 3, 3), - PLL_35XX_RATE(160000000, 160, 3, 3), + PLL_35XX_RATE(24 * MHZ, 1700000000, 425, 6, 0), + PLL_35XX_RATE(24 * MHZ, 1600000000, 200, 3, 0), + PLL_35XX_RATE(24 * MHZ, 1500000000, 250, 4, 0), + PLL_35XX_RATE(24 * MHZ, 1400000000, 175, 3, 0), + PLL_35XX_RATE(24 * MHZ, 1300000000, 325, 6, 0), + PLL_35XX_RATE(24 * MHZ, 1200000000, 400, 4, 1), + PLL_35XX_RATE(24 * MHZ, 1100000000, 275, 3, 1), + PLL_35XX_RATE(24 * MHZ, 1000000000, 250, 3, 1), + PLL_35XX_RATE(24 * MHZ, 933000000, 311, 4, 1), + PLL_35XX_RATE(24 * MHZ, 900000000, 300, 4, 1), + PLL_35XX_RATE(24 * MHZ, 800000000, 200, 3, 1), + PLL_35XX_RATE(24 * MHZ, 733000000, 733, 12, 1), + PLL_35XX_RATE(24 * MHZ, 700000000, 175, 3, 1), + PLL_35XX_RATE(24 * MHZ, 667000000, 667, 12, 1), + PLL_35XX_RATE(24 * MHZ, 633000000, 211, 4, 1), + PLL_35XX_RATE(24 * MHZ, 620000000, 310, 3, 2), + PLL_35XX_RATE(24 * MHZ, 600000000, 400, 4, 2), + PLL_35XX_RATE(24 * MHZ, 543000000, 362, 4, 2), + PLL_35XX_RATE(24 * MHZ, 533000000, 533, 6, 2), + PLL_35XX_RATE(24 * MHZ, 500000000, 250, 3, 2), + PLL_35XX_RATE(24 * MHZ, 450000000, 300, 4, 2), + PLL_35XX_RATE(24 * MHZ, 400000000, 200, 3, 2), + PLL_35XX_RATE(24 * MHZ, 350000000, 175, 3, 2), + PLL_35XX_RATE(24 * MHZ, 300000000, 400, 4, 3), + PLL_35XX_RATE(24 * MHZ, 266000000, 266, 3, 3), + PLL_35XX_RATE(24 * MHZ, 200000000, 200, 3, 3), + PLL_35XX_RATE(24 * MHZ, 160000000, 160, 3, 3), }; /* * Applicable for 2650 Type PLL for AUD_PLL. */ static const struct samsung_pll_rate_table pll2650_24mhz_tbl[] __initconst = { - PLL_36XX_RATE(1600000000, 200, 3, 0, 0), - PLL_36XX_RATE(1200000000, 100, 2, 0, 0), - PLL_36XX_RATE(1000000000, 250, 3, 1, 0), - PLL_36XX_RATE(800000000, 200, 3, 1, 0), - PLL_36XX_RATE(600000000, 100, 2, 1, 0), - PLL_36XX_RATE(532000000, 266, 3, 2, 0), - PLL_36XX_RATE(480000000, 160, 2, 2, 0), - PLL_36XX_RATE(432000000, 144, 2, 2, 0), - PLL_36XX_RATE(400000000, 200, 3, 2, 0), - PLL_36XX_RATE(394073128, 459, 7, 2, 49282), - PLL_36XX_RATE(333000000, 111, 2, 2, 0), - PLL_36XX_RATE(300000000, 100, 2, 2, 0), - PLL_36XX_RATE(266000000, 266, 3, 3, 0), - PLL_36XX_RATE(200000000, 200, 3, 3, 0), - PLL_36XX_RATE(166000000, 166, 3, 3, 0), - PLL_36XX_RATE(133000000, 266, 3, 4, 0), - PLL_36XX_RATE(100000000, 200, 3, 4, 0), - PLL_36XX_RATE(66000000, 176, 2, 5, 0), + PLL_36XX_RATE(24 * MHZ, 1600000000, 200, 3, 0, 0), + PLL_36XX_RATE(24 * MHZ, 1200000000, 100, 2, 0, 0), + PLL_36XX_RATE(24 * MHZ, 1000000000, 250, 3, 1, 0), + PLL_36XX_RATE(24 * MHZ, 800000000, 200, 3, 1, 0), + PLL_36XX_RATE(24 * MHZ, 600000000, 100, 2, 1, 0), + PLL_36XX_RATE(24 * MHZ, 532000000, 266, 3, 2, 0), + PLL_36XX_RATE(24 * MHZ, 480000000, 160, 2, 2, 0), + PLL_36XX_RATE(24 * MHZ, 432000000, 144, 2, 2, 0), + PLL_36XX_RATE(24 * MHZ, 400000000, 200, 3, 2, 0), + PLL_36XX_RATE(24 * MHZ, 394073128, 459, 7, 2, 49282), + PLL_36XX_RATE(24 * MHZ, 333000000, 111, 2, 2, 0), + PLL_36XX_RATE(24 * MHZ, 300000000, 100, 2, 2, 0), + PLL_36XX_RATE(24 * MHZ, 266000000, 266, 3, 3, 0), + PLL_36XX_RATE(24 * MHZ, 200000000, 200, 3, 3, 0), + PLL_36XX_RATE(24 * MHZ, 166000000, 166, 3, 3, 0), + PLL_36XX_RATE(24 * MHZ, 133000000, 266, 3, 4, 0), + PLL_36XX_RATE(24 * MHZ, 100000000, 200, 3, 4, 0), + PLL_36XX_RATE(24 * MHZ, 66000000, 176, 2, 5, 0), }; /* CMU_AUD */ diff --git a/drivers/clk/samsung/clk-exynos5410.c b/drivers/clk/samsung/clk-exynos5410.c index fc471a49e8f4..0a0b09591e6f 100644 --- a/drivers/clk/samsung/clk-exynos5410.c +++ b/drivers/clk/samsung/clk-exynos5410.c @@ -226,16 +226,16 @@ static const struct samsung_gate_clock exynos5410_gate_clks[] __initconst = { }; static const struct samsung_pll_rate_table exynos5410_pll2550x_24mhz_tbl[] __initconst = { - PLL_36XX_RATE(400000000U, 200, 3, 2, 0), - PLL_36XX_RATE(333000000U, 111, 2, 2, 0), - PLL_36XX_RATE(300000000U, 100, 2, 2, 0), - PLL_36XX_RATE(266000000U, 266, 3, 3, 0), - PLL_36XX_RATE(200000000U, 200, 3, 3, 0), - PLL_36XX_RATE(192000000U, 192, 3, 3, 0), - PLL_36XX_RATE(166000000U, 166, 3, 3, 0), - PLL_36XX_RATE(133000000U, 266, 3, 4, 0), - PLL_36XX_RATE(100000000U, 200, 3, 4, 0), - PLL_36XX_RATE(66000000U, 176, 2, 5, 0), + PLL_36XX_RATE(24 * MHZ, 400000000U, 200, 3, 2, 0), + PLL_36XX_RATE(24 * MHZ, 333000000U, 111, 2, 2, 0), + PLL_36XX_RATE(24 * MHZ, 300000000U, 100, 2, 2, 0), + PLL_36XX_RATE(24 * MHZ, 266000000U, 266, 3, 3, 0), + PLL_36XX_RATE(24 * MHZ, 200000000U, 200, 3, 3, 0), + PLL_36XX_RATE(24 * MHZ, 192000000U, 192, 3, 3, 0), + PLL_36XX_RATE(24 * MHZ, 166000000U, 166, 3, 3, 0), + PLL_36XX_RATE(24 * MHZ, 133000000U, 266, 3, 4, 0), + PLL_36XX_RATE(24 * MHZ, 100000000U, 200, 3, 4, 0), + PLL_36XX_RATE(24 * MHZ, 66000000U, 176, 2, 5, 0), }; static struct samsung_pll_clock exynos5410_plls[nr_plls] __initdata = { diff --git a/drivers/clk/samsung/clk-exynos5420.c b/drivers/clk/samsung/clk-exynos5420.c index 45d34f601e9e..6b10b70f7d72 100644 --- a/drivers/clk/samsung/clk-exynos5420.c +++ b/drivers/clk/samsung/clk-exynos5420.c @@ -1263,40 +1263,40 @@ static const struct samsung_gate_clock exynos5x_gate_clks[] __initconst = { }; static const struct samsung_pll_rate_table exynos5420_pll2550x_24mhz_tbl[] __initconst = { - PLL_35XX_RATE(2000000000, 250, 3, 0), - PLL_35XX_RATE(1900000000, 475, 6, 0), - PLL_35XX_RATE(1800000000, 225, 3, 0), - PLL_35XX_RATE(1700000000, 425, 6, 0), - PLL_35XX_RATE(1600000000, 200, 3, 0), - PLL_35XX_RATE(1500000000, 250, 4, 0), - PLL_35XX_RATE(1400000000, 175, 3, 0), - PLL_35XX_RATE(1300000000, 325, 6, 0), - PLL_35XX_RATE(1200000000, 200, 2, 1), - PLL_35XX_RATE(1100000000, 275, 3, 1), - PLL_35XX_RATE(1000000000, 250, 3, 1), - PLL_35XX_RATE(900000000, 150, 2, 1), - PLL_35XX_RATE(800000000, 200, 3, 1), - PLL_35XX_RATE(700000000, 175, 3, 1), - PLL_35XX_RATE(600000000, 200, 2, 2), - PLL_35XX_RATE(500000000, 250, 3, 2), - PLL_35XX_RATE(400000000, 200, 3, 2), - PLL_35XX_RATE(300000000, 200, 2, 3), - PLL_35XX_RATE(200000000, 200, 3, 3), + PLL_35XX_RATE(24 * MHZ, 2000000000, 250, 3, 0), + PLL_35XX_RATE(24 * MHZ, 1900000000, 475, 6, 0), + PLL_35XX_RATE(24 * MHZ, 1800000000, 225, 3, 0), + PLL_35XX_RATE(24 * MHZ, 1700000000, 425, 6, 0), + PLL_35XX_RATE(24 * MHZ, 1600000000, 200, 3, 0), + PLL_35XX_RATE(24 * MHZ, 1500000000, 250, 4, 0), + PLL_35XX_RATE(24 * MHZ, 1400000000, 175, 3, 0), + PLL_35XX_RATE(24 * MHZ, 1300000000, 325, 6, 0), + PLL_35XX_RATE(24 * MHZ, 1200000000, 200, 2, 1), + PLL_35XX_RATE(24 * MHZ, 1100000000, 275, 3, 1), + PLL_35XX_RATE(24 * MHZ, 1000000000, 250, 3, 1), + PLL_35XX_RATE(24 * MHZ, 900000000, 150, 2, 1), + PLL_35XX_RATE(24 * MHZ, 800000000, 200, 3, 1), + PLL_35XX_RATE(24 * MHZ, 700000000, 175, 3, 1), + PLL_35XX_RATE(24 * MHZ, 600000000, 200, 2, 2), + PLL_35XX_RATE(24 * MHZ, 500000000, 250, 3, 2), + PLL_35XX_RATE(24 * MHZ, 400000000, 200, 3, 2), + PLL_35XX_RATE(24 * MHZ, 300000000, 200, 2, 3), + PLL_35XX_RATE(24 * MHZ, 200000000, 200, 3, 3), }; static const struct samsung_pll_rate_table exynos5420_epll_24mhz_tbl[] = { - PLL_36XX_RATE(600000000U, 100, 2, 1, 0), - PLL_36XX_RATE(400000000U, 200, 3, 2, 0), - PLL_36XX_RATE(393216003U, 197, 3, 2, -25690), - PLL_36XX_RATE(361267218U, 301, 5, 2, 3671), - PLL_36XX_RATE(200000000U, 200, 3, 3, 0), - PLL_36XX_RATE(196608001U, 197, 3, 3, -25690), - PLL_36XX_RATE(180633609U, 301, 5, 3, 3671), - PLL_36XX_RATE(131072006U, 131, 3, 3, 4719), - PLL_36XX_RATE(100000000U, 200, 3, 4, 0), - PLL_36XX_RATE( 65536003U, 131, 3, 4, 4719), - PLL_36XX_RATE( 49152000U, 197, 3, 5, -25690), - PLL_36XX_RATE( 32768001U, 131, 3, 5, 4719), + PLL_36XX_RATE(24 * MHZ, 600000000U, 100, 2, 1, 0), + PLL_36XX_RATE(24 * MHZ, 400000000U, 200, 3, 2, 0), + PLL_36XX_RATE(24 * MHZ, 393216003U, 197, 3, 2, -25690), + PLL_36XX_RATE(24 * MHZ, 361267218U, 301, 5, 2, 3671), + PLL_36XX_RATE(24 * MHZ, 200000000U, 200, 3, 3, 0), + PLL_36XX_RATE(24 * MHZ, 196608001U, 197, 3, 3, -25690), + PLL_36XX_RATE(24 * MHZ, 180633609U, 301, 5, 3, 3671), + PLL_36XX_RATE(24 * MHZ, 131072006U, 131, 3, 3, 4719), + PLL_36XX_RATE(24 * MHZ, 100000000U, 200, 3, 4, 0), + PLL_36XX_RATE(24 * MHZ, 65536003U, 131, 3, 4, 4719), + PLL_36XX_RATE(24 * MHZ, 49152000U, 197, 3, 5, -25690), + PLL_36XX_RATE(24 * MHZ, 32768001U, 131, 3, 5, 4719), }; static struct samsung_pll_clock exynos5x_plls[nr_plls] __initdata = { diff --git a/drivers/clk/samsung/clk-exynos5433.c b/drivers/clk/samsung/clk-exynos5433.c index 7985352ceb2f..5305ace514b2 100644 --- a/drivers/clk/samsung/clk-exynos5433.c +++ b/drivers/clk/samsung/clk-exynos5433.c @@ -703,69 +703,69 @@ static const struct samsung_gate_clock top_gate_clks[] __initconst = { * & MPHY_PLL & G3D_PLL & DISP_PLL & ISP_PLL */ static const struct samsung_pll_rate_table exynos5433_pll_rates[] __initconst = { - PLL_35XX_RATE(2500000000U, 625, 6, 0), - PLL_35XX_RATE(2400000000U, 500, 5, 0), - PLL_35XX_RATE(2300000000U, 575, 6, 0), - PLL_35XX_RATE(2200000000U, 550, 6, 0), - PLL_35XX_RATE(2100000000U, 350, 4, 0), - PLL_35XX_RATE(2000000000U, 500, 6, 0), - PLL_35XX_RATE(1900000000U, 475, 6, 0), - PLL_35XX_RATE(1800000000U, 375, 5, 0), - PLL_35XX_RATE(1700000000U, 425, 6, 0), - PLL_35XX_RATE(1600000000U, 400, 6, 0), - PLL_35XX_RATE(1500000000U, 250, 4, 0), - PLL_35XX_RATE(1400000000U, 350, 6, 0), - PLL_35XX_RATE(1332000000U, 222, 4, 0), - PLL_35XX_RATE(1300000000U, 325, 6, 0), - PLL_35XX_RATE(1200000000U, 500, 5, 1), - PLL_35XX_RATE(1100000000U, 550, 6, 1), - PLL_35XX_RATE(1086000000U, 362, 4, 1), - PLL_35XX_RATE(1066000000U, 533, 6, 1), - PLL_35XX_RATE(1000000000U, 500, 6, 1), - PLL_35XX_RATE(933000000U, 311, 4, 1), - PLL_35XX_RATE(921000000U, 307, 4, 1), - PLL_35XX_RATE(900000000U, 375, 5, 1), - PLL_35XX_RATE(825000000U, 275, 4, 1), - PLL_35XX_RATE(800000000U, 400, 6, 1), - PLL_35XX_RATE(733000000U, 733, 12, 1), - PLL_35XX_RATE(700000000U, 175, 3, 1), - PLL_35XX_RATE(666000000U, 222, 4, 1), - PLL_35XX_RATE(633000000U, 211, 4, 1), - PLL_35XX_RATE(600000000U, 500, 5, 2), - PLL_35XX_RATE(552000000U, 460, 5, 2), - PLL_35XX_RATE(550000000U, 550, 6, 2), - PLL_35XX_RATE(543000000U, 362, 4, 2), - PLL_35XX_RATE(533000000U, 533, 6, 2), - PLL_35XX_RATE(500000000U, 500, 6, 2), - PLL_35XX_RATE(444000000U, 370, 5, 2), - PLL_35XX_RATE(420000000U, 350, 5, 2), - PLL_35XX_RATE(400000000U, 400, 6, 2), - PLL_35XX_RATE(350000000U, 350, 6, 2), - PLL_35XX_RATE(333000000U, 222, 4, 2), - PLL_35XX_RATE(300000000U, 500, 5, 3), - PLL_35XX_RATE(278000000U, 556, 6, 3), - PLL_35XX_RATE(266000000U, 532, 6, 3), - PLL_35XX_RATE(250000000U, 500, 6, 3), - PLL_35XX_RATE(200000000U, 400, 6, 3), - PLL_35XX_RATE(166000000U, 332, 6, 3), - PLL_35XX_RATE(160000000U, 320, 6, 3), - PLL_35XX_RATE(133000000U, 532, 6, 4), - PLL_35XX_RATE(100000000U, 400, 6, 4), + PLL_35XX_RATE(24 * MHZ, 2500000000U, 625, 6, 0), + PLL_35XX_RATE(24 * MHZ, 2400000000U, 500, 5, 0), + PLL_35XX_RATE(24 * MHZ, 2300000000U, 575, 6, 0), + PLL_35XX_RATE(24 * MHZ, 2200000000U, 550, 6, 0), + PLL_35XX_RATE(24 * MHZ, 2100000000U, 350, 4, 0), + PLL_35XX_RATE(24 * MHZ, 2000000000U, 500, 6, 0), + PLL_35XX_RATE(24 * MHZ, 1900000000U, 475, 6, 0), + PLL_35XX_RATE(24 * MHZ, 1800000000U, 375, 5, 0), + PLL_35XX_RATE(24 * MHZ, 1700000000U, 425, 6, 0), + PLL_35XX_RATE(24 * MHZ, 1600000000U, 400, 6, 0), + PLL_35XX_RATE(24 * MHZ, 1500000000U, 250, 4, 0), + PLL_35XX_RATE(24 * MHZ, 1400000000U, 350, 6, 0), + PLL_35XX_RATE(24 * MHZ, 1332000000U, 222, 4, 0), + PLL_35XX_RATE(24 * MHZ, 1300000000U, 325, 6, 0), + PLL_35XX_RATE(24 * MHZ, 1200000000U, 500, 5, 1), + PLL_35XX_RATE(24 * MHZ, 1100000000U, 550, 6, 1), + PLL_35XX_RATE(24 * MHZ, 1086000000U, 362, 4, 1), + PLL_35XX_RATE(24 * MHZ, 1066000000U, 533, 6, 1), + PLL_35XX_RATE(24 * MHZ, 1000000000U, 500, 6, 1), + PLL_35XX_RATE(24 * MHZ, 933000000U, 311, 4, 1), + PLL_35XX_RATE(24 * MHZ, 921000000U, 307, 4, 1), + PLL_35XX_RATE(24 * MHZ, 900000000U, 375, 5, 1), + PLL_35XX_RATE(24 * MHZ, 825000000U, 275, 4, 1), + PLL_35XX_RATE(24 * MHZ, 800000000U, 400, 6, 1), + PLL_35XX_RATE(24 * MHZ, 733000000U, 733, 12, 1), + PLL_35XX_RATE(24 * MHZ, 700000000U, 175, 3, 1), + PLL_35XX_RATE(24 * MHZ, 666000000U, 222, 4, 1), + PLL_35XX_RATE(24 * MHZ, 633000000U, 211, 4, 1), + PLL_35XX_RATE(24 * MHZ, 600000000U, 500, 5, 2), + PLL_35XX_RATE(24 * MHZ, 552000000U, 460, 5, 2), + PLL_35XX_RATE(24 * MHZ, 550000000U, 550, 6, 2), + PLL_35XX_RATE(24 * MHZ, 543000000U, 362, 4, 2), + PLL_35XX_RATE(24 * MHZ, 533000000U, 533, 6, 2), + PLL_35XX_RATE(24 * MHZ, 500000000U, 500, 6, 2), + PLL_35XX_RATE(24 * MHZ, 444000000U, 370, 5, 2), + PLL_35XX_RATE(24 * MHZ, 420000000U, 350, 5, 2), + PLL_35XX_RATE(24 * MHZ, 400000000U, 400, 6, 2), + PLL_35XX_RATE(24 * MHZ, 350000000U, 350, 6, 2), + PLL_35XX_RATE(24 * MHZ, 333000000U, 222, 4, 2), + PLL_35XX_RATE(24 * MHZ, 300000000U, 500, 5, 3), + PLL_35XX_RATE(24 * MHZ, 278000000U, 556, 6, 3), + PLL_35XX_RATE(24 * MHZ, 266000000U, 532, 6, 3), + PLL_35XX_RATE(24 * MHZ, 250000000U, 500, 6, 3), + PLL_35XX_RATE(24 * MHZ, 200000000U, 400, 6, 3), + PLL_35XX_RATE(24 * MHZ, 166000000U, 332, 6, 3), + PLL_35XX_RATE(24 * MHZ, 160000000U, 320, 6, 3), + PLL_35XX_RATE(24 * MHZ, 133000000U, 532, 6, 4), + PLL_35XX_RATE(24 * MHZ, 100000000U, 400, 6, 4), { /* sentinel */ } }; /* AUD_PLL */ static const struct samsung_pll_rate_table exynos5433_aud_pll_rates[] __initconst = { - PLL_36XX_RATE(400000000U, 200, 3, 2, 0), - PLL_36XX_RATE(393216003U, 197, 3, 2, -25690), - PLL_36XX_RATE(384000000U, 128, 2, 2, 0), - PLL_36XX_RATE(368639991U, 246, 4, 2, -15729), - PLL_36XX_RATE(361507202U, 181, 3, 2, -16148), - PLL_36XX_RATE(338687988U, 113, 2, 2, -6816), - PLL_36XX_RATE(294912002U, 98, 1, 3, 19923), - PLL_36XX_RATE(288000000U, 96, 1, 3, 0), - PLL_36XX_RATE(252000000U, 84, 1, 3, 0), - PLL_36XX_RATE(196608001U, 197, 3, 3, -25690), + PLL_36XX_RATE(24 * MHZ, 400000000U, 200, 3, 2, 0), + PLL_36XX_RATE(24 * MHZ, 393216003U, 197, 3, 2, -25690), + PLL_36XX_RATE(24 * MHZ, 384000000U, 128, 2, 2, 0), + PLL_36XX_RATE(24 * MHZ, 368639991U, 246, 4, 2, -15729), + PLL_36XX_RATE(24 * MHZ, 361507202U, 181, 3, 2, -16148), + PLL_36XX_RATE(24 * MHZ, 338687988U, 113, 2, 2, -6816), + PLL_36XX_RATE(24 * MHZ, 294912002U, 98, 1, 3, 19923), + PLL_36XX_RATE(24 * MHZ, 288000000U, 96, 1, 3, 0), + PLL_36XX_RATE(24 * MHZ, 252000000U, 84, 1, 3, 0), + PLL_36XX_RATE(24 * MHZ, 196608001U, 197, 3, 3, -25690), { /* sentinel */ } }; diff --git a/drivers/clk/samsung/clk-exynos7.c b/drivers/clk/samsung/clk-exynos7.c index bbfa57b4e017..492d51691080 100644 --- a/drivers/clk/samsung/clk-exynos7.c +++ b/drivers/clk/samsung/clk-exynos7.c @@ -140,7 +140,7 @@ static const struct samsung_div_clock topc_div_clks[] __initconst = { }; static const struct samsung_pll_rate_table pll1460x_24mhz_tbl[] __initconst = { - PLL_36XX_RATE(491519897, 20, 1, 0, 31457), + PLL_36XX_RATE(24 * MHZ, 491519897, 20, 1, 0, 31457), {}, }; diff --git a/drivers/clk/samsung/clk-pll.h b/drivers/clk/samsung/clk-pll.h index 61eb8abbfd9c..ca57b3dfa814 100644 --- a/drivers/clk/samsung/clk-pll.h +++ b/drivers/clk/samsung/clk-pll.h @@ -41,35 +41,62 @@ enum samsung_pll_type { pll_1460x, }; -#define PLL_35XX_RATE(_rate, _m, _p, _s) \ +#define PLL_RATE(_fin, _m, _p, _s, _k, _ks) \ + ((u64)(_fin) * (BIT(_ks) * (_m) + (_k)) / BIT(_ks) / ((_p) << (_s))) +#define PLL_VALID_RATE(_fin, _fout, _m, _p, _s, _k, _ks) ((_fout) + \ + BUILD_BUG_ON_ZERO(PLL_RATE(_fin, _m, _p, _s, _k, _ks) != (_fout))) + +#define PLL_35XX_RATE(_fin, _rate, _m, _p, _s) \ + { \ + .rate = PLL_VALID_RATE(_fin, _rate, \ + _m, _p, _s, 0, 16), \ + .mdiv = (_m), \ + .pdiv = (_p), \ + .sdiv = (_s), \ + } + +#define PLL_S3C2410_MPLL_RATE(_fin, _rate, _m, _p, _s) \ + { \ + .rate = PLL_VALID_RATE(_fin, _rate, \ + _m + 8, _p + 2, _s, 0, 16), \ + .mdiv = (_m), \ + .pdiv = (_p), \ + .sdiv = (_s), \ + } + +#define PLL_S3C2440_MPLL_RATE(_fin, _rate, _m, _p, _s) \ { \ - .rate = (_rate), \ + .rate = PLL_VALID_RATE(_fin, _rate, \ + 2 * (_m + 8), _p + 2, _s, 0, 16), \ .mdiv = (_m), \ .pdiv = (_p), \ .sdiv = (_s), \ } -#define PLL_36XX_RATE(_rate, _m, _p, _s, _k) \ +#define PLL_36XX_RATE(_fin, _rate, _m, _p, _s, _k) \ { \ - .rate = (_rate), \ + .rate = PLL_VALID_RATE(_fin, _rate, \ + _m, _p, _s, _k, 16), \ .mdiv = (_m), \ .pdiv = (_p), \ .sdiv = (_s), \ .kdiv = (_k), \ } -#define PLL_45XX_RATE(_rate, _m, _p, _s, _afc) \ +#define PLL_4508_RATE(_fin, _rate, _m, _p, _s, _afc) \ { \ - .rate = (_rate), \ + .rate = PLL_VALID_RATE(_fin, _rate, \ + _m, _p, _s - 1, 0, 16), \ .mdiv = (_m), \ .pdiv = (_p), \ .sdiv = (_s), \ .afc = (_afc), \ } -#define PLL_4600_RATE(_rate, _m, _p, _s, _k, _vsel) \ +#define PLL_4600_RATE(_fin, _rate, _m, _p, _s, _k, _vsel) \ { \ - .rate = (_rate), \ + .rate = PLL_VALID_RATE(_fin, _rate, \ + _m, _p, _s, _k, 16), \ .mdiv = (_m), \ .pdiv = (_p), \ .sdiv = (_s), \ @@ -77,9 +104,10 @@ enum samsung_pll_type { .vsel = (_vsel), \ } -#define PLL_4650_RATE(_rate, _m, _p, _s, _k, _mfr, _mrr, _vsel) \ +#define PLL_4650_RATE(_fin, _rate, _m, _p, _s, _k, _mfr, _mrr, _vsel) \ { \ - .rate = (_rate), \ + .rate = PLL_VALID_RATE(_fin, _rate, \ + _m, _p, _s, _k, 10), \ .mdiv = (_m), \ .pdiv = (_p), \ .sdiv = (_s), \ diff --git a/drivers/clk/samsung/clk-s3c2410.c b/drivers/clk/samsung/clk-s3c2410.c index d8e58a659467..0c6aa3e51336 100644 --- a/drivers/clk/samsung/clk-s3c2410.c +++ b/drivers/clk/samsung/clk-s3c2410.c @@ -162,34 +162,34 @@ struct samsung_clock_alias s3c2410_common_aliases[] __initdata = { static struct samsung_pll_rate_table pll_s3c2410_12mhz_tbl[] __initdata = { /* sorted in descending order */ /* 2410A extras */ - PLL_35XX_RATE(270000000, 127, 1, 1), - PLL_35XX_RATE(268000000, 126, 1, 1), - PLL_35XX_RATE(266000000, 125, 1, 1), - PLL_35XX_RATE(226000000, 105, 1, 1), - PLL_35XX_RATE(210000000, 132, 2, 1), + PLL_S3C2410_MPLL_RATE(12 * MHZ, 270000000, 127, 1, 1), + PLL_S3C2410_MPLL_RATE(12 * MHZ, 268000000, 126, 1, 1), + PLL_S3C2410_MPLL_RATE(12 * MHZ, 266000000, 125, 1, 1), + PLL_S3C2410_MPLL_RATE(12 * MHZ, 226000000, 105, 1, 1), + PLL_S3C2410_MPLL_RATE(12 * MHZ, 210000000, 132, 2, 1), /* 2410 common */ - PLL_35XX_RATE(202800000, 161, 3, 1), - PLL_35XX_RATE(192000000, 88, 1, 1), - PLL_35XX_RATE(186000000, 85, 1, 1), - PLL_35XX_RATE(180000000, 82, 1, 1), - PLL_35XX_RATE(170000000, 77, 1, 1), - PLL_35XX_RATE(158000000, 71, 1, 1), - PLL_35XX_RATE(152000000, 68, 1, 1), - PLL_35XX_RATE(147000000, 90, 2, 1), - PLL_35XX_RATE(135000000, 82, 2, 1), - PLL_35XX_RATE(124000000, 116, 1, 2), - PLL_35XX_RATE(118500000, 150, 2, 2), - PLL_35XX_RATE(113000000, 105, 1, 2), - PLL_35XX_RATE(101250000, 127, 2, 2), - PLL_35XX_RATE(90000000, 112, 2, 2), - PLL_35XX_RATE(84750000, 105, 2, 2), - PLL_35XX_RATE(79000000, 71, 1, 2), - PLL_35XX_RATE(67500000, 82, 2, 2), - PLL_35XX_RATE(56250000, 142, 2, 3), - PLL_35XX_RATE(48000000, 120, 2, 3), - PLL_35XX_RATE(50700000, 161, 3, 3), - PLL_35XX_RATE(45000000, 82, 1, 3), - PLL_35XX_RATE(33750000, 82, 2, 3), + PLL_S3C2410_MPLL_RATE(12 * MHZ, 202800000, 161, 3, 1), + PLL_S3C2410_MPLL_RATE(12 * MHZ, 192000000, 88, 1, 1), + PLL_S3C2410_MPLL_RATE(12 * MHZ, 186000000, 85, 1, 1), + PLL_S3C2410_MPLL_RATE(12 * MHZ, 180000000, 82, 1, 1), + PLL_S3C2410_MPLL_RATE(12 * MHZ, 170000000, 77, 1, 1), + PLL_S3C2410_MPLL_RATE(12 * MHZ, 158000000, 71, 1, 1), + PLL_S3C2410_MPLL_RATE(12 * MHZ, 152000000, 68, 1, 1), + PLL_S3C2410_MPLL_RATE(12 * MHZ, 147000000, 90, 2, 1), + PLL_S3C2410_MPLL_RATE(12 * MHZ, 135000000, 82, 2, 1), + PLL_S3C2410_MPLL_RATE(12 * MHZ, 124000000, 116, 1, 2), + PLL_S3C2410_MPLL_RATE(12 * MHZ, 118500000, 150, 2, 2), + PLL_S3C2410_MPLL_RATE(12 * MHZ, 113000000, 105, 1, 2), + PLL_S3C2410_MPLL_RATE(12 * MHZ, 101250000, 127, 2, 2), + PLL_S3C2410_MPLL_RATE(12 * MHZ, 90000000, 112, 2, 2), + PLL_S3C2410_MPLL_RATE(12 * MHZ, 84750000, 105, 2, 2), + PLL_S3C2410_MPLL_RATE(12 * MHZ, 79000000, 71, 1, 2), + PLL_S3C2410_MPLL_RATE(12 * MHZ, 67500000, 82, 2, 2), + PLL_S3C2410_MPLL_RATE(12 * MHZ, 56250000, 142, 2, 3), + PLL_S3C2410_MPLL_RATE(12 * MHZ, 48000000, 120, 2, 3), + PLL_S3C2410_MPLL_RATE(12 * MHZ, 50700000, 161, 3, 3), + PLL_S3C2410_MPLL_RATE(12 * MHZ, 45000000, 82, 1, 3), + PLL_S3C2410_MPLL_RATE(12 * MHZ, 33750000, 82, 2, 3), { /* sentinel */ }, }; @@ -229,33 +229,33 @@ struct samsung_clock_alias s3c2410_aliases[] __initdata = { static struct samsung_pll_rate_table pll_s3c244x_12mhz_tbl[] __initdata = { /* sorted in descending order */ - PLL_35XX_RATE(400000000, 0x5c, 1, 1), - PLL_35XX_RATE(390000000, 0x7a, 2, 1), - PLL_35XX_RATE(380000000, 0x57, 1, 1), - PLL_35XX_RATE(370000000, 0xb1, 4, 1), - PLL_35XX_RATE(360000000, 0x70, 2, 1), - PLL_35XX_RATE(350000000, 0xa7, 4, 1), - PLL_35XX_RATE(340000000, 0x4d, 1, 1), - PLL_35XX_RATE(330000000, 0x66, 2, 1), - PLL_35XX_RATE(320000000, 0x98, 4, 1), - PLL_35XX_RATE(310000000, 0x93, 4, 1), - PLL_35XX_RATE(300000000, 0x75, 3, 1), - PLL_35XX_RATE(240000000, 0x70, 1, 2), - PLL_35XX_RATE(230000000, 0x6b, 1, 2), - PLL_35XX_RATE(220000000, 0x66, 1, 2), - PLL_35XX_RATE(210000000, 0x84, 2, 2), - PLL_35XX_RATE(200000000, 0x5c, 1, 2), - PLL_35XX_RATE(190000000, 0x57, 1, 2), - PLL_35XX_RATE(180000000, 0x70, 2, 2), - PLL_35XX_RATE(170000000, 0x4d, 1, 2), - PLL_35XX_RATE(160000000, 0x98, 4, 2), - PLL_35XX_RATE(150000000, 0x75, 3, 2), - PLL_35XX_RATE(120000000, 0x70, 1, 3), - PLL_35XX_RATE(110000000, 0x66, 1, 3), - PLL_35XX_RATE(100000000, 0x5c, 1, 3), - PLL_35XX_RATE(90000000, 0x70, 2, 3), - PLL_35XX_RATE(80000000, 0x98, 4, 3), - PLL_35XX_RATE(75000000, 0x75, 3, 3), + PLL_S3C2440_MPLL_RATE(12 * MHZ, 400000000, 0x5c, 1, 1), + PLL_S3C2440_MPLL_RATE(12 * MHZ, 390000000, 0x7a, 2, 1), + PLL_S3C2440_MPLL_RATE(12 * MHZ, 380000000, 0x57, 1, 1), + PLL_S3C2440_MPLL_RATE(12 * MHZ, 370000000, 0xb1, 4, 1), + PLL_S3C2440_MPLL_RATE(12 * MHZ, 360000000, 0x70, 2, 1), + PLL_S3C2440_MPLL_RATE(12 * MHZ, 350000000, 0xa7, 4, 1), + PLL_S3C2440_MPLL_RATE(12 * MHZ, 340000000, 0x4d, 1, 1), + PLL_S3C2440_MPLL_RATE(12 * MHZ, 330000000, 0x66, 2, 1), + PLL_S3C2440_MPLL_RATE(12 * MHZ, 320000000, 0x98, 4, 1), + PLL_S3C2440_MPLL_RATE(12 * MHZ, 310000000, 0x93, 4, 1), + PLL_S3C2440_MPLL_RATE(12 * MHZ, 300000000, 0x75, 3, 1), + PLL_S3C2440_MPLL_RATE(12 * MHZ, 240000000, 0x70, 1, 2), + PLL_S3C2440_MPLL_RATE(12 * MHZ, 230000000, 0x6b, 1, 2), + PLL_S3C2440_MPLL_RATE(12 * MHZ, 220000000, 0x66, 1, 2), + PLL_S3C2440_MPLL_RATE(12 * MHZ, 210000000, 0x84, 2, 2), + PLL_S3C2440_MPLL_RATE(12 * MHZ, 200000000, 0x5c, 1, 2), + PLL_S3C2440_MPLL_RATE(12 * MHZ, 190000000, 0x57, 1, 2), + PLL_S3C2440_MPLL_RATE(12 * MHZ, 180000000, 0x70, 2, 2), + PLL_S3C2440_MPLL_RATE(12 * MHZ, 170000000, 0x4d, 1, 2), + PLL_S3C2440_MPLL_RATE(12 * MHZ, 160000000, 0x98, 4, 2), + PLL_S3C2440_MPLL_RATE(12 * MHZ, 150000000, 0x75, 3, 2), + PLL_S3C2440_MPLL_RATE(12 * MHZ, 120000000, 0x70, 1, 3), + PLL_S3C2440_MPLL_RATE(12 * MHZ, 110000000, 0x66, 1, 3), + PLL_S3C2440_MPLL_RATE(12 * MHZ, 100000000, 0x5c, 1, 3), + PLL_S3C2440_MPLL_RATE(12 * MHZ, 90000000, 0x70, 2, 3), + PLL_S3C2440_MPLL_RATE(12 * MHZ, 80000000, 0x98, 4, 3), + PLL_S3C2440_MPLL_RATE(12 * MHZ, 75000000, 0x75, 3, 3), { /* sentinel */ }, }; -- cgit v1.2.3 From af8d30ac64e1ddef50981dc039f5773f57338b1a Mon Sep 17 00:00:00 2001 From: Marek Szyprowski Date: Wed, 21 Feb 2018 11:15:22 +0100 Subject: soc: samsung: pm_domains: Add blacklisting clock handling Handling of clock reparenting will be move to clock controller driver, so add possibility to blacklist clock handling on systems, where the clock controller already does all needed operations. This is needed to avoid potential deadlock on clock reparenting during power domain on/off procedure. Signed-off-by: Marek Szyprowski Reviewed-by: Krzysztof Kozlowski Signed-off-by: Sylwester Nawrocki --- drivers/soc/samsung/pm_domains.c | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/drivers/soc/samsung/pm_domains.c b/drivers/soc/samsung/pm_domains.c index b6a436594a19..cef30bdf19b1 100644 --- a/drivers/soc/samsung/pm_domains.c +++ b/drivers/soc/samsung/pm_domains.c @@ -147,6 +147,9 @@ static __init const char *exynos_get_domain_name(struct device_node *node) return kstrdup_const(name, GFP_KERNEL); } +static const char *soc_force_no_clk[] = { +}; + static __init int exynos4_pm_init_power_domain(void) { struct device_node *np; @@ -183,6 +186,11 @@ static __init int exynos4_pm_init_power_domain(void) pd->pd.power_on = exynos_pd_power_on; pd->local_pwr_cfg = pm_domain_cfg->local_pwr_cfg; + for (i = 0; i < ARRAY_SIZE(soc_force_no_clk); i++) + if (of_find_compatible_node(NULL, NULL, + soc_force_no_clk[i])) + goto no_clk; + for (i = 0; i < MAX_CLK_PER_DOMAIN; i++) { char clk_name[8]; -- cgit v1.2.3 From b06a532bf1fa99af0d9364e5dfb8654fa78d490b Mon Sep 17 00:00:00 2001 From: Marek Szyprowski Date: Tue, 6 Mar 2018 15:33:08 +0100 Subject: clk: samsung: Add Exynos5 sub-CMU clock driver Exynos5250/5420/5800 have only one clock controller, but some of their clock depends on respective power domains. Handling integration of clock controller and power domain can be done using runtime PM feature of CCF framework. This however needs a separate struct device for each power domain. This patch adds such separate driver for a group of such clocks, which can be instantiated more than once, each time for a different power domain. Signed-off-by: Marek Szyprowski Reviewed-by: Krzysztof Kozlowski Signed-off-by: Sylwester Nawrocki --- drivers/clk/samsung/clk-exynos5-subcmu.c | 186 +++++++++++++++++++++++++++++++ drivers/clk/samsung/clk-exynos5-subcmu.h | 26 +++++ 2 files changed, 212 insertions(+) create mode 100644 drivers/clk/samsung/clk-exynos5-subcmu.c create mode 100644 drivers/clk/samsung/clk-exynos5-subcmu.h diff --git a/drivers/clk/samsung/clk-exynos5-subcmu.c b/drivers/clk/samsung/clk-exynos5-subcmu.c new file mode 100644 index 000000000000..ac3983c8adf2 --- /dev/null +++ b/drivers/clk/samsung/clk-exynos5-subcmu.c @@ -0,0 +1,186 @@ +// SPDX-License-Identifier: GPL-2.0 +// +// Copyright (c) 2018 Samsung Electronics Co., Ltd. +// Author: Marek Szyprowski +// Common Clock Framework support for Exynos5 power-domain dependent clocks + +#include +#include +#include +#include + +#include "clk.h" +#include "clk-exynos5-subcmu.h" + +static struct samsung_clk_provider *ctx; +static const struct exynos5_subcmu_info *cmu; +static int nr_cmus; + +static void exynos5_subcmu_clk_save(void __iomem *base, + struct exynos5_subcmu_reg_dump *rd, + unsigned int num_regs) +{ + for (; num_regs > 0; --num_regs, ++rd) { + rd->save = readl(base + rd->offset); + writel((rd->save & ~rd->mask) | rd->value, base + rd->offset); + rd->save &= rd->mask; + } +}; + +static void exynos5_subcmu_clk_restore(void __iomem *base, + struct exynos5_subcmu_reg_dump *rd, + unsigned int num_regs) +{ + for (; num_regs > 0; --num_regs, ++rd) + writel((readl(base + rd->offset) & ~rd->mask) | rd->save, + base + rd->offset); +} + +static void exynos5_subcmu_defer_gate(struct samsung_clk_provider *ctx, + const struct samsung_gate_clock *list, int nr_clk) +{ + while (nr_clk--) + samsung_clk_add_lookup(ctx, ERR_PTR(-EPROBE_DEFER), list++->id); +} + +/* + * Pass the needed clock provider context and register sub-CMU clocks + * + * NOTE: This function has to be called from the main, OF_CLK_DECLARE- + * initialized clock provider driver. This happens very early during boot + * process. Then this driver, during core_initcall registers two platform + * drivers: one which binds to the same device-tree node as OF_CLK_DECLARE + * driver and second, for handling its per-domain child-devices. Those + * platform drivers are bound to their devices a bit later in arch_initcall, + * when OF-core populates all device-tree nodes. + */ +void exynos5_subcmus_init(struct samsung_clk_provider *_ctx, int _nr_cmus, + const struct exynos5_subcmu_info *_cmu) +{ + ctx = _ctx; + cmu = _cmu; + nr_cmus = _nr_cmus; + + for (; _nr_cmus--; _cmu++) { + exynos5_subcmu_defer_gate(ctx, _cmu->gate_clks, + _cmu->nr_gate_clks); + exynos5_subcmu_clk_save(ctx->reg_base, _cmu->suspend_regs, + _cmu->nr_suspend_regs); + } +} + +static int __maybe_unused exynos5_subcmu_suspend(struct device *dev) +{ + struct exynos5_subcmu_info *info = dev_get_drvdata(dev); + unsigned long flags; + + spin_lock_irqsave(&ctx->lock, flags); + exynos5_subcmu_clk_save(ctx->reg_base, info->suspend_regs, + info->nr_suspend_regs); + spin_unlock_irqrestore(&ctx->lock, flags); + + return 0; +} + +static int __maybe_unused exynos5_subcmu_resume(struct device *dev) +{ + struct exynos5_subcmu_info *info = dev_get_drvdata(dev); + unsigned long flags; + + spin_lock_irqsave(&ctx->lock, flags); + exynos5_subcmu_clk_restore(ctx->reg_base, info->suspend_regs, + info->nr_suspend_regs); + spin_unlock_irqrestore(&ctx->lock, flags); + + return 0; +} + +static int __init exynos5_subcmu_probe(struct platform_device *pdev) +{ + struct device *dev = &pdev->dev; + struct exynos5_subcmu_info *info = dev_get_drvdata(dev); + + pm_runtime_set_suspended(dev); + pm_runtime_enable(dev); + pm_runtime_get(dev); + + ctx->dev = dev; + samsung_clk_register_div(ctx, info->div_clks, info->nr_div_clks); + samsung_clk_register_gate(ctx, info->gate_clks, info->nr_gate_clks); + ctx->dev = NULL; + + pm_runtime_put_sync(dev); + + return 0; +} + +static const struct dev_pm_ops exynos5_subcmu_pm_ops = { + SET_RUNTIME_PM_OPS(exynos5_subcmu_suspend, + exynos5_subcmu_resume, NULL) + SET_LATE_SYSTEM_SLEEP_PM_OPS(pm_runtime_force_suspend, + pm_runtime_force_resume) +}; + +static struct platform_driver exynos5_subcmu_driver __refdata = { + .driver = { + .name = "exynos5-subcmu", + .suppress_bind_attrs = true, + .pm = &exynos5_subcmu_pm_ops, + }, + .probe = exynos5_subcmu_probe, +}; + +static int __init exynos5_clk_register_subcmu(struct device *parent, + const struct exynos5_subcmu_info *info, + struct device_node *pd_node) +{ + struct of_phandle_args genpdspec = { .np = pd_node }; + struct platform_device *pdev; + + pdev = platform_device_alloc(info->pd_name, -1); + pdev->dev.parent = parent; + pdev->driver_override = "exynos5-subcmu"; + platform_set_drvdata(pdev, (void *)info); + of_genpd_add_device(&genpdspec, &pdev->dev); + platform_device_add(pdev); + + return 0; +} + +static int __init exynos5_clk_probe(struct platform_device *pdev) +{ + struct device_node *np; + const char *name; + int i; + + for_each_compatible_node(np, NULL, "samsung,exynos4210-pd") { + if (of_property_read_string(np, "label", &name) < 0) + continue; + for (i = 0; i < nr_cmus; i++) + if (strcmp(cmu[i].pd_name, name) == 0) + exynos5_clk_register_subcmu(&pdev->dev, + &cmu[i], np); + } + return 0; +} + +static const struct of_device_id exynos5_clk_of_match[] = { + { }, +}; + +static struct platform_driver exynos5_clk_driver __refdata = { + .driver = { + .name = "exynos5-clock", + .of_match_table = exynos5_clk_of_match, + .suppress_bind_attrs = true, + }, + .probe = exynos5_clk_probe, +}; + +static int __init exynos5_clk_drv_init(void) +{ + platform_driver_register(&exynos5_clk_driver); + platform_driver_register(&exynos5_subcmu_driver); + return 0; +} +core_initcall(exynos5_clk_drv_init); diff --git a/drivers/clk/samsung/clk-exynos5-subcmu.h b/drivers/clk/samsung/clk-exynos5-subcmu.h new file mode 100644 index 000000000000..755ee8aaa3de --- /dev/null +++ b/drivers/clk/samsung/clk-exynos5-subcmu.h @@ -0,0 +1,26 @@ +/* SPDX-License-Identifier: GPL-2.0 */ + +#ifndef __CLK_EXYNOS5_SUBCMU_H +#define __CLK_EXYNOS5_SUBCMU_H + +struct exynos5_subcmu_reg_dump { + u32 offset; + u32 value; + u32 mask; + u32 save; +}; + +struct exynos5_subcmu_info { + const struct samsung_div_clock *div_clks; + unsigned int nr_div_clks; + const struct samsung_gate_clock *gate_clks; + unsigned int nr_gate_clks; + struct exynos5_subcmu_reg_dump *suspend_regs; + unsigned int nr_suspend_regs; + const char *pd_name; +}; + +void exynos5_subcmus_init(struct samsung_clk_provider *ctx, int nr_cmus, + const struct exynos5_subcmu_info *cmu); + +#endif -- cgit v1.2.3 From ec4016ff6e60fffab2e34fe87578c6362147cb98 Mon Sep 17 00:00:00 2001 From: Marek Szyprowski Date: Tue, 6 Mar 2018 15:33:09 +0100 Subject: clk: samsung: exynos5420: Move PD-dependent clocks to Exynos5 sub-CMU Clocks related to DISP, GSC and MFC blocks require special handling for power domain turn on/off sequences. Till now this was handled by Exynos power domain driver, but that approach was limited only to some special cases. This patch moves handling of those operations to clock controller driver. This gives more flexibility and allows fine tune values of some clock-specific registers. This patch moves handling of those mentioned clocks to Exynos5 sub-CMU driver instantiated from Exynos5420 driver. Signed-off-by: Marek Szyprowski Acked-by: Krzysztof Kozlowski Signed-off-by: Sylwester Nawrocki --- drivers/clk/samsung/Makefile | 1 + drivers/clk/samsung/clk-exynos5-subcmu.c | 2 + drivers/clk/samsung/clk-exynos5420.c | 121 ++++++++++++++++++++++++------- drivers/soc/samsung/pm_domains.c | 2 + 4 files changed, 100 insertions(+), 26 deletions(-) diff --git a/drivers/clk/samsung/Makefile b/drivers/clk/samsung/Makefile index ef8900bc077f..b23d6cfac723 100644 --- a/drivers/clk/samsung/Makefile +++ b/drivers/clk/samsung/Makefile @@ -11,6 +11,7 @@ obj-$(CONFIG_SOC_EXYNOS5250) += clk-exynos5250.o obj-$(CONFIG_SOC_EXYNOS5260) += clk-exynos5260.o obj-$(CONFIG_SOC_EXYNOS5410) += clk-exynos5410.o obj-$(CONFIG_SOC_EXYNOS5420) += clk-exynos5420.o +obj-$(CONFIG_SOC_EXYNOS5420) += clk-exynos5-subcmu.o obj-$(CONFIG_EXYNOS_ARM64_COMMON_CLK) += clk-exynos5433.o obj-$(CONFIG_SOC_EXYNOS5440) += clk-exynos5440.o obj-$(CONFIG_EXYNOS_AUDSS_CLK_CON) += clk-exynos-audss.o diff --git a/drivers/clk/samsung/clk-exynos5-subcmu.c b/drivers/clk/samsung/clk-exynos5-subcmu.c index ac3983c8adf2..bea10f4b3ee2 100644 --- a/drivers/clk/samsung/clk-exynos5-subcmu.c +++ b/drivers/clk/samsung/clk-exynos5-subcmu.c @@ -165,6 +165,8 @@ static int __init exynos5_clk_probe(struct platform_device *pdev) } static const struct of_device_id exynos5_clk_of_match[] = { + { .compatible = "samsung,exynos5420-clock", }, + { .compatible = "samsung,exynos5800-clock", }, { }, }; diff --git a/drivers/clk/samsung/clk-exynos5420.c b/drivers/clk/samsung/clk-exynos5420.c index 6b10b70f7d72..c7b0f55dfbb6 100644 --- a/drivers/clk/samsung/clk-exynos5420.c +++ b/drivers/clk/samsung/clk-exynos5420.c @@ -19,6 +19,7 @@ #include "clk.h" #include "clk-cpu.h" +#include "clk-exynos5-subcmu.h" #define APLL_LOCK 0x0 #define APLL_CON0 0x100 @@ -863,7 +864,6 @@ static const struct samsung_div_clock exynos5x_div_clks[] __initconst = { DIV(0, "dout_mipi1", "mout_mipi1", DIV_DISP10, 16, 8), DIV(0, "dout_dp1", "mout_dp1", DIV_DISP10, 24, 4), DIV(CLK_DOUT_PIXEL, "dout_hdmi_pixel", "mout_pixel", DIV_DISP10, 28, 4), - DIV(0, "dout_disp1_blk", "aclk200_disp1", DIV2_RATIO0, 16, 2), DIV(CLK_DOUT_ACLK400_DISP1, "dout_aclk400_disp1", "mout_aclk400_disp1", DIV_TOP2, 4, 3), @@ -912,8 +912,6 @@ static const struct samsung_div_clock exynos5x_div_clks[] __initconst = { DIV(0, "dout_spi1", "mout_spi1", DIV_PERIC1, 24, 4), DIV(0, "dout_spi2", "mout_spi2", DIV_PERIC1, 28, 4), - /* Mfc Block */ - DIV(0, "dout_mfc_blk", "mout_user_aclk333", DIV4_RATIO, 0, 2), /* PCM */ DIV(0, "dout_pcm1", "dout_audio1", DIV_PERIC2, 16, 8), @@ -932,8 +930,6 @@ static const struct samsung_div_clock exynos5x_div_clks[] __initconst = { DIV(0, "dout_spi2_pre", "dout_spi2", DIV_PERIC4, 24, 8), /* GSCL Block */ - DIV(0, "dout_gscl_blk_300", "mout_user_aclk300_gscl", - DIV2_RATIO0, 4, 2), DIV(0, "dout_gscl_blk_333", "aclk333_432_gscl", DIV2_RATIO0, 6, 2), /* MSCL Block */ @@ -1190,8 +1186,6 @@ static const struct samsung_gate_clock exynos5x_gate_clks[] __initconst = { GATE(CLK_SCLK_GSCL_WB, "sclk_gscl_wb", "mout_user_aclk333_432_gscl", GATE_TOP_SCLK_GSCL, 7, 0, 0), - GATE(CLK_GSCL0, "gscl0", "aclk300_gscl", GATE_IP_GSCL0, 0, 0, 0), - GATE(CLK_GSCL1, "gscl1", "aclk300_gscl", GATE_IP_GSCL0, 1, 0, 0), GATE(CLK_FIMC_3AA, "fimc_3aa", "aclk333_432_gscl", GATE_IP_GSCL0, 4, 0, 0), GATE(CLK_FIMC_LITE0, "fimc_lite0", "aclk333_432_gscl", @@ -1205,10 +1199,6 @@ static const struct samsung_gate_clock exynos5x_gate_clks[] __initconst = { GATE_IP_GSCL1, 3, 0, 0), GATE(CLK_SMMU_FIMCL1, "smmu_fimcl1", "dout_gscl_blk_333", GATE_IP_GSCL1, 4, 0, 0), - GATE(CLK_SMMU_GSCL0, "smmu_gscl0", "dout_gscl_blk_300", - GATE_IP_GSCL1, 6, 0, 0), - GATE(CLK_SMMU_GSCL1, "smmu_gscl1", "dout_gscl_blk_300", - GATE_IP_GSCL1, 7, 0, 0), GATE(CLK_GSCL_WA, "gscl_wa", "sclk_gscl_wa", GATE_IP_GSCL1, 12, 0, 0), GATE(CLK_GSCL_WB, "gscl_wb", "sclk_gscl_wb", GATE_IP_GSCL1, 13, 0, 0), GATE(CLK_SMMU_FIMCL3, "smmu_fimcl3,", "dout_gscl_blk_333", @@ -1227,18 +1217,6 @@ static const struct samsung_gate_clock exynos5x_gate_clks[] __initconst = { GATE(CLK_SMMU_MSCL2, "smmu_mscl2", "dout_mscl_blk", GATE_IP_MSCL, 10, 0, 0), - GATE(CLK_FIMD1, "fimd1", "aclk300_disp1", GATE_IP_DISP1, 0, 0, 0), - GATE(CLK_DSIM1, "dsim1", "aclk200_disp1", GATE_IP_DISP1, 3, 0, 0), - GATE(CLK_DP1, "dp1", "aclk200_disp1", GATE_IP_DISP1, 4, 0, 0), - GATE(CLK_MIXER, "mixer", "aclk200_disp1", GATE_IP_DISP1, 5, 0, 0), - GATE(CLK_HDMI, "hdmi", "aclk200_disp1", GATE_IP_DISP1, 6, 0, 0), - GATE(CLK_SMMU_FIMD1M0, "smmu_fimd1m0", "dout_disp1_blk", - GATE_IP_DISP1, 7, 0, 0), - GATE(CLK_SMMU_FIMD1M1, "smmu_fimd1m1", "dout_disp1_blk", - GATE_IP_DISP1, 8, 0, 0), - GATE(CLK_SMMU_MIXER, "smmu_mixer", "aclk200_disp1", - GATE_IP_DISP1, 9, 0, 0), - /* ISP */ GATE(CLK_SCLK_UART_ISP, "sclk_uart_isp", "dout_uart_isp", GATE_TOP_SCLK_ISP, 0, CLK_SET_RATE_PARENT, 0), @@ -1255,11 +1233,98 @@ static const struct samsung_gate_clock exynos5x_gate_clks[] __initconst = { GATE(CLK_SCLK_ISP_SENSOR2, "sclk_isp_sensor2", "dout_isp_sensor2", GATE_TOP_SCLK_ISP, 12, CLK_SET_RATE_PARENT, 0), + GATE(CLK_G3D, "g3d", "mout_user_aclk_g3d", GATE_IP_G3D, 9, 0, 0), +}; + +static const struct samsung_div_clock exynos5x_disp_div_clks[] __initconst = { + DIV(0, "dout_disp1_blk", "aclk200_disp1", DIV2_RATIO0, 16, 2), +}; + +static const struct samsung_gate_clock exynos5x_disp_gate_clks[] __initconst = { + GATE(CLK_FIMD1, "fimd1", "aclk300_disp1", GATE_IP_DISP1, 0, 0, 0), + GATE(CLK_DSIM1, "dsim1", "aclk200_disp1", GATE_IP_DISP1, 3, 0, 0), + GATE(CLK_DP1, "dp1", "aclk200_disp1", GATE_IP_DISP1, 4, 0, 0), + GATE(CLK_MIXER, "mixer", "aclk200_disp1", GATE_IP_DISP1, 5, 0, 0), + GATE(CLK_HDMI, "hdmi", "aclk200_disp1", GATE_IP_DISP1, 6, 0, 0), + GATE(CLK_SMMU_FIMD1M0, "smmu_fimd1m0", "dout_disp1_blk", + GATE_IP_DISP1, 7, 0, 0), + GATE(CLK_SMMU_FIMD1M1, "smmu_fimd1m1", "dout_disp1_blk", + GATE_IP_DISP1, 8, 0, 0), + GATE(CLK_SMMU_MIXER, "smmu_mixer", "aclk200_disp1", + GATE_IP_DISP1, 9, 0, 0), +}; + +static struct exynos5_subcmu_reg_dump exynos5x_disp_suspend_regs[] = { + { GATE_IP_DISP1, 0xffffffff, 0xffffffff }, /* DISP1 gates */ + { SRC_TOP5, 0, BIT(0) }, /* MUX mout_user_aclk400_disp1 */ + { SRC_TOP5, 0, BIT(24) }, /* MUX mout_user_aclk300_disp1 */ + { SRC_TOP3, 0, BIT(8) }, /* MUX mout_user_aclk200_disp1 */ + { DIV2_RATIO0, 0, 0x30000 }, /* DIV dout_disp1_blk */ +}; + +static const struct samsung_div_clock exynos5x_gsc_div_clks[] __initconst = { + DIV(0, "dout_gscl_blk_300", "mout_user_aclk300_gscl", + DIV2_RATIO0, 4, 2), +}; + +static const struct samsung_gate_clock exynos5x_gsc_gate_clks[] __initconst = { + GATE(CLK_GSCL0, "gscl0", "aclk300_gscl", GATE_IP_GSCL0, 0, 0, 0), + GATE(CLK_GSCL1, "gscl1", "aclk300_gscl", GATE_IP_GSCL0, 1, 0, 0), + GATE(CLK_SMMU_GSCL0, "smmu_gscl0", "dout_gscl_blk_300", + GATE_IP_GSCL1, 6, 0, 0), + GATE(CLK_SMMU_GSCL1, "smmu_gscl1", "dout_gscl_blk_300", + GATE_IP_GSCL1, 7, 0, 0), +}; + +static struct exynos5_subcmu_reg_dump exynos5x_gsc_suspend_regs[] = { + { GATE_IP_GSCL0, 0x3, 0x3 }, /* GSC gates */ + { GATE_IP_GSCL1, 0xc0, 0xc0 }, /* GSC gates */ + { SRC_TOP5, 0, BIT(28) }, /* MUX mout_user_aclk300_gscl */ + { DIV2_RATIO0, 0, 0x30 }, /* DIV dout_gscl_blk_300 */ +}; + +static const struct samsung_div_clock exynos5x_mfc_div_clks[] __initconst = { + DIV(0, "dout_mfc_blk", "mout_user_aclk333", DIV4_RATIO, 0, 2), +}; + +static const struct samsung_gate_clock exynos5x_mfc_gate_clks[] __initconst = { GATE(CLK_MFC, "mfc", "aclk333", GATE_IP_MFC, 0, 0, 0), GATE(CLK_SMMU_MFCL, "smmu_mfcl", "dout_mfc_blk", GATE_IP_MFC, 1, 0, 0), GATE(CLK_SMMU_MFCR, "smmu_mfcr", "dout_mfc_blk", GATE_IP_MFC, 2, 0, 0), +}; - GATE(CLK_G3D, "g3d", "mout_user_aclk_g3d", GATE_IP_G3D, 9, 0, 0), +static struct exynos5_subcmu_reg_dump exynos5x_mfc_suspend_regs[] = { + { GATE_IP_MFC, 0xffffffff, 0xffffffff }, /* MFC gates */ + { SRC_TOP4, 0, BIT(28) }, /* MUX mout_user_aclk333 */ + { DIV4_RATIO, 0, 0x3 }, /* DIV dout_mfc_blk */ +}; + +static const struct exynos5_subcmu_info exynos5x_subcmus[] = { + { + .div_clks = exynos5x_disp_div_clks, + .nr_div_clks = ARRAY_SIZE(exynos5x_disp_div_clks), + .gate_clks = exynos5x_disp_gate_clks, + .nr_gate_clks = ARRAY_SIZE(exynos5x_disp_gate_clks), + .suspend_regs = exynos5x_disp_suspend_regs, + .nr_suspend_regs = ARRAY_SIZE(exynos5x_disp_suspend_regs), + .pd_name = "DISP", + }, { + .div_clks = exynos5x_gsc_div_clks, + .nr_div_clks = ARRAY_SIZE(exynos5x_gsc_div_clks), + .gate_clks = exynos5x_gsc_gate_clks, + .nr_gate_clks = ARRAY_SIZE(exynos5x_gsc_gate_clks), + .suspend_regs = exynos5x_gsc_suspend_regs, + .nr_suspend_regs = ARRAY_SIZE(exynos5x_gsc_suspend_regs), + .pd_name = "GSC", + }, { + .div_clks = exynos5x_mfc_div_clks, + .nr_div_clks = ARRAY_SIZE(exynos5x_mfc_div_clks), + .gate_clks = exynos5x_mfc_gate_clks, + .nr_gate_clks = ARRAY_SIZE(exynos5x_mfc_gate_clks), + .suspend_regs = exynos5x_mfc_suspend_regs, + .nr_suspend_regs = ARRAY_SIZE(exynos5x_mfc_suspend_regs), + .pd_name = "MFC", + }, }; static const struct samsung_pll_rate_table exynos5420_pll2550x_24mhz_tbl[] __initconst = { @@ -1472,6 +1537,8 @@ static void __init exynos5x_clk_init(struct device_node *np, exynos5420_kfcclk_d, ARRAY_SIZE(exynos5420_kfcclk_d), 0); exynos5420_clk_sleep_init(); + exynos5_subcmus_init(ctx, ARRAY_SIZE(exynos5x_subcmus), + exynos5x_subcmus); samsung_clk_of_add_provider(np, ctx); } @@ -1480,10 +1547,12 @@ static void __init exynos5420_clk_init(struct device_node *np) { exynos5x_clk_init(np, EXYNOS5420); } -CLK_OF_DECLARE(exynos5420_clk, "samsung,exynos5420-clock", exynos5420_clk_init); +CLK_OF_DECLARE_DRIVER(exynos5420_clk, "samsung,exynos5420-clock", + exynos5420_clk_init); static void __init exynos5800_clk_init(struct device_node *np) { exynos5x_clk_init(np, EXYNOS5800); } -CLK_OF_DECLARE(exynos5800_clk, "samsung,exynos5800-clock", exynos5800_clk_init); +CLK_OF_DECLARE_DRIVER(exynos5800_clk, "samsung,exynos5800-clock", + exynos5800_clk_init); diff --git a/drivers/soc/samsung/pm_domains.c b/drivers/soc/samsung/pm_domains.c index cef30bdf19b1..f2d6d7a09c16 100644 --- a/drivers/soc/samsung/pm_domains.c +++ b/drivers/soc/samsung/pm_domains.c @@ -148,6 +148,8 @@ static __init const char *exynos_get_domain_name(struct device_node *node) } static const char *soc_force_no_clk[] = { + "samsung,exynos5420-clock", + "samsung,exynos5800-clock", }; static __init int exynos4_pm_init_power_domain(void) -- cgit v1.2.3 From edcefb96fb07f6742fd47ac60915e76c1b77768e Mon Sep 17 00:00:00 2001 From: Marek Szyprowski Date: Tue, 6 Mar 2018 15:33:10 +0100 Subject: clk: samsung: exynos5250: Move PD-dependent clocks to Exynos5 sub-CMU Clocks related to DISP1 block require special handling for power domain turn on/off sequences. Till now this was handled by Exynos power domain driver, but that approach was limited only to some special cases. This patch moves handling of those operations to clock controller driver. This gives more flexibility and allows fine tune values of some clock-specific registers. This patch moves handling of those mentioned clocks to Exynos5 sub-CMU driver instantiated from Exynos5250 driver. Signed-off-by: Marek Szyprowski Acked-by: Krzysztof Kozlowski Signed-off-by: Sylwester Nawrocki --- drivers/clk/samsung/Makefile | 1 + drivers/clk/samsung/clk-exynos5-subcmu.c | 1 + drivers/clk/samsung/clk-exynos5250.c | 51 ++++++++++++++++++++++---------- drivers/soc/samsung/pm_domains.c | 1 + 4 files changed, 38 insertions(+), 16 deletions(-) diff --git a/drivers/clk/samsung/Makefile b/drivers/clk/samsung/Makefile index b23d6cfac723..513826393158 100644 --- a/drivers/clk/samsung/Makefile +++ b/drivers/clk/samsung/Makefile @@ -8,6 +8,7 @@ obj-$(CONFIG_SOC_EXYNOS3250) += clk-exynos3250.o obj-$(CONFIG_ARCH_EXYNOS4) += clk-exynos4.o obj-$(CONFIG_ARCH_EXYNOS4) += clk-exynos4412-isp.o obj-$(CONFIG_SOC_EXYNOS5250) += clk-exynos5250.o +obj-$(CONFIG_SOC_EXYNOS5250) += clk-exynos5-subcmu.o obj-$(CONFIG_SOC_EXYNOS5260) += clk-exynos5260.o obj-$(CONFIG_SOC_EXYNOS5410) += clk-exynos5410.o obj-$(CONFIG_SOC_EXYNOS5420) += clk-exynos5420.o diff --git a/drivers/clk/samsung/clk-exynos5-subcmu.c b/drivers/clk/samsung/clk-exynos5-subcmu.c index bea10f4b3ee2..93306283d764 100644 --- a/drivers/clk/samsung/clk-exynos5-subcmu.c +++ b/drivers/clk/samsung/clk-exynos5-subcmu.c @@ -165,6 +165,7 @@ static int __init exynos5_clk_probe(struct platform_device *pdev) } static const struct of_device_id exynos5_clk_of_match[] = { + { .compatible = "samsung,exynos5250-clock", }, { .compatible = "samsung,exynos5420-clock", }, { .compatible = "samsung,exynos5800-clock", }, { }, diff --git a/drivers/clk/samsung/clk-exynos5250.c b/drivers/clk/samsung/clk-exynos5250.c index 1b3a8f9cd519..06e5ddcb30db 100644 --- a/drivers/clk/samsung/clk-exynos5250.c +++ b/drivers/clk/samsung/clk-exynos5250.c @@ -18,6 +18,7 @@ #include "clk.h" #include "clk-cpu.h" +#include "clk-exynos5-subcmu.h" #define APLL_LOCK 0x0 #define APLL_CON0 0x100 @@ -571,17 +572,6 @@ static const struct samsung_gate_clock exynos5250_gate_clks[] __initconst = { GATE(CLK_SMMU_GSCL3, "smmu_gscl3", "mout_aclk266_gscl_sub", GATE_IP_GSCL, 10, 0, 0), - GATE(CLK_FIMD1, "fimd1", "mout_aclk200_disp1_sub", GATE_IP_DISP1, 0, 0, - 0), - GATE(CLK_MIE1, "mie1", "mout_aclk200_disp1_sub", GATE_IP_DISP1, 1, 0, - 0), - GATE(CLK_DSIM0, "dsim0", "mout_aclk200_disp1_sub", GATE_IP_DISP1, 3, 0, - 0), - GATE(CLK_DP, "dp", "mout_aclk200_disp1_sub", GATE_IP_DISP1, 4, 0, 0), - GATE(CLK_MIXER, "mixer", "mout_aclk200_disp1_sub", GATE_IP_DISP1, 5, 0, - 0), - GATE(CLK_HDMI, "hdmi", "mout_aclk200_disp1_sub", GATE_IP_DISP1, 6, 0, - 0), GATE(CLK_MFC, "mfc", "mout_aclk333_sub", GATE_IP_MFC, 0, 0, 0), GATE(CLK_SMMU_MFCR, "smmu_mfcr", "mout_aclk333_sub", GATE_IP_MFC, 1, 0, @@ -671,10 +661,6 @@ static const struct samsung_gate_clock exynos5250_gate_clks[] __initconst = { GATE(CLK_WDT, "wdt", "div_aclk66", GATE_IP_PERIS, 19, 0, 0), GATE(CLK_RTC, "rtc", "div_aclk66", GATE_IP_PERIS, 20, 0, 0), GATE(CLK_TMU, "tmu", "div_aclk66", GATE_IP_PERIS, 21, 0, 0), - GATE(CLK_SMMU_TV, "smmu_tv", "mout_aclk200_disp1_sub", - GATE_IP_DISP1, 9, 0, 0), - GATE(CLK_SMMU_FIMD1, "smmu_fimd1", "mout_aclk200_disp1_sub", - GATE_IP_DISP1, 8, 0, 0), GATE(CLK_SMMU_2D, "smmu_2d", "div_aclk200", GATE_IP_ACP, 7, 0, 0), GATE(CLK_SMMU_FIMC_ISP, "smmu_fimc_isp", "mout_aclk_266_isp_sub", GATE_IP_ISP0, 8, 0, 0), @@ -698,6 +684,38 @@ static const struct samsung_gate_clock exynos5250_gate_clks[] __initconst = { GATE_IP_ISP1, 7, 0, 0), }; +static const struct samsung_gate_clock exynos5250_disp_gate_clks[] __initconst = { + GATE(CLK_FIMD1, "fimd1", "mout_aclk200_disp1_sub", GATE_IP_DISP1, 0, 0, + 0), + GATE(CLK_MIE1, "mie1", "mout_aclk200_disp1_sub", GATE_IP_DISP1, 1, 0, + 0), + GATE(CLK_DSIM0, "dsim0", "mout_aclk200_disp1_sub", GATE_IP_DISP1, 3, 0, + 0), + GATE(CLK_DP, "dp", "mout_aclk200_disp1_sub", GATE_IP_DISP1, 4, 0, 0), + GATE(CLK_MIXER, "mixer", "mout_aclk200_disp1_sub", GATE_IP_DISP1, 5, 0, + 0), + GATE(CLK_HDMI, "hdmi", "mout_aclk200_disp1_sub", GATE_IP_DISP1, 6, 0, + 0), + GATE(CLK_SMMU_TV, "smmu_tv", "mout_aclk200_disp1_sub", + GATE_IP_DISP1, 9, 0, 0), + GATE(CLK_SMMU_FIMD1, "smmu_fimd1", "mout_aclk200_disp1_sub", + GATE_IP_DISP1, 8, 0, 0), +}; + +static struct exynos5_subcmu_reg_dump exynos5250_disp_suspend_regs[] = { + { GATE_IP_DISP1, 0xffffffff, 0xffffffff }, /* DISP1 gates */ + { SRC_TOP3, 0, BIT(4) }, /* MUX mout_aclk200_disp1_sub */ + { SRC_TOP3, 0, BIT(6) }, /* MUX mout_aclk300_disp1_sub */ +}; + +static const struct exynos5_subcmu_info exynos5250_disp_subcmu = { + .gate_clks = exynos5250_disp_gate_clks, + .nr_gate_clks = ARRAY_SIZE(exynos5250_disp_gate_clks), + .suspend_regs = exynos5250_disp_suspend_regs, + .nr_suspend_regs = ARRAY_SIZE(exynos5250_disp_suspend_regs), + .pd_name = "DISP1", +}; + static const struct samsung_pll_rate_table vpll_24mhz_tbl[] __initconst = { /* sorted in descending order */ /* PLL_36XX_RATE(rate, m, p, s, k) */ @@ -859,10 +877,11 @@ static void __init exynos5250_clk_init(struct device_node *np) __raw_writel(tmp, reg_base + PWR_CTRL2); exynos5250_clk_sleep_init(); + exynos5_subcmus_init(ctx, 1, &exynos5250_disp_subcmu); samsung_clk_of_add_provider(np, ctx); pr_info("Exynos5250: clock setup completed, armclk=%ld\n", _get_rate("div_arm2")); } -CLK_OF_DECLARE(exynos5250_clk, "samsung,exynos5250-clock", exynos5250_clk_init); +CLK_OF_DECLARE_DRIVER(exynos5250_clk, "samsung,exynos5250-clock", exynos5250_clk_init); diff --git a/drivers/soc/samsung/pm_domains.c b/drivers/soc/samsung/pm_domains.c index f2d6d7a09c16..caf45cf7aa8e 100644 --- a/drivers/soc/samsung/pm_domains.c +++ b/drivers/soc/samsung/pm_domains.c @@ -148,6 +148,7 @@ static __init const char *exynos_get_domain_name(struct device_node *node) } static const char *soc_force_no_clk[] = { + "samsung,exynos5250-clock", "samsung,exynos5420-clock", "samsung,exynos5800-clock", }; -- cgit v1.2.3 From 89e423c3f14c4a87d124e4a5437dc337b90b6f29 Mon Sep 17 00:00:00 2001 From: Peter De Schrijver Date: Thu, 25 Jan 2018 16:00:10 +0200 Subject: clk: tegra: Add la clock for Tegra210 This clock is needed by the memory built-in self test work around. Signed-off-by: Peter De Schrijver Reviewed-by: Jon Hunter Tested-by: Jon Hunter Tested-by: Hector Martin Tested-by: Andre Heider Tested-by: Mikko Perttunen Signed-off-by: Thierry Reding --- drivers/clk/tegra/clk-tegra210.c | 14 ++++++++++++++ include/dt-bindings/clock/tegra210-car.h | 2 +- 2 files changed, 15 insertions(+), 1 deletion(-) diff --git a/drivers/clk/tegra/clk-tegra210.c b/drivers/clk/tegra/clk-tegra210.c index 9e6260869eb9..f790c2dc5b5d 100644 --- a/drivers/clk/tegra/clk-tegra210.c +++ b/drivers/clk/tegra/clk-tegra210.c @@ -41,6 +41,7 @@ #define CLK_SOURCE_CSITE 0x1d4 #define CLK_SOURCE_EMC 0x19c #define CLK_SOURCE_SOR1 0x410 +#define CLK_SOURCE_LA 0x1f8 #define PLLC_BASE 0x80 #define PLLC_OUT 0x84 @@ -2654,6 +2655,13 @@ static struct tegra_periph_init_data tegra210_periph[] = { sor1_parents_idx, 0, &sor1_lock), }; +static const char * const la_parents[] = { + "pll_p", "pll_c2", "pll_c", "pll_c3", "pll_re_out1", "pll_a1", "clk_m", "pll_c4_out0" +}; + +static struct tegra_clk_periph tegra210_la = + TEGRA_CLK_PERIPH(29, 7, 9, 0, 8, 1, TEGRA_DIVIDER_ROUND_UP, 76, 0, NULL, 0); + static __init void tegra210_periph_clk_init(void __iomem *clk_base, void __iomem *pmc_base) { @@ -2700,6 +2708,12 @@ static __init void tegra210_periph_clk_init(void __iomem *clk_base, periph_clk_enb_refcnt); clks[TEGRA210_CLK_DSIB] = clk; + /* la */ + clk = tegra_clk_register_periph("la", la_parents, + ARRAY_SIZE(la_parents), &tegra210_la, clk_base, + CLK_SOURCE_LA, 0); + clks[TEGRA210_CLK_LA] = clk; + /* emc mux */ clk = clk_register_mux(NULL, "emc_mux", mux_pllmcp_clkm, ARRAY_SIZE(mux_pllmcp_clkm), 0, diff --git a/include/dt-bindings/clock/tegra210-car.h b/include/dt-bindings/clock/tegra210-car.h index 6422314e46eb..6b77e721f6b1 100644 --- a/include/dt-bindings/clock/tegra210-car.h +++ b/include/dt-bindings/clock/tegra210-car.h @@ -95,7 +95,7 @@ #define TEGRA210_CLK_CSITE 73 /* 74 */ /* 75 */ -/* 76 */ +#define TEGRA210_CLK_LA 76 /* 77 */ #define TEGRA210_CLK_SOC_THERM 78 #define TEGRA210_CLK_DTV 79 -- cgit v1.2.3 From cbfc8d0a85aa72ad66227c69b08904143dc73bbb Mon Sep 17 00:00:00 2001 From: Peter De Schrijver Date: Thu, 25 Jan 2018 16:00:11 +0200 Subject: clk: tegra: add fence_delay for clock registers To ensure writes to clock registers have properly propagated through the clock control logic and state machines, we need to ensure the writes have been posted in the registers and wait for 1us after that. Signed-off-by: Peter De Schrijver Reviewed-by: Jon Hunter Tested-by: Jon Hunter Tested-by: Hector Martin Tested-by: Andre Heider Tested-by: Mikko Perttunen Signed-off-by: Thierry Reding --- drivers/clk/tegra/clk.h | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/drivers/clk/tegra/clk.h b/drivers/clk/tegra/clk.h index 3b2763df51c2..ba7e20e6a82b 100644 --- a/drivers/clk/tegra/clk.h +++ b/drivers/clk/tegra/clk.h @@ -812,4 +812,11 @@ int tegra_pll_wait_for_lock(struct tegra_clk_pll *pll); u16 tegra_pll_get_fixed_mdiv(struct clk_hw *hw, unsigned long input_rate); int tegra_pll_p_div_to_hw(struct tegra_clk_pll *pll, u8 p_div); +/* Combined read fence with delay */ +#define fence_udelay(delay, reg) \ + do { \ + readl(reg); \ + udelay(delay); \ + } while (0) + #endif /* TEGRA_CLK_H */ -- cgit v1.2.3 From e403d00573431e1e3de1710a91c6090c60ec16af Mon Sep 17 00:00:00 2001 From: Peter De Schrijver Date: Thu, 25 Jan 2018 16:00:12 +0200 Subject: clk: tegra: MBIST work around for Tegra210 Tegra210 has a hw bug which can cause IP blocks to lock up when ungating a domain. The reason is that the logic responsible for resetting the memory built-in self test mode can come up in an undefined state because its clock is gated by a second level clock gate (SLCG). Work around this by making sure the logic will get some clock edges by ensuring the relevant clock is enabled and temporarily override the relevant SLCGs. Unfortunately for some IP blocks, the control bits for overriding the SLCGs are not in CAR, but in the IP block itself. This means we need to map a few extra register banks in the clock code. Signed-off-by: Peter De Schrijver Reviewed-by: Jon Hunter Tested-by: Jon Hunter Tested-by: Hector Martin Tested-by: Andre Heider Tested-by: Mikko Perttunen Signed-off-by: Thierry Reding fixup mbist --- drivers/clk/tegra/clk-tegra210.c | 344 ++++++++++++++++++++++++++++++++++++++- include/linux/clk/tegra.h | 1 + 2 files changed, 343 insertions(+), 2 deletions(-) diff --git a/drivers/clk/tegra/clk-tegra210.c b/drivers/clk/tegra/clk-tegra210.c index f790c2dc5b5d..946d708add1e 100644 --- a/drivers/clk/tegra/clk-tegra210.c +++ b/drivers/clk/tegra/clk-tegra210.c @@ -22,10 +22,12 @@ #include #include #include +#include #include #include #include #include +#include #include "clk.h" #include "clk-id.h" @@ -232,6 +234,30 @@ #define CLK_RST_CONTROLLER_RST_DEV_Y_SET 0x2a8 #define CLK_RST_CONTROLLER_RST_DEV_Y_CLR 0x2ac +#define LVL2_CLK_GATE_OVRA 0xf8 +#define LVL2_CLK_GATE_OVRC 0x3a0 +#define LVL2_CLK_GATE_OVRD 0x3a4 +#define LVL2_CLK_GATE_OVRE 0x554 + +/* I2S registers to handle during APE MBIST WAR */ +#define TEGRA210_I2S_BASE 0x1000 +#define TEGRA210_I2S_SIZE 0x100 +#define TEGRA210_I2S_CTRLS 5 +#define TEGRA210_I2S_CG 0x88 +#define TEGRA210_I2S_CTRL 0xa0 + +/* DISPA registers to handle during MBIST WAR */ +#define DC_CMD_DISPLAY_COMMAND 0xc8 +#define DC_COM_DSC_TOP_CTL 0xcf8 + +/* VIC register to handle during MBIST WAR */ +#define NV_PVIC_THI_SLCG_OVERRIDE_LOW 0x8c + +/* APE, DISPA and VIC base addesses needed for MBIST WAR */ +#define TEGRA210_AHUB_BASE 0x702d0000 +#define TEGRA210_DISPA_BASE 0x54200000 +#define TEGRA210_VIC_BASE 0x54340000 + /* * SDM fractional divisor is 16-bit 2's complement signed number within * (-2^12 ... 2^12-1) range. Represented in PLL data structure as unsigned @@ -256,8 +282,22 @@ static struct cpu_clk_suspend_context { } tegra210_cpu_clk_sctx; #endif +struct tegra210_domain_mbist_war { + void (*handle_lvl2_ovr)(struct tegra210_domain_mbist_war *mbist); + const u32 lvl2_offset; + const u32 lvl2_mask; + const unsigned int num_clks; + const unsigned int *clk_init_data; + struct clk_bulk_data *clks; +}; + +static struct clk **clks; + static void __iomem *clk_base; static void __iomem *pmc_base; +static void __iomem *ahub_base; +static void __iomem *dispa_base; +static void __iomem *vic_base; static unsigned long osc_freq; static unsigned long pll_ref_freq; @@ -268,6 +308,7 @@ static DEFINE_SPINLOCK(pll_re_lock); static DEFINE_SPINLOCK(pll_u_lock); static DEFINE_SPINLOCK(sor1_lock); static DEFINE_SPINLOCK(emc_lock); +static DEFINE_MUTEX(lvl2_ovr_lock); /* possible OSC frequencies in Hz */ static unsigned long tegra210_input_freq[] = { @@ -311,6 +352,8 @@ static const char *mux_pllmcp_clkm[] = { #define PLLA_MISC2_WRITE_MASK 0x06ffffff /* PLLD */ +#define PLLD_BASE_CSI_CLKSOURCE (1 << 23) + #define PLLD_MISC0_EN_SDM (1 << 16) #define PLLD_MISC0_LOCK_OVERRIDE (1 << 17) #define PLLD_MISC0_LOCK_ENABLE (1 << 18) @@ -514,6 +557,115 @@ void tegra210_set_sata_pll_seq_sw(bool state) } EXPORT_SYMBOL_GPL(tegra210_set_sata_pll_seq_sw); +static void tegra210_generic_mbist_war(struct tegra210_domain_mbist_war *mbist) +{ + u32 val; + + val = readl_relaxed(clk_base + mbist->lvl2_offset); + writel_relaxed(val | mbist->lvl2_mask, clk_base + mbist->lvl2_offset); + fence_udelay(1, clk_base); + writel_relaxed(val, clk_base + mbist->lvl2_offset); + fence_udelay(1, clk_base); +} + +static void tegra210_venc_mbist_war(struct tegra210_domain_mbist_war *mbist) +{ + u32 csi_src, ovra, ovre; + unsigned long flags = 0; + + spin_lock_irqsave(&pll_d_lock, flags); + + csi_src = readl_relaxed(clk_base + PLLD_BASE); + writel_relaxed(csi_src | PLLD_BASE_CSI_CLKSOURCE, clk_base + PLLD_BASE); + fence_udelay(1, clk_base); + + ovra = readl_relaxed(clk_base + LVL2_CLK_GATE_OVRA); + writel_relaxed(ovra | BIT(15), clk_base + LVL2_CLK_GATE_OVRA); + ovre = readl_relaxed(clk_base + LVL2_CLK_GATE_OVRE); + writel_relaxed(ovre | BIT(3), clk_base + LVL2_CLK_GATE_OVRE); + fence_udelay(1, clk_base); + + writel_relaxed(ovra, clk_base + LVL2_CLK_GATE_OVRA); + writel_relaxed(ovre, clk_base + LVL2_CLK_GATE_OVRE); + writel_relaxed(csi_src, clk_base + PLLD_BASE); + fence_udelay(1, clk_base); + + spin_unlock_irqrestore(&pll_d_lock, flags); +} + +static void tegra210_disp_mbist_war(struct tegra210_domain_mbist_war *mbist) +{ + u32 ovra, dsc_top_ctrl; + + ovra = readl_relaxed(clk_base + LVL2_CLK_GATE_OVRA); + writel_relaxed(ovra | BIT(1), clk_base + LVL2_CLK_GATE_OVRA); + fence_udelay(1, clk_base); + + dsc_top_ctrl = readl_relaxed(dispa_base + DC_COM_DSC_TOP_CTL); + writel_relaxed(dsc_top_ctrl | BIT(2), dispa_base + DC_COM_DSC_TOP_CTL); + readl_relaxed(dispa_base + DC_CMD_DISPLAY_COMMAND); + writel_relaxed(dsc_top_ctrl, dispa_base + DC_COM_DSC_TOP_CTL); + readl_relaxed(dispa_base + DC_CMD_DISPLAY_COMMAND); + + writel_relaxed(ovra, clk_base + LVL2_CLK_GATE_OVRA); + fence_udelay(1, clk_base); +} + +static void tegra210_vic_mbist_war(struct tegra210_domain_mbist_war *mbist) +{ + u32 ovre, val; + + ovre = readl_relaxed(clk_base + LVL2_CLK_GATE_OVRE); + writel_relaxed(ovre | BIT(5), clk_base + LVL2_CLK_GATE_OVRE); + fence_udelay(1, clk_base); + + val = readl_relaxed(vic_base + NV_PVIC_THI_SLCG_OVERRIDE_LOW); + writel_relaxed(val | BIT(0) | GENMASK(7, 2) | BIT(24), + vic_base + NV_PVIC_THI_SLCG_OVERRIDE_LOW); + fence_udelay(1, vic_base + NV_PVIC_THI_SLCG_OVERRIDE_LOW); + + writel_relaxed(val, vic_base + NV_PVIC_THI_SLCG_OVERRIDE_LOW); + readl(vic_base + NV_PVIC_THI_SLCG_OVERRIDE_LOW); + + writel_relaxed(ovre, clk_base + LVL2_CLK_GATE_OVRE); + fence_udelay(1, clk_base); +} + +static void tegra210_ape_mbist_war(struct tegra210_domain_mbist_war *mbist) +{ + void __iomem *i2s_base; + unsigned int i; + u32 ovrc, ovre; + + ovrc = readl_relaxed(clk_base + LVL2_CLK_GATE_OVRC); + ovre = readl_relaxed(clk_base + LVL2_CLK_GATE_OVRE); + writel_relaxed(ovrc | BIT(1), clk_base + LVL2_CLK_GATE_OVRC); + writel_relaxed(ovre | BIT(10) | BIT(11), + clk_base + LVL2_CLK_GATE_OVRE); + fence_udelay(1, clk_base); + + i2s_base = ahub_base + TEGRA210_I2S_BASE; + + for (i = 0; i < TEGRA210_I2S_CTRLS; i++) { + u32 i2s_ctrl; + + i2s_ctrl = readl_relaxed(i2s_base + TEGRA210_I2S_CTRL); + writel_relaxed(i2s_ctrl | BIT(10), + i2s_base + TEGRA210_I2S_CTRL); + writel_relaxed(0, i2s_base + TEGRA210_I2S_CG); + readl(i2s_base + TEGRA210_I2S_CG); + writel_relaxed(1, i2s_base + TEGRA210_I2S_CG); + writel_relaxed(i2s_ctrl, i2s_base + TEGRA210_I2S_CTRL); + readl(i2s_base + TEGRA210_I2S_CTRL); + + i2s_base += TEGRA210_I2S_SIZE; + } + + writel_relaxed(ovrc, clk_base + LVL2_CLK_GATE_OVRC); + writel_relaxed(ovre, clk_base + LVL2_CLK_GATE_OVRE); + fence_udelay(1, clk_base); +} + static inline void _pll_misc_chk_default(void __iomem *base, struct tegra_clk_pll_params *params, u8 misc_num, u32 default_val, u32 mask) @@ -2412,13 +2564,150 @@ static struct tegra_audio_clk_info tegra210_audio_plls[] = { { "pll_a1", &pll_a1_params, tegra_clk_pll_a1, "pll_ref" }, }; -static struct clk **clks; - static const char * const aclk_parents[] = { "pll_a1", "pll_c", "pll_p", "pll_a_out0", "pll_c2", "pll_c3", "clk_m" }; +static const unsigned int nvjpg_slcg_clkids[] = { TEGRA210_CLK_NVDEC }; +static const unsigned int nvdec_slcg_clkids[] = { TEGRA210_CLK_NVJPG }; +static const unsigned int sor_slcg_clkids[] = { TEGRA210_CLK_HDA2CODEC_2X, + TEGRA210_CLK_HDA2HDMI, TEGRA210_CLK_DISP1, TEGRA210_CLK_DISP2 }; +static const unsigned int disp_slcg_clkids[] = { TEGRA210_CLK_LA, + TEGRA210_CLK_HOST1X}; +static const unsigned int xusba_slcg_clkids[] = { TEGRA210_CLK_XUSB_HOST, + TEGRA210_CLK_XUSB_DEV }; +static const unsigned int xusbb_slcg_clkids[] = { TEGRA210_CLK_XUSB_HOST, + TEGRA210_CLK_XUSB_SS }; +static const unsigned int xusbc_slcg_clkids[] = { TEGRA210_CLK_XUSB_DEV, + TEGRA210_CLK_XUSB_SS }; +static const unsigned int venc_slcg_clkids[] = { TEGRA210_CLK_HOST1X, + TEGRA210_CLK_PLL_D }; +static const unsigned int ape_slcg_clkids[] = { TEGRA210_CLK_ACLK, + TEGRA210_CLK_I2S0, TEGRA210_CLK_I2S1, TEGRA210_CLK_I2S2, + TEGRA210_CLK_I2S3, TEGRA210_CLK_I2S4, TEGRA210_CLK_SPDIF_OUT, + TEGRA210_CLK_D_AUDIO }; +static const unsigned int vic_slcg_clkids[] = { TEGRA210_CLK_HOST1X }; + +static struct tegra210_domain_mbist_war tegra210_pg_mbist_war[] = { + [TEGRA_POWERGATE_VENC] = { + .handle_lvl2_ovr = tegra210_venc_mbist_war, + .num_clks = ARRAY_SIZE(venc_slcg_clkids), + .clk_init_data = venc_slcg_clkids, + }, + [TEGRA_POWERGATE_SATA] = { + .handle_lvl2_ovr = tegra210_generic_mbist_war, + .lvl2_offset = LVL2_CLK_GATE_OVRC, + .lvl2_mask = BIT(0) | BIT(17) | BIT(19), + }, + [TEGRA_POWERGATE_MPE] = { + .handle_lvl2_ovr = tegra210_generic_mbist_war, + .lvl2_offset = LVL2_CLK_GATE_OVRE, + .lvl2_mask = BIT(2), + }, + [TEGRA_POWERGATE_SOR] = { + .handle_lvl2_ovr = tegra210_generic_mbist_war, + .num_clks = ARRAY_SIZE(sor_slcg_clkids), + .clk_init_data = sor_slcg_clkids, + .lvl2_offset = LVL2_CLK_GATE_OVRA, + .lvl2_mask = BIT(1) | BIT(2), + }, + [TEGRA_POWERGATE_DIS] = { + .handle_lvl2_ovr = tegra210_disp_mbist_war, + .num_clks = ARRAY_SIZE(disp_slcg_clkids), + .clk_init_data = disp_slcg_clkids, + }, + [TEGRA_POWERGATE_DISB] = { + .num_clks = ARRAY_SIZE(disp_slcg_clkids), + .clk_init_data = disp_slcg_clkids, + .handle_lvl2_ovr = tegra210_generic_mbist_war, + .lvl2_offset = LVL2_CLK_GATE_OVRA, + .lvl2_mask = BIT(2), + }, + [TEGRA_POWERGATE_XUSBA] = { + .num_clks = ARRAY_SIZE(xusba_slcg_clkids), + .clk_init_data = xusba_slcg_clkids, + .handle_lvl2_ovr = tegra210_generic_mbist_war, + .lvl2_offset = LVL2_CLK_GATE_OVRC, + .lvl2_mask = BIT(30) | BIT(31), + }, + [TEGRA_POWERGATE_XUSBB] = { + .num_clks = ARRAY_SIZE(xusbb_slcg_clkids), + .clk_init_data = xusbb_slcg_clkids, + .handle_lvl2_ovr = tegra210_generic_mbist_war, + .lvl2_offset = LVL2_CLK_GATE_OVRC, + .lvl2_mask = BIT(30) | BIT(31), + }, + [TEGRA_POWERGATE_XUSBC] = { + .num_clks = ARRAY_SIZE(xusbc_slcg_clkids), + .clk_init_data = xusbc_slcg_clkids, + .handle_lvl2_ovr = tegra210_generic_mbist_war, + .lvl2_offset = LVL2_CLK_GATE_OVRC, + .lvl2_mask = BIT(30) | BIT(31), + }, + [TEGRA_POWERGATE_VIC] = { + .num_clks = ARRAY_SIZE(vic_slcg_clkids), + .clk_init_data = vic_slcg_clkids, + .handle_lvl2_ovr = tegra210_vic_mbist_war, + }, + [TEGRA_POWERGATE_NVDEC] = { + .num_clks = ARRAY_SIZE(nvdec_slcg_clkids), + .clk_init_data = nvdec_slcg_clkids, + .handle_lvl2_ovr = tegra210_generic_mbist_war, + .lvl2_offset = LVL2_CLK_GATE_OVRC, + .lvl2_mask = BIT(9) | BIT(31), + }, + [TEGRA_POWERGATE_NVJPG] = { + .num_clks = ARRAY_SIZE(nvjpg_slcg_clkids), + .clk_init_data = nvjpg_slcg_clkids, + .handle_lvl2_ovr = tegra210_generic_mbist_war, + .lvl2_offset = LVL2_CLK_GATE_OVRC, + .lvl2_mask = BIT(9) | BIT(31), + }, + [TEGRA_POWERGATE_AUD] = { + .num_clks = ARRAY_SIZE(ape_slcg_clkids), + .clk_init_data = ape_slcg_clkids, + .handle_lvl2_ovr = tegra210_ape_mbist_war, + }, + [TEGRA_POWERGATE_VE2] = { + .handle_lvl2_ovr = tegra210_generic_mbist_war, + .lvl2_offset = LVL2_CLK_GATE_OVRD, + .lvl2_mask = BIT(22), + }, +}; + +int tegra210_clk_handle_mbist_war(unsigned int id) +{ + int err; + struct tegra210_domain_mbist_war *mbist_war; + + if (id >= ARRAY_SIZE(tegra210_pg_mbist_war)) { + WARN(1, "unknown domain id in MBIST WAR handler\n"); + return -EINVAL; + } + + mbist_war = &tegra210_pg_mbist_war[id]; + if (!mbist_war->handle_lvl2_ovr) + return 0; + + if (mbist_war->num_clks && !mbist_war->clks) + return -ENODEV; + + err = clk_bulk_prepare_enable(mbist_war->num_clks, mbist_war->clks); + if (err < 0) + return err; + + mutex_lock(&lvl2_ovr_lock); + + mbist_war->handle_lvl2_ovr(mbist_war); + + mutex_unlock(&lvl2_ovr_lock); + + clk_bulk_disable_unprepare(mbist_war->num_clks, mbist_war->clks); + + return 0; +} + void tegra210_put_utmipll_in_iddq(void) { u32 reg; @@ -3163,6 +3452,37 @@ static int tegra210_reset_deassert(unsigned long id) return 0; } +static void tegra210_mbist_clk_init(void) +{ + unsigned int i, j; + + for (i = 0; i < ARRAY_SIZE(tegra210_pg_mbist_war); i++) { + unsigned int num_clks = tegra210_pg_mbist_war[i].num_clks; + struct clk_bulk_data *clk_data; + + if (!num_clks) + continue; + + clk_data = kmalloc_array(num_clks, sizeof(*clk_data), + GFP_KERNEL); + if (WARN_ON(!clk_data)) + return; + + tegra210_pg_mbist_war[i].clks = clk_data; + for (j = 0; j < num_clks; j++) { + int clk_id = tegra210_pg_mbist_war[i].clk_init_data[j]; + struct clk *clk = clks[clk_id]; + + if (WARN(IS_ERR(clk), "clk_id: %d\n", clk_id)) { + kfree(clk_data); + tegra210_pg_mbist_war[i].clks = NULL; + break; + } + clk_data[j].clk = clk; + } + } +} + /** * tegra210_clock_init - Tegra210-specific clock initialization * @np: struct device_node * of the DT node for the SoC CAR IP block @@ -3197,6 +3517,24 @@ static void __init tegra210_clock_init(struct device_node *np) return; } + ahub_base = ioremap(TEGRA210_AHUB_BASE, SZ_64K); + if (!ahub_base) { + pr_err("ioremap tegra210 APE failed\n"); + return; + } + + dispa_base = ioremap(TEGRA210_DISPA_BASE, SZ_256K); + if (!dispa_base) { + pr_err("ioremap tegra210 DISPA failed\n"); + return; + } + + vic_base = ioremap(TEGRA210_VIC_BASE, SZ_256K); + if (!vic_base) { + pr_err("ioremap tegra210 VIC failed\n"); + return; + } + clks = tegra_clk_init(clk_base, TEGRA210_CLK_CLK_MAX, TEGRA210_CAR_BANK_COUNT); if (!clks) @@ -3233,6 +3571,8 @@ static void __init tegra210_clock_init(struct device_node *np) tegra_add_of_provider(np); tegra_register_devclks(devclks, ARRAY_SIZE(devclks)); + tegra210_mbist_clk_init(); + tegra_cpu_car_ops = &tegra210_cpu_car_ops; } CLK_OF_DECLARE(tegra210, "nvidia,tegra210-car", tegra210_clock_init); diff --git a/include/linux/clk/tegra.h b/include/linux/clk/tegra.h index d23c9cf26993..afb9edfa5d58 100644 --- a/include/linux/clk/tegra.h +++ b/include/linux/clk/tegra.h @@ -128,5 +128,6 @@ extern void tegra210_sata_pll_hw_sequence_start(void); extern void tegra210_set_sata_pll_seq_sw(bool state); extern void tegra210_put_utmipll_in_iddq(void); extern void tegra210_put_utmipll_out_iddq(void); +extern int tegra210_clk_handle_mbist_war(unsigned int id); #endif /* __LINUX_CLK_TEGRA_H_ */ -- cgit v1.2.3 From 06255a92793925474ea806d0c46ed8a82c49bcc7 Mon Sep 17 00:00:00 2001 From: Sylwester Nawrocki Date: Wed, 7 Mar 2018 17:46:55 +0100 Subject: clk: samsung: exynos5420: Add CLK_SET_RATE_PARENT flag to mout_mau_epll_clk This allows changing the EPLL output frequency through the audio subsystem clock tree leaf clocks. This change is needed to support audio on the HDMI interface on Peach-Pi(t) Chromebook. Signed-off-by: Sylwester Nawrocki Acked-by: Chanwoo Choi Signed-off-by: Sylwester Nawrocki --- drivers/clk/samsung/clk-exynos5420.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/drivers/clk/samsung/clk-exynos5420.c b/drivers/clk/samsung/clk-exynos5420.c index c7b0f55dfbb6..1bb6e103509f 100644 --- a/drivers/clk/samsung/clk-exynos5420.c +++ b/drivers/clk/samsung/clk-exynos5420.c @@ -621,7 +621,8 @@ static const struct samsung_mux_clock exynos5420_mux_clks[] __initconst = { MUX(CLK_MOUT_MX_MSPLL_CCORE, "mout_mx_mspll_ccore", mout_group5_5800_p, SRC_TOP7, 16, 2), - MUX(0, "mout_mau_epll_clk", mout_mau_epll_clk_p, SRC_TOP7, 20, 2), + MUX_F(0, "mout_mau_epll_clk", mout_mau_epll_clk_p, SRC_TOP7, 20, 2, + CLK_SET_RATE_PARENT, 0), MUX(0, "mout_fimd1", mout_group3_p, SRC_DISP10, 4, 1), }; -- cgit v1.2.3 From 948e068454568789792f9f10c3242c2bfb8ddbdc Mon Sep 17 00:00:00 2001 From: Sylwester Nawrocki Date: Mon, 12 Mar 2018 11:23:27 +0100 Subject: clk: samsung: exynos5420: Add more entries to EPLL rate table Adding these EPLL output frequency entries allows to support all required audio sample rates on the CODEC and the HDMI interface on Peach-Pit Chromebook. Signed-off-by: Sylwester Nawrocki Acked-by: Chanwoo Choi Signed-off-by: Sylwester Nawrocki --- drivers/clk/samsung/clk-exynos5420.c | 3 +++ 1 file changed, 3 insertions(+) diff --git a/drivers/clk/samsung/clk-exynos5420.c b/drivers/clk/samsung/clk-exynos5420.c index 1bb6e103509f..95e1bf69449b 100644 --- a/drivers/clk/samsung/clk-exynos5420.c +++ b/drivers/clk/samsung/clk-exynos5420.c @@ -1360,8 +1360,11 @@ static const struct samsung_pll_rate_table exynos5420_epll_24mhz_tbl[] = { PLL_36XX_RATE(24 * MHZ, 180633609U, 301, 5, 3, 3671), PLL_36XX_RATE(24 * MHZ, 131072006U, 131, 3, 3, 4719), PLL_36XX_RATE(24 * MHZ, 100000000U, 200, 3, 4, 0), + PLL_36XX_RATE(24 * MHZ, 73728000U, 98, 2, 4, 19923), + PLL_36XX_RATE(24 * MHZ, 67737602U, 90, 2, 4, 20762), PLL_36XX_RATE(24 * MHZ, 65536003U, 131, 3, 4, 4719), PLL_36XX_RATE(24 * MHZ, 49152000U, 197, 3, 5, -25690), + PLL_36XX_RATE(24 * MHZ, 45158401U, 90, 3, 4, 20762), PLL_36XX_RATE(24 * MHZ, 32768001U, 131, 3, 5, 4719), }; -- cgit v1.2.3 From 2dcabf053c6ecde46f7aa3612c5a57fb8bd185c4 Mon Sep 17 00:00:00 2001 From: Dmitry Osipenko Date: Wed, 10 Jan 2018 16:59:42 +0300 Subject: clk: tegra: Mark HCLK, SCLK and EMC as critical Machine dies if HCLK, SCLK or EMC is disabled. Hence mark these clocks as critical. Signed-off-by: Dmitry Osipenko Acked-by: Peter De Schrijver Cc: # v4.16 Signed-off-by: Thierry Reding --- drivers/clk/tegra/clk-emc.c | 2 +- drivers/clk/tegra/clk-tegra-periph.c | 2 +- drivers/clk/tegra/clk-tegra-super-gen4.c | 8 +++++--- drivers/clk/tegra/clk-tegra114.c | 3 +-- drivers/clk/tegra/clk-tegra124.c | 7 +++---- drivers/clk/tegra/clk-tegra20.c | 23 ++++++++++------------- drivers/clk/tegra/clk-tegra210.c | 3 +-- drivers/clk/tegra/clk-tegra30.c | 14 ++++---------- 8 files changed, 26 insertions(+), 36 deletions(-) diff --git a/drivers/clk/tegra/clk-emc.c b/drivers/clk/tegra/clk-emc.c index 11a5066e5c27..5234acd30e89 100644 --- a/drivers/clk/tegra/clk-emc.c +++ b/drivers/clk/tegra/clk-emc.c @@ -515,7 +515,7 @@ struct clk *tegra_clk_register_emc(void __iomem *base, struct device_node *np, init.name = "emc"; init.ops = &tegra_clk_emc_ops; - init.flags = 0; + init.flags = CLK_IS_CRITICAL; init.parent_names = emc_parent_clk_names; init.num_parents = ARRAY_SIZE(emc_parent_clk_names); diff --git a/drivers/clk/tegra/clk-tegra-periph.c b/drivers/clk/tegra/clk-tegra-periph.c index c02711927d79..2acba2986bc6 100644 --- a/drivers/clk/tegra/clk-tegra-periph.c +++ b/drivers/clk/tegra/clk-tegra-periph.c @@ -830,7 +830,7 @@ static struct tegra_periph_init_data gate_clks[] = { GATE("xusb_host", "xusb_host_src", 89, 0, tegra_clk_xusb_host, 0), GATE("xusb_ss", "xusb_ss_src", 156, 0, tegra_clk_xusb_ss, 0), GATE("xusb_dev", "xusb_dev_src", 95, 0, tegra_clk_xusb_dev, 0), - GATE("emc", "emc_mux", 57, 0, tegra_clk_emc, CLK_IGNORE_UNUSED), + GATE("emc", "emc_mux", 57, 0, tegra_clk_emc, CLK_IS_CRITICAL), GATE("sata_cold", "clk_m", 129, TEGRA_PERIPH_ON_APB, tegra_clk_sata_cold, 0), GATE("ispa", "isp", 23, 0, tegra_clk_ispa, 0), GATE("ispb", "isp", 3, 0, tegra_clk_ispb, 0), diff --git a/drivers/clk/tegra/clk-tegra-super-gen4.c b/drivers/clk/tegra/clk-tegra-super-gen4.c index 10047107c1dc..89d6b47a27a8 100644 --- a/drivers/clk/tegra/clk-tegra-super-gen4.c +++ b/drivers/clk/tegra/clk-tegra-super-gen4.c @@ -125,7 +125,8 @@ static void __init tegra_sclk_init(void __iomem *clk_base, /* SCLK */ dt_clk = tegra_lookup_dt_id(tegra_clk_sclk, tegra_clks); if (dt_clk) { - clk = clk_register_divider(NULL, "sclk", "sclk_mux", 0, + clk = clk_register_divider(NULL, "sclk", "sclk_mux", + CLK_IS_CRITICAL, clk_base + SCLK_DIVIDER, 0, 8, 0, &sysrate_lock); *dt_clk = clk; @@ -137,7 +138,8 @@ static void __init tegra_sclk_init(void __iomem *clk_base, clk = tegra_clk_register_super_mux("sclk", gen_info->sclk_parents, gen_info->num_sclk_parents, - CLK_SET_RATE_PARENT, + CLK_SET_RATE_PARENT | + CLK_IS_CRITICAL, clk_base + SCLK_BURST_POLICY, 0, 4, 0, 0, NULL); *dt_clk = clk; @@ -151,7 +153,7 @@ static void __init tegra_sclk_init(void __iomem *clk_base, clk_base + SYSTEM_CLK_RATE, 4, 2, 0, &sysrate_lock); clk = clk_register_gate(NULL, "hclk", "hclk_div", - CLK_SET_RATE_PARENT | CLK_IGNORE_UNUSED, + CLK_SET_RATE_PARENT | CLK_IS_CRITICAL, clk_base + SYSTEM_CLK_RATE, 7, CLK_GATE_SET_TO_DISABLE, &sysrate_lock); *dt_clk = clk; diff --git a/drivers/clk/tegra/clk-tegra114.c b/drivers/clk/tegra/clk-tegra114.c index 63087d17c3e2..c3945c683f60 100644 --- a/drivers/clk/tegra/clk-tegra114.c +++ b/drivers/clk/tegra/clk-tegra114.c @@ -955,8 +955,7 @@ static void __init tegra114_pll_init(void __iomem *clk_base, /* PLLM */ clk = tegra_clk_register_pllm("pll_m", "pll_ref", clk_base, pmc, - CLK_IGNORE_UNUSED | CLK_SET_RATE_GATE, - &pll_m_params, NULL); + CLK_SET_RATE_GATE, &pll_m_params, NULL); clks[TEGRA114_CLK_PLL_M] = clk; /* PLLM_OUT1 */ diff --git a/drivers/clk/tegra/clk-tegra124.c b/drivers/clk/tegra/clk-tegra124.c index e81ea5b11577..230f9a2c1abf 100644 --- a/drivers/clk/tegra/clk-tegra124.c +++ b/drivers/clk/tegra/clk-tegra124.c @@ -1089,8 +1089,7 @@ static void __init tegra124_pll_init(void __iomem *clk_base, /* PLLM */ clk = tegra_clk_register_pllm("pll_m", "pll_ref", clk_base, pmc, - CLK_IGNORE_UNUSED | CLK_SET_RATE_GATE, - &pll_m_params, NULL); + CLK_SET_RATE_GATE, &pll_m_params, NULL); clk_register_clkdev(clk, "pll_m", NULL); clks[TEGRA124_CLK_PLL_M] = clk; @@ -1099,7 +1098,7 @@ static void __init tegra124_pll_init(void __iomem *clk_base, clk_base + PLLM_OUT, 0, TEGRA_DIVIDER_ROUND_UP, 8, 8, 1, NULL); clk = tegra_clk_register_pll_out("pll_m_out1", "pll_m_out1_div", - clk_base + PLLM_OUT, 1, 0, CLK_IGNORE_UNUSED | + clk_base + PLLM_OUT, 1, 0, CLK_SET_RATE_PARENT, 0, NULL); clk_register_clkdev(clk, "pll_m_out1", NULL); clks[TEGRA124_CLK_PLL_M_OUT1] = clk; @@ -1272,7 +1271,7 @@ static struct tegra_clk_init_table common_init_table[] __initdata = { { TEGRA124_CLK_HOST1X, TEGRA124_CLK_PLL_P, 136000000, 1 }, { TEGRA124_CLK_DSIALP, TEGRA124_CLK_PLL_P, 68000000, 0 }, { TEGRA124_CLK_DSIBLP, TEGRA124_CLK_PLL_P, 68000000, 0 }, - { TEGRA124_CLK_SCLK, TEGRA124_CLK_PLL_P_OUT2, 102000000, 1 }, + { TEGRA124_CLK_SCLK, TEGRA124_CLK_PLL_P_OUT2, 102000000, 0 }, { TEGRA124_CLK_DFLL_SOC, TEGRA124_CLK_PLL_P, 51000000, 1 }, { TEGRA124_CLK_DFLL_REF, TEGRA124_CLK_PLL_P, 51000000, 1 }, { TEGRA124_CLK_PLL_C, TEGRA124_CLK_CLK_MAX, 768000000, 0 }, diff --git a/drivers/clk/tegra/clk-tegra20.c b/drivers/clk/tegra/clk-tegra20.c index cbd5a2e5c569..e3392ca2c2fc 100644 --- a/drivers/clk/tegra/clk-tegra20.c +++ b/drivers/clk/tegra/clk-tegra20.c @@ -576,6 +576,7 @@ static struct tegra_clk tegra20_clks[tegra_clk_max] __initdata = { [tegra_clk_afi] = { .dt_id = TEGRA20_CLK_AFI, .present = true }, [tegra_clk_fuse] = { .dt_id = TEGRA20_CLK_FUSE, .present = true }, [tegra_clk_kfuse] = { .dt_id = TEGRA20_CLK_KFUSE, .present = true }, + [tegra_clk_emc] = { .dt_id = TEGRA20_CLK_EMC, .present = true }, }; static unsigned long tegra20_clk_measure_input_freq(void) @@ -651,8 +652,7 @@ static void tegra20_pll_init(void) /* PLLM */ clk = tegra_clk_register_pll("pll_m", "pll_ref", clk_base, NULL, - CLK_IGNORE_UNUSED | CLK_SET_RATE_GATE, - &pll_m_params, NULL); + CLK_SET_RATE_GATE, &pll_m_params, NULL); clks[TEGRA20_CLK_PLL_M] = clk; /* PLLM_OUT1 */ @@ -660,7 +660,7 @@ static void tegra20_pll_init(void) clk_base + PLLM_OUT, 0, TEGRA_DIVIDER_ROUND_UP, 8, 8, 1, NULL); clk = tegra_clk_register_pll_out("pll_m_out1", "pll_m_out1_div", - clk_base + PLLM_OUT, 1, 0, CLK_IGNORE_UNUSED | + clk_base + PLLM_OUT, 1, 0, CLK_SET_RATE_PARENT, 0, NULL); clks[TEGRA20_CLK_PLL_M_OUT1] = clk; @@ -723,7 +723,8 @@ static void tegra20_super_clk_init(void) /* SCLK */ clk = tegra_clk_register_super_mux("sclk", sclk_parents, - ARRAY_SIZE(sclk_parents), CLK_SET_RATE_PARENT, + ARRAY_SIZE(sclk_parents), + CLK_SET_RATE_PARENT | CLK_IS_CRITICAL, clk_base + SCLK_BURST_POLICY, 0, 4, 0, 0, NULL); clks[TEGRA20_CLK_SCLK] = clk; @@ -814,9 +815,6 @@ static void __init tegra20_periph_clk_init(void) CLK_SET_RATE_NO_REPARENT, clk_base + CLK_SOURCE_EMC, 30, 2, 0, &emc_lock); - clk = tegra_clk_register_periph_gate("emc", "emc_mux", 0, clk_base, 0, - 57, periph_clk_enb_refcnt); - clks[TEGRA20_CLK_EMC] = clk; clk = tegra_clk_register_mc("mc", "emc_mux", clk_base + CLK_SOURCE_EMC, &emc_lock); @@ -1019,13 +1017,12 @@ static struct tegra_clk_init_table init_table[] __initdata = { { TEGRA20_CLK_PLL_P_OUT2, TEGRA20_CLK_CLK_MAX, 48000000, 1 }, { TEGRA20_CLK_PLL_P_OUT3, TEGRA20_CLK_CLK_MAX, 72000000, 1 }, { TEGRA20_CLK_PLL_P_OUT4, TEGRA20_CLK_CLK_MAX, 24000000, 1 }, - { TEGRA20_CLK_PLL_C, TEGRA20_CLK_CLK_MAX, 600000000, 1 }, - { TEGRA20_CLK_PLL_C_OUT1, TEGRA20_CLK_CLK_MAX, 216000000, 1 }, - { TEGRA20_CLK_SCLK, TEGRA20_CLK_PLL_C_OUT1, 0, 1 }, - { TEGRA20_CLK_HCLK, TEGRA20_CLK_CLK_MAX, 0, 1 }, - { TEGRA20_CLK_PCLK, TEGRA20_CLK_CLK_MAX, 60000000, 1 }, + { TEGRA20_CLK_PLL_C, TEGRA20_CLK_CLK_MAX, 600000000, 0 }, + { TEGRA20_CLK_PLL_C_OUT1, TEGRA20_CLK_CLK_MAX, 216000000, 0 }, + { TEGRA20_CLK_SCLK, TEGRA20_CLK_PLL_C_OUT1, 0, 0 }, + { TEGRA20_CLK_HCLK, TEGRA20_CLK_CLK_MAX, 0, 0 }, + { TEGRA20_CLK_PCLK, TEGRA20_CLK_CLK_MAX, 60000000, 0 }, { TEGRA20_CLK_CSITE, TEGRA20_CLK_CLK_MAX, 0, 1 }, - { TEGRA20_CLK_EMC, TEGRA20_CLK_CLK_MAX, 0, 1 }, { TEGRA20_CLK_CCLK, TEGRA20_CLK_CLK_MAX, 0, 1 }, { TEGRA20_CLK_UARTA, TEGRA20_CLK_PLL_P, 0, 0 }, { TEGRA20_CLK_UARTB, TEGRA20_CLK_PLL_P, 0, 0 }, diff --git a/drivers/clk/tegra/clk-tegra210.c b/drivers/clk/tegra/clk-tegra210.c index 946d708add1e..9fb5d51ccce4 100644 --- a/drivers/clk/tegra/clk-tegra210.c +++ b/drivers/clk/tegra/clk-tegra210.c @@ -3328,7 +3328,7 @@ static struct tegra_clk_init_table init_table[] __initdata = { { TEGRA210_CLK_I2S4, TEGRA210_CLK_PLL_A_OUT0, 11289600, 0 }, { TEGRA210_CLK_HOST1X, TEGRA210_CLK_PLL_P, 136000000, 1 }, { TEGRA210_CLK_SCLK_MUX, TEGRA210_CLK_PLL_P, 0, 1 }, - { TEGRA210_CLK_SCLK, TEGRA210_CLK_CLK_MAX, 102000000, 1 }, + { TEGRA210_CLK_SCLK, TEGRA210_CLK_CLK_MAX, 102000000, 0 }, { TEGRA210_CLK_DFLL_SOC, TEGRA210_CLK_PLL_P, 51000000, 1 }, { TEGRA210_CLK_DFLL_REF, TEGRA210_CLK_PLL_P, 51000000, 1 }, { TEGRA210_CLK_SBC4, TEGRA210_CLK_PLL_P, 12000000, 1 }, @@ -3343,7 +3343,6 @@ static struct tegra_clk_init_table init_table[] __initdata = { { TEGRA210_CLK_XUSB_DEV_SRC, TEGRA210_CLK_PLL_P_OUT_XUSB, 102000000, 0 }, { TEGRA210_CLK_SATA, TEGRA210_CLK_PLL_P, 104000000, 0 }, { TEGRA210_CLK_SATA_OOB, TEGRA210_CLK_PLL_P, 204000000, 0 }, - { TEGRA210_CLK_EMC, TEGRA210_CLK_CLK_MAX, 0, 1 }, { TEGRA210_CLK_MSELECT, TEGRA210_CLK_CLK_MAX, 0, 1 }, { TEGRA210_CLK_CSITE, TEGRA210_CLK_CLK_MAX, 0, 1 }, /* TODO find a way to enable this on-demand */ diff --git a/drivers/clk/tegra/clk-tegra30.c b/drivers/clk/tegra/clk-tegra30.c index bee84c554932..8428895ad475 100644 --- a/drivers/clk/tegra/clk-tegra30.c +++ b/drivers/clk/tegra/clk-tegra30.c @@ -819,6 +819,7 @@ static struct tegra_clk tegra30_clks[tegra_clk_max] __initdata = { [tegra_clk_pll_a] = { .dt_id = TEGRA30_CLK_PLL_A, .present = true }, [tegra_clk_pll_a_out0] = { .dt_id = TEGRA30_CLK_PLL_A_OUT0, .present = true }, [tegra_clk_cec] = { .dt_id = TEGRA30_CLK_CEC, .present = true }, + [tegra_clk_emc] = { .dt_id = TEGRA30_CLK_EMC, .present = true }, }; static const char *pll_e_parents[] = { "pll_ref", "pll_p" }; @@ -843,8 +844,7 @@ static void __init tegra30_pll_init(void) /* PLLM */ clk = tegra_clk_register_pll("pll_m", "pll_ref", clk_base, pmc_base, - CLK_IGNORE_UNUSED | CLK_SET_RATE_GATE, - &pll_m_params, NULL); + CLK_SET_RATE_GATE, &pll_m_params, NULL); clks[TEGRA30_CLK_PLL_M] = clk; /* PLLM_OUT1 */ @@ -852,7 +852,7 @@ static void __init tegra30_pll_init(void) clk_base + PLLM_OUT, 0, TEGRA_DIVIDER_ROUND_UP, 8, 8, 1, NULL); clk = tegra_clk_register_pll_out("pll_m_out1", "pll_m_out1_div", - clk_base + PLLM_OUT, 1, 0, CLK_IGNORE_UNUSED | + clk_base + PLLM_OUT, 1, 0, CLK_SET_RATE_PARENT, 0, NULL); clks[TEGRA30_CLK_PLL_M_OUT1] = clk; @@ -990,7 +990,7 @@ static void __init tegra30_super_clk_init(void) /* SCLK */ clk = tegra_clk_register_super_mux("sclk", sclk_parents, ARRAY_SIZE(sclk_parents), - CLK_SET_RATE_PARENT, + CLK_SET_RATE_PARENT | CLK_IS_CRITICAL, clk_base + SCLK_BURST_POLICY, 0, 4, 0, 0, NULL); clks[TEGRA30_CLK_SCLK] = clk; @@ -1060,9 +1060,6 @@ static void __init tegra30_periph_clk_init(void) CLK_SET_RATE_NO_REPARENT, clk_base + CLK_SOURCE_EMC, 30, 2, 0, &emc_lock); - clk = tegra_clk_register_periph_gate("emc", "emc_mux", 0, clk_base, 0, - 57, periph_clk_enb_refcnt); - clks[TEGRA30_CLK_EMC] = clk; clk = tegra_clk_register_mc("mc", "emc_mux", clk_base + CLK_SOURCE_EMC, &emc_lock); @@ -1252,10 +1249,7 @@ static struct tegra_clk_init_table init_table[] __initdata = { { TEGRA30_CLK_SDMMC1, TEGRA30_CLK_PLL_P, 48000000, 0 }, { TEGRA30_CLK_SDMMC2, TEGRA30_CLK_PLL_P, 48000000, 0 }, { TEGRA30_CLK_SDMMC3, TEGRA30_CLK_PLL_P, 48000000, 0 }, - { TEGRA30_CLK_PLL_M, TEGRA30_CLK_CLK_MAX, 0, 1 }, - { TEGRA30_CLK_PCLK, TEGRA30_CLK_CLK_MAX, 0, 1 }, { TEGRA30_CLK_CSITE, TEGRA30_CLK_CLK_MAX, 0, 1 }, - { TEGRA30_CLK_EMC, TEGRA30_CLK_CLK_MAX, 0, 1 }, { TEGRA30_CLK_MSELECT, TEGRA30_CLK_CLK_MAX, 0, 1 }, { TEGRA30_CLK_SBC1, TEGRA30_CLK_PLL_P, 100000000, 0 }, { TEGRA30_CLK_SBC2, TEGRA30_CLK_PLL_P, 100000000, 0 }, -- cgit v1.2.3 From ea141d5819db989eb688cee2713b664faba4f1ca Mon Sep 17 00:00:00 2001 From: Dmitry Osipenko Date: Wed, 10 Jan 2018 16:59:43 +0300 Subject: clk: tegra20: Correct PLL_C_OUT1 setup PLL_C_OUT_1 can't produce 216 MHz defined in the init_table. Let's set it to 240 MHz and explicitly specify HCLK rate for consistency. Signed-off-by: Dmitry Osipenko Acked-by: Peter De Schrijver Signed-off-by: Thierry Reding --- drivers/clk/tegra/clk-tegra20.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/drivers/clk/tegra/clk-tegra20.c b/drivers/clk/tegra/clk-tegra20.c index e3392ca2c2fc..dec95919fbff 100644 --- a/drivers/clk/tegra/clk-tegra20.c +++ b/drivers/clk/tegra/clk-tegra20.c @@ -1018,9 +1018,9 @@ static struct tegra_clk_init_table init_table[] __initdata = { { TEGRA20_CLK_PLL_P_OUT3, TEGRA20_CLK_CLK_MAX, 72000000, 1 }, { TEGRA20_CLK_PLL_P_OUT4, TEGRA20_CLK_CLK_MAX, 24000000, 1 }, { TEGRA20_CLK_PLL_C, TEGRA20_CLK_CLK_MAX, 600000000, 0 }, - { TEGRA20_CLK_PLL_C_OUT1, TEGRA20_CLK_CLK_MAX, 216000000, 0 }, - { TEGRA20_CLK_SCLK, TEGRA20_CLK_PLL_C_OUT1, 0, 0 }, - { TEGRA20_CLK_HCLK, TEGRA20_CLK_CLK_MAX, 0, 0 }, + { TEGRA20_CLK_PLL_C_OUT1, TEGRA20_CLK_CLK_MAX, 240000000, 0 }, + { TEGRA20_CLK_SCLK, TEGRA20_CLK_PLL_C_OUT1, 240000000, 0 }, + { TEGRA20_CLK_HCLK, TEGRA20_CLK_CLK_MAX, 240000000, 0 }, { TEGRA20_CLK_PCLK, TEGRA20_CLK_CLK_MAX, 60000000, 0 }, { TEGRA20_CLK_CSITE, TEGRA20_CLK_CLK_MAX, 0, 1 }, { TEGRA20_CLK_CCLK, TEGRA20_CLK_CLK_MAX, 0, 1 }, -- cgit v1.2.3 From c485ad63abb4b30a3654e80fef9708a181447965 Mon Sep 17 00:00:00 2001 From: Dmitry Osipenko Date: Wed, 10 Jan 2018 16:59:44 +0300 Subject: clk: tegra: Specify VDE clock rate Currently VDE clock rate is determined by clock config left from bootloader, let's not rely on it and explicitly specify the clock rate in the CCF driver. Signed-off-by: Dmitry Osipenko Acked-by: Peter De Schrijver Signed-off-by: Thierry Reding --- drivers/clk/tegra/clk-tegra114.c | 1 + drivers/clk/tegra/clk-tegra124.c | 2 +- drivers/clk/tegra/clk-tegra20.c | 1 + drivers/clk/tegra/clk-tegra30.c | 1 + 4 files changed, 4 insertions(+), 1 deletion(-) diff --git a/drivers/clk/tegra/clk-tegra114.c b/drivers/clk/tegra/clk-tegra114.c index c3945c683f60..5d5a22d529f5 100644 --- a/drivers/clk/tegra/clk-tegra114.c +++ b/drivers/clk/tegra/clk-tegra114.c @@ -1189,6 +1189,7 @@ static struct tegra_clk_init_table init_table[] __initdata = { { TEGRA114_CLK_XUSB_HS_SRC, TEGRA114_CLK_XUSB_SS_DIV2, 61200000, 0 }, { TEGRA114_CLK_XUSB_FALCON_SRC, TEGRA114_CLK_PLL_P, 204000000, 0 }, { TEGRA114_CLK_XUSB_HOST_SRC, TEGRA114_CLK_PLL_P, 102000000, 0 }, + { TEGRA114_CLK_VDE, TEGRA114_CLK_CLK_MAX, 600000000, 0 }, /* must be the last entry */ { TEGRA114_CLK_CLK_MAX, TEGRA114_CLK_CLK_MAX, 0, 0 }, }; diff --git a/drivers/clk/tegra/clk-tegra124.c b/drivers/clk/tegra/clk-tegra124.c index 230f9a2c1abf..50088e976611 100644 --- a/drivers/clk/tegra/clk-tegra124.c +++ b/drivers/clk/tegra/clk-tegra124.c @@ -1267,7 +1267,7 @@ static struct tegra_clk_init_table common_init_table[] __initdata = { { TEGRA124_CLK_I2S2, TEGRA124_CLK_PLL_A_OUT0, 11289600, 0 }, { TEGRA124_CLK_I2S3, TEGRA124_CLK_PLL_A_OUT0, 11289600, 0 }, { TEGRA124_CLK_I2S4, TEGRA124_CLK_PLL_A_OUT0, 11289600, 0 }, - { TEGRA124_CLK_VDE, TEGRA124_CLK_PLL_P, 0, 0 }, + { TEGRA124_CLK_VDE, TEGRA124_CLK_CLK_MAX, 600000000, 0 }, { TEGRA124_CLK_HOST1X, TEGRA124_CLK_PLL_P, 136000000, 1 }, { TEGRA124_CLK_DSIALP, TEGRA124_CLK_PLL_P, 68000000, 0 }, { TEGRA124_CLK_DSIBLP, TEGRA124_CLK_PLL_P, 68000000, 0 }, diff --git a/drivers/clk/tegra/clk-tegra20.c b/drivers/clk/tegra/clk-tegra20.c index dec95919fbff..0ee56dd04cec 100644 --- a/drivers/clk/tegra/clk-tegra20.c +++ b/drivers/clk/tegra/clk-tegra20.c @@ -1048,6 +1048,7 @@ static struct tegra_clk_init_table init_table[] __initdata = { { TEGRA20_CLK_DISP2, TEGRA20_CLK_PLL_P, 600000000, 0 }, { TEGRA20_CLK_GR2D, TEGRA20_CLK_PLL_C, 300000000, 0 }, { TEGRA20_CLK_GR3D, TEGRA20_CLK_PLL_C, 300000000, 0 }, + { TEGRA20_CLK_VDE, TEGRA20_CLK_CLK_MAX, 300000000, 0 }, /* must be the last entry */ { TEGRA20_CLK_CLK_MAX, TEGRA20_CLK_CLK_MAX, 0, 0 }, }; diff --git a/drivers/clk/tegra/clk-tegra30.c b/drivers/clk/tegra/clk-tegra30.c index 8428895ad475..b316dfb6f6c7 100644 --- a/drivers/clk/tegra/clk-tegra30.c +++ b/drivers/clk/tegra/clk-tegra30.c @@ -1266,6 +1266,7 @@ static struct tegra_clk_init_table init_table[] __initdata = { { TEGRA30_CLK_GR3D, TEGRA30_CLK_PLL_C, 300000000, 0 }, { TEGRA30_CLK_GR3D2, TEGRA30_CLK_PLL_C, 300000000, 0 }, { TEGRA30_CLK_PLL_U, TEGRA30_CLK_CLK_MAX, 480000000, 0 }, + { TEGRA30_CLK_VDE, TEGRA30_CLK_CLK_MAX, 600000000, 0 }, /* must be the last entry */ { TEGRA30_CLK_CLK_MAX, TEGRA30_CLK_CLK_MAX, 0, 0 }, }; -- cgit v1.2.3 From c35b518f9ba06c9de79fb3ff62eed7462d804995 Mon Sep 17 00:00:00 2001 From: Marcel Ziswiler Date: Fri, 23 Feb 2018 00:04:51 +0100 Subject: clk: tegra: Fix pll_u rate configuration Turns out latest upstream U-Boot does not configure/enable pll_u which leaves it at some default rate of 500 kHz: root@apalis-t30:~# cat /sys/kernel/debug/clk/clk_summary | grep pll_u pll_u 3 3 0 500000 0 Of course this won't quite work leading to the following messages: [ 6.559593] usb 2-1: new full-speed USB device number 2 using tegra- ehci [ 11.759173] usb 2-1: device descriptor read/64, error -110 [ 27.119453] usb 2-1: device descriptor read/64, error -110 [ 27.389217] usb 2-1: new full-speed USB device number 3 using tegra- ehci [ 32.559454] usb 2-1: device descriptor read/64, error -110 [ 47.929777] usb 2-1: device descriptor read/64, error -110 [ 48.049658] usb usb2-port1: attempt power cycle [ 48.759475] usb 2-1: new full-speed USB device number 4 using tegra- ehci [ 59.349457] usb 2-1: device not accepting address 4, error -110 [ 59.509449] usb 2-1: new full-speed USB device number 5 using tegra- ehci [ 70.069457] usb 2-1: device not accepting address 5, error -110 [ 70.079721] usb usb2-port1: unable to enumerate USB device Fix this by actually allowing the rate also being set from within the Linux kernel. Signed-off-by: Marcel Ziswiler Tested-by: Jon Hunter Signed-off-by: Thierry Reding --- drivers/clk/tegra/clk-pll.c | 2 ++ 1 file changed, 2 insertions(+) diff --git a/drivers/clk/tegra/clk-pll.c b/drivers/clk/tegra/clk-pll.c index 7c369e21c91c..830d1c87fa7c 100644 --- a/drivers/clk/tegra/clk-pll.c +++ b/drivers/clk/tegra/clk-pll.c @@ -1151,6 +1151,8 @@ static const struct clk_ops tegra_clk_pllu_ops = { .enable = clk_pllu_enable, .disable = clk_pll_disable, .recalc_rate = clk_pll_recalc_rate, + .round_rate = clk_pll_round_rate, + .set_rate = clk_pll_set_rate, }; static int _pll_fixed_mdiv(struct tegra_clk_pll_params *pll_params, -- cgit v1.2.3 From 99652a469df19086d594e8e89757d4081a812789 Mon Sep 17 00:00:00 2001 From: Jerome Brunet Date: Wed, 14 Feb 2018 14:43:36 +0100 Subject: clk: migrate the count of orphaned clocks at init The orphan clocks reparents should migrate any existing count from the orphan clock to its new acestor clocks, otherwise we may have inconsistent counts in the tree and end-up with gated critical clocks Assuming we have two clocks, A and B. * Clock A has CLK_IS_CRITICAL flag set. * Clock B is an ancestor of A which can gate. Clock B gate is left enabled by the bootloader. Step 1: Clock A is registered. Since it is a critical clock, it is enabled. The clock being still an orphan, no parent are enabled. Step 2: Clock B is registered and reparented to clock A (potentially through several other clocks). We are now in situation where the enable count of clock A is 1 while the enable count of its ancestors is 0, which is not good. Step 3: in lateinit, clk_disable_unused() is called, the enable_count of clock B being 0, clock B is gated and and critical clock A actually gets disabled. This situation was found while adding fdiv_clk gates to the meson8b platform. These clocks parent clk81 critical clock, which is the mother of all peripheral clocks in this system. Because of the issue described here, the system is crashing when clk_disable_unused() is called. The situation is solved by reverting commit f8f8f1d04494 ("clk: Don't touch hardware when reparenting during registration"). To avoid breaking again the situation described in this commit description, enabling critical clock should be done before walking the orphan list. This way, a parent critical clock may not be accidentally disabled due to the CLK_OPS_PARENT_ENABLE mechanism. Fixes: f8f8f1d04494 ("clk: Don't touch hardware when reparenting during registration") Cc: Stephen Boyd Cc: Shawn Guo Cc: Dong Aisheng Signed-off-by: Jerome Brunet Tested-by: Marek Szyprowski Tested-by: Heiko Stuebner Signed-off-by: Michael Turquette --- drivers/clk/clk.c | 37 +++++++++++++++++++++---------------- 1 file changed, 21 insertions(+), 16 deletions(-) diff --git a/drivers/clk/clk.c b/drivers/clk/clk.c index 0f686a9dac3e..6d54e933c901 100644 --- a/drivers/clk/clk.c +++ b/drivers/clk/clk.c @@ -2967,23 +2967,38 @@ static int __clk_core_init(struct clk_core *core) rate = 0; core->rate = core->req_rate = rate; + /* + * Enable CLK_IS_CRITICAL clocks so newly added critical clocks + * don't get accidentally disabled when walking the orphan tree and + * reparenting clocks + */ + if (core->flags & CLK_IS_CRITICAL) { + unsigned long flags; + + clk_core_prepare(core); + + flags = clk_enable_lock(); + clk_core_enable(core); + clk_enable_unlock(flags); + } + /* * walk the list of orphan clocks and reparent any that newly finds a * parent. */ hlist_for_each_entry_safe(orphan, tmp2, &clk_orphan_list, child_node) { struct clk_core *parent = __clk_init_parent(orphan); - unsigned long flags; /* - * we could call __clk_set_parent, but that would result in a - * redundant call to the .set_rate op, if it exists + * We need to use __clk_set_parent_before() and _after() to + * to properly migrate any prepare/enable count of the orphan + * clock. This is important for CLK_IS_CRITICAL clocks, which + * are enabled during init but might not have a parent yet. */ if (parent) { /* update the clk tree topology */ - flags = clk_enable_lock(); - clk_reparent(orphan, parent); - clk_enable_unlock(flags); + __clk_set_parent_before(orphan, parent); + __clk_set_parent_after(orphan, parent, NULL); __clk_recalc_accuracies(orphan); __clk_recalc_rates(orphan, 0); } @@ -3000,16 +3015,6 @@ static int __clk_core_init(struct clk_core *core) if (core->ops->init) core->ops->init(core->hw); - if (core->flags & CLK_IS_CRITICAL) { - unsigned long flags; - - clk_core_prepare(core); - - flags = clk_enable_lock(); - clk_core_enable(core); - clk_enable_unlock(flags); - } - kref_init(&core->ref); out: clk_pm_runtime_put(core); -- cgit v1.2.3 From 04bf9ab3359ff89059509ee5c35446c45b9cdaaa Mon Sep 17 00:00:00 2001 From: Jerome Brunet Date: Wed, 14 Feb 2018 14:43:35 +0100 Subject: clk: fix determine rate error with pass-through clock If we try to determine the rate of a pass-through clock (a clock which does not implement .round_rate() nor .determine_rate()), clk_core_round_rate_nolock() will directly forward the call to the parent clock. In the particular case where the pass-through actually does not have a parent, clk_core_round_rate_nolock() will directly return 0 with the requested rate still set to the initial request structure. This is interpreted as if the rate could be exactly achieved while it actually cannot be adjusted. This become a real problem when this particular pass-through clock is the parent of a mux with the flag CLK_SET_RATE_PARENT set. The pass-through clock will always report an exact match, get picked and finally error when the rate is actually getting set. This is fixed by setting the rate inside the req to 0 when core is NULL in clk_core_round_rate_nolock() (same as in __clk_determine_rate() when hw is NULL) Fixes: 0f6cc2b8e94d ("clk: rework calls to round and determine rate callbacks") Signed-off-by: Jerome Brunet Signed-off-by: Michael Turquette Signed-off-by: Stephen Boyd --- drivers/clk/clk.c | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/drivers/clk/clk.c b/drivers/clk/clk.c index 6d54e933c901..cca05ea2c058 100644 --- a/drivers/clk/clk.c +++ b/drivers/clk/clk.c @@ -1125,8 +1125,10 @@ static int clk_core_round_rate_nolock(struct clk_core *core, { lockdep_assert_held(&prepare_lock); - if (!core) + if (!core) { + req->rate = 0; return 0; + } clk_core_init_rate_req(core, req); -- cgit v1.2.3 From e6d3cc7b1fac3d7f1313faf8ac9b23830113e3ec Mon Sep 17 00:00:00 2001 From: Jerome Brunet Date: Wed, 14 Feb 2018 14:43:33 +0100 Subject: clk: divider: export clk_div_mask() helper Export clk_div_mask() in clk-provider header so every clock providers derived from the generic clock divider may share the definition instead of redefining it. Signed-off-by: Jerome Brunet Signed-off-by: Michael Turquette Signed-off-by: Stephen Boyd --- drivers/clk/clk-divider.c | 24 +++++++++++------------- include/linux/clk-provider.h | 1 + 2 files changed, 12 insertions(+), 13 deletions(-) diff --git a/drivers/clk/clk-divider.c b/drivers/clk/clk-divider.c index b49942b9fe50..3c98d2650fa3 100644 --- a/drivers/clk/clk-divider.c +++ b/drivers/clk/clk-divider.c @@ -28,12 +28,10 @@ * parent - fixed parent. No clk_set_parent support */ -#define div_mask(width) ((1 << (width)) - 1) - static unsigned int _get_table_maxdiv(const struct clk_div_table *table, u8 width) { - unsigned int maxdiv = 0, mask = div_mask(width); + unsigned int maxdiv = 0, mask = clk_div_mask(width); const struct clk_div_table *clkt; for (clkt = table; clkt->div; clkt++) @@ -57,12 +55,12 @@ static unsigned int _get_maxdiv(const struct clk_div_table *table, u8 width, unsigned long flags) { if (flags & CLK_DIVIDER_ONE_BASED) - return div_mask(width); + return clk_div_mask(width); if (flags & CLK_DIVIDER_POWER_OF_TWO) - return 1 << div_mask(width); + return 1 << clk_div_mask(width); if (table) return _get_table_maxdiv(table, width); - return div_mask(width) + 1; + return clk_div_mask(width) + 1; } static unsigned int _get_table_div(const struct clk_div_table *table, @@ -84,7 +82,7 @@ static unsigned int _get_div(const struct clk_div_table *table, if (flags & CLK_DIVIDER_POWER_OF_TWO) return 1 << val; if (flags & CLK_DIVIDER_MAX_AT_ZERO) - return val ? val : div_mask(width) + 1; + return val ? val : clk_div_mask(width) + 1; if (table) return _get_table_div(table, val); return val + 1; @@ -109,7 +107,7 @@ static unsigned int _get_val(const struct clk_div_table *table, if (flags & CLK_DIVIDER_POWER_OF_TWO) return __ffs(div); if (flags & CLK_DIVIDER_MAX_AT_ZERO) - return (div == div_mask(width) + 1) ? 0 : div; + return (div == clk_div_mask(width) + 1) ? 0 : div; if (table) return _get_table_val(table, div); return div - 1; @@ -141,7 +139,7 @@ static unsigned long clk_divider_recalc_rate(struct clk_hw *hw, unsigned int val; val = clk_readl(divider->reg) >> divider->shift; - val &= div_mask(divider->width); + val &= clk_div_mask(divider->width); return divider_recalc_rate(hw, parent_rate, val, divider->table, divider->flags, divider->width); @@ -353,7 +351,7 @@ static long clk_divider_round_rate(struct clk_hw *hw, unsigned long rate, /* if read only, just return current value */ if (divider->flags & CLK_DIVIDER_READ_ONLY) { bestdiv = clk_readl(divider->reg) >> divider->shift; - bestdiv &= div_mask(divider->width); + bestdiv &= clk_div_mask(divider->width); bestdiv = _get_div(divider->table, bestdiv, divider->flags, divider->width); return DIV_ROUND_UP_ULL((u64)*prate, bestdiv); @@ -376,7 +374,7 @@ int divider_get_val(unsigned long rate, unsigned long parent_rate, value = _get_val(table, div, flags, width); - return min_t(unsigned int, value, div_mask(width)); + return min_t(unsigned int, value, clk_div_mask(width)); } EXPORT_SYMBOL_GPL(divider_get_val); @@ -399,10 +397,10 @@ static int clk_divider_set_rate(struct clk_hw *hw, unsigned long rate, __acquire(divider->lock); if (divider->flags & CLK_DIVIDER_HIWORD_MASK) { - val = div_mask(divider->width) << (divider->shift + 16); + val = clk_div_mask(divider->width) << (divider->shift + 16); } else { val = clk_readl(divider->reg); - val &= ~(div_mask(divider->width) << divider->shift); + val &= ~(clk_div_mask(divider->width) << divider->shift); } val |= (u32)value << divider->shift; clk_writel(val, divider->reg); diff --git a/include/linux/clk-provider.h b/include/linux/clk-provider.h index f711be6e8c44..d8ba26d03332 100644 --- a/include/linux/clk-provider.h +++ b/include/linux/clk-provider.h @@ -399,6 +399,7 @@ struct clk_divider { spinlock_t *lock; }; +#define clk_div_mask(width) ((1 << (width)) - 1) #define to_clk_divider(_hw) container_of(_hw, struct clk_divider, hw) #define CLK_DIVIDER_ONE_BASED BIT(0) -- cgit v1.2.3 From 77deb66d262f8512130ff75ec5ea8e31070b41ed Mon Sep 17 00:00:00 2001 From: Jerome Brunet Date: Wed, 14 Feb 2018 14:43:34 +0100 Subject: clk: mux: add helper function for index/value translation Add helper functions for the translation between parent index and register value in the generic multiplexer function. The purpose of this change is avoid duplicating the code in other clock providers, using the same generic logic. Signed-off-by: Jerome Brunet Signed-off-by: Michael Turquette Signed-off-by: Stephen Boyd --- drivers/clk/clk-mux.c | 75 +++++++++++++++++++++++++------------------- include/linux/clk-provider.h | 4 +++ 2 files changed, 47 insertions(+), 32 deletions(-) diff --git a/drivers/clk/clk-mux.c b/drivers/clk/clk-mux.c index 39cabe157163..ac4a042f8658 100644 --- a/drivers/clk/clk-mux.c +++ b/drivers/clk/clk-mux.c @@ -26,35 +26,24 @@ * parent - parent is adjustable through clk_set_parent */ -static u8 clk_mux_get_parent(struct clk_hw *hw) +int clk_mux_val_to_index(struct clk_hw *hw, u32 *table, unsigned int flags, + unsigned int val) { - struct clk_mux *mux = to_clk_mux(hw); int num_parents = clk_hw_get_num_parents(hw); - u32 val; - /* - * FIXME need a mux-specific flag to determine if val is bitwise or numeric - * e.g. sys_clkin_ck's clksel field is 3 bits wide, but ranges from 0x1 - * to 0x7 (index starts at one) - * OTOH, pmd_trace_clk_mux_ck uses a separate bit for each clock, so - * val = 0x4 really means "bit 2, index starts at bit 0" - */ - val = clk_readl(mux->reg) >> mux->shift; - val &= mux->mask; - - if (mux->table) { + if (table) { int i; for (i = 0; i < num_parents; i++) - if (mux->table[i] == val) + if (table[i] == val) return i; return -EINVAL; } - if (val && (mux->flags & CLK_MUX_INDEX_BIT)) + if (val && (flags & CLK_MUX_INDEX_BIT)) val = ffs(val) - 1; - if (val && (mux->flags & CLK_MUX_INDEX_ONE)) + if (val && (flags & CLK_MUX_INDEX_ONE)) val--; if (val >= num_parents) @@ -62,36 +51,58 @@ static u8 clk_mux_get_parent(struct clk_hw *hw) return val; } +EXPORT_SYMBOL_GPL(clk_mux_val_to_index); -static int clk_mux_set_parent(struct clk_hw *hw, u8 index) +unsigned int clk_mux_index_to_val(u32 *table, unsigned int flags, u8 index) { - struct clk_mux *mux = to_clk_mux(hw); - u32 val; - unsigned long flags = 0; + unsigned int val = index; - if (mux->table) { - index = mux->table[index]; + if (table) { + val = table[index]; } else { - if (mux->flags & CLK_MUX_INDEX_BIT) - index = 1 << index; + if (flags & CLK_MUX_INDEX_BIT) + val = 1 << index; - if (mux->flags & CLK_MUX_INDEX_ONE) - index++; + if (flags & CLK_MUX_INDEX_ONE) + val++; } + return val; +} +EXPORT_SYMBOL_GPL(clk_mux_index_to_val); + +static u8 clk_mux_get_parent(struct clk_hw *hw) +{ + struct clk_mux *mux = to_clk_mux(hw); + u32 val; + + val = clk_readl(mux->reg) >> mux->shift; + val &= mux->mask; + + return clk_mux_val_to_index(hw, mux->table, mux->flags, val); +} + +static int clk_mux_set_parent(struct clk_hw *hw, u8 index) +{ + struct clk_mux *mux = to_clk_mux(hw); + u32 val = clk_mux_index_to_val(mux->table, mux->flags, index); + unsigned long flags = 0; + u32 reg; + if (mux->lock) spin_lock_irqsave(mux->lock, flags); else __acquire(mux->lock); if (mux->flags & CLK_MUX_HIWORD_MASK) { - val = mux->mask << (mux->shift + 16); + reg = mux->mask << (mux->shift + 16); } else { - val = clk_readl(mux->reg); - val &= ~(mux->mask << mux->shift); + reg = clk_readl(mux->reg); + reg &= ~(mux->mask << mux->shift); } - val |= index << mux->shift; - clk_writel(val, mux->reg); + val = val << mux->shift; + reg |= val; + clk_writel(reg, mux->reg); if (mux->lock) spin_unlock_irqrestore(mux->lock, flags); diff --git a/include/linux/clk-provider.h b/include/linux/clk-provider.h index d8ba26d03332..fe720d679c31 100644 --- a/include/linux/clk-provider.h +++ b/include/linux/clk-provider.h @@ -511,6 +511,10 @@ struct clk_hw *clk_hw_register_mux_table(struct device *dev, const char *name, void __iomem *reg, u8 shift, u32 mask, u8 clk_mux_flags, u32 *table, spinlock_t *lock); +int clk_mux_val_to_index(struct clk_hw *hw, u32 *table, unsigned int flags, + unsigned int val); +unsigned int clk_mux_index_to_val(u32 *table, unsigned int flags, u8 index); + void clk_unregister_mux(struct clk *clk); void clk_hw_unregister_mux(struct clk_hw *hw); -- cgit v1.2.3 From 541debae0adf0bee96137724fa1ce81d3102d14c Mon Sep 17 00:00:00 2001 From: Jerome Brunet Date: Wed, 14 Feb 2018 14:43:37 +0100 Subject: clk: call the clock init() callback before any other ops callback Some clocks may need to initialize things, whatever it is, before being able to properly operate. Move the .init() call before any other callback, such recalc_rate() or get_phase(), so the clock is properly setup before being used. Signed-off-by: Jerome Brunet Signed-off-by: Michael Turquette Signed-off-by: Stephen Boyd --- drivers/clk/clk.c | 22 +++++++++++----------- 1 file changed, 11 insertions(+), 11 deletions(-) diff --git a/drivers/clk/clk.c b/drivers/clk/clk.c index cca05ea2c058..9d56be6ead39 100644 --- a/drivers/clk/clk.c +++ b/drivers/clk/clk.c @@ -2929,6 +2929,17 @@ static int __clk_core_init(struct clk_core *core) core->orphan = true; } + /* + * optional platform-specific magic + * + * The .init callback is not used by any of the basic clock types, but + * exists for weird hardware that must perform initialization magic. + * Please consider other ways of solving initialization problems before + * using this callback, as its use is discouraged. + */ + if (core->ops->init) + core->ops->init(core->hw); + /* * Set clk's accuracy. The preferred method is to use * .recalc_accuracy. For simple clocks and lazy developers the default @@ -3006,17 +3017,6 @@ static int __clk_core_init(struct clk_core *core) } } - /* - * optional platform-specific magic - * - * The .init callback is not used by any of the basic clock types, but - * exists for weird hardware that must perform initialization magic. - * Please consider other ways of solving initialization problems before - * using this callback, as its use is discouraged. - */ - if (core->ops->init) - core->ops->init(core->hw); - kref_init(&core->ref); out: clk_pm_runtime_put(core); -- cgit v1.2.3 From fe3f338f0cb2ed4d4f06da054c21ae2f8a36ef2d Mon Sep 17 00:00:00 2001 From: Jerome Brunet Date: Wed, 14 Feb 2018 14:43:38 +0100 Subject: clk: fix mux clock documentation The mux documentation mentions the non-existing parameter width instead of mask, so just sed this. The table field is missing in the documentation of clk_mux. Add a small blurb explaining what it is Fixes: 9d9f78ed9af0 ("clk: basic clock hardware types") Signed-off-by: Jerome Brunet Signed-off-by: Michael Turquette Signed-off-by: Stephen Boyd --- include/linux/clk-provider.h | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/include/linux/clk-provider.h b/include/linux/clk-provider.h index fe720d679c31..cb18526d69cb 100644 --- a/include/linux/clk-provider.h +++ b/include/linux/clk-provider.h @@ -450,8 +450,9 @@ void clk_hw_unregister_divider(struct clk_hw *hw); * * @hw: handle between common and hardware-specific interfaces * @reg: register controlling multiplexer + * @table: array of register values corresponding to the parent index * @shift: shift to multiplexer bit field - * @width: width of mutliplexer bit field + * @mask: mask of mutliplexer bit field * @flags: hardware-specific flags * @lock: register lock * -- cgit v1.2.3 From b15ee490e16324c35b51f04bad54ae45a2cefd29 Mon Sep 17 00:00:00 2001 From: Jerome Brunet Date: Wed, 14 Feb 2018 14:43:39 +0100 Subject: clk: divider: read-only divider can propagate rate change When a divider clock has CLK_DIVIDER_READ_ONLY set, it means that the register shall be left un-touched, but it does not mean the clock should stop rate propagation if CLK_SET_RATE_PARENT is set This is properly handled in qcom clk-regmap-divider but it was not in the generic divider To fix this situation, introduce a new helper function divider_ro_round_rate, on the same model as divider_round_rate. Fixes: e6d5e7d90be9 ("clk-divider: Fix READ_ONLY when divider > 1") Signed-off-by: Jerome Brunet Tested-By: David Lechner Signed-off-by: Michael Turquette Signed-off-by: Stephen Boyd --- drivers/clk/clk-divider.c | 36 ++++++++++++++++++++++++++++++------ include/linux/clk-provider.h | 15 +++++++++++++++ 2 files changed, 45 insertions(+), 6 deletions(-) diff --git a/drivers/clk/clk-divider.c b/drivers/clk/clk-divider.c index 3c98d2650fa3..b6234a5da12d 100644 --- a/drivers/clk/clk-divider.c +++ b/drivers/clk/clk-divider.c @@ -342,19 +342,43 @@ long divider_round_rate_parent(struct clk_hw *hw, struct clk_hw *parent, } EXPORT_SYMBOL_GPL(divider_round_rate_parent); +long divider_ro_round_rate_parent(struct clk_hw *hw, struct clk_hw *parent, + unsigned long rate, unsigned long *prate, + const struct clk_div_table *table, u8 width, + unsigned long flags, unsigned int val) +{ + int div; + + div = _get_div(table, val, flags, width); + + /* Even a read-only clock can propagate a rate change */ + if (clk_hw_get_flags(hw) & CLK_SET_RATE_PARENT) { + if (!parent) + return -EINVAL; + + *prate = clk_hw_round_rate(parent, rate * div); + } + + return DIV_ROUND_UP_ULL((u64)*prate, div); +} +EXPORT_SYMBOL_GPL(divider_ro_round_rate_parent); + + static long clk_divider_round_rate(struct clk_hw *hw, unsigned long rate, unsigned long *prate) { struct clk_divider *divider = to_clk_divider(hw); - int bestdiv; /* if read only, just return current value */ if (divider->flags & CLK_DIVIDER_READ_ONLY) { - bestdiv = clk_readl(divider->reg) >> divider->shift; - bestdiv &= clk_div_mask(divider->width); - bestdiv = _get_div(divider->table, bestdiv, divider->flags, - divider->width); - return DIV_ROUND_UP_ULL((u64)*prate, bestdiv); + u32 val; + + val = clk_readl(divider->reg) >> divider->shift; + val &= clk_div_mask(divider->width); + + return divider_ro_round_rate(hw, rate, prate, divider->table, + divider->width, divider->flags, + val); } return divider_round_rate(hw, rate, prate, divider->table, diff --git a/include/linux/clk-provider.h b/include/linux/clk-provider.h index cb18526d69cb..210a890008f9 100644 --- a/include/linux/clk-provider.h +++ b/include/linux/clk-provider.h @@ -420,6 +420,10 @@ long divider_round_rate_parent(struct clk_hw *hw, struct clk_hw *parent, unsigned long rate, unsigned long *prate, const struct clk_div_table *table, u8 width, unsigned long flags); +long divider_ro_round_rate_parent(struct clk_hw *hw, struct clk_hw *parent, + unsigned long rate, unsigned long *prate, + const struct clk_div_table *table, u8 width, + unsigned long flags, unsigned int val); int divider_get_val(unsigned long rate, unsigned long parent_rate, const struct clk_div_table *table, u8 width, unsigned long flags); @@ -780,6 +784,17 @@ static inline long divider_round_rate(struct clk_hw *hw, unsigned long rate, rate, prate, table, width, flags); } +static inline long divider_ro_round_rate(struct clk_hw *hw, unsigned long rate, + unsigned long *prate, + const struct clk_div_table *table, + u8 width, unsigned long flags, + unsigned int val) +{ + return divider_ro_round_rate_parent(hw, clk_hw_get_parent(hw), + rate, prate, table, width, flags, + val); +} + /* * FIXME clock api without lock protection */ -- cgit v1.2.3 From f5edaefee2d621f4e7628f1421c58a2361572d3a Mon Sep 17 00:00:00 2001 From: Jerome Brunet Date: Wed, 14 Feb 2018 14:43:40 +0100 Subject: clk: qcom: use divider_ro_round_rate helper There is now an helper function to round the rate when the divider is read-only. Let's use it Signed-off-by: Jerome Brunet Signed-off-by: Michael Turquette Signed-off-by: Stephen Boyd --- drivers/clk/qcom/clk-regmap-divider.c | 20 ++++++-------------- 1 file changed, 6 insertions(+), 14 deletions(-) diff --git a/drivers/clk/qcom/clk-regmap-divider.c b/drivers/clk/qcom/clk-regmap-divider.c index 4e9b8c2c8980..1ee75a5e93f4 100644 --- a/drivers/clk/qcom/clk-regmap-divider.c +++ b/drivers/clk/qcom/clk-regmap-divider.c @@ -28,22 +28,14 @@ static long div_round_ro_rate(struct clk_hw *hw, unsigned long rate, { struct clk_regmap_div *divider = to_clk_regmap_div(hw); struct clk_regmap *clkr = ÷r->clkr; - u32 div; - struct clk_hw *hw_parent = clk_hw_get_parent(hw); - - regmap_read(clkr->regmap, divider->reg, &div); - div >>= divider->shift; - div &= BIT(divider->width) - 1; - div += 1; - - if (clk_hw_get_flags(hw) & CLK_SET_RATE_PARENT) { - if (!hw_parent) - return -EINVAL; + u32 val; - *prate = clk_hw_round_rate(hw_parent, rate * div); - } + regmap_read(clkr->regmap, divider->reg, &val); + val >>= divider->shift; + val &= BIT(divider->width) - 1; - return DIV_ROUND_UP_ULL((u64)*prate, div); + return divider_ro_round_rate(hw, rate, prate, NULL, divider->width, + CLK_DIVIDER_ROUND_CLOSEST, val); } static long div_round_rate(struct clk_hw *hw, unsigned long rate, -- cgit v1.2.3 From 323346d31d68542b133088c7fe043c234f26eee4 Mon Sep 17 00:00:00 2001 From: Jerome Brunet Date: Mon, 12 Feb 2018 15:58:28 +0100 Subject: clk: meson: use dev pointer where possible The 'dev' pointer is directly available in gxbb and axg clock controller, so consistently use it instead of going the through the 'pdev' pointer once in while Signed-off-by: Jerome Brunet Signed-off-by: Neil Armstrong --- drivers/clk/meson/axg.c | 8 ++++---- drivers/clk/meson/gxbb.c | 2 +- 2 files changed, 5 insertions(+), 5 deletions(-) diff --git a/drivers/clk/meson/axg.c b/drivers/clk/meson/axg.c index 2dc70e0e925c..1f48649a7d2a 100644 --- a/drivers/clk/meson/axg.c +++ b/drivers/clk/meson/axg.c @@ -804,7 +804,7 @@ static int axg_clkc_probe(struct platform_device *pdev) void __iomem *clk_base; int ret, clkid, i; - clkc_data = of_device_get_match_data(&pdev->dev); + clkc_data = of_device_get_match_data(dev); if (!clkc_data) return -EINVAL; @@ -812,9 +812,9 @@ static int axg_clkc_probe(struct platform_device *pdev) res = platform_get_resource(pdev, IORESOURCE_MEM, 0); if (!res) return -EINVAL; - clk_base = devm_ioremap(&pdev->dev, res->start, resource_size(res)); + clk_base = devm_ioremap(dev, res->start, resource_size(res)); if (!clk_base) { - dev_err(&pdev->dev, "Unable to map clk base\n"); + dev_err(dev, "Unable to map clk base\n"); return -ENXIO; } @@ -849,7 +849,7 @@ static int axg_clkc_probe(struct platform_device *pdev) ret = devm_clk_hw_register(dev, clkc_data->hw_onecell_data->hws[clkid]); if (ret) { - dev_err(&pdev->dev, "Clock registration failed\n"); + dev_err(dev, "Clock registration failed\n"); return ret; } } diff --git a/drivers/clk/meson/gxbb.c b/drivers/clk/meson/gxbb.c index a5f25cc1944c..423abcb8ef88 100644 --- a/drivers/clk/meson/gxbb.c +++ b/drivers/clk/meson/gxbb.c @@ -1950,7 +1950,7 @@ static int gxbb_clkc_probe(struct platform_device *pdev) int ret, clkid, i; struct device *dev = &pdev->dev; - clkc_data = of_device_get_match_data(&pdev->dev); + clkc_data = of_device_get_match_data(dev); if (!clkc_data) return -EINVAL; -- cgit v1.2.3 From 332b32a23225e01cdfac4fb6cb1c76553f906cb5 Mon Sep 17 00:00:00 2001 From: Jerome Brunet Date: Mon, 12 Feb 2018 15:58:29 +0100 Subject: clk: meson: use devm_of_clk_add_hw_provider There is no remove callbacks in meson's clock controllers and of_clk_del_provider is never called if of_clk_add_hw_provider has been executed, introducing a potential memory leak. Fixing this by the using the devm variant. In reality, the leak would never happen since these controllers are never unloaded once in use ... still, this is worth cleaning. Signed-off-by: Jerome Brunet Signed-off-by: Neil Armstrong --- drivers/clk/meson/axg.c | 4 ++-- drivers/clk/meson/gxbb.c | 5 +++-- drivers/clk/meson/meson8b.c | 4 ++-- 3 files changed, 7 insertions(+), 6 deletions(-) diff --git a/drivers/clk/meson/axg.c b/drivers/clk/meson/axg.c index 1f48649a7d2a..e16d53b6be30 100644 --- a/drivers/clk/meson/axg.c +++ b/drivers/clk/meson/axg.c @@ -854,8 +854,8 @@ static int axg_clkc_probe(struct platform_device *pdev) } } - return of_clk_add_hw_provider(dev->of_node, of_clk_hw_onecell_get, - clkc_data->hw_onecell_data); + return devm_of_clk_add_hw_provider(dev, of_clk_hw_onecell_get, + clkc_data->hw_onecell_data); } static struct platform_driver axg_driver = { diff --git a/drivers/clk/meson/gxbb.c b/drivers/clk/meson/gxbb.c index 423abcb8ef88..17f44ac751b3 100644 --- a/drivers/clk/meson/gxbb.c +++ b/drivers/clk/meson/gxbb.c @@ -2002,8 +2002,9 @@ static int gxbb_clkc_probe(struct platform_device *pdev) goto iounmap; } - return of_clk_add_hw_provider(dev->of_node, of_clk_hw_onecell_get, - clkc_data->hw_onecell_data); + + return devm_of_clk_add_hw_provider(dev, of_clk_hw_onecell_get, + clkc_data->hw_onecell_data); iounmap: iounmap(clk_base); diff --git a/drivers/clk/meson/meson8b.c b/drivers/clk/meson/meson8b.c index 3ffea80c1308..abac079ff77f 100644 --- a/drivers/clk/meson/meson8b.c +++ b/drivers/clk/meson/meson8b.c @@ -878,8 +878,8 @@ static int meson8b_clkc_probe(struct platform_device *pdev) return ret; } - return of_clk_add_hw_provider(dev->of_node, of_clk_hw_onecell_get, - &meson8b_hw_onecell_data); + return devm_of_clk_add_hw_provider(dev, of_clk_hw_onecell_get, + &meson8b_hw_onecell_data); } static const struct of_device_id meson8b_clkc_match_table[] = { -- cgit v1.2.3 From 14bd7b9c8d3f4cc1f06563630b30adae7838f301 Mon Sep 17 00:00:00 2001 From: Jerome Brunet Date: Mon, 12 Feb 2018 15:58:30 +0100 Subject: clk: meson: only one loop index is necessary in probe We don't need several loop index variables in the probe function This is far from being critical but since we are doing a vast rework of meson clock controllers, now is the time to lower the entropy a bit Signed-off-by: Jerome Brunet Signed-off-by: Neil Armstrong --- drivers/clk/meson/axg.c | 8 ++++---- drivers/clk/meson/gxbb.c | 13 ++++++------- drivers/clk/meson/meson8b.c | 8 ++++---- 3 files changed, 14 insertions(+), 15 deletions(-) diff --git a/drivers/clk/meson/axg.c b/drivers/clk/meson/axg.c index e16d53b6be30..3bb77b4f1e8d 100644 --- a/drivers/clk/meson/axg.c +++ b/drivers/clk/meson/axg.c @@ -802,7 +802,7 @@ static int axg_clkc_probe(struct platform_device *pdev) const struct clkc_data *clkc_data; struct resource *res; void __iomem *clk_base; - int ret, clkid, i; + int ret, i; clkc_data = of_device_get_match_data(dev); if (!clkc_data) @@ -841,13 +841,13 @@ static int axg_clkc_probe(struct platform_device *pdev) clkc_data->clk_dividers[i]->reg = clk_base + (u64)clkc_data->clk_dividers[i]->reg; - for (clkid = 0; clkid < clkc_data->hw_onecell_data->num; clkid++) { + for (i = 0; i < clkc_data->hw_onecell_data->num; i++) { /* array might be sparse */ - if (!clkc_data->hw_onecell_data->hws[clkid]) + if (!clkc_data->hw_onecell_data->hws[i]) continue; ret = devm_clk_hw_register(dev, - clkc_data->hw_onecell_data->hws[clkid]); + clkc_data->hw_onecell_data->hws[i]); if (ret) { dev_err(dev, "Clock registration failed\n"); return ret; diff --git a/drivers/clk/meson/gxbb.c b/drivers/clk/meson/gxbb.c index 17f44ac751b3..e6adab49c0ba 100644 --- a/drivers/clk/meson/gxbb.c +++ b/drivers/clk/meson/gxbb.c @@ -1947,7 +1947,7 @@ static int gxbb_clkc_probe(struct platform_device *pdev) { const struct clkc_data *clkc_data; void __iomem *clk_base; - int ret, clkid, i; + int ret, i; struct device *dev = &pdev->dev; clkc_data = of_device_get_match_data(dev); @@ -1988,16 +1988,15 @@ static int gxbb_clkc_probe(struct platform_device *pdev) for (i = 0; i < clkc_data->clk_audio_dividers_count; i++) clkc_data->clk_audio_dividers[i]->base = clk_base; - /* - * register all clks - */ - for (clkid = 0; clkid < clkc_data->hw_onecell_data->num; clkid++) { + + /* Register all clks */ + for (i = 0; i < clkc_data->hw_onecell_data->num; i++) { /* array might be sparse */ - if (!clkc_data->hw_onecell_data->hws[clkid]) + if (!clkc_data->hw_onecell_data->hws[i]) continue; ret = devm_clk_hw_register(dev, - clkc_data->hw_onecell_data->hws[clkid]); + clkc_data->hw_onecell_data->hws[i]); if (ret) goto iounmap; } diff --git a/drivers/clk/meson/meson8b.c b/drivers/clk/meson/meson8b.c index abac079ff77f..ffadad27375e 100644 --- a/drivers/clk/meson/meson8b.c +++ b/drivers/clk/meson/meson8b.c @@ -806,7 +806,7 @@ static const struct reset_control_ops meson8b_clk_reset_ops = { static int meson8b_clkc_probe(struct platform_device *pdev) { - int ret, clkid, i; + int ret, i; struct clk_hw *parent_hw; struct clk *parent_clk; struct device *dev = &pdev->dev; @@ -844,13 +844,13 @@ static int meson8b_clkc_probe(struct platform_device *pdev) * register all clks * CLKID_UNUSED = 0, so skip it and start with CLKID_XTAL = 1 */ - for (clkid = CLKID_XTAL; clkid < CLK_NR_CLKS; clkid++) { + for (i = CLKID_XTAL; i < CLK_NR_CLKS; i++) { /* array might be sparse */ - if (!meson8b_hw_onecell_data.hws[clkid]) + if (!meson8b_hw_onecell_data.hws[i]) continue; /* FIXME convert to devm_clk_register */ - ret = devm_clk_hw_register(dev, meson8b_hw_onecell_data.hws[clkid]); + ret = devm_clk_hw_register(dev, meson8b_hw_onecell_data.hws[i]); if (ret) return ret; } -- cgit v1.2.3 From 7b174c5ebe46c739b0802d0781a32788f5259d2c Mon Sep 17 00:00:00 2001 From: Jerome Brunet Date: Mon, 12 Feb 2018 15:58:31 +0100 Subject: clk: meson: remove obsolete comments Over time things changes in CCF and issues have been fixed in meson controllers. Now, clk81 is decently modeled by read-only PLLs, a mux, a divider and a gate. We can remove the FIXME comments related to clk81. Also remove the comment about devm_clk_hw_register, as there is apparently nothing wrong with it. Signed-off-by: Jerome Brunet Signed-off-by: Neil Armstrong --- drivers/clk/meson/axg.c | 5 ----- drivers/clk/meson/gxbb.c | 6 ------ drivers/clk/meson/meson8b.c | 1 - 3 files changed, 12 deletions(-) diff --git a/drivers/clk/meson/axg.c b/drivers/clk/meson/axg.c index 3bb77b4f1e8d..bc5c29f13282 100644 --- a/drivers/clk/meson/axg.c +++ b/drivers/clk/meson/axg.c @@ -411,11 +411,6 @@ static struct meson_clk_mpll axg_mpll3 = { }, }; -/* - * FIXME The legacy composite clocks (e.g. clk81) are both PLL post-dividers - * and should be modeled with their respective PLLs via the forthcoming - * coordinated clock rates feature - */ static u32 mux_table_clk81[] = { 0, 2, 3, 4, 5, 6, 7 }; static const char * const clk81_parent_names[] = { "xtal", "fclk_div7", "mpll1", "mpll2", "fclk_div4", diff --git a/drivers/clk/meson/gxbb.c b/drivers/clk/meson/gxbb.c index e6adab49c0ba..6609024eee00 100644 --- a/drivers/clk/meson/gxbb.c +++ b/drivers/clk/meson/gxbb.c @@ -575,12 +575,6 @@ static struct meson_clk_mpll gxbb_mpll2 = { }, }; -/* - * FIXME The legacy composite clocks (e.g. clk81) are both PLL post-dividers - * and should be modeled with their respective PLLs via the forthcoming - * coordinated clock rates feature - */ - static u32 mux_table_clk81[] = { 0, 2, 3, 4, 5, 6, 7 }; static const char * const clk81_parent_names[] = { "xtal", "fclk_div7", "mpll1", "mpll2", "fclk_div4", diff --git a/drivers/clk/meson/meson8b.c b/drivers/clk/meson/meson8b.c index ffadad27375e..db017c29a84c 100644 --- a/drivers/clk/meson/meson8b.c +++ b/drivers/clk/meson/meson8b.c @@ -849,7 +849,6 @@ static int meson8b_clkc_probe(struct platform_device *pdev) if (!meson8b_hw_onecell_data.hws[i]) continue; - /* FIXME convert to devm_clk_register */ ret = devm_clk_hw_register(dev, meson8b_hw_onecell_data.hws[i]); if (ret) return ret; -- cgit v1.2.3 From ea11dda9e091aba0fe6497108477699286a2d036 Mon Sep 17 00:00:00 2001 From: Jerome Brunet Date: Mon, 12 Feb 2018 15:58:32 +0100 Subject: clk: meson: add regmap clocks Meson clock controllers need to move the classical iomem registers to regmap. This is triggered because the HHI controllers found on the GXBB and GXL host more than just clocks. To properly handle this, we would like to migrate HHI to syscon. Also GXBB AO clock controller already use regmap, AXG AO and Audio clock controllers will as well. The purpose of this change is to provide a common structure to these meson controllers (and possibly others) for regmap based clocks. This change provides the basic gate, mux and divider, based on the helpers provided by the related generic clocks Signed-off-by: Jerome Brunet Signed-off-by: Neil Armstrong --- drivers/clk/meson/Kconfig | 4 + drivers/clk/meson/Makefile | 1 + drivers/clk/meson/clk-regmap.c | 166 +++++++++++++++++++++++++++++++++++++++++ drivers/clk/meson/clk-regmap.h | 111 +++++++++++++++++++++++++++ 4 files changed, 282 insertions(+) create mode 100644 drivers/clk/meson/clk-regmap.c create mode 100644 drivers/clk/meson/clk-regmap.h diff --git a/drivers/clk/meson/Kconfig b/drivers/clk/meson/Kconfig index 7694302c70a4..e97e85077da1 100644 --- a/drivers/clk/meson/Kconfig +++ b/drivers/clk/meson/Kconfig @@ -3,6 +3,10 @@ config COMMON_CLK_AMLOGIC depends on OF depends on ARCH_MESON || COMPILE_TEST +config COMMON_CLK_REGMAP_MESON + bool + select REGMAP + config COMMON_CLK_MESON8B bool depends on COMMON_CLK_AMLOGIC diff --git a/drivers/clk/meson/Makefile b/drivers/clk/meson/Makefile index 3c03ce583798..11a50586666a 100644 --- a/drivers/clk/meson/Makefile +++ b/drivers/clk/meson/Makefile @@ -6,3 +6,4 @@ obj-$(CONFIG_COMMON_CLK_AMLOGIC) += clk-pll.o clk-cpu.o clk-mpll.o clk-audio-div obj-$(CONFIG_COMMON_CLK_MESON8B) += meson8b.o obj-$(CONFIG_COMMON_CLK_GXBB) += gxbb.o gxbb-aoclk.o gxbb-aoclk-regmap.o gxbb-aoclk-32k.o obj-$(CONFIG_COMMON_CLK_AXG) += axg.o +obj-$(CONFIG_COMMON_CLK_REGMAP_MESON) += clk-regmap.o diff --git a/drivers/clk/meson/clk-regmap.c b/drivers/clk/meson/clk-regmap.c new file mode 100644 index 000000000000..3645fdb62343 --- /dev/null +++ b/drivers/clk/meson/clk-regmap.c @@ -0,0 +1,166 @@ +// SPDX-License-Identifier: GPL-2.0 +// Copyright (c) 2018 BayLibre, SAS. +// Author: Jerome Brunet + +#include "clk-regmap.h" + +static int clk_regmap_gate_endisable(struct clk_hw *hw, int enable) +{ + struct clk_regmap *clk = to_clk_regmap(hw); + struct clk_regmap_gate_data *gate = clk_get_regmap_gate_data(clk); + int set = gate->flags & CLK_GATE_SET_TO_DISABLE ? 1 : 0; + + set ^= enable; + + return regmap_update_bits(clk->map, gate->offset, BIT(gate->bit_idx), + set ? BIT(gate->bit_idx) : 0); +} + +static int clk_regmap_gate_enable(struct clk_hw *hw) +{ + return clk_regmap_gate_endisable(hw, 1); +} + +static void clk_regmap_gate_disable(struct clk_hw *hw) +{ + clk_regmap_gate_endisable(hw, 0); +} + +static int clk_regmap_gate_is_enabled(struct clk_hw *hw) +{ + struct clk_regmap *clk = to_clk_regmap(hw); + struct clk_regmap_gate_data *gate = clk_get_regmap_gate_data(clk); + unsigned int val; + + regmap_read(clk->map, gate->offset, &val); + if (gate->flags & CLK_GATE_SET_TO_DISABLE) + val ^= BIT(gate->bit_idx); + + val &= BIT(gate->bit_idx); + + return val ? 1 : 0; +} + +const struct clk_ops clk_regmap_gate_ops = { + .enable = clk_regmap_gate_enable, + .disable = clk_regmap_gate_disable, + .is_enabled = clk_regmap_gate_is_enabled, +}; +EXPORT_SYMBOL_GPL(clk_regmap_gate_ops); + +static unsigned long clk_regmap_div_recalc_rate(struct clk_hw *hw, + unsigned long prate) +{ + struct clk_regmap *clk = to_clk_regmap(hw); + struct clk_regmap_div_data *div = clk_get_regmap_div_data(clk); + unsigned int val; + int ret; + + ret = regmap_read(clk->map, div->offset, &val); + if (ret) + /* Gives a hint that something is wrong */ + return 0; + + val >>= div->shift; + val &= clk_div_mask(div->width); + return divider_recalc_rate(hw, prate, val, div->table, div->flags, + div->width); +} + +static long clk_regmap_div_round_rate(struct clk_hw *hw, unsigned long rate, + unsigned long *prate) +{ + struct clk_regmap *clk = to_clk_regmap(hw); + struct clk_regmap_div_data *div = clk_get_regmap_div_data(clk); + unsigned int val; + int ret; + + /* if read only, just return current value */ + if (div->flags & CLK_DIVIDER_READ_ONLY) { + ret = regmap_read(clk->map, div->offset, &val); + if (ret) + /* Gives a hint that something is wrong */ + return 0; + + val >>= div->shift; + val &= clk_div_mask(div->width); + + return divider_ro_round_rate(hw, rate, prate, div->table, + div->width, div->flags, val); + } + + return divider_round_rate(hw, rate, prate, div->table, div->width, + div->flags); +} + +static int clk_regmap_div_set_rate(struct clk_hw *hw, unsigned long rate, + unsigned long parent_rate) +{ + struct clk_regmap *clk = to_clk_regmap(hw); + struct clk_regmap_div_data *div = clk_get_regmap_div_data(clk); + unsigned int val; + int ret; + + ret = divider_get_val(rate, parent_rate, div->table, div->width, + div->flags); + if (ret < 0) + return ret; + + val = (unsigned int)ret << div->shift; + return regmap_update_bits(clk->map, div->offset, + clk_div_mask(div->width) << div->shift, val); +}; + +/* Would prefer clk_regmap_div_ro_ops but clashes with qcom */ + +const struct clk_ops clk_regmap_divider_ops = { + .recalc_rate = clk_regmap_div_recalc_rate, + .round_rate = clk_regmap_div_round_rate, + .set_rate = clk_regmap_div_set_rate, +}; +EXPORT_SYMBOL_GPL(clk_regmap_divider_ops); + +const struct clk_ops clk_regmap_divider_ro_ops = { + .recalc_rate = clk_regmap_div_recalc_rate, + .round_rate = clk_regmap_div_round_rate, +}; +EXPORT_SYMBOL_GPL(clk_regmap_divider_ro_ops); + +static u8 clk_regmap_mux_get_parent(struct clk_hw *hw) +{ + struct clk_regmap *clk = to_clk_regmap(hw); + struct clk_regmap_mux_data *mux = clk_get_regmap_mux_data(clk); + unsigned int val; + int ret; + + ret = regmap_read(clk->map, mux->offset, &val); + if (ret) + return ret; + + val >>= mux->shift; + val &= mux->mask; + return clk_mux_val_to_index(hw, mux->table, mux->flags, val); +} + +static int clk_regmap_mux_set_parent(struct clk_hw *hw, u8 index) +{ + struct clk_regmap *clk = to_clk_regmap(hw); + struct clk_regmap_mux_data *mux = clk_get_regmap_mux_data(clk); + unsigned int val = clk_mux_index_to_val(mux->table, mux->flags, index); + + return regmap_update_bits(clk->map, mux->offset, + mux->mask << mux->shift, + val << mux->shift); +} + +const struct clk_ops clk_regmap_mux_ops = { + .get_parent = clk_regmap_mux_get_parent, + .set_parent = clk_regmap_mux_set_parent, + .determine_rate = __clk_mux_determine_rate, +}; +EXPORT_SYMBOL_GPL(clk_regmap_mux_ops); + +const struct clk_ops clk_regmap_mux_ro_ops = { + .get_parent = clk_regmap_mux_get_parent, +}; +EXPORT_SYMBOL_GPL(clk_regmap_mux_ro_ops); diff --git a/drivers/clk/meson/clk-regmap.h b/drivers/clk/meson/clk-regmap.h new file mode 100644 index 000000000000..627c888026d7 --- /dev/null +++ b/drivers/clk/meson/clk-regmap.h @@ -0,0 +1,111 @@ +// SPDX-License-Identifier: GPL-2.0 +// Copyright (c) 2018 BayLibre, SAS. +// Author: Jerome Brunet + +#ifndef __CLK_REGMAP_H +#define __CLK_REGMAP_H + +#include +#include + +/** + * struct clk_regmap - regmap backed clock + * + * @hw: handle between common and hardware-specific interfaces + * @map: pointer to the regmap structure controlling the clock + * @data: data specific to the clock type + * + * Clock which is controlled by regmap backed registers. The actual type of + * of the clock is controlled by the clock_ops and data. + */ +struct clk_regmap { + struct clk_hw hw; + struct regmap *map; + void *data; +}; + +#define to_clk_regmap(_hw) container_of(_hw, struct clk_regmap, hw) + +/** + * struct clk_regmap_gate_data - regmap backed gate specific data + * + * @offset: offset of the register controlling gate + * @bit_idx: single bit controlling gate + * @flags: hardware-specific flags + * + * Flags: + * Same as clk_gate except CLK_GATE_HIWORD_MASK which is ignored + */ +struct clk_regmap_gate_data { + unsigned int offset; + u8 bit_idx; + u8 flags; +}; + +static inline struct clk_regmap_gate_data * +clk_get_regmap_gate_data(struct clk_regmap *clk) +{ + return (struct clk_regmap_gate_data *)clk->data; +} + +extern const struct clk_ops clk_regmap_gate_ops; + +/** + * struct clk_regmap_div_data - regmap backed adjustable divider specific data + * + * @offset: offset of the register controlling the divider + * @shift: shift to the divider bit field + * @width: width of the divider bit field + * @table: array of value/divider pairs, last entry should have div = 0 + * + * Flags: + * Same as clk_divider except CLK_DIVIDER_HIWORD_MASK which is ignored + */ +struct clk_regmap_div_data { + unsigned int offset; + u8 shift; + u8 width; + u8 flags; + const struct clk_div_table *table; +}; + +static inline struct clk_regmap_div_data * +clk_get_regmap_div_data(struct clk_regmap *clk) +{ + return (struct clk_regmap_div_data *)clk->data; +} + +extern const struct clk_ops clk_regmap_divider_ops; +extern const struct clk_ops clk_regmap_divider_ro_ops; + +/** + * struct clk_regmap_mux_data - regmap backed multiplexer clock specific data + * + * @hw: handle between common and hardware-specific interfaces + * @offset: offset of theregister controlling multiplexer + * @table: array of parent indexed register values + * @shift: shift to multiplexer bit field + * @mask: mask of mutliplexer bit field + * @flags: hardware-specific flags + * + * Flags: + * Same as clk_divider except CLK_MUX_HIWORD_MASK which is ignored + */ +struct clk_regmap_mux_data { + unsigned int offset; + u32 *table; + u32 mask; + u8 shift; + u8 flags; +}; + +static inline struct clk_regmap_mux_data * +clk_get_regmap_mux_data(struct clk_regmap *clk) +{ + return (struct clk_regmap_mux_data *)clk->data; +} + +extern const struct clk_ops clk_regmap_mux_ops; +extern const struct clk_ops clk_regmap_mux_ro_ops; + +#endif /* __CLK_REGMAP_H */ -- cgit v1.2.3 From 81c7fcac9b5ffe5744bb1437d991739be7053528 Mon Sep 17 00:00:00 2001 From: Jerome Brunet Date: Mon, 12 Feb 2018 15:58:33 +0100 Subject: clk: meson: switch gxbb ao_clk to clk_regmap Drop the gxbb ao specific regmap based clock and use the meson clk_regmap based clock instead. Signed-off-by: Jerome Brunet Signed-off-by: Neil Armstrong --- drivers/clk/meson/Kconfig | 1 + drivers/clk/meson/Makefile | 2 +- drivers/clk/meson/gxbb-aoclk.c | 20 ++++++++++---------- drivers/clk/meson/gxbb-aoclk.h | 1 - 4 files changed, 12 insertions(+), 12 deletions(-) diff --git a/drivers/clk/meson/Kconfig b/drivers/clk/meson/Kconfig index e97e85077da1..33d148e19066 100644 --- a/drivers/clk/meson/Kconfig +++ b/drivers/clk/meson/Kconfig @@ -20,6 +20,7 @@ config COMMON_CLK_GXBB bool depends on COMMON_CLK_AMLOGIC select RESET_CONTROLLER + select COMMON_CLK_REGMAP_MESON help Support for the clock controller on AmLogic S905 devices, aka gxbb. Say Y if you want peripherals and CPU frequency scaling to work. diff --git a/drivers/clk/meson/Makefile b/drivers/clk/meson/Makefile index 11a50586666a..465086118d62 100644 --- a/drivers/clk/meson/Makefile +++ b/drivers/clk/meson/Makefile @@ -4,6 +4,6 @@ obj-$(CONFIG_COMMON_CLK_AMLOGIC) += clk-pll.o clk-cpu.o clk-mpll.o clk-audio-divider.o obj-$(CONFIG_COMMON_CLK_MESON8B) += meson8b.o -obj-$(CONFIG_COMMON_CLK_GXBB) += gxbb.o gxbb-aoclk.o gxbb-aoclk-regmap.o gxbb-aoclk-32k.o +obj-$(CONFIG_COMMON_CLK_GXBB) += gxbb.o gxbb-aoclk.o gxbb-aoclk-32k.o obj-$(CONFIG_COMMON_CLK_AXG) += axg.o obj-$(CONFIG_COMMON_CLK_REGMAP_MESON) += clk-regmap.o diff --git a/drivers/clk/meson/gxbb-aoclk.c b/drivers/clk/meson/gxbb-aoclk.c index 6c161e0a8e59..9ec23ae9a219 100644 --- a/drivers/clk/meson/gxbb-aoclk.c +++ b/drivers/clk/meson/gxbb-aoclk.c @@ -62,10 +62,9 @@ #include #include #include +#include "clk-regmap.h" #include "gxbb-aoclk.h" -static DEFINE_SPINLOCK(gxbb_aoclk_lock); - struct gxbb_aoclk_reset_controller { struct reset_controller_dev reset; unsigned int *data; @@ -87,12 +86,14 @@ static const struct reset_control_ops gxbb_aoclk_reset_ops = { }; #define GXBB_AO_GATE(_name, _bit) \ -static struct aoclk_gate_regmap _name##_ao = { \ - .bit_idx = (_bit), \ - .lock = &gxbb_aoclk_lock, \ +static struct clk_regmap _name##_ao = { \ + .data = &(struct clk_regmap_gate_data) { \ + .offset = AO_RTI_GEN_CNTL_REG0, \ + .bit_idx = (_bit), \ + }, \ .hw.init = &(struct clk_init_data) { \ .name = #_name "_ao", \ - .ops = &meson_aoclk_gate_regmap_ops, \ + .ops = &clk_regmap_gate_ops, \ .parent_names = (const char *[]){ "clk81" }, \ .num_parents = 1, \ .flags = (CLK_SET_RATE_PARENT | CLK_IGNORE_UNUSED), \ @@ -107,7 +108,6 @@ GXBB_AO_GATE(uart2, 5); GXBB_AO_GATE(ir_blaster, 6); static struct aoclk_cec_32k cec_32k_ao = { - .lock = &gxbb_aoclk_lock, .hw.init = &(struct clk_init_data) { .name = "cec_32k_ao", .ops = &meson_aoclk_cec_32k_ops, @@ -126,7 +126,7 @@ static unsigned int gxbb_aoclk_reset[] = { [RESET_AO_IR_BLASTER] = 23, }; -static struct aoclk_gate_regmap *gxbb_aoclk_gate[] = { +static struct clk_regmap *gxbb_aoclk_gate[] = { [CLKID_AO_REMOTE] = &remote_ao, [CLKID_AO_I2C_MASTER] = &i2c_master_ao, [CLKID_AO_I2C_SLAVE] = &i2c_slave_ao, @@ -177,10 +177,10 @@ static int gxbb_aoclkc_probe(struct platform_device *pdev) * Populate regmap and register all clks */ for (clkid = 0; clkid < ARRAY_SIZE(gxbb_aoclk_gate); clkid++) { - gxbb_aoclk_gate[clkid]->regmap = regmap; + gxbb_aoclk_gate[clkid]->map = regmap; ret = devm_clk_hw_register(dev, - gxbb_aoclk_onecell_data.hws[clkid]); + gxbb_aoclk_onecell_data.hws[clkid]); if (ret) return ret; } diff --git a/drivers/clk/meson/gxbb-aoclk.h b/drivers/clk/meson/gxbb-aoclk.h index e8604c8f7eee..127d58954cca 100644 --- a/drivers/clk/meson/gxbb-aoclk.h +++ b/drivers/clk/meson/gxbb-aoclk.h @@ -32,7 +32,6 @@ extern const struct clk_ops meson_aoclk_gate_regmap_ops; struct aoclk_cec_32k { struct clk_hw hw; struct regmap *regmap; - spinlock_t *lock; }; #define to_aoclk_cec_32k(_hw) container_of(_hw, struct aoclk_cec_32k, hw) -- cgit v1.2.3 From 1f932d99710d70572f8703641db9a878a6dbd063 Mon Sep 17 00:00:00 2001 From: Jerome Brunet Date: Mon, 12 Feb 2018 15:58:34 +0100 Subject: clk: meson: remove superseded aoclk_gate_regmap aoclk_gate_regmap has been replaced by meson's clk_regmap. It is no longer necessary so, remove it Signed-off-by: Jerome Brunet Signed-off-by: Neil Armstrong --- drivers/clk/meson/gxbb-aoclk-regmap.c | 46 ----------------------------------- drivers/clk/meson/gxbb-aoclk.h | 10 -------- 2 files changed, 56 deletions(-) delete mode 100644 drivers/clk/meson/gxbb-aoclk-regmap.c diff --git a/drivers/clk/meson/gxbb-aoclk-regmap.c b/drivers/clk/meson/gxbb-aoclk-regmap.c deleted file mode 100644 index 2515fbfa0467..000000000000 --- a/drivers/clk/meson/gxbb-aoclk-regmap.c +++ /dev/null @@ -1,46 +0,0 @@ -/* - * Copyright (c) 2017 BayLibre, SAS. - * Author: Neil Armstrong - * - * SPDX-License-Identifier: GPL-2.0+ - */ - -#include -#include -#include -#include "gxbb-aoclk.h" - -static int aoclk_gate_regmap_enable(struct clk_hw *hw) -{ - struct aoclk_gate_regmap *gate = to_aoclk_gate_regmap(hw); - - return regmap_update_bits(gate->regmap, AO_RTI_GEN_CNTL_REG0, - BIT(gate->bit_idx), BIT(gate->bit_idx)); -} - -static void aoclk_gate_regmap_disable(struct clk_hw *hw) -{ - struct aoclk_gate_regmap *gate = to_aoclk_gate_regmap(hw); - - regmap_update_bits(gate->regmap, AO_RTI_GEN_CNTL_REG0, - BIT(gate->bit_idx), 0); -} - -static int aoclk_gate_regmap_is_enabled(struct clk_hw *hw) -{ - struct aoclk_gate_regmap *gate = to_aoclk_gate_regmap(hw); - unsigned int val; - int ret; - - ret = regmap_read(gate->regmap, AO_RTI_GEN_CNTL_REG0, &val); - if (ret) - return ret; - - return (val & BIT(gate->bit_idx)) != 0; -} - -const struct clk_ops meson_aoclk_gate_regmap_ops = { - .enable = aoclk_gate_regmap_enable, - .disable = aoclk_gate_regmap_disable, - .is_enabled = aoclk_gate_regmap_is_enabled, -}; diff --git a/drivers/clk/meson/gxbb-aoclk.h b/drivers/clk/meson/gxbb-aoclk.h index 127d58954cca..0be78383f257 100644 --- a/drivers/clk/meson/gxbb-aoclk.h +++ b/drivers/clk/meson/gxbb-aoclk.h @@ -17,16 +17,6 @@ #define AO_RTC_ALT_CLK_CNTL0 0x94 #define AO_RTC_ALT_CLK_CNTL1 0x98 -struct aoclk_gate_regmap { - struct clk_hw hw; - unsigned bit_idx; - struct regmap *regmap; - spinlock_t *lock; -}; - -#define to_aoclk_gate_regmap(_hw) \ - container_of(_hw, struct aoclk_gate_regmap, hw) - extern const struct clk_ops meson_aoclk_gate_regmap_ops; struct aoclk_cec_32k { -- cgit v1.2.3 From 161f6e5baabdecb7057696bc4ce006d0d94091ec Mon Sep 17 00:00:00 2001 From: Jerome Brunet Date: Mon, 12 Feb 2018 15:58:35 +0100 Subject: clk: meson: add regmap to the clock controllers This change registers a regmap in meson8b, gxbb and axg controllers. The clock are still accessing their registers directly through iomem. Once all clocks handled by these controllers have been move to regmap, the regmap register will be removed and replaced with a syscon request. This is needed because other drivers, such as the HDMI driver, need to access the HHI register region Acked-by: Martin Blumenstingl Signed-off-by: Jerome Brunet Signed-off-by: Neil Armstrong --- drivers/clk/meson/Kconfig | 2 ++ drivers/clk/meson/axg.c | 15 ++++++++++++++- drivers/clk/meson/gxbb.c | 33 +++++++++++++++++++++++---------- drivers/clk/meson/meson8b.c | 14 +++++++++++++- 4 files changed, 52 insertions(+), 12 deletions(-) diff --git a/drivers/clk/meson/Kconfig b/drivers/clk/meson/Kconfig index 33d148e19066..9735335b17a9 100644 --- a/drivers/clk/meson/Kconfig +++ b/drivers/clk/meson/Kconfig @@ -11,6 +11,7 @@ config COMMON_CLK_MESON8B bool depends on COMMON_CLK_AMLOGIC select RESET_CONTROLLER + select REGMAP help Support for the clock controller on AmLogic S802 (Meson8), S805 (Meson8b) and S812 (Meson8m2) devices. Say Y if you @@ -29,6 +30,7 @@ config COMMON_CLK_AXG bool depends on COMMON_CLK_AMLOGIC select RESET_CONTROLLER + select REGMAP help Support for the clock controller on AmLogic A113D devices, aka axg. Say Y if you want peripherals and CPU frequency scaling to work. diff --git a/drivers/clk/meson/axg.c b/drivers/clk/meson/axg.c index bc5c29f13282..aed0f9e64f71 100644 --- a/drivers/clk/meson/axg.c +++ b/drivers/clk/meson/axg.c @@ -11,10 +11,11 @@ #include #include +#include #include #include #include -#include +#include #include "clkc.h" #include "axg.h" @@ -791,12 +792,19 @@ static const struct of_device_id clkc_match_table[] = { {} }; +static const struct regmap_config clkc_regmap_config = { + .reg_bits = 32, + .val_bits = 32, + .reg_stride = 4, +}; + static int axg_clkc_probe(struct platform_device *pdev) { struct device *dev = &pdev->dev; const struct clkc_data *clkc_data; struct resource *res; void __iomem *clk_base; + struct regmap *map; int ret, i; clkc_data = of_device_get_match_data(dev); @@ -807,12 +815,17 @@ static int axg_clkc_probe(struct platform_device *pdev) res = platform_get_resource(pdev, IORESOURCE_MEM, 0); if (!res) return -EINVAL; + clk_base = devm_ioremap(dev, res->start, resource_size(res)); if (!clk_base) { dev_err(dev, "Unable to map clk base\n"); return -ENXIO; } + map = devm_regmap_init_mmio(dev, clk_base, &clkc_regmap_config); + if (IS_ERR(map)) + return PTR_ERR(map); + /* Populate base address for PLLs */ for (i = 0; i < clkc_data->clk_plls_count; i++) clkc_data->clk_plls[i]->base = clk_base; diff --git a/drivers/clk/meson/gxbb.c b/drivers/clk/meson/gxbb.c index 6609024eee00..e3faf0a0fdb7 100644 --- a/drivers/clk/meson/gxbb.c +++ b/drivers/clk/meson/gxbb.c @@ -19,10 +19,11 @@ #include #include +#include #include #include #include -#include +#include #include "clkc.h" #include "gxbb.h" @@ -1937,10 +1938,18 @@ static const struct of_device_id clkc_match_table[] = { {}, }; +static const struct regmap_config clkc_regmap_config = { + .reg_bits = 32, + .val_bits = 32, + .reg_stride = 4, +}; + static int gxbb_clkc_probe(struct platform_device *pdev) { const struct clkc_data *clkc_data; + struct resource *res; void __iomem *clk_base; + struct regmap *map; int ret, i; struct device *dev = &pdev->dev; @@ -1948,13 +1957,20 @@ static int gxbb_clkc_probe(struct platform_device *pdev) if (!clkc_data) return -EINVAL; - /* Generic clocks and PLLs */ - clk_base = of_iomap(dev->of_node, 0); + res = platform_get_resource(pdev, IORESOURCE_MEM, 0); + if (!res) + return -EINVAL; + + clk_base = devm_ioremap(dev, res->start, resource_size(res)); if (!clk_base) { pr_err("%s: Unable to map clk base\n", __func__); return -ENXIO; } + map = devm_regmap_init_mmio(dev, clk_base, &clkc_regmap_config); + if (IS_ERR(map)) + return PTR_ERR(map); + /* Populate base address for PLLs */ for (i = 0; i < clkc_data->clk_plls_count; i++) clkc_data->clk_plls[i]->base = clk_base; @@ -1991,17 +2007,14 @@ static int gxbb_clkc_probe(struct platform_device *pdev) ret = devm_clk_hw_register(dev, clkc_data->hw_onecell_data->hws[i]); - if (ret) - goto iounmap; + if (ret) { + dev_err(dev, "Clock registration failed\n"); + return ret; + } } - return devm_of_clk_add_hw_provider(dev, of_clk_hw_onecell_get, clkc_data->hw_onecell_data); - -iounmap: - iounmap(clk_base); - return ret; } static struct platform_driver gxbb_driver = { diff --git a/drivers/clk/meson/meson8b.c b/drivers/clk/meson/meson8b.c index db017c29a84c..0981e970de3d 100644 --- a/drivers/clk/meson/meson8b.c +++ b/drivers/clk/meson/meson8b.c @@ -23,11 +23,12 @@ #include #include +#include #include #include #include #include -#include +#include #include "clkc.h" #include "meson8b.h" @@ -804,16 +805,27 @@ static const struct reset_control_ops meson8b_clk_reset_ops = { .deassert = meson8b_clk_reset_deassert, }; +static const struct regmap_config clkc_regmap_config = { + .reg_bits = 32, + .val_bits = 32, + .reg_stride = 4, +}; + static int meson8b_clkc_probe(struct platform_device *pdev) { int ret, i; struct clk_hw *parent_hw; struct clk *parent_clk; struct device *dev = &pdev->dev; + struct regmap *map; if (!clk_base) return -ENXIO; + map = devm_regmap_init_mmio(dev, clk_base, &clkc_regmap_config); + if (IS_ERR(map)) + return PTR_ERR(map); + /* Populate base address for PLLs */ for (i = 0; i < ARRAY_SIZE(meson8b_clk_plls); i++) meson8b_clk_plls[i]->base = clk_base; -- cgit v1.2.3 From 7f9768a5405192d49c5d963f5e29c740315efca7 Mon Sep 17 00:00:00 2001 From: Jerome Brunet Date: Mon, 12 Feb 2018 15:58:36 +0100 Subject: clk: meson: migrate gates to clk_regmap Move meson8b, gxbb and axg clocks using clk_gate to clk_regmap Signed-off-by: Jerome Brunet Signed-off-by: Neil Armstrong --- drivers/clk/meson/Kconfig | 4 +- drivers/clk/meson/axg.c | 72 ++++++------ drivers/clk/meson/clkc.h | 20 ++-- drivers/clk/meson/gxbb.c | 266 +++++++++++++++++++++++--------------------- drivers/clk/meson/meson8b.c | 39 +++---- 5 files changed, 206 insertions(+), 195 deletions(-) diff --git a/drivers/clk/meson/Kconfig b/drivers/clk/meson/Kconfig index 9735335b17a9..936afddae406 100644 --- a/drivers/clk/meson/Kconfig +++ b/drivers/clk/meson/Kconfig @@ -11,7 +11,7 @@ config COMMON_CLK_MESON8B bool depends on COMMON_CLK_AMLOGIC select RESET_CONTROLLER - select REGMAP + select COMMON_CLK_REGMAP_MESON help Support for the clock controller on AmLogic S802 (Meson8), S805 (Meson8b) and S812 (Meson8m2) devices. Say Y if you @@ -30,7 +30,7 @@ config COMMON_CLK_AXG bool depends on COMMON_CLK_AMLOGIC select RESET_CONTROLLER - select REGMAP + select COMMON_CLK_REGMAP_MESON help Support for the clock controller on AmLogic A113D devices, aka axg. Say Y if you want peripherals and CPU frequency scaling to work. diff --git a/drivers/clk/meson/axg.c b/drivers/clk/meson/axg.c index aed0f9e64f71..ed14f6ea7b07 100644 --- a/drivers/clk/meson/axg.c +++ b/drivers/clk/meson/axg.c @@ -447,13 +447,14 @@ static struct clk_divider axg_mpeg_clk_div = { }, }; -static struct clk_gate axg_clk81 = { - .reg = (void *)HHI_MPEG_CLK_CNTL, - .bit_idx = 7, - .lock = &meson_clk_lock, +static struct clk_regmap axg_clk81 = { + .data = &(struct clk_regmap_gate_data){ + .offset = HHI_MPEG_CLK_CNTL, + .bit_idx = 7, + }, .hw.init = &(struct clk_init_data){ .name = "clk81", - .ops = &clk_gate_ops, + .ops = &clk_regmap_gate_ops, .parent_names = (const char *[]){ "mpeg_clk_div" }, .num_parents = 1, .flags = (CLK_SET_RATE_PARENT | CLK_IS_CRITICAL), @@ -501,13 +502,14 @@ static struct clk_divider axg_sd_emmc_b_clk0_div = { }, }; -static struct clk_gate axg_sd_emmc_b_clk0 = { - .reg = (void *)HHI_SD_EMMC_CLK_CNTL, - .bit_idx = 23, - .lock = &meson_clk_lock, +static struct clk_regmap axg_sd_emmc_b_clk0 = { + .data = &(struct clk_regmap_gate_data){ + .offset = HHI_SD_EMMC_CLK_CNTL, + .bit_idx = 23, + }, .hw.init = &(struct clk_init_data){ .name = "sd_emmc_b_clk0", - .ops = &clk_gate_ops, + .ops = &clk_regmap_gate_ops, .parent_names = (const char *[]){ "sd_emmc_b_clk0_div" }, .num_parents = 1, .flags = CLK_SET_RATE_PARENT, @@ -544,13 +546,14 @@ static struct clk_divider axg_sd_emmc_c_clk0_div = { }, }; -static struct clk_gate axg_sd_emmc_c_clk0 = { - .reg = (void *)HHI_NAND_CLK_CNTL, - .bit_idx = 7, - .lock = &meson_clk_lock, +static struct clk_regmap axg_sd_emmc_c_clk0 = { + .data = &(struct clk_regmap_gate_data){ + .offset = HHI_NAND_CLK_CNTL, + .bit_idx = 7, + }, .hw.init = &(struct clk_init_data){ .name = "sd_emmc_c_clk0", - .ops = &clk_gate_ops, + .ops = &clk_regmap_gate_ops, .parent_names = (const char *[]){ "sd_emmc_c_clk0_div" }, .num_parents = 1, .flags = CLK_SET_RATE_PARENT, @@ -697,7 +700,19 @@ static struct meson_clk_mpll *const axg_clk_mplls[] = { &axg_mpll3, }; -static struct clk_gate *const axg_clk_gates[] = { +static struct clk_mux *const axg_clk_muxes[] = { + &axg_mpeg_clk_sel, + &axg_sd_emmc_b_clk0_sel, + &axg_sd_emmc_c_clk0_sel, +}; + +static struct clk_divider *const axg_clk_dividers[] = { + &axg_mpeg_clk_div, + &axg_sd_emmc_b_clk0_div, + &axg_sd_emmc_c_clk0_div, +}; + +static struct clk_regmap *const axg_clk_regmaps[] = { &axg_clk81, &axg_ddr, &axg_audio_locker, @@ -747,21 +762,7 @@ static struct clk_gate *const axg_clk_gates[] = { &axg_sd_emmc_c_clk0, }; -static struct clk_mux *const axg_clk_muxes[] = { - &axg_mpeg_clk_sel, - &axg_sd_emmc_b_clk0_sel, - &axg_sd_emmc_c_clk0_sel, -}; - -static struct clk_divider *const axg_clk_dividers[] = { - &axg_mpeg_clk_div, - &axg_sd_emmc_b_clk0_div, - &axg_sd_emmc_c_clk0_div, -}; - struct clkc_data { - struct clk_gate *const *clk_gates; - unsigned int clk_gates_count; struct meson_clk_mpll *const *clk_mplls; unsigned int clk_mplls_count; struct meson_clk_pll *const *clk_plls; @@ -774,8 +775,6 @@ struct clkc_data { }; static const struct clkc_data axg_clkc_data = { - .clk_gates = axg_clk_gates, - .clk_gates_count = ARRAY_SIZE(axg_clk_gates), .clk_mplls = axg_clk_mplls, .clk_mplls_count = ARRAY_SIZE(axg_clk_mplls), .clk_plls = axg_clk_plls, @@ -834,11 +833,6 @@ static int axg_clkc_probe(struct platform_device *pdev) for (i = 0; i < clkc_data->clk_mplls_count; i++) clkc_data->clk_mplls[i]->base = clk_base; - /* Populate base address for gates */ - for (i = 0; i < clkc_data->clk_gates_count; i++) - clkc_data->clk_gates[i]->reg = clk_base + - (u64)clkc_data->clk_gates[i]->reg; - /* Populate base address for muxes */ for (i = 0; i < clkc_data->clk_muxes_count; i++) clkc_data->clk_muxes[i]->reg = clk_base + @@ -849,6 +843,10 @@ static int axg_clkc_probe(struct platform_device *pdev) clkc_data->clk_dividers[i]->reg = clk_base + (u64)clkc_data->clk_dividers[i]->reg; + /* Populate regmap for the regmap backed clocks */ + for (i = 0; i < ARRAY_SIZE(axg_clk_regmaps); i++) + axg_clk_regmaps[i]->map = map; + for (i = 0; i < clkc_data->hw_onecell_data->num; i++) { /* array might be sparse */ if (!clkc_data->hw_onecell_data->hws[i]) diff --git a/drivers/clk/meson/clkc.h b/drivers/clk/meson/clkc.h index 07aaba26a857..aa2dfa0ff89f 100644 --- a/drivers/clk/meson/clkc.h +++ b/drivers/clk/meson/clkc.h @@ -18,6 +18,9 @@ #ifndef __CLKC_H #define __CLKC_H +#include +#include "clk-regmap.h" + #define PMASK(width) GENMASK(width - 1, 0) #define SETPMASK(width, shift) GENMASK(shift + width - 1, shift) #define CLRPMASK(width, shift) (~SETPMASK(width, shift)) @@ -134,16 +137,17 @@ struct meson_clk_audio_divider { }; #define MESON_GATE(_name, _reg, _bit) \ -struct clk_gate _name = { \ - .reg = (void __iomem *) _reg, \ - .bit_idx = (_bit), \ - .lock = &meson_clk_lock, \ - .hw.init = &(struct clk_init_data) { \ - .name = #_name, \ - .ops = &clk_gate_ops, \ +struct clk_regmap _name = { \ + .data = &(struct clk_regmap_gate_data){ \ + .offset = (_reg), \ + .bit_idx = (_bit), \ + }, \ + .hw.init = &(struct clk_init_data) { \ + .name = #_name, \ + .ops = &clk_regmap_gate_ops, \ .parent_names = (const char *[]){ "clk81" }, \ .num_parents = 1, \ - .flags = (CLK_SET_RATE_PARENT | CLK_IGNORE_UNUSED), \ + .flags = (CLK_SET_RATE_PARENT | CLK_IGNORE_UNUSED), \ }, \ }; diff --git a/drivers/clk/meson/gxbb.c b/drivers/clk/meson/gxbb.c index e3faf0a0fdb7..ccbbebb6a69b 100644 --- a/drivers/clk/meson/gxbb.c +++ b/drivers/clk/meson/gxbb.c @@ -27,6 +27,7 @@ #include "clkc.h" #include "gxbb.h" +#include "clk-regmap.h" static DEFINE_SPINLOCK(meson_clk_lock); @@ -617,14 +618,15 @@ static struct clk_divider gxbb_mpeg_clk_div = { }, }; -/* the mother of dragons^W gates */ -static struct clk_gate gxbb_clk81 = { - .reg = (void *)HHI_MPEG_CLK_CNTL, - .bit_idx = 7, - .lock = &meson_clk_lock, +/* the mother of dragons gates */ +static struct clk_regmap gxbb_clk81 = { + .data = &(struct clk_regmap_gate_data){ + .offset = HHI_MPEG_CLK_CNTL, + .bit_idx = 7, + }, .hw.init = &(struct clk_init_data){ .name = "clk81", - .ops = &clk_gate_ops, + .ops = &clk_regmap_gate_ops, .parent_names = (const char *[]){ "mpeg_clk_div" }, .num_parents = 1, .flags = (CLK_SET_RATE_PARENT | CLK_IS_CRITICAL), @@ -658,13 +660,14 @@ static struct clk_divider gxbb_sar_adc_clk_div = { }, }; -static struct clk_gate gxbb_sar_adc_clk = { - .reg = (void *)HHI_SAR_CLK_CNTL, - .bit_idx = 8, - .lock = &meson_clk_lock, +static struct clk_regmap gxbb_sar_adc_clk = { + .data = &(struct clk_regmap_gate_data){ + .offset = HHI_SAR_CLK_CNTL, + .bit_idx = 8, + }, .hw.init = &(struct clk_init_data){ .name = "sar_adc_clk", - .ops = &clk_gate_ops, + .ops = &clk_regmap_gate_ops, .parent_names = (const char *[]){ "sar_adc_clk_div" }, .num_parents = 1, .flags = CLK_SET_RATE_PARENT, @@ -716,13 +719,14 @@ static struct clk_divider gxbb_mali_0_div = { }, }; -static struct clk_gate gxbb_mali_0 = { - .reg = (void *)HHI_MALI_CLK_CNTL, - .bit_idx = 8, - .lock = &meson_clk_lock, +static struct clk_regmap gxbb_mali_0 = { + .data = &(struct clk_regmap_gate_data){ + .offset = HHI_MALI_CLK_CNTL, + .bit_idx = 8, + }, .hw.init = &(struct clk_init_data){ .name = "mali_0", - .ops = &clk_gate_ops, + .ops = &clk_regmap_gate_ops, .parent_names = (const char *[]){ "mali_0_div" }, .num_parents = 1, .flags = CLK_SET_RATE_PARENT, @@ -763,13 +767,14 @@ static struct clk_divider gxbb_mali_1_div = { }, }; -static struct clk_gate gxbb_mali_1 = { - .reg = (void *)HHI_MALI_CLK_CNTL, - .bit_idx = 24, - .lock = &meson_clk_lock, +static struct clk_regmap gxbb_mali_1 = { + .data = &(struct clk_regmap_gate_data){ + .offset = HHI_MALI_CLK_CNTL, + .bit_idx = 24, + }, .hw.init = &(struct clk_init_data){ .name = "mali_1", - .ops = &clk_gate_ops, + .ops = &clk_regmap_gate_ops, .parent_names = (const char *[]){ "mali_1_div" }, .num_parents = 1, .flags = CLK_SET_RATE_PARENT, @@ -829,13 +834,14 @@ static struct meson_clk_audio_divider gxbb_cts_amclk_div = { }, }; -static struct clk_gate gxbb_cts_amclk = { - .reg = (void *) HHI_AUD_CLK_CNTL, - .bit_idx = 8, - .lock = &meson_clk_lock, +static struct clk_regmap gxbb_cts_amclk = { + .data = &(struct clk_regmap_gate_data){ + .offset = HHI_AUD_CLK_CNTL, + .bit_idx = 8, + }, .hw.init = &(struct clk_init_data){ .name = "cts_amclk", - .ops = &clk_gate_ops, + .ops = &clk_regmap_gate_ops, .parent_names = (const char *[]){ "cts_amclk_div" }, .num_parents = 1, .flags = CLK_SET_RATE_PARENT, @@ -873,13 +879,14 @@ static struct clk_divider gxbb_cts_mclk_i958_div = { }, }; -static struct clk_gate gxbb_cts_mclk_i958 = { - .reg = (void *)HHI_AUD_CLK_CNTL2, - .bit_idx = 24, - .lock = &meson_clk_lock, +static struct clk_regmap gxbb_cts_mclk_i958 = { + .data = &(struct clk_regmap_gate_data){ + .offset = HHI_AUD_CLK_CNTL2, + .bit_idx = 24, + }, .hw.init = &(struct clk_init_data){ .name = "cts_mclk_i958", - .ops = &clk_gate_ops, + .ops = &clk_regmap_gate_ops, .parent_names = (const char *[]){ "cts_mclk_i958_div" }, .num_parents = 1, .flags = CLK_SET_RATE_PARENT, @@ -918,13 +925,14 @@ static struct clk_divider gxbb_32k_clk_div = { }, }; -static struct clk_gate gxbb_32k_clk = { - .reg = (void *)HHI_32K_CLK_CNTL, - .bit_idx = 15, - .lock = &meson_clk_lock, +static struct clk_regmap gxbb_32k_clk = { + .data = &(struct clk_regmap_gate_data){ + .offset = HHI_32K_CLK_CNTL, + .bit_idx = 15, + }, .hw.init = &(struct clk_init_data){ .name = "32k_clk", - .ops = &clk_gate_ops, + .ops = &clk_regmap_gate_ops, .parent_names = (const char *[]){ "32k_clk_div" }, .num_parents = 1, .flags = CLK_SET_RATE_PARENT, @@ -990,13 +998,14 @@ static struct clk_divider gxbb_sd_emmc_a_clk0_div = { }, }; -static struct clk_gate gxbb_sd_emmc_a_clk0 = { - .reg = (void *)HHI_SD_EMMC_CLK_CNTL, - .bit_idx = 7, - .lock = &meson_clk_lock, +static struct clk_regmap gxbb_sd_emmc_a_clk0 = { + .data = &(struct clk_regmap_gate_data){ + .offset = HHI_SD_EMMC_CLK_CNTL, + .bit_idx = 7, + }, .hw.init = &(struct clk_init_data){ .name = "sd_emmc_a_clk0", - .ops = &clk_gate_ops, + .ops = &clk_regmap_gate_ops, .parent_names = (const char *[]){ "sd_emmc_a_clk0_div" }, .num_parents = 1, .flags = CLK_SET_RATE_PARENT, @@ -1033,13 +1042,14 @@ static struct clk_divider gxbb_sd_emmc_b_clk0_div = { }, }; -static struct clk_gate gxbb_sd_emmc_b_clk0 = { - .reg = (void *)HHI_SD_EMMC_CLK_CNTL, - .bit_idx = 23, - .lock = &meson_clk_lock, +static struct clk_regmap gxbb_sd_emmc_b_clk0 = { + .data = &(struct clk_regmap_gate_data){ + .offset = HHI_SD_EMMC_CLK_CNTL, + .bit_idx = 23, + }, .hw.init = &(struct clk_init_data){ .name = "sd_emmc_b_clk0", - .ops = &clk_gate_ops, + .ops = &clk_regmap_gate_ops, .parent_names = (const char *[]){ "sd_emmc_b_clk0_div" }, .num_parents = 1, .flags = CLK_SET_RATE_PARENT, @@ -1076,13 +1086,14 @@ static struct clk_divider gxbb_sd_emmc_c_clk0_div = { }, }; -static struct clk_gate gxbb_sd_emmc_c_clk0 = { - .reg = (void *)HHI_NAND_CLK_CNTL, - .bit_idx = 7, - .lock = &meson_clk_lock, +static struct clk_regmap gxbb_sd_emmc_c_clk0 = { + .data = &(struct clk_regmap_gate_data){ + .offset = HHI_NAND_CLK_CNTL, + .bit_idx = 7, + }, .hw.init = &(struct clk_init_data){ .name = "sd_emmc_c_clk0", - .ops = &clk_gate_ops, + .ops = &clk_regmap_gate_ops, .parent_names = (const char *[]){ "sd_emmc_c_clk0_div" }, .num_parents = 1, .flags = CLK_SET_RATE_PARENT, @@ -1129,13 +1140,14 @@ static struct clk_divider gxbb_vpu_0_div = { }, }; -static struct clk_gate gxbb_vpu_0 = { - .reg = (void *)HHI_VPU_CLK_CNTL, - .bit_idx = 8, - .lock = &meson_clk_lock, +static struct clk_regmap gxbb_vpu_0 = { + .data = &(struct clk_regmap_gate_data){ + .offset = HHI_VPU_CLK_CNTL, + .bit_idx = 8, + }, .hw.init = &(struct clk_init_data) { .name = "vpu_0", - .ops = &clk_gate_ops, + .ops = &clk_regmap_gate_ops, .parent_names = (const char *[]){ "vpu_0_div" }, .num_parents = 1, .flags = CLK_SET_RATE_PARENT | CLK_IGNORE_UNUSED, @@ -1175,13 +1187,14 @@ static struct clk_divider gxbb_vpu_1_div = { }, }; -static struct clk_gate gxbb_vpu_1 = { - .reg = (void *)HHI_VPU_CLK_CNTL, - .bit_idx = 24, - .lock = &meson_clk_lock, +static struct clk_regmap gxbb_vpu_1 = { + .data = &(struct clk_regmap_gate_data){ + .offset = HHI_VPU_CLK_CNTL, + .bit_idx = 24, + }, .hw.init = &(struct clk_init_data) { .name = "vpu_1", - .ops = &clk_gate_ops, + .ops = &clk_regmap_gate_ops, .parent_names = (const char *[]){ "vpu_1_div" }, .num_parents = 1, .flags = CLK_SET_RATE_PARENT | CLK_IGNORE_UNUSED, @@ -1246,13 +1259,14 @@ static struct clk_divider gxbb_vapb_0_div = { }, }; -static struct clk_gate gxbb_vapb_0 = { - .reg = (void *)HHI_VAPBCLK_CNTL, - .bit_idx = 8, - .lock = &meson_clk_lock, +static struct clk_regmap gxbb_vapb_0 = { + .data = &(struct clk_regmap_gate_data){ + .offset = HHI_VAPBCLK_CNTL, + .bit_idx = 8, + }, .hw.init = &(struct clk_init_data) { .name = "vapb_0", - .ops = &clk_gate_ops, + .ops = &clk_regmap_gate_ops, .parent_names = (const char *[]){ "vapb_0_div" }, .num_parents = 1, .flags = CLK_SET_RATE_PARENT | CLK_IGNORE_UNUSED, @@ -1292,13 +1306,14 @@ static struct clk_divider gxbb_vapb_1_div = { }, }; -static struct clk_gate gxbb_vapb_1 = { - .reg = (void *)HHI_VAPBCLK_CNTL, - .bit_idx = 24, - .lock = &meson_clk_lock, +static struct clk_regmap gxbb_vapb_1 = { + .data = &(struct clk_regmap_gate_data){ + .offset = HHI_VAPBCLK_CNTL, + .bit_idx = 24, + }, .hw.init = &(struct clk_init_data) { .name = "vapb_1", - .ops = &clk_gate_ops, + .ops = &clk_regmap_gate_ops, .parent_names = (const char *[]){ "vapb_1_div" }, .num_parents = 1, .flags = CLK_SET_RATE_PARENT | CLK_IGNORE_UNUSED, @@ -1323,13 +1338,14 @@ static struct clk_mux gxbb_vapb_sel = { }, }; -static struct clk_gate gxbb_vapb = { - .reg = (void *)HHI_VAPBCLK_CNTL, - .bit_idx = 30, - .lock = &meson_clk_lock, +static struct clk_regmap gxbb_vapb = { + .data = &(struct clk_regmap_gate_data){ + .offset = HHI_VAPBCLK_CNTL, + .bit_idx = 30, + }, .hw.init = &(struct clk_init_data) { .name = "vapb", - .ops = &clk_gate_ops, + .ops = &clk_regmap_gate_ops, .parent_names = (const char *[]){ "vapb_sel" }, .num_parents = 1, .flags = CLK_SET_RATE_PARENT | CLK_IGNORE_UNUSED, @@ -1744,7 +1760,48 @@ static struct meson_clk_mpll *const gxbb_clk_mplls[] = { &gxbb_mpll2, }; -static struct clk_gate *const gxbb_clk_gates[] = { +static struct clk_mux *const gxbb_clk_muxes[] = { + &gxbb_mpeg_clk_sel, + &gxbb_sar_adc_clk_sel, + &gxbb_mali_0_sel, + &gxbb_mali_1_sel, + &gxbb_mali, + &gxbb_cts_amclk_sel, + &gxbb_cts_mclk_i958_sel, + &gxbb_cts_i958, + &gxbb_32k_clk_sel, + &gxbb_sd_emmc_a_clk0_sel, + &gxbb_sd_emmc_b_clk0_sel, + &gxbb_sd_emmc_c_clk0_sel, + &gxbb_vpu_0_sel, + &gxbb_vpu_1_sel, + &gxbb_vpu, + &gxbb_vapb_0_sel, + &gxbb_vapb_1_sel, + &gxbb_vapb_sel, +}; + +static struct clk_divider *const gxbb_clk_dividers[] = { + &gxbb_mpeg_clk_div, + &gxbb_sar_adc_clk_div, + &gxbb_mali_0_div, + &gxbb_mali_1_div, + &gxbb_cts_mclk_i958_div, + &gxbb_32k_clk_div, + &gxbb_sd_emmc_a_clk0_div, + &gxbb_sd_emmc_b_clk0_div, + &gxbb_sd_emmc_c_clk0_div, + &gxbb_vpu_0_div, + &gxbb_vpu_1_div, + &gxbb_vapb_0_div, + &gxbb_vapb_1_div, +}; + +static struct meson_clk_audio_divider *const gxbb_audio_dividers[] = { + &gxbb_cts_amclk_div, +}; + +static struct clk_regmap *const gx_clk_regmaps[] = { &gxbb_clk81, &gxbb_ddr, &gxbb_dos, @@ -1843,50 +1900,7 @@ static struct clk_gate *const gxbb_clk_gates[] = { &gxbb_vapb, }; -static struct clk_mux *const gxbb_clk_muxes[] = { - &gxbb_mpeg_clk_sel, - &gxbb_sar_adc_clk_sel, - &gxbb_mali_0_sel, - &gxbb_mali_1_sel, - &gxbb_mali, - &gxbb_cts_amclk_sel, - &gxbb_cts_mclk_i958_sel, - &gxbb_cts_i958, - &gxbb_32k_clk_sel, - &gxbb_sd_emmc_a_clk0_sel, - &gxbb_sd_emmc_b_clk0_sel, - &gxbb_sd_emmc_c_clk0_sel, - &gxbb_vpu_0_sel, - &gxbb_vpu_1_sel, - &gxbb_vpu, - &gxbb_vapb_0_sel, - &gxbb_vapb_1_sel, - &gxbb_vapb_sel, -}; - -static struct clk_divider *const gxbb_clk_dividers[] = { - &gxbb_mpeg_clk_div, - &gxbb_sar_adc_clk_div, - &gxbb_mali_0_div, - &gxbb_mali_1_div, - &gxbb_cts_mclk_i958_div, - &gxbb_32k_clk_div, - &gxbb_sd_emmc_a_clk0_div, - &gxbb_sd_emmc_b_clk0_div, - &gxbb_sd_emmc_c_clk0_div, - &gxbb_vpu_0_div, - &gxbb_vpu_1_div, - &gxbb_vapb_0_div, - &gxbb_vapb_1_div, -}; - -static struct meson_clk_audio_divider *const gxbb_audio_dividers[] = { - &gxbb_cts_amclk_div, -}; - struct clkc_data { - struct clk_gate *const *clk_gates; - unsigned int clk_gates_count; struct meson_clk_mpll *const *clk_mplls; unsigned int clk_mplls_count; struct meson_clk_pll *const *clk_plls; @@ -1901,8 +1915,6 @@ struct clkc_data { }; static const struct clkc_data gxbb_clkc_data = { - .clk_gates = gxbb_clk_gates, - .clk_gates_count = ARRAY_SIZE(gxbb_clk_gates), .clk_mplls = gxbb_clk_mplls, .clk_mplls_count = ARRAY_SIZE(gxbb_clk_mplls), .clk_plls = gxbb_clk_plls, @@ -1917,8 +1929,6 @@ static const struct clkc_data gxbb_clkc_data = { }; static const struct clkc_data gxl_clkc_data = { - .clk_gates = gxbb_clk_gates, - .clk_gates_count = ARRAY_SIZE(gxbb_clk_gates), .clk_mplls = gxbb_clk_mplls, .clk_mplls_count = ARRAY_SIZE(gxbb_clk_mplls), .clk_plls = gxl_clk_plls, @@ -1979,11 +1989,6 @@ static int gxbb_clkc_probe(struct platform_device *pdev) for (i = 0; i < clkc_data->clk_mplls_count; i++) clkc_data->clk_mplls[i]->base = clk_base; - /* Populate base address for gates */ - for (i = 0; i < clkc_data->clk_gates_count; i++) - clkc_data->clk_gates[i]->reg = clk_base + - (u64)clkc_data->clk_gates[i]->reg; - /* Populate base address for muxes */ for (i = 0; i < clkc_data->clk_muxes_count; i++) clkc_data->clk_muxes[i]->reg = clk_base + @@ -1998,6 +2003,9 @@ static int gxbb_clkc_probe(struct platform_device *pdev) for (i = 0; i < clkc_data->clk_audio_dividers_count; i++) clkc_data->clk_audio_dividers[i]->base = clk_base; + /* Populate regmap for the common regmap backed clocks */ + for (i = 0; i < ARRAY_SIZE(gx_clk_regmaps); i++) + gx_clk_regmaps[i]->map = map; /* Register all clks */ for (i = 0; i < clkc_data->hw_onecell_data->num; i++) { diff --git a/drivers/clk/meson/meson8b.c b/drivers/clk/meson/meson8b.c index 0981e970de3d..835dbb1d2c9d 100644 --- a/drivers/clk/meson/meson8b.c +++ b/drivers/clk/meson/meson8b.c @@ -32,6 +32,7 @@ #include "clkc.h" #include "meson8b.h" +#include "clk-regmap.h" static DEFINE_SPINLOCK(meson_clk_lock); @@ -406,13 +407,14 @@ struct clk_divider meson8b_mpeg_clk_div = { }, }; -struct clk_gate meson8b_clk81 = { - .reg = (void *)HHI_MPEG_CLK_CNTL, - .bit_idx = 7, - .lock = &meson_clk_lock, +struct clk_regmap meson8b_clk81 = { + .data = &(struct clk_regmap_gate_data){ + .offset = HHI_MPEG_CLK_CNTL, + .bit_idx = 7, + }, .hw.init = &(struct clk_init_data){ .name = "clk81", - .ops = &clk_gate_ops, + .ops = &clk_regmap_gate_ops, .parent_names = (const char *[]){ "mpeg_clk_div" }, .num_parents = 1, .flags = (CLK_SET_RATE_PARENT | CLK_IS_CRITICAL), @@ -617,7 +619,15 @@ static struct meson_clk_mpll *const meson8b_clk_mplls[] = { &meson8b_mpll2, }; -static struct clk_gate *const meson8b_clk_gates[] = { +static struct clk_mux *const meson8b_clk_muxes[] = { + &meson8b_mpeg_clk_sel, +}; + +static struct clk_divider *const meson8b_clk_dividers[] = { + &meson8b_mpeg_clk_div, +}; + +static struct clk_regmap *const meson8b_clk_regmaps[] = { &meson8b_clk81, &meson8b_ddr, &meson8b_dos, @@ -698,14 +708,6 @@ static struct clk_gate *const meson8b_clk_gates[] = { &meson8b_ao_iface, }; -static struct clk_mux *const meson8b_clk_muxes[] = { - &meson8b_mpeg_clk_sel, -}; - -static struct clk_divider *const meson8b_clk_dividers[] = { - &meson8b_mpeg_clk_div, -}; - static const struct meson8b_clk_reset_line { u32 reg; u8 bit_idx; @@ -837,11 +839,6 @@ static int meson8b_clkc_probe(struct platform_device *pdev) /* Populate the base address for CPU clk */ meson8b_cpu_clk.base = clk_base; - /* Populate base address for gates */ - for (i = 0; i < ARRAY_SIZE(meson8b_clk_gates); i++) - meson8b_clk_gates[i]->reg = clk_base + - (u32)meson8b_clk_gates[i]->reg; - /* Populate base address for muxes */ for (i = 0; i < ARRAY_SIZE(meson8b_clk_muxes); i++) meson8b_clk_muxes[i]->reg = clk_base + @@ -852,6 +849,10 @@ static int meson8b_clkc_probe(struct platform_device *pdev) meson8b_clk_dividers[i]->reg = clk_base + (u32)meson8b_clk_dividers[i]->reg; + /* Populate regmap for the regmap backed clocks */ + for (i = 0; i < ARRAY_SIZE(meson8b_clk_regmaps); i++) + meson8b_clk_regmaps[i]->map = map; + /* * register all clks * CLKID_UNUSED = 0, so skip it and start with CLKID_XTAL = 1 -- cgit v1.2.3 From f06ddd2852b3f45cf37e2abd6b0de4f9cec80f0f Mon Sep 17 00:00:00 2001 From: Jerome Brunet Date: Mon, 12 Feb 2018 15:58:37 +0100 Subject: clk: meson: migrate dividers to clk_regmap Move meson8b, gxbb and axg clocks using clk_divider to clk_regmap Signed-off-by: Jerome Brunet Signed-off-by: Neil Armstrong --- drivers/clk/meson/axg.c | 61 ++++++------- drivers/clk/meson/gxbb.c | 217 ++++++++++++++++++++++---------------------- drivers/clk/meson/meson8b.c | 23 ++--- 3 files changed, 142 insertions(+), 159 deletions(-) diff --git a/drivers/clk/meson/axg.c b/drivers/clk/meson/axg.c index ed14f6ea7b07..f8b8ff2eba6c 100644 --- a/drivers/clk/meson/axg.c +++ b/drivers/clk/meson/axg.c @@ -433,14 +433,15 @@ static struct clk_mux axg_mpeg_clk_sel = { }, }; -static struct clk_divider axg_mpeg_clk_div = { - .reg = (void *)HHI_MPEG_CLK_CNTL, - .shift = 0, - .width = 7, - .lock = &meson_clk_lock, +static struct clk_regmap axg_mpeg_clk_div = { + .data = &(struct clk_regmap_div_data){ + .offset = HHI_MPEG_CLK_CNTL, + .shift = 0, + .width = 7, + }, .hw.init = &(struct clk_init_data){ .name = "mpeg_clk_div", - .ops = &clk_divider_ops, + .ops = &clk_regmap_divider_ops, .parent_names = (const char *[]){ "mpeg_clk_sel" }, .num_parents = 1, .flags = CLK_SET_RATE_PARENT, @@ -487,15 +488,16 @@ static struct clk_mux axg_sd_emmc_b_clk0_sel = { }, }; -static struct clk_divider axg_sd_emmc_b_clk0_div = { - .reg = (void *)HHI_SD_EMMC_CLK_CNTL, - .shift = 16, - .width = 7, - .lock = &meson_clk_lock, - .flags = CLK_DIVIDER_ROUND_CLOSEST, +static struct clk_regmap axg_sd_emmc_b_clk0_div = { + .data = &(struct clk_regmap_div_data){ + .offset = HHI_SD_EMMC_CLK_CNTL, + .shift = 16, + .width = 7, + .flags = CLK_DIVIDER_ROUND_CLOSEST, + }, .hw.init = &(struct clk_init_data) { .name = "sd_emmc_b_clk0_div", - .ops = &clk_divider_ops, + .ops = &clk_regmap_divider_ops, .parent_names = (const char *[]){ "sd_emmc_b_clk0_sel" }, .num_parents = 1, .flags = CLK_SET_RATE_PARENT, @@ -531,15 +533,16 @@ static struct clk_mux axg_sd_emmc_c_clk0_sel = { }, }; -static struct clk_divider axg_sd_emmc_c_clk0_div = { - .reg = (void *)HHI_NAND_CLK_CNTL, - .shift = 0, - .width = 7, - .lock = &meson_clk_lock, - .flags = CLK_DIVIDER_ROUND_CLOSEST, +static struct clk_regmap axg_sd_emmc_c_clk0_div = { + .data = &(struct clk_regmap_div_data){ + .offset = HHI_NAND_CLK_CNTL, + .shift = 0, + .width = 7, + .flags = CLK_DIVIDER_ROUND_CLOSEST, + }, .hw.init = &(struct clk_init_data) { .name = "sd_emmc_c_clk0_div", - .ops = &clk_divider_ops, + .ops = &clk_regmap_divider_ops, .parent_names = (const char *[]){ "sd_emmc_c_clk0_sel" }, .num_parents = 1, .flags = CLK_SET_RATE_PARENT, @@ -706,12 +709,6 @@ static struct clk_mux *const axg_clk_muxes[] = { &axg_sd_emmc_c_clk0_sel, }; -static struct clk_divider *const axg_clk_dividers[] = { - &axg_mpeg_clk_div, - &axg_sd_emmc_b_clk0_div, - &axg_sd_emmc_c_clk0_div, -}; - static struct clk_regmap *const axg_clk_regmaps[] = { &axg_clk81, &axg_ddr, @@ -760,6 +757,9 @@ static struct clk_regmap *const axg_clk_regmaps[] = { &axg_ao_i2c, &axg_sd_emmc_b_clk0, &axg_sd_emmc_c_clk0, + &axg_mpeg_clk_div, + &axg_sd_emmc_b_clk0_div, + &axg_sd_emmc_c_clk0_div, }; struct clkc_data { @@ -769,8 +769,6 @@ struct clkc_data { unsigned int clk_plls_count; struct clk_mux *const *clk_muxes; unsigned int clk_muxes_count; - struct clk_divider *const *clk_dividers; - unsigned int clk_dividers_count; struct clk_hw_onecell_data *hw_onecell_data; }; @@ -781,8 +779,6 @@ static const struct clkc_data axg_clkc_data = { .clk_plls_count = ARRAY_SIZE(axg_clk_plls), .clk_muxes = axg_clk_muxes, .clk_muxes_count = ARRAY_SIZE(axg_clk_muxes), - .clk_dividers = axg_clk_dividers, - .clk_dividers_count = ARRAY_SIZE(axg_clk_dividers), .hw_onecell_data = &axg_hw_onecell_data, }; @@ -838,11 +834,6 @@ static int axg_clkc_probe(struct platform_device *pdev) clkc_data->clk_muxes[i]->reg = clk_base + (u64)clkc_data->clk_muxes[i]->reg; - /* Populate base address for dividers */ - for (i = 0; i < clkc_data->clk_dividers_count; i++) - clkc_data->clk_dividers[i]->reg = clk_base + - (u64)clkc_data->clk_dividers[i]->reg; - /* Populate regmap for the regmap backed clocks */ for (i = 0; i < ARRAY_SIZE(axg_clk_regmaps); i++) axg_clk_regmaps[i]->map = map; diff --git a/drivers/clk/meson/gxbb.c b/drivers/clk/meson/gxbb.c index ccbbebb6a69b..ec515dc71476 100644 --- a/drivers/clk/meson/gxbb.c +++ b/drivers/clk/meson/gxbb.c @@ -604,14 +604,15 @@ static struct clk_mux gxbb_mpeg_clk_sel = { }, }; -static struct clk_divider gxbb_mpeg_clk_div = { - .reg = (void *)HHI_MPEG_CLK_CNTL, - .shift = 0, - .width = 7, - .lock = &meson_clk_lock, +static struct clk_regmap gxbb_mpeg_clk_div = { + .data = &(struct clk_regmap_div_data){ + .offset = HHI_MPEG_CLK_CNTL, + .shift = 0, + .width = 7, + }, .hw.init = &(struct clk_init_data){ .name = "mpeg_clk_div", - .ops = &clk_divider_ops, + .ops = &clk_regmap_divider_ops, .parent_names = (const char *[]){ "mpeg_clk_sel" }, .num_parents = 1, .flags = (CLK_SET_RATE_PARENT | CLK_IGNORE_UNUSED), @@ -647,14 +648,15 @@ static struct clk_mux gxbb_sar_adc_clk_sel = { }, }; -static struct clk_divider gxbb_sar_adc_clk_div = { - .reg = (void *)HHI_SAR_CLK_CNTL, - .shift = 0, - .width = 8, - .lock = &meson_clk_lock, +static struct clk_regmap gxbb_sar_adc_clk_div = { + .data = &(struct clk_regmap_div_data){ + .offset = HHI_SAR_CLK_CNTL, + .shift = 0, + .width = 8, + }, .hw.init = &(struct clk_init_data){ .name = "sar_adc_clk_div", - .ops = &clk_divider_ops, + .ops = &clk_regmap_divider_ops, .parent_names = (const char *[]){ "sar_adc_clk_sel" }, .num_parents = 1, }, @@ -705,14 +707,15 @@ static struct clk_mux gxbb_mali_0_sel = { }, }; -static struct clk_divider gxbb_mali_0_div = { - .reg = (void *)HHI_MALI_CLK_CNTL, - .shift = 0, - .width = 7, - .lock = &meson_clk_lock, +static struct clk_regmap gxbb_mali_0_div = { + .data = &(struct clk_regmap_div_data){ + .offset = HHI_MALI_CLK_CNTL, + .shift = 0, + .width = 7, + }, .hw.init = &(struct clk_init_data){ .name = "mali_0_div", - .ops = &clk_divider_ops, + .ops = &clk_regmap_divider_ops, .parent_names = (const char *[]){ "mali_0_sel" }, .num_parents = 1, .flags = CLK_SET_RATE_NO_REPARENT, @@ -753,14 +756,15 @@ static struct clk_mux gxbb_mali_1_sel = { }, }; -static struct clk_divider gxbb_mali_1_div = { - .reg = (void *)HHI_MALI_CLK_CNTL, - .shift = 16, - .width = 7, - .lock = &meson_clk_lock, +static struct clk_regmap gxbb_mali_1_div = { + .data = &(struct clk_regmap_div_data){ + .offset = HHI_MALI_CLK_CNTL, + .shift = 16, + .width = 7, + }, .hw.init = &(struct clk_init_data){ .name = "mali_1_div", - .ops = &clk_divider_ops, + .ops = &clk_regmap_divider_ops, .parent_names = (const char *[]){ "mali_1_sel" }, .num_parents = 1, .flags = CLK_SET_RATE_NO_REPARENT, @@ -864,15 +868,16 @@ static struct clk_mux gxbb_cts_mclk_i958_sel = { }, }; -static struct clk_divider gxbb_cts_mclk_i958_div = { - .reg = (void *)HHI_AUD_CLK_CNTL2, - .shift = 16, - .width = 8, - .lock = &meson_clk_lock, - .flags = CLK_DIVIDER_ROUND_CLOSEST, +static struct clk_regmap gxbb_cts_mclk_i958_div = { + .data = &(struct clk_regmap_div_data){ + .offset = HHI_AUD_CLK_CNTL2, + .shift = 16, + .width = 8, + .flags = CLK_DIVIDER_ROUND_CLOSEST, + }, .hw.init = &(struct clk_init_data) { .name = "cts_mclk_i958_div", - .ops = &clk_divider_ops, + .ops = &clk_regmap_divider_ops, .parent_names = (const char *[]){ "cts_mclk_i958_sel" }, .num_parents = 1, .flags = CLK_SET_RATE_PARENT, @@ -911,14 +916,15 @@ static struct clk_mux gxbb_cts_i958 = { }, }; -static struct clk_divider gxbb_32k_clk_div = { - .reg = (void *)HHI_32K_CLK_CNTL, - .shift = 0, - .width = 14, - .lock = &meson_clk_lock, +static struct clk_regmap gxbb_32k_clk_div = { + .data = &(struct clk_regmap_div_data){ + .offset = HHI_32K_CLK_CNTL, + .shift = 0, + .width = 14, + }, .hw.init = &(struct clk_init_data){ .name = "32k_clk_div", - .ops = &clk_divider_ops, + .ops = &clk_regmap_divider_ops, .parent_names = (const char *[]){ "32k_clk_sel" }, .num_parents = 1, .flags = CLK_SET_RATE_PARENT | CLK_DIVIDER_ROUND_CLOSEST, @@ -983,15 +989,16 @@ static struct clk_mux gxbb_sd_emmc_a_clk0_sel = { }, }; -static struct clk_divider gxbb_sd_emmc_a_clk0_div = { - .reg = (void *)HHI_SD_EMMC_CLK_CNTL, - .shift = 0, - .width = 7, - .lock = &meson_clk_lock, - .flags = CLK_DIVIDER_ROUND_CLOSEST, +static struct clk_regmap gxbb_sd_emmc_a_clk0_div = { + .data = &(struct clk_regmap_div_data){ + .offset = HHI_SD_EMMC_CLK_CNTL, + .shift = 0, + .width = 7, + .flags = CLK_DIVIDER_ROUND_CLOSEST, + }, .hw.init = &(struct clk_init_data) { .name = "sd_emmc_a_clk0_div", - .ops = &clk_divider_ops, + .ops = &clk_regmap_divider_ops, .parent_names = (const char *[]){ "sd_emmc_a_clk0_sel" }, .num_parents = 1, .flags = CLK_SET_RATE_PARENT, @@ -1027,15 +1034,16 @@ static struct clk_mux gxbb_sd_emmc_b_clk0_sel = { }, }; -static struct clk_divider gxbb_sd_emmc_b_clk0_div = { - .reg = (void *)HHI_SD_EMMC_CLK_CNTL, - .shift = 16, - .width = 7, - .lock = &meson_clk_lock, - .flags = CLK_DIVIDER_ROUND_CLOSEST, +static struct clk_regmap gxbb_sd_emmc_b_clk0_div = { + .data = &(struct clk_regmap_div_data){ + .offset = HHI_SD_EMMC_CLK_CNTL, + .shift = 16, + .width = 7, + .flags = CLK_DIVIDER_ROUND_CLOSEST, + }, .hw.init = &(struct clk_init_data) { .name = "sd_emmc_b_clk0_div", - .ops = &clk_divider_ops, + .ops = &clk_regmap_divider_ops, .parent_names = (const char *[]){ "sd_emmc_b_clk0_sel" }, .num_parents = 1, .flags = CLK_SET_RATE_PARENT, @@ -1071,15 +1079,16 @@ static struct clk_mux gxbb_sd_emmc_c_clk0_sel = { }, }; -static struct clk_divider gxbb_sd_emmc_c_clk0_div = { - .reg = (void *)HHI_NAND_CLK_CNTL, - .shift = 0, - .width = 7, - .lock = &meson_clk_lock, - .flags = CLK_DIVIDER_ROUND_CLOSEST, +static struct clk_regmap gxbb_sd_emmc_c_clk0_div = { + .data = &(struct clk_regmap_div_data){ + .offset = HHI_NAND_CLK_CNTL, + .shift = 0, + .width = 7, + .flags = CLK_DIVIDER_ROUND_CLOSEST, + }, .hw.init = &(struct clk_init_data) { .name = "sd_emmc_c_clk0_div", - .ops = &clk_divider_ops, + .ops = &clk_regmap_divider_ops, .parent_names = (const char *[]){ "sd_emmc_c_clk0_sel" }, .num_parents = 1, .flags = CLK_SET_RATE_PARENT, @@ -1126,14 +1135,15 @@ static struct clk_mux gxbb_vpu_0_sel = { }, }; -static struct clk_divider gxbb_vpu_0_div = { - .reg = (void *)HHI_VPU_CLK_CNTL, - .shift = 0, - .width = 7, - .lock = &meson_clk_lock, +static struct clk_regmap gxbb_vpu_0_div = { + .data = &(struct clk_regmap_div_data){ + .offset = HHI_VPU_CLK_CNTL, + .shift = 0, + .width = 7, + }, .hw.init = &(struct clk_init_data){ .name = "vpu_0_div", - .ops = &clk_divider_ops, + .ops = &clk_regmap_divider_ops, .parent_names = (const char *[]){ "vpu_0_sel" }, .num_parents = 1, .flags = CLK_SET_RATE_PARENT, @@ -1173,14 +1183,15 @@ static struct clk_mux gxbb_vpu_1_sel = { }, }; -static struct clk_divider gxbb_vpu_1_div = { - .reg = (void *)HHI_VPU_CLK_CNTL, - .shift = 16, - .width = 7, - .lock = &meson_clk_lock, +static struct clk_regmap gxbb_vpu_1_div = { + .data = &(struct clk_regmap_div_data){ + .offset = HHI_VPU_CLK_CNTL, + .shift = 16, + .width = 7, + }, .hw.init = &(struct clk_init_data){ .name = "vpu_1_div", - .ops = &clk_divider_ops, + .ops = &clk_regmap_divider_ops, .parent_names = (const char *[]){ "vpu_1_sel" }, .num_parents = 1, .flags = CLK_SET_RATE_PARENT, @@ -1245,14 +1256,15 @@ static struct clk_mux gxbb_vapb_0_sel = { }, }; -static struct clk_divider gxbb_vapb_0_div = { - .reg = (void *)HHI_VAPBCLK_CNTL, - .shift = 0, - .width = 7, - .lock = &meson_clk_lock, +static struct clk_regmap gxbb_vapb_0_div = { + .data = &(struct clk_regmap_div_data){ + .offset = HHI_VAPBCLK_CNTL, + .shift = 0, + .width = 7, + }, .hw.init = &(struct clk_init_data){ .name = "vapb_0_div", - .ops = &clk_divider_ops, + .ops = &clk_regmap_divider_ops, .parent_names = (const char *[]){ "vapb_0_sel" }, .num_parents = 1, .flags = CLK_SET_RATE_PARENT, @@ -1292,14 +1304,15 @@ static struct clk_mux gxbb_vapb_1_sel = { }, }; -static struct clk_divider gxbb_vapb_1_div = { - .reg = (void *)HHI_VAPBCLK_CNTL, - .shift = 16, - .width = 7, - .lock = &meson_clk_lock, +static struct clk_regmap gxbb_vapb_1_div = { + .data = &(struct clk_regmap_div_data){ + .offset = HHI_VAPBCLK_CNTL, + .shift = 16, + .width = 7, + }, .hw.init = &(struct clk_init_data){ .name = "vapb_1_div", - .ops = &clk_divider_ops, + .ops = &clk_regmap_divider_ops, .parent_names = (const char *[]){ "vapb_1_sel" }, .num_parents = 1, .flags = CLK_SET_RATE_PARENT, @@ -1781,22 +1794,6 @@ static struct clk_mux *const gxbb_clk_muxes[] = { &gxbb_vapb_sel, }; -static struct clk_divider *const gxbb_clk_dividers[] = { - &gxbb_mpeg_clk_div, - &gxbb_sar_adc_clk_div, - &gxbb_mali_0_div, - &gxbb_mali_1_div, - &gxbb_cts_mclk_i958_div, - &gxbb_32k_clk_div, - &gxbb_sd_emmc_a_clk0_div, - &gxbb_sd_emmc_b_clk0_div, - &gxbb_sd_emmc_c_clk0_div, - &gxbb_vpu_0_div, - &gxbb_vpu_1_div, - &gxbb_vapb_0_div, - &gxbb_vapb_1_div, -}; - static struct meson_clk_audio_divider *const gxbb_audio_dividers[] = { &gxbb_cts_amclk_div, }; @@ -1898,6 +1895,19 @@ static struct clk_regmap *const gx_clk_regmaps[] = { &gxbb_vapb_0, &gxbb_vapb_1, &gxbb_vapb, + &gxbb_mpeg_clk_div, + &gxbb_sar_adc_clk_div, + &gxbb_mali_0_div, + &gxbb_mali_1_div, + &gxbb_cts_mclk_i958_div, + &gxbb_32k_clk_div, + &gxbb_sd_emmc_a_clk0_div, + &gxbb_sd_emmc_b_clk0_div, + &gxbb_sd_emmc_c_clk0_div, + &gxbb_vpu_0_div, + &gxbb_vpu_1_div, + &gxbb_vapb_0_div, + &gxbb_vapb_1_div, }; struct clkc_data { @@ -1907,8 +1917,6 @@ struct clkc_data { unsigned int clk_plls_count; struct clk_mux *const *clk_muxes; unsigned int clk_muxes_count; - struct clk_divider *const *clk_dividers; - unsigned int clk_dividers_count; struct meson_clk_audio_divider *const *clk_audio_dividers; unsigned int clk_audio_dividers_count; struct clk_hw_onecell_data *hw_onecell_data; @@ -1921,8 +1929,6 @@ static const struct clkc_data gxbb_clkc_data = { .clk_plls_count = ARRAY_SIZE(gxbb_clk_plls), .clk_muxes = gxbb_clk_muxes, .clk_muxes_count = ARRAY_SIZE(gxbb_clk_muxes), - .clk_dividers = gxbb_clk_dividers, - .clk_dividers_count = ARRAY_SIZE(gxbb_clk_dividers), .clk_audio_dividers = gxbb_audio_dividers, .clk_audio_dividers_count = ARRAY_SIZE(gxbb_audio_dividers), .hw_onecell_data = &gxbb_hw_onecell_data, @@ -1935,8 +1941,6 @@ static const struct clkc_data gxl_clkc_data = { .clk_plls_count = ARRAY_SIZE(gxl_clk_plls), .clk_muxes = gxbb_clk_muxes, .clk_muxes_count = ARRAY_SIZE(gxbb_clk_muxes), - .clk_dividers = gxbb_clk_dividers, - .clk_dividers_count = ARRAY_SIZE(gxbb_clk_dividers), .clk_audio_dividers = gxbb_audio_dividers, .clk_audio_dividers_count = ARRAY_SIZE(gxbb_audio_dividers), .hw_onecell_data = &gxl_hw_onecell_data, @@ -1994,11 +1998,6 @@ static int gxbb_clkc_probe(struct platform_device *pdev) clkc_data->clk_muxes[i]->reg = clk_base + (u64)clkc_data->clk_muxes[i]->reg; - /* Populate base address for dividers */ - for (i = 0; i < clkc_data->clk_dividers_count; i++) - clkc_data->clk_dividers[i]->reg = clk_base + - (u64)clkc_data->clk_dividers[i]->reg; - /* Populate base address for the audio dividers */ for (i = 0; i < clkc_data->clk_audio_dividers_count; i++) clkc_data->clk_audio_dividers[i]->base = clk_base; diff --git a/drivers/clk/meson/meson8b.c b/drivers/clk/meson/meson8b.c index 835dbb1d2c9d..e9c5278072cd 100644 --- a/drivers/clk/meson/meson8b.c +++ b/drivers/clk/meson/meson8b.c @@ -393,14 +393,15 @@ struct clk_mux meson8b_mpeg_clk_sel = { }, }; -struct clk_divider meson8b_mpeg_clk_div = { - .reg = (void *)HHI_MPEG_CLK_CNTL, - .shift = 0, - .width = 7, - .lock = &meson_clk_lock, +struct clk_regmap meson8b_mpeg_clk_div = { + .data = &(struct clk_regmap_div_data){ + .offset = HHI_MPEG_CLK_CNTL, + .shift = 0, + .width = 7, + }, .hw.init = &(struct clk_init_data){ .name = "mpeg_clk_div", - .ops = &clk_divider_ops, + .ops = &clk_regmap_divider_ops, .parent_names = (const char *[]){ "mpeg_clk_sel" }, .num_parents = 1, .flags = (CLK_SET_RATE_PARENT | CLK_IGNORE_UNUSED), @@ -623,10 +624,6 @@ static struct clk_mux *const meson8b_clk_muxes[] = { &meson8b_mpeg_clk_sel, }; -static struct clk_divider *const meson8b_clk_dividers[] = { - &meson8b_mpeg_clk_div, -}; - static struct clk_regmap *const meson8b_clk_regmaps[] = { &meson8b_clk81, &meson8b_ddr, @@ -706,6 +703,7 @@ static struct clk_regmap *const meson8b_clk_regmaps[] = { &meson8b_ao_ahb_sram, &meson8b_ao_ahb_bus, &meson8b_ao_iface, + &meson8b_mpeg_clk_div, }; static const struct meson8b_clk_reset_line { @@ -844,11 +842,6 @@ static int meson8b_clkc_probe(struct platform_device *pdev) meson8b_clk_muxes[i]->reg = clk_base + (u32)meson8b_clk_muxes[i]->reg; - /* Populate base address for dividers */ - for (i = 0; i < ARRAY_SIZE(meson8b_clk_dividers); i++) - meson8b_clk_dividers[i]->reg = clk_base + - (u32)meson8b_clk_dividers[i]->reg; - /* Populate regmap for the regmap backed clocks */ for (i = 0; i < ARRAY_SIZE(meson8b_clk_regmaps); i++) meson8b_clk_regmaps[i]->map = map; -- cgit v1.2.3 From 2513a28c108b0584989927195ba5230e296762ec Mon Sep 17 00:00:00 2001 From: Jerome Brunet Date: Mon, 12 Feb 2018 15:58:38 +0100 Subject: clk: meson: migrate muxes to clk_regmap Move meson8b, gxbb and axg clocks using clk_mux to clk_regmap Also remove a few useless tables in the process Signed-off-by: Jerome Brunet Signed-off-by: Neil Armstrong --- drivers/clk/meson/axg.c | 60 ++++----- drivers/clk/meson/gxbb.c | 310 +++++++++++++++++++++----------------------- drivers/clk/meson/meson8b.c | 27 ++-- 3 files changed, 184 insertions(+), 213 deletions(-) diff --git a/drivers/clk/meson/axg.c b/drivers/clk/meson/axg.c index f8b8ff2eba6c..9f0c36e12cb8 100644 --- a/drivers/clk/meson/axg.c +++ b/drivers/clk/meson/axg.c @@ -418,16 +418,16 @@ static const char * const clk81_parent_names[] = { "fclk_div3", "fclk_div5" }; -static struct clk_mux axg_mpeg_clk_sel = { - .reg = (void *)HHI_MPEG_CLK_CNTL, - .mask = 0x7, - .shift = 12, - .flags = CLK_MUX_READ_ONLY, - .table = mux_table_clk81, - .lock = &meson_clk_lock, +static struct clk_regmap axg_mpeg_clk_sel = { + .data = &(struct clk_regmap_mux_data){ + .offset = HHI_MPEG_CLK_CNTL, + .mask = 0x7, + .shift = 12, + .table = mux_table_clk81, + }, .hw.init = &(struct clk_init_data){ .name = "mpeg_clk_sel", - .ops = &clk_mux_ro_ops, + .ops = &clk_regmap_mux_ro_ops, .parent_names = clk81_parent_names, .num_parents = ARRAY_SIZE(clk81_parent_names), }, @@ -474,14 +474,15 @@ static const char * const axg_sd_emmc_clk0_parent_names[] = { }; /* SDcard clock */ -static struct clk_mux axg_sd_emmc_b_clk0_sel = { - .reg = (void *)HHI_SD_EMMC_CLK_CNTL, - .mask = 0x7, - .shift = 25, - .lock = &meson_clk_lock, +static struct clk_regmap axg_sd_emmc_b_clk0_sel = { + .data = &(struct clk_regmap_mux_data){ + .offset = HHI_SD_EMMC_CLK_CNTL, + .mask = 0x7, + .shift = 25, + }, .hw.init = &(struct clk_init_data) { .name = "sd_emmc_b_clk0_sel", - .ops = &clk_mux_ops, + .ops = &clk_regmap_mux_ops, .parent_names = axg_sd_emmc_clk0_parent_names, .num_parents = ARRAY_SIZE(axg_sd_emmc_clk0_parent_names), .flags = CLK_SET_RATE_PARENT, @@ -519,14 +520,15 @@ static struct clk_regmap axg_sd_emmc_b_clk0 = { }; /* EMMC/NAND clock */ -static struct clk_mux axg_sd_emmc_c_clk0_sel = { - .reg = (void *)HHI_NAND_CLK_CNTL, - .mask = 0x7, - .shift = 9, - .lock = &meson_clk_lock, +static struct clk_regmap axg_sd_emmc_c_clk0_sel = { + .data = &(struct clk_regmap_mux_data){ + .offset = HHI_NAND_CLK_CNTL, + .mask = 0x7, + .shift = 9, + }, .hw.init = &(struct clk_init_data) { .name = "sd_emmc_c_clk0_sel", - .ops = &clk_mux_ops, + .ops = &clk_regmap_mux_ops, .parent_names = axg_sd_emmc_clk0_parent_names, .num_parents = ARRAY_SIZE(axg_sd_emmc_clk0_parent_names), .flags = CLK_SET_RATE_PARENT, @@ -703,12 +705,6 @@ static struct meson_clk_mpll *const axg_clk_mplls[] = { &axg_mpll3, }; -static struct clk_mux *const axg_clk_muxes[] = { - &axg_mpeg_clk_sel, - &axg_sd_emmc_b_clk0_sel, - &axg_sd_emmc_c_clk0_sel, -}; - static struct clk_regmap *const axg_clk_regmaps[] = { &axg_clk81, &axg_ddr, @@ -760,6 +756,9 @@ static struct clk_regmap *const axg_clk_regmaps[] = { &axg_mpeg_clk_div, &axg_sd_emmc_b_clk0_div, &axg_sd_emmc_c_clk0_div, + &axg_mpeg_clk_sel, + &axg_sd_emmc_b_clk0_sel, + &axg_sd_emmc_c_clk0_sel, }; struct clkc_data { @@ -767,8 +766,6 @@ struct clkc_data { unsigned int clk_mplls_count; struct meson_clk_pll *const *clk_plls; unsigned int clk_plls_count; - struct clk_mux *const *clk_muxes; - unsigned int clk_muxes_count; struct clk_hw_onecell_data *hw_onecell_data; }; @@ -777,8 +774,6 @@ static const struct clkc_data axg_clkc_data = { .clk_mplls_count = ARRAY_SIZE(axg_clk_mplls), .clk_plls = axg_clk_plls, .clk_plls_count = ARRAY_SIZE(axg_clk_plls), - .clk_muxes = axg_clk_muxes, - .clk_muxes_count = ARRAY_SIZE(axg_clk_muxes), .hw_onecell_data = &axg_hw_onecell_data, }; @@ -829,11 +824,6 @@ static int axg_clkc_probe(struct platform_device *pdev) for (i = 0; i < clkc_data->clk_mplls_count; i++) clkc_data->clk_mplls[i]->base = clk_base; - /* Populate base address for muxes */ - for (i = 0; i < clkc_data->clk_muxes_count; i++) - clkc_data->clk_muxes[i]->reg = clk_base + - (u64)clkc_data->clk_muxes[i]->reg; - /* Populate regmap for the regmap backed clocks */ for (i = 0; i < ARRAY_SIZE(axg_clk_regmaps); i++) axg_clk_regmaps[i]->map = map; diff --git a/drivers/clk/meson/gxbb.c b/drivers/clk/meson/gxbb.c index ec515dc71476..d9f426265774 100644 --- a/drivers/clk/meson/gxbb.c +++ b/drivers/clk/meson/gxbb.c @@ -583,16 +583,16 @@ static const char * const clk81_parent_names[] = { "fclk_div3", "fclk_div5" }; -static struct clk_mux gxbb_mpeg_clk_sel = { - .reg = (void *)HHI_MPEG_CLK_CNTL, - .mask = 0x7, - .shift = 12, - .flags = CLK_MUX_READ_ONLY, - .table = mux_table_clk81, - .lock = &meson_clk_lock, +static struct clk_regmap gxbb_mpeg_clk_sel = { + .data = &(struct clk_regmap_mux_data){ + .offset = HHI_MPEG_CLK_CNTL, + .mask = 0x7, + .shift = 12, + .table = mux_table_clk81, + }, .hw.init = &(struct clk_init_data){ .name = "mpeg_clk_sel", - .ops = &clk_mux_ro_ops, + .ops = &clk_regmap_mux_ro_ops, /* * bits 14:12 selects from 8 possible parents: * xtal, 1'b0 (wtf), fclk_div7, mpll_clkout1, mpll_clkout2, @@ -634,14 +634,15 @@ static struct clk_regmap gxbb_clk81 = { }, }; -static struct clk_mux gxbb_sar_adc_clk_sel = { - .reg = (void *)HHI_SAR_CLK_CNTL, - .mask = 0x3, - .shift = 9, - .lock = &meson_clk_lock, +static struct clk_regmap gxbb_sar_adc_clk_sel = { + .data = &(struct clk_regmap_mux_data){ + .offset = HHI_SAR_CLK_CNTL, + .mask = 0x3, + .shift = 9, + }, .hw.init = &(struct clk_init_data){ .name = "sar_adc_clk_sel", - .ops = &clk_mux_ops, + .ops = &clk_regmap_mux_ops, /* NOTE: The datasheet doesn't list the parents for bit 10 */ .parent_names = (const char *[]){ "xtal", "clk81", }, .num_parents = 2, @@ -681,21 +682,20 @@ static struct clk_regmap gxbb_sar_adc_clk = { * muxed by a glitch-free switch. */ -static u32 mux_table_mali_0_1[] = {0, 1, 2, 3, 4, 5, 6, 7}; static const char * const gxbb_mali_0_1_parent_names[] = { "xtal", "gp0_pll", "mpll2", "mpll1", "fclk_div7", "fclk_div4", "fclk_div3", "fclk_div5" }; -static struct clk_mux gxbb_mali_0_sel = { - .reg = (void *)HHI_MALI_CLK_CNTL, - .mask = 0x7, - .shift = 9, - .table = mux_table_mali_0_1, - .lock = &meson_clk_lock, +static struct clk_regmap gxbb_mali_0_sel = { + .data = &(struct clk_regmap_mux_data){ + .offset = HHI_MALI_CLK_CNTL, + .mask = 0x7, + .shift = 9, + }, .hw.init = &(struct clk_init_data){ .name = "mali_0_sel", - .ops = &clk_mux_ops, + .ops = &clk_regmap_mux_ops, /* * bits 10:9 selects from 8 possible parents: * xtal, gp0_pll, mpll2, mpll1, fclk_div7, @@ -736,15 +736,15 @@ static struct clk_regmap gxbb_mali_0 = { }, }; -static struct clk_mux gxbb_mali_1_sel = { - .reg = (void *)HHI_MALI_CLK_CNTL, - .mask = 0x7, - .shift = 25, - .table = mux_table_mali_0_1, - .lock = &meson_clk_lock, +static struct clk_regmap gxbb_mali_1_sel = { + .data = &(struct clk_regmap_mux_data){ + .offset = HHI_MALI_CLK_CNTL, + .mask = 0x7, + .shift = 25, + }, .hw.init = &(struct clk_init_data){ .name = "mali_1_sel", - .ops = &clk_mux_ops, + .ops = &clk_regmap_mux_ops, /* * bits 10:9 selects from 8 possible parents: * xtal, gp0_pll, mpll2, mpll1, fclk_div7, @@ -785,36 +785,35 @@ static struct clk_regmap gxbb_mali_1 = { }, }; -static u32 mux_table_mali[] = {0, 1}; static const char * const gxbb_mali_parent_names[] = { "mali_0", "mali_1" }; -static struct clk_mux gxbb_mali = { - .reg = (void *)HHI_MALI_CLK_CNTL, - .mask = 1, - .shift = 31, - .table = mux_table_mali, - .lock = &meson_clk_lock, +static struct clk_regmap gxbb_mali = { + .data = &(struct clk_regmap_mux_data){ + .offset = HHI_MALI_CLK_CNTL, + .mask = 1, + .shift = 31, + }, .hw.init = &(struct clk_init_data){ .name = "mali", - .ops = &clk_mux_ops, + .ops = &clk_regmap_mux_ops, .parent_names = gxbb_mali_parent_names, .num_parents = 2, .flags = CLK_SET_RATE_NO_REPARENT, }, }; -static struct clk_mux gxbb_cts_amclk_sel = { - .reg = (void *) HHI_AUD_CLK_CNTL, - .mask = 0x3, - .shift = 9, - /* Default parent unknown (register reset value: 0) */ - .table = (u32[]){ 1, 2, 3 }, - .lock = &meson_clk_lock, - .hw.init = &(struct clk_init_data){ +static struct clk_regmap gxbb_cts_amclk_sel = { + .data = &(struct clk_regmap_mux_data){ + .offset = HHI_AUD_CLK_CNTL, + .mask = 0x3, + .shift = 9, + .table = (u32[]){ 1, 2, 3 }, + }, + .hw.init = &(struct clk_init_data){ .name = "cts_amclk_sel", - .ops = &clk_mux_ops, + .ops = &clk_regmap_mux_ops, .parent_names = (const char *[]){ "mpll0", "mpll1", "mpll2" }, .num_parents = 3, .flags = CLK_SET_RATE_PARENT, @@ -852,16 +851,16 @@ static struct clk_regmap gxbb_cts_amclk = { }, }; -static struct clk_mux gxbb_cts_mclk_i958_sel = { - .reg = (void *)HHI_AUD_CLK_CNTL2, - .mask = 0x3, - .shift = 25, - /* Default parent unknown (register reset value: 0) */ - .table = (u32[]){ 1, 2, 3 }, - .lock = &meson_clk_lock, +static struct clk_regmap gxbb_cts_mclk_i958_sel = { + .data = &(struct clk_regmap_mux_data){ + .offset = HHI_AUD_CLK_CNTL2, + .mask = 0x3, + .shift = 25, + .table = (u32[]){ 1, 2, 3 }, + }, .hw.init = &(struct clk_init_data) { .name = "cts_mclk_i958_sel", - .ops = &clk_mux_ops, + .ops = &clk_regmap_mux_ops, .parent_names = (const char *[]){ "mpll0", "mpll1", "mpll2" }, .num_parents = 3, .flags = CLK_SET_RATE_PARENT, @@ -898,14 +897,15 @@ static struct clk_regmap gxbb_cts_mclk_i958 = { }, }; -static struct clk_mux gxbb_cts_i958 = { - .reg = (void *)HHI_AUD_CLK_CNTL2, - .mask = 0x1, - .shift = 27, - .lock = &meson_clk_lock, - .hw.init = &(struct clk_init_data){ +static struct clk_regmap gxbb_cts_i958 = { + .data = &(struct clk_regmap_mux_data){ + .offset = HHI_AUD_CLK_CNTL2, + .mask = 0x1, + .shift = 27, + }, + .hw.init = &(struct clk_init_data){ .name = "cts_i958", - .ops = &clk_mux_ops, + .ops = &clk_regmap_mux_ops, .parent_names = (const char *[]){ "cts_amclk", "cts_mclk_i958" }, .num_parents = 2, /* @@ -949,14 +949,15 @@ static const char * const gxbb_32k_clk_parent_names[] = { "xtal", "cts_slow_oscin", "fclk_div3", "fclk_div5" }; -static struct clk_mux gxbb_32k_clk_sel = { - .reg = (void *)HHI_32K_CLK_CNTL, - .mask = 0x3, - .shift = 16, - .lock = &meson_clk_lock, - .hw.init = &(struct clk_init_data){ +static struct clk_regmap gxbb_32k_clk_sel = { + .data = &(struct clk_regmap_mux_data){ + .offset = HHI_32K_CLK_CNTL, + .mask = 0x3, + .shift = 16, + }, + .hw.init = &(struct clk_init_data){ .name = "32k_clk_sel", - .ops = &clk_mux_ops, + .ops = &clk_regmap_mux_ops, .parent_names = gxbb_32k_clk_parent_names, .num_parents = 4, .flags = CLK_SET_RATE_PARENT, @@ -975,14 +976,15 @@ static const char * const gxbb_sd_emmc_clk0_parent_names[] = { }; /* SDIO clock */ -static struct clk_mux gxbb_sd_emmc_a_clk0_sel = { - .reg = (void *)HHI_SD_EMMC_CLK_CNTL, - .mask = 0x7, - .shift = 9, - .lock = &meson_clk_lock, +static struct clk_regmap gxbb_sd_emmc_a_clk0_sel = { + .data = &(struct clk_regmap_mux_data){ + .offset = HHI_SD_EMMC_CLK_CNTL, + .mask = 0x7, + .shift = 9, + }, .hw.init = &(struct clk_init_data) { .name = "sd_emmc_a_clk0_sel", - .ops = &clk_mux_ops, + .ops = &clk_regmap_mux_ops, .parent_names = gxbb_sd_emmc_clk0_parent_names, .num_parents = ARRAY_SIZE(gxbb_sd_emmc_clk0_parent_names), .flags = CLK_SET_RATE_PARENT, @@ -1020,14 +1022,15 @@ static struct clk_regmap gxbb_sd_emmc_a_clk0 = { }; /* SDcard clock */ -static struct clk_mux gxbb_sd_emmc_b_clk0_sel = { - .reg = (void *)HHI_SD_EMMC_CLK_CNTL, - .mask = 0x7, - .shift = 25, - .lock = &meson_clk_lock, +static struct clk_regmap gxbb_sd_emmc_b_clk0_sel = { + .data = &(struct clk_regmap_mux_data){ + .offset = HHI_SD_EMMC_CLK_CNTL, + .mask = 0x7, + .shift = 25, + }, .hw.init = &(struct clk_init_data) { .name = "sd_emmc_b_clk0_sel", - .ops = &clk_mux_ops, + .ops = &clk_regmap_mux_ops, .parent_names = gxbb_sd_emmc_clk0_parent_names, .num_parents = ARRAY_SIZE(gxbb_sd_emmc_clk0_parent_names), .flags = CLK_SET_RATE_PARENT, @@ -1065,14 +1068,15 @@ static struct clk_regmap gxbb_sd_emmc_b_clk0 = { }; /* EMMC/NAND clock */ -static struct clk_mux gxbb_sd_emmc_c_clk0_sel = { - .reg = (void *)HHI_NAND_CLK_CNTL, - .mask = 0x7, - .shift = 9, - .lock = &meson_clk_lock, +static struct clk_regmap gxbb_sd_emmc_c_clk0_sel = { + .data = &(struct clk_regmap_mux_data){ + .offset = HHI_NAND_CLK_CNTL, + .mask = 0x7, + .shift = 9, + }, .hw.init = &(struct clk_init_data) { .name = "sd_emmc_c_clk0_sel", - .ops = &clk_mux_ops, + .ops = &clk_regmap_mux_ops, .parent_names = gxbb_sd_emmc_clk0_parent_names, .num_parents = ARRAY_SIZE(gxbb_sd_emmc_clk0_parent_names), .flags = CLK_SET_RATE_PARENT, @@ -1111,20 +1115,19 @@ static struct clk_regmap gxbb_sd_emmc_c_clk0 = { /* VPU Clock */ -static u32 mux_table_vpu[] = {0, 1, 2, 3}; static const char * const gxbb_vpu_parent_names[] = { "fclk_div4", "fclk_div3", "fclk_div5", "fclk_div7" }; -static struct clk_mux gxbb_vpu_0_sel = { - .reg = (void *)HHI_VPU_CLK_CNTL, - .mask = 0x3, - .shift = 9, - .lock = &meson_clk_lock, - .table = mux_table_vpu, +static struct clk_regmap gxbb_vpu_0_sel = { + .data = &(struct clk_regmap_mux_data){ + .offset = HHI_VPU_CLK_CNTL, + .mask = 0x3, + .shift = 9, + }, .hw.init = &(struct clk_init_data){ .name = "vpu_0_sel", - .ops = &clk_mux_ops, + .ops = &clk_regmap_mux_ops, /* * bits 9:10 selects from 4 possible parents: * fclk_div4, fclk_div3, fclk_div5, fclk_div7, @@ -1164,15 +1167,15 @@ static struct clk_regmap gxbb_vpu_0 = { }, }; -static struct clk_mux gxbb_vpu_1_sel = { - .reg = (void *)HHI_VPU_CLK_CNTL, - .mask = 0x3, - .shift = 25, - .lock = &meson_clk_lock, - .table = mux_table_vpu, +static struct clk_regmap gxbb_vpu_1_sel = { + .data = &(struct clk_regmap_mux_data){ + .offset = HHI_VPU_CLK_CNTL, + .mask = 0x3, + .shift = 25, + }, .hw.init = &(struct clk_init_data){ .name = "vpu_1_sel", - .ops = &clk_mux_ops, + .ops = &clk_regmap_mux_ops, /* * bits 25:26 selects from 4 possible parents: * fclk_div4, fclk_div3, fclk_div5, fclk_div7, @@ -1212,14 +1215,15 @@ static struct clk_regmap gxbb_vpu_1 = { }, }; -static struct clk_mux gxbb_vpu = { - .reg = (void *)HHI_VPU_CLK_CNTL, - .mask = 1, - .shift = 31, - .lock = &meson_clk_lock, +static struct clk_regmap gxbb_vpu = { + .data = &(struct clk_regmap_mux_data){ + .offset = HHI_VPU_CLK_CNTL, + .mask = 1, + .shift = 31, + }, .hw.init = &(struct clk_init_data){ .name = "vpu", - .ops = &clk_mux_ops, + .ops = &clk_regmap_mux_ops, /* * bit 31 selects from 2 possible parents: * vpu_0 or vpu_1 @@ -1232,20 +1236,19 @@ static struct clk_mux gxbb_vpu = { /* VAPB Clock */ -static u32 mux_table_vapb[] = {0, 1, 2, 3}; static const char * const gxbb_vapb_parent_names[] = { "fclk_div4", "fclk_div3", "fclk_div5", "fclk_div7" }; -static struct clk_mux gxbb_vapb_0_sel = { - .reg = (void *)HHI_VAPBCLK_CNTL, - .mask = 0x3, - .shift = 9, - .lock = &meson_clk_lock, - .table = mux_table_vapb, +static struct clk_regmap gxbb_vapb_0_sel = { + .data = &(struct clk_regmap_mux_data){ + .offset = HHI_VAPBCLK_CNTL, + .mask = 0x3, + .shift = 9, + }, .hw.init = &(struct clk_init_data){ .name = "vapb_0_sel", - .ops = &clk_mux_ops, + .ops = &clk_regmap_mux_ops, /* * bits 9:10 selects from 4 possible parents: * fclk_div4, fclk_div3, fclk_div5, fclk_div7, @@ -1285,15 +1288,15 @@ static struct clk_regmap gxbb_vapb_0 = { }, }; -static struct clk_mux gxbb_vapb_1_sel = { - .reg = (void *)HHI_VAPBCLK_CNTL, - .mask = 0x3, - .shift = 25, - .lock = &meson_clk_lock, - .table = mux_table_vapb, +static struct clk_regmap gxbb_vapb_1_sel = { + .data = &(struct clk_regmap_mux_data){ + .offset = HHI_VAPBCLK_CNTL, + .mask = 0x3, + .shift = 25, + }, .hw.init = &(struct clk_init_data){ .name = "vapb_1_sel", - .ops = &clk_mux_ops, + .ops = &clk_regmap_mux_ops, /* * bits 25:26 selects from 4 possible parents: * fclk_div4, fclk_div3, fclk_div5, fclk_div7, @@ -1333,14 +1336,15 @@ static struct clk_regmap gxbb_vapb_1 = { }, }; -static struct clk_mux gxbb_vapb_sel = { - .reg = (void *)HHI_VAPBCLK_CNTL, - .mask = 1, - .shift = 31, - .lock = &meson_clk_lock, +static struct clk_regmap gxbb_vapb_sel = { + .data = &(struct clk_regmap_mux_data){ + .offset = HHI_VAPBCLK_CNTL, + .mask = 1, + .shift = 31, + }, .hw.init = &(struct clk_init_data){ .name = "vapb_sel", - .ops = &clk_mux_ops, + .ops = &clk_regmap_mux_ops, /* * bit 31 selects from 2 possible parents: * vapb_0 or vapb_1 @@ -1773,27 +1777,6 @@ static struct meson_clk_mpll *const gxbb_clk_mplls[] = { &gxbb_mpll2, }; -static struct clk_mux *const gxbb_clk_muxes[] = { - &gxbb_mpeg_clk_sel, - &gxbb_sar_adc_clk_sel, - &gxbb_mali_0_sel, - &gxbb_mali_1_sel, - &gxbb_mali, - &gxbb_cts_amclk_sel, - &gxbb_cts_mclk_i958_sel, - &gxbb_cts_i958, - &gxbb_32k_clk_sel, - &gxbb_sd_emmc_a_clk0_sel, - &gxbb_sd_emmc_b_clk0_sel, - &gxbb_sd_emmc_c_clk0_sel, - &gxbb_vpu_0_sel, - &gxbb_vpu_1_sel, - &gxbb_vpu, - &gxbb_vapb_0_sel, - &gxbb_vapb_1_sel, - &gxbb_vapb_sel, -}; - static struct meson_clk_audio_divider *const gxbb_audio_dividers[] = { &gxbb_cts_amclk_div, }; @@ -1908,6 +1891,24 @@ static struct clk_regmap *const gx_clk_regmaps[] = { &gxbb_vpu_1_div, &gxbb_vapb_0_div, &gxbb_vapb_1_div, + &gxbb_mpeg_clk_sel, + &gxbb_sar_adc_clk_sel, + &gxbb_mali_0_sel, + &gxbb_mali_1_sel, + &gxbb_mali, + &gxbb_cts_amclk_sel, + &gxbb_cts_mclk_i958_sel, + &gxbb_cts_i958, + &gxbb_32k_clk_sel, + &gxbb_sd_emmc_a_clk0_sel, + &gxbb_sd_emmc_b_clk0_sel, + &gxbb_sd_emmc_c_clk0_sel, + &gxbb_vpu_0_sel, + &gxbb_vpu_1_sel, + &gxbb_vpu, + &gxbb_vapb_0_sel, + &gxbb_vapb_1_sel, + &gxbb_vapb_sel, }; struct clkc_data { @@ -1915,8 +1916,6 @@ struct clkc_data { unsigned int clk_mplls_count; struct meson_clk_pll *const *clk_plls; unsigned int clk_plls_count; - struct clk_mux *const *clk_muxes; - unsigned int clk_muxes_count; struct meson_clk_audio_divider *const *clk_audio_dividers; unsigned int clk_audio_dividers_count; struct clk_hw_onecell_data *hw_onecell_data; @@ -1927,8 +1926,6 @@ static const struct clkc_data gxbb_clkc_data = { .clk_mplls_count = ARRAY_SIZE(gxbb_clk_mplls), .clk_plls = gxbb_clk_plls, .clk_plls_count = ARRAY_SIZE(gxbb_clk_plls), - .clk_muxes = gxbb_clk_muxes, - .clk_muxes_count = ARRAY_SIZE(gxbb_clk_muxes), .clk_audio_dividers = gxbb_audio_dividers, .clk_audio_dividers_count = ARRAY_SIZE(gxbb_audio_dividers), .hw_onecell_data = &gxbb_hw_onecell_data, @@ -1939,8 +1936,6 @@ static const struct clkc_data gxl_clkc_data = { .clk_mplls_count = ARRAY_SIZE(gxbb_clk_mplls), .clk_plls = gxl_clk_plls, .clk_plls_count = ARRAY_SIZE(gxl_clk_plls), - .clk_muxes = gxbb_clk_muxes, - .clk_muxes_count = ARRAY_SIZE(gxbb_clk_muxes), .clk_audio_dividers = gxbb_audio_dividers, .clk_audio_dividers_count = ARRAY_SIZE(gxbb_audio_dividers), .hw_onecell_data = &gxl_hw_onecell_data, @@ -1993,11 +1988,6 @@ static int gxbb_clkc_probe(struct platform_device *pdev) for (i = 0; i < clkc_data->clk_mplls_count; i++) clkc_data->clk_mplls[i]->base = clk_base; - /* Populate base address for muxes */ - for (i = 0; i < clkc_data->clk_muxes_count; i++) - clkc_data->clk_muxes[i]->reg = clk_base + - (u64)clkc_data->clk_muxes[i]->reg; - /* Populate base address for the audio dividers */ for (i = 0; i < clkc_data->clk_audio_dividers_count; i++) clkc_data->clk_audio_dividers[i]->base = clk_base; diff --git a/drivers/clk/meson/meson8b.c b/drivers/clk/meson/meson8b.c index e9c5278072cd..e643f7556f5e 100644 --- a/drivers/clk/meson/meson8b.c +++ b/drivers/clk/meson/meson8b.c @@ -370,17 +370,16 @@ static struct meson_clk_cpu meson8b_cpu_clk = { }; static u32 mux_table_clk81[] = { 6, 5, 7 }; - -struct clk_mux meson8b_mpeg_clk_sel = { - .reg = (void *)HHI_MPEG_CLK_CNTL, - .mask = 0x7, - .shift = 12, - .flags = CLK_MUX_READ_ONLY, - .table = mux_table_clk81, - .lock = &meson_clk_lock, +static struct clk_regmap meson8b_mpeg_clk_sel = { + .data = &(struct clk_regmap_mux_data){ + .offset = HHI_MPEG_CLK_CNTL, + .mask = 0x7, + .shift = 12, + .table = mux_table_clk81, + }, .hw.init = &(struct clk_init_data){ .name = "mpeg_clk_sel", - .ops = &clk_mux_ro_ops, + .ops = &clk_regmap_mux_ro_ops, /* * FIXME bits 14:12 selects from 8 possible parents: * xtal, 1'b0 (wtf), fclk_div7, mpll_clkout1, mpll_clkout2, @@ -620,10 +619,6 @@ static struct meson_clk_mpll *const meson8b_clk_mplls[] = { &meson8b_mpll2, }; -static struct clk_mux *const meson8b_clk_muxes[] = { - &meson8b_mpeg_clk_sel, -}; - static struct clk_regmap *const meson8b_clk_regmaps[] = { &meson8b_clk81, &meson8b_ddr, @@ -704,6 +699,7 @@ static struct clk_regmap *const meson8b_clk_regmaps[] = { &meson8b_ao_ahb_bus, &meson8b_ao_iface, &meson8b_mpeg_clk_div, + &meson8b_mpeg_clk_sel, }; static const struct meson8b_clk_reset_line { @@ -837,11 +833,6 @@ static int meson8b_clkc_probe(struct platform_device *pdev) /* Populate the base address for CPU clk */ meson8b_cpu_clk.base = clk_base; - /* Populate base address for muxes */ - for (i = 0; i < ARRAY_SIZE(meson8b_clk_muxes); i++) - meson8b_clk_muxes[i]->reg = clk_base + - (u32)meson8b_clk_muxes[i]->reg; - /* Populate regmap for the regmap backed clocks */ for (i = 0; i < ARRAY_SIZE(meson8b_clk_regmaps); i++) meson8b_clk_regmaps[i]->map = map; -- cgit v1.2.3 From f510c32a6af6123bc0638bfe869728bf8be71027 Mon Sep 17 00:00:00 2001 From: Jerome Brunet Date: Mon, 12 Feb 2018 15:58:39 +0100 Subject: clk: meson: add regmap helpers for parm Meson clock drivers are using struct parm to describe each field of the clock provider. Providing helpers to access these fields with regmap helps to keep drivers readable Signed-off-by: Jerome Brunet Signed-off-by: Neil Armstrong --- drivers/clk/meson/clkc.h | 16 ++++++++++++++++ 1 file changed, 16 insertions(+) diff --git a/drivers/clk/meson/clkc.h b/drivers/clk/meson/clkc.h index aa2dfa0ff89f..8edc25297422 100644 --- a/drivers/clk/meson/clkc.h +++ b/drivers/clk/meson/clkc.h @@ -38,6 +38,22 @@ struct parm { u8 width; }; +static inline unsigned int meson_parm_read(struct regmap *map, struct parm *p) +{ + unsigned int val; + + regmap_read(map, p->reg_off, &val); + return PARM_GET(p->width, p->shift, val); +} + +static inline void meson_parm_write(struct regmap *map, struct parm *p, + unsigned int val) +{ + regmap_update_bits(map, p->reg_off, SETPMASK(p->width, p->shift), + val << p->shift); +} + + struct pll_rate_table { unsigned long rate; u16 m; -- cgit v1.2.3 From c763e61ae8cbc9424e95b23a4d4ad5d2d7a71dcd Mon Sep 17 00:00:00 2001 From: Jerome Brunet Date: Mon, 12 Feb 2018 15:58:40 +0100 Subject: clk: meson: migrate mplls clocks to clk_regmap Rework meson mpll driver to use clk_regmap and move meson8b, gxbb and axg clocks using meson_clk_mpll to clk_regmap Signed-off-by: Jerome Brunet Signed-off-by: Neil Armstrong --- drivers/clk/meson/axg.c | 245 +++++++++++++++++++++---------------------- drivers/clk/meson/clk-mpll.c | 102 +++++++----------- drivers/clk/meson/clkc.h | 4 +- drivers/clk/meson/gxbb.c | 161 ++++++++++++++-------------- drivers/clk/meson/meson8b.c | 155 ++++++++++++++------------- 5 files changed, 313 insertions(+), 354 deletions(-) diff --git a/drivers/clk/meson/axg.c b/drivers/clk/meson/axg.c index 9f0c36e12cb8..85f9466ce006 100644 --- a/drivers/clk/meson/axg.c +++ b/drivers/clk/meson/axg.c @@ -267,38 +267,40 @@ static struct clk_fixed_factor axg_fclk_div7 = { }, }; -static struct meson_clk_mpll axg_mpll0 = { - .sdm = { - .reg_off = HHI_MPLL_CNTL7, - .shift = 0, - .width = 14, - }, - .sdm_en = { - .reg_off = HHI_MPLL_CNTL7, - .shift = 15, - .width = 1, - }, - .n2 = { - .reg_off = HHI_MPLL_CNTL7, - .shift = 16, - .width = 9, - }, - .en = { - .reg_off = HHI_MPLL_CNTL7, - .shift = 14, - .width = 1, +static struct clk_regmap axg_mpll0 = { + .data = &(struct meson_clk_mpll_data){ + .sdm = { + .reg_off = HHI_MPLL_CNTL7, + .shift = 0, + .width = 14, + }, + .sdm_en = { + .reg_off = HHI_MPLL_CNTL7, + .shift = 15, + .width = 1, + }, + .n2 = { + .reg_off = HHI_MPLL_CNTL7, + .shift = 16, + .width = 9, + }, + .en = { + .reg_off = HHI_MPLL_CNTL7, + .shift = 14, + .width = 1, + }, + .ssen = { + .reg_off = HHI_MPLL_CNTL, + .shift = 25, + .width = 1, + }, + .misc = { + .reg_off = HHI_PLL_TOP_MISC, + .shift = 0, + .width = 1, + }, + .lock = &meson_clk_lock, }, - .ssen = { - .reg_off = HHI_MPLL_CNTL, - .shift = 25, - .width = 1, - }, - .misc = { - .reg_off = HHI_PLL_TOP_MISC, - .shift = 0, - .width = 1, - }, - .lock = &meson_clk_lock, .hw.init = &(struct clk_init_data){ .name = "mpll0", .ops = &meson_clk_mpll_ops, @@ -307,33 +309,35 @@ static struct meson_clk_mpll axg_mpll0 = { }, }; -static struct meson_clk_mpll axg_mpll1 = { - .sdm = { - .reg_off = HHI_MPLL_CNTL8, - .shift = 0, - .width = 14, +static struct clk_regmap axg_mpll1 = { + .data = &(struct meson_clk_mpll_data){ + .sdm = { + .reg_off = HHI_MPLL_CNTL8, + .shift = 0, + .width = 14, + }, + .sdm_en = { + .reg_off = HHI_MPLL_CNTL8, + .shift = 15, + .width = 1, + }, + .n2 = { + .reg_off = HHI_MPLL_CNTL8, + .shift = 16, + .width = 9, + }, + .en = { + .reg_off = HHI_MPLL_CNTL8, + .shift = 14, + .width = 1, + }, + .misc = { + .reg_off = HHI_PLL_TOP_MISC, + .shift = 1, + .width = 1, + }, + .lock = &meson_clk_lock, }, - .sdm_en = { - .reg_off = HHI_MPLL_CNTL8, - .shift = 15, - .width = 1, - }, - .n2 = { - .reg_off = HHI_MPLL_CNTL8, - .shift = 16, - .width = 9, - }, - .en = { - .reg_off = HHI_MPLL_CNTL8, - .shift = 14, - .width = 1, - }, - .misc = { - .reg_off = HHI_PLL_TOP_MISC, - .shift = 1, - .width = 1, - }, - .lock = &meson_clk_lock, .hw.init = &(struct clk_init_data){ .name = "mpll1", .ops = &meson_clk_mpll_ops, @@ -342,33 +346,35 @@ static struct meson_clk_mpll axg_mpll1 = { }, }; -static struct meson_clk_mpll axg_mpll2 = { - .sdm = { - .reg_off = HHI_MPLL_CNTL9, - .shift = 0, - .width = 14, - }, - .sdm_en = { - .reg_off = HHI_MPLL_CNTL9, - .shift = 15, - .width = 1, +static struct clk_regmap axg_mpll2 = { + .data = &(struct meson_clk_mpll_data){ + .sdm = { + .reg_off = HHI_MPLL_CNTL9, + .shift = 0, + .width = 14, + }, + .sdm_en = { + .reg_off = HHI_MPLL_CNTL9, + .shift = 15, + .width = 1, + }, + .n2 = { + .reg_off = HHI_MPLL_CNTL9, + .shift = 16, + .width = 9, + }, + .en = { + .reg_off = HHI_MPLL_CNTL9, + .shift = 14, + .width = 1, + }, + .misc = { + .reg_off = HHI_PLL_TOP_MISC, + .shift = 2, + .width = 1, + }, + .lock = &meson_clk_lock, }, - .n2 = { - .reg_off = HHI_MPLL_CNTL9, - .shift = 16, - .width = 9, - }, - .en = { - .reg_off = HHI_MPLL_CNTL9, - .shift = 14, - .width = 1, - }, - .misc = { - .reg_off = HHI_PLL_TOP_MISC, - .shift = 2, - .width = 1, - }, - .lock = &meson_clk_lock, .hw.init = &(struct clk_init_data){ .name = "mpll2", .ops = &meson_clk_mpll_ops, @@ -377,33 +383,35 @@ static struct meson_clk_mpll axg_mpll2 = { }, }; -static struct meson_clk_mpll axg_mpll3 = { - .sdm = { - .reg_off = HHI_MPLL3_CNTL0, - .shift = 12, - .width = 14, - }, - .sdm_en = { - .reg_off = HHI_MPLL3_CNTL0, - .shift = 11, - .width = 1, +static struct clk_regmap axg_mpll3 = { + .data = &(struct meson_clk_mpll_data){ + .sdm = { + .reg_off = HHI_MPLL3_CNTL0, + .shift = 12, + .width = 14, + }, + .sdm_en = { + .reg_off = HHI_MPLL3_CNTL0, + .shift = 11, + .width = 1, + }, + .n2 = { + .reg_off = HHI_MPLL3_CNTL0, + .shift = 2, + .width = 9, + }, + .en = { + .reg_off = HHI_MPLL3_CNTL0, + .shift = 0, + .width = 1, + }, + .misc = { + .reg_off = HHI_PLL_TOP_MISC, + .shift = 3, + .width = 1, + }, + .lock = &meson_clk_lock, }, - .n2 = { - .reg_off = HHI_MPLL3_CNTL0, - .shift = 2, - .width = 9, - }, - .en = { - .reg_off = HHI_MPLL3_CNTL0, - .shift = 0, - .width = 1, - }, - .misc = { - .reg_off = HHI_PLL_TOP_MISC, - .shift = 3, - .width = 1, - }, - .lock = &meson_clk_lock, .hw.init = &(struct clk_init_data){ .name = "mpll3", .ops = &meson_clk_mpll_ops, @@ -698,13 +706,6 @@ static struct meson_clk_pll *const axg_clk_plls[] = { &axg_gp0_pll, }; -static struct meson_clk_mpll *const axg_clk_mplls[] = { - &axg_mpll0, - &axg_mpll1, - &axg_mpll2, - &axg_mpll3, -}; - static struct clk_regmap *const axg_clk_regmaps[] = { &axg_clk81, &axg_ddr, @@ -759,19 +760,19 @@ static struct clk_regmap *const axg_clk_regmaps[] = { &axg_mpeg_clk_sel, &axg_sd_emmc_b_clk0_sel, &axg_sd_emmc_c_clk0_sel, + &axg_mpll0, + &axg_mpll1, + &axg_mpll2, + &axg_mpll3, }; struct clkc_data { - struct meson_clk_mpll *const *clk_mplls; - unsigned int clk_mplls_count; struct meson_clk_pll *const *clk_plls; unsigned int clk_plls_count; struct clk_hw_onecell_data *hw_onecell_data; }; static const struct clkc_data axg_clkc_data = { - .clk_mplls = axg_clk_mplls, - .clk_mplls_count = ARRAY_SIZE(axg_clk_mplls), .clk_plls = axg_clk_plls, .clk_plls_count = ARRAY_SIZE(axg_clk_plls), .hw_onecell_data = &axg_hw_onecell_data, @@ -820,10 +821,6 @@ static int axg_clkc_probe(struct platform_device *pdev) for (i = 0; i < clkc_data->clk_plls_count; i++) clkc_data->clk_plls[i]->base = clk_base; - /* Populate base address for MPLLs */ - for (i = 0; i < clkc_data->clk_mplls_count; i++) - clkc_data->clk_mplls[i]->base = clk_base; - /* Populate regmap for the regmap backed clocks */ for (i = 0; i < ARRAY_SIZE(axg_clk_regmaps); i++) axg_clk_regmaps[i]->map = map; diff --git a/drivers/clk/meson/clk-mpll.c b/drivers/clk/meson/clk-mpll.c index 6d79d6daadc4..66998ff47635 100644 --- a/drivers/clk/meson/clk-mpll.c +++ b/drivers/clk/meson/clk-mpll.c @@ -68,11 +68,15 @@ #define N2_MIN 4 #define N2_MAX 511 -#define to_meson_clk_mpll(_hw) container_of(_hw, struct meson_clk_mpll, hw) +static inline struct meson_clk_mpll_data * +meson_clk_mpll_data(struct clk_regmap *clk) +{ + return (struct meson_clk_mpll_data *)clk->data; +} static long rate_from_params(unsigned long parent_rate, - unsigned long sdm, - unsigned long n2) + unsigned int sdm, + unsigned int n2) { unsigned long divisor = (SDM_DEN * n2) + sdm; @@ -84,8 +88,8 @@ static long rate_from_params(unsigned long parent_rate, static void params_from_rate(unsigned long requested_rate, unsigned long parent_rate, - unsigned long *sdm, - unsigned long *n2) + unsigned int *sdm, + unsigned int *n2) { uint64_t div = parent_rate; unsigned long rem = do_div(div, requested_rate); @@ -105,31 +109,23 @@ static void params_from_rate(unsigned long requested_rate, static unsigned long mpll_recalc_rate(struct clk_hw *hw, unsigned long parent_rate) { - struct meson_clk_mpll *mpll = to_meson_clk_mpll(hw); - struct parm *p; - unsigned long reg, sdm, n2; + struct clk_regmap *clk = to_clk_regmap(hw); + struct meson_clk_mpll_data *mpll = meson_clk_mpll_data(clk); + unsigned int sdm, n2; long rate; - p = &mpll->sdm; - reg = readl(mpll->base + p->reg_off); - sdm = PARM_GET(p->width, p->shift, reg); - - p = &mpll->n2; - reg = readl(mpll->base + p->reg_off); - n2 = PARM_GET(p->width, p->shift, reg); + sdm = meson_parm_read(clk->map, &mpll->sdm); + n2 = meson_parm_read(clk->map, &mpll->n2); rate = rate_from_params(parent_rate, sdm, n2); - if (rate < 0) - return 0; - - return rate; + return rate < 0 ? 0 : rate; } static long mpll_round_rate(struct clk_hw *hw, unsigned long rate, unsigned long *parent_rate) { - unsigned long sdm, n2; + unsigned int sdm, n2; params_from_rate(rate, *parent_rate, &sdm, &n2); return rate_from_params(*parent_rate, sdm, n2); @@ -139,9 +135,9 @@ static int mpll_set_rate(struct clk_hw *hw, unsigned long rate, unsigned long parent_rate) { - struct meson_clk_mpll *mpll = to_meson_clk_mpll(hw); - struct parm *p; - unsigned long reg, sdm, n2; + struct clk_regmap *clk = to_clk_regmap(hw); + struct meson_clk_mpll_data *mpll = meson_clk_mpll_data(clk); + unsigned int sdm, n2; unsigned long flags = 0; params_from_rate(rate, parent_rate, &sdm, &n2); @@ -151,34 +147,20 @@ static int mpll_set_rate(struct clk_hw *hw, else __acquire(mpll->lock); - p = &mpll->sdm; - reg = readl(mpll->base + p->reg_off); - reg = PARM_SET(p->width, p->shift, reg, sdm); - writel(reg, mpll->base + p->reg_off); - - p = &mpll->sdm_en; - reg = readl(mpll->base + p->reg_off); - reg = PARM_SET(p->width, p->shift, reg, 1); - writel(reg, mpll->base + p->reg_off); - - p = &mpll->ssen; - if (p->width != 0) { - reg = readl(mpll->base + p->reg_off); - reg = PARM_SET(p->width, p->shift, reg, 1); - writel(reg, mpll->base + p->reg_off); - } + /* Enable and set the fractional part */ + meson_parm_write(clk->map, &mpll->sdm, sdm); + meson_parm_write(clk->map, &mpll->sdm_en, 1); - p = &mpll->n2; - reg = readl(mpll->base + p->reg_off); - reg = PARM_SET(p->width, p->shift, reg, n2); - writel(reg, mpll->base + p->reg_off); + /* Set additional fractional part enable if required */ + if (MESON_PARM_APPLICABLE(&mpll->ssen)) + meson_parm_write(clk->map, &mpll->ssen, 1); - p = &mpll->misc; - if (p->width != 0) { - reg = readl(mpll->base + p->reg_off); - reg = PARM_SET(p->width, p->shift, reg, 1); - writel(reg, mpll->base + p->reg_off); - } + /* Set the integer divider part */ + meson_parm_write(clk->map, &mpll->n2, n2); + + /* Set the magic misc bit if required */ + if (MESON_PARM_APPLICABLE(&mpll->misc)) + meson_parm_write(clk->map, &mpll->misc, 1); if (mpll->lock) spin_unlock_irqrestore(mpll->lock, flags); @@ -190,9 +172,8 @@ static int mpll_set_rate(struct clk_hw *hw, static void mpll_enable_core(struct clk_hw *hw, int enable) { - struct meson_clk_mpll *mpll = to_meson_clk_mpll(hw); - struct parm *p; - unsigned long reg; + struct clk_regmap *clk = to_clk_regmap(hw); + struct meson_clk_mpll_data *mpll = meson_clk_mpll_data(clk); unsigned long flags = 0; if (mpll->lock) @@ -200,10 +181,7 @@ static void mpll_enable_core(struct clk_hw *hw, int enable) else __acquire(mpll->lock); - p = &mpll->en; - reg = readl(mpll->base + p->reg_off); - reg = PARM_SET(p->width, p->shift, reg, enable ? 1 : 0); - writel(reg, mpll->base + p->reg_off); + meson_parm_write(clk->map, &mpll->en, enable ? 1 : 0); if (mpll->lock) spin_unlock_irqrestore(mpll->lock, flags); @@ -226,16 +204,10 @@ static void mpll_disable(struct clk_hw *hw) static int mpll_is_enabled(struct clk_hw *hw) { - struct meson_clk_mpll *mpll = to_meson_clk_mpll(hw); - struct parm *p; - unsigned long reg; - int en; - - p = &mpll->en; - reg = readl(mpll->base + p->reg_off); - en = PARM_GET(p->width, p->shift, reg); + struct clk_regmap *clk = to_clk_regmap(hw); + struct meson_clk_mpll_data *mpll = meson_clk_mpll_data(clk); - return en; + return meson_parm_read(clk->map, &mpll->en); } const struct clk_ops meson_clk_mpll_ro_ops = { diff --git a/drivers/clk/meson/clkc.h b/drivers/clk/meson/clkc.h index 8edc25297422..08a1ebfc65dc 100644 --- a/drivers/clk/meson/clkc.h +++ b/drivers/clk/meson/clkc.h @@ -132,9 +132,7 @@ struct meson_clk_cpu { int meson_clk_cpu_notifier_cb(struct notifier_block *nb, unsigned long event, void *data); -struct meson_clk_mpll { - struct clk_hw hw; - void __iomem *base; +struct meson_clk_mpll_data { struct parm sdm; struct parm sdm_en; struct parm n2; diff --git a/drivers/clk/meson/gxbb.c b/drivers/clk/meson/gxbb.c index d9f426265774..d2724a7ce9e7 100644 --- a/drivers/clk/meson/gxbb.c +++ b/drivers/clk/meson/gxbb.c @@ -482,33 +482,35 @@ static struct clk_fixed_factor gxbb_fclk_div7 = { }, }; -static struct meson_clk_mpll gxbb_mpll0 = { - .sdm = { - .reg_off = HHI_MPLL_CNTL7, - .shift = 0, - .width = 14, - }, - .sdm_en = { - .reg_off = HHI_MPLL_CNTL7, - .shift = 15, - .width = 1, - }, - .n2 = { - .reg_off = HHI_MPLL_CNTL7, - .shift = 16, - .width = 9, - }, - .en = { - .reg_off = HHI_MPLL_CNTL7, - .shift = 14, - .width = 1, - }, - .ssen = { - .reg_off = HHI_MPLL_CNTL, - .shift = 25, - .width = 1, +static struct clk_regmap gxbb_mpll0 = { + .data = &(struct meson_clk_mpll_data){ + .sdm = { + .reg_off = HHI_MPLL_CNTL7, + .shift = 0, + .width = 14, + }, + .sdm_en = { + .reg_off = HHI_MPLL_CNTL7, + .shift = 15, + .width = 1, + }, + .n2 = { + .reg_off = HHI_MPLL_CNTL7, + .shift = 16, + .width = 9, + }, + .en = { + .reg_off = HHI_MPLL_CNTL7, + .shift = 14, + .width = 1, + }, + .ssen = { + .reg_off = HHI_MPLL_CNTL, + .shift = 25, + .width = 1, + }, + .lock = &meson_clk_lock, }, - .lock = &meson_clk_lock, .hw.init = &(struct clk_init_data){ .name = "mpll0", .ops = &meson_clk_mpll_ops, @@ -517,28 +519,30 @@ static struct meson_clk_mpll gxbb_mpll0 = { }, }; -static struct meson_clk_mpll gxbb_mpll1 = { - .sdm = { - .reg_off = HHI_MPLL_CNTL8, - .shift = 0, - .width = 14, - }, - .sdm_en = { - .reg_off = HHI_MPLL_CNTL8, - .shift = 15, - .width = 1, - }, - .n2 = { - .reg_off = HHI_MPLL_CNTL8, - .shift = 16, - .width = 9, - }, - .en = { - .reg_off = HHI_MPLL_CNTL8, - .shift = 14, - .width = 1, +static struct clk_regmap gxbb_mpll1 = { + .data = &(struct meson_clk_mpll_data){ + .sdm = { + .reg_off = HHI_MPLL_CNTL8, + .shift = 0, + .width = 14, + }, + .sdm_en = { + .reg_off = HHI_MPLL_CNTL8, + .shift = 15, + .width = 1, + }, + .n2 = { + .reg_off = HHI_MPLL_CNTL8, + .shift = 16, + .width = 9, + }, + .en = { + .reg_off = HHI_MPLL_CNTL8, + .shift = 14, + .width = 1, + }, + .lock = &meson_clk_lock, }, - .lock = &meson_clk_lock, .hw.init = &(struct clk_init_data){ .name = "mpll1", .ops = &meson_clk_mpll_ops, @@ -547,28 +551,30 @@ static struct meson_clk_mpll gxbb_mpll1 = { }, }; -static struct meson_clk_mpll gxbb_mpll2 = { - .sdm = { - .reg_off = HHI_MPLL_CNTL9, - .shift = 0, - .width = 14, - }, - .sdm_en = { - .reg_off = HHI_MPLL_CNTL9, - .shift = 15, - .width = 1, - }, - .n2 = { - .reg_off = HHI_MPLL_CNTL9, - .shift = 16, - .width = 9, - }, - .en = { - .reg_off = HHI_MPLL_CNTL9, - .shift = 14, - .width = 1, +static struct clk_regmap gxbb_mpll2 = { + .data = &(struct meson_clk_mpll_data){ + .sdm = { + .reg_off = HHI_MPLL_CNTL9, + .shift = 0, + .width = 14, + }, + .sdm_en = { + .reg_off = HHI_MPLL_CNTL9, + .shift = 15, + .width = 1, + }, + .n2 = { + .reg_off = HHI_MPLL_CNTL9, + .shift = 16, + .width = 9, + }, + .en = { + .reg_off = HHI_MPLL_CNTL9, + .shift = 14, + .width = 1, + }, + .lock = &meson_clk_lock, }, - .lock = &meson_clk_lock, .hw.init = &(struct clk_init_data){ .name = "mpll2", .ops = &meson_clk_mpll_ops, @@ -1771,12 +1777,6 @@ static struct meson_clk_pll *const gxl_clk_plls[] = { &gxl_gp0_pll, }; -static struct meson_clk_mpll *const gxbb_clk_mplls[] = { - &gxbb_mpll0, - &gxbb_mpll1, - &gxbb_mpll2, -}; - static struct meson_clk_audio_divider *const gxbb_audio_dividers[] = { &gxbb_cts_amclk_div, }; @@ -1909,11 +1909,12 @@ static struct clk_regmap *const gx_clk_regmaps[] = { &gxbb_vapb_0_sel, &gxbb_vapb_1_sel, &gxbb_vapb_sel, + &gxbb_mpll0, + &gxbb_mpll1, + &gxbb_mpll2, }; struct clkc_data { - struct meson_clk_mpll *const *clk_mplls; - unsigned int clk_mplls_count; struct meson_clk_pll *const *clk_plls; unsigned int clk_plls_count; struct meson_clk_audio_divider *const *clk_audio_dividers; @@ -1922,8 +1923,6 @@ struct clkc_data { }; static const struct clkc_data gxbb_clkc_data = { - .clk_mplls = gxbb_clk_mplls, - .clk_mplls_count = ARRAY_SIZE(gxbb_clk_mplls), .clk_plls = gxbb_clk_plls, .clk_plls_count = ARRAY_SIZE(gxbb_clk_plls), .clk_audio_dividers = gxbb_audio_dividers, @@ -1932,8 +1931,6 @@ static const struct clkc_data gxbb_clkc_data = { }; static const struct clkc_data gxl_clkc_data = { - .clk_mplls = gxbb_clk_mplls, - .clk_mplls_count = ARRAY_SIZE(gxbb_clk_mplls), .clk_plls = gxl_clk_plls, .clk_plls_count = ARRAY_SIZE(gxl_clk_plls), .clk_audio_dividers = gxbb_audio_dividers, @@ -1984,10 +1981,6 @@ static int gxbb_clkc_probe(struct platform_device *pdev) for (i = 0; i < clkc_data->clk_plls_count; i++) clkc_data->clk_plls[i]->base = clk_base; - /* Populate base address for MPLLs */ - for (i = 0; i < clkc_data->clk_mplls_count; i++) - clkc_data->clk_mplls[i]->base = clk_base; - /* Populate base address for the audio dividers */ for (i = 0; i < clkc_data->clk_audio_dividers_count; i++) clkc_data->clk_audio_dividers[i]->base = clk_base; diff --git a/drivers/clk/meson/meson8b.c b/drivers/clk/meson/meson8b.c index e643f7556f5e..4bb51c8f3102 100644 --- a/drivers/clk/meson/meson8b.c +++ b/drivers/clk/meson/meson8b.c @@ -257,33 +257,35 @@ static struct clk_fixed_factor meson8b_fclk_div7 = { }, }; -static struct meson_clk_mpll meson8b_mpll0 = { - .sdm = { - .reg_off = HHI_MPLL_CNTL7, - .shift = 0, - .width = 14, - }, - .sdm_en = { - .reg_off = HHI_MPLL_CNTL7, - .shift = 15, - .width = 1, - }, - .n2 = { - .reg_off = HHI_MPLL_CNTL7, - .shift = 16, - .width = 9, - }, - .en = { - .reg_off = HHI_MPLL_CNTL7, - .shift = 14, - .width = 1, - }, - .ssen = { - .reg_off = HHI_MPLL_CNTL, - .shift = 25, - .width = 1, +static struct clk_regmap meson8b_mpll0 = { + .data = &(struct meson_clk_mpll_data){ + .sdm = { + .reg_off = HHI_MPLL_CNTL7, + .shift = 0, + .width = 14, + }, + .sdm_en = { + .reg_off = HHI_MPLL_CNTL7, + .shift = 15, + .width = 1, + }, + .n2 = { + .reg_off = HHI_MPLL_CNTL7, + .shift = 16, + .width = 9, + }, + .en = { + .reg_off = HHI_MPLL_CNTL7, + .shift = 14, + .width = 1, + }, + .ssen = { + .reg_off = HHI_MPLL_CNTL, + .shift = 25, + .width = 1, + }, + .lock = &meson_clk_lock, }, - .lock = &meson_clk_lock, .hw.init = &(struct clk_init_data){ .name = "mpll0", .ops = &meson_clk_mpll_ops, @@ -292,28 +294,30 @@ static struct meson_clk_mpll meson8b_mpll0 = { }, }; -static struct meson_clk_mpll meson8b_mpll1 = { - .sdm = { - .reg_off = HHI_MPLL_CNTL8, - .shift = 0, - .width = 14, - }, - .sdm_en = { - .reg_off = HHI_MPLL_CNTL8, - .shift = 15, - .width = 1, - }, - .n2 = { - .reg_off = HHI_MPLL_CNTL8, - .shift = 16, - .width = 9, +static struct clk_regmap meson8b_mpll1 = { + .data = &(struct meson_clk_mpll_data){ + .sdm = { + .reg_off = HHI_MPLL_CNTL8, + .shift = 0, + .width = 14, + }, + .sdm_en = { + .reg_off = HHI_MPLL_CNTL8, + .shift = 15, + .width = 1, + }, + .n2 = { + .reg_off = HHI_MPLL_CNTL8, + .shift = 16, + .width = 9, + }, + .en = { + .reg_off = HHI_MPLL_CNTL8, + .shift = 14, + .width = 1, + }, + .lock = &meson_clk_lock, }, - .en = { - .reg_off = HHI_MPLL_CNTL8, - .shift = 14, - .width = 1, - }, - .lock = &meson_clk_lock, .hw.init = &(struct clk_init_data){ .name = "mpll1", .ops = &meson_clk_mpll_ops, @@ -322,28 +326,30 @@ static struct meson_clk_mpll meson8b_mpll1 = { }, }; -static struct meson_clk_mpll meson8b_mpll2 = { - .sdm = { - .reg_off = HHI_MPLL_CNTL9, - .shift = 0, - .width = 14, - }, - .sdm_en = { - .reg_off = HHI_MPLL_CNTL9, - .shift = 15, - .width = 1, - }, - .n2 = { - .reg_off = HHI_MPLL_CNTL9, - .shift = 16, - .width = 9, - }, - .en = { - .reg_off = HHI_MPLL_CNTL9, - .shift = 14, - .width = 1, +static struct clk_regmap meson8b_mpll2 = { + .data = &(struct meson_clk_mpll_data){ + .sdm = { + .reg_off = HHI_MPLL_CNTL9, + .shift = 0, + .width = 14, + }, + .sdm_en = { + .reg_off = HHI_MPLL_CNTL9, + .shift = 15, + .width = 1, + }, + .n2 = { + .reg_off = HHI_MPLL_CNTL9, + .shift = 16, + .width = 9, + }, + .en = { + .reg_off = HHI_MPLL_CNTL9, + .shift = 14, + .width = 1, + }, + .lock = &meson_clk_lock, }, - .lock = &meson_clk_lock, .hw.init = &(struct clk_init_data){ .name = "mpll2", .ops = &meson_clk_mpll_ops, @@ -613,12 +619,6 @@ static struct meson_clk_pll *const meson8b_clk_plls[] = { &meson8b_sys_pll, }; -static struct meson_clk_mpll *const meson8b_clk_mplls[] = { - &meson8b_mpll0, - &meson8b_mpll1, - &meson8b_mpll2, -}; - static struct clk_regmap *const meson8b_clk_regmaps[] = { &meson8b_clk81, &meson8b_ddr, @@ -700,6 +700,9 @@ static struct clk_regmap *const meson8b_clk_regmaps[] = { &meson8b_ao_iface, &meson8b_mpeg_clk_div, &meson8b_mpeg_clk_sel, + &meson8b_mpll0, + &meson8b_mpll1, + &meson8b_mpll2, }; static const struct meson8b_clk_reset_line { @@ -826,10 +829,6 @@ static int meson8b_clkc_probe(struct platform_device *pdev) for (i = 0; i < ARRAY_SIZE(meson8b_clk_plls); i++) meson8b_clk_plls[i]->base = clk_base; - /* Populate base address for MPLLs */ - for (i = 0; i < ARRAY_SIZE(meson8b_clk_mplls); i++) - meson8b_clk_mplls[i]->base = clk_base; - /* Populate the base address for CPU clk */ meson8b_cpu_clk.base = clk_base; -- cgit v1.2.3 From 88a4e1283681e0f07048b2bd867cc81fbbae57cc Mon Sep 17 00:00:00 2001 From: Jerome Brunet Date: Mon, 12 Feb 2018 15:58:41 +0100 Subject: clk: meson: migrate the audio divider clock to clk_regmap Rework meson audio divider driver to use clk_regmap and move gxbb clock using meson_clk_audio_divider to clk_regmap. Signed-off-by: Jerome Brunet Signed-off-by: Neil Armstrong --- drivers/clk/meson/clk-audio-divider.c | 63 +++++++++++------------------------ drivers/clk/meson/clkc.h | 5 +-- drivers/clk/meson/gxbb.c | 30 +++++------------ 3 files changed, 30 insertions(+), 68 deletions(-) diff --git a/drivers/clk/meson/clk-audio-divider.c b/drivers/clk/meson/clk-audio-divider.c index 6c07db06642d..f7ab5b1db342 100644 --- a/drivers/clk/meson/clk-audio-divider.c +++ b/drivers/clk/meson/clk-audio-divider.c @@ -28,8 +28,11 @@ #include #include "clkc.h" -#define to_meson_clk_audio_divider(_hw) container_of(_hw, \ - struct meson_clk_audio_divider, hw) +static inline struct meson_clk_audio_div_data * +meson_clk_audio_div_data(struct clk_regmap *clk) +{ + return (struct meson_clk_audio_div_data *)clk->data; +} static int _div_round(unsigned long parent_rate, unsigned long rate, unsigned long flags) @@ -45,15 +48,9 @@ static int _get_val(unsigned long parent_rate, unsigned long rate) return DIV_ROUND_UP_ULL((u64)parent_rate, rate) - 1; } -static int _valid_divider(struct clk_hw *hw, int divider) +static int _valid_divider(unsigned int width, int divider) { - struct meson_clk_audio_divider *adiv = - to_meson_clk_audio_divider(hw); - int max_divider; - u8 width; - - width = adiv->div.width; - max_divider = 1 << width; + int max_divider = 1 << width; return clamp(divider, 1, max_divider); } @@ -61,14 +58,11 @@ static int _valid_divider(struct clk_hw *hw, int divider) static unsigned long audio_divider_recalc_rate(struct clk_hw *hw, unsigned long parent_rate) { - struct meson_clk_audio_divider *adiv = - to_meson_clk_audio_divider(hw); - struct parm *p; - unsigned long reg, divider; + struct clk_regmap *clk = to_clk_regmap(hw); + struct meson_clk_audio_div_data *adiv = meson_clk_audio_div_data(clk); + unsigned long divider; - p = &adiv->div; - reg = readl(adiv->base + p->reg_off); - divider = PARM_GET(p->width, p->shift, reg) + 1; + divider = meson_parm_read(clk->map, &adiv->div); return DIV_ROUND_UP_ULL((u64)parent_rate, divider); } @@ -77,14 +71,14 @@ static long audio_divider_round_rate(struct clk_hw *hw, unsigned long rate, unsigned long *parent_rate) { - struct meson_clk_audio_divider *adiv = - to_meson_clk_audio_divider(hw); + struct clk_regmap *clk = to_clk_regmap(hw); + struct meson_clk_audio_div_data *adiv = meson_clk_audio_div_data(clk); unsigned long max_prate; int divider; if (!(clk_hw_get_flags(hw) & CLK_SET_RATE_PARENT)) { divider = _div_round(*parent_rate, rate, adiv->flags); - divider = _valid_divider(hw, divider); + divider = _valid_divider(adiv->div.width, divider); return DIV_ROUND_UP_ULL((u64)*parent_rate, divider); } @@ -93,7 +87,7 @@ static long audio_divider_round_rate(struct clk_hw *hw, /* Get the corresponding rounded down divider */ divider = max_prate / rate; - divider = _valid_divider(hw, divider); + divider = _valid_divider(adiv->div.width, divider); /* Get actual rate of the parent */ *parent_rate = clk_hw_round_rate(clk_hw_get_parent(hw), @@ -106,28 +100,11 @@ static int audio_divider_set_rate(struct clk_hw *hw, unsigned long rate, unsigned long parent_rate) { - struct meson_clk_audio_divider *adiv = - to_meson_clk_audio_divider(hw); - struct parm *p; - unsigned long reg, flags = 0; - int val; - - val = _get_val(parent_rate, rate); - - if (adiv->lock) - spin_lock_irqsave(adiv->lock, flags); - else - __acquire(adiv->lock); - - p = &adiv->div; - reg = readl(adiv->base + p->reg_off); - reg = PARM_SET(p->width, p->shift, reg, val); - writel(reg, adiv->base + p->reg_off); - - if (adiv->lock) - spin_unlock_irqrestore(adiv->lock, flags); - else - __release(adiv->lock); + struct clk_regmap *clk = to_clk_regmap(hw); + struct meson_clk_audio_div_data *adiv = meson_clk_audio_div_data(clk); + int val = _get_val(parent_rate, rate); + + meson_parm_write(clk->map, &adiv->div, val); return 0; } diff --git a/drivers/clk/meson/clkc.h b/drivers/clk/meson/clkc.h index 08a1ebfc65dc..a4a526cbca4c 100644 --- a/drivers/clk/meson/clkc.h +++ b/drivers/clk/meson/clkc.h @@ -142,12 +142,9 @@ struct meson_clk_mpll_data { spinlock_t *lock; }; -struct meson_clk_audio_divider { - struct clk_hw hw; - void __iomem *base; +struct meson_clk_audio_div_data { struct parm div; u8 flags; - spinlock_t *lock; }; #define MESON_GATE(_name, _reg, _bit) \ diff --git a/drivers/clk/meson/gxbb.c b/drivers/clk/meson/gxbb.c index d2724a7ce9e7..196557f11608 100644 --- a/drivers/clk/meson/gxbb.c +++ b/drivers/clk/meson/gxbb.c @@ -826,14 +826,15 @@ static struct clk_regmap gxbb_cts_amclk_sel = { }, }; -static struct meson_clk_audio_divider gxbb_cts_amclk_div = { - .div = { - .reg_off = HHI_AUD_CLK_CNTL, - .shift = 0, - .width = 8, +static struct clk_regmap gxbb_cts_amclk_div = { + .data = &(struct meson_clk_audio_div_data){ + .div = { + .reg_off = HHI_AUD_CLK_CNTL, + .shift = 0, + .width = 8, + }, + .flags = CLK_DIVIDER_ROUND_CLOSEST, }, - .flags = CLK_DIVIDER_ROUND_CLOSEST, - .lock = &meson_clk_lock, .hw.init = &(struct clk_init_data){ .name = "cts_amclk_div", .ops = &meson_clk_audio_divider_ops, @@ -1777,10 +1778,6 @@ static struct meson_clk_pll *const gxl_clk_plls[] = { &gxl_gp0_pll, }; -static struct meson_clk_audio_divider *const gxbb_audio_dividers[] = { - &gxbb_cts_amclk_div, -}; - static struct clk_regmap *const gx_clk_regmaps[] = { &gxbb_clk81, &gxbb_ddr, @@ -1912,29 +1909,24 @@ static struct clk_regmap *const gx_clk_regmaps[] = { &gxbb_mpll0, &gxbb_mpll1, &gxbb_mpll2, + &gxbb_cts_amclk_div, }; struct clkc_data { struct meson_clk_pll *const *clk_plls; unsigned int clk_plls_count; - struct meson_clk_audio_divider *const *clk_audio_dividers; - unsigned int clk_audio_dividers_count; struct clk_hw_onecell_data *hw_onecell_data; }; static const struct clkc_data gxbb_clkc_data = { .clk_plls = gxbb_clk_plls, .clk_plls_count = ARRAY_SIZE(gxbb_clk_plls), - .clk_audio_dividers = gxbb_audio_dividers, - .clk_audio_dividers_count = ARRAY_SIZE(gxbb_audio_dividers), .hw_onecell_data = &gxbb_hw_onecell_data, }; static const struct clkc_data gxl_clkc_data = { .clk_plls = gxl_clk_plls, .clk_plls_count = ARRAY_SIZE(gxl_clk_plls), - .clk_audio_dividers = gxbb_audio_dividers, - .clk_audio_dividers_count = ARRAY_SIZE(gxbb_audio_dividers), .hw_onecell_data = &gxl_hw_onecell_data, }; @@ -1981,10 +1973,6 @@ static int gxbb_clkc_probe(struct platform_device *pdev) for (i = 0; i < clkc_data->clk_plls_count; i++) clkc_data->clk_plls[i]->base = clk_base; - /* Populate base address for the audio dividers */ - for (i = 0; i < clkc_data->clk_audio_dividers_count; i++) - clkc_data->clk_audio_dividers[i]->base = clk_base; - /* Populate regmap for the common regmap backed clocks */ for (i = 0; i < ARRAY_SIZE(gx_clk_regmaps); i++) gx_clk_regmaps[i]->map = map; -- cgit v1.2.3 From 722825dcd54b2e427c1aee54a7992eb4ab04a49d Mon Sep 17 00:00:00 2001 From: Jerome Brunet Date: Mon, 12 Feb 2018 15:58:42 +0100 Subject: clk: meson: migrate plls clocks to clk_regmap Rework meson pll driver to use clk_regmap and move meson8b, gxbb and axg's clock using meson_clk_pll to clk_regmap. This rework is not just about clk_regmap, there a serious clean-up of the driver code: * Add lock and reset field: Previously inferred from the n field. * Simplify the reset logic: Code seemed to apply reset differently but in fact it was always the same -> assert reset, apply params, de-assert reset. The 2 lock checking loops have been kept for now, as they seem to be necessary. * Do the sequence of init register pokes only at .init() instead of in .set_rate(). Redoing the init on every set_rate() is not necessary Signed-off-by: Jerome Brunet Signed-off-by: Neil Armstrong --- drivers/clk/meson/axg.c | 213 +++++++++++----------- drivers/clk/meson/clk-pll.c | 243 ++++++++++--------------- drivers/clk/meson/clkc.h | 36 +--- drivers/clk/meson/gxbb.c | 424 +++++++++++++++++++++++++------------------- drivers/clk/meson/meson8b.c | 149 +++++++++------- 5 files changed, 535 insertions(+), 530 deletions(-) diff --git a/drivers/clk/meson/axg.c b/drivers/clk/meson/axg.c index 85f9466ce006..8c27ceffda4a 100644 --- a/drivers/clk/meson/axg.c +++ b/drivers/clk/meson/axg.c @@ -22,28 +22,39 @@ static DEFINE_SPINLOCK(meson_clk_lock); -static struct meson_clk_pll axg_fixed_pll = { - .m = { - .reg_off = HHI_MPLL_CNTL, - .shift = 0, - .width = 9, - }, - .n = { - .reg_off = HHI_MPLL_CNTL, - .shift = 9, - .width = 5, - }, - .od = { - .reg_off = HHI_MPLL_CNTL, - .shift = 16, - .width = 2, - }, - .frac = { - .reg_off = HHI_MPLL_CNTL2, - .shift = 0, - .width = 12, - }, - .lock = &meson_clk_lock, +static struct clk_regmap axg_fixed_pll = { + .data = &(struct meson_clk_pll_data){ + .m = { + .reg_off = HHI_MPLL_CNTL, + .shift = 0, + .width = 9, + }, + .n = { + .reg_off = HHI_MPLL_CNTL, + .shift = 9, + .width = 5, + }, + .od = { + .reg_off = HHI_MPLL_CNTL, + .shift = 16, + .width = 2, + }, + .frac = { + .reg_off = HHI_MPLL_CNTL2, + .shift = 0, + .width = 12, + }, + .l = { + .reg_off = HHI_MPLL_CNTL, + .shift = 31, + .width = 1, + }, + .rst = { + .reg_off = HHI_MPLL_CNTL, + .shift = 29, + .width = 1, + }, + }, .hw.init = &(struct clk_init_data){ .name = "fixed_pll", .ops = &meson_clk_pll_ro_ops, @@ -52,23 +63,34 @@ static struct meson_clk_pll axg_fixed_pll = { }, }; -static struct meson_clk_pll axg_sys_pll = { - .m = { - .reg_off = HHI_SYS_PLL_CNTL, - .shift = 0, - .width = 9, - }, - .n = { - .reg_off = HHI_SYS_PLL_CNTL, - .shift = 9, - .width = 5, - }, - .od = { - .reg_off = HHI_SYS_PLL_CNTL, - .shift = 16, - .width = 2, +static struct clk_regmap axg_sys_pll = { + .data = &(struct meson_clk_pll_data){ + .m = { + .reg_off = HHI_SYS_PLL_CNTL, + .shift = 0, + .width = 9, + }, + .n = { + .reg_off = HHI_SYS_PLL_CNTL, + .shift = 9, + .width = 5, + }, + .od = { + .reg_off = HHI_SYS_PLL_CNTL, + .shift = 16, + .width = 2, + }, + .l = { + .reg_off = HHI_SYS_PLL_CNTL, + .shift = 31, + .width = 1, + }, + .rst = { + .reg_off = HHI_SYS_PLL_CNTL, + .shift = 29, + .width = 1, + }, }, - .lock = &meson_clk_lock, .hw.init = &(struct clk_init_data){ .name = "sys_pll", .ops = &meson_clk_pll_ro_ops, @@ -169,40 +191,47 @@ static const struct pll_rate_table axg_gp0_pll_rate_table[] = { { /* sentinel */ }, }; -static struct pll_params_table axg_gp0_params_table[] = { - PLL_PARAM(HHI_GP0_PLL_CNTL, 0x40010250), - PLL_PARAM(HHI_GP0_PLL_CNTL1, 0xc084a000), - PLL_PARAM(HHI_GP0_PLL_CNTL2, 0xb75020be), - PLL_PARAM(HHI_GP0_PLL_CNTL3, 0x0a59a288), - PLL_PARAM(HHI_GP0_PLL_CNTL4, 0xc000004d), - PLL_PARAM(HHI_GP0_PLL_CNTL5, 0x00078000), +const struct reg_sequence axg_gp0_init_regs[] = { + { .reg = HHI_GP0_PLL_CNTL, .def = 0x40010250 }, + { .reg = HHI_GP0_PLL_CNTL1, .def = 0xc084a000 }, + { .reg = HHI_GP0_PLL_CNTL2, .def = 0xb75020be }, + { .reg = HHI_GP0_PLL_CNTL3, .def = 0x0a59a288 }, + { .reg = HHI_GP0_PLL_CNTL4, .def = 0xc000004d }, + { .reg = HHI_GP0_PLL_CNTL5, .def = 0x00078000 }, }; -static struct meson_clk_pll axg_gp0_pll = { - .m = { - .reg_off = HHI_GP0_PLL_CNTL, - .shift = 0, - .width = 9, - }, - .n = { - .reg_off = HHI_GP0_PLL_CNTL, - .shift = 9, - .width = 5, - }, - .od = { - .reg_off = HHI_GP0_PLL_CNTL, - .shift = 16, - .width = 2, - }, - .params = { - .params_table = axg_gp0_params_table, - .params_count = ARRAY_SIZE(axg_gp0_params_table), - .no_init_reset = true, - .reset_lock_loop = true, - }, - .rate_table = axg_gp0_pll_rate_table, - .rate_count = ARRAY_SIZE(axg_gp0_pll_rate_table), - .lock = &meson_clk_lock, +static struct clk_regmap axg_gp0_pll = { + .data = &(struct meson_clk_pll_data){ + .m = { + .reg_off = HHI_GP0_PLL_CNTL, + .shift = 0, + .width = 9, + }, + .n = { + .reg_off = HHI_GP0_PLL_CNTL, + .shift = 9, + .width = 5, + }, + .od = { + .reg_off = HHI_GP0_PLL_CNTL, + .shift = 16, + .width = 2, + }, + .l = { + .reg_off = HHI_GP0_PLL_CNTL, + .shift = 31, + .width = 1, + }, + .rst = { + .reg_off = HHI_GP0_PLL_CNTL, + .shift = 29, + .width = 1, + }, + .table = axg_gp0_pll_rate_table, + .init_regs = axg_gp0_init_regs, + .init_count = ARRAY_SIZE(axg_gp0_init_regs), + .flags = CLK_MESON_PLL_LOCK_LOOP_RST, + }, .hw.init = &(struct clk_init_data){ .name = "gp0_pll", .ops = &meson_clk_pll_ops, @@ -698,14 +727,7 @@ static struct clk_hw_onecell_data axg_hw_onecell_data = { .num = NR_CLKS, }; -/* Convenience tables to populate base addresses in .probe */ - -static struct meson_clk_pll *const axg_clk_plls[] = { - &axg_fixed_pll, - &axg_sys_pll, - &axg_gp0_pll, -}; - +/* Convenience table to populate regmap in .probe */ static struct clk_regmap *const axg_clk_regmaps[] = { &axg_clk81, &axg_ddr, @@ -764,22 +786,13 @@ static struct clk_regmap *const axg_clk_regmaps[] = { &axg_mpll1, &axg_mpll2, &axg_mpll3, -}; - -struct clkc_data { - struct meson_clk_pll *const *clk_plls; - unsigned int clk_plls_count; - struct clk_hw_onecell_data *hw_onecell_data; -}; - -static const struct clkc_data axg_clkc_data = { - .clk_plls = axg_clk_plls, - .clk_plls_count = ARRAY_SIZE(axg_clk_plls), - .hw_onecell_data = &axg_hw_onecell_data, + &axg_fixed_pll, + &axg_sys_pll, + &axg_gp0_pll, }; static const struct of_device_id clkc_match_table[] = { - { .compatible = "amlogic,axg-clkc", .data = &axg_clkc_data }, + { .compatible = "amlogic,axg-clkc" }, {} }; @@ -792,16 +805,11 @@ static const struct regmap_config clkc_regmap_config = { static int axg_clkc_probe(struct platform_device *pdev) { struct device *dev = &pdev->dev; - const struct clkc_data *clkc_data; struct resource *res; void __iomem *clk_base; struct regmap *map; int ret, i; - clkc_data = of_device_get_match_data(dev); - if (!clkc_data) - return -EINVAL; - /* Generic clocks and PLLs */ res = platform_get_resource(pdev, IORESOURCE_MEM, 0); if (!res) @@ -817,21 +825,16 @@ static int axg_clkc_probe(struct platform_device *pdev) if (IS_ERR(map)) return PTR_ERR(map); - /* Populate base address for PLLs */ - for (i = 0; i < clkc_data->clk_plls_count; i++) - clkc_data->clk_plls[i]->base = clk_base; - /* Populate regmap for the regmap backed clocks */ for (i = 0; i < ARRAY_SIZE(axg_clk_regmaps); i++) axg_clk_regmaps[i]->map = map; - for (i = 0; i < clkc_data->hw_onecell_data->num; i++) { + for (i = 0; i < axg_hw_onecell_data.num; i++) { /* array might be sparse */ - if (!clkc_data->hw_onecell_data->hws[i]) + if (!axg_hw_onecell_data.hws[i]) continue; - ret = devm_clk_hw_register(dev, - clkc_data->hw_onecell_data->hws[i]); + ret = devm_clk_hw_register(dev, axg_hw_onecell_data.hws[i]); if (ret) { dev_err(dev, "Clock registration failed\n"); return ret; @@ -839,7 +842,7 @@ static int axg_clkc_probe(struct platform_device *pdev) } return devm_of_clk_add_hw_provider(dev, of_clk_hw_onecell_get, - clkc_data->hw_onecell_data); + &axg_hw_onecell_data); } static struct platform_driver axg_driver = { diff --git a/drivers/clk/meson/clk-pll.c b/drivers/clk/meson/clk-pll.c index 218c769c6d50..f3d909719111 100644 --- a/drivers/clk/meson/clk-pll.c +++ b/drivers/clk/meson/clk-pll.c @@ -42,52 +42,36 @@ #include "clkc.h" -#define MESON_PLL_RESET BIT(29) -#define MESON_PLL_LOCK BIT(31) - -#define to_meson_clk_pll(_hw) container_of(_hw, struct meson_clk_pll, hw) +static inline struct meson_clk_pll_data * +meson_clk_pll_data(struct clk_regmap *clk) +{ + return (struct meson_clk_pll_data *)clk->data; +} static unsigned long meson_clk_pll_recalc_rate(struct clk_hw *hw, unsigned long parent_rate) { - struct meson_clk_pll *pll = to_meson_clk_pll(hw); - struct parm *p; + struct clk_regmap *clk = to_clk_regmap(hw); + struct meson_clk_pll_data *pll = meson_clk_pll_data(clk); u64 rate; u16 n, m, frac = 0, od, od2 = 0, od3 = 0; - u32 reg; - - p = &pll->n; - reg = readl(pll->base + p->reg_off); - n = PARM_GET(p->width, p->shift, reg); - p = &pll->m; - reg = readl(pll->base + p->reg_off); - m = PARM_GET(p->width, p->shift, reg); + n = meson_parm_read(clk->map, &pll->n); + m = meson_parm_read(clk->map, &pll->m); + od = meson_parm_read(clk->map, &pll->od); - p = &pll->od; - reg = readl(pll->base + p->reg_off); - od = PARM_GET(p->width, p->shift, reg); + if (MESON_PARM_APPLICABLE(&pll->od2)) + od2 = meson_parm_read(clk->map, &pll->od2); - p = &pll->od2; - if (p->width) { - reg = readl(pll->base + p->reg_off); - od2 = PARM_GET(p->width, p->shift, reg); - } - - p = &pll->od3; - if (p->width) { - reg = readl(pll->base + p->reg_off); - od3 = PARM_GET(p->width, p->shift, reg); - } + if (MESON_PARM_APPLICABLE(&pll->od3)) + od3 = meson_parm_read(clk->map, &pll->od3); rate = (u64)m * parent_rate; - p = &pll->frac; - if (p->width) { - reg = readl(pll->base + p->reg_off); - frac = PARM_GET(p->width, p->shift, reg); + if (MESON_PARM_APPLICABLE(&pll->frac)) { + frac = meson_parm_read(clk->map, &pll->frac); - rate += mul_u64_u32_shr(parent_rate, frac, p->width); + rate += mul_u64_u32_shr(parent_rate, frac, pll->frac.width); } return div_u64(rate, n) >> od >> od2 >> od3; @@ -96,177 +80,136 @@ static unsigned long meson_clk_pll_recalc_rate(struct clk_hw *hw, static long meson_clk_pll_round_rate(struct clk_hw *hw, unsigned long rate, unsigned long *parent_rate) { - struct meson_clk_pll *pll = to_meson_clk_pll(hw); - const struct pll_rate_table *rate_table = pll->rate_table; - int i; + struct clk_regmap *clk = to_clk_regmap(hw); + struct meson_clk_pll_data *pll = meson_clk_pll_data(clk); + const struct pll_rate_table *pllt; /* * if the table is missing, just return the current rate * since we don't have the other available frequencies */ - if (!rate_table) + if (!pll->table) return meson_clk_pll_recalc_rate(hw, *parent_rate); - for (i = 0; i < pll->rate_count; i++) { - if (rate <= rate_table[i].rate) - return rate_table[i].rate; + for (pllt = pll->table; pllt->rate; pllt++) { + if (rate <= pllt->rate) + return pllt->rate; } /* else return the smallest value */ - return rate_table[0].rate; + return pll->table[0].rate; } -static const struct pll_rate_table *meson_clk_get_pll_settings(struct meson_clk_pll *pll, - unsigned long rate) +static const struct pll_rate_table * +meson_clk_get_pll_settings(const struct pll_rate_table *table, + unsigned long rate) { - const struct pll_rate_table *rate_table = pll->rate_table; - int i; + const struct pll_rate_table *pllt; - if (!rate_table) + if (!table) return NULL; - for (i = 0; i < pll->rate_count; i++) { - if (rate == rate_table[i].rate) - return &rate_table[i]; + for (pllt = table; pllt->rate; pllt++) { + if (rate == pllt->rate) + return pllt; } + return NULL; } -/* Specific wait loop for GXL/GXM GP0 PLL */ -static int meson_clk_pll_wait_lock_reset(struct meson_clk_pll *pll, - struct parm *p_n) +static int meson_clk_pll_wait_lock(struct clk_hw *hw) { - int delay = 100; - u32 reg; - - while (delay > 0) { - reg = readl(pll->base + p_n->reg_off); - writel(reg | MESON_PLL_RESET, pll->base + p_n->reg_off); - udelay(10); - writel(reg & ~MESON_PLL_RESET, pll->base + p_n->reg_off); - - /* This delay comes from AMLogic tree clk-gp0-gxl driver */ - mdelay(1); - - reg = readl(pll->base + p_n->reg_off); - if (reg & MESON_PLL_LOCK) + struct clk_regmap *clk = to_clk_regmap(hw); + struct meson_clk_pll_data *pll = meson_clk_pll_data(clk); + int delay = pll->flags & CLK_MESON_PLL_LOCK_LOOP_RST ? + 100 : 24000000; + + do { + /* Specific wait loop for GXL/GXM GP0 PLL */ + if (pll->flags & CLK_MESON_PLL_LOCK_LOOP_RST) { + /* Procedure taken from the vendor kernel */ + meson_parm_write(clk->map, &pll->rst, 1); + udelay(10); + meson_parm_write(clk->map, &pll->rst, 0); + mdelay(1); + } + + /* Is the clock locked now ? */ + if (meson_parm_read(clk->map, &pll->l)) return 0; - delay--; - } - return -ETIMEDOUT; -} -static int meson_clk_pll_wait_lock(struct meson_clk_pll *pll, - struct parm *p_n) -{ - int delay = 24000000; - u32 reg; - - while (delay > 0) { - reg = readl(pll->base + p_n->reg_off); - - if (reg & MESON_PLL_LOCK) - return 0; delay--; - } + } while (delay > 0); + return -ETIMEDOUT; } -static void meson_clk_pll_init_params(struct meson_clk_pll *pll) +static void meson_clk_pll_init(struct clk_hw *hw) { - int i; - - for (i = 0 ; i < pll->params.params_count ; ++i) - writel(pll->params.params_table[i].value, - pll->base + pll->params.params_table[i].reg_off); + struct clk_regmap *clk = to_clk_regmap(hw); + struct meson_clk_pll_data *pll = meson_clk_pll_data(clk); + + if (pll->init_count) { + meson_parm_write(clk->map, &pll->rst, 1); + regmap_multi_reg_write(clk->map, pll->init_regs, + pll->init_count); + meson_parm_write(clk->map, &pll->rst, 0); + } } static int meson_clk_pll_set_rate(struct clk_hw *hw, unsigned long rate, unsigned long parent_rate) { - struct meson_clk_pll *pll = to_meson_clk_pll(hw); - struct parm *p; - const struct pll_rate_table *rate_set; + struct clk_regmap *clk = to_clk_regmap(hw); + struct meson_clk_pll_data *pll = meson_clk_pll_data(clk); + const struct pll_rate_table *pllt; unsigned long old_rate; - int ret = 0; - u32 reg; if (parent_rate == 0 || rate == 0) return -EINVAL; old_rate = rate; - rate_set = meson_clk_get_pll_settings(pll, rate); - if (!rate_set) + pllt = meson_clk_get_pll_settings(pll->table, rate); + if (!pllt) return -EINVAL; - /* Initialize the PLL in a clean state if specified */ - if (pll->params.params_count) - meson_clk_pll_init_params(pll); - - /* PLL reset */ - p = &pll->n; - reg = readl(pll->base + p->reg_off); - /* If no_init_reset is provided, avoid resetting at this point */ - if (!pll->params.no_init_reset) - writel(reg | MESON_PLL_RESET, pll->base + p->reg_off); - - reg = PARM_SET(p->width, p->shift, reg, rate_set->n); - writel(reg, pll->base + p->reg_off); - - p = &pll->m; - reg = readl(pll->base + p->reg_off); - reg = PARM_SET(p->width, p->shift, reg, rate_set->m); - writel(reg, pll->base + p->reg_off); - - p = &pll->od; - reg = readl(pll->base + p->reg_off); - reg = PARM_SET(p->width, p->shift, reg, rate_set->od); - writel(reg, pll->base + p->reg_off); - - p = &pll->od2; - if (p->width) { - reg = readl(pll->base + p->reg_off); - reg = PARM_SET(p->width, p->shift, reg, rate_set->od2); - writel(reg, pll->base + p->reg_off); - } + /* Put the pll in reset to write the params */ + meson_parm_write(clk->map, &pll->rst, 1); - p = &pll->od3; - if (p->width) { - reg = readl(pll->base + p->reg_off); - reg = PARM_SET(p->width, p->shift, reg, rate_set->od3); - writel(reg, pll->base + p->reg_off); - } + meson_parm_write(clk->map, &pll->n, pllt->n); + meson_parm_write(clk->map, &pll->m, pllt->m); + meson_parm_write(clk->map, &pll->od, pllt->od); - p = &pll->frac; - if (p->width) { - reg = readl(pll->base + p->reg_off); - reg = PARM_SET(p->width, p->shift, reg, rate_set->frac); - writel(reg, pll->base + p->reg_off); - } + if (MESON_PARM_APPLICABLE(&pll->od2)) + meson_parm_write(clk->map, &pll->od2, pllt->od2); - p = &pll->n; - /* If clear_reset_for_lock is provided, remove the reset bit here */ - if (pll->params.clear_reset_for_lock) { - reg = readl(pll->base + p->reg_off); - writel(reg & ~MESON_PLL_RESET, pll->base + p->reg_off); - } + if (MESON_PARM_APPLICABLE(&pll->od3)) + meson_parm_write(clk->map, &pll->od3, pllt->od3); + + if (MESON_PARM_APPLICABLE(&pll->frac)) + meson_parm_write(clk->map, &pll->frac, pllt->frac); + + /* make sure the reset is cleared at this point */ + meson_parm_write(clk->map, &pll->rst, 0); - /* If reset_lock_loop, use a special loop including resetting */ - if (pll->params.reset_lock_loop) - ret = meson_clk_pll_wait_lock_reset(pll, p); - else - ret = meson_clk_pll_wait_lock(pll, p); - if (ret) { + if (meson_clk_pll_wait_lock(hw)) { pr_warn("%s: pll did not lock, trying to restore old rate %lu\n", __func__, old_rate); + /* + * FIXME: Do we really need/want this HACK ? + * It looks unsafe. what happens if the clock gets into a + * broken state and we can't lock back on the old_rate ? Looks + * like an infinite recursion is possible + */ meson_clk_pll_set_rate(hw, old_rate, parent_rate); } - return ret; + return 0; } const struct clk_ops meson_clk_pll_ops = { + .init = meson_clk_pll_init, .recalc_rate = meson_clk_pll_recalc_rate, .round_rate = meson_clk_pll_round_rate, .set_rate = meson_clk_pll_set_rate, diff --git a/drivers/clk/meson/clkc.h b/drivers/clk/meson/clkc.h index a4a526cbca4c..f0d70eaffcf3 100644 --- a/drivers/clk/meson/clkc.h +++ b/drivers/clk/meson/clkc.h @@ -82,41 +82,21 @@ struct pll_rate_table { .frac = (_frac), \ } \ -struct pll_params_table { - unsigned int reg_off; - unsigned int value; -}; - -#define PLL_PARAM(_reg, _val) \ - { \ - .reg_off = (_reg), \ - .value = (_val), \ - } - -struct pll_setup_params { - struct pll_params_table *params_table; - unsigned int params_count; - /* Workaround for GP0, do not reset before configuring */ - bool no_init_reset; - /* Workaround for GP0, unreset right before checking for lock */ - bool clear_reset_for_lock; - /* Workaround for GXL GP0, reset in the lock checking loop */ - bool reset_lock_loop; -}; +#define CLK_MESON_PLL_LOCK_LOOP_RST BIT(0) -struct meson_clk_pll { - struct clk_hw hw; - void __iomem *base; +struct meson_clk_pll_data { struct parm m; struct parm n; struct parm frac; struct parm od; struct parm od2; struct parm od3; - const struct pll_setup_params params; - const struct pll_rate_table *rate_table; - unsigned int rate_count; - spinlock_t *lock; + struct parm l; + struct parm rst; + const struct reg_sequence *init_regs; + unsigned int init_count; + const struct pll_rate_table *table; + u8 flags; }; #define to_meson_clk_pll(_hw) container_of(_hw, struct meson_clk_pll, hw) diff --git a/drivers/clk/meson/gxbb.c b/drivers/clk/meson/gxbb.c index 196557f11608..49f5716ce8b6 100644 --- a/drivers/clk/meson/gxbb.c +++ b/drivers/clk/meson/gxbb.c @@ -188,28 +188,39 @@ static const struct pll_rate_table gxl_gp0_pll_rate_table[] = { { /* sentinel */ }, }; -static struct meson_clk_pll gxbb_fixed_pll = { - .m = { - .reg_off = HHI_MPLL_CNTL, - .shift = 0, - .width = 9, - }, - .n = { - .reg_off = HHI_MPLL_CNTL, - .shift = 9, - .width = 5, - }, - .od = { - .reg_off = HHI_MPLL_CNTL, - .shift = 16, - .width = 2, - }, - .frac = { - .reg_off = HHI_MPLL_CNTL2, - .shift = 0, - .width = 12, - }, - .lock = &meson_clk_lock, +static struct clk_regmap gxbb_fixed_pll = { + .data = &(struct meson_clk_pll_data){ + .m = { + .reg_off = HHI_MPLL_CNTL, + .shift = 0, + .width = 9, + }, + .n = { + .reg_off = HHI_MPLL_CNTL, + .shift = 9, + .width = 5, + }, + .od = { + .reg_off = HHI_MPLL_CNTL, + .shift = 16, + .width = 2, + }, + .frac = { + .reg_off = HHI_MPLL_CNTL2, + .shift = 0, + .width = 12, + }, + .l = { + .reg_off = HHI_MPLL_CNTL, + .shift = 31, + .width = 1, + }, + .rst = { + .reg_off = HHI_MPLL_CNTL, + .shift = 29, + .width = 1, + }, + }, .hw.init = &(struct clk_init_data){ .name = "fixed_pll", .ops = &meson_clk_pll_ro_ops, @@ -230,38 +241,49 @@ static struct clk_fixed_factor gxbb_hdmi_pll_pre_mult = { }, }; -static struct meson_clk_pll gxbb_hdmi_pll = { - .m = { - .reg_off = HHI_HDMI_PLL_CNTL, - .shift = 0, - .width = 9, - }, - .n = { - .reg_off = HHI_HDMI_PLL_CNTL, - .shift = 9, - .width = 5, - }, - .frac = { - .reg_off = HHI_HDMI_PLL_CNTL2, - .shift = 0, - .width = 12, - }, - .od = { - .reg_off = HHI_HDMI_PLL_CNTL2, - .shift = 16, - .width = 2, - }, - .od2 = { - .reg_off = HHI_HDMI_PLL_CNTL2, - .shift = 22, - .width = 2, - }, - .od3 = { - .reg_off = HHI_HDMI_PLL_CNTL2, - .shift = 18, - .width = 2, +static struct clk_regmap gxbb_hdmi_pll = { + .data = &(struct meson_clk_pll_data){ + .m = { + .reg_off = HHI_HDMI_PLL_CNTL, + .shift = 0, + .width = 9, + }, + .n = { + .reg_off = HHI_HDMI_PLL_CNTL, + .shift = 9, + .width = 5, + }, + .frac = { + .reg_off = HHI_HDMI_PLL_CNTL2, + .shift = 0, + .width = 12, + }, + .od = { + .reg_off = HHI_HDMI_PLL_CNTL2, + .shift = 16, + .width = 2, + }, + .od2 = { + .reg_off = HHI_HDMI_PLL_CNTL2, + .shift = 22, + .width = 2, + }, + .od3 = { + .reg_off = HHI_HDMI_PLL_CNTL2, + .shift = 18, + .width = 2, + }, + .l = { + .reg_off = HHI_HDMI_PLL_CNTL, + .shift = 31, + .width = 1, + }, + .rst = { + .reg_off = HHI_HDMI_PLL_CNTL, + .shift = 28, + .width = 1, + }, }, - .lock = &meson_clk_lock, .hw.init = &(struct clk_init_data){ .name = "hdmi_pll", .ops = &meson_clk_pll_ro_ops, @@ -271,43 +293,55 @@ static struct meson_clk_pll gxbb_hdmi_pll = { }, }; -static struct meson_clk_pll gxl_hdmi_pll = { - .m = { - .reg_off = HHI_HDMI_PLL_CNTL, - .shift = 0, - .width = 9, - }, - .n = { - .reg_off = HHI_HDMI_PLL_CNTL, - .shift = 9, - .width = 5, +static struct clk_regmap gxl_hdmi_pll = { + .data = &(struct meson_clk_pll_data){ + .m = { + .reg_off = HHI_HDMI_PLL_CNTL, + .shift = 0, + .width = 9, + }, + .n = { + .reg_off = HHI_HDMI_PLL_CNTL, + .shift = 9, + .width = 5, + }, + .frac = { + /* + * On gxl, there is a register shift due to + * HHI_HDMI_PLL_CNTL1 which does not exist on gxbb, + * so we compute the register offset based on the PLL + * base to get it right + */ + .reg_off = HHI_HDMI_PLL_CNTL + 4, + .shift = 0, + .width = 12, + }, + .od = { + .reg_off = HHI_HDMI_PLL_CNTL + 8, + .shift = 21, + .width = 2, + }, + .od2 = { + .reg_off = HHI_HDMI_PLL_CNTL + 8, + .shift = 23, + .width = 2, + }, + .od3 = { + .reg_off = HHI_HDMI_PLL_CNTL + 8, + .shift = 19, + .width = 2, + }, + .l = { + .reg_off = HHI_HDMI_PLL_CNTL, + .shift = 31, + .width = 1, + }, + .rst = { + .reg_off = HHI_HDMI_PLL_CNTL, + .shift = 29, + .width = 1, + }, }, - .frac = { - /* - * On gxl, there is a register shift due to HHI_HDMI_PLL_CNTL1 - * which does not exist on gxbb, so we compute the register - * offset based on the PLL base to get it right - */ - .reg_off = HHI_HDMI_PLL_CNTL + 4, - .shift = 0, - .width = 12, - }, - .od = { - .reg_off = HHI_HDMI_PLL_CNTL + 8, - .shift = 21, - .width = 2, - }, - .od2 = { - .reg_off = HHI_HDMI_PLL_CNTL + 8, - .shift = 23, - .width = 2, - }, - .od3 = { - .reg_off = HHI_HDMI_PLL_CNTL + 8, - .shift = 19, - .width = 2, - }, - .lock = &meson_clk_lock, .hw.init = &(struct clk_init_data){ .name = "hdmi_pll", .ops = &meson_clk_pll_ro_ops, @@ -317,23 +351,34 @@ static struct meson_clk_pll gxl_hdmi_pll = { }, }; -static struct meson_clk_pll gxbb_sys_pll = { - .m = { - .reg_off = HHI_SYS_PLL_CNTL, - .shift = 0, - .width = 9, - }, - .n = { - .reg_off = HHI_SYS_PLL_CNTL, - .shift = 9, - .width = 5, - }, - .od = { - .reg_off = HHI_SYS_PLL_CNTL, - .shift = 10, - .width = 2, +static struct clk_regmap gxbb_sys_pll = { + .data = &(struct meson_clk_pll_data){ + .m = { + .reg_off = HHI_SYS_PLL_CNTL, + .shift = 0, + .width = 9, + }, + .n = { + .reg_off = HHI_SYS_PLL_CNTL, + .shift = 9, + .width = 5, + }, + .od = { + .reg_off = HHI_SYS_PLL_CNTL, + .shift = 10, + .width = 2, + }, + .l = { + .reg_off = HHI_SYS_PLL_CNTL, + .shift = 31, + .width = 1, + }, + .rst = { + .reg_off = HHI_SYS_PLL_CNTL, + .shift = 29, + .width = 1, + }, }, - .lock = &meson_clk_lock, .hw.init = &(struct clk_init_data){ .name = "sys_pll", .ops = &meson_clk_pll_ro_ops, @@ -343,38 +388,44 @@ static struct meson_clk_pll gxbb_sys_pll = { }, }; -struct pll_params_table gxbb_gp0_params_table[] = { - PLL_PARAM(HHI_GP0_PLL_CNTL, 0x6a000228), - PLL_PARAM(HHI_GP0_PLL_CNTL2, 0x69c80000), - PLL_PARAM(HHI_GP0_PLL_CNTL3, 0x0a5590c4), - PLL_PARAM(HHI_GP0_PLL_CNTL4, 0x0000500d), +const struct reg_sequence gxbb_gp0_init_regs[] = { + { .reg = HHI_GP0_PLL_CNTL, .def = 0x6a000228 }, + { .reg = HHI_GP0_PLL_CNTL2, .def = 0x69c80000 }, + { .reg = HHI_GP0_PLL_CNTL3, .def = 0x0a5590c4 }, + { .reg = HHI_GP0_PLL_CNTL4, .def = 0x0000500d }, }; -static struct meson_clk_pll gxbb_gp0_pll = { - .m = { - .reg_off = HHI_GP0_PLL_CNTL, - .shift = 0, - .width = 9, - }, - .n = { - .reg_off = HHI_GP0_PLL_CNTL, - .shift = 9, - .width = 5, - }, - .od = { - .reg_off = HHI_GP0_PLL_CNTL, - .shift = 16, - .width = 2, - }, - .params = { - .params_table = gxbb_gp0_params_table, - .params_count = ARRAY_SIZE(gxbb_gp0_params_table), - .no_init_reset = true, - .clear_reset_for_lock = true, +static struct clk_regmap gxbb_gp0_pll = { + .data = &(struct meson_clk_pll_data){ + .m = { + .reg_off = HHI_GP0_PLL_CNTL, + .shift = 0, + .width = 9, + }, + .n = { + .reg_off = HHI_GP0_PLL_CNTL, + .shift = 9, + .width = 5, + }, + .od = { + .reg_off = HHI_GP0_PLL_CNTL, + .shift = 16, + .width = 2, + }, + .l = { + .reg_off = HHI_GP0_PLL_CNTL, + .shift = 31, + .width = 1, + }, + .rst = { + .reg_off = HHI_GP0_PLL_CNTL, + .shift = 29, + .width = 1, + }, + .table = gxbb_gp0_pll_rate_table, + .init_regs = gxbb_gp0_init_regs, + .init_count = ARRAY_SIZE(gxbb_gp0_init_regs), }, - .rate_table = gxbb_gp0_pll_rate_table, - .rate_count = ARRAY_SIZE(gxbb_gp0_pll_rate_table), - .lock = &meson_clk_lock, .hw.init = &(struct clk_init_data){ .name = "gp0_pll", .ops = &meson_clk_pll_ops, @@ -384,40 +435,47 @@ static struct meson_clk_pll gxbb_gp0_pll = { }, }; -struct pll_params_table gxl_gp0_params_table[] = { - PLL_PARAM(HHI_GP0_PLL_CNTL, 0x40010250), - PLL_PARAM(HHI_GP0_PLL_CNTL1, 0xc084a000), - PLL_PARAM(HHI_GP0_PLL_CNTL2, 0xb75020be), - PLL_PARAM(HHI_GP0_PLL_CNTL3, 0x0a59a288), - PLL_PARAM(HHI_GP0_PLL_CNTL4, 0xc000004d), - PLL_PARAM(HHI_GP0_PLL_CNTL5, 0x00078000), +const struct reg_sequence gxl_gp0_init_regs[] = { + { .reg = HHI_GP0_PLL_CNTL, .def = 0x40010250 }, + { .reg = HHI_GP0_PLL_CNTL1, .def = 0xc084a000 }, + { .reg = HHI_GP0_PLL_CNTL2, .def = 0xb75020be }, + { .reg = HHI_GP0_PLL_CNTL3, .def = 0x0a59a288 }, + { .reg = HHI_GP0_PLL_CNTL4, .def = 0xc000004d }, + { .reg = HHI_GP0_PLL_CNTL5, .def = 0x00078000 }, }; -static struct meson_clk_pll gxl_gp0_pll = { - .m = { - .reg_off = HHI_GP0_PLL_CNTL, - .shift = 0, - .width = 9, - }, - .n = { - .reg_off = HHI_GP0_PLL_CNTL, - .shift = 9, - .width = 5, - }, - .od = { - .reg_off = HHI_GP0_PLL_CNTL, - .shift = 16, - .width = 2, - }, - .params = { - .params_table = gxl_gp0_params_table, - .params_count = ARRAY_SIZE(gxl_gp0_params_table), - .no_init_reset = true, - .reset_lock_loop = true, +static struct clk_regmap gxl_gp0_pll = { + .data = &(struct meson_clk_pll_data){ + .m = { + .reg_off = HHI_GP0_PLL_CNTL, + .shift = 0, + .width = 9, + }, + .n = { + .reg_off = HHI_GP0_PLL_CNTL, + .shift = 9, + .width = 5, + }, + .od = { + .reg_off = HHI_GP0_PLL_CNTL, + .shift = 16, + .width = 2, + }, + .l = { + .reg_off = HHI_GP0_PLL_CNTL, + .shift = 31, + .width = 1, + }, + .rst = { + .reg_off = HHI_GP0_PLL_CNTL, + .shift = 29, + .width = 1, + }, + .table = gxl_gp0_pll_rate_table, + .init_regs = gxl_gp0_init_regs, + .init_count = ARRAY_SIZE(gxl_gp0_init_regs), + .flags = CLK_MESON_PLL_LOCK_LOOP_RST, }, - .rate_table = gxl_gp0_pll_rate_table, - .rate_count = ARRAY_SIZE(gxl_gp0_pll_rate_table), - .lock = &meson_clk_lock, .hw.init = &(struct clk_init_data){ .name = "gp0_pll", .ops = &meson_clk_pll_ops, @@ -1762,20 +1820,14 @@ static struct clk_hw_onecell_data gxl_hw_onecell_data = { .num = NR_CLKS, }; -/* Convenience tables to populate base addresses in .probe */ - -static struct meson_clk_pll *const gxbb_clk_plls[] = { - &gxbb_fixed_pll, - &gxbb_hdmi_pll, - &gxbb_sys_pll, +static struct clk_regmap *const gxbb_clk_regmaps[] = { &gxbb_gp0_pll, + &gxbb_hdmi_pll, }; -static struct meson_clk_pll *const gxl_clk_plls[] = { - &gxbb_fixed_pll, - &gxl_hdmi_pll, - &gxbb_sys_pll, +static struct clk_regmap *const gxl_clk_regmaps[] = { &gxl_gp0_pll, + &gxl_hdmi_pll, }; static struct clk_regmap *const gx_clk_regmaps[] = { @@ -1910,23 +1962,25 @@ static struct clk_regmap *const gx_clk_regmaps[] = { &gxbb_mpll1, &gxbb_mpll2, &gxbb_cts_amclk_div, + &gxbb_fixed_pll, + &gxbb_sys_pll, }; struct clkc_data { - struct meson_clk_pll *const *clk_plls; - unsigned int clk_plls_count; + struct clk_regmap *const *regmap_clks; + unsigned int regmap_clks_count; struct clk_hw_onecell_data *hw_onecell_data; }; static const struct clkc_data gxbb_clkc_data = { - .clk_plls = gxbb_clk_plls, - .clk_plls_count = ARRAY_SIZE(gxbb_clk_plls), + .regmap_clks = gxbb_clk_regmaps, + .regmap_clks_count = ARRAY_SIZE(gxbb_clk_regmaps), .hw_onecell_data = &gxbb_hw_onecell_data, }; static const struct clkc_data gxl_clkc_data = { - .clk_plls = gxl_clk_plls, - .clk_plls_count = ARRAY_SIZE(gxl_clk_plls), + .regmap_clks = gxl_clk_regmaps, + .regmap_clks_count = ARRAY_SIZE(gxl_clk_regmaps), .hw_onecell_data = &gxl_hw_onecell_data, }; @@ -1969,14 +2023,14 @@ static int gxbb_clkc_probe(struct platform_device *pdev) if (IS_ERR(map)) return PTR_ERR(map); - /* Populate base address for PLLs */ - for (i = 0; i < clkc_data->clk_plls_count; i++) - clkc_data->clk_plls[i]->base = clk_base; - /* Populate regmap for the common regmap backed clocks */ for (i = 0; i < ARRAY_SIZE(gx_clk_regmaps); i++) gx_clk_regmaps[i]->map = map; + /* Populate regmap for soc specific clocks */ + for (i = 0; i < clkc_data->regmap_clks_count; i++) + clkc_data->regmap_clks[i]->map = map; + /* Register all clks */ for (i = 0; i < clkc_data->hw_onecell_data->num; i++) { /* array might be sparse */ diff --git a/drivers/clk/meson/meson8b.c b/drivers/clk/meson/meson8b.c index 4bb51c8f3102..4fd8253c54bb 100644 --- a/drivers/clk/meson/meson8b.c +++ b/drivers/clk/meson/meson8b.c @@ -122,23 +122,34 @@ static struct clk_fixed_rate meson8b_xtal = { }, }; -static struct meson_clk_pll meson8b_fixed_pll = { - .m = { - .reg_off = HHI_MPLL_CNTL, - .shift = 0, - .width = 9, - }, - .n = { - .reg_off = HHI_MPLL_CNTL, - .shift = 9, - .width = 5, - }, - .od = { - .reg_off = HHI_MPLL_CNTL, - .shift = 16, - .width = 2, - }, - .lock = &meson_clk_lock, +static struct clk_regmap meson8b_fixed_pll = { + .data = &(struct meson_clk_pll_data){ + .m = { + .reg_off = HHI_MPLL_CNTL, + .shift = 0, + .width = 9, + }, + .n = { + .reg_off = HHI_MPLL_CNTL, + .shift = 9, + .width = 5, + }, + .od = { + .reg_off = HHI_MPLL_CNTL, + .shift = 16, + .width = 2, + }, + .l = { + .reg_off = HHI_MPLL_CNTL, + .shift = 31, + .width = 1, + }, + .rst = { + .reg_off = HHI_MPLL_CNTL, + .shift = 29, + .width = 1, + }, + }, .hw.init = &(struct clk_init_data){ .name = "fixed_pll", .ops = &meson_clk_pll_ro_ops, @@ -148,23 +159,34 @@ static struct meson_clk_pll meson8b_fixed_pll = { }, }; -static struct meson_clk_pll meson8b_vid_pll = { - .m = { - .reg_off = HHI_VID_PLL_CNTL, - .shift = 0, - .width = 9, - }, - .n = { - .reg_off = HHI_VID_PLL_CNTL, - .shift = 9, - .width = 5, - }, - .od = { - .reg_off = HHI_VID_PLL_CNTL, - .shift = 16, - .width = 2, +static struct clk_regmap meson8b_vid_pll = { + .data = &(struct meson_clk_pll_data){ + .m = { + .reg_off = HHI_VID_PLL_CNTL, + .shift = 0, + .width = 9, + }, + .n = { + .reg_off = HHI_VID_PLL_CNTL, + .shift = 9, + .width = 5, + }, + .od = { + .reg_off = HHI_VID_PLL_CNTL, + .shift = 16, + .width = 2, + }, + .l = { + .reg_off = HHI_VID_PLL_CNTL, + .shift = 31, + .width = 1, + }, + .rst = { + .reg_off = HHI_VID_PLL_CNTL, + .shift = 29, + .width = 1, + }, }, - .lock = &meson_clk_lock, .hw.init = &(struct clk_init_data){ .name = "vid_pll", .ops = &meson_clk_pll_ro_ops, @@ -174,25 +196,35 @@ static struct meson_clk_pll meson8b_vid_pll = { }, }; -static struct meson_clk_pll meson8b_sys_pll = { - .m = { - .reg_off = HHI_SYS_PLL_CNTL, - .shift = 0, - .width = 9, - }, - .n = { - .reg_off = HHI_SYS_PLL_CNTL, - .shift = 9, - .width = 5, - }, - .od = { - .reg_off = HHI_SYS_PLL_CNTL, - .shift = 16, - .width = 2, - }, - .rate_table = sys_pll_rate_table, - .rate_count = ARRAY_SIZE(sys_pll_rate_table), - .lock = &meson_clk_lock, +static struct clk_regmap meson8b_sys_pll = { + .data = &(struct meson_clk_pll_data){ + .m = { + .reg_off = HHI_SYS_PLL_CNTL, + .shift = 0, + .width = 9, + }, + .n = { + .reg_off = HHI_SYS_PLL_CNTL, + .shift = 9, + .width = 5, + }, + .od = { + .reg_off = HHI_SYS_PLL_CNTL, + .shift = 16, + .width = 2, + }, + .l = { + .reg_off = HHI_SYS_PLL_CNTL, + .shift = 31, + .width = 1, + }, + .rst = { + .reg_off = HHI_SYS_PLL_CNTL, + .shift = 29, + .width = 1, + }, + .table = sys_pll_rate_table, + }, .hw.init = &(struct clk_init_data){ .name = "sys_pll", .ops = &meson_clk_pll_ops, @@ -613,12 +645,6 @@ static struct clk_hw_onecell_data meson8b_hw_onecell_data = { .num = CLK_NR_CLKS, }; -static struct meson_clk_pll *const meson8b_clk_plls[] = { - &meson8b_fixed_pll, - &meson8b_vid_pll, - &meson8b_sys_pll, -}; - static struct clk_regmap *const meson8b_clk_regmaps[] = { &meson8b_clk81, &meson8b_ddr, @@ -703,6 +729,9 @@ static struct clk_regmap *const meson8b_clk_regmaps[] = { &meson8b_mpll0, &meson8b_mpll1, &meson8b_mpll2, + &meson8b_fixed_pll, + &meson8b_vid_pll, + &meson8b_sys_pll, }; static const struct meson8b_clk_reset_line { @@ -825,10 +854,6 @@ static int meson8b_clkc_probe(struct platform_device *pdev) if (IS_ERR(map)) return PTR_ERR(map); - /* Populate base address for PLLs */ - for (i = 0; i < ARRAY_SIZE(meson8b_clk_plls); i++) - meson8b_clk_plls[i]->base = clk_base; - /* Populate the base address for CPU clk */ meson8b_cpu_clk.base = clk_base; -- cgit v1.2.3 From d610b54f77002bbddca54c10d9488c2faa7ff102 Mon Sep 17 00:00:00 2001 From: Jerome Brunet Date: Mon, 12 Feb 2018 15:58:43 +0100 Subject: clk: meson: split divider and gate part of mpll The mpll clock is a kind of fractional divider which can gate. When the RW operation have been added, enable/disable ops have been mistakenly inserted in this driver. These ops are essentially a poor copy/paste of the generic gate ops. This change removes the gate ops from the mpll driver and inserts a generic gate clock on each mpll divider, simplifying the mpll driver and reducing code duplication. Signed-off-by: Jerome Brunet Signed-off-by: Neil Armstrong --- drivers/clk/meson/axg.c | 100 +++++++++++++++++++++++++++++++------------ drivers/clk/meson/axg.h | 6 ++- drivers/clk/meson/clk-mpll.c | 44 ------------------- drivers/clk/meson/clkc.h | 1 - drivers/clk/meson/gxbb.c | 78 ++++++++++++++++++++++++--------- drivers/clk/meson/gxbb.h | 5 ++- drivers/clk/meson/meson8b.c | 75 +++++++++++++++++++++++--------- drivers/clk/meson/meson8b.h | 6 ++- 8 files changed, 197 insertions(+), 118 deletions(-) diff --git a/drivers/clk/meson/axg.c b/drivers/clk/meson/axg.c index 8c27ceffda4a..6813b632c1a9 100644 --- a/drivers/clk/meson/axg.c +++ b/drivers/clk/meson/axg.c @@ -296,7 +296,7 @@ static struct clk_fixed_factor axg_fclk_div7 = { }, }; -static struct clk_regmap axg_mpll0 = { +static struct clk_regmap axg_mpll0_div = { .data = &(struct meson_clk_mpll_data){ .sdm = { .reg_off = HHI_MPLL_CNTL7, @@ -313,11 +313,6 @@ static struct clk_regmap axg_mpll0 = { .shift = 16, .width = 9, }, - .en = { - .reg_off = HHI_MPLL_CNTL7, - .shift = 14, - .width = 1, - }, .ssen = { .reg_off = HHI_MPLL_CNTL, .shift = 25, @@ -331,14 +326,28 @@ static struct clk_regmap axg_mpll0 = { .lock = &meson_clk_lock, }, .hw.init = &(struct clk_init_data){ - .name = "mpll0", + .name = "mpll0_div", .ops = &meson_clk_mpll_ops, .parent_names = (const char *[]){ "fixed_pll" }, .num_parents = 1, }, }; -static struct clk_regmap axg_mpll1 = { +static struct clk_regmap axg_mpll0 = { + .data = &(struct clk_regmap_gate_data){ + .offset = HHI_MPLL_CNTL7, + .bit_idx = 14, + }, + .hw.init = &(struct clk_init_data){ + .name = "mpll0", + .ops = &clk_regmap_gate_ops, + .parent_names = (const char *[]){ "mpll0_div" }, + .num_parents = 1, + .flags = CLK_SET_RATE_PARENT, + }, +}; + +static struct clk_regmap axg_mpll1_div = { .data = &(struct meson_clk_mpll_data){ .sdm = { .reg_off = HHI_MPLL_CNTL8, @@ -355,11 +364,6 @@ static struct clk_regmap axg_mpll1 = { .shift = 16, .width = 9, }, - .en = { - .reg_off = HHI_MPLL_CNTL8, - .shift = 14, - .width = 1, - }, .misc = { .reg_off = HHI_PLL_TOP_MISC, .shift = 1, @@ -368,14 +372,28 @@ static struct clk_regmap axg_mpll1 = { .lock = &meson_clk_lock, }, .hw.init = &(struct clk_init_data){ - .name = "mpll1", + .name = "mpll1_div", .ops = &meson_clk_mpll_ops, .parent_names = (const char *[]){ "fixed_pll" }, .num_parents = 1, }, }; -static struct clk_regmap axg_mpll2 = { +static struct clk_regmap axg_mpll1 = { + .data = &(struct clk_regmap_gate_data){ + .offset = HHI_MPLL_CNTL8, + .bit_idx = 14, + }, + .hw.init = &(struct clk_init_data){ + .name = "mpll1", + .ops = &clk_regmap_gate_ops, + .parent_names = (const char *[]){ "mpll1_div" }, + .num_parents = 1, + .flags = CLK_SET_RATE_PARENT, + }, +}; + +static struct clk_regmap axg_mpll2_div = { .data = &(struct meson_clk_mpll_data){ .sdm = { .reg_off = HHI_MPLL_CNTL9, @@ -392,11 +410,6 @@ static struct clk_regmap axg_mpll2 = { .shift = 16, .width = 9, }, - .en = { - .reg_off = HHI_MPLL_CNTL9, - .shift = 14, - .width = 1, - }, .misc = { .reg_off = HHI_PLL_TOP_MISC, .shift = 2, @@ -405,14 +418,28 @@ static struct clk_regmap axg_mpll2 = { .lock = &meson_clk_lock, }, .hw.init = &(struct clk_init_data){ - .name = "mpll2", + .name = "mpll2_div", .ops = &meson_clk_mpll_ops, .parent_names = (const char *[]){ "fixed_pll" }, .num_parents = 1, }, }; -static struct clk_regmap axg_mpll3 = { +static struct clk_regmap axg_mpll2 = { + .data = &(struct clk_regmap_gate_data){ + .offset = HHI_MPLL_CNTL9, + .bit_idx = 14, + }, + .hw.init = &(struct clk_init_data){ + .name = "mpll2", + .ops = &clk_regmap_gate_ops, + .parent_names = (const char *[]){ "mpll2_div" }, + .num_parents = 1, + .flags = CLK_SET_RATE_PARENT, + }, +}; + +static struct clk_regmap axg_mpll3_div = { .data = &(struct meson_clk_mpll_data){ .sdm = { .reg_off = HHI_MPLL3_CNTL0, @@ -429,11 +456,6 @@ static struct clk_regmap axg_mpll3 = { .shift = 2, .width = 9, }, - .en = { - .reg_off = HHI_MPLL3_CNTL0, - .shift = 0, - .width = 1, - }, .misc = { .reg_off = HHI_PLL_TOP_MISC, .shift = 3, @@ -442,13 +464,27 @@ static struct clk_regmap axg_mpll3 = { .lock = &meson_clk_lock, }, .hw.init = &(struct clk_init_data){ - .name = "mpll3", + .name = "mpll3_div", .ops = &meson_clk_mpll_ops, .parent_names = (const char *[]){ "fixed_pll" }, .num_parents = 1, }, }; +static struct clk_regmap axg_mpll3 = { + .data = &(struct clk_regmap_gate_data){ + .offset = HHI_MPLL3_CNTL0, + .bit_idx = 0, + }, + .hw.init = &(struct clk_init_data){ + .name = "mpll3", + .ops = &clk_regmap_gate_ops, + .parent_names = (const char *[]){ "mpll3_div" }, + .num_parents = 1, + .flags = CLK_SET_RATE_PARENT, + }, +}; + static u32 mux_table_clk81[] = { 0, 2, 3, 4, 5, 6, 7 }; static const char * const clk81_parent_names[] = { "xtal", "fclk_div7", "mpll1", "mpll2", "fclk_div4", @@ -722,6 +758,10 @@ static struct clk_hw_onecell_data axg_hw_onecell_data = { [CLKID_SD_EMMC_C_CLK0_SEL] = &axg_sd_emmc_c_clk0_sel.hw, [CLKID_SD_EMMC_C_CLK0_DIV] = &axg_sd_emmc_c_clk0_div.hw, [CLKID_SD_EMMC_C_CLK0] = &axg_sd_emmc_c_clk0.hw, + [CLKID_MPLL0_DIV] = &axg_mpll0_div.hw, + [CLKID_MPLL1_DIV] = &axg_mpll1_div.hw, + [CLKID_MPLL2_DIV] = &axg_mpll2_div.hw, + [CLKID_MPLL3_DIV] = &axg_mpll3_div.hw, [NR_CLKS] = NULL, }, .num = NR_CLKS, @@ -786,6 +826,10 @@ static struct clk_regmap *const axg_clk_regmaps[] = { &axg_mpll1, &axg_mpll2, &axg_mpll3, + &axg_mpll0_div, + &axg_mpll1_div, + &axg_mpll2_div, + &axg_mpll3_div, &axg_fixed_pll, &axg_sys_pll, &axg_gp0_pll, diff --git a/drivers/clk/meson/axg.h b/drivers/clk/meson/axg.h index ce0bafdb6b28..4c1502a8b8c9 100644 --- a/drivers/clk/meson/axg.h +++ b/drivers/clk/meson/axg.h @@ -117,8 +117,12 @@ #define CLKID_SD_EMMC_B_CLK0_DIV 62 #define CLKID_SD_EMMC_C_CLK0_SEL 63 #define CLKID_SD_EMMC_C_CLK0_DIV 64 +#define CLKID_MPLL0_DIV 65 +#define CLKID_MPLL1_DIV 66 +#define CLKID_MPLL2_DIV 67 +#define CLKID_MPLL3_DIV 68 -#define NR_CLKS 65 +#define NR_CLKS 69 /* include the CLKIDs that have been made part of the DT binding */ #include diff --git a/drivers/clk/meson/clk-mpll.c b/drivers/clk/meson/clk-mpll.c index 66998ff47635..0df1227b65b3 100644 --- a/drivers/clk/meson/clk-mpll.c +++ b/drivers/clk/meson/clk-mpll.c @@ -170,57 +170,13 @@ static int mpll_set_rate(struct clk_hw *hw, return 0; } -static void mpll_enable_core(struct clk_hw *hw, int enable) -{ - struct clk_regmap *clk = to_clk_regmap(hw); - struct meson_clk_mpll_data *mpll = meson_clk_mpll_data(clk); - unsigned long flags = 0; - - if (mpll->lock) - spin_lock_irqsave(mpll->lock, flags); - else - __acquire(mpll->lock); - - meson_parm_write(clk->map, &mpll->en, enable ? 1 : 0); - - if (mpll->lock) - spin_unlock_irqrestore(mpll->lock, flags); - else - __release(mpll->lock); -} - - -static int mpll_enable(struct clk_hw *hw) -{ - mpll_enable_core(hw, 1); - - return 0; -} - -static void mpll_disable(struct clk_hw *hw) -{ - mpll_enable_core(hw, 0); -} - -static int mpll_is_enabled(struct clk_hw *hw) -{ - struct clk_regmap *clk = to_clk_regmap(hw); - struct meson_clk_mpll_data *mpll = meson_clk_mpll_data(clk); - - return meson_parm_read(clk->map, &mpll->en); -} - const struct clk_ops meson_clk_mpll_ro_ops = { .recalc_rate = mpll_recalc_rate, .round_rate = mpll_round_rate, - .is_enabled = mpll_is_enabled, }; const struct clk_ops meson_clk_mpll_ops = { .recalc_rate = mpll_recalc_rate, .round_rate = mpll_round_rate, .set_rate = mpll_set_rate, - .enable = mpll_enable, - .disable = mpll_disable, - .is_enabled = mpll_is_enabled, }; diff --git a/drivers/clk/meson/clkc.h b/drivers/clk/meson/clkc.h index f0d70eaffcf3..cc1a964cd4d7 100644 --- a/drivers/clk/meson/clkc.h +++ b/drivers/clk/meson/clkc.h @@ -116,7 +116,6 @@ struct meson_clk_mpll_data { struct parm sdm; struct parm sdm_en; struct parm n2; - struct parm en; struct parm ssen; struct parm misc; spinlock_t *lock; diff --git a/drivers/clk/meson/gxbb.c b/drivers/clk/meson/gxbb.c index 49f5716ce8b6..5ab8338eb894 100644 --- a/drivers/clk/meson/gxbb.c +++ b/drivers/clk/meson/gxbb.c @@ -540,7 +540,7 @@ static struct clk_fixed_factor gxbb_fclk_div7 = { }, }; -static struct clk_regmap gxbb_mpll0 = { +static struct clk_regmap gxbb_mpll0_div = { .data = &(struct meson_clk_mpll_data){ .sdm = { .reg_off = HHI_MPLL_CNTL7, @@ -557,11 +557,6 @@ static struct clk_regmap gxbb_mpll0 = { .shift = 16, .width = 9, }, - .en = { - .reg_off = HHI_MPLL_CNTL7, - .shift = 14, - .width = 1, - }, .ssen = { .reg_off = HHI_MPLL_CNTL, .shift = 25, @@ -570,14 +565,28 @@ static struct clk_regmap gxbb_mpll0 = { .lock = &meson_clk_lock, }, .hw.init = &(struct clk_init_data){ - .name = "mpll0", + .name = "mpll0_div", .ops = &meson_clk_mpll_ops, .parent_names = (const char *[]){ "fixed_pll" }, .num_parents = 1, }, }; -static struct clk_regmap gxbb_mpll1 = { +static struct clk_regmap gxbb_mpll0 = { + .data = &(struct clk_regmap_gate_data){ + .offset = HHI_MPLL_CNTL7, + .bit_idx = 14, + }, + .hw.init = &(struct clk_init_data){ + .name = "mpll0", + .ops = &clk_regmap_gate_ops, + .parent_names = (const char *[]){ "mpll0_div" }, + .num_parents = 1, + .flags = CLK_SET_RATE_PARENT, + }, +}; + +static struct clk_regmap gxbb_mpll1_div = { .data = &(struct meson_clk_mpll_data){ .sdm = { .reg_off = HHI_MPLL_CNTL8, @@ -594,22 +603,31 @@ static struct clk_regmap gxbb_mpll1 = { .shift = 16, .width = 9, }, - .en = { - .reg_off = HHI_MPLL_CNTL8, - .shift = 14, - .width = 1, - }, .lock = &meson_clk_lock, }, .hw.init = &(struct clk_init_data){ - .name = "mpll1", + .name = "mpll1_div", .ops = &meson_clk_mpll_ops, .parent_names = (const char *[]){ "fixed_pll" }, .num_parents = 1, }, }; -static struct clk_regmap gxbb_mpll2 = { +static struct clk_regmap gxbb_mpll1 = { + .data = &(struct clk_regmap_gate_data){ + .offset = HHI_MPLL_CNTL8, + .bit_idx = 14, + }, + .hw.init = &(struct clk_init_data){ + .name = "mpll1", + .ops = &clk_regmap_gate_ops, + .parent_names = (const char *[]){ "mpll1_div" }, + .num_parents = 1, + .flags = CLK_SET_RATE_PARENT, + }, +}; + +static struct clk_regmap gxbb_mpll2_div = { .data = &(struct meson_clk_mpll_data){ .sdm = { .reg_off = HHI_MPLL_CNTL9, @@ -626,21 +644,30 @@ static struct clk_regmap gxbb_mpll2 = { .shift = 16, .width = 9, }, - .en = { - .reg_off = HHI_MPLL_CNTL9, - .shift = 14, - .width = 1, - }, .lock = &meson_clk_lock, }, .hw.init = &(struct clk_init_data){ - .name = "mpll2", + .name = "mpll2_div", .ops = &meson_clk_mpll_ops, .parent_names = (const char *[]){ "fixed_pll" }, .num_parents = 1, }, }; +static struct clk_regmap gxbb_mpll2 = { + .data = &(struct clk_regmap_gate_data){ + .offset = HHI_MPLL_CNTL9, + .bit_idx = 14, + }, + .hw.init = &(struct clk_init_data){ + .name = "mpll2", + .ops = &clk_regmap_gate_ops, + .parent_names = (const char *[]){ "mpll2_div" }, + .num_parents = 1, + .flags = CLK_SET_RATE_PARENT, + }, +}; + static u32 mux_table_clk81[] = { 0, 2, 3, 4, 5, 6, 7 }; static const char * const clk81_parent_names[] = { "xtal", "fclk_div7", "mpll1", "mpll2", "fclk_div4", @@ -1668,6 +1695,9 @@ static struct clk_hw_onecell_data gxbb_hw_onecell_data = { [CLKID_VAPB_SEL] = &gxbb_vapb_sel.hw, [CLKID_VAPB] = &gxbb_vapb.hw, [CLKID_HDMI_PLL_PRE_MULT] = &gxbb_hdmi_pll_pre_mult.hw, + [CLKID_MPLL0_DIV] = &gxbb_mpll0_div.hw, + [CLKID_MPLL1_DIV] = &gxbb_mpll1_div.hw, + [CLKID_MPLL2_DIV] = &gxbb_mpll2_div.hw, [NR_CLKS] = NULL, }, .num = NR_CLKS, @@ -1815,6 +1845,9 @@ static struct clk_hw_onecell_data gxl_hw_onecell_data = { [CLKID_VAPB_1] = &gxbb_vapb_1.hw, [CLKID_VAPB_SEL] = &gxbb_vapb_sel.hw, [CLKID_VAPB] = &gxbb_vapb.hw, + [CLKID_MPLL0_DIV] = &gxbb_mpll0_div.hw, + [CLKID_MPLL1_DIV] = &gxbb_mpll1_div.hw, + [CLKID_MPLL2_DIV] = &gxbb_mpll2_div.hw, [NR_CLKS] = NULL, }, .num = NR_CLKS, @@ -1961,6 +1994,9 @@ static struct clk_regmap *const gx_clk_regmaps[] = { &gxbb_mpll0, &gxbb_mpll1, &gxbb_mpll2, + &gxbb_mpll0_div, + &gxbb_mpll1_div, + &gxbb_mpll2_div, &gxbb_cts_amclk_div, &gxbb_fixed_pll, &gxbb_sys_pll, diff --git a/drivers/clk/meson/gxbb.h b/drivers/clk/meson/gxbb.h index 42573b28a137..a8e7b8884e95 100644 --- a/drivers/clk/meson/gxbb.h +++ b/drivers/clk/meson/gxbb.h @@ -195,8 +195,11 @@ #define CLKID_VAPB_0_DIV 134 #define CLKID_VAPB_1_DIV 137 #define CLKID_HDMI_PLL_PRE_MULT 141 +#define CLKID_MPLL0_DIV 142 +#define CLKID_MPLL1_DIV 143 +#define CLKID_MPLL2_DIV 144 -#define NR_CLKS 142 +#define NR_CLKS 145 /* include the CLKIDs that have been made part of the DT binding */ #include diff --git a/drivers/clk/meson/meson8b.c b/drivers/clk/meson/meson8b.c index 4fd8253c54bb..625d953511be 100644 --- a/drivers/clk/meson/meson8b.c +++ b/drivers/clk/meson/meson8b.c @@ -289,7 +289,7 @@ static struct clk_fixed_factor meson8b_fclk_div7 = { }, }; -static struct clk_regmap meson8b_mpll0 = { +static struct clk_regmap meson8b_mpll0_div = { .data = &(struct meson_clk_mpll_data){ .sdm = { .reg_off = HHI_MPLL_CNTL7, @@ -306,11 +306,6 @@ static struct clk_regmap meson8b_mpll0 = { .shift = 16, .width = 9, }, - .en = { - .reg_off = HHI_MPLL_CNTL7, - .shift = 14, - .width = 1, - }, .ssen = { .reg_off = HHI_MPLL_CNTL, .shift = 25, @@ -319,14 +314,28 @@ static struct clk_regmap meson8b_mpll0 = { .lock = &meson_clk_lock, }, .hw.init = &(struct clk_init_data){ - .name = "mpll0", + .name = "mpll0_div", .ops = &meson_clk_mpll_ops, .parent_names = (const char *[]){ "fixed_pll" }, .num_parents = 1, }, }; -static struct clk_regmap meson8b_mpll1 = { +static struct clk_regmap meson8b_mpll0 = { + .data = &(struct clk_regmap_gate_data){ + .offset = HHI_MPLL_CNTL7, + .bit_idx = 14, + }, + .hw.init = &(struct clk_init_data){ + .name = "mpll0", + .ops = &clk_regmap_gate_ops, + .parent_names = (const char *[]){ "mpll0_div" }, + .num_parents = 1, + .flags = CLK_SET_RATE_PARENT, + }, +}; + +static struct clk_regmap meson8b_mpll1_div = { .data = &(struct meson_clk_mpll_data){ .sdm = { .reg_off = HHI_MPLL_CNTL8, @@ -343,22 +352,31 @@ static struct clk_regmap meson8b_mpll1 = { .shift = 16, .width = 9, }, - .en = { - .reg_off = HHI_MPLL_CNTL8, - .shift = 14, - .width = 1, - }, .lock = &meson_clk_lock, }, .hw.init = &(struct clk_init_data){ - .name = "mpll1", + .name = "mpll1_div", .ops = &meson_clk_mpll_ops, .parent_names = (const char *[]){ "fixed_pll" }, .num_parents = 1, }, }; -static struct clk_regmap meson8b_mpll2 = { +static struct clk_regmap meson8b_mpll1 = { + .data = &(struct clk_regmap_gate_data){ + .offset = HHI_MPLL_CNTL8, + .bit_idx = 14, + }, + .hw.init = &(struct clk_init_data){ + .name = "mpll1", + .ops = &clk_regmap_gate_ops, + .parent_names = (const char *[]){ "mpll1_div" }, + .num_parents = 1, + .flags = CLK_SET_RATE_PARENT, + }, +}; + +static struct clk_regmap meson8b_mpll2_div = { .data = &(struct meson_clk_mpll_data){ .sdm = { .reg_off = HHI_MPLL_CNTL9, @@ -375,21 +393,30 @@ static struct clk_regmap meson8b_mpll2 = { .shift = 16, .width = 9, }, - .en = { - .reg_off = HHI_MPLL_CNTL9, - .shift = 14, - .width = 1, - }, .lock = &meson_clk_lock, }, .hw.init = &(struct clk_init_data){ - .name = "mpll2", + .name = "mpll2_div", .ops = &meson_clk_mpll_ops, .parent_names = (const char *[]){ "fixed_pll" }, .num_parents = 1, }, }; +static struct clk_regmap meson8b_mpll2 = { + .data = &(struct clk_regmap_gate_data){ + .offset = HHI_MPLL_CNTL9, + .bit_idx = 14, + }, + .hw.init = &(struct clk_init_data){ + .name = "mpll2", + .ops = &clk_regmap_gate_ops, + .parent_names = (const char *[]){ "mpll2_div" }, + .num_parents = 1, + .flags = CLK_SET_RATE_PARENT, + }, +}; + /* * FIXME cpu clocks and the legacy composite clocks (e.g. clk81) are both PLL * post-dividers and should be modeled with their respective PLLs via the @@ -640,6 +667,9 @@ static struct clk_hw_onecell_data meson8b_hw_onecell_data = { [CLKID_MPLL0] = &meson8b_mpll0.hw, [CLKID_MPLL1] = &meson8b_mpll1.hw, [CLKID_MPLL2] = &meson8b_mpll2.hw, + [CLKID_MPLL0_DIV] = &meson8b_mpll0_div.hw, + [CLKID_MPLL1_DIV] = &meson8b_mpll1_div.hw, + [CLKID_MPLL2_DIV] = &meson8b_mpll2_div.hw, [CLK_NR_CLKS] = NULL, }, .num = CLK_NR_CLKS, @@ -729,6 +759,9 @@ static struct clk_regmap *const meson8b_clk_regmaps[] = { &meson8b_mpll0, &meson8b_mpll1, &meson8b_mpll2, + &meson8b_mpll0_div, + &meson8b_mpll1_div, + &meson8b_mpll2_div, &meson8b_fixed_pll, &meson8b_vid_pll, &meson8b_sys_pll, diff --git a/drivers/clk/meson/meson8b.h b/drivers/clk/meson/meson8b.h index 2eaf8a52e7dd..f2780508edec 100644 --- a/drivers/clk/meson/meson8b.h +++ b/drivers/clk/meson/meson8b.h @@ -69,7 +69,11 @@ * will remain defined here. */ -#define CLK_NR_CLKS 96 +#define CLKID_MPLL0_DIV 96 +#define CLKID_MPLL1_DIV 97 +#define CLKID_MPLL2_DIV 98 + +#define CLK_NR_CLKS 99 /* * include the CLKID and RESETID that have -- cgit v1.2.3 From 251b6fd38bcb9c8fafdc67851d09fddb79efb049 Mon Sep 17 00:00:00 2001 From: Jerome Brunet Date: Mon, 12 Feb 2018 15:58:44 +0100 Subject: clk: meson: rework meson8b cpu clock Instead of migrating meson cpu_clk to clk_regmap, like the other meson clock drivers, we take advantage of the massive rework to get rid of it completely, and solve (the first part) of the related FIXME notice. As pointed out in the code comments, the cpu_clk should be modeled with dividers and muxes it is made of, instead of one big composite clock. The cpu_clk was not working correctly to enable dvfs on meson8b. It hangs quite often when changing the cpu clock rate. This new implementation, based on simple elements improves the situation but the platform will still hang from time to time. This is not acceptable so, until we can make the mechanism around the cpu clock stable, the cpu clock subtree has been put in read-only mode, preventing any change of the cpu clock The notifier and read-write operation will be added back when we have a solution to the problem. Cc: Martin Blumenstingl Signed-off-by: Jerome Brunet Signed-off-by: Neil Armstrong --- drivers/clk/meson/meson8b.c | 173 +++++++++++++++++++++++++++++--------------- drivers/clk/meson/meson8b.h | 7 +- 2 files changed, 119 insertions(+), 61 deletions(-) diff --git a/drivers/clk/meson/meson8b.c b/drivers/clk/meson/meson8b.c index 625d953511be..ea73b5de9672 100644 --- a/drivers/clk/meson/meson8b.c +++ b/drivers/clk/meson/meson8b.c @@ -99,20 +99,6 @@ static const struct pll_rate_table sys_pll_rate_table[] = { { /* sentinel */ }, }; -static const struct clk_div_table cpu_div_table[] = { - { .val = 1, .div = 1 }, - { .val = 2, .div = 2 }, - { .val = 3, .div = 3 }, - { .val = 2, .div = 4 }, - { .val = 3, .div = 6 }, - { .val = 4, .div = 8 }, - { .val = 5, .div = 10 }, - { .val = 6, .div = 12 }, - { .val = 7, .div = 14 }, - { .val = 8, .div = 16 }, - { /* sentinel */ }, -}; - static struct clk_fixed_rate meson8b_xtal = { .fixed_rate = 24000000, .hw.init = &(struct clk_init_data){ @@ -227,7 +213,7 @@ static struct clk_regmap meson8b_sys_pll = { }, .hw.init = &(struct clk_init_data){ .name = "sys_pll", - .ops = &meson_clk_pll_ops, + .ops = &meson_clk_pll_ro_ops, .parent_names = (const char *[]){ "xtal" }, .num_parents = 1, .flags = CLK_GET_RATE_NOCACHE, @@ -417,23 +403,6 @@ static struct clk_regmap meson8b_mpll2 = { }, }; -/* - * FIXME cpu clocks and the legacy composite clocks (e.g. clk81) are both PLL - * post-dividers and should be modeled with their respective PLLs via the - * forthcoming coordinated clock rates feature - */ -static struct meson_clk_cpu meson8b_cpu_clk = { - .reg_off = HHI_SYS_CPU_CLK_CNTL1, - .div_table = cpu_div_table, - .clk_nb.notifier_call = meson_clk_cpu_notifier_cb, - .hw.init = &(struct clk_init_data){ - .name = "cpu_clk", - .ops = &meson_clk_cpu_ops, - .parent_names = (const char *[]){ "sys_pll" }, - .num_parents = 1, - }, -}; - static u32 mux_table_clk81[] = { 6, 5, 7 }; static struct clk_regmap meson8b_mpeg_clk_sel = { .data = &(struct clk_regmap_mux_data){ @@ -486,6 +455,108 @@ struct clk_regmap meson8b_clk81 = { }, }; +struct clk_regmap meson8b_cpu_in_sel = { + .data = &(struct clk_regmap_mux_data){ + .offset = HHI_SYS_CPU_CLK_CNTL0, + .mask = 0x1, + .shift = 0, + }, + .hw.init = &(struct clk_init_data){ + .name = "cpu_in_sel", + .ops = &clk_regmap_mux_ro_ops, + .parent_names = (const char *[]){ "xtal", "sys_pll" }, + .num_parents = 2, + .flags = (CLK_SET_RATE_PARENT | + CLK_SET_RATE_NO_REPARENT), + }, +}; + +static struct clk_fixed_factor meson8b_cpu_div2 = { + .mult = 1, + .div = 2, + .hw.init = &(struct clk_init_data){ + .name = "cpu_div2", + .ops = &clk_fixed_factor_ops, + .parent_names = (const char *[]){ "cpu_in_sel" }, + .num_parents = 1, + .flags = CLK_SET_RATE_PARENT, + }, +}; + +static struct clk_fixed_factor meson8b_cpu_div3 = { + .mult = 1, + .div = 3, + .hw.init = &(struct clk_init_data){ + .name = "cpu_div3", + .ops = &clk_fixed_factor_ops, + .parent_names = (const char *[]){ "cpu_in_sel" }, + .num_parents = 1, + .flags = CLK_SET_RATE_PARENT, + }, +}; + +static const struct clk_div_table cpu_scale_table[] = { + { .val = 2, .div = 4 }, + { .val = 3, .div = 6 }, + { .val = 4, .div = 8 }, + { .val = 5, .div = 10 }, + { .val = 6, .div = 12 }, + { .val = 7, .div = 14 }, + { .val = 8, .div = 16 }, + { /* sentinel */ }, +}; + +struct clk_regmap meson8b_cpu_scale_div = { + .data = &(struct clk_regmap_div_data){ + .offset = HHI_SYS_CPU_CLK_CNTL1, + .shift = 20, + .width = 9, + .table = cpu_scale_table, + .flags = CLK_DIVIDER_ALLOW_ZERO, + }, + .hw.init = &(struct clk_init_data){ + .name = "cpu_scale_div", + .ops = &clk_regmap_divider_ro_ops, + .parent_names = (const char *[]){ "cpu_in_sel" }, + .num_parents = 1, + .flags = CLK_SET_RATE_PARENT, + }, +}; + +struct clk_regmap meson8b_cpu_scale_out_sel = { + .data = &(struct clk_regmap_mux_data){ + .offset = HHI_SYS_CPU_CLK_CNTL0, + .mask = 0x3, + .shift = 2, + }, + .hw.init = &(struct clk_init_data){ + .name = "cpu_scale_out_sel", + .ops = &clk_regmap_mux_ro_ops, + .parent_names = (const char *[]) { "cpu_in_sel", + "cpu_div2", + "cpu_div3", + "cpu_scale_div" }, + .num_parents = 4, + .flags = CLK_SET_RATE_PARENT, + }, +}; + +struct clk_regmap meson8b_cpu_clk = { + .data = &(struct clk_regmap_mux_data){ + .offset = HHI_SYS_CPU_CLK_CNTL0, + .mask = 0x1, + .shift = 7, + }, + .hw.init = &(struct clk_init_data){ + .name = "cpu_clk", + .ops = &clk_regmap_mux_ro_ops, + .parent_names = (const char *[]){ "xtal", "cpu_out_sel" }, + .num_parents = 2, + .flags = (CLK_SET_RATE_PARENT | + CLK_SET_RATE_NO_REPARENT), + }, +}; + /* Everything Else (EE) domain gates */ static MESON_GATE(meson8b_ddr, HHI_GCLK_MPEG0, 0); @@ -670,6 +741,11 @@ static struct clk_hw_onecell_data meson8b_hw_onecell_data = { [CLKID_MPLL0_DIV] = &meson8b_mpll0_div.hw, [CLKID_MPLL1_DIV] = &meson8b_mpll1_div.hw, [CLKID_MPLL2_DIV] = &meson8b_mpll2_div.hw, + [CLKID_CPU_IN_SEL] = &meson8b_cpu_in_sel.hw, + [CLKID_CPU_DIV2] = &meson8b_cpu_div2.hw, + [CLKID_CPU_DIV3] = &meson8b_cpu_div3.hw, + [CLKID_CPU_SCALE_DIV] = &meson8b_cpu_scale_div.hw, + [CLKID_CPU_SCALE_OUT_SEL] = &meson8b_cpu_scale_out_sel.hw, [CLK_NR_CLKS] = NULL, }, .num = CLK_NR_CLKS, @@ -765,6 +841,10 @@ static struct clk_regmap *const meson8b_clk_regmaps[] = { &meson8b_fixed_pll, &meson8b_vid_pll, &meson8b_sys_pll, + &meson8b_cpu_in_sel, + &meson8b_cpu_scale_div, + &meson8b_cpu_scale_out_sel, + &meson8b_cpu_clk, }; static const struct meson8b_clk_reset_line { @@ -875,8 +955,7 @@ static const struct regmap_config clkc_regmap_config = { static int meson8b_clkc_probe(struct platform_device *pdev) { int ret, i; - struct clk_hw *parent_hw; - struct clk *parent_clk; + struct clk *clk; struct device *dev = &pdev->dev; struct regmap *map; @@ -887,9 +966,6 @@ static int meson8b_clkc_probe(struct platform_device *pdev) if (IS_ERR(map)) return PTR_ERR(map); - /* Populate the base address for CPU clk */ - meson8b_cpu_clk.base = clk_base; - /* Populate regmap for the regmap backed clocks */ for (i = 0; i < ARRAY_SIZE(meson8b_clk_regmaps); i++) meson8b_clk_regmaps[i]->map = map; @@ -908,29 +984,6 @@ static int meson8b_clkc_probe(struct platform_device *pdev) return ret; } - /* - * Register CPU clk notifier - * - * FIXME this is wrong for a lot of reasons. First, the muxes should be - * struct clk_hw objects. Second, we shouldn't program the muxes in - * notifier handlers. The tricky programming sequence will be handled - * by the forthcoming coordinated clock rates mechanism once that - * feature is released. - * - * Furthermore, looking up the parent this way is terrible. At some - * point we will stop allocating a default struct clk when registering - * a new clk_hw, and this hack will no longer work. Releasing the ccr - * feature before that time solves the problem :-) - */ - parent_hw = clk_hw_get_parent(&meson8b_cpu_clk.hw); - parent_clk = parent_hw->clk; - ret = clk_notifier_register(parent_clk, &meson8b_cpu_clk.clk_nb); - if (ret) { - pr_err("%s: failed to register clock notifier for cpu_clk\n", - __func__); - return ret; - } - return devm_of_clk_add_hw_provider(dev, of_clk_hw_onecell_get, &meson8b_hw_onecell_data); } diff --git a/drivers/clk/meson/meson8b.h b/drivers/clk/meson/meson8b.h index f2780508edec..73dae83d9932 100644 --- a/drivers/clk/meson/meson8b.h +++ b/drivers/clk/meson/meson8b.h @@ -72,8 +72,13 @@ #define CLKID_MPLL0_DIV 96 #define CLKID_MPLL1_DIV 97 #define CLKID_MPLL2_DIV 98 +#define CLKID_CPU_IN_SEL 99 +#define CLKID_CPU_DIV2 100 +#define CLKID_CPU_DIV3 101 +#define CLKID_CPU_SCALE_DIV 102 +#define CLKID_CPU_SCALE_OUT_SEL 103 -#define CLK_NR_CLKS 99 +#define CLK_NR_CLKS 104 /* * include the CLKID and RESETID that have -- cgit v1.2.3 From 03a6519e9cd4d04f1ec2b0cb77d4ebbf7680c3a5 Mon Sep 17 00:00:00 2001 From: Jerome Brunet Date: Mon, 12 Feb 2018 15:58:45 +0100 Subject: clk: meson: remove obsolete cpu_clk meson8b cpu_clk has been replaced by a set of divider and mux clocks. meson_cpu_clk is no longer used and can be removed Acked-by: Martin Blumenstingl Signed-off-by: Jerome Brunet Signed-off-by: Neil Armstrong --- drivers/clk/meson/Makefile | 2 +- drivers/clk/meson/clk-cpu.c | 178 -------------------------------------------- drivers/clk/meson/clkc.h | 11 --- 3 files changed, 1 insertion(+), 190 deletions(-) delete mode 100644 drivers/clk/meson/clk-cpu.c diff --git a/drivers/clk/meson/Makefile b/drivers/clk/meson/Makefile index 465086118d62..ffee82e60b7a 100644 --- a/drivers/clk/meson/Makefile +++ b/drivers/clk/meson/Makefile @@ -2,7 +2,7 @@ # Makefile for Meson specific clk # -obj-$(CONFIG_COMMON_CLK_AMLOGIC) += clk-pll.o clk-cpu.o clk-mpll.o clk-audio-divider.o +obj-$(CONFIG_COMMON_CLK_AMLOGIC) += clk-pll.o clk-mpll.o clk-audio-divider.o obj-$(CONFIG_COMMON_CLK_MESON8B) += meson8b.o obj-$(CONFIG_COMMON_CLK_GXBB) += gxbb.o gxbb-aoclk.o gxbb-aoclk-32k.o obj-$(CONFIG_COMMON_CLK_AXG) += axg.o diff --git a/drivers/clk/meson/clk-cpu.c b/drivers/clk/meson/clk-cpu.c deleted file mode 100644 index f8b2b7efd016..000000000000 --- a/drivers/clk/meson/clk-cpu.c +++ /dev/null @@ -1,178 +0,0 @@ -/* - * Copyright (c) 2015 Endless Mobile, Inc. - * Author: Carlo Caione - * - * This program is free software; you can redistribute it and/or modify it - * under the terms and conditions of the GNU General Public License, - * version 2, as published by the Free Software Foundation. - * - * This program is distributed in the hope it will be useful, but WITHOUT - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or - * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for - * more details. - * - * You should have received a copy of the GNU General Public License along with - * this program. If not, see . - */ - -/* - * CPU clock path: - * - * +-[/N]-----|3| - * MUX2 +--[/3]-+----------|2| MUX1 - * [sys_pll]---|1| |--[/2]------------|1|-|1| - * | |---+------------------|0| | |----- [a5_clk] - * +--|0| | | - * [xtal]---+-------------------------------|0| - * - * - * - */ - -#include -#include -#include -#include -#include -#include -#include -#include - -#define MESON_CPU_CLK_CNTL1 0x00 -#define MESON_CPU_CLK_CNTL 0x40 - -#define MESON_CPU_CLK_MUX1 BIT(7) -#define MESON_CPU_CLK_MUX2 BIT(0) - -#define MESON_N_WIDTH 9 -#define MESON_N_SHIFT 20 -#define MESON_SEL_WIDTH 2 -#define MESON_SEL_SHIFT 2 - -#include "clkc.h" - -#define to_meson_clk_cpu_hw(_hw) container_of(_hw, struct meson_clk_cpu, hw) -#define to_meson_clk_cpu_nb(_nb) container_of(_nb, struct meson_clk_cpu, clk_nb) - -static long meson_clk_cpu_round_rate(struct clk_hw *hw, unsigned long rate, - unsigned long *prate) -{ - struct meson_clk_cpu *clk_cpu = to_meson_clk_cpu_hw(hw); - - return divider_round_rate(hw, rate, prate, clk_cpu->div_table, - MESON_N_WIDTH, CLK_DIVIDER_ROUND_CLOSEST); -} - -static int meson_clk_cpu_set_rate(struct clk_hw *hw, unsigned long rate, - unsigned long parent_rate) -{ - struct meson_clk_cpu *clk_cpu = to_meson_clk_cpu_hw(hw); - unsigned int div, sel, N = 0; - u32 reg; - - div = DIV_ROUND_UP(parent_rate, rate); - - if (div <= 3) { - sel = div - 1; - } else { - sel = 3; - N = div / 2; - } - - reg = readl(clk_cpu->base + clk_cpu->reg_off + MESON_CPU_CLK_CNTL1); - reg = PARM_SET(MESON_N_WIDTH, MESON_N_SHIFT, reg, N); - writel(reg, clk_cpu->base + clk_cpu->reg_off + MESON_CPU_CLK_CNTL1); - - reg = readl(clk_cpu->base + clk_cpu->reg_off + MESON_CPU_CLK_CNTL); - reg = PARM_SET(MESON_SEL_WIDTH, MESON_SEL_SHIFT, reg, sel); - writel(reg, clk_cpu->base + clk_cpu->reg_off + MESON_CPU_CLK_CNTL); - - return 0; -} - -static unsigned long meson_clk_cpu_recalc_rate(struct clk_hw *hw, - unsigned long parent_rate) -{ - struct meson_clk_cpu *clk_cpu = to_meson_clk_cpu_hw(hw); - unsigned int N, sel; - unsigned int div = 1; - u32 reg; - - reg = readl(clk_cpu->base + clk_cpu->reg_off + MESON_CPU_CLK_CNTL1); - N = PARM_GET(MESON_N_WIDTH, MESON_N_SHIFT, reg); - - reg = readl(clk_cpu->base + clk_cpu->reg_off + MESON_CPU_CLK_CNTL); - sel = PARM_GET(MESON_SEL_WIDTH, MESON_SEL_SHIFT, reg); - - if (sel < 3) - div = sel + 1; - else - div = 2 * N; - - return parent_rate / div; -} - -/* FIXME MUX1 & MUX2 should be struct clk_hw objects */ -static int meson_clk_cpu_pre_rate_change(struct meson_clk_cpu *clk_cpu, - struct clk_notifier_data *ndata) -{ - u32 cpu_clk_cntl; - - /* switch MUX1 to xtal */ - cpu_clk_cntl = readl(clk_cpu->base + clk_cpu->reg_off - + MESON_CPU_CLK_CNTL); - cpu_clk_cntl &= ~MESON_CPU_CLK_MUX1; - writel(cpu_clk_cntl, clk_cpu->base + clk_cpu->reg_off - + MESON_CPU_CLK_CNTL); - udelay(100); - - /* switch MUX2 to sys-pll */ - cpu_clk_cntl |= MESON_CPU_CLK_MUX2; - writel(cpu_clk_cntl, clk_cpu->base + clk_cpu->reg_off - + MESON_CPU_CLK_CNTL); - - return 0; -} - -/* FIXME MUX1 & MUX2 should be struct clk_hw objects */ -static int meson_clk_cpu_post_rate_change(struct meson_clk_cpu *clk_cpu, - struct clk_notifier_data *ndata) -{ - u32 cpu_clk_cntl; - - /* switch MUX1 to divisors' output */ - cpu_clk_cntl = readl(clk_cpu->base + clk_cpu->reg_off - + MESON_CPU_CLK_CNTL); - cpu_clk_cntl |= MESON_CPU_CLK_MUX1; - writel(cpu_clk_cntl, clk_cpu->base + clk_cpu->reg_off - + MESON_CPU_CLK_CNTL); - udelay(100); - - return 0; -} - -/* - * This clock notifier is called when the frequency of the of the parent - * PLL clock is to be changed. We use the xtal input as temporary parent - * while the PLL frequency is stabilized. - */ -int meson_clk_cpu_notifier_cb(struct notifier_block *nb, - unsigned long event, void *data) -{ - struct clk_notifier_data *ndata = data; - struct meson_clk_cpu *clk_cpu = to_meson_clk_cpu_nb(nb); - int ret = 0; - - if (event == PRE_RATE_CHANGE) - ret = meson_clk_cpu_pre_rate_change(clk_cpu, ndata); - else if (event == POST_RATE_CHANGE) - ret = meson_clk_cpu_post_rate_change(clk_cpu, ndata); - - return notifier_from_errno(ret); -} - -const struct clk_ops meson_clk_cpu_ops = { - .recalc_rate = meson_clk_cpu_recalc_rate, - .round_rate = meson_clk_cpu_round_rate, - .set_rate = meson_clk_cpu_set_rate, -}; diff --git a/drivers/clk/meson/clkc.h b/drivers/clk/meson/clkc.h index cc1a964cd4d7..8d8fe608cff4 100644 --- a/drivers/clk/meson/clkc.h +++ b/drivers/clk/meson/clkc.h @@ -101,17 +101,6 @@ struct meson_clk_pll_data { #define to_meson_clk_pll(_hw) container_of(_hw, struct meson_clk_pll, hw) -struct meson_clk_cpu { - struct clk_hw hw; - void __iomem *base; - u16 reg_off; - struct notifier_block clk_nb; - const struct clk_div_table *div_table; -}; - -int meson_clk_cpu_notifier_cb(struct notifier_block *nb, unsigned long event, - void *data); - struct meson_clk_mpll_data { struct parm sdm; struct parm sdm_en; -- cgit v1.2.3 From 4162dd5b3a17f2bf20abbaa7229028e7bc021523 Mon Sep 17 00:00:00 2001 From: Jerome Brunet Date: Mon, 12 Feb 2018 15:58:46 +0100 Subject: clk: meson: use hhi syscon if available On gxbb and axg, try to get the hhi regmap from the parent DT node, which should be the HHI system controller once the necessary changes have been made in amlogic's DTs Until then, if getting regmap through the system controller fails, the clock controller will fall back to the old way, requesting memory region directly and then registering the regmap itself. This should allow a smooth transition to syscon Signed-off-by: Jerome Brunet Signed-off-by: Neil Armstrong --- drivers/clk/meson/Kconfig | 2 ++ drivers/clk/meson/axg.c | 43 ++++++++++++++++++++++++++++++------------- drivers/clk/meson/gxbb.c | 39 ++++++++++++++++++++++++++++----------- 3 files changed, 60 insertions(+), 24 deletions(-) diff --git a/drivers/clk/meson/Kconfig b/drivers/clk/meson/Kconfig index 936afddae406..d5cbec522aec 100644 --- a/drivers/clk/meson/Kconfig +++ b/drivers/clk/meson/Kconfig @@ -22,6 +22,7 @@ config COMMON_CLK_GXBB depends on COMMON_CLK_AMLOGIC select RESET_CONTROLLER select COMMON_CLK_REGMAP_MESON + select MFD_SYSCON help Support for the clock controller on AmLogic S905 devices, aka gxbb. Say Y if you want peripherals and CPU frequency scaling to work. @@ -31,6 +32,7 @@ config COMMON_CLK_AXG depends on COMMON_CLK_AMLOGIC select RESET_CONTROLLER select COMMON_CLK_REGMAP_MESON + select MFD_SYSCON help Support for the clock controller on AmLogic A113D devices, aka axg. Say Y if you want peripherals and CPU frequency scaling to work. diff --git a/drivers/clk/meson/axg.c b/drivers/clk/meson/axg.c index 6813b632c1a9..acb63c8e0fd8 100644 --- a/drivers/clk/meson/axg.c +++ b/drivers/clk/meson/axg.c @@ -14,6 +14,7 @@ #include #include #include +#include #include #include @@ -850,25 +851,41 @@ static int axg_clkc_probe(struct platform_device *pdev) { struct device *dev = &pdev->dev; struct resource *res; - void __iomem *clk_base; + void __iomem *clk_base = NULL; struct regmap *map; int ret, i; - /* Generic clocks and PLLs */ - res = platform_get_resource(pdev, IORESOURCE_MEM, 0); - if (!res) - return -EINVAL; + /* Get the hhi system controller node if available */ + map = syscon_node_to_regmap(of_get_parent(dev->of_node)); + if (IS_ERR(map)) { + dev_err(dev, + "failed to get HHI regmap - Trying obsolete regs\n"); + + /* + * FIXME: HHI registers should be accessed through + * the appropriate system controller. This is required because + * there is more than just clocks in this register space + * + * This fallback method is only provided temporarily until + * all the platform DTs are properly using the syscon node + */ + res = platform_get_resource(pdev, IORESOURCE_MEM, 0); + if (!res) + return -EINVAL; + + + clk_base = devm_ioremap(dev, res->start, resource_size(res)); + if (!clk_base) { + dev_err(dev, "Unable to map clk base\n"); + return -ENXIO; + } - clk_base = devm_ioremap(dev, res->start, resource_size(res)); - if (!clk_base) { - dev_err(dev, "Unable to map clk base\n"); - return -ENXIO; + map = devm_regmap_init_mmio(dev, clk_base, + &clkc_regmap_config); + if (IS_ERR(map)) + return PTR_ERR(map); } - map = devm_regmap_init_mmio(dev, clk_base, &clkc_regmap_config); - if (IS_ERR(map)) - return PTR_ERR(map); - /* Populate regmap for the regmap backed clocks */ for (i = 0; i < ARRAY_SIZE(axg_clk_regmaps); i++) axg_clk_regmaps[i]->map = map; diff --git a/drivers/clk/meson/gxbb.c b/drivers/clk/meson/gxbb.c index 5ab8338eb894..bb0b0529ca81 100644 --- a/drivers/clk/meson/gxbb.c +++ b/drivers/clk/meson/gxbb.c @@ -22,6 +22,7 @@ #include #include #include +#include #include #include @@ -2045,19 +2046,35 @@ static int gxbb_clkc_probe(struct platform_device *pdev) if (!clkc_data) return -EINVAL; - res = platform_get_resource(pdev, IORESOURCE_MEM, 0); - if (!res) - return -EINVAL; + /* Get the hhi system controller node if available */ + map = syscon_node_to_regmap(of_get_parent(dev->of_node)); + if (IS_ERR(map)) { + dev_err(dev, + "failed to get HHI regmap - Trying obsolete regs\n"); - clk_base = devm_ioremap(dev, res->start, resource_size(res)); - if (!clk_base) { - pr_err("%s: Unable to map clk base\n", __func__); - return -ENXIO; - } + /* + * FIXME: HHI registers should be accessed through + * the appropriate system controller. This is required because + * there is more than just clocks in this register space + * + * This fallback method is only provided temporarily until + * all the platform DTs are properly using the syscon node + */ + res = platform_get_resource(pdev, IORESOURCE_MEM, 0); + if (!res) + return -EINVAL; + + clk_base = devm_ioremap(dev, res->start, resource_size(res)); + if (!clk_base) { + dev_err(dev, "Unable to map clk base\n"); + return -ENXIO; + } - map = devm_regmap_init_mmio(dev, clk_base, &clkc_regmap_config); - if (IS_ERR(map)) - return PTR_ERR(map); + map = devm_regmap_init_mmio(dev, clk_base, + &clkc_regmap_config); + if (IS_ERR(map)) + return PTR_ERR(map); + } /* Populate regmap for the common regmap backed clocks */ for (i = 0; i < ARRAY_SIZE(gx_clk_regmaps); i++) -- cgit v1.2.3 From 2eab2d7cab2804f767b84cbdd06d291214d61df4 Mon Sep 17 00:00:00 2001 From: Jerome Brunet Date: Mon, 19 Feb 2018 12:21:36 +0100 Subject: clk: meson: add fractional part of meson8b fixed_pll Add the missing frac parameter to the meson8b fixed_pll. It seems to be always on this platform, so the rate remains unchanged Signed-off-by: Jerome Brunet Signed-off-by: Neil Armstrong --- drivers/clk/meson/meson8b.c | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/drivers/clk/meson/meson8b.c b/drivers/clk/meson/meson8b.c index ea73b5de9672..62c54a75a1d2 100644 --- a/drivers/clk/meson/meson8b.c +++ b/drivers/clk/meson/meson8b.c @@ -125,6 +125,11 @@ static struct clk_regmap meson8b_fixed_pll = { .shift = 16, .width = 2, }, + .frac = { + .reg_off = HHI_MPLL_CNTL2, + .shift = 0, + .width = 12, + }, .l = { .reg_off = HHI_MPLL_CNTL, .shift = 31, -- cgit v1.2.3 From 117863e8424791e310f299072080d7b745dbec83 Mon Sep 17 00:00:00 2001 From: Jerome Brunet Date: Mon, 19 Feb 2018 12:21:37 +0100 Subject: clk: meson: poke pll CNTL last Poking CNTL first may take the PLL out of reset while we are still applying the initial settings, including the filter values initialization. This is the case for the axg and gxl gp0 pll. Doing this poke last ensures the pll stays in reset while the initial settings are applied. Signed-off-by: Jerome Brunet Signed-off-by: Neil Armstrong --- drivers/clk/meson/axg.c | 2 +- drivers/clk/meson/gxbb.c | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/drivers/clk/meson/axg.c b/drivers/clk/meson/axg.c index acb63c8e0fd8..8226b82c67fd 100644 --- a/drivers/clk/meson/axg.c +++ b/drivers/clk/meson/axg.c @@ -193,12 +193,12 @@ static const struct pll_rate_table axg_gp0_pll_rate_table[] = { }; const struct reg_sequence axg_gp0_init_regs[] = { - { .reg = HHI_GP0_PLL_CNTL, .def = 0x40010250 }, { .reg = HHI_GP0_PLL_CNTL1, .def = 0xc084a000 }, { .reg = HHI_GP0_PLL_CNTL2, .def = 0xb75020be }, { .reg = HHI_GP0_PLL_CNTL3, .def = 0x0a59a288 }, { .reg = HHI_GP0_PLL_CNTL4, .def = 0xc000004d }, { .reg = HHI_GP0_PLL_CNTL5, .def = 0x00078000 }, + { .reg = HHI_GP0_PLL_CNTL, .def = 0x40010250 }, }; static struct clk_regmap axg_gp0_pll = { diff --git a/drivers/clk/meson/gxbb.c b/drivers/clk/meson/gxbb.c index bb0b0529ca81..3cd07f960489 100644 --- a/drivers/clk/meson/gxbb.c +++ b/drivers/clk/meson/gxbb.c @@ -390,10 +390,10 @@ static struct clk_regmap gxbb_sys_pll = { }; const struct reg_sequence gxbb_gp0_init_regs[] = { - { .reg = HHI_GP0_PLL_CNTL, .def = 0x6a000228 }, { .reg = HHI_GP0_PLL_CNTL2, .def = 0x69c80000 }, { .reg = HHI_GP0_PLL_CNTL3, .def = 0x0a5590c4 }, { .reg = HHI_GP0_PLL_CNTL4, .def = 0x0000500d }, + { .reg = HHI_GP0_PLL_CNTL, .def = 0x4a000228 }, }; static struct clk_regmap gxbb_gp0_pll = { @@ -437,12 +437,12 @@ static struct clk_regmap gxbb_gp0_pll = { }; const struct reg_sequence gxl_gp0_init_regs[] = { - { .reg = HHI_GP0_PLL_CNTL, .def = 0x40010250 }, { .reg = HHI_GP0_PLL_CNTL1, .def = 0xc084a000 }, { .reg = HHI_GP0_PLL_CNTL2, .def = 0xb75020be }, { .reg = HHI_GP0_PLL_CNTL3, .def = 0x0a59a288 }, { .reg = HHI_GP0_PLL_CNTL4, .def = 0xc000004d }, { .reg = HHI_GP0_PLL_CNTL5, .def = 0x00078000 }, + { .reg = HHI_GP0_PLL_CNTL, .def = 0x40010250 }, }; static struct clk_regmap gxl_gp0_pll = { -- cgit v1.2.3 From c178b003bfcfde5a973c6ba6a45ca60fb1470fc6 Mon Sep 17 00:00:00 2001 From: Jerome Brunet Date: Mon, 19 Feb 2018 12:21:38 +0100 Subject: clk: meson: remove special gp0 lock loop After testing, it appears that the gxl (and axg) does not require the special locking/reset loop which was initially added for it. All the values present in the gxl table can locked with the simple lock checking loop. The change switches the gxl and axg gp0 back to the simple lock checking loop and removes the code no longer required. Signed-off-by: Jerome Brunet Signed-off-by: Neil Armstrong --- drivers/clk/meson/axg.c | 1 - drivers/clk/meson/clk-pll.c | 12 +----------- drivers/clk/meson/clkc.h | 2 -- drivers/clk/meson/gxbb.c | 1 - 4 files changed, 1 insertion(+), 15 deletions(-) diff --git a/drivers/clk/meson/axg.c b/drivers/clk/meson/axg.c index 8226b82c67fd..4f13929cd594 100644 --- a/drivers/clk/meson/axg.c +++ b/drivers/clk/meson/axg.c @@ -231,7 +231,6 @@ static struct clk_regmap axg_gp0_pll = { .table = axg_gp0_pll_rate_table, .init_regs = axg_gp0_init_regs, .init_count = ARRAY_SIZE(axg_gp0_init_regs), - .flags = CLK_MESON_PLL_LOCK_LOOP_RST, }, .hw.init = &(struct clk_init_data){ .name = "gp0_pll", diff --git a/drivers/clk/meson/clk-pll.c b/drivers/clk/meson/clk-pll.c index f3d909719111..0b9b4422c968 100644 --- a/drivers/clk/meson/clk-pll.c +++ b/drivers/clk/meson/clk-pll.c @@ -121,19 +121,9 @@ static int meson_clk_pll_wait_lock(struct clk_hw *hw) { struct clk_regmap *clk = to_clk_regmap(hw); struct meson_clk_pll_data *pll = meson_clk_pll_data(clk); - int delay = pll->flags & CLK_MESON_PLL_LOCK_LOOP_RST ? - 100 : 24000000; + int delay = 24000000; do { - /* Specific wait loop for GXL/GXM GP0 PLL */ - if (pll->flags & CLK_MESON_PLL_LOCK_LOOP_RST) { - /* Procedure taken from the vendor kernel */ - meson_parm_write(clk->map, &pll->rst, 1); - udelay(10); - meson_parm_write(clk->map, &pll->rst, 0); - mdelay(1); - } - /* Is the clock locked now ? */ if (meson_parm_read(clk->map, &pll->l)) return 0; diff --git a/drivers/clk/meson/clkc.h b/drivers/clk/meson/clkc.h index 8d8fe608cff4..ebd88afe1eb5 100644 --- a/drivers/clk/meson/clkc.h +++ b/drivers/clk/meson/clkc.h @@ -82,8 +82,6 @@ struct pll_rate_table { .frac = (_frac), \ } \ -#define CLK_MESON_PLL_LOCK_LOOP_RST BIT(0) - struct meson_clk_pll_data { struct parm m; struct parm n; diff --git a/drivers/clk/meson/gxbb.c b/drivers/clk/meson/gxbb.c index 3cd07f960489..ac48eef0f490 100644 --- a/drivers/clk/meson/gxbb.c +++ b/drivers/clk/meson/gxbb.c @@ -475,7 +475,6 @@ static struct clk_regmap gxl_gp0_pll = { .table = gxl_gp0_pll_rate_table, .init_regs = gxl_gp0_init_regs, .init_count = ARRAY_SIZE(gxl_gp0_init_regs), - .flags = CLK_MESON_PLL_LOCK_LOOP_RST, }, .hw.init = &(struct clk_init_data){ .name = "gp0_pll", -- cgit v1.2.3 From 8289aafa4f361050b05f77a35d3167259530a473 Mon Sep 17 00:00:00 2001 From: Jerome Brunet Date: Mon, 19 Feb 2018 12:21:39 +0100 Subject: clk: meson: improve pll driver results with frac Finding the appropriate settings of meson plls is too tricky to be done entirely at runtime, using calculation only. Many combination of m, n and od won't lock which is why we are using a table for this. However, for plls having a fractional parameters, it is possible to improve on the result provided by the table by calculating the frac parameter. This change adds the calculation of frac when the parameter is available and the rate provided by the table is not an exact match for the requested rate. Signed-off-by: Jerome Brunet Signed-off-by: Neil Armstrong --- drivers/clk/meson/clk-pll.c | 137 +++++++++++++++++++++++++++++--------------- drivers/clk/meson/clkc.h | 13 +---- 2 files changed, 91 insertions(+), 59 deletions(-) diff --git a/drivers/clk/meson/clk-pll.c b/drivers/clk/meson/clk-pll.c index 0b9b4422c968..d58961f35b71 100644 --- a/drivers/clk/meson/clk-pll.c +++ b/drivers/clk/meson/clk-pll.c @@ -2,6 +2,9 @@ * Copyright (c) 2015 Endless Mobile, Inc. * Author: Carlo Caione * + * Copyright (c) 2018 Baylibre, SAS. + * Author: Jerome Brunet + * * This program is free software; you can redistribute it and/or modify it * under the terms and conditions of the GNU General Public License, * version 2, as published by the Free Software Foundation. @@ -27,7 +30,7 @@ * | | * FREF VCO * - * out = (in * M / N) >> OD + * out = in * (m + frac / frac_max) / (n << sum(ods)) */ #include @@ -48,73 +51,110 @@ meson_clk_pll_data(struct clk_regmap *clk) return (struct meson_clk_pll_data *)clk->data; } +static unsigned long __pll_params_to_rate(unsigned long parent_rate, + const struct pll_rate_table *pllt, + u16 frac, + struct meson_clk_pll_data *pll) +{ + u64 rate = (u64)parent_rate * pllt->m; + unsigned int od = pllt->od + pllt->od2 + pllt->od3; + + if (frac && MESON_PARM_APPLICABLE(&pll->frac)) { + u64 frac_rate = (u64)parent_rate * frac; + + rate += DIV_ROUND_UP_ULL(frac_rate, + (1 << pll->frac.width)); + } + + return DIV_ROUND_UP_ULL(rate, pllt->n << od); +} + static unsigned long meson_clk_pll_recalc_rate(struct clk_hw *hw, unsigned long parent_rate) { struct clk_regmap *clk = to_clk_regmap(hw); struct meson_clk_pll_data *pll = meson_clk_pll_data(clk); - u64 rate; - u16 n, m, frac = 0, od, od2 = 0, od3 = 0; - - n = meson_parm_read(clk->map, &pll->n); - m = meson_parm_read(clk->map, &pll->m); - od = meson_parm_read(clk->map, &pll->od); - - if (MESON_PARM_APPLICABLE(&pll->od2)) - od2 = meson_parm_read(clk->map, &pll->od2); + struct pll_rate_table pllt; + u16 frac; - if (MESON_PARM_APPLICABLE(&pll->od3)) - od3 = meson_parm_read(clk->map, &pll->od3); + pllt.n = meson_parm_read(clk->map, &pll->n); + pllt.m = meson_parm_read(clk->map, &pll->m); + pllt.od = meson_parm_read(clk->map, &pll->od); - rate = (u64)m * parent_rate; + pllt.od2 = MESON_PARM_APPLICABLE(&pll->od2) ? + meson_parm_read(clk->map, &pll->od2) : + 0; - if (MESON_PARM_APPLICABLE(&pll->frac)) { - frac = meson_parm_read(clk->map, &pll->frac); + pllt.od3 = MESON_PARM_APPLICABLE(&pll->od3) ? + meson_parm_read(clk->map, &pll->od3) : + 0; - rate += mul_u64_u32_shr(parent_rate, frac, pll->frac.width); - } + frac = MESON_PARM_APPLICABLE(&pll->frac) ? + meson_parm_read(clk->map, &pll->frac) : + 0; - return div_u64(rate, n) >> od >> od2 >> od3; + return __pll_params_to_rate(parent_rate, &pllt, frac, pll); } -static long meson_clk_pll_round_rate(struct clk_hw *hw, unsigned long rate, - unsigned long *parent_rate) +static u16 __pll_params_with_frac(unsigned long rate, + unsigned long parent_rate, + const struct pll_rate_table *pllt, + struct meson_clk_pll_data *pll) { - struct clk_regmap *clk = to_clk_regmap(hw); - struct meson_clk_pll_data *pll = meson_clk_pll_data(clk); - const struct pll_rate_table *pllt; - - /* - * if the table is missing, just return the current rate - * since we don't have the other available frequencies - */ - if (!pll->table) - return meson_clk_pll_recalc_rate(hw, *parent_rate); + u16 frac_max = (1 << pll->frac.width); + u64 val = (u64)rate * pllt->n; - for (pllt = pll->table; pllt->rate; pllt++) { - if (rate <= pllt->rate) - return pllt->rate; - } + val <<= pllt->od + pllt->od2 + pllt->od3; + val = div_u64(val * frac_max, parent_rate); + val -= pllt->m * frac_max; - /* else return the smallest value */ - return pll->table[0].rate; + return min((u16)val, (u16)(frac_max - 1)); } static const struct pll_rate_table * -meson_clk_get_pll_settings(const struct pll_rate_table *table, - unsigned long rate) +meson_clk_get_pll_settings(unsigned long rate, + struct meson_clk_pll_data *pll) { - const struct pll_rate_table *pllt; + const struct pll_rate_table *table = pll->table; + unsigned int i = 0; if (!table) return NULL; - for (pllt = table; pllt->rate; pllt++) { - if (rate == pllt->rate) - return pllt; - } + /* Find the first table element exceeding rate */ + while (table[i].rate && table[i].rate <= rate) + i++; + + /* Select the setting of the rounded down rate */ + if (i != 0) + i--; + + return (struct pll_rate_table *)&table[i]; +} + +static long meson_clk_pll_round_rate(struct clk_hw *hw, unsigned long rate, + unsigned long *parent_rate) +{ + struct clk_regmap *clk = to_clk_regmap(hw); + struct meson_clk_pll_data *pll = meson_clk_pll_data(clk); + const struct pll_rate_table *pllt = + meson_clk_get_pll_settings(rate, pll); + u16 frac; + + if (!pllt) + return meson_clk_pll_recalc_rate(hw, *parent_rate); + + if (!MESON_PARM_APPLICABLE(&pll->frac) + || rate == pllt->rate) + return pllt->rate; - return NULL; + /* + * The rate provided by the setting is not an exact match, let's + * try to improve the result using the fractional parameter + */ + frac = __pll_params_with_frac(rate, *parent_rate, pllt, pll); + + return __pll_params_to_rate(*parent_rate, pllt, frac, pll); } static int meson_clk_pll_wait_lock(struct clk_hw *hw) @@ -154,13 +194,14 @@ static int meson_clk_pll_set_rate(struct clk_hw *hw, unsigned long rate, struct meson_clk_pll_data *pll = meson_clk_pll_data(clk); const struct pll_rate_table *pllt; unsigned long old_rate; + u16 frac = 0; if (parent_rate == 0 || rate == 0) return -EINVAL; old_rate = rate; - pllt = meson_clk_get_pll_settings(pll->table, rate); + pllt = meson_clk_get_pll_settings(rate, pll); if (!pllt) return -EINVAL; @@ -177,8 +218,10 @@ static int meson_clk_pll_set_rate(struct clk_hw *hw, unsigned long rate, if (MESON_PARM_APPLICABLE(&pll->od3)) meson_parm_write(clk->map, &pll->od3, pllt->od3); - if (MESON_PARM_APPLICABLE(&pll->frac)) - meson_parm_write(clk->map, &pll->frac, pllt->frac); + if (MESON_PARM_APPLICABLE(&pll->frac)) { + frac = __pll_params_with_frac(rate, parent_rate, pllt, pll); + meson_parm_write(clk->map, &pll->frac, frac); + } /* make sure the reset is cleared at this point */ meson_parm_write(clk->map, &pll->rst, 0); diff --git a/drivers/clk/meson/clkc.h b/drivers/clk/meson/clkc.h index ebd88afe1eb5..9cdcd9b6c16c 100644 --- a/drivers/clk/meson/clkc.h +++ b/drivers/clk/meson/clkc.h @@ -61,7 +61,6 @@ struct pll_rate_table { u16 od; u16 od2; u16 od3; - u16 frac; }; #define PLL_RATE(_r, _m, _n, _od) \ @@ -70,17 +69,7 @@ struct pll_rate_table { .m = (_m), \ .n = (_n), \ .od = (_od), \ - } \ - -#define PLL_FRAC_RATE(_r, _m, _n, _od, _od2, _frac) \ - { \ - .rate = (_r), \ - .m = (_m), \ - .n = (_n), \ - .od = (_od), \ - .od2 = (_od2), \ - .frac = (_frac), \ - } \ + } struct meson_clk_pll_data { struct parm m; -- cgit v1.2.3 From c77de0e5c95a249fd2d4105dbc619f436ec96345 Mon Sep 17 00:00:00 2001 From: Jerome Brunet Date: Mon, 19 Feb 2018 12:21:40 +0100 Subject: clk: meson: add gp0 frac parameter for axg and gxl Add the frac parameter for the gp0 pll of the axg and gxl. This allows to achieve rates between the fixed settings provided by the table. Signed-off-by: Jerome Brunet Signed-off-by: Neil Armstrong --- drivers/clk/meson/axg.c | 7 ++++++- drivers/clk/meson/gxbb.c | 7 ++++++- 2 files changed, 12 insertions(+), 2 deletions(-) diff --git a/drivers/clk/meson/axg.c b/drivers/clk/meson/axg.c index 4f13929cd594..892572a2d70f 100644 --- a/drivers/clk/meson/axg.c +++ b/drivers/clk/meson/axg.c @@ -193,7 +193,7 @@ static const struct pll_rate_table axg_gp0_pll_rate_table[] = { }; const struct reg_sequence axg_gp0_init_regs[] = { - { .reg = HHI_GP0_PLL_CNTL1, .def = 0xc084a000 }, + { .reg = HHI_GP0_PLL_CNTL1, .def = 0xc084b000 }, { .reg = HHI_GP0_PLL_CNTL2, .def = 0xb75020be }, { .reg = HHI_GP0_PLL_CNTL3, .def = 0x0a59a288 }, { .reg = HHI_GP0_PLL_CNTL4, .def = 0xc000004d }, @@ -218,6 +218,11 @@ static struct clk_regmap axg_gp0_pll = { .shift = 16, .width = 2, }, + .frac = { + .reg_off = HHI_GP0_PLL_CNTL1, + .shift = 0, + .width = 10, + }, .l = { .reg_off = HHI_GP0_PLL_CNTL, .shift = 31, diff --git a/drivers/clk/meson/gxbb.c b/drivers/clk/meson/gxbb.c index ac48eef0f490..fdeb372863de 100644 --- a/drivers/clk/meson/gxbb.c +++ b/drivers/clk/meson/gxbb.c @@ -437,7 +437,7 @@ static struct clk_regmap gxbb_gp0_pll = { }; const struct reg_sequence gxl_gp0_init_regs[] = { - { .reg = HHI_GP0_PLL_CNTL1, .def = 0xc084a000 }, + { .reg = HHI_GP0_PLL_CNTL1, .def = 0xc084b000 }, { .reg = HHI_GP0_PLL_CNTL2, .def = 0xb75020be }, { .reg = HHI_GP0_PLL_CNTL3, .def = 0x0a59a288 }, { .reg = HHI_GP0_PLL_CNTL4, .def = 0xc000004d }, @@ -462,6 +462,11 @@ static struct clk_regmap gxl_gp0_pll = { .shift = 16, .width = 2, }, + .frac = { + .reg_off = HHI_GP0_PLL_CNTL1, + .shift = 0, + .width = 10, + }, .l = { .reg_off = HHI_GP0_PLL_CNTL, .shift = 31, -- cgit v1.2.3 From 0a1be867b92a5afb93bce62e12ef76b7c2b777fd Mon Sep 17 00:00:00 2001 From: Jerome Brunet Date: Mon, 19 Feb 2018 12:21:41 +0100 Subject: clk: meson: add ROUND_CLOSEST to the pll driver Provide an option for the pll driver to round to the rate closest to the requested rate, instead of systematically rounding down. This may allow the provided rate to be closer to the requested rate when rounding up is not an issue Signed-off-by: Jerome Brunet Signed-off-by: Neil Armstrong --- drivers/clk/meson/clk-pll.c | 17 +++++++++++++---- drivers/clk/meson/clkc.h | 2 ++ 2 files changed, 15 insertions(+), 4 deletions(-) diff --git a/drivers/clk/meson/clk-pll.c b/drivers/clk/meson/clk-pll.c index d58961f35b71..65a7bd903551 100644 --- a/drivers/clk/meson/clk-pll.c +++ b/drivers/clk/meson/clk-pll.c @@ -105,7 +105,12 @@ static u16 __pll_params_with_frac(unsigned long rate, u64 val = (u64)rate * pllt->n; val <<= pllt->od + pllt->od2 + pllt->od3; - val = div_u64(val * frac_max, parent_rate); + + if (pll->flags & CLK_MESON_PLL_ROUND_CLOSEST) + val = DIV_ROUND_CLOSEST_ULL(val * frac_max, parent_rate); + else + val = div_u64(val * frac_max, parent_rate); + val -= pllt->m * frac_max; return min((u16)val, (u16)(frac_max - 1)); @@ -125,9 +130,13 @@ meson_clk_get_pll_settings(unsigned long rate, while (table[i].rate && table[i].rate <= rate) i++; - /* Select the setting of the rounded down rate */ - if (i != 0) - i--; + if (i != 0) { + if (MESON_PARM_APPLICABLE(&pll->frac) || + !(pll->flags & CLK_MESON_PLL_ROUND_CLOSEST) || + (abs(rate - table[i - 1].rate) < + abs(rate - table[i].rate))) + i--; + } return (struct pll_rate_table *)&table[i]; } diff --git a/drivers/clk/meson/clkc.h b/drivers/clk/meson/clkc.h index 9cdcd9b6c16c..8fe73c4edca8 100644 --- a/drivers/clk/meson/clkc.h +++ b/drivers/clk/meson/clkc.h @@ -71,6 +71,8 @@ struct pll_rate_table { .od = (_od), \ } +#define CLK_MESON_PLL_ROUND_CLOSEST BIT(0) + struct meson_clk_pll_data { struct parm m; struct parm n; -- cgit v1.2.3 From a4fb7df25de26d12feec4e96687121ec28480a71 Mon Sep 17 00:00:00 2001 From: Jerome Brunet Date: Mon, 19 Feb 2018 12:21:42 +0100 Subject: clk: meson: axg: add hifi clock bindings Add the new HIFI pll to axg clock bindings Signed-off-by: Jerome Brunet Signed-off-by: Neil Armstrong --- include/dt-bindings/clock/axg-clkc.h | 1 + 1 file changed, 1 insertion(+) diff --git a/include/dt-bindings/clock/axg-clkc.h b/include/dt-bindings/clock/axg-clkc.h index 941ac70e7f30..555937a25504 100644 --- a/include/dt-bindings/clock/axg-clkc.h +++ b/include/dt-bindings/clock/axg-clkc.h @@ -67,5 +67,6 @@ #define CLKID_AO_I2C 58 #define CLKID_SD_EMMC_B_CLK0 59 #define CLKID_SD_EMMC_C_CLK0 60 +#define CLKID_HIFI_PLL 69 #endif /* __AXG_CLKC_H */ -- cgit v1.2.3 From 093c3fac4619d267136dc4cb87b916c692fa07db Mon Sep 17 00:00:00 2001 From: Jerome Brunet Date: Mon, 19 Feb 2018 12:21:43 +0100 Subject: clk: meson: axg: add hifi pll clock Add the hifi pll to the axg clock controller. This clock maybe used as an input of the axg audio clock controller. It uses the same settings table as the gp0 pll but has a frac parameter allowing more precision. Signed-off-by: Jerome Brunet Signed-off-by: Neil Armstrong --- drivers/clk/meson/axg.c | 55 +++++++++++++++++++++++++++++++++++++++++++++++++ drivers/clk/meson/axg.h | 2 +- 2 files changed, 56 insertions(+), 1 deletion(-) diff --git a/drivers/clk/meson/axg.c b/drivers/clk/meson/axg.c index 892572a2d70f..ed4a645753c4 100644 --- a/drivers/clk/meson/axg.c +++ b/drivers/clk/meson/axg.c @@ -245,6 +245,59 @@ static struct clk_regmap axg_gp0_pll = { }, }; +const struct reg_sequence axg_hifi_init_regs[] = { + { .reg = HHI_HIFI_PLL_CNTL1, .def = 0xc084b000 }, + { .reg = HHI_HIFI_PLL_CNTL2, .def = 0xb75020be }, + { .reg = HHI_HIFI_PLL_CNTL3, .def = 0x0a6a3a88 }, + { .reg = HHI_HIFI_PLL_CNTL4, .def = 0xc000004d }, + { .reg = HHI_HIFI_PLL_CNTL5, .def = 0x00058000 }, + { .reg = HHI_HIFI_PLL_CNTL, .def = 0x40010250 }, +}; + +static struct clk_regmap axg_hifi_pll = { + .data = &(struct meson_clk_pll_data){ + .m = { + .reg_off = HHI_HIFI_PLL_CNTL, + .shift = 0, + .width = 9, + }, + .n = { + .reg_off = HHI_HIFI_PLL_CNTL, + .shift = 9, + .width = 5, + }, + .od = { + .reg_off = HHI_HIFI_PLL_CNTL, + .shift = 16, + .width = 2, + }, + .frac = { + .reg_off = HHI_HIFI_PLL_CNTL5, + .shift = 0, + .width = 13, + }, + .l = { + .reg_off = HHI_HIFI_PLL_CNTL, + .shift = 31, + .width = 1, + }, + .rst = { + .reg_off = HHI_HIFI_PLL_CNTL, + .shift = 29, + .width = 1, + }, + .table = axg_gp0_pll_rate_table, + .init_regs = axg_hifi_init_regs, + .init_count = ARRAY_SIZE(axg_hifi_init_regs), + .flags = CLK_MESON_PLL_ROUND_CLOSEST, + }, + .hw.init = &(struct clk_init_data){ + .name = "hifi_pll", + .ops = &meson_clk_pll_ops, + .parent_names = (const char *[]){ "xtal" }, + .num_parents = 1, + }, +}; static struct clk_fixed_factor axg_fclk_div2 = { .mult = 1, @@ -767,6 +820,7 @@ static struct clk_hw_onecell_data axg_hw_onecell_data = { [CLKID_MPLL1_DIV] = &axg_mpll1_div.hw, [CLKID_MPLL2_DIV] = &axg_mpll2_div.hw, [CLKID_MPLL3_DIV] = &axg_mpll3_div.hw, + [CLKID_HIFI_PLL] = &axg_hifi_pll.hw, [NR_CLKS] = NULL, }, .num = NR_CLKS, @@ -838,6 +892,7 @@ static struct clk_regmap *const axg_clk_regmaps[] = { &axg_fixed_pll, &axg_sys_pll, &axg_gp0_pll, + &axg_hifi_pll, }; static const struct of_device_id clkc_match_table[] = { diff --git a/drivers/clk/meson/axg.h b/drivers/clk/meson/axg.h index 4c1502a8b8c9..4916c7045c48 100644 --- a/drivers/clk/meson/axg.h +++ b/drivers/clk/meson/axg.h @@ -122,7 +122,7 @@ #define CLKID_MPLL2_DIV 67 #define CLKID_MPLL3_DIV 68 -#define NR_CLKS 69 +#define NR_CLKS 70 /* include the CLKIDs that have been made part of the DT binding */ #include -- cgit v1.2.3 From 513b67ac39b0ef91761d94d1d6e31bb84e380744 Mon Sep 17 00:00:00 2001 From: Jerome Brunet Date: Mon, 19 Feb 2018 12:21:44 +0100 Subject: clk: meson: add mpll pre-divider mpll clocks parent can actually be divided by 1 or 2. So far, this divider has always been set to 1, so the calculation was correct. Now that we know it exists, model the tree correctly. If we ever get a platform where the divider is different, we won't get into trouble Signed-off-by: Jerome Brunet Signed-off-by: Neil Armstrong --- drivers/clk/meson/axg.c | 24 ++++++++++++++++++++---- drivers/clk/meson/axg.h | 3 ++- drivers/clk/meson/gxbb.c | 23 ++++++++++++++++++++--- drivers/clk/meson/gxbb.h | 3 ++- drivers/clk/meson/meson8b.c | 22 +++++++++++++++++++--- drivers/clk/meson/meson8b.h | 3 ++- 6 files changed, 65 insertions(+), 13 deletions(-) diff --git a/drivers/clk/meson/axg.c b/drivers/clk/meson/axg.c index ed4a645753c4..2989087fb52d 100644 --- a/drivers/clk/meson/axg.c +++ b/drivers/clk/meson/axg.c @@ -354,6 +354,20 @@ static struct clk_fixed_factor axg_fclk_div7 = { }, }; +static struct clk_regmap axg_mpll_prediv = { + .data = &(struct clk_regmap_div_data){ + .offset = HHI_MPLL_CNTL5, + .shift = 12, + .width = 1, + }, + .hw.init = &(struct clk_init_data){ + .name = "mpll_prediv", + .ops = &clk_regmap_divider_ro_ops, + .parent_names = (const char *[]){ "fixed_pll" }, + .num_parents = 1, + }, +}; + static struct clk_regmap axg_mpll0_div = { .data = &(struct meson_clk_mpll_data){ .sdm = { @@ -386,7 +400,7 @@ static struct clk_regmap axg_mpll0_div = { .hw.init = &(struct clk_init_data){ .name = "mpll0_div", .ops = &meson_clk_mpll_ops, - .parent_names = (const char *[]){ "fixed_pll" }, + .parent_names = (const char *[]){ "mpll_prediv" }, .num_parents = 1, }, }; @@ -432,7 +446,7 @@ static struct clk_regmap axg_mpll1_div = { .hw.init = &(struct clk_init_data){ .name = "mpll1_div", .ops = &meson_clk_mpll_ops, - .parent_names = (const char *[]){ "fixed_pll" }, + .parent_names = (const char *[]){ "mpll_prediv" }, .num_parents = 1, }, }; @@ -478,7 +492,7 @@ static struct clk_regmap axg_mpll2_div = { .hw.init = &(struct clk_init_data){ .name = "mpll2_div", .ops = &meson_clk_mpll_ops, - .parent_names = (const char *[]){ "fixed_pll" }, + .parent_names = (const char *[]){ "mpll_prediv" }, .num_parents = 1, }, }; @@ -524,7 +538,7 @@ static struct clk_regmap axg_mpll3_div = { .hw.init = &(struct clk_init_data){ .name = "mpll3_div", .ops = &meson_clk_mpll_ops, - .parent_names = (const char *[]){ "fixed_pll" }, + .parent_names = (const char *[]){ "mpll_prediv" }, .num_parents = 1, }, }; @@ -821,6 +835,7 @@ static struct clk_hw_onecell_data axg_hw_onecell_data = { [CLKID_MPLL2_DIV] = &axg_mpll2_div.hw, [CLKID_MPLL3_DIV] = &axg_mpll3_div.hw, [CLKID_HIFI_PLL] = &axg_hifi_pll.hw, + [CLKID_MPLL_PREDIV] = &axg_mpll_prediv.hw, [NR_CLKS] = NULL, }, .num = NR_CLKS, @@ -893,6 +908,7 @@ static struct clk_regmap *const axg_clk_regmaps[] = { &axg_sys_pll, &axg_gp0_pll, &axg_hifi_pll, + &axg_mpll_prediv, }; static const struct of_device_id clkc_match_table[] = { diff --git a/drivers/clk/meson/axg.h b/drivers/clk/meson/axg.h index 4916c7045c48..6e5dc65041b5 100644 --- a/drivers/clk/meson/axg.h +++ b/drivers/clk/meson/axg.h @@ -121,8 +121,9 @@ #define CLKID_MPLL1_DIV 66 #define CLKID_MPLL2_DIV 67 #define CLKID_MPLL3_DIV 68 +#define CLKID_MPLL_PREDIV 70 -#define NR_CLKS 70 +#define NR_CLKS 71 /* include the CLKIDs that have been made part of the DT binding */ #include diff --git a/drivers/clk/meson/gxbb.c b/drivers/clk/meson/gxbb.c index fdeb372863de..b62d181a6d33 100644 --- a/drivers/clk/meson/gxbb.c +++ b/drivers/clk/meson/gxbb.c @@ -545,6 +545,20 @@ static struct clk_fixed_factor gxbb_fclk_div7 = { }, }; +static struct clk_regmap gxbb_mpll_prediv = { + .data = &(struct clk_regmap_div_data){ + .offset = HHI_MPLL_CNTL5, + .shift = 12, + .width = 1, + }, + .hw.init = &(struct clk_init_data){ + .name = "mpll_prediv", + .ops = &clk_regmap_divider_ro_ops, + .parent_names = (const char *[]){ "fixed_pll" }, + .num_parents = 1, + }, +}; + static struct clk_regmap gxbb_mpll0_div = { .data = &(struct meson_clk_mpll_data){ .sdm = { @@ -572,7 +586,7 @@ static struct clk_regmap gxbb_mpll0_div = { .hw.init = &(struct clk_init_data){ .name = "mpll0_div", .ops = &meson_clk_mpll_ops, - .parent_names = (const char *[]){ "fixed_pll" }, + .parent_names = (const char *[]){ "mpll_prediv" }, .num_parents = 1, }, }; @@ -613,7 +627,7 @@ static struct clk_regmap gxbb_mpll1_div = { .hw.init = &(struct clk_init_data){ .name = "mpll1_div", .ops = &meson_clk_mpll_ops, - .parent_names = (const char *[]){ "fixed_pll" }, + .parent_names = (const char *[]){ "mpll_prediv" }, .num_parents = 1, }, }; @@ -654,7 +668,7 @@ static struct clk_regmap gxbb_mpll2_div = { .hw.init = &(struct clk_init_data){ .name = "mpll2_div", .ops = &meson_clk_mpll_ops, - .parent_names = (const char *[]){ "fixed_pll" }, + .parent_names = (const char *[]){ "mpll_prediv" }, .num_parents = 1, }, }; @@ -1703,6 +1717,7 @@ static struct clk_hw_onecell_data gxbb_hw_onecell_data = { [CLKID_MPLL0_DIV] = &gxbb_mpll0_div.hw, [CLKID_MPLL1_DIV] = &gxbb_mpll1_div.hw, [CLKID_MPLL2_DIV] = &gxbb_mpll2_div.hw, + [CLKID_MPLL_PREDIV] = &gxbb_mpll_prediv.hw, [NR_CLKS] = NULL, }, .num = NR_CLKS, @@ -1853,6 +1868,7 @@ static struct clk_hw_onecell_data gxl_hw_onecell_data = { [CLKID_MPLL0_DIV] = &gxbb_mpll0_div.hw, [CLKID_MPLL1_DIV] = &gxbb_mpll1_div.hw, [CLKID_MPLL2_DIV] = &gxbb_mpll2_div.hw, + [CLKID_MPLL_PREDIV] = &gxbb_mpll_prediv.hw, [NR_CLKS] = NULL, }, .num = NR_CLKS, @@ -2005,6 +2021,7 @@ static struct clk_regmap *const gx_clk_regmaps[] = { &gxbb_cts_amclk_div, &gxbb_fixed_pll, &gxbb_sys_pll, + &gxbb_mpll_prediv, }; struct clkc_data { diff --git a/drivers/clk/meson/gxbb.h b/drivers/clk/meson/gxbb.h index a8e7b8884e95..afae007ae1ec 100644 --- a/drivers/clk/meson/gxbb.h +++ b/drivers/clk/meson/gxbb.h @@ -198,8 +198,9 @@ #define CLKID_MPLL0_DIV 142 #define CLKID_MPLL1_DIV 143 #define CLKID_MPLL2_DIV 144 +#define CLKID_MPLL_PREDIV 145 -#define NR_CLKS 145 +#define NR_CLKS 146 /* include the CLKIDs that have been made part of the DT binding */ #include diff --git a/drivers/clk/meson/meson8b.c b/drivers/clk/meson/meson8b.c index 62c54a75a1d2..f8b2f23c49de 100644 --- a/drivers/clk/meson/meson8b.c +++ b/drivers/clk/meson/meson8b.c @@ -280,6 +280,20 @@ static struct clk_fixed_factor meson8b_fclk_div7 = { }, }; +static struct clk_regmap meson8b_mpll_prediv = { + .data = &(struct clk_regmap_div_data){ + .offset = HHI_MPLL_CNTL5, + .shift = 12, + .width = 1, + }, + .hw.init = &(struct clk_init_data){ + .name = "mpll_prediv", + .ops = &clk_regmap_divider_ro_ops, + .parent_names = (const char *[]){ "fixed_pll" }, + .num_parents = 1, + }, +}; + static struct clk_regmap meson8b_mpll0_div = { .data = &(struct meson_clk_mpll_data){ .sdm = { @@ -307,7 +321,7 @@ static struct clk_regmap meson8b_mpll0_div = { .hw.init = &(struct clk_init_data){ .name = "mpll0_div", .ops = &meson_clk_mpll_ops, - .parent_names = (const char *[]){ "fixed_pll" }, + .parent_names = (const char *[]){ "mpll_prediv" }, .num_parents = 1, }, }; @@ -348,7 +362,7 @@ static struct clk_regmap meson8b_mpll1_div = { .hw.init = &(struct clk_init_data){ .name = "mpll1_div", .ops = &meson_clk_mpll_ops, - .parent_names = (const char *[]){ "fixed_pll" }, + .parent_names = (const char *[]){ "mpll_prediv" }, .num_parents = 1, }, }; @@ -389,7 +403,7 @@ static struct clk_regmap meson8b_mpll2_div = { .hw.init = &(struct clk_init_data){ .name = "mpll2_div", .ops = &meson_clk_mpll_ops, - .parent_names = (const char *[]){ "fixed_pll" }, + .parent_names = (const char *[]){ "mpll_prediv" }, .num_parents = 1, }, }; @@ -751,6 +765,7 @@ static struct clk_hw_onecell_data meson8b_hw_onecell_data = { [CLKID_CPU_DIV3] = &meson8b_cpu_div3.hw, [CLKID_CPU_SCALE_DIV] = &meson8b_cpu_scale_div.hw, [CLKID_CPU_SCALE_OUT_SEL] = &meson8b_cpu_scale_out_sel.hw, + [CLKID_MPLL_PREDIV] = &meson8b_mpll_prediv.hw, [CLK_NR_CLKS] = NULL, }, .num = CLK_NR_CLKS, @@ -850,6 +865,7 @@ static struct clk_regmap *const meson8b_clk_regmaps[] = { &meson8b_cpu_scale_div, &meson8b_cpu_scale_out_sel, &meson8b_cpu_clk, + &meson8b_mpll_prediv, }; static const struct meson8b_clk_reset_line { diff --git a/drivers/clk/meson/meson8b.h b/drivers/clk/meson/meson8b.h index 73dae83d9932..839ffc9da5f7 100644 --- a/drivers/clk/meson/meson8b.h +++ b/drivers/clk/meson/meson8b.h @@ -77,8 +77,9 @@ #define CLKID_CPU_DIV3 101 #define CLKID_CPU_SCALE_DIV 102 #define CLKID_CPU_SCALE_OUT_SEL 103 +#define CLKID_MPLL_PREDIV 104 -#define CLK_NR_CLKS 104 +#define CLK_NR_CLKS 105 /* * include the CLKID and RESETID that have -- cgit v1.2.3 From 05f814402d6174369b3b29832cbb5eb5ed287059 Mon Sep 17 00:00:00 2001 From: Jerome Brunet Date: Mon, 19 Feb 2018 12:21:45 +0100 Subject: clk: meson: add fdiv clock gates Fdiv fixed dividers clocks of the fixed_pll can actually gate independently. We never had an issue so far because these clocks were provided 'enabled' by the bootloader. Add these gates to enable/disable the clocks when required. Signed-off-by: Jerome Brunet Signed-off-by: Neil Armstrong --- drivers/clk/meson/axg.c | 95 ++++++++++++++++++++++++++++++++++++----- drivers/clk/meson/axg.h | 7 +++- drivers/clk/meson/gxbb.c | 100 +++++++++++++++++++++++++++++++++++++++----- drivers/clk/meson/gxbb.h | 7 +++- drivers/clk/meson/meson8b.c | 95 ++++++++++++++++++++++++++++++++++++----- drivers/clk/meson/meson8b.h | 7 +++- 6 files changed, 278 insertions(+), 33 deletions(-) diff --git a/drivers/clk/meson/axg.c b/drivers/clk/meson/axg.c index 2989087fb52d..99b2738c204f 100644 --- a/drivers/clk/meson/axg.c +++ b/drivers/clk/meson/axg.c @@ -299,61 +299,126 @@ static struct clk_regmap axg_hifi_pll = { }, }; -static struct clk_fixed_factor axg_fclk_div2 = { +static struct clk_fixed_factor axg_fclk_div2_div = { .mult = 1, .div = 2, .hw.init = &(struct clk_init_data){ - .name = "fclk_div2", + .name = "fclk_div2_div", .ops = &clk_fixed_factor_ops, .parent_names = (const char *[]){ "fixed_pll" }, .num_parents = 1, }, }; -static struct clk_fixed_factor axg_fclk_div3 = { +static struct clk_regmap axg_fclk_div2 = { + .data = &(struct clk_regmap_gate_data){ + .offset = HHI_MPLL_CNTL6, + .bit_idx = 27, + }, + .hw.init = &(struct clk_init_data){ + .name = "fclk_div2", + .ops = &clk_regmap_gate_ops, + .parent_names = (const char *[]){ "fclk_div2_div" }, + .num_parents = 1, + }, +}; + +static struct clk_fixed_factor axg_fclk_div3_div = { .mult = 1, .div = 3, .hw.init = &(struct clk_init_data){ - .name = "fclk_div3", + .name = "fclk_div3_div", .ops = &clk_fixed_factor_ops, .parent_names = (const char *[]){ "fixed_pll" }, .num_parents = 1, }, }; -static struct clk_fixed_factor axg_fclk_div4 = { +static struct clk_regmap axg_fclk_div3 = { + .data = &(struct clk_regmap_gate_data){ + .offset = HHI_MPLL_CNTL6, + .bit_idx = 28, + }, + .hw.init = &(struct clk_init_data){ + .name = "fclk_div3", + .ops = &clk_regmap_gate_ops, + .parent_names = (const char *[]){ "fclk_div3_div" }, + .num_parents = 1, + }, +}; + +static struct clk_fixed_factor axg_fclk_div4_div = { .mult = 1, .div = 4, .hw.init = &(struct clk_init_data){ - .name = "fclk_div4", + .name = "fclk_div4_div", .ops = &clk_fixed_factor_ops, .parent_names = (const char *[]){ "fixed_pll" }, .num_parents = 1, }, }; -static struct clk_fixed_factor axg_fclk_div5 = { +static struct clk_regmap axg_fclk_div4 = { + .data = &(struct clk_regmap_gate_data){ + .offset = HHI_MPLL_CNTL6, + .bit_idx = 29, + }, + .hw.init = &(struct clk_init_data){ + .name = "fclk_div4", + .ops = &clk_regmap_gate_ops, + .parent_names = (const char *[]){ "fclk_div4_div" }, + .num_parents = 1, + }, +}; + +static struct clk_fixed_factor axg_fclk_div5_div = { .mult = 1, .div = 5, .hw.init = &(struct clk_init_data){ - .name = "fclk_div5", + .name = "fclk_div5_div", .ops = &clk_fixed_factor_ops, .parent_names = (const char *[]){ "fixed_pll" }, .num_parents = 1, }, }; -static struct clk_fixed_factor axg_fclk_div7 = { +static struct clk_regmap axg_fclk_div5 = { + .data = &(struct clk_regmap_gate_data){ + .offset = HHI_MPLL_CNTL6, + .bit_idx = 30, + }, + .hw.init = &(struct clk_init_data){ + .name = "fclk_div5", + .ops = &clk_regmap_gate_ops, + .parent_names = (const char *[]){ "fclk_div5_div" }, + .num_parents = 1, + }, +}; + +static struct clk_fixed_factor axg_fclk_div7_div = { .mult = 1, .div = 7, .hw.init = &(struct clk_init_data){ - .name = "fclk_div7", + .name = "fclk_div7_div", .ops = &clk_fixed_factor_ops, .parent_names = (const char *[]){ "fixed_pll" }, .num_parents = 1, }, }; +static struct clk_regmap axg_fclk_div7 = { + .data = &(struct clk_regmap_gate_data){ + .offset = HHI_MPLL_CNTL6, + .bit_idx = 31, + }, + .hw.init = &(struct clk_init_data){ + .name = "fclk_div7", + .ops = &clk_regmap_gate_ops, + .parent_names = (const char *[]){ "fclk_div7_div" }, + .num_parents = 1, + }, +}; + static struct clk_regmap axg_mpll_prediv = { .data = &(struct clk_regmap_div_data){ .offset = HHI_MPLL_CNTL5, @@ -836,6 +901,11 @@ static struct clk_hw_onecell_data axg_hw_onecell_data = { [CLKID_MPLL3_DIV] = &axg_mpll3_div.hw, [CLKID_HIFI_PLL] = &axg_hifi_pll.hw, [CLKID_MPLL_PREDIV] = &axg_mpll_prediv.hw, + [CLKID_FCLK_DIV2_DIV] = &axg_fclk_div2_div.hw, + [CLKID_FCLK_DIV3_DIV] = &axg_fclk_div3_div.hw, + [CLKID_FCLK_DIV4_DIV] = &axg_fclk_div4_div.hw, + [CLKID_FCLK_DIV5_DIV] = &axg_fclk_div5_div.hw, + [CLKID_FCLK_DIV7_DIV] = &axg_fclk_div7_div.hw, [NR_CLKS] = NULL, }, .num = NR_CLKS, @@ -909,6 +979,11 @@ static struct clk_regmap *const axg_clk_regmaps[] = { &axg_gp0_pll, &axg_hifi_pll, &axg_mpll_prediv, + &axg_fclk_div2, + &axg_fclk_div3, + &axg_fclk_div4, + &axg_fclk_div5, + &axg_fclk_div7, }; static const struct of_device_id clkc_match_table[] = { diff --git a/drivers/clk/meson/axg.h b/drivers/clk/meson/axg.h index 6e5dc65041b5..b421df6a7ea0 100644 --- a/drivers/clk/meson/axg.h +++ b/drivers/clk/meson/axg.h @@ -122,8 +122,13 @@ #define CLKID_MPLL2_DIV 67 #define CLKID_MPLL3_DIV 68 #define CLKID_MPLL_PREDIV 70 +#define CLKID_FCLK_DIV2_DIV 71 +#define CLKID_FCLK_DIV3_DIV 72 +#define CLKID_FCLK_DIV4_DIV 73 +#define CLKID_FCLK_DIV5_DIV 74 +#define CLKID_FCLK_DIV7_DIV 75 -#define NR_CLKS 71 +#define NR_CLKS 76 /* include the CLKIDs that have been made part of the DT binding */ #include diff --git a/drivers/clk/meson/gxbb.c b/drivers/clk/meson/gxbb.c index b62d181a6d33..70b4669cf7d6 100644 --- a/drivers/clk/meson/gxbb.c +++ b/drivers/clk/meson/gxbb.c @@ -490,61 +490,126 @@ static struct clk_regmap gxl_gp0_pll = { }, }; -static struct clk_fixed_factor gxbb_fclk_div2 = { +static struct clk_fixed_factor gxbb_fclk_div2_div = { .mult = 1, .div = 2, .hw.init = &(struct clk_init_data){ - .name = "fclk_div2", + .name = "fclk_div2_div", .ops = &clk_fixed_factor_ops, .parent_names = (const char *[]){ "fixed_pll" }, .num_parents = 1, }, }; -static struct clk_fixed_factor gxbb_fclk_div3 = { +static struct clk_regmap gxbb_fclk_div2 = { + .data = &(struct clk_regmap_gate_data){ + .offset = HHI_MPLL_CNTL6, + .bit_idx = 27, + }, + .hw.init = &(struct clk_init_data){ + .name = "fclk_div2", + .ops = &clk_regmap_gate_ops, + .parent_names = (const char *[]){ "fclk_div2_div" }, + .num_parents = 1, + }, +}; + +static struct clk_fixed_factor gxbb_fclk_div3_div = { .mult = 1, .div = 3, .hw.init = &(struct clk_init_data){ - .name = "fclk_div3", + .name = "fclk_div3_div", .ops = &clk_fixed_factor_ops, .parent_names = (const char *[]){ "fixed_pll" }, .num_parents = 1, }, }; -static struct clk_fixed_factor gxbb_fclk_div4 = { +static struct clk_regmap gxbb_fclk_div3 = { + .data = &(struct clk_regmap_gate_data){ + .offset = HHI_MPLL_CNTL6, + .bit_idx = 28, + }, + .hw.init = &(struct clk_init_data){ + .name = "fclk_div3", + .ops = &clk_regmap_gate_ops, + .parent_names = (const char *[]){ "fclk_div3_div" }, + .num_parents = 1, + }, +}; + +static struct clk_fixed_factor gxbb_fclk_div4_div = { .mult = 1, .div = 4, .hw.init = &(struct clk_init_data){ - .name = "fclk_div4", + .name = "fclk_div4_div", .ops = &clk_fixed_factor_ops, .parent_names = (const char *[]){ "fixed_pll" }, .num_parents = 1, }, }; -static struct clk_fixed_factor gxbb_fclk_div5 = { +static struct clk_regmap gxbb_fclk_div4 = { + .data = &(struct clk_regmap_gate_data){ + .offset = HHI_MPLL_CNTL6, + .bit_idx = 29, + }, + .hw.init = &(struct clk_init_data){ + .name = "fclk_div4", + .ops = &clk_regmap_gate_ops, + .parent_names = (const char *[]){ "fclk_div4_div" }, + .num_parents = 1, + }, +}; + +static struct clk_fixed_factor gxbb_fclk_div5_div = { .mult = 1, .div = 5, .hw.init = &(struct clk_init_data){ - .name = "fclk_div5", + .name = "fclk_div5_div", .ops = &clk_fixed_factor_ops, .parent_names = (const char *[]){ "fixed_pll" }, .num_parents = 1, }, }; -static struct clk_fixed_factor gxbb_fclk_div7 = { +static struct clk_regmap gxbb_fclk_div5 = { + .data = &(struct clk_regmap_gate_data){ + .offset = HHI_MPLL_CNTL6, + .bit_idx = 30, + }, + .hw.init = &(struct clk_init_data){ + .name = "fclk_div5", + .ops = &clk_regmap_gate_ops, + .parent_names = (const char *[]){ "fclk_div5_div" }, + .num_parents = 1, + }, +}; + +static struct clk_fixed_factor gxbb_fclk_div7_div = { .mult = 1, .div = 7, .hw.init = &(struct clk_init_data){ - .name = "fclk_div7", + .name = "fclk_div7_div", .ops = &clk_fixed_factor_ops, .parent_names = (const char *[]){ "fixed_pll" }, .num_parents = 1, }, }; +static struct clk_regmap gxbb_fclk_div7 = { + .data = &(struct clk_regmap_gate_data){ + .offset = HHI_MPLL_CNTL6, + .bit_idx = 31, + }, + .hw.init = &(struct clk_init_data){ + .name = "fclk_div7", + .ops = &clk_regmap_gate_ops, + .parent_names = (const char *[]){ "fclk_div7_div" }, + .num_parents = 1, + }, +}; + static struct clk_regmap gxbb_mpll_prediv = { .data = &(struct clk_regmap_div_data){ .offset = HHI_MPLL_CNTL5, @@ -1718,6 +1783,11 @@ static struct clk_hw_onecell_data gxbb_hw_onecell_data = { [CLKID_MPLL1_DIV] = &gxbb_mpll1_div.hw, [CLKID_MPLL2_DIV] = &gxbb_mpll2_div.hw, [CLKID_MPLL_PREDIV] = &gxbb_mpll_prediv.hw, + [CLKID_FCLK_DIV2_DIV] = &gxbb_fclk_div2_div.hw, + [CLKID_FCLK_DIV3_DIV] = &gxbb_fclk_div3_div.hw, + [CLKID_FCLK_DIV4_DIV] = &gxbb_fclk_div4_div.hw, + [CLKID_FCLK_DIV5_DIV] = &gxbb_fclk_div5_div.hw, + [CLKID_FCLK_DIV7_DIV] = &gxbb_fclk_div7_div.hw, [NR_CLKS] = NULL, }, .num = NR_CLKS, @@ -1869,6 +1939,11 @@ static struct clk_hw_onecell_data gxl_hw_onecell_data = { [CLKID_MPLL1_DIV] = &gxbb_mpll1_div.hw, [CLKID_MPLL2_DIV] = &gxbb_mpll2_div.hw, [CLKID_MPLL_PREDIV] = &gxbb_mpll_prediv.hw, + [CLKID_FCLK_DIV2_DIV] = &gxbb_fclk_div2_div.hw, + [CLKID_FCLK_DIV3_DIV] = &gxbb_fclk_div3_div.hw, + [CLKID_FCLK_DIV4_DIV] = &gxbb_fclk_div4_div.hw, + [CLKID_FCLK_DIV5_DIV] = &gxbb_fclk_div5_div.hw, + [CLKID_FCLK_DIV7_DIV] = &gxbb_fclk_div7_div.hw, [NR_CLKS] = NULL, }, .num = NR_CLKS, @@ -2022,6 +2097,11 @@ static struct clk_regmap *const gx_clk_regmaps[] = { &gxbb_fixed_pll, &gxbb_sys_pll, &gxbb_mpll_prediv, + &gxbb_fclk_div2, + &gxbb_fclk_div3, + &gxbb_fclk_div4, + &gxbb_fclk_div5, + &gxbb_fclk_div7, }; struct clkc_data { diff --git a/drivers/clk/meson/gxbb.h b/drivers/clk/meson/gxbb.h index afae007ae1ec..9febf3f03739 100644 --- a/drivers/clk/meson/gxbb.h +++ b/drivers/clk/meson/gxbb.h @@ -199,8 +199,13 @@ #define CLKID_MPLL1_DIV 143 #define CLKID_MPLL2_DIV 144 #define CLKID_MPLL_PREDIV 145 +#define CLKID_FCLK_DIV2_DIV 146 +#define CLKID_FCLK_DIV3_DIV 147 +#define CLKID_FCLK_DIV4_DIV 148 +#define CLKID_FCLK_DIV5_DIV 149 +#define CLKID_FCLK_DIV7_DIV 150 -#define NR_CLKS 146 +#define NR_CLKS 151 /* include the CLKIDs that have been made part of the DT binding */ #include diff --git a/drivers/clk/meson/meson8b.c b/drivers/clk/meson/meson8b.c index f8b2f23c49de..9c9e3d180120 100644 --- a/drivers/clk/meson/meson8b.c +++ b/drivers/clk/meson/meson8b.c @@ -225,61 +225,126 @@ static struct clk_regmap meson8b_sys_pll = { }, }; -static struct clk_fixed_factor meson8b_fclk_div2 = { +static struct clk_fixed_factor meson8b_fclk_div2_div = { .mult = 1, .div = 2, .hw.init = &(struct clk_init_data){ - .name = "fclk_div2", + .name = "fclk_div2_div", .ops = &clk_fixed_factor_ops, .parent_names = (const char *[]){ "fixed_pll" }, .num_parents = 1, }, }; -static struct clk_fixed_factor meson8b_fclk_div3 = { +static struct clk_regmap meson8b_fclk_div2 = { + .data = &(struct clk_regmap_gate_data){ + .offset = HHI_MPLL_CNTL6, + .bit_idx = 27, + }, + .hw.init = &(struct clk_init_data){ + .name = "fclk_div2", + .ops = &clk_regmap_gate_ops, + .parent_names = (const char *[]){ "fclk_div2_div" }, + .num_parents = 1, + }, +}; + +static struct clk_fixed_factor meson8b_fclk_div3_div = { .mult = 1, .div = 3, .hw.init = &(struct clk_init_data){ - .name = "fclk_div3", + .name = "fclk_div_div3", .ops = &clk_fixed_factor_ops, .parent_names = (const char *[]){ "fixed_pll" }, .num_parents = 1, }, }; -static struct clk_fixed_factor meson8b_fclk_div4 = { +static struct clk_regmap meson8b_fclk_div3 = { + .data = &(struct clk_regmap_gate_data){ + .offset = HHI_MPLL_CNTL6, + .bit_idx = 28, + }, + .hw.init = &(struct clk_init_data){ + .name = "fclk_div3", + .ops = &clk_regmap_gate_ops, + .parent_names = (const char *[]){ "fclk_div3_div" }, + .num_parents = 1, + }, +}; + +static struct clk_fixed_factor meson8b_fclk_div4_div = { .mult = 1, .div = 4, .hw.init = &(struct clk_init_data){ - .name = "fclk_div4", + .name = "fclk_div4_div", .ops = &clk_fixed_factor_ops, .parent_names = (const char *[]){ "fixed_pll" }, .num_parents = 1, }, }; -static struct clk_fixed_factor meson8b_fclk_div5 = { +static struct clk_regmap meson8b_fclk_div4 = { + .data = &(struct clk_regmap_gate_data){ + .offset = HHI_MPLL_CNTL6, + .bit_idx = 29, + }, + .hw.init = &(struct clk_init_data){ + .name = "fclk_div4", + .ops = &clk_regmap_gate_ops, + .parent_names = (const char *[]){ "fclk_div4_div" }, + .num_parents = 1, + }, +}; + +static struct clk_fixed_factor meson8b_fclk_div5_div = { .mult = 1, .div = 5, .hw.init = &(struct clk_init_data){ - .name = "fclk_div5", + .name = "fclk_div5_div", .ops = &clk_fixed_factor_ops, .parent_names = (const char *[]){ "fixed_pll" }, .num_parents = 1, }, }; -static struct clk_fixed_factor meson8b_fclk_div7 = { +static struct clk_regmap meson8b_fclk_div5 = { + .data = &(struct clk_regmap_gate_data){ + .offset = HHI_MPLL_CNTL6, + .bit_idx = 30, + }, + .hw.init = &(struct clk_init_data){ + .name = "fclk_div5", + .ops = &clk_regmap_gate_ops, + .parent_names = (const char *[]){ "fclk_div5_div" }, + .num_parents = 1, + }, +}; + +static struct clk_fixed_factor meson8b_fclk_div7_div = { .mult = 1, .div = 7, .hw.init = &(struct clk_init_data){ - .name = "fclk_div7", + .name = "fclk_div7_div", .ops = &clk_fixed_factor_ops, .parent_names = (const char *[]){ "fixed_pll" }, .num_parents = 1, }, }; +static struct clk_regmap meson8b_fclk_div7 = { + .data = &(struct clk_regmap_gate_data){ + .offset = HHI_MPLL_CNTL6, + .bit_idx = 31, + }, + .hw.init = &(struct clk_init_data){ + .name = "fclk_div7", + .ops = &clk_regmap_gate_ops, + .parent_names = (const char *[]){ "fclk_div7_div" }, + .num_parents = 1, + }, +}; + static struct clk_regmap meson8b_mpll_prediv = { .data = &(struct clk_regmap_div_data){ .offset = HHI_MPLL_CNTL5, @@ -766,6 +831,11 @@ static struct clk_hw_onecell_data meson8b_hw_onecell_data = { [CLKID_CPU_SCALE_DIV] = &meson8b_cpu_scale_div.hw, [CLKID_CPU_SCALE_OUT_SEL] = &meson8b_cpu_scale_out_sel.hw, [CLKID_MPLL_PREDIV] = &meson8b_mpll_prediv.hw, + [CLKID_FCLK_DIV2_DIV] = &meson8b_fclk_div2_div.hw, + [CLKID_FCLK_DIV3_DIV] = &meson8b_fclk_div3_div.hw, + [CLKID_FCLK_DIV4_DIV] = &meson8b_fclk_div4_div.hw, + [CLKID_FCLK_DIV5_DIV] = &meson8b_fclk_div5_div.hw, + [CLKID_FCLK_DIV7_DIV] = &meson8b_fclk_div7_div.hw, [CLK_NR_CLKS] = NULL, }, .num = CLK_NR_CLKS, @@ -866,6 +936,11 @@ static struct clk_regmap *const meson8b_clk_regmaps[] = { &meson8b_cpu_scale_out_sel, &meson8b_cpu_clk, &meson8b_mpll_prediv, + &meson8b_fclk_div2, + &meson8b_fclk_div3, + &meson8b_fclk_div4, + &meson8b_fclk_div5, + &meson8b_fclk_div7, }; static const struct meson8b_clk_reset_line { diff --git a/drivers/clk/meson/meson8b.h b/drivers/clk/meson/meson8b.h index 839ffc9da5f7..6e414bd36981 100644 --- a/drivers/clk/meson/meson8b.h +++ b/drivers/clk/meson/meson8b.h @@ -78,8 +78,13 @@ #define CLKID_CPU_SCALE_DIV 102 #define CLKID_CPU_SCALE_OUT_SEL 103 #define CLKID_MPLL_PREDIV 104 +#define CLKID_FCLK_DIV2_DIV 105 +#define CLKID_FCLK_DIV3_DIV 106 +#define CLKID_FCLK_DIV4_DIV 107 +#define CLKID_FCLK_DIV5_DIV 108 +#define CLKID_FCLK_DIV7_DIV 109 -#define CLK_NR_CLKS 105 +#define CLK_NR_CLKS 110 /* * include the CLKID and RESETID that have -- cgit v1.2.3 From 5b13ef64eebdc9e989fac2a3eb9aaa252a3edda6 Mon Sep 17 00:00:00 2001 From: Jerome Brunet Date: Mon, 19 Feb 2018 12:21:46 +0100 Subject: clk: meson: clean-up clk81 clocks clk81 is a composite clock which parents all the peripheral clocks of the platform. It is a critical clock which is used as provided by the bootloader. We don't want to change its rate or reparent it, ever. Remove the CLK_IGNORE_UNUSED on the mux and divider. These clock can't gate so the flag is useless, and the gate is already critical, so the clock won't ever be unused. Remove CLK_SET_RATE_NO_REPARENT from mux, it is useless since the mux is read-only. Remove CLK_SET_RATE_PARENT from the gate and divider and use ro_ops for the divider. A peripheral clock should not try to change the rate of clk81. Stopping the rate propagation is good way to make sure such request would be ignored. Signed-off-by: Jerome Brunet Signed-off-by: Neil Armstrong --- drivers/clk/meson/gxbb.c | 6 ++---- drivers/clk/meson/meson8b.c | 6 ++---- 2 files changed, 4 insertions(+), 8 deletions(-) diff --git a/drivers/clk/meson/gxbb.c b/drivers/clk/meson/gxbb.c index 70b4669cf7d6..db5e0dcbb5aa 100644 --- a/drivers/clk/meson/gxbb.c +++ b/drivers/clk/meson/gxbb.c @@ -775,7 +775,6 @@ static struct clk_regmap gxbb_mpeg_clk_sel = { */ .parent_names = clk81_parent_names, .num_parents = ARRAY_SIZE(clk81_parent_names), - .flags = (CLK_SET_RATE_NO_REPARENT | CLK_IGNORE_UNUSED), }, }; @@ -787,10 +786,9 @@ static struct clk_regmap gxbb_mpeg_clk_div = { }, .hw.init = &(struct clk_init_data){ .name = "mpeg_clk_div", - .ops = &clk_regmap_divider_ops, + .ops = &clk_regmap_divider_ro_ops, .parent_names = (const char *[]){ "mpeg_clk_sel" }, .num_parents = 1, - .flags = (CLK_SET_RATE_PARENT | CLK_IGNORE_UNUSED), }, }; @@ -805,7 +803,7 @@ static struct clk_regmap gxbb_clk81 = { .ops = &clk_regmap_gate_ops, .parent_names = (const char *[]){ "mpeg_clk_div" }, .num_parents = 1, - .flags = (CLK_SET_RATE_PARENT | CLK_IS_CRITICAL), + .flags = CLK_IS_CRITICAL, }, }; diff --git a/drivers/clk/meson/meson8b.c b/drivers/clk/meson/meson8b.c index 9c9e3d180120..b324c44d36eb 100644 --- a/drivers/clk/meson/meson8b.c +++ b/drivers/clk/meson/meson8b.c @@ -506,7 +506,6 @@ static struct clk_regmap meson8b_mpeg_clk_sel = { .parent_names = (const char *[]){ "fclk_div3", "fclk_div4", "fclk_div5" }, .num_parents = 3, - .flags = (CLK_SET_RATE_NO_REPARENT | CLK_IGNORE_UNUSED), }, }; @@ -518,10 +517,9 @@ struct clk_regmap meson8b_mpeg_clk_div = { }, .hw.init = &(struct clk_init_data){ .name = "mpeg_clk_div", - .ops = &clk_regmap_divider_ops, + .ops = &clk_regmap_divider_ro_ops, .parent_names = (const char *[]){ "mpeg_clk_sel" }, .num_parents = 1, - .flags = (CLK_SET_RATE_PARENT | CLK_IGNORE_UNUSED), }, }; @@ -535,7 +533,7 @@ struct clk_regmap meson8b_clk81 = { .ops = &clk_regmap_gate_ops, .parent_names = (const char *[]){ "mpeg_clk_div" }, .num_parents = 1, - .flags = (CLK_SET_RATE_PARENT | CLK_IS_CRITICAL), + .flags = CLK_IS_CRITICAL, }, }; -- cgit v1.2.3 From 5b23fceec1ff94305c5d1accde018cae27448005 Mon Sep 17 00:00:00 2001 From: Marek Szyprowski Date: Tue, 13 Mar 2018 11:46:12 +0100 Subject: clk: samsung: exynos5250: Add missing clocks for FIMC LITE SYSMMU devices FIMC LITE SYSMMU devices are defined in exynos5250.dtsi, but clocks for them are not instantiated by Exynos5250 clock provider driver. Add needed definitions for those clocks to fix IOMMU probe failure: ERROR: could not get clock /soc/sysmmu@13c40000:sysmmu(0) exynos-sysmmu 13c40000.sysmmu: Failed to get device clock(s)! exynos-sysmmu: probe of 13c40000.sysmmu failed with error -38 ERROR: could not get clock /soc/sysmmu@13c50000:sysmmu(0) exynos-sysmmu 13c50000.sysmmu: Failed to get device clock(s)! exynos-sysmmu: probe of 13c50000.sysmmu failed with error -38 Signed-off-by: Marek Szyprowski Fixes: bfed1074f213 ("clk: exynos5250: Add missing sysmmu clocks for DISP and ISP blocks") Acked-by: Chanwoo Choi Signed-off-by: Sylwester Nawrocki --- drivers/clk/samsung/clk-exynos5250.c | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/drivers/clk/samsung/clk-exynos5250.c b/drivers/clk/samsung/clk-exynos5250.c index 06e5ddcb30db..347fd80c351b 100644 --- a/drivers/clk/samsung/clk-exynos5250.c +++ b/drivers/clk/samsung/clk-exynos5250.c @@ -561,6 +561,8 @@ static const struct samsung_gate_clock exynos5250_gate_clks[] __initconst = { 0), GATE(CLK_GSCL3, "gscl3", "mout_aclk266_gscl_sub", GATE_IP_GSCL, 3, 0, 0), + GATE(CLK_CAMIF_TOP, "camif_top", "mout_aclk266_gscl_sub", + GATE_IP_GSCL, 4, 0, 0), GATE(CLK_GSCL_WA, "gscl_wa", "div_gscl_wa", GATE_IP_GSCL, 5, 0, 0), GATE(CLK_GSCL_WB, "gscl_wb", "div_gscl_wb", GATE_IP_GSCL, 6, 0, 0), GATE(CLK_SMMU_GSCL0, "smmu_gscl0", "mout_aclk266_gscl_sub", @@ -571,6 +573,10 @@ static const struct samsung_gate_clock exynos5250_gate_clks[] __initconst = { GATE_IP_GSCL, 9, 0, 0), GATE(CLK_SMMU_GSCL3, "smmu_gscl3", "mout_aclk266_gscl_sub", GATE_IP_GSCL, 10, 0, 0), + GATE(CLK_SMMU_FIMC_LITE0, "smmu_fimc_lite0", "mout_aclk266_gscl_sub", + GATE_IP_GSCL, 11, 0, 0), + GATE(CLK_SMMU_FIMC_LITE1, "smmu_fimc_lite1", "mout_aclk266_gscl_sub", + GATE_IP_GSCL, 12, 0, 0), GATE(CLK_MFC, "mfc", "mout_aclk333_sub", GATE_IP_MFC, 0, 0, 0), -- cgit v1.2.3 From 5d1c04dde0eb396aec781c825a025e69c48b67cd Mon Sep 17 00:00:00 2001 From: Stephen Boyd Date: Wed, 14 Mar 2018 15:36:31 -0700 Subject: clk: meson: Drop unused local variable and add static Fixes the following warnings: drivers/clk/meson/meson8b.c:512:19: warning: symbol 'meson8b_mpeg_clk_div' was not declared. Should it be static? drivers/clk/meson/meson8b.c:526:19: warning: symbol 'meson8b_clk81' was not declared. Should it be static? drivers/clk/meson/meson8b.c:540:19: warning: symbol 'meson8b_cpu_in_sel' was not declared. Should it be static? drivers/clk/meson/meson8b.c:591:19: warning: symbol 'meson8b_cpu_scale_div' was not declared. Should it be static? drivers/clk/meson/meson8b.c:608:19: warning: symbol 'meson8b_cpu_scale_out_sel' was not declared. Should it be static? drivers/clk/meson/meson8b.c:626:19: warning: symbol 'meson8b_cpu_clk' was not declared. Should it be static? drivers/clk/meson/gxbb.c:392:27: warning: symbol 'gxbb_gp0_init_regs' was not declared. Should it be static? drivers/clk/meson/gxbb.c:439:27: warning: symbol 'gxl_gp0_init_regs' was not declared. Should it be static? drivers/clk/meson/axg.c:195:27: warning: symbol 'axg_gp0_init_regs' was not declared. Should it be static? drivers/clk/meson/axg.c:248:27: warning: symbol 'axg_hifi_init_regs' was not declared. Should it be static? drivers/clk/meson/meson8b.c: In function 'meson8b_clkc_probe': drivers/clk/meson/meson8b.c:1052:14: warning: unused variable 'clk' [-Wunused-variable] Signed-off-by: Stephen Boyd --- drivers/clk/meson/axg.c | 4 ++-- drivers/clk/meson/gxbb.c | 4 ++-- drivers/clk/meson/meson8b.c | 13 ++++++------- 3 files changed, 10 insertions(+), 11 deletions(-) diff --git a/drivers/clk/meson/axg.c b/drivers/clk/meson/axg.c index 99b2738c204f..5f5d468c1efe 100644 --- a/drivers/clk/meson/axg.c +++ b/drivers/clk/meson/axg.c @@ -192,7 +192,7 @@ static const struct pll_rate_table axg_gp0_pll_rate_table[] = { { /* sentinel */ }, }; -const struct reg_sequence axg_gp0_init_regs[] = { +static const struct reg_sequence axg_gp0_init_regs[] = { { .reg = HHI_GP0_PLL_CNTL1, .def = 0xc084b000 }, { .reg = HHI_GP0_PLL_CNTL2, .def = 0xb75020be }, { .reg = HHI_GP0_PLL_CNTL3, .def = 0x0a59a288 }, @@ -245,7 +245,7 @@ static struct clk_regmap axg_gp0_pll = { }, }; -const struct reg_sequence axg_hifi_init_regs[] = { +static const struct reg_sequence axg_hifi_init_regs[] = { { .reg = HHI_HIFI_PLL_CNTL1, .def = 0xc084b000 }, { .reg = HHI_HIFI_PLL_CNTL2, .def = 0xb75020be }, { .reg = HHI_HIFI_PLL_CNTL3, .def = 0x0a6a3a88 }, diff --git a/drivers/clk/meson/gxbb.c b/drivers/clk/meson/gxbb.c index db5e0dcbb5aa..b1e4d9557610 100644 --- a/drivers/clk/meson/gxbb.c +++ b/drivers/clk/meson/gxbb.c @@ -389,7 +389,7 @@ static struct clk_regmap gxbb_sys_pll = { }, }; -const struct reg_sequence gxbb_gp0_init_regs[] = { +static const struct reg_sequence gxbb_gp0_init_regs[] = { { .reg = HHI_GP0_PLL_CNTL2, .def = 0x69c80000 }, { .reg = HHI_GP0_PLL_CNTL3, .def = 0x0a5590c4 }, { .reg = HHI_GP0_PLL_CNTL4, .def = 0x0000500d }, @@ -436,7 +436,7 @@ static struct clk_regmap gxbb_gp0_pll = { }, }; -const struct reg_sequence gxl_gp0_init_regs[] = { +static const struct reg_sequence gxl_gp0_init_regs[] = { { .reg = HHI_GP0_PLL_CNTL1, .def = 0xc084b000 }, { .reg = HHI_GP0_PLL_CNTL2, .def = 0xb75020be }, { .reg = HHI_GP0_PLL_CNTL3, .def = 0x0a59a288 }, diff --git a/drivers/clk/meson/meson8b.c b/drivers/clk/meson/meson8b.c index b324c44d36eb..cc2992493e0b 100644 --- a/drivers/clk/meson/meson8b.c +++ b/drivers/clk/meson/meson8b.c @@ -509,7 +509,7 @@ static struct clk_regmap meson8b_mpeg_clk_sel = { }, }; -struct clk_regmap meson8b_mpeg_clk_div = { +static struct clk_regmap meson8b_mpeg_clk_div = { .data = &(struct clk_regmap_div_data){ .offset = HHI_MPEG_CLK_CNTL, .shift = 0, @@ -523,7 +523,7 @@ struct clk_regmap meson8b_mpeg_clk_div = { }, }; -struct clk_regmap meson8b_clk81 = { +static struct clk_regmap meson8b_clk81 = { .data = &(struct clk_regmap_gate_data){ .offset = HHI_MPEG_CLK_CNTL, .bit_idx = 7, @@ -537,7 +537,7 @@ struct clk_regmap meson8b_clk81 = { }, }; -struct clk_regmap meson8b_cpu_in_sel = { +static struct clk_regmap meson8b_cpu_in_sel = { .data = &(struct clk_regmap_mux_data){ .offset = HHI_SYS_CPU_CLK_CNTL0, .mask = 0x1, @@ -588,7 +588,7 @@ static const struct clk_div_table cpu_scale_table[] = { { /* sentinel */ }, }; -struct clk_regmap meson8b_cpu_scale_div = { +static struct clk_regmap meson8b_cpu_scale_div = { .data = &(struct clk_regmap_div_data){ .offset = HHI_SYS_CPU_CLK_CNTL1, .shift = 20, @@ -605,7 +605,7 @@ struct clk_regmap meson8b_cpu_scale_div = { }, }; -struct clk_regmap meson8b_cpu_scale_out_sel = { +static struct clk_regmap meson8b_cpu_scale_out_sel = { .data = &(struct clk_regmap_mux_data){ .offset = HHI_SYS_CPU_CLK_CNTL0, .mask = 0x3, @@ -623,7 +623,7 @@ struct clk_regmap meson8b_cpu_scale_out_sel = { }, }; -struct clk_regmap meson8b_cpu_clk = { +static struct clk_regmap meson8b_cpu_clk = { .data = &(struct clk_regmap_mux_data){ .offset = HHI_SYS_CPU_CLK_CNTL0, .mask = 0x1, @@ -1049,7 +1049,6 @@ static const struct regmap_config clkc_regmap_config = { static int meson8b_clkc_probe(struct platform_device *pdev) { int ret, i; - struct clk *clk; struct device *dev = &pdev->dev; struct regmap *map; -- cgit v1.2.3 From 182c084da5d1e4d7c02d913de154cf5167521580 Mon Sep 17 00:00:00 2001 From: Sylwester Nawrocki Date: Wed, 14 Mar 2018 12:32:26 +0100 Subject: clk: samsung: Add fout=196608001 Hz EPLL rate entry for exynos4412 This additional frequency is required for HDMI audio support on Odroid U3 board. Signed-off-by: Sylwester Nawrocki --- drivers/clk/samsung/clk-exynos4.c | 1 + 1 file changed, 1 insertion(+) diff --git a/drivers/clk/samsung/clk-exynos4.c b/drivers/clk/samsung/clk-exynos4.c index edf125525a36..0421960eb963 100644 --- a/drivers/clk/samsung/clk-exynos4.c +++ b/drivers/clk/samsung/clk-exynos4.c @@ -1319,6 +1319,7 @@ static const struct samsung_pll_rate_table exynos4x12_apll_rates[] __initconst = }; static const struct samsung_pll_rate_table exynos4x12_epll_rates[] __initconst = { + PLL_36XX_RATE(24 * MHZ, 196608001, 197, 3, 3, -25690), PLL_36XX_RATE(24 * MHZ, 192000000, 48, 3, 1, 0), PLL_36XX_RATE(24 * MHZ, 180633605, 45, 3, 1, 10381), PLL_36XX_RATE(24 * MHZ, 180000000, 45, 3, 1, 0), -- cgit v1.2.3 From 1871f0fcba5debf21d5b0475e6a064dc5c21a026 Mon Sep 17 00:00:00 2001 From: Stephen Boyd Date: Fri, 16 Mar 2018 09:21:40 -0700 Subject: clk: samsung: Mark a few things static Running sparse on the samsung clk directory has some noise that we can fix to look for future problems easier. drivers/clk/samsung/clk-s3c2443.c:111:26: warning: symbol 's3c2443_common_muxes' was not declared. Should it be static? drivers/clk/samsung/clk-s3c2443.c:139:26: warning: symbol 's3c2443_common_dividers' was not declared. Should it be static? drivers/clk/samsung/clk-s3c2443.c:152:27: warning: symbol 's3c2443_common_gates' was not declared. Should it be static? drivers/clk/samsung/clk-s3c2443.c:186:28: warning: symbol 's3c2443_common_aliases' was not declared. Should it be static? drivers/clk/samsung/clk-s3c2443.c:241:26: warning: symbol 's3c2416_dividers' was not declared. Should it be static? drivers/clk/samsung/clk-s3c2443.c:247:26: warning: symbol 's3c2416_muxes' was not declared. Should it be static? drivers/clk/samsung/clk-s3c2443.c:253:27: warning: symbol 's3c2416_gates' was not declared. Should it be static? drivers/clk/samsung/clk-s3c2443.c:263:28: warning: symbol 's3c2416_aliases' was not declared. Should it be static? drivers/clk/samsung/clk-s3c2443.c:291:26: warning: symbol 's3c2443_dividers' was not declared. Should it be static? drivers/clk/samsung/clk-s3c2443.c:296:27: warning: symbol 's3c2443_gates' was not declared. Should it be static? drivers/clk/samsung/clk-s3c2443.c:305:28: warning: symbol 's3c2443_aliases' was not declared. Should it be static? drivers/clk/samsung/clk-s3c2443.c:321:26: warning: symbol 's3c2450_dividers' was not declared. Should it be static? drivers/clk/samsung/clk-s3c2443.c:328:26: warning: symbol 's3c2450_muxes' was not declared. Should it be static? drivers/clk/samsung/clk-s3c2443.c:334:27: warning: symbol 's3c2450_gates' was not declared. Should it be static? drivers/clk/samsung/clk-s3c2443.c:345:28: warning: symbol 's3c2450_aliases' was not declared. Should it be static? drivers/clk/samsung/clk-s3c2443.c:368:33: warning: symbol 's3c2443_common_frate_clks' was not declared. Should it be static? drivers/clk/samsung/clk-s3c2443.c:464:49: warning: Using plain integer as NULL pointer drivers/clk/samsung/clk-s3c2443.c:470:49: warning: Using plain integer as NULL pointer drivers/clk/samsung/clk-s3c2443.c:476:49: warning: Using plain integer as NULL pointer drivers/clk/samsung/clk-s3c2412.c:96:26: warning: symbol 's3c2412_dividers' was not declared. Should it be static? drivers/clk/samsung/clk-s3c2412.c:108:35: warning: symbol 's3c2412_ffactor' was not declared. Should it be static? drivers/clk/samsung/clk-s3c2412.c:128:26: warning: symbol 's3c2412_muxes' was not declared. Should it be static? drivers/clk/samsung/clk-s3c2412.c:146:27: warning: symbol 's3c2412_gates' was not declared. Should it be static? drivers/clk/samsung/clk-s3c2412.c:177:28: warning: symbol 's3c2412_aliases' was not declared. Should it be static? drivers/clk/samsung/clk-s3c2412.c:227:33: warning: symbol 's3c2412_common_frate_clks' was not declared. Should it be static? drivers/clk/samsung/clk-s3c2412.c:292:43: warning: Using plain integer as NULL pointer drivers/clk/samsung/clk-s3c2410.c:98:26: warning: symbol 's3c2410_common_muxes' was not declared. Should it be static? drivers/clk/samsung/clk-s3c2410.c:114:26: warning: symbol 's3c2410_common_dividers' was not declared. Should it be static? drivers/clk/samsung/clk-s3c2410.c:119:27: warning: symbol 's3c2410_common_gates' was not declared. Should it be static? drivers/clk/samsung/clk-s3c2410.c:138:28: warning: symbol 's3c2410_common_aliases' was not declared. Should it be static? drivers/clk/samsung/clk-s3c2410.c:203:26: warning: symbol 's3c2410_dividers' was not declared. Should it be static? drivers/clk/samsung/clk-s3c2410.c:207:35: warning: symbol 's3c2410_ffactor' was not declared. Should it be static? drivers/clk/samsung/clk-s3c2410.c:218:28: warning: symbol 's3c2410_aliases' was not declared. Should it be static? drivers/clk/samsung/clk-s3c2410.c:272:26: warning: symbol 's3c244x_common_muxes' was not declared. Should it be static? drivers/clk/samsung/clk-s3c2410.c:277:35: warning: symbol 's3c244x_common_ffactor' was not declared. Should it be static? drivers/clk/samsung/clk-s3c2410.c:294:26: warning: symbol 's3c244x_common_dividers' was not declared. Should it be static? drivers/clk/samsung/clk-s3c2410.c:302:27: warning: symbol 's3c244x_common_gates' was not declared. Should it be static? drivers/clk/samsung/clk-s3c2410.c:306:28: warning: symbol 's3c244x_common_aliases' was not declared. Should it be static? drivers/clk/samsung/clk-s3c2410.c:321:26: warning: symbol 's3c2440_muxes' was not declared. Should it be static? drivers/clk/samsung/clk-s3c2410.c:325:27: warning: symbol 's3c2440_gates' was not declared. Should it be static? drivers/clk/samsung/clk-s3c2410.c:331:35: warning: symbol 's3c2442_ffactor' was not declared. Should it be static? drivers/clk/samsung/clk-s3c2410.c:337:26: warning: symbol 's3c2442_muxes' was not declared. Should it be static? drivers/clk/samsung/clk-s3c2410.c:346:33: warning: symbol 's3c2410_common_frate_clks' was not declared. Should it be static? drivers/clk/samsung/clk-s3c2410.c:471:49: warning: Using plain integer as NULL pointer drivers/clk/samsung/clk-s3c2410.c:477:49: warning: Using plain integer as NULL pointer drivers/clk/samsung/clk-s3c2410.c:483:49: warning: Using plain integer as NULL pointer Signed-off-by: Stephen Boyd --- drivers/clk/samsung/clk-s3c2410.c | 40 +++++++++++++++++++-------------------- drivers/clk/samsung/clk-s3c2412.c | 14 +++++++------- drivers/clk/samsung/clk-s3c2443.c | 38 ++++++++++++++++++------------------- 3 files changed, 46 insertions(+), 46 deletions(-) diff --git a/drivers/clk/samsung/clk-s3c2410.c b/drivers/clk/samsung/clk-s3c2410.c index 0c6aa3e51336..a9c887475054 100644 --- a/drivers/clk/samsung/clk-s3c2410.c +++ b/drivers/clk/samsung/clk-s3c2410.c @@ -95,7 +95,7 @@ static void __init s3c2410_clk_sleep_init(void) {} PNAME(fclk_p) = { "mpll", "div_slow" }; -struct samsung_mux_clock s3c2410_common_muxes[] __initdata = { +static struct samsung_mux_clock s3c2410_common_muxes[] __initdata = { MUX(FCLK, "fclk", fclk_p, CLKSLOW, 4, 1), }; @@ -111,12 +111,12 @@ static struct clk_div_table divslow_d[] = { { /* sentinel */ }, }; -struct samsung_div_clock s3c2410_common_dividers[] __initdata = { +static struct samsung_div_clock s3c2410_common_dividers[] __initdata = { DIV_T(0, "div_slow", "xti", CLKSLOW, 0, 3, divslow_d), DIV(PCLK, "pclk", "hclk", CLKDIVN, 0, 1), }; -struct samsung_gate_clock s3c2410_common_gates[] __initdata = { +static struct samsung_gate_clock s3c2410_common_gates[] __initdata = { GATE(PCLK_SPI, "spi", "pclk", CLKCON, 18, 0, 0), GATE(PCLK_I2S, "i2s", "pclk", CLKCON, 17, 0, 0), GATE(PCLK_I2C, "i2c", "pclk", CLKCON, 16, 0, 0), @@ -135,7 +135,7 @@ struct samsung_gate_clock s3c2410_common_gates[] __initdata = { }; /* should be added _after_ the soc-specific clocks are created */ -struct samsung_clock_alias s3c2410_common_aliases[] __initdata = { +static struct samsung_clock_alias s3c2410_common_aliases[] __initdata = { ALIAS(PCLK_I2C, "s3c2410-i2c.0", "i2c"), ALIAS(PCLK_ADC, NULL, "adc"), ALIAS(PCLK_RTC, NULL, "rtc"), @@ -200,11 +200,11 @@ static struct samsung_pll_clock s3c2410_plls[] __initdata = { LOCKTIME, UPLLCON, NULL), }; -struct samsung_div_clock s3c2410_dividers[] __initdata = { +static struct samsung_div_clock s3c2410_dividers[] __initdata = { DIV(HCLK, "hclk", "mpll", CLKDIVN, 1, 1), }; -struct samsung_fixed_factor_clock s3c2410_ffactor[] __initdata = { +static struct samsung_fixed_factor_clock s3c2410_ffactor[] __initdata = { /* * armclk is directly supplied by the fclk, without * switching possibility like on the s3c244x below. @@ -215,7 +215,7 @@ struct samsung_fixed_factor_clock s3c2410_ffactor[] __initdata = { FFACTOR(UCLK, "uclk", "upll", 1, 1, 0), }; -struct samsung_clock_alias s3c2410_aliases[] __initdata = { +static struct samsung_clock_alias s3c2410_aliases[] __initdata = { ALIAS(PCLK_UART0, "s3c2410-uart.0", "uart"), ALIAS(PCLK_UART1, "s3c2410-uart.1", "uart"), ALIAS(PCLK_UART2, "s3c2410-uart.2", "uart"), @@ -269,12 +269,12 @@ static struct samsung_pll_clock s3c244x_common_plls[] __initdata = { PNAME(hclk_p) = { "fclk", "div_hclk_2", "div_hclk_4", "div_hclk_3" }; PNAME(armclk_p) = { "fclk", "hclk" }; -struct samsung_mux_clock s3c244x_common_muxes[] __initdata = { +static struct samsung_mux_clock s3c244x_common_muxes[] __initdata = { MUX(HCLK, "hclk", hclk_p, CLKDIVN, 1, 2), MUX(ARMCLK, "armclk", armclk_p, CAMDIVN, 12, 1), }; -struct samsung_fixed_factor_clock s3c244x_common_ffactor[] __initdata = { +static struct samsung_fixed_factor_clock s3c244x_common_ffactor[] __initdata = { FFACTOR(0, "div_hclk_2", "fclk", 1, 2, 0), FFACTOR(0, "ff_cam", "div_cam", 2, 1, CLK_SET_RATE_PARENT), }; @@ -291,7 +291,7 @@ static struct clk_div_table div_hclk_3_d[] = { { /* sentinel */ }, }; -struct samsung_div_clock s3c244x_common_dividers[] __initdata = { +static struct samsung_div_clock s3c244x_common_dividers[] __initdata = { DIV(UCLK, "uclk", "upll", CLKDIVN, 3, 1), DIV(0, "div_hclk", "fclk", CLKDIVN, 1, 1), DIV_T(0, "div_hclk_4", "fclk", CAMDIVN, 9, 1, div_hclk_4_d), @@ -299,11 +299,11 @@ struct samsung_div_clock s3c244x_common_dividers[] __initdata = { DIV(0, "div_cam", "upll", CAMDIVN, 0, 3), }; -struct samsung_gate_clock s3c244x_common_gates[] __initdata = { +static struct samsung_gate_clock s3c244x_common_gates[] __initdata = { GATE(HCLK_CAM, "cam", "hclk", CLKCON, 19, 0, 0), }; -struct samsung_clock_alias s3c244x_common_aliases[] __initdata = { +static struct samsung_clock_alias s3c244x_common_aliases[] __initdata = { ALIAS(PCLK_UART0, "s3c2440-uart.0", "uart"), ALIAS(PCLK_UART1, "s3c2440-uart.1", "uart"), ALIAS(PCLK_UART2, "s3c2440-uart.2", "uart"), @@ -318,23 +318,23 @@ struct samsung_clock_alias s3c244x_common_aliases[] __initdata = { PNAME(s3c2440_camif_p) = { "upll", "ff_cam" }; -struct samsung_mux_clock s3c2440_muxes[] __initdata = { +static struct samsung_mux_clock s3c2440_muxes[] __initdata = { MUX(CAMIF, "camif", s3c2440_camif_p, CAMDIVN, 4, 1), }; -struct samsung_gate_clock s3c2440_gates[] __initdata = { +static struct samsung_gate_clock s3c2440_gates[] __initdata = { GATE(PCLK_AC97, "ac97", "pclk", CLKCON, 20, 0, 0), }; /* S3C2442 specific clocks */ -struct samsung_fixed_factor_clock s3c2442_ffactor[] __initdata = { +static struct samsung_fixed_factor_clock s3c2442_ffactor[] __initdata = { FFACTOR(0, "upll_3", "upll", 1, 3, 0), }; PNAME(s3c2442_camif_p) = { "upll", "ff_cam", "upll", "upll_3" }; -struct samsung_mux_clock s3c2442_muxes[] __initdata = { +static struct samsung_mux_clock s3c2442_muxes[] __initdata = { MUX(CAMIF, "camif", s3c2442_camif_p, CAMDIVN, 4, 2), }; @@ -343,7 +343,7 @@ struct samsung_mux_clock s3c2442_muxes[] __initdata = { * Only necessary until the devicetree-move is complete */ #define XTI 1 -struct samsung_fixed_rate_clock s3c2410_common_frate_clks[] __initdata = { +static struct samsung_fixed_rate_clock s3c2410_common_frate_clks[] __initdata = { FRATE(XTI, "xti", NULL, 0, 0), }; @@ -468,18 +468,18 @@ void __init s3c2410_common_clk_init(struct device_node *np, unsigned long xti_f, static void __init s3c2410_clk_init(struct device_node *np) { - s3c2410_common_clk_init(np, 0, S3C2410, 0); + s3c2410_common_clk_init(np, 0, S3C2410, NULL); } CLK_OF_DECLARE(s3c2410_clk, "samsung,s3c2410-clock", s3c2410_clk_init); static void __init s3c2440_clk_init(struct device_node *np) { - s3c2410_common_clk_init(np, 0, S3C2440, 0); + s3c2410_common_clk_init(np, 0, S3C2440, NULL); } CLK_OF_DECLARE(s3c2440_clk, "samsung,s3c2440-clock", s3c2440_clk_init); static void __init s3c2442_clk_init(struct device_node *np) { - s3c2410_common_clk_init(np, 0, S3C2442, 0); + s3c2410_common_clk_init(np, 0, S3C2442, NULL); } CLK_OF_DECLARE(s3c2442_clk, "samsung,s3c2442-clock", s3c2442_clk_init); diff --git a/drivers/clk/samsung/clk-s3c2412.c b/drivers/clk/samsung/clk-s3c2412.c index 1555e407529e..6bc94d3aff78 100644 --- a/drivers/clk/samsung/clk-s3c2412.c +++ b/drivers/clk/samsung/clk-s3c2412.c @@ -93,7 +93,7 @@ static struct clk_div_table divxti_d[] = { { /* sentinel */ }, }; -struct samsung_div_clock s3c2412_dividers[] __initdata = { +static struct samsung_div_clock s3c2412_dividers[] __initdata = { DIV_T(0, "div_xti", "xti", CLKSRC, 0, 3, divxti_d), DIV(0, "div_cam", "mux_cam", CLKDIVN, 16, 4), DIV(0, "div_i2s", "mux_i2s", CLKDIVN, 12, 4), @@ -105,7 +105,7 @@ struct samsung_div_clock s3c2412_dividers[] __initdata = { DIV(HCLK, "hclk", "armdiv", CLKDIVN, 0, 2), }; -struct samsung_fixed_factor_clock s3c2412_ffactor[] __initdata = { +static struct samsung_fixed_factor_clock s3c2412_ffactor[] __initdata = { FFACTOR(0, "ff_hclk", "hclk", 2, 1, CLK_SET_RATE_PARENT), }; @@ -125,7 +125,7 @@ PNAME(msysclk_p) = { "mdivclk", "mpll" }; PNAME(mdivclk_p) = { "xti", "div_xti" }; PNAME(armclk_p) = { "armdiv", "hclk" }; -struct samsung_mux_clock s3c2412_muxes[] __initdata = { +static struct samsung_mux_clock s3c2412_muxes[] __initdata = { MUX(0, "erefclk", erefclk_p, CLKSRC, 14, 2), MUX(0, "urefclk", urefclk_p, CLKSRC, 12, 2), MUX(0, "mux_cam", camclk_p, CLKSRC, 11, 1), @@ -143,7 +143,7 @@ static struct samsung_pll_clock s3c2412_plls[] __initdata = { PLL(pll_s3c2410_upll, UPLL, "upll", "urefclk", LOCKTIME, UPLLCON, NULL), }; -struct samsung_gate_clock s3c2412_gates[] __initdata = { +static struct samsung_gate_clock s3c2412_gates[] __initdata = { GATE(PCLK_WDT, "wdt", "pclk", CLKCON, 28, 0, 0), GATE(PCLK_SPI, "spi", "pclk", CLKCON, 27, 0, 0), GATE(PCLK_I2S, "i2s", "pclk", CLKCON, 26, 0, 0), @@ -174,7 +174,7 @@ struct samsung_gate_clock s3c2412_gates[] __initdata = { GATE(HCLK_DMA0, "dma0", "hclk", CLKCON, 0, CLK_IGNORE_UNUSED, 0), }; -struct samsung_clock_alias s3c2412_aliases[] __initdata = { +static struct samsung_clock_alias s3c2412_aliases[] __initdata = { ALIAS(PCLK_UART0, "s3c2412-uart.0", "uart"), ALIAS(PCLK_UART1, "s3c2412-uart.1", "uart"), ALIAS(PCLK_UART2, "s3c2412-uart.2", "uart"), @@ -224,7 +224,7 @@ static struct notifier_block s3c2412_restart_handler = { * Only necessary until the devicetree-move is complete */ #define XTI 1 -struct samsung_fixed_rate_clock s3c2412_common_frate_clks[] __initdata = { +static struct samsung_fixed_rate_clock s3c2412_common_frate_clks[] __initdata = { FRATE(XTI, "xti", NULL, 0, 0), FRATE(0, "ext", NULL, 0, 0), }; @@ -289,6 +289,6 @@ void __init s3c2412_common_clk_init(struct device_node *np, unsigned long xti_f, static void __init s3c2412_clk_init(struct device_node *np) { - s3c2412_common_clk_init(np, 0, 0, 0); + s3c2412_common_clk_init(np, 0, 0, NULL); } CLK_OF_DECLARE(s3c2412_clk, "samsung,s3c2412-clock", s3c2412_clk_init); diff --git a/drivers/clk/samsung/clk-s3c2443.c b/drivers/clk/samsung/clk-s3c2443.c index 9580a6baf4d7..c46e6d5bc9bc 100644 --- a/drivers/clk/samsung/clk-s3c2443.c +++ b/drivers/clk/samsung/clk-s3c2443.c @@ -108,7 +108,7 @@ PNAME(msysclk_p) = { "mpllref", "mpll" }; PNAME(armclk_p) = { "armdiv" , "hclk" }; PNAME(i2s0_p) = { "div_i2s0", "ext_i2s", "epllref", "epllref" }; -struct samsung_mux_clock s3c2443_common_muxes[] __initdata = { +static struct samsung_mux_clock s3c2443_common_muxes[] __initdata = { MUX(0, "epllref", epllref_p, CLKSRC, 7, 2), MUX(ESYSCLK, "esysclk", esysclk_p, CLKSRC, 6, 1), MUX(0, "mpllref", mpllref_p, CLKSRC, 3, 1), @@ -136,7 +136,7 @@ static struct clk_div_table mdivclk_d[] = { { /* sentinel */ }, }; -struct samsung_div_clock s3c2443_common_dividers[] __initdata = { +static struct samsung_div_clock s3c2443_common_dividers[] __initdata = { DIV_T(0, "mdivclk", "xti", CLKDIV0, 6, 3, mdivclk_d), DIV(0, "prediv", "msysclk", CLKDIV0, 4, 2), DIV_T(HCLK, "hclk", "prediv", CLKDIV0, 0, 2, hclk_d), @@ -149,7 +149,7 @@ struct samsung_div_clock s3c2443_common_dividers[] __initdata = { DIV(0, "div_usbhost", "esysclk", CLKDIV1, 4, 2), }; -struct samsung_gate_clock s3c2443_common_gates[] __initdata = { +static struct samsung_gate_clock s3c2443_common_gates[] __initdata = { GATE(SCLK_HSMMC_EXT, "sclk_hsmmcext", "ext", SCLKCON, 13, 0, 0), GATE(SCLK_HSMMC1, "sclk_hsmmc1", "div_hsmmc1", SCLKCON, 12, 0, 0), GATE(SCLK_FIMD, "sclk_fimd", "div_fimd", SCLKCON, 10, 0, 0), @@ -183,7 +183,7 @@ struct samsung_gate_clock s3c2443_common_gates[] __initdata = { GATE(PCLK_UART0, "uart0", "pclk", PCLKCON, 0, 0, 0), }; -struct samsung_clock_alias s3c2443_common_aliases[] __initdata = { +static struct samsung_clock_alias s3c2443_common_aliases[] __initdata = { ALIAS(MSYSCLK, NULL, "msysclk"), ALIAS(ARMCLK, NULL, "armclk"), ALIAS(MPLL, NULL, "mpll"), @@ -238,19 +238,19 @@ static struct clk_div_table armdiv_s3c2416_d[] = { { /* sentinel */ }, }; -struct samsung_div_clock s3c2416_dividers[] __initdata = { +static struct samsung_div_clock s3c2416_dividers[] __initdata = { DIV_T(ARMDIV, "armdiv", "msysclk", CLKDIV0, 9, 3, armdiv_s3c2416_d), DIV(0, "div_hsspi0_mpll", "msysclk", CLKDIV2, 0, 4), DIV(0, "div_hsmmc0", "esysclk", CLKDIV2, 6, 2), }; -struct samsung_mux_clock s3c2416_muxes[] __initdata = { +static struct samsung_mux_clock s3c2416_muxes[] __initdata = { MUX(MUX_HSMMC0, "mux_hsmmc0", s3c2416_hsmmc0_p, CLKSRC, 16, 1), MUX(MUX_HSMMC1, "mux_hsmmc1", s3c2416_hsmmc1_p, CLKSRC, 17, 1), MUX(MUX_HSSPI0, "mux_hsspi0", s3c2416_hsspi0_p, CLKSRC, 18, 1), }; -struct samsung_gate_clock s3c2416_gates[] __initdata = { +static struct samsung_gate_clock s3c2416_gates[] __initdata = { GATE(0, "hsspi0_mpll", "div_hsspi0_mpll", SCLKCON, 19, 0, 0), GATE(0, "hsspi0_epll", "div_hsspi0_epll", SCLKCON, 14, 0, 0), GATE(0, "sclk_hsmmc0", "div_hsmmc0", SCLKCON, 6, 0, 0), @@ -260,7 +260,7 @@ struct samsung_gate_clock s3c2416_gates[] __initdata = { GATE(PCLK_PCM, "pcm", "pclk", PCLKCON, 19, 0, 0), }; -struct samsung_clock_alias s3c2416_aliases[] __initdata = { +static struct samsung_clock_alias s3c2416_aliases[] __initdata = { ALIAS(HCLK_HSMMC0, "s3c-sdhci.0", "hsmmc"), ALIAS(HCLK_HSMMC0, "s3c-sdhci.0", "mmc_busclk.0"), ALIAS(MUX_HSMMC0, "s3c-sdhci.0", "mmc_busclk.2"), @@ -288,12 +288,12 @@ static struct clk_div_table armdiv_s3c2443_d[] = { { /* sentinel */ }, }; -struct samsung_div_clock s3c2443_dividers[] __initdata = { +static struct samsung_div_clock s3c2443_dividers[] __initdata = { DIV_T(ARMDIV, "armdiv", "msysclk", CLKDIV0, 9, 4, armdiv_s3c2443_d), DIV(0, "div_cam", "esysclk", CLKDIV1, 26, 4), }; -struct samsung_gate_clock s3c2443_gates[] __initdata = { +static struct samsung_gate_clock s3c2443_gates[] __initdata = { GATE(SCLK_HSSPI0, "sclk_hsspi0", "div_hsspi0_epll", SCLKCON, 14, 0, 0), GATE(SCLK_CAM, "sclk_cam", "div_cam", SCLKCON, 11, 0, 0), GATE(HCLK_CFC, "cfc", "hclk", HCLKCON, 17, CLK_IGNORE_UNUSED, 0), @@ -302,7 +302,7 @@ struct samsung_gate_clock s3c2443_gates[] __initdata = { GATE(PCLK_SDI, "sdi", "pclk", PCLKCON, 5, 0, 0), }; -struct samsung_clock_alias s3c2443_aliases[] __initdata = { +static struct samsung_clock_alias s3c2443_aliases[] __initdata = { ALIAS(SCLK_HSSPI0, "s3c2443-spi.0", "spi_busclk2"), ALIAS(SCLK_HSMMC1, "s3c-sdhci.1", "mmc_busclk.2"), ALIAS(SCLK_CAM, NULL, "camif-upll"), @@ -318,20 +318,20 @@ PNAME(s3c2450_cam_p) = { "div_cam", "hclk" }; PNAME(s3c2450_hsspi1_p) = { "hsspi1_epll", "hsspi1_mpll" }; PNAME(i2s1_p) = { "div_i2s1", "ext_i2s", "epllref", "epllref" }; -struct samsung_div_clock s3c2450_dividers[] __initdata = { +static struct samsung_div_clock s3c2450_dividers[] __initdata = { DIV(0, "div_cam", "esysclk", CLKDIV1, 26, 4), DIV(0, "div_hsspi1_epll", "esysclk", CLKDIV2, 24, 2), DIV(0, "div_hsspi1_mpll", "msysclk", CLKDIV2, 16, 4), DIV(0, "div_i2s1", "esysclk", CLKDIV2, 12, 4), }; -struct samsung_mux_clock s3c2450_muxes[] __initdata = { +static struct samsung_mux_clock s3c2450_muxes[] __initdata = { MUX(0, "mux_cam", s3c2450_cam_p, CLKSRC, 20, 1), MUX(MUX_HSSPI1, "mux_hsspi1", s3c2450_hsspi1_p, CLKSRC, 19, 1), MUX(0, "mux_i2s1", i2s1_p, CLKSRC, 12, 2), }; -struct samsung_gate_clock s3c2450_gates[] __initdata = { +static struct samsung_gate_clock s3c2450_gates[] __initdata = { GATE(SCLK_I2S1, "sclk_i2s1", "div_i2s1", SCLKCON, 5, 0, 0), GATE(HCLK_CFC, "cfc", "hclk", HCLKCON, 17, 0, 0), GATE(HCLK_CAM, "cam", "hclk", HCLKCON, 8, 0, 0), @@ -342,7 +342,7 @@ struct samsung_gate_clock s3c2450_gates[] __initdata = { GATE(PCLK_SPI1, "spi1", "pclk", PCLKCON, 14, 0, 0), }; -struct samsung_clock_alias s3c2450_aliases[] __initdata = { +static struct samsung_clock_alias s3c2450_aliases[] __initdata = { ALIAS(PCLK_SPI1, "s3c2443-spi.1", "spi"), ALIAS(PCLK_SPI1, "s3c2443-spi.1", "spi_busclk0"), ALIAS(MUX_HSSPI1, "s3c2443-spi.1", "spi_busclk2"), @@ -365,7 +365,7 @@ static struct notifier_block s3c2443_restart_handler = { * fixed rate clocks generated outside the soc * Only necessary until the devicetree-move is complete */ -struct samsung_fixed_rate_clock s3c2443_common_frate_clks[] __initdata = { +static struct samsung_fixed_rate_clock s3c2443_common_frate_clks[] __initdata = { FRATE(0, "xti", NULL, 0, 0), FRATE(0, "ext", NULL, 0, 0), FRATE(0, "ext_i2s", NULL, 0, 0), @@ -461,18 +461,18 @@ void __init s3c2443_common_clk_init(struct device_node *np, unsigned long xti_f, static void __init s3c2416_clk_init(struct device_node *np) { - s3c2443_common_clk_init(np, 0, S3C2416, 0); + s3c2443_common_clk_init(np, 0, S3C2416, NULL); } CLK_OF_DECLARE(s3c2416_clk, "samsung,s3c2416-clock", s3c2416_clk_init); static void __init s3c2443_clk_init(struct device_node *np) { - s3c2443_common_clk_init(np, 0, S3C2443, 0); + s3c2443_common_clk_init(np, 0, S3C2443, NULL); } CLK_OF_DECLARE(s3c2443_clk, "samsung,s3c2443-clock", s3c2443_clk_init); static void __init s3c2450_clk_init(struct device_node *np) { - s3c2443_common_clk_init(np, 0, S3C2450, 0); + s3c2443_common_clk_init(np, 0, S3C2450, NULL); } CLK_OF_DECLARE(s3c2450_clk, "samsung,s3c2450-clock", s3c2450_clk_init); -- cgit v1.2.3