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