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