/arch/arm/mach-fsm/clock-local.c
C | 690 lines | 466 code | 118 blank | 106 comment | 149 complexity | ff565baa5e5d0124f1b29a972a9ada55 MD5 | raw file
Possible License(s): GPL-2.0, LGPL-2.0, AGPL-1.0
1/* Copyright (c) 2009-2010, Code Aurora Forum. All rights reserved.
2 *
3 * This program is free software; you can redistribute it and/or modify
4 * it under the terms of the GNU General Public License version 2 and
5 * only version 2 as published by the Free Software Foundation.
6 *
7 * This program is distributed in the hope that it will be useful,
8 * but WITHOUT ANY WARRANTY; without even the implied warranty of
9 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
10 * GNU General Public License for more details.
11 *
12 * You should have received a copy of the GNU General Public License
13 * along with this program; if not, write to the Free Software
14 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
15 * 02110-1301, USA.
16 *
17 */
18
19#include <linux/kernel.h>
20#include <linux/init.h>
21#include <linux/err.h>
22#include <linux/ctype.h>
23#include <linux/bitops.h>
24#include <linux/io.h>
25#include <linux/spinlock.h>
26#include <linux/delay.h>
27#include <mach/msm_iomap.h>
28#include <mach/clk.h>
29
30#include "clock.h"
31#include "clock-local.h"
32
33/* When enabling/disabling a clock, check the halt bit up to this number
34 * number of times (with a 1 us delay in between) before continuing. */
35#define HALT_CHECK_MAX_LOOPS 100
36/* For clock without halt checking, wait this long after enables/disables. */
37#define HALT_CHECK_DELAY_US 10
38
39DEFINE_SPINLOCK(local_clock_reg_lock);
40struct clk_freq_tbl local_dummy_freq = F_END;
41
42#define MAX_SOURCES 20
43static int src_votes[MAX_SOURCES];
44static DEFINE_SPINLOCK(src_vote_lock);
45
46unsigned local_sys_vdd_votes[NUM_SYS_VDD_LEVELS];
47static DEFINE_SPINLOCK(sys_vdd_vote_lock);
48
49static int local_clk_enable_nolock(unsigned id);
50static int local_clk_disable_nolock(unsigned id);
51static int local_src_enable_nolock(int src);
52static int local_src_disable_nolock(int src);
53
54/*
55 * Common Set-Rate Functions
56 */
57/* For clocks with integer dividers only. */
58void set_rate_basic(struct clk_local *clk, struct clk_freq_tbl *nf)
59{
60 uint32_t reg_val;
61
62 reg_val = readl(clk->ns_reg);
63 reg_val &= ~(clk->ns_mask);
64 reg_val |= nf->ns_val;
65 writel(reg_val, clk->ns_reg);
66}
67
68/* For clocks with MND dividers. */
69void set_rate_mnd(struct clk_local *clk, struct clk_freq_tbl *nf)
70{
71 uint32_t ns_reg_val, cc_reg_val;
72
73 /* Assert MND reset. */
74 ns_reg_val = readl(clk->ns_reg);
75 ns_reg_val |= B(7);
76 writel(ns_reg_val, clk->ns_reg);
77
78 /* Program M and D values. */
79 writel(nf->md_val, clk->md_reg);
80
81 /* Program NS register. */
82 ns_reg_val &= ~(clk->ns_mask);
83 ns_reg_val |= nf->ns_val;
84 writel(ns_reg_val, clk->ns_reg);
85
86 /* If the clock has a separate CC register, program it. */
87 if (clk->ns_reg != clk->cc_reg) {
88 cc_reg_val = readl(clk->cc_reg);
89 cc_reg_val &= ~(clk->cc_mask);
90 cc_reg_val |= nf->cc_val;
91 writel(cc_reg_val, clk->cc_reg);
92 }
93
94 /* Deassert MND reset. */
95 ns_reg_val &= ~B(7);
96 writel(ns_reg_val, clk->ns_reg);
97}
98
99void set_rate_nop(struct clk_local *clk, struct clk_freq_tbl *nf)
100{
101 /* Nothing to do for fixed-rate clocks. */
102}
103
104/*
105 * SYS_VDD voting functions
106 */
107
108/* Update system voltage level given the current votes. */
109static int local_update_sys_vdd(void)
110{
111 static int cur_level;
112 int level, rc = 0;
113
114 if (local_sys_vdd_votes[HIGH])
115 level = HIGH;
116 else if (local_sys_vdd_votes[NOMINAL])
117 level = NOMINAL;
118 else
119 level = LOW;
120
121 if (level == cur_level)
122 return rc;
123
124 rc = soc_update_sys_vdd(level);
125 if (!rc)
126 cur_level = level;
127
128 return rc;
129}
130
131/* Vote for a system voltage level. */
132int local_vote_sys_vdd(unsigned level)
133{
134 int rc = 0;
135 unsigned long flags;
136
137 /* Bounds checking. */
138 if (level >= ARRAY_SIZE(local_sys_vdd_votes))
139 return -EINVAL;
140
141 spin_lock_irqsave(&sys_vdd_vote_lock, flags);
142 local_sys_vdd_votes[level]++;
143 rc = local_update_sys_vdd();
144 if (rc)
145 local_sys_vdd_votes[level]--;
146 spin_unlock_irqrestore(&sys_vdd_vote_lock, flags);
147
148 return rc;
149}
150
151/* Remove vote for a system voltage level. */
152int local_unvote_sys_vdd(unsigned level)
153{
154 int rc = 0;
155 unsigned long flags;
156
157 /* Bounds checking. */
158 if (level >= ARRAY_SIZE(local_sys_vdd_votes))
159 return -EINVAL;
160
161 spin_lock_irqsave(&sys_vdd_vote_lock, flags);
162 if (local_sys_vdd_votes[level])
163 local_sys_vdd_votes[level]--;
164 else {
165 pr_warning("%s: Reference counts are incorrect for level %d!\n",
166 __func__, level);
167 goto out;
168 }
169
170 rc = local_update_sys_vdd();
171 if (rc)
172 local_sys_vdd_votes[level]++;
173out:
174 spin_unlock_irqrestore(&sys_vdd_vote_lock, flags);
175 return rc;
176}
177
178/*
179 * Clock source (PLL/XO) control functions
180 */
181
182/* Enable clock source without taking the lock. */
183static int local_src_enable_nolock(int src)
184{
185 int rc = 0;
186
187 if (!src_votes[src]) {
188 if (soc_clk_sources[src].par != SRC_NONE)
189 rc = local_src_enable_nolock(soc_clk_sources[src].par);
190 if (rc)
191 goto err_par;
192 /* Perform source-specific enable operations. */
193 if (soc_clk_sources[src].enable_func)
194 rc = soc_clk_sources[src].enable_func(src, 1);
195 if (rc)
196 goto err_enable;
197 }
198 src_votes[src]++;
199
200 return rc;
201
202err_enable:
203 if (soc_clk_sources[src].par != SRC_NONE)
204 local_src_disable_nolock(soc_clk_sources[src].par);
205err_par:
206 return rc;
207}
208
209/* Enable clock source. */
210int local_src_enable(int src)
211{
212 int rc = 0;
213 unsigned long flags;
214
215 if (src == SRC_NONE)
216 return rc;
217
218 spin_lock_irqsave(&src_vote_lock, flags);
219 rc = local_src_enable_nolock(src);
220 spin_unlock_irqrestore(&src_vote_lock, flags);
221
222 return rc;
223}
224
225/* Disable clock source without taking the lock. */
226static int local_src_disable_nolock(int src)
227{
228 int rc = 0;
229
230 if (src_votes[src] > 0)
231 src_votes[src]--;
232 else {
233 pr_warning("%s: Reference counts are incorrect for "
234 "src %d!\n", __func__, src);
235 return rc;
236 }
237
238 if (src_votes[src] == 0) {
239 /* Perform source-specific disable operations. */
240 if (soc_clk_sources[src].enable_func)
241 rc = soc_clk_sources[src].enable_func(src, 0);
242 if (rc)
243 goto err_disable;
244 if (soc_clk_sources[src].par != SRC_NONE)
245 rc = local_src_disable_nolock(soc_clk_sources[src].par);
246 if (rc)
247 goto err_disable_par;
248
249 }
250
251 return rc;
252
253err_disable_par:
254 soc_clk_sources[src].enable_func(src, 1);
255err_disable:
256 src_votes[src]++;
257 return rc;
258}
259
260/* Disable clock source. */
261int local_src_disable(int src)
262{
263 int rc = 0;
264 unsigned long flags;
265
266 if (src == SRC_NONE)
267 return rc;
268
269 spin_lock_irqsave(&src_vote_lock, flags);
270 rc = local_src_disable_nolock(src);
271 spin_unlock_irqrestore(&src_vote_lock, flags);
272
273 return rc;
274}
275
276/*
277 * Clock enable/disable functions
278 */
279
280/* Return non-zero if a clock status registers shows the clock is halted. */
281static int local_clk_is_halted(unsigned id)
282{
283 struct clk_local *clk = &soc_clk_local_tbl[id];
284 int invert = (clk->halt_check == ENABLE);
285 int status_bit = readl(clk->halt_reg) & B(clk->halt_bit);
286 return invert ? !status_bit : status_bit;
287}
288
289/* Perform any register operations required to enable the clock. */
290void local_clk_enable_reg(unsigned id)
291{
292 struct clk_local *clk = &soc_clk_local_tbl[id];
293 void *reg = clk->cc_reg;
294 uint32_t reg_val;
295
296 WARN((clk->type != NORATE) && (clk->current_freq == &local_dummy_freq),
297 "Attempting to enable clock %d before setting its rate. "
298 "Set the rate first!\n", id);
299
300 /* Enable MN counter, if applicable. */
301 reg_val = readl(reg);
302 if (clk->type == MND) {
303 reg_val |= clk->current_freq->mnd_en_mask;
304 writel(reg_val, reg);
305 }
306 /* Enable root. */
307 if (clk->root_en_mask) {
308 reg_val |= clk->root_en_mask;
309 writel(reg_val, reg);
310 }
311 /* Enable branch. */
312 if (clk->br_en_mask) {
313 reg_val |= clk->br_en_mask;
314 writel(reg_val, reg);
315 }
316
317 /* Wait for clock to enable before returning. */
318 if (clk->halt_check == DELAY)
319 udelay(HALT_CHECK_DELAY_US);
320 else if (clk->halt_check == ENABLE || clk->halt_check == HALT) {
321 int count;
322 /* Use a memory barrier since some halt status registers are
323 * not within the same 1K segment as the branch/root enable
324 * registers. */
325 mb();
326
327 /* Wait up to HALT_CHECK_MAX_LOOPS for clock to enable. */
328 for (count = HALT_CHECK_MAX_LOOPS; local_clk_is_halted(id)
329 && count > 0; count--)
330 udelay(1);
331 if (count == 0)
332 pr_warning("%s: clock %d status bit stuck off\n",
333 __func__, id);
334 }
335}
336
337/* Perform any register operations required to enable the clock. */
338void local_clk_disable_reg(unsigned id)
339{
340 struct clk_local *clk = &soc_clk_local_tbl[id];
341 void *reg = clk->cc_reg;
342 uint32_t reg_val;
343
344 /* Disable branch. */
345 reg_val = readl(reg);
346 if (clk->br_en_mask) {
347 reg_val &= ~(clk->br_en_mask);
348 writel(reg_val, reg);
349 }
350
351 /* Wait for clock to disable before continuing. */
352 if (clk->halt_check == DELAY)
353 udelay(HALT_CHECK_DELAY_US);
354 else if (clk->halt_check == ENABLE || clk->halt_check == HALT) {
355 int count;
356 /* Use a memory barrier since some halt status registers are
357 * not within the same 1K segment as the branch/root enable
358 * registers. */
359 mb();
360
361 /* Wait up to HALT_CHECK_MAX_LOOPS for clock to disable. */
362 for (count = HALT_CHECK_MAX_LOOPS; !local_clk_is_halted(id)
363 && count > 0; count--)
364 udelay(1);
365 if (count == 0)
366 pr_warning("%s: clock %d status bit stuck on\n",
367 __func__, id);
368 }
369
370 /* Disable root. */
371 if (clk->root_en_mask) {
372 reg_val &= ~(clk->root_en_mask);
373 writel(reg_val, reg);
374 }
375 /* Disable MN counter, if applicable. */
376 if (clk->type == MND) {
377 reg_val &= ~(clk->current_freq->mnd_en_mask);
378 writel(reg_val, reg);
379 }
380}
381
382/* Enable a clock with no locking, enabling parent clocks as needed. */
383static int local_clk_enable_nolock(unsigned id)
384{
385 struct clk_local *clk = &soc_clk_local_tbl[id];
386 int rc = 0;
387
388 if (clk->type == RESET)
389 return -EPERM;
390
391 if (!clk->count) {
392 rc = local_vote_sys_vdd(clk->current_freq->sys_vdd);
393 if (rc)
394 goto err_vdd;
395 if (clk->parent != C(NONE)) {
396 rc = local_clk_enable_nolock(clk->parent);
397 if (rc)
398 goto err_par;
399 }
400 rc = local_src_enable(clk->current_freq->src);
401 if (rc)
402 goto err_src;
403 local_clk_enable_reg(id);
404 }
405 clk->count++;
406
407 return rc;
408
409err_src:
410 if (clk->parent != C(NONE))
411 rc = local_clk_disable_nolock(clk->parent);
412err_par:
413 local_unvote_sys_vdd(clk->current_freq->sys_vdd);
414err_vdd:
415 return rc;
416}
417
418/* Disable a clock with no locking, disabling unused parents, too. */
419static int local_clk_disable_nolock(unsigned id)
420{
421 struct clk_local *clk = &soc_clk_local_tbl[id];
422 int rc = 0;
423
424 if (clk->count > 0)
425 clk->count--;
426 else {
427 pr_warning("%s: Reference counts are incorrect for clock %d!\n",
428 __func__, id);
429 return rc;
430 }
431
432 if (clk->count == 0) {
433 local_clk_disable_reg(id);
434 rc = local_src_disable(clk->current_freq->src);
435 if (rc)
436 goto err_src;
437 if (clk->parent != C(NONE))
438 rc = local_clk_disable_nolock(clk->parent);
439 if (rc)
440 goto err_par;
441 rc = local_unvote_sys_vdd(clk->current_freq->sys_vdd);
442 if (rc)
443 goto err_vdd;
444 }
445
446 return rc;
447
448err_vdd:
449 if (clk->parent != C(NONE))
450 rc = local_clk_enable_nolock(clk->parent);
451err_par:
452 local_src_enable(clk->current_freq->src);
453err_src:
454 local_clk_enable_reg(id);
455 clk->count++;
456
457 return rc;
458}
459
460/* Enable a clock and any related power rail. */
461int local_clk_enable(unsigned id)
462{
463 int rc = 0;
464 unsigned long flags;
465
466 spin_lock_irqsave(&local_clock_reg_lock, flags);
467 rc = local_clk_enable_nolock(id);
468 if (rc)
469 goto unlock;
470 /*
471 * With remote rail control, the remote processor might modify
472 * the clock control register when the rail is enabled/disabled.
473 * Enable the rail inside the lock to protect against this.
474 */
475 rc = soc_set_pwr_rail(id, 1);
476 if (rc)
477 local_clk_disable_nolock(id);
478unlock:
479 spin_unlock_irqrestore(&local_clock_reg_lock, flags);
480
481 return rc;
482}
483
484/* Disable a clock and any related power rail. */
485void local_clk_disable(unsigned id)
486{
487 unsigned long flags;
488
489 spin_lock_irqsave(&local_clock_reg_lock, flags);
490 soc_set_pwr_rail(id, 0);
491 local_clk_disable_nolock(id);
492 spin_unlock_irqrestore(&local_clock_reg_lock, flags);
493
494 return;
495}
496
497/* Turn off a clock at boot, without checking refcounts or disabling parents. */
498void local_clk_auto_off(unsigned id)
499{
500 unsigned long flags;
501
502 spin_lock_irqsave(&local_clock_reg_lock, flags);
503 local_clk_disable_reg(id);
504 spin_unlock_irqrestore(&local_clock_reg_lock, flags);
505}
506
507/*
508 * Frequency-related functions
509 */
510
511/* Set a clock's frequency. */
512static int _local_clk_set_rate(unsigned id, struct clk_freq_tbl *nf)
513{
514 struct clk_local *clk = &soc_clk_local_tbl[id];
515 struct clk_freq_tbl *cf;
516 const int32_t *chld = clk->children;
517 int i, rc = 0;
518 unsigned long flags;
519
520 spin_lock_irqsave(&local_clock_reg_lock, flags);
521
522 /* Check if frequency is actually changed. */
523 cf = clk->current_freq;
524 if (nf == cf)
525 goto release_lock;
526
527 /* Disable branch if clock isn't dual-banked with a glitch-free MUX. */
528 if (clk->banked_mnd_masks == NULL) {
529 /* Disable all branches to prevent glitches. */
530 for (i = 0; chld && chld[i] != C(NONE); i++) {
531 struct clk_local *ch = &soc_clk_local_tbl[chld[i]];
532 /* Don't bother turning off if it is already off.
533 * Checking ch->count is cheaper (cache) than reading
534 * and writing to a register (uncached/unbuffered). */
535 if (ch->count)
536 local_clk_disable_reg(chld[i]);
537 }
538 if (clk->count)
539 local_clk_disable_reg(id);
540 }
541
542 if (clk->count) {
543 /* Vote for voltage and source for new freq. */
544 rc = local_vote_sys_vdd(nf->sys_vdd);
545 if (rc)
546 goto sys_vdd_vote_failed;
547 rc = local_src_enable(nf->src);
548 if (rc) {
549 local_unvote_sys_vdd(nf->sys_vdd);
550 goto src_enable_failed;
551 }
552 }
553
554 /* Perform clock-specific frequency switch operations. */
555 BUG_ON(!clk->set_rate);
556 clk->set_rate(clk, nf);
557
558 /* Release requirements of the old freq. */
559 if (clk->count) {
560 local_src_disable(cf->src);
561 local_unvote_sys_vdd(cf->sys_vdd);
562 }
563
564 /* Current freq must be updated before local_clk_enable_reg()
565 * is called to make sure the MNCNTR_EN bit is set correctly. */
566 clk->current_freq = nf;
567
568src_enable_failed:
569sys_vdd_vote_failed:
570 /* Enable any clocks that were disabled. */
571 if (clk->banked_mnd_masks == NULL) {
572 if (clk->count)
573 local_clk_enable_reg(id);
574 /* Enable only branches that were ON before. */
575 for (i = 0; chld && chld[i] != C(NONE); i++) {
576 struct clk_local *ch = &soc_clk_local_tbl[chld[i]];
577 if (ch->count)
578 local_clk_enable_reg(chld[i]);
579 }
580 }
581
582release_lock:
583 spin_unlock_irqrestore(&local_clock_reg_lock, flags);
584 return rc;
585}
586
587/* Set a clock to an exact rate. */
588int local_clk_set_rate(unsigned id, unsigned rate)
589{
590 struct clk_local *clk = &soc_clk_local_tbl[id];
591 struct clk_freq_tbl *nf;
592
593 if (clk->type == NORATE || clk->type == RESET)
594 return -EPERM;
595
596 for (nf = clk->freq_tbl; nf->freq_hz != FREQ_END
597 && nf->freq_hz != rate; nf++)
598 ;
599
600 if (nf->freq_hz == FREQ_END)
601 return -EINVAL;
602
603 return _local_clk_set_rate(id, nf);
604}
605
606/* Set a clock to a rate greater than some minimum. */
607int local_clk_set_min_rate(unsigned id, unsigned rate)
608{
609 struct clk_local *clk = &soc_clk_local_tbl[id];
610 struct clk_freq_tbl *nf;
611
612 if (clk->type == NORATE || clk->type == RESET)
613 return -EPERM;
614
615 for (nf = clk->freq_tbl; nf->freq_hz != FREQ_END
616 && nf->freq_hz < rate; nf++)
617 ;
618
619 if (nf->freq_hz == FREQ_END)
620 return -EINVAL;
621
622 return _local_clk_set_rate(id, nf);
623}
624
625/* Set a clock to a maximum rate. */
626int local_clk_set_max_rate(unsigned id, unsigned rate)
627{
628 return -EPERM;
629}
630
631/* Get the currently-set rate of a clock in Hz. */
632unsigned local_clk_get_rate(unsigned id)
633{
634 struct clk_local *clk = &soc_clk_local_tbl[id];
635 unsigned long flags;
636 unsigned ret = 0;
637
638 if (clk->type == NORATE || clk->type == RESET)
639 return 0;
640
641 spin_lock_irqsave(&local_clock_reg_lock, flags);
642 ret = clk->current_freq->freq_hz;
643 spin_unlock_irqrestore(&local_clock_reg_lock, flags);
644
645 /* Return 0 if the rate has never been set. Might not be correct,
646 * but it's good enough. */
647 if (ret == FREQ_END)
648 ret = 0;
649
650 return ret;
651}
652
653/* Check if a clock is currently enabled. */
654unsigned local_clk_is_enabled(unsigned id)
655{
656 struct clk_local *clk = &soc_clk_local_tbl[id];
657
658 if (clk->type == RESET)
659 return -EPERM;
660
661 return !!(soc_clk_local_tbl[id].count);
662}
663
664/* Return a supported rate that's at least the specified rate. */
665long local_clk_round_rate(unsigned id, unsigned rate)
666{
667 struct clk_local *clk = &soc_clk_local_tbl[id];
668 struct clk_freq_tbl *f;
669
670 if (clk->type == NORATE || clk->type == RESET)
671 return -EINVAL;
672
673 for (f = clk->freq_tbl; f->freq_hz != FREQ_END; f++)
674 if (f->freq_hz >= rate)
675 return f->freq_hz;
676
677 return -EPERM;
678}
679
680/* Return the nth supported frequency for a given clock. */
681int local_clk_list_rate(unsigned id, unsigned n)
682{
683 struct clk_local *clk = &soc_clk_local_tbl[id];
684
685 if (!clk->freq_tbl || clk->freq_tbl->freq_hz == FREQ_END)
686 return -ENXIO;
687
688 return (clk->freq_tbl + n)->freq_hz;
689}
690