spi: spi-mxs: add support 9-16 bits per word transfer
This commit is contained in:
parent
91059a9eae
commit
ec75fd1c93
|
@ -68,6 +68,13 @@ static int mxs_spi_setup_transfer(struct spi_device *dev,
|
||||||
struct mxs_ssp *ssp = &spi->ssp;
|
struct mxs_ssp *ssp = &spi->ssp;
|
||||||
const unsigned int hz = min(dev->max_speed_hz, t->speed_hz);
|
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) {
|
if (hz == 0) {
|
||||||
dev_err(&dev->dev, "SPI clock rate of zero not allowed\n");
|
dev_err(&dev->dev, "SPI clock rate of zero not allowed\n");
|
||||||
return -EINVAL;
|
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);
|
ssp->base + HW_SSP_CTRL0 + STMP_OFFSET_REG_SET);
|
||||||
|
|
||||||
writel(BF_SSP_CTRL1_SSP_MODE(BV_SSP_CTRL1_SSP_MODE__SPI) |
|
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_CPOL) ? BM_SSP_CTRL1_POLARITY : 0) |
|
||||||
((dev->mode & SPI_CPHA) ? BM_SSP_CTRL1_PHASE : 0),
|
((dev->mode & SPI_CPHA) ? BM_SSP_CTRL1_PHASE : 0),
|
||||||
ssp->base + HW_SSP_CTRL1(ssp));
|
ssp->base + HW_SSP_CTRL1(ssp));
|
||||||
|
@ -297,14 +304,18 @@ err_mapped:
|
||||||
}
|
}
|
||||||
|
|
||||||
static int mxs_spi_txrx_pio(struct mxs_spi *spi,
|
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)
|
unsigned int flags)
|
||||||
{
|
{
|
||||||
struct mxs_ssp *ssp = &spi->ssp;
|
struct mxs_ssp *ssp = &spi->ssp;
|
||||||
|
u32 val;
|
||||||
|
|
||||||
writel(BM_SSP_CTRL0_IGNORE_CRC,
|
writel(BM_SSP_CTRL0_IGNORE_CRC,
|
||||||
ssp->base + HW_SSP_CTRL0 + STMP_OFFSET_REG_CLR);
|
ssp->base + HW_SSP_CTRL0 + STMP_OFFSET_REG_CLR);
|
||||||
|
|
||||||
|
if (bit_per_word > 8)
|
||||||
|
len /= 2;
|
||||||
|
|
||||||
while (len--) {
|
while (len--) {
|
||||||
if (len == 0 && (flags & TXRX_DEASSERT_CS))
|
if (len == 0 && (flags & TXRX_DEASSERT_CS))
|
||||||
writel(BM_SSP_CTRL0_IGNORE_CRC,
|
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))
|
if (mxs_ssp_wait(spi, HW_SSP_CTRL0, BM_SSP_CTRL0_RUN, 1))
|
||||||
return -ETIMEDOUT;
|
return -ETIMEDOUT;
|
||||||
|
|
||||||
if (flags & TXRX_WRITE)
|
if (flags & TXRX_WRITE) {
|
||||||
writel(*buf, ssp->base + HW_SSP_DATA(ssp));
|
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,
|
writel(BM_SSP_CTRL0_DATA_XFER,
|
||||||
ssp->base + HW_SSP_CTRL0 + STMP_OFFSET_REG_SET);
|
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))
|
BM_SSP_STATUS_FIFO_EMPTY, 0))
|
||||||
return -ETIMEDOUT;
|
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))
|
if (mxs_ssp_wait(spi, HW_SSP_CTRL0, BM_SSP_CTRL0_RUN, 0))
|
||||||
return -ETIMEDOUT;
|
return -ETIMEDOUT;
|
||||||
|
|
||||||
buf++;
|
if (bit_per_word > 8)
|
||||||
|
buf += 2;
|
||||||
|
else
|
||||||
|
buf++;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (len <= 0)
|
if (len <= 0)
|
||||||
|
@ -401,11 +426,13 @@ static int mxs_spi_transfer_one(struct spi_master *master,
|
||||||
|
|
||||||
if (t->tx_buf)
|
if (t->tx_buf)
|
||||||
status = mxs_spi_txrx_pio(spi,
|
status = mxs_spi_txrx_pio(spi,
|
||||||
(void *)t->tx_buf,
|
(void *)t->tx_buf, t->len,
|
||||||
t->len, flag | TXRX_WRITE);
|
t->bits_per_word,
|
||||||
|
flag | TXRX_WRITE);
|
||||||
if (t->rx_buf)
|
if (t->rx_buf)
|
||||||
status = mxs_spi_txrx_pio(spi,
|
status = mxs_spi_txrx_pio(spi,
|
||||||
t->rx_buf, t->len,
|
t->rx_buf, t->len,
|
||||||
|
t->bits_per_word,
|
||||||
flag);
|
flag);
|
||||||
} else {
|
} else {
|
||||||
writel(BM_SSP_CTRL1_DMA_ENABLE,
|
writel(BM_SSP_CTRL1_DMA_ENABLE,
|
||||||
|
@ -569,7 +596,7 @@ static int mxs_spi_probe(struct platform_device *pdev)
|
||||||
platform_set_drvdata(pdev, master);
|
platform_set_drvdata(pdev, master);
|
||||||
|
|
||||||
master->transfer_one_message = mxs_spi_transfer_one;
|
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->mode_bits = SPI_CPOL | SPI_CPHA;
|
||||||
master->num_chipselect = 3;
|
master->num_chipselect = 3;
|
||||||
master->dev.of_node = np;
|
master->dev.of_node = np;
|
||||||
|
|
Loading…
Reference in New Issue