allow coexistance of N build and AC build.
[tomato.git] / release / src-rt-6.x / cfe / cfe / arch / mips / board / pt1125 / src / dev_ptflash.c
blob6646b69970083c7637d353c123b04aa597daa970
1 /* *********************************************************************
2 * Broadcom Common Firmware Environment (CFE)
3 *
4 * Flash device driver File: dev_ptflash.c
5 * (special version for production test board)
6 *
7 * This driver supports various types of flash
8 * parts. You can also put the environment storage in
9 * the flash - the top sector is reserved for that purpose.
11 * Author: Mitch Lichtenberg (mpl@broadcom.com)
13 *********************************************************************
15 * Copyright 2000,2001
16 * Broadcom Corporation. All rights reserved.
18 * This software is furnished under license and may be used and
19 * copied only in accordance with the following terms and
20 * conditions. Subject to these conditions, you may download,
21 * copy, install, use, modify and distribute modified or unmodified
22 * copies of this software in source and/or binary form. No title
23 * or ownership is transferred hereby.
25 * 1) Any source code used, modified or distributed must reproduce
26 * and retain this copyright notice and list of conditions as
27 * they appear in the source file.
29 * 2) No right is granted to use any trade name, trademark, or
30 * logo of Broadcom Corporation. Neither the "Broadcom
31 * Corporation" name nor any trademark or logo of Broadcom
32 * Corporation may be used to endorse or promote products
33 * derived from this software without the prior written
34 * permission of Broadcom Corporation.
36 * 3) THIS SOFTWARE IS PROVIDED "AS-IS" AND ANY EXPRESS OR
37 * IMPLIED WARRANTIES, INCLUDING BUT NOT LIMITED TO, ANY IMPLIED
38 * WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR
39 * PURPOSE, OR NON-INFRINGEMENT ARE DISCLAIMED. IN NO EVENT
40 * SHALL BROADCOM BE LIABLE FOR ANY DAMAGES WHATSOEVER, AND IN
41 * PARTICULAR, BROADCOM SHALL NOT BE LIABLE FOR DIRECT, INDIRECT,
42 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
43 * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE
44 * GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
45 * BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
46 * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR
47 * TORT (INCLUDING NEGLIGENCE OR OTHERWISE), EVEN IF ADVISED OF
48 * THE POSSIBILITY OF SUCH DAMAGE.
49 ********************************************************************* */
52 #include "sbmips.h"
53 #include "sb1250_defs.h"
54 #include "lib_types.h"
55 #include "lib_malloc.h"
56 #include "lib_printf.h"
57 #include "lib_string.h"
58 #include "addrspace.h"
59 #include "cfe_iocb.h"
60 #include "cfe_console.h"
61 #include "cfe_device.h"
62 #include "cfe_ioctl.h"
63 #include "cfe_error.h"
65 #include "dev_ptflash.h"
66 #include "cfe_timer.h"
68 /* *********************************************************************
69 * Macros
70 ********************************************************************* */
72 #ifdef __long64
74 /* When using processor in 64-bit mode, use XKSEG instead of KSEG1 */
76 #define FLASHCMD(sc,x,y) *((volatile unsigned char *) PHYS_TO_XKSEG_UNCACHED(\
77 ( (uintptr_t) ((sc)->flashdrv_cmdaddr+ \
78 (sc)->chip_select * (sc)->flashdrv_probe.chipsize + \
79 ((x)<<(sc)->flashdrv_widemode))))) = (y)
81 #define FLASHSTATUS(sc,x) *((volatile unsigned char *) PHYS_TO_XKSEG_UNCACHED(\
82 ((uintptr_t)((sc)->flashdrv_cmdaddr+ \
83 (sc)->chip_select * (sc)->flashdrv_probe.chipsize + \
84 ((x)<<(sc)->flashdrv_widemode)))))
86 #define WRITEFLASH_K1(sc,x,y) \
87 *((volatile unsigned char *) PHYS_TO_XKSEG_UNCACHED(\
88 ((uintptr_t) ((sc)->flashdrv_cmdaddr+(x))))) = (y)
90 #define READFLASH_K1(sc,x) *((volatile unsigned char *) PHYS_TO_XKSEG_UNCACHED(\
91 ((uintptr_t) ((sc)->flashdrv_cmdaddr+(x)))))
93 #define WRITEFLASH_K1W(sc,x,y) *((volatile unsigned short *) \
94 PHYS_TO_XKSEG_UNCACHED((uintptr_t) \
95 (sc->flashdrv_cmdaddr+(x)))) = (y)
97 #define READFLASH_K1W(sc,x) *((volatile unsigned short *) \
98 PHYS_TO_XKSEG_UNCACHED((uintptr_t) \
99 (sc->flashdrv_cmdaddr+(x))))
101 #else /* 32-bit addressing */
103 #define FLASHCMD(sc,x,y) *((volatile unsigned char *)(sc->flashdrv_cmdaddr+ \
104 (sc)->chip_select * (sc)->flashdrv_probe.chipsize + \
105 ((x)<<(sc)->flashdrv_widemode))) = (y)
106 #define FLASHSTATUS(sc,x) *((volatile unsigned char *)(sc->flashdrv_cmdaddr+ \
107 (sc)->chip_select * (sc)->flashdrv_probe.chipsize + \
108 ((x)<<(sc)->flashdrv_widemode)))
109 #define WRITEFLASH_K1(sc,x,y) *((volatile unsigned char *)(sc->flashdrv_cmdaddr+(x))) = (y)
110 #define READFLASH_K1(sc,x) *((volatile unsigned char *)(sc->flashdrv_cmdaddr+(x)))
112 #define WRITEFLASH_K1W(sc,x,y) *((volatile unsigned short *)(sc->flashdrv_cmdaddr+(x))) = (y)
113 #define READFLASH_K1W(sc,x) *((volatile unsigned short *)(sc->flashdrv_cmdaddr+(x)))
115 #endif /* __long64 */
117 #define GETCFIBYTE(softc,offset) READFLASH_K1(softc,((offset) << (softc->flashdrv_widemode)))
119 /* Convert microseconds to ticks, assuming 1 GHz processor clock (CP0 clock is half that) */
121 #define USEC_TO_TICK(x) (1000*(x) >> 1)
123 /* *********************************************************************
124 * Forward declarations
125 ********************************************************************* */
128 static void flashdrv_probe(cfe_driver_t *drv,
129 unsigned long probe_a, unsigned long probe_b,
130 void *probe_ptr);
133 static int flashdrv_open(cfe_devctx_t *ctx);
134 static int flashdrv_read(cfe_devctx_t *ctx,iocb_buffer_t *buffer);
135 static int flashdrv_inpstat(cfe_devctx_t *ctx,iocb_inpstat_t *inpstat);
136 static int flashdrv_write(cfe_devctx_t *ctx,iocb_buffer_t *buffer);
137 static int flashdrv_ioctl(cfe_devctx_t *ctx,iocb_buffer_t *buffer);
138 static int flashdrv_close(cfe_devctx_t *ctx);
140 /* *********************************************************************
141 * Device dispatch
142 ********************************************************************* */
144 const static cfe_devdisp_t flashdrv_dispatch = {
145 flashdrv_open,
146 flashdrv_read,
147 flashdrv_inpstat,
148 flashdrv_write,
149 flashdrv_ioctl,
150 flashdrv_close,
151 NULL,
152 NULL
155 const static cfe_devdisp_t flashdrv_ro_dispatch = {
156 flashdrv_open,
157 flashdrv_read,
158 NULL,
159 NULL,
160 NULL,
161 flashdrv_close,
162 NULL,
163 NULL
166 const cfe_driver_t ptflashdrv = {
167 "CFI flash",
168 "flash",
169 CFE_DEV_FLASH,
170 &flashdrv_dispatch,
171 flashdrv_probe
174 const cfe_driver_t ptflashdrv_ro = {
175 "Read only flash",
176 "flashr",
177 CFE_DEV_FLASH,
178 &flashdrv_ro_dispatch,
179 flashdrv_probe
182 /* *********************************************************************
183 * Structures
184 ********************************************************************* */
186 typedef struct flash_cfidata_s {
187 unsigned int cfidata_cmdset; /* ID of primary command set */
188 unsigned int cfidata_devif; /* device interface byte */
189 unsigned int cfidata_size; /* probed device size */
190 } flash_cfidata_t;
192 typedef struct flashops_s flashops_t;
194 typedef struct flashdrv_s {
195 flash_probe_t flashdrv_probe; /* data from probe */
196 int flashdrv_devsize; /* size reported by driver */
197 unsigned char *flashdrv_cmdaddr; /* virtual address (K1) */
198 int flashdrv_widemode; /* 1=wide flash in byte mode, 0=narrow flash */
199 int flashdrv_initialized; /* true if we've probed already */
200 flash_info_t flashdrv_info;
201 int flashdrv_nvram_ok; /* true if we can use as NVRAM */
202 int flashdrv_unlocked; /* true if we can r/w past devsize */
203 int chip_select; /* for multi-chip use */
204 nvram_info_t flashdrv_nvraminfo;
205 flashops_t *flashdrv_ops;
206 flash_cfidata_t flashdrv_cfidata;
207 } flashdrv_t;
209 struct flashops_s {
210 int (*erasesector)(flashdrv_t *f,int offset);
211 int (*writeblk)(flashdrv_t *f,int offset,void *buf,int len);
212 int (*protectsector)(flashdrv_t *f,int offset);
213 int (*unprotectsector)(flashdrv_t *f,int offset);
216 /* *********************************************************************
217 * Macros
218 ********************************************************************* */
220 #define FLASHOP_ERASE_SECTOR(softc,sect) (*((softc)->flashdrv_ops->erasesector))((softc),(sect))
221 #define FLASHOP_WRITE_BLOCK(softc,off,buf,len) (*((softc)->flashdrv_ops->writeblk))((softc),(off),(buf),(len))
222 #define FLASHOP_PROTECT_SECTOR(softc,sect) (*((softc)->flashdrv_ops->protectsector))((softc),(sect))
223 #define FLASHOP_UNPROTECT_SECTOR(softc,sect) (*((softc)->flashdrv_ops->unprotectsector))((softc),(sect))
225 /* *********************************************************************
226 * forward declarations
227 ********************************************************************* */
230 static int flash_sector_query(flashdrv_t *softc,flash_sector_t *sector);
232 static int amd_flash_write_block(flashdrv_t *softc,int offset,void *buf,int len);
233 static int amd_flash_erase_sector(flashdrv_t *softc,int offset);
235 static int hyundai_flash_write_block(flashdrv_t *softc,int offset,void *buf,int len);
236 static int hyundai_flash_erase_sector(flashdrv_t *softc,int offset);
238 static int hyundai_flash_protect_sector(flashdrv_t *softc,int offset);
239 static int hyundai_flash_unprotect_sector(flashdrv_t *softc,int offset);
241 static int intel_flash_write_block(flashdrv_t *softc,int offset,void *buf,int len);
242 static int intel_flash_erase_sector(flashdrv_t *softc,int offset);
244 static flashops_t amd_flashops = {
245 amd_flash_erase_sector,
246 amd_flash_write_block,
247 NULL,
248 NULL,
251 static flashops_t hyundai_flashops = {
252 hyundai_flash_erase_sector,
253 hyundai_flash_write_block,
254 hyundai_flash_protect_sector,
255 hyundai_flash_unprotect_sector,
258 static flashops_t intel_flashops = {
259 intel_flash_erase_sector,
260 intel_flash_write_block,
261 NULL,
262 NULL,
265 #define FLASHOPS_DEFAULT amd_flashops
269 /* *********************************************************************
270 * Externs
271 ********************************************************************* */
273 extern void *flash_write_all_ptr;
274 extern int flash_write_all_len;
276 extern void _cfe_flushcache(int);
278 /* *********************************************************************
279 * jedec_flash_maufacturer(softc)
281 * Return the manufacturer ID for this flash part.
283 * Input parameters:
284 * softc - flash context
286 * Return value:
287 * nothing
288 ********************************************************************* */
290 static unsigned int jedec_flash_manufacturer(flashdrv_t *softc)
292 unsigned int res;
294 /* Do an "unlock write" sequence */
295 FLASHCMD(softc,AMD_FLASH_MAGIC_ADDR_1,AMD_FLASH_MAGIC_1);
296 FLASHCMD(softc,AMD_FLASH_MAGIC_ADDR_2,AMD_FLASH_MAGIC_2);
297 FLASHCMD(softc,AMD_FLASH_MAGIC_ADDR_1,AMD_FLASH_AUTOSEL);
299 res = FLASHSTATUS(softc,FLASH_JEDEC_OFFSET_MFR) & 0xFF;
301 FLASHCMD(softc,AMD_FLASH_MAGIC_ADDR_1,AMD_FLASH_RESET);
303 return res;
307 /* *********************************************************************
308 * amd_flash_write_byte(softc,offset,val)
310 * Write a single byte to the flash. The sector that the flash
311 * byte is in should have been previously erased, or else this
312 * routine may hang.
314 * Input parameters:
315 * softc - flash context
316 * offset - distance in bytes into the flash
317 * val - byte to write
319 * Return value:
320 * 0 if ok
321 * else if flash could not be written
322 ********************************************************************* */
324 static inline int amd_flash_write_byte(flashdrv_t *softc,int offset, unsigned char val)
326 unsigned int value;
328 if (softc->flashdrv_probe.nchips > 1)
329 softc->chip_select = offset / softc->flashdrv_probe.chipsize;
330 else
331 softc->chip_select = 0;
333 /* Do an "unlock write" sequence */
334 FLASHCMD(softc,AMD_FLASH_MAGIC_ADDR_1,AMD_FLASH_MAGIC_1);
335 FLASHCMD(softc,AMD_FLASH_MAGIC_ADDR_2,AMD_FLASH_MAGIC_2);
337 /* Send a program command */
338 FLASHCMD(softc,AMD_FLASH_MAGIC_ADDR_1,AMD_FLASH_PROGRAM);
340 /* Restore chip select to default value */
342 softc->chip_select = 0;
344 /* Write a byte */
345 WRITEFLASH_K1(softc,offset,val);
347 for (;;) {
348 value = READFLASH_K1(softc,offset) & 0xFF;
350 if ((value & 0x80) == (val & 0x80)) {
351 return 0;
353 if ((value & 0x20) != 0x20) {
354 continue;
357 if ((READFLASH_K1(softc,offset) & 0x80) == (val & 0x80)) {
358 return 0;
360 else {
361 return -1;
365 /* *********************************************************************
366 * hyundai_flash_write_byte_flash(softc,offset,val)
368 * Write a single byte to the flash. The sector that the flash
369 * byte is in should have been previously erased, or else this
370 * routine may hang.
372 * Input parameters:
373 * softc - flash context
374 * offset - distance in bytes into the flash
375 * val - byte to write
377 * Return value:
378 * 0 if ok
379 * else if flash could not be written
380 ********************************************************************* */
382 static inline int hyundai_flash_write_byte_fast(flashdrv_t *softc,int offset, unsigned char val)
384 unsigned char toggle;
385 unsigned char status;
387 /* Send a fast program command */
389 WRITEFLASH_K1(softc,offset,AMD_FLASH_PROGRAM);
391 /* Write a byte */
393 WRITEFLASH_K1(softc,offset,val);
395 /* Wait for write completion (toggle bit stops toggling) */
397 toggle = (READFLASH_K1(softc,offset) & 0x40);
398 while (1) {
399 status = READFLASH_K1(softc,offset);
401 if ((status & 0x40) == toggle)
402 break;
404 toggle ^= 0x40;
407 /* In fast write mode we can't do a read check, so assume data OK */
409 return 0;
413 /* *********************************************************************
414 * hyundai_flash_write_block(softc,offset,val)
416 * Write a byte stream to the flash. The sector that the flash
417 * byte is in should have been previously erased, or else this
418 * routine may hang.
420 * Input parameters:
421 * softc - flash context
422 * offset - distance in bytes into the flash
423 * buf - buffer of bytes to write
424 * len - number of bytes to write
426 * Return value:
427 * number of bytes written
428 ********************************************************************* */
429 static int hyundai_flash_write_block(flashdrv_t *softc,int offset,void *buf,int len)
431 unsigned char *ptr;
432 int chipsize;
433 int chip_unlocked = 1;
436 /* Use unlock bypass so that byte write takes fewer ops */
439 chipsize = softc->flashdrv_probe.chipsize;
441 if (softc->flashdrv_probe.nchips > 1)
442 softc->chip_select = offset / chipsize;
443 else
444 softc->chip_select = 0;
446 chipsize -= offset;
448 ptr = buf;
450 while (len) {
451 if (chip_unlocked) {
452 /* First an "unlock write" sequence */
453 FLASHCMD(softc,AMD_FLASH_MAGIC_ADDR_1,AMD_FLASH_MAGIC_1);
454 FLASHCMD(softc,AMD_FLASH_MAGIC_ADDR_2,AMD_FLASH_MAGIC_2);
456 /* Send an unlock bypass command */
457 FLASHCMD(softc,AMD_FLASH_MAGIC_ADDR_1,AMD_FLASH_UNLOCK_BYPASS);
458 chip_unlocked = 0;
460 if (hyundai_flash_write_byte_fast(softc,offset,*ptr) < 0) break;
461 len--;
462 ptr++;
463 offset++;
464 chipsize--;
465 /* See if write crosses into next flash chip */
466 if (len && (chipsize == 0))
468 if (softc->chip_select == (softc->flashdrv_probe.nchips - 1))
469 break;
470 /* Bypass reset (restore current flash to read mode) */
471 WRITEFLASH_K1(softc,0,0x90);
472 WRITEFLASH_K1(softc,0,0x00);
473 softc->chip_select++;
474 chip_unlocked = 1;
475 chipsize = softc->flashdrv_probe.chipsize;
479 if (!chip_unlocked) {
480 WRITEFLASH_K1(softc,0,0x90);
481 WRITEFLASH_K1(softc,0,0x00);
484 return (ptr - (unsigned char *)buf);
486 /* *********************************************************************
487 * amd_flash_write_block(softc,offset,val)
489 * Write a single byte to the flash. The sector that the flash
490 * byte is in should have been previously erased, or else this
491 * routine may hang.
493 * Input parameters:
494 * softc - flash context
495 * offset - distance in bytes into the flash
496 * buf - buffer of bytes to write
497 * len - number of bytes to write
499 * Return value:
500 * number of bytes written
501 ********************************************************************* */
502 static int amd_flash_write_block(flashdrv_t *softc,int offset,void *buf,int len)
504 unsigned char *ptr;
506 ptr = buf;
508 while (len) {
509 if (amd_flash_write_byte(softc,offset,*ptr) < 0) break;
510 len--;
511 ptr++;
512 offset++;
515 return (ptr - (unsigned char *)buf);
519 /* *********************************************************************
520 * amd_flash_erase_sector(softc,offset)
522 * Erase a single sector in the flash device
524 * Input parameters:
525 * softc - device context
526 * offset - offset in flash of sector to erase
528 * Return value:
529 * 0 if ok, else error code
530 ********************************************************************* */
532 static int amd_flash_erase_sector(flashdrv_t *softc,int offset)
535 if (softc->flashdrv_probe.nchips > 1)
536 softc->chip_select = offset / softc->flashdrv_probe.chipsize;
537 else
538 softc->chip_select = 0;
540 /* Do an "unlock write" sequence */
541 FLASHCMD(softc,AMD_FLASH_MAGIC_ADDR_1,AMD_FLASH_MAGIC_1); /* cycles 1-2 */
542 FLASHCMD(softc,AMD_FLASH_MAGIC_ADDR_2,AMD_FLASH_MAGIC_2);
544 /* send the erase command */
545 FLASHCMD(softc,AMD_FLASH_MAGIC_ADDR_1,AMD_FLASH_ERASE_3); /* cycle 3 */
547 /* Do an "unlock write" sequence */
548 FLASHCMD(softc,AMD_FLASH_MAGIC_ADDR_1,AMD_FLASH_MAGIC_1); /* cycles 4-5 */
549 FLASHCMD(softc,AMD_FLASH_MAGIC_ADDR_2,AMD_FLASH_MAGIC_2);
551 /* Restore chip select to default value */
553 softc->chip_select = 0;
555 * Send the "erase sector" qualifier - don't use FLASHCMD
556 * because it changes the offset.
558 WRITEFLASH_K1(softc,offset,AMD_FLASH_ERASE_SEC_6);
560 while ((READFLASH_K1(softc,offset) & 0x80) != 0x80) {
561 /* NULL LOOP */
564 return 0;
567 /* *********************************************************************
568 * hyundai_flash_erase_sector(softc,offset)
570 * Erase a single sector in the flash device
572 * Input parameters:
573 * softc - device context
574 * offset - offset in flash of sector to erase
576 * Return value:
577 * 0 if ok, else error code
578 ********************************************************************* */
580 static int hyundai_flash_erase_sector(flashdrv_t *softc,int offset)
582 uint8_t toggle;
583 uint8_t status;
584 unsigned int count = 0;
586 if (softc->flashdrv_probe.nchips > 1)
587 softc->chip_select = offset / softc->flashdrv_probe.chipsize;
588 else
589 softc->chip_select = 0;
591 /* Do an "unlock write" sequence */
592 FLASHCMD(softc,AMD_FLASH_MAGIC_ADDR_1,AMD_FLASH_MAGIC_1); /* cycles 1-2 */
593 FLASHCMD(softc,AMD_FLASH_MAGIC_ADDR_2,AMD_FLASH_MAGIC_2);
595 /* send the erase command */
596 FLASHCMD(softc,AMD_FLASH_MAGIC_ADDR_1,AMD_FLASH_ERASE_3); /* cycle 3 */
598 /* Do an "unlock write" sequence */
599 FLASHCMD(softc,AMD_FLASH_MAGIC_ADDR_1,AMD_FLASH_MAGIC_1); /* cycles 4-5 */
600 FLASHCMD(softc,AMD_FLASH_MAGIC_ADDR_2,AMD_FLASH_MAGIC_2);
602 /* Restore chip select to default value */
604 softc->chip_select = 0;
606 * Send the "erase sector" qualifier - don't use FLASHCMD
607 * because it changes the offset.
609 WRITEFLASH_K1(softc,offset,AMD_FLASH_ERASE_SEC_6);
611 toggle = (READFLASH_K1(softc,offset) & 0x40);
612 while (1) {
613 status = READFLASH_K1(softc,offset);
614 if ((status & 0x40) == toggle)
615 break;
616 toggle ^= 0x40;
617 if ((status & 0x20) == 0x20) {
618 if ((READFLASH_K1(softc,offset) & 0x40) == toggle) {
619 break; /* no toggle, erase complete */
621 else {
622 xprintf ("sector erase timed out\n");
623 break;
626 count++;
629 return 0;
632 /* *********************************************************************
633 * hyundai_flash_protect_sector(softc,offset)
635 * Protect a sectors in the flash device
637 * Input parameters:
638 * softc - device context
639 * offset - offset of sector to protect
641 * Return value:
642 * 0 if ok, else error code
643 ********************************************************************* */
645 static int hyundai_flash_protect_sector(flashdrv_t *softc, int offset)
647 int chipsize = softc->flashdrv_probe.chipsize;
648 int trycnt = 25;
649 offset &= ~(0xff); /* Clear least significant byte */
651 xprintf("protect sector at offset 0x%x\n");
653 /* Address bit 1 must be set. */
654 /* Note: in byte mode, address bit 1 is left shifted by 1 */
656 if (softc->flashdrv_widemode)
657 offset |= 0x4;
658 else
659 offset |= 0x2;
661 /* Get device ready */
663 WRITEFLASH_K1(softc, chipsize*(offset/chipsize), 0x60);
665 xprintf ("protect!, offset = 0x%x\n",offset);
666 WRITEFLASH_K1(softc,offset,0x60); /* Protect CMD 1 */
667 cfe_usleep (USEC_TO_TICK(150)); /* Wait 150 usec */
668 WRITEFLASH_K1(softc,offset,0x40); /* Protect CMD 2 */
670 while (READFLASH_K1(softc,offset) != 0x01 && trycnt) {
671 WRITEFLASH_K1(softc,offset,0x60); /* Protect CMD 1 */
672 cfe_usleep (USEC_TO_TICK(150)); /* Wait 150 usec */
673 WRITEFLASH_K1(softc,offset,0x40); /* Protect CMD 2 */
674 trycnt--;
677 if (trycnt == 0 && READFLASH_K1(softc,offset) != 0x01)
679 xprintf ("protect! failed\n");
680 return (1);
682 else
684 xprintf ("protect! succeeded trycnt = 0x%x\n",trycnt);
685 return (0);
689 /* *********************************************************************
690 * flash_protect_range(softc,range)
692 * Protect a range of sectors in the flash device
694 * Input parameters:
695 * softc - device context
696 * ranget - range of bytes to protect
698 * Return value:
699 * 0 if ok, else error code
700 ********************************************************************* */
702 static int flash_protect_range(flashdrv_t *softc, flash_range_t *range)
704 int status;
705 flash_sector_t sector;
706 int soffset;
707 int res;
708 int i;
710 if (((softc)->flashdrv_ops->protectsector) == NULL)
712 return CFE_ERR_UNSUPPORTED;
715 if ((softc)->flashdrv_ops == &hyundai_flashops) {
717 xprintf ("\n *** Apply high voltage to flash, then hit any key (or q to quit):");
718 if (console_readkey() == 'q') {
719 xprintf ("\n");
720 return 0;
723 xprintf ("\n");
727 sector.flash_sector_idx = 0;
730 for (;;) {
731 res = flash_sector_query(softc,&sector);
732 if (res != 0) break;
733 if (sector.flash_sector_status == FLASH_SECTOR_INVALID) {
734 break;
737 soffset = sector.flash_sector_offset;
738 if ((soffset >= range->range_base) &&
739 (soffset < (range->range_base+range->range_length-1))) {
740 res = FLASHOP_PROTECT_SECTOR(softc,soffset);
741 if (res != 0) break;
743 else if ((soffset < range->range_base) &&
744 (soffset + sector.flash_sector_size > range->range_base)) {
745 res = FLASHOP_PROTECT_SECTOR(softc,soffset);
746 if (res != 0) break;
748 else if (soffset >= range->range_base + range->range_length) {
749 res = 0;
750 break;
752 sector.flash_sector_idx++;
754 status = res;
756 /* Now that we've done all the protecting, send a reset to every flash */
758 if ((softc)->flashdrv_ops == &hyundai_flashops) {
760 xprintf ("\n *** Restore normal voltage to flash, then hit any key:");
761 console_readkey();
762 xprintf ("\n");
765 * Even if every flash chip didn't get put in protect mode, it doesn't
766 * hurt to reset...
768 for (i = 0; i < softc->flashdrv_probe.nchips; i++)
769 WRITEFLASH_K1(softc,i*softc->flashdrv_probe.chipsize, AMD_FLASH_RESET);
772 return status;
775 /* *********************************************************************
776 * hyundai_flash_unprotect_sector(softc,offset)
778 * Unprotect a sectors in the flash device
780 * Input parameters:
781 * softc - device context
782 * range - offset of sector to unprotect
784 * Return value:
785 * 0 if ok, else error code
786 ********************************************************************* */
788 static int hyundai_flash_unprotect_sector(flashdrv_t *softc, int offset)
790 int trycnt = 1000;
791 int chipsize = softc->flashdrv_probe.chipsize;
793 offset &= ~(0xff); /* Clear least significant byte */
795 /* Address bits 6 and 1 must be set. */
796 /* Note: in byte mode, address bits left shifted by 1 */
798 if (softc->flashdrv_widemode)
799 offset |= 0x84;
800 else
801 offset |= 0x42;
803 /* Get device ready */
805 if (softc->flashdrv_probe.nchips > 1)
806 WRITEFLASH_K1(softc, chipsize*(offset/chipsize), 0x60);
807 else
808 WRITEFLASH_K1(softc,0x0,0x60); /* Get device ready */
810 xprintf ("unprotect!, offset = 0x%x\n",offset);
811 WRITEFLASH_K1(softc,offset,0x60); /* Unprotect CMD 1 */
812 cfe_usleep (USEC_TO_TICK(15000)); /* Wait 15 msec */
813 WRITEFLASH_K1(softc,offset,0x40); /* Unprotect CMD 2 */
815 while (READFLASH_K1(softc,offset) != 0x00 && trycnt) {
816 trycnt--;
817 WRITEFLASH_K1(softc,offset,0x60); /* Unprotect CMD 1 */
818 cfe_usleep (USEC_TO_TICK(15000)); /* Wait 15 msec */
819 WRITEFLASH_K1(softc,offset,0x40); /* Unprotect CMD 2 */
822 if (trycnt == 0 && READFLASH_K1(softc,offset) != 0x00)
824 xprintf ("protect! failed\n");
825 return 1;
827 else
829 xprintf ("protect! succeeded trycnt = 0x%x\n",trycnt);
830 return 0;
833 /* *********************************************************************
834 * flash_unprotect_range(softc,range)
836 * Unprotect a range of sectors in the flash device
838 * Input parameters:
839 * softc - device context
840 * range - range of bytes to unprotect
842 * Return value:
843 * 0 if ok, else error code
844 ********************************************************************* */
846 static int flash_unprotect_range(flashdrv_t *softc, flash_range_t *range)
848 int status;
849 flash_sector_t sector;
850 int soffset;
851 int res;
852 int i;
854 if (((softc)->flashdrv_ops->unprotectsector) == NULL)
856 return CFE_ERR_UNSUPPORTED;
859 if ((softc)->flashdrv_ops == &hyundai_flashops) {
861 xprintf ("\n *** Apply high voltage to flash, then hit any key (or q to quit):");
862 if (console_readkey() == 'q') {
863 xprintf ("\n");
864 return 0;
867 xprintf ("\n");
870 sector.flash_sector_idx = 0;
874 for (;;) {
875 res = flash_sector_query(softc,&sector);
876 if (res != 0) break;
877 if (sector.flash_sector_status == FLASH_SECTOR_INVALID) {
878 break;
881 soffset = sector.flash_sector_offset;
882 if ((soffset >= range->range_base) &&
883 (soffset < (range->range_base+range->range_length-1))) {
884 res = FLASHOP_UNPROTECT_SECTOR(softc,soffset);
885 if (res != 0) break;
887 else if ((soffset < range->range_base) &&
888 (soffset + sector.flash_sector_size > range->range_base)) {
889 res = FLASHOP_UNPROTECT_SECTOR(softc,soffset);
890 if (res != 0) break;
892 else if (soffset >= range->range_base + range->range_length) {
893 res = 0;
894 break;
896 sector.flash_sector_idx++;
898 status = res;
900 /* Now that we've done the unprotecting, send a reset to every flash */
902 if ((softc)->flashdrv_ops == &hyundai_flashops) {
904 xprintf ("\n *** Restore normal voltage to flash, then hit any key:");
905 console_readkey();
906 xprintf ("\n");
907 for (i = 0; i < softc->flashdrv_probe.nchips; i++)
909 WRITEFLASH_K1(softc,i*softc->flashdrv_probe.chipsize, AMD_FLASH_RESET);
913 return status;
916 /* *********************************************************************
917 * intel_flash_write_byte(softc,offset,val)
919 * Write a single byte to the flash. The sector that the flash
920 * byte is in should have been previously erased, or else this
921 * routine may hang.
923 * Input parameters:
924 * softc - flash context
925 * offset - distance in bytes into the flash
926 * val - byte to write
928 * Return value:
929 * 0 if ok
930 * else if flash could not be written
931 ********************************************************************* */
932 static inline int intel_flash_write_byte(flashdrv_t *softc,
933 int offset, unsigned char val)
935 unsigned int value;
937 /* Send a program command */
938 WRITEFLASH_K1(softc,offset,INTEL_FLASH_PROGRAM);
940 /* Write a byte */
941 WRITEFLASH_K1(softc,offset,val);
944 while ((READFLASH_K1(softc,offset) & 0x80) != 0x80) {
945 /* NULL LOOP */
948 value = READFLASH_K1(softc,offset) & 0xFF;
950 if (value & (0x01|0x08|0x10)) return -1;
951 return 0;
954 /* *********************************************************************
955 * intel_flash_write_word(softc,offset,val)
957 * Write a single word to the flash. The sector that the flash
958 * byte is in should have been previously erased, or else this
959 * routine may hang.
961 * Input parameters:
962 * softc - flash context
963 * offset - distance in bytes into the flash
964 * val - word to write
966 * Return value:
967 * 0 if ok
968 * else if flash could not be written
969 ********************************************************************* */
970 static inline int intel_flash_write_word(flashdrv_t *softc,
971 int offset, unsigned short val)
973 unsigned int value;
976 /* Send a program command */
977 WRITEFLASH_K1W(softc,offset,INTEL_FLASH_PROGRAM);
979 /* Write a byte */
980 WRITEFLASH_K1W(softc,offset,val);
983 while ((READFLASH_K1W(softc,offset) & 0x80) != 0x80) {
984 /* NULL LOOP */
987 value = READFLASH_K1W(softc,offset) & 0xFF;
989 if (value & (0x01|0x08|0x10)) return -1;
990 return 0;
993 /* *********************************************************************
994 * intel_flash_write_block(softc,offset,val)
996 * Write a single byte to the flash. The sector that the flash
997 * byte is in should have been previously erased, or else this
998 * routine may hang.
1000 * Input parameters:
1001 * softc - flash context
1002 * offset - distance in bytes into the flash
1003 * buf - buffer of bytes to write
1004 * len - number of bytes to write
1006 * Return value:
1007 * number of bytes written
1008 ********************************************************************* */
1009 static int intel_flash_write_block(flashdrv_t *softc,int offset,void *buf,int len)
1011 unsigned char *ptr;
1012 unsigned short *ptrw;
1014 if (softc->flashdrv_probe.flash_flags & FLASH_FLG_16BIT) {
1015 ptrw = buf;
1016 offset &= ~1; /* offset must be even */
1017 while (len > 0) {
1018 if (intel_flash_write_word(softc,offset,*ptrw) < 0) break;
1019 len-=2;
1020 ptrw++;
1021 offset+=2;
1023 WRITEFLASH_K1(softc,offset,INTEL_FLASH_READ_MODE);
1024 return ((unsigned char *) ptrw - (unsigned char *)buf);
1026 else {
1027 ptr = buf;
1028 while (len) {
1029 if (intel_flash_write_byte(softc,offset,*ptr) < 0) break;
1030 len--;
1031 ptr++;
1032 offset++;
1034 WRITEFLASH_K1(softc,offset,INTEL_FLASH_READ_MODE);
1035 return (ptr - (unsigned char *)buf);
1041 /* *********************************************************************
1042 * intel_flash_erase_sector(softc,offset)
1044 * Erase a single sector on the flash device
1046 * Input parameters:
1047 * softc - device context
1048 * offset - offset in flash of sector to erase
1050 * Return value:
1051 * 0 if ok, else error code
1052 ********************************************************************* */
1053 static int intel_flash_erase_sector(flashdrv_t *softc,int offset)
1055 WRITEFLASH_K1(softc,offset,INTEL_FLASH_ERASE_BLOCK);
1056 WRITEFLASH_K1(softc,offset,INTEL_FLASH_ERASE_CONFIRM);
1058 while ((READFLASH_K1(softc,offset) & 0x80) != 0x80) {
1059 /* NULL LOOP */
1061 WRITEFLASH_K1(softc,offset,INTEL_FLASH_READ_MODE);
1063 return 0;
1068 /* *********************************************************************
1069 * FLASH_ERASE_RANGE(softc,range)
1071 * Erase a range of sectors
1073 * Input parameters:
1074 * softc - our flash
1075 * range - range structure
1077 * Return value:
1078 * 0 if ok
1079 * else error
1080 ********************************************************************* */
1082 static int flash_erase_range(flashdrv_t *softc,flash_range_t *range)
1084 flash_sector_t sector;
1085 int soffset;
1086 int res;
1088 if (softc->flashdrv_info.flash_type != FLASH_TYPE_FLASH) {
1089 return CFE_ERR_UNSUPPORTED;
1093 if (range->range_base+range->range_length > softc->flashdrv_devsize) {
1094 return CFE_ERR_INV_PARAM;
1097 res = 0;
1099 sector.flash_sector_idx = 0;
1100 softc->chip_select = range->range_base / softc->flashdrv_probe.chipsize;
1102 for (;;) {
1103 res = flash_sector_query(softc,&sector);
1104 if (res != 0) break;
1105 if (sector.flash_sector_status == FLASH_SECTOR_INVALID) {
1106 break;
1109 soffset = sector.flash_sector_offset;
1110 if ((soffset >= range->range_base) &&
1111 (soffset < (range->range_base+range->range_length-1))) {
1112 if (softc->flashdrv_nvram_ok &&
1113 (soffset >= softc->flashdrv_nvraminfo.nvram_offset)) {
1114 break;
1116 res = FLASHOP_ERASE_SECTOR(softc,soffset);
1117 if (res != 0) break;
1119 else if ((soffset < range->range_base) &&
1120 (soffset + sector.flash_sector_size > range->range_base)) {
1121 if (softc->flashdrv_nvram_ok &&
1122 (soffset >= softc->flashdrv_nvraminfo.nvram_offset)) {
1123 break;
1125 res = FLASHOP_ERASE_SECTOR(softc,soffset);
1126 if (res != 0) break;
1128 else if (soffset >= range->range_base + range->range_length) {
1129 res = 0;
1130 break;
1132 sector.flash_sector_idx++;
1135 return res;
1139 /* *********************************************************************
1140 * FLASH_ERASE_ALL(softc)
1142 * Erase the entire flash device, except the NVRAM area,
1143 * sector-by-sector.
1145 * Input parameters:
1146 * softc - our flash
1148 * Return value:
1149 * 0 if ok
1150 * else error code
1151 ********************************************************************* */
1153 static int flash_erase_all(flashdrv_t *softc)
1155 flash_range_t range;
1156 int i;
1159 if (softc->flashdrv_probe.nchips == 1)
1161 range.range_base = 0;
1162 range.range_length = softc->flashdrv_devsize;
1164 return flash_erase_range(softc,&range);
1166 else
1168 for (i = 0; i < softc->flashdrv_probe.nchips; i++)
1170 range.range_base = i*softc->flashdrv_probe.chipsize;
1171 range.range_length = softc->flashdrv_probe.chipsize;
1172 flash_erase_range(softc,&range);
1174 return 0;
1178 /* *********************************************************************
1179 * FLASH_CFI_GETSECTORS(softc)
1181 * Query the CFI information and store the sector info in our
1182 * private probe structure.
1184 * Input parameters:
1185 * softc - our flash info
1187 * Return value:
1188 * 0 if ok
1189 * else error code
1190 ********************************************************************* */
1192 static int flash_cfi_getsectors(flashdrv_t *softc)
1194 int idx;
1195 int regcnt;
1196 int nblks;
1197 int blksiz;
1199 regcnt = GETCFIBYTE(softc,FLASH_CFI_REGION_COUNT);
1201 softc->flashdrv_probe.flash_nsectors = regcnt;
1203 for (idx = 0; idx < regcnt; idx++) {
1204 nblks = ((int)GETCFIBYTE(softc,FLASH_CFI_REGION_TABLE+0+idx*4) +
1205 (int)(GETCFIBYTE(softc,FLASH_CFI_REGION_TABLE+1+idx*4)<<8)) + 1;
1206 blksiz = ((int)GETCFIBYTE(softc,FLASH_CFI_REGION_TABLE+2+idx*4) +
1207 (int)(GETCFIBYTE(softc,FLASH_CFI_REGION_TABLE+3+idx*4)<<8)) * 256;
1208 softc->flashdrv_probe.flash_sectors[idx] =
1209 FLASH_SECTOR_RANGE(nblks,blksiz);
1213 return 0;
1216 /* *********************************************************************
1217 * FLASH_SECTOR_QUERY(softc,sector)
1219 * Query the sector information about a particular sector. You can
1220 * call this iteratively to find out about all of the sectors.
1222 * Input parameters:
1223 * softc - our flash info
1224 * sector - structure to receive sector information
1226 * Return value:
1227 * 0 if ok
1228 * else error code
1229 ********************************************************************* */
1231 static int flash_sector_query(flashdrv_t *softc,flash_sector_t *sector)
1233 int idx = 0;
1234 int nblks;
1235 int blksiz;
1236 unsigned int offset;
1237 int curblk;
1238 int nchip;
1240 if (softc->flashdrv_info.flash_type != FLASH_TYPE_FLASH) {
1241 return CFE_ERR_UNSUPPORTED;
1244 if (softc->flashdrv_probe.flash_nsectors == 0) {
1245 return CFE_ERR_UNSUPPORTED;
1248 offset = 0;
1249 curblk = 0;
1250 for (nchip = 0; nchip < softc->flashdrv_probe.nchips; nchip++) {
1251 for (idx = 0; idx < softc->flashdrv_probe.flash_nsectors; idx++) {
1252 nblks = FLASH_SECTOR_NBLKS(softc->flashdrv_probe.flash_sectors[idx]);
1253 blksiz = FLASH_SECTOR_SIZE(softc->flashdrv_probe.flash_sectors[idx]);
1254 if (sector->flash_sector_idx < curblk+nblks) {
1255 sector->flash_sector_status = FLASH_SECTOR_OK;
1256 sector->flash_sector_offset =
1257 offset + (sector->flash_sector_idx-curblk)*blksiz;
1258 sector->flash_sector_size = blksiz;
1259 goto done;
1262 offset += (nblks)*blksiz;
1263 curblk += nblks;
1267 done:
1269 if (idx == softc->flashdrv_probe.flash_nsectors) {
1270 sector->flash_sector_status = FLASH_SECTOR_INVALID;
1273 return 0;
1276 /* *********************************************************************
1277 * FLASH_SET_CMDSET(softc,cmdset)
1279 * Set the command-set that we'll honor for this flash.
1281 * Input parameters:
1282 * softc - our flash
1283 * cmdset - FLASH_CFI_CMDSET_xxx
1285 * Return value:
1286 * nothing
1287 ********************************************************************* */
1289 static void flash_set_cmdset(flashdrv_t *softc,int cmdset)
1291 switch (cmdset) {
1292 case FLASH_CFI_CMDSET_INTEL_ECS:
1293 case FLASH_CFI_CMDSET_INTEL_STD:
1294 softc->flashdrv_ops = &intel_flashops;
1295 softc->flashdrv_widemode = 0;
1296 break;
1297 case FLASH_CFI_CMDSET_AMD_STD:
1298 if (jedec_flash_manufacturer(softc) == FLASH_MFR_HYUNDAI)
1300 softc->flashdrv_ops = &hyundai_flashops;
1301 break;
1303 case FLASH_CFI_CMDSET_AMD_ECS:
1304 softc->flashdrv_ops = &amd_flashops;
1305 break;
1306 default:
1307 /* we don't understand the command set - treat it like ROM */
1308 softc->flashdrv_info.flash_type = FLASH_TYPE_ROM;
1313 /* *********************************************************************
1314 * FLASH_CFI_PROBE(softc)
1316 * Try to do a CFI query on this device. If we find the
1317 * magic signature, extract some useful information from the
1318 * query structure.
1320 * Input parameters:
1321 * softc - out flash
1323 * Return value:
1324 * 0 if successful, <0 if error
1325 ********************************************************************* */
1326 static int flash_cfi_probe(flashdrv_t *softc)
1328 softc->chip_select = 0;
1329 FLASHCMD(softc,FLASH_CFI_QUERY_ADDR,FLASH_CFI_QUERY_MODE);
1331 if (!((GETCFIBYTE(softc,FLASH_CFI_SIGNATURE+0) == 'Q') &&
1332 (GETCFIBYTE(softc,FLASH_CFI_SIGNATURE+1) == 'R') &&
1333 (GETCFIBYTE(softc,FLASH_CFI_SIGNATURE+2) == 'Y'))) {
1335 FLASHCMD(softc,FLASH_CFI_QUERY_ADDR,FLASH_CFI_QUERY_EXIT);
1336 return CFE_ERR_UNSUPPORTED;
1340 * Gather info from flash
1343 softc->flashdrv_cfidata.cfidata_cmdset =
1344 ((unsigned int) (GETCFIBYTE(softc,FLASH_CFI_COMMAND_SET))) +
1345 (((unsigned int) (GETCFIBYTE(softc,FLASH_CFI_COMMAND_SET+1))) << 8);
1347 softc->flashdrv_cfidata.cfidata_devif =
1348 ((unsigned int) (GETCFIBYTE(softc,FLASH_CFI_DEVICE_INTERFACE))) +
1349 (((unsigned int) (GETCFIBYTE(softc,FLASH_CFI_DEVICE_INTERFACE+1))) << 8);
1351 softc->flashdrv_cfidata.cfidata_size =
1352 1 << ((unsigned int) (GETCFIBYTE(softc,FLASH_CFI_DEVICE_SIZE)));
1354 flash_cfi_getsectors(softc);
1357 * Don't need to be in query mode anymore.
1360 FLASHCMD(softc,FLASH_CFI_QUERY_ADDR,FLASH_CFI_QUERY_EXIT);
1362 softc->flashdrv_info.flash_type = FLASH_TYPE_FLASH;
1364 flash_set_cmdset(softc,softc->flashdrv_cfidata.cfidata_cmdset);
1366 return 0;
1370 /* *********************************************************************
1371 * FLASH_GETWIDTH(softc,info)
1373 * Try to determine the width of the flash. This is needed for
1374 * management purposes, since some 16-bit flash parts in 8-bit mode
1375 * have an "A-1" (address line -1) wire to select bytes within
1376 * a 16-bit word. When this is present, the flash commands
1377 * will have different offsets.
1379 * Input parameters:
1380 * softc - our flash
1381 * info - flash info structure
1383 * Return value:
1384 * nothing
1385 ********************************************************************* */
1387 static void flash_getwidth(flashdrv_t *softc,flash_info_t *info)
1389 softc->flashdrv_widemode = 0; /* first try narrow */
1391 if (flash_cfi_probe(softc) == 0) {
1392 return;
1395 softc->flashdrv_widemode = 1; /* then wide */
1397 if (flash_cfi_probe(softc) == 0) {
1398 return;
1401 /* Just return, assume not wide if no CFI interface */
1402 softc->flashdrv_widemode = 0;
1404 softc->flashdrv_info.flash_type = FLASH_TYPE_ROM; /* no CFI: treat as ROM */
1407 /* *********************************************************************
1408 * flash_getinfo(softc)
1410 * Try to determine if the specified region is flash, ROM, SRAM,
1411 * or something else.
1413 * Input parameters:
1414 * softc - our context
1416 * Return value:
1417 * nothing
1418 ********************************************************************* */
1420 static void flash_getinfo(flashdrv_t *softc)
1422 uint8_t save0,save1;
1423 volatile uint8_t *ptr;
1424 flash_info_t *info = &(softc->flashdrv_info);
1427 * Set up some defaults based on the probe data
1430 softc->flashdrv_widemode = 0;
1431 info->flash_base = softc->flashdrv_probe.flash_phys;
1432 info->flash_size = softc->flashdrv_probe.flash_size;
1433 softc->flashdrv_devsize = softc->flashdrv_probe.flash_size;
1434 info->flash_type = FLASH_TYPE_UNKNOWN;
1435 info->flash_flags = 0;
1438 * If we've been told not to try probing, just assume
1439 * we're a flash part.
1442 if (softc->flashdrv_probe.flash_flags & FLASH_FLG_MANUAL) {
1443 info->flash_type = FLASH_TYPE_FLASH;
1444 if (softc->flashdrv_probe.flash_flags & FLASH_FLG_WIDE) {
1445 softc->flashdrv_widemode = TRUE;
1447 if (softc->flashdrv_probe.flash_cmdset) {
1448 flash_set_cmdset(softc,softc->flashdrv_probe.flash_cmdset);
1450 return;
1454 * Attempt to read/write byte zero. If it is changable,
1455 * this is SRAM (or maybe a ROM emulator with the write line hooked up)
1458 ptr = (volatile uint8_t *) UNCADDR(softc->flashdrv_probe.flash_phys);
1459 save0 = *ptr; /* save old value */
1460 save1 = *(ptr+1); /* save old value */
1461 *(ptr) = 0x55;
1462 if ((*ptr) == 0x55) {
1463 *(ptr) = 0xAA;
1464 if ((*ptr) == 0xAA) {
1465 info->flash_type = FLASH_TYPE_SRAM;
1469 if (*ptr == save0) info->flash_type = FLASH_TYPE_ROM;
1470 else (*ptr) = save0; /* restore old value */
1473 * If we thought it was ROM, try doing a CFI query
1474 * to see if it was flash. This check is kind of kludgey
1475 * but should work.
1478 if (info->flash_type == FLASH_TYPE_ROM) {
1479 flash_getwidth(softc,info);
1480 if (info->flash_type == FLASH_TYPE_FLASH) {
1485 /* *********************************************************************
1486 * flashdrv_setup_nvram(softc)
1488 * If we're going to be using a sector of the flash for NVRAM,
1489 * go find that sector and set it up.
1491 * Input parameters:
1492 * softc - our flash
1494 * Return value:
1495 * nothing. flashdrv_nvram_ok might change though.
1496 ********************************************************************* */
1498 static void flashdrv_setup_nvram(flashdrv_t *softc)
1500 flash_sector_t sector;
1501 int res;
1503 softc->flashdrv_nvram_ok = FALSE;
1505 if (softc->flashdrv_info.flash_type != FLASH_TYPE_FLASH) {
1506 return;
1509 sector.flash_sector_idx = 0;
1510 for (;;) {
1511 res = flash_sector_query(softc,&sector);
1512 if (res == CFE_ERR_UNSUPPORTED) break;
1513 if (res == 0) {
1514 if (sector.flash_sector_status != FLASH_SECTOR_INVALID) {
1515 sector.flash_sector_idx++;
1516 continue;
1519 break;
1522 /* The sector offset will still contain the value at the end
1523 of the last successful call. That's the last sector, so
1524 we can now use this to fill in the NVRAM info structure */
1526 if (res != CFE_ERR_UNSUPPORTED) {
1527 softc->flashdrv_nvraminfo.nvram_offset = sector.flash_sector_offset;
1528 softc->flashdrv_nvraminfo.nvram_size = sector.flash_sector_size;
1529 softc->flashdrv_nvraminfo.nvram_eraseflg = TRUE; /* needs erase */
1530 softc->flashdrv_nvram_ok = TRUE;
1532 * Set the flash's size as reported in the flash_info structure
1533 * to be the size without the NVRAM sector at the end.
1535 softc->flashdrv_info.flash_size = sector.flash_sector_offset;
1536 softc->flashdrv_devsize = sector.flash_sector_offset;
1542 /* *********************************************************************
1543 * flashdrv_probe(drv,probe_a,probe_b,probe_ptr)
1545 * Device probe routine. Attach the flash device to
1546 * CFE's device table.
1548 * Input parameters:
1549 * drv - driver descriptor
1550 * probe_a - physical address of flash
1551 * probe_b - size of flash (bytes)
1552 * probe_ptr - unused
1554 * Return value:
1555 * nothing
1556 ********************************************************************* */
1558 static void flashdrv_probe(cfe_driver_t *drv,
1559 unsigned long probe_a, unsigned long probe_b,
1560 void *probe_ptr)
1562 flashdrv_t *softc;
1563 flash_probe_t *probe;
1564 char descr[80];
1566 probe = (flash_probe_t *) probe_ptr;
1569 * probe_a is the flash base address
1570 * probe_b is the size of the flash
1571 * probe_ptr is unused.
1574 softc = (flashdrv_t *) KMALLOC(sizeof(flashdrv_t),0);
1575 if (softc) {
1576 memset(softc,0,sizeof(flashdrv_t));
1578 if (probe) {
1579 /* Passed probe structure, do fancy stuff */
1580 memcpy(&(softc->flashdrv_probe),probe,sizeof(flash_probe_t));
1581 if (softc->flashdrv_probe.flash_prog_phys == 0) {
1582 softc->flashdrv_probe.flash_prog_phys =
1583 softc->flashdrv_probe.flash_phys;
1586 else {
1587 /* Didn't pass probe structure, do the compatible thing */
1588 softc->flashdrv_probe.flash_phys = probe_a;
1589 softc->flashdrv_probe.flash_prog_phys = probe_a;
1590 softc->flashdrv_probe.flash_size = probe_b;
1591 softc->flashdrv_probe.flash_flags = FLASH_FLG_NVRAM;
1592 softc->flashdrv_probe.nchips = 1;
1595 #if __long64
1596 softc->flashdrv_cmdaddr = (char *) (softc->flashdrv_probe.flash_prog_phys);
1597 #else
1598 softc->flashdrv_cmdaddr = (char *) UNCADDR(softc->flashdrv_probe.flash_prog_phys);
1599 #endif
1600 softc->flashdrv_initialized = 0;
1601 softc->flashdrv_ops = &FLASHOPS_DEFAULT;
1602 xsprintf(descr,"%s at %08X size %uKB",drv->drv_description,
1603 softc->flashdrv_probe.flash_phys,
1604 softc->flashdrv_probe.flash_size/1024);
1605 cfe_attach(drv,softc,NULL,descr);
1611 /* *********************************************************************
1612 * flashdrv_open(ctx)
1614 * Called when the flash device is opened.
1616 * Input parameters:
1617 * ctx - device context
1619 * Return value:
1620 * 0 if ok else error code
1621 ********************************************************************* */
1623 static int flashdrv_open(cfe_devctx_t *ctx)
1625 flashdrv_t *softc = ctx->dev_softc;
1628 * do initialization
1631 if (!softc->flashdrv_initialized) {
1634 * Assume it's not an NVRAM-capable flash
1637 softc->flashdrv_nvram_ok = FALSE;
1640 * Probe flash for geometry
1642 flash_getinfo(softc);
1645 * Find the last sector if in NVRAM mode
1648 if (softc->flashdrv_probe.flash_flags & FLASH_FLG_NVRAM) {
1649 flashdrv_setup_nvram(softc);
1652 softc->flashdrv_initialized = TRUE;
1655 return 0;
1658 /* *********************************************************************
1659 * flashdrv_read(ctx,buffer)
1661 * Read data from the flash device. The flash device is
1662 * considered to be like a disk (you need to specify the offset).
1664 * Input parameters:
1665 * ctx - device context
1666 * buffer - buffer descriptor
1668 * Return value:
1669 * 0 if ok, else error code
1670 ********************************************************************* */
1672 static int flashdrv_read(cfe_devctx_t *ctx,iocb_buffer_t *buffer)
1674 flashdrv_t *softc = ctx->dev_softc;
1675 unsigned char *bptr;
1676 unsigned char *flashbase;
1677 int offset;
1678 int blen;
1681 * For now, read the flash from K1 (always). Eventually
1682 * we need to flush the cache after a write.
1685 flashbase = (unsigned char *) UNCADDR(softc->flashdrv_probe.flash_phys);
1687 bptr = buffer->buf_ptr;
1688 blen = buffer->buf_length;
1689 offset = (int) buffer->buf_offset;
1691 if (!(softc->flashdrv_unlocked)) {
1692 if ((offset + blen) > softc->flashdrv_devsize) {
1693 blen = softc->flashdrv_devsize - offset;
1697 #ifdef _FLASH_BROKEN_BYTEREAD_
1699 * BCM1250 users: don't worry about this. This hack is for
1700 * something else and should not be used with the BCM1250.
1702 if (softc->flashdrv_probe.flash_flags & FLASH_FLG_16BIT) {
1703 uint16_t *src;
1704 int len = blen;
1705 int idx = 0;
1706 union {
1707 uint16_t x;
1708 char b[2];
1709 } u;
1711 src = (uint16_t *) flashbase;
1712 while (len > 0) {
1713 u.x = src[(idx+offset)>>1];
1714 *bptr++ = u.b[(idx+offset)&1];
1715 len--;
1716 idx++;
1719 else {
1720 memcpy(bptr,flashbase + offset, blen);
1722 #else /* not _FLASH_BROKEN_BYTEREAD_ */
1724 #ifdef __long64
1726 /* Do it this way to allow flash at CS0 to be > 4 MB */
1727 int i;
1728 for (i = 0; i < blen; i++) {
1729 *bptr++ = (READFLASH_K1(softc,offset));
1730 offset++;
1733 #else
1734 memcpy(bptr,flashbase + offset, blen);
1735 #endif
1737 #endif /* ifdef _FLASH_BROKEN_BYTEREAD_ */
1739 buffer->buf_retlen = blen;
1741 return 0;
1744 /* *********************************************************************
1745 * flashdrv_inpstat(ctx,inpstat)
1747 * Return "input status". For flash devices, we always return true.
1749 * Input parameters:
1750 * ctx - device context
1751 * inpstat - input status structure
1753 * Return value:
1754 * 0 if ok, else error code
1755 ********************************************************************* */
1757 static int flashdrv_inpstat(cfe_devctx_t *ctx,iocb_inpstat_t *inpstat)
1759 /* flashdrv_t *softc = ctx->dev_softc; */
1761 inpstat->inp_status = 1;
1762 return 0;
1766 /* *********************************************************************
1767 * flash_writeall(softc,buffer)
1769 * Write the entire flash and reboot. This is a special case
1770 * used for when the flash currently being used for CFE's
1771 * execution is updated. A small assembly routine is relocated
1772 * to DRAM to do the update (so that the programming routine is
1773 * not erased while we're running it), and then the update
1774 * is done. When completed, CFE is restarted.
1776 * (we could get really sleazy here and touch the routine first
1777 * so it will stay in the cache, thereby eliminating the need
1778 * to relocate it, but that's dangerous)
1780 * Input parameters:
1781 * softc - our context
1782 * buffer - buffer descriptor
1784 * Return value:
1785 * does not return
1786 ********************************************************************* */
1788 static int flash_writeall(flashdrv_t *softc,iocb_buffer_t *buffer)
1790 void *rptr;
1791 void (*routine)(unsigned char *data,unsigned int flashbase,
1792 unsigned int size,unsigned int secsize);
1794 rptr = KMALLOC(flash_write_all_len,0);
1796 if (!rptr) return CFE_ERR_NOMEM;
1798 memcpy(rptr,flash_write_all_ptr,flash_write_all_len);
1800 _cfe_flushcache(0);
1802 routine = rptr;
1804 (*routine)(buffer->buf_ptr,
1805 softc->flashdrv_probe.flash_phys,
1806 buffer->buf_length,
1807 65536);
1809 return -1;
1813 /* *********************************************************************
1814 * flashdrv_write(ctx,buffer)
1816 * Write data to the flash device. The flash device is
1817 * considered to be like a disk (you need to specify the offset).
1819 * Input parameters:
1820 * ctx - device context
1821 * buffer - buffer descriptor
1823 * Return value:
1824 * 0 if ok, else error code
1825 ********************************************************************* */
1827 static int flashdrv_write(cfe_devctx_t *ctx,iocb_buffer_t *buffer)
1829 flashdrv_t *softc = ctx->dev_softc;
1830 unsigned char *bptr;
1831 int offset;
1832 int blen;
1833 int res;
1835 bptr = buffer->buf_ptr;
1836 blen = buffer->buf_length;
1837 offset = (int) buffer->buf_offset;
1839 if (!(softc->flashdrv_unlocked)) {
1840 if ((offset + blen) > softc->flashdrv_devsize) {
1841 blen = softc->flashdrv_devsize - offset;
1845 res = FLASHOP_WRITE_BLOCK(softc,offset,bptr,blen);
1847 buffer->buf_retlen = res;
1850 return (res == blen) ? 0 : CFE_ERR_IOERR;
1853 /* *********************************************************************
1854 * flashdrv_ioctl(ctx,buffer)
1856 * Handle special IOCTL functions for the flash. Flash devices
1857 * support NVRAM information, sector and chip erase, and a
1858 * special IOCTL for updating the running copy of CFE.
1860 * Input parameters:
1861 * ctx - device context
1862 * buffer - descriptor for IOCTL parameters
1864 * Return value:
1865 * 0 if ok else error
1866 ********************************************************************* */
1867 static int flashdrv_ioctl(cfe_devctx_t *ctx,iocb_buffer_t *buffer)
1869 flashdrv_t *softc = ctx->dev_softc;
1870 nvram_info_t *info;
1871 int offset;
1874 * If using flash to store environment, only the last sector
1875 * is used for environment stuff.
1878 switch ((int)buffer->buf_ioctlcmd) {
1879 case IOCTL_NVRAM_ERASE:
1880 if (softc->flashdrv_nvram_ok == FALSE) return CFE_ERR_UNSUPPORTED;
1881 FLASHOP_ERASE_SECTOR(softc,softc->flashdrv_nvraminfo.nvram_offset);
1882 return 0;
1884 case IOCTL_NVRAM_GETINFO:
1885 info = (nvram_info_t *) buffer->buf_ptr;
1886 if (buffer->buf_length != sizeof(nvram_info_t)) return CFE_ERR_INV_PARAM;
1887 if (softc->flashdrv_nvram_ok == FALSE) return CFE_ERR_UNSUPPORTED;
1888 info->nvram_offset = softc->flashdrv_nvraminfo.nvram_offset;
1889 info->nvram_size = softc->flashdrv_nvraminfo.nvram_size;
1890 info->nvram_eraseflg = softc->flashdrv_nvraminfo.nvram_eraseflg;
1891 buffer->buf_retlen = sizeof(nvram_info_t);
1892 return 0;
1894 case IOCTL_FLASH_ERASE_SECTOR:
1895 offset = (int) buffer->buf_offset;
1896 if (!(softc->flashdrv_unlocked)) {
1897 if (offset >= softc->flashdrv_devsize) return -1;
1899 FLASHOP_ERASE_SECTOR(softc,offset);
1900 return 0;
1902 case IOCTL_FLASH_ERASE_ALL:
1903 offset = (int) buffer->buf_offset;
1904 if (offset != 0) return -1;
1905 flash_erase_all(softc);
1906 return 0;
1908 case IOCTL_FLASH_WRITE_ALL:
1909 flash_writeall(softc,buffer);
1910 return -1; /* should not return */
1912 case IOCTL_FLASH_GETINFO:
1913 memcpy(buffer->buf_ptr,&(softc->flashdrv_info),sizeof(flash_info_t));
1914 return 0;
1916 case IOCTL_FLASH_GETSECTORS:
1917 return flash_sector_query(softc,(flash_sector_t *) buffer->buf_ptr);
1920 case IOCTL_FLASH_ERASE_RANGE:
1921 return flash_erase_range(softc,(flash_range_t *) buffer->buf_ptr);
1923 case IOCTL_NVRAM_UNLOCK:
1924 softc->flashdrv_unlocked = TRUE;
1925 break;
1927 case IOCTL_FLASH_PROTECT_RANGE:
1928 return flash_protect_range(softc,(flash_range_t *) buffer->buf_ptr);
1930 case IOCTL_FLASH_UNPROTECT_RANGE:
1931 return flash_unprotect_range(softc,(flash_range_t *) buffer->buf_ptr);
1933 default:
1934 return -1;
1937 return -1;
1941 /* *********************************************************************
1942 * flashdrv_close(ctx)
1944 * Close the flash device.
1946 * Input parameters:
1947 * ctx - device context
1949 * Return value:
1951 ********************************************************************* */
1952 static int flashdrv_close(cfe_devctx_t *ctx)
1954 /* flashdrv_t *softc = ctx->dev_softc; */
1957 return 0;