]> git.kernelconcepts.de Git - karo-tx-uboot.git/blob - board/lart/flash.c
Some code cleanup for GCC 4.x
[karo-tx-uboot.git] / board / lart / flash.c
1 /*
2  * (C) Copyright 2002
3  * Sysgo Real-Time Solutions, GmbH <www.elinos.com>
4  * Marius Groeger <mgroeger@sysgo.de>
5  *
6  * See file CREDITS for list of people who contributed to this
7  * project.
8  *
9  * This program is free software; you can redistribute it and/or
10  * modify it under the terms of the GNU General Public License as
11  * published by the Free Software Foundation; either version 2 of
12  * the License, or (at your option) any later version.
13  *
14  * This program is distributed in the hope that it will be useful,
15  * but WITHOUT ANY WARRANTY; without even the implied warranty of
16  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
17  * GNU General Public License for more details.
18  *
19  * You should have received a copy of the GNU General Public License
20  * along with this program; if not, write to the Free Software
21  * Foundation, Inc., 59 Temple Place, Suite 330, Boston,
22  * MA 02111-1307 USA
23  */
24
25 #include <common.h>
26
27 ulong myflush(void);
28
29
30 #define FLASH_BANK_SIZE 0x800000
31 #define MAIN_SECT_SIZE  0x20000
32 #define PARAM_SECT_SIZE 0x4000
33
34 /* puzzle magic for lart
35  * data_*_flash are def'd in flashasm.S
36  */
37
38 extern u32 data_from_flash(u32);
39 extern u32 data_to_flash(u32);
40
41 #define PUZZLE_FROM_FLASH(x)    data_from_flash((x))
42 #define PUZZLE_TO_FLASH(x)      data_to_flash((x))
43
44 flash_info_t    flash_info[CFG_MAX_FLASH_BANKS];
45
46
47 #define CMD_READ_ARRAY          0x00FF00FF
48 #define CMD_IDENTIFY            0x00900090
49 #define CMD_ERASE_SETUP         0x00200020
50 #define CMD_ERASE_CONFIRM       0x00D000D0
51 #define CMD_PROGRAM             0x00400040
52 #define CMD_RESUME              0x00D000D0
53 #define CMD_SUSPEND             0x00B000B0
54 #define CMD_STATUS_READ         0x00700070
55 #define CMD_STATUS_RESET        0x00500050
56
57 #define BIT_BUSY                0x00800080
58 #define BIT_ERASE_SUSPEND       0x00400040
59 #define BIT_ERASE_ERROR         0x00200020
60 #define BIT_PROGRAM_ERROR       0x00100010
61 #define BIT_VPP_RANGE_ERROR     0x00080008
62 #define BIT_PROGRAM_SUSPEND     0x00040004
63 #define BIT_PROTECT_ERROR       0x00020002
64 #define BIT_UNDEFINED           0x00010001
65
66 #define BIT_SEQUENCE_ERROR      0x00300030
67 #define BIT_TIMEOUT             0x80000000
68
69 /*-----------------------------------------------------------------------
70  */
71
72 ulong flash_init(void)
73 {
74     int i, j;
75     ulong size = 0;
76
77     for (i = 0; i < CFG_MAX_FLASH_BANKS; i++)
78     {
79         ulong flashbase = 0;
80         flash_info[i].flash_id =
81           (INTEL_MANUFACT & FLASH_VENDMASK) |
82           (INTEL_ID_28F160F3B & FLASH_TYPEMASK);
83         flash_info[i].size = FLASH_BANK_SIZE;
84         flash_info[i].sector_count = CFG_MAX_FLASH_SECT;
85         memset(flash_info[i].protect, 0, CFG_MAX_FLASH_SECT);
86         if (i == 0)
87           flashbase = PHYS_FLASH_1;
88         else
89           panic("configured too many flash banks!\n");
90         for (j = 0; j < flash_info[i].sector_count; j++)
91         {
92             if (j <= 7)
93             {
94                 flash_info[i].start[j] = flashbase + j * PARAM_SECT_SIZE;
95             }
96             else
97             {
98                 flash_info[i].start[j] = flashbase + (j - 7)*MAIN_SECT_SIZE;
99             }
100         }
101         size += flash_info[i].size;
102     }
103
104     /* Protect monitor and environment sectors
105      */
106     flash_protect(FLAG_PROTECT_SET,
107                   CFG_FLASH_BASE,
108                   CFG_FLASH_BASE + monitor_flash_len - 1,
109                   &flash_info[0]);
110
111     flash_protect(FLAG_PROTECT_SET,
112                   CFG_ENV_ADDR,
113                   CFG_ENV_ADDR + CFG_ENV_SIZE - 1,
114                   &flash_info[0]);
115
116     return size;
117 }
118
119 /*-----------------------------------------------------------------------
120  */
121 void flash_print_info  (flash_info_t *info)
122 {
123     int i;
124
125     switch (info->flash_id & FLASH_VENDMASK)
126     {
127     case (INTEL_MANUFACT & FLASH_VENDMASK):
128         printf("Intel: ");
129         break;
130     default:
131         printf("Unknown Vendor ");
132         break;
133     }
134
135     switch (info->flash_id & FLASH_TYPEMASK)
136     {
137     case (INTEL_ID_28F160F3B & FLASH_TYPEMASK):
138         printf("2x 28F160F3B (16Mbit)\n");
139         break;
140     default:
141         printf("Unknown Chip Type\n");
142         goto Done;
143         break;
144     }
145
146     printf("  Size: %ld MB in %d Sectors\n",
147            info->size >> 20, info->sector_count);
148
149     printf("  Sector Start Addresses:");
150     for (i = 0; i < info->sector_count; i++)
151     {
152         if ((i % 5) == 0)
153         {
154             printf ("\n   ");
155         }
156         printf (" %08lX%s", info->start[i],
157                 info->protect[i] ? " (RO)" : "     ");
158     }
159     printf ("\n");
160
161 Done:
162     ;
163 }
164
165 /*-----------------------------------------------------------------------
166  */
167
168 int flash_error (ulong code)
169 {
170         /* Check bit patterns */
171         /* SR.7=0 is busy, SR.7=1 is ready */
172         /* all other flags indicate error on 1 */
173         /* SR.0 is undefined */
174         /* Timeout is our faked flag */
175
176         /* sequence is described in Intel 290644-005 document */
177
178         /* check Timeout */
179         if (code & BIT_TIMEOUT)
180         {
181                 printf ("Timeout\n");
182                 return ERR_TIMOUT;
183         }
184
185         /* check Busy, SR.7 */
186         if (~code & BIT_BUSY)
187         {
188                 printf ("Busy\n");
189                 return ERR_PROG_ERROR;
190         }
191
192         /* check Vpp low, SR.3 */
193         if (code & BIT_VPP_RANGE_ERROR)
194         {
195                 printf ("Vpp range error\n");
196                 return ERR_PROG_ERROR;
197         }
198
199         /* check Device Protect Error, SR.1 */
200         if (code & BIT_PROTECT_ERROR)
201         {
202                 printf ("Device protect error\n");
203                 return ERR_PROG_ERROR;
204         }
205
206         /* check Command Seq Error, SR.4 & SR.5 */
207         if (code & BIT_SEQUENCE_ERROR)
208         {
209                 printf ("Command seqence error\n");
210                 return ERR_PROG_ERROR;
211         }
212
213         /* check Block Erase Error, SR.5 */
214         if (code & BIT_ERASE_ERROR)
215         {
216                 printf ("Block erase error\n");
217                 return ERR_PROG_ERROR;
218         }
219
220         /* check Program Error, SR.4 */
221         if (code & BIT_PROGRAM_ERROR)
222         {
223                 printf ("Program error\n");
224                 return ERR_PROG_ERROR;
225         }
226
227         /* check Block Erase Suspended, SR.6 */
228         if (code & BIT_ERASE_SUSPEND)
229         {
230                 printf ("Block erase suspended\n");
231                 return ERR_PROG_ERROR;
232         }
233
234         /* check Program Suspended, SR.2 */
235         if (code & BIT_PROGRAM_SUSPEND)
236         {
237                 printf ("Program suspended\n");
238                 return ERR_PROG_ERROR;
239         }
240
241         /* OK, no error */
242         return ERR_OK;
243 }
244
245 /*-----------------------------------------------------------------------
246  */
247
248 int     flash_erase (flash_info_t *info, int s_first, int s_last)
249 {
250     ulong result;
251     int iflag, cflag, prot, sect;
252     int rc = ERR_OK;
253
254     /* first look for protection bits */
255
256     if (info->flash_id == FLASH_UNKNOWN)
257         return ERR_UNKNOWN_FLASH_TYPE;
258
259     if ((s_first < 0) || (s_first > s_last)) {
260         return ERR_INVAL;
261     }
262
263     if ((info->flash_id & FLASH_VENDMASK) !=
264         (INTEL_MANUFACT & FLASH_VENDMASK)) {
265         return ERR_UNKNOWN_FLASH_VENDOR;
266     }
267
268     prot = 0;
269     for (sect=s_first; sect<=s_last; ++sect) {
270         if (info->protect[sect]) {
271             prot++;
272         }
273     }
274     if (prot)
275         return ERR_PROTECTED;
276
277     /*
278      * Disable interrupts which might cause a timeout
279      * here. Remember that our exception vectors are
280      * at address 0 in the flash, and we don't want a
281      * (ticker) exception to happen while the flash
282      * chip is in programming mode.
283      */
284     cflag = icache_status();
285     icache_disable();
286     iflag = disable_interrupts();
287
288     /* Start erase on unprotected sectors */
289     for (sect = s_first; sect<=s_last && !ctrlc(); sect++)
290     {
291         printf("Erasing sector %2d ... ", sect);
292
293         /* arm simple, non interrupt dependent timer */
294         reset_timer_masked();
295
296         if (info->protect[sect] == 0)
297         {       /* not protected */
298             vu_long *addr = (vu_long *)(info->start[sect]);
299
300             *addr = PUZZLE_TO_FLASH(CMD_STATUS_RESET);
301             *addr = PUZZLE_TO_FLASH(CMD_ERASE_SETUP);
302             *addr = PUZZLE_TO_FLASH(CMD_ERASE_CONFIRM);
303
304             /* wait until flash is ready */
305             do
306             {
307                 /* check timeout */
308                 if (get_timer_masked() > CFG_FLASH_ERASE_TOUT)
309                 {
310                     *addr = PUZZLE_TO_FLASH(CMD_SUSPEND);
311                     result = BIT_TIMEOUT;
312                     break;
313                 }
314
315                 result = PUZZLE_FROM_FLASH(*addr);
316             }  while (~result & BIT_BUSY);
317
318             *addr = PUZZLE_TO_FLASH(CMD_READ_ARRAY);
319
320             if ((rc = flash_error(result)) != ERR_OK)
321                 goto outahere;
322
323             printf("ok.\n");
324         }
325         else /* it was protected */
326         {
327             printf("protected!\n");
328         }
329     }
330
331     if (ctrlc())
332       printf("User Interrupt!\n");
333
334 outahere:
335     /* allow flash to settle - wait 10 ms */
336     udelay_masked(10000);
337
338     if (iflag)
339       enable_interrupts();
340
341     if (cflag)
342       icache_enable();
343
344     return rc;
345 }
346
347 /*-----------------------------------------------------------------------
348  * Copy memory to flash
349  */
350
351 static int write_word (flash_info_t *info, ulong dest, ulong data)
352 {
353     vu_long *addr = (vu_long *)dest;
354     ulong result;
355     int rc = ERR_OK;
356     int cflag, iflag;
357
358     /* Check if Flash is (sufficiently) erased
359      */
360     result = PUZZLE_FROM_FLASH(*addr);
361     if ((result & data) != data)
362         return ERR_NOT_ERASED;
363
364     /*
365      * Disable interrupts which might cause a timeout
366      * here. Remember that our exception vectors are
367      * at address 0 in the flash, and we don't want a
368      * (ticker) exception to happen while the flash
369      * chip is in programming mode.
370      */
371     cflag = icache_status();
372     icache_disable();
373     iflag = disable_interrupts();
374
375     *addr = PUZZLE_TO_FLASH(CMD_STATUS_RESET);
376     *addr = PUZZLE_TO_FLASH(CMD_PROGRAM);
377     *addr = data;
378
379     /* arm simple, non interrupt dependent timer */
380     reset_timer_masked();
381
382     /* wait until flash is ready */
383     do
384     {
385         /* check timeout */
386         if (get_timer_masked() > CFG_FLASH_ERASE_TOUT)
387         {
388             *addr = PUZZLE_TO_FLASH(CMD_SUSPEND);
389             result = BIT_TIMEOUT;
390             break;
391         }
392
393         result = PUZZLE_FROM_FLASH(*addr);
394     }  while (~result & BIT_BUSY);
395
396     *addr = PUZZLE_TO_FLASH(CMD_READ_ARRAY);
397
398     rc = flash_error(result);
399
400     if (iflag)
401       enable_interrupts();
402
403     if (cflag)
404       icache_enable();
405
406     return rc;
407 }
408
409 /*-----------------------------------------------------------------------
410  * Copy memory to flash.
411  */
412
413 int write_buff (flash_info_t *info, uchar *src, ulong addr, ulong cnt)
414 {
415     ulong cp, wp, data;
416     int l;
417     int i, rc;
418
419     wp = (addr & ~3);   /* get lower word aligned address */
420
421     /*
422      * handle unaligned start bytes
423      */
424     if ((l = addr - wp) != 0) {
425         data = 0;
426         for (i=0, cp=wp; i<l; ++i, ++cp) {
427             data = (data >> 8) | (*(uchar *)cp << 24);
428         }
429         for (; i<4 && cnt>0; ++i) {
430             data = (data >> 8) | (*src++ << 24);
431             --cnt;
432             ++cp;
433         }
434         for (; cnt==0 && i<4; ++i, ++cp) {
435             data = (data >> 8) | (*(uchar *)cp << 24);
436         }
437
438         if ((rc = write_word(info, wp, data)) != 0) {
439             return (rc);
440         }
441         wp += 4;
442     }
443
444     /*
445      * handle word aligned part
446      */
447     while (cnt >= 4) {
448         data = *((vu_long*)src);
449         if ((rc = write_word(info, wp, data)) != 0) {
450             return (rc);
451         }
452         src += 4;
453         wp  += 4;
454         cnt -= 4;
455     }
456
457     if (cnt == 0) {
458         return ERR_OK;
459     }
460
461     /*
462      * handle unaligned tail bytes
463      */
464     data = 0;
465     for (i=0, cp=wp; i<4 && cnt>0; ++i, ++cp) {
466         data = (data >> 8) | (*src++ << 24);
467         --cnt;
468     }
469     for (; i<4; ++i, ++cp) {
470         data = (data >> 8) | (*(uchar *)cp << 24);
471     }
472
473     return write_word(info, wp, data);
474 }