TX51 pre-release
[karo-tx-redboot.git] / packages / hal / arm / mx37 / 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 int gcd(int m, int n);
48
49 typedef unsigned long long      u64;
50 typedef unsigned int            u32;
51 typedef unsigned short          u16;
52 typedef unsigned char           u8;
53
54 #define SZ_DEC_1M               1000000
55 #define PLL_PD_MAX              16              //actual pd+1
56 #define PLL_MFI_MAX             15
57 #define PLL_MFI_MIN             5
58 #define ARM_DIV_MAX             8
59 #define IPG_DIV_MAX             4
60 #define AHB_DIV_MAX             8
61 #define EMI_DIV_MAX             8
62 #define NFC_DIV_MAX             8
63
64 #define REF_IN_CLK_NUM  4
65 struct fixed_pll_mfd {
66         u32 ref_clk_hz;
67         u32 mfd;
68 };
69 const struct fixed_pll_mfd fixed_mfd[REF_IN_CLK_NUM] = {
70         {0,                                       0},      // reserved
71         {0,                                       0},      // reserved
72         {FREQ_24MHZ,              24 * 16},        // 384
73         {0,                                       0},      // reserved
74 };
75
76 struct pll_param {
77         u32 pd;
78         u32 mfi;
79         u32 mfn;
80         u32 mfd;
81 };
82
83 #define PLL_FREQ_MAX(_ref_clk_)    (2 * _ref_clk_ * PLL_MFI_MAX)
84 #define PLL_FREQ_MIN(_ref_clk_)    ((2 * _ref_clk_ * (PLL_MFI_MIN - 1)) / PLL_PD_MAX)
85 #define AHB_CLK_MAX             133333333
86 #define IPG_CLK_MAX             (AHB_CLK_MAX / 2)
87 #define NFC_CLK_MAX             25000000
88 // IPU-HSP clock is independent of the HCLK and can go up to 177MHz but requires
89 // higher voltage support. For simplicity, limit it to 133MHz
90 #define HSP_CLK_MAX             133333333
91
92 #define ERR_WRONG_CLK   -1
93 #define ERR_NO_MFI              -2
94 #define ERR_NO_MFN              -3
95 #define ERR_NO_PD               -4
96 #define ERR_NO_PRESC    -5
97 #define ERR_NO_AHB_DIV  -6
98
99 u32 pll_clock(enum plls pll);
100 u32 get_main_clock(enum main_clocks clk);
101 u32 get_peri_clock(enum peri_clocks clk);
102
103 static volatile u32 *pll_base[] =
104 {
105         REG32_PTR(PLL1_BASE_ADDR),
106         REG32_PTR(PLL2_BASE_ADDR),
107         REG32_PTR(PLL3_BASE_ADDR),
108 };
109
110 #define NOT_ON_VAL      0xDEADBEEF
111
112 static void clock_setup(int argc, char *argv[]);
113 static void clko(int argc, char *argv[]);
114
115 RedBoot_cmd("clock",
116                         "Setup/Display clock (max AHB=133MHz, max IPG=66.5MHz)\nSyntax:",
117                         "[<core clock in MHz> [:<AHB-to-core divider>[:<IPG-to-AHB divider>]]] \n\n\
118 If a divider is zero or no divider is specified, the optimal divider values \n\
119 will be chosen. Examples:\n\
120    [clock]                 -> Show various clocks\n\
121    [clock 532]     -> Core=532  AHB=133                   IPG=66.5\n\
122    [clock 399]     -> Core=399  AHB=133                   IPG=66.5\n\
123    [clock 532:8]   -> Core=532  AHB=66.5(Core/8)  IPG=66.5\n\
124    [clock 532:8:2] -> Core=532  AHB=66.5(Core/8)  IPG=33.25(AHB/2)\n",
125                         clock_setup
126                    );
127
128 /*!
129  * This is to calculate various parameters based on reference clock and
130  * targeted clock based on the equation:
131  *              t_clk = 2*ref_freq*(mfi + mfn/(mfd+1))/(pd+1)
132  * This calculation is based on a fixed MFD value for simplicity.
133  *
134  * @param ref           reference clock freq in Hz
135  * @param target        targeted clock in Hz
136  * @param p_pd          calculated pd value (pd value from register + 1) upon return
137  * @param p_mfi         calculated actual mfi value upon return
138  * @param p_mfn         calculated actual mfn value upon return
139  * @param p_mfd         fixed mfd value (mfd value from register + 1) upon return
140  *
141  * @return                      0 if successful; non-zero otherwise.
142  */
143 int calc_pll_params(u32 ref, u32 target, struct pll_param *pll)
144 {
145         u64 pd, mfi = 1, mfn, mfd, n_target = target, n_ref = ref, i;
146
147         // make sure targeted freq is in the valid range. Otherwise the
148         // following calculation might be wrong!!!
149         if (n_target < PLL_FREQ_MIN(ref) || n_target > PLL_FREQ_MAX(ref))
150                 return ERR_WRONG_CLK;
151         for (i = 0; ; i++) {
152                 if (i == REF_IN_CLK_NUM)
153                         return ERR_WRONG_CLK;
154                 if (fixed_mfd[i].ref_clk_hz == ref) {
155                         mfd = fixed_mfd[i].mfd;
156                         break;
157                 }
158         }
159         // Use n_target and n_ref to avoid overflow
160         for (pd = 1; pd <= PLL_PD_MAX; pd++) {
161                 mfi = (n_target * pd) / (2 * n_ref);
162                 if (mfi > PLL_MFI_MAX) {
163                         return ERR_NO_MFI;
164                 } else if (mfi < 5) {
165                         continue;
166                 }
167                 break;
168         }
169         // Now got pd and mfi already
170         mfn = (((n_target * pd) / 2 - n_ref * mfi) * mfd) / n_ref;
171 #ifdef CMD_CLOCK_DEBUG
172         diag_printf("%d: ref=%d, target=%d, pd=%d, mfi=%d,mfn=%d, mfd=%d\n",
173                                 __LINE__, ref, (u32)n_target, (u32)pd, (u32)mfi, (u32)mfn, (u32)mfd);
174 #endif
175         i = 1;
176         if (mfn != 0)
177                 i = gcd(mfd, mfn);
178         pll->pd = (u32)pd;
179         pll->mfi = (u32)mfi;
180         pll->mfn = (u32)(mfn / i);
181         pll->mfd = (u32)(mfd / i);
182         return 0;
183 }
184
185 /*!
186  * This function assumes the expected core clock has to be changed by
187  * modifying the PLL. This is NOT true always but for most of the times,
188  * it is. So it assumes the PLL output freq is the same as the expected
189  * core clock (presc=1) unless the core clock is less than PLL_FREQ_MIN.
190  * In the latter case, it will try to increase the presc value until
191  * (presc*core_clk) is greater than PLL_FREQ_MIN. It then makes call to
192  * calc_pll_params() and obtains the values of PD, MFI,MFN, MFD based
193  * on the targeted PLL and reference input clock to the PLL. Lastly,
194  * it sets the register based on these values along with the dividers.
195  * Note 1) There is no value checking for the passed-in divider values
196  *                 so the caller has to make sure those values are sensible.
197  *              2) Also adjust the NFC divider such that the NFC clock doesn't
198  *                 exceed NFC_CLK_MAX.
199  *              3) IPU HSP clock is independent of AHB clock. Even it can go up to
200  *                 177MHz for higher voltage, this function fixes the max to 133MHz.
201  *              4) This function should not have allowed diag_printf() calls since
202  *                 the serial driver has been stoped. But leave then here to allow
203  *                 easy debugging by NOT calling the cyg_hal_plf_serial_stop().
204  *
205  * @param ref           pll input reference clock (32KHz or 26MHz)
206  * @param core_clk      core clock in Hz
207  * @param emi_clk       emi clock in Hz
208  * @param ahb_div       ahb divider to divide the core clock to get ahb clock
209  *                                      (ahb_div - 1) needs to be set in the register
210  * @param ipg_div       ipg divider to divide the core clock to get ipg clock
211  *                                      (ipg_div - 1) needs to be set in the register
212  # @return                      0 if successful; non-zero otherwise
213  */
214 int configure_clock(u32 ref, u32 core_clk, u32 emi_clk, u32 ahb_div, u32 ipg_div)
215 {
216 #if 0
217         u32 pll, arm_div = 1, emi_div = 0, nfc_div, ascsr, acdr, acder2;
218         struct pll_param pll_param;
219         int ret;
220
221         // assume pll default to core clock first
222         pll = core_clk;
223         // when core_clk >= PLL_FREQ_MIN, the presc can be 1.
224         // Otherwise, need to calculate presc value below and adjust the targeted pll
225         if (core_clk < PLL_FREQ_MIN) {
226                 for (presc = 1; presc <= PRESC_MAX; presc++) {
227                         if ((core_clk * presc) > PLL_FREQ_MIN) {
228                                 break;
229                         }
230                 }
231                 if (presc == (PRESC_MAX + 1)) {
232                         diag_printf("can't make presc=%d\n", presc);
233                         return ERR_NO_PRESC;
234                 }
235                 pll = core_clk * presc;
236         }
237         // get hsp_div
238         for (hsp_div = 1; hsp_div <= HSP_PODF_MAX; hsp_div++) {
239                 if ((pll / hsp_div) <= HSP_CLK_MAX) {
240                         break;
241                 }
242         }
243         if (hsp_div == (HSP_PODF_MAX + 1)) {
244                 diag_printf("can't make hsp_div=%d\n", hsp_div);
245                 return ERR_NO_PRESC;
246         }
247
248         // get nfc_div - make sure optimal NFC clock but less than NFC_CLK_MAX
249         for (nfc_div = 1; nfc_div <= NFC_PODF_MAX; nfc_div++) {
250                 if ((pll / (ahb_div * nfc_div)) <= NFC_CLK_MAX) {
251                         break;
252                 }
253         }
254
255         // pll is now the targeted pll output. Use it along with ref input clock
256         // to get pd, mfi, mfn, mfd
257         if ((ret = calc_pll_params(ref, pll, &pd, &mfi, &mfn, &mfd)) != 0) {
258                 diag_printf("can't find pll parameters: %d\n", ret);
259                 return ret;
260         }
261 #ifdef CMD_CLOCK_DEBUG
262         diag_printf("ref=%d, pll=%d, pd=%d, mfi=%d,mfn=%d, mfd=%d\n",
263                                 ref, pll, pd, mfi, mfn, mfd);
264 #endif
265
266         // blindly increase divider first to avoid too fast ahbclk and ipgclk
267         // in case the core clock increases too much
268         pdr0 = readl(CCM_BASE_ADDR + CLKCTL_PDR0);
269         pdr0 &= ~0x000000FF;
270         // increase the dividers. should work even when core clock is 832 (26*2*16)MHz
271         // which is unlikely true.
272         pdr0 |= (1 << 6) | (6 << 3) | (0 << 0);
273         writel(pdr0, CCM_BASE_ADDR + CLKCTL_PDR0);
274         // calculate new pdr0
275         pdr0 &= ~0x00003FFF;
276         pdr0 |= ((hsp_div - 1) << 11) | ((nfc_div - 1) << 8) | ((ipg_div - 1) << 6) |
277                         ((ahb_div - 1) << 3) | ((presc - 1) << 0);
278
279         // update PLL register
280         if ((mfd >= (10 * mfn)) || ((10 * mfn) >= (9 * mfd)))
281                 brmo = 1;
282
283         mpctl0 = readl(CCM_BASE_ADDR + CLKCTL_MPCTL);
284         mpctl0 = (mpctl0 & 0x4000C000)  |
285                          (brmo << 31)                   |
286                          ((pd - 1) << 26)               |
287                          ((mfd - 1) << 16)              |
288                          (mfi << 10)                    |
289                          mfn;
290         writel(mpctl0, CCM_BASE_ADDR + CLKCTL_MPCTL);
291         writel(pdr0, CCM_BASE_ADDR + CLKCTL_PDR0);
292         // add some delay for new values to take effect
293         for (i = 0; i < 10000; i++);
294 #endif
295         return 0;
296 }
297
298 static void clock_setup(int argc,char *argv[])
299 {
300 #if 0
301         u32 i, core_clk, ipg_div, data[3], temp, ahb_div, ahb_clk, ipg_clk;
302         int ret;
303
304         if (argc == 1)
305                 goto print_clock;
306
307         for (i = 0;      i < 3;  i++) {
308                 if (!parse_num(argv[1], &temp, &argv[1], ":")) {
309                         diag_printf("Error: Invalid parameter\n");
310                         return;
311                 }
312                 data[i] = temp;
313         }
314
315         core_clk = data[0] * SZ_DEC_1M;
316         ahb_div = data[1];      // actual register field + 1
317         ipg_div = data[2];      // actual register field + 1
318
319         if (core_clk < (PLL_FREQ_MIN / PRESC_MAX) || core_clk > PLL_FREQ_MAX) {
320                 diag_printf("Targeted core clock should be within [%d - %d]\n",
321                                         PLL_FREQ_MIN / PRESC_MAX, PLL_FREQ_MAX);
322                 return;
323         }
324
325         // find the ahb divider
326         if (ahb_div > AHB_DIV_MAX) {
327                 diag_printf("Invalid AHB divider: %d. Maximum value is %d\n",
328                                         ahb_div, AHB_DIV_MAX);
329                 return;
330         }
331         if (ahb_div == 0) {
332                 // no HCLK divider specified
333                 for (ahb_div = 1; ; ahb_div++) {
334                         if ((core_clk / ahb_div) <= AHB_CLK_MAX) {
335                                 break;
336                         }
337                 }
338         }
339         if (ahb_div > AHB_DIV_MAX || (core_clk / ahb_div) > AHB_CLK_MAX) {
340                 diag_printf("Can't make AHB=%d since max=%d\n",
341                                         core_clk / ahb_div, AHB_CLK_MAX);
342                 return;
343         }
344
345         // find the ipg divider
346         ahb_clk = core_clk / ahb_div;
347         if (ipg_div > IPG_DIV_MAX) {
348                 diag_printf("Invalid IPG divider: %d. Maximum value is %d\n",
349                                         ipg_div, IPG_DIV_MAX);
350                 return;
351         }
352         if (ipg_div == 0) {
353                 ipg_div++;                      // At least =1
354                 if (ahb_clk > IPG_CLK_MAX)
355                         ipg_div++;              // Make it =2
356         }
357         if (ipg_div > IPG_DIV_MAX || (ahb_clk / ipg_div) > IPG_CLK_MAX) {
358                 diag_printf("Can't make IPG=%d since max=%d\n",
359                                         (ahb_clk / ipg_div), IPG_CLK_MAX);
360                 return;
361         }
362         ipg_clk = ahb_clk / ipg_div;
363
364         diag_printf("Trying to set core=%d ahb=%d ipg=%d...\n",
365                                 core_clk, ahb_clk, ipg_clk);
366
367         // stop the serial to be ready to adjust the clock
368         hal_delay_us(100000);
369         cyg_hal_plf_serial_stop();
370         // adjust the clock
371         ret = configure_clock(PLL_REF_CLK, core_clk, ahb_div, ipg_div);
372         // restart the serial driver
373         cyg_hal_plf_serial_init();
374         hal_delay_us(100000);
375
376         if (ret != 0) {
377                 diag_printf("Failed to setup clock: %d\n", ret);
378                 return;
379         }
380         diag_printf("\n<<<New clock setting>>>\n");
381
382         // Now printing clocks
383 print_clock:
384 #endif
385         diag_printf("\nPLL1\t\tPLL2\t\tPLL3\n");
386         diag_printf("========================================\n");
387         diag_printf("%-16d%-16d%-16d\n\n", pll_clock(PLL1), pll_clock(PLL2),
388                                 pll_clock(PLL3));
389         diag_printf("CPU\t\tAHB\t\tIPG\t\tEMI_CLK\n");
390         diag_printf("========================================================\n");
391         diag_printf("%-16d%-16d%-16d%-16d\n\n",
392                                 get_main_clock(CPU_CLK),
393                                 get_main_clock(AHB_CLK),
394                                 get_main_clock(IPG_CLK),
395                                 get_main_clock(DDR_CLK));
396
397         diag_printf("NFC\t\tUSB\n");
398         diag_printf("========================================\n");
399         diag_printf("%-16d%-16d\n\n",
400                                 get_main_clock(NFC_CLK),
401                                 get_main_clock(USB_CLK));
402
403         diag_printf("UART1-3\t\tSSI1\t\tSSI2\t\tCSI\n");
404         diag_printf("===========================================");
405         diag_printf("=============\n");
406
407         diag_printf("%-16d%-16d%-16d%-16d\n\n",
408                                 get_peri_clock(UART1_BAUD),
409                                 get_peri_clock(SSI1_BAUD),
410                                 get_peri_clock(SSI2_BAUD),
411                                 get_peri_clock(CSI_BAUD));
412
413         diag_printf("MSTICK1\t\tMSTICK2\t\tSPI\n");
414         diag_printf("===========================================");
415         diag_printf("=============\n");
416
417         diag_printf("%-16d%-16d%-16d\n\n",
418                                 get_peri_clock(MSTICK1_CLK),
419                                 get_peri_clock(MSTICK2_CLK),
420                                 get_peri_clock(SPI1_CLK));
421 #if 0
422         diag_printf("IPG_PERCLK as baud clock for: UART1-5, I2C, OWIRE, SDHC");
423         if (((readl(EPIT1_BASE_ADDR) >> 24) & 0x3) == 0x2) {
424                 diag_printf(", EPIT");
425         }
426         if (((readl(GPT1_BASE_ADDR) >> 6) & 0x7) == 0x2) {
427                 diag_printf("GPT,");
428         }
429 #endif
430         diag_printf("\n");
431
432 }
433
434 /*!
435  * This function returns the PLL output value in Hz based on pll.
436  */
437 u32 pll_clock(enum plls pll)
438 {
439         u64 mfi, mfn, mfd, pdf, ref_clk, pll_out, sign;
440         u64 dp_ctrl, dp_op, dp_mfd, dp_mfn, clk_sel;
441         u8 dbl = 0;
442
443         dp_ctrl = pll_base[pll][PLL_DP_CTL >> 2];
444         clk_sel = MXC_GET_FIELD(dp_ctrl, 2, 8);
445         ref_clk = fixed_mfd[clk_sel].ref_clk_hz;
446
447         if ((pll_base[pll][PLL_DP_CTL >> 2] & 0x80) == 0) {
448                 dp_op = pll_base[pll][PLL_DP_OP >> 2];
449                 dp_mfd = pll_base[pll][PLL_DP_MFD >> 2];
450                 dp_mfn = pll_base[pll][PLL_DP_MFN >> 2];
451         } else {
452                 dp_op = pll_base[pll][PLL_DP_HFS_OP >> 2];
453                 dp_mfd = pll_base[pll][PLL_DP_HFS_MFD >> 2];
454                 dp_mfn = pll_base[pll][PLL_DP_HFS_MFN >> 2];
455         }
456         pdf = dp_op & 0xF;
457         mfi = (dp_op >> 4) & 0xF;
458         mfi = (mfi <= 5) ? 5: mfi;
459         mfd = dp_mfd & 0x07FFFFFF;
460         mfn = dp_mfn & 0x07FFFFFF;
461
462         sign = (mfn < 0x4000000) ? 0: 1;
463         mfn = (mfn <= 0x4000000) ? mfn: (0x8000000 - mfn);
464
465         dbl = ((dp_ctrl >> 12) & 0x1) + 1;
466
467         dbl = dbl * 2;
468         if (sign == 0) {
469                 pll_out = (dbl * ref_clk * mfi + ((dbl * ref_clk * mfn) / (mfd + 1))) /
470                                   (pdf + 1);
471         } else {
472                 pll_out = (dbl * ref_clk * mfi - ((dbl * ref_clk * mfn) / (mfd + 1))) /
473                                   (pdf + 1);
474         }
475
476         return (u32)pll_out;
477 }
478
479 // The clocks are on by default. But need to setup the IOMUX
480 void clock_spi_enable(unsigned int spi_clk)
481 {
482         // Take care of  SPI2
483         writel(0x0, IOMUXC_BASE_ADDR + 0x14C);
484         writel(0x1, IOMUXC_BASE_ADDR + 0x3AC);
485         writel(0x100, IOMUXC_BASE_ADDR + 0x494);
486         writel(0x0, IOMUXC_BASE_ADDR + 0x148);
487         writel(0x1, IOMUXC_BASE_ADDR + 0x3A8);
488         writel(0x3, IOMUXC_BASE_ADDR + 0x168);
489         writel(0x180, IOMUXC_BASE_ADDR + 0x3C8);
490         writel(0x0, IOMUXC_BASE_ADDR + 0x158);
491         writel(0x101, IOMUXC_BASE_ADDR + 0x3B8);
492         writel(0x0, IOMUXC_BASE_ADDR + 0x150);
493         writel(0x1, IOMUXC_BASE_ADDR + 0x3B0);
494         writel(0x100, IOMUXC_BASE_ADDR + 0x490);
495 }
496
497 /*!
498  * This function returns the low power audio clock.
499  */
500 u32 get_lp_apm(void)
501 {
502         u32 ret_val = 0;
503         u32 ccsr = readl(CCM_BASE_ADDR + CLKCTL_CCSR);
504
505         if (((ccsr >> 9) & 1) == 0) {
506                 ret_val = FREQ_24MHZ;
507         } else {
508                 ret_val = FREQ_32000HZ;
509         }
510         return ret_val;
511 }
512
513 /*!
514  * This function returns the periph_clk.
515  */
516 u32 get_periph_clk(void)
517 {
518         u32 cbcdr6 = readl(CCM_BASE_ADDR + CLKCTL_CBCDR6);
519         u32 camr = readl(CCM_BASE_ADDR + CLKCTL_CAMR);
520         u32 ret_val = 0, clk_sel;
521
522         if (((cbcdr6 >> 4) & 1) == 0) {
523                 ret_val = pll_clock(PLL2);
524         } else {
525                 clk_sel = (camr >> 12) & 3;
526                 if (clk_sel == 0) {
527                         ret_val = pll_clock(PLL1);
528                 } else if (clk_sel == 1) {
529                         ret_val = pll_clock(PLL3);
530                 } else if (clk_sel == 2) {
531                         ret_val = get_lp_apm();
532                 }
533         }
534
535         return ret_val;
536 }
537
538 /*!
539  * This function returns the emi_core_clk_root clock.
540  */
541 u32 get_emi_core_clk(void)
542 {
543         u32 cbcdr6 = readl(CCM_BASE_ADDR + CLKCTL_CBCDR6);
544         u32 cbcdr2 = readl(CCM_BASE_ADDR + CLKCTL_CBCDR2);
545         u32 clk_sel = 0, pdf = 0, max_pdf = 0, peri_clk = 0, ahb_clk = 0;
546         u32 ret_val = 0;
547
548         max_pdf = (cbcdr2 >> 10) & 0x7;
549         peri_clk = get_periph_clk();
550         ahb_clk = peri_clk / (max_pdf + 1);
551
552         pdf = cbcdr6 & 0x7;
553         clk_sel = (cbcdr6 >> 3) & 1;
554         if (clk_sel == 0) {
555                 ret_val = peri_clk / (pdf + 1);
556         } else {
557                 ret_val = ahb_clk / (pdf + 1);
558         }
559         return ret_val;
560 }
561
562 // The clocks are on by default. But need to setup the IOMUX
563 void mxc_i2c_init(unsigned int module_base)
564 {
565         unsigned int val, reg;
566
567         switch (module_base) {
568         case I2C_BASE_ADDR:
569                 writel(0x0, IOMUXC_BASE_ADDR + 0x104);
570                 writel(0x1, IOMUXC_BASE_ADDR + 0x5C0);
571                 writel(0xA8, IOMUXC_BASE_ADDR + 0x364);
572
573                 writel(0x0, IOMUXC_BASE_ADDR + 0x108);
574                 writel(0x1, IOMUXC_BASE_ADDR + 0x5C4);
575                 writel(0xA8, IOMUXC_BASE_ADDR + 0x368);
576
577                 writel(0x100, IOMUXC_BASE_ADDR + 0x4D0);
578                 break;
579         case I2C2_BASE_ADDR:
580                 // i2c SCL
581                 writel(0x2, IOMUXC_BASE_ADDR + 0x210);
582                 writel(0x1EC, IOMUXC_BASE_ADDR + 0x468);
583                 writel(0x1, IOMUXC_BASE_ADDR + 0x5C8);
584                 // i2c SDA
585                 writel(0x2, IOMUXC_BASE_ADDR + 0x214);
586                 writel(0x1EC, IOMUXC_BASE_ADDR + 0x46C);
587                 writel(0x1, IOMUXC_BASE_ADDR + 0x5CC);
588                 break;
589         case I2C3_BASE_ADDR:
590                 reg = IOMUXC_BASE_ADDR + 0x84;
591                 val = (readl(reg) & 0xFFFFFF00) | 0x24; // alt mode 1
592                 writel(val, reg);
593                 reg = IOMUXC_BASE_ADDR + 0x80;
594                 val = (readl(reg) & 0x00FFFFFF) | 0x24000000; // alt mode 1
595                 writel(val, reg);
596                 break;
597         default:
598                 diag_printf("Invalid I2C base: 0x%x\n", module_base);
599                 return;
600         }
601 }
602
603 /*!
604  * This function returns the main clock value in Hz.
605  */
606 u32 get_main_clock(enum main_clocks clk)
607 {
608         u32 mcu_podf, max_pdf, ipg_pdf, nfc_pdf, clk_sel;
609         u32 pll, ret_val = 0;
610         u32 cacrr = readl(CCM_BASE_ADDR + CLKCTL_CACRR);
611         u32 cbcdr2 = readl(CCM_BASE_ADDR + CLKCTL_CBCDR2);
612         u32 cbcdr3 = readl(CCM_BASE_ADDR + CLKCTL_CBCDR3);
613         u32 cbcdr4 = readl(CCM_BASE_ADDR + CLKCTL_CBCDR4);
614         u32 cbcdr5 = readl(CCM_BASE_ADDR + CLKCTL_CBCDR5);
615         u32 cbcdr7 = readl(CCM_BASE_ADDR + CLKCTL_CBCDR7);
616         u32 camr = readl(CCM_BASE_ADDR + CLKCTL_CAMR);
617
618         switch (clk) {
619         case CPU_CLK:
620                 mcu_podf = cacrr & 0x7;
621                 pll = pll_clock(PLL1);
622                 ret_val = pll / (mcu_podf + 1);
623                 break;
624         case AHB_CLK:
625                 max_pdf = (cbcdr2 >> 10) & 0x7;
626                 pll = get_periph_clk();
627                 ret_val = pll / (max_pdf + 1);
628                 break;
629         case IPG_CLK:
630                 max_pdf = (cbcdr2 >> 10) & 0x7;
631                 ipg_pdf = (cbcdr2 >> 8) & 0x3;
632                 pll = get_periph_clk();
633                 ret_val = pll / ((max_pdf + 1) * (ipg_pdf + 1));
634                 break;
635         case IPG_PER_CLK:
636 #if 0
637                 clk_sel = ccmr & (1 << 24);
638                 pdf = (mpdr0 >> 16) & 0x1F;
639                 if (clk_sel != 0) {
640                         // get the ipg_clk
641                         max_pdf = (reg >> 3) & 0x7;
642                         ipg_pdf = (reg >> 6) & 0x3;
643                         pll = pll_clock(PLL1);
644                         ret_val = pll / ((max_pdf + 1) * (ipg_pdf + 1));
645                 } else {
646                         ret_val = pll_clock(PLL2) / (pdf + 1);
647                 }
648 #endif
649                 break;
650         case DDR_CLK:
651                 clk_sel = (camr >> 10) & 3;
652                 if (clk_sel == 0) {
653                         ret_val = get_periph_clk() / ((cbcdr3 & 7) + 1);
654                 } else if (clk_sel == 1) {
655                         ret_val = get_periph_clk() / ((cbcdr4 & 7) + 1);
656                 } else if (clk_sel == 2) {
657                         ret_val = get_periph_clk() / ((cbcdr5 & 7) + 1);
658                 } else if (clk_sel == 3) {
659                         ret_val = get_emi_core_clk();
660                 }
661                 break;
662         case NFC_CLK:
663                 nfc_pdf = cbcdr7 & 0x7;
664                 pll = get_emi_core_clk();
665                 /* AHB/nfc_pdf */
666                 ret_val = pll / (nfc_pdf + 1);
667                 break;
668         case USB_CLK:
669 #if 0
670                 usb_prdf = reg1 >> 30;
671                 usb_podf = (reg1 >> 27) & 0x7;
672                 pll = pll_clock(PLL2);
673                 ret_val = pll / ((usb_prdf + 1) * (usb_podf + 1));
674 #endif
675                 break;
676         default:
677                 diag_printf("Unknown clock: %d\n", clk);
678                 break;
679         }
680
681         return ret_val;
682 }
683
684 /*!
685  * This function returns the peripheral clock value in Hz.
686  */
687 u32 get_peri_clock(enum peri_clocks clk)
688 {
689         u32 ret_val = 0, pdf, pre_pdf, clk_sel;
690         u32 cscmr1 = readl(CCM_BASE_ADDR + CLKCTL_CSCMR1);
691         u32 cscdr1 = readl(CCM_BASE_ADDR + CLKCTL_CSCDR1);
692         u32 cscdr2 = readl(CCM_BASE_ADDR + CLKCTL_CSCDR2);
693         u32 cs1cdr = readl(CCM_BASE_ADDR + CLKCTL_CS1CDR);
694         u32 cs2cdr = readl(CCM_BASE_ADDR + CLKCTL_CS2CDR);
695
696         switch (clk) {
697         case UART1_BAUD:
698         case UART2_BAUD:
699         case UART3_BAUD:
700                 pre_pdf = (cscdr1 >> 3) & 0x7;
701                 pdf = cscdr1 & 0x7;
702                 clk_sel = (cscmr1 >> 24) & 3;
703                 if (clk_sel == 0) {
704                         ret_val = pll_clock(PLL1) / ((pre_pdf + 1) * (pdf + 1));
705                 } else if (clk_sel == 1) {
706                         ret_val = pll_clock(PLL2) / ((pre_pdf + 1) * (pdf + 1));
707                 } else if (clk_sel == 2) {
708                         ret_val = pll_clock(PLL3) / ((pre_pdf + 1) * (pdf + 1));
709                 }
710                 break;
711         case SSI1_BAUD:
712                 pre_pdf = (cs1cdr >> 6) & 0x7;
713                 pdf = cs1cdr & 0x3F;
714                 clk_sel = (cscmr1 >> 14) & 3;
715                 if (clk_sel == 0) {
716                         ret_val = pll_clock(PLL1) / ((pre_pdf + 1) * (pdf + 1));
717                 } else if (clk_sel == 0x1) {
718                         ret_val = pll_clock(PLL2) / ((pre_pdf + 1) * (pdf + 1));
719                 } else if (clk_sel == 0x2) {
720                         ret_val = pll_clock(PLL3) / ((pre_pdf + 1) * (pdf + 1));
721                 } else {
722                         diag_printf("Error: Use reserved value for SSI1!\n");
723                         ret_val = 0;
724                 }
725                 break;
726         case SSI2_BAUD:
727                 pre_pdf = (cs2cdr >> 6) & 0x7;
728                 pdf = cs2cdr & 0x3F;
729                 clk_sel = (cscmr1 >> 12) & 3;
730                 if (clk_sel == 0) {
731                         ret_val = pll_clock(PLL1) / ((pre_pdf + 1) * (pdf + 1));
732                 } else if (clk_sel == 0x1) {
733                         ret_val = pll_clock(PLL2) / ((pre_pdf + 1) * (pdf + 1));
734                 } else if (clk_sel == 0x2) {
735                         ret_val = pll_clock(PLL3) / ((pre_pdf + 1) * (pdf + 1));
736                 } else {
737                         diag_printf("Error: Use reserved value for SSI2!\n");
738                         ret_val = 0;
739                 }
740                 break;
741         case CSI_BAUD:
742 #if 0
743                 clk_sel = ccmr & (1 << 25);
744                 pdf = (mpdr0 >> 23) & 0x1FF;
745                 ret_val = (clk_sel != 0) ? (pll_clock(PLL3) / (pdf + 1)) :
746                                   (pll_clock(PLL2) / (pdf + 1));
747 #endif
748                 break;
749         case MSTICK1_CLK:
750 #if 0
751                 pdf = mpdr2 & 0x3F;
752                 ret_val = pll_clock(PLL2) / (pdf + 1);
753 #endif
754                 break;
755         case MSTICK2_CLK:
756 #if 0
757                 pdf = (mpdr2 >> 7) & 0x3F;
758                 ret_val = pll_clock(PLL2) / (pdf + 1);
759 #endif
760                 break;
761         case SPI1_CLK:
762         case SPI2_CLK:
763                 pre_pdf = (cscdr2 >> 25) & 0x7;
764                 pdf = (cscdr2 >> 19) & 0x3F;
765                 clk_sel = (cscmr1 >> 4) & 3;
766                 if (clk_sel == 0) {
767                         ret_val = pll_clock(PLL1) / ((pre_pdf + 1) * (pdf + 1));
768                 } else if (clk_sel == 1) {
769                         ret_val = pll_clock(PLL2) / ((pre_pdf + 1) * (pdf + 1));
770                 } else if (clk_sel == 2) {
771                         ret_val = pll_clock(PLL3) / ((pre_pdf + 1) * (pdf + 1));
772                 }
773                 break;
774         default:
775                 diag_printf("%s(): This clock: %d not supported yet \n",
776                                         __FUNCTION__, clk);
777                 break;
778         }
779
780         return ret_val;
781 }
782
783 RedBoot_cmd("clko",
784                         "Select clock source for CLKO (J11 on the CPU daughter card)",
785                         " Default is 1/8 of ARM core\n\
786                   <0> - display current clko selection \n\
787                   <1> - mpl_dpdgck_clk (MPLL) \n\
788                   <2> - ipg_clk_ccm (IPG) \n\
789                   <3> - upl_dpdgck_clk (UPLL) \n\
790                   <4> - pll_ref_clk \n\
791                   <5> - fpm_ckil512_clk \n\
792                   <6> - ipg_clk_ahb_arm (AHB) \n\
793                   <7> - ipg_clk_arm (ARM) \n\
794                   <8> - spl_dpdgck_clk (SPLL) \n\
795                   <9> - ckih \n\
796                   <10> - ipg_clk_ahb_emi_clk \n\
797                   <11> - ipg_clk_ipu_hsp \n\
798                   <12> - ipg_clk_nfc_20m \n\
799                   <13> - ipg_clk_perclk_uart1 (IPG_PER)",
800                         clko
801                    );
802
803 static char *clko_name[] ={
804         "NULL",
805         "1/8 of mpl_dpdgck_clk (MPLL)",
806         "ipg_clk_ccm (IPG)",
807         "1/8 of upl_dpdgck_clk (UPLL)",
808         "pll_ref_clk",
809         "fpm_ckil512_clk",
810         "ipg_clk_ahb_arm (AHB)",
811         "1/8 of ipg_clk_arm (ARM)",
812         "1/8 of spl_dpdgck_clk (SPLL)",
813         "ckih",
814         "ipg_clk_ahb_emi_clk",
815         "ipg_clk_ipu_hsp",
816         "ipg_clk_nfc_20m",
817         "ipg_clk_perclk_uart1 (IPG_PER)",
818 };
819
820 #define CLKO_MAX_INDEX                  NUM_ELEMS(clko_name)
821
822 static void clko(int argc, char *argv[])
823 {
824         u32 action = 0, cosr;
825
826         if (!scan_opts(argc, argv, 1, 0, 0, &action,
827                                    OPTION_ARG_TYPE_NUM, "action"))
828                 return;
829
830         if (action >= CLKO_MAX_INDEX) {
831                 diag_printf("%d is not supported\n\n", action);
832                 return;
833         }
834
835         cosr = readl(CCM_BASE_ADDR + CLKCTL_COSR);
836
837         if (action != 0) {
838                 cosr = (cosr & (~0x1FF)) + action - 1;
839                 if (action == 1 || action == 3 || action == 7 || action == 8) {
840                         cosr |= (0x3 << 6); // make it divided by 8
841                 }
842                 writel(cosr, CCM_BASE_ADDR + CLKCTL_COSR);
843                 diag_printf("Set clko to ");
844         }
845
846         cosr = readl(CCM_BASE_ADDR + CLKCTL_COSR);
847         diag_printf("%s\n", clko_name[(cosr & 0xF) + 1]);
848         diag_printf("COSR register[0x%08lx] = 0x%08x\n",
849                                 (CCM_BASE_ADDR + CLKCTL_COSR), cosr);
850 }
851
852 #ifdef L2CC_ENABLED
853 /*
854  * This command is added for some simple testing only. It turns on/off
855  * L2 cache regardless of L1 cache state. The side effect of this is
856  * when doing any flash operations such as "fis init", the L2
857  * will be turned back on along with L1 caches even though it is off
858  * by using this command.
859  */
860 RedBoot_cmd("L2",
861                         "L2 cache",
862                         "[ON | OFF]",
863                         do_L2_caches
864                    );
865
866 void do_L2_caches(int argc, char *argv[])
867 {
868         u32 oldints;
869         int L2cache_on=0;
870
871         if (argc == 2) {
872                 if (strcasecmp(argv[1], "on") == 0) {
873                         HAL_DISABLE_INTERRUPTS(oldints);
874                         HAL_ENABLE_L2();
875                         HAL_RESTORE_INTERRUPTS(oldints);
876                 } else if (strcasecmp(argv[1], "off") == 0) {
877                         HAL_DISABLE_INTERRUPTS(oldints);
878                         HAL_CLEAN_INVALIDATE_L2();
879                         HAL_DISABLE_L2();
880                         HAL_RESTORE_INTERRUPTS(oldints);
881                 } else {
882                         diag_printf("Invalid L2 cache mode: %s\n", argv[1]);
883                 }
884         } else {
885                 HAL_L2CACHE_IS_ENABLED(L2cache_on);
886                 diag_printf("L2 cache: %s\n", L2cache_on?"On":"Off");
887         }
888 }
889 #endif //L2CC_ENABLED
890
891 #define IIM_ERR_SHIFT           8
892 #define POLL_FUSE_PRGD          (IIM_STAT_PRGD | (IIM_ERR_PRGE << IIM_ERR_SHIFT))
893 #define POLL_FUSE_SNSD          (IIM_STAT_SNSD | (IIM_ERR_SNSE << IIM_ERR_SHIFT))
894
895 static void fuse_op_start(void)
896 {
897         /* Do not generate interrupt */
898         writel(0, IIM_BASE_ADDR + IIM_STATM_OFF);
899         // clear the status bits and error bits
900         writel(0x3, IIM_BASE_ADDR + IIM_STAT_OFF);
901         writel(0xFE, IIM_BASE_ADDR + IIM_ERR_OFF);
902 }
903
904 /*
905  * The action should be either:
906  *                      POLL_FUSE_PRGD
907  * or:
908  *                      POLL_FUSE_SNSD
909  */
910 static int poll_fuse_op_done(int action)
911 {
912
913         u32 status, error;
914
915         if (action != POLL_FUSE_PRGD && action != POLL_FUSE_SNSD) {
916                 diag_printf("%s(%d) invalid operation\n", __FUNCTION__, action);
917                 return -1;
918         }
919
920         /* Poll busy bit till it is NOT set */
921         while ((readl(IIM_BASE_ADDR + IIM_STAT_OFF) & IIM_STAT_BUSY) != 0 ) {
922         }
923
924         /* Test for successful write */
925         status = readl(IIM_BASE_ADDR + IIM_STAT_OFF);
926         error = readl(IIM_BASE_ADDR + IIM_ERR_OFF);
927
928         if ((status & action) != 0 && (error & (action >> IIM_ERR_SHIFT)) == 0) {
929                 if (error) {
930                         diag_printf("Even though the operation seems successful...\n");
931                         diag_printf("There are some error(s) at addr=0x%08lx: 0x%08x\n",
932                                                 IIM_BASE_ADDR + IIM_ERR_OFF, error);
933                 }
934                 return 0;
935         }
936         diag_printf("%s(%d) failed\n", __FUNCTION__, action);
937         diag_printf("status address=0x%08lx, value=0x%08x\n",
938                                 (IIM_BASE_ADDR + IIM_STAT_OFF), status);
939         diag_printf("There are some error(s) at addr=0x%08lx: 0x%08x\n",
940                                 (IIM_BASE_ADDR + IIM_ERR_OFF), error);
941         return -1;
942 }
943
944 static void sense_fuse(int bank, int row, int bit)
945 {
946         int addr, addr_l, addr_h, reg_addr;
947
948         fuse_op_start();
949
950         addr = ((bank << 11) | (row << 3) | (bit & 0x7));
951         /* Set IIM Program Upper Address */
952         addr_h = (addr >> 8) & 0x000000FF;
953         /* Set IIM Program Lower Address */
954         addr_l = (addr & 0x000000FF);
955
956 #ifdef IIM_FUSE_DEBUG
957         diag_printf("%s: addr_h=0x%x, addr_l=0x%x\n",
958                                 __FUNCTION__, addr_h, addr_l);
959 #endif
960         writel(addr_h, IIM_BASE_ADDR + IIM_UA_OFF);
961         writel(addr_l, IIM_BASE_ADDR + IIM_LA_OFF);
962         /* Start sensing */
963         writel(0x8, IIM_BASE_ADDR + IIM_FCTL_OFF);
964         if (poll_fuse_op_done(POLL_FUSE_SNSD) != 0) {
965                 diag_printf("%s(bank: %d, row: %d, bit: %d failed\n",
966                                         __FUNCTION__, bank, row, bit);
967         }
968         reg_addr = IIM_BASE_ADDR + IIM_SDAT_OFF;
969         diag_printf("fuses at (bank:%d, row:%d) = 0x%x\n", bank, row, readl(reg_addr));
970 }
971
972 void do_fuse_read(int argc, char *argv[])
973 {
974         unsigned long bank, row;
975
976         if (argc == 1) {
977                 diag_printf("Usage: fuse_read <bank> <row>\n");
978                 return;
979         } else if (argc == 3) {
980                 if (!parse_num(argv[1], &bank, &argv[1], " ")) {
981                                 diag_printf("Error: Invalid parameter\n");
982                         return;
983                 }
984                 if (!parse_num(argv[2], &row, &argv[2], " ")) {
985                                 diag_printf("Error: Invalid parameter\n");
986                                 return;
987                         }
988
989                 diag_printf("Read fuse at bank:%ld row:%ld\n", bank, row);
990                 sense_fuse(bank, row, 0);
991
992         } else {
993                 diag_printf("Passing in wrong arguments: %d\n", argc);
994                 diag_printf("Usage: fuse_read <bank> <row>\n");
995         }
996 }
997
998 /* Blow fuses based on the bank, row and bit positions (all 0-based)
999 */
1000 static int fuse_blow(int bank,int row,int bit)
1001 {
1002         int addr, addr_l, addr_h, ret = -1;
1003
1004         fuse_op_start();
1005
1006         /* Disable IIM Program Protect */
1007         writel(0xAA, IIM_BASE_ADDR + IIM_PREG_P_OFF);
1008
1009         addr = ((bank << 11) | (row << 3) | (bit & 0x7));
1010         /* Set IIM Program Upper Address */
1011         addr_h = (addr >> 8) & 0x000000FF;
1012         /* Set IIM Program Lower Address */
1013         addr_l = (addr & 0x000000FF);
1014
1015 #ifdef IIM_FUSE_DEBUG
1016         diag_printf("blowing addr_h=0x%x, addr_l=0x%x\n", addr_h, addr_l);
1017 #endif
1018
1019         writel(addr_h, IIM_BASE_ADDR + IIM_UA_OFF);
1020         writel(addr_l, IIM_BASE_ADDR + IIM_LA_OFF);
1021         /* Start Programming */
1022         writel(0x71, IIM_BASE_ADDR + IIM_FCTL_OFF);
1023         if (poll_fuse_op_done(POLL_FUSE_PRGD) == 0) {
1024                 ret = 0;
1025         }
1026
1027         /* Enable IIM Program Protect */
1028         writel(0x0, IIM_BASE_ADDR + IIM_PREG_P_OFF);
1029         return ret;
1030 }
1031
1032 /*
1033  * This command is added for burning IIM fuses
1034  */
1035 RedBoot_cmd("fuse_read",
1036                         "read some fuses",
1037                         "<bank> <row>",
1038                         do_fuse_read
1039                    );
1040
1041 RedBoot_cmd("fuse_blow",
1042                         "blow some fuses",
1043                         "<bank> <row> <value>",
1044                         do_fuse_blow
1045                    );
1046
1047 #define                 INIT_STRING                              "12345678"
1048 static char ready_to_blow[] = INIT_STRING;
1049
1050 void quick_itoa(u32 num, char *a)
1051 {
1052         int i, j, k;
1053         for (i = 0; i <= 7; i++) {
1054                 j = (num >> (4 * i)) & 0xF;
1055                 k = (j < 10) ? '0' : ('a' - 0xa);
1056                 a[i] = j + k;
1057         }
1058 }
1059
1060 void do_fuse_blow(int argc, char *argv[])
1061 {
1062         unsigned long bank, row, value;
1063         int i;
1064
1065         if (argc == 1) {
1066                 diag_printf("It is too dangeous for you to use this command.\n");
1067                 return;
1068         } else if (argc == 2) {
1069                 if (strcasecmp(argv[1], "nandboot") == 0) {
1070                         quick_itoa(readl(EPIT_BASE_ADDR + EPITCNR), ready_to_blow);
1071                         diag_printf("%s\n", ready_to_blow);
1072                 }
1073                 return;
1074         } else if (argc == 3) {
1075                 if (strcasecmp(argv[1], "nandboot") == 0 &&
1076                         strcasecmp(argv[2], ready_to_blow) == 0) {
1077 #if defined(CYGPKG_HAL_ARM_MXC91131) || defined(CYGPKG_HAL_ARM_MX21) || defined(CYGPKG_HAL_ARM_MX27) || defined(CYGPKG_HAL_ARM_MX31)
1078                         diag_printf("No need to blow any fuses for NAND boot on this platform\n\n");
1079 #else
1080                         diag_printf("Ready to burn NAND boot fuses\n");
1081                         if (fuse_blow(0, 16, 1) != 0 || fuse_blow(0, 16, 7) != 0) {
1082                                 diag_printf("NAND BOOT fuse blown failed miserably ...\n");
1083                         } else {
1084                                 diag_printf("NAND BOOT fuse blown successfully ...\n");
1085                         }
1086                 } else {
1087                         diag_printf("Not ready: %s, %s\n", argv[1], argv[2]);
1088 #endif
1089                 }
1090         } else if (argc == 4) {
1091                 if (!parse_num(argv[1], &bank, &argv[1], " ")) {
1092                                 diag_printf("Error: Invalid parameter\n");
1093                                 return;
1094                 }
1095                 if (!parse_num(argv[2], &row, &argv[2], " ")) {
1096                                 diag_printf("Error: Invalid parameter\n");
1097                                 return;
1098                 }
1099                 if (!parse_num(argv[3], &value, &argv[3], " ")) {
1100                                 diag_printf("Error: Invalid parameter\n");
1101                                 return;
1102                 }
1103
1104                 diag_printf("Blowing fuse at bank: %ld row: %ld value: %ld\n",
1105                                         bank, row, value);
1106                 for (i = 0; i < 8; i++) {
1107                         if (((value >> i) & 0x1) == 0) {
1108                                 continue;
1109                         }
1110                         if (fuse_blow(bank, row, i) != 0) {
1111                                 diag_printf("fuse_blow(bank: %ld, row: %ld, bit: %d failed\n",
1112                                                         bank, row, i);
1113                         } else {
1114                                 diag_printf("fuse_blow(bank: %ld, row: %ld, bit: %d successful\n",
1115                                                         bank, row, i);
1116                         }
1117                 }
1118                 sense_fuse(bank, row, 0);
1119
1120         } else {
1121                 diag_printf("Wrong number of arguments: %d\n", argc);
1122         }
1123         /* Reset to default string */
1124         strcpy(ready_to_blow, INIT_STRING);;
1125 }
1126
1127 /* precondition: m>0 and n>0.  Let g=gcd(m,n). */
1128 int gcd(int m, int n)
1129 {
1130         int t;
1131         while(m > 0) {
1132                 if(n > m) {t = m; m = n; n = t;} /* swap */
1133                 m -= n;
1134         }
1135         return n;
1136 }
1137
1138 #define CLOCK_SRC_DETECT_MS                     100
1139 #define CLOCK_IPG_DEFAULT                       66500000
1140 #define CLOCK_SRC_DETECT_MARGIN         500000
1141 void mxc_show_clk_input(void)
1142 {
1143 //        u32 c1, c2, diff, ipg_real, num = 0;
1144
1145         return;  // FIXME
1146 #if 0
1147         switch (prcs) {
1148         case 0x01:
1149                 diag_printf("FPM enabled --> 32KHz input source\n");
1150                 return;
1151         case 0x02:
1152                 break;
1153         default:
1154                 diag_printf("Error %d: unknown clock source %d\n", __LINE__, prcs);
1155                 return;
1156         }
1157
1158         // enable GPT with IPG clock input
1159         writel(0x241, GPT_BASE_ADDR + GPTCR);
1160         // prescaler = 1
1161         writel(0, GPT_BASE_ADDR + GPTPR);
1162
1163         c1 = readl(GPT_BASE_ADDR + GPTCNT);
1164         // use 32KHz input clock to get the delay
1165         hal_delay_us(CLOCK_SRC_DETECT_MS * 1000);
1166         c2 = readl(GPT_BASE_ADDR + GPTCNT);
1167         diff = (c2 > c1) ? (c2 - c1) : (0xFFFFFFFF - c1 + c2);
1168
1169         ipg_real = diff * (1000 / CLOCK_SRC_DETECT_MS);
1170
1171         if (num != 0) {
1172                 diag_printf("Error: Actual clock input is %d MHz\n", num);
1173                 diag_printf("           ipg_real=%d CLOCK_IPG_DEFAULT - CLOCK_SRC_DETECT_MARGIN=%d\n\n",
1174                                         ipg_real, CLOCK_IPG_DEFAULT - CLOCK_SRC_DETECT_MARGIN);
1175                 hal_delay_us(2000000);
1176         } else {
1177                 diag_printf("ipg_real=%d CLOCK_IPG_DEFAULT - CLOCK_SRC_DETECT_MARGIN=%d\n\n",
1178                                         ipg_real, CLOCK_IPG_DEFAULT - CLOCK_SRC_DETECT_MARGIN);
1179         }
1180 #endif
1181 }
1182
1183 RedBoot_init(mxc_show_clk_input, RedBoot_INIT_LAST);
1184
1185 void imx_power_mode(int mode)
1186 {
1187         volatile unsigned int val;
1188         switch (mode) {
1189         case 0:
1190                 diag_printf("WFI only\n");
1191                 break;
1192         case 1:
1193                 diag_printf("Entering WAIT mode\n");
1194                 // wait mode - from validation code
1195                 // Set DSM_INT_HOLDOFF bit in TZIC
1196                 // If the TZIC didn't write the bit then there was interrupt pending
1197                 // It will be serviced while we're in the loop
1198                 // So we write to this bit again
1199                 while (readl(INTC_BASE_ADDR + 0x14) == 0) {
1200                         writel(1, INTC_BASE_ADDR + 0x14);
1201                         // Wait few cycles
1202                         __asm("nop");
1203                         __asm("nop");
1204                         __asm("nop");
1205                         __asm("nop");
1206                         __asm("nop");
1207                         __asm("nop");
1208                         __asm("nop");
1209                 }
1210                 val = readl(CCM_BASE_ADDR + 0x74);
1211                 val = (val & 0xfffffffc) | 0x1; // set WAIT mode
1212                 writel(val, CCM_BASE_ADDR + 0x74);
1213                 val = readl(PLATFORM_LPC_REG);
1214                 writel(val | (1 << 16), PLATFORM_LPC_REG);// ENABLE DSM in ELBOW submodule of ARM platform
1215                 val = readl(PLATFORM_LPC_REG);
1216                 writel(val | (1 << 17), PLATFORM_LPC_REG);// ENABLE DSM in ELBOW submodule of ARM platform
1217                 break;
1218         case 2:
1219                 diag_printf("Entering stop mode\n");
1220                 hal_delay_us(100);
1221                 // stop mode - from validation code
1222                 // Set DSM_INT_HOLDOFF bit in TZIC
1223                 // If the TZIC didn't write the bit then there was interrupt pending
1224                 // It will be serviced while we're in the loop
1225                 // So we write to this bit again
1226                 while (readl(INTC_BASE_ADDR + 0x14) == 0) {
1227                         writel(1, INTC_BASE_ADDR + 0x14);
1228                         // Wait few cycles
1229                         __asm("nop");
1230                         __asm("nop");
1231                         __asm("nop");
1232                         __asm("nop");
1233                         __asm("nop");
1234                         __asm("nop");
1235                         __asm("nop");
1236                 }
1237                 val = readl(CCM_BASE_ADDR + 0x74);
1238                 val = (val & 0xfffffffc) | 0x2; // set STOP mode
1239                 writel(val, CCM_BASE_ADDR + 0x74);
1240                 val = readl(PLATFORM_LPC_REG);
1241                 writel(val | (3 << 16), PLATFORM_LPC_REG);// ENABLE DSM in ELBOW submodule of ARM platform
1242
1243                 // power gating these peripherals
1244                 writel(0x0000030f, GPC_PGR);
1245                 writel(0x1, SRPGCR_EMI);
1246                 writel(0x1, SRPGCR_ARM);
1247                 writel(0x1, PGC_PGCR_VPU);
1248                 writel(0x1, PGC_PGCR_IPU);
1249                 break;
1250         default:
1251                 diag_printf("Unknown low power mode: %d\n", mode);
1252                 return;
1253         }
1254
1255         asm("mov r1, #0");
1256         asm("mcr p15, 0, r1, c7, c0, 4");
1257 }
1258
1259 void do_power_mode(int argc, char *argv[])
1260 {
1261         unsigned long mode;
1262
1263         if (argc == 1) {
1264                 diag_printf("Usage: power_mode <mode>\n");
1265                 return;
1266         } else if (argc == 2) {
1267                 if (!parse_num(argv[1], &mode, &argv[1], " ")) {
1268                                 diag_printf("Error: Invalid parameter\n");
1269                         return;
1270                 }
1271                 imx_power_mode(mode);
1272
1273         } else {
1274                 diag_printf("Passing in wrong arguments: %d\n", argc);
1275                 diag_printf("Usage: power_mode <mode>\n");
1276         }
1277 }
1278
1279 /*
1280  * This command is added for burning IIM fuses
1281  */
1282 RedBoot_cmd("power_mode",
1283             "Enter various power modes:",
1284             "\n"
1285                         "        <0> - WAIT\n"
1286                         "        <1> - SRPG\n"
1287                         "        <2> - STOP\n"
1288                         "        <3> - STOP with Power-Gating\n"
1289                         "        -- need reset after issuing the command",
1290             do_power_mode
1291                    );
1292