1 /* *********************************************************************
2 * Broadcom Common Firmware Environment (CFE)
4 * Flash device driver File: dev_ptflash.c
5 * (special version for production test board)
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 *********************************************************************
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 ********************************************************************* */
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"
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 /* *********************************************************************
70 ********************************************************************* */
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
,
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 /* *********************************************************************
142 ********************************************************************* */
144 const static cfe_devdisp_t flashdrv_dispatch
= {
155 const static cfe_devdisp_t flashdrv_ro_dispatch
= {
166 const cfe_driver_t ptflashdrv
= {
174 const cfe_driver_t ptflashdrv_ro
= {
178 &flashdrv_ro_dispatch
,
182 /* *********************************************************************
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 */
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
;
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 /* *********************************************************************
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
,
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
,
265 #define FLASHOPS_DEFAULT amd_flashops
269 /* *********************************************************************
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.
284 * softc - flash context
288 ********************************************************************* */
290 static unsigned int jedec_flash_manufacturer(flashdrv_t
*softc
)
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
);
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
315 * softc - flash context
316 * offset - distance in bytes into the flash
317 * val - byte to write
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
)
328 if (softc
->flashdrv_probe
.nchips
> 1)
329 softc
->chip_select
= offset
/ softc
->flashdrv_probe
.chipsize
;
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;
345 WRITEFLASH_K1(softc
,offset
,val
);
348 value
= READFLASH_K1(softc
,offset
) & 0xFF;
350 if ((value
& 0x80) == (val
& 0x80)) {
353 if ((value
& 0x20) != 0x20) {
357 if ((READFLASH_K1(softc
,offset
) & 0x80) == (val
& 0x80)) {
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
373 * softc - flash context
374 * offset - distance in bytes into the flash
375 * val - byte to write
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
);
393 WRITEFLASH_K1(softc
,offset
,val
);
395 /* Wait for write completion (toggle bit stops toggling) */
397 toggle
= (READFLASH_K1(softc
,offset
) & 0x40);
399 status
= READFLASH_K1(softc
,offset
);
401 if ((status
& 0x40) == toggle
)
407 /* In fast write mode we can't do a read check, so assume data OK */
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
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
427 * number of bytes written
428 ********************************************************************* */
429 static int hyundai_flash_write_block(flashdrv_t
*softc
,int offset
,void *buf
,int len
)
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
;
444 softc
->chip_select
= 0;
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
);
460 if (hyundai_flash_write_byte_fast(softc
,offset
,*ptr
) < 0) break;
465 /* See if write crosses into next flash chip */
466 if (len
&& (chipsize
== 0))
468 if (softc
->chip_select
== (softc
->flashdrv_probe
.nchips
- 1))
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
++;
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
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
500 * number of bytes written
501 ********************************************************************* */
502 static int amd_flash_write_block(flashdrv_t
*softc
,int offset
,void *buf
,int len
)
509 if (amd_flash_write_byte(softc
,offset
,*ptr
) < 0) break;
515 return (ptr
- (unsigned char *)buf
);
519 /* *********************************************************************
520 * amd_flash_erase_sector(softc,offset)
522 * Erase a single sector in the flash device
525 * softc - device context
526 * offset - offset in flash of sector to erase
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
;
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) {
567 /* *********************************************************************
568 * hyundai_flash_erase_sector(softc,offset)
570 * Erase a single sector in the flash device
573 * softc - device context
574 * offset - offset in flash of sector to erase
577 * 0 if ok, else error code
578 ********************************************************************* */
580 static int hyundai_flash_erase_sector(flashdrv_t
*softc
,int offset
)
584 unsigned int count
= 0;
586 if (softc
->flashdrv_probe
.nchips
> 1)
587 softc
->chip_select
= offset
/ softc
->flashdrv_probe
.chipsize
;
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);
613 status
= READFLASH_K1(softc
,offset
);
614 if ((status
& 0x40) == toggle
)
617 if ((status
& 0x20) == 0x20) {
618 if ((READFLASH_K1(softc
,offset
) & 0x40) == toggle
) {
619 break; /* no toggle, erase complete */
622 xprintf ("sector erase timed out\n");
632 /* *********************************************************************
633 * hyundai_flash_protect_sector(softc,offset)
635 * Protect a sectors in the flash device
638 * softc - device context
639 * offset - offset of sector to protect
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
;
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
)
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 */
677 if (trycnt
== 0 && READFLASH_K1(softc
,offset
) != 0x01)
679 xprintf ("protect! failed\n");
684 xprintf ("protect! succeeded trycnt = 0x%x\n",trycnt
);
689 /* *********************************************************************
690 * flash_protect_range(softc,range)
692 * Protect a range of sectors in the flash device
695 * softc - device context
696 * ranget - range of bytes to protect
699 * 0 if ok, else error code
700 ********************************************************************* */
702 static int flash_protect_range(flashdrv_t
*softc
, flash_range_t
*range
)
705 flash_sector_t sector
;
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') {
727 sector
.flash_sector_idx
= 0;
731 res
= flash_sector_query(softc
,§or
);
733 if (sector
.flash_sector_status
== FLASH_SECTOR_INVALID
) {
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
);
743 else if ((soffset
< range
->range_base
) &&
744 (soffset
+ sector
.flash_sector_size
> range
->range_base
)) {
745 res
= FLASHOP_PROTECT_SECTOR(softc
,soffset
);
748 else if (soffset
>= range
->range_base
+ range
->range_length
) {
752 sector
.flash_sector_idx
++;
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:");
765 * Even if every flash chip didn't get put in protect mode, it doesn't
768 for (i
= 0; i
< softc
->flashdrv_probe
.nchips
; i
++)
769 WRITEFLASH_K1(softc
,i
*softc
->flashdrv_probe
.chipsize
, AMD_FLASH_RESET
);
775 /* *********************************************************************
776 * hyundai_flash_unprotect_sector(softc,offset)
778 * Unprotect a sectors in the flash device
781 * softc - device context
782 * range - offset of sector to unprotect
785 * 0 if ok, else error code
786 ********************************************************************* */
788 static int hyundai_flash_unprotect_sector(flashdrv_t
*softc
, int offset
)
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
)
803 /* Get device ready */
805 if (softc
->flashdrv_probe
.nchips
> 1)
806 WRITEFLASH_K1(softc
, chipsize
*(offset
/chipsize
), 0x60);
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
) {
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");
829 xprintf ("protect! succeeded trycnt = 0x%x\n",trycnt
);
833 /* *********************************************************************
834 * flash_unprotect_range(softc,range)
836 * Unprotect a range of sectors in the flash device
839 * softc - device context
840 * range - range of bytes to unprotect
843 * 0 if ok, else error code
844 ********************************************************************* */
846 static int flash_unprotect_range(flashdrv_t
*softc
, flash_range_t
*range
)
849 flash_sector_t sector
;
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') {
870 sector
.flash_sector_idx
= 0;
875 res
= flash_sector_query(softc
,§or
);
877 if (sector
.flash_sector_status
== FLASH_SECTOR_INVALID
) {
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
);
887 else if ((soffset
< range
->range_base
) &&
888 (soffset
+ sector
.flash_sector_size
> range
->range_base
)) {
889 res
= FLASHOP_UNPROTECT_SECTOR(softc
,soffset
);
892 else if (soffset
>= range
->range_base
+ range
->range_length
) {
896 sector
.flash_sector_idx
++;
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:");
907 for (i
= 0; i
< softc
->flashdrv_probe
.nchips
; i
++)
909 WRITEFLASH_K1(softc
,i
*softc
->flashdrv_probe
.chipsize
, AMD_FLASH_RESET
);
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
924 * softc - flash context
925 * offset - distance in bytes into the flash
926 * val - byte to write
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
)
937 /* Send a program command */
938 WRITEFLASH_K1(softc
,offset
,INTEL_FLASH_PROGRAM
);
941 WRITEFLASH_K1(softc
,offset
,val
);
944 while ((READFLASH_K1(softc
,offset
) & 0x80) != 0x80) {
948 value
= READFLASH_K1(softc
,offset
) & 0xFF;
950 if (value
& (0x01|0x08|0x10)) return -1;
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
962 * softc - flash context
963 * offset - distance in bytes into the flash
964 * val - word to write
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
)
976 /* Send a program command */
977 WRITEFLASH_K1W(softc
,offset
,INTEL_FLASH_PROGRAM
);
980 WRITEFLASH_K1W(softc
,offset
,val
);
983 while ((READFLASH_K1W(softc
,offset
) & 0x80) != 0x80) {
987 value
= READFLASH_K1W(softc
,offset
) & 0xFF;
989 if (value
& (0x01|0x08|0x10)) return -1;
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
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
1007 * number of bytes written
1008 ********************************************************************* */
1009 static int intel_flash_write_block(flashdrv_t
*softc
,int offset
,void *buf
,int len
)
1012 unsigned short *ptrw
;
1014 if (softc
->flashdrv_probe
.flash_flags
& FLASH_FLG_16BIT
) {
1016 offset
&= ~1; /* offset must be even */
1018 if (intel_flash_write_word(softc
,offset
,*ptrw
) < 0) break;
1023 WRITEFLASH_K1(softc
,offset
,INTEL_FLASH_READ_MODE
);
1024 return ((unsigned char *) ptrw
- (unsigned char *)buf
);
1029 if (intel_flash_write_byte(softc
,offset
,*ptr
) < 0) break;
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
1047 * softc - device context
1048 * offset - offset in flash of sector to erase
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) {
1061 WRITEFLASH_K1(softc
,offset
,INTEL_FLASH_READ_MODE
);
1068 /* *********************************************************************
1069 * FLASH_ERASE_RANGE(softc,range)
1071 * Erase a range of sectors
1075 * range - range structure
1080 ********************************************************************* */
1082 static int flash_erase_range(flashdrv_t
*softc
,flash_range_t
*range
)
1084 flash_sector_t sector
;
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
;
1099 sector
.flash_sector_idx
= 0;
1100 softc
->chip_select
= range
->range_base
/ softc
->flashdrv_probe
.chipsize
;
1103 res
= flash_sector_query(softc
,§or
);
1104 if (res
!= 0) break;
1105 if (sector
.flash_sector_status
== FLASH_SECTOR_INVALID
) {
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
)) {
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
)) {
1125 res
= FLASHOP_ERASE_SECTOR(softc
,soffset
);
1126 if (res
!= 0) break;
1128 else if (soffset
>= range
->range_base
+ range
->range_length
) {
1132 sector
.flash_sector_idx
++;
1139 /* *********************************************************************
1140 * FLASH_ERASE_ALL(softc)
1142 * Erase the entire flash device, except the NVRAM area,
1151 ********************************************************************* */
1153 static int flash_erase_all(flashdrv_t
*softc
)
1155 flash_range_t range
;
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
);
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
);
1178 /* *********************************************************************
1179 * FLASH_CFI_GETSECTORS(softc)
1181 * Query the CFI information and store the sector info in our
1182 * private probe structure.
1185 * softc - our flash info
1190 ********************************************************************* */
1192 static int flash_cfi_getsectors(flashdrv_t
*softc
)
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
);
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.
1223 * softc - our flash info
1224 * sector - structure to receive sector information
1229 ********************************************************************* */
1231 static int flash_sector_query(flashdrv_t
*softc
,flash_sector_t
*sector
)
1236 unsigned int offset
;
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
;
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
;
1262 offset
+= (nblks
)*blksiz
;
1269 if (idx
== softc
->flashdrv_probe
.flash_nsectors
) {
1270 sector
->flash_sector_status
= FLASH_SECTOR_INVALID
;
1276 /* *********************************************************************
1277 * FLASH_SET_CMDSET(softc,cmdset)
1279 * Set the command-set that we'll honor for this flash.
1283 * cmdset - FLASH_CFI_CMDSET_xxx
1287 ********************************************************************* */
1289 static void flash_set_cmdset(flashdrv_t
*softc
,int 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;
1297 case FLASH_CFI_CMDSET_AMD_STD
:
1298 if (jedec_flash_manufacturer(softc
) == FLASH_MFR_HYUNDAI
)
1300 softc
->flashdrv_ops
= &hyundai_flashops
;
1303 case FLASH_CFI_CMDSET_AMD_ECS
:
1304 softc
->flashdrv_ops
= &amd_flashops
;
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
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
);
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.
1381 * info - flash info structure
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) {
1395 softc
->flashdrv_widemode
= 1; /* then wide */
1397 if (flash_cfi_probe(softc
) == 0) {
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.
1414 * softc - our context
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
);
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 */
1462 if ((*ptr
) == 0x55) {
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
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.
1495 * nothing. flashdrv_nvram_ok might change though.
1496 ********************************************************************* */
1498 static void flashdrv_setup_nvram(flashdrv_t
*softc
)
1500 flash_sector_t sector
;
1503 softc
->flashdrv_nvram_ok
= FALSE
;
1505 if (softc
->flashdrv_info
.flash_type
!= FLASH_TYPE_FLASH
) {
1509 sector
.flash_sector_idx
= 0;
1511 res
= flash_sector_query(softc
,§or
);
1512 if (res
== CFE_ERR_UNSUPPORTED
) break;
1514 if (sector
.flash_sector_status
!= FLASH_SECTOR_INVALID
) {
1515 sector
.flash_sector_idx
++;
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.
1549 * drv - driver descriptor
1550 * probe_a - physical address of flash
1551 * probe_b - size of flash (bytes)
1552 * probe_ptr - unused
1556 ********************************************************************* */
1558 static void flashdrv_probe(cfe_driver_t
*drv
,
1559 unsigned long probe_a
, unsigned long probe_b
,
1563 flash_probe_t
*probe
;
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);
1576 memset(softc
,0,sizeof(flashdrv_t
));
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
;
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;
1596 softc
->flashdrv_cmdaddr
= (char *) (softc
->flashdrv_probe
.flash_prog_phys
);
1598 softc
->flashdrv_cmdaddr
= (char *) UNCADDR(softc
->flashdrv_probe
.flash_prog_phys
);
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.
1617 * ctx - device context
1620 * 0 if ok else error code
1621 ********************************************************************* */
1623 static int flashdrv_open(cfe_devctx_t
*ctx
)
1625 flashdrv_t
*softc
= ctx
->dev_softc
;
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
;
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).
1665 * ctx - device context
1666 * buffer - buffer descriptor
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
;
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
) {
1711 src
= (uint16_t *) flashbase
;
1713 u
.x
= src
[(idx
+offset
)>>1];
1714 *bptr
++ = u
.b
[(idx
+offset
)&1];
1720 memcpy(bptr
,flashbase
+ offset
, blen
);
1722 #else /* not _FLASH_BROKEN_BYTEREAD_ */
1726 /* Do it this way to allow flash at CS0 to be > 4 MB */
1728 for (i
= 0; i
< blen
; i
++) {
1729 *bptr
++ = (READFLASH_K1(softc
,offset
));
1734 memcpy(bptr
,flashbase
+ offset
, blen
);
1737 #endif /* ifdef _FLASH_BROKEN_BYTEREAD_ */
1739 buffer
->buf_retlen
= blen
;
1744 /* *********************************************************************
1745 * flashdrv_inpstat(ctx,inpstat)
1747 * Return "input status". For flash devices, we always return true.
1750 * ctx - device context
1751 * inpstat - input status structure
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;
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)
1781 * softc - our context
1782 * buffer - buffer descriptor
1786 ********************************************************************* */
1788 static int flash_writeall(flashdrv_t
*softc
,iocb_buffer_t
*buffer
)
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
);
1804 (*routine
)(buffer
->buf_ptr
,
1805 softc
->flashdrv_probe
.flash_phys
,
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).
1820 * ctx - device context
1821 * buffer - buffer descriptor
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
;
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.
1861 * ctx - device context
1862 * buffer - descriptor for IOCTL parameters
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
;
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
);
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
);
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
);
1902 case IOCTL_FLASH_ERASE_ALL
:
1903 offset
= (int) buffer
->buf_offset
;
1904 if (offset
!= 0) return -1;
1905 flash_erase_all(softc
);
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
));
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
;
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
);
1941 /* *********************************************************************
1942 * flashdrv_close(ctx)
1944 * Close the flash device.
1947 * ctx - device context
1951 ********************************************************************* */
1952 static int flashdrv_close(cfe_devctx_t
*ctx
)
1954 /* flashdrv_t *softc = ctx->dev_softc; */