1. Support for some new features
2. fix up some error
Chang in V4:
[PATCH v3 1/5] : Update the commit message.
[PATCH v3 2/5] : Update the commit message.
Chang in V3:
[PATCH v2 3/6] : It's been merged
So rebased and resubmit.
Chang in V2:
[PATCH v2 5/6] : fix up the Register error, and add delay.
Elaine Zhang (5):
clk: rockchip: Add supprot to limit input rate for fractional divider
clk: rockchip: fix up the frac clk get rate error
clk: rockchip: add a clock-type for muxes based in the pmugrf
clk: rockchip: add pll up and down when change pll freq
clk: rockchip: support pll setting by auto
drivers/clk/rockchip/clk-pll.c | 236 ++++++++++++++++++++++++++++--
drivers/clk/rockchip/clk-px30.c | 29 ++--
drivers/clk/rockchip/clk-rk3036.c | 13 +-
drivers/clk/rockchip/clk-rk3128.c | 15 +-
drivers/clk/rockchip/clk-rk3188.c | 24 +--
drivers/clk/rockchip/clk-rk3228.c | 18 ++-
drivers/clk/rockchip/clk-rk3288.c | 19 ++-
drivers/clk/rockchip/clk-rk3308.c | 46 +++---
drivers/clk/rockchip/clk-rk3328.c | 17 ++-
drivers/clk/rockchip/clk-rk3368.c | 17 ++-
drivers/clk/rockchip/clk-rk3399.c | 32 ++--
drivers/clk/rockchip/clk-rv1108.c | 14 +-
drivers/clk/rockchip/clk.c | 39 ++++-
drivers/clk/rockchip/clk.h | 27 +++-
include/linux/clk-provider.h | 2 +
15 files changed, 422 insertions(+), 126 deletions(-)
--
2.17.1
set pll sequence:
->set pll to slow mode or other plls
->set pll down
->set pll params
->set pll up
->wait pll lock status
->set pll to normal mode
To slove the system error:
wait_pll_lock: timeout waiting for pll to lock
pll_set_params: pll update unsucessful,
trying to restore old params
Signed-off-by: Elaine Zhang <[email protected]>
---
drivers/clk/rockchip/clk-pll.c | 21 +++++++++++++++++++++
1 file changed, 21 insertions(+)
diff --git a/drivers/clk/rockchip/clk-pll.c b/drivers/clk/rockchip/clk-pll.c
index 4c6c9167ef50..8adc6f54a605 100644
--- a/drivers/clk/rockchip/clk-pll.c
+++ b/drivers/clk/rockchip/clk-pll.c
@@ -210,6 +210,11 @@ static int rockchip_rk3036_pll_set_params(struct rockchip_clk_pll *pll,
rate_change_remuxed = 1;
}
+ /* set pll power down */
+ writel(HIWORD_UPDATE(RK3036_PLLCON1_PWRDOWN,
+ RK3036_PLLCON1_PWRDOWN, 0),
+ pll->reg_base + RK3036_PLLCON(1));
+
/* update pll values */
writel_relaxed(HIWORD_UPDATE(rate->fbdiv, RK3036_PLLCON0_FBDIV_MASK,
RK3036_PLLCON0_FBDIV_SHIFT) |
@@ -231,6 +236,11 @@ static int rockchip_rk3036_pll_set_params(struct rockchip_clk_pll *pll,
pllcon |= rate->frac << RK3036_PLLCON2_FRAC_SHIFT;
writel_relaxed(pllcon, pll->reg_base + RK3036_PLLCON(2));
+ /* set pll power up */
+ writel(HIWORD_UPDATE(0, RK3036_PLLCON1_PWRDOWN, 0),
+ pll->reg_base + RK3036_PLLCON(1));
+ udelay(1);
+
/* wait for the pll to lock */
ret = rockchip_rk3036_pll_wait_lock(pll);
if (ret) {
@@ -692,6 +702,11 @@ static int rockchip_rk3399_pll_set_params(struct rockchip_clk_pll *pll,
rate_change_remuxed = 1;
}
+ /* set pll power down */
+ writel(HIWORD_UPDATE(RK3399_PLLCON3_PWRDOWN,
+ RK3399_PLLCON3_PWRDOWN, 0),
+ pll->reg_base + RK3399_PLLCON(3));
+
/* update pll values */
writel_relaxed(HIWORD_UPDATE(rate->fbdiv, RK3399_PLLCON0_FBDIV_MASK,
RK3399_PLLCON0_FBDIV_SHIFT),
@@ -715,6 +730,12 @@ static int rockchip_rk3399_pll_set_params(struct rockchip_clk_pll *pll,
RK3399_PLLCON3_DSMPD_SHIFT),
pll->reg_base + RK3399_PLLCON(3));
+ /* set pll power up */
+ writel(HIWORD_UPDATE(0,
+ RK3399_PLLCON3_PWRDOWN, 0),
+ pll->reg_base + RK3399_PLLCON(3));
+ udelay(1);
+
/* wait for the pll to lock */
ret = rockchip_rk3399_pll_wait_lock(pll);
if (ret) {
--
2.17.1
support fractional divider with one level and two level parent clock
.i.e:
normal fractional divider is:
|--\
---[GPLL]---| \ |--\
---[CPLL]---|mux|--[GATE]--[DIV]-----------------------| \
---[NPLL]---| / | |mux|--[GATE]--[UART0]
|--/ |--[GATE]--[FRACDIV]--| /
|--/
but rk3399 uart is special:
|--\
---[GPLL]---| \ |--\
---[CPLL]---|mux|--|--[GATE]--[DIV]-----------------------| \
---[NPLL]---| / | | |mux|--[GATE]--[UART1]
|--/ | |--[GATE]--[FRACDIV]--| /
| |--/
|
| |--\
|--[GATE]--[DIV]-----------------------| \
| | |mux|--[GATE]--[UART2]
| |--[GATE]--[FRACDIV]--| /
| |--/
|
| |--\
|--[GATE]--[DIV]-----------------------| \
| |mux|--[GATE]--[UART3]
|--[GATE]--[FRACDIV]--| /
|--/
The special fractional divider, there are two levels of clock between FRACDIV and PLL.
Signed-off-by: Elaine Zhang <[email protected]>
---
drivers/clk/rockchip/clk.c | 19 ++++++++++++-------
1 file changed, 12 insertions(+), 7 deletions(-)
diff --git a/drivers/clk/rockchip/clk.c b/drivers/clk/rockchip/clk.c
index fac5a4a3f5c3..8f77c3f9fab7 100644
--- a/drivers/clk/rockchip/clk.c
+++ b/drivers/clk/rockchip/clk.c
@@ -190,16 +190,21 @@ static void rockchip_fractional_approximation(struct clk_hw *hw,
if (((rate * 20 > p_rate) && (p_rate % rate != 0)) ||
(fd->max_prate && fd->max_prate < p_rate)) {
p_parent = clk_hw_get_parent(clk_hw_get_parent(hw));
- p_parent_rate = clk_hw_get_rate(p_parent);
- *parent_rate = p_parent_rate;
- if (fd->max_prate && p_parent_rate > fd->max_prate) {
- div = DIV_ROUND_UP(p_parent_rate, fd->max_prate);
- *parent_rate = p_parent_rate / div;
+ if (!p_parent) {
+ *parent_rate = p_rate;
+ } else {
+ p_parent_rate = clk_hw_get_rate(p_parent);
+ *parent_rate = p_parent_rate;
+ if (fd->max_prate && p_parent_rate > fd->max_prate) {
+ div = DIV_ROUND_UP(p_parent_rate,
+ fd->max_prate);
+ *parent_rate = p_parent_rate / div;
+ }
}
if (*parent_rate < rate * 20) {
- pr_err("%s parent_rate(%ld) is low than rate(%ld)*20, fractional div is not allowed\n",
- clk_hw_get_name(hw), *parent_rate, rate);
+ pr_warn("%s p_rate(%ld) is low than rate(%ld)*20, use integer or half-div\n",
+ clk_hw_get_name(hw), *parent_rate, rate);
*m = 0;
*n = 1;
return;
--
2.17.1
Rockchip socs often have some tiny number of muxes not controlled from
the core clock controller but through bits set in the pmugrf.
Use MUXPMUGRF() to cover this special clock-type.
Signed-off-by: Elaine Zhang <[email protected]>
---
drivers/clk/rockchip/clk.c | 9 +++++++++
drivers/clk/rockchip/clk.h | 17 +++++++++++++++++
2 files changed, 26 insertions(+)
diff --git a/drivers/clk/rockchip/clk.c b/drivers/clk/rockchip/clk.c
index 8f77c3f9fab7..4f238f2851ac 100644
--- a/drivers/clk/rockchip/clk.c
+++ b/drivers/clk/rockchip/clk.c
@@ -407,6 +407,8 @@ struct rockchip_clk_provider * __init rockchip_clk_init(struct device_node *np,
ctx->grf = syscon_regmap_lookup_by_phandle(ctx->cru_node,
"rockchip,grf");
+ ctx->pmugrf = syscon_regmap_lookup_by_phandle(ctx->cru_node,
+ "rockchip,pmugrf");
return ctx;
@@ -482,6 +484,13 @@ void __init rockchip_clk_register_branches(
list->mux_shift, list->mux_width,
list->mux_flags);
break;
+ case branch_muxpmugrf:
+ clk = rockchip_clk_register_muxgrf(list->name,
+ list->parent_names, list->num_parents,
+ flags, ctx->pmugrf, list->muxdiv_offset,
+ list->mux_shift, list->mux_width,
+ list->mux_flags);
+ break;
case branch_divider:
if (list->div_table)
clk = clk_register_divider_table(NULL,
diff --git a/drivers/clk/rockchip/clk.h b/drivers/clk/rockchip/clk.h
index 0d401ce09a54..ae059b7744f9 100644
--- a/drivers/clk/rockchip/clk.h
+++ b/drivers/clk/rockchip/clk.h
@@ -238,6 +238,7 @@ struct rockchip_clk_provider {
struct clk_onecell_data clk_data;
struct device_node *cru_node;
struct regmap *grf;
+ struct regmap *pmugrf;
spinlock_t lock;
};
@@ -390,6 +391,7 @@ enum rockchip_clk_branch_type {
branch_composite,
branch_mux,
branch_muxgrf,
+ branch_muxpmugrf,
branch_divider,
branch_fraction_divider,
branch_gate,
@@ -662,6 +664,21 @@ struct rockchip_clk_branch {
.gate_offset = -1, \
}
+#define MUXPMUGRF(_id, cname, pnames, f, o, s, w, mf) \
+ { \
+ .id = _id, \
+ .branch_type = branch_muxpmugrf, \
+ .name = cname, \
+ .parent_names = pnames, \
+ .num_parents = ARRAY_SIZE(pnames), \
+ .flags = f, \
+ .muxdiv_offset = o, \
+ .mux_shift = s, \
+ .mux_width = w, \
+ .mux_flags = mf, \
+ .gate_offset = -1, \
+ }
+
#define DIV(_id, cname, pname, f, o, s, w, df) \
{ \
.id = _id, \
--
2.17.1