1 //==========================================================================
5 // SoC [platform] specific RedBoot commands
7 //==========================================================================
8 //####ECOSGPLCOPYRIGHTBEGIN####
9 // -------------------------------------------
10 // This file is part of eCos, the Embedded Configurable Operating System.
11 // Copyright (C) 1998, 1999, 2000, 2001, 2002 Red Hat, Inc.
13 // eCos is free software; you can redistribute it and/or modify it under
14 // the terms of the GNU General Public License as published by the Free
15 // Software Foundation; either version 2 or (at your option) any later version.
17 // eCos is distributed in the hope that it will be useful, but WITHOUT ANY
18 // WARRANTY; without even the implied warranty of MERCHANTABILITY or
19 // FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
22 // You should have received a copy of the GNU General Public License along
23 // with eCos; if not, write to the Free Software Foundation, Inc.,
24 // 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
26 // As a special exception, if other files instantiate templates or use macros
27 // or inline functions from this file, or you compile this file and link it
28 // with other works to produce a work based on this file, this file does not
29 // by itself cause the resulting work to be covered by the GNU General Public
30 // License. However the source code for this file must still be made available
31 // in accordance with section (3) of the GNU General Public License.
33 // This exception does not invalidate any other reasons why a work based on
34 // this file might be covered by the GNU General Public License.
36 // Alternative licenses for eCos may be arranged by contacting Red Hat, Inc.
37 // at http://sources.redhat.com/ecos/ecos-license/
38 // -------------------------------------------
39 //####ECOSGPLCOPYRIGHTEND####
40 //==========================================================================
42 #include <cyg/hal/hal_intr.h>
43 #include <cyg/hal/plf_mmap.h>
44 #include <cyg/hal/hal_soc.h> // Hardware definitions
45 #include <cyg/hal/hal_cache.h>
47 typedef unsigned long long u64;
48 typedef unsigned int u32;
49 typedef unsigned short u16;
50 typedef unsigned char u8;
52 #define SZ_DEC_1M 1000000
53 #define PLL_PD_MAX 16 //actual pd+1
54 #define PLL_MFI_MAX 15
56 #define PLL_MFD_MAX 1024 //actual mfd+1
57 #define PLL_MFN_MAX 511
61 #define HSP_PODF_MAX 8
62 #define NFC_PODF_MAX 8
64 #define PLL_FREQ_MAX (2 * PLL_REF_CLK * PLL_MFI_MAX)
65 #define PLL_FREQ_MIN ((2 * PLL_REF_CLK * (PLL_MFI_MIN - 1)) / PLL_PD_MAX)
66 #define AHB_CLK_MAX 133333333
67 #define IPG_CLK_MAX (AHB_CLK_MAX / 2)
68 #define NFC_CLK_MAX 25000000
69 // IPU-HSP clock is independent of the HCLK and can go up to 177MHz but requires
70 // higher voltage support. For simplicity, limit it to 133MHz
71 #define HSP_CLK_MAX 133333333
73 #define ERR_WRONG_CLK -1
77 #define ERR_NO_PRESC -5
78 #define ERR_NO_AHB_DIV -6
80 u32 pll_clock(enum plls pll);
81 u32 get_main_clock(enum main_clocks clk);
82 u32 get_peri_clock(enum peri_clocks clk);
84 static u32 pll_mfd_fixed;
86 static void clock_setup(int argc, char *argv[]);
87 static void clko(int argc, char *argv[]);
88 extern unsigned int g_clock_src;
91 "Setup/Display clock (max AHB=133MHz, max IPG=66.5MHz)\nSyntax:",
92 "[<core clock in MHz> [:<AHB-to-core divider>[:<IPG-to-AHB divider>]]] \n\n\
93 If a divider is zero or no divider is specified, the optimal divider values \n\
94 will be chosen. Examples:\n\
95 [clock] -> Show various clocks\n\
96 [clock 532] -> Core=532 AHB=133 IPG=66.5\n\
97 [clock 399] -> Core=399 AHB=133 IPG=66.5\n\
98 [clock 532:8] -> Core=532 AHB=66.5(Core/8) IPG=66.5\n\
99 [clock 532:8:2] -> Core=532 AHB=66.5(Core/8) IPG=33.25(AHB/2)\n",
104 * This is to calculate various parameters based on reference clock and
105 * targeted clock based on the equation:
106 * t_clk = 2*ref_freq*(mfi + mfn/(mfd+1))/(pd+1)
107 * This calculation is based on a fixed MFD value for simplicity.
109 * @param ref reference clock freq
110 * @param target targeted clock in HZ
111 * @param p_pd calculated pd value (pd value from register + 1) upon return
112 * @param p_mfi calculated actual mfi value upon return
113 * @param p_mfn calculated actual mfn value upon return
114 * @param p_mfd fixed mfd value (mfd value from register + 1) upon return
116 * @return 0 if successful; non-zero otherwise.
118 int calc_pll_params(u32 ref, u32 target, u32 *p_pd,
119 u32 *p_mfi, u32 *p_mfn, u32 *p_mfd)
121 u64 pd, mfi, mfn, n_target = (u64)target, n_ref = (u64)ref;
123 if (g_clock_src == FREQ_26MHZ) {
124 pll_mfd_fixed = 26 * 16;
125 } else if (g_clock_src == FREQ_27MHZ) {
126 pll_mfd_fixed = 27 * 16;
128 pll_mfd_fixed = 1024;
131 // Make sure targeted freq is in the valid range. Otherwise the
132 // following calculation might be wrong!!!
133 if (target < PLL_FREQ_MIN || target > PLL_FREQ_MAX) {
134 return ERR_WRONG_CLK;
136 // Use n_target and n_ref to avoid overflow
137 for (pd = 1; pd <= PLL_PD_MAX; pd++) {
138 mfi = (n_target * pd) / (2 * n_ref);
139 if (mfi > PLL_MFI_MAX) {
141 } else if (mfi < 5) {
146 // Now got pd and mfi already
147 mfn = (((n_target * pd) / 2 - n_ref * mfi) * pll_mfd_fixed) / n_ref;
148 // Check mfn within limit and mfn < denominator
149 if (mfn > PLL_MFN_MAX || mfn >= pll_mfd_fixed) {
153 if (pd > PLL_PD_MAX) {
159 *p_mfd = pll_mfd_fixed;
164 * This function assumes the expected core clock has to be changed by
165 * modifying the PLL. This is NOT true always but for most of the times,
166 * it is. So it assumes the PLL output freq is the same as the expected
167 * core clock (presc=1) unless the core clock is less than PLL_FREQ_MIN.
168 * In the latter case, it will try to increase the presc value until
169 * (presc*core_clk) is greater than PLL_FREQ_MIN. It then makes call to
170 * calc_pll_params() and obtains the values of PD, MFI,MFN, MFD based
171 * on the targeted PLL and reference input clock to the PLL. Lastly,
172 * it sets the register based on these values along with the dividers.
173 * Note 1) There is no value checking for the passed-in divider values
174 * so the caller has to make sure those values are sensible.
175 * 2) Also adjust the NFC divider such that the NFC clock doesn't
176 * exceed NFC_CLK_MAX.
177 * 3) IPU HSP clock is independent of AHB clock. Even it can go up to
178 * 177MHz for higher voltage, this function fixes the max to 133MHz.
179 * 4) This function should not have allowed diag_printf() calls since
180 * the serial driver has been stoped. But leave then here to allow
181 * easy debugging by NOT calling the cyg_hal_plf_serial_stop().
183 * @param ref pll input reference clock (32KHz or 26MHz)
184 * @param core_clk core clock in Hz
185 * @param ahb_div ahb divider to divide the core clock to get ahb clock
186 * (ahb_div - 1) needs to be set in the register
187 * @param ipg_div ipg divider to divide the ahb clock to get ipg clock
188 * (ipg_div - 1) needs to be set in the register
189 # @return 0 if successful; non-zero otherwise
191 int configure_clock(u32 ref, u32 core_clk, u32 ahb_div, u32 ipg_div)
193 u32 pll, presc = 1, pd, mfi, mfn, mfd, brmo = 0, mpctl0, hsp_div;
197 // assume pll default to core clock first
199 // when core_clk >= PLL_FREQ_MIN, the presc can be 1.
200 // Otherwise, need to calculate presc value below and adjust the targeted pll
201 if (core_clk < PLL_FREQ_MIN) {
202 for (presc = 1; presc <= PRESC_MAX; presc++) {
203 if ((core_clk * presc) > PLL_FREQ_MIN) {
207 if (presc == (PRESC_MAX + 1)) {
208 diag_printf("can't make presc=%d\n", presc);
211 pll = core_clk * presc;
214 for (hsp_div = 1; hsp_div <= HSP_PODF_MAX; hsp_div++) {
215 if ((pll / hsp_div) <= HSP_CLK_MAX) {
219 if (hsp_div == (HSP_PODF_MAX + 1)) {
220 diag_printf("can't make hsp_div=%d\n", hsp_div);
224 // get nfc_div - make sure optimal NFC clock but less than NFC_CLK_MAX
225 for (nfc_div = 1; nfc_div <= NFC_PODF_MAX; nfc_div++) {
226 if ((pll / (ahb_div * nfc_div)) <= NFC_CLK_MAX) {
231 // pll is now the targeted pll output. Use it along with ref input clock
232 // to get pd, mfi, mfn, mfd
233 if ((ret = calc_pll_params(ref, pll, &pd, &mfi, &mfn, &mfd)) != 0) {
234 diag_printf("can't find pll parameters: %d\n", ret);
237 #ifdef CMD_CLOCK_DEBUG
238 diag_printf("ref=%d, pll=%d, pd=%d, mfi=%d,mfn=%d, mfd=%d\n",
239 ref, pll, pd, mfi, mfn, mfd);
242 // blindly increase divider first to avoid too fast ahbclk and ipgclk
243 // in case the core clock increases too much
244 pdr0 = readl(CCM_BASE_ADDR + CLKCTL_PDR0);
246 // increase the dividers. should work even when core clock is 832 (26*2*16)MHz
247 // which is unlikely true.
248 pdr0 |= (1 << 6) | (6 << 3) | (0 << 0);
249 writel(pdr0, CCM_BASE_ADDR + CLKCTL_PDR0);
250 // calculate new pdr0
252 pdr0 |= ((hsp_div - 1) << 11) | ((nfc_div - 1) << 8) | ((ipg_div - 1) << 6) |
253 ((ahb_div - 1) << 3) | ((presc - 1) << 0);
255 // update PLL register
256 if ((mfd >= (10 * mfn)) || ((10 * mfn) >= (9 * mfd)))
259 mpctl0 = readl(CCM_BASE_ADDR + CLKCTL_MPCTL);
260 mpctl0 = (mpctl0 & 0x4000C000) |
266 writel(mpctl0, CCM_BASE_ADDR + CLKCTL_MPCTL);
267 writel(pdr0, CCM_BASE_ADDR + CLKCTL_PDR0);
268 // add some delay for new values to take effect
269 for (i = 0; i < 10000; i++);
274 static void clock_setup(int argc,char *argv[])
276 u32 i, core_clk, ipg_div, data[3], temp, ahb_div, ahb_clk, ipg_clk;
281 if (g_clock_src == FREQ_27MHZ) {
282 diag_printf("Error: clock setup is not supported for 27MHz source\n\n");
285 for (i = 0; i < 3; i++) {
286 if (!parse_num(*(&argv[1]), (unsigned long *)&temp, &argv[1], ":")) {
287 diag_printf("Error: Invalid parameter\n");
293 core_clk = data[0] * SZ_DEC_1M;
294 ahb_div = data[1]; // actual register field + 1
295 ipg_div = data[2]; // actual register field + 1
297 if (core_clk < (PLL_FREQ_MIN / PRESC_MAX) || core_clk > PLL_FREQ_MAX) {
298 diag_printf("Targeted core clock should be within [%d - %d]\n",
299 PLL_FREQ_MIN / PRESC_MAX, PLL_FREQ_MAX);
303 // find the ahb divider
304 if (ahb_div > AHB_DIV_MAX) {
305 diag_printf("Invalid AHB divider: %d. Maximum value is %d\n",
306 ahb_div, AHB_DIV_MAX);
310 // no HCLK divider specified
311 for (ahb_div = 1; ; ahb_div++) {
312 if ((core_clk / ahb_div) <= AHB_CLK_MAX) {
317 if (ahb_div > AHB_DIV_MAX || (core_clk / ahb_div) > AHB_CLK_MAX) {
318 diag_printf("Can't make AHB=%d since max=%d\n",
319 core_clk / ahb_div, AHB_CLK_MAX);
323 // find the ipg divider
324 ahb_clk = core_clk / ahb_div;
325 if (ipg_div > IPG_DIV_MAX) {
326 diag_printf("Invalid IPG divider: %d. Maximum value is %d\n",
327 ipg_div, IPG_DIV_MAX);
331 ipg_div++; // At least =1
332 if (ahb_clk > IPG_CLK_MAX)
333 ipg_div++; // Make it =2
335 if (ipg_div > IPG_DIV_MAX || (ahb_clk / ipg_div) > IPG_CLK_MAX) {
336 diag_printf("Can't make IPG=%d since max=%d\n",
337 (ahb_clk / ipg_div), IPG_CLK_MAX);
340 ipg_clk = ahb_clk / ipg_div;
342 diag_printf("Trying to set core=%d ahb=%d ipg=%d...\n",
343 core_clk, ahb_clk, ipg_clk);
345 // stop the serial to be ready to adjust the clock
346 hal_delay_us(100000);
347 cyg_hal_plf_serial_stop();
349 ret = configure_clock(PLL_REF_CLK, core_clk, ahb_div, ipg_div);
350 // restart the serial driver
351 cyg_hal_plf_serial_init();
352 hal_delay_us(100000);
355 diag_printf("Failed to setup clock: %d\n", ret);
358 diag_printf("\n<<<New clock setting>>>\n");
360 // Now printing clocks
362 diag_printf("\nMPLL\t\tUPLL\t\tSPLL\n");
363 diag_printf("========================================\n");
364 diag_printf("%-16d%-16d%-16d\n\n", pll_clock(MCU_PLL), pll_clock(USB_PLL),
366 diag_printf("CPU\t\tAHB\t\tIPG\t\tIPG_PER\n");
367 diag_printf("========================================================\n");
368 diag_printf("%-16d%-16d%-16d%-16d\n\n",
369 get_main_clock(CPU_CLK),
370 get_main_clock(AHB_CLK),
371 get_main_clock(IPG_CLK),
372 get_main_clock(IPG_PER_CLK));
374 diag_printf("NFC\t\tUSB\t\tIPU-HSP\n");
375 diag_printf("========================================\n");
376 diag_printf("%-16d%-16d%-16d\n\n",
377 get_main_clock(NFC_CLK),
378 get_main_clock(USB_CLK),
379 get_main_clock(HSP_CLK));
381 diag_printf("UART1-5\t\tSSI1\t\tSSI2\t\tCSI\n");
382 diag_printf("===========================================");
383 diag_printf("=============\n");
385 diag_printf("%-16d%-16d%-16d%-16d\n\n",
386 get_peri_clock(UART1_BAUD),
387 get_peri_clock(SSI1_BAUD),
388 get_peri_clock(SSI2_BAUD),
389 get_peri_clock(CSI_BAUD));
391 diag_printf("FIRI\t\tSIM\t\tMSTICK1\t\tMSTICK2\n");
392 diag_printf("===========================================");
393 diag_printf("=============\n");
395 diag_printf("%-16d%-16d%-16d%-16d\n\n",
396 get_peri_clock(FIRI_BAUD),
397 get_peri_clock(SIM_BAUD),
398 get_peri_clock(MSTICK1_CLK),
399 get_peri_clock(MSTICK2_CLK));
400 diag_printf("IPG_PERCLK as baud clock for: UART1-5, I2C, SIM, OWIRE, SDHC");
401 if (((readl(EPIT1_BASE_ADDR) >> 24) & 0x3) == 0x2) {
402 diag_printf(", EPIT");
404 if (((readl(GPT1_BASE_ADDR) >> 6) & 0x7) == 0x2) {
407 if (((readl(PWM_BASE_ADDR) >> 16) & 0x3) == 0x2) {
414 * This function returns the PLL output value in Hz based on pll.
416 u32 pll_clock(enum plls pll)
418 u64 mfi, mfn, mfd, pdf, ref_clk, pll_out, sign;
419 u64 reg = readl(pll);
421 pdf = (reg >> 26) & 0xF;
422 mfd = (reg >> 16) & 0x3FF;
423 mfi = (reg >> 10) & 0xF;
424 mfi = (mfi <= 5) ? 5: mfi;
426 sign = (mfn < 512) ? 0: 1;
427 mfn = (mfn < 512) ? mfn: (1024 - mfn);
429 ref_clk = g_clock_src;
432 pll_out = (2 * ref_clk * mfi + ((2 * ref_clk * mfn) / (mfd + 1))) /
435 pll_out = (2 * ref_clk * mfi - ((2 * ref_clk * mfn) / (mfd + 1))) /
442 // The clocks are on by default. But need to setup the IOMUX
443 void clock_spi_enable(unsigned int spi_clk)
447 // Take care of SPI1 and SPI2
448 val = readl(IOMUXC_BASE_ADDR + 0x80);
449 writel((val & 0xFFFF) | 0x12120000, IOMUXC_BASE_ADDR + 0x80);
451 writel(0x12123812, IOMUXC_BASE_ADDR + 0x84);
453 val = readl(IOMUXC_BASE_ADDR + 0x88);
454 writel((val & 0xFFFFFF00) | 0x12, IOMUXC_BASE_ADDR + 0x88);
456 /* Select CSPI 1 signals */
457 val = readl(IOMUXC_BASE_ADDR + 0x8);
458 writel((val | 0x4), IOMUXC_BASE_ADDR + 0x8);
460 val = readl(IOMUXC_BASE_ADDR + 0x78);
461 writel((val & 0xFFFFFF) | 0x24000000, IOMUXC_BASE_ADDR + 0x78);
463 val = readl(IOMUXC_BASE_ADDR + 0x7C);
464 writel((val & 0xFFFFFF00) | 0x24, IOMUXC_BASE_ADDR + 0x7C);
466 writel(0x12121212, IOMUXC_BASE_ADDR + 0x8C);
468 val = readl(IOMUXC_BASE_ADDR + 0x88);
469 writel((val & 0xFF) | 0x12121200, IOMUXC_BASE_ADDR + 0x88);
472 // The clocks are on by default. But need to setup the IOMUX
473 void mxc_i2c_init(unsigned int module_base)
475 unsigned int val, reg;
477 switch (module_base) {
479 reg = IOMUXC_BASE_ADDR + 0xA0;
480 val = (readl(reg) & 0xFFFF0000) | 0x1212; // func mode
484 reg = IOMUXC_BASE_ADDR + 0x88;
485 val = (readl(reg) & 0xFFFFFF00) | 0x24; // alt mode 1
487 reg = IOMUXC_BASE_ADDR + 0x84;
488 val = (readl(reg) & 0x00FFFFFF) | 0x24000000; // alt mode 1
492 reg = IOMUXC_BASE_ADDR + 0x84;
493 val = (readl(reg) & 0xFFFFFF00) | 0x24; // alt mode 1
495 reg = IOMUXC_BASE_ADDR + 0x80;
496 val = (readl(reg) & 0x00FFFFFF) | 0x24000000; // alt mode 1
500 diag_printf("Invalide I2C base: 0x%x\n", module_base);
506 * This function returns the main clock value in Hz.
508 u32 get_main_clock(enum main_clocks clk)
510 u32 mcu_podf, max_pdf, ipg_pdf, nfc_pdf, hsp_podf, clk_sel;
511 u32 pll, ret_val = 0, usb_prdf, usb_podf, pdf;
512 u32 reg = readl(CCM_BASE_ADDR + CLKCTL_PDR0);
513 u32 reg1 = readl(CCM_BASE_ADDR + CLKCTL_PDR1);
514 u32 ccmr = readl(CCM_BASE_ADDR + CLKCTL_CCMR);
515 u32 mpdr0 = readl(CCM_BASE_ADDR + CLKCTL_PDR0);
519 mcu_podf = reg & 0x7;
520 pll = pll_clock(MCU_PLL);
521 ret_val = pll / (mcu_podf + 1);
524 max_pdf = (reg >> 3) & 0x7;
525 pll = pll_clock(MCU_PLL);
526 ret_val = pll / (max_pdf + 1);
529 hsp_podf = (reg >> 11) & 0x7;
530 pll = pll_clock(MCU_PLL);
531 ret_val = pll / (hsp_podf + 1);
534 max_pdf = (reg >> 3) & 0x7;
535 pll = pll_clock(MCU_PLL);
536 ret_val = (pll / (max_pdf + 1)) / 2;
539 max_pdf = (reg >> 3) & 0x7;
540 ipg_pdf = (reg >> 6) & 0x3;
541 pll = pll_clock(MCU_PLL);
542 ret_val = pll / ((max_pdf + 1) * (ipg_pdf + 1));
545 clk_sel = ccmr & (1 << 24);
546 pdf = (mpdr0 >> 16) & 0x1F;
549 max_pdf = (reg >> 3) & 0x7;
550 ipg_pdf = (reg >> 6) & 0x3;
551 pll = pll_clock(MCU_PLL);
552 ret_val = pll / ((max_pdf + 1) * (ipg_pdf + 1));
554 ret_val = pll_clock(USB_PLL) / (pdf + 1);
558 nfc_pdf = (reg >> 8) & 0x7;
559 max_pdf = (reg >> 3) & 0x7;
560 pll = pll_clock(MCU_PLL);
562 ret_val = pll / ((max_pdf + 1) * (nfc_pdf + 1));
565 usb_prdf = reg1 >> 30;
566 usb_podf = (reg1 >> 27) & 0x7;
567 pll = pll_clock(USB_PLL);
568 ret_val = pll / ((usb_prdf + 1) * (usb_podf + 1));
571 diag_printf("Unknown clock: %d\n", clk);
579 * This function returns the peripheral clock value in Hz.
581 u32 get_peri_clock(enum peri_clocks clk)
583 u32 ret_val = 0, pdf, pre_pdf, clk_sel;
584 u32 ccmr = readl(CCM_BASE_ADDR + CLKCTL_CCMR);
585 u32 mpdr0 = readl(CCM_BASE_ADDR + CLKCTL_PDR0);
586 u32 mpdr1 = readl(CCM_BASE_ADDR + CLKCTL_PDR1);
587 u32 mpdr2 = readl(CCM_BASE_ADDR + CLKCTL_PDR2);
596 clk_sel = ccmr & (1 << 24);
597 pdf = (mpdr0 >> 16) & 0x1F;
598 ret_val = (clk_sel != 0) ? get_main_clock(IPG_CLK) :
599 pll_clock(USB_PLL) / (pdf + 1);
602 pre_pdf = (mpdr1 >> 6) & 0x7;
604 clk_sel = (ccmr >> 18) & 3;
606 ret_val = pll_clock(MCU_PLL) / ((pre_pdf + 1) * (pdf + 1));
607 } else if (clk_sel == 0x1) {
608 ret_val = pll_clock(USB_PLL) / ((pre_pdf + 1) * (pdf + 1));
609 } else if (clk_sel == 0x2) {
610 ret_val = pll_clock(SER_PLL) / ((pre_pdf + 1) * (pdf + 1));
612 diag_printf("Error: Use reserved value for SSI1!\n");
617 pre_pdf = (mpdr1 >> 15) & 0x7;
618 pdf = (mpdr1 >> 9) & 0x3F;
619 clk_sel = (ccmr >> 21) & 3;
621 ret_val = pll_clock(MCU_PLL) / ((pre_pdf + 1) * (pdf + 1));
622 } else if (clk_sel == 0x1) {
623 ret_val = pll_clock(USB_PLL) / ((pre_pdf + 1) * (pdf + 1));
624 } else if (clk_sel == 0x2) {
625 ret_val = pll_clock(SER_PLL) / ((pre_pdf + 1) * (pdf + 1));
627 diag_printf("Error: Use reserved value for SSI2!\n");
632 clk_sel = ccmr & (1 << 25);
633 pdf = (mpdr0 >> 23) & 0x1FF;
634 ret_val = (clk_sel != 0) ? (pll_clock(SER_PLL) / (pdf + 1)) :
635 (pll_clock(USB_PLL) / (pdf + 1));
638 pre_pdf = (mpdr1 >> 24) & 0x7;
639 pdf = (mpdr1 >> 18) & 0x3F;
640 clk_sel = (ccmr >> 11) & 3;
642 ret_val = pll_clock(MCU_PLL) / ((pre_pdf + 1) * (pdf + 1));
643 } else if (clk_sel == 0x1) {
644 ret_val = pll_clock(USB_PLL) / ((pre_pdf + 1) * (pdf + 1));
645 } else if (clk_sel == 0x2) {
646 ret_val = pll_clock(SER_PLL) / ((pre_pdf + 1) * (pdf + 1));
648 diag_printf("Error: Use reserved value for SSI1!\n");
654 ret_val = pll_clock(USB_PLL) / (pdf + 1);
657 pdf = (mpdr2 >> 7) & 0x3F;
658 ret_val = pll_clock(USB_PLL) / (pdf + 1);
662 ret_val = get_main_clock(IPG_CLK);
665 diag_printf("%s(): This clock: %d not supported yet \n",
674 "Select clock source for CLKO (J11 on the CPU daughter card)",
675 " Default is 1/8 of ARM core\n\
676 <0> - display current clko selection \n\
677 <1> - mpl_dpdgck_clk (MPLL) \n\
678 <2> - ipg_clk_ccm (IPG) \n\
679 <3> - upl_dpdgck_clk (UPLL) \n\
680 <4> - pll_ref_clk \n\
681 <5> - fpm_ckil512_clk \n\
682 <6> - ipg_clk_ahb_arm (AHB) \n\
683 <7> - ipg_clk_arm (ARM) \n\
684 <8> - spl_dpdgck_clk (SPLL) \n\
686 <10> - ipg_clk_ahb_emi_clk \n\
687 <11> - ipg_clk_ipu_hsp \n\
688 <12> - ipg_clk_nfc_20m \n\
689 <13> - ipg_clk_perclk_uart1 (IPG_PER)",
693 static u8* clko_name[] ={
695 "1/8 of mpl_dpdgck_clk (MPLL)",
697 "1/8 of upl_dpdgck_clk (UPLL)",
700 "ipg_clk_ahb_arm (AHB)",
701 "1/8 of ipg_clk_arm (ARM)",
702 "1/8 of spl_dpdgck_clk (SPLL)",
704 "ipg_clk_ahb_emi_clk",
707 "ipg_clk_perclk_uart1 (IPG_PER)",
710 #define CLKO_MAX_INDEX (sizeof(clko_name) / sizeof(u8*))
712 static void clko(int argc,char *argv[])
714 u32 action = 0, cosr;
716 if (!scan_opts(argc, argv, 1, 0, 0, (void*) &action,
717 OPTION_ARG_TYPE_NUM, "action"))
720 if (action >= CLKO_MAX_INDEX) {
721 diag_printf("%d is not supported\n\n", action);
725 cosr = readl(CCM_BASE_ADDR + CLKCTL_COSR);
728 cosr = (cosr & (~0x1FF)) + action - 1;
729 if (action == 1 || action == 3 || action == 7 || action == 8) {
730 cosr |= (0x3 << 6); // make it divided by 8
732 writel(cosr, CCM_BASE_ADDR + CLKCTL_COSR);
733 diag_printf("Set clko to ");
736 cosr = readl(CCM_BASE_ADDR + CLKCTL_COSR);
737 diag_printf("%s\n", clko_name[(cosr & 0xF) + 1]);
738 diag_printf("COSR register[0x%x] = 0x%x\n",
739 (CCM_BASE_ADDR + CLKCTL_COSR), cosr);
744 * This command is added for some simple testing only. It turns on/off
745 * L2 cache regardless of L1 cache state. The side effect of this is
746 * when doing any flash operations such as "fis init", the L2
747 * will be turned back on along with L1 caches even though it is off
748 * by using this command.
756 void do_L2_caches(int argc, char *argv[])
762 if (strcasecmp(argv[1], "on") == 0) {
763 HAL_DISABLE_INTERRUPTS(oldints);
765 HAL_RESTORE_INTERRUPTS(oldints);
766 } else if (strcasecmp(argv[1], "off") == 0) {
767 HAL_DISABLE_INTERRUPTS(oldints);
768 HAL_CLEAN_INVALIDATE_L2();
770 HAL_RESTORE_INTERRUPTS(oldints);
772 diag_printf("Invalid L2 cache mode: %s\n", argv[1]);
775 HAL_L2CACHE_IS_ENABLED(L2cache_on);
776 diag_printf("L2 cache: %s\n", L2cache_on?"On":"Off");
779 #endif //L2CC_ENABLED
781 #define IIM_ERR_SHIFT 8
782 #define POLL_FUSE_PRGD (IIM_STAT_PRGD | (IIM_ERR_PRGE << IIM_ERR_SHIFT))
783 #define POLL_FUSE_SNSD (IIM_STAT_SNSD | (IIM_ERR_SNSE << IIM_ERR_SHIFT))
785 static void fuse_op_start(void)
787 /* Do not generate interrupt */
788 writel(0, IIM_BASE_ADDR + IIM_STATM_OFF);
789 // clear the status bits and error bits
790 writel(0x3, IIM_BASE_ADDR + IIM_STAT_OFF);
791 writel(0xFE, IIM_BASE_ADDR + IIM_ERR_OFF);
795 * The action should be either:
800 static int poll_fuse_op_done(int action)
805 if (action != POLL_FUSE_PRGD && action != POLL_FUSE_SNSD) {
806 diag_printf("%s(%d) invalid operation\n", __FUNCTION__, action);
810 /* Poll busy bit till it is NOT set */
811 while ((readl(IIM_BASE_ADDR + IIM_STAT_OFF) & IIM_STAT_BUSY) != 0 ) {
814 /* Test for successful write */
815 status = readl(IIM_BASE_ADDR + IIM_STAT_OFF);
816 error = readl(IIM_BASE_ADDR + IIM_ERR_OFF);
818 if ((status & action) != 0 && (error & (action >> IIM_ERR_SHIFT)) == 0) {
820 diag_printf("Even though the operation seems successful...\n");
821 diag_printf("There are some error(s) at addr=0x%x: 0x%x\n",
822 (IIM_BASE_ADDR + IIM_ERR_OFF), error);
826 diag_printf("%s(%d) failed\n", __FUNCTION__, action);
827 diag_printf("status address=0x%x, value=0x%x\n",
828 (IIM_BASE_ADDR + IIM_STAT_OFF), status);
829 diag_printf("There are some error(s) at addr=0x%x: 0x%x\n",
830 (IIM_BASE_ADDR + IIM_ERR_OFF), error);
834 static void sense_fuse(int bank, int row, int bit)
836 int addr, addr_l, addr_h, reg_addr;
840 addr = ((bank << 11) | (row << 3) | (bit & 0x7));
841 /* Set IIM Program Upper Address */
842 addr_h = (addr >> 8) & 0x000000FF;
843 /* Set IIM Program Lower Address */
844 addr_l = (addr & 0x000000FF);
846 #ifdef IIM_FUSE_DEBUG
847 diag_printf("%s: addr_h=0x%x, addr_l=0x%x\n",
848 __FUNCTION__, addr_h, addr_l);
850 writel(addr_h, IIM_BASE_ADDR + IIM_UA_OFF);
851 writel(addr_l, IIM_BASE_ADDR + IIM_LA_OFF);
853 writel(0x8, IIM_BASE_ADDR + IIM_FCTL_OFF);
854 if (poll_fuse_op_done(POLL_FUSE_SNSD) != 0) {
855 diag_printf("%s(bank: %d, row: %d, bit: %d failed\n",
856 __FUNCTION__, bank, row, bit);
858 reg_addr = IIM_BASE_ADDR + IIM_SDAT_OFF;
859 diag_printf("fuses at (bank:%d, row:%d) = 0x%x\n", bank, row, readl(reg_addr));
862 void do_fuse_read(int argc, char *argv[])
867 diag_printf("Useage: fuse_read <bank> <row>\n");
869 } else if (argc == 3) {
870 if (!parse_num(*(&argv[1]), (unsigned long *)&bank, &argv[1], " ")) {
871 diag_printf("Error: Invalid parameter\n");
874 if (!parse_num(*(&argv[2]), (unsigned long *)&row, &argv[2], " ")) {
875 diag_printf("Error: Invalid parameter\n");
879 diag_printf("Read fuse at bank:%d row:%d\n", bank, row);
880 sense_fuse(bank, row, 0);
883 diag_printf("Passing in wrong arguments: %d\n", argc);
884 diag_printf("Useage: fuse_read <bank> <row>\n");
888 /* Blow fuses based on the bank, row and bit positions (all 0-based)
890 static int fuse_blow(int bank,int row,int bit)
892 int addr, addr_l, addr_h, ret = -1;
896 /* Disable IIM Program Protect */
897 writel(0xAA, IIM_BASE_ADDR + IIM_PREG_P_OFF);
899 addr = ((bank << 11) | (row << 3) | (bit & 0x7));
900 /* Set IIM Program Upper Address */
901 addr_h = (addr >> 8) & 0x000000FF;
902 /* Set IIM Program Lower Address */
903 addr_l = (addr & 0x000000FF);
905 #ifdef IIM_FUSE_DEBUG
906 diag_printf("blowing addr_h=0x%x, addr_l=0x%x\n", addr_h, addr_l);
909 writel(addr_h, IIM_BASE_ADDR + IIM_UA_OFF);
910 writel(addr_l, IIM_BASE_ADDR + IIM_LA_OFF);
911 /* Start Programming */
912 writel(0x31, IIM_BASE_ADDR + IIM_FCTL_OFF);
913 if (poll_fuse_op_done(POLL_FUSE_PRGD) == 0) {
917 /* Enable IIM Program Protect */
918 writel(0x0, IIM_BASE_ADDR + IIM_PREG_P_OFF);
923 * This command is added for burning IIM fuses
925 RedBoot_cmd("fuse_read",
931 RedBoot_cmd("fuse_blow",
933 "<bank> <row> <value>",
937 #define INIT_STRING "12345678"
938 static char ready_to_blow[] = INIT_STRING;
940 void quick_itoa(u32 num, char *a)
943 for (i = 0; i <= 7; i++) {
944 j = (num >> (4 * i)) & 0xF;
945 k = (j < 10) ? '0' : ('a' - 0xa);
950 void do_fuse_blow(int argc, char *argv[])
952 int bank, row, value, i;
955 diag_printf("It is too dangeous for you to use this command.\n");
957 } else if (argc == 2) {
958 if (strcasecmp(argv[1], "nandboot") == 0) {
959 quick_itoa(readl(EPIT_BASE_ADDR + EPITCNR), ready_to_blow);
960 diag_printf("%s\n", ready_to_blow);
963 } else if (argc == 3) {
964 if (strcasecmp(argv[1], "nandboot") == 0 &&
965 strcasecmp(argv[2], ready_to_blow) == 0) {
966 #if defined(CYGPKG_HAL_ARM_MXC91131) || defined(CYGPKG_HAL_ARM_MX21) || defined(CYGPKG_HAL_ARM_MX27) || defined(CYGPKG_HAL_ARM_MX31)
967 diag_printf("No need to blow any fuses for NAND boot on this platform\n\n");
969 diag_printf("Ready to burn NAND boot fuses\n");
970 if (fuse_blow(0, 16, 1) != 0 || fuse_blow(0, 16, 7) != 0) {
971 diag_printf("NAND BOOT fuse blown failed miserably ...\n");
973 diag_printf("NAND BOOT fuse blown successfully ...\n");
976 diag_printf("Not ready: %s, %s\n", argv[1], argv[2]);
979 } else if (argc == 4) {
980 if (!parse_num(*(&argv[1]), (unsigned long *)&bank, &argv[1], " ")) {
981 diag_printf("Error: Invalid parameter\n");
984 if (!parse_num(*(&argv[2]), (unsigned long *)&row, &argv[2], " ")) {
985 diag_printf("Error: Invalid parameter\n");
988 if (!parse_num(*(&argv[3]), (unsigned long *)&value, &argv[3], " ")) {
989 diag_printf("Error: Invalid parameter\n");
993 diag_printf("Blowing fuse at bank:%d row:%d value:%d\n",
995 for (i = 0; i < 8; i++) {
996 if (((value >> i) & 0x1) == 0) {
999 if (fuse_blow(bank, row, i) != 0) {
1000 diag_printf("fuse_blow(bank: %d, row: %d, bit: %d failed\n",
1003 diag_printf("fuse_blow(bank: %d, row: %d, bit: %d successful\n",
1007 sense_fuse(bank, row, 0);
1010 diag_printf("Passing in wrong arguments: %d\n", argc);
1012 /* Reset to default string */
1013 strcpy(ready_to_blow, INIT_STRING);;
1016 /* precondition: m>0 and n>0. Let g=gcd(m,n). */
1017 int gcd(int m, int n)
1021 if(n > m) {t = m; m = n; n = t;} /* swap */
1027 #define CLOCK_SRC_DETECT_MS 100
1028 #define CLOCK_IPG_DEFAULT 66500000
1029 #define CLOCK_SRC_DETECT_MARGIN 500000
1030 void mxc_show_clk_input(void)
1032 u32 c1, c2, diff, ipg_real, num = 0;
1033 u32 prcs = (readl(CCM_BASE_ADDR + CLKCTL_CCMR) >> 1) & 0x3;
1039 diag_printf("FPM enabled --> 32KHz input source\n");
1044 diag_printf("Error %d: unknown clock source %d\n", __LINE__, prcs);
1048 // enable GPT with IPG clock input
1049 writel(0x241, GPT_BASE_ADDR + GPTCR);
1051 writel(0, GPT_BASE_ADDR + GPTPR);
1053 c1 = readl(GPT_BASE_ADDR + GPTCNT);
1054 // use 32KHz input clock to get the delay
1055 hal_delay_us(CLOCK_SRC_DETECT_MS * 1000);
1056 c2 = readl(GPT_BASE_ADDR + GPTCNT);
1057 diff = (c2 > c1) ? (c2 - c1) : (0xFFFFFFFF - c1 + c2);
1059 ipg_real = diff * (1000 / CLOCK_SRC_DETECT_MS);
1061 if (ipg_real > (CLOCK_IPG_DEFAULT + CLOCK_SRC_DETECT_MARGIN)) {
1062 if (g_clock_src != FREQ_27MHZ)
1064 } else if (ipg_real < (CLOCK_IPG_DEFAULT - CLOCK_SRC_DETECT_MARGIN)) {
1065 if (g_clock_src != FREQ_26MHZ)
1069 diag_printf("Error: Actural clock input is %d MHz\n", num);
1070 diag_printf(" ipg_real=%d CLOCK_IPG_DEFAULT - CLOCK_SRC_DETECT_MARGIN=%d\n\n",
1071 ipg_real, CLOCK_IPG_DEFAULT - CLOCK_SRC_DETECT_MARGIN);
1072 diag_printf(" But clock source defined to be %d\n\n", g_clock_src);
1073 hal_delay_us(2000000);
1075 diag_printf("ipg_real=%d CLOCK_IPG_DEFAULT - CLOCK_SRC_DETECT_MARGIN=%d\n\n",
1076 ipg_real, CLOCK_IPG_DEFAULT - CLOCK_SRC_DETECT_MARGIN);
1077 diag_printf("clock source defined to be %d\n\n", g_clock_src);
1081 RedBoot_init(mxc_show_clk_input, RedBoot_INIT_LAST);