summaryrefslogtreecommitdiff
path: root/drivers/spi/spi-dw.h
diff options
context:
space:
mode:
authorSerge Semin <Sergey.Semin@baikalelectronics.ru>2020-10-08 02:55:06 +0300
committerMark Brown <broonie@kernel.org>2020-10-08 23:00:19 +0100
commit6423207e57ea53826eaae1a14c14fd6d22561b06 (patch)
tree51d2e7baa26af253b09a9d91ddcf8abdd74b323d /drivers/spi/spi-dw.h
parentbf64b66036eef7d5a92fb1cb7398ef67a29fc64b (diff)
spi: dw: Add memory operations support
Aside from the synchronous Tx-Rx mode, which has been utilized to create the normal SPI transfers in the framework of the DW SSI driver, DW SPI controller supports Tx-only and EEPROM-read modes. The former one just enables the controller to transmit all the data from the Tx FIFO ignoring anything retrieved from the MISO lane. The later mode is so called write-then-read operation: DW SPI controller first pushes out all the data from the Tx FIFO, after that it'll automatically receive as much data as has been specified by means of the CTRLR1 register. Both of those modes can be used to implement the memory operations supported by the SPI-memory subsystem. The memory operation implementation is pretty much straightforward, except a few peculiarities we have had to take into account to make things working. Since DW SPI controller doesn't provide a way to directly set and clear the native CS lane level, but instead automatically de-asserts it when a transfer going on, we have to make sure the Tx FIFO isn't empty during entire Tx procedure. In addition we also need to read data from the Rx FIFO as fast as possible to prevent it' overflow with automatically fetched incoming traffic. The denoted peculiarities get to cause even more problems if DW SSI controller is equipped with relatively small FIFO and is connected to a relatively slow system bus (APB) (with respect to the SPI bus speed). In order to workaround the problems for as much as it's possible, the memory operation execution procedure collects all the Tx data into a single buffer and disables the local IRQs to speed the write-then-optionally-read method up. Note the provided memory operations are utilized by default only if a glue driver hasn't provided a custom version of ones and this is not a DW APB SSI controller with fixed automatic CS toggle functionality. Co-developed-by: Ramil Zaripov <Ramil.Zaripov@baikalelectronics.ru> Signed-off-by: Ramil Zaripov <Ramil.Zaripov@baikalelectronics.ru> Signed-off-by: Serge Semin <Sergey.Semin@baikalelectronics.ru> Link: https://lore.kernel.org/r/20201007235511.4935-18-Sergey.Semin@baikalelectronics.ru Signed-off-by: Mark Brown <broonie@kernel.org>
Diffstat (limited to 'drivers/spi/spi-dw.h')
-rw-r--r--drivers/spi/spi-dw.h13
1 files changed, 13 insertions, 0 deletions
diff --git a/drivers/spi/spi-dw.h b/drivers/spi/spi-dw.h
index 7f26e46b1f87..7fadb5b963f8 100644
--- a/drivers/spi/spi-dw.h
+++ b/drivers/spi/spi-dw.h
@@ -8,6 +8,7 @@
#include <linux/irqreturn.h>
#include <linux/io.h>
#include <linux/scatterlist.h>
+#include <linux/spi/spi-mem.h>
/* Register offsets */
#define DW_SPI_CTRLR0 0x00
@@ -78,6 +79,9 @@
*/
#define DWC_SSI_CTRLR0_KEEMBAY_MST BIT(31)
+/* Bit fields in CTRLR1 */
+#define SPI_NDF_MASK GENMASK(15, 0)
+
/* Bit fields in SR, 7 bits */
#define SR_MASK 0x7f /* cover 7 bits */
#define SR_BUSY (1 << 0)
@@ -101,6 +105,11 @@
#define SPI_DMA_TDMAE (1 << 1)
#define SPI_WAIT_RETRIES 5
+#define SPI_BUF_SIZE \
+ (sizeof_field(struct spi_mem_op, cmd.opcode) + \
+ sizeof_field(struct spi_mem_op, addr.val) + 256)
+#define SPI_GET_BYTE(_val, _idx) \
+ ((_val) >> (BITS_PER_BYTE * (_idx)) & 0xff)
enum dw_ssi_type {
SSI_MOTO_SPI = 0,
@@ -153,6 +162,7 @@ struct dw_spi {
unsigned int tx_len;
void *rx;
unsigned int rx_len;
+ u8 buf[SPI_BUF_SIZE];
int dma_mapped;
u8 n_bytes; /* current is a 1/2 bytes op */
irqreturn_t (*transfer_handler)(struct dw_spi *dws);
@@ -160,6 +170,9 @@ struct dw_spi {
u32 cur_rx_sample_dly;
u32 def_rx_sample_dly_ns;
+ /* Custom memory operations */
+ struct spi_controller_mem_ops mem_ops;
+
/* DMA info */
struct dma_chan *txchan;
u32 txburst;