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 int gcd(int m, int n);
49 typedef unsigned long long u64;
50 typedef unsigned int u32;
51 typedef unsigned short u16;
52 typedef unsigned char u8;
54 #define SZ_DEC_1M 1000000
55 #define PLL_PD_MAX 16 //actual pd+1
56 #define PLL_MFI_MAX 15
64 #define REF_IN_CLK_NUM 4
65 struct fixed_pll_mfd {
69 const struct fixed_pll_mfd fixed_mfd[REF_IN_CLK_NUM] = {
72 {FREQ_24MHZ, 24 * 16}, // 384
83 #define PLL_FREQ_MAX(_ref_clk_) (4 * _ref_clk_ * PLL_MFI_MAX)
84 #define PLL_FREQ_MIN(_ref_clk_) ((2 * _ref_clk_ * (PLL_MFI_MIN - 1)) / PLL_PD_MAX)
85 #define MAX_DDR_CLK 200000000
86 #define AHB_CLK_MAX 133333333
87 #define IPG_CLK_MAX (AHB_CLK_MAX / 2)
88 #define NFC_CLK_MAX 25000000
89 // IPU-HSP clock is independent of the HCLK and can go up to 177MHz but requires
90 // higher voltage support. For simplicity, limit it to 133MHz
91 #define HSP_CLK_MAX 133333333
93 #define ERR_WRONG_CLK -1
97 #define ERR_NO_PRESC -5
98 #define ERR_NO_AHB_DIV -6
100 u32 pll_clock(enum plls pll);
101 u32 get_main_clock(enum main_clocks clk);
102 u32 get_peri_clock(enum peri_clocks clk);
104 static volatile u32 *pll_base[] =
106 REG32_PTR(PLL1_BASE_ADDR),
107 REG32_PTR(PLL2_BASE_ADDR),
108 REG32_PTR(PLL3_BASE_ADDR),
111 #define NOT_ON_VAL 0xDEADBEEF
113 static void clock_setup(int argc, char *argv[]);
116 "Setup/Display clock\nSyntax:",
117 "[<core clock in MHz> :<DDR clock in MHz>] \n\n\
119 [clock] -> Show various clocks\n\
120 [clock 665] -> Core=665 \n\
121 [clock 800:133] -> Core=800 DDR=133 \n\
122 [clock :166] -> Core=no change DDR=166 \n",
127 * This is to calculate various parameters based on reference clock and
128 * targeted clock based on the equation:
129 * t_clk = 2*ref_freq*(mfi + mfn/(mfd+1))/(pd+1)
130 * This calculation is based on a fixed MFD value for simplicity.
132 * @param ref reference clock freq in Hz
133 * @param target targeted clock in Hz
134 * @param p_pd calculated pd value (pd value from register + 1) upon return
135 * @param p_mfi calculated actual mfi value upon return
136 * @param p_mfn calculated actual mfn value upon return
137 * @param p_mfd fixed mfd value (mfd value from register + 1) upon return
139 * @return 0 if successful; non-zero otherwise.
141 int calc_pll_params(u32 ref, u32 target, struct pll_param *pll)
143 u64 pd, mfi = 1, mfn, mfd, n_target = target, n_ref = ref, i;
145 // make sure targeted freq is in the valid range. Otherwise the
146 // following calculation might be wrong!!!
147 if (n_target < PLL_FREQ_MIN(ref) || n_target > PLL_FREQ_MAX(ref))
148 return ERR_WRONG_CLK;
150 if (i == REF_IN_CLK_NUM)
151 return ERR_WRONG_CLK;
152 if (fixed_mfd[i].ref_clk_hz == ref) {
153 mfd = fixed_mfd[i].mfd;
158 // Use n_target and n_ref to avoid overflow
159 for (pd = 1; pd <= PLL_PD_MAX; pd++) {
160 mfi = (n_target * pd) / (4 * n_ref);
161 if (mfi > PLL_MFI_MAX) {
163 } else if (mfi < 5) {
168 // Now got pd and mfi already
169 mfn = (((n_target * pd) / 4 - n_ref * mfi) * mfd) / n_ref;
170 #ifdef CMD_CLOCK_DEBUG
171 diag_printf("%d: ref=%d, target=%d, pd=%d, mfi=%d,mfn=%d, mfd=%d\n",
172 __LINE__, ref, (u32)n_target, (u32)pd, (u32)mfi, (u32)mfn, (u32)mfd);
179 pll->mfn = (u32)(mfn / i);
180 pll->mfd = (u32)(mfd / i);
185 * This function returns the low power audio clock.
190 u32 ccsr = readl(CCM_BASE_ADDR + CLKCTL_CCSR);
192 if (((ccsr >> 9) & 1) == 0) {
193 ret_val = FREQ_24MHZ;
195 ret_val = FREQ_32768HZ;
201 * This function returns the periph_clk.
203 u32 get_periph_clk(void)
205 u32 ret_val = 0, clk_sel;
207 u32 cbcdr = readl(CCM_BASE_ADDR + CLKCTL_CBCDR);
208 u32 cbcmr = readl(CCM_BASE_ADDR + CLKCTL_CBCMR);
210 if (((cbcdr >> 25) & 1) == 0) {
211 ret_val = pll_clock(PLL2);
213 clk_sel = (cbcmr >> 12) & 3;
215 ret_val = pll_clock(PLL1);
216 } else if (clk_sel == 1) {
217 ret_val = pll_clock(PLL3);
218 } else if (clk_sel == 2) {
219 ret_val = get_lp_apm();
226 * This function assumes the expected core clock has to be changed by
227 * modifying the PLL. This is NOT true always but for most of the times,
228 * it is. So it assumes the PLL output freq is the same as the expected
229 * core clock (presc=1) unless the core clock is less than PLL_FREQ_MIN.
230 * In the latter case, it will try to increase the presc value until
231 * (presc*core_clk) is greater than PLL_FREQ_MIN. It then makes call to
232 * calc_pll_params() and obtains the values of PD, MFI,MFN, MFD based
233 * on the targeted PLL and reference input clock to the PLL. Lastly,
234 * it sets the register based on these values along with the dividers.
235 * Note 1) There is no value checking for the passed-in divider values
236 * so the caller has to make sure those values are sensible.
237 * 2) Also adjust the NFC divider such that the NFC clock doesn't
238 * exceed NFC_CLK_MAX.
239 * 3) IPU HSP clock is independent of AHB clock. Even it can go up to
240 * 177MHz for higher voltage, this function fixes the max to 133MHz.
241 * 4) This function should not have allowed diag_printf() calls since
242 * the serial driver has been stoped. But leave then here to allow
243 * easy debugging by NOT calling the cyg_hal_plf_serial_stop().
245 * @param ref pll input reference clock (24MHz)
246 * @param core_clk core clock in Hz
247 * @param emi_clk emi clock in Hz
248 # @return 0 if successful; non-zero otherwise
250 int configure_clock(u32 ref, u32 core_clk, u32 emi_clk)
254 struct pll_param pll_param;
255 int ret, clk_sel, div = 1, div_core = 1, div_per = 1, shift = 0;
256 u32 cbcdr = readl(CCM_BASE_ADDR + CLKCTL_CBCDR);
257 u32 cbcmr = readl(CCM_BASE_ADDR + CLKCTL_CBCMR);
258 u32 ccsr = readl(CCM_BASE_ADDR + CLKCTL_CCSR);
259 u32 icgc = readl(PLATFORM_BASE_ADDR + PLATFORM_ICGC);
262 // assume pll default to core clock first
264 if ((ret = calc_pll_params(ref, pll, &pll_param)) != 0) {
265 diag_printf("can't find pll parameters: %d\n", ret);
268 #ifdef CMD_CLOCK_DEBUG
269 diag_printf("ref=%d, pll=%d, pd=%d, mfi=%d,mfn=%d, mfd=%d\n",
270 ref, pll, pll_param.pd, pll_param.mfi, pll_param.mfn, pll_param.mfd);
273 /* Applies for TO 2 only */
274 if (((cbcdr >> 30) & 0x1) == 0x1) {
275 /* Disable IPU and HSC dividers */
276 writel(0x60000, CCM_BASE_ADDR + CLKCTL_CCDR);
277 /* Switch DDR to different source */
278 writel(cbcdr & ~0x40000000, CCM_BASE_ADDR + CLKCTL_CBCDR);
279 while (readl(CCM_BASE_ADDR + CLKCTL_CDHIPR) != 0);
280 writel(0x0, CCM_BASE_ADDR + CLKCTL_CCDR);
283 /* Switch ARM to PLL2 clock */
284 writel(ccsr | 0x4, CCM_BASE_ADDR + CLKCTL_CCSR);
286 if ((core_clk > 665000000) && (core_clk <= 800000000)) {
288 } else if (core_clk > 800000000) {
294 if (core_clk > 800000000) {
296 increase_core_voltage(true);
299 increase_core_voltage(false);
302 // adjust pll settings
303 writel(((pll_param.pd - 1) << 0) | (pll_param.mfi << 4),
304 PLL1_BASE_ADDR + PLL_DP_OP);
305 writel(pll_param.mfn, PLL1_BASE_ADDR + PLL_DP_MFN);
306 writel(pll_param.mfd - 1, PLL1_BASE_ADDR + PLL_DP_MFD);
307 writel(((pll_param.pd - 1) << 0) | (pll_param.mfi << 4),
308 PLL1_BASE_ADDR + PLL_DP_HFS_OP);
309 writel(pll_param.mfn, PLL1_BASE_ADDR + PLL_DP_HFS_MFN);
310 writel(pll_param.mfd - 1, PLL1_BASE_ADDR + PLL_DP_HFS_MFD);
313 icgc |= (div_core << 4);
315 /* Set the platform clock dividers */
316 writel(icgc, PLATFORM_BASE_ADDR + PLATFORM_ICGC);
317 /* Switch ARM back to PLL1 */
318 writel((ccsr & ~0x4), CCM_BASE_ADDR + CLKCTL_CCSR);
319 /* Applies for TO 2 only */
320 if (((cbcdr >> 30) & 0x1) == 0x1) {
321 /* Disable IPU and HSC dividers */
322 writel(0x60000, CCM_BASE_ADDR + CLKCTL_CCDR);
323 /* Switch DDR back to PLL1 */
324 writel(cbcdr | 0x40000000, CCM_BASE_ADDR + CLKCTL_CBCDR);
325 while (readl(CCM_BASE_ADDR + CLKCTL_CDHIPR) != 0);
326 writel(0x0, CCM_BASE_ADDR + CLKCTL_CCDR);
328 /* Keep EMI clock to the max if not specified */
335 /* Applies for TO 2 only */
336 if (((cbcdr >> 30) & 0x1) == 0x1) {
337 clk_src = pll_clock(PLL1);
340 clk_src = get_periph_clk();
341 /* Find DDR clock input */
342 clk_sel = (cbcmr >> 10) & 0x3;
345 } else if (clk_sel == 1) {
347 } else if (clk_sel == 2) {
349 } else if (clk_sel == 3) {
353 if ((clk_src % emi_clk) == 0)
354 div = clk_src / emi_clk;
356 div = (clk_src / emi_clk) + 1;
360 cbcdr = cbcdr & ~(0x7 << shift);
361 cbcdr |= ((div - 1) << shift);
362 /* Disable IPU and HSC dividers */
363 writel(0x60000, CCM_BASE_ADDR + CLKCTL_CCDR);
364 writel(cbcdr, CCM_BASE_ADDR + CLKCTL_CBCDR);
365 while (readl(CCM_BASE_ADDR + CLKCTL_CDHIPR) != 0);
366 writel(0x0, CCM_BASE_ADDR + CLKCTL_CCDR);
371 static void clock_setup(int argc,char *argv[])
374 u32 i, core_clk, ddr_clk, data[3];
381 for (i = 0; i < 2; i++) {
382 if (!parse_num(*(&argv[1]), &temp, &argv[1], ":")) {
383 diag_printf("Error: Invalid parameter\n");
389 core_clk = data[0] * SZ_DEC_1M;
390 ddr_clk = data[1] * SZ_DEC_1M;
393 if ((core_clk < PLL_FREQ_MIN(PLL_REF_CLK)) || (core_clk > PLL_FREQ_MAX(PLL_REF_CLK))) {
394 diag_printf("Targeted core clock should be within [%d - %d]\n",
395 PLL_FREQ_MIN(PLL_REF_CLK), PLL_FREQ_MAX(PLL_REF_CLK));
401 if (ddr_clk > MAX_DDR_CLK) {
402 diag_printf("DDR clock should be less than %d MHz, assuming max value \n", (MAX_DDR_CLK / SZ_DEC_1M));
403 ddr_clk = MAX_DDR_CLK;
407 // stop the serial to be ready to adjust the clock
408 hal_delay_us(100000);
409 cyg_hal_plf_serial_stop();
411 ret = configure_clock(PLL_REF_CLK, core_clk, ddr_clk);
412 // restart the serial driver
413 cyg_hal_plf_serial_init();
414 hal_delay_us(100000);
417 diag_printf("Failed to setup clock: %d\n", ret);
420 diag_printf("\n<<<New clock setting>>>\n");
422 // Now printing clocks
425 diag_printf("\nPLL1\t\tPLL2\t\tPLL3\n");
426 diag_printf("========================================\n");
427 diag_printf("%-16d%-16d%-16d\n\n", pll_clock(PLL1), pll_clock(PLL2),
429 diag_printf("CPU\t\tAHB\t\tIPG\t\tEMI_CLK\n");
430 diag_printf("========================================================\n");
431 diag_printf("%-16d%-16d%-16d%-16d\n\n",
432 get_main_clock(CPU_CLK),
433 get_main_clock(AHB_CLK),
434 get_main_clock(IPG_CLK),
435 get_main_clock(DDR_CLK));
437 diag_printf("NFC\t\tUSB\t\tIPG_PER_CLK\n");
438 diag_printf("========================================\n");
439 diag_printf("%-16d%-16d%-16d\n\n",
440 get_main_clock(NFC_CLK),
441 get_main_clock(USB_CLK),
442 get_main_clock(IPG_PER_CLK));
444 diag_printf("UART1-3\t\tSSI1\t\tSSI2\t\tSPI\n");
445 diag_printf("===========================================");
446 diag_printf("=============\n");
448 diag_printf("%-16d%-16d%-16d%-16d\n\n",
449 get_peri_clock(UART1_BAUD),
450 get_peri_clock(SSI1_BAUD),
451 get_peri_clock(SSI2_BAUD),
452 get_peri_clock(SPI1_CLK));
455 diag_printf("IPG_PERCLK as baud clock for: UART1-5, I2C, OWIRE, SDHC");
456 if (((readl(EPIT1_BASE_ADDR) >> 24) & 0x3) == 0x2) {
457 diag_printf(", EPIT");
459 if (((readl(GPT1_BASE_ADDR) >> 6) & 0x7) == 0x2) {
468 * This function returns the PLL output value in Hz based on pll.
470 u32 pll_clock(enum plls pll)
472 u64 mfi, mfn, mfd, pdf, ref_clk, pll_out, sign;
473 u64 dp_ctrl, dp_op, dp_mfd, dp_mfn, clk_sel;
476 dp_ctrl = pll_base[pll][PLL_DP_CTL >> 2];
477 clk_sel = MXC_GET_FIELD(dp_ctrl, 2, 8);
478 ref_clk = fixed_mfd[clk_sel].ref_clk_hz;
480 if ((pll_base[pll][PLL_DP_CTL >> 2] & 0x80) == 0) {
481 dp_op = pll_base[pll][PLL_DP_OP >> 2];
482 dp_mfd = pll_base[pll][PLL_DP_MFD >> 2];
483 dp_mfn = pll_base[pll][PLL_DP_MFN >> 2];
485 dp_op = pll_base[pll][PLL_DP_HFS_OP >> 2];
486 dp_mfd = pll_base[pll][PLL_DP_HFS_MFD >> 2];
487 dp_mfn = pll_base[pll][PLL_DP_HFS_MFN >> 2];
490 mfi = (dp_op >> 4) & 0xF;
491 mfi = (mfi <= 5) ? 5: mfi;
492 mfd = dp_mfd & 0x07FFFFFF;
493 mfn = dp_mfn & 0x07FFFFFF;
495 sign = (mfn < 0x4000000) ? 0: 1;
496 mfn = (mfn <= 0x4000000) ? mfn: (0x8000000 - mfn);
498 dbl = ((dp_ctrl >> 12) & 0x1) + 1;
502 pll_out = (dbl * ref_clk * mfi + ((dbl * ref_clk * mfn) / (mfd + 1))) /
505 pll_out = (dbl * ref_clk * mfi - ((dbl * ref_clk * mfn) / (mfd + 1))) /
513 * This function returns the emi_core_clk_root clock.
515 u32 get_emi_core_clk(void)
517 u32 cbcdr = readl(CCM_BASE_ADDR + CLKCTL_CBCDR);
518 u32 clk_sel = 0, max_pdf = 0, peri_clk = 0, ahb_clk = 0;
521 max_pdf = (cbcdr >> 10) & 0x7;
522 peri_clk = get_periph_clk();
523 ahb_clk = peri_clk / (max_pdf + 1);
525 clk_sel = (cbcdr >> 26) & 1;
535 * This function returns the main clock value in Hz.
537 u32 get_main_clock(enum main_clocks clk)
539 u32 pdf, max_pdf, ipg_pdf, nfc_pdf, clk_sel;
540 u32 pll, ret_val = 0;
541 u32 cacrr = readl(CCM_BASE_ADDR + CLKCTL_CACRR);
542 u32 cbcdr = readl(CCM_BASE_ADDR + CLKCTL_CBCDR);
543 u32 cbcmr = readl(CCM_BASE_ADDR + CLKCTL_CBCMR);
544 u32 cscmr1 = readl(CCM_BASE_ADDR + CLKCTL_CSCMR1);
545 u32 cscdr1 = readl(CCM_BASE_ADDR + CLKCTL_CSCDR1);
550 pll = pll_clock(PLL1);
551 ret_val = pll / (pdf + 1);
554 max_pdf = (cbcdr >> 10) & 0x7;
555 pll = get_periph_clk();
556 ret_val = pll / (max_pdf + 1);
559 max_pdf = (cbcdr >> 10) & 0x7;
560 ipg_pdf = (cbcdr >> 8) & 0x3;
561 pll = get_periph_clk();
562 ret_val = pll / ((max_pdf + 1) * (ipg_pdf + 1));
567 clk_sel = (cbcmr >> 1) & 1;
568 pdf = (((cbcdr >> 6) & 3) + 1) * (((cbcdr >> 3) & 7) + 1) * ((cbcdr & 7) + 1);
570 ret_val = get_periph_clk() / pdf;
572 ret_val = get_lp_apm();
575 /* Same as IPG_CLK */
576 max_pdf = (cbcdr >> 10) & 0x7;
577 ipg_pdf = (cbcdr >> 8) & 0x3;
578 pll = get_periph_clk();
579 ret_val = pll / ((max_pdf + 1) * (ipg_pdf + 1));
583 if (((cbcdr >> 30) & 0x1) == 0x1) {
584 pll = pll_clock(PLL1);
585 pdf = (cbcdr >> 27) & 0x7;
587 clk_sel = (cbcmr >> 10) & 3;
588 pll = get_periph_clk();
591 pdf = (cbcdr >> 16) & 0x7;
592 } else if (clk_sel == 1) {
594 pdf = (cbcdr >> 19) & 0x7;
595 } else if (clk_sel == 2) {
596 /* EMI SLOW CLOCK ROOT */
597 pll = get_emi_core_clk();
598 pdf = (cbcdr >> 22) & 0x7;
599 } else if (clk_sel == 3) {
601 pdf = (cbcdr >> 10) & 0x7;
605 ret_val = pll / (pdf + 1);
608 pdf = (cbcdr >> 22) & 0x7;
609 nfc_pdf = (cbcdr >> 13) & 0x7;
610 pll = get_emi_core_clk();
611 ret_val = pll / ((pdf + 1) * (nfc_pdf + 1));
614 clk_sel = (cscmr1 >> 22) & 3;
616 pll = pll_clock(PLL1);
617 } else if (clk_sel == 1) {
618 pll = pll_clock(PLL2);
619 } else if (clk_sel == 2) {
620 pll = pll_clock(PLL3);
621 } else if (clk_sel == 3) {
624 pdf = (cscdr1 >> 8) & 0x7;
625 max_pdf = (cscdr1 >> 6) & 0x3;
626 ret_val = pll / ((pdf + 1) * (max_pdf + 1));
629 diag_printf("Unknown clock: %d\n", clk);
637 * This function returns the peripheral clock value in Hz.
639 u32 get_peri_clock(enum peri_clocks clk)
641 u32 ret_val = 0, pdf, pre_pdf, clk_sel;
642 u32 cscmr1 = readl(CCM_BASE_ADDR + CLKCTL_CSCMR1);
643 u32 cscdr1 = readl(CCM_BASE_ADDR + CLKCTL_CSCDR1);
644 u32 cscdr2 = readl(CCM_BASE_ADDR + CLKCTL_CSCDR2);
645 u32 cs1cdr = readl(CCM_BASE_ADDR + CLKCTL_CS1CDR);
646 u32 cs2cdr = readl(CCM_BASE_ADDR + CLKCTL_CS2CDR);
652 pre_pdf = (cscdr1 >> 3) & 0x7;
654 clk_sel = (cscmr1 >> 24) & 3;
656 ret_val = pll_clock(PLL1) / ((pre_pdf + 1) * (pdf + 1));
657 } else if (clk_sel == 1) {
658 ret_val = pll_clock(PLL2) / ((pre_pdf + 1) * (pdf + 1));
659 } else if (clk_sel == 2) {
660 ret_val = pll_clock(PLL3) / ((pre_pdf + 1) * (pdf + 1));
662 ret_val = get_lp_apm() / ((pre_pdf + 1) * (pdf + 1));
666 pre_pdf = (cs1cdr >> 6) & 0x7;
668 clk_sel = (cscmr1 >> 14) & 3;
670 ret_val = pll_clock(PLL1) / ((pre_pdf + 1) * (pdf + 1));
671 } else if (clk_sel == 0x1) {
672 ret_val = pll_clock(PLL2) / ((pre_pdf + 1) * (pdf + 1));
673 } else if (clk_sel == 0x2) {
674 ret_val = pll_clock(PLL3) / ((pre_pdf + 1) * (pdf + 1));
676 ret_val = CKIH /((pre_pdf + 1) * (pdf + 1));
680 pre_pdf = (cs2cdr >> 6) & 0x7;
682 clk_sel = (cscmr1 >> 12) & 3;
684 ret_val = pll_clock(PLL1) / ((pre_pdf + 1) * (pdf + 1));
685 } else if (clk_sel == 0x1) {
686 ret_val = pll_clock(PLL2) / ((pre_pdf + 1) * (pdf + 1));
687 } else if (clk_sel == 0x2) {
688 ret_val = pll_clock(PLL3) / ((pre_pdf + 1) * (pdf + 1));
690 ret_val = CKIH /((pre_pdf + 1) * (pdf + 1));
695 pre_pdf = (cscdr2 >> 25) & 0x7;
696 pdf = (cscdr2 >> 19) & 0x3F;
697 clk_sel = (cscmr1 >> 4) & 3;
699 ret_val = pll_clock(PLL1) / ((pre_pdf + 1) * (pdf + 1));
700 } else if (clk_sel == 1) {
701 ret_val = pll_clock(PLL2) / ((pre_pdf + 1) * (pdf + 1));
702 } else if (clk_sel == 2) {
703 ret_val = pll_clock(PLL3) / ((pre_pdf + 1) * (pdf + 1));
705 ret_val = get_lp_apm() / ((pre_pdf + 1) * (pdf + 1));
709 diag_printf("%s(): This clock: %d not supported yet \n",
719 * This command is added for some simple testing only. It turns on/off
720 * L2 cache regardless of L1 cache state. The side effect of this is
721 * when doing any flash operations such as "fis init", the L2
722 * will be turned back on along with L1 caches even though it is off
723 * by using this command.
731 void do_L2_caches(int argc, char *argv[])
737 if (strcasecmp(argv[1], "on") == 0) {
738 HAL_DISABLE_INTERRUPTS(oldints);
740 HAL_RESTORE_INTERRUPTS(oldints);
741 } else if (strcasecmp(argv[1], "off") == 0) {
742 HAL_DISABLE_INTERRUPTS(oldints);
743 HAL_DCACHE_DISABLE_C1();
744 HAL_CACHE_FLUSH_ALL();
746 HAL_DCACHE_ENABLE_L1();
747 HAL_RESTORE_INTERRUPTS(oldints);
749 diag_printf("Invalid L2 cache mode: %s\n", argv[1]);
752 HAL_L2CACHE_IS_ENABLED(L2cache_on);
753 diag_printf("L2 cache: %s\n", L2cache_on?"On":"Off");
756 #endif //L2CC_ENABLED
758 #define IIM_ERR_SHIFT 8
759 #define POLL_FUSE_PRGD (IIM_STAT_PRGD | (IIM_ERR_PRGE << IIM_ERR_SHIFT))
760 #define POLL_FUSE_SNSD (IIM_STAT_SNSD | (IIM_ERR_SNSE << IIM_ERR_SHIFT))
762 static void fuse_op_start(void)
764 /* Do not generate interrupt */
765 writel(0, IIM_BASE_ADDR + IIM_STATM_OFF);
766 // clear the status bits and error bits
767 writel(0x3, IIM_BASE_ADDR + IIM_STAT_OFF);
768 writel(0xFE, IIM_BASE_ADDR + IIM_ERR_OFF);
772 * The action should be either:
777 static int poll_fuse_op_done(int action)
782 if (action != POLL_FUSE_PRGD && action != POLL_FUSE_SNSD) {
783 diag_printf("%s(%d) invalid operation\n", __FUNCTION__, action);
787 /* Poll busy bit till it is NOT set */
788 while ((readl(IIM_BASE_ADDR + IIM_STAT_OFF) & IIM_STAT_BUSY) != 0 ) {
791 /* Test for successful write */
792 status = readl(IIM_BASE_ADDR + IIM_STAT_OFF);
793 error = readl(IIM_BASE_ADDR + IIM_ERR_OFF);
795 if ((status & action) != 0 && (error & (action >> IIM_ERR_SHIFT)) == 0) {
797 diag_printf("Even though the operation seems successful...\n");
798 diag_printf("There are some error(s) at addr=0x%x: 0x%x\n",
799 (IIM_BASE_ADDR + IIM_ERR_OFF), error);
803 diag_printf("%s(%d) failed\n", __FUNCTION__, action);
804 diag_printf("status address=0x%x, value=0x%x\n",
805 (IIM_BASE_ADDR + IIM_STAT_OFF), status);
806 diag_printf("There are some error(s) at addr=0x%x: 0x%x\n",
807 (IIM_BASE_ADDR + IIM_ERR_OFF), error);
811 static void sense_fuse(int bank, int row, int bit)
813 int addr, addr_l, addr_h, reg_addr;
817 addr = ((bank << 11) | (row << 3) | (bit & 0x7));
818 /* Set IIM Program Upper Address */
819 addr_h = (addr >> 8) & 0x000000FF;
820 /* Set IIM Program Lower Address */
821 addr_l = (addr & 0x000000FF);
823 #ifdef IIM_FUSE_DEBUG
824 diag_printf("%s: addr_h=0x%x, addr_l=0x%x\n",
825 __FUNCTION__, addr_h, addr_l);
827 writel(addr_h, IIM_BASE_ADDR + IIM_UA_OFF);
828 writel(addr_l, IIM_BASE_ADDR + IIM_LA_OFF);
830 writel(0x8, IIM_BASE_ADDR + IIM_FCTL_OFF);
831 if (poll_fuse_op_done(POLL_FUSE_SNSD) != 0) {
832 diag_printf("%s(bank: %d, row: %d, bit: %d failed\n",
833 __FUNCTION__, bank, row, bit);
835 reg_addr = IIM_BASE_ADDR + IIM_SDAT_OFF;
836 diag_printf("fuses at (bank:%d, row:%d) = 0x%x\n", bank, row, readl(reg_addr));
839 void do_fuse_read(int argc, char *argv[])
841 unsigned long bank, row;
844 diag_printf("Useage: fuse_read <bank> <row>\n");
846 } else if (argc == 3) {
847 if (!parse_num(*(&argv[1]), &bank, &argv[1], " ")) {
848 diag_printf("Error: Invalid parameter\n");
851 if (!parse_num(*(&argv[2]), &row, &argv[2], " ")) {
852 diag_printf("Error: Invalid parameter\n");
856 diag_printf("Read fuse at bank:%ld row:%ld\n", bank, row);
857 sense_fuse(bank, row, 0);
860 diag_printf("Passing in wrong arguments: %d\n", argc);
861 diag_printf("Useage: fuse_read <bank> <row>\n");
865 /* Blow fuses based on the bank, row and bit positions (all 0-based)
867 static int fuse_blow(int bank,int row,int bit)
869 int addr, addr_l, addr_h, ret = -1;
873 /* Disable IIM Program Protect */
874 writel(0xAA, IIM_BASE_ADDR + IIM_PREG_P_OFF);
876 addr = ((bank << 11) | (row << 3) | (bit & 0x7));
877 /* Set IIM Program Upper Address */
878 addr_h = (addr >> 8) & 0x000000FF;
879 /* Set IIM Program Lower Address */
880 addr_l = (addr & 0x000000FF);
882 #ifdef IIM_FUSE_DEBUG
883 diag_printf("blowing addr_h=0x%x, addr_l=0x%x\n", addr_h, addr_l);
886 writel(addr_h, IIM_BASE_ADDR + IIM_UA_OFF);
887 writel(addr_l, IIM_BASE_ADDR + IIM_LA_OFF);
888 /* Start Programming */
889 writel(0x31, IIM_BASE_ADDR + IIM_FCTL_OFF);
890 if (poll_fuse_op_done(POLL_FUSE_PRGD) == 0) {
894 /* Enable IIM Program Protect */
895 writel(0x0, IIM_BASE_ADDR + IIM_PREG_P_OFF);
900 * This command is added for burning IIM fuses
902 RedBoot_cmd("fuse_read",
908 RedBoot_cmd("fuse_blow",
910 "<bank> <row> <value>",
914 #define INIT_STRING "12345678"
916 void quick_itoa(u32 num, char *a)
919 for (i = 0; i <= 7; i++) {
920 j = (num >> (4 * i)) & 0xF;
921 k = (j < 10) ? '0' : ('a' - 0xa);
926 void do_fuse_blow(int argc, char *argv[])
928 unsigned long bank, row, value;
932 diag_printf("It is too dangeous for you to use this command.\n");
935 if (!parse_num(*(&argv[1]), &bank, &argv[1], " ")) {
936 diag_printf("Error: Invalid parameter\n");
939 if (!parse_num(*(&argv[2]), &row, &argv[2], " ")) {
940 diag_printf("Error: Invalid parameter\n");
943 if (!parse_num(*(&argv[3]), &value, &argv[3], " ")) {
944 diag_printf("Error: Invalid parameter\n");
948 reg = readl(CCM_BASE_ADDR + 0x64);
950 writel(reg, CCM_BASE_ADDR + 0x64);
952 diag_printf("Blowing fuse at bank:%ld row:%ld value:%ld\n",
954 for (i = 0; i < 8; i++) {
955 if (((value >> i) & 0x1) == 0) {
958 if (fuse_blow(bank, row, i) != 0) {
959 diag_printf("fuse_blow(bank: %ld, row: %ld, bit: %d failed\n",
962 diag_printf("fuse_blow(bank: %ld, row: %ld, bit: %d successful\n",
966 sense_fuse(bank, row, 0);
968 writel(reg, CCM_BASE_ADDR + 0x64);
971 /* precondition: m>0 and n>0. Let g=gcd(m,n). */
972 int gcd(int m, int n)
976 if(n > m) {t = m; m = n; n = t;} /* swap */
982 #define CLOCK_SRC_DETECT_MS 100
983 #define CLOCK_IPG_DEFAULT 66500000
984 #define CLOCK_SRC_DETECT_MARGIN 500000
985 void mxc_show_clk_input(void)
987 // u32 c1, c2, diff, ipg_real, num = 0;
993 diag_printf("FPM enabled --> 32KHz input source\n");
998 diag_printf("Error %d: unknown clock source %d\n", __LINE__, prcs);
1002 // enable GPT with IPG clock input
1003 writel(0x241, GPT_BASE_ADDR + GPTCR);
1005 writel(0, GPT_BASE_ADDR + GPTPR);
1007 c1 = readl(GPT_BASE_ADDR + GPTCNT);
1008 // use 32KHz input clock to get the delay
1009 hal_delay_us(CLOCK_SRC_DETECT_MS * 1000);
1010 c2 = readl(GPT_BASE_ADDR + GPTCNT);
1011 diff = (c2 > c1) ? (c2 - c1) : (0xFFFFFFFF - c1 + c2);
1013 ipg_real = diff * (1000 / CLOCK_SRC_DETECT_MS);
1016 diag_printf("Error: Actural clock input is %d MHz\n", num);
1017 diag_printf(" ipg_real=%d CLOCK_IPG_DEFAULT - CLOCK_SRC_DETECT_MARGIN=%d\n\n",
1018 ipg_real, CLOCK_IPG_DEFAULT - CLOCK_SRC_DETECT_MARGIN);
1019 hal_delay_us(2000000);
1021 diag_printf("ipg_real=%d CLOCK_IPG_DEFAULT - CLOCK_SRC_DETECT_MARGIN=%d\n\n",
1022 ipg_real, CLOCK_IPG_DEFAULT - CLOCK_SRC_DETECT_MARGIN);
1027 RedBoot_init(mxc_show_clk_input, RedBoot_INIT_LAST);
1029 void imx_power_mode(int mode)
1031 volatile unsigned int val;
1034 writel(0x0000030f, GPC_PGR);
1035 writel(0x1, SRPGCR_EMI);
1036 writel(0x1, SRPGCR_ARM);
1037 writel(0x1, PGC_PGCR_VPU);
1038 writel(0x1, PGC_PGCR_IPU);
1042 // stop mode - from validation code
1043 // Set DSM_INT_HOLDOFF bit in TZIC
1044 // If the TZIC didn't write the bit then there was interrupt pending
1045 // It will be serviced while we're in the loop
1046 // So we write to this bit again
1047 while (readl(INTC_BASE_ADDR + 0x14) == 0) {
1048 writel(1, INTC_BASE_ADDR + 0x14);
1058 diag_printf("Entering stop mode\n");
1059 val = readl(CCM_BASE_ADDR + 0x74);
1060 val = (val & 0xfffffffc) | 0x2; // set STOP mode
1061 writel(val, CCM_BASE_ADDR + 0x74);
1062 val = readl(PLATFORM_LPC_REG);
1063 writel(val | (1 << 16), PLATFORM_LPC_REG);// ENABLE DSM in ELBOW submodule of ARM platform
1064 writel(val | (1 << 17), PLATFORM_LPC_REG);// ENABLE DSM in ELBOW submodule of ARM platform
1073 asm("mcr p15, 0, r1, c7, c0, 4");
1076 void do_power_mode(int argc, char *argv[])
1081 diag_printf("Useage: power_mode <mode>\n");
1083 } else if (argc == 2) {
1084 if (!parse_num(*(&argv[1]), (unsigned long *)&mode, &argv[1], " ")) {
1085 diag_printf("Error: Invalid parameter\n");
1088 diag_printf("Entering power mode: %d\n", mode);
1089 imx_power_mode(mode);
1092 diag_printf("Passing in wrong arguments: %d\n", argc);
1093 diag_printf("Useage: power_mode <mode>\n");
1098 * This command is added for burning IIM fuses
1100 RedBoot_cmd("power_mode",
1101 "Enter various power modes:",
1106 <3> - STOP with Power-Gating\n\
1107 -- need reset after issuing the command",