0001
0002 #ifndef FWH_LOCK_H
0003 #define FWH_LOCK_H
0004
0005
0006 enum fwh_lock_state {
0007 FWH_UNLOCKED = 0,
0008 FWH_DENY_WRITE = 1,
0009 FWH_IMMUTABLE = 2,
0010 FWH_DENY_READ = 4,
0011 };
0012
0013 struct fwh_xxlock_thunk {
0014 enum fwh_lock_state val;
0015 flstate_t state;
0016 };
0017
0018
0019 #define FWH_XXLOCK_ONEBLOCK_LOCK ((struct fwh_xxlock_thunk){ FWH_DENY_WRITE, FL_LOCKING})
0020 #define FWH_XXLOCK_ONEBLOCK_UNLOCK ((struct fwh_xxlock_thunk){ FWH_UNLOCKED, FL_UNLOCKING})
0021
0022
0023
0024
0025
0026
0027
0028
0029 static int fwh_xxlock_oneblock(struct map_info *map, struct flchip *chip,
0030 unsigned long adr, int len, void *thunk)
0031 {
0032 struct cfi_private *cfi = map->fldrv_priv;
0033 struct fwh_xxlock_thunk *xxlt = (struct fwh_xxlock_thunk *)thunk;
0034 int ret;
0035
0036
0037 if (chip->start < 0x400000) {
0038 pr_debug( "MTD %s(): chip->start: %lx wanted >= 0x400000\n",
0039 __func__, chip->start );
0040 return -EIO;
0041 }
0042
0043
0044
0045
0046
0047
0048
0049
0050
0051
0052
0053 adr = (adr & ~0xffffUL) | 0x2;
0054 adr += chip->start - 0x400000;
0055
0056
0057
0058
0059
0060
0061 mutex_lock(&chip->mutex);
0062 ret = get_chip(map, chip, adr, FL_LOCKING);
0063 if (ret) {
0064 mutex_unlock(&chip->mutex);
0065 return ret;
0066 }
0067
0068 chip->oldstate = chip->state;
0069 chip->state = xxlt->state;
0070 map_write(map, CMD(xxlt->val), adr);
0071
0072
0073 chip->state = chip->oldstate;
0074 put_chip(map, chip, adr);
0075 mutex_unlock(&chip->mutex);
0076 return 0;
0077 }
0078
0079
0080 static int fwh_lock_varsize(struct mtd_info *mtd, loff_t ofs, uint64_t len)
0081 {
0082 int ret;
0083
0084 ret = cfi_varsize_frob(mtd, fwh_xxlock_oneblock, ofs, len,
0085 (void *)&FWH_XXLOCK_ONEBLOCK_LOCK);
0086
0087 return ret;
0088 }
0089
0090
0091 static int fwh_unlock_varsize(struct mtd_info *mtd, loff_t ofs, uint64_t len)
0092 {
0093 int ret;
0094
0095 ret = cfi_varsize_frob(mtd, fwh_xxlock_oneblock, ofs, len,
0096 (void *)&FWH_XXLOCK_ONEBLOCK_UNLOCK);
0097
0098 return ret;
0099 }
0100
0101 static void fixup_use_fwh_lock(struct mtd_info *mtd)
0102 {
0103 printk(KERN_NOTICE "using fwh lock/unlock method\n");
0104
0105 mtd->_lock = fwh_lock_varsize;
0106 mtd->_unlock = fwh_unlock_varsize;
0107 }
0108 #endif