diff options
author | Icenowy Zheng <icenowy@aosc.io> | 2018-03-16 10:02:11 -0400 |
---|---|---|
committer | Maxime Ripard <maxime.ripard@bootlin.com> | 2018-03-18 16:16:54 -0400 |
commit | a910f251ee084230e2f8d214f1621346cec94e69 (patch) | |
tree | 0d6f3659b49faa55ca3b4af6a8f07f0bf52ed4ad /drivers | |
parent | 55de0f31df1a31b346edfe98d061f11162ff1ad4 (diff) |
clk: sunxi-ng: Support fixed post-dividers on NKMP style clocks
On the new Allwinner H6 SoC, multiple PLL's are NMP style clocks
(modelled as NKMP with no K) and have fixed post-dividers.
Add fixed post divider support to the NKMP style clocks.
Signed-off-by: Icenowy Zheng <icenowy@aosc.io>
Signed-off-by: Maxime Ripard <maxime.ripard@bootlin.com>
Diffstat (limited to 'drivers')
-rw-r--r-- | drivers/clk/sunxi-ng/ccu_nkmp.c | 20 | ||||
-rw-r--r-- | drivers/clk/sunxi-ng/ccu_nkmp.h | 2 |
2 files changed, 19 insertions, 3 deletions
diff --git a/drivers/clk/sunxi-ng/ccu_nkmp.c b/drivers/clk/sunxi-ng/ccu_nkmp.c index c3f6fe7be565..ebd9436d2c7c 100644 --- a/drivers/clk/sunxi-ng/ccu_nkmp.c +++ b/drivers/clk/sunxi-ng/ccu_nkmp.c | |||
@@ -95,7 +95,7 @@ static unsigned long ccu_nkmp_recalc_rate(struct clk_hw *hw, | |||
95 | unsigned long parent_rate) | 95 | unsigned long parent_rate) |
96 | { | 96 | { |
97 | struct ccu_nkmp *nkmp = hw_to_ccu_nkmp(hw); | 97 | struct ccu_nkmp *nkmp = hw_to_ccu_nkmp(hw); |
98 | unsigned long n, m, k, p; | 98 | unsigned long n, m, k, p, rate; |
99 | u32 reg; | 99 | u32 reg; |
100 | 100 | ||
101 | reg = readl(nkmp->common.base + nkmp->common.reg); | 101 | reg = readl(nkmp->common.base + nkmp->common.reg); |
@@ -121,7 +121,11 @@ static unsigned long ccu_nkmp_recalc_rate(struct clk_hw *hw, | |||
121 | p = reg >> nkmp->p.shift; | 121 | p = reg >> nkmp->p.shift; |
122 | p &= (1 << nkmp->p.width) - 1; | 122 | p &= (1 << nkmp->p.width) - 1; |
123 | 123 | ||
124 | return ccu_nkmp_calc_rate(parent_rate, n, k, m, 1 << p); | 124 | rate = ccu_nkmp_calc_rate(parent_rate, n, k, m, 1 << p); |
125 | if (nkmp->common.features & CCU_FEATURE_FIXED_POSTDIV) | ||
126 | rate /= nkmp->fixed_post_div; | ||
127 | |||
128 | return rate; | ||
125 | } | 129 | } |
126 | 130 | ||
127 | static long ccu_nkmp_round_rate(struct clk_hw *hw, unsigned long rate, | 131 | static long ccu_nkmp_round_rate(struct clk_hw *hw, unsigned long rate, |
@@ -130,6 +134,9 @@ static long ccu_nkmp_round_rate(struct clk_hw *hw, unsigned long rate, | |||
130 | struct ccu_nkmp *nkmp = hw_to_ccu_nkmp(hw); | 134 | struct ccu_nkmp *nkmp = hw_to_ccu_nkmp(hw); |
131 | struct _ccu_nkmp _nkmp; | 135 | struct _ccu_nkmp _nkmp; |
132 | 136 | ||
137 | if (nkmp->common.features & CCU_FEATURE_FIXED_POSTDIV) | ||
138 | rate *= nkmp->fixed_post_div; | ||
139 | |||
133 | _nkmp.min_n = nkmp->n.min ?: 1; | 140 | _nkmp.min_n = nkmp->n.min ?: 1; |
134 | _nkmp.max_n = nkmp->n.max ?: 1 << nkmp->n.width; | 141 | _nkmp.max_n = nkmp->n.max ?: 1 << nkmp->n.width; |
135 | _nkmp.min_k = nkmp->k.min ?: 1; | 142 | _nkmp.min_k = nkmp->k.min ?: 1; |
@@ -141,8 +148,12 @@ static long ccu_nkmp_round_rate(struct clk_hw *hw, unsigned long rate, | |||
141 | 148 | ||
142 | ccu_nkmp_find_best(*parent_rate, rate, &_nkmp); | 149 | ccu_nkmp_find_best(*parent_rate, rate, &_nkmp); |
143 | 150 | ||
144 | return ccu_nkmp_calc_rate(*parent_rate, _nkmp.n, _nkmp.k, | 151 | rate = ccu_nkmp_calc_rate(*parent_rate, _nkmp.n, _nkmp.k, |
145 | _nkmp.m, _nkmp.p); | 152 | _nkmp.m, _nkmp.p); |
153 | if (nkmp->common.features & CCU_FEATURE_FIXED_POSTDIV) | ||
154 | rate = rate / nkmp->fixed_post_div; | ||
155 | |||
156 | return rate; | ||
146 | } | 157 | } |
147 | 158 | ||
148 | static int ccu_nkmp_set_rate(struct clk_hw *hw, unsigned long rate, | 159 | static int ccu_nkmp_set_rate(struct clk_hw *hw, unsigned long rate, |
@@ -154,6 +165,9 @@ static int ccu_nkmp_set_rate(struct clk_hw *hw, unsigned long rate, | |||
154 | unsigned long flags; | 165 | unsigned long flags; |
155 | u32 reg; | 166 | u32 reg; |
156 | 167 | ||
168 | if (nkmp->common.features & CCU_FEATURE_FIXED_POSTDIV) | ||
169 | rate = rate * nkmp->fixed_post_div; | ||
170 | |||
157 | _nkmp.min_n = nkmp->n.min ?: 1; | 171 | _nkmp.min_n = nkmp->n.min ?: 1; |
158 | _nkmp.max_n = nkmp->n.max ?: 1 << nkmp->n.width; | 172 | _nkmp.max_n = nkmp->n.max ?: 1 << nkmp->n.width; |
159 | _nkmp.min_k = nkmp->k.min ?: 1; | 173 | _nkmp.min_k = nkmp->k.min ?: 1; |
diff --git a/drivers/clk/sunxi-ng/ccu_nkmp.h b/drivers/clk/sunxi-ng/ccu_nkmp.h index a82facbc6144..6940503e7fc4 100644 --- a/drivers/clk/sunxi-ng/ccu_nkmp.h +++ b/drivers/clk/sunxi-ng/ccu_nkmp.h | |||
@@ -34,6 +34,8 @@ struct ccu_nkmp { | |||
34 | struct ccu_div_internal m; | 34 | struct ccu_div_internal m; |
35 | struct ccu_div_internal p; | 35 | struct ccu_div_internal p; |
36 | 36 | ||
37 | unsigned int fixed_post_div; | ||
38 | |||
37 | struct ccu_common common; | 39 | struct ccu_common common; |
38 | }; | 40 | }; |
39 | 41 | ||