1 /* *********************************************************************
2 * Broadcom Common Firmware Environment (CFE)
4 * Flash device driver File: dev_flash.c
6 * This driver supports various types of flash
7 * parts. You can also put the environment storage in
8 * the flash - the top sector is reserved for that purpose.
10 * Author: Mitch Lichtenberg (mpl@broadcom.com)
12 *********************************************************************
14 * Copyright 2000,2001,2002,2003
15 * Broadcom Corporation. All rights reserved.
17 * This software is furnished under license and may be used and
18 * copied only in accordance with the following terms and
19 * conditions. Subject to these conditions, you may download,
20 * copy, install, use, modify and distribute modified or unmodified
21 * copies of this software in source and/or binary form. No title
22 * or ownership is transferred hereby.
24 * 1) Any source code used, modified or distributed must reproduce
25 * and retain this copyright notice and list of conditions
26 * as they appear in the source file.
28 * 2) No right is granted to use any trade name, trademark, or
29 * logo of Broadcom Corporation. The "Broadcom Corporation"
30 * name may not be used to endorse or promote products derived
31 * from this software without the prior written permission of
32 * Broadcom Corporation.
34 * 3) THIS SOFTWARE IS PROVIDED "AS-IS" AND ANY EXPRESS OR
35 * IMPLIED WARRANTIES, INCLUDING BUT NOT LIMITED TO, ANY IMPLIED
36 * WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR
37 * PURPOSE, OR NON-INFRINGEMENT ARE DISCLAIMED. IN NO EVENT
38 * SHALL BROADCOM BE LIABLE FOR ANY DAMAGES WHATSOEVER, AND IN
39 * PARTICULAR, BROADCOM SHALL NOT BE LIABLE FOR DIRECT, INDIRECT,
40 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
41 * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE
42 * GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
43 * BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
44 * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR
45 * TORT (INCLUDING NEGLIGENCE OR OTHERWISE), EVEN IF ADVISED OF
46 * THE POSSIBILITY OF SUCH DAMAGE.
47 ********************************************************************* */
50 #include "lib_types.h"
51 #include "lib_malloc.h"
52 #include "lib_printf.h"
53 #include "lib_string.h"
54 #include "addrspace.h"
56 #include "cfe_device.h"
57 #include "cfe_ioctl.h"
58 #include "cfe_error.h"
60 #include "dev_flash.h"
62 /* *********************************************************************
64 ********************************************************************* */
66 #define FLASHCMD(sc,x,y) *((volatile unsigned char *)(sc->flashdrv_cmdaddr+ \
67 ((x)<<(sc)->flashdrv_widemode))) = (y)
68 #define FLASHSTATUS(sc,x) *((volatile unsigned char *)(sc->flashdrv_cmdaddr+ \
69 ((x)<<(sc)->flashdrv_widemode)))
71 #define WRITEFLASH_K1(sc,x,y) *((volatile unsigned char *)(sc->flashdrv_cmdaddr+(x))) = (y)
72 #define READFLASH_K1(sc,x) *((volatile unsigned char *)(sc->flashdrv_cmdaddr+(x)))
74 #define WRITEFLASH_K1W(sc,x,y) *((volatile unsigned short *)(sc->flashdrv_cmdaddr+(x))) = (y)
75 #define READFLASH_K1W(sc,x) *((volatile unsigned short *)(sc->flashdrv_cmdaddr+(x)))
78 #define GETCFIBYTE(softc,offset) READFLASH_K1(softc,((offset) << (softc->flashdrv_widemode)))
80 /* *********************************************************************
81 * Forward declarations
82 ********************************************************************* */
85 static void flashdrv_probe(cfe_driver_t
*drv
,
86 unsigned long probe_a
, unsigned long probe_b
,
90 static int flashdrv_open(cfe_devctx_t
*ctx
);
91 static int flashdrv_read(cfe_devctx_t
*ctx
,iocb_buffer_t
*buffer
);
92 static int flashdrv_inpstat(cfe_devctx_t
*ctx
,iocb_inpstat_t
*inpstat
);
93 static int flashdrv_write(cfe_devctx_t
*ctx
,iocb_buffer_t
*buffer
);
94 static int flashdrv_ioctl(cfe_devctx_t
*ctx
,iocb_buffer_t
*buffer
);
95 static int flashdrv_close(cfe_devctx_t
*ctx
);
97 /* *********************************************************************
99 ********************************************************************* */
101 const static cfe_devdisp_t flashdrv_dispatch
= {
112 const cfe_driver_t flashdrv
= {
121 /* *********************************************************************
123 ********************************************************************* */
125 typedef struct flash_cfidata_s
{
126 unsigned int cfidata_cmdset
; /* ID of primary command set */
127 unsigned int cfidata_devif
; /* device interface byte */
128 unsigned int cfidata_size
; /* probed device size */
131 typedef struct flashops_s flashops_t
;
133 typedef struct flashdrv_s
{
134 flash_probe_t flashdrv_probe
; /* data from probe */
135 int flashdrv_devsize
; /* size reported by driver */
136 unsigned char *flashdrv_cmdaddr
; /* virtual address (K1) */
137 int flashdrv_widemode
; /* 1=wide flash in byte mode, 0=narrow flash */
138 int flashdrv_initialized
; /* true if we've probed already */
139 flash_info_t flashdrv_info
;
140 int flashdrv_nvram_ok
; /* true if we can use as NVRAM */
141 int flashdrv_unlocked
; /* true if we can r/w past devsize */
142 nvram_info_t flashdrv_nvraminfo
;
143 flashops_t
*flashdrv_ops
;
144 flash_cfidata_t flashdrv_cfidata
;
148 int (*erasesector
)(flashdrv_t
*f
,int offset
);
149 int (*writeblk
)(flashdrv_t
*f
,int offset
,void *buf
,int len
);
152 /* *********************************************************************
154 ********************************************************************* */
156 #define FLASHOP_ERASE_SECTOR(softc,sect) (*((softc)->flashdrv_ops->erasesector))((softc),(sect))
157 #define FLASHOP_WRITE_BLOCK(softc,off,buf,len) (*((softc)->flashdrv_ops->writeblk))((softc),(off),(buf),(len))
159 /* *********************************************************************
160 * forward declarations
161 ********************************************************************* */
164 static int flash_sector_query(flashdrv_t
*softc
,flash_sector_t
*sector
);
166 static int amd_flash_write_block(flashdrv_t
*softc
,int offset
,void *buf
,int len
);
167 static int amd_flash_erase_sector(flashdrv_t
*softc
,int offset
);
169 static int intel_flash_write_block(flashdrv_t
*softc
,int offset
,void *buf
,int len
);
170 static int intel_flash_erase_sector(flashdrv_t
*softc
,int offset
);
172 static flashops_t amd_flashops
= {
173 amd_flash_erase_sector
,
174 amd_flash_write_block
,
177 static flashops_t intel_flashops
= {
178 intel_flash_erase_sector
,
179 intel_flash_write_block
,
182 #define FLASHOPS_DEFAULT amd_flashops
186 /* *********************************************************************
188 ********************************************************************* */
190 extern void *flash_write_all_ptr
;
191 extern int flash_write_all_len
;
193 extern void _cfe_flushcache(int);
197 /* *********************************************************************
198 * amd_flash_write_byte(softc,offset,val)
200 * Write a single byte to the flash. The sector that the flash
201 * byte is in should have been previously erased, or else this
205 * softc - flash context
206 * offset - distance in bytes into the flash
207 * val - byte to write
211 * else if flash could not be written
212 ********************************************************************* */
213 static inline int amd_flash_write_byte(flashdrv_t
*softc
,int offset
, unsigned char val
)
217 /* Do an "unlock write" sequence */
218 FLASHCMD(softc
,AMD_FLASH_MAGIC_ADDR_1
,AMD_FLASH_MAGIC_1
);
219 FLASHCMD(softc
,AMD_FLASH_MAGIC_ADDR_2
,AMD_FLASH_MAGIC_2
);
221 /* Send a program command */
222 FLASHCMD(softc
,AMD_FLASH_MAGIC_ADDR_1
,AMD_FLASH_PROGRAM
);
225 WRITEFLASH_K1(softc
,offset
,val
);
228 value
= READFLASH_K1(softc
,offset
) & 0xFF;
230 if ((value
& 0x80) == (val
& 0x80)) {
233 if ((value
& 0x20) != 0x20) {
237 if ((READFLASH_K1(softc
,offset
) & 0x80) == (val
& 0x80)) {
247 /* *********************************************************************
248 * amd_flash_write_block(softc,offset,val)
250 * Write a single byte to the flash. The sector that the flash
251 * byte is in should have been previously erased, or else this
255 * softc - flash context
256 * offset - distance in bytes into the flash
257 * buf - buffer of bytes to write
258 * len - number of bytes to write
261 * number of bytes written
262 ********************************************************************* */
263 static int amd_flash_write_block(flashdrv_t
*softc
,int offset
,void *buf
,int len
)
270 if (amd_flash_write_byte(softc
,offset
,*ptr
) < 0) break;
277 return (ptr
- (unsigned char *)buf
);
281 /* *********************************************************************
282 * amd_flash_erase_sector(softc,offset)
284 * Erase a single sector in the flash device
287 * softc - device context
288 * offset - offset in flash of sector to erase
291 * 0 if ok, else error code
292 ********************************************************************* */
294 static int amd_flash_erase_sector(flashdrv_t
*softc
,int offset
)
296 /* Do an "unlock write" sequence */
297 FLASHCMD(softc
,AMD_FLASH_MAGIC_ADDR_1
,AMD_FLASH_MAGIC_1
); /* cycles 1-2 */
298 FLASHCMD(softc
,AMD_FLASH_MAGIC_ADDR_2
,AMD_FLASH_MAGIC_2
);
300 /* send the erase command */
301 FLASHCMD(softc
,AMD_FLASH_MAGIC_ADDR_1
,AMD_FLASH_ERASE_3
); /* cycle 3 */
303 /* Do an "unlock write" sequence */
304 FLASHCMD(softc
,AMD_FLASH_MAGIC_ADDR_1
,AMD_FLASH_MAGIC_1
); /* cycles 4-5 */
305 FLASHCMD(softc
,AMD_FLASH_MAGIC_ADDR_2
,AMD_FLASH_MAGIC_2
);
308 * Send the "erase sector" qualifier - don't use FLASHCMD
309 * because it changes the offset.
311 WRITEFLASH_K1(softc
,offset
,AMD_FLASH_ERASE_SEC_6
);
313 while ((READFLASH_K1(softc
,offset
) & 0x80) != 0x80) {
322 /* *********************************************************************
323 * intel_flash_write_byte(softc,offset,val)
325 * Write a single byte to the flash. The sector that the flash
326 * byte is in should have been previously erased, or else this
330 * softc - flash context
331 * offset - distance in bytes into the flash
332 * val - byte to write
336 * else if flash could not be written
337 ********************************************************************* */
338 static inline int intel_flash_write_byte(flashdrv_t
*softc
,
339 int offset
, unsigned char val
)
343 /* Send a program command */
344 WRITEFLASH_K1(softc
,offset
,INTEL_FLASH_PROGRAM
);
347 WRITEFLASH_K1(softc
,offset
,val
);
350 while ((READFLASH_K1(softc
,offset
) & 0x80) != 0x80) {
354 value
= READFLASH_K1(softc
,offset
) & 0xFF;
356 if (value
& (0x01|0x08|0x10)) return -1;
360 /* *********************************************************************
361 * intel_flash_write_word(softc,offset,val)
363 * Write a single word to the flash. The sector that the flash
364 * byte is in should have been previously erased, or else this
368 * softc - flash context
369 * offset - distance in bytes into the flash
370 * val - word to write
374 * else if flash could not be written
375 ********************************************************************* */
376 static inline int intel_flash_write_word(flashdrv_t
*softc
,
377 int offset
, unsigned short val
)
382 /* Send a program command */
383 WRITEFLASH_K1W(softc
,offset
,INTEL_FLASH_PROGRAM
);
386 WRITEFLASH_K1W(softc
,offset
,val
);
389 while ((READFLASH_K1W(softc
,offset
) & 0x80) != 0x80) {
393 value
= READFLASH_K1W(softc
,offset
) & 0xFF;
395 if (value
& (0x01|0x08|0x10)) return -1;
399 /* *********************************************************************
400 * intel_flash_write_block(softc,offset,val)
402 * Write a single byte to the flash. The sector that the flash
403 * byte is in should have been previously erased, or else this
407 * softc - flash context
408 * offset - distance in bytes into the flash
409 * buf - buffer of bytes to write
410 * len - number of bytes to write
413 * number of bytes written
414 ********************************************************************* */
415 static int intel_flash_write_block(flashdrv_t
*softc
,int offset
,void *buf
,int len
)
418 unsigned short *ptrw
;
420 if (softc
->flashdrv_probe
.flash_flags
& FLASH_FLG_16BIT
) {
422 offset
&= ~1; /* offset must be even */
424 if (intel_flash_write_word(softc
,offset
,*ptrw
) < 0) break;
429 WRITEFLASH_K1(softc
,offset
,INTEL_FLASH_READ_MODE
);
430 return ((unsigned char *) ptrw
- (unsigned char *)buf
);
435 if (intel_flash_write_byte(softc
,offset
,*ptr
) < 0) break;
440 WRITEFLASH_K1(softc
,offset
,INTEL_FLASH_READ_MODE
);
441 return (ptr
- (unsigned char *)buf
);
447 /* *********************************************************************
448 * intel_flash_erase_sector(softc,offset)
450 * Erase a single sector on the flash device
453 * softc - device context
454 * offset - offset in flash of sector to erase
457 * 0 if ok, else error code
458 ********************************************************************* */
459 static int intel_flash_erase_sector(flashdrv_t
*softc
,int offset
)
461 WRITEFLASH_K1(softc
,offset
,INTEL_FLASH_ERASE_BLOCK
);
462 WRITEFLASH_K1(softc
,offset
,INTEL_FLASH_ERASE_CONFIRM
);
464 while ((READFLASH_K1(softc
,offset
) & 0x80) != 0x80) {
467 WRITEFLASH_K1(softc
,offset
,INTEL_FLASH_READ_MODE
);
476 /* *********************************************************************
477 * FLASH_ERASE_RANGE(softc,range)
479 * Erase a range of sectors
483 * range - range structure
488 ********************************************************************* */
490 static int flash_erase_range(flashdrv_t
*softc
,flash_range_t
*range
)
492 flash_sector_t sector
;
495 if (softc
->flashdrv_info
.flash_type
!= FLASH_TYPE_FLASH
) {
496 return CFE_ERR_UNSUPPORTED
;
500 if (range
->range_base
+range
->range_length
> softc
->flashdrv_devsize
) {
501 return CFE_ERR_INV_PARAM
;
506 sector
.flash_sector_idx
= 0;
509 res
= flash_sector_query(softc
,§or
);
511 if (sector
.flash_sector_status
== FLASH_SECTOR_INVALID
) {
515 if ((sector
.flash_sector_offset
>= range
->range_base
) &&
516 (sector
.flash_sector_offset
<
517 (range
->range_base
+range
->range_length
-1))) {
519 if (softc
->flashdrv_nvram_ok
&&
520 (sector
.flash_sector_offset
>= softc
->flashdrv_nvraminfo
.nvram_offset
)) {
523 res
= FLASHOP_ERASE_SECTOR(softc
,sector
.flash_sector_offset
);
526 sector
.flash_sector_idx
++;
533 /* *********************************************************************
534 * FLASH_ERASE_ALL(softc)
536 * Erase the entire flash device, except the NVRAM area,
545 ********************************************************************* */
547 static int flash_erase_all(flashdrv_t
*softc
)
551 range
.range_base
= 0;
552 range
.range_length
= softc
->flashdrv_devsize
;
554 return flash_erase_range(softc
,&range
);
557 /* *********************************************************************
558 * FLASH_CFI_GETSECTORS(softc)
560 * Query the CFI information and store the sector info in our
561 * private probe structure.
564 * softc - our flash info
569 ********************************************************************* */
571 static int flash_cfi_getsectors(flashdrv_t
*softc
)
578 regcnt
= GETCFIBYTE(softc
,FLASH_CFI_REGION_COUNT
);
580 softc
->flashdrv_probe
.flash_nsectors
= regcnt
;
582 for (idx
= 0; idx
< regcnt
; idx
++) {
583 nblks
= ((int)GETCFIBYTE(softc
,FLASH_CFI_REGION_TABLE
+0+idx
*4) +
584 (int)(GETCFIBYTE(softc
,FLASH_CFI_REGION_TABLE
+1+idx
*4)<<8)) + 1;
585 blksiz
= ((int)GETCFIBYTE(softc
,FLASH_CFI_REGION_TABLE
+2+idx
*4) +
586 (int)(GETCFIBYTE(softc
,FLASH_CFI_REGION_TABLE
+3+idx
*4)<<8)) * 256;
587 softc
->flashdrv_probe
.flash_sectors
[idx
] =
588 FLASH_SECTOR_RANGE(nblks
,blksiz
);
595 /* *********************************************************************
596 * FLASH_SECTOR_QUERY(softc,sector)
598 * Query the sector information about a particular sector. You can
599 * call this iteratively to find out about all of the sectors.
602 * softc - our flash info
603 * sector - structure to receive sector information
608 ********************************************************************* */
610 static int flash_sector_query(flashdrv_t
*softc
,flash_sector_t
*sector
)
618 if (softc
->flashdrv_info
.flash_type
!= FLASH_TYPE_FLASH
) {
619 return CFE_ERR_UNSUPPORTED
;
622 if (softc
->flashdrv_probe
.flash_nsectors
== 0) {
623 return CFE_ERR_UNSUPPORTED
;
628 for (idx
= 0; idx
< softc
->flashdrv_probe
.flash_nsectors
; idx
++) {
629 nblks
= FLASH_SECTOR_NBLKS(softc
->flashdrv_probe
.flash_sectors
[idx
]);
630 blksiz
= FLASH_SECTOR_SIZE(softc
->flashdrv_probe
.flash_sectors
[idx
]);
631 if (sector
->flash_sector_idx
< curblk
+nblks
) {
632 sector
->flash_sector_status
= FLASH_SECTOR_OK
;
633 sector
->flash_sector_offset
=
634 offset
+ (sector
->flash_sector_idx
-curblk
)*blksiz
;
635 sector
->flash_sector_size
= blksiz
;
639 offset
+= (nblks
)*blksiz
;
644 if (idx
== softc
->flashdrv_probe
.flash_nsectors
) {
645 sector
->flash_sector_status
= FLASH_SECTOR_INVALID
;
652 /* *********************************************************************
653 * FLASH_SET_CMDSET(softc,cmdset)
655 * Set the command-set that we'll honor for this flash.
659 * cmdset - FLASH_CFI_CMDSET_xxx
663 ********************************************************************* */
665 static void flash_set_cmdset(flashdrv_t
*softc
,int cmdset
)
668 case FLASH_CFI_CMDSET_INTEL_ECS
:
669 case FLASH_CFI_CMDSET_INTEL_STD
:
670 softc
->flashdrv_ops
= &intel_flashops
;
671 softc
->flashdrv_widemode
= 0;
673 case FLASH_CFI_CMDSET_AMD_STD
:
674 case FLASH_CFI_CMDSET_AMD_ECS
:
675 softc
->flashdrv_ops
= &amd_flashops
;
678 /* we don't understand the command set - treat it like ROM */
679 softc
->flashdrv_info
.flash_type
= FLASH_TYPE_ROM
;
684 /* *********************************************************************
685 * FLASH_CFI_PROBE(softc)
687 * Try to do a CFI query on this device. If we find the m
688 * magic signature, extract some useful information from the
695 * 0 if successful, <0 if error
696 ********************************************************************* */
697 static int flash_cfi_probe(flashdrv_t
*softc
)
699 FLASHCMD(softc
,FLASH_CFI_QUERY_ADDR
,FLASH_CFI_QUERY_MODE
);
701 if (!((GETCFIBYTE(softc
,FLASH_CFI_SIGNATURE
+0) == 'Q') &&
702 (GETCFIBYTE(softc
,FLASH_CFI_SIGNATURE
+1) == 'R') &&
703 (GETCFIBYTE(softc
,FLASH_CFI_SIGNATURE
+2) == 'Y'))) {
705 FLASHCMD(softc
,FLASH_CFI_QUERY_ADDR
,FLASH_CFI_QUERY_EXIT
);
706 return CFE_ERR_UNSUPPORTED
;
710 * Gather info from flash
713 softc
->flashdrv_cfidata
.cfidata_cmdset
=
714 ((unsigned int) (GETCFIBYTE(softc
,FLASH_CFI_COMMAND_SET
))) +
715 (((unsigned int) (GETCFIBYTE(softc
,FLASH_CFI_COMMAND_SET
+1))) << 8);
717 softc
->flashdrv_cfidata
.cfidata_devif
=
718 ((unsigned int) (GETCFIBYTE(softc
,FLASH_CFI_DEVICE_INTERFACE
))) +
719 (((unsigned int) (GETCFIBYTE(softc
,FLASH_CFI_DEVICE_INTERFACE
+1))) << 8);
721 softc
->flashdrv_cfidata
.cfidata_size
=
722 1 << ((unsigned int) (GETCFIBYTE(softc
,FLASH_CFI_DEVICE_SIZE
)));
724 flash_cfi_getsectors(softc
);
727 * Don't need to be in query mode anymore.
730 FLASHCMD(softc
,FLASH_CFI_QUERY_ADDR
,FLASH_CFI_QUERY_EXIT
);
732 softc
->flashdrv_info
.flash_type
= FLASH_TYPE_FLASH
;
734 flash_set_cmdset(softc
,softc
->flashdrv_cfidata
.cfidata_cmdset
);
740 /* *********************************************************************
741 * FLASH_GETWIDTH(softc,info)
743 * Try to determine the width of the flash. This is needed for
744 * management purposes, since some 16-bit flash parts in 8-bit mode
745 * have an "A-1" (address line -1) wire to select bytes within
746 * a 16-bit word. When this is present, the flash commands
747 * will have different offsets.
751 * info - flash info structure
755 ********************************************************************* */
757 static void flash_getwidth(flashdrv_t
*softc
,flash_info_t
*info
)
759 softc
->flashdrv_widemode
= 0; /* first try narrow */
761 if (flash_cfi_probe(softc
) == 0) {
765 softc
->flashdrv_widemode
= 1; /* then wide */
767 if (flash_cfi_probe(softc
) == 0) {
771 /* Just return, assume not wide if no CFI interface */
772 softc
->flashdrv_widemode
= 0;
774 softc
->flashdrv_info
.flash_type
= FLASH_TYPE_ROM
; /* no CFI: treat as ROM */
777 /* *********************************************************************
778 * flash_getinfo(softc)
780 * Try to determine if the specified region is flash, ROM, SRAM,
784 * softc - our context
788 ********************************************************************* */
790 static void flash_getinfo(flashdrv_t
*softc
)
793 volatile uint8_t *ptr
;
794 flash_info_t
*info
= &(softc
->flashdrv_info
);
797 * Set up some defaults based on the probe data
800 softc
->flashdrv_widemode
= 0;
801 info
->flash_base
= softc
->flashdrv_probe
.flash_phys
;
802 info
->flash_size
= softc
->flashdrv_probe
.flash_size
;
803 softc
->flashdrv_devsize
= softc
->flashdrv_probe
.flash_size
;
804 info
->flash_type
= FLASH_TYPE_UNKNOWN
;
805 info
->flash_flags
= 0;
808 * If we've been told not to try probing, just assume
809 * we're a flash part.
812 if (softc
->flashdrv_probe
.flash_flags
& FLASH_FLG_MANUAL
) {
813 info
->flash_type
= FLASH_TYPE_FLASH
;
814 if (softc
->flashdrv_probe
.flash_flags
& FLASH_FLG_WIDE
) {
815 softc
->flashdrv_widemode
= TRUE
;
817 if (softc
->flashdrv_probe
.flash_cmdset
) {
818 flash_set_cmdset(softc
,softc
->flashdrv_probe
.flash_cmdset
);
824 * Attempt to read/write byte zero. If it is changable,
825 * this is SRAM (or maybe a ROM emulator with the write line hooked up)
828 ptr
= (volatile uint8_t *) UNCADDR(softc
->flashdrv_probe
.flash_phys
);
829 save0
= *ptr
; /* save old value */
830 save1
= *(ptr
+1); /* save old value */
832 if ((*ptr
) == 0x55) {
834 if ((*ptr
) == 0xAA) {
835 info
->flash_type
= FLASH_TYPE_SRAM
;
839 if (*ptr
== save0
) info
->flash_type
= FLASH_TYPE_ROM
;
840 else (*ptr
) = save0
; /* restore old value */
843 * If we thought it was ROM, try doing a CFI query
844 * to see if it was flash. This check is kind of kludgey
848 if (info
->flash_type
== FLASH_TYPE_ROM
) {
849 flash_getwidth(softc
,info
);
850 if (info
->flash_type
== FLASH_TYPE_FLASH
) {
855 /* *********************************************************************
856 * flashdrv_setup_nvram(softc)
858 * If we're going to be using a sector of the flash for NVRAM,
859 * go find that sector and set it up.
865 * nothing. flashdrv_nvram_ok might change though.
866 ********************************************************************* */
868 static void flashdrv_setup_nvram(flashdrv_t
*softc
)
870 flash_sector_t sector
;
873 softc
->flashdrv_nvram_ok
= FALSE
;
875 if (softc
->flashdrv_info
.flash_type
!= FLASH_TYPE_FLASH
) {
879 sector
.flash_sector_idx
= 0;
881 res
= flash_sector_query(softc
,§or
);
882 if (res
== CFE_ERR_UNSUPPORTED
) break;
884 if (sector
.flash_sector_status
!= FLASH_SECTOR_INVALID
) {
885 sector
.flash_sector_idx
++;
892 /* The sector offset will still contain the value at the end
893 of the last successful call. That's the last sector, so
894 we can now use this to fill in the NVRAM info structure */
896 if (res
!= CFE_ERR_UNSUPPORTED
) {
897 softc
->flashdrv_nvraminfo
.nvram_offset
= sector
.flash_sector_offset
;
898 softc
->flashdrv_nvraminfo
.nvram_size
= sector
.flash_sector_size
;
899 softc
->flashdrv_nvraminfo
.nvram_eraseflg
= TRUE
; /* needs erase */
900 softc
->flashdrv_nvram_ok
= TRUE
;
902 * Set the flash's size as reported in the flash_info structure
903 * to be the size without the NVRAM sector at the end.
905 softc
->flashdrv_info
.flash_size
= sector
.flash_sector_offset
;
906 softc
->flashdrv_devsize
= sector
.flash_sector_offset
;
912 /* *********************************************************************
913 * flashdrv_probe(drv,probe_a,probe_b,probe_ptr)
915 * Device probe routine. Attach the flash device to
916 * CFE's device table.
919 * drv - driver descriptor
920 * probe_a - physical address of flash
921 * probe_b - size of flash (bytes)
926 ********************************************************************* */
928 static void flashdrv_probe(cfe_driver_t
*drv
,
929 unsigned long probe_a
, unsigned long probe_b
,
933 flash_probe_t
*probe
;
936 probe
= (flash_probe_t
*) probe_ptr
;
939 * probe_a is the flash base address
940 * probe_b is the size of the flash
941 * probe_ptr is unused.
944 softc
= (flashdrv_t
*) KMALLOC(sizeof(flashdrv_t
),0);
946 memset(softc
,0,sizeof(flashdrv_t
));
949 /* Passed probe structure, do fancy stuff */
950 memcpy(&(softc
->flashdrv_probe
),probe
,sizeof(flash_probe_t
));
951 if (softc
->flashdrv_probe
.flash_prog_phys
== 0) {
952 softc
->flashdrv_probe
.flash_prog_phys
=
953 softc
->flashdrv_probe
.flash_phys
;
957 /* Didn't pass probe structure, do the compatible thing */
958 softc
->flashdrv_probe
.flash_phys
= probe_a
;
959 softc
->flashdrv_probe
.flash_prog_phys
= probe_a
;
960 softc
->flashdrv_probe
.flash_size
= probe_b
;
961 softc
->flashdrv_probe
.flash_flags
= FLASH_FLG_NVRAM
;
964 softc
->flashdrv_cmdaddr
= (unsigned char *) UNCADDR(softc
->flashdrv_probe
.flash_prog_phys
);
965 softc
->flashdrv_initialized
= 0;
966 softc
->flashdrv_ops
= &FLASHOPS_DEFAULT
;
967 xsprintf(descr
,"%s at %08X size %uKB",drv
->drv_description
,
968 softc
->flashdrv_probe
.flash_phys
,
969 softc
->flashdrv_probe
.flash_size
/1024);
970 cfe_attach(drv
,softc
,NULL
,descr
);
976 /* *********************************************************************
979 * Called when the flash device is opened.
982 * ctx - device context
985 * 0 if ok else error code
986 ********************************************************************* */
988 static int flashdrv_open(cfe_devctx_t
*ctx
)
990 flashdrv_t
*softc
= ctx
->dev_softc
;
996 if (!softc
->flashdrv_initialized
) {
999 * Assume it's not an NVRAM-capable flash
1002 softc
->flashdrv_nvram_ok
= FALSE
;
1005 * Probe flash for geometry
1007 flash_getinfo(softc
);
1010 * Find the last sector if in NVRAM mode
1013 if (softc
->flashdrv_probe
.flash_flags
& FLASH_FLG_NVRAM
) {
1014 flashdrv_setup_nvram(softc
);
1017 softc
->flashdrv_initialized
= TRUE
;
1024 /* *********************************************************************
1025 * flashdrv_read(ctx,buffer)
1027 * Read data from the flash device. The flash device is
1028 * considered to be like a disk (you need to specify the offset).
1031 * ctx - device context
1032 * buffer - buffer descriptor
1035 * 0 if ok, else error code
1036 ********************************************************************* */
1038 static int flashdrv_read(cfe_devctx_t
*ctx
,iocb_buffer_t
*buffer
)
1040 flashdrv_t
*softc
= ctx
->dev_softc
;
1041 unsigned char *bptr
;
1042 unsigned char *flashbase
;
1047 * For now, read the flash from K1 (always). Eventually
1048 * we need to flush the cache after a write.
1051 flashbase
= (unsigned char *) UNCADDR(softc
->flashdrv_probe
.flash_phys
);
1053 bptr
= buffer
->buf_ptr
;
1054 blen
= buffer
->buf_length
;
1055 offset
= (int) buffer
->buf_offset
;
1057 if (!(softc
->flashdrv_unlocked
)) {
1058 if ((offset
+ blen
) > softc
->flashdrv_devsize
) {
1059 blen
= softc
->flashdrv_devsize
- offset
;
1063 #ifdef _FLASH_BROKEN_BYTEREAD_
1065 * BCM1250 users: don't worry about this. This hack is for
1066 * something else and should not be used with the BCM1250.
1068 if (softc
->flashdrv_probe
.flash_flags
& FLASH_FLG_16BIT
) {
1077 src
= (uint16_t *) flashbase
;
1079 u
.x
= src
[(idx
+offset
)>>1];
1080 *bptr
++ = u
.b
[(idx
+offset
)&1];
1086 memcpy(bptr
,flashbase
+ offset
, blen
);
1089 memcpy(bptr
,flashbase
+ offset
, blen
);
1092 buffer
->buf_retlen
= blen
;
1097 /* *********************************************************************
1098 * flashdrv_inpstat(ctx,inpstat)
1100 * Return "input status". For flash devices, we always return true.
1103 * ctx - device context
1104 * inpstat - input status structure
1107 * 0 if ok, else error code
1108 ********************************************************************* */
1110 static int flashdrv_inpstat(cfe_devctx_t
*ctx
,iocb_inpstat_t
*inpstat
)
1112 /* flashdrv_t *softc = ctx->dev_softc; */
1114 inpstat
->inp_status
= 1;
1119 /* *********************************************************************
1120 * flash_writeall(softc,buffer)
1122 * Write the entire flash and reboot. This is a special case
1123 * used for when the flash currently being used for CFE's
1124 * execution is updated. A small assembly routine is relocated
1125 * to DRAM to do the update (so that the programming routine is
1126 * not erased while we're running it), and then the update
1127 * is done. When completed, CFE is restarted.
1129 * (we could get really sleazy here and touch the routine first
1130 * so it will stay in the cache, thereby eliminating the need
1131 * to relocate it, but that's dangerous)
1134 * softc - our context
1135 * buffer - buffer descriptor
1139 ********************************************************************* */
1141 static int flash_writeall(flashdrv_t
*softc
,iocb_buffer_t
*buffer
)
1144 void (*routine
)(unsigned char *data
,unsigned int flashbase
,
1145 unsigned int size
,unsigned int secsize
);
1147 rptr
= KMALLOC(flash_write_all_len
,0);
1149 if (!rptr
) return CFE_ERR_NOMEM
;
1151 memcpy(rptr
,flash_write_all_ptr
,flash_write_all_len
);
1157 (*routine
)(buffer
->buf_ptr
,
1158 softc
->flashdrv_probe
.flash_phys
,
1166 /* *********************************************************************
1167 * flashdrv_write(ctx,buffer)
1169 * Write data to the flash device. The flash device is
1170 * considered to be like a disk (you need to specify the offset).
1173 * ctx - device context
1174 * buffer - buffer descriptor
1177 * 0 if ok, else error code
1178 ********************************************************************* */
1180 static int flashdrv_write(cfe_devctx_t
*ctx
,iocb_buffer_t
*buffer
)
1182 flashdrv_t
*softc
= ctx
->dev_softc
;
1183 unsigned char *bptr
;
1188 bptr
= buffer
->buf_ptr
;
1189 blen
= buffer
->buf_length
;
1190 offset
= (int) buffer
->buf_offset
;
1192 if (!(softc
->flashdrv_unlocked
)) {
1193 if ((offset
+ blen
) > softc
->flashdrv_devsize
) {
1194 blen
= softc
->flashdrv_devsize
- offset
;
1198 res
= FLASHOP_WRITE_BLOCK(softc
,offset
,bptr
,blen
);
1200 buffer
->buf_retlen
= res
;
1203 return (res
== blen
) ? 0 : CFE_ERR_IOERR
;
1206 /* *********************************************************************
1207 * flashdrv_ioctl(ctx,buffer)
1209 * Handle special IOCTL functions for the flash. Flash devices
1210 * support NVRAM information, sector and chip erase, and a
1211 * special IOCTL for updating the running copy of CFE.
1214 * ctx - device context
1215 * buffer - descriptor for IOCTL parameters
1218 * 0 if ok else error
1219 ********************************************************************* */
1220 static int flashdrv_ioctl(cfe_devctx_t
*ctx
,iocb_buffer_t
*buffer
)
1222 flashdrv_t
*softc
= ctx
->dev_softc
;
1227 * If using flash to store environment, only the last sector
1228 * is used for environment stuff.
1231 switch ((int)buffer
->buf_ioctlcmd
) {
1232 case IOCTL_NVRAM_ERASE
:
1233 if (softc
->flashdrv_nvram_ok
== FALSE
) return CFE_ERR_UNSUPPORTED
;
1234 FLASHOP_ERASE_SECTOR(softc
,softc
->flashdrv_nvraminfo
.nvram_offset
);
1237 case IOCTL_NVRAM_GETINFO
:
1238 info
= (nvram_info_t
*) buffer
->buf_ptr
;
1239 if (buffer
->buf_length
!= sizeof(nvram_info_t
)) return CFE_ERR_INV_PARAM
;
1240 if (softc
->flashdrv_nvram_ok
== FALSE
) return CFE_ERR_UNSUPPORTED
;
1241 info
->nvram_offset
= softc
->flashdrv_nvraminfo
.nvram_offset
;
1242 info
->nvram_size
= softc
->flashdrv_nvraminfo
.nvram_size
;
1243 info
->nvram_eraseflg
= softc
->flashdrv_nvraminfo
.nvram_eraseflg
;
1244 buffer
->buf_retlen
= sizeof(nvram_info_t
);
1247 case IOCTL_FLASH_ERASE_SECTOR
:
1248 offset
= (int) buffer
->buf_offset
;
1249 if (!(softc
->flashdrv_unlocked
)) {
1250 if (offset
>= softc
->flashdrv_devsize
) return -1;
1252 FLASHOP_ERASE_SECTOR(softc
,offset
);
1255 case IOCTL_FLASH_ERASE_ALL
:
1256 offset
= (int) buffer
->buf_offset
;
1257 if (offset
!= 0) return -1;
1258 flash_erase_all(softc
);
1261 case IOCTL_FLASH_WRITE_ALL
:
1262 flash_writeall(softc
,buffer
);
1263 return -1; /* should not return */
1265 case IOCTL_FLASH_GETINFO
:
1266 memcpy(buffer
->buf_ptr
,&(softc
->flashdrv_info
),sizeof(flash_info_t
));
1269 case IOCTL_FLASH_GETSECTORS
:
1270 return flash_sector_query(softc
,(flash_sector_t
*) buffer
->buf_ptr
);
1273 case IOCTL_FLASH_ERASE_RANGE
:
1274 return flash_erase_range(softc
,(flash_range_t
*) buffer
->buf_ptr
);
1276 case IOCTL_NVRAM_UNLOCK
:
1277 softc
->flashdrv_unlocked
= TRUE
;
1288 /* *********************************************************************
1289 * flashdrv_close(ctx)
1291 * Close the flash device.
1294 * ctx - device context
1298 ********************************************************************* */
1299 static int flashdrv_close(cfe_devctx_t
*ctx
)
1301 /* flashdrv_t *softc = ctx->dev_softc; */