]> git.sur5r.net Git - u-boot/blob - board/lpd7a40x/flash.c
mpc8323erdb: Improve the system performance
[u-boot] / board / lpd7a40x / flash.c
1 /*
2  * (C) Copyright 2002
3  * Sysgo Real-Time Solutions, GmbH <www.elinos.com>
4  * Marius Groeger <mgroeger@sysgo.de>
5  *
6  * (C) Copyright 2002
7  * Gary Jennejohn, DENX Software Engineering, <gj@denx.de>
8  *
9  * See file CREDITS for list of people who contributed to this
10  * project.
11  *
12  * This program is free software; you can redistribute it and/or
13  * modify it under the terms of the GNU General Public License as
14  * published by the Free Software Foundation; either version 2 of
15  * the License, or (at your option) any later version.
16  *
17  * This program is distributed in the hope that it will be useful,
18  * but WITHOUT ANY WARRANTY; without even the implied warranty of
19  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
20  * GNU General Public License for more details.
21  *
22  * You should have received a copy of the GNU General Public License
23  * along with this program; if not, write to the Free Software
24  * Foundation, Inc., 59 Temple Place, Suite 330, Boston,
25  * MA 02111-1307 USA
26  */
27
28 /* #define DEBUG */
29
30 #include <common.h>
31 #include <environment.h>
32
33 #define FLASH_BANK_SIZE 0x1000000       /* 16MB (2 x 8 MB) */
34 #define MAIN_SECT_SIZE  0x40000         /* 256KB (2 x 128kB) */
35
36 flash_info_t flash_info[CFG_MAX_FLASH_BANKS];
37
38
39 #define CMD_READ_ARRAY          0x00FF00FF
40 #define CMD_IDENTIFY            0x00900090
41 #define CMD_ERASE_SETUP         0x00200020
42 #define CMD_ERASE_CONFIRM       0x00D000D0
43 #define CMD_PROGRAM             0x00400040
44 #define CMD_RESUME              0x00D000D0
45 #define CMD_SUSPEND             0x00B000B0
46 #define CMD_STATUS_READ         0x00700070
47 #define CMD_STATUS_RESET        0x00500050
48
49 #define BIT_BUSY                0x00800080
50 #define BIT_ERASE_SUSPEND       0x00400040
51 #define BIT_ERASE_ERROR         0x00200020
52 #define BIT_PROGRAM_ERROR       0x00100010
53 #define BIT_VPP_RANGE_ERROR     0x00080008
54 #define BIT_PROGRAM_SUSPEND     0x00040004
55 #define BIT_PROTECT_ERROR       0x00020002
56 #define BIT_UNDEFINED           0x00010001
57
58 #define BIT_SEQUENCE_ERROR      0x00300030
59 #define BIT_TIMEOUT             0x80000000
60
61 /*-----------------------------------------------------------------------
62  */
63
64 ulong flash_init (void)
65 {
66         int i, j;
67         ulong size = 0;
68
69         for (i = 0; i < CFG_MAX_FLASH_BANKS; i++) {
70                 ulong flashbase = 0;
71
72                 flash_info[i].flash_id =
73                         (INTEL_MANUFACT     & FLASH_VENDMASK) |
74                         (INTEL_ID_28F640J3A & FLASH_TYPEMASK);
75                 flash_info[i].size = FLASH_BANK_SIZE;
76                 flash_info[i].sector_count = CFG_MAX_FLASH_SECT;
77                 memset (flash_info[i].protect, 0, CFG_MAX_FLASH_SECT);
78                 if (i == 0)
79                         flashbase = CFG_FLASH_BASE;
80                 else
81                         panic ("configured too many flash banks!\n");
82                 for (j = 0; j < flash_info[i].sector_count; j++) {
83                         flash_info[i].start[j] = flashbase;
84
85                         /* uniform sector size */
86                         flashbase += MAIN_SECT_SIZE;
87                 }
88                 size += flash_info[i].size;
89         }
90
91         /*
92          * Protect monitor and environment sectors
93          */
94         flash_protect ( FLAG_PROTECT_SET,
95                         CFG_FLASH_BASE,
96                         CFG_FLASH_BASE + monitor_flash_len - 1,
97                         &flash_info[0]);
98
99         flash_protect ( FLAG_PROTECT_SET,
100                         CFG_ENV_ADDR,
101                         CFG_ENV_ADDR + CFG_ENV_SIZE - 1, &flash_info[0]);
102
103 #ifdef CFG_ENV_ADDR_REDUND
104         flash_protect ( FLAG_PROTECT_SET,
105                         CFG_ENV_ADDR_REDUND,
106                         CFG_ENV_ADDR_REDUND + CFG_ENV_SIZE_REDUND - 1,
107                         &flash_info[0]);
108 #endif
109
110         return size;
111 }
112
113 /*-----------------------------------------------------------------------
114  */
115 void flash_print_info (flash_info_t * info)
116 {
117         int i;
118
119         switch (info->flash_id & FLASH_VENDMASK) {
120         case (INTEL_MANUFACT & FLASH_VENDMASK):
121                 printf ("Intel: ");
122                 break;
123         default:
124                 printf ("Unknown Vendor ");
125                 break;
126         }
127
128         switch (info->flash_id & FLASH_TYPEMASK) {
129         case (INTEL_ID_28F640J3A & FLASH_TYPEMASK):
130                 printf ("2x 28F640J3A (64Mbit)\n");
131                 break;
132         default:
133                 printf ("Unknown Chip Type\n");
134                 return;
135                 break;
136         }
137
138         printf ("  Size: %ld MB in %d Sectors\n",
139                         info->size >> 20, info->sector_count);
140
141         printf ("  Sector Start Addresses:");
142         for (i = 0; i < info->sector_count; i++) {
143                 if ((i % 5) == 0) {
144                         printf ("\n   ");
145                 }
146                 printf (" %08lX%s",
147                         info->start[i],
148                         info->protect[i] ? " (RO)" : "     ");
149         }
150         printf ("\n");
151 }
152
153 /*-----------------------------------------------------------------------
154  */
155
156 int flash_error (ulong code)
157 {
158         /* Check bit patterns */
159         /* SR.7=0 is busy, SR.7=1 is ready */
160         /* all other flags indicate error on 1 */
161         /* SR.0 is undefined */
162         /* Timeout is our faked flag */
163
164         /* sequence is described in Intel 290644-005 document */
165
166         /* check Timeout */
167         if (code & BIT_TIMEOUT) {
168                 puts ("Timeout\n");
169                 return ERR_TIMOUT;
170         }
171
172         /* check Busy, SR.7 */
173         if (~code & BIT_BUSY) {
174                 puts ("Busy\n");
175                 return ERR_PROG_ERROR;
176         }
177
178         /* check Vpp low, SR.3 */
179         if (code & BIT_VPP_RANGE_ERROR) {
180                 puts ("Vpp range error\n");
181                 return ERR_PROG_ERROR;
182         }
183
184         /* check Device Protect Error, SR.1 */
185         if (code & BIT_PROTECT_ERROR) {
186                 puts ("Device protect error\n");
187                 return ERR_PROG_ERROR;
188         }
189
190         /* check Command Seq Error, SR.4 & SR.5 */
191         if (code & BIT_SEQUENCE_ERROR) {
192                 puts ("Command seqence error\n");
193                 return ERR_PROG_ERROR;
194         }
195
196         /* check Block Erase Error, SR.5 */
197         if (code & BIT_ERASE_ERROR) {
198                 puts ("Block erase error\n");
199                 return ERR_PROG_ERROR;
200         }
201
202         /* check Program Error, SR.4 */
203         if (code & BIT_PROGRAM_ERROR) {
204                 puts ("Program error\n");
205                 return ERR_PROG_ERROR;
206         }
207
208         /* check Block Erase Suspended, SR.6 */
209         if (code & BIT_ERASE_SUSPEND) {
210                 puts ("Block erase suspended\n");
211                 return ERR_PROG_ERROR;
212         }
213
214         /* check Program Suspended, SR.2 */
215         if (code & BIT_PROGRAM_SUSPEND) {
216                 puts ("Program suspended\n");
217                 return ERR_PROG_ERROR;
218         }
219
220         /* OK, no error */
221         return ERR_OK;
222 }
223
224 /*-----------------------------------------------------------------------
225  */
226
227 int flash_erase (flash_info_t * info, int s_first, int s_last)
228 {
229         ulong result, result1;
230         int iflag, prot, sect;
231         int rc = ERR_OK;
232
233 #ifdef USE_920T_MMU
234         int cflag;
235 #endif
236
237         debug ("flash_erase: s_first %d  s_last %d\n", s_first, s_last);
238
239         /* first look for protection bits */
240
241         if (info->flash_id == FLASH_UNKNOWN)
242                 return ERR_UNKNOWN_FLASH_TYPE;
243
244         if ((s_first < 0) || (s_first > s_last)) {
245                 return ERR_INVAL;
246         }
247
248         if ((info->flash_id & FLASH_VENDMASK) !=
249                 (INTEL_MANUFACT & FLASH_VENDMASK)) {
250                 return ERR_UNKNOWN_FLASH_VENDOR;
251         }
252
253         prot = 0;
254         for (sect = s_first; sect <= s_last; ++sect) {
255                 if (info->protect[sect]) {
256                         prot++;
257                 }
258         }
259
260         if (prot) {
261                 printf ("- Warning: %d protected sectors will not be erased!\n",
262                         prot);
263         } else {
264                 printf ("\n");
265         }
266
267         /*
268          * Disable interrupts which might cause a timeout
269          * here. Remember that our exception vectors are
270          * at address 0 in the flash, and we don't want a
271          * (ticker) exception to happen while the flash
272          * chip is in programming mode.
273          */
274 #ifdef USE_920T_MMU
275         cflag = dcache_status ();
276         dcache_disable ();
277 #endif
278         iflag = disable_interrupts ();
279
280         /* Start erase on unprotected sectors */
281         for (sect = s_first; sect <= s_last && !ctrlc (); sect++) {
282
283                 debug ("Erasing sector %2d @ %08lX... ",
284                         sect, info->start[sect]);
285
286                 /* arm simple, non interrupt dependent timer */
287                 reset_timer_masked();
288
289                 if (info->protect[sect] == 0) { /* not protected */
290                         vu_long *addr = (vu_long *) (info->start[sect]);
291                         ulong bsR7, bsR7_2, bsR5, bsR5_2;
292
293                         /* *addr = CMD_STATUS_RESET; */
294                         *addr = CMD_ERASE_SETUP;
295                         *addr = CMD_ERASE_CONFIRM;
296
297                         /* wait until flash is ready */
298                         do {
299                                 /* check timeout */
300                                 if (get_timer_masked () > CFG_FLASH_ERASE_TOUT) {
301                                         *addr = CMD_STATUS_RESET;
302                                         result = BIT_TIMEOUT;
303                                         break;
304                                 }
305
306                                 *addr = CMD_STATUS_READ;
307                                 result = *addr;
308                                 bsR7 = result & (1 << 7);
309                                 bsR7_2 = result & (1 << 23);
310                         } while (!bsR7 | !bsR7_2);
311
312                         *addr = CMD_STATUS_READ;
313                         result1 = *addr;
314                         bsR5 = result1 & (1 << 5);
315                         bsR5_2 = result1 & (1 << 21);
316 #ifdef SAMSUNG_FLASH_DEBUG
317                         printf ("bsR5 %lx bsR5_2 %lx\n", bsR5, bsR5_2);
318                         if (bsR5 != 0 && bsR5_2 != 0)
319                                 printf ("bsR5 %lx bsR5_2 %lx\n", bsR5, bsR5_2);
320 #endif
321
322                         *addr = CMD_READ_ARRAY;
323                         *addr = CMD_RESUME;
324
325                         if ((rc = flash_error (result)) != ERR_OK)
326                                 goto outahere;
327 #if 0
328                         printf ("ok.\n");
329                 } else {                /* it was protected */
330
331                         printf ("protected!\n");
332 #endif
333                 }
334         }
335
336 outahere:
337         /* allow flash to settle - wait 10 ms */
338         udelay_masked (10000);
339
340         if (iflag)
341                 enable_interrupts ();
342
343 #ifdef USE_920T_MMU
344         if (cflag)
345                 dcache_enable ();
346 #endif
347         return rc;
348 }
349
350 /*-----------------------------------------------------------------------
351  * Copy memory to flash
352  */
353
354 static int write_word (flash_info_t * info, ulong dest, ulong data)
355 {
356         vu_long *addr = (vu_long *) dest;
357         ulong result;
358         int rc = ERR_OK;
359         int iflag;
360
361 #ifdef USE_920T_MMU
362         int cflag;
363 #endif
364
365         /*
366          * Check if Flash is (sufficiently) erased
367          */
368         result = *addr;
369         if ((result & data) != data)
370                 return ERR_NOT_ERASED;
371
372         /*
373          * Disable interrupts which might cause a timeout
374          * here. Remember that our exception vectors are
375          * at address 0 in the flash, and we don't want a
376          * (ticker) exception to happen while the flash
377          * chip is in programming mode.
378          */
379 #ifdef USE_920T_MMU
380         cflag = dcache_status ();
381         dcache_disable ();
382 #endif
383         iflag = disable_interrupts ();
384
385         /* *addr = CMD_STATUS_RESET; */
386         *addr = CMD_PROGRAM;
387         *addr = data;
388
389         /* arm simple, non interrupt dependent timer */
390         reset_timer_masked ();
391
392         /* wait until flash is ready */
393         do {
394                 /* check timeout */
395                 if (get_timer_masked () > CFG_FLASH_ERASE_TOUT) {
396                         *addr = CMD_SUSPEND;
397                         result = BIT_TIMEOUT;
398                         break;
399                 }
400
401                 *addr = CMD_STATUS_READ;
402                 result = *addr;
403         } while (~result & BIT_BUSY);
404
405         /* *addr = CMD_READ_ARRAY; */
406         *addr = CMD_STATUS_READ;
407         result = *addr;
408
409         rc = flash_error (result);
410
411         if (iflag)
412                 enable_interrupts ();
413
414 #ifdef USE_920T_MMU
415         if (cflag)
416                 dcache_enable ();
417 #endif
418         *addr = CMD_READ_ARRAY;
419         *addr = CMD_RESUME;
420         return rc;
421 }
422
423 /*-----------------------------------------------------------------------
424  * Copy memory to flash.
425  */
426
427 int write_buff (flash_info_t * info, uchar * src, ulong addr, ulong cnt)
428 {
429         ulong cp, wp, data;
430         int l;
431         int i, rc;
432
433         wp = (addr & ~3);                       /* get lower word aligned address */
434
435         /*
436          * handle unaligned start bytes
437          */
438         if ((l = addr - wp) != 0) {
439                 data = 0;
440                 for (i = 0, cp = wp; i < l; ++i, ++cp) {
441                         data = (data >> 8) | (*(uchar *) cp << 24);
442                 }
443                 for (; i < 4 && cnt > 0; ++i) {
444                         data = (data >> 8) | (*src++ << 24);
445                         --cnt;
446                         ++cp;
447                 }
448                 for (; cnt == 0 && i < 4; ++i, ++cp) {
449                         data = (data >> 8) | (*(uchar *) cp << 24);
450                 }
451
452                 if ((rc = write_word (info, wp, data)) != 0) {
453                         return (rc);
454                 }
455                 wp += 4;
456         }
457
458         /*
459          * handle word aligned part
460          */
461         while (cnt >= 4) {
462                 data = *((vu_long *) src);
463                 if ((rc = write_word (info, wp, data)) != 0) {
464                         return (rc);
465                 }
466                 src += 4;
467                 wp += 4;
468                 cnt -= 4;
469         }
470
471         if (cnt == 0) {
472                 return ERR_OK;
473         }
474
475         /*
476          * handle unaligned tail bytes
477          */
478         data = 0;
479         for (i = 0, cp = wp; i < 4 && cnt > 0; ++i, ++cp) {
480                 data = (data >> 8) | (*src++ << 24);
481                 --cnt;
482         }
483         for (; i < 4; ++i, ++cp) {
484                 data = (data >> 8) | (*(uchar *) cp << 24);
485         }
486
487         return write_word (info, wp, data);
488 }