瀏覽代碼

[MTD] Add the reverse operation of cfi_build_cmd()

This is necessary to fix the broken status check in cfi_cmdset_0001

Signed-off-by: Thomas Gleixner <tglx@linutronix.de>
Thomas Gleixner 20 年之前
父節點
當前提交
c927cd3a22
共有 1 個文件被更改,包括 64 次插入1 次删除
  1. 64 1
      include/linux/mtd/cfi.h

+ 64 - 1
include/linux/mtd/cfi.h

@@ -1,7 +1,7 @@
 
 /* Common Flash Interface structures 
  * See http://support.intel.com/design/flash/technote/index.htm
- * $Id: cfi.h,v 1.52 2005/02/08 17:11:15 nico Exp $
+ * $Id: cfi.h,v 1.53 2005/03/15 19:03:13 gleixner Exp $
  */
 
 #ifndef __MTD_CFI_H__
@@ -315,6 +315,69 @@ static inline map_word cfi_build_cmd(u_long cmd, struct map_info *map, struct cf
 }
 #define CMD(x)  cfi_build_cmd((x), map, cfi)
 
+
+static inline unsigned char cfi_merge_status(map_word val, struct map_info *map, 
+					   struct cfi_private *cfi)
+{
+	int wordwidth, words_per_bus, chip_mode, chips_per_word;
+	unsigned long onestat, res = 0;
+	int i;
+
+	/* We do it this way to give the compiler a fighting chance 
+	   of optimising away all the crap for 'bankwidth' larger than
+	   an unsigned long, in the common case where that support is
+	   disabled */
+	if (map_bankwidth_is_large(map)) {
+		wordwidth = sizeof(unsigned long);
+		words_per_bus = (map_bankwidth(map)) / wordwidth; // i.e. normally 1
+	} else {
+		wordwidth = map_bankwidth(map);
+		words_per_bus = 1;
+	}
+	
+	chip_mode = map_bankwidth(map) / cfi_interleave(cfi);
+	chips_per_word = wordwidth * cfi_interleave(cfi) / map_bankwidth(map);
+
+	onestat = val.x[0];
+	/* Or all status words together */
+	for (i=1; i < words_per_bus; i++) {
+		onestat |= val.x[i];
+	}
+
+	res = onestat;
+	switch(chips_per_word) {
+	default: BUG();
+#if BITS_PER_LONG >= 64
+	case 8:
+		res |= (onestat >> (chip_mode * 32));
+#endif
+	case 4:
+		res |= (onestat >> (chip_mode * 16));
+	case 2:
+		res |= (onestat >> (chip_mode * 8));
+	case 1:
+		;
+	}
+
+	/* Last, determine what the bit-pattern should be for a single
+	   device, according to chip mode and endianness... */
+	switch (chip_mode) {
+	case 1:
+		break;
+	case 2:
+		res = cfi16_to_cpu(res);
+		break;
+	case 4:
+		res = cfi32_to_cpu(res);
+		break;
+	default: BUG();
+	}
+	return res;
+}
+
+#define MERGESTATUS(x) cfi_merge_status((x), map, cfi)
+
+
 /*
  * Sends a CFI command to a bank of flash for the given geometry.
  *