PageRenderTime 39ms CodeModel.GetById 16ms app.highlight 19ms RepoModel.GetById 0ms app.codeStats 0ms

/arch/arm/mach-fsm/clock-local.c

https://bitbucket.org/sammyz/iscream_thunderc-2.6.35-rebase
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