clock24xx.c 22.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 <mach/sdrc.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
		omap2xxx_sdrc_reprogram(CORE_CLK_SRC_DPLL, 1);
393
	} else if ((rate == (cur_rate * 2)) && (mult == 1)) {
394
		omap2xxx_sdrc_reprogram(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 434
		/* For omap2xxx_sdrc_init_params() */
		omap2xxx_sdrc_reprogram(CORE_CLK_SRC_DPLL_X2, 1);
435 436 437 438 439 440

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

		/* Errata: ret dll entry state */
441 442
		omap2xxx_sdrc_init_params(omap2xxx_sdrc_dll_is_unlocked());
		omap2xxx_sdrc_reprogram(done_rate, 0);
443
	}
444
	omap2_dpllcore_recalc(&dpll_ck);
445 446 447 448 449 450 451
	ret = 0;

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

452 453 454 455 456 457 458
/**
 * 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)
459 460 461 462 463 464 465 466 467 468 469
{
	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.
 */
470
static long omap2_round_to_table_rate(struct clk *clk, unsigned long rate)
471
{
472
	struct prcm_config *ptr;
473 474 475 476 477 478 479 480
	long highest_rate;

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

	highest_rate = -EINVAL;

	for (ptr = rate_table; ptr->mpu_speed; ptr++) {
481 482
		if (!(ptr->flags & cpu_mask))
			continue;
483 484 485 486 487 488 489 490 491 492 493 494 495
		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 */
496
static int omap2_select_table_rate(struct clk *clk, unsigned long rate)
497
{
498
	u32 cur_rate, done_rate, bypass = 0, tmp;
499 500
	struct prcm_config *prcm;
	unsigned long found_speed = 0;
501
	unsigned long flags;
502 503 504 505 506 507 508 509 510 511 512 513 514 515 516 517 518 519 520

	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",
521
		       rate / 1000000);
522 523 524 525
		return -EINVAL;
	}

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

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

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

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

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

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

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

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

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

562 563
		/* x2 to enter omap2xxx_sdrc_init_params() */
		omap2xxx_sdrc_reprogram(CORE_CLK_SRC_DPLL_X2, 1);
564 565 566 567

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

568 569
		omap2xxx_sdrc_init_params(omap2xxx_sdrc_dll_is_unlocked());
		omap2xxx_sdrc_reprogram(done_rate, 0);
570 571 572

		local_irq_restore(flags);
	}
573
	omap2_dpllcore_recalc(&dpll_ck);
574 575 576 577

	return 0;
}

578 579 580 581 582 583 584 585 586 587 588 589 590 591 592 593 594 595 596 597 598 599 600 601 602 603 604 605 606 607 608 609 610 611 612 613 614 615 616
#ifdef CONFIG_CPU_FREQ
/*
 * Walk PRCM rate table and fillout cpufreq freq_table
 */
static struct cpufreq_frequency_table freq_table[ARRAY_SIZE(rate_table)];

void omap2_clk_init_cpufreq_table(struct cpufreq_frequency_table **table)
{
	struct prcm_config *prcm;
	int i = 0;

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

		/* don't put bypass rates in table */
		if (prcm->dpll_speed == prcm->xtal_speed)
			continue;

		freq_table[i].index = i;
		freq_table[i].frequency = prcm->mpu_speed / 1000;
		i++;
	}

	if (i == 0) {
		printk(KERN_WARNING "%s: failed to initialize frequency "
		       "table\n", __func__);
		return;
	}

	freq_table[i].index = i;
	freq_table[i].frequency = CPUFREQ_TABLE_END;

	*table = &freq_table[0];
}
#endif

617 618 619 620 621 622
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,
623
	.clk_disable_unused	= omap2_clk_disable_unused,
624 625 626
#ifdef	CONFIG_CPU_FREQ
	.clk_init_cpufreq_table	= omap2_clk_init_cpufreq_table,
#endif
627 628
};

629
static u32 omap2_get_apll_clkin(void)
630
{
631
	u32 aplls, srate = 0;
632

633 634 635
	aplls = cm_read_mod_reg(PLL_MOD, CM_CLKSEL1);
	aplls &= OMAP24XX_APLLS_CLKIN_MASK;
	aplls >>= OMAP24XX_APLLS_CLKIN_SHIFT;
636

637
	if (aplls == APLLS_CLKIN_19_2MHZ)
638
		srate = 19200000;
639
	else if (aplls == APLLS_CLKIN_13MHZ)
640
		srate = 13000000;
641
	else if (aplls == APLLS_CLKIN_12MHZ)
642
		srate = 12000000;
643

644
	return srate;
645 646 647 648 649 650 651 652 653
}

static u32 omap2_get_sysclkdiv(void)
{
	u32 div;

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

655 656 657 658 659 660 661 662 663 664 665
	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();
666 667
}

668 669 670 671 672 673 674 675 676 677 678 679 680 681
/*
 * 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);
}

682 683 684 685 686 687 688 689 690
/*
 * 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;

691
	if (clk_set_rate(&virt_prcm_set, mpurate))
692 693
		printk(KERN_ERR "Could not find matching MPU rate\n");

694
	recalculate_root_clocks();
695 696 697 698 699 700 701 702 703 704 705 706 707

	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;
708 709
	struct omap_clk *c;
	u32 clkrate, cpu_mask;
710

711 712 713 714 715
	if (cpu_is_omap242x())
		cpu_mask = RATE_IN_242X;
	else if (cpu_is_omap2430())
		cpu_mask = RATE_IN_243X;

716 717
	clk_init(&omap2_clk_functions);

718
	omap2_osc_clk_recalc(&osc_ck);
719
	propagate_rate(&osc_ck);
720
	omap2_sys_clk_recalc(&sys_ck);
721
	propagate_rate(&sys_ck);
722

723 724 725 726 727
	cpu_mask = 0;
	if (cpu_is_omap2420())
		cpu_mask |= CK_242X;
	if (cpu_is_omap2430())
		cpu_mask |= CK_243X;
728

729 730 731 732
	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);
733 734 735
		}

	/* Check the MPU rate set by bootloader */
736
	clkrate = omap2_get_dpll_rate_24xx(&dpll_ck);
737
	for (prcm = rate_table; prcm->mpu_speed; prcm++) {
738 739
		if (!(prcm->flags & cpu_mask))
			continue;
740 741 742 743 744 745 746
		if (prcm->xtal_speed != sys_ck.rate)
			continue;
		if (prcm->dpll_speed <= clkrate)
			 break;
	}
	curr_prcm_set = prcm;

747
	recalculate_root_clocks();
748 749 750 751 752 753 754 755 756 757

	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
	 */
758
	clk_enable_init_clocks();
759

760 761 762 763
	/* Avoid sleeping sleeping during omap2_clk_prepare_for_reboot() */
	vclk = clk_get(NULL, "virt_prcm_set");
	sclk = clk_get(NULL, "sys_ck");

764 765
	return 0;
}