From f684ff8b67ec19f003cc894477afb20442064692 Mon Sep 17 00:00:00 2001 From: Stephen Boyd Date: Fri, 19 Jun 2015 15:00:46 -0700 Subject: clk: rockchip: Properly include clk.h Clock provider drivers generally shouldn't include clk.h because it's the consumer API. Only include clk.h if it's actually used. Cc: Heiko Stuebner Signed-off-by: Stephen Boyd --- drivers/clk/rockchip/clk-pll.c | 1 - 1 file changed, 1 deletion(-) (limited to 'drivers/clk/rockchip/clk-pll.c') diff --git a/drivers/clk/rockchip/clk-pll.c b/drivers/clk/rockchip/clk-pll.c index 76027261f7ed..1f88dd158b93 100644 --- a/drivers/clk/rockchip/clk-pll.c +++ b/drivers/clk/rockchip/clk-pll.c @@ -17,7 +17,6 @@ #include #include #include -#include #include #include #include "clk.h" -- cgit v1.2.3-55-g7522 From 2bbfe00147a7c075f5c43e657ec218afea662819 Mon Sep 17 00:00:00 2001 From: Douglas Anderson Date: Tue, 21 Jul 2015 13:41:23 -0700 Subject: clk: rockchip: Fix PLL bandwidth In the TRM we see that BWADJ is "a 12-bit bus that selects the values 1-4096 for the bandwidth divider (NB)": NB = BWADJ[11:0] + 1 The recommended setting of NB: NB = NF / 2. So: NB = NF / 2 BWADJ[11:0] + 1 = NF / 2 BWADJ[11:0] = NF / 2 - 1 Right now, we have: { \ .rate = _rate##U, \ .nr = _nr, \ .nf = _nf, \ .no = _no, \ .bwadj = (_nf >> 1), \ } That means we set bwadj to NF / 2, not NF / 2 - 1 All of this is a bit confusing because we specify "NR" (the 1-based value), "NF" (the 1-based value), "NO" (the 1-based value), but "BWADJ" (the 0-based value) instead of "NB" (the 1-based value). Let's change to working with "NB" and fix the off by one error. This may affect PLL jitter in a small way (hopefully for the better). Signed-off-by: Douglas Anderson Reviewed-by: Heiko Stuebner Signed-off-by: Stephen Boyd --- drivers/clk/rockchip/clk-pll.c | 18 +++++++++--------- drivers/clk/rockchip/clk-rk3188.c | 2 +- drivers/clk/rockchip/clk-rk3288.c | 2 +- drivers/clk/rockchip/clk.h | 8 ++++---- 4 files changed, 15 insertions(+), 15 deletions(-) (limited to 'drivers/clk/rockchip/clk-pll.c') diff --git a/drivers/clk/rockchip/clk-pll.c b/drivers/clk/rockchip/clk-pll.c index 1f88dd158b93..96903ae8b192 100644 --- a/drivers/clk/rockchip/clk-pll.c +++ b/drivers/clk/rockchip/clk-pll.c @@ -120,8 +120,8 @@ static int rockchip_pll_wait_lock(struct rockchip_clk_pll *pll) #define RK3066_PLLCON0_NR_SHIFT 8 #define RK3066_PLLCON1_NF_MASK 0x1fff #define RK3066_PLLCON1_NF_SHIFT 0 -#define RK3066_PLLCON2_BWADJ_MASK 0xfff -#define RK3066_PLLCON2_BWADJ_SHIFT 0 +#define RK3066_PLLCON2_NB_MASK 0xfff +#define RK3066_PLLCON2_NB_SHIFT 0 #define RK3066_PLLCON3_RESET (1 << 5) #define RK3066_PLLCON3_PWRDOWN (1 << 1) #define RK3066_PLLCON3_BYPASS (1 << 0) @@ -207,8 +207,8 @@ static int rockchip_rk3066_pll_set_rate(struct clk_hw *hw, unsigned long drate, writel_relaxed(HIWORD_UPDATE(rate->nf - 1, RK3066_PLLCON1_NF_MASK, RK3066_PLLCON1_NF_SHIFT), pll->reg_base + RK3066_PLLCON(1)); - writel_relaxed(HIWORD_UPDATE(rate->bwadj, RK3066_PLLCON2_BWADJ_MASK, - RK3066_PLLCON2_BWADJ_SHIFT), + writel_relaxed(HIWORD_UPDATE(rate->nb - 1, RK3066_PLLCON2_NB_MASK, + RK3066_PLLCON2_NB_SHIFT), pll->reg_base + RK3066_PLLCON(2)); /* leave reset and wait the reset_delay */ @@ -261,7 +261,7 @@ static void rockchip_rk3066_pll_init(struct clk_hw *hw) { struct rockchip_clk_pll *pll = to_rockchip_clk_pll(hw); const struct rockchip_pll_rate_table *rate; - unsigned int nf, nr, no, bwadj; + unsigned int nf, nr, no, nb; unsigned long drate; u32 pllcon; @@ -283,13 +283,13 @@ static void rockchip_rk3066_pll_init(struct clk_hw *hw) nf = ((pllcon >> RK3066_PLLCON1_NF_SHIFT) & RK3066_PLLCON1_NF_MASK) + 1; pllcon = readl_relaxed(pll->reg_base + RK3066_PLLCON(2)); - bwadj = (pllcon >> RK3066_PLLCON2_BWADJ_SHIFT) & RK3066_PLLCON2_BWADJ_MASK; + nb = ((pllcon >> RK3066_PLLCON2_NB_SHIFT) & RK3066_PLLCON2_NB_MASK) + 1; - pr_debug("%s: pll %s@%lu: nr (%d:%d); no (%d:%d); nf(%d:%d), bwadj(%d:%d)\n", + pr_debug("%s: pll %s@%lu: nr (%d:%d); no (%d:%d); nf(%d:%d), nb(%d:%d)\n", __func__, __clk_get_name(hw->clk), drate, rate->nr, nr, - rate->no, no, rate->nf, nf, rate->bwadj, bwadj); + rate->no, no, rate->nf, nf, rate->nb, nb); if (rate->nr != nr || rate->no != no || rate->nf != nf - || rate->bwadj != bwadj) { + || rate->nb != nb) { struct clk *parent = __clk_get_parent(hw->clk); unsigned long prate; diff --git a/drivers/clk/rockchip/clk-rk3188.c b/drivers/clk/rockchip/clk-rk3188.c index edbafbcabeb6..0abf22d14401 100644 --- a/drivers/clk/rockchip/clk-rk3188.c +++ b/drivers/clk/rockchip/clk-rk3188.c @@ -817,7 +817,7 @@ static void __init rk3188_clk_init(struct device_node *np) rate = pll->rate_table; while (rate->rate > 0) { - rate->bwadj = 0; + rate->nb = 1; rate++; } } diff --git a/drivers/clk/rockchip/clk-rk3288.c b/drivers/clk/rockchip/clk-rk3288.c index a8bad7d3a487..0df5bae9ddbf 100644 --- a/drivers/clk/rockchip/clk-rk3288.c +++ b/drivers/clk/rockchip/clk-rk3288.c @@ -84,7 +84,7 @@ static struct rockchip_pll_rate_table rk3288_pll_rates[] = { RK3066_PLL_RATE( 742500000, 8, 495, 2), RK3066_PLL_RATE( 696000000, 1, 58, 2), RK3066_PLL_RATE( 600000000, 1, 50, 2), - RK3066_PLL_RATE_BWADJ(594000000, 1, 198, 8, 1), + RK3066_PLL_RATE_NB(594000000, 1, 198, 8, 1), RK3066_PLL_RATE( 552000000, 1, 46, 2), RK3066_PLL_RATE( 504000000, 1, 84, 4), RK3066_PLL_RATE( 500000000, 3, 125, 2), diff --git a/drivers/clk/rockchip/clk.h b/drivers/clk/rockchip/clk.h index 93ea335f2653..dc8ecb2673b7 100644 --- a/drivers/clk/rockchip/clk.h +++ b/drivers/clk/rockchip/clk.h @@ -83,16 +83,16 @@ enum rockchip_pll_type { .nr = _nr, \ .nf = _nf, \ .no = _no, \ - .bwadj = ((_nf) >> 1), \ + .nb = ((_nf) < 2) ? 1 : (_nf) >> 1, \ } -#define RK3066_PLL_RATE_BWADJ(_rate, _nr, _nf, _no, _bw) \ +#define RK3066_PLL_RATE_NB(_rate, _nr, _nf, _no, _nb) \ { \ .rate = _rate##U, \ .nr = _nr, \ .nf = _nf, \ .no = _no, \ - .bwadj = _bw, \ + .nb = _nb, \ } struct rockchip_pll_rate_table { @@ -100,7 +100,7 @@ struct rockchip_pll_rate_table { unsigned int nr; unsigned int nf; unsigned int no; - unsigned int bwadj; + unsigned int nb; }; /** -- cgit v1.2.3-55-g7522 From 4c34875059fa025be671108de1b0993cc14c9256 Mon Sep 17 00:00:00 2001 From: Stephen Boyd Date: Thu, 30 Jul 2015 17:20:57 -0700 Subject: clk: rockchip: Convert to clk_hw based provider APIs We're removing struct clk from the clk provider API, so switch this code to using the clk_hw based provider APIs. Reviewed-by: Heiko Stuebner Signed-off-by: Stephen Boyd --- drivers/clk/rockchip/clk-pll.c | 18 +++++++++--------- 1 file changed, 9 insertions(+), 9 deletions(-) (limited to 'drivers/clk/rockchip/clk-pll.c') diff --git a/drivers/clk/rockchip/clk-pll.c b/drivers/clk/rockchip/clk-pll.c index 96903ae8b192..eab430452c52 100644 --- a/drivers/clk/rockchip/clk-pll.c +++ b/drivers/clk/rockchip/clk-pll.c @@ -136,7 +136,7 @@ static unsigned long rockchip_rk3066_pll_recalc_rate(struct clk_hw *hw, pllcon = readl_relaxed(pll->reg_base + RK3066_PLLCON(3)); if (pllcon & RK3066_PLLCON3_BYPASS) { pr_debug("%s: pll %s is bypassed\n", __func__, - __clk_get_name(hw->clk)); + clk_hw_get_name(hw)); return prate; } @@ -174,13 +174,13 @@ static int rockchip_rk3066_pll_set_rate(struct clk_hw *hw, unsigned long drate, } pr_debug("%s: changing %s from %lu to %lu with a parent rate of %lu\n", - __func__, __clk_get_name(hw->clk), old_rate, drate, prate); + __func__, clk_hw_get_name(hw), old_rate, drate, prate); /* Get required rate settings from table */ rate = rockchip_get_pll_settings(pll, drate); if (!rate) { pr_err("%s: Invalid rate : %lu for pll clk %s\n", __func__, - drate, __clk_get_name(hw->clk)); + drate, clk_hw_get_name(hw)); return -EINVAL; } @@ -268,7 +268,7 @@ static void rockchip_rk3066_pll_init(struct clk_hw *hw) if (!(pll->flags & ROCKCHIP_PLL_SYNC_RATE)) return; - drate = __clk_get_rate(hw->clk); + drate = clk_hw_get_rate(hw); rate = rockchip_get_pll_settings(pll, drate); /* when no rate setting for the current rate, rely on clk_set_rate */ @@ -286,22 +286,22 @@ static void rockchip_rk3066_pll_init(struct clk_hw *hw) nb = ((pllcon >> RK3066_PLLCON2_NB_SHIFT) & RK3066_PLLCON2_NB_MASK) + 1; pr_debug("%s: pll %s@%lu: nr (%d:%d); no (%d:%d); nf(%d:%d), nb(%d:%d)\n", - __func__, __clk_get_name(hw->clk), drate, rate->nr, nr, + __func__, clk_hw_get_name(hw), drate, rate->nr, nr, rate->no, no, rate->nf, nf, rate->nb, nb); if (rate->nr != nr || rate->no != no || rate->nf != nf || rate->nb != nb) { - struct clk *parent = __clk_get_parent(hw->clk); + struct clk_hw *parent = clk_hw_get_parent(hw); unsigned long prate; if (!parent) { pr_warn("%s: parent of %s not available\n", - __func__, __clk_get_name(hw->clk)); + __func__, clk_hw_get_name(hw)); return; } pr_debug("%s: pll %s: rate params do not match rate table, adjusting\n", - __func__, __clk_get_name(hw->clk)); - prate = __clk_get_rate(parent); + __func__, clk_hw_get_name(hw)); + prate = clk_hw_get_rate(parent); rockchip_rk3066_pll_set_rate(hw, drate, prate); } } -- cgit v1.2.3-55-g7522 From 10897370345b792c00ccba6aa7ea86ae6bfa2c7a Mon Sep 17 00:00:00 2001 From: Heiko Stuebner Date: Wed, 19 Aug 2015 15:06:55 +0200 Subject: clk: rockchip: register pll mux before pll itself The structure is xin24m -> pll -> pll-mux (xin24m,pll,xin32k). The pll does have an init callback to make sure the boot-selected frequency is using the expected pll settings and resets the same frequency using the values provided in the driver if necessary. The setting itself also involves remuxing the pll-mux temporarily to the xin24m source to let the new pll rate settle. Until now this worked flawlessly, even when it had the flaw of accessing the mux settings before the mux actually got registered. With the recent clock-core conversions this flaw became apparent in null pointer dereference in [] (clk_hw_get_num_parents) from [] (clk_mux_get_parent+0x14/0xc8) [] (clk_mux_get_parent) from [] (rockchip_rk3066_pll_set_rate+0xd8/0x320) So to fix that, simply register the pll-mux before the pll, so that it will be fully initialized when the pll clock executes its init- callback and possibly touches the pll-mux clock. Signed-off-by: Heiko Stuebner Signed-off-by: Michael Turquette --- drivers/clk/rockchip/clk-pll.c | 63 +++++++++++++++++++++--------------------- 1 file changed, 32 insertions(+), 31 deletions(-) (limited to 'drivers/clk/rockchip/clk-pll.c') diff --git a/drivers/clk/rockchip/clk-pll.c b/drivers/clk/rockchip/clk-pll.c index eab430452c52..7737a1df1e4b 100644 --- a/drivers/clk/rockchip/clk-pll.c +++ b/drivers/clk/rockchip/clk-pll.c @@ -353,6 +353,35 @@ struct clk *rockchip_clk_register_pll(enum rockchip_pll_type pll_type, if (!pll) return ERR_PTR(-ENOMEM); + /* create the mux on top of the real pll */ + pll->pll_mux_ops = &clk_mux_ops; + pll_mux = &pll->pll_mux; + pll_mux->reg = base + mode_offset; + pll_mux->shift = mode_shift; + pll_mux->mask = PLL_MODE_MASK; + pll_mux->flags = 0; + pll_mux->lock = lock; + pll_mux->hw.init = &init; + + if (pll_type == pll_rk3066) + pll_mux->flags |= CLK_MUX_HIWORD_MASK; + + /* the actual muxing is xin24m, pll-output, xin32k */ + pll_parents[0] = parent_names[0]; + pll_parents[1] = pll_name; + pll_parents[2] = parent_names[1]; + + init.name = name; + init.flags = CLK_SET_RATE_PARENT; + init.ops = pll->pll_mux_ops; + init.parent_names = pll_parents; + init.num_parents = ARRAY_SIZE(pll_parents); + + mux_clk = clk_register(NULL, &pll_mux->hw); + if (IS_ERR(mux_clk)) + goto err_mux; + + /* now create the actual pll */ init.name = pll_name; /* keep all plls untouched for now */ @@ -398,47 +427,19 @@ struct clk *rockchip_clk_register_pll(enum rockchip_pll_type pll_type, pll->flags = clk_pll_flags; pll->lock = lock; - /* create the mux on top of the real pll */ - pll->pll_mux_ops = &clk_mux_ops; - pll_mux = &pll->pll_mux; - pll_mux->reg = base + mode_offset; - pll_mux->shift = mode_shift; - pll_mux->mask = PLL_MODE_MASK; - pll_mux->flags = 0; - pll_mux->lock = lock; - pll_mux->hw.init = &init; - - if (pll_type == pll_rk3066) - pll_mux->flags |= CLK_MUX_HIWORD_MASK; - pll_clk = clk_register(NULL, &pll->hw); if (IS_ERR(pll_clk)) { pr_err("%s: failed to register pll clock %s : %ld\n", __func__, name, PTR_ERR(pll_clk)); - mux_clk = pll_clk; goto err_pll; } - /* the actual muxing is xin24m, pll-output, xin32k */ - pll_parents[0] = parent_names[0]; - pll_parents[1] = pll_name; - pll_parents[2] = parent_names[1]; - - init.name = name; - init.flags = CLK_SET_RATE_PARENT; - init.ops = pll->pll_mux_ops; - init.parent_names = pll_parents; - init.num_parents = ARRAY_SIZE(pll_parents); - - mux_clk = clk_register(NULL, &pll_mux->hw); - if (IS_ERR(mux_clk)) - goto err_mux; - return mux_clk; -err_mux: - clk_unregister(pll_clk); err_pll: + clk_unregister(mux_clk); + mux_clk = pll_clk; +err_mux: kfree(pll); return mux_clk; } -- cgit v1.2.3-55-g7522