source: SVN/rincon/u-boot/board/snmc/qs850/flash.c @ 55

Last change on this file since 55 was 55, checked in by Tim Harvey, 22 months ago

rincon: added latest u-boot source

restored form server backup

Signed-off-by: Tim Harvey <tharvey@…>

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