diff options
| author | Linus Torvalds <torvalds@linux-foundation.org> | 2021-02-22 09:19:08 -0800 |
|---|---|---|
| committer | Linus Torvalds <torvalds@linux-foundation.org> | 2021-02-22 09:19:08 -0800 |
| commit | a2590d69893f232cbb79d149dbbb456a1febca22 (patch) | |
| tree | 870326105cf0ff810fe9778764b276324fc6b1b9 /drivers/spi/spi-orion.c | |
| parent | d6560052c2f73db59834e9a3c0aba20579aa7059 (diff) | |
| parent | eec262d179ff60e8d12298ab2f118661040e0bf5 (diff) | |
Merge tag 'spi-v5.12' of git://git.kernel.org/pub/scm/linux/kernel/git/broonie/spi
Pull spi updates from Mark Brown:
"The main focus of this release from a framework point of view has been
spi-mem where we've acquired support for a few new hardware features
which enable better performance on suitable hardware.
Otherwise mostly thanks to Arnd's cleanup efforts on old platforms
we've removed several obsolete drivers which just about balance out
the newer drivers we've added this cycle.
Summary:
- Allow drivers to flag if they are unidirectional.
- Support for DTR mode and hardware acceleration of dummy cycles in
spi-mem.
- Support for Allwinder H616, Intel Lightning Mountain, nVidia Tegra
QuadSPI, Realtek RTL838x and RTL839x.
- Removal of obsolete EFM32, Txx9 and SIRF Prima and Atlas drivers"
* tag 'spi-v5.12' of git://git.kernel.org/pub/scm/linux/kernel/git/broonie/spi: (76 commits)
spi: Skip zero-length transfers in spi_transfer_one_message()
spi: dw: Avoid stack content exposure
spi: cadence-quadspi: Use spi_mem_dtr_supports_op()
spi: spi-mem: add spi_mem_dtr_supports_op()
spi: atmel-quadspi: Disable the QSPI IP at suspend()
spi: pxa2xx: Add IDs for the controllers found on Intel Lynxpoint
spi: pxa2xx: Fix the controller numbering for Wildcat Point
spi: Change provied to provided in the file spi.h
spi: mediatek: add set_cs_timing support
spi: support CS timing for HW & SW mode
spi: add power control when set_cs_timing
spi: stm32: make spurious and overrun interrupts visible
spi: stm32h7: replace private SPI_1HZ_NS with NSEC_PER_SEC
spi: stm32: defer probe for reset
spi: stm32: driver uses reset controller only at init
spi: stm32h7: ensure message are smaller than max size
spi: stm32: use bitfield macros
spi: stm32: do not mandate cs_gpio
spi: stm32: properly handle 0 byte transfer
spi: clps711xx: remove redundant white-space
...
Diffstat (limited to 'drivers/spi/spi-orion.c')
| -rw-r--r-- | drivers/spi/spi-orion.c | 55 |
1 files changed, 50 insertions, 5 deletions
diff --git a/drivers/spi/spi-orion.c b/drivers/spi/spi-orion.c index b57b8b3cc26e..68ed7fd64256 100644 --- a/drivers/spi/spi-orion.c +++ b/drivers/spi/spi-orion.c @@ -96,10 +96,16 @@ struct orion_spi { struct clk *clk; struct clk *axi_clk; const struct orion_spi_dev *devdata; + struct device *dev; struct orion_child_options child[ORION_NUM_CHIPSELECTS]; }; +#ifdef CONFIG_PM +static int orion_spi_runtime_suspend(struct device *dev); +static int orion_spi_runtime_resume(struct device *dev); +#endif + static inline void __iomem *spi_reg(struct orion_spi *orion_spi, u32 reg) { return orion_spi->base + reg; @@ -369,8 +375,15 @@ orion_spi_write_read_8bit(struct spi_device *spi, { void __iomem *tx_reg, *rx_reg, *int_reg; struct orion_spi *orion_spi; + bool cs_single_byte; + + cs_single_byte = spi->mode & SPI_CS_WORD; orion_spi = spi_master_get_devdata(spi->master); + + if (cs_single_byte) + orion_spi_set_cs(spi, 0); + tx_reg = spi_reg(orion_spi, ORION_SPI_DATA_OUT_REG); rx_reg = spi_reg(orion_spi, ORION_SPI_DATA_IN_REG); int_reg = spi_reg(orion_spi, ORION_SPI_INT_CAUSE_REG); @@ -384,6 +397,11 @@ orion_spi_write_read_8bit(struct spi_device *spi, writel(0, tx_reg); if (orion_spi_wait_till_ready(orion_spi) < 0) { + if (cs_single_byte) { + orion_spi_set_cs(spi, 1); + /* Satisfy some SLIC devices requirements */ + udelay(4); + } dev_err(&spi->dev, "TXS timed out\n"); return -1; } @@ -391,6 +409,12 @@ orion_spi_write_read_8bit(struct spi_device *spi, if (rx_buf && *rx_buf) *(*rx_buf)++ = readl(rx_reg); + if (cs_single_byte) { + orion_spi_set_cs(spi, 1); + /* Satisfy some SLIC devices requirements */ + udelay(4); + } + return 1; } @@ -401,6 +425,11 @@ orion_spi_write_read_16bit(struct spi_device *spi, void __iomem *tx_reg, *rx_reg, *int_reg; struct orion_spi *orion_spi; + if (spi->mode & SPI_CS_WORD) { + dev_err(&spi->dev, "SPI_CS_WORD is only supported for 8 bit words\n"); + return -1; + } + orion_spi = spi_master_get_devdata(spi->master); tx_reg = spi_reg(orion_spi, ORION_SPI_DATA_OUT_REG); rx_reg = spi_reg(orion_spi, ORION_SPI_DATA_IN_REG); @@ -440,12 +469,13 @@ orion_spi_write_read(struct spi_device *spi, struct spi_transfer *xfer) orion_spi = spi_master_get_devdata(spi->master); /* - * Use SPI direct write mode if base address is available. Otherwise - * fall back to PIO mode for this transfer. + * Use SPI direct write mode if base address is available + * and SPI_CS_WORD flag is not set. + * Otherwise fall back to PIO mode for this transfer. */ vaddr = orion_spi->child[cs].direct_access.vaddr; - if (vaddr && xfer->tx_buf && word_len == 8) { + if (vaddr && xfer->tx_buf && word_len == 8 && (spi->mode & SPI_CS_WORD) == 0) { unsigned int cnt = count / 4; unsigned int rem = count % 4; @@ -507,7 +537,21 @@ static int orion_spi_transfer_one(struct spi_master *master, static int orion_spi_setup(struct spi_device *spi) { - return orion_spi_setup_transfer(spi, NULL); + int ret; +#ifdef CONFIG_PM + struct orion_spi *orion_spi = spi_master_get_devdata(spi->master); + struct device *dev = orion_spi->dev; + + orion_spi_runtime_resume(dev); +#endif + + ret = orion_spi_setup_transfer(spi, NULL); + +#ifdef CONFIG_PM + orion_spi_runtime_suspend(dev); +#endif + + return ret; } static int orion_spi_reset(struct orion_spi *orion_spi) @@ -616,7 +660,7 @@ static int orion_spi_probe(struct platform_device *pdev) } /* we support all 4 SPI modes and LSB first option */ - master->mode_bits = SPI_CPHA | SPI_CPOL | SPI_LSB_FIRST; + master->mode_bits = SPI_CPHA | SPI_CPOL | SPI_LSB_FIRST | SPI_CS_WORD; master->set_cs = orion_spi_set_cs; master->transfer_one = orion_spi_transfer_one; master->num_chipselect = ORION_NUM_CHIPSELECTS; @@ -630,6 +674,7 @@ static int orion_spi_probe(struct platform_device *pdev) spi = spi_master_get_devdata(master); spi->master = master; + spi->dev = &pdev->dev; of_id = of_match_device(orion_spi_of_match_table, &pdev->dev); devdata = (of_id) ? of_id->data : &orion_spi_dev_data; |
