Gitweb:     
http://git.kernel.org/git/?p=linux/kernel/git/torvalds/linux-2.6.git;a=commit;h=0ecbc81adfcb9f15f86b05ff576b342ce81bbef8
Commit:     0ecbc81adfcb9f15f86b05ff576b342ce81bbef8
Parent:     8dc64fca75b631142f282047d7f6ae9e8af82543
Author:     Rodolfo Giometti <[EMAIL PROTECTED]>
AuthorDate: Mon Mar 26 21:45:43 2007 -0800
Committer:  David Woodhouse <[EMAIL PROTECTED]>
CommitDate: Mon Apr 2 14:12:23 2007 -0400

    [MTD] [NOR] Support for auto locking flash on power up
    
    Auto unlock sectors on resume for auto locking flash on power up.
    
    Signed-off-by: Rodolfo Giometti <[EMAIL PROTECTED]>
    Signed-off-by: Andrew Morton <[EMAIL PROTECTED]>
    Signed-off-by: David Woodhouse <[EMAIL PROTECTED]>
---
 drivers/mtd/chips/cfi_cmdset_0001.c |   93 +++++++++++++++++++++++++++++++++-
 include/linux/mtd/mtd.h             |    1 +
 2 files changed, 91 insertions(+), 3 deletions(-)

diff --git a/drivers/mtd/chips/cfi_cmdset_0001.c 
b/drivers/mtd/chips/cfi_cmdset_0001.c
index f334959..2f19fa7 100644
--- a/drivers/mtd/chips/cfi_cmdset_0001.c
+++ b/drivers/mtd/chips/cfi_cmdset_0001.c
@@ -15,6 +15,8 @@
  *     - optimized write buffer method
  * 02/05/2002  Christopher Hoover <[EMAIL PROTECTED]>/<[EMAIL PROTECTED]>
  *     - reworked lock/unlock/erase support for var size flash
+ * 21/03/2007   Rodolfo Giometti <[EMAIL PROTECTED]>
+ *     - auto unlock sectors on resume for auto locking flash on power up
  */
 
 #include <linux/module.h>
@@ -30,6 +32,7 @@
 #include <linux/delay.h>
 #include <linux/interrupt.h>
 #include <linux/reboot.h>
+#include <linux/bitmap.h>
 #include <linux/mtd/xip.h>
 #include <linux/mtd/map.h>
 #include <linux/mtd/mtd.h>
@@ -220,6 +223,15 @@ static void fixup_use_write_buffers(struct mtd_info *mtd, 
void *param)
        }
 }
 
+/*
+ * Some chips power-up with all sectors locked by default.
+ */
+static void fixup_use_powerup_lock(struct mtd_info *mtd, void *param)
+{
+       printk(KERN_INFO "Using auto-unlock on power-up/resume\n" );
+       mtd->flags |= MTD_STUPID_LOCK;
+}
+
 static struct cfi_fixup cfi_fixup_table[] = {
 #ifdef CMDSET0001_DISABLE_ERASE_SUSPEND_ON_WRITE
        { CFI_MFR_ANY, CFI_ID_ANY, fixup_intel_strataflash, NULL },
@@ -232,6 +244,7 @@ static struct cfi_fixup cfi_fixup_table[] = {
 #endif
        { CFI_MFR_ST, 0x00ba, /* M28W320CT */ fixup_st_m28w320ct, NULL },
        { CFI_MFR_ST, 0x00bb, /* M28W320CB */ fixup_st_m28w320cb, NULL },
+       { MANUFACTURER_INTEL, 0x891c,         fixup_use_powerup_lock, NULL, },
        { 0, 0, NULL, NULL }
 };
 
@@ -460,6 +473,7 @@ static struct mtd_info *cfi_intelext_setup(struct mtd_info 
*mtd)
                        
mtd->eraseregions[(j*cfi->cfiq->NumEraseRegions)+i].offset = (j*devsize)+offset;
                        
mtd->eraseregions[(j*cfi->cfiq->NumEraseRegions)+i].erasesize = ersize;
                        
mtd->eraseregions[(j*cfi->cfiq->NumEraseRegions)+i].numblocks = ernum;
+                       
mtd->eraseregions[(j*cfi->cfiq->NumEraseRegions)+i].lockmap = kmalloc(ernum / 8 
+ 1, GFP_KERNEL);
                }
                offset += (ersize * ernum);
        }
@@ -1825,8 +1839,7 @@ static void cfi_intelext_sync (struct mtd_info *mtd)
        }
 }
 
-#ifdef DEBUG_LOCK_BITS
-static int __xipram do_printlockstatus_oneblock(struct map_info *map,
+static int __xipram do_getlockstatus_oneblock(struct map_info *map,
                                                struct flchip *chip,
                                                unsigned long adr,
                                                int len, void *thunk)
@@ -1840,8 +1853,17 @@ static int __xipram do_printlockstatus_oneblock(struct 
map_info *map,
        chip->state = FL_JEDEC_QUERY;
        status = cfi_read_query(map, adr+(2*ofs_factor));
        xip_enable(map, chip, 0);
+       return status;
+}
+
+#ifdef DEBUG_LOCK_BITS
+static int __xipram do_printlockstatus_oneblock(struct map_info *map,
+                                               struct flchip *chip,
+                                               unsigned long adr,
+                                               int len, void *thunk)
+{
        printk(KERN_DEBUG "block status register for 0x%08lx is %x\n",
-              adr, status);
+              adr, do_getlockstatus_oneblock(map, chip, adr, len, thunk));
        return 0;
 }
 #endif
@@ -2216,14 +2238,45 @@ static int cfi_intelext_get_user_prot_info(struct 
mtd_info *mtd,
 
 #endif
 
+static void cfi_intelext_save_locks(struct mtd_info *mtd)
+{
+       struct mtd_erase_region_info *region;
+       int block, status, i;
+       unsigned long adr;
+       size_t len;
+
+       for (i = 0; i < mtd->numeraseregions; i++) {
+               region = &mtd->eraseregions[i];
+               if (!region->lockmap)
+                       continue;
+
+               for (block = 0; block < region->numblocks; block++){
+                       len = region->erasesize;
+                       adr = region->offset + block * len;
+
+                       status = cfi_varsize_frob(mtd,
+                                       do_getlockstatus_oneblock, adr, len, 0);
+                       if (status)
+                               set_bit(block, region->lockmap);
+                       else
+                               clear_bit(block, region->lockmap);
+               }
+       }
+}
+
 static int cfi_intelext_suspend(struct mtd_info *mtd)
 {
        struct map_info *map = mtd->priv;
        struct cfi_private *cfi = map->fldrv_priv;
+       struct cfi_pri_intelext *extp = cfi->cmdset_priv;
        int i;
        struct flchip *chip;
        int ret = 0;
 
+       if ((mtd->flags & MTD_STUPID_LOCK)
+           && extp && (extp->FeatureSupport & (1 << 5)))
+               cfi_intelext_save_locks(mtd);
+
        for (i=0; !ret && i<cfi->numchips; i++) {
                chip = &cfi->chips[i];
 
@@ -2285,10 +2338,33 @@ static int cfi_intelext_suspend(struct mtd_info *mtd)
        return ret;
 }
 
+static void cfi_intelext_restore_locks(struct mtd_info *mtd)
+{
+       struct mtd_erase_region_info *region;
+       int block, i;
+       unsigned long adr;
+       size_t len;
+
+       for (i = 0; i < mtd->numeraseregions; i++) {
+               region = &mtd->eraseregions[i];
+               if (!region->lockmap)
+                       continue;
+
+               for (block = 0; block < region->numblocks; block++) {
+                       len = region->erasesize;
+                       adr = region->offset + block * len;
+
+                       if (!test_bit(block, region->lockmap))
+                               cfi_intelext_unlock(mtd, adr, len);
+               }
+       }
+}
+
 static void cfi_intelext_resume(struct mtd_info *mtd)
 {
        struct map_info *map = mtd->priv;
        struct cfi_private *cfi = map->fldrv_priv;
+       struct cfi_pri_intelext *extp = cfi->cmdset_priv;
        int i;
        struct flchip *chip;
 
@@ -2307,6 +2383,10 @@ static void cfi_intelext_resume(struct mtd_info *mtd)
 
                spin_unlock(chip->mutex);
        }
+
+       if ((mtd->flags & MTD_STUPID_LOCK)
+           && extp && (extp->FeatureSupport & (1 << 5)))
+               cfi_intelext_restore_locks(mtd);
 }
 
 static int cfi_intelext_reset(struct mtd_info *mtd)
@@ -2347,12 +2427,19 @@ static void cfi_intelext_destroy(struct mtd_info *mtd)
 {
        struct map_info *map = mtd->priv;
        struct cfi_private *cfi = map->fldrv_priv;
+       struct mtd_erase_region_info *region;
+       int i;
        cfi_intelext_reset(mtd);
        unregister_reboot_notifier(&mtd->reboot_notifier);
        kfree(cfi->cmdset_priv);
        kfree(cfi->cfiq);
        kfree(cfi->chips[0].priv);
        kfree(cfi);
+       for (i = 0; i < mtd->numeraseregions; i++) {
+               region = &mtd->eraseregions[i];
+               if (region->lockmap)
+                       kfree(region->lockmap);
+       }
        kfree(mtd->eraseregions);
 }
 
diff --git a/include/linux/mtd/mtd.h b/include/linux/mtd/mtd.h
index 3d956c3..45d482c 100644
--- a/include/linux/mtd/mtd.h
+++ b/include/linux/mtd/mtd.h
@@ -53,6 +53,7 @@ struct mtd_erase_region_info {
        u_int32_t offset;                       /* At which this region starts, 
from the beginning of the MTD */
        u_int32_t erasesize;            /* For this region */
        u_int32_t numblocks;            /* Number of blocks of erasesize in 
this region */
+       unsigned long *lockmap;         /* If keeping bitmap of locks */
 };
 
 /*
-
To unsubscribe from this list: send the line "unsubscribe git-commits-head" in
the body of a message to [EMAIL PROTECTED]
More majordomo info at  http://vger.kernel.org/majordomo-info.html

Reply via email to