diff options
Diffstat (limited to 'drivers/spi/spi-fsi.c')
-rw-r--r-- | drivers/spi/spi-fsi.c | 28 |
1 files changed, 25 insertions, 3 deletions
diff --git a/drivers/spi/spi-fsi.c b/drivers/spi/spi-fsi.c index 559d0ff981f3..c31a852b6a3e 100644 --- a/drivers/spi/spi-fsi.c +++ b/drivers/spi/spi-fsi.c @@ -29,6 +29,10 @@ #define SPI_FSI_ERROR 0x0 #define SPI_FSI_COUNTER_CFG 0x1 #define SPI_FSI_COUNTER_CFG_LOOPS(x) (((u64)(x) & 0xffULL) << 32) +#define SPI_FSI_COUNTER_CFG_N2_RX BIT_ULL(8) +#define SPI_FSI_COUNTER_CFG_N2_TX BIT_ULL(9) +#define SPI_FSI_COUNTER_CFG_N2_IMPLICIT BIT_ULL(10) +#define SPI_FSI_COUNTER_CFG_N2_RELOAD BIT_ULL(11) #define SPI_FSI_CFG1 0x2 #define SPI_FSI_CLOCK_CFG 0x3 #define SPI_FSI_CLOCK_CFG_MM_ENABLE BIT_ULL(32) @@ -61,7 +65,7 @@ #define SPI_FSI_STATUS_RDR_OVERRUN BIT_ULL(62) #define SPI_FSI_STATUS_RDR_FULL BIT_ULL(63) #define SPI_FSI_STATUS_ANY_ERROR \ - (SPI_FSI_STATUS_ERROR | SPI_FSI_STATUS_TDR_UNDERRUN | \ + (SPI_FSI_STATUS_ERROR | \ SPI_FSI_STATUS_TDR_OVERRUN | SPI_FSI_STATUS_RDR_UNDERRUN | \ SPI_FSI_STATUS_RDR_OVERRUN) #define SPI_FSI_PORT_CTRL 0x9 @@ -238,6 +242,7 @@ static int fsi_spi_sequence_transfer(struct fsi_spi *ctx, int rc; u8 len = min(transfer->len, 8U); u8 rem = transfer->len % len; + u64 cfg = 0ULL; loops = transfer->len / len; @@ -258,8 +263,14 @@ static int fsi_spi_sequence_transfer(struct fsi_spi *ctx, if (loops > 1) { fsi_spi_sequence_add(seq, SPI_FSI_SEQUENCE_BRANCH(idx)); - rc = fsi_spi_write_reg(ctx, SPI_FSI_COUNTER_CFG, - SPI_FSI_COUNTER_CFG_LOOPS(loops - 1)); + cfg = SPI_FSI_COUNTER_CFG_LOOPS(loops - 1); + if (transfer->rx_buf) + cfg |= SPI_FSI_COUNTER_CFG_N2_RX | + SPI_FSI_COUNTER_CFG_N2_TX | + SPI_FSI_COUNTER_CFG_N2_IMPLICIT | + SPI_FSI_COUNTER_CFG_N2_RELOAD; + + rc = fsi_spi_write_reg(ctx, SPI_FSI_COUNTER_CFG, cfg); if (rc) return rc; } @@ -275,6 +286,7 @@ static int fsi_spi_transfer_data(struct fsi_spi *ctx, { int rc = 0; u64 status = 0ULL; + u64 cfg = 0ULL; if (transfer->tx_buf) { int nb; @@ -312,6 +324,16 @@ static int fsi_spi_transfer_data(struct fsi_spi *ctx, u64 in = 0ULL; u8 *rx = transfer->rx_buf; + rc = fsi_spi_read_reg(ctx, SPI_FSI_COUNTER_CFG, &cfg); + if (rc) + return rc; + + if (cfg & SPI_FSI_COUNTER_CFG_N2_IMPLICIT) { + rc = fsi_spi_write_reg(ctx, SPI_FSI_DATA_TX, 0); + if (rc) + return rc; + } + while (transfer->len > recv) { do { rc = fsi_spi_read_reg(ctx, SPI_FSI_STATUS, |