diff options
author | Linus Torvalds <torvalds@linux-foundation.org> | 2022-12-13 21:54:31 +0100 |
---|---|---|
committer | Linus Torvalds <torvalds@linux-foundation.org> | 2022-12-13 21:54:31 +0100 |
commit | d0f3ad23cf4f4046e88eef92c608d43cad9e4f7e (patch) | |
tree | f22a64cac48017fab350b4a954652f687a952a5d /drivers/spi/spi-intel.c | |
parent | Merge tag 'regulator-v6.2' of git://git.kernel.org/pub/scm/linux/kernel/git/b... (diff) | |
parent | spi: dt-bindings: Convert Synquacer SPI to DT schema (diff) | |
download | linux-d0f3ad23cf4f4046e88eef92c608d43cad9e4f7e.tar.xz linux-d0f3ad23cf4f4046e88eef92c608d43cad9e4f7e.zip |
Merge tag 'spi-v6.2' of git://git.kernel.org/pub/scm/linux/kernel/git/broonie/spi
Pull spi updates from Mark Brown:
"A busy enough release, but not for the core which has only seen very
small updates. The biggest addition is the readdition of support for
detailed configuration of the timings around chip selects. That had
been removed for lack of use but there's been applications found for
it on Atmel systems. Otherwise the updates are mostly feature
additions and cleanups to existing drivers.
Summary:
- Provide a helper for getting device match data in a way that
abstracts away which firmware interface is being used.
- Re-add the spi_set_cs_timing() API for detailed configuration of
the timing around chip select and support it on Atmel.
- Support for MediaTek MT7986, Microchip PCI1xxxx, Nuvoton WPCM450
FIU and Socionext F_OSPI"
* tag 'spi-v6.2' of git://git.kernel.org/pub/scm/linux/kernel/git/broonie/spi: (66 commits)
spi: dt-bindings: Convert Synquacer SPI to DT schema
spi: spi-gpio: Don't set MOSI as an input if not 3WIRE mode
spi: spi-mtk-nor: Add recovery mechanism for dma read timeout
spi: spi-fsl-lpspi: add num-cs binding for lpspi
spi: spi-fsl-lpspi: support multiple cs for lpspi
spi: mtk-snfi: Add snfi support for MT7986 IC
spi: spidev: mask SPI_CS_HIGH in SPI_IOC_RD_MODE
spi: cadence-quadspi: Add minimum operable clock rate warning to baudrate divisor calculation
spi: microchip: pci1xxxx: Add suspend and resume support for PCI1XXXX SPI driver
spi: dt-bindings: nuvoton,wpcm450-fiu: Fix warning in example (missing reg property)
spi: dt-bindings: nuvoton,wpcm450-fiu: Fix error in example (bogus include)
spi: mediatek: Enable irq when pdata is ready
spi: spi-mtk-nor: Unify write buffer on/off
spi: intel: Add support for SFDP opcode
spi: intel: Take possible chip address into account in intel_spi_read/write_reg()
spi: intel: Implement adjust_op_size()
spi: intel: Use ->replacement_op in intel_spi_hw_cycle()
spi: cadence: Drop obsolete dependency on COMPILE_TEST
spi: Add Nuvoton WPCM450 Flash Interface Unit (FIU) bindings
spi: wpcm-fiu: Add direct map support
...
Diffstat (limited to 'drivers/spi/spi-intel.c')
-rw-r--r-- | drivers/spi/spi-intel.c | 78 |
1 files changed, 40 insertions, 38 deletions
diff --git a/drivers/spi/spi-intel.c b/drivers/spi/spi-intel.c index 3ac73691fbb5..f619212b0d5c 100644 --- a/drivers/spi/spi-intel.c +++ b/drivers/spi/spi-intel.c @@ -33,6 +33,7 @@ #define HSFSTS_CTL_FCYCLE_WRITE (0x02 << HSFSTS_CTL_FCYCLE_SHIFT) #define HSFSTS_CTL_FCYCLE_ERASE (0x03 << HSFSTS_CTL_FCYCLE_SHIFT) #define HSFSTS_CTL_FCYCLE_ERASE_64K (0x04 << HSFSTS_CTL_FCYCLE_SHIFT) +#define HSFSTS_CTL_FCYCLE_RDSFDP (0x05 << HSFSTS_CTL_FCYCLE_SHIFT) #define HSFSTS_CTL_FCYCLE_RDID (0x06 << HSFSTS_CTL_FCYCLE_SHIFT) #define HSFSTS_CTL_FCYCLE_WRSR (0x07 << HSFSTS_CTL_FCYCLE_SHIFT) #define HSFSTS_CTL_FCYCLE_RDSR (0x08 << HSFSTS_CTL_FCYCLE_SHIFT) @@ -352,34 +353,21 @@ static int intel_spi_opcode_index(struct intel_spi *ispi, u8 opcode, int optype) return 0; } -static int intel_spi_hw_cycle(struct intel_spi *ispi, u8 opcode, size_t len) +static int intel_spi_hw_cycle(struct intel_spi *ispi, + const struct intel_spi_mem_op *iop, size_t len) { u32 val, status; int ret; - val = readl(ispi->base + HSFSTS_CTL); - val &= ~(HSFSTS_CTL_FCYCLE_MASK | HSFSTS_CTL_FDBC_MASK); - - switch (opcode) { - case SPINOR_OP_RDID: - val |= HSFSTS_CTL_FCYCLE_RDID; - break; - case SPINOR_OP_WRSR: - val |= HSFSTS_CTL_FCYCLE_WRSR; - break; - case SPINOR_OP_RDSR: - val |= HSFSTS_CTL_FCYCLE_RDSR; - break; - default: - return -EINVAL; - } - - if (len > INTEL_SPI_FIFO_SZ) + if (!iop->replacement_op) return -EINVAL; + val = readl(ispi->base + HSFSTS_CTL); + val &= ~(HSFSTS_CTL_FCYCLE_MASK | HSFSTS_CTL_FDBC_MASK); val |= (len - 1) << HSFSTS_CTL_FDBC_SHIFT; val |= HSFSTS_CTL_FCERR | HSFSTS_CTL_FDONE; val |= HSFSTS_CTL_FGO; + val |= iop->replacement_op; writel(val, ispi->base + HSFSTS_CTL); ret = intel_spi_wait_hw_busy(ispi); @@ -406,9 +394,6 @@ static int intel_spi_sw_cycle(struct intel_spi *ispi, u8 opcode, size_t len, if (ret < 0) return ret; - if (len > INTEL_SPI_FIFO_SZ) - return -EINVAL; - /* * Always clear it after each SW sequencer operation regardless * of whether it is successful or not. @@ -473,17 +458,18 @@ static int intel_spi_read_reg(struct intel_spi *ispi, const struct spi_mem *mem, const struct intel_spi_mem_op *iop, const struct spi_mem_op *op) { + u32 addr = intel_spi_chip_addr(ispi, mem) + op->addr.val; size_t nbytes = op->data.nbytes; u8 opcode = op->cmd.opcode; int ret; - writel(intel_spi_chip_addr(ispi, mem), ispi->base + FADDR); + writel(addr, ispi->base + FADDR); if (ispi->swseq_reg) ret = intel_spi_sw_cycle(ispi, opcode, nbytes, OPTYPE_READ_NO_ADDR); else - ret = intel_spi_hw_cycle(ispi, opcode, nbytes); + ret = intel_spi_hw_cycle(ispi, iop, nbytes); if (ret) return ret; @@ -495,6 +481,7 @@ static int intel_spi_write_reg(struct intel_spi *ispi, const struct spi_mem *mem const struct intel_spi_mem_op *iop, const struct spi_mem_op *op) { + u32 addr = intel_spi_chip_addr(ispi, mem) + op->addr.val; size_t nbytes = op->data.nbytes; u8 opcode = op->cmd.opcode; int ret; @@ -538,7 +525,7 @@ static int intel_spi_write_reg(struct intel_spi *ispi, const struct spi_mem *mem if (opcode == SPINOR_OP_WRDI) return 0; - writel(intel_spi_chip_addr(ispi, mem), ispi->base + FADDR); + writel(addr, ispi->base + FADDR); /* Write the value beforehand */ ret = intel_spi_write_block(ispi, op->data.buf.out, nbytes); @@ -548,7 +535,7 @@ static int intel_spi_write_reg(struct intel_spi *ispi, const struct spi_mem *mem if (ispi->swseq_reg) return intel_spi_sw_cycle(ispi, opcode, nbytes, OPTYPE_WRITE_NO_ADDR); - return intel_spi_hw_cycle(ispi, opcode, nbytes); + return intel_spi_hw_cycle(ispi, iop, nbytes); } static int intel_spi_read(struct intel_spi *ispi, const struct spi_mem *mem, @@ -713,6 +700,12 @@ static int intel_spi_erase(struct intel_spi *ispi, const struct spi_mem *mem, return 0; } +static int intel_spi_adjust_op_size(struct spi_mem *mem, struct spi_mem_op *op) +{ + op->data.nbytes = clamp_val(op->data.nbytes, 0, INTEL_SPI_FIFO_SZ); + return 0; +} + static bool intel_spi_cmp_mem_op(const struct intel_spi_mem_op *iop, const struct spi_mem_op *op) { @@ -853,6 +846,7 @@ static ssize_t intel_spi_dirmap_write(struct spi_mem_dirmap_desc *desc, u64 offs } static const struct spi_controller_mem_ops intel_spi_mem_ops = { + .adjust_op_size = intel_spi_adjust_op_size, .supports_op = intel_spi_supports_mem_op, .exec_op = intel_spi_exec_mem_op, .get_name = intel_spi_get_name, @@ -912,18 +906,26 @@ static const struct spi_controller_mem_ops intel_spi_mem_ops = { */ #define INTEL_SPI_GENERIC_OPS \ /* Status register operations */ \ - INTEL_SPI_MEM_OP(SPI_MEM_OP_CMD(SPINOR_OP_RDID, 1), \ - SPI_MEM_OP_NO_ADDR, \ - INTEL_SPI_OP_DATA_IN(1), \ - intel_spi_read_reg), \ - INTEL_SPI_MEM_OP(SPI_MEM_OP_CMD(SPINOR_OP_RDSR, 1), \ - SPI_MEM_OP_NO_ADDR, \ - INTEL_SPI_OP_DATA_IN(1), \ - intel_spi_read_reg), \ - INTEL_SPI_MEM_OP(SPI_MEM_OP_CMD(SPINOR_OP_WRSR, 1), \ - SPI_MEM_OP_NO_ADDR, \ - INTEL_SPI_OP_DATA_OUT(1), \ - intel_spi_write_reg), \ + INTEL_SPI_MEM_OP_REPL(SPI_MEM_OP_CMD(SPINOR_OP_RDID, 1), \ + SPI_MEM_OP_NO_ADDR, \ + INTEL_SPI_OP_DATA_IN(1), \ + intel_spi_read_reg, \ + HSFSTS_CTL_FCYCLE_RDID), \ + INTEL_SPI_MEM_OP_REPL(SPI_MEM_OP_CMD(SPINOR_OP_RDSR, 1), \ + SPI_MEM_OP_NO_ADDR, \ + INTEL_SPI_OP_DATA_IN(1), \ + intel_spi_read_reg, \ + HSFSTS_CTL_FCYCLE_RDSR), \ + INTEL_SPI_MEM_OP_REPL(SPI_MEM_OP_CMD(SPINOR_OP_WRSR, 1), \ + SPI_MEM_OP_NO_ADDR, \ + INTEL_SPI_OP_DATA_OUT(1), \ + intel_spi_write_reg, \ + HSFSTS_CTL_FCYCLE_WRSR), \ + INTEL_SPI_MEM_OP_REPL(SPI_MEM_OP_CMD(SPINOR_OP_RDSFDP, 1), \ + INTEL_SPI_OP_ADDR(3), \ + INTEL_SPI_OP_DATA_IN(1), \ + intel_spi_read_reg, \ + HSFSTS_CTL_FCYCLE_RDSFDP), \ /* Normal read */ \ INTEL_SPI_MEM_OP(SPI_MEM_OP_CMD(SPINOR_OP_READ, 1), \ INTEL_SPI_OP_ADDR(3), \ |