]> git.kernelconcepts.de Git - karo-tx-uboot.git/blob - board/sc520_cdp/flash.c
imported Ka-Ro specific additions to U-Boot 2009.08 for TX28
[karo-tx-uboot.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         return result;
174 }
175
176 extern int _probe_flash_end;
177 asm ("_probe_flash_end:\n"
178      ".long 0\n");
179
180 static int identify_flash(unsigned address, int width)
181 {
182         int is;
183         int device;
184         int vendor;
185         int size;
186         unsigned res;
187
188         u32 (*_probe_flash_ptr)(u32 a, u32 bw, int il);
189
190         size = (unsigned)&_probe_flash_end - (unsigned)_probe_flash;
191
192         if (size > PROBE_BUFFER_SIZE) {
193                 printf("_probe_flash() routine too large (%d) %p - %p\n",
194                        size, &_probe_flash_end, _probe_flash);
195                 return 0;
196         }
197
198         memcpy(buffer, _probe_flash, size);
199         _probe_flash_ptr = (void*)buffer;
200
201         is = disable_interrupts();
202         res = _probe_flash_ptr(address, width, 1);
203         if (is) {
204                 enable_interrupts();
205         }
206
207
208         vendor = res >> 16;
209         device = res & 0xffff;
210
211
212         return res;
213 }
214
215 ulong flash_init(void)
216 {
217         int i, j;
218         ulong size = 0;
219
220         for (i = 0; i < SC520_MAX_FLASH_BANKS; i++) {
221                 unsigned id;
222                 ulong flashbase = 0;
223                 int sectsize = 0;
224
225                 memset(flash_info[i].protect, 0, CONFIG_SYS_MAX_FLASH_SECT);
226                 switch (i) {
227                 case 0:
228                         flashbase = SC520_FLASH_BANK0_BASE;
229                         break;
230                 case 1:
231                         flashbase = SC520_FLASH_BANK1_BASE;
232                         break;
233                 case 2:
234                         flashbase = SC520_FLASH_BANK2_BASE;
235                         break;
236                 default:
237                         panic("configured too many flash banks!\n");
238                 }
239
240                 id = identify_flash(flashbase, 4);
241                 switch (id & 0x00ff00ff) {
242                 case 0x000100c8:
243                         /* 29LV016B/29LV017B */
244                         flash_info[i].flash_id =
245                                 (AMD_MANUFACT & FLASH_VENDMASK) |
246                                 (AMD_ID_LV016B & FLASH_TYPEMASK);
247
248                         flash_info[i].size = AMD29LV016B_SIZE*4;
249                         flash_info[i].sector_count = AMD29LV016B_SECTORS;
250                         sectsize = (AMD29LV016B_SIZE*4)/AMD29LV016B_SECTORS;
251                         printf("Bank %d: 4 x AMD 29LV017B\n", i);
252                         break;
253
254
255                 default:
256                         printf("Bank %d have unknown flash %08x\n", i, id);
257                         flash_info[i].flash_id = FLASH_UNKNOWN;
258                         continue;
259                 }
260
261                 for (j = 0; j < flash_info[i].sector_count; j++) {
262                         flash_info[i].start[j] = flashbase + j * sectsize;
263                 }
264                 size += flash_info[i].size;
265
266                 flash_protect(FLAG_PROTECT_CLEAR,
267                               flash_info[i].start[0],
268                                flash_info[i].start[0] + flash_info[i].size - 1,
269                               &flash_info[i]);
270         }
271
272         /*
273          * Protect monitor and environment sectors
274          */
275         flash_protect(FLAG_PROTECT_SET,
276                       i386boot_start,
277                       i386boot_end,
278                       &flash_info[0]);
279 #ifdef CONFIG_ENV_ADDR
280         flash_protect(FLAG_PROTECT_SET,
281                       CONFIG_ENV_ADDR,
282                       CONFIG_ENV_ADDR + CONFIG_ENV_SIZE - 1,
283                       &flash_info[0]);
284 #endif
285         return size;
286 }
287
288 /*-----------------------------------------------------------------------
289  */
290 void flash_print_info(flash_info_t *info)
291 {
292         int i;
293
294         switch (info->flash_id & FLASH_VENDMASK) {
295
296         case (AMD_MANUFACT & FLASH_VENDMASK):
297                 printf("AMD:   ");
298                 switch (info->flash_id & FLASH_TYPEMASK) {
299                 case (AMD_ID_LV016B & FLASH_TYPEMASK):
300                         printf("4x AMD29LV017B (4x16Mbit)\n");
301                         break;
302                 default:
303                         printf("Unknown Chip Type\n");
304                         goto done;
305                         break;
306                 }
307
308                 break;
309         default:
310                 printf("Unknown Vendor ");
311                 break;
312         }
313
314
315         printf("  Size: %ld MB in %d Sectors\n",
316                info->size >> 20, info->sector_count);
317
318         printf("  Sector Start Addresses:");
319         for (i = 0; i < info->sector_count; i++) {
320                 if ((i % 5) == 0) {
321                         printf ("\n   ");
322                 }
323                 printf (" %08lX%s", info->start[i],
324                         info->protect[i] ? " (RO)" : "     ");
325         }
326         printf ("\n");
327
328 done:   ;
329 }
330
331 /*-----------------------------------------------------------------------
332  */
333
334 /* this needs to be inlined, the SWTMRMMILLI register is reset by each read */
335 #define __udelay(delay) \
336 {       \
337         unsigned micro; \
338         unsigned milli=0; \
339         \
340         micro = *(volatile u16*)(0xfffef000+SC520_SWTMRMILLI); \
341          \
342         for (;;) { \
343                 \
344                 milli += *(volatile u16*)(0xfffef000+SC520_SWTMRMILLI); \
345                 micro = *(volatile u16*)(0xfffef000+SC520_SWTMRMICRO); \
346                 \
347                 if ((delay) <= (micro + (milli * 1000))) { \
348                         break; \
349                 } \
350         } \
351 } while (0)
352
353 static u32 _amd_erase_flash(u32 addr, u32 sector)
354 {
355         unsigned elapsed;
356
357         /* Issue erase */
358         *(volatile u32*)(addr + 0x5554) = 0xAAAAAAAA;
359         *(volatile u32*)(addr + 0xaaa8) = 0x55555555;
360         *(volatile u32*)(addr + 0x5554) = 0x80808080;
361         /* And one unlock */
362         *(volatile u32*)(addr + 0x5554) = 0xAAAAAAAA;
363         *(volatile u32*)(addr + 0xaaa8) = 0x55555555;
364         /* Sector erase command comes last */
365         *(volatile u32*)(addr + sector) = 0x30303030;
366
367         elapsed = *(volatile u16*)(0xfffef000+SC520_SWTMRMILLI); /* dummy read */
368         elapsed = 0;
369         __udelay(50);
370         while (((*(volatile u32*)(addr + sector)) & 0x80808080) != 0x80808080) {
371
372                 elapsed += *(volatile u16*)(0xfffef000+SC520_SWTMRMILLI);
373                 if (elapsed > ((CONFIG_SYS_FLASH_ERASE_TOUT/CONFIG_SYS_HZ) * 1000)) {
374                         *(volatile u32*)(addr) = 0xf0f0f0f0;
375                         return 1;
376                 }
377         }
378
379         *(volatile u32*)(addr) = 0xf0f0f0f0;
380
381         return 0;
382 }
383
384 extern int _amd_erase_flash_end;
385 asm ("_amd_erase_flash_end:\n"
386      ".long 0\n");
387
388 int flash_erase(flash_info_t *info, int s_first, int s_last)
389 {
390         u32 (*_erase_flash_ptr)(u32 a, u32 so);
391         int prot;
392         int sect;
393         unsigned size;
394
395         if ((s_first < 0) || (s_first > s_last)) {
396                 if (info->flash_id == FLASH_UNKNOWN) {
397                         printf("- missing\n");
398                 } else {
399                         printf("- no sectors to erase\n");
400                 }
401                 return 1;
402         }
403
404         if ((info->flash_id & FLASH_VENDMASK) == (AMD_MANUFACT & FLASH_VENDMASK)) {
405                 size = (unsigned)&_amd_erase_flash_end - (unsigned)_amd_erase_flash;
406
407                 if (size > PROBE_BUFFER_SIZE) {
408                         printf("_amd_erase_flash() routine too large (%d) %p - %p\n",
409                                size, &_amd_erase_flash_end, _amd_erase_flash);
410                         return 0;
411                 }
412
413                 memcpy(buffer, _amd_erase_flash, size);
414                 _erase_flash_ptr = (void*)buffer;
415
416         }  else {
417                 printf ("Can't erase unknown flash type - aborted\n");
418                 return 1;
419         }
420
421         prot = 0;
422         for (sect=s_first; sect<=s_last; ++sect) {
423                 if (info->protect[sect]) {
424                         prot++;
425                 }
426         }
427
428         if (prot) {
429                 printf ("- Warning: %d protected sectors will not be erased!\n", prot);
430         } else {
431                 printf ("\n");
432         }
433
434
435         /* Start erase on unprotected sectors */
436         for (sect = s_first; sect<=s_last; sect++) {
437
438                 if (info->protect[sect] == 0) { /* not protected */
439                         int res;
440                         int flag;
441
442                         /* Disable interrupts which might cause a timeout here */
443                         flag = disable_interrupts();
444
445                         res = _erase_flash_ptr(info->start[0], info->start[sect]-info->start[0]);
446
447                         /* re-enable interrupts if necessary */
448                         if (flag) {
449                                 enable_interrupts();
450                         }
451
452
453                         if (res) {
454                                 printf("Erase timed out, sector %d\n", sect);
455                                 return res;
456                         }
457
458                         putc('.');
459                 }
460         }
461
462
463         return 0;
464 }
465
466 /*-----------------------------------------------------------------------
467  * Write a word to Flash, returns:
468  * 0 - OK
469  * 1 - write timeout
470  * 2 - Flash not erased
471  */
472 static int _amd_write_word(unsigned start, unsigned dest, unsigned data)
473 {
474         volatile u32 *addr2 = (u32*)start;
475         volatile u32 *dest2 = (u32*)dest;
476         volatile u32 *data2 = (u32*)&data;
477         unsigned elapsed;
478
479         /* Check if Flash is (sufficiently) erased */
480         if ((*((volatile u32*)dest) & (u32)data) != (u32)data) {
481                 return 2;
482         }
483
484         addr2[0x5554] = 0xAAAAAAAA;
485         addr2[0xaaa8] = 0x55555555;
486         addr2[0x5554] = 0xA0A0A0A0;
487
488         dest2[0] = data;
489
490         elapsed = *(volatile u16*)(0xfffef000+SC520_SWTMRMILLI); /* dummy read */
491         elapsed = 0;
492
493         /* data polling for D7 */
494         while ((dest2[0] & 0x80808080) != (data2[0] & 0x80808080)) {
495                 elapsed += *(volatile u16*)(0xfffef000+SC520_SWTMRMILLI);
496                 if (elapsed > ((CONFIG_SYS_FLASH_WRITE_TOUT/CONFIG_SYS_HZ) * 1000)) {
497                         addr2[0] = 0xf0f0f0f0;
498                         return 1;
499                 }
500         }
501
502
503         addr2[0] = 0xf0f0f0f0;
504
505         return 0;
506 }
507
508 extern int _amd_write_word_end;
509 asm ("_amd_write_word_end:\n"
510      ".long 0\n");
511
512
513 /*-----------------------------------------------------------------------
514  * Copy memory to flash, returns:
515  * 0 - OK
516  * 1 - write timeout
517  * 2 - Flash not erased
518  * 3 - Unsupported flash type
519  */
520
521 int write_buff(flash_info_t *info, uchar *src, ulong addr, ulong cnt)
522 {
523         ulong cp, wp, data;
524         int i, l, rc;
525         int flag;
526         u32 (*_write_word_ptr)(unsigned start, unsigned dest, unsigned data);
527         unsigned size;
528
529         if ((info->flash_id & FLASH_VENDMASK) == (AMD_MANUFACT & FLASH_VENDMASK)) {
530                 size = (unsigned)&_amd_write_word_end - (unsigned)_amd_write_word;
531
532                 if (size > PROBE_BUFFER_SIZE) {
533                         printf("_amd_write_word() routine too large (%d) %p - %p\n",
534                                size, &_amd_write_word_end, _amd_write_word);
535                         return 0;
536                 }
537
538                 memcpy(buffer, _amd_write_word, size);
539                 _write_word_ptr = (void*)buffer;
540
541         } else {
542                 printf ("Can't program unknown flash type - aborted\n");
543                 return 3;
544         }
545
546
547         wp = (addr & ~3);       /* get lower word aligned address */
548
549
550         /*
551          * handle unaligned start bytes
552          */
553         if ((l = addr - wp) != 0) {
554                 data = 0;
555                 for (i=0, cp=wp; i<l; ++i, ++cp) {
556                         data |= (*(uchar *)cp) << (8*i);
557                 }
558                 for (; i<4 && cnt>0; ++i) {
559                         data |= *src++ << (8*i);
560                         --cnt;
561                         ++cp;
562                 }
563                 for (; cnt==0 && i<4; ++i, ++cp) {
564                         data |= (*(uchar *)cp)  << (8*i);
565                 }
566
567                 /* Disable interrupts which might cause a timeout here */
568                 flag = disable_interrupts();
569
570                 rc = _write_word_ptr(info->start[0], wp, data);
571
572                 /* re-enable interrupts if necessary */
573                 if (flag) {
574                         enable_interrupts();
575                 }
576                 if (rc != 0) {
577                         return rc;
578                 }
579                 wp += 4;
580         }
581
582         /*
583          * handle word aligned part
584          */
585         while (cnt >= 4) {
586                 data = 0;
587
588                 for (i=0; i<4; ++i) {
589                         data |= *src++ << (8*i);
590                 }
591
592                 /* Disable interrupts which might cause a timeout here */
593                 flag = disable_interrupts();
594
595                 rc = _write_word_ptr(info->start[0], wp, data);
596
597                 /* re-enable interrupts if necessary */
598                 if (flag) {
599                         enable_interrupts();
600                 }
601                 if (rc != 0) {
602                         return rc;
603                 }
604                 wp  += 4;
605                 cnt -= 4;
606         }
607
608         if (cnt == 0) {
609                 return 0;
610         }
611
612         /*
613          * handle unaligned tail bytes
614          */
615         data = 0;
616         for (i=0, cp=wp; i<4 && cnt>0; ++i, ++cp) {
617                 data |= *src++ << (8*i);
618                 --cnt;
619         }
620
621         for (; i<4; ++i, ++cp) {
622                 data |= (*(uchar *)cp) << (8*i);
623         }
624
625         /* Disable interrupts which might cause a timeout here */
626         flag = disable_interrupts();
627
628         rc = _write_word_ptr(info->start[0], wp, data);
629
630         /* re-enable interrupts if necessary */
631         if (flag) {
632                 enable_interrupts();
633         }
634
635         return rc;
636
637 }