summaryrefslogtreecommitdiff
path: root/include/linux/mtd
diff options
context:
space:
mode:
authorThomas Gleixner <tglx@linutronix.de>2005-03-15 19:03:16 +0000
committerThomas Gleixner <tglx@mtd.linutronix.de>2005-05-23 12:53:05 +0200
commitc927cd3a226bed5cf063cdf04de13cef51144cef (patch)
treeebb14c72811e3d2d76bf8be82799334302600947 /include/linux/mtd
parentfb6bb52ddde0429b654ab6d4cb20fa016a1d5b0d (diff)
downloadlwn-c927cd3a226bed5cf063cdf04de13cef51144cef.tar.gz
lwn-c927cd3a226bed5cf063cdf04de13cef51144cef.zip
[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>
Diffstat (limited to 'include/linux/mtd')
-rw-r--r--include/linux/mtd/cfi.h65
1 files changed, 64 insertions, 1 deletions
diff --git a/include/linux/mtd/cfi.h b/include/linux/mtd/cfi.h
index 76255474a27c..66e0a32efbac 100644
--- a/include/linux/mtd/cfi.h
+++ b/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.
*