Merge branch 'master' of git://git.denx.de/u-boot-nand-flash
[platform/kernel/u-boot.git] / board / a3000 / flash.c
1 /*
2  * (C) Copyright 2001
3  * Wolfgang Denk, DENX Software Engineering, wd@denx.de.
4  *
5  * See file CREDITS for list of people who contributed to this
6  * project.
7  *
8  * This program is free software; you can redistribute it and/or
9  * modify it under the terms of the GNU General Public License as
10  * published by the Free Software Foundation; either version 2 of
11  * the License, or (at your option) any later version.
12  *
13  * This program is distributed in the hope that it will be useful,
14  * but WITHOUT ANY WARRANTY; without even the implied warranty of
15  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
16  * GNU General Public License for more details.
17  *
18  * You should have received a copy of the GNU General Public License
19  * along with this program; if not, write to the Free Software
20  * Foundation, Inc., 59 Temple Place, Suite 330, Boston,
21  * MA 02111-1307 USA
22  */
23
24
25 #include <common.h>
26 #include <mpc824x.h>
27
28 #if defined(CONFIG_ENV_IS_IN_FLASH)
29 # ifndef  CONFIG_ENV_ADDR
30 #  define CONFIG_ENV_ADDR  (CFG_FLASH_BASE + CONFIG_ENV_OFFSET)
31 # endif
32 # ifndef  CONFIG_ENV_SIZE
33 #  define CONFIG_ENV_SIZE  CONFIG_ENV_SECT_SIZE
34 # endif
35 # ifndef  CONFIG_ENV_SECT_SIZE
36 #  define CONFIG_ENV_SECT_SIZE  CONFIG_ENV_SIZE
37 # endif
38 #endif
39
40
41 /*---------------------------------------------------------------------*/
42 #define DEBUG_FLASH
43
44 #ifdef DEBUG_FLASH
45 #define DEBUGF(fmt,args...) printf(fmt ,##args)
46 #else
47 #define DEBUGF(fmt,args...)
48 #endif
49 /*---------------------------------------------------------------------*/
50
51 flash_info_t    flash_info[CFG_MAX_FLASH_BANKS]; /* info for FLASH chips        */
52
53 /*-----------------------------------------------------------------------
54  * Functions
55  */
56 static ulong flash_get_size (vu_char *addr, flash_info_t *info);
57 static int write_data (flash_info_t *info, uchar *dest, uchar data);
58 static void flash_get_offsets (ulong base, flash_info_t *info);
59
60 #define BS(b)     (b)
61 #define BYTEME(x) ((x) & 0xFF)
62
63 /*-----------------------------------------------------------------------
64  */
65
66 unsigned long flash_init (void)
67 {
68         unsigned long flash_banks[CFG_MAX_FLASH_BANKS] = CFG_FLASH_BANKS;
69         unsigned long size, size_b[CFG_MAX_FLASH_BANKS];
70
71         int i;
72
73         /* Init: no FLASHes known */
74         for (i=0; i<CFG_MAX_FLASH_BANKS; ++i)
75         {
76                 flash_info[i].flash_id = FLASH_UNKNOWN;
77
78                 DEBUGF("Get flash bank %d @ 0x%08lx\n", i, flash_banks[i]);
79 /*
80                 size_b[i] = flash_get_size((vu_char *)flash_banks[i], &flash_info[i]);
81 */
82                 size_b[i] = flash_get_size((vu_char *) 0xff800000 , &flash_info[i]);
83
84                 if (flash_info[i].flash_id == FLASH_UNKNOWN)
85                 {
86                         printf ("## Unknown FLASH on Bank %d: "
87                                 "ID 0x%lx, Size = 0x%08lx = %ld MB\n",
88                                 i, flash_info[i].flash_id,
89                                 size_b[i], size_b[i]<<20);
90                 }
91                 else
92                 {
93                         DEBUGF("## Flash bank %d at 0x%08lx sizes: 0x%08lx \n",
94                                 i, flash_banks[i], size_b[i]);
95
96                         flash_get_offsets (flash_banks[i], &flash_info[i]);
97                         flash_info[i].size = size_b[i];
98                 }
99         }
100
101
102 #if CFG_MONITOR_BASE >= CFG_FLASH_BASE
103         DEBUGF("protect monitor %x @ %x\n", CFG_MONITOR_BASE, CFG_MONITOR_LEN);
104         /* monitor protection ON by default */
105         flash_protect(FLAG_PROTECT_SET,
106                       CFG_MONITOR_BASE,
107                       CFG_MONITOR_BASE+CFG_MONITOR_LEN-1,
108                       &flash_info[0]);
109 #endif
110
111 #ifdef  CONFIG_ENV_IS_IN_FLASH
112         /* ENV protection ON by default */
113         DEBUGF("protect environtment %x @ %x\n", CONFIG_ENV_ADDR, CONFIG_ENV_SECT_SIZE);
114         flash_protect(FLAG_PROTECT_SET,
115                       CONFIG_ENV_ADDR,
116                       CONFIG_ENV_ADDR+CONFIG_ENV_SECT_SIZE-1,
117                       &flash_info[0]);
118 #endif
119
120         size = 0;
121         DEBUGF("## Final Flash bank sizes: ");
122         for (i=0; i<CFG_MAX_FLASH_BANKS; ++i)
123         {
124                 DEBUGF("%08lx ", size_b[i]);
125                 size += size_b[i];
126         }
127         DEBUGF("\n");
128         return (size);
129 }
130
131 /*-----------------------------------------------------------------------
132  */
133 static void flash_get_offsets (ulong base, flash_info_t *info)
134 {
135         int i;
136
137         if (info->flash_id == FLASH_UNKNOWN) {
138                 return;
139         }
140
141         switch (info->flash_id & FLASH_VENDMASK) {
142                 case FLASH_MAN_INTEL:
143                     for (i = 0; i < info->sector_count; i++) {
144                                 info->start[i] = base;
145                                 base += 0x00020000;             /* 128k per bank */
146                     }
147                     return;
148
149                 default:
150                     printf ("Don't know sector ofsets for flash type 0x%lx\n", info->flash_id);
151                     return;
152         }
153 }
154
155 /*-----------------------------------------------------------------------
156  */
157 void flash_print_info  (flash_info_t *info)
158 {
159         int i;
160
161         if (info->flash_id == FLASH_UNKNOWN) {
162                 printf ("missing or unknown FLASH type\n");
163                 return;
164         }
165
166         switch (info->flash_id & FLASH_VENDMASK) {
167         case FLASH_MAN_AMD:     printf ("AMD ");                break;
168         case FLASH_MAN_FUJ:     printf ("Fujitsu ");            break;
169         case FLASH_MAN_SST:     printf ("SST ");                break;
170         case FLASH_MAN_STM:     printf ("STM ");                break;
171         case FLASH_MAN_INTEL:   printf ("Intel ");              break;
172         case FLASH_MAN_MT:      printf ("MT ");                 break;
173         default:                printf ("Unknown Vendor ");     break;
174         }
175
176         switch (info->flash_id & FLASH_TYPEMASK) {
177         case FLASH_28F320J3A:
178                         printf ("28F320J3A (32Mbit = 128K x 32)\n");
179                         break;
180         case FLASH_28F640J3A:
181                         printf ("28F640J3A (64Mbit = 128K x 64)\n");
182                         break;
183         case FLASH_28F128J3A:
184                         printf ("28F128J3A (128Mbit = 128K x 128)\n");
185                         break;
186         default:
187                         printf ("Unknown Chip Type\n");
188                         break;
189         }
190
191 #if 1
192         if (info->size >= (1 << 20)) {
193                 i = 20;
194         } else {
195                 i = 10;
196         }
197         printf ("  Size: %ld %cB in %d Sectors\n",
198                 info->size >> i,
199                 (i == 20) ? 'M' : 'k',
200                 info->sector_count);
201
202         printf ("  Sector Start Addresses:");
203         for (i=0; i<info->sector_count; ++i) {
204                 if ((i % 5) == 0)
205                         printf ("\n   ");
206                 printf (" %08lX%s",
207                         info->start[i],
208                         info->protect[i] ? " (RO)" : "     "
209                 );
210         }
211         printf ("\n");
212 #endif
213         return;
214 }
215
216 /*-----------------------------------------------------------------------
217  */
218
219
220 /*-----------------------------------------------------------------------
221  */
222
223 /*
224  * The following code cannot be run from FLASH!
225  */
226 static ulong flash_get_size (vu_char *addr, flash_info_t *info)
227 {
228         vu_char manuf, device;
229
230         addr[0] = BS(0x90);
231         manuf = BS(addr[0]);
232         DEBUGF("Manuf. ID @ 0x%08lx: 0x%08x\n", (ulong)addr, manuf);
233
234         switch (manuf) {
235         case BYTEME(AMD_MANUFACT):
236                 info->flash_id = FLASH_MAN_AMD;
237                 break;
238         case BYTEME(FUJ_MANUFACT):
239                 info->flash_id = FLASH_MAN_FUJ;
240                 break;
241         case BYTEME(SST_MANUFACT):
242                 info->flash_id = FLASH_MAN_SST;
243                 break;
244         case BYTEME(STM_MANUFACT):
245                 info->flash_id = FLASH_MAN_STM;
246                 break;
247         case BYTEME(INTEL_MANUFACT):
248                 info->flash_id = FLASH_MAN_INTEL;
249                 break;
250         default:
251                 info->flash_id = FLASH_UNKNOWN;
252                 info->sector_count = 0;
253                 info->size = 0;
254                 addr[0] = BS(0xFF);             /* restore read mode, (yes, BS is a NOP) */
255                 return 0;                       /* no or unknown flash  */
256         }
257
258         device = BS(addr[2]);                   /* device ID            */
259
260         DEBUGF("Device ID @ 0x%08lx: 0x%08x\n", (ulong)(&addr[1]), device);
261
262         switch (device) {
263         case BYTEME(INTEL_ID_28F320J3A):
264                 info->flash_id += FLASH_28F320J3A;
265                 info->sector_count = 32;
266                 info->size = 0x00400000;
267                 break;                          /* =>  4 MB             */
268
269         case BYTEME(INTEL_ID_28F640J3A):
270                 info->flash_id += FLASH_28F640J3A;
271                 info->sector_count = 64;
272                 info->size = 0x00800000;
273                 break;                          /* => 8 MB              */
274
275         case BYTEME(INTEL_ID_28F128J3A):
276                 info->flash_id += FLASH_28F128J3A;
277                 info->sector_count = 128;
278                 info->size = 0x01000000;
279                 break;                          /* => 16 MB             */
280
281         default:
282                 info->flash_id = FLASH_UNKNOWN;
283                 addr[0] = BS(0xFF);             /* restore read mode (yes, a NOP) */
284                 return 0;                       /* => no or unknown flash */
285
286         }
287
288         if (info->sector_count > CFG_MAX_FLASH_SECT) {
289                 printf ("** ERROR: sector count %d > max (%d) **\n",
290                         info->sector_count, CFG_MAX_FLASH_SECT);
291                 info->sector_count = CFG_MAX_FLASH_SECT;
292         }
293
294         addr[0] = BS(0xFF);             /* restore read mode */
295
296         return (info->size);
297 }
298
299
300 /*-----------------------------------------------------------------------
301  */
302
303 int     flash_erase (flash_info_t *info, int s_first, int s_last)
304 {
305         int flag, prot, sect;
306         ulong start, now, last;
307
308         if ((s_first < 0) || (s_first > s_last)) {
309                 if (info->flash_id == FLASH_UNKNOWN) {
310                         printf ("- missing\n");
311                 } else {
312                         printf ("- no sectors to erase\n");
313                 }
314                 return 1;
315         }
316
317         if ((info->flash_id & FLASH_VENDMASK) != FLASH_MAN_INTEL) {
318                 printf ("Can erase only Intel flash types - aborted\n");
319                 return 1;
320         }
321
322         prot = 0;
323         for (sect=s_first; sect<=s_last; ++sect) {
324                 if (info->protect[sect]) {
325                         prot++;
326                 }
327         }
328
329         if (prot) {
330                 printf ("- Warning: %d protected sectors will not be erased!\n", prot);
331         } else {
332                 printf ("\n");
333         }
334
335         start = get_timer (0);
336         last  = start;
337         /* Start erase on unprotected sectors */
338         for (sect = s_first; sect<=s_last; sect++) {
339                 if (info->protect[sect] == 0) { /* not protected */
340                         vu_char *addr = (vu_char *)(info->start[sect]);
341                         unsigned long status;
342
343                         /* Disable interrupts which might cause a timeout here */
344                         flag = disable_interrupts();
345
346                         *addr = BS(0x50);       /* clear status register */
347                         *addr = BS(0x20);       /* erase setup */
348                         *addr = BS(0xD0);       /* erase confirm */
349
350                         /* re-enable interrupts if necessary */
351                         if (flag) {
352                                 enable_interrupts();
353                         }
354
355                         /* wait at least 80us - let's wait 1 ms */
356                         udelay (1000);
357
358                         while (((status = BS(*addr)) & BYTEME(0x00800080)) != BYTEME(0x00800080)) {
359                                 if ((now=get_timer(start)) > CFG_FLASH_ERASE_TOUT) {
360                                         printf ("Timeout\n");
361                                         *addr = BS(0xB0); /* suspend erase        */
362                                         *addr = BS(0xFF); /* reset to read mode */
363                                         return 1;
364                                 }
365
366                                 /* show that we're waiting */
367                                 if ((now - last) > 1000) {      /* every second */
368                                         putc ('.');
369                                         last = now;
370                                 }
371                         }
372
373                         *addr = BS(0xFF);       /* reset to read mode */
374                 }
375         }
376         printf (" done\n");
377         return 0;
378 }
379
380 /*-----------------------------------------------------------------------
381  * Copy memory to flash, returns:
382  * 0 - OK
383  * 1 - write timeout
384  * 2 - Flash not erased
385  * 4 - Flash not identified
386  */
387
388 #define FLASH_WIDTH     1       /* flash bus width in bytes */
389
390 int write_buff (flash_info_t *info, uchar *src, ulong addr, ulong cnt)
391 {
392         uchar *wp = (uchar *)addr;
393         int rc;
394
395         if (info->flash_id == FLASH_UNKNOWN) {
396                 return 4;
397         }
398
399         while (cnt > 0) {
400                 if ((rc = write_data(info, wp, *src)) != 0) {
401                         return rc;
402                 }
403                 wp++;
404                 src++;
405                 cnt--;
406         }
407
408         return cnt;
409 }
410
411 /*-----------------------------------------------------------------------
412  * Write a word to Flash, returns:
413  * 0 - OK
414  * 1 - write timeout
415  * 2 - Flash not erased
416  */
417 static int write_data (flash_info_t *info, uchar *dest, uchar data)
418 {
419         vu_char *addr = (vu_char *)dest;
420         ulong status;
421         ulong start;
422         int flag;
423
424         /* Check if Flash is (sufficiently) erased */
425         if ((BS(*addr) & data) != data) {
426                 return 2;
427         }
428         /* Disable interrupts which might cause a timeout here */
429         flag = disable_interrupts();
430
431         *addr = BS(0x40);               /* write setup */
432         *addr = data;
433
434         /* re-enable interrupts if necessary */
435         if (flag) {
436                 enable_interrupts();
437         }
438
439         start = get_timer (0);
440
441         while (((status = BS(*addr)) & BYTEME(0x00800080)) != BYTEME(0x00800080)) {
442                 if (get_timer(start) > CFG_FLASH_WRITE_TOUT) {
443                         *addr = BS(0xFF);       /* restore read mode */
444                         return 1;
445                 }
446         }
447
448         *addr = BS(0xFF);       /* restore read mode */
449
450         return 0;
451 }
452
453 /*-----------------------------------------------------------------------
454  */