This is the mail archive of the
ecos-discuss@sourceware.org
mailing list for the eCos project.
Re: asymmetric block size in Strata P30/P33 flash
- From: Mark Salter <msalter at redhat dot com>
- To: Jacob Avraham <jacob at imagine-com dot com>
- Cc: ecos-discuss at ecos dot sourceware dot org
- Date: Mon, 30 Apr 2007 15:49:05 -0400
- Subject: Re: [ECOS] asymmetric block size in Strata P30/P33 flash
- References: <395D1D85A454F14CB58638B1AC60D7093EC130@server.imagine-com.local>
On Mon, 2007-04-30 at 16:43 +0300, Jacob Avraham wrote:
> Hi,
>
> I'm about to bringup an IXP420-based board with a Strata P33 flash on
> it.
> I'm using Redboot 2.02.
> I wonder if Redboot can handle the fact that this chip has 2 erase block
> sizes:
> 128k and 32k. I saw in the code that there is one variable for the block
> size,
> so it makes me suspicious...
>
Here is a patch for P30 support taken against the cvs tree. Haven't had
a chance to fully test it with the cvs head and check it in...
--Mark
Index: devs/flash/intel/strata/current/src/flash_erase_block.c
===================================================================
RCS file: /cvs/ecos/ecos/packages/devs/flash/intel/strata/current/src/flash_erase_block.c,v
retrieving revision 1.7
diff -u -p -5 -r1.7 flash_erase_block.c
--- devs/flash/intel/strata/current/src/flash_erase_block.c 11 Sep 2003 13:21:39 -0000 1.7
+++ devs/flash/intel/strata/current/src/flash_erase_block.c 30 Apr 2007 19:39:25 -0000
@@ -60,56 +60,70 @@ int flash_erase_block(volatile flash_t *
int flash_erase_block(volatile flash_t *block, unsigned int block_size)
{
volatile flash_t *ROM;
flash_t stat = 0;
int timeout = 50000;
- int len, block_len, erase_block_size;
- volatile flash_t *eb;
+ int len, block_len;
+ volatile flash_t *eb, *start;
+#ifdef CYGOPT_FLASH_IS_BOOTBLOCK
+ int erase_block_size;
+#endif
// Get base address and map addresses to virtual addresses
ROM = FLASH_P2V(CYGNUM_FLASH_BASE_MASK & (unsigned int)block);
- eb = block = FLASH_P2V(block);
+ start = FLASH_P2V(block);
block_len = block_size;
#ifdef CYGOPT_FLASH_IS_BOOTBLOCK
#define BLOCKSIZE (0x10000*CYGNUM_FLASH_DEVICES)
#define ERASE_BLOCKSIZE (0x2000*CYGNUM_FLASH_DEVICES)
- if ((eb - ROM) < BLOCKSIZE/(sizeof eb[0])) {
+ if ((start - ROM) < BLOCKSIZE/(sizeof eb[0])) {
erase_block_size = ERASE_BLOCKSIZE;
} else {
erase_block_size = block_size;
}
-#else
- erase_block_size = block_size;
#endif
// Clear any error conditions
ROM[0] = FLASH_Clear_Status;
// Erase block
while (block_len > 0) {
+
+ eb = FLASH_P2V(block);
+
eb[0] = FLASH_Block_Erase;
eb[0] = FLASH_Confirm;
timeout = 5000000;
while(((stat = eb[0]) & FLASH_Status_Ready) != FLASH_Status_Ready) {
if (--timeout == 0) break;
}
+#ifdef CYGOPT_FLASH_IS_BOOTBLOCK
block_len -= erase_block_size;
- eb = FLASH_P2V((unsigned int)eb + erase_block_size);
+ block += (erase_block_size/sizeof(*block);
+#else
+ if (block < __strata_info.base2) {
+ block_len -= __strata_info.blocksize1;
+ block += __strata_info.blocksize1/sizeof(*block);
+ } else {
+ block_len -= __strata_info.blocksize2;
+ block += __strata_info.blocksize2/sizeof(*block);
+ }
+#endif
}
// Restore ROM to "normal" mode
ROM[0] = FLASH_Reset;
// If an error was reported, see if the block erased anyway
if (stat & FLASH_ErrorMask ) {
len = block_size;
while (len > 0) {
- if (*block++ != FLASH_BlankValue ) break;
- len -= sizeof(*block);
+ if (*start++ != FLASH_BlankValue ) break;
+ len -= sizeof(*start);
}
if (len == 0) stat = 0;
}
return stat;
Index: devs/flash/intel/strata/current/src/flash_lock_block.c
===================================================================
RCS file: /cvs/ecos/ecos/packages/devs/flash/intel/strata/current/src/flash_lock_block.c,v
retrieving revision 1.5
diff -u -p -5 -r1.5 flash_lock_block.c
--- devs/flash/intel/strata/current/src/flash_lock_block.c 10 Sep 2003 20:52:53 -0000 1.5
+++ devs/flash/intel/strata/current/src/flash_lock_block.c 30 Apr 2007 19:39:25 -0000
@@ -57,27 +57,48 @@ int
flash_lock_block(volatile flash_t *block)
__attribute__ ((section (".2ram.flash_lock_block")));
int
flash_lock_block(volatile flash_t *block)
{
- volatile flash_t *ROM;
+ volatile flash_t *ROM, *end, *b;
flash_t stat;
- int timeout = 5000000;
+ int timeout;
// Get base address and map addresses to virtual addresses
ROM = FLASH_P2V(CYGNUM_FLASH_BASE_MASK & (unsigned int)block);
block = FLASH_P2V(block);
- // Clear any error conditions
- ROM[0] = FLASH_Clear_Status;
+#ifdef CYGOPT_FLASH_IS_BOOTBLOCK
+ end = block;
+#else
+ end = block + (__strata_info.logical_blocksize/sizeof(*block)) - 1;
+#endif
- // Set lock bit
- block[0] = FLASH_Set_Lock;
- block[0] = FLASH_Set_Lock_Confirm; // Confirmation
- while(((stat = ROM[0]) & FLASH_Status_Ready) != FLASH_Status_Ready) {
- if (--timeout == 0) break;
- }
+ do {
+ timeout = 5000000;
+
+ // Get base address and map addresses to virtual addresses
+ b = FLASH_P2V(block);
+
+ // Clear any error conditions
+ ROM[0] = FLASH_Clear_Status;
+
+ // Set lock bit
+ b[0] = FLASH_Set_Lock;
+ b[0] = FLASH_Set_Lock_Confirm; // Confirmation
+ while(((stat = ROM[0]) & FLASH_Status_Ready) != FLASH_Status_Ready) {
+ if (--timeout == 0) break;
+ }
+
+#ifndef CYGOPT_FLASH_IS_BOOTBLOCK
+ if (block < __strata_info.base2)
+ block += __strata_info.blocksize1/sizeof(*block);
+ else
+ block += __strata_info.blocksize2/sizeof(*block);
+#endif
+
+ } while (timeout && block < end);
// Restore ROM to "normal" mode
ROM[0] = FLASH_Reset;
return stat;
Index: devs/flash/intel/strata/current/src/flash_unlock_block.c
===================================================================
RCS file: /cvs/ecos/ecos/packages/devs/flash/intel/strata/current/src/flash_unlock_block.c,v
retrieving revision 1.8
diff -u -p -5 -r1.8 flash_unlock_block.c
--- devs/flash/intel/strata/current/src/flash_unlock_block.c 21 Aug 2004 08:37:48 -0000 1.8
+++ devs/flash/intel/strata/current/src/flash_unlock_block.c 30 Apr 2007 19:39:25 -0000
@@ -74,27 +74,47 @@ flash_unlock_block(volatile flash_t *blo
int timeout = 5000000;
#ifndef CYGOPT_FLASH_IS_SYNCHRONOUS
int i;
volatile flash_t *bp, *bpv;
unsigned char is_locked[CYGNUM_DEVS_FLASH_STRATA_MAX_BLOCKS];
+#else
+ volatile flash_t *end, *b;
#endif
// Get base address and map addresses to virtual addresses
ROM = FLASH_P2V( CYGNUM_FLASH_BASE_MASK & (unsigned int)block );
+
+#ifdef CYGOPT_FLASH_IS_SYNCHRONOUS
+ end = block + (block_size/sizeof(*block)) - 1;
+
+ // Clear lock bit[s]
+ do {
+ timeout = 5000000;
+
+ b = FLASH_P2V(block);
+
+ // Clear any error conditions
+ ROM[0] = FLASH_Clear_Status;
+
+ b[0] = FLASH_Clear_Locks;
+ b[0] = FLASH_Clear_Locks_Confirm; // Confirmation
+ while(((stat = ROM[0]) & FLASH_Status_Ready) != FLASH_Status_Ready) {
+ if (--timeout == 0) break;
+ }
+
+ if (block < __strata_info.base2)
+ block += __strata_info.blocksize1/sizeof(*block);
+ else
+ block += __strata_info.blocksize2/sizeof(*block);
+
+ } while (timeout && (block < end));
+#else
block = FLASH_P2V(block);
// Clear any error conditions
ROM[0] = FLASH_Clear_Status;
-#ifdef CYGOPT_FLASH_IS_SYNCHRONOUS
- // Clear lock bit
- block[0] = FLASH_Clear_Locks;
- block[0] = FLASH_Clear_Locks_Confirm; // Confirmation
- while(((stat = ROM[0]) & FLASH_Status_Ready) != FLASH_Status_Ready) {
- if (--timeout == 0) break;
- }
-#else
// Get current block lock state. This needs to access each block on
// the device so currently locked blocks can be re-locked.
bp = ROM;
for (i = 0; i < blocks; i++) {
bpv = FLASH_P2V( bp );
Index: devs/flash/intel/strata/current/src/strata.c
===================================================================
RCS file: /cvs/ecos/ecos/packages/devs/flash/intel/strata/current/src/strata.c,v
retrieving revision 1.9
diff -u -p -5 -r1.9 strata.c
--- devs/flash/intel/strata/current/src/strata.c 26 Jan 2004 23:59:10 -0000 1.9
+++ devs/flash/intel/strata/current/src/strata.c 30 Apr 2007 19:39:25 -0000
@@ -64,16 +64,22 @@
extern void diag_dump_buf(void *buf, CYG_ADDRWORD len);
extern int strncmp(const char *s1, const char *s2, size_t len);
extern void *memcpy( void *, const void *, size_t );
+#ifndef CYGOPT_FLASH_IS_BOOTBLOCK
+struct FLASH_info __strata_info;
+#endif
+
int
flash_hwr_init(void)
{
struct FLASH_query data, *qp;
int num_regions, region_size, buffer_size;
+ __strata_info.base1 = (void *)CYGNUM_FLASH_BASE;
+
flash_dev_query(&data);
qp = &data;
if ( ((qp->manuf_code == FLASH_Intel_code) ||
(qp->manuf_code == FLASH_STMicro_code))
#ifdef CYGOPT_FLASH_IS_BOOTBLOCK
@@ -105,12 +111,45 @@ flash_hwr_init(void)
num_regions /= 8; // to bytes
num_regions /= BLOCKSIZE; // to blocks
buffer_size = 0;
#else // CYGOPT_FLASH_IS_BOOTBLOCK
&& (strncmp(qp->id, "QRY", 3) == 0)) {
- num_regions = _si(qp->num_regions)+1;
- region_size = _si(qp->region_size)*256;
+
+ __strata_info.num_regions = qp->erase_regions;
+ __strata_info.base1 = (void *)CYGNUM_FLASH_BASE;
+
+ num_regions = _si(qp->num_blocks_1)+1;
+ region_size = _si(qp->block_size_1)*256;
+
+ __strata_info.blocksize1 = region_size * CYGNUM_FLASH_DEVICES;
+ __strata_info.base2 = __strata_info.base1 + (region_size*num_regions);
+
+ if (__strata_info.num_regions == 2) {
+ unsigned int nblocks2, size_ratio;
+
+ __strata_info.blocksize2 = _si(qp->block_size_2)*256*CYGNUM_FLASH_DEVICES;
+ nblocks2 = _si(qp->num_blocks_2)+1;
+
+ if (__strata_info.blocksize2 <= __strata_info.blocksize2) {
+ // small blocks at top
+ size_ratio = __strata_info.blocksize1 / __strata_info.blocksize2;
+ num_regions += (nblocks2 / size_ratio);
+ } else {
+ // small blocks at bottom
+ size_ratio = __strata_info.blocksize2 / __strata_info.blocksize1;
+ num_regions /= size_ratio;
+ num_regions += nblocks2;
+ region_size = __strata_info.blocksize2;
+ }
+ } else if (__strata_info.num_regions != 1) {
+ (*flash_info.pf)("\nFLASH: Can't handle %d regions!\n",
+ __strata_info.num_regions);
+ return FLASH_ERR_HWR;
+ }
+
+ __strata_info.logical_blocksize = region_size * CYGNUM_FLASH_DEVICES;
+
if (_si(qp->buffer_size)) {
buffer_size = CYGNUM_FLASH_DEVICES << _si(qp->buffer_size);
} else {
buffer_size = 0;
}
Index: devs/flash/intel/strata/current/src/strata.h
===================================================================
RCS file: /cvs/ecos/ecos/packages/devs/flash/intel/strata/current/src/strata.h,v
retrieving revision 1.6
diff -u -p -5 -r1.6 strata.h
--- devs/flash/intel/strata/current/src/strata.h 26 Jan 2004 23:59:10 -0000 1.6
+++ devs/flash/intel/strata/current/src/strata.h 30 Apr 2007 19:39:25 -0000
@@ -69,14 +69,14 @@
// 28FxxxK3 - Synchronous StrataFlash - yes yes yes
//
// These options are controlled by defining or not, in that include file,
// these symbols (not CDL options, just symbols - though they could be CDL
// in future)
-// CYGOPT_FLASH_IS_BOOTBLOCK - for xxxB3 devices.
-// CYGOPT_FLASH_IS_NOT_ADVANCED - for xxxC3 devices.
-// CYGOPT_FLASH_IS_SYNCHRONOUS - for xxxK3 devices.
-// none of the above - for xxxJ3 devices.
+// CYGOPT_FLASH_IS_BOOTBLOCK - for xxxB3 devices.
+// CYGOPT_FLASH_IS_NOT_ADVANCED - for xxxC3 devices.
+// CYGOPT_FLASH_IS_SYNCHRONOUS - for xxxK3, xxxP30 devices.
+// none of the above - for xxxJ3 devices.
// (Advanced seems to be usual these days hence the sense of that opt)
//
// Other properties are controlled by these symbols:
// CYGNUM_FLASH_DEVICES number of devices across the databus
// CYGNUM_FLASH_WIDTH number of bits in each device
@@ -166,13 +166,27 @@ struct FLASH_query {
unsigned char id[3]; // Q R Y
unsigned char _unused1[20];
unsigned char device_size;
unsigned char device_interface[2];
unsigned char buffer_size[2];
- unsigned char is_block_oriented;
- unsigned char num_regions[2];
- unsigned char region_size[2];
+ unsigned char erase_regions;
+ unsigned char num_blocks_1[2];
+ unsigned char block_size_1[2];
+ unsigned char num_blocks_2[2];
+ unsigned char block_size_2[2];
};
+
+struct FLASH_info {
+ int num_regions;
+ unsigned int logical_blocksize;
+ void *base1;
+ unsigned int blocksize1;
+ void *base2;
+ unsigned int blocksize2;
+};
+
+extern struct FLASH_info __strata_info;
+
#endif // CYGONCE_DEVS_FLASH_INTEL_STRATA_FLASH_H
// ------------------------------------------------------------------------
// EOF strata.h
--
Before posting, please read the FAQ: http://ecos.sourceware.org/fom/ecos
and search the list archive: http://ecos.sourceware.org/ml/ecos-discuss