3 * Copyright (c) 2004 Cucy Systems (http://www.cucy.com)
4 * Curt Brune <curt@cucy.com>
6 * See file CREDITS for list of people who contributed to this
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.
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.
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,
26 #include <asm/hardware.h>
29 flash_info_t flash_info
[CONFIG_SYS_MAX_FLASH_BANKS
];
32 FLASH_DEV_U9_512KB
= 0,
36 #define FLASH_DQ7 (0x80)
37 #define FLASH_DQ5 (0x20)
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)
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)
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)
59 #define WRITE_UNLOCK(addr) { \
60 PUT__U8( addr + UNLOCK_ADDR1, UNLOCK_CMD1); \
61 PUT__U8( addr + UNLOCK_ADDR2, UNLOCK_CMD2); \
64 /* auto select command */
65 #define CMD_ID(addr) WRITE_UNLOCK(addr); { \
66 PUT__U8( addr + ID_ADDR, ID_CMD); \
69 #define CMD_RESET(addr) WRITE_UNLOCK(addr); { \
70 PUT__U8( addr + ID_ADDR, RESET_CMD); \
73 #define CMD_ERASE_SEC(base, addr) WRITE_UNLOCK(base); \
74 PUT__U8( base + SETUP_ADDR, SETUP_CMD); \
76 PUT__U8( addr, SECERASE_CMD);
78 #define CMD_ERASE_CHIP(base) WRITE_UNLOCK(base); \
79 PUT__U8( base + SETUP_ADDR, SETUP_CMD); \
81 PUT__U8( base + SETUP_ADDR, CHIPERASE_CMD);
83 /* prepare for bypass programming */
84 #define CMD_UNLOCK_BYPASS(addr) WRITE_UNLOCK(addr); { \
85 PUT__U8( addr + ID_ADDR, 0x20); \
88 /* terminate bypass programming */
89 #define CMD_BYPASS_RESET(addr) { \
90 PUT__U8(addr, 0x90); \
91 PUT__U8(addr, 0x00); \
95 inline static void FLASH_CMD_UNLOCK (FLASH_DEV dev
, u32 base
)
98 case FLASH_DEV_U7_2MB
:
99 PUT__U8 (base
+ 0xAAA, 0xAA);
100 PUT__U8 (base
+ 0x555, 0x55);
102 case FLASH_DEV_U9_512KB
:
103 PUT__U8 (base
+ 0x555, 0xAA);
104 PUT__U8 (base
+ 0x2AA, 0x55);
109 inline static void FLASH_CMD_SELECT (FLASH_DEV dev
, u32 base
)
112 case FLASH_DEV_U7_2MB
:
113 FLASH_CMD_UNLOCK (dev
, base
);
114 PUT__U8 (base
+ 0xAAA, SELECT_CMD
);
116 case FLASH_DEV_U9_512KB
:
117 FLASH_CMD_UNLOCK (dev
, base
);
118 PUT__U8 (base
+ 0x555, SELECT_CMD
);
123 inline static void FLASH_CMD_RESET (FLASH_DEV dev
, u32 base
)
126 case FLASH_DEV_U7_2MB
:
127 FLASH_CMD_UNLOCK (dev
, base
);
128 PUT__U8 (base
+ 0xAAA, RESET_CMD
);
130 case FLASH_DEV_U9_512KB
:
131 FLASH_CMD_UNLOCK (dev
, base
);
132 PUT__U8 (base
+ 0x555, RESET_CMD
);
137 inline static void FLASH_CMD_ERASE_SEC (FLASH_DEV dev
, u32 base
, u32 addr
)
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
);
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
);
155 inline static void FLASH_CMD_ERASE_CHIP (FLASH_DEV dev
, u32 base
)
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
);
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
);
173 inline static void FLASH_CMD_UNLOCK_BYPASS (FLASH_DEV dev
, u32 base
)
176 case FLASH_DEV_U7_2MB
:
177 FLASH_CMD_UNLOCK (dev
, base
);
178 PUT__U8 (base
+ 0xAAA, BYPASS_CMD
);
180 case FLASH_DEV_U9_512KB
:
181 FLASH_CMD_UNLOCK (dev
, base
);
182 PUT__U8 (base
+ 0x555, BYPASS_CMD
);
187 inline static void FLASH_CMD_BYPASS_RESET (FLASH_DEV dev
, u32 base
)
189 PUT__U8 (base
, SELECT_CMD
);
193 /* poll for flash command completion */
194 static u16
_flash_poll (FLASH_DEV dev
, u32 addr
, u16 data
, ulong timeOut
)
200 volatile u16 flashData
;
204 while (get_timer (t0
) < timeOut
) {
205 /* for( i = 0; i < POLL_LOOPS; i++) { */
207 flashData
= GET__U8 (addr
);
209 /* FLASH_DQ7 = Data? */
210 if ((flashData
& FLASH_DQ7
) == (data
& FLASH_DQ7
)) {
215 /* Check Timeout (FLASH_DQ5==1) */
216 if (flashData
& FLASH_DQ5
) {
218 flashData
= GET__U8 (addr
);
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
;
225 FLASH_CMD_RESET (dev
, addr
);
236 printf ("_flash_poll(): Timeout\n");
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",
254 /*-----------------------------------------------------------------------
256 static int _flash_check_protection (flash_info_t
* info
, int s_first
, int s_last
)
260 for (sect
= s_first
; sect
<= s_last
; sect
++)
261 if (info
->protect
[sect
]) {
262 printf (" Flash sector %d protected.\n", sect
);
268 static int _detectFlash (FLASH_DEV dev
, u32 base
, u8 venId
, u8 devId
)
271 u32 baseAddr
= base
| CACHE_DISABLE_MASK
;
272 u8 vendorId
, deviceId
;
274 /* printf(__FUNCTION__"(): detecting flash @ 0x%08x\n", base); */
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
);
281 /* Send auto select command and read device info */
282 FLASH_CMD_SELECT (dev
, baseAddr
);
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);
292 FLASH_CMD_RESET (dev
, baseAddr
);
294 /* printf (__FUNCTION__"(): found vendorId 0x%04x, deviceId 0x%04x\n",
298 return (vendorId
== venId
) && (deviceId
== devId
);
302 /******************************************************************************
304 * Public u-boot interface functions below
306 *****************************************************************************/
308 /***************************************************************************
310 * Flash initialization
312 * This board has two banks of flash, but the base addresses depend on
313 * how the board is jumpered.
315 * The two flash types are:
317 * AMD Am29LV160DB (2MB) sectors layout 16KB, 2x8KB, 32KB, 31x64KB
319 * AMD Am29LV040B (512KB) sectors: 8x64KB
320 *****************************************************************************/
322 unsigned long flash_init (void)
330 #if CONFIG_SYS_MAX_FLASH_BANKS == 2
335 /* configure PHYS_FLASH_1 */
336 if (_detectFlash (FLASH_DEV_U7_2MB
, PHYS_FLASH_1
, 0x1, 0x49)) {
338 amd160base
= PHYS_FLASH_1
;
339 #if CONFIG_SYS_MAX_FLASH_BANKS == 1
343 (FLASH_DEV_U9_512KB
, PHYS_FLASH_2
, 0x1, 0x4F)) {
345 amd040base
= PHYS_FLASH_2
;
348 "(): Unable to detect PHYS_FLASH_2: 0x%08x\n",
351 } else if (_detectFlash (FLASH_DEV_U9_512KB
, PHYS_FLASH_1
, 0x1, 0x4F)) {
353 amd040base
= PHYS_FLASH_1
;
354 if (_detectFlash (FLASH_DEV_U7_2MB
, PHYS_FLASH_2
, 0x1, 0x49)) {
356 amd160base
= PHYS_FLASH_2
;
359 "(): Unable to detect PHYS_FLASH_2: 0x%08x\n",
365 printf ("flash_init(): Unable to detect PHYS_FLASH_1: 0x%08x\n",
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 */
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);
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
);
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);
396 * protect monitor and environment sectors in 2MB flash
398 flash_protect (FLAG_PROTECT_SET
,
399 amd160base
, amd160base
+ monitor_flash_len
- 1, info
);
401 flash_protect (FLAG_PROTECT_SET
,
402 CONFIG_ENV_ADDR
, CONFIG_ENV_ADDR
+ CONFIG_ENV_SIZE
- 1, info
);
404 #if CONFIG_SYS_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
);
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);
423 return flash_info
[0].size
424 #if CONFIG_SYS_MAX_FLASH_BANKS == 2
430 void flash_print_info (flash_info_t
* info
)
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");
439 printf ("Unknown flash_id ...\n");
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
++) {
449 printf (" S%02d @ 0x%08lX%s", i
,
450 info
->start
[i
], info
->protect
[i
] ? " !" : " ");
455 int flash_erase (flash_info_t
* info
, int s_first
, int s_last
)
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
;
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
,
471 /* bypass the cache to access the flash memory */
472 FLASH_CMD_ERASE_SEC (info
->flash_id
,
474 start
[0] | CACHE_DISABLE_MASK
),
476 start
[i
] | CACHE_DISABLE_MASK
));
477 /* look for sector to become 0xFF after erase */
478 error
= _flash_poll (info
->flash_id
,
480 start
[i
] | CACHE_DISABLE_MASK
,
481 0xFF, CONFIG_SYS_FLASH_ERASE_TOUT
);
482 FLASH_CMD_RESET (info
->flash_id
,
484 start
[0] | CACHE_DISABLE_MASK
));
496 int write_buff (flash_info_t
* info
, uchar
* src
, ulong addr
, ulong cnt
)
503 /* bypass the cache to access the flash memory */
504 FLASH_CMD_UNLOCK_BYPASS (info
->flash_id
,
505 (info
->start
[0] | CACHE_DISABLE_MASK
));
507 /* Write the Data to Flash */
509 bp
= (u8
*) (addr
| CACHE_DISABLE_MASK
);
512 for (n
= 0; n
< cnt
&& !error
; n
++, bp
++, bps
++) {
514 if (!(n
% (cnt
/ 15))) {
518 /* write the flash command for flash memory */
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 CONFIG_SYS_FLASH_WRITE_TOUT
);
533 /* Reset the Flash Mode to read */
534 FLASH_CMD_BYPASS_RESET (info
->flash_id
, info
->start
[0]);