diff options
author | Philippe Langlais <philippe.langlais@linaro.org> | 2011-03-22 10:43:59 +0100 |
---|---|---|
committer | Robert Marklund <robert.marklund@stericsson.com> | 2011-05-04 18:04:53 +0200 |
commit | 0f45b9150c6373652bf968229e547547e343f689 (patch) | |
tree | 5ab2104d72aad7e9f6daf319c083ef4c6c8bd68e /drivers/mmc | |
parent | 437855158c2727065affa065093c6f187ac44903 (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.c | 47 |
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, |