• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright 2005-2007 Freescale Semiconductor, Inc. All Rights Reserved.
3  * Copyright (C) 2008 by Sascha Hauer <kernel@pengutronix.de>
4  *
5  * This program is free software; you can redistribute it and/or
6  * modify it under the terms of the GNU General Public License
7  * as published by the Free Software Foundation; either version 2
8  * of the License, or (at your option) any later version.
9  * This program is distributed in the hope that it will be useful,
10  * but WITHOUT ANY WARRANTY; without even the implied warranty of
11  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
12  * GNU General Public License for more details.
13  *
14  * You should have received a copy of the GNU General Public License
15  * along with this program; if not, write to the Free Software
16  * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
17  * MA 02110-1301, USA.
18  */
19 
20 #include <linux/module.h>
21 #include <linux/spinlock.h>
22 #include <linux/delay.h>
23 #include <linux/clk.h>
24 #include <linux/err.h>
25 #include <linux/io.h>
26 #include <mach/clock.h>
27 #include <mach/hardware.h>
28 #include <asm/div64.h>
29 
30 #include "crm_regs.h"
31 
32 #define PRE_DIV_MIN_FREQ    10000000 /* Minimum Frequency after Predivider */
33 
__calc_pre_post_dividers(u32 div,u32 * pre,u32 * post)34 static void __calc_pre_post_dividers(u32 div, u32 *pre, u32 *post)
35 {
36 	u32 min_pre, temp_pre, old_err, err;
37 
38 	if (div >= 512) {
39 		*pre = 8;
40 		*post = 64;
41 	} else if (div >= 64) {
42 		min_pre = (div - 1) / 64 + 1;
43 		old_err = 8;
44 		for (temp_pre = 8; temp_pre >= min_pre; temp_pre--) {
45 			err = div % temp_pre;
46 			if (err == 0) {
47 				*pre = temp_pre;
48 				break;
49 			}
50 			err = temp_pre - err;
51 			if (err < old_err) {
52 				old_err = err;
53 				*pre = temp_pre;
54 			}
55 		}
56 		*post = (div + *pre - 1) / *pre;
57 	} else if (div <= 8) {
58 		*pre = div;
59 		*post = 1;
60 	} else {
61 		*pre = 1;
62 		*post = div;
63 	}
64 }
65 
66 static struct clk mcu_pll_clk;
67 static struct clk mcu_main_clk;
68 static struct clk usb_pll_clk;
69 static struct clk serial_pll_clk;
70 static struct clk ipg_clk;
71 static struct clk ckih_clk;
72 static struct clk ahb_clk;
73 
_clk_enable(struct clk * clk)74 static int _clk_enable(struct clk *clk)
75 {
76 	u32 reg;
77 
78 	reg = __raw_readl(clk->enable_reg);
79 	reg |= 3 << clk->enable_shift;
80 	__raw_writel(reg, clk->enable_reg);
81 
82 	return 0;
83 }
84 
_clk_disable(struct clk * clk)85 static void _clk_disable(struct clk *clk)
86 {
87 	u32 reg;
88 
89 	reg = __raw_readl(clk->enable_reg);
90 	reg &= ~(3 << clk->enable_shift);
91 	__raw_writel(reg, clk->enable_reg);
92 }
93 
_clk_emi_disable(struct clk * clk)94 static void _clk_emi_disable(struct clk *clk)
95 {
96 	u32 reg;
97 
98 	reg = __raw_readl(clk->enable_reg);
99 	reg &= ~(3 << clk->enable_shift);
100 	reg |= (1 << clk->enable_shift);
101 	__raw_writel(reg, clk->enable_reg);
102 }
103 
_clk_pll_set_rate(struct clk * clk,unsigned long rate)104 static int _clk_pll_set_rate(struct clk *clk, unsigned long rate)
105 {
106 	u32 reg;
107 	signed long pd = 1;	/* Pre-divider */
108 	signed long mfi;	/* Multiplication Factor (Integer part) */
109 	signed long mfn;	/* Multiplication Factor (Integer part) */
110 	signed long mfd;	/* Multiplication Factor (Denominator Part) */
111 	signed long tmp;
112 	u32 ref_freq = clk_get_rate(clk->parent);
113 
114 	while (((ref_freq / pd) * 10) > rate)
115 		pd++;
116 
117 	if ((ref_freq / pd) < PRE_DIV_MIN_FREQ)
118 		return -EINVAL;
119 
120 	/* the ref_freq/2 in the following is to round up */
121 	mfi = (((rate / 2) * pd) + (ref_freq / 2)) / ref_freq;
122 	if (mfi < 5 || mfi > 15)
123 		return -EINVAL;
124 
125 	/* pick a mfd value that will work
126 	 * then solve for mfn */
127 	mfd = ref_freq / 50000;
128 
129 	/*
130 	 *          pll_freq * pd * mfd
131 	 *   mfn = --------------------  -  (mfi * mfd)
132 	 *           2 * ref_freq
133 	 */
134 	/* the tmp/2 is for rounding */
135 	tmp = ref_freq / 10000;
136 	mfn =
137 	    ((((((rate / 2) + (tmp / 2)) / tmp) * pd) * mfd) / 10000) -
138 	    (mfi * mfd);
139 
140 	mfn = mfn & 0x3ff;
141 	pd--;
142 	mfd--;
143 
144 	/* Change the Pll value */
145 	reg = (mfi << MXC_CCM_PCTL_MFI_OFFSET) |
146 	    (mfn << MXC_CCM_PCTL_MFN_OFFSET) |
147 	    (mfd << MXC_CCM_PCTL_MFD_OFFSET) | (pd << MXC_CCM_PCTL_PD_OFFSET);
148 
149 	if (clk == &mcu_pll_clk)
150 		__raw_writel(reg, MXC_CCM_MPCTL);
151 	else if (clk == &usb_pll_clk)
152 		__raw_writel(reg, MXC_CCM_UPCTL);
153 	else if (clk == &serial_pll_clk)
154 		__raw_writel(reg, MXC_CCM_SRPCTL);
155 
156 	return 0;
157 }
158 
_clk_pll_get_rate(struct clk * clk)159 static unsigned long _clk_pll_get_rate(struct clk *clk)
160 {
161 	long mfi, mfn, mfd, pdf, ref_clk, mfn_abs;
162 	unsigned long reg, ccmr;
163 	s64 temp;
164 	unsigned int prcs;
165 
166 	ccmr = __raw_readl(MXC_CCM_CCMR);
167 	prcs = (ccmr & MXC_CCM_CCMR_PRCS_MASK) >> MXC_CCM_CCMR_PRCS_OFFSET;
168 	if (prcs == 0x1)
169 		ref_clk = CKIL_CLK_FREQ * 1024;
170 	else
171 		ref_clk = clk_get_rate(&ckih_clk);
172 
173 	if (clk == &mcu_pll_clk) {
174 		if ((ccmr & MXC_CCM_CCMR_MPE) == 0)
175 			return ref_clk;
176 		if ((ccmr & MXC_CCM_CCMR_MDS) != 0)
177 			return ref_clk;
178 		reg = __raw_readl(MXC_CCM_MPCTL);
179 	} else if (clk == &usb_pll_clk)
180 		reg = __raw_readl(MXC_CCM_UPCTL);
181 	else if (clk == &serial_pll_clk)
182 		reg = __raw_readl(MXC_CCM_SRPCTL);
183 	else {
184 		BUG();
185 		return 0;
186 	}
187 
188 	pdf = (reg & MXC_CCM_PCTL_PD_MASK) >> MXC_CCM_PCTL_PD_OFFSET;
189 	mfd = (reg & MXC_CCM_PCTL_MFD_MASK) >> MXC_CCM_PCTL_MFD_OFFSET;
190 	mfi = (reg & MXC_CCM_PCTL_MFI_MASK) >> MXC_CCM_PCTL_MFI_OFFSET;
191 	mfi = (mfi <= 5) ? 5 : mfi;
192 	mfn = mfn_abs = reg & MXC_CCM_PCTL_MFN_MASK;
193 
194 	if (mfn >= 0x200) {
195 		mfn |= 0xFFFFFE00;
196 		mfn_abs = -mfn;
197 	}
198 
199 	ref_clk *= 2;
200 	ref_clk /= pdf + 1;
201 
202 	temp = (u64) ref_clk * mfn_abs;
203 	do_div(temp, mfd + 1);
204 	if (mfn < 0)
205 		temp = -temp;
206 	temp = (ref_clk * mfi) + temp;
207 
208 	return temp;
209 }
210 
_clk_usb_pll_enable(struct clk * clk)211 static int _clk_usb_pll_enable(struct clk *clk)
212 {
213 	u32 reg;
214 
215 	reg = __raw_readl(MXC_CCM_CCMR);
216 	reg |= MXC_CCM_CCMR_UPE;
217 	__raw_writel(reg, MXC_CCM_CCMR);
218 
219 	/* No lock bit on MX31, so using max time from spec */
220 	udelay(80);
221 
222 	return 0;
223 }
224 
_clk_usb_pll_disable(struct clk * clk)225 static void _clk_usb_pll_disable(struct clk *clk)
226 {
227 	u32 reg;
228 
229 	reg = __raw_readl(MXC_CCM_CCMR);
230 	reg &= ~MXC_CCM_CCMR_UPE;
231 	__raw_writel(reg, MXC_CCM_CCMR);
232 }
233 
_clk_serial_pll_enable(struct clk * clk)234 static int _clk_serial_pll_enable(struct clk *clk)
235 {
236 	u32 reg;
237 
238 	reg = __raw_readl(MXC_CCM_CCMR);
239 	reg |= MXC_CCM_CCMR_SPE;
240 	__raw_writel(reg, MXC_CCM_CCMR);
241 
242 	/* No lock bit on MX31, so using max time from spec */
243 	udelay(80);
244 
245 	return 0;
246 }
247 
_clk_serial_pll_disable(struct clk * clk)248 static void _clk_serial_pll_disable(struct clk *clk)
249 {
250 	u32 reg;
251 
252 	reg = __raw_readl(MXC_CCM_CCMR);
253 	reg &= ~MXC_CCM_CCMR_SPE;
254 	__raw_writel(reg, MXC_CCM_CCMR);
255 }
256 
257 #define PDR0(mask, off) ((__raw_readl(MXC_CCM_PDR0) & mask) >> off)
258 #define PDR1(mask, off) ((__raw_readl(MXC_CCM_PDR1) & mask) >> off)
259 #define PDR2(mask, off) ((__raw_readl(MXC_CCM_PDR2) & mask) >> off)
260 
_clk_mcu_main_get_rate(struct clk * clk)261 static unsigned long _clk_mcu_main_get_rate(struct clk *clk)
262 {
263 	u32 pmcr0 = __raw_readl(MXC_CCM_PMCR0);
264 
265 	if ((pmcr0 & MXC_CCM_PMCR0_DFSUP1) == MXC_CCM_PMCR0_DFSUP1_SPLL)
266 		return clk_get_rate(&serial_pll_clk);
267 	else
268 		return clk_get_rate(&mcu_pll_clk);
269 }
270 
_clk_hclk_get_rate(struct clk * clk)271 static unsigned long _clk_hclk_get_rate(struct clk *clk)
272 {
273 	unsigned long max_pdf;
274 
275 	max_pdf = PDR0(MXC_CCM_PDR0_MAX_PODF_MASK,
276 		       MXC_CCM_PDR0_MAX_PODF_OFFSET);
277 	return clk_get_rate(clk->parent) / (max_pdf + 1);
278 }
279 
_clk_ipg_get_rate(struct clk * clk)280 static unsigned long _clk_ipg_get_rate(struct clk *clk)
281 {
282 	unsigned long ipg_pdf;
283 
284 	ipg_pdf = PDR0(MXC_CCM_PDR0_IPG_PODF_MASK,
285 		       MXC_CCM_PDR0_IPG_PODF_OFFSET);
286 	return clk_get_rate(clk->parent) / (ipg_pdf + 1);
287 }
288 
_clk_nfc_get_rate(struct clk * clk)289 static unsigned long _clk_nfc_get_rate(struct clk *clk)
290 {
291 	unsigned long nfc_pdf;
292 
293 	nfc_pdf = PDR0(MXC_CCM_PDR0_NFC_PODF_MASK,
294 		       MXC_CCM_PDR0_NFC_PODF_OFFSET);
295 	return clk_get_rate(clk->parent) / (nfc_pdf + 1);
296 }
297 
_clk_hsp_get_rate(struct clk * clk)298 static unsigned long _clk_hsp_get_rate(struct clk *clk)
299 {
300 	unsigned long hsp_pdf;
301 
302 	hsp_pdf = PDR0(MXC_CCM_PDR0_HSP_PODF_MASK,
303 		       MXC_CCM_PDR0_HSP_PODF_OFFSET);
304 	return clk_get_rate(clk->parent) / (hsp_pdf + 1);
305 }
306 
_clk_usb_get_rate(struct clk * clk)307 static unsigned long _clk_usb_get_rate(struct clk *clk)
308 {
309 	unsigned long usb_pdf, usb_prepdf;
310 
311 	usb_pdf = PDR1(MXC_CCM_PDR1_USB_PODF_MASK,
312 		       MXC_CCM_PDR1_USB_PODF_OFFSET);
313 	usb_prepdf = PDR1(MXC_CCM_PDR1_USB_PRDF_MASK,
314 			  MXC_CCM_PDR1_USB_PRDF_OFFSET);
315 	return clk_get_rate(clk->parent) / (usb_prepdf + 1) / (usb_pdf + 1);
316 }
317 
_clk_csi_get_rate(struct clk * clk)318 static unsigned long _clk_csi_get_rate(struct clk *clk)
319 {
320 	u32 reg, pre, post;
321 
322 	reg = __raw_readl(MXC_CCM_PDR0);
323 	pre = (reg & MXC_CCM_PDR0_CSI_PRDF_MASK) >>
324 	    MXC_CCM_PDR0_CSI_PRDF_OFFSET;
325 	pre++;
326 	post = (reg & MXC_CCM_PDR0_CSI_PODF_MASK) >>
327 	    MXC_CCM_PDR0_CSI_PODF_OFFSET;
328 	post++;
329 	return clk_get_rate(clk->parent) / (pre * post);
330 }
331 
_clk_csi_round_rate(struct clk * clk,unsigned long rate)332 static unsigned long _clk_csi_round_rate(struct clk *clk, unsigned long rate)
333 {
334 	u32 pre, post, parent = clk_get_rate(clk->parent);
335 	u32 div = parent / rate;
336 
337 	if (parent % rate)
338 		div++;
339 
340 	__calc_pre_post_dividers(div, &pre, &post);
341 
342 	return parent / (pre * post);
343 }
344 
_clk_csi_set_rate(struct clk * clk,unsigned long rate)345 static int _clk_csi_set_rate(struct clk *clk, unsigned long rate)
346 {
347 	u32 reg, div, pre, post, parent = clk_get_rate(clk->parent);
348 
349 	div = parent / rate;
350 
351 	if ((parent / div) != rate)
352 		return -EINVAL;
353 
354 	__calc_pre_post_dividers(div, &pre, &post);
355 
356 	/* Set CSI clock divider */
357 	reg = __raw_readl(MXC_CCM_PDR0) &
358 	    ~(MXC_CCM_PDR0_CSI_PODF_MASK | MXC_CCM_PDR0_CSI_PRDF_MASK);
359 	reg |= (post - 1) << MXC_CCM_PDR0_CSI_PODF_OFFSET;
360 	reg |= (pre - 1) << MXC_CCM_PDR0_CSI_PRDF_OFFSET;
361 	__raw_writel(reg, MXC_CCM_PDR0);
362 
363 	return 0;
364 }
365 
_clk_per_get_rate(struct clk * clk)366 static unsigned long _clk_per_get_rate(struct clk *clk)
367 {
368 	unsigned long per_pdf;
369 
370 	per_pdf = PDR0(MXC_CCM_PDR0_PER_PODF_MASK,
371 		       MXC_CCM_PDR0_PER_PODF_OFFSET);
372 	return clk_get_rate(clk->parent) / (per_pdf + 1);
373 }
374 
_clk_ssi1_get_rate(struct clk * clk)375 static unsigned long _clk_ssi1_get_rate(struct clk *clk)
376 {
377 	unsigned long ssi1_pdf, ssi1_prepdf;
378 
379 	ssi1_pdf = PDR1(MXC_CCM_PDR1_SSI1_PODF_MASK,
380 			MXC_CCM_PDR1_SSI1_PODF_OFFSET);
381 	ssi1_prepdf = PDR1(MXC_CCM_PDR1_SSI1_PRE_PODF_MASK,
382 			   MXC_CCM_PDR1_SSI1_PRE_PODF_OFFSET);
383 	return clk_get_rate(clk->parent) / (ssi1_prepdf + 1) / (ssi1_pdf + 1);
384 }
385 
_clk_ssi2_get_rate(struct clk * clk)386 static unsigned long _clk_ssi2_get_rate(struct clk *clk)
387 {
388 	unsigned long ssi2_pdf, ssi2_prepdf;
389 
390 	ssi2_pdf = PDR1(MXC_CCM_PDR1_SSI2_PODF_MASK,
391 			MXC_CCM_PDR1_SSI2_PODF_OFFSET);
392 	ssi2_prepdf = PDR1(MXC_CCM_PDR1_SSI2_PRE_PODF_MASK,
393 			   MXC_CCM_PDR1_SSI2_PRE_PODF_OFFSET);
394 	return clk_get_rate(clk->parent) / (ssi2_prepdf + 1) / (ssi2_pdf + 1);
395 }
396 
_clk_firi_get_rate(struct clk * clk)397 static unsigned long _clk_firi_get_rate(struct clk *clk)
398 {
399 	unsigned long firi_pdf, firi_prepdf;
400 
401 	firi_pdf = PDR1(MXC_CCM_PDR1_FIRI_PODF_MASK,
402 			MXC_CCM_PDR1_FIRI_PODF_OFFSET);
403 	firi_prepdf = PDR1(MXC_CCM_PDR1_FIRI_PRE_PODF_MASK,
404 			   MXC_CCM_PDR1_FIRI_PRE_PODF_OFFSET);
405 	return clk_get_rate(clk->parent) / (firi_prepdf + 1) / (firi_pdf + 1);
406 }
407 
_clk_firi_round_rate(struct clk * clk,unsigned long rate)408 static unsigned long _clk_firi_round_rate(struct clk *clk, unsigned long rate)
409 {
410 	u32 pre, post;
411 	u32 parent = clk_get_rate(clk->parent);
412 	u32 div = parent / rate;
413 
414 	if (parent % rate)
415 		div++;
416 
417 	__calc_pre_post_dividers(div, &pre, &post);
418 
419 	return parent / (pre * post);
420 
421 }
422 
_clk_firi_set_rate(struct clk * clk,unsigned long rate)423 static int _clk_firi_set_rate(struct clk *clk, unsigned long rate)
424 {
425 	u32 reg, div, pre, post, parent = clk_get_rate(clk->parent);
426 
427 	div = parent / rate;
428 
429 	if ((parent / div) != rate)
430 		return -EINVAL;
431 
432 	__calc_pre_post_dividers(div, &pre, &post);
433 
434 	/* Set FIRI clock divider */
435 	reg = __raw_readl(MXC_CCM_PDR1) &
436 	    ~(MXC_CCM_PDR1_FIRI_PODF_MASK | MXC_CCM_PDR1_FIRI_PRE_PODF_MASK);
437 	reg |= (pre - 1) << MXC_CCM_PDR1_FIRI_PRE_PODF_OFFSET;
438 	reg |= (post - 1) << MXC_CCM_PDR1_FIRI_PODF_OFFSET;
439 	__raw_writel(reg, MXC_CCM_PDR1);
440 
441 	return 0;
442 }
443 
_clk_mbx_get_rate(struct clk * clk)444 static unsigned long _clk_mbx_get_rate(struct clk *clk)
445 {
446 	return clk_get_rate(clk->parent) / 2;
447 }
448 
_clk_mstick1_get_rate(struct clk * clk)449 static unsigned long _clk_mstick1_get_rate(struct clk *clk)
450 {
451 	unsigned long msti_pdf;
452 
453 	msti_pdf = PDR2(MXC_CCM_PDR2_MST1_PDF_MASK,
454 			MXC_CCM_PDR2_MST1_PDF_OFFSET);
455 	return clk_get_rate(clk->parent) / (msti_pdf + 1);
456 }
457 
_clk_mstick2_get_rate(struct clk * clk)458 static unsigned long _clk_mstick2_get_rate(struct clk *clk)
459 {
460 	unsigned long msti_pdf;
461 
462 	msti_pdf = PDR2(MXC_CCM_PDR2_MST2_PDF_MASK,
463 			MXC_CCM_PDR2_MST2_PDF_OFFSET);
464 	return clk_get_rate(clk->parent) / (msti_pdf + 1);
465 }
466 
467 static unsigned long ckih_rate;
468 
clk_ckih_get_rate(struct clk * clk)469 static unsigned long clk_ckih_get_rate(struct clk *clk)
470 {
471 	return ckih_rate;
472 }
473 
474 static struct clk ckih_clk = {
475 	.name = "ckih",
476 	.get_rate = clk_ckih_get_rate,
477 };
478 
clk_ckil_get_rate(struct clk * clk)479 static unsigned long clk_ckil_get_rate(struct clk *clk)
480 {
481 	return CKIL_CLK_FREQ;
482 }
483 
484 static struct clk ckil_clk = {
485 	.name = "ckil",
486 	.get_rate = clk_ckil_get_rate,
487 };
488 
489 static struct clk mcu_pll_clk = {
490 	.name = "mcu_pll",
491 	.parent = &ckih_clk,
492 	.set_rate = _clk_pll_set_rate,
493 	.get_rate = _clk_pll_get_rate,
494 };
495 
496 static struct clk mcu_main_clk = {
497 	.name = "mcu_main_clk",
498 	.parent = &mcu_pll_clk,
499 	.get_rate = _clk_mcu_main_get_rate,
500 };
501 
502 static struct clk serial_pll_clk = {
503 	.name = "serial_pll",
504 	.parent = &ckih_clk,
505 	.set_rate = _clk_pll_set_rate,
506 	.get_rate = _clk_pll_get_rate,
507 	.enable = _clk_serial_pll_enable,
508 	.disable = _clk_serial_pll_disable,
509 };
510 
511 static struct clk usb_pll_clk = {
512 	.name = "usb_pll",
513 	.parent = &ckih_clk,
514 	.set_rate = _clk_pll_set_rate,
515 	.get_rate = _clk_pll_get_rate,
516 	.enable = _clk_usb_pll_enable,
517 	.disable = _clk_usb_pll_disable,
518 };
519 
520 static struct clk ahb_clk = {
521 	.name = "ahb_clk",
522 	.parent = &mcu_main_clk,
523 	.get_rate = _clk_hclk_get_rate,
524 };
525 
526 static struct clk per_clk = {
527 	.name = "per_clk",
528 	.parent = &usb_pll_clk,
529 	.get_rate = _clk_per_get_rate,
530 };
531 
532 static struct clk perclk_clk = {
533 	.name = "perclk_clk",
534 	.parent = &ipg_clk,
535 };
536 
537 static struct clk cspi_clk[] = {
538 	{
539 	 .name = "cspi_clk",
540 	 .id = 0,
541 	 .parent = &ipg_clk,
542 	 .enable = _clk_enable,
543 	 .enable_reg = MXC_CCM_CGR2,
544 	 .enable_shift = MXC_CCM_CGR2_CSPI1_OFFSET,
545 	 .disable = _clk_disable,},
546 	{
547 	 .name = "cspi_clk",
548 	 .id = 1,
549 	 .parent = &ipg_clk,
550 	 .enable = _clk_enable,
551 	 .enable_reg = MXC_CCM_CGR2,
552 	 .enable_shift = MXC_CCM_CGR2_CSPI2_OFFSET,
553 	 .disable = _clk_disable,},
554 	{
555 	 .name = "cspi_clk",
556 	 .id = 2,
557 	 .parent = &ipg_clk,
558 	 .enable = _clk_enable,
559 	 .enable_reg = MXC_CCM_CGR0,
560 	 .enable_shift = MXC_CCM_CGR0_CSPI3_OFFSET,
561 	 .disable = _clk_disable,},
562 };
563 
564 static struct clk ipg_clk = {
565 	.name = "ipg_clk",
566 	.parent = &ahb_clk,
567 	.get_rate = _clk_ipg_get_rate,
568 };
569 
570 static struct clk emi_clk = {
571 	.name = "emi_clk",
572 	.parent = &ahb_clk,
573 	.enable = _clk_enable,
574 	.enable_reg = MXC_CCM_CGR2,
575 	.enable_shift = MXC_CCM_CGR2_EMI_OFFSET,
576 	.disable = _clk_emi_disable,
577 };
578 
579 static struct clk gpt_clk = {
580 	.name = "gpt_clk",
581 	.parent = &perclk_clk,
582 	.enable = _clk_enable,
583 	.enable_reg = MXC_CCM_CGR0,
584 	.enable_shift = MXC_CCM_CGR0_GPT_OFFSET,
585 	.disable = _clk_disable,
586 };
587 
588 static struct clk pwm_clk = {
589 	.name = "pwm_clk",
590 	.parent = &perclk_clk,
591 	.enable = _clk_enable,
592 	.enable_reg = MXC_CCM_CGR0,
593 	.enable_shift = MXC_CCM_CGR1_PWM_OFFSET,
594 	.disable = _clk_disable,
595 };
596 
597 static struct clk epit_clk[] = {
598 	{
599 	 .name = "epit_clk",
600 	 .id = 0,
601 	 .parent = &perclk_clk,
602 	 .enable = _clk_enable,
603 	 .enable_reg = MXC_CCM_CGR0,
604 	 .enable_shift = MXC_CCM_CGR0_EPIT1_OFFSET,
605 	 .disable = _clk_disable,},
606 	{
607 	 .name = "epit_clk",
608 	 .id = 1,
609 	 .parent = &perclk_clk,
610 	 .enable = _clk_enable,
611 	 .enable_reg = MXC_CCM_CGR0,
612 	 .enable_shift = MXC_CCM_CGR0_EPIT2_OFFSET,
613 	 .disable = _clk_disable,},
614 };
615 
616 static struct clk nfc_clk = {
617 	.name = "nfc_clk",
618 	.parent = &ahb_clk,
619 	.get_rate = _clk_nfc_get_rate,
620 };
621 
622 static struct clk scc_clk = {
623 	.name = "scc_clk",
624 	.parent = &ipg_clk,
625 };
626 
627 static struct clk ipu_clk = {
628 	.name = "ipu_clk",
629 	.parent = &mcu_main_clk,
630 	.get_rate = _clk_hsp_get_rate,
631 	.enable = _clk_enable,
632 	.enable_reg = MXC_CCM_CGR1,
633 	.enable_shift = MXC_CCM_CGR1_IPU_OFFSET,
634 	.disable = _clk_disable,
635 };
636 
637 static struct clk kpp_clk = {
638 	.name = "kpp_clk",
639 	.parent = &ipg_clk,
640 	.enable = _clk_enable,
641 	.enable_reg = MXC_CCM_CGR1,
642 	.enable_shift = MXC_CCM_CGR1_KPP_OFFSET,
643 	.disable = _clk_disable,
644 };
645 
646 static struct clk wdog_clk = {
647 	.name = "wdog_clk",
648 	.parent = &ipg_clk,
649 	.enable = _clk_enable,
650 	.enable_reg = MXC_CCM_CGR1,
651 	.enable_shift = MXC_CCM_CGR1_WDOG_OFFSET,
652 	.disable = _clk_disable,
653 };
654 static struct clk rtc_clk = {
655 	.name = "rtc_clk",
656 	.parent = &ipg_clk,
657 	.enable = _clk_enable,
658 	.enable_reg = MXC_CCM_CGR1,
659 	.enable_shift = MXC_CCM_CGR1_RTC_OFFSET,
660 	.disable = _clk_disable,
661 };
662 
663 static struct clk usb_clk[] = {
664 	{
665 	 .name = "usb_clk",
666 	 .parent = &usb_pll_clk,
667 	 .get_rate = _clk_usb_get_rate,},
668 	{
669 	 .name = "usb_ahb_clk",
670 	 .parent = &ahb_clk,
671 	 .enable = _clk_enable,
672 	 .enable_reg = MXC_CCM_CGR1,
673 	 .enable_shift = MXC_CCM_CGR1_USBOTG_OFFSET,
674 	 .disable = _clk_disable,},
675 };
676 
677 static struct clk csi_clk = {
678 	.name = "csi_clk",
679 	.parent = &serial_pll_clk,
680 	.get_rate = _clk_csi_get_rate,
681 	.round_rate = _clk_csi_round_rate,
682 	.set_rate = _clk_csi_set_rate,
683 	.enable = _clk_enable,
684 	.enable_reg = MXC_CCM_CGR1,
685 	.enable_shift = MXC_CCM_CGR1_CSI_OFFSET,
686 	.disable = _clk_disable,
687 };
688 
689 static struct clk uart_clk[] = {
690 	{
691 	 .name = "uart_clk",
692 	 .id = 0,
693 	 .parent = &perclk_clk,
694 	 .enable = _clk_enable,
695 	 .enable_reg = MXC_CCM_CGR0,
696 	 .enable_shift = MXC_CCM_CGR0_UART1_OFFSET,
697 	 .disable = _clk_disable,},
698 	{
699 	 .name = "uart_clk",
700 	 .id = 1,
701 	 .parent = &perclk_clk,
702 	 .enable = _clk_enable,
703 	 .enable_reg = MXC_CCM_CGR0,
704 	 .enable_shift = MXC_CCM_CGR0_UART2_OFFSET,
705 	 .disable = _clk_disable,},
706 	{
707 	 .name = "uart_clk",
708 	 .id = 2,
709 	 .parent = &perclk_clk,
710 	 .enable = _clk_enable,
711 	 .enable_reg = MXC_CCM_CGR1,
712 	 .enable_shift = MXC_CCM_CGR1_UART3_OFFSET,
713 	 .disable = _clk_disable,},
714 	{
715 	 .name = "uart_clk",
716 	 .id = 3,
717 	 .parent = &perclk_clk,
718 	 .enable = _clk_enable,
719 	 .enable_reg = MXC_CCM_CGR1,
720 	 .enable_shift = MXC_CCM_CGR1_UART4_OFFSET,
721 	 .disable = _clk_disable,},
722 	{
723 	 .name = "uart_clk",
724 	 .id = 4,
725 	 .parent = &perclk_clk,
726 	 .enable = _clk_enable,
727 	 .enable_reg = MXC_CCM_CGR1,
728 	 .enable_shift = MXC_CCM_CGR1_UART5_OFFSET,
729 	 .disable = _clk_disable,},
730 };
731 
732 static struct clk i2c_clk[] = {
733 	{
734 	 .name = "i2c_clk",
735 	 .id = 0,
736 	 .parent = &perclk_clk,
737 	 .enable = _clk_enable,
738 	 .enable_reg = MXC_CCM_CGR0,
739 	 .enable_shift = MXC_CCM_CGR0_I2C1_OFFSET,
740 	 .disable = _clk_disable,},
741 	{
742 	 .name = "i2c_clk",
743 	 .id = 1,
744 	 .parent = &perclk_clk,
745 	 .enable = _clk_enable,
746 	 .enable_reg = MXC_CCM_CGR0,
747 	 .enable_shift = MXC_CCM_CGR0_I2C2_OFFSET,
748 	 .disable = _clk_disable,},
749 	{
750 	 .name = "i2c_clk",
751 	 .id = 2,
752 	 .parent = &perclk_clk,
753 	 .enable = _clk_enable,
754 	 .enable_reg = MXC_CCM_CGR0,
755 	 .enable_shift = MXC_CCM_CGR0_I2C3_OFFSET,
756 	 .disable = _clk_disable,},
757 };
758 
759 static struct clk owire_clk = {
760 	.name = "owire_clk",
761 	.parent = &perclk_clk,
762 	.enable_reg = MXC_CCM_CGR1,
763 	.enable_shift = MXC_CCM_CGR1_OWIRE_OFFSET,
764 	.enable = _clk_enable,
765 	.disable = _clk_disable,
766 };
767 
768 static struct clk sdhc_clk[] = {
769 	{
770 	 .name = "sdhc_clk",
771 	 .id = 0,
772 	 .parent = &perclk_clk,
773 	 .enable = _clk_enable,
774 	 .enable_reg = MXC_CCM_CGR0,
775 	 .enable_shift = MXC_CCM_CGR0_SD_MMC1_OFFSET,
776 	 .disable = _clk_disable,},
777 	{
778 	 .name = "sdhc_clk",
779 	 .id = 1,
780 	 .parent = &perclk_clk,
781 	 .enable = _clk_enable,
782 	 .enable_reg = MXC_CCM_CGR0,
783 	 .enable_shift = MXC_CCM_CGR0_SD_MMC2_OFFSET,
784 	 .disable = _clk_disable,},
785 };
786 
787 static struct clk ssi_clk[] = {
788 	{
789 	 .name = "ssi_clk",
790 	 .parent = &serial_pll_clk,
791 	 .get_rate = _clk_ssi1_get_rate,
792 	 .enable = _clk_enable,
793 	 .enable_reg = MXC_CCM_CGR0,
794 	 .enable_shift = MXC_CCM_CGR0_SSI1_OFFSET,
795 	 .disable = _clk_disable,},
796 	{
797 	 .name = "ssi_clk",
798 	 .id = 1,
799 	 .parent = &serial_pll_clk,
800 	 .get_rate = _clk_ssi2_get_rate,
801 	 .enable = _clk_enable,
802 	 .enable_reg = MXC_CCM_CGR2,
803 	 .enable_shift = MXC_CCM_CGR2_SSI2_OFFSET,
804 	 .disable = _clk_disable,},
805 };
806 
807 static struct clk firi_clk = {
808 	.name = "firi_clk",
809 	.parent = &usb_pll_clk,
810 	.round_rate = _clk_firi_round_rate,
811 	.set_rate = _clk_firi_set_rate,
812 	.get_rate = _clk_firi_get_rate,
813 	.enable = _clk_enable,
814 	.enable_reg = MXC_CCM_CGR2,
815 	.enable_shift = MXC_CCM_CGR2_FIRI_OFFSET,
816 	.disable = _clk_disable,
817 };
818 
819 static struct clk ata_clk = {
820 	.name = "ata_clk",
821 	.parent = &ipg_clk,
822 	.enable = _clk_enable,
823 	.enable_reg = MXC_CCM_CGR0,
824 	.enable_shift = MXC_CCM_CGR0_ATA_OFFSET,
825 	.disable = _clk_disable,
826 };
827 
828 static struct clk mbx_clk = {
829 	.name = "mbx_clk",
830 	.parent = &ahb_clk,
831 	.enable = _clk_enable,
832 	.enable_reg = MXC_CCM_CGR2,
833 	.enable_shift = MXC_CCM_CGR2_GACC_OFFSET,
834 	.get_rate = _clk_mbx_get_rate,
835 };
836 
837 static struct clk vpu_clk = {
838 	.name = "vpu_clk",
839 	.parent = &ahb_clk,
840 	.enable = _clk_enable,
841 	.enable_reg = MXC_CCM_CGR2,
842 	.enable_shift = MXC_CCM_CGR2_GACC_OFFSET,
843 	.get_rate = _clk_mbx_get_rate,
844 };
845 
846 static struct clk rtic_clk = {
847 	.name = "rtic_clk",
848 	.parent = &ahb_clk,
849 	.enable = _clk_enable,
850 	.enable_reg = MXC_CCM_CGR2,
851 	.enable_shift = MXC_CCM_CGR2_RTIC_OFFSET,
852 	.disable = _clk_disable,
853 };
854 
855 static struct clk rng_clk = {
856 	.name = "rng_clk",
857 	.parent = &ipg_clk,
858 	.enable = _clk_enable,
859 	.enable_reg = MXC_CCM_CGR0,
860 	.enable_shift = MXC_CCM_CGR0_RNG_OFFSET,
861 	.disable = _clk_disable,
862 };
863 
864 static struct clk sdma_clk[] = {
865 	{
866 	 .name = "sdma_ahb_clk",
867 	 .parent = &ahb_clk,
868 	 .enable = _clk_enable,
869 	 .enable_reg = MXC_CCM_CGR0,
870 	 .enable_shift = MXC_CCM_CGR0_SDMA_OFFSET,
871 	 .disable = _clk_disable,},
872 	{
873 	 .name = "sdma_ipg_clk",
874 	 .parent = &ipg_clk,}
875 };
876 
877 static struct clk mpeg4_clk = {
878 	.name = "mpeg4_clk",
879 	.parent = &ahb_clk,
880 	.enable = _clk_enable,
881 	.enable_reg = MXC_CCM_CGR1,
882 	.enable_shift = MXC_CCM_CGR1_HANTRO_OFFSET,
883 	.disable = _clk_disable,
884 };
885 
886 static struct clk vl2cc_clk = {
887 	.name = "vl2cc_clk",
888 	.parent = &ahb_clk,
889 	.enable = _clk_enable,
890 	.enable_reg = MXC_CCM_CGR1,
891 	.enable_shift = MXC_CCM_CGR1_HANTRO_OFFSET,
892 	.disable = _clk_disable,
893 };
894 
895 static struct clk mstick_clk[] = {
896 	{
897 	 .name = "mstick_clk",
898 	 .id = 0,
899 	 .parent = &usb_pll_clk,
900 	 .get_rate = _clk_mstick1_get_rate,
901 	 .enable = _clk_enable,
902 	 .enable_reg = MXC_CCM_CGR1,
903 	 .enable_shift = MXC_CCM_CGR1_MEMSTICK1_OFFSET,
904 	 .disable = _clk_disable,},
905 	{
906 	 .name = "mstick_clk",
907 	 .id = 1,
908 	 .parent = &usb_pll_clk,
909 	 .get_rate = _clk_mstick2_get_rate,
910 	 .enable = _clk_enable,
911 	 .enable_reg = MXC_CCM_CGR1,
912 	 .enable_shift = MXC_CCM_CGR1_MEMSTICK2_OFFSET,
913 	 .disable = _clk_disable,},
914 };
915 
916 static struct clk iim_clk = {
917 	.name = "iim_clk",
918 	.parent = &ipg_clk,
919 	.enable = _clk_enable,
920 	.enable_reg = MXC_CCM_CGR0,
921 	.enable_shift = MXC_CCM_CGR0_IIM_OFFSET,
922 	.disable = _clk_disable,
923 };
924 
_clk_cko1_round_rate(struct clk * clk,unsigned long rate)925 static unsigned long _clk_cko1_round_rate(struct clk *clk, unsigned long rate)
926 {
927 	u32 div, parent = clk_get_rate(clk->parent);
928 
929 	div = parent / rate;
930 	if (parent % rate)
931 		div++;
932 
933 	if (div > 8)
934 		div = 16;
935 	else if (div > 4)
936 		div = 8;
937 	else if (div > 2)
938 		div = 4;
939 
940 	return parent / div;
941 }
942 
_clk_cko1_set_rate(struct clk * clk,unsigned long rate)943 static int _clk_cko1_set_rate(struct clk *clk, unsigned long rate)
944 {
945 	u32 reg, div, parent = clk_get_rate(clk->parent);
946 
947 	div = parent / rate;
948 
949 	if (div == 16)
950 		div = 4;
951 	else if (div == 8)
952 		div = 3;
953 	else if (div == 4)
954 		div = 2;
955 	else if (div == 2)
956 		div = 1;
957 	else if (div == 1)
958 		div = 0;
959 	else
960 		return -EINVAL;
961 
962 	reg = __raw_readl(MXC_CCM_COSR) & ~MXC_CCM_COSR_CLKOUTDIV_MASK;
963 	reg |= div << MXC_CCM_COSR_CLKOUTDIV_OFFSET;
964 	__raw_writel(reg, MXC_CCM_COSR);
965 
966 	return 0;
967 }
968 
_clk_cko1_get_rate(struct clk * clk)969 static unsigned long _clk_cko1_get_rate(struct clk *clk)
970 {
971 	u32 div;
972 
973 	div = __raw_readl(MXC_CCM_COSR) & MXC_CCM_COSR_CLKOUTDIV_MASK >>
974 	    MXC_CCM_COSR_CLKOUTDIV_OFFSET;
975 
976 	return clk_get_rate(clk->parent) / (1 << div);
977 }
978 
_clk_cko1_set_parent(struct clk * clk,struct clk * parent)979 static int _clk_cko1_set_parent(struct clk *clk, struct clk *parent)
980 {
981 	u32 reg;
982 
983 	reg = __raw_readl(MXC_CCM_COSR) & ~MXC_CCM_COSR_CLKOSEL_MASK;
984 
985 	if (parent == &mcu_main_clk)
986 		reg |= 0 << MXC_CCM_COSR_CLKOSEL_OFFSET;
987 	else if (parent == &ipg_clk)
988 		reg |= 1 << MXC_CCM_COSR_CLKOSEL_OFFSET;
989 	else if (parent == &usb_pll_clk)
990 		reg |= 2 << MXC_CCM_COSR_CLKOSEL_OFFSET;
991 	else if (parent == mcu_main_clk.parent)
992 		reg |= 3 << MXC_CCM_COSR_CLKOSEL_OFFSET;
993 	else if (parent == &ahb_clk)
994 		reg |= 5 << MXC_CCM_COSR_CLKOSEL_OFFSET;
995 	else if (parent == &serial_pll_clk)
996 		reg |= 7 << MXC_CCM_COSR_CLKOSEL_OFFSET;
997 	else if (parent == &ckih_clk)
998 		reg |= 8 << MXC_CCM_COSR_CLKOSEL_OFFSET;
999 	else if (parent == &emi_clk)
1000 		reg |= 9 << MXC_CCM_COSR_CLKOSEL_OFFSET;
1001 	else if (parent == &ipu_clk)
1002 		reg |= 0xA << MXC_CCM_COSR_CLKOSEL_OFFSET;
1003 	else if (parent == &nfc_clk)
1004 		reg |= 0xB << MXC_CCM_COSR_CLKOSEL_OFFSET;
1005 	else if (parent == &uart_clk[0])
1006 		reg |= 0xC << MXC_CCM_COSR_CLKOSEL_OFFSET;
1007 	else
1008 		return -EINVAL;
1009 
1010 	__raw_writel(reg, MXC_CCM_COSR);
1011 
1012 	return 0;
1013 }
1014 
_clk_cko1_enable(struct clk * clk)1015 static int _clk_cko1_enable(struct clk *clk)
1016 {
1017 	u32 reg;
1018 
1019 	reg = __raw_readl(MXC_CCM_COSR) | MXC_CCM_COSR_CLKOEN;
1020 	__raw_writel(reg, MXC_CCM_COSR);
1021 
1022 	return 0;
1023 }
1024 
_clk_cko1_disable(struct clk * clk)1025 static void _clk_cko1_disable(struct clk *clk)
1026 {
1027 	u32 reg;
1028 
1029 	reg = __raw_readl(MXC_CCM_COSR) & ~MXC_CCM_COSR_CLKOEN;
1030 	__raw_writel(reg, MXC_CCM_COSR);
1031 }
1032 
1033 static struct clk cko1_clk = {
1034 	.name = "cko1_clk",
1035 	.get_rate = _clk_cko1_get_rate,
1036 	.set_rate = _clk_cko1_set_rate,
1037 	.round_rate = _clk_cko1_round_rate,
1038 	.set_parent = _clk_cko1_set_parent,
1039 	.enable = _clk_cko1_enable,
1040 	.disable = _clk_cko1_disable,
1041 };
1042 
1043 static struct clk *mxc_clks[] = {
1044 	&ckih_clk,
1045 	&ckil_clk,
1046 	&mcu_pll_clk,
1047 	&usb_pll_clk,
1048 	&serial_pll_clk,
1049 	&mcu_main_clk,
1050 	&ahb_clk,
1051 	&per_clk,
1052 	&perclk_clk,
1053 	&cko1_clk,
1054 	&emi_clk,
1055 	&cspi_clk[0],
1056 	&cspi_clk[1],
1057 	&cspi_clk[2],
1058 	&ipg_clk,
1059 	&gpt_clk,
1060 	&pwm_clk,
1061 	&wdog_clk,
1062 	&rtc_clk,
1063 	&epit_clk[0],
1064 	&epit_clk[1],
1065 	&nfc_clk,
1066 	&ipu_clk,
1067 	&kpp_clk,
1068 	&usb_clk[0],
1069 	&usb_clk[1],
1070 	&csi_clk,
1071 	&uart_clk[0],
1072 	&uart_clk[1],
1073 	&uart_clk[2],
1074 	&uart_clk[3],
1075 	&uart_clk[4],
1076 	&i2c_clk[0],
1077 	&i2c_clk[1],
1078 	&i2c_clk[2],
1079 	&owire_clk,
1080 	&sdhc_clk[0],
1081 	&sdhc_clk[1],
1082 	&ssi_clk[0],
1083 	&ssi_clk[1],
1084 	&firi_clk,
1085 	&ata_clk,
1086 	&rtic_clk,
1087 	&rng_clk,
1088 	&sdma_clk[0],
1089 	&sdma_clk[1],
1090 	&mstick_clk[0],
1091 	&mstick_clk[1],
1092 	&scc_clk,
1093 	&iim_clk,
1094 };
1095 
mxc_clocks_init(unsigned long fref)1096 int __init mxc_clocks_init(unsigned long fref)
1097 {
1098 	u32 reg;
1099 	struct clk **clkp;
1100 
1101 	ckih_rate = fref;
1102 
1103 	for (clkp = mxc_clks; clkp < mxc_clks + ARRAY_SIZE(mxc_clks); clkp++)
1104 		clk_register(*clkp);
1105 
1106 	if (cpu_is_mx31()) {
1107 		clk_register(&mpeg4_clk);
1108 		clk_register(&mbx_clk);
1109 	} else {
1110 		clk_register(&vpu_clk);
1111 		clk_register(&vl2cc_clk);
1112 	}
1113 
1114 	/* Turn off all possible clocks */
1115 	__raw_writel(MXC_CCM_CGR0_GPT_MASK, MXC_CCM_CGR0);
1116 	__raw_writel(0, MXC_CCM_CGR1);
1117 
1118 	__raw_writel(MXC_CCM_CGR2_EMI_MASK |
1119 		     MXC_CCM_CGR2_IPMUX1_MASK |
1120 		     MXC_CCM_CGR2_IPMUX2_MASK |
1121 		     MXC_CCM_CGR2_MXCCLKENSEL_MASK |	/* for MX32 */
1122 		     MXC_CCM_CGR2_CHIKCAMPEN_MASK |	/* for MX32 */
1123 		     MXC_CCM_CGR2_OVRVPUBUSY_MASK |	/* for MX32 */
1124 		     1 << 27 | 1 << 28, /* Bit 27 and 28 are not defined for
1125 					   MX32, but still required to be set */
1126 		     MXC_CCM_CGR2);
1127 
1128 	clk_disable(&cko1_clk);
1129 	clk_disable(&usb_pll_clk);
1130 
1131 	pr_info("Clock input source is %ld\n", clk_get_rate(&ckih_clk));
1132 
1133 	clk_enable(&gpt_clk);
1134 	clk_enable(&emi_clk);
1135 	clk_enable(&iim_clk);
1136 
1137 	clk_enable(&serial_pll_clk);
1138 
1139 	if (mx31_revision() >= CHIP_REV_2_0) {
1140 		reg = __raw_readl(MXC_CCM_PMCR1);
1141 		/* No PLL restart on DVFS switch; enable auto EMI handshake */
1142 		reg |= MXC_CCM_PMCR1_PLLRDIS | MXC_CCM_PMCR1_EMIRQ_EN;
1143 		__raw_writel(reg, MXC_CCM_PMCR1);
1144 	}
1145 
1146 	return 0;
1147 }
1148 
1149