arm: nvidia and smdk6400: use common code for machine type
[oweals/u-boot.git] / board / shannon / flash.c
1 /*
2  * (C) Copyright 2002
3  * Sysgo Real-Time Solutions, GmbH <www.elinos.com>
4  * Alex Zuepke <azu@sysgo.de>
5  *
6  * See file CREDITS for list of people who contributed to this
7  * project.
8  *
9  * This program is free software; you can redistribute it and/or
10  * modify it under the terms of the GNU General Public License as
11  * published by the Free Software Foundation; either version 2 of
12  * the License, or (at your option) any later version.
13  *
14  * This program is distributed in the hope that it will be useful,
15  * but WITHOUT ANY WARRANTY; without even the implied warranty of
16  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
17  * GNU General Public License for more details.
18  *
19  * You should have received a copy of the GNU General Public License
20  * along with this program; if not, write to the Free Software
21  * Foundation, Inc., 59 Temple Place, Suite 330, Boston,
22  * MA 02111-1307 USA
23  */
24
25 #include <common.h>
26
27 ulong myflush(void);
28
29
30 #define FLASH_BANK_SIZE 0x400000        /* 4 MB */
31 #define MAIN_SECT_SIZE  0x20000         /* 128 KB */
32
33 flash_info_t    flash_info[CONFIG_SYS_MAX_FLASH_BANKS];
34
35
36 #define CMD_READ_ARRAY          0x00F000F0
37 #define CMD_UNLOCK1             0x00AA00AA
38 #define CMD_UNLOCK2             0x00550055
39 #define CMD_ERASE_SETUP         0x00800080
40 #define CMD_ERASE_CONFIRM       0x00300030
41 #define CMD_PROGRAM             0x00A000A0
42 #define CMD_UNLOCK_BYPASS       0x00200020
43
44 #define MEM_FLASH_ADDR1         (*(volatile u32 *)(CONFIG_SYS_FLASH_BASE + (0x00000555 << 2)))
45 #define MEM_FLASH_ADDR2         (*(volatile u32 *)(CONFIG_SYS_FLASH_BASE + (0x000002AA << 2)))
46
47 #define BIT_ERASE_DONE          0x00800080
48 #define BIT_RDY_MASK            0x00800080
49 #define BIT_PROGRAM_ERROR       0x00200020
50 #define BIT_TIMEOUT             0x80000000 /* our flag */
51
52 #define READY 1
53 #define ERR   2
54 #define TMO   4
55
56 /*-----------------------------------------------------------------------
57  */
58
59 ulong flash_init(void)
60 {
61     int i, j;
62     ulong size = 0;
63
64     for (i = 0; i < CONFIG_SYS_MAX_FLASH_BANKS; i++)
65     {
66         ulong flashbase = 0;
67         flash_info[i].flash_id =
68           (AMD_MANUFACT & FLASH_VENDMASK) |
69           (AMD_ID_LV160B & FLASH_TYPEMASK);
70         flash_info[i].size = FLASH_BANK_SIZE;
71         flash_info[i].sector_count = CONFIG_SYS_MAX_FLASH_SECT;
72         memset(flash_info[i].protect, 0, CONFIG_SYS_MAX_FLASH_SECT);
73         if (i == 0)
74           flashbase = PHYS_FLASH_1;
75         else
76           panic("configured too many flash banks!\n");
77         for (j = 0; j < flash_info[i].sector_count; j++)
78         {
79
80             if (j <= 3)
81             {
82                 /* 1st one is 32 KB */
83                 if (j == 0)
84                 {
85                         flash_info[i].start[j] = flashbase + 0;
86                 }
87
88                 /* 2nd and 3rd are both 16 KB */
89                 if ((j == 1) || (j == 2))
90                 {
91                         flash_info[i].start[j] = flashbase + 0x8000 + (j-1)*0x4000;
92                 }
93
94                 /* 4th 64 KB */
95                 if (j == 3)
96                 {
97                         flash_info[i].start[j] = flashbase + 0x10000;
98                 }
99             }
100             else
101             {
102                 flash_info[i].start[j] = flashbase + (j - 3)*MAIN_SECT_SIZE;
103             }
104         }
105         size += flash_info[i].size;
106     }
107
108     /*
109      * Protect monitor and environment sectors
110      * Inferno is complicated, it's hardware locked
111      */
112 #ifdef CONFIG_INFERNO
113     /* first one, 0x00000 to 0x07fff */
114     flash_protect(FLAG_PROTECT_SET,
115                   CONFIG_SYS_FLASH_BASE + 0x00000,
116                   CONFIG_SYS_FLASH_BASE + 0x08000 - 1,
117                   &flash_info[0]);
118
119     /* third to 10th, 0x0c000 - 0xdffff */
120     flash_protect(FLAG_PROTECT_SET,
121                   CONFIG_SYS_FLASH_BASE + 0x0c000,
122                   CONFIG_SYS_FLASH_BASE + 0xe0000 - 1,
123                   &flash_info[0]);
124 #else
125     flash_protect(FLAG_PROTECT_SET,
126                   CONFIG_SYS_FLASH_BASE,
127                   CONFIG_SYS_FLASH_BASE + monitor_flash_len - 1,
128                   &flash_info[0]);
129
130     flash_protect(FLAG_PROTECT_SET,
131                   CONFIG_ENV_ADDR,
132                   CONFIG_ENV_ADDR + CONFIG_ENV_SIZE - 1,
133                   &flash_info[0]);
134 #endif
135     return size;
136 }
137
138 /*-----------------------------------------------------------------------
139  */
140 void flash_print_info  (flash_info_t *info)
141 {
142     int i;
143
144     switch (info->flash_id & FLASH_VENDMASK)
145     {
146     case (AMD_MANUFACT & FLASH_VENDMASK):
147         printf("AMD: ");
148         break;
149     default:
150         printf("Unknown Vendor ");
151         break;
152     }
153
154     switch (info->flash_id & FLASH_TYPEMASK)
155     {
156     case (AMD_ID_LV160B & FLASH_TYPEMASK):
157         printf("2x Amd29F160BB (16Mbit)\n");
158         break;
159     default:
160         printf("Unknown Chip Type\n");
161         goto Done;
162         break;
163     }
164
165     printf("  Size: %ld MB in %d Sectors\n",
166            info->size >> 20, info->sector_count);
167
168     printf("  Sector Start Addresses:");
169     for (i = 0; i < info->sector_count; i++)
170     {
171         if ((i % 5) == 0)
172         {
173             printf ("\n   ");
174         }
175         printf (" %08lX%s", info->start[i],
176                 info->protect[i] ? " (RO)" : "     ");
177     }
178     printf ("\n");
179
180 Done:
181     ;
182 }
183
184 /*-----------------------------------------------------------------------
185  */
186
187 int     flash_erase (flash_info_t *info, int s_first, int s_last)
188 {
189     ulong result;
190     int iflag, cflag, prot, sect;
191     int rc = ERR_OK;
192     int chip1, chip2;
193     ulong start;
194
195     /* first look for protection bits */
196
197     if (info->flash_id == FLASH_UNKNOWN)
198         return ERR_UNKNOWN_FLASH_TYPE;
199
200     if ((s_first < 0) || (s_first > s_last)) {
201         return ERR_INVAL;
202     }
203
204     if ((info->flash_id & FLASH_VENDMASK) !=
205         (AMD_MANUFACT & FLASH_VENDMASK)) {
206         return ERR_UNKNOWN_FLASH_VENDOR;
207     }
208
209     prot = 0;
210     for (sect=s_first; sect<=s_last; ++sect) {
211         if (info->protect[sect]) {
212             prot++;
213         }
214     }
215     if (prot)
216         return ERR_PROTECTED;
217
218     /*
219      * Disable interrupts which might cause a timeout
220      * here. Remember that our exception vectors are
221      * at address 0 in the flash, and we don't want a
222      * (ticker) exception to happen while the flash
223      * chip is in programming mode.
224      */
225     cflag = icache_status();
226     icache_disable();
227     iflag = disable_interrupts();
228
229     /* Start erase on unprotected sectors */
230     for (sect = s_first; sect<=s_last && !ctrlc(); sect++)
231     {
232         printf("Erasing sector %2d ... ", sect);
233
234         /* arm simple, non interrupt dependent timer */
235         start = get_timer(0);
236
237         if (info->protect[sect] == 0)
238         {       /* not protected */
239             vu_long *addr = (vu_long *)(info->start[sect]);
240
241             MEM_FLASH_ADDR1 = CMD_UNLOCK1;
242             MEM_FLASH_ADDR2 = CMD_UNLOCK2;
243             MEM_FLASH_ADDR1 = CMD_ERASE_SETUP;
244
245             MEM_FLASH_ADDR1 = CMD_UNLOCK1;
246             MEM_FLASH_ADDR2 = CMD_UNLOCK2;
247             *addr = CMD_ERASE_CONFIRM;
248
249             /* wait until flash is ready */
250             chip1 = chip2 = 0;
251
252             do
253             {
254                 result = *addr;
255
256                 /* check timeout */
257                 if (get_timer(start) > CONFIG_SYS_FLASH_ERASE_TOUT)
258                 {
259                     MEM_FLASH_ADDR1 = CMD_READ_ARRAY;
260                     chip1 = TMO;
261                     break;
262                 }
263
264                 if (!chip1 && (result & 0xFFFF) & BIT_ERASE_DONE)
265                         chip1 = READY;
266
267                 if (!chip1 && (result & 0xFFFF) & BIT_PROGRAM_ERROR)
268                         chip1 = ERR;
269
270                 if (!chip2 && (result >> 16) & BIT_ERASE_DONE)
271                         chip2 = READY;
272
273                 if (!chip2 && (result >> 16) & BIT_PROGRAM_ERROR)
274                         chip2 = ERR;
275
276             }  while (!chip1 || !chip2);
277
278             MEM_FLASH_ADDR1 = CMD_READ_ARRAY;
279
280             if (chip1 == ERR || chip2 == ERR)
281             {
282                 rc = ERR_PROG_ERROR;
283                 goto outahere;
284             }
285             if (chip1 == TMO)
286             {
287                 rc = ERR_TIMOUT;
288                 goto outahere;
289             }
290
291             printf("ok.\n");
292         }
293         else /* it was protected */
294         {
295             printf("protected!\n");
296         }
297     }
298
299     if (ctrlc())
300       printf("User Interrupt!\n");
301
302 outahere:
303     /* allow flash to settle - wait 10 ms */
304     udelay_masked(10000);
305
306     if (iflag)
307       enable_interrupts();
308
309     if (cflag)
310       icache_enable();
311
312     return rc;
313 }
314
315 /*-----------------------------------------------------------------------
316  * Copy memory to flash
317  */
318
319 static int write_word (flash_info_t *info, ulong dest, ulong data)
320 {
321     vu_long *addr = (vu_long *)dest;
322     ulong result;
323     int rc = ERR_OK;
324     int cflag, iflag;
325     int chip1, chip2;
326     ulong start;
327
328     /*
329      * Check if Flash is (sufficiently) erased
330      */
331     result = *addr;
332     if ((result & data) != data)
333         return ERR_NOT_ERASED;
334
335
336     /*
337      * Disable interrupts which might cause a timeout
338      * here. Remember that our exception vectors are
339      * at address 0 in the flash, and we don't want a
340      * (ticker) exception to happen while the flash
341      * chip is in programming mode.
342      */
343     cflag = icache_status();
344     icache_disable();
345     iflag = disable_interrupts();
346
347     MEM_FLASH_ADDR1 = CMD_UNLOCK1;
348     MEM_FLASH_ADDR2 = CMD_UNLOCK2;
349     MEM_FLASH_ADDR1 = CMD_UNLOCK_BYPASS;
350     *addr = CMD_PROGRAM;
351     *addr = data;
352
353     /* arm simple, non interrupt dependent timer */
354     start = get_timer(0);
355
356     /* wait until flash is ready */
357     chip1 = chip2 = 0;
358     do
359     {
360         result = *addr;
361
362         /* check timeout */
363         if (get_timer(start) > CONFIG_SYS_FLASH_ERASE_TOUT)
364         {
365             chip1 = ERR | TMO;
366             break;
367         }
368         if (!chip1 && ((result & 0x80) == (data & 0x80)))
369                 chip1 = READY;
370
371         if (!chip1 && ((result & 0xFFFF) & BIT_PROGRAM_ERROR))
372         {
373                 result = *addr;
374
375                 if ((result & 0x80) == (data & 0x80))
376                         chip1 = READY;
377                 else
378                         chip1 = ERR;
379         }
380
381         if (!chip2 && ((result & (0x80 << 16)) == (data & (0x80 << 16))))
382                 chip2 = READY;
383
384         if (!chip2 && ((result >> 16) & BIT_PROGRAM_ERROR))
385         {
386                 result = *addr;
387
388                 if ((result & (0x80 << 16)) == (data & (0x80 << 16)))
389                         chip2 = READY;
390                 else
391                         chip2 = ERR;
392         }
393
394     }  while (!chip1 || !chip2);
395
396     *addr = CMD_READ_ARRAY;
397
398     if (chip1 == ERR || chip2 == ERR || *addr != data)
399         rc = ERR_PROG_ERROR;
400
401     if (iflag)
402       enable_interrupts();
403
404     if (cflag)
405       icache_enable();
406
407     return rc;
408 }
409
410 /*-----------------------------------------------------------------------
411  * Copy memory to flash.
412  */
413
414 int write_buff (flash_info_t *info, uchar *src, ulong addr, ulong cnt)
415 {
416     ulong cp, wp, data;
417     int l;
418     int i, rc;
419
420     wp = (addr & ~3);   /* get lower word aligned address */
421
422     /*
423      * handle unaligned start bytes
424      */
425     if ((l = addr - wp) != 0) {
426         data = 0;
427         for (i=0, cp=wp; i<l; ++i, ++cp) {
428             data = (data >> 8) | (*(uchar *)cp << 24);
429         }
430         for (; i<4 && cnt>0; ++i) {
431             data = (data >> 8) | (*src++ << 24);
432             --cnt;
433             ++cp;
434         }
435         for (; cnt==0 && i<4; ++i, ++cp) {
436             data = (data >> 8) | (*(uchar *)cp << 24);
437         }
438
439         if ((rc = write_word(info, wp, data)) != 0) {
440             return (rc);
441         }
442         wp += 4;
443     }
444
445     /*
446      * handle word aligned part
447      */
448     while (cnt >= 4) {
449         data = *((vu_long*)src);
450         if ((rc = write_word(info, wp, data)) != 0) {
451             return (rc);
452         }
453         src += 4;
454         wp  += 4;
455         cnt -= 4;
456     }
457
458     if (cnt == 0) {
459         return ERR_OK;
460     }
461
462     /*
463      * handle unaligned tail bytes
464      */
465     data = 0;
466     for (i=0, cp=wp; i<4 && cnt>0; ++i, ++cp) {
467         data = (data >> 8) | (*src++ << 24);
468         --cnt;
469     }
470     for (; i<4; ++i, ++cp) {
471         data = (data >> 8) | (*(uchar *)cp << 24);
472     }
473
474     return write_word(info, wp, data);
475 }