/*
- * linux/drivers/mmc/sdhci.c - Secure Digital Host Controller Interface driver
+ * linux/drivers/mmc/host/sdhci.c - Secure Digital Host Controller Interface driver
*
* Copyright (C) 2005-2007 Pierre Ossman, All Rights Reserved.
*
/* Controller doesn't like some resets when there is no card inserted. */
#define SDHCI_QUIRK_NO_CARD_NO_RESET (1<<2)
#define SDHCI_QUIRK_SINGLE_POWER_WRITE (1<<3)
+#define SDHCI_QUIRK_RESET_CMD_DATA_ON_IOS (1<<4)
static const struct pci_device_id pci_ids[] __devinitdata = {
{
.driver_data = SDHCI_QUIRK_SINGLE_POWER_WRITE,
},
+ {
+ .vendor = PCI_VENDOR_ID_ENE,
+ .device = PCI_DEVICE_ID_ENE_CB714_SD,
+ .subvendor = PCI_ANY_ID,
+ .subdevice = PCI_ANY_ID,
+ .driver_data = SDHCI_QUIRK_SINGLE_POWER_WRITE |
+ SDHCI_QUIRK_RESET_CMD_DATA_ON_IOS,
+ },
+
+ {
+ .vendor = PCI_VENDOR_ID_ENE,
+ .device = PCI_DEVICE_ID_ENE_CB714_SD_2,
+ .subvendor = PCI_ANY_ID,
+ .subdevice = PCI_ANY_ID,
+ .driver_data = SDHCI_QUIRK_SINGLE_POWER_WRITE |
+ SDHCI_QUIRK_RESET_CMD_DATA_ON_IOS,
+ },
+
{ /* Generic SD host controller */
PCI_DEVICE_CLASS((PCI_CLASS_SYSTEM_SDHCI << 8), 0xFFFF00)
},
if (data == NULL)
return;
- DBG("blksz %04x blks %04x flags %08x\n",
- data->blksz, data->blocks, data->flags);
- DBG("tsac %d ms nsac %d clk\n",
- data->timeout_ns / 1000000, data->timeout_clks);
-
/* Sanity checks */
BUG_ON(data->blksz * data->blocks > 524288);
BUG_ON(data->blksz > host->mmc->max_blk_size);
BUG_ON(data->blocks > 65535);
+ host->data = data;
+ host->data_early = 0;
+
/* timeout in us */
target_timeout = data->timeout_ns / 1000 +
data->timeout_clks / host->clock;
{
u16 mode;
- WARN_ON(host->data);
-
if (data == NULL)
return;
+ WARN_ON(!host->data);
+
mode = SDHCI_TRNS_BLK_CNT_EN;
if (data->blocks > 1)
mode |= SDHCI_TRNS_MULTI;
/*
* Controller doesn't count down when in single block mode.
*/
- if ((data->blocks == 1) && (data->error == MMC_ERR_NONE))
- blocks = 0;
+ if (data->blocks == 1)
+ blocks = (data->error == MMC_ERR_NONE) ? 0 : 1;
else
blocks = readw(host->ioaddr + SDHCI_BLOCK_COUNT);
data->bytes_xfered = data->blksz * (data->blocks - blocks);
data->error = MMC_ERR_FAILED;
}
- DBG("Ending data transfer (%d bytes)\n", data->bytes_xfered);
-
if (data->stop) {
/*
* The controller needs a reset of internal state machines
WARN_ON(host->cmd);
- DBG("Sending cmd (%x)\n", cmd->opcode);
-
/* Wait max 10 ms */
timeout = 10;
host->cmd->error = MMC_ERR_NONE;
- DBG("Ending cmd (%x)\n", host->cmd->opcode);
+ if (host->data && host->data_early)
+ sdhci_finish_data(host);
- if (host->cmd->data)
- host->data = host->cmd->data;
- else
+ if (!host->cmd->data)
tasklet_schedule(&host->finish_tasklet);
host->cmd = NULL;
writeb(ctrl, host->ioaddr + SDHCI_HOST_CONTROL);
+ /*
+ * Some (ENE) controllers go apeshit on some ios operation,
+ * signalling timeout and CRC errors even on CMD0. Resetting
+ * it on each ios seems to solve the problem.
+ */
+ if(host->chip->quirks & SDHCI_QUIRK_RESET_CMD_DATA_ON_IOS)
+ sdhci_reset(host, SDHCI_RESET_CMD | SDHCI_RESET_DATA);
+
mmiowb();
spin_unlock_irqrestore(&host->lock, flags);
}
mrq = host->mrq;
- DBG("Ending request, cmd (%x)\n", mrq->cmd->opcode);
-
/*
* The controller needs a reset of internal state machines
* upon error conditions.
BUG_ON(intmask == 0);
if (!host->cmd) {
- printk(KERN_ERR "%s: Got command interrupt even though no "
- "command operation was in progress.\n",
- mmc_hostname(host->mmc));
+ printk(KERN_ERR "%s: Got command interrupt 0x%08x even "
+ "though no command operation was in progress.\n",
+ mmc_hostname(host->mmc), (unsigned)intmask);
sdhci_dumpregs(host);
return;
}
- if (intmask & SDHCI_INT_RESPONSE)
- sdhci_finish_command(host);
- else {
- if (intmask & SDHCI_INT_TIMEOUT)
- host->cmd->error = MMC_ERR_TIMEOUT;
- else if (intmask & SDHCI_INT_CRC)
- host->cmd->error = MMC_ERR_BADCRC;
- else if (intmask & (SDHCI_INT_END_BIT | SDHCI_INT_INDEX))
- host->cmd->error = MMC_ERR_FAILED;
- else
- host->cmd->error = MMC_ERR_INVALID;
+ if (intmask & SDHCI_INT_TIMEOUT)
+ host->cmd->error = MMC_ERR_TIMEOUT;
+ else if (intmask & SDHCI_INT_CRC)
+ host->cmd->error = MMC_ERR_BADCRC;
+ else if (intmask & (SDHCI_INT_END_BIT | SDHCI_INT_INDEX))
+ host->cmd->error = MMC_ERR_FAILED;
+ if (host->cmd->error != MMC_ERR_NONE)
tasklet_schedule(&host->finish_tasklet);
- }
+ else if (intmask & SDHCI_INT_RESPONSE)
+ sdhci_finish_command(host);
}
static void sdhci_data_irq(struct sdhci_host *host, u32 intmask)
if (intmask & SDHCI_INT_DATA_END)
return;
- printk(KERN_ERR "%s: Got data interrupt even though no "
- "data operation was in progress.\n",
- mmc_hostname(host->mmc));
+ printk(KERN_ERR "%s: Got data interrupt 0x%08x even "
+ "though no data operation was in progress.\n",
+ mmc_hostname(host->mmc), (unsigned)intmask);
sdhci_dumpregs(host);
return;
writel(readl(host->ioaddr + SDHCI_DMA_ADDRESS),
host->ioaddr + SDHCI_DMA_ADDRESS);
- if (intmask & SDHCI_INT_DATA_END)
- sdhci_finish_data(host);
+ if (intmask & SDHCI_INT_DATA_END) {
+ if (host->cmd) {
+ /*
+ * Data managed to finish before the
+ * command completed. Make sure we do
+ * things in the proper order.
+ */
+ host->data_early = 1;
+ } else {
+ sdhci_finish_data(host);
+ }
+ }
}
}
*/
mmc->max_blk_size = (caps & SDHCI_MAX_BLOCK_MASK) >> SDHCI_MAX_BLOCK_SHIFT;
if (mmc->max_blk_size >= 3) {
- printk(KERN_ERR "%s: Invalid maximum block size.\n",
+ printk(KERN_WARNING "%s: Invalid maximum block size, assuming 512\n",
host->slot_descr);
- ret = -ENODEV;
- goto unmap;
- }
- mmc->max_blk_size = 512 << mmc->max_blk_size;
+ mmc->max_blk_size = 512;
+ } else
+ mmc->max_blk_size = 512 << mmc->max_blk_size;
/*
* Maximum block count.