aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/mmc/host/msm_sdcc.c
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/mmc/host/msm_sdcc.c')
-rw-r--r--drivers/mmc/host/msm_sdcc.c86
1 files changed, 58 insertions, 28 deletions
diff --git a/drivers/mmc/host/msm_sdcc.c b/drivers/mmc/host/msm_sdcc.c
index a4c865a5286b..80d8eb143b48 100644
--- a/drivers/mmc/host/msm_sdcc.c
+++ b/drivers/mmc/host/msm_sdcc.c
@@ -213,7 +213,8 @@ msmsdcc_dma_exec_func(struct msm_dmov_cmd *cmd)
213 msmsdcc_writel(host, host->cmd_timeout, MMCIDATATIMER); 213 msmsdcc_writel(host, host->cmd_timeout, MMCIDATATIMER);
214 msmsdcc_writel(host, (unsigned int)host->curr.xfer_size, 214 msmsdcc_writel(host, (unsigned int)host->curr.xfer_size,
215 MMCIDATALENGTH); 215 MMCIDATALENGTH);
216 msmsdcc_writel(host, host->cmd_pio_irqmask, MMCIMASK1); 216 msmsdcc_writel(host, (msmsdcc_readl(host, MMCIMASK0) &
217 (~MCI_IRQ_PIO)) | host->cmd_pio_irqmask, MMCIMASK0);
217 msmsdcc_writel(host, host->cmd_datactrl, MMCIDATACTRL); 218 msmsdcc_writel(host, host->cmd_datactrl, MMCIDATACTRL);
218 219
219 if (host->cmd_cmd) { 220 if (host->cmd_cmd) {
@@ -388,7 +389,7 @@ static int msmsdcc_config_dma(struct msmsdcc_host *host, struct mmc_data *data)
388 n = dma_map_sg(mmc_dev(host->mmc), host->dma.sg, 389 n = dma_map_sg(mmc_dev(host->mmc), host->dma.sg,
389 host->dma.num_ents, host->dma.dir); 390 host->dma.num_ents, host->dma.dir);
390 if (n == 0) { 391 if (n == 0) {
391 printk(KERN_ERR "%s: Unable to map in all sg elements\n", 392 pr_err("%s: Unable to map in all sg elements\n",
392 mmc_hostname(host->mmc)); 393 mmc_hostname(host->mmc));
393 host->dma.sg = NULL; 394 host->dma.sg = NULL;
394 host->dma.num_ents = 0; 395 host->dma.num_ents = 0;
@@ -474,7 +475,7 @@ msmsdcc_start_command_deferred(struct msmsdcc_host *host,
474 *c |= MCI_CSPM_MCIABORT; 475 *c |= MCI_CSPM_MCIABORT;
475 476
476 if (host->curr.cmd != NULL) { 477 if (host->curr.cmd != NULL) {
477 printk(KERN_ERR "%s: Overlapping command requests\n", 478 pr_err("%s: Overlapping command requests\n",
478 mmc_hostname(host->mmc)); 479 mmc_hostname(host->mmc));
479 } 480 }
480 host->curr.cmd = cmd; 481 host->curr.cmd = cmd;
@@ -543,7 +544,9 @@ msmsdcc_start_data(struct msmsdcc_host *host, struct mmc_data *data,
543 544
544 msmsdcc_writel(host, host->curr.xfer_size, MMCIDATALENGTH); 545 msmsdcc_writel(host, host->curr.xfer_size, MMCIDATALENGTH);
545 546
546 msmsdcc_writel(host, pio_irqmask, MMCIMASK1); 547 msmsdcc_writel(host, (msmsdcc_readl(host, MMCIMASK0) &
548 (~MCI_IRQ_PIO)) | pio_irqmask, MMCIMASK0);
549
547 msmsdcc_writel(host, datactrl, MMCIDATACTRL); 550 msmsdcc_writel(host, datactrl, MMCIDATACTRL);
548 551
549 if (cmd) { 552 if (cmd) {
@@ -659,8 +662,13 @@ msmsdcc_pio_irq(int irq, void *dev_id)
659{ 662{
660 struct msmsdcc_host *host = dev_id; 663 struct msmsdcc_host *host = dev_id;
661 uint32_t status; 664 uint32_t status;
665 u32 mci_mask0;
662 666
663 status = msmsdcc_readl(host, MMCISTATUS); 667 status = msmsdcc_readl(host, MMCISTATUS);
668 mci_mask0 = msmsdcc_readl(host, MMCIMASK0);
669
670 if (((mci_mask0 & status) & MCI_IRQ_PIO) == 0)
671 return IRQ_NONE;
664 672
665 do { 673 do {
666 unsigned long flags; 674 unsigned long flags;
@@ -719,10 +727,12 @@ msmsdcc_pio_irq(int irq, void *dev_id)
719 } while (1); 727 } while (1);
720 728
721 if (status & MCI_RXACTIVE && host->curr.xfer_remain < MCI_FIFOSIZE) 729 if (status & MCI_RXACTIVE && host->curr.xfer_remain < MCI_FIFOSIZE)
722 msmsdcc_writel(host, MCI_RXDATAAVLBLMASK, MMCIMASK1); 730 msmsdcc_writel(host, (mci_mask0 & (~MCI_IRQ_PIO)) |
731 MCI_RXDATAAVLBLMASK, MMCIMASK0);
723 732
724 if (!host->curr.xfer_remain) 733 if (!host->curr.xfer_remain)
725 msmsdcc_writel(host, 0, MMCIMASK1); 734 msmsdcc_writel(host, (mci_mask0 & (~MCI_IRQ_PIO)) | 0,
735 MMCIMASK0);
726 736
727 return IRQ_HANDLED; 737 return IRQ_HANDLED;
728} 738}
@@ -854,6 +864,8 @@ msmsdcc_irq(int irq, void *dev_id)
854 do { 864 do {
855 status = msmsdcc_readl(host, MMCISTATUS); 865 status = msmsdcc_readl(host, MMCISTATUS);
856 status &= msmsdcc_readl(host, MMCIMASK0); 866 status &= msmsdcc_readl(host, MMCIMASK0);
867 if ((status & (~MCI_IRQ_PIO)) == 0)
868 break;
857 msmsdcc_writel(host, status, MMCICLEAR); 869 msmsdcc_writel(host, status, MMCICLEAR);
858 870
859 if (status & MCI_SDIOINTR) 871 if (status & MCI_SDIOINTR)
@@ -939,7 +951,7 @@ static void msmsdcc_setup_gpio(struct msmsdcc_host *host, bool enable)
939 struct msm_mmc_gpio_data *curr; 951 struct msm_mmc_gpio_data *curr;
940 int i, rc = 0; 952 int i, rc = 0;
941 953
942 if (!host->plat->gpio_data && host->gpio_config_status == enable) 954 if (!host->plat->gpio_data || host->gpio_config_status == enable)
943 return; 955 return;
944 956
945 curr = host->plat->gpio_data; 957 curr = host->plat->gpio_data;
@@ -1052,10 +1064,19 @@ static void msmsdcc_enable_sdio_irq(struct mmc_host *mmc, int enable)
1052 spin_unlock_irqrestore(&host->lock, flags); 1064 spin_unlock_irqrestore(&host->lock, flags);
1053} 1065}
1054 1066
1067static void msmsdcc_init_card(struct mmc_host *mmc, struct mmc_card *card)
1068{
1069 struct msmsdcc_host *host = mmc_priv(mmc);
1070
1071 if (host->plat->init_card)
1072 host->plat->init_card(card);
1073}
1074
1055static const struct mmc_host_ops msmsdcc_ops = { 1075static const struct mmc_host_ops msmsdcc_ops = {
1056 .request = msmsdcc_request, 1076 .request = msmsdcc_request,
1057 .set_ios = msmsdcc_set_ios, 1077 .set_ios = msmsdcc_set_ios,
1058 .enable_sdio_irq = msmsdcc_enable_sdio_irq, 1078 .enable_sdio_irq = msmsdcc_enable_sdio_irq,
1079 .init_card = msmsdcc_init_card,
1059}; 1080};
1060 1081
1061static void 1082static void
@@ -1092,7 +1113,7 @@ msmsdcc_platform_status_irq(int irq, void *dev_id)
1092{ 1113{
1093 struct msmsdcc_host *host = dev_id; 1114 struct msmsdcc_host *host = dev_id;
1094 1115
1095 printk(KERN_DEBUG "%s: %d\n", __func__, irq); 1116 pr_debug("%s: %d\n", __func__, irq);
1096 msmsdcc_check_status((unsigned long) host); 1117 msmsdcc_check_status((unsigned long) host);
1097 return IRQ_HANDLED; 1118 return IRQ_HANDLED;
1098} 1119}
@@ -1102,7 +1123,7 @@ msmsdcc_status_notify_cb(int card_present, void *dev_id)
1102{ 1123{
1103 struct msmsdcc_host *host = dev_id; 1124 struct msmsdcc_host *host = dev_id;
1104 1125
1105 printk(KERN_DEBUG "%s: card_present %d\n", mmc_hostname(host->mmc), 1126 pr_debug("%s: card_present %d\n", mmc_hostname(host->mmc),
1106 card_present); 1127 card_present);
1107 msmsdcc_check_status((unsigned long) host); 1128 msmsdcc_check_status((unsigned long) host);
1108} 1129}
@@ -1150,7 +1171,6 @@ msmsdcc_probe(struct platform_device *pdev)
1150 struct msmsdcc_host *host; 1171 struct msmsdcc_host *host;
1151 struct mmc_host *mmc; 1172 struct mmc_host *mmc;
1152 struct resource *cmd_irqres = NULL; 1173 struct resource *cmd_irqres = NULL;
1153 struct resource *pio_irqres = NULL;
1154 struct resource *stat_irqres = NULL; 1174 struct resource *stat_irqres = NULL;
1155 struct resource *memres = NULL; 1175 struct resource *memres = NULL;
1156 struct resource *dmares = NULL; 1176 struct resource *dmares = NULL;
@@ -1175,12 +1195,10 @@ msmsdcc_probe(struct platform_device *pdev)
1175 dmares = platform_get_resource(pdev, IORESOURCE_DMA, 0); 1195 dmares = platform_get_resource(pdev, IORESOURCE_DMA, 0);
1176 cmd_irqres = platform_get_resource_byname(pdev, IORESOURCE_IRQ, 1196 cmd_irqres = platform_get_resource_byname(pdev, IORESOURCE_IRQ,
1177 "cmd_irq"); 1197 "cmd_irq");
1178 pio_irqres = platform_get_resource_byname(pdev, IORESOURCE_IRQ,
1179 "pio_irq");
1180 stat_irqres = platform_get_resource_byname(pdev, IORESOURCE_IRQ, 1198 stat_irqres = platform_get_resource_byname(pdev, IORESOURCE_IRQ,
1181 "status_irq"); 1199 "status_irq");
1182 1200
1183 if (!cmd_irqres || !pio_irqres || !memres) { 1201 if (!cmd_irqres || !memres) {
1184 pr_err("%s: Invalid resource\n", __func__); 1202 pr_err("%s: Invalid resource\n", __func__);
1185 return -ENXIO; 1203 return -ENXIO;
1186 } 1204 }
@@ -1200,17 +1218,20 @@ msmsdcc_probe(struct platform_device *pdev)
1200 host->plat = plat; 1218 host->plat = plat;
1201 host->mmc = mmc; 1219 host->mmc = mmc;
1202 host->curr.cmd = NULL; 1220 host->curr.cmd = NULL;
1221 init_timer(&host->busclk_timer);
1222 host->busclk_timer.data = (unsigned long) host;
1223 host->busclk_timer.function = msmsdcc_busclk_expired;
1224
1203 1225
1204 host->cmdpoll = 1; 1226 host->cmdpoll = 1;
1205 1227
1206 host->base = ioremap(memres->start, PAGE_SIZE); 1228 host->base = ioremap(memres->start, PAGE_SIZE);
1207 if (!host->base) { 1229 if (!host->base) {
1208 ret = -ENOMEM; 1230 ret = -ENOMEM;
1209 goto out; 1231 goto host_free;
1210 } 1232 }
1211 1233
1212 host->cmd_irqres = cmd_irqres; 1234 host->cmd_irqres = cmd_irqres;
1213 host->pio_irqres = pio_irqres;
1214 host->memres = memres; 1235 host->memres = memres;
1215 host->dmares = dmares; 1236 host->dmares = dmares;
1216 spin_lock_init(&host->lock); 1237 spin_lock_init(&host->lock);
@@ -1221,13 +1242,19 @@ msmsdcc_probe(struct platform_device *pdev)
1221 /* 1242 /*
1222 * Setup DMA 1243 * Setup DMA
1223 */ 1244 */
1224 msmsdcc_init_dma(host); 1245 if (host->dmares) {
1246 ret = msmsdcc_init_dma(host);
1247 if (ret)
1248 goto ioremap_free;
1249 } else {
1250 host->dma.channel = -1;
1251 }
1225 1252
1226 /* Get our clocks */ 1253 /* Get our clocks */
1227 host->pclk = clk_get(&pdev->dev, "sdc_pclk"); 1254 host->pclk = clk_get(&pdev->dev, "sdc_pclk");
1228 if (IS_ERR(host->pclk)) { 1255 if (IS_ERR(host->pclk)) {
1229 ret = PTR_ERR(host->pclk); 1256 ret = PTR_ERR(host->pclk);
1230 goto host_free; 1257 goto dma_free;
1231 } 1258 }
1232 1259
1233 host->clk = clk_get(&pdev->dev, "sdc_clk"); 1260 host->clk = clk_get(&pdev->dev, "sdc_clk");
@@ -1236,17 +1263,17 @@ msmsdcc_probe(struct platform_device *pdev)
1236 goto pclk_put; 1263 goto pclk_put;
1237 } 1264 }
1238 1265
1239 /* Enable clocks */
1240 ret = msmsdcc_enable_clocks(host);
1241 if (ret)
1242 goto clk_put;
1243
1244 ret = clk_set_rate(host->clk, msmsdcc_fmin); 1266 ret = clk_set_rate(host->clk, msmsdcc_fmin);
1245 if (ret) { 1267 if (ret) {
1246 pr_err("%s: Clock rate set failed (%d)\n", __func__, ret); 1268 pr_err("%s: Clock rate set failed (%d)\n", __func__, ret);
1247 goto clk_disable; 1269 goto clk_put;
1248 } 1270 }
1249 1271
1272 /* Enable clocks */
1273 ret = msmsdcc_enable_clocks(host);
1274 if (ret)
1275 goto clk_put;
1276
1250 host->pclk_rate = clk_get_rate(host->pclk); 1277 host->pclk_rate = clk_get_rate(host->pclk);
1251 host->clk_rate = clk_get_rate(host->clk); 1278 host->clk_rate = clk_get_rate(host->clk);
1252 1279
@@ -1316,16 +1343,12 @@ msmsdcc_probe(struct platform_device *pdev)
1316 host->eject = !host->oldstat; 1343 host->eject = !host->oldstat;
1317 } 1344 }
1318 1345
1319 init_timer(&host->busclk_timer);
1320 host->busclk_timer.data = (unsigned long) host;
1321 host->busclk_timer.function = msmsdcc_busclk_expired;
1322
1323 ret = request_irq(cmd_irqres->start, msmsdcc_irq, IRQF_SHARED, 1346 ret = request_irq(cmd_irqres->start, msmsdcc_irq, IRQF_SHARED,
1324 DRIVER_NAME " (cmd)", host); 1347 DRIVER_NAME " (cmd)", host);
1325 if (ret) 1348 if (ret)
1326 goto stat_irq_free; 1349 goto stat_irq_free;
1327 1350
1328 ret = request_irq(pio_irqres->start, msmsdcc_pio_irq, IRQF_SHARED, 1351 ret = request_irq(cmd_irqres->start, msmsdcc_pio_irq, IRQF_SHARED,
1329 DRIVER_NAME " (pio)", host); 1352 DRIVER_NAME " (pio)", host);
1330 if (ret) 1353 if (ret)
1331 goto cmd_irq_free; 1354 goto cmd_irq_free;
@@ -1368,6 +1391,13 @@ msmsdcc_probe(struct platform_device *pdev)
1368 clk_put(host->clk); 1391 clk_put(host->clk);
1369 pclk_put: 1392 pclk_put:
1370 clk_put(host->pclk); 1393 clk_put(host->pclk);
1394dma_free:
1395 if (host->dmares)
1396 dma_free_coherent(NULL, sizeof(struct msmsdcc_nc_dmadata),
1397 host->dma.nc, host->dma.nc_busaddr);
1398ioremap_free:
1399 tasklet_kill(&host->dma_tlet);
1400 iounmap(host->base);
1371 host_free: 1401 host_free:
1372 mmc_free_host(mmc); 1402 mmc_free_host(mmc);
1373 out: 1403 out: