source: SVN/rincon/u-boot/board/flagadm/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: 15.1 KB
Line 
1/*
2 * (C) Copyright 2001
3 * Wolfgang Denk, DENX Software Engineering, wd@denx.de.
4 *
5 * See file CREDITS for list of people who contributed to this
6 * project.
7 *
8 * This program is free software; you can redistribute it and/or
9 * modify it under the terms of the GNU General Public License as
10 * published by the Free Software Foundation; either version 2 of
11 * the License, or (at your option) any later version.
12 *
13 * This program is distributed in the hope that it will be useful,
14 * but WITHOUT ANY WARRANTY; without even the implied warranty of
15 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
16 * GNU General Public License for more details.
17 *
18 * You should have received a copy of the GNU General Public License
19 * along with this program; if not, write to the Free Software
20 * Foundation, Inc., 59 Temple Place, Suite 330, Boston,
21 * MA 02111-1307 USA
22 */
23
24#include <common.h>
25#include <mpc8xx.h>
26#include <flash.h>
27
28flash_info_t    flash_info[CFG_MAX_FLASH_BANKS]; /* info for FLASH chips        */
29
30/*-----------------------------------------------------------------------
31 * Functions
32 */
33ulong flash_recognize (vu_long *base);
34int write_word (flash_info_t *info, ulong dest, ulong data);
35void flash_get_geometry (vu_long *base, flash_info_t *info);
36void flash_unprotect(flash_info_t *info);
37int _flash_real_protect(flash_info_t *info, long idx, int on);
38
39
40unsigned long flash_init (void)
41{
42        volatile immap_t        *immap  = (immap_t *)CFG_IMMR;
43        volatile memctl8xx_t    *memctl = &immap->im_memctl;
44        int i;
45        int rec;
46
47        for (i=0; i<CFG_MAX_FLASH_BANKS; ++i) {
48                flash_info[i].flash_id = FLASH_UNKNOWN;
49        }
50
51        *((vu_short*)CFG_FLASH_BASE) = 0xffff;
52
53        flash_get_geometry ((vu_long*)CFG_FLASH_BASE, &flash_info[0]);
54
55        /* Remap FLASH according to real size */
56        memctl->memc_or0 = CFG_OR_TIMING_FLASH | (-flash_info[0].size & 0xFFFF8000);
57        memctl->memc_br0 = (CFG_FLASH_BASE & BR_BA_MSK) |
58                (memctl->memc_br0 & ~(BR_BA_MSK));
59
60        rec = flash_recognize((vu_long*)CFG_FLASH_BASE);
61
62        if (rec == FLASH_UNKNOWN) {
63                printf ("## Unknown FLASH on Bank 0 - Size = 0x%08lx = %ld MB\n",
64                                flash_info[0].size, flash_info[0].size<<20);
65        }
66
67#if CFG_FLASH_PROTECTION
68        /*Unprotect all the flash memory*/
69        flash_unprotect(&flash_info[0]);
70#endif
71
72        *((vu_short*)CFG_FLASH_BASE) = 0xffff;
73
74        return (flash_info[0].size);
75
76#if CFG_MONITOR_BASE >= CFG_FLASH_BASE
77        /* monitor protection ON by default */
78        flash_protect(FLAG_PROTECT_SET,
79                      CFG_MONITOR_BASE,
80                      CFG_MONITOR_BASE+monitor_flash_len-1,
81                      &flash_info[0]);
82#endif
83
84#ifdef  CONFIG_ENV_IS_IN_FLASH
85        /* ENV protection ON by default */
86        flash_protect(FLAG_PROTECT_SET,
87                      CONFIG_ENV_OFFSET,
88                      CONFIG_ENV_OFFSET+CONFIG_ENV_SIZE-1,
89                      &flash_info[0]);
90#endif
91        return (flash_info[0].size);
92}
93
94
95int flash_get_protect_status(flash_info_t * info, long idx)
96{
97        vu_short * base;
98        ushort res;
99
100#ifdef DEBUG
101        printf("\n Attempting to set protection info with %d sectors\n", info->sector_count);
102#endif
103
104
105        base = (vu_short*)info->start[idx];
106
107        *(base) = 0xffff;
108
109        *(base + 0x55) = 0x0098;
110        res = base[0x2];
111
112        *(base) = 0xffff;
113
114        if(res != 0)
115                res = 1;
116        else
117                res = 0;
118
119        return res;
120}
121
122void flash_get_geometry (vu_long *base, flash_info_t *info)
123{
124        int i,j;
125        ulong ner = 0;
126        vu_short * sb  = (vu_short*)base;
127        ulong offset = (ulong)base;
128
129        /* Read Device geometry */
130
131        *sb = 0xffff;
132
133        *sb = 0x0090;
134
135        info->flash_id = ((ulong)base[0x0]);
136#ifdef DEBUG
137        printf("Id is %x\n", (uint)(ulong)info->flash_id);
138#endif
139
140        *sb = 0xffff;
141
142        *(sb+0x55) = 0x0098;
143
144        info->size = 1 << (sb[0x27]); /* Read flash size */
145
146#ifdef DEBUG
147        printf("Size is %x\n", (uint)(ulong)info->size);
148#endif
149
150        *sb = 0xffff;
151
152        *(sb + 0x55) = 0x0098;
153        ner = sb[0x2c] ; /*Number of erase regions*/
154
155#ifdef DEBUG
156        printf("Number of erase regions %x\n", (uint)ner);
157#endif
158
159        info->sector_count = 0;
160
161        for(i = 0; i < ner; i++)
162        {
163                uint s;
164                uint count;
165                uint t1,t2,t3,t4;
166
167                *sb = 0xffff;
168
169                *(sb + 0x55) = 0x0098;
170
171                t1 = sb[0x2d + i*4];
172                t2 = sb[0x2e + i*4];
173                t3 = sb[0x2f + i*4];
174                t4 = sb[0x30 + i*4];
175
176                count = ((t1 & 0x00ff) | (((t2 & 0x00ff) << 8) & 0xff00) )+ 1; /*sector count*/
177                s = ((t3 & 0x00ff) | (((t4 & 0x00ff) << 8) & 0xff00)) * 256;; /*Sector size*/
178
179#ifdef DEBUG
180                printf("count and size %x, %x\n", count, s);
181                printf("sector count for erase region %d is %d\n", i, count);
182#endif
183                for(j = 0; j < count; j++)
184                {
185#ifdef DEBUG
186                        printf("%x, ", (uint)offset);
187#endif
188                        info->start[ info->sector_count + j] = offset;
189                        offset += s;
190                }
191                info->sector_count += count;
192        }
193
194        if ((offset - (ulong)base) != info->size)
195                printf("WARNING reported size %x does not match to calculted size %x.\n"
196                                , (uint)info->size, (uint)(offset - (ulong)base) );
197
198        /* Next check if there are any sectors protected.*/
199
200        for(i = 0; i < info->sector_count; i++)
201                info->protect[i] = flash_get_protect_status(info, i);
202
203        *sb = 0xffff;
204}
205
206/*-----------------------------------------------------------------------
207 */
208void flash_print_info  (flash_info_t *info)
209{
210        int i;
211
212        if (info->flash_id == FLASH_UNKNOWN) {
213                printf ("missing or unknown FLASH type\n");
214                return ;
215        }
216
217        switch (info->flash_id & FLASH_VENDMASK) {
218        case INTEL_MANUFACT & FLASH_VENDMASK:
219                printf ("Intel ");
220                break;
221        default:
222                printf ("Unknown Vendor ");
223                break;
224        }
225
226        switch (info->flash_id & FLASH_TYPEMASK) {
227        case INTEL_ID_28F320C3B & FLASH_TYPEMASK:
228                printf ("28F320RC3(4 MB)\n");
229                break;
230        case INTEL_ID_28F320J3A:
231                printf("28F320J3A (4 MB)\n");
232                break;
233        default:
234                printf ("Unknown Chip Type\n");
235                        break;
236        }
237
238        printf ("  Size: %ld MB in %d Sectors\n",
239                info->size >> 20, info->sector_count);
240
241        printf ("  Sector Start Addresses:");
242        for (i=0; i<info->sector_count; ++i) {
243                if ((i % 4) == 0)
244                        printf ("\n   ");
245                printf ("  %02d %08lX%s",
246                        i, info->start[i],
247                        info->protect[i]!=0 ? " (RO)" : "     "
248                );
249        }
250        printf ("\n");
251        return ;
252}
253
254ulong flash_recognize (vu_long *base)
255{
256        ulong id;
257        ulong res = FLASH_UNKNOWN;
258        vu_short * sb = (vu_short*)base;
259
260        *sb = 0xffff;
261
262        *sb = 0x0090;
263        id = base[0];
264
265        switch (id & 0x00FF0000)
266        {
267                case (MT_MANUFACT & 0x00FF0000):        /* MT or => Intel */
268                case (INTEL_ALT_MANU & 0x00FF0000):
269                res = FLASH_MAN_INTEL;
270                break;
271        default:
272                res = FLASH_UNKNOWN;
273        }
274
275        *sb = 0xffff;
276
277        return res;
278}
279
280/*-----------------------------------------------------------------------*/
281#define INTEL_FLASH_STATUS_BLS  0x02
282#define INTEL_FLASH_STATUS_PSS  0x04
283#define INTEL_FLASH_STATUS_VPPS 0x08
284#define INTEL_FLASH_STATUS_PS   0x10
285#define INTEL_FLASH_STATUS_ES   0x20
286#define INTEL_FLASH_STATUS_ESS  0x40
287#define INTEL_FLASH_STATUS_WSMS 0x80
288
289int     flash_decode_status_bits(char status)
290{
291        int err = 0;
292
293        if(!(status & INTEL_FLASH_STATUS_WSMS)) {
294                printf("Busy\n");
295                err = -1;
296        }
297
298        if(status & INTEL_FLASH_STATUS_ESS) {
299                printf("Erase suspended\n");
300                err = -1;
301        }
302
303        if(status & INTEL_FLASH_STATUS_ES) {
304                printf("Error in block erase\n");
305                err = -1;
306        }
307
308        if(status & INTEL_FLASH_STATUS_PS) {
309                printf("Error in programming\n");
310                err = -1;
311        }
312
313        if(status & INTEL_FLASH_STATUS_VPPS) {
314                printf("Vpp low, operation aborted\n");
315                err = -1;
316        }
317
318        if(status & INTEL_FLASH_STATUS_PSS) {
319                printf("Program is suspended\n");
320                err = -1;
321        }
322
323        if(status & INTEL_FLASH_STATUS_BLS) {
324                printf("Attempting to program/erase a locked sector\n");
325                err = -1;
326        }
327
328        if((status & INTEL_FLASH_STATUS_PS) &&
329           (status & INTEL_FLASH_STATUS_ES) &&
330           (status & INTEL_FLASH_STATUS_ESS)) {
331                printf("A command sequence error\n");
332                return -1;
333        }
334
335        return err;
336}
337
338/*-----------------------------------------------------------------------
339 */
340
341int     flash_erase (flash_info_t *info, int s_first, int s_last)
342{
343        vu_short *addr;
344        int flag, prot, sect;
345        ulong start, now;
346        int rcode = 0;
347
348        if ((s_first < 0) || (s_first > s_last)) {
349                if (info->flash_id == FLASH_UNKNOWN) {
350                        printf ("- missing\n");
351                } else {
352                        printf ("- no sectors to erase\n");
353                }
354                return 1;
355        }
356
357        if ((info->flash_id & FLASH_VENDMASK) != (INTEL_MANUFACT & FLASH_VENDMASK)) {
358                printf ("Can't erase unknown flash type %08lx - aborted\n",
359                        info->flash_id);
360                return 1;
361        }
362
363        prot = 0;
364        for (sect=s_first; sect<=s_last; ++sect) {
365                if (info->protect[sect]) {
366                        prot++;
367                }
368        }
369
370        if (prot) {
371                printf ("- Warning: %d protected sectors will not be erased!\n",
372                        prot);
373        } else {
374                printf ("\n");
375        }
376
377        start = get_timer (0);
378
379        /* Start erase on unprotected sectors */
380        for (sect = s_first; sect<=s_last; sect++) {
381                char tmp;
382
383                if (info->protect[sect] == 0) { /* not protected */
384                        addr = (vu_short *)(info->start[sect]);
385
386                        /* Disable interrupts which might cause a timeout here */
387                        flag = disable_interrupts();
388
389                        /* Single Block Erase Command */
390                        *addr = 0x0020;
391                        /* Confirm */
392                        *addr = 0x00D0;
393                        /* Resume Command, as per errata update */
394                        *addr = 0x00D0;
395
396                        /* re-enable interrupts if necessary */
397                        if (flag)
398                                enable_interrupts();
399
400                        *addr = 0x70; /*Read status register command*/
401                        tmp = (short)*addr & 0x00FF; /* Read the status */
402                        while (!(tmp & INTEL_FLASH_STATUS_WSMS)) {
403                                if ((now=get_timer(start)) > CFG_FLASH_ERASE_TOUT) {
404                                        *addr = 0x0050; /* Reset the status register */
405                                        *addr = 0xffff;
406                                        printf ("Timeout\n");
407                                        return 1;
408                                }
409                                /* show that we're waiting */
410                                if ((now - start) > 1000) {     /* every second */
411                                        putc ('.');
412                                }
413                                udelay(100000); /* 100 ms */
414                                *addr = 0x0070; /*Read status register command*/
415                                tmp = (short)*addr & 0x00FF; /* Read status */
416                                start = get_timer(0);
417                        }
418                        if( tmp & INTEL_FLASH_STATUS_ES )
419                                flash_decode_status_bits(tmp);
420
421                        *addr = 0x0050; /* Reset the status register */
422                        *addr = 0xffff; /* Reset to read mode */
423                }
424        }
425
426
427        printf (" done\n");
428        return rcode;
429}
430
431void flash_unprotect (flash_info_t *info)
432{
433        /*We can only unprotect the whole flash at once*/
434        /*Therefore we must prevent the _flash_real_protect()*/
435        /*from re-protecting sectors, that ware protected before */
436        /*we called flash_real_protect();*/
437
438        int i;
439
440        for(i = 0; i < info->sector_count; i++)
441                info->protect[i] = 0;
442
443#ifdef CFG_FLASH_PROTECTION
444                _flash_real_protect(info, 0, 0);
445#endif
446}
447
448/*-----------------------------------------------------------------------
449 * Copy memory to flash, returns:
450 * 0 - OK
451 * 1 - write timeout
452 * 2 - Flash not erased
453 */
454
455int write_buff (flash_info_t *info, uchar *src, ulong addr, ulong cnt)
456{
457        ulong cp, wp, data;
458        int i, l, rc;
459
460        wp = (addr & ~3);       /* get lower word aligned address */
461
462        /*
463         * handle unaligned start bytes
464         */
465        if ((l = addr - wp) != 0) {
466                data = 0;
467                for (i=0, cp=wp; i<l; ++i, ++cp) {
468                        data = (data << 8) | (*(uchar *)cp);
469                }
470                for (; i<4 && cnt>0; ++i) {
471                        data = (data << 8) | *src++;
472                        --cnt;
473                        ++cp;
474                }
475                for (; cnt==0 && i<4; ++i, ++cp) {
476                        data = (data << 8) | (*(uchar *)cp);
477                }
478
479                if ((rc = write_word(info, wp, data)) != 0) {
480                        return (rc);
481                }
482                wp += 4;
483        }
484
485        /*
486         * handle word aligned part
487         */
488        while (cnt >= 4) {
489                data = 0;
490                for (i=0; i<4; ++i) {
491                        data = (data << 8) | *src++;
492                }
493                if ((rc = write_word(info, wp, data)) != 0) {
494                        return (rc);
495                }
496                wp  += 4;
497                cnt -= 4;
498        }
499
500        if (cnt == 0) {
501                return (0);
502        }
503
504        /*
505         * handle unaligned tail bytes
506         */
507        data = 0;
508        for (i=0, cp=wp; i<4 && cnt>0; ++i, ++cp) {
509                data = (data << 8) | *src++;
510                --cnt;
511        }
512        for (; i<4; ++i, ++cp) {
513                data = (data << 8) | (*(uchar *)cp);
514        }
515
516        return (write_word(info, wp, data));
517}
518
519/*-----------------------------------------------------------------------
520 * Write a word to Flash, returns:
521 * 0 - OK
522 * 1 - write timeout
523 * 2 - Flash not erased
524 */
525int write_word (flash_info_t *info, ulong dest, ulong da)
526{
527        vu_short *addr = (vu_short *)dest;
528        ulong start;
529        char csr;
530        int flag;
531        ushort * d = (ushort*)&da;
532        int i;
533
534        /* Check if Flash is (sufficiently) erased */
535        if (((*addr & d[0]) != d[0]) || ((*(addr+1) & d[1]) != d[1])) {
536                return (2);
537        }
538        /* Disable interrupts which might cause a timeout here */
539        flag = disable_interrupts();
540
541        for(i = 0; i < 2; i++)
542        {
543                /* Write Command */
544                *addr = 0x0010;
545
546                /* Write Data */
547                *addr = d[i];
548
549                /* re-enable interrupts if necessary */
550                if (flag)
551                        enable_interrupts();
552
553                /* data polling for D7 */
554                start = get_timer (0);
555                flag  = 0;
556                *addr = 0x0070; /*Read statusregister command */
557                while (((csr = *addr) & INTEL_FLASH_STATUS_WSMS)!=INTEL_FLASH_STATUS_WSMS) {
558                        if (get_timer(start) > CFG_FLASH_WRITE_TOUT) {
559                                flag = 1;
560                                break;
561                        }
562                        *addr = 0x0070; /*Read statusregister command */
563                }
564                if (csr & INTEL_FLASH_STATUS_PSS) {
565                        printf ("CSR indicates write error (%0x) at %08lx\n",
566                                        csr, (ulong)addr);
567                        flag = 1;
568                }
569
570                /* Clear Status Registers Command */
571                *addr = 0x0050;
572                /* Reset to read array mode */
573                *addr = 0xffff;
574                addr++;
575        }
576
577        return (flag);
578}
579
580int flash_real_protect(flash_info_t *info, long offset, int prot)
581{
582        int i, idx;
583
584        for(idx = 0; idx < info->sector_count; idx++)
585                if(info->start[idx] == offset)
586                        break;
587
588        if(idx==info->sector_count)
589                return -1;
590
591        if(prot == 0) {
592                /* Unprotect one sector, which means unprotect all flash
593                 * and reprotect the other protected sectors.
594                 */
595                _flash_real_protect(info, 0, 0); /* Unprotects the whole flash*/
596                info->protect[idx] = 0;
597
598                for(i = 0; i < info->sector_count; i++)
599                        if(info->protect[i])
600                                _flash_real_protect(info, i, 1);
601                }
602        else {
603                /* We can protect individual sectors */
604                _flash_real_protect(info, idx, 1);
605        }
606
607        for( i = 0; i < info->sector_count; i++)
608                info->protect[i] = flash_get_protect_status(info, i);
609
610        return 0;
611}
612
613int _flash_real_protect(flash_info_t *info, long idx, int prot)
614{
615        vu_short *addr;
616        int flag;
617        ushort cmd;
618        ushort tmp;
619        ulong now, start;
620
621        if ((info->flash_id & FLASH_VENDMASK) != (INTEL_MANUFACT & FLASH_VENDMASK)) {
622                printf ("Can't change protection for unknown flash type %08lx - aborted\n",
623                        info->flash_id);
624                return -1;
625        }
626
627        if(prot == 0) {
628                /*Unlock the sector*/
629                cmd = 0x00D0;
630        }
631        else {
632                /*Lock the sector*/
633                cmd = 0x0001;
634        }
635
636        addr = (vu_short *)(info->start[idx]);
637
638        /* If chip is busy, wait for it */
639        start = get_timer(0);
640        *addr = 0x0070; /*Read status register command*/
641        tmp = ((ushort)(*addr))&0x00ff; /*Read the status*/
642        while(!(tmp & INTEL_FLASH_STATUS_WSMS)) {
643                /*Write State Machine Busy*/
644                /*Wait untill done or timeout.*/
645                if ((now=get_timer(start)) > CFG_FLASH_WRITE_TOUT) {
646                        *addr = 0x0050; /* Reset the status register */
647                        *addr = 0xffff; /* Reset the chip */
648                        printf ("TTimeout\n");
649                        return 1;
650                }
651                *addr = 0x0070;
652                tmp = ((ushort)(*addr))&0x00ff; /*Read the status*/
653                start = get_timer(0);
654        }
655
656        /* Disable interrupts which might cause a timeout here */
657        flag = disable_interrupts();
658
659        /* Unlock block*/
660        *addr = 0x0060;
661
662        *addr = cmd;
663
664        /* re-enable interrupts if necessary */
665        if (flag)
666                enable_interrupts();
667
668        start = get_timer(0);
669        *addr = 0x0070; /*Read status register command*/
670        tmp = ((ushort)(*addr)) & 0x00FF; /* Read the status */
671        while (!(tmp & INTEL_FLASH_STATUS_WSMS)) {
672                /* Write State Machine Busy */
673                if ((now=get_timer(start)) > CFG_FLASH_WRITE_TOUT) {
674                        *addr = 0x0050; /* Reset the status register */
675                        *addr = 0xffff;
676                        printf ("Timeout\n");
677                        return 1;
678                }
679                /* show that we're waiting */
680                if ((now - start) > 1000) {     /* every second */
681                        putc ('.');
682                }
683                udelay(100000); /* 100 ms */
684                *addr = 0x70; /*Read status register command*/
685                tmp = (short)*addr & 0x00FF; /* Read status */
686                start = get_timer(0);
687        }
688        if( tmp & INTEL_FLASH_STATUS_PS )
689                flash_decode_status_bits(tmp);
690
691        *addr =0x0050; /*Clear status register*/
692
693        /* reset to read mode */
694        *addr = 0xffff;
695
696        return 0;
697}
Note: See TracBrowser for help on using the repository browser.