summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorJustin Waters <justin.waters@timesys.com>2010-05-18 10:10:26 -0400
committerJustin Waters <justin.waters@timesys.com>2010-05-18 10:10:26 -0400
commit2e70c9f0621b65a563ba6961310ad7de9c6b4052 (patch)
tree63d99c5c390cecaa252eac3ee0b746cebbe2c1ce
parent63144b093aae08e3f573545326586b07f0d1cf95 (diff)
Add support for SDIO Wireless chip on the CCWMX51JS2.6.31-ccwmx51js-201005181410
-rw-r--r--arch/arm/mach-mx51/mx51_ccwmx51js_gpio.c37
-rw-r--r--arch/arm/plat-mxc/include/mach/mmc.h1
-rw-r--r--drivers/mmc/core/core.c2
-rw-r--r--drivers/mmc/core/sdio_ops.c119
-rw-r--r--drivers/mmc/core/sdio_ops.h1
-rw-r--r--drivers/mmc/host/mx_sdhci.c23
6 files changed, 133 insertions, 50 deletions
diff --git a/arch/arm/mach-mx51/mx51_ccwmx51js_gpio.c b/arch/arm/mach-mx51/mx51_ccwmx51js_gpio.c
index 293c9aa9545f..5d6d5def4566 100644
--- a/arch/arm/mach-mx51/mx51_ccwmx51js_gpio.c
+++ b/arch/arm/mach-mx51/mx51_ccwmx51js_gpio.c
@@ -332,6 +332,43 @@ static struct mxc_iomux_pin_cfg __initdata mxc_iomux_pins[] = {
MX51_PIN_GPIO1_0, IOMUX_CONFIG_GPIO | IOMUX_CONFIG_SION,
(PAD_CTL_HYS_ENABLE | PAD_CTL_100K_PU),
},
+ /* SDHC2*/
+#if defined(CONFIG_MMC_IMX_ESDHCI) || defined(CONFIG_MMC_IMX_ESDHCI_MODULE)
+ {
+ MX51_PIN_SD2_CMD, IOMUX_CONFIG_ALT0 | IOMUX_CONFIG_SION,
+ (PAD_CTL_PUE_KEEPER | PAD_CTL_PKE_ENABLE | PAD_CTL_DRV_HIGH |
+ PAD_CTL_47K_PU | PAD_CTL_SRE_FAST),
+ },
+ {
+ MX51_PIN_SD2_CLK, IOMUX_CONFIG_ALT0,
+ (PAD_CTL_PUE_KEEPER | PAD_CTL_PKE_ENABLE | PAD_CTL_DRV_HIGH |
+ PAD_CTL_47K_PU | PAD_CTL_SRE_FAST),
+ },
+ {
+ MX51_PIN_SD2_DATA0, IOMUX_CONFIG_ALT0,
+ (PAD_CTL_PUE_KEEPER | PAD_CTL_PKE_ENABLE | PAD_CTL_DRV_HIGH |
+ PAD_CTL_47K_PU | PAD_CTL_SRE_FAST),
+ },
+ {
+ MX51_PIN_SD2_DATA1, IOMUX_CONFIG_ALT0,
+ (PAD_CTL_PUE_KEEPER | PAD_CTL_PKE_ENABLE | PAD_CTL_DRV_HIGH |
+ PAD_CTL_47K_PU | PAD_CTL_SRE_FAST),
+ },
+ {
+ MX51_PIN_SD2_DATA2, IOMUX_CONFIG_ALT0,
+ (PAD_CTL_PUE_KEEPER | PAD_CTL_PKE_ENABLE | PAD_CTL_DRV_HIGH |
+ PAD_CTL_47K_PU | PAD_CTL_SRE_FAST),
+ },
+ {
+ MX51_PIN_SD2_DATA3, IOMUX_CONFIG_ALT0,
+ (PAD_CTL_PUE_KEEPER | PAD_CTL_PKE_ENABLE | PAD_CTL_DRV_HIGH |
+ PAD_CTL_47K_PU | PAD_CTL_SRE_FAST),
+ },
+ {
+ MX51_PIN_GPIO1_1, IOMUX_CONFIG_GPIO,
+ (PAD_CTL_HYS_ENABLE | PAD_CTL_100K_PU),
+ },
+#endif
/* SDHC3 */
{
MX51_PIN_NANDF_RDY_INT, IOMUX_CONFIG_ALT5 | IOMUX_CONFIG_SION,
diff --git a/arch/arm/plat-mxc/include/mach/mmc.h b/arch/arm/plat-mxc/include/mach/mmc.h
index 80cc61c175ea..d563c157bad7 100644
--- a/arch/arm/plat-mxc/include/mach/mmc.h
+++ b/arch/arm/plat-mxc/include/mach/mmc.h
@@ -43,6 +43,7 @@ struct mxc_mmc_platform_data {
unsigned int reserved:16;
unsigned int card_fixed:1;
unsigned int card_inserted_state:1;
+ unsigned int quirks; /* Device quirks */
// u32 (*translate_vdd)(struct device *, unsigned int);
unsigned int (*status) (struct device *);
int (*wp_status) (struct device *);
diff --git a/drivers/mmc/core/core.c b/drivers/mmc/core/core.c
index d84c880fac84..50b208253440 100644
--- a/drivers/mmc/core/core.c
+++ b/drivers/mmc/core/core.c
@@ -890,6 +890,8 @@ void mmc_rescan(struct work_struct *work)
mmc_claim_host(host);
mmc_power_up(host);
+ sdio_go_idle(host);
+
mmc_go_idle(host);
mmc_send_if_cond(host, host->ocr_avail);
diff --git a/drivers/mmc/core/sdio_ops.c b/drivers/mmc/core/sdio_ops.c
index 4eb7825fd1a7..208beeb23ed6 100644
--- a/drivers/mmc/core/sdio_ops.c
+++ b/drivers/mmc/core/sdio_ops.c
@@ -67,54 +67,6 @@ int mmc_send_io_op_cond(struct mmc_host *host, u32 ocr, u32 *rocr)
return err;
}
-int mmc_io_rw_direct(struct mmc_card *card, int write, unsigned fn,
- unsigned addr, u8 in, u8* out)
-{
- struct mmc_command cmd;
- int err;
-
- BUG_ON(!card);
- BUG_ON(fn > 7);
-
- /* sanity check */
- if (addr & ~0x1FFFF)
- return -EINVAL;
-
- memset(&cmd, 0, sizeof(struct mmc_command));
-
- cmd.opcode = SD_IO_RW_DIRECT;
- cmd.arg = write ? 0x80000000 : 0x00000000;
- cmd.arg |= fn << 28;
- cmd.arg |= (write && out) ? 0x08000000 : 0x00000000;
- cmd.arg |= addr << 9;
- cmd.arg |= in;
- cmd.flags = MMC_RSP_SPI_R5 | MMC_RSP_R5 | MMC_CMD_AC;
-
- err = mmc_wait_for_cmd(card->host, &cmd, 0);
- if (err)
- return err;
-
- if (mmc_host_is_spi(card->host)) {
- /* host driver already reported errors */
- } else {
- if (cmd.resp[0] & R5_ERROR)
- return -EIO;
- if (cmd.resp[0] & R5_FUNCTION_NUMBER)
- return -EINVAL;
- if (cmd.resp[0] & R5_OUT_OF_RANGE)
- return -ERANGE;
- }
-
- if (out) {
- if (mmc_host_is_spi(card->host))
- *out = (cmd.resp[0] >> 8) & 0xFF;
- else
- *out = cmd.resp[0] & 0xFF;
- }
-
- return 0;
-}
-
int mmc_io_rw_extended(struct mmc_card *card, int write, unsigned fn,
unsigned addr, int incr_addr, u8 *buf, unsigned blocks, unsigned blksz)
{
@@ -182,3 +134,74 @@ int mmc_io_rw_extended(struct mmc_card *card, int write, unsigned fn,
return 0;
}
+static int mmc_io_rw_direct_host(struct mmc_host *host, int write, unsigned fn,
+ unsigned addr, u8 in, u8 *out)
+{
+ struct mmc_command cmd;
+ int err;
+
+ BUG_ON(!host);
+ BUG_ON(fn > 7);
+
+ /* sanity check */
+ if (addr & ~0x1FFFF)
+ return -EINVAL;
+
+ memset(&cmd, 0, sizeof(struct mmc_command));
+
+ cmd.opcode = SD_IO_RW_DIRECT;
+ cmd.arg = write ? 0x80000000 : 0x00000000;
+ cmd.arg |= fn << 28;
+ cmd.arg |= (write && out) ? 0x08000000 : 0x00000000;
+ cmd.arg |= addr << 9;
+ cmd.arg |= in;
+ cmd.flags = MMC_RSP_SPI_R5 | MMC_RSP_R5 | MMC_CMD_AC;
+
+ err = mmc_wait_for_cmd(host, &cmd, 0);
+ if (err)
+ return err;
+
+ if (mmc_host_is_spi(host)) {
+ /* host driver already reported errors */
+ } else {
+ if (cmd.resp[0] & R5_ERROR)
+ return -EIO;
+ if (cmd.resp[0] & R5_FUNCTION_NUMBER)
+ return -EINVAL;
+ if (cmd.resp[0] & R5_OUT_OF_RANGE)
+ return -ERANGE;
+ }
+
+ if (out) {
+ if (mmc_host_is_spi(host))
+ *out = (cmd.resp[0] >> 8) & 0xFF;
+ else
+ *out = cmd.resp[0] & 0xFF;
+ }
+
+ return 0;
+}
+
+int mmc_io_rw_direct(struct mmc_card *card, int write, unsigned fn,
+ unsigned addr, u8 in, u8 *out)
+{
+ BUG_ON(!card);
+ return mmc_io_rw_direct_host(card->host, write, fn, addr, in, out);
+}
+
+int sdio_go_idle(struct mmc_host *host)
+{
+ int ret;
+ u8 abort;
+
+ /* SDIO Simplified Specification V2.0, 4.4 Reset for SDIO */
+
+ ret = mmc_io_rw_direct_host(host, 0, 0, SDIO_CCCR_ABORT, 0, &abort);
+ if (ret)
+ abort = 0x08;
+ else
+ abort |= 0x08;
+
+ ret = mmc_io_rw_direct_host(host, 1, 0, SDIO_CCCR_ABORT, abort, NULL);
+ return ret;
+}
diff --git a/drivers/mmc/core/sdio_ops.h b/drivers/mmc/core/sdio_ops.h
index e2e74b0d17d8..9b546c71eb5e 100644
--- a/drivers/mmc/core/sdio_ops.h
+++ b/drivers/mmc/core/sdio_ops.h
@@ -17,6 +17,7 @@ int mmc_io_rw_direct(struct mmc_card *card, int write, unsigned fn,
unsigned addr, u8 in, u8* out);
int mmc_io_rw_extended(struct mmc_card *card, int write, unsigned fn,
unsigned addr, int incr_addr, u8 *buf, unsigned blocks, unsigned blksz);
+int sdio_go_idle(struct mmc_host *host);
#endif
diff --git a/drivers/mmc/host/mx_sdhci.c b/drivers/mmc/host/mx_sdhci.c
index 4e686d80d071..682a6771169c 100644
--- a/drivers/mmc/host/mx_sdhci.c
+++ b/drivers/mmc/host/mx_sdhci.c
@@ -1184,6 +1184,16 @@ static void sdhci_tasklet_finish(unsigned long param)
spin_unlock_irqrestore(&host->lock, flags);
/* Stop the clock when the req is done */
+ if (machine_is_mx51_ccwmx51js()) {
+ /**
+ * On the ConnectCore Wi-i.MX51 this, disabling there clock
+ * causes that we lose interrupts on the wireless SDIO cards
+ * For that reason, we dont disable the clock on this platform
+ */
+ mmc_request_done(host->mmc, mrq);
+ return;
+ }
+
flags = SDHCI_DATA_ACTIVE | SDHCI_DOING_WRITE | SDHCI_DOING_READ;
if (machine_is_mx35_3ds()) {
/* Do not disable the eSDHC clk on MX35 3DS board,
@@ -1203,7 +1213,6 @@ static void sdhci_tasklet_finish(unsigned long param)
mmc_request_done(host->mmc, mrq);
}
-
}
static void sdhci_timeout_timer(unsigned long data)
@@ -1784,13 +1793,13 @@ static int __devinit sdhci_probe_slot(struct platform_device
set_irq_type(host->detect_irq, IRQF_TRIGGER_RISING);
} while (ret != host->plat_data->status(host->mmc->parent));
+ no_detect_irq:
ret = host->plat_data->status(host->mmc->parent);
if (ret)
host->flags &= ~SDHCI_CD_PRESENT;
else
host->flags |= SDHCI_CD_PRESENT;
- no_detect_irq:
DBG("slot %d at 0x%x, irq %d \n", slot, host->res->start, host->irq);
if (!request_mem_region(host->res->start,
host->res->end -
@@ -2064,6 +2073,7 @@ static int sdhci_probe(struct platform_device *pdev)
int ret = 0, i;
u8 slots = 1;
struct sdhci_chip *chip;
+ struct mxc_mmc_platform_data *mmc_plat = pdev->dev.platform_data;
printk(KERN_INFO DRIVER_NAME ": MXC SDHCI Controller Driver. \n");
BUG_ON(pdev == NULL);
@@ -2085,6 +2095,15 @@ static int sdhci_probe(struct platform_device *pdev)
chip->pdev = pdev;
chip->quirks = mxc_quirks;
+ /**
+ * FIXME
+ * PPH This should be revisited and implemented a bit different.
+ * We pass quirks per device through the platform_data variable to allow
+ * different settings on each interface (DMA vs PIO, etc.
+ */
+ if (mmc_plat->quirks != 0)
+ chip->quirks = mmc_plat->quirks;
+
if (debug_quirks)
chip->quirks = debug_quirks;