CFI JEDEC probing

Stuart Menefy Stuart.Menefy at st.com
Mon Jun 11 12:42:18 EDT 2001


Folks

I think I've come across a limitation in the CFI JEDEC proving code.

I'm working with four ST M29W160DT devices, mapped as follows:

x               data bus
x
x           D31    D16   D15     D0
x            |      |     |      |
x            |      |     |      |
x        0 +----------+ +----------+
x          |D15     D0| |D15     D0|
x          |          | |          |
x   3fffff |          | |          |
x          +----------+ +----------+
x            |      |     |      |
x   400000 +----------+ +----------+
x          |D15     D0| |D15     D0|
x          |          | |          |
x   7fffff |          | |          |
x          +----------+ +----------+
x

Humm, not sure if that makes things clearer or not! What I'm trying to
say is, four 16 bit devices, on a 32bit data bus, with an interleave
of 2, mapped into contiguous memory locations.

When probing for the first two devices, the code in cfi_jedec_lookup()
only appears to only be able to handle an interleave of 1.

I've added code which works for me and generates the appropriate
device and manufacturer ID's, based on the bus width and interleave,
for comparison with the values read back from the Flash devices.
A copy of the code is attached. Do you think this is generally useful,
or have I missed something obvious?

Thanks

Stuart
-------------- next part --------------
Index: drivers/mtd/chips/cfi_jedec.c
===================================================================
RCS file: /home/cvs/mtd/drivers/mtd/chips/cfi_jedec.c,v
retrieving revision 1.5
diff -c -r1.5 cfi_jedec.c
*** drivers/mtd/chips/cfi_jedec.c	2001/06/02 14:52:23	1.5
--- drivers/mtd/chips/cfi_jedec.c	2001/06/11 16:39:37
***************
*** 246,261 ****
  	} 
  };
  
! int cfi_jedec_lookup(int index, int mfr_id, int dev_id)
  {
    	if (index>=0){
! 		if (jedec_table[index].mfr_id == mfr_id &&
! 		    jedec_table[index].dev_id == dev_id) return index;
    	}
    	else{
  		for (index=0; jedec_table[index].mfr_id; index++){
! 		    if (jedec_table[index].mfr_id == mfr_id &&
! 		        jedec_table[index].dev_id == dev_id) return index;
  		}
    	}
  	return -1;
--- 246,304 ----
  	} 
  };
  
! /*
!  * Transforms the ID for the given geometry (bus width & interleave).
!  * This is a slightly modified version of cfi_build_cmd, in that it copes
!  * with truncating down a 16 bit ID to 8 bits when required.
!  */
! static __u32 cfi_build_id(__u16 id, struct map_info *map, int interleave)
  {
+ 	__u32 val = 0;
+ 
+ 	if (cfi_buswidth_is_1()) {
+ 		/* 1 x8 device */
+ 		val = id & 0xff;
+ 	} else if (cfi_buswidth_is_2()) {
+ 		if (cfi_interleave_is_1()) {
+ 			/* 1 x16 device in x16 mode */
+ 			val = cpu_to_cfi16(id);
+ 		} else if (cfi_interleave_is_2()) {
+ 			/* 2 (x8, x16 or x32) devices in x8 mode */
+ 			id &= 0xff;
+ 			val = cpu_to_cfi16((id << 8) | id);
+ 		}
+ 	} else if (cfi_buswidth_is_4()) {
+ 		if (cfi_interleave_is_1()) {
+ 			/* 1 x32 device in x32 mode */
+ 			val = cpu_to_cfi32(id);
+ 		} else if (cfi_interleave_is_2()) {
+ 			/* 2 x16 device in x16 mode */
+ 			val = cpu_to_cfi32((id << 16) | id);
+ 		} else if (cfi_interleave_is_4()) {
+ 			/* 4 (x8, x16 or x32) devices in x8 mode */
+ 			id &= 0xff;
+ 			val = (id << 16) | id;
+ 			val = cpu_to_cfi32((val << 8) | val);
+ 		}
+ 	}
+ 	return val;
+ }
+ 
+ int cfi_jedec_lookup(int index, int mfr_id, int dev_id, struct map_info *map, int interleave)
+ {
+ 	printk("buswidth %d, interleave %d\n", map->buswidth, interleave);
    	if (index>=0){
! 		const __u32 dev_mfr_id = cfi_build_id(jedec_table[index].mfr_id, map, interleave);
! 		const __u32 dev_dev_id = cfi_build_id(jedec_table[index].dev_id, map, interleave);
! 		if (dev_mfr_id == mfr_id && dev_dev_id == dev_id) return index;
    	}
    	else{
  		for (index=0; jedec_table[index].mfr_id; index++){
! 		    const __u32 dev_mfr_id = cfi_build_id(jedec_table[index].mfr_id, map, interleave);
! 		    const __u32 dev_dev_id = cfi_build_id(jedec_table[index].dev_id, map, interleave);
! 		    printk("Comp %08x %08x and %08x %08x\n",
! 			   dev_mfr_id, mfr_id, dev_dev_id, dev_id);
! 		    if (dev_mfr_id == mfr_id && dev_dev_id == dev_id) return index;
  		}
    	}
  	return -1;


More information about the linux-mtd mailing list