]> git.kernelconcepts.de Git - karo-tx-uboot.git/blob - board/stxgp3/flash.c
imported Freescale specific U-Boot additions for i.MX28,... release L2.6.31_10.08.01
[karo-tx-uboot.git] / board / stxgp3 / flash.c
1 /*
2  * (C) Copyright 2003, Dan Malek, Embedded Edge, LLC.  <dan@embeddededge.com>
3  * Copied from ADS85xx.
4  * Updated to support the Silicon Tx GP3 8560.  We should only find
5  * two Intel 28F640 parts in 16-bit mode (i.e. 32-bit wide flash),
6  * but I left other code here in case people order custom boards.
7  *
8  * (C) Copyright 2003 Motorola Inc.
9  *  Xianghua Xiao,(X.Xiao@motorola.com)
10  *
11  * (C) Copyright 2000, 2001
12  *  Wolfgang Denk, DENX Software Engineering, wd@denx.de.
13  *
14  * (C) Copyright 2001, Stuart Hughes, Lineo Inc, stuarth@lineo.com
15  * Add support the Sharp chips on the mpc8260ads.
16  * I started with board/ip860/flash.c and made changes I found in
17  * the MTD project by David Schleef.
18  *
19  * See file CREDITS for list of people who contributed to this
20  * project.
21  *
22  * This program is free software; you can redistribute it and/or
23  * modify it under the terms of the GNU General Public License as
24  * published by the Free Software Foundation; either version 2 of
25  * the License, or (at your option) any later version.
26  *
27  * This program is distributed in the hope that it will be useful,
28  * but WITHOUT ANY WARRANTY; without even the implied warranty of
29  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
30  * GNU General Public License for more details.
31  *
32  * You should have received a copy of the GNU General Public License
33  * along with this program; if not, write to the Free Software
34  * Foundation, Inc., 59 Temple Place, Suite 330, Boston,
35  * MA 02111-1307 USA
36  */
37
38 #include <common.h>
39
40 #if !defined(CONFIG_SYS_NO_FLASH)
41
42 flash_info_t    flash_info[CONFIG_SYS_MAX_FLASH_BANKS]; /* info for FLASH chips */
43
44 #if defined(CONFIG_ENV_IS_IN_FLASH)
45 # ifndef  CONFIG_ENV_ADDR
46 #  define CONFIG_ENV_ADDR       (CONFIG_SYS_FLASH_BASE + CONFIG_ENV_OFFSET)
47 # endif
48 # ifndef  CONFIG_ENV_SIZE
49 #  define CONFIG_ENV_SIZE       CONFIG_ENV_SECT_SIZE
50 # endif
51 # ifndef  CONFIG_ENV_SECT_SIZE
52 #  define CONFIG_ENV_SECT_SIZE  CONFIG_ENV_SIZE
53 # endif
54 #endif
55
56 #undef DEBUG
57
58 /*-----------------------------------------------------------------------
59  * Functions
60  */
61 static ulong flash_get_size (vu_long *addr, flash_info_t *info);
62 static int write_word (flash_info_t *info, ulong dest, ulong data);
63 static int clear_block_lock_bit(vu_long * addr);
64 /*-----------------------------------------------------------------------
65  */
66
67 unsigned long flash_init (void)
68 {
69         unsigned long size;
70         int i;
71
72         /* Init: enable write,
73          * or we cannot even write flash commands
74          */
75         for (i=0; i<CONFIG_SYS_MAX_FLASH_BANKS; ++i) {
76                 flash_info[i].flash_id = FLASH_UNKNOWN;
77
78                 /* set the default sector offset */
79         }
80
81         /* Static FLASH Bank configuration here - FIXME XXX */
82
83         size = flash_get_size((vu_long *)CONFIG_SYS_FLASH_BASE, &flash_info[0]);
84
85         if (flash_info[0].flash_id == FLASH_UNKNOWN) {
86                 printf ("## Unknown FLASH on Bank 0 - Size = 0x%08lx = %ld MB\n",
87                         size, size<<20);
88         }
89
90         /* Re-do sizing to get full correct info */
91         size = flash_get_size((vu_long *)CONFIG_SYS_FLASH_BASE, &flash_info[0]);
92
93         flash_info[0].size = size;
94
95 #if CONFIG_SYS_MONITOR_BASE >= CONFIG_SYS_FLASH_BASE
96         /* monitor protection ON by default */
97         flash_protect(FLAG_PROTECT_SET,
98                       CONFIG_SYS_MONITOR_BASE,
99                       CONFIG_SYS_MONITOR_BASE+monitor_flash_len-1,
100                       &flash_info[0]);
101
102 #ifdef  CONFIG_ENV_IS_IN_FLASH
103         /* ENV protection ON by default */
104         flash_protect(FLAG_PROTECT_SET,
105                       CONFIG_ENV_ADDR,
106                       CONFIG_ENV_ADDR+CONFIG_ENV_SECT_SIZE-1,
107                       &flash_info[0]);
108 #endif
109 #endif
110         return (size);
111 }
112
113 /*-----------------------------------------------------------------------
114  */
115 void flash_print_info  (flash_info_t *info)
116 {
117         int i;
118
119         if (info->flash_id == FLASH_UNKNOWN) {
120                 printf ("missing or unknown FLASH type\n");
121                 return;
122         }
123
124         switch (info->flash_id & FLASH_VENDMASK) {
125         case FLASH_MAN_INTEL:   printf ("Intel ");              break;
126         case FLASH_MAN_SHARP:   printf ("Sharp ");              break;
127         default:                printf ("Unknown Vendor ");     break;
128         }
129
130         switch (info->flash_id & FLASH_TYPEMASK) {
131         case FLASH_28F640C3T:   printf ("28F640C3T (64 Mbit x 2, 128 x 128k)\n");
132                                 break;
133         default:                printf ("Unknown Chip Type\n");
134                                 break;
135         }
136
137         printf ("  Size: %ld MB in %d Sectors\n",
138                 info->size >> 20, info->sector_count);
139
140         printf ("  Sector Start Addresses:");
141         for (i=0; i<info->sector_count; ++i) {
142                 if ((i % 5) == 0)
143                         printf ("\n   ");
144                 printf (" %08lX%s",
145                         info->start[i],
146                         info->protect[i] ? " (RO)" : "     "
147                 );
148         }
149         printf ("\n");
150 }
151
152 /*
153  * The following code cannot be run from FLASH!
154  */
155
156 static ulong flash_get_size (vu_long *addr, flash_info_t *info)
157 {
158         short i;
159         ulong value;
160         ulong base = (ulong)addr;
161         ulong sector_offset;
162
163 #ifdef DEBUG
164         printf("Check flash at 0x%08x\n",(uint)addr);
165 #endif
166         /* Write "Intelligent Identifier" command: read Manufacturer ID */
167         *addr = 0x90909090;
168         udelay(20);
169         asm("sync");
170
171         value = addr[0] & 0x00FF00FF;
172
173 #ifdef DEBUG
174         printf("manufacturer=0x%x\n",(uint)value);
175 #endif
176         switch (value) {
177         case MT_MANUFACT:       /* SHARP, MT or => Intel */
178         case INTEL_ALT_MANU:
179                 info->flash_id = FLASH_MAN_INTEL;
180                 break;
181         default:
182                 printf("unknown manufacturer: %x\n", (unsigned int)value);
183                 info->flash_id = FLASH_UNKNOWN;
184                 info->sector_count = 0;
185                 info->size = 0;
186                 return (0);                     /* no or unknown flash  */
187         }
188
189         value = addr[1];             /* device ID            */
190
191 #ifdef DEBUG
192         printf("deviceID=0x%x\n",(uint)value);
193 #endif
194         switch (value) {
195
196         case (INTEL_ID_28F640C3T):
197                 info->flash_id += FLASH_28F640C3T;
198                 info->sector_count = 135;
199                 info->size = 0x01000000;
200                 sector_offset = 0x20000;
201                 break;                          /* => 2x8 MB            */
202
203         default:
204                 info->flash_id = FLASH_UNKNOWN;
205                 return (0);                     /* => no or unknown flash */
206
207         }
208
209         /* set up sector start address table
210          * The first 127 blocks are large, the last 8 are small.
211          */
212         for (i = 0; i < 127; i++) {
213                 info->start[i] = base;
214                 base += sector_offset;
215                 /* Sectors are locked upon reset */
216                 info->protect[i] = 0;
217         }
218         for (i = 127; i < 135; i++) {
219                 info->start[i] = base;
220                 base += 0x4000;
221                 /* Sectors are locked upon reset */
222                 info->protect[i] = 0;
223         }
224
225
226         /*
227          * Prevent writes to uninitialized FLASH.
228          */
229         if (info->flash_id != FLASH_UNKNOWN) {
230                 addr = (vu_long *)info->start[0];
231                 *addr = 0xFFFFFF;       /* reset bank to read array mode */
232                 asm("sync");
233         }
234
235         return (info->size);
236 }
237
238
239 /*-----------------------------------------------------------------------
240  */
241
242 int     flash_erase (flash_info_t *info, int s_first, int s_last)
243 {
244         int flag, prot, sect;
245         ulong start, now, last;
246
247         if ((s_first < 0) || (s_first > s_last)) {
248                 if (info->flash_id == FLASH_UNKNOWN) {
249                         printf ("- missing\n");
250                 } else {
251                         printf ("- no sectors to erase\n");
252                 }
253                 return 1;
254         }
255
256         if (    ((info->flash_id & FLASH_VENDMASK) != FLASH_MAN_INTEL)
257              && ((info->flash_id & FLASH_VENDMASK) != FLASH_MAN_SHARP) ) {
258                 printf ("Can't erase unknown flash type %08lx - aborted\n",
259                         info->flash_id);
260                 return 1;
261         }
262
263         prot = 0;
264         for (sect=s_first; sect<=s_last; ++sect) {
265                 if (info->protect[sect]) {
266                         prot++;
267                 }
268         }
269
270         if (prot) {
271                 printf ("- Warning: %d protected sectors will not be erased!\n",
272                         prot);
273         } else {
274                 printf ("\n");
275         }
276
277 #ifdef DEBUG
278         printf("\nFlash Erase:\n");
279 #endif
280         /* Make Sure Block Lock Bit is not set. */
281         if(clear_block_lock_bit((vu_long *)(info->start[s_first]))){
282                 return 1;
283         }
284
285         /* Start erase on unprotected sectors */
286 #if defined(DEBUG)
287         printf("Begin to erase now,s_first=0x%x s_last=0x%x...\n",s_first,s_last);
288 #endif
289         for (sect = s_first; sect<=s_last; sect++) {
290                 if (info->protect[sect] == 0) { /* not protected */
291                         vu_long *addr = (vu_long *)(info->start[sect]);
292                         asm("sync");
293
294                         last = start = get_timer (0);
295
296                         /* Disable interrupts which might cause a timeout here */
297                         flag = disable_interrupts();
298
299                         /* Reset Array */
300                         *addr = 0xffffffff;
301                         asm("sync");
302                         /* Clear Status Register */
303                         *addr = 0x50505050;
304                         asm("sync");
305                         /* Single Block Erase Command */
306                         *addr = 0x20202020;
307                         asm("sync");
308                         /* Confirm */
309                         *addr = 0xD0D0D0D0;
310                         asm("sync");
311
312                         if((info->flash_id & FLASH_TYPEMASK) != FLASH_LH28F016SCT) {
313                             /* Resume Command, as per errata update */
314                             *addr = 0xD0D0D0D0;
315                             asm("sync");
316                         }
317
318                         /* re-enable interrupts if necessary */
319                         if (flag)
320                                 enable_interrupts();
321
322                         /* wait at least 80us - let's wait 1 ms */
323                         udelay (1000);
324                         while ((*addr & 0x00800080) != 0x00800080) {
325                                 if(*addr & 0x00200020){
326                                         printf("Error in Block Erase - Lock Bit may be set!\n");
327                                         printf("Status Register = 0x%X\n", (uint)*addr);
328                                         *addr = 0xFFFFFFFF;     /* reset bank */
329                                         asm("sync");
330                                         return 1;
331                                 }
332                                 if ((now=get_timer(start)) > CONFIG_SYS_FLASH_ERASE_TOUT) {
333                                         printf ("Timeout\n");
334                                         *addr = 0xFFFFFFFF;     /* reset bank */
335                                         asm("sync");
336                                         return 1;
337                                 }
338                                 /* show that we're waiting */
339                                 if ((now - last) > 1000) {      /* every second */
340                                         putc ('.');
341                                         last = now;
342                                 }
343                         }
344
345                         /* reset to read mode */
346                         *addr = 0xFFFFFFFF;
347                         asm("sync");
348                 }
349         }
350
351         printf ("flash erase done\n");
352         return 0;
353 }
354
355 /*-----------------------------------------------------------------------
356  * Copy memory to flash, returns:
357  * 0 - OK
358  * 1 - write timeout
359  * 2 - Flash not erased
360  */
361
362 int write_buff (flash_info_t *info, uchar *src, ulong addr, ulong cnt)
363 {
364         ulong cp, wp, data;
365         int i, l, rc;
366
367         wp = (addr & ~3);       /* get lower word aligned address */
368
369         /*
370          * handle unaligned start bytes
371          */
372         if ((l = addr - wp) != 0) {
373                 data = 0;
374                 for (i=0, cp=wp; i<l; ++i, ++cp) {
375                         data = (data << 8) | (*(uchar *)cp);
376                 }
377                 for (; i<4 && cnt>0; ++i) {
378                         data = (data << 8) | *src++;
379                         --cnt;
380                         ++cp;
381                 }
382                 for (; cnt==0 && i<4; ++i, ++cp) {
383                         data = (data << 8) | (*(uchar *)cp);
384                 }
385
386                 if ((rc = write_word(info, wp, data)) != 0) {
387                         return (rc);
388                 }
389                 wp += 4;
390         }
391
392         /*
393          * handle word aligned part
394          */
395         while (cnt >= 4) {
396                 data = 0;
397                 for (i=0; i<4; ++i) {
398                         data = (data << 8) | *src++;
399                 }
400                 if ((rc = write_word(info, wp, data)) != 0) {
401                         return (rc);
402                 }
403                 wp  += 4;
404                 cnt -= 4;
405         }
406
407         if (cnt == 0) {
408                 return (0);
409         }
410
411         /*
412          * handle unaligned tail bytes
413          */
414         data = 0;
415         for (i=0, cp=wp; i<4 && cnt>0; ++i, ++cp) {
416                 data = (data << 8) | *src++;
417                 --cnt;
418         }
419         for (; i<4; ++i, ++cp) {
420                 data = (data << 8) | (*(uchar *)cp);
421         }
422
423         return (write_word(info, wp, data));
424 }
425
426 /*-----------------------------------------------------------------------
427  * Write a word to Flash, returns:
428  * 0 - OK
429  * 1 - write timeout
430  * 2 - Flash not erased
431  */
432 static int write_word (flash_info_t *info, ulong dest, ulong data)
433 {
434         vu_long *addr = (vu_long *)dest;
435         ulong start, csr;
436         int flag;
437
438         /* Check if Flash is (sufficiently) erased */
439         if ((*addr & data) != data) {
440                 return (2);
441         }
442         /* Disable interrupts which might cause a timeout here */
443         flag = disable_interrupts();
444
445         /* Write Command */
446         *addr = 0x10101010;
447         asm("sync");
448
449         /* Write Data */
450         *addr = data;
451
452         /* re-enable interrupts if necessary */
453         if (flag)
454                 enable_interrupts();
455
456         /* data polling for D7 */
457         start = get_timer (0);
458         flag  = 0;
459
460         while (((csr = *addr) & 0x00800080) != 0x00800080) {
461                 if (get_timer(start) > CONFIG_SYS_FLASH_WRITE_TOUT) {
462                         flag = 1;
463                         break;
464                 }
465         }
466         if (csr & 0x40404040) {
467                 printf ("CSR indicates write error (%08lx) at %08lx\n", csr, (ulong)addr);
468                 flag = 1;
469         }
470
471         /* Clear Status Registers Command */
472         *addr = 0x50505050;
473         asm("sync");
474         /* Reset to read array mode */
475         *addr = 0xFFFFFFFF;
476         asm("sync");
477
478         return (flag);
479 }
480
481 /*-----------------------------------------------------------------------
482  * Clear Block Lock Bit, returns:
483  * 0 - OK
484  * 1 - Timeout
485  */
486
487 static int clear_block_lock_bit(vu_long  * addr)
488 {
489         ulong start, now;
490
491         /* Reset Array */
492         *addr = 0xffffffff;
493         asm("sync");
494         /* Clear Status Register */
495         *addr = 0x50505050;
496         asm("sync");
497
498         *addr = 0x60606060;
499         asm("sync");
500         *addr = 0xd0d0d0d0;
501         asm("sync");
502
503         start = get_timer (0);
504         while((*addr & 0x00800080) != 0x00800080){
505                 if ((now=get_timer(start)) > CONFIG_SYS_FLASH_ERASE_TOUT) {
506                         printf ("Timeout on clearing Block Lock Bit\n");
507                         *addr = 0xFFFFFFFF;     /* reset bank */
508                         asm("sync");
509                         return 1;
510                 }
511         }
512         return 0;
513 }
514
515 #endif /* !CONFIG_SYS_NO_FLASH */