]> git.kernelconcepts.de Git - karo-tx-uboot.git/blob - board/mvs1/flash.c
bootm: refactor do_reset and os boot function args
[karo-tx-uboot.git] / board / mvs1 / flash.c
1 /*
2  * (C) Copyright 2000
3  * Wolfgang Denk, DENX Software Engineering, wd@denx.de.
4  *
5  * Changes for MATRIX Vision MVsensor (C) Copyright 2001
6  * MATRIX Vision GmbH / hg, info@matrix-vision.de
7  *
8  * See file CREDITS for list of people who contributed to this
9  * project.
10  *
11  * This program is free software; you can redistribute it and/or
12  * modify it under the terms of the GNU General Public License as
13  * published by the Free Software Foundation; either version 2 of
14  * the License, or (at your option) any later version.
15  *
16  * This program is distributed in the hope that it will be useful,
17  * but WITHOUT ANY WARRANTY; without even the implied warranty of
18  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
19  * GNU General Public License for more details.
20  *
21  * You should have received a copy of the GNU General Public License
22  * along with this program; if not, write to the Free Software
23  * Foundation, Inc., 59 Temple Place, Suite 330, Boston,
24  * MA 02111-1307 USA
25  */
26
27 #include <common.h>
28 #include <mpc8xx.h>
29
30 #undef MVDEBUG
31 #ifdef MVDEBUG
32 #define mvdebug debug
33 #else
34 #define mvdebug(p) do {} while (0)
35 #endif
36
37
38 flash_info_t    flash_info[CFG_MAX_FLASH_BANKS]; /* info for FLASH chips        */
39
40
41 #ifdef CONFIG_MVS_16BIT_FLASH
42         #define FLASH_DATA_MASK 0xffff
43         #define FLASH_SHIFT 0
44 #else
45         #define FLASH_DATA_MASK 0xffffffff
46         #define FLASH_SHIFT 1
47 #endif
48
49
50 /*-----------------------------------------------------------------------
51  * Functions
52  */
53 static ulong flash_get_size (vu_long *address, flash_info_t *info);
54 static int write_word (flash_info_t *info, ulong dest, ulong data);
55 static void flash_get_offsets (ulong base, flash_info_t *info);
56
57 /*-----------------------------------------------------------------------
58  */
59
60 unsigned long flash_init (void)
61 {
62         volatile immap_t     *immap  = (immap_t *)CFG_IMMR;
63         volatile memctl8xx_t *memctl = &immap->im_memctl;
64         unsigned long size_b0, size_b1;
65         int i;
66
67         /* Init: no FLASHes known */
68         for (i=0; i<CFG_MAX_FLASH_BANKS; ++i) {
69                 flash_info[i].flash_id = FLASH_UNKNOWN;
70         }
71
72         /* Static FLASH Bank configuration here - FIXME XXX */
73
74         size_b0 = flash_get_size((vu_long *)FLASH_BASE0_PRELIM, &flash_info[0]);
75
76         if (flash_info[0].flash_id == FLASH_UNKNOWN) {
77                 printf ("## Unknown FLASH on Bank 0 - Size = 0x%08lx = %ld MB\n",
78                         size_b0, size_b0<<20);
79         }
80
81 #if defined (FLASH_BASE1_PRELIM)
82         size_b1 = flash_get_size((vu_long *)FLASH_BASE1_PRELIM, &flash_info[1]);
83
84         if (size_b1 > size_b0) {
85                 printf ("## ERROR: "
86                         "Bank 1 (0x%08lx = %ld MB) > Bank 0 (0x%08lx = %ld MB)\n",
87                         size_b1, size_b1<<20,
88                         size_b0, size_b0<<20
89                 );
90                 flash_info[0].flash_id  = FLASH_UNKNOWN;
91                 flash_info[1].flash_id  = FLASH_UNKNOWN;
92                 flash_info[0].sector_count      = -1;
93                 flash_info[1].sector_count      = -1;
94                 flash_info[0].size              = 0;
95                 flash_info[1].size              = 0;
96                 return (0);
97         }
98 #else
99         size_b1 = 0;
100 #endif
101
102         /* Remap FLASH according to real size */
103         memctl->memc_or0 = CFG_OR_TIMING_FLASH | (-size_b0 & 0xFFFF8000);
104 #ifdef CONFIG_MVS_16BIT_FLASH
105         memctl->memc_br0 = (CFG_FLASH_BASE & BR_BA_MSK) | BR_PS_16 | BR_MS_GPCM | BR_V;
106 #else
107         memctl->memc_br0 = (CFG_FLASH_BASE & BR_BA_MSK) | BR_PS_32 | BR_MS_GPCM | BR_V;
108 #endif
109
110         /* Re-do sizing to get full correct info */
111         size_b0 = flash_get_size((vu_long *)CFG_FLASH_BASE, &flash_info[0]);
112
113         flash_get_offsets (CFG_FLASH_BASE, &flash_info[0]);
114
115         /* monitor protection ON by default */
116         flash_protect(FLAG_PROTECT_SET,
117                       CFG_FLASH_BASE,
118                       CFG_FLASH_BASE+monitor_flash_len-1,
119                       &flash_info[0]);
120
121         if (size_b1) {
122                 memctl->memc_or1 = CFG_OR_TIMING_FLASH | (-size_b1 & 0xFFFF8000);
123 #ifdef CONFIG_MVS_16BIT_FLASH
124                 memctl->memc_br1 = ((CFG_FLASH_BASE + size_b0) & BR_BA_MSK) |
125                                     BR_PS_16 | BR_MS_GPCM | BR_V;
126 #else
127                 memctl->memc_br1 = ((CFG_FLASH_BASE + size_b0) & BR_BA_MSK) |
128                                     BR_PS_32 | BR_MS_GPCM | BR_V;
129 #endif
130                 /* Re-do sizing to get full correct info */
131                 size_b1 = flash_get_size((vu_long *)(CFG_FLASH_BASE + size_b0),
132                                           &flash_info[1]);
133
134                 flash_get_offsets (CFG_FLASH_BASE + size_b0, &flash_info[1]);
135
136                 /* monitor protection ON by default */
137                 flash_protect(FLAG_PROTECT_SET,
138                               CFG_FLASH_BASE,
139                               CFG_FLASH_BASE+monitor_flash_len-1,
140                               &flash_info[1]);
141         } else {
142                 memctl->memc_br1 = 0;           /* invalidate bank */
143
144                 flash_info[1].flash_id = FLASH_UNKNOWN;
145                 flash_info[1].sector_count = -1;
146         }
147
148         flash_info[0].size = size_b0;
149         flash_info[1].size = size_b1;
150
151         return (size_b0 + size_b1);
152 }
153
154 /*-----------------------------------------------------------------------
155  */
156 static void flash_get_offsets (ulong base, flash_info_t *info)
157 {
158         int i;
159
160         /* set up sector start address table */
161         if (info->flash_id & FLASH_BTYPE)
162         {       /* bottom boot sector types - these are the useful ones! */
163                 /* set sector offsets for bottom boot block type */
164                 if ((info->flash_id & FLASH_TYPEMASK) == FLASH_AM320B)
165                 {       /* AMDLV320B has 8 x 8k bottom boot sectors */
166                         for (i = 0; i < 8; i++)                                                                                         /* +8k          */
167                                 info->start[i] = base + (i * (0x00002000 << FLASH_SHIFT));
168                         for (; i < info->sector_count; i++)                                                                     /* +64k         */
169                                 info->start[i] = base + (i * (0x00010000 << FLASH_SHIFT)) - (0x00070000 << FLASH_SHIFT);
170                 }
171                 else
172                 {       /* other types have 4 bottom boot sectors (16,8,8,32) */
173                         i = 0;
174                         info->start[i++] = base +  0x00000000;                                                          /* -            */
175                         info->start[i++] = base + (0x00004000 << FLASH_SHIFT);                          /* +16k         */
176                         info->start[i++] = base + (0x00006000 << FLASH_SHIFT);                          /* +8k          */
177                         info->start[i++] = base + (0x00008000 << FLASH_SHIFT);                          /* +8k          */
178                         info->start[i++] = base + (0x00010000 << FLASH_SHIFT);                          /* +32k         */
179                         for (; i < info->sector_count; i++)                                                                     /* +64k         */
180                                 info->start[i] = base + (i * (0x00010000 << FLASH_SHIFT)) - (0x00030000 << FLASH_SHIFT);
181                 }
182         }
183         else
184         {       /* top boot sector types - not so useful */
185                 /* set sector offsets for top boot block type */
186                 if ((info->flash_id & FLASH_TYPEMASK) == FLASH_AM320T)
187                 {       /* AMDLV320T has 8 x 8k top boot sectors */
188                         for (i = 0; i < info->sector_count - 8; i++)                                            /* +64k         */
189                                 info->start[i] = base + (i * (0x00010000 << FLASH_SHIFT));
190                         for (; i < info->sector_count; i++)                                                                     /* +8k          */
191                                 info->start[i] = base + (i * (0x00002000 << FLASH_SHIFT));
192                 }
193                 else
194                 {       /* other types have 4 top boot sectors (32,8,8,16) */
195                         for (i = 0; i < info->sector_count - 4; i++)                                            /* +64k         */
196                                 info->start[i] = base + (i * (0x00010000 << FLASH_SHIFT));
197
198                         info->start[i++] = base + info->size - (0x00010000 << FLASH_SHIFT);     /* -32k         */
199                         info->start[i++] = base + info->size - (0x00008000 << FLASH_SHIFT);     /* -8k          */
200                         info->start[i++] = base + info->size - (0x00006000 << FLASH_SHIFT);     /* -8k          */
201                         info->start[i]   = base + info->size - (0x00004000 << FLASH_SHIFT);     /* -16k         */
202                 }
203         }
204 }
205
206 /*-----------------------------------------------------------------------
207  */
208 void flash_print_info  (flash_info_t *info)
209 {
210         int i;
211
212         if (info->flash_id == FLASH_UNKNOWN) {
213                 printf ("missing or unknown FLASH type\n");
214                 return;
215         }
216
217         switch (info->flash_id & FLASH_VENDMASK) {
218         case FLASH_MAN_AMD:     printf ("AMD ");                break;
219         case FLASH_MAN_FUJ:     printf ("FUJITSU ");    break;
220         case FLASH_MAN_STM:     printf ("ST ");                 break;
221         default:                printf ("Unknown Vendor ");     break;
222         }
223
224         switch (info->flash_id & FLASH_TYPEMASK) {
225         case FLASH_AM160B:      printf ("AM29LV160B (16 Mbit, bottom boot sect)\n");
226                                 break;
227         case FLASH_AM160T:      printf ("AM29LV160T (16 Mbit, top boot sector)\n");
228                                 break;
229         case FLASH_AM320B:      printf ("AM29LV320B (32 Mbit, bottom boot sect)\n");
230                                 break;
231         case FLASH_AM320T:      printf ("AM29LV320T (32 Mbit, top boot sector)\n");
232                                 break;
233         case FLASH_STMW320DB:   printf ("M29W320B (32 Mbit, bottom boot sect)\n");
234                                 break;
235         case FLASH_STMW320DT:   printf ("M29W320T (32 Mbit, top boot sector)\n");
236                                 break;
237         default:                printf ("Unknown Chip Type\n");
238                                 break;
239         }
240
241         printf ("  Size: %ld MB in %d Sectors\n",
242                 info->size >> 20, info->sector_count);
243
244         printf ("  Sector Start Addresses:");
245         for (i=0; i<info->sector_count; ++i) {
246                 if ((i % 5) == 0)
247                         printf ("\n   ");
248                 printf (" %08lX%s",
249                         info->start[i],
250                         info->protect[i] ? " (RO)" : "     "
251                 );
252         }
253         printf ("\n");
254 }
255
256 /*-----------------------------------------------------------------------
257  */
258
259
260 /*-----------------------------------------------------------------------
261  */
262
263 /*
264  * The following code cannot be run from FLASH!
265  */
266
267 #define AMD_ID_LV160T_MVS       (AMD_ID_LV160T & FLASH_DATA_MASK)
268 #define AMD_ID_LV160B_MVS       (AMD_ID_LV160B & FLASH_DATA_MASK)
269 #define AMD_ID_LV320T_MVS       (AMD_ID_LV320T & FLASH_DATA_MASK)
270 #define AMD_ID_LV320B_MVS       (AMD_ID_LV320B & FLASH_DATA_MASK)
271 #define STM_ID_W320DT_MVS       (STM_ID_29W320DT & FLASH_DATA_MASK)
272 #define STM_ID_W320DB_MVS       (STM_ID_29W320DB & FLASH_DATA_MASK)
273 #define AMD_MANUFACT_MVS        (AMD_MANUFACT  & FLASH_DATA_MASK)
274 #define FUJ_MANUFACT_MVS        (FUJ_MANUFACT  & FLASH_DATA_MASK)
275 #define STM_MANUFACT_MVS        (STM_MANUFACT  & FLASH_DATA_MASK)
276
277 #define AUTOSELECT_ADDR1        0x0555
278 #define AUTOSELECT_ADDR2        0x02AA
279 #define AUTOSELECT_ADDR3        AUTOSELECT_ADDR1
280
281 #define AUTOSELECT_DATA1        (0x00AA00AA & FLASH_DATA_MASK)
282 #define AUTOSELECT_DATA2        (0x00550055 & FLASH_DATA_MASK)
283 #define AUTOSELECT_DATA3        (0x00900090 & FLASH_DATA_MASK)
284
285 #define RESET_BANK_DATA         (0x00F000F0 & FLASH_DATA_MASK)
286
287 static ulong flash_get_size (vu_long *address, flash_info_t *info)
288 {
289         short i;
290 #ifdef CONFIG_MVS_16BIT_FLASH
291         ushort value;
292         vu_short *addr = (vu_short *)address;
293 #else
294         ulong value;
295         vu_long *addr = (vu_long *)address;
296 #endif
297         ulong base = (ulong)address;
298
299         /* Write auto select command: read Manufacturer ID */
300         addr[AUTOSELECT_ADDR1] = AUTOSELECT_DATA1;
301         addr[AUTOSELECT_ADDR2] = AUTOSELECT_DATA2;
302         addr[AUTOSELECT_ADDR3] = AUTOSELECT_DATA3;
303
304         value = addr[0];                        /* manufacturer ID      */
305         switch (value) {
306         case AMD_MANUFACT_MVS:
307                 info->flash_id = FLASH_MAN_AMD;
308                 break;
309         case FUJ_MANUFACT_MVS:
310                 info->flash_id = FLASH_MAN_FUJ;
311                 break;
312         case STM_MANUFACT_MVS:
313                 info->flash_id = FLASH_MAN_STM;
314                 break;
315         default:
316                 info->flash_id = FLASH_UNKNOWN;
317                 info->sector_count = 0;
318                 info->size = 0;
319                 return (0);                     /* no or unknown flash  */
320         }
321
322         value = addr[1];                        /* device ID            */
323         switch (value) {
324         case AMD_ID_LV160T_MVS:
325                 info->flash_id += FLASH_AM160T;
326                 info->sector_count = 37;
327                 info->size = (0x00200000 << FLASH_SHIFT);
328                 break;                          /* => 2 or 4 MB         */
329
330         case AMD_ID_LV160B_MVS:
331                 info->flash_id += FLASH_AM160B;
332                 info->sector_count = 37;
333                 info->size = (0x00200000 << FLASH_SHIFT);
334                 break;                          /* => 2 or 4 MB         */
335
336         case AMD_ID_LV320T_MVS:
337                 info->flash_id += FLASH_AM320T;
338                 info->sector_count = 71;
339                 info->size = (0x00400000 << FLASH_SHIFT);
340                 break;                          /* => 4 or 8 MB         */
341
342         case AMD_ID_LV320B_MVS:
343                 info->flash_id += FLASH_AM320B;
344                 info->sector_count = 71;
345                 info->size = (0x00400000 << FLASH_SHIFT);
346                 break;                          /* => 4 or 8MB          */
347
348         case STM_ID_W320DT_MVS:
349                 info->flash_id += FLASH_STMW320DT;
350                 info->sector_count = 67;
351                 info->size = (0x00400000 << FLASH_SHIFT);
352                 break;                          /* => 4 or 8 MB         */
353
354         case STM_ID_W320DB_MVS:
355                 info->flash_id += FLASH_STMW320DB;
356                 info->sector_count = 67;
357                 info->size = (0x00400000 << FLASH_SHIFT);
358                 break;                          /* => 4 or 8MB          */
359
360         default:
361                 info->flash_id = FLASH_UNKNOWN;
362                 return (0);                     /* => no or unknown flash */
363
364         }
365
366         /* set up sector start address table */
367         flash_get_offsets (base, info);
368
369         /* check for protected sectors */
370         for (i = 0; i < info->sector_count; i++) {
371                 /* read sector protection at sector address, (A7 .. A0) = 0x02 */
372                 /* D0 = 1 if protected */
373 #ifdef CONFIG_MVS_16BIT_FLASH
374                 addr = (vu_short *)(info->start[i]);
375 #else
376                 addr = (vu_long *)(info->start[i]);
377 #endif
378                 info->protect[i] = addr[2] & 1;
379         }
380
381         /*
382          * Prevent writes to uninitialized FLASH.
383          */
384         if (info->flash_id != FLASH_UNKNOWN) {
385 #ifdef CONFIG_MVS_16BIT_FLASH
386                 addr = (vu_short *)info->start[0];
387 #else
388                 addr = (vu_long *)info->start[0];
389 #endif
390                 *addr = RESET_BANK_DATA;        /* reset bank */
391         }
392
393         return (info->size);
394 }
395
396
397 /*-----------------------------------------------------------------------
398  */
399
400 #define ERASE_ADDR1 0x0555
401 #define ERASE_ADDR2 0x02AA
402 #define ERASE_ADDR3 ERASE_ADDR1
403 #define ERASE_ADDR4 ERASE_ADDR1
404 #define ERASE_ADDR5 ERASE_ADDR2
405
406 #define ERASE_DATA1 (0x00AA00AA & FLASH_DATA_MASK)
407 #define ERASE_DATA2 (0x00550055 & FLASH_DATA_MASK)
408 #define ERASE_DATA3 (0x00800080 & FLASH_DATA_MASK)
409 #define ERASE_DATA4 ERASE_DATA1
410 #define ERASE_DATA5 ERASE_DATA2
411
412 #define ERASE_SECTOR_DATA (0x00300030 & FLASH_DATA_MASK)
413 #define ERASE_CHIP_DATA (0x00100010 & FLASH_DATA_MASK)
414 #define ERASE_CONFIRM_DATA (0x00800080 & FLASH_DATA_MASK)
415
416 int     flash_erase (flash_info_t *info, int s_first, int s_last)
417 {
418 #ifdef CONFIG_MVS_16BIT_FLASH
419         vu_short *addr = (vu_short *)(info->start[0]);
420 #else
421         vu_long *addr = (vu_long *)(info->start[0]);
422 #endif
423         int flag, prot, sect, l_sect;
424         ulong start, now, last;
425
426         if ((s_first < 0) || (s_first > s_last)) {
427                 if (info->flash_id == FLASH_UNKNOWN) {
428                         printf ("- missing\n");
429                 } else {
430                         printf ("- no sectors to erase\n");
431                 }
432                 return 1;
433         }
434
435         if ((info->flash_id == FLASH_UNKNOWN) ||
436             (info->flash_id > FLASH_AMD_COMP)) {
437                 printf ("Can't erase unknown flash type %08lx - aborted\n",
438                         info->flash_id);
439                 return 1;
440         }
441
442         prot = 0;
443         for (sect=s_first; sect<=s_last; ++sect) {
444                 if (info->protect[sect]) {
445                         prot++;
446                 }
447         }
448
449         if (prot) {
450                 printf ("- Warning: %d protected sectors will not be erased!\n",
451                         prot);
452         } else {
453                 printf ("\n");
454         }
455
456         l_sect = -1;
457
458         /* Disable interrupts which might cause a timeout here */
459         flag = disable_interrupts();
460
461         addr[ERASE_ADDR1] = ERASE_DATA1;
462         addr[ERASE_ADDR2] = ERASE_DATA2;
463         addr[ERASE_ADDR3] = ERASE_DATA3;
464         addr[ERASE_ADDR4] = ERASE_DATA4;
465         addr[ERASE_ADDR5] = ERASE_DATA5;
466
467         /* Start erase on unprotected sectors */
468         for (sect = s_first; sect<=s_last; sect++) {
469                 if (info->protect[sect] == 0) { /* not protected */
470 #ifdef CONFIG_MVS_16BIT_FLASH
471                         addr = (vu_short *)(info->start[sect]);
472 #else
473                         addr = (vu_long *)(info->start[sect]);
474 #endif
475                         addr[0] = ERASE_SECTOR_DATA;
476                         l_sect = sect;
477                 }
478         }
479
480         /* re-enable interrupts if necessary */
481         if (flag)
482                 enable_interrupts();
483
484         /* wait at least 80us - let's wait 1 ms */
485         udelay (1000);
486
487         /*
488          * We wait for the last triggered sector
489          */
490         if (l_sect < 0)
491                 goto DONE;
492
493         start = get_timer (0);
494         last  = start;
495 #ifdef CONFIG_MVS_16BIT_FLASH
496         addr = (vu_short *)(info->start[l_sect]);
497 #else
498         addr = (vu_long *)(info->start[l_sect]);
499 #endif
500         while ((addr[0] & ERASE_CONFIRM_DATA) != ERASE_CONFIRM_DATA) {
501                 if ((now = get_timer(start)) > CFG_FLASH_ERASE_TOUT) {
502                         printf ("Timeout\n");
503                         return 1;
504                 }
505                 /* show that we're waiting */
506                 if ((now - last) > 1000) {      /* every second */
507                         putc ('.');
508                         last = now;
509                 }
510         }
511
512 DONE:
513         /* reset to read mode */
514 #ifdef CONFIG_MVS_16BIT_FLASH
515         addr = (vu_short *)info->start[0];
516 #else
517         addr = (vu_long *)info->start[0];
518 #endif
519         addr[0] = RESET_BANK_DATA;      /* reset bank */
520
521         printf (" done\n");
522         return 0;
523 }
524
525
526 /*-----------------------------------------------------------------------
527  * Copy memory to flash, returns:
528  * 0 - OK
529  * 1 - write timeout
530  * 2 - Flash not erased
531  */
532
533 int write_buff (flash_info_t *info, uchar *src, ulong addr, ulong cnt)
534 {
535 #define BUFF_INC 4
536         ulong cp, wp, data;
537         int i, l, rc;
538
539         mvdebug (("+write_buff %p ==> 0x%08lx, count = 0x%08lx\n", src, addr, cnt));
540
541         wp = (addr & ~3);       /* get lower word aligned address */
542         /*
543          * handle unaligned start bytes
544          */
545         if ((l = addr - wp) != 0) {
546                 mvdebug ((" handle unaligned start bytes (cnt = 0x%08%lx)\n", cnt));
547                 data = 0;
548                 for (i=0, cp=wp; i<l; ++i, ++cp) {
549                         data = (data << 8) | (*(uchar *)cp);
550                 }
551                 for (; i<BUFF_INC && cnt>0; ++i) {
552                         data = (data << 8) | *src++;
553                         --cnt;
554                         ++cp;
555                 }
556                 for (; cnt==0 && i<BUFF_INC; ++i, ++cp) {
557                         data = (data << 8) | (*(uchar *)cp);
558                 }
559
560                 if ((rc = write_word(info, wp, data)) != 0) {
561                         return (rc);
562                 }
563                 wp += BUFF_INC;
564         }
565
566         /*
567          * handle (half)word aligned part
568          */
569         mvdebug ((" handle word aligned part (cnt = 0x%08%lx)\n", cnt));
570         while (cnt >= BUFF_INC) {
571                 data = 0;
572                 for (i=0; i<BUFF_INC; ++i) {
573                         data = (data << 8) | *src++;
574                 }
575                 if ((rc = write_word(info, wp, data)) != 0) {
576                         return (rc);
577                 }
578                 wp  += BUFF_INC;
579                 cnt -= BUFF_INC;
580         }
581
582         if (cnt == 0) {
583                 return (0);
584         }
585
586         /*
587          * handle unaligned tail bytes
588          */
589         mvdebug ((" handle unaligned tail bytes (cnt = 0x%08%lx)\n", cnt));
590         data = 0;
591         for (i=0, cp=wp; i<BUFF_INC && cnt>0; ++i, ++cp) {
592                 data = (data << 8) | *src++;
593                 --cnt;
594         }
595         for (; i<BUFF_INC; ++i, ++cp) {
596                 data = (data << 8) | (*(uchar *)cp);
597         }
598
599         return (write_word(info, wp, data));
600 }
601
602 #define WRITE_ADDR1 0x0555
603 #define WRITE_ADDR2 0x02AA
604 #define WRITE_ADDR3 WRITE_ADDR1
605
606 #define WRITE_DATA1 (0x00AA00AA & FLASH_DATA_MASK)
607 #define WRITE_DATA2 (0x00550055 & FLASH_DATA_MASK)
608 #define WRITE_DATA3 (0x00A000A0 & FLASH_DATA_MASK)
609
610 #define WRITE_CONFIRM_DATA ERASE_CONFIRM_DATA
611
612 #ifndef CONFIG_MVS_16BIT_FLASH
613 /*-----------------------------------------------------------------------
614  * Write a word to Flash, returns:
615  * 0 - OK
616  * 1 - write timeout
617  * 2 - Flash not erased
618  */
619 static int write_word (flash_info_t *info, ulong dest, ulong data)
620 {
621         vu_long *addr = (vu_long *)(info->start[0]);
622         ulong start;
623         int flag;
624
625         mvdebug (("+write_word (to 0x%08lx)\n", dest));
626         /* Check if Flash is (sufficiently) erased */
627         if ((*((vu_long *)dest) & data) != data) {
628                 return (2);
629         }
630         /* Disable interrupts which might cause a timeout here */
631         flag = disable_interrupts();
632
633         addr[WRITE_ADDR1] = WRITE_DATA1;
634         addr[WRITE_ADDR2] = WRITE_DATA2;
635         addr[WRITE_ADDR3] = WRITE_DATA3;
636
637         *((vu_long *)dest) = data;
638
639         /* re-enable interrupts if necessary */
640         if (flag)
641                 enable_interrupts();
642
643         /* data polling for D7 */
644         start = get_timer (0);
645         addr = (vu_long *)dest;
646         while ((*addr & WRITE_CONFIRM_DATA) != (data & WRITE_CONFIRM_DATA)) {
647                 if (get_timer(start) > CFG_FLASH_WRITE_TOUT) {
648                         return (1);
649                 }
650         }
651
652         mvdebug (("-write_word\n"));
653         return (0);
654 }
655 #else /* CONFIG_MVS_16BIT_FLASH */
656 /*-----------------------------------------------------------------------
657  * Write a halfword to Flash, returns:
658  * 0 - OK
659  * 1 - write timeout
660  * 2 - Flash not erased
661  */
662 static int write_halfword (flash_info_t *info, ulong dest, ushort data)
663 {
664         vu_short *addr = (vu_short *)(info->start[0]);
665         ulong start;
666         int flag;
667
668         mvdebug (("+write_halfword (to 0x%08lx)\n", dest));
669         /* Check if Flash is (sufficiently) erased */
670         if ((*((vu_short *)dest) & data) != data) {
671                 return (2);
672         }
673         /* Disable interrupts which might cause a timeout here */
674         flag = disable_interrupts();
675
676         addr[WRITE_ADDR1] = WRITE_DATA1;
677         addr[WRITE_ADDR2] = WRITE_DATA2;
678         addr[WRITE_ADDR3] = WRITE_DATA3;
679
680         *((vu_short *)dest) = data;
681
682         /* re-enable interrupts if necessary */
683         if (flag)
684                 enable_interrupts();
685
686         /* data polling for D7 */
687         start = get_timer (0);
688         addr = (vu_short *)dest;
689         while ((*addr & WRITE_CONFIRM_DATA) != (data & WRITE_CONFIRM_DATA)) {
690                 if (get_timer(start) > CFG_FLASH_WRITE_TOUT) {
691                         return (1);
692                 }
693         }
694         mvdebug (("-write_halfword\n"));
695         return (0);
696 }
697
698
699 /*-----------------------------------------------------------------------
700  * Write a word to Flash, returns:
701  * 0 - OK
702  * 1 - write timeout
703  * 2 - Flash not erased
704  */
705 static int write_word (flash_info_t *info, ulong dest, ulong data)
706 {
707         int result = 0;
708
709         if (write_halfword (info, dest, (data & ~FLASH_DATA_MASK) >> 16) == 0)
710         {
711                 dest += 2;
712                 data = data & FLASH_DATA_MASK;
713                 result = write_halfword (info, dest, data);
714         }
715         return result;
716 }
717 #endif
718 /*-----------------------------------------------------------------------
719  */