aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/clk
diff options
context:
space:
mode:
authorLinus Torvalds <torvalds@linux-foundation.org>2014-10-15 01:05:03 -0400
committerLinus Torvalds <torvalds@linux-foundation.org>2014-10-15 01:05:03 -0400
commitc0fa2373f8cfed90437d8d7b17e0b1a84009a10a (patch)
tree43fb2edd0c11874d0b2e56714e53894d10321e19 /drivers/clk
parentfcc3a5d277571bc6048e7b4ef8cd391b935de629 (diff)
parent98d147f50eb0ce4328e013f5f2c076896003c761 (diff)
Merge tag 'clk-for-linus-3.18' of git://git.linaro.org/people/mike.turquette/linux
Pull clock tree updates from Mike Turquette: "The clk tree changes for 3.18 are dominated by clock drivers. Mostly fixes and enhancements to existing drivers as well as new drivers. This tag contains a bit more arch code than I usually take due to some OMAP2+ changes. Additionally it contains the restart notifier handlers which are merged as a dependency into several trees. The PXA changes are the only messy part. Due to having a stable tree I had to revert one patch and follow up with one more fix near the tip of this tag. Some dead code is introduced but it will soon become live code after 3.18-rc1 is released as the rest of the PXA family is converted over to the common clock framework. Another trend in this tag is that multiple vendors have started to push the complexity of changing their CPU frequency into the clock driver, whereas this used to be done in CPUfreq drivers. Changes to the clk core include a generic gpio-clock type and a clk_set_phase() function added to the top-level clk.h api. Due to some confusion on the fbdev mailing list the kernel boot parameters documentation was updated to further explain the clk_ignore_unused parameter, which is often required by users of the simplefb driver. Finally some fixes to the locking around the clock debugfs stuff was done to prevent deadlocks when interacting with other subsystems." * tag 'clk-for-linus-3.18' of git://git.linaro.org/people/mike.turquette/linux: (99 commits) clk: pxa clocks build system fix Revert "arm: pxa: Transition pxa27x to clk framework" clk: samsung: register restart handlers for s3c2412 and s3c2443 clk: rockchip: add restart handler clk: rockchip: rk3288: i2s_frac adds flag to set parent's rate doc/kernel-parameters.txt: clarify clk_ignore_unused arm: pxa: Transition pxa27x to clk framework dts: add devicetree bindings for pxa27x clocks clk: add pxa27x clock drivers arm: pxa: add clock pll selection bits clk: dts: document pxa clock binding clk: add pxa clocks infrastructure clk: gpio-gate: Ensure gpiod_ APIs are prototyped clk: ti: dra7-atl-clock: Mark the device as pm_runtime_irq_safe clk: ti: LLVMLinux: Move __init outside of type definition clk: ti: consider the fact that of_clk_get() might return an error clk: ti: dra7-atl-clock: fix a memory leak clk: ti: change clock init to use generic of_clk_init clk: hix5hd2: add I2C clocks clk: hix5hd2: add watchdog0 clocks ...
Diffstat (limited to 'drivers/clk')
-rw-r--r--drivers/clk/Kconfig16
-rw-r--r--drivers/clk/Makefile4
-rw-r--r--drivers/clk/at91/clk-pll.c160
-rw-r--r--drivers/clk/at91/clk-usb.c20
-rw-r--r--drivers/clk/clk-axi-clkgen.c1
-rw-r--r--drivers/clk/clk-fractional-divider.c2
-rw-r--r--drivers/clk/clk-gate.c2
-rw-r--r--drivers/clk/clk-gpio-gate.c205
-rw-r--r--drivers/clk/clk-max-gen.c192
-rw-r--r--drivers/clk/clk-max-gen.h32
-rw-r--r--drivers/clk/clk-max77686.c184
-rw-r--r--drivers/clk/clk-max77802.c97
-rw-r--r--drivers/clk/clk-palmas.c1
-rw-r--r--drivers/clk/clk-twl6040.c1
-rw-r--r--drivers/clk/clk-wm831x.c1
-rw-r--r--drivers/clk/clk.c168
-rw-r--r--drivers/clk/hisilicon/clk-hix5hd2.c232
-rw-r--r--drivers/clk/mvebu/armada-370.c8
-rw-r--r--drivers/clk/mvebu/armada-375.c4
-rw-r--r--drivers/clk/mvebu/common.c91
-rw-r--r--drivers/clk/mvebu/common.h9
-rw-r--r--drivers/clk/mvebu/kirkwood.c102
-rw-r--r--drivers/clk/pxa/Makefile2
-rw-r--r--drivers/clk/pxa/clk-pxa.c97
-rw-r--r--drivers/clk/pxa/clk-pxa.h107
-rw-r--r--drivers/clk/pxa/clk-pxa27x.c370
-rw-r--r--drivers/clk/qcom/clk-pll.c68
-rw-r--r--drivers/clk/qcom/clk-pll.h20
-rw-r--r--drivers/clk/qcom/clk-rcg.c115
-rw-r--r--drivers/clk/qcom/clk-rcg.h6
-rw-r--r--drivers/clk/qcom/clk-rcg2.c19
-rw-r--r--drivers/clk/qcom/common.c16
-rw-r--r--drivers/clk/qcom/common.h4
-rw-r--r--drivers/clk/qcom/gcc-ipq806x.c31
-rw-r--r--drivers/clk/qcom/mmcc-apq8084.c1
-rw-r--r--drivers/clk/qcom/mmcc-msm8960.c29
-rw-r--r--drivers/clk/qcom/mmcc-msm8974.c1
-rw-r--r--drivers/clk/rockchip/Makefile1
-rw-r--r--drivers/clk/rockchip/clk-cpu.c329
-rw-r--r--drivers/clk/rockchip/clk-pll.c63
-rw-r--r--drivers/clk/rockchip/clk-rk3188.c171
-rw-r--r--drivers/clk/rockchip/clk-rk3288.c203
-rw-r--r--drivers/clk/rockchip/clk.c119
-rw-r--r--drivers/clk/rockchip/clk.h39
-rw-r--r--drivers/clk/samsung/clk-exynos3250.c202
-rw-r--r--drivers/clk/samsung/clk-exynos4.c18
-rw-r--r--drivers/clk/samsung/clk-exynos5260.c2
-rw-r--r--drivers/clk/samsung/clk-s3c2410-dclk.c1
-rw-r--r--drivers/clk/samsung/clk-s3c2412.c29
-rw-r--r--drivers/clk/samsung/clk-s3c2443.c19
-rw-r--r--drivers/clk/shmobile/clk-rcar-gen2.c1
-rw-r--r--drivers/clk/sunxi/Makefile2
-rw-r--r--drivers/clk/sunxi/clk-factors.c101
-rw-r--r--drivers/clk/sunxi/clk-factors.h16
-rw-r--r--drivers/clk/sunxi/clk-mod0.c283
-rw-r--r--drivers/clk/sunxi/clk-sun6i-apb0-gates.c1
-rw-r--r--drivers/clk/sunxi/clk-sun6i-apb0.c1
-rw-r--r--drivers/clk/sunxi/clk-sun6i-ar100.c1
-rw-r--r--drivers/clk/sunxi/clk-sun8i-apb0.c1
-rw-r--r--drivers/clk/sunxi/clk-sun8i-mbus.c78
-rw-r--r--drivers/clk/sunxi/clk-sunxi.c161
-rw-r--r--drivers/clk/tegra/clk-tegra124.c8
-rw-r--r--drivers/clk/tegra/clk.c9
-rw-r--r--drivers/clk/ti/clk-dra7-atl.c3
-rw-r--r--drivers/clk/ti/clk.c68
-rw-r--r--drivers/clk/ti/clockdomain.c5
-rw-r--r--drivers/clk/ti/divider.c4
-rw-r--r--drivers/clk/zynq/clkc.c30
-rw-r--r--drivers/clk/zynq/pll.c4
69 files changed, 3627 insertions, 764 deletions
diff --git a/drivers/clk/Kconfig b/drivers/clk/Kconfig
index 84e0590e31dc..455fd17d938e 100644
--- a/drivers/clk/Kconfig
+++ b/drivers/clk/Kconfig
@@ -32,12 +32,23 @@ config COMMON_CLK_WM831X
32 32
33source "drivers/clk/versatile/Kconfig" 33source "drivers/clk/versatile/Kconfig"
34 34
35config COMMON_CLK_MAX_GEN
36 bool
37
35config COMMON_CLK_MAX77686 38config COMMON_CLK_MAX77686
36 tristate "Clock driver for Maxim 77686 MFD" 39 tristate "Clock driver for Maxim 77686 MFD"
37 depends on MFD_MAX77686 40 depends on MFD_MAX77686
41 select COMMON_CLK_MAX_GEN
38 ---help--- 42 ---help---
39 This driver supports Maxim 77686 crystal oscillator clock. 43 This driver supports Maxim 77686 crystal oscillator clock.
40 44
45config COMMON_CLK_MAX77802
46 tristate "Clock driver for Maxim 77802 PMIC"
47 depends on MFD_MAX77686
48 select COMMON_CLK_MAX_GEN
49 ---help---
50 This driver supports Maxim 77802 crystal oscillator clock.
51
41config COMMON_CLK_RK808 52config COMMON_CLK_RK808
42 tristate "Clock driver for RK808" 53 tristate "Clock driver for RK808"
43 depends on MFD_RK808 54 depends on MFD_RK808
@@ -118,6 +129,11 @@ config COMMON_CLK_PALMAS
118 This driver supports TI Palmas devices 32KHz output KG and KG_AUDIO 129 This driver supports TI Palmas devices 32KHz output KG and KG_AUDIO
119 using common clock framework. 130 using common clock framework.
120 131
132config COMMON_CLK_PXA
133 def_bool COMMON_CLK && ARCH_PXA
134 ---help---
135 Sypport for the Marvell PXA SoC.
136
121source "drivers/clk/qcom/Kconfig" 137source "drivers/clk/qcom/Kconfig"
122 138
123endmenu 139endmenu
diff --git a/drivers/clk/Makefile b/drivers/clk/Makefile
index 99f53d5f8766..d5fba5bc6e1b 100644
--- a/drivers/clk/Makefile
+++ b/drivers/clk/Makefile
@@ -9,6 +9,7 @@ obj-$(CONFIG_COMMON_CLK) += clk-gate.o
9obj-$(CONFIG_COMMON_CLK) += clk-mux.o 9obj-$(CONFIG_COMMON_CLK) += clk-mux.o
10obj-$(CONFIG_COMMON_CLK) += clk-composite.o 10obj-$(CONFIG_COMMON_CLK) += clk-composite.o
11obj-$(CONFIG_COMMON_CLK) += clk-fractional-divider.o 11obj-$(CONFIG_COMMON_CLK) += clk-fractional-divider.o
12obj-$(CONFIG_COMMON_CLK) += clk-gpio-gate.o
12ifeq ($(CONFIG_OF), y) 13ifeq ($(CONFIG_OF), y)
13obj-$(CONFIG_COMMON_CLK) += clk-conf.o 14obj-$(CONFIG_COMMON_CLK) += clk-conf.o
14endif 15endif
@@ -22,7 +23,9 @@ obj-$(CONFIG_ARCH_CLPS711X) += clk-clps711x.o
22obj-$(CONFIG_ARCH_EFM32) += clk-efm32gg.o 23obj-$(CONFIG_ARCH_EFM32) += clk-efm32gg.o
23obj-$(CONFIG_ARCH_HIGHBANK) += clk-highbank.o 24obj-$(CONFIG_ARCH_HIGHBANK) += clk-highbank.o
24obj-$(CONFIG_MACH_LOONGSON1) += clk-ls1x.o 25obj-$(CONFIG_MACH_LOONGSON1) += clk-ls1x.o
26obj-$(CONFIG_COMMON_CLK_MAX_GEN) += clk-max-gen.o
25obj-$(CONFIG_COMMON_CLK_MAX77686) += clk-max77686.o 27obj-$(CONFIG_COMMON_CLK_MAX77686) += clk-max77686.o
28obj-$(CONFIG_COMMON_CLK_MAX77802) += clk-max77802.o
26obj-$(CONFIG_ARCH_MOXART) += clk-moxart.o 29obj-$(CONFIG_ARCH_MOXART) += clk-moxart.o
27obj-$(CONFIG_ARCH_NOMADIK) += clk-nomadik.o 30obj-$(CONFIG_ARCH_NOMADIK) += clk-nomadik.o
28obj-$(CONFIG_ARCH_NSPIRE) += clk-nspire.o 31obj-$(CONFIG_ARCH_NSPIRE) += clk-nspire.o
@@ -49,6 +52,7 @@ obj-$(CONFIG_ARCH_MMP) += mmp/
49endif 52endif
50obj-$(CONFIG_PLAT_ORION) += mvebu/ 53obj-$(CONFIG_PLAT_ORION) += mvebu/
51obj-$(CONFIG_ARCH_MXS) += mxs/ 54obj-$(CONFIG_ARCH_MXS) += mxs/
55obj-$(CONFIG_COMMON_CLK_PXA) += pxa/
52obj-$(CONFIG_COMMON_CLK_QCOM) += qcom/ 56obj-$(CONFIG_COMMON_CLK_QCOM) += qcom/
53obj-$(CONFIG_ARCH_ROCKCHIP) += rockchip/ 57obj-$(CONFIG_ARCH_ROCKCHIP) += rockchip/
54obj-$(CONFIG_COMMON_CLK_SAMSUNG) += samsung/ 58obj-$(CONFIG_COMMON_CLK_SAMSUNG) += samsung/
diff --git a/drivers/clk/at91/clk-pll.c b/drivers/clk/at91/clk-pll.c
index cf6ed023504c..6ec79dbc0840 100644
--- a/drivers/clk/at91/clk-pll.c
+++ b/drivers/clk/at91/clk-pll.c
@@ -15,6 +15,7 @@
15#include <linux/of_address.h> 15#include <linux/of_address.h>
16#include <linux/of_irq.h> 16#include <linux/of_irq.h>
17#include <linux/io.h> 17#include <linux/io.h>
18#include <linux/kernel.h>
18#include <linux/wait.h> 19#include <linux/wait.h>
19#include <linux/sched.h> 20#include <linux/sched.h>
20#include <linux/interrupt.h> 21#include <linux/interrupt.h>
@@ -29,9 +30,12 @@
29#define PLL_DIV(reg) ((reg) & PLL_DIV_MASK) 30#define PLL_DIV(reg) ((reg) & PLL_DIV_MASK)
30#define PLL_MUL(reg, layout) (((reg) >> (layout)->mul_shift) & \ 31#define PLL_MUL(reg, layout) (((reg) >> (layout)->mul_shift) & \
31 (layout)->mul_mask) 32 (layout)->mul_mask)
33#define PLL_MUL_MIN 2
34#define PLL_MUL_MASK(layout) ((layout)->mul_mask)
35#define PLL_MUL_MAX(layout) (PLL_MUL_MASK(layout) + 1)
32#define PLL_ICPR_SHIFT(id) ((id) * 16) 36#define PLL_ICPR_SHIFT(id) ((id) * 16)
33#define PLL_ICPR_MASK(id) (0xffff << PLL_ICPR_SHIFT(id)) 37#define PLL_ICPR_MASK(id) (0xffff << PLL_ICPR_SHIFT(id))
34#define PLL_MAX_COUNT 0x3ff 38#define PLL_MAX_COUNT 0x3f
35#define PLL_COUNT_SHIFT 8 39#define PLL_COUNT_SHIFT 8
36#define PLL_OUT_SHIFT 14 40#define PLL_OUT_SHIFT 14
37#define PLL_MAX_ID 1 41#define PLL_MAX_ID 1
@@ -147,115 +151,113 @@ static unsigned long clk_pll_recalc_rate(struct clk_hw *hw,
147 unsigned long parent_rate) 151 unsigned long parent_rate)
148{ 152{
149 struct clk_pll *pll = to_clk_pll(hw); 153 struct clk_pll *pll = to_clk_pll(hw);
150 const struct clk_pll_layout *layout = pll->layout; 154
151 struct at91_pmc *pmc = pll->pmc; 155 if (!pll->div || !pll->mul)
152 int offset = PLL_REG(pll->id);
153 u32 tmp = pmc_read(pmc, offset) & layout->pllr_mask;
154 u8 div = PLL_DIV(tmp);
155 u16 mul = PLL_MUL(tmp, layout);
156 if (!div || !mul)
157 return 0; 156 return 0;
158 157
159 return (parent_rate * (mul + 1)) / div; 158 return (parent_rate / pll->div) * (pll->mul + 1);
160} 159}
161 160
162static long clk_pll_get_best_div_mul(struct clk_pll *pll, unsigned long rate, 161static long clk_pll_get_best_div_mul(struct clk_pll *pll, unsigned long rate,
163 unsigned long parent_rate, 162 unsigned long parent_rate,
164 u32 *div, u32 *mul, 163 u32 *div, u32 *mul,
165 u32 *index) { 164 u32 *index) {
166 unsigned long maxrate;
167 unsigned long minrate;
168 unsigned long divrate;
169 unsigned long bestdiv = 1;
170 unsigned long bestmul;
171 unsigned long tmpdiv;
172 unsigned long roundup;
173 unsigned long rounddown;
174 unsigned long remainder;
175 unsigned long bestremainder;
176 unsigned long maxmul;
177 unsigned long maxdiv;
178 unsigned long mindiv;
179 int i = 0;
180 const struct clk_pll_layout *layout = pll->layout; 165 const struct clk_pll_layout *layout = pll->layout;
181 const struct clk_pll_characteristics *characteristics = 166 const struct clk_pll_characteristics *characteristics =
182 pll->characteristics; 167 pll->characteristics;
168 unsigned long bestremainder = ULONG_MAX;
169 unsigned long maxdiv, mindiv, tmpdiv;
170 long bestrate = -ERANGE;
171 unsigned long bestdiv;
172 unsigned long bestmul;
173 int i = 0;
183 174
184 /* Minimum divider = 1 */ 175 /* Check if parent_rate is a valid input rate */
185 /* Maximum multiplier = max_mul */
186 maxmul = layout->mul_mask + 1;
187 maxrate = (parent_rate * maxmul) / 1;
188
189 /* Maximum divider = max_div */
190 /* Minimum multiplier = 2 */
191 maxdiv = PLL_DIV_MAX;
192 minrate = (parent_rate * 2) / maxdiv;
193
194 if (parent_rate < characteristics->input.min || 176 if (parent_rate < characteristics->input.min ||
195 parent_rate < characteristics->input.max) 177 parent_rate > characteristics->input.max)
196 return -ERANGE;
197
198 if (parent_rate < minrate || parent_rate > maxrate)
199 return -ERANGE; 178 return -ERANGE;
200 179
201 for (i = 0; i < characteristics->num_output; i++) { 180 /*
202 if (parent_rate >= characteristics->output[i].min && 181 * Calculate minimum divider based on the minimum multiplier, the
203 parent_rate <= characteristics->output[i].max) 182 * parent_rate and the requested rate.
204 break; 183 * Should always be 2 according to the input and output characteristics
205 } 184 * of the PLL blocks.
206 185 */
207 if (i >= characteristics->num_output) 186 mindiv = (parent_rate * PLL_MUL_MIN) / rate;
208 return -ERANGE; 187 if (!mindiv)
209 188 mindiv = 1;
210 bestmul = rate / parent_rate; 189
211 rounddown = parent_rate % rate; 190 /*
212 roundup = rate - rounddown; 191 * Calculate the maximum divider which is limited by PLL register
213 bestremainder = roundup < rounddown ? roundup : rounddown; 192 * layout (limited by the MUL or DIV field size).
214 193 */
215 if (!bestremainder) { 194 maxdiv = DIV_ROUND_UP(parent_rate * PLL_MUL_MAX(layout), rate);
216 if (div) 195 if (maxdiv > PLL_DIV_MAX)
217 *div = bestdiv; 196 maxdiv = PLL_DIV_MAX;
218 if (mul) 197
219 *mul = bestmul; 198 /*
220 if (index) 199 * Iterate over the acceptable divider values to find the best
221 *index = i; 200 * divider/multiplier pair (the one that generates the closest
222 return rate; 201 * rate to the requested one).
223 } 202 */
224 203 for (tmpdiv = mindiv; tmpdiv <= maxdiv; tmpdiv++) {
225 maxdiv = 255 / (bestmul + 1); 204 unsigned long remainder;
226 if (parent_rate / maxdiv < characteristics->input.min) 205 unsigned long tmprate;
227 maxdiv = parent_rate / characteristics->input.min; 206 unsigned long tmpmul;
228 mindiv = parent_rate / characteristics->input.max; 207
229 if (parent_rate % characteristics->input.max) 208 /*
230 mindiv++; 209 * Calculate the multiplier associated with the current
231 210 * divider that provide the closest rate to the requested one.
232 for (tmpdiv = mindiv; tmpdiv < maxdiv; tmpdiv++) { 211 */
233 divrate = parent_rate / tmpdiv; 212 tmpmul = DIV_ROUND_CLOSEST(rate, parent_rate / tmpdiv);
234 213 tmprate = (parent_rate / tmpdiv) * tmpmul;
235 rounddown = rate % divrate; 214 if (tmprate > rate)
236 roundup = divrate - rounddown; 215 remainder = tmprate - rate;
237 remainder = roundup < rounddown ? roundup : rounddown; 216 else
238 217 remainder = rate - tmprate;
218
219 /*
220 * Compare the remainder with the best remainder found until
221 * now and elect a new best multiplier/divider pair if the
222 * current remainder is smaller than the best one.
223 */
239 if (remainder < bestremainder) { 224 if (remainder < bestremainder) {
240 bestremainder = remainder; 225 bestremainder = remainder;
241 bestmul = rate / divrate;
242 bestdiv = tmpdiv; 226 bestdiv = tmpdiv;
227 bestmul = tmpmul;
228 bestrate = tmprate;
243 } 229 }
244 230
231 /*
232 * We've found a perfect match!
233 * Stop searching now and use this multiplier/divider pair.
234 */
245 if (!remainder) 235 if (!remainder)
246 break; 236 break;
247 } 237 }
248 238
249 rate = (parent_rate / bestdiv) * bestmul; 239 /* We haven't found any multiplier/divider pair => return -ERANGE */
240 if (bestrate < 0)
241 return bestrate;
242
243 /* Check if bestrate is a valid output rate */
244 for (i = 0; i < characteristics->num_output; i++) {
245 if (bestrate >= characteristics->output[i].min &&
246 bestrate <= characteristics->output[i].max)
247 break;
248 }
249
250 if (i >= characteristics->num_output)
251 return -ERANGE;
250 252
251 if (div) 253 if (div)
252 *div = bestdiv; 254 *div = bestdiv;
253 if (mul) 255 if (mul)
254 *mul = bestmul; 256 *mul = bestmul - 1;
255 if (index) 257 if (index)
256 *index = i; 258 *index = i;
257 259
258 return rate; 260 return bestrate;
259} 261}
260 262
261static long clk_pll_round_rate(struct clk_hw *hw, unsigned long rate, 263static long clk_pll_round_rate(struct clk_hw *hw, unsigned long rate,
diff --git a/drivers/clk/at91/clk-usb.c b/drivers/clk/at91/clk-usb.c
index 7d1d26a4bd04..24b5b020753a 100644
--- a/drivers/clk/at91/clk-usb.c
+++ b/drivers/clk/at91/clk-usb.c
@@ -238,16 +238,22 @@ static long at91rm9200_clk_usb_round_rate(struct clk_hw *hw, unsigned long rate,
238 unsigned long *parent_rate) 238 unsigned long *parent_rate)
239{ 239{
240 struct at91rm9200_clk_usb *usb = to_at91rm9200_clk_usb(hw); 240 struct at91rm9200_clk_usb *usb = to_at91rm9200_clk_usb(hw);
241 struct clk *parent = __clk_get_parent(hw->clk);
241 unsigned long bestrate = 0; 242 unsigned long bestrate = 0;
242 int bestdiff = -1; 243 int bestdiff = -1;
243 unsigned long tmprate; 244 unsigned long tmprate;
244 int tmpdiff; 245 int tmpdiff;
245 int i = 0; 246 int i = 0;
246 247
247 for (i = 0; i < 4; i++) { 248 for (i = 0; i < RM9200_USB_DIV_TAB_SIZE; i++) {
249 unsigned long tmp_parent_rate;
250
248 if (!usb->divisors[i]) 251 if (!usb->divisors[i])
249 continue; 252 continue;
250 tmprate = *parent_rate / usb->divisors[i]; 253
254 tmp_parent_rate = rate * usb->divisors[i];
255 tmp_parent_rate = __clk_round_rate(parent, tmp_parent_rate);
256 tmprate = tmp_parent_rate / usb->divisors[i];
251 if (tmprate < rate) 257 if (tmprate < rate)
252 tmpdiff = rate - tmprate; 258 tmpdiff = rate - tmprate;
253 else 259 else
@@ -256,6 +262,7 @@ static long at91rm9200_clk_usb_round_rate(struct clk_hw *hw, unsigned long rate,
256 if (bestdiff < 0 || bestdiff > tmpdiff) { 262 if (bestdiff < 0 || bestdiff > tmpdiff) {
257 bestrate = tmprate; 263 bestrate = tmprate;
258 bestdiff = tmpdiff; 264 bestdiff = tmpdiff;
265 *parent_rate = tmp_parent_rate;
259 } 266 }
260 267
261 if (!bestdiff) 268 if (!bestdiff)
@@ -272,10 +279,13 @@ static int at91rm9200_clk_usb_set_rate(struct clk_hw *hw, unsigned long rate,
272 int i; 279 int i;
273 struct at91rm9200_clk_usb *usb = to_at91rm9200_clk_usb(hw); 280 struct at91rm9200_clk_usb *usb = to_at91rm9200_clk_usb(hw);
274 struct at91_pmc *pmc = usb->pmc; 281 struct at91_pmc *pmc = usb->pmc;
275 unsigned long div = parent_rate / rate; 282 unsigned long div;
276 283
277 if (parent_rate % rate) 284 if (!rate || parent_rate % rate)
278 return -EINVAL; 285 return -EINVAL;
286
287 div = parent_rate / rate;
288
279 for (i = 0; i < RM9200_USB_DIV_TAB_SIZE; i++) { 289 for (i = 0; i < RM9200_USB_DIV_TAB_SIZE; i++) {
280 if (usb->divisors[i] == div) { 290 if (usb->divisors[i] == div) {
281 tmp = pmc_read(pmc, AT91_CKGR_PLLBR) & 291 tmp = pmc_read(pmc, AT91_CKGR_PLLBR) &
@@ -311,7 +321,7 @@ at91rm9200_clk_register_usb(struct at91_pmc *pmc, const char *name,
311 init.ops = &at91rm9200_usb_ops; 321 init.ops = &at91rm9200_usb_ops;
312 init.parent_names = &parent_name; 322 init.parent_names = &parent_name;
313 init.num_parents = 1; 323 init.num_parents = 1;
314 init.flags = 0; 324 init.flags = CLK_SET_RATE_PARENT;
315 325
316 usb->hw.init = &init; 326 usb->hw.init = &init;
317 usb->pmc = pmc; 327 usb->pmc = pmc;
diff --git a/drivers/clk/clk-axi-clkgen.c b/drivers/clk/clk-axi-clkgen.c
index 1127ee46b802..e619285c6def 100644
--- a/drivers/clk/clk-axi-clkgen.c
+++ b/drivers/clk/clk-axi-clkgen.c
@@ -544,7 +544,6 @@ static int axi_clkgen_remove(struct platform_device *pdev)
544static struct platform_driver axi_clkgen_driver = { 544static struct platform_driver axi_clkgen_driver = {
545 .driver = { 545 .driver = {
546 .name = "adi-axi-clkgen", 546 .name = "adi-axi-clkgen",
547 .owner = THIS_MODULE,
548 .of_match_table = axi_clkgen_ids, 547 .of_match_table = axi_clkgen_ids,
549 }, 548 },
550 .probe = axi_clkgen_probe, 549 .probe = axi_clkgen_probe,
diff --git a/drivers/clk/clk-fractional-divider.c b/drivers/clk/clk-fractional-divider.c
index ede685ca0d20..82a59d0086cc 100644
--- a/drivers/clk/clk-fractional-divider.c
+++ b/drivers/clk/clk-fractional-divider.c
@@ -36,7 +36,7 @@ static unsigned long clk_fd_recalc_rate(struct clk_hw *hw,
36 m = (val & fd->mmask) >> fd->mshift; 36 m = (val & fd->mmask) >> fd->mshift;
37 n = (val & fd->nmask) >> fd->nshift; 37 n = (val & fd->nmask) >> fd->nshift;
38 38
39 ret = parent_rate * m; 39 ret = (u64)parent_rate * m;
40 do_div(ret, n); 40 do_div(ret, n);
41 41
42 return ret; 42 return ret;
diff --git a/drivers/clk/clk-gate.c b/drivers/clk/clk-gate.c
index 4a58c55255bd..51fd87fb7ba6 100644
--- a/drivers/clk/clk-gate.c
+++ b/drivers/clk/clk-gate.c
@@ -45,7 +45,7 @@ static void clk_gate_endisable(struct clk_hw *hw, int enable)
45{ 45{
46 struct clk_gate *gate = to_clk_gate(hw); 46 struct clk_gate *gate = to_clk_gate(hw);
47 int set = gate->flags & CLK_GATE_SET_TO_DISABLE ? 1 : 0; 47 int set = gate->flags & CLK_GATE_SET_TO_DISABLE ? 1 : 0;
48 unsigned long flags = 0; 48 unsigned long uninitialized_var(flags);
49 u32 reg; 49 u32 reg;
50 50
51 set ^= enable; 51 set ^= enable;
diff --git a/drivers/clk/clk-gpio-gate.c b/drivers/clk/clk-gpio-gate.c
new file mode 100644
index 000000000000..08e43224fd52
--- /dev/null
+++ b/drivers/clk/clk-gpio-gate.c
@@ -0,0 +1,205 @@
1/*
2 * Copyright (C) 2013 - 2014 Texas Instruments Incorporated - http://www.ti.com
3 * Author: Jyri Sarha <jsarha@ti.com>
4 *
5 * This program is free software; you can redistribute it and/or modify
6 * it under the terms of the GNU General Public License version 2 as
7 * published by the Free Software Foundation.
8 *
9 * Gpio gated clock implementation
10 */
11
12#include <linux/clk-provider.h>
13#include <linux/module.h>
14#include <linux/slab.h>
15#include <linux/gpio.h>
16#include <linux/gpio/consumer.h>
17#include <linux/of_gpio.h>
18#include <linux/err.h>
19#include <linux/device.h>
20
21/**
22 * DOC: basic gpio gated clock which can be enabled and disabled
23 * with gpio output
24 * Traits of this clock:
25 * prepare - clk_(un)prepare only ensures parent is (un)prepared
26 * enable - clk_enable and clk_disable are functional & control gpio
27 * rate - inherits rate from parent. No clk_set_rate support
28 * parent - fixed parent. No clk_set_parent support
29 */
30
31#define to_clk_gpio(_hw) container_of(_hw, struct clk_gpio, hw)
32
33static int clk_gpio_gate_enable(struct clk_hw *hw)
34{
35 struct clk_gpio *clk = to_clk_gpio(hw);
36
37 gpiod_set_value(clk->gpiod, 1);
38
39 return 0;
40}
41
42static void clk_gpio_gate_disable(struct clk_hw *hw)
43{
44 struct clk_gpio *clk = to_clk_gpio(hw);
45
46 gpiod_set_value(clk->gpiod, 0);
47}
48
49static int clk_gpio_gate_is_enabled(struct clk_hw *hw)
50{
51 struct clk_gpio *clk = to_clk_gpio(hw);
52
53 return gpiod_get_value(clk->gpiod);
54}
55
56const struct clk_ops clk_gpio_gate_ops = {
57 .enable = clk_gpio_gate_enable,
58 .disable = clk_gpio_gate_disable,
59 .is_enabled = clk_gpio_gate_is_enabled,
60};
61EXPORT_SYMBOL_GPL(clk_gpio_gate_ops);
62
63/**
64 * clk_register_gpio - register a gpip clock with the clock framework
65 * @dev: device that is registering this clock
66 * @name: name of this clock
67 * @parent_name: name of this clock's parent
68 * @gpiod: gpio descriptor to gate this clock
69 */
70struct clk *clk_register_gpio_gate(struct device *dev, const char *name,
71 const char *parent_name, struct gpio_desc *gpiod,
72 unsigned long flags)
73{
74 struct clk_gpio *clk_gpio = NULL;
75 struct clk *clk = ERR_PTR(-EINVAL);
76 struct clk_init_data init = { NULL };
77 unsigned long gpio_flags;
78 int err;
79
80 if (gpiod_is_active_low(gpiod))
81 gpio_flags = GPIOF_OUT_INIT_HIGH;
82 else
83 gpio_flags = GPIOF_OUT_INIT_LOW;
84
85 if (dev)
86 err = devm_gpio_request_one(dev, desc_to_gpio(gpiod),
87 gpio_flags, name);
88 else
89 err = gpio_request_one(desc_to_gpio(gpiod), gpio_flags, name);
90
91 if (err) {
92 pr_err("%s: %s: Error requesting clock control gpio %u\n",
93 __func__, name, desc_to_gpio(gpiod));
94 return ERR_PTR(err);
95 }
96
97 if (dev)
98 clk_gpio = devm_kzalloc(dev, sizeof(struct clk_gpio),
99 GFP_KERNEL);
100 else
101 clk_gpio = kzalloc(sizeof(struct clk_gpio), GFP_KERNEL);
102
103 if (!clk_gpio) {
104 clk = ERR_PTR(-ENOMEM);
105 goto clk_register_gpio_gate_err;
106 }
107
108 init.name = name;
109 init.ops = &clk_gpio_gate_ops;
110 init.flags = flags | CLK_IS_BASIC;
111 init.parent_names = (parent_name ? &parent_name : NULL);
112 init.num_parents = (parent_name ? 1 : 0);
113
114 clk_gpio->gpiod = gpiod;
115 clk_gpio->hw.init = &init;
116
117 clk = clk_register(dev, &clk_gpio->hw);
118
119 if (!IS_ERR(clk))
120 return clk;
121
122 if (!dev)
123 kfree(clk_gpio);
124
125clk_register_gpio_gate_err:
126 gpiod_put(gpiod);
127
128 return clk;
129}
130EXPORT_SYMBOL_GPL(clk_register_gpio_gate);
131
132#ifdef CONFIG_OF
133/**
134 * The clk_register_gpio_gate has to be delayed, because the EPROBE_DEFER
135 * can not be handled properly at of_clk_init() call time.
136 */
137
138struct clk_gpio_gate_delayed_register_data {
139 struct device_node *node;
140 struct mutex lock;
141 struct clk *clk;
142};
143
144static struct clk *of_clk_gpio_gate_delayed_register_get(
145 struct of_phandle_args *clkspec,
146 void *_data)
147{
148 struct clk_gpio_gate_delayed_register_data *data = _data;
149 struct clk *clk;
150 const char *clk_name = data->node->name;
151 const char *parent_name;
152 struct gpio_desc *gpiod;
153 int gpio;
154
155 mutex_lock(&data->lock);
156
157 if (data->clk) {
158 mutex_unlock(&data->lock);
159 return data->clk;
160 }
161
162 gpio = of_get_named_gpio_flags(data->node, "enable-gpios", 0, NULL);
163 if (gpio < 0) {
164 mutex_unlock(&data->lock);
165 if (gpio != -EPROBE_DEFER)
166 pr_err("%s: %s: Can't get 'enable-gpios' DT property\n",
167 __func__, clk_name);
168 return ERR_PTR(gpio);
169 }
170 gpiod = gpio_to_desc(gpio);
171
172 parent_name = of_clk_get_parent_name(data->node, 0);
173
174 clk = clk_register_gpio_gate(NULL, clk_name, parent_name, gpiod, 0);
175 if (IS_ERR(clk)) {
176 mutex_unlock(&data->lock);
177 return clk;
178 }
179
180 data->clk = clk;
181 mutex_unlock(&data->lock);
182
183 return clk;
184}
185
186/**
187 * of_gpio_gate_clk_setup() - Setup function for gpio controlled clock
188 */
189void __init of_gpio_gate_clk_setup(struct device_node *node)
190{
191 struct clk_gpio_gate_delayed_register_data *data;
192
193 data = kzalloc(sizeof(struct clk_gpio_gate_delayed_register_data),
194 GFP_KERNEL);
195 if (!data)
196 return;
197
198 data->node = node;
199 mutex_init(&data->lock);
200
201 of_clk_add_provider(node, of_clk_gpio_gate_delayed_register_get, data);
202}
203EXPORT_SYMBOL_GPL(of_gpio_gate_clk_setup);
204CLK_OF_DECLARE(gpio_gate_clk, "gpio-gate-clock", of_gpio_gate_clk_setup);
205#endif
diff --git a/drivers/clk/clk-max-gen.c b/drivers/clk/clk-max-gen.c
new file mode 100644
index 000000000000..6505049d50f1
--- /dev/null
+++ b/drivers/clk/clk-max-gen.c
@@ -0,0 +1,192 @@
1/*
2 * clk-max-gen.c - Generic clock driver for Maxim PMICs clocks
3 *
4 * Copyright (C) 2014 Google, Inc
5 *
6 * Copyright (C) 2012 Samsung Electornics
7 * Jonghwa Lee <jonghwa3.lee@samsung.com>
8 *
9 * This program is free software; you can redistribute it and/or modify it
10 * under the terms of the GNU General Public License as published by the
11 * Free Software Foundation; either version 2 of the License, or (at your
12 * option) any later version.
13 *
14 * This program is distributed in the hope that it will be useful,
15 * but WITHOUT ANY WARRANTY; without even the implied warranty of
16 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
17 * GNU General Public License for more details.
18 *
19 * This driver is based on clk-max77686.c
20 *
21 */
22
23#include <linux/kernel.h>
24#include <linux/slab.h>
25#include <linux/err.h>
26#include <linux/regmap.h>
27#include <linux/platform_device.h>
28#include <linux/clk-provider.h>
29#include <linux/mutex.h>
30#include <linux/clkdev.h>
31#include <linux/of.h>
32#include <linux/export.h>
33
34struct max_gen_clk {
35 struct regmap *regmap;
36 u32 mask;
37 u32 reg;
38 struct clk_hw hw;
39};
40
41static struct max_gen_clk *to_max_gen_clk(struct clk_hw *hw)
42{
43 return container_of(hw, struct max_gen_clk, hw);
44}
45
46static int max_gen_clk_prepare(struct clk_hw *hw)
47{
48 struct max_gen_clk *max_gen = to_max_gen_clk(hw);
49
50 return regmap_update_bits(max_gen->regmap, max_gen->reg,
51 max_gen->mask, max_gen->mask);
52}
53
54static void max_gen_clk_unprepare(struct clk_hw *hw)
55{
56 struct max_gen_clk *max_gen = to_max_gen_clk(hw);
57
58 regmap_update_bits(max_gen->regmap, max_gen->reg,
59 max_gen->mask, ~max_gen->mask);
60}
61
62static int max_gen_clk_is_prepared(struct clk_hw *hw)
63{
64 struct max_gen_clk *max_gen = to_max_gen_clk(hw);
65 int ret;
66 u32 val;
67
68 ret = regmap_read(max_gen->regmap, max_gen->reg, &val);
69
70 if (ret < 0)
71 return -EINVAL;
72
73 return val & max_gen->mask;
74}
75
76static unsigned long max_gen_recalc_rate(struct clk_hw *hw,
77 unsigned long parent_rate)
78{
79 return 32768;
80}
81
82struct clk_ops max_gen_clk_ops = {
83 .prepare = max_gen_clk_prepare,
84 .unprepare = max_gen_clk_unprepare,
85 .is_prepared = max_gen_clk_is_prepared,
86 .recalc_rate = max_gen_recalc_rate,
87};
88EXPORT_SYMBOL_GPL(max_gen_clk_ops);
89
90static struct clk *max_gen_clk_register(struct device *dev,
91 struct max_gen_clk *max_gen)
92{
93 struct clk *clk;
94 struct clk_hw *hw = &max_gen->hw;
95 int ret;
96
97 clk = devm_clk_register(dev, hw);
98 if (IS_ERR(clk))
99 return clk;
100
101 ret = clk_register_clkdev(clk, hw->init->name, NULL);
102
103 if (ret)
104 return ERR_PTR(ret);
105
106 return clk;
107}
108
109int max_gen_clk_probe(struct platform_device *pdev, struct regmap *regmap,
110 u32 reg, struct clk_init_data *clks_init, int num_init)
111{
112 int i, ret;
113 struct max_gen_clk *max_gen_clks;
114 struct clk **clocks;
115 struct device *dev = pdev->dev.parent;
116 const char *clk_name;
117 struct clk_init_data *init;
118
119 clocks = devm_kzalloc(dev, sizeof(struct clk *) * num_init, GFP_KERNEL);
120 if (!clocks)
121 return -ENOMEM;
122
123 max_gen_clks = devm_kzalloc(dev, sizeof(struct max_gen_clk)
124 * num_init, GFP_KERNEL);
125 if (!max_gen_clks)
126 return -ENOMEM;
127
128 for (i = 0; i < num_init; i++) {
129 max_gen_clks[i].regmap = regmap;
130 max_gen_clks[i].mask = 1 << i;
131 max_gen_clks[i].reg = reg;
132
133 init = devm_kzalloc(dev, sizeof(*init), GFP_KERNEL);
134 if (!init)
135 return -ENOMEM;
136
137 if (dev->of_node &&
138 !of_property_read_string_index(dev->of_node,
139 "clock-output-names",
140 i, &clk_name))
141 init->name = clk_name;
142 else
143 init->name = clks_init[i].name;
144
145 init->ops = clks_init[i].ops;
146 init->flags = clks_init[i].flags;
147
148 max_gen_clks[i].hw.init = init;
149
150 clocks[i] = max_gen_clk_register(dev, &max_gen_clks[i]);
151 if (IS_ERR(clocks[i])) {
152 ret = PTR_ERR(clocks[i]);
153 dev_err(dev, "failed to register %s\n",
154 max_gen_clks[i].hw.init->name);
155 return ret;
156 }
157 }
158
159 platform_set_drvdata(pdev, clocks);
160
161 if (dev->of_node) {
162 struct clk_onecell_data *of_data;
163
164 of_data = devm_kzalloc(dev, sizeof(*of_data), GFP_KERNEL);
165 if (!of_data)
166 return -ENOMEM;
167
168 of_data->clks = clocks;
169 of_data->clk_num = num_init;
170 ret = of_clk_add_provider(dev->of_node, of_clk_src_onecell_get,
171 of_data);
172
173 if (ret) {
174 dev_err(dev, "failed to register OF clock provider\n");
175 return ret;
176 }
177 }
178
179 return 0;
180}
181EXPORT_SYMBOL_GPL(max_gen_clk_probe);
182
183int max_gen_clk_remove(struct platform_device *pdev, int num_init)
184{
185 struct device *dev = pdev->dev.parent;
186
187 if (dev->of_node)
188 of_clk_del_provider(dev->of_node);
189
190 return 0;
191}
192EXPORT_SYMBOL_GPL(max_gen_clk_remove);
diff --git a/drivers/clk/clk-max-gen.h b/drivers/clk/clk-max-gen.h
new file mode 100644
index 000000000000..997e86fc3f4d
--- /dev/null
+++ b/drivers/clk/clk-max-gen.h
@@ -0,0 +1,32 @@
1/*
2 * clk-max-gen.h - Generic clock driver for Maxim PMICs clocks
3 *
4 * Copyright (C) 2014 Google, Inc
5 *
6 * This program is free software; you can redistribute it and/or modify it
7 * under the terms of the GNU General Public License as published by the
8 * Free Software Foundation; either version 2 of the License, or (at your
9 * option) any later version.
10 *
11 * This program is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 * GNU General Public License for more details.
15 *
16 */
17
18#ifndef __CLK_MAX_GEN_H__
19#define __CLK_MAX_GEN_H__
20
21#include <linux/types.h>
22#include <linux/device.h>
23#include <linux/clkdev.h>
24#include <linux/regmap.h>
25#include <linux/platform_device.h>
26
27int max_gen_clk_probe(struct platform_device *pdev, struct regmap *regmap,
28 u32 reg, struct clk_init_data *clks_init, int num_init);
29int max_gen_clk_remove(struct platform_device *pdev, int num_init);
30extern struct clk_ops max_gen_clk_ops;
31
32#endif /* __CLK_MAX_GEN_H__ */
diff --git a/drivers/clk/clk-max77686.c b/drivers/clk/clk-max77686.c
index 3d7e8dd8fd58..86cdb3a28629 100644
--- a/drivers/clk/clk-max77686.c
+++ b/drivers/clk/clk-max77686.c
@@ -30,193 +30,38 @@
30#include <linux/mutex.h> 30#include <linux/mutex.h>
31#include <linux/clkdev.h> 31#include <linux/clkdev.h>
32 32
33enum { 33#include <dt-bindings/clock/maxim,max77686.h>
34 MAX77686_CLK_AP = 0, 34#include "clk-max-gen.h"
35 MAX77686_CLK_CP,
36 MAX77686_CLK_PMIC,
37 MAX77686_CLKS_NUM,
38};
39
40struct max77686_clk {
41 struct max77686_dev *iodev;
42 u32 mask;
43 struct clk_hw hw;
44 struct clk_lookup *lookup;
45};
46
47static struct max77686_clk *to_max77686_clk(struct clk_hw *hw)
48{
49 return container_of(hw, struct max77686_clk, hw);
50}
51
52static int max77686_clk_prepare(struct clk_hw *hw)
53{
54 struct max77686_clk *max77686 = to_max77686_clk(hw);
55
56 return regmap_update_bits(max77686->iodev->regmap,
57 MAX77686_REG_32KHZ, max77686->mask,
58 max77686->mask);
59}
60
61static void max77686_clk_unprepare(struct clk_hw *hw)
62{
63 struct max77686_clk *max77686 = to_max77686_clk(hw);
64
65 regmap_update_bits(max77686->iodev->regmap,
66 MAX77686_REG_32KHZ, max77686->mask, ~max77686->mask);
67}
68
69static int max77686_clk_is_prepared(struct clk_hw *hw)
70{
71 struct max77686_clk *max77686 = to_max77686_clk(hw);
72 int ret;
73 u32 val;
74
75 ret = regmap_read(max77686->iodev->regmap,
76 MAX77686_REG_32KHZ, &val);
77
78 if (ret < 0)
79 return -EINVAL;
80
81 return val & max77686->mask;
82}
83
84static unsigned long max77686_recalc_rate(struct clk_hw *hw,
85 unsigned long parent_rate)
86{
87 return 32768;
88}
89
90static struct clk_ops max77686_clk_ops = {
91 .prepare = max77686_clk_prepare,
92 .unprepare = max77686_clk_unprepare,
93 .is_prepared = max77686_clk_is_prepared,
94 .recalc_rate = max77686_recalc_rate,
95};
96 35
97static struct clk_init_data max77686_clks_init[MAX77686_CLKS_NUM] = { 36static struct clk_init_data max77686_clks_init[MAX77686_CLKS_NUM] = {
98 [MAX77686_CLK_AP] = { 37 [MAX77686_CLK_AP] = {
99 .name = "32khz_ap", 38 .name = "32khz_ap",
100 .ops = &max77686_clk_ops, 39 .ops = &max_gen_clk_ops,
101 .flags = CLK_IS_ROOT, 40 .flags = CLK_IS_ROOT,
102 }, 41 },
103 [MAX77686_CLK_CP] = { 42 [MAX77686_CLK_CP] = {
104 .name = "32khz_cp", 43 .name = "32khz_cp",
105 .ops = &max77686_clk_ops, 44 .ops = &max_gen_clk_ops,
106 .flags = CLK_IS_ROOT, 45 .flags = CLK_IS_ROOT,
107 }, 46 },
108 [MAX77686_CLK_PMIC] = { 47 [MAX77686_CLK_PMIC] = {
109 .name = "32khz_pmic", 48 .name = "32khz_pmic",
110 .ops = &max77686_clk_ops, 49 .ops = &max_gen_clk_ops,
111 .flags = CLK_IS_ROOT, 50 .flags = CLK_IS_ROOT,
112 }, 51 },
113}; 52};
114 53
115static struct clk *max77686_clk_register(struct device *dev,
116 struct max77686_clk *max77686)
117{
118 struct clk *clk;
119 struct clk_hw *hw = &max77686->hw;
120
121 clk = clk_register(dev, hw);
122 if (IS_ERR(clk))
123 return clk;
124
125 max77686->lookup = kzalloc(sizeof(struct clk_lookup), GFP_KERNEL);
126 if (!max77686->lookup)
127 return ERR_PTR(-ENOMEM);
128
129 max77686->lookup->con_id = hw->init->name;
130 max77686->lookup->clk = clk;
131
132 clkdev_add(max77686->lookup);
133
134 return clk;
135}
136
137static int max77686_clk_probe(struct platform_device *pdev) 54static int max77686_clk_probe(struct platform_device *pdev)
138{ 55{
139 struct max77686_dev *iodev = dev_get_drvdata(pdev->dev.parent); 56 struct max77686_dev *iodev = dev_get_drvdata(pdev->dev.parent);
140 struct max77686_clk *max77686_clks[MAX77686_CLKS_NUM];
141 struct clk **clocks;
142 int i, ret;
143
144 clocks = devm_kzalloc(&pdev->dev, sizeof(struct clk *)
145 * MAX77686_CLKS_NUM, GFP_KERNEL);
146 if (!clocks)
147 return -ENOMEM;
148
149 for (i = 0; i < MAX77686_CLKS_NUM; i++) {
150 max77686_clks[i] = devm_kzalloc(&pdev->dev,
151 sizeof(struct max77686_clk), GFP_KERNEL);
152 if (!max77686_clks[i])
153 return -ENOMEM;
154 }
155
156 for (i = 0; i < MAX77686_CLKS_NUM; i++) {
157 max77686_clks[i]->iodev = iodev;
158 max77686_clks[i]->mask = 1 << i;
159 max77686_clks[i]->hw.init = &max77686_clks_init[i];
160
161 clocks[i] = max77686_clk_register(&pdev->dev, max77686_clks[i]);
162 if (IS_ERR(clocks[i])) {
163 ret = PTR_ERR(clocks[i]);
164 dev_err(&pdev->dev, "failed to register %s\n",
165 max77686_clks[i]->hw.init->name);
166 goto err_clocks;
167 }
168 }
169
170 platform_set_drvdata(pdev, clocks);
171
172 if (iodev->dev->of_node) {
173 struct clk_onecell_data *of_data;
174 57
175 of_data = devm_kzalloc(&pdev->dev, 58 return max_gen_clk_probe(pdev, iodev->regmap, MAX77686_REG_32KHZ,
176 sizeof(*of_data), GFP_KERNEL); 59 max77686_clks_init, MAX77686_CLKS_NUM);
177 if (!of_data) {
178 ret = -ENOMEM;
179 goto err_clocks;
180 }
181
182 of_data->clks = clocks;
183 of_data->clk_num = MAX77686_CLKS_NUM;
184 ret = of_clk_add_provider(iodev->dev->of_node,
185 of_clk_src_onecell_get, of_data);
186 if (ret) {
187 dev_err(&pdev->dev, "failed to register OF clock provider\n");
188 goto err_clocks;
189 }
190 }
191
192 return 0;
193
194err_clocks:
195 for (--i; i >= 0; --i) {
196 clkdev_drop(max77686_clks[i]->lookup);
197 clk_unregister(max77686_clks[i]->hw.clk);
198 }
199
200 return ret;
201} 60}
202 61
203static int max77686_clk_remove(struct platform_device *pdev) 62static int max77686_clk_remove(struct platform_device *pdev)
204{ 63{
205 struct max77686_dev *iodev = dev_get_drvdata(pdev->dev.parent); 64 return max_gen_clk_remove(pdev, MAX77686_CLKS_NUM);
206 struct clk **clocks = platform_get_drvdata(pdev);
207 int i;
208
209 if (iodev->dev->of_node)
210 of_clk_del_provider(iodev->dev->of_node);
211
212 for (i = 0; i < MAX77686_CLKS_NUM; i++) {
213 struct clk_hw *hw = __clk_get_hw(clocks[i]);
214 struct max77686_clk *max77686 = to_max77686_clk(hw);
215
216 clkdev_drop(max77686->lookup);
217 clk_unregister(clocks[i]);
218 }
219 return 0;
220} 65}
221 66
222static const struct platform_device_id max77686_clk_id[] = { 67static const struct platform_device_id max77686_clk_id[] = {
@@ -228,24 +73,13 @@ MODULE_DEVICE_TABLE(platform, max77686_clk_id);
228static struct platform_driver max77686_clk_driver = { 73static struct platform_driver max77686_clk_driver = {
229 .driver = { 74 .driver = {
230 .name = "max77686-clk", 75 .name = "max77686-clk",
231 .owner = THIS_MODULE,
232 }, 76 },
233 .probe = max77686_clk_probe, 77 .probe = max77686_clk_probe,
234 .remove = max77686_clk_remove, 78 .remove = max77686_clk_remove,
235 .id_table = max77686_clk_id, 79 .id_table = max77686_clk_id,
236}; 80};
237 81
238static int __init max77686_clk_init(void) 82module_platform_driver(max77686_clk_driver);
239{
240 return platform_driver_register(&max77686_clk_driver);
241}
242subsys_initcall(max77686_clk_init);
243
244static void __init max77686_clk_cleanup(void)
245{
246 platform_driver_unregister(&max77686_clk_driver);
247}
248module_exit(max77686_clk_cleanup);
249 83
250MODULE_DESCRIPTION("MAXIM 77686 Clock Driver"); 84MODULE_DESCRIPTION("MAXIM 77686 Clock Driver");
251MODULE_AUTHOR("Jonghwa Lee <jonghwa3.lee@samsung.com>"); 85MODULE_AUTHOR("Jonghwa Lee <jonghwa3.lee@samsung.com>");
diff --git a/drivers/clk/clk-max77802.c b/drivers/clk/clk-max77802.c
new file mode 100644
index 000000000000..0729dc723a8f
--- /dev/null
+++ b/drivers/clk/clk-max77802.c
@@ -0,0 +1,97 @@
1/*
2 * clk-max77802.c - Clock driver for Maxim 77802
3 *
4 * Copyright (C) 2014 Google, Inc
5 *
6 * Copyright (C) 2012 Samsung Electornics
7 * Jonghwa Lee <jonghwa3.lee@samsung.com>
8 *
9 * This program is free software; you can redistribute it and/or modify it
10 * under the terms of the GNU General Public License as published by the
11 * Free Software Foundation; either version 2 of the License, or (at your
12 * option) any later version.
13 *
14 * This program is distributed in the hope that it will be useful,
15 * but WITHOUT ANY WARRANTY; without even the implied warranty of
16 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
17 * GNU General Public License for more details.
18 *
19 * This driver is based on clk-max77686.c
20 */
21
22#include <linux/kernel.h>
23#include <linux/slab.h>
24#include <linux/err.h>
25#include <linux/platform_device.h>
26#include <linux/mfd/max77686-private.h>
27#include <linux/clk-provider.h>
28#include <linux/mutex.h>
29#include <linux/clkdev.h>
30
31#include <dt-bindings/clock/maxim,max77802.h>
32#include "clk-max-gen.h"
33
34#define MAX77802_CLOCK_OPMODE_MASK 0x1
35#define MAX77802_CLOCK_LOW_JITTER_SHIFT 0x3
36
37static struct clk_init_data max77802_clks_init[MAX77802_CLKS_NUM] = {
38 [MAX77802_CLK_32K_AP] = {
39 .name = "32khz_ap",
40 .ops = &max_gen_clk_ops,
41 .flags = CLK_IS_ROOT,
42 },
43 [MAX77802_CLK_32K_CP] = {
44 .name = "32khz_cp",
45 .ops = &max_gen_clk_ops,
46 .flags = CLK_IS_ROOT,
47 },
48};
49
50static int max77802_clk_probe(struct platform_device *pdev)
51{
52 struct max77686_dev *iodev = dev_get_drvdata(pdev->dev.parent);
53 int ret;
54
55 ret = max_gen_clk_probe(pdev, iodev->regmap, MAX77802_REG_32KHZ,
56 max77802_clks_init, MAX77802_CLKS_NUM);
57
58 if (ret) {
59 dev_err(&pdev->dev, "generic probe failed %d\n", ret);
60 return ret;
61 }
62
63 /* Enable low-jitter mode on the 32khz clocks. */
64 ret = regmap_update_bits(iodev->regmap, MAX77802_REG_32KHZ,
65 1 << MAX77802_CLOCK_LOW_JITTER_SHIFT,
66 1 << MAX77802_CLOCK_LOW_JITTER_SHIFT);
67 if (ret < 0)
68 dev_err(&pdev->dev, "failed to enable low-jitter mode\n");
69
70 return ret;
71}
72
73static int max77802_clk_remove(struct platform_device *pdev)
74{
75 return max_gen_clk_remove(pdev, MAX77802_CLKS_NUM);
76}
77
78static const struct platform_device_id max77802_clk_id[] = {
79 { "max77802-clk", 0},
80 { },
81};
82MODULE_DEVICE_TABLE(platform, max77802_clk_id);
83
84static struct platform_driver max77802_clk_driver = {
85 .driver = {
86 .name = "max77802-clk",
87 },
88 .probe = max77802_clk_probe,
89 .remove = max77802_clk_remove,
90 .id_table = max77802_clk_id,
91};
92
93module_platform_driver(max77802_clk_driver);
94
95MODULE_DESCRIPTION("MAXIM 77802 Clock Driver");
96MODULE_AUTHOR("Javier Martinez Canillas <javier.martinez@collabora.co.uk>");
97MODULE_LICENSE("GPL");
diff --git a/drivers/clk/clk-palmas.c b/drivers/clk/clk-palmas.c
index 781630e1372b..8d459923a15f 100644
--- a/drivers/clk/clk-palmas.c
+++ b/drivers/clk/clk-palmas.c
@@ -292,7 +292,6 @@ static int palmas_clks_remove(struct platform_device *pdev)
292static struct platform_driver palmas_clks_driver = { 292static struct platform_driver palmas_clks_driver = {
293 .driver = { 293 .driver = {
294 .name = "palmas-clk", 294 .name = "palmas-clk",
295 .owner = THIS_MODULE,
296 .of_match_table = palmas_clks_of_match, 295 .of_match_table = palmas_clks_of_match,
297 }, 296 },
298 .probe = palmas_clks_probe, 297 .probe = palmas_clks_probe,
diff --git a/drivers/clk/clk-twl6040.c b/drivers/clk/clk-twl6040.c
index 1ada79a28052..4a755135bcd3 100644
--- a/drivers/clk/clk-twl6040.c
+++ b/drivers/clk/clk-twl6040.c
@@ -112,7 +112,6 @@ static int twl6040_clk_remove(struct platform_device *pdev)
112static struct platform_driver twl6040_clk_driver = { 112static struct platform_driver twl6040_clk_driver = {
113 .driver = { 113 .driver = {
114 .name = "twl6040-clk", 114 .name = "twl6040-clk",
115 .owner = THIS_MODULE,
116 }, 115 },
117 .probe = twl6040_clk_probe, 116 .probe = twl6040_clk_probe,
118 .remove = twl6040_clk_remove, 117 .remove = twl6040_clk_remove,
diff --git a/drivers/clk/clk-wm831x.c b/drivers/clk/clk-wm831x.c
index b131041c8f48..ef67719f4e52 100644
--- a/drivers/clk/clk-wm831x.c
+++ b/drivers/clk/clk-wm831x.c
@@ -395,7 +395,6 @@ static struct platform_driver wm831x_clk_driver = {
395 .probe = wm831x_clk_probe, 395 .probe = wm831x_clk_probe,
396 .driver = { 396 .driver = {
397 .name = "wm831x-clk", 397 .name = "wm831x-clk",
398 .owner = THIS_MODULE,
399 }, 398 },
400}; 399};
401 400
diff --git a/drivers/clk/clk.c b/drivers/clk/clk.c
index bacc06ff939b..4896ae9e23da 100644
--- a/drivers/clk/clk.c
+++ b/drivers/clk/clk.c
@@ -100,6 +100,8 @@ static void clk_enable_unlock(unsigned long flags)
100 100
101static struct dentry *rootdir; 101static struct dentry *rootdir;
102static int inited = 0; 102static int inited = 0;
103static DEFINE_MUTEX(clk_debug_lock);
104static HLIST_HEAD(clk_debug_list);
103 105
104static struct hlist_head *all_lists[] = { 106static struct hlist_head *all_lists[] = {
105 &clk_root_list, 107 &clk_root_list,
@@ -117,11 +119,11 @@ static void clk_summary_show_one(struct seq_file *s, struct clk *c, int level)
117 if (!c) 119 if (!c)
118 return; 120 return;
119 121
120 seq_printf(s, "%*s%-*s %11d %12d %11lu %10lu\n", 122 seq_printf(s, "%*s%-*s %11d %12d %11lu %10lu %-3d\n",
121 level * 3 + 1, "", 123 level * 3 + 1, "",
122 30 - level * 3, c->name, 124 30 - level * 3, c->name,
123 c->enable_count, c->prepare_count, clk_get_rate(c), 125 c->enable_count, c->prepare_count, clk_get_rate(c),
124 clk_get_accuracy(c)); 126 clk_get_accuracy(c), clk_get_phase(c));
125} 127}
126 128
127static void clk_summary_show_subtree(struct seq_file *s, struct clk *c, 129static void clk_summary_show_subtree(struct seq_file *s, struct clk *c,
@@ -143,8 +145,8 @@ static int clk_summary_show(struct seq_file *s, void *data)
143 struct clk *c; 145 struct clk *c;
144 struct hlist_head **lists = (struct hlist_head **)s->private; 146 struct hlist_head **lists = (struct hlist_head **)s->private;
145 147
146 seq_puts(s, " clock enable_cnt prepare_cnt rate accuracy\n"); 148 seq_puts(s, " clock enable_cnt prepare_cnt rate accuracy phase\n");
147 seq_puts(s, "--------------------------------------------------------------------------------\n"); 149 seq_puts(s, "----------------------------------------------------------------------------------------\n");
148 150
149 clk_prepare_lock(); 151 clk_prepare_lock();
150 152
@@ -180,6 +182,7 @@ static void clk_dump_one(struct seq_file *s, struct clk *c, int level)
180 seq_printf(s, "\"prepare_count\": %d,", c->prepare_count); 182 seq_printf(s, "\"prepare_count\": %d,", c->prepare_count);
181 seq_printf(s, "\"rate\": %lu", clk_get_rate(c)); 183 seq_printf(s, "\"rate\": %lu", clk_get_rate(c));
182 seq_printf(s, "\"accuracy\": %lu", clk_get_accuracy(c)); 184 seq_printf(s, "\"accuracy\": %lu", clk_get_accuracy(c));
185 seq_printf(s, "\"phase\": %d", clk_get_phase(c));
183} 186}
184 187
185static void clk_dump_subtree(struct seq_file *s, struct clk *c, int level) 188static void clk_dump_subtree(struct seq_file *s, struct clk *c, int level)
@@ -264,6 +267,11 @@ static int clk_debug_create_one(struct clk *clk, struct dentry *pdentry)
264 if (!d) 267 if (!d)
265 goto err_out; 268 goto err_out;
266 269
270 d = debugfs_create_u32("clk_phase", S_IRUGO, clk->dentry,
271 (u32 *)&clk->phase);
272 if (!d)
273 goto err_out;
274
267 d = debugfs_create_x32("clk_flags", S_IRUGO, clk->dentry, 275 d = debugfs_create_x32("clk_flags", S_IRUGO, clk->dentry,
268 (u32 *)&clk->flags); 276 (u32 *)&clk->flags);
269 if (!d) 277 if (!d)
@@ -300,28 +308,6 @@ out:
300 return ret; 308 return ret;
301} 309}
302 310
303/* caller must hold prepare_lock */
304static int clk_debug_create_subtree(struct clk *clk, struct dentry *pdentry)
305{
306 struct clk *child;
307 int ret = -EINVAL;;
308
309 if (!clk || !pdentry)
310 goto out;
311
312 ret = clk_debug_create_one(clk, pdentry);
313
314 if (ret)
315 goto out;
316
317 hlist_for_each_entry(child, &clk->children, child_node)
318 clk_debug_create_subtree(child, pdentry);
319
320 ret = 0;
321out:
322 return ret;
323}
324
325/** 311/**
326 * clk_debug_register - add a clk node to the debugfs clk tree 312 * clk_debug_register - add a clk node to the debugfs clk tree
327 * @clk: the clk being added to the debugfs clk tree 313 * @clk: the clk being added to the debugfs clk tree
@@ -329,20 +315,21 @@ out:
329 * Dynamically adds a clk to the debugfs clk tree if debugfs has been 315 * Dynamically adds a clk to the debugfs clk tree if debugfs has been
330 * initialized. Otherwise it bails out early since the debugfs clk tree 316 * initialized. Otherwise it bails out early since the debugfs clk tree
331 * will be created lazily by clk_debug_init as part of a late_initcall. 317 * will be created lazily by clk_debug_init as part of a late_initcall.
332 *
333 * Caller must hold prepare_lock. Only clk_init calls this function (so
334 * far) so this is taken care.
335 */ 318 */
336static int clk_debug_register(struct clk *clk) 319static int clk_debug_register(struct clk *clk)
337{ 320{
338 int ret = 0; 321 int ret = 0;
339 322
323 mutex_lock(&clk_debug_lock);
324 hlist_add_head(&clk->debug_node, &clk_debug_list);
325
340 if (!inited) 326 if (!inited)
341 goto out; 327 goto unlock;
342 328
343 ret = clk_debug_create_subtree(clk, rootdir); 329 ret = clk_debug_create_one(clk, rootdir);
330unlock:
331 mutex_unlock(&clk_debug_lock);
344 332
345out:
346 return ret; 333 return ret;
347} 334}
348 335
@@ -353,12 +340,18 @@ out:
353 * Dynamically removes a clk and all it's children clk nodes from the 340 * Dynamically removes a clk and all it's children clk nodes from the
354 * debugfs clk tree if clk->dentry points to debugfs created by 341 * debugfs clk tree if clk->dentry points to debugfs created by
355 * clk_debug_register in __clk_init. 342 * clk_debug_register in __clk_init.
356 *
357 * Caller must hold prepare_lock.
358 */ 343 */
359static void clk_debug_unregister(struct clk *clk) 344static void clk_debug_unregister(struct clk *clk)
360{ 345{
346 mutex_lock(&clk_debug_lock);
347 if (!clk->dentry)
348 goto out;
349
350 hlist_del_init(&clk->debug_node);
361 debugfs_remove_recursive(clk->dentry); 351 debugfs_remove_recursive(clk->dentry);
352 clk->dentry = NULL;
353out:
354 mutex_unlock(&clk_debug_lock);
362} 355}
363 356
364struct dentry *clk_debugfs_add_file(struct clk *clk, char *name, umode_t mode, 357struct dentry *clk_debugfs_add_file(struct clk *clk, char *name, umode_t mode,
@@ -415,17 +408,12 @@ static int __init clk_debug_init(void)
415 if (!d) 408 if (!d)
416 return -ENOMEM; 409 return -ENOMEM;
417 410
418 clk_prepare_lock(); 411 mutex_lock(&clk_debug_lock);
419 412 hlist_for_each_entry(clk, &clk_debug_list, debug_node)
420 hlist_for_each_entry(clk, &clk_root_list, child_node) 413 clk_debug_create_one(clk, rootdir);
421 clk_debug_create_subtree(clk, rootdir);
422
423 hlist_for_each_entry(clk, &clk_orphan_list, child_node)
424 clk_debug_create_subtree(clk, rootdir);
425 414
426 inited = 1; 415 inited = 1;
427 416 mutex_unlock(&clk_debug_lock);
428 clk_prepare_unlock();
429 417
430 return 0; 418 return 0;
431} 419}
@@ -1744,6 +1732,77 @@ out:
1744EXPORT_SYMBOL_GPL(clk_set_parent); 1732EXPORT_SYMBOL_GPL(clk_set_parent);
1745 1733
1746/** 1734/**
1735 * clk_set_phase - adjust the phase shift of a clock signal
1736 * @clk: clock signal source
1737 * @degrees: number of degrees the signal is shifted
1738 *
1739 * Shifts the phase of a clock signal by the specified
1740 * degrees. Returns 0 on success, -EERROR otherwise.
1741 *
1742 * This function makes no distinction about the input or reference
1743 * signal that we adjust the clock signal phase against. For example
1744 * phase locked-loop clock signal generators we may shift phase with
1745 * respect to feedback clock signal input, but for other cases the
1746 * clock phase may be shifted with respect to some other, unspecified
1747 * signal.
1748 *
1749 * Additionally the concept of phase shift does not propagate through
1750 * the clock tree hierarchy, which sets it apart from clock rates and
1751 * clock accuracy. A parent clock phase attribute does not have an
1752 * impact on the phase attribute of a child clock.
1753 */
1754int clk_set_phase(struct clk *clk, int degrees)
1755{
1756 int ret = 0;
1757
1758 if (!clk)
1759 goto out;
1760
1761 /* sanity check degrees */
1762 degrees %= 360;
1763 if (degrees < 0)
1764 degrees += 360;
1765
1766 clk_prepare_lock();
1767
1768 if (!clk->ops->set_phase)
1769 goto out_unlock;
1770
1771 ret = clk->ops->set_phase(clk->hw, degrees);
1772
1773 if (!ret)
1774 clk->phase = degrees;
1775
1776out_unlock:
1777 clk_prepare_unlock();
1778
1779out:
1780 return ret;
1781}
1782
1783/**
1784 * clk_get_phase - return the phase shift of a clock signal
1785 * @clk: clock signal source
1786 *
1787 * Returns the phase shift of a clock node in degrees, otherwise returns
1788 * -EERROR.
1789 */
1790int clk_get_phase(struct clk *clk)
1791{
1792 int ret = 0;
1793
1794 if (!clk)
1795 goto out;
1796
1797 clk_prepare_lock();
1798 ret = clk->phase;
1799 clk_prepare_unlock();
1800
1801out:
1802 return ret;
1803}
1804
1805/**
1747 * __clk_init - initialize the data structures in a struct clk 1806 * __clk_init - initialize the data structures in a struct clk
1748 * @dev: device initializing this clk, placeholder for now 1807 * @dev: device initializing this clk, placeholder for now
1749 * @clk: clk being initialized 1808 * @clk: clk being initialized
@@ -1862,6 +1921,16 @@ int __clk_init(struct device *dev, struct clk *clk)
1862 clk->accuracy = 0; 1921 clk->accuracy = 0;
1863 1922
1864 /* 1923 /*
1924 * Set clk's phase.
1925 * Since a phase is by definition relative to its parent, just
1926 * query the current clock phase, or just assume it's in phase.
1927 */
1928 if (clk->ops->get_phase)
1929 clk->phase = clk->ops->get_phase(clk->hw);
1930 else
1931 clk->phase = 0;
1932
1933 /*
1865 * Set clk's rate. The preferred method is to use .recalc_rate. For 1934 * Set clk's rate. The preferred method is to use .recalc_rate. For
1866 * simple clocks and lazy developers the default fallback is to use the 1935 * simple clocks and lazy developers the default fallback is to use the
1867 * parent's rate. If a clock doesn't have a parent (or is orphaned) 1936 * parent's rate. If a clock doesn't have a parent (or is orphaned)
@@ -2092,14 +2161,16 @@ void clk_unregister(struct clk *clk)
2092{ 2161{
2093 unsigned long flags; 2162 unsigned long flags;
2094 2163
2095 if (!clk || WARN_ON_ONCE(IS_ERR(clk))) 2164 if (!clk || WARN_ON_ONCE(IS_ERR(clk)))
2096 return; 2165 return;
2166
2167 clk_debug_unregister(clk);
2097 2168
2098 clk_prepare_lock(); 2169 clk_prepare_lock();
2099 2170
2100 if (clk->ops == &clk_nodrv_ops) { 2171 if (clk->ops == &clk_nodrv_ops) {
2101 pr_err("%s: unregistered clock: %s\n", __func__, clk->name); 2172 pr_err("%s: unregistered clock: %s\n", __func__, clk->name);
2102 goto out; 2173 return;
2103 } 2174 }
2104 /* 2175 /*
2105 * Assign empty clock ops for consumers that might still hold 2176 * Assign empty clock ops for consumers that might still hold
@@ -2118,16 +2189,13 @@ void clk_unregister(struct clk *clk)
2118 clk_set_parent(child, NULL); 2189 clk_set_parent(child, NULL);
2119 } 2190 }
2120 2191
2121 clk_debug_unregister(clk);
2122
2123 hlist_del_init(&clk->child_node); 2192 hlist_del_init(&clk->child_node);
2124 2193
2125 if (clk->prepare_count) 2194 if (clk->prepare_count)
2126 pr_warn("%s: unregistering prepared clock: %s\n", 2195 pr_warn("%s: unregistering prepared clock: %s\n",
2127 __func__, clk->name); 2196 __func__, clk->name);
2128
2129 kref_put(&clk->ref, __clk_release); 2197 kref_put(&clk->ref, __clk_release);
2130out: 2198
2131 clk_prepare_unlock(); 2199 clk_prepare_unlock();
2132} 2200}
2133EXPORT_SYMBOL_GPL(clk_unregister); 2201EXPORT_SYMBOL_GPL(clk_unregister);
diff --git a/drivers/clk/hisilicon/clk-hix5hd2.c b/drivers/clk/hisilicon/clk-hix5hd2.c
index e5fcfb4e32ef..3f369c60fe56 100644
--- a/drivers/clk/hisilicon/clk-hix5hd2.c
+++ b/drivers/clk/hisilicon/clk-hix5hd2.c
@@ -9,6 +9,8 @@
9 9
10#include <linux/of_address.h> 10#include <linux/of_address.h>
11#include <dt-bindings/clock/hix5hd2-clock.h> 11#include <dt-bindings/clock/hix5hd2-clock.h>
12#include <linux/slab.h>
13#include <linux/delay.h>
12#include "clk.h" 14#include "clk.h"
13 15
14static struct hisi_fixed_rate_clock hix5hd2_fixed_rate_clks[] __initdata = { 16static struct hisi_fixed_rate_clock hix5hd2_fixed_rate_clks[] __initdata = {
@@ -48,9 +50,9 @@ static const char *sfc_mux_p[] __initconst = {
48 "24m", "150m", "200m", "100m", "75m", }; 50 "24m", "150m", "200m", "100m", "75m", };
49static u32 sfc_mux_table[] = {0, 4, 5, 6, 7}; 51static u32 sfc_mux_table[] = {0, 4, 5, 6, 7};
50 52
51static const char *sdio1_mux_p[] __initconst = { 53static const char *sdio_mux_p[] __initconst = {
52 "75m", "100m", "50m", "15m", }; 54 "75m", "100m", "50m", "15m", };
53static u32 sdio1_mux_table[] = {0, 1, 2, 3}; 55static u32 sdio_mux_table[] = {0, 1, 2, 3};
54 56
55static const char *fephy_mux_p[] __initconst = { "25m", "125m"}; 57static const char *fephy_mux_p[] __initconst = { "25m", "125m"};
56static u32 fephy_mux_table[] = {0, 1}; 58static u32 fephy_mux_table[] = {0, 1};
@@ -59,28 +61,243 @@ static u32 fephy_mux_table[] = {0, 1};
59static struct hisi_mux_clock hix5hd2_mux_clks[] __initdata = { 61static struct hisi_mux_clock hix5hd2_mux_clks[] __initdata = {
60 { HIX5HD2_SFC_MUX, "sfc_mux", sfc_mux_p, ARRAY_SIZE(sfc_mux_p), 62 { HIX5HD2_SFC_MUX, "sfc_mux", sfc_mux_p, ARRAY_SIZE(sfc_mux_p),
61 CLK_SET_RATE_PARENT, 0x5c, 8, 3, 0, sfc_mux_table, }, 63 CLK_SET_RATE_PARENT, 0x5c, 8, 3, 0, sfc_mux_table, },
62 { HIX5HD2_MMC_MUX, "mmc_mux", sdio1_mux_p, ARRAY_SIZE(sdio1_mux_p), 64 { HIX5HD2_MMC_MUX, "mmc_mux", sdio_mux_p, ARRAY_SIZE(sdio_mux_p),
63 CLK_SET_RATE_PARENT, 0xa0, 8, 2, 0, sdio1_mux_table, }, 65 CLK_SET_RATE_PARENT, 0xa0, 8, 2, 0, sdio_mux_table, },
66 { HIX5HD2_SD_MUX, "sd_mux", sdio_mux_p, ARRAY_SIZE(sdio_mux_p),
67 CLK_SET_RATE_PARENT, 0x9c, 8, 2, 0, sdio_mux_table, },
64 { HIX5HD2_FEPHY_MUX, "fephy_mux", 68 { HIX5HD2_FEPHY_MUX, "fephy_mux",
65 fephy_mux_p, ARRAY_SIZE(fephy_mux_p), 69 fephy_mux_p, ARRAY_SIZE(fephy_mux_p),
66 CLK_SET_RATE_PARENT, 0x120, 8, 2, 0, fephy_mux_table, }, 70 CLK_SET_RATE_PARENT, 0x120, 8, 2, 0, fephy_mux_table, },
67}; 71};
68 72
69static struct hisi_gate_clock hix5hd2_gate_clks[] __initdata = { 73static struct hisi_gate_clock hix5hd2_gate_clks[] __initdata = {
70 /*sfc*/ 74 /* sfc */
71 { HIX5HD2_SFC_CLK, "clk_sfc", "sfc_mux", 75 { HIX5HD2_SFC_CLK, "clk_sfc", "sfc_mux",
72 CLK_SET_RATE_PARENT, 0x5c, 0, 0, }, 76 CLK_SET_RATE_PARENT, 0x5c, 0, 0, },
73 { HIX5HD2_SFC_RST, "rst_sfc", "clk_sfc", 77 { HIX5HD2_SFC_RST, "rst_sfc", "clk_sfc",
74 CLK_SET_RATE_PARENT, 0x5c, 4, CLK_GATE_SET_TO_DISABLE, }, 78 CLK_SET_RATE_PARENT, 0x5c, 4, CLK_GATE_SET_TO_DISABLE, },
75 /*sdio1*/ 79 /* sdio0 */
80 { HIX5HD2_SD_BIU_CLK, "clk_sd_biu", "200m",
81 CLK_SET_RATE_PARENT, 0x9c, 0, 0, },
82 { HIX5HD2_SD_CIU_CLK, "clk_sd_ciu", "sd_mux",
83 CLK_SET_RATE_PARENT, 0x9c, 1, 0, },
84 { HIX5HD2_SD_CIU_RST, "rst_sd_ciu", "clk_sd_ciu",
85 CLK_SET_RATE_PARENT, 0x9c, 4, CLK_GATE_SET_TO_DISABLE, },
86 /* sdio1 */
76 { HIX5HD2_MMC_BIU_CLK, "clk_mmc_biu", "200m", 87 { HIX5HD2_MMC_BIU_CLK, "clk_mmc_biu", "200m",
77 CLK_SET_RATE_PARENT, 0xa0, 0, 0, }, 88 CLK_SET_RATE_PARENT, 0xa0, 0, 0, },
78 { HIX5HD2_MMC_CIU_CLK, "clk_mmc_ciu", "mmc_mux", 89 { HIX5HD2_MMC_CIU_CLK, "clk_mmc_ciu", "mmc_mux",
79 CLK_SET_RATE_PARENT, 0xa0, 1, 0, }, 90 CLK_SET_RATE_PARENT, 0xa0, 1, 0, },
80 { HIX5HD2_MMC_CIU_RST, "rst_mmc_ciu", "clk_mmc_ciu", 91 { HIX5HD2_MMC_CIU_RST, "rst_mmc_ciu", "clk_mmc_ciu",
81 CLK_SET_RATE_PARENT, 0xa0, 4, CLK_GATE_SET_TO_DISABLE, }, 92 CLK_SET_RATE_PARENT, 0xa0, 4, CLK_GATE_SET_TO_DISABLE, },
93 /* gsf */
94 { HIX5HD2_FWD_BUS_CLK, "clk_fwd_bus", NULL, 0, 0xcc, 0, 0, },
95 { HIX5HD2_FWD_SYS_CLK, "clk_fwd_sys", "clk_fwd_bus", 0, 0xcc, 5, 0, },
96 { HIX5HD2_MAC0_PHY_CLK, "clk_fephy", "clk_fwd_sys",
97 CLK_SET_RATE_PARENT, 0x120, 0, 0, },
98 /* wdg0 */
99 { HIX5HD2_WDG0_CLK, "clk_wdg0", "24m",
100 CLK_SET_RATE_PARENT, 0x178, 0, 0, },
101 { HIX5HD2_WDG0_RST, "rst_wdg0", "clk_wdg0",
102 CLK_SET_RATE_PARENT, 0x178, 4, CLK_GATE_SET_TO_DISABLE, },
103 /* I2C */
104 {HIX5HD2_I2C0_CLK, "clk_i2c0", "100m",
105 CLK_SET_RATE_PARENT, 0x06c, 4, 0, },
106 {HIX5HD2_I2C0_RST, "rst_i2c0", "clk_i2c0",
107 CLK_SET_RATE_PARENT, 0x06c, 5, CLK_GATE_SET_TO_DISABLE, },
108 {HIX5HD2_I2C1_CLK, "clk_i2c1", "100m",
109 CLK_SET_RATE_PARENT, 0x06c, 8, 0, },
110 {HIX5HD2_I2C1_RST, "rst_i2c1", "clk_i2c1",
111 CLK_SET_RATE_PARENT, 0x06c, 9, CLK_GATE_SET_TO_DISABLE, },
112 {HIX5HD2_I2C2_CLK, "clk_i2c2", "100m",
113 CLK_SET_RATE_PARENT, 0x06c, 12, 0, },
114 {HIX5HD2_I2C2_RST, "rst_i2c2", "clk_i2c2",
115 CLK_SET_RATE_PARENT, 0x06c, 13, CLK_GATE_SET_TO_DISABLE, },
116 {HIX5HD2_I2C3_CLK, "clk_i2c3", "100m",
117 CLK_SET_RATE_PARENT, 0x06c, 16, 0, },
118 {HIX5HD2_I2C3_RST, "rst_i2c3", "clk_i2c3",
119 CLK_SET_RATE_PARENT, 0x06c, 17, CLK_GATE_SET_TO_DISABLE, },
120 {HIX5HD2_I2C4_CLK, "clk_i2c4", "100m",
121 CLK_SET_RATE_PARENT, 0x06c, 20, 0, },
122 {HIX5HD2_I2C4_RST, "rst_i2c4", "clk_i2c4",
123 CLK_SET_RATE_PARENT, 0x06c, 21, CLK_GATE_SET_TO_DISABLE, },
124 {HIX5HD2_I2C5_CLK, "clk_i2c5", "100m",
125 CLK_SET_RATE_PARENT, 0x06c, 0, 0, },
126 {HIX5HD2_I2C5_RST, "rst_i2c5", "clk_i2c5",
127 CLK_SET_RATE_PARENT, 0x06c, 1, CLK_GATE_SET_TO_DISABLE, },
82}; 128};
83 129
130enum hix5hd2_clk_type {
131 TYPE_COMPLEX,
132 TYPE_ETHER,
133};
134
135struct hix5hd2_complex_clock {
136 const char *name;
137 const char *parent_name;
138 u32 id;
139 u32 ctrl_reg;
140 u32 ctrl_clk_mask;
141 u32 ctrl_rst_mask;
142 u32 phy_reg;
143 u32 phy_clk_mask;
144 u32 phy_rst_mask;
145 enum hix5hd2_clk_type type;
146};
147
148struct hix5hd2_clk_complex {
149 struct clk_hw hw;
150 u32 id;
151 void __iomem *ctrl_reg;
152 u32 ctrl_clk_mask;
153 u32 ctrl_rst_mask;
154 void __iomem *phy_reg;
155 u32 phy_clk_mask;
156 u32 phy_rst_mask;
157};
158
159static struct hix5hd2_complex_clock hix5hd2_complex_clks[] __initdata = {
160 {"clk_mac0", "clk_fephy", HIX5HD2_MAC0_CLK,
161 0xcc, 0xa, 0x500, 0x120, 0, 0x10, TYPE_ETHER},
162 {"clk_mac1", "clk_fwd_sys", HIX5HD2_MAC1_CLK,
163 0xcc, 0x14, 0xa00, 0x168, 0x2, 0, TYPE_ETHER},
164 {"clk_sata", NULL, HIX5HD2_SATA_CLK,
165 0xa8, 0x1f, 0x300, 0xac, 0x1, 0x0, TYPE_COMPLEX},
166 {"clk_usb", NULL, HIX5HD2_USB_CLK,
167 0xb8, 0xff, 0x3f000, 0xbc, 0x7, 0x3f00, TYPE_COMPLEX},
168};
169
170#define to_complex_clk(_hw) container_of(_hw, struct hix5hd2_clk_complex, hw)
171
172static int clk_ether_prepare(struct clk_hw *hw)
173{
174 struct hix5hd2_clk_complex *clk = to_complex_clk(hw);
175 u32 val;
176
177 val = readl_relaxed(clk->ctrl_reg);
178 val |= clk->ctrl_clk_mask | clk->ctrl_rst_mask;
179 writel_relaxed(val, clk->ctrl_reg);
180 val &= ~(clk->ctrl_rst_mask);
181 writel_relaxed(val, clk->ctrl_reg);
182
183 val = readl_relaxed(clk->phy_reg);
184 val |= clk->phy_clk_mask;
185 val &= ~(clk->phy_rst_mask);
186 writel_relaxed(val, clk->phy_reg);
187 mdelay(10);
188
189 val &= ~(clk->phy_clk_mask);
190 val |= clk->phy_rst_mask;
191 writel_relaxed(val, clk->phy_reg);
192 mdelay(10);
193
194 val |= clk->phy_clk_mask;
195 val &= ~(clk->phy_rst_mask);
196 writel_relaxed(val, clk->phy_reg);
197 mdelay(30);
198 return 0;
199}
200
201static void clk_ether_unprepare(struct clk_hw *hw)
202{
203 struct hix5hd2_clk_complex *clk = to_complex_clk(hw);
204 u32 val;
205
206 val = readl_relaxed(clk->ctrl_reg);
207 val &= ~(clk->ctrl_clk_mask);
208 writel_relaxed(val, clk->ctrl_reg);
209}
210
211static struct clk_ops clk_ether_ops = {
212 .prepare = clk_ether_prepare,
213 .unprepare = clk_ether_unprepare,
214};
215
216static int clk_complex_enable(struct clk_hw *hw)
217{
218 struct hix5hd2_clk_complex *clk = to_complex_clk(hw);
219 u32 val;
220
221 val = readl_relaxed(clk->ctrl_reg);
222 val |= clk->ctrl_clk_mask;
223 val &= ~(clk->ctrl_rst_mask);
224 writel_relaxed(val, clk->ctrl_reg);
225
226 val = readl_relaxed(clk->phy_reg);
227 val |= clk->phy_clk_mask;
228 val &= ~(clk->phy_rst_mask);
229 writel_relaxed(val, clk->phy_reg);
230
231 return 0;
232}
233
234static void clk_complex_disable(struct clk_hw *hw)
235{
236 struct hix5hd2_clk_complex *clk = to_complex_clk(hw);
237 u32 val;
238
239 val = readl_relaxed(clk->ctrl_reg);
240 val |= clk->ctrl_rst_mask;
241 val &= ~(clk->ctrl_clk_mask);
242 writel_relaxed(val, clk->ctrl_reg);
243
244 val = readl_relaxed(clk->phy_reg);
245 val |= clk->phy_rst_mask;
246 val &= ~(clk->phy_clk_mask);
247 writel_relaxed(val, clk->phy_reg);
248}
249
250static struct clk_ops clk_complex_ops = {
251 .enable = clk_complex_enable,
252 .disable = clk_complex_disable,
253};
254
255void __init hix5hd2_clk_register_complex(struct hix5hd2_complex_clock *clks,
256 int nums, struct hisi_clock_data *data)
257{
258 void __iomem *base = data->base;
259 int i;
260
261 for (i = 0; i < nums; i++) {
262 struct hix5hd2_clk_complex *p_clk;
263 struct clk *clk;
264 struct clk_init_data init;
265
266 p_clk = kzalloc(sizeof(*p_clk), GFP_KERNEL);
267 if (!p_clk)
268 return;
269
270 init.name = clks[i].name;
271 if (clks[i].type == TYPE_ETHER)
272 init.ops = &clk_ether_ops;
273 else
274 init.ops = &clk_complex_ops;
275
276 init.flags = CLK_IS_BASIC;
277 init.parent_names =
278 (clks[i].parent_name ? &clks[i].parent_name : NULL);
279 init.num_parents = (clks[i].parent_name ? 1 : 0);
280
281 p_clk->ctrl_reg = base + clks[i].ctrl_reg;
282 p_clk->ctrl_clk_mask = clks[i].ctrl_clk_mask;
283 p_clk->ctrl_rst_mask = clks[i].ctrl_rst_mask;
284 p_clk->phy_reg = base + clks[i].phy_reg;
285 p_clk->phy_clk_mask = clks[i].phy_clk_mask;
286 p_clk->phy_rst_mask = clks[i].phy_rst_mask;
287 p_clk->hw.init = &init;
288
289 clk = clk_register(NULL, &p_clk->hw);
290 if (IS_ERR(clk)) {
291 kfree(p_clk);
292 pr_err("%s: failed to register clock %s\n",
293 __func__, clks[i].name);
294 continue;
295 }
296
297 data->clk_data.clks[clks[i].id] = clk;
298 }
299}
300
84static void __init hix5hd2_clk_init(struct device_node *np) 301static void __init hix5hd2_clk_init(struct device_node *np)
85{ 302{
86 struct hisi_clock_data *clk_data; 303 struct hisi_clock_data *clk_data;
@@ -96,6 +313,9 @@ static void __init hix5hd2_clk_init(struct device_node *np)
96 clk_data); 313 clk_data);
97 hisi_clk_register_gate(hix5hd2_gate_clks, 314 hisi_clk_register_gate(hix5hd2_gate_clks,
98 ARRAY_SIZE(hix5hd2_gate_clks), clk_data); 315 ARRAY_SIZE(hix5hd2_gate_clks), clk_data);
316 hix5hd2_clk_register_complex(hix5hd2_complex_clks,
317 ARRAY_SIZE(hix5hd2_complex_clks),
318 clk_data);
99} 319}
100 320
101CLK_OF_DECLARE(hix5hd2_clk, "hisilicon,hix5hd2-clock", hix5hd2_clk_init); 321CLK_OF_DECLARE(hix5hd2_clk, "hisilicon,hix5hd2-clock", hix5hd2_clk_init);
diff --git a/drivers/clk/mvebu/armada-370.c b/drivers/clk/mvebu/armada-370.c
index bef198a83863..756f0f39d6a3 100644
--- a/drivers/clk/mvebu/armada-370.c
+++ b/drivers/clk/mvebu/armada-370.c
@@ -23,6 +23,7 @@
23 */ 23 */
24 24
25#define SARL 0 /* Low part [0:31] */ 25#define SARL 0 /* Low part [0:31] */
26#define SARL_A370_SSCG_ENABLE BIT(10)
26#define SARL_A370_PCLK_FREQ_OPT 11 27#define SARL_A370_PCLK_FREQ_OPT 11
27#define SARL_A370_PCLK_FREQ_OPT_MASK 0xF 28#define SARL_A370_PCLK_FREQ_OPT_MASK 0xF
28#define SARL_A370_FAB_FREQ_OPT 15 29#define SARL_A370_FAB_FREQ_OPT 15
@@ -133,10 +134,17 @@ static void __init a370_get_clk_ratio(
133 } 134 }
134} 135}
135 136
137static bool a370_is_sscg_enabled(void __iomem *sar)
138{
139 return !(readl(sar) & SARL_A370_SSCG_ENABLE);
140}
141
136static const struct coreclk_soc_desc a370_coreclks = { 142static const struct coreclk_soc_desc a370_coreclks = {
137 .get_tclk_freq = a370_get_tclk_freq, 143 .get_tclk_freq = a370_get_tclk_freq,
138 .get_cpu_freq = a370_get_cpu_freq, 144 .get_cpu_freq = a370_get_cpu_freq,
139 .get_clk_ratio = a370_get_clk_ratio, 145 .get_clk_ratio = a370_get_clk_ratio,
146 .is_sscg_enabled = a370_is_sscg_enabled,
147 .fix_sscg_deviation = kirkwood_fix_sscg_deviation,
140 .ratios = a370_coreclk_ratios, 148 .ratios = a370_coreclk_ratios,
141 .num_ratios = ARRAY_SIZE(a370_coreclk_ratios), 149 .num_ratios = ARRAY_SIZE(a370_coreclk_ratios),
142}; 150};
diff --git a/drivers/clk/mvebu/armada-375.c b/drivers/clk/mvebu/armada-375.c
index c991a4d95e10..c7af2242b796 100644
--- a/drivers/clk/mvebu/armada-375.c
+++ b/drivers/clk/mvebu/armada-375.c
@@ -27,14 +27,14 @@
27 * all modified at the same time, and not separately as for the Armada 27 * all modified at the same time, and not separately as for the Armada
28 * 370 or the Armada XP SoCs. 28 * 370 or the Armada XP SoCs.
29 * 29 *
30 * SAR0[21:17] : CPU frequency DDR frequency L2 frequency 30 * SAR1[21:17] : CPU frequency DDR frequency L2 frequency
31 * 6 = 400 MHz 400 MHz 200 MHz 31 * 6 = 400 MHz 400 MHz 200 MHz
32 * 15 = 600 MHz 600 MHz 300 MHz 32 * 15 = 600 MHz 600 MHz 300 MHz
33 * 21 = 800 MHz 534 MHz 400 MHz 33 * 21 = 800 MHz 534 MHz 400 MHz
34 * 25 = 1000 MHz 500 MHz 500 MHz 34 * 25 = 1000 MHz 500 MHz 500 MHz
35 * others reserved. 35 * others reserved.
36 * 36 *
37 * SAR0[22] : TCLK frequency 37 * SAR1[22] : TCLK frequency
38 * 0 = 166 MHz 38 * 0 = 166 MHz
39 * 1 = 200 MHz 39 * 1 = 200 MHz
40 */ 40 */
diff --git a/drivers/clk/mvebu/common.c b/drivers/clk/mvebu/common.c
index 25ceccf939ad..b7fcb469c87a 100644
--- a/drivers/clk/mvebu/common.c
+++ b/drivers/clk/mvebu/common.c
@@ -26,8 +26,85 @@
26 * Core Clocks 26 * Core Clocks
27 */ 27 */
28 28
29#define SSCG_CONF_MODE(reg) (((reg) >> 16) & 0x3)
30#define SSCG_SPREAD_DOWN 0x0
31#define SSCG_SPREAD_UP 0x1
32#define SSCG_SPREAD_CENTRAL 0x2
33#define SSCG_CONF_LOW(reg) (((reg) >> 8) & 0xFF)
34#define SSCG_CONF_HIGH(reg) ((reg) & 0xFF)
35
29static struct clk_onecell_data clk_data; 36static struct clk_onecell_data clk_data;
30 37
38/*
39 * This function can be used by the Kirkwood, the Armada 370, the
40 * Armada XP and the Armada 375 SoC. The name of the function was
41 * chosen following the dt convention: using the first known SoC
42 * compatible with it.
43 */
44u32 kirkwood_fix_sscg_deviation(u32 system_clk)
45{
46 struct device_node *sscg_np = NULL;
47 void __iomem *sscg_map;
48 u32 sscg_reg;
49 s32 low_bound, high_bound;
50 u64 freq_swing_half;
51
52 sscg_np = of_find_node_by_name(NULL, "sscg");
53 if (sscg_np == NULL) {
54 pr_err("cannot get SSCG register node\n");
55 return system_clk;
56 }
57
58 sscg_map = of_iomap(sscg_np, 0);
59 if (sscg_map == NULL) {
60 pr_err("cannot map SSCG register\n");
61 goto out;
62 }
63
64 sscg_reg = readl(sscg_map);
65 high_bound = SSCG_CONF_HIGH(sscg_reg);
66 low_bound = SSCG_CONF_LOW(sscg_reg);
67
68 if ((high_bound - low_bound) <= 0)
69 goto out;
70 /*
71 * From Marvell engineer we got the following formula (when
72 * this code was written, the datasheet was erroneous)
73 * Spread percentage = 1/96 * (H - L) / H
74 * H = SSCG_High_Boundary
75 * L = SSCG_Low_Boundary
76 *
77 * As the deviation is half of spread then it lead to the
78 * following formula in the code.
79 *
80 * To avoid an overflow and not lose any significant digit in
81 * the same time we have to use a 64 bit integer.
82 */
83
84 freq_swing_half = (((u64)high_bound - (u64)low_bound)
85 * (u64)system_clk);
86 do_div(freq_swing_half, (2 * 96 * high_bound));
87
88 switch (SSCG_CONF_MODE(sscg_reg)) {
89 case SSCG_SPREAD_DOWN:
90 system_clk -= freq_swing_half;
91 break;
92 case SSCG_SPREAD_UP:
93 system_clk += freq_swing_half;
94 break;
95 case SSCG_SPREAD_CENTRAL:
96 default:
97 break;
98 }
99
100 iounmap(sscg_map);
101
102out:
103 of_node_put(sscg_np);
104
105 return system_clk;
106}
107
31void __init mvebu_coreclk_setup(struct device_node *np, 108void __init mvebu_coreclk_setup(struct device_node *np,
32 const struct coreclk_soc_desc *desc) 109 const struct coreclk_soc_desc *desc)
33{ 110{
@@ -62,6 +139,11 @@ void __init mvebu_coreclk_setup(struct device_node *np,
62 of_property_read_string_index(np, "clock-output-names", 1, 139 of_property_read_string_index(np, "clock-output-names", 1,
63 &cpuclk_name); 140 &cpuclk_name);
64 rate = desc->get_cpu_freq(base); 141 rate = desc->get_cpu_freq(base);
142
143 if (desc->is_sscg_enabled && desc->fix_sscg_deviation
144 && desc->is_sscg_enabled(base))
145 rate = desc->fix_sscg_deviation(rate);
146
65 clk_data.clks[1] = clk_register_fixed_rate(NULL, cpuclk_name, NULL, 147 clk_data.clks[1] = clk_register_fixed_rate(NULL, cpuclk_name, NULL,
66 CLK_IS_ROOT, rate); 148 CLK_IS_ROOT, rate);
67 WARN_ON(IS_ERR(clk_data.clks[1])); 149 WARN_ON(IS_ERR(clk_data.clks[1]));
@@ -89,8 +171,10 @@ void __init mvebu_coreclk_setup(struct device_node *np,
89 * Clock Gating Control 171 * Clock Gating Control
90 */ 172 */
91 173
174DEFINE_SPINLOCK(ctrl_gating_lock);
175
92struct clk_gating_ctrl { 176struct clk_gating_ctrl {
93 spinlock_t lock; 177 spinlock_t *lock;
94 struct clk **gates; 178 struct clk **gates;
95 int num_gates; 179 int num_gates;
96}; 180};
@@ -138,7 +222,8 @@ void __init mvebu_clk_gating_setup(struct device_node *np,
138 if (WARN_ON(!ctrl)) 222 if (WARN_ON(!ctrl))
139 goto ctrl_out; 223 goto ctrl_out;
140 224
141 spin_lock_init(&ctrl->lock); 225 /* lock must already be initialized */
226 ctrl->lock = &ctrl_gating_lock;
142 227
143 /* Count, allocate, and register clock gates */ 228 /* Count, allocate, and register clock gates */
144 for (n = 0; desc[n].name;) 229 for (n = 0; desc[n].name;)
@@ -155,7 +240,7 @@ void __init mvebu_clk_gating_setup(struct device_node *np,
155 (desc[n].parent) ? desc[n].parent : default_parent; 240 (desc[n].parent) ? desc[n].parent : default_parent;
156 ctrl->gates[n] = clk_register_gate(NULL, desc[n].name, parent, 241 ctrl->gates[n] = clk_register_gate(NULL, desc[n].name, parent,
157 desc[n].flags, base, desc[n].bit_idx, 242 desc[n].flags, base, desc[n].bit_idx,
158 0, &ctrl->lock); 243 0, ctrl->lock);
159 WARN_ON(IS_ERR(ctrl->gates[n])); 244 WARN_ON(IS_ERR(ctrl->gates[n]));
160 } 245 }
161 246
diff --git a/drivers/clk/mvebu/common.h b/drivers/clk/mvebu/common.h
index f968b4d9df92..783b5631a453 100644
--- a/drivers/clk/mvebu/common.h
+++ b/drivers/clk/mvebu/common.h
@@ -17,6 +17,8 @@
17 17
18#include <linux/kernel.h> 18#include <linux/kernel.h>
19 19
20extern spinlock_t ctrl_gating_lock;
21
20struct device_node; 22struct device_node;
21 23
22struct coreclk_ratio { 24struct coreclk_ratio {
@@ -28,6 +30,8 @@ struct coreclk_soc_desc {
28 u32 (*get_tclk_freq)(void __iomem *sar); 30 u32 (*get_tclk_freq)(void __iomem *sar);
29 u32 (*get_cpu_freq)(void __iomem *sar); 31 u32 (*get_cpu_freq)(void __iomem *sar);
30 void (*get_clk_ratio)(void __iomem *sar, int id, int *mult, int *div); 32 void (*get_clk_ratio)(void __iomem *sar, int id, int *mult, int *div);
33 bool (*is_sscg_enabled)(void __iomem *sar);
34 u32 (*fix_sscg_deviation)(u32 system_clk);
31 const struct coreclk_ratio *ratios; 35 const struct coreclk_ratio *ratios;
32 int num_ratios; 36 int num_ratios;
33}; 37};
@@ -45,4 +49,9 @@ void __init mvebu_coreclk_setup(struct device_node *np,
45void __init mvebu_clk_gating_setup(struct device_node *np, 49void __init mvebu_clk_gating_setup(struct device_node *np,
46 const struct clk_gating_soc_desc *desc); 50 const struct clk_gating_soc_desc *desc);
47 51
52/*
53 * This function is shared among the Kirkwood, Armada 370, Armada XP
54 * and Armada 375 SoC
55 */
56u32 kirkwood_fix_sscg_deviation(u32 system_clk);
48#endif 57#endif
diff --git a/drivers/clk/mvebu/kirkwood.c b/drivers/clk/mvebu/kirkwood.c
index ddb666a86500..99550f25975e 100644
--- a/drivers/clk/mvebu/kirkwood.c
+++ b/drivers/clk/mvebu/kirkwood.c
@@ -13,9 +13,11 @@
13 */ 13 */
14 14
15#include <linux/kernel.h> 15#include <linux/kernel.h>
16#include <linux/slab.h>
16#include <linux/clk-provider.h> 17#include <linux/clk-provider.h>
17#include <linux/io.h> 18#include <linux/io.h>
18#include <linux/of.h> 19#include <linux/of.h>
20#include <linux/of_address.h>
19#include "common.h" 21#include "common.h"
20 22
21/* 23/*
@@ -214,7 +216,6 @@ static const struct clk_gating_soc_desc kirkwood_gating_desc[] __initconst = {
214 { "runit", NULL, 7, 0 }, 216 { "runit", NULL, 7, 0 },
215 { "xor0", NULL, 8, 0 }, 217 { "xor0", NULL, 8, 0 },
216 { "audio", NULL, 9, 0 }, 218 { "audio", NULL, 9, 0 },
217 { "powersave", "cpuclk", 11, 0 },
218 { "sata0", NULL, 14, 0 }, 219 { "sata0", NULL, 14, 0 },
219 { "sata1", NULL, 15, 0 }, 220 { "sata1", NULL, 15, 0 },
220 { "xor1", NULL, 16, 0 }, 221 { "xor1", NULL, 16, 0 },
@@ -225,6 +226,101 @@ static const struct clk_gating_soc_desc kirkwood_gating_desc[] __initconst = {
225 { } 226 { }
226}; 227};
227 228
229
230/*
231 * Clock Muxing Control
232 */
233
234struct clk_muxing_soc_desc {
235 const char *name;
236 const char **parents;
237 int num_parents;
238 int shift;
239 int width;
240 unsigned long flags;
241};
242
243struct clk_muxing_ctrl {
244 spinlock_t *lock;
245 struct clk **muxes;
246 int num_muxes;
247};
248
249static const char *powersave_parents[] = {
250 "cpuclk",
251 "ddrclk",
252};
253
254static const struct clk_muxing_soc_desc kirkwood_mux_desc[] __initconst = {
255 { "powersave", powersave_parents, ARRAY_SIZE(powersave_parents),
256 11, 1, 0 },
257};
258
259#define to_clk_mux(_hw) container_of(_hw, struct clk_mux, hw)
260
261static struct clk *clk_muxing_get_src(
262 struct of_phandle_args *clkspec, void *data)
263{
264 struct clk_muxing_ctrl *ctrl = (struct clk_muxing_ctrl *)data;
265 int n;
266
267 if (clkspec->args_count < 1)
268 return ERR_PTR(-EINVAL);
269
270 for (n = 0; n < ctrl->num_muxes; n++) {
271 struct clk_mux *mux =
272 to_clk_mux(__clk_get_hw(ctrl->muxes[n]));
273 if (clkspec->args[0] == mux->shift)
274 return ctrl->muxes[n];
275 }
276 return ERR_PTR(-ENODEV);
277}
278
279static void __init kirkwood_clk_muxing_setup(struct device_node *np,
280 const struct clk_muxing_soc_desc *desc)
281{
282 struct clk_muxing_ctrl *ctrl;
283 void __iomem *base;
284 int n;
285
286 base = of_iomap(np, 0);
287 if (WARN_ON(!base))
288 return;
289
290 ctrl = kzalloc(sizeof(*ctrl), GFP_KERNEL);
291 if (WARN_ON(!ctrl))
292 goto ctrl_out;
293
294 /* lock must already be initialized */
295 ctrl->lock = &ctrl_gating_lock;
296
297 /* Count, allocate, and register clock muxes */
298 for (n = 0; desc[n].name;)
299 n++;
300
301 ctrl->num_muxes = n;
302 ctrl->muxes = kcalloc(ctrl->num_muxes, sizeof(struct clk *),
303 GFP_KERNEL);
304 if (WARN_ON(!ctrl->muxes))
305 goto muxes_out;
306
307 for (n = 0; n < ctrl->num_muxes; n++) {
308 ctrl->muxes[n] = clk_register_mux(NULL, desc[n].name,
309 desc[n].parents, desc[n].num_parents,
310 desc[n].flags, base, desc[n].shift,
311 desc[n].width, desc[n].flags, ctrl->lock);
312 WARN_ON(IS_ERR(ctrl->muxes[n]));
313 }
314
315 of_clk_add_provider(np, clk_muxing_get_src, ctrl);
316
317 return;
318muxes_out:
319 kfree(ctrl);
320ctrl_out:
321 iounmap(base);
322}
323
228static void __init kirkwood_clk_init(struct device_node *np) 324static void __init kirkwood_clk_init(struct device_node *np)
229{ 325{
230 struct device_node *cgnp = 326 struct device_node *cgnp =
@@ -236,8 +332,10 @@ static void __init kirkwood_clk_init(struct device_node *np)
236 else 332 else
237 mvebu_coreclk_setup(np, &kirkwood_coreclks); 333 mvebu_coreclk_setup(np, &kirkwood_coreclks);
238 334
239 if (cgnp) 335 if (cgnp) {
240 mvebu_clk_gating_setup(cgnp, kirkwood_gating_desc); 336 mvebu_clk_gating_setup(cgnp, kirkwood_gating_desc);
337 kirkwood_clk_muxing_setup(cgnp, kirkwood_mux_desc);
338 }
241} 339}
242CLK_OF_DECLARE(kirkwood_clk, "marvell,kirkwood-core-clock", 340CLK_OF_DECLARE(kirkwood_clk, "marvell,kirkwood-core-clock",
243 kirkwood_clk_init); 341 kirkwood_clk_init);
diff --git a/drivers/clk/pxa/Makefile b/drivers/clk/pxa/Makefile
new file mode 100644
index 000000000000..4ff2abcd500b
--- /dev/null
+++ b/drivers/clk/pxa/Makefile
@@ -0,0 +1,2 @@
1obj-y += clk-pxa.o
2obj-$(CONFIG_PXA27x) += clk-pxa27x.o
diff --git a/drivers/clk/pxa/clk-pxa.c b/drivers/clk/pxa/clk-pxa.c
new file mode 100644
index 000000000000..ef3c05389c0a
--- /dev/null
+++ b/drivers/clk/pxa/clk-pxa.c
@@ -0,0 +1,97 @@
1/*
2 * Marvell PXA family clocks
3 *
4 * Copyright (C) 2014 Robert Jarzmik
5 *
6 * Common clock code for PXA clocks ("CKEN" type clocks + DT)
7 *
8 * This program is free software; you can redistribute it and/or modify
9 * it under the terms of the GNU General Public License as published by
10 * the Free Software Foundation; version 2 of the License.
11 *
12 */
13#include <linux/clk.h>
14#include <linux/clk-provider.h>
15#include <linux/clkdev.h>
16#include <linux/of.h>
17
18#include <dt-bindings/clock/pxa-clock.h>
19#include "clk-pxa.h"
20
21DEFINE_SPINLOCK(lock);
22
23static struct clk *pxa_clocks[CLK_MAX];
24static struct clk_onecell_data onecell_data = {
25 .clks = pxa_clocks,
26 .clk_num = CLK_MAX,
27};
28
29#define to_pxa_clk(_hw) container_of(_hw, struct pxa_clk_cken, hw)
30
31static unsigned long cken_recalc_rate(struct clk_hw *hw,
32 unsigned long parent_rate)
33{
34 struct pxa_clk_cken *pclk = to_pxa_clk(hw);
35 struct clk_fixed_factor *fix;
36
37 if (!pclk->is_in_low_power || pclk->is_in_low_power())
38 fix = &pclk->lp;
39 else
40 fix = &pclk->hp;
41 fix->hw.clk = hw->clk;
42 return clk_fixed_factor_ops.recalc_rate(&fix->hw, parent_rate);
43}
44
45static struct clk_ops cken_rate_ops = {
46 .recalc_rate = cken_recalc_rate,
47};
48
49static u8 cken_get_parent(struct clk_hw *hw)
50{
51 struct pxa_clk_cken *pclk = to_pxa_clk(hw);
52
53 if (!pclk->is_in_low_power)
54 return 0;
55 return pclk->is_in_low_power() ? 0 : 1;
56}
57
58static struct clk_ops cken_mux_ops = {
59 .get_parent = cken_get_parent,
60 .set_parent = dummy_clk_set_parent,
61};
62
63void __init clkdev_pxa_register(int ckid, const char *con_id,
64 const char *dev_id, struct clk *clk)
65{
66 if (!IS_ERR(clk) && (ckid != CLK_NONE))
67 pxa_clocks[ckid] = clk;
68 if (!IS_ERR(clk))
69 clk_register_clkdev(clk, con_id, dev_id);
70}
71
72int __init clk_pxa_cken_init(struct pxa_clk_cken *clks, int nb_clks)
73{
74 int i;
75 struct pxa_clk_cken *pclk;
76 struct clk *clk;
77
78 for (i = 0; i < nb_clks; i++) {
79 pclk = clks + i;
80 pclk->gate.lock = &lock;
81 clk = clk_register_composite(NULL, pclk->name,
82 pclk->parent_names, 2,
83 &pclk->hw, &cken_mux_ops,
84 &pclk->hw, &cken_rate_ops,
85 &pclk->gate.hw, &clk_gate_ops,
86 pclk->flags);
87 clkdev_pxa_register(pclk->ckid, pclk->con_id, pclk->dev_id,
88 clk);
89 }
90 return 0;
91}
92
93static void __init pxa_dt_clocks_init(struct device_node *np)
94{
95 of_clk_add_provider(np, of_clk_src_onecell_get, &onecell_data);
96}
97CLK_OF_DECLARE(pxa_clks, "marvell,pxa-clocks", pxa_dt_clocks_init);
diff --git a/drivers/clk/pxa/clk-pxa.h b/drivers/clk/pxa/clk-pxa.h
new file mode 100644
index 000000000000..5fe219d06b49
--- /dev/null
+++ b/drivers/clk/pxa/clk-pxa.h
@@ -0,0 +1,107 @@
1/*
2 * Marvell PXA family clocks
3 *
4 * Copyright (C) 2014 Robert Jarzmik
5 *
6 * Common clock code for PXA clocks ("CKEN" type clocks + DT)
7 *
8 * This program is free software; you can redistribute it and/or modify
9 * it under the terms of the GNU General Public License as published by
10 * the Free Software Foundation; version 2 of the License.
11 *
12 */
13#ifndef _CLK_PXA_
14#define _CLK_PXA_
15
16#define PARENTS(name) \
17 static const char *name ## _parents[] __initconst
18#define MUX_RO_RATE_RO_OPS(name, clk_name) \
19 static struct clk_hw name ## _mux_hw; \
20 static struct clk_hw name ## _rate_hw; \
21 static struct clk_ops name ## _mux_ops = { \
22 .get_parent = name ## _get_parent, \
23 .set_parent = dummy_clk_set_parent, \
24 }; \
25 static struct clk_ops name ## _rate_ops = { \
26 .recalc_rate = name ## _get_rate, \
27 }; \
28 static struct clk *clk_register_ ## name(void) \
29 { \
30 return clk_register_composite(NULL, clk_name, \
31 name ## _parents, \
32 ARRAY_SIZE(name ## _parents), \
33 &name ## _mux_hw, &name ## _mux_ops, \
34 &name ## _rate_hw, &name ## _rate_ops, \
35 NULL, NULL, CLK_GET_RATE_NOCACHE); \
36 }
37
38#define RATE_RO_OPS(name, clk_name) \
39 static struct clk_hw name ## _rate_hw; \
40 static struct clk_ops name ## _rate_ops = { \
41 .recalc_rate = name ## _get_rate, \
42 }; \
43 static struct clk *clk_register_ ## name(void) \
44 { \
45 return clk_register_composite(NULL, clk_name, \
46 name ## _parents, \
47 ARRAY_SIZE(name ## _parents), \
48 NULL, NULL, \
49 &name ## _rate_hw, &name ## _rate_ops, \
50 NULL, NULL, CLK_GET_RATE_NOCACHE); \
51 }
52
53/*
54 * CKEN clock type
55 * This clock takes it source from 2 possible parents :
56 * - a low power parent
57 * - a normal parent
58 *
59 * +------------+ +-----------+
60 * | Low Power | --- | x mult_lp |
61 * | Clock | | / div_lp |\
62 * +------------+ +-----------+ \+-----+ +-----------+
63 * | Mux |---| CKEN gate |
64 * +------------+ +-----------+ /+-----+ +-----------+
65 * | High Power | | x mult_hp |/
66 * | Clock | --- | / div_hp |
67 * +------------+ +-----------+
68 */
69struct pxa_clk_cken {
70 struct clk_hw hw;
71 int ckid;
72 const char *name;
73 const char *dev_id;
74 const char *con_id;
75 const char **parent_names;
76 struct clk_fixed_factor lp;
77 struct clk_fixed_factor hp;
78 struct clk_gate gate;
79 bool (*is_in_low_power)(void);
80 const unsigned long flags;
81};
82
83#define PXA_CKEN(_dev_id, _con_id, _name, parents, _mult_lp, _div_lp, \
84 _mult_hp, _div_hp, is_lp, _cken_reg, _cken_bit, flag) \
85 { .ckid = CLK_ ## _name, .name = #_name, \
86 .dev_id = _dev_id, .con_id = _con_id, .parent_names = parents,\
87 .lp = { .mult = _mult_lp, .div = _div_lp }, \
88 .hp = { .mult = _mult_hp, .div = _div_hp }, \
89 .is_in_low_power = is_lp, \
90 .gate = { .reg = (void __iomem *)_cken_reg, .bit_idx = _cken_bit }, \
91 .flags = flag, \
92 }
93#define PXA_CKEN_1RATE(dev_id, con_id, name, parents, cken_reg, \
94 cken_bit, flag) \
95 PXA_CKEN(dev_id, con_id, name, parents, 1, 1, 1, 1, \
96 NULL, cken_reg, cken_bit, flag)
97
98static int dummy_clk_set_parent(struct clk_hw *hw, u8 index)
99{
100 return 0;
101}
102
103extern void clkdev_pxa_register(int ckid, const char *con_id,
104 const char *dev_id, struct clk *clk);
105extern int clk_pxa_cken_init(struct pxa_clk_cken *clks, int nb_clks);
106
107#endif
diff --git a/drivers/clk/pxa/clk-pxa27x.c b/drivers/clk/pxa/clk-pxa27x.c
new file mode 100644
index 000000000000..b345cc791e5d
--- /dev/null
+++ b/drivers/clk/pxa/clk-pxa27x.c
@@ -0,0 +1,370 @@
1/*
2 * Marvell PXA27x family clocks
3 *
4 * Copyright (C) 2014 Robert Jarzmik
5 *
6 * Heavily inspired from former arch/arm/mach-pxa/clock.c.
7 *
8 * This program is free software; you can redistribute it and/or modify
9 * it under the terms of the GNU General Public License as published by
10 * the Free Software Foundation; version 2 of the License.
11 *
12 */
13#include <linux/clk-provider.h>
14#include <mach/pxa2xx-regs.h>
15#include <linux/io.h>
16#include <linux/clk.h>
17#include <linux/clkdev.h>
18#include <linux/of.h>
19
20#include <dt-bindings/clock/pxa-clock.h>
21#include "clk-pxa.h"
22
23#define KHz 1000
24#define MHz (1000 * 1000)
25
26enum {
27 PXA_CORE_13Mhz = 0,
28 PXA_CORE_RUN,
29 PXA_CORE_TURBO,
30};
31
32enum {
33 PXA_BUS_13Mhz = 0,
34 PXA_BUS_RUN,
35};
36
37enum {
38 PXA_LCD_13Mhz = 0,
39 PXA_LCD_RUN,
40};
41
42enum {
43 PXA_MEM_13Mhz = 0,
44 PXA_MEM_SYSTEM_BUS,
45 PXA_MEM_RUN,
46};
47
48static const char * const get_freq_khz[] = {
49 "core", "run", "cpll", "memory",
50 "system_bus"
51};
52
53/*
54 * Get the clock frequency as reflected by CCSR and the turbo flag.
55 * We assume these values have been applied via a fcs.
56 * If info is not 0 we also display the current settings.
57 */
58unsigned int pxa27x_get_clk_frequency_khz(int info)
59{
60 struct clk *clk;
61 unsigned long clks[5];
62 int i;
63
64 for (i = 0; i < 5; i++) {
65 clk = clk_get(NULL, get_freq_khz[i]);
66 if (IS_ERR(clk)) {
67 clks[i] = 0;
68 } else {
69 clks[i] = clk_get_rate(clk);
70 clk_put(clk);
71 }
72 }
73 if (info) {
74 pr_info("Run Mode clock: %ld.%02ldMHz\n",
75 clks[1] / 1000000, (clks[1] % 1000000) / 10000);
76 pr_info("Turbo Mode clock: %ld.%02ldMHz\n",
77 clks[2] / 1000000, (clks[2] % 1000000) / 10000);
78 pr_info("Memory clock: %ld.%02ldMHz\n",
79 clks[3] / 1000000, (clks[3] % 1000000) / 10000);
80 pr_info("System bus clock: %ld.%02ldMHz\n",
81 clks[4] / 1000000, (clks[4] % 1000000) / 10000);
82 }
83 return (unsigned int)clks[0];
84}
85
86bool pxa27x_is_ppll_disabled(void)
87{
88 unsigned long ccsr = CCSR;
89
90 return ccsr & (1 << CCCR_PPDIS_BIT);
91}
92
93#define PXA27X_CKEN(dev_id, con_id, parents, mult_hp, div_hp, \
94 bit, is_lp, flags) \
95 PXA_CKEN(dev_id, con_id, bit, parents, 1, 1, mult_hp, div_hp, \
96 is_lp, &CKEN, CKEN_ ## bit, flags)
97#define PXA27X_PBUS_CKEN(dev_id, con_id, bit, mult_hp, div_hp, delay) \
98 PXA27X_CKEN(dev_id, con_id, pxa27x_pbus_parents, mult_hp, \
99 div_hp, bit, pxa27x_is_ppll_disabled, 0)
100
101PARENTS(pxa27x_pbus) = { "osc_13mhz", "ppll_312mhz" };
102PARENTS(pxa27x_sbus) = { "system_bus", "system_bus" };
103PARENTS(pxa27x_32Mhz_bus) = { "osc_32_768khz", "osc_32_768khz" };
104PARENTS(pxa27x_lcd_bus) = { "lcd_base", "lcd_base" };
105PARENTS(pxa27x_membus) = { "lcd_base", "lcd_base" };
106
107#define PXA27X_CKEN_1RATE(dev_id, con_id, bit, parents, delay) \
108 PXA_CKEN_1RATE(dev_id, con_id, bit, parents, \
109 &CKEN, CKEN_ ## bit, 0)
110#define PXA27X_CKEN_1RATE_AO(dev_id, con_id, bit, parents, delay) \
111 PXA_CKEN_1RATE(dev_id, con_id, bit, parents, \
112 &CKEN, CKEN_ ## bit, CLK_IGNORE_UNUSED)
113
114static struct pxa_clk_cken pxa27x_clocks[] = {
115 PXA27X_PBUS_CKEN("pxa2xx-uart.0", NULL, FFUART, 2, 42, 1),
116 PXA27X_PBUS_CKEN("pxa2xx-uart.1", NULL, BTUART, 2, 42, 1),
117 PXA27X_PBUS_CKEN("pxa2xx-uart.2", NULL, STUART, 2, 42, 1),
118 PXA27X_PBUS_CKEN("pxa2xx-i2s", NULL, I2S, 2, 51, 0),
119 PXA27X_PBUS_CKEN("pxa2xx-i2c.0", NULL, I2C, 2, 19, 0),
120 PXA27X_PBUS_CKEN("pxa27x-udc", NULL, USB, 2, 13, 5),
121 PXA27X_PBUS_CKEN("pxa2xx-mci.0", NULL, MMC, 2, 32, 0),
122 PXA27X_PBUS_CKEN("pxa2xx-ir", "FICPCLK", FICP, 2, 13, 0),
123 PXA27X_PBUS_CKEN("pxa27x-ohci", NULL, USBHOST, 2, 13, 0),
124 PXA27X_PBUS_CKEN("pxa2xx-i2c.1", NULL, PWRI2C, 1, 24, 0),
125 PXA27X_PBUS_CKEN("pxa27x-ssp.0", NULL, SSP1, 1, 24, 0),
126 PXA27X_PBUS_CKEN("pxa27x-ssp.1", NULL, SSP2, 1, 24, 0),
127 PXA27X_PBUS_CKEN("pxa27x-ssp.2", NULL, SSP3, 1, 24, 0),
128 PXA27X_PBUS_CKEN("pxa27x-pwm.0", NULL, PWM0, 1, 24, 0),
129 PXA27X_PBUS_CKEN("pxa27x-pwm.1", NULL, PWM1, 1, 24, 0),
130 PXA27X_PBUS_CKEN(NULL, "MSLCLK", MSL, 2, 13, 0),
131 PXA27X_PBUS_CKEN(NULL, "USIMCLK", USIM, 2, 13, 0),
132 PXA27X_PBUS_CKEN(NULL, "MSTKCLK", MEMSTK, 2, 32, 0),
133 PXA27X_PBUS_CKEN(NULL, "AC97CLK", AC97, 1, 1, 0),
134 PXA27X_PBUS_CKEN(NULL, "AC97CONFCLK", AC97CONF, 1, 1, 0),
135 PXA27X_PBUS_CKEN(NULL, "OSTIMER0", OSTIMER, 1, 96, 0),
136
137 PXA27X_CKEN_1RATE("pxa27x-keypad", NULL, KEYPAD,
138 pxa27x_32Mhz_bus_parents, 0),
139 PXA27X_CKEN_1RATE(NULL, "IMCLK", IM, pxa27x_sbus_parents, 0),
140 PXA27X_CKEN_1RATE("pxa2xx-fb", NULL, LCD, pxa27x_lcd_bus_parents, 0),
141 PXA27X_CKEN_1RATE("pxa27x-camera.0", NULL, CAMERA,
142 pxa27x_lcd_bus_parents, 0),
143 PXA27X_CKEN_1RATE_AO("pxa2xx-pcmcia", NULL, MEMC,
144 pxa27x_membus_parents, 0),
145
146};
147
148static unsigned long clk_pxa27x_cpll_get_rate(struct clk_hw *hw,
149 unsigned long parent_rate)
150{
151 unsigned long clkcfg;
152 unsigned int t, ht;
153 unsigned int l, L, n2, N;
154 unsigned long ccsr = CCSR;
155
156 asm("mrc\tp14, 0, %0, c6, c0, 0" : "=r" (clkcfg));
157 t = clkcfg & (1 << 0);
158 ht = clkcfg & (1 << 2);
159
160 l = ccsr & CCSR_L_MASK;
161 n2 = (ccsr & CCSR_N2_MASK) >> CCSR_N2_SHIFT;
162 L = l * parent_rate;
163 N = (L * n2) / 2;
164
165 return t ? N : L;
166}
167PARENTS(clk_pxa27x_cpll) = { "osc_13mhz" };
168RATE_RO_OPS(clk_pxa27x_cpll, "cpll");
169
170static unsigned long clk_pxa27x_lcd_base_get_rate(struct clk_hw *hw,
171 unsigned long parent_rate)
172{
173 unsigned int l, osc_forced;
174 unsigned long ccsr = CCSR;
175 unsigned long cccr = CCCR;
176
177 l = ccsr & CCSR_L_MASK;
178 osc_forced = ccsr & (1 << CCCR_CPDIS_BIT);
179 if (osc_forced) {
180 if (cccr & (1 << CCCR_LCD_26_BIT))
181 return parent_rate * 2;
182 else
183 return parent_rate;
184 }
185
186 if (l <= 7)
187 return parent_rate;
188 if (l <= 16)
189 return parent_rate / 2;
190 return parent_rate / 4;
191}
192
193static u8 clk_pxa27x_lcd_base_get_parent(struct clk_hw *hw)
194{
195 unsigned int osc_forced;
196 unsigned long ccsr = CCSR;
197
198 osc_forced = ccsr & (1 << CCCR_CPDIS_BIT);
199 if (osc_forced)
200 return PXA_LCD_13Mhz;
201 else
202 return PXA_LCD_RUN;
203}
204
205PARENTS(clk_pxa27x_lcd_base) = { "osc_13mhz", "run" };
206MUX_RO_RATE_RO_OPS(clk_pxa27x_lcd_base, "lcd_base");
207
208static void __init pxa27x_register_plls(void)
209{
210 clk_register_fixed_rate(NULL, "osc_13mhz", NULL,
211 CLK_GET_RATE_NOCACHE | CLK_IS_ROOT,
212 13 * MHz);
213 clk_register_fixed_rate(NULL, "osc_32_768khz", NULL,
214 CLK_GET_RATE_NOCACHE | CLK_IS_ROOT,
215 32768 * KHz);
216 clk_register_fixed_rate(NULL, "clk_dummy", NULL, CLK_IS_ROOT, 0);
217 clk_register_fixed_factor(NULL, "ppll_312mhz", "osc_13mhz", 0, 24, 1);
218}
219
220static unsigned long clk_pxa27x_core_get_rate(struct clk_hw *hw,
221 unsigned long parent_rate)
222{
223 unsigned long clkcfg;
224 unsigned int t, ht, b, osc_forced;
225 unsigned long ccsr = CCSR;
226
227 osc_forced = ccsr & (1 << CCCR_CPDIS_BIT);
228 asm("mrc\tp14, 0, %0, c6, c0, 0" : "=r" (clkcfg));
229 t = clkcfg & (1 << 0);
230 ht = clkcfg & (1 << 2);
231 b = clkcfg & (1 << 3);
232
233 if (osc_forced)
234 return parent_rate;
235 if (ht)
236 return parent_rate / 2;
237 else
238 return parent_rate;
239}
240
241static u8 clk_pxa27x_core_get_parent(struct clk_hw *hw)
242{
243 unsigned long clkcfg;
244 unsigned int t, ht, b, osc_forced;
245 unsigned long ccsr = CCSR;
246
247 osc_forced = ccsr & (1 << CCCR_CPDIS_BIT);
248 if (osc_forced)
249 return PXA_CORE_13Mhz;
250
251 asm("mrc\tp14, 0, %0, c6, c0, 0" : "=r" (clkcfg));
252 t = clkcfg & (1 << 0);
253 ht = clkcfg & (1 << 2);
254 b = clkcfg & (1 << 3);
255
256 if (ht || t)
257 return PXA_CORE_TURBO;
258 return PXA_CORE_RUN;
259}
260PARENTS(clk_pxa27x_core) = { "osc_13mhz", "run", "cpll" };
261MUX_RO_RATE_RO_OPS(clk_pxa27x_core, "core");
262
263static unsigned long clk_pxa27x_run_get_rate(struct clk_hw *hw,
264 unsigned long parent_rate)
265{
266 unsigned long ccsr = CCSR;
267 unsigned int n2 = (ccsr & CCSR_N2_MASK) >> CCSR_N2_SHIFT;
268
269 return (parent_rate / n2) * 2;
270}
271PARENTS(clk_pxa27x_run) = { "cpll" };
272RATE_RO_OPS(clk_pxa27x_run, "run");
273
274static void __init pxa27x_register_core(void)
275{
276 clk_register_clk_pxa27x_cpll();
277 clk_register_clk_pxa27x_run();
278
279 clkdev_pxa_register(CLK_CORE, "core", NULL,
280 clk_register_clk_pxa27x_core());
281}
282
283static unsigned long clk_pxa27x_system_bus_get_rate(struct clk_hw *hw,
284 unsigned long parent_rate)
285{
286 unsigned long clkcfg;
287 unsigned int b, osc_forced;
288 unsigned long ccsr = CCSR;
289
290 osc_forced = ccsr & (1 << CCCR_CPDIS_BIT);
291 asm("mrc\tp14, 0, %0, c6, c0, 0" : "=r" (clkcfg));
292 b = clkcfg & (1 << 3);
293
294 if (osc_forced)
295 return parent_rate;
296 if (b)
297 return parent_rate / 2;
298 else
299 return parent_rate;
300}
301
302static u8 clk_pxa27x_system_bus_get_parent(struct clk_hw *hw)
303{
304 unsigned int osc_forced;
305 unsigned long ccsr = CCSR;
306
307 osc_forced = ccsr & (1 << CCCR_CPDIS_BIT);
308 if (osc_forced)
309 return PXA_BUS_13Mhz;
310 else
311 return PXA_BUS_RUN;
312}
313
314PARENTS(clk_pxa27x_system_bus) = { "osc_13mhz", "run" };
315MUX_RO_RATE_RO_OPS(clk_pxa27x_system_bus, "system_bus");
316
317static unsigned long clk_pxa27x_memory_get_rate(struct clk_hw *hw,
318 unsigned long parent_rate)
319{
320 unsigned int a, l, osc_forced;
321 unsigned long cccr = CCCR;
322 unsigned long ccsr = CCSR;
323
324 osc_forced = ccsr & (1 << CCCR_CPDIS_BIT);
325 a = cccr & CCCR_A_BIT;
326 l = ccsr & CCSR_L_MASK;
327
328 if (osc_forced || a)
329 return parent_rate;
330 if (l <= 10)
331 return parent_rate;
332 if (l <= 20)
333 return parent_rate / 2;
334 return parent_rate / 4;
335}
336
337static u8 clk_pxa27x_memory_get_parent(struct clk_hw *hw)
338{
339 unsigned int osc_forced, a;
340 unsigned long cccr = CCCR;
341 unsigned long ccsr = CCSR;
342
343 osc_forced = ccsr & (1 << CCCR_CPDIS_BIT);
344 a = cccr & CCCR_A_BIT;
345 if (osc_forced)
346 return PXA_MEM_13Mhz;
347 if (a)
348 return PXA_MEM_SYSTEM_BUS;
349 else
350 return PXA_MEM_RUN;
351}
352
353PARENTS(clk_pxa27x_memory) = { "osc_13mhz", "system_bus", "run" };
354MUX_RO_RATE_RO_OPS(clk_pxa27x_memory, "memory");
355
356static void __init pxa27x_base_clocks_init(void)
357{
358 pxa27x_register_plls();
359 pxa27x_register_core();
360 clk_register_clk_pxa27x_system_bus();
361 clk_register_clk_pxa27x_memory();
362 clk_register_clk_pxa27x_lcd_base();
363}
364
365static int __init pxa27x_clocks_init(void)
366{
367 pxa27x_base_clocks_init();
368 return clk_pxa_cken_init(pxa27x_clocks, ARRAY_SIZE(pxa27x_clocks));
369}
370postcore_initcall(pxa27x_clocks_init);
diff --git a/drivers/clk/qcom/clk-pll.c b/drivers/clk/qcom/clk-pll.c
index 9db03d3b1657..b823bc3b6250 100644
--- a/drivers/clk/qcom/clk-pll.c
+++ b/drivers/clk/qcom/clk-pll.c
@@ -97,7 +97,7 @@ static unsigned long
97clk_pll_recalc_rate(struct clk_hw *hw, unsigned long parent_rate) 97clk_pll_recalc_rate(struct clk_hw *hw, unsigned long parent_rate)
98{ 98{
99 struct clk_pll *pll = to_clk_pll(hw); 99 struct clk_pll *pll = to_clk_pll(hw);
100 u32 l, m, n; 100 u32 l, m, n, config;
101 unsigned long rate; 101 unsigned long rate;
102 u64 tmp; 102 u64 tmp;
103 103
@@ -116,13 +116,79 @@ clk_pll_recalc_rate(struct clk_hw *hw, unsigned long parent_rate)
116 do_div(tmp, n); 116 do_div(tmp, n);
117 rate += tmp; 117 rate += tmp;
118 } 118 }
119 if (pll->post_div_width) {
120 regmap_read(pll->clkr.regmap, pll->config_reg, &config);
121 config >>= pll->post_div_shift;
122 config &= BIT(pll->post_div_width) - 1;
123 rate /= config + 1;
124 }
125
119 return rate; 126 return rate;
120} 127}
121 128
129static const
130struct pll_freq_tbl *find_freq(const struct pll_freq_tbl *f, unsigned long rate)
131{
132 if (!f)
133 return NULL;
134
135 for (; f->freq; f++)
136 if (rate <= f->freq)
137 return f;
138
139 return NULL;
140}
141
142static long
143clk_pll_determine_rate(struct clk_hw *hw, unsigned long rate,
144 unsigned long *p_rate, struct clk **p)
145{
146 struct clk_pll *pll = to_clk_pll(hw);
147 const struct pll_freq_tbl *f;
148
149 f = find_freq(pll->freq_tbl, rate);
150 if (!f)
151 return clk_pll_recalc_rate(hw, *p_rate);
152
153 return f->freq;
154}
155
156static int
157clk_pll_set_rate(struct clk_hw *hw, unsigned long rate, unsigned long p_rate)
158{
159 struct clk_pll *pll = to_clk_pll(hw);
160 const struct pll_freq_tbl *f;
161 bool enabled;
162 u32 mode;
163 u32 enable_mask = PLL_OUTCTRL | PLL_BYPASSNL | PLL_RESET_N;
164
165 f = find_freq(pll->freq_tbl, rate);
166 if (!f)
167 return -EINVAL;
168
169 regmap_read(pll->clkr.regmap, pll->mode_reg, &mode);
170 enabled = (mode & enable_mask) == enable_mask;
171
172 if (enabled)
173 clk_pll_disable(hw);
174
175 regmap_update_bits(pll->clkr.regmap, pll->l_reg, 0x3ff, f->l);
176 regmap_update_bits(pll->clkr.regmap, pll->m_reg, 0x7ffff, f->m);
177 regmap_update_bits(pll->clkr.regmap, pll->n_reg, 0x7ffff, f->n);
178 regmap_write(pll->clkr.regmap, pll->config_reg, f->ibits);
179
180 if (enabled)
181 clk_pll_enable(hw);
182
183 return 0;
184}
185
122const struct clk_ops clk_pll_ops = { 186const struct clk_ops clk_pll_ops = {
123 .enable = clk_pll_enable, 187 .enable = clk_pll_enable,
124 .disable = clk_pll_disable, 188 .disable = clk_pll_disable,
125 .recalc_rate = clk_pll_recalc_rate, 189 .recalc_rate = clk_pll_recalc_rate,
190 .determine_rate = clk_pll_determine_rate,
191 .set_rate = clk_pll_set_rate,
126}; 192};
127EXPORT_SYMBOL_GPL(clk_pll_ops); 193EXPORT_SYMBOL_GPL(clk_pll_ops);
128 194
diff --git a/drivers/clk/qcom/clk-pll.h b/drivers/clk/qcom/clk-pll.h
index 3003e9962472..c9c0cda306d0 100644
--- a/drivers/clk/qcom/clk-pll.h
+++ b/drivers/clk/qcom/clk-pll.h
@@ -18,6 +18,21 @@
18#include "clk-regmap.h" 18#include "clk-regmap.h"
19 19
20/** 20/**
21 * struct pll_freq_tbl - PLL frequency table
22 * @l: L value
23 * @m: M value
24 * @n: N value
25 * @ibits: internal values
26 */
27struct pll_freq_tbl {
28 unsigned long freq;
29 u16 l;
30 u16 m;
31 u16 n;
32 u32 ibits;
33};
34
35/**
21 * struct clk_pll - phase locked loop (PLL) 36 * struct clk_pll - phase locked loop (PLL)
22 * @l_reg: L register 37 * @l_reg: L register
23 * @m_reg: M register 38 * @m_reg: M register
@@ -26,6 +41,7 @@
26 * @mode_reg: mode register 41 * @mode_reg: mode register
27 * @status_reg: status register 42 * @status_reg: status register
28 * @status_bit: ANDed with @status_reg to determine if PLL is enabled 43 * @status_bit: ANDed with @status_reg to determine if PLL is enabled
44 * @freq_tbl: PLL frequency table
29 * @hw: handle between common and hardware-specific interfaces 45 * @hw: handle between common and hardware-specific interfaces
30 */ 46 */
31struct clk_pll { 47struct clk_pll {
@@ -36,6 +52,10 @@ struct clk_pll {
36 u32 mode_reg; 52 u32 mode_reg;
37 u32 status_reg; 53 u32 status_reg;
38 u8 status_bit; 54 u8 status_bit;
55 u8 post_div_width;
56 u8 post_div_shift;
57
58 const struct pll_freq_tbl *freq_tbl;
39 59
40 struct clk_regmap clkr; 60 struct clk_regmap clkr;
41}; 61};
diff --git a/drivers/clk/qcom/clk-rcg.c b/drivers/clk/qcom/clk-rcg.c
index b638c5846dbf..b6e6959e89aa 100644
--- a/drivers/clk/qcom/clk-rcg.c
+++ b/drivers/clk/qcom/clk-rcg.c
@@ -21,6 +21,7 @@
21#include <asm/div64.h> 21#include <asm/div64.h>
22 22
23#include "clk-rcg.h" 23#include "clk-rcg.h"
24#include "common.h"
24 25
25static u32 ns_to_src(struct src_sel *s, u32 ns) 26static u32 ns_to_src(struct src_sel *s, u32 ns)
26{ 27{
@@ -67,16 +68,16 @@ static u8 clk_dyn_rcg_get_parent(struct clk_hw *hw)
67{ 68{
68 struct clk_dyn_rcg *rcg = to_clk_dyn_rcg(hw); 69 struct clk_dyn_rcg *rcg = to_clk_dyn_rcg(hw);
69 int num_parents = __clk_get_num_parents(hw->clk); 70 int num_parents = __clk_get_num_parents(hw->clk);
70 u32 ns, ctl; 71 u32 ns, reg;
71 int bank; 72 int bank;
72 int i; 73 int i;
73 struct src_sel *s; 74 struct src_sel *s;
74 75
75 regmap_read(rcg->clkr.regmap, rcg->clkr.enable_reg, &ctl); 76 regmap_read(rcg->clkr.regmap, rcg->bank_reg, &reg);
76 bank = reg_to_bank(rcg, ctl); 77 bank = reg_to_bank(rcg, reg);
77 s = &rcg->s[bank]; 78 s = &rcg->s[bank];
78 79
79 regmap_read(rcg->clkr.regmap, rcg->ns_reg, &ns); 80 regmap_read(rcg->clkr.regmap, rcg->ns_reg[bank], &ns);
80 ns = ns_to_src(s, ns); 81 ns = ns_to_src(s, ns);
81 82
82 for (i = 0; i < num_parents; i++) 83 for (i = 0; i < num_parents; i++)
@@ -192,90 +193,93 @@ static u32 mn_to_reg(struct mn *mn, u32 m, u32 n, u32 val)
192 193
193static void configure_bank(struct clk_dyn_rcg *rcg, const struct freq_tbl *f) 194static void configure_bank(struct clk_dyn_rcg *rcg, const struct freq_tbl *f)
194{ 195{
195 u32 ns, md, ctl, *regp; 196 u32 ns, md, reg;
196 int bank, new_bank; 197 int bank, new_bank;
197 struct mn *mn; 198 struct mn *mn;
198 struct pre_div *p; 199 struct pre_div *p;
199 struct src_sel *s; 200 struct src_sel *s;
200 bool enabled; 201 bool enabled;
201 u32 md_reg; 202 u32 md_reg, ns_reg;
202 u32 bank_reg;
203 bool banked_mn = !!rcg->mn[1].width; 203 bool banked_mn = !!rcg->mn[1].width;
204 bool banked_p = !!rcg->p[1].pre_div_width;
204 struct clk_hw *hw = &rcg->clkr.hw; 205 struct clk_hw *hw = &rcg->clkr.hw;
205 206
206 enabled = __clk_is_enabled(hw->clk); 207 enabled = __clk_is_enabled(hw->clk);
207 208
208 regmap_read(rcg->clkr.regmap, rcg->ns_reg, &ns); 209 regmap_read(rcg->clkr.regmap, rcg->bank_reg, &reg);
209 regmap_read(rcg->clkr.regmap, rcg->clkr.enable_reg, &ctl); 210 bank = reg_to_bank(rcg, reg);
210
211 if (banked_mn) {
212 regp = &ctl;
213 bank_reg = rcg->clkr.enable_reg;
214 } else {
215 regp = &ns;
216 bank_reg = rcg->ns_reg;
217 }
218
219 bank = reg_to_bank(rcg, *regp);
220 new_bank = enabled ? !bank : bank; 211 new_bank = enabled ? !bank : bank;
221 212
213 ns_reg = rcg->ns_reg[new_bank];
214 regmap_read(rcg->clkr.regmap, ns_reg, &ns);
215
222 if (banked_mn) { 216 if (banked_mn) {
223 mn = &rcg->mn[new_bank]; 217 mn = &rcg->mn[new_bank];
224 md_reg = rcg->md_reg[new_bank]; 218 md_reg = rcg->md_reg[new_bank];
225 219
226 ns |= BIT(mn->mnctr_reset_bit); 220 ns |= BIT(mn->mnctr_reset_bit);
227 regmap_write(rcg->clkr.regmap, rcg->ns_reg, ns); 221 regmap_write(rcg->clkr.regmap, ns_reg, ns);
228 222
229 regmap_read(rcg->clkr.regmap, md_reg, &md); 223 regmap_read(rcg->clkr.regmap, md_reg, &md);
230 md = mn_to_md(mn, f->m, f->n, md); 224 md = mn_to_md(mn, f->m, f->n, md);
231 regmap_write(rcg->clkr.regmap, md_reg, md); 225 regmap_write(rcg->clkr.regmap, md_reg, md);
232 226
233 ns = mn_to_ns(mn, f->m, f->n, ns); 227 ns = mn_to_ns(mn, f->m, f->n, ns);
234 regmap_write(rcg->clkr.regmap, rcg->ns_reg, ns); 228 regmap_write(rcg->clkr.regmap, ns_reg, ns);
235 229
236 ctl = mn_to_reg(mn, f->m, f->n, ctl); 230 /* Two NS registers means mode control is in NS register */
237 regmap_write(rcg->clkr.regmap, rcg->clkr.enable_reg, ctl); 231 if (rcg->ns_reg[0] != rcg->ns_reg[1]) {
232 ns = mn_to_reg(mn, f->m, f->n, ns);
233 regmap_write(rcg->clkr.regmap, ns_reg, ns);
234 } else {
235 reg = mn_to_reg(mn, f->m, f->n, reg);
236 regmap_write(rcg->clkr.regmap, rcg->bank_reg, reg);
237 }
238 238
239 ns &= ~BIT(mn->mnctr_reset_bit); 239 ns &= ~BIT(mn->mnctr_reset_bit);
240 regmap_write(rcg->clkr.regmap, rcg->ns_reg, ns); 240 regmap_write(rcg->clkr.regmap, ns_reg, ns);
241 } else { 241 }
242
243 if (banked_p) {
242 p = &rcg->p[new_bank]; 244 p = &rcg->p[new_bank];
243 ns = pre_div_to_ns(p, f->pre_div - 1, ns); 245 ns = pre_div_to_ns(p, f->pre_div - 1, ns);
244 } 246 }
245 247
246 s = &rcg->s[new_bank]; 248 s = &rcg->s[new_bank];
247 ns = src_to_ns(s, s->parent_map[f->src], ns); 249 ns = src_to_ns(s, s->parent_map[f->src], ns);
248 regmap_write(rcg->clkr.regmap, rcg->ns_reg, ns); 250 regmap_write(rcg->clkr.regmap, ns_reg, ns);
249 251
250 if (enabled) { 252 if (enabled) {
251 *regp ^= BIT(rcg->mux_sel_bit); 253 regmap_read(rcg->clkr.regmap, rcg->bank_reg, &reg);
252 regmap_write(rcg->clkr.regmap, bank_reg, *regp); 254 reg ^= BIT(rcg->mux_sel_bit);
255 regmap_write(rcg->clkr.regmap, rcg->bank_reg, reg);
253 } 256 }
254} 257}
255 258
256static int clk_dyn_rcg_set_parent(struct clk_hw *hw, u8 index) 259static int clk_dyn_rcg_set_parent(struct clk_hw *hw, u8 index)
257{ 260{
258 struct clk_dyn_rcg *rcg = to_clk_dyn_rcg(hw); 261 struct clk_dyn_rcg *rcg = to_clk_dyn_rcg(hw);
259 u32 ns, ctl, md, reg; 262 u32 ns, md, reg;
260 int bank; 263 int bank;
261 struct freq_tbl f = { 0 }; 264 struct freq_tbl f = { 0 };
262 bool banked_mn = !!rcg->mn[1].width; 265 bool banked_mn = !!rcg->mn[1].width;
266 bool banked_p = !!rcg->p[1].pre_div_width;
263 267
264 regmap_read(rcg->clkr.regmap, rcg->ns_reg, &ns); 268 regmap_read(rcg->clkr.regmap, rcg->bank_reg, &reg);
265 regmap_read(rcg->clkr.regmap, rcg->clkr.enable_reg, &ctl);
266 reg = banked_mn ? ctl : ns;
267
268 bank = reg_to_bank(rcg, reg); 269 bank = reg_to_bank(rcg, reg);
269 270
271 regmap_read(rcg->clkr.regmap, rcg->ns_reg[bank], &ns);
272
270 if (banked_mn) { 273 if (banked_mn) {
271 regmap_read(rcg->clkr.regmap, rcg->md_reg[bank], &md); 274 regmap_read(rcg->clkr.regmap, rcg->md_reg[bank], &md);
272 f.m = md_to_m(&rcg->mn[bank], md); 275 f.m = md_to_m(&rcg->mn[bank], md);
273 f.n = ns_m_to_n(&rcg->mn[bank], ns, f.m); 276 f.n = ns_m_to_n(&rcg->mn[bank], ns, f.m);
274 } else {
275 f.pre_div = ns_to_pre_div(&rcg->p[bank], ns) + 1;
276 } 277 }
277 f.src = index;
278 278
279 if (banked_p)
280 f.pre_div = ns_to_pre_div(&rcg->p[bank], ns) + 1;
281
282 f.src = index;
279 configure_bank(rcg, &f); 283 configure_bank(rcg, &f);
280 284
281 return 0; 285 return 0;
@@ -336,41 +340,30 @@ clk_dyn_rcg_recalc_rate(struct clk_hw *hw, unsigned long parent_rate)
336 u32 m, n, pre_div, ns, md, mode, reg; 340 u32 m, n, pre_div, ns, md, mode, reg;
337 int bank; 341 int bank;
338 struct mn *mn; 342 struct mn *mn;
343 bool banked_p = !!rcg->p[1].pre_div_width;
339 bool banked_mn = !!rcg->mn[1].width; 344 bool banked_mn = !!rcg->mn[1].width;
340 345
341 regmap_read(rcg->clkr.regmap, rcg->ns_reg, &ns); 346 regmap_read(rcg->clkr.regmap, rcg->bank_reg, &reg);
342
343 if (banked_mn)
344 regmap_read(rcg->clkr.regmap, rcg->clkr.enable_reg, &reg);
345 else
346 reg = ns;
347
348 bank = reg_to_bank(rcg, reg); 347 bank = reg_to_bank(rcg, reg);
349 348
349 regmap_read(rcg->clkr.regmap, rcg->ns_reg[bank], &ns);
350 m = n = pre_div = mode = 0;
351
350 if (banked_mn) { 352 if (banked_mn) {
351 mn = &rcg->mn[bank]; 353 mn = &rcg->mn[bank];
352 regmap_read(rcg->clkr.regmap, rcg->md_reg[bank], &md); 354 regmap_read(rcg->clkr.regmap, rcg->md_reg[bank], &md);
353 m = md_to_m(mn, md); 355 m = md_to_m(mn, md);
354 n = ns_m_to_n(mn, ns, m); 356 n = ns_m_to_n(mn, ns, m);
357 /* Two NS registers means mode control is in NS register */
358 if (rcg->ns_reg[0] != rcg->ns_reg[1])
359 reg = ns;
355 mode = reg_to_mnctr_mode(mn, reg); 360 mode = reg_to_mnctr_mode(mn, reg);
356 return calc_rate(parent_rate, m, n, mode, 0);
357 } else {
358 pre_div = ns_to_pre_div(&rcg->p[bank], ns);
359 return calc_rate(parent_rate, 0, 0, 0, pre_div);
360 } 361 }
361}
362 362
363static const 363 if (banked_p)
364struct freq_tbl *find_freq(const struct freq_tbl *f, unsigned long rate) 364 pre_div = ns_to_pre_div(&rcg->p[bank], ns);
365{
366 if (!f)
367 return NULL;
368
369 for (; f->freq; f++)
370 if (rate <= f->freq)
371 return f;
372 365
373 return NULL; 366 return calc_rate(parent_rate, m, n, mode, pre_div);
374} 367}
375 368
376static long _freq_tbl_determine_rate(struct clk_hw *hw, 369static long _freq_tbl_determine_rate(struct clk_hw *hw,
@@ -379,7 +372,7 @@ static long _freq_tbl_determine_rate(struct clk_hw *hw,
379{ 372{
380 unsigned long clk_flags; 373 unsigned long clk_flags;
381 374
382 f = find_freq(f, rate); 375 f = qcom_find_freq(f, rate);
383 if (!f) 376 if (!f)
384 return -EINVAL; 377 return -EINVAL;
385 378
@@ -477,7 +470,7 @@ static int clk_rcg_set_rate(struct clk_hw *hw, unsigned long rate,
477 struct clk_rcg *rcg = to_clk_rcg(hw); 470 struct clk_rcg *rcg = to_clk_rcg(hw);
478 const struct freq_tbl *f; 471 const struct freq_tbl *f;
479 472
480 f = find_freq(rcg->freq_tbl, rate); 473 f = qcom_find_freq(rcg->freq_tbl, rate);
481 if (!f) 474 if (!f)
482 return -EINVAL; 475 return -EINVAL;
483 476
@@ -497,7 +490,7 @@ static int __clk_dyn_rcg_set_rate(struct clk_hw *hw, unsigned long rate)
497 struct clk_dyn_rcg *rcg = to_clk_dyn_rcg(hw); 490 struct clk_dyn_rcg *rcg = to_clk_dyn_rcg(hw);
498 const struct freq_tbl *f; 491 const struct freq_tbl *f;
499 492
500 f = find_freq(rcg->freq_tbl, rate); 493 f = qcom_find_freq(rcg->freq_tbl, rate);
501 if (!f) 494 if (!f)
502 return -EINVAL; 495 return -EINVAL;
503 496
diff --git a/drivers/clk/qcom/clk-rcg.h b/drivers/clk/qcom/clk-rcg.h
index ba0523cefd2e..687e41f91d7c 100644
--- a/drivers/clk/qcom/clk-rcg.h
+++ b/drivers/clk/qcom/clk-rcg.h
@@ -103,8 +103,9 @@ extern const struct clk_ops clk_rcg_bypass_ops;
103 * struct clk_dyn_rcg - root clock generator with glitch free mux 103 * struct clk_dyn_rcg - root clock generator with glitch free mux
104 * 104 *
105 * @mux_sel_bit: bit to switch glitch free mux 105 * @mux_sel_bit: bit to switch glitch free mux
106 * @ns_reg: NS register 106 * @ns_reg: NS0 and NS1 register
107 * @md_reg: MD0 and MD1 register 107 * @md_reg: MD0 and MD1 register
108 * @bank_reg: register to XOR @mux_sel_bit into to switch glitch free mux
108 * @mn: mn counter (banked) 109 * @mn: mn counter (banked)
109 * @s: source selector (banked) 110 * @s: source selector (banked)
110 * @freq_tbl: frequency table 111 * @freq_tbl: frequency table
@@ -113,8 +114,9 @@ extern const struct clk_ops clk_rcg_bypass_ops;
113 * 114 *
114 */ 115 */
115struct clk_dyn_rcg { 116struct clk_dyn_rcg {
116 u32 ns_reg; 117 u32 ns_reg[2];
117 u32 md_reg[2]; 118 u32 md_reg[2];
119 u32 bank_reg;
118 120
119 u8 mux_sel_bit; 121 u8 mux_sel_bit;
120 122
diff --git a/drivers/clk/qcom/clk-rcg2.c b/drivers/clk/qcom/clk-rcg2.c
index cd185d5cc67a..cfa9eb4fe9ca 100644
--- a/drivers/clk/qcom/clk-rcg2.c
+++ b/drivers/clk/qcom/clk-rcg2.c
@@ -24,6 +24,7 @@
24#include <asm/div64.h> 24#include <asm/div64.h>
25 25
26#include "clk-rcg.h" 26#include "clk-rcg.h"
27#include "common.h"
27 28
28#define CMD_REG 0x0 29#define CMD_REG 0x0
29#define CMD_UPDATE BIT(0) 30#define CMD_UPDATE BIT(0)
@@ -172,27 +173,13 @@ clk_rcg2_recalc_rate(struct clk_hw *hw, unsigned long parent_rate)
172 return calc_rate(parent_rate, m, n, mode, hid_div); 173 return calc_rate(parent_rate, m, n, mode, hid_div);
173} 174}
174 175
175static const
176struct freq_tbl *find_freq(const struct freq_tbl *f, unsigned long rate)
177{
178 if (!f)
179 return NULL;
180
181 for (; f->freq; f++)
182 if (rate <= f->freq)
183 return f;
184
185 /* Default to our fastest rate */
186 return f - 1;
187}
188
189static long _freq_tbl_determine_rate(struct clk_hw *hw, 176static long _freq_tbl_determine_rate(struct clk_hw *hw,
190 const struct freq_tbl *f, unsigned long rate, 177 const struct freq_tbl *f, unsigned long rate,
191 unsigned long *p_rate, struct clk **p) 178 unsigned long *p_rate, struct clk **p)
192{ 179{
193 unsigned long clk_flags; 180 unsigned long clk_flags;
194 181
195 f = find_freq(f, rate); 182 f = qcom_find_freq(f, rate);
196 if (!f) 183 if (!f)
197 return -EINVAL; 184 return -EINVAL;
198 185
@@ -268,7 +255,7 @@ static int __clk_rcg2_set_rate(struct clk_hw *hw, unsigned long rate)
268 struct clk_rcg2 *rcg = to_clk_rcg2(hw); 255 struct clk_rcg2 *rcg = to_clk_rcg2(hw);
269 const struct freq_tbl *f; 256 const struct freq_tbl *f;
270 257
271 f = find_freq(rcg->freq_tbl, rate); 258 f = qcom_find_freq(rcg->freq_tbl, rate);
272 if (!f) 259 if (!f)
273 return -EINVAL; 260 return -EINVAL;
274 261
diff --git a/drivers/clk/qcom/common.c b/drivers/clk/qcom/common.c
index eeb3eea01f4c..e20d947db3e5 100644
--- a/drivers/clk/qcom/common.c
+++ b/drivers/clk/qcom/common.c
@@ -18,6 +18,7 @@
18#include <linux/reset-controller.h> 18#include <linux/reset-controller.h>
19 19
20#include "common.h" 20#include "common.h"
21#include "clk-rcg.h"
21#include "clk-regmap.h" 22#include "clk-regmap.h"
22#include "reset.h" 23#include "reset.h"
23 24
@@ -27,6 +28,21 @@ struct qcom_cc {
27 struct clk *clks[]; 28 struct clk *clks[];
28}; 29};
29 30
31const
32struct freq_tbl *qcom_find_freq(const struct freq_tbl *f, unsigned long rate)
33{
34 if (!f)
35 return NULL;
36
37 for (; f->freq; f++)
38 if (rate <= f->freq)
39 return f;
40
41 /* Default to our fastest rate */
42 return f - 1;
43}
44EXPORT_SYMBOL_GPL(qcom_find_freq);
45
30struct regmap * 46struct regmap *
31qcom_cc_map(struct platform_device *pdev, const struct qcom_cc_desc *desc) 47qcom_cc_map(struct platform_device *pdev, const struct qcom_cc_desc *desc)
32{ 48{
diff --git a/drivers/clk/qcom/common.h b/drivers/clk/qcom/common.h
index 2765e9d3da97..f519322acdf3 100644
--- a/drivers/clk/qcom/common.h
+++ b/drivers/clk/qcom/common.h
@@ -18,6 +18,7 @@ struct regmap_config;
18struct clk_regmap; 18struct clk_regmap;
19struct qcom_reset_map; 19struct qcom_reset_map;
20struct regmap; 20struct regmap;
21struct freq_tbl;
21 22
22struct qcom_cc_desc { 23struct qcom_cc_desc {
23 const struct regmap_config *config; 24 const struct regmap_config *config;
@@ -27,6 +28,9 @@ struct qcom_cc_desc {
27 size_t num_resets; 28 size_t num_resets;
28}; 29};
29 30
31extern const struct freq_tbl *qcom_find_freq(const struct freq_tbl *f,
32 unsigned long rate);
33
30extern struct regmap *qcom_cc_map(struct platform_device *pdev, 34extern struct regmap *qcom_cc_map(struct platform_device *pdev,
31 const struct qcom_cc_desc *desc); 35 const struct qcom_cc_desc *desc);
32extern int qcom_cc_really_probe(struct platform_device *pdev, 36extern int qcom_cc_really_probe(struct platform_device *pdev,
diff --git a/drivers/clk/qcom/gcc-ipq806x.c b/drivers/clk/qcom/gcc-ipq806x.c
index 3b83b7dd78c7..5cd62a709ac7 100644
--- a/drivers/clk/qcom/gcc-ipq806x.c
+++ b/drivers/clk/qcom/gcc-ipq806x.c
@@ -32,6 +32,33 @@
32#include "clk-branch.h" 32#include "clk-branch.h"
33#include "reset.h" 33#include "reset.h"
34 34
35static struct clk_pll pll0 = {
36 .l_reg = 0x30c4,
37 .m_reg = 0x30c8,
38 .n_reg = 0x30cc,
39 .config_reg = 0x30d4,
40 .mode_reg = 0x30c0,
41 .status_reg = 0x30d8,
42 .status_bit = 16,
43 .clkr.hw.init = &(struct clk_init_data){
44 .name = "pll0",
45 .parent_names = (const char *[]){ "pxo" },
46 .num_parents = 1,
47 .ops = &clk_pll_ops,
48 },
49};
50
51static struct clk_regmap pll0_vote = {
52 .enable_reg = 0x34c0,
53 .enable_mask = BIT(0),
54 .hw.init = &(struct clk_init_data){
55 .name = "pll0_vote",
56 .parent_names = (const char *[]){ "pll0" },
57 .num_parents = 1,
58 .ops = &clk_pll_vote_ops,
59 },
60};
61
35static struct clk_pll pll3 = { 62static struct clk_pll pll3 = {
36 .l_reg = 0x3164, 63 .l_reg = 0x3164,
37 .m_reg = 0x3168, 64 .m_reg = 0x3168,
@@ -154,7 +181,7 @@ static const u8 gcc_pxo_pll8_pll0[] = {
154static const char *gcc_pxo_pll8_pll0_map[] = { 181static const char *gcc_pxo_pll8_pll0_map[] = {
155 "pxo", 182 "pxo",
156 "pll8_vote", 183 "pll8_vote",
157 "pll0", 184 "pll0_vote",
158}; 185};
159 186
160static struct freq_tbl clk_tbl_gsbi_uart[] = { 187static struct freq_tbl clk_tbl_gsbi_uart[] = {
@@ -2133,6 +2160,8 @@ static struct clk_branch usb_fs1_h_clk = {
2133}; 2160};
2134 2161
2135static struct clk_regmap *gcc_ipq806x_clks[] = { 2162static struct clk_regmap *gcc_ipq806x_clks[] = {
2163 [PLL0] = &pll0.clkr,
2164 [PLL0_VOTE] = &pll0_vote,
2136 [PLL3] = &pll3.clkr, 2165 [PLL3] = &pll3.clkr,
2137 [PLL8] = &pll8.clkr, 2166 [PLL8] = &pll8.clkr,
2138 [PLL8_VOTE] = &pll8_vote, 2167 [PLL8_VOTE] = &pll8_vote,
diff --git a/drivers/clk/qcom/mmcc-apq8084.c b/drivers/clk/qcom/mmcc-apq8084.c
index 751eea376a2b..dab988ab8cf1 100644
--- a/drivers/clk/qcom/mmcc-apq8084.c
+++ b/drivers/clk/qcom/mmcc-apq8084.c
@@ -3341,7 +3341,6 @@ static struct platform_driver mmcc_apq8084_driver = {
3341 .remove = mmcc_apq8084_remove, 3341 .remove = mmcc_apq8084_remove,
3342 .driver = { 3342 .driver = {
3343 .name = "mmcc-apq8084", 3343 .name = "mmcc-apq8084",
3344 .owner = THIS_MODULE,
3345 .of_match_table = mmcc_apq8084_match_table, 3344 .of_match_table = mmcc_apq8084_match_table,
3346 }, 3345 },
3347}; 3346};
diff --git a/drivers/clk/qcom/mmcc-msm8960.c b/drivers/clk/qcom/mmcc-msm8960.c
index 2e80a219b8ea..e8b33bbc362f 100644
--- a/drivers/clk/qcom/mmcc-msm8960.c
+++ b/drivers/clk/qcom/mmcc-msm8960.c
@@ -773,9 +773,11 @@ static struct freq_tbl clk_tbl_gfx2d[] = {
773}; 773};
774 774
775static struct clk_dyn_rcg gfx2d0_src = { 775static struct clk_dyn_rcg gfx2d0_src = {
776 .ns_reg = 0x0070, 776 .ns_reg[0] = 0x0070,
777 .ns_reg[1] = 0x0070,
777 .md_reg[0] = 0x0064, 778 .md_reg[0] = 0x0064,
778 .md_reg[1] = 0x0068, 779 .md_reg[1] = 0x0068,
780 .bank_reg = 0x0060,
779 .mn[0] = { 781 .mn[0] = {
780 .mnctr_en_bit = 8, 782 .mnctr_en_bit = 8,
781 .mnctr_reset_bit = 25, 783 .mnctr_reset_bit = 25,
@@ -831,9 +833,11 @@ static struct clk_branch gfx2d0_clk = {
831}; 833};
832 834
833static struct clk_dyn_rcg gfx2d1_src = { 835static struct clk_dyn_rcg gfx2d1_src = {
834 .ns_reg = 0x007c, 836 .ns_reg[0] = 0x007c,
837 .ns_reg[1] = 0x007c,
835 .md_reg[0] = 0x0078, 838 .md_reg[0] = 0x0078,
836 .md_reg[1] = 0x006c, 839 .md_reg[1] = 0x006c,
840 .bank_reg = 0x0074,
837 .mn[0] = { 841 .mn[0] = {
838 .mnctr_en_bit = 8, 842 .mnctr_en_bit = 8,
839 .mnctr_reset_bit = 25, 843 .mnctr_reset_bit = 25,
@@ -930,9 +934,11 @@ static struct freq_tbl clk_tbl_gfx3d_8064[] = {
930}; 934};
931 935
932static struct clk_dyn_rcg gfx3d_src = { 936static struct clk_dyn_rcg gfx3d_src = {
933 .ns_reg = 0x008c, 937 .ns_reg[0] = 0x008c,
938 .ns_reg[1] = 0x008c,
934 .md_reg[0] = 0x0084, 939 .md_reg[0] = 0x0084,
935 .md_reg[1] = 0x0088, 940 .md_reg[1] = 0x0088,
941 .bank_reg = 0x0080,
936 .mn[0] = { 942 .mn[0] = {
937 .mnctr_en_bit = 8, 943 .mnctr_en_bit = 8,
938 .mnctr_reset_bit = 25, 944 .mnctr_reset_bit = 25,
@@ -1006,9 +1012,11 @@ static struct freq_tbl clk_tbl_vcap[] = {
1006}; 1012};
1007 1013
1008static struct clk_dyn_rcg vcap_src = { 1014static struct clk_dyn_rcg vcap_src = {
1009 .ns_reg = 0x021c, 1015 .ns_reg[0] = 0x021c,
1016 .ns_reg[1] = 0x021c,
1010 .md_reg[0] = 0x01ec, 1017 .md_reg[0] = 0x01ec,
1011 .md_reg[1] = 0x0218, 1018 .md_reg[1] = 0x0218,
1019 .bank_reg = 0x0178,
1012 .mn[0] = { 1020 .mn[0] = {
1013 .mnctr_en_bit = 8, 1021 .mnctr_en_bit = 8,
1014 .mnctr_reset_bit = 23, 1022 .mnctr_reset_bit = 23,
@@ -1211,9 +1219,11 @@ static struct freq_tbl clk_tbl_mdp[] = {
1211}; 1219};
1212 1220
1213static struct clk_dyn_rcg mdp_src = { 1221static struct clk_dyn_rcg mdp_src = {
1214 .ns_reg = 0x00d0, 1222 .ns_reg[0] = 0x00d0,
1223 .ns_reg[1] = 0x00d0,
1215 .md_reg[0] = 0x00c4, 1224 .md_reg[0] = 0x00c4,
1216 .md_reg[1] = 0x00c8, 1225 .md_reg[1] = 0x00c8,
1226 .bank_reg = 0x00c0,
1217 .mn[0] = { 1227 .mn[0] = {
1218 .mnctr_en_bit = 8, 1228 .mnctr_en_bit = 8,
1219 .mnctr_reset_bit = 31, 1229 .mnctr_reset_bit = 31,
@@ -1318,7 +1328,9 @@ static struct freq_tbl clk_tbl_rot[] = {
1318}; 1328};
1319 1329
1320static struct clk_dyn_rcg rot_src = { 1330static struct clk_dyn_rcg rot_src = {
1321 .ns_reg = 0x00e8, 1331 .ns_reg[0] = 0x00e8,
1332 .ns_reg[1] = 0x00e8,
1333 .bank_reg = 0x00e8,
1322 .p[0] = { 1334 .p[0] = {
1323 .pre_div_shift = 22, 1335 .pre_div_shift = 22,
1324 .pre_div_width = 4, 1336 .pre_div_width = 4,
@@ -1542,9 +1554,11 @@ static struct freq_tbl clk_tbl_vcodec[] = {
1542}; 1554};
1543 1555
1544static struct clk_dyn_rcg vcodec_src = { 1556static struct clk_dyn_rcg vcodec_src = {
1545 .ns_reg = 0x0100, 1557 .ns_reg[0] = 0x0100,
1558 .ns_reg[1] = 0x0100,
1546 .md_reg[0] = 0x00fc, 1559 .md_reg[0] = 0x00fc,
1547 .md_reg[1] = 0x0128, 1560 .md_reg[1] = 0x0128,
1561 .bank_reg = 0x00f8,
1548 .mn[0] = { 1562 .mn[0] = {
1549 .mnctr_en_bit = 5, 1563 .mnctr_en_bit = 5,
1550 .mnctr_reset_bit = 31, 1564 .mnctr_reset_bit = 31,
@@ -2679,7 +2693,6 @@ static struct platform_driver mmcc_msm8960_driver = {
2679 .remove = mmcc_msm8960_remove, 2693 .remove = mmcc_msm8960_remove,
2680 .driver = { 2694 .driver = {
2681 .name = "mmcc-msm8960", 2695 .name = "mmcc-msm8960",
2682 .owner = THIS_MODULE,
2683 .of_match_table = mmcc_msm8960_match_table, 2696 .of_match_table = mmcc_msm8960_match_table,
2684 }, 2697 },
2685}; 2698};
diff --git a/drivers/clk/qcom/mmcc-msm8974.c b/drivers/clk/qcom/mmcc-msm8974.c
index bc8f519c47aa..be94c54a9a4f 100644
--- a/drivers/clk/qcom/mmcc-msm8974.c
+++ b/drivers/clk/qcom/mmcc-msm8974.c
@@ -2570,7 +2570,6 @@ static struct platform_driver mmcc_msm8974_driver = {
2570 .remove = mmcc_msm8974_remove, 2570 .remove = mmcc_msm8974_remove,
2571 .driver = { 2571 .driver = {
2572 .name = "mmcc-msm8974", 2572 .name = "mmcc-msm8974",
2573 .owner = THIS_MODULE,
2574 .of_match_table = mmcc_msm8974_match_table, 2573 .of_match_table = mmcc_msm8974_match_table,
2575 }, 2574 },
2576}; 2575};
diff --git a/drivers/clk/rockchip/Makefile b/drivers/clk/rockchip/Makefile
index ee6b077381e1..bd8514d63634 100644
--- a/drivers/clk/rockchip/Makefile
+++ b/drivers/clk/rockchip/Makefile
@@ -5,6 +5,7 @@
5obj-y += clk-rockchip.o 5obj-y += clk-rockchip.o
6obj-y += clk.o 6obj-y += clk.o
7obj-y += clk-pll.o 7obj-y += clk-pll.o
8obj-y += clk-cpu.o
8obj-$(CONFIG_RESET_CONTROLLER) += softrst.o 9obj-$(CONFIG_RESET_CONTROLLER) += softrst.o
9 10
10obj-y += clk-rk3188.o 11obj-y += clk-rk3188.o
diff --git a/drivers/clk/rockchip/clk-cpu.c b/drivers/clk/rockchip/clk-cpu.c
new file mode 100644
index 000000000000..75c8c45ef728
--- /dev/null
+++ b/drivers/clk/rockchip/clk-cpu.c
@@ -0,0 +1,329 @@
1/*
2 * Copyright (c) 2014 MundoReader S.L.
3 * Author: Heiko Stuebner <heiko@sntech.de>
4 *
5 * based on clk/samsung/clk-cpu.c
6 * Copyright (c) 2014 Samsung Electronics Co., Ltd.
7 * Author: Thomas Abraham <thomas.ab@samsung.com>
8 *
9 * This program is free software; you can redistribute it and/or modify
10 * it under the terms of the GNU General Public License version 2 as
11 * published by the Free Software Foundation.
12 *
13 * A CPU clock is defined as a clock supplied to a CPU or a group of CPUs.
14 * The CPU clock is typically derived from a hierarchy of clock
15 * blocks which includes mux and divider blocks. There are a number of other
16 * auxiliary clocks supplied to the CPU domain such as the debug blocks and AXI
17 * clock for CPU domain. The rates of these auxiliary clocks are related to the
18 * CPU clock rate and this relation is usually specified in the hardware manual
19 * of the SoC or supplied after the SoC characterization.
20 *
21 * The below implementation of the CPU clock allows the rate changes of the CPU
22 * clock and the corresponding rate changes of the auxillary clocks of the CPU
23 * domain. The platform clock driver provides a clock register configuration
24 * for each configurable rate which is then used to program the clock hardware
25 * registers to acheive a fast co-oridinated rate change for all the CPU domain
26 * clocks.
27 *
28 * On a rate change request for the CPU clock, the rate change is propagated
29 * upto the PLL supplying the clock to the CPU domain clock blocks. While the
30 * CPU domain PLL is reconfigured, the CPU domain clocks are driven using an
31 * alternate clock source. If required, the alternate clock source is divided
32 * down in order to keep the output clock rate within the previous OPP limits.
33 */
34
35#include <linux/of.h>
36#include <linux/slab.h>
37#include <linux/io.h>
38#include <linux/clk-provider.h>
39#include "clk.h"
40
41/**
42 * struct rockchip_cpuclk: information about clock supplied to a CPU core.
43 * @hw: handle between ccf and cpu clock.
44 * @alt_parent: alternate parent clock to use when switching the speed
45 * of the primary parent clock.
46 * @reg_base: base register for cpu-clock values.
47 * @clk_nb: clock notifier registered for changes in clock speed of the
48 * primary parent clock.
49 * @rate_count: number of rates in the rate_table
50 * @rate_table: pll-rates and their associated dividers
51 * @reg_data: cpu-specific register settings
52 * @lock: clock lock
53 */
54struct rockchip_cpuclk {
55 struct clk_hw hw;
56
57 struct clk_mux cpu_mux;
58 const struct clk_ops *cpu_mux_ops;
59
60 struct clk *alt_parent;
61 void __iomem *reg_base;
62 struct notifier_block clk_nb;
63 unsigned int rate_count;
64 struct rockchip_cpuclk_rate_table *rate_table;
65 const struct rockchip_cpuclk_reg_data *reg_data;
66 spinlock_t *lock;
67};
68
69#define to_rockchip_cpuclk_hw(hw) container_of(hw, struct rockchip_cpuclk, hw)
70#define to_rockchip_cpuclk_nb(nb) \
71 container_of(nb, struct rockchip_cpuclk, clk_nb)
72
73static const struct rockchip_cpuclk_rate_table *rockchip_get_cpuclk_settings(
74 struct rockchip_cpuclk *cpuclk, unsigned long rate)
75{
76 const struct rockchip_cpuclk_rate_table *rate_table =
77 cpuclk->rate_table;
78 int i;
79
80 for (i = 0; i < cpuclk->rate_count; i++) {
81 if (rate == rate_table[i].prate)
82 return &rate_table[i];
83 }
84
85 return NULL;
86}
87
88static unsigned long rockchip_cpuclk_recalc_rate(struct clk_hw *hw,
89 unsigned long parent_rate)
90{
91 struct rockchip_cpuclk *cpuclk = to_rockchip_cpuclk_hw(hw);
92 const struct rockchip_cpuclk_reg_data *reg_data = cpuclk->reg_data;
93 u32 clksel0 = readl_relaxed(cpuclk->reg_base + reg_data->core_reg);
94
95 clksel0 >>= reg_data->div_core_shift;
96 clksel0 &= reg_data->div_core_mask;
97 return parent_rate / (clksel0 + 1);
98}
99
100static const struct clk_ops rockchip_cpuclk_ops = {
101 .recalc_rate = rockchip_cpuclk_recalc_rate,
102};
103
104static void rockchip_cpuclk_set_dividers(struct rockchip_cpuclk *cpuclk,
105 const struct rockchip_cpuclk_rate_table *rate)
106{
107 int i;
108
109 /* alternate parent is active now. set the dividers */
110 for (i = 0; i < ARRAY_SIZE(rate->divs); i++) {
111 const struct rockchip_cpuclk_clksel *clksel = &rate->divs[i];
112
113 if (!clksel->reg)
114 continue;
115
116 pr_debug("%s: setting reg 0x%x to 0x%x\n",
117 __func__, clksel->reg, clksel->val);
118 writel(clksel->val , cpuclk->reg_base + clksel->reg);
119 }
120}
121
122static int rockchip_cpuclk_pre_rate_change(struct rockchip_cpuclk *cpuclk,
123 struct clk_notifier_data *ndata)
124{
125 const struct rockchip_cpuclk_reg_data *reg_data = cpuclk->reg_data;
126 unsigned long alt_prate, alt_div;
127
128 alt_prate = clk_get_rate(cpuclk->alt_parent);
129
130 spin_lock(cpuclk->lock);
131
132 /*
133 * If the old parent clock speed is less than the clock speed
134 * of the alternate parent, then it should be ensured that at no point
135 * the armclk speed is more than the old_rate until the dividers are
136 * set.
137 */
138 if (alt_prate > ndata->old_rate) {
139 /* calculate dividers */
140 alt_div = DIV_ROUND_UP(alt_prate, ndata->old_rate) - 1;
141 if (alt_div > reg_data->div_core_mask) {
142 pr_warn("%s: limiting alt-divider %lu to %d\n",
143 __func__, alt_div, reg_data->div_core_mask);
144 alt_div = reg_data->div_core_mask;
145 }
146
147 /*
148 * Change parents and add dividers in a single transaction.
149 *
150 * NOTE: we do this in a single transaction so we're never
151 * dividing the primary parent by the extra dividers that were
152 * needed for the alt.
153 */
154 pr_debug("%s: setting div %lu as alt-rate %lu > old-rate %lu\n",
155 __func__, alt_div, alt_prate, ndata->old_rate);
156
157 writel(HIWORD_UPDATE(alt_div, reg_data->div_core_mask,
158 reg_data->div_core_shift) |
159 HIWORD_UPDATE(1, 1, reg_data->mux_core_shift),
160 cpuclk->reg_base + reg_data->core_reg);
161 } else {
162 /* select alternate parent */
163 writel(HIWORD_UPDATE(1, 1, reg_data->mux_core_shift),
164 cpuclk->reg_base + reg_data->core_reg);
165 }
166
167 spin_unlock(cpuclk->lock);
168 return 0;
169}
170
171static int rockchip_cpuclk_post_rate_change(struct rockchip_cpuclk *cpuclk,
172 struct clk_notifier_data *ndata)
173{
174 const struct rockchip_cpuclk_reg_data *reg_data = cpuclk->reg_data;
175 const struct rockchip_cpuclk_rate_table *rate;
176
177 rate = rockchip_get_cpuclk_settings(cpuclk, ndata->new_rate);
178 if (!rate) {
179 pr_err("%s: Invalid rate : %lu for cpuclk\n",
180 __func__, ndata->new_rate);
181 return -EINVAL;
182 }
183
184 spin_lock(cpuclk->lock);
185
186 if (ndata->old_rate < ndata->new_rate)
187 rockchip_cpuclk_set_dividers(cpuclk, rate);
188
189 /*
190 * post-rate change event, re-mux to primary parent and remove dividers.
191 *
192 * NOTE: we do this in a single transaction so we're never dividing the
193 * primary parent by the extra dividers that were needed for the alt.
194 */
195
196 writel(HIWORD_UPDATE(0, reg_data->div_core_mask,
197 reg_data->div_core_shift) |
198 HIWORD_UPDATE(0, 1, reg_data->mux_core_shift),
199 cpuclk->reg_base + reg_data->core_reg);
200
201 if (ndata->old_rate > ndata->new_rate)
202 rockchip_cpuclk_set_dividers(cpuclk, rate);
203
204 spin_unlock(cpuclk->lock);
205 return 0;
206}
207
208/*
209 * This clock notifier is called when the frequency of the parent clock
210 * of cpuclk is to be changed. This notifier handles the setting up all
211 * the divider clocks, remux to temporary parent and handling the safe
212 * frequency levels when using temporary parent.
213 */
214static int rockchip_cpuclk_notifier_cb(struct notifier_block *nb,
215 unsigned long event, void *data)
216{
217 struct clk_notifier_data *ndata = data;
218 struct rockchip_cpuclk *cpuclk = to_rockchip_cpuclk_nb(nb);
219 int ret = 0;
220
221 pr_debug("%s: event %lu, old_rate %lu, new_rate: %lu\n",
222 __func__, event, ndata->old_rate, ndata->new_rate);
223 if (event == PRE_RATE_CHANGE)
224 ret = rockchip_cpuclk_pre_rate_change(cpuclk, ndata);
225 else if (event == POST_RATE_CHANGE)
226 ret = rockchip_cpuclk_post_rate_change(cpuclk, ndata);
227
228 return notifier_from_errno(ret);
229}
230
231struct clk *rockchip_clk_register_cpuclk(const char *name,
232 const char **parent_names, u8 num_parents,
233 const struct rockchip_cpuclk_reg_data *reg_data,
234 const struct rockchip_cpuclk_rate_table *rates,
235 int nrates, void __iomem *reg_base, spinlock_t *lock)
236{
237 struct rockchip_cpuclk *cpuclk;
238 struct clk_init_data init;
239 struct clk *clk, *cclk;
240 int ret;
241
242 if (num_parents != 2) {
243 pr_err("%s: needs two parent clocks\n", __func__);
244 return ERR_PTR(-EINVAL);
245 }
246
247 cpuclk = kzalloc(sizeof(*cpuclk), GFP_KERNEL);
248 if (!cpuclk)
249 return ERR_PTR(-ENOMEM);
250
251 init.name = name;
252 init.parent_names = &parent_names[0];
253 init.num_parents = 1;
254 init.ops = &rockchip_cpuclk_ops;
255
256 /* only allow rate changes when we have a rate table */
257 init.flags = (nrates > 0) ? CLK_SET_RATE_PARENT : 0;
258
259 /* disallow automatic parent changes by ccf */
260 init.flags |= CLK_SET_RATE_NO_REPARENT;
261
262 init.flags |= CLK_GET_RATE_NOCACHE;
263
264 cpuclk->reg_base = reg_base;
265 cpuclk->lock = lock;
266 cpuclk->reg_data = reg_data;
267 cpuclk->clk_nb.notifier_call = rockchip_cpuclk_notifier_cb;
268 cpuclk->hw.init = &init;
269
270 cpuclk->alt_parent = __clk_lookup(parent_names[1]);
271 if (!cpuclk->alt_parent) {
272 pr_err("%s: could not lookup alternate parent\n",
273 __func__);
274 ret = -EINVAL;
275 goto free_cpuclk;
276 }
277
278 ret = clk_prepare_enable(cpuclk->alt_parent);
279 if (ret) {
280 pr_err("%s: could not enable alternate parent\n",
281 __func__);
282 goto free_cpuclk;
283 }
284
285 clk = __clk_lookup(parent_names[0]);
286 if (!clk) {
287 pr_err("%s: could not lookup parent clock %s\n",
288 __func__, parent_names[0]);
289 ret = -EINVAL;
290 goto free_cpuclk;
291 }
292
293 ret = clk_notifier_register(clk, &cpuclk->clk_nb);
294 if (ret) {
295 pr_err("%s: failed to register clock notifier for %s\n",
296 __func__, name);
297 goto free_cpuclk;
298 }
299
300 if (nrates > 0) {
301 cpuclk->rate_count = nrates;
302 cpuclk->rate_table = kmemdup(rates,
303 sizeof(*rates) * nrates,
304 GFP_KERNEL);
305 if (!cpuclk->rate_table) {
306 pr_err("%s: could not allocate memory for cpuclk rates\n",
307 __func__);
308 ret = -ENOMEM;
309 goto unregister_notifier;
310 }
311 }
312
313 cclk = clk_register(NULL, &cpuclk->hw);
314 if (IS_ERR(clk)) {
315 pr_err("%s: could not register cpuclk %s\n", __func__, name);
316 ret = PTR_ERR(clk);
317 goto free_rate_table;
318 }
319
320 return cclk;
321
322free_rate_table:
323 kfree(cpuclk->rate_table);
324unregister_notifier:
325 clk_notifier_unregister(clk, &cpuclk->clk_nb);
326free_cpuclk:
327 kfree(cpuclk);
328 return ERR_PTR(ret);
329}
diff --git a/drivers/clk/rockchip/clk-pll.c b/drivers/clk/rockchip/clk-pll.c
index f2a1c7abf4d9..a3e886a38480 100644
--- a/drivers/clk/rockchip/clk-pll.c
+++ b/drivers/clk/rockchip/clk-pll.c
@@ -34,7 +34,6 @@ struct rockchip_clk_pll {
34 const struct clk_ops *pll_mux_ops; 34 const struct clk_ops *pll_mux_ops;
35 35
36 struct notifier_block clk_nb; 36 struct notifier_block clk_nb;
37 bool rate_change_remuxed;
38 37
39 void __iomem *reg_base; 38 void __iomem *reg_base;
40 int lock_offset; 39 int lock_offset;
@@ -109,38 +108,6 @@ static int rockchip_pll_wait_lock(struct rockchip_clk_pll *pll)
109} 108}
110 109
111/** 110/**
112 * Set pll mux when changing the pll rate.
113 * This makes sure to move the pll mux away from the actual pll before
114 * changing its rate and back to the original parent after the change.
115 */
116static int rockchip_pll_notifier_cb(struct notifier_block *nb,
117 unsigned long event, void *data)
118{
119 struct rockchip_clk_pll *pll = to_rockchip_clk_pll_nb(nb);
120 struct clk_mux *pll_mux = &pll->pll_mux;
121 const struct clk_ops *pll_mux_ops = pll->pll_mux_ops;
122 int cur_parent;
123
124 switch (event) {
125 case PRE_RATE_CHANGE:
126 cur_parent = pll_mux_ops->get_parent(&pll_mux->hw);
127 if (cur_parent == PLL_MODE_NORM) {
128 pll_mux_ops->set_parent(&pll_mux->hw, PLL_MODE_SLOW);
129 pll->rate_change_remuxed = 1;
130 }
131 break;
132 case POST_RATE_CHANGE:
133 if (pll->rate_change_remuxed) {
134 pll_mux_ops->set_parent(&pll_mux->hw, PLL_MODE_NORM);
135 pll->rate_change_remuxed = 0;
136 }
137 break;
138 }
139
140 return NOTIFY_OK;
141}
142
143/**
144 * PLL used in RK3066, RK3188 and RK3288 111 * PLL used in RK3066, RK3188 and RK3288
145 */ 112 */
146 113
@@ -194,6 +161,10 @@ static int rockchip_rk3066_pll_set_rate(struct clk_hw *hw, unsigned long drate,
194 const struct rockchip_pll_rate_table *rate; 161 const struct rockchip_pll_rate_table *rate;
195 unsigned long old_rate = rockchip_rk3066_pll_recalc_rate(hw, prate); 162 unsigned long old_rate = rockchip_rk3066_pll_recalc_rate(hw, prate);
196 struct regmap *grf = rockchip_clk_get_grf(); 163 struct regmap *grf = rockchip_clk_get_grf();
164 struct clk_mux *pll_mux = &pll->pll_mux;
165 const struct clk_ops *pll_mux_ops = pll->pll_mux_ops;
166 int rate_change_remuxed = 0;
167 int cur_parent;
197 int ret; 168 int ret;
198 169
199 if (IS_ERR(grf)) { 170 if (IS_ERR(grf)) {
@@ -216,6 +187,12 @@ static int rockchip_rk3066_pll_set_rate(struct clk_hw *hw, unsigned long drate,
216 pr_debug("%s: rate settings for %lu (nr, no, nf): (%d, %d, %d)\n", 187 pr_debug("%s: rate settings for %lu (nr, no, nf): (%d, %d, %d)\n",
217 __func__, rate->rate, rate->nr, rate->no, rate->nf); 188 __func__, rate->rate, rate->nr, rate->no, rate->nf);
218 189
190 cur_parent = pll_mux_ops->get_parent(&pll_mux->hw);
191 if (cur_parent == PLL_MODE_NORM) {
192 pll_mux_ops->set_parent(&pll_mux->hw, PLL_MODE_SLOW);
193 rate_change_remuxed = 1;
194 }
195
219 /* enter reset mode */ 196 /* enter reset mode */
220 writel(HIWORD_UPDATE(RK3066_PLLCON3_RESET, RK3066_PLLCON3_RESET, 0), 197 writel(HIWORD_UPDATE(RK3066_PLLCON3_RESET, RK3066_PLLCON3_RESET, 0),
221 pll->reg_base + RK3066_PLLCON(3)); 198 pll->reg_base + RK3066_PLLCON(3));
@@ -247,6 +224,9 @@ static int rockchip_rk3066_pll_set_rate(struct clk_hw *hw, unsigned long drate,
247 rockchip_rk3066_pll_set_rate(hw, old_rate, prate); 224 rockchip_rk3066_pll_set_rate(hw, old_rate, prate);
248 } 225 }
249 226
227 if (rate_change_remuxed)
228 pll_mux_ops->set_parent(&pll_mux->hw, PLL_MODE_NORM);
229
250 return ret; 230 return ret;
251} 231}
252 232
@@ -310,7 +290,6 @@ struct clk *rockchip_clk_register_pll(enum rockchip_pll_type pll_type,
310 struct clk_mux *pll_mux; 290 struct clk_mux *pll_mux;
311 struct clk *pll_clk, *mux_clk; 291 struct clk *pll_clk, *mux_clk;
312 char pll_name[20]; 292 char pll_name[20];
313 int ret;
314 293
315 if (num_parents != 2) { 294 if (num_parents != 2) {
316 pr_err("%s: needs two parent clocks\n", __func__); 295 pr_err("%s: needs two parent clocks\n", __func__);
@@ -367,7 +346,6 @@ struct clk *rockchip_clk_register_pll(enum rockchip_pll_type pll_type,
367 pll->lock_offset = grf_lock_offset; 346 pll->lock_offset = grf_lock_offset;
368 pll->lock_shift = lock_shift; 347 pll->lock_shift = lock_shift;
369 pll->lock = lock; 348 pll->lock = lock;
370 pll->clk_nb.notifier_call = rockchip_pll_notifier_cb;
371 349
372 pll_clk = clk_register(NULL, &pll->hw); 350 pll_clk = clk_register(NULL, &pll->hw);
373 if (IS_ERR(pll_clk)) { 351 if (IS_ERR(pll_clk)) {
@@ -377,14 +355,6 @@ struct clk *rockchip_clk_register_pll(enum rockchip_pll_type pll_type,
377 goto err_pll; 355 goto err_pll;
378 } 356 }
379 357
380 ret = clk_notifier_register(pll_clk, &pll->clk_nb);
381 if (ret) {
382 pr_err("%s: failed to register clock notifier for %s : %d\n",
383 __func__, name, ret);
384 mux_clk = ERR_PTR(ret);
385 goto err_pll_notifier;
386 }
387
388 /* create the mux on top of the real pll */ 358 /* create the mux on top of the real pll */
389 pll->pll_mux_ops = &clk_mux_ops; 359 pll->pll_mux_ops = &clk_mux_ops;
390 pll_mux = &pll->pll_mux; 360 pll_mux = &pll->pll_mux;
@@ -417,13 +387,6 @@ struct clk *rockchip_clk_register_pll(enum rockchip_pll_type pll_type,
417 return mux_clk; 387 return mux_clk;
418 388
419err_mux: 389err_mux:
420 ret = clk_notifier_unregister(pll_clk, &pll->clk_nb);
421 if (ret) {
422 pr_err("%s: could not unregister clock notifier in error path : %d\n",
423 __func__, ret);
424 return mux_clk;
425 }
426err_pll_notifier:
427 clk_unregister(pll_clk); 390 clk_unregister(pll_clk);
428err_pll: 391err_pll:
429 kfree(pll); 392 kfree(pll);
diff --git a/drivers/clk/rockchip/clk-rk3188.c b/drivers/clk/rockchip/clk-rk3188.c
index a83a6d8d0fb6..beed49c79126 100644
--- a/drivers/clk/rockchip/clk-rk3188.c
+++ b/drivers/clk/rockchip/clk-rk3188.c
@@ -19,6 +19,7 @@
19#include <dt-bindings/clock/rk3188-cru-common.h> 19#include <dt-bindings/clock/rk3188-cru-common.h>
20#include "clk.h" 20#include "clk.h"
21 21
22#define RK3066_GRF_SOC_STATUS 0x15c
22#define RK3188_GRF_SOC_STATUS 0xac 23#define RK3188_GRF_SOC_STATUS 0xac
23 24
24enum rk3188_plls { 25enum rk3188_plls {
@@ -100,6 +101,98 @@ struct rockchip_pll_rate_table rk3188_pll_rates[] = {
100 { /* sentinel */ }, 101 { /* sentinel */ },
101}; 102};
102 103
104#define RK3066_DIV_CORE_PERIPH_MASK 0x3
105#define RK3066_DIV_CORE_PERIPH_SHIFT 6
106#define RK3066_DIV_ACLK_CORE_MASK 0x7
107#define RK3066_DIV_ACLK_CORE_SHIFT 0
108#define RK3066_DIV_ACLK_HCLK_MASK 0x3
109#define RK3066_DIV_ACLK_HCLK_SHIFT 8
110#define RK3066_DIV_ACLK_PCLK_MASK 0x3
111#define RK3066_DIV_ACLK_PCLK_SHIFT 12
112#define RK3066_DIV_AHB2APB_MASK 0x3
113#define RK3066_DIV_AHB2APB_SHIFT 14
114
115#define RK3066_CLKSEL0(_core_peri) \
116 { \
117 .reg = RK2928_CLKSEL_CON(0), \
118 .val = HIWORD_UPDATE(_core_peri, RK3066_DIV_CORE_PERIPH_MASK, \
119 RK3066_DIV_CORE_PERIPH_SHIFT) \
120 }
121#define RK3066_CLKSEL1(_aclk_core, _aclk_hclk, _aclk_pclk, _ahb2apb) \
122 { \
123 .reg = RK2928_CLKSEL_CON(1), \
124 .val = HIWORD_UPDATE(_aclk_core, RK3066_DIV_ACLK_CORE_MASK, \
125 RK3066_DIV_ACLK_CORE_SHIFT) | \
126 HIWORD_UPDATE(_aclk_hclk, RK3066_DIV_ACLK_HCLK_MASK, \
127 RK3066_DIV_ACLK_HCLK_SHIFT) | \
128 HIWORD_UPDATE(_aclk_pclk, RK3066_DIV_ACLK_PCLK_MASK, \
129 RK3066_DIV_ACLK_PCLK_SHIFT) | \
130 HIWORD_UPDATE(_ahb2apb, RK3066_DIV_AHB2APB_MASK, \
131 RK3066_DIV_AHB2APB_SHIFT), \
132 }
133
134#define RK3066_CPUCLK_RATE(_prate, _core_peri, _acore, _ahclk, _apclk, _h2p) \
135 { \
136 .prate = _prate, \
137 .divs = { \
138 RK3066_CLKSEL0(_core_peri), \
139 RK3066_CLKSEL1(_acore, _ahclk, _apclk, _h2p), \
140 }, \
141 }
142
143static struct rockchip_cpuclk_rate_table rk3066_cpuclk_rates[] __initdata = {
144 RK3066_CPUCLK_RATE(1416000000, 2, 3, 1, 2, 1),
145 RK3066_CPUCLK_RATE(1200000000, 2, 3, 1, 2, 1),
146 RK3066_CPUCLK_RATE(1008000000, 2, 2, 1, 2, 1),
147 RK3066_CPUCLK_RATE( 816000000, 2, 2, 1, 2, 1),
148 RK3066_CPUCLK_RATE( 600000000, 1, 2, 1, 2, 1),
149 RK3066_CPUCLK_RATE( 504000000, 1, 1, 1, 2, 1),
150 RK3066_CPUCLK_RATE( 312000000, 0, 1, 1, 1, 0),
151};
152
153static const struct rockchip_cpuclk_reg_data rk3066_cpuclk_data = {
154 .core_reg = RK2928_CLKSEL_CON(0),
155 .div_core_shift = 0,
156 .div_core_mask = 0x1f,
157 .mux_core_shift = 8,
158};
159
160#define RK3188_DIV_ACLK_CORE_MASK 0x7
161#define RK3188_DIV_ACLK_CORE_SHIFT 3
162
163#define RK3188_CLKSEL1(_aclk_core) \
164 { \
165 .reg = RK2928_CLKSEL_CON(1), \
166 .val = HIWORD_UPDATE(_aclk_core, RK3188_DIV_ACLK_CORE_MASK,\
167 RK3188_DIV_ACLK_CORE_SHIFT) \
168 }
169#define RK3188_CPUCLK_RATE(_prate, _core_peri, _aclk_core) \
170 { \
171 .prate = _prate, \
172 .divs = { \
173 RK3066_CLKSEL0(_core_peri), \
174 RK3188_CLKSEL1(_aclk_core), \
175 }, \
176 }
177
178static struct rockchip_cpuclk_rate_table rk3188_cpuclk_rates[] __initdata = {
179 RK3188_CPUCLK_RATE(1608000000, 2, 3),
180 RK3188_CPUCLK_RATE(1416000000, 2, 3),
181 RK3188_CPUCLK_RATE(1200000000, 2, 3),
182 RK3188_CPUCLK_RATE(1008000000, 2, 3),
183 RK3188_CPUCLK_RATE( 816000000, 2, 3),
184 RK3188_CPUCLK_RATE( 600000000, 1, 3),
185 RK3188_CPUCLK_RATE( 504000000, 1, 3),
186 RK3188_CPUCLK_RATE( 312000000, 0, 1),
187};
188
189static const struct rockchip_cpuclk_reg_data rk3188_cpuclk_data = {
190 .core_reg = RK2928_CLKSEL_CON(0),
191 .div_core_shift = 9,
192 .div_core_mask = 0x1f,
193 .mux_core_shift = 8,
194};
195
103PNAME(mux_pll_p) = { "xin24m", "xin32k" }; 196PNAME(mux_pll_p) = { "xin24m", "xin32k" };
104PNAME(mux_armclk_p) = { "apll", "gpll_armclk" }; 197PNAME(mux_armclk_p) = { "apll", "gpll_armclk" };
105PNAME(mux_ddrphy_p) = { "dpll", "gpll_ddr" }; 198PNAME(mux_ddrphy_p) = { "dpll", "gpll_ddr" };
@@ -173,17 +266,10 @@ static struct rockchip_clk_branch common_clk_branches[] __initdata = {
173 GATE(0, "aclk_cpu", "aclk_cpu_pre", 0, 266 GATE(0, "aclk_cpu", "aclk_cpu_pre", 0,
174 RK2928_CLKGATE_CON(0), 3, GFLAGS), 267 RK2928_CLKGATE_CON(0), 3, GFLAGS),
175 268
176 DIV(0, "pclk_cpu_pre", "aclk_cpu_pre", 0,
177 RK2928_CLKSEL_CON(1), 12, 2, DFLAGS | CLK_DIVIDER_POWER_OF_TWO),
178 GATE(0, "atclk_cpu", "pclk_cpu_pre", 0, 269 GATE(0, "atclk_cpu", "pclk_cpu_pre", 0,
179 RK2928_CLKGATE_CON(0), 6, GFLAGS), 270 RK2928_CLKGATE_CON(0), 6, GFLAGS),
180 GATE(0, "pclk_cpu", "pclk_cpu_pre", 0, 271 GATE(0, "pclk_cpu", "pclk_cpu_pre", 0,
181 RK2928_CLKGATE_CON(0), 5, GFLAGS), 272 RK2928_CLKGATE_CON(0), 5, GFLAGS),
182 DIV(0, "hclk_cpu_pre", "aclk_cpu_pre", 0,
183 RK2928_CLKSEL_CON(1), 8, 2, DFLAGS | CLK_DIVIDER_POWER_OF_TWO),
184 COMPOSITE_NOMUX(0, "hclk_ahb2apb", "hclk_cpu_pre", 0,
185 RK2928_CLKSEL_CON(1), 14, 2, DFLAGS | CLK_DIVIDER_POWER_OF_TWO,
186 RK2928_CLKGATE_CON(4), 9, GFLAGS),
187 GATE(0, "hclk_cpu", "hclk_cpu_pre", 0, 273 GATE(0, "hclk_cpu", "hclk_cpu_pre", 0,
188 RK2928_CLKGATE_CON(0), 4, GFLAGS), 274 RK2928_CLKGATE_CON(0), 4, GFLAGS),
189 275
@@ -412,10 +498,18 @@ static struct clk_div_table div_aclk_cpu_t[] = {
412}; 498};
413 499
414static struct rockchip_clk_branch rk3066a_clk_branches[] __initdata = { 500static struct rockchip_clk_branch rk3066a_clk_branches[] __initdata = {
415 COMPOSITE_NOGATE(0, "armclk", mux_armclk_p, 0,
416 RK2928_CLKSEL_CON(0), 8, 1, MFLAGS, 0, 5, DFLAGS),
417 DIVTBL(0, "aclk_cpu_pre", "armclk", 0, 501 DIVTBL(0, "aclk_cpu_pre", "armclk", 0,
418 RK2928_CLKSEL_CON(1), 0, 3, DFLAGS, div_aclk_cpu_t), 502 RK2928_CLKSEL_CON(1), 0, 3, DFLAGS | CLK_DIVIDER_READ_ONLY, div_aclk_cpu_t),
503 DIV(0, "pclk_cpu_pre", "aclk_cpu_pre", 0,
504 RK2928_CLKSEL_CON(1), 12, 2, DFLAGS | CLK_DIVIDER_POWER_OF_TWO
505 | CLK_DIVIDER_READ_ONLY),
506 DIV(0, "hclk_cpu_pre", "aclk_cpu_pre", 0,
507 RK2928_CLKSEL_CON(1), 8, 2, DFLAGS | CLK_DIVIDER_POWER_OF_TWO
508 | CLK_DIVIDER_READ_ONLY),
509 COMPOSITE_NOMUX(0, "hclk_ahb2apb", "hclk_cpu_pre", 0,
510 RK2928_CLKSEL_CON(1), 14, 2, DFLAGS | CLK_DIVIDER_POWER_OF_TWO
511 | CLK_DIVIDER_READ_ONLY,
512 RK2928_CLKGATE_CON(4), 9, GFLAGS),
419 513
420 GATE(CORE_L2C, "core_l2c", "aclk_cpu", 0, 514 GATE(CORE_L2C, "core_l2c", "aclk_cpu", 0,
421 RK2928_CLKGATE_CON(9), 4, GFLAGS), 515 RK2928_CLKGATE_CON(9), 4, GFLAGS),
@@ -524,8 +618,6 @@ PNAME(mux_hsicphy_p) = { "sclk_otgphy0", "sclk_otgphy1",
524 "gpll", "cpll" }; 618 "gpll", "cpll" };
525 619
526static struct rockchip_clk_branch rk3188_clk_branches[] __initdata = { 620static struct rockchip_clk_branch rk3188_clk_branches[] __initdata = {
527 COMPOSITE_NOGATE(0, "armclk", mux_armclk_p, 0,
528 RK2928_CLKSEL_CON(0), 8, 1, MFLAGS, 9, 5, DFLAGS),
529 COMPOSITE_NOMUX_DIVTBL(0, "aclk_core", "armclk", 0, 621 COMPOSITE_NOMUX_DIVTBL(0, "aclk_core", "armclk", 0,
530 RK2928_CLKSEL_CON(1), 3, 3, DFLAGS | CLK_DIVIDER_READ_ONLY, 622 RK2928_CLKSEL_CON(1), 3, 3, DFLAGS | CLK_DIVIDER_READ_ONLY,
531 div_rk3188_aclk_core_t, RK2928_CLKGATE_CON(0), 7, GFLAGS), 623 div_rk3188_aclk_core_t, RK2928_CLKGATE_CON(0), 7, GFLAGS),
@@ -533,6 +625,13 @@ static struct rockchip_clk_branch rk3188_clk_branches[] __initdata = {
533 /* do not source aclk_cpu_pre from the apll, to keep complexity down */ 625 /* do not source aclk_cpu_pre from the apll, to keep complexity down */
534 COMPOSITE_NOGATE(0, "aclk_cpu_pre", mux_aclk_cpu_p, CLK_SET_RATE_NO_REPARENT, 626 COMPOSITE_NOGATE(0, "aclk_cpu_pre", mux_aclk_cpu_p, CLK_SET_RATE_NO_REPARENT,
535 RK2928_CLKSEL_CON(0), 5, 1, MFLAGS, 0, 5, DFLAGS), 627 RK2928_CLKSEL_CON(0), 5, 1, MFLAGS, 0, 5, DFLAGS),
628 DIV(0, "pclk_cpu_pre", "aclk_cpu_pre", 0,
629 RK2928_CLKSEL_CON(1), 12, 2, DFLAGS | CLK_DIVIDER_POWER_OF_TWO),
630 DIV(0, "hclk_cpu_pre", "aclk_cpu_pre", 0,
631 RK2928_CLKSEL_CON(1), 8, 2, DFLAGS | CLK_DIVIDER_POWER_OF_TWO),
632 COMPOSITE_NOMUX(0, "hclk_ahb2apb", "hclk_cpu_pre", 0,
633 RK2928_CLKSEL_CON(1), 14, 2, DFLAGS | CLK_DIVIDER_POWER_OF_TWO,
634 RK2928_CLKGATE_CON(4), 9, GFLAGS),
536 635
537 GATE(CORE_L2C, "core_l2c", "armclk", 0, 636 GATE(CORE_L2C, "core_l2c", "armclk", 0,
538 RK2928_CLKGATE_CON(9), 4, GFLAGS), 637 RK2928_CLKGATE_CON(9), 4, GFLAGS),
@@ -599,6 +698,12 @@ static struct rockchip_clk_branch rk3188_clk_branches[] __initdata = {
599 GATE(ACLK_GPS, "aclk_gps", "aclk_peri", 0, RK2928_CLKGATE_CON(8), 13, GFLAGS), 698 GATE(ACLK_GPS, "aclk_gps", "aclk_peri", 0, RK2928_CLKGATE_CON(8), 13, GFLAGS),
600}; 699};
601 700
701static const char *rk3188_critical_clocks[] __initconst = {
702 "aclk_cpu",
703 "aclk_peri",
704 "hclk_peri",
705};
706
602static void __init rk3188_common_clk_init(struct device_node *np) 707static void __init rk3188_common_clk_init(struct device_node *np)
603{ 708{
604 void __iomem *reg_base; 709 void __iomem *reg_base;
@@ -623,29 +728,65 @@ static void __init rk3188_common_clk_init(struct device_node *np)
623 pr_warn("%s: could not register clock usb480m: %ld\n", 728 pr_warn("%s: could not register clock usb480m: %ld\n",
624 __func__, PTR_ERR(clk)); 729 __func__, PTR_ERR(clk));
625 730
626 rockchip_clk_register_plls(rk3188_pll_clks,
627 ARRAY_SIZE(rk3188_pll_clks),
628 RK3188_GRF_SOC_STATUS);
629 rockchip_clk_register_branches(common_clk_branches, 731 rockchip_clk_register_branches(common_clk_branches,
630 ARRAY_SIZE(common_clk_branches)); 732 ARRAY_SIZE(common_clk_branches));
733 rockchip_clk_protect_critical(rk3188_critical_clocks,
734 ARRAY_SIZE(rk3188_critical_clocks));
631 735
632 rockchip_register_softrst(np, 9, reg_base + RK2928_SOFTRST_CON(0), 736 rockchip_register_softrst(np, 9, reg_base + RK2928_SOFTRST_CON(0),
633 ROCKCHIP_SOFTRST_HIWORD_MASK); 737 ROCKCHIP_SOFTRST_HIWORD_MASK);
738
739 rockchip_register_restart_notifier(RK2928_GLB_SRST_FST);
634} 740}
635 741
636static void __init rk3066a_clk_init(struct device_node *np) 742static void __init rk3066a_clk_init(struct device_node *np)
637{ 743{
638 rk3188_common_clk_init(np); 744 rk3188_common_clk_init(np);
745 rockchip_clk_register_plls(rk3188_pll_clks,
746 ARRAY_SIZE(rk3188_pll_clks),
747 RK3066_GRF_SOC_STATUS);
639 rockchip_clk_register_branches(rk3066a_clk_branches, 748 rockchip_clk_register_branches(rk3066a_clk_branches,
640 ARRAY_SIZE(rk3066a_clk_branches)); 749 ARRAY_SIZE(rk3066a_clk_branches));
750 rockchip_clk_register_armclk(ARMCLK, "armclk",
751 mux_armclk_p, ARRAY_SIZE(mux_armclk_p),
752 &rk3066_cpuclk_data, rk3066_cpuclk_rates,
753 ARRAY_SIZE(rk3066_cpuclk_rates));
641} 754}
642CLK_OF_DECLARE(rk3066a_cru, "rockchip,rk3066a-cru", rk3066a_clk_init); 755CLK_OF_DECLARE(rk3066a_cru, "rockchip,rk3066a-cru", rk3066a_clk_init);
643 756
644static void __init rk3188a_clk_init(struct device_node *np) 757static void __init rk3188a_clk_init(struct device_node *np)
645{ 758{
759 struct clk *clk1, *clk2;
760 unsigned long rate;
761 int ret;
762
646 rk3188_common_clk_init(np); 763 rk3188_common_clk_init(np);
764 rockchip_clk_register_plls(rk3188_pll_clks,
765 ARRAY_SIZE(rk3188_pll_clks),
766 RK3188_GRF_SOC_STATUS);
647 rockchip_clk_register_branches(rk3188_clk_branches, 767 rockchip_clk_register_branches(rk3188_clk_branches,
648 ARRAY_SIZE(rk3188_clk_branches)); 768 ARRAY_SIZE(rk3188_clk_branches));
769 rockchip_clk_register_armclk(ARMCLK, "armclk",
770 mux_armclk_p, ARRAY_SIZE(mux_armclk_p),
771 &rk3188_cpuclk_data, rk3188_cpuclk_rates,
772 ARRAY_SIZE(rk3188_cpuclk_rates));
773
774 /* reparent aclk_cpu_pre from apll */
775 clk1 = __clk_lookup("aclk_cpu_pre");
776 clk2 = __clk_lookup("gpll");
777 if (clk1 && clk2) {
778 rate = clk_get_rate(clk1);
779
780 ret = clk_set_parent(clk1, clk2);
781 if (ret < 0)
782 pr_warn("%s: could not reparent aclk_cpu_pre to gpll\n",
783 __func__);
784
785 clk_set_rate(clk1, rate);
786 } else {
787 pr_warn("%s: missing clocks to reparent aclk_cpu_pre to gpll\n",
788 __func__);
789 }
649} 790}
650CLK_OF_DECLARE(rk3188a_cru, "rockchip,rk3188a-cru", rk3188a_clk_init); 791CLK_OF_DECLARE(rk3188a_cru, "rockchip,rk3188a-cru", rk3188a_clk_init);
651 792
diff --git a/drivers/clk/rockchip/clk-rk3288.c b/drivers/clk/rockchip/clk-rk3288.c
index b22a2d2f21e9..23278291da44 100644
--- a/drivers/clk/rockchip/clk-rk3288.c
+++ b/drivers/clk/rockchip/clk-rk3288.c
@@ -20,7 +20,7 @@
20#include "clk.h" 20#include "clk.h"
21 21
22#define RK3288_GRF_SOC_CON(x) (0x244 + x * 4) 22#define RK3288_GRF_SOC_CON(x) (0x244 + x * 4)
23#define RK3288_GRF_SOC_STATUS 0x280 23#define RK3288_GRF_SOC_STATUS1 0x284
24 24
25enum rk3288_plls { 25enum rk3288_plls {
26 apll, dpll, cpll, gpll, npll, 26 apll, dpll, cpll, gpll, npll,
@@ -101,6 +101,70 @@ struct rockchip_pll_rate_table rk3288_pll_rates[] = {
101 { /* sentinel */ }, 101 { /* sentinel */ },
102}; 102};
103 103
104#define RK3288_DIV_ACLK_CORE_M0_MASK 0xf
105#define RK3288_DIV_ACLK_CORE_M0_SHIFT 0
106#define RK3288_DIV_ACLK_CORE_MP_MASK 0xf
107#define RK3288_DIV_ACLK_CORE_MP_SHIFT 4
108#define RK3288_DIV_L2RAM_MASK 0x7
109#define RK3288_DIV_L2RAM_SHIFT 0
110#define RK3288_DIV_ATCLK_MASK 0x1f
111#define RK3288_DIV_ATCLK_SHIFT 4
112#define RK3288_DIV_PCLK_DBGPRE_MASK 0x1f
113#define RK3288_DIV_PCLK_DBGPRE_SHIFT 9
114
115#define RK3288_CLKSEL0(_core_m0, _core_mp) \
116 { \
117 .reg = RK3288_CLKSEL_CON(0), \
118 .val = HIWORD_UPDATE(_core_m0, RK3288_DIV_ACLK_CORE_M0_MASK, \
119 RK3288_DIV_ACLK_CORE_M0_SHIFT) | \
120 HIWORD_UPDATE(_core_mp, RK3288_DIV_ACLK_CORE_MP_MASK, \
121 RK3288_DIV_ACLK_CORE_MP_SHIFT), \
122 }
123#define RK3288_CLKSEL37(_l2ram, _atclk, _pclk_dbg_pre) \
124 { \
125 .reg = RK3288_CLKSEL_CON(37), \
126 .val = HIWORD_UPDATE(_l2ram, RK3288_DIV_L2RAM_MASK, \
127 RK3288_DIV_L2RAM_SHIFT) | \
128 HIWORD_UPDATE(_atclk, RK3288_DIV_ATCLK_MASK, \
129 RK3288_DIV_ATCLK_SHIFT) | \
130 HIWORD_UPDATE(_pclk_dbg_pre, \
131 RK3288_DIV_PCLK_DBGPRE_MASK, \
132 RK3288_DIV_PCLK_DBGPRE_SHIFT), \
133 }
134
135#define RK3288_CPUCLK_RATE(_prate, _core_m0, _core_mp, _l2ram, _atclk, _pdbg) \
136 { \
137 .prate = _prate, \
138 .divs = { \
139 RK3288_CLKSEL0(_core_m0, _core_mp), \
140 RK3288_CLKSEL37(_l2ram, _atclk, _pdbg), \
141 }, \
142 }
143
144static struct rockchip_cpuclk_rate_table rk3288_cpuclk_rates[] __initdata = {
145 RK3288_CPUCLK_RATE(1800000000, 2, 4, 2, 4, 4),
146 RK3288_CPUCLK_RATE(1704000000, 2, 4, 2, 4, 4),
147 RK3288_CPUCLK_RATE(1608000000, 2, 4, 2, 4, 4),
148 RK3288_CPUCLK_RATE(1512000000, 2, 4, 2, 4, 4),
149 RK3288_CPUCLK_RATE(1416000000, 2, 4, 2, 4, 4),
150 RK3288_CPUCLK_RATE(1200000000, 2, 4, 2, 4, 4),
151 RK3288_CPUCLK_RATE(1008000000, 2, 4, 2, 4, 4),
152 RK3288_CPUCLK_RATE( 816000000, 2, 4, 2, 4, 4),
153 RK3288_CPUCLK_RATE( 696000000, 2, 4, 2, 4, 4),
154 RK3288_CPUCLK_RATE( 600000000, 2, 4, 2, 4, 4),
155 RK3288_CPUCLK_RATE( 408000000, 2, 4, 2, 4, 4),
156 RK3288_CPUCLK_RATE( 312000000, 2, 4, 2, 4, 4),
157 RK3288_CPUCLK_RATE( 216000000, 2, 4, 2, 4, 4),
158 RK3288_CPUCLK_RATE( 126000000, 2, 4, 2, 4, 4),
159};
160
161static const struct rockchip_cpuclk_reg_data rk3288_cpuclk_data = {
162 .core_reg = RK3288_CLKSEL_CON(0),
163 .div_core_shift = 8,
164 .div_core_mask = 0x1f,
165 .mux_core_shift = 15,
166};
167
104PNAME(mux_pll_p) = { "xin24m", "xin32k" }; 168PNAME(mux_pll_p) = { "xin24m", "xin32k" };
105PNAME(mux_armclk_p) = { "apll_core", "gpll_core" }; 169PNAME(mux_armclk_p) = { "apll_core", "gpll_core" };
106PNAME(mux_ddrphy_p) = { "dpll_ddr", "gpll_ddr" }; 170PNAME(mux_ddrphy_p) = { "dpll_ddr", "gpll_ddr" };
@@ -143,7 +207,7 @@ static struct rockchip_pll_clock rk3288_pll_clks[] __initdata = {
143 [gpll] = PLL(pll_rk3066, PLL_GPLL, "gpll", mux_pll_p, 0, RK3288_PLL_CON(12), 207 [gpll] = PLL(pll_rk3066, PLL_GPLL, "gpll", mux_pll_p, 0, RK3288_PLL_CON(12),
144 RK3288_MODE_CON, 12, 8, rk3288_pll_rates), 208 RK3288_MODE_CON, 12, 8, rk3288_pll_rates),
145 [npll] = PLL(pll_rk3066, PLL_NPLL, "npll", mux_pll_p, 0, RK3288_PLL_CON(16), 209 [npll] = PLL(pll_rk3066, PLL_NPLL, "npll", mux_pll_p, 0, RK3288_PLL_CON(16),
146 RK3288_MODE_CON, 14, 9, NULL), 210 RK3288_MODE_CON, 14, 9, rk3288_pll_rates),
147}; 211};
148 212
149static struct clk_div_table div_hclk_cpu_t[] = { 213static struct clk_div_table div_hclk_cpu_t[] = {
@@ -166,35 +230,33 @@ static struct rockchip_clk_branch rk3288_clk_branches[] __initdata = {
166 RK3288_CLKGATE_CON(0), 1, GFLAGS), 230 RK3288_CLKGATE_CON(0), 1, GFLAGS),
167 GATE(0, "gpll_core", "gpll", 0, 231 GATE(0, "gpll_core", "gpll", 0,
168 RK3288_CLKGATE_CON(0), 2, GFLAGS), 232 RK3288_CLKGATE_CON(0), 2, GFLAGS),
169 COMPOSITE_NOGATE(0, "armclk", mux_armclk_p, 0,
170 RK3288_CLKSEL_CON(0), 15, 1, MFLAGS, 8, 5, DFLAGS),
171 233
172 COMPOSITE_NOMUX(0, "armcore0", "armclk", 0, 234 COMPOSITE_NOMUX(0, "armcore0", "armclk", 0,
173 RK3288_CLKSEL_CON(36), 0, 3, DFLAGS, 235 RK3288_CLKSEL_CON(36), 0, 3, DFLAGS | CLK_DIVIDER_READ_ONLY,
174 RK3288_CLKGATE_CON(12), 0, GFLAGS), 236 RK3288_CLKGATE_CON(12), 0, GFLAGS),
175 COMPOSITE_NOMUX(0, "armcore1", "armclk", 0, 237 COMPOSITE_NOMUX(0, "armcore1", "armclk", 0,
176 RK3288_CLKSEL_CON(36), 4, 3, DFLAGS, 238 RK3288_CLKSEL_CON(36), 4, 3, DFLAGS | CLK_DIVIDER_READ_ONLY,
177 RK3288_CLKGATE_CON(12), 1, GFLAGS), 239 RK3288_CLKGATE_CON(12), 1, GFLAGS),
178 COMPOSITE_NOMUX(0, "armcore2", "armclk", 0, 240 COMPOSITE_NOMUX(0, "armcore2", "armclk", 0,
179 RK3288_CLKSEL_CON(36), 8, 3, DFLAGS, 241 RK3288_CLKSEL_CON(36), 8, 3, DFLAGS | CLK_DIVIDER_READ_ONLY,
180 RK3288_CLKGATE_CON(12), 2, GFLAGS), 242 RK3288_CLKGATE_CON(12), 2, GFLAGS),
181 COMPOSITE_NOMUX(0, "armcore3", "armclk", 0, 243 COMPOSITE_NOMUX(0, "armcore3", "armclk", 0,
182 RK3288_CLKSEL_CON(36), 12, 3, DFLAGS, 244 RK3288_CLKSEL_CON(36), 12, 3, DFLAGS | CLK_DIVIDER_READ_ONLY,
183 RK3288_CLKGATE_CON(12), 3, GFLAGS), 245 RK3288_CLKGATE_CON(12), 3, GFLAGS),
184 COMPOSITE_NOMUX(0, "l2ram", "armclk", 0, 246 COMPOSITE_NOMUX(0, "l2ram", "armclk", 0,
185 RK3288_CLKSEL_CON(37), 0, 3, DFLAGS, 247 RK3288_CLKSEL_CON(37), 0, 3, DFLAGS | CLK_DIVIDER_READ_ONLY,
186 RK3288_CLKGATE_CON(12), 4, GFLAGS), 248 RK3288_CLKGATE_CON(12), 4, GFLAGS),
187 COMPOSITE_NOMUX(0, "aclk_core_m0", "armclk", 0, 249 COMPOSITE_NOMUX(0, "aclk_core_m0", "armclk", 0,
188 RK3288_CLKSEL_CON(0), 0, 4, DFLAGS, 250 RK3288_CLKSEL_CON(0), 0, 4, DFLAGS | CLK_DIVIDER_READ_ONLY,
189 RK3288_CLKGATE_CON(12), 5, GFLAGS), 251 RK3288_CLKGATE_CON(12), 5, GFLAGS),
190 COMPOSITE_NOMUX(0, "aclk_core_mp", "armclk", 0, 252 COMPOSITE_NOMUX(0, "aclk_core_mp", "armclk", 0,
191 RK3288_CLKSEL_CON(0), 4, 4, DFLAGS, 253 RK3288_CLKSEL_CON(0), 4, 4, DFLAGS | CLK_DIVIDER_READ_ONLY,
192 RK3288_CLKGATE_CON(12), 6, GFLAGS), 254 RK3288_CLKGATE_CON(12), 6, GFLAGS),
193 COMPOSITE_NOMUX(0, "atclk", "armclk", 0, 255 COMPOSITE_NOMUX(0, "atclk", "armclk", 0,
194 RK3288_CLKSEL_CON(37), 4, 5, DFLAGS, 256 RK3288_CLKSEL_CON(37), 4, 5, DFLAGS | CLK_DIVIDER_READ_ONLY,
195 RK3288_CLKGATE_CON(12), 7, GFLAGS), 257 RK3288_CLKGATE_CON(12), 7, GFLAGS),
196 COMPOSITE_NOMUX(0, "pclk_dbg_pre", "armclk", 0, 258 COMPOSITE_NOMUX(0, "pclk_dbg_pre", "armclk", 0,
197 RK3288_CLKSEL_CON(37), 9, 5, DFLAGS, 259 RK3288_CLKSEL_CON(37), 9, 5, DFLAGS | CLK_DIVIDER_READ_ONLY,
198 RK3288_CLKGATE_CON(12), 8, GFLAGS), 260 RK3288_CLKGATE_CON(12), 8, GFLAGS),
199 GATE(0, "pclk_dbg", "pclk_dbg_pre", 0, 261 GATE(0, "pclk_dbg", "pclk_dbg_pre", 0,
200 RK3288_CLKGATE_CON(12), 9, GFLAGS), 262 RK3288_CLKGATE_CON(12), 9, GFLAGS),
@@ -219,12 +281,12 @@ static struct rockchip_clk_branch rk3288_clk_branches[] __initdata = {
219 RK3288_CLKSEL_CON(1), 15, 1, MFLAGS, 3, 5, DFLAGS), 281 RK3288_CLKSEL_CON(1), 15, 1, MFLAGS, 3, 5, DFLAGS),
220 DIV(0, "aclk_cpu_pre", "aclk_cpu_src", 0, 282 DIV(0, "aclk_cpu_pre", "aclk_cpu_src", 0,
221 RK3288_CLKSEL_CON(1), 0, 3, DFLAGS), 283 RK3288_CLKSEL_CON(1), 0, 3, DFLAGS),
222 GATE(0, "aclk_cpu", "aclk_cpu_pre", 0, 284 GATE(ACLK_CPU, "aclk_cpu", "aclk_cpu_pre", 0,
223 RK3288_CLKGATE_CON(0), 3, GFLAGS), 285 RK3288_CLKGATE_CON(0), 3, GFLAGS),
224 COMPOSITE_NOMUX(0, "pclk_cpu", "aclk_cpu_pre", 0, 286 COMPOSITE_NOMUX(PCLK_CPU, "pclk_cpu", "aclk_cpu_pre", 0,
225 RK3288_CLKSEL_CON(1), 12, 3, DFLAGS, 287 RK3288_CLKSEL_CON(1), 12, 3, DFLAGS,
226 RK3288_CLKGATE_CON(0), 5, GFLAGS), 288 RK3288_CLKGATE_CON(0), 5, GFLAGS),
227 COMPOSITE_NOMUX_DIVTBL(0, "hclk_cpu", "aclk_cpu_pre", 0, 289 COMPOSITE_NOMUX_DIVTBL(HCLK_CPU, "hclk_cpu", "aclk_cpu_pre", 0,
228 RK3288_CLKSEL_CON(1), 8, 2, DFLAGS, div_hclk_cpu_t, 290 RK3288_CLKSEL_CON(1), 8, 2, DFLAGS, div_hclk_cpu_t,
229 RK3288_CLKGATE_CON(0), 4, GFLAGS), 291 RK3288_CLKGATE_CON(0), 4, GFLAGS),
230 GATE(0, "c2c_host", "aclk_cpu_src", 0, 292 GATE(0, "c2c_host", "aclk_cpu_src", 0,
@@ -238,15 +300,15 @@ static struct rockchip_clk_branch rk3288_clk_branches[] __initdata = {
238 COMPOSITE(0, "i2s_src", mux_pll_src_cpll_gpll_p, 0, 300 COMPOSITE(0, "i2s_src", mux_pll_src_cpll_gpll_p, 0,
239 RK3288_CLKSEL_CON(4), 15, 1, MFLAGS, 0, 7, DFLAGS, 301 RK3288_CLKSEL_CON(4), 15, 1, MFLAGS, 0, 7, DFLAGS,
240 RK3288_CLKGATE_CON(4), 1, GFLAGS), 302 RK3288_CLKGATE_CON(4), 1, GFLAGS),
241 COMPOSITE_FRAC(0, "i2s_frac", "i2s_src", 0, 303 COMPOSITE_FRAC(0, "i2s_frac", "i2s_src", CLK_SET_RATE_PARENT,
242 RK3288_CLKSEL_CON(8), 0, 304 RK3288_CLKSEL_CON(8), 0,
243 RK3288_CLKGATE_CON(4), 2, GFLAGS), 305 RK3288_CLKGATE_CON(4), 2, GFLAGS),
244 MUX(0, "i2s_pre", mux_i2s_pre_p, 0, 306 MUX(0, "i2s_pre", mux_i2s_pre_p, CLK_SET_RATE_PARENT,
245 RK3288_CLKSEL_CON(4), 8, 2, MFLAGS), 307 RK3288_CLKSEL_CON(4), 8, 2, MFLAGS),
246 COMPOSITE_NODIV(0, "i2s0_clkout", mux_i2s_clkout_p, 0, 308 COMPOSITE_NODIV(0, "i2s0_clkout", mux_i2s_clkout_p, CLK_SET_RATE_PARENT,
247 RK3288_CLKSEL_CON(4), 12, 1, MFLAGS, 309 RK3288_CLKSEL_CON(4), 12, 1, MFLAGS,
248 RK3288_CLKGATE_CON(4), 0, GFLAGS), 310 RK3288_CLKGATE_CON(4), 0, GFLAGS),
249 GATE(SCLK_I2S0, "sclk_i2s0", "i2s_pre", 0, 311 GATE(SCLK_I2S0, "sclk_i2s0", "i2s_pre", CLK_SET_RATE_PARENT,
250 RK3288_CLKGATE_CON(4), 3, GFLAGS), 312 RK3288_CLKGATE_CON(4), 3, GFLAGS),
251 313
252 MUX(0, "spdif_src", mux_pll_src_cpll_gpll_p, 0, 314 MUX(0, "spdif_src", mux_pll_src_cpll_gpll_p, 0,
@@ -296,6 +358,20 @@ static struct rockchip_clk_branch rk3288_clk_branches[] __initdata = {
296 COMPOSITE(0, "aclk_vdpu", mux_pll_src_cpll_gpll_usb480m_p, 0, 358 COMPOSITE(0, "aclk_vdpu", mux_pll_src_cpll_gpll_usb480m_p, 0,
297 RK3288_CLKSEL_CON(32), 14, 2, MFLAGS, 8, 5, DFLAGS, 359 RK3288_CLKSEL_CON(32), 14, 2, MFLAGS, 8, 5, DFLAGS,
298 RK3288_CLKGATE_CON(3), 11, GFLAGS), 360 RK3288_CLKGATE_CON(3), 11, GFLAGS),
361 /*
362 * We use aclk_vdpu by default GRF_SOC_CON0[7] setting in system,
363 * so we ignore the mux and make clocks nodes as following,
364 */
365 GATE(ACLK_VCODEC, "aclk_vcodec", "aclk_vdpu", 0,
366 RK3288_CLKGATE_CON(9), 0, GFLAGS),
367 /*
368 * We introduce a virtul node of hclk_vodec_pre_v to split one clock
369 * struct with a gate and a fix divider into two node in software.
370 */
371 GATE(0, "hclk_vcodec_pre_v", "aclk_vdpu", 0,
372 RK3288_CLKGATE_CON(3), 10, GFLAGS),
373 GATE(HCLK_VCODEC, "hclk_vcodec", "hclk_vcodec_pre", 0,
374 RK3288_CLKGATE_CON(9), 1, GFLAGS),
299 375
300 COMPOSITE(0, "aclk_vio0", mux_pll_src_cpll_gpll_usb480m_p, 0, 376 COMPOSITE(0, "aclk_vio0", mux_pll_src_cpll_gpll_usb480m_p, 0,
301 RK3288_CLKSEL_CON(31), 6, 2, MFLAGS, 0, 5, DFLAGS, 377 RK3288_CLKSEL_CON(31), 6, 2, MFLAGS, 0, 5, DFLAGS,
@@ -309,7 +385,7 @@ static struct rockchip_clk_branch rk3288_clk_branches[] __initdata = {
309 COMPOSITE(0, "aclk_rga_pre", mux_pll_src_cpll_gpll_usb480m_p, 0, 385 COMPOSITE(0, "aclk_rga_pre", mux_pll_src_cpll_gpll_usb480m_p, 0,
310 RK3288_CLKSEL_CON(30), 6, 2, MFLAGS, 0, 5, DFLAGS, 386 RK3288_CLKSEL_CON(30), 6, 2, MFLAGS, 0, 5, DFLAGS,
311 RK3288_CLKGATE_CON(3), 5, GFLAGS), 387 RK3288_CLKGATE_CON(3), 5, GFLAGS),
312 COMPOSITE(0, "sclk_rga", mux_pll_src_cpll_gpll_usb480m_p, 0, 388 COMPOSITE(SCLK_RGA, "sclk_rga", mux_pll_src_cpll_gpll_usb480m_p, 0,
313 RK3288_CLKSEL_CON(30), 14, 2, MFLAGS, 8, 5, DFLAGS, 389 RK3288_CLKSEL_CON(30), 14, 2, MFLAGS, 8, 5, DFLAGS,
314 RK3288_CLKGATE_CON(3), 4, GFLAGS), 390 RK3288_CLKGATE_CON(3), 4, GFLAGS),
315 391
@@ -320,35 +396,35 @@ static struct rockchip_clk_branch rk3288_clk_branches[] __initdata = {
320 RK3288_CLKSEL_CON(29), 6, 2, MFLAGS, 8, 8, DFLAGS, 396 RK3288_CLKSEL_CON(29), 6, 2, MFLAGS, 8, 8, DFLAGS,
321 RK3288_CLKGATE_CON(3), 3, GFLAGS), 397 RK3288_CLKGATE_CON(3), 3, GFLAGS),
322 398
323 COMPOSITE_NODIV(0, "sclk_edp_24m", mux_edp_24m_p, 0, 399 COMPOSITE_NODIV(SCLK_EDP_24M, "sclk_edp_24m", mux_edp_24m_p, 0,
324 RK3288_CLKSEL_CON(28), 15, 1, MFLAGS, 400 RK3288_CLKSEL_CON(28), 15, 1, MFLAGS,
325 RK3288_CLKGATE_CON(3), 12, GFLAGS), 401 RK3288_CLKGATE_CON(3), 12, GFLAGS),
326 COMPOSITE(0, "sclk_edp", mux_pll_src_cpll_gpll_npll_p, 0, 402 COMPOSITE(SCLK_EDP, "sclk_edp", mux_pll_src_cpll_gpll_npll_p, 0,
327 RK3288_CLKSEL_CON(28), 6, 2, MFLAGS, 0, 6, DFLAGS, 403 RK3288_CLKSEL_CON(28), 6, 2, MFLAGS, 0, 6, DFLAGS,
328 RK3288_CLKGATE_CON(3), 13, GFLAGS), 404 RK3288_CLKGATE_CON(3), 13, GFLAGS),
329 405
330 COMPOSITE(0, "sclk_isp", mux_pll_src_cpll_gpll_npll_p, 0, 406 COMPOSITE(SCLK_ISP, "sclk_isp", mux_pll_src_cpll_gpll_npll_p, 0,
331 RK3288_CLKSEL_CON(6), 6, 2, MFLAGS, 0, 6, DFLAGS, 407 RK3288_CLKSEL_CON(6), 6, 2, MFLAGS, 0, 6, DFLAGS,
332 RK3288_CLKGATE_CON(3), 14, GFLAGS), 408 RK3288_CLKGATE_CON(3), 14, GFLAGS),
333 COMPOSITE(0, "sclk_isp_jpe", mux_pll_src_cpll_gpll_npll_p, 0, 409 COMPOSITE(SCLK_ISP_JPE, "sclk_isp_jpe", mux_pll_src_cpll_gpll_npll_p, 0,
334 RK3288_CLKSEL_CON(6), 14, 2, MFLAGS, 8, 6, DFLAGS, 410 RK3288_CLKSEL_CON(6), 14, 2, MFLAGS, 8, 6, DFLAGS,
335 RK3288_CLKGATE_CON(3), 15, GFLAGS), 411 RK3288_CLKGATE_CON(3), 15, GFLAGS),
336 412
337 GATE(0, "sclk_hdmi_hdcp", "xin24m", 0, 413 GATE(SCLK_HDMI_HDCP, "sclk_hdmi_hdcp", "xin24m", 0,
338 RK3288_CLKGATE_CON(5), 12, GFLAGS), 414 RK3288_CLKGATE_CON(5), 12, GFLAGS),
339 GATE(0, "sclk_hdmi_cec", "xin32k", 0, 415 GATE(SCLK_HDMI_CEC, "sclk_hdmi_cec", "xin32k", 0,
340 RK3288_CLKGATE_CON(5), 11, GFLAGS), 416 RK3288_CLKGATE_CON(5), 11, GFLAGS),
341 417
342 COMPOSITE(0, "aclk_hevc", mux_pll_src_cpll_gpll_npll_p, 0, 418 COMPOSITE(ACLK_HEVC, "aclk_hevc", mux_pll_src_cpll_gpll_npll_p, 0,
343 RK3288_CLKSEL_CON(39), 14, 2, MFLAGS, 8, 5, DFLAGS, 419 RK3288_CLKSEL_CON(39), 14, 2, MFLAGS, 8, 5, DFLAGS,
344 RK3288_CLKGATE_CON(13), 13, GFLAGS), 420 RK3288_CLKGATE_CON(13), 13, GFLAGS),
345 DIV(0, "hclk_hevc", "aclk_hevc", 0, 421 DIV(HCLK_HEVC, "hclk_hevc", "aclk_hevc", 0,
346 RK3288_CLKSEL_CON(40), 12, 2, DFLAGS), 422 RK3288_CLKSEL_CON(40), 12, 2, DFLAGS),
347 423
348 COMPOSITE(0, "sclk_hevc_cabac", mux_pll_src_cpll_gpll_npll_p, 0, 424 COMPOSITE(SCLK_HEVC_CABAC, "sclk_hevc_cabac", mux_pll_src_cpll_gpll_npll_p, 0,
349 RK3288_CLKSEL_CON(42), 6, 2, MFLAGS, 0, 5, DFLAGS, 425 RK3288_CLKSEL_CON(42), 6, 2, MFLAGS, 0, 5, DFLAGS,
350 RK3288_CLKGATE_CON(13), 14, GFLAGS), 426 RK3288_CLKGATE_CON(13), 14, GFLAGS),
351 COMPOSITE(0, "sclk_hevc_core", mux_pll_src_cpll_gpll_npll_p, 0, 427 COMPOSITE(SCLK_HEVC_CORE, "sclk_hevc_core", mux_pll_src_cpll_gpll_npll_p, 0,
352 RK3288_CLKSEL_CON(42), 14, 2, MFLAGS, 8, 5, DFLAGS, 428 RK3288_CLKSEL_CON(42), 14, 2, MFLAGS, 8, 5, DFLAGS,
353 RK3288_CLKGATE_CON(13), 15, GFLAGS), 429 RK3288_CLKGATE_CON(13), 15, GFLAGS),
354 430
@@ -371,13 +447,13 @@ static struct rockchip_clk_branch rk3288_clk_branches[] __initdata = {
371 COMPOSITE(0, "aclk_peri_src", mux_pll_src_cpll_gpll_p, 0, 447 COMPOSITE(0, "aclk_peri_src", mux_pll_src_cpll_gpll_p, 0,
372 RK3288_CLKSEL_CON(10), 15, 1, MFLAGS, 0, 5, DFLAGS, 448 RK3288_CLKSEL_CON(10), 15, 1, MFLAGS, 0, 5, DFLAGS,
373 RK3288_CLKGATE_CON(2), 0, GFLAGS), 449 RK3288_CLKGATE_CON(2), 0, GFLAGS),
374 COMPOSITE_NOMUX(0, "pclk_peri", "aclk_peri_src", 0, 450 COMPOSITE_NOMUX(PCLK_PERI, "pclk_peri", "aclk_peri_src", 0,
375 RK3288_CLKSEL_CON(10), 12, 2, DFLAGS | CLK_DIVIDER_POWER_OF_TWO, 451 RK3288_CLKSEL_CON(10), 12, 2, DFLAGS | CLK_DIVIDER_POWER_OF_TWO,
376 RK3288_CLKGATE_CON(2), 3, GFLAGS), 452 RK3288_CLKGATE_CON(2), 3, GFLAGS),
377 COMPOSITE_NOMUX(0, "hclk_peri", "aclk_peri_src", 0, 453 COMPOSITE_NOMUX(HCLK_PERI, "hclk_peri", "aclk_peri_src", 0,
378 RK3288_CLKSEL_CON(10), 8, 2, DFLAGS | CLK_DIVIDER_POWER_OF_TWO, 454 RK3288_CLKSEL_CON(10), 8, 2, DFLAGS | CLK_DIVIDER_POWER_OF_TWO,
379 RK3288_CLKGATE_CON(2), 2, GFLAGS), 455 RK3288_CLKGATE_CON(2), 2, GFLAGS),
380 GATE(0, "aclk_peri", "aclk_peri_src", 0, 456 GATE(ACLK_PERI, "aclk_peri", "aclk_peri_src", 0,
381 RK3288_CLKGATE_CON(2), 1, GFLAGS), 457 RK3288_CLKGATE_CON(2), 1, GFLAGS),
382 458
383 /* 459 /*
@@ -643,34 +719,34 @@ static struct rockchip_clk_branch rk3288_clk_branches[] __initdata = {
643 GATE(HCLK_RGA, "hclk_rga", "hclk_vio", 0, RK3288_CLKGATE_CON(15), 1, GFLAGS), 719 GATE(HCLK_RGA, "hclk_rga", "hclk_vio", 0, RK3288_CLKGATE_CON(15), 1, GFLAGS),
644 GATE(HCLK_VOP0, "hclk_vop0", "hclk_vio", 0, RK3288_CLKGATE_CON(15), 6, GFLAGS), 720 GATE(HCLK_VOP0, "hclk_vop0", "hclk_vio", 0, RK3288_CLKGATE_CON(15), 6, GFLAGS),
645 GATE(HCLK_VOP1, "hclk_vop1", "hclk_vio", 0, RK3288_CLKGATE_CON(15), 8, GFLAGS), 721 GATE(HCLK_VOP1, "hclk_vop1", "hclk_vio", 0, RK3288_CLKGATE_CON(15), 8, GFLAGS),
646 GATE(0, "hclk_vio_ahb_arbi", "hclk_vio", 0, RK3288_CLKGATE_CON(15), 9, GFLAGS), 722 GATE(HCLK_VIO_AHB_ARBI, "hclk_vio_ahb_arbi", "hclk_vio", 0, RK3288_CLKGATE_CON(15), 9, GFLAGS),
647 GATE(0, "hclk_vio_niu", "hclk_vio", 0, RK3288_CLKGATE_CON(15), 10, GFLAGS), 723 GATE(HCLK_VIO_NIU, "hclk_vio_niu", "hclk_vio", 0, RK3288_CLKGATE_CON(15), 10, GFLAGS),
648 GATE(0, "hclk_vip", "hclk_vio", 0, RK3288_CLKGATE_CON(15), 15, GFLAGS), 724 GATE(HCLK_VIP, "hclk_vip", "hclk_vio", 0, RK3288_CLKGATE_CON(15), 15, GFLAGS),
649 GATE(HCLK_IEP, "hclk_iep", "hclk_vio", 0, RK3288_CLKGATE_CON(15), 3, GFLAGS), 725 GATE(HCLK_IEP, "hclk_iep", "hclk_vio", 0, RK3288_CLKGATE_CON(15), 3, GFLAGS),
650 GATE(HCLK_ISP, "hclk_isp", "hclk_vio", 0, RK3288_CLKGATE_CON(16), 1, GFLAGS), 726 GATE(HCLK_ISP, "hclk_isp", "hclk_vio", 0, RK3288_CLKGATE_CON(16), 1, GFLAGS),
651 GATE(0, "hclk_vio2_h2p", "hclk_vio", 0, RK3288_CLKGATE_CON(16), 10, GFLAGS), 727 GATE(HCLK_VIO2_H2P, "hclk_vio2_h2p", "hclk_vio", 0, RK3288_CLKGATE_CON(16), 10, GFLAGS),
652 GATE(0, "pclk_mipi_dsi0", "hclk_vio", 0, RK3288_CLKGATE_CON(16), 4, GFLAGS), 728 GATE(PCLK_MIPI_DSI0, "pclk_mipi_dsi0", "hclk_vio", 0, RK3288_CLKGATE_CON(16), 4, GFLAGS),
653 GATE(0, "pclk_mipi_dsi1", "hclk_vio", 0, RK3288_CLKGATE_CON(16), 5, GFLAGS), 729 GATE(PCLK_MIPI_DSI1, "pclk_mipi_dsi1", "hclk_vio", 0, RK3288_CLKGATE_CON(16), 5, GFLAGS),
654 GATE(0, "pclk_mipi_csi", "hclk_vio", 0, RK3288_CLKGATE_CON(16), 6, GFLAGS), 730 GATE(PCLK_MIPI_CSI, "pclk_mipi_csi", "hclk_vio", 0, RK3288_CLKGATE_CON(16), 6, GFLAGS),
655 GATE(0, "pclk_lvds_phy", "hclk_vio", 0, RK3288_CLKGATE_CON(16), 7, GFLAGS), 731 GATE(PCLK_LVDS_PHY, "pclk_lvds_phy", "hclk_vio", 0, RK3288_CLKGATE_CON(16), 7, GFLAGS),
656 GATE(0, "pclk_edp_ctrl", "hclk_vio", 0, RK3288_CLKGATE_CON(16), 8, GFLAGS), 732 GATE(PCLK_EDP_CTRL, "pclk_edp_ctrl", "hclk_vio", 0, RK3288_CLKGATE_CON(16), 8, GFLAGS),
657 GATE(0, "pclk_hdmi_ctrl", "hclk_vio", 0, RK3288_CLKGATE_CON(16), 9, GFLAGS), 733 GATE(PCLK_HDMI_CTRL, "pclk_hdmi_ctrl", "hclk_vio", 0, RK3288_CLKGATE_CON(16), 9, GFLAGS),
658 GATE(0, "pclk_vio2_h2p", "hclk_vio", 0, RK3288_CLKGATE_CON(16), 11, GFLAGS), 734 GATE(PCLK_VIO2_H2P, "pclk_vio2_h2p", "hclk_vio", 0, RK3288_CLKGATE_CON(16), 11, GFLAGS),
659 735
660 /* aclk_vio0 gates */ 736 /* aclk_vio0 gates */
661 GATE(ACLK_VOP0, "aclk_vop0", "aclk_vio0", 0, RK3288_CLKGATE_CON(15), 5, GFLAGS), 737 GATE(ACLK_VOP0, "aclk_vop0", "aclk_vio0", 0, RK3288_CLKGATE_CON(15), 5, GFLAGS),
662 GATE(0, "aclk_iep", "aclk_vio0", 0, RK3288_CLKGATE_CON(15), 2, GFLAGS), 738 GATE(ACLK_IEP, "aclk_iep", "aclk_vio0", 0, RK3288_CLKGATE_CON(15), 2, GFLAGS),
663 GATE(0, "aclk_vio0_niu", "aclk_vio0", 0, RK3288_CLKGATE_CON(15), 11, GFLAGS), 739 GATE(ACLK_VIO0_NIU, "aclk_vio0_niu", "aclk_vio0", 0, RK3288_CLKGATE_CON(15), 11, GFLAGS),
664 GATE(0, "aclk_vip", "aclk_vio0", 0, RK3288_CLKGATE_CON(15), 14, GFLAGS), 740 GATE(ACLK_VIP, "aclk_vip", "aclk_vio0", 0, RK3288_CLKGATE_CON(15), 14, GFLAGS),
665 741
666 /* aclk_vio1 gates */ 742 /* aclk_vio1 gates */
667 GATE(ACLK_VOP1, "aclk_vop1", "aclk_vio1", 0, RK3288_CLKGATE_CON(15), 7, GFLAGS), 743 GATE(ACLK_VOP1, "aclk_vop1", "aclk_vio1", 0, RK3288_CLKGATE_CON(15), 7, GFLAGS),
668 GATE(0, "aclk_isp", "aclk_vio1", 0, RK3288_CLKGATE_CON(16), 2, GFLAGS), 744 GATE(ACLK_ISP, "aclk_isp", "aclk_vio1", 0, RK3288_CLKGATE_CON(16), 2, GFLAGS),
669 GATE(0, "aclk_vio1_niu", "aclk_vio1", 0, RK3288_CLKGATE_CON(15), 12, GFLAGS), 745 GATE(ACLK_VIO1_NIU, "aclk_vio1_niu", "aclk_vio1", 0, RK3288_CLKGATE_CON(15), 12, GFLAGS),
670 746
671 /* aclk_rga_pre gates */ 747 /* aclk_rga_pre gates */
672 GATE(ACLK_RGA, "aclk_rga", "aclk_rga_pre", 0, RK3288_CLKGATE_CON(15), 0, GFLAGS), 748 GATE(ACLK_RGA, "aclk_rga", "aclk_rga_pre", 0, RK3288_CLKGATE_CON(15), 0, GFLAGS),
673 GATE(0, "aclk_rga_niu", "aclk_rga_pre", 0, RK3288_CLKGATE_CON(15), 13, GFLAGS), 749 GATE(ACLK_RGA_NIU, "aclk_rga_niu", "aclk_rga_pre", 0, RK3288_CLKGATE_CON(15), 13, GFLAGS),
674 750
675 /* 751 /*
676 * Other ungrouped clocks. 752 * Other ungrouped clocks.
@@ -680,6 +756,12 @@ static struct rockchip_clk_branch rk3288_clk_branches[] __initdata = {
680 GATE(0, "pclk_isp_in", "ext_isp", 0, RK3288_CLKGATE_CON(16), 3, GFLAGS), 756 GATE(0, "pclk_isp_in", "ext_isp", 0, RK3288_CLKGATE_CON(16), 3, GFLAGS),
681}; 757};
682 758
759static const char *rk3288_critical_clocks[] __initconst = {
760 "aclk_cpu",
761 "aclk_peri",
762 "hclk_peri",
763};
764
683static void __init rk3288_clk_init(struct device_node *np) 765static void __init rk3288_clk_init(struct device_node *np)
684{ 766{
685 void __iomem *reg_base; 767 void __iomem *reg_base;
@@ -705,13 +787,28 @@ static void __init rk3288_clk_init(struct device_node *np)
705 pr_warn("%s: could not register clock usb480m: %ld\n", 787 pr_warn("%s: could not register clock usb480m: %ld\n",
706 __func__, PTR_ERR(clk)); 788 __func__, PTR_ERR(clk));
707 789
790 clk = clk_register_fixed_factor(NULL, "hclk_vcodec_pre",
791 "hclk_vcodec_pre_v", 0, 1, 4);
792 if (IS_ERR(clk))
793 pr_warn("%s: could not register clock hclk_vcodec_pre: %ld\n",
794 __func__, PTR_ERR(clk));
795
708 rockchip_clk_register_plls(rk3288_pll_clks, 796 rockchip_clk_register_plls(rk3288_pll_clks,
709 ARRAY_SIZE(rk3288_pll_clks), 797 ARRAY_SIZE(rk3288_pll_clks),
710 RK3288_GRF_SOC_STATUS); 798 RK3288_GRF_SOC_STATUS1);
711 rockchip_clk_register_branches(rk3288_clk_branches, 799 rockchip_clk_register_branches(rk3288_clk_branches,
712 ARRAY_SIZE(rk3288_clk_branches)); 800 ARRAY_SIZE(rk3288_clk_branches));
801 rockchip_clk_protect_critical(rk3288_critical_clocks,
802 ARRAY_SIZE(rk3288_critical_clocks));
713 803
714 rockchip_register_softrst(np, 9, reg_base + RK3288_SOFTRST_CON(0), 804 rockchip_clk_register_armclk(ARMCLK, "armclk",
805 mux_armclk_p, ARRAY_SIZE(mux_armclk_p),
806 &rk3288_cpuclk_data, rk3288_cpuclk_rates,
807 ARRAY_SIZE(rk3288_cpuclk_rates));
808
809 rockchip_register_softrst(np, 12, reg_base + RK3288_SOFTRST_CON(0),
715 ROCKCHIP_SOFTRST_HIWORD_MASK); 810 ROCKCHIP_SOFTRST_HIWORD_MASK);
811
812 rockchip_register_restart_notifier(RK3288_GLB_SRST_FST);
716} 813}
717CLK_OF_DECLARE(rk3288_cru, "rockchip,rk3288-cru", rk3288_clk_init); 814CLK_OF_DECLARE(rk3288_cru, "rockchip,rk3288-cru", rk3288_clk_init);
diff --git a/drivers/clk/rockchip/clk.c b/drivers/clk/rockchip/clk.c
index 278cf9dd1e23..1e68bff481b8 100644
--- a/drivers/clk/rockchip/clk.c
+++ b/drivers/clk/rockchip/clk.c
@@ -25,6 +25,7 @@
25#include <linux/clk-provider.h> 25#include <linux/clk-provider.h>
26#include <linux/mfd/syscon.h> 26#include <linux/mfd/syscon.h>
27#include <linux/regmap.h> 27#include <linux/regmap.h>
28#include <linux/reboot.h>
28#include "clk.h" 29#include "clk.h"
29 30
30/** 31/**
@@ -37,7 +38,7 @@
37 * 38 *
38 * sometimes without one of those components. 39 * sometimes without one of those components.
39 */ 40 */
40struct clk *rockchip_clk_register_branch(const char *name, 41static struct clk *rockchip_clk_register_branch(const char *name,
41 const char **parent_names, u8 num_parents, void __iomem *base, 42 const char **parent_names, u8 num_parents, void __iomem *base,
42 int muxdiv_offset, u8 mux_shift, u8 mux_width, u8 mux_flags, 43 int muxdiv_offset, u8 mux_shift, u8 mux_width, u8 mux_flags,
43 u8 div_shift, u8 div_width, u8 div_flags, 44 u8 div_shift, u8 div_width, u8 div_flags,
@@ -103,6 +104,54 @@ struct clk *rockchip_clk_register_branch(const char *name,
103 return clk; 104 return clk;
104} 105}
105 106
107static struct clk *rockchip_clk_register_frac_branch(const char *name,
108 const char **parent_names, u8 num_parents, void __iomem *base,
109 int muxdiv_offset, u8 div_flags,
110 int gate_offset, u8 gate_shift, u8 gate_flags,
111 unsigned long flags, spinlock_t *lock)
112{
113 struct clk *clk;
114 struct clk_gate *gate = NULL;
115 struct clk_fractional_divider *div = NULL;
116 const struct clk_ops *div_ops = NULL, *gate_ops = NULL;
117
118 if (gate_offset >= 0) {
119 gate = kzalloc(sizeof(*gate), GFP_KERNEL);
120 if (!gate)
121 return ERR_PTR(-ENOMEM);
122
123 gate->flags = gate_flags;
124 gate->reg = base + gate_offset;
125 gate->bit_idx = gate_shift;
126 gate->lock = lock;
127 gate_ops = &clk_gate_ops;
128 }
129
130 if (muxdiv_offset < 0)
131 return ERR_PTR(-EINVAL);
132
133 div = kzalloc(sizeof(*div), GFP_KERNEL);
134 if (!div)
135 return ERR_PTR(-ENOMEM);
136
137 div->flags = div_flags;
138 div->reg = base + muxdiv_offset;
139 div->mshift = 16;
140 div->mmask = 0xffff0000;
141 div->nshift = 0;
142 div->nmask = 0xffff;
143 div->lock = lock;
144 div_ops = &clk_fractional_divider_ops;
145
146 clk = clk_register_composite(NULL, name, parent_names, num_parents,
147 NULL, NULL,
148 &div->hw, div_ops,
149 gate ? &gate->hw : NULL, gate_ops,
150 flags);
151
152 return clk;
153}
154
106static DEFINE_SPINLOCK(clk_lock); 155static DEFINE_SPINLOCK(clk_lock);
107static struct clk **clk_table; 156static struct clk **clk_table;
108static void __iomem *reg_base; 157static void __iomem *reg_base;
@@ -197,8 +246,14 @@ void __init rockchip_clk_register_branches(
197 list->div_flags, &clk_lock); 246 list->div_flags, &clk_lock);
198 break; 247 break;
199 case branch_fraction_divider: 248 case branch_fraction_divider:
200 /* unimplemented */ 249 /* keep all gates untouched for now */
201 continue; 250 flags |= CLK_IGNORE_UNUSED;
251
252 clk = rockchip_clk_register_frac_branch(list->name,
253 list->parent_names, list->num_parents,
254 reg_base, list->muxdiv_offset, list->div_flags,
255 list->gate_offset, list->gate_shift,
256 list->gate_flags, flags, &clk_lock);
202 break; 257 break;
203 case branch_gate: 258 case branch_gate:
204 flags |= CLK_SET_RATE_PARENT; 259 flags |= CLK_SET_RATE_PARENT;
@@ -242,3 +297,61 @@ void __init rockchip_clk_register_branches(
242 rockchip_clk_add_lookup(clk, list->id); 297 rockchip_clk_add_lookup(clk, list->id);
243 } 298 }
244} 299}
300
301void __init rockchip_clk_register_armclk(unsigned int lookup_id,
302 const char *name, const char **parent_names,
303 u8 num_parents,
304 const struct rockchip_cpuclk_reg_data *reg_data,
305 const struct rockchip_cpuclk_rate_table *rates,
306 int nrates)
307{
308 struct clk *clk;
309
310 clk = rockchip_clk_register_cpuclk(name, parent_names, num_parents,
311 reg_data, rates, nrates, reg_base,
312 &clk_lock);
313 if (IS_ERR(clk)) {
314 pr_err("%s: failed to register clock %s: %ld\n",
315 __func__, name, PTR_ERR(clk));
316 return;
317 }
318
319 rockchip_clk_add_lookup(clk, lookup_id);
320}
321
322void __init rockchip_clk_protect_critical(const char *clocks[], int nclocks)
323{
324 int i;
325
326 /* Protect the clocks that needs to stay on */
327 for (i = 0; i < nclocks; i++) {
328 struct clk *clk = __clk_lookup(clocks[i]);
329
330 if (clk)
331 clk_prepare_enable(clk);
332 }
333}
334
335static unsigned int reg_restart;
336static int rockchip_restart_notify(struct notifier_block *this,
337 unsigned long mode, void *cmd)
338{
339 writel(0xfdb9, reg_base + reg_restart);
340 return NOTIFY_DONE;
341}
342
343static struct notifier_block rockchip_restart_handler = {
344 .notifier_call = rockchip_restart_notify,
345 .priority = 128,
346};
347
348void __init rockchip_register_restart_notifier(unsigned int reg)
349{
350 int ret;
351
352 reg_restart = reg;
353 ret = register_restart_handler(&rockchip_restart_handler);
354 if (ret)
355 pr_err("%s: cannot register restart handler, %d\n",
356 __func__, ret);
357}
diff --git a/drivers/clk/rockchip/clk.h b/drivers/clk/rockchip/clk.h
index 887cbdeca2aa..ca009ab0a33a 100644
--- a/drivers/clk/rockchip/clk.h
+++ b/drivers/clk/rockchip/clk.h
@@ -120,6 +120,38 @@ struct clk *rockchip_clk_register_pll(enum rockchip_pll_type pll_type,
120 struct rockchip_pll_rate_table *rate_table, 120 struct rockchip_pll_rate_table *rate_table,
121 spinlock_t *lock); 121 spinlock_t *lock);
122 122
123struct rockchip_cpuclk_clksel {
124 int reg;
125 u32 val;
126};
127
128#define ROCKCHIP_CPUCLK_NUM_DIVIDERS 2
129struct rockchip_cpuclk_rate_table {
130 unsigned long prate;
131 struct rockchip_cpuclk_clksel divs[ROCKCHIP_CPUCLK_NUM_DIVIDERS];
132};
133
134/**
135 * struct rockchip_cpuclk_reg_data: describes register offsets and masks of the cpuclock
136 * @core_reg: register offset of the core settings register
137 * @div_core_shift: core divider offset used to divide the pll value
138 * @div_core_mask: core divider mask
139 * @mux_core_shift: offset of the core multiplexer
140 */
141struct rockchip_cpuclk_reg_data {
142 int core_reg;
143 u8 div_core_shift;
144 u32 div_core_mask;
145 int mux_core_reg;
146 u8 mux_core_shift;
147};
148
149struct clk *rockchip_clk_register_cpuclk(const char *name,
150 const char **parent_names, u8 num_parents,
151 const struct rockchip_cpuclk_reg_data *reg_data,
152 const struct rockchip_cpuclk_rate_table *rates,
153 int nrates, void __iomem *reg_base, spinlock_t *lock);
154
123#define PNAME(x) static const char *x[] __initconst 155#define PNAME(x) static const char *x[] __initconst
124 156
125enum rockchip_clk_branch_type { 157enum rockchip_clk_branch_type {
@@ -329,6 +361,13 @@ void rockchip_clk_register_branches(struct rockchip_clk_branch *clk_list,
329 unsigned int nr_clk); 361 unsigned int nr_clk);
330void rockchip_clk_register_plls(struct rockchip_pll_clock *pll_list, 362void rockchip_clk_register_plls(struct rockchip_pll_clock *pll_list,
331 unsigned int nr_pll, int grf_lock_offset); 363 unsigned int nr_pll, int grf_lock_offset);
364void rockchip_clk_register_armclk(unsigned int lookup_id, const char *name,
365 const char **parent_names, u8 num_parents,
366 const struct rockchip_cpuclk_reg_data *reg_data,
367 const struct rockchip_cpuclk_rate_table *rates,
368 int nrates);
369void rockchip_clk_protect_critical(const char *clocks[], int nclocks);
370void rockchip_register_restart_notifier(unsigned int reg);
332 371
333#define ROCKCHIP_SOFTRST_HIWORD_MASK BIT(0) 372#define ROCKCHIP_SOFTRST_HIWORD_MASK BIT(0)
334 373
diff --git a/drivers/clk/samsung/clk-exynos3250.c b/drivers/clk/samsung/clk-exynos3250.c
index dc85f8e7a2d7..6e6cca392082 100644
--- a/drivers/clk/samsung/clk-exynos3250.c
+++ b/drivers/clk/samsung/clk-exynos3250.c
@@ -110,7 +110,14 @@ enum exynos3250_plls {
110 nr_plls 110 nr_plls
111}; 111};
112 112
113/* list of PLLs in DMC block to be registered */
114enum exynos3250_dmc_plls {
115 bpll, epll,
116 nr_dmc_plls
117};
118
113static void __iomem *reg_base; 119static void __iomem *reg_base;
120static void __iomem *dmc_reg_base;
114 121
115/* 122/*
116 * Support for CMU save/restore across system suspends 123 * Support for CMU save/restore across system suspends
@@ -266,6 +273,7 @@ PNAME(group_sclk_cam_blk_p) = { "xxti", "xusbxti",
266 "none", "none", "none", 273 "none", "none", "none",
267 "none", "div_mpll_pre", 274 "none", "div_mpll_pre",
268 "mout_epll_user", "mout_vpll", 275 "mout_epll_user", "mout_vpll",
276 "none", "none", "none",
269 "div_cam_blk_320", }; 277 "div_cam_blk_320", };
270PNAME(group_sclk_fimd0_p) = { "xxti", "xusbxti", 278PNAME(group_sclk_fimd0_p) = { "xxti", "xusbxti",
271 "m_bitclkhsdiv4_2l", "none", 279 "m_bitclkhsdiv4_2l", "none",
@@ -353,8 +361,8 @@ static struct samsung_mux_clock mux_clks[] __initdata = {
353 361
354 /* SRC_FSYS */ 362 /* SRC_FSYS */
355 MUX(CLK_MOUT_TSADC, "mout_tsadc", group_sclk_p, SRC_FSYS, 28, 4), 363 MUX(CLK_MOUT_TSADC, "mout_tsadc", group_sclk_p, SRC_FSYS, 28, 4),
356 MUX(CLK_MOUT_MMC1, "mout_mmc1", group_sclk_p, SRC_FSYS, 4, 3), 364 MUX(CLK_MOUT_MMC1, "mout_mmc1", group_sclk_p, SRC_FSYS, 4, 4),
357 MUX(CLK_MOUT_MMC0, "mout_mmc0", group_sclk_p, SRC_FSYS, 0, 3), 365 MUX(CLK_MOUT_MMC0, "mout_mmc0", group_sclk_p, SRC_FSYS, 0, 4),
358 366
359 /* SRC_PERIL0 */ 367 /* SRC_PERIL0 */
360 MUX(CLK_MOUT_UART1, "mout_uart1", group_sclk_p, SRC_PERIL0, 4, 4), 368 MUX(CLK_MOUT_UART1, "mout_uart1", group_sclk_p, SRC_PERIL0, 4, 4),
@@ -423,7 +431,7 @@ static struct samsung_div_clock div_clks[] __initdata = {
423 DIV(CLK_DIV_SPI1_ISP, "div_spi1_isp", "mout_spi1_isp", DIV_ISP, 16, 4), 431 DIV(CLK_DIV_SPI1_ISP, "div_spi1_isp", "mout_spi1_isp", DIV_ISP, 16, 4),
424 DIV_F(CLK_DIV_SPI0_ISP_PRE, "div_spi0_isp_pre", "div_spi0_isp", 432 DIV_F(CLK_DIV_SPI0_ISP_PRE, "div_spi0_isp_pre", "div_spi0_isp",
425 DIV_ISP, 8, 8, CLK_SET_RATE_PARENT, 0), 433 DIV_ISP, 8, 8, CLK_SET_RATE_PARENT, 0),
426 DIV(CLK_DIV_SPI0_ISP, "div_spi0_isp", "mout_spi0_isp", DIV_ISP, 0, 4), 434 DIV(CLK_DIV_SPI0_ISP, "div_spi0_isp", "mout_spi0_isp", DIV_ISP, 4, 4),
427 435
428 /* DIV_FSYS0 */ 436 /* DIV_FSYS0 */
429 DIV_F(CLK_DIV_TSADC_PRE, "div_tsadc_pre", "div_tsadc", DIV_FSYS0, 8, 8, 437 DIV_F(CLK_DIV_TSADC_PRE, "div_tsadc_pre", "div_tsadc", DIV_FSYS0, 8, 8,
@@ -724,6 +732,25 @@ static struct samsung_pll_rate_table exynos3250_pll_rates[] = {
724 { /* sentinel */ } 732 { /* sentinel */ }
725}; 733};
726 734
735/* EPLL */
736static struct samsung_pll_rate_table exynos3250_epll_rates[] = {
737 PLL_36XX_RATE(800000000, 200, 3, 1, 0),
738 PLL_36XX_RATE(288000000, 96, 2, 2, 0),
739 PLL_36XX_RATE(192000000, 128, 2, 3, 0),
740 PLL_36XX_RATE(144000000, 96, 2, 3, 0),
741 PLL_36XX_RATE( 96000000, 128, 2, 4, 0),
742 PLL_36XX_RATE( 84000000, 112, 2, 4, 0),
743 PLL_36XX_RATE( 80000004, 106, 2, 4, 43691),
744 PLL_36XX_RATE( 73728000, 98, 2, 4, 19923),
745 PLL_36XX_RATE( 67737598, 270, 3, 5, 62285),
746 PLL_36XX_RATE( 65535999, 174, 2, 5, 49982),
747 PLL_36XX_RATE( 50000000, 200, 3, 5, 0),
748 PLL_36XX_RATE( 49152002, 131, 2, 5, 4719),
749 PLL_36XX_RATE( 48000000, 128, 2, 5, 0),
750 PLL_36XX_RATE( 45158401, 180, 3, 5, 41524),
751 { /* sentinel */ }
752};
753
727/* VPLL */ 754/* VPLL */
728static struct samsung_pll_rate_table exynos3250_vpll_rates[] = { 755static struct samsung_pll_rate_table exynos3250_vpll_rates[] = {
729 PLL_36XX_RATE(600000000, 100, 2, 1, 0), 756 PLL_36XX_RATE(600000000, 100, 2, 1, 0),
@@ -821,3 +848,172 @@ static void __init exynos3250_cmu_init(struct device_node *np)
821 samsung_clk_of_add_provider(np, ctx); 848 samsung_clk_of_add_provider(np, ctx);
822} 849}
823CLK_OF_DECLARE(exynos3250_cmu, "samsung,exynos3250-cmu", exynos3250_cmu_init); 850CLK_OF_DECLARE(exynos3250_cmu, "samsung,exynos3250-cmu", exynos3250_cmu_init);
851
852/*
853 * CMU DMC
854 */
855
856#define BPLL_LOCK 0x0118
857#define BPLL_CON0 0x0218
858#define BPLL_CON1 0x021c
859#define BPLL_CON2 0x0220
860#define SRC_DMC 0x0300
861#define DIV_DMC1 0x0504
862#define GATE_BUS_DMC0 0x0700
863#define GATE_BUS_DMC1 0x0704
864#define GATE_BUS_DMC2 0x0708
865#define GATE_BUS_DMC3 0x070c
866#define GATE_SCLK_DMC 0x0800
867#define GATE_IP_DMC0 0x0900
868#define GATE_IP_DMC1 0x0904
869#define EPLL_LOCK 0x1110
870#define EPLL_CON0 0x1114
871#define EPLL_CON1 0x1118
872#define EPLL_CON2 0x111c
873#define SRC_EPLL 0x1120
874
875/*
876 * Support for CMU save/restore across system suspends
877 */
878#ifdef CONFIG_PM_SLEEP
879static struct samsung_clk_reg_dump *exynos3250_dmc_clk_regs;
880
881static unsigned long exynos3250_cmu_dmc_clk_regs[] __initdata = {
882 BPLL_LOCK,
883 BPLL_CON0,
884 BPLL_CON1,
885 BPLL_CON2,
886 SRC_DMC,
887 DIV_DMC1,
888 GATE_BUS_DMC0,
889 GATE_BUS_DMC1,
890 GATE_BUS_DMC2,
891 GATE_BUS_DMC3,
892 GATE_SCLK_DMC,
893 GATE_IP_DMC0,
894 GATE_IP_DMC1,
895 EPLL_LOCK,
896 EPLL_CON0,
897 EPLL_CON1,
898 EPLL_CON2,
899 SRC_EPLL,
900};
901
902static int exynos3250_dmc_clk_suspend(void)
903{
904 samsung_clk_save(dmc_reg_base, exynos3250_dmc_clk_regs,
905 ARRAY_SIZE(exynos3250_cmu_dmc_clk_regs));
906 return 0;
907}
908
909static void exynos3250_dmc_clk_resume(void)
910{
911 samsung_clk_restore(dmc_reg_base, exynos3250_dmc_clk_regs,
912 ARRAY_SIZE(exynos3250_cmu_dmc_clk_regs));
913}
914
915static struct syscore_ops exynos3250_dmc_clk_syscore_ops = {
916 .suspend = exynos3250_dmc_clk_suspend,
917 .resume = exynos3250_dmc_clk_resume,
918};
919
920static void exynos3250_dmc_clk_sleep_init(void)
921{
922 exynos3250_dmc_clk_regs =
923 samsung_clk_alloc_reg_dump(exynos3250_cmu_dmc_clk_regs,
924 ARRAY_SIZE(exynos3250_cmu_dmc_clk_regs));
925 if (!exynos3250_dmc_clk_regs) {
926 pr_warn("%s: Failed to allocate sleep save data\n", __func__);
927 goto err;
928 }
929
930 register_syscore_ops(&exynos3250_dmc_clk_syscore_ops);
931 return;
932err:
933 kfree(exynos3250_dmc_clk_regs);
934}
935#else
936static inline void exynos3250_dmc_clk_sleep_init(void) { }
937#endif
938
939PNAME(mout_epll_p) = { "fin_pll", "fout_epll", };
940PNAME(mout_bpll_p) = { "fin_pll", "fout_bpll", };
941PNAME(mout_mpll_mif_p) = { "fin_pll", "sclk_mpll_mif", };
942PNAME(mout_dphy_p) = { "mout_mpll_mif", "mout_bpll", };
943
944static struct samsung_mux_clock dmc_mux_clks[] __initdata = {
945 /*
946 * NOTE: Following table is sorted by register address in ascending
947 * order and then bitfield shift in descending order, as it is done
948 * in the User's Manual. When adding new entries, please make sure
949 * that the order is preserved, to avoid merge conflicts and make
950 * further work with defined data easier.
951 */
952
953 /* SRC_DMC */
954 MUX(CLK_MOUT_MPLL_MIF, "mout_mpll_mif", mout_mpll_mif_p, SRC_DMC, 12, 1),
955 MUX(CLK_MOUT_BPLL, "mout_bpll", mout_bpll_p, SRC_DMC, 10, 1),
956 MUX(CLK_MOUT_DPHY, "mout_dphy", mout_dphy_p, SRC_DMC, 8, 1),
957 MUX(CLK_MOUT_DMC_BUS, "mout_dmc_bus", mout_dphy_p, SRC_DMC, 4, 1),
958
959 /* SRC_EPLL */
960 MUX(CLK_MOUT_EPLL, "mout_epll", mout_epll_p, SRC_EPLL, 4, 1),
961};
962
963static struct samsung_div_clock dmc_div_clks[] __initdata = {
964 /*
965 * NOTE: Following table is sorted by register address in ascending
966 * order and then bitfield shift in descending order, as it is done
967 * in the User's Manual. When adding new entries, please make sure
968 * that the order is preserved, to avoid merge conflicts and make
969 * further work with defined data easier.
970 */
971
972 /* DIV_DMC1 */
973 DIV(CLK_DIV_DMC, "div_dmc", "div_dmc_pre", DIV_DMC1, 27, 3),
974 DIV(CLK_DIV_DPHY, "div_dphy", "mout_dphy", DIV_DMC1, 23, 3),
975 DIV(CLK_DIV_DMC_PRE, "div_dmc_pre", "mout_dmc_bus", DIV_DMC1, 19, 2),
976 DIV(CLK_DIV_DMCP, "div_dmcp", "div_dmcd", DIV_DMC1, 15, 3),
977 DIV(CLK_DIV_DMCD, "div_dmcd", "div_dmc", DIV_DMC1, 11, 3),
978};
979
980static struct samsung_pll_clock exynos3250_dmc_plls[nr_dmc_plls] __initdata = {
981 [bpll] = PLL(pll_35xx, CLK_FOUT_BPLL, "fout_bpll", "fin_pll",
982 BPLL_LOCK, BPLL_CON0, NULL),
983 [epll] = PLL(pll_36xx, CLK_FOUT_EPLL, "fout_epll", "fin_pll",
984 EPLL_LOCK, EPLL_CON0, NULL),
985};
986
987static void __init exynos3250_cmu_dmc_init(struct device_node *np)
988{
989 struct samsung_clk_provider *ctx;
990
991 dmc_reg_base = of_iomap(np, 0);
992 if (!dmc_reg_base)
993 panic("%s: failed to map registers\n", __func__);
994
995 ctx = samsung_clk_init(np, dmc_reg_base, NR_CLKS_DMC);
996 if (!ctx)
997 panic("%s: unable to allocate context.\n", __func__);
998
999 exynos3250_dmc_plls[bpll].rate_table = exynos3250_pll_rates;
1000 exynos3250_dmc_plls[epll].rate_table = exynos3250_epll_rates;
1001
1002 pr_err("CLK registering epll bpll: %d, %d, %d, %d\n",
1003 exynos3250_dmc_plls[bpll].rate_table[0].rate,
1004 exynos3250_dmc_plls[bpll].rate_table[0].mdiv,
1005 exynos3250_dmc_plls[bpll].rate_table[0].pdiv,
1006 exynos3250_dmc_plls[bpll].rate_table[0].sdiv
1007 );
1008 samsung_clk_register_pll(ctx, exynos3250_dmc_plls,
1009 ARRAY_SIZE(exynos3250_dmc_plls), dmc_reg_base);
1010
1011 samsung_clk_register_mux(ctx, dmc_mux_clks, ARRAY_SIZE(dmc_mux_clks));
1012 samsung_clk_register_div(ctx, dmc_div_clks, ARRAY_SIZE(dmc_div_clks));
1013
1014 exynos3250_dmc_clk_sleep_init();
1015
1016 samsung_clk_of_add_provider(np, ctx);
1017}
1018CLK_OF_DECLARE(exynos3250_cmu_dmc, "samsung,exynos3250-cmu-dmc",
1019 exynos3250_cmu_dmc_init);
diff --git a/drivers/clk/samsung/clk-exynos4.c b/drivers/clk/samsung/clk-exynos4.c
index ac163d7f5bc3..940f02837b82 100644
--- a/drivers/clk/samsung/clk-exynos4.c
+++ b/drivers/clk/samsung/clk-exynos4.c
@@ -517,7 +517,7 @@ static struct samsung_fixed_factor_clock exynos4_fixed_factor_clks[] __initdata
517 FFACTOR(0, "sclk_apll_div_2", "sclk_apll", 1, 2, 0), 517 FFACTOR(0, "sclk_apll_div_2", "sclk_apll", 1, 2, 0),
518 FFACTOR(0, "fout_mpll_div_2", "fout_mpll", 1, 2, 0), 518 FFACTOR(0, "fout_mpll_div_2", "fout_mpll", 1, 2, 0),
519 FFACTOR(0, "fout_apll_div_2", "fout_apll", 1, 2, 0), 519 FFACTOR(0, "fout_apll_div_2", "fout_apll", 1, 2, 0),
520 FFACTOR(0, "arm_clk_div_2", "arm_clk", 1, 2, 0), 520 FFACTOR(0, "arm_clk_div_2", "div_core2", 1, 2, 0),
521}; 521};
522 522
523static struct samsung_fixed_factor_clock exynos4210_fixed_factor_clks[] __initdata = { 523static struct samsung_fixed_factor_clock exynos4210_fixed_factor_clks[] __initdata = {
@@ -535,7 +535,7 @@ static struct samsung_fixed_factor_clock exynos4x12_fixed_factor_clks[] __initda
535static struct samsung_mux_clock exynos4_mux_clks[] __initdata = { 535static struct samsung_mux_clock exynos4_mux_clks[] __initdata = {
536 MUX_FA(CLK_MOUT_APLL, "mout_apll", mout_apll_p, SRC_CPU, 0, 1, 536 MUX_FA(CLK_MOUT_APLL, "mout_apll", mout_apll_p, SRC_CPU, 0, 1,
537 CLK_SET_RATE_PARENT, 0, "mout_apll"), 537 CLK_SET_RATE_PARENT, 0, "mout_apll"),
538 MUX(0, "mout_hdmi", mout_hdmi_p, SRC_TV, 0, 1), 538 MUX(CLK_MOUT_HDMI, "mout_hdmi", mout_hdmi_p, SRC_TV, 0, 1),
539 MUX(0, "mout_mfc1", sclk_evpll_p, SRC_MFC, 4, 1), 539 MUX(0, "mout_mfc1", sclk_evpll_p, SRC_MFC, 4, 1),
540 MUX(0, "mout_mfc", mout_mfc_p, SRC_MFC, 8, 1), 540 MUX(0, "mout_mfc", mout_mfc_p, SRC_MFC, 8, 1),
541 MUX_F(CLK_MOUT_G3D1, "mout_g3d1", sclk_evpll_p, SRC_G3D, 4, 1, 541 MUX_F(CLK_MOUT_G3D1, "mout_g3d1", sclk_evpll_p, SRC_G3D, 4, 1,
@@ -569,7 +569,7 @@ static struct samsung_mux_clock exynos4210_mux_clks[] __initdata = {
569 MUX(0, "mout_aclk100", sclk_ampll_p4210, SRC_TOP0, 16, 1), 569 MUX(0, "mout_aclk100", sclk_ampll_p4210, SRC_TOP0, 16, 1),
570 MUX(0, "mout_aclk160", sclk_ampll_p4210, SRC_TOP0, 20, 1), 570 MUX(0, "mout_aclk160", sclk_ampll_p4210, SRC_TOP0, 20, 1),
571 MUX(0, "mout_aclk133", sclk_ampll_p4210, SRC_TOP0, 24, 1), 571 MUX(0, "mout_aclk133", sclk_ampll_p4210, SRC_TOP0, 24, 1),
572 MUX(0, "mout_mixer", mout_mixer_p4210, SRC_TV, 4, 1), 572 MUX(CLK_MOUT_MIXER, "mout_mixer", mout_mixer_p4210, SRC_TV, 4, 1),
573 MUX(0, "mout_dac", mout_dac_p4210, SRC_TV, 8, 1), 573 MUX(0, "mout_dac", mout_dac_p4210, SRC_TV, 8, 1),
574 MUX(0, "mout_g2d0", sclk_ampll_p4210, E4210_SRC_IMAGE, 0, 1), 574 MUX(0, "mout_g2d0", sclk_ampll_p4210, E4210_SRC_IMAGE, 0, 1),
575 MUX(0, "mout_g2d1", sclk_evpll_p, E4210_SRC_IMAGE, 4, 1), 575 MUX(0, "mout_g2d1", sclk_evpll_p, E4210_SRC_IMAGE, 4, 1),
@@ -719,7 +719,7 @@ static struct samsung_div_clock exynos4_div_clks[] __initdata = {
719 DIV(0, "div_periph", "div_core2", DIV_CPU0, 12, 3), 719 DIV(0, "div_periph", "div_core2", DIV_CPU0, 12, 3),
720 DIV(0, "div_atb", "mout_core", DIV_CPU0, 16, 3), 720 DIV(0, "div_atb", "mout_core", DIV_CPU0, 16, 3),
721 DIV(0, "div_pclk_dbg", "div_atb", DIV_CPU0, 20, 3), 721 DIV(0, "div_pclk_dbg", "div_atb", DIV_CPU0, 20, 3),
722 DIV(0, "div_core2", "div_core", DIV_CPU0, 28, 3), 722 DIV(CLK_ARM_CLK, "div_core2", "div_core", DIV_CPU0, 28, 3),
723 DIV(0, "div_copy", "mout_hpm", DIV_CPU1, 0, 3), 723 DIV(0, "div_copy", "mout_hpm", DIV_CPU1, 0, 3),
724 DIV(0, "div_hpm", "div_copy", DIV_CPU1, 4, 3), 724 DIV(0, "div_hpm", "div_copy", DIV_CPU1, 4, 3),
725 DIV(0, "div_clkout_cpu", "mout_clkout_cpu", CLKOUT_CMU_CPU, 8, 6), 725 DIV(0, "div_clkout_cpu", "mout_clkout_cpu", CLKOUT_CMU_CPU, 8, 6),
@@ -733,8 +733,7 @@ static struct samsung_div_clock exynos4_div_clks[] __initdata = {
733 DIV(0, "div_csis0", "mout_csis0", DIV_CAM, 24, 4), 733 DIV(0, "div_csis0", "mout_csis0", DIV_CAM, 24, 4),
734 DIV(0, "div_csis1", "mout_csis1", DIV_CAM, 28, 4), 734 DIV(0, "div_csis1", "mout_csis1", DIV_CAM, 28, 4),
735 DIV(CLK_SCLK_MFC, "sclk_mfc", "mout_mfc", DIV_MFC, 0, 4), 735 DIV(CLK_SCLK_MFC, "sclk_mfc", "mout_mfc", DIV_MFC, 0, 4),
736 DIV_F(0, "div_g3d", "mout_g3d", DIV_G3D, 0, 4, 736 DIV(CLK_SCLK_G3D, "sclk_g3d", "mout_g3d", DIV_G3D, 0, 4),
737 CLK_SET_RATE_PARENT, 0),
738 DIV(0, "div_fimd0", "mout_fimd0", DIV_LCD0, 0, 4), 737 DIV(0, "div_fimd0", "mout_fimd0", DIV_LCD0, 0, 4),
739 DIV(0, "div_mipi0", "mout_mipi0", DIV_LCD0, 16, 4), 738 DIV(0, "div_mipi0", "mout_mipi0", DIV_LCD0, 16, 4),
740 DIV(0, "div_audio0", "mout_audio0", DIV_MAUDIO, 0, 4), 739 DIV(0, "div_audio0", "mout_audio0", DIV_MAUDIO, 0, 4),
@@ -769,7 +768,6 @@ static struct samsung_div_clock exynos4_div_clks[] __initdata = {
769 DIV(0, "div_spi_pre2", "div_spi2", DIV_PERIL2, 8, 8), 768 DIV(0, "div_spi_pre2", "div_spi2", DIV_PERIL2, 8, 8),
770 DIV(0, "div_audio1", "mout_audio1", DIV_PERIL4, 0, 4), 769 DIV(0, "div_audio1", "mout_audio1", DIV_PERIL4, 0, 4),
771 DIV(0, "div_audio2", "mout_audio2", DIV_PERIL4, 16, 4), 770 DIV(0, "div_audio2", "mout_audio2", DIV_PERIL4, 16, 4),
772 DIV(CLK_ARM_CLK, "arm_clk", "div_core2", DIV_CPU0, 28, 3),
773 DIV(CLK_SCLK_APLL, "sclk_apll", "mout_apll", DIV_CPU0, 24, 3), 771 DIV(CLK_SCLK_APLL, "sclk_apll", "mout_apll", DIV_CPU0, 24, 3),
774 DIV_F(0, "div_mipi_pre0", "div_mipi0", DIV_LCD0, 20, 4, 772 DIV_F(0, "div_mipi_pre0", "div_mipi0", DIV_LCD0, 20, 4,
775 CLK_SET_RATE_PARENT, 0), 773 CLK_SET_RATE_PARENT, 0),
@@ -857,8 +855,7 @@ static struct samsung_gate_clock exynos4_gate_clks[] __initdata = {
857 0), 855 0),
858 GATE(CLK_TSI, "tsi", "aclk133", GATE_IP_FSYS, 4, 0, 0), 856 GATE(CLK_TSI, "tsi", "aclk133", GATE_IP_FSYS, 4, 0, 0),
859 GATE(CLK_SROMC, "sromc", "aclk133", GATE_IP_FSYS, 11, 0, 0), 857 GATE(CLK_SROMC, "sromc", "aclk133", GATE_IP_FSYS, 11, 0, 0),
860 GATE(CLK_SCLK_G3D, "sclk_g3d", "div_g3d", GATE_IP_G3D, 0, 858 GATE(CLK_G3D, "g3d", "aclk200", GATE_IP_G3D, 0, 0, 0),
861 CLK_SET_RATE_PARENT, 0),
862 GATE(CLK_PPMUG3D, "ppmug3d", "aclk200", GATE_IP_G3D, 1, 0, 0), 859 GATE(CLK_PPMUG3D, "ppmug3d", "aclk200", GATE_IP_G3D, 1, 0, 0),
863 GATE(CLK_USB_DEVICE, "usb_device", "aclk133", GATE_IP_FSYS, 13, 0, 0), 860 GATE(CLK_USB_DEVICE, "usb_device", "aclk133", GATE_IP_FSYS, 13, 0, 0),
864 GATE(CLK_ONENAND, "onenand", "aclk133", GATE_IP_FSYS, 15, 0, 0), 861 GATE(CLK_ONENAND, "onenand", "aclk133", GATE_IP_FSYS, 15, 0, 0),
@@ -1183,6 +1180,7 @@ static struct samsung_gate_clock exynos4x12_gate_clks[] __initdata = {
1183 GATE(CLK_SPI1_ISP, "spi1_isp", "aclk200", E4X12_GATE_ISP1, 13, 1180 GATE(CLK_SPI1_ISP, "spi1_isp", "aclk200", E4X12_GATE_ISP1, 13,
1184 CLK_IGNORE_UNUSED | CLK_GET_RATE_NOCACHE, 0), 1181 CLK_IGNORE_UNUSED | CLK_GET_RATE_NOCACHE, 0),
1185 GATE(CLK_G2D, "g2d", "aclk200", GATE_IP_DMC, 23, 0, 0), 1182 GATE(CLK_G2D, "g2d", "aclk200", GATE_IP_DMC, 23, 0, 0),
1183 GATE(CLK_SMMU_G2D, "smmu_g2d", "aclk200", GATE_IP_DMC, 24, 0, 0),
1186 GATE(CLK_TMU_APBIF, "tmu_apbif", "aclk100", E4X12_GATE_IP_PERIR, 17, 0, 1184 GATE(CLK_TMU_APBIF, "tmu_apbif", "aclk100", E4X12_GATE_IP_PERIR, 17, 0,
1187 0), 1185 0),
1188}; 1186};
@@ -1486,7 +1484,7 @@ static void __init exynos4_clk_init(struct device_node *np,
1486 exynos4_soc == EXYNOS4210 ? "Exynos4210" : "Exynos4x12", 1484 exynos4_soc == EXYNOS4210 ? "Exynos4210" : "Exynos4x12",
1487 _get_rate("sclk_apll"), _get_rate("sclk_mpll"), 1485 _get_rate("sclk_apll"), _get_rate("sclk_mpll"),
1488 _get_rate("sclk_epll"), _get_rate("sclk_vpll"), 1486 _get_rate("sclk_epll"), _get_rate("sclk_vpll"),
1489 _get_rate("arm_clk")); 1487 _get_rate("div_core2"));
1490} 1488}
1491 1489
1492 1490
diff --git a/drivers/clk/samsung/clk-exynos5260.c b/drivers/clk/samsung/clk-exynos5260.c
index ce3de97e5f11..2527e39aadcf 100644
--- a/drivers/clk/samsung/clk-exynos5260.c
+++ b/drivers/clk/samsung/clk-exynos5260.c
@@ -1581,7 +1581,7 @@ struct samsung_fixed_rate_clock fixed_rate_clks[] __initdata = {
1581 FRATE(PHYCLK_HDMI_LINK_O_TMDS_CLKHI, "phyclk_hdmi_link_o_tmds_clkhi", 1581 FRATE(PHYCLK_HDMI_LINK_O_TMDS_CLKHI, "phyclk_hdmi_link_o_tmds_clkhi",
1582 NULL, CLK_IS_ROOT, 125000000), 1582 NULL, CLK_IS_ROOT, 125000000),
1583 FRATE(PHYCLK_MIPI_DPHY_4L_M_TXBYTECLKHS, 1583 FRATE(PHYCLK_MIPI_DPHY_4L_M_TXBYTECLKHS,
1584 "phyclk_mipi_dphy_4l_m_txbyteclkhs" , NULL, 1584 "phyclk_mipi_dphy_4l_m_txbyte_clkhs" , NULL,
1585 CLK_IS_ROOT, 187500000), 1585 CLK_IS_ROOT, 187500000),
1586 FRATE(PHYCLK_DPTX_PHY_O_REF_CLK_24M, "phyclk_dptx_phy_o_ref_clk_24m", 1586 FRATE(PHYCLK_DPTX_PHY_O_REF_CLK_24M, "phyclk_dptx_phy_o_ref_clk_24m",
1587 NULL, CLK_IS_ROOT, 24000000), 1587 NULL, CLK_IS_ROOT, 24000000),
diff --git a/drivers/clk/samsung/clk-s3c2410-dclk.c b/drivers/clk/samsung/clk-s3c2410-dclk.c
index 0449cc0458ed..f4f29ed6bd25 100644
--- a/drivers/clk/samsung/clk-s3c2410-dclk.c
+++ b/drivers/clk/samsung/clk-s3c2410-dclk.c
@@ -426,7 +426,6 @@ MODULE_DEVICE_TABLE(platform, s3c24xx_dclk_driver_ids);
426static struct platform_driver s3c24xx_dclk_driver = { 426static struct platform_driver s3c24xx_dclk_driver = {
427 .driver = { 427 .driver = {
428 .name = "s3c24xx-dclk", 428 .name = "s3c24xx-dclk",
429 .owner = THIS_MODULE,
430 .pm = &s3c24xx_dclk_pm_ops, 429 .pm = &s3c24xx_dclk_pm_ops,
431 }, 430 },
432 .probe = s3c24xx_dclk_probe, 431 .probe = s3c24xx_dclk_probe,
diff --git a/drivers/clk/samsung/clk-s3c2412.c b/drivers/clk/samsung/clk-s3c2412.c
index 34af09f6a155..2ceedaf8ce18 100644
--- a/drivers/clk/samsung/clk-s3c2412.c
+++ b/drivers/clk/samsung/clk-s3c2412.c
@@ -14,6 +14,7 @@
14#include <linux/of.h> 14#include <linux/of.h>
15#include <linux/of_address.h> 15#include <linux/of_address.h>
16#include <linux/syscore_ops.h> 16#include <linux/syscore_ops.h>
17#include <linux/reboot.h>
17 18
18#include <dt-bindings/clock/s3c2412.h> 19#include <dt-bindings/clock/s3c2412.h>
19 20
@@ -26,6 +27,7 @@
26#define CLKCON 0x0c 27#define CLKCON 0x0c
27#define CLKDIVN 0x14 28#define CLKDIVN 0x14
28#define CLKSRC 0x1c 29#define CLKSRC 0x1c
30#define SWRST 0x30
29 31
30/* list of PLLs to be registered */ 32/* list of PLLs to be registered */
31enum s3c2412_plls { 33enum s3c2412_plls {
@@ -204,6 +206,28 @@ struct samsung_clock_alias s3c2412_aliases[] __initdata = {
204 ALIAS(MSYSCLK, NULL, "fclk"), 206 ALIAS(MSYSCLK, NULL, "fclk"),
205}; 207};
206 208
209static int s3c2412_restart(struct notifier_block *this,
210 unsigned long mode, void *cmd)
211{
212 /* errata "Watch-dog/Software Reset Problem" specifies that
213 * this reset must be done with the SYSCLK sourced from
214 * EXTCLK instead of FOUT to avoid a glitch in the reset
215 * mechanism.
216 *
217 * See the watchdog section of the S3C2412 manual for more
218 * information on this fix.
219 */
220
221 __raw_writel(0x00, reg_base + CLKSRC);
222 __raw_writel(0x533C2412, reg_base + SWRST);
223 return NOTIFY_DONE;
224}
225
226static struct notifier_block s3c2412_restart_handler = {
227 .notifier_call = s3c2412_restart,
228 .priority = 129,
229};
230
207/* 231/*
208 * fixed rate clocks generated outside the soc 232 * fixed rate clocks generated outside the soc
209 * Only necessary until the devicetree-move is complete 233 * Only necessary until the devicetree-move is complete
@@ -233,6 +257,7 @@ void __init s3c2412_common_clk_init(struct device_node *np, unsigned long xti_f,
233 unsigned long ext_f, void __iomem *base) 257 unsigned long ext_f, void __iomem *base)
234{ 258{
235 struct samsung_clk_provider *ctx; 259 struct samsung_clk_provider *ctx;
260 int ret;
236 reg_base = base; 261 reg_base = base;
237 262
238 if (np) { 263 if (np) {
@@ -267,6 +292,10 @@ void __init s3c2412_common_clk_init(struct device_node *np, unsigned long xti_f,
267 s3c2412_clk_sleep_init(); 292 s3c2412_clk_sleep_init();
268 293
269 samsung_clk_of_add_provider(np, ctx); 294 samsung_clk_of_add_provider(np, ctx);
295
296 ret = register_restart_handler(&s3c2412_restart_handler);
297 if (ret)
298 pr_warn("cannot register restart handler, %d\n", ret);
270} 299}
271 300
272static void __init s3c2412_clk_init(struct device_node *np) 301static void __init s3c2412_clk_init(struct device_node *np)
diff --git a/drivers/clk/samsung/clk-s3c2443.c b/drivers/clk/samsung/clk-s3c2443.c
index c92f853fca9f..0c3c182b902a 100644
--- a/drivers/clk/samsung/clk-s3c2443.c
+++ b/drivers/clk/samsung/clk-s3c2443.c
@@ -14,6 +14,7 @@
14#include <linux/of.h> 14#include <linux/of.h>
15#include <linux/of_address.h> 15#include <linux/of_address.h>
16#include <linux/syscore_ops.h> 16#include <linux/syscore_ops.h>
17#include <linux/reboot.h>
17 18
18#include <dt-bindings/clock/s3c2443.h> 19#include <dt-bindings/clock/s3c2443.h>
19 20
@@ -33,6 +34,7 @@
33#define HCLKCON 0x30 34#define HCLKCON 0x30
34#define PCLKCON 0x34 35#define PCLKCON 0x34
35#define SCLKCON 0x38 36#define SCLKCON 0x38
37#define SWRST 0x44
36 38
37/* the soc types */ 39/* the soc types */
38enum supported_socs { 40enum supported_socs {
@@ -354,6 +356,18 @@ struct samsung_clock_alias s3c2450_aliases[] __initdata = {
354 ALIAS(PCLK_I2C1, "s3c2410-i2c.1", "i2c"), 356 ALIAS(PCLK_I2C1, "s3c2410-i2c.1", "i2c"),
355}; 357};
356 358
359static int s3c2443_restart(struct notifier_block *this,
360 unsigned long mode, void *cmd)
361{
362 __raw_writel(0x533c2443, reg_base + SWRST);
363 return NOTIFY_DONE;
364}
365
366static struct notifier_block s3c2443_restart_handler = {
367 .notifier_call = s3c2443_restart,
368 .priority = 129,
369};
370
357/* 371/*
358 * fixed rate clocks generated outside the soc 372 * fixed rate clocks generated outside the soc
359 * Only necessary until the devicetree-move is complete 373 * Only necessary until the devicetree-move is complete
@@ -378,6 +392,7 @@ void __init s3c2443_common_clk_init(struct device_node *np, unsigned long xti_f,
378 void __iomem *base) 392 void __iomem *base)
379{ 393{
380 struct samsung_clk_provider *ctx; 394 struct samsung_clk_provider *ctx;
395 int ret;
381 reg_base = base; 396 reg_base = base;
382 397
383 if (np) { 398 if (np) {
@@ -447,6 +462,10 @@ void __init s3c2443_common_clk_init(struct device_node *np, unsigned long xti_f,
447 s3c2443_clk_sleep_init(); 462 s3c2443_clk_sleep_init();
448 463
449 samsung_clk_of_add_provider(np, ctx); 464 samsung_clk_of_add_provider(np, ctx);
465
466 ret = register_restart_handler(&s3c2443_restart_handler);
467 if (ret)
468 pr_warn("cannot register restart handler, %d\n", ret);
450} 469}
451 470
452static void __init s3c2416_clk_init(struct device_node *np) 471static void __init s3c2416_clk_init(struct device_node *np)
diff --git a/drivers/clk/shmobile/clk-rcar-gen2.c b/drivers/clk/shmobile/clk-rcar-gen2.c
index dff7f79a19b9..e996425d06a9 100644
--- a/drivers/clk/shmobile/clk-rcar-gen2.c
+++ b/drivers/clk/shmobile/clk-rcar-gen2.c
@@ -202,6 +202,7 @@ static const struct clk_div_table cpg_sdh_div_table[] = {
202}; 202};
203 203
204static const struct clk_div_table cpg_sd01_div_table[] = { 204static const struct clk_div_table cpg_sd01_div_table[] = {
205 { 4, 8 },
205 { 5, 12 }, { 6, 16 }, { 7, 18 }, { 8, 24 }, 206 { 5, 12 }, { 6, 16 }, { 7, 18 }, { 8, 24 },
206 { 10, 36 }, { 11, 48 }, { 12, 10 }, { 0, 0 }, 207 { 10, 36 }, { 11, 48 }, { 12, 10 }, { 0, 0 },
207}; 208};
diff --git a/drivers/clk/sunxi/Makefile b/drivers/clk/sunxi/Makefile
index 6850cba35871..7ddc2b553846 100644
--- a/drivers/clk/sunxi/Makefile
+++ b/drivers/clk/sunxi/Makefile
@@ -5,6 +5,8 @@
5obj-y += clk-sunxi.o clk-factors.o 5obj-y += clk-sunxi.o clk-factors.o
6obj-y += clk-a10-hosc.o 6obj-y += clk-a10-hosc.o
7obj-y += clk-a20-gmac.o 7obj-y += clk-a20-gmac.o
8obj-y += clk-mod0.o
9obj-y += clk-sun8i-mbus.o
8 10
9obj-$(CONFIG_MFD_SUN6I_PRCM) += \ 11obj-$(CONFIG_MFD_SUN6I_PRCM) += \
10 clk-sun6i-ar100.o clk-sun6i-apb0.o clk-sun6i-apb0-gates.o \ 12 clk-sun6i-ar100.o clk-sun6i-apb0.o clk-sun6i-apb0-gates.o \
diff --git a/drivers/clk/sunxi/clk-factors.c b/drivers/clk/sunxi/clk-factors.c
index 2057c8ac648f..f83ba097126c 100644
--- a/drivers/clk/sunxi/clk-factors.c
+++ b/drivers/clk/sunxi/clk-factors.c
@@ -9,18 +9,18 @@
9 */ 9 */
10 10
11#include <linux/clk-provider.h> 11#include <linux/clk-provider.h>
12#include <linux/delay.h>
13#include <linux/err.h>
14#include <linux/io.h>
12#include <linux/module.h> 15#include <linux/module.h>
16#include <linux/of_address.h>
13#include <linux/slab.h> 17#include <linux/slab.h>
14#include <linux/io.h>
15#include <linux/err.h>
16#include <linux/string.h> 18#include <linux/string.h>
17 19
18#include <linux/delay.h>
19
20#include "clk-factors.h" 20#include "clk-factors.h"
21 21
22/* 22/*
23 * DOC: basic adjustable factor-based clock that cannot gate 23 * DOC: basic adjustable factor-based clock
24 * 24 *
25 * Traits of this clock: 25 * Traits of this clock:
26 * prepare - clk_prepare only ensures that parents are prepared 26 * prepare - clk_prepare only ensures that parents are prepared
@@ -32,6 +32,8 @@
32 32
33#define to_clk_factors(_hw) container_of(_hw, struct clk_factors, hw) 33#define to_clk_factors(_hw) container_of(_hw, struct clk_factors, hw)
34 34
35#define FACTORS_MAX_PARENTS 5
36
35#define SETMASK(len, pos) (((1U << (len)) - 1) << (pos)) 37#define SETMASK(len, pos) (((1U << (len)) - 1) << (pos))
36#define CLRMASK(len, pos) (~(SETMASK(len, pos))) 38#define CLRMASK(len, pos) (~(SETMASK(len, pos)))
37#define FACTOR_GET(bit, len, reg) (((reg) & SETMASK(len, bit)) >> (bit)) 39#define FACTOR_GET(bit, len, reg) (((reg) & SETMASK(len, bit)) >> (bit))
@@ -147,9 +149,96 @@ static int clk_factors_set_rate(struct clk_hw *hw, unsigned long rate,
147 return 0; 149 return 0;
148} 150}
149 151
150const struct clk_ops clk_factors_ops = { 152static const struct clk_ops clk_factors_ops = {
151 .determine_rate = clk_factors_determine_rate, 153 .determine_rate = clk_factors_determine_rate,
152 .recalc_rate = clk_factors_recalc_rate, 154 .recalc_rate = clk_factors_recalc_rate,
153 .round_rate = clk_factors_round_rate, 155 .round_rate = clk_factors_round_rate,
154 .set_rate = clk_factors_set_rate, 156 .set_rate = clk_factors_set_rate,
155}; 157};
158
159struct clk * __init sunxi_factors_register(struct device_node *node,
160 const struct factors_data *data,
161 spinlock_t *lock)
162{
163 struct clk *clk;
164 struct clk_factors *factors;
165 struct clk_gate *gate = NULL;
166 struct clk_mux *mux = NULL;
167 struct clk_hw *gate_hw = NULL;
168 struct clk_hw *mux_hw = NULL;
169 const char *clk_name = node->name;
170 const char *parents[FACTORS_MAX_PARENTS];
171 void __iomem *reg;
172 int i = 0;
173
174 reg = of_iomap(node, 0);
175
176 /* if we have a mux, we will have >1 parents */
177 while (i < FACTORS_MAX_PARENTS &&
178 (parents[i] = of_clk_get_parent_name(node, i)) != NULL)
179 i++;
180
181 /*
182 * some factor clocks, such as pll5 and pll6, may have multiple
183 * outputs, and have their name designated in factors_data
184 */
185 if (data->name)
186 clk_name = data->name;
187 else
188 of_property_read_string(node, "clock-output-names", &clk_name);
189
190 factors = kzalloc(sizeof(struct clk_factors), GFP_KERNEL);
191 if (!factors)
192 return NULL;
193
194 /* set up factors properties */
195 factors->reg = reg;
196 factors->config = data->table;
197 factors->get_factors = data->getter;
198 factors->lock = lock;
199
200 /* Add a gate if this factor clock can be gated */
201 if (data->enable) {
202 gate = kzalloc(sizeof(struct clk_gate), GFP_KERNEL);
203 if (!gate) {
204 kfree(factors);
205 return NULL;
206 }
207
208 /* set up gate properties */
209 gate->reg = reg;
210 gate->bit_idx = data->enable;
211 gate->lock = factors->lock;
212 gate_hw = &gate->hw;
213 }
214
215 /* Add a mux if this factor clock can be muxed */
216 if (data->mux) {
217 mux = kzalloc(sizeof(struct clk_mux), GFP_KERNEL);
218 if (!mux) {
219 kfree(factors);
220 kfree(gate);
221 return NULL;
222 }
223
224 /* set up gate properties */
225 mux->reg = reg;
226 mux->shift = data->mux;
227 mux->mask = SUNXI_FACTORS_MUX_MASK;
228 mux->lock = factors->lock;
229 mux_hw = &mux->hw;
230 }
231
232 clk = clk_register_composite(NULL, clk_name,
233 parents, i,
234 mux_hw, &clk_mux_ops,
235 &factors->hw, &clk_factors_ops,
236 gate_hw, &clk_gate_ops, 0);
237
238 if (!IS_ERR(clk)) {
239 of_clk_add_provider(node, of_clk_src_simple_get, clk);
240 clk_register_clkdev(clk, clk_name, NULL);
241 }
242
243 return clk;
244}
diff --git a/drivers/clk/sunxi/clk-factors.h b/drivers/clk/sunxi/clk-factors.h
index d2d0efa39379..9913840018d3 100644
--- a/drivers/clk/sunxi/clk-factors.h
+++ b/drivers/clk/sunxi/clk-factors.h
@@ -3,9 +3,12 @@
3 3
4#include <linux/clk-provider.h> 4#include <linux/clk-provider.h>
5#include <linux/clkdev.h> 5#include <linux/clkdev.h>
6#include <linux/spinlock.h>
6 7
7#define SUNXI_FACTORS_NOT_APPLICABLE (0) 8#define SUNXI_FACTORS_NOT_APPLICABLE (0)
8 9
10#define SUNXI_FACTORS_MUX_MASK 0x3
11
9struct clk_factors_config { 12struct clk_factors_config {
10 u8 nshift; 13 u8 nshift;
11 u8 nwidth; 14 u8 nwidth;
@@ -18,6 +21,14 @@ struct clk_factors_config {
18 u8 n_start; 21 u8 n_start;
19}; 22};
20 23
24struct factors_data {
25 int enable;
26 int mux;
27 struct clk_factors_config *table;
28 void (*getter) (u32 *rate, u32 parent_rate, u8 *n, u8 *k, u8 *m, u8 *p);
29 const char *name;
30};
31
21struct clk_factors { 32struct clk_factors {
22 struct clk_hw hw; 33 struct clk_hw hw;
23 void __iomem *reg; 34 void __iomem *reg;
@@ -26,5 +37,8 @@ struct clk_factors {
26 spinlock_t *lock; 37 spinlock_t *lock;
27}; 38};
28 39
29extern const struct clk_ops clk_factors_ops; 40struct clk * __init sunxi_factors_register(struct device_node *node,
41 const struct factors_data *data,
42 spinlock_t *lock);
43
30#endif 44#endif
diff --git a/drivers/clk/sunxi/clk-mod0.c b/drivers/clk/sunxi/clk-mod0.c
new file mode 100644
index 000000000000..4a563850ee6e
--- /dev/null
+++ b/drivers/clk/sunxi/clk-mod0.c
@@ -0,0 +1,283 @@
1/*
2 * Copyright 2013 Emilio López
3 *
4 * Emilio López <emilio@elopez.com.ar>
5 *
6 * This program is free software; you can redistribute it and/or modify
7 * it under the terms of the GNU General Public License as published by
8 * the Free Software Foundation; either version 2 of the License, or
9 * (at your option) any later version.
10 *
11 * This program is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 * GNU General Public License for more details.
15 */
16
17#include <linux/clk-provider.h>
18#include <linux/clkdev.h>
19#include <linux/of_address.h>
20
21#include "clk-factors.h"
22
23/**
24 * sun4i_get_mod0_factors() - calculates m, n factors for MOD0-style clocks
25 * MOD0 rate is calculated as follows
26 * rate = (parent_rate >> p) / (m + 1);
27 */
28
29static void sun4i_a10_get_mod0_factors(u32 *freq, u32 parent_rate,
30 u8 *n, u8 *k, u8 *m, u8 *p)
31{
32 u8 div, calcm, calcp;
33
34 /* These clocks can only divide, so we will never be able to achieve
35 * frequencies higher than the parent frequency */
36 if (*freq > parent_rate)
37 *freq = parent_rate;
38
39 div = DIV_ROUND_UP(parent_rate, *freq);
40
41 if (div < 16)
42 calcp = 0;
43 else if (div / 2 < 16)
44 calcp = 1;
45 else if (div / 4 < 16)
46 calcp = 2;
47 else
48 calcp = 3;
49
50 calcm = DIV_ROUND_UP(div, 1 << calcp);
51
52 *freq = (parent_rate >> calcp) / calcm;
53
54 /* we were called to round the frequency, we can now return */
55 if (n == NULL)
56 return;
57
58 *m = calcm - 1;
59 *p = calcp;
60}
61
62/* user manual says "n" but it's really "p" */
63static struct clk_factors_config sun4i_a10_mod0_config = {
64 .mshift = 0,
65 .mwidth = 4,
66 .pshift = 16,
67 .pwidth = 2,
68};
69
70static const struct factors_data sun4i_a10_mod0_data __initconst = {
71 .enable = 31,
72 .mux = 24,
73 .table = &sun4i_a10_mod0_config,
74 .getter = sun4i_a10_get_mod0_factors,
75};
76
77static DEFINE_SPINLOCK(sun4i_a10_mod0_lock);
78
79static void __init sun4i_a10_mod0_setup(struct device_node *node)
80{
81 sunxi_factors_register(node, &sun4i_a10_mod0_data, &sun4i_a10_mod0_lock);
82}
83CLK_OF_DECLARE(sun4i_a10_mod0, "allwinner,sun4i-a10-mod0-clk", sun4i_a10_mod0_setup);
84
85static DEFINE_SPINLOCK(sun5i_a13_mbus_lock);
86
87static void __init sun5i_a13_mbus_setup(struct device_node *node)
88{
89 struct clk *mbus = sunxi_factors_register(node, &sun4i_a10_mod0_data, &sun5i_a13_mbus_lock);
90
91 /* The MBUS clocks needs to be always enabled */
92 __clk_get(mbus);
93 clk_prepare_enable(mbus);
94}
95CLK_OF_DECLARE(sun5i_a13_mbus, "allwinner,sun5i-a13-mbus-clk", sun5i_a13_mbus_setup);
96
97struct mmc_phase_data {
98 u8 offset;
99};
100
101struct mmc_phase {
102 struct clk_hw hw;
103 void __iomem *reg;
104 struct mmc_phase_data *data;
105 spinlock_t *lock;
106};
107
108#define to_mmc_phase(_hw) container_of(_hw, struct mmc_phase, hw)
109
110static int mmc_get_phase(struct clk_hw *hw)
111{
112 struct clk *mmc, *mmc_parent, *clk = hw->clk;
113 struct mmc_phase *phase = to_mmc_phase(hw);
114 unsigned int mmc_rate, mmc_parent_rate;
115 u16 step, mmc_div;
116 u32 value;
117 u8 delay;
118
119 value = readl(phase->reg);
120 delay = (value >> phase->data->offset) & 0x3;
121
122 if (!delay)
123 return 180;
124
125 /* Get the main MMC clock */
126 mmc = clk_get_parent(clk);
127 if (!mmc)
128 return -EINVAL;
129
130 /* And its rate */
131 mmc_rate = clk_get_rate(mmc);
132 if (!mmc_rate)
133 return -EINVAL;
134
135 /* Now, get the MMC parent (most likely some PLL) */
136 mmc_parent = clk_get_parent(mmc);
137 if (!mmc_parent)
138 return -EINVAL;
139
140 /* And its rate */
141 mmc_parent_rate = clk_get_rate(mmc_parent);
142 if (!mmc_parent_rate)
143 return -EINVAL;
144
145 /* Get MMC clock divider */
146 mmc_div = mmc_parent_rate / mmc_rate;
147
148 step = DIV_ROUND_CLOSEST(360, mmc_div);
149 return delay * step;
150}
151
152static int mmc_set_phase(struct clk_hw *hw, int degrees)
153{
154 struct clk *mmc, *mmc_parent, *clk = hw->clk;
155 struct mmc_phase *phase = to_mmc_phase(hw);
156 unsigned int mmc_rate, mmc_parent_rate;
157 unsigned long flags;
158 u32 value;
159 u8 delay;
160
161 /* Get the main MMC clock */
162 mmc = clk_get_parent(clk);
163 if (!mmc)
164 return -EINVAL;
165
166 /* And its rate */
167 mmc_rate = clk_get_rate(mmc);
168 if (!mmc_rate)
169 return -EINVAL;
170
171 /* Now, get the MMC parent (most likely some PLL) */
172 mmc_parent = clk_get_parent(mmc);
173 if (!mmc_parent)
174 return -EINVAL;
175
176 /* And its rate */
177 mmc_parent_rate = clk_get_rate(mmc_parent);
178 if (!mmc_parent_rate)
179 return -EINVAL;
180
181 if (degrees != 180) {
182 u16 step, mmc_div;
183
184 /* Get MMC clock divider */
185 mmc_div = mmc_parent_rate / mmc_rate;
186
187 /*
188 * We can only outphase the clocks by multiple of the
189 * PLL's period.
190 *
191 * Since the MMC clock in only a divider, and the
192 * formula to get the outphasing in degrees is deg =
193 * 360 * delta / period
194 *
195 * If we simplify this formula, we can see that the
196 * only thing that we're concerned about is the number
197 * of period we want to outphase our clock from, and
198 * the divider set by the MMC clock.
199 */
200 step = DIV_ROUND_CLOSEST(360, mmc_div);
201 delay = DIV_ROUND_CLOSEST(degrees, step);
202 } else {
203 delay = 0;
204 }
205
206 spin_lock_irqsave(phase->lock, flags);
207 value = readl(phase->reg);
208 value &= ~GENMASK(phase->data->offset + 3, phase->data->offset);
209 value |= delay << phase->data->offset;
210 writel(value, phase->reg);
211 spin_unlock_irqrestore(phase->lock, flags);
212
213 return 0;
214}
215
216static const struct clk_ops mmc_clk_ops = {
217 .get_phase = mmc_get_phase,
218 .set_phase = mmc_set_phase,
219};
220
221static void __init sun4i_a10_mmc_phase_setup(struct device_node *node,
222 struct mmc_phase_data *data)
223{
224 const char *parent_names[1] = { of_clk_get_parent_name(node, 0) };
225 struct clk_init_data init = {
226 .num_parents = 1,
227 .parent_names = parent_names,
228 .ops = &mmc_clk_ops,
229 };
230
231 struct mmc_phase *phase;
232 struct clk *clk;
233
234 phase = kmalloc(sizeof(*phase), GFP_KERNEL);
235 if (!phase)
236 return;
237
238 phase->hw.init = &init;
239
240 phase->reg = of_iomap(node, 0);
241 if (!phase->reg)
242 goto err_free;
243
244 phase->data = data;
245 phase->lock = &sun4i_a10_mod0_lock;
246
247 if (of_property_read_string(node, "clock-output-names", &init.name))
248 init.name = node->name;
249
250 clk = clk_register(NULL, &phase->hw);
251 if (IS_ERR(clk))
252 goto err_unmap;
253
254 of_clk_add_provider(node, of_clk_src_simple_get, clk);
255
256 return;
257
258err_unmap:
259 iounmap(phase->reg);
260err_free:
261 kfree(phase);
262}
263
264
265static struct mmc_phase_data mmc_output_clk = {
266 .offset = 8,
267};
268
269static struct mmc_phase_data mmc_sample_clk = {
270 .offset = 20,
271};
272
273static void __init sun4i_a10_mmc_output_setup(struct device_node *node)
274{
275 sun4i_a10_mmc_phase_setup(node, &mmc_output_clk);
276}
277CLK_OF_DECLARE(sun4i_a10_mmc_output, "allwinner,sun4i-a10-mmc-output-clk", sun4i_a10_mmc_output_setup);
278
279static void __init sun4i_a10_mmc_sample_setup(struct device_node *node)
280{
281 sun4i_a10_mmc_phase_setup(node, &mmc_sample_clk);
282}
283CLK_OF_DECLARE(sun4i_a10_mmc_sample, "allwinner,sun4i-a10-mmc-sample-clk", sun4i_a10_mmc_sample_setup);
diff --git a/drivers/clk/sunxi/clk-sun6i-apb0-gates.c b/drivers/clk/sunxi/clk-sun6i-apb0-gates.c
index e10d0521ec76..64f3e46d383c 100644
--- a/drivers/clk/sunxi/clk-sun6i-apb0-gates.c
+++ b/drivers/clk/sunxi/clk-sun6i-apb0-gates.c
@@ -99,7 +99,6 @@ static int sun6i_a31_apb0_gates_clk_probe(struct platform_device *pdev)
99static struct platform_driver sun6i_a31_apb0_gates_clk_driver = { 99static struct platform_driver sun6i_a31_apb0_gates_clk_driver = {
100 .driver = { 100 .driver = {
101 .name = "sun6i-a31-apb0-gates-clk", 101 .name = "sun6i-a31-apb0-gates-clk",
102 .owner = THIS_MODULE,
103 .of_match_table = sun6i_a31_apb0_gates_clk_dt_ids, 102 .of_match_table = sun6i_a31_apb0_gates_clk_dt_ids,
104 }, 103 },
105 .probe = sun6i_a31_apb0_gates_clk_probe, 104 .probe = sun6i_a31_apb0_gates_clk_probe,
diff --git a/drivers/clk/sunxi/clk-sun6i-apb0.c b/drivers/clk/sunxi/clk-sun6i-apb0.c
index 1fa23371c8c6..70763600aeae 100644
--- a/drivers/clk/sunxi/clk-sun6i-apb0.c
+++ b/drivers/clk/sunxi/clk-sun6i-apb0.c
@@ -65,7 +65,6 @@ static const struct of_device_id sun6i_a31_apb0_clk_dt_ids[] = {
65static struct platform_driver sun6i_a31_apb0_clk_driver = { 65static struct platform_driver sun6i_a31_apb0_clk_driver = {
66 .driver = { 66 .driver = {
67 .name = "sun6i-a31-apb0-clk", 67 .name = "sun6i-a31-apb0-clk",
68 .owner = THIS_MODULE,
69 .of_match_table = sun6i_a31_apb0_clk_dt_ids, 68 .of_match_table = sun6i_a31_apb0_clk_dt_ids,
70 }, 69 },
71 .probe = sun6i_a31_apb0_clk_probe, 70 .probe = sun6i_a31_apb0_clk_probe,
diff --git a/drivers/clk/sunxi/clk-sun6i-ar100.c b/drivers/clk/sunxi/clk-sun6i-ar100.c
index eca8ca025b6a..acca53290be2 100644
--- a/drivers/clk/sunxi/clk-sun6i-ar100.c
+++ b/drivers/clk/sunxi/clk-sun6i-ar100.c
@@ -221,7 +221,6 @@ static const struct of_device_id sun6i_a31_ar100_clk_dt_ids[] = {
221static struct platform_driver sun6i_a31_ar100_clk_driver = { 221static struct platform_driver sun6i_a31_ar100_clk_driver = {
222 .driver = { 222 .driver = {
223 .name = "sun6i-a31-ar100-clk", 223 .name = "sun6i-a31-ar100-clk",
224 .owner = THIS_MODULE,
225 .of_match_table = sun6i_a31_ar100_clk_dt_ids, 224 .of_match_table = sun6i_a31_ar100_clk_dt_ids,
226 }, 225 },
227 .probe = sun6i_a31_ar100_clk_probe, 226 .probe = sun6i_a31_ar100_clk_probe,
diff --git a/drivers/clk/sunxi/clk-sun8i-apb0.c b/drivers/clk/sunxi/clk-sun8i-apb0.c
index 1f5ba9b4b8cd..155d0022194f 100644
--- a/drivers/clk/sunxi/clk-sun8i-apb0.c
+++ b/drivers/clk/sunxi/clk-sun8i-apb0.c
@@ -56,7 +56,6 @@ static const struct of_device_id sun8i_a23_apb0_clk_dt_ids[] = {
56static struct platform_driver sun8i_a23_apb0_clk_driver = { 56static struct platform_driver sun8i_a23_apb0_clk_driver = {
57 .driver = { 57 .driver = {
58 .name = "sun8i-a23-apb0-clk", 58 .name = "sun8i-a23-apb0-clk",
59 .owner = THIS_MODULE,
60 .of_match_table = sun8i_a23_apb0_clk_dt_ids, 59 .of_match_table = sun8i_a23_apb0_clk_dt_ids,
61 }, 60 },
62 .probe = sun8i_a23_apb0_clk_probe, 61 .probe = sun8i_a23_apb0_clk_probe,
diff --git a/drivers/clk/sunxi/clk-sun8i-mbus.c b/drivers/clk/sunxi/clk-sun8i-mbus.c
new file mode 100644
index 000000000000..8e49b44cee41
--- /dev/null
+++ b/drivers/clk/sunxi/clk-sun8i-mbus.c
@@ -0,0 +1,78 @@
1/*
2 * Copyright 2014 Chen-Yu Tsai
3 *
4 * Chen-Yu Tsai <wens@csie.org>
5 *
6 * This program is free software; you can redistribute it and/or modify
7 * it under the terms of the GNU General Public License as published by
8 * the Free Software Foundation; either version 2 of the License, or
9 * (at your option) any later version.
10 *
11 * This program is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 * GNU General Public License for more details.
15 */
16
17#include <linux/clk-provider.h>
18#include <linux/clkdev.h>
19#include <linux/of_address.h>
20
21#include "clk-factors.h"
22
23/**
24 * sun8i_a23_get_mbus_factors() - calculates m factor for MBUS clocks
25 * MBUS rate is calculated as follows
26 * rate = parent_rate / (m + 1);
27 */
28
29static void sun8i_a23_get_mbus_factors(u32 *freq, u32 parent_rate,
30 u8 *n, u8 *k, u8 *m, u8 *p)
31{
32 u8 div;
33
34 /*
35 * These clocks can only divide, so we will never be able to
36 * achieve frequencies higher than the parent frequency
37 */
38 if (*freq > parent_rate)
39 *freq = parent_rate;
40
41 div = DIV_ROUND_UP(parent_rate, *freq);
42
43 if (div > 8)
44 div = 8;
45
46 *freq = parent_rate / div;
47
48 /* we were called to round the frequency, we can now return */
49 if (m == NULL)
50 return;
51
52 *m = div - 1;
53}
54
55static struct clk_factors_config sun8i_a23_mbus_config = {
56 .mshift = 0,
57 .mwidth = 3,
58};
59
60static const struct factors_data sun8i_a23_mbus_data __initconst = {
61 .enable = 31,
62 .mux = 24,
63 .table = &sun8i_a23_mbus_config,
64 .getter = sun8i_a23_get_mbus_factors,
65};
66
67static DEFINE_SPINLOCK(sun8i_a23_mbus_lock);
68
69static void __init sun8i_a23_mbus_setup(struct device_node *node)
70{
71 struct clk *mbus = sunxi_factors_register(node, &sun8i_a23_mbus_data,
72 &sun8i_a23_mbus_lock);
73
74 /* The MBUS clocks needs to be always enabled */
75 __clk_get(mbus);
76 clk_prepare_enable(mbus);
77}
78CLK_OF_DECLARE(sun8i_a23_mbus, "allwinner,sun8i-a23-mbus-clk", sun8i_a23_mbus_setup);
diff --git a/drivers/clk/sunxi/clk-sunxi.c b/drivers/clk/sunxi/clk-sunxi.c
index b654b7b1d137..d5dc951264ca 100644
--- a/drivers/clk/sunxi/clk-sunxi.c
+++ b/drivers/clk/sunxi/clk-sunxi.c
@@ -19,6 +19,7 @@
19#include <linux/of.h> 19#include <linux/of.h>
20#include <linux/of_address.h> 20#include <linux/of_address.h>
21#include <linux/reset-controller.h> 21#include <linux/reset-controller.h>
22#include <linux/spinlock.h>
22 23
23#include "clk-factors.h" 24#include "clk-factors.h"
24 25
@@ -319,46 +320,6 @@ static void sun4i_get_apb1_factors(u32 *freq, u32 parent_rate,
319 320
320 321
321 322
322/**
323 * sun4i_get_mod0_factors() - calculates m, n factors for MOD0-style clocks
324 * MOD0 rate is calculated as follows
325 * rate = (parent_rate >> p) / (m + 1);
326 */
327
328static void sun4i_get_mod0_factors(u32 *freq, u32 parent_rate,
329 u8 *n, u8 *k, u8 *m, u8 *p)
330{
331 u8 div, calcm, calcp;
332
333 /* These clocks can only divide, so we will never be able to achieve
334 * frequencies higher than the parent frequency */
335 if (*freq > parent_rate)
336 *freq = parent_rate;
337
338 div = DIV_ROUND_UP(parent_rate, *freq);
339
340 if (div < 16)
341 calcp = 0;
342 else if (div / 2 < 16)
343 calcp = 1;
344 else if (div / 4 < 16)
345 calcp = 2;
346 else
347 calcp = 3;
348
349 calcm = DIV_ROUND_UP(div, 1 << calcp);
350
351 *freq = (parent_rate >> calcp) / calcm;
352
353 /* we were called to round the frequency, we can now return */
354 if (n == NULL)
355 return;
356
357 *m = calcm - 1;
358 *p = calcp;
359}
360
361
362 323
363/** 324/**
364 * sun7i_a20_get_out_factors() - calculates m, p factors for CLK_OUT_A/B 325 * sun7i_a20_get_out_factors() - calculates m, p factors for CLK_OUT_A/B
@@ -440,16 +401,6 @@ EXPORT_SYMBOL(clk_sunxi_mmc_phase_control);
440 * sunxi_factors_clk_setup() - Setup function for factor clocks 401 * sunxi_factors_clk_setup() - Setup function for factor clocks
441 */ 402 */
442 403
443#define SUNXI_FACTORS_MUX_MASK 0x3
444
445struct factors_data {
446 int enable;
447 int mux;
448 struct clk_factors_config *table;
449 void (*getter) (u32 *rate, u32 parent_rate, u8 *n, u8 *k, u8 *m, u8 *p);
450 const char *name;
451};
452
453static struct clk_factors_config sun4i_pll1_config = { 404static struct clk_factors_config sun4i_pll1_config = {
454 .nshift = 8, 405 .nshift = 8,
455 .nwidth = 5, 406 .nwidth = 5,
@@ -504,14 +455,6 @@ static struct clk_factors_config sun4i_apb1_config = {
504}; 455};
505 456
506/* user manual says "n" but it's really "p" */ 457/* user manual says "n" but it's really "p" */
507static struct clk_factors_config sun4i_mod0_config = {
508 .mshift = 0,
509 .mwidth = 4,
510 .pshift = 16,
511 .pwidth = 2,
512};
513
514/* user manual says "n" but it's really "p" */
515static struct clk_factors_config sun7i_a20_out_config = { 458static struct clk_factors_config sun7i_a20_out_config = {
516 .mshift = 8, 459 .mshift = 8,
517 .mwidth = 5, 460 .mwidth = 5,
@@ -568,13 +511,6 @@ static const struct factors_data sun4i_apb1_data __initconst = {
568 .getter = sun4i_get_apb1_factors, 511 .getter = sun4i_get_apb1_factors,
569}; 512};
570 513
571static const struct factors_data sun4i_mod0_data __initconst = {
572 .enable = 31,
573 .mux = 24,
574 .table = &sun4i_mod0_config,
575 .getter = sun4i_get_mod0_factors,
576};
577
578static const struct factors_data sun7i_a20_out_data __initconst = { 514static const struct factors_data sun7i_a20_out_data __initconst = {
579 .enable = 31, 515 .enable = 31,
580 .mux = 24, 516 .mux = 24,
@@ -583,89 +519,9 @@ static const struct factors_data sun7i_a20_out_data __initconst = {
583}; 519};
584 520
585static struct clk * __init sunxi_factors_clk_setup(struct device_node *node, 521static struct clk * __init sunxi_factors_clk_setup(struct device_node *node,
586 const struct factors_data *data) 522 const struct factors_data *data)
587{ 523{
588 struct clk *clk; 524 return sunxi_factors_register(node, data, &clk_lock);
589 struct clk_factors *factors;
590 struct clk_gate *gate = NULL;
591 struct clk_mux *mux = NULL;
592 struct clk_hw *gate_hw = NULL;
593 struct clk_hw *mux_hw = NULL;
594 const char *clk_name = node->name;
595 const char *parents[SUNXI_MAX_PARENTS];
596 void __iomem *reg;
597 int i = 0;
598
599 reg = of_iomap(node, 0);
600
601 /* if we have a mux, we will have >1 parents */
602 while (i < SUNXI_MAX_PARENTS &&
603 (parents[i] = of_clk_get_parent_name(node, i)) != NULL)
604 i++;
605
606 /*
607 * some factor clocks, such as pll5 and pll6, may have multiple
608 * outputs, and have their name designated in factors_data
609 */
610 if (data->name)
611 clk_name = data->name;
612 else
613 of_property_read_string(node, "clock-output-names", &clk_name);
614
615 factors = kzalloc(sizeof(struct clk_factors), GFP_KERNEL);
616 if (!factors)
617 return NULL;
618
619 /* Add a gate if this factor clock can be gated */
620 if (data->enable) {
621 gate = kzalloc(sizeof(struct clk_gate), GFP_KERNEL);
622 if (!gate) {
623 kfree(factors);
624 return NULL;
625 }
626
627 /* set up gate properties */
628 gate->reg = reg;
629 gate->bit_idx = data->enable;
630 gate->lock = &clk_lock;
631 gate_hw = &gate->hw;
632 }
633
634 /* Add a mux if this factor clock can be muxed */
635 if (data->mux) {
636 mux = kzalloc(sizeof(struct clk_mux), GFP_KERNEL);
637 if (!mux) {
638 kfree(factors);
639 kfree(gate);
640 return NULL;
641 }
642
643 /* set up gate properties */
644 mux->reg = reg;
645 mux->shift = data->mux;
646 mux->mask = SUNXI_FACTORS_MUX_MASK;
647 mux->lock = &clk_lock;
648 mux_hw = &mux->hw;
649 }
650
651 /* set up factors properties */
652 factors->reg = reg;
653 factors->config = data->table;
654 factors->get_factors = data->getter;
655 factors->lock = &clk_lock;
656
657 clk = clk_register_composite(NULL, clk_name,
658 parents, i,
659 mux_hw, &clk_mux_ops,
660 &factors->hw, &clk_factors_ops,
661 gate_hw, &clk_gate_ops, 0);
662
663 if (!IS_ERR(clk)) {
664 of_clk_add_provider(node, of_clk_src_simple_get, clk);
665 clk_register_clkdev(clk, clk_name, NULL);
666 }
667
668 return clk;
669} 525}
670 526
671 527
@@ -762,10 +618,19 @@ static const struct div_data sun4i_ahb_data __initconst = {
762 .width = 2, 618 .width = 2,
763}; 619};
764 620
621static const struct clk_div_table sun4i_apb0_table[] __initconst = {
622 { .val = 0, .div = 2 },
623 { .val = 1, .div = 2 },
624 { .val = 2, .div = 4 },
625 { .val = 3, .div = 8 },
626 { } /* sentinel */
627};
628
765static const struct div_data sun4i_apb0_data __initconst = { 629static const struct div_data sun4i_apb0_data __initconst = {
766 .shift = 8, 630 .shift = 8,
767 .pow = 1, 631 .pow = 1,
768 .width = 2, 632 .width = 2,
633 .table = sun4i_apb0_table,
769}; 634};
770 635
771static const struct div_data sun6i_a31_apb2_div_data __initconst = { 636static const struct div_data sun6i_a31_apb2_div_data __initconst = {
@@ -1199,7 +1064,6 @@ static const struct of_device_id clk_factors_match[] __initconst = {
1199 {.compatible = "allwinner,sun7i-a20-pll4-clk", .data = &sun7i_a20_pll4_data,}, 1064 {.compatible = "allwinner,sun7i-a20-pll4-clk", .data = &sun7i_a20_pll4_data,},
1200 {.compatible = "allwinner,sun6i-a31-pll6-clk", .data = &sun6i_a31_pll6_data,}, 1065 {.compatible = "allwinner,sun6i-a31-pll6-clk", .data = &sun6i_a31_pll6_data,},
1201 {.compatible = "allwinner,sun4i-a10-apb1-clk", .data = &sun4i_apb1_data,}, 1066 {.compatible = "allwinner,sun4i-a10-apb1-clk", .data = &sun4i_apb1_data,},
1202 {.compatible = "allwinner,sun4i-a10-mod0-clk", .data = &sun4i_mod0_data,},
1203 {.compatible = "allwinner,sun7i-a20-out-clk", .data = &sun7i_a20_out_data,}, 1067 {.compatible = "allwinner,sun7i-a20-out-clk", .data = &sun7i_a20_out_data,},
1204 {} 1068 {}
1205}; 1069};
@@ -1311,7 +1175,6 @@ static void __init sun4i_a10_init_clocks(struct device_node *node)
1311CLK_OF_DECLARE(sun4i_a10_clk_init, "allwinner,sun4i-a10", sun4i_a10_init_clocks); 1175CLK_OF_DECLARE(sun4i_a10_clk_init, "allwinner,sun4i-a10", sun4i_a10_init_clocks);
1312 1176
1313static const char *sun5i_critical_clocks[] __initdata = { 1177static const char *sun5i_critical_clocks[] __initdata = {
1314 "mbus",
1315 "pll5_ddr", 1178 "pll5_ddr",
1316 "ahb_sdram", 1179 "ahb_sdram",
1317}; 1180};
diff --git a/drivers/clk/tegra/clk-tegra124.c b/drivers/clk/tegra/clk-tegra124.c
index 9525c684d149..e3a85842ce0c 100644
--- a/drivers/clk/tegra/clk-tegra124.c
+++ b/drivers/clk/tegra/clk-tegra124.c
@@ -1166,6 +1166,12 @@ static void __init tegra124_pll_init(void __iomem *clk_base,
1166 clk_register_clkdev(clk, "pll_c_out1", NULL); 1166 clk_register_clkdev(clk, "pll_c_out1", NULL);
1167 clks[TEGRA124_CLK_PLL_C_OUT1] = clk; 1167 clks[TEGRA124_CLK_PLL_C_OUT1] = clk;
1168 1168
1169 /* PLLC_UD */
1170 clk = clk_register_fixed_factor(NULL, "pll_c_ud", "pll_c",
1171 CLK_SET_RATE_PARENT, 1, 1);
1172 clk_register_clkdev(clk, "pll_c_ud", NULL);
1173 clks[TEGRA124_CLK_PLL_C_UD] = clk;
1174
1169 /* PLLC2 */ 1175 /* PLLC2 */
1170 clk = tegra_clk_register_pllc("pll_c2", "pll_ref", clk_base, pmc, 0, 1176 clk = tegra_clk_register_pllc("pll_c2", "pll_ref", clk_base, pmc, 0,
1171 &pll_c2_params, NULL); 1177 &pll_c2_params, NULL);
@@ -1198,6 +1204,8 @@ static void __init tegra124_pll_init(void __iomem *clk_base,
1198 /* PLLM_UD */ 1204 /* PLLM_UD */
1199 clk = clk_register_fixed_factor(NULL, "pll_m_ud", "pll_m", 1205 clk = clk_register_fixed_factor(NULL, "pll_m_ud", "pll_m",
1200 CLK_SET_RATE_PARENT, 1, 1); 1206 CLK_SET_RATE_PARENT, 1, 1);
1207 clk_register_clkdev(clk, "pll_m_ud", NULL);
1208 clks[TEGRA124_CLK_PLL_M_UD] = clk;
1201 1209
1202 /* PLLU */ 1210 /* PLLU */
1203 val = readl(clk_base + pll_u_params.base_reg); 1211 val = readl(clk_base + pll_u_params.base_reg);
diff --git a/drivers/clk/tegra/clk.c b/drivers/clk/tegra/clk.c
index f87c609e8f72..97dc8595c3cd 100644
--- a/drivers/clk/tegra/clk.c
+++ b/drivers/clk/tegra/clk.c
@@ -207,8 +207,13 @@ void __init tegra_init_from_table(struct tegra_clk_init_table *tbl,
207 207
208 for (; tbl->clk_id < clk_max; tbl++) { 208 for (; tbl->clk_id < clk_max; tbl++) {
209 clk = clks[tbl->clk_id]; 209 clk = clks[tbl->clk_id];
210 if (IS_ERR_OR_NULL(clk)) 210 if (IS_ERR_OR_NULL(clk)) {
211 return; 211 pr_err("%s: invalid entry %ld in clks array for id %d\n",
212 __func__, PTR_ERR(clk), tbl->clk_id);
213 WARN_ON(1);
214
215 continue;
216 }
212 217
213 if (tbl->parent_id < clk_max) { 218 if (tbl->parent_id < clk_max) {
214 struct clk *parent = clks[tbl->parent_id]; 219 struct clk *parent = clks[tbl->parent_id];
diff --git a/drivers/clk/ti/clk-dra7-atl.c b/drivers/clk/ti/clk-dra7-atl.c
index af29359677da..59bb4b39d12e 100644
--- a/drivers/clk/ti/clk-dra7-atl.c
+++ b/drivers/clk/ti/clk-dra7-atl.c
@@ -203,6 +203,7 @@ static void __init of_dra7_atl_clock_setup(struct device_node *node)
203 203
204 if (!IS_ERR(clk)) { 204 if (!IS_ERR(clk)) {
205 of_clk_add_provider(node, of_clk_src_simple_get, clk); 205 of_clk_add_provider(node, of_clk_src_simple_get, clk);
206 kfree(parent_names);
206 return; 207 return;
207 } 208 }
208cleanup: 209cleanup:
@@ -228,6 +229,7 @@ static int of_dra7_atl_clk_probe(struct platform_device *pdev)
228 cinfo->iobase = of_iomap(node, 0); 229 cinfo->iobase = of_iomap(node, 0);
229 cinfo->dev = &pdev->dev; 230 cinfo->dev = &pdev->dev;
230 pm_runtime_enable(cinfo->dev); 231 pm_runtime_enable(cinfo->dev);
232 pm_runtime_irq_safe(cinfo->dev);
231 233
232 pm_runtime_get_sync(cinfo->dev); 234 pm_runtime_get_sync(cinfo->dev);
233 atl_write(cinfo, DRA7_ATL_PCLKMUX_REG(0), DRA7_ATL_PCLKMUX); 235 atl_write(cinfo, DRA7_ATL_PCLKMUX_REG(0), DRA7_ATL_PCLKMUX);
@@ -301,7 +303,6 @@ MODULE_DEVICE_TABLE(of, of_dra7_atl_clk_match_tbl);
301static struct platform_driver dra7_atl_clk_driver = { 303static struct platform_driver dra7_atl_clk_driver = {
302 .driver = { 304 .driver = {
303 .name = "dra7-atl", 305 .name = "dra7-atl",
304 .owner = THIS_MODULE,
305 .of_match_table = of_dra7_atl_clk_match_tbl, 306 .of_match_table = of_dra7_atl_clk_match_tbl,
306 }, 307 },
307 .probe = of_dra7_atl_clk_probe, 308 .probe = of_dra7_atl_clk_probe,
diff --git a/drivers/clk/ti/clk.c b/drivers/clk/ti/clk.c
index b1a6f7144f3f..337abe5909e1 100644
--- a/drivers/clk/ti/clk.c
+++ b/drivers/clk/ti/clk.c
@@ -25,8 +25,8 @@
25#undef pr_fmt 25#undef pr_fmt
26#define pr_fmt(fmt) "%s: " fmt, __func__ 26#define pr_fmt(fmt) "%s: " fmt, __func__
27 27
28static int ti_dt_clk_memmap_index;
29struct ti_clk_ll_ops *ti_clk_ll_ops; 28struct ti_clk_ll_ops *ti_clk_ll_ops;
29static struct device_node *clocks_node_ptr[CLK_MAX_MEMMAPS];
30 30
31/** 31/**
32 * ti_dt_clocks_register - register DT alias clocks during boot 32 * ti_dt_clocks_register - register DT alias clocks during boot
@@ -108,9 +108,21 @@ void __iomem *ti_clk_get_reg_addr(struct device_node *node, int index)
108 struct clk_omap_reg *reg; 108 struct clk_omap_reg *reg;
109 u32 val; 109 u32 val;
110 u32 tmp; 110 u32 tmp;
111 int i;
111 112
112 reg = (struct clk_omap_reg *)&tmp; 113 reg = (struct clk_omap_reg *)&tmp;
113 reg->index = ti_dt_clk_memmap_index; 114
115 for (i = 0; i < CLK_MAX_MEMMAPS; i++) {
116 if (clocks_node_ptr[i] == node->parent)
117 break;
118 }
119
120 if (i == CLK_MAX_MEMMAPS) {
121 pr_err("clk-provider not found for %s!\n", node->name);
122 return NULL;
123 }
124
125 reg->index = i;
114 126
115 if (of_property_read_u32_index(node, "reg", index, &val)) { 127 if (of_property_read_u32_index(node, "reg", index, &val)) {
116 pr_err("%s must have reg[%d]!\n", node->name, index); 128 pr_err("%s must have reg[%d]!\n", node->name, index);
@@ -127,20 +139,14 @@ void __iomem *ti_clk_get_reg_addr(struct device_node *node, int index)
127 * @parent: master node 139 * @parent: master node
128 * @index: internal index for clk_reg_ops 140 * @index: internal index for clk_reg_ops
129 * 141 *
130 * Initializes a master clock IP block and its child clock nodes. 142 * Initializes a master clock IP block. This basically sets up the
131 * Regmap is provided for accessing the register space for the 143 * mapping from clocks node to the memory map index. All the clocks
132 * IP block and all the clocks under it. 144 * are then initialized through the common of_clk_init call, and the
145 * clocks will access their memory maps based on the node layout.
133 */ 146 */
134void ti_dt_clk_init_provider(struct device_node *parent, int index) 147void ti_dt_clk_init_provider(struct device_node *parent, int index)
135{ 148{
136 const struct of_device_id *match;
137 struct device_node *np;
138 struct device_node *clocks; 149 struct device_node *clocks;
139 of_clk_init_cb_t clk_init_cb;
140 struct clk_init_item *retry;
141 struct clk_init_item *tmp;
142
143 ti_dt_clk_memmap_index = index;
144 150
145 /* get clocks for this parent */ 151 /* get clocks for this parent */
146 clocks = of_get_child_by_name(parent, "clocks"); 152 clocks = of_get_child_by_name(parent, "clocks");
@@ -149,19 +155,31 @@ void ti_dt_clk_init_provider(struct device_node *parent, int index)
149 return; 155 return;
150 } 156 }
151 157
152 for_each_child_of_node(clocks, np) { 158 /* add clocks node info */
153 match = of_match_node(&__clk_of_table, np); 159 clocks_node_ptr[index] = clocks;
154 if (!match) 160}
155 continue;
156 clk_init_cb = (of_clk_init_cb_t)match->data;
157 pr_debug("%s: initializing: %s\n", __func__, np->name);
158 clk_init_cb(np);
159 }
160 161
161 list_for_each_entry_safe(retry, tmp, &retry_list, link) { 162/**
162 pr_debug("retry-init: %s\n", retry->node->name); 163 * ti_dt_clk_init_retry_clks - init clocks from the retry list
163 retry->func(retry->hw, retry->node); 164 *
164 list_del(&retry->link); 165 * Initializes any clocks that have failed to initialize before,
165 kfree(retry); 166 * reasons being missing parent node(s) during earlier init. This
167 * typically happens only for DPLLs which need to have both of their
168 * parent clocks ready during init.
169 */
170void ti_dt_clk_init_retry_clks(void)
171{
172 struct clk_init_item *retry;
173 struct clk_init_item *tmp;
174 int retries = 5;
175
176 while (!list_empty(&retry_list) && retries) {
177 list_for_each_entry_safe(retry, tmp, &retry_list, link) {
178 pr_debug("retry-init: %s\n", retry->node->name);
179 retry->func(retry->hw, retry->node);
180 list_del(&retry->link);
181 kfree(retry);
182 }
183 retries--;
166 } 184 }
167} 185}
diff --git a/drivers/clk/ti/clockdomain.c b/drivers/clk/ti/clockdomain.c
index f1e0038d76ac..b4c5faccaece 100644
--- a/drivers/clk/ti/clockdomain.c
+++ b/drivers/clk/ti/clockdomain.c
@@ -36,6 +36,11 @@ static void __init of_ti_clockdomain_setup(struct device_node *node)
36 36
37 for (i = 0; i < num_clks; i++) { 37 for (i = 0; i < num_clks; i++) {
38 clk = of_clk_get(node, i); 38 clk = of_clk_get(node, i);
39 if (IS_ERR(clk)) {
40 pr_err("%s: Failed get %s' clock nr %d (%ld)\n",
41 __func__, node->full_name, i, PTR_ERR(clk));
42 continue;
43 }
39 if (__clk_get_flags(clk) & CLK_IS_BASIC) { 44 if (__clk_get_flags(clk) & CLK_IS_BASIC) {
40 pr_warn("can't setup clkdm for basic clk %s\n", 45 pr_warn("can't setup clkdm for basic clk %s\n",
41 __clk_get_name(clk)); 46 __clk_get_name(clk));
diff --git a/drivers/clk/ti/divider.c b/drivers/clk/ti/divider.c
index a837f703be65..bff2b5b8ff59 100644
--- a/drivers/clk/ti/divider.c
+++ b/drivers/clk/ti/divider.c
@@ -300,8 +300,8 @@ static struct clk *_register_divider(struct device *dev, const char *name,
300 return clk; 300 return clk;
301} 301}
302 302
303static struct clk_div_table 303static struct clk_div_table *
304__init *ti_clk_get_div_table(struct device_node *node) 304__init ti_clk_get_div_table(struct device_node *node)
305{ 305{
306 struct clk_div_table *table; 306 struct clk_div_table *table;
307 const __be32 *divspec; 307 const __be32 *divspec;
diff --git a/drivers/clk/zynq/clkc.c b/drivers/clk/zynq/clkc.c
index 246cf1226eaa..9037bebd69f7 100644
--- a/drivers/clk/zynq/clkc.c
+++ b/drivers/clk/zynq/clkc.c
@@ -85,24 +85,22 @@ static DEFINE_SPINLOCK(canmioclk_lock);
85static DEFINE_SPINLOCK(dbgclk_lock); 85static DEFINE_SPINLOCK(dbgclk_lock);
86static DEFINE_SPINLOCK(aperclk_lock); 86static DEFINE_SPINLOCK(aperclk_lock);
87 87
88static const char dummy_nm[] __initconst = "dummy_name"; 88static const char *armpll_parents[] __initconst = {"armpll_int", "ps_clk"};
89 89static const char *ddrpll_parents[] __initconst = {"ddrpll_int", "ps_clk"};
90static const char *armpll_parents[] __initdata = {"armpll_int", "ps_clk"}; 90static const char *iopll_parents[] __initconst = {"iopll_int", "ps_clk"};
91static const char *ddrpll_parents[] __initdata = {"ddrpll_int", "ps_clk"}; 91static const char *gem0_mux_parents[] __initconst = {"gem0_div1", "dummy_name"};
92static const char *iopll_parents[] __initdata = {"iopll_int", "ps_clk"}; 92static const char *gem1_mux_parents[] __initconst = {"gem1_div1", "dummy_name"};
93static const char *gem0_mux_parents[] __initdata = {"gem0_div1", dummy_nm}; 93static const char *can0_mio_mux2_parents[] __initconst = {"can0_gate",
94static const char *gem1_mux_parents[] __initdata = {"gem1_div1", dummy_nm};
95static const char *can0_mio_mux2_parents[] __initdata = {"can0_gate",
96 "can0_mio_mux"}; 94 "can0_mio_mux"};
97static const char *can1_mio_mux2_parents[] __initdata = {"can1_gate", 95static const char *can1_mio_mux2_parents[] __initconst = {"can1_gate",
98 "can1_mio_mux"}; 96 "can1_mio_mux"};
99static const char *dbg_emio_mux_parents[] __initdata = {"dbg_div", 97static const char *dbg_emio_mux_parents[] __initconst = {"dbg_div",
100 dummy_nm}; 98 "dummy_name"};
101 99
102static const char *dbgtrc_emio_input_names[] __initdata = {"trace_emio_clk"}; 100static const char *dbgtrc_emio_input_names[] __initconst = {"trace_emio_clk"};
103static const char *gem0_emio_input_names[] __initdata = {"gem0_emio_clk"}; 101static const char *gem0_emio_input_names[] __initconst = {"gem0_emio_clk"};
104static const char *gem1_emio_input_names[] __initdata = {"gem1_emio_clk"}; 102static const char *gem1_emio_input_names[] __initconst = {"gem1_emio_clk"};
105static const char *swdt_ext_clk_input_names[] __initdata = {"swdt_ext_clk"}; 103static const char *swdt_ext_clk_input_names[] __initconst = {"swdt_ext_clk"};
106 104
107static void __init zynq_clk_register_fclk(enum zynq_clk fclk, 105static void __init zynq_clk_register_fclk(enum zynq_clk fclk,
108 const char *clk_name, void __iomem *fclk_ctrl_reg, 106 const char *clk_name, void __iomem *fclk_ctrl_reg,
@@ -230,6 +228,7 @@ static void __init zynq_clk_setup(struct device_node *np)
230 const char *periph_parents[4]; 228 const char *periph_parents[4];
231 const char *swdt_ext_clk_mux_parents[2]; 229 const char *swdt_ext_clk_mux_parents[2];
232 const char *can_mio_mux_parents[NUM_MIO_PINS]; 230 const char *can_mio_mux_parents[NUM_MIO_PINS];
231 const char *dummy_nm = "dummy_name";
233 232
234 pr_info("Zynq clock init\n"); 233 pr_info("Zynq clock init\n");
235 234
@@ -619,5 +618,4 @@ void __init zynq_clock_init(void)
619np_err: 618np_err:
620 of_node_put(np); 619 of_node_put(np);
621 BUG(); 620 BUG();
622 return;
623} 621}
diff --git a/drivers/clk/zynq/pll.c b/drivers/clk/zynq/pll.c
index cec97596fe65..00d72fb5c036 100644
--- a/drivers/clk/zynq/pll.c
+++ b/drivers/clk/zynq/pll.c
@@ -211,10 +211,8 @@ struct clk *clk_register_zynq_pll(const char *name, const char *parent,
211 }; 211 };
212 212
213 pll = kmalloc(sizeof(*pll), GFP_KERNEL); 213 pll = kmalloc(sizeof(*pll), GFP_KERNEL);
214 if (!pll) { 214 if (!pll)
215 pr_err("%s: Could not allocate Zynq PLL clk.\n", __func__);
216 return ERR_PTR(-ENOMEM); 215 return ERR_PTR(-ENOMEM);
217 }
218 216
219 /* Populate the struct */ 217 /* Populate the struct */
220 pll->hw.init = &initd; 218 pll->hw.init = &initd;