]> git.kernelconcepts.de Git - karo-tx-uboot.git/blob - board/LEOX/elpt860/elpt860.c
* Patch by Josef Wagner, 12 Mar 2003:
[karo-tx-uboot.git] / board / LEOX / elpt860 / elpt860.c
1 /*
2 **=====================================================================
3 **
4 ** Copyright (C) 2000, 2001, 2002, 2003
5 ** The LEOX team <team@leox.org>, http://www.leox.org
6 **
7 ** LEOX.org is about the development of free hardware and software resources
8 **   for system on chip.
9 **
10 ** Description: U-Boot port on the LEOX's ELPT860 CPU board
11 ** ~~~~~~~~~~~
12 **
13 **=====================================================================
14 **
15 ** This program is free software; you can redistribute it and/or
16 ** modify it under the terms of the GNU General Public License as
17 ** published by the Free Software Foundation; either version 2 of
18 ** the License, or (at your option) any later version.
19 **
20 ** This program is distributed in the hope that it will be useful,
21 ** but WITHOUT ANY WARRANTY; without even the implied warranty of
22 ** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
23 ** GNU General Public License for more details.
24 **
25 ** You should have received a copy of the GNU General Public License
26 ** along with this program; if not, write to the Free Software
27 ** Foundation, Inc., 59 Temple Place, Suite 330, Boston,
28 ** MA 02111-1307 USA
29 **
30 **=====================================================================
31 */
32
33 /*
34 ** Note 1: In this file, you have to provide the following functions:
35 ** ------
36 **              int             board_pre_init(void)
37 **              int             checkboard(void)
38 **              long int        initdram(int board_type)
39 ** called from 'board_init_f()' into 'common/board.c'
40 **
41 **              void            reset_phy(void)
42 ** called from 'board_init_r()' into 'common/board.c'
43 */
44
45 #include <common.h>
46 #include <mpc8xx.h>
47
48 /* ------------------------------------------------------------------------- */
49
50 static long int dram_size (long int, long int *, long int);
51
52 /* ------------------------------------------------------------------------- */
53
54 #define _NOT_USED_      0xFFFFFFFF
55
56 const uint init_sdram_table[] =
57 {
58   /*
59    * Single Read. (Offset 0 in UPMA RAM)
60    */
61   0x0FFCCC04, 0xFFFFFC04, 0x0FFC3C04, 0xFFFFFC04,
62   0xFFFFFC04, /* last */
63   /*
64    * SDRAM Initialization (offset 5 in UPMA RAM)
65    *
66    * This is no UPM entry point. The following definition uses
67    * the remaining space to establish an initialization
68    * sequence, which is executed by a RUN command.
69    *
70    */
71   0xFFFFFC04, 0xFFFFFC04, 0x0FFC3C04,  /* last */
72   /*
73    * Burst Read. (Offset 8 in UPMA RAM)
74    */
75   0xFFFFFC04, 0xFFFFFC04, 0xFFFFFC04, 0xFFFFFC04,
76   0x0FFC3C04, 0xFFFFFC04, 0xFFFFFC04, 0xFFFFFC04,
77   0xFFFFFC04, 0x0FFC3C04, 0xFFFFFC04, 0xFFFFFC04,
78   0xFFFFFC04, 0xFFFFFC04, 0x0FFC3C04, 0xFFFFFC04, /* last */
79   /*
80    * Single Write. (Offset 18 in UPMA RAM)
81    */
82   0xFFFFFC04, 0xFFFFFC04, 0xFFFFFC04, 0x0FFC3C04,
83   0xFFFFFC04, 0xFFFFFC04, 0x0FFFFC04, 0xFFFFFC04, /* last */
84   /*
85    * Burst Write. (Offset 20 in UPMA RAM)
86    */
87   0x0FFC3C04, 0xFFFFFC04, 0xFFFFFC04, 0xFFFFFC04,
88   0xFFFFFC04, 0x0FFC3C04, 0xFFFFFC04, 0xFFFFFC04,
89   0xFFFFFC04, 0xFFFFFC04, 0xFFFFFC34, 0x0FAC0C34,
90   0xFFFFFC05, 0xFFFFFC04, 0x0FFCFC04, 0xFFFFFC05, /* last */
91 };
92
93 const uint sdram_table[] =
94 {
95   /*
96    * Single Read. (Offset 0 in UPMA RAM)
97    */
98   0x0F0FFC24, 0x0F0CFC04, 0xFF0FFC04, 0x00AF3C04, 
99   0xFF0FFC00, /* last */
100   /*
101    * SDRAM Initialization (offset 5 in UPMA RAM)
102    *
103    * This is no UPM entry point. The following definition uses
104    * the remaining space to establish an initialization
105    * sequence, which is executed by a RUN command.
106    *
107    */
108   0x0FFCCC04, 0xFFAFFC05, 0xFFAFFC05, /* last */
109   /*
110    * Burst Read. (Offset 8 in UPMA RAM)
111    */
112   0x0F0FFC24, 0x0F0CFC04, 0xFF0FFC04, 0x00AF3C04, 
113   0xF00FFC00, 0xF00FFC00, 0xF00FFC00, 0xFF0FFC00,
114   0x0FFCCC04, 0xFFAFFC05, 0xFFAFFC04, 0xFFAFFC04, 
115   0xFFAFFC04, 0xFFAFFC04, 0xFFAFFC04, 0xFFAFFC04, /* last */
116   /*
117    * Single Write. (Offset 18 in UPMA RAM)
118    */
119   0x0F0FFC24, 0x0F0CFC04, 0xFF0FFC04, 0x00AF0C00, 
120   0xFF0FFC04, 0x0FFCCC04, 0xFFAFFC05, /* last */
121   _NOT_USED_, 
122   /*
123    * Burst Write. (Offset 20 in UPMA RAM)
124    */
125   0x0F0FFC24, 0x0F0CFC04, 0xFF0FFC00, 0x00AF0C00, 
126   0xF00FFC00, 0xF00FFC00, 0xF00FFC04, 0x0FFCCC04, 
127   0xFFAFFC04, 0xFFAFFC05, 0xFFAFFC04, 0xFFAFFC04, 
128   0xFFAFFC04, 0xFFAFFC04, 0xFFAFFC04, 0xFFAFFC04, /* last */
129   /*
130    * Refresh  (Offset 30 in UPMA RAM)
131    */
132   0x0FFC3C04, 0xFFFFFC04, 0xFFFFFC04, 0xFFFFFC04, 
133   0xFFFFFC05, 0xFFFFFC04, 0xFFFFFC05, _NOT_USED_, 
134   0xFFAFFC04, 0xFFAFFC04, 0xFFAFFC04, 0xFFAFFC04, /* last */
135   /*
136    * Exception. (Offset 3c in UPMA RAM)
137    */
138   0x0FFFFC34, 0x0FAC0C34, 0xFFFFFC05, 0xFFAFFC04, /* last */
139 };
140
141 /* ------------------------------------------------------------------------- */
142
143 #define CFG_PC4    0x0800
144
145 #define CFG_DS1    CFG_PC4
146
147 /*
148  * Very early board init code (fpga boot, etc.)
149  */
150 int
151 board_pre_init (void)
152 {
153   volatile immap_t *immr = (immap_t *) CFG_IMMR;
154
155   /* 
156    * Light up the red led on ELPT860 pcb (DS1) (PCDAT) 
157    */
158   immr->im_ioport.iop_pcdat &= ~CFG_DS1;   /* PCDAT (DS1 = 0)                */
159   immr->im_ioport.iop_pcpar &= ~CFG_DS1;   /* PCPAR (0=general purpose I/O)  */
160   immr->im_ioport.iop_pcdir |=  CFG_DS1;   /* PCDIR (I/O: 0=input, 1=output) */
161
162   return ( 0 );    /* success */
163 }
164
165 /*
166  * Check Board Identity:
167  *
168  * Test ELPT860 ID string
169  *
170  * Return 1 if no second DRAM bank, otherwise returns 0
171  */
172
173 int 
174 checkboard (void)
175 {
176     unsigned char *s = getenv("serial#");
177
178     if ( !s || strncmp(s, "ELPT860", 7) )
179       printf ("### No HW ID - assuming ELPT860\n");
180     
181     return ( 0 );    /* success */
182 }
183
184 /* ------------------------------------------------------------------------- */
185
186 long int 
187 initdram (int board_type)
188 {
189     volatile immap_t     *immap  = (immap_t *)CFG_IMMR;
190     volatile memctl8xx_t *memctl = &immap->im_memctl;
191     long int              size8, size9;
192     long int              size_b0 = 0;
193
194     /*
195      * This sequence initializes SDRAM chips on ELPT860 board
196      */
197     upmconfig(UPMA, (uint *)init_sdram_table, 
198               sizeof(init_sdram_table)/sizeof(uint));
199
200     memctl->memc_mptpr = 0x0200;
201     memctl->memc_mamr  = 0x18002111;
202
203     memctl->memc_mar   = 0x00000088;
204     memctl->memc_mcr   = 0x80002000;    /* CS1: SDRAM bank 0 */
205
206     upmconfig(UPMA, (uint *)sdram_table, 
207               sizeof(sdram_table)/sizeof(uint));
208
209     /*
210      * Preliminary prescaler for refresh (depends on number of
211      * banks): This value is selected for four cycles every 62.4 us
212      * with two SDRAM banks or four cycles every 31.2 us with one
213      * bank. It will be adjusted after memory sizing.
214      */
215     memctl->memc_mptpr = CFG_MPTPR_2BK_8K;
216
217     /*
218      * The following value is used as an address (i.e. opcode) for
219      * the LOAD MODE REGISTER COMMAND during SDRAM initialisation. If
220      * the port size is 32bit the SDRAM does NOT "see" the lower two
221      * address lines, i.e. mar=0x00000088 -> opcode=0x00000022 for
222      * MICRON SDRAMs:
223      * ->    0 00 010 0 010
224      *       |  |   | |   +- Burst Length = 4
225      *       |  |   | +----- Burst Type   = Sequential
226      *       |  |   +------- CAS Latency  = 2
227      *       |  +----------- Operating Mode = Standard
228      *       +-------------- Write Burst Mode = Programmed Burst Length
229      */
230     memctl->memc_mar   = 0x00000088;
231
232     /*
233      * Map controller banks 2 and 3 to the SDRAM banks 2 and 3 at
234      * preliminary addresses - these have to be modified after the
235      * SDRAM size has been determined.
236      */
237     memctl->memc_or1   = CFG_OR1_PRELIM;
238     memctl->memc_br1   = CFG_BR1_PRELIM;
239
240     memctl->memc_mamr  = CFG_MAMR_8COL & (~(MAMR_PTAE)); /* no refresh yet */
241
242     udelay (200);
243
244     /* perform SDRAM initializsation sequence */
245
246     memctl->memc_mcr   = 0x80002105;    /* CS1: SDRAM bank 0 */
247     udelay (1);
248     memctl->memc_mcr   = 0x80002230;    /* CS1: SDRAM bank 0 - execute twice */
249     udelay (1);
250
251     memctl->memc_mamr |= MAMR_PTAE;     /* enable refresh */
252
253     udelay (1000);
254
255     /*
256      * Check Bank 0 Memory Size for re-configuration
257      *
258      * try 8 column mode
259      */
260     size8 = dram_size (CFG_MAMR_8COL, 
261                        (ulong *) SDRAM_BASE1_PRELIM, 
262                        SDRAM_MAX_SIZE);
263
264     udelay (1000);
265
266     /*
267      * try 9 column mode
268      */
269     size9 = dram_size (CFG_MAMR_9COL, 
270                        (ulong *) SDRAM_BASE1_PRELIM, 
271                        SDRAM_MAX_SIZE);
272
273     if ( size8 < size9 )    /* leave configuration at 9 columns */
274       {
275         size_b0 = size9;
276         /* debug ("SDRAM Bank 0 in 9 column mode: %ld MB\n", size >> 20); */
277       } 
278     else                  /* back to 8 columns                  */
279       {
280         size_b0 = size8;
281         memctl->memc_mamr = CFG_MAMR_8COL;
282         udelay (500);
283         /* debug ("SDRAM Bank 0 in 8 column mode: %ld MB\n", size >> 20); */
284       }
285     
286     udelay (1000);
287
288     /*
289      * Adjust refresh rate depending on SDRAM type, both banks
290      * For types > 128 MBit leave it at the current (fast) rate
291      */
292     if ( size_b0 < 0x02000000 ) 
293       {
294         /* reduce to 15.6 us (62.4 us / quad) */
295         memctl->memc_mptpr = CFG_MPTPR_2BK_4K;
296         udelay (1000);
297       }
298
299     /*
300      * Final mapping: map bigger bank first
301      */
302     memctl->memc_or1 = ((-size_b0) & 0xFFFF0000) | CFG_OR_TIMING_SDRAM;
303     memctl->memc_br1 = (CFG_SDRAM_BASE & BR_BA_MSK) | BR_MS_UPMA | BR_V;
304
305     {
306       unsigned long reg;
307       
308       /* adjust refresh rate depending on SDRAM type, one bank */
309       reg = memctl->memc_mptpr;
310       reg >>= 1;        /* reduce to CFG_MPTPR_1BK_8K / _4K */
311       memctl->memc_mptpr = reg;
312     }
313
314     udelay(10000);
315     
316     return (size_b0);
317 }
318
319 /* ------------------------------------------------------------------------- */
320
321 /*
322  * Check memory range for valid RAM. A simple memory test determines
323  * the actually available RAM size between addresses `base' and
324  * `base + maxsize'. Some (not all) hardware errors are detected:
325  * - short between address lines
326  * - short between data lines
327  */
328
329 static long int 
330 dram_size (long int   mamr_value, 
331            long int  *base, 
332            long int   maxsize)
333 {
334   volatile immap_t     *immap  = (immap_t *)CFG_IMMR;
335   volatile memctl8xx_t *memctl = &immap->im_memctl;
336   volatile long int    *addr;
337   ulong                 cnt, val;
338   ulong                 save[32];    /* to make test non-destructive */
339   unsigned char         i = 0;
340   
341   memctl->memc_mamr = mamr_value;
342   
343   for (cnt = maxsize/sizeof(long); cnt > 0; cnt >>= 1) 
344     {
345       addr = base + cnt;    /* pointer arith! */
346       
347       save[i++] = *addr;
348       *addr     = ~cnt;
349     }
350   
351   /* write 0 to base address */
352   addr    = base;
353   save[i] = *addr;
354   *addr   = 0;
355   
356   /* check at base address */
357   if ( (val = *addr) != 0 ) 
358     {
359       *addr = save[i];
360
361       return (0);
362     }
363   
364   for (cnt = 1; cnt <= maxsize/sizeof(long); cnt <<= 1) 
365     {
366       addr = base + cnt;    /* pointer arith! */
367       
368       val   = *addr;
369       *addr = save[--i];
370       
371       if ( val != (~cnt) ) 
372         {
373           return (cnt * sizeof(long));
374         }
375     }
376
377   return (maxsize);
378 }
379
380 /* ------------------------------------------------------------------------- */
381
382 #define CFG_PA1     0x4000
383 #define CFG_PA2     0x2000
384
385 #define CFG_LBKs    (CFG_PA2 | CFG_PA1)
386
387 void
388 reset_phy (void)
389 {
390   volatile immap_t *immr = (immap_t *) CFG_IMMR;
391   
392   /*
393    * Ensure LBK LXT901 ethernet 1 & 2 = 0 ... for normal loopback in effect
394    *                                          and no AUI loopback
395    */
396   immr->im_ioport.iop_padat &= ~CFG_LBKs;  /* PADAT (LBK eth 1&2 = 0)        */
397   immr->im_ioport.iop_papar &= ~CFG_LBKs;  /* PAPAR (0=general purpose I/O)  */
398   immr->im_ioport.iop_padir |=  CFG_LBKs;  /* PADIR (I/O: 0=input, 1=output) */
399 }