iMX28: Add support for DENX M28EVK board
[oweals/u-boot.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  * (C) Copyright 2002
13  * Auerswald GmbH & Co KG, Germany
14  * Kai-Uwe Bloem <kai-uwe.bloem@auerswald.de>
15  *
16  * See file CREDITS for list of people who contributed to this
17  * project.
18  *
19  * This program is free software; you can redistribute it and/or
20  * modify it under the terms of the GNU General Public License as
21  * published by the Free Software Foundation; either version 2 of
22  * the License, or (at your option) any later version.
23  *
24  * This program is distributed in the hope that it will be useful,
25  * but WITHOUT ANY WARRANTY; without even the implied warranty of
26  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
27  * GNU General Public License for more details.
28  *
29  * You should have received a copy of the GNU General Public License
30  * along with this program; if not, write to the Free Software
31  * Foundation, Inc., 59 Temple Place, Suite 330, Boston,
32  * MA 02111-1307 USA
33  */
34
35 #include <common.h>
36 #include <asm/arch/pxa-regs.h>
37
38 /* Debugging macros ------------------------------------------------------  */
39
40 #undef FLASH_DEBUG
41
42 /* Some debug macros */
43 #if (FLASH_DEBUG > 2 )
44 #define PRINTK3(args...) printf(args)
45 #else
46 #define PRINTK3(args...)
47 #endif
48
49 #if FLASH_DEBUG > 1
50 #define PRINTK2(args...) printf(args)
51 #else
52 #define PRINTK2(args...)
53 #endif
54
55 #ifdef FLASH_DEBUG
56 #define PRINTK(args...) printf(args)
57 #else
58 #define PRINTK(args...)
59 #endif
60
61 /* ------------------------------------------------------------------------ */
62
63 /* Development system: we have only 16 MB Flash                             */
64 #ifdef CONFIG_MTD_INNOKOM_16MB
65 #define FLASH_BANK_SIZE 0x01000000      /* 16 MB (during development)       */
66 #define MAIN_SECT_SIZE  0x00020000      /* 128k per sector                  */
67 #endif
68
69 /* Production system: we have 64 MB Flash                                   */
70 #ifdef CONFIG_MTD_INNOKOM_64MB
71 #define FLASH_BANK_SIZE 0x04000000      /* 64 MB                            */
72 #define MAIN_SECT_SIZE  0x00020000      /* 128k per sector                  */
73 #endif
74
75 flash_info_t    flash_info[CONFIG_SYS_MAX_FLASH_BANKS];
76
77 /**
78  * flash_init: - initialize data structures for flash chips
79  *
80  * @return: size of the flash
81  */
82
83 ulong flash_init(void)
84 {
85         int i, j;
86         ulong size = 0;
87
88         for (i = 0; i < CONFIG_SYS_MAX_FLASH_BANKS; i++) {
89                 ulong flashbase = 0;
90                 flash_info[i].flash_id =
91                         (INTEL_MANUFACT & FLASH_VENDMASK) |
92                         (INTEL_ID_28F128J3 & FLASH_TYPEMASK);
93                 flash_info[i].size = FLASH_BANK_SIZE;
94                 flash_info[i].sector_count = CONFIG_SYS_MAX_FLASH_SECT;
95                 memset(flash_info[i].protect, 0, CONFIG_SYS_MAX_FLASH_SECT);
96
97                 switch (i) {
98                         case 0:
99                                 flashbase = PHYS_FLASH_1;
100                                 break;
101                         default:
102                                 panic("configured too many flash banks!\n");
103                                 break;
104                 }
105                 for (j = 0; j < flash_info[i].sector_count; j++) {
106                         flash_info[i].start[j] = flashbase + j*MAIN_SECT_SIZE;
107                 }
108                 size += flash_info[i].size;
109         }
110
111         /* Protect u-boot sectors */
112         flash_protect(FLAG_PROTECT_SET,
113                         CONFIG_SYS_FLASH_BASE,
114                         CONFIG_SYS_FLASH_BASE + (256*1024) - 1,
115                         &flash_info[0]);
116
117 #ifdef CONFIG_ENV_IS_IN_FLASH
118         flash_protect(FLAG_PROTECT_SET,
119                         CONFIG_ENV_ADDR,
120                         CONFIG_ENV_ADDR + CONFIG_ENV_SIZE - 1,
121                         &flash_info[0]);
122 #endif
123
124         return size;
125 }
126
127
128 /**
129  * flash_print_info: - print information about the flash situation
130  *
131  * @param info:
132  */
133
134 void flash_print_info  (flash_info_t *info)
135 {
136         int i, j;
137
138         for (j=0; j<CONFIG_SYS_MAX_FLASH_BANKS; j++) {
139
140                 switch (info->flash_id & FLASH_VENDMASK) {
141
142                         case (INTEL_MANUFACT & FLASH_VENDMASK):
143                                 printf("Intel: ");
144                                 break;
145                         default:
146                                 printf("Unknown Vendor ");
147                                 break;
148                 }
149
150                 switch (info->flash_id & FLASH_TYPEMASK) {
151
152                         case (INTEL_ID_28F128J3 & FLASH_TYPEMASK):
153                                 printf("28F128J3 (128Mbit)\n");
154                                 break;
155                         default:
156                                 printf("Unknown Chip Type\n");
157                                 return;
158                 }
159
160                 printf("  Size: %ld MB in %d Sectors\n",
161                         info->size >> 20, info->sector_count);
162
163                 printf("  Sector Start Addresses:");
164                 for (i = 0; i < info->sector_count; i++) {
165                         if ((i % 5) == 0) printf ("\n   ");
166
167                         printf (" %08lX%s", info->start[i],
168                                 info->protect[i] ? " (RO)" : "     ");
169                 }
170                 printf ("\n");
171                 info++;
172         }
173 }
174
175
176 /**
177  * flash_erase: - erase flash sectors
178  *
179  */
180
181 int flash_erase(flash_info_t *info, int s_first, int s_last)
182 {
183         int flag, prot, sect;
184         int rc = ERR_OK;
185         ulong start;
186
187         if (info->flash_id == FLASH_UNKNOWN)
188                 return ERR_UNKNOWN_FLASH_TYPE;
189
190         if ((s_first < 0) || (s_first > s_last)) {
191                 return ERR_INVAL;
192         }
193
194         if ((info->flash_id & FLASH_VENDMASK) != (INTEL_MANUFACT & FLASH_VENDMASK))
195                 return ERR_UNKNOWN_FLASH_VENDOR;
196
197         prot = 0;
198         for (sect=s_first; sect<=s_last; ++sect) {
199                 if (info->protect[sect]) prot++;
200         }
201
202         if (prot) return ERR_PROTECTED;
203
204         /*
205          * Disable interrupts which might cause a timeout
206          * here. Remember that our exception vectors are
207          * at address 0 in the flash, and we don't want a
208          * (ticker) exception to happen while the flash
209          * chip is in programming mode.
210          */
211
212         flag = disable_interrupts();
213
214         /* Start erase on unprotected sectors */
215         for (sect = s_first; sect<=s_last && !ctrlc(); sect++) {
216
217                 printf("Erasing sector %2d ... ", sect);
218
219                 PRINTK("\n");
220
221                 /* arm simple, non interrupt dependent timer */
222                 start = get_timer(0);
223
224                 if (info->protect[sect] == 0) { /* not protected */
225                         u16 * volatile addr = (u16 * volatile)(info->start[sect]);
226
227                         PRINTK("unlocking sector\n");
228                         *addr = 0x0060;
229                         *addr = 0x00d0;
230                         *addr = 0x00ff;
231
232                         PRINTK("erasing sector\n");
233                         *addr = 0x0020;
234                         PRINTK("confirming erase\n");
235                         *addr = 0x00D0;
236
237                         while ((*addr & 0x0080) != 0x0080) {
238                                 PRINTK(".");
239                                 if (get_timer(start) > CONFIG_SYS_FLASH_ERASE_TOUT) {
240                                         *addr = 0x00B0; /* suspend erase*/
241                                         *addr = 0x00FF; /* read mode    */
242                                         rc = ERR_TIMOUT;
243                                         goto outahere;
244                                 }
245                         }
246
247                         PRINTK("clearing status register\n");
248                         *addr = 0x0050;
249                         PRINTK("resetting to read mode");
250                         *addr = 0x00FF;
251                 }
252
253                 printf("ok.\n");
254         }
255
256         if (ctrlc()) printf("User Interrupt!\n");
257
258         outahere:
259
260         /* allow flash to settle - wait 10 ms */
261         udelay_masked(10000);
262
263         if (flag) enable_interrupts();
264
265         return rc;
266 }
267
268
269 /**
270  * write_word: - copy memory to flash
271  *
272  * @param info:
273  * @param dest:
274  * @param data:
275  * @return:
276  */
277
278 static int write_word (flash_info_t *info, ulong dest, ushort data)
279 {
280         volatile u16 *addr = (u16 *)dest, val;
281         int rc = ERR_OK;
282         int flag;
283         ulong start;
284
285         /* Check if Flash is (sufficiently) erased */
286         if ((*addr & data) != data) return ERR_NOT_ERASED;
287
288         /*
289          * Disable interrupts which might cause a timeout
290          * here. Remember that our exception vectors are
291          * at address 0 in the flash, and we don't want a
292          * (ticker) exception to happen while the flash
293          * chip is in programming mode.
294          */
295         flag = disable_interrupts();
296
297         /* clear status register command */
298         *addr = 0x50;
299
300         /* program set-up command */
301         *addr = 0x40;
302
303         /* latch address/data */
304         *addr = data;
305
306         /* arm simple, non interrupt dependent timer */
307         start = get_timer(0);
308
309         /* wait while polling the status register */
310         while(((val = *addr) & 0x80) != 0x80) {
311                 if (get_timer(start) > CONFIG_SYS_FLASH_WRITE_TOUT) {
312                         rc = ERR_TIMOUT;
313                         *addr = 0xB0; /* suspend program command */
314                         goto outahere;
315                 }
316         }
317
318         if(val & 0x1A) {        /* check for error */
319                 printf("\nFlash write error %02x at address %08lx\n",
320                         (int)val, (unsigned long)dest);
321                 if(val & (1<<3)) {
322                         printf("Voltage range error.\n");
323                         rc = ERR_PROG_ERROR;
324                         goto outahere;
325                 }
326                 if(val & (1<<1)) {
327                         printf("Device protect error.\n");
328                         rc = ERR_PROTECTED;
329                         goto outahere;
330                 }
331                 if(val & (1<<4)) {
332                         printf("Programming error.\n");
333                         rc = ERR_PROG_ERROR;
334                         goto outahere;
335                 }
336                 rc = ERR_PROG_ERROR;
337                 goto outahere;
338         }
339
340         outahere:
341
342         *addr = 0xFF; /* read array command */
343         if (flag) enable_interrupts();
344
345         return rc;
346 }
347
348
349 /**
350  * write_buf: - Copy memory to flash.
351  *
352  * @param info:
353  * @param src:  source of copy transaction
354  * @param addr: where to copy to
355  * @param cnt:  number of bytes to copy
356  *
357  * @return      error code
358  */
359
360 int write_buff (flash_info_t *info, uchar *src, ulong addr, ulong cnt)
361 {
362         ulong cp, wp;
363         ushort data;
364         int l;
365         int i, rc;
366
367         wp = (addr & ~1);       /* get lower word aligned address */
368
369         /*
370          * handle unaligned start bytes
371          */
372         if ((l = addr - wp) != 0) {
373                 data = 0;
374                 for (i=0, cp=wp; i<l; ++i, ++cp) {
375                         data = (data >> 8) | (*(uchar *)cp << 8);
376                 }
377                 for (; i<2 && cnt>0; ++i) {
378                         data = (data >> 8) | (*src++ << 8);
379                         --cnt;
380                         ++cp;
381                 }
382                 for (; cnt==0 && i<2; ++i, ++cp) {
383                         data = (data >> 8) | (*(uchar *)cp << 8);
384                 }
385
386                 if ((rc = write_word(info, wp, data)) != 0) {
387                         return (rc);
388                 }
389                 wp += 2;
390         }
391
392         /*
393          * handle word aligned part
394          */
395         while (cnt >= 2) {
396                 /* data = *((vushort*)src); */
397                 data = *((ushort*)src);
398                 if ((rc = write_word(info, wp, data)) != 0) {
399                         return (rc);
400                 }
401                 src += 2;
402                 wp  += 2;
403                 cnt -= 2;
404         }
405
406         if (cnt == 0) return ERR_OK;
407
408         /*
409          * handle unaligned tail bytes
410          */
411         data = 0;
412         for (i=0, cp=wp; i<2 && cnt>0; ++i, ++cp) {
413                 data = (data >> 8) | (*src++ << 8);
414                 --cnt;
415         }
416         for (; i<2; ++i, ++cp) {
417                 data = (data >> 8) | (*(uchar *)cp << 8);
418         }
419
420         return write_word(info, wp, data);
421 }