]> git.kernelconcepts.de Git - karo-tx-uboot.git/blob - board/smdk2400/flash.c
* Get (mostly) rid of CFG_MONITOR_LEN definition; compute real length
[karo-tx-uboot.git] / board / smdk2400 / 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       /* 2 x   8 MB */
34 #define MAIN_SECT_SIZE  0x40000         /* 2 x 128 kB */
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                 goto Done;
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   Done:
153 }
154
155 /*-----------------------------------------------------------------------
156  */
157
158 int flash_error (ulong code)
159 {
160         /* Check bit patterns */
161         /* SR.7=0 is busy, SR.7=1 is ready */
162         /* all other flags indicate error on 1 */
163         /* SR.0 is undefined */
164         /* Timeout is our faked flag */
165
166         /* sequence is described in Intel 290644-005 document */
167
168         /* check Timeout */
169         if (code & BIT_TIMEOUT) {
170                 puts ("Timeout\n");
171                 return ERR_TIMOUT;
172         }
173
174         /* check Busy, SR.7 */
175         if (~code & BIT_BUSY) {
176                 puts ("Busy\n");
177                 return ERR_PROG_ERROR;
178         }
179
180         /* check Vpp low, SR.3 */
181         if (code & BIT_VPP_RANGE_ERROR) {
182                 puts ("Vpp range error\n");
183                 return ERR_PROG_ERROR;
184         }
185
186         /* check Device Protect Error, SR.1 */
187         if (code & BIT_PROTECT_ERROR) {
188                 puts ("Device protect error\n");
189                 return ERR_PROG_ERROR;
190         }
191
192         /* check Command Seq Error, SR.4 & SR.5 */
193         if (code & BIT_SEQUENCE_ERROR) {
194                 puts ("Command seqence error\n");
195                 return ERR_PROG_ERROR;
196         }
197
198         /* check Block Erase Error, SR.5 */
199         if (code & BIT_ERASE_ERROR) {
200                 puts ("Block erase error\n");
201                 return ERR_PROG_ERROR;
202         }
203
204         /* check Program Error, SR.4 */
205         if (code & BIT_PROGRAM_ERROR) {
206                 puts ("Program error\n");
207                 return ERR_PROG_ERROR;
208         }
209
210         /* check Block Erase Suspended, SR.6 */
211         if (code & BIT_ERASE_SUSPEND) {
212                 puts ("Block erase suspended\n");
213                 return ERR_PROG_ERROR;
214         }
215
216         /* check Program Suspended, SR.2 */
217         if (code & BIT_PROGRAM_SUSPEND) {
218                 puts ("Program suspended\n");
219                 return ERR_PROG_ERROR;
220         }
221
222         /* OK, no error */
223         return ERR_OK;
224 }
225
226 /*-----------------------------------------------------------------------
227  */
228
229 int flash_erase (flash_info_t * info, int s_first, int s_last)
230 {
231         ulong result, result1;
232         int iflag, prot, sect;
233         int rc = ERR_OK;
234
235 #ifdef USE_920T_MMU
236         int cflag;
237 #endif
238
239         debug ("flash_erase: s_first %d  s_last %d\n", s_first, s_last);
240
241         /* first look for protection bits */
242
243         if (info->flash_id == FLASH_UNKNOWN)
244                 return ERR_UNKNOWN_FLASH_TYPE;
245
246         if ((s_first < 0) || (s_first > s_last)) {
247                 return ERR_INVAL;
248         }
249
250         if ((info->flash_id & FLASH_VENDMASK) !=
251                 (INTEL_MANUFACT & FLASH_VENDMASK)) {
252                 return ERR_UNKNOWN_FLASH_VENDOR;
253         }
254
255         prot = 0;
256         for (sect = s_first; sect <= s_last; ++sect) {
257                 if (info->protect[sect]) {
258                         prot++;
259                 }
260         }
261
262         if (prot) {
263                 printf ("- Warning: %d protected sectors will not be erased!\n",
264                         prot);
265         } else {
266                 printf ("\n");
267         }
268
269         /*
270          * Disable interrupts which might cause a timeout
271          * here. Remember that our exception vectors are
272          * at address 0 in the flash, and we don't want a
273          * (ticker) exception to happen while the flash
274          * chip is in programming mode.
275          */
276 #ifdef USE_920T_MMU
277         cflag = dcache_status ();
278         dcache_disable ();
279 #endif
280         iflag = disable_interrupts ();
281
282         /* Start erase on unprotected sectors */
283         for (sect = s_first; sect <= s_last && !ctrlc (); sect++) {
284
285                 debug ("Erasing sector %2d @ %08lX... ",
286                         sect, info->start[sect]);
287
288                 /* arm simple, non interrupt dependent timer */
289                 reset_timer_masked ();
290
291                 if (info->protect[sect] == 0) { /* not protected */
292                         vu_long *addr = (vu_long *) (info->start[sect]);
293                         ulong bsR7, bsR7_2, bsR5, bsR5_2;
294
295                         /* *addr = CMD_STATUS_RESET; */
296                         *addr = CMD_ERASE_SETUP;
297                         *addr = CMD_ERASE_CONFIRM;
298
299                         /* wait until flash is ready */
300                         do {
301                                 /* check timeout */
302                                 if (get_timer_masked () > CFG_FLASH_ERASE_TOUT) {
303                                         *addr = CMD_STATUS_RESET;
304                                         result = BIT_TIMEOUT;
305                                         break;
306                                 }
307
308                                 *addr = CMD_STATUS_READ;
309                                 result = *addr;
310                                 bsR7 = result & (1 << 7);
311                                 bsR7_2 = result & (1 << 23);
312                         } while (!bsR7 | !bsR7_2);
313
314                         *addr = CMD_STATUS_READ;
315                         result1 = *addr;
316                         bsR5 = result1 & (1 << 5);
317                         bsR5_2 = result1 & (1 << 21);
318 #ifdef SAMSUNG_FLASH_DEBUG
319                         printf ("bsR5 %lx bsR5_2 %lx\n", bsR5, bsR5_2);
320                         if (bsR5 != 0 && bsR5_2 != 0)
321                                 printf ("bsR5 %lx bsR5_2 %lx\n", bsR5, bsR5_2);
322 #endif
323
324                         *addr = CMD_READ_ARRAY;
325                         *addr = CMD_RESUME;
326
327                         if ((rc = flash_error (result)) != ERR_OK)
328                                 goto outahere;
329 #if 0
330                         printf ("ok.\n");
331                 } else {                /* it was protected */
332
333                         printf ("protected!\n");
334 #endif
335                 }
336         }
337
338 outahere:
339         /* allow flash to settle - wait 10 ms */
340         udelay_masked (10000);
341
342         if (iflag)
343                 enable_interrupts ();
344
345 #ifdef USE_920T_MMU
346         if (cflag)
347                 dcache_enable ();
348 #endif
349         return rc;
350 }
351
352 /*-----------------------------------------------------------------------
353  * Copy memory to flash
354  */
355
356 volatile static int write_word (flash_info_t * info, ulong dest,
357                                                                 ulong data)
358 {
359         vu_long *addr = (vu_long *) dest;
360         ulong result;
361         int rc = ERR_OK;
362         int iflag;
363
364 #ifdef USE_920T_MMU
365         int cflag;
366 #endif
367
368         /*
369          * Check if Flash is (sufficiently) erased
370          */
371         result = *addr;
372         if ((result & data) != data)
373                 return ERR_NOT_ERASED;
374
375         /*
376          * Disable interrupts which might cause a timeout
377          * here. Remember that our exception vectors are
378          * at address 0 in the flash, and we don't want a
379          * (ticker) exception to happen while the flash
380          * chip is in programming mode.
381          */
382 #ifdef USE_920T_MMU
383         cflag = dcache_status ();
384         dcache_disable ();
385 #endif
386         iflag = disable_interrupts ();
387
388         /* *addr = CMD_STATUS_RESET; */
389         *addr = CMD_PROGRAM;
390         *addr = data;
391
392         /* arm simple, non interrupt dependent timer */
393         reset_timer_masked ();
394
395         /* wait until flash is ready */
396         do {
397                 /* check timeout */
398                 if (get_timer_masked () > CFG_FLASH_ERASE_TOUT) {
399                         *addr = CMD_SUSPEND;
400                         result = BIT_TIMEOUT;
401                         break;
402                 }
403
404                 *addr = CMD_STATUS_READ;
405                 result = *addr;
406         } while (~result & BIT_BUSY);
407
408         /* *addr = CMD_READ_ARRAY; */
409         *addr = CMD_STATUS_READ;
410         result = *addr;
411
412         rc = flash_error (result);
413
414         if (iflag)
415                 enable_interrupts ();
416
417 #ifdef USE_920T_MMU
418         if (cflag)
419                 dcache_enable ();
420 #endif
421         *addr = CMD_READ_ARRAY;
422         *addr = CMD_RESUME;
423         return rc;
424 }
425
426 /*-----------------------------------------------------------------------
427  * Copy memory to flash.
428  */
429
430 int write_buff (flash_info_t * info, uchar * src, ulong addr, ulong cnt)
431 {
432         ulong cp, wp, data;
433         int l;
434         int i, rc;
435
436         wp = (addr & ~3);                       /* get lower word aligned address */
437
438         /*
439          * handle unaligned start bytes
440          */
441         if ((l = addr - wp) != 0) {
442                 data = 0;
443                 for (i = 0, cp = wp; i < l; ++i, ++cp) {
444                         data = (data >> 8) | (*(uchar *) cp << 24);
445                 }
446                 for (; i < 4 && cnt > 0; ++i) {
447                         data = (data >> 8) | (*src++ << 24);
448                         --cnt;
449                         ++cp;
450                 }
451                 for (; cnt == 0 && i < 4; ++i, ++cp) {
452                         data = (data >> 8) | (*(uchar *) cp << 24);
453                 }
454
455                 if ((rc = write_word (info, wp, data)) != 0) {
456                         return (rc);
457                 }
458                 wp += 4;
459         }
460
461         /*
462          * handle word aligned part
463          */
464         while (cnt >= 4) {
465                 data = *((vu_long *) src);
466                 if ((rc = write_word (info, wp, data)) != 0) {
467                         return (rc);
468                 }
469                 src += 4;
470                 wp += 4;
471                 cnt -= 4;
472         }
473
474         if (cnt == 0) {
475                 return ERR_OK;
476         }
477
478         /*
479          * handle unaligned tail bytes
480          */
481         data = 0;
482         for (i = 0, cp = wp; i < 4 && cnt > 0; ++i, ++cp) {
483                 data = (data >> 8) | (*src++ << 24);
484                 --cnt;
485         }
486         for (; i < 4; ++i, ++cp) {
487                 data = (data >> 8) | (*(uchar *) cp << 24);
488         }
489
490         return write_word (info, wp, data);
491 }