3 * Sysgo Real-Time Solutions, GmbH <www.elinos.com>
4 * Alex Zuepke <azu@sysgo.de>
7 * 2N Telekomunikace, a.s. <www.2n.cz>
8 * Ladislav Michl <michl@2n.cz>
10 * See file CREDITS for list of people who contributed to this
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.
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.
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,
32 #if (PHYS_SDRAM_1_SIZE != SZ_32M)
36 #if (CFG_MAX_FLASH_BANKS > 1)
37 #error There is always only _one_ flash chip
40 flash_info_t flash_info
[CFG_MAX_FLASH_BANKS
];
42 #define CMD_READ_ARRAY 0x000000f0
43 #define CMD_UNLOCK1 0x000000aa
44 #define CMD_UNLOCK2 0x00000055
45 #define CMD_ERASE_SETUP 0x00000080
46 #define CMD_ERASE_CONFIRM 0x00000030
47 #define CMD_PROGRAM 0x000000a0
48 #define CMD_UNLOCK_BYPASS 0x00000020
50 #define MEM_FLASH_ADDR1 (*(volatile u16 *)(CFG_FLASH_BASE + (0x00000555 << 1)))
51 #define MEM_FLASH_ADDR2 (*(volatile u16 *)(CFG_FLASH_BASE + (0x000002aa << 1)))
53 #define BIT_ERASE_DONE 0x00000080
54 #define BIT_RDY_MASK 0x00000080
55 #define BIT_PROGRAM_ERROR 0x00000020
56 #define BIT_TIMEOUT 0x80000000 /* our flag */
58 /*-----------------------------------------------------------------------
61 ulong
flash_init(void)
65 flash_info
[0].flash_id
= (AMD_MANUFACT
& FLASH_VENDMASK
) |
66 (AMD_ID_LV800B
& FLASH_TYPEMASK
);
67 flash_info
[0].size
= PHYS_FLASH_1_SIZE
;
68 flash_info
[0].sector_count
= CFG_MAX_FLASH_SECT
;
69 memset(flash_info
[0].protect
, 0, CFG_MAX_FLASH_SECT
);
71 for (i
= 0; i
< flash_info
[0].sector_count
; i
++) {
74 flash_info
[0].start
[0] = CFG_FLASH_BASE
;
77 flash_info
[0].start
[1] = CFG_FLASH_BASE
+ 0x4000;
80 flash_info
[0].start
[2] = CFG_FLASH_BASE
+ 0x4000 +
84 flash_info
[0].start
[3] = CFG_FLASH_BASE
+ 0x4000 +
88 flash_info
[0].start
[4] = CFG_FLASH_BASE
+ 0x4000 +
92 flash_info
[0].start
[i
] = flash_info
[0].start
[i
-1] +
99 flash_protect(FLAG_PROTECT_SET
,
101 LOADER1_OFFSET
+ LOADER_SIZE
- 1, flash_info
);
102 /* Protect crcek, env and r_env as well */
103 flash_protect(FLAG_PROTECT_SET
, 0, 0x8000 - 1, flash_info
);
105 return flash_info
[0].size
;
108 /*-----------------------------------------------------------------------
110 void flash_print_info(flash_info_t
*info
)
114 switch (info
->flash_id
& FLASH_VENDMASK
) {
115 case (AMD_MANUFACT
& FLASH_VENDMASK
):
119 puts("Unknown vendor ");
123 switch (info
->flash_id
& FLASH_TYPEMASK
) {
124 case (AMD_ID_LV800B
& FLASH_TYPEMASK
):
125 puts("AM29LV800BB (8Mb)\n");
128 puts("Unknown chip type\n");
132 printf(" Size: %ld MB in %d sectors\n",
133 info
->size
>> 20, info
->sector_count
);
135 puts(" Sector start addresses:");
136 for (i
= 0; i
< info
->sector_count
; i
++) {
140 printf(" %08lX%s", info
->start
[i
],
141 info
->protect
[i
] ? " (RO)" : " ");
146 /*-----------------------------------------------------------------------
149 int flash_erase(flash_info_t
*info
, int s_first
, int s_last
)
155 /* first look for protection bits */
157 if (info
->flash_id
== FLASH_UNKNOWN
)
158 return ERR_UNKNOWN_FLASH_TYPE
;
160 if ((s_first
< 0) || (s_first
> s_last
))
163 if ((info
->flash_id
& FLASH_VENDMASK
) !=
164 (AMD_MANUFACT
& FLASH_VENDMASK
))
165 return ERR_UNKNOWN_FLASH_VENDOR
;
168 for (sect
= s_first
; sect
<= s_last
; ++sect
)
169 if (info
->protect
[sect
])
173 printf("- Warning: %d protected sectors will not be erased!\n",
178 /* Start erase on unprotected sectors */
179 for (sect
= s_first
; sect
<= s_last
&& !ctrlc (); sect
++) {
180 if (info
->protect
[sect
] == 0) { /* not protected */
181 vu_short
*addr
= (vu_short
*) (info
->start
[sect
]);
183 /* arm simple, non interrupt dependent timer */
184 reset_timer_masked();
186 MEM_FLASH_ADDR1
= CMD_UNLOCK1
;
187 MEM_FLASH_ADDR2
= CMD_UNLOCK2
;
188 MEM_FLASH_ADDR1
= CMD_ERASE_SETUP
;
190 MEM_FLASH_ADDR1
= CMD_UNLOCK1
;
191 MEM_FLASH_ADDR2
= CMD_UNLOCK2
;
192 *addr
= CMD_ERASE_CONFIRM
;
194 /* wait until flash is ready */
199 if (get_timer_masked() > CFG_FLASH_ERASE_TOUT
) {
200 MEM_FLASH_ADDR1
= CMD_READ_ARRAY
;
205 if ((result
& 0xfff) & BIT_ERASE_DONE
)
208 if ((result
& 0xffff) & BIT_PROGRAM_ERROR
) {
214 MEM_FLASH_ADDR1
= CMD_READ_ARRAY
;
223 /* allow flash to settle - wait 10 ms */
224 udelay_masked(10000);
229 /*-----------------------------------------------------------------------
230 * Copy memory to flash
233 static int write_hword(flash_info_t
*info
, ulong dest
, ushort data
)
235 vu_short
*addr
= (vu_short
*) dest
;
239 /* check if flash is (sufficiently) erased */
241 if ((result
& data
) != data
)
242 return ERR_NOT_ERASED
;
244 MEM_FLASH_ADDR1
= CMD_UNLOCK1
;
245 MEM_FLASH_ADDR2
= CMD_UNLOCK2
;
246 MEM_FLASH_ADDR1
= CMD_PROGRAM
;
249 /* arm simple, non interrupt dependent timer */
250 reset_timer_masked();
252 /* wait until flash is ready */
257 if (get_timer_masked () > CFG_FLASH_ERASE_TOUT
) {
262 if ((result
& 0x80) == (data
& 0x80))
265 if ((result
& 0xffff) & BIT_PROGRAM_ERROR
) {
268 if ((result
& 0x80) != (data
& 0x80))
273 *addr
= CMD_READ_ARRAY
;
281 /*-----------------------------------------------------------------------
282 * Copy memory to flash.
285 int write_buff(flash_info_t
*info
, uchar
*src
, ulong addr
, ulong cnt
)
292 wp
= (addr
& ~1); /* get lower word aligned address */
295 * handle unaligned start bytes
297 if ((l
= addr
- wp
) != 0) {
299 for (i
= 0, cp
= wp
; i
< l
; ++i
, ++cp
)
300 data
= (data
>> 8) | (*(uchar
*) cp
<< 8);
301 for (; i
< 2 && cnt
> 0; ++i
) {
302 data
= (data
>> 8) | (*src
++ << 8);
306 for (; cnt
== 0 && i
< 2; ++i
, ++cp
)
307 data
= (data
>> 8) | (*(uchar
*) cp
<< 8);
309 if ((rc
= write_hword(info
, wp
, data
)) != 0)
315 * handle word aligned part
318 data
= *((vu_short
*) src
);
319 if ((rc
= write_hword(info
, wp
, data
)) != 0)
330 * handle unaligned tail bytes
333 for (i
= 0, cp
= wp
; i
< 2 && cnt
> 0; ++i
, ++cp
) {
334 data
= (data
>> 8) | (*src
++ << 8);
337 for (; i
< 2; ++i
, ++cp
)
338 data
= (data
>> 8) | (*(uchar
*) cp
<< 8);
340 return write_hword(info
, wp
, data
);