aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/mmc/host/sdhci.c
diff options
context:
space:
mode:
authorPierre Ossman <drzeus@drzeus.cx>2007-09-04 01:59:18 -0400
committerPierre Ossman <drzeus@drzeus.cx>2007-09-23 15:25:52 -0400
commitf75979b77fb20b01522d8fab96dfc76cc9f42420 (patch)
treee5c4c4fdf04b2fbf079c0be25edfc416279b072e /drivers/mmc/host/sdhci.c
parent15b82b46de358a574c2a6a6dea4c8076bef7ac43 (diff)
sdhci: sdio interrupt support
Add support for relaying the sdio interrupt signal from the card. Signed-off-by: Pierre Ossman <drzeus@drzeus.cx>
Diffstat (limited to 'drivers/mmc/host/sdhci.c')
-rw-r--r--drivers/mmc/host/sdhci.c39
1 files changed, 38 insertions, 1 deletions
diff --git a/drivers/mmc/host/sdhci.c b/drivers/mmc/host/sdhci.c
index c63edc5c17e4..228ce42371dc 100644
--- a/drivers/mmc/host/sdhci.c
+++ b/drivers/mmc/host/sdhci.c
@@ -800,10 +800,35 @@ static int sdhci_get_ro(struct mmc_host *mmc)
800 return !(present & SDHCI_WRITE_PROTECT); 800 return !(present & SDHCI_WRITE_PROTECT);
801} 801}
802 802
803static void sdhci_enable_sdio_irq(struct mmc_host *mmc, int enable)
804{
805 struct sdhci_host *host;
806 unsigned long flags;
807 u32 ier;
808
809 host = mmc_priv(mmc);
810
811 spin_lock_irqsave(&host->lock, flags);
812
813 ier = readl(host->ioaddr + SDHCI_INT_ENABLE);
814
815 ier &= ~SDHCI_INT_CARD_INT;
816 if (enable)
817 ier |= SDHCI_INT_CARD_INT;
818
819 writel(ier, host->ioaddr + SDHCI_INT_ENABLE);
820 writel(ier, host->ioaddr + SDHCI_SIGNAL_ENABLE);
821
822 mmiowb();
823
824 spin_unlock_irqrestore(&host->lock, flags);
825}
826
803static const struct mmc_host_ops sdhci_ops = { 827static const struct mmc_host_ops sdhci_ops = {
804 .request = sdhci_request, 828 .request = sdhci_request,
805 .set_ios = sdhci_set_ios, 829 .set_ios = sdhci_set_ios,
806 .get_ro = sdhci_get_ro, 830 .get_ro = sdhci_get_ro,
831 .enable_sdio_irq = sdhci_enable_sdio_irq,
807}; 832};
808 833
809/*****************************************************************************\ 834/*****************************************************************************\
@@ -1012,6 +1037,7 @@ static irqreturn_t sdhci_irq(int irq, void *dev_id)
1012 irqreturn_t result; 1037 irqreturn_t result;
1013 struct sdhci_host* host = dev_id; 1038 struct sdhci_host* host = dev_id;
1014 u32 intmask; 1039 u32 intmask;
1040 int cardint = 0;
1015 1041
1016 spin_lock(&host->lock); 1042 spin_lock(&host->lock);
1017 1043
@@ -1056,6 +1082,11 @@ static irqreturn_t sdhci_irq(int irq, void *dev_id)
1056 1082
1057 intmask &= ~SDHCI_INT_BUS_POWER; 1083 intmask &= ~SDHCI_INT_BUS_POWER;
1058 1084
1085 if (intmask & SDHCI_INT_CARD_INT)
1086 cardint = 1;
1087
1088 intmask &= ~SDHCI_INT_CARD_INT;
1089
1059 if (intmask) { 1090 if (intmask) {
1060 printk(KERN_ERR "%s: Unexpected interrupt 0x%08x.\n", 1091 printk(KERN_ERR "%s: Unexpected interrupt 0x%08x.\n",
1061 mmc_hostname(host->mmc), intmask); 1092 mmc_hostname(host->mmc), intmask);
@@ -1070,6 +1101,12 @@ static irqreturn_t sdhci_irq(int irq, void *dev_id)
1070out: 1101out:
1071 spin_unlock(&host->lock); 1102 spin_unlock(&host->lock);
1072 1103
1104 /*
1105 * We have to delay this as it calls back into the driver.
1106 */
1107 if (cardint)
1108 mmc_signal_sdio_irq(host->mmc);
1109
1073 return result; 1110 return result;
1074} 1111}
1075 1112
@@ -1309,7 +1346,7 @@ static int __devinit sdhci_probe_slot(struct pci_dev *pdev, int slot)
1309 mmc->ops = &sdhci_ops; 1346 mmc->ops = &sdhci_ops;
1310 mmc->f_min = host->max_clk / 256; 1347 mmc->f_min = host->max_clk / 256;
1311 mmc->f_max = host->max_clk; 1348 mmc->f_max = host->max_clk;
1312 mmc->caps = MMC_CAP_4_BIT_DATA | MMC_CAP_MULTIWRITE; 1349 mmc->caps = MMC_CAP_4_BIT_DATA | MMC_CAP_MULTIWRITE | MMC_CAP_SDIO_IRQ;
1313 1350
1314 if (caps & SDHCI_CAN_DO_HISPD) 1351 if (caps & SDHCI_CAN_DO_HISPD)
1315 mmc->caps |= MMC_CAP_SD_HIGHSPEED; 1352 mmc->caps |= MMC_CAP_SD_HIGHSPEED;