Commit 773bbe10 authored by Michael Walle's avatar Michael Walle Committed by Tudor Ambarus

mtd: spi-nor: add generic flash driver

Our SFDP parsing is everything we need to support all basic operations
of a flash device. If the flash isn't found in our in-kernel flash
database, gracefully fall back to a driver described solely by its SFDP
tables.
Signed-off-by: default avatarMichael Walle <michael@walle.cc>
Signed-off-by: default avatarTudor Ambarus <tudor.ambarus@microchip.com>
Tested-by: default avatarTudor Ambarus <tudor.ambarus@microchip.com>
Reviewed-by: default avatarTakahiro Kuwano <Takahiro.Kuwano@infineon.com>
Link: https://lore.kernel.org/r/20220810220654.1297699-7-michael@walle.cc
parent 39eece67
......@@ -1634,6 +1634,16 @@ static const struct spi_nor_manufacturer *manufacturers[] = {
&spi_nor_xmc,
};
static const struct flash_info spi_nor_generic_flash = {
.name = "spi-nor-generic",
/*
* JESD216 rev A doesn't specify the page size, therefore we need a
* sane default.
*/
.page_size = 256,
.parse_sfdp = true,
};
static const struct flash_info *spi_nor_match_id(struct spi_nor *nor,
const u8 *id)
{
......@@ -1672,6 +1682,14 @@ static const struct flash_info *spi_nor_detect(struct spi_nor *nor)
return ERR_PTR(-ENOMEM);
info = spi_nor_match_id(nor, id);
/* Fallback to a generic flash described only by its SFDP data. */
if (!info) {
ret = spi_nor_check_sfdp_signature(nor);
if (!ret)
info = &spi_nor_generic_flash;
}
if (!info) {
dev_err(nor->dev, "unrecognized JEDEC id bytes: %*ph\n",
SPI_NOR_MAX_ID_LEN, id);
......@@ -2098,8 +2116,12 @@ static int spi_nor_select_pp(struct spi_nor *nor,
* spi_nor_select_uniform_erase() - select optimum uniform erase type
* @map: the erase map of the SPI NOR
* @wanted_size: the erase type size to search for. Contains the value of
* info->sector_size or of the "small sector" size in case
* CONFIG_MTD_SPI_NOR_USE_4K_SECTORS is defined.
* info->sector_size, the "small sector" size in case
* CONFIG_MTD_SPI_NOR_USE_4K_SECTORS is defined or 0 if
* there is no information about the sector size. The
* latter is the case if the flash parameters are parsed
* solely by SFDP, then the largest supported erase type
* is selected.
*
* Once the optimum uniform sector erase command is found, disable all the
* other.
......
......@@ -701,6 +701,7 @@ int spi_nor_controller_ops_read_reg(struct spi_nor *nor, u8 opcode,
int spi_nor_controller_ops_write_reg(struct spi_nor *nor, u8 opcode,
const u8 *buf, size_t len);
int spi_nor_check_sfdp_signature(struct spi_nor *nor);
int spi_nor_parse_sfdp(struct spi_nor *nor);
static inline struct spi_nor *mtd_to_spi_nor(struct mtd_info *mtd)
......
......@@ -1256,6 +1256,33 @@ static void spi_nor_post_sfdp_fixups(struct spi_nor *nor)
nor->info->fixups->post_sfdp(nor);
}
/**
* spi_nor_check_sfdp_signature() - check for a valid SFDP signature
* @nor: pointer to a 'struct spi_nor'
*
* Used to detect if the flash supports the RDSFDP command as well as the
* presence of a valid SFDP table.
*
* Return: 0 on success, -errno otherwise.
*/
int spi_nor_check_sfdp_signature(struct spi_nor *nor)
{
u32 signature;
int err;
/* Get the SFDP header. */
err = spi_nor_read_sfdp_dma_unsafe(nor, 0, sizeof(signature),
&signature);
if (err < 0)
return err;
/* Check the SFDP signature. */
if (le32_to_cpu(signature) != SFDP_SIGNATURE)
return -EINVAL;
return 0;
}
/**
* spi_nor_parse_sfdp() - parse the Serial Flash Discoverable Parameters.
* @nor: pointer to a 'struct spi_nor'
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment