xref: /openbmc/linux/arch/arm/mach-omap1/clock.c (revision c73b9099)
1 // SPDX-License-Identifier: GPL-2.0-only
2 /*
3  *  linux/arch/arm/mach-omap1/clock.c
4  *
5  *  Copyright (C) 2004 - 2005, 2009-2010 Nokia Corporation
6  *  Written by Tuukka Tikkanen <tuukka.tikkanen@elektrobit.com>
7  *
8  *  Modified to use omap shared clock framework by
9  *  Tony Lindgren <tony@atomide.com>
10  */
11 #include <linux/kernel.h>
12 #include <linux/export.h>
13 #include <linux/list.h>
14 #include <linux/errno.h>
15 #include <linux/err.h>
16 #include <linux/io.h>
17 #include <linux/clk.h>
18 #include <linux/clkdev.h>
19 #include <linux/clk-provider.h>
20 #include <linux/soc/ti/omap1-io.h>
21 #include <linux/spinlock.h>
22 
23 #include <asm/mach-types.h>
24 
25 #include "hardware.h"
26 #include "soc.h"
27 #include "iomap.h"
28 #include "clock.h"
29 #include "opp.h"
30 #include "sram.h"
31 
32 __u32 arm_idlect1_mask;
33 /* provide direct internal access (not via clk API) to some clocks */
34 struct omap1_clk *api_ck_p, *ck_dpll1_p, *ck_ref_p;
35 
36 /* protect registeres shared among clk_enable/disable() and clk_set_rate() operations */
37 static DEFINE_SPINLOCK(arm_ckctl_lock);
38 static DEFINE_SPINLOCK(arm_idlect2_lock);
39 static DEFINE_SPINLOCK(mod_conf_ctrl_0_lock);
40 static DEFINE_SPINLOCK(mod_conf_ctrl_1_lock);
41 static DEFINE_SPINLOCK(swd_clk_div_ctrl_sel_lock);
42 
43 /*
44  * Omap1 specific clock functions
45  */
46 
omap1_uart_recalc(struct omap1_clk * clk,unsigned long p_rate)47 unsigned long omap1_uart_recalc(struct omap1_clk *clk, unsigned long p_rate)
48 {
49 	unsigned int val = __raw_readl(clk->enable_reg);
50 	return val & 1 << clk->enable_bit ? 48000000 : 12000000;
51 }
52 
omap1_sossi_recalc(struct omap1_clk * clk,unsigned long p_rate)53 unsigned long omap1_sossi_recalc(struct omap1_clk *clk, unsigned long p_rate)
54 {
55 	u32 div = omap_readl(MOD_CONF_CTRL_1);
56 
57 	div = (div >> 17) & 0x7;
58 	div++;
59 
60 	return p_rate / div;
61 }
62 
omap1_clk_allow_idle(struct omap1_clk * clk)63 static void omap1_clk_allow_idle(struct omap1_clk *clk)
64 {
65 	struct arm_idlect1_clk * iclk = (struct arm_idlect1_clk *)clk;
66 
67 	if (!(clk->flags & CLOCK_IDLE_CONTROL))
68 		return;
69 
70 	if (iclk->no_idle_count > 0 && !(--iclk->no_idle_count))
71 		arm_idlect1_mask |= 1 << iclk->idlect_shift;
72 }
73 
omap1_clk_deny_idle(struct omap1_clk * clk)74 static void omap1_clk_deny_idle(struct omap1_clk *clk)
75 {
76 	struct arm_idlect1_clk * iclk = (struct arm_idlect1_clk *)clk;
77 
78 	if (!(clk->flags & CLOCK_IDLE_CONTROL))
79 		return;
80 
81 	if (iclk->no_idle_count++ == 0)
82 		arm_idlect1_mask &= ~(1 << iclk->idlect_shift);
83 }
84 
verify_ckctl_value(__u16 newval)85 static __u16 verify_ckctl_value(__u16 newval)
86 {
87 	/* This function checks for following limitations set
88 	 * by the hardware (all conditions must be true):
89 	 * DSPMMU_CK == DSP_CK  or  DSPMMU_CK == DSP_CK/2
90 	 * ARM_CK >= TC_CK
91 	 * DSP_CK >= TC_CK
92 	 * DSPMMU_CK >= TC_CK
93 	 *
94 	 * In addition following rules are enforced:
95 	 * LCD_CK <= TC_CK
96 	 * ARMPER_CK <= TC_CK
97 	 *
98 	 * However, maximum frequencies are not checked for!
99 	 */
100 	__u8 per_exp;
101 	__u8 lcd_exp;
102 	__u8 arm_exp;
103 	__u8 dsp_exp;
104 	__u8 tc_exp;
105 	__u8 dspmmu_exp;
106 
107 	per_exp = (newval >> CKCTL_PERDIV_OFFSET) & 3;
108 	lcd_exp = (newval >> CKCTL_LCDDIV_OFFSET) & 3;
109 	arm_exp = (newval >> CKCTL_ARMDIV_OFFSET) & 3;
110 	dsp_exp = (newval >> CKCTL_DSPDIV_OFFSET) & 3;
111 	tc_exp = (newval >> CKCTL_TCDIV_OFFSET) & 3;
112 	dspmmu_exp = (newval >> CKCTL_DSPMMUDIV_OFFSET) & 3;
113 
114 	if (dspmmu_exp < dsp_exp)
115 		dspmmu_exp = dsp_exp;
116 	if (dspmmu_exp > dsp_exp+1)
117 		dspmmu_exp = dsp_exp+1;
118 	if (tc_exp < arm_exp)
119 		tc_exp = arm_exp;
120 	if (tc_exp < dspmmu_exp)
121 		tc_exp = dspmmu_exp;
122 	if (tc_exp > lcd_exp)
123 		lcd_exp = tc_exp;
124 	if (tc_exp > per_exp)
125 		per_exp = tc_exp;
126 
127 	newval &= 0xf000;
128 	newval |= per_exp << CKCTL_PERDIV_OFFSET;
129 	newval |= lcd_exp << CKCTL_LCDDIV_OFFSET;
130 	newval |= arm_exp << CKCTL_ARMDIV_OFFSET;
131 	newval |= dsp_exp << CKCTL_DSPDIV_OFFSET;
132 	newval |= tc_exp << CKCTL_TCDIV_OFFSET;
133 	newval |= dspmmu_exp << CKCTL_DSPMMUDIV_OFFSET;
134 
135 	return newval;
136 }
137 
calc_dsor_exp(unsigned long rate,unsigned long realrate)138 static int calc_dsor_exp(unsigned long rate, unsigned long realrate)
139 {
140 	/* Note: If target frequency is too low, this function will return 4,
141 	 * which is invalid value. Caller must check for this value and act
142 	 * accordingly.
143 	 *
144 	 * Note: This function does not check for following limitations set
145 	 * by the hardware (all conditions must be true):
146 	 * DSPMMU_CK == DSP_CK  or  DSPMMU_CK == DSP_CK/2
147 	 * ARM_CK >= TC_CK
148 	 * DSP_CK >= TC_CK
149 	 * DSPMMU_CK >= TC_CK
150 	 */
151 	unsigned  dsor_exp;
152 
153 	if (unlikely(realrate == 0))
154 		return -EIO;
155 
156 	for (dsor_exp=0; dsor_exp<4; dsor_exp++) {
157 		if (realrate <= rate)
158 			break;
159 
160 		realrate /= 2;
161 	}
162 
163 	return dsor_exp;
164 }
165 
omap1_ckctl_recalc(struct omap1_clk * clk,unsigned long p_rate)166 unsigned long omap1_ckctl_recalc(struct omap1_clk *clk, unsigned long p_rate)
167 {
168 	/* Calculate divisor encoded as 2-bit exponent */
169 	int dsor = 1 << (3 & (omap_readw(ARM_CKCTL) >> clk->rate_offset));
170 
171 	/* update locally maintained rate, required by arm_ck for omap1_show_rates() */
172 	clk->rate = p_rate / dsor;
173 	return clk->rate;
174 }
175 
omap1_clk_is_enabled(struct clk_hw * hw)176 static int omap1_clk_is_enabled(struct clk_hw *hw)
177 {
178 	struct omap1_clk *clk = to_omap1_clk(hw);
179 	bool api_ck_was_enabled = true;
180 	__u32 regval32;
181 	int ret;
182 
183 	if (!clk->ops)	/* no gate -- always enabled */
184 		return 1;
185 
186 	if (clk->ops == &clkops_dspck) {
187 		api_ck_was_enabled = omap1_clk_is_enabled(&api_ck_p->hw);
188 		if (!api_ck_was_enabled)
189 			if (api_ck_p->ops->enable(api_ck_p) < 0)
190 				return 0;
191 	}
192 
193 	if (clk->flags & ENABLE_REG_32BIT)
194 		regval32 = __raw_readl(clk->enable_reg);
195 	else
196 		regval32 = __raw_readw(clk->enable_reg);
197 
198 	ret = regval32 & (1 << clk->enable_bit);
199 
200 	if (!api_ck_was_enabled)
201 		api_ck_p->ops->disable(api_ck_p);
202 
203 	return ret;
204 }
205 
206 
omap1_ckctl_recalc_dsp_domain(struct omap1_clk * clk,unsigned long p_rate)207 unsigned long omap1_ckctl_recalc_dsp_domain(struct omap1_clk *clk, unsigned long p_rate)
208 {
209 	bool api_ck_was_enabled;
210 	int dsor;
211 
212 	/* Calculate divisor encoded as 2-bit exponent
213 	 *
214 	 * The clock control bits are in DSP domain,
215 	 * so api_ck is needed for access.
216 	 * Note that DSP_CKCTL virt addr = phys addr, so
217 	 * we must use __raw_readw() instead of omap_readw().
218 	 */
219 	api_ck_was_enabled = omap1_clk_is_enabled(&api_ck_p->hw);
220 	if (!api_ck_was_enabled)
221 		api_ck_p->ops->enable(api_ck_p);
222 	dsor = 1 << (3 & (__raw_readw(DSP_CKCTL) >> clk->rate_offset));
223 	if (!api_ck_was_enabled)
224 		api_ck_p->ops->disable(api_ck_p);
225 
226 	return p_rate / dsor;
227 }
228 
229 /* MPU virtual clock functions */
omap1_select_table_rate(struct omap1_clk * clk,unsigned long rate,unsigned long p_rate)230 int omap1_select_table_rate(struct omap1_clk *clk, unsigned long rate, unsigned long p_rate)
231 {
232 	/* Find the highest supported frequency <= rate and switch to it */
233 	struct mpu_rate * ptr;
234 	unsigned long ref_rate;
235 
236 	ref_rate = ck_ref_p->rate;
237 
238 	for (ptr = omap1_rate_table; ptr->rate; ptr++) {
239 		if (!(ptr->flags & cpu_mask))
240 			continue;
241 
242 		if (ptr->xtal != ref_rate)
243 			continue;
244 
245 		/* Can check only after xtal frequency check */
246 		if (ptr->rate <= rate)
247 			break;
248 	}
249 
250 	if (!ptr->rate)
251 		return -EINVAL;
252 
253 	/*
254 	 * In most cases we should not need to reprogram DPLL.
255 	 * Reprogramming the DPLL is tricky, it must be done from SRAM.
256 	 */
257 	omap_sram_reprogram_clock(ptr->dpllctl_val, ptr->ckctl_val);
258 
259 	/* XXX Do we need to recalculate the tree below DPLL1 at this point? */
260 	ck_dpll1_p->rate = ptr->pll_rate;
261 
262 	return 0;
263 }
264 
omap1_clk_set_rate_dsp_domain(struct omap1_clk * clk,unsigned long rate,unsigned long p_rate)265 int omap1_clk_set_rate_dsp_domain(struct omap1_clk *clk, unsigned long rate, unsigned long p_rate)
266 {
267 	int dsor_exp;
268 	u16 regval;
269 
270 	dsor_exp = calc_dsor_exp(rate, p_rate);
271 	if (dsor_exp > 3)
272 		dsor_exp = -EINVAL;
273 	if (dsor_exp < 0)
274 		return dsor_exp;
275 
276 	regval = __raw_readw(DSP_CKCTL);
277 	regval &= ~(3 << clk->rate_offset);
278 	regval |= dsor_exp << clk->rate_offset;
279 	__raw_writew(regval, DSP_CKCTL);
280 	clk->rate = p_rate / (1 << dsor_exp);
281 
282 	return 0;
283 }
284 
omap1_clk_round_rate_ckctl_arm(struct omap1_clk * clk,unsigned long rate,unsigned long * p_rate)285 long omap1_clk_round_rate_ckctl_arm(struct omap1_clk *clk, unsigned long rate,
286 				    unsigned long *p_rate)
287 {
288 	int dsor_exp = calc_dsor_exp(rate, *p_rate);
289 
290 	if (dsor_exp < 0)
291 		return dsor_exp;
292 	if (dsor_exp > 3)
293 		dsor_exp = 3;
294 	return *p_rate / (1 << dsor_exp);
295 }
296 
omap1_clk_set_rate_ckctl_arm(struct omap1_clk * clk,unsigned long rate,unsigned long p_rate)297 int omap1_clk_set_rate_ckctl_arm(struct omap1_clk *clk, unsigned long rate, unsigned long p_rate)
298 {
299 	unsigned long flags;
300 	int dsor_exp;
301 	u16 regval;
302 
303 	dsor_exp = calc_dsor_exp(rate, p_rate);
304 	if (dsor_exp > 3)
305 		dsor_exp = -EINVAL;
306 	if (dsor_exp < 0)
307 		return dsor_exp;
308 
309 	/* protect ARM_CKCTL register from concurrent access via clk_enable/disable() */
310 	spin_lock_irqsave(&arm_ckctl_lock, flags);
311 
312 	regval = omap_readw(ARM_CKCTL);
313 	regval &= ~(3 << clk->rate_offset);
314 	regval |= dsor_exp << clk->rate_offset;
315 	regval = verify_ckctl_value(regval);
316 	omap_writew(regval, ARM_CKCTL);
317 	clk->rate = p_rate / (1 << dsor_exp);
318 
319 	spin_unlock_irqrestore(&arm_ckctl_lock, flags);
320 
321 	return 0;
322 }
323 
omap1_round_to_table_rate(struct omap1_clk * clk,unsigned long rate,unsigned long * p_rate)324 long omap1_round_to_table_rate(struct omap1_clk *clk, unsigned long rate, unsigned long *p_rate)
325 {
326 	/* Find the highest supported frequency <= rate */
327 	struct mpu_rate * ptr;
328 	long highest_rate;
329 	unsigned long ref_rate;
330 
331 	ref_rate = ck_ref_p->rate;
332 
333 	highest_rate = -EINVAL;
334 
335 	for (ptr = omap1_rate_table; ptr->rate; ptr++) {
336 		if (!(ptr->flags & cpu_mask))
337 			continue;
338 
339 		if (ptr->xtal != ref_rate)
340 			continue;
341 
342 		highest_rate = ptr->rate;
343 
344 		/* Can check only after xtal frequency check */
345 		if (ptr->rate <= rate)
346 			break;
347 	}
348 
349 	return highest_rate;
350 }
351 
calc_ext_dsor(unsigned long rate)352 static unsigned calc_ext_dsor(unsigned long rate)
353 {
354 	unsigned dsor;
355 
356 	/* MCLK and BCLK divisor selection is not linear:
357 	 * freq = 96MHz / dsor
358 	 *
359 	 * RATIO_SEL range: dsor <-> RATIO_SEL
360 	 * 0..6: (RATIO_SEL+2) <-> (dsor-2)
361 	 * 6..48:  (8+(RATIO_SEL-6)*2) <-> ((dsor-8)/2+6)
362 	 * Minimum dsor is 2 and maximum is 96. Odd divisors starting from 9
363 	 * can not be used.
364 	 */
365 	for (dsor = 2; dsor < 96; ++dsor) {
366 		if ((dsor & 1) && dsor > 8)
367 			continue;
368 		if (rate >= 96000000 / dsor)
369 			break;
370 	}
371 	return dsor;
372 }
373 
374 /* XXX Only needed on 1510 */
omap1_round_uart_rate(struct omap1_clk * clk,unsigned long rate,unsigned long * p_rate)375 long omap1_round_uart_rate(struct omap1_clk *clk, unsigned long rate, unsigned long *p_rate)
376 {
377 	return rate > 24000000 ? 48000000 : 12000000;
378 }
379 
omap1_set_uart_rate(struct omap1_clk * clk,unsigned long rate,unsigned long p_rate)380 int omap1_set_uart_rate(struct omap1_clk *clk, unsigned long rate, unsigned long p_rate)
381 {
382 	unsigned long flags;
383 	unsigned int val;
384 
385 	if (rate == 12000000)
386 		val = 0;
387 	else if (rate == 48000000)
388 		val = 1 << clk->enable_bit;
389 	else
390 		return -EINVAL;
391 
392 	/* protect MOD_CONF_CTRL_0 register from concurrent access via clk_enable/disable() */
393 	spin_lock_irqsave(&mod_conf_ctrl_0_lock, flags);
394 
395 	val |= __raw_readl(clk->enable_reg) & ~(1 << clk->enable_bit);
396 	__raw_writel(val, clk->enable_reg);
397 
398 	spin_unlock_irqrestore(&mod_conf_ctrl_0_lock, flags);
399 
400 	clk->rate = rate;
401 
402 	return 0;
403 }
404 
405 /* External clock (MCLK & BCLK) functions */
omap1_set_ext_clk_rate(struct omap1_clk * clk,unsigned long rate,unsigned long p_rate)406 int omap1_set_ext_clk_rate(struct omap1_clk *clk, unsigned long rate, unsigned long p_rate)
407 {
408 	unsigned long flags;
409 	unsigned dsor;
410 	__u16 ratio_bits;
411 
412 	dsor = calc_ext_dsor(rate);
413 	clk->rate = 96000000 / dsor;
414 	if (dsor > 8)
415 		ratio_bits = ((dsor - 8) / 2 + 6) << 2;
416 	else
417 		ratio_bits = (dsor - 2) << 2;
418 
419 	/* protect SWD_CLK_DIV_CTRL_SEL register from concurrent access via clk_enable/disable() */
420 	spin_lock_irqsave(&swd_clk_div_ctrl_sel_lock, flags);
421 
422 	ratio_bits |= __raw_readw(clk->enable_reg) & ~0xfd;
423 	__raw_writew(ratio_bits, clk->enable_reg);
424 
425 	spin_unlock_irqrestore(&swd_clk_div_ctrl_sel_lock, flags);
426 
427 	return 0;
428 }
429 
calc_div_sossi(unsigned long rate,unsigned long p_rate)430 static int calc_div_sossi(unsigned long rate, unsigned long p_rate)
431 {
432 	int div;
433 
434 	/* Round towards slower frequency */
435 	div = (p_rate + rate - 1) / rate;
436 
437 	return --div;
438 }
439 
omap1_round_sossi_rate(struct omap1_clk * clk,unsigned long rate,unsigned long * p_rate)440 long omap1_round_sossi_rate(struct omap1_clk *clk, unsigned long rate, unsigned long *p_rate)
441 {
442 	int div;
443 
444 	div = calc_div_sossi(rate, *p_rate);
445 	if (div < 0)
446 		div = 0;
447 	else if (div > 7)
448 		div = 7;
449 
450 	return *p_rate / (div + 1);
451 }
452 
omap1_set_sossi_rate(struct omap1_clk * clk,unsigned long rate,unsigned long p_rate)453 int omap1_set_sossi_rate(struct omap1_clk *clk, unsigned long rate, unsigned long p_rate)
454 {
455 	unsigned long flags;
456 	u32 l;
457 	int div;
458 
459 	div = calc_div_sossi(rate, p_rate);
460 	if (div < 0 || div > 7)
461 		return -EINVAL;
462 
463 	/* protect MOD_CONF_CTRL_1 register from concurrent access via clk_enable/disable() */
464 	spin_lock_irqsave(&mod_conf_ctrl_1_lock, flags);
465 
466 	l = omap_readl(MOD_CONF_CTRL_1);
467 	l &= ~(7 << 17);
468 	l |= div << 17;
469 	omap_writel(l, MOD_CONF_CTRL_1);
470 
471 	clk->rate = p_rate / (div + 1);
472 
473 	spin_unlock_irqrestore(&mod_conf_ctrl_1_lock, flags);
474 
475 	return 0;
476 }
477 
omap1_round_ext_clk_rate(struct omap1_clk * clk,unsigned long rate,unsigned long * p_rate)478 long omap1_round_ext_clk_rate(struct omap1_clk *clk, unsigned long rate, unsigned long *p_rate)
479 {
480 	return 96000000 / calc_ext_dsor(rate);
481 }
482 
omap1_init_ext_clk(struct omap1_clk * clk)483 int omap1_init_ext_clk(struct omap1_clk *clk)
484 {
485 	unsigned dsor;
486 	__u16 ratio_bits;
487 
488 	/* Determine current rate and ensure clock is based on 96MHz APLL */
489 	ratio_bits = __raw_readw(clk->enable_reg) & ~1;
490 	__raw_writew(ratio_bits, clk->enable_reg);
491 
492 	ratio_bits = (ratio_bits & 0xfc) >> 2;
493 	if (ratio_bits > 6)
494 		dsor = (ratio_bits - 6) * 2 + 8;
495 	else
496 		dsor = ratio_bits + 2;
497 
498 	clk-> rate = 96000000 / dsor;
499 
500 	return 0;
501 }
502 
omap1_clk_enable(struct clk_hw * hw)503 static int omap1_clk_enable(struct clk_hw *hw)
504 {
505 	struct omap1_clk *clk = to_omap1_clk(hw), *parent = to_omap1_clk(clk_hw_get_parent(hw));
506 	int ret = 0;
507 
508 	if (parent && clk->flags & CLOCK_NO_IDLE_PARENT)
509 		omap1_clk_deny_idle(parent);
510 
511 	if (clk->ops && !(WARN_ON(!clk->ops->enable)))
512 		ret = clk->ops->enable(clk);
513 
514 	return ret;
515 }
516 
omap1_clk_disable(struct clk_hw * hw)517 static void omap1_clk_disable(struct clk_hw *hw)
518 {
519 	struct omap1_clk *clk = to_omap1_clk(hw), *parent = to_omap1_clk(clk_hw_get_parent(hw));
520 
521 	if (clk->ops && !(WARN_ON(!clk->ops->disable)))
522 		clk->ops->disable(clk);
523 
524 	if (likely(parent) && clk->flags & CLOCK_NO_IDLE_PARENT)
525 		omap1_clk_allow_idle(parent);
526 }
527 
omap1_clk_enable_generic(struct omap1_clk * clk)528 static int omap1_clk_enable_generic(struct omap1_clk *clk)
529 {
530 	unsigned long flags;
531 	__u16 regval16;
532 	__u32 regval32;
533 
534 	if (unlikely(clk->enable_reg == NULL)) {
535 		printk(KERN_ERR "clock.c: Enable for %s without enable code\n",
536 		       clk_hw_get_name(&clk->hw));
537 		return -EINVAL;
538 	}
539 
540 	/* protect clk->enable_reg from concurrent access via clk_set_rate() */
541 	if (clk->enable_reg == OMAP1_IO_ADDRESS(ARM_CKCTL))
542 		spin_lock_irqsave(&arm_ckctl_lock, flags);
543 	else if (clk->enable_reg == OMAP1_IO_ADDRESS(ARM_IDLECT2))
544 		spin_lock_irqsave(&arm_idlect2_lock, flags);
545 	else if (clk->enable_reg == OMAP1_IO_ADDRESS(MOD_CONF_CTRL_0))
546 		spin_lock_irqsave(&mod_conf_ctrl_0_lock, flags);
547 	else if (clk->enable_reg == OMAP1_IO_ADDRESS(MOD_CONF_CTRL_1))
548 		spin_lock_irqsave(&mod_conf_ctrl_1_lock, flags);
549 	else if (clk->enable_reg == OMAP1_IO_ADDRESS(SWD_CLK_DIV_CTRL_SEL))
550 		spin_lock_irqsave(&swd_clk_div_ctrl_sel_lock, flags);
551 
552 	if (clk->flags & ENABLE_REG_32BIT) {
553 		regval32 = __raw_readl(clk->enable_reg);
554 		regval32 |= (1 << clk->enable_bit);
555 		__raw_writel(regval32, clk->enable_reg);
556 	} else {
557 		regval16 = __raw_readw(clk->enable_reg);
558 		regval16 |= (1 << clk->enable_bit);
559 		__raw_writew(regval16, clk->enable_reg);
560 	}
561 
562 	if (clk->enable_reg == OMAP1_IO_ADDRESS(ARM_CKCTL))
563 		spin_unlock_irqrestore(&arm_ckctl_lock, flags);
564 	else if (clk->enable_reg == OMAP1_IO_ADDRESS(ARM_IDLECT2))
565 		spin_unlock_irqrestore(&arm_idlect2_lock, flags);
566 	else if (clk->enable_reg == OMAP1_IO_ADDRESS(MOD_CONF_CTRL_0))
567 		spin_unlock_irqrestore(&mod_conf_ctrl_0_lock, flags);
568 	else if (clk->enable_reg == OMAP1_IO_ADDRESS(MOD_CONF_CTRL_1))
569 		spin_unlock_irqrestore(&mod_conf_ctrl_1_lock, flags);
570 	else if (clk->enable_reg == OMAP1_IO_ADDRESS(SWD_CLK_DIV_CTRL_SEL))
571 		spin_unlock_irqrestore(&swd_clk_div_ctrl_sel_lock, flags);
572 
573 	return 0;
574 }
575 
omap1_clk_disable_generic(struct omap1_clk * clk)576 static void omap1_clk_disable_generic(struct omap1_clk *clk)
577 {
578 	unsigned long flags;
579 	__u16 regval16;
580 	__u32 regval32;
581 
582 	if (clk->enable_reg == NULL)
583 		return;
584 
585 	/* protect clk->enable_reg from concurrent access via clk_set_rate() */
586 	if (clk->enable_reg == OMAP1_IO_ADDRESS(ARM_CKCTL))
587 		spin_lock_irqsave(&arm_ckctl_lock, flags);
588 	else if (clk->enable_reg == OMAP1_IO_ADDRESS(ARM_IDLECT2))
589 		spin_lock_irqsave(&arm_idlect2_lock, flags);
590 	else if (clk->enable_reg == OMAP1_IO_ADDRESS(MOD_CONF_CTRL_0))
591 		spin_lock_irqsave(&mod_conf_ctrl_0_lock, flags);
592 	else if (clk->enable_reg == OMAP1_IO_ADDRESS(MOD_CONF_CTRL_1))
593 		spin_lock_irqsave(&mod_conf_ctrl_1_lock, flags);
594 	else if (clk->enable_reg == OMAP1_IO_ADDRESS(SWD_CLK_DIV_CTRL_SEL))
595 		spin_lock_irqsave(&swd_clk_div_ctrl_sel_lock, flags);
596 
597 	if (clk->flags & ENABLE_REG_32BIT) {
598 		regval32 = __raw_readl(clk->enable_reg);
599 		regval32 &= ~(1 << clk->enable_bit);
600 		__raw_writel(regval32, clk->enable_reg);
601 	} else {
602 		regval16 = __raw_readw(clk->enable_reg);
603 		regval16 &= ~(1 << clk->enable_bit);
604 		__raw_writew(regval16, clk->enable_reg);
605 	}
606 
607 	if (clk->enable_reg == OMAP1_IO_ADDRESS(ARM_CKCTL))
608 		spin_unlock_irqrestore(&arm_ckctl_lock, flags);
609 	else if (clk->enable_reg == OMAP1_IO_ADDRESS(ARM_IDLECT2))
610 		spin_unlock_irqrestore(&arm_idlect2_lock, flags);
611 	else if (clk->enable_reg == OMAP1_IO_ADDRESS(MOD_CONF_CTRL_0))
612 		spin_unlock_irqrestore(&mod_conf_ctrl_0_lock, flags);
613 	else if (clk->enable_reg == OMAP1_IO_ADDRESS(MOD_CONF_CTRL_1))
614 		spin_unlock_irqrestore(&mod_conf_ctrl_1_lock, flags);
615 	else if (clk->enable_reg == OMAP1_IO_ADDRESS(SWD_CLK_DIV_CTRL_SEL))
616 		spin_unlock_irqrestore(&swd_clk_div_ctrl_sel_lock, flags);
617 }
618 
619 const struct clkops clkops_generic = {
620 	.enable		= omap1_clk_enable_generic,
621 	.disable	= omap1_clk_disable_generic,
622 };
623 
omap1_clk_enable_dsp_domain(struct omap1_clk * clk)624 static int omap1_clk_enable_dsp_domain(struct omap1_clk *clk)
625 {
626 	bool api_ck_was_enabled;
627 	int retval = 0;
628 
629 	api_ck_was_enabled = omap1_clk_is_enabled(&api_ck_p->hw);
630 	if (!api_ck_was_enabled)
631 		retval = api_ck_p->ops->enable(api_ck_p);
632 
633 	if (!retval) {
634 		retval = omap1_clk_enable_generic(clk);
635 
636 		if (!api_ck_was_enabled)
637 			api_ck_p->ops->disable(api_ck_p);
638 	}
639 
640 	return retval;
641 }
642 
omap1_clk_disable_dsp_domain(struct omap1_clk * clk)643 static void omap1_clk_disable_dsp_domain(struct omap1_clk *clk)
644 {
645 	bool api_ck_was_enabled;
646 
647 	api_ck_was_enabled = omap1_clk_is_enabled(&api_ck_p->hw);
648 	if (!api_ck_was_enabled)
649 		if (api_ck_p->ops->enable(api_ck_p) < 0)
650 			return;
651 
652 	omap1_clk_disable_generic(clk);
653 
654 	if (!api_ck_was_enabled)
655 		api_ck_p->ops->disable(api_ck_p);
656 }
657 
658 const struct clkops clkops_dspck = {
659 	.enable		= omap1_clk_enable_dsp_domain,
660 	.disable	= omap1_clk_disable_dsp_domain,
661 };
662 
663 /* XXX SYSC register handling does not belong in the clock framework */
omap1_clk_enable_uart_functional_16xx(struct omap1_clk * clk)664 static int omap1_clk_enable_uart_functional_16xx(struct omap1_clk *clk)
665 {
666 	int ret;
667 	struct uart_clk *uclk;
668 
669 	ret = omap1_clk_enable_generic(clk);
670 	if (ret == 0) {
671 		/* Set smart idle acknowledgement mode */
672 		uclk = (struct uart_clk *)clk;
673 		omap_writeb((omap_readb(uclk->sysc_addr) & ~0x10) | 8,
674 			    uclk->sysc_addr);
675 	}
676 
677 	return ret;
678 }
679 
680 /* XXX SYSC register handling does not belong in the clock framework */
omap1_clk_disable_uart_functional_16xx(struct omap1_clk * clk)681 static void omap1_clk_disable_uart_functional_16xx(struct omap1_clk *clk)
682 {
683 	struct uart_clk *uclk;
684 
685 	/* Set force idle acknowledgement mode */
686 	uclk = (struct uart_clk *)clk;
687 	omap_writeb((omap_readb(uclk->sysc_addr) & ~0x18), uclk->sysc_addr);
688 
689 	omap1_clk_disable_generic(clk);
690 }
691 
692 /* XXX SYSC register handling does not belong in the clock framework */
693 const struct clkops clkops_uart_16xx = {
694 	.enable		= omap1_clk_enable_uart_functional_16xx,
695 	.disable	= omap1_clk_disable_uart_functional_16xx,
696 };
697 
omap1_clk_recalc_rate(struct clk_hw * hw,unsigned long p_rate)698 static unsigned long omap1_clk_recalc_rate(struct clk_hw *hw, unsigned long p_rate)
699 {
700 	struct omap1_clk *clk = to_omap1_clk(hw);
701 
702 	if (clk->recalc)
703 		return clk->recalc(clk, p_rate);
704 
705 	return clk->rate;
706 }
707 
omap1_clk_round_rate(struct clk_hw * hw,unsigned long rate,unsigned long * p_rate)708 static long omap1_clk_round_rate(struct clk_hw *hw, unsigned long rate, unsigned long *p_rate)
709 {
710 	struct omap1_clk *clk = to_omap1_clk(hw);
711 
712 	if (clk->round_rate != NULL)
713 		return clk->round_rate(clk, rate, p_rate);
714 
715 	return omap1_clk_recalc_rate(hw, *p_rate);
716 }
717 
omap1_clk_set_rate(struct clk_hw * hw,unsigned long rate,unsigned long p_rate)718 static int omap1_clk_set_rate(struct clk_hw *hw, unsigned long rate, unsigned long p_rate)
719 {
720 	struct omap1_clk *clk = to_omap1_clk(hw);
721 	int  ret = -EINVAL;
722 
723 	if (clk->set_rate)
724 		ret = clk->set_rate(clk, rate, p_rate);
725 	return ret;
726 }
727 
728 /*
729  * Omap1 clock reset and init functions
730  */
731 
omap1_clk_init_op(struct clk_hw * hw)732 static int omap1_clk_init_op(struct clk_hw *hw)
733 {
734 	struct omap1_clk *clk = to_omap1_clk(hw);
735 
736 	if (clk->init)
737 		return clk->init(clk);
738 
739 	return 0;
740 }
741 
742 #ifdef CONFIG_OMAP_RESET_CLOCKS
743 
omap1_clk_disable_unused(struct clk_hw * hw)744 static void omap1_clk_disable_unused(struct clk_hw *hw)
745 {
746 	struct omap1_clk *clk = to_omap1_clk(hw);
747 	const char *name = clk_hw_get_name(hw);
748 
749 	/* Clocks in the DSP domain need api_ck. Just assume bootloader
750 	 * has not enabled any DSP clocks */
751 	if (clk->enable_reg == DSP_IDLECT2) {
752 		pr_info("Skipping reset check for DSP domain clock \"%s\"\n", name);
753 		return;
754 	}
755 
756 	pr_info("Disabling unused clock \"%s\"... ", name);
757 	omap1_clk_disable(hw);
758 	printk(" done\n");
759 }
760 
761 #endif
762 
763 const struct clk_ops omap1_clk_gate_ops = {
764 	.enable		= omap1_clk_enable,
765 	.disable	= omap1_clk_disable,
766 	.is_enabled	= omap1_clk_is_enabled,
767 #ifdef CONFIG_OMAP_RESET_CLOCKS
768 	.disable_unused	= omap1_clk_disable_unused,
769 #endif
770 };
771 
772 const struct clk_ops omap1_clk_rate_ops = {
773 	.recalc_rate	= omap1_clk_recalc_rate,
774 	.round_rate	= omap1_clk_round_rate,
775 	.set_rate	= omap1_clk_set_rate,
776 	.init		= omap1_clk_init_op,
777 };
778 
779 const struct clk_ops omap1_clk_full_ops = {
780 	.enable		= omap1_clk_enable,
781 	.disable	= omap1_clk_disable,
782 	.is_enabled	= omap1_clk_is_enabled,
783 #ifdef CONFIG_OMAP_RESET_CLOCKS
784 	.disable_unused	= omap1_clk_disable_unused,
785 #endif
786 	.recalc_rate	= omap1_clk_recalc_rate,
787 	.round_rate	= omap1_clk_round_rate,
788 	.set_rate	= omap1_clk_set_rate,
789 	.init		= omap1_clk_init_op,
790 };
791 
792 /*
793  * OMAP specific clock functions shared between omap1 and omap2
794  */
795 
796 /* Used for clocks that always have same value as the parent clock */
followparent_recalc(struct omap1_clk * clk,unsigned long p_rate)797 unsigned long followparent_recalc(struct omap1_clk *clk, unsigned long p_rate)
798 {
799 	return p_rate;
800 }
801 
802 /*
803  * Used for clocks that have the same value as the parent clock,
804  * divided by some factor
805  */
omap_fixed_divisor_recalc(struct omap1_clk * clk,unsigned long p_rate)806 unsigned long omap_fixed_divisor_recalc(struct omap1_clk *clk, unsigned long p_rate)
807 {
808 	WARN_ON(!clk->fixed_div);
809 
810 	return p_rate / clk->fixed_div;
811 }
812 
813 /* Propagate rate to children */
propagate_rate(struct omap1_clk * tclk)814 void propagate_rate(struct omap1_clk *tclk)
815 {
816 	struct clk *clkp;
817 
818 	/* depend on CCF ability to recalculate new rates across whole clock subtree */
819 	if (WARN_ON(!(clk_hw_get_flags(&tclk->hw) & CLK_GET_RATE_NOCACHE)))
820 		return;
821 
822 	clkp = clk_get_sys(NULL, clk_hw_get_name(&tclk->hw));
823 	if (WARN_ON(!clkp))
824 		return;
825 
826 	clk_get_rate(clkp);
827 	clk_put(clkp);
828 }
829 
830 const struct clk_ops omap1_clk_null_ops = {
831 };
832 
833 /*
834  * Dummy clock
835  *
836  * Used for clock aliases that are needed on some OMAPs, but not others
837  */
838 struct omap1_clk dummy_ck __refdata = {
839 	.hw.init	= CLK_HW_INIT_NO_PARENT("dummy", &omap1_clk_null_ops, 0),
840 };
841