]> pilppa.org Git - linux-2.6-omap-h63xx.git/blobdiff - drivers/mtd/chips/cfi_util.c
Merge branches 'topic/fix/asoc', 'topic/fix/hda', 'topic/fix/misc' and 'topic/pci...
[linux-2.6-omap-h63xx.git] / drivers / mtd / chips / cfi_util.c
index 0cf183f01e493148a54ba24aa4da5c0a7e182465..34d40e25d312952b3cd2186465e17eff5a55d101 100644 (file)
@@ -6,15 +6,11 @@
  * Copyright (C) 2003 STMicroelectronics Limited
  *
  * This code is covered by the GPL.
- *
- * $Id: cfi_util.c,v 1.9 2005/07/20 21:01:14 tpoynor Exp $
- *
  */
 
 #include <linux/module.h>
 #include <linux/types.h>
 #include <linux/kernel.h>
-#include <linux/sched.h>
 #include <asm/io.h>
 #include <asm/byteorder.h>
 
 #include <linux/mtd/cfi.h>
 #include <linux/mtd/compatmac.h>
 
+int __xipram cfi_qry_present(struct map_info *map, __u32 base,
+                            struct cfi_private *cfi)
+{
+       int osf = cfi->interleave * cfi->device_type;   /* scale factor */
+       map_word val[3];
+       map_word qry[3];
+
+       qry[0] = cfi_build_cmd('Q', map, cfi);
+       qry[1] = cfi_build_cmd('R', map, cfi);
+       qry[2] = cfi_build_cmd('Y', map, cfi);
+
+       val[0] = map_read(map, base + osf*0x10);
+       val[1] = map_read(map, base + osf*0x11);
+       val[2] = map_read(map, base + osf*0x12);
+
+       if (!map_word_equal(map, qry[0], val[0]))
+               return 0;
+
+       if (!map_word_equal(map, qry[1], val[1]))
+               return 0;
+
+       if (!map_word_equal(map, qry[2], val[2]))
+               return 0;
+
+       return 1;       /* "QRY" found */
+}
+EXPORT_SYMBOL_GPL(cfi_qry_present);
+
+int __xipram cfi_qry_mode_on(uint32_t base, struct map_info *map,
+                            struct cfi_private *cfi)
+{
+       cfi_send_gen_cmd(0xF0, 0, base, map, cfi, cfi->device_type, NULL);
+       cfi_send_gen_cmd(0x98, 0x55, base, map, cfi, cfi->device_type, NULL);
+       if (cfi_qry_present(map, base, cfi))
+               return 1;
+       /* QRY not found probably we deal with some odd CFI chips */
+       /* Some revisions of some old Intel chips? */
+       cfi_send_gen_cmd(0xF0, 0, base, map, cfi, cfi->device_type, NULL);
+       cfi_send_gen_cmd(0xFF, 0, base, map, cfi, cfi->device_type, NULL);
+       cfi_send_gen_cmd(0x98, 0x55, base, map, cfi, cfi->device_type, NULL);
+       if (cfi_qry_present(map, base, cfi))
+               return 1;
+       /* ST M29DW chips */
+       cfi_send_gen_cmd(0xF0, 0, base, map, cfi, cfi->device_type, NULL);
+       cfi_send_gen_cmd(0x98, 0x555, base, map, cfi, cfi->device_type, NULL);
+       if (cfi_qry_present(map, base, cfi))
+               return 1;
+       /* QRY not found */
+       return 0;
+}
+EXPORT_SYMBOL_GPL(cfi_qry_mode_on);
+
+void __xipram cfi_qry_mode_off(uint32_t base, struct map_info *map,
+                              struct cfi_private *cfi)
+{
+       cfi_send_gen_cmd(0xF0, 0, base, map, cfi, cfi->device_type, NULL);
+       cfi_send_gen_cmd(0xFF, 0, base, map, cfi, cfi->device_type, NULL);
+}
+EXPORT_SYMBOL_GPL(cfi_qry_mode_off);
+
 struct cfi_extquery *
 __xipram cfi_read_pri(struct map_info *map, __u16 adr, __u16 size, const char* name)
 {
@@ -52,21 +108,19 @@ __xipram cfi_read_pri(struct map_info *map, __u16 adr, __u16 size, const char* n
 #endif
 
        /* Switch it into Query Mode */
-       cfi_send_gen_cmd(0x98, 0x55, base, map, cfi, cfi->device_type, NULL);
-
+       cfi_qry_mode_on(base, map, cfi);
        /* Read in the Extended Query Table */
        for (i=0; i<size; i++) {
-               ((unsigned char *)extp)[i] = 
+               ((unsigned char *)extp)[i] =
                        cfi_read_query(map, base+((adr+i)*ofs_factor));
        }
 
        /* Make sure it returns to read mode */
-       cfi_send_gen_cmd(0xf0, 0, base, map, cfi, cfi->device_type, NULL);
-       cfi_send_gen_cmd(0xff, 0, base, map, cfi, cfi->device_type, NULL);
+       cfi_qry_mode_off(base, map, cfi);
 
 #ifdef CONFIG_MTD_XIP
        (void) map_read(map, base);
-       asm volatile (".rep 8; nop; .endr");
+       xip_iprefetch();
        local_irq_enable();
 #endif
 
@@ -113,17 +167,17 @@ int cfi_varsize_frob(struct mtd_info *mtd, varsize_frob_t frob,
 
        i = 0;
 
-       /* Skip all erase regions which are ended before the start of 
+       /* Skip all erase regions which are ended before the start of
           the requested erase. Actually, to save on the calculations,
           we skip to the first erase region which starts after the
           start of the requested erase, and then go back one.
        */
-       
+
        while (i < mtd->numeraseregions && ofs >= regions[i].offset)
               i++;
        i--;
 
-       /* OK, now i is pointing at the erase region in which this 
+       /* OK, now i is pointing at the erase region in which this
           erase request starts. Check the start of the requested
           erase range is aligned with the erase size which is in
           effect here.
@@ -146,7 +200,7 @@ int cfi_varsize_frob(struct mtd_info *mtd, varsize_frob_t frob,
           the address actually falls
        */
        i--;
-       
+
        if ((ofs + len) & (regions[i].erasesize-1))
                return -EINVAL;
 
@@ -159,7 +213,7 @@ int cfi_varsize_frob(struct mtd_info *mtd, varsize_frob_t frob,
                int size = regions[i].erasesize;
 
                ret = (*frob)(map, &cfi->chips[chipnum], adr, size, thunk);
-               
+
                if (ret)
                        return ret;
 
@@ -173,7 +227,7 @@ int cfi_varsize_frob(struct mtd_info *mtd, varsize_frob_t frob,
                if (adr >> cfi->chipshift) {
                        adr = 0;
                        chipnum++;
-                       
+
                        if (chipnum >= cfi->numchips)
                        break;
                }