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