1/*
2 *  linux/arch/arm/mach-omap2/clock.c
3 *
4 *  Copyright (C) 2005 Texas Instruments Inc.
5 *  Richard Woodruff <r-woodruff2@ti.com>
6 *  Created for OMAP2.
7 *
8 *  Cleaned up and modified to use omap shared clock framework by
9 *  Tony Lindgren <tony@atomide.com>
10 *
11 *  Based on omap1 clock.c, Copyright (C) 2004 - 2005 Nokia corporation
12 *  Written by Tuukka Tikkanen <tuukka.tikkanen@elektrobit.com>
13 *
14 * This program is free software; you can redistribute it and/or modify
15 * it under the terms of the GNU General Public License version 2 as
16 * published by the Free Software Foundation.
17 */
18#include <linux/module.h>
19#include <linux/kernel.h>
20#include <linux/device.h>
21#include <linux/list.h>
22#include <linux/errno.h>
23#include <linux/delay.h>
24#include <linux/clk.h>
25
26#include <asm/io.h>
27
28#include <asm/arch/clock.h>
29#include <asm/arch/sram.h>
30#include <asm/div64.h>
31
32#include "prcm-regs.h"
33#include "memory.h"
34#include "clock.h"
35
36#undef DEBUG
37
38//#define DOWN_VARIABLE_DPLL 1			/* Experimental */
39
40static struct prcm_config *curr_prcm_set;
41static u32 curr_perf_level = PRCM_FULL_SPEED;
42static struct clk *vclk;
43static struct clk *sclk;
44
45/*-------------------------------------------------------------------------
46 * Omap2 specific clock functions
47 *-------------------------------------------------------------------------*/
48
49/* Recalculate SYST_CLK */
50static void omap2_sys_clk_recalc(struct clk * clk)
51{
52	u32 div = PRCM_CLKSRC_CTRL;
53	div &= (1 << 7) | (1 << 6);	/* Test if ext clk divided by 1 or 2 */
54	div >>= clk->rate_offset;
55	clk->rate = (clk->parent->rate / div);
56	propagate_rate(clk);
57}
58
59static u32 omap2_get_dpll_rate(struct clk * tclk)
60{
61	long long dpll_clk;
62	int dpll_mult, dpll_div, amult;
63
64	dpll_mult = (CM_CLKSEL1_PLL >> 12) & 0x03ff;	/* 10 bits */
65	dpll_div = (CM_CLKSEL1_PLL >> 8) & 0x0f;	/* 4 bits */
66	dpll_clk = (long long)tclk->parent->rate * dpll_mult;
67	do_div(dpll_clk, dpll_div + 1);
68	amult = CM_CLKSEL2_PLL & 0x3;
69	dpll_clk *= amult;
70
71	return dpll_clk;
72}
73
74static void omap2_followparent_recalc(struct clk *clk)
75{
76	followparent_recalc(clk);
77}
78
79static void omap2_propagate_rate(struct clk * clk)
80{
81	if (!(clk->flags & RATE_FIXED))
82		clk->rate = clk->parent->rate;
83
84	propagate_rate(clk);
85}
86
87static void omap2_set_osc_ck(int enable)
88{
89	if (enable)
90		PRCM_CLKSRC_CTRL &= ~(0x3 << 3);
91	else
92		PRCM_CLKSRC_CTRL |= 0x3 << 3;
93}
94
95/* Enable an APLL if off */
96static void omap2_clk_fixed_enable(struct clk *clk)
97{
98	u32 cval, i=0;
99
100	if (clk->enable_bit == 0xff)			/* Parent will do it */
101		return;
102
103	cval = CM_CLKEN_PLL;
104
105	if ((cval & (0x3 << clk->enable_bit)) == (0x3 << clk->enable_bit))
106		return;
107
108	cval &= ~(0x3 << clk->enable_bit);
109	cval |= (0x3 << clk->enable_bit);
110	CM_CLKEN_PLL = cval;
111
112	if (clk == &apll96_ck)
113		cval = (1 << 8);
114	else if (clk == &apll54_ck)
115		cval = (1 << 6);
116
117	while (!(CM_IDLEST_CKGEN & cval)) {		/* Wait for lock */
118		++i;
119		udelay(1);
120		if (i == 100000) {
121			printk(KERN_ERR "Clock %s didn't lock\n", clk->name);
122			break;
123		}
124	}
125}
126
127static void omap2_clk_wait_ready(struct clk *clk)
128{
129	unsigned long reg, other_reg, st_reg;
130	u32 bit;
131	int i;
132
133	reg = (unsigned long) clk->enable_reg;
134	if (reg == (unsigned long) &CM_FCLKEN1_CORE ||
135	    reg == (unsigned long) &CM_FCLKEN2_CORE)
136		other_reg = (reg & ~0xf0) | 0x10;
137	else if (reg == (unsigned long) &CM_ICLKEN1_CORE ||
138		 reg == (unsigned long) &CM_ICLKEN2_CORE)
139		other_reg = (reg & ~0xf0) | 0x00;
140	else
141		return;
142
143	/* No check for DSS or cam clocks */
144	if ((reg & 0x0f) == 0) {
145		if (clk->enable_bit <= 1 || clk->enable_bit == 31)
146			return;
147	}
148
149	/* Check if both functional and interface clocks
150	 * are running. */
151	bit = 1 << clk->enable_bit;
152	if (!(__raw_readl(other_reg) & bit))
153		return;
154	st_reg = (other_reg & ~0xf0) | 0x20;
155	i = 0;
156	while (!(__raw_readl(st_reg) & bit)) {
157		i++;
158		if (i == 100000) {
159			printk(KERN_ERR "Timeout enabling clock %s\n", clk->name);
160			break;
161		}
162	}
163	if (i)
164		pr_debug("Clock %s stable after %d loops\n", clk->name, i);
165}
166
167/* Enables clock without considering parent dependencies or use count
168 * REVISIT: Maybe change this to use clk->enable like on omap1?
169 */
170static int _omap2_clk_enable(struct clk * clk)
171{
172	u32 regval32;
173
174	if (clk->flags & ALWAYS_ENABLED)
175		return 0;
176
177	if (unlikely(clk == &osc_ck)) {
178		omap2_set_osc_ck(1);
179		return 0;
180	}
181
182	if (unlikely(clk->enable_reg == 0)) {
183		printk(KERN_ERR "clock.c: Enable for %s without enable code\n",
184		       clk->name);
185		return 0;
186	}
187
188	if (clk->enable_reg == (void __iomem *)&CM_CLKEN_PLL) {
189		omap2_clk_fixed_enable(clk);
190		return 0;
191	}
192
193	regval32 = __raw_readl(clk->enable_reg);
194	regval32 |= (1 << clk->enable_bit);
195	__raw_writel(regval32, clk->enable_reg);
196	wmb();
197
198	omap2_clk_wait_ready(clk);
199
200	return 0;
201}
202
203/* Stop APLL */
204static void omap2_clk_fixed_disable(struct clk *clk)
205{
206	u32 cval;
207
208	if(clk->enable_bit == 0xff)		/* let parent off do it */
209		return;
210
211	cval = CM_CLKEN_PLL;
212	cval &= ~(0x3 << clk->enable_bit);
213	CM_CLKEN_PLL = cval;
214}
215
216/* Disables clock without considering parent dependencies or use count */
217static void _omap2_clk_disable(struct clk *clk)
218{
219	u32 regval32;
220
221	if (unlikely(clk == &osc_ck)) {
222		omap2_set_osc_ck(0);
223		return;
224	}
225
226	if (clk->enable_reg == 0)
227		return;
228
229	if (clk->enable_reg == (void __iomem *)&CM_CLKEN_PLL) {
230		omap2_clk_fixed_disable(clk);
231		return;
232	}
233
234	regval32 = __raw_readl(clk->enable_reg);
235	regval32 &= ~(1 << clk->enable_bit);
236	__raw_writel(regval32, clk->enable_reg);
237	wmb();
238}
239
240static int omap2_clk_enable(struct clk *clk)
241{
242	int ret = 0;
243
244	if (clk->usecount++ == 0) {
245		if (likely((u32)clk->parent))
246			ret = omap2_clk_enable(clk->parent);
247
248		if (unlikely(ret != 0)) {
249			clk->usecount--;
250			return ret;
251		}
252
253		ret = _omap2_clk_enable(clk);
254
255		if (unlikely(ret != 0) && clk->parent) {
256			omap2_clk_disable(clk->parent);
257			clk->usecount--;
258		}
259	}
260
261	return ret;
262}
263
264static void omap2_clk_disable(struct clk *clk)
265{
266	if (clk->usecount > 0 && !(--clk->usecount)) {
267		_omap2_clk_disable(clk);
268		if (likely((u32)clk->parent))
269			omap2_clk_disable(clk->parent);
270	}
271}
272
273/*
274 * Uses the current prcm set to tell if a rate is valid.
275 * You can go slower, but not faster within a given rate set.
276 */
277static u32 omap2_dpll_round_rate(unsigned long target_rate)
278{
279	u32 high, low;
280
281	if ((CM_CLKSEL2_PLL & 0x3) == 1) {	/* DPLL clockout */
282		high = curr_prcm_set->dpll_speed * 2;
283		low = curr_prcm_set->dpll_speed;
284	} else {				/* DPLL clockout x 2 */
285		high = curr_prcm_set->dpll_speed;
286		low = curr_prcm_set->dpll_speed / 2;
287	}
288
289#ifdef DOWN_VARIABLE_DPLL
290	if (target_rate > high)
291		return high;
292	else
293		return target_rate;
294#else
295	if (target_rate > low)
296		return high;
297	else
298		return low;
299#endif
300
301}
302
303/*
304 * Used for clocks that are part of CLKSEL_xyz governed clocks.
305 * REVISIT: Maybe change to use clk->enable() functions like on omap1?
306 */
307static void omap2_clksel_recalc(struct clk * clk)
308{
309	u32 fixed = 0, div = 0;
310
311	if (clk == &dpll_ck) {
312		clk->rate = omap2_get_dpll_rate(clk);
313		fixed = 1;
314		div = 0;
315	}
316
317	if (clk == &iva1_mpu_int_ifck) {
318		div = 2;
319		fixed = 1;
320	}
321
322	if ((clk == &dss1_fck) && ((CM_CLKSEL1_CORE & (0x1f << 8)) == 0)) {
323		clk->rate = sys_ck.rate;
324		return;
325	}
326
327	if (!fixed) {
328		div = omap2_clksel_get_divisor(clk);
329		if (div == 0)
330			return;
331	}
332
333	if (div != 0) {
334		if (unlikely(clk->rate == clk->parent->rate / div))
335			return;
336		clk->rate = clk->parent->rate / div;
337	}
338
339	if (unlikely(clk->flags & RATE_PROPAGATES))
340		propagate_rate(clk);
341}
342
343/*
344 * Finds best divider value in an array based on the source and target
345 * rates. The divider array must be sorted with smallest divider first.
346 */
347static inline u32 omap2_divider_from_table(u32 size, u32 *div_array,
348					   u32 src_rate, u32 tgt_rate)
349{
350	int i, test_rate;
351
352	if (div_array == NULL)
353		return ~1;
354
355	for (i=0; i < size; i++) {
356		test_rate = src_rate / *div_array;
357		if (test_rate <= tgt_rate)
358			return *div_array;
359		++div_array;
360	}
361
362	return ~0;	/* No acceptable divider */
363}
364
365/*
366 * Find divisor for the given clock and target rate.
367 *
368 * Note that this will not work for clocks which are part of CONFIG_PARTICIPANT,
369 * they are only settable as part of virtual_prcm set.
370 */
371static u32 omap2_clksel_round_rate(struct clk *tclk, u32 target_rate,
372	u32 *new_div)
373{
374	u32 gfx_div[] = {2, 3, 4};
375	u32 sysclkout_div[] = {1, 2, 4, 8, 16};
376	u32 dss1_div[] = {1, 2, 3, 4, 5, 6, 8, 9, 12, 16};
377	u32 vylnq_div[] = {1, 2, 3, 4, 6, 8, 9, 12, 16, 18};
378	u32 best_div = ~0, asize = 0;
379	u32 *div_array = NULL;
380
381	switch (tclk->flags & SRC_RATE_SEL_MASK) {
382	case CM_GFX_SEL1:
383		asize = 3;
384		div_array = gfx_div;
385		break;
386	case CM_PLL_SEL1:
387		return omap2_dpll_round_rate(target_rate);
388	case CM_SYSCLKOUT_SEL1:
389		asize = 5;
390		div_array = sysclkout_div;
391		break;
392	case CM_CORE_SEL1:
393		if(tclk == &dss1_fck){
394			if(tclk->parent == &core_ck){
395				asize = 10;
396				div_array = dss1_div;
397			} else {
398				*new_div = 0; /* fixed clk */
399				return(tclk->parent->rate);
400			}
401		} else if((tclk == &vlynq_fck) && cpu_is_omap2420()){
402			if(tclk->parent == &core_ck){
403				asize = 10;
404				div_array = vylnq_div;
405			} else {
406				*new_div = 0; /* fixed clk */
407				return(tclk->parent->rate);
408			}
409		}
410		break;
411	}
412
413	best_div = omap2_divider_from_table(asize, div_array,
414	 tclk->parent->rate, target_rate);
415	if (best_div == ~0){
416		*new_div = 1;
417		return best_div; /* signal error */
418	}
419
420	*new_div = best_div;
421	return (tclk->parent->rate / best_div);
422}
423
424/* Given a clock and a rate apply a clock specific rounding function */
425static long omap2_clk_round_rate(struct clk *clk, unsigned long rate)
426{
427	u32 new_div = 0;
428	int valid_rate;
429
430	if (clk->flags & RATE_FIXED)
431		return clk->rate;
432
433	if (clk->flags & RATE_CKCTL) {
434		valid_rate = omap2_clksel_round_rate(clk, rate, &new_div);
435		return valid_rate;
436	}
437
438	if (clk->round_rate != 0)
439		return clk->round_rate(clk, rate);
440
441	return clk->rate;
442}
443
444/*
445 * Check the DLL lock state, and return tue if running in unlock mode.
446 * This is needed to compensate for the shifted DLL value in unlock mode.
447 */
448static u32 omap2_dll_force_needed(void)
449{
450	u32 dll_state = SDRC_DLLA_CTRL;		/* dlla and dllb are a set */
451
452	if ((dll_state & (1 << 2)) == (1 << 2))
453		return 1;
454	else
455		return 0;
456}
457
458static u32 omap2_reprogram_sdrc(u32 level, u32 force)
459{
460	u32 slow_dll_ctrl, fast_dll_ctrl, m_type;
461	u32 prev = curr_perf_level, flags;
462
463	if ((curr_perf_level == level) && !force)
464		return prev;
465
466	m_type = omap2_memory_get_type();
467	slow_dll_ctrl = omap2_memory_get_slow_dll_ctrl();
468	fast_dll_ctrl = omap2_memory_get_fast_dll_ctrl();
469
470	if (level == PRCM_HALF_SPEED) {
471		local_irq_save(flags);
472		PRCM_VOLTSETUP = 0xffff;
473		omap2_sram_reprogram_sdrc(PRCM_HALF_SPEED,
474					  slow_dll_ctrl, m_type);
475		curr_perf_level = PRCM_HALF_SPEED;
476		local_irq_restore(flags);
477	}
478	if (level == PRCM_FULL_SPEED) {
479		local_irq_save(flags);
480		PRCM_VOLTSETUP = 0xffff;
481		omap2_sram_reprogram_sdrc(PRCM_FULL_SPEED,
482					  fast_dll_ctrl, m_type);
483		curr_perf_level = PRCM_FULL_SPEED;
484		local_irq_restore(flags);
485	}
486
487	return prev;
488}
489
490static int omap2_reprogram_dpll(struct clk * clk, unsigned long rate)
491{
492	u32 flags, cur_rate, low, mult, div, valid_rate, done_rate;
493	u32 bypass = 0;
494	struct prcm_config tmpset;
495	int ret = -EINVAL;
496
497	local_irq_save(flags);
498	cur_rate = omap2_get_dpll_rate(&dpll_ck);
499	mult = CM_CLKSEL2_PLL & 0x3;
500
501	if ((rate == (cur_rate / 2)) && (mult == 2)) {
502		omap2_reprogram_sdrc(PRCM_HALF_SPEED, 1);
503	} else if ((rate == (cur_rate * 2)) && (mult == 1)) {
504		omap2_reprogram_sdrc(PRCM_FULL_SPEED, 1);
505	} else if (rate != cur_rate) {
506		valid_rate = omap2_dpll_round_rate(rate);
507		if (valid_rate != rate)
508			goto dpll_exit;
509
510		if ((CM_CLKSEL2_PLL & 0x3) == 1)
511			low = curr_prcm_set->dpll_speed;
512		else
513			low = curr_prcm_set->dpll_speed / 2;
514
515		tmpset.cm_clksel1_pll = CM_CLKSEL1_PLL;
516		tmpset.cm_clksel1_pll &= ~(0x3FFF << 8);
517		div = ((curr_prcm_set->xtal_speed / 1000000) - 1);
518		tmpset.cm_clksel2_pll = CM_CLKSEL2_PLL;
519		tmpset.cm_clksel2_pll &= ~0x3;
520		if (rate > low) {
521			tmpset.cm_clksel2_pll |= 0x2;
522			mult = ((rate / 2) / 1000000);
523			done_rate = PRCM_FULL_SPEED;
524		} else {
525			tmpset.cm_clksel2_pll |= 0x1;
526			mult = (rate / 1000000);
527			done_rate = PRCM_HALF_SPEED;
528		}
529		tmpset.cm_clksel1_pll |= ((div << 8) | (mult << 12));
530
531		/* Worst case */
532		tmpset.base_sdrc_rfr = V24XX_SDRC_RFR_CTRL_BYPASS;
533
534		if (rate == curr_prcm_set->xtal_speed)	/* If asking for 1-1 */
535			bypass = 1;
536
537		omap2_reprogram_sdrc(PRCM_FULL_SPEED, 1); /* For init_mem */
538
539		/* Force dll lock mode */
540		omap2_set_prcm(tmpset.cm_clksel1_pll, tmpset.base_sdrc_rfr,
541			       bypass);
542
543		/* Errata: ret dll entry state */
544		omap2_init_memory_params(omap2_dll_force_needed());
545		omap2_reprogram_sdrc(done_rate, 0);
546	}
547	omap2_clksel_recalc(&dpll_ck);
548	ret = 0;
549
550dpll_exit:
551	local_irq_restore(flags);
552	return(ret);
553}
554
555/* Just return the MPU speed */
556static void omap2_mpu_recalc(struct clk * clk)
557{
558	clk->rate = curr_prcm_set->mpu_speed;
559}
560
561/*
562 * Look for a rate equal or less than the target rate given a configuration set.
563 *
564 * What's not entirely clear is "which" field represents the key field.
565 * Some might argue L3-DDR, others ARM, others IVA. This code is simple and
566 * just uses the ARM rates.
567 */
568static long omap2_round_to_table_rate(struct clk * clk, unsigned long rate)
569{
570	struct prcm_config * ptr;
571	long highest_rate;
572
573	if (clk != &virt_prcm_set)
574		return -EINVAL;
575
576	highest_rate = -EINVAL;
577
578	for (ptr = rate_table; ptr->mpu_speed; ptr++) {
579		if (ptr->xtal_speed != sys_ck.rate)
580			continue;
581
582		highest_rate = ptr->mpu_speed;
583
584		/* Can check only after xtal frequency check */
585		if (ptr->mpu_speed <= rate)
586			break;
587	}
588	return highest_rate;
589}
590
591/*
592 * omap2_convert_field_to_div() - turn field value into integer divider
593 */
594static u32 omap2_clksel_to_divisor(u32 div_sel, u32 field_val)
595{
596	u32 i;
597	u32 clkout_array[] = {1, 2, 4, 8, 16};
598
599	if ((div_sel & SRC_RATE_SEL_MASK) == CM_SYSCLKOUT_SEL1) {
600		for (i = 0; i < 5; i++) {
601			if (field_val == i)
602				return clkout_array[i];
603		}
604		return ~0;
605	} else
606		return field_val;
607}
608
609/*
610 * Returns the CLKSEL divider register value
611 * REVISIT: This should be cleaned up to work nicely with void __iomem *
612 */
613static u32 omap2_get_clksel(u32 *div_sel, u32 *field_mask,
614			    struct clk *clk)
615{
616	int ret = ~0;
617	u32 reg_val, div_off;
618	u32 div_addr = 0;
619	u32 mask = ~0;
620
621	div_off = clk->rate_offset;
622
623	switch ((*div_sel & SRC_RATE_SEL_MASK)) {
624	case CM_MPU_SEL1:
625		div_addr = (u32)&CM_CLKSEL_MPU;
626		mask = 0x1f;
627		break;
628	case CM_DSP_SEL1:
629		div_addr = (u32)&CM_CLKSEL_DSP;
630		if (cpu_is_omap2420()) {
631			if ((div_off == 0) || (div_off == 8))
632				mask = 0x1f;
633			else if (div_off == 5)
634				mask = 0x3;
635		} else if (cpu_is_omap2430()) {
636			if (div_off == 0)
637				mask = 0x1f;
638			else if (div_off == 5)
639				mask = 0x3;
640		}
641		break;
642	case CM_GFX_SEL1:
643		div_addr = (u32)&CM_CLKSEL_GFX;
644		if (div_off == 0)
645			mask = 0x7;
646		break;
647	case CM_MODEM_SEL1:
648		div_addr = (u32)&CM_CLKSEL_MDM;
649		if (div_off == 0)
650			mask = 0xf;
651		break;
652	case CM_SYSCLKOUT_SEL1:
653		div_addr = (u32)&PRCM_CLKOUT_CTRL;
654		if ((div_off == 3) || (div_off = 11))
655			mask= 0x3;
656		break;
657	case CM_CORE_SEL1:
658		div_addr = (u32)&CM_CLKSEL1_CORE;
659		switch (div_off) {
660		case 0:					/* l3 */
661		case 8:					/* dss1 */
662		case 15:				/* vylnc-2420 */
663		case 20:				/* ssi */
664			mask = 0x1f; break;
665		case 5:					/* l4 */
666			mask = 0x3; break;
667		case 13:				/* dss2 */
668			mask = 0x1; break;
669		case 25:				/* usb */
670			mask = 0x7; break;
671		}
672	}
673
674	*field_mask = mask;
675
676	if (unlikely(mask == ~0))
677		div_addr = 0;
678
679	*div_sel = div_addr;
680
681	if (unlikely(div_addr == 0))
682		return ret;
683
684	/* Isolate field */
685	reg_val = __raw_readl((void __iomem *)div_addr) & (mask << div_off);
686
687	/* Normalize back to divider value */
688	reg_val >>= div_off;
689
690	return reg_val;
691}
692
693/*
694 * Return divider to be applied to parent clock.
695 * Return 0 on error.
696 */
697static u32 omap2_clksel_get_divisor(struct clk *clk)
698{
699	int ret = 0;
700	u32 div, div_sel, div_off, field_mask, field_val;
701
702	/* isolate control register */
703	div_sel = (SRC_RATE_SEL_MASK & clk->flags);
704
705	div_off = clk->rate_offset;
706	field_val = omap2_get_clksel(&div_sel, &field_mask, clk);
707	if (div_sel == 0)
708		return ret;
709
710	div_sel = (SRC_RATE_SEL_MASK & clk->flags);
711	div = omap2_clksel_to_divisor(div_sel, field_val);
712
713	return div;
714}
715
716/* Set the clock rate for a clock source */
717static int omap2_clk_set_rate(struct clk *clk, unsigned long rate)
718
719{
720	int ret = -EINVAL;
721	void __iomem * reg;
722	u32 div_sel, div_off, field_mask, field_val, reg_val, validrate;
723	u32 new_div = 0;
724
725	if (!(clk->flags & CONFIG_PARTICIPANT) && (clk->flags & RATE_CKCTL)) {
726		if (clk == &dpll_ck)
727			return omap2_reprogram_dpll(clk, rate);
728
729		/* Isolate control register */
730		div_sel = (SRC_RATE_SEL_MASK & clk->flags);
731		div_off = clk->rate_offset;
732
733		validrate = omap2_clksel_round_rate(clk, rate, &new_div);
734		if (validrate != rate)
735			return(ret);
736
737		field_val = omap2_get_clksel(&div_sel, &field_mask, clk);
738		if (div_sel == 0)
739			return ret;
740
741		if (clk->flags & CM_SYSCLKOUT_SEL1) {
742			switch (new_div) {
743			case 16:
744				field_val = 4;
745				break;
746			case 8:
747				field_val = 3;
748				break;
749			case 4:
750				field_val = 2;
751				break;
752			case 2:
753				field_val = 1;
754				break;
755			case 1:
756				field_val = 0;
757				break;
758			}
759		} else
760			field_val = new_div;
761
762		reg = (void __iomem *)div_sel;
763
764		reg_val = __raw_readl(reg);
765		reg_val &= ~(field_mask << div_off);
766		reg_val |= (field_val << div_off);
767		__raw_writel(reg_val, reg);
768		wmb();
769		clk->rate = clk->parent->rate / field_val;
770
771		if (clk->flags & DELAYED_APP) {
772			__raw_writel(0x1, (void __iomem *)&PRCM_CLKCFG_CTRL);
773			wmb();
774		}
775		ret = 0;
776	} else if (clk->set_rate != 0)
777		ret = clk->set_rate(clk, rate);
778
779	if (unlikely(ret == 0 && (clk->flags & RATE_PROPAGATES)))
780		propagate_rate(clk);
781
782	return ret;
783}
784
785/* Converts encoded control register address into a full address */
786static u32 omap2_get_src_field(u32 *type_to_addr, u32 reg_offset,
787			       struct clk *src_clk, u32 *field_mask)
788{
789	u32 val = ~0, src_reg_addr = 0, mask = 0;
790
791	/* Find target control register.*/
792	switch ((*type_to_addr & SRC_RATE_SEL_MASK)) {
793	case CM_CORE_SEL1:
794		src_reg_addr = (u32)&CM_CLKSEL1_CORE;
795		if (reg_offset == 13) {			/* DSS2_fclk */
796			mask = 0x1;
797			if (src_clk == &sys_ck)
798				val = 0;
799			if (src_clk == &func_48m_ck)
800				val = 1;
801		} else if (reg_offset == 8) {		/* DSS1_fclk */
802			mask = 0x1f;
803			if (src_clk == &sys_ck)
804				val = 0;
805			else if (src_clk == &core_ck)	/* divided clock */
806				val = 0x10;		/* rate needs fixing */
807		} else if ((reg_offset == 15) && cpu_is_omap2420()){ /*vlnyq*/
808			mask = 0x1F;
809			if(src_clk == &func_96m_ck)
810				val = 0;
811			else if (src_clk == &core_ck)
812				val = 0x10;
813		}
814		break;
815	case CM_CORE_SEL2:
816		src_reg_addr = (u32)&CM_CLKSEL2_CORE;
817		mask = 0x3;
818		if (src_clk == &func_32k_ck)
819			val = 0x0;
820		if (src_clk == &sys_ck)
821			val = 0x1;
822		if (src_clk == &alt_ck)
823			val = 0x2;
824		break;
825	case CM_WKUP_SEL1:
826		src_reg_addr = (u32)&CM_CLKSEL_WKUP;
827		mask = 0x3;
828		if (src_clk == &func_32k_ck)
829			val = 0x0;
830		if (src_clk == &sys_ck)
831			val = 0x1;
832		if (src_clk == &alt_ck)
833			val = 0x2;
834		break;
835	case CM_PLL_SEL1:
836		src_reg_addr = (u32)&CM_CLKSEL1_PLL;
837		mask = 0x1;
838		if (reg_offset == 0x3) {
839			if (src_clk == &apll96_ck)
840				val = 0;
841			if (src_clk == &alt_ck)
842				val = 1;
843		}
844		else if (reg_offset == 0x5) {
845			if (src_clk == &apll54_ck)
846				val = 0;
847			if (src_clk == &alt_ck)
848				val = 1;
849		}
850		break;
851	case CM_PLL_SEL2:
852		src_reg_addr = (u32)&CM_CLKSEL2_PLL;
853		mask = 0x3;
854		if (src_clk == &func_32k_ck)
855			val = 0x0;
856		if (src_clk == &dpll_ck)
857			val = 0x2;
858		break;
859	case CM_SYSCLKOUT_SEL1:
860		src_reg_addr = (u32)&PRCM_CLKOUT_CTRL;
861		mask = 0x3;
862		if (src_clk == &dpll_ck)
863			val = 0;
864		if (src_clk == &sys_ck)
865			val = 1;
866		if (src_clk == &func_96m_ck)
867			val = 2;
868		if (src_clk == &func_54m_ck)
869			val = 3;
870		break;
871	}
872
873	if (val == ~0)			/* Catch errors in offset */
874		*type_to_addr = 0;
875	else
876		*type_to_addr = src_reg_addr;
877	*field_mask = mask;
878
879	return val;
880}
881
882static int omap2_clk_set_parent(struct clk *clk, struct clk *new_parent)
883{
884	void __iomem * reg;
885	u32 src_sel, src_off, field_val, field_mask, reg_val, rate;
886	int ret = -EINVAL;
887
888	if (unlikely(clk->flags & CONFIG_PARTICIPANT))
889		return ret;
890
891	if (clk->flags & SRC_SEL_MASK) {	/* On-chip SEL collection */
892		src_sel = (SRC_RATE_SEL_MASK & clk->flags);
893		src_off = clk->src_offset;
894
895		if (src_sel == 0)
896			goto set_parent_error;
897
898		field_val = omap2_get_src_field(&src_sel, src_off, new_parent,
899						&field_mask);
900
901		reg = (void __iomem *)src_sel;
902
903		if (clk->usecount > 0)
904			_omap2_clk_disable(clk);
905
906		/* Set new source value (previous dividers if any in effect) */
907		reg_val = __raw_readl(reg) & ~(field_mask << src_off);
908		reg_val |= (field_val << src_off);
909		__raw_writel(reg_val, reg);
910		wmb();
911
912		if (clk->flags & DELAYED_APP) {
913			__raw_writel(0x1, (void __iomem *)&PRCM_CLKCFG_CTRL);
914			wmb();
915		}
916		if (clk->usecount > 0)
917			_omap2_clk_enable(clk);
918
919		clk->parent = new_parent;
920
921		/* SRC_RATE_SEL_MASK clocks follow their parents rates.*/
922		if ((new_parent == &core_ck) && (clk == &dss1_fck))
923			clk->rate = new_parent->rate / 0x10;
924		else
925			clk->rate = new_parent->rate;
926
927		if (unlikely(clk->flags & RATE_PROPAGATES))
928			propagate_rate(clk);
929
930		return 0;
931	} else {
932		clk->parent = new_parent;
933		rate = new_parent->rate;
934		omap2_clk_set_rate(clk, rate);
935		ret = 0;
936	}
937
938 set_parent_error:
939	return ret;
940}
941
942/* Sets basic clocks based on the specified rate */
943static int omap2_select_table_rate(struct clk * clk, unsigned long rate)
944{
945	u32 flags, cur_rate, done_rate, bypass = 0;
946	u8 cpu_mask = 0;
947	struct prcm_config *prcm;
948	unsigned long found_speed = 0;
949
950	if (clk != &virt_prcm_set)
951		return -EINVAL;
952
953	if (cpu_is_omap2420())
954		cpu_mask = RATE_IN_242X;
955	else if (cpu_is_omap2430())
956		cpu_mask = RATE_IN_243X;
957
958	for (prcm = rate_table; prcm->mpu_speed; prcm++) {
959		if (!(prcm->flags & cpu_mask))
960			continue;
961
962		if (prcm->xtal_speed != sys_ck.rate)
963			continue;
964
965		if (prcm->mpu_speed <= rate) {
966			found_speed = prcm->mpu_speed;
967			break;
968		}
969	}
970
971	if (!found_speed) {
972		printk(KERN_INFO "Could not set MPU rate to %luMHz\n",
973	 rate / 1000000);
974		return -EINVAL;
975	}
976
977	curr_prcm_set = prcm;
978	cur_rate = omap2_get_dpll_rate(&dpll_ck);
979
980	if (prcm->dpll_speed == cur_rate / 2) {
981		omap2_reprogram_sdrc(PRCM_HALF_SPEED, 1);
982	} else if (prcm->dpll_speed == cur_rate * 2) {
983		omap2_reprogram_sdrc(PRCM_FULL_SPEED, 1);
984	} else if (prcm->dpll_speed != cur_rate) {
985		local_irq_save(flags);
986
987		if (prcm->dpll_speed == prcm->xtal_speed)
988			bypass = 1;
989
990		if ((prcm->cm_clksel2_pll & 0x3) == 2)
991			done_rate = PRCM_FULL_SPEED;
992		else
993			done_rate = PRCM_HALF_SPEED;
994
995		/* MPU divider */
996		CM_CLKSEL_MPU = prcm->cm_clksel_mpu;
997
998		/* dsp + iva1 div(2420), iva2.1(2430) */
999		CM_CLKSEL_DSP = prcm->cm_clksel_dsp;
1000
1001		CM_CLKSEL_GFX = prcm->cm_clksel_gfx;
1002
1003		/* Major subsystem dividers */
1004		CM_CLKSEL1_CORE = prcm->cm_clksel1_core;
1005		if (cpu_is_omap2430())
1006			CM_CLKSEL_MDM = prcm->cm_clksel_mdm;
1007
1008		/* x2 to enter init_mem */
1009		omap2_reprogram_sdrc(PRCM_FULL_SPEED, 1);
1010
1011		omap2_set_prcm(prcm->cm_clksel1_pll, prcm->base_sdrc_rfr,
1012			       bypass);
1013
1014		omap2_init_memory_params(omap2_dll_force_needed());
1015		omap2_reprogram_sdrc(done_rate, 0);
1016
1017		local_irq_restore(flags);
1018	}
1019	omap2_clksel_recalc(&dpll_ck);
1020
1021	return 0;
1022}
1023
1024/*-------------------------------------------------------------------------
1025 * Omap2 clock reset and init functions
1026 *-------------------------------------------------------------------------*/
1027
1028#ifdef CONFIG_OMAP_RESET_CLOCKS
1029static void __init omap2_clk_disable_unused(struct clk *clk)
1030{
1031	u32 regval32;
1032
1033	regval32 = __raw_readl(clk->enable_reg);
1034	if ((regval32 & (1 << clk->enable_bit)) == 0)
1035		return;
1036
1037	printk(KERN_INFO "Disabling unused clock \"%s\"\n", clk->name);
1038	_omap2_clk_disable(clk);
1039}
1040#else
1041#define omap2_clk_disable_unused	NULL
1042#endif
1043
1044static struct clk_functions omap2_clk_functions = {
1045	.clk_enable		= omap2_clk_enable,
1046	.clk_disable		= omap2_clk_disable,
1047	.clk_round_rate		= omap2_clk_round_rate,
1048	.clk_set_rate		= omap2_clk_set_rate,
1049	.clk_set_parent		= omap2_clk_set_parent,
1050	.clk_disable_unused	= omap2_clk_disable_unused,
1051};
1052
1053static void __init omap2_get_crystal_rate(struct clk *osc, struct clk *sys)
1054{
1055	u32 div, aplls, sclk = 13000000;
1056
1057	aplls = CM_CLKSEL1_PLL;
1058	aplls &= ((1 << 23) | (1 << 24) | (1 << 25));
1059	aplls >>= 23;			/* Isolate field, 0,2,3 */
1060
1061	if (aplls == 0)
1062		sclk = 19200000;
1063	else if (aplls == 2)
1064		sclk = 13000000;
1065	else if (aplls == 3)
1066		sclk = 12000000;
1067
1068	div = PRCM_CLKSRC_CTRL;
1069	div &= ((1 << 7) | (1 << 6));
1070	div >>= sys->rate_offset;
1071
1072	osc->rate = sclk * div;
1073	sys->rate = sclk;
1074}
1075
1076/*
1077 * Set clocks for bypass mode for reboot to work.
1078 */
1079void omap2_clk_prepare_for_reboot(void)
1080{
1081	u32 rate;
1082
1083	if (vclk == NULL || sclk == NULL)
1084		return;
1085
1086	rate = clk_get_rate(sclk);
1087	clk_set_rate(vclk, rate);
1088}
1089
1090/*
1091 * Switch the MPU rate if specified on cmdline.
1092 * We cannot do this early until cmdline is parsed.
1093 */
1094static int __init omap2_clk_arch_init(void)
1095{
1096	if (!mpurate)
1097		return -EINVAL;
1098
1099	if (omap2_select_table_rate(&virt_prcm_set, mpurate))
1100		printk(KERN_ERR "Could not find matching MPU rate\n");
1101
1102	propagate_rate(&osc_ck);		/* update main root fast */
1103	propagate_rate(&func_32k_ck);		/* update main root slow */
1104
1105	printk(KERN_INFO "Switched to new clocking rate (Crystal/DPLL/MPU): "
1106	       "%ld.%01ld/%ld/%ld MHz\n",
1107	       (sys_ck.rate / 1000000), (sys_ck.rate / 100000) % 10,
1108	       (dpll_ck.rate / 1000000), (mpu_ck.rate / 1000000)) ;
1109
1110	return 0;
1111}
1112arch_initcall(omap2_clk_arch_init);
1113
1114int __init omap2_clk_init(void)
1115{
1116	struct prcm_config *prcm;
1117	struct clk ** clkp;
1118	u32 clkrate;
1119
1120	clk_init(&omap2_clk_functions);
1121	omap2_get_crystal_rate(&osc_ck, &sys_ck);
1122
1123	for (clkp = onchip_clks; clkp < onchip_clks + ARRAY_SIZE(onchip_clks);
1124	     clkp++) {
1125
1126		if ((*clkp)->flags & CLOCK_IN_OMAP242X && cpu_is_omap2420()) {
1127			clk_register(*clkp);
1128			continue;
1129		}
1130
1131		if ((*clkp)->flags & CLOCK_IN_OMAP243X && cpu_is_omap2430()) {
1132			clk_register(*clkp);
1133			continue;
1134		}
1135	}
1136
1137	/* Check the MPU rate set by bootloader */
1138	clkrate = omap2_get_dpll_rate(&dpll_ck);
1139	for (prcm = rate_table; prcm->mpu_speed; prcm++) {
1140		if (prcm->xtal_speed != sys_ck.rate)
1141			continue;
1142		if (prcm->dpll_speed <= clkrate)
1143			 break;
1144	}
1145	curr_prcm_set = prcm;
1146
1147	propagate_rate(&osc_ck);		/* update main root fast */
1148	propagate_rate(&func_32k_ck);		/* update main root slow */
1149
1150	printk(KERN_INFO "Clocking rate (Crystal/DPLL/MPU): "
1151	       "%ld.%01ld/%ld/%ld MHz\n",
1152	       (sys_ck.rate / 1000000), (sys_ck.rate / 100000) % 10,
1153	       (dpll_ck.rate / 1000000), (mpu_ck.rate / 1000000)) ;
1154
1155	/*
1156	 * Only enable those clocks we will need, let the drivers
1157	 * enable other clocks as necessary
1158	 */
1159	clk_enable(&sync_32k_ick);
1160	clk_enable(&omapctrl_ick);
1161
1162	/* Force the APLLs active during bootup to avoid disabling and
1163	 * enabling them unnecessarily. */
1164	clk_enable(&apll96_ck);
1165	clk_enable(&apll54_ck);
1166
1167	if (cpu_is_omap2430())
1168		clk_enable(&sdrc_ick);
1169
1170	/* Avoid sleeping sleeping during omap2_clk_prepare_for_reboot() */
1171	vclk = clk_get(NULL, "virt_prcm_set");
1172	sclk = clk_get(NULL, "sys_ck");
1173
1174	return 0;
1175}
1176
1177static int __init omap2_disable_aplls(void)
1178{
1179	clk_disable(&apll96_ck);
1180	clk_disable(&apll54_ck);
1181
1182	return 0;
1183}
1184late_initcall(omap2_disable_aplls);
1185