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("AXI_A\t\tAXI_B\t\tEMI_SLOW_CLK\n");
468 diag_printf("========================================================\n");
469 diag_printf("%-16d%-16d%-16d\n\n",
470 get_main_clock(AXI_A_CLK),
471 get_main_clock(AXI_B_CLK),
472 get_main_clock(EMI_SLOW_CLK));
473 diag_printf("CPU\t\tAHB\t\tIPG\t\tDDR_CLK\n");
474 diag_printf("========================================================\n");
475 diag_printf("%-16d%-16d%-16d%-16d\n\n",
476 get_main_clock(CPU_CLK),
477 get_main_clock(AHB_CLK),
478 get_main_clock(IPG_CLK),
479 get_main_clock(DDR_CLK));
481 diag_printf("NFC\t\tUSB\t\tIPG_PER_CLK\n");
482 diag_printf("========================================\n");
483 diag_printf("%-16d%-16d%-16d\n\n",
484 get_main_clock(NFC_CLK),
485 get_main_clock(USB_CLK),
486 get_main_clock(IPG_PER_CLK));
488 diag_printf("UART1-3\t\tSSI1\t\tSSI2\t\tSPI\n");
489 diag_printf("===========================================");
490 diag_printf("=============\n");
492 diag_printf("%-16d%-16d%-16d%-16d\n\n",
493 get_peri_clock(UART1_BAUD),
494 get_peri_clock(SSI1_BAUD),
495 get_peri_clock(SSI2_BAUD),
496 get_peri_clock(SPI1_CLK));
499 diag_printf("IPG_PERCLK as baud clock for: UART1-5, I2C, OWIRE, SDHC");
500 if (((readl(EPIT1_BASE_ADDR) >> 24) & 0x3) == 0x2) {
501 diag_printf(", EPIT");
503 if (((readl(GPT1_BASE_ADDR) >> 6) & 0x7) == 0x2) {
512 * This function returns the PLL output value in Hz based on pll.
514 u32 pll_clock(enum plls pll)
517 u32 mfi, mfn, mfd, pdf, pll_out, sign;
518 u32 dp_ctrl, dp_op, dp_mfd, dp_mfn;
522 dp_ctrl = pll_base[pll][PLL_DP_CTL >> 2];
523 clk_sel = MXC_GET_FIELD(dp_ctrl, 2, 8);
524 ref_clk = fixed_mfd[clk_sel].ref_clk_hz;
526 dbg("clk_sel=%d\n", clk_sel);
528 if ((pll_base[pll][PLL_DP_CTL >> 2] & 0x80) == 0) {
529 dp_op = pll_base[pll][PLL_DP_OP >> 2];
530 dp_mfd = pll_base[pll][PLL_DP_MFD >> 2];
531 dp_mfn = pll_base[pll][PLL_DP_MFN >> 2];
533 dp_op = pll_base[pll][PLL_DP_HFS_OP >> 2];
534 dp_mfd = pll_base[pll][PLL_DP_HFS_MFD >> 2];
535 dp_mfn = pll_base[pll][PLL_DP_HFS_MFN >> 2];
538 mfi = (dp_op >> 4) & 0xF;
539 mfi = (mfi <= 5) ? 5: mfi;
540 mfd = dp_mfd & 0x07FFFFFF;
541 mfn = dp_mfn & 0x07FFFFFF;
543 sign = (mfn < 0x4000000) ? 1 : -1;
544 mfn = (mfn < 0x4000000) ? mfn : (0x8000000 - mfn);
546 dbl = 2 * (((dp_ctrl >> 12) & 0x1) + 1);
548 dbg("%s: ref=%llu.%03lluMHz, dbl=%d, pd=%d, mfi=%d, mfn=%s%d, mfd=%d\n",
549 __FUNCTION__, ref_clk / 1000000, ref_clk / 1000 % 1000,
550 dbl, pdf, mfi, sign ? "-" : "", mfn, mfd);
552 pll_out = (dbl * ref_clk * mfi + ((dbl * ref_clk * sign * mfn) / (mfd + 1))) /
559 * This function returns the emi_core_clk_root clock.
561 u32 get_emi_core_clk(void)
563 u32 cbcdr = readl(CCM_BASE_ADDR + CLKCTL_CBCDR);
564 u32 clk_sel, max_pdf, peri_clk, ahb_clk;
567 max_pdf = (cbcdr >> 10) & 0x7;
568 peri_clk = get_periph_clk();
569 ahb_clk = peri_clk / (max_pdf + 1);
571 clk_sel = (cbcdr >> 26) & 1;
577 dbg("%s: CBCDR[%08lx]=%08x freq=%u.%03uMHz\n", __FUNCTION__,
578 CCM_BASE_ADDR + CLKCTL_CBCDR, cbcdr, ret_val / 1000000, ret_val / 1000 % 1000);
583 * This function returns the main clock value in Hz.
585 u32 get_main_clock(enum main_clocks clk)
587 u32 pdf, max_pdf, ipg_pdf, nfc_pdf, clk_sel;
589 u32 cacrr = readl(CCM_BASE_ADDR + CLKCTL_CACRR);
590 u32 cbcdr = readl(CCM_BASE_ADDR + CLKCTL_CBCDR);
591 u32 cbcmr = readl(CCM_BASE_ADDR + CLKCTL_CBCMR);
592 u32 cscmr1 = readl(CCM_BASE_ADDR + CLKCTL_CSCMR1);
593 u32 cscdr1 = readl(CCM_BASE_ADDR + CLKCTL_CSCDR1);
595 dbg("%s: \n", __FUNCTION__);
599 pll = pll_clock(PLL1);
600 ret_val = pll / (pdf + 1);
604 max_pdf = (cbcdr >> 10) & 0x7;
605 pll = get_periph_clk();
606 ret_val = pll / (max_pdf + 1);
610 pdf = (cbcdr >> 16) & 0x7;
611 pll = get_periph_clk();
612 ret_val = pll / (pdf + 1);
616 pdf = (cbcdr >> 19) & 0x7;
617 pll = get_periph_clk();
618 ret_val = pll / (pdf + 1);
622 pll = get_emi_core_clk();
623 pdf = (cbcdr >> 22) & 0x7;
624 ret_val = pll / (pdf + 1);
628 max_pdf = (cbcdr >> 10) & 0x7;
629 ipg_pdf = (cbcdr >> 8) & 0x3;
630 pll = get_periph_clk();
631 ret_val = pll / ((max_pdf + 1) * (ipg_pdf + 1));
637 clk_sel = (cbcmr >> 1) & 1;
638 pdf = (((cbcdr >> 6) & 3) + 1) * (((cbcdr >> 3) & 7) + 1) * ((cbcdr & 7) + 1);
640 ret_val = get_periph_clk() / pdf;
642 ret_val = get_lp_apm();
645 /* Same as IPG_CLK */
646 max_pdf = (cbcdr >> 10) & 0x7;
647 ipg_pdf = (cbcdr >> 8) & 0x3;
648 pll = get_periph_clk();
649 ret_val = pll / ((max_pdf + 1) * (ipg_pdf + 1));
654 if (cbcdr & (1 << 30)) {
655 pll = pll_clock(PLL1);
656 pdf = (cbcdr >> 27) & 0x7;
658 clk_sel = (cbcmr >> 10) & 3;
659 pll = get_periph_clk();
662 pdf = (cbcdr >> 16) & 0x7;
663 } else if (clk_sel == 1) {
665 pdf = (cbcdr >> 19) & 0x7;
666 } else if (clk_sel == 2) {
667 /* EMI SLOW CLOCK ROOT */
668 pll = get_emi_core_clk();
669 pdf = (cbcdr >> 22) & 0x7;
670 } else if (clk_sel == 3) {
672 pdf = (cbcdr >> 10) & 0x7;
676 ret_val = pll / (pdf + 1);
680 pdf = (cbcdr >> 22) & 0x7;
681 nfc_pdf = (cbcdr >> 13) & 0x7;
682 pll = get_emi_core_clk();
683 ret_val = pll / ((pdf + 1) * (nfc_pdf + 1));
687 clk_sel = (cscmr1 >> 22) & 3;
689 pll = pll_clock(PLL1);
690 } else if (clk_sel == 1) {
691 pll = pll_clock(PLL2);
692 } else if (clk_sel == 2) {
693 pll = pll_clock(PLL3);
694 } else if (clk_sel == 3) {
697 pdf = (cscdr1 >> 8) & 0x7;
698 max_pdf = (cscdr1 >> 6) & 0x3;
699 ret_val = pll / ((pdf + 1) * (max_pdf + 1));
703 diag_printf("Unknown clock: %d\n", clk);
704 return ERR_WRONG_CLK;
711 * This function returns the peripheral clock value in Hz.
713 u32 get_peri_clock(enum peri_clocks clk)
715 u32 ret_val = 0, pdf, pre_pdf, clk_sel;
716 u32 cscmr1 = readl(CCM_BASE_ADDR + CLKCTL_CSCMR1);
717 u32 cscdr1 = readl(CCM_BASE_ADDR + CLKCTL_CSCDR1);
718 u32 cscdr2 = readl(CCM_BASE_ADDR + CLKCTL_CSCDR2);
719 u32 cs1cdr = readl(CCM_BASE_ADDR + CLKCTL_CS1CDR);
720 u32 cs2cdr = readl(CCM_BASE_ADDR + CLKCTL_CS2CDR);
722 dbg("%s: \n", __FUNCTION__);
727 pre_pdf = (cscdr1 >> 3) & 0x7;
729 clk_sel = (cscmr1 >> 24) & 3;
731 ret_val = pll_clock(PLL1) / ((pre_pdf + 1) * (pdf + 1));
732 } else if (clk_sel == 1) {
733 ret_val = pll_clock(PLL2) / ((pre_pdf + 1) * (pdf + 1));
734 } else if (clk_sel == 2) {
735 ret_val = pll_clock(PLL3) / ((pre_pdf + 1) * (pdf + 1));
737 ret_val = get_lp_apm() / ((pre_pdf + 1) * (pdf + 1));
741 pre_pdf = (cs1cdr >> 6) & 0x7;
743 clk_sel = (cscmr1 >> 14) & 3;
745 ret_val = pll_clock(PLL1) / ((pre_pdf + 1) * (pdf + 1));
746 } else if (clk_sel == 0x1) {
747 ret_val = pll_clock(PLL2) / ((pre_pdf + 1) * (pdf + 1));
748 } else if (clk_sel == 0x2) {
749 ret_val = pll_clock(PLL3) / ((pre_pdf + 1) * (pdf + 1));
751 ret_val = CKIH /((pre_pdf + 1) * (pdf + 1));
755 pre_pdf = (cs2cdr >> 6) & 0x7;
757 clk_sel = (cscmr1 >> 12) & 3;
759 ret_val = pll_clock(PLL1) / ((pre_pdf + 1) * (pdf + 1));
760 } else if (clk_sel == 0x1) {
761 ret_val = pll_clock(PLL2) / ((pre_pdf + 1) * (pdf + 1));
762 } else if (clk_sel == 0x2) {
763 ret_val = pll_clock(PLL3) / ((pre_pdf + 1) * (pdf + 1));
765 ret_val = CKIH /((pre_pdf + 1) * (pdf + 1));
770 pre_pdf = (cscdr2 >> 25) & 0x7;
771 pdf = (cscdr2 >> 19) & 0x3F;
772 clk_sel = (cscmr1 >> 4) & 3;
774 ret_val = pll_clock(PLL1) / ((pre_pdf + 1) * (pdf + 1));
775 } else if (clk_sel == 1) {
776 ret_val = pll_clock(PLL2) / ((pre_pdf + 1) * (pdf + 1));
777 } else if (clk_sel == 2) {
778 ret_val = pll_clock(PLL3) / ((pre_pdf + 1) * (pdf + 1));
780 ret_val = get_lp_apm() / ((pre_pdf + 1) * (pdf + 1));
784 diag_printf("%s(): This clock: %d not supported yet\n",
793 * This command is added for some simple testing only. It turns on/off
794 * L2 cache regardless of L1 cache state. The side effect of this is
795 * when doing any flash operations such as "fis init", the L2
796 * will be turned back on along with L1 caches even though it is off
797 * by using this command.
805 void do_L2_caches(int argc, char *argv[])
810 if (strcasecmp(argv[1], "on") == 0) {
811 HAL_DISABLE_INTERRUPTS(oldints);
813 HAL_RESTORE_INTERRUPTS(oldints);
814 } else if (strcasecmp(argv[1], "off") == 0) {
815 HAL_DISABLE_INTERRUPTS(oldints);
816 HAL_DCACHE_DISABLE_L1();
817 HAL_CACHE_FLUSH_ALL();
819 HAL_DCACHE_ENABLE_L1();
820 HAL_RESTORE_INTERRUPTS(oldints);
822 diag_printf("Invalid L2 cache mode: %s\n", argv[1]);
827 HAL_L2CACHE_IS_ENABLED(L2cache_on);
828 diag_printf("L2 cache: %s\n", L2cache_on ? "On" : "Off");
831 #endif //L2CC_ENABLED
833 #define IIM_ERR_SHIFT 8
834 #define POLL_FUSE_PRGD (IIM_STAT_PRGD | (IIM_ERR_PRGE << IIM_ERR_SHIFT))
835 #define POLL_FUSE_SNSD (IIM_STAT_SNSD | (IIM_ERR_SNSE << IIM_ERR_SHIFT))
837 static void fuse_op_start(void)
839 /* Do not generate interrupt */
840 writel(0, IIM_BASE_ADDR + IIM_STATM_OFF);
841 // clear the status bits and error bits
842 writel(0x3, IIM_BASE_ADDR + IIM_STAT_OFF);
843 writel(0xFE, IIM_BASE_ADDR + IIM_ERR_OFF);
847 * The action should be either:
852 static int poll_fuse_op_done(int action)
856 if (action != POLL_FUSE_PRGD && action != POLL_FUSE_SNSD) {
857 diag_printf("%s(%d) invalid operation\n", __FUNCTION__, action);
861 /* Poll busy bit till it is NOT set */
862 while ((readl(IIM_BASE_ADDR + IIM_STAT_OFF) & IIM_STAT_BUSY) != 0 ) {
865 /* Test for successful write */
866 status = readl(IIM_BASE_ADDR + IIM_STAT_OFF);
867 error = readl(IIM_BASE_ADDR + IIM_ERR_OFF);
869 if ((status & action) != 0 && (error & (action >> IIM_ERR_SHIFT)) == 0) {
871 diag_printf("Even though the operation seems successful...\n");
872 diag_printf("There are some error(s) at addr=0x%08lx: 0x%08x\n",
873 (IIM_BASE_ADDR + IIM_ERR_OFF), error);
877 diag_printf("%s(%d) failed\n", __FUNCTION__, action);
878 diag_printf("status address=0x%08lx, value=0x%08x\n",
879 (IIM_BASE_ADDR + IIM_STAT_OFF), status);
880 diag_printf("There are some error(s) at addr=0x%08lx: 0x%08x\n",
881 (IIM_BASE_ADDR + IIM_ERR_OFF), error);
885 unsigned int sense_fuse(int bank, int row, int bit)
887 int addr, addr_l, addr_h, reg_addr;
891 addr = ((bank << 11) | (row << 3) | (bit & 0x7));
892 /* Set IIM Program Upper Address */
893 addr_h = (addr >> 8) & 0x000000FF;
894 /* Set IIM Program Lower Address */
895 addr_l = (addr & 0x000000FF);
897 #ifdef IIM_FUSE_DEBUG
898 diag_printf("%s: addr_h=0x%02x, addr_l=0x%02x\n",
899 __FUNCTION__, addr_h, addr_l);
901 writel(addr_h, IIM_BASE_ADDR + IIM_UA_OFF);
902 writel(addr_l, IIM_BASE_ADDR + IIM_LA_OFF);
904 writel(0x8, IIM_BASE_ADDR + IIM_FCTL_OFF);
905 if (poll_fuse_op_done(POLL_FUSE_SNSD) != 0) {
906 diag_printf("%s(bank: %d, row: %d, bit: %d failed\n",
907 __FUNCTION__, bank, row, bit);
909 reg_addr = IIM_BASE_ADDR + IIM_SDAT_OFF;
910 diag_printf("fuses at (bank:%d, row:%d) = 0x%08x\n", bank, row, readl(reg_addr));
911 return readl(reg_addr);
914 void do_fuse_read(int argc, char *argv[])
916 unsigned long bank, row;
917 unsigned long fuse_val;
920 diag_printf("Usage: fuse_read <bank> <row>\n");
922 } else if (argc == 3) {
923 if (!parse_num(*(&argv[1]), &bank, &argv[1], " ")) {
924 diag_printf("Error: Invalid parameter\n");
927 if (!parse_num(*(&argv[2]), &row, &argv[2], " ")) {
928 diag_printf("Error: Invalid parameter\n");
932 diag_printf("Read fuse at bank:%ld row:%ld\n", bank, row);
933 fuse_val = sense_fuse(bank, row, 0);
934 diag_printf("fuses at (bank:%ld, row:%ld) = 0x%lx\n", bank, row, fuse_val);
936 diag_printf("Passing in wrong arguments: %d\n", argc);
937 diag_printf("Usage: fuse_read <bank> <row>\n");
941 /* Blow fuses based on the bank, row and bit positions (all 0-based)
943 static int fuse_blow(int bank, int row, int bit)
945 int addr, addr_l, addr_h, ret = -1;
949 /* Disable IIM Program Protect */
950 writel(0xAA, IIM_BASE_ADDR + IIM_PREG_P_OFF);
952 addr = ((bank << 11) | (row << 3) | (bit & 0x7));
953 /* Set IIM Program Upper Address */
954 addr_h = (addr >> 8) & 0x000000FF;
955 /* Set IIM Program Lower Address */
956 addr_l = (addr & 0x000000FF);
958 #ifdef IIM_FUSE_DEBUG
959 diag_printf("blowing fuse %d %d bit %d addr_h=0x%02x, addr_l=0x%02x\n",
960 bank, row, bit, addr_h, addr_l);
963 writel(addr_h, IIM_BASE_ADDR + IIM_UA_OFF);
964 writel(addr_l, IIM_BASE_ADDR + IIM_LA_OFF);
965 /* Start Programming */
966 writel(0x71, IIM_BASE_ADDR + IIM_FCTL_OFF);
967 if (poll_fuse_op_done(POLL_FUSE_PRGD) == 0) {
971 /* Enable IIM Program Protect */
972 writel(0x0, IIM_BASE_ADDR + IIM_PREG_P_OFF);
977 * This command is added for burning IIM fuses
979 RedBoot_cmd("fuse_read",
985 RedBoot_cmd("fuse_blow",
987 "<bank> <row> <value>",
991 void quick_itoa(u32 num, char *a)
994 for (i = 0; i <= 7; i++) {
995 j = (num >> (4 * i)) & 0xF;
996 k = (j < 10) ? '0' : ('a' - 0xa);
1001 // slen - streng length, e.g.: 23 -> slen=2; abcd -> slen=4
1002 // only convert hex value as string input. so "12" is 0x12.
1003 u32 quick_atoi(char *a, u32 slen)
1005 u32 i, num = 0, digit;
1007 for (i = 0; i < slen; i++) {
1008 if (a[i] >= '0' && a[i] <= '9') {
1010 } else if (a[i] >= 'a' && a[i] <= 'f') {
1011 digit = a[i] - 'a' + 10;
1012 } else if (a[i] >= 'A' && a[i] <= 'F') {
1013 digit = a[i] - 'A' + 10;
1015 diag_printf("ERROR: %c\n", a[i]);
1018 num = (num * 16) + digit;
1023 void fuse_blow_row(int bank, int row, int value)
1025 unsigned int reg, i;
1027 // enable fuse blown
1028 reg = readl(CCM_BASE_ADDR + 0x64);
1030 writel(reg, CCM_BASE_ADDR + 0x64);
1032 for (i = 0; i < 8; i++) {
1033 if (((value >> i) & 0x1) == 0) {
1036 if (fuse_blow(bank, row, i) != 0) {
1037 diag_printf("fuse_blow(bank: %d, row: %d, bit: %d failed\n",
1042 writel(reg, CCM_BASE_ADDR + 0x64);
1045 void do_fuse_blow(int argc, char *argv[])
1047 unsigned long bank, row, value, i;
1048 unsigned int fuse_val;
1053 diag_printf("It is too dangeous for you to use this command.\n");
1058 if (strcasecmp(argv[1], "scc") == 0) {
1059 // fuse_blow scc C3D153EDFD2EA9982226EF5047D3B9A0B9C7138EA87C028401D28C2C2C0B9AA2
1060 diag_printf("Ready to burn SCC fuses\n");
1065 value = quick_atoi(val, 2);
1066 // diag_printf("fuse_blow_row(2, %d, value=0x%02x)\n", i, value);
1067 fuse_blow_row(2, i, value);
1069 if ((++s)[0] == '\0') {
1070 diag_printf("ERROR: Odd string input\n");
1073 if ((++s)[0] == '\0') {
1074 diag_printf("Successful\n");
1078 } else if (strcasecmp(argv[1], "srk") == 0) {
1079 // fuse_blow srk 418bccd09b53bee1ab59e2662b3c7877bc0094caee201052add49be8780dff95
1080 diag_printf("Ready to burn SRK key fuses\n");
1085 value = quick_atoi(val, 2);
1087 fuse_blow_row(1, 1, value); // 0x41 goes to SRK_HASH[255:248], bank 1, row 1
1089 fuse_blow_row(3, i, value); // 0x8b in SRK_HASH[247:240] bank 3, row 1
1090 // 0xcc in SRK_HASH[239:232] bank 3, row 2
1092 if ((++s)[0] == '\0') {
1093 diag_printf("ERROR: Odd string input\n");
1096 if ((++s)[0] == '\0') {
1097 diag_printf("Successful\n");
1102 diag_printf("This command is not supported\n");
1105 } else if (argc == 4) {
1106 if (!parse_num(*(&argv[1]), (unsigned long *)&bank, &argv[1], " ")) {
1107 diag_printf("Error: Invalid parameter\n");
1110 if (!parse_num(*(&argv[2]), &row, &argv[2], " ")) {
1111 diag_printf("Error: Invalid parameter\n");
1114 if (!parse_num(*(&argv[3]), &value, &argv[3], " ")) {
1115 diag_printf("Error: Invalid parameter\n");
1119 diag_printf("Blowing fuse at bank:%ld row:%ld value:%ld\n",
1121 fuse_blow_row(bank, row, value);
1122 fuse_val = sense_fuse(bank, row, 0);
1123 diag_printf("fuses at (bank:%ld, row:%ld) = 0x%02x\n", bank, row, fuse_val);
1126 diag_printf("Passing in wrong arguments: %d\n", argc);
1130 /* precondition: m>0 and n>0. Let g=gcd(m,n). */
1131 int gcd(int m, int n)
1135 if(n > m) {t = m; m = n; n = t;} /* swap */
1141 int read_mac_addr_from_fuse(unsigned char* data)
1143 data[0] = sense_fuse(1, 9, 0) ;
1144 data[1] = sense_fuse(1, 10, 0) ;
1145 data[2] = sense_fuse(1, 11, 0) ;
1146 data[3] = sense_fuse(1, 12, 0) ;
1147 data[4] = sense_fuse(1, 13, 0) ;
1148 data[5] = sense_fuse(1, 14, 0) ;
1150 if ((data[0] == 0) && (data[1] == 0) && (data[2] == 0) &&
1151 (data[3] == 0) && (data[4] == 0) && (data[5] == 0)) {
1159 void imx_power_mode(int mode)
1161 volatile unsigned int val;
1164 writel(0x0000030f, GPC_PGR);
1165 writel(0x1, SRPGCR_EMI);
1166 writel(0x1, SRPGCR_ARM);
1167 writel(0x1, PGC_PGCR_VPU);
1168 writel(0x1, PGC_PGCR_IPU);
1172 // stop mode - from validation code
1173 // Set DSM_INT_HOLDOFF bit in TZIC
1174 // If the TZIC didn't write the bit then there was interrupt pending
1175 // It will be serviced while we're in the loop
1176 // So we write to this bit again
1177 while (readl(INTC_BASE_ADDR + 0x14) == 0) {
1178 writel(1, INTC_BASE_ADDR + 0x14);
1188 diag_printf("Entering stop mode\n");
1189 val = readl(CCM_BASE_ADDR + 0x74);
1190 val = (val & 0xfffffffc) | 0x2; // set STOP mode
1191 writel(val, CCM_BASE_ADDR + 0x74);
1192 val = readl(PLATFORM_LPC_REG);
1193 writel(val | (1 << 16), PLATFORM_LPC_REG);// ENABLE DSM in ELBOW submodule of ARM platform
1194 writel(val | (1 << 17), PLATFORM_LPC_REG);// ENABLE DSM in ELBOW submodule of ARM platform
1201 asm("mcr p15, 0, r1, c7, c0, 4");
1204 void do_power_mode(int argc, char *argv[])
1209 diag_printf("Usage: power_mode <mode>\n");
1211 } else if (argc == 2) {
1212 if (!parse_num(*(&argv[1]), (unsigned long *)&mode, &argv[1], " ")) {
1213 diag_printf("Error: Invalid parameter\n");
1216 diag_printf("Entering power mode: %d\n", mode);
1217 imx_power_mode(mode);
1220 diag_printf("Passing in wrong arguments: %d\n", argc);
1221 diag_printf("Usage: power_mode <mode>\n");
1226 * This command is added for burning IIM fuses
1228 RedBoot_cmd("power_mode",
1229 "Enter various power modes:",
1234 " <3> - STOP with Power-Gating\n"
1235 " -- need reset after issuing the command",
1240 /* Super Root key moduli */
1241 static const UINT8 hab_super_root_moduli[] = {
1243 0xb9, 0x84, 0xc8, 0x8a, 0xd3, 0x7e, 0xcc, 0xc0, 0xe7, 0x3e, 0x11, 0x53,
1244 0x6b, 0x5e, 0xea, 0xf4, 0xd9, 0xac, 0x5a, 0x63, 0x8a, 0x79, 0x96, 0x83,
1245 0xb1, 0x39, 0xb2, 0x6f, 0x9c, 0x54, 0x87, 0xf4, 0x3b, 0x9e, 0xd8, 0x0f,
1246 0x89, 0xf5, 0x01, 0x53, 0xb8, 0xe2, 0xcc, 0x75, 0x0d, 0xe1, 0x13, 0xfa,
1247 0xa7, 0xb9, 0x1e, 0xff, 0x6a, 0x05, 0xdb, 0x58, 0x10, 0xbf, 0x2b, 0xf4,
1248 0xe7, 0x0a, 0x63, 0x82, 0x2c, 0xa3, 0xb5, 0x0a, 0x72, 0x1c, 0xdc, 0x29,
1249 0xc1, 0x81, 0xb5, 0x9a, 0xf0, 0x25, 0x7d, 0xd6, 0xee, 0x01, 0x64, 0xc7,
1250 0x07, 0x2d, 0xcb, 0x31, 0x4c, 0x8d, 0x82, 0xf6, 0x44, 0x95, 0x4a, 0xbc,
1251 0xae, 0xe8, 0x2a, 0x89, 0xd4, 0xf2, 0x66, 0x72, 0x2b, 0x09, 0x4e, 0x56,
1252 0xe9, 0xbf, 0x5e, 0x38, 0x5c, 0xd5, 0x7e, 0x15, 0x55, 0x86, 0x0f, 0x19,
1253 0xf6, 0x00, 0xee, 0xa1, 0x92, 0x78, 0xef, 0x93, 0xcb, 0xfa, 0xb4, 0x98,
1254 0x19, 0xef, 0x10, 0x70, 0xde, 0x36, 0x1c, 0x12, 0x2e, 0xd2, 0x09, 0xc7,
1255 0x7b, 0xd1, 0xaa, 0xd3, 0x46, 0x65, 0xa1, 0x5b, 0xee, 0xa5, 0x96, 0x97,
1256 0x98, 0x3e, 0xfc, 0xf8, 0x74, 0x22, 0x51, 0xe7, 0xf1, 0x2f, 0x30, 0x79,
1257 0x13, 0xe5, 0x42, 0xc6, 0x7c, 0x18, 0x76, 0xd3, 0x7f, 0x5a, 0x13, 0xde,
1258 0x2f, 0x51, 0x07, 0xfa, 0x93, 0xfe, 0x10, 0x8a, 0x0c, 0x18, 0x60, 0x3c,
1259 0xff, 0x6a, 0x9b, 0xe7, 0x10, 0x2d, 0x71, 0xd2, 0x34, 0xc0, 0xdf, 0xbe,
1260 0x17, 0x4e, 0x75, 0x40, 0x83, 0xaa, 0x90, 0xd1, 0xed, 0xbd, 0xbf, 0xac,
1261 0x9a, 0x30, 0xbd, 0x69, 0x4d, 0xd8, 0x00, 0x63, 0x92, 0x69, 0x98, 0xf8,
1262 0x89, 0xdc, 0x7b, 0xe3, 0x66, 0x7e, 0xdd, 0xfa, 0x8c, 0x74, 0xe2, 0xb1,
1263 0xeb, 0x94, 0xf7, 0xab, 0x0e, 0x92, 0x06, 0xab, 0x60, 0xe5, 0x00, 0x43,
1264 0xb2, 0x5e, 0x6e, 0xeb
1267 /* Super Root key */
1268 const hab_rsa_public_key hab_super_root_key[] = {
1271 /* RSA public exponent, right-padded */
1272 0x01, 0x00, 0x01, 0x00,
1274 /* pointer to modulus data */
1275 hab_super_root_moduli,
1276 /* Exponent size in bytes */
1278 /* Modulus size in bytes */
1280 /* Key data valid */