]> git.kernelconcepts.de Git - karo-tx-uboot.git/blob - board/innokom/flash.c
* Patch by Robert Schwebel, 21 Jan 2003:
[karo-tx-uboot.git] / board / innokom / 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 #ifdef CFG_ENV_IS_IN_FLASH
81         flash_protect(FLAG_PROTECT_SET,
82                         CFG_ENV_ADDR,
83                         CFG_ENV_ADDR + CFG_ENV_SIZE - 1,
84                         &flash_info[0]);
85 #endif
86
87         return size;
88 }
89
90
91 /**
92  * flash_print_info: - print information about the flash situation
93  *
94  * @param info:
95  */
96
97 void flash_print_info  (flash_info_t *info)
98 {
99         int i, j;
100
101         for (j=0; j<CFG_MAX_FLASH_BANKS; j++) {
102
103                 switch (info->flash_id & FLASH_VENDMASK) {
104
105                         case (INTEL_MANUFACT & FLASH_VENDMASK):
106                                 printf("Intel: ");
107                                 break;
108                         default:
109                                 printf("Unknown Vendor ");
110                                 break;
111                 }
112
113                 switch (info->flash_id & FLASH_TYPEMASK) {
114
115                         case (INTEL_ID_28F128J3 & FLASH_TYPEMASK):
116                                 printf("28F128J3 (128Mbit)\n");
117                                 break;
118                         default:
119                                 printf("Unknown Chip Type\n");
120                                 return;
121                 }
122
123                 printf("  Size: %ld MB in %d Sectors\n",
124                         info->size >> 20, info->sector_count);
125
126                 printf("  Sector Start Addresses:");
127                 for (i = 0; i < info->sector_count; i++) {
128                         if ((i % 5) == 0) printf ("\n   ");
129
130                         printf (" %08lX%s", info->start[i],
131                                 info->protect[i] ? " (RO)" : "     ");
132                 }
133                 printf ("\n");
134                 info++;
135         }
136 }
137
138
139 /**
140  * flash_erase: - erase flash sectors
141  *
142  */
143
144 int flash_erase(flash_info_t *info, int s_first, int s_last)
145 {
146         int flag, prot, sect;
147         int rc = ERR_OK;
148
149         if (info->flash_id == FLASH_UNKNOWN)
150                 return ERR_UNKNOWN_FLASH_TYPE;
151
152         if ((s_first < 0) || (s_first > s_last)) {
153                 return ERR_INVAL;
154         }
155
156         if ((info->flash_id & FLASH_VENDMASK) != (INTEL_MANUFACT & FLASH_VENDMASK))
157                 return ERR_UNKNOWN_FLASH_VENDOR;
158
159         prot = 0;
160         for (sect=s_first; sect<=s_last; ++sect) {
161                 if (info->protect[sect]) prot++;
162         }
163
164         if (prot) return ERR_PROTECTED;
165
166         /*
167          * Disable interrupts which might cause a timeout
168          * here. Remember that our exception vectors are
169          * at address 0 in the flash, and we don't want a
170          * (ticker) exception to happen while the flash
171          * chip is in programming mode.
172          */
173
174         flag = disable_interrupts();
175
176         /* Start erase on unprotected sectors */
177         for (sect = s_first; sect<=s_last && !ctrlc(); sect++) {
178
179                 printf("Erasing sector %2d ... ", sect);
180
181                 /* arm simple, non interrupt dependent timer */
182                 reset_timer_masked();
183
184                 if (info->protect[sect] == 0) { /* not protected */
185                         u32 * volatile addr = (u32 * volatile)(info->start[sect]);
186
187                         /* erase sector:                                    */
188                         /* The strata flashs are aligned side by side on    */
189                         /* the data bus, so we have to write the commands   */
190                         /* to both chips here:                              */
191
192                         *addr = 0x00200020;     /* erase setup */
193                         *addr = 0x00D000D0;     /* erase confirm */
194
195                         while ((*addr & 0x00800080) != 0x00800080) {
196                                 if (get_timer_masked() > CFG_FLASH_ERASE_TOUT) {
197                                         *addr = 0x00B000B0; /* suspend erase*/
198                                         *addr = 0x00FF00FF; /* read mode    */
199                                         rc = ERR_TIMOUT;
200                                         goto outahere;
201                                 }
202                         }
203
204                         *addr = 0x00500050; /* clear status register cmd.   */
205                         *addr = 0x00FF00FF; /* resest to read mode          */
206
207                 }
208
209                 printf("ok.\n");
210         }
211
212         if (ctrlc()) printf("User Interrupt!\n");
213
214         outahere:
215
216         /* allow flash to settle - wait 10 ms */
217         udelay_masked(10000);
218
219         if (flag) enable_interrupts();
220
221         return rc;
222 }
223
224
225 /**
226  * write_word: - copy memory to flash
227  *
228  * @param info:
229  * @param dest:
230  * @param data:
231  * @return:
232  */
233
234 static int write_word (flash_info_t *info, ulong dest, ushort data)
235 {
236         ushort *addr = (ushort *)dest, val;
237         int rc = ERR_OK;
238         int flag;
239
240         /* Check if Flash is (sufficiently) erased */
241         if ((*addr & data) != data) return ERR_NOT_ERASED;
242
243         /*
244          * Disable interrupts which might cause a timeout
245          * here. Remember that our exception vectors are
246          * at address 0 in the flash, and we don't want a
247          * (ticker) exception to happen while the flash
248          * chip is in programming mode.
249          */
250         flag = disable_interrupts();
251
252         /* clear status register command */
253         *addr = 0x50;
254
255         /* program set-up command */
256         *addr = 0x40;
257
258         /* latch address/data */
259         *addr = data;
260
261         /* arm simple, non interrupt dependent timer */
262         reset_timer_masked();
263
264         /* wait while polling the status register */
265         while(((val = *addr) & 0x80) != 0x80) {
266                 if (get_timer_masked() > CFG_FLASH_WRITE_TOUT) {
267                         rc = ERR_TIMOUT;
268                         *addr = 0xB0; /* suspend program command */
269                         goto outahere;
270                 }
271         }
272
273         if(val & 0x1A) {        /* check for error */
274                 printf("\nFlash write error %02x at address %08lx\n",
275                         (int)val, (unsigned long)dest);
276                 if(val & (1<<3)) {
277                         printf("Voltage range error.\n");
278                         rc = ERR_PROG_ERROR;
279                         goto outahere;
280                 }
281                 if(val & (1<<1)) {
282                         printf("Device protect error.\n");
283                         rc = ERR_PROTECTED;
284                         goto outahere;
285                 }
286                 if(val & (1<<4)) {
287                         printf("Programming error.\n");
288                         rc = ERR_PROG_ERROR;
289                         goto outahere;
290                 }
291                 rc = ERR_PROG_ERROR;
292                 goto outahere;
293         }
294
295         outahere:
296
297         *addr = 0xFF; /* read array command */
298         if (flag) enable_interrupts();
299
300         return rc;
301 }
302
303
304 /**
305  * write_buf: - Copy memory to flash.
306  *
307  * @param info:
308  * @param src:  source of copy transaction
309  * @param addr: where to copy to
310  * @param cnt:  number of bytes to copy
311  *
312  * @return      error code
313  */
314
315 int write_buff (flash_info_t *info, uchar *src, ulong addr, ulong cnt)
316 {
317         ulong cp, wp;
318         ushort data;
319         int l;
320         int i, rc;
321
322         wp = (addr & ~1);       /* get lower word aligned address */
323
324         /*
325          * handle unaligned start bytes
326          */
327         if ((l = addr - wp) != 0) {
328                 data = 0;
329                 for (i=0, cp=wp; i<l; ++i, ++cp) {
330                         data = (data >> 8) | (*(uchar *)cp << 8);
331                 }
332                 for (; i<2 && cnt>0; ++i) {
333                         data = (data >> 8) | (*src++ << 8);
334                         --cnt;
335                         ++cp;
336                 }
337                 for (; cnt==0 && i<2; ++i, ++cp) {
338                         data = (data >> 8) | (*(uchar *)cp << 8);
339                 }
340
341                 if ((rc = write_word(info, wp, data)) != 0) {
342                         return (rc);
343                 }
344                 wp += 2;
345         }
346
347         /*
348          * handle word aligned part
349          */
350         while (cnt >= 2) {
351                 /* data = *((vushort*)src); */
352                 data = *((ushort*)src);
353                 if ((rc = write_word(info, wp, data)) != 0) {
354                         return (rc);
355                 }
356                 src += 2;
357                 wp  += 2;
358                 cnt -= 2;
359         }
360
361         if (cnt == 0) return ERR_OK;
362
363         /*
364          * handle unaligned tail bytes
365          */
366         data = 0;
367         for (i=0, cp=wp; i<2 && cnt>0; ++i, ++cp) {
368                 data = (data >> 8) | (*src++ << 8);
369                 --cnt;
370         }
371         for (; i<2; ++i, ++cp) {
372                 data = (data >> 8) | (*(uchar *)cp << 8);
373         }
374
375         return write_word(info, wp, data);
376 }
377