0001
0002
0003
0004
0005
0006
0007
0008 #include <linux/mtd/mtd.h>
0009 #include <linux/mtd/spi-nor.h>
0010
0011 #include "core.h"
0012
0013 static u8 spi_nor_get_sr_bp_mask(struct spi_nor *nor)
0014 {
0015 u8 mask = SR_BP2 | SR_BP1 | SR_BP0;
0016
0017 if (nor->flags & SNOR_F_HAS_SR_BP3_BIT6)
0018 return mask | SR_BP3_BIT6;
0019
0020 if (nor->flags & SNOR_F_HAS_4BIT_BP)
0021 return mask | SR_BP3;
0022
0023 return mask;
0024 }
0025
0026 static u8 spi_nor_get_sr_tb_mask(struct spi_nor *nor)
0027 {
0028 if (nor->flags & SNOR_F_HAS_SR_TB_BIT6)
0029 return SR_TB_BIT6;
0030 else
0031 return SR_TB_BIT5;
0032 }
0033
0034 static u64 spi_nor_get_min_prot_length_sr(struct spi_nor *nor)
0035 {
0036 unsigned int bp_slots, bp_slots_needed;
0037 u8 mask = spi_nor_get_sr_bp_mask(nor);
0038
0039
0040 bp_slots = (1 << hweight8(mask)) - 2;
0041 bp_slots_needed = ilog2(nor->info->n_sectors);
0042
0043 if (bp_slots_needed > bp_slots)
0044 return nor->info->sector_size <<
0045 (bp_slots_needed - bp_slots);
0046 else
0047 return nor->info->sector_size;
0048 }
0049
0050 static void spi_nor_get_locked_range_sr(struct spi_nor *nor, u8 sr, loff_t *ofs,
0051 uint64_t *len)
0052 {
0053 struct mtd_info *mtd = &nor->mtd;
0054 u64 min_prot_len;
0055 u8 mask = spi_nor_get_sr_bp_mask(nor);
0056 u8 tb_mask = spi_nor_get_sr_tb_mask(nor);
0057 u8 bp, val = sr & mask;
0058
0059 if (nor->flags & SNOR_F_HAS_SR_BP3_BIT6 && val & SR_BP3_BIT6)
0060 val = (val & ~SR_BP3_BIT6) | SR_BP3;
0061
0062 bp = val >> SR_BP_SHIFT;
0063
0064 if (!bp) {
0065
0066 *ofs = 0;
0067 *len = 0;
0068 return;
0069 }
0070
0071 min_prot_len = spi_nor_get_min_prot_length_sr(nor);
0072 *len = min_prot_len << (bp - 1);
0073
0074 if (*len > mtd->size)
0075 *len = mtd->size;
0076
0077 if (nor->flags & SNOR_F_HAS_SR_TB && sr & tb_mask)
0078 *ofs = 0;
0079 else
0080 *ofs = mtd->size - *len;
0081 }
0082
0083
0084
0085
0086
0087 static bool spi_nor_check_lock_status_sr(struct spi_nor *nor, loff_t ofs,
0088 uint64_t len, u8 sr, bool locked)
0089 {
0090 loff_t lock_offs, lock_offs_max, offs_max;
0091 uint64_t lock_len;
0092
0093 if (!len)
0094 return true;
0095
0096 spi_nor_get_locked_range_sr(nor, sr, &lock_offs, &lock_len);
0097
0098 lock_offs_max = lock_offs + lock_len;
0099 offs_max = ofs + len;
0100
0101 if (locked)
0102
0103 return (offs_max <= lock_offs_max) && (ofs >= lock_offs);
0104 else
0105
0106 return (ofs >= lock_offs_max) || (offs_max <= lock_offs);
0107 }
0108
0109 static bool spi_nor_is_locked_sr(struct spi_nor *nor, loff_t ofs, uint64_t len,
0110 u8 sr)
0111 {
0112 return spi_nor_check_lock_status_sr(nor, ofs, len, sr, true);
0113 }
0114
0115 static bool spi_nor_is_unlocked_sr(struct spi_nor *nor, loff_t ofs,
0116 uint64_t len, u8 sr)
0117 {
0118 return spi_nor_check_lock_status_sr(nor, ofs, len, sr, false);
0119 }
0120
0121
0122
0123
0124
0125
0126
0127
0128
0129
0130
0131
0132
0133
0134
0135
0136
0137
0138
0139
0140
0141
0142
0143
0144
0145
0146
0147
0148
0149
0150
0151
0152
0153
0154 static int spi_nor_sr_lock(struct spi_nor *nor, loff_t ofs, uint64_t len)
0155 {
0156 struct mtd_info *mtd = &nor->mtd;
0157 u64 min_prot_len;
0158 int ret, status_old, status_new;
0159 u8 mask = spi_nor_get_sr_bp_mask(nor);
0160 u8 tb_mask = spi_nor_get_sr_tb_mask(nor);
0161 u8 pow, val;
0162 loff_t lock_len;
0163 bool can_be_top = true, can_be_bottom = nor->flags & SNOR_F_HAS_SR_TB;
0164 bool use_top;
0165
0166 ret = spi_nor_read_sr(nor, nor->bouncebuf);
0167 if (ret)
0168 return ret;
0169
0170 status_old = nor->bouncebuf[0];
0171
0172
0173 if (spi_nor_is_locked_sr(nor, ofs, len, status_old))
0174 return 0;
0175
0176
0177 if (!spi_nor_is_locked_sr(nor, 0, ofs, status_old))
0178 can_be_bottom = false;
0179
0180
0181 if (!spi_nor_is_locked_sr(nor, ofs + len, mtd->size - (ofs + len),
0182 status_old))
0183 can_be_top = false;
0184
0185 if (!can_be_bottom && !can_be_top)
0186 return -EINVAL;
0187
0188
0189 use_top = can_be_top;
0190
0191
0192 if (use_top)
0193 lock_len = mtd->size - ofs;
0194 else
0195 lock_len = ofs + len;
0196
0197 if (lock_len == mtd->size) {
0198 val = mask;
0199 } else {
0200 min_prot_len = spi_nor_get_min_prot_length_sr(nor);
0201 pow = ilog2(lock_len) - ilog2(min_prot_len) + 1;
0202 val = pow << SR_BP_SHIFT;
0203
0204 if (nor->flags & SNOR_F_HAS_SR_BP3_BIT6 && val & SR_BP3)
0205 val = (val & ~SR_BP3) | SR_BP3_BIT6;
0206
0207 if (val & ~mask)
0208 return -EINVAL;
0209
0210
0211 if (!(val & mask))
0212 return -EINVAL;
0213 }
0214
0215 status_new = (status_old & ~mask & ~tb_mask) | val;
0216
0217
0218 status_new |= SR_SRWD;
0219
0220 if (!use_top)
0221 status_new |= tb_mask;
0222
0223
0224 if (status_new == status_old)
0225 return 0;
0226
0227
0228 if ((status_new & mask) < (status_old & mask))
0229 return -EINVAL;
0230
0231 return spi_nor_write_sr_and_check(nor, status_new);
0232 }
0233
0234
0235
0236
0237
0238
0239 static int spi_nor_sr_unlock(struct spi_nor *nor, loff_t ofs, uint64_t len)
0240 {
0241 struct mtd_info *mtd = &nor->mtd;
0242 u64 min_prot_len;
0243 int ret, status_old, status_new;
0244 u8 mask = spi_nor_get_sr_bp_mask(nor);
0245 u8 tb_mask = spi_nor_get_sr_tb_mask(nor);
0246 u8 pow, val;
0247 loff_t lock_len;
0248 bool can_be_top = true, can_be_bottom = nor->flags & SNOR_F_HAS_SR_TB;
0249 bool use_top;
0250
0251 ret = spi_nor_read_sr(nor, nor->bouncebuf);
0252 if (ret)
0253 return ret;
0254
0255 status_old = nor->bouncebuf[0];
0256
0257
0258 if (spi_nor_is_unlocked_sr(nor, ofs, len, status_old))
0259 return 0;
0260
0261
0262 if (!spi_nor_is_unlocked_sr(nor, 0, ofs, status_old))
0263 can_be_top = false;
0264
0265
0266 if (!spi_nor_is_unlocked_sr(nor, ofs + len, mtd->size - (ofs + len),
0267 status_old))
0268 can_be_bottom = false;
0269
0270 if (!can_be_bottom && !can_be_top)
0271 return -EINVAL;
0272
0273
0274 use_top = can_be_top;
0275
0276
0277 if (use_top)
0278 lock_len = mtd->size - (ofs + len);
0279 else
0280 lock_len = ofs;
0281
0282 if (lock_len == 0) {
0283 val = 0;
0284 } else {
0285 min_prot_len = spi_nor_get_min_prot_length_sr(nor);
0286 pow = ilog2(lock_len) - ilog2(min_prot_len) + 1;
0287 val = pow << SR_BP_SHIFT;
0288
0289 if (nor->flags & SNOR_F_HAS_SR_BP3_BIT6 && val & SR_BP3)
0290 val = (val & ~SR_BP3) | SR_BP3_BIT6;
0291
0292
0293 if (val & ~mask)
0294 return -EINVAL;
0295 }
0296
0297 status_new = (status_old & ~mask & ~tb_mask) | val;
0298
0299
0300 if (lock_len == 0)
0301 status_new &= ~SR_SRWD;
0302
0303 if (!use_top)
0304 status_new |= tb_mask;
0305
0306
0307 if (status_new == status_old)
0308 return 0;
0309
0310
0311 if ((status_new & mask) > (status_old & mask))
0312 return -EINVAL;
0313
0314 return spi_nor_write_sr_and_check(nor, status_new);
0315 }
0316
0317
0318
0319
0320
0321
0322
0323
0324 static int spi_nor_sr_is_locked(struct spi_nor *nor, loff_t ofs, uint64_t len)
0325 {
0326 int ret;
0327
0328 ret = spi_nor_read_sr(nor, nor->bouncebuf);
0329 if (ret)
0330 return ret;
0331
0332 return spi_nor_is_locked_sr(nor, ofs, len, nor->bouncebuf[0]);
0333 }
0334
0335 static const struct spi_nor_locking_ops spi_nor_sr_locking_ops = {
0336 .lock = spi_nor_sr_lock,
0337 .unlock = spi_nor_sr_unlock,
0338 .is_locked = spi_nor_sr_is_locked,
0339 };
0340
0341 void spi_nor_init_default_locking_ops(struct spi_nor *nor)
0342 {
0343 nor->params->locking_ops = &spi_nor_sr_locking_ops;
0344 }
0345
0346 static int spi_nor_lock(struct mtd_info *mtd, loff_t ofs, uint64_t len)
0347 {
0348 struct spi_nor *nor = mtd_to_spi_nor(mtd);
0349 int ret;
0350
0351 ret = spi_nor_lock_and_prep(nor);
0352 if (ret)
0353 return ret;
0354
0355 ret = nor->params->locking_ops->lock(nor, ofs, len);
0356
0357 spi_nor_unlock_and_unprep(nor);
0358 return ret;
0359 }
0360
0361 static int spi_nor_unlock(struct mtd_info *mtd, loff_t ofs, uint64_t len)
0362 {
0363 struct spi_nor *nor = mtd_to_spi_nor(mtd);
0364 int ret;
0365
0366 ret = spi_nor_lock_and_prep(nor);
0367 if (ret)
0368 return ret;
0369
0370 ret = nor->params->locking_ops->unlock(nor, ofs, len);
0371
0372 spi_nor_unlock_and_unprep(nor);
0373 return ret;
0374 }
0375
0376 static int spi_nor_is_locked(struct mtd_info *mtd, loff_t ofs, uint64_t len)
0377 {
0378 struct spi_nor *nor = mtd_to_spi_nor(mtd);
0379 int ret;
0380
0381 ret = spi_nor_lock_and_prep(nor);
0382 if (ret)
0383 return ret;
0384
0385 ret = nor->params->locking_ops->is_locked(nor, ofs, len);
0386
0387 spi_nor_unlock_and_unprep(nor);
0388 return ret;
0389 }
0390
0391
0392
0393
0394
0395
0396
0397
0398
0399
0400
0401
0402
0403 void spi_nor_try_unlock_all(struct spi_nor *nor)
0404 {
0405 int ret;
0406
0407 if (!(nor->flags & SNOR_F_HAS_LOCK))
0408 return;
0409
0410 dev_dbg(nor->dev, "Unprotecting entire flash array\n");
0411
0412 ret = spi_nor_unlock(&nor->mtd, 0, nor->params->size);
0413 if (ret)
0414 dev_dbg(nor->dev, "Failed to unlock the entire flash memory array\n");
0415 }
0416
0417 void spi_nor_set_mtd_locking_ops(struct spi_nor *nor)
0418 {
0419 struct mtd_info *mtd = &nor->mtd;
0420
0421 if (!nor->params->locking_ops)
0422 return;
0423
0424 mtd->_lock = spi_nor_lock;
0425 mtd->_unlock = spi_nor_unlock;
0426 mtd->_is_locked = spi_nor_is_locked;
0427 }