diff options
Diffstat (limited to 'drivers/spi/spi-cadence.c')
-rw-r--r-- | drivers/spi/spi-cadence.c | 37 |
1 files changed, 27 insertions, 10 deletions
diff --git a/drivers/spi/spi-cadence.c b/drivers/spi/spi-cadence.c index bb758978465d..562ff83debd9 100644 --- a/drivers/spi/spi-cadence.c +++ b/drivers/spi/spi-cadence.c | |||
@@ -205,18 +205,30 @@ static void cdns_spi_chipselect(struct spi_device *spi, bool is_high) | |||
205 | static void cdns_spi_config_clock_mode(struct spi_device *spi) | 205 | static void cdns_spi_config_clock_mode(struct spi_device *spi) |
206 | { | 206 | { |
207 | struct cdns_spi *xspi = spi_master_get_devdata(spi->master); | 207 | struct cdns_spi *xspi = spi_master_get_devdata(spi->master); |
208 | u32 ctrl_reg; | 208 | u32 ctrl_reg, new_ctrl_reg; |
209 | 209 | ||
210 | ctrl_reg = cdns_spi_read(xspi, CDNS_SPI_CR_OFFSET); | 210 | new_ctrl_reg = ctrl_reg = cdns_spi_read(xspi, CDNS_SPI_CR_OFFSET); |
211 | 211 | ||
212 | /* Set the SPI clock phase and clock polarity */ | 212 | /* Set the SPI clock phase and clock polarity */ |
213 | ctrl_reg &= ~(CDNS_SPI_CR_CPHA_MASK | CDNS_SPI_CR_CPOL_MASK); | 213 | new_ctrl_reg &= ~(CDNS_SPI_CR_CPHA_MASK | CDNS_SPI_CR_CPOL_MASK); |
214 | if (spi->mode & SPI_CPHA) | 214 | if (spi->mode & SPI_CPHA) |
215 | ctrl_reg |= CDNS_SPI_CR_CPHA_MASK; | 215 | new_ctrl_reg |= CDNS_SPI_CR_CPHA_MASK; |
216 | if (spi->mode & SPI_CPOL) | 216 | if (spi->mode & SPI_CPOL) |
217 | ctrl_reg |= CDNS_SPI_CR_CPOL_MASK; | 217 | new_ctrl_reg |= CDNS_SPI_CR_CPOL_MASK; |
218 | 218 | ||
219 | cdns_spi_write(xspi, CDNS_SPI_CR_OFFSET, ctrl_reg); | 219 | if (new_ctrl_reg != ctrl_reg) { |
220 | /* | ||
221 | * Just writing the CR register does not seem to apply the clock | ||
222 | * setting changes. This is problematic when changing the clock | ||
223 | * polarity as it will cause the SPI slave to see spurious clock | ||
224 | * transitions. To workaround the issue toggle the ER register. | ||
225 | */ | ||
226 | cdns_spi_write(xspi, CDNS_SPI_ER_OFFSET, | ||
227 | CDNS_SPI_ER_DISABLE_MASK); | ||
228 | cdns_spi_write(xspi, CDNS_SPI_CR_OFFSET, new_ctrl_reg); | ||
229 | cdns_spi_write(xspi, CDNS_SPI_ER_OFFSET, | ||
230 | CDNS_SPI_ER_ENABLE_MASK); | ||
231 | } | ||
220 | } | 232 | } |
221 | 233 | ||
222 | /** | 234 | /** |
@@ -370,6 +382,12 @@ static irqreturn_t cdns_spi_irq(int irq, void *dev_id) | |||
370 | 382 | ||
371 | return status; | 383 | return status; |
372 | } | 384 | } |
385 | static int cdns_prepare_message(struct spi_master *master, | ||
386 | struct spi_message *msg) | ||
387 | { | ||
388 | cdns_spi_config_clock_mode(msg->spi); | ||
389 | return 0; | ||
390 | } | ||
373 | 391 | ||
374 | /** | 392 | /** |
375 | * cdns_transfer_one - Initiates the SPI transfer | 393 | * cdns_transfer_one - Initiates the SPI transfer |
@@ -416,8 +434,6 @@ static int cdns_prepare_transfer_hardware(struct spi_master *master) | |||
416 | { | 434 | { |
417 | struct cdns_spi *xspi = spi_master_get_devdata(master); | 435 | struct cdns_spi *xspi = spi_master_get_devdata(master); |
418 | 436 | ||
419 | cdns_spi_config_clock_mode(master->cur_msg->spi); | ||
420 | |||
421 | cdns_spi_write(xspi, CDNS_SPI_ER_OFFSET, | 437 | cdns_spi_write(xspi, CDNS_SPI_ER_OFFSET, |
422 | CDNS_SPI_ER_ENABLE_MASK); | 438 | CDNS_SPI_ER_ENABLE_MASK); |
423 | 439 | ||
@@ -532,6 +548,7 @@ static int cdns_spi_probe(struct platform_device *pdev) | |||
532 | xspi->is_decoded_cs = 0; | 548 | xspi->is_decoded_cs = 0; |
533 | 549 | ||
534 | master->prepare_transfer_hardware = cdns_prepare_transfer_hardware; | 550 | master->prepare_transfer_hardware = cdns_prepare_transfer_hardware; |
551 | master->prepare_message = cdns_prepare_message; | ||
535 | master->transfer_one = cdns_transfer_one; | 552 | master->transfer_one = cdns_transfer_one; |
536 | master->unprepare_transfer_hardware = cdns_unprepare_transfer_hardware; | 553 | master->unprepare_transfer_hardware = cdns_unprepare_transfer_hardware; |
537 | master->set_cs = cdns_spi_chipselect; | 554 | master->set_cs = cdns_spi_chipselect; |
@@ -647,7 +664,7 @@ static int __maybe_unused cdns_spi_resume(struct device *dev) | |||
647 | static SIMPLE_DEV_PM_OPS(cdns_spi_dev_pm_ops, cdns_spi_suspend, | 664 | static SIMPLE_DEV_PM_OPS(cdns_spi_dev_pm_ops, cdns_spi_suspend, |
648 | cdns_spi_resume); | 665 | cdns_spi_resume); |
649 | 666 | ||
650 | static struct of_device_id cdns_spi_of_match[] = { | 667 | static const struct of_device_id cdns_spi_of_match[] = { |
651 | { .compatible = "xlnx,zynq-spi-r1p6" }, | 668 | { .compatible = "xlnx,zynq-spi-r1p6" }, |
652 | { .compatible = "cdns,spi-r1p6" }, | 669 | { .compatible = "cdns,spi-r1p6" }, |
653 | { /* end of table */ } | 670 | { /* end of table */ } |