Skip to content

Commit

Permalink
[MTD] [NOR] Support for auto locking flash on power up
Browse files Browse the repository at this point in the history
Auto unlock sectors on resume for auto locking flash on power up.

Signed-off-by: Rodolfo Giometti <giometti@enneenne.com>
Signed-off-by: Andrew Morton <akpm@linux-foundation.org>
Signed-off-by: David Woodhouse <dwmw2@infradead.org>
  • Loading branch information
Rodolfo Giometti authored and David Woodhouse committed Apr 2, 2007
1 parent 8dc64fc commit 0ecbc81
Show file tree
Hide file tree
Showing 2 changed files with 91 additions and 3 deletions.
93 changes: 90 additions & 3 deletions drivers/mtd/chips/cfi_cmdset_0001.c
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,8 @@
* - optimized write buffer method
* 02/05/2002 Christopher Hoover <ch@hpl.hp.com>/<ch@murgatroid.com>
* - reworked lock/unlock/erase support for var size flash
* 21/03/2007 Rodolfo Giometti <giometti@linux.it>
* - auto unlock sectors on resume for auto locking flash on power up
*/

#include <linux/module.h>
Expand All @@ -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>
Expand Down Expand Up @@ -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 },
Expand All @@ -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 }
};

Expand Down Expand Up @@ -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);
}
Expand Down Expand Up @@ -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)
Expand All @@ -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
Expand Down Expand Up @@ -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];

Expand Down Expand Up @@ -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;

Expand All @@ -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)
Expand Down Expand Up @@ -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);
}

Expand Down
1 change: 1 addition & 0 deletions include/linux/mtd/mtd.h
Original file line number Diff line number Diff line change
Expand Up @@ -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 */
};

/*
Expand Down

0 comments on commit 0ecbc81

Please sign in to comment.