blob: 64862b31f1f2073fca718c1471c249dac40bfd4c [file] [log] [blame]
Stefano Babica521a772010-01-20 18:19:32 +01001/*
2 * (C) Copyright 2007
3 * Sascha Hauer, Pengutronix
4 *
5 * (C) Copyright 2009 Freescale Semiconductor, Inc.
6 *
7 * See file CREDITS for list of people who contributed to this
8 * project.
9 *
10 * This program is free software; you can redistribute it and/or
11 * modify it under the terms of the GNU General Public License as
12 * published by the Free Software Foundation; either version 2 of
13 * the License, or (at your option) any later version.
14 *
15 * This program is distributed in the hope that it will be useful,
16 * but WITHOUT ANY WARRANTY; without even the implied warranty of
17 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
18 * GNU General Public License for more details.
19 *
20 * You should have received a copy of the GNU General Public License
21 * along with this program; if not, write to the Free Software
22 * Foundation, Inc., 59 Temple Place, Suite 330, Boston,
23 * MA 02111-1307 USA
24 */
25
26#include <common.h>
27#include <asm/io.h>
28#include <asm/errno.h>
29#include <asm/arch/imx-regs.h>
30#include <asm/arch/crm_regs.h>
Stefano Babicac41d4d2010-03-05 17:54:37 +010031#include <asm/arch/clock.h>
Marek Vasut3c844f32011-09-23 11:43:47 +020032#include <div64.h>
Fabio Estevam6479f512012-04-29 08:11:13 +000033#include <asm/arch/sys_proto.h>
Stefano Babica521a772010-01-20 18:19:32 +010034
35enum pll_clocks {
36 PLL1_CLOCK = 0,
37 PLL2_CLOCK,
38 PLL3_CLOCK,
Marek Vasut3c844f32011-09-23 11:43:47 +020039 PLL4_CLOCK,
Stefano Babica521a772010-01-20 18:19:32 +010040 PLL_CLOCKS,
41};
42
43struct mxc_pll_reg *mxc_plls[PLL_CLOCKS] = {
44 [PLL1_CLOCK] = (struct mxc_pll_reg *)PLL1_BASE_ADDR,
45 [PLL2_CLOCK] = (struct mxc_pll_reg *)PLL2_BASE_ADDR,
46 [PLL3_CLOCK] = (struct mxc_pll_reg *)PLL3_BASE_ADDR,
Marek Vasut3c844f32011-09-23 11:43:47 +020047#ifdef CONFIG_MX53
48 [PLL4_CLOCK] = (struct mxc_pll_reg *)PLL4_BASE_ADDR,
49#endif
Stefano Babica521a772010-01-20 18:19:32 +010050};
51
Fabio Estevamb4121012012-04-30 08:12:02 +000052#define AHB_CLK_ROOT 133333333
53#define SZ_DEC_1M 1000000
54#define PLL_PD_MAX 16 /* Actual pd+1 */
55#define PLL_MFI_MAX 15
56#define PLL_MFI_MIN 5
57#define ARM_DIV_MAX 8
58#define IPG_DIV_MAX 4
59#define AHB_DIV_MAX 8
60#define EMI_DIV_MAX 8
61#define NFC_DIV_MAX 8
62
63#define MX5_CBCMR 0x00015154
64#define MX5_CBCDR 0x02888945
65
66struct fixed_pll_mfd {
67 u32 ref_clk_hz;
68 u32 mfd;
69};
70
71const struct fixed_pll_mfd fixed_mfd[] = {
72 {CONFIG_SYS_MX5_HCLK, 24 * 16},
73};
74
75struct pll_param {
76 u32 pd;
77 u32 mfi;
78 u32 mfn;
79 u32 mfd;
80};
81
82#define PLL_FREQ_MAX(ref_clk) (4 * (ref_clk) * PLL_MFI_MAX)
83#define PLL_FREQ_MIN(ref_clk) \
84 ((2 * (ref_clk) * (PLL_MFI_MIN - 1)) / PLL_PD_MAX)
85#define MAX_DDR_CLK 420000000
86#define NFC_CLK_MAX 34000000
87
Stefano Babicac41d4d2010-03-05 17:54:37 +010088struct mxc_ccm_reg *mxc_ccm = (struct mxc_ccm_reg *)MXC_CCM_BASE;
Stefano Babica521a772010-01-20 18:19:32 +010089
Wolfgang Grandegger8c1e4d32011-11-11 14:03:34 +010090void set_usboh3_clk(void)
91{
92 unsigned int reg;
93
94 reg = readl(&mxc_ccm->cscmr1) &
95 ~MXC_CCM_CSCMR1_USBOH3_CLK_SEL_MASK;
96 reg |= 1 << MXC_CCM_CSCMR1_USBOH3_CLK_SEL_OFFSET;
97 writel(reg, &mxc_ccm->cscmr1);
98
99 reg = readl(&mxc_ccm->cscdr1);
100 reg &= ~MXC_CCM_CSCDR1_USBOH3_CLK_PODF_MASK;
101 reg &= ~MXC_CCM_CSCDR1_USBOH3_CLK_PRED_MASK;
102 reg |= 4 << MXC_CCM_CSCDR1_USBOH3_CLK_PRED_OFFSET;
103 reg |= 1 << MXC_CCM_CSCDR1_USBOH3_CLK_PODF_OFFSET;
104
105 writel(reg, &mxc_ccm->cscdr1);
106}
107
108void enable_usboh3_clk(unsigned char enable)
109{
110 unsigned int reg;
111
112 reg = readl(&mxc_ccm->CCGR2);
113 if (enable)
114 reg |= 1 << MXC_CCM_CCGR2_CG14_OFFSET;
115 else
116 reg &= ~(1 << MXC_CCM_CCGR2_CG14_OFFSET);
117 writel(reg, &mxc_ccm->CCGR2);
118}
119
120void set_usb_phy1_clk(void)
121{
122 unsigned int reg;
123
124 reg = readl(&mxc_ccm->cscmr1);
125 reg &= ~MXC_CCM_CSCMR1_USB_PHY_CLK_SEL;
126 writel(reg, &mxc_ccm->cscmr1);
127}
128
129void enable_usb_phy1_clk(unsigned char enable)
130{
131 unsigned int reg;
132
133 reg = readl(&mxc_ccm->CCGR4);
134 if (enable)
135 reg |= 1 << MXC_CCM_CCGR4_CG5_OFFSET;
136 else
137 reg &= ~(1 << MXC_CCM_CCGR4_CG5_OFFSET);
138 writel(reg, &mxc_ccm->CCGR4);
139}
140
141void set_usb_phy2_clk(void)
142{
143 unsigned int reg;
144
145 reg = readl(&mxc_ccm->cscmr1);
146 reg &= ~MXC_CCM_CSCMR1_USB_PHY_CLK_SEL;
147 writel(reg, &mxc_ccm->cscmr1);
148}
149
150void enable_usb_phy2_clk(unsigned char enable)
151{
152 unsigned int reg;
153
154 reg = readl(&mxc_ccm->CCGR4);
155 if (enable)
156 reg |= 1 << MXC_CCM_CCGR4_CG6_OFFSET;
157 else
158 reg &= ~(1 << MXC_CCM_CCGR4_CG6_OFFSET);
159 writel(reg, &mxc_ccm->CCGR4);
160}
161
Stefano Babica521a772010-01-20 18:19:32 +0100162/*
Marek Vasut3c844f32011-09-23 11:43:47 +0200163 * Calculate the frequency of PLLn.
Stefano Babica521a772010-01-20 18:19:32 +0100164 */
Marek Vasut3c844f32011-09-23 11:43:47 +0200165static uint32_t decode_pll(struct mxc_pll_reg *pll, uint32_t infreq)
Stefano Babica521a772010-01-20 18:19:32 +0100166{
Marek Vasut3c844f32011-09-23 11:43:47 +0200167 uint32_t ctrl, op, mfd, mfn, mfi, pdf, ret;
168 uint64_t refclk, temp;
169 int32_t mfn_abs;
Stefano Babica521a772010-01-20 18:19:32 +0100170
Marek Vasut3c844f32011-09-23 11:43:47 +0200171 ctrl = readl(&pll->ctrl);
Stefano Babica521a772010-01-20 18:19:32 +0100172
Marek Vasut3c844f32011-09-23 11:43:47 +0200173 if (ctrl & MXC_DPLLC_CTL_HFSM) {
174 mfn = __raw_readl(&pll->hfs_mfn);
175 mfd = __raw_readl(&pll->hfs_mfd);
176 op = __raw_readl(&pll->hfs_op);
177 } else {
178 mfn = __raw_readl(&pll->mfn);
179 mfd = __raw_readl(&pll->mfd);
180 op = __raw_readl(&pll->op);
181 }
182
183 mfd &= MXC_DPLLC_MFD_MFD_MASK;
184 mfn &= MXC_DPLLC_MFN_MFN_MASK;
185 pdf = op & MXC_DPLLC_OP_PDF_MASK;
186 mfi = (op & MXC_DPLLC_OP_MFI_MASK) >> MXC_DPLLC_OP_MFI_OFFSET;
187
188 /* 21.2.3 */
189 if (mfi < 5)
190 mfi = 5;
191
192 /* Sign extend */
193 if (mfn >= 0x04000000) {
194 mfn |= 0xfc000000;
195 mfn_abs = -mfn;
196 } else
197 mfn_abs = mfn;
198
199 refclk = infreq * 2;
200 if (ctrl & MXC_DPLLC_CTL_DPDCK0_2_EN)
201 refclk *= 2;
202
Simon Glass3d557882011-11-05 04:25:22 +0000203 do_div(refclk, pdf + 1);
Marek Vasut3c844f32011-09-23 11:43:47 +0200204 temp = refclk * mfn_abs;
205 do_div(temp, mfd + 1);
206 ret = refclk * mfi;
207
208 if ((int)mfn < 0)
209 ret -= temp;
210 else
211 ret += temp;
212
213 return ret;
Stefano Babica521a772010-01-20 18:19:32 +0100214}
215
216/*
217 * Get mcu main rate
218 */
219u32 get_mcu_main_clk(void)
220{
221 u32 reg, freq;
222
223 reg = (__raw_readl(&mxc_ccm->cacrr) & MXC_CCM_CACRR_ARM_PODF_MASK) >>
224 MXC_CCM_CACRR_ARM_PODF_OFFSET;
Jason Liue7a7ed22010-10-18 11:09:26 +0800225 freq = decode_pll(mxc_plls[PLL1_CLOCK], CONFIG_SYS_MX5_HCLK);
Stefano Babica521a772010-01-20 18:19:32 +0100226 return freq / (reg + 1);
227}
228
229/*
230 * Get the rate of peripheral's root clock.
231 */
Fabio Estevam6479f512012-04-29 08:11:13 +0000232u32 get_periph_clk(void)
Stefano Babica521a772010-01-20 18:19:32 +0100233{
234 u32 reg;
235
236 reg = __raw_readl(&mxc_ccm->cbcdr);
237 if (!(reg & MXC_CCM_CBCDR_PERIPH_CLK_SEL))
Jason Liue7a7ed22010-10-18 11:09:26 +0800238 return decode_pll(mxc_plls[PLL2_CLOCK], CONFIG_SYS_MX5_HCLK);
Stefano Babica521a772010-01-20 18:19:32 +0100239 reg = __raw_readl(&mxc_ccm->cbcmr);
240 switch ((reg & MXC_CCM_CBCMR_PERIPH_CLK_SEL_MASK) >>
241 MXC_CCM_CBCMR_PERIPH_CLK_SEL_OFFSET) {
242 case 0:
Jason Liue7a7ed22010-10-18 11:09:26 +0800243 return decode_pll(mxc_plls[PLL1_CLOCK], CONFIG_SYS_MX5_HCLK);
Stefano Babica521a772010-01-20 18:19:32 +0100244 case 1:
Jason Liue7a7ed22010-10-18 11:09:26 +0800245 return decode_pll(mxc_plls[PLL3_CLOCK], CONFIG_SYS_MX5_HCLK);
Stefano Babica521a772010-01-20 18:19:32 +0100246 default:
247 return 0;
248 }
249 /* NOTREACHED */
250}
251
252/*
253 * Get the rate of ipg clock.
254 */
255static u32 get_ipg_clk(void)
256{
Marek Vasut6674bf52011-09-22 09:20:37 +0000257 uint32_t freq, reg, div;
Stefano Babica521a772010-01-20 18:19:32 +0100258
Marek Vasut6674bf52011-09-22 09:20:37 +0000259 freq = get_ahb_clk();
260
261 reg = __raw_readl(&mxc_ccm->cbcdr);
262 div = ((reg & MXC_CCM_CBCDR_IPG_PODF_MASK) >>
263 MXC_CCM_CBCDR_IPG_PODF_OFFSET) + 1;
264
265 return freq / div;
Stefano Babica521a772010-01-20 18:19:32 +0100266}
267
268/*
269 * Get the rate of ipg_per clock.
270 */
271static u32 get_ipg_per_clk(void)
272{
273 u32 pred1, pred2, podf;
274
275 if (__raw_readl(&mxc_ccm->cbcmr) & MXC_CCM_CBCMR_PERCLK_IPG_CLK_SEL)
276 return get_ipg_clk();
277 /* Fixme: not handle what about lpm*/
278 podf = __raw_readl(&mxc_ccm->cbcdr);
279 pred1 = (podf & MXC_CCM_CBCDR_PERCLK_PRED1_MASK) >>
280 MXC_CCM_CBCDR_PERCLK_PRED1_OFFSET;
281 pred2 = (podf & MXC_CCM_CBCDR_PERCLK_PRED2_MASK) >>
282 MXC_CCM_CBCDR_PERCLK_PRED2_OFFSET;
283 podf = (podf & MXC_CCM_CBCDR_PERCLK_PODF_MASK) >>
284 MXC_CCM_CBCDR_PERCLK_PODF_OFFSET;
285
286 return get_periph_clk() / ((pred1 + 1) * (pred2 + 1) * (podf + 1));
287}
288
289/*
290 * Get the rate of uart clk.
291 */
292static u32 get_uart_clk(void)
293{
294 unsigned int freq, reg, pred, podf;
295
296 reg = __raw_readl(&mxc_ccm->cscmr1);
297 switch ((reg & MXC_CCM_CSCMR1_UART_CLK_SEL_MASK) >>
298 MXC_CCM_CSCMR1_UART_CLK_SEL_OFFSET) {
299 case 0x0:
300 freq = decode_pll(mxc_plls[PLL1_CLOCK],
Jason Liue7a7ed22010-10-18 11:09:26 +0800301 CONFIG_SYS_MX5_HCLK);
Stefano Babica521a772010-01-20 18:19:32 +0100302 break;
303 case 0x1:
304 freq = decode_pll(mxc_plls[PLL2_CLOCK],
Jason Liue7a7ed22010-10-18 11:09:26 +0800305 CONFIG_SYS_MX5_HCLK);
Stefano Babica521a772010-01-20 18:19:32 +0100306 break;
307 case 0x2:
308 freq = decode_pll(mxc_plls[PLL3_CLOCK],
Jason Liue7a7ed22010-10-18 11:09:26 +0800309 CONFIG_SYS_MX5_HCLK);
Stefano Babica521a772010-01-20 18:19:32 +0100310 break;
311 default:
312 return 66500000;
313 }
314
315 reg = __raw_readl(&mxc_ccm->cscdr1);
316
317 pred = (reg & MXC_CCM_CSCDR1_UART_CLK_PRED_MASK) >>
318 MXC_CCM_CSCDR1_UART_CLK_PRED_OFFSET;
319
320 podf = (reg & MXC_CCM_CSCDR1_UART_CLK_PODF_MASK) >>
321 MXC_CCM_CSCDR1_UART_CLK_PODF_OFFSET;
322 freq /= (pred + 1) * (podf + 1);
323
324 return freq;
325}
326
327/*
328 * This function returns the low power audio clock.
329 */
Fabio Estevamb4121012012-04-30 08:12:02 +0000330static u32 get_lp_apm(void)
Stefano Babica521a772010-01-20 18:19:32 +0100331{
332 u32 ret_val = 0;
333 u32 ccsr = __raw_readl(&mxc_ccm->ccsr);
334
335 if (((ccsr >> 9) & 1) == 0)
Jason Liue7a7ed22010-10-18 11:09:26 +0800336 ret_val = CONFIG_SYS_MX5_HCLK;
Stefano Babica521a772010-01-20 18:19:32 +0100337 else
338 ret_val = ((32768 * 1024));
339
340 return ret_val;
341}
342
343/*
344 * get cspi clock rate.
345 */
Fabio Estevamb4121012012-04-30 08:12:02 +0000346static u32 imx_get_cspiclk(void)
Stefano Babica521a772010-01-20 18:19:32 +0100347{
348 u32 ret_val = 0, pdf, pre_pdf, clk_sel;
349 u32 cscmr1 = __raw_readl(&mxc_ccm->cscmr1);
350 u32 cscdr2 = __raw_readl(&mxc_ccm->cscdr2);
351
352 pre_pdf = (cscdr2 & MXC_CCM_CSCDR2_CSPI_CLK_PRED_MASK) \
353 >> MXC_CCM_CSCDR2_CSPI_CLK_PRED_OFFSET;
354 pdf = (cscdr2 & MXC_CCM_CSCDR2_CSPI_CLK_PODF_MASK) \
355 >> MXC_CCM_CSCDR2_CSPI_CLK_PODF_OFFSET;
356 clk_sel = (cscmr1 & MXC_CCM_CSCMR1_CSPI_CLK_SEL_MASK) \
357 >> MXC_CCM_CSCMR1_CSPI_CLK_SEL_OFFSET;
358
359 switch (clk_sel) {
360 case 0:
361 ret_val = decode_pll(mxc_plls[PLL1_CLOCK],
Jason Liue7a7ed22010-10-18 11:09:26 +0800362 CONFIG_SYS_MX5_HCLK) /
Stefano Babica521a772010-01-20 18:19:32 +0100363 ((pre_pdf + 1) * (pdf + 1));
364 break;
365 case 1:
366 ret_val = decode_pll(mxc_plls[PLL2_CLOCK],
Jason Liue7a7ed22010-10-18 11:09:26 +0800367 CONFIG_SYS_MX5_HCLK) /
Stefano Babica521a772010-01-20 18:19:32 +0100368 ((pre_pdf + 1) * (pdf + 1));
369 break;
370 case 2:
371 ret_val = decode_pll(mxc_plls[PLL3_CLOCK],
Jason Liue7a7ed22010-10-18 11:09:26 +0800372 CONFIG_SYS_MX5_HCLK) /
Stefano Babica521a772010-01-20 18:19:32 +0100373 ((pre_pdf + 1) * (pdf + 1));
374 break;
375 default:
376 ret_val = get_lp_apm() / ((pre_pdf + 1) * (pdf + 1));
377 break;
378 }
379
380 return ret_val;
381}
382
Fabio Estevamb4121012012-04-30 08:12:02 +0000383static u32 get_axi_a_clk(void)
384{
385 u32 cbcdr = __raw_readl(&mxc_ccm->cbcdr);
386 u32 pdf = (cbcdr & MXC_CCM_CBCDR_AXI_A_PODF_MASK) \
387 >> MXC_CCM_CBCDR_AXI_A_PODF_OFFSET;
388
389 return get_periph_clk() / (pdf + 1);
390}
391
392static u32 get_axi_b_clk(void)
393{
394 u32 cbcdr = __raw_readl(&mxc_ccm->cbcdr);
395 u32 pdf = (cbcdr & MXC_CCM_CBCDR_AXI_B_PODF_MASK) \
396 >> MXC_CCM_CBCDR_AXI_B_PODF_OFFSET;
397
398 return get_periph_clk() / (pdf + 1);
399}
400
401static u32 get_emi_slow_clk(void)
402{
403 u32 cbcdr = __raw_readl(&mxc_ccm->cbcdr);
404 u32 emi_clk_sel = cbcdr & MXC_CCM_CBCDR_EMI_CLK_SEL;
405 u32 pdf = (cbcdr & MXC_CCM_CBCDR_EMI_PODF_MASK) \
406 >> MXC_CCM_CBCDR_EMI_PODF_OFFSET;
407
408 if (emi_clk_sel)
409 return get_ahb_clk() / (pdf + 1);
410
411 return get_periph_clk() / (pdf + 1);
412}
413
414static u32 get_ddr_clk(void)
415{
416 u32 ret_val = 0;
417 u32 cbcmr = __raw_readl(&mxc_ccm->cbcmr);
418 u32 ddr_clk_sel = (cbcmr & MXC_CCM_CBCMR_DDR_CLK_SEL_MASK) \
419 >> MXC_CCM_CBCMR_DDR_CLK_SEL_OFFSET;
420#ifdef CONFIG_MX51
421 u32 cbcdr = __raw_readl(&mxc_ccm->cbcdr);
422 if (cbcdr & MXC_CCM_CBCDR_DDR_HIFREQ_SEL) {
423 u32 ddr_clk_podf = (cbcdr & MXC_CCM_CBCDR_DDR_PODF_MASK) >> \
424 MXC_CCM_CBCDR_DDR_PODF_OFFSET;
425
426 ret_val = decode_pll(mxc_plls[PLL1_CLOCK], CONFIG_SYS_MX5_HCLK);
427 ret_val /= ddr_clk_podf + 1;
428
429 return ret_val;
430 }
431#endif
432 switch (ddr_clk_sel) {
433 case 0:
434 ret_val = get_axi_a_clk();
435 break;
436 case 1:
437 ret_val = get_axi_b_clk();
438 break;
439 case 2:
440 ret_val = get_emi_slow_clk();
441 break;
442 case 3:
443 ret_val = get_ahb_clk();
444 break;
445 default:
446 break;
447 }
448
449 return ret_val;
450}
451
Stefano Babica521a772010-01-20 18:19:32 +0100452/*
Fabio Estevamb4121012012-04-30 08:12:02 +0000453 * The API of get mxc clocks.
Stefano Babica521a772010-01-20 18:19:32 +0100454 */
455unsigned int mxc_get_clock(enum mxc_clock clk)
456{
457 switch (clk) {
458 case MXC_ARM_CLK:
459 return get_mcu_main_clk();
460 case MXC_AHB_CLK:
Marek Vasut6674bf52011-09-22 09:20:37 +0000461 return get_ahb_clk();
Stefano Babica521a772010-01-20 18:19:32 +0100462 case MXC_IPG_CLK:
463 return get_ipg_clk();
464 case MXC_IPG_PERCLK:
465 return get_ipg_per_clk();
466 case MXC_UART_CLK:
467 return get_uart_clk();
468 case MXC_CSPI_CLK:
469 return imx_get_cspiclk();
470 case MXC_FEC_CLK:
471 return decode_pll(mxc_plls[PLL1_CLOCK],
Jason Liue7a7ed22010-10-18 11:09:26 +0800472 CONFIG_SYS_MX5_HCLK);
Stefano Babicd38db762012-02-22 00:24:36 +0000473 case MXC_SATA_CLK:
474 return get_ahb_clk();
Fabio Estevamb4121012012-04-30 08:12:02 +0000475 case MXC_DDR_CLK:
476 return get_ddr_clk();
Stefano Babica521a772010-01-20 18:19:32 +0100477 default:
478 break;
479 }
Fabio Estevamb4121012012-04-30 08:12:02 +0000480 return -EINVAL;
Stefano Babica521a772010-01-20 18:19:32 +0100481}
482
483u32 imx_get_uartclk(void)
484{
485 return get_uart_clk();
486}
487
488
489u32 imx_get_fecclk(void)
490{
491 return mxc_get_clock(MXC_IPG_CLK);
492}
493
Fabio Estevamb4121012012-04-30 08:12:02 +0000494static int gcd(int m, int n)
495{
496 int t;
497 while (m > 0) {
498 if (n > m) {
499 t = m;
500 m = n;
501 n = t;
502 } /* swap */
503 m -= n;
504 }
505 return n;
506}
507
508/*
509 * This is to calculate various parameters based on reference clock and
510 * targeted clock based on the equation:
511 * t_clk = 2*ref_freq*(mfi + mfn/(mfd+1))/(pd+1)
512 * This calculation is based on a fixed MFD value for simplicity.
513 */
514static int calc_pll_params(u32 ref, u32 target, struct pll_param *pll)
515{
516 u64 pd, mfi = 1, mfn, mfd, t1;
517 u32 n_target = target;
518 u32 n_ref = ref, i;
519
520 /*
521 * Make sure targeted freq is in the valid range.
522 * Otherwise the following calculation might be wrong!!!
523 */
524 if (n_target < PLL_FREQ_MIN(ref) ||
525 n_target > PLL_FREQ_MAX(ref)) {
526 printf("Targeted peripheral clock should be"
527 "within [%d - %d]\n",
528 PLL_FREQ_MIN(ref) / SZ_DEC_1M,
529 PLL_FREQ_MAX(ref) / SZ_DEC_1M);
530 return -EINVAL;
531 }
532
533 for (i = 0; i < ARRAY_SIZE(fixed_mfd); i++) {
534 if (fixed_mfd[i].ref_clk_hz == ref) {
535 mfd = fixed_mfd[i].mfd;
536 break;
537 }
538 }
539
540 if (i == ARRAY_SIZE(fixed_mfd))
541 return -EINVAL;
542
543 /* Use n_target and n_ref to avoid overflow */
544 for (pd = 1; pd <= PLL_PD_MAX; pd++) {
545 t1 = n_target * pd;
546 do_div(t1, (4 * n_ref));
547 mfi = t1;
548 if (mfi > PLL_MFI_MAX)
549 return -EINVAL;
550 else if (mfi < 5)
551 continue;
552 break;
553 }
554 /*
555 * Now got pd and mfi already
556 *
557 * mfn = (((n_target * pd) / 4 - n_ref * mfi) * mfd) / n_ref;
558 */
559 t1 = n_target * pd;
560 do_div(t1, 4);
561 t1 -= n_ref * mfi;
562 t1 *= mfd;
563 do_div(t1, n_ref);
564 mfn = t1;
565 debug("ref=%d, target=%d, pd=%d," "mfi=%d,mfn=%d, mfd=%d\n",
566 ref, n_target, (u32)pd, (u32)mfi, (u32)mfn, (u32)mfd);
567 i = 1;
568 if (mfn != 0)
569 i = gcd(mfd, mfn);
570 pll->pd = (u32)pd;
571 pll->mfi = (u32)mfi;
572 do_div(mfn, i);
573 pll->mfn = (u32)mfn;
574 do_div(mfd, i);
575 pll->mfd = (u32)mfd;
576
577 return 0;
578}
579
580#define calc_div(tgt_clk, src_clk, limit) ({ \
581 u32 v = 0; \
582 if (((src_clk) % (tgt_clk)) <= 100) \
583 v = (src_clk) / (tgt_clk); \
584 else \
585 v = ((src_clk) / (tgt_clk)) + 1;\
586 if (v > limit) \
587 v = limit; \
588 (v - 1); \
589 })
590
591#define CHANGE_PLL_SETTINGS(pll, pd, fi, fn, fd) \
592 { \
593 __raw_writel(0x1232, &pll->ctrl); \
594 __raw_writel(0x2, &pll->config); \
595 __raw_writel((((pd) - 1) << 0) | ((fi) << 4), \
596 &pll->op); \
597 __raw_writel(fn, &(pll->mfn)); \
598 __raw_writel((fd) - 1, &pll->mfd); \
599 __raw_writel((((pd) - 1) << 0) | ((fi) << 4), \
600 &pll->hfs_op); \
601 __raw_writel(fn, &pll->hfs_mfn); \
602 __raw_writel((fd) - 1, &pll->hfs_mfd); \
603 __raw_writel(0x1232, &pll->ctrl); \
604 while (!__raw_readl(&pll->ctrl) & 0x1) \
605 ;\
606 }
607
608static int config_pll_clk(enum pll_clocks index, struct pll_param *pll_param)
609{
610 u32 ccsr = __raw_readl(&mxc_ccm->ccsr);
611 struct mxc_pll_reg *pll = mxc_plls[index];
612
613 switch (index) {
614 case PLL1_CLOCK:
615 /* Switch ARM to PLL2 clock */
616 __raw_writel(ccsr | 0x4, &mxc_ccm->ccsr);
617 CHANGE_PLL_SETTINGS(pll, pll_param->pd,
618 pll_param->mfi, pll_param->mfn,
619 pll_param->mfd);
620 /* Switch back */
621 __raw_writel(ccsr & ~0x4, &mxc_ccm->ccsr);
622 break;
623 case PLL2_CLOCK:
624 /* Switch to pll2 bypass clock */
625 __raw_writel(ccsr | 0x2, &mxc_ccm->ccsr);
626 CHANGE_PLL_SETTINGS(pll, pll_param->pd,
627 pll_param->mfi, pll_param->mfn,
628 pll_param->mfd);
629 /* Switch back */
630 __raw_writel(ccsr & ~0x2, &mxc_ccm->ccsr);
631 break;
632 case PLL3_CLOCK:
633 /* Switch to pll3 bypass clock */
634 __raw_writel(ccsr | 0x1, &mxc_ccm->ccsr);
635 CHANGE_PLL_SETTINGS(pll, pll_param->pd,
636 pll_param->mfi, pll_param->mfn,
637 pll_param->mfd);
638 /* Switch back */
639 __raw_writel(ccsr & ~0x1, &mxc_ccm->ccsr);
640 break;
641 case PLL4_CLOCK:
642 /* Switch to pll4 bypass clock */
643 __raw_writel(ccsr | 0x20, &mxc_ccm->ccsr);
644 CHANGE_PLL_SETTINGS(pll, pll_param->pd,
645 pll_param->mfi, pll_param->mfn,
646 pll_param->mfd);
647 /* Switch back */
648 __raw_writel(ccsr & ~0x20, &mxc_ccm->ccsr);
649 break;
650 default:
651 return -EINVAL;
652 }
653
654 return 0;
655}
656
657/* Config CPU clock */
658static int config_core_clk(u32 ref, u32 freq)
659{
660 int ret = 0;
661 struct pll_param pll_param;
662
663 memset(&pll_param, 0, sizeof(struct pll_param));
664
665 /* The case that periph uses PLL1 is not considered here */
666 ret = calc_pll_params(ref, freq, &pll_param);
667 if (ret != 0) {
668 printf("Error:Can't find pll parameters: %d\n", ret);
669 return ret;
670 }
671
672 return config_pll_clk(PLL1_CLOCK, &pll_param);
673}
674
675static int config_nfc_clk(u32 nfc_clk)
676{
677 u32 reg;
678 u32 parent_rate = get_emi_slow_clk();
679 u32 div = parent_rate / nfc_clk;
680
681 if (nfc_clk <= 0)
682 return -EINVAL;
683 if (div == 0)
684 div++;
685 if (parent_rate / div > NFC_CLK_MAX)
686 div++;
687 reg = __raw_readl(&mxc_ccm->cbcdr);
688 reg &= ~MXC_CCM_CBCDR_NFC_PODF_MASK;
689 reg |= (div - 1) << MXC_CCM_CBCDR_NFC_PODF_OFFSET;
690 __raw_writel(reg, &mxc_ccm->cbcdr);
691 while (__raw_readl(&mxc_ccm->cdhipr) != 0)
692 ;
693 return 0;
694}
695
696/* Config main_bus_clock for periphs */
697static int config_periph_clk(u32 ref, u32 freq)
698{
699 int ret = 0;
700 struct pll_param pll_param;
701
702 memset(&pll_param, 0, sizeof(struct pll_param));
703
704 if (__raw_readl(&mxc_ccm->cbcdr) & MXC_CCM_CBCDR_PERIPH_CLK_SEL) {
705 ret = calc_pll_params(ref, freq, &pll_param);
706 if (ret != 0) {
707 printf("Error:Can't find pll parameters: %d\n",
708 ret);
709 return ret;
710 }
711 switch ((__raw_readl(&mxc_ccm->cbcmr) & \
712 MXC_CCM_CBCMR_PERIPH_CLK_SEL_MASK) >> \
713 MXC_CCM_CBCMR_PERIPH_CLK_SEL_OFFSET) {
714 case 0:
715 return config_pll_clk(PLL1_CLOCK, &pll_param);
716 break;
717 case 1:
718 return config_pll_clk(PLL3_CLOCK, &pll_param);
719 break;
720 default:
721 return -EINVAL;
722 }
723 }
724
725 return 0;
726}
727
728static int config_ddr_clk(u32 emi_clk)
729{
730 u32 clk_src;
731 s32 shift = 0, clk_sel, div = 1;
732 u32 cbcmr = __raw_readl(&mxc_ccm->cbcmr);
733 u32 cbcdr = __raw_readl(&mxc_ccm->cbcdr);
734
735 if (emi_clk > MAX_DDR_CLK) {
736 printf("Warning:DDR clock should not exceed %d MHz\n",
737 MAX_DDR_CLK / SZ_DEC_1M);
738 emi_clk = MAX_DDR_CLK;
739 }
740
741 clk_src = get_periph_clk();
742 /* Find DDR clock input */
743 clk_sel = (cbcmr >> 10) & 0x3;
744 switch (clk_sel) {
745 case 0:
746 shift = 16;
747 break;
748 case 1:
749 shift = 19;
750 break;
751 case 2:
752 shift = 22;
753 break;
754 case 3:
755 shift = 10;
756 break;
757 default:
758 return -EINVAL;
759 }
760
761 if ((clk_src % emi_clk) < 10000000)
762 div = clk_src / emi_clk;
763 else
764 div = (clk_src / emi_clk) + 1;
765 if (div > 8)
766 div = 8;
767
768 cbcdr = cbcdr & ~(0x7 << shift);
769 cbcdr |= ((div - 1) << shift);
770 __raw_writel(cbcdr, &mxc_ccm->cbcdr);
771 while (__raw_readl(&mxc_ccm->cdhipr) != 0)
772 ;
773 __raw_writel(0x0, &mxc_ccm->ccdr);
774
775 return 0;
776}
777
778/*
779 * This function assumes the expected core clock has to be changed by
780 * modifying the PLL. This is NOT true always but for most of the times,
781 * it is. So it assumes the PLL output freq is the same as the expected
782 * core clock (presc=1) unless the core clock is less than PLL_FREQ_MIN.
783 * In the latter case, it will try to increase the presc value until
784 * (presc*core_clk) is greater than PLL_FREQ_MIN. It then makes call to
785 * calc_pll_params() and obtains the values of PD, MFI,MFN, MFD based
786 * on the targeted PLL and reference input clock to the PLL. Lastly,
787 * it sets the register based on these values along with the dividers.
788 * Note 1) There is no value checking for the passed-in divider values
789 * so the caller has to make sure those values are sensible.
790 * 2) Also adjust the NFC divider such that the NFC clock doesn't
791 * exceed NFC_CLK_MAX.
792 * 3) IPU HSP clock is independent of AHB clock. Even it can go up to
793 * 177MHz for higher voltage, this function fixes the max to 133MHz.
794 * 4) This function should not have allowed diag_printf() calls since
795 * the serial driver has been stoped. But leave then here to allow
796 * easy debugging by NOT calling the cyg_hal_plf_serial_stop().
797 */
798int mxc_set_clock(u32 ref, u32 freq, enum mxc_clock clk)
799{
800 freq *= SZ_DEC_1M;
801
802 switch (clk) {
803 case MXC_ARM_CLK:
804 if (config_core_clk(ref, freq))
805 return -EINVAL;
806 break;
807 case MXC_PERIPH_CLK:
808 if (config_periph_clk(ref, freq))
809 return -EINVAL;
810 break;
811 case MXC_DDR_CLK:
812 if (config_ddr_clk(freq))
813 return -EINVAL;
814 break;
815 case MXC_NFC_CLK:
816 if (config_nfc_clk(freq))
817 return -EINVAL;
818 break;
819 default:
820 printf("Warning:Unsupported or invalid clock type\n");
821 }
822
823 return 0;
824}
825
Stefano Babicc378abf2012-02-22 00:24:38 +0000826#ifdef CONFIG_MX53
827/*
828 * The clock for the external interface can be set to use internal clock
829 * if fuse bank 4, row 3, bit 2 is set.
830 * This is an undocumented feature and it was confirmed by Freescale's support:
831 * Fuses (but not pins) may be used to configure SATA clocks.
832 * Particularly the i.MX53 Fuse_Map contains the next information
833 * about configuring SATA clocks : SATA_ALT_REF_CLK[1:0] (offset 0x180C)
834 * '00' - 100MHz (External)
835 * '01' - 50MHz (External)
836 * '10' - 120MHz, internal (USB PHY)
837 * '11' - Reserved
838*/
839void mxc_set_sata_internal_clock(void)
840{
841 u32 *tmp_base =
842 (u32 *)(IIM_BASE_ADDR + 0x180c);
843
844 set_usb_phy1_clk();
845
Fabio Estevamcd7ec872012-05-11 14:39:11 +0000846 writel((readl(tmp_base) & (~0x6)) | 0x4, tmp_base);
Stefano Babicc378abf2012-02-22 00:24:38 +0000847}
848#endif
849
Stefano Babica521a772010-01-20 18:19:32 +0100850/*
851 * Dump some core clockes.
852 */
Stefano Babic6eb90102010-10-28 11:08:52 +0200853int do_mx5_showclocks(cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[])
Stefano Babica521a772010-01-20 18:19:32 +0100854{
855 u32 freq;
856
Jason Liue7a7ed22010-10-18 11:09:26 +0800857 freq = decode_pll(mxc_plls[PLL1_CLOCK], CONFIG_SYS_MX5_HCLK);
Marek Vasut421bf452011-09-14 14:09:04 +0000858 printf("PLL1 %8d MHz\n", freq / 1000000);
Jason Liue7a7ed22010-10-18 11:09:26 +0800859 freq = decode_pll(mxc_plls[PLL2_CLOCK], CONFIG_SYS_MX5_HCLK);
Marek Vasut421bf452011-09-14 14:09:04 +0000860 printf("PLL2 %8d MHz\n", freq / 1000000);
Jason Liue7a7ed22010-10-18 11:09:26 +0800861 freq = decode_pll(mxc_plls[PLL3_CLOCK], CONFIG_SYS_MX5_HCLK);
Marek Vasut421bf452011-09-14 14:09:04 +0000862 printf("PLL3 %8d MHz\n", freq / 1000000);
Marek Vasut3c844f32011-09-23 11:43:47 +0200863#ifdef CONFIG_MX53
864 freq = decode_pll(mxc_plls[PLL4_CLOCK], CONFIG_SYS_MX5_HCLK);
Marek Vasut421bf452011-09-14 14:09:04 +0000865 printf("PLL4 %8d MHz\n", freq / 1000000);
Marek Vasut3c844f32011-09-23 11:43:47 +0200866#endif
Marek Vasut421bf452011-09-14 14:09:04 +0000867
868 printf("\n");
869 printf("AHB %8d kHz\n", mxc_get_clock(MXC_AHB_CLK) / 1000);
870 printf("IPG %8d kHz\n", mxc_get_clock(MXC_IPG_CLK) / 1000);
871 printf("IPG PERCLK %8d kHz\n", mxc_get_clock(MXC_IPG_PERCLK) / 1000);
Fabio Estevamb4121012012-04-30 08:12:02 +0000872 printf("DDR %8d kHz\n", mxc_get_clock(MXC_DDR_CLK) / 1000);
Stefano Babica521a772010-01-20 18:19:32 +0100873
874 return 0;
875}
876
877/***************************************************/
878
879U_BOOT_CMD(
Stefano Babicc8a02c32011-08-17 17:52:40 +0200880 clocks, CONFIG_SYS_MAXARGS, 1, do_mx5_showclocks,
881 "display clocks",
Stefano Babica521a772010-01-20 18:19:32 +0100882 ""
883);