aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/mmc
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/mmc')
-rw-r--r--drivers/mmc/core/mmc_ops.c22
-rw-r--r--drivers/mmc/core/sd_ops.c4
-rw-r--r--drivers/mmc/host/au1xmmc.c6
-rw-r--r--drivers/mmc/host/imxmmc.c2
-rw-r--r--drivers/mmc/host/mmc_spi.c52
-rw-r--r--drivers/mmc/host/mmci.c6
-rw-r--r--drivers/mmc/host/pxamci.c12
-rw-r--r--drivers/mmc/host/sdhci.c2
-rw-r--r--drivers/mmc/host/wbsd.c2
9 files changed, 72 insertions, 36 deletions
diff --git a/drivers/mmc/core/mmc_ops.c b/drivers/mmc/core/mmc_ops.c
index bf4bc6a..7471d49 100644
--- a/drivers/mmc/core/mmc_ops.c
+++ b/drivers/mmc/core/mmc_ops.c
@@ -267,15 +267,26 @@ mmc_send_cxd_data(struct mmc_card *card, struct mmc_host *host,
int mmc_send_csd(struct mmc_card *card, u32 *csd)
{
+ int ret, i;
+
if (!mmc_host_is_spi(card->host))
return mmc_send_cxd_native(card->host, card->rca << 16,
csd, MMC_SEND_CSD);
- return mmc_send_cxd_data(card, card->host, MMC_SEND_CSD, csd, 16);
+ ret = mmc_send_cxd_data(card, card->host, MMC_SEND_CSD, csd, 16);
+ if (ret)
+ return ret;
+
+ for (i = 0;i < 4;i++)
+ csd[i] = be32_to_cpu(csd[i]);
+
+ return 0;
}
int mmc_send_cid(struct mmc_host *host, u32 *cid)
{
+ int ret, i;
+
if (!mmc_host_is_spi(host)) {
if (!host->card)
return -EINVAL;
@@ -283,7 +294,14 @@ int mmc_send_cid(struct mmc_host *host, u32 *cid)
cid, MMC_SEND_CID);
}
- return mmc_send_cxd_data(NULL, host, MMC_SEND_CID, cid, 16);
+ ret = mmc_send_cxd_data(NULL, host, MMC_SEND_CID, cid, 16);
+ if (ret)
+ return ret;
+
+ for (i = 0;i < 4;i++)
+ cid[i] = be32_to_cpu(cid[i]);
+
+ return 0;
}
int mmc_send_ext_csd(struct mmc_card *card, u8 *ext_csd)
diff --git a/drivers/mmc/core/sd_ops.c b/drivers/mmc/core/sd_ops.c
index ee4029a..a6dafe6 100644
--- a/drivers/mmc/core/sd_ops.c
+++ b/drivers/mmc/core/sd_ops.c
@@ -294,8 +294,8 @@ int mmc_app_send_scr(struct mmc_card *card, u32 *scr)
if (data.error)
return data.error;
- scr[0] = ntohl(scr[0]);
- scr[1] = ntohl(scr[1]);
+ scr[0] = be32_to_cpu(scr[0]);
+ scr[1] = be32_to_cpu(scr[1]);
return 0;
}
diff --git a/drivers/mmc/host/au1xmmc.c b/drivers/mmc/host/au1xmmc.c
index bcbb6d2..c3926eb 100644
--- a/drivers/mmc/host/au1xmmc.c
+++ b/drivers/mmc/host/au1xmmc.c
@@ -40,13 +40,13 @@
#include <linux/mm.h>
#include <linux/interrupt.h>
#include <linux/dma-mapping.h>
+#include <linux/scatterlist.h>
#include <linux/mmc/host.h>
#include <asm/io.h>
#include <asm/mach-au1x00/au1000.h>
#include <asm/mach-au1x00/au1xxx_dbdma.h>
#include <asm/mach-au1x00/au1100_mmc.h>
-#include <asm/scatterlist.h>
#include <au1xxx.h>
#include "au1xmmc.h"
@@ -212,12 +212,12 @@ static int au1xmmc_send_command(struct au1xmmc_host *host, int wait,
}
if (data) {
- if (flags & MMC_DATA_READ) {
+ if (data->flags & MMC_DATA_READ) {
if (data->blocks > 1)
mmccmd |= SD_CMD_CT_4;
else
mmccmd |= SD_CMD_CT_2;
- } else if (flags & MMC_DATA_WRITE) {
+ } else if (data->flags & MMC_DATA_WRITE) {
if (data->blocks > 1)
mmccmd |= SD_CMD_CT_3;
else
diff --git a/drivers/mmc/host/imxmmc.c b/drivers/mmc/host/imxmmc.c
index fc72e1f..f2070a1 100644
--- a/drivers/mmc/host/imxmmc.c
+++ b/drivers/mmc/host/imxmmc.c
@@ -262,7 +262,7 @@ static void imxmci_setup_data(struct imxmci_host *host, struct mmc_data *data)
}
/* Convert back to virtual address */
- host->data_ptr = (u16*)sg_virt(sg);
+ host->data_ptr = (u16*)sg_virt(data->sg);
host->data_cnt = 0;
clear_bit(IMXMCI_PEND_DMA_DATA_b, &host->pending_events);
diff --git a/drivers/mmc/host/mmc_spi.c b/drivers/mmc/host/mmc_spi.c
index 12c2d80..a646921 100644
--- a/drivers/mmc/host/mmc_spi.c
+++ b/drivers/mmc/host/mmc_spi.c
@@ -1165,6 +1165,23 @@ 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;
@@ -1188,33 +1205,30 @@ static int mmc_spi_probe(struct spi_device *spi)
return status;
}
- /* We can use the bus safely iff nobody else will interfere with
- * us. That is, either we have the experimental exclusive access
- * primitives ... or else there's nobody to share it with.
+ /* 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 device *parent = spi->dev.parent;
+ struct count_children cc;
- /* If there are multiple devices on this bus, we
- * can't proceed.
- */
- spin_lock(&parent->klist_children.k_lock);
- if (parent->klist_children.k_list.next
- != parent->klist_children.k_list.prev)
- status = -EMLINK;
- else
- status = 0;
- spin_unlock(&parent->klist_children.k_lock);
+ 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;
}
- /* REVISIT we can't guarantee another device won't
- * be added later. It's uncommon though ... for now,
- * work as if this is safe.
- */
- dev_warn(&spi->dev, "ASSUMING unshared SPI bus!\n");
+ dev_warn(&spi->dev, "ASSUMING SPI bus stays unshared!\n");
}
/* We need a supply of ones to transmit. This is the only time
diff --git a/drivers/mmc/host/mmci.c b/drivers/mmc/host/mmci.c
index d0eb0a2..95244a7 100644
--- a/drivers/mmc/host/mmci.c
+++ b/drivers/mmc/host/mmci.c
@@ -20,11 +20,11 @@
#include <linux/mmc/host.h>
#include <linux/amba/bus.h>
#include <linux/clk.h>
+#include <linux/scatterlist.h>
#include <asm/cacheflush.h>
#include <asm/div64.h>
#include <asm/io.h>
-#include <asm/scatterlist.h>
#include <asm/sizes.h>
#include <asm/mach/mmc.h>
@@ -167,7 +167,7 @@ mmci_data_irq(struct mmci_host *host, struct mmc_data *data,
* partially written to a page is properly coherent.
*/
if (host->sg_len && data->flags & MMC_DATA_READ)
- flush_dcache_page(host->sg_ptr->page);
+ flush_dcache_page(sg_page(host->sg_ptr));
}
if (status & MCI_DATAEND) {
mmci_stop_data(host);
@@ -319,7 +319,7 @@ static irqreturn_t mmci_pio_irq(int irq, void *dev_id)
* page, ensure that the data cache is coherent.
*/
if (status & MCI_RXACTIVE)
- flush_dcache_page(host->sg_ptr->page);
+ flush_dcache_page(sg_page(host->sg_ptr));
if (!mmci_next_sg(host))
break;
diff --git a/drivers/mmc/host/pxamci.c b/drivers/mmc/host/pxamci.c
index 0601e01..1654a33 100644
--- a/drivers/mmc/host/pxamci.c
+++ b/drivers/mmc/host/pxamci.c
@@ -29,7 +29,6 @@
#include <asm/dma.h>
#include <asm/io.h>
-#include <asm/scatterlist.h>
#include <asm/sizes.h>
#include <asm/arch/pxa-regs.h>
@@ -40,6 +39,7 @@
#define DRIVER_NAME "pxa2xx-mci"
#define NR_SG 1
+#define CLKRT_OFF (~0)
struct pxamci_host {
struct mmc_host *mmc;
@@ -372,6 +372,9 @@ static void pxamci_set_ios(struct mmc_host *mmc, struct mmc_ios *ios)
unsigned long rate = host->clkrate;
unsigned int clk = rate / ios->clock;
+ if (host->clkrt == CLKRT_OFF)
+ clk_enable(host->clk);
+
/*
* clk might result in a lower divisor than we
* desire. check for that condition and adjust
@@ -380,14 +383,16 @@ static void pxamci_set_ios(struct mmc_host *mmc, struct mmc_ios *ios)
if (rate / clk > ios->clock)
clk <<= 1;
host->clkrt = fls(clk) - 1;
- clk_enable(host->clk);
/*
* we write clkrt on the next command
*/
} else {
pxamci_stop_clock(host);
- clk_disable(host->clk);
+ if (host->clkrt != CLKRT_OFF) {
+ host->clkrt = CLKRT_OFF;
+ clk_disable(host->clk);
+ }
}
if (host->power_mode != ios->power_mode) {
@@ -499,6 +504,7 @@ static int pxamci_probe(struct platform_device *pdev)
host->mmc = mmc;
host->dma = -1;
host->pdata = pdev->dev.platform_data;
+ host->clkrt = CLKRT_OFF;
host->clk = clk_get(&pdev->dev, "MMCCLK");
if (IS_ERR(host->clk)) {
diff --git a/drivers/mmc/host/sdhci.c b/drivers/mmc/host/sdhci.c
index d7c5b94..6b80bf7 100644
--- a/drivers/mmc/host/sdhci.c
+++ b/drivers/mmc/host/sdhci.c
@@ -17,8 +17,6 @@
#include <linux/mmc/host.h>
-#include <asm/scatterlist.h>
-
#include "sdhci.h"
#define DRIVER_NAME "sdhci"
diff --git a/drivers/mmc/host/wbsd.c b/drivers/mmc/host/wbsd.c
index fa4c8c5..4d5f374 100644
--- a/drivers/mmc/host/wbsd.c
+++ b/drivers/mmc/host/wbsd.c
@@ -33,10 +33,10 @@
#include <linux/pnp.h>
#include <linux/highmem.h>
#include <linux/mmc/host.h>
+#include <linux/scatterlist.h>
#include <asm/io.h>
#include <asm/dma.h>
-#include <asm/scatterlist.h>
#include "wbsd.h"