Core changes:
- Apply reset hacks only when reset is explicitly marked as broken in the DT Driver changes: - Minor cleanup/fixes in the m25p80 driver - Release flash_np in the nxp-spifi driver - Add suspend/resume hooks to the atmel-quadspi driver - Include gpio/consumer.h instead of gpio.h in the atmel-quadspi driver - Use %pK instead of %p in the stm32-quadspi driver - Improve timeout handling in the cadence-quadspi driver - Use mtd_device_register() instead of mtd_device_parse_register() in the intel-spi driver -----BEGIN PGP SIGNATURE----- iQI5BAABCAAjBQJbYWD3HBxib3Jpcy5icmV6aWxsb25AYm9vdGxpbi5jb20ACgkQ Ze02AX4ItwB4lxAAivl1dYSu+tRtQsV6RGnl3mB8RmYF6sIAhwu+cRJLis9ekedA AlCk/MQP1UPsY2MmiVD3akjsVXatm7DZW7SU/lADY5ua0ATQ1BYdQT9GJgFkymwb fvrNd2YsgQgteKiQrt1HpGxT1mP1140G7SuwZPOMcvbECRZ4lES/kSAiRst+2aWN 6Aj+EFcHZWNVz2bHqfzgunV6H/B8o8TghwMk/hlfgNcq17eWMrZhNWRlMRaCdKxK vNwP9E+mVxiudb4BNylkyH2k8+NcPePUCXzOdjC5ePMDjKAD1OOizo+tc63oZb9k DCRP/qodOLKjTFqsxeyET8YEgYQJIEyy+1WVF2PPF2zQewono9zxWpe1yN5dRwG6 MhKuufvzVrAiL/xSYWbmHE4y42MyWF/KrXUN/0zSSrcUCkrA5SyafehBDyJZbLVv +rtr+cjFVYqssIPYq9GmYlPxuyX4kwxAS337hJ00A+NbvB6h7uo+qvHyBR+XZ2YZ mYhrOQCamVoHAt2POZOQqc0692KjaS4naryiuCUwyqnp89HZkUxEDOYlYRCNZz8u SF/uG4obU4En1Lo+JqrBijYQ1qn1FvSGiilagbFnutyZmgTdohi67ImX8tGsgvSN pVc16KiNKVhiiywpUeIQWXUzzqWBKtmU+f3d2eQ+iX/oKZOYtDZneE4nov0= =uNJl -----END PGP SIGNATURE----- Merge tag 'spi-nor/for-4.19' of git://git.infradead.org/linux-mtd into mtd/next Pull SPI NOR updates from Boris Brezillon: " Core changes: - Apply reset hacks only when reset is explicitly marked as broken in the DT Driver changes: - Minor cleanup/fixes in the m25p80 driver - Release flash_np in the nxp-spifi driver - Add suspend/resume hooks to the atmel-quadspi driver - Include gpio/consumer.h instead of gpio.h in the atmel-quadspi driver - Use %pK instead of %p in the stm32-quadspi driver - Improve timeout handling in the cadence-quadspi driver - Use mtd_device_register() instead of mtd_device_parse_register() in the intel-spi driver "
This commit is contained in:
commit
d0eea5d8db
@ -69,6 +69,15 @@ Optional properties:
|
||||
all chips and support for it can not be detected at runtime.
|
||||
Refer to your chips' datasheet to check if this is supported
|
||||
by your chip.
|
||||
- broken-flash-reset : Some flash devices utilize stateful addressing modes
|
||||
(e.g., for 32-bit addressing) which need to be managed
|
||||
carefully by a system. Because these sorts of flash don't
|
||||
have a standardized software reset command, and because some
|
||||
systems don't toggle the flash RESET# pin upon system reset
|
||||
(if the pin even exists at all), there are systems which
|
||||
cannot reboot properly if the flash is left in the "wrong"
|
||||
state. This boolean flag can be used on such systems, to
|
||||
denote the absence of a reliable reset mechanism.
|
||||
|
||||
Example:
|
||||
|
||||
|
@ -28,11 +28,9 @@
|
||||
#include <linux/spi/flash.h>
|
||||
#include <linux/mtd/spi-nor.h>
|
||||
|
||||
#define MAX_CMD_SIZE 6
|
||||
struct m25p {
|
||||
struct spi_mem *spimem;
|
||||
struct spi_nor spi_nor;
|
||||
u8 command[MAX_CMD_SIZE];
|
||||
};
|
||||
|
||||
static int m25p80_read_reg(struct spi_nor *nor, u8 code, u8 *val, int len)
|
||||
@ -70,7 +68,7 @@ static ssize_t m25p80_write(struct spi_nor *nor, loff_t to, size_t len,
|
||||
struct spi_mem_op op =
|
||||
SPI_MEM_OP(SPI_MEM_OP_CMD(nor->program_opcode, 1),
|
||||
SPI_MEM_OP_ADDR(nor->addr_width, to, 1),
|
||||
SPI_MEM_OP_DUMMY(0, 1),
|
||||
SPI_MEM_OP_NO_DUMMY,
|
||||
SPI_MEM_OP_DATA_OUT(len, buf, 1));
|
||||
size_t remaining = len;
|
||||
int ret;
|
||||
@ -78,7 +76,6 @@ static ssize_t m25p80_write(struct spi_nor *nor, loff_t to, size_t len,
|
||||
/* get transfer protocols. */
|
||||
op.cmd.buswidth = spi_nor_get_protocol_inst_nbits(nor->write_proto);
|
||||
op.addr.buswidth = spi_nor_get_protocol_addr_nbits(nor->write_proto);
|
||||
op.dummy.buswidth = op.addr.buswidth;
|
||||
op.data.buswidth = spi_nor_get_protocol_data_nbits(nor->write_proto);
|
||||
|
||||
if (nor->program_opcode == SPINOR_OP_AAI_WP && nor->sst_write_second)
|
||||
|
@ -34,7 +34,7 @@
|
||||
#include <linux/of.h>
|
||||
|
||||
#include <linux/io.h>
|
||||
#include <linux/gpio.h>
|
||||
#include <linux/gpio/consumer.h>
|
||||
|
||||
/* QSPI register offsets */
|
||||
#define QSPI_CR 0x0000 /* Control Register */
|
||||
@ -737,6 +737,26 @@ static int atmel_qspi_remove(struct platform_device *pdev)
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int __maybe_unused atmel_qspi_suspend(struct device *dev)
|
||||
{
|
||||
struct atmel_qspi *aq = dev_get_drvdata(dev);
|
||||
|
||||
clk_disable_unprepare(aq->clk);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int __maybe_unused atmel_qspi_resume(struct device *dev)
|
||||
{
|
||||
struct atmel_qspi *aq = dev_get_drvdata(dev);
|
||||
|
||||
clk_prepare_enable(aq->clk);
|
||||
|
||||
return atmel_qspi_init(aq);
|
||||
}
|
||||
|
||||
static SIMPLE_DEV_PM_OPS(atmel_qspi_pm_ops, atmel_qspi_suspend,
|
||||
atmel_qspi_resume);
|
||||
|
||||
static const struct of_device_id atmel_qspi_dt_ids[] = {
|
||||
{ .compatible = "atmel,sama5d2-qspi" },
|
||||
@ -749,6 +769,7 @@ static struct platform_driver atmel_qspi_driver = {
|
||||
.driver = {
|
||||
.name = "atmel_qspi",
|
||||
.of_match_table = atmel_qspi_dt_ids,
|
||||
.pm = &atmel_qspi_pm_ops,
|
||||
},
|
||||
.probe = atmel_qspi_probe,
|
||||
.remove = atmel_qspi_remove,
|
||||
|
@ -525,15 +525,14 @@ static int cqspi_indirect_read_execute(struct spi_nor *nor, u8 *rxbuf,
|
||||
reg_base + CQSPI_REG_INDIRECTRD);
|
||||
|
||||
while (remaining > 0) {
|
||||
ret = wait_for_completion_timeout(&cqspi->transfer_complete,
|
||||
msecs_to_jiffies
|
||||
(CQSPI_READ_TIMEOUT_MS));
|
||||
if (!wait_for_completion_timeout(&cqspi->transfer_complete,
|
||||
msecs_to_jiffies(CQSPI_READ_TIMEOUT_MS)))
|
||||
ret = -ETIMEDOUT;
|
||||
|
||||
bytes_to_read = cqspi_get_rd_sram_level(cqspi);
|
||||
|
||||
if (!ret && bytes_to_read == 0) {
|
||||
if (ret && bytes_to_read == 0) {
|
||||
dev_err(nor->dev, "Indirect read timeout, no bytes\n");
|
||||
ret = -ETIMEDOUT;
|
||||
goto failrd;
|
||||
}
|
||||
|
||||
@ -649,10 +648,8 @@ static int cqspi_indirect_write_execute(struct spi_nor *nor, loff_t to_addr,
|
||||
iowrite32_rep(cqspi->ahb_base, txbuf,
|
||||
DIV_ROUND_UP(write_bytes, 4));
|
||||
|
||||
ret = wait_for_completion_timeout(&cqspi->transfer_complete,
|
||||
msecs_to_jiffies
|
||||
(CQSPI_TIMEOUT_MS));
|
||||
if (!ret) {
|
||||
if (!wait_for_completion_timeout(&cqspi->transfer_complete,
|
||||
msecs_to_jiffies(CQSPI_TIMEOUT_MS))) {
|
||||
dev_err(nor->dev, "Indirect write timeout\n");
|
||||
ret = -ETIMEDOUT;
|
||||
goto failwr;
|
||||
@ -986,9 +983,8 @@ static int cqspi_direct_read_execute(struct spi_nor *nor, u_char *buf,
|
||||
}
|
||||
|
||||
dma_async_issue_pending(cqspi->rx_chan);
|
||||
ret = wait_for_completion_timeout(&cqspi->rx_dma_complete,
|
||||
msecs_to_jiffies(len));
|
||||
if (ret <= 0) {
|
||||
if (!wait_for_completion_timeout(&cqspi->rx_dma_complete,
|
||||
msecs_to_jiffies(len))) {
|
||||
dmaengine_terminate_sync(cqspi->rx_chan);
|
||||
dev_err(nor->dev, "DMA wait_for_completion_timeout\n");
|
||||
ret = -ETIMEDOUT;
|
||||
|
@ -908,7 +908,7 @@ struct intel_spi *intel_spi_probe(struct device *dev,
|
||||
if (!ispi->writeable || !writeable)
|
||||
ispi->nor.mtd.flags &= ~MTD_WRITEABLE;
|
||||
|
||||
ret = mtd_device_parse_register(&ispi->nor.mtd, NULL, NULL, &part, 1);
|
||||
ret = mtd_device_register(&ispi->nor.mtd, &part, 1);
|
||||
if (ret)
|
||||
return ERR_PTR(ret);
|
||||
|
||||
|
@ -436,6 +436,7 @@ static int nxp_spifi_probe(struct platform_device *pdev)
|
||||
}
|
||||
|
||||
ret = nxp_spifi_setup_flash(spifi, flash_np);
|
||||
of_node_put(flash_np);
|
||||
if (ret) {
|
||||
dev_err(&pdev->dev, "unable to setup flash chip\n");
|
||||
goto dis_clks;
|
||||
|
@ -2757,8 +2757,18 @@ static int spi_nor_init(struct spi_nor *nor)
|
||||
|
||||
if ((nor->addr_width == 4) &&
|
||||
(JEDEC_MFR(nor->info) != SNOR_MFR_SPANSION) &&
|
||||
!(nor->info->flags & SPI_NOR_4B_OPCODES))
|
||||
!(nor->info->flags & SPI_NOR_4B_OPCODES)) {
|
||||
/*
|
||||
* If the RESET# pin isn't hooked up properly, or the system
|
||||
* otherwise doesn't perform a reset command in the boot
|
||||
* sequence, it's impossible to 100% protect against unexpected
|
||||
* reboots (e.g., crashes). Warn the user (or hopefully, system
|
||||
* designer) that this is bad.
|
||||
*/
|
||||
WARN_ONCE(nor->flags & SNOR_F_BROKEN_RESET,
|
||||
"enabling reset hack; may not recover from unexpected reboots\n");
|
||||
set_4byte(nor, nor->info, 1);
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
@ -2781,7 +2791,8 @@ void spi_nor_restore(struct spi_nor *nor)
|
||||
/* restore the addressing mode */
|
||||
if ((nor->addr_width == 4) &&
|
||||
(JEDEC_MFR(nor->info) != SNOR_MFR_SPANSION) &&
|
||||
!(nor->info->flags & SPI_NOR_4B_OPCODES))
|
||||
!(nor->info->flags & SPI_NOR_4B_OPCODES) &&
|
||||
(nor->flags & SNOR_F_BROKEN_RESET))
|
||||
set_4byte(nor, nor->info, 0);
|
||||
}
|
||||
EXPORT_SYMBOL_GPL(spi_nor_restore);
|
||||
@ -2911,6 +2922,9 @@ int spi_nor_scan(struct spi_nor *nor, const char *name,
|
||||
params.hwcaps.mask |= SNOR_HWCAPS_READ_FAST;
|
||||
}
|
||||
|
||||
if (of_property_read_bool(np, "broken-flash-reset"))
|
||||
nor->flags |= SNOR_F_BROKEN_RESET;
|
||||
|
||||
/* Some devices cannot do fast-read, no matter what DT tells us */
|
||||
if (info->flags & SPI_NOR_NO_FR)
|
||||
params.hwcaps.mask &= ~SNOR_HWCAPS_READ_FAST;
|
||||
|
@ -355,7 +355,7 @@ static int stm32_qspi_read_reg(struct spi_nor *nor,
|
||||
struct device *dev = flash->qspi->dev;
|
||||
struct stm32_qspi_cmd cmd;
|
||||
|
||||
dev_dbg(dev, "read_reg: cmd:%#.2x buf:%p len:%#x\n", opcode, buf, len);
|
||||
dev_dbg(dev, "read_reg: cmd:%#.2x buf:%pK len:%#x\n", opcode, buf, len);
|
||||
|
||||
memset(&cmd, 0, sizeof(cmd));
|
||||
cmd.opcode = opcode;
|
||||
@ -376,7 +376,7 @@ static int stm32_qspi_write_reg(struct spi_nor *nor, u8 opcode,
|
||||
struct device *dev = flash->qspi->dev;
|
||||
struct stm32_qspi_cmd cmd;
|
||||
|
||||
dev_dbg(dev, "write_reg: cmd:%#.2x buf:%p len:%#x\n", opcode, buf, len);
|
||||
dev_dbg(dev, "write_reg: cmd:%#.2x buf:%pK len:%#x\n", opcode, buf, len);
|
||||
|
||||
memset(&cmd, 0, sizeof(cmd));
|
||||
cmd.opcode = opcode;
|
||||
@ -398,7 +398,7 @@ static ssize_t stm32_qspi_read(struct spi_nor *nor, loff_t from, size_t len,
|
||||
struct stm32_qspi_cmd cmd;
|
||||
int err;
|
||||
|
||||
dev_dbg(qspi->dev, "read(%#.2x): buf:%p from:%#.8x len:%#zx\n",
|
||||
dev_dbg(qspi->dev, "read(%#.2x): buf:%pK from:%#.8x len:%#zx\n",
|
||||
nor->read_opcode, buf, (u32)from, len);
|
||||
|
||||
memset(&cmd, 0, sizeof(cmd));
|
||||
|
@ -235,6 +235,7 @@ enum spi_nor_option_flags {
|
||||
SNOR_F_S3AN_ADDR_DEFAULT = BIT(3),
|
||||
SNOR_F_READY_XSR_RDY = BIT(4),
|
||||
SNOR_F_USE_CLSR = BIT(5),
|
||||
SNOR_F_BROKEN_RESET = BIT(6),
|
||||
};
|
||||
|
||||
/**
|
||||
|
Loading…
Reference in New Issue
Block a user