]> git.kernelconcepts.de Git - karo-tx-uboot.git/blob - board/LEOX/elpt860/flash.c
* Patch by Josef Wagner, 12 Mar 2003:
[karo-tx-uboot.git] / board / LEOX / elpt860 / flash.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 variable:
35 ** ------
36 **              flash_info_t    flash_info[CFG_MAX_FLASH_BANKS]
37 ** 'flash_info_t' structure is defined into 'include/flash.h'
38 ** and defined as extern into 'common/cmd_flash.c'
39 **
40 ** Note 2: In this file, you have to provide the following functions:
41 ** ------
42 **              unsigned long   flash_init(void)
43 ** called from 'board_init_r()' into 'common/board.c'
44 **
45 **              void            flash_print_info(flash_info_t *info)
46 ** called from 'do_flinfo()' into 'common/cmd_flash.c'
47 **
48 **              int             flash_erase(flash_info_t *info,
49 **                                          int           s_first,
50 **                                          int           s_last)
51 ** called from 'do_flerase()' & 'flash_sect_erase()' into 'common/cmd_flash.c'
52 **
53 **              int             write_buff (flash_info_t *info,
54 **                                          uchar        *src,
55 **                                          ulong         addr,
56 **                                          ulong         cnt)
57 ** called from 'flash_write()' into 'common/cmd_flash.c'
58 */
59
60 #include <common.h>
61 #include <mpc8xx.h>
62
63
64 #ifndef CFG_ENV_ADDR
65 #  define CFG_ENV_ADDR  (CFG_FLASH_BASE + CFG_ENV_OFFSET)
66 #endif
67
68 flash_info_t    flash_info[CFG_MAX_FLASH_BANKS]; /* info for FLASH chips */
69
70 /*-----------------------------------------------------------------------
71  * Internal Functions
72  */
73 static void   flash_get_offsets (ulong base, flash_info_t *info);
74 static ulong  flash_get_size (volatile unsigned char *addr, flash_info_t *info);
75
76 static int write_word (flash_info_t *info, ulong dest, ulong data);
77 static int write_byte (flash_info_t *info, ulong dest, uchar data);
78
79 /*-----------------------------------------------------------------------
80  */
81
82 unsigned long 
83 flash_init (void)
84 {
85   volatile immap_t     *immap  = (immap_t *)CFG_IMMR;
86   volatile memctl8xx_t *memctl = &immap->im_memctl;
87   unsigned long         size_b0;
88   int i;
89   
90   /* Init: no FLASHes known */
91   for (i=0; i<CFG_MAX_FLASH_BANKS; ++i) 
92     {
93       flash_info[i].flash_id = FLASH_UNKNOWN;
94     }
95   
96   /* Static FLASH Bank configuration here - FIXME XXX */
97   
98   size_b0 = flash_get_size ((volatile unsigned char *)FLASH_BASE0_PRELIM, 
99                             &flash_info[0]);
100   
101   if ( flash_info[0].flash_id == FLASH_UNKNOWN ) 
102     {
103       printf ("## Unknown FLASH on Bank 0 - Size = 0x%08lx = %ld MB\n",
104               size_b0, size_b0<<20);
105     }
106   
107   /* Remap FLASH according to real size */
108   memctl->memc_or0 = CFG_OR_TIMING_FLASH | (-size_b0 & OR_AM_MSK);
109   memctl->memc_br0 = (CFG_FLASH_BASE & BR_BA_MSK) | BR_MS_GPCM | BR_PS_8 | BR_V;
110   
111   /* Re-do sizing to get full correct info */
112   size_b0 = flash_get_size ((volatile unsigned char *)CFG_FLASH_BASE, 
113                             &flash_info[0]);
114   
115   flash_get_offsets (CFG_FLASH_BASE, &flash_info[0]);
116   
117 #if CFG_MONITOR_BASE >= CFG_FLASH_BASE
118   /* monitor protection ON by default */
119   flash_protect (FLAG_PROTECT_SET,
120                  CFG_MONITOR_BASE,
121                  CFG_MONITOR_BASE + CFG_MONITOR_LEN-1,
122                  &flash_info[0]);
123 #endif
124   
125 #ifdef  CFG_ENV_IS_IN_FLASH
126   /* ENV protection ON by default */
127   flash_protect(FLAG_PROTECT_SET,
128                 CFG_ENV_ADDR,
129                 CFG_ENV_ADDR + CFG_ENV_SIZE-1,
130                 &flash_info[0]);
131 #endif
132
133   flash_info[0].size = size_b0;
134   
135   return (size_b0);
136 }
137
138 /*-----------------------------------------------------------------------
139  */
140 static void 
141 flash_get_offsets (ulong          base, 
142                    flash_info_t  *info)
143 {
144   int i;
145
146 #define SECTOR_64KB    0x00010000
147
148   /* set up sector start adress table */
149   for (i = 0; i < info->sector_count; i++) 
150     {
151       info->start[i] = base + (i * SECTOR_64KB);
152     }
153 }
154
155 /*-----------------------------------------------------------------------
156  */
157 void 
158 flash_print_info (flash_info_t *info)
159 {
160   int i;
161   
162   if ( info->flash_id == FLASH_UNKNOWN ) 
163     {
164       printf ("missing or unknown FLASH type\n");
165       return;
166     }
167
168   switch ( info->flash_id & FLASH_VENDMASK ) 
169     {
170     case FLASH_MAN_AMD: printf ("AMD ");                break;
171     case FLASH_MAN_FUJ: printf ("FUJITSU ");            break;
172     case FLASH_MAN_STM: printf ("STM (Thomson) ");      break;
173     default:            printf ("Unknown Vendor ");     break;
174     }
175   
176   switch ( info->flash_id & FLASH_TYPEMASK ) 
177     {
178     case FLASH_AM040:   printf ("AM29F040   (4 Mbits)\n");
179       break;
180     default:            printf ("Unknown Chip Type\n");
181       break;
182     }
183   
184   printf ("  Size: %ld KB in %d Sectors\n", 
185           info->size >> 10, info->sector_count);
186   
187   printf ("  Sector Start Addresses:");
188   for (i=0; i<info->sector_count; ++i) 
189     {
190       if ((i % 5) == 0)
191         printf ("\n   ");
192       printf (" %08lX%s",
193               info->start[i],
194               info->protect[i] ? " (RO)" : "     "
195               );
196     }
197   printf ("\n");
198
199   return;
200 }
201
202 /*-----------------------------------------------------------------------
203  */
204
205
206 /*-----------------------------------------------------------------------
207  */
208
209 /*
210  * The following code cannot be run from FLASH!
211  */
212
213 static ulong 
214 flash_get_size (volatile unsigned char *addr, 
215                 flash_info_t           *info)
216 {
217   short i;
218   uchar value;
219   ulong base = (ulong)addr;
220
221   /* Write auto select command: read Manufacturer ID */
222   addr[0x0555] = 0xAA;
223   addr[0x02AA] = 0x55;
224   addr[0x0555] = 0x90;
225   
226   value = addr[0];
227
228   switch ( value ) 
229     {
230       /*    case AMD_MANUFACT: */
231     case 0x01:
232       info->flash_id = FLASH_MAN_AMD;
233       break;
234       /*    case FUJ_MANUFACT: */
235     case 0x04:
236       info->flash_id = FLASH_MAN_FUJ;
237       break;
238       /*    case STM_MANUFACT: */
239     case 0x20:
240       info->flash_id = FLASH_MAN_STM;
241       break;
242
243     default:
244       info->flash_id = FLASH_UNKNOWN;
245       info->sector_count = 0;
246       info->size = 0;
247       return (0);                       /* no or unknown flash  */
248     }
249   
250   value = addr[1];                      /* device ID            */
251   
252   switch ( value ) 
253     {
254     case STM_ID_F040B:
255     case AMD_ID_F040B:
256       info->flash_id += FLASH_AM040;    /* 4 Mbits = 512k * 8  */
257       info->sector_count = 8;
258       info->size = 0x00080000;
259       break;
260
261     default:
262       info->flash_id = FLASH_UNKNOWN;
263       return (0);                       /* => no or unknown flash */
264     }
265
266   /* set up sector start adress table */
267   for (i = 0; i < info->sector_count; i++) 
268     {
269       info->start[i] = base + (i * 0x00010000);
270     }
271   
272   /* check for protected sectors */
273   for (i = 0; i < info->sector_count; i++) 
274     {
275       /* read sector protection at sector address, (A7 .. A0) = 0x02 */
276       /* D0 = 1 if protected */
277       addr = (volatile unsigned char *)(info->start[i]);
278       info->protect[i] = addr[2] & 1;
279     }
280
281   /*
282    * Prevent writes to uninitialized FLASH.
283    */
284   if ( info->flash_id != FLASH_UNKNOWN ) 
285     {
286       addr = (volatile unsigned char *)info->start[0];
287       
288       *addr = 0xF0;     /* reset bank */
289     }
290   
291   return (info->size);
292 }
293
294
295 /*-----------------------------------------------------------------------
296  */
297
298 int
299 flash_erase (flash_info_t  *info, 
300              int            s_first, 
301              int            s_last)
302 {
303   volatile unsigned char *addr = (volatile unsigned char *)(info->start[0]);
304   int flag, prot, sect, l_sect;
305   ulong start, now, last;
306   
307   if ( (s_first < 0) || (s_first > s_last) ) 
308     {
309       if ( info->flash_id == FLASH_UNKNOWN ) 
310         {
311           printf ("- missing\n");
312         } 
313       else 
314         {
315           printf ("- no sectors to erase\n");
316         }
317       return ( 1 );
318     }
319
320   if ( (info->flash_id == FLASH_UNKNOWN) ||
321        (info->flash_id > FLASH_AMD_COMP) ) 
322     {
323       printf ("Can't erase unknown flash type %08lx - aborted\n",
324               info->flash_id);
325       return ( 1 );
326     }
327   
328   prot = 0;
329   for (sect=s_first; sect<=s_last; ++sect) 
330     {
331       if ( info->protect[sect] ) 
332         {
333           prot++;
334         }
335     }
336   
337   if ( prot ) 
338     {
339       printf ("- Warning: %d protected sectors will not be erased!\n", prot);
340     } 
341   else 
342     {
343       printf ("\n");
344     }
345   
346   l_sect = -1;
347   
348   /* Disable interrupts which might cause a timeout here */
349   flag = disable_interrupts();
350   
351   addr[0x0555] = 0xAA;
352   addr[0x02AA] = 0x55;
353   addr[0x0555] = 0x80;
354   addr[0x0555] = 0xAA;
355   addr[0x02AA] = 0x55;
356   
357   /* Start erase on unprotected sectors */
358   for (sect = s_first; sect<=s_last; sect++) 
359     {
360       if (info->protect[sect] == 0)    /* not protected */
361         {
362           addr = (volatile unsigned char *)(info->start[sect]);
363           addr[0] = 0x30;
364           l_sect = sect;
365         }
366     }
367   
368   /* re-enable interrupts if necessary */
369   if ( flag )
370     enable_interrupts();
371   
372   /* wait at least 80us - let's wait 1 ms */
373   udelay (1000);
374   
375   /*
376    * We wait for the last triggered sector
377    */
378   if ( l_sect < 0 )
379     goto DONE;
380   
381   start = get_timer (0);
382   last  = start;
383   addr = (volatile unsigned char *)(info->start[l_sect]);
384   while ( (addr[0] & 0x80) != 0x80 ) 
385     {
386       if ( (now = get_timer(start)) > CFG_FLASH_ERASE_TOUT ) 
387         {
388           printf ("Timeout\n");
389           return ( 1 );
390         }
391       /* show that we're waiting */
392       if ( (now - last) > 1000 )     /* every second */
393         {
394           putc ('.');
395           last = now;
396         }
397     }
398   
399 DONE:
400   /* reset to read mode */
401   addr = (volatile unsigned char *)info->start[0];
402   addr[0] = 0xF0;       /* reset bank */
403   
404   printf (" done\n");
405   
406   return ( 0 );
407 }
408
409 /*-----------------------------------------------------------------------
410  * Copy memory to flash, returns:
411  * 0 - OK
412  * 1 - write timeout
413  * 2 - Flash not erased
414  */
415
416 int 
417 write_buff (flash_info_t  *info, 
418             uchar         *src, 
419             ulong          addr, 
420             ulong          cnt)
421 {
422   ulong cp, wp, data;
423   uchar bdata;
424   int i, l, rc;
425
426   if ( (info->flash_id & FLASH_TYPEMASK) == FLASH_AM040 )
427     {
428       /* Width of the data bus: 8 bits */
429
430       wp = addr;
431       
432       while ( cnt )
433         {
434           bdata = *src++;
435           
436           if ( (rc = write_byte(info, wp, bdata)) != 0 )
437             {
438               return (rc);
439             }
440           
441           ++wp;
442           --cnt;
443         }
444
445       return ( 0 );
446     }
447   else
448     {
449       /* Width of the data bus: 32 bits */
450
451       wp = (addr & ~3); /* get lower word aligned address */
452       
453       /*
454        * handle unaligned start bytes
455        */
456       if ( (l = addr - wp) != 0 ) 
457         {
458           data = 0;
459           for (i=0, cp=wp; i<l; ++i, ++cp) 
460             {
461               data = (data << 8) | (*(uchar *)cp);
462             }
463           for (; i<4 && cnt>0; ++i) 
464             {
465               data = (data << 8) | *src++;
466               --cnt;
467               ++cp;
468             }
469           for (; cnt==0 && i<4; ++i, ++cp) 
470             {
471               data = (data << 8) | (*(uchar *)cp);
472             }
473           
474           if ( (rc = write_word(info, wp, data)) != 0 ) 
475             {
476               return (rc);
477             }
478           wp += 4;
479         }
480       
481       /*
482        * handle word aligned part
483        */
484       while ( cnt >= 4 ) 
485         {
486           data = 0;
487           for (i=0; i<4; ++i) 
488             {
489               data = (data << 8) | *src++;
490             }
491           if ( (rc = write_word(info, wp, data)) != 0 ) 
492             {
493               return (rc);
494             }
495           wp  += 4;
496           cnt -= 4;
497         }
498       
499       if ( cnt == 0 ) 
500         {
501           return (0);
502         }
503       
504       /*
505        * handle unaligned tail bytes
506        */
507       data = 0;
508       for (i=0, cp=wp; i<4 && cnt>0; ++i, ++cp) 
509         {
510           data = (data << 8) | *src++;
511           --cnt;
512         }
513       for (; i<4; ++i, ++cp) 
514         {
515           data = (data << 8) | (*(uchar *)cp);
516         }
517       
518       return (write_word(info, wp, data));
519     }
520 }
521
522 /*-----------------------------------------------------------------------
523  * Write a word to Flash, returns:
524  * 0 - OK
525  * 1 - write timeout
526  * 2 - Flash not erased
527  */
528 static int 
529 write_word (flash_info_t  *info, 
530             ulong          dest, 
531             ulong          data)
532 {
533   vu_long *addr = (vu_long*)(info->start[0]);
534   ulong start;
535   int flag;
536   
537   /* Check if Flash is (sufficiently) erased */
538   if ( (*((vu_long *)dest) & data) != data ) 
539     {
540       return (2);
541     }
542   /* Disable interrupts which might cause a timeout here */
543   flag = disable_interrupts();
544   
545   addr[0x0555] = 0x00AA00AA;
546   addr[0x02AA] = 0x00550055;
547   addr[0x0555] = 0x00A000A0;
548   
549   *((vu_long *)dest) = data;
550   
551   /* re-enable interrupts if necessary */
552   if ( flag )
553     enable_interrupts();
554
555   /* data polling for D7 */
556   start = get_timer (0);
557   while ( (*((vu_long *)dest) & 0x00800080) != (data & 0x00800080) ) 
558     {
559       if ( get_timer(start) > CFG_FLASH_WRITE_TOUT ) 
560         {
561           return (1);
562         }
563     }
564
565   return (0);
566 }
567
568 /*-----------------------------------------------------------------------
569  * Write a byte to Flash, returns:
570  * 0 - OK
571  * 1 - write timeout
572  * 2 - Flash not erased
573  */
574 static int 
575 write_byte (flash_info_t  *info, 
576             ulong          dest, 
577             uchar          data)
578 {
579   volatile unsigned char *addr = (volatile unsigned char *)(info->start[0]);
580   ulong  start;
581   int    flag;
582   
583   /* Check if Flash is (sufficiently) erased */
584   if ( (*((volatile unsigned char *)dest) & data) != data ) 
585     {
586       return (2);
587     }
588   /* Disable interrupts which might cause a timeout here */
589   flag = disable_interrupts();
590   
591   addr[0x0555] = 0xAA;
592   addr[0x02AA] = 0x55;
593   addr[0x0555] = 0xA0;
594   
595   *((volatile unsigned char *)dest) = data;
596   
597   /* re-enable interrupts if necessary */
598   if ( flag )
599     enable_interrupts();
600
601   /* data polling for D7 */
602   start = get_timer (0);
603   while ( (*((volatile unsigned char *)dest) & 0x80) != (data & 0x80) ) 
604     {
605       if ( get_timer(start) > CFG_FLASH_WRITE_TOUT ) 
606         {
607           return (1);
608         }
609     }
610
611   return (0);
612 }
613
614 /*-----------------------------------------------------------------------
615  */