]> git.kernelconcepts.de Git - karo-tx-uboot.git/blob - tools/updater/flash_hw.c
Coding Style cleanup: remove trailing white space
[karo-tx-uboot.git] / tools / updater / flash_hw.c
1 /*
2  * (C) Copyright 2001
3  * Josh Huber <huber@mclx.com>, Mission Critical Linux, Inc.
4  *
5  * (C) Copyright 2002
6  * Wolfgang Denk, DENX Software Engineering, wd@denx.de.
7  *
8  * SPDX-License-Identifier:     GPL-2.0+
9  */
10
11 #include <common.h>
12 #include <flash.h>
13 #include <asm/io.h>
14 #include <memio.h>
15
16 /*---------------------------------------------------------------------*/
17 #undef DEBUG_FLASH
18
19 #ifdef DEBUG_FLASH
20 #define DEBUGF(fmt,args...) printf(fmt ,##args)
21 #else
22 #define DEBUGF(fmt,args...)
23 #endif
24 /*---------------------------------------------------------------------*/
25
26 flash_info_t    flash_info[];
27
28 static ulong flash_get_size (ulong addr, flash_info_t *info);
29 static int flash_get_offsets (ulong base, flash_info_t *info);
30 static int write_word (flash_info_t *info, ulong dest, ulong data);
31 static void flash_reset (ulong addr);
32
33 int flash_xd_nest;
34
35 static void flash_to_xd(void)
36 {
37     unsigned char x;
38
39     flash_xd_nest ++;
40
41     if (flash_xd_nest == 1)
42     {
43         DEBUGF("Flash on XD\n");
44         x = pci_read_cfg_byte(0, 0, 0x74);
45         pci_write_cfg_byte(0, 0, 0x74, x|1);
46     }
47 }
48
49 static void flash_to_mem(void)
50 {
51     unsigned char x;
52
53     flash_xd_nest --;
54
55     if (flash_xd_nest == 0)
56     {
57         DEBUGF("Flash on memory bus\n");
58         x = pci_read_cfg_byte(0, 0, 0x74);
59         pci_write_cfg_byte(0, 0, 0x74, x&0xFE);
60     }
61 }
62
63 unsigned long flash_init_old(void)
64 {
65     int i;
66
67     for (i = 0; i < CONFIG_SYS_MAX_FLASH_BANKS; i++)
68     {
69         flash_info[i].flash_id = FLASH_UNKNOWN;
70         flash_info[i].sector_count = 0;
71         flash_info[i].size = 0;
72     }
73
74
75     return 1;
76 }
77
78 unsigned long flash_init (void)
79 {
80         unsigned int i;
81         unsigned long flash_size = 0;
82
83         flash_xd_nest = 0;
84
85         flash_to_xd();
86
87         /* Init: no FLASHes known */
88         for (i=0; i<CONFIG_SYS_MAX_FLASH_BANKS; ++i) {
89                 flash_info[i].flash_id = FLASH_UNKNOWN;
90                 flash_info[i].sector_count = 0;
91                 flash_info[i].size = 0;
92         }
93
94         DEBUGF("\n## Get flash size @ 0x%08x\n", CONFIG_SYS_FLASH_BASE);
95
96         flash_size = flash_get_size (CONFIG_SYS_FLASH_BASE, flash_info);
97
98         DEBUGF("## Flash bank size: %08lx\n", flash_size);
99
100         if (flash_size) {
101 #if CONFIG_SYS_MONITOR_BASE >= CONFIG_SYS_FLASH_BASE && \
102     CONFIG_SYS_MONITOR_BASE < CONFIG_SYS_FLASH_BASE + CONFIG_SYS_FLASH_MAX_SIZE
103                 /* monitor protection ON by default */
104                 flash_protect(FLAG_PROTECT_SET,
105                               CONFIG_SYS_MONITOR_BASE,
106                               CONFIG_SYS_MONITOR_BASE + CONFIG_SYS_MONITOR_LEN - 1,
107                               &flash_info[0]);
108 #endif
109
110 #ifdef CONFIG_ENV_IS_IN_FLASH
111                 /* ENV protection ON by default */
112                 flash_protect(FLAG_PROTECT_SET,
113                               CONFIG_ENV_ADDR,
114                               CONFIG_ENV_ADDR + CONFIG_ENV_SECT_SIZE - 1,
115                               &flash_info[0]);
116 #endif
117
118         } else {
119                 printf ("Warning: the BOOT Flash is not initialised !");
120         }
121
122         flash_to_mem();
123
124         return flash_size;
125 }
126
127 /*
128  * The following code cannot be run from FLASH!
129  */
130 static ulong flash_get_size (ulong addr, flash_info_t *info)
131 {
132         short i;
133         uchar value;
134         uchar *x = (uchar *)addr;
135
136         flash_to_xd();
137
138         /* Write auto select command: read Manufacturer ID */
139         x[0x0555] =  0xAA;
140         __asm__ volatile ("sync\n eieio");
141         x[0x02AA] =  0x55;
142         __asm__ volatile ("sync\n eieio");
143         x[0x0555] =  0x90;
144         __asm__ volatile ("sync\n eieio");
145
146         value = x[0];
147         __asm__ volatile ("sync\n eieio");
148
149         DEBUGF("Manuf. ID @ 0x%08lx: 0x%08x\n", (ulong)addr, value);
150
151         switch (value | (value << 16)) {
152                 case AMD_MANUFACT:
153                         info->flash_id = FLASH_MAN_AMD;
154                         break;
155
156                 case FUJ_MANUFACT:
157                         info->flash_id = FLASH_MAN_FUJ;
158                         break;
159
160                 case STM_MANUFACT:
161                         info->flash_id = FLASH_MAN_STM;
162                         break;
163
164                 default:
165                         info->flash_id = FLASH_UNKNOWN;
166                         info->sector_count = 0;
167                         info->size = 0;
168                         flash_reset (addr);
169                         return 0;
170         }
171
172         value = x[1];
173         __asm__ volatile ("sync\n eieio");
174
175         DEBUGF("Device ID @ 0x%08lx: 0x%08x\n", addr+1, value);
176
177         switch (value) {
178                 case AMD_ID_F040B:
179                         DEBUGF("Am29F040B\n");
180                         info->flash_id += FLASH_AM040;
181                         info->sector_count = 8;
182                         info->size = 0x00080000;
183                         break;                  /* => 512 kB            */
184
185                 case AMD_ID_LV040B:
186                         DEBUGF("Am29LV040B\n");
187                         info->flash_id += FLASH_AM040;
188                         info->sector_count = 8;
189                         info->size = 0x00080000;
190                         break;                  /* => 512 kB            */
191
192                 case AMD_ID_LV400T:
193                         DEBUGF("Am29LV400T\n");
194                         info->flash_id += FLASH_AM400T;
195                         info->sector_count = 11;
196                         info->size = 0x00100000;
197                         break;                  /* => 1 MB              */
198
199                 case AMD_ID_LV400B:
200                         DEBUGF("Am29LV400B\n");
201                         info->flash_id += FLASH_AM400B;
202                         info->sector_count = 11;
203                         info->size = 0x00100000;
204                         break;                  /* => 1 MB              */
205
206                 case AMD_ID_LV800T:
207                         DEBUGF("Am29LV800T\n");
208                         info->flash_id += FLASH_AM800T;
209                         info->sector_count = 19;
210                         info->size = 0x00200000;
211                         break;                  /* => 2 MB              */
212
213                 case AMD_ID_LV800B:
214                         DEBUGF("Am29LV400B\n");
215                         info->flash_id += FLASH_AM800B;
216                         info->sector_count = 19;
217                         info->size = 0x00200000;
218                         break;                  /* => 2 MB              */
219
220                 case AMD_ID_LV160T:
221                         DEBUGF("Am29LV160T\n");
222                         info->flash_id += FLASH_AM160T;
223                         info->sector_count = 35;
224                         info->size = 0x00400000;
225                         break;                  /* => 4 MB              */
226
227                 case AMD_ID_LV160B:
228                         DEBUGF("Am29LV160B\n");
229                         info->flash_id += FLASH_AM160B;
230                         info->sector_count = 35;
231                         info->size = 0x00400000;
232                         break;                  /* => 4 MB              */
233
234                 case AMD_ID_LV320T:
235                         DEBUGF("Am29LV320T\n");
236                         info->flash_id += FLASH_AM320T;
237                         info->sector_count = 67;
238                         info->size = 0x00800000;
239                         break;                  /* => 8 MB              */
240
241 #if 0
242                 /* Has the same ID as AMD_ID_LV320T, to be fixed */
243                 case AMD_ID_LV320B:
244                         DEBUGF("Am29LV320B\n");
245                         info->flash_id += FLASH_AM320B;
246                         info->sector_count = 67;
247                         info->size = 0x00800000;
248                         break;                  /* => 8 MB              */
249 #endif
250
251                 case AMD_ID_LV033C:
252                         DEBUGF("Am29LV033C\n");
253                         info->flash_id += FLASH_AM033C;
254                         info->sector_count = 64;
255                         info->size = 0x01000000;
256                         break;                  /* => 16Mb              */
257
258                 case STM_ID_F040B:
259                         DEBUGF("M29F040B\n");
260                         info->flash_id += FLASH_AM040;
261                         info->sector_count = 8;
262                         info->size = 0x00080000;
263                         break;                  /* => 512 kB            */
264
265                 default:
266                         info->flash_id = FLASH_UNKNOWN;
267                         flash_reset (addr);
268                         flash_to_mem();
269                         return (0);             /* => no or unknown flash */
270
271         }
272
273         if (info->sector_count > CONFIG_SYS_MAX_FLASH_SECT) {
274                 printf ("** ERROR: sector count %d > max (%d) **\n",
275                         info->sector_count, CONFIG_SYS_MAX_FLASH_SECT);
276                 info->sector_count = CONFIG_SYS_MAX_FLASH_SECT;
277         }
278
279         if (! flash_get_offsets (addr, info)) {
280                 flash_reset (addr);
281                 flash_to_mem();
282                 return 0;
283         }
284
285         /* check for protected sectors */
286         for (i = 0; i < info->sector_count; i++) {
287                 /* read sector protection at sector address, (A7 .. A0) = 0x02 */
288                 /* D0 = 1 if protected */
289                 value = in8(info->start[i] + 2);
290                 iobarrier_rw();
291                 info->protect[i] = (value & 1) != 0;
292         }
293
294         /*
295          * Reset bank to read mode
296          */
297         flash_reset (addr);
298
299         flash_to_mem();
300
301         return (info->size);
302 }
303
304 static int flash_get_offsets (ulong base, flash_info_t *info)
305 {
306         unsigned int i;
307
308         switch (info->flash_id & FLASH_TYPEMASK) {
309                 case FLASH_AM040:
310                         /* set sector offsets for uniform sector type   */
311                         for (i = 0; i < info->sector_count; i++) {
312                                 info->start[i] = base + i * info->size /
313                                                             info->sector_count;
314                         }
315                         break;
316                 default:
317                         return 0;
318         }
319
320         return 1;
321 }
322
323 int flash_erase (flash_info_t *info, int s_first, int s_last)
324 {
325         volatile ulong addr = info->start[0];
326         int flag, prot, sect, l_sect;
327         ulong start, now, last;
328
329         flash_to_xd();
330
331         if (s_first < 0 || s_first > s_last) {
332                 if (info->flash_id == FLASH_UNKNOWN) {
333                         printf ("- missing\n");
334                 } else {
335                         printf ("- no sectors to erase\n");
336                 }
337                 flash_to_mem();
338                 return 1;
339         }
340
341         if (info->flash_id == FLASH_UNKNOWN) {
342                 printf ("Can't erase unknown flash type %08lx - aborted\n",
343                         info->flash_id);
344                 flash_to_mem();
345                 return 1;
346         }
347
348         prot = 0;
349         for (sect=s_first; sect<=s_last; ++sect) {
350                 if (info->protect[sect]) {
351                         prot++;
352                 }
353         }
354
355         if (prot) {
356                 printf ("- Warning: %d protected sectors will not be erased!\n",
357                         prot);
358         } else {
359                 printf ("");
360         }
361
362         l_sect = -1;
363
364         /* Disable interrupts which might cause a timeout here */
365         flag = disable_interrupts();
366
367         out8(addr + 0x555, 0xAA);
368         iobarrier_rw();
369         out8(addr + 0x2AA, 0x55);
370         iobarrier_rw();
371         out8(addr + 0x555, 0x80);
372         iobarrier_rw();
373         out8(addr + 0x555, 0xAA);
374         iobarrier_rw();
375         out8(addr + 0x2AA, 0x55);
376         iobarrier_rw();
377
378         /* Start erase on unprotected sectors */
379         for (sect = s_first; sect<=s_last; sect++) {
380                 if (info->protect[sect] == 0) { /* not protected */
381                         addr = info->start[sect];
382                         out8(addr, 0x30);
383                         iobarrier_rw();
384                         l_sect = sect;
385                 }
386         }
387
388         /* re-enable interrupts if necessary */
389         if (flag)
390                 enable_interrupts();
391
392         /* wait at least 80us - let's wait 1 ms */
393         udelay (1000);
394
395         /*
396          * We wait for the last triggered sector
397          */
398         if (l_sect < 0)
399                 goto DONE;
400
401         start = get_timer (0);
402         last  = start;
403         addr = info->start[l_sect];
404
405         DEBUGF ("Start erase timeout: %d\n", CONFIG_SYS_FLASH_ERASE_TOUT);
406
407         while ((in8(addr) & 0x80) != 0x80) {
408                 if ((now = get_timer(start)) > CONFIG_SYS_FLASH_ERASE_TOUT) {
409                         printf ("Timeout\n");
410                         flash_reset (info->start[0]);
411                         flash_to_mem();
412                         return 1;
413                 }
414                 /* show that we're waiting */
415                 if ((now - last) > 1000) {      /* every second */
416                         putc ('.');
417                         last = now;
418                 }
419                 iobarrier_rw();
420         }
421
422 DONE:
423         /* reset to read mode */
424         flash_reset (info->start[0]);
425         flash_to_mem();
426
427         printf (" done\n");
428         return 0;
429 }
430
431 /*
432  * Copy memory to flash, returns:
433  * 0 - OK
434  * 1 - write timeout
435  * 2 - Flash not erased
436  */
437 int write_buff (flash_info_t *info, uchar *src, ulong addr, ulong cnt)
438 {
439         ulong cp, wp, data;
440         int i, l, rc;
441         ulong out_cnt = 0;
442
443         flash_to_xd();
444
445         wp = (addr & ~3);       /* get lower word aligned address */
446
447         /*
448          * handle unaligned start bytes
449          */
450         if ((l = addr - wp) != 0) {
451                 data = 0;
452                 for (i=0, cp=wp; i<l; ++i, ++cp) {
453                         data = (data << 8) | (*(uchar *)cp);
454                 }
455                 for (; i<4 && cnt>0; ++i) {
456                         data = (data << 8) | *src++;
457                         --cnt;
458                         ++cp;
459                 }
460                 for (; cnt==0 && i<4; ++i, ++cp) {
461                         data = (data << 8) | (*(uchar *)cp);
462                 }
463
464                 if ((rc = write_word(info, wp, data)) != 0) {
465                         flash_to_mem();
466                         return (rc);
467                 }
468                 wp += 4;
469         }
470
471         putc(219);
472
473         /*
474          * handle word aligned part
475          */
476         while (cnt >= 4) {
477             if (out_cnt>26214)
478             {
479                 putc(219);
480                 out_cnt = 0;
481             }
482             data = 0;
483             for (i=0; i<4; ++i) {
484                 data = (data << 8) | *src++;
485             }
486             if ((rc = write_word(info, wp, data)) != 0) {
487                 flash_to_mem();
488                 return (rc);
489             }
490             wp  += 4;
491             cnt -= 4;
492             out_cnt += 4;
493         }
494
495         if (cnt == 0) {
496                 flash_to_mem();
497                 return (0);
498         }
499
500         /*
501          * handle unaligned tail bytes
502          */
503         data = 0;
504         for (i=0, cp=wp; i<4 && cnt>0; ++i, ++cp) {
505                 data = (data << 8) | *src++;
506                 --cnt;
507         }
508         for (; i<4; ++i, ++cp) {
509                 data = (data << 8) | (*(uchar *)cp);
510         }
511
512         flash_to_mem();
513         return (write_word(info, wp, data));
514 }
515
516 /*
517  * Write a word to Flash, returns:
518  * 0 - OK
519  * 1 - write timeout
520  * 2 - Flash not erased
521  */
522 static int write_word (flash_info_t *info, ulong dest, ulong data)
523 {
524         volatile ulong addr = info->start[0];
525         ulong start;
526         int i;
527
528         flash_to_xd();
529
530         /* Check if Flash is (sufficiently) erased */
531         if ((in32(dest) & data) != data) {
532                 flash_to_mem();
533                 return (2);
534         }
535
536         /* write each byte out */
537         for (i = 0; i < 4; i++) {
538                 char *data_ch = (char *)&data;
539                 int flag = disable_interrupts();
540
541                 out8(addr + 0x555, 0xAA);
542                 iobarrier_rw();
543                 out8(addr + 0x2AA, 0x55);
544                 iobarrier_rw();
545                 out8(addr + 0x555, 0xA0);
546                 iobarrier_rw();
547                 out8(dest+i, data_ch[i]);
548                 iobarrier_rw();
549
550                 /* re-enable interrupts if necessary */
551                 if (flag)
552                         enable_interrupts();
553
554                 /* data polling for D7 */
555                 start = get_timer (0);
556                 while ((in8(dest+i) & 0x80) != (data_ch[i] & 0x80)) {
557                         if (get_timer(start) > CONFIG_SYS_FLASH_WRITE_TOUT) {
558                                 flash_reset (addr);
559                                 flash_to_mem();
560                                 return (1);
561                         }
562                         iobarrier_rw();
563                 }
564         }
565
566         flash_reset (addr);
567         flash_to_mem();
568         return (0);
569 }
570
571 /*
572  * Reset bank to read mode
573  */
574 static void flash_reset (ulong addr)
575 {
576         flash_to_xd();
577         out8(addr, 0xF0);       /* reset bank */
578         iobarrier_rw();
579         flash_to_mem();
580 }
581
582 void flash_print_info (flash_info_t *info)
583 {
584         int i;
585
586         if (info->flash_id == FLASH_UNKNOWN) {
587                 printf ("missing or unknown FLASH type\n");
588                 return;
589         }
590
591         switch (info->flash_id & FLASH_VENDMASK) {
592         case FLASH_MAN_AMD:     printf ("AMD ");                break;
593         case FLASH_MAN_FUJ:     printf ("FUJITSU ");            break;
594         case FLASH_MAN_BM:      printf ("BRIGHT MICRO ");       break;
595         case FLASH_MAN_STM:     printf ("SGS THOMSON ");        break;
596         default:                printf ("Unknown Vendor ");     break;
597         }
598
599         switch (info->flash_id & FLASH_TYPEMASK) {
600         case FLASH_AM040:       printf ("29F040 or 29LV040 (4 Mbit, uniform sectors)\n");
601                                 break;
602         case FLASH_AM400B:      printf ("AM29LV400B (4 Mbit, bottom boot sect)\n");
603                                 break;
604         case FLASH_AM400T:      printf ("AM29LV400T (4 Mbit, top boot sector)\n");
605                                 break;
606         case FLASH_AM800B:      printf ("AM29LV800B (8 Mbit, bottom boot sect)\n");
607                                 break;
608         case FLASH_AM800T:      printf ("AM29LV800T (8 Mbit, top boot sector)\n");
609                                 break;
610         case FLASH_AM160B:      printf ("AM29LV160B (16 Mbit, bottom boot sect)\n");
611                                 break;
612         case FLASH_AM160T:      printf ("AM29LV160T (16 Mbit, top boot sector)\n");
613                                 break;
614         case FLASH_AM320B:      printf ("AM29LV320B (32 Mbit, bottom boot sect)\n");
615                                 break;
616         case FLASH_AM320T:      printf ("AM29LV320T (32 Mbit, top boot sector)\n");
617                                 break;
618         default:                printf ("Unknown Chip Type\n");
619                                 break;
620         }
621
622         if (info->size % 0x100000 == 0) {
623                 printf ("  Size: %ld MB in %d Sectors\n",
624                         info->size / 0x100000, info->sector_count);
625         } else if (info->size % 0x400 == 0) {
626                 printf ("  Size: %ld KB in %d Sectors\n",
627                         info->size / 0x400, info->sector_count);
628         } else {
629                 printf ("  Size: %ld B in %d Sectors\n",
630                         info->size, info->sector_count);
631         }
632
633         printf ("  Sector Start Addresses:");
634         for (i=0; i<info->sector_count; ++i) {
635                 if ((i % 5) == 0)
636                         printf ("\n   ");
637                 printf (" %08lX%s",
638                         info->start[i],
639                         info->protect[i] ? " (RO)" : "     "
640                 );
641         }
642         printf ("\n");
643 }