This is the mail archive of the ecos-discuss@sourceware.org mailing list for the eCos project.


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]
Other format: [Raw text]

Re: asymmetric block size in Strata P30/P33 flash


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

Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]