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