GCC4.6: Squash warning in cmd_nvedit.c
[profile/mobile/platform/kernel/u-boot-tm1.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
186         if (info->flash_id == FLASH_UNKNOWN)
187                 return ERR_UNKNOWN_FLASH_TYPE;
188
189         if ((s_first < 0) || (s_first > s_last)) {
190                 return ERR_INVAL;
191         }
192
193         if ((info->flash_id & FLASH_VENDMASK) != (INTEL_MANUFACT & FLASH_VENDMASK))
194                 return ERR_UNKNOWN_FLASH_VENDOR;
195
196         prot = 0;
197         for (sect=s_first; sect<=s_last; ++sect) {
198                 if (info->protect[sect]) prot++;
199         }
200
201         if (prot) return ERR_PROTECTED;
202
203         /*
204          * Disable interrupts which might cause a timeout
205          * here. Remember that our exception vectors are
206          * at address 0 in the flash, and we don't want a
207          * (ticker) exception to happen while the flash
208          * chip is in programming mode.
209          */
210
211         flag = disable_interrupts();
212
213         /* Start erase on unprotected sectors */
214         for (sect = s_first; sect<=s_last && !ctrlc(); sect++) {
215
216                 printf("Erasing sector %2d ... ", sect);
217
218                 PRINTK("\n");
219
220                 /* arm simple, non interrupt dependent timer */
221                 reset_timer_masked();
222
223                 if (info->protect[sect] == 0) { /* not protected */
224                         u16 * volatile addr = (u16 * volatile)(info->start[sect]);
225
226                         PRINTK("unlocking sector\n");
227                         *addr = 0x0060;
228                         *addr = 0x00d0;
229                         *addr = 0x00ff;
230
231                         PRINTK("erasing sector\n");
232                         *addr = 0x0020;
233                         PRINTK("confirming erase\n");
234                         *addr = 0x00D0;
235
236                         while ((*addr & 0x0080) != 0x0080) {
237                                 PRINTK(".");
238                                 if (get_timer_masked() > CONFIG_SYS_FLASH_ERASE_TOUT) {
239                                         *addr = 0x00B0; /* suspend erase*/
240                                         *addr = 0x00FF; /* read mode    */
241                                         rc = ERR_TIMOUT;
242                                         goto outahere;
243                                 }
244                         }
245
246                         PRINTK("clearing status register\n");
247                         *addr = 0x0050;
248                         PRINTK("resetting to read mode");
249                         *addr = 0x00FF;
250                 }
251
252                 printf("ok.\n");
253         }
254
255         if (ctrlc()) printf("User Interrupt!\n");
256
257         outahere:
258
259         /* allow flash to settle - wait 10 ms */
260         udelay_masked(10000);
261
262         if (flag) enable_interrupts();
263
264         return rc;
265 }
266
267
268 /**
269  * write_word: - copy memory to flash
270  *
271  * @param info:
272  * @param dest:
273  * @param data:
274  * @return:
275  */
276
277 static int write_word (flash_info_t *info, ulong dest, ushort data)
278 {
279         volatile u16 *addr = (u16 *)dest, val;
280         int rc = ERR_OK;
281         int flag;
282
283         /* Check if Flash is (sufficiently) erased */
284         if ((*addr & data) != data) return ERR_NOT_ERASED;
285
286         /*
287          * Disable interrupts which might cause a timeout
288          * here. Remember that our exception vectors are
289          * at address 0 in the flash, and we don't want a
290          * (ticker) exception to happen while the flash
291          * chip is in programming mode.
292          */
293         flag = disable_interrupts();
294
295         /* clear status register command */
296         *addr = 0x50;
297
298         /* program set-up command */
299         *addr = 0x40;
300
301         /* latch address/data */
302         *addr = data;
303
304         /* arm simple, non interrupt dependent timer */
305         reset_timer_masked();
306
307         /* wait while polling the status register */
308         while(((val = *addr) & 0x80) != 0x80) {
309                 if (get_timer_masked() > CONFIG_SYS_FLASH_WRITE_TOUT) {
310                         rc = ERR_TIMOUT;
311                         *addr = 0xB0; /* suspend program command */
312                         goto outahere;
313                 }
314         }
315
316         if(val & 0x1A) {        /* check for error */
317                 printf("\nFlash write error %02x at address %08lx\n",
318                         (int)val, (unsigned long)dest);
319                 if(val & (1<<3)) {
320                         printf("Voltage range error.\n");
321                         rc = ERR_PROG_ERROR;
322                         goto outahere;
323                 }
324                 if(val & (1<<1)) {
325                         printf("Device protect error.\n");
326                         rc = ERR_PROTECTED;
327                         goto outahere;
328                 }
329                 if(val & (1<<4)) {
330                         printf("Programming error.\n");
331                         rc = ERR_PROG_ERROR;
332                         goto outahere;
333                 }
334                 rc = ERR_PROG_ERROR;
335                 goto outahere;
336         }
337
338         outahere:
339
340         *addr = 0xFF; /* read array command */
341         if (flag) enable_interrupts();
342
343         return rc;
344 }
345
346
347 /**
348  * write_buf: - Copy memory to flash.
349  *
350  * @param info:
351  * @param src:  source of copy transaction
352  * @param addr: where to copy to
353  * @param cnt:  number of bytes to copy
354  *
355  * @return      error code
356  */
357
358 int write_buff (flash_info_t *info, uchar *src, ulong addr, ulong cnt)
359 {
360         ulong cp, wp;
361         ushort data;
362         int l;
363         int i, rc;
364
365         wp = (addr & ~1);       /* get lower word aligned address */
366
367         /*
368          * handle unaligned start bytes
369          */
370         if ((l = addr - wp) != 0) {
371                 data = 0;
372                 for (i=0, cp=wp; i<l; ++i, ++cp) {
373                         data = (data >> 8) | (*(uchar *)cp << 8);
374                 }
375                 for (; i<2 && cnt>0; ++i) {
376                         data = (data >> 8) | (*src++ << 8);
377                         --cnt;
378                         ++cp;
379                 }
380                 for (; cnt==0 && i<2; ++i, ++cp) {
381                         data = (data >> 8) | (*(uchar *)cp << 8);
382                 }
383
384                 if ((rc = write_word(info, wp, data)) != 0) {
385                         return (rc);
386                 }
387                 wp += 2;
388         }
389
390         /*
391          * handle word aligned part
392          */
393         while (cnt >= 2) {
394                 /* data = *((vushort*)src); */
395                 data = *((ushort*)src);
396                 if ((rc = write_word(info, wp, data)) != 0) {
397                         return (rc);
398                 }
399                 src += 2;
400                 wp  += 2;
401                 cnt -= 2;
402         }
403
404         if (cnt == 0) return ERR_OK;
405
406         /*
407          * handle unaligned tail bytes
408          */
409         data = 0;
410         for (i=0, cp=wp; i<2 && cnt>0; ++i, ++cp) {
411                 data = (data >> 8) | (*src++ << 8);
412                 --cnt;
413         }
414         for (; i<2; ++i, ++cp) {
415                 data = (data >> 8) | (*(uchar *)cp << 8);
416         }
417
418         return write_word(info, wp, data);
419 }