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
60 #define HSP_PODF_MAX 8
61 #define NFC_PODF_MAX 8
63 #if (PLL_REF_CLK == FREQ_32768HZ) || (PLL_REF_CLK == FREQ_32000HZ)
64 #define PLL_MFD_FIXED 1024
66 #if (PLL_REF_CLK == FREQ_26MHZ)
67 #define PLL_MFD_FIXED (26 * 16) // =416
70 #define PLL_FREQ_MAX (2 * PLL_REF_CLK * PLL_MFI_MAX)
71 #define TPLL_FREQ_MAX 534000000
72 #define PLL_FREQ_MIN ((2 * PLL_REF_CLK * (PLL_MFI_MIN - 1)) / PLL_PD_MAX)
73 #define AHB_CLK_MAX 133333333
74 #define IPG_CLK_MAX (AHB_CLK_MAX / 2)
75 #define NFC_CLK_MAX 25000000
76 // IPU-HSP clock is independent of the HCLK and can go up to 177MHz but requires
77 // higher voltage support. For simplicity, limit it to 133MHz
78 #define HSP_CLK_MAX 133333333
80 #define ERR_WRONG_CLK -1
84 #define ERR_NO_AHB_DIV -6
86 u32 pll_clock(enum plls pll);
87 u32 get_main_clock(enum main_clocks clk);
88 u32 get_peri_clock(enum peri_clocks clk);
89 int poll_fuse_set(void);
90 int gcd(int m, int n);
92 static void clock_setup(int argc, char *argv[]);
93 static void ckol(int argc, char *argv[]);
94 static void ckoh(int argc, char *argv[]);
97 "Setup/Display clock (max AHB=133MHz, max IPG=66.5MHz)\nSyntax:",
98 "[<core clock in MHz> [:<AHB-to-core divider>[:<IPG-to-AHB divider>]]] \n\n\
99 If a divider is zero or no divider is specified, the optimal divider values \n\
100 will be chosen. It does NOT do integer freq scaling so no brmm value changes.\n\
101 Instead, it always adjusts the PLL settings. \n\
103 [clock] -> Show various clocks\n\
104 [clock 399] -> Core=399 AHB=133 IPG=66.5\n\
105 [clock 200] -> Core=200 AHB=100 IPG=50\n\
106 [clock 399:6] -> Core=399 AHB=66.5(Core/6) IPG=66.5\n\
107 [clock 399:6:2] -> Core=399 AHB=66.5(Core/6) IPG=33.25(AHB/2)\n",
112 * This is to calculate various parameters based on reference clock and
113 * targeted clock based on the equation:
114 * t_clk = 2*ref_freq*(mfi + mfn/(mfd+1))/(pd+1)
115 * This calculation is based on a fixed MFD value for simplicity.
117 * @param ref reference clock freq
118 * @param target targeted clock in HZ
119 * @param p_pd calculated pd value (pd value from register + 1) upon return
120 * @param p_mfi calculated actual mfi value upon return
121 * @param p_mfn calculated actual mfn value upon return
122 * @param p_mfd fixed mfd value (mfd value from register + 1) upon return
124 * @return 0 if successful; non-zero otherwise.
126 int calc_pll_params(u32 ref, u32 target, u32 *p_pd,
127 u32 *p_mfi, u32 *p_mfn, u32 *p_mfd)
129 u64 pd, mfi, mfn, n_target = (u64)target, n_ref = (u64)ref;
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, pd, mfi, mfn, mfd, brmo = 0, pctl0;
194 u32 pdr0, nfc_div, ahb_clk = core_clk / ahb_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 diag_printf("can't make core_clk=%d\n", core_clk);
203 return ERR_WRONG_CLK;
206 // get nfc_div - make sure optimal NFC clock but less than NFC_CLK_MAX
207 for (nfc_div = 1; nfc_div <= NFC_PODF_MAX; nfc_div++) {
208 if ((pll / (ahb_div * nfc_div)) <= NFC_CLK_MAX) {
213 // pll is now the targeted pll output. Use it along with ref input clock
214 // to get pd, mfi, mfn, mfd
215 if ((ret = calc_pll_params(ref, pll, &pd, &mfi, &mfn, &mfd)) != 0) {
216 diag_printf("can't find pll parameters: %d\n", ret);
219 #ifdef CMD_CLOCK_DEBUG
220 diag_printf("ref=%d, pll=%d, pd=%d, mfi=%d,mfn=%d, mfd=%d\n",
221 ref, pll, pd, mfi, mfn, mfd);
224 // blindly increase divider first to avoid too fast ahbclk and ipgclk
225 // in case the core clock increases too much
226 pdr0 = readl(CRM_MCU_BASE_ADDR + CLKCTL_PDR0);
228 // increase the dividers. should work even when core clock is 832 (26*2*16)MHz
229 // which is unlikely true.
230 pdr0 |= (1 << 6) | (6 << 3);
231 writel(pdr0, CRM_MCU_BASE_ADDR + CLKCTL_PDR0);
232 // calculate new pdr0. Also clear the brmm bits
234 pdr0 |= ((nfc_div - 1) << 8) | ((ipg_div - 1) << 6) | ((ahb_div - 1) << 3);
236 // update PLL register
237 if ((mfd >= (10 * mfn)) || ((10 * mfn) >= (9 * mfd)))
240 pctl0 = readl(CRM_MCU_BASE_ADDR + CLKCTL_MPCTL);
241 pctl0 = (pctl0 & 0x40008000) |
247 writel(pctl0, CRM_MCU_BASE_ADDR + CLKCTL_MPCTL);
248 writel(pdr0, CRM_MCU_BASE_ADDR + CLKCTL_PDR0);
249 // add some delay for new values to take effect
250 for (i = 0; i < 10000; i++);
252 // --------------- now adjust for TPLL ---------------------------
253 pll = (TPLL_FREQ_MAX / ahb_clk) * ahb_clk;
254 if ((ret = calc_pll_params(ref, pll, &pd, &mfi, &mfn, &mfd)) != 0) {
255 diag_printf("can't find tpll parameters: %d\n", ret);
258 #ifdef CMD_CLOCK_DEBUG
259 diag_printf("ref=%d, pll=%d, pd=%d, mfi=%d,mfn=%d, mfd=%d\n",
260 ref, pll, pd, mfi, mfn, mfd);
263 // update PLL register
264 if ((mfd >= (10 * mfn)) || ((10 * mfn) >= (9 * mfd)))
267 pctl0 = readl(CRM_MCU_BASE_ADDR + CLKCTL_TPCTL);
268 pctl0 = (pctl0 & 0x40008000) |
274 writel(pctl0, CRM_MCU_BASE_ADDR + CLKCTL_TPCTL);
279 static void clock_setup(int argc,char *argv[])
281 u32 i, core_clk, ipg_div, data[3],
282 ahb_div, ahb_clk, ipg_clk;
287 for (i = 0; i < 3; i++) {
289 if (!parse_num(*(&argv[1]), &temp, &argv[1], ":")) {
290 diag_printf("Error: Invalid parameter\n");
296 core_clk = data[0] * SZ_DEC_1M;
297 ahb_div = data[1]; // actual register field + 1
298 ipg_div = data[2]; // actual register field + 1
300 if (core_clk < PLL_FREQ_MIN || core_clk > PLL_FREQ_MAX) {
301 diag_printf("Targeted core clock should be within [%d - %d]\n",
302 PLL_FREQ_MIN, PLL_FREQ_MAX);
306 // find the ahb divider
307 if (ahb_div > AHB_DIV_MAX) {
308 diag_printf("Invalid AHB divider: %d. Maximum value is %d\n",
309 ahb_div, AHB_DIV_MAX);
313 // no HCLK divider specified
314 for (ahb_div = 1; ; ahb_div++) {
315 if ((core_clk / ahb_div) <= AHB_CLK_MAX) {
320 if (ahb_div > AHB_DIV_MAX || (core_clk / ahb_div) > AHB_CLK_MAX) {
321 diag_printf("Can't make AHB=%d since max=%d\n",
322 core_clk / ahb_div, AHB_CLK_MAX);
326 // find the ipg divider
327 ahb_clk = core_clk / ahb_div;
328 if (ipg_div > IPG_DIV_MAX) {
329 diag_printf("Invalid IPG divider: %d. Maximum value is %d\n",
330 ipg_div, IPG_DIV_MAX);
334 ipg_div++; // At least =1
335 if (ahb_clk > IPG_CLK_MAX)
336 ipg_div++; // Make it =2
338 if (ipg_div > IPG_DIV_MAX || (ahb_clk / ipg_div) > IPG_CLK_MAX) {
339 diag_printf("Can't make IPG=%d since max=%d\n",
340 (ahb_clk / ipg_div), IPG_CLK_MAX);
343 ipg_clk = ahb_clk / ipg_div;
345 diag_printf("Trying to set core=%d ahb=%d ipg=%d...\n",
346 core_clk, ahb_clk, ipg_clk);
348 // stop the serial to be ready to adjust the clock
349 hal_delay_us(100000);
350 cyg_hal_plf_serial_stop();
352 ret = configure_clock(PLL_REF_CLK, core_clk, ahb_div, ipg_div);
353 // restart the serial driver
354 cyg_hal_plf_serial_init();
355 hal_delay_us(100000);
358 diag_printf("Failed to setup clock: %d\n", ret);
361 diag_printf("\n<<<New clock setting>>>\n");
363 // Now printing clocks
365 #ifdef CYGPKG_HAL_ARM_MXC91331_CHIP
366 diag_printf("\nMPLL\t\tUPLL\n");
367 diag_printf("=========================\n");
368 diag_printf("%-16d%-16d\n\n", pll_clock(MCU_PLL), pll_clock(USB_PLL));
370 #ifdef CYGPKG_HAL_ARM_MXC91321_CHIP
371 diag_printf("\nMPLL\t\tUPLL\t\tTPLL\n");
372 diag_printf("================================================\n");
373 diag_printf("%-16d%-16d%-16d\n\n",
374 pll_clock(MCU_PLL), pll_clock(USB_PLL), pll_clock(TUR_PLL));
377 diag_printf("CPU\t\tAHB\t\tIPG\t\tNFC\t\tUSB\n");
378 diag_printf("===========================================");
379 diag_printf("=============================\n");
380 diag_printf("%-16d%-16d%-16d%-16d%-16d\n\n",
381 get_main_clock(CPU_CLK),
382 get_main_clock(AHB_CLK),
383 get_main_clock(IPG_CLK),
384 get_main_clock(NFC_CLK),
385 get_main_clock(USB_CLK));
387 diag_printf("UART1/2/3/4\tSSI1\t\tSSI2\t\tCSI\t\tFIRI\n");
388 diag_printf("===========================================");
389 diag_printf("=============================\n");
391 diag_printf("%-16d%-16d%-16d%-16d%-16d\n\n",
392 get_peri_clock(UART1_BAUD),
393 get_peri_clock(SSI1_BAUD),
394 get_peri_clock(SSI2_BAUD),
395 get_peri_clock(CSI_BAUD),
396 get_peri_clock(FIRI_BAUD));
400 * This function returns the PLL output value in Hz based on pll.
402 u32 pll_clock(enum plls pll)
404 u64 mfi, mfn, mfd, pdf, ref_clk, pll_out, sign;
405 u64 reg = readl(pll);
407 pdf = (reg >> 26) & 0xF;
408 mfd = (reg >> 16) & 0x3FF;
409 if (pll == MCU_PLL || pll == TUR_PLL) {
410 mfi = (reg >> 11) & 0xF;
411 mfi = (mfi <= 5) ? 5: mfi;
413 sign = (mfn < 1024) ? 0: 1;
414 mfn = (mfn <= 0x400) ? mfn: (0x800 - mfn);
417 mfi = (reg >> 10) & 0xF;
418 mfi = (mfi <= 5) ? 5: mfi;
422 /* Scale down to avoid overflow */
423 ref_clk = PLL_REF_CLK;
425 diag_printf("Error: fix input clock first for %s() to work\n",
431 pll_out = (2 * ref_clk * mfi + ((2 * ref_clk * mfn) / (mfd + 1))) /
434 pll_out = (2 * ref_clk * mfi - ((2 * ref_clk * mfn) / (mfd + 1))) /
441 #define NORMALIZE_FACTOR 10
443 void clock_spi_enable(unsigned int spi_clk)
445 if (spi_clk == SPI1_CLK) {
446 // do nothing now as it is already enabled by default
447 } else if (spi_clk == SPI2_CLK) {
448 // do nothing now as it is already enabled by default
453 * This function returns the main clock value in Hz.
455 u32 get_main_clock(enum main_clocks clk)
457 u32 brmm, max_pdf, ipg_pdf, nfc_pdf, csi_pdf;
458 u32 pll, ret_val = 0, hclk, usb_pdf, div;
459 enum plls CORE_PLL_SEL = MCU_PLL;
461 volatile u32 reg = readl(CRM_MCU_BASE_ADDR + CLKCTL_PDR0);
462 volatile u32 reg1 = readl(CRM_MCU_BASE_ADDR + CLKCTL_PDR1);
464 max_pdf = (reg >> 3) & 0x7;
465 ipg_pdf = (reg >> 6) & 0x3;
466 nfc_pdf = (reg >> 8) & 0x7;
468 usb_pdf = (reg1 >> 27) & 0x7;
470 #ifdef CYGPKG_HAL_ARM_MXC91321_CHIP
471 if ((readl(CRM_MCU_BASE_ADDR + CLKCTL_PDR0) & (1 << 11)) != 0) {
472 CORE_PLL_SEL = TUR_PLL;
478 pll = pll_clock(CORE_PLL_SEL);
480 diag_printf("Wrong BRMM value in the CRM_AP, MPDR0 reg \n");
483 hclk = pll / (max_pdf + 1);
484 div = (pll * NORMALIZE_FACTOR) / hclk;
490 // new period = (2*MCU_period + 1*AHB_period)/3
491 // => new freq = (3*pll*hclk)/(2*hclk+pll)
492 // => new frq = (3*pll)/(2+pll/hclk). Also normalize it.
493 ret_val = (3* pll * NORMALIZE_FACTOR) /
494 ((2 * NORMALIZE_FACTOR) + ((pll * NORMALIZE_FACTOR) / hclk));
497 // new period = (1*MCU_period + 1*AHB_period)/2
498 // => new freq = (2*pll*hclk)/(hclk+pll)
499 // => new frq = (2*pll)/(1+pll/hclk). Also normalize it.
500 ret_val = (2* pll * NORMALIZE_FACTOR) /
501 ((1 * NORMALIZE_FACTOR) + ((pll * NORMALIZE_FACTOR) / hclk));
504 // new period = (1*MCU_period + 2*AHB_period)/3
505 // => new freq = (3*pll*hclk)/(hclk+2*pll)
506 // => new frq = (3*pll)/(1+(2*pll)/hclk). Also normalize it.
507 ret_val = (3* pll * NORMALIZE_FACTOR) /
508 ((1 * NORMALIZE_FACTOR) + ((2 * pll * NORMALIZE_FACTOR) / hclk));
518 pll = pll_clock(CORE_PLL_SEL);
519 ret_val = pll / (max_pdf + 1);
522 pll = pll_clock(CORE_PLL_SEL);
523 ret_val = pll / ((max_pdf + 1) * (ipg_pdf + 1));
526 pll = pll_clock(CORE_PLL_SEL);
527 ret_val = pll / ((max_pdf + 1) * (nfc_pdf + 1));
530 pll = pll_clock(USB_PLL);
531 ret_val = pll / (usb_pdf + 1);
534 diag_printf("%s(): This clock: %d not supported yet \n",
542 #ifdef CYGPKG_HAL_ARM_MXC91321_CHIP
543 static u32 csi_sdhc_clock_src(u32 clksrc)
549 val = pll_clock(USB_PLL);
552 val = pll_clock(MCU_PLL);
555 val = pll_clock(TUR_PLL);
566 * This function returns the peripheral clock value in Hz.
568 u32 get_peri_clock(enum peri_clocks clk)
570 volatile u32 mcr = readl(CRM_MCU_BASE_ADDR + CLKCTL_MCR);
571 volatile u32 mpdr0 = readl(CRM_MCU_BASE_ADDR + CLKCTL_PDR0);
572 volatile u32 mpdr1 = readl(CRM_MCU_BASE_ADDR + CLKCTL_PDR1);
573 u32 clk_sel, pre_pdf, pdf, ref_clk, ret_val = 0;
580 return get_main_clock(IPG_CLK);
583 pre_pdf = (mpdr1 >> 6) & 0x7;
584 pdf = (mpdr1 >> 1) & 0x1F;
585 clk_sel = mcr & (1 << 28);
586 ref_clk = (clk_sel != 0) ? pll_clock(USB_PLL) : pll_clock(MCU_PLL);
587 ret_val = ref_clk / ((pre_pdf + 1) * (pdf + 1));
590 pre_pdf = (mpdr1 >> 15) & 0x7;
591 pdf = (mpdr1 >> 10) & 0x1F;
592 clk_sel = mcr & (1 << 27);
593 ref_clk = (clk_sel != 0) ? pll_clock(USB_PLL) : pll_clock(MCU_PLL);
594 ret_val = ref_clk / ((pre_pdf + 1) * (pdf + 1));
597 #ifdef CYGPKG_HAL_ARM_MXC91331_CHIP
598 pdf = (mpdr0 >> 23) & 0x1FF;
599 ret_val = pll_clock(USB_PLL) / (pdf + 1);
601 #ifdef CYGPKG_HAL_ARM_MXC91321_CHIP
602 clk_sel = (mcr >> 25) & 0x3;
603 pdf = ((mpdr0 >> 23) & 0x1FF) + 1;
604 pdf = (2 * pdf) + (mpdr0 & (1 << 22)); //multiplied by 2
605 pdf *= (1 + (mpdr0 & (1 << 21)));
607 ret_val = (2 * csi_sdhc_clock_src(clk_sel)) / pdf;
611 pre_pdf = (mpdr1 >> 24) & 0x7;
612 pdf = (mpdr1 >> 19) & 0x1F;
613 clk_sel = mcr & (1 << 11);
614 ref_clk = (clk_sel != 0) ? pll_clock(USB_PLL) : pll_clock(MCU_PLL);
615 ret_val = ref_clk / ((pre_pdf + 1) * (pdf + 1));
619 ret_val = get_main_clock(IPG_CLK);
622 diag_printf("%s(): This clock: %d not supported yet \n",
631 "Select clock source for CKO1 (AKA CKO) (J10 on the EVB CPU daughter card)",
632 " The output is 1/8 of actual clock. Default is MCU_PLL\n\
633 <0> - display current cko selection\n\
641 <8> - MB_PAT_REF \n",
645 static u8* cko_name[] = {
657 #define CKO_MAX_INDEX (sizeof(cko_name) / sizeof(u8*))
658 #define CKO_DIV 3 // default divide by 8
659 #define CKOH_DIV 3 // default divide by 8
661 static void ckol(int argc,char *argv[])
663 u32 action = 0, cosr;
665 if (!scan_opts(argc, argv, 1, 0, 0, (void*) &action,
666 OPTION_ARG_TYPE_NUM, "action"))
669 if (action >= CKO_MAX_INDEX) {
670 diag_printf("%d is not supported\n\n", action);
674 cosr = readl(CRM_MCU_BASE_ADDR + CLKCTL_COSR);
677 cosr = (cosr & (~0x7F)) + (1 << 6) + (CKO_DIV << 3) + action - 1;
678 writel(cosr, CRM_MCU_BASE_ADDR + CLKCTL_COSR);
679 diag_printf("Set clko to ");
682 cosr = readl(CRM_MCU_BASE_ADDR + CLKCTL_COSR);
683 diag_printf("%s\n", cko_name[(cosr & 0x7) + 1]);
684 diag_printf("COSR register[0x%x] = 0x%x\n",
685 (CRM_MCU_BASE_ADDR + CLKCTL_COSR), cosr);
689 "Select clock source for CKO2 (J9 on the EVB CPU daughter card)",
690 " The default is 1/8 of IPG_CLK_ARM (core clock)\n\
691 <0> - display current cko selection\n\
701 <10> - MCU_AHB_CLK \n\
704 <13> - DSP_AHB_CLK \n\
705 <14> - IPG_CLK_ARM (Core) \n\
706 <15> - PAT_REF_CLK_SYNC \n\
707 <16> - WB_PAT_REF_CLK_SYNC \n\
708 <17> - TURBO_PLL (MXC91321 only)\n\
709 <18> - AFC_PLL (MXC91321 only) \n",
713 static u8* div_str[] = {
724 static u8* ckoh_name[] ={
739 "IPG_CLK_ARM (Core)",
741 "WB_PAT_REF_CLK_SYNC",
742 #ifdef CYGPKG_HAL_ARM_MXC91321_CHIP
748 #define CKOH_MAX_INDEX (sizeof(ckoh_name) / sizeof(u8*))
750 static void ckoh(int argc,char *argv[])
752 u32 action = 0, cosr, div = 0, i, j;
754 if (!scan_opts(argc, argv, 1, 0, 0, (void*) &action,
755 OPTION_ARG_TYPE_NUM, "action"))
758 if (action >= CKOH_MAX_INDEX) {
759 diag_printf("%d is not supported\n\n", action);
763 cosr = readl(CRM_MCU_BASE_ADDR + CLKCTL_COSR);
766 if (action == 1 || action == 3 || action == 4 || action == 5 || action == 14 || action == 17)
768 cosr = (cosr & (~0x0007FC00)) + (div << 10) + (1 << 13) +
769 ((action - 1) << 14);
770 writel(cosr, CRM_MCU_BASE_ADDR + CLKCTL_COSR);
771 diag_printf("Set clko to ");
774 cosr = readl(CRM_MCU_BASE_ADDR + CLKCTL_COSR);
775 i = (cosr >> 10) & 0x7;
776 j = (cosr >> 14) & 0x1F;
777 diag_printf("%s%s\n", div_str[i], ckoh_name[j + 1]);
778 diag_printf("COSR register[0x%x] = 0x%x\n",
779 (CRM_MCU_BASE_ADDR + CLKCTL_COSR), cosr);
784 * This command is added for some simple testing only. It turns on/off
785 * L2 cache regardless of L1 cache state. The side effect of this is
786 * when doing any flash operations such as "fis init", the L2
787 * will be turned back on along with L1 caches even though it is off
788 * by using this command.
796 void do_L2_caches(int argc, char *argv[])
802 if (strcasecmp(argv[1], "on") == 0) {
803 HAL_DISABLE_INTERRUPTS(oldints);
805 HAL_RESTORE_INTERRUPTS(oldints);
806 } else if (strcasecmp(argv[1], "off") == 0) {
807 HAL_DISABLE_INTERRUPTS(oldints);
808 HAL_CLEAN_INVALIDATE_L2();
810 HAL_RESTORE_INTERRUPTS(oldints);
812 diag_printf("Invalid L2 cache mode: %s\n", argv[1]);
815 HAL_L2CACHE_IS_ENABLED(L2cache_on);
816 diag_printf("L2 cache: %s\n", L2cache_on?"On":"Off");
819 #endif //L2CC_ENABLED
821 #define IIM_ERR_SHIFT 8
822 #define POLL_FUSE_PRGD (IIM_STAT_PRGD | (IIM_ERR_PRGE << IIM_ERR_SHIFT))
823 #define POLL_FUSE_SNSD (IIM_STAT_SNSD | (IIM_ERR_SNSE << IIM_ERR_SHIFT))
825 static void fuse_op_start(void)
827 /* Do not generate interrupt */
828 writel(0, IIM_BASE_ADDR + IIM_STATM_OFF);
829 // clear the status bits and error bits
830 writel(0x3, IIM_BASE_ADDR + IIM_STAT_OFF);
831 writel(0xFE, IIM_BASE_ADDR + IIM_ERR_OFF);
835 * The action should be either:
840 static int poll_fuse_op_done(int action)
845 if (action != POLL_FUSE_PRGD && action != POLL_FUSE_SNSD) {
846 diag_printf("%s(%d) invalid operation\n", __FUNCTION__, action);
850 /* Poll busy bit till it is NOT set */
851 while ((readl(IIM_BASE_ADDR + IIM_STAT_OFF) & IIM_STAT_BUSY) != 0 ) {
854 /* Test for successful write */
855 status = readl(IIM_BASE_ADDR + IIM_STAT_OFF);
856 error = readl(IIM_BASE_ADDR + IIM_ERR_OFF);
858 if ((status & action) != 0 && (error & (action >> IIM_ERR_SHIFT)) == 0) {
860 diag_printf("Even though the operation seems successful...\n");
861 diag_printf("There are some error(s) at addr=0x%x: 0x%x\n",
862 (IIM_BASE_ADDR + IIM_ERR_OFF), error);
866 diag_printf("%s(%d) failed\n", __FUNCTION__, action);
867 diag_printf("status address=0x%x, value=0x%x\n",
868 (IIM_BASE_ADDR + IIM_STAT_OFF), status);
869 diag_printf("There are some error(s) at addr=0x%x: 0x%x\n",
870 (IIM_BASE_ADDR + IIM_ERR_OFF), error);
874 static void sense_fuse(int bank, int row, int bit)
876 int addr, addr_l, addr_h, reg_addr;
880 addr = ((bank << 11) | (row << 3) | (bit & 0x7));
881 /* Set IIM Program Upper Address */
882 addr_h = (addr >> 8) & 0x000000FF;
883 /* Set IIM Program Lower Address */
884 addr_l = (addr & 0x000000FF);
886 #ifdef IIM_FUSE_DEBUG
887 diag_printf("%s: addr_h=0x%x, addr_l=0x%x\n",
888 __FUNCTION__, addr_h, addr_l);
890 writel(addr_h, IIM_BASE_ADDR + IIM_UA_OFF);
891 writel(addr_l, IIM_BASE_ADDR + IIM_LA_OFF);
893 writel(0x8, IIM_BASE_ADDR + IIM_FCTL_OFF);
894 if (poll_fuse_op_done(POLL_FUSE_SNSD) != 0) {
895 diag_printf("%s(bank: %d, row: %d, bit: %d failed\n",
896 __FUNCTION__, bank, row, bit);
898 reg_addr = IIM_BASE_ADDR + IIM_SDAT_OFF;
899 diag_printf("fuses at (bank:%d, row:%d) = 0x%x\n", bank, row, readl(reg_addr));
902 void do_fuse_read(int argc, char *argv[])
907 diag_printf("Useage: fuse_read <bank> <row>\n");
909 } else if (argc == 3) {
910 if (!parse_num(*(&argv[1]), (unsigned long *)&bank, &argv[1], " ")) {
911 diag_printf("Error: Invalid parameter\n");
914 if (!parse_num(*(&argv[2]), (unsigned long *)&row, &argv[2], " ")) {
915 diag_printf("Error: Invalid parameter\n");
919 diag_printf("Read fuse at bank:%d row:%d\n", bank, row);
920 sense_fuse(bank, row, 0);
923 diag_printf("Passing in wrong arguments: %d\n", argc);
924 diag_printf("Useage: fuse_read <bank> <row>\n");
928 /* Blow fuses based on the bank, row and bit positions (all 0-based)
930 static int fuse_blow(int bank,int row,int bit)
932 int addr, addr_l, addr_h, ret = -1;
936 /* Disable IIM Program Protect */
937 writel(0xAA, IIM_BASE_ADDR + IIM_PREG_P_OFF);
939 addr = ((bank << 11) | (row << 3) | (bit & 0x7));
940 /* Set IIM Program Upper Address */
941 addr_h = (addr >> 8) & 0x000000FF;
942 /* Set IIM Program Lower Address */
943 addr_l = (addr & 0x000000FF);
945 #ifdef IIM_FUSE_DEBUG
946 diag_printf("blowing addr_h=0x%x, addr_l=0x%x\n", addr_h, addr_l);
949 writel(addr_h, IIM_BASE_ADDR + IIM_UA_OFF);
950 writel(addr_l, IIM_BASE_ADDR + IIM_LA_OFF);
951 /* Start Programming */
952 writel(0x31, IIM_BASE_ADDR + IIM_FCTL_OFF);
953 if (poll_fuse_op_done(POLL_FUSE_PRGD) == 0) {
957 /* Enable IIM Program Protect */
958 writel(0x0, IIM_BASE_ADDR + IIM_PREG_P_OFF);
963 * This command is added for burning IIM fuses
965 RedBoot_cmd("fuse_read",
971 RedBoot_cmd("fuse_blow",
973 "<bank> <row> <value>",
977 #define INIT_STRING "12345678"
978 static char ready_to_blow[] = INIT_STRING;
980 void quick_itoa(u32 num, char *a)
983 for (i = 0; i <= 7; i++) {
984 j = (num >> (4 * i)) & 0xF;
985 k = (j < 10) ? '0' : ('a' - 0xa);
990 void do_fuse_blow(int argc, char *argv[])
992 int bank, row, value, i;
995 diag_printf("It is too dangeous for you to use this command.\n");
997 } else if (argc == 2) {
998 if (strcasecmp(argv[1], "nandboot") == 0) {
999 quick_itoa(readl(EPIT_BASE_ADDR + EPITCNR), ready_to_blow);
1000 diag_printf("%s\n", ready_to_blow);
1003 } else if (argc == 3) {
1004 if (strcasecmp(argv[1], "nandboot") == 0 &&
1005 strcasecmp(argv[2], ready_to_blow) == 0) {
1006 #if defined(CYGPKG_HAL_ARM_MXC91131) || defined(CYGPKG_HAL_ARM_MX21) || defined(CYGPKG_HAL_ARM_MX27) || defined(CYGPKG_HAL_ARM_MX31)
1007 diag_printf("No need to blow any fuses for NAND boot on this platform\n\n");
1009 diag_printf("Ready to burn NAND boot fuses\n");
1010 if (fuse_blow(0, 16, 1) != 0 || fuse_blow(0, 16, 7) != 0) {
1011 diag_printf("NAND BOOT fuse blown failed miserably ...\n");
1013 diag_printf("NAND BOOT fuse blown successfully ...\n");
1016 diag_printf("Not ready: %s, %s\n", argv[1], argv[2]);
1019 } else if (argc == 4) {
1020 if (!parse_num(*(&argv[1]), (unsigned long *)&bank, &argv[1], " ")) {
1021 diag_printf("Error: Invalid parameter\n");
1024 if (!parse_num(*(&argv[2]), (unsigned long *)&row, &argv[2], " ")) {
1025 diag_printf("Error: Invalid parameter\n");
1028 if (!parse_num(*(&argv[3]), (unsigned long *)&value, &argv[3], " ")) {
1029 diag_printf("Error: Invalid parameter\n");
1033 diag_printf("Blowing fuse at bank:%d row:%d value:%d\n",
1035 for (i = 0; i < 8; i++) {
1036 if (((value >> i) & 0x1) == 0) {
1039 if (fuse_blow(bank, row, i) != 0) {
1040 diag_printf("fuse_blow(bank: %d, row: %d, bit: %d failed\n",
1043 diag_printf("fuse_blow(bank: %d, row: %d, bit: %d successful\n",
1047 sense_fuse(bank, row, 0);
1050 diag_printf("Passing in wrong arguments: %d\n", argc);
1052 /* Reset to default string */
1053 strcpy(ready_to_blow, INIT_STRING);;
1056 /* precondition: m>0 and n>0. Let g=gcd(m,n). */
1057 int gcd(int m, int n)
1061 if(n > m) {t = m; m = n; n = t;} /* swap */