1 //==========================================================================
5 // SoC [platform] specific RedBoot commands
7 //==========================================================================
8 //####ECOSGPLCOPYRIGHTBEGIN####
9 // -------------------------------------------
10 // This file is part of eCos, the Embedded Configurable Operating System.
11 // Copyright (C) 1998, 1999, 2000, 2001, 2002 Red Hat, Inc.
13 // eCos is free software; you can redistribute it and/or modify it under
14 // the terms of the GNU General Public License as published by the Free
15 // Software Foundation; either version 2 or (at your option) any later version.
17 // eCos is distributed in the hope that it will be useful, but WITHOUT ANY
18 // WARRANTY; without even the implied warranty of MERCHANTABILITY or
19 // FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
22 // You should have received a copy of the GNU General Public License along
23 // with eCos; if not, write to the Free Software Foundation, Inc.,
24 // 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
26 // As a special exception, if other files instantiate templates or use macros
27 // or inline functions from this file, or you compile this file and link it
28 // with other works to produce a work based on this file, this file does not
29 // by itself cause the resulting work to be covered by the GNU General Public
30 // License. However the source code for this file must still be made available
31 // in accordance with section (3) of the GNU General Public License.
33 // This exception does not invalidate any other reasons why a work based on
34 // this file might be covered by the GNU General Public License.
36 // Alternative licenses for eCos may be arranged by contacting Red Hat, Inc.
37 // at http://sources.redhat.com/ecos/ecos-license/
38 // -------------------------------------------
39 //####ECOSGPLCOPYRIGHTEND####
40 //==========================================================================
42 #include <cyg/hal/hal_intr.h>
43 #include <cyg/hal/plf_mmap.h>
44 #include <cyg/hal/hal_soc.h> // Hardware definitions
45 #include <cyg/hal/hal_cache.h>
47 typedef unsigned long long u64;
48 typedef unsigned int u32;
49 typedef unsigned short u16;
50 typedef unsigned char u8;
52 #define SZ_DEC_1M 1000000
53 #define PLL_PD_MAX 16 //actual pd+1
54 #define PLL_MFI_MAX 15
56 #define PLL_MFD_MAX 1024 //actual mfd+1
57 #define PLL_MFN_MAX 511
58 #define NFC_PODF_MAX 16
61 #define PLL_FREQ_MAX (2 * PLL_REF_CLK * PLL_MFI_MAX)
62 #define PLL_FREQ_MIN ((2 * PLL_REF_CLK * (PLL_MFI_MIN - 1)) / PLL_PD_MAX)
63 #define AHB_CLK_MAX 133333333
64 #define IPG_CLK_MAX (AHB_CLK_MAX / 2)
65 #define NFC_CLK_MAX 25000000
66 // IPU-HSP clock is independent of the HCLK and can go up to 177MHz but requires
67 // higher voltage support. For simplicity, limit it to 133MHz
68 #define HSP_CLK_MAX 178000000
70 #define ERR_WRONG_CLK -1
74 #define ERR_NO_PRESC -5
75 #define ERR_NO_AHB_DIV -6
77 #define ARM_DIV_OFF 16
81 #define CLOCK_PATH_FIELD(arm, ahb, sel) \
82 (((arm) << ARM_DIV_OFF) + ((ahb) << AHB_DIV_OFF) + ((sel) << ARM_SEL_OFF))
84 static unsigned int clock_auto_path[8] =
86 CLOCK_PATH_FIELD(1, 3, 0), CLOCK_PATH_FIELD(1, 2, 1),
87 CLOCK_PATH_FIELD(2, 1, 1), -1,
88 CLOCK_PATH_FIELD(1, 6, 0), CLOCK_PATH_FIELD(1, 4, 1),
89 CLOCK_PATH_FIELD(2, 2, 1), -1,
92 static unsigned int clock_consumer_path[16] =
94 CLOCK_PATH_FIELD(1, 4, 0), CLOCK_PATH_FIELD(1, 3, 1),
95 CLOCK_PATH_FIELD(2, 2, 0), -1,
97 CLOCK_PATH_FIELD(4, 1, 0), CLOCK_PATH_FIELD(1, 5, 0),
98 CLOCK_PATH_FIELD(1, 8, 0), CLOCK_PATH_FIELD(1, 6, 1),
99 CLOCK_PATH_FIELD(2, 4, 0), -1,
101 CLOCK_PATH_FIELD(4, 2, 0), -1,
104 static int hsp_div_table[3][16] =
106 {4, 3, 2, -1, -1, -1, 1, 5, 4, 3, 2, -1, -1, -1, 1, -1},
107 {-1, -1, -1, -1, -1, -1, -1, -1, 8, 6, 4, -1, -1, -1, 2, -1},
108 {3, -1, -1, -1, -1, -1, -1, -1, 3, -1, -1, -1, -1, -1, -1, -1},
111 u32 pll_clock(enum plls pll);
112 u32 get_main_clock(enum main_clocks clk);
113 u32 get_peri_clock(enum peri_clocks clk);
115 static u32 pll_mfd_fixed;
117 static void clock_setup(int argc, char *argv[]);
118 static void clko(int argc, char *argv[]);
119 extern unsigned int g_clock_src;
120 extern unsigned int system_rev;
123 "Setup/Display clock (max AHB=133MHz, max IPG=66.5MHz)\nSyntax:",
124 "[<ARM core clock in MHz> [:<ARM-AHB-IPG clock selection>[:<HSP selection>]]] \n\n\
125 If a selection is zero or no selectin is specified, the optimal divider values \n\
126 will be chosen. Examples:\n\
127 [clock] -> Show various clocks\n\
128 [clock 532] -> Core=532 AHB=133 IPG=66.5 HSP=133\n\
129 [clock 399] -> Core=399 AHB=133 IPG=66.5 HSP=133\n\
130 [clock 532:?] -> show ARM-AHB-IPG clock selections\n\
131 [clock 532:8] -> Core=532 AHB=66.5 IPG=33.25 HSP=133\n\
132 [clock 532:8:?] -> show HSP selection\n\
133 [clock 532:8:2] -> Core=532 AHB=66.5 IPG=33.25 HSP=178\n",
137 static char consume_core_clocks[] =
138 " selection of consumer path ARM clock source\n\
139 ========ARM\t AHB \t IPG ========\n\
140 <01> - 532\t 133 \t 66.5\n\
141 <02> - 399\t 133 \t 66.5\n\
142 <03> - 266\t 133 \t 66.5\n\
143 <07> - 133\t 133 \t 66.5\n\
144 <08> - 665\t 133 \t 66.5\n\
145 <09> - 532\t 66.5\t33.25\n\
146 <10> - 399\t 66.5\t33.25\n\
147 <11> - 266\t 66.5\t33.25\n\
148 <15> - 133\t 66.5\t33.25\n\
149 Other selection value can't be configured";
151 static char auto_core_clocks[] =
152 " selection of auto path ARM clock source\n\
153 ========ARM\t AHB \t IPG ========\n\
154 <1> - 399\t 133 \t 66.5\n\
155 <2> - 266\t 133 \t 66.5\n\
156 <3> - 133\t 133 \t 66.5\n\
157 <5> - 399\t 66.5\t33.25\n\
158 <6> - 266\t 66.5\t33.25\n\
159 <7> - 133\t 66.5\t33.25\n\
160 Other selection value can't be configured";
162 static char consume_hsp_clocks[] =
163 " selection of consumer path hsp clock source\n\
164 ========HSP ========\n\
168 Other selection value can't be configured";
170 static inline unsigned long decode_root_clocks(int mode, int pll, int index, int arm)
172 unsigned int * p, max, arm_div, ahb_div = 1;
174 p = clock_consumer_path;
175 max = sizeof(clock_consumer_path)/sizeof(clock_consumer_path[0]);
178 max = sizeof(clock_auto_path)/sizeof(clock_auto_path[0]);
180 if(index >= max || p[index] == -1) return 0;
182 arm_div = (p[index] >> 16)&0xFF;
184 ahb_div = (p[index] >> 8)&0xFF;
186 if(!(p[index]&0xFF)) {
187 return pll/(arm_div*ahb_div);
190 return (pll*3)/(arm_div*ahb_div*4);
192 return (pll*2)/(arm_div*ahb_div*3);
195 static inline unsigned long calc_pll_base_core(unsigned long core, unsigned int pdr0)
197 unsigned int * p, arm_div, index;
198 if(pdr0 & CLKMODE_CONSUMER) {
199 p = clock_consumer_path;
200 index = (pdr0 >> 16) & 0xF;
203 index = (pdr0 >> 9) & 7;
206 arm_div = (p[index] >> 16)&0xFF;
207 if(!(p[index]&0xFF)) {
210 if(pdr0 & CLKMODE_CONSUMER) {
211 return (core*arm_div*4)/3;
213 return (core*arm_div*3)/2;
216 static unsigned long get_arm_ahb_clock(int arm, unsigned long pdr0)
218 int mode = pdr0 & CLKMODE_CONSUMER, cfg;
221 cfg = (pdr0 >> 16) & 0xF;
223 cfg = (pdr0 >> 9) & 0x7;
225 pll = pll_clock(MCU_PLL);
226 return decode_root_clocks(mode, pll, cfg, arm);
230 * This is to calculate various parameters based on reference clock and
231 * targeted clock based on the equation:
232 * t_clk = 2*ref_freq*(mfi + mfn/(mfd+1))/(pd+1)
233 * This calculation is based on a fixed MFD value for simplicity.
235 * @param ref reference clock freq
236 * @param target targeted clock in HZ
237 * @param p_pd calculated pd value (pd value from register + 1) upon return
238 * @param p_mfi calculated actual mfi value upon return
239 * @param p_mfn calculated actual mfn value upon return
240 * @param p_mfd fixed mfd value (mfd value from register + 1) upon return
242 * @return 0 if successful; non-zero otherwise.
244 int calc_pll_params(u32 ref, u32 target, u32 *p_pd,
245 u32 *p_mfi, u32 *p_mfn, u32 *p_mfd)
247 u64 pd, mfi, mfn, n_target = (u64)target, n_ref = (u64)ref;
249 pll_mfd_fixed = 24 * 16;
251 // Make sure targeted freq is in the valid range. Otherwise the
252 // following calculation might be wrong!!!
253 if (target < PLL_FREQ_MIN || target > PLL_FREQ_MAX) {
254 return ERR_WRONG_CLK;
256 // Use n_target and n_ref to avoid overflow
257 for (pd = 1; pd <= PLL_PD_MAX; pd++) {
258 mfi = (n_target * pd) / (2 * n_ref);
259 if (mfi > PLL_MFI_MAX) {
261 } else if (mfi < 5) {
266 // Now got pd and mfi already
267 mfn = (((n_target * pd) / 2 - n_ref * mfi) * pll_mfd_fixed) / n_ref;
268 // Check mfn within limit and mfn < denominator
269 if (mfn > PLL_MFN_MAX || mfn >= pll_mfd_fixed) {
273 if (pd > PLL_PD_MAX) {
279 *p_mfd = pll_mfd_fixed;
284 * This function assumes the expected core clock has to be changed by
285 * modifying the PLL. This is NOT true always but for most of the times,
286 * it is. So it assumes the PLL output freq is the same as the expected
287 * core clock (presc=1) unless the core clock is less than PLL_FREQ_MIN.
288 * In the latter case, it will try to increase the presc value until
289 * (presc*core_clk) is greater than PLL_FREQ_MIN. It then makes call to
290 * calc_pll_params() and obtains the values of PD, MFI,MFN, MFD based
291 * on the targeted PLL and reference input clock to the PLL. Lastly,
292 * it sets the register based on these values along with the dividers.
293 * Note 1) There is no value checking for the passed-in divider values
294 * so the caller has to make sure those values are sensible.
295 * 2) Also adjust the NFC divider such that the NFC clock doesn't
296 * exceed NFC_CLK_MAX.
297 * 3) IPU HSP clock is independent of AHB clock. Even it can go up to
298 * 177MHz for higher voltage, this function fixes the max to 133MHz.
299 * 4) This function should not have allowed diag_printf() calls since
300 * the serial driver has been stoped. But leave then here to allow
301 * easy debugging by NOT calling the cyg_hal_plf_serial_stop().
303 * @param ref pll input reference clock (32KHz or 26MHz)
304 * @param core_clk core clock in Hz
305 * @param ahb_div ahb divider to divide the core clock to get ahb clock
306 * (ahb_div - 1) needs to be set in the register
307 * @param ipg_div ipg divider to divide the ahb clock to get ipg clock
308 * (ipg_div - 1) needs to be set in the register
309 # @return 0 if successful; non-zero otherwise
311 int configure_clock(u32 ref, u32 core_clk, u32 ahb_clk, u32 pdr0)
313 u32 pll, pd, mfi, mfn, mfd, brmo = 0, mpctl0;
317 pll = calc_pll_base_core(core_clk, pdr0);
319 if((pll < PLL_FREQ_MIN ) || (pll > PLL_FREQ_MAX)) {
320 return ERR_WRONG_CLK;
322 // get nfc_div - make sure optimal NFC clock but less than NFC_CLK_MAX
323 for (nfc_div = 1; nfc_div <= NFC_PODF_MAX; nfc_div++) {
324 if ((ahb_clk/ nfc_div) <= NFC_CLK_MAX) {
329 // pll is now the targeted pll output. Use it along with ref input clock
330 // to get pd, mfi, mfn, mfd
331 if ((ret = calc_pll_params(ref, pll, &pd, &mfi, &mfn, &mfd)) != 0) {
332 diag_printf("can't find pll(%d) parameters: %d\n", pll, ret);
335 #ifdef CMD_CLOCK_DEBUG
336 diag_printf("ref=%d, pll=%d, pd=%d, mfi=%d,mfn=%d, mfd=%d\n",
337 ref, pll, pd, mfi, mfn, mfd);
340 // blindly increase divider first to avoid too fast ahbclk and ipgclk
341 // in case the core clock increases too much
342 pdr4 = readl(CCM_BASE_ADDR + CLKCTL_PDR4);
344 // increase the dividers. should work even when core clock is 832 (26*2*16)MHz
345 // which is unlikely true.
346 pdr4 |= (nfc_div -1) << 28;
348 // update PLL register
349 if ((mfd >= (10 * mfn)) || ((10 * mfn) >= (9 * mfd)))
352 mpctl0 = readl(CCM_BASE_ADDR + CLKCTL_MPCTL);
353 mpctl0 = (mpctl0 & 0x4000C000) |
359 writel(mpctl0, CCM_BASE_ADDR + CLKCTL_MPCTL);
360 writel(pdr0, CCM_BASE_ADDR + CLKCTL_PDR0);
361 writel(pdr4, CCM_BASE_ADDR + CLKCTL_PDR4);
362 // add some delay for new values to take effect
363 for (i = 0; i < 10000; i++);
367 static int clock_setup_polling(u32 * params, u32 * ahb_clk, u32 * hsp_clk, u32 * pdr0)
369 u32 ahb_div, hsp_div;
370 diag_printf("data[0]=%d, data[1]=%d, data[2]=%d\n", params[0], params[1], params[2]);
374 if((*pdr0) & CLKMODE_CONSUMER) {
375 if((params[1] > 16) || (clock_consumer_path[params[1] - 1] == -1)) {
376 diag_printf("Error: Invalid arm source selection in consumer path\n");
379 ahb_div = (clock_consumer_path[params[1] - 1] >> AHB_DIV_OFF) & 0xFF;
381 if((params[1] > 8) || (clock_auto_path[params[1] -1 ] == -1)) {
382 diag_printf("Error: Invalid arm source selection in auto path\n");
385 ahb_div = (clock_auto_path[params[1] - 1] >> AHB_DIV_OFF) & 0xFF;
388 if(((*pdr0) & CLKMODE_CONSUMER)){
389 if(!params[2]) params[2] = ((*pdr0 >> 20) & 0x3) + 1;
390 if((params[2] > 3) || (hsp_div_table[params[2] - 1][params[1] -1] == -1)) {
391 diag_printf("Error: current hsp source selection[%d] in current core path is invalid\n", params[2]);
396 if (params[0] < (PLL_FREQ_MIN / PRESC_MAX) || params[0] > PLL_FREQ_MAX) {
397 diag_printf("Targeted core clock should be within [%d - %d]\n",
398 PLL_FREQ_MIN / PRESC_MAX, PLL_FREQ_MAX);
402 if ((params[0] / ahb_div) > AHB_CLK_MAX) {
403 diag_printf("Can't make AHB=%d since max=%d\n",
404 params[0] / ahb_div, AHB_CLK_MAX);
409 *ahb_clk = params[0] / ahb_div;
410 if((*pdr0) & CLKMODE_CONSUMER) {
411 *hsp_clk = params[0] /hsp_div_table[params[2] - 1][params[1] -1];
412 *pdr0 &= ~((0x3<<20) | (0xF<<16));
413 *pdr0 |= ((params[2] - 1)<< 20) | (params[1] -1) << 16;
416 *pdr0 &= ~(0x7 << 9);
417 *pdr0 |= (params[1] -1) << 9;
425 static void clock_setup(int argc,char *argv[])
428 u32 pdr0 = readl(CCM_BASE_ADDR + CLKCTL_PDR0);
429 u32 i, data[3], temp, ahb_clk, hsp_clk;
431 if (system_rev & (0x2 << 4)) /* consumer path only in TO2.0 */
437 memset(data, 0, sizeof(u32)*3);
438 for (i = 0; i < 3; i++) {
439 if (!parse_num(*(&argv[1]), (unsigned long *)&temp, &argv[1], ":")) {
440 if(*argv[1] == '?') {
443 diag_printf("ARM-AHB-IPG clock selections:\n");
444 if(pdr0 & CLKMODE_CONSUMER) {
445 diag_printf("%s\n", consume_core_clocks);
447 diag_printf("%s\n", auto_core_clocks);
451 diag_printf("HSP clock selections:\n");
452 if(pdr0 & CLKMODE_CONSUMER) {
453 diag_printf("%s\n", consume_hsp_clocks);
455 diag_printf("In auto path, HSP clock always is same as AHB clock.\n");
460 diag_printf("Error: Invalid parameter\n");
466 data[0] = data[0] * SZ_DEC_1M;
468 if(clock_setup_polling(data, &ahb_clk, &hsp_clk, &pdr0)) return;
469 diag_printf("Trying to set core=%d ahb=%d ipg=%d hsp=%d...\n",
470 data[0], ahb_clk, ahb_clk/2, hsp_clk);
471 diag_printf("Current pdr0=%x\n", pdr0);
472 // stop the serial to be ready to adjust the clock
473 hal_delay_us(100000);
474 cyg_hal_plf_serial_stop();
476 ret = configure_clock(PLL_REF_CLK, data[0], ahb_clk, pdr0);
477 // restart the serial driver
478 cyg_hal_plf_serial_init();
479 hal_delay_us(100000);
482 diag_printf("Failed to setup clock: %d\n", ret);
485 diag_printf("\n<<<New clock setting>>>\n");
486 // Now printing clocks
488 diag_printf("\nMPLL\t\tPPLL\n");
489 diag_printf("========================================\n");
490 diag_printf("%-16d%-16d\n\n", pll_clock(MCU_PLL), pll_clock(PER_PLL));
491 diag_printf("CPU\t\tAHB\t\tIPG\t\tIPG_PER\n");
492 diag_printf("========================================================\n");
493 diag_printf("%-16d%-16d%-16d%-16d\n\n",
494 get_main_clock(CPU_CLK),
495 get_main_clock(AHB_CLK),
496 get_main_clock(IPG_CLK),
497 get_main_clock(IPG_PER_CLK));
499 diag_printf("NFC\t\tUSB\t\tIPU-HSP\n");
500 diag_printf("========================================\n");
501 diag_printf("%-16d%-16d%-16d\n\n",
502 get_main_clock(NFC_CLK),
503 get_main_clock(USB_CLK),
504 get_main_clock(HSP_CLK));
506 diag_printf("UART1-3\t\tSSI1\t\tSSI2\t\tCSI\n");
507 diag_printf("===========================================");
508 diag_printf("=============\n");
510 diag_printf("%-16d%-16d%-16d%-16d\n\n",
511 get_peri_clock(UART1_BAUD),
512 get_peri_clock(SSI1_BAUD),
513 get_peri_clock(SSI2_BAUD),
514 get_peri_clock(CSI_BAUD));
516 diag_printf("MSHC\t\tESDHC1\t\tESDHC2\t\tESDHC3\n");
517 diag_printf("===========================================");
518 diag_printf("=============\n");
520 diag_printf("%-16d%-16d%-16d%-16d\n\n",
521 get_peri_clock(MSHC_CLK),
522 get_peri_clock(ESDHC1_CLK),
523 get_peri_clock(ESDHC2_CLK),
524 get_peri_clock(ESDHC3_CLK));
526 diag_printf("SPDIF\t\t\n");
527 diag_printf("===========================================");
528 diag_printf("=============\n");
530 diag_printf("%-16d\n\n",
531 get_peri_clock(SPDIF_CLK));
532 diag_printf("IPG_PERCLK as baud clock for: UART1-5, I2C, SIM, OWIRE");
533 if (((readl(EPIT1_BASE_ADDR) >> 24) & 0x3) == 0x2) {
534 diag_printf(", EPIT");
536 if (((readl(GPT1_BASE_ADDR) >> 6) & 0x7) == 0x2) {
539 if (((readl(PWM_BASE_ADDR) >> 16) & 0x3) == 0x2) {
546 * This function returns the PLL output value in Hz based on pll.
548 u32 pll_clock(enum plls pll)
550 u64 mfi, mfn, mfd, pdf, ref_clk, pll_out, sign;
551 u64 reg = readl(pll);
553 pdf = (reg >> 26) & 0xF;
554 mfd = (reg >> 16) & 0x3FF;
555 mfi = (reg >> 10) & 0xF;
556 mfi = (mfi <= 5) ? 5: mfi;
558 sign = (mfn < 512) ? 0: 1;
559 mfn = (mfn < 512) ? mfn: (1024 - mfn);
561 ref_clk = g_clock_src;
564 pll_out = (2 * ref_clk * mfi + ((2 * ref_clk * mfn) / (mfd + 1))) /
567 pll_out = (2 * ref_clk * mfi - ((2 * ref_clk * mfn) / (mfd + 1))) /
575 * This function returns the main clock value in Hz.
577 u32 get_main_clock(enum main_clocks clk)
579 u32 ipg_pdf, nfc_pdf, hsp_podf;
580 u32 pll, ret_val = 0, usb_prdf, usb_podf, pdf;
582 u32 reg = readl(CCM_BASE_ADDR + CLKCTL_PDR0);
583 u32 reg4 = readl(CCM_BASE_ADDR + CLKCTL_PDR4);
585 if (system_rev & (0x2 << 4)) /* consumer path only in TO2.0 */
590 ret_val = get_arm_ahb_clock(1, reg);
593 ret_val = get_arm_ahb_clock(0, reg);
596 if( reg & CLKMODE_CONSUMER) {
597 hsp_podf = (reg >> 20) & 0x3;
598 pll = get_arm_ahb_clock(1, reg);
599 hsp_podf = hsp_div_table[hsp_podf][(reg>>16)&0xF];
601 ret_val = pll / hsp_podf;
603 diag_printf("mismatch HSP with ARM clock setting\n");
607 ret_val = get_arm_ahb_clock(0, reg);
611 ret_val = get_arm_ahb_clock(0, reg) / 2;
614 if(reg & 0x04000000) {
615 ipg_pdf = (reg >> 12) & 0x7;
616 ret_val = get_arm_ahb_clock(0, reg)/ (ipg_pdf + 1);
618 pdf = (((reg4 >> 16) & 0x7) + 1);
619 ipg_pdf = (((reg4 >> 19) & 0x7) + 1);
620 ret_val = get_arm_ahb_clock(1, reg)/(pdf * ipg_pdf);
624 nfc_pdf = (reg4 >> 28) & 0xF;
625 pll = get_arm_ahb_clock(0, reg);
627 ret_val = pll / (nfc_pdf + 1);
630 usb_prdf = (reg4 >> 25) & 0x7;
631 usb_podf = (reg4 >> 22) & 0x7;
633 pll = get_arm_ahb_clock(1, reg);
635 pll = pll_clock(PER_PLL);
637 ret_val = pll / ((usb_prdf + 1) * (usb_podf + 1));
640 diag_printf("Unknown clock: %d\n", clk);
648 * This function returns the peripheral clock value in Hz.
650 u32 get_peri_clock(enum peri_clocks clk)
652 u32 ret_val = 0, pdf, pre_pdf, clk_sel;
653 u32 mpdr2 = readl(CCM_BASE_ADDR + CLKCTL_PDR2);
654 u32 mpdr3 = readl(CCM_BASE_ADDR + CLKCTL_PDR3);
655 u32 mpdr4 = readl(CCM_BASE_ADDR + CLKCTL_PDR4);
661 clk_sel = mpdr3 & (1 << 14);
662 pre_pdf = (mpdr4 >> 13) & 0x7;
663 pdf = (mpdr4 >> 10) & 0x7;
664 ret_val = ((clk_sel != 0) ? get_main_clock(CPU_CLK) :
665 pll_clock(PER_PLL)) / ((pre_pdf + 1) * (pdf + 1));
668 pre_pdf = (mpdr2 >> 24) & 0x7;
670 clk_sel = mpdr2 & ( 1 << 6);
671 ret_val = ((clk_sel != 0) ? get_main_clock(CPU_CLK) :
672 pll_clock(PER_PLL)) / ((pre_pdf + 1) * (pdf + 1));
675 pre_pdf = (mpdr2 >> 27) & 0x7;
676 pdf = (mpdr2 >> 8)& 0x3F;
677 clk_sel = mpdr2 & ( 1 << 6);
678 ret_val = ((clk_sel != 0) ? get_main_clock(CPU_CLK) :
679 pll_clock(PER_PLL)) / ((pre_pdf + 1) * (pdf + 1));
682 clk_sel = mpdr2 & (1 << 7);
683 pre_pdf = (mpdr2 >> 16) & 0x7;
684 pdf = (mpdr2 >> 19) & 0x7;
685 ret_val = ((clk_sel != 0) ? get_main_clock(CPU_CLK) :
686 pll_clock(PER_PLL)) / ((pre_pdf + 1) * (pdf + 1));
690 pre_pdf = readl(CCM_BASE_ADDR + CLKCTL_PDR1);
691 clk_sel = (pre_pdf & 0x80);
692 pdf = (pre_pdf >> 22) & 0x3F;
693 pre_pdf = (pre_pdf >> 28) & 0x7;
694 ret_val = ((clk_sel != 0)? get_main_clock(CPU_CLK) :
695 pll_clock(PER_PLL)) / ((pre_pdf + 1) * (pdf + 1));
698 clk_sel = mpdr3 & 0x40;
700 pdf = (mpdr3>>3)&0x7;
701 ret_val = ((clk_sel != 0)? get_main_clock(CPU_CLK) :
702 pll_clock(PER_PLL)) / ((pre_pdf + 1) * (pdf + 1));
705 clk_sel = mpdr3 & 0x40;
706 pre_pdf = (mpdr3 >> 8)&0x7;
707 pdf = (mpdr3 >> 11)&0x7;
708 ret_val = ((clk_sel != 0)? get_main_clock(CPU_CLK) :
709 pll_clock(PER_PLL)) / ((pre_pdf + 1) * (pdf + 1));
712 clk_sel = mpdr3 & 0x40;
713 pre_pdf = (mpdr3 >> 16)&0x7;
714 pdf = (mpdr3 >> 19)&0x7;
715 ret_val = ((clk_sel != 0)? get_main_clock(CPU_CLK) :
716 pll_clock(PER_PLL)) / ((pre_pdf + 1) * (pdf + 1));
719 clk_sel = mpdr3 & 0x400000;
720 pre_pdf = (mpdr3 >> 29)&0x7;
721 pdf = (mpdr3 >> 23)&0x3F;
722 ret_val = ((clk_sel != 0)? get_main_clock(CPU_CLK) :
723 pll_clock(PER_PLL)) / ((pre_pdf + 1) * (pdf + 1));
726 diag_printf("%s(): This clock: %d not supported yet \n",
734 "Select clock source for CLKO (J11 on the CPU daughter card)",
735 " Default is 1/32 of ARM core\n\
736 <00> - display current clko selection \n\
737 <01> - async 32K clock \n\
738 <02> - input 24Mhz clock for pll ref(PLL_REF_CLK)\n\
739 <03> - input 24.576Mhz osc audio clk(AUDIO_REF_CLK) \n\
740 <04> - 1/32 mpll_divgen output 2x(MPLL_OUTPUT_2) \n\
741 <05> - 1/32 ppll_divgen output 0.75x(PPLL_OUTPUT_1) \n\
742 <06> - 1/32 mpll_divgen output 1x(MPLL_OUTPUT_1) \n\
743 <07> - 1/32 ppll output clock(PPLL) \n\
744 <08> - 1/32 arm clock(ARM_CLK) \n\
745 <09> - hclk always(AHB_CLK) \n\
746 <10> - ipg clock always(IPG_CLK) \n\
747 <11> - synched per clock root(PER_CLK) \n\
748 <12> - usb clock(USB_CLK) \n\
749 <13> - esdhc1 clock root (ESDHC_CLK) \n\
750 <14> - ssi clock root (SSI_CLK) \n\
751 <15> - mlb memory clock (MLB_CLK) \n\
752 <16> - csi clock root (ESDHC_CLK) \n\
753 <17> - spdif clock root (ESDHC_CLK) \n\
754 <18> - uart clock root (ESDHC_CLK) \n\
755 <19> - asrc autio input clock(ASRC_CLK) \n\
756 <20> - dptc reference clock 1 from ref cir(DPTC_REF_CLK)",
760 static u8* clko_name[] ={
763 "input 24Mhz clock for pll ref(PLL_REF_CLK)",
764 "input 24.576Mhz osc audio clk(AUDIO_REF_CLK)",
765 "1/32 mpll_divgen output 2x(MPLL_OUTPUT_2)",
766 "1/32 ppll_divgen output 0.75x(PPLL_OUTPUT_1)",
767 "1/32 mpll_divgen output 1x(MPLL_OUTPUT_1)",
768 "1/32 ppll output clock(PPLL)",
769 "1/32 arm clock(ARM_CLK)",
770 "hclk always(AHB_CLK)",
771 "ipg clock always(IPG_CLK)",
772 "synched per clock root(PER_CLK)",
773 "usb clock(USB_CLK)",
774 "esdhc1 clock root (ESDHC_CLK)",
775 "ssi clock root (SSI_CLK)" ,
776 "mlb memory clock (MLB_CLK)" ,
778 "csi clock root (ESDHC_CLK)" ,
779 "spdif clock root (ESDHC_CLK)",
780 "uart clock root (ESDHC_CLK)" ,
781 "asrc autio input clock(ASRC_CLK)",
782 "dptc reference clock 1 from ref cir(DPTC_REF_CLK)",
785 #define CLKO_MAX_INDEX (sizeof(clko_name) / sizeof(u8*))
787 static void clko(int argc,char *argv[])
789 u32 action = 0, cosr;
791 if (!scan_opts(argc, argv, 1, 0, 0, (void*) &action,
792 OPTION_ARG_TYPE_NUM, "action"))
795 if (action >= (CLKO_MAX_INDEX -1)) {
796 diag_printf("%d is not supported\n\n", action);
800 cosr = readl(CCM_BASE_ADDR + CLKCTL_COSR);
802 cosr = (cosr & 0xFFFF0020) + ((action<16)?(action - 1):action);
803 if (action > 3 && action < 9) {
804 cosr |= 0x6C40; // make it divided by 32
806 writel(cosr, CCM_BASE_ADDR + CLKCTL_COSR);
807 diag_printf("Set clko to ");
810 cosr = readl(CCM_BASE_ADDR + CLKCTL_COSR);
811 if((cosr&0x1F) > 0x14) {
812 diag_printf("reserved selections\n");
814 diag_printf("%s\n", clko_name[(cosr&0x1F)+1]);
816 diag_printf("COSR register[0x%x] = 0x%x\n",
817 (CCM_BASE_ADDR + CLKCTL_COSR), cosr);
822 * This command is added for some simple testing only. It turns on/off
823 * L2 cache regardless of L1 cache state. The side effect of this is
824 * when doing any flash operations such as "fis init", the L2
825 * will be turned back on along with L1 caches even though it is off
826 * by using this command.
834 void do_L2_caches(int argc, char *argv[])
840 if (strcasecmp(argv[1], "on") == 0) {
841 HAL_DISABLE_INTERRUPTS(oldints);
843 HAL_RESTORE_INTERRUPTS(oldints);
844 } else if (strcasecmp(argv[1], "off") == 0) {
845 HAL_DISABLE_INTERRUPTS(oldints);
846 HAL_CLEAN_INVALIDATE_L2();
848 HAL_RESTORE_INTERRUPTS(oldints);
850 diag_printf("Invalid L2 cache mode: %s\n", argv[1]);
853 HAL_L2CACHE_IS_ENABLED(L2cache_on);
854 diag_printf("L2 cache: %s\n", L2cache_on?"On":"Off");
857 #endif //L2CC_ENABLED
859 #define IIM_ERR_SHIFT 8
860 #define POLL_FUSE_PRGD (IIM_STAT_PRGD | (IIM_ERR_PRGE << IIM_ERR_SHIFT))
861 #define POLL_FUSE_SNSD (IIM_STAT_SNSD | (IIM_ERR_SNSE << IIM_ERR_SHIFT))
863 static void fuse_op_start(void)
865 /* Do not generate interrupt */
866 writel(0, IIM_BASE_ADDR + IIM_STATM_OFF);
867 // clear the status bits and error bits
868 writel(0x3, IIM_BASE_ADDR + IIM_STAT_OFF);
869 writel(0xFE, IIM_BASE_ADDR + IIM_ERR_OFF);
873 * The action should be either:
878 static int poll_fuse_op_done(int action)
883 if (action != POLL_FUSE_PRGD && action != POLL_FUSE_SNSD) {
884 diag_printf("%s(%d) invalid operation\n", __FUNCTION__, action);
888 /* Poll busy bit till it is NOT set */
889 while ((readl(IIM_BASE_ADDR + IIM_STAT_OFF) & IIM_STAT_BUSY) != 0 ) {
892 /* Test for successful write */
893 status = readl(IIM_BASE_ADDR + IIM_STAT_OFF);
894 error = readl(IIM_BASE_ADDR + IIM_ERR_OFF);
896 if ((status & action) != 0 && (error & (action >> IIM_ERR_SHIFT)) == 0) {
898 diag_printf("Even though the operation seems successful...\n");
899 diag_printf("There are some error(s) at addr=0x%x: 0x%x\n",
900 (IIM_BASE_ADDR + IIM_ERR_OFF), error);
904 diag_printf("%s(%d) failed\n", __FUNCTION__, action);
905 diag_printf("status address=0x%x, value=0x%x\n",
906 (IIM_BASE_ADDR + IIM_STAT_OFF), status);
907 diag_printf("There are some error(s) at addr=0x%x: 0x%x\n",
908 (IIM_BASE_ADDR + IIM_ERR_OFF), error);
912 static void sense_fuse(int bank, int row, int bit)
914 int addr, addr_l, addr_h, reg_addr;
918 addr = ((bank << 11) | (row << 3) | (bit & 0x7));
919 /* Set IIM Program Upper Address */
920 addr_h = (addr >> 8) & 0x000000FF;
921 /* Set IIM Program Lower Address */
922 addr_l = (addr & 0x000000FF);
924 #ifdef IIM_FUSE_DEBUG
925 diag_printf("%s: addr_h=0x%x, addr_l=0x%x\n",
926 __FUNCTION__, addr_h, addr_l);
928 writel(addr_h, IIM_BASE_ADDR + IIM_UA_OFF);
929 writel(addr_l, IIM_BASE_ADDR + IIM_LA_OFF);
931 writel(0x8, IIM_BASE_ADDR + IIM_FCTL_OFF);
932 if (poll_fuse_op_done(POLL_FUSE_SNSD) != 0) {
933 diag_printf("%s(bank: %d, row: %d, bit: %d failed\n",
934 __FUNCTION__, bank, row, bit);
936 reg_addr = IIM_BASE_ADDR + IIM_SDAT_OFF;
937 diag_printf("fuses at (bank:%d, row:%d) = 0x%x\n", bank, row, readl(reg_addr));
940 void do_fuse_read(int argc, char *argv[])
945 diag_printf("Useage: fuse_read <bank> <row>\n");
947 } else if (argc == 3) {
948 if (!parse_num(*(&argv[1]), (unsigned long *)&bank, &argv[1], " ")) {
949 diag_printf("Error: Invalid parameter\n");
952 if (!parse_num(*(&argv[2]), (unsigned long *)&row, &argv[2], " ")) {
953 diag_printf("Error: Invalid parameter\n");
957 diag_printf("Read fuse at bank:%d row:%d\n", bank, row);
958 sense_fuse(bank, row, 0);
961 diag_printf("Passing in wrong arguments: %d\n", argc);
962 diag_printf("Useage: fuse_read <bank> <row>\n");
966 /* Blow fuses based on the bank, row and bit positions (all 0-based)
968 static int fuse_blow(int bank,int row,int bit)
970 int addr, addr_l, addr_h, ret = -1;
974 /* Disable IIM Program Protect */
975 writel(0xAA, IIM_BASE_ADDR + IIM_PREG_P_OFF);
977 addr = ((bank << 11) | (row << 3) | (bit & 0x7));
978 /* Set IIM Program Upper Address */
979 addr_h = (addr >> 8) & 0x000000FF;
980 /* Set IIM Program Lower Address */
981 addr_l = (addr & 0x000000FF);
983 #ifdef IIM_FUSE_DEBUG
984 diag_printf("blowing addr_h=0x%x, addr_l=0x%x\n", addr_h, addr_l);
987 writel(addr_h, IIM_BASE_ADDR + IIM_UA_OFF);
988 writel(addr_l, IIM_BASE_ADDR + IIM_LA_OFF);
989 /* Start Programming */
990 writel(0x31, IIM_BASE_ADDR + IIM_FCTL_OFF);
991 if (poll_fuse_op_done(POLL_FUSE_PRGD) == 0) {
995 /* Enable IIM Program Protect */
996 writel(0x0, IIM_BASE_ADDR + IIM_PREG_P_OFF);
1001 * This command is added for burning IIM fuses
1003 RedBoot_cmd("fuse_read",
1009 RedBoot_cmd("fuse_blow",
1011 "<bank> <row> <value>",
1015 #define INIT_STRING "12345678"
1016 static char ready_to_blow[] = INIT_STRING;
1018 void quick_itoa(u32 num, char *a)
1021 for (i = 0; i <= 7; i++) {
1022 j = (num >> (4 * i)) & 0xF;
1023 k = (j < 10) ? '0' : ('a' - 0xa);
1028 void do_fuse_blow(int argc, char *argv[])
1030 int bank, row, value, i;
1033 diag_printf("It is too dangeous for you to use this command.\n");
1035 } else if (argc == 2) {
1036 if (strcasecmp(argv[1], "nandboot") == 0) {
1037 quick_itoa(readl(EPIT_BASE_ADDR + EPITCNR), ready_to_blow);
1038 diag_printf("%s\n", ready_to_blow);
1041 } else if (argc == 3) {
1042 if (strcasecmp(argv[1], "nandboot") == 0 &&
1043 strcasecmp(argv[2], ready_to_blow) == 0) {
1044 #if defined(CYGPKG_HAL_ARM_MXC91131) || defined(CYGPKG_HAL_ARM_MX21) || defined(CYGPKG_HAL_ARM_MX27) || defined(CYGPKG_HAL_ARM_MX31) ||defined(CYGPKG_HAL_ARM_MX35)
1045 diag_printf("No need to blow any fuses for NAND boot on this platform\n\n");
1047 diag_printf("Ready to burn NAND boot fuses\n");
1048 if (fuse_blow(0, 16, 1) != 0 || fuse_blow(0, 16, 7) != 0) {
1049 diag_printf("NAND BOOT fuse blown failed miserably ...\n");
1051 diag_printf("NAND BOOT fuse blown successfully ...\n");
1054 diag_printf("Not ready: %s, %s\n", argv[1], argv[2]);
1057 } else if (argc == 4) {
1058 if (!parse_num(*(&argv[1]), (unsigned long *)&bank, &argv[1], " ")) {
1059 diag_printf("Error: Invalid parameter\n");
1062 if (!parse_num(*(&argv[2]), (unsigned long *)&row, &argv[2], " ")) {
1063 diag_printf("Error: Invalid parameter\n");
1066 if (!parse_num(*(&argv[3]), (unsigned long *)&value, &argv[3], " ")) {
1067 diag_printf("Error: Invalid parameter\n");
1071 diag_printf("Blowing fuse at bank:%d row:%d value:%d\n",
1073 for (i = 0; i < 8; i++) {
1074 if (((value >> i) & 0x1) == 0) {
1077 if (fuse_blow(bank, row, i) != 0) {
1078 diag_printf("fuse_blow(bank: %d, row: %d, bit: %d failed\n",
1081 diag_printf("fuse_blow(bank: %d, row: %d, bit: %d successful\n",
1085 sense_fuse(bank, row, 0);
1088 diag_printf("Passing in wrong arguments: %d\n", argc);
1090 /* Reset to default string */
1091 strcpy(ready_to_blow, INIT_STRING);;
1094 /* precondition: m>0 and n>0. Let g=gcd(m,n). */
1095 int gcd(int m, int n)
1099 if(n > m) {t = m; m = n; n = t;} /* swap */
1105 #define CLOCK_SRC_DETECT_MS 100
1106 #define CLOCK_SRC_DETECT_MARGIN 500000
1107 void mxc_show_clk_input(void)
1110 u32 c1, c2, diff, ipg_real, ipg_clk = get_main_clock(IPG_CLK);
1111 u32 reg = readl(CCM_BASE_ADDR + CLKCTL_PDR0);
1113 if (system_rev & (0x2 << 4)) /* consumer path only in TO2.0 */
1116 diag_printf("Chip is working in %s mode\n", (reg&CLKMODE_CONSUMER)?"consumer":"auto");
1118 // enable GPT with IPG clock input
1119 writel(0x241, GPT_BASE_ADDR + GPTCR);
1121 writel(0, GPT_BASE_ADDR + GPTPR);
1123 c1 = readl(GPT_BASE_ADDR + GPTCNT);
1124 // use 32KHz input clock to get the delay
1125 hal_delay_us(CLOCK_SRC_DETECT_MS * 1000);
1126 c2 = readl(GPT_BASE_ADDR + GPTCNT);
1127 diff = (c2 > c1) ? (c2 - c1) : (0xFFFFFFFF - c1 + c2);
1128 ipg_real = diff * 10;
1130 if (ipg_real > (ipg_clk + CLOCK_SRC_DETECT_MARGIN)) {
1132 } else if (ipg_real < (ipg_clk - CLOCK_SRC_DETECT_MARGIN)) {
1137 diag_printf("Error: Actural ipg clock input is %d Hz\n", ipg_real);
1138 diag_printf(" ipg_clk=%d difference=%d\n\n",
1139 ipg_clk, (ipg_clk > ipg_real) ? (ipg_clk-ipg_real) : (ipg_real-ipg_clk));
1140 hal_delay_us(2000000);
1143 RedBoot_init(mxc_show_clk_input, RedBoot_INIT_LAST);