mirror of
https://git.kernel.org/pub/scm/linux/kernel/git/stable/linux.git
synced 2025-01-10 23:20:05 +00:00
mtd: spi-nor: sfdp: save a copy of the SFDP data
Due to possible mode switching to 8D-8D-8D, it might not be possible to read the SFDP after the initial probe. To be able to dump the SFDP via sysfs afterwards, make a complete copy of it. Signed-off-by: Michael Walle <michael@walle.cc> Signed-off-by: Vignesh Raghavendra <vigneshr@ti.com> Tested-by: Heiko Thiery <heiko.thiery@gmail.com> Reviewed-by: Pratyush Yadav <p.yadav@ti.com>
This commit is contained in:
parent
c6ec3e1e3a
commit
65b6d89d45
@ -461,6 +461,16 @@ struct spi_nor_manufacturer {
|
|||||||
const struct spi_nor_fixups *fixups;
|
const struct spi_nor_fixups *fixups;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* struct sfdp - SFDP data
|
||||||
|
* @num_dwords: number of entries in the dwords array
|
||||||
|
* @dwords: array of double words of the SFDP data
|
||||||
|
*/
|
||||||
|
struct sfdp {
|
||||||
|
size_t num_dwords;
|
||||||
|
u32 *dwords;
|
||||||
|
};
|
||||||
|
|
||||||
/* Manufacturer drivers. */
|
/* Manufacturer drivers. */
|
||||||
extern const struct spi_nor_manufacturer spi_nor_atmel;
|
extern const struct spi_nor_manufacturer spi_nor_atmel;
|
||||||
extern const struct spi_nor_manufacturer spi_nor_catalyst;
|
extern const struct spi_nor_manufacturer spi_nor_catalyst;
|
||||||
|
@ -16,6 +16,7 @@
|
|||||||
(((p)->parameter_table_pointer[2] << 16) | \
|
(((p)->parameter_table_pointer[2] << 16) | \
|
||||||
((p)->parameter_table_pointer[1] << 8) | \
|
((p)->parameter_table_pointer[1] << 8) | \
|
||||||
((p)->parameter_table_pointer[0] << 0))
|
((p)->parameter_table_pointer[0] << 0))
|
||||||
|
#define SFDP_PARAM_HEADER_PARAM_LEN(p) ((p)->length * 4)
|
||||||
|
|
||||||
#define SFDP_BFPT_ID 0xff00 /* Basic Flash Parameter Table */
|
#define SFDP_BFPT_ID 0xff00 /* Basic Flash Parameter Table */
|
||||||
#define SFDP_SECTOR_MAP_ID 0xff81 /* Sector Map Table */
|
#define SFDP_SECTOR_MAP_ID 0xff81 /* Sector Map Table */
|
||||||
@ -1245,6 +1246,8 @@ int spi_nor_parse_sfdp(struct spi_nor *nor)
|
|||||||
struct sfdp_parameter_header *param_headers = NULL;
|
struct sfdp_parameter_header *param_headers = NULL;
|
||||||
struct sfdp_header header;
|
struct sfdp_header header;
|
||||||
struct device *dev = nor->dev;
|
struct device *dev = nor->dev;
|
||||||
|
struct sfdp *sfdp;
|
||||||
|
size_t sfdp_size;
|
||||||
size_t psize;
|
size_t psize;
|
||||||
int i, err;
|
int i, err;
|
||||||
|
|
||||||
@ -1267,6 +1270,9 @@ int spi_nor_parse_sfdp(struct spi_nor *nor)
|
|||||||
bfpt_header->major != SFDP_JESD216_MAJOR)
|
bfpt_header->major != SFDP_JESD216_MAJOR)
|
||||||
return -EINVAL;
|
return -EINVAL;
|
||||||
|
|
||||||
|
sfdp_size = SFDP_PARAM_HEADER_PTP(bfpt_header) +
|
||||||
|
SFDP_PARAM_HEADER_PARAM_LEN(bfpt_header);
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Allocate memory then read all parameter headers with a single
|
* Allocate memory then read all parameter headers with a single
|
||||||
* Read SFDP command. These parameter headers will actually be parsed
|
* Read SFDP command. These parameter headers will actually be parsed
|
||||||
@ -1293,6 +1299,58 @@ int spi_nor_parse_sfdp(struct spi_nor *nor)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Cache the complete SFDP data. It is not (easily) possible to fetch
|
||||||
|
* SFDP after probe time and we need it for the sysfs access.
|
||||||
|
*/
|
||||||
|
for (i = 0; i < header.nph; i++) {
|
||||||
|
param_header = ¶m_headers[i];
|
||||||
|
sfdp_size = max_t(size_t, sfdp_size,
|
||||||
|
SFDP_PARAM_HEADER_PTP(param_header) +
|
||||||
|
SFDP_PARAM_HEADER_PARAM_LEN(param_header));
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Limit the total size to a reasonable value to avoid allocating too
|
||||||
|
* much memory just of because the flash returned some insane values.
|
||||||
|
*/
|
||||||
|
if (sfdp_size > PAGE_SIZE) {
|
||||||
|
dev_dbg(dev, "SFDP data (%zu) too big, truncating\n",
|
||||||
|
sfdp_size);
|
||||||
|
sfdp_size = PAGE_SIZE;
|
||||||
|
}
|
||||||
|
|
||||||
|
sfdp = devm_kzalloc(dev, sizeof(*sfdp), GFP_KERNEL);
|
||||||
|
if (!sfdp) {
|
||||||
|
err = -ENOMEM;
|
||||||
|
goto exit;
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* The SFDP is organized in chunks of DWORDs. Thus, in theory, the
|
||||||
|
* sfdp_size should be a multiple of DWORDs. But in case a flash
|
||||||
|
* is not spec compliant, make sure that we have enough space to store
|
||||||
|
* the complete SFDP data.
|
||||||
|
*/
|
||||||
|
sfdp->num_dwords = DIV_ROUND_UP(sfdp_size, sizeof(*sfdp->dwords));
|
||||||
|
sfdp->dwords = devm_kcalloc(dev, sfdp->num_dwords,
|
||||||
|
sizeof(*sfdp->dwords), GFP_KERNEL);
|
||||||
|
if (!sfdp->dwords) {
|
||||||
|
err = -ENOMEM;
|
||||||
|
devm_kfree(dev, sfdp);
|
||||||
|
goto exit;
|
||||||
|
}
|
||||||
|
|
||||||
|
err = spi_nor_read_sfdp(nor, 0, sfdp_size, sfdp->dwords);
|
||||||
|
if (err < 0) {
|
||||||
|
dev_dbg(dev, "failed to read SFDP data\n");
|
||||||
|
devm_kfree(dev, sfdp->dwords);
|
||||||
|
devm_kfree(dev, sfdp);
|
||||||
|
goto exit;
|
||||||
|
}
|
||||||
|
|
||||||
|
nor->sfdp = sfdp;
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Check other parameter headers to get the latest revision of
|
* Check other parameter headers to get the latest revision of
|
||||||
* the basic flash parameter table.
|
* the basic flash parameter table.
|
||||||
|
@ -383,6 +383,7 @@ struct spi_nor_flash_parameter;
|
|||||||
* @read_proto: the SPI protocol for read operations
|
* @read_proto: the SPI protocol for read operations
|
||||||
* @write_proto: the SPI protocol for write operations
|
* @write_proto: the SPI protocol for write operations
|
||||||
* @reg_proto: the SPI protocol for read_reg/write_reg/erase operations
|
* @reg_proto: the SPI protocol for read_reg/write_reg/erase operations
|
||||||
|
* @sfdp: the SFDP data of the flash
|
||||||
* @controller_ops: SPI NOR controller driver specific operations.
|
* @controller_ops: SPI NOR controller driver specific operations.
|
||||||
* @params: [FLASH-SPECIFIC] SPI NOR flash parameters and settings.
|
* @params: [FLASH-SPECIFIC] SPI NOR flash parameters and settings.
|
||||||
* The structure includes legacy flash parameters and
|
* The structure includes legacy flash parameters and
|
||||||
@ -412,6 +413,7 @@ struct spi_nor {
|
|||||||
bool sst_write_second;
|
bool sst_write_second;
|
||||||
u32 flags;
|
u32 flags;
|
||||||
enum spi_nor_cmd_ext cmd_ext_type;
|
enum spi_nor_cmd_ext cmd_ext_type;
|
||||||
|
struct sfdp *sfdp;
|
||||||
|
|
||||||
const struct spi_nor_controller_ops *controller_ops;
|
const struct spi_nor_controller_ops *controller_ops;
|
||||||
|
|
||||||
|
Loading…
x
Reference in New Issue
Block a user