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