* Patch by Marc Singer, 29 May 2003:
[kernel/u-boot.git] / board / sc520_cdp / flash.c
1 /*
2  * (C) Copyright 2002, 2003
3  * Daniel Engström, Omicron Ceti AB, daniel@omicron.se
4  * 
5  * (C) Copyright 2002
6  * Sysgo Real-Time Solutions, GmbH <www.elinos.com>
7  * Alex Zuepke <azu@sysgo.de>
8  *
9  * See file CREDITS for list of people who contributed to this
10  * project.
11  *
12  * This program is free software; you can redistribute it and/or
13  * modify it under the terms of the GNU General Public License as
14  * published by the Free Software Foundation; either version 2 of
15  * the License, or (at your option) any later version.
16  *
17  * This program is distributed in the hope that it will be useful,
18  * but WITHOUT ANY WARRANTY; without even the implied warranty of
19  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
20  * GNU General Public License for more details.
21  *
22  * You should have received a copy of the GNU General Public License
23  * along with this program; if not, write to the Free Software
24  * Foundation, Inc., 59 Temple Place, Suite 330, Boston,
25  * MA 02111-1307 USA
26  */
27
28 #include <common.h>
29 #include <asm/io.h>
30 #include <pci.h>
31 #include <asm/ic/sc520.h>
32
33 #define PROBE_BUFFER_SIZE 1024
34 static unsigned char buffer[PROBE_BUFFER_SIZE];
35
36 #define SC520_MAX_FLASH_BANKS  3
37 #define SC520_FLASH_BANK0_BASE 0x38000000  /* BOOTCS */
38 #define SC520_FLASH_BANK1_BASE 0x30000000  /* ROMCS0 */
39 #define SC520_FLASH_BANK2_BASE 0x28000000  /* ROMCS1 */
40 #define SC520_FLASH_BANKSIZE   0x8000000
41
42 #define AMD29LV016B_SIZE        0x200000
43 #define AMD29LV016B_SECTORS     32
44
45 flash_info_t    flash_info[SC520_MAX_FLASH_BANKS];
46
47 #define READY 1
48 #define ERR   2
49 #define TMO   4
50
51 /*-----------------------------------------------------------------------
52  */
53
54
55 static u32 _probe_flash(u32 addr, u32 bw, int il)
56 {
57         u32 result=0;
58         
59         /* First do an unlock cycle for the benefit of
60          * devices that need it */
61         
62         switch (bw) {
63                 
64         case 1:
65                 *(volatile u8*)(addr+0x5555) = 0xaa;
66                 *(volatile u8*)(addr+0x2aaa) = 0x55;
67                 *(volatile u8*)(addr+0x5555) = 0x90;
68                 
69                 /* Read vendor */
70                 result = *(volatile u8*)addr;
71                 result <<= 16;
72                 
73                 /* Read device */
74                 result |= *(volatile u8*)(addr+2);
75                 
76                 /* Return device to data mode */
77                 *(volatile u8*)addr = 0xff;
78                 *(volatile u8*)(addr+0x5555), 0xf0;  
79                 break;
80                 
81         case 2:
82                 *(volatile u16*)(addr+0xaaaa) = 0xaaaa;
83                 *(volatile u16*)(addr+0x5554) = 0x5555;
84                 
85                 /* Issue identification command */
86                 if (il == 2) {
87                         *(volatile u16*)(addr+0xaaaa) = 0x9090;
88                         
89                         /* Read vendor */
90                         result = *(volatile u8*)addr;
91                         result <<= 16;
92                         
93                         /* Read device */
94                         result |= *(volatile u8*)(addr+2);
95                         
96                         /* Return device to data mode */
97                         *(volatile u16*)addr =  0xffff;
98                         *(volatile u16*)(addr+0xaaaa), 0xf0f0;  
99                         
100                 } else {
101                         *(volatile u8*)(addr+0xaaaa) = 0x90;
102                         /* Read vendor */
103                         result = *(volatile u16*)addr;
104                         result <<= 16;
105                         
106                         /* Read device */
107                         result |= *(volatile u16*)(addr+2);
108                         
109                         /* Return device to data mode */
110                         *(volatile u8*)addr = 0xff;
111                         *(volatile u8*)(addr+0xaaaa), 0xf0;                     
112                 }
113                 
114                 break;
115                 
116          case 4:
117                 *(volatile u32*)(addr+0x5554) = 0xaaaaaaaa;
118                 *(volatile u32*)(addr+0xaaa8) = 0x55555555;
119                 
120                 switch (il) {
121                 case 1:
122                         /* Issue identification command */
123                         *(volatile u8*)(addr+0x5554) = 0x90;
124                         
125                         /* Read vendor */
126                         result = *(volatile u16*)addr;
127                         result <<= 16;
128                 
129                         /* Read device */
130                         result |= *(volatile u16*)(addr+4);
131                         
132                         /* Return device to data mode */
133                         *(volatile u8*)addr =  0xff;
134                         *(volatile u8*)(addr+0x5554), 0xf0;  
135                         break;
136                         
137                 case 2:
138                         /* Issue identification command */
139                         *(volatile u32*)(addr + 0x5554) = 0x00900090;
140                         
141                         /* Read vendor */
142                         result = *(volatile u16*)addr;
143                         result <<= 16;
144                         
145                         /* Read device */
146                         result |= *(volatile u16*)(addr+4);
147                         
148                         /* Return device to data mode */
149                         *(volatile u32*)addr =  0x00ff00ff;
150                         *(volatile u32*)(addr+0x5554), 0x00f000f0;  
151                         break;
152                         
153                 case 4:
154                         /* Issue identification command */
155                         *(volatile u32*)(addr+0x5554) = 0x90909090;
156                         
157                         /* Read vendor */
158                         result = *(volatile u8*)addr;
159                         result <<= 16;
160                         
161                         /* Read device */
162                         result |= *(volatile u8*)(addr+4);
163                         
164                         /* Return device to data mode */
165                         *(volatile u32*)addr =  0xffffffff;
166                         *(volatile u32*)(addr+0x5554), 0xf0f0f0f0; 
167                         break;
168                 }
169                 break;
170         }
171         
172         
173         
174         return result;
175 }
176
177 extern int _probe_flash_end;
178 asm ("_probe_flash_end:\n"
179      ".long 0\n");
180
181 static int identify_flash(unsigned address, int width)
182 {
183         int is; 
184         int device;
185         int vendor;     
186         int size;
187         unsigned res;
188         
189         u32 (*_probe_flash_ptr)(u32 a, u32 bw, int il);
190         
191         size = (unsigned)&_probe_flash_end - (unsigned)_probe_flash; 
192         
193         if (size > PROBE_BUFFER_SIZE) {
194                 printf("_probe_flash() routine too large (%d) %p - %p\n",
195                        size, &_probe_flash_end, _probe_flash);
196                 return 0;
197         }
198         
199         memcpy(buffer, _probe_flash, size);
200         _probe_flash_ptr = (void*)buffer;
201         
202         is = disable_interrupts();
203         res = _probe_flash_ptr(address, width, 1);
204         if (is) {
205                 enable_interrupts();
206         }
207         
208         
209         vendor = res >> 16;
210         device = res & 0xffff;
211         
212                 
213         return res;
214 }
215
216 ulong flash_init(void)
217 {
218         int i, j;
219         ulong size = 0;
220         
221         for (i = 0; i < SC520_MAX_FLASH_BANKS; i++) {
222                 unsigned id;
223                 ulong flashbase = 0;
224                 int sectsize = 0; 
225                 
226                 memset(flash_info[i].protect, 0, CFG_MAX_FLASH_SECT);
227                 switch (i) {
228                 case 0:
229                         flashbase = SC520_FLASH_BANK0_BASE;
230                         break;
231                 case 1:
232                         flashbase = SC520_FLASH_BANK1_BASE;
233                         break;
234                 case 2:
235                         flashbase = SC520_FLASH_BANK2_BASE;
236                         break;
237                 default:
238                         panic("configured to many flash banks!\n");
239                 }
240                 
241                 id = identify_flash(flashbase, 4);
242                 switch (id & 0x00ff00ff) {
243                 case 0x000100c8:
244                         /* 29LV016B/29LV017B */
245                         flash_info[i].flash_id =
246                                 (AMD_MANUFACT & FLASH_VENDMASK) |
247                                 (AMD_ID_LV016B & FLASH_TYPEMASK);
248                         
249                         flash_info[i].size = AMD29LV016B_SIZE*4;
250                         flash_info[i].sector_count = AMD29LV016B_SECTORS;
251                         sectsize = (AMD29LV016B_SIZE*4)/AMD29LV016B_SECTORS;
252                         printf("Bank %d: 4 x AMD 29LV017B\n", i);
253                         break;
254                         
255                         
256                 default:
257                         printf("Bank %d have unknown flash %08x\n", i, id);
258                         flash_info[i].flash_id = FLASH_UNKNOWN;
259                         continue;
260                 }
261                 
262                 for (j = 0; j < flash_info[i].sector_count; j++) {
263                         flash_info[i].start[j] = flashbase + j * sectsize;
264                 }
265                 size += flash_info[i].size;
266                 
267                 flash_protect(FLAG_PROTECT_CLEAR,
268                               flash_info[i].start[0],
269                                flash_info[i].start[0] + flash_info[i].size - 1,
270                               &flash_info[i]);
271         }
272         
273         /*
274          * Protect monitor and environment sectors
275          */
276         flash_protect(FLAG_PROTECT_SET,
277                       i386boot_start,
278                       i386boot_end,
279                       &flash_info[0]);
280 #ifdef CFG_ENV_ADDR
281         flash_protect(FLAG_PROTECT_SET,
282                       CFG_ENV_ADDR,
283                       CFG_ENV_ADDR + CFG_ENV_SIZE - 1,
284                       &flash_info[0]);
285 #endif  
286         return size;
287 }
288
289 /*-----------------------------------------------------------------------
290  */
291 void flash_print_info(flash_info_t *info)
292 {
293         int i;
294         
295         switch (info->flash_id & FLASH_VENDMASK) {
296                 
297         case (AMD_MANUFACT & FLASH_VENDMASK):
298                 printf("AMD:   ");
299                 switch (info->flash_id & FLASH_TYPEMASK) {
300                 case (AMD_ID_LV016B & FLASH_TYPEMASK):
301                         printf("4x AMD29LV017B (4x16Mbit)\n");
302                         break;
303                 default:
304                         printf("Unknown Chip Type\n");
305                         goto done;
306                         break;
307                 }
308                 
309                 break;
310         default:
311                 printf("Unknown Vendor ");
312                 break;
313         }
314         
315         
316         printf("  Size: %ld MB in %d Sectors\n",
317                info->size >> 20, info->sector_count);
318         
319         printf("  Sector Start Addresses:");
320         for (i = 0; i < info->sector_count; i++) {
321                 if ((i % 5) == 0) {
322                         printf ("\n   ");
323                 }
324                 printf (" %08lX%s", info->start[i],
325                         info->protect[i] ? " (RO)" : "     ");
326         }
327         printf ("\n");
328         
329         done:
330 }
331
332 /*-----------------------------------------------------------------------
333  */
334
335 /* this needs to be inlined, the SWTMRMMILLI register is reset by each read */
336 #define __udelay(delay) \
337 {       \
338         unsigned micro; \
339         unsigned milli=0; \
340         \
341         micro = *(volatile u16*)(0xfffef000+SC520_SWTMRMILLI); \
342          \
343         for (;;) { \
344                 \
345                 milli += *(volatile u16*)(0xfffef000+SC520_SWTMRMILLI); \
346                 micro = *(volatile u16*)(0xfffef000+SC520_SWTMRMICRO); \
347                 \
348                 if ((delay) <= (micro + (milli * 1000))) { \
349                         break; \
350                 } \
351         } \
352 } while (0) 
353
354 static u32 _amd_erase_flash(u32 addr, u32 sector)
355 {
356         unsigned elapsed;
357         
358         /* Issue erase */
359         *(volatile u32*)(addr + 0x5554) = 0xAAAAAAAA;
360         *(volatile u32*)(addr + 0xaaa8) = 0x55555555;
361         *(volatile u32*)(addr + 0x5554) = 0x80808080;
362         /* And one unlock */
363         *(volatile u32*)(addr + 0x5554) = 0xAAAAAAAA;
364         *(volatile u32*)(addr + 0xaaa8) = 0x55555555;
365         /* Sector erase command comes last */
366         *(volatile u32*)(addr + sector) = 0x30303030;
367         
368         elapsed = *(volatile u16*)(0xfffef000+SC520_SWTMRMILLI); /* dummy read */
369         elapsed = 0;
370         __udelay(50);
371         while (((*(volatile u32*)(addr + sector)) & 0x80808080) != 0x80808080) {
372                 
373                 elapsed += *(volatile u16*)(0xfffef000+SC520_SWTMRMILLI);
374                 if (elapsed > ((CFG_FLASH_ERASE_TOUT/CFG_HZ) * 1000)) {
375                         *(volatile u32*)(addr) = 0xf0f0f0f0;
376                         return 1;                       
377                 }
378         }
379         
380         *(volatile u32*)(addr) = 0xf0f0f0f0;
381         
382         return 0;
383 }
384
385 extern int _amd_erase_flash_end;
386 asm ("_amd_erase_flash_end:\n"
387      ".long 0\n");
388
389 int flash_erase(flash_info_t *info, int s_first, int s_last)
390 {
391         u32 (*_erase_flash_ptr)(u32 a, u32 so);
392         int prot;
393         int sect;
394         unsigned size;
395         
396         if ((s_first < 0) || (s_first > s_last)) {
397                 if (info->flash_id == FLASH_UNKNOWN) {
398                         printf("- missing\n");
399                 } else {
400                         printf("- no sectors to erase\n");
401                 }
402                 return 1;
403         }
404         
405         if ((info->flash_id & FLASH_VENDMASK) == (AMD_MANUFACT & FLASH_VENDMASK)) {
406                 size = (unsigned)&_amd_erase_flash_end - (unsigned)_amd_erase_flash; 
407                 
408                 if (size > PROBE_BUFFER_SIZE) {
409                         printf("_amd_erase_flash() routine too large (%d) %p - %p\n",
410                                size, &_amd_erase_flash_end, _amd_erase_flash);
411                         return 0;
412                 }
413                 
414                 memcpy(buffer, _amd_erase_flash, size);
415                 _erase_flash_ptr = (void*)buffer;
416         
417         }  else {
418                 printf ("Can't erase unknown flash type - aborted\n");
419                 return 1;
420         }
421         
422         prot = 0;
423         for (sect=s_first; sect<=s_last; ++sect) {
424                 if (info->protect[sect]) {
425                         prot++;
426                 }
427         }
428         
429         if (prot) {
430                 printf ("- Warning: %d protected sectors will not be erased!\n", prot);
431         } else {
432                 printf ("\n");
433         }
434                 
435         
436         /* Start erase on unprotected sectors */
437         for (sect = s_first; sect<=s_last; sect++) {
438                 
439                 if (info->protect[sect] == 0) { /* not protected */
440                         int res;
441                         int flag;
442                         
443                         /* Disable interrupts which might cause a timeout here */
444                         flag = disable_interrupts();
445                         
446                         res = _erase_flash_ptr(info->start[0], info->start[sect]-info->start[0]);
447                         
448                         /* re-enable interrupts if necessary */
449                         if (flag) {
450                                 enable_interrupts();
451                         }
452                         
453                         
454                         if (res) {
455                                 printf("Erase timed out, sector %d\n", sect);
456                                 return res;
457                         }
458                         
459                         putc('.');                      
460                 }               
461         }
462
463         
464         return 0;
465 }
466
467 /*-----------------------------------------------------------------------
468  * Write a word to Flash, returns:
469  * 0 - OK
470  * 1 - write timeout
471  * 2 - Flash not erased
472  */
473 static int _amd_write_word(unsigned start, unsigned dest, unsigned data)
474 {
475         volatile u32 *addr2 = (u32*)start;
476         volatile u32 *dest2 = (u32*)dest;
477         volatile u32 *data2 = (u32*)&data;
478         unsigned elapsed;
479         
480         /* Check if Flash is (sufficiently) erased */
481         if ((*((volatile u32*)dest) & (u32)data) != (u32)data) {
482                 return 2;
483         }
484                 
485         addr2[0x5554] = 0xAAAAAAAA;
486         addr2[0xaaa8] = 0x55555555;
487         addr2[0x5554] = 0xA0A0A0A0;
488         
489         dest2[0] = data;
490         
491         elapsed = *(volatile u16*)(0xfffef000+SC520_SWTMRMILLI); /* dummy read */
492         elapsed = 0;
493         
494         /* data polling for D7 */
495         while ((dest2[0] & 0x80808080) != (data2[0] & 0x80808080)) {
496                 elapsed += *(volatile u16*)(0xfffef000+SC520_SWTMRMILLI);
497                 if (elapsed > ((CFG_FLASH_WRITE_TOUT/CFG_HZ) * 1000)) {
498                         addr2[0] = 0xf0f0f0f0;
499                         return 1;                       
500                 }
501         }
502
503         
504         addr2[0] = 0xf0f0f0f0;
505         
506         return 0;
507 }
508
509 extern int _amd_write_word_end;
510 asm ("_amd_write_word_end:\n"
511      ".long 0\n");
512
513
514
515
516 /*-----------------------------------------------------------------------
517  * Copy memory to flash, returns:
518  * 0 - OK
519  * 1 - write timeout
520  * 2 - Flash not erased
521  * 3 - Unsupported flash type
522  */
523
524 int write_buff(flash_info_t *info, uchar *src, ulong addr, ulong cnt)
525 {
526         ulong cp, wp, data;
527         int i, l, rc;
528         int flag;
529         u32 (*_write_word_ptr)(unsigned start, unsigned dest, unsigned data);
530         unsigned size;
531         
532         if ((info->flash_id & FLASH_VENDMASK) == (AMD_MANUFACT & FLASH_VENDMASK)) {
533                 size = (unsigned)&_amd_write_word_end - (unsigned)_amd_write_word; 
534                 
535                 if (size > PROBE_BUFFER_SIZE) {
536                         printf("_amd_write_word() routine too large (%d) %p - %p\n",
537                                size, &_amd_write_word_end, _amd_write_word);
538                         return 0;
539                 }
540                 
541                 memcpy(buffer, _amd_write_word, size);
542                 _write_word_ptr = (void*)buffer;
543         
544         } else {
545                 printf ("Can't program unknown flash type - aborted\n");
546                 return 3;
547         }
548
549
550         wp = (addr & ~3);       /* get lower word aligned address */
551         
552
553         /*
554          * handle unaligned start bytes
555          */
556         if ((l = addr - wp) != 0) {
557                 data = 0;
558                 for (i=0, cp=wp; i<l; ++i, ++cp) {
559                         data |= (*(uchar *)cp) << (8*i);
560                 }
561                 for (; i<4 && cnt>0; ++i) {
562                         data |= *src++ << (8*i);
563                         --cnt;
564                         ++cp;
565                 }
566                 for (; cnt==0 && i<4; ++i, ++cp) {
567                         data |= (*(uchar *)cp)  << (8*i);
568                 }
569                 
570                 /* Disable interrupts which might cause a timeout here */
571                 flag = disable_interrupts();
572                 
573                 rc = _write_word_ptr(info->start[0], wp, data);
574                 
575                 /* re-enable interrupts if necessary */
576                 if (flag) {
577                         enable_interrupts();
578                 }
579                 if (rc != 0) {
580                         return rc;
581                 }
582                 wp += 4;
583         }
584         
585         /*
586          * handle word aligned part
587          */
588         while (cnt >= 4) {
589                 data = 0;
590                                
591                 for (i=0; i<4; ++i) {
592                         data |= *src++ << (8*i);
593                 }
594                 
595                 /* Disable interrupts which might cause a timeout here */
596                 flag = disable_interrupts();
597
598                 rc = _write_word_ptr(info->start[0], wp, data);
599                 
600                 /* re-enable interrupts if necessary */
601                 if (flag) {
602                         enable_interrupts();
603                 }
604                 if (rc != 0) {
605                         return rc;
606                 }
607                 wp  += 4;
608                 cnt -= 4;
609         }
610         
611         if (cnt == 0) {
612                 return 0;
613         }
614         
615         /*
616          * handle unaligned tail bytes
617          */
618         data = 0;
619         for (i=0, cp=wp; i<4 && cnt>0; ++i, ++cp) {
620                 data |= *src++ << (8*i);
621                 --cnt;
622         }
623         
624         for (; i<4; ++i, ++cp) {
625                 data |= (*(uchar *)cp) << (8*i);
626         }
627
628         /* Disable interrupts which might cause a timeout here */
629         flag = disable_interrupts();
630
631         rc = _write_word_ptr(info->start[0], wp, data);
632         
633         /* re-enable interrupts if necessary */
634         if (flag) {
635                 enable_interrupts();
636         }
637         
638         return rc;
639         
640 }
641
642