]> git.kernelconcepts.de Git - karo-tx-uboot.git/blob - board/svm_sc8xx/flash.c
serial: punt unused serial_addr()
[karo-tx-uboot.git] / board / svm_sc8xx / flash.c
1 /*
2  * Wolfgang Denk, DENX Software Engineering, wd@denx.de.
3  *
4  * See file CREDITS for list of people who contributed to this
5  * project.
6  *
7  * This program is free software; you can redistribute it and/or
8  * modify it under the terms of the GNU General Public License as
9  * published by the Free Software Foundation; either version 2 of
10  * the License, or (at your option) any later version.
11  *
12  * This program is distributed in the hope that it will be useful,
13  * but WITHOUT ANY WARRANTY; without even the implied warranty of
14  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
15  * GNU General Public License for more details.
16  *
17  * You should have received a copy of the GNU General Public License
18  * along with this program; if not, write to the Free Software
19  * Foundation, Inc., 59 Temple Place, Suite 330, Boston,
20  * MA 02111-1307 USA
21  */
22
23 #include <common.h>
24 #include <mpc8xx.h>
25
26 #ifndef CONFIG_ENV_ADDR
27 #define CONFIG_ENV_ADDR (CONFIG_SYS_FLASH_BASE + CONFIG_ENV_OFFSET)
28 #endif
29
30 flash_info_t    flash_info[CONFIG_SYS_MAX_FLASH_BANKS]; /* info for FLASH chips */
31
32 /*-----------------------------------------------------------------------
33  * Functions
34  */
35 static int write_word (flash_info_t *info, ulong dest, ulong data);
36 #if 0
37 static ulong flash_get_size (vu_long *addr, flash_info_t *info);
38 static void flash_get_offsets (ulong base, flash_info_t *info);
39 #endif
40 #ifdef  CONFIG_BOOT_8B
41 static int my_in_8( unsigned char *addr);
42 static  void my_out_8( unsigned char *addr, int val);
43 #endif
44 #ifdef  CONFIG_BOOT_16B
45 static  int my_in_be16( unsigned short *addr);
46 static  void my_out_be16( unsigned short *addr, int val);
47 #endif
48 #ifdef  CONFIG_BOOT_32B
49 static  unsigned my_in_be32( unsigned *addr);
50 static  void my_out_be32( unsigned *addr, int val);
51 #endif
52 /*-----------------------------------------------------------------------
53  */
54
55 unsigned long flash_init (void)
56 {
57         volatile immap_t     *immap  = (immap_t *)CONFIG_SYS_IMMR;
58         volatile memctl8xx_t *memctl = &immap->im_memctl;
59         unsigned long size_b0, size_b1;
60         int i;
61
62         size_b0=0;
63         size_b1=0;
64         /* Init: no FLASHes known */
65         for (i=0; i<CONFIG_SYS_MAX_FLASH_BANKS; ++i) {
66                 flash_info[i].flash_id = FLASH_UNKNOWN;
67         }
68 #ifdef CONFIG_SYS_DOC_BASE
69 #ifndef CONFIG_FEL8xx_AT
70         memctl->memc_or5 = (0xffff8000 | CONFIG_SYS_OR_TIMING_DOC ); /* 32k bytes */
71         memctl->memc_br5 = CONFIG_SYS_DOC_BASE | 0x401;
72 #else
73         memctl->memc_or3 = (0xffff8000 | CONFIG_SYS_OR_TIMING_DOC ); /* 32k bytes */
74         memctl->memc_br3 = CONFIG_SYS_DOC_BASE | 0x401;
75 #endif
76 #endif
77 #if defined( CONFIG_BOOT_8B)
78 /*        memctl->memc_or0 = 0xfff80ff4; /###* 4MB bytes */
79 /*        memctl->memc_br0 = 0x40000401; */
80         size_b0 = 0x80000;  /* 512 K */
81         flash_info[0].flash_id = FLASH_MAN_AMD | FLASH_AM040;
82         flash_info[0].sector_count = 8;
83         flash_info[0].size = 0x00080000;
84         /* set up sector start address table */
85         for (i = 0; i < flash_info[0].sector_count; i++)
86         flash_info[0].start[i] = 0x40000000 + (i * 0x10000);
87         /* protect all sectors */
88         for (i = 0; i < flash_info[0].sector_count; i++)
89         flash_info[0].protect[i] = 0x1;
90 #elif defined (CONFIG_BOOT_16B)
91 /*        memctl->memc_or0 = 0xfff80ff4; /###* 4MB bytes */
92 /*        memctl->memc_br0 = 0x40000401; */
93         size_b0 = 0x400000;  /* 4MB , assume AMD29LV320B */
94         flash_info[0].flash_id = FLASH_MAN_AMD | FLASH_AM320B;
95         flash_info[0].sector_count = 67;
96         flash_info[0].size = 0x00400000;
97         /* set up sector start address table */
98         flash_info[0].start[0] = 0x40000000  ;
99         flash_info[0].start[1] = 0x40000000 + 0x4000;
100         flash_info[0].start[2] = 0x40000000 + 0x6000;
101         flash_info[0].start[3] = 0x40000000 + 0x8000;
102         for (i = 4; i < flash_info[0].sector_count; i++)
103         flash_info[0].start[i] = 0x40000000 + 0x10000 + ((i-4) * 0x10000);
104         /* protect all sectors */
105         for (i = 0; i < flash_info[0].sector_count; i++)
106         flash_info[0].protect[i] = 0x1;
107 #endif
108
109
110 #ifdef CONFIG_BOOT_32B
111
112         /* Static FLASH Bank configuration here - FIXME XXX */
113
114         size_b0 = flash_get_size((vu_long *)FLASH_BASE0_PRELIM, &flash_info[0]);
115
116         if (flash_info[0].flash_id == FLASH_UNKNOWN) {
117                 printf ("## Unknown FLASH on Bank 0 - Size = 0x%08lx = %ld MB\n",
118                         size_b0, size_b0<<20);
119         }
120
121         size_b1 = flash_get_size((vu_long *)FLASH_BASE1_PRELIM, &flash_info[1]);
122
123         if (size_b1 > size_b0) {
124                 printf ("## ERROR: "
125                         "Bank 1 (0x%08lx = %ld MB) > Bank 0 (0x%08lx = %ld MB)\n",
126                         size_b1, size_b1<<20,
127                         size_b0, size_b0<<20
128                 );
129                 flash_info[0].flash_id  = FLASH_UNKNOWN;
130                 flash_info[1].flash_id  = FLASH_UNKNOWN;
131                 flash_info[0].sector_count      = -1;
132                 flash_info[1].sector_count      = -1;
133                 flash_info[0].size              = 0;
134                 flash_info[1].size              = 0;
135                 return (0);
136         }
137
138         /* Remap FLASH according to real size */
139         memctl->memc_or0 = CONFIG_SYS_OR_TIMING_FLASH | (-size_b0 & OR_AM_MSK);
140         memctl->memc_br0 = (CONFIG_SYS_FLASH_BASE & BR_BA_MSK) | BR_MS_GPCM | BR_V;
141
142         /* Re-do sizing to get full correct info */
143         size_b0 = flash_get_size((vu_long *)CONFIG_SYS_FLASH_BASE, &flash_info[0]);
144
145         flash_get_offsets (CONFIG_SYS_FLASH_BASE, &flash_info[0]);
146
147 #if CONFIG_SYS_MONITOR_BASE >= CONFIG_SYS_FLASH_BASE
148         /* monitor protection ON by default */
149         flash_protect(FLAG_PROTECT_SET,
150                       CONFIG_SYS_MONITOR_BASE,
151                       CONFIG_SYS_MONITOR_BASE+monitor_flash_len-1,
152                       &flash_info[0]);
153 #endif
154
155 #ifdef  CONFIG_ENV_IS_IN_FLASH
156         /* ENV protection ON by default */
157         flash_protect(FLAG_PROTECT_SET,
158                       CONFIG_ENV_ADDR,
159                       CONFIG_ENV_ADDR+CONFIG_ENV_SIZE-1,
160                       &flash_info[0]);
161 #endif
162
163         if (size_b1) {
164                 memctl->memc_or1 = CONFIG_SYS_OR_TIMING_FLASH | (-size_b1 & 0xFFFF8000);
165                 memctl->memc_br1 = ((CONFIG_SYS_FLASH_BASE + size_b0) & BR_BA_MSK) |
166                                     BR_MS_GPCM | BR_V;
167
168                 /* Re-do sizing to get full correct info */
169                 size_b1 = flash_get_size((vu_long *)(CONFIG_SYS_FLASH_BASE + size_b0),
170                                           &flash_info[1]);
171
172                 flash_get_offsets (CONFIG_SYS_FLASH_BASE + size_b0, &flash_info[1]);
173
174 #if CONFIG_SYS_MONITOR_BASE >= CONFIG_SYS_FLASH_BASE
175                 /* monitor protection ON by default */
176                 flash_protect(FLAG_PROTECT_SET,
177                               CONFIG_SYS_MONITOR_BASE,
178                               CONFIG_SYS_MONITOR_BASE+monitor_flash_len-1,
179                               &flash_info[1]);
180 #endif
181
182 #ifdef  CONFIG_ENV_IS_IN_FLASH
183                 /* ENV protection ON by default */
184                 flash_protect(FLAG_PROTECT_SET,
185                               CONFIG_ENV_ADDR,
186                               CONFIG_ENV_ADDR+CONFIG_ENV_SIZE-1,
187                               &flash_info[1]);
188 #endif
189         } else {
190                 memctl->memc_br1 = 0;           /* invalidate bank */
191
192                 flash_info[1].flash_id = FLASH_UNKNOWN;
193                 flash_info[1].sector_count = -1;
194         }
195
196         flash_info[0].size = size_b0;
197         flash_info[1].size = size_b1;
198
199
200 #endif  /* CONFIG_BOOT_32B */
201
202         return (size_b0 + size_b1);
203 }
204 #if 0
205 /*-----------------------------------------------------------------------
206  */
207 static void flash_get_offsets (ulong base, flash_info_t *info)
208 {
209         int i;
210
211         /* set up sector start address table */
212         if (info->flash_id & FLASH_BTYPE) {
213                 /* set sector offsets for bottom boot block type        */
214                 info->start[0] = base + 0x00000000;
215                 info->start[1] = base + 0x00008000;
216                 info->start[2] = base + 0x0000C000;
217                 info->start[3] = base + 0x00010000;
218                 for (i = 4; i < info->sector_count; i++) {
219                         info->start[i] = base + (i * 0x00020000) - 0x00060000;
220                 }
221         } else {
222                 /* set sector offsets for top boot block type           */
223                 i = info->sector_count - 1;
224                 info->start[i--] = base + info->size - 0x00008000;
225                 info->start[i--] = base + info->size - 0x0000C000;
226                 info->start[i--] = base + info->size - 0x00010000;
227                 for (; i >= 0; i--) {
228                         info->start[i] = base + i * 0x00020000;
229                 }
230         }
231 }
232 #endif
233 /*-----------------------------------------------------------------------
234  */
235 void flash_print_info  (flash_info_t *info)
236 {
237         int i;
238
239         if (info->flash_id == FLASH_UNKNOWN) {
240                 printf ("missing or unknown FLASH type\n");
241                 return;
242         }
243
244         switch (info->flash_id & FLASH_VENDMASK) {
245         case FLASH_MAN_AMD:     printf ("AMD ");                break;
246         case FLASH_MAN_FUJ:     printf ("FUJITSU ");            break;
247         default:                printf ("Unknown Vendor ");     break;
248         }
249
250         switch (info->flash_id & FLASH_TYPEMASK) {
251         case FLASH_AM400B:      printf ("AM29LV400B (4 Mbit, bottom boot sect)\n");
252                                 break;
253         case FLASH_AM400T:      printf ("AM29LV400T (4 Mbit, top boot sector)\n");
254                                 break;
255         case FLASH_AM800B:      printf ("AM29LV800B (8 Mbit, bottom boot sect)\n");
256                                 break;
257         case FLASH_AM800T:      printf ("AM29LV800T (8 Mbit, top boot sector)\n");
258                                 break;
259         case FLASH_AM160B:      printf ("AM29LV160B (16 Mbit, bottom boot sect)\n");
260                                 break;
261         case FLASH_AM160T:      printf ("AM29LV160T (16 Mbit, top boot sector)\n");
262                                 break;
263         case FLASH_AM320B:      printf ("AM29LV320B (32 Mbit, bottom boot sect)\n");
264                                 break;
265         case FLASH_AM320T:      printf ("AM29LV320T (32 Mbit, top boot sector)\n");
266                                 break;
267         default:                printf ("Unknown Chip Type\n");
268                                 break;
269         }
270
271         printf ("  Size: %ld MB in %d Sectors\n",
272                 info->size >> 20, info->sector_count);
273
274         printf ("  Sector Start Addresses:");
275         for (i=0; i<info->sector_count; ++i) {
276                 if ((i % 5) == 0)
277                         printf ("\n   ");
278                 printf (" %08lX%s",
279                         info->start[i],
280                         info->protect[i] ? " (RO)" : "     "
281                 );
282         }
283         printf ("\n");
284         return;
285 }
286
287 /*-----------------------------------------------------------------------
288  */
289
290
291 /*-----------------------------------------------------------------------
292  */
293
294 /*
295  * The following code cannot be run from FLASH!
296  */
297 #if 0
298 static ulong flash_get_size (vu_long *addr, flash_info_t *info)
299 {
300         short i;
301         ulong value;
302         ulong base = (ulong)addr;
303
304         /* Write auto select command: read Manufacturer ID */
305         addr[0x0555] = 0x00AA00AA;
306         addr[0x02AA] = 0x00550055;
307         addr[0x0555] = 0x00900090;
308
309         value = addr[0];
310
311         switch (value) {
312         case AMD_MANUFACT:
313                 info->flash_id = FLASH_MAN_AMD;
314                 break;
315         case FUJ_MANUFACT:
316                 info->flash_id = FLASH_MAN_FUJ;
317                 break;
318         default:
319                 info->flash_id = FLASH_UNKNOWN;
320                 info->sector_count = 0;
321                 info->size = 0;
322                 return (0);                     /* no or unknown flash  */
323         }
324
325         value = addr[1];                        /* device ID            */
326
327         switch (value) {
328         case AMD_ID_LV400T:
329                 info->flash_id += FLASH_AM400T;
330                 info->sector_count = 11;
331                 info->size = 0x00100000;
332                 break;                          /* => 1 MB              */
333
334         case AMD_ID_LV400B:
335                 info->flash_id += FLASH_AM400B;
336                 info->sector_count = 11;
337                 info->size = 0x00100000;
338                 break;                          /* => 1 MB              */
339
340         case AMD_ID_LV800T:
341                 info->flash_id += FLASH_AM800T;
342                 info->sector_count = 19;
343                 info->size = 0x00200000;
344                 break;                          /* => 2 MB              */
345
346         case AMD_ID_LV800B:
347                 info->flash_id += FLASH_AM800B;
348                 info->sector_count = 19;
349                 info->size = 0x00200000;
350                 break;                          /* => 2 MB              */
351
352         case AMD_ID_LV160T:
353                 info->flash_id += FLASH_AM160T;
354                 info->sector_count = 35;
355                 info->size = 0x00400000;
356                 break;                          /* => 4 MB              */
357
358         case AMD_ID_LV160B:
359                 info->flash_id += FLASH_AM160B;
360                 info->sector_count = 35;
361                 info->size = 0x00400000;
362                 break;                          /* => 4 MB              */
363 #if 0   /* enable when device IDs are available */
364         case AMD_ID_LV320T:
365                 info->flash_id += FLASH_AM320T;
366                 info->sector_count = 67;
367                 info->size = 0x00800000;
368                 break;                          /* => 8 MB              */
369
370         case AMD_ID_LV320B:
371                 info->flash_id += FLASH_AM320B;
372                 info->sector_count = 67;
373                 info->size = 0x00800000;
374                 break;                          /* => 8 MB              */
375 #endif
376         default:
377                 info->flash_id = FLASH_UNKNOWN;
378                 return (0);                     /* => no or unknown flash */
379         }
380
381         /* set up sector start address table */
382         if (info->flash_id & FLASH_BTYPE) {
383                 /* set sector offsets for bottom boot block type        */
384                 info->start[0] = base + 0x00000000;
385                 info->start[1] = base + 0x00008000;
386                 info->start[2] = base + 0x0000C000;
387                 info->start[3] = base + 0x00010000;
388                 for (i = 4; i < info->sector_count; i++) {
389                         info->start[i] = base + (i * 0x00020000) - 0x00060000;
390                 }
391         } else {
392                 /* set sector offsets for top boot block type           */
393                 i = info->sector_count - 1;
394                 info->start[i--] = base + info->size - 0x00008000;
395                 info->start[i--] = base + info->size - 0x0000C000;
396                 info->start[i--] = base + info->size - 0x00010000;
397                 for (; i >= 0; i--) {
398                         info->start[i] = base + i * 0x00020000;
399                 }
400         }
401
402         /* check for protected sectors */
403         for (i = 0; i < info->sector_count; i++) {
404                 /* read sector protection at sector address, (A7 .. A0) = 0x02 */
405                 /* D0 = 1 if protected */
406                 addr = (volatile unsigned long *)(info->start[i]);
407                 info->protect[i] = addr[2] & 1;
408         }
409
410         /*
411          * Prevent writes to uninitialized FLASH.
412          */
413         if (info->flash_id != FLASH_UNKNOWN) {
414                 addr = (volatile unsigned long *)info->start[0];
415
416                 *addr = 0x00F000F0;     /* reset bank */
417         }
418
419         return (info->size);
420 }
421 #endif
422
423 /*-----------------------------------------------------------------------
424  */
425
426 int     flash_erase (flash_info_t *info, int s_first, int s_last)
427 {
428         vu_long *addr = (vu_long*)(info->start[0]);
429         int flag, prot, sect, l_sect,in_mid,in_did;
430         ulong start, now, last;
431
432         if ((s_first < 0) || (s_first > s_last)) {
433                 if (info->flash_id == FLASH_UNKNOWN) {
434                         printf ("- missing\n");
435                 } else {
436                         printf ("- no sectors to erase\n");
437                 }
438                 return 1;
439         }
440
441         if ((info->flash_id == FLASH_UNKNOWN) ||
442             (info->flash_id > FLASH_AMD_COMP)) {
443                 printf ("Can't erase unknown flash type %08lx - aborted\n",
444                         info->flash_id);
445                 return 1;
446         }
447
448         prot = 0;
449         for (sect=s_first; sect<=s_last; ++sect) {
450                 if (info->protect[sect]) {
451                         prot++;
452                 }
453         }
454
455         if (prot) {
456                 printf ("- Warning: %d protected sectors will not be erased!\n",
457                         prot);
458         } else {
459                 printf ("\n");
460         }
461
462         l_sect = -1;
463
464         /* Disable interrupts which might cause a timeout here */
465         flag = disable_interrupts();
466 #if defined (CONFIG_BOOT_8B )
467         my_out_8( (unsigned char * )  ((ulong)addr+0x555) , 0xaa );
468         my_out_8( (unsigned char * )  ((ulong)addr+0x2aa) , 0x55 );
469         my_out_8( (unsigned char * )  ((ulong)addr+0x555) , 0x90 );
470         in_mid=my_in_8( (unsigned char * ) addr );
471         in_did=my_in_8( (unsigned char * ) ((ulong)addr+1) );
472         printf(" man ID=0x%x, dev ID=0x%x.\n",in_mid,in_did );
473         my_out_8( (unsigned char *)addr, 0xf0);
474         udelay(1);
475         my_out_8(     (unsigned char *) ((ulong)addr+0x555),0xaa );
476         my_out_8(     (unsigned char *) ((ulong)addr+0x2aa),0x55 );
477         my_out_8(     (unsigned char *) ((ulong)addr+0x555),0x80 );
478         my_out_8(     (unsigned char *) ((ulong)addr+0x555),0xaa );
479         my_out_8(     (unsigned char *) ((ulong)addr+0x2aa),0x55 );
480         /* Start erase on unprotected sectors */
481         for (sect = s_first; sect<=s_last; sect++) {
482                 if (info->protect[sect] == 0) { /* not protected */
483                         addr = (vu_long*)(info->start[sect]);
484                         /*addr[0] = 0x00300030; */
485                         my_out_8(     (unsigned char *) ((ulong)addr),0x30 );
486                         l_sect = sect;
487                 }
488         }
489 #elif defined(CONFIG_BOOT_16B )
490         my_out_be16( (unsigned short * )  ((ulong)addr+ (0xaaa)) , 0xaa );
491         my_out_be16( (unsigned short * )  ((ulong)addr+ (0x554)) , 0x55 );
492         my_out_be16( (unsigned short * )  ((ulong)addr+ (0xaaa)) , 0x90 );
493         in_mid=my_in_be16( (unsigned short * ) addr );
494         in_did=my_in_be16 ( (unsigned short * ) ((ulong)addr+2) );
495         printf(" man ID=0x%x, dev ID=0x%x.\n",in_mid,in_did );
496         my_out_be16( (unsigned short *)addr, 0xf0);
497         udelay(1);
498         my_out_be16(     (unsigned short *) ((ulong)addr+ 0xaaa),0xaa );
499         my_out_be16(     (unsigned short *) ((ulong)addr+0x554),0x55 );
500         my_out_be16(     (unsigned short *) ((ulong)addr+0xaaa),0x80 );
501         my_out_be16(     (unsigned short *) ((ulong)addr+0xaaa),0xaa );
502         my_out_be16(     (unsigned short *) ((ulong)addr+0x554),0x55 );
503         /* Start erase on unprotected sectors */
504         for (sect = s_first; sect<=s_last; sect++) {
505                 if (info->protect[sect] == 0) { /* not protected */
506                         addr = (vu_long*)(info->start[sect]);
507                         my_out_be16(     (unsigned short *) ((ulong)addr),0x30 );
508                         l_sect = sect;
509                 }
510         }
511
512 #elif defined(CONFIG_BOOT_32B)
513         my_out_be32( (unsigned * )  ((ulong)addr+0x1554) , 0xaa );
514         my_out_be32( (unsigned * )  ((ulong)addr+0xaa8) , 0x55 );
515         my_out_be32( (unsigned  *)  ((ulong)addr+0x1554) , 0x90 );
516         in_mid=my_in_be32( (unsigned  * ) addr );
517         in_did=my_in_be32( (unsigned  * ) ((ulong)addr+4) );
518         printf(" man ID=0x%x, dev ID=0x%x.\n",in_mid,in_did );
519         my_out_be32( (unsigned *)addr, 0xf0);
520         udelay(1);
521         my_out_be32(     (unsigned  *) ((ulong)addr+0x1554),0xaa );
522         my_out_be32(     (unsigned  *) ((ulong)addr+0xaa8),0x55 );
523         my_out_be32(     (unsigned  *) ((ulong)addr+0x1554),0x80 );
524         my_out_be32(     (unsigned  *) ((ulong)addr+0x1554),0xaa );
525         my_out_be32(     (unsigned  *) ((ulong)addr+0xaa8),0x55 );
526         /* Start erase on unprotected sectors */
527         for (sect = s_first; sect<=s_last; sect++) {
528                 if (info->protect[sect] == 0) { /* not protected */
529                         addr = (vu_long*)(info->start[sect]);
530                         my_out_be32(     (unsigned *) ((ulong)addr),0x00300030 );
531                         l_sect = sect;
532                 }
533         }
534
535 #else
536 # error CONFIG_BOOT_(size)B missing.
537 #endif
538         /* re-enable interrupts if necessary */
539         if (flag)
540                 enable_interrupts();
541
542         /* wait at least 80us - let's wait 1 ms */
543         udelay (1000);
544
545         /*
546          * We wait for the last triggered sector
547          */
548         if (l_sect < 0)
549                 goto DONE;
550
551         start = get_timer (0);
552         last  = start;
553         addr = (vu_long*)(info->start[l_sect]);
554 #if defined (CONFIG_BOOT_8B)
555         while (  (my_in_8((unsigned char *)addr) & 0x80) != 0x80 )
556 #elif defined(CONFIG_BOOT_16B )
557         while (  (my_in_be16((unsigned short *)addr) & 0x0080) != 0x0080 )
558 #elif defined(CONFIG_BOOT_32B)
559         while (  (my_in_be32((unsigned  *)addr) & 0x00800080) != 0x00800080 )
560 #else
561 # error CONFIG_BOOT_(size)B missing.
562 #endif
563         {
564                 if ((now = get_timer(start)) > CONFIG_SYS_FLASH_ERASE_TOUT) {
565                         printf ("Timeout\n");
566                         return 1;
567                 }
568                 /* show that we're waiting */
569                 if ((now - last) > 1000) {      /* every second */
570                         putc ('.');
571                         last = now;
572                 }
573         }
574 DONE:
575         /* reset to read mode */
576         addr = (volatile unsigned long *)info->start[0];
577 #if defined (CONFIG_BOOT_8B)
578         my_out_8( (unsigned char *)addr, 0xf0);
579 #elif defined(CONFIG_BOOT_16B )
580         my_out_be16( (unsigned short * ) addr , 0x00f0 );
581 #elif defined(CONFIG_BOOT_32B)
582         my_out_be32 ( (unsigned *)addr,  0x00F000F0 );  /* reset bank */
583 #else
584 # error CONFIG_BOOT_(size)B missing.
585 #endif
586         printf (" done\n");
587         return 0;
588 }
589
590 /*-----------------------------------------------------------------------
591  * Copy memory to flash, returns:
592  * 0 - OK
593  * 1 - write timeout
594  * 2 - Flash not erased
595  */
596
597 int write_buff (flash_info_t *info, uchar *src, ulong addr, ulong cnt)
598 {
599         ulong cp, wp, data;
600         int i, l, rc;
601
602         wp = (addr & ~3);       /* get lower word aligned address */
603
604         /*
605          * handle unaligned start bytes
606          */
607         if ((l = addr - wp) != 0) {
608                 data = 0;
609                 for (i=0, cp=wp; i<l; ++i, ++cp) {
610                         data = (data << 8) | (*(uchar *)cp);
611                 }
612                 for (; i<4 && cnt>0; ++i) {
613                         data = (data << 8) | *src++;
614                         --cnt;
615                         ++cp;
616                 }
617                 for (; cnt==0 && i<4; ++i, ++cp) {
618                         data = (data << 8) | (*(uchar *)cp);
619                 }
620
621                 if ((rc = write_word(info, wp, data)) != 0) {
622                         return (rc);
623                 }
624                 wp += 4;
625         }
626
627         /*
628          * handle word aligned part
629          */
630         while (cnt >= 4) {
631                 data = 0;
632                 for (i=0; i<4; ++i) {
633                         data = (data << 8) | *src++;
634                 }
635                 if ((rc = write_word(info, wp, data)) != 0) {
636                         return (rc);
637                 }
638                 wp  += 4;
639                 cnt -= 4;
640         }
641
642         if (cnt == 0) {
643                 return (0);
644         }
645
646         /*
647          * handle unaligned tail bytes
648          */
649         data = 0;
650         for (i=0, cp=wp; i<4 && cnt>0; ++i, ++cp) {
651                 data = (data << 8) | *src++;
652                 --cnt;
653         }
654         for (; i<4; ++i, ++cp) {
655                 data = (data << 8) | (*(uchar *)cp);
656         }
657
658         return (write_word(info, wp, data));
659 }
660
661 /*-----------------------------------------------------------------------
662  * Write a word to Flash, returns:
663  * 0 - OK
664  * 1 - write timeout
665  * 2 - Flash not erased
666  */
667 static int write_word (flash_info_t *info, ulong dest, ulong data)
668 {
669         ulong addr = (ulong)(info->start[0]);
670         ulong start,last;
671         int flag;
672         ulong i;
673         int  data_short[2];
674
675         /* Check if Flash is (sufficiently) erased */
676         if ( ((ulong)  *(ulong *)dest & data) != data ) {
677                 return (2);
678         }
679         /* Disable interrupts which might cause a timeout here */
680         flag = disable_interrupts();
681 #if defined(CONFIG_BOOT_8B)
682 #ifdef DEBUG
683         {
684         int in_mid,in_did;
685         my_out_8( (unsigned char * )  (addr+0x555) , 0xaa );
686         my_out_8( (unsigned char * )  (addr+0x2aa) , 0x55 );
687         my_out_8( (unsigned char * )  (addr+0x555) , 0x90 );
688         in_mid=my_in_8( (unsigned char * ) addr );
689         in_did=my_in_8( (unsigned char * ) (addr+1) );
690         printf(" man ID=0x%x, dev ID=0x%x.\n",in_mid,in_did );
691         my_out_8( (unsigned char *)addr, 0xf0);
692         udelay(1);
693         }
694 #endif
695       {
696         int  data_ch[4];
697         data_ch[0]=(int ) ((data>>24) & 0xff);
698         data_ch[1]=(int ) ((data>>16) &0xff );
699         data_ch[2]=(int ) ((data >>8) & 0xff);
700         data_ch[3]=(int ) (data & 0xff);
701         for (i=0;i<4;i++ ){
702           my_out_8( (unsigned char *) (addr+0x555),0xaa);
703           my_out_8((unsigned char *) (addr+0x2aa),0x55);
704           my_out_8( (unsigned char *)  (addr+0x555),0xa0);
705           my_out_8((unsigned char *)  (dest+i) ,data_ch[i]);
706         /* re-enable interrupts if necessary */
707         if (flag)
708                 enable_interrupts();
709
710           start = get_timer (0);
711         last  = start;
712           while(  ( my_in_8((unsigned char *) (dest+i)) ) != ( data_ch[i]  ) ) {
713                   if (get_timer(start) > CONFIG_SYS_FLASH_WRITE_TOUT ) {
714                           return 1;
715                   }
716           }
717         }/* for */
718      }
719 #elif defined( CONFIG_BOOT_16B)
720         data_short[0]=(int) (data>>16) & 0xffff;
721         data_short[1]=(int ) data & 0xffff ;
722         for (i=0;i<2;i++ ){
723         my_out_be16(     (unsigned short *) ((ulong)addr+ 0xaaa),0xaa );
724         my_out_be16(     (unsigned short *) ((ulong)addr+ 0x554),0x55 );
725         my_out_be16(     (unsigned short *) ((ulong)addr+ 0xaaa),0xa0 );
726         my_out_be16(  (unsigned short *) (dest+(i*2)) ,data_short[i]);
727         /* re-enable interrupts if necessary */
728         if (flag)
729                 enable_interrupts();
730           start = get_timer (0);
731         last  = start;
732           while(  ( my_in_be16((unsigned short *) (dest+(i*2))) ) != ( data_short[i]  ) ) {
733                   if (get_timer(start) > CONFIG_SYS_FLASH_WRITE_TOUT ) {
734                           return 1;
735                   }
736           }
737         }
738 #elif defined( CONFIG_BOOT_32B)
739         addr[0x0555] = 0x00AA00AA;
740         addr[0x02AA] = 0x00550055;
741         addr[0x0555] = 0x00A000A0;
742
743         *((vu_long *)dest) = data;
744
745         /* re-enable interrupts if necessary */
746         if (flag)
747                 enable_interrupts();
748
749         /* data polling for D7 */
750         start = get_timer (0);
751         while ((*((vu_long *)dest) & 0x00800080) != (data & 0x00800080)) {
752                 if (get_timer(start) > CONFIG_SYS_FLASH_WRITE_TOUT) {
753                         return (1);
754                 }
755         }
756 #endif
757
758
759         return (0);
760 }
761 #ifdef  CONFIG_BOOT_8B
762 static int my_in_8  ( unsigned char *addr)
763 {
764        int ret;
765        __asm__ __volatile__("lbz%U1%X1 %0,%1; eieio" : "=r" (ret) : "m" (*addr));
766        return ret;
767 }
768
769 static void my_out_8  ( unsigned char *addr, int val)
770 {
771        __asm__ __volatile__("stb%U0%X0 %1,%0; eieio" : "=m" (*addr) : "r" (val));
772 }
773 #endif
774 #ifdef  CONFIG_BOOT_16B
775 static int my_in_be16( unsigned short *addr)
776 {
777        int ret;
778         __asm__ __volatile__("lhz%U1%X1 %0,%1; eieio" : "=r" (ret) : "m" (*addr));
779                                 return ret;
780 }
781 static void my_out_be16( unsigned short *addr, int val)
782 {
783        __asm__ __volatile__("sth%U0%X0 %1,%0; eieio" : "=m" (*addr) : "r" (val));
784 }
785 #endif
786 #ifdef  CONFIG_BOOT_32B
787 static  unsigned my_in_be32( unsigned *addr)
788 {
789         unsigned ret;
790         __asm__ __volatile__("lwz%U1%X1 %0,%1; eieio" : "=r" (ret) : "m" (*addr));
791                                 return ret;
792 }
793 static  void my_out_be32( unsigned *addr, int val)
794 {
795        __asm__ __volatile__("stw%U0%X0 %1,%0; eieio" : "=m" (*addr) : "r" (val));
796 }
797 #endif