123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138 |
- From 2c5a3db21926e9ebfd7a32e3c36a3256ed84903c Mon Sep 17 00:00:00 2001
- From: Hou Zhiqiang <Zhiqiang.Hou@freescale.com>
- Date: Thu, 19 Nov 2015 20:25:24 +0800
- Subject: [PATCH 090/113] mtd: spi-nor: Add SPI NOR layer PM support
- [context adjustment]
- Add the Power Management API in SPI NOR framework.
- The Power Management system will turn off power supply to SPI flash
- when system suspending, and then the SPI flash will be in the reset
- state after system resuming. As a result, the status&configurations
- of SPI flash driver will mismatch with its current hardware state.
- So reinitialize SPI flash to make sure it is resumed to the correct
- state.
- And the SPI NOR layer just do common configuration depending on the
- records in structure spi_nor.
- Signed-off-by: Hou Zhiqiang <Zhiqiang.Hou@freescale.com>
- Integrated-by: Jiang Yutang <yutang.jiang@nxp.com>
- ---
- drivers/mtd/spi-nor/spi-nor.c | 74 ++++++++++++++++++++++++++++++++++-------
- include/linux/mtd/spi-nor.h | 9 +++++
- 2 files changed, 71 insertions(+), 12 deletions(-)
- --- a/drivers/mtd/spi-nor/spi-nor.c
- +++ b/drivers/mtd/spi-nor/spi-nor.c
- @@ -1154,6 +1154,26 @@ static int spi_nor_check(struct spi_nor
- return 0;
- }
-
- +/*
- + * Atmel, SST, Intel/Numonyx, and others serial NOR tend to power up
- + * with the software protection bits set
- + */
- +static int spi_nor_unprotect_on_powerup(struct spi_nor *nor)
- +{
- + const struct flash_info *info = NULL;
- + int ret = 0;
- +
- + info = spi_nor_read_id(nor);
- + if (JEDEC_MFR(info) == SNOR_MFR_ATMEL ||
- + JEDEC_MFR(info) == SNOR_MFR_INTEL ||
- + JEDEC_MFR(info) == SNOR_MFR_SST) {
- + write_enable(nor);
- + ret = write_sr(nor, 0);
- + }
- +
- + return ret;
- +}
- +
- int spi_nor_scan(struct spi_nor *nor, const char *name, enum read_mode mode)
- {
- const struct flash_info *info = NULL;
- @@ -1201,19 +1221,9 @@ int spi_nor_scan(struct spi_nor *nor, co
-
- mutex_init(&nor->lock);
-
- - /*
- - * Atmel, SST, Intel/Numonyx, and others serial NOR tend to power up
- - * with the software protection bits set
- - */
- -
- - if (JEDEC_MFR(info) == SNOR_MFR_ATMEL ||
- - JEDEC_MFR(info) == SNOR_MFR_INTEL ||
- - JEDEC_MFR(info) == SNOR_MFR_MACRONIX ||
- - JEDEC_MFR(info) == SNOR_MFR_SST ||
- - info->flags & SPI_NOR_HAS_LOCK) {
- - write_enable(nor);
- - write_sr(nor, 0);
- - }
- + ret = spi_nor_unprotect_on_powerup(nor);
- + if (ret)
- + return ret;
-
- if (!mtd->name)
- mtd->name = dev_name(dev);
- @@ -1380,6 +1390,45 @@ int spi_nor_scan(struct spi_nor *nor, co
- }
- EXPORT_SYMBOL_GPL(spi_nor_scan);
-
- +static int spi_nor_hw_reinit(struct spi_nor *nor)
- +{
- + const struct flash_info *info = NULL;
- + struct device *dev = nor->dev;
- + int ret;
- +
- + info = spi_nor_read_id(nor);
- +
- + ret = spi_nor_unprotect_on_powerup(nor);
- + if (ret)
- + return ret;
- +
- + if (nor->flash_read == SPI_NOR_QUAD) {
- + ret = set_quad_mode(nor, info);
- + if (ret) {
- + dev_err(dev, "quad mode not supported\n");
- + return ret;
- + }
- + }
- +
- + if (nor->addr_width == 4 &&
- + JEDEC_MFR(info) != SNOR_MFR_SPANSION)
- + set_4byte(nor, info, 1);
- +
- + return 0;
- +}
- +
- +int spi_nor_suspend(struct spi_nor *nor)
- +{
- + return 0;
- +}
- +EXPORT_SYMBOL_GPL(spi_nor_suspend);
- +
- +int spi_nor_resume(struct spi_nor *nor)
- +{
- + return spi_nor_hw_reinit(nor);
- +}
- +EXPORT_SYMBOL_GPL(spi_nor_resume);
- +
- static const struct flash_info *spi_nor_match_id(const char *name)
- {
- const struct flash_info *id = spi_nor_ids;
- --- a/include/linux/mtd/spi-nor.h
- +++ b/include/linux/mtd/spi-nor.h
- @@ -210,4 +210,13 @@ static inline struct device_node *spi_no
- */
- int spi_nor_scan(struct spi_nor *nor, const char *name, enum read_mode mode);
-
- +/**
- + * spi_nor_suspend/resume() - the SPI NOR layer PM API
- + * @nor: the spi_nor structure
- + *
- + * Return: 0 for success, others for failure.
- + */
- +int spi_nor_suspend(struct spi_nor *nor);
- +int spi_nor_resume(struct spi_nor *nor);
- +
- #endif
|