]> git.sur5r.net Git - u-boot/blob - board/samsung/smdk2400/flash.c
Merge branch 'master' of git://git.denx.de/u-boot-blackfin
[u-boot] / board / samsung / 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, <garyj@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[CONFIG_SYS_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 < CONFIG_SYS_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 = CONFIG_SYS_MAX_FLASH_SECT;
77                 memset (flash_info[i].protect, 0, CONFIG_SYS_MAX_FLASH_SECT);
78                 if (i == 0)
79                         flashbase = CONFIG_SYS_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                         CONFIG_SYS_FLASH_BASE,
96                         CONFIG_SYS_FLASH_BASE + monitor_flash_len - 1,
97                         &flash_info[0]);
98
99         flash_protect ( FLAG_PROTECT_SET,
100                         CONFIG_ENV_ADDR,
101                         CONFIG_ENV_ADDR + CONFIG_ENV_SECT_SIZE - 1, &flash_info[0]);
102
103 #ifdef CONFIG_ENV_ADDR_REDUND
104         flash_protect ( FLAG_PROTECT_SET,
105                         CONFIG_ENV_ADDR_REDUND,
106                         CONFIG_ENV_ADDR_REDUND + CONFIG_ENV_SECT_SIZE - 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         ulong start;
235
236 #ifdef USE_920T_MMU
237         int cflag;
238 #endif
239
240         debug ("flash_erase: s_first %d  s_last %d\n", s_first, s_last);
241
242         /* first look for protection bits */
243
244         if (info->flash_id == FLASH_UNKNOWN)
245                 return ERR_UNKNOWN_FLASH_TYPE;
246
247         if ((s_first < 0) || (s_first > s_last)) {
248                 return ERR_INVAL;
249         }
250
251         if ((info->flash_id & FLASH_VENDMASK) !=
252                 (INTEL_MANUFACT & FLASH_VENDMASK)) {
253                 return ERR_UNKNOWN_FLASH_VENDOR;
254         }
255
256         prot = 0;
257         for (sect = s_first; sect <= s_last; ++sect) {
258                 if (info->protect[sect]) {
259                         prot++;
260                 }
261         }
262
263         if (prot) {
264                 printf ("- Warning: %d protected sectors will not be erased!\n",
265                         prot);
266         } else {
267                 printf ("\n");
268         }
269
270         /*
271          * Disable interrupts which might cause a timeout
272          * here. Remember that our exception vectors are
273          * at address 0 in the flash, and we don't want a
274          * (ticker) exception to happen while the flash
275          * chip is in programming mode.
276          */
277 #ifdef USE_920T_MMU
278         cflag = dcache_status ();
279         dcache_disable ();
280 #endif
281         iflag = disable_interrupts ();
282
283         /* Start erase on unprotected sectors */
284         for (sect = s_first; sect <= s_last && !ctrlc (); sect++) {
285
286                 debug ("Erasing sector %2d @ %08lX... ",
287                         sect, info->start[sect]);
288
289                 /* arm simple, non interrupt dependent timer */
290                 start = get_timer(0);
291
292                 if (info->protect[sect] == 0) { /* not protected */
293                         vu_long *addr = (vu_long *) (info->start[sect]);
294                         ulong bsR7, bsR7_2, bsR5, bsR5_2;
295
296                         /* *addr = CMD_STATUS_RESET; */
297                         *addr = CMD_ERASE_SETUP;
298                         *addr = CMD_ERASE_CONFIRM;
299
300                         /* wait until flash is ready */
301                         do {
302                                 /* check timeout */
303                                 if (get_timer(start) > CONFIG_SYS_FLASH_ERASE_TOUT) {
304                                         *addr = CMD_STATUS_RESET;
305                                         result = BIT_TIMEOUT;
306                                         break;
307                                 }
308
309                                 *addr = CMD_STATUS_READ;
310                                 result = *addr;
311                                 bsR7 = result & (1 << 7);
312                                 bsR7_2 = result & (1 << 23);
313                         } while (!bsR7 | !bsR7_2);
314
315                         *addr = CMD_STATUS_READ;
316                         result1 = *addr;
317                         bsR5 = result1 & (1 << 5);
318                         bsR5_2 = result1 & (1 << 21);
319 #ifdef SAMSUNG_FLASH_DEBUG
320                         printf ("bsR5 %lx bsR5_2 %lx\n", bsR5, bsR5_2);
321                         if (bsR5 != 0 && bsR5_2 != 0)
322                                 printf ("bsR5 %lx bsR5_2 %lx\n", bsR5, bsR5_2);
323 #endif
324
325                         *addr = CMD_READ_ARRAY;
326                         *addr = CMD_RESUME;
327
328                         if ((rc = flash_error (result)) != ERR_OK)
329                                 goto outahere;
330 #if 0
331                         printf ("ok.\n");
332                 } else {                /* it was protected */
333
334                         printf ("protected!\n");
335 #endif
336                 }
337         }
338
339 outahere:
340         /* allow flash to settle - wait 10 ms */
341         udelay_masked (10000);
342
343         if (iflag)
344                 enable_interrupts ();
345
346 #ifdef USE_920T_MMU
347         if (cflag)
348                 dcache_enable ();
349 #endif
350         return rc;
351 }
352
353 /*-----------------------------------------------------------------------
354  * Copy memory to flash
355  */
356
357 static int write_word (flash_info_t * info, ulong dest, ulong data)
358 {
359         vu_long *addr = (vu_long *) dest;
360         ulong result;
361         int rc = ERR_OK;
362         int iflag;
363         ulong start;
364
365 #ifdef USE_920T_MMU
366         int cflag;
367 #endif
368
369         /*
370          * Check if Flash is (sufficiently) erased
371          */
372         result = *addr;
373         if ((result & data) != data)
374                 return ERR_NOT_ERASED;
375
376         /*
377          * Disable interrupts which might cause a timeout
378          * here. Remember that our exception vectors are
379          * at address 0 in the flash, and we don't want a
380          * (ticker) exception to happen while the flash
381          * chip is in programming mode.
382          */
383 #ifdef USE_920T_MMU
384         cflag = dcache_status ();
385         dcache_disable ();
386 #endif
387         iflag = disable_interrupts ();
388
389         /* *addr = CMD_STATUS_RESET; */
390         *addr = CMD_PROGRAM;
391         *addr = data;
392
393         /* arm simple, non interrupt dependent timer */
394         start = get_timer(0);
395
396         /* wait until flash is ready */
397         do {
398                 /* check timeout */
399                 if (get_timer(start) > CONFIG_SYS_FLASH_ERASE_TOUT) {
400                         *addr = CMD_SUSPEND;
401                         result = BIT_TIMEOUT;
402                         break;
403                 }
404
405                 *addr = CMD_STATUS_READ;
406                 result = *addr;
407         } while (~result & BIT_BUSY);
408
409         /* *addr = CMD_READ_ARRAY; */
410         *addr = CMD_STATUS_READ;
411         result = *addr;
412
413         rc = flash_error (result);
414
415         if (iflag)
416                 enable_interrupts ();
417
418 #ifdef USE_920T_MMU
419         if (cflag)
420                 dcache_enable ();
421 #endif
422         *addr = CMD_READ_ARRAY;
423         *addr = CMD_RESUME;
424         return rc;
425 }
426
427 /*-----------------------------------------------------------------------
428  * Copy memory to flash.
429  */
430
431 int write_buff (flash_info_t * info, uchar * src, ulong addr, ulong cnt)
432 {
433         ulong cp, wp, data;
434         int l;
435         int i, rc;
436
437         wp = (addr & ~3);                       /* get lower word aligned address */
438
439         /*
440          * handle unaligned start bytes
441          */
442         if ((l = addr - wp) != 0) {
443                 data = 0;
444                 for (i = 0, cp = wp; i < l; ++i, ++cp) {
445                         data = (data >> 8) | (*(uchar *) cp << 24);
446                 }
447                 for (; i < 4 && cnt > 0; ++i) {
448                         data = (data >> 8) | (*src++ << 24);
449                         --cnt;
450                         ++cp;
451                 }
452                 for (; cnt == 0 && i < 4; ++i, ++cp) {
453                         data = (data >> 8) | (*(uchar *) cp << 24);
454                 }
455
456                 if ((rc = write_word (info, wp, data)) != 0) {
457                         return (rc);
458                 }
459                 wp += 4;
460         }
461
462         /*
463          * handle word aligned part
464          */
465         while (cnt >= 4) {
466                 data = *((vu_long *) src);
467                 if ((rc = write_word (info, wp, data)) != 0) {
468                         return (rc);
469                 }
470                 src += 4;
471                 wp += 4;
472                 cnt -= 4;
473         }
474
475         if (cnt == 0) {
476                 return ERR_OK;
477         }
478
479         /*
480          * handle unaligned tail bytes
481          */
482         data = 0;
483         for (i = 0, cp = wp; i < 4 && cnt > 0; ++i, ++cp) {
484                 data = (data >> 8) | (*src++ << 24);
485                 --cnt;
486         }
487         for (; i < 4; ++i, ++cp) {
488                 data = (data >> 8) | (*(uchar *) cp << 24);
489         }
490
491         return write_word (info, wp, data);
492 }