mirror of
https://github.com/openwrt/openwrt.git
synced 2024-12-27 01:11:14 +00:00
4ca54a5b39
SVN-Revision: 22862
144 lines
4.2 KiB
Diff
144 lines
4.2 KiB
Diff
From 4751c1c74bc7b596db5de0c93be1a22a570145c0 Mon Sep 17 00:00:00 2001
|
|
From: Ernst Schwab <eschwab@online.de>
|
|
Date: Thu, 18 Feb 2010 12:47:46 +0100
|
|
Subject: [PATCH] spi/mmc_spi: mmc_spi adaptations for SPI bus locking API
|
|
|
|
Modification of the mmc_spi driver to use the SPI bus locking API.
|
|
With this, the mmc_spi driver can be used together with other SPI
|
|
devices on the same SPI bus. The exclusive access to the SPI bus is
|
|
now managed in the SPI layer. The counting of chip selects in the probe
|
|
function is no longer needed.
|
|
|
|
Signed-off-by: Ernst Schwab <eschwab@online.de>
|
|
Signed-off-by: Grant Likely <grant.likely@secretlab.ca>
|
|
Tested-by: Matt Fleming <matt@console-pimps.org>
|
|
Tested-by: Antonio Ospite <ospite@studenti.unina.it>
|
|
---
|
|
drivers/mmc/host/mmc_spi.c | 59 ++++++++-----------------------------------
|
|
1 files changed, 11 insertions(+), 48 deletions(-)
|
|
|
|
--- a/drivers/mmc/host/mmc_spi.c
|
|
+++ b/drivers/mmc/host/mmc_spi.c
|
|
@@ -181,7 +181,7 @@ mmc_spi_readbytes(struct mmc_spi_host *h
|
|
host->data_dma, sizeof(*host->data),
|
|
DMA_FROM_DEVICE);
|
|
|
|
- status = spi_sync(host->spi, &host->readback);
|
|
+ status = spi_sync_locked(host->spi, &host->readback);
|
|
|
|
if (host->dma_dev)
|
|
dma_sync_single_for_cpu(host->dma_dev,
|
|
@@ -540,7 +540,7 @@ mmc_spi_command_send(struct mmc_spi_host
|
|
host->data_dma, sizeof(*host->data),
|
|
DMA_BIDIRECTIONAL);
|
|
}
|
|
- status = spi_sync(host->spi, &host->m);
|
|
+ status = spi_sync_locked(host->spi, &host->m);
|
|
|
|
if (host->dma_dev)
|
|
dma_sync_single_for_cpu(host->dma_dev,
|
|
@@ -684,7 +684,7 @@ mmc_spi_writeblock(struct mmc_spi_host *
|
|
host->data_dma, sizeof(*scratch),
|
|
DMA_BIDIRECTIONAL);
|
|
|
|
- status = spi_sync(spi, &host->m);
|
|
+ status = spi_sync_locked(spi, &host->m);
|
|
|
|
if (status != 0) {
|
|
dev_dbg(&spi->dev, "write error (%d)\n", status);
|
|
@@ -821,7 +821,7 @@ mmc_spi_readblock(struct mmc_spi_host *h
|
|
DMA_FROM_DEVICE);
|
|
}
|
|
|
|
- status = spi_sync(spi, &host->m);
|
|
+ status = spi_sync_locked(spi, &host->m);
|
|
|
|
if (host->dma_dev) {
|
|
dma_sync_single_for_cpu(host->dma_dev,
|
|
@@ -1017,7 +1017,7 @@ mmc_spi_data_do(struct mmc_spi_host *hos
|
|
host->data_dma, sizeof(*scratch),
|
|
DMA_BIDIRECTIONAL);
|
|
|
|
- tmp = spi_sync(spi, &host->m);
|
|
+ tmp = spi_sync_locked(spi, &host->m);
|
|
|
|
if (host->dma_dev)
|
|
dma_sync_single_for_cpu(host->dma_dev,
|
|
@@ -1083,6 +1083,9 @@ static void mmc_spi_request(struct mmc_h
|
|
}
|
|
#endif
|
|
|
|
+ /* request exclusive bus access */
|
|
+ spi_bus_lock(host->spi->master);
|
|
+
|
|
/* issue command; then optionally data and stop */
|
|
status = mmc_spi_command_send(host, mrq, mrq->cmd, mrq->data != NULL);
|
|
if (status == 0 && mrq->data) {
|
|
@@ -1093,6 +1096,9 @@ static void mmc_spi_request(struct mmc_h
|
|
mmc_cs_off(host);
|
|
}
|
|
|
|
+ /* release the bus */
|
|
+ spi_bus_unlock(host->spi->master);
|
|
+
|
|
mmc_request_done(host->mmc, mrq);
|
|
}
|
|
|
|
@@ -1289,23 +1295,6 @@ mmc_spi_detect_irq(int irq, void *mmc)
|
|
return IRQ_HANDLED;
|
|
}
|
|
|
|
-struct count_children {
|
|
- unsigned n;
|
|
- struct bus_type *bus;
|
|
-};
|
|
-
|
|
-static int maybe_count_child(struct device *dev, void *c)
|
|
-{
|
|
- struct count_children *ccp = c;
|
|
-
|
|
- if (dev->bus == ccp->bus) {
|
|
- if (ccp->n)
|
|
- return -EBUSY;
|
|
- ccp->n++;
|
|
- }
|
|
- return 0;
|
|
-}
|
|
-
|
|
static int mmc_spi_probe(struct spi_device *spi)
|
|
{
|
|
void *ones;
|
|
@@ -1337,32 +1326,6 @@ static int mmc_spi_probe(struct spi_devi
|
|
return status;
|
|
}
|
|
|
|
- /* We can use the bus safely iff nobody else will interfere with us.
|
|
- * Most commands consist of one SPI message to issue a command, then
|
|
- * several more to collect its response, then possibly more for data
|
|
- * transfer. Clocking access to other devices during that period will
|
|
- * corrupt the command execution.
|
|
- *
|
|
- * Until we have software primitives which guarantee non-interference,
|
|
- * we'll aim for a hardware-level guarantee.
|
|
- *
|
|
- * REVISIT we can't guarantee another device won't be added later...
|
|
- */
|
|
- if (spi->master->num_chipselect > 1) {
|
|
- struct count_children cc;
|
|
-
|
|
- cc.n = 0;
|
|
- cc.bus = spi->dev.bus;
|
|
- status = device_for_each_child(spi->dev.parent, &cc,
|
|
- maybe_count_child);
|
|
- if (status < 0) {
|
|
- dev_err(&spi->dev, "can't share SPI bus\n");
|
|
- return status;
|
|
- }
|
|
-
|
|
- dev_warn(&spi->dev, "ASSUMING SPI bus stays unshared!\n");
|
|
- }
|
|
-
|
|
/* We need a supply of ones to transmit. This is the only time
|
|
* the CPU touches these, so cache coherency isn't a concern.
|
|
*
|