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 #include "hab_super_root.h"
49 //#define IIM_FUSE_DEBUG
50 //#define CMD_CLOCK_DEBUG
51 #ifdef CMD_CLOCK_DEBUG
57 #define dbg(fmt...) CYG_EMPTY_STATEMENT
60 int gcd(int m, int n);
61 extern void increase_core_voltage(bool i);
63 typedef unsigned long long u64;
64 typedef unsigned int u32;
65 typedef unsigned short u16;
66 typedef unsigned char u8;
68 #define SZ_DEC_1M 1000000
69 #define PLL_PD_MAX 16 //actual pd+1
70 #define PLL_MFI_MAX 15
78 #define REF_IN_CLK_NUM 4
79 struct fixed_pll_mfd {
84 const struct fixed_pll_mfd fixed_mfd[REF_IN_CLK_NUM] = {
85 { 0, 0, }, // reserved
86 { 0, 0, }, // reserved
87 { FREQ_24MHZ, 24 * 16, }, // internal osc
88 { FREQ_32768HZ, 1024, }, // FPM
98 #define PLL_FREQ_MAX(_ref_clk_) (4 * _ref_clk_ * PLL_MFI_MAX)
99 #define PLL_FREQ_MIN(_ref_clk_) ((2 * _ref_clk_ * (PLL_MFI_MIN - 1)) / PLL_PD_MAX)
100 #define MAX_DDR_CLK 220000000
101 #define AHB_CLK_MAX 133333333
102 #define IPG_CLK_MAX (AHB_CLK_MAX / 2)
103 #define NFC_CLK_MAX 25000000
104 // IPU-HSP clock is independent of the HCLK and can go up to 177MHz but requires
105 // higher voltage support. For simplicity, limit it to 133MHz
106 #define HSP_CLK_MAX 133333333
108 #define ERR_WRONG_CLK (-1)
109 #define ERR_NO_MFI (-2)
110 #define ERR_NO_MFN (-3)
111 #define ERR_NO_PD (-4)
112 #define ERR_NO_PRESC (-5)
113 #define ERR_NO_AHB_DIV (-6)
115 u32 pll_clock(enum plls pll);
116 u32 get_main_clock(enum main_clocks clk);
117 u32 get_peri_clock(enum peri_clocks clk);
119 static volatile u32 *pll_base[] =
121 REG32_PTR(PLL1_BASE_ADDR),
122 REG32_PTR(PLL2_BASE_ADDR),
123 REG32_PTR(PLL3_BASE_ADDR),
126 #define NOT_ON_VAL 0xDEADBEEF
128 static void clock_setup(int argc, char *argv[]);
131 "Setup/Display clock\nSyntax:",
132 "[<core clock in MHz> :<DDR clock in MHz>]\n\n"
134 " [clock] -> Show various clocks\n"
135 " [clock 665] -> Core=665\n"
136 " [clock 800:133] -> Core=800 DDR=133\n"
137 " [clock :166] -> Core=no change DDR=166\n",
142 * This is to calculate various parameters based on reference clock and
143 * targeted clock based on the equation:
144 * t_clk = 2*ref_freq*(mfi + mfn/(mfd+1))/(pd+1)
145 * This calculation is based on a fixed MFD value for simplicity.
147 * @param ref reference clock freq in Hz
148 * @param target targeted clock in Hz
149 * @param p_pd calculated pd value (pd value from register + 1) upon return
150 * @param p_mfi calculated actual mfi value upon return
151 * @param p_mfn calculated actual mfn value upon return
152 * @param p_mfd fixed mfd value (mfd value from register + 1) upon return
154 * @return 0 if successful; non-zero otherwise.
156 int calc_pll_params(u32 ref, u32 target, struct pll_param *pll)
158 u64 pd, mfi = 1, mfn, mfd, n_target = target, n_ref = ref, i;
160 // make sure targeted freq is in the valid range. Otherwise the
161 // following calculation might be wrong!!!
162 if (n_target < PLL_FREQ_MIN(ref) || n_target > PLL_FREQ_MAX(ref))
163 return ERR_WRONG_CLK;
165 if (i == REF_IN_CLK_NUM)
166 return ERR_WRONG_CLK;
167 if (fixed_mfd[i].ref_clk_hz == ref) {
168 mfd = fixed_mfd[i].mfd;
173 // Use n_target and n_ref to avoid overflow
174 for (pd = 1; pd <= PLL_PD_MAX; pd++) {
175 mfi = (n_target * pd) / (4 * n_ref);
176 if (mfi > PLL_MFI_MAX) {
178 } else if (mfi < 5) {
183 // Now got pd and mfi already
184 mfn = (((n_target * pd) / 4 - n_ref * mfi) * mfd) / n_ref;
186 dbg("%d: ref=%d, target=%d, pd=%d, mfi=%d,mfn=%d, mfd=%d\n",
187 __LINE__, ref, (u32)n_target, (u32)pd, (u32)mfi, (u32)mfn, (u32)mfd);
194 pll->mfn = (u32)(mfn / i);
195 pll->mfd = (u32)(mfd / i);
200 * This function returns the low power audio clock.
205 u32 ccsr = readl(CCM_BASE_ADDR + CLKCTL_CCSR);
207 if (((ccsr >> 9) & 1) == 0) {
208 ret_val = FREQ_24MHZ;
210 ret_val = FREQ_32768HZ;
212 dbg("%s: CCSR[%08lx]=%08x freq=%u.%03uMHz\n", __FUNCTION__,
213 CCM_BASE_ADDR + CLKCTL_CCSR, ccsr, ret_val / 1000000, ret_val / 1000 % 1000);
218 * This function returns the periph_clk.
220 u32 get_periph_clk(void)
222 u32 ret_val, clk_sel;
224 u32 cbcdr = readl(CCM_BASE_ADDR + CLKCTL_CBCDR);
225 u32 cbcmr = readl(CCM_BASE_ADDR + CLKCTL_CBCMR);
227 if (!(cbcdr & (1 << 25))) {
228 ret_val = pll_clock(PLL2);
229 dbg("%s: CBCDR[%08lx]=%08x CBCMR[%08lx]=%08x freq=%u.%03uMHz\n", __FUNCTION__,
230 CCM_BASE_ADDR + CLKCTL_CBCDR, cbcdr,
231 CCM_BASE_ADDR + CLKCTL_CBCMR, cbcmr,
232 ret_val / 1000000, ret_val / 1000 % 1000);
234 clk_sel = (cbcmr >> 12) & 3;
236 ret_val = pll_clock(PLL1);
237 } else if (clk_sel == 1) {
238 ret_val = pll_clock(PLL3);
239 } else if (clk_sel == 2) {
240 ret_val = get_lp_apm();
242 diag_printf("Invalid CBCMR[CLK_SEL]: %d\n", clk_sel);
243 return ERR_WRONG_CLK;
245 dbg("%s: CBCDR[%08lx]=%08x CBCMR[%08lx]=%08x clk_sel=%d freq=%u.%03uMHz\n", __FUNCTION__,
246 CCM_BASE_ADDR + CLKCTL_CBCDR, cbcdr,
247 CCM_BASE_ADDR + CLKCTL_CBCMR, cbcmr,
248 clk_sel, ret_val / 1000000, ret_val / 1000 % 1000);
254 * This function assumes the expected core clock has to be changed by
255 * modifying the PLL. This is NOT true always but for most of the times,
256 * it is. So it assumes the PLL output freq is the same as the expected
257 * core clock (presc=1) unless the core clock is less than PLL_FREQ_MIN.
258 * In the latter case, it will try to increase the presc value until
259 * (presc*core_clk) is greater than PLL_FREQ_MIN. It then makes call to
260 * calc_pll_params() and obtains the values of PD, MFI,MFN, MFD based
261 * on the targeted PLL and reference input clock to the PLL. Lastly,
262 * it sets the register based on these values along with the dividers.
263 * Note 1) There is no value checking for the passed-in divider values
264 * so the caller has to make sure those values are sensible.
265 * 2) Also adjust the NFC divider such that the NFC clock doesn't
266 * exceed NFC_CLK_MAX.
267 * 3) IPU HSP clock is independent of AHB clock. Even it can go up to
268 * 177MHz for higher voltage, this function fixes the max to 133MHz.
269 * 4) This function should not have allowed diag_printf() calls since
270 * the serial driver has been stoped. But leave then here to allow
271 * easy debugging by NOT calling the cyg_hal_plf_serial_stop().
273 * @param ref pll input reference clock (24MHz)
274 * @param core_clk core clock in Hz
275 * @param emi_clk emi clock in Hz
276 # @return 0 if successful; non-zero otherwise
278 int configure_clock(u32 ref, u32 core_clk, u32 emi_clk)
281 struct pll_param pll_param;
282 int ret, clk_sel, div = 1, div_core = 1, div_per = 1, shift = 0;
283 u32 cbcdr = readl(CCM_BASE_ADDR + CLKCTL_CBCDR);
284 u32 cbcmr = readl(CCM_BASE_ADDR + CLKCTL_CBCMR);
285 u32 ccsr = readl(CCM_BASE_ADDR + CLKCTL_CCSR);
286 u32 icgc = readl(PLATFORM_BASE_ADDR + PLATFORM_ICGC);
288 dbg("%s: cbcdr[%08lx]=%08x\n", __FUNCTION__,
289 CCM_BASE_ADDR + CLKCTL_CBCDR, cbcdr);
290 dbg("%s: cbcmr[%08lx]=%08x\n", __FUNCTION__,
291 CCM_BASE_ADDR + CLKCTL_CBCMR, cbcdr);
292 dbg("%s: ccsr[%08lx]=%08x\n", __FUNCTION__,
293 CCM_BASE_ADDR + CLKCTL_CCSR, cbcdr);
294 dbg("%s: icgc[%08lx]=%08x\n", __FUNCTION__,
295 PLATFORM_BASE_ADDR + PLATFORM_ICGC, icgc);
298 // assume pll default to core clock first
300 if ((ret = calc_pll_params(ref, pll, &pll_param)) != 0) {
301 diag_printf("can't find pll parameters: %d\n", ret);
305 dbg("%s: ref=%d, pll=%d, pd=%d, mfi=%d,mfn=%d, mfd=%d\n", __FUNCTION__,
306 ref, pll, pll_param.pd, pll_param.mfi, pll_param.mfn, pll_param.mfd);
308 /* Applies for TO 2 only */
309 if (((cbcdr >> 30) & 0x1) == 0x1) {
310 /* Disable IPU and HSC dividers */
311 writel(0x60000, CCM_BASE_ADDR + CLKCTL_CCDR);
312 /* Switch DDR to different source */
313 writel(cbcdr & ~0x40000000, CCM_BASE_ADDR + CLKCTL_CBCDR);
314 while (readl(CCM_BASE_ADDR + CLKCTL_CDHIPR) != 0);
315 writel(0x0, CCM_BASE_ADDR + CLKCTL_CCDR);
318 /* Switch ARM to PLL2 clock */
319 writel(ccsr | 0x4, CCM_BASE_ADDR + CLKCTL_CCSR);
321 if ((core_clk > 665000000) && (core_clk <= 800000000)) {
323 } else if (core_clk > 800000000) {
329 if (core_clk > 800000000) {
331 increase_core_voltage(true);
334 increase_core_voltage(false);
337 // adjust pll settings
338 writel(((pll_param.pd - 1) << 0) | (pll_param.mfi << 4),
339 PLL1_BASE_ADDR + PLL_DP_OP);
340 writel(pll_param.mfn, PLL1_BASE_ADDR + PLL_DP_MFN);
341 writel(pll_param.mfd - 1, PLL1_BASE_ADDR + PLL_DP_MFD);
342 writel(((pll_param.pd - 1) << 0) | (pll_param.mfi << 4),
343 PLL1_BASE_ADDR + PLL_DP_HFS_OP);
344 writel(pll_param.mfn, PLL1_BASE_ADDR + PLL_DP_HFS_MFN);
345 writel(pll_param.mfd - 1, PLL1_BASE_ADDR + PLL_DP_HFS_MFD);
348 icgc |= div_core << 4;
350 /* Set the platform clock dividers */
351 writel(icgc, PLATFORM_BASE_ADDR + PLATFORM_ICGC);
352 /* Switch ARM back to PLL1 */
353 writel((ccsr & ~0x4), CCM_BASE_ADDR + CLKCTL_CCSR);
354 /* Applies for TO 2 only */
355 if (((cbcdr >> 30) & 0x1) == 0x1) {
356 /* Disable IPU and HSC dividers */
357 writel(0x60000, CCM_BASE_ADDR + CLKCTL_CCDR);
358 /* Switch DDR back to PLL1 */
359 writel(cbcdr | 0x40000000, CCM_BASE_ADDR + CLKCTL_CBCDR);
360 while (readl(CCM_BASE_ADDR + CLKCTL_CDHIPR) != 0);
361 writel(0x0, CCM_BASE_ADDR + CLKCTL_CCDR);
363 /* Keep EMI clock to the max if not specified */
370 /* Applies for TO 2 only */
371 if (((cbcdr >> 30) & 0x1) == 0x1) {
372 clk_src = pll_clock(PLL1);
375 clk_src = get_periph_clk();
376 /* Find DDR clock input */
377 clk_sel = (cbcmr >> 10) & 0x3;
380 } else if (clk_sel == 1) {
382 } else if (clk_sel == 2) {
384 } else if (clk_sel == 3) {
388 if ((clk_src % emi_clk) == 0)
389 div = clk_src / emi_clk;
391 div = (clk_src / emi_clk) + 1;
395 cbcdr &= ~(0x7 << shift);
396 cbcdr |= (div - 1) << shift;
397 dbg("%s@%d: \n", __FUNCTION__, __LINE__);
399 /* Disable IPU and HSC dividers */
400 writel(0x60000, CCM_BASE_ADDR + CLKCTL_CCDR);
401 writel(cbcdr, CCM_BASE_ADDR + CLKCTL_CBCDR);
402 while (readl(CCM_BASE_ADDR + CLKCTL_CDHIPR) != 0);
403 writel(0x0, CCM_BASE_ADDR + CLKCTL_CCDR);
408 static void clock_setup(int argc,char *argv[])
410 u32 i, core_clk, ddr_clk, data[3];
417 for (i = 0; i < 2; i++) {
418 if (!parse_num(*(&argv[1]), &temp, &argv[1], ":")) {
419 diag_printf("Error: Invalid parameter\n");
425 core_clk = data[0] * SZ_DEC_1M;
426 ddr_clk = data[1] * SZ_DEC_1M;
429 if ((core_clk < PLL_FREQ_MIN(PLL_REF_CLK)) || (core_clk > PLL_FREQ_MAX(PLL_REF_CLK))) {
430 diag_printf("Targeted core clock should be within [%d - %d]\n",
431 PLL_FREQ_MIN(PLL_REF_CLK), PLL_FREQ_MAX(PLL_REF_CLK));
437 if (ddr_clk > MAX_DDR_CLK) {
438 diag_printf("DDR clock should be less than %d MHz, assuming max value\n", (MAX_DDR_CLK / SZ_DEC_1M));
439 ddr_clk = MAX_DDR_CLK;
444 // stop the serial to be ready to adjust the clock
445 hal_delay_us(100000);
446 cyg_hal_plf_serial_stop();
449 ret = configure_clock(PLL_REF_CLK, core_clk, ddr_clk);
450 // restart the serial driver
451 cyg_hal_plf_serial_init();
452 hal_delay_us(100000);
455 diag_printf("Failed to setup clock: %d\n", ret);
458 diag_printf("\n<<<New clock setting>>>\n");
460 // Now printing clocks
463 diag_printf("\nPLL1\t\tPLL2\t\tPLL3\n");
464 diag_printf("========================================\n");
465 diag_printf("%-16d%-16d%-16d\n\n", pll_clock(PLL1), pll_clock(PLL2),
467 diag_printf("CPU\t\tAHB\t\tIPG\t\tEMI_CLK\n");
468 diag_printf("========================================================\n");
469 diag_printf("%-16d%-16d%-16d%-16d\n\n",
470 get_main_clock(CPU_CLK),
471 get_main_clock(AHB_CLK),
472 get_main_clock(IPG_CLK),
473 get_main_clock(DDR_CLK));
475 diag_printf("NFC\t\tUSB\t\tIPG_PER_CLK\n");
476 diag_printf("========================================\n");
477 diag_printf("%-16d%-16d%-16d\n\n",
478 get_main_clock(NFC_CLK),
479 get_main_clock(USB_CLK),
480 get_main_clock(IPG_PER_CLK));
482 diag_printf("UART1-3\t\tSSI1\t\tSSI2\t\tSPI\n");
483 diag_printf("===========================================");
484 diag_printf("=============\n");
486 diag_printf("%-16d%-16d%-16d%-16d\n\n",
487 get_peri_clock(UART1_BAUD),
488 get_peri_clock(SSI1_BAUD),
489 get_peri_clock(SSI2_BAUD),
490 get_peri_clock(SPI1_CLK));
493 diag_printf("IPG_PERCLK as baud clock for: UART1-5, I2C, OWIRE, SDHC");
494 if (((readl(EPIT1_BASE_ADDR) >> 24) & 0x3) == 0x2) {
495 diag_printf(", EPIT");
497 if (((readl(GPT1_BASE_ADDR) >> 6) & 0x7) == 0x2) {
506 * This function returns the PLL output value in Hz based on pll.
508 u32 pll_clock(enum plls pll)
511 u32 mfi, mfn, mfd, pdf, pll_out, sign;
512 u32 dp_ctrl, dp_op, dp_mfd, dp_mfn;
516 dp_ctrl = pll_base[pll][PLL_DP_CTL >> 2];
517 clk_sel = MXC_GET_FIELD(dp_ctrl, 2, 8);
518 ref_clk = fixed_mfd[clk_sel].ref_clk_hz;
520 dbg("clk_sel=%d\n", clk_sel);
522 if ((pll_base[pll][PLL_DP_CTL >> 2] & 0x80) == 0) {
523 dp_op = pll_base[pll][PLL_DP_OP >> 2];
524 dp_mfd = pll_base[pll][PLL_DP_MFD >> 2];
525 dp_mfn = pll_base[pll][PLL_DP_MFN >> 2];
527 dp_op = pll_base[pll][PLL_DP_HFS_OP >> 2];
528 dp_mfd = pll_base[pll][PLL_DP_HFS_MFD >> 2];
529 dp_mfn = pll_base[pll][PLL_DP_HFS_MFN >> 2];
532 mfi = (dp_op >> 4) & 0xF;
533 mfi = (mfi <= 5) ? 5: mfi;
534 mfd = dp_mfd & 0x07FFFFFF;
535 mfn = dp_mfn & 0x07FFFFFF;
537 sign = (mfn < 0x4000000) ? 1 : -1;
538 mfn = (mfn < 0x4000000) ? mfn : (0x8000000 - mfn);
540 dbl = 2 * (((dp_ctrl >> 12) & 0x1) + 1);
542 dbg("%s: ref=%llu.%03lluMHz, dbl=%d, pd=%d, mfi=%d, mfn=%s%d, mfd=%d\n",
543 __FUNCTION__, ref_clk / 1000000, ref_clk / 1000 % 1000,
544 dbl, pdf, mfi, sign ? "-" : "", mfn, mfd);
546 pll_out = (dbl * ref_clk * mfi + ((dbl * ref_clk * sign * mfn) / (mfd + 1))) /
553 * This function returns the emi_core_clk_root clock.
555 u32 get_emi_core_clk(void)
557 u32 cbcdr = readl(CCM_BASE_ADDR + CLKCTL_CBCDR);
558 u32 clk_sel, max_pdf, peri_clk, ahb_clk;
561 max_pdf = (cbcdr >> 10) & 0x7;
562 peri_clk = get_periph_clk();
563 ahb_clk = peri_clk / (max_pdf + 1);
565 clk_sel = (cbcdr >> 26) & 1;
571 dbg("%s: CBCDR[%08lx]=%08x freq=%u.%03uMHz\n", __FUNCTION__,
572 CCM_BASE_ADDR + CLKCTL_CBCDR, cbcdr, ret_val / 1000000, ret_val / 1000 % 1000);
577 * This function returns the main clock value in Hz.
579 u32 get_main_clock(enum main_clocks clk)
581 u32 pdf, max_pdf, ipg_pdf, nfc_pdf, clk_sel;
583 u32 cacrr = readl(CCM_BASE_ADDR + CLKCTL_CACRR);
584 u32 cbcdr = readl(CCM_BASE_ADDR + CLKCTL_CBCDR);
585 u32 cbcmr = readl(CCM_BASE_ADDR + CLKCTL_CBCMR);
586 u32 cscmr1 = readl(CCM_BASE_ADDR + CLKCTL_CSCMR1);
587 u32 cscdr1 = readl(CCM_BASE_ADDR + CLKCTL_CSCDR1);
589 dbg("%s: \n", __FUNCTION__);
593 pll = pll_clock(PLL1);
594 ret_val = pll / (pdf + 1);
597 max_pdf = (cbcdr >> 10) & 0x7;
598 pll = get_periph_clk();
599 ret_val = pll / (max_pdf + 1);
602 max_pdf = (cbcdr >> 10) & 0x7;
603 ipg_pdf = (cbcdr >> 8) & 0x3;
604 pll = get_periph_clk();
605 ret_val = pll / ((max_pdf + 1) * (ipg_pdf + 1));
610 clk_sel = (cbcmr >> 1) & 1;
611 pdf = (((cbcdr >> 6) & 3) + 1) * (((cbcdr >> 3) & 7) + 1) * ((cbcdr & 7) + 1);
613 ret_val = get_periph_clk() / pdf;
615 ret_val = get_lp_apm();
618 /* Same as IPG_CLK */
619 max_pdf = (cbcdr >> 10) & 0x7;
620 ipg_pdf = (cbcdr >> 8) & 0x3;
621 pll = get_periph_clk();
622 ret_val = pll / ((max_pdf + 1) * (ipg_pdf + 1));
626 if (cbcdr & (1 << 30)) {
627 pll = pll_clock(PLL1);
628 pdf = (cbcdr >> 27) & 0x7;
630 clk_sel = (cbcmr >> 10) & 3;
631 pll = get_periph_clk();
634 pdf = (cbcdr >> 16) & 0x7;
635 } else if (clk_sel == 1) {
637 pdf = (cbcdr >> 19) & 0x7;
638 } else if (clk_sel == 2) {
639 /* EMI SLOW CLOCK ROOT */
640 pll = get_emi_core_clk();
641 pdf = (cbcdr >> 22) & 0x7;
642 } else if (clk_sel == 3) {
644 pdf = (cbcdr >> 10) & 0x7;
648 ret_val = pll / (pdf + 1);
651 pdf = (cbcdr >> 22) & 0x7;
652 nfc_pdf = (cbcdr >> 13) & 0x7;
653 pll = get_emi_core_clk();
654 ret_val = pll / ((pdf + 1) * (nfc_pdf + 1));
657 clk_sel = (cscmr1 >> 22) & 3;
659 pll = pll_clock(PLL1);
660 } else if (clk_sel == 1) {
661 pll = pll_clock(PLL2);
662 } else if (clk_sel == 2) {
663 pll = pll_clock(PLL3);
664 } else if (clk_sel == 3) {
667 pdf = (cscdr1 >> 8) & 0x7;
668 max_pdf = (cscdr1 >> 6) & 0x3;
669 ret_val = pll / ((pdf + 1) * (max_pdf + 1));
672 diag_printf("Unknown clock: %d\n", clk);
673 return ERR_WRONG_CLK;
680 * This function returns the peripheral clock value in Hz.
682 u32 get_peri_clock(enum peri_clocks clk)
684 u32 ret_val = 0, pdf, pre_pdf, clk_sel;
685 u32 cscmr1 = readl(CCM_BASE_ADDR + CLKCTL_CSCMR1);
686 u32 cscdr1 = readl(CCM_BASE_ADDR + CLKCTL_CSCDR1);
687 u32 cscdr2 = readl(CCM_BASE_ADDR + CLKCTL_CSCDR2);
688 u32 cs1cdr = readl(CCM_BASE_ADDR + CLKCTL_CS1CDR);
689 u32 cs2cdr = readl(CCM_BASE_ADDR + CLKCTL_CS2CDR);
691 dbg("%s: \n", __FUNCTION__);
696 pre_pdf = (cscdr1 >> 3) & 0x7;
698 clk_sel = (cscmr1 >> 24) & 3;
700 ret_val = pll_clock(PLL1) / ((pre_pdf + 1) * (pdf + 1));
701 } else if (clk_sel == 1) {
702 ret_val = pll_clock(PLL2) / ((pre_pdf + 1) * (pdf + 1));
703 } else if (clk_sel == 2) {
704 ret_val = pll_clock(PLL3) / ((pre_pdf + 1) * (pdf + 1));
706 ret_val = get_lp_apm() / ((pre_pdf + 1) * (pdf + 1));
710 pre_pdf = (cs1cdr >> 6) & 0x7;
712 clk_sel = (cscmr1 >> 14) & 3;
714 ret_val = pll_clock(PLL1) / ((pre_pdf + 1) * (pdf + 1));
715 } else if (clk_sel == 0x1) {
716 ret_val = pll_clock(PLL2) / ((pre_pdf + 1) * (pdf + 1));
717 } else if (clk_sel == 0x2) {
718 ret_val = pll_clock(PLL3) / ((pre_pdf + 1) * (pdf + 1));
720 ret_val = CKIH /((pre_pdf + 1) * (pdf + 1));
724 pre_pdf = (cs2cdr >> 6) & 0x7;
726 clk_sel = (cscmr1 >> 12) & 3;
728 ret_val = pll_clock(PLL1) / ((pre_pdf + 1) * (pdf + 1));
729 } else if (clk_sel == 0x1) {
730 ret_val = pll_clock(PLL2) / ((pre_pdf + 1) * (pdf + 1));
731 } else if (clk_sel == 0x2) {
732 ret_val = pll_clock(PLL3) / ((pre_pdf + 1) * (pdf + 1));
734 ret_val = CKIH /((pre_pdf + 1) * (pdf + 1));
739 pre_pdf = (cscdr2 >> 25) & 0x7;
740 pdf = (cscdr2 >> 19) & 0x3F;
741 clk_sel = (cscmr1 >> 4) & 3;
743 ret_val = pll_clock(PLL1) / ((pre_pdf + 1) * (pdf + 1));
744 } else if (clk_sel == 1) {
745 ret_val = pll_clock(PLL2) / ((pre_pdf + 1) * (pdf + 1));
746 } else if (clk_sel == 2) {
747 ret_val = pll_clock(PLL3) / ((pre_pdf + 1) * (pdf + 1));
749 ret_val = get_lp_apm() / ((pre_pdf + 1) * (pdf + 1));
753 diag_printf("%s(): This clock: %d not supported yet\n",
762 * This command is added for some simple testing only. It turns on/off
763 * L2 cache regardless of L1 cache state. The side effect of this is
764 * when doing any flash operations such as "fis init", the L2
765 * will be turned back on along with L1 caches even though it is off
766 * by using this command.
774 void do_L2_caches(int argc, char *argv[])
779 if (strcasecmp(argv[1], "on") == 0) {
780 HAL_DISABLE_INTERRUPTS(oldints);
782 HAL_RESTORE_INTERRUPTS(oldints);
783 } else if (strcasecmp(argv[1], "off") == 0) {
784 HAL_DISABLE_INTERRUPTS(oldints);
785 HAL_DCACHE_DISABLE_L1();
786 HAL_CACHE_FLUSH_ALL();
788 HAL_DCACHE_ENABLE_L1();
789 HAL_RESTORE_INTERRUPTS(oldints);
791 diag_printf("Invalid L2 cache mode: %s\n", argv[1]);
796 HAL_L2CACHE_IS_ENABLED(L2cache_on);
797 diag_printf("L2 cache: %s\n", L2cache_on ? "On" : "Off");
800 #endif //L2CC_ENABLED
802 #define IIM_ERR_SHIFT 8
803 #define POLL_FUSE_PRGD (IIM_STAT_PRGD | (IIM_ERR_PRGE << IIM_ERR_SHIFT))
804 #define POLL_FUSE_SNSD (IIM_STAT_SNSD | (IIM_ERR_SNSE << IIM_ERR_SHIFT))
806 static void fuse_op_start(void)
808 /* Do not generate interrupt */
809 writel(0, IIM_BASE_ADDR + IIM_STATM_OFF);
810 // clear the status bits and error bits
811 writel(0x3, IIM_BASE_ADDR + IIM_STAT_OFF);
812 writel(0xFE, IIM_BASE_ADDR + IIM_ERR_OFF);
816 * The action should be either:
821 static int poll_fuse_op_done(int action)
825 if (action != POLL_FUSE_PRGD && action != POLL_FUSE_SNSD) {
826 diag_printf("%s(%d) invalid operation\n", __FUNCTION__, action);
830 /* Poll busy bit till it is NOT set */
831 while ((readl(IIM_BASE_ADDR + IIM_STAT_OFF) & IIM_STAT_BUSY) != 0 ) {
834 /* Test for successful write */
835 status = readl(IIM_BASE_ADDR + IIM_STAT_OFF);
836 error = readl(IIM_BASE_ADDR + IIM_ERR_OFF);
838 if ((status & action) != 0 && (error & (action >> IIM_ERR_SHIFT)) == 0) {
840 diag_printf("Even though the operation seems successful...\n");
841 diag_printf("There are some error(s) at addr=0x%08lx: 0x%08x\n",
842 (IIM_BASE_ADDR + IIM_ERR_OFF), error);
846 diag_printf("%s(%d) failed\n", __FUNCTION__, action);
847 diag_printf("status address=0x%08lx, value=0x%08x\n",
848 (IIM_BASE_ADDR + IIM_STAT_OFF), status);
849 diag_printf("There are some error(s) at addr=0x%08lx: 0x%08x\n",
850 (IIM_BASE_ADDR + IIM_ERR_OFF), error);
854 unsigned int sense_fuse(int bank, int row, int bit)
856 int addr, addr_l, addr_h, reg_addr;
860 addr = ((bank << 11) | (row << 3) | (bit & 0x7));
861 /* Set IIM Program Upper Address */
862 addr_h = (addr >> 8) & 0x000000FF;
863 /* Set IIM Program Lower Address */
864 addr_l = (addr & 0x000000FF);
866 #ifdef IIM_FUSE_DEBUG
867 diag_printf("%s: addr_h=0x%02x, addr_l=0x%02x\n",
868 __FUNCTION__, addr_h, addr_l);
870 writel(addr_h, IIM_BASE_ADDR + IIM_UA_OFF);
871 writel(addr_l, IIM_BASE_ADDR + IIM_LA_OFF);
873 writel(0x8, IIM_BASE_ADDR + IIM_FCTL_OFF);
874 if (poll_fuse_op_done(POLL_FUSE_SNSD) != 0) {
875 diag_printf("%s(bank: %d, row: %d, bit: %d failed\n",
876 __FUNCTION__, bank, row, bit);
878 reg_addr = IIM_BASE_ADDR + IIM_SDAT_OFF;
879 diag_printf("fuses at (bank:%d, row:%d) = 0x%08x\n", bank, row, readl(reg_addr));
880 return readl(reg_addr);
883 void do_fuse_read(int argc, char *argv[])
885 unsigned long bank, row;
886 unsigned long fuse_val;
889 diag_printf("Usage: fuse_read <bank> <row>\n");
891 } else if (argc == 3) {
892 if (!parse_num(*(&argv[1]), &bank, &argv[1], " ")) {
893 diag_printf("Error: Invalid parameter\n");
896 if (!parse_num(*(&argv[2]), &row, &argv[2], " ")) {
897 diag_printf("Error: Invalid parameter\n");
901 diag_printf("Read fuse at bank:%ld row:%ld\n", bank, row);
902 fuse_val = sense_fuse(bank, row, 0);
903 diag_printf("fuses at (bank:%ld, row:%ld) = 0x%lx\n", bank, row, fuse_val);
905 diag_printf("Passing in wrong arguments: %d\n", argc);
906 diag_printf("Usage: fuse_read <bank> <row>\n");
910 /* Blow fuses based on the bank, row and bit positions (all 0-based)
912 static int fuse_blow(int bank, int row, int bit)
914 int addr, addr_l, addr_h, ret = -1;
918 /* Disable IIM Program Protect */
919 writel(0xAA, IIM_BASE_ADDR + IIM_PREG_P_OFF);
921 addr = ((bank << 11) | (row << 3) | (bit & 0x7));
922 /* Set IIM Program Upper Address */
923 addr_h = (addr >> 8) & 0x000000FF;
924 /* Set IIM Program Lower Address */
925 addr_l = (addr & 0x000000FF);
927 #ifdef IIM_FUSE_DEBUG
928 diag_printf("blowing fuse %d %d bit %d addr_h=0x%02x, addr_l=0x%02x\n",
929 bank, row, bit, addr_h, addr_l);
932 writel(addr_h, IIM_BASE_ADDR + IIM_UA_OFF);
933 writel(addr_l, IIM_BASE_ADDR + IIM_LA_OFF);
934 /* Start Programming */
935 writel(0x71, IIM_BASE_ADDR + IIM_FCTL_OFF);
936 if (poll_fuse_op_done(POLL_FUSE_PRGD) == 0) {
940 /* Enable IIM Program Protect */
941 writel(0x0, IIM_BASE_ADDR + IIM_PREG_P_OFF);
946 * This command is added for burning IIM fuses
948 RedBoot_cmd("fuse_read",
954 RedBoot_cmd("fuse_blow",
956 "<bank> <row> <value>",
960 void quick_itoa(u32 num, char *a)
963 for (i = 0; i <= 7; i++) {
964 j = (num >> (4 * i)) & 0xF;
965 k = (j < 10) ? '0' : ('a' - 0xa);
970 // slen - streng length, e.g.: 23 -> slen=2; abcd -> slen=4
971 // only convert hex value as string input. so "12" is 0x12.
972 u32 quick_atoi(char *a, u32 slen)
974 u32 i, num = 0, digit;
976 for (i = 0; i < slen; i++) {
977 if (a[i] >= '0' && a[i] <= '9') {
979 } else if (a[i] >= 'a' && a[i] <= 'f') {
980 digit = a[i] - 'a' + 10;
981 } else if (a[i] >= 'A' && a[i] <= 'F') {
982 digit = a[i] - 'A' + 10;
984 diag_printf("ERROR: %c\n", a[i]);
987 num = (num * 16) + digit;
992 void fuse_blow_row(int bank, int row, int value)
997 reg = readl(CCM_BASE_ADDR + 0x64);
999 writel(reg, CCM_BASE_ADDR + 0x64);
1001 for (i = 0; i < 8; i++) {
1002 if (((value >> i) & 0x1) == 0) {
1005 if (fuse_blow(bank, row, i) != 0) {
1006 diag_printf("fuse_blow(bank: %d, row: %d, bit: %d failed\n",
1011 writel(reg, CCM_BASE_ADDR + 0x64);
1014 void do_fuse_blow(int argc, char *argv[])
1016 unsigned long bank, row, value, i;
1017 unsigned int fuse_val;
1022 diag_printf("It is too dangeous for you to use this command.\n");
1027 if (strcasecmp(argv[1], "scc") == 0) {
1028 // fuse_blow scc C3D153EDFD2EA9982226EF5047D3B9A0B9C7138EA87C028401D28C2C2C0B9AA2
1029 diag_printf("Ready to burn SCC fuses\n");
1034 value = quick_atoi(val, 2);
1035 // diag_printf("fuse_blow_row(2, %d, value=0x%02x)\n", i, value);
1036 fuse_blow_row(2, i, value);
1038 if ((++s)[0] == '\0') {
1039 diag_printf("ERROR: Odd string input\n");
1042 if ((++s)[0] == '\0') {
1043 diag_printf("Successful\n");
1047 } else if (strcasecmp(argv[1], "srk") == 0) {
1048 // fuse_blow srk 418bccd09b53bee1ab59e2662b3c7877bc0094caee201052add49be8780dff95
1049 diag_printf("Ready to burn SRK key fuses\n");
1054 value = quick_atoi(val, 2);
1056 fuse_blow_row(1, 1, value); // 0x41 goes to SRK_HASH[255:248], bank 1, row 1
1058 fuse_blow_row(3, i, value); // 0x8b in SRK_HASH[247:240] bank 3, row 1
1059 // 0xcc in SRK_HASH[239:232] bank 3, row 2
1061 if ((++s)[0] == '\0') {
1062 diag_printf("ERROR: Odd string input\n");
1065 if ((++s)[0] == '\0') {
1066 diag_printf("Successful\n");
1071 diag_printf("This command is not supported\n");
1074 } else if (argc == 4) {
1075 if (!parse_num(*(&argv[1]), (unsigned long *)&bank, &argv[1], " ")) {
1076 diag_printf("Error: Invalid parameter\n");
1079 if (!parse_num(*(&argv[2]), &row, &argv[2], " ")) {
1080 diag_printf("Error: Invalid parameter\n");
1083 if (!parse_num(*(&argv[3]), &value, &argv[3], " ")) {
1084 diag_printf("Error: Invalid parameter\n");
1088 diag_printf("Blowing fuse at bank:%ld row:%ld value:%ld\n",
1090 fuse_blow_row(bank, row, value);
1091 fuse_val = sense_fuse(bank, row, 0);
1092 diag_printf("fuses at (bank:%ld, row:%ld) = 0x%02x\n", bank, row, fuse_val);
1095 diag_printf("Passing in wrong arguments: %d\n", argc);
1099 /* precondition: m>0 and n>0. Let g=gcd(m,n). */
1100 int gcd(int m, int n)
1104 if(n > m) {t = m; m = n; n = t;} /* swap */
1110 int read_mac_addr_from_fuse(unsigned char* data)
1112 data[0] = sense_fuse(1, 9, 0) ;
1113 data[1] = sense_fuse(1, 10, 0) ;
1114 data[2] = sense_fuse(1, 11, 0) ;
1115 data[3] = sense_fuse(1, 12, 0) ;
1116 data[4] = sense_fuse(1, 13, 0) ;
1117 data[5] = sense_fuse(1, 14, 0) ;
1119 if ((data[0] == 0) && (data[1] == 0) && (data[2] == 0) &&
1120 (data[3] == 0) && (data[4] == 0) && (data[5] == 0)) {
1128 void imx_power_mode(int mode)
1130 volatile unsigned int val;
1133 writel(0x0000030f, GPC_PGR);
1134 writel(0x1, SRPGCR_EMI);
1135 writel(0x1, SRPGCR_ARM);
1136 writel(0x1, PGC_PGCR_VPU);
1137 writel(0x1, PGC_PGCR_IPU);
1141 // stop mode - from validation code
1142 // Set DSM_INT_HOLDOFF bit in TZIC
1143 // If the TZIC didn't write the bit then there was interrupt pending
1144 // It will be serviced while we're in the loop
1145 // So we write to this bit again
1146 while (readl(INTC_BASE_ADDR + 0x14) == 0) {
1147 writel(1, INTC_BASE_ADDR + 0x14);
1157 diag_printf("Entering stop mode\n");
1158 val = readl(CCM_BASE_ADDR + 0x74);
1159 val = (val & 0xfffffffc) | 0x2; // set STOP mode
1160 writel(val, CCM_BASE_ADDR + 0x74);
1161 val = readl(PLATFORM_LPC_REG);
1162 writel(val | (1 << 16), PLATFORM_LPC_REG);// ENABLE DSM in ELBOW submodule of ARM platform
1163 writel(val | (1 << 17), PLATFORM_LPC_REG);// ENABLE DSM in ELBOW submodule of ARM platform
1170 asm("mcr p15, 0, r1, c7, c0, 4");
1173 void do_power_mode(int argc, char *argv[])
1178 diag_printf("Usage: power_mode <mode>\n");
1180 } else if (argc == 2) {
1181 if (!parse_num(*(&argv[1]), (unsigned long *)&mode, &argv[1], " ")) {
1182 diag_printf("Error: Invalid parameter\n");
1185 diag_printf("Entering power mode: %d\n", mode);
1186 imx_power_mode(mode);
1189 diag_printf("Passing in wrong arguments: %d\n", argc);
1190 diag_printf("Usage: power_mode <mode>\n");
1195 * This command is added for burning IIM fuses
1197 RedBoot_cmd("power_mode",
1198 "Enter various power modes:",
1203 " <3> - STOP with Power-Gating\n"
1204 " -- need reset after issuing the command",
1209 /* Super Root key moduli */
1210 static const UINT8 hab_super_root_moduli[] = {
1212 0xb9, 0x84, 0xc8, 0x8a, 0xd3, 0x7e, 0xcc, 0xc0, 0xe7, 0x3e, 0x11, 0x53,
1213 0x6b, 0x5e, 0xea, 0xf4, 0xd9, 0xac, 0x5a, 0x63, 0x8a, 0x79, 0x96, 0x83,
1214 0xb1, 0x39, 0xb2, 0x6f, 0x9c, 0x54, 0x87, 0xf4, 0x3b, 0x9e, 0xd8, 0x0f,
1215 0x89, 0xf5, 0x01, 0x53, 0xb8, 0xe2, 0xcc, 0x75, 0x0d, 0xe1, 0x13, 0xfa,
1216 0xa7, 0xb9, 0x1e, 0xff, 0x6a, 0x05, 0xdb, 0x58, 0x10, 0xbf, 0x2b, 0xf4,
1217 0xe7, 0x0a, 0x63, 0x82, 0x2c, 0xa3, 0xb5, 0x0a, 0x72, 0x1c, 0xdc, 0x29,
1218 0xc1, 0x81, 0xb5, 0x9a, 0xf0, 0x25, 0x7d, 0xd6, 0xee, 0x01, 0x64, 0xc7,
1219 0x07, 0x2d, 0xcb, 0x31, 0x4c, 0x8d, 0x82, 0xf6, 0x44, 0x95, 0x4a, 0xbc,
1220 0xae, 0xe8, 0x2a, 0x89, 0xd4, 0xf2, 0x66, 0x72, 0x2b, 0x09, 0x4e, 0x56,
1221 0xe9, 0xbf, 0x5e, 0x38, 0x5c, 0xd5, 0x7e, 0x15, 0x55, 0x86, 0x0f, 0x19,
1222 0xf6, 0x00, 0xee, 0xa1, 0x92, 0x78, 0xef, 0x93, 0xcb, 0xfa, 0xb4, 0x98,
1223 0x19, 0xef, 0x10, 0x70, 0xde, 0x36, 0x1c, 0x12, 0x2e, 0xd2, 0x09, 0xc7,
1224 0x7b, 0xd1, 0xaa, 0xd3, 0x46, 0x65, 0xa1, 0x5b, 0xee, 0xa5, 0x96, 0x97,
1225 0x98, 0x3e, 0xfc, 0xf8, 0x74, 0x22, 0x51, 0xe7, 0xf1, 0x2f, 0x30, 0x79,
1226 0x13, 0xe5, 0x42, 0xc6, 0x7c, 0x18, 0x76, 0xd3, 0x7f, 0x5a, 0x13, 0xde,
1227 0x2f, 0x51, 0x07, 0xfa, 0x93, 0xfe, 0x10, 0x8a, 0x0c, 0x18, 0x60, 0x3c,
1228 0xff, 0x6a, 0x9b, 0xe7, 0x10, 0x2d, 0x71, 0xd2, 0x34, 0xc0, 0xdf, 0xbe,
1229 0x17, 0x4e, 0x75, 0x40, 0x83, 0xaa, 0x90, 0xd1, 0xed, 0xbd, 0xbf, 0xac,
1230 0x9a, 0x30, 0xbd, 0x69, 0x4d, 0xd8, 0x00, 0x63, 0x92, 0x69, 0x98, 0xf8,
1231 0x89, 0xdc, 0x7b, 0xe3, 0x66, 0x7e, 0xdd, 0xfa, 0x8c, 0x74, 0xe2, 0xb1,
1232 0xeb, 0x94, 0xf7, 0xab, 0x0e, 0x92, 0x06, 0xab, 0x60, 0xe5, 0x00, 0x43,
1233 0xb2, 0x5e, 0x6e, 0xeb
1236 /* Super Root key */
1237 const hab_rsa_public_key hab_super_root_key[] = {
1240 /* RSA public exponent, right-padded */
1241 0x01, 0x00, 0x01, 0x00,
1243 /* pointer to modulus data */
1244 hab_super_root_moduli,
1245 /* Exponent size in bytes */
1247 /* Modulus size in bytes */
1249 /* Key data valid */