aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/mtd
diff options
context:
space:
mode:
authorBrian Norris <computersforpeace@gmail.com>2015-03-13 03:38:39 -0400
committerBrian Norris <computersforpeace@gmail.com>2015-03-27 13:37:38 -0400
commit8cc7f33aadc8fb37b5a3f4c46f5fa83748a92a01 (patch)
treeeae708435c1462bed2bf4d460b36642adf69223b /drivers/mtd
parent73c8aaf43629e83541332f66fd08699e20ea87bc (diff)
mtd: spi-nor: factor out replace-able flash_{lock,unlock}
Flash lock/unlock is a flash-specific operations. Factor out a callback for it to more readily support other vendors. Signed-off-by: Brian Norris <computersforpeace@gmail.com> Tested-by: VIET NGA DAO <vndao@altera.com>
Diffstat (limited to 'drivers/mtd')
-rw-r--r--drivers/mtd/spi-nor/spi-nor.c57
1 files changed, 38 insertions, 19 deletions
diff --git a/drivers/mtd/spi-nor/spi-nor.c b/drivers/mtd/spi-nor/spi-nor.c
index b6a5a0c269e1..60bf3caf1ead 100644
--- a/drivers/mtd/spi-nor/spi-nor.c
+++ b/drivers/mtd/spi-nor/spi-nor.c
@@ -369,17 +369,13 @@ erase_err:
369 return ret; 369 return ret;
370} 370}
371 371
372static int spi_nor_lock(struct mtd_info *mtd, loff_t ofs, uint64_t len) 372static int stm_lock(struct spi_nor *nor, loff_t ofs, uint64_t len)
373{ 373{
374 struct spi_nor *nor = mtd_to_spi_nor(mtd); 374 struct mtd_info *mtd = nor->mtd;
375 uint32_t offset = ofs; 375 uint32_t offset = ofs;
376 uint8_t status_old, status_new; 376 uint8_t status_old, status_new;
377 int ret = 0; 377 int ret = 0;
378 378
379 ret = spi_nor_lock_and_prep(nor, SPI_NOR_OPS_LOCK);
380 if (ret)
381 return ret;
382
383 status_old = read_sr(nor); 379 status_old = read_sr(nor);
384 380
385 if (offset < mtd->size - (mtd->size / 2)) 381 if (offset < mtd->size - (mtd->size / 2))
@@ -402,26 +398,18 @@ static int spi_nor_lock(struct mtd_info *mtd, loff_t ofs, uint64_t len)
402 (status_old & (SR_BP2 | SR_BP1 | SR_BP0))) { 398 (status_old & (SR_BP2 | SR_BP1 | SR_BP0))) {
403 write_enable(nor); 399 write_enable(nor);
404 ret = write_sr(nor, status_new); 400 ret = write_sr(nor, status_new);
405 if (ret)
406 goto err;
407 } 401 }
408 402
409err:
410 spi_nor_unlock_and_unprep(nor, SPI_NOR_OPS_LOCK);
411 return ret; 403 return ret;
412} 404}
413 405
414static int spi_nor_unlock(struct mtd_info *mtd, loff_t ofs, uint64_t len) 406static int stm_unlock(struct spi_nor *nor, loff_t ofs, uint64_t len)
415{ 407{
416 struct spi_nor *nor = mtd_to_spi_nor(mtd); 408 struct mtd_info *mtd = nor->mtd;
417 uint32_t offset = ofs; 409 uint32_t offset = ofs;
418 uint8_t status_old, status_new; 410 uint8_t status_old, status_new;
419 int ret = 0; 411 int ret = 0;
420 412
421 ret = spi_nor_lock_and_prep(nor, SPI_NOR_OPS_UNLOCK);
422 if (ret)
423 return ret;
424
425 status_old = read_sr(nor); 413 status_old = read_sr(nor);
426 414
427 if (offset+len > mtd->size - (mtd->size / 64)) 415 if (offset+len > mtd->size - (mtd->size / 64))
@@ -444,15 +432,41 @@ static int spi_nor_unlock(struct mtd_info *mtd, loff_t ofs, uint64_t len)
444 (status_old & (SR_BP2 | SR_BP1 | SR_BP0))) { 432 (status_old & (SR_BP2 | SR_BP1 | SR_BP0))) {
445 write_enable(nor); 433 write_enable(nor);
446 ret = write_sr(nor, status_new); 434 ret = write_sr(nor, status_new);
447 if (ret)
448 goto err;
449 } 435 }
450 436
451err: 437 return ret;
438}
439
440static int spi_nor_lock(struct mtd_info *mtd, loff_t ofs, uint64_t len)
441{
442 struct spi_nor *nor = mtd_to_spi_nor(mtd);
443 int ret;
444
445 ret = spi_nor_lock_and_prep(nor, SPI_NOR_OPS_LOCK);
446 if (ret)
447 return ret;
448
449 ret = nor->flash_lock(nor, ofs, len);
450
452 spi_nor_unlock_and_unprep(nor, SPI_NOR_OPS_UNLOCK); 451 spi_nor_unlock_and_unprep(nor, SPI_NOR_OPS_UNLOCK);
453 return ret; 452 return ret;
454} 453}
455 454
455static int spi_nor_unlock(struct mtd_info *mtd, loff_t ofs, uint64_t len)
456{
457 struct spi_nor *nor = mtd_to_spi_nor(mtd);
458 int ret;
459
460 ret = spi_nor_lock_and_prep(nor, SPI_NOR_OPS_UNLOCK);
461 if (ret)
462 return ret;
463
464 ret = nor->flash_unlock(nor, ofs, len);
465
466 spi_nor_unlock_and_unprep(nor, SPI_NOR_OPS_LOCK);
467 return ret;
468}
469
456/* Used when the "_ext_id" is two bytes at most */ 470/* Used when the "_ext_id" is two bytes at most */
457#define INFO(_jedec_id, _ext_id, _sector_size, _n_sectors, _flags) \ 471#define INFO(_jedec_id, _ext_id, _sector_size, _n_sectors, _flags) \
458 ((kernel_ulong_t)&(struct flash_info) { \ 472 ((kernel_ulong_t)&(struct flash_info) { \
@@ -1045,6 +1059,11 @@ int spi_nor_scan(struct spi_nor *nor, const char *name, enum read_mode mode)
1045 1059
1046 /* nor protection support for STmicro chips */ 1060 /* nor protection support for STmicro chips */
1047 if (JEDEC_MFR(info) == CFI_MFR_ST) { 1061 if (JEDEC_MFR(info) == CFI_MFR_ST) {
1062 nor->flash_lock = stm_lock;
1063 nor->flash_unlock = stm_unlock;
1064 }
1065
1066 if (nor->flash_lock && nor->flash_unlock) {
1048 mtd->_lock = spi_nor_lock; 1067 mtd->_lock = spi_nor_lock;
1049 mtd->_unlock = spi_nor_unlock; 1068 mtd->_unlock = spi_nor_unlock;
1050 } 1069 }