source: SVN/rincon/u-boot/board/mpl/vcma9/flash.c @ 55

Last change on this file since 55 was 55, checked in by Tim Harvey, 2 years ago

rincon: added latest u-boot source

restored form server backup

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

File size: 9.1 KB
Line 
1/*
2 * (C) Copyright 2002
3 * Sysgo Real-Time Solutions, GmbH <www.elinos.com>
4 * Alex Zuepke <azu@sysgo.de>
5 *
6 * See file CREDITS for list of people who contributed to this
7 * project.
8 *
9 * This program is free software; you can redistribute it and/or
10 * modify it under the terms of the GNU General Public License as
11 * published by the Free Software Foundation; either version 2 of
12 * the License, or (at your option) any later version.
13 *
14 * This program is distributed in the hope that it will be useful,
15 * but WITHOUT ANY WARRANTY; without even the implied warranty of
16 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
17 * GNU General Public License for more details.
18 *
19 * You should have received a copy of the GNU General Public License
20 * along with this program; if not, write to the Free Software
21 * Foundation, Inc., 59 Temple Place, Suite 330, Boston,
22 * MA 02111-1307 USA
23 */
24
25#include <common.h>
26
27ulong myflush (void);
28
29
30#define FLASH_BANK_SIZE PHYS_FLASH_SIZE
31#define MAIN_SECT_SIZE  0x10000 /* 64 KB */
32
33flash_info_t flash_info[CFG_MAX_FLASH_BANKS];
34
35
36#define CMD_READ_ARRAY          0x000000F0
37#define CMD_UNLOCK1             0x000000AA
38#define CMD_UNLOCK2             0x00000055
39#define CMD_ERASE_SETUP         0x00000080
40#define CMD_ERASE_CONFIRM       0x00000030
41#define CMD_PROGRAM             0x000000A0
42#define CMD_UNLOCK_BYPASS       0x00000020
43
44#define MEM_FLASH_ADDR1         (*(volatile u16 *)(CFG_FLASH_BASE + (0x00000555 << 1)))
45#define MEM_FLASH_ADDR2         (*(volatile u16 *)(CFG_FLASH_BASE + (0x000002AA << 1)))
46
47#define BIT_ERASE_DONE          0x00000080
48#define BIT_RDY_MASK            0x00000080
49#define BIT_PROGRAM_ERROR       0x00000020
50#define BIT_TIMEOUT             0x80000000      /* our flag */
51
52#define READY 1
53#define ERR   2
54#define TMO   4
55
56/*-----------------------------------------------------------------------
57 */
58
59ulong flash_init (void)
60{
61        int i, j;
62        ulong size = 0;
63
64        for (i = 0; i < CFG_MAX_FLASH_BANKS; i++) {
65                ulong flashbase = 0;
66
67                flash_info[i].flash_id =
68#if defined(CONFIG_AMD_LV400)
69                        (AMD_MANUFACT & FLASH_VENDMASK) |
70                        (AMD_ID_LV400B & FLASH_TYPEMASK);
71#elif defined(CONFIG_AMD_LV800)
72                        (AMD_MANUFACT & FLASH_VENDMASK) |
73                        (AMD_ID_LV800B & FLASH_TYPEMASK);
74#else
75#error "Unknown flash configured"
76#endif
77                        flash_info[i].size = FLASH_BANK_SIZE;
78                flash_info[i].sector_count = CFG_MAX_FLASH_SECT;
79                memset (flash_info[i].protect, 0, CFG_MAX_FLASH_SECT);
80                if (i == 0)
81                        flashbase = PHYS_FLASH_1;
82                else
83                        panic ("configured too many flash banks!\n");
84                for (j = 0; j < flash_info[i].sector_count; j++) {
85                        if (j <= 3) {
86                                /* 1st one is 16 KB */
87                                if (j == 0) {
88                                        flash_info[i].start[j] =
89                                                flashbase + 0;
90                                }
91
92                                /* 2nd and 3rd are both 8 KB */
93                                if ((j == 1) || (j == 2)) {
94                                        flash_info[i].start[j] =
95                                                flashbase + 0x4000 + (j -
96                                                                      1) *
97                                                0x2000;
98                                }
99
100                                /* 4th 32 KB */
101                                if (j == 3) {
102                                        flash_info[i].start[j] =
103                                                flashbase + 0x8000;
104                                }
105                        } else {
106                                flash_info[i].start[j] =
107                                        flashbase + (j - 3) * MAIN_SECT_SIZE;
108                        }
109                }
110                size += flash_info[i].size;
111        }
112
113        flash_protect (FLAG_PROTECT_SET,
114                       CFG_FLASH_BASE,
115                       CFG_FLASH_BASE + monitor_flash_len - 1,
116                       &flash_info[0]);
117
118        flash_protect (FLAG_PROTECT_SET,
119                       CONFIG_ENV_ADDR,
120                       CONFIG_ENV_ADDR + CONFIG_ENV_SIZE - 1, &flash_info[0]);
121
122        return size;
123}
124
125/*-----------------------------------------------------------------------
126 */
127void flash_print_info (flash_info_t * info)
128{
129        int i;
130
131        switch (info->flash_id & FLASH_VENDMASK) {
132        case (AMD_MANUFACT & FLASH_VENDMASK):
133                puts ("AMD: ");
134                break;
135        default:
136                puts ("Unknown Vendor ");
137                break;
138        }
139
140        switch (info->flash_id & FLASH_TYPEMASK) {
141        case (AMD_ID_LV400B & FLASH_TYPEMASK):
142                puts ("1x Amd29LV400BB (4Mbit)\n");
143                break;
144        case (AMD_ID_LV800B & FLASH_TYPEMASK):
145                puts ("1x Amd29LV800BB (8Mbit)\n");
146                break;
147        default:
148                puts ("Unknown Chip Type\n");
149                goto Done;
150                break;
151        }
152
153        printf ("  Size: %ld MB in %d Sectors\n",
154                info->size >> 20, info->sector_count);
155
156        puts ("  Sector Start Addresses:");
157        for (i = 0; i < info->sector_count; i++) {
158                if ((i % 5) == 0) {
159                        puts ("\n   ");
160                }
161                printf (" %08lX%s", info->start[i],
162                        info->protect[i] ? " (RO)" : "     ");
163        }
164        puts ("\n");
165
166Done:   ;
167}
168
169/*-----------------------------------------------------------------------
170 */
171
172int flash_erase (flash_info_t * info, int s_first, int s_last)
173{
174        ushort result;
175        int iflag, cflag, prot, sect;
176        int rc = ERR_OK;
177        int chip;
178
179        /* first look for protection bits */
180
181        if (info->flash_id == FLASH_UNKNOWN)
182                return ERR_UNKNOWN_FLASH_TYPE;
183
184        if ((s_first < 0) || (s_first > s_last)) {
185                return ERR_INVAL;
186        }
187
188        if ((info->flash_id & FLASH_VENDMASK) !=
189            (AMD_MANUFACT & FLASH_VENDMASK)) {
190                return ERR_UNKNOWN_FLASH_VENDOR;
191        }
192
193        prot = 0;
194        for (sect = s_first; sect <= s_last; ++sect) {
195                if (info->protect[sect]) {
196                        prot++;
197                }
198        }
199        if (prot)
200                return ERR_PROTECTED;
201
202        /*
203         * Disable interrupts which might cause a timeout
204         * here. Remember that our exception vectors are
205         * at address 0 in the flash, and we don't want a
206         * (ticker) exception to happen while the flash
207         * chip is in programming mode.
208         */
209        cflag = icache_status ();
210        icache_disable ();
211        iflag = disable_interrupts ();
212
213        /* Start erase on unprotected sectors */
214        for (sect = s_first; sect <= s_last && !ctrlc (); sect++) {
215                printf ("Erasing sector %2d ... ", sect);
216
217                /* arm simple, non interrupt dependent timer */
218                reset_timer_masked ();
219
220                if (info->protect[sect] == 0) { /* not protected */
221                        vu_short *addr = (vu_short *) (info->start[sect]);
222
223                        MEM_FLASH_ADDR1 = CMD_UNLOCK1;
224                        MEM_FLASH_ADDR2 = CMD_UNLOCK2;
225                        MEM_FLASH_ADDR1 = CMD_ERASE_SETUP;
226
227                        MEM_FLASH_ADDR1 = CMD_UNLOCK1;
228                        MEM_FLASH_ADDR2 = CMD_UNLOCK2;
229                        *addr = CMD_ERASE_CONFIRM;
230
231                        /* wait until flash is ready */
232                        chip = 0;
233
234                        do {
235                                result = *addr;
236
237                                /* check timeout */
238                                if (get_timer_masked () >
239                                    CFG_FLASH_ERASE_TOUT) {
240                                        MEM_FLASH_ADDR1 = CMD_READ_ARRAY;
241                                        chip = TMO;
242                                        break;
243                                }
244
245                                if (!chip
246                                    && (result & 0xFFFF) & BIT_ERASE_DONE)
247                                        chip = READY;
248
249                                if (!chip
250                                    && (result & 0xFFFF) & BIT_PROGRAM_ERROR)
251                                        chip = ERR;
252
253                        } while (!chip);
254
255                        MEM_FLASH_ADDR1 = CMD_READ_ARRAY;
256
257                        if (chip == ERR) {
258                                rc = ERR_PROG_ERROR;
259                                goto outahere;
260                        }
261                        if (chip == TMO) {
262                                rc = ERR_TIMOUT;
263                                goto outahere;
264                        }
265
266                        puts ("ok.\n");
267                } else {        /* it was protected */
268
269                        puts ("protected!\n");
270                }
271        }
272
273        if (ctrlc ())
274                puts ("User Interrupt!\n");
275
276      outahere:
277        /* allow flash to settle - wait 10 ms */
278        udelay_masked (10000);
279
280        if (iflag)
281                enable_interrupts ();
282
283        if (cflag)
284                icache_enable ();
285
286        return rc;
287}
288
289/*-----------------------------------------------------------------------
290 * Copy memory to flash
291 */
292
293static int write_hword (flash_info_t * info, ulong dest, ushort data)
294{
295        vu_short *addr = (vu_short *) dest;
296        ushort result;
297        int rc = ERR_OK;
298        int cflag, iflag;
299        int chip;
300
301        /*
302         * Check if Flash is (sufficiently) erased
303         */
304        result = *addr;
305        if ((result & data) != data)
306                return ERR_NOT_ERASED;
307
308
309        /*
310         * Disable interrupts which might cause a timeout
311         * here. Remember that our exception vectors are
312         * at address 0 in the flash, and we don't want a
313         * (ticker) exception to happen while the flash
314         * chip is in programming mode.
315         */
316        cflag = icache_status ();
317        icache_disable ();
318        iflag = disable_interrupts ();
319
320        MEM_FLASH_ADDR1 = CMD_UNLOCK1;
321        MEM_FLASH_ADDR2 = CMD_UNLOCK2;
322        MEM_FLASH_ADDR1 = CMD_PROGRAM;
323        *addr = data;
324
325        /* arm simple, non interrupt dependent timer */
326        reset_timer_masked ();
327
328        /* wait until flash is ready */
329        chip = 0;
330        do {
331                result = *addr;
332
333                /* check timeout */
334                if (get_timer_masked () > CFG_FLASH_ERASE_TOUT) {
335                        chip = ERR | TMO;
336                        break;
337                }
338                if (!chip && ((result & 0x80) == (data & 0x80)))
339                        chip = READY;
340
341                if (!chip && ((result & 0xFFFF) & BIT_PROGRAM_ERROR)) {
342                        result = *addr;
343
344                        if ((result & 0x80) == (data & 0x80))
345                                chip = READY;
346                        else
347                                chip = ERR;
348                }
349
350        } while (!chip);
351
352        *addr = CMD_READ_ARRAY;
353
354        if (chip == ERR || *addr != data)
355                rc = ERR_PROG_ERROR;
356
357        if (iflag)
358                enable_interrupts ();
359
360        if (cflag)
361                icache_enable ();
362
363        return rc;
364}
365
366/*-----------------------------------------------------------------------
367 * Copy memory to flash.
368 */
369
370int write_buff (flash_info_t * info, uchar * src, ulong addr, ulong cnt)
371{
372        ulong cp, wp;
373        int l;
374        int i, rc;
375        ushort data;
376
377        wp = (addr & ~1);       /* get lower word aligned address */
378
379        /*
380         * handle unaligned start bytes
381         */
382        if ((l = addr - wp) != 0) {
383                data = 0;
384                for (i = 0, cp = wp; i < l; ++i, ++cp) {
385                        data = (data >> 8) | (*(uchar *) cp << 8);
386                }
387                for (; i < 2 && cnt > 0; ++i) {
388                        data = (data >> 8) | (*src++ << 8);
389                        --cnt;
390                        ++cp;
391                }
392                for (; cnt == 0 && i < 2; ++i, ++cp) {
393                        data = (data >> 8) | (*(uchar *) cp << 8);
394                }
395
396                if ((rc = write_hword (info, wp, data)) != 0) {
397                        return (rc);
398                }
399                wp += 2;
400        }
401
402        /*
403         * handle word aligned part
404         */
405        while (cnt >= 2) {
406                data = *((vu_short *) src);
407                if ((rc = write_hword (info, wp, data)) != 0) {
408                        return (rc);
409                }
410                src += 2;
411                wp += 2;
412                cnt -= 2;
413        }
414
415        if (cnt == 0) {
416                return ERR_OK;
417        }
418
419        /*
420         * handle unaligned tail bytes
421         */
422        data = 0;
423        for (i = 0, cp = wp; i < 2 && cnt > 0; ++i, ++cp) {
424                data = (data >> 8) | (*src++ << 8);
425                --cnt;
426        }
427        for (; i < 2; ++i, ++cp) {
428                data = (data >> 8) | (*(uchar *) cp << 8);
429        }
430
431        return write_hword (info, wp, data);
432}
Note: See TracBrowser for help on using the repository browser.