]> git.karo-electronics.de Git - karo-tx-uboot.git/blob - board/innokom/flash.c
* Patch by Arun Dharankar, 4 Apr 2003:
[karo-tx-uboot.git] / board / innokom / flash.c
1 /*
2  * (C) Copyright 2002
3  * Kyle Harris, Nexus Technologies, Inc. kharris@nexus-tech.net
4  *
5  * (C) Copyright 2002
6  * Sysgo Real-Time Solutions, GmbH <www.elinos.com>
7  * Marius Groeger <mgroeger@sysgo.de>
8  *
9  * (C) Copyright 2002
10  * Robert Schwebel, Pengutronix, <r.schwebel@pengutronix.de>
11  *
12  * (C) Copyright 2002
13  * Auerswald GmbH & Co KG, Germany 
14  * Kai-Uwe Bloem <kai-uwe.bloem@auerswald.de>
15  *
16  * See file CREDITS for list of people who contributed to this
17  * project.
18  *
19  * This program is free software; you can redistribute it and/or
20  * modify it under the terms of the GNU General Public License as
21  * published by the Free Software Foundation; either version 2 of
22  * the License, or (at your option) any later version.
23  *
24  * This program is distributed in the hope that it will be useful,
25  * but WITHOUT ANY WARRANTY; without even the implied warranty of
26  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
27  * GNU General Public License for more details.
28  *
29  * You should have received a copy of the GNU General Public License
30  * along with this program; if not, write to the Free Software
31  * Foundation, Inc., 59 Temple Place, Suite 330, Boston,
32  * MA 02111-1307 USA
33  */
34
35 #include <common.h>
36 #include <asm/arch/pxa-regs.h>
37
38 #if defined CFG_JFFS_CUSTOM_PART
39 #include <jffs2/jffs2.h>
40 #endif
41
42 /* Debugging macros ------------------------------------------------------  */
43
44 #undef FLASH_DEBUG
45 //#define FLASH_DEBUG 1
46
47 /* Some debug macros */
48 #if (FLASH_DEBUG > 2 )
49 #define PRINTK3(args...) printf(args)
50 #else
51 #define PRINTK3(args...)
52 #endif
53
54 #if FLASH_DEBUG > 1
55 #define PRINTK2(args...) printf(args)
56 #else
57 #define PRINTK2(args...)
58 #endif
59
60 #ifdef FLASH_DEBUG
61 #define PRINTK(args...) printf(args)
62 #else
63 #define PRINTK(args...)
64 #endif
65
66 /* ------------------------------------------------------------------------ */
67
68 /* Development system: we have only 16 MB Flash                             */
69 #ifdef CONFIG_MTD_INNOKOM_16MB
70 #define FLASH_BANK_SIZE 0x01000000      /* 16 MB (during development)       */
71 #define MAIN_SECT_SIZE  0x00020000      /* 128k per sector                  */
72 #endif
73
74 /* Production system: we have 64 MB Flash                                   */
75 #ifdef CONFIG_MTD_INNOKOM_64MB
76 #define FLASH_BANK_SIZE 0x04000000      /* 64 MB                            */
77 #define MAIN_SECT_SIZE  0x00020000      /* 128k per sector                  */
78 #endif
79
80 flash_info_t    flash_info[CFG_MAX_FLASH_BANKS];
81
82
83 #if defined CFG_JFFS_CUSTOM_PART
84
85 /**
86  * jffs2_part_info - get information about a JFFS2 partition
87  *
88  * @part_num: number of the partition you want to get info about
89  * @return:   struct part_info* in case of success, 0 if failure
90  */
91
92 static struct part_info part;
93 static int current_part = -1;
94
95 #ifdef CONFIG_MTD_INNOKOM_16MB
96 #ifdef CONFIG_MTD_INNOKOM_64MB
97 #error Please define only one CONFIG_MTD_INNOKOM_XXMB option.
98 #endif
99 struct part_info* jffs2_part_info(int part_num) {
100         void *jffs2_priv_saved = part.jffs2_priv;
101
102         PRINTK2("jffs2_part_info: part_num=%i\n",part_num);
103
104         if (current_part == part_num)
105                 return &part;
106
107         /* u-boot partition                                                 */
108         if(part_num==0){
109                 memset(&part, 0, sizeof(part));
110                 
111                 part.offset=(char*)0x00000000;
112                 part.size=256*1024;
113                 
114                 /* Mark the struct as ready */
115                 current_part = part_num;
116
117                 PRINTK("part.offset = 0x%08x\n",(unsigned int)part.offset);
118                 PRINTK("part.size   = 0x%08x\n",(unsigned int)part.size);
119         }
120
121         /* primary OS+firmware partition                                    */
122         if(part_num==1){
123                 memset(&part, 0, sizeof(part));
124                 
125                 part.offset=(char*)0x00040000;
126                 part.size=768*1024;
127                 
128                 /* Mark the struct as ready */
129                 current_part = part_num;
130
131                 PRINTK("part.offset = 0x%08x\n",(unsigned int)part.offset);
132                 PRINTK("part.size   = 0x%08x\n",(unsigned int)part.size);
133         }
134         
135         /* secondary OS+firmware partition                                  */
136         if(part_num==2){
137                 memset(&part, 0, sizeof(part));
138                 
139                 part.offset=(char*)0x00100000;
140                 part.size=8*1024*1024;
141                 
142                 /* Mark the struct as ready */
143                 current_part = part_num;
144
145                 PRINTK("part.offset = 0x%08x\n",(unsigned int)part.offset);
146                 PRINTK("part.size   = 0x%08x\n",(unsigned int)part.size);
147         }
148
149         /* data partition */
150         if(part_num==3){
151                 memset(&part, 0, sizeof(part));
152                 
153                 part.offset=(char*)0x00900000;
154                 part.size=7*1024*1024;
155                 
156                 /* Mark the struct as ready */
157                 current_part = part_num;
158
159                 PRINTK("part.offset = 0x%08x\n",(unsigned int)part.offset);
160                 PRINTK("part.size   = 0x%08x\n",(unsigned int)part.size);
161         }
162         
163         if (current_part == part_num) {
164                 part.usr_priv = &current_part;
165                 part.jffs2_priv = jffs2_priv_saved;
166                 return &part;
167         }
168
169         PRINTK("jffs2_part_info: end of partition table\n");
170         return 0;
171 }
172 #endif /* CONFIG_MTD_INNOKOM_16MB */
173
174 #ifdef CONFIG_MTD_INNOKOM_64MB
175 #ifdef CONFIG_MTD_INNOKOM_16MB
176 #error Please define only one CONFIG_MTD_INNOKOM_XXMB option.
177 #endif
178 struct part_info* jffs2_part_info(int part_num) {
179         void *jffs2_priv_saved = part.jffs2_priv;
180
181         PRINTK2("jffs2_part_info: part_num=%i\n",part_num);
182
183         if (current_part == part_num)
184                 return &part;
185
186         /* u-boot partition                                                 */
187         if(part_num==0){
188                 memset(&part, 0, sizeof(part));
189                 
190                 part.offset=(char*)0x00000000;
191                 part.size=256*1024;
192                 
193                 /* Mark the struct as ready */
194                 current_part = part_num;
195
196                 PRINTK("part.offset = 0x%08x\n",(unsigned int)part.offset);
197                 PRINTK("part.size   = 0x%08x\n",(unsigned int)part.size);
198         }
199
200         /* primary OS+firmware partition                                    */
201         if(part_num==1){
202                 memset(&part, 0, sizeof(part));
203                 
204                 part.offset=(char*)0x00040000;
205                 part.size=16*1024*1024-128*1024;
206                 
207                 /* Mark the struct as ready */
208                 current_part = part_num;
209
210                 PRINTK("part.offset = 0x%08x\n",(unsigned int)part.offset);
211                 PRINTK("part.size   = 0x%08x\n",(unsigned int)part.size);
212         }
213         
214         /* secondary OS+firmware partition                                  */
215         if(part_num==2){
216                 memset(&part, 0, sizeof(part));
217                 
218                 part.offset=(char*)0x01020000;
219                 part.size=16*1024*1024-128*1024;
220                 
221                 /* Mark the struct as ready */
222                 current_part = part_num;
223
224                 PRINTK("part.offset = 0x%08x\n",(unsigned int)part.offset);
225                 PRINTK("part.size   = 0x%08x\n",(unsigned int)part.size);
226         }
227
228         /* data partition */
229         if(part_num==3){
230                 memset(&part, 0, sizeof(part));
231                 
232                 part.offset=(char*)0x02000000;
233                 part.size=32*1024*1024;
234                 
235                 /* Mark the struct as ready */
236                 current_part = part_num;
237
238                 PRINTK("part.offset = 0x%08x\n",(unsigned int)part.offset);
239                 PRINTK("part.size   = 0x%08x\n",(unsigned int)part.size);
240         }
241         
242         if (current_part == part_num) {
243                 part.usr_priv = &current_part;
244                 part.jffs2_priv = jffs2_priv_saved;
245                 return &part;
246         }
247
248         PRINTK("jffs2_part_info: end of partition table\n");
249         return 0;
250 }
251 #endif /* CONFIG_MTD_INNOKOM_64MB */
252 #endif /* defined CFG_JFFS_CUSTOM_PART */
253
254
255 /**
256  * flash_init: - initialize data structures for flash chips
257  *
258  * @return: size of the flash
259  */
260
261 ulong flash_init(void)
262 {
263         int i, j;
264         ulong size = 0;
265
266         for (i = 0; i < CFG_MAX_FLASH_BANKS; i++) {
267                 ulong flashbase = 0;
268                 flash_info[i].flash_id =
269                         (INTEL_MANUFACT & FLASH_VENDMASK) |
270                         (INTEL_ID_28F128J3 & FLASH_TYPEMASK);
271                 flash_info[i].size = FLASH_BANK_SIZE;
272                 flash_info[i].sector_count = CFG_MAX_FLASH_SECT;
273                 memset(flash_info[i].protect, 0, CFG_MAX_FLASH_SECT);
274
275                 switch (i) {
276                         case 0:
277                                 flashbase = PHYS_FLASH_1;
278                                 break;
279                         default:
280                                 panic("configured to many flash banks!\n");
281                                 break;
282                 }
283                 for (j = 0; j < flash_info[i].sector_count; j++) {
284                         flash_info[i].start[j] = flashbase + j*MAIN_SECT_SIZE;
285                 }
286                 size += flash_info[i].size;
287         }
288
289         /* Protect u-boot sectors */
290         flash_protect(FLAG_PROTECT_SET,
291                         CFG_FLASH_BASE,
292                         CFG_FLASH_BASE + (256*1024) - 1,
293                         &flash_info[0]);
294
295 #ifdef CFG_ENV_IS_IN_FLASH
296         flash_protect(FLAG_PROTECT_SET,
297                         CFG_ENV_ADDR,
298                         CFG_ENV_ADDR + CFG_ENV_SIZE - 1,
299                         &flash_info[0]);
300 #endif
301
302         return size;
303 }
304
305
306 /**
307  * flash_print_info: - print information about the flash situation
308  *
309  * @param info:
310  */
311
312 void flash_print_info  (flash_info_t *info)
313 {
314         int i, j;
315
316         for (j=0; j<CFG_MAX_FLASH_BANKS; j++) {
317
318                 switch (info->flash_id & FLASH_VENDMASK) {
319
320                         case (INTEL_MANUFACT & FLASH_VENDMASK):
321                                 printf("Intel: ");
322                                 break;
323                         default:
324                                 printf("Unknown Vendor ");
325                                 break;
326                 }
327
328                 switch (info->flash_id & FLASH_TYPEMASK) {
329
330                         case (INTEL_ID_28F128J3 & FLASH_TYPEMASK):
331                                 printf("28F128J3 (128Mbit)\n");
332                                 break;
333                         default:
334                                 printf("Unknown Chip Type\n");
335                                 return;
336                 }
337
338                 printf("  Size: %ld MB in %d Sectors\n", 
339                         info->size >> 20, info->sector_count);
340
341                 printf("  Sector Start Addresses:");
342                 for (i = 0; i < info->sector_count; i++) {
343                         if ((i % 5) == 0) printf ("\n   ");
344                 
345                         printf (" %08lX%s", info->start[i],
346                                 info->protect[i] ? " (RO)" : "     ");
347                 }
348                 printf ("\n");
349                 info++;
350         }
351 }
352
353
354 /**
355  * flash_erase: - erase flash sectors
356  *
357  */
358
359 int flash_erase(flash_info_t *info, int s_first, int s_last)
360 {
361         int flag, prot, sect;
362         int rc = ERR_OK;
363
364         if (info->flash_id == FLASH_UNKNOWN)
365                 return ERR_UNKNOWN_FLASH_TYPE;
366
367         if ((s_first < 0) || (s_first > s_last)) {
368                 return ERR_INVAL;
369         }
370
371         if ((info->flash_id & FLASH_VENDMASK) != (INTEL_MANUFACT & FLASH_VENDMASK))
372                 return ERR_UNKNOWN_FLASH_VENDOR;
373         
374         prot = 0;
375         for (sect=s_first; sect<=s_last; ++sect) {
376                 if (info->protect[sect]) prot++;
377         }
378
379         if (prot) return ERR_PROTECTED;
380
381         /*
382          * Disable interrupts which might cause a timeout
383          * here. Remember that our exception vectors are
384          * at address 0 in the flash, and we don't want a
385          * (ticker) exception to happen while the flash
386          * chip is in programming mode.
387          */
388
389         flag = disable_interrupts();
390
391         /* Start erase on unprotected sectors */
392         for (sect = s_first; sect<=s_last && !ctrlc(); sect++) {
393
394                 printf("Erasing sector %2d ... ", sect);
395
396                 PRINTK("\n");
397
398                 /* arm simple, non interrupt dependent timer */
399                 reset_timer_masked();
400
401                 if (info->protect[sect] == 0) { /* not protected */
402                         u16 * volatile addr = (u16 * volatile)(info->start[sect]);
403
404                         PRINTK("unlocking sector\n");
405                         *addr = 0x0060;
406                         *addr = 0x00d0;
407                         *addr = 0x00ff;
408
409                         PRINTK("erasing sector\n");
410                         *addr = 0x0020;
411                         PRINTK("confirming erase\n");
412                         *addr = 0x00D0;
413
414                         while ((*addr & 0x0080) != 0x0080) {
415                                 PRINTK(".");
416                                 if (get_timer_masked() > CFG_FLASH_ERASE_TOUT) {
417                                         *addr = 0x00B0; /* suspend erase*/
418                                         *addr = 0x00FF; /* read mode    */
419                                         rc = ERR_TIMOUT;
420                                         goto outahere;
421                                 }
422                         }
423                         
424                         PRINTK("clearing status register\n");
425                         *addr = 0x0050; 
426                         PRINTK("resetting to read mode");
427                         *addr = 0x00FF; 
428                 }
429                 
430                 printf("ok.\n");
431         }
432
433         if (ctrlc()) printf("User Interrupt!\n");
434
435         outahere:
436
437         /* allow flash to settle - wait 10 ms */
438         udelay_masked(10000);
439
440         if (flag) enable_interrupts();
441
442         return rc;
443 }
444
445
446 /**
447  * write_word: - copy memory to flash
448  *
449  * @param info:
450  * @param dest:
451  * @param data:
452  * @return:
453  */
454
455 static int write_word (flash_info_t *info, ulong dest, ushort data)
456 {
457         volatile u16 *addr = (u16 *)dest, val;
458         int rc = ERR_OK;
459         int flag;
460
461         /* Check if Flash is (sufficiently) erased */
462         if ((*addr & data) != data) return ERR_NOT_ERASED;
463
464         /*
465          * Disable interrupts which might cause a timeout
466          * here. Remember that our exception vectors are
467          * at address 0 in the flash, and we don't want a
468          * (ticker) exception to happen while the flash
469          * chip is in programming mode.
470          */
471         flag = disable_interrupts();
472
473         /* clear status register command */
474         *addr = 0x50;
475
476         /* program set-up command */
477         *addr = 0x40;
478
479         /* latch address/data */
480         *addr = data;
481
482         /* arm simple, non interrupt dependent timer */
483         reset_timer_masked();
484
485         /* wait while polling the status register */
486         while(((val = *addr) & 0x80) != 0x80) {
487                 if (get_timer_masked() > CFG_FLASH_WRITE_TOUT) {
488                         rc = ERR_TIMOUT;
489                         *addr = 0xB0; /* suspend program command */
490                         goto outahere;
491                 }
492         }
493
494         if(val & 0x1A) {        /* check for error */
495                 printf("\nFlash write error %02x at address %08lx\n",
496                         (int)val, (unsigned long)dest);
497                 if(val & (1<<3)) {
498                         printf("Voltage range error.\n");
499                         rc = ERR_PROG_ERROR;
500                         goto outahere;
501                 }
502                 if(val & (1<<1)) {
503                         printf("Device protect error.\n");
504                         rc = ERR_PROTECTED;
505                         goto outahere;
506                 }
507                 if(val & (1<<4)) {
508                         printf("Programming error.\n");
509                         rc = ERR_PROG_ERROR;
510                         goto outahere;
511                 }
512                 rc = ERR_PROG_ERROR;
513                 goto outahere;
514         }
515
516         outahere:
517
518         *addr = 0xFF; /* read array command */
519         if (flag) enable_interrupts();
520
521         return rc;
522 }
523
524
525 /**
526  * write_buf: - Copy memory to flash.
527  *
528  * @param info:
529  * @param src:  source of copy transaction
530  * @param addr: where to copy to
531  * @param cnt:  number of bytes to copy
532  *
533  * @return      error code
534  */
535
536 int write_buff (flash_info_t *info, uchar *src, ulong addr, ulong cnt)
537 {
538         ulong cp, wp;
539         ushort data;
540         int l;
541         int i, rc;
542
543         wp = (addr & ~1);       /* get lower word aligned address */
544
545         /*
546          * handle unaligned start bytes
547          */
548         if ((l = addr - wp) != 0) {
549                 data = 0;
550                 for (i=0, cp=wp; i<l; ++i, ++cp) {
551                         data = (data >> 8) | (*(uchar *)cp << 8);
552                 }
553                 for (; i<2 && cnt>0; ++i) {
554                         data = (data >> 8) | (*src++ << 8);
555                         --cnt;
556                         ++cp;
557                 }
558                 for (; cnt==0 && i<2; ++i, ++cp) {
559                         data = (data >> 8) | (*(uchar *)cp << 8);
560                 }
561
562                 if ((rc = write_word(info, wp, data)) != 0) {
563                         return (rc);
564                 }
565                 wp += 2;
566         }
567
568         /*
569          * handle word aligned part
570          */
571         while (cnt >= 2) {
572                 /* data = *((vushort*)src); */
573                 data = *((ushort*)src);
574                 if ((rc = write_word(info, wp, data)) != 0) {
575                         return (rc);
576                 }
577                 src += 2;
578                 wp  += 2;
579                 cnt -= 2;
580         }
581
582         if (cnt == 0) return ERR_OK;
583
584         /*
585          * handle unaligned tail bytes
586          */
587         data = 0;
588         for (i=0, cp=wp; i<2 && cnt>0; ++i, ++cp) {
589                 data = (data >> 8) | (*src++ << 8);
590                 --cnt;
591         }
592         for (; i<2; ++i, ++cp) {
593                 data = (data >> 8) | (*(uchar *)cp << 8);
594         }
595
596         return write_word(info, wp, data);
597 }
598