[PATCHv3 1/2] mtd: spi-nor: Add SPI NOR layer PM support
Zhiqiang Hou
zhiqiang.hou at nxp.com
Thu Apr 14 00:59:39 PDT 2016
Hi,
Any comments?
> -----Original Message-----
> From: Zhiqiang Hou [mailto:Zhiqiang.Hou at freescale.com]
> Sent: 2016年1月22日 17:14
> To: linux-mtd at lists.infradead.org; computersforpeace at gmail.com;
> dwmw2 at infradead.org; jteki at openedev.com; marex at denx.de
> Cc: Mingkai.Hu at freescale.com; Hou Zhiqiang <Zhiqiang.Hou at freescale.com>
> Subject: [PATCHv3 1/2] mtd: spi-nor: Add SPI NOR layer PM support
>
> From: Hou Zhiqiang <Zhiqiang.Hou at freescale.com>
>
> 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 at freescale.com>
> ---
> Tested on T1042D4RDB.
>
> V3:
> - Remove the condition #ifdef CONFIG_PM_SLEEP
> - Define the spi_nor_unprotect_on_powerup() to make it reuseable.
>
> drivers/mtd/spi-nor/spi-nor.c | 73 ++++++++++++++++++++++++++++++++++++----
> ---
> include/linux/mtd/spi-nor.h | 9 ++++++
> 2 files changed, 71 insertions(+), 11 deletions(-)
>
> diff --git a/drivers/mtd/spi-nor/spi-nor.c b/drivers/mtd/spi-nor/spi-nor.c index
> ed0c19c..7e416fb 100644
> --- a/drivers/mtd/spi-nor/spi-nor.c
> +++ b/drivers/mtd/spi-nor/spi-nor.c
> @@ -1179,6 +1179,26 @@ static int spi_nor_check(struct spi_nor *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;
> @@ -1226,17 +1246,9 @@ int spi_nor_scan(struct spi_nor *nor, const char
> *name, enum read_mode mode)
>
> 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_SST) {
> - 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);
> @@ -1402,6 +1414,45 @@ int spi_nor_scan(struct spi_nor *nor, const char
> *name, enum read_mode mode) } 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; diff --git a/include/linux/mtd/spi-
> nor.h b/include/linux/mtd/spi-nor.h index 62356d5..32f12cc 100644
> --- a/include/linux/mtd/spi-nor.h
> +++ b/include/linux/mtd/spi-nor.h
> @@ -210,4 +210,13 @@ static inline struct device_node
> *spi_nor_get_flash_node(struct spi_nor *nor)
> */
> 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
> --
Thanks,
Zhiqiang
More information about the linux-mtd
mailing list