]> git.kernelconcepts.de Git - karo-tx-uboot.git/blob - board/dnp1110/flash.c
ca9aff957b20a8d1045312dd981e2958ea5a426e
[karo-tx-uboot.git] / board / dnp1110 / flash.c
1 /*
2  * (C) Copyright 2002
3  * Sysgo Real-Time Solutions, GmbH <www.elinos.com>
4  * Rolf Offermanns <rof@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)    (x)
42 #define PUZZLE_TO_FLASH(x)      (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 to 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 + _armboot_end_data - _armboot_start,
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 int flash_error (ulong code)
168 {
169         /* Check bit patterns */
170         /* SR.7=0 is busy, SR.7=1 is ready */
171         /* all other flags indicate error on 1 */
172         /* SR.0 is undefined */
173         /* Timeout is our faked flag */
174
175         /* sequence is described in Intel 290644-005 document */
176
177         /* check Timeout */
178         if (code & BIT_TIMEOUT)
179         {
180                 printf ("Timeout\n");
181                 return ERR_TIMOUT;
182         }
183
184         /* check Busy, SR.7 */
185         if (~code & BIT_BUSY)
186         {
187                 printf ("Busy\n");
188                 return ERR_PROG_ERROR;
189         }
190
191         /* check Vpp low, SR.3 */
192         if (code & BIT_VPP_RANGE_ERROR)
193         {
194                 printf ("Vpp range error\n");
195                 return ERR_PROG_ERROR;
196         }
197
198         /* check Device Protect Error, SR.1 */
199         if (code & BIT_PROTECT_ERROR)
200         {
201                 printf ("Device protect error\n");
202                 return ERR_PROG_ERROR;
203         }
204
205         /* check Command Seq Error, SR.4 & SR.5 */
206         if (code & BIT_SEQUENCE_ERROR)
207         {
208                 printf ("Command seqence error\n");
209                 return ERR_PROG_ERROR;
210         }
211
212         /* check Block Erase Error, SR.5 */
213         if (code & BIT_ERASE_ERROR)
214         {
215                 printf ("Block erase error\n");
216                 return ERR_PROG_ERROR;
217         }
218
219         /* check Program Error, SR.4 */
220         if (code & BIT_PROGRAM_ERROR)
221         {
222                 printf ("Program error\n");
223                 return ERR_PROG_ERROR;
224         }
225
226         /* check Block Erase Suspended, SR.6 */
227         if (code & BIT_ERASE_SUSPEND)
228         {
229                 printf ("Block erase suspended\n");
230                 return ERR_PROG_ERROR;
231         }
232
233         /* check Program Suspended, SR.2 */
234         if (code & BIT_PROGRAM_SUSPEND)
235         {
236                 printf ("Program suspended\n");
237                 return ERR_PROG_ERROR;
238         }
239
240         /* OK, no error */
241         return ERR_OK;
242 }
243
244 /*-----------------------------------------------------------------------
245  */
246
247 int     flash_erase (flash_info_t *info, int s_first, int s_last)
248 {
249     ulong result;
250     int iflag, cflag, prot, sect;
251     int rc = ERR_OK;
252
253     /* first look for protection bits */
254
255     if (info->flash_id == FLASH_UNKNOWN)
256         return ERR_UNKNOWN_FLASH_TYPE;
257
258     if ((s_first < 0) || (s_first > s_last)) {
259         return ERR_INVAL;
260     }
261
262     if ((info->flash_id & FLASH_VENDMASK) !=
263         (INTEL_MANUFACT & FLASH_VENDMASK)) {
264         return ERR_UNKNOWN_FLASH_VENDOR;
265     }
266
267     prot = 0;
268     for (sect=s_first; sect<=s_last; ++sect) {
269         if (info->protect[sect]) {
270             prot++;
271         }
272     }
273     if (prot)
274         return ERR_PROTECTED;
275
276     /*
277      * Disable interrupts which might cause a timeout
278      * here. Remember that our exception vectors are
279      * at address 0 in the flash, and we don't want a
280      * (ticker) exception to happen while the flash
281      * chip is in programming mode.
282      */
283     cflag = icache_status();
284     icache_disable();
285     iflag = disable_interrupts();
286
287     /* Start erase on unprotected sectors */
288     for (sect = s_first; sect<=s_last && !ctrlc(); sect++)
289     {
290         printf("Erasing sector %2d ... ", sect);
291
292         /* arm simple, non interrupt dependent timer */
293         reset_timer_masked();
294
295         if (info->protect[sect] == 0)
296         {       /* not protected */
297             vu_long *addr = (vu_long *)(info->start[sect]);
298
299             *addr = PUZZLE_TO_FLASH(CMD_STATUS_RESET);
300             *addr = PUZZLE_TO_FLASH(CMD_ERASE_SETUP);
301             *addr = PUZZLE_TO_FLASH(CMD_ERASE_CONFIRM);
302
303             /* wait until flash is ready */
304             do
305             {
306                 /* check timeout */
307                 if (get_timer_masked() > CFG_FLASH_ERASE_TOUT)
308                 {
309                     *addr = PUZZLE_TO_FLASH(CMD_SUSPEND);
310                     result = BIT_TIMEOUT;
311                     break;
312                 }
313
314                 result = PUZZLE_FROM_FLASH(*addr);
315             }  while (~result & BIT_BUSY);
316
317             *addr = PUZZLE_TO_FLASH(CMD_READ_ARRAY);
318
319             if ((rc = flash_error(result)) != ERR_OK)
320                 goto outahere;
321
322             printf("ok.\n");
323         }
324         else /* it was protected */
325         {
326             printf("protected!\n");
327         }
328     }
329
330     if (ctrlc())
331       printf("User Interrupt!\n");
332
333 outahere:
334     /* allow flash to settle - wait 10 ms */
335     udelay_masked(10000);
336
337     if (iflag)
338       enable_interrupts();
339
340     if (cflag)
341       icache_enable();
342
343     return rc;
344 }
345
346 /*-----------------------------------------------------------------------
347  * Copy memory to flash
348  */
349
350 volatile static int write_word (flash_info_t *info, ulong dest, ulong data)
351 {
352     vu_long *addr = (vu_long *)dest;
353     ulong result;
354     int rc = ERR_OK;
355     int cflag, iflag;
356
357     /* Check if Flash is (sufficiently) erased
358      */
359     result = PUZZLE_FROM_FLASH(*addr);
360     if ((result & data) != data)
361         return ERR_NOT_ERASED;
362
363     /*
364      * Disable interrupts which might cause a timeout
365      * here. Remember that our exception vectors are
366      * at address 0 in the flash, and we don't want a
367      * (ticker) exception to happen while the flash
368      * chip is in programming mode.
369      */
370     cflag = icache_status();
371     icache_disable();
372     iflag = disable_interrupts();
373
374     *addr = PUZZLE_TO_FLASH(CMD_STATUS_RESET);
375     *addr = PUZZLE_TO_FLASH(CMD_PROGRAM);
376     *addr = data;
377
378     /* arm simple, non interrupt dependent timer */
379     reset_timer_masked();
380
381     /* wait until flash is ready */
382     do
383     {
384         /* check timeout */
385         if (get_timer_masked() > CFG_FLASH_ERASE_TOUT)
386         {
387             *addr = PUZZLE_TO_FLASH(CMD_SUSPEND);
388             result = BIT_TIMEOUT;
389             break;
390         }
391
392         result = PUZZLE_FROM_FLASH(*addr);
393     }  while (~result & BIT_BUSY);
394
395     *addr = PUZZLE_TO_FLASH(CMD_READ_ARRAY);
396
397     rc = flash_error(result);
398
399     if (iflag)
400       enable_interrupts();
401
402     if (cflag)
403       icache_enable();
404
405     return rc;
406 }
407
408 /*-----------------------------------------------------------------------
409  * Copy memory to flash.
410  */
411
412 int write_buff (flash_info_t *info, uchar *src, ulong addr, ulong cnt)
413 {
414     ulong cp, wp, data;
415     int l;
416     int i, rc;
417
418     wp = (addr & ~3);   /* get lower word aligned address */
419
420     /*
421      * handle unaligned start bytes
422      */
423     if ((l = addr - wp) != 0) {
424         data = 0;
425         for (i=0, cp=wp; i<l; ++i, ++cp) {
426             data = (data >> 8) | (*(uchar *)cp << 24);
427         }
428         for (; i<4 && cnt>0; ++i) {
429             data = (data >> 8) | (*src++ << 24);
430             --cnt;
431             ++cp;
432         }
433         for (; cnt==0 && i<4; ++i, ++cp) {
434             data = (data >> 8) | (*(uchar *)cp << 24);
435         }
436
437         if ((rc = write_word(info, wp, data)) != 0) {
438             return (rc);
439         }
440         wp += 4;
441     }
442
443     /*
444      * handle word aligned part
445      */
446     while (cnt >= 4) {
447         data = *((vu_long*)src);
448         if ((rc = write_word(info, wp, data)) != 0) {
449             return (rc);
450         }
451         src += 4;
452         wp  += 4;
453         cnt -= 4;
454     }
455
456     if (cnt == 0) {
457         return ERR_OK;
458     }
459
460     /*
461      * handle unaligned tail bytes
462      */
463     data = 0;
464     for (i=0, cp=wp; i<4 && cnt>0; ++i, ++cp) {
465         data = (data >> 8) | (*src++ << 24);
466         --cnt;
467     }
468     for (; i<4; ++i, ++cp) {
469         data = (data >> 8) | (*(uchar *)cp << 24);
470     }
471
472     return write_word(info, wp, data);
473 }