]> git.karo-electronics.de Git - karo-tx-redboot.git/blob - packages/hal/arm/mx27/var/v2_0/src/cmds.c
8a52e4c0e7b543847b3c83c9c4b4be86d88e80ef
[karo-tx-redboot.git] / packages / hal / arm / mx27 / 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     6       // See TLSbo80174
56 #define PLL_MFD_MAX     1024    //actual mfd+1
57 #define PLL_MFN_MAX     1022
58 #define PLL_MFN_MAX_2   510
59 #define PRESC_MAX       8
60 #define IPG_DIV_MAX     2
61 #define AHB_DIV_MAX     16
62 #define ARM_DIV_MAX     4
63
64 #define CPLM_SETUP      0
65
66 #define PLL_FREQ_MAX    (2 * PLL_REF_CLK * PLL_MFI_MAX)
67 #define PLL_FREQ_MIN    ((2 * PLL_REF_CLK * PLL_MFI_MIN) / PLL_PD_MAX)
68 #define AHB_CLK_MAX     133333333
69 #define IPG_CLK_MAX     (AHB_CLK_MAX / 2)
70 #define NFC_CLK_MAX     33333333
71
72 #define ERR_WRONG_CLK   -1
73 #define ERR_NO_MFI      -2
74 #define ERR_NO_MFN      -3
75 #define ERR_NO_PD       -4
76 #define ERR_NO_PRESC    -5
77
78 u32 pll_clock(enum plls pll);
79 u32 get_main_clock(enum main_clocks clk);
80 u32 get_peri_clock(enum peri_clocks clk);
81
82 static u32 pll_mfd_fixed;
83
84 static void clock_setup(int argc, char *argv[]);
85 static void clko(int argc, char *argv[]);
86 extern unsigned int g_clock_src;
87 extern unsigned int system_rev;
88 extern int sys_ver;
89
90 #define MXC_PERCLK_NUM  4
91
92 RedBoot_cmd("clock",
93             "Setup/Display clock (max AHB=133MHz, max IPG=66.5MHz)\nSyntax:",
94             "[<core clock in MHz> [:<AHB-to-core divider>[:<IPG-to-AHB divider>]]] \n\n\
95 If a divider is zero or no divider is specified, the optimal divider values \n\
96 will be chosen. Examples:\n\
97    [clock]         -> Show various clocks\n\
98    [clock 266]     -> Core=266  AHB=133           IPG=66.5\n\
99    [clock 350]     -> Core=350  AHB=117           IPG=58.5\n\
100    [clock 266:4]   -> Core=266  AHB=66.5(Core/4)  IPG=66.5\n\
101    [clock 266:4:2] -> Core=266  AHB=66.5(Core/4)  IPG=33.25(AHB/2)\n",
102             clock_setup
103            );
104
105 /*!
106  * This is to calculate various parameters based on reference clock and
107  * targeted clock based on the equation:
108  *      t_clk = 2*ref_freq*(mfi + mfn/(mfd+1))/(pd+1)
109  * This calculation is based on a fixed MFD value for simplicity.
110  *
111  * @param ref       reference clock freq
112  * @param target    targeted clock in HZ
113  * @param p_pd      calculated pd value (pd value from register + 1) upon return
114  * @param p_mfi     calculated actual mfi value upon return
115  * @param p_mfn     calculated actual mfn value upon return
116  * @param p_mfd     fixed mfd value (mfd value from register + 1) upon return
117  *
118  * @return          0 if successful; non-zero otherwise.
119  */
120 int calc_pll_params(u32 ref, u32 target, u32 *p_pd,
121                     u32 *p_mfi, u32 *p_mfn, u32 *p_mfd)
122 {
123     u64 pd, mfi, mfn, n_target = (u64)target, n_ref = (u64)ref;
124
125     if (g_clock_src == FREQ_26MHZ) {
126         pll_mfd_fixed = 26 * 16;
127     } else if (g_clock_src == FREQ_27MHZ) {
128         pll_mfd_fixed = 27 * 16;
129     } else {
130         pll_mfd_fixed = 512;
131     }
132
133     // Make sure targeted freq is in the valid range. Otherwise the
134     // following calculation might be wrong!!!
135     if (target < PLL_FREQ_MIN || target > PLL_FREQ_MAX) {
136         return ERR_WRONG_CLK;
137     }
138     // Use n_target and n_ref to avoid overflow
139     for (pd = 1; pd <= PLL_PD_MAX; pd++) {
140         mfi = (n_target * pd) / (2 * n_ref);
141         if (mfi > PLL_MFI_MAX) {
142             return ERR_NO_MFI;
143         } else if (mfi < PLL_MFI_MIN) {
144             continue;
145         }
146         break;
147     }
148     // Now got pd and mfi already
149     mfn = (((n_target * pd) / 2 - n_ref * mfi) * pll_mfd_fixed) / n_ref;
150     // Check mfn within limit and mfn < denominator
151     if (sys_ver == SOC_SILICONID_Rev1_0) {
152         if (mfn > PLL_MFN_MAX || mfn >= pll_mfd_fixed) {
153             return ERR_NO_MFN;
154         }
155     } else {
156         if (mfn > PLL_MFN_MAX_2 || mfn >= pll_mfd_fixed) {
157             return ERR_NO_MFN;
158         }
159     }
160
161     if (pd > PLL_PD_MAX) {
162         return ERR_NO_PD;
163     }
164     *p_pd = (u32)pd;
165     *p_mfi = (u32)mfi;
166     *p_mfn = (u32)mfn;
167     *p_mfd = pll_mfd_fixed;
168     return 0;
169 }
170
171 static u32 per_clk_old[MXC_PERCLK_NUM];
172
173 /*!
174  * This function assumes the expected core clock has to be changed by
175  * modifying the PLL. This is NOT true always but for most of the times,
176  * it is. So it assumes the PLL output freq is the same as the expected
177  * core clock (presc=1) unless the core clock is less than PLL_FREQ_MIN.
178  * In the latter case, it will try to increase the presc value until
179  * (presc*core_clk) is greater than PLL_FREQ_MIN. It then makes call to
180  * calc_pll_params() and obtains the values of PD, MFI,MFN, MFD based
181  * on the targeted PLL and reference input clock to the PLL. Lastly,
182  * it sets the register based on these values along with the dividers.
183  * Note 1) There is no value checking for the passed-in divider values
184  *         so the caller has to make sure those values are sensible.
185  *      2) Also adjust the NFC divider such that the NFC clock doesn't
186  *         exceed NFC_CLK_MAX (which is 33MHz now).
187  *      3) Added feature to maintain the perclock before and after the call.
188  * !!!! 4) This function can't have printf in it since the serial i/f is
189  *         stopped.
190  *
191  * @param ref       pll input reference clock (32KHz or 26MHz)
192  * @param core_clk  core clock in Hz
193  * @param ahb_div   ahb divider to divide the core clock to get ahb clock
194  *                  (ahb_div - 1) needs to be set in the register
195  * @param ipg_div   ipg divider to divide the ahb clock to get ipg clock
196  *                  (ipg_div - 1) needs to be set in the register
197  # @return          0 if successful; non-zero otherwise
198  */
199 int configure_clock(u32 ref, u32 core_clk, u32 ahb_div, u32 ipg_div)
200 {
201     u32 pll, presc = 1, pd, mfi, mfn, mfd, brmo = 1, cscr, mpctl0;
202     u32 pcdr0, nfc_div, hdiv, nfc_div_factor;
203     u32 per_div[MXC_PERCLK_NUM];
204     int ret, i, arm_src = 0;
205
206     per_clk_old[0] = get_peri_clock(PER_CLK1);
207     per_clk_old[1] = get_peri_clock(PER_CLK2);
208     per_clk_old[2] = get_peri_clock(PER_CLK3);
209     per_clk_old[3] = get_peri_clock(PER_CLK4);
210
211     // assume pll default to core clock first
212     if (sys_ver == SOC_SILICONID_Rev1_0) {
213         pll = core_clk;
214         nfc_div_factor = 1;
215     } else {
216         if (core_clk > (266 * SZ_DEC_1M)) {
217             pll = core_clk;
218             arm_src = 1;
219         } else {
220             pll = core_clk * 3 / 2;
221         }
222         nfc_div_factor = ahb_div;
223     }
224
225     // when core_clk >= PLL_FREQ_MIN, the presc can be 1.
226     // Otherwise, need to calculate presc value below and adjust the targeted pll
227     if (pll < PLL_FREQ_MIN) {
228         int presc_max;
229         if(sys_ver   == SOC_SILICONID_Rev1_0) {
230             presc_max = PRESC_MAX;
231         } else {
232             presc_max = ARM_DIV_MAX;
233         }
234
235         for (presc = 1; presc <= presc_max; presc++) {
236             if ((pll * presc) > PLL_FREQ_MIN) {
237                 break;
238             }
239         }
240         if (presc == (presc_max + 1)) {
241             diag_printf("can't make presc=%d\n", presc);
242             return ERR_NO_PRESC;
243         }
244         if (sys_ver == SOC_SILICONID_Rev1_0) {
245             pll = core_clk * presc;
246         } else {
247             pll = 3 * core_clk * presc / 2;
248         }
249     }
250     // pll is now the targeted pll output. Use it along with ref input clock
251     // to get pd, mfi, mfn, mfd
252     if ((ret = calc_pll_params(ref, pll, &pd, &mfi, &mfn, &mfd)) != 0) {
253 #ifdef CMD_CLOCK_DEBUG
254         diag_printf("can't find pll parameters: %d\n", ret);
255 #endif
256         return ret;
257     }
258 #ifdef CMD_CLOCK_DEBUG
259     diag_printf("ref=%d, pll=%d, pd=%d, mfi=%d,mfn=%d, mfd=%d\n",
260                 ref, pll, pd, mfi, mfn, mfd);
261 #endif
262
263     // blindly increase divider first to avoid too fast ahbclk and ipgclk
264     // in case the core clock increases too much
265     cscr = readl(SOC_CRM_CSCR);
266     if (sys_ver == SOC_SILICONID_Rev1_0) {
267         hdiv = (pll + AHB_CLK_MAX -1) / AHB_CLK_MAX;
268         cscr = (cscr & ~(0x0000FF00)) | ((hdiv - 1) << 9) | (1 << 8);
269     } else {
270         if (core_clk > (266 * SZ_DEC_1M)) {
271             hdiv = (pll + AHB_CLK_MAX - 1) / AHB_CLK_MAX;
272         } else {
273             hdiv = (2 * pll + 3 * AHB_CLK_MAX - 1) / (3 * AHB_CLK_MAX);
274         }
275         cscr = (cscr & ~(0x0000FF00)) | ((hdiv - 1) << 8);
276     }
277     writel(cscr, SOC_CRM_CSCR);
278
279     // update PLL register
280     if ((mfd < (10 * mfn)) && ((10 * mfn) < (9 * mfd)))
281         brmo = 0;
282     if (brmo != 0)
283         writel(1 << 6, SOC_CRM_MPCTL1);
284
285     mpctl0 = readl(SOC_CRM_MPCTL0);
286     mpctl0 = (mpctl0 & 0xC000C000)  |
287              CPLM_SETUP             |
288              ((pd - 1) << 26)       |
289              ((mfd - 1) << 16)      |
290              (mfi << 10)            |
291              mfn;
292     writel(mpctl0, SOC_CRM_MPCTL0);
293
294     // restart mpll
295     writel((cscr | (1 << 18)), SOC_CRM_CSCR);
296     // check the LF bit to insure lock
297     while ((readl(SOC_CRM_MPCTL1) & (1 << 15)) == 0);
298     // have to add some delay for new values to take effect
299     for (i = 0; i < 100000; i++);
300
301     // PLL locked already so use the new divider values
302     cscr = readl(SOC_CRM_CSCR);
303     cscr &= ~0x0000FF00;
304
305     if (sys_ver == SOC_SILICONID_Rev1_0) {
306         cscr |= ((presc - 1) << 13) | ((ahb_div - 1) << 9) | ((ipg_div - 1) << 8);
307     } else {
308         cscr |= (arm_src << 15) | ((presc - 1) << 12) | ((ahb_div - 1) << 8);
309     }
310     writel(cscr, SOC_CRM_CSCR);
311
312     // Make sure optimal NFC clock but less than NFC_CLK_MAX
313     for (nfc_div = 1; nfc_div <= 16; nfc_div++) {
314         if ((core_clk / (nfc_div_factor * nfc_div)) <= NFC_CLK_MAX) {
315             break;
316         }
317     }
318     pcdr0 = readl(SOC_CRM_PCDR0);
319     if(sys_ver == SOC_SILICONID_Rev1_0) {
320         writel(((pcdr0 & 0xFFFF0FFF) | ((nfc_div - 1) << 12)),
321            SOC_CRM_PCDR0);
322     } else {
323         writel(((pcdr0 & 0xFFFFF3CF) | ((nfc_div - 1) << 6)),
324            SOC_CRM_PCDR0);
325     }
326
327     if(sys_ver == SOC_SILICONID_Rev1_0) {
328         pll = pll_clock(MCU_PLL) + 500000;
329     } else {
330         if (core_clk > (266 * SZ_DEC_1M)) {
331             pll = pll_clock(MCU_PLL) + 500000;
332         } else {
333             pll = 2 * pll_clock(MCU_PLL) / 3 + 500000;
334         }
335     }
336     for (i = 0; i < MXC_PERCLK_NUM; i++) {
337         per_div[i] = (pll / per_clk_old[i]) - 1;
338     }
339     writel((per_div[3] << 24) | (per_div[2] << 16) | (per_div[1] << 8) |
340            (per_div[0]), SOC_CRM_PCDR1);
341
342     return 0;
343 }
344
345 static void clock_setup(int argc, char *argv[])
346 {
347     u32 i, core_clk, ipg_div, data[3], ahb_div, ahb_clk, ahb_clk_in, ipg_clk;
348     u32 presc_max,  ahb_div_max, pll;
349     unsigned long temp;
350     int ret;
351
352     if (argc == 1)
353         goto print_clock;
354     if (g_clock_src == FREQ_27MHZ) {
355         diag_printf("Error: clock setup is not supported for 27MHz source\n\n");
356         return;
357     }
358     for (i = 0;  i < 3;  i++) {
359         if (!parse_num(argv[1], &temp, &argv[1], ":")) {
360             diag_printf("Error: Invalid parameter\n");
361             return;
362         }
363         data[i] = temp;
364     }
365
366     core_clk = data[0] * SZ_DEC_1M;
367     ahb_div = data[1];  // actual register field + 1
368     ipg_div = data[2];  // actual register field + 1
369
370     if(sys_ver == SOC_SILICONID_Rev1_0) {
371         presc_max = PRESC_MAX;
372         ahb_div_max = AHB_DIV_MAX;
373         pll = core_clk;
374         ahb_clk_in = core_clk;
375     } else {
376         presc_max = ARM_DIV_MAX;
377         ahb_div_max = AHB_DIV_MAX / ARM_DIV_MAX;
378         if (core_clk > (266 * SZ_DEC_1M)) {
379             pll = core_clk;
380             ahb_clk_in = core_clk * 2 / 3;
381         } else {
382             pll = 3 * core_clk / 2;
383             ahb_clk_in = core_clk;
384         }
385         ipg_div = 2;
386     }
387
388     if (pll < (PLL_FREQ_MIN / presc_max) || pll > PLL_FREQ_MAX) {
389         diag_printf("Targeted core clock should be within [%d - %d]\n",
390                  PLL_FREQ_MIN / presc_max, PLL_FREQ_MAX);
391         return;
392     }
393
394     // find the ahb divider
395     if (ahb_div > ahb_div_max) {
396         diag_printf("Invalid AHB divider: %d. Maximum value is %d\n",
397                  ahb_div, ahb_div_max);
398         return;
399     }
400     if (ahb_div == 0) {
401         // no AHBCLK divider specified
402         for (ahb_div = 1; ; ahb_div++) {
403             if ((ahb_clk_in / ahb_div) <= AHB_CLK_MAX) {
404                 break;
405             }
406         }
407     }
408     if (ahb_div > ahb_div_max || (ahb_clk_in / ahb_div) > AHB_CLK_MAX) {
409         diag_printf("Can't make AHB=%d since max=%d\n",
410                  core_clk / ahb_div, AHB_CLK_MAX);
411         return;
412     }
413
414     // find the ipg divider
415     ahb_clk = ahb_clk_in / ahb_div;
416     if (ipg_div > IPG_DIV_MAX) {
417         diag_printf("Invalid IPG divider: %d. Maximum value is %d\n",
418                     ipg_div, IPG_DIV_MAX);
419         return;
420     }
421     if (ipg_div == 0) {
422         ipg_div++;          // At least =1
423         if (ahb_clk > IPG_CLK_MAX)
424             ipg_div++;      // Make it =2
425     }
426     if (ipg_div > IPG_DIV_MAX || (ahb_clk / ipg_div) > IPG_CLK_MAX) {
427         diag_printf("Can't make IPG=%d since max=%d\n",
428                     (ahb_clk / ipg_div), IPG_CLK_MAX);
429         return;
430     }
431     ipg_clk = ahb_clk / ipg_div;
432
433     diag_printf("Trying to set core=%d ahb=%d ipg=%d...\n",
434                 core_clk, ahb_clk, ipg_clk);
435
436     // stop the serial to be ready to adjust the clock
437     hal_delay_us(100000);
438     cyg_hal_plf_serial_stop();
439     // adjust the clock
440     ret = configure_clock(PLL_REF_CLK, core_clk, ahb_div, ipg_div);
441     // restart the serial driver
442     cyg_hal_plf_serial_init();
443     hal_delay_us(100000);
444
445     if (ret != 0) {
446         diag_printf("Failed to setup clock: %d\n", ret);
447         return;
448     }
449
450     // check for new per clock settings and warn user if there is a change.
451     if (per_clk_old[0] != get_peri_clock(PER_CLK1)) {
452         diag_printf("New per_clk1 changed! Old freq is %d\n", per_clk_old[0]);
453     }
454     if (per_clk_old[1] != get_peri_clock(PER_CLK2)) {
455         diag_printf("New per_clk2 changed! Old freq is %d\n", per_clk_old[1]);
456     }
457     if (per_clk_old[2] != get_peri_clock(PER_CLK3)) {
458         diag_printf("New per_clk3 changed! Old freq is %d\n", per_clk_old[2]);
459     }
460     if (per_clk_old[3] != get_peri_clock(PER_CLK4)) {
461         diag_printf("New per_clk4 changed! Old freq is %d\n", per_clk_old[3]);
462     }
463
464     diag_printf("\n<<<New clock setting>>>\n");
465
466     // Now printing clocks
467 print_clock:
468     diag_printf("\nMPLL\t\tSPLL\n");
469     diag_printf("=========================\n");
470     diag_printf("%-16d%-16d\n\n", pll_clock(MCU_PLL), pll_clock(SER_PLL));
471     diag_printf("CPU\t\tAHB\t\tIPG\t\tNFC\t\tUSB\n");
472     diag_printf("========================================================================\n");
473     diag_printf("%-16d%-16d%-16d%-16d%-16d\n\n",
474                 get_main_clock(CPU_CLK),
475                 get_main_clock(AHB_CLK),
476                 get_main_clock(IPG_CLK),
477                 get_main_clock(NFC_CLK),
478                 get_main_clock(USB_CLK));
479
480     diag_printf("PER1\t\tPER2\t\tPER3\t\tPER4\n");
481     diag_printf("===========================================");
482     diag_printf("=============\n");
483
484     diag_printf("%-16d%-16d%-16d%-16d\n\n",
485                 get_peri_clock(PER_CLK1),
486                 get_peri_clock(PER_CLK2),
487                 get_peri_clock(PER_CLK3),
488                 get_peri_clock(PER_CLK4));
489
490     diag_printf("H264\t\tMSHC\t\tSSI1\t\tSSI2\n");
491     diag_printf("========================================================\n");
492     diag_printf("%-16d%-16d%-16d%-16d\n\n",
493                 get_peri_clock(H264_BAUD),
494                 get_peri_clock(MSHC_BAUD),
495                 get_peri_clock(SSI1_BAUD),
496                 get_peri_clock(SSI2_BAUD));
497     diag_printf("PERCLK: 1-<UART|GPT|PWM> 2-<SDHC|CSPI> 3-<LCDC> 4-<CSI>\n");
498 }
499
500 /*!
501  * This function returns the PLL output value in Hz based on pll.
502  */
503 u32 pll_clock(enum plls pll)
504 {
505     u64 mfi, mfn, mfd, pdf, ref_clk, pll_out;
506     u64 reg = readl(pll);
507
508     if ((pll == SER_PLL) && (sys_ver == SOC_SILICONID_Rev2_0)) {
509         writel(reg, pll);
510     }
511     pdf = (reg >> 26) & 0xF;
512     mfd = (reg >> 16) & 0x3FF;
513     mfi = (reg >> 10) & 0xF;
514     mfi = (mfi <= 5) ? 5: mfi;
515     mfn = reg & 0x3FF;
516
517     ref_clk = g_clock_src;
518
519     pll_out = (2 * ref_clk * mfi + ((2 * ref_clk * mfn) / (mfd + 1))) /
520               (pdf + 1);
521
522     return (u32)pll_out;
523 }
524
525 /*!
526  * This function returns the main clock value in Hz.
527  */
528 u32 get_main_clock(enum main_clocks clk)
529 {
530     u32 presc, ahb_div, ipg_pdf, nfc_div;
531     u32 ret_val = 0, usb_div;
532     u32 cscr = readl(SOC_CRM_CSCR);
533     u32 pcdr0 = readl(SOC_CRM_PCDR0);
534
535     if (sys_ver == SOC_SILICONID_Rev1_0) {
536         presc = ((cscr >> CRM_CSCR_PRESC_OFFSET) & 0x7) + 1;
537     } else {
538         presc = ((cscr >> CRM_CSCR_ARM_OFFSET) & 0x3) + 1;
539     }
540
541     switch (clk) {
542     case CPU_CLK:
543         if ((sys_ver == SOC_SILICONID_Rev1_0) || (cscr & CRM_CSCR_ARM_SRC)) {
544             ret_val = pll_clock(MCU_PLL) / presc;
545         } else {
546             ret_val = 2 * pll_clock(MCU_PLL) / (3 * presc);
547         }
548         break;
549     case AHB_CLK:
550         if (sys_ver == SOC_SILICONID_Rev1_0) {
551             ahb_div = ((cscr >> CRM_CSCR_BCLKDIV_OFFSET) & 0xF) + 1;
552             ret_val = pll_clock(MCU_PLL) / (presc * ahb_div);
553         } else {
554             ahb_div = ((cscr >> CRM_CSCR_AHB_OFFSET) & 0x3) + 1;
555             ret_val = 2*pll_clock(MCU_PLL) / (3*ahb_div);
556         }
557         break;
558     case IPG_CLK:
559         if (sys_ver == SOC_SILICONID_Rev1_0) {
560             ahb_div = ((cscr >> CRM_CSCR_BCLKDIV_OFFSET) & 0xF) + 1;
561             ipg_pdf = ((cscr >> CRM_CSCR_IPDIV_OFFSET) & 0x1) + 1;
562             ret_val = pll_clock(MCU_PLL) / (presc * ahb_div * ipg_pdf);
563         } else {
564             ahb_div = ((cscr >> CRM_CSCR_AHB_OFFSET) & 0x3) + 1;
565             ret_val = pll_clock(MCU_PLL) / (3*ahb_div);
566         }
567         break;
568     case NFC_CLK:
569         if (sys_ver == SOC_SILICONID_Rev1_0) {
570             nfc_div = ((pcdr0 >> 12) & 0xF) + 1;
571             /* AHB/nfc_div */
572             ret_val = pll_clock(MCU_PLL) / (presc * nfc_div);
573         } else {
574             nfc_div = ((pcdr0 >> 6) & 0xF) + 1;
575             ahb_div = ((cscr >> CRM_CSCR_AHB_OFFSET) & 0x3) + 1;
576             ret_val = 2*pll_clock(MCU_PLL) / (3*ahb_div*nfc_div);
577         }
578         break;
579     case USB_CLK:
580         usb_div = ((cscr >> CRM_CSCR_USB_DIV_OFFSET) & 0x7) + 1;
581         ret_val = pll_clock(SER_PLL) / usb_div;
582         break;
583     default:
584         diag_printf("Unknown clock: %d\n", clk);
585         break;
586     }
587     return ret_val;
588 }
589
590 /*!
591  * This function returns the peripheral clock value in Hz.
592  */
593 u32 get_peri_clock(enum peri_clocks clk)
594 {
595     u32 ret_val = 0, div;
596     u32 pcdr0 = readl(SOC_CRM_PCDR0);
597     u32 pcdr1 = readl(SOC_CRM_PCDR1);
598     u32 cscr = readl(SOC_CRM_CSCR);
599
600     switch (clk) {
601     case PER_CLK1:
602         div = (pcdr1 & 0x3F) + 1;
603         if (sys_ver == SOC_SILICONID_Rev1_0) {
604             ret_val = pll_clock(MCU_PLL) / div;
605         } else {
606             ret_val = 2*pll_clock(MCU_PLL) / (3*div);
607         }
608         break;
609     case PER_CLK2:
610     case SPI1_CLK:
611     case SPI2_CLK:
612         div = ((pcdr1 >> 8) & 0x3F) + 1;
613         if (sys_ver == SOC_SILICONID_Rev1_0) {
614             ret_val = pll_clock(MCU_PLL) / div;
615         } else {
616             ret_val = 2*pll_clock(MCU_PLL) / (3*div);
617         }
618         break;
619     case PER_CLK3:
620         div = ((pcdr1 >> 16) & 0x3F) + 1;
621         if (sys_ver == SOC_SILICONID_Rev1_0) {
622             ret_val = pll_clock(MCU_PLL) / div;
623         } else {
624             ret_val = 2*pll_clock(MCU_PLL) / (3*div);
625         }
626         break;
627     case PER_CLK4:
628         div = ((pcdr1 >> 24) & 0x3F) + 1;
629         if (sys_ver == SOC_SILICONID_Rev1_0) {
630             ret_val = pll_clock(MCU_PLL) / div;
631         } else {
632             ret_val = 2*pll_clock(MCU_PLL) / (3*div);
633         }
634         break;
635     case SSI1_BAUD:
636         div = (pcdr0 >> 16) & 0x3F;
637         if (sys_ver == SOC_SILICONID_Rev1_0) {
638             if (div < 2) {
639                 div = 62 * 2;
640             }
641         } else {
642             div += 4;
643         }
644         if ((cscr & (1 << 22)) != 0) {
645             // This takes care of 0.5*SSIDIV[0] by x2
646             if (sys_ver == SOC_SILICONID_Rev1_0) {
647                 ret_val = (2 * pll_clock(MCU_PLL)) / div;
648             } else {
649                 ret_val = (4 * pll_clock(MCU_PLL)) / (3*div);
650             }
651         } else {
652             ret_val = (2 * pll_clock(SER_PLL)) / div;
653         }
654         break;
655     case SSI2_BAUD:
656         div = (pcdr0 >> 26) & 0x3F;
657         if (sys_ver == SOC_SILICONID_Rev1_0) {
658             if (div < 2) {
659                 div = 62 * 2;
660             }
661         } else {
662             div += 4;
663         }
664         if ((cscr & (1 << 23)) != 0) {
665             if (sys_ver == SOC_SILICONID_Rev1_0) {
666                 ret_val = (2 * pll_clock(MCU_PLL)) / div;
667             } else {
668                 ret_val = (4 * pll_clock(MCU_PLL)) / (3*div);
669             }
670         } else {
671             ret_val = (2 * pll_clock(SER_PLL)) / div;
672         }
673         break;
674     case H264_BAUD:
675         if (sys_ver == SOC_SILICONID_Rev1_0) {
676             div = (pcdr0 >> 8) & 0xF;
677             if (div < 2) {
678                 div = 62 * 2;
679             }
680         } else {
681             div = (pcdr0 >> 10) & 0x3F;
682             div += 4;
683         }
684         if ((cscr & (1 << 21)) != 0) {
685             if (sys_ver == SOC_SILICONID_Rev1_0) {
686                 ret_val = (2 * pll_clock(MCU_PLL)) / div;
687             } else {
688                 ret_val = (4 * pll_clock(MCU_PLL)) / (3*div);
689             }
690         } else {
691             ret_val = (2 * pll_clock(SER_PLL)) / div;
692         }
693         break;
694     case MSHC_BAUD:
695         if ((cscr & (1 << 20)) != 0) {
696             if (sys_ver == SOC_SILICONID_Rev1_0) {
697                 div = (pcdr0 & 0x1F) + 1;
698                 ret_val = pll_clock(MCU_PLL) / div;
699             } else {
700                 div = (pcdr0 & 0x3F) + 1;
701                 ret_val = 2*pll_clock(MCU_PLL) / (3*div);
702             }
703         } else {
704             div = (pcdr0 & 0x1F) + 1;
705             ret_val = (2 * pll_clock(SER_PLL)) / div;
706         }
707         break;
708     default:
709         diag_printf("%s(): This clock: %d not supported yet \n",
710                     __FUNCTION__, clk);
711         break;
712     }
713
714     return ret_val;
715 }
716
717 RedBoot_cmd("clko",
718             "Select clock source for CLKO (TP1 on EVB or S3 Pin 1)",
719             " The output clock is the actual clock source freq divided by 8. Default is FCLK\n\
720          Note that the module clock will be turned on for reading!\n\
721           <0> - display current clko selection \n\
722           <1> - CLK32 \n\
723           <2> - PREMCLK \n\
724           <3> - CLK26M (may see nothing if 26MHz Crystal is not connected) \n\
725           <4> - MPLL Reference CLK \n\
726           <5> - SPLL Reference CLK \n\
727           <6> - MPLL CLK \n\
728           <7> - SPLL CLK \n\
729           <8> - FCLK \n\
730           <9> - AHBCLK \n\
731           <10> - IPG_CLK (PERCLK) \n\
732           <11> - PERCLK1 \n\
733           <12> - PERCLK2 \n\
734           <13> - PERCLK3 \n\
735           <14> - PERCLK4 \n\
736           <15> - SSI 1 Baud \n\
737           <16> - SSI 2 Baud \n\
738           <17> - NFC \n\
739           <18> - MSHC Baud \n\
740           <19> - H264 Baud \n\
741           <20> - CLK60M Always \n\
742           <21> - CLK32K Always \n\
743           <22> - CLK60M \n\
744           <23> - DPTC Ref",
745             clko
746            );
747
748 static u8* clko_name[] ={
749     "NULL",
750     "CLK32",
751     "PREMCLK",
752     "CLK26M (may see nothing if 26MHz Crystal is not connected)",
753     "MPLL Reference CLK",
754     "SPLL Reference CLK",
755     "MPLL CLK",
756     "SPLL CLK",
757     "FCLK",
758     "AHBCLK",
759     "IPG_CLK (PERCLK)",
760     "PERCLK1",
761     "PERCLK2",
762     "PERCLK3",
763     "PERCLK4",
764     "SSI 1 Baud",
765     "SSI 2 Baud",
766     "NFC",
767     "MSHC Baud",
768     "H264 Baud",
769     "CLK60M Always",
770     "CLK32K Always",
771     "CLK60M",
772     "DPTC Ref",
773 };
774
775 #define CLKO_MAX_INDEX          (sizeof(clko_name) / sizeof(u8*))
776
777 static void clko(int argc,char *argv[])
778 {
779     u32 action = 0, ccsr;
780
781     if (!scan_opts(argc, argv, 1, 0, 0, &action,
782                    OPTION_ARG_TYPE_NUM, "action"))
783         return;
784
785     if (action >= CLKO_MAX_INDEX) {
786         diag_printf("%d is not supported\n\n", action);
787         return;
788     }
789
790     ccsr = readl(SOC_CRM_CCSR);
791
792     if (action != 0) {
793         ccsr = (ccsr & (~0x1F)) + action - 1;
794         writel(ccsr, SOC_CRM_CCSR);
795         diag_printf("Set clko to ");
796     }
797
798     ccsr = readl(SOC_CRM_CCSR);
799     diag_printf("%s\n", clko_name[(ccsr & 0x1F) + 1]);
800     diag_printf("CCSR register[0x%x] = 0x%x\n", SOC_CRM_CCSR, ccsr);
801 }
802
803 extern int flash_program(void *_addr, void *_data, int len, void **err_addr);
804 extern int flash_erase(void *addr, int len, void **err_addr);
805
806 void auto_flash_start(void)
807 {
808     void *err_addr;
809         int stat;
810     int nor_update = 1; //todo: need to support NAND
811     u32 src = readl(SERIAL_DOWNLOAD_SRC_REG);
812     u32 dst = readl(SERIAL_DOWNLOAD_TGT_REG);
813     u32 sz = readl(SERIAL_DOWNLOAD_SZ_REG);
814
815     if (readl(SERIAL_DOWNLOAD_MAGIC_REG) != SERIAL_DOWNLOAD_MAGIC) {
816         return;
817     }
818
819     if (nor_update) {
820         // Erase area to be programmed
821         if ((stat = flash_erase((void *)dst, sz, &err_addr)) != 0) {
822             diag_printf("BEADDEAD\n");
823         return;
824         }
825         diag_printf("BEADBEEF\n");
826         // Now program it
827         if ((stat = flash_program((void *)dst, (void *)src, sz,
828                                   &err_addr)) != 0) {
829             diag_printf("BEADFEEF\n");
830         }
831     }
832     diag_printf("BEADCEEF\n");
833 }
834
835 RedBoot_init(auto_flash_start, RedBoot_INIT_LAST);
836
837 #define IIM_ERR_SHIFT       8
838 #define POLL_FUSE_PRGD      (IIM_STAT_PRGD | (IIM_ERR_PRGE << IIM_ERR_SHIFT))
839 #define POLL_FUSE_SNSD      (IIM_STAT_SNSD | (IIM_ERR_SNSE << IIM_ERR_SHIFT))
840
841 static void fuse_op_start(void)
842 {
843     /* Do not generate interrupt */
844     writel(0, IIM_BASE_ADDR + IIM_STATM_OFF);
845     // clear the status bits and error bits
846     writel(0x3, IIM_BASE_ADDR + IIM_STAT_OFF);
847     writel(0xFE, IIM_BASE_ADDR + IIM_ERR_OFF);
848 }
849
850 /*
851  * The action should be either:
852  *          POLL_FUSE_PRGD
853  * or:
854  *          POLL_FUSE_SNSD
855  */
856 static int poll_fuse_op_done(int action)
857 {
858
859     u32 status, error;
860
861     if (action != POLL_FUSE_PRGD && action != POLL_FUSE_SNSD) {
862         diag_printf("%s(%d) invalid operation\n", __FUNCTION__, action);
863         return -1;
864     }
865
866     /* Poll busy bit till it is NOT set */
867     while ((readl(IIM_BASE_ADDR + IIM_STAT_OFF) & IIM_STAT_BUSY) != 0 ) {
868     }
869
870     /* Test for successful write */
871     status = readl(IIM_BASE_ADDR + IIM_STAT_OFF);
872     error = readl(IIM_BASE_ADDR + IIM_ERR_OFF);
873
874     if ((status & action) != 0 && (error & (action >> IIM_ERR_SHIFT)) == 0) {
875         if (error) {
876             diag_printf("Even though the operation seems successful...\n");
877             diag_printf("There are some error(s) at addr=0x%x: 0x%x\n",
878                         (IIM_BASE_ADDR + IIM_ERR_OFF), error);
879         }
880         return 0;
881     }
882     diag_printf("%s(%d) failed\n", __FUNCTION__, action);
883     diag_printf("status address=0x%x, value=0x%x\n",
884                 (IIM_BASE_ADDR + IIM_STAT_OFF), status);
885     diag_printf("There are some error(s) at addr=0x%x: 0x%x\n",
886                 (IIM_BASE_ADDR + IIM_ERR_OFF), error);
887     return -1;
888 }
889
890 static void sense_fuse(int bank, int row, int bit)
891 {
892     int ret;
893     int addr, addr_l, addr_h, reg_addr;
894
895     fuse_op_start();
896
897     addr = ((bank << 11) | (row << 3) | (bit & 0x7));
898     /* Set IIM Program Upper Address */
899     addr_h = (addr >> 8) & 0x000000FF;
900     /* Set IIM Program Lower Address */
901     addr_l = (addr & 0x000000FF);
902
903 #ifdef IIM_FUSE_DEBUG
904     diag_printf("%s: addr_h=0x%x, addr_l=0x%x\n",
905                 __FUNCTION__, addr_h, addr_l);
906 #endif
907     writel(addr_h, IIM_BASE_ADDR + IIM_UA_OFF);
908     writel(addr_l, IIM_BASE_ADDR + IIM_LA_OFF);
909     /* Start sensing */
910     writel(0x8, IIM_BASE_ADDR + IIM_FCTL_OFF);
911     if ((ret = poll_fuse_op_done(POLL_FUSE_SNSD)) != 0) {
912         diag_printf("%s(bank: %d, row: %d, bit: %d failed\n",
913                     __FUNCTION__, bank, row, bit);
914     }
915     reg_addr = IIM_BASE_ADDR + IIM_SDAT_OFF;
916     if (ret == 0)
917         diag_printf("fuses at (bank:%d, row:%d) = 0x%x\n", bank, row, readl(reg_addr));
918 }
919
920 void do_fuse_read(int argc, char *argv[])
921 {
922     unsigned long bank, row;
923
924     if (argc == 1) {
925         diag_printf("Useage: fuse_read <bank> <row>\n");
926         return;
927     } else if (argc == 3) {
928         if (!parse_num(argv[1], &bank, &argv[1], " ")) {
929                 diag_printf("Error: Invalid parameter\n");
930             return;
931         }
932         if (!parse_num(*(&argv[2]), &row, &argv[2], " ")) {
933                 diag_printf("Error: Invalid parameter\n");
934                 return;
935             }
936
937         diag_printf("Read fuse at bank:%ld row:%ld\n", bank, row);
938         sense_fuse(bank, row, 0);
939
940     } else {
941         diag_printf("Passing in wrong arguments: %d\n", argc);
942         diag_printf("Useage: fuse_read <bank> <row>\n");
943     }
944 }
945
946 /* Blow fuses based on the bank, row and bit positions (all 0-based)
947 */
948 static int fuse_blow(int bank,int row,int bit)
949 {
950     int addr, addr_l, addr_h, ret = -1;
951
952     fuse_op_start();
953
954     /* Disable IIM Program Protect */
955     writel(0xAA, IIM_BASE_ADDR + IIM_PREG_P_OFF);
956
957     addr = ((bank << 11) | (row << 3) | (bit & 0x7));
958     /* Set IIM Program Upper Address */
959     addr_h = (addr >> 8) & 0x000000FF;
960     /* Set IIM Program Lower Address */
961     addr_l = (addr & 0x000000FF);
962
963 #ifdef IIM_FUSE_DEBUG
964     diag_printf("blowing addr_h=0x%x, addr_l=0x%x\n", addr_h, addr_l);
965 #endif
966
967     writel(addr_h, IIM_BASE_ADDR + IIM_UA_OFF);
968     writel(addr_l, IIM_BASE_ADDR + IIM_LA_OFF);
969     /* Start Programming */
970     writel(0x31, IIM_BASE_ADDR + IIM_FCTL_OFF);
971     if (poll_fuse_op_done(POLL_FUSE_PRGD) == 0) {
972         ret = 0;
973     }
974
975     /* Enable IIM Program Protect */
976     writel(0x0, IIM_BASE_ADDR + IIM_PREG_P_OFF);
977     return ret;
978 }
979
980 /*
981  * This command is added for burning IIM fuses
982  */
983 RedBoot_cmd("fuse_read",
984             "read some fuses",
985             "<bank> <row>",
986             do_fuse_read
987            );
988
989 RedBoot_cmd("fuse_blow",
990             "blow some fuses",
991             "<bank> <row> <value>",
992             do_fuse_blow
993            );
994
995 #define         INIT_STRING              "12345678"
996 static char ready_to_blow[] = INIT_STRING;
997
998 void quick_itoa(u32 num, char *a)
999 {
1000     int i, j, k;
1001     for (i = 0; i <= 7; i++) {
1002         j = (num >> (4 * i)) & 0xF;
1003         k = (j < 10) ? '0' : ('a' - 0xa);
1004         a[i] = j + k;
1005     }
1006 }
1007
1008 void do_fuse_blow(int argc, char *argv[])
1009 {
1010     unsigned long bank, row, value;
1011     int i;
1012
1013     if (argc == 1) {
1014         diag_printf("It is too dangeous for you to use this command.\n");
1015         return;
1016     } else if (argc == 2) {
1017         if (strcasecmp(argv[1], "nandboot") == 0) {
1018             diag_printf("%s\n", "fuse blown not needed");
1019         }
1020         return;
1021     } else if (argc == 3) {
1022         if (strcasecmp(argv[1], "nandboot") == 0) {
1023 #if defined(CYGPKG_HAL_ARM_MXC91131) || defined(CYGPKG_HAL_ARM_MX21) || defined(CYGPKG_HAL_ARM_MX27) || defined(CYGPKG_HAL_ARM_MX31)
1024             diag_printf("No need to blow any fuses for NAND boot on this platform\n\n");
1025 #else
1026             diag_printf("Ready to burn NAND boot fuses\n");
1027             if (fuse_blow(0, 16, 1) != 0 || fuse_blow(0, 16, 7) != 0) {
1028                 diag_printf("NAND BOOT fuse blown failed miserably ...\n");
1029             } else {
1030                 diag_printf("NAND BOOT fuse blown successfully ...\n");
1031             }
1032         } else {
1033             diag_printf("Not ready: %s, %s\n", argv[1], argv[2]);
1034 #endif
1035         }
1036     } else if (argc == 4) {
1037         if (!parse_num(argv[1], &bank, &argv[1], " ")) {
1038                 diag_printf("Error: Invalid parameter\n");
1039                 return;
1040         }
1041         if (!parse_num(argv[2], &row, &argv[2], " ")) {
1042                 diag_printf("Error: Invalid parameter\n");
1043                 return;
1044         }
1045         if (!parse_num(argv[3], &value, &argv[3], " ")) {
1046                 diag_printf("Error: Invalid parameter\n");
1047                 return;
1048         }
1049
1050         diag_printf("Blowing fuse at bank:%ld row:%ld value:%ld\n",
1051                     bank, row, value);
1052         for (i = 0; i < 8; i++) {
1053             if (((value >> i) & 0x1) == 0) {
1054                 continue;
1055             }
1056             if (fuse_blow(bank, row, i) != 0) {
1057                 diag_printf("fuse_blow(bank: %ld, row: %ld, bit: %d failed\n",
1058                             bank, row, i);
1059             } else {
1060                 diag_printf("fuse_blow(bank: %ld, row: %ld, bit: %d successful\n",
1061                             bank, row, i);
1062             }
1063         }
1064         sense_fuse(bank, row, 0);
1065
1066     } else {
1067         diag_printf("Passing in wrong arguments: %d\n", argc);
1068     }
1069     /* Reset to default string */
1070     strcpy(ready_to_blow, INIT_STRING);
1071 }
1072
1073 /* precondition: m>0 and n>0.  Let g=gcd(m,n). */
1074 int gcd(int m, int n)
1075 {
1076     int t;
1077     while(m > 0) {
1078         if(n > m) {t = m; m = n; n = t;} /* swap */
1079         m -= n;
1080     }
1081     return n;
1082 }
1083
1084 #define CLOCK_SRC_DETECT_MS         100
1085 #define CLOCK_IPG_DEFAULT           66500000
1086 #define CLOCK_SRC_DETECT_MARGIN     500000
1087 void mxc_show_clk_input(void)
1088 {
1089 #if 0
1090     u32 c1, c2, diff, ipg_real, num = 0;
1091     u32 prcs = (readl(CCM_BASE_ADDR + CLKCTL_CCMR) >> 1) & 0x3;
1092
1093     return;  // FIXME
1094
1095     switch (prcs) {
1096     case 0x01:
1097         diag_printf("FPM enabled --> 32KHz input source\n");
1098         return;
1099     case 0x02:
1100         break;
1101     default:
1102         diag_printf("Error %d: unknown clock source %d\n", __LINE__, prcs);
1103         return;
1104     }
1105
1106     // enable GPT with IPG clock input
1107     writel(0x241, GPT_BASE_ADDR + GPTCR);
1108     // prescaler = 1
1109     writel(0, GPT_BASE_ADDR + GPTPR);
1110
1111     c1 = readl(GPT_BASE_ADDR + GPTCNT);
1112     // use 32KHz input clock to get the delay
1113     hal_delay_us(CLOCK_SRC_DETECT_MS * 1000);
1114     c2 = readl(GPT_BASE_ADDR + GPTCNT);
1115     diff = (c2 > c1) ? (c2 - c1) : (0xFFFFFFFF - c1 + c2);
1116
1117     ipg_real = diff * (1000 / CLOCK_SRC_DETECT_MS);
1118
1119     if (ipg_real > (CLOCK_IPG_DEFAULT + CLOCK_SRC_DETECT_MARGIN)) {
1120         if (g_clock_src != FREQ_27MHZ)
1121             num = 27;
1122     } else if (ipg_real < (CLOCK_IPG_DEFAULT - CLOCK_SRC_DETECT_MARGIN)) {
1123         if (g_clock_src != FREQ_26MHZ)
1124             num = 26;
1125     }
1126     if (num != 0) {
1127         diag_printf("Error: Actural clock input is %d MHz\n", num);
1128         diag_printf("       ipg_real=%d CLOCK_IPG_DEFAULT - CLOCK_SRC_DETECT_MARGIN=%d\n\n",
1129                     ipg_real, CLOCK_IPG_DEFAULT - CLOCK_SRC_DETECT_MARGIN);
1130         diag_printf("       But clock source defined to be %d\n\n", g_clock_src);
1131         hal_delay_us(2000000);
1132     } else {
1133         diag_printf("ipg_real=%d CLOCK_IPG_DEFAULT - CLOCK_SRC_DETECT_MARGIN=%d\n\n",
1134                     ipg_real, CLOCK_IPG_DEFAULT - CLOCK_SRC_DETECT_MARGIN);
1135         diag_printf("clock source defined to be %d\n\n", g_clock_src);
1136     }
1137 #endif
1138 }
1139
1140 RedBoot_init(mxc_show_clk_input, RedBoot_INIT_LAST);
1141
1142 void clock_spi_enable(unsigned int spi_clk)
1143 {
1144     unsigned int reg = readl(SOC_CRM_PCCR1);
1145
1146     // turn on PERCLK2
1147     writel(reg | (1 << 9), SOC_CRM_PCCR1);
1148
1149     reg = readl(SOC_CRM_PCCR0);
1150
1151     if (spi_clk == SPI1_CLK) {
1152         writel(reg | (1 << 31), SOC_CRM_PCCR0);
1153         gpio_request_mux(MX27_PIN_CSPI1_MOSI, GPIO_MUX_PRIMARY);
1154         gpio_request_mux(MX27_PIN_CSPI1_MISO, GPIO_MUX_PRIMARY);
1155         gpio_request_mux(MX27_PIN_CSPI1_SCLK, GPIO_MUX_PRIMARY);
1156         gpio_request_mux(MX27_PIN_CSPI1_RDY, GPIO_MUX_PRIMARY);
1157         gpio_request_mux(MX27_PIN_CSPI1_SS0, GPIO_MUX_PRIMARY);
1158         gpio_request_mux(MX27_PIN_CSPI1_SS1, GPIO_MUX_PRIMARY);
1159         gpio_request_mux(MX27_PIN_CSPI1_SS2, GPIO_MUX_PRIMARY);
1160     } else if (spi_clk == SPI2_CLK) {
1161         writel(reg | (1 << 30), SOC_CRM_PCCR0);
1162     }
1163 }