]> git.kernelconcepts.de Git - karo-tx-uboot.git/blob - board/rmu/flash.c
imported Freescale specific U-Boot additions for i.MX28,... release L2.6.31_10.08.01
[karo-tx-uboot.git] / board / rmu / flash.c
1 /*
2  * (C) Copyright 2000-2004
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 /* #define DEBUG */
25
26 #include <common.h>
27 #include <mpc8xx.h>
28
29 flash_info_t    flash_info[CONFIG_SYS_MAX_FLASH_BANKS]; /* info for FLASH chips */
30
31 /*-----------------------------------------------------------------------
32  * Functions
33  */
34 static ulong flash_get_size (vu_long *addr, flash_info_t *info);
35 static int write_word (flash_info_t *info, ulong dest, ulong data);
36 static void flash_get_offsets (ulong base, flash_info_t *info);
37
38 /*-----------------------------------------------------------------------
39  */
40
41 unsigned long flash_init (void)
42 {
43         volatile immap_t     *immap  = (immap_t *)CONFIG_SYS_IMMR;
44         volatile memctl8xx_t *memctl = &immap->im_memctl;
45         unsigned long size_b0 ;
46         int i;
47
48         /* Init: no FLASHes known */
49         for (i=0; i<CONFIG_SYS_MAX_FLASH_BANKS; ++i) {
50                 flash_info[i].flash_id = FLASH_UNKNOWN;
51         }
52
53         /* Static FLASH Bank configuration here - FIXME XXX */
54
55         debug ("\n## Get flash bank size @ 0x%08x\n", FLASH_BASE_PRELIM);
56
57         size_b0 = flash_get_size((vu_long *)FLASH_BASE_PRELIM, &flash_info[0]);
58         if (flash_info[0].flash_id == FLASH_UNKNOWN) {
59                 printf ("## Unknown FLASH on Bank 0 - Size = 0x%08lx = %ld MB\n",
60                         size_b0, size_b0<<20);
61         }
62
63         debug  ("## Before remap:  BR0: 0x%08x    OR0: 0x%08x\n",
64                 memctl->memc_br0, memctl->memc_or0);
65
66         /* Remap FLASH according to real size */
67         memctl->memc_or0 = CONFIG_SYS_OR_TIMING_FLASH | (-size_b0 & 0xFFFF8000);
68         memctl->memc_br0 = (CONFIG_SYS_FLASH_BASE & BR_BA_MSK) | BR_MS_GPCM | BR_V;
69
70         debug ("## BR0: 0x%08x    OR0: 0x%08x\n",
71                 memctl->memc_br0, memctl->memc_or0);
72
73         /* Re-do sizing to get full correct info */
74
75         size_b0 = flash_get_size((vu_long *)CONFIG_SYS_FLASH_BASE, &flash_info[0]);
76         flash_get_offsets (CONFIG_SYS_FLASH_BASE, &flash_info[0]);
77
78         /* monitor protection ON by default */
79         flash_protect(FLAG_PROTECT_SET,
80                       CONFIG_SYS_MONITOR_BASE,
81                       CONFIG_SYS_MONITOR_BASE+monitor_flash_len-1,
82                       &flash_info[0]);
83
84 #ifdef  CONFIG_ENV_IS_IN_FLASH
85         /* ENV protection ON by default */
86         flash_protect(FLAG_PROTECT_SET,
87                       CONFIG_ENV_ADDR,
88                       CONFIG_ENV_ADDR+CONFIG_ENV_SECT_SIZE-1,
89                       &flash_info[0]);
90 #endif
91
92 #if defined(CONFIG_ENV_ADDR_REDUND) || defined(CONFIG_ENV_OFFSET_REDUND)
93         debug ("Protect redundand environment: %08lx ... %08lx\n",
94                 (ulong)CONFIG_ENV_ADDR_REDUND,
95                 (ulong)CONFIG_ENV_ADDR_REDUND + CONFIG_ENV_SECT_SIZE - 1);
96
97         flash_protect(FLAG_PROTECT_SET,
98                       CONFIG_ENV_ADDR_REDUND,
99                       CONFIG_ENV_ADDR_REDUND + CONFIG_ENV_SECT_SIZE - 1,
100                       &flash_info[0]);
101 #endif
102
103         flash_info[0].size = size_b0;
104
105         debug ("## Final Flash bank size: %08lx\n", size_b0);
106
107         return (size_b0);
108 }
109
110 /*-----------------------------------------------------------------------
111  */
112 static void flash_get_offsets (ulong base, flash_info_t *info)
113 {
114         int i;
115
116         /* set up sector start address table */
117         if (info->flash_id & FLASH_BTYPE) {
118                 /* set sector offsets for bottom boot block type        */
119                 info->start[0] = base + 0x00000000;
120                 info->start[1] = base + 0x00010000;
121                 info->start[2] = base + 0x00018000;
122                 info->start[3] = base + 0x00020000;
123                 for (i = 4; i < info->sector_count; i++) {
124                         info->start[i] = base + ((i-3) * 0x00040000) ;
125                 }
126         } else {
127                 /* set sector offsets for top boot block type           */
128                 i = info->sector_count - 1;
129                 info->start[i--] = base + info->size - 0x00010000;
130                 info->start[i--] = base + info->size - 0x00018000;
131                 info->start[i--] = base + info->size - 0x00020000;
132                 for (; i >= 0; i--) {
133                         info->start[i] = base + i * 0x00040000;
134                 }
135         }
136
137 }
138
139 /*-----------------------------------------------------------------------
140  */
141 void flash_print_info  (flash_info_t *info)
142 {
143         int i;
144
145         if (info->flash_id == FLASH_UNKNOWN) {
146                 printf ("missing or unknown FLASH type\n");
147                 return;
148         }
149
150         switch (info->flash_id & FLASH_VENDMASK) {
151         case FLASH_MAN_AMD:     printf ("AMD ");                break;
152         case FLASH_MAN_FUJ:     printf ("FUJITSU ");            break;
153         default:                printf ("Unknown Vendor ");     break;
154         }
155
156         switch (info->flash_id & FLASH_TYPEMASK) {
157         case FLASH_AM400B:      printf ("AM29LV400B (4 Mbit, bottom boot sect)\n");
158                                 break;
159         case FLASH_AM400T:      printf ("AM29LV400T (4 Mbit, top boot sector)\n");
160                                 break;
161         case FLASH_AM800B:      printf ("AM29LV800B (8 Mbit, bottom boot sect)\n");
162                                 break;
163         case FLASH_AM800T:      printf ("AM29LV800T (8 Mbit, top boot sector)\n");
164                                 break;
165         case FLASH_AM160B:      printf ("AM29LV160B (16 Mbit, bottom boot sect)\n");
166                                 break;
167         case FLASH_AM160T:      printf ("AM29LV160T (16 Mbit, top boot sector)\n");
168                                 break;
169         case FLASH_AM320B:      printf ("AM29LV320B (32 Mbit, bottom boot sect)\n");
170                                 break;
171         case FLASH_AM320T:      printf ("AM29LV320T (32 Mbit, top boot sector)\n");
172                                 break;
173         default:                printf ("Unknown Chip Type\n");
174                                 break;
175         }
176
177         printf ("  Size: %ld MB in %d Sectors\n",
178                 info->size >> 20, info->sector_count);
179
180         printf ("  Sector Start Addresses:");
181         for (i=0; i<info->sector_count; ++i) {
182                 if ((i % 5) == 0)
183                         printf ("\n   ");
184                 printf (" %08lX%s",
185                         info->start[i],
186                         info->protect[i] ? " (RO)" : "     "
187                 );
188         }
189         printf ("\n");
190         return;
191 }
192
193 /*-----------------------------------------------------------------------
194  */
195
196
197 /*-----------------------------------------------------------------------
198  */
199
200 /*
201  * The following code cannot be run from FLASH!
202  */
203
204 static ulong flash_get_size (vu_long *addr, flash_info_t *info)
205 {
206         short i;
207         ulong value;
208         ulong base = (ulong)addr;
209
210         /* Write auto select command: read Manufacturer ID */
211         addr[0xAAA] = 0xAAAAAAAA ;
212         addr[0x555] = 0x55555555 ;
213         addr[0xAAA] = 0x90909090 ;
214
215         value = addr[0] ;
216
217         debug ("Manuf. ID @ 0x%08lx: 0x%08lx\n", (ulong)addr, value);
218
219         switch (value & 0x00FF00FF) {
220         case AMD_MANUFACT:
221                 info->flash_id = FLASH_MAN_AMD;
222                 break;
223         case FUJ_MANUFACT:
224                 info->flash_id = FLASH_MAN_FUJ;
225                 break;
226         default:
227                 info->flash_id = FLASH_UNKNOWN;
228                 info->sector_count = 0;
229                 info->size = 0;
230                 return (0);                     /* no or unknown flash  */
231         }
232
233         value = addr[2] ;               /* device ID            */
234
235         debug ("Device ID @ 0x%08lx: 0x%08lx\n", (ulong)(&addr[1]), value);
236
237         switch (value & 0x00FF00FF) {
238         case (AMD_ID_LV400T & 0x00FF00FF):
239                 info->flash_id += FLASH_AM400T;
240                 info->sector_count = 11;
241                 info->size = 0x00100000;
242                 break;                          /* => 1 MB              */
243
244         case (AMD_ID_LV400B & 0x00FF00FF):
245                 info->flash_id += FLASH_AM400B;
246                 info->sector_count = 11;
247                 info->size = 0x00100000;
248                 break;                          /* => 1 MB              */
249
250         case (AMD_ID_LV800T & 0x00FF00FF):
251                 info->flash_id += FLASH_AM800T;
252                 info->sector_count = 19;
253                 info->size = 0x00200000;
254                 break;                          /* => 2 MB              */
255
256         case (AMD_ID_LV800B & 0x00FF00FF):
257                 info->flash_id += FLASH_AM800B;
258                 info->sector_count = 19;
259                 info->size = 0x00400000;        /*%%% Size doubled by yooth */
260                 break;                          /* => 4 MB              */
261
262         case (AMD_ID_LV160T & 0x00FF00FF):
263                 info->flash_id += FLASH_AM160T;
264                 info->sector_count = 35;
265                 info->size = 0x00400000;
266                 break;                          /* => 4 MB              */
267
268         case (AMD_ID_LV160B & 0x00FF00FF):
269                 info->flash_id += FLASH_AM160B;
270                 info->sector_count = 35;
271                 info->size = 0x00800000;
272                 break;                          /* => 8 MB              */
273         case (AMD_ID_LV320T & 0x00FF00FF):
274                 info->flash_id += FLASH_AM320T;
275                 info->sector_count = 67;
276                 info->size = 0x00800000;
277                 break;                          /* => 8 MB              */
278
279         case (AMD_ID_LV320B & 0x00FF00FF):
280                 info->flash_id += FLASH_AM320B;
281                 info->sector_count = 67;
282                 info->size = 0x01000000;
283                 break;                          /* => 16 MB             */
284         default:
285                 info->flash_id = FLASH_UNKNOWN;
286                 return (0);                     /* => no or unknown flash */
287
288         }
289         /* set up sector start address table */
290         if (info->flash_id & FLASH_BTYPE) {
291                 /* set sector offsets for bottom boot block type        */
292                 info->start[0] = base + 0x00000000;
293                 info->start[1] = base + 0x00010000;
294                 info->start[2] = base + 0x00018000;
295                 info->start[3] = base + 0x00020000;
296                 for (i = 4; i < info->sector_count; i++) {
297                         info->start[i] = base + ((i-3) * 0x00040000) ;
298                 }
299         } else {
300                 /* set sector offsets for top boot block type           */
301                 i = info->sector_count - 1;
302                 info->start[i--] = base + info->size - 0x00010000;
303                 info->start[i--] = base + info->size - 0x00018000;
304                 info->start[i--] = base + info->size - 0x00020000;
305                 for (; i >= 0; i--) {
306                         info->start[i] = base + i * 0x00040000;
307                 }
308         }
309
310         /* check for protected sectors */
311         for (i = 0; i < info->sector_count; i++) {
312                 /* read sector protection at sector address, (A7 .. A0) = 0x02 */
313                 /* D0 = 1 if protected */
314                 addr = (volatile unsigned long *)(info->start[i]);
315                 info->protect[i] = addr[4] & 1 ;
316         }
317
318         /*
319          * Prevent writes to uninitialized FLASH.
320          */
321         if (info->flash_id != FLASH_UNKNOWN) {
322                 addr = (volatile unsigned long *)info->start[0];
323
324                 *addr = 0xF0F0F0F0;     /* reset bank */
325         }
326
327         return (info->size);
328 }
329
330
331 /*-----------------------------------------------------------------------
332  */
333
334 int     flash_erase (flash_info_t *info, int s_first, int s_last)
335 {
336         vu_long *addr = (vu_long*)(info->start[0]);
337         int flag, prot, sect, l_sect;
338         ulong start, now, last;
339
340         debug ("flash_erase: first: %d last: %d\n", s_first, s_last);
341
342         if ((s_first < 0) || (s_first > s_last)) {
343                 if (info->flash_id == FLASH_UNKNOWN) {
344                         printf ("- missing\n");
345                 } else {
346                         printf ("- no sectors to erase\n");
347                 }
348                 return 1;
349         }
350
351         if ((info->flash_id == FLASH_UNKNOWN) ||
352             (info->flash_id > FLASH_AMD_COMP)) {
353                 printf ("Can't erase unknown flash type %08lx - aborted\n",
354                         info->flash_id);
355                 return 1;
356         }
357
358         prot = 0;
359         for (sect=s_first; sect<=s_last; ++sect) {
360                 if (info->protect[sect]) {
361                         prot++;
362                 }
363         }
364
365         if (prot) {
366                 printf ("- Warning: %d protected sectors will not be erased!\n",
367                         prot);
368         } else {
369                 printf ("\n");
370         }
371
372         l_sect = -1;
373
374         /* Disable interrupts which might cause a timeout here */
375         flag = disable_interrupts();
376
377         addr[0xAAA] = 0xAAAAAAAA;
378         addr[0x555] = 0x55555555;
379         addr[0xAAA] = 0x80808080;
380         addr[0xAAA] = 0xAAAAAAAA;
381         addr[0x555] = 0x55555555;
382
383         /* Start erase on unprotected sectors */
384         for (sect = s_first; sect<=s_last; sect++) {
385                 if (info->protect[sect] == 0) { /* not protected */
386                         addr = (vu_long *)(info->start[sect]) ;
387                         addr[0] = 0x30303030 ;
388                         l_sect = sect;
389                 }
390         }
391
392         /* re-enable interrupts if necessary */
393         if (flag)
394                 enable_interrupts();
395
396         /* wait at least 80us - let's wait 1 ms */
397         udelay (1000);
398
399         /*
400          * We wait for the last triggered sector
401          */
402         if (l_sect < 0)
403                 goto DONE;
404
405         start = get_timer (0);
406         last  = start;
407         addr = (vu_long *)(info->start[l_sect]);
408         while ((addr[0] & 0x80808080) != 0x80808080) {
409                 if ((now = get_timer(start)) > CONFIG_SYS_FLASH_ERASE_TOUT) {
410                         printf ("Timeout\n");
411                         return 1;
412                 }
413                 /* show that we're waiting */
414                 if ((now - last) > 1000) {      /* every second */
415                         putc ('.');
416                         last = now;
417                 }
418         }
419
420 DONE:
421         /* reset to read mode */
422         addr = (vu_long *)info->start[0];
423         addr[0] = 0xF0F0F0F0;   /* reset bank */
424
425         printf (" done\n");
426         return 0;
427 }
428
429 /*-----------------------------------------------------------------------
430  * Copy memory to flash, returns:
431  * 0 - OK
432  * 1 - write timeout
433  * 2 - Flash not erased
434  */
435
436 int write_buff (flash_info_t *info, uchar *src, ulong addr, ulong cnt)
437 {
438         ulong cp, wp, data;
439         int i, l, rc;
440
441         wp = (addr & ~3);       /* get lower word aligned address */
442
443         /*
444          * handle unaligned start bytes
445          */
446         if ((l = addr - wp) != 0) {
447                 data = 0;
448                 for (i=0, cp=wp; i<l; ++i, ++cp) {
449                         data = (data << 8) | (*(uchar *)cp);
450                 }
451                 for (; i<4 && cnt>0; ++i) {
452                         data = (data << 8) | *src++;
453                         --cnt;
454                         ++cp;
455                 }
456                 for (; cnt==0 && i<4; ++i, ++cp) {
457                         data = (data << 8) | (*(uchar *)cp);
458                 }
459
460                 if ((rc = write_word(info, wp, data)) != 0) {
461                         return (rc);
462                 }
463                 wp += 4;
464         }
465
466         /*
467          * handle word aligned part
468          */
469         while (cnt >= 4) {
470                 data = 0;
471                 for (i=0; i<4; ++i) {
472                         data = (data << 8) | *src++;
473                 }
474                 if ((rc = write_word(info, wp, data)) != 0) {
475                         return (rc);
476                 }
477                 wp  += 4;
478                 cnt -= 4;
479         }
480
481         if (cnt == 0) {
482                 return (0);
483         }
484
485         /*
486          * handle unaligned tail bytes
487          */
488         data = 0;
489         for (i=0, cp=wp; i<4 && cnt>0; ++i, ++cp) {
490                 data = (data << 8) | *src++;
491                 --cnt;
492         }
493         for (; i<4; ++i, ++cp) {
494                 data = (data << 8) | (*(uchar *)cp);
495         }
496
497         return (write_word(info, wp, data));
498 }
499
500 /*-----------------------------------------------------------------------
501  * Write a word to Flash, returns:
502  * 0 - OK
503  * 1 - write timeout
504  * 2 - Flash not erased
505  */
506 static int write_word (flash_info_t *info, ulong dest, ulong data)
507 {
508         vu_long *addr = (vu_long *)(info->start[0]);
509         ulong start;
510         int flag;
511
512         /* Check if Flash is (sufficiently) erased */
513         if ((*((vu_long *)dest) & data) != data) {
514                 return (2);
515         }
516         /* Disable interrupts which might cause a timeout here */
517         flag = disable_interrupts();
518
519         addr[0xAAA] = 0xAAAAAAAA;
520         addr[0x555] = 0x55555555;
521         addr[0xAAA] = 0xA0A0A0A0;
522
523         *((vu_long *)dest) = data;
524
525         /* re-enable interrupts if necessary */
526         if (flag)
527                 enable_interrupts();
528
529         /* data polling for D7 */
530         start = get_timer (0);
531         while ((*((vu_long *)dest) & 0x80808080) != (data & 0x80808080)) {
532                 if (get_timer(start) > CONFIG_SYS_FLASH_WRITE_TOUT) {
533                         return (1);
534                 }
535         }
536         return (0);
537 }
538
539 /*-----------------------------------------------------------------------
540  */