]> git.kernelconcepts.de Git - karo-tx-uboot.git/blob - board/at91rm9200dk/flash.c
* Patch by Rick Bronson, 16 Mar 2003:
[karo-tx-uboot.git] / board / at91rm9200dk / flash.c
1 /*
2  * (C) Copyright 2002
3  * Lineo, Inc. <www.lineo.com>
4  * Bernhard Kuhn <bkuhn@lineo.com>
5  *
6  * (C) Copyright 2002
7  * Sysgo Real-Time Solutions, GmbH <www.elinos.com>
8  * Alex Zuepke <azu@sysgo.de>
9  *
10  * See file CREDITS for list of people who contributed to this
11  * project.
12  *
13  * This program is free software; you can redistribute it and/or
14  * modify it under the terms of the GNU General Public License as
15  * published by the Free Software Foundation; either version 2 of
16  * the License, or (at your option) any later version.
17  *
18  * This program is distributed in the hope that it will be useful,
19  * but WITHOUT ANY WARRANTY; without even the implied warranty of
20  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
21  * GNU General Public License for more details.
22  *
23  * You should have received a copy of the GNU General Public License
24  * along with this program; if not, write to the Free Software
25  * Foundation, Inc., 59 Temple Place, Suite 330, Boston,
26  * MA 02111-1307 USA
27  */
28
29 #include <common.h>
30
31 ulong myflush(void);
32
33
34 #define FLASH_BANK_SIZE 0x200000        /* 2 MB */
35 #define MAIN_SECT_SIZE  0x10000         /* 64 KB */
36
37 flash_info_t    flash_info[CFG_MAX_FLASH_BANKS];
38
39
40 #define CMD_READ_ARRAY          0x00F0
41 #define CMD_UNLOCK1             0x00AA
42 #define CMD_UNLOCK2             0x0055
43 #define CMD_ERASE_SETUP         0x0080
44 #define CMD_ERASE_CONFIRM       0x0030
45 #define CMD_PROGRAM             0x00A0
46 #define CMD_UNLOCK_BYPASS       0x0020
47
48 #define MEM_FLASH_ADDR1         (*(volatile u16 *)(CFG_FLASH_BASE + (0x00005555<<1)))
49 #define MEM_FLASH_ADDR2         (*(volatile u16 *)(CFG_FLASH_BASE + (0x00002AAA<<1)))
50
51 #define BIT_ERASE_DONE          0x0080
52 #define BIT_RDY_MASK            0x0080
53 #define BIT_PROGRAM_ERROR       0x0020
54 #define BIT_TIMEOUT             0x80000000 /* our flag */
55
56 #define READY 1
57 #define ERR   2
58 #define TMO   4
59
60 /*-----------------------------------------------------------------------
61  */
62
63 ulong flash_init(void)
64 {
65     int i, j;
66     ulong size = 0;
67
68     for (i = 0; i < CFG_MAX_FLASH_BANKS; i++)
69     {
70         ulong flashbase = 0;
71         flash_info[i].flash_id =
72           (ATM_MANUFACT & FLASH_VENDMASK) |
73           (ATM_ID_BV1614 & FLASH_TYPEMASK);
74         flash_info[i].size = FLASH_BANK_SIZE;
75         flash_info[i].sector_count = CFG_MAX_FLASH_SECT;
76         memset(flash_info[i].protect, 0, CFG_MAX_FLASH_SECT);
77         if (i == 0)
78           flashbase = PHYS_FLASH_1;
79         else
80           panic("configured to many flash banks!\n");
81         for (j = 0; j < flash_info[i].sector_count; j++)
82         {
83
84             if (j <= 9)
85             {
86                 /* 1st to 8th are 8 KB */
87                 if (j <= 7)
88                 {
89                     flash_info[i].start[j] = flashbase + j*0x2000;
90                 }
91
92                 /* 9th and 10th are both 32 KB */
93                 if ((j == 8) || (j == 9))
94                 {
95                         flash_info[i].start[j] = flashbase + 0x10000 + (j-8)*0x8000;
96                 }
97             }
98             else
99             {
100                 flash_info[i].start[j] = flashbase + (j-8)*MAIN_SECT_SIZE;
101             }
102         }
103         size += flash_info[i].size;
104     }
105
106     flash_protect(FLAG_PROTECT_SET,
107                   CFG_FLASH_BASE,
108                   CFG_ENV_ADDR - 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 (ATM_MANUFACT & FLASH_VENDMASK):
128         printf("Atmel: ");
129         break;
130     default:
131         printf("Unknown Vendor ");
132         break;
133     }
134
135     switch (info->flash_id & FLASH_TYPEMASK)
136     {
137     case (ATM_ID_BV1614 & FLASH_TYPEMASK):
138         printf("AT49BV1614 (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_erase (flash_info_t *info, int s_first, int s_last)
168 {
169     ulong result;
170     int iflag, cflag, prot, sect;
171     int rc = ERR_OK;
172     int chip1;
173
174     /* first look for protection bits */
175
176     if (info->flash_id == FLASH_UNKNOWN)
177         return ERR_UNKNOWN_FLASH_TYPE;
178
179     if ((s_first < 0) || (s_first > s_last)) {
180         return ERR_INVAL;
181     }
182
183     if ((info->flash_id & FLASH_VENDMASK) !=
184         (ATM_MANUFACT & FLASH_VENDMASK)) {
185         return ERR_UNKNOWN_FLASH_VENDOR;
186     }
187
188     prot = 0;
189     for (sect=s_first; sect<=s_last; ++sect) {
190         if (info->protect[sect]) {
191             prot++;
192         }
193     }
194     if (prot)
195         return ERR_PROTECTED;
196
197     /*
198      * Disable interrupts which might cause a timeout
199      * here. Remember that our exception vectors are
200      * at address 0 in the flash, and we don't want a
201      * (ticker) exception to happen while the flash
202      * chip is in programming mode.
203      */
204     cflag = icache_status();
205     icache_disable();
206     iflag = disable_interrupts();
207
208     /* Start erase on unprotected sectors */
209     for (sect = s_first; sect<=s_last && !ctrlc(); sect++)
210     {
211         printf("Erasing sector %2d ... ", sect);
212
213         /* arm simple, non interrupt dependent timer */
214         reset_timer_masked();
215
216         if (info->protect[sect] == 0)
217         {       /* not protected */
218             volatile u16 *addr = (volatile u16 *)(info->start[sect]);
219
220             MEM_FLASH_ADDR1 = CMD_UNLOCK1;
221             MEM_FLASH_ADDR2 = CMD_UNLOCK2;
222             MEM_FLASH_ADDR1 = CMD_ERASE_SETUP;
223
224             MEM_FLASH_ADDR1 = CMD_UNLOCK1;
225             MEM_FLASH_ADDR2 = CMD_UNLOCK2;
226             *addr = CMD_ERASE_CONFIRM;
227
228             /* wait until flash is ready */
229             chip1 = 0;
230
231             do
232             {
233                 result = *addr;
234
235                 /* check timeout */
236                 if (get_timer_masked() > CFG_FLASH_ERASE_TOUT)
237                 {
238                     MEM_FLASH_ADDR1 = CMD_READ_ARRAY;
239                     chip1 = TMO;
240                     break;
241                 }
242
243                 if (!chip1 && (result & 0xFFFF) & BIT_ERASE_DONE)
244                         chip1 = READY;
245
246             }  while (!chip1);
247
248             MEM_FLASH_ADDR1 = CMD_READ_ARRAY;
249
250             if (chip1 == ERR)
251             {
252                 rc = ERR_PROG_ERROR;
253                 goto outahere;
254             }
255             if (chip1 == TMO)
256             {
257                 rc = ERR_TIMOUT;
258                 goto outahere;
259             }
260
261             printf("ok.\n");
262         }
263         else /* it was protected */
264         {
265             printf("protected!\n");
266         }
267     }
268
269     if (ctrlc())
270       printf("User Interrupt!\n");
271
272 outahere:
273     /* allow flash to settle - wait 10 ms */
274     udelay_masked(10000);
275
276     if (iflag)
277       enable_interrupts();
278
279     if (cflag)
280       icache_enable();
281
282     return rc;
283 }
284
285 /*-----------------------------------------------------------------------
286  * Copy memory to flash
287  */
288
289 volatile static int write_word (flash_info_t *info, ulong dest, ulong data)
290 {
291     volatile u16 *addr = (volatile u16 *)dest;
292     ulong result;
293     int rc = ERR_OK;
294     int cflag, iflag;
295     int chip1;
296
297     /*
298      * Check if Flash is (sufficiently) erased
299      */
300     result = *addr;
301     if ((result & data) != data)
302         return ERR_NOT_ERASED;
303
304
305     /*
306      * Disable interrupts which might cause a timeout
307      * here. Remember that our exception vectors are
308      * at address 0 in the flash, and we don't want a
309      * (ticker) exception to happen while the flash
310      * chip is in programming mode.
311      */
312     cflag = icache_status();
313     icache_disable();
314     iflag = disable_interrupts();
315
316     MEM_FLASH_ADDR1 = CMD_UNLOCK1;
317     MEM_FLASH_ADDR2 = CMD_UNLOCK2;
318     MEM_FLASH_ADDR1 = CMD_PROGRAM;
319     *addr = data;
320
321     /* arm simple, non interrupt dependent timer */
322     reset_timer_masked();
323
324     /* wait until flash is ready */
325     chip1 = 0;
326     do
327     {
328         result = *addr;
329
330         /* check timeout */
331         if (get_timer_masked() > CFG_FLASH_ERASE_TOUT)
332         {
333             chip1 = ERR | TMO;
334             break;
335         }
336         if (!chip1 && ((result & 0x80) == (data & 0x80)))
337                 chip1 = READY;
338
339     }  while (!chip1);
340
341     *addr = CMD_READ_ARRAY;
342
343     if (chip1 == ERR || *addr != data)
344         rc = ERR_PROG_ERROR;
345
346     if (iflag)
347       enable_interrupts();
348
349     if (cflag)
350       icache_enable();
351
352     return rc;
353 }
354
355 /*-----------------------------------------------------------------------
356  * Copy memory to flash.
357  */
358
359 int write_buff (flash_info_t *info, uchar *src, ulong addr, ulong cnt)
360 {
361     ulong wp, data;
362     int rc;
363
364     if(addr & 1) {
365       printf("unaligned destination not supported\n");
366       return ERR_ALIGN;
367     };
368
369     if((int)src & 1) {
370       printf("unaligned source not supported\n");
371       return ERR_ALIGN;
372     };
373
374     wp = addr;
375
376     while (cnt >= 2) {
377         data = *((volatile u16*)src);
378         if ((rc = write_word(info, wp, data)) != 0) {
379             return (rc);
380         }
381         src += 2;
382         wp  += 2;
383         cnt -= 2;
384     }
385
386     if(cnt == 1) {
387       data =  (*((volatile u8*)src)) | (*((volatile u8*)(wp+1)) << 8);
388         if ((rc = write_word(info, wp, data)) != 0) {
389             return (rc);
390         }
391         src += 1;
392         wp  += 1;
393         cnt -= 1;
394     };
395
396     return ERR_OK;
397 }