diff options
author | Steffen Trumtrar <s.trumtrar@pengutronix.de> | 2019-05-03 11:33:59 +0200 |
---|---|---|
committer | Sascha Hauer <s.hauer@pengutronix.de> | 2019-05-08 10:52:51 +0200 |
commit | b90c959f5cb71d53c3ecaf4ffe39424aaf346b51 (patch) | |
tree | d25e83dcc9c506f8fdd7a12dbe97a0dd28fab4a8 /drivers/mtd/spi-nor | |
parent | 8e3318b5bc593c5366edda37cde717c4f4a36ad5 (diff) | |
download | barebox-b90c959f5cb71d53c3ecaf4ffe39424aaf346b51.tar.gz barebox-b90c959f5cb71d53c3ecaf4ffe39424aaf346b51.tar.xz |
mtd: spi-nor: provide default erase_sector implementation
Based on the Linux v4.4 patch
commit c67cbb839da9cc2757eabfa128556db6a2baf160
Author: Brian Norris <computersforpeace@gmail.com>
AuthorDate: Tue Nov 10 12:15:27 2015 -0800
Commit: Brian Norris <computersforpeace@gmail.com>
CommitDate: Thu Nov 19 13:34:44 2015 -0800
mtd: spi-nor: provide default erase_sector implementation
Some spi-nor drivers perform sector erase by duplicating their
write_reg() command. Let's not require that the driver fill this out,
and provide a default instead.
Tested on m25p80.c and Medatek's MT8173 SPI NOR flash driver.
Signed-off-by: Brian Norris <computersforpeace@gmail.com>
Signed-off-by: Steffen Trumtrar <s.trumtrar@pengutronix.de>
Signed-off-by: Sascha Hauer <s.hauer@pengutronix.de>
Diffstat (limited to 'drivers/mtd/spi-nor')
-rw-r--r-- | drivers/mtd/spi-nor/spi-nor.c | 37 |
1 files changed, 33 insertions, 4 deletions
diff --git a/drivers/mtd/spi-nor/spi-nor.c b/drivers/mtd/spi-nor/spi-nor.c index e086d868e2..9f72df39f0 100644 --- a/drivers/mtd/spi-nor/spi-nor.c +++ b/drivers/mtd/spi-nor/spi-nor.c @@ -25,6 +25,7 @@ #include <spi/flash.h> #define SPI_NOR_MAX_ID_LEN 6 +#define SPI_NOR_MAX_ADDR_WIDTH 4 /* * For everything but full-chip erase; probably could be much smaller, but kept @@ -435,6 +436,29 @@ static void spi_nor_unlock_and_unprep(struct spi_nor *nor, enum spi_nor_ops ops) } /* + * Initiate the erasure of a single sector + */ +static int spi_nor_erase_sector(struct spi_nor *nor, u32 addr) +{ + u8 buf[SPI_NOR_MAX_ADDR_WIDTH]; + int i; + + if (nor->erase) + return nor->erase(nor, addr); + + /* + * Default implementation, if driver doesn't have a specialized HW + * control + */ + for (i = nor->addr_width - 1; i >= 0; i--) { + buf[i] = addr & 0xff; + addr >>= 8; + } + + return nor->write_reg(nor, nor->erase_opcode, buf, nor->addr_width); +} + +/* * Erase an address range on the nor chip. The address range may extend * one or more erase sectors. Return an error is there is a problem erasing. */ @@ -498,10 +522,9 @@ static int spi_nor_erase(struct mtd_info *mtd, struct erase_info *instr) while (len) { write_enable(nor); - if (nor->erase(nor, addr)) { - ret = -EIO; + ret = spi_nor_erase_sector(nor, addr); + if (ret) goto erase_err; - } addr += mtd->erasesize; len -= mtd->erasesize; @@ -988,7 +1011,7 @@ static int spansion_quad_enable(struct spi_nor *nor) static int spi_nor_check(struct spi_nor *nor) { if (!nor->dev || !nor->read || !nor->write || - !nor->read_reg || !nor->write_reg || !nor->erase) { + !nor->read_reg || !nor->write_reg) { pr_err("spi-nor: please fill all the necessary fields!\n"); return -EINVAL; } @@ -1394,6 +1417,12 @@ int spi_nor_scan(struct spi_nor *nor, const char *name, nor->addr_width = 3; } + if (nor->addr_width > SPI_NOR_MAX_ADDR_WIDTH) { + dev_err(dev, "address width is too large: %u\n", + nor->addr_width); + return -EINVAL; + } + dev_info(dev, "%s (%lld Kbytes)\n", id->name, (long long)mtd->size >> 10); |