diff options
author | Baruch Siach <baruch.siach@siklu.com> | 2022-04-11 21:45:29 +0300 |
---|---|---|
committer | Mark Brown <broonie@kernel.org> | 2022-04-19 15:13:49 +0300 |
commit | 79422ed9bd7fbd79f84d8a5abb0094c16221f55b (patch) | |
tree | d2702c08c0fae229fbd9484a81afd7baff5a4744 /drivers/spi/spi-imx.c | |
parent | 178d0cbbfe8ec652083058968c7a27485eaa33d2 (diff) | |
download | linux-79422ed9bd7fbd79f84d8a5abb0094c16221f55b.tar.xz |
spi: spi-imx: add support for SPI_RX_CPHA_FLIP
When SPI_RX_CPHA_FLIP is set, flip CPHA on Rx only transfers. This is
useful to access devices that use inverted CPHA for MISO vs MOSI
signals.
Only support the mx51/mx53 variants for now.
Tested on i.MX6ULL based system.
Signed-off-by: Baruch Siach <baruch.siach@siklu.com>
Link: https://lore.kernel.org/r/e11b4446afe9a46a282dd923d22c27d03fae15f8.1649702729.git.baruch@tkos.co.il
Signed-off-by: Mark Brown <broonie@kernel.org>
Diffstat (limited to 'drivers/spi/spi-imx.c')
-rw-r--r-- | drivers/spi/spi-imx.c | 32 |
1 files changed, 27 insertions, 5 deletions
diff --git a/drivers/spi/spi-imx.c b/drivers/spi/spi-imx.c index b2dd0a4d2446..4e1bfe2f043a 100644 --- a/drivers/spi/spi-imx.c +++ b/drivers/spi/spi-imx.c @@ -108,6 +108,7 @@ struct spi_imx_data { const void *tx_buf; unsigned int txfifo; /* number of words pushed in tx FIFO */ unsigned int dynamic_burst; + bool rx_only; /* Slave mode */ bool slave_mode; @@ -554,11 +555,6 @@ static int mx51_ecspi_prepare_message(struct spi_imx_data *spi_imx, else cfg |= MX51_ECSPI_CONFIG_SBBCTRL(spi->chip_select); - if (spi->mode & SPI_CPHA) - cfg |= MX51_ECSPI_CONFIG_SCLKPHA(spi->chip_select); - else - cfg &= ~MX51_ECSPI_CONFIG_SCLKPHA(spi->chip_select); - if (spi->mode & SPI_CPOL) { cfg |= MX51_ECSPI_CONFIG_SCLKPOL(spi->chip_select); cfg |= MX51_ECSPI_CONFIG_SCLKCTL(spi->chip_select); @@ -606,6 +602,24 @@ static int mx51_ecspi_prepare_message(struct spi_imx_data *spi_imx, return 0; } +static void mx51_configure_cpha(struct spi_imx_data *spi_imx, + struct spi_device *spi) +{ + bool cpha = (spi->mode & SPI_CPHA); + bool flip_cpha = (spi->mode & SPI_RX_CPHA_FLIP) && spi_imx->rx_only; + u32 cfg = readl(spi_imx->base + MX51_ECSPI_CONFIG); + + /* Flip cpha logical value iff flip_cpha */ + cpha ^= flip_cpha; + + if (cpha) + cfg |= MX51_ECSPI_CONFIG_SCLKPHA(spi->chip_select); + else + cfg &= ~MX51_ECSPI_CONFIG_SCLKPHA(spi->chip_select); + + writel(cfg, spi_imx->base + MX51_ECSPI_CONFIG); +} + static int mx51_ecspi_prepare_transfer(struct spi_imx_data *spi_imx, struct spi_device *spi) { @@ -627,6 +641,8 @@ static int mx51_ecspi_prepare_transfer(struct spi_imx_data *spi_imx, ctrl |= mx51_ecspi_clkdiv(spi_imx, spi_imx->spi_bus_clk, &clk); spi_imx->spi_bus_clk = clk; + mx51_configure_cpha(spi_imx, spi); + /* * ERR009165: work in XHC mode instead of SMC as PIO on the chips * before i.mx6ul. @@ -1251,6 +1267,9 @@ static int spi_imx_setupxfer(struct spi_device *spi, else spi_imx->usedma = false; + spi_imx->rx_only = ((t->tx_buf == NULL) + || (t->tx_buf == spi->controller->dummy_tx)); + if (is_imx53_ecspi(spi_imx) && spi_imx->slave_mode) { spi_imx->rx = mx53_ecspi_rx_slave; spi_imx->tx = mx53_ecspi_tx_slave; @@ -1655,6 +1674,9 @@ static int spi_imx_probe(struct platform_device *pdev) is_imx53_ecspi(spi_imx)) spi_imx->bitbang.master->mode_bits |= SPI_LOOP | SPI_READY; + if (is_imx51_ecspi(spi_imx) || is_imx53_ecspi(spi_imx)) + spi_imx->bitbang.master->mode_bits |= SPI_RX_CPHA_FLIP; + if (is_imx51_ecspi(spi_imx) && device_property_read_u32(&pdev->dev, "cs-gpios", NULL)) /* |