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:
Boris Brezillon 2018-08-11 12:19:35 +02:00
commit d0eea5d8db
9 changed files with 62 additions and 23 deletions

View file

@ -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:

View file

@ -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)

View file

@ -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,

View file

@ -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;

View file

@ -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);

View file

@ -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;

View file

@ -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;

View file

@ -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));

View file

@ -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),
};
/**