clock.c (ecf0aa5317b0ad6bb015128a5b763c954fd58708) clock.c (c73b9099da4fb5703abaa804a0377850eea66cb5)
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>
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>
19#include <linux/soc/ti/omap1-io.h>
20#include <linux/soc/ti/omap1-io.h>
21#include <linux/spinlock.h>
20
21#include <asm/mach-types.h>
22
23#include "hardware.h"
24#include "soc.h"
25#include "iomap.h"
26#include "clock.h"
27#include "opp.h"
28#include "sram.h"
29
30__u32 arm_idlect1_mask;
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;
31struct clk *api_ck_p, *ck_dpll1_p, *ck_ref_p;
33/* provide direct internal access (not via clk API) to some clocks */
34struct omap1_clk *api_ck_p, *ck_dpll1_p, *ck_ref_p;
32
35
33static LIST_HEAD(clocks);
34static DEFINE_MUTEX(clocks_mutex);
35static DEFINE_SPINLOCK(clockfw_lock);
36/* protect registeres shared among clk_enable/disable() and clk_set_rate() operations */
37static DEFINE_SPINLOCK(arm_ckctl_lock);
38static DEFINE_SPINLOCK(arm_idlect2_lock);
39static DEFINE_SPINLOCK(mod_conf_ctrl_0_lock);
40static DEFINE_SPINLOCK(mod_conf_ctrl_1_lock);
41static DEFINE_SPINLOCK(swd_clk_div_ctrl_sel_lock);
36
37/*
38 * Omap1 specific clock functions
39 */
40
42
43/*
44 * Omap1 specific clock functions
45 */
46
41unsigned long omap1_uart_recalc(struct clk *clk)
47unsigned long omap1_uart_recalc(struct omap1_clk *clk, unsigned long p_rate)
42{
43 unsigned int val = __raw_readl(clk->enable_reg);
44 return val & 1 << clk->enable_bit ? 48000000 : 12000000;
45}
46
48{
49 unsigned int val = __raw_readl(clk->enable_reg);
50 return val & 1 << clk->enable_bit ? 48000000 : 12000000;
51}
52
47unsigned long omap1_sossi_recalc(struct clk *clk)
53unsigned long omap1_sossi_recalc(struct omap1_clk *clk, unsigned long p_rate)
48{
49 u32 div = omap_readl(MOD_CONF_CTRL_1);
50
51 div = (div >> 17) & 0x7;
52 div++;
53
54{
55 u32 div = omap_readl(MOD_CONF_CTRL_1);
56
57 div = (div >> 17) & 0x7;
58 div++;
59
54 return clk->parent->rate / div;
60 return p_rate / div;
55}
56
61}
62
57static void omap1_clk_allow_idle(struct clk *clk)
63static void omap1_clk_allow_idle(struct omap1_clk *clk)
58{
59 struct arm_idlect1_clk * iclk = (struct arm_idlect1_clk *)clk;
60
61 if (!(clk->flags & CLOCK_IDLE_CONTROL))
62 return;
63
64 if (iclk->no_idle_count > 0 && !(--iclk->no_idle_count))
65 arm_idlect1_mask |= 1 << iclk->idlect_shift;
66}
67
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
68static void omap1_clk_deny_idle(struct clk *clk)
74static void omap1_clk_deny_idle(struct omap1_clk *clk)
69{
70 struct arm_idlect1_clk * iclk = (struct arm_idlect1_clk *)clk;
71
72 if (!(clk->flags & CLOCK_IDLE_CONTROL))
73 return;
74
75 if (iclk->no_idle_count++ == 0)
76 arm_idlect1_mask &= ~(1 << iclk->idlect_shift);

--- 47 unchanged lines hidden (view full) ---

124 newval |= arm_exp << CKCTL_ARMDIV_OFFSET;
125 newval |= dsp_exp << CKCTL_DSPDIV_OFFSET;
126 newval |= tc_exp << CKCTL_TCDIV_OFFSET;
127 newval |= dspmmu_exp << CKCTL_DSPMMUDIV_OFFSET;
128
129 return newval;
130}
131
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);

--- 47 unchanged lines hidden (view full) ---

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
132static int calc_dsor_exp(struct clk *clk, unsigned long rate)
138static int calc_dsor_exp(unsigned long rate, unsigned long realrate)
133{
134 /* Note: If target frequency is too low, this function will return 4,
135 * which is invalid value. Caller must check for this value and act
136 * accordingly.
137 *
138 * Note: This function does not check for following limitations set
139 * by the hardware (all conditions must be true):
140 * DSPMMU_CK == DSP_CK or DSPMMU_CK == DSP_CK/2
141 * ARM_CK >= TC_CK
142 * DSP_CK >= TC_CK
143 * DSPMMU_CK >= TC_CK
144 */
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 */
145 unsigned long realrate;
146 struct clk * parent;
147 unsigned dsor_exp;
148
151 unsigned dsor_exp;
152
149 parent = clk->parent;
150 if (unlikely(parent == NULL))
153 if (unlikely(realrate == 0))
151 return -EIO;
152
154 return -EIO;
155
153 realrate = parent->rate;
154 for (dsor_exp=0; dsor_exp<4; dsor_exp++) {
155 if (realrate <= rate)
156 break;
157
158 realrate /= 2;
159 }
160
161 return dsor_exp;
162}
163
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
164unsigned long omap1_ckctl_recalc(struct clk *clk)
166unsigned long omap1_ckctl_recalc(struct omap1_clk *clk, unsigned long p_rate)
165{
166 /* Calculate divisor encoded as 2-bit exponent */
167 int dsor = 1 << (3 & (omap_readw(ARM_CKCTL) >> clk->rate_offset));
168
167{
168 /* Calculate divisor encoded as 2-bit exponent */
169 int dsor = 1 << (3 & (omap_readw(ARM_CKCTL) >> clk->rate_offset));
170
169 return clk->parent->rate / dsor;
171 /* update locally maintained rate, required by arm_ck for omap1_show_rates() */
172 clk->rate = p_rate / dsor;
173 return clk->rate;
170}
171
174}
175
172unsigned long omap1_ckctl_recalc_dsp_domain(struct clk *clk)
176static int omap1_clk_is_enabled(struct clk_hw *hw)
173{
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
207unsigned long omap1_ckctl_recalc_dsp_domain(struct omap1_clk *clk, unsigned long p_rate)
208{
209 bool api_ck_was_enabled;
174 int dsor;
175
176 /* Calculate divisor encoded as 2-bit exponent
177 *
178 * The clock control bits are in DSP domain,
179 * so api_ck is needed for access.
180 * Note that DSP_CKCTL virt addr = phys addr, so
181 * we must use __raw_readw() instead of omap_readw().
182 */
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 */
183 omap1_clk_enable(api_ck_p);
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);
184 dsor = 1 << (3 & (__raw_readw(DSP_CKCTL) >> clk->rate_offset));
222 dsor = 1 << (3 & (__raw_readw(DSP_CKCTL) >> clk->rate_offset));
185 omap1_clk_disable(api_ck_p);
223 if (!api_ck_was_enabled)
224 api_ck_p->ops->disable(api_ck_p);
186
225
187 return clk->parent->rate / dsor;
226 return p_rate / dsor;
188}
189
190/* MPU virtual clock functions */
227}
228
229/* MPU virtual clock functions */
191int omap1_select_table_rate(struct clk *clk, unsigned long rate)
230int omap1_select_table_rate(struct omap1_clk *clk, unsigned long rate, unsigned long p_rate)
192{
193 /* Find the highest supported frequency <= rate and switch to it */
194 struct mpu_rate * ptr;
195 unsigned long ref_rate;
196
197 ref_rate = ck_ref_p->rate;
198
199 for (ptr = omap1_rate_table; ptr->rate; ptr++) {

--- 18 unchanged lines hidden (view full) ---

218 omap_sram_reprogram_clock(ptr->dpllctl_val, ptr->ckctl_val);
219
220 /* XXX Do we need to recalculate the tree below DPLL1 at this point? */
221 ck_dpll1_p->rate = ptr->pll_rate;
222
223 return 0;
224}
225
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++) {

--- 18 unchanged lines hidden (view full) ---

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
226int omap1_clk_set_rate_dsp_domain(struct clk *clk, unsigned long rate)
265int omap1_clk_set_rate_dsp_domain(struct omap1_clk *clk, unsigned long rate, unsigned long p_rate)
227{
228 int dsor_exp;
229 u16 regval;
230
266{
267 int dsor_exp;
268 u16 regval;
269
231 dsor_exp = calc_dsor_exp(clk, rate);
270 dsor_exp = calc_dsor_exp(rate, p_rate);
232 if (dsor_exp > 3)
233 dsor_exp = -EINVAL;
234 if (dsor_exp < 0)
235 return dsor_exp;
236
237 regval = __raw_readw(DSP_CKCTL);
238 regval &= ~(3 << clk->rate_offset);
239 regval |= dsor_exp << clk->rate_offset;
240 __raw_writew(regval, DSP_CKCTL);
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);
241 clk->rate = clk->parent->rate / (1 << dsor_exp);
280 clk->rate = p_rate / (1 << dsor_exp);
242
243 return 0;
244}
245
281
282 return 0;
283}
284
246long omap1_clk_round_rate_ckctl_arm(struct clk *clk, unsigned long rate)
285long omap1_clk_round_rate_ckctl_arm(struct omap1_clk *clk, unsigned long rate,
286 unsigned long *p_rate)
247{
287{
248 int dsor_exp = calc_dsor_exp(clk, rate);
288 int dsor_exp = calc_dsor_exp(rate, *p_rate);
289
249 if (dsor_exp < 0)
250 return dsor_exp;
251 if (dsor_exp > 3)
252 dsor_exp = 3;
290 if (dsor_exp < 0)
291 return dsor_exp;
292 if (dsor_exp > 3)
293 dsor_exp = 3;
253 return clk->parent->rate / (1 << dsor_exp);
294 return *p_rate / (1 << dsor_exp);
254}
255
295}
296
256int omap1_clk_set_rate_ckctl_arm(struct clk *clk, unsigned long rate)
297int omap1_clk_set_rate_ckctl_arm(struct omap1_clk *clk, unsigned long rate, unsigned long p_rate)
257{
298{
299 unsigned long flags;
258 int dsor_exp;
259 u16 regval;
260
300 int dsor_exp;
301 u16 regval;
302
261 dsor_exp = calc_dsor_exp(clk, rate);
303 dsor_exp = calc_dsor_exp(rate, p_rate);
262 if (dsor_exp > 3)
263 dsor_exp = -EINVAL;
264 if (dsor_exp < 0)
265 return dsor_exp;
266
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
267 regval = omap_readw(ARM_CKCTL);
268 regval &= ~(3 << clk->rate_offset);
269 regval |= dsor_exp << clk->rate_offset;
270 regval = verify_ckctl_value(regval);
271 omap_writew(regval, ARM_CKCTL);
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);
272 clk->rate = clk->parent->rate / (1 << dsor_exp);
317 clk->rate = p_rate / (1 << dsor_exp);
318
319 spin_unlock_irqrestore(&arm_ckctl_lock, flags);
320
273 return 0;
274}
275
321 return 0;
322}
323
276long omap1_round_to_table_rate(struct clk *clk, unsigned long rate)
324long omap1_round_to_table_rate(struct omap1_clk *clk, unsigned long rate, unsigned long *p_rate)
277{
278 /* Find the highest supported frequency <= rate */
279 struct mpu_rate * ptr;
280 long highest_rate;
281 unsigned long ref_rate;
282
283 ref_rate = ck_ref_p->rate;
284

--- 34 unchanged lines hidden (view full) ---

319 continue;
320 if (rate >= 96000000 / dsor)
321 break;
322 }
323 return dsor;
324}
325
326/* XXX Only needed on 1510 */
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

--- 34 unchanged lines hidden (view full) ---

367 continue;
368 if (rate >= 96000000 / dsor)
369 break;
370 }
371 return dsor;
372}
373
374/* XXX Only needed on 1510 */
327int omap1_set_uart_rate(struct clk *clk, unsigned long rate)
375long omap1_round_uart_rate(struct omap1_clk *clk, unsigned long rate, unsigned long *p_rate)
328{
376{
377 return rate > 24000000 ? 48000000 : 12000000;
378}
379
380int omap1_set_uart_rate(struct omap1_clk *clk, unsigned long rate, unsigned long p_rate)
381{
382 unsigned long flags;
329 unsigned int val;
330
383 unsigned int val;
384
331 val = __raw_readl(clk->enable_reg);
332 if (rate == 12000000)
385 if (rate == 12000000)
333 val &= ~(1 << clk->enable_bit);
386 val = 0;
334 else if (rate == 48000000)
387 else if (rate == 48000000)
335 val |= (1 << clk->enable_bit);
388 val = 1 << clk->enable_bit;
336 else
337 return -EINVAL;
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);
338 __raw_writel(val, clk->enable_reg);
396 __raw_writel(val, clk->enable_reg);
397
398 spin_unlock_irqrestore(&mod_conf_ctrl_0_lock, flags);
399
339 clk->rate = rate;
340
341 return 0;
342}
343
344/* External clock (MCLK & BCLK) functions */
400 clk->rate = rate;
401
402 return 0;
403}
404
405/* External clock (MCLK & BCLK) functions */
345int omap1_set_ext_clk_rate(struct clk *clk, unsigned long rate)
406int omap1_set_ext_clk_rate(struct omap1_clk *clk, unsigned long rate, unsigned long p_rate)
346{
407{
408 unsigned long flags;
347 unsigned dsor;
348 __u16 ratio_bits;
349
350 dsor = calc_ext_dsor(rate);
351 clk->rate = 96000000 / dsor;
352 if (dsor > 8)
353 ratio_bits = ((dsor - 8) / 2 + 6) << 2;
354 else
355 ratio_bits = (dsor - 2) << 2;
356
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
357 ratio_bits |= __raw_readw(clk->enable_reg) & ~0xfd;
358 __raw_writew(ratio_bits, clk->enable_reg);
359
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
360 return 0;
361}
362
427 return 0;
428}
429
363int omap1_set_sossi_rate(struct clk *clk, unsigned long rate)
430static int calc_div_sossi(unsigned long rate, unsigned long p_rate)
364{
431{
365 u32 l;
366 int div;
432 int div;
367 unsigned long p_rate;
368
433
369 p_rate = clk->parent->rate;
370 /* Round towards slower frequency */
371 div = (p_rate + rate - 1) / rate;
434 /* Round towards slower frequency */
435 div = (p_rate + rate - 1) / rate;
372 div--;
436
437 return --div;
438}
439
440long 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
453int 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);
373 if (div < 0 || div > 7)
374 return -EINVAL;
375
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
376 l = omap_readl(MOD_CONF_CTRL_1);
377 l &= ~(7 << 17);
378 l |= div << 17;
379 omap_writel(l, MOD_CONF_CTRL_1);
380
381 clk->rate = p_rate / (div + 1);
382
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
383 return 0;
384}
385
475 return 0;
476}
477
386long omap1_round_ext_clk_rate(struct clk *clk, unsigned long rate)
478long omap1_round_ext_clk_rate(struct omap1_clk *clk, unsigned long rate, unsigned long *p_rate)
387{
388 return 96000000 / calc_ext_dsor(rate);
389}
390
479{
480 return 96000000 / calc_ext_dsor(rate);
481}
482
391void omap1_init_ext_clk(struct clk *clk)
483int omap1_init_ext_clk(struct omap1_clk *clk)
392{
393 unsigned dsor;
394 __u16 ratio_bits;
395
396 /* Determine current rate and ensure clock is based on 96MHz APLL */
397 ratio_bits = __raw_readw(clk->enable_reg) & ~1;
398 __raw_writew(ratio_bits, clk->enable_reg);
399
400 ratio_bits = (ratio_bits & 0xfc) >> 2;
401 if (ratio_bits > 6)
402 dsor = (ratio_bits - 6) * 2 + 8;
403 else
404 dsor = ratio_bits + 2;
405
406 clk-> rate = 96000000 / dsor;
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;
407}
408
501}
502
409int omap1_clk_enable(struct clk *clk)
503static int omap1_clk_enable(struct clk_hw *hw)
410{
504{
505 struct omap1_clk *clk = to_omap1_clk(hw), *parent = to_omap1_clk(clk_hw_get_parent(hw));
411 int ret = 0;
412
506 int ret = 0;
507
413 if (clk->usecount++ == 0) {
414 if (clk->parent) {
415 ret = omap1_clk_enable(clk->parent);
416 if (ret)
417 goto err;
508 if (parent && clk->flags & CLOCK_NO_IDLE_PARENT)
509 omap1_clk_deny_idle(parent);
418
510
419 if (clk->flags & CLOCK_NO_IDLE_PARENT)
420 omap1_clk_deny_idle(clk->parent);
421 }
422
511 if (clk->ops && !(WARN_ON(!clk->ops->enable)))
423 ret = clk->ops->enable(clk);
512 ret = clk->ops->enable(clk);
424 if (ret) {
425 if (clk->parent)
426 omap1_clk_disable(clk->parent);
427 goto err;
428 }
429 }
430 return ret;
431
513
432err:
433 clk->usecount--;
434 return ret;
435}
436
514 return ret;
515}
516
437void omap1_clk_disable(struct clk *clk)
517static void omap1_clk_disable(struct clk_hw *hw)
438{
518{
439 if (clk->usecount > 0 && !(--clk->usecount)) {
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)))
440 clk->ops->disable(clk);
522 clk->ops->disable(clk);
441 if (likely(clk->parent)) {
442 omap1_clk_disable(clk->parent);
443 if (clk->flags & CLOCK_NO_IDLE_PARENT)
444 omap1_clk_allow_idle(clk->parent);
445 }
446 }
523
524 if (likely(parent) && clk->flags & CLOCK_NO_IDLE_PARENT)
525 omap1_clk_allow_idle(parent);
447}
448
526}
527
449static int omap1_clk_enable_generic(struct clk *clk)
528static int omap1_clk_enable_generic(struct omap1_clk *clk)
450{
529{
530 unsigned long flags;
451 __u16 regval16;
452 __u32 regval32;
453
454 if (unlikely(clk->enable_reg == NULL)) {
455 printk(KERN_ERR "clock.c: Enable for %s without enable code\n",
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",
456 clk->name);
536 clk_hw_get_name(&clk->hw));
457 return -EINVAL;
458 }
459
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
460 if (clk->flags & ENABLE_REG_32BIT) {
461 regval32 = __raw_readl(clk->enable_reg);
462 regval32 |= (1 << clk->enable_bit);
463 __raw_writel(regval32, clk->enable_reg);
464 } else {
465 regval16 = __raw_readw(clk->enable_reg);
466 regval16 |= (1 << clk->enable_bit);
467 __raw_writew(regval16, clk->enable_reg);
468 }
469
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
470 return 0;
471}
472
573 return 0;
574}
575
473static void omap1_clk_disable_generic(struct clk *clk)
576static void omap1_clk_disable_generic(struct omap1_clk *clk)
474{
577{
578 unsigned long flags;
475 __u16 regval16;
476 __u32 regval32;
477
478 if (clk->enable_reg == NULL)
479 return;
480
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
481 if (clk->flags & ENABLE_REG_32BIT) {
482 regval32 = __raw_readl(clk->enable_reg);
483 regval32 &= ~(1 << clk->enable_bit);
484 __raw_writel(regval32, clk->enable_reg);
485 } else {
486 regval16 = __raw_readw(clk->enable_reg);
487 regval16 &= ~(1 << clk->enable_bit);
488 __raw_writew(regval16, clk->enable_reg);
489 }
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);
490}
491
492const struct clkops clkops_generic = {
493 .enable = omap1_clk_enable_generic,
494 .disable = omap1_clk_disable_generic,
495};
496
617}
618
619const struct clkops clkops_generic = {
620 .enable = omap1_clk_enable_generic,
621 .disable = omap1_clk_disable_generic,
622};
623
497static int omap1_clk_enable_dsp_domain(struct clk *clk)
624static int omap1_clk_enable_dsp_domain(struct omap1_clk *clk)
498{
625{
499 int retval;
626 bool api_ck_was_enabled;
627 int retval = 0;
500
628
501 retval = omap1_clk_enable(api_ck_p);
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
502 if (!retval) {
503 retval = omap1_clk_enable_generic(clk);
633 if (!retval) {
634 retval = omap1_clk_enable_generic(clk);
504 omap1_clk_disable(api_ck_p);
635
636 if (!api_ck_was_enabled)
637 api_ck_p->ops->disable(api_ck_p);
505 }
506
507 return retval;
508}
509
638 }
639
640 return retval;
641}
642
510static void omap1_clk_disable_dsp_domain(struct clk *clk)
643static void omap1_clk_disable_dsp_domain(struct omap1_clk *clk)
511{
644{
512 if (omap1_clk_enable(api_ck_p) == 0) {
513 omap1_clk_disable_generic(clk);
514 omap1_clk_disable(api_ck_p);
515 }
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);
516}
517
518const struct clkops clkops_dspck = {
519 .enable = omap1_clk_enable_dsp_domain,
520 .disable = omap1_clk_disable_dsp_domain,
521};
522
523/* XXX SYSC register handling does not belong in the clock framework */
656}
657
658const 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 */
524static int omap1_clk_enable_uart_functional_16xx(struct clk *clk)
664static int omap1_clk_enable_uart_functional_16xx(struct omap1_clk *clk)
525{
526 int ret;
527 struct uart_clk *uclk;
528
529 ret = omap1_clk_enable_generic(clk);
530 if (ret == 0) {
531 /* Set smart idle acknowledgement mode */
532 uclk = (struct uart_clk *)clk;
533 omap_writeb((omap_readb(uclk->sysc_addr) & ~0x10) | 8,
534 uclk->sysc_addr);
535 }
536
537 return ret;
538}
539
540/* XXX SYSC register handling does not belong in the clock framework */
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 */
541static void omap1_clk_disable_uart_functional_16xx(struct clk *clk)
681static void omap1_clk_disable_uart_functional_16xx(struct omap1_clk *clk)
542{
543 struct uart_clk *uclk;
544
545 /* Set force idle acknowledgement mode */
546 uclk = (struct uart_clk *)clk;
547 omap_writeb((omap_readb(uclk->sysc_addr) & ~0x18), uclk->sysc_addr);
548
549 omap1_clk_disable_generic(clk);
550}
551
552/* XXX SYSC register handling does not belong in the clock framework */
553const struct clkops clkops_uart_16xx = {
554 .enable = omap1_clk_enable_uart_functional_16xx,
555 .disable = omap1_clk_disable_uart_functional_16xx,
556};
557
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 */
693const struct clkops clkops_uart_16xx = {
694 .enable = omap1_clk_enable_uart_functional_16xx,
695 .disable = omap1_clk_disable_uart_functional_16xx,
696};
697
558long omap1_clk_round_rate(struct clk *clk, unsigned long rate)
698static unsigned long omap1_clk_recalc_rate(struct clk_hw *hw, unsigned long p_rate)
559{
699{
560 if (clk->round_rate != NULL)
561 return clk->round_rate(clk, rate);
700 struct omap1_clk *clk = to_omap1_clk(hw);
562
701
702 if (clk->recalc)
703 return clk->recalc(clk, p_rate);
704
563 return clk->rate;
564}
565
705 return clk->rate;
706}
707
566int omap1_clk_set_rate(struct clk *clk, unsigned long rate)
708static long omap1_clk_round_rate(struct clk_hw *hw, unsigned long rate, unsigned long *p_rate)
567{
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
718static 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);
568 int ret = -EINVAL;
569
570 if (clk->set_rate)
721 int ret = -EINVAL;
722
723 if (clk->set_rate)
571 ret = clk->set_rate(clk, rate);
724 ret = clk->set_rate(clk, rate, p_rate);
572 return ret;
573}
574
575/*
576 * Omap1 clock reset and init functions
577 */
578
725 return ret;
726}
727
728/*
729 * Omap1 clock reset and init functions
730 */
731
732static 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
579#ifdef CONFIG_OMAP_RESET_CLOCKS
580
742#ifdef CONFIG_OMAP_RESET_CLOCKS
743
581void omap1_clk_disable_unused(struct clk *clk)
744static void omap1_clk_disable_unused(struct clk_hw *hw)
582{
745{
583 __u32 regval32;
746 struct omap1_clk *clk = to_omap1_clk(hw);
747 const char *name = clk_hw_get_name(hw);
584
585 /* Clocks in the DSP domain need api_ck. Just assume bootloader
586 * has not enabled any DSP clocks */
587 if (clk->enable_reg == DSP_IDLECT2) {
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) {
588 pr_info("Skipping reset check for DSP domain clock \"%s\"\n",
589 clk->name);
752 pr_info("Skipping reset check for DSP domain clock \"%s\"\n", name);
590 return;
591 }
592
753 return;
754 }
755
593 /* Is the clock already disabled? */
594 if (clk->flags & ENABLE_REG_32BIT)
595 regval32 = __raw_readl(clk->enable_reg);
596 else
597 regval32 = __raw_readw(clk->enable_reg);
598
599 if ((regval32 & (1 << clk->enable_bit)) == 0)
600 return;
601
602 printk(KERN_INFO "Disabling unused clock \"%s\"... ", clk->name);
603 clk->ops->disable(clk);
756 pr_info("Disabling unused clock \"%s\"... ", name);
757 omap1_clk_disable(hw);
604 printk(" done\n");
605}
606
607#endif
608
758 printk(" done\n");
759}
760
761#endif
762
763const 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};
609
771
610int clk_enable(struct clk *clk)
611{
612 unsigned long flags;
613 int ret;
772const 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};
614
778
615 if (IS_ERR_OR_NULL(clk))
616 return -EINVAL;
779const 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};
617
791
618 spin_lock_irqsave(&clockfw_lock, flags);
619 ret = omap1_clk_enable(clk);
620 spin_unlock_irqrestore(&clockfw_lock, flags);
621
622 return ret;
623}
624EXPORT_SYMBOL(clk_enable);
625
626void clk_disable(struct clk *clk)
627{
628 unsigned long flags;
629
630 if (IS_ERR_OR_NULL(clk))
631 return;
632
633 spin_lock_irqsave(&clockfw_lock, flags);
634 if (clk->usecount == 0) {
635 pr_err("Trying disable clock %s with 0 usecount\n",
636 clk->name);
637 WARN_ON(1);
638 goto out;
639 }
640
641 omap1_clk_disable(clk);
642
643out:
644 spin_unlock_irqrestore(&clockfw_lock, flags);
645}
646EXPORT_SYMBOL(clk_disable);
647
648unsigned long clk_get_rate(struct clk *clk)
649{
650 unsigned long flags;
651 unsigned long ret;
652
653 if (IS_ERR_OR_NULL(clk))
654 return 0;
655
656 spin_lock_irqsave(&clockfw_lock, flags);
657 ret = clk->rate;
658 spin_unlock_irqrestore(&clockfw_lock, flags);
659
660 return ret;
661}
662EXPORT_SYMBOL(clk_get_rate);
663
664/*
792/*
665 * Optional clock functions defined in include/linux/clk.h
666 */
667
668long clk_round_rate(struct clk *clk, unsigned long rate)
669{
670 unsigned long flags;
671 long ret;
672
673 if (IS_ERR_OR_NULL(clk))
674 return 0;
675
676 spin_lock_irqsave(&clockfw_lock, flags);
677 ret = omap1_clk_round_rate(clk, rate);
678 spin_unlock_irqrestore(&clockfw_lock, flags);
679
680 return ret;
681}
682EXPORT_SYMBOL(clk_round_rate);
683
684int clk_set_rate(struct clk *clk, unsigned long rate)
685{
686 unsigned long flags;
687 int ret = -EINVAL;
688
689 if (IS_ERR_OR_NULL(clk))
690 return ret;
691
692 spin_lock_irqsave(&clockfw_lock, flags);
693 ret = omap1_clk_set_rate(clk, rate);
694 if (ret == 0)
695 propagate_rate(clk);
696 spin_unlock_irqrestore(&clockfw_lock, flags);
697
698 return ret;
699}
700EXPORT_SYMBOL(clk_set_rate);
701
702int clk_set_parent(struct clk *clk, struct clk *parent)
703{
704 WARN_ONCE(1, "clk_set_parent() not implemented for OMAP1\n");
705
706 return -EINVAL;
707}
708EXPORT_SYMBOL(clk_set_parent);
709
710struct clk *clk_get_parent(struct clk *clk)
711{
712 return clk->parent;
713}
714EXPORT_SYMBOL(clk_get_parent);
715
716/*
717 * OMAP specific clock functions shared between omap1 and omap2
718 */
719
720/* Used for clocks that always have same value as the parent clock */
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 */
721unsigned long followparent_recalc(struct clk *clk)
797unsigned long followparent_recalc(struct omap1_clk *clk, unsigned long p_rate)
722{
798{
723 return clk->parent->rate;
799 return p_rate;
724}
725
726/*
727 * Used for clocks that have the same value as the parent clock,
728 * divided by some factor
729 */
800}
801
802/*
803 * Used for clocks that have the same value as the parent clock,
804 * divided by some factor
805 */
730unsigned long omap_fixed_divisor_recalc(struct clk *clk)
806unsigned long omap_fixed_divisor_recalc(struct omap1_clk *clk, unsigned long p_rate)
731{
732 WARN_ON(!clk->fixed_div);
733
807{
808 WARN_ON(!clk->fixed_div);
809
734 return clk->parent->rate / clk->fixed_div;
810 return p_rate / clk->fixed_div;
735}
736
737/* Propagate rate to children */
811}
812
813/* Propagate rate to children */
738void propagate_rate(struct clk *tclk)
814void propagate_rate(struct omap1_clk *tclk)
739{
740 struct clk *clkp;
741
815{
816 struct clk *clkp;
817
742 list_for_each_entry(clkp, &tclk->children, sibling) {
743 if (clkp->recalc)
744 clkp->rate = clkp->recalc(clkp);
745 propagate_rate(clkp);
746 }
747}
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;
748
821
749static LIST_HEAD(root_clks);
750
751/**
752 * clk_preinit - initialize any fields in the struct clk before clk init
753 * @clk: struct clk * to initialize
754 *
755 * Initialize any struct clk fields needed before normal clk initialization
756 * can run. No return value.
757 */
758void clk_preinit(struct clk *clk)
759{
760 INIT_LIST_HEAD(&clk->children);
761}
762
763int clk_register(struct clk *clk)
764{
765 if (IS_ERR_OR_NULL(clk))
766 return -EINVAL;
767
768 /*
769 * trap out already registered clocks
770 */
771 if (clk->node.next || clk->node.prev)
772 return 0;
773
774 mutex_lock(&clocks_mutex);
775 if (clk->parent)
776 list_add(&clk->sibling, &clk->parent->children);
777 else
778 list_add(&clk->sibling, &root_clks);
779
780 list_add(&clk->node, &clocks);
781 if (clk->init)
782 clk->init(clk);
783 mutex_unlock(&clocks_mutex);
784
785 return 0;
786}
787EXPORT_SYMBOL(clk_register);
788
789void clk_unregister(struct clk *clk)
790{
791 if (IS_ERR_OR_NULL(clk))
822 clkp = clk_get_sys(NULL, clk_hw_get_name(&tclk->hw));
823 if (WARN_ON(!clkp))
792 return;
793
824 return;
825
794 mutex_lock(&clocks_mutex);
795 list_del(&clk->sibling);
796 list_del(&clk->node);
797 mutex_unlock(&clocks_mutex);
826 clk_get_rate(clkp);
827 clk_put(clkp);
798}
828}
799EXPORT_SYMBOL(clk_unregister);
800
829
801/*
802 * Low level helpers
803 */
804static int clkll_enable_null(struct clk *clk)
805{
806 return 0;
807}
808
809static void clkll_disable_null(struct clk *clk)
810{
811}
812
813const struct clkops clkops_null = {
814 .enable = clkll_enable_null,
815 .disable = clkll_disable_null,
830const struct clk_ops omap1_clk_null_ops = {
816};
817
818/*
819 * Dummy clock
820 *
821 * Used for clock aliases that are needed on some OMAPs, but not others
822 */
831};
832
833/*
834 * Dummy clock
835 *
836 * Used for clock aliases that are needed on some OMAPs, but not others
837 */
823struct clk dummy_ck = {
824 .name = "dummy",
825 .ops = &clkops_null,
838struct omap1_clk dummy_ck __refdata = {
839 .hw.init = CLK_HW_INIT_NO_PARENT("dummy", &omap1_clk_null_ops, 0),
826};
840};
827
828/*
829 *
830 */
831
832#ifdef CONFIG_OMAP_RESET_CLOCKS
833/*
834 * Disable any unused clocks left on by the bootloader
835 */
836static int __init clk_disable_unused(void)
837{
838 struct clk *ck;
839 unsigned long flags;
840
841 pr_info("clock: disabling unused clocks to save power\n");
842
843 spin_lock_irqsave(&clockfw_lock, flags);
844 list_for_each_entry(ck, &clocks, node) {
845 if (ck->ops == &clkops_null)
846 continue;
847
848 if (ck->usecount > 0 || !ck->enable_reg)
849 continue;
850
851 omap1_clk_disable_unused(ck);
852 }
853 spin_unlock_irqrestore(&clockfw_lock, flags);
854
855 return 0;
856}
857late_initcall(clk_disable_unused);
858#endif
859
860#if defined(CONFIG_PM_DEBUG) && defined(CONFIG_DEBUG_FS)
861/*
862 * debugfs support to trace clock tree hierarchy and attributes
863 */
864
865#include <linux/debugfs.h>
866#include <linux/seq_file.h>
867
868static struct dentry *clk_debugfs_root;
869
870static int debug_clock_show(struct seq_file *s, void *unused)
871{
872 struct clk *c;
873 struct clk *pa;
874
875 mutex_lock(&clocks_mutex);
876 seq_printf(s, "%-30s %-30s %-10s %s\n",
877 "clock-name", "parent-name", "rate", "use-count");
878
879 list_for_each_entry(c, &clocks, node) {
880 pa = c->parent;
881 seq_printf(s, "%-30s %-30s %-10lu %d\n",
882 c->name, pa ? pa->name : "none", c->rate,
883 c->usecount);
884 }
885 mutex_unlock(&clocks_mutex);
886
887 return 0;
888}
889
890DEFINE_SHOW_ATTRIBUTE(debug_clock);
891
892static void clk_debugfs_register_one(struct clk *c)
893{
894 struct dentry *d;
895 struct clk *pa = c->parent;
896
897 d = debugfs_create_dir(c->name, pa ? pa->dent : clk_debugfs_root);
898 c->dent = d;
899
900 debugfs_create_u8("usecount", S_IRUGO, c->dent, &c->usecount);
901 debugfs_create_ulong("rate", S_IRUGO, c->dent, &c->rate);
902 debugfs_create_x8("flags", S_IRUGO, c->dent, &c->flags);
903}
904
905static void clk_debugfs_register(struct clk *c)
906{
907 struct clk *pa = c->parent;
908
909 if (pa && !pa->dent)
910 clk_debugfs_register(pa);
911
912 if (!c->dent)
913 clk_debugfs_register_one(c);
914}
915
916static int __init clk_debugfs_init(void)
917{
918 struct clk *c;
919 struct dentry *d;
920
921 d = debugfs_create_dir("clock", NULL);
922 clk_debugfs_root = d;
923
924 list_for_each_entry(c, &clocks, node)
925 clk_debugfs_register(c);
926
927 debugfs_create_file("summary", S_IRUGO, d, NULL, &debug_clock_fops);
928
929 return 0;
930}
931late_initcall(clk_debugfs_init);
932
933#endif /* defined(CONFIG_PM_DEBUG) && defined(CONFIG_DEBUG_FS) */