]> git.kernelconcepts.de Git - karo-tx-uboot.git/blob - board/siemens/IAD210/flash.c
imported Ka-Ro specific additions to U-Boot 2009.08 for TX28
[karo-tx-uboot.git] / board / siemens / IAD210 / flash.c
1 /*
2  * (C) Copyright 2000, 2001, 2002
3  * Wolfgang Denk, DENX Software Engineering, wd@denx.de.
4  *
5  * See file CREDITS for list of people who contributed to this
6  * project.
7  *
8  * This program is free software; you can redistribute it and/or
9  * modify it under the terms of the GNU General Public License as
10  * published by the Free Software Foundation; either version 2 of
11  * the License, or (at your option) any later version.
12  *
13  * This program is distributed in the hope that it will be useful,
14  * but WITHOUT ANY WARRANTY; without even the implied warranty of
15  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
16  * GNU General Public License for more details.
17  *
18  * You should have received a copy of the GNU General Public License
19  * along with this program; if not, write to the Free Software
20  * Foundation, Inc., 59 Temple Place, Suite 330, Boston,
21  * MA 02111-1307 USA
22  */
23
24 #include <common.h>
25 #include <mpc8xx.h>
26
27 flash_info_t    flash_info[CONFIG_SYS_MAX_FLASH_BANKS]; /* info for FLASH chips */
28
29 /*-----------------------------------------------------------------------
30  * Functions
31  */
32 static ulong flash_get_size (vu_long *addr, flash_info_t *info);
33 static int write_word (flash_info_t *info, ulong dest, ulong data);
34 static void flash_get_offsets (ulong base, flash_info_t *info);
35
36 /*-----------------------------------------------------------------------
37  */
38
39 unsigned long flash_init (void)
40 {
41   volatile immap_t     *immap  = (immap_t *)CONFIG_SYS_IMMR;
42   volatile memctl8xx_t *memctl = &immap->im_memctl;
43   unsigned long size;
44   int i;
45
46   /* Init: no FLASHes known */
47   for (i=0; i<CONFIG_SYS_MAX_FLASH_BANKS; ++i) {
48     flash_info[i].flash_id = FLASH_UNKNOWN;
49   }
50
51   /* Static FLASH Bank configuration here - FIXME XXX */
52
53   size = flash_get_size((vu_long *)FLASH_BASE0_PRELIM, &flash_info[0]);
54
55   if (flash_info[0].flash_id == FLASH_UNKNOWN) {
56     printf ("## Unknown FLASH on Bank 0 - Size = 0x%08lx = %ld MB\n",
57                         size, size<<20);
58   }
59
60
61   /* Remap FLASH according to real size */
62   memctl->memc_or0 = CONFIG_SYS_OR_TIMING_FLASH | (-size & 0xFFFF8000);
63   memctl->memc_br0 = (CONFIG_SYS_FLASH_BASE & BR_BA_MSK) | BR_MS_GPCM | BR_V;
64
65   /* Re-do sizing to get full correct info */
66   size = flash_get_size((vu_long *)CONFIG_SYS_FLASH_BASE, &flash_info[0]);
67
68   flash_get_offsets (CONFIG_SYS_FLASH_BASE, &flash_info[0]);
69
70   flash_info[0].size = size;
71
72   return (size);
73 }
74
75 /*-----------------------------------------------------------------------
76  */
77 static void flash_get_offsets (ulong base, flash_info_t *info)
78 {
79   int i;
80
81   /* set up sector start address table */
82   if (info->flash_id & FLASH_BTYPE) {
83     /* set sector offsets for bottom boot block type    */
84     info->start[0] = base + 0x00000000;
85     info->start[1] = base + 0x00008000;
86     info->start[2] = base + 0x0000C000;
87     info->start[3] = base + 0x00010000;
88     for (i = 4; i < info->sector_count; i++) {
89       info->start[i] = base + (i * 0x00020000) - 0x00060000;
90     }
91   } else {
92     /* set sector offsets for top boot block type               */
93     i = info->sector_count - 1;
94     info->start[i--] = base + info->size - 0x00008000;
95     info->start[i--] = base + info->size - 0x0000C000;
96     info->start[i--] = base + info->size - 0x00010000;
97     for (; i >= 0; i--) {
98       info->start[i] = base + i * 0x00020000;
99     }
100   }
101
102 }
103
104 /*-----------------------------------------------------------------------
105  */
106 void flash_print_info  (flash_info_t *info)
107 {
108   int i;
109
110   if (info->flash_id == FLASH_UNKNOWN) {
111     printf ("missing or unknown FLASH type\n");
112     return;
113   }
114
115   switch (info->flash_id & FLASH_VENDMASK) {
116   case FLASH_MAN_AMD:   printf ("AMD ");                break;
117   case FLASH_MAN_FUJ:   printf ("FUJITSU ");            break;
118   default:              printf ("Unknown Vendor ");     break;
119   }
120
121   switch (info->flash_id & FLASH_TYPEMASK) {
122   case FLASH_AM400B:    printf ("AM29LV400B (4 Mbit, bottom boot sect)\n");
123     break;
124   case FLASH_AM400T:    printf ("AM29LV400T (4 Mbit, top boot sector)\n");
125     break;
126   case FLASH_AM800B:    printf ("AM29LV800B (8 Mbit, bottom boot sect)\n");
127     break;
128   case FLASH_AM800T:    printf ("AM29LV800T (8 Mbit, top boot sector)\n");
129     break;
130   case FLASH_AM160B:    printf ("AM29LV160B (16 Mbit, bottom boot sect)\n");
131     break;
132   case FLASH_AM160T:    printf ("AM29LV160T (16 Mbit, top boot sector)\n");
133     break;
134   case FLASH_AM320B:    printf ("AM29LV320B (32 Mbit, bottom boot sect)\n");
135     break;
136   case FLASH_AM320T:    printf ("AM29LV320T (32 Mbit, top boot sector)\n");
137     break;
138   default:              printf ("Unknown Chip Type\n");
139     break;
140   }
141
142   printf ("  Size: %ld MB in %d Sectors\n",
143           info->size >> 20, info->sector_count);
144
145   printf ("  Sector Start Addresses:");
146   for (i=0; i<info->sector_count; ++i) {
147     if ((i % 5) == 0)
148       printf ("\n   ");
149     printf (" %08lX%s",
150                         info->start[i],
151                         info->protect[i] ? " (RO)" : "     "
152             );
153   }
154   printf ("\n");
155 }
156
157 /*-----------------------------------------------------------------------
158  */
159
160
161 /*-----------------------------------------------------------------------
162  */
163
164 /*
165  * The following code cannot be run from FLASH!
166  */
167
168 static ulong flash_get_size (vu_long *addr, flash_info_t *info)
169 {
170   short i;
171   ulong value;
172   ulong base = (ulong)addr;
173
174
175   /* Write auto select command: read Manufacturer ID */
176   addr[0x0555] = 0x00AA00AA;
177   addr[0x02AA] = 0x00550055;
178   addr[0x0555] = 0x00900090;
179
180   value = addr[0];
181
182   switch (value) {
183   case AMD_MANUFACT:
184     info->flash_id = FLASH_MAN_AMD;
185     break;
186   case FUJ_MANUFACT:
187     info->flash_id = FLASH_MAN_FUJ;
188     break;
189   default:
190     info->flash_id = FLASH_UNKNOWN;
191     info->sector_count = 0;
192     info->size = 0;
193     return (0);                 /* no or unknown flash  */
194   }
195
196   value = addr[1];                      /* device ID            */
197
198   switch (value) {
199   case AMD_ID_LV400T:
200     info->flash_id += FLASH_AM400T;
201     info->sector_count = 11;
202     info->size = 0x00100000;
203     break;                              /* => 1 MB              */
204
205   case AMD_ID_LV400B:
206     info->flash_id += FLASH_AM400B;
207     info->sector_count = 11;
208     info->size = 0x00100000;
209     break;                              /* => 1 MB              */
210
211   case AMD_ID_LV800T:
212     info->flash_id += FLASH_AM800T;
213     info->sector_count = 19;
214     info->size = 0x00200000;
215     break;                              /* => 2 MB              */
216
217   case AMD_ID_LV800B:
218     info->flash_id += FLASH_AM800B;
219     info->sector_count = 19;
220     info->size = 0x00200000;
221     break;                              /* => 2 MB              */
222
223   case AMD_ID_LV160T:
224     info->flash_id += FLASH_AM160T;
225     info->sector_count = 35;
226     info->size = 0x00400000;
227     break;                              /* => 4 MB              */
228
229   case AMD_ID_LV160B:
230     info->flash_id += FLASH_AM160B;
231     info->sector_count = 35;
232     info->size = 0x00400000;
233     break;                              /* => 4 MB              */
234 #if 0   /* enable when device IDs are available */
235   case AMD_ID_LV320T:
236     info->flash_id += FLASH_AM320T;
237     info->sector_count = 67;
238     info->size = 0x00800000;
239     break;                              /* => 8 MB              */
240
241   case AMD_ID_LV320B:
242     info->flash_id += FLASH_AM320B;
243     info->sector_count = 67;
244     info->size = 0x00800000;
245     break;                              /* => 8 MB              */
246 #endif
247   default:
248     info->flash_id = FLASH_UNKNOWN;
249     return (0);                 /* => no or unknown flash */
250
251   }
252
253   /* set up sector start address table */
254   if (info->flash_id & FLASH_BTYPE) {
255     /* set sector offsets for bottom boot block type    */
256     info->start[0] = base + 0x00000000;
257     info->start[1] = base + 0x00008000;
258     info->start[2] = base + 0x0000C000;
259     info->start[3] = base + 0x00010000;
260     for (i = 4; i < info->sector_count; i++) {
261       info->start[i] = base + (i * 0x00020000) - 0x00060000;
262     }
263   } else {
264     /* set sector offsets for top boot block type               */
265     i = info->sector_count - 1;
266     info->start[i--] = base + info->size - 0x00008000;
267     info->start[i--] = base + info->size - 0x0000C000;
268     info->start[i--] = base + info->size - 0x00010000;
269     for (; i >= 0; i--) {
270       info->start[i] = base + i * 0x00020000;
271     }
272   }
273
274   /* check for protected sectors */
275   for (i = 0; i < info->sector_count; i++) {
276     /* read sector protection at sector address, (A7 .. A0) = 0x02 */
277     /* D0 = 1 if protected */
278     addr = (volatile unsigned long *)(info->start[i]);
279     info->protect[i] = addr[2] & 1;
280   }
281
282   /*
283    * Prevent writes to uninitialized FLASH.
284    */
285   if (info->flash_id != FLASH_UNKNOWN) {
286     addr = (volatile unsigned long *)info->start[0];
287
288     *addr = 0x00F000F0; /* reset bank */
289   }
290
291   return (info->size);
292 }
293
294
295 /*-----------------------------------------------------------------------
296  */
297
298 int     flash_erase (flash_info_t *info, int s_first, int s_last)
299 {
300   vu_long *addr = (vu_long*)(info->start[0]);
301   int flag, prot, sect, l_sect;
302   ulong start, now, last;
303
304   if ((s_first < 0) || (s_first > s_last)) {
305     if (info->flash_id == FLASH_UNKNOWN) {
306       printf ("- missing\n");
307     } else {
308       printf ("- no sectors to erase\n");
309     }
310     return 1;
311   }
312
313   if ((info->flash_id == FLASH_UNKNOWN) ||
314       (info->flash_id > FLASH_AMD_COMP)) {
315     printf ("Can't erase unknown flash type %08lx - aborted\n",
316                         info->flash_id);
317     return 1;
318   }
319
320   prot = 0;
321   for (sect=s_first; sect<=s_last; ++sect) {
322     if (info->protect[sect]) {
323       prot++;
324     }
325   }
326
327   if (prot) {
328     printf ("- Warning: %d protected sectors will not be erased!\n",
329                         prot);
330   } else {
331     printf ("\n");
332   }
333
334   l_sect = -1;
335
336   /* Disable interrupts which might cause a timeout here */
337   flag = disable_interrupts();
338
339   addr[0x0555] = 0x00AA00AA;
340   addr[0x02AA] = 0x00550055;
341   addr[0x0555] = 0x00800080;
342   addr[0x0555] = 0x00AA00AA;
343   addr[0x02AA] = 0x00550055;
344
345   /* Start erase on unprotected sectors */
346   for (sect = s_first; sect<=s_last; sect++) {
347     if (info->protect[sect] == 0) {     /* not protected */
348       addr = (vu_long*)(info->start[sect]);
349       addr[0] = 0x00300030;
350       l_sect = sect;
351     }
352   }
353
354   /* re-enable interrupts if necessary */
355   if (flag)
356     enable_interrupts();
357
358   /* wait at least 80us - let's wait 1 ms */
359   udelay (1000);
360
361   /*
362    * We wait for the last triggered sector
363    */
364   if (l_sect < 0)
365     goto DONE;
366
367   start = get_timer (0);
368   last  = start;
369   addr = (vu_long*)(info->start[l_sect]);
370   while ((addr[0] & 0x00800080) != 0x00800080) {
371     if ((now = get_timer(start)) > CONFIG_SYS_FLASH_ERASE_TOUT) {
372       printf ("Timeout\n");
373       return 1;
374     }
375     /* show that we're waiting */
376     if ((now - last) > 1000) {  /* every second */
377       putc ('.');
378       last = now;
379     }
380   }
381
382  DONE:
383   /* reset to read mode */
384   addr = (volatile unsigned long *)info->start[0];
385   addr[0] = 0x00F000F0; /* reset bank */
386
387   printf (" done\n");
388   return 0;
389 }
390
391 /*-----------------------------------------------------------------------
392  * Copy memory to flash, returns:
393  * 0 - OK
394  * 1 - write timeout
395  * 2 - Flash not erased
396  */
397
398 int write_buff (flash_info_t *info, uchar *src, ulong addr, ulong cnt)
399 {
400   ulong cp, wp, data;
401   int i, l, rc;
402
403   wp = (addr & ~3);     /* get lower word aligned address */
404
405   /*
406    * handle unaligned start bytes
407    */
408   if ((l = addr - wp) != 0) {
409     data = 0;
410     for (i=0, cp=wp; i<l; ++i, ++cp) {
411       data = (data << 8) | (*(uchar *)cp);
412     }
413     for (; i<4 && cnt>0; ++i) {
414       data = (data << 8) | *src++;
415       --cnt;
416       ++cp;
417     }
418     for (; cnt==0 && i<4; ++i, ++cp) {
419       data = (data << 8) | (*(uchar *)cp);
420     }
421
422     if ((rc = write_word(info, wp, data)) != 0) {
423       return (rc);
424     }
425     wp += 4;
426   }
427
428   /*
429    * handle word aligned part
430    */
431   while (cnt >= 4) {
432     data = 0;
433     for (i=0; i<4; ++i) {
434       data = (data << 8) | *src++;
435     }
436     if ((rc = write_word(info, wp, data)) != 0) {
437       return (rc);
438     }
439     wp  += 4;
440     cnt -= 4;
441   }
442
443   if (cnt == 0) {
444     return (0);
445   }
446
447   /*
448    * handle unaligned tail bytes
449    */
450   data = 0;
451   for (i=0, cp=wp; i<4 && cnt>0; ++i, ++cp) {
452     data = (data << 8) | *src++;
453     --cnt;
454   }
455   for (; i<4; ++i, ++cp) {
456     data = (data << 8) | (*(uchar *)cp);
457   }
458
459   return (write_word(info, wp, data));
460 }
461
462 /*-----------------------------------------------------------------------
463  * Write a word to Flash, returns:
464  * 0 - OK
465  * 1 - write timeout
466  * 2 - Flash not erased
467  */
468 static int write_word (flash_info_t *info, ulong dest, ulong data)
469 {
470   vu_long *addr = (vu_long*)(info->start[0]);
471   ulong start;
472   int flag;
473
474   /* Check if Flash is (sufficiently) erased */
475   if ((*((vu_long *)dest) & data) != data) {
476     return (2);
477   }
478   /* Disable interrupts which might cause a timeout here */
479   flag = disable_interrupts();
480
481   addr[0x0555] = 0x00AA00AA;
482   addr[0x02AA] = 0x00550055;
483   addr[0x0555] = 0x00A000A0;
484
485   *((vu_long *)dest) = data;
486
487   /* re-enable interrupts if necessary */
488   if (flag)
489     enable_interrupts();
490
491   /* data polling for D7 */
492   start = get_timer (0);
493   while ((*((vu_long *)dest) & 0x00800080) != (data & 0x00800080)) {
494     if (get_timer(start) > CONFIG_SYS_FLASH_WRITE_TOUT) {
495       return (1);
496     }
497   }
498   return (0);
499 }
500
501 /*-----------------------------------------------------------------------
502  */