supporting flash that powers up locked
Hello,
I noticed that this topic has been issued several times during last years. I found several solutions but no one has been reported into the main line.
Can you please tell me current work around? I'm using strataflash Intel P30.
Thanks in advance,
Rodolfo
Signature · 4 lines
GNU/Linux Solutions e-mail: [email protected] Linux Device Driver [email protected] Embedded Systems [email protected] UNIX programming phone: +39 349 2432127
Quoted 5 lines · Rodolfo Giometti
Hello,
I noticed that this topic has been issued several times during last years. I found several solutions but no one has been reported into the main line.
Actually, there was one recently. The MTD_STUPID_LOCK flag was added, and if the chip driver sets that for a particular chip the core will unlock them when add_mtd_device is called.
Quoted 2 lines
Can you please tell me current work around? I'm using strataflash Intel P30.
You'd need to add a fixup to cfi_cmdset_0001.c for P30 to set that flag. See the fixup_use_amtel_lock function in cfi_cmdset_0002.c for an example.
josh
Quoted 3 lines · Josh Boyer
You'd need to add a fixup to
cfi_cmdset_0001.cfor P30 to set that flag. See thefixup_use_amtel_lockfunction incfi_cmdset_0002.cfor an example.
Ok, that could resolve problem during boot but not during suspend/resume cycle.
However I'm working on it and I'll propose a patch.
Thanks,
Rodolfo
Signature · 4 lines
GNU/Linux Solutions e-mail: [email protected] Linux Device Driver [email protected] Embedded Systems [email protected] UNIX programming phone: +39 349 2432127
PATCH 1/1 MTD: support for auto locking flash on power up
Auto unlock sectors on resume for auto locking flash on power up.
drivers/mtd/chips/cfi_cmdset_0001.c +90 -3
@@ -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 } };
@@ -446,6 +459,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); }
@@ -1813,8 +1827,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)
@@ -1828,8 +1841,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
@@ -2204,14 +2226,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];
@@ -2273,10 +2326,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;
@@ -2295,6 +2371,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)
@@ -2335,12 +2415,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); }
include/linux/mtd/mtd.h +1 -0
@@ -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 */ };/*