aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/mmc/host/mmc_spi.c
diff options
context:
space:
mode:
authorLinus Walleij <linus.walleij@linaro.org>2019-12-04 16:27:49 +0100
committerUlf Hansson <ulf.hansson@linaro.org>2019-12-16 12:29:05 +0100
commitaf3ed119329cf9690598c5a562d95dfd128e91d6 (patch)
tree50877c05a8b81be132b6c506b6f9677de09acd72 /drivers/mmc/host/mmc_spi.c
parentmmc: sdhci-of-at91: rework clocks management to support SAM9x60 device (diff)
downloadlinux-dev-af3ed119329cf9690598c5a562d95dfd128e91d6.tar.xz
linux-dev-af3ed119329cf9690598c5a562d95dfd128e91d6.zip
mmc: spi: Toggle SPI polarity, do not hardcode it
The code in mmc_spi_initsequence() tries to send a burst with high chipselect and for this reason hardcodes the device into SPI_CS_HIGH. This is not good because the SPI_CS_HIGH flag indicates logical "asserted" CS not always the physical level. In some cases the signal is inverted in the GPIO library and in that case SPI_CS_HIGH is already set, and enforcing SPI_CS_HIGH again will actually drive it low. Instead of hard-coding this, toggle the polarity so if the default is LOW it goes high to assert chipselect but if it is already high then toggle it low instead. Cc: Phil Elwell <phil@raspberrypi.org> Reported-by: Mark Brown <broonie@kernel.org> Signed-off-by: Linus Walleij <linus.walleij@linaro.org> Reviewed-by: Mark Brown <broonie@kernel.org> Link: https://lore.kernel.org/r/20191204152749.12652-1-linus.walleij@linaro.org Cc: stable@vger.kernel.org Signed-off-by: Ulf Hansson <ulf.hansson@linaro.org>
Diffstat (limited to 'drivers/mmc/host/mmc_spi.c')
-rw-r--r--drivers/mmc/host/mmc_spi.c11
1 files changed, 8 insertions, 3 deletions
diff --git a/drivers/mmc/host/mmc_spi.c b/drivers/mmc/host/mmc_spi.c
index 74c6cfbf9172..1f02f54f09c0 100644
--- a/drivers/mmc/host/mmc_spi.c
+++ b/drivers/mmc/host/mmc_spi.c
@@ -1134,17 +1134,22 @@ static void mmc_spi_initsequence(struct mmc_spi_host *host)
* SPI protocol. Another is that when chipselect is released while
* the card returns BUSY status, the clock must issue several cycles
* with chipselect high before the card will stop driving its output.
+ *
+ * SPI_CS_HIGH means "asserted" here. In some cases like when using
+ * GPIOs for chip select, SPI_CS_HIGH is set but this will be logically
+ * inverted by gpiolib, so if we want to ascertain to drive it high
+ * we should toggle the default with an XOR as we do here.
*/
- host->spi->mode |= SPI_CS_HIGH;
+ host->spi->mode ^= SPI_CS_HIGH;
if (spi_setup(host->spi) != 0) {
/* Just warn; most cards work without it. */
dev_warn(&host->spi->dev,
"can't change chip-select polarity\n");
- host->spi->mode &= ~SPI_CS_HIGH;
+ host->spi->mode ^= SPI_CS_HIGH;
} else {
mmc_spi_readbytes(host, 18);
- host->spi->mode &= ~SPI_CS_HIGH;
+ host->spi->mode ^= SPI_CS_HIGH;
if (spi_setup(host->spi) != 0) {
/* Wot, we can't get the same setup we had before? */
dev_err(&host->spi->dev,