diff options
author | Brian Norris <computersforpeace@gmail.com> | 2015-03-13 03:38:39 -0400 |
---|---|---|
committer | Brian Norris <computersforpeace@gmail.com> | 2015-03-27 13:37:38 -0400 |
commit | 8cc7f33aadc8fb37b5a3f4c46f5fa83748a92a01 (patch) | |
tree | eae708435c1462bed2bf4d460b36642adf69223b /drivers/mtd | |
parent | 73c8aaf43629e83541332f66fd08699e20ea87bc (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.c | 57 |
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 | ||
372 | static int spi_nor_lock(struct mtd_info *mtd, loff_t ofs, uint64_t len) | 372 | static 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 | ||
409 | err: | ||
410 | spi_nor_unlock_and_unprep(nor, SPI_NOR_OPS_LOCK); | ||
411 | return ret; | 403 | return ret; |
412 | } | 404 | } |
413 | 405 | ||
414 | static int spi_nor_unlock(struct mtd_info *mtd, loff_t ofs, uint64_t len) | 406 | static 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 | ||
451 | err: | 437 | return ret; |
438 | } | ||
439 | |||
440 | static 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 | ||
455 | static 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 | } |