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 CMD_CLOCK_DEBUG
50 #ifdef CMD_CLOCK_DEBUG
56 #define dbg(fmt...) CYG_EMPTY_STATEMENT
59 int gcd(int m, int n);
60 extern void increase_core_voltage(bool i);
62 typedef unsigned long long u64;
63 typedef unsigned int u32;
64 typedef unsigned short u16;
65 typedef unsigned char u8;
67 #define SZ_DEC_1M 1000000
68 #define PLL_PD_MAX 16 //actual pd+1
69 #define PLL_MFI_MAX 15
77 #define REF_IN_CLK_NUM 4
78 struct fixed_pll_mfd {
83 const struct fixed_pll_mfd fixed_mfd[REF_IN_CLK_NUM] = {
84 { 0, 0, }, // reserved
85 { 0, 0, }, // reserved
86 { FREQ_24MHZ, 24 * 16, }, // internal osc
87 { FREQ_32768HZ, 1024, }, // FPM
97 #define PLL_FREQ_MAX(_ref_clk_) (4 * _ref_clk_ * PLL_MFI_MAX)
98 #define PLL_FREQ_MIN(_ref_clk_) ((2 * _ref_clk_ * (PLL_MFI_MIN - 1)) / PLL_PD_MAX)
99 #define MAX_DDR_CLK 220000000
100 #define AHB_CLK_MAX 133333333
101 #define IPG_CLK_MAX (AHB_CLK_MAX / 2)
102 #define NFC_CLK_MAX 25000000
103 // IPU-HSP clock is independent of the HCLK and can go up to 177MHz but requires
104 // higher voltage support. For simplicity, limit it to 133MHz
105 #define HSP_CLK_MAX 133333333
107 #define ERR_WRONG_CLK (-1)
108 #define ERR_NO_MFI (-2)
109 #define ERR_NO_MFN (-3)
110 #define ERR_NO_PD (-4)
111 #define ERR_NO_PRESC (-5)
112 #define ERR_NO_AHB_DIV (-6)
114 u32 pll_clock(enum plls pll);
115 u32 get_main_clock(enum main_clocks clk);
116 u32 get_peri_clock(enum peri_clocks clk);
118 static volatile u32 *pll_base[] =
120 REG32_PTR(PLL1_BASE_ADDR),
121 REG32_PTR(PLL2_BASE_ADDR),
122 REG32_PTR(PLL3_BASE_ADDR),
125 #define NOT_ON_VAL 0xDEADBEEF
127 static void clock_setup(int argc, char *argv[]);
130 "Setup/Display clock\nSyntax:",
131 "[<core clock in MHz> :<DDR clock in MHz>]\n\n"
133 " [clock] -> Show various clocks\n"
134 " [clock 665] -> Core=665\n"
135 " [clock 800:133] -> Core=800 DDR=133\n"
136 " [clock :166] -> Core=no change DDR=166\n",
141 * This is to calculate various parameters based on reference clock and
142 * targeted clock based on the equation:
143 * t_clk = 2*ref_freq*(mfi + mfn/(mfd+1))/(pd+1)
144 * This calculation is based on a fixed MFD value for simplicity.
146 * @param ref reference clock freq in Hz
147 * @param target targeted clock in Hz
148 * @param p_pd calculated pd value (pd value from register + 1) upon return
149 * @param p_mfi calculated actual mfi value upon return
150 * @param p_mfn calculated actual mfn value upon return
151 * @param p_mfd fixed mfd value (mfd value from register + 1) upon return
153 * @return 0 if successful; non-zero otherwise.
155 int calc_pll_params(u32 ref, u32 target, struct pll_param *pll)
157 u64 pd, mfi = 1, mfn, mfd, n_target = target, n_ref = ref, i;
159 // make sure targeted freq is in the valid range. Otherwise the
160 // following calculation might be wrong!!!
161 if (n_target < PLL_FREQ_MIN(ref) || n_target > PLL_FREQ_MAX(ref))
162 return ERR_WRONG_CLK;
164 if (i == REF_IN_CLK_NUM)
165 return ERR_WRONG_CLK;
166 if (fixed_mfd[i].ref_clk_hz == ref) {
167 mfd = fixed_mfd[i].mfd;
172 // Use n_target and n_ref to avoid overflow
173 for (pd = 1; pd <= PLL_PD_MAX; pd++) {
174 mfi = (n_target * pd) / (4 * n_ref);
175 if (mfi > PLL_MFI_MAX) {
177 } else if (mfi < 5) {
182 // Now got pd and mfi already
183 mfn = (((n_target * pd) / 4 - n_ref * mfi) * mfd) / n_ref;
185 dbg("%d: ref=%d, target=%d, pd=%d, mfi=%d,mfn=%d, mfd=%d\n",
186 __LINE__, ref, (u32)n_target, (u32)pd, (u32)mfi, (u32)mfn, (u32)mfd);
193 pll->mfn = (u32)(mfn / i);
194 pll->mfd = (u32)(mfd / i);
199 * This function returns the low power audio clock.
204 u32 ccsr = readl(CCM_BASE_ADDR + CLKCTL_CCSR);
206 if (((ccsr >> 9) & 1) == 0) {
207 ret_val = FREQ_24MHZ;
209 ret_val = FREQ_32768HZ;
211 dbg("%s: CCSR[%08lx]=%08x freq=%u.%03uMHz\n", __FUNCTION__,
212 CCM_BASE_ADDR + CLKCTL_CCSR, ccsr, ret_val / 1000000, ret_val / 1000 % 1000);
217 * This function returns the periph_clk.
219 u32 get_periph_clk(void)
221 u32 ret_val, clk_sel;
223 u32 cbcdr = readl(CCM_BASE_ADDR + CLKCTL_CBCDR);
224 u32 cbcmr = readl(CCM_BASE_ADDR + CLKCTL_CBCMR);
226 if (!(cbcdr & (1 << 25))) {
227 ret_val = pll_clock(PLL2);
228 dbg("%s: CBCDR[%08lx]=%08x CBCMR[%08lx]=%08x freq=%u.%03uMHz\n", __FUNCTION__,
229 CCM_BASE_ADDR + CLKCTL_CBCDR, cbcdr,
230 CCM_BASE_ADDR + CLKCTL_CBCMR, cbcmr,
231 ret_val / 1000000, ret_val / 1000 % 1000);
233 clk_sel = (cbcmr >> 12) & 3;
235 ret_val = pll_clock(PLL1);
236 } else if (clk_sel == 1) {
237 ret_val = pll_clock(PLL3);
238 } else if (clk_sel == 2) {
239 ret_val = get_lp_apm();
241 diag_printf("Invalid CBCMR[CLK_SEL]: %d\n", clk_sel);
242 return ERR_WRONG_CLK;
244 dbg("%s: CBCDR[%08lx]=%08x CBCMR[%08lx]=%08x clk_sel=%d freq=%u.%03uMHz\n", __FUNCTION__,
245 CCM_BASE_ADDR + CLKCTL_CBCDR, cbcdr,
246 CCM_BASE_ADDR + CLKCTL_CBCMR, cbcmr,
247 clk_sel, ret_val / 1000000, ret_val / 1000 % 1000);
253 * This function assumes the expected core clock has to be changed by
254 * modifying the PLL. This is NOT true always but for most of the times,
255 * it is. So it assumes the PLL output freq is the same as the expected
256 * core clock (presc=1) unless the core clock is less than PLL_FREQ_MIN.
257 * In the latter case, it will try to increase the presc value until
258 * (presc*core_clk) is greater than PLL_FREQ_MIN. It then makes call to
259 * calc_pll_params() and obtains the values of PD, MFI,MFN, MFD based
260 * on the targeted PLL and reference input clock to the PLL. Lastly,
261 * it sets the register based on these values along with the dividers.
262 * Note 1) There is no value checking for the passed-in divider values
263 * so the caller has to make sure those values are sensible.
264 * 2) Also adjust the NFC divider such that the NFC clock doesn't
265 * exceed NFC_CLK_MAX.
266 * 3) IPU HSP clock is independent of AHB clock. Even it can go up to
267 * 177MHz for higher voltage, this function fixes the max to 133MHz.
268 * 4) This function should not have allowed diag_printf() calls since
269 * the serial driver has been stoped. But leave then here to allow
270 * easy debugging by NOT calling the cyg_hal_plf_serial_stop().
272 * @param ref pll input reference clock (24MHz)
273 * @param core_clk core clock in Hz
274 * @param emi_clk emi clock in Hz
275 # @return 0 if successful; non-zero otherwise
277 int configure_clock(u32 ref, u32 core_clk, u32 emi_clk)
280 struct pll_param pll_param;
281 int ret, clk_sel, div = 1, div_core = 1, div_per = 1, shift = 0;
282 u32 cbcdr = readl(CCM_BASE_ADDR + CLKCTL_CBCDR);
283 u32 cbcmr = readl(CCM_BASE_ADDR + CLKCTL_CBCMR);
284 u32 ccsr = readl(CCM_BASE_ADDR + CLKCTL_CCSR);
285 u32 icgc = readl(PLATFORM_BASE_ADDR + PLATFORM_ICGC);
287 dbg("%s: cbcdr[%08lx]=%08x\n", __FUNCTION__,
288 CCM_BASE_ADDR + CLKCTL_CBCDR, cbcdr);
289 dbg("%s: cbcmr[%08lx]=%08x\n", __FUNCTION__,
290 CCM_BASE_ADDR + CLKCTL_CBCMR, cbcdr);
291 dbg("%s: ccsr[%08lx]=%08x\n", __FUNCTION__,
292 CCM_BASE_ADDR + CLKCTL_CCSR, cbcdr);
293 dbg("%s: icgc[%08lx]=%08x\n", __FUNCTION__,
294 PLATFORM_BASE_ADDR + PLATFORM_ICGC, icgc);
297 // assume pll default to core clock first
299 if ((ret = calc_pll_params(ref, pll, &pll_param)) != 0) {
300 diag_printf("can't find pll parameters: %d\n", ret);
304 dbg("%s: ref=%d, pll=%d, pd=%d, mfi=%d,mfn=%d, mfd=%d\n", __FUNCTION__,
305 ref, pll, pll_param.pd, pll_param.mfi, pll_param.mfn, pll_param.mfd);
307 /* Applies for TO 2 only */
308 if (((cbcdr >> 30) & 0x1) == 0x1) {
309 /* Disable IPU and HSC dividers */
310 writel(0x60000, CCM_BASE_ADDR + CLKCTL_CCDR);
311 /* Switch DDR to different source */
312 writel(cbcdr & ~0x40000000, CCM_BASE_ADDR + CLKCTL_CBCDR);
313 while (readl(CCM_BASE_ADDR + CLKCTL_CDHIPR) != 0);
314 writel(0x0, CCM_BASE_ADDR + CLKCTL_CCDR);
317 /* Switch ARM to PLL2 clock */
318 writel(ccsr | 0x4, CCM_BASE_ADDR + CLKCTL_CCSR);
320 if ((core_clk > 665000000) && (core_clk <= 800000000)) {
322 } else if (core_clk > 800000000) {
328 if (core_clk > 800000000) {
330 increase_core_voltage(true);
333 increase_core_voltage(false);
336 // adjust pll settings
337 writel(((pll_param.pd - 1) << 0) | (pll_param.mfi << 4),
338 PLL1_BASE_ADDR + PLL_DP_OP);
339 writel(pll_param.mfn, PLL1_BASE_ADDR + PLL_DP_MFN);
340 writel(pll_param.mfd - 1, PLL1_BASE_ADDR + PLL_DP_MFD);
341 writel(((pll_param.pd - 1) << 0) | (pll_param.mfi << 4),
342 PLL1_BASE_ADDR + PLL_DP_HFS_OP);
343 writel(pll_param.mfn, PLL1_BASE_ADDR + PLL_DP_HFS_MFN);
344 writel(pll_param.mfd - 1, PLL1_BASE_ADDR + PLL_DP_HFS_MFD);
347 icgc |= div_core << 4;
349 /* Set the platform clock dividers */
350 writel(icgc, PLATFORM_BASE_ADDR + PLATFORM_ICGC);
351 /* Switch ARM back to PLL1 */
352 writel((ccsr & ~0x4), CCM_BASE_ADDR + CLKCTL_CCSR);
353 /* Applies for TO 2 only */
354 if (((cbcdr >> 30) & 0x1) == 0x1) {
355 /* Disable IPU and HSC dividers */
356 writel(0x60000, CCM_BASE_ADDR + CLKCTL_CCDR);
357 /* Switch DDR back to PLL1 */
358 writel(cbcdr | 0x40000000, CCM_BASE_ADDR + CLKCTL_CBCDR);
359 while (readl(CCM_BASE_ADDR + CLKCTL_CDHIPR) != 0);
360 writel(0x0, CCM_BASE_ADDR + CLKCTL_CCDR);
362 /* Keep EMI clock to the max if not specified */
369 /* Applies for TO 2 only */
370 if (((cbcdr >> 30) & 0x1) == 0x1) {
371 clk_src = pll_clock(PLL1);
374 clk_src = get_periph_clk();
375 /* Find DDR clock input */
376 clk_sel = (cbcmr >> 10) & 0x3;
379 } else if (clk_sel == 1) {
381 } else if (clk_sel == 2) {
383 } else if (clk_sel == 3) {
387 if ((clk_src % emi_clk) == 0)
388 div = clk_src / emi_clk;
390 div = (clk_src / emi_clk) + 1;
394 cbcdr &= ~(0x7 << shift);
395 cbcdr |= (div - 1) << shift;
396 dbg("%s@%d: \n", __FUNCTION__, __LINE__);
398 /* Disable IPU and HSC dividers */
399 writel(0x60000, CCM_BASE_ADDR + CLKCTL_CCDR);
400 writel(cbcdr, CCM_BASE_ADDR + CLKCTL_CBCDR);
401 while (readl(CCM_BASE_ADDR + CLKCTL_CDHIPR) != 0);
402 writel(0x0, CCM_BASE_ADDR + CLKCTL_CCDR);
407 static void clock_setup(int argc,char *argv[])
409 u32 i, core_clk, ddr_clk, data[3];
416 for (i = 0; i < 2; i++) {
417 if (!parse_num(*(&argv[1]), &temp, &argv[1], ":")) {
418 diag_printf("Error: Invalid parameter\n");
424 core_clk = data[0] * SZ_DEC_1M;
425 ddr_clk = data[1] * SZ_DEC_1M;
428 if ((core_clk < PLL_FREQ_MIN(PLL_REF_CLK)) || (core_clk > PLL_FREQ_MAX(PLL_REF_CLK))) {
429 diag_printf("Targeted core clock should be within [%d - %d]\n",
430 PLL_FREQ_MIN(PLL_REF_CLK), PLL_FREQ_MAX(PLL_REF_CLK));
436 if (ddr_clk > MAX_DDR_CLK) {
437 diag_printf("DDR clock should be less than %d MHz, assuming max value\n", (MAX_DDR_CLK / SZ_DEC_1M));
438 ddr_clk = MAX_DDR_CLK;
443 // stop the serial to be ready to adjust the clock
444 hal_delay_us(100000);
445 cyg_hal_plf_serial_stop();
448 ret = configure_clock(PLL_REF_CLK, core_clk, ddr_clk);
449 // restart the serial driver
450 cyg_hal_plf_serial_init();
451 hal_delay_us(100000);
454 diag_printf("Failed to setup clock: %d\n", ret);
457 diag_printf("\n<<<New clock setting>>>\n");
459 // Now printing clocks
462 diag_printf("\nPLL1\t\tPLL2\t\tPLL3\n");
463 diag_printf("========================================\n");
464 diag_printf("%-16d%-16d%-16d\n\n", pll_clock(PLL1), pll_clock(PLL2),
466 diag_printf("CPU\t\tAHB\t\tIPG\t\tEMI_CLK\n");
467 diag_printf("========================================================\n");
468 diag_printf("%-16d%-16d%-16d%-16d\n\n",
469 get_main_clock(CPU_CLK),
470 get_main_clock(AHB_CLK),
471 get_main_clock(IPG_CLK),
472 get_main_clock(DDR_CLK));
474 diag_printf("NFC\t\tUSB\t\tIPG_PER_CLK\n");
475 diag_printf("========================================\n");
476 diag_printf("%-16d%-16d%-16d\n\n",
477 get_main_clock(NFC_CLK),
478 get_main_clock(USB_CLK),
479 get_main_clock(IPG_PER_CLK));
481 diag_printf("UART1-3\t\tSSI1\t\tSSI2\t\tSPI\n");
482 diag_printf("===========================================");
483 diag_printf("=============\n");
485 diag_printf("%-16d%-16d%-16d%-16d\n\n",
486 get_peri_clock(UART1_BAUD),
487 get_peri_clock(SSI1_BAUD),
488 get_peri_clock(SSI2_BAUD),
489 get_peri_clock(SPI1_CLK));
492 diag_printf("IPG_PERCLK as baud clock for: UART1-5, I2C, OWIRE, SDHC");
493 if (((readl(EPIT1_BASE_ADDR) >> 24) & 0x3) == 0x2) {
494 diag_printf(", EPIT");
496 if (((readl(GPT1_BASE_ADDR) >> 6) & 0x7) == 0x2) {
505 * This function returns the PLL output value in Hz based on pll.
507 u32 pll_clock(enum plls pll)
510 u32 mfi, mfn, mfd, pdf, pll_out, sign;
511 u32 dp_ctrl, dp_op, dp_mfd, dp_mfn;
515 dp_ctrl = pll_base[pll][PLL_DP_CTL >> 2];
516 clk_sel = MXC_GET_FIELD(dp_ctrl, 2, 8);
517 ref_clk = fixed_mfd[clk_sel].ref_clk_hz;
519 dbg("clk_sel=%d\n", clk_sel);
521 if ((pll_base[pll][PLL_DP_CTL >> 2] & 0x80) == 0) {
522 dp_op = pll_base[pll][PLL_DP_OP >> 2];
523 dp_mfd = pll_base[pll][PLL_DP_MFD >> 2];
524 dp_mfn = pll_base[pll][PLL_DP_MFN >> 2];
526 dp_op = pll_base[pll][PLL_DP_HFS_OP >> 2];
527 dp_mfd = pll_base[pll][PLL_DP_HFS_MFD >> 2];
528 dp_mfn = pll_base[pll][PLL_DP_HFS_MFN >> 2];
531 mfi = (dp_op >> 4) & 0xF;
532 mfi = (mfi <= 5) ? 5: mfi;
533 mfd = dp_mfd & 0x07FFFFFF;
534 mfn = dp_mfn & 0x07FFFFFF;
536 sign = (mfn < 0x4000000) ? 1 : -1;
537 mfn = (mfn < 0x4000000) ? mfn : (0x8000000 - mfn);
539 dbl = 2 * (((dp_ctrl >> 12) & 0x1) + 1);
541 dbg("%s: ref=%llu.%03lluMHz, dbl=%d, pd=%d, mfi=%d, mfn=%s%d, mfd=%d\n",
542 __FUNCTION__, ref_clk / 1000000, ref_clk / 1000 % 1000,
543 dbl, pdf, mfi, sign ? "-" : "", mfn, mfd);
545 pll_out = (dbl * ref_clk * mfi + ((dbl * ref_clk * sign * mfn) / (mfd + 1))) /
552 * This function returns the emi_core_clk_root clock.
554 u32 get_emi_core_clk(void)
556 u32 cbcdr = readl(CCM_BASE_ADDR + CLKCTL_CBCDR);
557 u32 clk_sel, max_pdf, peri_clk, ahb_clk;
560 max_pdf = (cbcdr >> 10) & 0x7;
561 peri_clk = get_periph_clk();
562 ahb_clk = peri_clk / (max_pdf + 1);
564 clk_sel = (cbcdr >> 26) & 1;
570 dbg("%s: CBCDR[%08lx]=%08x freq=%u.%03uMHz\n", __FUNCTION__,
571 CCM_BASE_ADDR + CLKCTL_CBCDR, cbcdr, ret_val / 1000000, ret_val / 1000 % 1000);
576 * This function returns the main clock value in Hz.
578 u32 get_main_clock(enum main_clocks clk)
580 u32 pdf, max_pdf, ipg_pdf, nfc_pdf, clk_sel;
582 u32 cacrr = readl(CCM_BASE_ADDR + CLKCTL_CACRR);
583 u32 cbcdr = readl(CCM_BASE_ADDR + CLKCTL_CBCDR);
584 u32 cbcmr = readl(CCM_BASE_ADDR + CLKCTL_CBCMR);
585 u32 cscmr1 = readl(CCM_BASE_ADDR + CLKCTL_CSCMR1);
586 u32 cscdr1 = readl(CCM_BASE_ADDR + CLKCTL_CSCDR1);
588 dbg("%s: \n", __FUNCTION__);
592 pll = pll_clock(PLL1);
593 ret_val = pll / (pdf + 1);
596 max_pdf = (cbcdr >> 10) & 0x7;
597 pll = get_periph_clk();
598 ret_val = pll / (max_pdf + 1);
601 max_pdf = (cbcdr >> 10) & 0x7;
602 ipg_pdf = (cbcdr >> 8) & 0x3;
603 pll = get_periph_clk();
604 ret_val = pll / ((max_pdf + 1) * (ipg_pdf + 1));
609 clk_sel = (cbcmr >> 1) & 1;
610 pdf = (((cbcdr >> 6) & 3) + 1) * (((cbcdr >> 3) & 7) + 1) * ((cbcdr & 7) + 1);
612 ret_val = get_periph_clk() / pdf;
614 ret_val = get_lp_apm();
617 /* Same as IPG_CLK */
618 max_pdf = (cbcdr >> 10) & 0x7;
619 ipg_pdf = (cbcdr >> 8) & 0x3;
620 pll = get_periph_clk();
621 ret_val = pll / ((max_pdf + 1) * (ipg_pdf + 1));
625 if (((cbcdr >> 30) & 0x1) == 0x1) {
626 pll = pll_clock(PLL1);
627 pdf = (cbcdr >> 27) & 0x7;
629 clk_sel = (cbcmr >> 10) & 3;
630 pll = get_periph_clk();
633 pdf = (cbcdr >> 16) & 0x7;
634 } else if (clk_sel == 1) {
636 pdf = (cbcdr >> 19) & 0x7;
637 } else if (clk_sel == 2) {
638 /* EMI SLOW CLOCK ROOT */
639 pll = get_emi_core_clk();
640 pdf = (cbcdr >> 22) & 0x7;
641 } else if (clk_sel == 3) {
643 pdf = (cbcdr >> 10) & 0x7;
647 ret_val = pll / (pdf + 1);
650 pdf = (cbcdr >> 22) & 0x7;
651 nfc_pdf = (cbcdr >> 13) & 0x7;
652 pll = get_emi_core_clk();
653 ret_val = pll / ((pdf + 1) * (nfc_pdf + 1));
656 clk_sel = (cscmr1 >> 22) & 3;
658 pll = pll_clock(PLL1);
659 } else if (clk_sel == 1) {
660 pll = pll_clock(PLL2);
661 } else if (clk_sel == 2) {
662 pll = pll_clock(PLL3);
663 } else if (clk_sel == 3) {
666 pdf = (cscdr1 >> 8) & 0x7;
667 max_pdf = (cscdr1 >> 6) & 0x3;
668 ret_val = pll / ((pdf + 1) * (max_pdf + 1));
671 diag_printf("Unknown clock: %d\n", clk);
672 return ERR_WRONG_CLK;
679 * This function returns the peripheral clock value in Hz.
681 u32 get_peri_clock(enum peri_clocks clk)
683 u32 ret_val = 0, pdf, pre_pdf, clk_sel;
684 u32 cscmr1 = readl(CCM_BASE_ADDR + CLKCTL_CSCMR1);
685 u32 cscdr1 = readl(CCM_BASE_ADDR + CLKCTL_CSCDR1);
686 u32 cscdr2 = readl(CCM_BASE_ADDR + CLKCTL_CSCDR2);
687 u32 cs1cdr = readl(CCM_BASE_ADDR + CLKCTL_CS1CDR);
688 u32 cs2cdr = readl(CCM_BASE_ADDR + CLKCTL_CS2CDR);
690 dbg("%s: \n", __FUNCTION__);
695 pre_pdf = (cscdr1 >> 3) & 0x7;
697 clk_sel = (cscmr1 >> 24) & 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 pre_pdf = (cs1cdr >> 6) & 0x7;
711 clk_sel = (cscmr1 >> 14) & 3;
713 ret_val = pll_clock(PLL1) / ((pre_pdf + 1) * (pdf + 1));
714 } else if (clk_sel == 0x1) {
715 ret_val = pll_clock(PLL2) / ((pre_pdf + 1) * (pdf + 1));
716 } else if (clk_sel == 0x2) {
717 ret_val = pll_clock(PLL3) / ((pre_pdf + 1) * (pdf + 1));
719 ret_val = CKIH /((pre_pdf + 1) * (pdf + 1));
723 pre_pdf = (cs2cdr >> 6) & 0x7;
725 clk_sel = (cscmr1 >> 12) & 3;
727 ret_val = pll_clock(PLL1) / ((pre_pdf + 1) * (pdf + 1));
728 } else if (clk_sel == 0x1) {
729 ret_val = pll_clock(PLL2) / ((pre_pdf + 1) * (pdf + 1));
730 } else if (clk_sel == 0x2) {
731 ret_val = pll_clock(PLL3) / ((pre_pdf + 1) * (pdf + 1));
733 ret_val = CKIH /((pre_pdf + 1) * (pdf + 1));
738 pre_pdf = (cscdr2 >> 25) & 0x7;
739 pdf = (cscdr2 >> 19) & 0x3F;
740 clk_sel = (cscmr1 >> 4) & 3;
742 ret_val = pll_clock(PLL1) / ((pre_pdf + 1) * (pdf + 1));
743 } else if (clk_sel == 1) {
744 ret_val = pll_clock(PLL2) / ((pre_pdf + 1) * (pdf + 1));
745 } else if (clk_sel == 2) {
746 ret_val = pll_clock(PLL3) / ((pre_pdf + 1) * (pdf + 1));
748 ret_val = get_lp_apm() / ((pre_pdf + 1) * (pdf + 1));
752 diag_printf("%s(): This clock: %d not supported yet\n",
761 * This command is added for some simple testing only. It turns on/off
762 * L2 cache regardless of L1 cache state. The side effect of this is
763 * when doing any flash operations such as "fis init", the L2
764 * will be turned back on along with L1 caches even though it is off
765 * by using this command.
773 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]);
794 HAL_L2CACHE_IS_ENABLED(L2cache_on);
795 diag_printf("L2 cache: %s\n", L2cache_on?"On":"Off");
798 #endif //L2CC_ENABLED
800 #define IIM_ERR_SHIFT 8
801 #define POLL_FUSE_PRGD (IIM_STAT_PRGD | (IIM_ERR_PRGE << IIM_ERR_SHIFT))
802 #define POLL_FUSE_SNSD (IIM_STAT_SNSD | (IIM_ERR_SNSE << IIM_ERR_SHIFT))
804 static void fuse_op_start(void)
806 /* Do not generate interrupt */
807 writel(0, IIM_BASE_ADDR + IIM_STATM_OFF);
808 // clear the status bits and error bits
809 writel(0x3, IIM_BASE_ADDR + IIM_STAT_OFF);
810 writel(0xFE, IIM_BASE_ADDR + IIM_ERR_OFF);
814 * The action should be either:
819 static int poll_fuse_op_done(int action)
823 if (action != POLL_FUSE_PRGD && action != POLL_FUSE_SNSD) {
824 diag_printf("%s(%d) invalid operation\n", __FUNCTION__, action);
828 /* Poll busy bit till it is NOT set */
829 while ((readl(IIM_BASE_ADDR + IIM_STAT_OFF) & IIM_STAT_BUSY) != 0 ) {
832 /* Test for successful write */
833 status = readl(IIM_BASE_ADDR + IIM_STAT_OFF);
834 error = readl(IIM_BASE_ADDR + IIM_ERR_OFF);
836 if ((status & action) != 0 && (error & (action >> IIM_ERR_SHIFT)) == 0) {
838 diag_printf("Even though the operation seems successful...\n");
839 diag_printf("There are some error(s) at addr=0x%08lx: 0x%08x\n",
840 (IIM_BASE_ADDR + IIM_ERR_OFF), error);
844 diag_printf("%s(%d) failed\n", __FUNCTION__, action);
845 diag_printf("status address=0x%08lx, value=0x%08x\n",
846 (IIM_BASE_ADDR + IIM_STAT_OFF), status);
847 diag_printf("There are some error(s) at addr=0x%08lx: 0x%08x\n",
848 (IIM_BASE_ADDR + IIM_ERR_OFF), error);
852 static unsigned int sense_fuse(int bank, int row, int bit)
854 int addr, addr_l, addr_h, reg_addr;
858 addr = ((bank << 11) | (row << 3) | (bit & 0x7));
859 /* Set IIM Program Upper Address */
860 addr_h = (addr >> 8) & 0x000000FF;
861 /* Set IIM Program Lower Address */
862 addr_l = (addr & 0x000000FF);
864 #ifdef IIM_FUSE_DEBUG
865 diag_printf("%s: addr_h=0x%x, addr_l=0x%x\n",
866 __FUNCTION__, addr_h, addr_l);
868 writel(addr_h, IIM_BASE_ADDR + IIM_UA_OFF);
869 writel(addr_l, IIM_BASE_ADDR + IIM_LA_OFF);
871 writel(0x8, IIM_BASE_ADDR + IIM_FCTL_OFF);
872 if (poll_fuse_op_done(POLL_FUSE_SNSD) != 0) {
873 diag_printf("%s(bank: %d, row: %d, bit: %d failed\n",
874 __FUNCTION__, bank, row, bit);
876 reg_addr = IIM_BASE_ADDR + IIM_SDAT_OFF;
877 diag_printf("fuses at (bank:%d, row:%d) = 0x%08x\n", bank, row, readl(reg_addr));
878 return readl(reg_addr);
881 void do_fuse_read(int argc, char *argv[])
883 unsigned long bank, row;
884 unsigned long fuse_val;
887 diag_printf("Usage: fuse_read <bank> <row>\n");
889 } else if (argc == 3) {
890 if (!parse_num(*(&argv[1]), &bank, &argv[1], " ")) {
891 diag_printf("Error: Invalid parameter\n");
894 if (!parse_num(*(&argv[2]), &row, &argv[2], " ")) {
895 diag_printf("Error: Invalid parameter\n");
899 diag_printf("Read fuse at bank:%ld row:%ld\n", bank, row);
900 fuse_val = sense_fuse(bank, row, 0);
901 diag_printf("fuses at (bank:%ld, row:%ld) = 0x%lx\n", bank, row, fuse_val);
903 diag_printf("Passing in wrong arguments: %d\n", argc);
904 diag_printf("Usage: fuse_read <bank> <row>\n");
908 /* Blow fuses based on the bank, row and bit positions (all 0-based)
910 int fuse_blow(int bank,int row,int bit)
912 int addr, addr_l, addr_h, ret = -1;
916 /* Disable IIM Program Protect */
917 writel(0xAA, IIM_BASE_ADDR + IIM_PREG_P_OFF);
919 addr = ((bank << 11) | (row << 3) | (bit & 0x7));
920 /* Set IIM Program Upper Address */
921 addr_h = (addr >> 8) & 0x000000FF;
922 /* Set IIM Program Lower Address */
923 addr_l = (addr & 0x000000FF);
925 #ifdef IIM_FUSE_DEBUG
926 diag_printf("blowing addr_h=0x%x, addr_l=0x%x\n", addr_h, addr_l);
929 writel(addr_h, IIM_BASE_ADDR + IIM_UA_OFF);
930 writel(addr_l, IIM_BASE_ADDR + IIM_LA_OFF);
931 /* Start Programming */
932 writel(0x31, IIM_BASE_ADDR + IIM_FCTL_OFF);
933 if (poll_fuse_op_done(POLL_FUSE_PRGD) == 0) {
937 /* Enable IIM Program Protect */
938 writel(0x0, IIM_BASE_ADDR + IIM_PREG_P_OFF);
943 * This command is added for burning IIM fuses
945 RedBoot_cmd("fuse_read",
951 RedBoot_cmd("fuse_blow",
953 "<bank> <row> <value>",
957 void quick_itoa(u32 num, char *a)
960 for (i = 0; i <= 7; i++) {
961 j = (num >> (4 * i)) & 0xF;
962 k = (j < 10) ? '0' : ('a' - 0xa);
967 // slen - streng length, e.g.: 23 -> slen=2; abcd -> slen=4
968 // only convert hex value as string input. so "12" is 0x12.
969 u32 quick_atoi(char *a, u32 slen)
971 u32 i, num = 0, digit;
973 for (i = 0; i < slen; i++) {
974 if (a[i] >= '0' && a[i] <= '9') {
976 } else if (a[i] >= 'a' && a[i] <= 'f') {
977 digit = a[i] - 'a' + 10;
978 } else if (a[i] >= 'A' && a[i] <= 'F') {
979 digit = a[i] - 'A' + 10;
981 diag_printf("ERROR: %c\n", a[i]);
984 num = (num * 16) + digit;
989 static void fuse_blow_row(int bank, int row, int value)
994 reg = readl(CCM_BASE_ADDR + 0x64);
996 writel(reg, CCM_BASE_ADDR + 0x64);
998 for (i = 0; i < 8; i++) {
999 if (((value >> i) & 0x1) == 0) {
1002 if (fuse_blow(bank, row, i) != 0) {
1003 diag_printf("fuse_blow(bank: %d, row: %d, bit: %d failed\n",
1008 writel(reg, CCM_BASE_ADDR + 0x64);
1011 void do_fuse_blow(int argc, char *argv[])
1013 unsigned long bank, row, value, i;
1014 unsigned int fuse_val;
1019 diag_printf("It is too dangeous for you to use this command.\n");
1024 if (strcasecmp(argv[1], "scc") == 0) {
1025 // fuse_blow scc C3D153EDFD2EA9982226EF5047D3B9A0B9C7138EA87C028401D28C2C2C0B9AA2
1026 diag_printf("Ready to burn SCC fuses\n");
1031 value = quick_atoi(val, 2);
1032 // diag_printf("fuse_blow_row(2, %d, value=0x%x)\n", i, value);
1033 fuse_blow_row(2, i, value);
1035 if ((++s)[0] == '\0') {
1036 diag_printf("ERROR: Odd string input\n");
1039 if ((++s)[0] == '\0') {
1040 diag_printf("Successful\n");
1044 } else if (strcasecmp(argv[1], "srk") == 0) {
1045 // fuse_blow srk 418bccd09b53bee1ab59e2662b3c7877bc0094caee201052add49be8780dff95
1046 diag_printf("Ready to burn SRK key fuses\n");
1051 value = quick_atoi(val, 2);
1053 fuse_blow_row(1, 1, value); // 0x41 goes to SRK_HASH[255:248], bank 1, row 1
1055 fuse_blow_row(3, i, value); // 0x8b in SRK_HASH[247:240] bank 3, row 1
1056 // 0xcc in SRK_HASH[239:232] bank 3, row 2
1058 if ((++s)[0] == '\0') {
1059 diag_printf("ERROR: Odd string input\n");
1062 if ((++s)[0] == '\0') {
1063 diag_printf("Successful\n");
1068 diag_printf("This command is not supported\n");
1071 } else if (argc == 4) {
1072 if (!parse_num(*(&argv[1]), (unsigned long *)&bank, &argv[1], " ")) {
1073 diag_printf("Error: Invalid parameter\n");
1076 if (!parse_num(*(&argv[2]), &row, &argv[2], " ")) {
1077 diag_printf("Error: Invalid parameter\n");
1080 if (!parse_num(*(&argv[3]), &value, &argv[3], " ")) {
1081 diag_printf("Error: Invalid parameter\n");
1085 diag_printf("Blowing fuse at bank:%ld row:%ld value:%ld\n",
1087 fuse_blow_row(bank, row, value);
1088 fuse_val = sense_fuse(bank, row, 0);
1089 diag_printf("fuses at (bank:%ld, row:%ld) = 0x%x\n", bank, row, fuse_val);
1092 diag_printf("Passing in wrong arguments: %d\n", argc);
1096 /* precondition: m>0 and n>0. Let g=gcd(m,n). */
1097 int gcd(int m, int n)
1101 if(n > m) {t = m; m = n; n = t;} /* swap */
1107 int read_mac_addr_from_fuse(unsigned char* data)
1109 data[0] = sense_fuse(1, 9, 0) ;
1110 data[1] = sense_fuse(1, 10, 0) ;
1111 data[2] = sense_fuse(1, 11, 0) ;
1112 data[3] = sense_fuse(1, 12, 0) ;
1113 data[4] = sense_fuse(1, 13, 0) ;
1114 data[5] = sense_fuse(1, 14, 0) ;
1116 if ((data[0] == 0) && (data[1] == 0) && (data[2] == 0) &&
1117 (data[3] == 0) && (data[4] == 0) && (data[5] == 0)) {
1125 void imx_power_mode(int mode)
1127 volatile unsigned int val;
1130 writel(0x0000030f, GPC_PGR);
1131 writel(0x1, SRPGCR_EMI);
1132 writel(0x1, SRPGCR_ARM);
1133 writel(0x1, PGC_PGCR_VPU);
1134 writel(0x1, PGC_PGCR_IPU);
1138 // stop mode - from validation code
1139 // Set DSM_INT_HOLDOFF bit in TZIC
1140 // If the TZIC didn't write the bit then there was interrupt pending
1141 // It will be serviced while we're in the loop
1142 // So we write to this bit again
1143 while (readl(INTC_BASE_ADDR + 0x14) == 0) {
1144 writel(1, INTC_BASE_ADDR + 0x14);
1154 diag_printf("Entering stop mode\n");
1155 val = readl(CCM_BASE_ADDR + 0x74);
1156 val = (val & 0xfffffffc) | 0x2; // set STOP mode
1157 writel(val, CCM_BASE_ADDR + 0x74);
1158 val = readl(PLATFORM_LPC_REG);
1159 writel(val | (1 << 16), PLATFORM_LPC_REG);// ENABLE DSM in ELBOW submodule of ARM platform
1160 writel(val | (1 << 17), PLATFORM_LPC_REG);// ENABLE DSM in ELBOW submodule of ARM platform
1167 asm("mcr p15, 0, r1, c7, c0, 4");
1170 void do_power_mode(int argc, char *argv[])
1175 diag_printf("Usage: power_mode <mode>\n");
1177 } else if (argc == 2) {
1178 if (!parse_num(*(&argv[1]), (unsigned long *)&mode, &argv[1], " ")) {
1179 diag_printf("Error: Invalid parameter\n");
1182 diag_printf("Entering power mode: %d\n", mode);
1183 imx_power_mode(mode);
1186 diag_printf("Passing in wrong arguments: %d\n", argc);
1187 diag_printf("Usage: power_mode <mode>\n");
1192 * This command is added for burning IIM fuses
1194 RedBoot_cmd("power_mode",
1195 "Enter various power modes:",
1200 " <3> - STOP with Power-Gating\n"
1201 " -- need reset after issuing the command",
1206 /* Super Root key moduli */
1207 static const UINT8 hab_super_root_moduli[] = {
1209 0xb9, 0x84, 0xc8, 0x8a, 0xd3, 0x7e, 0xcc, 0xc0, 0xe7, 0x3e, 0x11, 0x53,
1210 0x6b, 0x5e, 0xea, 0xf4, 0xd9, 0xac, 0x5a, 0x63, 0x8a, 0x79, 0x96, 0x83,
1211 0xb1, 0x39, 0xb2, 0x6f, 0x9c, 0x54, 0x87, 0xf4, 0x3b, 0x9e, 0xd8, 0x0f,
1212 0x89, 0xf5, 0x01, 0x53, 0xb8, 0xe2, 0xcc, 0x75, 0x0d, 0xe1, 0x13, 0xfa,
1213 0xa7, 0xb9, 0x1e, 0xff, 0x6a, 0x05, 0xdb, 0x58, 0x10, 0xbf, 0x2b, 0xf4,
1214 0xe7, 0x0a, 0x63, 0x82, 0x2c, 0xa3, 0xb5, 0x0a, 0x72, 0x1c, 0xdc, 0x29,
1215 0xc1, 0x81, 0xb5, 0x9a, 0xf0, 0x25, 0x7d, 0xd6, 0xee, 0x01, 0x64, 0xc7,
1216 0x07, 0x2d, 0xcb, 0x31, 0x4c, 0x8d, 0x82, 0xf6, 0x44, 0x95, 0x4a, 0xbc,
1217 0xae, 0xe8, 0x2a, 0x89, 0xd4, 0xf2, 0x66, 0x72, 0x2b, 0x09, 0x4e, 0x56,
1218 0xe9, 0xbf, 0x5e, 0x38, 0x5c, 0xd5, 0x7e, 0x15, 0x55, 0x86, 0x0f, 0x19,
1219 0xf6, 0x00, 0xee, 0xa1, 0x92, 0x78, 0xef, 0x93, 0xcb, 0xfa, 0xb4, 0x98,
1220 0x19, 0xef, 0x10, 0x70, 0xde, 0x36, 0x1c, 0x12, 0x2e, 0xd2, 0x09, 0xc7,
1221 0x7b, 0xd1, 0xaa, 0xd3, 0x46, 0x65, 0xa1, 0x5b, 0xee, 0xa5, 0x96, 0x97,
1222 0x98, 0x3e, 0xfc, 0xf8, 0x74, 0x22, 0x51, 0xe7, 0xf1, 0x2f, 0x30, 0x79,
1223 0x13, 0xe5, 0x42, 0xc6, 0x7c, 0x18, 0x76, 0xd3, 0x7f, 0x5a, 0x13, 0xde,
1224 0x2f, 0x51, 0x07, 0xfa, 0x93, 0xfe, 0x10, 0x8a, 0x0c, 0x18, 0x60, 0x3c,
1225 0xff, 0x6a, 0x9b, 0xe7, 0x10, 0x2d, 0x71, 0xd2, 0x34, 0xc0, 0xdf, 0xbe,
1226 0x17, 0x4e, 0x75, 0x40, 0x83, 0xaa, 0x90, 0xd1, 0xed, 0xbd, 0xbf, 0xac,
1227 0x9a, 0x30, 0xbd, 0x69, 0x4d, 0xd8, 0x00, 0x63, 0x92, 0x69, 0x98, 0xf8,
1228 0x89, 0xdc, 0x7b, 0xe3, 0x66, 0x7e, 0xdd, 0xfa, 0x8c, 0x74, 0xe2, 0xb1,
1229 0xeb, 0x94, 0xf7, 0xab, 0x0e, 0x92, 0x06, 0xab, 0x60, 0xe5, 0x00, 0x43,
1230 0xb2, 0x5e, 0x6e, 0xeb
1233 /* Super Root key */
1234 const hab_rsa_public_key hab_super_root_key[] = {
1237 /* RSA public exponent, right-padded */
1238 0x01, 0x00, 0x01, 0x00,
1240 /* pointer to modulus data */
1241 hab_super_root_moduli,
1242 /* Exponent size in bytes */
1244 /* Modulus size in bytes */
1246 /* Key data valid */