aboutsummaryrefslogtreecommitdiff
path: root/drivers/mmc
diff options
context:
space:
mode:
authorPhilippe Langlais <philippe.langlais@linaro.org>2011-03-22 10:43:59 +0100
committerRobert Marklund <robert.marklund@stericsson.com>2011-05-04 18:04:53 +0200
commit0f45b9150c6373652bf968229e547547e343f689 (patch)
tree5ab2104d72aad7e9f6daf319c083ef4c6c8bd68e /drivers/mmc
parent437855158c2727065affa065093c6f187ac44903 (diff)
MMCI: Add SDIO irq support (FIXME partial merge, TODO dynamic clocking managment)
SDIO irq support. The SDIO mode enable bit in the DATACTRL register together with SDIO interrupt mask are set to be able to generate SDIO interrupts from the DAT1 line. In sleep mode, SDIO interrupts are not handled and thus not being generated. Returning from sleep mode turns on SDIO interrupt handling again. ST-Ericsson ID: 319566 Change-Id: Ib919ad7b38dc999f5fa613f2c679ba9a9970c715 Signed-off-by: Stefan Nilsson XK <stefan.xk.nilsson@stericsson.com> Signed-off-by: Ulf Hansson <ulf.hansson@stericsson.com> Reviewed-on: http://gerrit.lud.stericsson.com/gerrit/12912 Conflicts: drivers/mmc/host/mmci.c
Diffstat (limited to 'drivers/mmc')
-rw-r--r--drivers/mmc/host/mmci.c47
1 files changed, 45 insertions, 2 deletions
diff --git a/drivers/mmc/host/mmci.c b/drivers/mmc/host/mmci.c
index 4f37c5d57df..c8b4bd71fad 100644
--- a/drivers/mmc/host/mmci.c
+++ b/drivers/mmc/host/mmci.c
@@ -179,8 +179,20 @@ static void mmci_set_mask1(struct mmci_host *host, unsigned int mask)
static void mmci_stop_data(struct mmci_host *host)
{
u32 clk;
+ unsigned int datactrl = 0;
- writel(0, host->base + MMCIDATACTRL);
+ /*
+ * The ST Micro variants has a special bit
+ * to enable SDIO mode. This bit must remain set even when not
+ * doing data transfers, otherwise no SDIO interrupts can be
+ * received.
+ */
+ if (host->variant->sdio &&
+ host->mmc->card &&
+ mmc_card_sdio(host->mmc->card))
+ datactrl |= MCI_ST_DPSM_SDIOEN;
+
+ writel(datactrl, host->base + MMCIDATACTRL);
mmci_set_mask1(host, 0);
/* Needed for DDR */
@@ -528,7 +540,11 @@ static void mmci_start_data(struct mmci_host *host, struct mmc_data *data)
if (mmc_card_sdio(host->mmc->card)) {
/*
* The ST Micro variants has a special bit
- * to enable SDIO.
+ * to enable SDIO mode. This bit is set the first time
+ * a SDIO data transfer is done and must remain set
+ * after the data transfer is completed. The reason is
+ * because of otherwise no SDIO interrupts can be
+ * received.
*/
datactrl |= MCI_ST_DPSM_SDIOEN;
@@ -845,6 +861,9 @@ static irqreturn_t mmci_irq(int irq, void *dev_id)
dev_dbg(mmc_dev(host->mmc), "irq0 (data+cmd) %08x\n", status);
+ if (status & MCI_ST_SDIOIT)
+ mmc_signal_sdio_irq(host->mmc);
+
data = host->data;
if (status & (MCI_DATACRCFAIL|MCI_DATATIMEOUT|MCI_TXUNDERRUN|
MCI_RXOVERRUN|MCI_DATAEND|MCI_DATABLOCKEND) && data)
@@ -998,11 +1017,35 @@ static irqreturn_t mmci_cd_irq(int irq, void *dev_id)
return IRQ_HANDLED;
}
+static void mmci_enable_sdio_irq(struct mmc_host *mmc, int enable)
+{
+ unsigned long flags;
+ struct mmci_host *host = mmc_priv(mmc);
+
+ if (enable) {
+ /*
+ * Since the host is not claimed when doing enable
+ * we must handle it here.
+ */
+ spin_lock_irqsave(&host->lock, flags);
+
+ writel((readl(host->base + MMCIMASK0) | MCI_ST_SDIOIT),
+ (host->base + MMCIMASK0));
+
+ spin_unlock_irqrestore(&host->lock, flags);
+ } else {
+ /* We assumes the host is claimed when doing disable. */
+ writel((readl(host->base + MMCIMASK0) & ~MCI_ST_SDIOIT),
+ (host->base + MMCIMASK0));
+ }
+}
+
static const struct mmc_host_ops mmci_ops = {
.request = mmci_request,
.set_ios = mmci_set_ios,
.get_ro = mmci_get_ro,
.get_cd = mmci_get_cd,
+ .enable_sdio_irq = mmci_enable_sdio_irq,
};
static int __devinit mmci_probe(struct amba_device *dev,