]> git.kernelconcepts.de Git - karo-tx-uboot.git/blob - board/shannon/flash.c
rename CFG_ macros to CONFIG_SYS
[karo-tx-uboot.git] / board / shannon / flash.c
1 /*
2  * (C) Copyright 2002
3  * Sysgo Real-Time Solutions, GmbH <www.elinos.com>
4  * Alex Zuepke <azu@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 0x400000        /* 4 MB */
31 #define MAIN_SECT_SIZE  0x20000         /* 128 KB */
32
33 flash_info_t    flash_info[CONFIG_SYS_MAX_FLASH_BANKS];
34
35
36 #define CMD_READ_ARRAY          0x00F000F0
37 #define CMD_UNLOCK1             0x00AA00AA
38 #define CMD_UNLOCK2             0x00550055
39 #define CMD_ERASE_SETUP         0x00800080
40 #define CMD_ERASE_CONFIRM       0x00300030
41 #define CMD_PROGRAM             0x00A000A0
42 #define CMD_UNLOCK_BYPASS       0x00200020
43
44 #define MEM_FLASH_ADDR1         (*(volatile u32 *)(CONFIG_SYS_FLASH_BASE + (0x00000555 << 2)))
45 #define MEM_FLASH_ADDR2         (*(volatile u32 *)(CONFIG_SYS_FLASH_BASE + (0x000002AA << 2)))
46
47 #define BIT_ERASE_DONE          0x00800080
48 #define BIT_RDY_MASK            0x00800080
49 #define BIT_PROGRAM_ERROR       0x00200020
50 #define BIT_TIMEOUT             0x80000000 /* our flag */
51
52 #define READY 1
53 #define ERR   2
54 #define TMO   4
55
56 /*-----------------------------------------------------------------------
57  */
58
59 ulong flash_init(void)
60 {
61     int i, j;
62     ulong size = 0;
63
64     for (i = 0; i < CONFIG_SYS_MAX_FLASH_BANKS; i++)
65     {
66         ulong flashbase = 0;
67         flash_info[i].flash_id =
68           (AMD_MANUFACT & FLASH_VENDMASK) |
69           (AMD_ID_LV160B & FLASH_TYPEMASK);
70         flash_info[i].size = FLASH_BANK_SIZE;
71         flash_info[i].sector_count = CONFIG_SYS_MAX_FLASH_SECT;
72         memset(flash_info[i].protect, 0, CONFIG_SYS_MAX_FLASH_SECT);
73         if (i == 0)
74           flashbase = PHYS_FLASH_1;
75         else
76           panic("configured too many flash banks!\n");
77         for (j = 0; j < flash_info[i].sector_count; j++)
78         {
79
80             if (j <= 3)
81             {
82                 /* 1st one is 32 KB */
83                 if (j == 0)
84                 {
85                         flash_info[i].start[j] = flashbase + 0;
86                 }
87
88                 /* 2nd and 3rd are both 16 KB */
89                 if ((j == 1) || (j == 2))
90                 {
91                         flash_info[i].start[j] = flashbase + 0x8000 + (j-1)*0x4000;
92                 }
93
94                 /* 4th 64 KB */
95                 if (j == 3)
96                 {
97                         flash_info[i].start[j] = flashbase + 0x10000;
98                 }
99             }
100             else
101             {
102                 flash_info[i].start[j] = flashbase + (j - 3)*MAIN_SECT_SIZE;
103             }
104         }
105         size += flash_info[i].size;
106     }
107
108     /*
109      * Protect monitor and environment sectors
110      * Inferno is complicated, it's hardware locked
111      */
112 #ifdef CONFIG_INFERNO
113     /* first one, 0x00000 to 0x07fff */
114     flash_protect(FLAG_PROTECT_SET,
115                   CONFIG_SYS_FLASH_BASE + 0x00000,
116                   CONFIG_SYS_FLASH_BASE + 0x08000 - 1,
117                   &flash_info[0]);
118
119     /* third to 10th, 0x0c000 - 0xdffff */
120     flash_protect(FLAG_PROTECT_SET,
121                   CONFIG_SYS_FLASH_BASE + 0x0c000,
122                   CONFIG_SYS_FLASH_BASE + 0xe0000 - 1,
123                   &flash_info[0]);
124 #else
125     flash_protect(FLAG_PROTECT_SET,
126                   CONFIG_SYS_FLASH_BASE,
127                   CONFIG_SYS_FLASH_BASE + monitor_flash_len - 1,
128                   &flash_info[0]);
129
130     flash_protect(FLAG_PROTECT_SET,
131                   CONFIG_ENV_ADDR,
132                   CONFIG_ENV_ADDR + CONFIG_ENV_SIZE - 1,
133                   &flash_info[0]);
134 #endif
135     return size;
136 }
137
138 /*-----------------------------------------------------------------------
139  */
140 void flash_print_info  (flash_info_t *info)
141 {
142     int i;
143
144     switch (info->flash_id & FLASH_VENDMASK)
145     {
146     case (AMD_MANUFACT & FLASH_VENDMASK):
147         printf("AMD: ");
148         break;
149     default:
150         printf("Unknown Vendor ");
151         break;
152     }
153
154     switch (info->flash_id & FLASH_TYPEMASK)
155     {
156     case (AMD_ID_LV160B & FLASH_TYPEMASK):
157         printf("2x Amd29F160BB (16Mbit)\n");
158         break;
159     default:
160         printf("Unknown Chip Type\n");
161         goto Done;
162         break;
163     }
164
165     printf("  Size: %ld MB in %d Sectors\n",
166            info->size >> 20, info->sector_count);
167
168     printf("  Sector Start Addresses:");
169     for (i = 0; i < info->sector_count; i++)
170     {
171         if ((i % 5) == 0)
172         {
173             printf ("\n   ");
174         }
175         printf (" %08lX%s", info->start[i],
176                 info->protect[i] ? " (RO)" : "     ");
177     }
178     printf ("\n");
179
180 Done:
181     ;
182 }
183
184 /*-----------------------------------------------------------------------
185  */
186
187 int     flash_erase (flash_info_t *info, int s_first, int s_last)
188 {
189     ulong result;
190     int iflag, cflag, prot, sect;
191     int rc = ERR_OK;
192     int chip1, chip2;
193
194     /* first look for protection bits */
195
196     if (info->flash_id == FLASH_UNKNOWN)
197         return ERR_UNKNOWN_FLASH_TYPE;
198
199     if ((s_first < 0) || (s_first > s_last)) {
200         return ERR_INVAL;
201     }
202
203     if ((info->flash_id & FLASH_VENDMASK) !=
204         (AMD_MANUFACT & FLASH_VENDMASK)) {
205         return ERR_UNKNOWN_FLASH_VENDOR;
206     }
207
208     prot = 0;
209     for (sect=s_first; sect<=s_last; ++sect) {
210         if (info->protect[sect]) {
211             prot++;
212         }
213     }
214     if (prot)
215         return ERR_PROTECTED;
216
217     /*
218      * Disable interrupts which might cause a timeout
219      * here. Remember that our exception vectors are
220      * at address 0 in the flash, and we don't want a
221      * (ticker) exception to happen while the flash
222      * chip is in programming mode.
223      */
224     cflag = icache_status();
225     icache_disable();
226     iflag = disable_interrupts();
227
228     /* Start erase on unprotected sectors */
229     for (sect = s_first; sect<=s_last && !ctrlc(); sect++)
230     {
231         printf("Erasing sector %2d ... ", sect);
232
233         /* arm simple, non interrupt dependent timer */
234         reset_timer_masked();
235
236         if (info->protect[sect] == 0)
237         {       /* not protected */
238             vu_long *addr = (vu_long *)(info->start[sect]);
239
240             MEM_FLASH_ADDR1 = CMD_UNLOCK1;
241             MEM_FLASH_ADDR2 = CMD_UNLOCK2;
242             MEM_FLASH_ADDR1 = CMD_ERASE_SETUP;
243
244             MEM_FLASH_ADDR1 = CMD_UNLOCK1;
245             MEM_FLASH_ADDR2 = CMD_UNLOCK2;
246             *addr = CMD_ERASE_CONFIRM;
247
248             /* wait until flash is ready */
249             chip1 = chip2 = 0;
250
251             do
252             {
253                 result = *addr;
254
255                 /* check timeout */
256                 if (get_timer_masked() > CONFIG_SYS_FLASH_ERASE_TOUT)
257                 {
258                     MEM_FLASH_ADDR1 = CMD_READ_ARRAY;
259                     chip1 = TMO;
260                     break;
261                 }
262
263                 if (!chip1 && (result & 0xFFFF) & BIT_ERASE_DONE)
264                         chip1 = READY;
265
266                 if (!chip1 && (result & 0xFFFF) & BIT_PROGRAM_ERROR)
267                         chip1 = ERR;
268
269                 if (!chip2 && (result >> 16) & BIT_ERASE_DONE)
270                         chip2 = READY;
271
272                 if (!chip2 && (result >> 16) & BIT_PROGRAM_ERROR)
273                         chip2 = ERR;
274
275             }  while (!chip1 || !chip2);
276
277             MEM_FLASH_ADDR1 = CMD_READ_ARRAY;
278
279             if (chip1 == ERR || chip2 == ERR)
280             {
281                 rc = ERR_PROG_ERROR;
282                 goto outahere;
283             }
284             if (chip1 == TMO)
285             {
286                 rc = ERR_TIMOUT;
287                 goto outahere;
288             }
289
290             printf("ok.\n");
291         }
292         else /* it was protected */
293         {
294             printf("protected!\n");
295         }
296     }
297
298     if (ctrlc())
299       printf("User Interrupt!\n");
300
301 outahere:
302     /* allow flash to settle - wait 10 ms */
303     udelay_masked(10000);
304
305     if (iflag)
306       enable_interrupts();
307
308     if (cflag)
309       icache_enable();
310
311     return rc;
312 }
313
314 /*-----------------------------------------------------------------------
315  * Copy memory to flash
316  */
317
318 static int write_word (flash_info_t *info, ulong dest, ulong data)
319 {
320     vu_long *addr = (vu_long *)dest;
321     ulong result;
322     int rc = ERR_OK;
323     int cflag, iflag;
324     int chip1, chip2;
325
326     /*
327      * Check if Flash is (sufficiently) erased
328      */
329     result = *addr;
330     if ((result & data) != data)
331         return ERR_NOT_ERASED;
332
333
334     /*
335      * Disable interrupts which might cause a timeout
336      * here. Remember that our exception vectors are
337      * at address 0 in the flash, and we don't want a
338      * (ticker) exception to happen while the flash
339      * chip is in programming mode.
340      */
341     cflag = icache_status();
342     icache_disable();
343     iflag = disable_interrupts();
344
345     MEM_FLASH_ADDR1 = CMD_UNLOCK1;
346     MEM_FLASH_ADDR2 = CMD_UNLOCK2;
347     MEM_FLASH_ADDR1 = CMD_UNLOCK_BYPASS;
348     *addr = CMD_PROGRAM;
349     *addr = data;
350
351     /* arm simple, non interrupt dependent timer */
352     reset_timer_masked();
353
354     /* wait until flash is ready */
355     chip1 = chip2 = 0;
356     do
357     {
358         result = *addr;
359
360         /* check timeout */
361         if (get_timer_masked() > CONFIG_SYS_FLASH_ERASE_TOUT)
362         {
363             chip1 = ERR | TMO;
364             break;
365         }
366         if (!chip1 && ((result & 0x80) == (data & 0x80)))
367                 chip1 = READY;
368
369         if (!chip1 && ((result & 0xFFFF) & BIT_PROGRAM_ERROR))
370         {
371                 result = *addr;
372
373                 if ((result & 0x80) == (data & 0x80))
374                         chip1 = READY;
375                 else
376                         chip1 = ERR;
377         }
378
379         if (!chip2 && ((result & (0x80 << 16)) == (data & (0x80 << 16))))
380                 chip2 = READY;
381
382         if (!chip2 && ((result >> 16) & BIT_PROGRAM_ERROR))
383         {
384                 result = *addr;
385
386                 if ((result & (0x80 << 16)) == (data & (0x80 << 16)))
387                         chip2 = READY;
388                 else
389                         chip2 = ERR;
390         }
391
392     }  while (!chip1 || !chip2);
393
394     *addr = CMD_READ_ARRAY;
395
396     if (chip1 == ERR || chip2 == ERR || *addr != data)
397         rc = ERR_PROG_ERROR;
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 }