Merge with /home/wd/git/u-boot/custodian/u-boot-mpc83xx
[platform/kernel/u-boot.git] / board / hymod / flash.c
1 /*
2  * (C) Copyright 2000
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  * Hacked for the Hymod board by Murray.Jensen@csiro.au, 20-Oct-00
24  */
25
26 #include <common.h>
27 #include <mpc8260.h>
28 #include <board/hymod/flash.h>
29
30 flash_info_t flash_info[CFG_MAX_FLASH_BANKS];   /* info for FLASH chips */
31
32 /*-----------------------------------------------------------------------
33  * Protection Flags:
34  */
35 #define FLAG_PROTECT_SET        0x01
36 #define FLAG_PROTECT_CLEAR      0x02
37
38 /*-----------------------------------------------------------------------
39  */
40
41 /*
42  * probe for flash bank at address "base" and store info about it
43  * in the flash_info entry "fip". Fatal error if nothing there.
44  */
45 static void
46 bank_probe (flash_info_t *fip, volatile bank_addr_t base)
47 {
48         volatile bank_addr_t addr;
49         bank_word_t word;
50         int i;
51
52         /* reset the flash */
53         *base = BANK_CMD_RST;
54
55         /* put flash into read id mode */
56         *base = BANK_CMD_RD_ID;
57
58         /* check the manufacturer id - must be intel */
59         word = *BANK_REG_MAN_CODE (base);
60         if (word != BANK_FILL_WORD (INTEL_MANUFACT&0xff))
61                 panic ("\nbad manufacturer's code (0x%08lx) at addr 0x%08lx",
62                         (unsigned long)word, (unsigned long)base);
63
64         /* check the device id */
65         word = *BANK_REG_DEV_CODE (base);
66         switch (word) {
67
68         case BANK_FILL_WORD (INTEL_ID_28F320J5&0xff):
69                 fip->flash_id = FLASH_MAN_INTEL | FLASH_28F320J5;
70                 fip->sector_count = 32;
71                 break;
72
73         case BANK_FILL_WORD (INTEL_ID_28F640J5&0xff):
74                 fip->flash_id = FLASH_MAN_INTEL | FLASH_28F640J5;
75                 fip->sector_count = 64;
76                 break;
77
78         case BANK_FILL_WORD (INTEL_ID_28F320J3A&0xff):
79                 fip->flash_id = FLASH_MAN_INTEL | FLASH_28F320J3A;
80                 fip->sector_count = 32;
81                 break;
82
83         case BANK_FILL_WORD (INTEL_ID_28F640J3A&0xff):
84                 fip->flash_id = FLASH_MAN_INTEL | FLASH_28F640J3A;
85                 fip->sector_count = 64;
86                 break;
87
88         case BANK_FILL_WORD (INTEL_ID_28F128J3A&0xff):
89                 fip->flash_id = FLASH_MAN_INTEL | FLASH_28F128J3A;
90                 fip->sector_count = 128;
91                 break;
92
93         default:
94                 panic ("\nbad device code (0x%08lx) at addr 0x%08lx",
95                         (unsigned long)word, (unsigned long)base);
96         }
97
98         if (fip->sector_count >= CFG_MAX_FLASH_SECT)
99                 panic ("\ntoo many sectors (%d) in flash at address 0x%08lx",
100                         fip->sector_count, (unsigned long)base);
101
102         addr = base;
103         for (i = 0; i < fip->sector_count; i++) {
104                 fip->start[i] = (unsigned long)addr;
105                 fip->protect[i] = 0;
106                 addr = BANK_ADDR_NEXT_BLK (addr);
107         }
108
109         fip->size = (bank_size_t)addr - (bank_size_t)base;
110
111         /* reset the flash */
112         *base = BANK_CMD_RST;
113 }
114
115 static void
116 bank_reset (flash_info_t *info, int sect)
117 {
118         volatile bank_addr_t addr = (bank_addr_t)info->start[sect];
119
120 #ifdef FLASH_DEBUG
121         printf ("writing reset cmd to addr 0x%08lx\n", (unsigned long)addr);
122 #endif
123
124         *addr = BANK_CMD_RST;
125 }
126
127 static void
128 bank_erase_init (flash_info_t *info, int sect)
129 {
130         volatile bank_addr_t addr = (bank_addr_t)info->start[sect];
131         int flag;
132
133 #ifdef FLASH_DEBUG
134         printf ("erasing sector %d, addr = 0x%08lx\n",
135                 sect, (unsigned long)addr);
136 #endif
137
138         /* Disable intrs which might cause a timeout here */
139         flag = disable_interrupts ();
140
141 #ifdef FLASH_DEBUG
142         printf ("writing erase cmd to addr 0x%08lx\n", (unsigned long)addr);
143 #endif
144         *addr = BANK_CMD_ERASE1;
145         *addr = BANK_CMD_ERASE2;
146
147         /* re-enable interrupts if necessary */
148         if (flag)
149                 enable_interrupts ();
150 }
151
152 static int
153 bank_erase_poll (flash_info_t *info, int sect)
154 {
155         volatile bank_addr_t addr = (bank_addr_t)info->start[sect];
156         bank_word_t stat = *addr;
157
158 #ifdef FLASH_DEBUG
159         printf ("checking status at addr 0x%08lx [0x%08lx]\n",
160                 (unsigned long)addr, (unsigned long)stat);
161 #endif
162
163         if ((stat & BANK_STAT_RDY) == BANK_STAT_RDY) {
164                 if ((stat & BANK_STAT_ERR) != 0) {
165                         printf ("failed on sector %d [0x%08lx] at "
166                                 "address 0x%08lx\n", sect,
167                                 (unsigned long)stat, (unsigned long)addr);
168                         *addr = BANK_CMD_CLR_STAT;
169                         return (-1);
170                 }
171                 else
172                         return (1);
173         }
174         else
175                 return (0);
176 }
177
178 static int
179 bank_write_word (volatile bank_addr_t addr, bank_word_t value)
180 {
181         bank_word_t stat;
182         ulong start;
183         int flag, retval;
184
185         /* Disable interrupts which might cause a timeout here */
186         flag = disable_interrupts ();
187
188         *addr = BANK_CMD_PROG;
189
190         *addr = value;
191
192         /* re-enable interrupts if necessary */
193         if (flag)
194                 enable_interrupts ();
195
196         retval = 0;
197
198         /* data polling for D7 */
199         start = get_timer (0);
200         do {
201                 if (get_timer (start) > CFG_FLASH_WRITE_TOUT) {
202                         retval = 1;
203                         goto done;
204                 }
205                 stat = *addr;
206         } while ((stat & BANK_STAT_RDY) != BANK_STAT_RDY);
207
208         if ((stat & BANK_STAT_ERR) != 0) {
209                 printf ("flash program failed [0x%08lx] at address 0x%08lx\n",
210                         (unsigned long)stat, (unsigned long)addr);
211                 *addr = BANK_CMD_CLR_STAT;
212                 retval = 3;
213         }
214
215 done:
216         /* reset to read mode */
217         *addr = BANK_CMD_RST;
218
219         return (retval);
220 }
221
222 /*-----------------------------------------------------------------------
223  */
224
225 unsigned long
226 flash_init (void)
227 {
228         int i;
229
230         /* Init: no FLASHes known */
231         for (i=0; i<CFG_MAX_FLASH_BANKS; ++i) {
232                 flash_info[i].flash_id = FLASH_UNKNOWN;
233         }
234
235         bank_probe (&flash_info[0], (bank_addr_t)CFG_FLASH_BASE);
236
237         /*
238          * protect monitor and environment sectors
239          */
240
241 #if CFG_MONITOR_BASE == CFG_FLASH_BASE
242         (void)flash_protect (FLAG_PROTECT_SET,
243                       CFG_MONITOR_BASE,
244                       CFG_MONITOR_BASE+monitor_flash_len-1,
245                       &flash_info[0]);
246 #endif
247
248 #if defined(CFG_FLASH_ENV_ADDR)
249         (void)flash_protect (FLAG_PROTECT_SET,
250                       CFG_FLASH_ENV_ADDR,
251 #if defined(CFG_FLASH_ENV_BUF)
252                       CFG_FLASH_ENV_ADDR + CFG_FLASH_ENV_BUF - 1,
253 #else
254                       CFG_FLASH_ENV_ADDR + CFG_FLASH_ENV_SIZE - 1,
255 #endif
256                       &flash_info[0]);
257 #endif
258
259         return flash_info[0].size;
260 }
261
262 /*-----------------------------------------------------------------------
263  */
264 void
265 flash_print_info (flash_info_t *info)
266 {
267         int i;
268
269         if (info->flash_id == FLASH_UNKNOWN) {
270                 printf ("missing or unknown FLASH type\n");
271                 return;
272         }
273
274         switch (info->flash_id & FLASH_VENDMASK) {
275         case FLASH_MAN_INTEL:   printf ("INTEL ");              break;
276         default:                printf ("Unknown Vendor ");     break;
277         }
278
279         switch (info->flash_id & FLASH_TYPEMASK) {
280         case FLASH_28F320J5:    printf ("28F320J5 (32 Mbit, 2 x 16bit)\n");
281                                 break;
282         case FLASH_28F640J5:    printf ("28F640J5 (64 Mbit, 2 x 16bit)\n");
283                                 break;
284         case FLASH_28F320J3A:   printf ("28F320J3A (32 Mbit, 2 x 16bit)\n");
285                                 break;
286         case FLASH_28F640J3A:   printf ("28F640J3A (64 Mbit, 2 x 16bit)\n");
287                                 break;
288         case FLASH_28F128J3A:   printf ("28F320J3A (128 Mbit, 2 x 16bit)\n");
289                                 break;
290         default:                printf ("Unknown Chip Type\n");
291                                 break;
292         }
293
294         printf ("  Size: %ld MB in %d Sectors\n",
295                 info->size >> 20, info->sector_count);
296
297         printf ("  Sector Start Addresses:");
298         for (i=0; i<info->sector_count; ++i) {
299                 if ((i % 5) == 0)
300                         printf ("\n   ");
301                 printf (" %08lX%s",
302                         info->start[i],
303                         info->protect[i] ? " (RO)" : "     "
304                 );
305         }
306         printf ("\n");
307         return;
308 }
309
310 /*
311  * The following code cannot be run from FLASH!
312  */
313
314 /*-----------------------------------------------------------------------
315  */
316
317 int
318 flash_erase (flash_info_t *info, int s_first, int s_last)
319 {
320         int prot, sect, haderr;
321         ulong start, now, last;
322         int rcode = 0;
323
324 #ifdef FLASH_DEBUG
325         printf ("\nflash_erase: erase %d sectors (%d to %d incl.) from\n"
326                 "  Bank # %d: ", s_last - s_first + 1, s_first, s_last,
327                 (info - flash_info) + 1);
328         flash_print_info (info);
329 #endif
330
331         if ((s_first < 0) || (s_first > s_last)) {
332                 if (info->flash_id == FLASH_UNKNOWN) {
333                         printf ("- missing\n");
334                 } else {
335                         printf ("- no sectors to erase\n");
336                 }
337                 return 1;
338         }
339
340         prot = 0;
341         for (sect = s_first; sect <= s_last; ++sect) {
342                 if (info->protect[sect]) {
343                         prot++;
344                 }
345         }
346
347         if (prot) {
348                 printf ("- Warning: %d protected sector%s will not be erased\n",
349                         prot, (prot > 1 ? "s" : ""));
350         }
351
352         start = get_timer (0);
353         last = 0;
354         haderr = 0;
355
356         for (sect = s_first; sect <= s_last; sect++) {
357                 if (info->protect[sect] == 0) { /* not protected */
358                         ulong estart;
359                         int sectdone;
360
361                         bank_erase_init (info, sect);
362
363                         /* wait at least 80us - let's wait 1 ms */
364                         udelay (1000);
365
366                         estart = get_timer (start);
367
368                         do {
369                                 now = get_timer (start);
370
371                                 if (now - estart > CFG_FLASH_ERASE_TOUT) {
372                                         printf ("Timeout (sect %d)\n", sect);
373                                         haderr = 1;
374                                         rcode = 1;
375                                         break;
376                                 }
377
378 #ifndef FLASH_DEBUG
379                                 /* show that we're waiting */
380                                 if ((now - last) > 1000) { /* every second */
381                                         putc ('.');
382                                         last = now;
383                                 }
384 #endif
385
386                                 sectdone = bank_erase_poll (info, sect);
387
388                                 if (sectdone < 0) {
389                                         haderr = 1;
390                                         rcode = 1;
391                                         break;
392                                 }
393
394                         } while (!sectdone);
395
396                         if (haderr)
397                                 break;
398                 }
399         }
400
401         if (haderr > 0)
402                 printf (" failed\n");
403         else
404                 printf (" done\n");
405
406         /* reset to read mode */
407         for (sect = s_first; sect <= s_last; sect++) {
408                 if (info->protect[sect] == 0) { /* not protected */
409                         bank_reset (info, sect);
410                 }
411         }
412         return rcode;
413 }
414
415 /*-----------------------------------------------------------------------
416  * Write a word to Flash, returns:
417  * 0 - OK
418  * 1 - write timeout
419  * 2 - Flash not erased
420  * 3 - Program failed
421  */
422 static int
423 write_word (flash_info_t *info, ulong dest, ulong data)
424 {
425         /* Check if Flash is (sufficiently) erased */
426         if ((*(ulong *)dest & data) != data)
427                 return (2);
428
429         return (bank_write_word ((bank_addr_t)dest, (bank_word_t)data));
430 }
431
432 /*-----------------------------------------------------------------------
433  * Copy memory to flash, returns:
434  * 0 - OK
435  * 1 - write timeout
436  * 2 - Flash not erased
437  * 3 - Program failed
438  */
439
440 int
441 write_buff (flash_info_t *info, uchar *src, ulong addr, ulong cnt)
442 {
443         ulong cp, wp, data;
444         int i, l, rc;
445
446         wp = (addr & ~3);       /* get lower word aligned address */
447
448         /*
449          * handle unaligned start bytes
450          */
451         if ((l = addr - wp) != 0) {
452                 data = 0;
453                 for (i=0, cp=wp; i<l; ++i, ++cp) {
454                         data = (data << 8) | (*(uchar *)cp);
455                 }
456                 for (; i<4 && cnt>0; ++i) {
457                         data = (data << 8) | *src++;
458                         --cnt;
459                         ++cp;
460                 }
461                 for (; cnt==0 && i<4; ++i, ++cp) {
462                         data = (data << 8) | (*(uchar *)cp);
463                 }
464
465                 if ((rc = write_word (info, wp, data)) != 0) {
466                         return (rc);
467                 }
468                 wp += 4;
469         }
470
471         /*
472          * handle word aligned part
473          */
474         while (cnt >= 4) {
475                 data = 0;
476                 for (i=0; i<4; ++i) {
477                         data = (data << 8) | *src++;
478                 }
479                 if ((rc = write_word (info, wp, data)) != 0) {
480                         return (rc);
481                 }
482                 wp  += 4;
483                 cnt -= 4;
484         }
485
486         if (cnt == 0) {
487                 return (0);
488         }
489
490         /*
491          * handle unaligned tail bytes
492          */
493         data = 0;
494         for (i=0, cp=wp; i<4 && cnt>0; ++i, ++cp) {
495                 data = (data << 8) | *src++;
496                 --cnt;
497         }
498         for (; i<4; ++i, ++cp) {
499                 data = (data << 8) | (*(uchar *)cp);
500         }
501
502         return (write_word (info, wp, data));
503 }
504
505 /*-----------------------------------------------------------------------
506  */