]> git.karo-electronics.de Git - karo-tx-uboot.git/blob - board/cobra5272/flash.c
merged current version of git://git.denx.de/u-boot
[karo-tx-uboot.git] / board / cobra5272 / flash.c
1 /*
2  * (C) Copyright 2000-2003
3  * Wolfgang Denk, DENX Software Engineering, wd@denx.de.
4  *
5  * See file CREDITS for list of people who contributed to this
6  * project.
7  *
8  * This program is free software; you can redistribute it and/or
9  * modify it under the terms of the GNU General Public License as
10  * published by the Free Software Foundation; either version 2 of
11  * the License, or (at your option) any later version.
12  *
13  * This program is distributed in the hope that it will be useful,
14  * but WITHOUT ANY WARRANTY; without even the implied warranty of
15  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
16  * GNU General Public License for more details.
17  *
18  * You should have received a copy of the GNU General Public License
19  * along with this program; if not, write to the Free Software
20  * Foundation, Inc., 59 Temple Place, Suite 330, Boston,
21  * MA 02111-1307 USA
22  */
23
24 #include <common.h>
25
26 #define PHYS_FLASH_1 CONFIG_SYS_FLASH_BASE
27 #define FLASH_BANK_SIZE 0x200000
28
29 flash_info_t flash_info[CONFIG_SYS_MAX_FLASH_BANKS];
30
31 void flash_print_info (flash_info_t * info)
32 {
33         int i;
34
35         switch (info->flash_id & FLASH_VENDMASK) {
36         case (AMD_MANUFACT & FLASH_VENDMASK):
37                 printf ("AMD: ");
38                 break;
39         default:
40                 printf ("Unknown Vendor ");
41                 break;
42         }
43
44         switch (info->flash_id & FLASH_TYPEMASK) {
45         case (AMD_ID_PL160CB & FLASH_TYPEMASK):
46                 printf ("AM29PL160CB (16Mbit)\n");
47                 break;
48         default:
49                 printf ("Unknown Chip Type\n");
50                 goto Done;
51                 break;
52         }
53
54         printf ("  Size: %ld MB in %d Sectors\n",
55                 info->size >> 20, info->sector_count);
56
57         printf ("  Sector Start Addresses:");
58         for (i = 0; i < info->sector_count; i++) {
59                 if ((i % 5) == 0) {
60                         printf ("\n   ");
61                 }
62                 printf (" %08lX%s", info->start[i],
63                         info->protect[i] ? " (RO)" : "     ");
64         }
65         printf ("\n");
66
67 Done:
68         return;
69 }
70
71
72 unsigned long flash_init (void)
73 {
74         int i, j;
75         ulong size = 0;
76
77         for (i = 0; i < CONFIG_SYS_MAX_FLASH_BANKS; i++) {
78                 ulong flashbase = 0;
79
80                 flash_info[i].flash_id =
81                         (AMD_MANUFACT & FLASH_VENDMASK) |
82                         (AMD_ID_PL160CB & FLASH_TYPEMASK);
83                 flash_info[i].size = FLASH_BANK_SIZE;
84                 flash_info[i].sector_count = CONFIG_SYS_MAX_FLASH_SECT;
85                 memset (flash_info[i].protect, 0, CONFIG_SYS_MAX_FLASH_SECT);
86                 if (i == 0)
87                         flashbase = PHYS_FLASH_1;
88                 else
89                         panic ("configured to many flash banks!\n");
90
91                 for (j = 0; j < flash_info[i].sector_count; j++) {
92                         if (j == 0) {
93                                 /* 1st is 16 KiB */
94                                 flash_info[i].start[j] = flashbase;
95                         }
96                         if ((j >= 1) && (j <= 2)) {
97                                 /* 2nd and 3rd are 8 KiB */
98                                 flash_info[i].start[j] =
99                                         flashbase + 0x4000 + 0x2000 * (j - 1);
100                         }
101                         if (j == 3) {
102                                 /* 4th is 224 KiB */
103                                 flash_info[i].start[j] = flashbase + 0x8000;
104                         }
105                         if ((j >= 4) && (j <= 10)) {
106                                 /* rest is 256 KiB */
107                                 flash_info[i].start[j] =
108                                         flashbase + 0x40000 + 0x40000 * (j -
109                                                                          4);
110                         }
111                 }
112                 size += flash_info[i].size;
113         }
114
115         flash_protect (FLAG_PROTECT_SET,
116                        CONFIG_SYS_FLASH_BASE,
117                        CONFIG_SYS_FLASH_BASE + 0x3ffff, &flash_info[0]);
118
119         return size;
120 }
121
122
123 #define CMD_READ_ARRAY          0x00F0
124 #define CMD_UNLOCK1             0x00AA
125 #define CMD_UNLOCK2             0x0055
126 #define CMD_ERASE_SETUP         0x0080
127 #define CMD_ERASE_CONFIRM       0x0030
128 #define CMD_PROGRAM             0x00A0
129 #define CMD_UNLOCK_BYPASS       0x0020
130
131 #define MEM_FLASH_ADDR1         (*(volatile u16 *)(CONFIG_SYS_FLASH_BASE + (0x00000555<<1)))
132 #define MEM_FLASH_ADDR2         (*(volatile u16 *)(CONFIG_SYS_FLASH_BASE + (0x000002AA<<1)))
133
134 #define BIT_ERASE_DONE          0x0080
135 #define BIT_RDY_MASK            0x0080
136 #define BIT_PROGRAM_ERROR       0x0020
137 #define BIT_TIMEOUT             0x80000000      /* our flag */
138
139 #define READY 1
140 #define ERR   2
141 #define TMO   4
142
143
144 int flash_erase (flash_info_t * info, int s_first, int s_last)
145 {
146         ulong result;
147         int iflag, cflag, prot, sect;
148         int rc = ERR_OK;
149         int chip1;
150         ulong start;
151
152         /* first look for protection bits */
153
154         if (info->flash_id == FLASH_UNKNOWN)
155                 return ERR_UNKNOWN_FLASH_TYPE;
156
157         if ((s_first < 0) || (s_first > s_last)) {
158                 return ERR_INVAL;
159         }
160
161         if ((info->flash_id & FLASH_VENDMASK) !=
162             (AMD_MANUFACT & FLASH_VENDMASK)) {
163                 return ERR_UNKNOWN_FLASH_VENDOR;
164         }
165
166         prot = 0;
167         for (sect = s_first; sect <= s_last; ++sect) {
168                 if (info->protect[sect]) {
169                         prot++;
170                 }
171         }
172         if (prot)
173                 return ERR_PROTECTED;
174
175         /*
176          * Disable interrupts which might cause a timeout
177          * here. Remember that our exception vectors are
178          * at address 0 in the flash, and we don't want a
179          * (ticker) exception to happen while the flash
180          * chip is in programming mode.
181          */
182
183         cflag = icache_status ();
184         icache_disable ();
185         iflag = disable_interrupts ();
186
187         printf ("\n");
188
189         /* Start erase on unprotected sectors */
190         for (sect = s_first; sect <= s_last && !ctrlc (); sect++) {
191                 printf ("Erasing sector %2d ... ", sect);
192
193                 /* arm simple, non interrupt dependent timer */
194                 start = get_timer(0);
195
196                 if (info->protect[sect] == 0) { /* not protected */
197                         volatile u16 *addr =
198                                 (volatile u16 *) (info->start[sect]);
199
200                         MEM_FLASH_ADDR1 = CMD_UNLOCK1;
201                         MEM_FLASH_ADDR2 = CMD_UNLOCK2;
202                         MEM_FLASH_ADDR1 = CMD_ERASE_SETUP;
203
204                         MEM_FLASH_ADDR1 = CMD_UNLOCK1;
205                         MEM_FLASH_ADDR2 = CMD_UNLOCK2;
206                         *addr = CMD_ERASE_CONFIRM;
207
208                         /* wait until flash is ready */
209                         chip1 = 0;
210
211                         do {
212                                 result = *addr;
213
214                                 /* check timeout */
215                                 if (get_timer(start) > CONFIG_SYS_FLASH_ERASE_TOUT) {
216                                         MEM_FLASH_ADDR1 = CMD_READ_ARRAY;
217                                         chip1 = TMO;
218                                         break;
219                                 }
220
221                                 if (!chip1
222                                     && (result & 0xFFFF) & BIT_ERASE_DONE)
223                                         chip1 = READY;
224
225                         } while (!chip1);
226
227                         MEM_FLASH_ADDR1 = CMD_READ_ARRAY;
228
229                         if (chip1 == ERR) {
230                                 rc = ERR_PROG_ERROR;
231                                 goto outahere;
232                         }
233                         if (chip1 == TMO) {
234                                 rc = ERR_TIMOUT;
235                                 goto outahere;
236                         }
237
238                         printf ("ok.\n");
239                 } else {        /* it was protected */
240
241                         printf ("protected!\n");
242                 }
243         }
244
245         if (ctrlc ())
246                 printf ("User Interrupt!\n");
247
248       outahere:
249         /* allow flash to settle - wait 10 ms */
250         udelay (10000);
251
252         if (iflag)
253                 enable_interrupts ();
254
255         if (cflag)
256                 icache_enable ();
257
258         return rc;
259 }
260
261 static int write_word (flash_info_t * info, ulong dest, ulong data)
262 {
263         volatile u16 *addr = (volatile u16 *) dest;
264         ulong result;
265         int rc = ERR_OK;
266         int cflag, iflag;
267         int chip1;
268         ulong start;
269
270         /*
271          * Check if Flash is (sufficiently) erased
272          */
273         result = *addr;
274         if ((result & data) != data)
275                 return ERR_NOT_ERASED;
276
277
278         /*
279          * Disable interrupts which might cause a timeout
280          * here. Remember that our exception vectors are
281          * at address 0 in the flash, and we don't want a
282          * (ticker) exception to happen while the flash
283          * chip is in programming mode.
284          */
285
286         cflag = icache_status ();
287         icache_disable ();
288         iflag = disable_interrupts ();
289
290         MEM_FLASH_ADDR1 = CMD_UNLOCK1;
291         MEM_FLASH_ADDR2 = CMD_UNLOCK2;
292         MEM_FLASH_ADDR1 = CMD_PROGRAM;
293         *addr = data;
294
295         /* arm simple, non interrupt dependent timer */
296         start = get_timer(0);
297
298         /* wait until flash is ready */
299         chip1 = 0;
300         do {
301                 result = *addr;
302
303                 /* check timeout */
304                 if (get_timer(start) > CONFIG_SYS_FLASH_ERASE_TOUT) {
305                         chip1 = ERR | TMO;
306                         break;
307                 }
308                 if (!chip1 && ((result & 0x80) == (data & 0x80)))
309                         chip1 = READY;
310
311         } while (!chip1);
312
313         *addr = CMD_READ_ARRAY;
314
315         if (chip1 == ERR || *addr != data)
316                 rc = ERR_PROG_ERROR;
317
318         if (iflag)
319                 enable_interrupts ();
320
321         if (cflag)
322                 icache_enable ();
323
324         return rc;
325 }
326
327
328 int write_buff (flash_info_t * info, uchar * src, ulong addr, ulong cnt)
329 {
330         ulong wp, data;
331         int rc;
332
333         if (addr & 1) {
334                 printf ("unaligned destination not supported\n");
335                 return ERR_ALIGN;
336         }
337
338 #if 0
339         if (cnt & 1) {
340                 printf ("odd transfer sizes not supported\n");
341                 return ERR_ALIGN;
342         }
343 #endif
344
345         wp = addr;
346
347         if (addr & 1) {
348                 data = (*((volatile u8 *) addr) << 8) | *((volatile u8 *)
349                                                           src);
350                 if ((rc = write_word (info, wp - 1, data)) != 0) {
351                         return (rc);
352                 }
353                 src += 1;
354                 wp += 1;
355                 cnt -= 1;
356         }
357
358         while (cnt >= 2) {
359                 data = *((volatile u16 *) src);
360                 if ((rc = write_word (info, wp, data)) != 0) {
361                         return (rc);
362                 }
363                 src += 2;
364                 wp += 2;
365                 cnt -= 2;
366         }
367
368         if (cnt == 1) {
369                 data = (*((volatile u8 *) src) << 8) |
370                         *((volatile u8 *) (wp + 1));
371                 if ((rc = write_word (info, wp, data)) != 0) {
372                         return (rc);
373                 }
374                 src += 1;
375                 wp += 1;
376                 cnt -= 1;
377         }
378
379         return ERR_OK;
380 }