source: SVN/rincon/u-boot/board/evb4510/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: 13.0 KB
Line 
1/*
2 *
3 * Copyright (c) 2004   Cucy Systems (http://www.cucy.com)
4 * Curt Brune <curt@cucy.com>
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#include <asm/hardware.h>
27#include <flash.h>
28
29flash_info_t flash_info[CFG_MAX_FLASH_BANKS];
30
31typedef enum {
32        FLASH_DEV_U9_512KB = 0,
33        FLASH_DEV_U7_2MB = 1
34} FLASH_DEV;
35
36#define FLASH_DQ7               (0x80)
37#define FLASH_DQ5               (0x20)
38
39#define PROG_ADDR               (0xAAA)
40#define SETUP_ADDR              (0xAAA)
41#define ID_ADDR                 (0xAAA)
42#define UNLOCK_ADDR1            (0xAAA)
43#define UNLOCK_ADDR2            (0x555)
44
45#define UNLOCK_CMD1             (0xAA)
46#define UNLOCK_CMD2             (0x55)
47#define ERASE_SUSPEND_CMD       (0xB0)
48#define ERASE_RESUME_CMD        (0x30)
49#define RESET_CMD               (0xF0)
50#define ID_CMD                  (0x90)
51#define SELECT_CMD              (0x90)
52#define CHIPERASE_CMD           (0x10)
53#define BYPASS_CMD              (0x20)
54#define SECERASE_CMD            (0x30)
55#define PROG_CMD                (0xa0)
56#define SETUP_CMD               (0x80)
57
58#if 0
59#define WRITE_UNLOCK(addr) { \
60        PUT__U8( addr + UNLOCK_ADDR1, UNLOCK_CMD1); \
61        PUT__U8( addr + UNLOCK_ADDR2, UNLOCK_CMD2); \
62}
63
64/* auto select command */
65#define CMD_ID(addr) WRITE_UNLOCK(addr); { \
66        PUT__U8( addr + ID_ADDR, ID_CMD); \
67}
68
69#define CMD_RESET(addr) WRITE_UNLOCK(addr); { \
70        PUT__U8( addr + ID_ADDR, RESET_CMD); \
71}
72
73#define CMD_ERASE_SEC(base, addr) WRITE_UNLOCK(base); \
74        PUT__U8( base + SETUP_ADDR, SETUP_CMD); \
75        WRITE_UNLOCK(base); \
76        PUT__U8( addr, SECERASE_CMD);
77
78#define CMD_ERASE_CHIP(base) WRITE_UNLOCK(base); \
79        PUT__U8( base + SETUP_ADDR, SETUP_CMD); \
80        WRITE_UNLOCK(base); \
81        PUT__U8( base + SETUP_ADDR, CHIPERASE_CMD);
82
83/* prepare for bypass programming */
84#define CMD_UNLOCK_BYPASS(addr) WRITE_UNLOCK(addr); { \
85        PUT__U8( addr + ID_ADDR, 0x20); \
86}
87
88/* terminate bypass programming */
89#define CMD_BYPASS_RESET(addr) { \
90        PUT__U8(addr, 0x90); \
91        PUT__U8(addr, 0x00); \
92}
93#endif
94
95inline static void FLASH_CMD_UNLOCK (FLASH_DEV dev, u32 base)
96{
97        switch (dev) {
98        case FLASH_DEV_U7_2MB:
99                PUT__U8 (base + 0xAAA, 0xAA);
100                PUT__U8 (base + 0x555, 0x55);
101                break;
102        case FLASH_DEV_U9_512KB:
103                PUT__U8 (base + 0x555, 0xAA);
104                PUT__U8 (base + 0x2AA, 0x55);
105                break;
106        }
107}
108
109inline static void FLASH_CMD_SELECT (FLASH_DEV dev, u32 base)
110{
111        switch (dev) {
112        case FLASH_DEV_U7_2MB:
113                FLASH_CMD_UNLOCK (dev, base);
114                PUT__U8 (base + 0xAAA, SELECT_CMD);
115                break;
116        case FLASH_DEV_U9_512KB:
117                FLASH_CMD_UNLOCK (dev, base);
118                PUT__U8 (base + 0x555, SELECT_CMD);
119                break;
120        }
121}
122
123inline static void FLASH_CMD_RESET (FLASH_DEV dev, u32 base)
124{
125        switch (dev) {
126        case FLASH_DEV_U7_2MB:
127                FLASH_CMD_UNLOCK (dev, base);
128                PUT__U8 (base + 0xAAA, RESET_CMD);
129                break;
130        case FLASH_DEV_U9_512KB:
131                FLASH_CMD_UNLOCK (dev, base);
132                PUT__U8 (base + 0x555, RESET_CMD);
133                break;
134        }
135}
136
137inline static void FLASH_CMD_ERASE_SEC (FLASH_DEV dev, u32 base, u32 addr)
138{
139        switch (dev) {
140        case FLASH_DEV_U7_2MB:
141                FLASH_CMD_UNLOCK (dev, base);
142                PUT__U8 (base + 0xAAA, SETUP_CMD);
143                FLASH_CMD_UNLOCK (dev, base);
144                PUT__U8 (addr, SECERASE_CMD);
145                break;
146        case FLASH_DEV_U9_512KB:
147                FLASH_CMD_UNLOCK (dev, base);
148                PUT__U8 (base + 0x555, SETUP_CMD);
149                FLASH_CMD_UNLOCK (dev, base);
150                PUT__U8 (addr, SECERASE_CMD);
151                break;
152        }
153}
154
155inline static void FLASH_CMD_ERASE_CHIP (FLASH_DEV dev, u32 base)
156{
157        switch (dev) {
158        case FLASH_DEV_U7_2MB:
159                FLASH_CMD_UNLOCK (dev, base);
160                PUT__U8 (base + 0xAAA, SETUP_CMD);
161                FLASH_CMD_UNLOCK (dev, base);
162                PUT__U8 (base, CHIPERASE_CMD);
163                break;
164        case FLASH_DEV_U9_512KB:
165                FLASH_CMD_UNLOCK (dev, base);
166                PUT__U8 (base + 0x555, SETUP_CMD);
167                FLASH_CMD_UNLOCK (dev, base);
168                PUT__U8 (base, CHIPERASE_CMD);
169                break;
170        }
171}
172
173inline static void FLASH_CMD_UNLOCK_BYPASS (FLASH_DEV dev, u32 base)
174{
175        switch (dev) {
176        case FLASH_DEV_U7_2MB:
177                FLASH_CMD_UNLOCK (dev, base);
178                PUT__U8 (base + 0xAAA, BYPASS_CMD);
179                break;
180        case FLASH_DEV_U9_512KB:
181                FLASH_CMD_UNLOCK (dev, base);
182                PUT__U8 (base + 0x555, BYPASS_CMD);
183                break;
184        }
185}
186
187inline static void FLASH_CMD_BYPASS_RESET (FLASH_DEV dev, u32 base)
188{
189        PUT__U8 (base, SELECT_CMD);
190        PUT__U8 (base, 0x0);
191}
192
193/* poll for flash command completion */
194static u16 _flash_poll (FLASH_DEV dev, u32 addr, u16 data, ulong timeOut)
195{
196        u32 done = 0;
197        ulong t0;
198
199        u16 error = 0;
200        volatile u16 flashData;
201
202        data = data & 0xFF;
203        t0 = get_timer (0);
204        while (get_timer (t0) < timeOut) {
205                /*      for( i = 0; i < POLL_LOOPS; i++) { */
206                /*  Read the Data */
207                flashData = GET__U8 (addr);
208
209                /*  FLASH_DQ7 = Data? */
210                if ((flashData & FLASH_DQ7) == (data & FLASH_DQ7)) {
211                        done = 1;
212                        break;
213                }
214
215                /*  Check Timeout (FLASH_DQ5==1) */
216                if (flashData & FLASH_DQ5) {
217                        /*  Read the Data */
218                        flashData = GET__U8 (addr);
219
220                        /*  FLASH_DQ7 = Data? */
221                        if (!((flashData & FLASH_DQ7) == (data & FLASH_DQ7))) {
222                                printf ("_flash_poll(): FLASH_DQ7 & flashData not equal to write value\n");
223                                error = ERR_PROG_ERROR;
224                        }
225                        FLASH_CMD_RESET (dev, addr);
226                        done = 1;
227                        break;
228                }
229                /*  spin delay */
230                udelay (10);
231        }
232
233
234        /*  error update */
235        if (!done) {
236                printf ("_flash_poll(): Timeout\n");
237                error = ERR_TIMOUT;
238        }
239
240        /*  Check the data */
241        if (!error) {
242                /*  Read the Data */
243                flashData = GET__U8 (addr);
244                if (flashData != data) {
245                        error = ERR_PROG_ERROR;
246                        printf ("_flash_poll(): flashData(0x%04x) not equal to data(0x%04x)\n",
247                                flashData, data);
248                }
249        }
250
251        return error;
252}
253
254/*-----------------------------------------------------------------------
255 */
256static int _flash_check_protection (flash_info_t * info, int s_first, int s_last)
257{
258        int sect, prot = 0;
259
260        for (sect = s_first; sect <= s_last; sect++)
261                if (info->protect[sect]) {
262                        printf ("  Flash sector %d protected.\n", sect);
263                        prot++;
264                }
265        return prot;
266}
267
268static int _detectFlash (FLASH_DEV dev, u32 base, u8 venId, u8 devId)
269{
270
271        u32 baseAddr = base | CACHE_DISABLE_MASK;
272        u8 vendorId, deviceId;
273
274        /*      printf(__FUNCTION__"(): detecting flash @ 0x%08x\n", base); */
275
276        /* Send auto select command and read manufacturer info */
277        FLASH_CMD_SELECT (dev, baseAddr);
278        vendorId = GET__U8 (baseAddr);
279        FLASH_CMD_RESET (dev, baseAddr);
280
281        /* Send auto select command and read device info */
282        FLASH_CMD_SELECT (dev, baseAddr);
283
284        if (dev == FLASH_DEV_U7_2MB) {
285                deviceId = GET__U8 (baseAddr + 2);
286        } else if (dev == FLASH_DEV_U9_512KB) {
287                deviceId = GET__U8 (baseAddr + 1);
288        } else {
289                return 0;
290        }
291
292        FLASH_CMD_RESET (dev, baseAddr);
293
294        /* printf (__FUNCTION__"(): found vendorId 0x%04x, deviceId 0x%04x\n",
295                vendorId, deviceId);
296         */
297
298        return (vendorId == venId) && (deviceId == devId);
299
300}
301
302/******************************************************************************
303 *
304 * Public u-boot interface functions below
305 *
306 *****************************************************************************/
307
308/***************************************************************************
309 *
310 * Flash initialization
311 *
312 * This board has two banks of flash, but the base addresses depend on
313 * how the board is jumpered.
314 *
315 * The two flash types are:
316 *
317 *   AMD Am29LV160DB (2MB) sectors layout 16KB, 2x8KB, 32KB, 31x64KB
318 *
319 *   AMD Am29LV040B  (512KB)  sectors: 8x64KB
320 *****************************************************************************/
321
322unsigned long flash_init (void)
323{
324        flash_info_t *info;
325        u16 i;
326        u32 flashtest;
327        s16 amd160 = -1;
328        u32 amd160base = 0;
329
330#if CFG_MAX_FLASH_BANKS == 2
331        s16 amd040 = -1;
332        u32 amd040base = 0;
333#endif
334
335        /* configure PHYS_FLASH_1 */
336        if (_detectFlash (FLASH_DEV_U7_2MB, PHYS_FLASH_1, 0x1, 0x49)) {
337                amd160 = 0;
338                amd160base = PHYS_FLASH_1;
339#if CFG_MAX_FLASH_BANKS == 1
340        }
341#else
342                if (_detectFlash
343                    (FLASH_DEV_U9_512KB, PHYS_FLASH_2, 0x1, 0x4F)) {
344                        amd040 = 1;
345                        amd040base = PHYS_FLASH_2;
346                } else {
347                        printf (__FUNCTION__
348                                "(): Unable to detect PHYS_FLASH_2: 0x%08x\n",
349                                PHYS_FLASH_2);
350                }
351        } else if (_detectFlash (FLASH_DEV_U9_512KB, PHYS_FLASH_1, 0x1, 0x4F)) {
352                amd040 = 0;
353                amd040base = PHYS_FLASH_1;
354                if (_detectFlash (FLASH_DEV_U7_2MB, PHYS_FLASH_2, 0x1, 0x49)) {
355                        amd160 = 1;
356                        amd160base = PHYS_FLASH_2;
357                } else {
358                        printf (__FUNCTION__
359                                "(): Unable to detect PHYS_FLASH_2: 0x%08x\n",
360                                PHYS_FLASH_2);
361                }
362        }
363#endif
364        else {
365                printf ("flash_init(): Unable to detect PHYS_FLASH_1: 0x%08x\n",
366                        PHYS_FLASH_1);
367        }
368
369        /* Configure AMD Am29LV160DB (2MB) */
370        info = &flash_info[amd160];
371        info->flash_id = FLASH_DEV_U7_2MB;
372        info->sector_count = 35;
373        info->size = 2 * 1024 * 1024;   /* 2MB */
374        /* 1*16K Boot Block
375           2*8K Parameter Block
376           1*32K Small Main Block */
377        info->start[0] = amd160base;
378        info->start[1] = amd160base + 0x4000;
379        info->start[2] = amd160base + 0x6000;
380        info->start[3] = amd160base + 0x8000;
381        for (i = 1; i < info->sector_count; i++)
382                info->start[3 + i] = amd160base + i * (64 * 1024);
383
384        for (i = 0; i < info->sector_count; i++) {
385                /* Write auto select command sequence and query sector protection */
386                FLASH_CMD_SELECT (info->flash_id,
387                                  info->start[i] | CACHE_DISABLE_MASK);
388                flashtest =
389                        GET__U8 (((info->start[i] + 4) | CACHE_DISABLE_MASK));
390                FLASH_CMD_RESET (info->flash_id,
391                                 amd160base | CACHE_DISABLE_MASK);
392                info->protect[i] = (flashtest & 0x0001);
393        }
394
395        /*
396         * protect monitor and environment sectors in 2MB flash
397         */
398        flash_protect (FLAG_PROTECT_SET,
399                       amd160base, amd160base + monitor_flash_len - 1, info);
400
401        flash_protect (FLAG_PROTECT_SET,
402                       CONFIG_ENV_ADDR, CONFIG_ENV_ADDR + CONFIG_ENV_SIZE - 1, info);
403
404#if CFG_MAX_FLASH_BANKS == 2
405        /* Configure AMD Am29LV040B (512KB) */
406        info = &flash_info[amd040];
407        info->flash_id = FLASH_DEV_U9_512KB;
408        info->sector_count = 8;
409        info->size = 512 * 1024;        /* 512KB, 8 x 64KB */
410        for (i = 0; i < info->sector_count; i++) {
411                info->start[i] = amd040base + i * (64 * 1024);
412                /* Write auto select command sequence and query sector protection */
413                FLASH_CMD_SELECT (info->flash_id,
414                                  info->start[i] | CACHE_DISABLE_MASK);
415                flashtest =
416                        GET__U8 (((info->start[i] + 2) | CACHE_DISABLE_MASK));
417                FLASH_CMD_RESET (info->flash_id,
418                                 amd040base | CACHE_DISABLE_MASK);
419                info->protect[i] = (flashtest & 0x0001);
420        }
421#endif
422
423        return flash_info[0].size
424#if CFG_MAX_FLASH_BANKS == 2
425                + flash_info[1].size
426#endif
427                ;
428}
429
430void flash_print_info (flash_info_t * info)
431{
432        int i;
433
434        if (info->flash_id == FLASH_DEV_U7_2MB) {
435                printf ("AMD Am29LV160DB (2MB) 16KB,2x8KB,32KB,31x64KB\n");
436        } else if (info->flash_id == FLASH_DEV_U9_512KB) {
437                printf ("AMD Am29LV040B  (512KB) 8x64KB\n");
438        } else {
439                printf ("Unknown flash_id ...\n");
440                return;
441        }
442
443        printf ("  Size: %ld KB in %d Sectors\n",
444                info->size >> 10, info->sector_count);
445        printf ("  Sector Start Addresses:");
446        for (i = 0; i < info->sector_count; i++) {
447                if ((i % 4) == 0)
448                        printf ("\n   ");
449                printf (" S%02d @ 0x%08lX%s", i,
450                        info->start[i], info->protect[i] ? " !" : "  ");
451        }
452        printf ("\n");
453}
454
455int flash_erase (flash_info_t * info, int s_first, int s_last)
456{
457        u16 i, error = 0;
458
459        printf ("\n");
460
461        /* check flash protection bits */
462        if (_flash_check_protection (info, s_first, s_last)) {
463                printf ("  Flash erase aborted due to protected sectors\n");
464                return ERR_PROTECTED;
465        }
466
467        if ((s_first < info->sector_count) && (s_first <= s_last)) {
468                for (i = s_first; i <= s_last && !error; i++) {
469                        printf ("  Erasing Sector %d @ 0x%08lx ... ", i,
470                                info->start[i]);
471                        /* bypass the cache to access the flash memory */
472                        FLASH_CMD_ERASE_SEC (info->flash_id,
473                                             (info->
474                                              start[0] | CACHE_DISABLE_MASK),
475                                             (info->
476                                              start[i] | CACHE_DISABLE_MASK));
477                        /* look for sector to become 0xFF after erase */
478                        error = _flash_poll (info->flash_id,
479                                             info->
480                                             start[i] | CACHE_DISABLE_MASK,
481                                             0xFF, CFG_FLASH_ERASE_TOUT);
482                        FLASH_CMD_RESET (info->flash_id,
483                                         (info->
484                                          start[0] | CACHE_DISABLE_MASK));
485                        printf ("done\n");
486                        if (error) {
487                                break;
488                        }
489                }
490        } else
491                error = ERR_INVAL;
492
493        return error;
494}
495
496int write_buff (flash_info_t * info, uchar * src, ulong addr, ulong cnt)
497{
498        u16 error = 0, i;
499        u32 n;
500        u8 *bp, *bps;
501
502        /*  Write Setup */
503        /* bypass the cache to access the flash memory */
504        FLASH_CMD_UNLOCK_BYPASS (info->flash_id,
505                                 (info->start[0] | CACHE_DISABLE_MASK));
506
507        /*  Write the Data to Flash */
508
509        bp = (u8 *) (addr | CACHE_DISABLE_MASK);
510        bps = (u8 *) src;
511
512        for (n = 0; n < cnt && !error; n++, bp++, bps++) {
513
514                if (!(n % (cnt / 15))) {
515                        printf (".");
516                }
517
518                /*  write the flash command for flash memory */
519                *bp = 0xA0;
520
521                /*  Write the data */
522                *bp = *bps;
523
524                /*  Check if the write is done */
525                for (i = 0; i < 0xff; i++);
526                error = _flash_poll (info->flash_id, (u32) bp, *bps,
527                                     CFG_FLASH_WRITE_TOUT);
528                if (error) {
529                        return error;
530                }
531        }
532
533        /*  Reset the Flash Mode to read */
534        FLASH_CMD_BYPASS_RESET (info->flash_id, info->start[0]);
535
536        printf (" ");
537
538        return error;
539}
Note: See TracBrowser for help on using the repository browser.