]> bbs.cooldavid.org Git - net-next-2.6.git/blob - arch/m68knommu/platform/532x/config.c
66e212b58b85908f3e92800cc1232523408da584
[net-next-2.6.git] / arch / m68knommu / platform / 532x / config.c
1 /***************************************************************************/
2
3 /*
4  *      linux/arch/m68knommu/platform/532x/config.c
5  *
6  *      Copyright (C) 1999-2002, Greg Ungerer (gerg@snapgear.com)
7  *      Copyright (C) 2000, Lineo (www.lineo.com)
8  *      Yaroslav Vinogradov yaroslav.vinogradov@freescale.com
9  *      Copyright Freescale Semiconductor, Inc 2006
10  *      Copyright (c) 2006, emlix, Sebastian Hess <sh@emlix.com>
11  *
12  * This program is free software; you can redistribute it and/or modify
13  * it under the terms of the GNU General Public License as published by
14  * the Free Software Foundation; either version 2 of the License, or
15  * (at your option) any later version.
16  */
17
18 /***************************************************************************/
19
20 #include <linux/kernel.h>
21 #include <linux/param.h>
22 #include <linux/init.h>
23 #include <linux/io.h>
24 #include <asm/machdep.h>
25 #include <asm/coldfire.h>
26 #include <asm/mcfsim.h>
27 #include <asm/mcfuart.h>
28 #include <asm/mcfdma.h>
29 #include <asm/mcfwdebug.h>
30
31 /***************************************************************************/
32
33 extern unsigned int mcf_timervector;
34 extern unsigned int mcf_profilevector;
35 extern unsigned int mcf_timerlevel;
36
37 /***************************************************************************/
38
39 static struct mcf_platform_uart m532x_uart_platform[] = {
40         {
41                 .mapbase        = MCFUART_BASE1,
42                 .irq            = MCFINT_VECBASE + MCFINT_UART0,
43         },
44         {
45                 .mapbase        = MCFUART_BASE2,
46                 .irq            = MCFINT_VECBASE + MCFINT_UART1,
47         },
48         {
49                 .mapbase        = MCFUART_BASE3,
50                 .irq            = MCFINT_VECBASE + MCFINT_UART2,
51         },
52         { },
53 };
54
55 static struct platform_device m532x_uart = {
56         .name                   = "mcfuart",
57         .id                     = 0,
58         .dev.platform_data      = m532x_uart_platform,
59 };
60
61 static struct resource m532x_fec_resources[] = {
62         {
63                 .start          = 0xfc030000,
64                 .end            = 0xfc0307ff,
65                 .flags          = IORESOURCE_MEM,
66         },
67         {
68                 .start          = 64 + 36,
69                 .end            = 64 + 36,
70                 .flags          = IORESOURCE_IRQ,
71         },
72         {
73                 .start          = 64 + 40,
74                 .end            = 64 + 40,
75                 .flags          = IORESOURCE_IRQ,
76         },
77         {
78                 .start          = 64 + 42,
79                 .end            = 64 + 42,
80                 .flags          = IORESOURCE_IRQ,
81         },
82 };
83
84 static struct platform_device m532x_fec = {
85         .name                   = "fec",
86         .id                     = 0,
87         .num_resources          = ARRAY_SIZE(m532x_fec_resources),
88         .resource               = m532x_fec_resources,
89 };
90 static struct platform_device *m532x_devices[] __initdata = {
91         &m532x_uart,
92         &m532x_fec,
93 };
94
95 /***************************************************************************/
96
97 static void __init m532x_uart_init_line(int line, int irq)
98 {
99         if (line == 0) {
100                 /* GPIO initialization */
101                 MCF_GPIO_PAR_UART |= 0x000F;
102         } else if (line == 1) {
103                 /* GPIO initialization */
104                 MCF_GPIO_PAR_UART |= 0x0FF0;
105         }
106 }
107
108 static void __init m532x_uarts_init(void)
109 {
110         const int nrlines = ARRAY_SIZE(m532x_uart_platform);
111         int line;
112
113         for (line = 0; (line < nrlines); line++)
114                 m532x_uart_init_line(line, m532x_uart_platform[line].irq);
115 }
116 /***************************************************************************/
117
118 static void __init m532x_fec_init(void)
119 {
120         /* Set multi-function pins to ethernet mode for fec0 */
121         MCF_GPIO_PAR_FECI2C |= (MCF_GPIO_PAR_FECI2C_PAR_MDC_EMDC |
122                 MCF_GPIO_PAR_FECI2C_PAR_MDIO_EMDIO);
123         MCF_GPIO_PAR_FEC = (MCF_GPIO_PAR_FEC_PAR_FEC_7W_FEC |
124                 MCF_GPIO_PAR_FEC_PAR_FEC_MII_FEC);
125 }
126
127 /***************************************************************************/
128
129 void mcf_settimericr(unsigned int timer, unsigned int level)
130 {
131 }
132
133 /***************************************************************************/
134
135 static void m532x_cpu_reset(void)
136 {
137         local_irq_disable();
138         __raw_writeb(MCF_RCR_SWRESET, MCF_RCR);
139 }
140
141 /***************************************************************************/
142
143 void __init config_BSP(char *commandp, int size)
144 {
145 #if !defined(CONFIG_BOOTPARAM)
146         /* Copy command line from FLASH to local buffer... */
147         memcpy(commandp, (char *) 0x4000, 4);
148         if(strncmp(commandp, "kcl ", 4) == 0){
149                 memcpy(commandp, (char *) 0x4004, size);
150                 commandp[size-1] = 0;
151         } else {
152                 memset(commandp, 0, size);
153         }
154 #endif
155
156         mcf_timervector = 64+32;
157         mcf_profilevector = 64+33;
158         mach_reset = m532x_cpu_reset;
159
160 #ifdef CONFIG_BDM_DISABLE
161         /*
162          * Disable the BDM clocking.  This also turns off most of the rest of
163          * the BDM device.  This is good for EMC reasons. This option is not
164          * incompatible with the memory protection option.
165          */
166         wdebug(MCFDEBUG_CSR, MCFDEBUG_CSR_PSTCLK);
167 #endif
168 }
169
170 /***************************************************************************/
171
172 static int __init init_BSP(void)
173 {
174         m532x_uarts_init();
175         m532x_fec_init();
176         platform_add_devices(m532x_devices, ARRAY_SIZE(m532x_devices));
177         return 0;
178 }
179
180 arch_initcall(init_BSP);
181
182 /***************************************************************************/
183 /* Board initialization */
184 /***************************************************************************/
185 /* 
186  * PLL min/max specifications
187  */
188 #define MAX_FVCO        500000  /* KHz */
189 #define MAX_FSYS        80000   /* KHz */
190 #define MIN_FSYS        58333   /* KHz */
191 #define FREF            16000   /* KHz */
192
193
194 #define MAX_MFD         135     /* Multiplier */
195 #define MIN_MFD         88      /* Multiplier */
196 #define BUSDIV          6       /* Divider */
197
198 /*
199  * Low Power Divider specifications
200  */
201 #define MIN_LPD         (1 << 0)    /* Divider (not encoded) */
202 #define MAX_LPD         (1 << 15)   /* Divider (not encoded) */
203 #define DEFAULT_LPD     (1 << 1)        /* Divider (not encoded) */
204
205 #define SYS_CLK_KHZ     80000
206 #define SYSTEM_PERIOD   12.5
207 /*
208  *  SDRAM Timing Parameters
209  */  
210 #define SDRAM_BL        8       /* # of beats in a burst */
211 #define SDRAM_TWR       2       /* in clocks */
212 #define SDRAM_CASL      2.5     /* CASL in clocks */
213 #define SDRAM_TRCD      2       /* in clocks */
214 #define SDRAM_TRP       2       /* in clocks */
215 #define SDRAM_TRFC      7       /* in clocks */
216 #define SDRAM_TREFI     7800    /* in ns */
217
218 #define EXT_SRAM_ADDRESS        (0xC0000000)
219 #define FLASH_ADDRESS           (0x00000000)
220 #define SDRAM_ADDRESS           (0x40000000)
221
222 #define NAND_FLASH_ADDRESS      (0xD0000000)
223
224 int sys_clk_khz = 0;
225 int sys_clk_mhz = 0;
226
227 void wtm_init(void);
228 void scm_init(void);
229 void gpio_init(void);
230 void fbcs_init(void);
231 void sdramc_init(void);
232 int  clock_pll (int fsys, int flags);
233 int  clock_limp (int);
234 int  clock_exit_limp (void);
235 int  get_sys_clock (void);
236
237 asmlinkage void __init sysinit(void)
238 {
239         sys_clk_khz = clock_pll(0, 0);
240         sys_clk_mhz = sys_clk_khz/1000;
241         
242         wtm_init();
243         scm_init();
244         gpio_init();
245         fbcs_init();
246         sdramc_init();
247 }
248
249 void wtm_init(void)
250 {
251         /* Disable watchdog timer */
252         MCF_WTM_WCR = 0;
253 }
254
255 #define MCF_SCM_BCR_GBW         (0x00000100)
256 #define MCF_SCM_BCR_GBR         (0x00000200)
257
258 void scm_init(void)
259 {
260         /* All masters are trusted */
261         MCF_SCM_MPR = 0x77777777;
262     
263         /* Allow supervisor/user, read/write, and trusted/untrusted
264            access to all slaves */
265         MCF_SCM_PACRA = 0;
266         MCF_SCM_PACRB = 0;
267         MCF_SCM_PACRC = 0;
268         MCF_SCM_PACRD = 0;
269         MCF_SCM_PACRE = 0;
270         MCF_SCM_PACRF = 0;
271
272         /* Enable bursts */
273         MCF_SCM_BCR = (MCF_SCM_BCR_GBR | MCF_SCM_BCR_GBW);
274 }
275
276
277 void fbcs_init(void)
278 {
279         MCF_GPIO_PAR_CS = 0x0000003E;
280
281         /* Latch chip select */
282         MCF_FBCS1_CSAR = 0x10080000;
283
284         MCF_FBCS1_CSCR = 0x002A3780;
285         MCF_FBCS1_CSMR = (MCF_FBCS_CSMR_BAM_2M | MCF_FBCS_CSMR_V);
286
287         /* Initialize latch to drive signals to inactive states */
288         *((u16 *)(0x10080000)) = 0xFFFF;
289
290         /* External SRAM */
291         MCF_FBCS1_CSAR = EXT_SRAM_ADDRESS;
292         MCF_FBCS1_CSCR = (MCF_FBCS_CSCR_PS_16
293                         | MCF_FBCS_CSCR_AA
294                         | MCF_FBCS_CSCR_SBM
295                         | MCF_FBCS_CSCR_WS(1));
296         MCF_FBCS1_CSMR = (MCF_FBCS_CSMR_BAM_512K
297                         | MCF_FBCS_CSMR_V);
298
299         /* Boot Flash connected to FBCS0 */
300         MCF_FBCS0_CSAR = FLASH_ADDRESS;
301         MCF_FBCS0_CSCR = (MCF_FBCS_CSCR_PS_16
302                         | MCF_FBCS_CSCR_BEM
303                         | MCF_FBCS_CSCR_AA
304                         | MCF_FBCS_CSCR_SBM
305                         | MCF_FBCS_CSCR_WS(7));
306         MCF_FBCS0_CSMR = (MCF_FBCS_CSMR_BAM_32M
307                         | MCF_FBCS_CSMR_V);
308 }
309
310 void sdramc_init(void)
311 {
312         /*
313          * Check to see if the SDRAM has already been initialized
314          * by a run control tool
315          */
316         if (!(MCF_SDRAMC_SDCR & MCF_SDRAMC_SDCR_REF)) {
317                 /* SDRAM chip select initialization */
318                 
319                 /* Initialize SDRAM chip select */
320                 MCF_SDRAMC_SDCS0 = (0
321                         | MCF_SDRAMC_SDCS_BA(SDRAM_ADDRESS)
322                         | MCF_SDRAMC_SDCS_CSSZ(MCF_SDRAMC_SDCS_CSSZ_32MBYTE));
323
324         /*
325          * Basic configuration and initialization
326          */
327         MCF_SDRAMC_SDCFG1 = (0
328                 | MCF_SDRAMC_SDCFG1_SRD2RW((int)((SDRAM_CASL + 2) + 0.5 ))
329                 | MCF_SDRAMC_SDCFG1_SWT2RD(SDRAM_TWR + 1)
330                 | MCF_SDRAMC_SDCFG1_RDLAT((int)((SDRAM_CASL*2) + 2))
331                 | MCF_SDRAMC_SDCFG1_ACT2RW((int)((SDRAM_TRCD ) + 0.5))
332                 | MCF_SDRAMC_SDCFG1_PRE2ACT((int)((SDRAM_TRP ) + 0.5))
333                 | MCF_SDRAMC_SDCFG1_REF2ACT((int)(((SDRAM_TRFC) ) + 0.5))
334                 | MCF_SDRAMC_SDCFG1_WTLAT(3));
335         MCF_SDRAMC_SDCFG2 = (0
336                 | MCF_SDRAMC_SDCFG2_BRD2PRE(SDRAM_BL/2 + 1)
337                 | MCF_SDRAMC_SDCFG2_BWT2RW(SDRAM_BL/2 + SDRAM_TWR)
338                 | MCF_SDRAMC_SDCFG2_BRD2WT((int)((SDRAM_CASL+SDRAM_BL/2-1.0)+0.5))
339                 | MCF_SDRAMC_SDCFG2_BL(SDRAM_BL-1));
340
341             
342         /*
343          * Precharge and enable write to SDMR
344          */
345         MCF_SDRAMC_SDCR = (0
346                 | MCF_SDRAMC_SDCR_MODE_EN
347                 | MCF_SDRAMC_SDCR_CKE
348                 | MCF_SDRAMC_SDCR_DDR
349                 | MCF_SDRAMC_SDCR_MUX(1)
350                 | MCF_SDRAMC_SDCR_RCNT((int)(((SDRAM_TREFI/(SYSTEM_PERIOD*64)) - 1) + 0.5))
351                 | MCF_SDRAMC_SDCR_PS_16
352                 | MCF_SDRAMC_SDCR_IPALL);            
353
354         /*
355          * Write extended mode register
356          */
357         MCF_SDRAMC_SDMR = (0
358                 | MCF_SDRAMC_SDMR_BNKAD_LEMR
359                 | MCF_SDRAMC_SDMR_AD(0x0)
360                 | MCF_SDRAMC_SDMR_CMD);
361
362         /*
363          * Write mode register and reset DLL
364          */
365         MCF_SDRAMC_SDMR = (0
366                 | MCF_SDRAMC_SDMR_BNKAD_LMR
367                 | MCF_SDRAMC_SDMR_AD(0x163)
368                 | MCF_SDRAMC_SDMR_CMD);
369
370         /*
371          * Execute a PALL command
372          */
373         MCF_SDRAMC_SDCR |= MCF_SDRAMC_SDCR_IPALL;
374
375         /*
376          * Perform two REF cycles
377          */
378         MCF_SDRAMC_SDCR |= MCF_SDRAMC_SDCR_IREF;
379         MCF_SDRAMC_SDCR |= MCF_SDRAMC_SDCR_IREF;
380
381         /*
382          * Write mode register and clear reset DLL
383          */
384         MCF_SDRAMC_SDMR = (0
385                 | MCF_SDRAMC_SDMR_BNKAD_LMR
386                 | MCF_SDRAMC_SDMR_AD(0x063)
387                 | MCF_SDRAMC_SDMR_CMD);
388                                 
389         /*
390          * Enable auto refresh and lock SDMR
391          */
392         MCF_SDRAMC_SDCR &= ~MCF_SDRAMC_SDCR_MODE_EN;
393         MCF_SDRAMC_SDCR |= (0
394                 | MCF_SDRAMC_SDCR_REF
395                 | MCF_SDRAMC_SDCR_DQS_OE(0xC));
396         }
397 }
398
399 void gpio_init(void)
400 {
401         /* Enable UART0 pins */
402         MCF_GPIO_PAR_UART = ( 0
403                 | MCF_GPIO_PAR_UART_PAR_URXD0
404                 | MCF_GPIO_PAR_UART_PAR_UTXD0);
405
406         /* Initialize TIN3 as a GPIO output to enable the write
407            half of the latch */
408         MCF_GPIO_PAR_TIMER = 0x00;
409         __raw_writeb(0x08, MCFGPIO_PDDR_TIMER);
410         __raw_writeb(0x00, MCFGPIO_PCLRR_TIMER);
411
412 }
413
414 int clock_pll(int fsys, int flags)
415 {
416         int fref, temp, fout, mfd;
417         u32 i;
418
419         fref = FREF;
420         
421         if (fsys == 0) {
422                 /* Return current PLL output */
423                 mfd = MCF_PLL_PFDR;
424
425                 return (fref * mfd / (BUSDIV * 4));
426         }
427
428         /* Check bounds of requested system clock */
429         if (fsys > MAX_FSYS)
430                 fsys = MAX_FSYS;
431         if (fsys < MIN_FSYS)
432                 fsys = MIN_FSYS;
433
434         /* Multiplying by 100 when calculating the temp value,
435            and then dividing by 100 to calculate the mfd allows
436            for exact values without needing to include floating
437            point libraries. */
438         temp = 100 * fsys / fref;
439         mfd = 4 * BUSDIV * temp / 100;
440                         
441         /* Determine the output frequency for selected values */
442         fout = (fref * mfd / (BUSDIV * 4));
443
444         /*
445          * Check to see if the SDRAM has already been initialized.
446          * If it has then the SDRAM needs to be put into self refresh
447          * mode before reprogramming the PLL.
448          */
449         if (MCF_SDRAMC_SDCR & MCF_SDRAMC_SDCR_REF)
450                 /* Put SDRAM into self refresh mode */
451                 MCF_SDRAMC_SDCR &= ~MCF_SDRAMC_SDCR_CKE;
452
453         /*
454          * Initialize the PLL to generate the new system clock frequency.
455          * The device must be put into LIMP mode to reprogram the PLL.
456          */
457
458         /* Enter LIMP mode */
459         clock_limp(DEFAULT_LPD);
460                                         
461         /* Reprogram PLL for desired fsys */
462         MCF_PLL_PODR = (0
463                 | MCF_PLL_PODR_CPUDIV(BUSDIV/3)
464                 | MCF_PLL_PODR_BUSDIV(BUSDIV));
465                                                 
466         MCF_PLL_PFDR = mfd;
467                 
468         /* Exit LIMP mode */
469         clock_exit_limp();
470         
471         /*
472          * Return the SDRAM to normal operation if it is in use.
473          */
474         if (MCF_SDRAMC_SDCR & MCF_SDRAMC_SDCR_REF)
475                 /* Exit self refresh mode */
476                 MCF_SDRAMC_SDCR |= MCF_SDRAMC_SDCR_CKE;
477
478         /* Errata - workaround for SDRAM opeartion after exiting LIMP mode */
479         MCF_SDRAMC_LIMP_FIX = MCF_SDRAMC_REFRESH;
480
481         /* wait for DQS logic to relock */
482         for (i = 0; i < 0x200; i++)
483                 ;
484
485         return fout;
486 }
487
488 int clock_limp(int div)
489 {
490         u32 temp;
491
492         /* Check bounds of divider */
493         if (div < MIN_LPD)
494                 div = MIN_LPD;
495         if (div > MAX_LPD)
496                 div = MAX_LPD;
497     
498         /* Save of the current value of the SSIDIV so we don't
499            overwrite the value*/
500         temp = (MCF_CCM_CDR & MCF_CCM_CDR_SSIDIV(0xF));
501       
502         /* Apply the divider to the system clock */
503         MCF_CCM_CDR = ( 0
504                 | MCF_CCM_CDR_LPDIV(div)
505                 | MCF_CCM_CDR_SSIDIV(temp));
506     
507         MCF_CCM_MISCCR |= MCF_CCM_MISCCR_LIMP;
508     
509         return (FREF/(3*(1 << div)));
510 }
511
512 int clock_exit_limp(void)
513 {
514         int fout;
515         
516         /* Exit LIMP mode */
517         MCF_CCM_MISCCR = (MCF_CCM_MISCCR & ~ MCF_CCM_MISCCR_LIMP);
518
519         /* Wait for PLL to lock */
520         while (!(MCF_CCM_MISCCR & MCF_CCM_MISCCR_PLL_LOCK))
521                 ;
522         
523         fout = get_sys_clock();
524
525         return fout;
526 }
527
528 int get_sys_clock(void)
529 {
530         int divider;
531         
532         /* Test to see if device is in LIMP mode */
533         if (MCF_CCM_MISCCR & MCF_CCM_MISCCR_LIMP) {
534                 divider = MCF_CCM_CDR & MCF_CCM_CDR_LPDIV(0xF);
535                 return (FREF/(2 << divider));
536         }
537         else
538                 return ((FREF * MCF_PLL_PFDR) / (BUSDIV * 4));
539 }