PPC4xx:HCU4/5-Board fix compile warning
[platform/kernel/u-boot.git] / board / netstal / common / hcu_flash.c
1 /*
2  * (C) Copyright 2000-2004
3  * Wolfgang Denk, DENX Software Engineering, wd@denx.de.
4  *
5  * See file CREDITS for list of people who contributed to this
6  * project.
7  *
8  * This program is free software; you can redistribute it and/or
9  * modify it under the terms of the GNU General Public License as
10  * published by the Free Software Foundation; either version 2 of
11  * the License, or (at your option) any later version.
12  *
13  * This program is distributed in the hope that it will be useful,
14  * but WITHOUT ANY WARRANTY; without even the implied warranty of
15  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
16  * GNU General Public License for more details.
17  *
18  * You should have received a copy of the GNU General Public License
19  * along with this program; if not, write to the Free Software
20  * Foundation, Inc., 59 Temple Place, Suite 330, Boston,
21  * MA 02111-1307 USA
22  */
23
24 /*
25  * Modified 4/5/2001
26  * Wait for completion of each sector erase command issued
27  * 4/5/2001
28  * Chris Hallinan - DS4.COM, Inc. - clh@net1plus.com
29  *
30  * Modified 6/6/2007
31  * Added isync
32  * Niklaus Giger, Netstal Maschinen, niklaus.giger@netstal.com
33  *
34  */
35
36 #include <common.h>
37 #include <ppc4xx.h>
38 #include <asm/processor.h>
39
40 #if CFG_MAX_FLASH_BANKS != 1
41 #error "CFG_MAX_FLASH_BANKS must be 1"
42 #endif
43 flash_info_t flash_info[CFG_MAX_FLASH_BANKS];   /* info for FLASH chips */
44
45 /*-----------------------------------------------------------------------
46  * Functions
47  */
48 static ulong flash_get_size (vu_long * addr, flash_info_t * info);
49 static int write_word (flash_info_t * info, ulong dest, ulong data);
50 static void flash_get_offsets (ulong base, flash_info_t * info);
51
52 #define ADDR0           0x5555
53 #define ADDR1           0x2aaa
54 #define FLASH_WORD_SIZE unsigned char
55
56 /*-----------------------------------------------------------------------*/
57
58 unsigned long flash_init (void)
59 {
60         unsigned long size_b0;
61
62         /* Init: no FLASHes known */
63         flash_info[0].flash_id = FLASH_UNKNOWN;
64
65         /* Static FLASH Bank configuration here - FIXME XXX */
66
67         size_b0 = flash_get_size ((vu_long *) FLASH_BASE0_PRELIM,
68                                   &flash_info[0]);
69
70         if (flash_info[0].flash_id == FLASH_UNKNOWN) {
71                 printf ("## Unknown FLASH on Bank 0- Size=0x%08lx=%ld MB\n",
72                         size_b0, size_b0 << 20);
73         }
74
75         /* Only one bank */
76         /* Setup offsets */
77         flash_get_offsets (FLASH_BASE0_PRELIM, &flash_info[0]);
78
79         /* Monitor protection ON by default */
80         (void) flash_protect (FLAG_PROTECT_SET,
81                               FLASH_BASE0_PRELIM,
82                               FLASH_BASE0_PRELIM + monitor_flash_len - 1,
83                               &flash_info[0]);
84         flash_info[0].size = size_b0;
85
86         return size_b0;
87 }
88
89
90 /*-----------------------------------------------------------------------*/
91 /*
92  * This implementation assumes that the flash chips are uniform sector
93  * devices. This is true for all likely flash devices on a HCUx.
94  */
95 static void flash_get_offsets (ulong base, flash_info_t * info)
96 {
97         unsigned idx;
98         unsigned long sector_size = info->size / info->sector_count;
99
100         for (idx = 0; idx < info->sector_count; idx += 1) {
101                 info->start[idx] = base + (idx * sector_size);
102         }
103 }
104
105 /*-----------------------------------------------------------------------*/
106 void flash_print_info (flash_info_t * info)
107 {
108         int i;
109         int k;
110         int size;
111         int erased;
112         volatile unsigned long *flash;
113
114         if (info->flash_id == FLASH_UNKNOWN) {
115                 printf ("missing or unknown FLASH type\n");
116                 return;
117         }
118
119         switch (info->flash_id & FLASH_VENDMASK) {
120         case FLASH_MAN_AMD:
121                 printf ("AMD ");
122                 break;
123         case FLASH_MAN_FUJ:
124                 printf ("FUJITSU ");
125                 break;
126         case FLASH_MAN_SST:
127                 printf ("SST ");
128                 break;
129         case FLASH_MAN_STM:
130                 printf ("ST Micro ");
131                 break;
132         default:
133                 printf ("Unknown Vendor ");
134                 break;
135         }
136
137           /* (Reduced table of only parts expected in HCUx boards.) */
138         switch (info->flash_id) {
139         case FLASH_MAN_AMD | FLASH_AM040:
140                 printf ("AM29F040 (512 Kbit, uniform sector size)\n");
141                 break;
142         case FLASH_MAN_STM | FLASH_AM040:
143                 printf ("MM29W040W (512 Kbit, uniform sector size)\n");
144                 break;
145         default:
146                 printf ("Unknown Chip Type\n");
147                 break;
148         }
149
150         printf ("  Size: %ld KB in %d Sectors\n",
151                 info->size >> 10, info->sector_count);
152
153         printf ("  Sector Start Addresses:");
154         for (i = 0; i < info->sector_count; ++i) {
155                 /*
156                  * Check if whole sector is erased
157                  */
158                 if (i != (info->sector_count - 1))
159                         size = info->start[i + 1] - info->start[i];
160                 else
161                         size = info->start[0] + info->size - info->start[i];
162                 erased = 1;
163                 flash = (volatile unsigned long *) info->start[i];
164                 size = size >> 2;       /* divide by 4 for longword access */
165                 for (k = 0; k < size; k++) {
166                         if (*flash++ != 0xffffffff) {
167                                 erased = 0;
168                                 break;
169                         }
170                 }
171
172                 if ((i % 5) == 0)
173                         printf ("\n   ");
174                 printf (" %08lX%s%s",
175                         info->start[i],
176                         erased ? " E" : "  ", info->protect[i] ? "RO " : "   "
177                 );
178         }
179         printf ("\n");
180         return;
181 }
182
183 /*-----------------------------------------------------------------------*/
184
185 /*
186  * The following code cannot be run from FLASH!
187  */
188 static ulong flash_get_size (vu_long * addr, flash_info_t * info)
189 {
190         short i;
191         FLASH_WORD_SIZE value;
192         ulong base = (ulong) addr;
193         volatile FLASH_WORD_SIZE *addr2 = (FLASH_WORD_SIZE *) addr;
194
195         /* Write auto select command: read Manufacturer ID */
196         asm("isync");
197         addr2[ADDR0] = (FLASH_WORD_SIZE) 0x00AA00AA;
198         asm("isync");
199         addr2[ADDR1] = (FLASH_WORD_SIZE) 0x00550055;
200         asm("isync");
201         addr2[ADDR0] = (FLASH_WORD_SIZE) 0x00900090;
202         asm("isync");
203
204         value = addr2[0];
205         asm("isync");
206
207         switch (value) {
208         case (FLASH_WORD_SIZE) AMD_MANUFACT:
209                 info->flash_id = FLASH_MAN_AMD;
210                 break;
211         case (FLASH_WORD_SIZE) FUJ_MANUFACT:
212                 info->flash_id = FLASH_MAN_FUJ;
213                 break;
214         case (FLASH_WORD_SIZE) SST_MANUFACT:
215                 info->flash_id = FLASH_MAN_SST;
216                 break;
217         case (FLASH_WORD_SIZE)STM_MANUFACT:
218                 info->flash_id = FLASH_MAN_STM;
219                 break;
220         default:
221                 info->flash_id = FLASH_UNKNOWN;
222                 info->sector_count = 0;
223                 info->size = 0;
224                 printf("Unknown flash manufacturer code: 0x%x at %p\n",
225                        value, addr);
226                 addr2[ADDR0] = (FLASH_WORD_SIZE) 0;
227                 return (0);     /* no or unknown flash  */
228         }
229
230         value = addr2[1];       /* device ID            */
231
232         switch (value) {
233         case (FLASH_WORD_SIZE) AMD_ID_F040B:
234                 info->flash_id += FLASH_AM040;
235                 info->sector_count = 8;
236                 info->size = 0x0080000; /* => 512 ko */
237                 break;
238         case (FLASH_WORD_SIZE) AMD_ID_LV040B:
239                 info->flash_id += FLASH_AM040;
240                 info->sector_count = 8;
241                 info->size = 0x0080000; /* => 512 ko */
242                 break;
243         case (FLASH_WORD_SIZE)STM_ID_M29W040B: /* most likele HCU5 chip */
244                 info->flash_id += FLASH_AM040;
245                 info->sector_count = 8;
246                 info->size = 0x0080000; /* => 512 ko */
247                 break;
248         default:
249                 info->flash_id = FLASH_UNKNOWN;
250                 return (0);     /* => no or unknown flash */
251
252         }
253
254           /* Calculate the sector offsets (Use HCUx Optimized code). */
255         flash_get_offsets(base, info);
256
257         /* check for protected sectors */
258         for (i = 0; i < info->sector_count; i++) {
259                 /* read sector protection at sector address,
260                  *(A7 .. A0) = 0x02
261                  * D0 = 1 if protected
262                  */
263                 addr2 = (volatile FLASH_WORD_SIZE *) (info->start[i]);
264                 if ((info->flash_id & FLASH_VENDMASK) == FLASH_MAN_SST)
265                         info->protect[i] = 0;
266                 else
267                         info->protect[i] = addr2[2] & 1;
268         }
269
270         /*
271          * Prevent writes to uninitialized FLASH.
272          */
273         if (info->flash_id != FLASH_UNKNOWN) {
274                 addr2 = (FLASH_WORD_SIZE *) info->start[0];
275                 *addr2 = (FLASH_WORD_SIZE) 0x00F000F0;  /* reset bank */
276         }
277
278         return (info->size);
279 }
280
281 int wait_for_DQ7 (flash_info_t * info, int sect)
282 {
283         ulong start, now, last;
284         volatile FLASH_WORD_SIZE *addr =
285                 (FLASH_WORD_SIZE *) (info->start[sect]);
286
287         start = get_timer (0);
288         last = start;
289         while ((addr[0] & (FLASH_WORD_SIZE) 0x00800080) !=
290                (FLASH_WORD_SIZE) 0x00800080) {
291                 if ((now = get_timer (start)) > CFG_FLASH_ERASE_TOUT) {
292                         printf ("Timeout\n");
293                         return -1;
294                 }
295                 /* show that we're waiting */
296                 if ((now - last) > 1000) {      /* every second */
297                         putc ('.');
298                         last = now;
299                 }
300         }
301         return 0;
302 }
303
304 /*-----------------------------------------------------------------------*/
305
306 int flash_erase (flash_info_t * info, int s_first, int s_last)
307 {
308         volatile FLASH_WORD_SIZE *addr = (FLASH_WORD_SIZE *) (info->start[0]);
309         volatile FLASH_WORD_SIZE *addr2;
310         int flag, prot, sect, l_sect;
311         int i;
312
313         if ((s_first < 0) || (s_first > s_last)) {
314                 if (info->flash_id == FLASH_UNKNOWN) {
315                         printf ("- missing\n");
316                 } else {
317                         printf ("- no sectors to erase\n");
318                 }
319                 return 1;
320         }
321
322         if (info->flash_id == FLASH_UNKNOWN) {
323                 printf ("Can't erase unknown flash type - aborted\n");
324                 return 1;
325         }
326
327         prot = 0;
328         for (sect = s_first; sect <= s_last; ++sect) {
329                 if (info->protect[sect]) {
330                         prot++;
331                 }
332         }
333
334         if (prot) {
335                 printf ("- Warning: %d protected sectors not erased!\n",
336                         prot);
337         } else {
338                 printf ("\n");
339         }
340
341         l_sect = -1;
342
343         /* Disable interrupts which might cause a timeout here */
344         flag = disable_interrupts ();
345
346         /* Start erase on unprotected sectors */
347         for (sect = s_first; sect <= s_last; sect++) {
348                 if (info->protect[sect] == 0) { /* not protected */
349                         addr2 = (FLASH_WORD_SIZE *) (info->start[sect]);
350                         printf ("Erasing sector %p\n", addr2);  /* CLH */
351
352                         if ((info->flash_id & FLASH_VENDMASK) ==
353                             FLASH_MAN_SST) {
354                                 addr[ADDR0] = (FLASH_WORD_SIZE) 0x00AA00AA;
355                                 addr[ADDR1] = (FLASH_WORD_SIZE) 0x00550055;
356                                 addr[ADDR0] = (FLASH_WORD_SIZE) 0x00800080;
357                                 addr[ADDR0] = (FLASH_WORD_SIZE) 0x00AA00AA;
358                                 addr[ADDR1] = (FLASH_WORD_SIZE) 0x00550055;
359                                 /* block erase */
360                                 addr2[0] = (FLASH_WORD_SIZE) 0x00500050;
361                                 for (i = 0; i < 50; i++) udelay (1000);
362                         } else {
363                                 addr[ADDR0] = (FLASH_WORD_SIZE) 0x00AA00AA;
364                                 addr[ADDR1] = (FLASH_WORD_SIZE) 0x00550055;
365                                 addr[ADDR0] = (FLASH_WORD_SIZE) 0x00800080;
366                                 addr[ADDR0] = (FLASH_WORD_SIZE) 0x00AA00AA;
367                                 addr[ADDR1] = (FLASH_WORD_SIZE) 0x00550055;
368                                 /* sector erase */
369                                 addr2[0] = (FLASH_WORD_SIZE) 0x00300030;
370                         }
371                         l_sect = sect;
372                         /*
373                          * Wait for each sector to complete, it's more
374                          * reliable.  According to AMD Spec, you must
375                          * issue all erase commands within a specified
376                          * timeout.  This has been seen to fail, especially
377                          * if printf()s are included (for debug)!!
378                          */
379                         wait_for_DQ7 (info, sect);
380                 }
381         }
382
383         /* re-enable interrupts if necessary */
384         if (flag)
385                 enable_interrupts ();
386
387         /* wait at least 80us - let's wait 1 ms */
388         udelay (1000);
389
390 #if 0
391         /*
392          * We wait for the last triggered sector
393          */
394         if (l_sect < 0)
395                 goto DONE;
396         wait_for_DQ7 (info, l_sect);
397
398 DONE:
399 #endif
400         /* reset to read mode */
401         addr = (FLASH_WORD_SIZE *) info->start[0];
402         addr[0] = (FLASH_WORD_SIZE) 0x00F000F0; /* reset bank */
403
404         printf (" done\n");
405         return 0;
406 }
407
408 /*-----------------------------------------------------------------------
409  * Copy memory to flash, returns:
410  * 0 - OK
411  * 1 - write timeout
412  * 2 - Flash not erased
413  */
414
415 int write_buff (flash_info_t * info, uchar * src, ulong addr, ulong cnt)
416 {
417         ulong cp, wp, data;
418         int i, l, 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);
429                 }
430                 for (; i < 4 && cnt > 0; ++i) {
431                         data = (data << 8) | *src++;
432                         --cnt;
433                         ++cp;
434                 }
435                 for (; cnt == 0 && i < 4; ++i, ++cp) {
436                         data = (data << 8) | (*(uchar *) cp);
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 = 0;
450                 for (i = 0; i < 4; ++i) {
451                         data = (data << 8) | *src++;
452                 }
453                 if ((rc = write_word (info, wp, data)) != 0) {
454                         return (rc);
455                 }
456                 wp += 4;
457                 cnt -= 4;
458         }
459
460         if (cnt == 0) {
461                 return (0);
462         }
463
464         /*
465          * handle unaligned tail bytes
466          */
467         data = 0;
468         for (i = 0, cp = wp; i < 4 && cnt > 0; ++i, ++cp) {
469                 data = (data << 8) | *src++;
470                 --cnt;
471         }
472         for (; i < 4; ++i, ++cp) {
473                 data = (data << 8) | (*(uchar *) cp);
474         }
475
476         return (write_word (info, wp, data));
477 }
478
479 /*-----------------------------------------------------------------------
480  * Write a word to Flash, returns:
481  * 0 - OK
482  * 1 - write timeout
483  * 2 - Flash not erased
484  */
485 static int write_word (flash_info_t * info, ulong dest, ulong data)
486 {
487         volatile FLASH_WORD_SIZE *addr2 =
488                 (FLASH_WORD_SIZE *) (info->start[0]);
489         volatile FLASH_WORD_SIZE *dest2 = (FLASH_WORD_SIZE *) dest;
490         volatile FLASH_WORD_SIZE *data2 = (FLASH_WORD_SIZE *) & data;
491         ulong start;
492         int i;
493
494         /* Check if Flash is (sufficiently) erased */
495         if ((*((volatile FLASH_WORD_SIZE *) dest) &
496             (FLASH_WORD_SIZE) data) != (FLASH_WORD_SIZE) data) {
497                 return (2);
498         }
499
500         for (i = 0; i < 4 / sizeof (FLASH_WORD_SIZE); i++) {
501                 int flag;
502
503                 /* Disable interrupts which might cause a timeout here */
504                 flag = disable_interrupts ();
505
506                 addr2[ADDR0] = (FLASH_WORD_SIZE) 0x00AA00AA;
507                 addr2[ADDR1] = (FLASH_WORD_SIZE) 0x00550055;
508                 addr2[ADDR0] = (FLASH_WORD_SIZE) 0x00A000A0;
509
510                 dest2[i] = data2[i];
511
512                 /* re-enable interrupts if necessary */
513                 if (flag)
514                         enable_interrupts ();
515
516                 /* data polling for D7 */
517                 start = get_timer (0);
518                 while ((dest2[i] & (FLASH_WORD_SIZE) 0x00800080) !=
519                        (data2[i] & (FLASH_WORD_SIZE) 0x00800080)) {
520
521                         if (get_timer (start) > CFG_FLASH_WRITE_TOUT) {
522                                 return (1);
523                         }
524                 }
525         }
526
527         return (0);
528 }