From mboxrd@z Thu Jan 1 00:00:00 1970 From: tkuw584924 at gmail.com Date: Wed, 4 Nov 2020 17:10:21 +0900 Subject: [PATCH v3 5/7] mtd: spi-nor-core: Add overlaid sector erase feature In-Reply-To: References: Message-ID: <8880f6efcab05efeca381503a844a7b778b81225.1604471789.git.Takahiro.Kuwano@infineon.com> List-Id: MIME-Version: 1.0 Content-Type: text/plain; charset="us-ascii" Content-Transfer-Encoding: 7bit To: u-boot@lists.denx.de From: Takahiro Kuwano Some of Spansion/Cypress chips have overlaid 4KB sectors at top and/or bottom, depending on the device configuration, while U-Boot supports uniform sector layout only. This patch adds an erase hook that emulates uniform sector layout. Signed-off-by: Takahiro Kuwano --- drivers/mtd/spi/spi-nor-core.c | 48 ++++++++++++++++++++++++++++++++++ 1 file changed, 48 insertions(+) diff --git a/drivers/mtd/spi/spi-nor-core.c b/drivers/mtd/spi/spi-nor-core.c index 6553a7f211..042da329da 100644 --- a/drivers/mtd/spi/spi-nor-core.c +++ b/drivers/mtd/spi/spi-nor-core.c @@ -732,6 +732,54 @@ erase_err: return ret; } +#ifdef CONFIG_SPI_FLASH_SPANSION +/* + * Erase for Spansion/Cypress Flash devices that has overlaid 4KB sectors at + * the top and/or bottom. + */ +static int spansion_overlaid_erase(struct mtd_info *mtd, + struct erase_info *instr) +{ + struct spi_nor *nor = mtd_to_spi_nor(mtd); + struct erase_info instr_4k; + u8 opcode; + u32 erasesize; + int ret; + + /* Perform default erase operation (non-overlaid portion is erased) */ + ret = spi_nor_erase(mtd, instr); + if (ret) + return ret; + + /* Backup default erase opcode and size */ + opcode = nor->erase_opcode; + erasesize = mtd->erasesize; + + /* + * Erase 4KB sectors. Use the possible max length of 4KB sector region. + * The Flash just ignores the command if the address is not configured + * as 4KB sector and reports ready status immediately. + */ + instr_4k.len = SZ_128K; + nor->erase_opcode = SPINOR_OP_BE_4K_4B; + mtd->erasesize = SZ_4K; + if (instr->addr == 0) { + instr_4k.addr = 0; + ret = spi_nor_erase(mtd, &instr_4k); + } + if (!ret && instr->addr + instr->len == mtd->size) { + instr_4k.addr = mtd->size - instr_4k.len; + ret = spi_nor_erase(mtd, &instr_4k); + } + + /* Restore erase opcode and size */ + nor->erase_opcode = opcode; + mtd->erasesize = erasesize; + + return ret; +} +#endif + #if defined(CONFIG_SPI_FLASH_STMICRO) || defined(CONFIG_SPI_FLASH_SST) /* Write status register and ensure bits in mask match written values */ static int write_sr_and_check(struct spi_nor *nor, u8 status_new, u8 mask) -- 2.25.1