aboutsummaryrefslogtreecommitdiffstats
path: root/recipes-kernel/linux/linux-yocto-3.10/patches/patches-mtd/collie-match-cfi-qry.patch
blob: e3fbf2e997caf5c09165412c4b2a197a1a7e53f9 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
diff --git a/drivers/mtd/chips/cfi_util.c b/drivers/mtd/chips/cfi_util.c
index f992418..7139d028 100644
--- a/drivers/mtd/chips/cfi_util.c
+++ b/drivers/mtd/chips/cfi_util.c
@@ -29,6 +29,7 @@
 	int osf = cfi->interleave * cfi->device_type;	/* scale factor */
 	map_word val[3];
 	map_word qry[3];
+	unsigned long mask = (1 << (cfi->device_type * 8)) - 1;
 
 	qry[0] = cfi_build_cmd('Q', map, cfi);
 	qry[1] = cfi_build_cmd('R', map, cfi);
@@ -38,6 +39,21 @@
 	val[1] = map_read(map, base + osf*0x11);
 	val[2] = map_read(map, base + osf*0x12);
 
+	/* Apparently only one of the 2 interleaved LH28F640BF 16 bit chips on
+	 * a 32 bit wide bus is answering to the CFI Query.
+	 * Using the expected map bankwidth=4 and chip interleave=2 we get wrong
+	 * readings like 0xffff0051 instead of 0x00510051 etc.
+	 * We take the valid bytes and recreate the expected answer as workaround.
+	 */
+	if (((val[0].x[0] >> (cfi->device_type * 8)) == mask) &&
+	    ((val[1].x[0] >> (cfi->device_type * 8)) == mask) &&
+	    ((val[2].x[0] >> (cfi->device_type * 8)) == mask))
+	{
+	val[0].x[0] = (val[0].x[0] & mask) + ((val[0].x[0] & mask) << (cfi->device_type * 8));
+	val[1].x[0] = (val[1].x[0] & mask) + ((val[1].x[0] & mask) << (cfi->device_type * 8));
+	val[2].x[0] = (val[2].x[0] & mask) + ((val[2].x[0] & mask) << (cfi->device_type * 8));
+	}
+
 	if (!map_word_equal(map, qry[0], val[0]))
 		return 0;