spi: spi-mxs: add support 9-16 bits per word transfer

This commit is contained in:
Suguru Saito 2021-10-03 20:48:29 +09:00 committed by Takumi Sueda
parent 91059a9eae
commit ec75fd1c93
1 changed files with 36 additions and 9 deletions

View File

@ -68,6 +68,13 @@ static int mxs_spi_setup_transfer(struct spi_device *dev,
struct mxs_ssp *ssp = &spi->ssp;
const unsigned int hz = min(dev->max_speed_hz, t->speed_hz);
if (t->bits_per_word > 8) {
if (t->len & 1) {
dev_err(&dev->dev, "Invalid size of rx and tx buffers\n");
return -EINVAL;
}
}
if (hz == 0) {
dev_err(&dev->dev, "SPI clock rate of zero not allowed\n");
return -EINVAL;
@ -91,7 +98,7 @@ static int mxs_spi_setup_transfer(struct spi_device *dev,
ssp->base + HW_SSP_CTRL0 + STMP_OFFSET_REG_SET);
writel(BF_SSP_CTRL1_SSP_MODE(BV_SSP_CTRL1_SSP_MODE__SPI) |
BF_SSP_CTRL1_WORD_LENGTH(BV_SSP_CTRL1_WORD_LENGTH__EIGHT_BITS) |
BF_SSP_CTRL1_WORD_LENGTH(t->bits_per_word - 1) |
((dev->mode & SPI_CPOL) ? BM_SSP_CTRL1_POLARITY : 0) |
((dev->mode & SPI_CPHA) ? BM_SSP_CTRL1_PHASE : 0),
ssp->base + HW_SSP_CTRL1(ssp));
@ -297,14 +304,18 @@ err_mapped:
}
static int mxs_spi_txrx_pio(struct mxs_spi *spi,
unsigned char *buf, int len,
unsigned char *buf, int len, u8 bit_per_word,
unsigned int flags)
{
struct mxs_ssp *ssp = &spi->ssp;
u32 val;
writel(BM_SSP_CTRL0_IGNORE_CRC,
ssp->base + HW_SSP_CTRL0 + STMP_OFFSET_REG_CLR);
if (bit_per_word > 8)
len /= 2;
while (len--) {
if (len == 0 && (flags & TXRX_DEASSERT_CS))
writel(BM_SSP_CTRL0_IGNORE_CRC,
@ -332,8 +343,14 @@ static int mxs_spi_txrx_pio(struct mxs_spi *spi,
if (mxs_ssp_wait(spi, HW_SSP_CTRL0, BM_SSP_CTRL0_RUN, 1))
return -ETIMEDOUT;
if (flags & TXRX_WRITE)
writel(*buf, ssp->base + HW_SSP_DATA(ssp));
if (flags & TXRX_WRITE) {
if (bit_per_word > 8)
val = *(u16*)(buf);
else
val = *buf;
writel(val, ssp->base + HW_SSP_DATA(ssp));
}
writel(BM_SSP_CTRL0_DATA_XFER,
ssp->base + HW_SSP_CTRL0 + STMP_OFFSET_REG_SET);
@ -343,13 +360,21 @@ static int mxs_spi_txrx_pio(struct mxs_spi *spi,
BM_SSP_STATUS_FIFO_EMPTY, 0))
return -ETIMEDOUT;
*buf = (readl(ssp->base + HW_SSP_DATA(ssp)) & 0xff);
val = readl(ssp->base + HW_SSP_DATA(ssp));
if (bit_per_word > 8)
*(u16*)buf = val & ((1 << bit_per_word) - 1);
else
*buf = val & 0xff;
}
if (mxs_ssp_wait(spi, HW_SSP_CTRL0, BM_SSP_CTRL0_RUN, 0))
return -ETIMEDOUT;
buf++;
if (bit_per_word > 8)
buf += 2;
else
buf++;
}
if (len <= 0)
@ -401,11 +426,13 @@ static int mxs_spi_transfer_one(struct spi_master *master,
if (t->tx_buf)
status = mxs_spi_txrx_pio(spi,
(void *)t->tx_buf,
t->len, flag | TXRX_WRITE);
(void *)t->tx_buf, t->len,
t->bits_per_word,
flag | TXRX_WRITE);
if (t->rx_buf)
status = mxs_spi_txrx_pio(spi,
t->rx_buf, t->len,
t->bits_per_word,
flag);
} else {
writel(BM_SSP_CTRL1_DMA_ENABLE,
@ -569,7 +596,7 @@ static int mxs_spi_probe(struct platform_device *pdev)
platform_set_drvdata(pdev, master);
master->transfer_one_message = mxs_spi_transfer_one;
master->bits_per_word_mask = SPI_BPW_MASK(8);
master->bits_per_word_mask = SPI_BPW_RANGE_MASK(8, 16);
master->mode_bits = SPI_CPOL | SPI_CPHA;
master->num_chipselect = 3;
master->dev.of_node = np;