Commit 5ce3cc56 authored by Lukasz Majewski's avatar Lukasz Majewski Committed by Mark Brown

spi: spi-fsl-dspi: Provide support for DSPI slave mode operation (Vybryd vf610)

The NXP's Vybryd vf610 can work as a SPI slave device (the CS and clock
signals are provided by master).

It is possible to specify a single device to work in that mode. As we do
use DMA for transferring data, the RX channel must be prepared for
incoming data.
Moreover, in slave mode we just set a subset of control fields in
configuration registers (CTAR0, PUSHR).

For testing the spidev_test program has been used.
Test script for this patch can be found here:
https://github.com/lmajewski/tests-spi/blob/master/tests/spi/spi_tests.shSigned-off-by: default avatarLukasz Majewski <lukma@denx.de>
Signed-off-by: default avatarMark Brown <broonie@kernel.org>
parent 473a78a7
...@@ -233,6 +233,9 @@ static u32 dspi_pop_tx_pushr(struct fsl_dspi *dspi) ...@@ -233,6 +233,9 @@ static u32 dspi_pop_tx_pushr(struct fsl_dspi *dspi)
{ {
u16 cmd = dspi->tx_cmd, data = dspi_pop_tx(dspi); u16 cmd = dspi->tx_cmd, data = dspi_pop_tx(dspi);
if (spi_controller_is_slave(dspi->master))
return data;
if (dspi->len > 0) if (dspi->len > 0)
cmd |= SPI_PUSHR_CMD_CONT; cmd |= SPI_PUSHR_CMD_CONT;
return cmd << 16 | data; return cmd << 16 | data;
...@@ -329,6 +332,11 @@ static int dspi_next_xfer_dma_submit(struct fsl_dspi *dspi) ...@@ -329,6 +332,11 @@ static int dspi_next_xfer_dma_submit(struct fsl_dspi *dspi)
dma_async_issue_pending(dma->chan_rx); dma_async_issue_pending(dma->chan_rx);
dma_async_issue_pending(dma->chan_tx); dma_async_issue_pending(dma->chan_tx);
if (spi_controller_is_slave(dspi->master)) {
wait_for_completion_interruptible(&dspi->dma->cmd_rx_complete);
return 0;
}
time_left = wait_for_completion_timeout(&dspi->dma->cmd_tx_complete, time_left = wait_for_completion_timeout(&dspi->dma->cmd_tx_complete,
DMA_COMPLETION_TIMEOUT); DMA_COMPLETION_TIMEOUT);
if (time_left == 0) { if (time_left == 0) {
...@@ -798,14 +806,18 @@ static int dspi_setup(struct spi_device *spi) ...@@ -798,14 +806,18 @@ static int dspi_setup(struct spi_device *spi)
ns_delay_scale(&pasc, &asc, sck_cs_delay, clkrate); ns_delay_scale(&pasc, &asc, sck_cs_delay, clkrate);
chip->ctar_val = 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_CPHA(spi->mode & SPI_CPHA ? 1 : 0);
| SPI_CTAR_LSBFE(spi->mode & SPI_LSB_FIRST ? 1 : 0)
if (!spi_controller_is_slave(dspi->master)) {
chip->ctar_val |= SPI_CTAR_LSBFE(spi->mode &
SPI_LSB_FIRST ? 1 : 0)
| SPI_CTAR_PCSSCK(pcssck) | SPI_CTAR_PCSSCK(pcssck)
| SPI_CTAR_CSSCK(cssck) | SPI_CTAR_CSSCK(cssck)
| SPI_CTAR_PASC(pasc) | SPI_CTAR_PASC(pasc)
| SPI_CTAR_ASC(asc) | SPI_CTAR_ASC(asc)
| SPI_CTAR_PBR(pbr) | SPI_CTAR_PBR(pbr)
| SPI_CTAR_BR(br); | SPI_CTAR_BR(br);
}
spi_set_ctldata(spi, chip); spi_set_ctldata(spi, chip);
...@@ -970,8 +982,13 @@ static const struct regmap_config dspi_xspi_regmap_config[] = { ...@@ -970,8 +982,13 @@ static const struct regmap_config dspi_xspi_regmap_config[] = {
static void dspi_init(struct fsl_dspi *dspi) static void dspi_init(struct fsl_dspi *dspi)
{ {
regmap_write(dspi->regmap, SPI_MCR, SPI_MCR_MASTER | SPI_MCR_PCSIS | unsigned int mcr = SPI_MCR_PCSIS |
(dspi->devtype_data->xspi_mode ? SPI_MCR_XSPI : 0)); (dspi->devtype_data->xspi_mode ? SPI_MCR_XSPI : 0);
if (!spi_controller_is_slave(dspi->master))
mcr |= SPI_MCR_MASTER;
regmap_write(dspi->regmap, SPI_MCR, mcr);
regmap_write(dspi->regmap, SPI_SR, SPI_SR_CLEAR); regmap_write(dspi->regmap, SPI_SR, SPI_SR_CLEAR);
if (dspi->devtype_data->xspi_mode) if (dspi->devtype_data->xspi_mode)
regmap_write(dspi->regmap, SPI_CTARE(0), regmap_write(dspi->regmap, SPI_CTARE(0),
...@@ -1027,6 +1044,9 @@ static int dspi_probe(struct platform_device *pdev) ...@@ -1027,6 +1044,9 @@ static int dspi_probe(struct platform_device *pdev)
} }
master->bus_num = bus_num; master->bus_num = bus_num;
if (of_property_read_bool(np, "spi-slave"))
master->slave = true;
dspi->devtype_data = of_device_get_match_data(&pdev->dev); dspi->devtype_data = of_device_get_match_data(&pdev->dev);
if (!dspi->devtype_data) { if (!dspi->devtype_data) {
dev_err(&pdev->dev, "can't get devtype_data\n"); dev_err(&pdev->dev, "can't get devtype_data\n");
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment