Merge branch 'lwmon5' of /home/wd/git/u-boot/projects
[platform/kernel/u-boot.git] / board / cmi / flash.c
1 /*
2  * (C) Copyright 2003
3  * Martin Winistoerfer, martinwinistoerfer@gmx.ch.
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  * File:                flash.c
26  *
27  * Discription:         This Driver is for 28F320J3A, 28F640J3A and
28  *                      28F128J3A Intel flashs working in 16 Bit mode.
29  *                      They are single bank flashs.
30  *
31  *                      Most of this code is taken from existing u-boot
32  *                      source code.
33  */
34
35
36 #include <common.h>
37 #include <mpc5xx.h>
38
39 #if defined(CFG_ENV_IS_IN_FLASH)
40 # ifndef  CFG_ENV_ADDR
41 #  define CFG_ENV_ADDR  (CFG_FLASH_BASE + CFG_ENV_OFFSET)
42 # endif
43 # ifndef  CFG_ENV_SIZE
44 #  define CFG_ENV_SIZE  CFG_ENV_SECT_SIZE
45 # endif
46 # ifndef  CFG_ENV_SECT_SIZE
47 #  define CFG_ENV_SECT_SIZE  CFG_ENV_SIZE
48 # endif
49 #endif
50
51 #define FLASH_ID_MASK                   0xFFFF
52 #define FLASH_BLOCK_SIZE                0x00010000
53 #define FLASH_CMD_READ_ID               0x0090
54 #define FLASH_CMD_RESET                 0x00ff
55 #define FLASH_CMD_BLOCK_ERASE           0x0020
56 #define FLASH_CMD_ERASE_CONFIRM         0x00D0
57 #define FLASH_CMD_CLEAR_STATUS          0x0050
58 #define FLASH_CMD_SUSPEND_ERASE         0x00B0
59 #define FLASH_CMD_WRITE                 0x0040
60 #define FLASH_CMD_PROTECT               0x0060
61 #define FLASH_CMD_PROTECT_SET           0x0001
62 #define FLASH_CMD_PROTECT_CLEAR         0x00D0
63 #define FLASH_STATUS_DONE               0x0080
64
65 flash_info_t    flash_info[CFG_MAX_FLASH_BANKS];
66
67 /*
68  * Local function prototypes
69  */
70 static ulong    flash_get_size          (vu_short *addr, flash_info_t *info);
71 static int      write_short             (flash_info_t *info, ulong dest, ushort data);
72 static void     flash_get_offsets       (ulong base, flash_info_t *info);
73
74 /*
75  * Initialize flash
76  */
77
78 unsigned long flash_init (void)
79 {
80         unsigned long size_b0;
81         int i;
82
83         /* Init: no FLASHes known */
84         for (i=0; i<CFG_MAX_FLASH_BANKS; ++i) {
85                 flash_info[i].flash_id = FLASH_UNKNOWN;
86         }
87
88         /* Static FLASH Bank configuration here - FIXME XXX */
89 #if 1
90         debug ("\n## Get flash bank 1 size @ 0x%08x\n",FLASH_BASE0_PRELIM);
91 #endif
92         size_b0 = flash_get_size((vu_short *)FLASH_BASE0_PRELIM, &flash_info[0]);
93
94         if (flash_info[0].flash_id == FLASH_UNKNOWN) {
95                 printf ("## Unknown FLASH on Bank 0: "
96                         "ID 0x%lx, Size = 0x%08lx = %ld MB\n",
97                         flash_info[0].flash_id,
98                         size_b0, size_b0<<20);
99         }
100
101         flash_get_offsets (FLASH_BASE0_PRELIM, &flash_info[0]);
102
103         flash_info[0].size = size_b0;
104
105 #if CFG_MONITOR_BASE >= CFG_FLASH_BASE
106         /* monitor protection ON by default */
107         flash_protect(FLAG_PROTECT_SET,
108                       CFG_MONITOR_BASE,
109                       CFG_MONITOR_BASE+monitor_flash_len-1,
110                       &flash_info[0]);
111 #endif
112
113 #ifdef  CFG_ENV_IS_IN_FLASH
114         /* ENV protection ON by default */
115         flash_protect(FLAG_PROTECT_SET,
116                       CFG_ENV_ADDR,
117                       CFG_ENV_ADDR+CFG_ENV_SECT_SIZE-1,
118                       &flash_info[0]);
119 #endif
120
121         return size_b0;
122 }
123
124 /*
125  * Compute start adress of each sector (block)
126  */
127
128 static void flash_get_offsets (ulong base, flash_info_t *info)
129 {
130         int i;
131
132         if (info->flash_id == FLASH_UNKNOWN) {
133                 return;
134         }
135
136         switch (info->flash_id & FLASH_VENDMASK) {
137         case FLASH_MAN_INTEL:
138             for (i = 0; i < info->sector_count; i++) {
139                 info->start[i] = base + i * FLASH_BLOCK_SIZE;
140             }
141             return;
142
143         default:
144             printf ("Don't know sector offsets for flash type 0x%lx\n",
145                 info->flash_id);
146             return;
147         }
148 }
149
150 /*
151  * Print flash information
152  */
153 void flash_print_info  (flash_info_t *info)
154 {
155         int i;
156
157         if (info->flash_id == FLASH_UNKNOWN) {
158                 printf ("missing or unknown FLASH type\n");
159                 return;
160         }
161
162         switch (info->flash_id & FLASH_VENDMASK) {
163         case FLASH_MAN_AMD:     printf ("AMD ");                break;
164         case FLASH_MAN_FUJ:     printf ("Fujitsu ");            break;
165         case FLASH_MAN_SST:     printf ("SST ");                break;
166         case FLASH_MAN_STM:     printf ("STM ");                break;
167         case FLASH_MAN_INTEL:   printf ("Intel ");              break;
168         case FLASH_MAN_MT:      printf ("MT ");                 break;
169         default:                printf ("Unknown Vendor ");     break;
170         }
171
172         switch (info->flash_id & FLASH_TYPEMASK) {
173         case FLASH_28F320J3A:   printf ("28F320J3A (32Mbit) 16-Bit\n");
174                                 break;
175         case FLASH_28F640J3A:   printf ("28F640J3A (64Mbit) 16-Bit\n");
176                                 break;
177         case FLASH_28F128J3A:   printf ("28F128J3A (128Mbit) 16-Bit\n");
178                                 break;
179         default:                printf ("Unknown Chip Type\n");
180                                 break;
181         }
182
183         if (info->size >= (1 << 20)) {
184                 i = 20;
185         } else {
186                 i = 10;
187         }
188         printf ("  Size: %ld %cB in %d Sectors\n",
189                 info->size >> i,
190                 (i == 20) ? 'M' : 'k',
191                 info->sector_count);
192
193         printf ("  Sector Start Addresses:");
194         for (i=0; i<info->sector_count; ++i) {
195                 if ((i % 5) == 0)
196                         printf ("\n   ");
197                 printf (" %08lX%s",
198                         info->start[i],
199                         info->protect[i] ? " (RO)" : "     "
200                 );
201         }
202         printf ("\n");
203         return;
204 }
205
206 /*
207  * Get size of flash in bytes.
208  * The following code cannot be run from FLASH!
209  */
210
211 static ulong flash_get_size (vu_short *addr, flash_info_t *info)
212 {
213         vu_short value;
214
215         /* Read Manufacturer ID */
216         addr[0] = FLASH_CMD_READ_ID;
217         value = addr[0];
218
219         switch (value) {
220         case (AMD_MANUFACT & FLASH_ID_MASK):
221                 info->flash_id = FLASH_MAN_AMD;
222                 break;
223         case (FUJ_MANUFACT & FLASH_ID_MASK):
224                 info->flash_id = FLASH_MAN_FUJ;
225                 break;
226         case (SST_MANUFACT & FLASH_ID_MASK):
227                 info->flash_id = FLASH_MAN_SST;
228                 break;
229         case (STM_MANUFACT & FLASH_ID_MASK):
230                 info->flash_id = FLASH_MAN_STM;
231                 break;
232         case (INTEL_MANUFACT & FLASH_ID_MASK):
233                 info->flash_id = FLASH_MAN_INTEL;
234                 break;
235         default:
236                 info->flash_id = FLASH_UNKNOWN;
237                 info->sector_count = 0;
238                 info->size = 0;
239                 addr[0] = FLASH_CMD_RESET;      /* restore read mode */
240                 return (0);                     /* no or unknown flash  */
241         }
242
243         value = addr[1];                        /* device ID            */
244
245         switch (value) {
246         case (INTEL_ID_28F320J3A  & FLASH_ID_MASK):
247                 info->flash_id += FLASH_28F320J3A;
248                 info->sector_count = 32;
249                 info->size = 0x00400000;
250                 break;                          /* =>  32 MBit          */
251
252         case (INTEL_ID_28F640J3A & FLASH_ID_MASK):
253                 info->flash_id += FLASH_28F640J3A;
254                 info->sector_count = 64;
255                 info->size = 0x00800000;
256                 break;                          /* => 64 MBit           */
257
258         case (INTEL_ID_28F128J3A & FLASH_ID_MASK):
259                 info->flash_id += FLASH_28F128J3A;
260                 info->sector_count = 128;
261                 info->size = 0x01000000;
262                 break;                          /* => 128 MBit          */
263
264         default:
265                 info->flash_id = FLASH_UNKNOWN;
266                 addr[0] = FLASH_CMD_RESET;      /* restore read mode */
267                 return (0);                     /* => no or unknown flash */
268
269         }
270
271         if (info->sector_count > CFG_MAX_FLASH_SECT) {
272                 printf ("** ERROR: sector count %d > max (%d) **\n",
273                         info->sector_count, CFG_MAX_FLASH_SECT);
274                 info->sector_count = CFG_MAX_FLASH_SECT;
275         }
276
277         addr[0] = FLASH_CMD_RESET;              /* restore read mode */
278
279         return (info->size);
280 }
281
282
283 /*
284  * Erase unprotected sectors
285  */
286
287 int flash_erase (flash_info_t *info, int s_first, int s_last)
288 {
289         int flag, prot, sect;
290         ulong start, now, last;
291
292         if ((s_first < 0) || (s_first > s_last)) {
293                 if (info->flash_id == FLASH_UNKNOWN) {
294                         printf ("- missing\n");
295                 } else {
296                         printf ("- no sectors to erase\n");
297                 }
298                 return 1;
299         }
300
301         if ((info->flash_id & FLASH_VENDMASK) != FLASH_MAN_INTEL) {
302                 printf ("Can erase only Intel flash types - aborted\n");
303                 return 1;
304         }
305
306         prot = 0;
307         for (sect=s_first; sect<=s_last; ++sect) {
308                 if (info->protect[sect]) {
309                         prot++;
310                 }
311         }
312
313         if (prot) {
314                 printf ("- Warning: %d protected sectors will not be erased!\n",
315                         prot);
316         } else {
317                 printf ("\n");
318         }
319
320         start = get_timer (0);
321         last  = start;
322
323         /* Start erase on unprotected sectors */
324         for (sect = s_first; sect<=s_last; sect++) {
325                 if (info->protect[sect] == 0) { /* not protected */
326                         vu_short *addr = (vu_short *)(info->start[sect]);
327                         unsigned long status;
328
329                         /* Disable interrupts which might cause a timeout here */
330                         flag = disable_interrupts();
331
332 #ifdef DEBUG
333                         printf("Erase sector %d at start addr 0x%08X", sect, (unsigned int)info->start[sect]);
334 #endif
335
336                         *addr = FLASH_CMD_CLEAR_STATUS;
337                         *addr = FLASH_CMD_BLOCK_ERASE;
338                         *addr = FLASH_CMD_ERASE_CONFIRM;
339
340                         /* re-enable interrupts if necessary */
341                         if (flag)
342                                 enable_interrupts();
343
344                         /* wait at least 80us - let's wait 1 ms */
345                         udelay (1000);
346
347                         while (((status = *addr) & FLASH_STATUS_DONE) != FLASH_STATUS_DONE) {
348                                 if ((now=get_timer(start)) > CFG_FLASH_ERASE_TOUT) {
349                                         printf("Flash erase timeout at address %lx\n", info->start[sect]);
350                                         *addr = FLASH_CMD_SUSPEND_ERASE;
351                                         *addr = FLASH_CMD_RESET;
352                                         return 1;
353                                 }
354
355                                 /* show that we're waiting */
356                                 if ((now - last) > 1000) {      /* every second */
357                                         putc ('.');
358                                         last = now;
359                                 }
360                         }
361                         *addr = FLASH_CMD_RESET;
362                 }
363         }
364         printf (" done\n");
365         return 0;
366 }
367
368 /*
369  * Copy memory to flash, returns:
370  * 0 - OK
371  * 1 - write timeout
372  * 2 - Flash not erased
373  * 4 - Flash not identified
374  */
375
376 int write_buff (flash_info_t *info, uchar *src, ulong addr, ulong cnt)
377 {
378         ulong cp, wp;
379         ushort data;
380         int i, rc;
381
382         if (info->flash_id == FLASH_UNKNOWN) {
383                 return 4;
384         }
385
386         wp = (addr & ~1);       /* get lower word aligned address */
387
388         /*
389          * handle unaligned start byte
390          */
391
392         if (addr - wp) {
393                 data = 0;
394                 data = (data << 8) | *src++;
395                 --cnt;
396                 if ((rc = write_short(info, wp, data)) != 0) {
397                         return (rc);
398                 }
399                 wp += 2;
400         }
401
402         /*
403          * handle word aligned part
404          */
405
406         while (cnt >= 2) {
407                 data = 0;
408                 for (i=0; i<2; ++i) {
409                         data = (data << 8) | *src++;
410                 }
411
412                 if ((rc = write_short(info, wp, data)) != 0) {
413                         return (rc);
414                 }
415                 wp  += 2;
416                 cnt -= 2;
417         }
418
419         if (cnt == 0) {
420                 return (0);
421         }
422
423         /*
424          * handle unaligned tail bytes
425          */
426
427         data = 0;
428         for (i=0, cp=wp; i<2 && cnt>0; ++i, ++cp) {
429                 data = (data << 8) | *src++;
430                 --cnt;
431         }
432         for (; i<2; ++i, ++cp) {
433                 data = (data << 8) | (*(uchar *)cp);
434         }
435
436         return (write_short(info, wp, data));
437
438 }
439
440 /*
441  * Write 16 bit (short) to flash
442  */
443
444 static int write_short (flash_info_t *info, ulong dest, ushort data)
445 {
446         vu_short *addr = (vu_short*)(info->start[0]);
447         ulong start;
448         int flag;
449
450         /* Check if Flash is (sufficiently) erased */
451         if ((*((vu_short *)dest) & data) != data) {
452                 return (2);
453         }
454
455         /* Disable interrupts which might cause a timeout here */
456         flag = disable_interrupts();
457
458         if (!(info->flash_id & FLASH_VENDMASK)) {
459                 return 4;
460         }
461         *addr = FLASH_CMD_ERASE_CONFIRM;
462         *addr = FLASH_CMD_WRITE;
463
464         *((vu_short *)dest) = data;
465
466         /* re-enable interrupts if necessary */
467         if (flag) {
468                 enable_interrupts();
469         }
470
471         /* data polling for D7 */
472         start = get_timer (0);
473
474         /* wait for error or finish */
475         while(!(addr[0] & FLASH_STATUS_DONE)){
476                 if (get_timer(start) > CFG_FLASH_WRITE_TOUT) {
477                         addr[0] = FLASH_CMD_RESET;
478                         return (1);
479                 }
480         }
481
482         *addr = FLASH_CMD_RESET;
483         return (0);
484 }
485
486 /*
487  * Protects a flash sector
488  */
489
490 int flash_real_protect(flash_info_t *info, long sector, int prot)
491 {
492         vu_short *addr = (vu_short*)(info->start[sector]);
493         ulong start;
494
495         *addr = FLASH_CMD_CLEAR_STATUS;
496         *addr = FLASH_CMD_PROTECT;
497
498         if(prot) {
499                 *addr = FLASH_CMD_PROTECT_SET;
500         } else {
501                 *addr = FLASH_CMD_PROTECT_CLEAR;
502         }
503
504         /* wait for error or finish */
505         start = get_timer (0);
506         while(!(addr[0] & FLASH_STATUS_DONE)){
507                 if (get_timer(start) > CFG_FLASH_ERASE_TOUT) {
508                         printf("Flash protect timeout at address %lx\n",  info->start[sector]);
509                         addr[0] = FLASH_CMD_RESET;
510                         return (1);
511                 }
512         }
513         /* Set software protect flag */
514         info->protect[sector] = prot;
515         *addr = FLASH_CMD_RESET;
516         return (0);
517 }