]> git.kernelconcepts.de Git - karo-tx-uboot.git/blob - board/snmc/qs850/flash.c
Merge branch 'u-boot/master' into u-boot-arm/master
[karo-tx-uboot.git] / board / snmc / qs850 / flash.c
1 /*
2  * (C) Copyright 2003
3  * MuLogic B.V.
4  *
5  * (C) Copyright 2001
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 <asm/ppc4xx.h>
13 #include <asm/u-boot.h>
14 #include <asm/processor.h>
15
16 flash_info_t flash_info[CONFIG_SYS_MAX_FLASH_BANKS]; /* info for FLASH chips */
17
18
19 #define FLASH_WORD_SIZE unsigned long
20 #define FLASH_ID_MASK 0xFFFFFFFF
21
22 /*-----------------------------------------------------------------------
23  * Functions
24  */
25 /* stolen from esteem192e/flash.c */
26 ulong flash_get_size (volatile FLASH_WORD_SIZE *addr, flash_info_t *info);
27
28 static int write_word (flash_info_t *info, ulong dest, ulong data);
29 static void flash_get_offsets (ulong base, flash_info_t *info);
30
31
32 /*-----------------------------------------------------------------------
33  */
34
35 unsigned long flash_init (void)
36 {
37         unsigned long size_b0, size_b1;
38         int i;
39         uint pbcr;
40         unsigned long base_b0, base_b1;
41         volatile FLASH_WORD_SIZE* flash_base;
42
43         /* Init: no FLASHes known */
44         for (i=0; i<CONFIG_SYS_MAX_FLASH_BANKS; ++i) {
45                 flash_info[i].flash_id = FLASH_UNKNOWN;
46         }
47
48         /* Static FLASH Bank configuration here */
49         /* Test for 8M Flash first */
50         debug ("\n## Get flash bank 1 size @ 0x%08x\n",FLASH_BASE0_8M_PRELIM);
51         flash_base = (volatile FLASH_WORD_SIZE*)(FLASH_BASE0_8M_PRELIM);
52         size_b0 = flash_get_size(flash_base, &flash_info[0]);
53
54         if (flash_info[0].flash_id == FLASH_UNKNOWN) {
55                 printf ("## Unknown FLASH on Bank 0 - Size = 0x%08lx = %ld MB\n",
56                 size_b0, size_b0<<20);
57                 return 0;
58         }
59
60         if (size_b0 < 8*1024*1024) {
61                 /* Not quite 8M, try 4M Flash base address */
62                 debug ("\n## Get flash bank 1 size @ 0x%08x\n",FLASH_BASE0_4M_PRELIM);
63                 flash_base = (volatile FLASH_WORD_SIZE*)(FLASH_BASE0_4M_PRELIM);
64                 size_b0 = flash_get_size(flash_base, &flash_info[0]);
65         }
66
67         if (flash_info[0].flash_id == FLASH_UNKNOWN) {
68                 printf ("## Unknown FLASH on Bank 0 - Size = 0x%08lx = %ld MB\n",
69                 size_b0, size_b0<<20);
70                 return 0;
71         }
72
73         /* Only one bank */
74         if (CONFIG_SYS_MAX_FLASH_BANKS == 1) {
75                 /* Setup offsets */
76                 flash_get_offsets ((ulong)flash_base, &flash_info[0]);
77
78                 /* Monitor protection ON by default */
79                 (void)flash_protect(FLAG_PROTECT_SET, CONFIG_SYS_MONITOR_BASE,
80                         CONFIG_SYS_MONITOR_BASE+CONFIG_SYS_MONITOR_LEN-1, &flash_info[0]);
81                 size_b1 = 0 ;
82                 flash_info[0].size = size_b0;
83                 return(size_b0);
84         }
85
86         /* We have 2 banks */
87         size_b1 = flash_get_size(flash_base, &flash_info[1]);
88
89         /* Re-do sizing to get full correct info */
90         if (size_b1) {
91                 mtdcr(EBC0_CFGADDR, PB0CR);
92                 pbcr = mfdcr(EBC0_CFGDATA);
93                 mtdcr(EBC0_CFGADDR, PB0CR);
94                 base_b1 = -size_b1;
95                 pbcr = (pbcr & 0x0001ffff) | base_b1 | (((size_b1/1024/1024)-1)<<17);
96                 mtdcr(EBC0_CFGDATA, pbcr);
97         }
98
99         if (size_b0) {
100                 mtdcr(EBC0_CFGADDR, PB1CR);
101                 pbcr = mfdcr(EBC0_CFGDATA);
102                 mtdcr(EBC0_CFGADDR, PB1CR);
103                 base_b0 = base_b1 - size_b0;
104                 pbcr = (pbcr & 0x0001ffff) | base_b0 | (((size_b0/1024/1024)-1)<<17);
105                 mtdcr(EBC0_CFGDATA, pbcr);
106         }
107
108         size_b0 = flash_get_size((volatile FLASH_WORD_SIZE *)base_b0, &flash_info[0]);
109         flash_get_offsets (base_b0, &flash_info[0]);
110
111         /* monitor protection ON by default */
112         (void)flash_protect(FLAG_PROTECT_SET, CONFIG_SYS_MONITOR_BASE,
113                 CONFIG_SYS_MONITOR_BASE+CONFIG_SYS_MONITOR_LEN-1, &flash_info[0]);
114
115         if (size_b1) {
116                 /* Re-do sizing to get full correct info */
117                 size_b1 = flash_get_size((volatile FLASH_WORD_SIZE *)base_b1, &flash_info[1]);
118                 flash_get_offsets (base_b1, &flash_info[1]);
119
120                 /* monitor protection ON by default */
121                 (void)flash_protect(FLAG_PROTECT_SET, base_b1+size_b1-CONFIG_SYS_MONITOR_LEN,
122                         base_b1+size_b1-1, &flash_info[1]);
123
124                 /* monitor protection OFF by default (one is enough) */
125                 (void)flash_protect(FLAG_PROTECT_CLEAR, base_b0+size_b0-CONFIG_SYS_MONITOR_LEN,
126                         base_b0+size_b0-1, &flash_info[0]);
127         } else {
128                 flash_info[1].flash_id = FLASH_UNKNOWN;
129                 flash_info[1].sector_count = -1;
130         }
131
132         flash_info[0].size = size_b0;
133         flash_info[1].size = size_b1;
134         return (size_b0 + size_b1);
135 }
136
137
138 /*-----------------------------------------------------------------------
139  This code is specific to the AM29DL163/AM29DL232 for the QS850/QS823.
140  */
141
142 static void flash_get_offsets (ulong base, flash_info_t *info)
143 {
144         int i;
145         long large_sect_size;
146         long small_sect_size;
147
148         /* set up sector start adress table */
149         large_sect_size = info->size / (info->sector_count - 8 + 1);
150         small_sect_size = large_sect_size / 8;
151
152         if (info->flash_id & FLASH_BTYPE) {
153
154                 /* set sector offsets for bottom boot block type */
155                 for (i = 0; i < 7; i++) {
156                         info->start[i] = base;
157                         base += small_sect_size;
158                 }
159
160                 for (; i < info->sector_count; i++) {
161                         info->start[i] = base;
162                         base += large_sect_size;
163                 }
164         }
165         else
166         {
167                 /* set sector offsets for top boot block type */
168                 for (i = 0; i < (info->sector_count - 8); i++) {
169                         info->start[i] = base;
170                         base += large_sect_size;
171                 }
172
173                 for (; i < info->sector_count; i++) {
174                         info->start[i] = base;
175                         base += small_sect_size;
176                 }
177         }
178 }
179
180 /*-----------------------------------------------------------------------
181  */
182
183 void flash_print_info  (flash_info_t *info)
184 {
185         int i;
186         uchar *boottype;
187         uchar botboot[]=", bottom boot sect)\n";
188         uchar topboot[]=", top boot sector)\n";
189
190         if (info->flash_id == FLASH_UNKNOWN) {
191                 printf ("missing or unknown FLASH type\n");
192                 return;
193         }
194
195         switch (info->flash_id & FLASH_VENDMASK) {
196                 case FLASH_MAN_AMD:
197                         printf ("AMD ");
198                         break;
199                 case FLASH_MAN_FUJ:
200                         printf ("FUJITSU ");
201                         break;
202                 case FLASH_MAN_SST:
203                         printf ("SST ");
204                         break;
205                 case FLASH_MAN_STM:
206                         printf ("STM ");
207                         break;
208                 case FLASH_MAN_INTEL:
209                         printf ("INTEL ");
210                         break;
211                 default:
212                         printf ("Unknown Vendor ");
213                         break;
214         }
215
216         if (info->flash_id & 0x0001 ) {
217                 boottype = botboot;
218         } else {
219                 boottype = topboot;
220         }
221
222         switch (info->flash_id & FLASH_TYPEMASK) {
223                 case FLASH_AM160B:
224                         printf ("AM29LV160B (16 Mbit%s",boottype);
225                         break;
226                 case FLASH_AM160T:
227                         printf ("AM29LV160T (16 Mbit%s",boottype);
228                         break;
229                 case FLASH_AMDL163T:
230                         printf ("AM29DL163T (16 Mbit%s",boottype);
231                         break;
232                 case FLASH_AMDL163B:
233                         printf ("AM29DL163B (16 Mbit%s",boottype);
234                         break;
235                 case FLASH_AM320B:
236                         printf ("AM29LV320B (32 Mbit%s",boottype);
237                         break;
238                 case FLASH_AM320T:
239                         printf ("AM29LV320T (32 Mbit%s",boottype);
240                         break;
241                 case FLASH_AMDL323T:
242                         printf ("AM29DL323T (32 Mbit%s",boottype);
243                         break;
244                 case FLASH_AMDL323B:
245                         printf ("AM29DL323B (32 Mbit%s",boottype);
246                         break;
247                 case FLASH_AMDL322T:
248                         printf ("AM29DL322T (32 Mbit%s",boottype);
249                         break;
250                 default:
251                         printf ("Unknown Chip Type\n");
252                         break;
253         }
254
255         printf ("  Size: %ld MB in %d Sectors\n",
256         info->size >> 20, info->sector_count);
257
258         printf ("  Sector Start Addresses:");
259         for (i=0; i<info->sector_count; ++i) {
260                 if ((i % 5) == 0)
261                         printf ("\n   ");
262                 printf (" %08lX%s", info->start[i],
263                         info->protect[i] ? " (RO)" : "     ");
264         }
265         printf ("\n");
266         return;
267 }
268
269
270 /*-----------------------------------------------------------------------
271  * The following code cannot be run from FLASH!
272  */
273 ulong flash_get_size (volatile FLASH_WORD_SIZE *addr, flash_info_t *info)
274 {
275         short i;
276         ulong base = (ulong)addr;
277         FLASH_WORD_SIZE value;
278
279         /* Write auto select command: read Manufacturer ID */
280
281         /*
282          * Note: if it is an AMD flash and the word at addr[0000]
283          * is 0x00890089 this routine will think it is an Intel
284          * flash device and may(most likely) cause trouble.
285          */
286
287         addr[0x0000] = 0x00900090;
288         if(addr[0x0000] != 0x00890089){
289                 addr[0x0555] = 0x00AA00AA;
290                 addr[0x02AA] = 0x00550055;
291                 addr[0x0555] = 0x00900090;
292         }
293         value = addr[0];
294
295         switch (value) {
296                 case (AMD_MANUFACT & FLASH_ID_MASK):
297                         info->flash_id = FLASH_MAN_AMD;
298                         break;
299                 case (FUJ_MANUFACT & FLASH_ID_MASK):
300                         info->flash_id = FLASH_MAN_FUJ;
301                         break;
302                 case (STM_MANUFACT & FLASH_ID_MASK):
303                         info->flash_id = FLASH_MAN_STM;
304                         break;
305                 case (SST_MANUFACT & FLASH_ID_MASK):
306                         info->flash_id = FLASH_MAN_SST;
307                         break;
308                 case (INTEL_MANUFACT & FLASH_ID_MASK):
309                         info->flash_id = FLASH_MAN_INTEL;
310                         break;
311                 default:
312                         info->flash_id = FLASH_UNKNOWN;
313                         info->sector_count = 0;
314                         info->size = 0;
315                         return (0); /* no or unknown flash */
316         }
317
318         value = addr[1]; /* device ID */
319
320         switch (value) {
321                 case (AMD_ID_LV160T & FLASH_ID_MASK):
322                         info->flash_id += FLASH_AM160T;
323                         info->sector_count = 35;
324                         info->size = 0x00400000;
325                         break; /* => 4 MB */
326
327                 case (AMD_ID_LV160B & FLASH_ID_MASK):
328                         info->flash_id += FLASH_AM160B;
329                         info->sector_count = 35;
330                         info->size = 0x00400000;
331                         break; /* => 4 MB */
332
333                 case (AMD_ID_DL163T & FLASH_ID_MASK):
334                         info->flash_id += FLASH_AMDL163T;
335                         info->sector_count = 39;
336                         info->size = 0x00400000;
337                         break; /* => 4 MB */
338
339                 case (AMD_ID_DL163B & FLASH_ID_MASK):
340                         info->flash_id += FLASH_AMDL163B;
341                         info->sector_count = 39;
342                         info->size = 0x00400000;
343                         break; /* => 4 MB */
344
345                 case (AMD_ID_DL323T & FLASH_ID_MASK):
346                         info->flash_id += FLASH_AMDL323T;
347                         info->sector_count = 71;
348                         info->size = 0x00800000;
349                         break; /* => 8 MB */
350
351                 case (AMD_ID_DL323B & FLASH_ID_MASK):
352                         info->flash_id += FLASH_AMDL323B;
353                         info->sector_count = 71;
354                         info->size = 0x00800000;
355                         break; /* => 8 MB */
356
357                 case (AMD_ID_DL322T & FLASH_ID_MASK):
358                         info->flash_id += FLASH_AMDL322T;
359                         info->sector_count = 71;
360                         info->size = 0x00800000;
361                         break; /* => 8 MB */
362
363                 default:
364                         /* FIXME*/
365                         info->flash_id = FLASH_UNKNOWN;
366                         return (0); /* => no or unknown flash */
367         }
368
369         flash_get_offsets(base, info);
370
371         /* check for protected sectors */
372         for (i = 0; i < info->sector_count; i++) {
373                 /* read sector protection at sector address, (A7 .. A0) = 0x02 */
374                 /* D0 = 1 if protected */
375                 addr = (volatile FLASH_WORD_SIZE *)(info->start[i]);
376                 info->protect[i] = addr[2] & 1;
377         }
378
379         /*
380          * Prevent writes to uninitialized FLASH.
381          */
382         if (info->flash_id != FLASH_UNKNOWN) {
383                 addr = (volatile FLASH_WORD_SIZE *)info->start[0];
384                 *addr = (0x00FF00FF & FLASH_ID_MASK);   /* reset bank */
385         }
386
387         return (info->size);
388 }
389
390
391 /*-----------------------------------------------------------------------
392  */
393
394 int flash_erase (flash_info_t *info, int s_first, int s_last)
395 {
396         volatile FLASH_WORD_SIZE *addr=(volatile FLASH_WORD_SIZE*)(info->start[0]);
397         int flag, prot, sect, l_sect;
398         ulong start, now, last;
399         int rcode = 0;
400
401         if ((s_first < 0) || (s_first > s_last)) {
402                 if (info->flash_id == FLASH_UNKNOWN) {
403                         printf ("- missing\n");
404                 } else {
405                         printf ("- no sectors to erase\n");
406                 }
407                 return 1;
408         }
409
410         if ((info->flash_id == FLASH_UNKNOWN) ||
411                 (info->flash_id > FLASH_AMD_COMP) ) {
412                 printf ("Can't erase unknown flash type - aborted\n");
413                 return 1;
414         }
415
416         prot = 0;
417         for (sect=s_first; sect<=s_last; ++sect) {
418                 if (info->protect[sect]) {
419                         prot++;
420                 }
421         }
422
423         if (prot) {
424                 printf ("- Warning: %d protected sectors will not be erased!\n",
425                         prot);
426         } else {
427                 printf ("\n");
428         }
429
430         l_sect = -1;
431
432         /* Disable interrupts which might cause a timeout here */
433         flag = disable_interrupts();
434         addr[0x0555] = 0x00AA00AA;
435         addr[0x02AA] = 0x00550055;
436         addr[0x0555] = 0x00800080;
437         addr[0x0555] = 0x00AA00AA;
438         addr[0x02AA] = 0x00550055;
439         /* Start erase on unprotected sectors */
440         for (sect = s_first; sect<=s_last; sect++) {
441                 if (info->protect[sect] == 0) { /* not protected */
442                         addr = (volatile FLASH_WORD_SIZE *)(info->start[sect]);
443                         addr[0] = (0x00300030 & FLASH_ID_MASK);
444                         l_sect = sect;
445                 }
446         }
447
448         /* re-enable interrupts if necessary */
449         if (flag)
450                 enable_interrupts();
451
452         /* wait at least 80us - let's wait 1 ms */
453         udelay (1000);
454
455         /*
456          * We wait for the last triggered sector
457          */
458         if (l_sect < 0)
459                 goto DONE;
460
461         start = get_timer (0);
462         last  = start;
463         addr = (volatile FLASH_WORD_SIZE*)(info->start[l_sect]);
464         while ((addr[0] & (0x00800080&FLASH_ID_MASK)) !=
465                         (0x00800080&FLASH_ID_MASK)  )
466         {
467                 if ((now = get_timer(start)) > CONFIG_SYS_FLASH_ERASE_TOUT) {
468                         printf ("Timeout\n");
469                         return 1;
470                 }
471                 /* show that we're waiting */
472                 if ((now - last) > 1000) { /* every second */
473                         serial_putc ('.');
474                         last = now;
475                 }
476         }
477
478 DONE:
479         /* reset to read mode */
480         addr = (volatile FLASH_WORD_SIZE *)info->start[0];
481         addr[0] = (0x00F000F0 & FLASH_ID_MASK); /* reset bank */
482
483         printf (" done\n");
484         return rcode;
485 }
486
487 /*-----------------------------------------------------------------------
488  * Copy memory to flash, returns:
489  * 0 - OK
490  * 1 - write timeout
491  * 2 - Flash not erased
492  */
493
494 int write_buff (flash_info_t *info, uchar *src, ulong addr, ulong cnt)
495 {
496         ulong cp, wp, data;
497         int l;
498         int i, rc;
499
500         wp = (addr & ~3); /* get lower word aligned address */
501
502         /*
503          * handle unaligned start bytes
504          */
505         if ((l = addr - wp) != 0) {
506                 data = 0;
507                 for (i=0, cp=wp; i<l; ++i, ++cp) {
508                         data = (data << 8) | (*(uchar *)cp);
509                 }
510                 for (; i<4 && cnt>0; ++i) {
511                         data = (data << 8) | *src++;
512                         --cnt;
513                         ++cp;
514                 }
515                 for (; cnt==0 && i<4; ++i, ++cp) {
516                         data = (data << 8) | (*(uchar *)cp);
517                 }
518
519                 if ((rc = write_word(info, wp, data)) != 0) {
520                         return (rc);
521                 }
522                 wp += 4;
523         }
524
525         /*
526          * handle word aligned part
527          */
528         while (cnt >= 4) {
529                 data = 0;
530                 for (i=0; i<4; ++i) {
531                         data = (data << 8) | *src++;
532                 }
533                 if ((rc = write_word(info, wp, data)) != 0) {
534                         return (rc);
535                 }
536                 wp  += 4;
537                 cnt -= 4;
538         }
539
540         if (cnt == 0) {
541                 return (0);
542         }
543
544         /*
545          * handle unaligned tail bytes
546          */
547         data = 0;
548         for (i=0, cp=wp; i<4 && cnt>0; ++i, ++cp) {
549                 data = (data << 8) | *src++;
550                 --cnt;
551         }
552         for (; i<4; ++i, ++cp) {
553                 data = (data << 8) | (*(uchar *)cp);
554         }
555
556         return (write_word(info, wp, data));
557 }
558
559 /*-----------------------------------------------------------------------
560  * Write a word to Flash, returns:
561  * 0 - OK
562  * 1 - write timeout
563  * 2 - Flash not erased
564  */
565 static int write_word (flash_info_t *info, ulong dest, ulong data)
566 {
567         vu_long *addr = (vu_long*)(info->start[0]);
568         ulong start;
569         int flag;
570
571         /* Check if Flash is (sufficiently) erased */
572         if ((*((vu_long *)dest) & data) != data) {
573                 return (2);
574         }
575
576         /* Disable interrupts which might cause a timeout here */
577         flag = disable_interrupts();
578
579         /* AMD stuff */
580         addr[0x0555] = 0x00AA00AA;
581         addr[0x02AA] = 0x00550055;
582         addr[0x0555] = 0x00A000A0;
583
584         *((vu_long *)dest) = data;
585
586         /* re-enable interrupts if necessary */
587         if (flag)
588                 enable_interrupts();
589
590         /* data polling for D7 */
591         start = get_timer(0);
592
593         while ((*((vu_long *)dest) & 0x00800080) != (data & 0x00800080)) {
594                 if (get_timer(start) > CONFIG_SYS_FLASH_WRITE_TOUT) {
595                         return (1);
596                 }
597         }
598
599         return (0);
600 }