x86: merge the TSC cpu-freq code
[safe/jmp/linux-2.6] / include / linux / mtd / cfi.h
index e6b6a1c..b0ddf4b 100644 (file)
@@ -1,14 +1,12 @@
 
-/* Common Flash Interface structures 
+/* Common Flash Interface structures
  * See http://support.intel.com/design/flash/technote/index.htm
- * $Id: cfi.h,v 1.54 2005/06/06 23:04:36 tpoynor Exp $
+ * $Id: cfi.h,v 1.57 2005/11/15 23:28:17 tpoynor Exp $
  */
 
 #ifndef __MTD_CFI_H__
 #define __MTD_CFI_H__
 
-#include <linux/config.h>
-#include <linux/version.h>
 #include <linux/delay.h>
 #include <linux/types.h>
 #include <linux/interrupt.h>
 #define cfi_interleave_is_8(cfi) (0)
 #endif
 
+#ifndef cfi_interleave
+#warning No CONFIG_MTD_CFI_Ix selected. No NOR chip support can work.
+static inline int cfi_interleave(void *cfi)
+{
+       BUG();
+       return 0;
+}
+#endif
+
 static inline int cfi_interleave_supported(int i)
 {
        switch (i) {
@@ -82,8 +89,8 @@ static inline int cfi_interleave_supported(int i)
 }
 
 
-/* NB: these values must represents the number of bytes needed to meet the 
- *     device type (x8, x16, x32).  Eg. a 32 bit device is 4 x 8 bytes. 
+/* NB: these values must represents the number of bytes needed to meet the
+ *     device type (x8, x16, x32).  Eg. a 32 bit device is 4 x 8 bytes.
  *     These numbers are used in calculations.
  */
 #define CFI_DEVICETYPE_X8  (8 / 8)
@@ -91,6 +98,18 @@ static inline int cfi_interleave_supported(int i)
 #define CFI_DEVICETYPE_X32 (32 / 8)
 #define CFI_DEVICETYPE_X64 (64 / 8)
 
+
+/* Device Interface Code Assignments from the "Common Flash Memory Interface
+ * Publication 100" dated December 1, 2001.
+ */
+#define CFI_INTERFACE_X8_ASYNC         0x0000
+#define CFI_INTERFACE_X16_ASYNC                0x0001
+#define CFI_INTERFACE_X8_BY_X16_ASYNC  0x0002
+#define CFI_INTERFACE_X32_ASYNC                0x0003
+#define CFI_INTERFACE_X16_BY_X32_ASYNC 0x0005
+#define CFI_INTERFACE_NOT_ALLOWED      0xffff
+
+
 /* NB: We keep these structures in memory in HOST byteorder, except
  * where individually noted.
  */
@@ -173,6 +192,15 @@ struct cfi_intelext_regioninfo {
        struct cfi_intelext_blockinfo BlockTypes[1];
 } __attribute__((packed));
 
+struct cfi_intelext_programming_regioninfo {
+       uint8_t  ProgRegShift;
+       uint8_t  Reserved1;
+       uint8_t  ControlValid;
+       uint8_t  Reserved2;
+       uint8_t  ControlInvalid;
+       uint8_t  Reserved3;
+} __attribute__((packed));
+
 /* Vendor-Specific PRI for AMD/Fujitsu Extended Command Set (0x0002) */
 
 struct cfi_pri_amdstd {
@@ -192,6 +220,18 @@ struct cfi_pri_amdstd {
        uint8_t  TopBottom;
 } __attribute__((packed));
 
+/* Vendor-Specific PRI for Atmel chips (command set 0x0002) */
+
+struct cfi_pri_atmel {
+       uint8_t pri[3];
+       uint8_t MajorVersion;
+       uint8_t MinorVersion;
+       uint8_t Features;
+       uint8_t BottomBoot;
+       uint8_t BurstMode;
+       uint8_t PageMode;
+} __attribute__((packed));
+
 struct cfi_pri_query {
        uint8_t  NumFields;
        uint32_t ProtField[1]; /* Not host ordered */
@@ -250,7 +290,7 @@ static inline uint32_t cfi_build_cmd_addr(uint32_t cmd_ofs, int interleave, int
 /*
  * Transforms the CFI command for the given geometry (bus width & interleave).
  * It looks too long to be inline, but in the common case it should almost all
- * get optimised away. 
+ * get optimised away.
  */
 static inline map_word cfi_build_cmd(u_long cmd, struct map_info *map, struct cfi_private *cfi)
 {
@@ -259,7 +299,7 @@ static inline map_word cfi_build_cmd(u_long cmd, struct map_info *map, struct cf
        unsigned long onecmd;
        int i;
 
-       /* We do it this way to give the compiler a fighting chance 
+       /* 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 */
@@ -270,7 +310,7 @@ static inline map_word cfi_build_cmd(u_long cmd, struct map_info *map, struct cf
                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);
 
@@ -289,7 +329,7 @@ static inline map_word cfi_build_cmd(u_long cmd, struct map_info *map, struct cf
                break;
        }
 
-       /* Now replicate it across the size of an unsigned long, or 
+       /* Now replicate it across the size of an unsigned long, or
           just to the bus width as appropriate */
        switch (chips_per_word) {
        default: BUG();
@@ -305,7 +345,7 @@ static inline map_word cfi_build_cmd(u_long cmd, struct map_info *map, struct cf
                ;
        }
 
-       /* And finally, for the multi-word case, replicate it 
+       /* And finally, for the multi-word case, replicate it
           in all words in the structure */
        for (i=0; i < words_per_bus; i++) {
                val.x[i] = onecmd;
@@ -316,14 +356,14 @@ 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, 
+static inline unsigned long 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 
+       /* 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 */
@@ -334,7 +374,7 @@ static inline unsigned char cfi_merge_status(map_word val, struct map_info *map,
                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);
 
@@ -418,6 +458,22 @@ static inline uint8_t cfi_read_query(struct map_info *map, uint32_t addr)
        }
 }
 
+static inline uint16_t cfi_read_query16(struct map_info *map, uint32_t addr)
+{
+       map_word val = map_read(map, addr);
+
+       if (map_bankwidth_is_1(map)) {
+               return val.x[0] & 0xff;
+       } else if (map_bankwidth_is_2(map)) {
+               return cfi16_to_cpu(val.x[0]);
+       } else {
+               /* No point in a 64-bit byteswap since that would just be
+                  swapping the responses from different chips, and we are
+                  only interested in one chip (a representative sample) */
+               return cfi32_to_cpu(val.x[0]);
+       }
+}
+
 static inline void cfi_udelay(int us)
 {
        if (us >= 1000) {
@@ -441,6 +497,7 @@ struct cfi_fixup {
 #define CFI_ID_ANY  0xffff
 
 #define CFI_MFR_AMD 0x0001
+#define CFI_MFR_ATMEL 0x001F
 #define CFI_MFR_ST  0x0020     /* STMicroelectronics */
 
 void cfi_fixup(struct mtd_info *mtd, struct cfi_fixup* fixups);