]> git.kernelconcepts.de Git - karo-tx-uboot.git/blob - board/etin/debris/flash.c
Coding Style cleanup: replace leading SPACEs by TABs
[karo-tx-uboot.git] / board / etin / debris / flash.c
1 /*
2  * board/eva/flash.c
3  *
4  * (C) Copyright 2002
5  * Sangmoon Kim, Etin Systems, dogoil@etinsys.com.
6  *
7  * SPDX-License-Identifier:     GPL-2.0+
8  */
9
10 #include <common.h>
11 #include <asm/processor.h>
12 #include <asm/pci_io.h>
13 #include <mpc824x.h>
14 #include <asm/mmu.h>
15
16 int (*do_flash_erase)(flash_info_t*, uint32_t, uint32_t);
17 int (*write_dword)(flash_info_t*, ulong, uint64_t);
18
19 typedef uint64_t cfi_word;
20
21 #define cfi_read(flash, addr) *((volatile cfi_word*)(flash->start[0] + addr))
22
23 #define cfi_write(flash, val, addr) \
24         move64((cfi_word*)&val, \
25                         (cfi_word*)(flash->start[0] + addr))
26
27 #define CMD(x) ((((cfi_word)x)<<48)|(((cfi_word)x)<<32)|(((cfi_word)x)<<16)|(((cfi_word)x)))
28
29 static void write32(unsigned long addr, uint32_t value)
30 {
31         *(volatile uint32_t*)(addr) = value;
32         asm volatile("sync");
33 }
34
35 static uint32_t read32(unsigned long addr)
36 {
37         uint32_t value;
38         value = *(volatile uint32_t*)addr;
39         asm volatile("sync");
40         return value;
41 }
42
43 static cfi_word cfi_cmd(flash_info_t *flash, uint8_t cmd, uint32_t addr)
44 {
45         uint32_t base = flash->start[0];
46         uint32_t val=(cmd << 16) | cmd;
47         addr <<= 3;
48         write32(base + addr, val);
49         return addr;
50 }
51
52 static uint16_t cfi_read_query(flash_info_t *flash, uint32_t addr)
53 {
54         uint32_t base = flash->start[0];
55         addr <<= 3;
56         return (uint16_t)read32(base + addr);
57 }
58
59 flash_info_t    flash_info[CONFIG_SYS_MAX_FLASH_BANKS]; /* info for FLASH chips */
60
61 static void move64(uint64_t *src, uint64_t *dest)
62 {
63         asm volatile("lfd  0, 0(3)\n\t" /* fpr0   =  *scr       */
64          "stfd 0, 0(4)"         /* *dest  =  fpr0       */
65          : : : "fr0" );         /* Clobbers fr0         */
66         return;
67 }
68
69 static int cfi_write_dword(flash_info_t *flash, ulong dest, cfi_word data)
70 {
71         unsigned long start;
72         cfi_word status = 0;
73
74         status = cfi_read(flash, dest);
75         data &= status;
76
77         cfi_cmd(flash, 0x40, 0);
78         cfi_write(flash, data, dest);
79
80         udelay(10);
81         start = get_timer (0);
82         for(;;) {
83                 status = cfi_read(flash, dest);
84                 status &= CMD(0x80);
85                 if(status == CMD(0x80))
86                         break;
87                 if (get_timer(start) > CONFIG_SYS_FLASH_WRITE_TOUT) {
88                         cfi_cmd(flash, 0xff, 0);
89                         return 1;
90                 }
91                 udelay(1);
92         }
93         cfi_cmd(flash, 0xff, 0);
94
95         return 0;
96 }
97
98 static int jedec_write_dword (flash_info_t *flash, ulong dest, cfi_word data)
99 {
100         ulong start;
101         cfi_word status = 0;
102
103         status = cfi_read(flash, dest);
104         if(status != CMD(0xffff)) return 2;
105
106         cfi_cmd(flash, 0xaa, 0x555);
107         cfi_cmd(flash, 0x55, 0x2aa);
108         cfi_cmd(flash, 0xa0, 0x555);
109
110         cfi_write(flash, data, dest);
111
112         udelay(10);
113         start = get_timer (0);
114         status = ~data;
115         while(status != data) {
116                 if (get_timer(start) > CONFIG_SYS_FLASH_WRITE_TOUT)
117                         return 1;
118                 status = cfi_read(flash, dest);
119                 udelay(1);
120         }
121         return 0;
122 }
123
124 static __inline__ unsigned long get_msr(void)
125 {
126         unsigned long msr;
127         __asm__ __volatile__ ("mfmsr %0" : "=r" (msr) :);
128         return msr;
129 }
130
131 static __inline__ void set_msr(unsigned long msr)
132 {
133         __asm__ __volatile__ ("mtmsr %0" : : "r" (msr));
134 }
135
136 int write_buff (flash_info_t *flash, uchar *src, ulong addr, ulong cnt)
137 {
138         ulong wp;
139         int i, s, l, rc;
140         cfi_word data;
141         uint8_t *t = (uint8_t*)&data;
142         unsigned long base = flash->start[0];
143         uint32_t msr;
144
145         if (flash->flash_id == FLASH_UNKNOWN)
146                 return 4;
147
148         if (cnt == 0)
149                 return 0;
150
151         addr -= base;
152
153         msr = get_msr();
154         set_msr(msr|MSR_FP);
155
156         wp = (addr & ~7);   /* get lower word aligned address */
157
158         if((addr-wp) != 0) {
159                 data = cfi_read(flash, wp);
160                 s = addr & 7;
161                 l = ( cnt < (8-s) ) ? cnt : (8-s);
162                 for(i = 0; i < l; i++)
163                         t[s+i] = *src++;
164                 if ((rc = write_dword(flash, wp, data)) != 0)
165                         goto DONE;
166                 wp += 8;
167                 cnt -= l;
168         }
169
170         while (cnt >= 8) {
171                 for (i = 0; i < 8; i++)
172                         t[i] = *src++;
173                 if ((rc = write_dword(flash, wp, data)) != 0)
174                         goto DONE;
175                 wp  += 8;
176                 cnt -= 8;
177         }
178
179         if (cnt == 0) {
180                 rc = 0;
181                 goto DONE;
182         }
183
184         data = cfi_read(flash, wp);
185         for(i = 0; i < cnt; i++)
186                 t[i] = *src++;
187         rc = write_dword(flash, wp, data);
188 DONE:
189         set_msr(msr);
190         return rc;
191 }
192
193 static int cfi_erase_oneblock(flash_info_t *flash, uint32_t sect)
194 {
195         int sa;
196         int flag;
197         ulong start, last, now;
198         cfi_word status;
199
200         flag = disable_interrupts();
201
202         sa = (flash->start[sect] - flash->start[0]);
203         write32(flash->start[sect], 0x00200020);
204         write32(flash->start[sect], 0x00d000d0);
205
206         if (flag)
207                 enable_interrupts();
208
209         udelay(1000);
210         start = get_timer (0);
211         last  = start;
212
213         for (;;) {
214                 status = cfi_read(flash, sa);
215                 status &= CMD(0x80);
216                 if (status == CMD(0x80))
217                         break;
218                 if ((now = get_timer(start)) > CONFIG_SYS_FLASH_ERASE_TOUT) {
219                         cfi_cmd(flash, 0xff, 0);
220                         printf ("Timeout\n");
221                         return ERR_TIMOUT;
222                 }
223
224                 if ((now - last) > 1000) {
225                         serial_putc ('.');
226                         last = now;
227                 }
228                 udelay(10);
229         }
230         cfi_cmd(flash, 0xff, 0);
231         return ERR_OK;
232 }
233
234 static int cfi_erase(flash_info_t *flash, uint32_t s_first, uint32_t s_last)
235 {
236         int sect;
237         int rc = ERR_OK;
238
239         for (sect = s_first; sect <= s_last; sect++) {
240                 if (flash->protect[sect] == 0) {
241                         rc = cfi_erase_oneblock(flash, sect);
242                         if (rc != ERR_OK) break;
243                 }
244         }
245         printf (" done\n");
246         return rc;
247 }
248
249 static int jedec_erase(flash_info_t *flash, uint32_t s_first, uint32_t s_last)
250 {
251         int sect;
252         cfi_word status;
253         int sa = -1;
254         int flag;
255         ulong start, last, now;
256
257         flag = disable_interrupts();
258
259         cfi_cmd(flash, 0xaa, 0x555);
260         cfi_cmd(flash, 0x55, 0x2aa);
261         cfi_cmd(flash, 0x80, 0x555);
262         cfi_cmd(flash, 0xaa, 0x555);
263         cfi_cmd(flash, 0x55, 0x2aa);
264         for ( sect = s_first; sect <= s_last; sect++) {
265                 if (flash->protect[sect] == 0) {
266                         sa = flash->start[sect] - flash->start[0];
267                         write32(flash->start[sect], 0x00300030);
268                 }
269         }
270         if (flag)
271                 enable_interrupts();
272
273         if (sa < 0)
274                 goto DONE;
275
276         udelay (1000);
277         start = get_timer (0);
278         last  = start;
279         for(;;) {
280                 status = cfi_read(flash, sa);
281                 if (status == CMD(0xffff))
282                         break;
283
284                 if ((now = get_timer(start)) > CONFIG_SYS_FLASH_ERASE_TOUT) {
285                         printf ("Timeout\n");
286                         return ERR_TIMOUT;
287                 }
288
289                 if ((now - last) > 1000) {
290                         serial_putc ('.');
291                         last = now;
292                 }
293                 udelay(10);
294         }
295 DONE:
296         cfi_cmd(flash, 0xf0, 0);
297
298         printf (" done\n");
299
300         return ERR_OK;
301 }
302
303 int flash_erase (flash_info_t *flash, int s_first, int s_last)
304 {
305         int sect;
306         int prot;
307
308         if ((s_first < 0) || (s_first > s_last)) {
309                 if (flash->flash_id == FLASH_UNKNOWN)
310                         printf ("- missing\n");
311                 else
312                         printf ("- no sectors to erase\n");
313                 return ERR_NOT_ERASED;
314         }
315         if (flash->flash_id == FLASH_UNKNOWN) {
316                 printf ("Can't erase unknown flash type - aborted\n");
317                 return ERR_NOT_ERASED;
318         }
319
320         prot = 0;
321         for (sect = s_first; sect <= s_last; sect++)
322                 if (flash->protect[sect]) prot++;
323
324         if (prot)
325                 printf ("- Warning: %d protected sectors will not be erased!\n",
326                                                                 prot);
327         else
328                 printf ("\n");
329
330         return do_flash_erase(flash, s_first, s_last);
331 }
332
333 struct jedec_flash_info {
334         const uint16_t mfr_id;
335         const uint16_t dev_id;
336         const char *name;
337         const int DevSize;
338         const int InterfaceDesc;
339         const int NumEraseRegions;
340         const ulong regions[4];
341 };
342
343 #define ERASEINFO(size,blocks) (size<<8)|(blocks-1)
344
345 #define SIZE_1MiB 20
346 #define SIZE_2MiB 21
347 #define SIZE_4MiB 22
348
349 static const struct jedec_flash_info jedec_table[] = {
350         {
351                 mfr_id: (uint16_t)AMD_MANUFACT,
352                 dev_id: (uint16_t)AMD_ID_LV800T,
353                 name: "AMD AM29LV800T",
354                 DevSize: SIZE_1MiB,
355                 NumEraseRegions: 4,
356                 regions: {ERASEINFO(0x10000,15),
357                           ERASEINFO(0x08000,1),
358                           ERASEINFO(0x02000,2),
359                           ERASEINFO(0x04000,1)
360                 }
361         }, {
362                 mfr_id: (uint16_t)AMD_MANUFACT,
363                 dev_id: (uint16_t)AMD_ID_LV800B,
364                 name: "AMD AM29LV800B",
365                 DevSize: SIZE_1MiB,
366                 NumEraseRegions: 4,
367                 regions: {ERASEINFO(0x10000,15),
368                           ERASEINFO(0x08000,1),
369                           ERASEINFO(0x02000,2),
370                           ERASEINFO(0x04000,1)
371                 }
372         }, {
373                 mfr_id: (uint16_t)AMD_MANUFACT,
374                 dev_id: (uint16_t)AMD_ID_LV160T,
375                 name: "AMD AM29LV160T",
376                 DevSize: SIZE_2MiB,
377                 NumEraseRegions: 4,
378                 regions: {ERASEINFO(0x10000,31),
379                           ERASEINFO(0x08000,1),
380                           ERASEINFO(0x02000,2),
381                           ERASEINFO(0x04000,1)
382                 }
383         }, {
384                 mfr_id: (uint16_t)AMD_MANUFACT,
385                 dev_id: (uint16_t)AMD_ID_LV160B,
386                 name: "AMD AM29LV160B",
387                 DevSize: SIZE_2MiB,
388                 NumEraseRegions: 4,
389                 regions: {ERASEINFO(0x04000,1),
390                           ERASEINFO(0x02000,2),
391                           ERASEINFO(0x08000,1),
392                           ERASEINFO(0x10000,31)
393                 }
394         }, {
395                 mfr_id: (uint16_t)AMD_MANUFACT,
396                 dev_id: (uint16_t)AMD_ID_LV320T,
397                 name: "AMD AM29LV320T",
398                 DevSize: SIZE_4MiB,
399                 NumEraseRegions: 2,
400                 regions: {ERASEINFO(0x10000,63),
401                           ERASEINFO(0x02000,8)
402                 }
403
404         }, {
405                 mfr_id: (uint16_t)AMD_MANUFACT,
406                 dev_id: (uint16_t)AMD_ID_LV320B,
407                 name: "AMD AM29LV320B",
408                 DevSize: SIZE_4MiB,
409                 NumEraseRegions: 2,
410                 regions: {ERASEINFO(0x02000,8),
411                           ERASEINFO(0x10000,63)
412                 }
413         }
414 };
415
416 static ulong cfi_init(uint32_t base,  flash_info_t *flash)
417 {
418         int sector;
419         int block;
420         int block_count;
421         int offset = 0;
422         int reverse = 0;
423         int primary;
424         int mfr_id;
425         int dev_id;
426
427         flash->start[0] = base;
428         cfi_cmd(flash, 0xF0, 0);
429         cfi_cmd(flash, 0x98, 0);
430         if ( !( cfi_read_query(flash, 0x10) == 'Q' &&
431                 cfi_read_query(flash, 0x11) == 'R' &&
432                 cfi_read_query(flash, 0x12) == 'Y' )) {
433                 cfi_cmd(flash, 0xff, 0);
434                 return 0;
435         }
436
437         flash->size = 1 << cfi_read_query(flash, 0x27);
438         flash->size *= 4;
439         block_count = cfi_read_query(flash, 0x2c);
440         primary = cfi_read_query(flash, 0x15);
441         if ( cfi_read_query(flash, primary + 4) == 0x30)
442                 reverse = (cfi_read_query(flash, 0x1) & 0x01);
443         else
444                 reverse = (cfi_read_query(flash, primary+15) == 3);
445
446         flash->sector_count = 0;
447
448         for ( block = reverse ? block_count - 1 : 0;
449                       reverse ? block >= 0      : block < block_count;
450                       reverse ? block--         : block ++) {
451                 int sector_size =
452                         (cfi_read_query(flash, 0x2d + block*4+2) |
453                         (cfi_read_query(flash, 0x2d + block*4+3) << 8)) << 8;
454                 int sector_count =
455                         (cfi_read_query(flash, 0x2d + block*4+0) |
456                         (cfi_read_query(flash, 0x2d + block*4+1) << 8)) + 1;
457                 for(sector = 0; sector < sector_count; sector++) {
458                         flash->start[flash->sector_count++] = base + offset;
459                         offset += sector_size * 4;
460                 }
461         }
462         mfr_id = cfi_read_query(flash, 0x00);
463         dev_id = cfi_read_query(flash, 0x01);
464
465         cfi_cmd(flash, 0xff, 0);
466
467         flash->flash_id = (mfr_id << 16) | dev_id;
468
469         for (sector = 0; sector < flash->sector_count; sector++) {
470                 write32(flash->start[sector], 0x00600060);
471                 write32(flash->start[sector], 0x00d000d0);
472         }
473         cfi_cmd(flash, 0xff, 0);
474
475         for (sector = 0; sector < flash->sector_count; sector++)
476                 flash->protect[sector] = 0;
477
478         do_flash_erase = cfi_erase;
479         write_dword = cfi_write_dword;
480
481         return flash->size;
482 }
483
484 static ulong jedec_init(unsigned long base, flash_info_t *flash)
485 {
486         int i;
487         int block, block_count;
488         int sector, offset;
489         int mfr_id, dev_id;
490         flash->start[0] = base;
491         cfi_cmd(flash, 0xF0, 0x000);
492         cfi_cmd(flash, 0xAA, 0x555);
493         cfi_cmd(flash, 0x55, 0x2AA);
494         cfi_cmd(flash, 0x90, 0x555);
495         mfr_id = cfi_read_query(flash, 0x000);
496         dev_id = cfi_read_query(flash, 0x0001);
497         cfi_cmd(flash, 0xf0, 0x000);
498
499         for(i=0; i<sizeof(jedec_table)/sizeof(struct jedec_flash_info); i++) {
500                 if((jedec_table[i].mfr_id == mfr_id) &&
501                         (jedec_table[i].dev_id == dev_id)) {
502
503                         flash->flash_id = (mfr_id << 16) | dev_id;
504                         flash->size = 1 << jedec_table[0].DevSize;
505                         flash->size *= 4;
506                         block_count = jedec_table[i].NumEraseRegions;
507                         offset = 0;
508                         flash->sector_count = 0;
509                         for (block = 0; block < block_count; block++) {
510                                 int sector_size = jedec_table[i].regions[block];
511                                 int sector_count = (sector_size & 0xff) + 1;
512                                 sector_size >>= 8;
513                                 for (sector=0; sector<sector_count; sector++) {
514                                         flash->start[flash->sector_count++] =
515                                                 base + offset;
516                                         offset += sector_size * 4;
517                                 }
518                         }
519                         break;
520                 }
521         }
522
523         for (sector = 0; sector < flash->sector_count; sector++)
524                 flash->protect[sector] = 0;
525
526         do_flash_erase = jedec_erase;
527         write_dword = jedec_write_dword;
528
529         return flash->size;
530 }
531
532 inline void mtibat1u(unsigned int x)
533 {
534         __asm__ __volatile__ ("mtspr   530, %0" :: "r" (x));
535 }
536
537 inline void mtibat1l(unsigned int x)
538 {
539         __asm__ __volatile__ ("mtspr   531, %0" :: "r" (x));
540 }
541
542 inline void mtdbat1u(unsigned int x)
543 {
544         __asm__ __volatile__ ("mtspr   538, %0" :: "r" (x));
545 }
546
547 inline void mtdbat1l(unsigned int x)
548 {
549         __asm__ __volatile__ ("mtspr   539, %0" :: "r" (x));
550 }
551
552 unsigned long flash_init (void)
553 {
554         unsigned long size = 0;
555         int i;
556         unsigned int msr;
557
558         /* BAT1 */
559         CONFIG_WRITE_WORD(ERCR3, 0x0C00000C);
560         CONFIG_WRITE_WORD(ERCR4, 0x0800000C);
561         msr = get_msr();
562         set_msr(msr & ~(MSR_IR | MSR_DR));
563         mtibat1l(0x70000000 | BATL_PP_10 | BATL_CACHEINHIBIT);
564         mtibat1u(0x70000000 | BATU_BL_256M | BATU_VS | BATU_VP);
565         mtdbat1l(0x70000000 | BATL_PP_10 | BATL_CACHEINHIBIT);
566         mtdbat1u(0x70000000 | BATU_BL_256M | BATU_VS | BATU_VP);
567         set_msr(msr);
568
569         for (i = 0; i < CONFIG_SYS_MAX_FLASH_BANKS; i++)
570                 flash_info[i].flash_id = FLASH_UNKNOWN;
571         size = cfi_init(FLASH_BASE0_PRELIM, &flash_info[0]);
572         if (!size)
573                 size = jedec_init(FLASH_BASE0_PRELIM, &flash_info[0]);
574
575         if (flash_info[0].flash_id == FLASH_UNKNOWN)
576                 printf ("# Unknown FLASH on Bank 1 - Size = 0x%08lx = %ld MB\n",
577                         size, size<<20);
578
579         return size;
580 }
581
582 void flash_print_info  (flash_info_t *flash)
583 {
584         int i;
585         int k;
586         int size;
587         int erased;
588         volatile unsigned long *p;
589
590         if (flash->flash_id == FLASH_UNKNOWN) {
591                 printf ("missing or unknown FLASH type\n");
592                 flash_init();
593         }
594
595         if (flash->flash_id == FLASH_UNKNOWN) {
596                 printf ("missing or unknown FLASH type\n");
597                 return;
598         }
599
600         switch (((flash->flash_id) >> 16) & 0xff) {
601         case 0x01:
602                 printf ("AMD ");
603                 break;
604         case 0x04:
605                 printf("FUJITSU ");
606                 break;
607         case 0x20:
608                 printf("STM ");
609                 break;
610         case 0xBF:
611                 printf("SST ");
612                 break;
613         case 0x89:
614         case 0xB0:
615                 printf("INTEL ");
616                 break;
617         default:
618                 printf ("Unknown Vendor ");
619                 break;
620         }
621
622         switch ((flash->flash_id) & 0xffff) {
623         case (uint16_t)AMD_ID_LV800T:
624                 printf ("AM29LV800T\n");
625                 break;
626         case (uint16_t)AMD_ID_LV800B:
627                 printf ("AM29LV800B\n");
628                 break;
629         case (uint16_t)AMD_ID_LV160T:
630                 printf ("AM29LV160T\n");
631                 break;
632         case (uint16_t)AMD_ID_LV160B:
633                 printf ("AM29LV160B\n");
634                 break;
635         case (uint16_t)AMD_ID_LV320T:
636                 printf ("AM29LV320T\n");
637                 break;
638         case (uint16_t)AMD_ID_LV320B:
639                 printf ("AM29LV320B\n");
640                 break;
641         case (uint16_t)INTEL_ID_28F800C3T:
642                 printf ("28F800C3T\n");
643                 break;
644         case (uint16_t)INTEL_ID_28F800C3B:
645                 printf ("28F800C3B\n");
646                 break;
647         case (uint16_t)INTEL_ID_28F160C3T:
648                 printf ("28F160C3T\n");
649                 break;
650         case (uint16_t)INTEL_ID_28F160C3B:
651                 printf ("28F160C3B\n");
652                 break;
653         case (uint16_t)INTEL_ID_28F320C3T:
654                 printf ("28F320C3T\n");
655                 break;
656         case (uint16_t)INTEL_ID_28F320C3B:
657                 printf ("28F320C3B\n");
658                 break;
659         case (uint16_t)INTEL_ID_28F640C3T:
660                 printf ("28F640C3T\n");
661                 break;
662         case (uint16_t)INTEL_ID_28F640C3B:
663                 printf ("28F640C3B\n");
664                 break;
665         default:
666                 printf ("Unknown Chip Type\n");
667                 break;
668         }
669
670         if (flash->size >= (1 << 20)) {
671                 printf ("  Size: %ld MB in %d Sectors\n",
672                                 flash->size >> 20, flash->sector_count);
673         } else {
674                 printf ("  Size: %ld kB in %d Sectors\n",
675                                 flash->size >> 10, flash->sector_count);
676         }
677
678         printf ("  Sector Start Addresses:");
679         for (i = 0; i < flash->sector_count; ++i) {
680                 /* Check if whole sector is erased*/
681                 if (i != (flash->sector_count-1))
682                         size = flash->start[i+1] - flash->start[i];
683                 else
684                         size = flash->start[0] + flash->size - flash->start[i];
685
686                 erased = 1;
687                 p = (volatile unsigned long *)flash->start[i];
688                 size = size >> 2;        /* divide by 4 for longword access */
689                 for (k=0; k<size; k++) {
690                         if (*p++ != 0xffffffff) {
691                                 erased = 0;
692                                 break;
693                         }
694                 }
695
696                 if ((i % 5) == 0)
697                         printf ("\n   ");
698
699                 printf (" %08lX%s%s",
700                         flash->start[i],
701                         erased ? " E" : "  ",
702                         flash->protect[i] ? "RO " : "   ");
703         }
704         printf ("\n");
705 }