]> git.kernelconcepts.de Git - karo-tx-redboot.git/blob - packages/hal/arm/mx31/var/v2_0/src/cmds.c
Initial revision
[karo-tx-redboot.git] / packages / hal / arm / mx31 / var / v2_0 / src / cmds.c
1 //==========================================================================
2 //
3 //      cmds.c
4 //
5 //      SoC [platform] specific RedBoot commands
6 //
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.
12 //
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.
16 //
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
20 // for more details.
21 //
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.
25 //
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.
32 //
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.
35 //
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 //==========================================================================
41 #include <redboot.h>
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>
46
47 typedef unsigned long long  u64;
48 typedef unsigned int        u32;
49 typedef unsigned short      u16;
50 typedef unsigned char       u8;
51
52 #define SZ_DEC_1M       1000000
53 #define PLL_PD_MAX      16      //actual pd+1
54 #define PLL_MFI_MAX     15
55 #define PLL_MFI_MIN     5
56 #define PLL_MFD_MAX     1024    //actual mfd+1
57 #define PLL_MFN_MAX     511
58 #define PRESC_MAX       8
59 #define IPG_DIV_MAX     4
60 #define AHB_DIV_MAX     8
61 #define HSP_PODF_MAX    8
62 #define NFC_PODF_MAX    8
63
64 #define PLL_FREQ_MAX    (2 * PLL_REF_CLK * PLL_MFI_MAX)
65 #define PLL_FREQ_MIN    ((2 * PLL_REF_CLK * (PLL_MFI_MIN - 1)) / PLL_PD_MAX)
66 #define AHB_CLK_MAX     133333333
67 #define IPG_CLK_MAX     (AHB_CLK_MAX / 2)
68 #define NFC_CLK_MAX     25000000
69 // IPU-HSP clock is independent of the HCLK and can go up to 177MHz but requires
70 // higher voltage support. For simplicity, limit it to 133MHz
71 #define HSP_CLK_MAX     133333333
72
73 #define ERR_WRONG_CLK   -1
74 #define ERR_NO_MFI      -2
75 #define ERR_NO_MFN      -3
76 #define ERR_NO_PD       -4
77 #define ERR_NO_PRESC    -5
78 #define ERR_NO_AHB_DIV  -6
79
80 u32 pll_clock(enum plls pll);
81 u32 get_main_clock(enum main_clocks clk);
82 u32 get_peri_clock(enum peri_clocks clk);
83
84 static u32 pll_mfd_fixed;
85
86 static void clock_setup(int argc, char *argv[]);
87 static void clko(int argc, char *argv[]);
88 extern unsigned int g_clock_src;
89
90 RedBoot_cmd("clock",
91             "Setup/Display clock (max AHB=133MHz, max IPG=66.5MHz)\nSyntax:",
92             "[<core clock in MHz> [:<AHB-to-core divider>[:<IPG-to-AHB divider>]]] \n\n\
93 If a divider is zero or no divider is specified, the optimal divider values \n\
94 will be chosen. Examples:\n\
95    [clock]         -> Show various clocks\n\
96    [clock 532]     -> Core=532  AHB=133           IPG=66.5\n\
97    [clock 399]     -> Core=399  AHB=133           IPG=66.5\n\
98    [clock 532:8]   -> Core=532  AHB=66.5(Core/8)  IPG=66.5\n\
99    [clock 532:8:2] -> Core=532  AHB=66.5(Core/8)  IPG=33.25(AHB/2)\n",
100             clock_setup
101            );
102
103 /*!
104  * This is to calculate various parameters based on reference clock and 
105  * targeted clock based on the equation:
106  *      t_clk = 2*ref_freq*(mfi + mfn/(mfd+1))/(pd+1)
107  * This calculation is based on a fixed MFD value for simplicity.
108  *
109  * @param ref       reference clock freq
110  * @param target    targeted clock in HZ
111  * @param p_pd      calculated pd value (pd value from register + 1) upon return
112  * @param p_mfi     calculated actual mfi value upon return
113  * @param p_mfn     calculated actual mfn value upon return
114  * @param p_mfd     fixed mfd value (mfd value from register + 1) upon return
115  *
116  * @return          0 if successful; non-zero otherwise.
117  */
118 int calc_pll_params(u32 ref, u32 target, u32 *p_pd, 
119                     u32 *p_mfi, u32 *p_mfn, u32 *p_mfd)
120 {
121     u64 pd, mfi, mfn, n_target = (u64)target, n_ref = (u64)ref;
122
123     if (g_clock_src == FREQ_26MHZ) {
124         pll_mfd_fixed = 26 * 16;
125     } else if (g_clock_src == FREQ_27MHZ) {
126         pll_mfd_fixed = 27 * 16;
127     } else {
128         pll_mfd_fixed = 1024;
129     }
130
131     // Make sure targeted freq is in the valid range. Otherwise the 
132     // following calculation might be wrong!!!
133     if (target < PLL_FREQ_MIN || target > PLL_FREQ_MAX) {
134         return ERR_WRONG_CLK;
135     }
136     // Use n_target and n_ref to avoid overflow
137     for (pd = 1; pd <= PLL_PD_MAX; pd++) {
138         mfi = (n_target * pd) / (2 * n_ref);
139         if (mfi > PLL_MFI_MAX) {
140             return ERR_NO_MFI;
141         } else if (mfi < 5) {
142             continue;
143         }
144         break;
145     }
146     // Now got pd and mfi already
147     mfn = (((n_target * pd) / 2 - n_ref * mfi) * pll_mfd_fixed) / n_ref;
148     // Check mfn within limit and mfn < denominator
149     if (mfn > PLL_MFN_MAX || mfn >= pll_mfd_fixed) {
150         return ERR_NO_MFN;
151     }
152
153     if (pd > PLL_PD_MAX) {
154         return ERR_NO_PD;
155     }
156     *p_pd = (u32)pd;
157     *p_mfi = (u32)mfi;
158     *p_mfn = (u32)mfn;
159     *p_mfd = pll_mfd_fixed;
160     return 0;
161 }
162
163 /*!
164  * This function assumes the expected core clock has to be changed by
165  * modifying the PLL. This is NOT true always but for most of the times,
166  * it is. So it assumes the PLL output freq is the same as the expected 
167  * core clock (presc=1) unless the core clock is less than PLL_FREQ_MIN.
168  * In the latter case, it will try to increase the presc value until 
169  * (presc*core_clk) is greater than PLL_FREQ_MIN. It then makes call to
170  * calc_pll_params() and obtains the values of PD, MFI,MFN, MFD based
171  * on the targeted PLL and reference input clock to the PLL. Lastly, 
172  * it sets the register based on these values along with the dividers.
173  * Note 1) There is no value checking for the passed-in divider values
174  *         so the caller has to make sure those values are sensible.
175  *      2) Also adjust the NFC divider such that the NFC clock doesn't
176  *         exceed NFC_CLK_MAX.
177  *      3) IPU HSP clock is independent of AHB clock. Even it can go up to
178  *         177MHz for higher voltage, this function fixes the max to 133MHz.
179  *      4) This function should not have allowed diag_printf() calls since
180  *         the serial driver has been stoped. But leave then here to allow
181  *         easy debugging by NOT calling the cyg_hal_plf_serial_stop().
182  * 
183  * @param ref       pll input reference clock (32KHz or 26MHz)
184  * @param core_clk  core clock in Hz
185  * @param ahb_div   ahb divider to divide the core clock to get ahb clock 
186  *                  (ahb_div - 1) needs to be set in the register
187  * @param ipg_div   ipg divider to divide the ahb clock to get ipg clock
188  *                  (ipg_div - 1) needs to be set in the register
189  # @return          0 if successful; non-zero otherwise
190  */
191 int configure_clock(u32 ref, u32 core_clk, u32 ahb_div, u32 ipg_div)
192 {
193     u32 pll, presc = 1, pd, mfi, mfn, mfd, brmo = 0, mpctl0, hsp_div;
194     u32 pdr0, nfc_div;
195     int ret, i;
196
197     // assume pll default to core clock first
198     pll = core_clk;
199     // when core_clk >= PLL_FREQ_MIN, the presc can be 1.
200     // Otherwise, need to calculate presc value below and adjust the targeted pll
201     if (core_clk < PLL_FREQ_MIN) {
202         for (presc = 1; presc <= PRESC_MAX; presc++) {
203             if ((core_clk * presc) > PLL_FREQ_MIN) {
204                 break;
205             }
206         }
207         if (presc == (PRESC_MAX + 1)) {
208             diag_printf("can't make presc=%d\n", presc);
209             return ERR_NO_PRESC;
210         }
211         pll = core_clk * presc;
212     }
213     // get hsp_div
214     for (hsp_div = 1; hsp_div <= HSP_PODF_MAX; hsp_div++) {
215         if ((pll / hsp_div) <= HSP_CLK_MAX) {
216             break;
217         }
218     }
219     if (hsp_div == (HSP_PODF_MAX + 1)) {
220         diag_printf("can't make hsp_div=%d\n", hsp_div);
221         return ERR_NO_PRESC;
222     }
223     
224     // get nfc_div - make sure optimal NFC clock but less than NFC_CLK_MAX
225     for (nfc_div = 1; nfc_div <= NFC_PODF_MAX; nfc_div++) {
226         if ((pll / (ahb_div * nfc_div)) <= NFC_CLK_MAX) {
227             break;
228         }
229     }
230
231     // pll is now the targeted pll output. Use it along with ref input clock
232     // to get pd, mfi, mfn, mfd
233     if ((ret = calc_pll_params(ref, pll, &pd, &mfi, &mfn, &mfd)) != 0) {
234         diag_printf("can't find pll parameters: %d\n", ret);
235         return ret;
236     }
237 #ifdef CMD_CLOCK_DEBUG
238     diag_printf("ref=%d, pll=%d, pd=%d, mfi=%d,mfn=%d, mfd=%d\n", 
239                 ref, pll, pd, mfi, mfn, mfd);
240 #endif
241
242     // blindly increase divider first to avoid too fast ahbclk and ipgclk
243     // in case the core clock increases too much
244     pdr0 = readl(CCM_BASE_ADDR + CLKCTL_PDR0);
245     pdr0 &= ~0x000000FF;
246     // increase the dividers. should work even when core clock is 832 (26*2*16)MHz
247     // which is unlikely true.
248     pdr0 |= (1 << 6) | (6 << 3) | (0 << 0);
249     writel(pdr0, CCM_BASE_ADDR + CLKCTL_PDR0);
250     // calculate new pdr0
251     pdr0 &= ~0x00003FFF;
252     pdr0 |= ((hsp_div - 1) << 11) | ((nfc_div - 1) << 8) | ((ipg_div - 1) << 6) | 
253             ((ahb_div - 1) << 3) | ((presc - 1) << 0);
254
255     // update PLL register
256     if ((mfd >= (10 * mfn)) || ((10 * mfn) >= (9 * mfd)))
257         brmo = 1;
258
259     mpctl0 = readl(CCM_BASE_ADDR + CLKCTL_MPCTL);
260     mpctl0 = (mpctl0 & 0x4000C000)  |
261              (brmo << 31)           |
262              ((pd - 1) << 26)       |
263              ((mfd - 1) << 16)      |
264              (mfi << 10)            |
265              mfn;
266     writel(mpctl0, CCM_BASE_ADDR + CLKCTL_MPCTL);
267     writel(pdr0, CCM_BASE_ADDR + CLKCTL_PDR0);
268     // add some delay for new values to take effect
269     for (i = 0; i < 10000; i++);
270
271     return 0;
272 }
273
274 static void clock_setup(int argc,char *argv[])
275 {
276     u32 i, core_clk, ipg_div, data[3], temp, ahb_div, ahb_clk, ipg_clk;
277     int ret;
278
279     if (argc == 1)
280         goto print_clock;
281     if (g_clock_src == FREQ_27MHZ) {
282         diag_printf("Error: clock setup is not supported for 27MHz source\n\n");
283         return;
284     }
285     for (i = 0;  i < 3;  i++) {
286         if (!parse_num(*(&argv[1]), (unsigned long *)&temp, &argv[1], ":")) {
287             diag_printf("Error: Invalid parameter\n");
288             return;
289         }
290         data[i] = temp;
291     }
292
293     core_clk = data[0] * SZ_DEC_1M;
294     ahb_div = data[1];  // actual register field + 1
295     ipg_div = data[2];  // actual register field + 1
296
297     if (core_clk < (PLL_FREQ_MIN / PRESC_MAX) || core_clk > PLL_FREQ_MAX) {
298         diag_printf("Targeted core clock should be within [%d - %d]\n", 
299                     PLL_FREQ_MIN / PRESC_MAX, PLL_FREQ_MAX);
300         return;
301     }
302
303     // find the ahb divider  
304     if (ahb_div > AHB_DIV_MAX) {
305         diag_printf("Invalid AHB divider: %d. Maximum value is %d\n",
306                     ahb_div, AHB_DIV_MAX);
307         return;
308     }
309     if (ahb_div == 0) {
310         // no HCLK divider specified
311         for (ahb_div = 1; ; ahb_div++) {
312             if ((core_clk / ahb_div) <= AHB_CLK_MAX) {
313                 break;
314             }
315         }
316     }
317     if (ahb_div > AHB_DIV_MAX || (core_clk / ahb_div) > AHB_CLK_MAX) {
318         diag_printf("Can't make AHB=%d since max=%d\n", 
319                     core_clk / ahb_div, AHB_CLK_MAX);
320         return;
321     }
322
323     // find the ipg divider
324     ahb_clk = core_clk / ahb_div;
325     if (ipg_div > IPG_DIV_MAX) {
326         diag_printf("Invalid IPG divider: %d. Maximum value is %d\n", 
327                     ipg_div, IPG_DIV_MAX);
328         return;
329     }
330     if (ipg_div == 0) {
331         ipg_div++;          // At least =1
332         if (ahb_clk > IPG_CLK_MAX)
333             ipg_div++;      // Make it =2
334     }
335     if (ipg_div > IPG_DIV_MAX || (ahb_clk / ipg_div) > IPG_CLK_MAX) {
336         diag_printf("Can't make IPG=%d since max=%d\n", 
337                     (ahb_clk / ipg_div), IPG_CLK_MAX);
338         return;
339     }
340     ipg_clk = ahb_clk / ipg_div;
341
342     diag_printf("Trying to set core=%d ahb=%d ipg=%d...\n", 
343                 core_clk, ahb_clk, ipg_clk);
344
345     // stop the serial to be ready to adjust the clock
346     hal_delay_us(100000);
347     cyg_hal_plf_serial_stop();
348     // adjust the clock
349     ret = configure_clock(PLL_REF_CLK, core_clk, ahb_div, ipg_div);
350     // restart the serial driver
351     cyg_hal_plf_serial_init();
352     hal_delay_us(100000);
353
354     if (ret != 0) {
355         diag_printf("Failed to setup clock: %d\n", ret);
356         return;
357     }
358     diag_printf("\n<<<New clock setting>>>\n");
359
360     // Now printing clocks
361 print_clock:
362     diag_printf("\nMPLL\t\tUPLL\t\tSPLL\n");
363     diag_printf("========================================\n");
364     diag_printf("%-16d%-16d%-16d\n\n", pll_clock(MCU_PLL), pll_clock(USB_PLL),
365                 pll_clock(SER_PLL));
366     diag_printf("CPU\t\tAHB\t\tIPG\t\tIPG_PER\n");
367     diag_printf("========================================================\n");
368     diag_printf("%-16d%-16d%-16d%-16d\n\n",
369                 get_main_clock(CPU_CLK),
370                 get_main_clock(AHB_CLK),
371                 get_main_clock(IPG_CLK),
372                 get_main_clock(IPG_PER_CLK));
373
374     diag_printf("NFC\t\tUSB\t\tIPU-HSP\n");
375     diag_printf("========================================\n");
376     diag_printf("%-16d%-16d%-16d\n\n",
377                 get_main_clock(NFC_CLK),
378                 get_main_clock(USB_CLK),
379                 get_main_clock(HSP_CLK));
380
381     diag_printf("UART1-5\t\tSSI1\t\tSSI2\t\tCSI\n");
382     diag_printf("===========================================");
383     diag_printf("=============\n");
384
385     diag_printf("%-16d%-16d%-16d%-16d\n\n", 
386                 get_peri_clock(UART1_BAUD),
387                 get_peri_clock(SSI1_BAUD),
388                 get_peri_clock(SSI2_BAUD),
389                 get_peri_clock(CSI_BAUD));
390
391     diag_printf("FIRI\t\tSIM\t\tMSTICK1\t\tMSTICK2\n");
392     diag_printf("===========================================");
393     diag_printf("=============\n");
394
395     diag_printf("%-16d%-16d%-16d%-16d\n\n", 
396                 get_peri_clock(FIRI_BAUD),
397                 get_peri_clock(SIM_BAUD),
398                 get_peri_clock(MSTICK1_CLK),
399                 get_peri_clock(MSTICK2_CLK));
400     diag_printf("IPG_PERCLK as baud clock for: UART1-5, I2C, SIM, OWIRE, SDHC");
401     if (((readl(EPIT1_BASE_ADDR) >> 24) & 0x3) == 0x2) {
402         diag_printf(", EPIT");
403     }
404     if (((readl(GPT1_BASE_ADDR) >> 6) & 0x7) == 0x2) {
405         diag_printf("GPT,");
406     }
407     if (((readl(PWM_BASE_ADDR) >> 16) & 0x3) == 0x2) {
408         diag_printf("PWM,");
409     }
410     diag_printf("\n");
411 }
412
413 /*!
414  * This function returns the PLL output value in Hz based on pll.
415  */
416 u32 pll_clock(enum plls pll)
417 {
418     u64 mfi, mfn, mfd, pdf, ref_clk, pll_out, sign;
419     u64 reg = readl(pll);
420
421     pdf = (reg >> 26) & 0xF;
422     mfd = (reg >> 16) & 0x3FF;
423     mfi = (reg >> 10) & 0xF;
424     mfi = (mfi <= 5) ? 5: mfi;
425     mfn = reg & 0x3FF;
426     sign = (mfn < 512) ? 0: 1;
427     mfn = (mfn < 512) ? mfn: (1024 - mfn);
428
429     ref_clk = g_clock_src;
430
431     if (sign == 0) {
432         pll_out = (2 * ref_clk * mfi + ((2 * ref_clk * mfn) / (mfd + 1))) /
433                   (pdf + 1);
434     } else {
435         pll_out = (2 * ref_clk * mfi - ((2 * ref_clk * mfn) / (mfd + 1))) /
436                   (pdf + 1);
437     }
438
439     return (u32)pll_out;
440 }
441
442 // The clocks are on by default. But need to setup the IOMUX
443 void clock_spi_enable(unsigned int spi_clk)
444 {
445     u32 val;
446
447     // Take care of SPI1 and SPI2
448     val = readl(IOMUXC_BASE_ADDR + 0x80);
449     writel((val & 0xFFFF) | 0x12120000, IOMUXC_BASE_ADDR + 0x80);
450
451     writel(0x12121212, IOMUXC_BASE_ADDR + 0x84);
452     writel(0x12121212, IOMUXC_BASE_ADDR + 0x88);
453     writel(0x12121212, IOMUXC_BASE_ADDR + 0x8C);
454 }
455
456 /*!
457  * This function returns the main clock value in Hz.
458  */
459 u32 get_main_clock(enum main_clocks clk)
460 {
461     u32 mcu_podf, max_pdf, ipg_pdf, nfc_pdf, hsp_podf, clk_sel;
462     u32 pll, ret_val = 0, usb_prdf, usb_podf, pdf;
463     u32 reg = readl(CCM_BASE_ADDR + CLKCTL_PDR0);
464     u32 reg1 = readl(CCM_BASE_ADDR + CLKCTL_PDR1);
465     u32 ccmr = readl(CCM_BASE_ADDR + CLKCTL_CCMR);
466     u32 mpdr0 = readl(CCM_BASE_ADDR + CLKCTL_PDR0);
467
468     switch (clk) {
469     case CPU_CLK:
470         mcu_podf = reg & 0x7;
471         pll = pll_clock(MCU_PLL);
472         ret_val = pll / (mcu_podf + 1);
473         break;
474     case AHB_CLK:
475         max_pdf = (reg >> 3) & 0x7;
476         pll = pll_clock(MCU_PLL);
477         ret_val = pll / (max_pdf + 1);
478         break;
479     case HSP_CLK:
480         hsp_podf = (reg >> 11) & 0x7;
481         pll = pll_clock(MCU_PLL);
482         ret_val = pll / (hsp_podf + 1);
483         break;
484     case MBX_CLK:
485         max_pdf = (reg >> 3) & 0x7;
486         pll = pll_clock(MCU_PLL);
487         ret_val = (pll / (max_pdf + 1)) / 2;
488         break;
489     case IPG_CLK:
490         max_pdf = (reg >> 3) & 0x7;
491         ipg_pdf = (reg >> 6) & 0x3;
492         pll = pll_clock(MCU_PLL);
493         ret_val = pll / ((max_pdf + 1) * (ipg_pdf + 1));
494         break;
495     case IPG_PER_CLK:
496         clk_sel = ccmr & (1 << 24);
497         pdf = (mpdr0 >> 16) & 0x1F;
498         if (clk_sel != 0) {
499             // get the ipg_clk
500             max_pdf = (reg >> 3) & 0x7;
501             ipg_pdf = (reg >> 6) & 0x3;
502             pll = pll_clock(MCU_PLL);
503             ret_val = pll / ((max_pdf + 1) * (ipg_pdf + 1));
504         } else {
505             ret_val = pll_clock(USB_PLL) / (pdf + 1);
506         }
507         break;
508     case NFC_CLK:
509         nfc_pdf = (reg >> 8) & 0x7;
510         max_pdf = (reg >> 3) & 0x7;
511         pll = pll_clock(MCU_PLL);
512         /* AHB/nfc_pdf */
513         ret_val = pll / ((max_pdf + 1) * (nfc_pdf + 1));
514         break;
515     case USB_CLK:
516         usb_prdf = reg1 >> 30;
517         usb_podf = (reg1 >> 27) & 0x7;
518         pll = pll_clock(USB_PLL);
519         ret_val = pll / ((usb_prdf + 1) * (usb_podf + 1));
520         break;
521     default:
522         diag_printf("Unknown clock: %d\n", clk);
523         break;
524     }
525
526     return ret_val;
527 }
528
529 /*!
530  * This function returns the peripheral clock value in Hz.
531  */
532 u32 get_peri_clock(enum peri_clocks clk)
533 {
534     u32 ret_val = 0, pdf, pre_pdf, clk_sel;
535     u32 ccmr = readl(CCM_BASE_ADDR + CLKCTL_CCMR);
536     u32 mpdr0 = readl(CCM_BASE_ADDR + CLKCTL_PDR0);
537     u32 mpdr1 = readl(CCM_BASE_ADDR + CLKCTL_PDR1);
538     u32 mpdr2 = readl(CCM_BASE_ADDR + CLKCTL_PDR2);
539
540     switch (clk) {
541     case UART1_BAUD:
542     case UART2_BAUD:
543     case UART3_BAUD:
544     case UART4_BAUD:
545     case UART5_BAUD:
546     case SIM_BAUD:
547         clk_sel = ccmr & (1 << 24);
548         pdf = (mpdr0 >> 16) & 0x1F;
549         ret_val = (clk_sel != 0) ? get_main_clock(IPG_CLK) : 
550                   pll_clock(USB_PLL) / (pdf + 1);
551         break;
552     case SSI1_BAUD:
553         pre_pdf = (mpdr1 >> 6) & 0x7;
554         pdf = mpdr1 & 0x3F;
555         clk_sel = (ccmr >> 18) & 3;
556         if (clk_sel == 0) {
557             ret_val = pll_clock(MCU_PLL) / ((pre_pdf + 1) * (pdf + 1));
558         } else if (clk_sel == 0x1) {
559             ret_val = pll_clock(USB_PLL) / ((pre_pdf + 1) * (pdf + 1));
560         } else if (clk_sel == 0x2) {
561             ret_val = pll_clock(SER_PLL) / ((pre_pdf + 1) * (pdf + 1));
562         } else {
563             diag_printf("Error: Use reserved value for SSI1!\n");
564             ret_val = 0;
565         }
566         break;
567     case SSI2_BAUD:
568         pre_pdf = (mpdr1 >> 15) & 0x7;
569         pdf = (mpdr1 >> 9) & 0x3F;
570         clk_sel = (ccmr >> 21) & 3;
571         if (clk_sel == 0) {
572             ret_val = pll_clock(MCU_PLL) / ((pre_pdf + 1) * (pdf + 1));
573         } else if (clk_sel == 0x1) {
574             ret_val = pll_clock(USB_PLL) / ((pre_pdf + 1) * (pdf + 1));
575         } else if (clk_sel == 0x2) {
576             ret_val = pll_clock(SER_PLL) / ((pre_pdf + 1) * (pdf + 1));
577         } else {
578             diag_printf("Error: Use reserved value for SSI2!\n");
579             ret_val = 0;
580         }
581         break;
582     case CSI_BAUD:
583         clk_sel = ccmr & (1 << 25);
584         pdf = (mpdr0 >> 23) & 0x1FF;
585         ret_val = (clk_sel != 0) ? (pll_clock(SER_PLL) / (pdf + 1)) : 
586                   (pll_clock(USB_PLL) / (pdf + 1));
587         break;
588     case FIRI_BAUD:
589         pre_pdf = (mpdr1 >> 24) & 0x7;
590         pdf = (mpdr1 >> 18) & 0x3F;
591         clk_sel = (ccmr >> 11) & 3;
592         if (clk_sel == 0) {
593             ret_val = pll_clock(MCU_PLL) / ((pre_pdf + 1) * (pdf + 1));
594         } else if (clk_sel == 0x1) {
595             ret_val = pll_clock(USB_PLL) / ((pre_pdf + 1) * (pdf + 1));
596         } else if (clk_sel == 0x2) {
597             ret_val = pll_clock(SER_PLL) / ((pre_pdf + 1) * (pdf + 1));
598         } else {
599             diag_printf("Error: Use reserved value for SSI1!\n");
600             ret_val = 0;
601         }
602         break;
603     case MSTICK1_CLK:
604         pdf = mpdr2 & 0x3F;
605         ret_val = pll_clock(USB_PLL) / (pdf + 1);
606         break;
607     case MSTICK2_CLK:
608         pdf = (mpdr2 >> 7) & 0x3F;
609         ret_val = pll_clock(USB_PLL) / (pdf + 1);
610         break;
611     case SPI1_CLK:
612     case SPI2_CLK:
613         ret_val = get_main_clock(IPG_CLK);
614         break;
615     default:
616         diag_printf("%s(): This clock: %d not supported yet \n",
617                     __FUNCTION__, clk);
618         break;
619     }
620
621     return ret_val;
622 }
623
624 RedBoot_cmd("clko",
625             "Select clock source for CLKO (J11 on the CPU daughter card)",
626             " Default is 1/8 of ARM core\n\
627           <0> - display current clko selection \n\
628           <1> - mpl_dpdgck_clk (MPLL) \n\
629           <2> - ipg_clk_ccm (IPG) \n\
630           <3> - upl_dpdgck_clk (UPLL) \n\
631           <4> - pll_ref_clk \n\
632           <5> - fpm_ckil512_clk \n\
633           <6> - ipg_clk_ahb_arm (AHB) \n\
634           <7> - ipg_clk_arm (ARM) \n\
635           <8> - spl_dpdgck_clk (SPLL) \n\
636           <9> - ckih \n\
637           <10> - ipg_clk_ahb_emi_clk \n\
638           <11> - ipg_clk_ipu_hsp \n\
639           <12> - ipg_clk_nfc_20m \n\
640           <13> - ipg_clk_perclk_uart1 (IPG_PER)",
641             clko
642            );
643
644 static u8* clko_name[] ={
645     "NULL",
646     "1/8 of mpl_dpdgck_clk (MPLL)",
647     "ipg_clk_ccm (IPG)",
648     "1/8 of upl_dpdgck_clk (UPLL)",
649     "pll_ref_clk",
650     "fpm_ckil512_clk",
651     "ipg_clk_ahb_arm (AHB)",
652     "1/8 of ipg_clk_arm (ARM)",
653     "1/8 of spl_dpdgck_clk (SPLL)",
654     "ckih",
655     "ipg_clk_ahb_emi_clk",
656     "ipg_clk_ipu_hsp",
657     "ipg_clk_nfc_20m",
658     "ipg_clk_perclk_uart1 (IPG_PER)",
659 };
660
661 #define CLKO_MAX_INDEX          (sizeof(clko_name) / sizeof(u8*))
662
663 static void clko(int argc,char *argv[])
664 {
665     u32 action = 0, cosr;
666
667     if (!scan_opts(argc, argv, 1, 0, 0, (void*) &action,
668                    OPTION_ARG_TYPE_NUM, "action"))
669         return;
670
671     if (action >= CLKO_MAX_INDEX) {
672         diag_printf("%d is not supported\n\n", action);
673         return;
674     }
675
676     cosr = readl(CCM_BASE_ADDR + CLKCTL_COSR);
677
678     if (action != 0) {
679         cosr = (cosr & (~0x1FF)) + action - 1;
680         if (action == 1 || action == 3 || action == 7 || action == 8) {
681             cosr |= (0x3 << 6); // make it divided by 8
682         }
683         writel(cosr, CCM_BASE_ADDR + CLKCTL_COSR);
684         diag_printf("Set clko to ");
685     }
686
687     cosr = readl(CCM_BASE_ADDR + CLKCTL_COSR);
688     diag_printf("%s\n", clko_name[(cosr & 0xF) + 1]);
689     diag_printf("COSR register[0x%x] = 0x%x\n", 
690                 (CCM_BASE_ADDR + CLKCTL_COSR), cosr);
691 }
692
693 #ifdef L2CC_ENABLED
694 /*
695  * This command is added for some simple testing only. It turns on/off
696  * L2 cache regardless of L1 cache state. The side effect of this is
697  * when doing any flash operations such as "fis init", the L2
698  * will be turned back on along with L1 caches even though it is off
699  * by using this command.
700  */
701 RedBoot_cmd("L2",
702             "L2 cache",
703             "[ON | OFF]",
704             do_L2_caches
705            );
706
707 void do_L2_caches(int argc, char *argv[])
708 {
709     u32 oldints;
710     int L2cache_on=0;
711
712     if (argc == 2) {
713         if (strcasecmp(argv[1], "on") == 0) {
714             HAL_DISABLE_INTERRUPTS(oldints);
715             HAL_ENABLE_L2();
716             HAL_RESTORE_INTERRUPTS(oldints);
717         } else if (strcasecmp(argv[1], "off") == 0) {
718             HAL_DISABLE_INTERRUPTS(oldints);
719             HAL_CLEAN_INVALIDATE_L2();
720             HAL_DISABLE_L2();
721             HAL_RESTORE_INTERRUPTS(oldints);
722         } else {
723             diag_printf("Invalid L2 cache mode: %s\n", argv[1]);
724         }
725     } else {
726         HAL_L2CACHE_IS_ENABLED(L2cache_on);
727         diag_printf("L2 cache: %s\n", L2cache_on?"On":"Off");
728     }
729 }
730 #endif //L2CC_ENABLED
731
732 #define IIM_ERR_SHIFT       8
733 #define POLL_FUSE_PRGD      (IIM_STAT_PRGD | (IIM_ERR_PRGE << IIM_ERR_SHIFT))
734 #define POLL_FUSE_SNSD      (IIM_STAT_SNSD | (IIM_ERR_SNSE << IIM_ERR_SHIFT))
735
736 static void fuse_op_start(void)
737 {
738     /* Do not generate interrupt */
739     writel(0, IIM_BASE_ADDR + IIM_STATM_OFF);
740     // clear the status bits and error bits
741     writel(0x3, IIM_BASE_ADDR + IIM_STAT_OFF);
742     writel(0xFE, IIM_BASE_ADDR + IIM_ERR_OFF);
743 }
744
745 /*
746  * The action should be either:
747  *          POLL_FUSE_PRGD 
748  * or:
749  *          POLL_FUSE_SNSD
750  */
751 static int poll_fuse_op_done(int action)
752 {
753
754     u32 status, error;
755
756     if (action != POLL_FUSE_PRGD && action != POLL_FUSE_SNSD) {
757         diag_printf("%s(%d) invalid operation\n", __FUNCTION__, action);
758         return -1;
759     }
760
761     /* Poll busy bit till it is NOT set */
762     while ((readl(IIM_BASE_ADDR + IIM_STAT_OFF) & IIM_STAT_BUSY) != 0 ) {
763     }
764
765     /* Test for successful write */
766     status = readl(IIM_BASE_ADDR + IIM_STAT_OFF);
767     error = readl(IIM_BASE_ADDR + IIM_ERR_OFF);
768
769     if ((status & action) != 0 && (error & (action >> IIM_ERR_SHIFT)) == 0) {
770         if (error) {
771             diag_printf("Even though the operation seems successful...\n");
772             diag_printf("There are some error(s) at addr=0x%x: 0x%x\n",
773                         (IIM_BASE_ADDR + IIM_ERR_OFF), error);
774         }
775         return 0;
776     }
777     diag_printf("%s(%d) failed\n", __FUNCTION__, action);
778     diag_printf("status address=0x%x, value=0x%x\n",
779                 (IIM_BASE_ADDR + IIM_STAT_OFF), status);
780     diag_printf("There are some error(s) at addr=0x%x: 0x%x\n",
781                 (IIM_BASE_ADDR + IIM_ERR_OFF), error);
782     return -1;
783 }
784
785 static void sense_fuse(int bank, int row, int bit)
786 {
787     int addr, addr_l, addr_h, reg_addr;
788
789     fuse_op_start();
790     
791     addr = ((bank << 11) | (row << 3) | (bit & 0x7));
792     /* Set IIM Program Upper Address */
793     addr_h = (addr >> 8) & 0x000000FF;
794     /* Set IIM Program Lower Address */
795     addr_l = (addr & 0x000000FF);
796
797 #ifdef IIM_FUSE_DEBUG
798     diag_printf("%s: addr_h=0x%x, addr_l=0x%x\n",
799                 __FUNCTION__, addr_h, addr_l);
800 #endif
801     writel(addr_h, IIM_BASE_ADDR + IIM_UA_OFF);
802     writel(addr_l, IIM_BASE_ADDR + IIM_LA_OFF);
803     /* Start sensing */
804     writel(0x8, IIM_BASE_ADDR + IIM_FCTL_OFF);
805     if (poll_fuse_op_done(POLL_FUSE_SNSD) != 0) {
806         diag_printf("%s(bank: %d, row: %d, bit: %d failed\n",
807                     __FUNCTION__, bank, row, bit);
808     }
809     reg_addr = IIM_BASE_ADDR + IIM_SDAT_OFF;
810     diag_printf("fuses at (bank:%d, row:%d) = 0x%x\n", bank, row, readl(reg_addr));
811 }
812
813 void do_fuse_read(int argc, char *argv[])
814 {
815     int bank, row;
816
817     if (argc == 1) {
818         diag_printf("Useage: fuse_read <bank> <row>\n");
819         return;
820     } else if (argc == 3) {
821         if (!parse_num(*(&argv[1]), (unsigned long *)&bank, &argv[1], " ")) {
822                 diag_printf("Error: Invalid parameter\n");
823             return;
824         }
825         if (!parse_num(*(&argv[2]), (unsigned long *)&row, &argv[2], " ")) {
826                 diag_printf("Error: Invalid parameter\n");
827                 return;
828             }
829
830         diag_printf("Read fuse at bank:%d row:%d\n", bank, row);
831         sense_fuse(bank, row, 0);
832
833     } else {
834         diag_printf("Passing in wrong arguments: %d\n", argc);
835         diag_printf("Useage: fuse_read <bank> <row>\n");
836     }
837 }
838
839 /* Blow fuses based on the bank, row and bit positions (all 0-based)
840 */
841 static int fuse_blow(int bank,int row,int bit)
842 {
843     int addr, addr_l, addr_h, ret = -1;
844
845     fuse_op_start();
846
847     /* Disable IIM Program Protect */
848     writel(0xAA, IIM_BASE_ADDR + IIM_PREG_P_OFF);
849
850     addr = ((bank << 11) | (row << 3) | (bit & 0x7));
851     /* Set IIM Program Upper Address */
852     addr_h = (addr >> 8) & 0x000000FF;
853     /* Set IIM Program Lower Address */
854     addr_l = (addr & 0x000000FF);
855
856 #ifdef IIM_FUSE_DEBUG
857     diag_printf("blowing addr_h=0x%x, addr_l=0x%x\n", addr_h, addr_l);
858 #endif
859
860     writel(addr_h, IIM_BASE_ADDR + IIM_UA_OFF);
861     writel(addr_l, IIM_BASE_ADDR + IIM_LA_OFF);
862     /* Start Programming */
863     writel(0x31, IIM_BASE_ADDR + IIM_FCTL_OFF);
864     if (poll_fuse_op_done(POLL_FUSE_PRGD) == 0) {
865         ret = 0;
866     }
867
868     /* Enable IIM Program Protect */
869     writel(0x0, IIM_BASE_ADDR + IIM_PREG_P_OFF);
870     return ret;
871 }
872
873 /*
874  * This command is added for burning IIM fuses
875  */
876 RedBoot_cmd("fuse_read",
877             "read some fuses",
878             "<bank> <row>",
879             do_fuse_read
880            );
881
882 RedBoot_cmd("fuse_blow",
883             "blow some fuses",
884             "<bank> <row> <value>",
885             do_fuse_blow
886            );
887
888 #define         INIT_STRING              "12345678"
889 static char ready_to_blow[] = INIT_STRING;
890
891 void quick_itoa(u32 num, char *a) 
892 {
893     int i, j, k;        
894     for (i = 0; i <= 7; i++) {
895         j = (num >> (4 * i)) & 0xF;
896         k = (j < 10) ? '0' : ('a' - 0xa);
897         a[i] = j + k;
898     }
899 }
900
901 void do_fuse_blow(int argc, char *argv[])
902 {
903     int bank, row, value, i;
904
905     if (argc == 1) {
906         diag_printf("It is too dangeous for you to use this command.\n");
907         return;
908     } else if (argc == 2) {
909         if (strcasecmp(argv[1], "nandboot") == 0) {
910             quick_itoa(readl(EPIT_BASE_ADDR + EPITCNR), ready_to_blow);
911             diag_printf("%s\n", ready_to_blow);
912         }
913         return;
914     } else if (argc == 3) {
915         if (strcasecmp(argv[1], "nandboot") == 0 && 
916             strcasecmp(argv[2], ready_to_blow) == 0) {
917 #if defined(CYGPKG_HAL_ARM_MXC91131) || defined(CYGPKG_HAL_ARM_MX21) || defined(CYGPKG_HAL_ARM_MX27) || defined(CYGPKG_HAL_ARM_MX31)
918             diag_printf("No need to blow any fuses for NAND boot on this platform\n\n");
919 #else
920             diag_printf("Ready to burn NAND boot fuses\n");
921             if (fuse_blow(0, 16, 1) != 0 || fuse_blow(0, 16, 7) != 0) {
922                 diag_printf("NAND BOOT fuse blown failed miserably ...\n");
923             } else {
924                 diag_printf("NAND BOOT fuse blown successfully ...\n");
925             }
926         } else {
927             diag_printf("Not ready: %s, %s\n", argv[1], argv[2]);
928 #endif
929         }
930     } else if (argc == 4) {
931         if (!parse_num(*(&argv[1]), (unsigned long *)&bank, &argv[1], " ")) {
932                 diag_printf("Error: Invalid parameter\n");
933                 return;
934         }
935         if (!parse_num(*(&argv[2]), (unsigned long *)&row, &argv[2], " ")) {
936                 diag_printf("Error: Invalid parameter\n");
937                 return;
938         }
939         if (!parse_num(*(&argv[3]), (unsigned long *)&value, &argv[3], " ")) {
940                 diag_printf("Error: Invalid parameter\n");
941                 return;
942         }
943
944         diag_printf("Blowing fuse at bank:%d row:%d value:%d\n",
945                     bank, row, value);
946         for (i = 0; i < 8; i++) {
947             if (((value >> i) & 0x1) == 0) {
948                 continue;
949             }
950             if (fuse_blow(bank, row, i) != 0) {
951                 diag_printf("fuse_blow(bank: %d, row: %d, bit: %d failed\n",
952                             bank, row, i);
953             } else {
954                 diag_printf("fuse_blow(bank: %d, row: %d, bit: %d successful\n",
955                             bank, row, i);
956             }
957         }
958         sense_fuse(bank, row, 0);
959
960     } else {
961         diag_printf("Passing in wrong arguments: %d\n", argc);
962     }
963     /* Reset to default string */
964     strcpy(ready_to_blow, INIT_STRING);;
965 }
966
967 /* precondition: m>0 and n>0.  Let g=gcd(m,n). */
968 int gcd(int m, int n)
969 {
970     int t;
971     while(m > 0) {
972         if(n > m) {t = m; m = n; n = t;} /* swap */
973         m -= n;
974     }
975     return n;
976 }
977
978 #define CLOCK_SRC_DETECT_MS         100
979 #define CLOCK_IPG_DEFAULT           66500000
980 #define CLOCK_SRC_DETECT_MARGIN     500000
981 void mxc_show_clk_input(void)
982 {
983     u32 c1, c2, diff, ipg_real, num = 0;
984     u32 prcs = (readl(CCM_BASE_ADDR + CLKCTL_CCMR) >> 1) & 0x3;
985
986     return;  // FIXME
987
988     switch (prcs) {
989     case 0x01:
990         diag_printf("FPM enabled --> 32KHz input source\n");
991         return;
992     case 0x02:
993         break;
994     default:
995         diag_printf("Error %d: unknown clock source %d\n", __LINE__, prcs);
996         return;
997     }
998
999     // enable GPT with IPG clock input
1000     writel(0x241, GPT_BASE_ADDR + GPTCR);
1001     // prescaler = 1
1002     writel(0, GPT_BASE_ADDR + GPTPR);
1003
1004     c1 = readl(GPT_BASE_ADDR + GPTCNT);
1005     // use 32KHz input clock to get the delay
1006     hal_delay_us(CLOCK_SRC_DETECT_MS * 1000);
1007     c2 = readl(GPT_BASE_ADDR + GPTCNT);
1008     diff = (c2 > c1) ? (c2 - c1) : (0xFFFFFFFF - c1 + c2);
1009
1010     ipg_real = diff * (1000 / CLOCK_SRC_DETECT_MS);
1011
1012     if (ipg_real > (CLOCK_IPG_DEFAULT + CLOCK_SRC_DETECT_MARGIN)) {
1013         if (g_clock_src != FREQ_27MHZ)
1014             num = 27;
1015     } else if (ipg_real < (CLOCK_IPG_DEFAULT - CLOCK_SRC_DETECT_MARGIN)) {
1016         if (g_clock_src != FREQ_26MHZ)
1017             num = 26;
1018     }
1019     if (num != 0) {
1020         diag_printf("Error: Actural clock input is %d MHz\n", num);
1021         diag_printf("       ipg_real=%d CLOCK_IPG_DEFAULT - CLOCK_SRC_DETECT_MARGIN=%d\n\n",
1022                     ipg_real, CLOCK_IPG_DEFAULT - CLOCK_SRC_DETECT_MARGIN);
1023         diag_printf("       But clock source defined to be %d\n\n", g_clock_src);
1024         hal_delay_us(2000000);
1025     } else {
1026         diag_printf("ipg_real=%d CLOCK_IPG_DEFAULT - CLOCK_SRC_DETECT_MARGIN=%d\n\n",
1027                     ipg_real, CLOCK_IPG_DEFAULT - CLOCK_SRC_DETECT_MARGIN);
1028         diag_printf("clock source defined to be %d\n\n", g_clock_src);
1029     }
1030 }
1031
1032 RedBoot_init(mxc_show_clk_input, RedBoot_INIT_LAST);