diff options
Diffstat (limited to 'drivers/mmc/host/sdhci.c')
-rw-r--r-- | drivers/mmc/host/sdhci.c | 39 |
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 | ||
803 | static 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 | |||
803 | static const struct mmc_host_ops sdhci_ops = { | 827 | static 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) | |||
1070 | out: | 1101 | out: |
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; |