diff options
| -rw-r--r-- | drivers/mmc/host/davinci_mmc.c | 78 |
1 files changed, 73 insertions, 5 deletions
diff --git a/drivers/mmc/host/davinci_mmc.c b/drivers/mmc/host/davinci_mmc.c index b643ddef4f70..0076c7448fe6 100644 --- a/drivers/mmc/host/davinci_mmc.c +++ b/drivers/mmc/host/davinci_mmc.c | |||
| @@ -66,8 +66,8 @@ | |||
| 66 | #define DAVINCI_MMCBLNC 0x60 | 66 | #define DAVINCI_MMCBLNC 0x60 |
| 67 | #define DAVINCI_SDIOCTL 0x64 | 67 | #define DAVINCI_SDIOCTL 0x64 |
| 68 | #define DAVINCI_SDIOST0 0x68 | 68 | #define DAVINCI_SDIOST0 0x68 |
| 69 | #define DAVINCI_SDIOEN 0x6C | 69 | #define DAVINCI_SDIOIEN 0x6C |
| 70 | #define DAVINCI_SDIOST 0x70 | 70 | #define DAVINCI_SDIOIST 0x70 |
| 71 | #define DAVINCI_MMCFIFOCTL 0x74 /* FIFO Control Register */ | 71 | #define DAVINCI_MMCFIFOCTL 0x74 /* FIFO Control Register */ |
| 72 | 72 | ||
| 73 | /* DAVINCI_MMCCTL definitions */ | 73 | /* DAVINCI_MMCCTL definitions */ |
| @@ -131,6 +131,14 @@ | |||
| 131 | #define MMCFIFOCTL_ACCWD_2 (2 << 3) /* access width of 2 bytes */ | 131 | #define MMCFIFOCTL_ACCWD_2 (2 << 3) /* access width of 2 bytes */ |
| 132 | #define MMCFIFOCTL_ACCWD_1 (3 << 3) /* access width of 1 byte */ | 132 | #define MMCFIFOCTL_ACCWD_1 (3 << 3) /* access width of 1 byte */ |
| 133 | 133 | ||
| 134 | /* DAVINCI_SDIOST0 definitions */ | ||
| 135 | #define SDIOST0_DAT1_HI BIT(0) | ||
| 136 | |||
| 137 | /* DAVINCI_SDIOIEN definitions */ | ||
| 138 | #define SDIOIEN_IOINTEN BIT(0) | ||
| 139 | |||
| 140 | /* DAVINCI_SDIOIST definitions */ | ||
| 141 | #define SDIOIST_IOINT BIT(0) | ||
| 134 | 142 | ||
| 135 | /* MMCSD Init clock in Hz in opendrain mode */ | 143 | /* MMCSD Init clock in Hz in opendrain mode */ |
| 136 | #define MMCSD_INIT_CLOCK 200000 | 144 | #define MMCSD_INIT_CLOCK 200000 |
| @@ -164,7 +172,7 @@ struct mmc_davinci_host { | |||
| 164 | unsigned int mmc_input_clk; | 172 | unsigned int mmc_input_clk; |
| 165 | void __iomem *base; | 173 | void __iomem *base; |
| 166 | struct resource *mem_res; | 174 | struct resource *mem_res; |
| 167 | int irq; | 175 | int mmc_irq, sdio_irq; |
| 168 | unsigned char bus_mode; | 176 | unsigned char bus_mode; |
| 169 | 177 | ||
| 170 | #define DAVINCI_MMC_DATADIR_NONE 0 | 178 | #define DAVINCI_MMC_DATADIR_NONE 0 |
| @@ -184,6 +192,7 @@ struct mmc_davinci_host { | |||
| 184 | u32 rxdma, txdma; | 192 | u32 rxdma, txdma; |
| 185 | bool use_dma; | 193 | bool use_dma; |
| 186 | bool do_dma; | 194 | bool do_dma; |
| 195 | bool sdio_int; | ||
| 187 | 196 | ||
| 188 | /* Scatterlist DMA uses one or more parameter RAM entries: | 197 | /* Scatterlist DMA uses one or more parameter RAM entries: |
| 189 | * the main one (associated with rxdma or txdma) plus zero or | 198 | * the main one (associated with rxdma or txdma) plus zero or |
| @@ -866,6 +875,19 @@ mmc_davinci_xfer_done(struct mmc_davinci_host *host, struct mmc_data *data) | |||
| 866 | { | 875 | { |
| 867 | host->data = NULL; | 876 | host->data = NULL; |
| 868 | 877 | ||
| 878 | if (host->mmc->caps & MMC_CAP_SDIO_IRQ) { | ||
| 879 | /* | ||
| 880 | * SDIO Interrupt Detection work-around as suggested by | ||
| 881 | * Davinci Errata (TMS320DM355 Silicon Revision 1.1 Errata | ||
| 882 | * 2.1.6): Signal SDIO interrupt only if it is enabled by core | ||
| 883 | */ | ||
| 884 | if (host->sdio_int && !(readl(host->base + DAVINCI_SDIOST0) & | ||
| 885 | SDIOST0_DAT1_HI)) { | ||
| 886 | writel(SDIOIST_IOINT, host->base + DAVINCI_SDIOIST); | ||
| 887 | mmc_signal_sdio_irq(host->mmc); | ||
| 888 | } | ||
| 889 | } | ||
| 890 | |||
| 869 | if (host->do_dma) { | 891 | if (host->do_dma) { |
| 870 | davinci_abort_dma(host); | 892 | davinci_abort_dma(host); |
| 871 | 893 | ||
| @@ -932,6 +954,21 @@ davinci_abort_data(struct mmc_davinci_host *host, struct mmc_data *data) | |||
| 932 | mmc_davinci_reset_ctrl(host, 0); | 954 | mmc_davinci_reset_ctrl(host, 0); |
| 933 | } | 955 | } |
| 934 | 956 | ||
| 957 | static irqreturn_t mmc_davinci_sdio_irq(int irq, void *dev_id) | ||
| 958 | { | ||
| 959 | struct mmc_davinci_host *host = dev_id; | ||
| 960 | unsigned int status; | ||
| 961 | |||
| 962 | status = readl(host->base + DAVINCI_SDIOIST); | ||
| 963 | if (status & SDIOIST_IOINT) { | ||
| 964 | dev_dbg(mmc_dev(host->mmc), | ||
| 965 | "SDIO interrupt status %x\n", status); | ||
| 966 | writel(status | SDIOIST_IOINT, host->base + DAVINCI_SDIOIST); | ||
| 967 | mmc_signal_sdio_irq(host->mmc); | ||
| 968 | } | ||
| 969 | return IRQ_HANDLED; | ||
| 970 | } | ||
| 971 | |||
| 935 | static irqreturn_t mmc_davinci_irq(int irq, void *dev_id) | 972 | static irqreturn_t mmc_davinci_irq(int irq, void *dev_id) |
| 936 | { | 973 | { |
| 937 | struct mmc_davinci_host *host = (struct mmc_davinci_host *)dev_id; | 974 | struct mmc_davinci_host *host = (struct mmc_davinci_host *)dev_id; |
| @@ -1076,11 +1113,32 @@ static int mmc_davinci_get_ro(struct mmc_host *mmc) | |||
| 1076 | return config->get_ro(pdev->id); | 1113 | return config->get_ro(pdev->id); |
| 1077 | } | 1114 | } |
| 1078 | 1115 | ||
| 1116 | static void mmc_davinci_enable_sdio_irq(struct mmc_host *mmc, int enable) | ||
| 1117 | { | ||
| 1118 | struct mmc_davinci_host *host = mmc_priv(mmc); | ||
| 1119 | |||
| 1120 | if (enable) { | ||
| 1121 | if (!(readl(host->base + DAVINCI_SDIOST0) & SDIOST0_DAT1_HI)) { | ||
| 1122 | writel(SDIOIST_IOINT, host->base + DAVINCI_SDIOIST); | ||
| 1123 | mmc_signal_sdio_irq(host->mmc); | ||
| 1124 | } else { | ||
| 1125 | host->sdio_int = true; | ||
| 1126 | writel(readl(host->base + DAVINCI_SDIOIEN) | | ||
| 1127 | SDIOIEN_IOINTEN, host->base + DAVINCI_SDIOIEN); | ||
| 1128 | } | ||
| 1129 | } else { | ||
| 1130 | host->sdio_int = false; | ||
| 1131 | writel(readl(host->base + DAVINCI_SDIOIEN) & ~SDIOIEN_IOINTEN, | ||
| 1132 | host->base + DAVINCI_SDIOIEN); | ||
| 1133 | } | ||
| 1134 | } | ||
| 1135 | |||
| 1079 | static struct mmc_host_ops mmc_davinci_ops = { | 1136 | static struct mmc_host_ops mmc_davinci_ops = { |
| 1080 | .request = mmc_davinci_request, | 1137 | .request = mmc_davinci_request, |
| 1081 | .set_ios = mmc_davinci_set_ios, | 1138 | .set_ios = mmc_davinci_set_ios, |
| 1082 | .get_cd = mmc_davinci_get_cd, | 1139 | .get_cd = mmc_davinci_get_cd, |
| 1083 | .get_ro = mmc_davinci_get_ro, | 1140 | .get_ro = mmc_davinci_get_ro, |
| 1141 | .enable_sdio_irq = mmc_davinci_enable_sdio_irq, | ||
| 1084 | }; | 1142 | }; |
| 1085 | 1143 | ||
| 1086 | /*----------------------------------------------------------------------*/ | 1144 | /*----------------------------------------------------------------------*/ |
| @@ -1209,7 +1267,8 @@ static int __init davinci_mmcsd_probe(struct platform_device *pdev) | |||
| 1209 | host->nr_sg = MAX_NR_SG; | 1267 | host->nr_sg = MAX_NR_SG; |
| 1210 | 1268 | ||
| 1211 | host->use_dma = use_dma; | 1269 | host->use_dma = use_dma; |
| 1212 | host->irq = irq; | 1270 | host->mmc_irq = irq; |
| 1271 | host->sdio_irq = platform_get_irq(pdev, 1); | ||
| 1213 | 1272 | ||
| 1214 | if (host->use_dma && davinci_acquire_dma_channels(host) != 0) | 1273 | if (host->use_dma && davinci_acquire_dma_channels(host) != 0) |
| 1215 | host->use_dma = 0; | 1274 | host->use_dma = 0; |
| @@ -1270,6 +1329,13 @@ static int __init davinci_mmcsd_probe(struct platform_device *pdev) | |||
| 1270 | if (ret) | 1329 | if (ret) |
| 1271 | goto out; | 1330 | goto out; |
| 1272 | 1331 | ||
| 1332 | if (host->sdio_irq >= 0) { | ||
| 1333 | ret = request_irq(host->sdio_irq, mmc_davinci_sdio_irq, 0, | ||
| 1334 | mmc_hostname(mmc), host); | ||
| 1335 | if (!ret) | ||
| 1336 | mmc->caps |= MMC_CAP_SDIO_IRQ; | ||
| 1337 | } | ||
| 1338 | |||
| 1273 | rename_region(mem, mmc_hostname(mmc)); | 1339 | rename_region(mem, mmc_hostname(mmc)); |
| 1274 | 1340 | ||
| 1275 | dev_info(mmc_dev(host->mmc), "Using %s, %d-bit mode\n", | 1341 | dev_info(mmc_dev(host->mmc), "Using %s, %d-bit mode\n", |
| @@ -1313,7 +1379,9 @@ static int __exit davinci_mmcsd_remove(struct platform_device *pdev) | |||
| 1313 | mmc_davinci_cpufreq_deregister(host); | 1379 | mmc_davinci_cpufreq_deregister(host); |
| 1314 | 1380 | ||
| 1315 | mmc_remove_host(host->mmc); | 1381 | mmc_remove_host(host->mmc); |
| 1316 | free_irq(host->irq, host); | 1382 | free_irq(host->mmc_irq, host); |
| 1383 | if (host->mmc->caps & MMC_CAP_SDIO_IRQ) | ||
| 1384 | free_irq(host->sdio_irq, host); | ||
| 1317 | 1385 | ||
| 1318 | davinci_release_dma_channels(host); | 1386 | davinci_release_dma_channels(host); |
| 1319 | 1387 | ||
