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