• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright 2004-2007 Freescale Semiconductor, Inc. All Rights Reserved.
3  * Copyright 2008 Juergen Beisert, 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/clk.h>
21 #include <linux/io.h>
22 #include <linux/module.h>
23 #include <linux/spinlock.h>
24 
25 #include <mach/clock.h>
26 #include <mach/common.h>
27 #include <asm/div64.h>
28 
29 #include "crm_regs.h"
30 
31 static struct clk ckil_clk;
32 static struct clk mpll_clk;
33 static struct clk mpll_main_clk[];
34 static struct clk spll_clk;
35 
_clk_enable(struct clk * clk)36 static int _clk_enable(struct clk *clk)
37 {
38 	unsigned long reg;
39 
40 	reg = __raw_readl(clk->enable_reg);
41 	reg |= 1 << clk->enable_shift;
42 	__raw_writel(reg, clk->enable_reg);
43 
44 	return 0;
45 }
46 
_clk_disable(struct clk * clk)47 static void _clk_disable(struct clk *clk)
48 {
49 	unsigned long reg;
50 
51 	reg = __raw_readl(clk->enable_reg);
52 	reg &= ~(1 << clk->enable_shift);
53 	__raw_writel(reg, clk->enable_reg);
54 }
55 
_clk_spll_enable(struct clk * clk)56 static int _clk_spll_enable(struct clk *clk)
57 {
58 	unsigned long reg;
59 
60 	reg = __raw_readl(CCM_CSCR);
61 	reg |= CCM_CSCR_SPEN;
62 	__raw_writel(reg, CCM_CSCR);
63 
64 	while ((__raw_readl(CCM_SPCTL1) & CCM_SPCTL1_LF) == 0)
65 		;
66 
67 	return 0;
68 }
69 
_clk_spll_disable(struct clk * clk)70 static void _clk_spll_disable(struct clk *clk)
71 {
72 	unsigned long reg;
73 
74 	reg = __raw_readl(CCM_CSCR);
75 	reg &= ~CCM_CSCR_SPEN;
76 	__raw_writel(reg, CCM_CSCR);
77 }
78 
_clk_pccr01_enable(unsigned long mask0,unsigned long mask1)79 static void _clk_pccr01_enable(unsigned long mask0, unsigned long mask1)
80 {
81 	unsigned long reg;
82 
83 	reg = __raw_readl(CCM_PCCR0);
84 	reg |= mask0;
85 	__raw_writel(reg, CCM_PCCR0);
86 
87 	reg = __raw_readl(CCM_PCCR1);
88 	reg |= mask1;
89 	__raw_writel(reg, CCM_PCCR1);
90 
91 }
92 
_clk_pccr01_disable(unsigned long mask0,unsigned long mask1)93 static void _clk_pccr01_disable(unsigned long mask0, unsigned long mask1)
94 {
95 	unsigned long reg;
96 
97 	reg = __raw_readl(CCM_PCCR0);
98 	reg &= ~mask0;
99 	__raw_writel(reg, CCM_PCCR0);
100 
101 	reg = __raw_readl(CCM_PCCR1);
102 	reg &= ~mask1;
103 	__raw_writel(reg, CCM_PCCR1);
104 }
105 
_clk_pccr10_enable(unsigned long mask1,unsigned long mask0)106 static void _clk_pccr10_enable(unsigned long mask1, unsigned long mask0)
107 {
108 	unsigned long reg;
109 
110 	reg = __raw_readl(CCM_PCCR1);
111 	reg |= mask1;
112 	__raw_writel(reg, CCM_PCCR1);
113 
114 	reg = __raw_readl(CCM_PCCR0);
115 	reg |= mask0;
116 	__raw_writel(reg, CCM_PCCR0);
117 }
118 
_clk_pccr10_disable(unsigned long mask1,unsigned long mask0)119 static void _clk_pccr10_disable(unsigned long mask1, unsigned long mask0)
120 {
121 	unsigned long reg;
122 
123 	reg = __raw_readl(CCM_PCCR1);
124 	reg &= ~mask1;
125 	__raw_writel(reg, CCM_PCCR1);
126 
127 	reg = __raw_readl(CCM_PCCR0);
128 	reg &= ~mask0;
129 	__raw_writel(reg, CCM_PCCR0);
130 }
131 
_clk_dma_enable(struct clk * clk)132 static int _clk_dma_enable(struct clk *clk)
133 {
134 	_clk_pccr01_enable(CCM_PCCR0_DMA_MASK, CCM_PCCR1_HCLK_DMA_MASK);
135 
136 	return 0;
137 }
138 
_clk_dma_disable(struct clk * clk)139 static void _clk_dma_disable(struct clk *clk)
140 {
141 	_clk_pccr01_disable(CCM_PCCR0_DMA_MASK, CCM_PCCR1_HCLK_DMA_MASK);
142 }
143 
_clk_rtic_enable(struct clk * clk)144 static int _clk_rtic_enable(struct clk *clk)
145 {
146 	_clk_pccr01_enable(CCM_PCCR0_RTIC_MASK, CCM_PCCR1_HCLK_RTIC_MASK);
147 
148 	return 0;
149 }
150 
_clk_rtic_disable(struct clk * clk)151 static void _clk_rtic_disable(struct clk *clk)
152 {
153 	_clk_pccr01_disable(CCM_PCCR0_RTIC_MASK, CCM_PCCR1_HCLK_RTIC_MASK);
154 }
155 
_clk_emma_enable(struct clk * clk)156 static int _clk_emma_enable(struct clk *clk)
157 {
158 	_clk_pccr01_enable(CCM_PCCR0_EMMA_MASK, CCM_PCCR1_HCLK_EMMA_MASK);
159 
160 	return 0;
161 }
162 
_clk_emma_disable(struct clk * clk)163 static void _clk_emma_disable(struct clk *clk)
164 {
165 	_clk_pccr01_disable(CCM_PCCR0_EMMA_MASK, CCM_PCCR1_HCLK_EMMA_MASK);
166 }
167 
_clk_slcdc_enable(struct clk * clk)168 static int _clk_slcdc_enable(struct clk *clk)
169 {
170 	_clk_pccr01_enable(CCM_PCCR0_SLCDC_MASK, CCM_PCCR1_HCLK_SLCDC_MASK);
171 
172 	return 0;
173 }
174 
_clk_slcdc_disable(struct clk * clk)175 static void _clk_slcdc_disable(struct clk *clk)
176 {
177 	_clk_pccr01_disable(CCM_PCCR0_SLCDC_MASK, CCM_PCCR1_HCLK_SLCDC_MASK);
178 }
179 
_clk_fec_enable(struct clk * clk)180 static int _clk_fec_enable(struct clk *clk)
181 {
182 	_clk_pccr01_enable(CCM_PCCR0_FEC_MASK, CCM_PCCR1_HCLK_FEC_MASK);
183 
184 	return 0;
185 }
186 
_clk_fec_disable(struct clk * clk)187 static void _clk_fec_disable(struct clk *clk)
188 {
189 	_clk_pccr01_disable(CCM_PCCR0_FEC_MASK, CCM_PCCR1_HCLK_FEC_MASK);
190 }
191 
_clk_vpu_enable(struct clk * clk)192 static int _clk_vpu_enable(struct clk *clk)
193 {
194 	unsigned long reg;
195 
196 	reg = __raw_readl(CCM_PCCR1);
197 	reg |= CCM_PCCR1_VPU_BAUD_MASK | CCM_PCCR1_HCLK_VPU_MASK;
198 	__raw_writel(reg, CCM_PCCR1);
199 
200 	return 0;
201 }
202 
_clk_vpu_disable(struct clk * clk)203 static void _clk_vpu_disable(struct clk *clk)
204 {
205 	unsigned long reg;
206 
207 	reg = __raw_readl(CCM_PCCR1);
208 	reg &= ~(CCM_PCCR1_VPU_BAUD_MASK | CCM_PCCR1_HCLK_VPU_MASK);
209 	__raw_writel(reg, CCM_PCCR1);
210 }
211 
_clk_sahara2_enable(struct clk * clk)212 static int _clk_sahara2_enable(struct clk *clk)
213 {
214 	_clk_pccr01_enable(CCM_PCCR0_SAHARA_MASK, CCM_PCCR1_HCLK_SAHARA_MASK);
215 
216 	return 0;
217 }
218 
_clk_sahara2_disable(struct clk * clk)219 static void _clk_sahara2_disable(struct clk *clk)
220 {
221 	_clk_pccr01_disable(CCM_PCCR0_SAHARA_MASK, CCM_PCCR1_HCLK_SAHARA_MASK);
222 }
223 
_clk_mstick1_enable(struct clk * clk)224 static int _clk_mstick1_enable(struct clk *clk)
225 {
226 	_clk_pccr10_enable(CCM_PCCR1_MSHC_BAUD_MASK, CCM_PCCR0_MSHC_MASK);
227 
228 	return 0;
229 }
230 
_clk_mstick1_disable(struct clk * clk)231 static void _clk_mstick1_disable(struct clk *clk)
232 {
233 	_clk_pccr10_disable(CCM_PCCR1_MSHC_BAUD_MASK, CCM_PCCR0_MSHC_MASK);
234 }
235 
236 #define CSCR() (__raw_readl(CCM_CSCR))
237 #define PCDR0() (__raw_readl(CCM_PCDR0))
238 #define PCDR1() (__raw_readl(CCM_PCDR1))
239 
_clk_cpu_set_parent(struct clk * clk,struct clk * parent)240 static int _clk_cpu_set_parent(struct clk *clk, struct clk *parent)
241 {
242 	int cscr = CSCR();
243 
244 	if (clk->parent == parent)
245 		return 0;
246 
247 	if (mx27_revision() >= CHIP_REV_2_0) {
248 		if (parent == &mpll_main_clk[0]) {
249 			cscr |= CCM_CSCR_ARM_SRC;
250 		} else {
251 			if (parent == &mpll_main_clk[1])
252 				cscr &= ~CCM_CSCR_ARM_SRC;
253 			else
254 				return -EINVAL;
255 		}
256 		__raw_writel(cscr, CCM_CSCR);
257 	} else
258 		return -ENODEV;
259 
260 	clk->parent = parent;
261 	return 0;
262 }
263 
_clk_cpu_round_rate(struct clk * clk,unsigned long rate)264 static unsigned long _clk_cpu_round_rate(struct clk *clk, unsigned long rate)
265 {
266 	int div;
267 	unsigned long parent_rate;
268 
269 	parent_rate = clk_get_rate(clk->parent);
270 
271 	div = parent_rate / rate;
272 	if (parent_rate % rate)
273 		div++;
274 
275 	if (div > 4)
276 		div = 4;
277 
278 	return parent_rate / div;
279 }
280 
_clk_cpu_set_rate(struct clk * clk,unsigned long rate)281 static int _clk_cpu_set_rate(struct clk *clk, unsigned long rate)
282 {
283 	unsigned int div;
284 	uint32_t reg;
285 	unsigned long parent_rate;
286 
287 	parent_rate = clk_get_rate(clk->parent);
288 
289 	div = parent_rate / rate;
290 
291 	if (div > 4 || div < 1 || ((parent_rate / div) != rate))
292 		return -EINVAL;
293 
294 	div--;
295 
296 	reg = __raw_readl(CCM_CSCR);
297 	if (mx27_revision() >= CHIP_REV_2_0) {
298 		reg &= ~CCM_CSCR_ARM_MASK;
299 		reg |= div << CCM_CSCR_ARM_OFFSET;
300 		reg &= ~0x06;
301 		__raw_writel(reg | 0x80000000, CCM_CSCR);
302 	} else {
303 		printk(KERN_ERR "Cant set CPU frequency!\n");
304 	}
305 
306 	return 0;
307 }
308 
_clk_perclkx_round_rate(struct clk * clk,unsigned long rate)309 static unsigned long _clk_perclkx_round_rate(struct clk *clk,
310 					     unsigned long rate)
311 {
312 	u32 div;
313 	unsigned long parent_rate;
314 
315 	parent_rate = clk_get_rate(clk->parent);
316 
317 	div = parent_rate / rate;
318 	if (parent_rate % rate)
319 		div++;
320 
321 	if (div > 64)
322 		div = 64;
323 
324 	return parent_rate / div;
325 }
326 
_clk_perclkx_set_rate(struct clk * clk,unsigned long rate)327 static int _clk_perclkx_set_rate(struct clk *clk, unsigned long rate)
328 {
329 	u32 reg;
330 	u32 div;
331 	unsigned long parent_rate;
332 
333 	parent_rate = clk_get_rate(clk->parent);
334 
335 	if (clk->id < 0 || clk->id > 3)
336 		return -EINVAL;
337 
338 	div = parent_rate / rate;
339 	if (div > 64 || div < 1 || ((parent_rate / div) != rate))
340 		return -EINVAL;
341 	div--;
342 
343 	reg =
344 	    __raw_readl(CCM_PCDR1) & ~(CCM_PCDR1_PERDIV1_MASK <<
345 				       (clk->id << 3));
346 	reg |= div << (clk->id << 3);
347 	__raw_writel(reg, CCM_PCDR1);
348 
349 	return 0;
350 }
351 
_clk_usb_recalc(struct clk * clk)352 static unsigned long _clk_usb_recalc(struct clk *clk)
353 {
354 	unsigned long usb_pdf;
355 	unsigned long parent_rate;
356 
357 	parent_rate = clk_get_rate(clk->parent);
358 
359 	usb_pdf = (CSCR() & CCM_CSCR_USB_MASK) >> CCM_CSCR_USB_OFFSET;
360 
361 	return parent_rate / (usb_pdf + 1U);
362 }
363 
_clk_ssi1_recalc(struct clk * clk)364 static unsigned long _clk_ssi1_recalc(struct clk *clk)
365 {
366 	unsigned long ssi1_pdf;
367 	unsigned long parent_rate;
368 
369 	parent_rate = clk_get_rate(clk->parent);
370 
371 	ssi1_pdf = (PCDR0() & CCM_PCDR0_SSI1BAUDDIV_MASK) >>
372 					CCM_PCDR0_SSI1BAUDDIV_OFFSET;
373 
374 	if (mx27_revision() >= CHIP_REV_2_0)
375 		ssi1_pdf += 4;
376 	else
377 		ssi1_pdf = (ssi1_pdf < 2) ? 124UL : ssi1_pdf;
378 
379 	return 2UL * parent_rate / ssi1_pdf;
380 }
381 
_clk_ssi2_recalc(struct clk * clk)382 static unsigned long _clk_ssi2_recalc(struct clk *clk)
383 {
384 	unsigned long ssi2_pdf;
385 	unsigned long parent_rate;
386 
387 	parent_rate = clk_get_rate(clk->parent);
388 
389 	ssi2_pdf = (PCDR0() & CCM_PCDR0_SSI2BAUDDIV_MASK) >>
390 	    CCM_PCDR0_SSI2BAUDDIV_OFFSET;
391 
392 	if (mx27_revision() >= CHIP_REV_2_0)
393 		ssi2_pdf += 4;
394 	else
395 		ssi2_pdf = (ssi2_pdf < 2) ? 124UL : ssi2_pdf;
396 
397 	return 2UL * parent_rate / ssi2_pdf;
398 }
399 
_clk_nfc_recalc(struct clk * clk)400 static unsigned long _clk_nfc_recalc(struct clk *clk)
401 {
402 	unsigned long nfc_pdf;
403 	unsigned long parent_rate;
404 
405 	parent_rate = clk_get_rate(clk->parent);
406 
407 	if (mx27_revision() >= CHIP_REV_2_0) {
408 		nfc_pdf =
409 		    (PCDR0() & CCM_PCDR0_NFCDIV2_MASK) >>
410 		    CCM_PCDR0_NFCDIV2_OFFSET;
411 	} else {
412 		nfc_pdf =
413 		    (PCDR0() & CCM_PCDR0_NFCDIV_MASK) >>
414 		    CCM_PCDR0_NFCDIV_OFFSET;
415 	}
416 
417 	return parent_rate / (nfc_pdf + 1);
418 }
419 
_clk_vpu_recalc(struct clk * clk)420 static unsigned long _clk_vpu_recalc(struct clk *clk)
421 {
422 	unsigned long vpu_pdf;
423 	unsigned long parent_rate;
424 
425 	parent_rate = clk_get_rate(clk->parent);
426 
427 	if (mx27_revision() >= CHIP_REV_2_0) {
428 		vpu_pdf =
429 		    (PCDR0() & CCM_PCDR0_VPUDIV2_MASK) >>
430 		    CCM_PCDR0_VPUDIV2_OFFSET;
431 		vpu_pdf += 4;
432 	} else {
433 		vpu_pdf =
434 		    (PCDR0() & CCM_PCDR0_VPUDIV_MASK) >>
435 		    CCM_PCDR0_VPUDIV_OFFSET;
436 		vpu_pdf = (vpu_pdf < 2) ? 124 : vpu_pdf;
437 	}
438 	return 2UL * parent_rate / vpu_pdf;
439 }
440 
_clk_parent_round_rate(struct clk * clk,unsigned long rate)441 static unsigned long _clk_parent_round_rate(struct clk *clk, unsigned long rate)
442 {
443 	return clk->parent->round_rate(clk->parent, rate);
444 }
445 
_clk_parent_set_rate(struct clk * clk,unsigned long rate)446 static int _clk_parent_set_rate(struct clk *clk, unsigned long rate)
447 {
448 	return clk->parent->set_rate(clk->parent, rate);
449 }
450 
451 /* in Hz */
452 static unsigned long external_high_reference = 26000000;
453 
get_high_reference_clock_rate(struct clk * clk)454 static unsigned long get_high_reference_clock_rate(struct clk *clk)
455 {
456 	return external_high_reference;
457 }
458 
459 /*
460  * the high frequency external clock reference
461  * Default case is 26MHz. Could be changed at runtime
462  * with a call to change_external_high_reference()
463  */
464 static struct clk ckih_clk = {
465 	.name = "ckih",
466 	.get_rate = get_high_reference_clock_rate,
467 };
468 
469 /* in Hz */
470 static unsigned long external_low_reference = 32768;
471 
get_low_reference_clock_rate(struct clk * clk)472 static unsigned long get_low_reference_clock_rate(struct clk *clk)
473 {
474 	return external_low_reference;
475 }
476 
477 /*
478  * the low frequency external clock reference
479  * Default case is 32.768kHz Could be changed at runtime
480  * with a call to change_external_low_reference()
481  */
482 static struct clk ckil_clk = {
483 	.name = "ckil",
484 	.get_rate = get_low_reference_clock_rate,
485 };
486 
get_mpll_clk(struct clk * clk)487 static unsigned long get_mpll_clk(struct clk *clk)
488 {
489 	uint32_t reg;
490 	unsigned long ref_clk;
491 	unsigned long mfi = 0, mfn = 0, mfd = 0, pdf = 0;
492 	unsigned long long temp;
493 
494 	ref_clk = clk_get_rate(clk->parent);
495 
496 	reg = __raw_readl(CCM_MPCTL0);
497 	pdf = (reg & CCM_MPCTL0_PD_MASK) >> CCM_MPCTL0_PD_OFFSET;
498 	mfd = (reg & CCM_MPCTL0_MFD_MASK) >> CCM_MPCTL0_MFD_OFFSET;
499 	mfi = (reg & CCM_MPCTL0_MFI_MASK) >> CCM_MPCTL0_MFI_OFFSET;
500 	mfn = (reg & CCM_MPCTL0_MFN_MASK) >> CCM_MPCTL0_MFN_OFFSET;
501 
502 	mfi = (mfi <= 5) ? 5 : mfi;
503 	temp = 2LL * ref_clk * mfn;
504 	do_div(temp, mfd + 1);
505 	temp = 2LL * ref_clk * mfi + temp;
506 	do_div(temp, pdf + 1);
507 
508 	return (unsigned long)temp;
509 }
510 
511 static struct clk mpll_clk = {
512 	.name = "mpll",
513 	.parent = &ckih_clk,
514 	.get_rate = get_mpll_clk,
515 };
516 
_clk_mpll_main_get_rate(struct clk * clk)517 static unsigned long _clk_mpll_main_get_rate(struct clk *clk)
518 {
519 	unsigned long parent_rate;
520 
521 	parent_rate = clk_get_rate(clk->parent);
522 
523 	/* i.MX27 TO2:
524 	 * clk->id == 0: arm clock source path 1 which is from 2*MPLL/DIV_2
525 	 * clk->id == 1: arm clock source path 2 which is from 2*MPLL/DIV_3
526 	 */
527 
528 	if (mx27_revision() >= CHIP_REV_2_0 && clk->id == 1)
529 		return 2UL * parent_rate / 3UL;
530 
531 	return parent_rate;
532 }
533 
534 static struct clk mpll_main_clk[] = {
535 	{
536 		/* For i.MX27 TO2, it is the MPLL path 1 of ARM core
537 		 * It provide the clock source whose rate is same as MPLL
538 		 */
539 		.name = "mpll_main",
540 		.id = 0,
541 		.parent = &mpll_clk,
542 		.get_rate = _clk_mpll_main_get_rate
543 	}, {
544 		/* For i.MX27 TO2, it is the MPLL path 2 of ARM core
545 		 * It provide the clock source whose rate is same MPLL * 2/3
546 		 */
547 		.name = "mpll_main",
548 		.id = 1,
549 		.parent = &mpll_clk,
550 		.get_rate = _clk_mpll_main_get_rate
551 	}
552 };
553 
get_spll_clk(struct clk * clk)554 static unsigned long get_spll_clk(struct clk *clk)
555 {
556 	uint32_t reg;
557 	unsigned long ref_clk;
558 	unsigned long mfi = 0, mfn = 0, mfd = 0, pdf = 0;
559 	unsigned long long temp;
560 
561 	ref_clk = clk_get_rate(clk->parent);
562 
563 	reg = __raw_readl(CCM_SPCTL0);
564 	/*TODO: This is TO2 Bug */
565 	if (mx27_revision() >= CHIP_REV_2_0)
566 		__raw_writel(reg, CCM_SPCTL0);
567 
568 	pdf = (reg & CCM_SPCTL0_PD_MASK) >> CCM_SPCTL0_PD_OFFSET;
569 	mfd = (reg & CCM_SPCTL0_MFD_MASK) >> CCM_SPCTL0_MFD_OFFSET;
570 	mfi = (reg & CCM_SPCTL0_MFI_MASK) >> CCM_SPCTL0_MFI_OFFSET;
571 	mfn = (reg & CCM_SPCTL0_MFN_MASK) >> CCM_SPCTL0_MFN_OFFSET;
572 
573 	mfi = (mfi <= 5) ? 5 : mfi;
574 	temp = 2LL * ref_clk * mfn;
575 	do_div(temp, mfd + 1);
576 	temp = 2LL * ref_clk * mfi + temp;
577 	do_div(temp, pdf + 1);
578 
579 	return (unsigned long)temp;
580 }
581 
582 static struct clk spll_clk = {
583 	.name = "spll",
584 	.parent = &ckih_clk,
585 	.get_rate = get_spll_clk,
586 	.enable = _clk_spll_enable,
587 	.disable = _clk_spll_disable,
588 };
589 
get_cpu_clk(struct clk * clk)590 static unsigned long get_cpu_clk(struct clk *clk)
591 {
592 	u32 div;
593 	unsigned long rate;
594 
595 	if (mx27_revision() >= CHIP_REV_2_0)
596 		div = (CSCR() & CCM_CSCR_ARM_MASK) >> CCM_CSCR_ARM_OFFSET;
597 	else
598 		div = (CSCR() & CCM_CSCR_PRESC_MASK) >> CCM_CSCR_PRESC_OFFSET;
599 
600 	rate = clk_get_rate(clk->parent);
601 	return rate / (div + 1);
602 }
603 
604 static struct clk cpu_clk = {
605 	.name = "cpu_clk",
606 	.parent = &mpll_main_clk[1],
607 	.set_parent = _clk_cpu_set_parent,
608 	.round_rate = _clk_cpu_round_rate,
609 	.get_rate = get_cpu_clk,
610 	.set_rate = _clk_cpu_set_rate,
611 };
612 
get_ahb_clk(struct clk * clk)613 static unsigned long get_ahb_clk(struct clk *clk)
614 {
615 	unsigned long rate;
616 	unsigned long bclk_pdf;
617 
618 	if (mx27_revision() >= CHIP_REV_2_0)
619 		bclk_pdf = (CSCR() & CCM_CSCR_AHB_MASK)
620 					>> CCM_CSCR_AHB_OFFSET;
621 	else
622 		bclk_pdf = (CSCR() & CCM_CSCR_BCLK_MASK)
623 					>> CCM_CSCR_BCLK_OFFSET;
624 
625 	rate = clk_get_rate(clk->parent);
626 	return rate / (bclk_pdf + 1);
627 }
628 
629 static struct clk ahb_clk = {
630 	.name = "ahb_clk",
631 	.parent = &mpll_main_clk[1],
632 	.get_rate = get_ahb_clk,
633 };
634 
get_ipg_clk(struct clk * clk)635 static unsigned long get_ipg_clk(struct clk *clk)
636 {
637 	unsigned long rate;
638 	unsigned long ipg_pdf;
639 
640 	if (mx27_revision() >= CHIP_REV_2_0)
641 		return clk_get_rate(clk->parent);
642 	else
643 		ipg_pdf = (CSCR() & CCM_CSCR_IPDIV) >> CCM_CSCR_IPDIV_OFFSET;
644 
645 	rate = clk_get_rate(clk->parent);
646 	return rate / (ipg_pdf + 1);
647 }
648 
649 static struct clk ipg_clk = {
650 	.name = "ipg_clk",
651 	.parent = &ahb_clk,
652 	.get_rate = get_ipg_clk,
653 };
654 
_clk_perclkx_recalc(struct clk * clk)655 static unsigned long _clk_perclkx_recalc(struct clk *clk)
656 {
657 	unsigned long perclk_pdf;
658 	unsigned long parent_rate;
659 
660 	parent_rate = clk_get_rate(clk->parent);
661 
662 	if (clk->id < 0 || clk->id > 3)
663 		return 0;
664 
665 	perclk_pdf = (PCDR1() >> (clk->id << 3)) & CCM_PCDR1_PERDIV1_MASK;
666 
667 	return parent_rate / (perclk_pdf + 1);
668 }
669 
670 static struct clk per_clk[] = {
671 	{
672 		.name = "per_clk",
673 		.id = 0,
674 		.parent = &mpll_main_clk[1],
675 		.get_rate = _clk_perclkx_recalc,
676 		.enable = _clk_enable,
677 		.enable_reg = CCM_PCCR1,
678 		.enable_shift = CCM_PCCR1_PERCLK1_OFFSET,
679 		.disable = _clk_disable,
680 	}, {
681 		.name = "per_clk",
682 		.id = 1,
683 		.parent = &mpll_main_clk[1],
684 		.get_rate = _clk_perclkx_recalc,
685 		.enable = _clk_enable,
686 		.enable_reg = CCM_PCCR1,
687 		.enable_shift = CCM_PCCR1_PERCLK2_OFFSET,
688 		.disable = _clk_disable,
689 	}, {
690 		.name = "per_clk",
691 		.id = 2,
692 		.parent = &mpll_main_clk[1],
693 		.round_rate = _clk_perclkx_round_rate,
694 		.set_rate = _clk_perclkx_set_rate,
695 		.get_rate = _clk_perclkx_recalc,
696 		.enable = _clk_enable,
697 		.enable_reg = CCM_PCCR1,
698 		.enable_shift = CCM_PCCR1_PERCLK3_OFFSET,
699 		.disable = _clk_disable,
700 	}, {
701 		.name = "per_clk",
702 		.id = 3,
703 		.parent = &mpll_main_clk[1],
704 		.round_rate = _clk_perclkx_round_rate,
705 		.set_rate = _clk_perclkx_set_rate,
706 		.get_rate = _clk_perclkx_recalc,
707 		.enable = _clk_enable,
708 		.enable_reg = CCM_PCCR1,
709 		.enable_shift = CCM_PCCR1_PERCLK4_OFFSET,
710 		.disable = _clk_disable,
711 	},
712 };
713 
714 struct clk uart1_clk[] = {
715 	{
716 		.name = "uart_clk",
717 		.id = 0,
718 		.parent = &per_clk[0],
719 		.secondary = &uart1_clk[1],
720 	}, {
721 		.name = "uart_ipg_clk",
722 		.id = 0,
723 		.parent = &ipg_clk,
724 		.enable = _clk_enable,
725 		.enable_reg = CCM_PCCR1,
726 		.enable_shift = CCM_PCCR1_UART1_OFFSET,
727 		.disable = _clk_disable,
728 	},
729 };
730 
731 struct clk uart2_clk[] = {
732 	{
733 		.name = "uart_clk",
734 		.id = 1,
735 		.parent = &per_clk[0],
736 		.secondary = &uart2_clk[1],
737 	}, {
738 		.name = "uart_ipg_clk",
739 		.id = 1,
740 		.parent = &ipg_clk,
741 		.enable = _clk_enable,
742 		.enable_reg = CCM_PCCR1,
743 		.enable_shift = CCM_PCCR1_UART2_OFFSET,
744 		.disable = _clk_disable,
745 	},
746 };
747 
748 struct clk uart3_clk[] = {
749 	{
750 		.name = "uart_clk",
751 		.id = 2,
752 		.parent = &per_clk[0],
753 		.secondary = &uart3_clk[1],
754 	}, {
755 		.name = "uart_ipg_clk",
756 		.id = 2,
757 		.parent = &ipg_clk,
758 		.enable = _clk_enable,
759 		.enable_reg = CCM_PCCR1,
760 		.enable_shift = CCM_PCCR1_UART3_OFFSET,
761 		.disable = _clk_disable,
762 	},
763 };
764 
765 struct clk uart4_clk[] = {
766 	{
767 		.name = "uart_clk",
768 		.id = 3,
769 		.parent = &per_clk[0],
770 		.secondary = &uart4_clk[1],
771 	}, {
772 		.name = "uart_ipg_clk",
773 		.id = 3,
774 		.parent = &ipg_clk,
775 		.enable = _clk_enable,
776 		.enable_reg = CCM_PCCR1,
777 		.enable_shift = CCM_PCCR1_UART4_OFFSET,
778 		.disable = _clk_disable,
779 	},
780 };
781 
782 struct clk uart5_clk[] = {
783 	{
784 		.name = "uart_clk",
785 		.id = 4,
786 		.parent = &per_clk[0],
787 		.secondary = &uart5_clk[1],
788 	}, {
789 		.name = "uart_ipg_clk",
790 		.id = 4,
791 		.parent = &ipg_clk,
792 		.enable = _clk_enable,
793 		.enable_reg = CCM_PCCR1,
794 		.enable_shift = CCM_PCCR1_UART5_OFFSET,
795 		.disable = _clk_disable,
796 	},
797 };
798 
799 struct clk uart6_clk[] = {
800 	{
801 		.name = "uart_clk",
802 		.id = 5,
803 		.parent = &per_clk[0],
804 		.secondary = &uart6_clk[1],
805 	}, {
806 		.name = "uart_ipg_clk",
807 		.id = 5,
808 		.parent = &ipg_clk,
809 		.enable = _clk_enable,
810 		.enable_reg = CCM_PCCR1,
811 		.enable_shift = CCM_PCCR1_UART6_OFFSET,
812 		.disable = _clk_disable,
813 	},
814 };
815 
816 static struct clk gpt1_clk[] = {
817 	{
818 		.name = "gpt_clk",
819 		.id = 0,
820 		.parent = &per_clk[0],
821 		.secondary = &gpt1_clk[1],
822 	}, {
823 		.name = "gpt_ipg_clk",
824 		.id = 0,
825 		.parent = &ipg_clk,
826 		.enable = _clk_enable,
827 		.enable_reg = CCM_PCCR0,
828 		.enable_shift = CCM_PCCR0_GPT1_OFFSET,
829 		.disable = _clk_disable,
830 	},
831 };
832 
833 static struct clk gpt2_clk[] = {
834 	{
835 		.name = "gpt_clk",
836 		.id = 1,
837 		.parent = &per_clk[0],
838 		.secondary = &gpt2_clk[1],
839 	}, {
840 		.name = "gpt_ipg_clk",
841 		.id = 1,
842 		.parent = &ipg_clk,
843 		.enable = _clk_enable,
844 		.enable_reg = CCM_PCCR0,
845 		.enable_shift = CCM_PCCR0_GPT2_OFFSET,
846 		.disable = _clk_disable,
847 	},
848 };
849 
850 static struct clk gpt3_clk[] = {
851 	{
852 		.name = "gpt_clk",
853 		.id = 2,
854 		.parent = &per_clk[0],
855 		.secondary = &gpt3_clk[1],
856 	}, {
857 		.name = "gpt_ipg_clk",
858 		.id = 2,
859 		.parent = &ipg_clk,
860 		.enable = _clk_enable,
861 		.enable_reg = CCM_PCCR0,
862 		.enable_shift = CCM_PCCR0_GPT3_OFFSET,
863 		.disable = _clk_disable,
864 	},
865 };
866 
867 static struct clk gpt4_clk[] = {
868 	{
869 		.name = "gpt_clk",
870 		.id = 3,
871 		.parent = &per_clk[0],
872 		.secondary = &gpt4_clk[1],
873 	}, {
874 		.name = "gpt_ipg_clk",
875 		.id = 3,
876 		.parent = &ipg_clk,
877 		.enable = _clk_enable,
878 		.enable_reg = CCM_PCCR0,
879 		.enable_shift = CCM_PCCR0_GPT4_OFFSET,
880 		.disable = _clk_disable,
881 	},
882 };
883 
884 static struct clk gpt5_clk[] = {
885 	{
886 		.name = "gpt_clk",
887 		.id = 4,
888 		.parent = &per_clk[0],
889 		.secondary = &gpt5_clk[1],
890 	}, {
891 		.name = "gpt_ipg_clk",
892 		.id = 4,
893 		.parent = &ipg_clk,
894 		.enable = _clk_enable,
895 		.enable_reg = CCM_PCCR0,
896 		.enable_shift = CCM_PCCR0_GPT5_OFFSET,
897 		.disable = _clk_disable,
898 	},
899 };
900 
901 static struct clk gpt6_clk[] = {
902 	{
903 		.name = "gpt_clk",
904 		.id = 5,
905 		.parent = &per_clk[0],
906 		.secondary = &gpt6_clk[1],
907 	}, {
908 		.name = "gpt_ipg_clk",
909 		.id = 5,
910 		.parent = &ipg_clk,
911 		.enable = _clk_enable,
912 		.enable_reg = CCM_PCCR0,
913 		.enable_shift = CCM_PCCR0_GPT6_OFFSET,
914 		.disable = _clk_disable,
915 	},
916 };
917 
918 static struct clk pwm_clk[] = {
919 	{
920 		.name = "pwm_clk",
921 		.parent = &per_clk[0],
922 		.secondary = &pwm_clk[1],
923 	}, {
924 		.name = "pwm_clk",
925 		.parent = &ipg_clk,
926 		.enable = _clk_enable,
927 		.enable_reg = CCM_PCCR0,
928 		.enable_shift = CCM_PCCR0_PWM_OFFSET,
929 		.disable = _clk_disable,
930 	},
931 };
932 
933 static struct clk sdhc1_clk[] = {
934 	{
935 		.name = "sdhc_clk",
936 		.id = 0,
937 		.parent = &per_clk[1],
938 		.secondary = &sdhc1_clk[1],
939 	}, {
940 		.name = "sdhc_ipg_clk",
941 		.id = 0,
942 		.parent = &ipg_clk,
943 		.enable = _clk_enable,
944 		.enable_reg = CCM_PCCR0,
945 		.enable_shift = CCM_PCCR0_SDHC1_OFFSET,
946 		.disable = _clk_disable,
947 	},
948 };
949 
950 static struct clk sdhc2_clk[] = {
951 	{
952 		.name = "sdhc_clk",
953 		.id = 1,
954 		.parent = &per_clk[1],
955 		.secondary = &sdhc2_clk[1],
956 	}, {
957 		.name = "sdhc_ipg_clk",
958 		.id = 1,
959 		.parent = &ipg_clk,
960 		.enable = _clk_enable,
961 		.enable_reg = CCM_PCCR0,
962 		.enable_shift = CCM_PCCR0_SDHC2_OFFSET,
963 		.disable = _clk_disable,
964 	},
965 };
966 
967 static struct clk sdhc3_clk[] = {
968 	{
969 		.name = "sdhc_clk",
970 		.id = 2,
971 		.parent = &per_clk[1],
972 		.secondary = &sdhc3_clk[1],
973 	}, {
974 		.name = "sdhc_ipg_clk",
975 		.id = 2,
976 		.parent = &ipg_clk,
977 		.enable = _clk_enable,
978 		.enable_reg = CCM_PCCR0,
979 		.enable_shift = CCM_PCCR0_SDHC3_OFFSET,
980 		.disable = _clk_disable,
981 	},
982 };
983 
984 static struct clk cspi1_clk[] = {
985 	{
986 		.name = "cspi_clk",
987 		.id = 0,
988 		.parent = &per_clk[1],
989 		.secondary = &cspi1_clk[1],
990 	}, {
991 		.name = "cspi_ipg_clk",
992 		.id = 0,
993 		.parent = &ipg_clk,
994 		.enable = _clk_enable,
995 		.enable_reg = CCM_PCCR0,
996 		.enable_shift = CCM_PCCR0_CSPI1_OFFSET,
997 		.disable = _clk_disable,
998 	},
999 };
1000 
1001 static struct clk cspi2_clk[] = {
1002 	{
1003 		.name = "cspi_clk",
1004 		.id = 1,
1005 		.parent = &per_clk[1],
1006 		.secondary = &cspi2_clk[1],
1007 	}, {
1008 		.name = "cspi_ipg_clk",
1009 		.id = 1,
1010 		.parent = &ipg_clk,
1011 		.enable = _clk_enable,
1012 		.enable_reg = CCM_PCCR0,
1013 		.enable_shift = CCM_PCCR0_CSPI2_OFFSET,
1014 		.disable = _clk_disable,
1015 	},
1016 };
1017 
1018 static struct clk cspi3_clk[] = {
1019 	{
1020 		.name = "cspi_clk",
1021 		.id = 2,
1022 		.parent = &per_clk[1],
1023 		.secondary = &cspi3_clk[1],
1024 	}, {
1025 		.name = "cspi_ipg_clk",
1026 		.id = 2,
1027 		.parent = &ipg_clk,
1028 		.enable = _clk_enable,
1029 		.enable_reg = CCM_PCCR0,
1030 		.enable_shift = CCM_PCCR0_CSPI3_OFFSET,
1031 		.disable = _clk_disable,
1032 	},
1033 };
1034 
1035 static struct clk lcdc_clk[] = {
1036 	{
1037 		.name = "lcdc_clk",
1038 		.parent = &per_clk[2],
1039 		.secondary = &lcdc_clk[1],
1040 		.round_rate = _clk_parent_round_rate,
1041 		.set_rate = _clk_parent_set_rate,
1042 	}, {
1043 		.name = "lcdc_ipg_clk",
1044 		.parent = &ipg_clk,
1045 		.secondary = &lcdc_clk[2],
1046 		.enable = _clk_enable,
1047 		.enable_reg = CCM_PCCR0,
1048 		.enable_shift = CCM_PCCR0_LCDC_OFFSET,
1049 		.disable = _clk_disable,
1050 	}, {
1051 		.name = "lcdc_ahb_clk",
1052 		.parent = &ahb_clk,
1053 		.enable = _clk_enable,
1054 		.enable_reg = CCM_PCCR1,
1055 		.enable_shift = CCM_PCCR1_HCLK_LCDC_OFFSET,
1056 		.disable = _clk_disable,
1057 	},
1058 };
1059 
1060 static struct clk csi_clk[] = {
1061 	{
1062 		.name = "csi_perclk",
1063 		.parent = &per_clk[3],
1064 		.secondary = &csi_clk[1],
1065 		.round_rate = _clk_parent_round_rate,
1066 		.set_rate = _clk_parent_set_rate,
1067 	}, {
1068 		.name = "csi_ahb_clk",
1069 		.parent = &ahb_clk,
1070 		.enable = _clk_enable,
1071 		.enable_reg = CCM_PCCR1,
1072 		.enable_shift = CCM_PCCR1_HCLK_CSI_OFFSET,
1073 		.disable = _clk_disable,
1074 	},
1075 };
1076 
1077 static struct clk usb_clk[] = {
1078 	{
1079 		.name = "usb_clk",
1080 		.parent = &spll_clk,
1081 		.get_rate = _clk_usb_recalc,
1082 		.enable = _clk_enable,
1083 		.enable_reg = CCM_PCCR1,
1084 		.enable_shift = CCM_PCCR1_USBOTG_OFFSET,
1085 		.disable = _clk_disable,
1086 	}, {
1087 		.name = "usb_ahb_clk",
1088 		.parent = &ahb_clk,
1089 		.enable = _clk_enable,
1090 		.enable_reg = CCM_PCCR1,
1091 		.enable_shift = CCM_PCCR1_HCLK_USBOTG_OFFSET,
1092 		.disable = _clk_disable,
1093 	}
1094 };
1095 
1096 static struct clk ssi1_clk[] = {
1097 	{
1098 		.name = "ssi_clk",
1099 		.id = 0,
1100 		.parent = &mpll_main_clk[1],
1101 		.secondary = &ssi1_clk[1],
1102 		.get_rate = _clk_ssi1_recalc,
1103 		.enable = _clk_enable,
1104 		.enable_reg = CCM_PCCR1,
1105 		.enable_shift = CCM_PCCR1_SSI1_BAUD_OFFSET,
1106 		.disable = _clk_disable,
1107 	}, {
1108 		.name = "ssi_ipg_clk",
1109 		.id = 0,
1110 		.parent = &ipg_clk,
1111 		.enable = _clk_enable,
1112 		.enable_reg = CCM_PCCR0,
1113 		.enable_shift = CCM_PCCR0_SSI1_IPG_OFFSET,
1114 		.disable = _clk_disable,
1115 	},
1116 };
1117 
1118 static struct clk ssi2_clk[] = {
1119 	{
1120 		.name = "ssi_clk",
1121 		.id = 1,
1122 		.parent = &mpll_main_clk[1],
1123 		.secondary = &ssi2_clk[1],
1124 		.get_rate = _clk_ssi2_recalc,
1125 		.enable = _clk_enable,
1126 		.enable_reg = CCM_PCCR1,
1127 		.enable_shift = CCM_PCCR1_SSI2_BAUD_OFFSET,
1128 		.disable = _clk_disable,
1129 	}, {
1130 		.name = "ssi_ipg_clk",
1131 		.id = 1,
1132 		.parent = &ipg_clk,
1133 		.enable = _clk_enable,
1134 		.enable_reg = CCM_PCCR0,
1135 		.enable_shift = CCM_PCCR0_SSI2_IPG_OFFSET,
1136 		.disable = _clk_disable,
1137 	},
1138 };
1139 
1140 static struct clk nfc_clk = {
1141 	.name = "nfc_clk",
1142 	.parent = &cpu_clk,
1143 	.get_rate = _clk_nfc_recalc,
1144 	.enable = _clk_enable,
1145 	.enable_reg = CCM_PCCR1,
1146 	.enable_shift = CCM_PCCR1_NFC_BAUD_OFFSET,
1147 	.disable = _clk_disable,
1148 };
1149 
1150 static struct clk vpu_clk = {
1151 	.name = "vpu_clk",
1152 	.parent = &mpll_main_clk[1],
1153 	.get_rate = _clk_vpu_recalc,
1154 	.enable = _clk_vpu_enable,
1155 	.disable = _clk_vpu_disable,
1156 };
1157 
1158 static struct clk dma_clk = {
1159 	.name = "dma_clk",
1160 	.parent = &ahb_clk,
1161 	.enable = _clk_dma_enable,
1162 	.disable = _clk_dma_disable,
1163 };
1164 
1165 static struct clk rtic_clk = {
1166 	.name = "rtic_clk",
1167 	.parent = &ahb_clk,
1168 	.enable = _clk_rtic_enable,
1169 	.disable = _clk_rtic_disable,
1170 };
1171 
1172 static struct clk brom_clk = {
1173 	.name = "brom_clk",
1174 	.parent = &ahb_clk,
1175 	.enable = _clk_enable,
1176 	.enable_reg = CCM_PCCR1,
1177 	.enable_shift = CCM_PCCR1_HCLK_BROM_OFFSET,
1178 	.disable = _clk_disable,
1179 };
1180 
1181 static struct clk emma_clk = {
1182 	.name = "emma_clk",
1183 	.parent = &ahb_clk,
1184 	.enable = _clk_emma_enable,
1185 	.disable = _clk_emma_disable,
1186 };
1187 
1188 static struct clk slcdc_clk = {
1189 	.name = "slcdc_clk",
1190 	.parent = &ahb_clk,
1191 	.enable = _clk_slcdc_enable,
1192 	.disable = _clk_slcdc_disable,
1193 };
1194 
1195 static struct clk fec_clk = {
1196 	.name = "fec_clk",
1197 	.parent = &ahb_clk,
1198 	.enable = _clk_fec_enable,
1199 	.disable = _clk_fec_disable,
1200 };
1201 
1202 static struct clk emi_clk = {
1203 	.name = "emi_clk",
1204 	.parent = &ahb_clk,
1205 	.enable = _clk_enable,
1206 	.enable_reg = CCM_PCCR1,
1207 	.enable_shift = CCM_PCCR1_HCLK_EMI_OFFSET,
1208 	.disable = _clk_disable,
1209 };
1210 
1211 static struct clk sahara2_clk = {
1212 	.name = "sahara_clk",
1213 	.parent = &ahb_clk,
1214 	.enable = _clk_sahara2_enable,
1215 	.disable = _clk_sahara2_disable,
1216 };
1217 
1218 static struct clk ata_clk = {
1219 	.name = "ata_clk",
1220 	.parent = &ahb_clk,
1221 	.enable = _clk_enable,
1222 	.enable_reg = CCM_PCCR1,
1223 	.enable_shift = CCM_PCCR1_HCLK_ATA_OFFSET,
1224 	.disable = _clk_disable,
1225 };
1226 
1227 static struct clk mstick1_clk = {
1228 	.name = "mstick1_clk",
1229 	.parent = &ipg_clk,
1230 	.enable = _clk_mstick1_enable,
1231 	.disable = _clk_mstick1_disable,
1232 };
1233 
1234 static struct clk wdog_clk = {
1235 	.name = "wdog_clk",
1236 	.parent = &ipg_clk,
1237 	.enable = _clk_enable,
1238 	.enable_reg = CCM_PCCR1,
1239 	.enable_shift = CCM_PCCR1_WDT_OFFSET,
1240 	.disable = _clk_disable,
1241 };
1242 
1243 static struct clk gpio_clk = {
1244 	.name = "gpio_clk",
1245 	.parent = &ipg_clk,
1246 	.enable = _clk_enable,
1247 	.enable_reg = CCM_PCCR1,
1248 	.enable_shift = CCM_PCCR0_GPIO_OFFSET,
1249 	.disable = _clk_disable,
1250 };
1251 
1252 static struct clk i2c_clk[] = {
1253 	{
1254 		.name = "i2c_clk",
1255 		.id = 0,
1256 		.parent = &ipg_clk,
1257 		.enable = _clk_enable,
1258 		.enable_reg = CCM_PCCR0,
1259 		.enable_shift = CCM_PCCR0_I2C1_OFFSET,
1260 		.disable = _clk_disable,
1261 	}, {
1262 		.name = "i2c_clk",
1263 		.id = 1,
1264 		.parent = &ipg_clk,
1265 		.enable = _clk_enable,
1266 		.enable_reg = CCM_PCCR0,
1267 		.enable_shift = CCM_PCCR0_I2C2_OFFSET,
1268 		.disable = _clk_disable,
1269 	},
1270 };
1271 
1272 static struct clk iim_clk = {
1273 	.name = "iim_clk",
1274 	.parent = &ipg_clk,
1275 	.enable = _clk_enable,
1276 	.enable_reg = CCM_PCCR0,
1277 	.enable_shift = CCM_PCCR0_IIM_OFFSET,
1278 	.disable = _clk_disable,
1279 };
1280 
1281 static struct clk kpp_clk = {
1282 	.name = "kpp_clk",
1283 	.parent = &ipg_clk,
1284 	.enable = _clk_enable,
1285 	.enable_reg = CCM_PCCR0,
1286 	.enable_shift = CCM_PCCR0_KPP_OFFSET,
1287 	.disable = _clk_disable,
1288 };
1289 
1290 static struct clk owire_clk = {
1291 	.name = "owire_clk",
1292 	.parent = &ipg_clk,
1293 	.enable = _clk_enable,
1294 	.enable_reg = CCM_PCCR0,
1295 	.enable_shift = CCM_PCCR0_OWIRE_OFFSET,
1296 	.disable = _clk_disable,
1297 };
1298 
1299 static struct clk rtc_clk = {
1300 	.name = "rtc_clk",
1301 	.parent = &ipg_clk,
1302 	.enable = _clk_enable,
1303 	.enable_reg = CCM_PCCR0,
1304 	.enable_shift = CCM_PCCR0_RTC_OFFSET,
1305 	.disable = _clk_disable,
1306 };
1307 
1308 static struct clk scc_clk = {
1309 	.name = "scc_clk",
1310 	.parent = &ipg_clk,
1311 	.enable = _clk_enable,
1312 	.enable_reg = CCM_PCCR0,
1313 	.enable_shift = CCM_PCCR0_SCC_OFFSET,
1314 	.disable = _clk_disable,
1315 };
1316 
_clk_clko_round_rate(struct clk * clk,unsigned long rate)1317 static unsigned long _clk_clko_round_rate(struct clk *clk, unsigned long rate)
1318 {
1319 	u32 div;
1320 	unsigned long parent_rate;
1321 
1322 	parent_rate = clk_get_rate(clk->parent);
1323 	div = parent_rate / rate;
1324 	if (parent_rate % rate)
1325 		div++;
1326 
1327 	if (div > 8)
1328 		div = 8;
1329 
1330 	return parent_rate / div;
1331 }
1332 
_clk_clko_set_rate(struct clk * clk,unsigned long rate)1333 static int _clk_clko_set_rate(struct clk *clk, unsigned long rate)
1334 {
1335 	u32 reg;
1336 	u32 div;
1337 	unsigned long parent_rate;
1338 
1339 	parent_rate = clk_get_rate(clk->parent);
1340 
1341 	div = parent_rate / rate;
1342 
1343 	if (div > 8 || div < 1 || ((parent_rate / div) != rate))
1344 		return -EINVAL;
1345 	div--;
1346 
1347 	reg = __raw_readl(CCM_PCDR0) & ~CCM_PCDR0_CLKODIV_MASK;
1348 	reg |= div << CCM_PCDR0_CLKODIV_OFFSET;
1349 	__raw_writel(reg, CCM_PCDR0);
1350 
1351 	return 0;
1352 }
1353 
_clk_clko_recalc(struct clk * clk)1354 static unsigned long _clk_clko_recalc(struct clk *clk)
1355 {
1356 	u32 div;
1357 	unsigned long parent_rate;
1358 
1359 	parent_rate = clk_get_rate(clk->parent);
1360 
1361 	div = __raw_readl(CCM_PCDR0) & CCM_PCDR0_CLKODIV_MASK >>
1362 		CCM_PCDR0_CLKODIV_OFFSET;
1363 	div++;
1364 
1365 	return parent_rate / div;
1366 }
1367 
_clk_clko_set_parent(struct clk * clk,struct clk * parent)1368 static int _clk_clko_set_parent(struct clk *clk, struct clk *parent)
1369 {
1370 	u32 reg;
1371 
1372 	reg = __raw_readl(CCM_CCSR) & ~CCM_CCSR_CLKOSEL_MASK;
1373 
1374 	if (parent == &ckil_clk)
1375 		reg |= 0 << CCM_CCSR_CLKOSEL_OFFSET;
1376 	else if (parent == &ckih_clk)
1377 		reg |= 2 << CCM_CCSR_CLKOSEL_OFFSET;
1378 	else if (parent == mpll_clk.parent)
1379 		reg |= 3 << CCM_CCSR_CLKOSEL_OFFSET;
1380 	else if (parent == spll_clk.parent)
1381 		reg |= 4 << CCM_CCSR_CLKOSEL_OFFSET;
1382 	else if (parent == &mpll_clk)
1383 		reg |= 5 << CCM_CCSR_CLKOSEL_OFFSET;
1384 	else if (parent == &spll_clk)
1385 		reg |= 6 << CCM_CCSR_CLKOSEL_OFFSET;
1386 	else if (parent == &cpu_clk)
1387 		reg |= 7 << CCM_CCSR_CLKOSEL_OFFSET;
1388 	else if (parent == &ahb_clk)
1389 		reg |= 8 << CCM_CCSR_CLKOSEL_OFFSET;
1390 	else if (parent == &ipg_clk)
1391 		reg |= 9 << CCM_CCSR_CLKOSEL_OFFSET;
1392 	else if (parent == &per_clk[0])
1393 		reg |= 0xA << CCM_CCSR_CLKOSEL_OFFSET;
1394 	else if (parent == &per_clk[1])
1395 		reg |= 0xB << CCM_CCSR_CLKOSEL_OFFSET;
1396 	else if (parent == &per_clk[2])
1397 		reg |= 0xC << CCM_CCSR_CLKOSEL_OFFSET;
1398 	else if (parent == &per_clk[3])
1399 		reg |= 0xD << CCM_CCSR_CLKOSEL_OFFSET;
1400 	else if (parent == &ssi1_clk[0])
1401 		reg |= 0xE << CCM_CCSR_CLKOSEL_OFFSET;
1402 	else if (parent == &ssi2_clk[0])
1403 		reg |= 0xF << CCM_CCSR_CLKOSEL_OFFSET;
1404 	else if (parent == &nfc_clk)
1405 		reg |= 0x10 << CCM_CCSR_CLKOSEL_OFFSET;
1406 	else if (parent == &mstick1_clk)
1407 		reg |= 0x11 << CCM_CCSR_CLKOSEL_OFFSET;
1408 	else if (parent == &vpu_clk)
1409 		reg |= 0x12 << CCM_CCSR_CLKOSEL_OFFSET;
1410 	else if (parent == &usb_clk[0])
1411 		reg |= 0x15 << CCM_CCSR_CLKOSEL_OFFSET;
1412 	else
1413 		return -EINVAL;
1414 
1415 	__raw_writel(reg, CCM_CCSR);
1416 
1417 	return 0;
1418 }
1419 
_clk_clko_enable(struct clk * clk)1420 static int _clk_clko_enable(struct clk *clk)
1421 {
1422 	u32 reg;
1423 
1424 	reg = __raw_readl(CCM_PCDR0) | CCM_PCDR0_CLKO_EN;
1425 	__raw_writel(reg, CCM_PCDR0);
1426 
1427 	return 0;
1428 }
1429 
_clk_clko_disable(struct clk * clk)1430 static void _clk_clko_disable(struct clk *clk)
1431 {
1432 	u32 reg;
1433 
1434 	reg = __raw_readl(CCM_PCDR0) & ~CCM_PCDR0_CLKO_EN;
1435 	__raw_writel(reg, CCM_PCDR0);
1436 }
1437 
1438 static struct clk clko_clk = {
1439 	.name = "clko_clk",
1440 	.get_rate = _clk_clko_recalc,
1441 	.set_rate = _clk_clko_set_rate,
1442 	.round_rate = _clk_clko_round_rate,
1443 	.set_parent = _clk_clko_set_parent,
1444 	.enable = _clk_clko_enable,
1445 	.disable = _clk_clko_disable,
1446 };
1447 
1448 static struct clk *mxc_clks[] = {
1449 	&ckih_clk,
1450 	&ckil_clk,
1451 	&mpll_clk,
1452 	&mpll_main_clk[0],
1453 	&mpll_main_clk[1],
1454 	&spll_clk,
1455 	&cpu_clk,
1456 	&ahb_clk,
1457 	&ipg_clk,
1458 	&per_clk[0],
1459 	&per_clk[1],
1460 	&per_clk[2],
1461 	&per_clk[3],
1462 	&clko_clk,
1463 	&uart1_clk[0],
1464 	&uart1_clk[1],
1465 	&uart2_clk[0],
1466 	&uart2_clk[1],
1467 	&uart3_clk[0],
1468 	&uart3_clk[1],
1469 	&uart4_clk[0],
1470 	&uart4_clk[1],
1471 	&uart5_clk[0],
1472 	&uart5_clk[1],
1473 	&uart6_clk[0],
1474 	&uart6_clk[1],
1475 	&gpt1_clk[0],
1476 	&gpt1_clk[1],
1477 	&gpt2_clk[0],
1478 	&gpt2_clk[1],
1479 	&gpt3_clk[0],
1480 	&gpt3_clk[1],
1481 	&gpt4_clk[0],
1482 	&gpt4_clk[1],
1483 	&gpt5_clk[0],
1484 	&gpt5_clk[1],
1485 	&gpt6_clk[0],
1486 	&gpt6_clk[1],
1487 	&pwm_clk[0],
1488 	&pwm_clk[1],
1489 	&sdhc1_clk[0],
1490 	&sdhc1_clk[1],
1491 	&sdhc2_clk[0],
1492 	&sdhc2_clk[1],
1493 	&sdhc3_clk[0],
1494 	&sdhc3_clk[1],
1495 	&cspi1_clk[0],
1496 	&cspi1_clk[1],
1497 	&cspi2_clk[0],
1498 	&cspi2_clk[1],
1499 	&cspi3_clk[0],
1500 	&cspi3_clk[1],
1501 	&lcdc_clk[0],
1502 	&lcdc_clk[1],
1503 	&lcdc_clk[2],
1504 	&csi_clk[0],
1505 	&csi_clk[1],
1506 	&usb_clk[0],
1507 	&usb_clk[1],
1508 	&ssi1_clk[0],
1509 	&ssi1_clk[1],
1510 	&ssi2_clk[0],
1511 	&ssi2_clk[1],
1512 	&nfc_clk,
1513 	&vpu_clk,
1514 	&dma_clk,
1515 	&rtic_clk,
1516 	&brom_clk,
1517 	&emma_clk,
1518 	&slcdc_clk,
1519 	&fec_clk,
1520 	&emi_clk,
1521 	&sahara2_clk,
1522 	&ata_clk,
1523 	&mstick1_clk,
1524 	&wdog_clk,
1525 	&gpio_clk,
1526 	&i2c_clk[0],
1527 	&i2c_clk[1],
1528 	&iim_clk,
1529 	&kpp_clk,
1530 	&owire_clk,
1531 	&rtc_clk,
1532 	&scc_clk,
1533 };
1534 
change_external_low_reference(unsigned long new_ref)1535 void __init change_external_low_reference(unsigned long new_ref)
1536 {
1537 	external_low_reference = new_ref;
1538 }
1539 
clk_early_get_timer_rate(void)1540 unsigned long __init clk_early_get_timer_rate(void)
1541 {
1542 	return clk_get_rate(&per_clk[0]);
1543 }
1544 
probe_mxc_clocks(void)1545 static void __init probe_mxc_clocks(void)
1546 {
1547 	int i;
1548 
1549 	if (mx27_revision() >= CHIP_REV_2_0) {
1550 		if (CSCR() & 0x8000)
1551 			cpu_clk.parent = &mpll_main_clk[0];
1552 
1553 		if (!(CSCR() & 0x00800000))
1554 			ssi2_clk[0].parent = &spll_clk;
1555 
1556 		if (!(CSCR() & 0x00400000))
1557 			ssi1_clk[0].parent = &spll_clk;
1558 
1559 		if (!(CSCR() & 0x00200000))
1560 			vpu_clk.parent = &spll_clk;
1561 	} else {
1562 		cpu_clk.parent = &mpll_clk;
1563 		cpu_clk.set_parent = NULL;
1564 		cpu_clk.round_rate = NULL;
1565 		cpu_clk.set_rate = NULL;
1566 		ahb_clk.parent = &mpll_clk;
1567 
1568 		for (i = 0; i < sizeof(per_clk) / sizeof(per_clk[0]); i++)
1569 			per_clk[i].parent = &mpll_clk;
1570 
1571 		ssi1_clk[0].parent = &mpll_clk;
1572 		ssi2_clk[0].parent = &mpll_clk;
1573 
1574 		vpu_clk.parent = &mpll_clk;
1575 	}
1576 }
1577 
1578 /*
1579  * must be called very early to get information about the
1580  * available clock rate when the timer framework starts
1581  */
mxc_clocks_init(unsigned long fref)1582 int __init mxc_clocks_init(unsigned long fref)
1583 {
1584 	u32 cscr;
1585 	struct clk **clkp;
1586 
1587 	external_high_reference = fref;
1588 
1589 	/* detect clock reference for both system PLL */
1590 	cscr = CSCR();
1591 	if (cscr & CCM_CSCR_MCU)
1592 		mpll_clk.parent = &ckih_clk;
1593 	else
1594 		mpll_clk.parent = &ckil_clk;
1595 
1596 	if (cscr & CCM_CSCR_SP)
1597 		spll_clk.parent = &ckih_clk;
1598 	else
1599 		spll_clk.parent = &ckil_clk;
1600 
1601 	probe_mxc_clocks();
1602 
1603 	per_clk[0].enable(&per_clk[0]);
1604 	gpt1_clk[1].enable(&gpt1_clk[1]);
1605 
1606 	for (clkp = mxc_clks; clkp < mxc_clks + ARRAY_SIZE(mxc_clks); clkp++)
1607 		clk_register(*clkp);
1608 
1609 	/* Turn off all possible clocks */
1610 	__raw_writel(CCM_PCCR0_GPT1_MASK, CCM_PCCR0);
1611 	__raw_writel(CCM_PCCR1_PERCLK1_MASK | CCM_PCCR1_HCLK_EMI_MASK,
1612 		     CCM_PCCR1);
1613 	spll_clk.disable(&spll_clk);
1614 
1615 	/* This will propagate to all children and init all the clock rates */
1616 
1617 	clk_enable(&emi_clk);
1618 	clk_enable(&gpio_clk);
1619 	clk_enable(&iim_clk);
1620 	clk_enable(&gpt1_clk[0]);
1621 #ifdef CONFIG_DEBUG_LL_CONSOLE
1622 	clk_enable(&uart1_clk[0]);
1623 #endif
1624 	return 0;
1625 }
1626