clock24xx.c 21.0 KB
Newer Older
1 2 3
/*
 *  linux/arch/arm/mach-omap2/clock.c
 *
4 5
 *  Copyright (C) 2005-2008 Texas Instruments, Inc.
 *  Copyright (C) 2004-2008 Nokia Corporation
6
 *
7 8 9
 *  Contacts:
 *  Richard Woodruff <r-woodruff2@ti.com>
 *  Paul Walmsley
10
 *
11 12
 *  Based on earlier work by Tuukka Tikkanen, Tony Lindgren,
 *  Gordon McNutt and RidgeRun, Inc.
13 14 15 16 17
 *
 * This program is free software; you can redistribute it and/or modify
 * it under the terms of the GNU General Public License version 2 as
 * published by the Free Software Foundation.
 */
18 19
#undef DEBUG

20 21 22 23 24 25
#include <linux/module.h>
#include <linux/kernel.h>
#include <linux/device.h>
#include <linux/list.h>
#include <linux/errno.h>
#include <linux/delay.h>
26
#include <linux/clk.h>
27 28
#include <linux/io.h>
#include <linux/cpufreq.h>
29
#include <linux/bitops.h>
30

31 32
#include <mach/clock.h>
#include <mach/sram.h>
33
#include <asm/div64.h>
34
#include <asm/clkdev.h>
35

36
#include "memory.h"
37 38 39 40 41
#include "clock.h"
#include "prm.h"
#include "prm-regbits-24xx.h"
#include "cm.h"
#include "cm-regbits-24xx.h"
42

43 44 45 46 47
static const struct clkops clkops_oscck;
static const struct clkops clkops_fixed;

#include "clock24xx.h"

48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114
struct omap_clk {
	u32		cpu;
	struct clk_lookup lk;
};

#define CLK(dev, con, ck, cp) 		\
	{				\
		 .cpu = cp,		\
		.lk = {			\
			.dev_id = dev,	\
			.con_id = con,	\
			.clk = ck,	\
		},			\
	}

#define CK_243X	(1 << 0)
#define CK_242X	(1 << 1)

static struct omap_clk omap24xx_clks[] = {
	/* external root sources */
	CLK(NULL,	"func_32k_ck",	&func_32k_ck,	CK_243X | CK_242X),
	CLK(NULL,	"osc_ck",	&osc_ck,	CK_243X | CK_242X),
	CLK(NULL,	"sys_ck",	&sys_ck,	CK_243X | CK_242X),
	CLK(NULL,	"alt_ck",	&alt_ck,	CK_243X | CK_242X),
	/* internal analog sources */
	CLK(NULL,	"dpll_ck",	&dpll_ck,	CK_243X | CK_242X),
	CLK(NULL,	"apll96_ck",	&apll96_ck,	CK_243X | CK_242X),
	CLK(NULL,	"apll54_ck",	&apll54_ck,	CK_243X | CK_242X),
	/* internal prcm root sources */
	CLK(NULL,	"func_54m_ck",	&func_54m_ck,	CK_243X | CK_242X),
	CLK(NULL,	"core_ck",	&core_ck,	CK_243X | CK_242X),
	CLK(NULL,	"func_96m_ck",	&func_96m_ck,	CK_243X | CK_242X),
	CLK(NULL,	"func_48m_ck",	&func_48m_ck,	CK_243X | CK_242X),
	CLK(NULL,	"func_12m_ck",	&func_12m_ck,	CK_243X | CK_242X),
	CLK(NULL,	"ck_wdt1_osc",	&wdt1_osc_ck,	CK_243X | CK_242X),
	CLK(NULL,	"sys_clkout_src", &sys_clkout_src, CK_243X | CK_242X),
	CLK(NULL,	"sys_clkout",	&sys_clkout,	CK_243X | CK_242X),
	CLK(NULL,	"sys_clkout2_src", &sys_clkout2_src, CK_242X),
	CLK(NULL,	"sys_clkout2",	&sys_clkout2,	CK_242X),
	CLK(NULL,	"emul_ck",	&emul_ck,	CK_242X),
	/* mpu domain clocks */
	CLK(NULL,	"mpu_ck",	&mpu_ck,	CK_243X | CK_242X),
	/* dsp domain clocks */
	CLK(NULL,	"dsp_fck",	&dsp_fck,	CK_243X | CK_242X),
	CLK(NULL,	"dsp_irate_ick", &dsp_irate_ick, CK_243X | CK_242X),
	CLK(NULL,	"dsp_ick",	&dsp_ick,	CK_242X),
	CLK(NULL,	"iva2_1_ick",	&iva2_1_ick,	CK_243X),
	CLK(NULL,	"iva1_ifck",	&iva1_ifck,	CK_242X),
	CLK(NULL,	"iva1_mpu_int_ifck", &iva1_mpu_int_ifck, CK_242X),
	/* GFX domain clocks */
	CLK(NULL,	"gfx_3d_fck",	&gfx_3d_fck,	CK_243X | CK_242X),
	CLK(NULL,	"gfx_2d_fck",	&gfx_2d_fck,	CK_243X | CK_242X),
	CLK(NULL,	"gfx_ick",	&gfx_ick,	CK_243X | CK_242X),
	/* Modem domain clocks */
	CLK(NULL,	"mdm_ick",	&mdm_ick,	CK_243X),
	CLK(NULL,	"mdm_osc_ck",	&mdm_osc_ck,	CK_243X),
	/* DSS domain clocks */
	CLK(NULL,	"dss_ick",	&dss_ick,	CK_243X | CK_242X),
	CLK(NULL,	"dss1_fck",	&dss1_fck,	CK_243X | CK_242X),
	CLK(NULL,	"dss2_fck",	&dss2_fck,	CK_243X | CK_242X),
	CLK(NULL,	"dss_54m_fck",	&dss_54m_fck,	CK_243X | CK_242X),
	/* L3 domain clocks */
	CLK(NULL,	"core_l3_ck",	&core_l3_ck,	CK_243X | CK_242X),
	CLK(NULL,	"ssi_fck",	&ssi_ssr_sst_fck, CK_243X | CK_242X),
	CLK(NULL,	"usb_l4_ick",	&usb_l4_ick,	CK_243X | CK_242X),
	/* L4 domain clocks */
	CLK(NULL,	"l4_ck",	&l4_ck,		CK_243X | CK_242X),
115
	CLK(NULL,	"ssi_l4_ick",	&ssi_l4_ick,	CK_243X | CK_242X),
116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142
	/* virtual meta-group clock */
	CLK(NULL,	"virt_prcm_set", &virt_prcm_set, CK_243X | CK_242X),
	/* general l4 interface ck, multi-parent functional clk */
	CLK(NULL,	"gpt1_ick",	&gpt1_ick,	CK_243X | CK_242X),
	CLK(NULL,	"gpt1_fck",	&gpt1_fck,	CK_243X | CK_242X),
	CLK(NULL,	"gpt2_ick",	&gpt2_ick,	CK_243X | CK_242X),
	CLK(NULL,	"gpt2_fck",	&gpt2_fck,	CK_243X | CK_242X),
	CLK(NULL,	"gpt3_ick",	&gpt3_ick,	CK_243X | CK_242X),
	CLK(NULL,	"gpt3_fck",	&gpt3_fck,	CK_243X | CK_242X),
	CLK(NULL,	"gpt4_ick",	&gpt4_ick,	CK_243X | CK_242X),
	CLK(NULL,	"gpt4_fck",	&gpt4_fck,	CK_243X | CK_242X),
	CLK(NULL,	"gpt5_ick",	&gpt5_ick,	CK_243X | CK_242X),
	CLK(NULL,	"gpt5_fck",	&gpt5_fck,	CK_243X | CK_242X),
	CLK(NULL,	"gpt6_ick",	&gpt6_ick,	CK_243X | CK_242X),
	CLK(NULL,	"gpt6_fck",	&gpt6_fck,	CK_243X | CK_242X),
	CLK(NULL,	"gpt7_ick",	&gpt7_ick,	CK_243X | CK_242X),
	CLK(NULL,	"gpt7_fck",	&gpt7_fck,	CK_243X | CK_242X),
	CLK(NULL,	"gpt8_ick",	&gpt8_ick,	CK_243X | CK_242X),
	CLK(NULL,	"gpt8_fck",	&gpt8_fck,	CK_243X | CK_242X),
	CLK(NULL,	"gpt9_ick",	&gpt9_ick,	CK_243X | CK_242X),
	CLK(NULL,	"gpt9_fck",	&gpt9_fck,	CK_243X | CK_242X),
	CLK(NULL,	"gpt10_ick",	&gpt10_ick,	CK_243X | CK_242X),
	CLK(NULL,	"gpt10_fck",	&gpt10_fck,	CK_243X | CK_242X),
	CLK(NULL,	"gpt11_ick",	&gpt11_ick,	CK_243X | CK_242X),
	CLK(NULL,	"gpt11_fck",	&gpt11_fck,	CK_243X | CK_242X),
	CLK(NULL,	"gpt12_ick",	&gpt12_ick,	CK_243X | CK_242X),
	CLK(NULL,	"gpt12_fck",	&gpt12_fck,	CK_243X | CK_242X),
143 144 145 146 147 148 149 150 151 152
	CLK("omap-mcbsp.1", "ick",	&mcbsp1_ick,	CK_243X | CK_242X),
	CLK("omap-mcbsp.1", "fck",	&mcbsp1_fck,	CK_243X | CK_242X),
	CLK("omap-mcbsp.2", "ick",	&mcbsp2_ick,	CK_243X | CK_242X),
	CLK("omap-mcbsp.2", "fck",	&mcbsp2_fck,	CK_243X | CK_242X),
	CLK("omap-mcbsp.3", "ick",	&mcbsp3_ick,	CK_243X),
	CLK("omap-mcbsp.3", "fck",	&mcbsp3_fck,	CK_243X),
	CLK("omap-mcbsp.4", "ick",	&mcbsp4_ick,	CK_243X),
	CLK("omap-mcbsp.4", "fck",	&mcbsp4_fck,	CK_243X),
	CLK("omap-mcbsp.5", "ick",	&mcbsp5_ick,	CK_243X),
	CLK("omap-mcbsp.5", "fck",	&mcbsp5_fck,	CK_243X),
153 154 155 156 157 158
	CLK("omap2_mcspi.1", "ick",	&mcspi1_ick,	CK_243X | CK_242X),
	CLK("omap2_mcspi.1", "fck",	&mcspi1_fck,	CK_243X | CK_242X),
	CLK("omap2_mcspi.2", "ick",	&mcspi2_ick,	CK_243X | CK_242X),
	CLK("omap2_mcspi.2", "fck",	&mcspi2_fck,	CK_243X | CK_242X),
	CLK("omap2_mcspi.3", "ick",	&mcspi3_ick,	CK_243X),
	CLK("omap2_mcspi.3", "fck",	&mcspi3_fck,	CK_243X),
159 160 161 162 163 164 165 166
	CLK(NULL,	"uart1_ick",	&uart1_ick,	CK_243X | CK_242X),
	CLK(NULL,	"uart1_fck",	&uart1_fck,	CK_243X | CK_242X),
	CLK(NULL,	"uart2_ick",	&uart2_ick,	CK_243X | CK_242X),
	CLK(NULL,	"uart2_fck",	&uart2_fck,	CK_243X | CK_242X),
	CLK(NULL,	"uart3_ick",	&uart3_ick,	CK_243X | CK_242X),
	CLK(NULL,	"uart3_fck",	&uart3_fck,	CK_243X | CK_242X),
	CLK(NULL,	"gpios_ick",	&gpios_ick,	CK_243X | CK_242X),
	CLK(NULL,	"gpios_fck",	&gpios_fck,	CK_243X | CK_242X),
167 168
	CLK("omap_wdt",	"ick",		&mpu_wdt_ick,	CK_243X | CK_242X),
	CLK("omap_wdt",	"fck",		&mpu_wdt_fck,	CK_243X | CK_242X),
169 170 171 172
	CLK(NULL,	"sync_32k_ick",	&sync_32k_ick,	CK_243X | CK_242X),
	CLK(NULL,	"wdt1_ick",	&wdt1_ick,	CK_243X | CK_242X),
	CLK(NULL,	"omapctrl_ick",	&omapctrl_ick,	CK_243X | CK_242X),
	CLK(NULL,	"icr_ick",	&icr_ick,	CK_243X),
173 174
	CLK("omap24xxcam", "fck",	&cam_fck,	CK_243X | CK_242X),
	CLK("omap24xxcam", "ick",	&cam_ick,	CK_243X | CK_242X),
175 176 177 178 179 180 181
	CLK(NULL,	"mailboxes_ick", &mailboxes_ick,	CK_243X | CK_242X),
	CLK(NULL,	"wdt4_ick",	&wdt4_ick,	CK_243X | CK_242X),
	CLK(NULL,	"wdt4_fck",	&wdt4_fck,	CK_243X | CK_242X),
	CLK(NULL,	"wdt3_ick",	&wdt3_ick,	CK_242X),
	CLK(NULL,	"wdt3_fck",	&wdt3_fck,	CK_242X),
	CLK(NULL,	"mspro_ick",	&mspro_ick,	CK_243X | CK_242X),
	CLK(NULL,	"mspro_fck",	&mspro_fck,	CK_243X | CK_242X),
182 183
	CLK("mmci-omap.0", "ick",	&mmc_ick,	CK_242X),
	CLK("mmci-omap.0", "fck",	&mmc_fck,	CK_242X),
184 185 186 187
	CLK(NULL,	"fac_ick",	&fac_ick,	CK_243X | CK_242X),
	CLK(NULL,	"fac_fck",	&fac_fck,	CK_243X | CK_242X),
	CLK(NULL,	"eac_ick",	&eac_ick,	CK_242X),
	CLK(NULL,	"eac_fck",	&eac_fck,	CK_242X),
188 189
	CLK("omap_hdq.0", "ick",	&hdq_ick,	CK_243X | CK_242X),
	CLK("omap_hdq.1", "fck",	&hdq_fck,	CK_243X | CK_242X),
190 191 192 193 194 195
	CLK("i2c_omap.1", "ick",	&i2c1_ick,	CK_243X | CK_242X),
	CLK("i2c_omap.1", "fck",	&i2c1_fck,	CK_242X),
	CLK("i2c_omap.1", "fck",	&i2chs1_fck,	CK_243X),
	CLK("i2c_omap.2", "ick",	&i2c2_ick,	CK_243X | CK_242X),
	CLK("i2c_omap.2", "fck",	&i2c2_fck,	CK_242X),
	CLK("i2c_omap.2", "fck",	&i2chs2_fck,	CK_243X),
196 197 198 199 200 201 202 203
	CLK(NULL,	"gpmc_fck",	&gpmc_fck,	CK_243X | CK_242X),
	CLK(NULL,	"sdma_fck",	&sdma_fck,	CK_243X | CK_242X),
	CLK(NULL,	"sdma_ick",	&sdma_ick,	CK_243X | CK_242X),
	CLK(NULL,	"vlynq_ick",	&vlynq_ick,	CK_242X),
	CLK(NULL,	"vlynq_fck",	&vlynq_fck,	CK_242X),
	CLK(NULL,	"sdrc_ick",	&sdrc_ick,	CK_243X),
	CLK(NULL,	"des_ick",	&des_ick,	CK_243X | CK_242X),
	CLK(NULL,	"sha_ick",	&sha_ick,	CK_243X | CK_242X),
204
	CLK("omap_rng",	"ick",		&rng_ick,	CK_243X | CK_242X),
205 206 207 208
	CLK(NULL,	"aes_ick",	&aes_ick,	CK_243X | CK_242X),
	CLK(NULL,	"pka_ick",	&pka_ick,	CK_243X | CK_242X),
	CLK(NULL,	"usb_fck",	&usb_fck,	CK_243X | CK_242X),
	CLK(NULL,	"usbhs_ick",	&usbhs_ick,	CK_243X),
209 210 211 212
	CLK("mmci-omap-hs.0", "ick",	&mmchs1_ick,	CK_243X),
	CLK("mmci-omap-hs.0", "fck",	&mmchs1_fck,	CK_243X),
	CLK("mmci-omap-hs.1", "ick",	&mmchs2_ick,	CK_243X),
	CLK("mmci-omap-hs.1", "fck",	&mmchs2_fck,	CK_243X),
213 214 215 216 217 218 219
	CLK(NULL,	"gpio5_ick",	&gpio5_ick,	CK_243X),
	CLK(NULL,	"gpio5_fck",	&gpio5_fck,	CK_243X),
	CLK(NULL,	"mdm_intc_ick",	&mdm_intc_ick,	CK_243X),
	CLK("mmci-omap-hs.0", "mmchsdb_fck",	&mmchsdb1_fck,	CK_243X),
	CLK("mmci-omap-hs.1", "mmchsdb_fck", 	&mmchsdb2_fck,	CK_243X),
};

220 221 222
/* CM_CLKEN_PLL.EN_{54,96}M_PLL options (24XX) */
#define EN_APLL_STOPPED			0
#define EN_APLL_LOCKED			3
223

224 225 226 227 228 229
/* CM_CLKSEL1_PLL.APLLS_CLKIN options (24XX) */
#define APLLS_CLKIN_19_2MHZ		0
#define APLLS_CLKIN_13MHZ		2
#define APLLS_CLKIN_12MHZ		3

/* #define DOWN_VARIABLE_DPLL 1 */		/* Experimental */
230 231

static struct prcm_config *curr_prcm_set;
232 233
static struct clk *vclk;
static struct clk *sclk;
234 235

/*-------------------------------------------------------------------------
236
 * Omap24xx specific clock functions
237 238
 *-------------------------------------------------------------------------*/

239 240 241 242 243 244 245 246 247 248 249 250 251 252 253
/* This actually returns the rate of core_ck, not dpll_ck. */
static u32 omap2_get_dpll_rate_24xx(struct clk *tclk)
{
	long long dpll_clk;
	u8 amult;

	dpll_clk = omap2_get_dpll_rate(tclk);

	amult = cm_read_mod_reg(PLL_MOD, CM_CLKSEL2);
	amult &= OMAP24XX_CORE_CLK_SRC_MASK;
	dpll_clk *= amult;

	return dpll_clk;
}

254 255 256 257 258 259 260 261 262 263 264 265 266 267 268 269 270 271 272 273 274 275
static int omap2_enable_osc_ck(struct clk *clk)
{
	u32 pcc;

	pcc = __raw_readl(OMAP24XX_PRCM_CLKSRC_CTRL);

	__raw_writel(pcc & ~OMAP_AUTOEXTCLKMODE_MASK,
		      OMAP24XX_PRCM_CLKSRC_CTRL);

	return 0;
}

static void omap2_disable_osc_ck(struct clk *clk)
{
	u32 pcc;

	pcc = __raw_readl(OMAP24XX_PRCM_CLKSRC_CTRL);

	__raw_writel(pcc | OMAP_AUTOEXTCLKMODE_MASK,
		      OMAP24XX_PRCM_CLKSRC_CTRL);
}

276 277 278 279 280
static const struct clkops clkops_oscck = {
	.enable		= &omap2_enable_osc_ck,
	.disable	= &omap2_disable_osc_ck,
};

281
#ifdef OLD_CK
282 283 284 285 286 287 288 289 290
/* Recalculate SYST_CLK */
static void omap2_sys_clk_recalc(struct clk * clk)
{
	u32 div = PRCM_CLKSRC_CTRL;
	div &= (1 << 7) | (1 << 6);	/* Test if ext clk divided by 1 or 2 */
	div >>= clk->rate_offset;
	clk->rate = (clk->parent->rate / div);
	propagate_rate(clk);
}
291
#endif	/* OLD_CK */
292 293

/* Enable an APLL if off */
294
static int omap2_clk_fixed_enable(struct clk *clk)
295
{
296
	u32 cval, apll_mask;
297

298
	apll_mask = EN_APLL_LOCKED << clk->enable_bit;
299

300
	cval = cm_read_mod_reg(PLL_MOD, CM_CLKEN);
301

302 303
	if ((cval & apll_mask) == apll_mask)
		return 0;   /* apll already enabled */
304

305 306 307
	cval &= ~apll_mask;
	cval |= apll_mask;
	cm_write_mod_reg(cval, PLL_MOD, CM_CLKEN);
308 309

	if (clk == &apll96_ck)
310
		cval = OMAP24XX_ST_96M_APLL;
311
	else if (clk == &apll54_ck)
312
		cval = OMAP24XX_ST_54M_APLL;
313

314 315 316 317 318 319 320 321
	omap2_wait_clock_ready(OMAP_CM_REGADDR(PLL_MOD, CM_IDLEST), cval,
			    clk->name);

	/*
	 * REVISIT: Should we return an error code if omap2_wait_clock_ready()
	 * fails?
	 */
	return 0;
322 323 324 325 326 327 328
}

/* Stop APLL */
static void omap2_clk_fixed_disable(struct clk *clk)
{
	u32 cval;

329 330 331
	cval = cm_read_mod_reg(PLL_MOD, CM_CLKEN);
	cval &= ~(EN_APLL_LOCKED << clk->enable_bit);
	cm_write_mod_reg(cval, PLL_MOD, CM_CLKEN);
332 333
}

334 335 336 337 338
static const struct clkops clkops_fixed = {
	.enable		= &omap2_clk_fixed_enable,
	.disable	= &omap2_clk_fixed_disable,
};

339 340 341 342
/*
 * Uses the current prcm set to tell if a rate is valid.
 * You can go slower, but not faster within a given rate set.
 */
343
static long omap2_dpllcore_round_rate(unsigned long target_rate)
344
{
345
	u32 high, low, core_clk_src;
346

347 348 349 350
	core_clk_src = cm_read_mod_reg(PLL_MOD, CM_CLKSEL2);
	core_clk_src &= OMAP24XX_CORE_CLK_SRC_MASK;

	if (core_clk_src == CORE_CLK_SRC_DPLL) {	/* DPLL clockout */
351 352 353 354 355 356 357 358 359 360 361 362 363 364 365 366 367 368 369 370 371
		high = curr_prcm_set->dpll_speed * 2;
		low = curr_prcm_set->dpll_speed;
	} else {				/* DPLL clockout x 2 */
		high = curr_prcm_set->dpll_speed;
		low = curr_prcm_set->dpll_speed / 2;
	}

#ifdef DOWN_VARIABLE_DPLL
	if (target_rate > high)
		return high;
	else
		return target_rate;
#else
	if (target_rate > low)
		return high;
	else
		return low;
#endif

}

372
static void omap2_dpllcore_recalc(struct clk *clk)
373 374 375
{
	clk->rate = omap2_get_dpll_rate_24xx(clk);
}
376

377
static int omap2_reprogram_dpllcore(struct clk *clk, unsigned long rate)
378
{
379
	u32 cur_rate, low, mult, div, valid_rate, done_rate;
380 381
	u32 bypass = 0;
	struct prcm_config tmpset;
382 383
	const struct dpll_data *dd;
	unsigned long flags;
384 385 386
	int ret = -EINVAL;

	local_irq_save(flags);
387 388 389
	cur_rate = omap2_get_dpll_rate_24xx(&dpll_ck);
	mult = cm_read_mod_reg(PLL_MOD, CM_CLKSEL2);
	mult &= OMAP24XX_CORE_CLK_SRC_MASK;
390 391

	if ((rate == (cur_rate / 2)) && (mult == 2)) {
392
		omap2_reprogram_sdrc(CORE_CLK_SRC_DPLL, 1);
393
	} else if ((rate == (cur_rate * 2)) && (mult == 1)) {
394
		omap2_reprogram_sdrc(CORE_CLK_SRC_DPLL_X2, 1);
395
	} else if (rate != cur_rate) {
396
		valid_rate = omap2_dpllcore_round_rate(rate);
397 398 399
		if (valid_rate != rate)
			goto dpll_exit;

400
		if (mult == 1)
401 402 403 404
			low = curr_prcm_set->dpll_speed;
		else
			low = curr_prcm_set->dpll_speed / 2;

405 406 407 408 409 410 411
		dd = clk->dpll_data;
		if (!dd)
			goto dpll_exit;

		tmpset.cm_clksel1_pll = __raw_readl(dd->mult_div1_reg);
		tmpset.cm_clksel1_pll &= ~(dd->mult_mask |
					   dd->div1_mask);
412
		div = ((curr_prcm_set->xtal_speed / 1000000) - 1);
413 414
		tmpset.cm_clksel2_pll = cm_read_mod_reg(PLL_MOD, CM_CLKSEL2);
		tmpset.cm_clksel2_pll &= ~OMAP24XX_CORE_CLK_SRC_MASK;
415
		if (rate > low) {
416
			tmpset.cm_clksel2_pll |= CORE_CLK_SRC_DPLL_X2;
417
			mult = ((rate / 2) / 1000000);
418
			done_rate = CORE_CLK_SRC_DPLL_X2;
419
		} else {
420
			tmpset.cm_clksel2_pll |= CORE_CLK_SRC_DPLL;
421
			mult = (rate / 1000000);
422
			done_rate = CORE_CLK_SRC_DPLL;
423
		}
424 425
		tmpset.cm_clksel1_pll |= (div << __ffs(dd->mult_mask));
		tmpset.cm_clksel1_pll |= (mult << __ffs(dd->div1_mask));
426 427

		/* Worst case */
428
		tmpset.base_sdrc_rfr = SDRC_RFR_CTRL_BYPASS;
429 430 431 432

		if (rate == curr_prcm_set->xtal_speed)	/* If asking for 1-1 */
			bypass = 1;

433
		omap2_reprogram_sdrc(CORE_CLK_SRC_DPLL_X2, 1); /* For init_mem */
434 435 436 437 438 439 440 441 442

		/* Force dll lock mode */
		omap2_set_prcm(tmpset.cm_clksel1_pll, tmpset.base_sdrc_rfr,
			       bypass);

		/* Errata: ret dll entry state */
		omap2_init_memory_params(omap2_dll_force_needed());
		omap2_reprogram_sdrc(done_rate, 0);
	}
443
	omap2_dpllcore_recalc(&dpll_ck);
444 445 446 447 448 449 450
	ret = 0;

dpll_exit:
	local_irq_restore(flags);
	return(ret);
}

451 452 453 454 455 456 457
/**
 * omap2_table_mpu_recalc - just return the MPU speed
 * @clk: virt_prcm_set struct clk
 *
 * Set virt_prcm_set's rate to the mpu_speed field of the current PRCM set.
 */
static void omap2_table_mpu_recalc(struct clk *clk)
458 459 460 461 462 463 464 465 466 467 468
{
	clk->rate = curr_prcm_set->mpu_speed;
}

/*
 * Look for a rate equal or less than the target rate given a configuration set.
 *
 * What's not entirely clear is "which" field represents the key field.
 * Some might argue L3-DDR, others ARM, others IVA. This code is simple and
 * just uses the ARM rates.
 */
469
static long omap2_round_to_table_rate(struct clk *clk, unsigned long rate)
470
{
471
	struct prcm_config *ptr;
472 473 474 475 476 477 478 479
	long highest_rate;

	if (clk != &virt_prcm_set)
		return -EINVAL;

	highest_rate = -EINVAL;

	for (ptr = rate_table; ptr->mpu_speed; ptr++) {
480 481
		if (!(ptr->flags & cpu_mask))
			continue;
482 483 484 485 486 487 488 489 490 491 492 493 494
		if (ptr->xtal_speed != sys_ck.rate)
			continue;

		highest_rate = ptr->mpu_speed;

		/* Can check only after xtal frequency check */
		if (ptr->mpu_speed <= rate)
			break;
	}
	return highest_rate;
}

/* Sets basic clocks based on the specified rate */
495
static int omap2_select_table_rate(struct clk *clk, unsigned long rate)
496
{
497
	u32 cur_rate, done_rate, bypass = 0, tmp;
498 499
	struct prcm_config *prcm;
	unsigned long found_speed = 0;
500
	unsigned long flags;
501 502 503 504 505 506 507 508 509 510 511 512 513 514 515 516 517 518 519

	if (clk != &virt_prcm_set)
		return -EINVAL;

	for (prcm = rate_table; prcm->mpu_speed; prcm++) {
		if (!(prcm->flags & cpu_mask))
			continue;

		if (prcm->xtal_speed != sys_ck.rate)
			continue;

		if (prcm->mpu_speed <= rate) {
			found_speed = prcm->mpu_speed;
			break;
		}
	}

	if (!found_speed) {
		printk(KERN_INFO "Could not set MPU rate to %luMHz\n",
520
		       rate / 1000000);
521 522 523 524
		return -EINVAL;
	}

	curr_prcm_set = prcm;
525
	cur_rate = omap2_get_dpll_rate_24xx(&dpll_ck);
526 527

	if (prcm->dpll_speed == cur_rate / 2) {
528
		omap2_reprogram_sdrc(CORE_CLK_SRC_DPLL, 1);
529
	} else if (prcm->dpll_speed == cur_rate * 2) {
530
		omap2_reprogram_sdrc(CORE_CLK_SRC_DPLL_X2, 1);
531 532 533 534 535 536
	} else if (prcm->dpll_speed != cur_rate) {
		local_irq_save(flags);

		if (prcm->dpll_speed == prcm->xtal_speed)
			bypass = 1;

537 538 539
		if ((prcm->cm_clksel2_pll & OMAP24XX_CORE_CLK_SRC_MASK) ==
		    CORE_CLK_SRC_DPLL_X2)
			done_rate = CORE_CLK_SRC_DPLL_X2;
540
		else
541
			done_rate = CORE_CLK_SRC_DPLL;
542 543

		/* MPU divider */
544
		cm_write_mod_reg(prcm->cm_clksel_mpu, MPU_MOD, CM_CLKSEL);
545 546

		/* dsp + iva1 div(2420), iva2.1(2430) */
547 548
		cm_write_mod_reg(prcm->cm_clksel_dsp,
				 OMAP24XX_DSP_MOD, CM_CLKSEL);
549

550
		cm_write_mod_reg(prcm->cm_clksel_gfx, GFX_MOD, CM_CLKSEL);
551 552

		/* Major subsystem dividers */
553
		tmp = cm_read_mod_reg(CORE_MOD, CM_CLKSEL1) & OMAP24XX_CLKSEL_DSS2_MASK;
554 555 556
		cm_write_mod_reg(prcm->cm_clksel1_core | tmp, CORE_MOD,
				 CM_CLKSEL1);

557
		if (cpu_is_omap2430())
558 559
			cm_write_mod_reg(prcm->cm_clksel_mdm,
					 OMAP2430_MDM_MOD, CM_CLKSEL);
560 561

		/* x2 to enter init_mem */
562
		omap2_reprogram_sdrc(CORE_CLK_SRC_DPLL_X2, 1);
563 564 565 566 567 568 569 570 571

		omap2_set_prcm(prcm->cm_clksel1_pll, prcm->base_sdrc_rfr,
			       bypass);

		omap2_init_memory_params(omap2_dll_force_needed());
		omap2_reprogram_sdrc(done_rate, 0);

		local_irq_restore(flags);
	}
572
	omap2_dpllcore_recalc(&dpll_ck);
573 574 575 576 577 578 579 580 581 582

	return 0;
}

static struct clk_functions omap2_clk_functions = {
	.clk_enable		= omap2_clk_enable,
	.clk_disable		= omap2_clk_disable,
	.clk_round_rate		= omap2_clk_round_rate,
	.clk_set_rate		= omap2_clk_set_rate,
	.clk_set_parent		= omap2_clk_set_parent,
583
	.clk_disable_unused	= omap2_clk_disable_unused,
584 585
};

586
static u32 omap2_get_apll_clkin(void)
587
{
588
	u32 aplls, srate = 0;
589

590 591 592
	aplls = cm_read_mod_reg(PLL_MOD, CM_CLKSEL1);
	aplls &= OMAP24XX_APLLS_CLKIN_MASK;
	aplls >>= OMAP24XX_APLLS_CLKIN_SHIFT;
593

594
	if (aplls == APLLS_CLKIN_19_2MHZ)
595
		srate = 19200000;
596
	else if (aplls == APLLS_CLKIN_13MHZ)
597
		srate = 13000000;
598
	else if (aplls == APLLS_CLKIN_12MHZ)
599
		srate = 12000000;
600

601
	return srate;
602 603 604 605 606 607 608 609 610
}

static u32 omap2_get_sysclkdiv(void)
{
	u32 div;

	div = __raw_readl(OMAP24XX_PRCM_CLKSRC_CTRL);
	div &= OMAP_SYSCLKDIV_MASK;
	div >>= OMAP_SYSCLKDIV_SHIFT;
611

612 613 614 615 616 617 618 619 620 621 622
	return div;
}

static void omap2_osc_clk_recalc(struct clk *clk)
{
	clk->rate = omap2_get_apll_clkin() * omap2_get_sysclkdiv();
}

static void omap2_sys_clk_recalc(struct clk *clk)
{
	clk->rate = clk->parent->rate / omap2_get_sysclkdiv();
623 624
}

625 626 627 628 629 630 631 632 633 634 635 636 637 638
/*
 * Set clocks for bypass mode for reboot to work.
 */
void omap2_clk_prepare_for_reboot(void)
{
	u32 rate;

	if (vclk == NULL || sclk == NULL)
		return;

	rate = clk_get_rate(sclk);
	clk_set_rate(vclk, rate);
}

639 640 641 642 643 644 645 646 647 648 649 650
/*
 * Switch the MPU rate if specified on cmdline.
 * We cannot do this early until cmdline is parsed.
 */
static int __init omap2_clk_arch_init(void)
{
	if (!mpurate)
		return -EINVAL;

	if (omap2_select_table_rate(&virt_prcm_set, mpurate))
		printk(KERN_ERR "Could not find matching MPU rate\n");

651
	recalculate_root_clocks();
652 653 654 655 656 657 658 659 660 661 662 663 664

	printk(KERN_INFO "Switched to new clocking rate (Crystal/DPLL/MPU): "
	       "%ld.%01ld/%ld/%ld MHz\n",
	       (sys_ck.rate / 1000000), (sys_ck.rate / 100000) % 10,
	       (dpll_ck.rate / 1000000), (mpu_ck.rate / 1000000)) ;

	return 0;
}
arch_initcall(omap2_clk_arch_init);

int __init omap2_clk_init(void)
{
	struct prcm_config *prcm;
665 666
	struct omap_clk *c;
	u32 clkrate, cpu_mask;
667

668 669 670 671 672
	if (cpu_is_omap242x())
		cpu_mask = RATE_IN_242X;
	else if (cpu_is_omap2430())
		cpu_mask = RATE_IN_243X;

673 674
	clk_init(&omap2_clk_functions);

675
	omap2_osc_clk_recalc(&osc_ck);
676
	propagate_rate(&osc_ck);
677
	omap2_sys_clk_recalc(&sys_ck);
678
	propagate_rate(&sys_ck);
679

680 681 682 683 684
	cpu_mask = 0;
	if (cpu_is_omap2420())
		cpu_mask |= CK_242X;
	if (cpu_is_omap2430())
		cpu_mask |= CK_243X;
685

686 687 688 689
	for (c = omap24xx_clks; c < omap24xx_clks + ARRAY_SIZE(omap24xx_clks); c++)
		if (c->cpu & cpu_mask) {
			clkdev_add(&c->lk);
			clk_register(c->lk.clk);
690 691 692
		}

	/* Check the MPU rate set by bootloader */
693
	clkrate = omap2_get_dpll_rate_24xx(&dpll_ck);
694
	for (prcm = rate_table; prcm->mpu_speed; prcm++) {
695 696
		if (!(prcm->flags & cpu_mask))
			continue;
697 698 699 700 701 702 703
		if (prcm->xtal_speed != sys_ck.rate)
			continue;
		if (prcm->dpll_speed <= clkrate)
			 break;
	}
	curr_prcm_set = prcm;

704
	recalculate_root_clocks();
705 706 707 708 709 710 711 712 713 714

	printk(KERN_INFO "Clocking rate (Crystal/DPLL/MPU): "
	       "%ld.%01ld/%ld/%ld MHz\n",
	       (sys_ck.rate / 1000000), (sys_ck.rate / 100000) % 10,
	       (dpll_ck.rate / 1000000), (mpu_ck.rate / 1000000)) ;

	/*
	 * Only enable those clocks we will need, let the drivers
	 * enable other clocks as necessary
	 */
715
	clk_enable_init_clocks();
716

717 718 719 720
	/* Avoid sleeping sleeping during omap2_clk_prepare_for_reboot() */
	vclk = clk_get(NULL, "virt_prcm_set");
	sclk = clk_get(NULL, "sys_ck");

721 722
	return 0;
}