xref: /openbmc/linux/drivers/clk/mvebu/armada-37xx-periph.c (revision f79e4d5f92a129a1159c973735007d4ddc8541f3)
1 /*
2  * Marvell Armada 37xx SoC Peripheral clocks
3  *
4  * Copyright (C) 2016 Marvell
5  *
6  * Gregory CLEMENT <gregory.clement@free-electrons.com>
7  *
8  * This file is licensed under the terms of the GNU General Public
9  * License version 2 or later. This program is licensed "as is"
10  * without any warranty of any kind, whether express or implied.
11  *
12  * Most of the peripheral clocks can be modelled like this:
13  *             _____    _______    _______
14  * TBG-A-P  --|     |  |       |  |       |   ______
15  * TBG-B-P  --| Mux |--| /div1 |--| /div2 |--| Gate |--> perip_clk
16  * TBG-A-S  --|     |  |       |  |       |  |______|
17  * TBG-B-S  --|_____|  |_______|  |_______|
18  *
19  * However some clocks may use only one or two block or and use the
20  * xtal clock as parent.
21  */
22 
23 #include <linux/clk-provider.h>
24 #include <linux/mfd/syscon.h>
25 #include <linux/of.h>
26 #include <linux/of_device.h>
27 #include <linux/platform_device.h>
28 #include <linux/regmap.h>
29 #include <linux/slab.h>
30 
31 #define TBG_SEL		0x0
32 #define DIV_SEL0	0x4
33 #define DIV_SEL1	0x8
34 #define DIV_SEL2	0xC
35 #define CLK_SEL		0x10
36 #define CLK_DIS		0x14
37 
38 #define  ARMADA_37XX_DVFS_LOAD_1 1
39 #define LOAD_LEVEL_NR	4
40 
41 #define ARMADA_37XX_NB_L0L1	0x18
42 #define ARMADA_37XX_NB_L2L3	0x1C
43 #define		ARMADA_37XX_NB_TBG_DIV_OFF	13
44 #define		ARMADA_37XX_NB_TBG_DIV_MASK	0x7
45 #define		ARMADA_37XX_NB_CLK_SEL_OFF	11
46 #define		ARMADA_37XX_NB_CLK_SEL_MASK	0x1
47 #define		ARMADA_37XX_NB_TBG_SEL_OFF	9
48 #define		ARMADA_37XX_NB_TBG_SEL_MASK	0x3
49 #define		ARMADA_37XX_NB_CONFIG_SHIFT	16
50 #define ARMADA_37XX_NB_DYN_MOD	0x24
51 #define		ARMADA_37XX_NB_DFS_EN	31
52 #define ARMADA_37XX_NB_CPU_LOAD	0x30
53 #define		ARMADA_37XX_NB_CPU_LOAD_MASK	0x3
54 #define		ARMADA_37XX_DVFS_LOAD_0		0
55 #define		ARMADA_37XX_DVFS_LOAD_1		1
56 #define		ARMADA_37XX_DVFS_LOAD_2		2
57 #define		ARMADA_37XX_DVFS_LOAD_3		3
58 
59 struct clk_periph_driver_data {
60 	struct clk_hw_onecell_data *hw_data;
61 	spinlock_t lock;
62 };
63 
64 struct clk_double_div {
65 	struct clk_hw hw;
66 	void __iomem *reg1;
67 	u8 shift1;
68 	void __iomem *reg2;
69 	u8 shift2;
70 };
71 
72 struct clk_pm_cpu {
73 	struct clk_hw hw;
74 	void __iomem *reg_mux;
75 	u8 shift_mux;
76 	u32 mask_mux;
77 	void __iomem *reg_div;
78 	u8 shift_div;
79 	struct regmap *nb_pm_base;
80 };
81 
82 #define to_clk_double_div(_hw) container_of(_hw, struct clk_double_div, hw)
83 #define to_clk_pm_cpu(_hw) container_of(_hw, struct clk_pm_cpu, hw)
84 
85 struct clk_periph_data {
86 	const char *name;
87 	const char * const *parent_names;
88 	int num_parents;
89 	struct clk_hw *mux_hw;
90 	struct clk_hw *rate_hw;
91 	struct clk_hw *gate_hw;
92 	struct clk_hw *muxrate_hw;
93 	bool is_double_div;
94 };
95 
96 static const struct clk_div_table clk_table6[] = {
97 	{ .val = 1, .div = 1, },
98 	{ .val = 2, .div = 2, },
99 	{ .val = 3, .div = 3, },
100 	{ .val = 4, .div = 4, },
101 	{ .val = 5, .div = 5, },
102 	{ .val = 6, .div = 6, },
103 	{ .val = 0, .div = 0, }, /* last entry */
104 };
105 
106 static const struct clk_div_table clk_table1[] = {
107 	{ .val = 0, .div = 1, },
108 	{ .val = 1, .div = 2, },
109 	{ .val = 0, .div = 0, }, /* last entry */
110 };
111 
112 static const struct clk_div_table clk_table2[] = {
113 	{ .val = 0, .div = 2, },
114 	{ .val = 1, .div = 4, },
115 	{ .val = 0, .div = 0, }, /* last entry */
116 };
117 
118 static const struct clk_ops clk_double_div_ops;
119 static const struct clk_ops clk_pm_cpu_ops;
120 
121 #define PERIPH_GATE(_name, _bit)		\
122 struct clk_gate gate_##_name = {		\
123 	.reg = (void *)CLK_DIS,			\
124 	.bit_idx = _bit,			\
125 	.hw.init = &(struct clk_init_data){	\
126 		.ops =  &clk_gate_ops,		\
127 	}					\
128 };
129 
130 #define PERIPH_MUX(_name, _shift)		\
131 struct clk_mux mux_##_name = {			\
132 	.reg = (void *)TBG_SEL,			\
133 	.shift = _shift,			\
134 	.mask = 3,				\
135 	.hw.init = &(struct clk_init_data){	\
136 		.ops =  &clk_mux_ro_ops,	\
137 	}					\
138 };
139 
140 #define PERIPH_DOUBLEDIV(_name, _reg1, _reg2, _shift1, _shift2)	\
141 struct clk_double_div rate_##_name = {		\
142 	.reg1 = (void *)_reg1,			\
143 	.reg2 = (void *)_reg2,			\
144 	.shift1 = _shift1,			\
145 	.shift2 = _shift2,			\
146 	.hw.init = &(struct clk_init_data){	\
147 		.ops =  &clk_double_div_ops,	\
148 	}					\
149 };
150 
151 #define PERIPH_DIV(_name, _reg, _shift, _table)	\
152 struct clk_divider rate_##_name = {		\
153 	.reg = (void *)_reg,			\
154 	.table = _table,			\
155 	.shift = _shift,			\
156 	.hw.init = &(struct clk_init_data){	\
157 		.ops =  &clk_divider_ro_ops,	\
158 	}					\
159 };
160 
161 #define PERIPH_PM_CPU(_name, _shift1, _reg, _shift2)	\
162 struct clk_pm_cpu muxrate_##_name = {		\
163 	.reg_mux = (void *)TBG_SEL,		\
164 	.mask_mux = 3,				\
165 	.shift_mux = _shift1,			\
166 	.reg_div = (void *)_reg,		\
167 	.shift_div = _shift2,			\
168 	.hw.init = &(struct clk_init_data){	\
169 		.ops =  &clk_pm_cpu_ops,	\
170 	}					\
171 };
172 
173 #define PERIPH_CLK_FULL_DD(_name, _bit, _shift, _reg1, _reg2, _shift1, _shift2)\
174 static PERIPH_GATE(_name, _bit);			    \
175 static PERIPH_MUX(_name, _shift);			    \
176 static PERIPH_DOUBLEDIV(_name, _reg1, _reg2, _shift1, _shift2);
177 
178 #define PERIPH_CLK_FULL(_name, _bit, _shift, _reg, _shift1, _table)	\
179 static PERIPH_GATE(_name, _bit);			    \
180 static PERIPH_MUX(_name, _shift);			    \
181 static PERIPH_DIV(_name, _reg, _shift1, _table);
182 
183 #define PERIPH_CLK_GATE_DIV(_name, _bit,  _reg, _shift, _table)	\
184 static PERIPH_GATE(_name, _bit);			\
185 static PERIPH_DIV(_name, _reg, _shift, _table);
186 
187 #define PERIPH_CLK_MUX_DD(_name, _shift, _reg1, _reg2, _shift1, _shift2)\
188 static PERIPH_MUX(_name, _shift);			    \
189 static PERIPH_DOUBLEDIV(_name, _reg1, _reg2, _shift1, _shift2);
190 
191 #define REF_CLK_FULL(_name)				\
192 	{ .name = #_name,				\
193 	  .parent_names = (const char *[]){ "TBG-A-P",	\
194 	      "TBG-B-P", "TBG-A-S", "TBG-B-S"},		\
195 	  .num_parents = 4,				\
196 	  .mux_hw = &mux_##_name.hw,			\
197 	  .gate_hw = &gate_##_name.hw,			\
198 	  .rate_hw = &rate_##_name.hw,			\
199 	}
200 
201 #define REF_CLK_FULL_DD(_name)				\
202 	{ .name = #_name,				\
203 	  .parent_names = (const char *[]){ "TBG-A-P",	\
204 	      "TBG-B-P", "TBG-A-S", "TBG-B-S"},		\
205 	  .num_parents = 4,				\
206 	  .mux_hw = &mux_##_name.hw,			\
207 	  .gate_hw = &gate_##_name.hw,			\
208 	  .rate_hw = &rate_##_name.hw,			\
209 	  .is_double_div = true,			\
210 	}
211 
212 #define REF_CLK_GATE(_name, _parent_name)			\
213 	{ .name = #_name,					\
214 	  .parent_names = (const char *[]){ _parent_name},	\
215 	  .num_parents = 1,					\
216 	  .gate_hw = &gate_##_name.hw,				\
217 	}
218 
219 #define REF_CLK_GATE_DIV(_name, _parent_name)			\
220 	{ .name = #_name,					\
221 	  .parent_names = (const char *[]){ _parent_name},	\
222 	  .num_parents = 1,					\
223 	  .gate_hw = &gate_##_name.hw,				\
224 	  .rate_hw = &rate_##_name.hw,				\
225 	}
226 
227 #define REF_CLK_PM_CPU(_name)				\
228 	{ .name = #_name,				\
229 	  .parent_names = (const char *[]){ "TBG-A-P",	\
230 	      "TBG-B-P", "TBG-A-S", "TBG-B-S"},		\
231 	  .num_parents = 4,				\
232 	  .muxrate_hw = &muxrate_##_name.hw,		\
233 	}
234 
235 #define REF_CLK_MUX_DD(_name)				\
236 	{ .name = #_name,				\
237 	  .parent_names = (const char *[]){ "TBG-A-P",	\
238 	      "TBG-B-P", "TBG-A-S", "TBG-B-S"},		\
239 	  .num_parents = 4,				\
240 	  .mux_hw = &mux_##_name.hw,			\
241 	  .rate_hw = &rate_##_name.hw,			\
242 	  .is_double_div = true,			\
243 	}
244 
245 /* NB periph clocks */
246 PERIPH_CLK_FULL_DD(mmc, 2, 0, DIV_SEL2, DIV_SEL2, 16, 13);
247 PERIPH_CLK_FULL_DD(sata_host, 3, 2, DIV_SEL2, DIV_SEL2, 10, 7);
248 PERIPH_CLK_FULL_DD(sec_at, 6, 4, DIV_SEL1, DIV_SEL1, 3, 0);
249 PERIPH_CLK_FULL_DD(sec_dap, 7, 6, DIV_SEL1, DIV_SEL1, 9, 6);
250 PERIPH_CLK_FULL_DD(tscem, 8, 8, DIV_SEL1, DIV_SEL1, 15, 12);
251 PERIPH_CLK_FULL(tscem_tmx, 10, 10, DIV_SEL1, 18, clk_table6);
252 static PERIPH_GATE(avs, 11);
253 PERIPH_CLK_FULL_DD(pwm, 13, 14, DIV_SEL0, DIV_SEL0, 3, 0);
254 PERIPH_CLK_FULL_DD(sqf, 12, 12, DIV_SEL1, DIV_SEL1, 27, 24);
255 static PERIPH_GATE(i2c_2, 16);
256 static PERIPH_GATE(i2c_1, 17);
257 PERIPH_CLK_GATE_DIV(ddr_phy, 19, DIV_SEL0, 18, clk_table2);
258 PERIPH_CLK_FULL_DD(ddr_fclk, 21, 16, DIV_SEL0, DIV_SEL0, 15, 12);
259 PERIPH_CLK_FULL(trace, 22, 18, DIV_SEL0, 20, clk_table6);
260 PERIPH_CLK_FULL(counter, 23, 20, DIV_SEL0, 23, clk_table6);
261 PERIPH_CLK_FULL_DD(eip97, 24, 24, DIV_SEL2, DIV_SEL2, 22, 19);
262 static PERIPH_PM_CPU(cpu, 22, DIV_SEL0, 28);
263 
264 static struct clk_periph_data data_nb[] = {
265 	REF_CLK_FULL_DD(mmc),
266 	REF_CLK_FULL_DD(sata_host),
267 	REF_CLK_FULL_DD(sec_at),
268 	REF_CLK_FULL_DD(sec_dap),
269 	REF_CLK_FULL_DD(tscem),
270 	REF_CLK_FULL(tscem_tmx),
271 	REF_CLK_GATE(avs, "xtal"),
272 	REF_CLK_FULL_DD(sqf),
273 	REF_CLK_FULL_DD(pwm),
274 	REF_CLK_GATE(i2c_2, "xtal"),
275 	REF_CLK_GATE(i2c_1, "xtal"),
276 	REF_CLK_GATE_DIV(ddr_phy, "TBG-A-S"),
277 	REF_CLK_FULL_DD(ddr_fclk),
278 	REF_CLK_FULL(trace),
279 	REF_CLK_FULL(counter),
280 	REF_CLK_FULL_DD(eip97),
281 	REF_CLK_PM_CPU(cpu),
282 	{ },
283 };
284 
285 /* SB periph clocks */
286 PERIPH_CLK_MUX_DD(gbe_50, 6, DIV_SEL2, DIV_SEL2, 6, 9);
287 PERIPH_CLK_MUX_DD(gbe_core, 8, DIV_SEL1, DIV_SEL1, 18, 21);
288 PERIPH_CLK_MUX_DD(gbe_125, 10, DIV_SEL1, DIV_SEL1, 6, 9);
289 static PERIPH_GATE(gbe1_50, 0);
290 static PERIPH_GATE(gbe0_50, 1);
291 static PERIPH_GATE(gbe1_125, 2);
292 static PERIPH_GATE(gbe0_125, 3);
293 PERIPH_CLK_GATE_DIV(gbe1_core, 4, DIV_SEL1, 13, clk_table1);
294 PERIPH_CLK_GATE_DIV(gbe0_core, 5, DIV_SEL1, 14, clk_table1);
295 PERIPH_CLK_GATE_DIV(gbe_bm, 12, DIV_SEL1, 0, clk_table1);
296 PERIPH_CLK_FULL_DD(sdio, 11, 14, DIV_SEL0, DIV_SEL0, 3, 6);
297 PERIPH_CLK_FULL_DD(usb32_usb2_sys, 16, 16, DIV_SEL0, DIV_SEL0, 9, 12);
298 PERIPH_CLK_FULL_DD(usb32_ss_sys, 17, 18, DIV_SEL0, DIV_SEL0, 15, 18);
299 
300 static struct clk_periph_data data_sb[] = {
301 	REF_CLK_MUX_DD(gbe_50),
302 	REF_CLK_MUX_DD(gbe_core),
303 	REF_CLK_MUX_DD(gbe_125),
304 	REF_CLK_GATE(gbe1_50, "gbe_50"),
305 	REF_CLK_GATE(gbe0_50, "gbe_50"),
306 	REF_CLK_GATE(gbe1_125, "gbe_125"),
307 	REF_CLK_GATE(gbe0_125, "gbe_125"),
308 	REF_CLK_GATE_DIV(gbe1_core, "gbe_core"),
309 	REF_CLK_GATE_DIV(gbe0_core, "gbe_core"),
310 	REF_CLK_GATE_DIV(gbe_bm, "gbe_core"),
311 	REF_CLK_FULL_DD(sdio),
312 	REF_CLK_FULL_DD(usb32_usb2_sys),
313 	REF_CLK_FULL_DD(usb32_ss_sys),
314 	{ },
315 };
316 
317 static unsigned int get_div(void __iomem *reg, int shift)
318 {
319 	u32 val;
320 
321 	val = (readl(reg) >> shift) & 0x7;
322 	if (val > 6)
323 		return 0;
324 	return val;
325 }
326 
327 static unsigned long clk_double_div_recalc_rate(struct clk_hw *hw,
328 						unsigned long parent_rate)
329 {
330 	struct clk_double_div *double_div = to_clk_double_div(hw);
331 	unsigned int div;
332 
333 	div = get_div(double_div->reg1, double_div->shift1);
334 	div *= get_div(double_div->reg2, double_div->shift2);
335 
336 	return DIV_ROUND_UP_ULL((u64)parent_rate, div);
337 }
338 
339 static const struct clk_ops clk_double_div_ops = {
340 	.recalc_rate = clk_double_div_recalc_rate,
341 };
342 
343 static void armada_3700_pm_dvfs_update_regs(unsigned int load_level,
344 					    unsigned int *reg,
345 					    unsigned int *offset)
346 {
347 	if (load_level <= ARMADA_37XX_DVFS_LOAD_1)
348 		*reg = ARMADA_37XX_NB_L0L1;
349 	else
350 		*reg = ARMADA_37XX_NB_L2L3;
351 
352 	if (load_level == ARMADA_37XX_DVFS_LOAD_0 ||
353 	    load_level ==  ARMADA_37XX_DVFS_LOAD_2)
354 		*offset += ARMADA_37XX_NB_CONFIG_SHIFT;
355 }
356 
357 static bool armada_3700_pm_dvfs_is_enabled(struct regmap *base)
358 {
359 	unsigned int val, reg = ARMADA_37XX_NB_DYN_MOD;
360 
361 	if (IS_ERR(base))
362 		return false;
363 
364 	regmap_read(base, reg, &val);
365 
366 	return !!(val & BIT(ARMADA_37XX_NB_DFS_EN));
367 }
368 
369 static unsigned int armada_3700_pm_dvfs_get_cpu_div(struct regmap *base)
370 {
371 	unsigned int reg = ARMADA_37XX_NB_CPU_LOAD;
372 	unsigned int offset = ARMADA_37XX_NB_TBG_DIV_OFF;
373 	unsigned int load_level, div;
374 
375 	/*
376 	 * This function is always called after the function
377 	 * armada_3700_pm_dvfs_is_enabled, so no need to check again
378 	 * if the base is valid.
379 	 */
380 	regmap_read(base, reg, &load_level);
381 
382 	/*
383 	 * The register and the offset inside this register accessed to
384 	 * read the current divider depend on the load level
385 	 */
386 	load_level &= ARMADA_37XX_NB_CPU_LOAD_MASK;
387 	armada_3700_pm_dvfs_update_regs(load_level, &reg, &offset);
388 
389 	regmap_read(base, reg, &div);
390 
391 	return (div >> offset) & ARMADA_37XX_NB_TBG_DIV_MASK;
392 }
393 
394 static unsigned int armada_3700_pm_dvfs_get_cpu_parent(struct regmap *base)
395 {
396 	unsigned int reg = ARMADA_37XX_NB_CPU_LOAD;
397 	unsigned int offset = ARMADA_37XX_NB_TBG_SEL_OFF;
398 	unsigned int load_level, sel;
399 
400 	/*
401 	 * This function is always called after the function
402 	 * armada_3700_pm_dvfs_is_enabled, so no need to check again
403 	 * if the base is valid
404 	 */
405 	regmap_read(base, reg, &load_level);
406 
407 	/*
408 	 * The register and the offset inside this register accessed to
409 	 * read the current divider depend on the load level
410 	 */
411 	load_level &= ARMADA_37XX_NB_CPU_LOAD_MASK;
412 	armada_3700_pm_dvfs_update_regs(load_level, &reg, &offset);
413 
414 	regmap_read(base, reg, &sel);
415 
416 	return (sel >> offset) & ARMADA_37XX_NB_TBG_SEL_MASK;
417 }
418 
419 static u8 clk_pm_cpu_get_parent(struct clk_hw *hw)
420 {
421 	struct clk_pm_cpu *pm_cpu = to_clk_pm_cpu(hw);
422 	int num_parents = clk_hw_get_num_parents(hw);
423 	u32 val;
424 
425 	if (armada_3700_pm_dvfs_is_enabled(pm_cpu->nb_pm_base)) {
426 		val = armada_3700_pm_dvfs_get_cpu_parent(pm_cpu->nb_pm_base);
427 	} else {
428 		val = readl(pm_cpu->reg_mux) >> pm_cpu->shift_mux;
429 		val &= pm_cpu->mask_mux;
430 	}
431 
432 	if (val >= num_parents)
433 		return -EINVAL;
434 
435 	return val;
436 }
437 
438 static int clk_pm_cpu_set_parent(struct clk_hw *hw, u8 index)
439 {
440 	struct clk_pm_cpu *pm_cpu = to_clk_pm_cpu(hw);
441 	struct regmap *base = pm_cpu->nb_pm_base;
442 	int load_level;
443 
444 	/*
445 	 * We set the clock parent only if the DVFS is available but
446 	 * not enabled.
447 	 */
448 	if (IS_ERR(base) || armada_3700_pm_dvfs_is_enabled(base))
449 		return -EINVAL;
450 
451 	/* Set the parent clock for all the load level */
452 	for (load_level = 0; load_level < LOAD_LEVEL_NR; load_level++) {
453 		unsigned int reg, mask,  val,
454 			offset = ARMADA_37XX_NB_TBG_SEL_OFF;
455 
456 		armada_3700_pm_dvfs_update_regs(load_level, &reg, &offset);
457 
458 		val = index << offset;
459 		mask = ARMADA_37XX_NB_TBG_SEL_MASK << offset;
460 		regmap_update_bits(base, reg, mask, val);
461 	}
462 	return 0;
463 }
464 
465 static unsigned long clk_pm_cpu_recalc_rate(struct clk_hw *hw,
466 					    unsigned long parent_rate)
467 {
468 	struct clk_pm_cpu *pm_cpu = to_clk_pm_cpu(hw);
469 	unsigned int div;
470 
471 	if (armada_3700_pm_dvfs_is_enabled(pm_cpu->nb_pm_base))
472 		div = armada_3700_pm_dvfs_get_cpu_div(pm_cpu->nb_pm_base);
473 	else
474 		div = get_div(pm_cpu->reg_div, pm_cpu->shift_div);
475 	return DIV_ROUND_UP_ULL((u64)parent_rate, div);
476 }
477 
478 static long clk_pm_cpu_round_rate(struct clk_hw *hw, unsigned long rate,
479 				  unsigned long *parent_rate)
480 {
481 	struct clk_pm_cpu *pm_cpu = to_clk_pm_cpu(hw);
482 	struct regmap *base = pm_cpu->nb_pm_base;
483 	unsigned int div = *parent_rate / rate;
484 	unsigned int load_level;
485 	/* only available when DVFS is enabled */
486 	if (!armada_3700_pm_dvfs_is_enabled(base))
487 		return -EINVAL;
488 
489 	for (load_level = 0; load_level < LOAD_LEVEL_NR; load_level++) {
490 		unsigned int reg, val, offset = ARMADA_37XX_NB_TBG_DIV_OFF;
491 
492 		armada_3700_pm_dvfs_update_regs(load_level, &reg, &offset);
493 
494 		regmap_read(base, reg, &val);
495 
496 		val >>= offset;
497 		val &= ARMADA_37XX_NB_TBG_DIV_MASK;
498 		if (val == div)
499 			/*
500 			 * We found a load level matching the target
501 			 * divider, switch to this load level and
502 			 * return.
503 			 */
504 			return *parent_rate / div;
505 	}
506 
507 	/* We didn't find any valid divider */
508 	return -EINVAL;
509 }
510 
511 /*
512  * Switching the CPU from the L2 or L3 frequencies (300 and 200 Mhz
513  * respectively) to L0 frequency (1.2 Ghz) requires a significant
514  * amount of time to let VDD stabilize to the appropriate
515  * voltage. This amount of time is large enough that it cannot be
516  * covered by the hardware countdown register. Due to this, the CPU
517  * might start operating at L0 before the voltage is stabilized,
518  * leading to CPU stalls.
519  *
520  * To work around this problem, we prevent switching directly from the
521  * L2/L3 frequencies to the L0 frequency, and instead switch to the L1
522  * frequency in-between. The sequence therefore becomes:
523  * 1. First switch from L2/L3(200/300MHz) to L1(600MHZ)
524  * 2. Sleep 20ms for stabling VDD voltage
525  * 3. Then switch from L1(600MHZ) to L0(1200Mhz).
526  */
527 static void clk_pm_cpu_set_rate_wa(unsigned long rate, struct regmap *base)
528 {
529 	unsigned int cur_level;
530 
531 	if (rate != 1200 * 1000 * 1000)
532 		return;
533 
534 	regmap_read(base, ARMADA_37XX_NB_CPU_LOAD, &cur_level);
535 	cur_level &= ARMADA_37XX_NB_CPU_LOAD_MASK;
536 	if (cur_level <= ARMADA_37XX_DVFS_LOAD_1)
537 		return;
538 
539 	regmap_update_bits(base, ARMADA_37XX_NB_CPU_LOAD,
540 			   ARMADA_37XX_NB_CPU_LOAD_MASK,
541 			   ARMADA_37XX_DVFS_LOAD_1);
542 	msleep(20);
543 }
544 
545 static int clk_pm_cpu_set_rate(struct clk_hw *hw, unsigned long rate,
546 			       unsigned long parent_rate)
547 {
548 	struct clk_pm_cpu *pm_cpu = to_clk_pm_cpu(hw);
549 	struct regmap *base = pm_cpu->nb_pm_base;
550 	unsigned int div = parent_rate / rate;
551 	unsigned int load_level;
552 
553 	/* only available when DVFS is enabled */
554 	if (!armada_3700_pm_dvfs_is_enabled(base))
555 		return -EINVAL;
556 
557 	for (load_level = 0; load_level < LOAD_LEVEL_NR; load_level++) {
558 		unsigned int reg, mask, val,
559 			offset = ARMADA_37XX_NB_TBG_DIV_OFF;
560 
561 		armada_3700_pm_dvfs_update_regs(load_level, &reg, &offset);
562 
563 		regmap_read(base, reg, &val);
564 		val >>= offset;
565 		val &= ARMADA_37XX_NB_TBG_DIV_MASK;
566 
567 		if (val == div) {
568 			/*
569 			 * We found a load level matching the target
570 			 * divider, switch to this load level and
571 			 * return.
572 			 */
573 			reg = ARMADA_37XX_NB_CPU_LOAD;
574 			mask = ARMADA_37XX_NB_CPU_LOAD_MASK;
575 
576 			clk_pm_cpu_set_rate_wa(rate, base);
577 
578 			regmap_update_bits(base, reg, mask, load_level);
579 
580 			return rate;
581 		}
582 	}
583 
584 	/* We didn't find any valid divider */
585 	return -EINVAL;
586 }
587 
588 static const struct clk_ops clk_pm_cpu_ops = {
589 	.get_parent = clk_pm_cpu_get_parent,
590 	.set_parent = clk_pm_cpu_set_parent,
591 	.round_rate = clk_pm_cpu_round_rate,
592 	.set_rate = clk_pm_cpu_set_rate,
593 	.recalc_rate = clk_pm_cpu_recalc_rate,
594 };
595 
596 static const struct of_device_id armada_3700_periph_clock_of_match[] = {
597 	{ .compatible = "marvell,armada-3700-periph-clock-nb",
598 	  .data = data_nb, },
599 	{ .compatible = "marvell,armada-3700-periph-clock-sb",
600 	.data = data_sb, },
601 	{ }
602 };
603 
604 static int armada_3700_add_composite_clk(const struct clk_periph_data *data,
605 					 void __iomem *reg, spinlock_t *lock,
606 					 struct device *dev, struct clk_hw **hw)
607 {
608 	const struct clk_ops *mux_ops = NULL, *gate_ops = NULL,
609 		*rate_ops = NULL;
610 	struct clk_hw *mux_hw = NULL, *gate_hw = NULL, *rate_hw = NULL;
611 
612 	if (data->mux_hw) {
613 		struct clk_mux *mux;
614 
615 		mux_hw = data->mux_hw;
616 		mux = to_clk_mux(mux_hw);
617 		mux->lock = lock;
618 		mux_ops = mux_hw->init->ops;
619 		mux->reg = reg + (u64)mux->reg;
620 	}
621 
622 	if (data->gate_hw) {
623 		struct clk_gate *gate;
624 
625 		gate_hw = data->gate_hw;
626 		gate = to_clk_gate(gate_hw);
627 		gate->lock = lock;
628 		gate_ops = gate_hw->init->ops;
629 		gate->reg = reg + (u64)gate->reg;
630 		gate->flags = CLK_GATE_SET_TO_DISABLE;
631 	}
632 
633 	if (data->rate_hw) {
634 		rate_hw = data->rate_hw;
635 		rate_ops = rate_hw->init->ops;
636 		if (data->is_double_div) {
637 			struct clk_double_div *rate;
638 
639 			rate =  to_clk_double_div(rate_hw);
640 			rate->reg1 = reg + (u64)rate->reg1;
641 			rate->reg2 = reg + (u64)rate->reg2;
642 		} else {
643 			struct clk_divider *rate = to_clk_divider(rate_hw);
644 			const struct clk_div_table *clkt;
645 			int table_size = 0;
646 
647 			rate->reg = reg + (u64)rate->reg;
648 			for (clkt = rate->table; clkt->div; clkt++)
649 				table_size++;
650 			rate->width = order_base_2(table_size);
651 			rate->lock = lock;
652 		}
653 	}
654 
655 	if (data->muxrate_hw) {
656 		struct clk_pm_cpu *pmcpu_clk;
657 		struct clk_hw *muxrate_hw = data->muxrate_hw;
658 		struct regmap *map;
659 
660 		pmcpu_clk =  to_clk_pm_cpu(muxrate_hw);
661 		pmcpu_clk->reg_mux = reg + (u64)pmcpu_clk->reg_mux;
662 		pmcpu_clk->reg_div = reg + (u64)pmcpu_clk->reg_div;
663 
664 		mux_hw = muxrate_hw;
665 		rate_hw = muxrate_hw;
666 		mux_ops = muxrate_hw->init->ops;
667 		rate_ops = muxrate_hw->init->ops;
668 
669 		map = syscon_regmap_lookup_by_compatible(
670 				"marvell,armada-3700-nb-pm");
671 		pmcpu_clk->nb_pm_base = map;
672 	}
673 
674 	*hw = clk_hw_register_composite(dev, data->name, data->parent_names,
675 					data->num_parents, mux_hw,
676 					mux_ops, rate_hw, rate_ops,
677 					gate_hw, gate_ops, CLK_IGNORE_UNUSED);
678 
679 	return PTR_ERR_OR_ZERO(*hw);
680 }
681 
682 static int armada_3700_periph_clock_probe(struct platform_device *pdev)
683 {
684 	struct clk_periph_driver_data *driver_data;
685 	struct device_node *np = pdev->dev.of_node;
686 	const struct clk_periph_data *data;
687 	struct device *dev = &pdev->dev;
688 	int num_periph = 0, i, ret;
689 	struct resource *res;
690 	void __iomem *reg;
691 
692 	data = of_device_get_match_data(dev);
693 	if (!data)
694 		return -ENODEV;
695 
696 	while (data[num_periph].name)
697 		num_periph++;
698 
699 	res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
700 	reg = devm_ioremap_resource(dev, res);
701 	if (IS_ERR(reg))
702 		return PTR_ERR(reg);
703 
704 	driver_data = devm_kzalloc(dev, sizeof(*driver_data), GFP_KERNEL);
705 	if (!driver_data)
706 		return -ENOMEM;
707 
708 	driver_data->hw_data = devm_kzalloc(dev,
709 					    struct_size(driver_data->hw_data,
710 							hws, num_periph),
711 					    GFP_KERNEL);
712 	if (!driver_data->hw_data)
713 		return -ENOMEM;
714 	driver_data->hw_data->num = num_periph;
715 
716 	spin_lock_init(&driver_data->lock);
717 
718 	for (i = 0; i < num_periph; i++) {
719 		struct clk_hw **hw = &driver_data->hw_data->hws[i];
720 
721 		if (armada_3700_add_composite_clk(&data[i], reg,
722 						  &driver_data->lock, dev, hw))
723 			dev_err(dev, "Can't register periph clock %s\n",
724 				data[i].name);
725 	}
726 
727 	ret = of_clk_add_hw_provider(np, of_clk_hw_onecell_get,
728 				     driver_data->hw_data);
729 	if (ret) {
730 		for (i = 0; i < num_periph; i++)
731 			clk_hw_unregister(driver_data->hw_data->hws[i]);
732 		return ret;
733 	}
734 
735 	platform_set_drvdata(pdev, driver_data);
736 	return 0;
737 }
738 
739 static int armada_3700_periph_clock_remove(struct platform_device *pdev)
740 {
741 	struct clk_periph_driver_data *data = platform_get_drvdata(pdev);
742 	struct clk_hw_onecell_data *hw_data = data->hw_data;
743 	int i;
744 
745 	of_clk_del_provider(pdev->dev.of_node);
746 
747 	for (i = 0; i < hw_data->num; i++)
748 		clk_hw_unregister(hw_data->hws[i]);
749 
750 	return 0;
751 }
752 
753 static struct platform_driver armada_3700_periph_clock_driver = {
754 	.probe = armada_3700_periph_clock_probe,
755 	.remove = armada_3700_periph_clock_remove,
756 	.driver		= {
757 		.name	= "marvell-armada-3700-periph-clock",
758 		.of_match_table = armada_3700_periph_clock_of_match,
759 	},
760 };
761 
762 builtin_platform_driver(armada_3700_periph_clock_driver);
763