From f7f994a4c5f776823b527db5a9d86f27df573e76 Mon Sep 17 00:00:00 2001 From: Jingoo Han Date: Tue, 3 Jun 2014 21:01:40 +0900 Subject: spi: cadence: Make of_device_id array const Make of_device_id array const, because all OF functions handle it as const. Signed-off-by: Jingoo Han Acked-by: Harini Katakam Signed-off-by: Mark Brown --- drivers/spi/spi-cadence.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'drivers/spi/spi-cadence.c') diff --git a/drivers/spi/spi-cadence.c b/drivers/spi/spi-cadence.c index bb758978465d..98b763b705d7 100644 --- a/drivers/spi/spi-cadence.c +++ b/drivers/spi/spi-cadence.c @@ -647,7 +647,7 @@ static int __maybe_unused cdns_spi_resume(struct device *dev) static SIMPLE_DEV_PM_OPS(cdns_spi_dev_pm_ops, cdns_spi_suspend, cdns_spi_resume); -static struct of_device_id cdns_spi_of_match[] = { +static const struct of_device_id cdns_spi_of_match[] = { { .compatible = "xlnx,zynq-spi-r1p6" }, { .compatible = "cdns,spi-r1p6" }, { /* end of table */ } -- cgit v1.2.3 From a39e65e9cc935b84f35d080e934c3fdd9ff86654 Mon Sep 17 00:00:00 2001 From: Lars-Peter Clausen Date: Thu, 10 Jul 2014 11:26:28 +0200 Subject: spi: cadence: Make sure that clock polarity changes are applied It seems that the cadence SPI controller does not immediately change the clock polarity setting when writing the CR register. Instead the change is delayed until the next transfer starts. This happens after the chip select line has already been asserted. As a result the first transfer after a clock polarity change will generate spurious clock transitions which typically results in the SPI slave not being able to properly understand the message. Toggling the ER register seems to cause the SPI controller to apply the clock polarity changes, so implement this as a workaround to fix the issue. Signed-off-by: Lars-Peter Clausen Signed-off-by: Mark Brown --- drivers/spi/spi-cadence.c | 26 +++++++++++++++++++------- 1 file changed, 19 insertions(+), 7 deletions(-) (limited to 'drivers/spi/spi-cadence.c') diff --git a/drivers/spi/spi-cadence.c b/drivers/spi/spi-cadence.c index bb758978465d..f55702937052 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) static void cdns_spi_config_clock_mode(struct spi_device *spi) { struct cdns_spi *xspi = spi_master_get_devdata(spi->master); - u32 ctrl_reg; + u32 ctrl_reg, new_ctrl_reg; - ctrl_reg = cdns_spi_read(xspi, CDNS_SPI_CR_OFFSET); + new_ctrl_reg = ctrl_reg = cdns_spi_read(xspi, CDNS_SPI_CR_OFFSET); /* Set the SPI clock phase and clock polarity */ - ctrl_reg &= ~(CDNS_SPI_CR_CPHA_MASK | CDNS_SPI_CR_CPOL_MASK); + new_ctrl_reg &= ~(CDNS_SPI_CR_CPHA_MASK | CDNS_SPI_CR_CPOL_MASK); if (spi->mode & SPI_CPHA) - ctrl_reg |= CDNS_SPI_CR_CPHA_MASK; + new_ctrl_reg |= CDNS_SPI_CR_CPHA_MASK; if (spi->mode & SPI_CPOL) - ctrl_reg |= CDNS_SPI_CR_CPOL_MASK; - - cdns_spi_write(xspi, CDNS_SPI_CR_OFFSET, ctrl_reg); + new_ctrl_reg |= CDNS_SPI_CR_CPOL_MASK; + + if (new_ctrl_reg != ctrl_reg) { + /* + * Just writing the CR register does not seem to apply the clock + * setting changes. This is problematic when changing the clock + * polarity as it will cause the SPI slave to see spurious clock + * transitions. To workaround the issue toggle the ER register. + */ + cdns_spi_write(xspi, CDNS_SPI_ER_OFFSET, + CDNS_SPI_ER_DISABLE_MASK); + cdns_spi_write(xspi, CDNS_SPI_CR_OFFSET, new_ctrl_reg); + cdns_spi_write(xspi, CDNS_SPI_ER_OFFSET, + CDNS_SPI_ER_ENABLE_MASK); + } } /** -- cgit v1.2.3 From b48b9488e3180b173f37782a348b76ea6bff2c48 Mon Sep 17 00:00:00 2001 From: Lars-Peter Clausen Date: Thu, 10 Jul 2014 11:26:29 +0200 Subject: spi: cadence: Configure SPI clock in the prepare_message() callback Currently the cadence SPI driver does the SPI clock configuration (setup CPOL and CPHA) in the prepare_transfer_hardware() callback. The prepare_transfer_hardware() callback is only called though when the controller transitions from a idle state to a non-idle state. Such a transitions happens when the message queue goes from empty to non-empty. If multiple messages from different SPI slaves with different clock settings are in the message queue the clock settings will not be properly updated when switching from one slave device to another. Instead do the updating of the clock configuration in the prepare_message() callback which will be called for each individual message. Signed-off-by: Lars-Peter Clausen Signed-off-by: Mark Brown --- drivers/spi/spi-cadence.c | 9 +++++++-- 1 file changed, 7 insertions(+), 2 deletions(-) (limited to 'drivers/spi/spi-cadence.c') diff --git a/drivers/spi/spi-cadence.c b/drivers/spi/spi-cadence.c index f55702937052..3312eccb18c1 100644 --- a/drivers/spi/spi-cadence.c +++ b/drivers/spi/spi-cadence.c @@ -382,6 +382,12 @@ static irqreturn_t cdns_spi_irq(int irq, void *dev_id) return status; } +static int cdns_prepare_message(struct spi_master *master, + struct spi_message *msg) +{ + cdns_spi_config_clock_mode(msg->spi); + return 0; +} /** * cdns_transfer_one - Initiates the SPI transfer @@ -428,8 +434,6 @@ static int cdns_prepare_transfer_hardware(struct spi_master *master) { struct cdns_spi *xspi = spi_master_get_devdata(master); - cdns_spi_config_clock_mode(master->cur_msg->spi); - cdns_spi_write(xspi, CDNS_SPI_ER_OFFSET, CDNS_SPI_ER_ENABLE_MASK); @@ -544,6 +548,7 @@ static int cdns_spi_probe(struct platform_device *pdev) xspi->is_decoded_cs = 0; master->prepare_transfer_hardware = cdns_prepare_transfer_hardware; + master->prepare_message = cdns_prepare_message; master->transfer_one = cdns_transfer_one; master->unprepare_transfer_hardware = cdns_unprepare_transfer_hardware; master->set_cs = cdns_spi_chipselect; -- cgit v1.2.3