]> git.kernelconcepts.de Git - karo-tx-uboot.git/blob - board/mpl/vcma9/flash.c
* Get (mostly) rid of CFG_MONITOR_LEN definition; compute real length
[karo-tx-uboot.git] / board / mpl / vcma9 / 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 PHYS_FLASH_SIZE
31 #define MAIN_SECT_SIZE  0x10000         /* 64 KB */
32
33 flash_info_t    flash_info[CFG_MAX_FLASH_BANKS];
34
35
36 #define CMD_READ_ARRAY          0x000000F0
37 #define CMD_UNLOCK1             0x000000AA
38 #define CMD_UNLOCK2             0x00000055
39 #define CMD_ERASE_SETUP         0x00000080
40 #define CMD_ERASE_CONFIRM       0x00000030
41 #define CMD_PROGRAM             0x000000A0
42 #define CMD_UNLOCK_BYPASS       0x00000020
43
44 #define MEM_FLASH_ADDR1         (*(volatile u16 *)(CFG_FLASH_BASE + (0x00000555 << 1)))
45 #define MEM_FLASH_ADDR2         (*(volatile u16 *)(CFG_FLASH_BASE + (0x000002AA << 1)))
46
47 #define BIT_ERASE_DONE          0x00000080
48 #define BIT_RDY_MASK            0x00000080
49 #define BIT_PROGRAM_ERROR       0x00000020
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 < CFG_MAX_FLASH_BANKS; i++)
65     {
66         ulong flashbase = 0;
67         flash_info[i].flash_id =
68 #if defined(CONFIG_AMD_LV400)
69           (AMD_MANUFACT & FLASH_VENDMASK) |
70           (AMD_ID_LV400B & FLASH_TYPEMASK);
71 #elif defined(CONFIG_AMD_LV800)
72           (AMD_MANUFACT & FLASH_VENDMASK) |
73           (AMD_ID_LV800B & FLASH_TYPEMASK);
74 #else
75 #error "Unknown flash configured"
76 #endif
77         flash_info[i].size = FLASH_BANK_SIZE;
78         flash_info[i].sector_count = CFG_MAX_FLASH_SECT;
79         memset(flash_info[i].protect, 0, CFG_MAX_FLASH_SECT);
80         if (i == 0)
81           flashbase = PHYS_FLASH_1;
82         else
83           panic("configured to many flash banks!\n");
84         for (j = 0; j < flash_info[i].sector_count; j++)
85         {
86             if (j <= 3)
87             {
88                 /* 1st one is 16 KB */
89                 if (j == 0)
90                 {
91                         flash_info[i].start[j] = flashbase + 0;
92                 }
93
94                 /* 2nd and 3rd are both 8 KB */
95                 if ((j == 1) || (j == 2))
96                 {
97                         flash_info[i].start[j] = flashbase + 0x4000 + (j-1)*0x2000;
98                 }
99
100                 /* 4th 32 KB */
101                 if (j == 3)
102                 {
103                         flash_info[i].start[j] = flashbase + 0x8000;
104                 }
105             }
106             else
107             {
108                 flash_info[i].start[j] = flashbase + (j - 3)*MAIN_SECT_SIZE;
109             }
110         }
111         size += flash_info[i].size;
112     }
113
114     flash_protect(FLAG_PROTECT_SET,
115                   CFG_FLASH_BASE,
116                   CFG_FLASH_BASE + monitor_flash_len - 1,
117                   &flash_info[0]);
118
119     flash_protect(FLAG_PROTECT_SET,
120                   CFG_ENV_ADDR,
121                   CFG_ENV_ADDR + CFG_ENV_SIZE - 1,
122                   &flash_info[0]);
123
124     return size;
125 }
126
127 /*-----------------------------------------------------------------------
128  */
129 void flash_print_info  (flash_info_t *info)
130 {
131     int i;
132
133     switch (info->flash_id & FLASH_VENDMASK)
134     {
135     case (AMD_MANUFACT & FLASH_VENDMASK):
136         printf("AMD: ");
137         break;
138     default:
139         printf("Unknown Vendor ");
140         break;
141     }
142
143     switch (info->flash_id & FLASH_TYPEMASK)
144     {
145     case (AMD_ID_LV400B & FLASH_TYPEMASK):
146         printf("1x Amd29LV400BB (4Mbit)\n");
147         break;
148     case (AMD_ID_LV800B & FLASH_TYPEMASK):
149         printf("1x Amd29LV800BB (8Mbit)\n");
150         break;
151     default:
152         printf("Unknown Chip Type\n");
153         goto Done;
154         break;
155     }
156
157     printf("  Size: %ld MB in %d Sectors\n",
158            info->size >> 20, info->sector_count);
159
160     printf("  Sector Start Addresses:");
161     for (i = 0; i < info->sector_count; i++)
162     {
163         if ((i % 5) == 0)
164         {
165             printf ("\n   ");
166         }
167         printf (" %08lX%s", info->start[i],
168                 info->protect[i] ? " (RO)" : "     ");
169     }
170     printf ("\n");
171
172 Done:
173 }
174
175 /*-----------------------------------------------------------------------
176  */
177
178 int     flash_erase (flash_info_t *info, int s_first, int s_last)
179 {
180     ushort result;
181     int iflag, cflag, prot, sect;
182     int rc = ERR_OK;
183     int chip;
184
185     /* first look for protection bits */
186
187     if (info->flash_id == FLASH_UNKNOWN)
188         return ERR_UNKNOWN_FLASH_TYPE;
189
190     if ((s_first < 0) || (s_first > s_last)) {
191         return ERR_INVAL;
192     }
193
194     if ((info->flash_id & FLASH_VENDMASK) !=
195         (AMD_MANUFACT & FLASH_VENDMASK)) {
196         return ERR_UNKNOWN_FLASH_VENDOR;
197     }
198
199     prot = 0;
200     for (sect=s_first; sect<=s_last; ++sect) {
201         if (info->protect[sect]) {
202             prot++;
203         }
204     }
205     if (prot)
206         return ERR_PROTECTED;
207
208     /*
209      * Disable interrupts which might cause a timeout
210      * here. Remember that our exception vectors are
211      * at address 0 in the flash, and we don't want a
212      * (ticker) exception to happen while the flash
213      * chip is in programming mode.
214      */
215     cflag = icache_status();
216     icache_disable();
217     iflag = disable_interrupts();
218
219     /* Start erase on unprotected sectors */
220     for (sect = s_first; sect<=s_last && !ctrlc(); sect++)
221     {
222         printf("Erasing sector %2d ... ", sect);
223
224         /* arm simple, non interrupt dependent timer */
225         reset_timer_masked();
226
227         if (info->protect[sect] == 0)
228         {       /* not protected */
229             vu_short *addr = (vu_short *)(info->start[sect]);
230
231             MEM_FLASH_ADDR1 = CMD_UNLOCK1;
232             MEM_FLASH_ADDR2 = CMD_UNLOCK2;
233             MEM_FLASH_ADDR1 = CMD_ERASE_SETUP;
234
235             MEM_FLASH_ADDR1 = CMD_UNLOCK1;
236             MEM_FLASH_ADDR2 = CMD_UNLOCK2;
237             *addr = CMD_ERASE_CONFIRM;
238
239             /* wait until flash is ready */
240             chip = 0;
241
242             do
243             {
244                 result = *addr;
245
246                 /* check timeout */
247                 if (get_timer_masked() > CFG_FLASH_ERASE_TOUT)
248                 {
249                     MEM_FLASH_ADDR1 = CMD_READ_ARRAY;
250                     chip = TMO;
251                     break;
252                 }
253
254                 if (!chip && (result & 0xFFFF) & BIT_ERASE_DONE)
255                         chip = READY;
256
257                 if (!chip && (result & 0xFFFF) & BIT_PROGRAM_ERROR)
258                         chip = ERR;
259
260             }  while (!chip);
261
262             MEM_FLASH_ADDR1 = CMD_READ_ARRAY;
263
264             if (chip == ERR)
265             {
266                 rc = ERR_PROG_ERROR;
267                 goto outahere;
268             }
269             if (chip == TMO)
270             {
271                 rc = ERR_TIMOUT;
272                 goto outahere;
273             }
274
275             printf("ok.\n");
276         }
277         else /* it was protected */
278         {
279             printf("protected!\n");
280         }
281     }
282
283     if (ctrlc())
284       printf("User Interrupt!\n");
285
286 outahere:
287     /* allow flash to settle - wait 10 ms */
288     udelay_masked(10000);
289
290     if (iflag)
291       enable_interrupts();
292
293     if (cflag)
294       icache_enable();
295
296     return rc;
297 }
298
299 /*-----------------------------------------------------------------------
300  * Copy memory to flash
301  */
302
303 volatile static int write_hword (flash_info_t *info, ulong dest, ushort data)
304 {
305     vu_short *addr = (vu_short *)dest;
306     ushort result;
307     int rc = ERR_OK;
308     int cflag, iflag;
309     int chip;
310
311     /*
312      * Check if Flash is (sufficiently) erased
313      */
314     result = *addr;
315     if ((result & data) != data)
316         return ERR_NOT_ERASED;
317
318
319     /*
320      * Disable interrupts which might cause a timeout
321      * here. Remember that our exception vectors are
322      * at address 0 in the flash, and we don't want a
323      * (ticker) exception to happen while the flash
324      * chip is in programming mode.
325      */
326     cflag = icache_status();
327     icache_disable();
328     iflag = disable_interrupts();
329
330     MEM_FLASH_ADDR1 = CMD_UNLOCK1;
331     MEM_FLASH_ADDR2 = CMD_UNLOCK2;
332     MEM_FLASH_ADDR1 = CMD_PROGRAM;
333     *addr = data;
334
335     /* arm simple, non interrupt dependent timer */
336     reset_timer_masked();
337
338     /* wait until flash is ready */
339     chip = 0;
340     do
341     {
342         result = *addr;
343
344         /* check timeout */
345         if (get_timer_masked() > CFG_FLASH_ERASE_TOUT)
346         {
347             chip = ERR | TMO;
348             break;
349         }
350         if (!chip && ((result & 0x80) == (data & 0x80)))
351                 chip = READY;
352
353         if (!chip && ((result & 0xFFFF) & BIT_PROGRAM_ERROR))
354         {
355                 result = *addr;
356
357                 if ((result & 0x80) == (data & 0x80))
358                         chip = READY;
359                 else
360                         chip = ERR;
361         }
362
363     }  while (!chip);
364
365     *addr = CMD_READ_ARRAY;
366
367     if (chip == ERR || *addr != data)
368         rc = ERR_PROG_ERROR;
369
370     if (iflag)
371       enable_interrupts();
372
373     if (cflag)
374       icache_enable();
375
376     return rc;
377 }
378
379 /*-----------------------------------------------------------------------
380  * Copy memory to flash.
381  */
382
383 int write_buff (flash_info_t *info, uchar *src, ulong addr, ulong cnt)
384 {
385     ulong cp, wp;
386     int l;
387     int i, rc;
388     ushort data;
389
390     wp = (addr & ~1);   /* get lower word aligned address */
391
392     /*
393      * handle unaligned start bytes
394      */
395     if ((l = addr - wp) != 0) {
396         data = 0;
397         for (i=0, cp=wp; i<l; ++i, ++cp) {
398             data = (data >> 8) | (*(uchar *)cp << 8);
399         }
400         for (; i<2 && cnt>0; ++i) {
401             data = (data >> 8) | (*src++ << 8);
402             --cnt;
403             ++cp;
404         }
405         for (; cnt==0 && i<2; ++i, ++cp) {
406             data = (data >> 8) | (*(uchar *)cp << 8);
407         }
408
409         if ((rc = write_hword(info, wp, data)) != 0) {
410             return (rc);
411         }
412         wp += 2;
413     }
414
415     /*
416      * handle word aligned part
417      */
418     while (cnt >= 2) {
419         data = *((vu_short*)src);
420         if ((rc = write_hword(info, wp, data)) != 0) {
421             return (rc);
422         }
423         src += 2;
424         wp  += 2;
425         cnt -= 2;
426     }
427
428     if (cnt == 0) {
429         return ERR_OK;
430     }
431
432     /*
433      * handle unaligned tail bytes
434      */
435     data = 0;
436     for (i=0, cp=wp; i<2 && cnt>0; ++i, ++cp) {
437         data = (data >> 8) | (*src++ << 8);
438         --cnt;
439     }
440     for (; i<2; ++i, ++cp) {
441         data = (data >> 8) | (*(uchar *)cp << 8);
442     }
443
444     return write_hword(info, wp, data);
445 }