source: SVN/rincon/u-boot/board/pm826/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: 8.9 KB
Line 
1/*
2 * (C) Copyright 2001, 2002
3 * Wolfgang Denk, DENX Software Engineering, wd@denx.de.
4 *
5 * Flash Routines for Intel devices
6 *
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 <mpc8xx.h>
29
30
31flash_info_t flash_info[CFG_MAX_FLASH_BANKS];
32
33/*-----------------------------------------------------------------------
34 */
35ulong flash_get_size (volatile unsigned long *baseaddr,
36                                          flash_info_t * info)
37{
38        short i;
39        unsigned long flashtest_h, flashtest_l;
40
41        info->sector_count = info->size = 0;
42        info->flash_id = FLASH_UNKNOWN;
43
44        /* Write query command sequence and test FLASH answer
45         */
46        baseaddr[0] = 0x00980098;
47        baseaddr[1] = 0x00980098;
48
49        flashtest_h = baseaddr[0];      /* manufacturer ID      */
50        flashtest_l = baseaddr[1];
51
52        if (flashtest_h != INTEL_MANUFACT || flashtest_l != INTEL_MANUFACT)
53                return (0);             /* no or unknown flash  */
54
55        flashtest_h = baseaddr[2];      /* device ID            */
56        flashtest_l = baseaddr[3];
57
58        if (flashtest_h != flashtest_l)
59                return (0);
60
61        switch (flashtest_h) {
62        case INTEL_ID_28F160C3B:
63                info->flash_id = FLASH_28F160C3B;
64                info->sector_count = 39;
65                info->size = 0x00800000;        /* 4 * 2 MB = 8 MB      */
66                break;
67        case INTEL_ID_28F160F3B:
68                info->flash_id = FLASH_28F160F3B;
69                info->sector_count = 39;
70                info->size = 0x00800000;        /* 4 * 2 MB = 8 MB      */
71                break;
72        case INTEL_ID_28F640C3B:
73                info->flash_id = FLASH_28F640C3B;
74                info->sector_count = 135;
75                info->size = 0x02000000;        /* 16 * 2 MB = 32 MB    */
76                break;
77        default:
78                return (0);                     /* no or unknown flash  */
79        }
80
81        info->flash_id |= INTEL_MANUFACT << 16; /* set manufacturer offset */
82
83        if (info->flash_id & FLASH_BTYPE) {
84                volatile unsigned long *tmp = baseaddr;
85
86                /* set up sector start adress table (bottom sector type)
87                 * AND unlock the sectors (if our chip is 160C3 or 640C3)
88                 */
89                for (i = 0; i < info->sector_count; i++) {
90                        if (((info->flash_id & FLASH_TYPEMASK) == FLASH_28F160C3B) ||
91                            ((info->flash_id & FLASH_TYPEMASK) == FLASH_28F640C3B)) {
92                                tmp[0] = 0x00600060;
93                                tmp[1] = 0x00600060;
94                                tmp[0] = 0x00D000D0;
95                                tmp[1] = 0x00D000D0;
96                        }
97                        info->start[i] = (uint) tmp;
98                        tmp += i < 8 ? 0x2000 : 0x10000; /* pointer arith       */
99                }
100        }
101
102        memset (info->protect, 0, info->sector_count);
103
104        baseaddr[0] = 0x00FF00FF;
105        baseaddr[1] = 0x00FF00FF;
106
107        return (info->size);
108}
109
110/*-----------------------------------------------------------------------
111 */
112unsigned long flash_init (void)
113{
114        unsigned long size_b0 = 0;
115        int i;
116
117        /* Init: no FLASHes known
118         */
119        for (i = 0; i < CFG_MAX_FLASH_BANKS; ++i) {
120                flash_info[i].flash_id = FLASH_UNKNOWN;
121        }
122
123        /* Static FLASH Bank configuration here (only one bank) */
124
125        size_b0 = flash_get_size ((ulong *) CFG_FLASH0_BASE, &flash_info[0]);
126        if (flash_info[0].flash_id == FLASH_UNKNOWN || size_b0 == 0) {
127                printf ("## Unknown FLASH on Bank 0 - Size = 0x%08lx = %ld MB\n",
128                                size_b0, size_b0 >> 20);
129        }
130
131        /* protect monitor and environment sectors
132         */
133
134#ifndef CONFIG_BOOT_ROM
135        /* If U-Boot is  booted from ROM the CFG_MONITOR_BASE > CFG_FLASH0_BASE
136         * but we shouldn't protect it.
137         */
138
139# if CFG_MONITOR_BASE >= CFG_FLASH0_BASE
140        flash_protect (FLAG_PROTECT_SET,
141                       CFG_MONITOR_BASE,
142                       CFG_MONITOR_BASE + monitor_flash_len - 1, &flash_info[0]
143        );
144# endif
145#endif  /* CONFIG_BOOT_ROM */
146
147#if defined(CONFIG_ENV_IS_IN_FLASH) && defined(CONFIG_ENV_ADDR)
148# ifndef  CONFIG_ENV_SIZE
149#  define CONFIG_ENV_SIZE       CONFIG_ENV_SECT_SIZE
150# endif
151        flash_protect (FLAG_PROTECT_SET,
152                       CONFIG_ENV_ADDR,
153                       CONFIG_ENV_ADDR + CONFIG_ENV_SIZE - 1, &flash_info[0]);
154#endif
155
156        return (size_b0);
157}
158
159/*-----------------------------------------------------------------------
160 */
161void flash_print_info (flash_info_t * info)
162{
163        int i;
164
165        if (info->flash_id == FLASH_UNKNOWN) {
166                printf ("missing or unknown FLASH type\n");
167                return;
168        }
169
170        switch ((info->flash_id >> 16) & 0xff) {
171        case 0x89:
172                printf ("INTEL ");
173                break;
174        default:
175                printf ("Unknown Vendor ");
176                break;
177        }
178
179        switch (info->flash_id & FLASH_TYPEMASK) {
180        case FLASH_28F160C3B:
181                printf ("28F160C3B (16 M, bottom sector)\n");
182                break;
183        case FLASH_28F160F3B:
184                printf ("28F160F3B (16 M, bottom sector)\n");
185                break;
186        case FLASH_28F640C3B:
187                printf ("28F640C3B (64 M, bottom sector)\n");
188                break;
189        default:
190                printf ("Unknown Chip Type\n");
191                break;
192        }
193
194        printf ("  Size: %ld MB in %d Sectors\n",
195                        info->size >> 20, info->sector_count);
196
197        printf ("  Sector Start Addresses:");
198        for (i = 0; i < info->sector_count; ++i) {
199                if ((i % 5) == 0)
200                        printf ("\n   ");
201                printf (" %08lX%s",
202                        info->start[i],
203                        info->protect[i] ? " (RO)" : "     "
204                );
205        }
206        printf ("\n");
207}
208
209/*-----------------------------------------------------------------------
210 */
211int flash_erase (flash_info_t * info, int s_first, int s_last)
212{
213        int flag, prot, sect;
214        ulong start, now, last;
215
216        if ((s_first < 0) || (s_first > s_last)) {
217                if (info->flash_id == FLASH_UNKNOWN) {
218                        printf ("- missing\n");
219                } else {
220                        printf ("- no sectors to erase\n");
221                }
222                return 1;
223        }
224
225        prot = 0;
226        for (sect = s_first; sect <= s_last; sect++) {
227                if (info->protect[sect])
228                        prot++;
229        }
230
231        if (prot) {
232                printf ("- Warning: %d protected sectors will not be erased!\n",
233                                prot);
234        } else {
235                printf ("\n");
236        }
237
238        /* Start erase on unprotected sectors
239         */
240        for (sect = s_first; sect <= s_last; sect++) {
241                volatile ulong *addr =
242                                (volatile unsigned long *) info->start[sect];
243
244                start = get_timer (0);
245                last = start;
246                if (info->protect[sect] == 0) {
247                        /* Disable interrupts which might cause a timeout here
248                         */
249                        flag = disable_interrupts ();
250
251                        /* Erase the block
252                         */
253                        addr[0] = 0x00200020;
254                        addr[1] = 0x00200020;
255                        addr[0] = 0x00D000D0;
256                        addr[1] = 0x00D000D0;
257
258                        /* re-enable interrupts if necessary
259                         */
260                        if (flag)
261                                enable_interrupts ();
262
263                        /* wait at least 80us - let's wait 1 ms
264                         */
265                        udelay (1000);
266
267                        last = start;
268                        while ((addr[0] & 0x00800080) != 0x00800080 ||
269                                   (addr[1] & 0x00800080) != 0x00800080) {
270                                if ((now = get_timer (start)) > CFG_FLASH_ERASE_TOUT) {
271                                        printf ("Timeout (erase suspended!)\n");
272                                        /* Suspend erase
273                                         */
274                                        addr[0] = 0x00B000B0;
275                                        addr[1] = 0x00B000B0;
276                                        goto DONE;
277                                }
278                                /* show that we're waiting
279                                 */
280                                if ((now - last) > 1000) {      /* every second */
281                                        serial_putc ('.');
282                                        last = now;
283                                }
284                        }
285                        if (addr[0] & 0x00220022 || addr[1] & 0x00220022) {
286                                printf ("*** ERROR: erase failed!\n");
287                                goto DONE;
288                        }
289                }
290                /* Clear status register and reset to read mode
291                 */
292                addr[0] = 0x00500050;
293                addr[1] = 0x00500050;
294                addr[0] = 0x00FF00FF;
295                addr[1] = 0x00FF00FF;
296        }
297
298        printf (" done\n");
299
300DONE:
301        return 0;
302}
303
304static int write_word (flash_info_t *, volatile unsigned long *, ulong);
305
306/*-----------------------------------------------------------------------
307 * Copy memory to flash, returns:
308 * 0 - OK
309 * 1 - write timeout
310 * 2 - Flash not erased
311 */
312int write_buff (flash_info_t * info, uchar * src, ulong addr, ulong cnt)
313{
314        ulong v;
315        int i, l, cc = cnt, res = 0;
316
317
318        for (v=0; cc > 0; addr += 4, cc -= 4 - l) {
319                l = (addr & 3);
320                addr &= ~3;
321
322                for (i = 0; i < 4; i++) {
323                        v = (v << 8) + (i < l || i - l >= cc ?
324                                *((unsigned char *) addr + i) : *src++);
325                }
326
327                if ((res = write_word (info, (volatile unsigned long *) addr, v)) != 0)
328                        break;
329        }
330
331        return (res);
332}
333
334/*-----------------------------------------------------------------------
335 * Write a word to Flash, returns:
336 * 0 - OK
337 * 1 - write timeout
338 * 2 - Flash not erased
339 */
340static int write_word (flash_info_t * info, volatile unsigned long *addr,
341                                           ulong data)
342{
343        int flag, res = 0;
344        ulong start;
345
346        /* Check if Flash is (sufficiently) erased
347         */
348        if ((*addr & data) != data)
349                return (2);
350
351        /* Disable interrupts which might cause a timeout here
352         */
353        flag = disable_interrupts ();
354
355        *addr = 0x00400040;
356        *addr = data;
357
358        /* re-enable interrupts if necessary
359         */
360        if (flag)
361                enable_interrupts ();
362
363        start = get_timer (0);
364        while ((*addr & 0x00800080) != 0x00800080) {
365                if (get_timer (start) > CFG_FLASH_WRITE_TOUT) {
366                        /* Suspend program
367                         */
368                        *addr = 0x00B000B0;
369                        res = 1;
370                        goto OUT;
371                }
372        }
373
374        if (*addr & 0x00220022) {
375                printf ("*** ERROR: program failed!\n");
376                res = 1;
377        }
378
379OUT:
380        /* Clear status register and reset to read mode
381         */
382        *addr = 0x00500050;
383        *addr = 0x00FF00FF;
384
385        return (res);
386}
Note: See TracBrowser for help on using the repository browser.