]> git.kernelconcepts.de Git - karo-tx-uboot.git/blob - board/csb226/flash.c
* Patches by Robert Schwebel, 06 Mar 2003:
[karo-tx-uboot.git] / board / csb226 / flash.c
1 /*
2  * (C) Copyright 2002
3  * Kyle Harris, Nexus Technologies, Inc. kharris@nexus-tech.net
4  *
5  * (C) Copyright 2002
6  * Sysgo Real-Time Solutions, GmbH <www.elinos.com>
7  * Marius Groeger <mgroeger@sysgo.de>
8  *
9  * (C) Copyright 2002
10  * Robert Schwebel, Pengutronix, <r.schwebel@pengutronix.de> 
11  *
12  * See file CREDITS for list of people who contributed to this
13  * project.
14  *
15  * This program is free software; you can redistribute it and/or
16  * modify it under the terms of the GNU General Public License as
17  * published by the Free Software Foundation; either version 2 of
18  * the License, or (at your option) any later version.
19  *
20  * This program is distributed in the hope that it will be useful,
21  * but WITHOUT ANY WARRANTY; without even the implied warranty of
22  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
23  * GNU General Public License for more details.
24  *
25  * You should have received a copy of the GNU General Public License
26  * along with this program; if not, write to the Free Software
27  * Foundation, Inc., 59 Temple Place, Suite 330, Boston,
28  * MA 02111-1307 USA
29  */
30
31 #include <common.h>
32 #include <asm/arch/pxa-regs.h>
33
34 #define FLASH_BANK_SIZE 0x02000000
35 #define MAIN_SECT_SIZE  0x40000         /* 2x16 = 256k per sector */
36
37 flash_info_t    flash_info[CFG_MAX_FLASH_BANKS];
38
39
40 /**
41  * flash_init: - initialize data structures for flash chips
42  *
43  * @return: size of the flash
44  */
45
46 ulong flash_init(void)
47 {
48         int i, j;
49         ulong size = 0;
50
51         for (i = 0; i < CFG_MAX_FLASH_BANKS; i++) {
52                 ulong flashbase = 0;
53                 flash_info[i].flash_id =
54                         (INTEL_MANUFACT & FLASH_VENDMASK) |
55                         (INTEL_ID_28F128J3 & FLASH_TYPEMASK);
56                 flash_info[i].size = FLASH_BANK_SIZE;
57                 flash_info[i].sector_count = CFG_MAX_FLASH_SECT;
58                 memset(flash_info[i].protect, 0, CFG_MAX_FLASH_SECT);
59
60                 switch (i) {
61                         case 0:
62                                 flashbase = PHYS_FLASH_1;
63                                 break;
64                         default:
65                                 panic("configured to many flash banks!\n");
66                                 break;
67                 }
68                 for (j = 0; j < flash_info[i].sector_count; j++) {
69                         flash_info[i].start[j] = flashbase + j*MAIN_SECT_SIZE;
70                 }
71                 size += flash_info[i].size;
72         }
73
74         /* Protect monitor and environment sectors */
75         flash_protect(FLAG_PROTECT_SET,
76                         CFG_FLASH_BASE,
77                         CFG_FLASH_BASE + _armboot_end_data - _armboot_start,
78                         &flash_info[0]);
79
80         flash_protect(FLAG_PROTECT_SET,
81                         CFG_ENV_ADDR,
82                         CFG_ENV_ADDR + CFG_ENV_SIZE - 1,
83                         &flash_info[0]);
84
85         return size;
86 }
87
88
89 /**
90  * flash_print_info: - print information about the flash situation
91  *
92  * @param info: 
93  */
94
95 void flash_print_info  (flash_info_t *info)
96 {
97         int i, j;
98
99         for (j=0; j<CFG_MAX_FLASH_BANKS; j++) {
100
101                 switch (info->flash_id & FLASH_VENDMASK) {
102
103                         case (INTEL_MANUFACT & FLASH_VENDMASK):
104                                 printf("Intel: ");
105                                 break;
106                         default:
107                                 printf("Unknown Vendor ");
108                                 break;
109                 }
110
111                 switch (info->flash_id & FLASH_TYPEMASK) {
112
113                         case (INTEL_ID_28F128J3 & FLASH_TYPEMASK):
114                                 printf("28F128J3 (128Mbit)\n");
115                                 break;
116                         default:
117                                 printf("Unknown Chip Type\n");
118                                 return;
119                 }
120
121                 printf("  Size: %ld MB in %d Sectors\n", 
122                         info->size >> 20, info->sector_count);
123
124                 printf("  Sector Start Addresses:");
125                 for (i = 0; i < info->sector_count; i++) {
126                         if ((i % 5) == 0) printf ("\n   ");
127                 
128                         printf (" %08lX%s", info->start[i],
129                                 info->protect[i] ? " (RO)" : "     ");
130                 }
131                 printf ("\n");
132                 info++;
133         }
134 }
135
136
137 /**
138  * flash_erase: - erase flash sectors
139  *
140  */
141
142 int flash_erase(flash_info_t *info, int s_first, int s_last)
143 {
144         int flag, prot, sect;
145         int rc = ERR_OK;
146
147         if (info->flash_id == FLASH_UNKNOWN)
148                 return ERR_UNKNOWN_FLASH_TYPE;
149
150         if ((s_first < 0) || (s_first > s_last)) {
151                 return ERR_INVAL;
152         }
153
154         if ((info->flash_id & FLASH_VENDMASK) != (INTEL_MANUFACT & FLASH_VENDMASK))
155                 return ERR_UNKNOWN_FLASH_VENDOR;
156         
157         prot = 0;
158         for (sect=s_first; sect<=s_last; ++sect) {
159                 if (info->protect[sect]) prot++;
160         }
161
162         if (prot) return ERR_PROTECTED;
163
164         /*
165          * Disable interrupts which might cause a timeout
166          * here. Remember that our exception vectors are
167          * at address 0 in the flash, and we don't want a
168          * (ticker) exception to happen while the flash
169          * chip is in programming mode.
170          */
171
172         flag = disable_interrupts();
173
174         /* Start erase on unprotected sectors */
175         for (sect = s_first; sect<=s_last && !ctrlc(); sect++) {
176
177                 printf("Erasing sector %2d ... ", sect);
178
179                 /* arm simple, non interrupt dependent timer */
180                 reset_timer_masked();
181
182                 if (info->protect[sect] == 0) { /* not protected */
183                         u32 * volatile addr = (u32 * volatile)(info->start[sect]);
184
185                         /* erase sector:                                    */
186                         /* The strata flashs are aligned side by side on    */
187                         /* the data bus, so we have to write the commands   */
188                         /* to both chips here:                              */
189
190                         *addr = 0x00200020;     /* erase setup */
191                         *addr = 0x00D000D0;     /* erase confirm */
192
193                         while ((*addr & 0x00800080) != 0x00800080) {
194                                 if (get_timer_masked() > CFG_FLASH_ERASE_TOUT) {
195                                         *addr = 0x00B000B0; /* suspend erase*/
196                                         *addr = 0x00FF00FF; /* read mode    */
197                                         rc = ERR_TIMOUT;
198                                         goto outahere;
199                                 }
200                         }
201
202                         *addr = 0x00500050; /* clear status register cmd.   */
203                         *addr = 0x00FF00FF; /* resest to read mode          */
204
205                 }
206                 
207                 printf("ok.\n");
208         }
209
210         if (ctrlc()) printf("User Interrupt!\n");
211
212         outahere:
213
214         /* allow flash to settle - wait 10 ms */
215         udelay_masked(10000);
216
217         if (flag) enable_interrupts();
218
219         return rc;
220 }
221
222
223 /**
224  * write_word: - copy memory to flash
225  * 
226  * @param info:
227  * @param dest:
228  * @param data: 
229  * @return:
230  */
231
232 static int write_word (flash_info_t *info, ulong dest, ushort data)
233 {
234         u32 * volatile addr = (u32 * volatile)dest, val;
235         int rc = ERR_OK;
236         int flag;
237
238         /* Check if Flash is (sufficiently) erased */
239         if ((*addr & data) != data) return ERR_NOT_ERASED;
240
241         /*
242          * Disable interrupts which might cause a timeout
243          * here. Remember that our exception vectors are
244          * at address 0 in the flash, and we don't want a
245          * (ticker) exception to happen while the flash
246          * chip is in programming mode.
247          */
248         flag = disable_interrupts();
249
250         /* clear status register command */
251         *addr = 0x50;
252
253         /* program set-up command */
254         *addr = 0x40;
255
256         /* latch address/data */
257         *addr = data;
258
259         /* arm simple, non interrupt dependent timer */
260         reset_timer_masked();
261
262         /* wait while polling the status register */
263         while(((val = *addr) & 0x80) != 0x80) {
264                 if (get_timer_masked() > CFG_FLASH_WRITE_TOUT) {
265                         rc = ERR_TIMOUT;
266                         *addr = 0xB0; /* suspend program command */
267                         goto outahere;
268                 }
269         }
270
271         if(val & 0x1A) {        /* check for error */
272                 printf("\nFlash write error %02x at address %08lx\n",
273                         (int)val, (unsigned long)dest);
274                 if(val & (1<<3)) {
275                         printf("Voltage range error.\n");
276                         rc = ERR_PROG_ERROR;
277                         goto outahere;
278                 }
279                 if(val & (1<<1)) {
280                         printf("Device protect error.\n");
281                         rc = ERR_PROTECTED;
282                         goto outahere;
283                 }
284                 if(val & (1<<4)) {
285                         printf("Programming error.\n");
286                         rc = ERR_PROG_ERROR;
287                         goto outahere;
288                 }
289                 rc = ERR_PROG_ERROR;
290                 goto outahere;
291         }
292
293         outahere:
294
295         *addr = 0xFF; /* read array command */
296         if (flag) enable_interrupts();
297
298         return rc;
299 }
300
301
302 /**
303  * write_buf: - Copy memory to flash.
304  * 
305  * @param info:  
306  * @param src:  source of copy transaction
307  * @param addr: where to copy to
308  * @param cnt:  number of bytes to copy
309  *
310  * @return      error code
311  */
312
313 int write_buff (flash_info_t *info, uchar *src, ulong addr, ulong cnt)
314 {
315         ulong cp, wp;
316         ushort data;
317         int l;
318         int i, rc;
319
320         wp = (addr & ~1);       /* get lower word aligned address */
321
322         /*
323          * handle unaligned start bytes
324          */
325         if ((l = addr - wp) != 0) {
326                 data = 0;
327                 for (i=0, cp=wp; i<l; ++i, ++cp) {
328                         data = (data >> 8) | (*(uchar *)cp << 8);
329                 }
330                 for (; i<2 && cnt>0; ++i) {
331                         data = (data >> 8) | (*src++ << 8);
332                         --cnt;
333                         ++cp;
334                 }
335                 for (; cnt==0 && i<2; ++i, ++cp) {
336                         data = (data >> 8) | (*(uchar *)cp << 8);
337                 }
338
339                 if ((rc = write_word(info, wp, data)) != 0) {
340                         return (rc);
341                 }
342                 wp += 2;
343         }
344
345         /*
346          * handle word aligned part
347          */
348         while (cnt >= 2) {
349                 /* data = *((vushort*)src); */
350                 data = *((ushort*)src);
351                 if ((rc = write_word(info, wp, data)) != 0) {
352                         return (rc);
353                 }
354                 src += 2;
355                 wp  += 2;
356                 cnt -= 2;
357         }
358
359         if (cnt == 0) return ERR_OK;
360
361         /*
362          * handle unaligned tail bytes
363          */
364         data = 0;
365         for (i=0, cp=wp; i<2 && cnt>0; ++i, ++cp) {
366                 data = (data >> 8) | (*src++ << 8);
367                 --cnt;
368         }
369         for (; i<2; ++i, ++cp) {
370                 data = (data >> 8) | (*(uchar *)cp << 8);
371         }
372
373         return write_word(info, wp, data);
374 }
375