to make u-boot work for fat32 filesystem
[jz_uboot.git] / board / jdi / flash.c
blob328356ab797d0f2e351575a04ab72f4043fd6e3f
1 /*
2 * (C) Copyright 2005 Ingenic Semiconductor
4 * This program is free software; you can redistribute it and/or
5 * modify it under the terms of the GNU General Public License as
6 * published by the Free Software Foundation; either version 2 of
7 * the License, or (at your option) any later version.
9 * This program is distributed in the hope that it will be useful,
10 * but WITHOUT ANY WARRANTY; without even the implied warranty of
11 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12 * GNU General Public License for more details.
14 * You should have received a copy of the GNU General Public License
15 * along with this program; if not, write to the Free Software
16 * Foundation, Inc., 59 Temple Place, Suite 330, Boston,
17 * MA 02111-1307 USA
20 * This file supports SST 39xF3201 and AMD S29GL032M-R4
23 #define AMD_ID_GL032 0x227E227E /* S29GL032 ID (32Mb, bottom boot sectors) */
25 #include <common.h>
27 flash_info_t flash_info[CFG_MAX_FLASH_BANKS]; /* info for FLASH chips */
29 /*-----------------------------------------------------------------------
30 * Functions
32 static ulong flash_get_size (vu_long *addr, flash_info_t *info);
34 /*-----------------------------------------------------------------------
37 ulong flash_init (void)
39 int i, j;
40 ulong size = 0;
42 /* Init: no FLASHes known */
43 for (i = 0; i < CFG_MAX_FLASH_BANKS; ++i) {
44 flash_info[i].flash_id = FLASH_UNKNOWN;
47 for (i = 0; i < CFG_MAX_FLASH_BANKS; i++) {
48 ulong flashbase = 0;
50 if (i == 0) {
51 flashbase = CFG_FLASH_BASE;
52 size += flash_get_size((vu_long *)flashbase, &flash_info[0]);
54 else
55 panic ("configured too many flash banks!\n");
57 memset (flash_info[i].protect, 0, flash_info[i].sector_count);
59 switch (flash_info[i].flash_id & FLASH_TYPEMASK) {
60 case (AMD_ID_GL032 & FLASH_TYPEMASK):
61 for (j = 0; j < flash_info[i].sector_count; j++) {
62 if (j < 8) { /* 8 x 8KB bottom boot sectors */
63 flash_info[i].start[j] = flashbase;
64 flashbase += 0x2000;
66 else { /* 63 x 64KB */
67 flash_info[i].start[j] = flashbase + (j-8) * 0x10000;
70 break;
71 case (SST_ID_xF3201 & FLASH_TYPEMASK):
72 default:
73 for (j = 0; j < flash_info[i].sector_count; j++) {
74 /* 1024 * 4KB */
75 flash_info[i].start[j] = flashbase + j * 0x1000;
77 break;
81 /* Protect monitor and environment sectors
83 flash_protect ( FLAG_PROTECT_SET,
84 CFG_FLASH_BASE,
85 CFG_FLASH_BASE + monitor_flash_len - 1,
86 &flash_info[0]);
88 flash_protect ( FLAG_PROTECT_SET,
89 CFG_ENV_ADDR,
90 CFG_ENV_ADDR + CFG_ENV_SIZE - 1, &flash_info[0]);
92 return size;
95 /*-----------------------------------------------------------------------
97 void flash_print_info (flash_info_t * info)
99 int i;
101 switch (info->flash_id & FLASH_VENDMASK) {
102 case (SST_MANUFACT & FLASH_VENDMASK):
103 printf ("SST ");
104 break;
105 case (AMD_MANUFACT & FLASH_VENDMASK):
106 printf ("AMD ");
107 break;
108 default:
109 printf ("Unknown Vendor ");
110 break;
113 switch (info->flash_id & FLASH_TYPEMASK) {
114 case (SST_ID_xF3201 & FLASH_TYPEMASK):
115 printf ("39xF3201 (32Mbit)\n");
116 break;
117 case (AMD_ID_GL032 & FLASH_TYPEMASK):
118 printf ("29GL032 (32Mbit)\n");
119 break;
120 default:
121 printf ("Unknown Chip Type\n");
122 break;
125 printf (" Size: %ld MB in %d Sectors\n",
126 info->size >> 20, info->sector_count);
128 printf (" Sector Start Addresses:");
129 for (i = 0; i < info->sector_count; i++) {
130 if ((i % 5) == 0) {
131 printf ("\n ");
133 printf (" %08lX%s", info->start[i],
134 info->protect[i] ? " (RO)" : " ");
136 printf ("\n");
139 /*-----------------------------------------------------------------------
142 static ulong flash_get_size (vu_long *addr, flash_info_t *info)
144 ushort vid, did;
145 vu_short *saddr = (vu_short *)addr;
147 /* Read Manufacturer ID and Device ID */
149 /* AMD Flash stuff */
150 saddr[0x555] = 0xAA;
151 saddr[0x2AA] = 0x55;
152 saddr[0x555] = 0x90;
154 vid = saddr[0];
155 did = saddr[1];
157 /* Exit Read IDs */
158 saddr[0x555] = 0xAA;
159 saddr[0x2AA] = 0x55;
160 saddr[0x555] = 0xF0;
162 if (vid != (AMD_MANUFACT & 0xFFFF)) {
163 saddr[0x5555] = 0xAA;
164 saddr[0x2AAA] = 0x55;
165 saddr[0x5555] = 0x90;
167 vid = saddr[0];
168 did = saddr[1];
170 /* Exit Read IDs */
171 saddr[0x5555] = 0xAA;
172 saddr[0x2AAA] = 0x55;
173 saddr[0x5555] = 0xF0;
175 /* SST Flash bug */
176 vid = SST_MANUFACT & 0xFFFF;
177 did = SST_ID_xF3201 & 0xFFFF;
180 switch (vid) {
181 case (SST_MANUFACT & 0xFFFF):
182 info->flash_id = (SST_MANUFACT & 0xFFFF0000);
183 break;
184 case (AMD_MANUFACT & 0xFFFF):
185 info->flash_id = (AMD_MANUFACT & 0xFFFF0000);
186 break;
187 default:
188 info->flash_id = FLASH_UNKNOWN;
189 info->sector_count = 0;
190 info->size = 0;
191 return (0); /* no or unknown flash */
194 switch (did) {
195 case (SST_ID_xF3201 & 0xFFFF):
196 info->flash_id += (SST_ID_xF3201 & 0xFFFF);
197 info->sector_count = 1024;
198 info->size = 0x00400000;
199 break;
200 case (AMD_ID_GL032 & 0xFFFF):
201 info->flash_id += (AMD_ID_GL032 & 0xFFFF);
202 info->sector_count = 71; /* 8 x 8KB + 63 x 64KB */
203 info->size = 0x00400000;
204 break;
205 default:
206 info->flash_id = FLASH_UNKNOWN;
207 info->sector_count = 0;
208 info->size = 0;
209 return (0); /* no or unknown flash */
212 return (info->size);
215 /*-----------------------------------------------------------------------
218 int flash_erase (flash_info_t * info, int s_first, int s_last)
220 volatile u16 *base = (volatile u16 *) CFG_FLASH_BASE;
221 int flag, prot, sect;
222 int rc = ERR_OK;
223 unsigned int timeout;
225 if (info->flash_id == FLASH_UNKNOWN)
226 return ERR_UNKNOWN_FLASH_TYPE;
228 if ((s_first < 0) || (s_first > s_last)) {
229 return ERR_INVAL;
231 #if 0
232 if ((info->flash_id & FLASH_VENDMASK) !=
233 (SST_MANUFACT & FLASH_VENDMASK)) {
234 return ERR_UNKNOWN_FLASH_VENDOR;
236 #endif
238 prot = 0;
239 for (sect = s_first; sect <= s_last; ++sect) {
240 if (info->protect[sect]) {
241 prot++;
244 if (prot)
245 return ERR_PROTECTED;
247 /* Disable interrupts which might cause a timeout here */
248 flag = disable_interrupts ();
250 /* Start erase on unprotected sectors */
251 for (sect = s_first; sect <= s_last && !ctrlc (); sect++) {
253 printf ("Erasing sector %3d ... ", sect);
255 if (info->protect[sect] == 0) { /* not protected */
256 volatile u16 *addr = (volatile u16 *) (info->start[sect]);
258 switch (info->flash_id & FLASH_TYPEMASK) {
259 case (SST_ID_xF3201 & FLASH_TYPEMASK):
260 base[0x5555] = 0x00AA;
261 base[0x2AAA] = 0x0055;
262 base[0x5555] = 0x0080;
263 base[0x5555] = 0x00AA;
264 base[0x2AAA] = 0x0055;
265 addr[0x0000] = 0x0030;
266 break;
267 case (AMD_ID_GL032 & FLASH_TYPEMASK):
268 base[0x555] = 0x00AA;
269 base[0x2AA] = 0x0055;
270 base[0x555] = 0x0080;
271 base[0x555] = 0x00AA;
272 base[0x2AA] = 0x0055;
273 addr[0x000] = 0x0030;
274 break;
275 default:
276 printf ("Unknown Chip Type\n");
277 break;
280 timeout = 0x3ffffff;
281 while ((*base & 0x40) != (*base & 0x40)) {
282 if ((timeout--) == 0) {
283 rc = ERR_TIMOUT;
284 goto outahere;
288 printf ("ok.\n");
290 if (ctrlc ())
291 printf ("User Interrupt!\n");
293 outahere:
295 /* allow flash to settle - wait 20 ms */
296 udelay(20000);
298 if (flag)
299 enable_interrupts ();
301 return rc;
304 /*-----------------------------------------------------------------------
305 * Copy memory to flash
308 static int write_word (flash_info_t * info, ulong dest, ushort data)
310 volatile u16 *base = (volatile u16 *) CFG_FLASH_BASE;
311 volatile u16 *addr = (volatile u16 *) dest;
312 int rc = ERR_OK;
313 int flag;
314 unsigned int timeout;
316 /* Check if Flash is (sufficiently) erased
318 if ((*addr & data) != data)
319 return ERR_NOT_ERASED;
321 /* Disable interrupts which might cause a timeout here. */
322 flag = disable_interrupts ();
324 /* program set-up command */
325 switch (info->flash_id & FLASH_TYPEMASK) {
326 case (SST_ID_xF3201 & FLASH_TYPEMASK):
327 base[0x5555] = 0x00AA;
328 base[0x2AAA] = 0x0055;
329 base[0x5555] = 0x00A0;
330 break;
331 case (AMD_ID_GL032 & FLASH_TYPEMASK):
332 base[0x555] = 0x00AA;
333 base[0x2AA] = 0x0055;
334 base[0x555] = 0x00A0;
335 break;
336 default:
337 printf ("Unknown Chip Type\n");
338 break;
341 /* load address/data */
342 *addr = data;
344 /* wait while polling the status register */
345 timeout = 0x3ffffff;
346 while ((*base & 0x40) != (*base & 0x40)) {
347 if ((timeout--) == 0) {
348 rc = ERR_TIMOUT;
349 goto outahere;
353 outahere:
355 /* allow flash to settle - wait 10 us */
356 udelay(10);
358 if (flag)
359 enable_interrupts ();
361 return rc;
364 /*-----------------------------------------------------------------------
365 * Copy memory to flash.
368 int write_buff (flash_info_t * info, uchar * src, ulong addr, ulong cnt)
370 ulong cp, wp;
371 ushort data;
372 int l;
373 int i, rc;
375 wp = (addr & ~1); /* get lower word aligned address */
378 * handle unaligned start bytes
380 if ((l = addr - wp) != 0) {
381 data = 0;
382 for (i = 0, cp = wp; i < l; ++i, ++cp) {
383 data = (data >> 8) | (*(uchar *) cp << 8);
385 for (; i < 2 && cnt > 0; ++i) {
386 data = (data >> 8) | (*src++ << 8);
387 --cnt;
388 ++cp;
390 for (; cnt == 0 && i < 2; ++i, ++cp) {
391 data = (data >> 8) | (*(uchar *) cp << 8);
394 if ((rc = write_word (info, wp, data)) != 0) {
395 return (rc);
397 wp += 2;
401 * handle word aligned part
403 while (cnt >= 2) {
404 data = *((vu_short *) src);
405 if ((rc = write_word (info, wp, data)) != 0) {
406 return (rc);
408 src += 2;
409 wp += 2;
410 cnt -= 2;
413 if (cnt == 0) {
414 return ERR_OK;
418 * handle unaligned tail bytes
420 data = 0;
421 for (i = 0, cp = wp; i < 2 && cnt > 0; ++i, ++cp) {
422 data = (data >> 8) | (*src++ << 8);
423 --cnt;
425 for (; i < 2; ++i, ++cp) {
426 data = (data >> 8) | (*(uchar *) cp << 8);
429 return write_word (info, wp, data);