diff options
Diffstat (limited to 'drivers')
-rw-r--r-- | drivers/spi/spi-cadence.c | 2 | ||||
-rw-r--r-- | drivers/spi/spi-fsl-dspi.c | 485 | ||||
-rw-r--r-- | drivers/spi/spi-orion.c | 77 | ||||
-rw-r--r-- | drivers/spi/spi-pxa2xx.c | 4 | ||||
-rw-r--r-- | drivers/spi/spi-sh-msiof.c | 53 |
5 files changed, 339 insertions, 282 deletions
diff --git a/drivers/spi/spi-cadence.c b/drivers/spi/spi-cadence.c index f3dad6fcdc35..a568f35522f9 100644 --- a/drivers/spi/spi-cadence.c +++ b/drivers/spi/spi-cadence.c @@ -319,7 +319,7 @@ static void cdns_spi_fill_tx_fifo(struct cdns_spi *xspi) */ if (cdns_spi_read(xspi, CDNS_SPI_ISR) & CDNS_SPI_IXR_TXFULL) - usleep_range(10, 20); + udelay(10); if (xspi->txbuf) cdns_spi_write(xspi, CDNS_SPI_TXD, *xspi->txbuf++); diff --git a/drivers/spi/spi-fsl-dspi.c b/drivers/spi/spi-fsl-dspi.c index 0630962ce442..9e598642ca66 100644 --- a/drivers/spi/spi-fsl-dspi.c +++ b/drivers/spi/spi-fsl-dspi.c @@ -38,10 +38,6 @@ #define DRIVER_NAME "fsl-dspi" -#define TRAN_STATE_RX_VOID 0x01 -#define TRAN_STATE_TX_VOID 0x02 -#define TRAN_STATE_WORD_ODD_NUM 0x04 - #define DSPI_FIFO_SIZE 4 #define DSPI_DMA_BUFSIZE (DSPI_FIFO_SIZE * 1024) @@ -50,6 +46,7 @@ #define SPI_MCR_PCSIS (0x3F << 16) #define SPI_MCR_CLR_TXF (1 << 11) #define SPI_MCR_CLR_RXF (1 << 10) +#define SPI_MCR_XSPI (1 << 3) #define SPI_TCR 0x08 #define SPI_TCR_GET_TCNT(x) (((x) & 0xffff0000) >> 16) @@ -86,11 +83,16 @@ #define SPI_RSER_TCFQE 0x80000000 #define SPI_PUSHR 0x34 -#define SPI_PUSHR_CONT (1 << 31) -#define SPI_PUSHR_CTAS(x) (((x) & 0x00000003) << 28) -#define SPI_PUSHR_EOQ (1 << 27) -#define SPI_PUSHR_CTCNT (1 << 26) -#define SPI_PUSHR_PCS(x) (((1 << x) & 0x0000003f) << 16) +#define SPI_PUSHR_CMD_CONT (1 << 15) +#define SPI_PUSHR_CONT (SPI_PUSHR_CMD_CONT << 16) +#define SPI_PUSHR_CMD_CTAS(x) (((x) & 0x0003) << 12) +#define SPI_PUSHR_CTAS(x) (SPI_PUSHR_CMD_CTAS(x) << 16) +#define SPI_PUSHR_CMD_EOQ (1 << 11) +#define SPI_PUSHR_EOQ (SPI_PUSHR_CMD_EOQ << 16) +#define SPI_PUSHR_CMD_CTCNT (1 << 10) +#define SPI_PUSHR_CTCNT (SPI_PUSHR_CMD_CTCNT << 16) +#define SPI_PUSHR_CMD_PCS(x) ((1 << x) & 0x003f) +#define SPI_PUSHR_PCS(x) (SPI_PUSHR_CMD_PCS(x) << 16) #define SPI_PUSHR_TXDATA(x) ((x) & 0x0000ffff) #define SPI_PUSHR_SLAVE 0x34 @@ -107,21 +109,31 @@ #define SPI_RXFR2 0x84 #define SPI_RXFR3 0x88 +#define SPI_CTARE(x) (0x11c + (((x) & 0x3) * 4)) +#define SPI_CTARE_FMSZE(x) (((x) & 0x1) << 16) +#define SPI_CTARE_DTCP(x) ((x) & 0x7ff) + +#define SPI_SREX 0x13c + #define SPI_FRAME_BITS(bits) SPI_CTAR_FMSZ((bits) - 1) #define SPI_FRAME_BITS_MASK SPI_CTAR_FMSZ(0xf) #define SPI_FRAME_BITS_16 SPI_CTAR_FMSZ(0xf) #define SPI_FRAME_BITS_8 SPI_CTAR_FMSZ(0x7) +#define SPI_FRAME_EBITS(bits) SPI_CTARE_FMSZE(((bits) - 1) >> 4) +#define SPI_FRAME_EBITS_MASK SPI_CTARE_FMSZE(1) + +/* Register offsets for regmap_pushr */ +#define PUSHR_CMD 0x0 +#define PUSHR_TX 0x2 + #define SPI_CS_INIT 0x01 #define SPI_CS_ASSERT 0x02 #define SPI_CS_DROP 0x04 -#define SPI_TCR_TCNT_MAX 0x10000 - #define DMA_COMPLETION_TIMEOUT msecs_to_jiffies(3000) struct chip_data { - u32 mcr_val; u32 ctar_val; u16 void_write_data; }; @@ -135,6 +147,7 @@ enum dspi_trans_mode { struct fsl_dspi_devtype_data { enum dspi_trans_mode trans_mode; u8 max_clock_factor; + bool xspi_mode; }; static const struct fsl_dspi_devtype_data vf610_data = { @@ -145,6 +158,7 @@ static const struct fsl_dspi_devtype_data vf610_data = { static const struct fsl_dspi_devtype_data ls1021a_v1_data = { .trans_mode = DSPI_TCFQ_MODE, .max_clock_factor = 8, + .xspi_mode = true, }; static const struct fsl_dspi_devtype_data ls2085a_data = { @@ -179,6 +193,7 @@ struct fsl_dspi { struct platform_device *pdev; struct regmap *regmap; + struct regmap *regmap_pushr; int irq; struct clk *clk; @@ -186,32 +201,62 @@ struct fsl_dspi { struct spi_message *cur_msg; struct chip_data *cur_chip; size_t len; - void *tx; - void *tx_end; + const void *tx; void *rx; void *rx_end; - char dataflags; - u8 cs; u16 void_write_data; - u32 cs_change; + u16 tx_cmd; + u8 bits_per_word; + u8 bytes_per_word; const struct fsl_dspi_devtype_data *devtype_data; wait_queue_head_t waitq; u32 waitflags; - u32 spi_tcnt; struct fsl_dspi_dma *dma; }; -static u32 dspi_data_to_pushr(struct fsl_dspi *dspi, int tx_word); +static u32 dspi_pop_tx(struct fsl_dspi *dspi) +{ + u32 txdata = 0; + + if (dspi->tx) { + if (dspi->bytes_per_word == 1) + txdata = *(u8 *)dspi->tx; + else if (dspi->bytes_per_word == 2) + txdata = *(u16 *)dspi->tx; + else /* dspi->bytes_per_word == 4 */ + txdata = *(u32 *)dspi->tx; + dspi->tx += dspi->bytes_per_word; + } + dspi->len -= dspi->bytes_per_word; + return txdata; +} -static inline int is_double_byte_mode(struct fsl_dspi *dspi) +static u32 dspi_pop_tx_pushr(struct fsl_dspi *dspi) { - unsigned int val; + u16 cmd = dspi->tx_cmd, data = dspi_pop_tx(dspi); - regmap_read(dspi->regmap, SPI_CTAR(0), &val); + if (dspi->len > 0) + cmd |= SPI_PUSHR_CMD_CONT; + return cmd << 16 | data; +} - return ((val & SPI_FRAME_BITS_MASK) == SPI_FRAME_BITS(8)) ? 0 : 1; +static void dspi_push_rx(struct fsl_dspi *dspi, u32 rxdata) +{ + if (!dspi->rx) + return; + + /* Mask of undefined bits */ + rxdata &= (1 << dspi->bits_per_word) - 1; + + if (dspi->bytes_per_word == 1) + *(u8 *)dspi->rx = rxdata; + else if (dspi->bytes_per_word == 2) + *(u16 *)dspi->rx = rxdata; + else /* dspi->bytes_per_word == 4 */ + *(u32 *)dspi->rx = rxdata; + dspi->rx += dspi->bytes_per_word; } static void dspi_tx_dma_callback(void *arg) @@ -226,19 +271,11 @@ static void dspi_rx_dma_callback(void *arg) { struct fsl_dspi *dspi = arg; struct fsl_dspi_dma *dma = dspi->dma; - int rx_word; int i; - u16 d; - - rx_word = is_double_byte_mode(dspi); - if (!(dspi->dataflags & TRAN_STATE_RX_VOID)) { - for (i = 0; i < dma->curr_xfer_len; i++) { - d = dspi->dma->rx_dma_buf[i]; - rx_word ? (*(u16 *)dspi->rx = d) : - (*(u8 *)dspi->rx = d); - dspi->rx += rx_word + 1; - } + if (dspi->rx) { + for (i = 0; i < dma->curr_xfer_len; i++) + dspi_push_rx(dspi, dspi->dma->rx_dma_buf[i]); } complete(&dma->cmd_rx_complete); @@ -249,16 +286,10 @@ static int dspi_next_xfer_dma_submit(struct fsl_dspi *dspi) struct fsl_dspi_dma *dma = dspi->dma; struct device *dev = &dspi->pdev->dev; int time_left; - int tx_word; int i; - tx_word = is_double_byte_mode(dspi); - - for (i = 0; i < dma->curr_xfer_len; i++) { - dspi->dma->tx_dma_buf[i] = dspi_data_to_pushr(dspi, tx_word); - if ((dspi->cs_change) && (!dspi->len)) - dspi->dma->tx_dma_buf[i] &= ~SPI_PUSHR_CONT; - } + for (i = 0; i < dma->curr_xfer_len; i++) + dspi->dma->tx_dma_buf[i] = dspi_pop_tx_pushr(dspi); dma->tx_desc = dmaengine_prep_slave_single(dma->chan_tx, dma->tx_dma_phys, @@ -327,18 +358,17 @@ static int dspi_dma_xfer(struct fsl_dspi *dspi) { struct fsl_dspi_dma *dma = dspi->dma; struct device *dev = &dspi->pdev->dev; + struct spi_message *message = dspi->cur_msg; int curr_remaining_bytes; int bytes_per_buffer; - int word = 1; int ret = 0; - if (is_double_byte_mode(dspi)) - word = 2; curr_remaining_bytes = dspi->len; bytes_per_buffer = DSPI_DMA_BUFSIZE / DSPI_FIFO_SIZE; while (curr_remaining_bytes) { /* Check if current transfer fits the DMA buffer */ - dma->curr_xfer_len = curr_remaining_bytes / word; + dma->curr_xfer_len = curr_remaining_bytes + / dspi->bytes_per_word; if (dma->curr_xfer_len > bytes_per_buffer) dma->curr_xfer_len = bytes_per_buffer; @@ -348,7 +378,10 @@ static int dspi_dma_xfer(struct fsl_dspi *dspi) goto exit; } else { - curr_remaining_bytes -= dma->curr_xfer_len * word; + const int len = + dma->curr_xfer_len * dspi->bytes_per_word; + curr_remaining_bytes -= len; + message->actual_length += len; if (curr_remaining_bytes < 0) curr_remaining_bytes = 0; } @@ -534,125 +567,91 @@ static void ns_delay_scale(char *psc, char *sc, int delay_ns, } } -static u32 dspi_data_to_pushr(struct fsl_dspi *dspi, int tx_word) +static void fifo_write(struct fsl_dspi *dspi) { - u16 d16; - - if (!(dspi->dataflags & TRAN_STATE_TX_VOID)) - d16 = tx_word ? *(u16 *)dspi->tx : *(u8 *)dspi->tx; - else - d16 = dspi->void_write_data; - - dspi->tx += tx_word + 1; - dspi->len -= tx_word + 1; - - return SPI_PUSHR_TXDATA(d16) | - SPI_PUSHR_PCS(dspi->cs) | - SPI_PUSHR_CTAS(0) | - SPI_PUSHR_CONT; + regmap_write(dspi->regmap, SPI_PUSHR, dspi_pop_tx_pushr(dspi)); } -static void dspi_data_from_popr(struct fsl_dspi *dspi, int rx_word) +static void cmd_fifo_write(struct fsl_dspi *dspi) { - u16 d; - unsigned int val; - - regmap_read(dspi->regmap, SPI_POPR, &val); - d = SPI_POPR_RXDATA(val); + u16 cmd = dspi->tx_cmd; - if (!(dspi->dataflags & TRAN_STATE_RX_VOID)) - rx_word ? (*(u16 *)dspi->rx = d) : (*(u8 *)dspi->rx = d); - - dspi->rx += rx_word + 1; + if (dspi->len > 0) + cmd |= SPI_PUSHR_CMD_CONT; + regmap_write(dspi->regmap_pushr, PUSHR_CMD, cmd); } -static int dspi_eoq_write(struct fsl_dspi *dspi) +static void tx_fifo_write(struct fsl_dspi *dspi, u16 txdata) { - int tx_count = 0; - int tx_word; - u32 dspi_pushr = 0; + regmap_write(dspi->regmap_pushr, PUSHR_TX, txdata); +} - tx_word = is_double_byte_mode(dspi); +static void dspi_tcfq_write(struct fsl_dspi *dspi) +{ + /* Clear transfer count */ + dspi->tx_cmd |= SPI_PUSHR_CMD_CTCNT; - while (dspi->len && (tx_count < DSPI_FIFO_SIZE)) { - /* If we are in word mode, only have a single byte to transfer - * switch to byte mode temporarily. Will switch back at the - * end of the transfer. + if (dspi->devtype_data->xspi_mode && dspi->bits_per_word > 16) { + /* Write two TX FIFO entries first, and then the corresponding + * CMD FIFO entry. */ - if (tx_word && (dspi->len == 1)) { - dspi->dataflags |= TRAN_STATE_WORD_ODD_NUM; - regmap_update_bits(dspi->regmap, SPI_CTAR(0), - SPI_FRAME_BITS_MASK, SPI_FRAME_BITS(8)); - tx_word = 0; - } - - dspi_pushr = dspi_data_to_pushr(dspi, tx_word); - - if (dspi->len == 0 || tx_count == DSPI_FIFO_SIZE - 1) { - /* last transfer in the transfer */ - dspi_pushr |= SPI_PUSHR_EOQ; - if ((dspi->cs_change) && (!dspi->len)) - dspi_pushr &= ~SPI_PUSHR_CONT; - } else if (tx_word && (dspi->len == 1)) - dspi_pushr |= SPI_PUSHR_EOQ; + u32 data = dspi_pop_tx(dspi); - regmap_write(dspi->regmap, SPI_PUSHR, dspi_pushr); - - tx_count++; + if (dspi->cur_chip->ctar_val & SPI_CTAR_LSBFE(1)) { + /* LSB */ + tx_fifo_write(dspi, data & 0xFFFF); + tx_fifo_write(dspi, data >> 16); + } else { + /* MSB */ + tx_fifo_write(dspi, data >> 16); + tx_fifo_write(dspi, data & 0xFFFF); + } + cmd_fifo_write(dspi); + } else { + /* Write one entry to both TX FIFO and CMD FIFO + * simultaneously. + */ + fifo_write(dspi); } - - return tx_count * (tx_word + 1); } -static int dspi_eoq_read(struct fsl_dspi *dspi) +static u32 fifo_read(struct fsl_dspi *dspi) { - int rx_count = 0; - int rx_word = is_double_byte_mode(dspi); - - while ((dspi->rx < dspi->rx_end) - && (rx_count < DSPI_FIFO_SIZE)) { - if (rx_word && (dspi->rx_end - dspi->rx) == 1) - rx_word = 0; + u32 rxdata = 0; - dspi_data_from_popr(dspi, rx_word); - rx_count++; - } - - return rx_count; + regmap_read(dspi->regmap, SPI_POPR, &rxdata); + return rxdata; } -static int dspi_tcfq_write(struct fsl_dspi *dspi) +static void dspi_tcfq_read(struct fsl_dspi *dspi) { - int tx_word; - u32 dspi_pushr = 0; - - tx_word = is_double_byte_mode(dspi); + dspi_push_rx(dspi, fifo_read(dspi)); +} - if (tx_word && (dspi->len == 1)) { - dspi->dataflags |= TRAN_STATE_WORD_ODD_NUM; - regmap_update_bits(dspi->regmap, SPI_CTAR(0), - SPI_FRAME_BITS_MASK, SPI_FRAME_BITS(8)); - tx_word = 0; +static void dspi_eoq_write(struct fsl_dspi *dspi) +{ + int fifo_size = DSPI_FIFO_SIZE; + + /* Fill TX FIFO with as many transfers as possible */ + while (dspi->len && fifo_size--) { + /* Request EOQF for last transfer in FIFO */ + if (dspi->len == dspi->bytes_per_word || fifo_size == 0) + dspi->tx_cmd |= SPI_PUSHR_CMD_EOQ; + /* Clear transfer count for first transfer in FIFO */ + if (fifo_size == (DSPI_FIFO_SIZE - 1)) + dspi->tx_cmd |= SPI_PUSHR_CMD_CTCNT; + /* Write combined TX FIFO and CMD FIFO entry */ + fifo_write(dspi); } - - dspi_pushr = dspi_data_to_pushr(dspi, tx_word); - - if ((dspi->cs_change) && (!dspi->len)) - dspi_pushr &= ~SPI_PUSHR_CONT; - - regmap_write(dspi->regmap, SPI_PUSHR, dspi_pushr); - - return tx_word + 1; } -static void dspi_tcfq_read(struct fsl_dspi *dspi) +static void dspi_eoq_read(struct fsl_dspi *dspi) { - int rx_word = is_double_byte_mode(dspi); - - if (rx_word && (dspi->rx_end - dspi->rx) == 1) - rx_word = 0; + int fifo_size = DSPI_FIFO_SIZE; - dspi_data_from_popr(dspi, rx_word); + /* Read one FIFO entry at and push to rx buffer */ + while ((dspi->rx < dspi->rx_end) && fifo_size--) + dspi_push_rx(dspi, fifo_read(dspi)); } static int dspi_transfer_one_message(struct spi_master *master, @@ -663,10 +662,6 @@ static int dspi_transfer_one_message(struct spi_master *master, struct spi_transfer *transfer; int status = 0; enum dspi_trans_mode trans_mode; - u32 spi_tcr; - - regmap_read(dspi->regmap, SPI_TCR, &spi_tcr); - dspi->spi_tcnt = SPI_TCR_GET_TCNT(spi_tcr); message->actual_length = 0; @@ -674,32 +669,51 @@ static int dspi_transfer_one_message(struct spi_master *master, dspi->cur_transfer = transfer; dspi->cur_msg = message; dspi->cur_chip = spi_get_ctldata(spi); - dspi->cs = spi->chip_select; - dspi->cs_change = 0; + /* Prepare command word for CMD FIFO */ + dspi->tx_cmd = SPI_PUSHR_CMD_CTAS(0) | + SPI_PUSHR_CMD_PCS(spi->chip_select); if (list_is_last(&dspi->cur_transfer->transfer_list, - &dspi->cur_msg->transfers) || transfer->cs_change) - dspi->cs_change = 1; + &dspi->cur_msg->transfers)) { + /* Leave PCS activated after last transfer when + * cs_change is set. + */ + if (transfer->cs_change) + dspi->tx_cmd |= SPI_PUSHR_CMD_CONT; + } else { + /* Keep PCS active between transfers in same message + * when cs_change is not set, and de-activate PCS + * between transfers in the same message when + * cs_change is set. + */ + if (!transfer->cs_change) + dspi->tx_cmd |= SPI_PUSHR_CMD_CONT; + } + dspi->void_write_data = dspi->cur_chip->void_write_data; - dspi->dataflags = 0; - dspi->tx = (void *)transfer->tx_buf; - dspi->tx_end = dspi->tx + transfer->len; + dspi->tx = transfer->tx_buf; dspi->rx = transfer->rx_buf; dspi->rx_end = dspi->rx + transfer->len; dspi->len = transfer->len; + /* Validated transfer specific frame size (defaults applied) */ + dspi->bits_per_word = transfer->bits_per_word; + if (transfer->bits_per_word <= 8) + dspi->bytes_per_word = 1; + else if (transfer->bits_per_word <= 16) + dspi->bytes_per_word = 2; + else + dspi->bytes_per_word = 4; - if (!dspi->rx) - dspi->dataflags |= TRAN_STATE_RX_VOID; - - if (!dspi->tx) - dspi->dataflags |= TRAN_STATE_TX_VOID; - - regmap_write(dspi->regmap, SPI_MCR, dspi->cur_chip->mcr_val); regmap_update_bits(dspi->regmap, SPI_MCR, - SPI_MCR_CLR_TXF | SPI_MCR_CLR_RXF, - SPI_MCR_CLR_TXF | SPI_MCR_CLR_RXF); + SPI_MCR_CLR_TXF | SPI_MCR_CLR_RXF, + SPI_MCR_CLR_TXF | SPI_MCR_CLR_RXF); regmap_write(dspi->regmap, SPI_CTAR(0), - dspi->cur_chip->ctar_val); + dspi->cur_chip->ctar_val | + SPI_FRAME_BITS(transfer->bits_per_word)); + if (dspi->devtype_data->xspi_mode) + regmap_write(dspi->regmap, SPI_CTARE(0), + SPI_FRAME_EBITS(transfer->bits_per_word) + | SPI_CTARE_DTCP(1)); trans_mode = dspi->devtype_data->trans_mode; switch (trans_mode) { @@ -750,16 +764,9 @@ static int dspi_setup(struct spi_device *spi) struct fsl_dspi_platform_data *pdata; u32 cs_sck_delay = 0, sck_cs_delay = 0; unsigned char br = 0, pbr = 0, pcssck = 0, cssck = 0; - unsigned char pasc = 0, asc = 0, fmsz = 0; + unsigned char pasc = 0, asc = 0; unsigned long clkrate; - if ((spi->bits_per_word >= 4) && (spi->bits_per_word <= 16)) { - fmsz = spi->bits_per_word - 1; - } else { - pr_err("Invalid wordsize\n"); - return -ENODEV; - } - /* Only alloc on first setup */ chip = spi_get_ctldata(spi); if (chip == NULL) { @@ -781,9 +788,6 @@ static int dspi_setup(struct spi_device *spi) sck_cs_delay = pdata->sck_cs_delay; } - chip->mcr_val = SPI_MCR_MASTER | SPI_MCR_PCSIS | - SPI_MCR_CLR_TXF | SPI_MCR_CLR_RXF; - chip->void_write_data = 0; clkrate = clk_get_rate(dspi->clk); @@ -795,8 +799,7 @@ static int dspi_setup(struct spi_device *spi) /* Set After SCK delay scale values */ ns_delay_scale(&pasc, &asc, sck_cs_delay, clkrate); - chip->ctar_val = SPI_CTAR_FMSZ(fmsz) - | SPI_CTAR_CPOL(spi->mode & SPI_CPOL ? 1 : 0) + chip->ctar_val = SPI_CTAR_CPOL(spi->mode & SPI_CPOL ? 1 : 0) | SPI_CTAR_CPHA(spi->mode & SPI_CPHA ? 1 : 0) | SPI_CTAR_LSBFE(spi->mode & SPI_LSB_FIRST ? 1 : 0) | SPI_CTAR_PCSSCK(pcssck) @@ -827,36 +830,20 @@ static irqreturn_t dspi_interrupt(int irq, void *dev_id) struct spi_message *msg = dspi->cur_msg; enum dspi_trans_mode trans_mode; u32 spi_sr, spi_tcr; - u32 spi_tcnt, tcnt_diff; - int tx_word; + u16 spi_tcnt; regmap_read(dspi->regmap, SPI_SR, &spi_sr); regmap_write(dspi->regmap, SPI_SR, spi_sr); if (spi_sr & (SPI_SR_EOQF | SPI_SR_TCFQF)) { - tx_word = is_double_byte_mode(dspi); - + /* Get transfer counter (in number of SPI transfers). It was + * reset to 0 when transfer(s) were started. + */ regmap_read(dspi->regmap, SPI_TCR, &spi_tcr); spi_tcnt = SPI_TCR_GET_TCNT(spi_tcr); - /* - * The width of SPI Transfer Counter in SPI_TCR is 16bits, - * so the max couner is 65535. When the counter reach 65535, - * it will wrap around, counter reset to zero. - * spi_tcnt my be less than dspi->spi_tcnt, it means the - * counter already wrapped around. - * SPI Transfer Counter is a counter of transmitted frames. - * The size of frame maybe two bytes. - */ - tcnt_diff = ((spi_tcnt + SPI_TCR_TCNT_MAX) - dspi->spi_tcnt) - % SPI_TCR_TCNT_MAX; - tcnt_diff *= (tx_word + 1); - if (dspi->dataflags & TRAN_STATE_WORD_ODD_NUM) - tcnt_diff--; - - msg->actual_length += tcnt_diff; - - dspi->spi_tcnt = spi_tcnt; + /* Update total number of bytes that were transferred */ + msg->actual_length += spi_tcnt * dspi->bytes_per_word; trans_mode = dspi->devtype_data->trans_mode; switch (trans_mode) { @@ -873,14 +860,6 @@ static irqreturn_t dspi_interrupt(int irq, void *dev_id) } if (!dspi->len) { - if (dspi->dataflags & TRAN_STATE_WORD_ODD_NUM) { - regmap_update_bits(dspi->regmap, - SPI_CTAR(0), - SPI_FRAME_BITS_MASK, - SPI_FRAME_BITS(16)); - dspi->dataflags &= ~TRAN_STATE_WORD_ODD_NUM; - } - dspi->waitflags = 1; wake_up_interruptible(&dspi->waitq); } else { @@ -943,16 +922,62 @@ static int dspi_resume(struct device *dev) static SIMPLE_DEV_PM_OPS(dspi_pm, dspi_suspend, dspi_resume); +static const struct regmap_range dspi_volatile_ranges[] = { + regmap_reg_range(SPI_MCR, SPI_TCR), + regmap_reg_range(SPI_SR, SPI_SR), + regmap_reg_range(SPI_PUSHR, SPI_RXFR3), +}; + +static const struct regmap_access_table dspi_volatile_table = { + .yes_ranges = dspi_volatile_ranges, + .n_yes_ranges = ARRAY_SIZE(dspi_volatile_ranges), +}; + static const struct regmap_config dspi_regmap_config = { .reg_bits = 32, .val_bits = 32, .reg_stride = 4, .max_register = 0x88, + .volatile_table = &dspi_volatile_table, +}; + +static const struct regmap_range dspi_xspi_volatile_ranges[] = { + regmap_reg_range(SPI_MCR, SPI_TCR), + regmap_reg_range(SPI_SR, SPI_SR), + regmap_reg_range(SPI_PUSHR, SPI_RXFR3), + regmap_reg_range(SPI_SREX, SPI_SREX), +}; + +static const struct regmap_access_table dspi_xspi_volatile_table = { + .yes_ranges = dspi_xspi_volatile_ranges, + .n_yes_ranges = ARRAY_SIZE(dspi_xspi_volatile_ranges), +}; + +static const struct regmap_config dspi_xspi_regmap_config[] = { + { + .reg_bits = 32, + .val_bits = 32, + .reg_stride = 4, + .max_register = 0x13c, + .volatile_table = &dspi_xspi_volatile_table, + }, + { + .name = "pushr", + .reg_bits = 16, + .val_bits = 16, + .reg_stride = 2, + .max_register = 0x2, + }, }; static void dspi_init(struct fsl_dspi *dspi) { + regmap_write(dspi->regmap, SPI_MCR, SPI_MCR_MASTER | SPI_MCR_PCSIS | + (dspi->devtype_data->xspi_mode ? SPI_MCR_XSPI : 0)); regmap_write(dspi->regmap, SPI_SR, SPI_SR_CLEAR); + if (dspi->devtype_data->xspi_mode) + regmap_write(dspi->regmap, SPI_CTARE(0), + SPI_CTARE_FMSZE(0) | SPI_CTARE_DTCP(1)); } static int dspi_probe(struct platform_device *pdev) @@ -961,6 +986,7 @@ static int dspi_probe(struct platform_device *pdev) struct spi_master *master; struct fsl_dspi *dspi; struct resource *res; + const struct regmap_config *regmap_config; void __iomem *base; struct fsl_dspi_platform_data *pdata; int ret = 0, cs_num, bus_num; @@ -980,8 +1006,6 @@ static int dspi_probe(struct platform_device *pdev) master->cleanup = dspi_cleanup; master->mode_bits = SPI_CPOL | SPI_CPHA | SPI_LSB_FIRST; - master->bits_per_word_mask = SPI_BPW_MASK(4) | SPI_BPW_MASK(8) | - SPI_BPW_MASK(16); pdata = dev_get_platdata(&pdev->dev); if (pdata) { @@ -1013,6 +1037,11 @@ static int dspi_probe(struct platform_device *pdev) } } + if (dspi->devtype_data->xspi_mode) + master->bits_per_word_mask = SPI_BPW_RANGE_MASK(4, 32); + else + master->bits_per_word_mask = SPI_BPW_RANGE_MASK(4, 16); + res = platform_get_resource(pdev, IORESOURCE_MEM, 0); base = devm_ioremap_resource(&pdev->dev, res); if (IS_ERR(base)) { @@ -1020,8 +1049,11 @@ static int dspi_probe(struct platform_device *pdev) goto out_master_put; } - dspi->regmap = devm_regmap_init_mmio_clk(&pdev->dev, NULL, base, - &dspi_regmap_config); + if (dspi->devtype_data->xspi_mode) + regmap_config = &dspi_xspi_regmap_config[0]; + else + regmap_config = &dspi_regmap_config; + dspi->regmap = devm_regmap_init_mmio(&pdev->dev, base, regmap_config); if (IS_ERR(dspi->regmap)) { dev_err(&pdev->dev, "failed to init regmap: %ld\n", PTR_ERR(dspi->regmap)); @@ -1029,30 +1061,43 @@ static int dspi_probe(struct platform_device *pdev) goto out_master_put; } + if (dspi->devtype_data->xspi_mode) { + dspi->regmap_pushr = devm_regmap_init_mmio( + &pdev->dev, base + SPI_PUSHR, + &dspi_xspi_regmap_config[1]); + if (IS_ERR(dspi->regmap_pushr)) { + dev_err(&pdev->dev, + "failed to init pushr regmap: %ld\n", + PTR_ERR(dspi->regmap_pushr)); + ret = PTR_ERR(dspi->regmap_pushr); + goto out_master_put; + } + } + + dspi->clk = devm_clk_get(&pdev->dev, "dspi"); + if (IS_ERR(dspi->clk)) { + ret = PTR_ERR(dspi->clk); + dev_err(&pdev->dev, "unable to get clock\n"); + goto out_master_put; + } + ret = clk_prepare_enable(dspi->clk); + if (ret) + goto out_master_put; + dspi_init(dspi); dspi->irq = platform_get_irq(pdev, 0); if (dspi->irq < 0) { dev_err(&pdev->dev, "can't get platform irq\n"); ret = dspi->irq; - goto out_master_put; + goto out_clk_put; } ret = devm_request_irq(&pdev->dev, dspi->irq, dspi_interrupt, 0, pdev->name, dspi); if (ret < 0) { dev_err(&pdev->dev, "Unable to attach DSPI interrupt\n"); - goto out_master_put; - } - - dspi->clk = devm_clk_get(&pdev->dev, "dspi"); - if (IS_ERR(dspi->clk)) { - ret = PTR_ERR(dspi->clk); - dev_err(&pdev->dev, "unable to get clock\n"); - goto out_master_put; + goto out_clk_put; } - ret = clk_prepare_enable(dspi->clk); - if (ret) - goto out_master_put; if (dspi->devtype_data->trans_mode == DSPI_DMA_MODE) { ret = dspi_request_dma(dspi, res->start); diff --git a/drivers/spi/spi-orion.c b/drivers/spi/spi-orion.c index d01a6adc726e..47ef6b1a2e76 100644 --- a/drivers/spi/spi-orion.c +++ b/drivers/spi/spi-orion.c @@ -20,6 +20,7 @@ #include <linux/of.h> #include <linux/of_address.h> #include <linux/of_device.h> +#include <linux/of_gpio.h> #include <linux/clk.h> #include <linux/sizes.h> #include <linux/gpio.h> @@ -681,9 +682,9 @@ static int orion_spi_probe(struct platform_device *pdev) goto out_rel_axi_clk; } - /* Scan all SPI devices of this controller for direct mapped devices */ for_each_available_child_of_node(pdev->dev.of_node, np) { u32 cs; + int cs_gpio; /* Get chip-select number from the "reg" property */ status = of_property_read_u32(np, "reg", &cs); @@ -695,6 +696,44 @@ static int orion_spi_probe(struct platform_device *pdev) } /* + * Initialize the CS GPIO: + * - properly request the actual GPIO signal + * - de-assert the logical signal so that all GPIO CS lines + * are inactive when probing for slaves + * - find an unused physical CS which will be driven for any + * slave which uses a CS GPIO + */ + cs_gpio = of_get_named_gpio(pdev->dev.of_node, "cs-gpios", cs); + if (cs_gpio > 0) { + char *gpio_name; + int cs_flags; + + if (spi->unused_hw_gpio == -1) { + dev_info(&pdev->dev, + "Selected unused HW CS#%d for any GPIO CSes\n", + cs); + spi->unused_hw_gpio = cs; + } + + gpio_name = devm_kasprintf(&pdev->dev, GFP_KERNEL, + "%s-CS%d", dev_name(&pdev->dev), cs); + if (!gpio_name) { + status = -ENOMEM; + goto out_rel_axi_clk; + } + + cs_flags = of_property_read_bool(np, "spi-cs-high") ? + GPIOF_OUT_INIT_LOW : GPIOF_OUT_INIT_HIGH; + status = devm_gpio_request_one(&pdev->dev, cs_gpio, + cs_flags, gpio_name); + if (status) { + dev_err(&pdev->dev, + "Can't request GPIO for CS %d\n", cs); + goto out_rel_axi_clk; + } + } + + /* * Check if an address is configured for this SPI device. If * not, the MBus mapping via the 'ranges' property in the 'soc' * node is not configured and this device should not use the @@ -740,44 +779,8 @@ static int orion_spi_probe(struct platform_device *pdev) if (status < 0) goto out_rel_pm; - if (master->cs_gpios) { - int i; - for (i = 0; i < master->num_chipselect; ++i) { - char *gpio_name; - - if (!gpio_is_valid(master->cs_gpios[i])) { - continue; - } - - gpio_name = devm_kasprintf(&pdev->dev, GFP_KERNEL, - "%s-CS%d", dev_name(&pdev->dev), i); - if (!gpio_name) { - status = -ENOMEM; - goto out_rel_master; - } - - status = devm_gpio_request(&pdev->dev, - master->cs_gpios[i], gpio_name); - if (status) { - dev_err(&pdev->dev, - "Can't request GPIO for CS %d\n", - master->cs_gpios[i]); - goto out_rel_master; - } - if (spi->unused_hw_gpio == -1) { - dev_info(&pdev->dev, - "Selected unused HW CS#%d for any GPIO CSes\n", - i); - spi->unused_hw_gpio = i; - } - } - } - - return status; -out_rel_master: - spi_unregister_master(master); out_rel_pm: pm_runtime_disable(&pdev->dev); out_rel_axi_clk: diff --git a/drivers/spi/spi-pxa2xx.c b/drivers/spi/spi-pxa2xx.c index 0b2d60d30f69..14f4ea59caff 100644 --- a/drivers/spi/spi-pxa2xx.c +++ b/drivers/spi/spi-pxa2xx.c @@ -1391,6 +1391,10 @@ static const struct pci_device_id pxa2xx_spi_pci_compound_match[] = { { PCI_VDEVICE(INTEL, 0x31c2), LPSS_BXT_SSP }, { PCI_VDEVICE(INTEL, 0x31c4), LPSS_BXT_SSP }, { PCI_VDEVICE(INTEL, 0x31c6), LPSS_BXT_SSP }, + /* ICL-LP */ + { PCI_VDEVICE(INTEL, 0x34aa), LPSS_CNL_SSP }, + { PCI_VDEVICE(INTEL, 0x34ab), LPSS_CNL_SSP }, + { PCI_VDEVICE(INTEL, 0x34fb), LPSS_CNL_SSP }, /* APL */ { PCI_VDEVICE(INTEL, 0x5ac2), LPSS_BXT_SSP }, { PCI_VDEVICE(INTEL, 0x5ac4), LPSS_BXT_SSP }, diff --git a/drivers/spi/spi-sh-msiof.c b/drivers/spi/spi-sh-msiof.c index 0e74cbf9929d..539d6d1a277a 100644 --- a/drivers/spi/spi-sh-msiof.c +++ b/drivers/spi/spi-sh-msiof.c @@ -49,6 +49,7 @@ struct sh_msiof_spi_priv { struct platform_device *pdev; struct sh_msiof_spi_info *info; struct completion done; + struct completion done_txdma; unsigned int tx_fifo_size; unsigned int rx_fifo_size; unsigned int min_div_pow; @@ -649,19 +650,21 @@ static int sh_msiof_slave_abort(struct spi_master *master) p->slave_aborted = true; complete(&p->done); + complete(&p->done_txdma); return 0; } -static int sh_msiof_wait_for_completion(struct sh_msiof_spi_priv *p) +static int sh_msiof_wait_for_completion(struct sh_msiof_spi_priv *p, + struct completion *x) { if (spi_controller_is_slave(p->master)) { - if (wait_for_completion_interruptible(&p->done) || + if (wait_for_completion_interruptible(x) || p->slave_aborted) { dev_dbg(&p->pdev->dev, "interrupted\n"); return -EINTR; } } else { - if (!wait_for_completion_timeout(&p->done, HZ)) { + if (!wait_for_completion_timeout(x, HZ)) { dev_err(&p->pdev->dev, "timeout\n"); return -ETIMEDOUT; } @@ -711,7 +714,7 @@ static int sh_msiof_spi_txrx_once(struct sh_msiof_spi_priv *p, } /* wait for tx fifo to be emptied / rx fifo to be filled */ - ret = sh_msiof_wait_for_completion(p); + ret = sh_msiof_wait_for_completion(p, &p->done); if (ret) goto stop_reset; @@ -740,10 +743,7 @@ stop_ier: static void sh_msiof_dma_complete(void *arg) { - struct sh_msiof_spi_priv *p = arg; - - sh_msiof_write(p, IER, 0); - complete(&p->done); + complete(arg); } static int sh_msiof_dma_once(struct sh_msiof_spi_priv *p, const void *tx, @@ -764,7 +764,7 @@ static int sh_msiof_dma_once(struct sh_msiof_spi_priv *p, const void *tx, return -EAGAIN; desc_rx->callback = sh_msiof_dma_complete; - desc_rx->callback_param = p; + desc_rx->callback_param = &p->done; cookie = dmaengine_submit(desc_rx); if (dma_submit_error(cookie)) return cookie; @@ -782,13 +782,8 @@ static int sh_msiof_dma_once(struct sh_msiof_spi_priv *p, const void *tx, goto no_dma_tx; } - if (rx) { - /* No callback */ - desc_tx->callback = NULL; - } else { - desc_tx->callback = sh_msiof_dma_complete; - desc_tx->callback_param = p; - } + desc_tx->callback = sh_msiof_dma_complete; + desc_tx->callback_param = &p->done_txdma; cookie = dmaengine_submit(desc_tx); if (dma_submit_error(cookie)) { ret = cookie; @@ -805,6 +800,8 @@ static int sh_msiof_dma_once(struct sh_msiof_spi_priv *p, const void *tx, sh_msiof_write(p, IER, ier_bits); reinit_completion(&p->done); + if (tx) + reinit_completion(&p->done_txdma); p->slave_aborted = false; /* Now start DMA */ @@ -819,17 +816,24 @@ static int sh_msiof_dma_once(struct sh_msiof_spi_priv *p, const void *tx, goto stop_dma; } - /* wait for tx/rx DMA completion */ - ret = sh_msiof_wait_for_completion(p); - if (ret) - goto stop_reset; + if (tx) { + /* wait for tx DMA completion */ + ret = sh_msiof_wait_for_completion(p, &p->done_txdma); + if (ret) + goto stop_reset; + } - if (!rx) { - reinit_completion(&p->done); - sh_msiof_write(p, IER, IER_TEOFE); + if (rx) { + /* wait for rx DMA completion */ + ret = sh_msiof_wait_for_completion(p, &p->done); + if (ret) + goto stop_reset; + sh_msiof_write(p, IER, 0); + } else { /* wait for tx fifo to be emptied */ - ret = sh_msiof_wait_for_completion(p); + sh_msiof_write(p, IER, IER_TEOFE); + ret = sh_msiof_wait_for_completion(p, &p->done); if (ret) goto stop_reset; } @@ -1327,6 +1331,7 @@ static int sh_msiof_spi_probe(struct platform_device *pdev) p->min_div_pow = chipdata->min_div_pow; init_completion(&p->done); + init_completion(&p->done_txdma); p->clk = devm_clk_get(&pdev->dev, NULL); if (IS_ERR(p->clk)) { |