]> git.kernelconcepts.de Git - karo-tx-uboot.git/blob - board/netstar/flash.c
Some code cleanup for GCC 4.x
[karo-tx-uboot.git] / board / netstar / flash.c
1 /*
2  * (C) Copyright 2002
3  * Sysgo Real-Time Solutions, GmbH <www.elinos.com>
4  * Alex Zuepke <azu@sysgo.de>
5  *
6  * (C) Copyright 2005
7  * 2N Telekomunikace, a.s. <www.2n.cz>
8  * Ladislav Michl <michl@2n.cz>
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 /*#if 0 */
32 #if (PHYS_SDRAM_1_SIZE != SZ_32M)
33
34 #include "crcek.h"
35
36 #if (CFG_MAX_FLASH_BANKS > 1)
37 #error There is always only _one_ flash chip
38 #endif
39
40 flash_info_t flash_info[CFG_MAX_FLASH_BANKS];
41
42 #define CMD_READ_ARRAY          0x000000f0
43 #define CMD_UNLOCK1             0x000000aa
44 #define CMD_UNLOCK2             0x00000055
45 #define CMD_ERASE_SETUP         0x00000080
46 #define CMD_ERASE_CONFIRM       0x00000030
47 #define CMD_PROGRAM             0x000000a0
48 #define CMD_UNLOCK_BYPASS       0x00000020
49
50 #define MEM_FLASH_ADDR1         (*(volatile u16 *)(CFG_FLASH_BASE + (0x00000555 << 1)))
51 #define MEM_FLASH_ADDR2         (*(volatile u16 *)(CFG_FLASH_BASE + (0x000002aa << 1)))
52
53 #define BIT_ERASE_DONE          0x00000080
54 #define BIT_RDY_MASK            0x00000080
55 #define BIT_PROGRAM_ERROR       0x00000020
56 #define BIT_TIMEOUT             0x80000000      /* our flag */
57
58 /*-----------------------------------------------------------------------
59  */
60
61 ulong flash_init(void)
62 {
63         int i;
64
65         flash_info[0].flash_id = (AMD_MANUFACT & FLASH_VENDMASK) |
66                                  (AMD_ID_LV800B & FLASH_TYPEMASK);
67         flash_info[0].size = PHYS_FLASH_1_SIZE;
68         flash_info[0].sector_count = CFG_MAX_FLASH_SECT;
69         memset(flash_info[0].protect, 0, CFG_MAX_FLASH_SECT);
70
71         for (i = 0; i < flash_info[0].sector_count; i++) {
72                 switch (i) {
73                 case 0: /* 16kB */
74                         flash_info[0].start[0] = CFG_FLASH_BASE;
75                         break;
76                 case 1: /* 8kB */
77                         flash_info[0].start[1] = CFG_FLASH_BASE + 0x4000;
78                         break;
79                 case 2: /* 8kB */
80                         flash_info[0].start[2] = CFG_FLASH_BASE + 0x4000 +
81                                                  0x2000;
82                         break;
83                 case 3: /* 32 KB */
84                         flash_info[0].start[3] = CFG_FLASH_BASE + 0x4000 +
85                                                  2 * 0x2000;
86                         break;
87                 case 4:
88                         flash_info[0].start[4] = CFG_FLASH_BASE + 0x4000 +
89                                                  2 * 0x2000 + 0x8000;
90                         break;
91                 default: /* 64kB */
92                         flash_info[0].start[i] = flash_info[0].start[i-1] +
93                                                  0x10000;
94                         break;
95                 }
96         }
97
98         /* U-Boot */
99         flash_protect(FLAG_PROTECT_SET,
100                       LOADER1_OFFSET,
101                       LOADER1_OFFSET + LOADER_SIZE - 1, flash_info);
102         /* Protect crcek, env and r_env as well */
103         flash_protect(FLAG_PROTECT_SET, 0, 0x8000 - 1, flash_info);
104
105         return flash_info[0].size;
106 }
107
108 /*-----------------------------------------------------------------------
109  */
110 void flash_print_info(flash_info_t *info)
111 {
112         int i;
113
114         switch (info->flash_id & FLASH_VENDMASK) {
115         case (AMD_MANUFACT & FLASH_VENDMASK):
116                 puts("AMD: ");
117                 break;
118         default:
119                 puts("Unknown vendor ");
120                 break;
121         }
122
123         switch (info->flash_id & FLASH_TYPEMASK) {
124         case (AMD_ID_LV800B & FLASH_TYPEMASK):
125                 puts("AM29LV800BB (8Mb)\n");
126                 break;
127         default:
128                 puts("Unknown chip type\n");
129                 return;
130         }
131
132         printf("  Size: %ld MB in %d sectors\n",
133                info->size >> 20, info->sector_count);
134
135         puts("  Sector start addresses:");
136         for (i = 0; i < info->sector_count; i++) {
137                 if ((i % 5) == 0)
138                         puts("\n   ");
139
140                 printf(" %08lX%s", info->start[i],
141                        info->protect[i] ? " (RO)" : "     ");
142         }
143         puts("\n");
144 }
145
146 /*-----------------------------------------------------------------------
147  */
148
149 int flash_erase(flash_info_t *info, int s_first, int s_last)
150 {
151         ushort result;
152         int prot, sect;
153         int rc = ERR_OK;
154
155         /* first look for protection bits */
156
157         if (info->flash_id == FLASH_UNKNOWN)
158                 return ERR_UNKNOWN_FLASH_TYPE;
159
160         if ((s_first < 0) || (s_first > s_last))
161                 return ERR_INVAL;
162
163         if ((info->flash_id & FLASH_VENDMASK) !=
164             (AMD_MANUFACT & FLASH_VENDMASK))
165                 return ERR_UNKNOWN_FLASH_VENDOR;
166
167         prot = 0;
168         for (sect = s_first; sect <= s_last; ++sect)
169                 if (info->protect[sect])
170                         prot++;
171
172         if (prot)
173                 printf("- Warning: %d protected sectors will not be erased!\n",
174                        prot);
175         else
176                 putc('\n');
177
178         /* Start erase on unprotected sectors */
179         for (sect = s_first; sect <= s_last && !ctrlc (); sect++) {
180                 if (info->protect[sect] == 0) { /* not protected */
181                         vu_short *addr = (vu_short *) (info->start[sect]);
182
183                         /* arm simple, non interrupt dependent timer */
184                         reset_timer_masked();
185
186                         MEM_FLASH_ADDR1 = CMD_UNLOCK1;
187                         MEM_FLASH_ADDR2 = CMD_UNLOCK2;
188                         MEM_FLASH_ADDR1 = CMD_ERASE_SETUP;
189
190                         MEM_FLASH_ADDR1 = CMD_UNLOCK1;
191                         MEM_FLASH_ADDR2 = CMD_UNLOCK2;
192                         *addr = CMD_ERASE_CONFIRM;
193
194                         /* wait until flash is ready */
195                         while (1) {
196                                 result = *addr;
197
198                                 /* check timeout */
199                                 if (get_timer_masked() > CFG_FLASH_ERASE_TOUT) {
200                                         MEM_FLASH_ADDR1 = CMD_READ_ARRAY;
201                                         rc = ERR_TIMOUT;
202                                         break;
203                                 }
204
205                                 if ((result & 0xfff) & BIT_ERASE_DONE)
206                                         break;
207
208                                 if ((result & 0xffff) & BIT_PROGRAM_ERROR) {
209                                         rc = ERR_PROG_ERROR;
210                                         break;
211                                 }
212                         }
213
214                         MEM_FLASH_ADDR1 = CMD_READ_ARRAY;
215
216                         if (rc != ERR_OK)
217                                 goto out;
218
219                         putc('.');
220                 }
221         }
222 out:
223         /* allow flash to settle - wait 10 ms */
224         udelay_masked(10000);
225
226         return rc;
227 }
228
229 /*-----------------------------------------------------------------------
230  * Copy memory to flash
231  */
232
233 static int write_hword(flash_info_t *info, ulong dest, ushort data)
234 {
235         vu_short *addr = (vu_short *) dest;
236         ushort result;
237         int rc = ERR_OK;
238
239         /* check if flash is (sufficiently) erased */
240         result = *addr;
241         if ((result & data) != data)
242                 return ERR_NOT_ERASED;
243
244         MEM_FLASH_ADDR1 = CMD_UNLOCK1;
245         MEM_FLASH_ADDR2 = CMD_UNLOCK2;
246         MEM_FLASH_ADDR1 = CMD_PROGRAM;
247         *addr = data;
248
249         /* arm simple, non interrupt dependent timer */
250         reset_timer_masked();
251
252         /* wait until flash is ready */
253         while (1) {
254                 result = *addr;
255
256                 /* check timeout */
257                 if (get_timer_masked () > CFG_FLASH_ERASE_TOUT) {
258                         rc = ERR_TIMOUT;
259                         break;
260                 }
261
262                 if ((result & 0x80) == (data & 0x80))
263                         break;
264
265                 if ((result & 0xffff) & BIT_PROGRAM_ERROR) {
266                         result = *addr;
267
268                         if ((result & 0x80) != (data & 0x80))
269                                 rc = ERR_PROG_ERROR;
270                 }
271         }
272
273         *addr = CMD_READ_ARRAY;
274
275         if (*addr != data)
276                 rc = ERR_PROG_ERROR;
277
278         return rc;
279 }
280
281 /*-----------------------------------------------------------------------
282  * Copy memory to flash.
283  */
284
285 int write_buff(flash_info_t *info, uchar *src, ulong addr, ulong cnt)
286 {
287         ulong cp, wp;
288         int l;
289         int i, rc;
290         ushort data;
291
292         wp = (addr & ~1);       /* get lower word aligned address */
293
294         /*
295          * handle unaligned start bytes
296          */
297         if ((l = addr - wp) != 0) {
298                 data = 0;
299                 for (i = 0, cp = wp; i < l; ++i, ++cp)
300                         data = (data >> 8) | (*(uchar *) cp << 8);
301                 for (; i < 2 && cnt > 0; ++i) {
302                         data = (data >> 8) | (*src++ << 8);
303                         --cnt;
304                         ++cp;
305                 }
306                 for (; cnt == 0 && i < 2; ++i, ++cp)
307                         data = (data >> 8) | (*(uchar *) cp << 8);
308
309                 if ((rc = write_hword(info, wp, data)) != 0)
310                         return (rc);
311                 wp += 2;
312         }
313
314         /*
315          * handle word aligned part
316          */
317         while (cnt >= 2) {
318                 data = *((vu_short *) src);
319                 if ((rc = write_hword(info, wp, data)) != 0)
320                         return (rc);
321                 src += 2;
322                 wp += 2;
323                 cnt -= 2;
324         }
325
326         if (cnt == 0)
327                 return ERR_OK;
328
329         /*
330          * handle unaligned tail bytes
331          */
332         data = 0;
333         for (i = 0, cp = wp; i < 2 && cnt > 0; ++i, ++cp) {
334                 data = (data >> 8) | (*src++ << 8);
335                 --cnt;
336         }
337         for (; i < 2; ++i, ++cp)
338                 data = (data >> 8) | (*(uchar *) cp << 8);
339
340         return write_hword(info, wp, data);
341 }
342
343 #endif