mirror of
https://github.com/torvalds/linux.git
synced 2024-12-04 01:51:34 +00:00
SPI NOR core changes:
- Disable Quad Mode in spi_nor_restore(). - Don't abort BFPT parsing when QER reserved value is used. - Add support/update capabilities for few flashes. - Drop s70fl01gs flash: it does not support RDSR(05h) which is critical for erase/write. - Merge the SPIMEM DTR bits in spi-nor/next to avoid conflicts during the release cycle. SPI NOR controller drivers changes: - Move the cadence-quadspi driver to spi-mem. The series was taken through the SPI tree. Merge it also in spi-nor/next to avoid conflicts during the release cycle. - intel-spi: - Add new PCI IDs. - Ignore the Write Disable command, the controller doesn't support it. - Fix performance regression. -----BEGIN PGP SIGNATURE----- iQEzBAABCgAdFiEEHUIqys8OyG1eHf7fS1VPR6WNFOkFAl8f/IUACgkQS1VPR6WN FOk8nQf/ReDFzgrZGPRXK8MbcWdmrNQo5cGwCs2zuKskvWMdgNZC92DTlgrMmx+d NQ/0PpsOHZJ1bcPjlsxccSQNrFnSzxr91n8NJIQ6DuralCN+x9Zh4dtox0Q0WB1x d9y+I65EpSyEHRhWRW1y2sq5xRlwiANWVQPfIUN10q/flz9CI5Q8gY8wdUQT4Q5x /ER7CMSbZSehnxHnJ9kSFDRhJCobDKnOdsFLDVZFPseQZzXYe5zP0J/T5S63wem2 /QFKSCfcI4UqMbeurGpQok9ZywCUp+SUG2mAld/yTig+YCCeY1Dp45IGJZ7eKDky NPYjVYaRlvWwcTgS1OdCThGd+F29Ug== =YZOZ -----END PGP SIGNATURE----- Merge tag 'spi-nor/for-5.9' of https://git.kernel.org/pub/scm/linux/kernel/git/mtd/linux into mtd/next SPI NOR core changes: - Disable Quad Mode in spi_nor_restore(). - Don't abort BFPT parsing when QER reserved value is used. - Add support/update capabilities for few flashes. - Drop s70fl01gs flash: it does not support RDSR(05h) which is critical for erase/write. - Merge the SPIMEM DTR bits in spi-nor/next to avoid conflicts during the release cycle. SPI NOR controller drivers changes: - Move the cadence-quadspi driver to spi-mem. The series was taken through the SPI tree. Merge it also in spi-nor/next to avoid conflicts during the release cycle. - intel-spi: - Add new PCI IDs. - Ignore the Write Disable command, the controller doesn't support it. - Fix performance regression.
This commit is contained in:
commit
cb413909ae
@ -9,17 +9,6 @@ config SPI_ASPEED_SMC
|
||||
and support for the SPI flash memory controller (SPI) for
|
||||
the host firmware. The implementation only supports SPI NOR.
|
||||
|
||||
config SPI_CADENCE_QUADSPI
|
||||
tristate "Cadence Quad SPI controller"
|
||||
depends on OF && (ARM || ARM64 || COMPILE_TEST)
|
||||
help
|
||||
Enable support for the Cadence Quad SPI Flash controller.
|
||||
|
||||
Cadence QSPI is a specialized controller for connecting an SPI
|
||||
Flash over 1/2/4-bit wide bus. Enable this option if you have a
|
||||
device with a Cadence QSPI controller and want to access the
|
||||
Flash as an MTD device.
|
||||
|
||||
config SPI_HISI_SFC
|
||||
tristate "Hisilicon FMC SPI NOR Flash Controller(SFC)"
|
||||
depends on ARCH_HISI || COMPILE_TEST
|
||||
|
@ -1,6 +1,5 @@
|
||||
# SPDX-License-Identifier: GPL-2.0
|
||||
obj-$(CONFIG_SPI_ASPEED_SMC) += aspeed-smc.o
|
||||
obj-$(CONFIG_SPI_CADENCE_QUADSPI) += cadence-quadspi.o
|
||||
obj-$(CONFIG_SPI_HISI_SFC) += hisi-sfc.o
|
||||
obj-$(CONFIG_SPI_NXP_SPIFI) += nxp-spifi.o
|
||||
obj-$(CONFIG_SPI_INTEL_SPI) += intel-spi.o
|
||||
|
@ -68,7 +68,9 @@ static const struct pci_device_id intel_spi_pci_ids[] = {
|
||||
{ PCI_VDEVICE(INTEL, 0x06a4), (unsigned long)&bxt_info },
|
||||
{ PCI_VDEVICE(INTEL, 0x18e0), (unsigned long)&bxt_info },
|
||||
{ PCI_VDEVICE(INTEL, 0x19e0), (unsigned long)&bxt_info },
|
||||
{ PCI_VDEVICE(INTEL, 0x1bca), (unsigned long)&bxt_info },
|
||||
{ PCI_VDEVICE(INTEL, 0x34a4), (unsigned long)&bxt_info },
|
||||
{ PCI_VDEVICE(INTEL, 0x43a4), (unsigned long)&cnl_info },
|
||||
{ PCI_VDEVICE(INTEL, 0x4b24), (unsigned long)&bxt_info },
|
||||
{ PCI_VDEVICE(INTEL, 0x4da4), (unsigned long)&bxt_info },
|
||||
{ PCI_VDEVICE(INTEL, 0xa0a4), (unsigned long)&bxt_info },
|
||||
|
@ -292,7 +292,7 @@ static int intel_spi_wait_hw_busy(struct intel_spi *ispi)
|
||||
u32 val;
|
||||
|
||||
return readl_poll_timeout(ispi->base + HSFSTS_CTL, val,
|
||||
!(val & HSFSTS_CTL_SCIP), 40,
|
||||
!(val & HSFSTS_CTL_SCIP), 0,
|
||||
INTEL_SPI_TIMEOUT * 1000);
|
||||
}
|
||||
|
||||
@ -301,7 +301,7 @@ static int intel_spi_wait_sw_busy(struct intel_spi *ispi)
|
||||
u32 val;
|
||||
|
||||
return readl_poll_timeout(ispi->sregs + SSFSTS_CTL, val,
|
||||
!(val & SSFSTS_CTL_SCIP), 40,
|
||||
!(val & SSFSTS_CTL_SCIP), 0,
|
||||
INTEL_SPI_TIMEOUT * 1000);
|
||||
}
|
||||
|
||||
@ -612,6 +612,15 @@ static int intel_spi_write_reg(struct spi_nor *nor, u8 opcode, const u8 *buf,
|
||||
return 0;
|
||||
}
|
||||
|
||||
/*
|
||||
* We hope that HW sequencer will do the right thing automatically and
|
||||
* with the SW sequencer we cannot use preopcode anyway, so just ignore
|
||||
* the Write Disable operation and pretend it was completed
|
||||
* successfully.
|
||||
*/
|
||||
if (opcode == SPINOR_OP_WRDI)
|
||||
return 0;
|
||||
|
||||
writel(0, ispi->base + FADDR);
|
||||
|
||||
/* Write the value beforehand */
|
||||
|
@ -1907,15 +1907,16 @@ static int spi_nor_is_locked(struct mtd_info *mtd, loff_t ofs, uint64_t len)
|
||||
}
|
||||
|
||||
/**
|
||||
* spi_nor_sr1_bit6_quad_enable() - Set the Quad Enable BIT(6) in the Status
|
||||
* Register 1.
|
||||
* spi_nor_sr1_bit6_quad_enable() - Set/Unset the Quad Enable BIT(6) in the
|
||||
* Status Register 1.
|
||||
* @nor: pointer to a 'struct spi_nor'
|
||||
* @enable: true to enable Quad mode, false to disable Quad mode.
|
||||
*
|
||||
* Bit 6 of the Status Register 1 is the QE bit for Macronix like QSPI memories.
|
||||
*
|
||||
* Return: 0 on success, -errno otherwise.
|
||||
*/
|
||||
int spi_nor_sr1_bit6_quad_enable(struct spi_nor *nor)
|
||||
int spi_nor_sr1_bit6_quad_enable(struct spi_nor *nor, bool enable)
|
||||
{
|
||||
int ret;
|
||||
|
||||
@ -1923,45 +1924,56 @@ int spi_nor_sr1_bit6_quad_enable(struct spi_nor *nor)
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
if (nor->bouncebuf[0] & SR1_QUAD_EN_BIT6)
|
||||
if ((enable && (nor->bouncebuf[0] & SR1_QUAD_EN_BIT6)) ||
|
||||
(!enable && !(nor->bouncebuf[0] & SR1_QUAD_EN_BIT6)))
|
||||
return 0;
|
||||
|
||||
nor->bouncebuf[0] |= SR1_QUAD_EN_BIT6;
|
||||
if (enable)
|
||||
nor->bouncebuf[0] |= SR1_QUAD_EN_BIT6;
|
||||
else
|
||||
nor->bouncebuf[0] &= ~SR1_QUAD_EN_BIT6;
|
||||
|
||||
return spi_nor_write_sr1_and_check(nor, nor->bouncebuf[0]);
|
||||
}
|
||||
|
||||
/**
|
||||
* spi_nor_sr2_bit1_quad_enable() - set the Quad Enable BIT(1) in the Status
|
||||
* Register 2.
|
||||
* spi_nor_sr2_bit1_quad_enable() - set/unset the Quad Enable BIT(1) in the
|
||||
* Status Register 2.
|
||||
* @nor: pointer to a 'struct spi_nor'.
|
||||
* @enable: true to enable Quad mode, false to disable Quad mode.
|
||||
*
|
||||
* Bit 1 of the Status Register 2 is the QE bit for Spansion like QSPI memories.
|
||||
*
|
||||
* Return: 0 on success, -errno otherwise.
|
||||
*/
|
||||
int spi_nor_sr2_bit1_quad_enable(struct spi_nor *nor)
|
||||
int spi_nor_sr2_bit1_quad_enable(struct spi_nor *nor, bool enable)
|
||||
{
|
||||
int ret;
|
||||
|
||||
if (nor->flags & SNOR_F_NO_READ_CR)
|
||||
return spi_nor_write_16bit_cr_and_check(nor, SR2_QUAD_EN_BIT1);
|
||||
return spi_nor_write_16bit_cr_and_check(nor,
|
||||
enable ? SR2_QUAD_EN_BIT1 : 0);
|
||||
|
||||
ret = spi_nor_read_cr(nor, nor->bouncebuf);
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
if (nor->bouncebuf[0] & SR2_QUAD_EN_BIT1)
|
||||
if ((enable && (nor->bouncebuf[0] & SR2_QUAD_EN_BIT1)) ||
|
||||
(!enable && !(nor->bouncebuf[0] & SR2_QUAD_EN_BIT1)))
|
||||
return 0;
|
||||
|
||||
nor->bouncebuf[0] |= SR2_QUAD_EN_BIT1;
|
||||
if (enable)
|
||||
nor->bouncebuf[0] |= SR2_QUAD_EN_BIT1;
|
||||
else
|
||||
nor->bouncebuf[0] &= ~SR2_QUAD_EN_BIT1;
|
||||
|
||||
return spi_nor_write_16bit_cr_and_check(nor, nor->bouncebuf[0]);
|
||||
}
|
||||
|
||||
/**
|
||||
* spi_nor_sr2_bit7_quad_enable() - set QE bit in Status Register 2.
|
||||
* spi_nor_sr2_bit7_quad_enable() - set/unset QE bit in Status Register 2.
|
||||
* @nor: pointer to a 'struct spi_nor'
|
||||
* @enable: true to enable Quad mode, false to disable Quad mode.
|
||||
*
|
||||
* Set the Quad Enable (QE) bit in the Status Register 2.
|
||||
*
|
||||
@ -1971,7 +1983,7 @@ int spi_nor_sr2_bit1_quad_enable(struct spi_nor *nor)
|
||||
*
|
||||
* Return: 0 on success, -errno otherwise.
|
||||
*/
|
||||
int spi_nor_sr2_bit7_quad_enable(struct spi_nor *nor)
|
||||
int spi_nor_sr2_bit7_quad_enable(struct spi_nor *nor, bool enable)
|
||||
{
|
||||
u8 *sr2 = nor->bouncebuf;
|
||||
int ret;
|
||||
@ -1981,11 +1993,15 @@ int spi_nor_sr2_bit7_quad_enable(struct spi_nor *nor)
|
||||
ret = spi_nor_read_sr2(nor, sr2);
|
||||
if (ret)
|
||||
return ret;
|
||||
if (*sr2 & SR2_QUAD_EN_BIT7)
|
||||
if ((enable && (*sr2 & SR2_QUAD_EN_BIT7)) ||
|
||||
(!enable && !(*sr2 & SR2_QUAD_EN_BIT7)))
|
||||
return 0;
|
||||
|
||||
/* Update the Quad Enable bit. */
|
||||
*sr2 |= SR2_QUAD_EN_BIT7;
|
||||
if (enable)
|
||||
*sr2 |= SR2_QUAD_EN_BIT7;
|
||||
else
|
||||
*sr2 &= ~SR2_QUAD_EN_BIT7;
|
||||
|
||||
ret = spi_nor_write_sr2(nor, sr2);
|
||||
if (ret)
|
||||
@ -2898,12 +2914,13 @@ static int spi_nor_init_params(struct spi_nor *nor)
|
||||
}
|
||||
|
||||
/**
|
||||
* spi_nor_quad_enable() - enable Quad I/O if needed.
|
||||
* spi_nor_quad_enable() - enable/disable Quad I/O if needed.
|
||||
* @nor: pointer to a 'struct spi_nor'
|
||||
* @enable: true to enable Quad mode. false to disable Quad mode.
|
||||
*
|
||||
* Return: 0 on success, -errno otherwise.
|
||||
*/
|
||||
static int spi_nor_quad_enable(struct spi_nor *nor)
|
||||
static int spi_nor_quad_enable(struct spi_nor *nor, bool enable)
|
||||
{
|
||||
if (!nor->params->quad_enable)
|
||||
return 0;
|
||||
@ -2912,7 +2929,7 @@ static int spi_nor_quad_enable(struct spi_nor *nor)
|
||||
spi_nor_get_protocol_width(nor->write_proto) == 4))
|
||||
return 0;
|
||||
|
||||
return nor->params->quad_enable(nor);
|
||||
return nor->params->quad_enable(nor, enable);
|
||||
}
|
||||
|
||||
/**
|
||||
@ -2936,7 +2953,7 @@ static int spi_nor_init(struct spi_nor *nor)
|
||||
{
|
||||
int err;
|
||||
|
||||
err = spi_nor_quad_enable(nor);
|
||||
err = spi_nor_quad_enable(nor, true);
|
||||
if (err) {
|
||||
dev_dbg(nor->dev, "quad mode not supported\n");
|
||||
return err;
|
||||
@ -2983,6 +3000,8 @@ void spi_nor_restore(struct spi_nor *nor)
|
||||
if (nor->addr_width == 4 && !(nor->flags & SNOR_F_4B_OPCODES) &&
|
||||
nor->flags & SNOR_F_BROKEN_RESET)
|
||||
nor->params->set_4byte_addr_mode(nor, false);
|
||||
|
||||
spi_nor_quad_enable(nor, false);
|
||||
}
|
||||
EXPORT_SYMBOL_GPL(spi_nor_restore);
|
||||
|
||||
|
@ -198,7 +198,7 @@ struct spi_nor_locking_ops {
|
||||
* higher index in the array, the higher priority.
|
||||
* @erase_map: the erase map parsed from the SFDP Sector Map Parameter
|
||||
* Table.
|
||||
* @quad_enable: enables SPI NOR quad mode.
|
||||
* @quad_enable: enables/disables SPI NOR Quad mode.
|
||||
* @set_4byte_addr_mode: puts the SPI NOR in 4 byte addressing mode.
|
||||
* @convert_addr: converts an absolute address into something the flash
|
||||
* will understand. Particularly useful when pagesize is
|
||||
@ -219,7 +219,7 @@ struct spi_nor_flash_parameter {
|
||||
|
||||
struct spi_nor_erase_map erase_map;
|
||||
|
||||
int (*quad_enable)(struct spi_nor *nor);
|
||||
int (*quad_enable)(struct spi_nor *nor, bool enable);
|
||||
int (*set_4byte_addr_mode)(struct spi_nor *nor, bool enable);
|
||||
u32 (*convert_addr)(struct spi_nor *nor, u32 addr);
|
||||
int (*setup)(struct spi_nor *nor, const struct spi_nor_hwcaps *hwcaps);
|
||||
@ -406,9 +406,9 @@ int spi_nor_write_ear(struct spi_nor *nor, u8 ear);
|
||||
int spi_nor_wait_till_ready(struct spi_nor *nor);
|
||||
int spi_nor_lock_and_prep(struct spi_nor *nor);
|
||||
void spi_nor_unlock_and_unprep(struct spi_nor *nor);
|
||||
int spi_nor_sr1_bit6_quad_enable(struct spi_nor *nor);
|
||||
int spi_nor_sr2_bit1_quad_enable(struct spi_nor *nor);
|
||||
int spi_nor_sr2_bit7_quad_enable(struct spi_nor *nor);
|
||||
int spi_nor_sr1_bit6_quad_enable(struct spi_nor *nor, bool enable);
|
||||
int spi_nor_sr2_bit1_quad_enable(struct spi_nor *nor, bool enable);
|
||||
int spi_nor_sr2_bit7_quad_enable(struct spi_nor *nor, bool enable);
|
||||
|
||||
int spi_nor_xread_sr(struct spi_nor *nor, u8 *sr);
|
||||
ssize_t spi_nor_read_data(struct spi_nor *nor, loff_t from, size_t len,
|
||||
|
@ -52,6 +52,9 @@ static const struct flash_info macronix_parts[] = {
|
||||
{ "mx25u6435f", INFO(0xc22537, 0, 64 * 1024, 128, SECT_4K) },
|
||||
{ "mx25l12805d", INFO(0xc22018, 0, 64 * 1024, 256, 0) },
|
||||
{ "mx25l12855e", INFO(0xc22618, 0, 64 * 1024, 256, 0) },
|
||||
{ "mx25r1635f", INFO(0xc22815, 0, 64 * 1024, 32,
|
||||
SECT_4K | SPI_NOR_DUAL_READ |
|
||||
SPI_NOR_QUAD_READ) },
|
||||
{ "mx25r3235f", INFO(0xc22816, 0, 64 * 1024, 64,
|
||||
SECT_4K | SPI_NOR_DUAL_READ |
|
||||
SPI_NOR_QUAD_READ) },
|
||||
@ -84,6 +87,9 @@ static const struct flash_info macronix_parts[] = {
|
||||
SPI_NOR_QUAD_READ) },
|
||||
{ "mx66l1g55g", INFO(0xc2261b, 0, 64 * 1024, 2048,
|
||||
SPI_NOR_QUAD_READ) },
|
||||
{ "mx66u2g45g", INFO(0xc2253c, 0, 64 * 1024, 4096,
|
||||
SECT_4K | SPI_NOR_DUAL_READ |
|
||||
SPI_NOR_QUAD_READ | SPI_NOR_4B_OPCODES) },
|
||||
};
|
||||
|
||||
static void macronix_default_init(struct spi_nor *nor)
|
||||
|
@ -71,8 +71,8 @@ static const struct flash_info st_parts[] = {
|
||||
SECT_4K | USE_FSR | SPI_NOR_QUAD_READ |
|
||||
NO_CHIP_ERASE) },
|
||||
{ "mt25qu02g", INFO(0x20bb22, 0, 64 * 1024, 4096,
|
||||
SECT_4K | USE_FSR | SPI_NOR_QUAD_READ |
|
||||
NO_CHIP_ERASE) },
|
||||
SECT_4K | USE_FSR | SPI_NOR_DUAL_READ |
|
||||
SPI_NOR_QUAD_READ | NO_CHIP_ERASE) },
|
||||
|
||||
{ "m25p05", INFO(0x202010, 0, 32 * 1024, 2, 0) },
|
||||
{ "m25p10", INFO(0x202011, 0, 32 * 1024, 4, 0) },
|
||||
|
@ -598,7 +598,8 @@ static int spi_nor_parse_bfpt(struct spi_nor *nor,
|
||||
break;
|
||||
|
||||
default:
|
||||
return -EINVAL;
|
||||
dev_dbg(nor->dev, "BFPT QER reserved value used\n");
|
||||
break;
|
||||
}
|
||||
|
||||
/* Stop here if not JESD216 rev C or later. */
|
||||
|
@ -64,7 +64,6 @@ static const struct flash_info spansion_parts[] = {
|
||||
{ "s25fs512s", INFO6(0x010220, 0x4d0081, 256 * 1024, 256,
|
||||
SPI_NOR_DUAL_READ | SPI_NOR_QUAD_READ | USE_CLSR)
|
||||
.fixups = &s25fs_s_fixups, },
|
||||
{ "s70fl01gs", INFO(0x010221, 0x4d00, 256 * 1024, 256, 0) },
|
||||
{ "s25sl12800", INFO(0x012018, 0x0300, 256 * 1024, 64, 0) },
|
||||
{ "s25sl12801", INFO(0x012018, 0x0301, 64 * 1024, 256, 0) },
|
||||
{ "s25fl129p0", INFO(0x012018, 0x4d00, 256 * 1024, 64,
|
||||
@ -84,7 +83,8 @@ static const struct flash_info spansion_parts[] = {
|
||||
SECT_4K | SPI_NOR_DUAL_READ | SPI_NOR_QUAD_READ) },
|
||||
{ "s25fl016k", INFO(0xef4015, 0, 64 * 1024, 32,
|
||||
SECT_4K | SPI_NOR_DUAL_READ | SPI_NOR_QUAD_READ) },
|
||||
{ "s25fl064k", INFO(0xef4017, 0, 64 * 1024, 128, SECT_4K) },
|
||||
{ "s25fl064k", INFO(0xef4017, 0, 64 * 1024, 128,
|
||||
SECT_4K | SPI_NOR_DUAL_READ | SPI_NOR_QUAD_READ) },
|
||||
{ "s25fl116k", INFO(0x014015, 0, 64 * 1024, 32,
|
||||
SECT_4K | SPI_NOR_DUAL_READ | SPI_NOR_QUAD_READ) },
|
||||
{ "s25fl132k", INFO(0x014016, 0, 64 * 1024, 64, SECT_4K) },
|
||||
|
@ -64,10 +64,12 @@ static const struct flash_info winbond_parts[] = {
|
||||
SECT_4K | SPI_NOR_DUAL_READ | SPI_NOR_QUAD_READ |
|
||||
SPI_NOR_HAS_LOCK | SPI_NOR_HAS_TB) },
|
||||
{ "w25x64", INFO(0xef3017, 0, 64 * 1024, 128, SECT_4K) },
|
||||
{ "w25q64", INFO(0xef4017, 0, 64 * 1024, 128, SECT_4K) },
|
||||
{ "w25q64", INFO(0xef4017, 0, 64 * 1024, 128,
|
||||
SECT_4K | SPI_NOR_DUAL_READ | SPI_NOR_QUAD_READ) },
|
||||
{ "w25q64dw", INFO(0xef6017, 0, 64 * 1024, 128,
|
||||
SECT_4K | SPI_NOR_DUAL_READ | SPI_NOR_QUAD_READ |
|
||||
SPI_NOR_HAS_LOCK | SPI_NOR_HAS_TB) },
|
||||
{ "w25q64jvm", INFO(0xef7017, 0, 64 * 1024, 128, SECT_4K) },
|
||||
{ "w25q128fw", INFO(0xef6018, 0, 64 * 1024, 256,
|
||||
SECT_4K | SPI_NOR_DUAL_READ | SPI_NOR_QUAD_READ |
|
||||
SPI_NOR_HAS_LOCK | SPI_NOR_HAS_TB) },
|
||||
|
@ -200,6 +200,17 @@ config SPI_CADENCE
|
||||
This selects the Cadence SPI controller master driver
|
||||
used by Xilinx Zynq and ZynqMP.
|
||||
|
||||
config SPI_CADENCE_QUADSPI
|
||||
tristate "Cadence Quad SPI controller"
|
||||
depends on OF && (ARM || ARM64 || COMPILE_TEST)
|
||||
help
|
||||
Enable support for the Cadence Quad SPI Flash controller.
|
||||
|
||||
Cadence QSPI is a specialized controller for connecting an SPI
|
||||
Flash over 1/2/4-bit wide bus. Enable this option if you have a
|
||||
device with a Cadence QSPI controller and want to access the
|
||||
Flash as an MTD device.
|
||||
|
||||
config SPI_CLPS711X
|
||||
tristate "CLPS711X host SPI controller"
|
||||
depends on ARCH_CLPS711X || COMPILE_TEST
|
||||
|
@ -31,6 +31,7 @@ obj-$(CONFIG_SPI_BCM_QSPI) += spi-iproc-qspi.o spi-brcmstb-qspi.o spi-bcm-qspi.
|
||||
obj-$(CONFIG_SPI_BITBANG) += spi-bitbang.o
|
||||
obj-$(CONFIG_SPI_BUTTERFLY) += spi-butterfly.o
|
||||
obj-$(CONFIG_SPI_CADENCE) += spi-cadence.o
|
||||
obj-$(CONFIG_SPI_CADENCE_QUADSPI) += spi-cadence-quadspi.o
|
||||
obj-$(CONFIG_SPI_CLPS711X) += spi-clps711x.o
|
||||
obj-$(CONFIG_SPI_COLDFIRE_QSPI) += spi-coldfire-qspi.o
|
||||
obj-$(CONFIG_SPI_DAVINCI) += spi-davinci.o
|
||||
|
@ -285,6 +285,12 @@ static bool atmel_qspi_supports_op(struct spi_mem *mem,
|
||||
op->dummy.nbytes == 0)
|
||||
return false;
|
||||
|
||||
/* DTR ops not supported. */
|
||||
if (op->cmd.dtr || op->addr.dtr || op->dummy.dtr || op->data.dtr)
|
||||
return false;
|
||||
if (op->cmd.nbytes != 1)
|
||||
return false;
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
|
File diff suppressed because it is too large
Load Diff
@ -156,6 +156,12 @@ bool spi_mem_default_supports_op(struct spi_mem *mem,
|
||||
op->data.dir == SPI_MEM_DATA_OUT))
|
||||
return false;
|
||||
|
||||
if (op->cmd.dtr || op->addr.dtr || op->dummy.dtr || op->data.dtr)
|
||||
return false;
|
||||
|
||||
if (op->cmd.nbytes != 1)
|
||||
return false;
|
||||
|
||||
return true;
|
||||
}
|
||||
EXPORT_SYMBOL_GPL(spi_mem_default_supports_op);
|
||||
@ -170,7 +176,7 @@ static bool spi_mem_buswidth_is_valid(u8 buswidth)
|
||||
|
||||
static int spi_mem_check_op(const struct spi_mem_op *op)
|
||||
{
|
||||
if (!op->cmd.buswidth)
|
||||
if (!op->cmd.buswidth || !op->cmd.nbytes)
|
||||
return -EINVAL;
|
||||
|
||||
if ((op->addr.nbytes && !op->addr.buswidth) ||
|
||||
@ -306,8 +312,7 @@ int spi_mem_exec_op(struct spi_mem *mem, const struct spi_mem_op *op)
|
||||
return ret;
|
||||
}
|
||||
|
||||
tmpbufsize = sizeof(op->cmd.opcode) + op->addr.nbytes +
|
||||
op->dummy.nbytes;
|
||||
tmpbufsize = op->cmd.nbytes + op->addr.nbytes + op->dummy.nbytes;
|
||||
|
||||
/*
|
||||
* Allocate a buffer to transmit the CMD, ADDR cycles with kmalloc() so
|
||||
@ -322,7 +327,7 @@ int spi_mem_exec_op(struct spi_mem *mem, const struct spi_mem_op *op)
|
||||
|
||||
tmpbuf[0] = op->cmd.opcode;
|
||||
xfers[xferpos].tx_buf = tmpbuf;
|
||||
xfers[xferpos].len = sizeof(op->cmd.opcode);
|
||||
xfers[xferpos].len = op->cmd.nbytes;
|
||||
xfers[xferpos].tx_nbits = op->cmd.buswidth;
|
||||
spi_message_add_tail(&xfers[xferpos], &msg);
|
||||
xferpos++;
|
||||
@ -424,8 +429,7 @@ int spi_mem_adjust_op_size(struct spi_mem *mem, struct spi_mem_op *op)
|
||||
return ctlr->mem_ops->adjust_op_size(mem, op);
|
||||
|
||||
if (!ctlr->mem_ops || !ctlr->mem_ops->exec_op) {
|
||||
len = sizeof(op->cmd.opcode) + op->addr.nbytes +
|
||||
op->dummy.nbytes;
|
||||
len = op->cmd.nbytes + op->addr.nbytes + op->dummy.nbytes;
|
||||
|
||||
if (len > spi_max_transfer_size(mem->spi))
|
||||
return -EINVAL;
|
||||
|
@ -195,7 +195,7 @@ static int mtk_nor_adjust_op_size(struct spi_mem *mem, struct spi_mem_op *op)
|
||||
}
|
||||
}
|
||||
|
||||
len = MTK_NOR_PRG_MAX_SIZE - sizeof(op->cmd.opcode) - op->addr.nbytes -
|
||||
len = MTK_NOR_PRG_MAX_SIZE - op->cmd.nbytes - op->addr.nbytes -
|
||||
op->dummy.nbytes;
|
||||
if (op->data.nbytes > len)
|
||||
op->data.nbytes = len;
|
||||
@ -211,6 +211,12 @@ static bool mtk_nor_supports_op(struct spi_mem *mem,
|
||||
if (op->cmd.buswidth != 1)
|
||||
return false;
|
||||
|
||||
/* DTR ops not supported. */
|
||||
if (op->cmd.dtr || op->addr.dtr || op->dummy.dtr || op->data.dtr)
|
||||
return false;
|
||||
if (op->cmd.nbytes != 1)
|
||||
return false;
|
||||
|
||||
if ((op->addr.nbytes == 3) || (op->addr.nbytes == 4)) {
|
||||
if ((op->data.dir == SPI_MEM_DATA_IN) && mtk_nor_match_read(op))
|
||||
return true;
|
||||
@ -219,7 +225,7 @@ static bool mtk_nor_supports_op(struct spi_mem *mem,
|
||||
(op->dummy.buswidth == 0) &&
|
||||
(op->data.buswidth == 1);
|
||||
}
|
||||
len = sizeof(op->cmd.opcode) + op->addr.nbytes + op->dummy.nbytes;
|
||||
len = op->cmd.nbytes + op->addr.nbytes + op->dummy.nbytes;
|
||||
if ((len > MTK_NOR_PRG_MAX_SIZE) ||
|
||||
((op->data.nbytes) && (len == MTK_NOR_PRG_MAX_SIZE)))
|
||||
return false;
|
||||
|
@ -356,6 +356,7 @@ static int mxic_spi_mem_exec_op(struct spi_mem *mem,
|
||||
int nio = 1, i, ret;
|
||||
u32 ss_ctrl;
|
||||
u8 addr[8];
|
||||
u8 opcode = op->cmd.opcode;
|
||||
|
||||
ret = mxic_spi_set_freq(mxic, mem->spi->max_speed_hz);
|
||||
if (ret)
|
||||
@ -393,7 +394,7 @@ static int mxic_spi_mem_exec_op(struct spi_mem *mem,
|
||||
writel(readl(mxic->regs + HC_CFG) | HC_CFG_MAN_CS_ASSERT,
|
||||
mxic->regs + HC_CFG);
|
||||
|
||||
ret = mxic_spi_data_xfer(mxic, &op->cmd.opcode, NULL, 1);
|
||||
ret = mxic_spi_data_xfer(mxic, &opcode, NULL, 1);
|
||||
if (ret)
|
||||
goto out;
|
||||
|
||||
|
@ -527,20 +527,21 @@ static int zynq_qspi_exec_mem_op(struct spi_mem *mem,
|
||||
struct zynq_qspi *xqspi = spi_controller_get_devdata(mem->spi->master);
|
||||
int err = 0, i;
|
||||
u8 *tmpbuf;
|
||||
u8 opcode = op->cmd.opcode;
|
||||
|
||||
dev_dbg(xqspi->dev, "cmd:%#x mode:%d.%d.%d.%d\n",
|
||||
op->cmd.opcode, op->cmd.buswidth, op->addr.buswidth,
|
||||
opcode, op->cmd.buswidth, op->addr.buswidth,
|
||||
op->dummy.buswidth, op->data.buswidth);
|
||||
|
||||
zynq_qspi_chipselect(mem->spi, true);
|
||||
zynq_qspi_config_op(xqspi, mem->spi);
|
||||
|
||||
if (op->cmd.opcode) {
|
||||
if (op->cmd.nbytes) {
|
||||
reinit_completion(&xqspi->data_completion);
|
||||
xqspi->txbuf = (u8 *)&op->cmd.opcode;
|
||||
xqspi->txbuf = &opcode;
|
||||
xqspi->rxbuf = NULL;
|
||||
xqspi->tx_bytes = sizeof(op->cmd.opcode);
|
||||
xqspi->rx_bytes = sizeof(op->cmd.opcode);
|
||||
xqspi->tx_bytes = op->cmd.nbytes;
|
||||
xqspi->rx_bytes = op->cmd.nbytes;
|
||||
zynq_qspi_write_op(xqspi, ZYNQ_QSPI_FIFO_DEPTH, true);
|
||||
zynq_qspi_write(xqspi, ZYNQ_QSPI_IEN_OFFSET,
|
||||
ZYNQ_QSPI_IXR_RXTX_MASK);
|
||||
|
@ -17,6 +17,7 @@
|
||||
{ \
|
||||
.buswidth = __buswidth, \
|
||||
.opcode = __opcode, \
|
||||
.nbytes = 1, \
|
||||
}
|
||||
|
||||
#define SPI_MEM_OP_ADDR(__nbytes, __val, __buswidth) \
|
||||
@ -69,11 +70,15 @@ enum spi_mem_data_dir {
|
||||
|
||||
/**
|
||||
* struct spi_mem_op - describes a SPI memory operation
|
||||
* @cmd.nbytes: number of opcode bytes (only 1 or 2 are valid). The opcode is
|
||||
* sent MSB-first.
|
||||
* @cmd.buswidth: number of IO lines used to transmit the command
|
||||
* @cmd.opcode: operation opcode
|
||||
* @cmd.dtr: whether the command opcode should be sent in DTR mode or not
|
||||
* @addr.nbytes: number of address bytes to send. Can be zero if the operation
|
||||
* does not need to send an address
|
||||
* @addr.buswidth: number of IO lines used to transmit the address cycles
|
||||
* @addr.dtr: whether the address should be sent in DTR mode or not
|
||||
* @addr.val: address value. This value is always sent MSB first on the bus.
|
||||
* Note that only @addr.nbytes are taken into account in this
|
||||
* address value, so users should make sure the value fits in the
|
||||
@ -81,7 +86,9 @@ enum spi_mem_data_dir {
|
||||
* @dummy.nbytes: number of dummy bytes to send after an opcode or address. Can
|
||||
* be zero if the operation does not require dummy bytes
|
||||
* @dummy.buswidth: number of IO lanes used to transmit the dummy bytes
|
||||
* @dummy.dtr: whether the dummy bytes should be sent in DTR mode or not
|
||||
* @data.buswidth: number of IO lanes used to send/receive the data
|
||||
* @data.dtr: whether the data should be sent in DTR mode or not
|
||||
* @data.dir: direction of the transfer
|
||||
* @data.nbytes: number of data bytes to send/receive. Can be zero if the
|
||||
* operation does not involve transferring data
|
||||
@ -90,23 +97,28 @@ enum spi_mem_data_dir {
|
||||
*/
|
||||
struct spi_mem_op {
|
||||
struct {
|
||||
u8 nbytes;
|
||||
u8 buswidth;
|
||||
u8 opcode;
|
||||
u8 dtr : 1;
|
||||
u16 opcode;
|
||||
} cmd;
|
||||
|
||||
struct {
|
||||
u8 nbytes;
|
||||
u8 buswidth;
|
||||
u8 dtr : 1;
|
||||
u64 val;
|
||||
} addr;
|
||||
|
||||
struct {
|
||||
u8 nbytes;
|
||||
u8 buswidth;
|
||||
u8 dtr : 1;
|
||||
} dummy;
|
||||
|
||||
struct {
|
||||
u8 buswidth;
|
||||
u8 dtr : 1;
|
||||
enum spi_mem_data_dir dir;
|
||||
unsigned int nbytes;
|
||||
union {
|
||||
|
Loading…
Reference in New Issue
Block a user