source: SVN/rincon/u-boot/board/atmel/at91rm9200dk/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: 11.5 KB
Line 
1/*
2 * (C) Copyright 2002
3 * Lineo, Inc. <www.lineo.com>
4 * Bernhard Kuhn <bkuhn@lineo.com>
5 *
6 * (C) Copyright 2002
7 * Sysgo Real-Time Solutions, GmbH <www.elinos.com>
8 * Alex Zuepke <azu@sysgo.de>
9 *
10 * See file CREDITS for list of people who contributed to this
11 * project.
12 *
13 * This program is free software; you can redistribute it and/or
14 * modify it under the terms of the GNU General Public License as
15 * published by the Free Software Foundation; either version 2 of
16 * the License, or (at your option) any later version.
17 *
18 * This program is distributed in the hope that it will be useful,
19 * but WITHOUT ANY WARRANTY; without even the implied warranty of
20 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
21 * GNU General Public License for more details.
22 *
23 * You should have received a copy of the GNU General Public License
24 * along with this program; if not, write to the Free Software
25 * Foundation, Inc., 59 Temple Place, Suite 330, Boston,
26 * MA 02111-1307 USA
27 */
28
29#include <common.h>
30
31ulong myflush(void);
32
33
34/* Flash Organization Structure */
35typedef struct OrgDef
36{
37        unsigned int sector_number;
38        unsigned int sector_size;
39} OrgDef;
40
41
42/* Flash Organizations */
43OrgDef OrgAT49BV16x4[] =
44{
45        {  8,  8*1024 },        /*   8 *  8 kBytes sectors */
46        {  2, 32*1024 },        /*   2 * 32 kBytes sectors */
47        { 30, 64*1024 },        /*  30 * 64 kBytes sectors */
48};
49
50OrgDef OrgAT49BV16x4A[] =
51{
52        {  8,  8*1024 },        /*   8 *  8 kBytes sectors */
53        { 31, 64*1024 },        /*  31 * 64 kBytes sectors */
54};
55
56OrgDef OrgAT49BV6416[] =
57{
58        {   8,  8*1024 },       /*   8 *  8 kBytes sectors */
59        { 127, 64*1024 },       /* 127 * 64 kBytes sectors */
60};
61
62flash_info_t    flash_info[CFG_MAX_FLASH_BANKS];
63
64/* AT49BV1614A Codes */
65#define FLASH_CODE1             0xAA
66#define FLASH_CODE2             0x55
67#define ID_IN_CODE              0x90
68#define ID_OUT_CODE             0xF0
69
70
71#define CMD_READ_ARRAY          0x00F0
72#define CMD_UNLOCK1             0x00AA
73#define CMD_UNLOCK2             0x0055
74#define CMD_ERASE_SETUP         0x0080
75#define CMD_ERASE_CONFIRM       0x0030
76#define CMD_PROGRAM             0x00A0
77#define CMD_UNLOCK_BYPASS       0x0020
78#define CMD_SECTOR_UNLOCK       0x0070
79
80#define MEM_FLASH_ADDR1         (*(volatile u16 *)(CFG_FLASH_BASE + (0x00005555<<1)))
81#define MEM_FLASH_ADDR2         (*(volatile u16 *)(CFG_FLASH_BASE + (0x00002AAA<<1)))
82
83#define BIT_ERASE_DONE          0x0080
84#define BIT_RDY_MASK            0x0080
85#define BIT_PROGRAM_ERROR       0x0020
86#define BIT_TIMEOUT             0x80000000 /* our flag */
87
88#define READY 1
89#define ERR   2
90#define TMO   4
91
92/*-----------------------------------------------------------------------
93 */
94void flash_identification (flash_info_t * info)
95{
96        volatile u16 manuf_code, device_code, add_device_code;
97
98        MEM_FLASH_ADDR1 = FLASH_CODE1;
99        MEM_FLASH_ADDR2 = FLASH_CODE2;
100        MEM_FLASH_ADDR1 = ID_IN_CODE;
101
102        manuf_code = *(volatile u16 *) CFG_FLASH_BASE;
103        device_code = *(volatile u16 *) (CFG_FLASH_BASE + 2);
104        add_device_code = *(volatile u16 *) (CFG_FLASH_BASE + (3 << 1));
105
106        MEM_FLASH_ADDR1 = FLASH_CODE1;
107        MEM_FLASH_ADDR2 = FLASH_CODE2;
108        MEM_FLASH_ADDR1 = ID_OUT_CODE;
109
110        /* Vendor type */
111        info->flash_id = ATM_MANUFACT & FLASH_VENDMASK;
112        printf ("Atmel: ");
113
114        if ((device_code & FLASH_TYPEMASK) == (ATM_ID_BV1614 & FLASH_TYPEMASK)) {
115
116                if ((add_device_code & FLASH_TYPEMASK) ==
117                        (ATM_ID_BV1614A & FLASH_TYPEMASK)) {
118                        info->flash_id |= ATM_ID_BV1614A & FLASH_TYPEMASK;
119                        printf ("AT49BV1614A (16Mbit)\n");
120                } else {                                /* AT49BV1614 Flash */
121                        info->flash_id |= ATM_ID_BV1614 & FLASH_TYPEMASK;
122                        printf ("AT49BV1614 (16Mbit)\n");
123                }
124
125        } else if ((device_code & FLASH_TYPEMASK) == (ATM_ID_BV6416 & FLASH_TYPEMASK)) {
126                info->flash_id |= ATM_ID_BV6416 & FLASH_TYPEMASK;
127                printf ("AT49BV6416 (64Mbit)\n");
128        }
129}
130
131ushort flash_number_sector(OrgDef *pOrgDef, unsigned int nb_blocks)
132{
133        int i, nb_sectors = 0;
134
135        for (i=0; i<nb_blocks; i++){
136                nb_sectors += pOrgDef[i].sector_number;
137        }
138
139        return nb_sectors;
140}
141
142void flash_unlock_sector(flash_info_t * info, unsigned int sector)
143{
144        volatile u16 *addr = (volatile u16 *) (info->start[sector]);
145
146        MEM_FLASH_ADDR1 = CMD_UNLOCK1;
147        *addr = CMD_SECTOR_UNLOCK;
148}
149
150
151ulong flash_init (void)
152{
153        int i, j, k;
154        unsigned int flash_nb_blocks, sector;
155        unsigned int start_address;
156        OrgDef *pOrgDef;
157
158        ulong size = 0;
159
160        for (i = 0; i < CFG_MAX_FLASH_BANKS; i++) {
161                ulong flashbase = 0;
162
163                flash_identification (&flash_info[i]);
164
165                if ((flash_info[i].flash_id & FLASH_TYPEMASK) ==
166                        (ATM_ID_BV1614 & FLASH_TYPEMASK)) {
167
168                        pOrgDef = OrgAT49BV16x4;
169                        flash_nb_blocks = sizeof (OrgAT49BV16x4) / sizeof (OrgDef);
170                } else if ((flash_info[i].flash_id & FLASH_TYPEMASK) ==
171                        (ATM_ID_BV1614A & FLASH_TYPEMASK)){     /* AT49BV1614A Flash */
172
173                        pOrgDef = OrgAT49BV16x4A;
174                        flash_nb_blocks = sizeof (OrgAT49BV16x4A) / sizeof (OrgDef);
175                } else if ((flash_info[i].flash_id & FLASH_TYPEMASK) ==
176                        (ATM_ID_BV6416 & FLASH_TYPEMASK)){      /* AT49BV6416 Flash */
177
178                        pOrgDef = OrgAT49BV6416;
179                        flash_nb_blocks = sizeof (OrgAT49BV6416) / sizeof (OrgDef);
180                } else {
181                        flash_nb_blocks = 0;
182                        pOrgDef = OrgAT49BV16x4;
183                }
184
185                flash_info[i].sector_count = flash_number_sector(pOrgDef, flash_nb_blocks);
186                memset (flash_info[i].protect, 0, flash_info[i].sector_count);
187
188                if (i == 0)
189                        flashbase = PHYS_FLASH_1;
190                else
191                        panic ("configured too many flash banks!\n");
192
193                sector = 0;
194                start_address = flashbase;
195                flash_info[i].size = 0;
196
197                for (j = 0; j < flash_nb_blocks; j++) {
198                        for (k = 0; k < pOrgDef[j].sector_number; k++) {
199                                flash_info[i].start[sector++] = start_address;
200                                start_address += pOrgDef[j].sector_size;
201                                flash_info[i].size += pOrgDef[j].sector_size;
202                        }
203                }
204
205                size += flash_info[i].size;
206
207                if ((flash_info[i].flash_id & FLASH_TYPEMASK) ==
208                        (ATM_ID_BV6416 & FLASH_TYPEMASK)){      /* AT49BV6416 Flash */
209
210                        /* Unlock all sectors at reset */
211                        for (j=0; j<flash_info[i].sector_count; j++){
212                                flash_unlock_sector(&flash_info[i], j);
213                        }
214                }
215        }
216
217        /* Protect binary boot image */
218        flash_protect (FLAG_PROTECT_SET,
219                       CFG_FLASH_BASE,
220                       CFG_FLASH_BASE + CFG_BOOT_SIZE - 1, &flash_info[0]);
221
222        /* Protect environment variables */
223        flash_protect (FLAG_PROTECT_SET,
224                       CONFIG_ENV_ADDR,
225                       CONFIG_ENV_ADDR + CONFIG_ENV_SIZE - 1, &flash_info[0]);
226
227        /* Protect U-Boot gzipped image */
228        flash_protect (FLAG_PROTECT_SET,
229                       CFG_U_BOOT_BASE,
230                       CFG_U_BOOT_BASE + CFG_U_BOOT_SIZE - 1, &flash_info[0]);
231
232        return size;
233}
234
235/*-----------------------------------------------------------------------
236 */
237void flash_print_info (flash_info_t * info)
238{
239        int i;
240
241        switch (info->flash_id & FLASH_VENDMASK) {
242        case (ATM_MANUFACT & FLASH_VENDMASK):
243                printf ("Atmel: ");
244                break;
245        default:
246                printf ("Unknown Vendor ");
247                break;
248        }
249
250        switch (info->flash_id & FLASH_TYPEMASK) {
251        case (ATM_ID_BV1614 & FLASH_TYPEMASK):
252                printf ("AT49BV1614 (16Mbit)\n");
253                break;
254        case (ATM_ID_BV1614A & FLASH_TYPEMASK):
255                printf ("AT49BV1614A (16Mbit)\n");
256                break;
257        case (ATM_ID_BV6416 & FLASH_TYPEMASK):
258                printf ("AT49BV6416 (64Mbit)\n");
259                break;
260        default:
261                printf ("Unknown Chip Type\n");
262                return;
263        }
264
265        printf ("  Size: %ld MB in %d Sectors\n",
266                info->size >> 20, info->sector_count);
267
268        printf ("  Sector Start Addresses:");
269        for (i = 0; i < info->sector_count; i++) {
270                if ((i % 5) == 0) {
271                        printf ("\n   ");
272                }
273                printf (" %08lX%s", info->start[i],
274                        info->protect[i] ? " (RO)" : "     ");
275        }
276        printf ("\n");
277}
278
279/*-----------------------------------------------------------------------
280 */
281
282int flash_erase (flash_info_t * info, int s_first, int s_last)
283{
284        ulong result;
285        int iflag, cflag, prot, sect;
286        int rc = ERR_OK;
287        int chip1;
288
289        /* first look for protection bits */
290
291        if (info->flash_id == FLASH_UNKNOWN)
292                return ERR_UNKNOWN_FLASH_TYPE;
293
294        if ((s_first < 0) || (s_first > s_last)) {
295                return ERR_INVAL;
296        }
297
298        if ((info->flash_id & FLASH_VENDMASK) !=
299                (ATM_MANUFACT & FLASH_VENDMASK)) {
300                return ERR_UNKNOWN_FLASH_VENDOR;
301        }
302
303        prot = 0;
304        for (sect = s_first; sect <= s_last; ++sect) {
305                if (info->protect[sect]) {
306                        prot++;
307                }
308        }
309        if (prot)
310                return ERR_PROTECTED;
311
312        /*
313         * Disable interrupts which might cause a timeout
314         * here. Remember that our exception vectors are
315         * at address 0 in the flash, and we don't want a
316         * (ticker) exception to happen while the flash
317         * chip is in programming mode.
318         */
319        cflag = icache_status ();
320        icache_disable ();
321        iflag = disable_interrupts ();
322
323        /* Start erase on unprotected sectors */
324        for (sect = s_first; sect <= s_last && !ctrlc (); sect++) {
325                printf ("Erasing sector %2d ... ", sect);
326
327                /* arm simple, non interrupt dependent timer */
328                reset_timer_masked ();
329
330                if (info->protect[sect] == 0) { /* not protected */
331                        volatile u16 *addr = (volatile u16 *) (info->start[sect]);
332
333                        MEM_FLASH_ADDR1 = CMD_UNLOCK1;
334                        MEM_FLASH_ADDR2 = CMD_UNLOCK2;
335                        MEM_FLASH_ADDR1 = CMD_ERASE_SETUP;
336
337                        MEM_FLASH_ADDR1 = CMD_UNLOCK1;
338                        MEM_FLASH_ADDR2 = CMD_UNLOCK2;
339                        *addr = CMD_ERASE_CONFIRM;
340
341                        /* wait until flash is ready */
342                        chip1 = 0;
343
344                        do {
345                                result = *addr;
346
347                                /* check timeout */
348                                if (get_timer_masked () > CFG_FLASH_ERASE_TOUT) {
349                                        MEM_FLASH_ADDR1 = CMD_READ_ARRAY;
350                                        chip1 = TMO;
351                                        break;
352                                }
353
354                                if (!chip1 && (result & 0xFFFF) & BIT_ERASE_DONE)
355                                        chip1 = READY;
356
357                        } while (!chip1);
358
359                        MEM_FLASH_ADDR1 = CMD_READ_ARRAY;
360
361                        if (chip1 == ERR) {
362                                rc = ERR_PROG_ERROR;
363                                goto outahere;
364                        }
365                        if (chip1 == TMO) {
366                                rc = ERR_TIMOUT;
367                                goto outahere;
368                        }
369
370                        printf ("ok.\n");
371                } else {                        /* it was protected */
372                        printf ("protected!\n");
373                }
374        }
375
376        if (ctrlc ())
377                printf ("User Interrupt!\n");
378
379outahere:
380        /* allow flash to settle - wait 10 ms */
381        udelay_masked (10000);
382
383        if (iflag)
384                enable_interrupts ();
385
386        if (cflag)
387                icache_enable ();
388
389        return rc;
390}
391
392/*-----------------------------------------------------------------------
393 * Copy memory to flash
394 */
395
396static int write_word (flash_info_t * info, ulong dest, ulong data)
397{
398        volatile u16 *addr = (volatile u16 *) dest;
399        ulong result;
400        int rc = ERR_OK;
401        int cflag, iflag;
402        int chip1;
403
404        /*
405         * Check if Flash is (sufficiently) erased
406         */
407        result = *addr;
408        if ((result & data) != data)
409                return ERR_NOT_ERASED;
410
411        /*
412         * Disable interrupts which might cause a timeout
413         * here. Remember that our exception vectors are
414         * at address 0 in the flash, and we don't want a
415         * (ticker) exception to happen while the flash
416         * chip is in programming mode.
417         */
418        cflag = icache_status ();
419        icache_disable ();
420        iflag = disable_interrupts ();
421
422        MEM_FLASH_ADDR1 = CMD_UNLOCK1;
423        MEM_FLASH_ADDR2 = CMD_UNLOCK2;
424        MEM_FLASH_ADDR1 = CMD_PROGRAM;
425        *addr = data;
426
427        /* arm simple, non interrupt dependent timer */
428        reset_timer_masked ();
429
430        /* wait until flash is ready */
431        chip1 = 0;
432        do {
433                result = *addr;
434
435                /* check timeout */
436                if (get_timer_masked () > CFG_FLASH_ERASE_TOUT) {
437                        chip1 = ERR | TMO;
438                        break;
439                }
440                if (!chip1 && ((result & 0x80) == (data & 0x80)))
441                        chip1 = READY;
442
443        } while (!chip1);
444
445        *addr = CMD_READ_ARRAY;
446
447        if (chip1 == ERR || *addr != data)
448                rc = ERR_PROG_ERROR;
449
450        if (iflag)
451                enable_interrupts ();
452
453        if (cflag)
454                icache_enable ();
455
456        return rc;
457}
458
459/*-----------------------------------------------------------------------
460 * Copy memory to flash.
461 */
462
463int write_buff (flash_info_t * info, uchar * src, ulong addr, ulong cnt)
464{
465        ulong wp, data;
466        int rc;
467
468        if (addr & 1) {
469                printf ("unaligned destination not supported\n");
470                return ERR_ALIGN;
471        };
472
473        if ((int) src & 1) {
474                printf ("unaligned source not supported\n");
475                return ERR_ALIGN;
476        };
477
478        wp = addr;
479
480        while (cnt >= 2) {
481                data = *((volatile u16 *) src);
482                if ((rc = write_word (info, wp, data)) != 0) {
483                        return (rc);
484                }
485                src += 2;
486                wp += 2;
487                cnt -= 2;
488        }
489
490        if (cnt == 1) {
491                data = (*((volatile u8 *) src)) | (*((volatile u8 *) (wp + 1)) <<
492                                                                                   8);
493                if ((rc = write_word (info, wp, data)) != 0) {
494                        return (rc);
495                }
496                src += 1;
497                wp += 1;
498                cnt -= 1;
499        };
500
501        return ERR_OK;
502}
Note: See TracBrowser for help on using the repository browser.