1/*  *********************************************************************
2    *  Broadcom Common Firmware Environment (CFE)
3    *
4    *  Flash write module		File: dev_generic_flashop.c
5    *
6    *  Generic "C" version of the flashop engine that we can use
7    *  on any platform that supports relocation.
8    *
9    *  Author:  Mitch Lichtenberg
10    *
11    *********************************************************************
12    *
13    *  Copyright 2000,2001,2002,2003,2004,2005
14    *  Broadcom Corporation. All rights reserved.
15    *
16    *  This software is furnished under license and may be used and
17    *  copied only in accordance with the following terms and
18    *  conditions.  Subject to these conditions, you may download,
19    *  copy, install, use, modify and distribute modified or unmodified
20    *  copies of this software in source and/or binary form.  No title
21    *  or ownership is transferred hereby.
22    *
23    *  1) Any source code used, modified or distributed must reproduce
24    *     and retain this copyright notice and list of conditions
25    *     as they appear in the source file.
26    *
27    *  2) No right is granted to use any trade name, trademark, or
28    *     logo of Broadcom Corporation.  The "Broadcom Corporation"
29    *     name may not be used to endorse or promote products derived
30    *     from this software without the prior written permission of
31    *     Broadcom Corporation.
32    *
33    *  3) THIS SOFTWARE IS PROVIDED "AS-IS" AND ANY EXPRESS OR
34    *     IMPLIED WARRANTIES, INCLUDING BUT NOT LIMITED TO, ANY IMPLIED
35    *     WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR
36    *     PURPOSE, OR NON-INFRINGEMENT ARE DISCLAIMED. IN NO EVENT
37    *     SHALL BROADCOM BE LIABLE FOR ANY DAMAGES WHATSOEVER, AND IN
38    *     PARTICULAR, BROADCOM SHALL NOT BE LIABLE FOR DIRECT, INDIRECT,
39    *     INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
40    *     (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE
41    *     GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
42    *     BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
43    *     OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR
44    *     TORT (INCLUDING NEGLIGENCE OR OTHERWISE), EVEN IF ADVISED OF
45    *     THE POSSIBILITY OF SUCH DAMAGE.
46    ********************************************************************* */
47
48#include "cfe.h"
49#include "dev_newflash.h"
50#include "lib_physio.h"
51
52#if (!FLASH_XOR_ADDR)
53#define FLASHCMD_8(base,offset,value) phys_write8((base)+(offset),(value))
54#define FLASHCMD_16(base,offset,value) phys_write16((base)+((offset)<<1),(value))
55#define FLASHCMD_16B(base,offset,value) phys_write8((base)+((offset)<<1),(value))
56#else
57/* Invert the low order bits so that hw inversion will restore them. */
58#define FLASHCMD_8(base,offset,value) phys_write8(((base)+(offset))^3,(value))
59#define FLASHCMD_16(base,offset,value) phys_write16(((base)+((offset)<<1))^2,(value))
60#define FLASHCMD_16B(base,offset,value) phys_write8(((base)+((offset)<<1))^3,(value))
61#endif
62
63long flashop_engine_generic(flashinstr_t *inst);
64
65long flashop_engine_generic(flashinstr_t *inst)
66{
67    long result = 0;
68    volatile uint8_t *dest8;
69    volatile uint16_t *dest16;
70    volatile uint8_t *src8;
71    volatile uint16_t *src16;
72    uint16_t w16,b16;
73    uint8_t w8,b8,wrrev;
74    uint32_t w32;
75    long cnt,cnt2,wrbufsz;
76    physaddr_t base;
77    physaddr_t pptr;
78    physaddr_t dsave;
79
80
81    while (inst->fi_op != FEOP_RETURN) {
82
83	base = inst->fi_base;
84	cnt = inst->fi_cnt;
85
86	switch (inst->fi_op) {
87	    case FEOP_RETURN :
88		break;
89
90	    case FEOP_REBOOT :
91		break;
92
93	    case FEOP_READ8 :
94		pptr = base + inst->fi_src;
95		dest8 = (volatile uint8_t *) inst->fi_dest;
96		while (cnt > 0) {
97		    *dest8++ = phys_read8(pptr++);
98		    cnt--;
99		    }
100		break;
101
102	    case FEOP_READ16 :
103		pptr = base + inst->fi_src;
104		dest8 = (volatile uint8_t *) inst->fi_dest;
105
106		if ((cnt > 0) && (pptr & 1)) {
107		    w16 = phys_read16(pptr & ~1);
108#if !ENDIAN_BIG
109		    w16 >>= 8;
110#endif
111		    *dest8++ = (uint8_t) w16;
112		    pptr++;
113		    cnt--;
114		    }
115
116		while (cnt > 1) {
117		    w16 = phys_read16(pptr);
118#if ENDIAN_BIG
119		    *dest8++ = (uint8_t) (w16 >> 8);
120		    *dest8++ = (uint8_t) (w16 & 0xFF);
121#else
122		    *dest8++ = (uint8_t) (w16 & 0xFF);
123		    *dest8++ = (uint8_t) (w16 >> 8);
124#endif
125		    pptr+=2;
126		    cnt-=2;
127		    }
128
129		if (cnt > 0) {
130		    w16 = phys_read16(pptr);
131#if ENDIAN_BIG
132		    w16 >>= 8;
133#endif
134		    *dest8++ = (uint8_t) w16;
135		    }
136
137		    break;
138
139/* CFI - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
140#if (FLASH_DRIVERS & FLASH_DRIVER_CFI)
141	    case FEOP_CFIQUERY8 :
142#if FLASH_XOR_ADDR
143		wrrev = 3;
144#else
145		wrrev = 0;
146#endif
147		pptr = base + inst->fi_src;
148		dest8 = (volatile uint8_t *) inst->fi_dest;
149
150		FLASHCMD_8(base,FLASH_CFI_QUERY_ADDR,FLASH_CFI_QUERY_MODE);
151
152		while (cnt > 0) {
153		    *dest8++ = phys_read8(pptr^wrrev);
154		    pptr++;
155		    cnt--;
156		    }
157
158		FLASHCMD_8(base,FLASH_CFI_QUERY_ADDR,FLASH_CFI_QUERY_EXIT);
159		break;
160
161	    case FEOP_CFIQUERY16 :
162#if FLASH_XOR_ADDR
163		wrrev = 2;
164#else
165		wrrev = 0;
166#endif
167		pptr = base + inst->fi_src;
168		dest16 = (volatile uint16_t *) inst->fi_dest;
169
170		FLASHCMD_16(base,FLASH_CFI_QUERY_ADDR,FLASH_CFI_QUERY_MODE);
171
172		while (cnt > 1) {
173		    *dest16++ = phys_read16(pptr^wrrev);
174		    pptr += 2;
175		    cnt -= 2;
176		    }
177
178		FLASHCMD_16(base,FLASH_CFI_QUERY_ADDR,FLASH_CFI_QUERY_EXIT);
179		break;
180
181	    case FEOP_CFIQUERY16B :
182#if FLASH_XOR_ADDR
183		wrrev = 3;
184#else
185		wrrev = 0;
186#endif
187		pptr = base + inst->fi_src;
188		dest8 = (volatile uint8_t *) inst->fi_dest;
189
190		FLASHCMD_16B(base,FLASH_CFI_QUERY_ADDR,FLASH_CFI_QUERY_MODE);
191
192		while (cnt > 0) {
193		    *dest8++ = phys_read8(pptr^wrrev);
194		    pptr++;
195		    cnt--;
196		    }
197
198		FLASHCMD_16B(base,FLASH_CFI_QUERY_ADDR,FLASH_CFI_QUERY_EXIT);
199		break;
200#endif
201
202	    case FEOP_MEMCPY :
203		dest8 = (volatile uint8_t *) inst->fi_dest;
204		src8 = (volatile uint8_t *) inst->fi_src;
205		while (cnt > 0) {
206		    *dest8++ = *src8++;
207		    cnt--;
208		    }
209		break;
210
211/* AMD  - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
212#if (FLASH_DRIVERS & FLASH_DRIVER_AMD)
213	    case FEOP_AMD_ERASE8 :
214		pptr = base + inst->fi_dest;
215
216		/* Do an "unlock write" sequence  (cycles 1-2) */
217
218		FLASHCMD_8(base,AMD_FLASH_MAGIC_ADDR_1,AMD_FLASH_MAGIC_1);
219		FLASHCMD_8(base,AMD_FLASH_MAGIC_ADDR_2,AMD_FLASH_MAGIC_2);
220
221		/* send the erase command (cycle 3) */
222
223		FLASHCMD_8(base,AMD_FLASH_MAGIC_ADDR_1,AMD_FLASH_ERASE_3);
224
225		/* Do an "unlock write" sequence (cycles 4-5) */
226
227		FLASHCMD_8(base,AMD_FLASH_MAGIC_ADDR_1,AMD_FLASH_MAGIC_1);
228		FLASHCMD_8(base,AMD_FLASH_MAGIC_ADDR_2,AMD_FLASH_MAGIC_2);
229
230		/* Send the "erase sector" qualifier (cycle 6) */
231
232		FLASHCMD_8(pptr,0,AMD_FLASH_ERASE_SEC_6);
233
234		/* Wait for the erase to complete */
235
236		while (phys_read8(pptr) != 0xFF) ; /* null loop */
237
238		break;
239
240	    case FEOP_AMD_ERASE16 :
241		pptr = base + inst->fi_dest;
242
243		/* Do an "unlock write" sequence  (cycles 1-2) */
244
245		FLASHCMD_16(base,AMD_FLASH_MAGIC_ADDR_1,AMD_FLASH_MAGIC_1);
246		FLASHCMD_16(base,AMD_FLASH_MAGIC_ADDR_2,AMD_FLASH_MAGIC_2);
247
248		/* send the erase command (cycle 3) */
249
250		FLASHCMD_16(base,AMD_FLASH_MAGIC_ADDR_1,AMD_FLASH_ERASE_3);
251
252		/* Do an "unlock write" sequence (cycles 4-5) */
253
254		FLASHCMD_16(base,AMD_FLASH_MAGIC_ADDR_1,AMD_FLASH_MAGIC_1);
255		FLASHCMD_16(base,AMD_FLASH_MAGIC_ADDR_2,AMD_FLASH_MAGIC_2);
256
257		/* Send the "erase sector" qualifier (cycle 6) */
258
259		FLASHCMD_16(pptr,0,AMD_FLASH_ERASE_SEC_6);
260
261		/* Wait for the erase to complete */
262
263		while ((phys_read16(pptr) & 0xFF) != 0xFF) ; /* null loop */
264
265		break;
266
267	    case FEOP_AMD_ERASE16B :
268		pptr = base + inst->fi_dest;
269
270		/* Do an "unlock write" sequence  (cycles 1-2) */
271
272		FLASHCMD_16B(base,AMD_FLASH_MAGIC_ADDR_1,AMD_FLASH_MAGIC_1);
273		FLASHCMD_16B(base,AMD_FLASH_MAGIC_ADDR_2,AMD_FLASH_MAGIC_2);
274
275		/* send the erase command (cycle 3) */
276
277		FLASHCMD_16B(base,AMD_FLASH_MAGIC_ADDR_1,AMD_FLASH_ERASE_3);
278
279		/* Do an "unlock write" sequence (cycles 4-5) */
280
281		FLASHCMD_16B(base,AMD_FLASH_MAGIC_ADDR_1,AMD_FLASH_MAGIC_1);
282		FLASHCMD_16B(base,AMD_FLASH_MAGIC_ADDR_2,AMD_FLASH_MAGIC_2);
283
284		/* Send the "erase sector" qualifier (cycle 6) */
285
286		FLASHCMD_16B(pptr,0,AMD_FLASH_ERASE_SEC_6);
287
288		/* Wait for the erase to complete */
289
290		while ((phys_read8(pptr) & 0xFF) != 0xFF) ; /* null loop */
291
292		break;
293
294	    case FEOP_AMD_PGM8 :
295		pptr = base + inst->fi_dest;
296		src8 = (volatile uint8_t *) inst->fi_src;
297
298		while (cnt > 0) {
299
300		    FLASHCMD_8(base,AMD_FLASH_MAGIC_ADDR_1,AMD_FLASH_MAGIC_1);
301		    FLASHCMD_8(base,AMD_FLASH_MAGIC_ADDR_2,AMD_FLASH_MAGIC_2);
302
303		    /* Send a program command (cycle 3) */
304
305		    FLASHCMD_8(base,AMD_FLASH_MAGIC_ADDR_1,AMD_FLASH_PROGRAM);
306
307		    /* Write a byte (cycle 4) */
308
309		    b8 = *src8;
310		    phys_write8(pptr,b8);
311
312		    /* Wait for write to complete */
313
314		    for (;;) {
315			w8 = phys_read8(pptr);
316			if ((w8 & 0x80) == (b8 & 0x80)) break;
317			if ((w8 & 0x20) != 0x20) continue;
318			break;
319			}
320
321		    cnt--;
322		    pptr++;
323		    src8++;
324		    }
325
326		break;
327
328	    case FEOP_AMD_PGM16 :
329		pptr = base + inst->fi_dest;
330		src16 = (volatile uint16_t *) inst->fi_src;
331
332		while (cnt > 0) {
333
334		    /* Do an "unlock write" sequence  (cycles 1-2) */
335
336		    FLASHCMD_16(base,AMD_FLASH_MAGIC_ADDR_1,AMD_FLASH_MAGIC_1);
337		    FLASHCMD_16(base,AMD_FLASH_MAGIC_ADDR_2,AMD_FLASH_MAGIC_2);
338
339		    /* Send a program command (cycle 3) */
340
341		    FLASHCMD_16(base,AMD_FLASH_MAGIC_ADDR_1,AMD_FLASH_PROGRAM);
342
343		    /* Write a byte (cycle 4) */
344
345		    b16 = *src16;
346		    phys_write16(pptr,b16);
347
348		    /* Wait for write to complete */
349
350		    for (;;) {
351			w16 = phys_read16(pptr);
352			if ((w16 & 0x80) == (b16 & 0x80)) break;
353			if ((w16 & 0x20) != 0x20) continue;
354			break;
355			}
356
357		    pptr += 2;
358		    cnt -= 2;
359		    src16++;
360		    }
361
362		break;
363
364	    case FEOP_AMD_PGM16B :
365		pptr = base + inst->fi_dest;
366		src8 = (volatile uint8_t *) inst->fi_src;
367
368		while (cnt > 0) {
369
370		    FLASHCMD_16B(base,AMD_FLASH_MAGIC_ADDR_1,AMD_FLASH_MAGIC_1);
371		    FLASHCMD_16B(base,AMD_FLASH_MAGIC_ADDR_2,AMD_FLASH_MAGIC_2);
372
373		    /* Send a program command (cycle 3) */
374
375		    FLASHCMD_16B(base,AMD_FLASH_MAGIC_ADDR_1,AMD_FLASH_PROGRAM);
376
377		    /* Write a byte (cycle 4) */
378
379		    b8 = *src8;
380		    phys_write8(pptr,b8);
381
382		    /* Wait for write to complete */
383
384		    for (;;) {
385			w8 = phys_read8(pptr);
386			if ((w8 & 0x80) == (b8 & 0x80)) break;
387			if ((w8 & 0x20) != 0x20) continue;
388			break;
389			}
390
391		    cnt--;
392		    pptr++;
393		    src8++;
394		    }
395
396		break;
397
398	    case FEOP_AMD_DEVCODE8 :
399		pptr = base + inst->fi_src;
400		dest8 = (volatile uint8_t *) inst->fi_dest;
401
402		FLASHCMD_8(base,AMD_FLASH_MAGIC_ADDR_1,AMD_FLASH_MAGIC_1);
403		FLASHCMD_8(base,AMD_FLASH_MAGIC_ADDR_2,AMD_FLASH_MAGIC_2);
404		FLASHCMD_8(base,AMD_FLASH_MAGIC_ADDR_1,AMD_FLASH_AUTOSEL);
405
406		w8 = phys_read8(pptr);
407		*dest8 = w8;
408
409		phys_write8(base,AMD_FLASH_RESET);
410
411		break;
412
413	    case FEOP_AMD_DEVCODE16 :
414		pptr = base + inst->fi_src;
415		dest8 = (volatile uint8_t *) inst->fi_dest;
416
417		FLASHCMD_16(base,AMD_FLASH_MAGIC_ADDR_1,AMD_FLASH_MAGIC_1);
418		FLASHCMD_16(base,AMD_FLASH_MAGIC_ADDR_2,AMD_FLASH_MAGIC_2);
419		FLASHCMD_16(base,AMD_FLASH_MAGIC_ADDR_1,AMD_FLASH_AUTOSEL);
420
421		w32 = phys_read32(pptr);
422#if (ENDIAN_BIG && !FLASH_XOR_ADDR)
423		*dest8 = (uint8_t)(w32 >> 8);
424#else
425		*dest8 = (uint8_t)(w32 >> 16);
426#endif
427		phys_write8(base,AMD_FLASH_RESET);
428
429		break;
430
431	    case FEOP_AMD_DEVCODE16B :
432		pptr = base + inst->fi_src;
433		dest8 = (volatile uint8_t *) inst->fi_dest;
434
435		FLASHCMD_16B(base,AMD_FLASH_MAGIC_ADDR_1,AMD_FLASH_MAGIC_1);
436		FLASHCMD_16B(base,AMD_FLASH_MAGIC_ADDR_2,AMD_FLASH_MAGIC_2);
437		FLASHCMD_16B(base,AMD_FLASH_MAGIC_ADDR_1,AMD_FLASH_AUTOSEL);
438
439		w32 = phys_read32(pptr);
440#if (ENDIAN_BIG && !FLASH_XOR_ADDR)
441		*dest8 = (uint8_t) w32;
442#else
443		*dest8 = (uint8_t) (w32 >> 16);
444#endif
445		phys_write8(base,AMD_FLASH_RESET);
446
447		break;
448
449	    case FEOP_AMD_MANID8 :
450		pptr = base + inst->fi_src;
451		dest8 = (volatile uint8_t *) inst->fi_dest;
452
453		FLASHCMD_8(base,AMD_FLASH_MAGIC_ADDR_1,AMD_FLASH_MAGIC_1);
454		FLASHCMD_8(base,AMD_FLASH_MAGIC_ADDR_2,AMD_FLASH_MAGIC_2);
455		FLASHCMD_8(base,AMD_FLASH_MAGIC_ADDR_1,AMD_FLASH_AUTOSEL);
456
457		w8 = phys_read8(pptr + AMD_FLASH_MANID);
458		*dest8 = w8;
459
460		phys_write8(base,AMD_FLASH_RESET);
461
462		break;
463
464	    case FEOP_AMD_MANID16 :
465		pptr = base + inst->fi_src;
466		dest8 = (volatile uint8_t *) inst->fi_dest;
467
468		FLASHCMD_16(base,AMD_FLASH_MAGIC_ADDR_1,AMD_FLASH_MAGIC_1);
469		FLASHCMD_16(base,AMD_FLASH_MAGIC_ADDR_2,AMD_FLASH_MAGIC_2);
470		FLASHCMD_16(base,AMD_FLASH_MAGIC_ADDR_1,AMD_FLASH_AUTOSEL);
471
472		w32 = phys_read32(pptr);
473
474#if (ENDIAN_BIG && !FLASH_XOR_ADDR)
475		*dest8 = (uint8_t) (w32 >> ((3-AMD_FLASH_MANID)*8));
476#else
477		*dest8 = (uint8_t) (w32 >> (AMD_FLASH_MANID*8));
478#endif
479
480		phys_write8(base,AMD_FLASH_RESET);
481
482	    case FEOP_AMD_MANID16B :
483		pptr = base + inst->fi_src;
484		dest8 = (volatile uint8_t *) inst->fi_dest;
485
486		FLASHCMD_16B(base,AMD_FLASH_MAGIC_ADDR_1,AMD_FLASH_MAGIC_1);
487		FLASHCMD_16B(base,AMD_FLASH_MAGIC_ADDR_2,AMD_FLASH_MAGIC_2);
488		FLASHCMD_16B(base,AMD_FLASH_MAGIC_ADDR_1,AMD_FLASH_AUTOSEL);
489
490		w8 = phys_read8(pptr + AMD_FLASH_MANID);
491
492		*dest8 = w8;
493
494		phys_write8(base,AMD_FLASH_RESET);
495		break;
496#endif
497
498/* INTEL  - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
499#if (FLASH_DRIVERS & FLASH_DRIVER_INTEL)
500	    case FEOP_INTEL_ERASE8 :
501
502		pptr = base + inst->fi_dest;
503
504		FLASHCMD_8(pptr,0,INTEL_FLASH_ERASE_BLOCK);
505		FLASHCMD_8(pptr,0,INTEL_FLASH_ERASE_CONFIRM);
506
507		while ((phys_read8(pptr) & 0x80) == 0) ; /* NULL LOOP */
508
509		FLASHCMD_8(pptr,0,INTEL_FLASH_READ_MODE);
510		break;
511
512	    case FEOP_INTEL_ERASE16 :
513		pptr = base + inst->fi_dest;
514
515		FLASHCMD_16(pptr,0,INTEL_FLASH_ERASE_BLOCK);
516		FLASHCMD_16(pptr,0,INTEL_FLASH_ERASE_CONFIRM);
517
518		while ((phys_read16(pptr) & 0x80) == 0) ; /* NULL LOOP */
519
520		FLASHCMD_16(pptr,0,INTEL_FLASH_READ_MODE);
521		break;
522
523	    case FEOP_INTEL_PGM8 :
524		pptr = base + inst->fi_dest;
525		src8 = (volatile uint8_t *) inst->fi_src;
526
527		while (cnt > 0) {
528		    FLASHCMD_8(pptr,0,INTEL_FLASH_PROGRAM);
529
530		    b8 = *src8;
531		    phys_write8(pptr,b8);
532
533		    while ((phys_read8(pptr) & 0x80) == 0) ; /* NULL LOOP */
534
535		    src8++;
536		    pptr++;
537		    cnt--;
538		    }
539
540		FLASHCMD_8(pptr,0,INTEL_FLASH_READ_MODE);
541		break;
542
543	    case FEOP_INTEL_PGM16 :
544		pptr = base + inst->fi_dest;
545		src16 = (volatile uint16_t *) inst->fi_src;
546
547		while (cnt > 0) {
548		    FLASHCMD_16(pptr,0,INTEL_FLASH_PROGRAM);
549
550		    b16 = *src16;
551		    phys_write16(pptr,b16);
552
553		    while ((phys_read16(pptr) & 0x80) == 0) ; /* NULL LOOP */
554
555		    src16++;
556		    pptr+=2;
557		    cnt-=2;
558		    }
559
560		FLASHCMD_16(pptr,0,INTEL_FLASH_READ_MODE);
561		break;
562
563	    case FEOP_INTEL_PGM32B :
564#if FLASH_XOR_ADDR
565                /* Write in reverse order (no swap!).
566
567		   XXX This trick works only if the source and destination
568		   have the same alignment with respect to 32-bit word
569		   boundaries.  For simplicity, the current code assumes
570		   32-bit alignment and a length that is a multiple of
571		   32 bytes.  The dev_newflash driver always writes full
572		   sectors and guarantees this.  Other applicatons (e.g.,
573		   dribble updates) should not use this operation.
574		*/
575		wrrev = 3;
576#else
577		wrrev = 0;
578#endif
579		pptr = base + inst->fi_dest;
580		src8 = (volatile uint8_t *) inst->fi_src;
581		dsave = pptr;
582
583		while (cnt > 0) {
584		    FLASHCMD_8(pptr,0,INTEL_FLASH_WRITE_BUFFER);
585		    while ((phys_read8(pptr) & 0x80) == 0) ; /* NULL LOOP */
586		    wrbufsz = 32;
587		    phys_write8(pptr,(wrbufsz-1));	/* Device wants n-1 value */
588		    for (cnt2 = 0; cnt2 < wrbufsz; cnt2++) {
589			phys_write8(pptr^wrrev,src8[cnt2^wrrev]);
590			pptr++;
591			cnt--;
592			}
593		    src8 += wrbufsz;
594		    FLASHCMD_8(dsave,0,INTEL_FLASH_ERASE_CONFIRM); /* Program buffer to flash */
595		    while ((phys_read8(dsave) & 0x80) == 0) ; /* NULL LOOP */
596		    }
597
598		FLASHCMD_8(dsave,0,INTEL_FLASH_READ_STATUS);
599		while ((phys_read8(dsave) & 0x80) == 0) ; /* NULL LOOP */
600
601		phys_read8(dsave);
602
603		FLASHCMD_8(dsave,0,INTEL_FLASH_READ_MODE);
604		break;
605#endif /* FLASH_DRIVER_INTEL */
606
607	    }
608
609	inst++;
610	}
611
612    return result;
613}
614
615void *flashop_engine_ptr = flashop_engine_generic;
616int flashop_engine_len  = 1024; /* gack! */
617