aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/mmc/host/mxcmmc.c
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/mmc/host/mxcmmc.c')
-rw-r--r--drivers/mmc/host/mxcmmc.c183
1 files changed, 42 insertions, 141 deletions
diff --git a/drivers/mmc/host/mxcmmc.c b/drivers/mmc/host/mxcmmc.c
index a72936eea6f..b87143d0aeb 100644
--- a/drivers/mmc/host/mxcmmc.c
+++ b/drivers/mmc/host/mxcmmc.c
@@ -33,17 +33,15 @@
33#include <linux/gpio.h> 33#include <linux/gpio.h>
34#include <linux/regulator/consumer.h> 34#include <linux/regulator/consumer.h>
35#include <linux/dmaengine.h> 35#include <linux/dmaengine.h>
36#include <linux/types.h>
37 36
38#include <asm/dma.h> 37#include <asm/dma.h>
39#include <asm/irq.h> 38#include <asm/irq.h>
40#include <asm/sizes.h> 39#include <asm/sizes.h>
41#include <linux/platform_data/mmc-mxcmmc.h> 40#include <mach/mmc.h>
42 41
43#include <linux/platform_data/dma-imx.h> 42#include <mach/dma.h>
44 43
45#define DRIVER_NAME "mxc-mmc" 44#define DRIVER_NAME "mxc-mmc"
46#define MXCMCI_TIMEOUT_MS 10000
47 45
48#define MMC_REG_STR_STP_CLK 0x00 46#define MMC_REG_STR_STP_CLK 0x00
49#define MMC_REG_STATUS 0x04 47#define MMC_REG_STATUS 0x04
@@ -112,11 +110,6 @@
112#define INT_WRITE_OP_DONE_EN (1 << 1) 110#define INT_WRITE_OP_DONE_EN (1 << 1)
113#define INT_READ_OP_EN (1 << 0) 111#define INT_READ_OP_EN (1 << 0)
114 112
115enum mxcmci_type {
116 IMX21_MMC,
117 IMX31_MMC,
118};
119
120struct mxcmci_host { 113struct mxcmci_host {
121 struct mmc_host *mmc; 114 struct mmc_host *mmc;
122 struct resource *res; 115 struct resource *res;
@@ -141,8 +134,7 @@ struct mxcmci_host {
141 u16 rev_no; 134 u16 rev_no;
142 unsigned int cmdat; 135 unsigned int cmdat;
143 136
144 struct clk *clk_ipg; 137 struct clk *clk;
145 struct clk *clk_per;
146 138
147 int clock; 139 int clock;
148 140
@@ -155,28 +147,7 @@ struct mxcmci_host {
155 int dmareq; 147 int dmareq;
156 struct dma_slave_config dma_slave_config; 148 struct dma_slave_config dma_slave_config;
157 struct imx_dma_data dma_data; 149 struct imx_dma_data dma_data;
158
159 struct timer_list watchdog;
160 enum mxcmci_type devtype;
161};
162
163static struct platform_device_id mxcmci_devtype[] = {
164 {
165 .name = "imx21-mmc",
166 .driver_data = IMX21_MMC,
167 }, {
168 .name = "imx31-mmc",
169 .driver_data = IMX31_MMC,
170 }, {
171 /* sentinel */
172 }
173}; 150};
174MODULE_DEVICE_TABLE(platform, mxcmci_devtype);
175
176static inline int is_imx31_mmc(struct mxcmci_host *host)
177{
178 return host->devtype == IMX31_MMC;
179}
180 151
181static void mxcmci_set_clk_rate(struct mxcmci_host *host, unsigned int clk_ios); 152static void mxcmci_set_clk_rate(struct mxcmci_host *host, unsigned int clk_ios);
182 153
@@ -246,7 +217,6 @@ static int mxcmci_setup_data(struct mxcmci_host *host, struct mmc_data *data)
246 unsigned int blksz = data->blksz; 217 unsigned int blksz = data->blksz;
247 unsigned int datasize = nob * blksz; 218 unsigned int datasize = nob * blksz;
248 struct scatterlist *sg; 219 struct scatterlist *sg;
249 enum dma_transfer_direction slave_dirn;
250 int i, nents; 220 int i, nents;
251 221
252 if (data->flags & MMC_DATA_STREAM) 222 if (data->flags & MMC_DATA_STREAM)
@@ -263,27 +233,24 @@ static int mxcmci_setup_data(struct mxcmci_host *host, struct mmc_data *data)
263 return 0; 233 return 0;
264 234
265 for_each_sg(data->sg, sg, data->sg_len, i) { 235 for_each_sg(data->sg, sg, data->sg_len, i) {
266 if (sg->offset & 3 || sg->length & 3 || sg->length < 512) { 236 if (sg->offset & 3 || sg->length & 3) {
267 host->do_dma = 0; 237 host->do_dma = 0;
268 return 0; 238 return 0;
269 } 239 }
270 } 240 }
271 241
272 if (data->flags & MMC_DATA_READ) { 242 if (data->flags & MMC_DATA_READ)
273 host->dma_dir = DMA_FROM_DEVICE; 243 host->dma_dir = DMA_FROM_DEVICE;
274 slave_dirn = DMA_DEV_TO_MEM; 244 else
275 } else {
276 host->dma_dir = DMA_TO_DEVICE; 245 host->dma_dir = DMA_TO_DEVICE;
277 slave_dirn = DMA_MEM_TO_DEV;
278 }
279 246
280 nents = dma_map_sg(host->dma->device->dev, data->sg, 247 nents = dma_map_sg(host->dma->device->dev, data->sg,
281 data->sg_len, host->dma_dir); 248 data->sg_len, host->dma_dir);
282 if (nents != data->sg_len) 249 if (nents != data->sg_len)
283 return -EINVAL; 250 return -EINVAL;
284 251
285 host->desc = dmaengine_prep_slave_sg(host->dma, 252 host->desc = host->dma->device->device_prep_slave_sg(host->dma,
286 data->sg, data->sg_len, slave_dirn, 253 data->sg, data->sg_len, host->dma_dir,
287 DMA_PREP_INTERRUPT | DMA_CTRL_ACK); 254 DMA_PREP_INTERRUPT | DMA_CTRL_ACK);
288 255
289 if (!host->desc) { 256 if (!host->desc) {
@@ -295,34 +262,10 @@ static int mxcmci_setup_data(struct mxcmci_host *host, struct mmc_data *data)
295 wmb(); 262 wmb();
296 263
297 dmaengine_submit(host->desc); 264 dmaengine_submit(host->desc);
298 dma_async_issue_pending(host->dma);
299
300 mod_timer(&host->watchdog, jiffies + msecs_to_jiffies(MXCMCI_TIMEOUT_MS));
301 265
302 return 0; 266 return 0;
303} 267}
304 268
305static void mxcmci_cmd_done(struct mxcmci_host *host, unsigned int stat);
306static void mxcmci_data_done(struct mxcmci_host *host, unsigned int stat);
307
308static void mxcmci_dma_callback(void *data)
309{
310 struct mxcmci_host *host = data;
311 u32 stat;
312
313 del_timer(&host->watchdog);
314
315 stat = readl(host->base + MMC_REG_STATUS);
316 writel(stat & ~STATUS_DATA_TRANS_DONE, host->base + MMC_REG_STATUS);
317
318 dev_dbg(mmc_dev(host->mmc), "%s: 0x%08x\n", __func__, stat);
319
320 if (stat & STATUS_READ_OP_DONE)
321 writel(STATUS_READ_OP_DONE, host->base + MMC_REG_STATUS);
322
323 mxcmci_data_done(host, stat);
324}
325
326static int mxcmci_start_cmd(struct mxcmci_host *host, struct mmc_command *cmd, 269static int mxcmci_start_cmd(struct mxcmci_host *host, struct mmc_command *cmd,
327 unsigned int cmdat) 270 unsigned int cmdat)
328{ 271{
@@ -354,14 +297,8 @@ static int mxcmci_start_cmd(struct mxcmci_host *host, struct mmc_command *cmd,
354 297
355 int_cntr = INT_END_CMD_RES_EN; 298 int_cntr = INT_END_CMD_RES_EN;
356 299
357 if (mxcmci_use_dma(host)) { 300 if (mxcmci_use_dma(host))
358 if (host->dma_dir == DMA_FROM_DEVICE) { 301 int_cntr |= INT_READ_OP_EN | INT_WRITE_OP_DONE_EN;
359 host->desc->callback = mxcmci_dma_callback;
360 host->desc->callback_param = host;
361 } else {
362 int_cntr |= INT_WRITE_OP_DONE_EN;
363 }
364 }
365 302
366 spin_lock_irqsave(&host->lock, flags); 303 spin_lock_irqsave(&host->lock, flags);
367 if (host->use_sdio) 304 if (host->use_sdio)
@@ -400,9 +337,11 @@ static int mxcmci_finish_data(struct mxcmci_host *host, unsigned int stat)
400 struct mmc_data *data = host->data; 337 struct mmc_data *data = host->data;
401 int data_error; 338 int data_error;
402 339
403 if (mxcmci_use_dma(host)) 340 if (mxcmci_use_dma(host)) {
341 dmaengine_terminate_all(host->dma);
404 dma_unmap_sg(host->dma->device->dev, data->sg, data->sg_len, 342 dma_unmap_sg(host->dma->device->dev, data->sg, data->sg_len,
405 host->dma_dir); 343 host->dma_dir);
344 }
406 345
407 if (stat & STATUS_ERR_MASK) { 346 if (stat & STATUS_ERR_MASK) {
408 dev_dbg(mmc_dev(host->mmc), "request failed. status: 0x%08x\n", 347 dev_dbg(mmc_dev(host->mmc), "request failed. status: 0x%08x\n",
@@ -677,10 +616,8 @@ static irqreturn_t mxcmci_irq(int irq, void *devid)
677 mxcmci_cmd_done(host, stat); 616 mxcmci_cmd_done(host, stat);
678 617
679 if (mxcmci_use_dma(host) && 618 if (mxcmci_use_dma(host) &&
680 (stat & (STATUS_DATA_TRANS_DONE | STATUS_WRITE_OP_DONE))) { 619 (stat & (STATUS_DATA_TRANS_DONE | STATUS_WRITE_OP_DONE)))
681 del_timer(&host->watchdog);
682 mxcmci_data_done(host, stat); 620 mxcmci_data_done(host, stat);
683 }
684 621
685 if (host->default_irq_mask && 622 if (host->default_irq_mask &&
686 (stat & (STATUS_CARD_INSERTION | STATUS_CARD_REMOVAL))) 623 (stat & (STATUS_CARD_INSERTION | STATUS_CARD_REMOVAL)))
@@ -728,7 +665,7 @@ static void mxcmci_set_clk_rate(struct mxcmci_host *host, unsigned int clk_ios)
728{ 665{
729 unsigned int divider; 666 unsigned int divider;
730 int prescaler = 0; 667 int prescaler = 0;
731 unsigned int clk_in = clk_get_rate(host->clk_per); 668 unsigned int clk_in = clk_get_rate(host->clk);
732 669
733 while (prescaler <= 0x800) { 670 while (prescaler <= 0x800) {
734 for (divider = 1; divider <= 0xF; divider++) { 671 for (divider = 1; divider <= 0xF; divider++) {
@@ -768,7 +705,6 @@ static int mxcmci_setup_dma(struct mmc_host *mmc)
768 config->src_addr_width = 4; 705 config->src_addr_width = 4;
769 config->dst_maxburst = host->burstlen; 706 config->dst_maxburst = host->burstlen;
770 config->src_maxburst = host->burstlen; 707 config->src_maxburst = host->burstlen;
771 config->device_fc = false;
772 708
773 return dmaengine_slave_config(host->dma, config); 709 return dmaengine_slave_config(host->dma, config);
774} 710}
@@ -866,8 +802,6 @@ static void mxcmci_enable_sdio_irq(struct mmc_host *mmc, int enable)
866 802
867static void mxcmci_init_card(struct mmc_host *host, struct mmc_card *card) 803static void mxcmci_init_card(struct mmc_host *host, struct mmc_card *card)
868{ 804{
869 struct mxcmci_host *mxcmci = mmc_priv(host);
870
871 /* 805 /*
872 * MX3 SoCs have a silicon bug which corrupts CRC calculation of 806 * MX3 SoCs have a silicon bug which corrupts CRC calculation of
873 * multi-block transfers when connected SDIO peripheral doesn't 807 * multi-block transfers when connected SDIO peripheral doesn't
@@ -875,7 +809,7 @@ static void mxcmci_init_card(struct mmc_host *host, struct mmc_card *card)
875 * One way to prevent this is to only allow 1-bit transfers. 809 * One way to prevent this is to only allow 1-bit transfers.
876 */ 810 */
877 811
878 if (is_imx31_mmc(mxcmci) && card->type == MMC_TYPE_SDIO) 812 if (cpu_is_mx3() && card->type == MMC_TYPE_SDIO)
879 host->caps &= ~MMC_CAP_4_BIT_DATA; 813 host->caps &= ~MMC_CAP_4_BIT_DATA;
880 else 814 else
881 host->caps |= MMC_CAP_4_BIT_DATA; 815 host->caps |= MMC_CAP_4_BIT_DATA;
@@ -893,34 +827,6 @@ static bool filter(struct dma_chan *chan, void *param)
893 return true; 827 return true;
894} 828}
895 829
896static void mxcmci_watchdog(unsigned long data)
897{
898 struct mmc_host *mmc = (struct mmc_host *)data;
899 struct mxcmci_host *host = mmc_priv(mmc);
900 struct mmc_request *req = host->req;
901 unsigned int stat = readl(host->base + MMC_REG_STATUS);
902
903 if (host->dma_dir == DMA_FROM_DEVICE) {
904 dmaengine_terminate_all(host->dma);
905 dev_err(mmc_dev(host->mmc),
906 "%s: read time out (status = 0x%08x)\n",
907 __func__, stat);
908 } else {
909 dev_err(mmc_dev(host->mmc),
910 "%s: write time out (status = 0x%08x)\n",
911 __func__, stat);
912 mxcmci_softreset(host);
913 }
914
915 /* Mark transfer as erroneus and inform the upper layers */
916
917 host->data->error = -ETIMEDOUT;
918 host->req = NULL;
919 host->cmd = NULL;
920 host->data = NULL;
921 mmc_request_done(host->mmc, req);
922}
923
924static const struct mmc_host_ops mxcmci_ops = { 830static const struct mmc_host_ops mxcmci_ops = {
925 .request = mxcmci_request, 831 .request = mxcmci_request,
926 .set_ios = mxcmci_set_ios, 832 .set_ios = mxcmci_set_ios,
@@ -937,7 +843,7 @@ static int mxcmci_probe(struct platform_device *pdev)
937 int ret = 0, irq; 843 int ret = 0, irq;
938 dma_cap_mask_t mask; 844 dma_cap_mask_t mask;
939 845
940 pr_info("i.MX SDHC driver\n"); 846 printk(KERN_INFO "i.MX SDHC driver\n");
941 847
942 iores = platform_get_resource(pdev, IORESOURCE_MEM, 0); 848 iores = platform_get_resource(pdev, IORESOURCE_MEM, 0);
943 irq = platform_get_irq(pdev, 0); 849 irq = platform_get_irq(pdev, 0);
@@ -973,7 +879,6 @@ static int mxcmci_probe(struct platform_device *pdev)
973 879
974 host->mmc = mmc; 880 host->mmc = mmc;
975 host->pdata = pdev->dev.platform_data; 881 host->pdata = pdev->dev.platform_data;
976 host->devtype = pdev->id_entry->driver_data;
977 spin_lock_init(&host->lock); 882 spin_lock_init(&host->lock);
978 883
979 mxcmci_init_ocr(host); 884 mxcmci_init_ocr(host);
@@ -987,20 +892,12 @@ static int mxcmci_probe(struct platform_device *pdev)
987 host->res = r; 892 host->res = r;
988 host->irq = irq; 893 host->irq = irq;
989 894
990 host->clk_ipg = devm_clk_get(&pdev->dev, "ipg"); 895 host->clk = clk_get(&pdev->dev, NULL);
991 if (IS_ERR(host->clk_ipg)) { 896 if (IS_ERR(host->clk)) {
992 ret = PTR_ERR(host->clk_ipg); 897 ret = PTR_ERR(host->clk);
993 goto out_iounmap; 898 goto out_iounmap;
994 } 899 }
995 900 clk_enable(host->clk);
996 host->clk_per = devm_clk_get(&pdev->dev, "per");
997 if (IS_ERR(host->clk_per)) {
998 ret = PTR_ERR(host->clk_per);
999 goto out_iounmap;
1000 }
1001
1002 clk_prepare_enable(host->clk_per);
1003 clk_prepare_enable(host->clk_ipg);
1004 901
1005 mxcmci_softreset(host); 902 mxcmci_softreset(host);
1006 903
@@ -1012,8 +909,8 @@ static int mxcmci_probe(struct platform_device *pdev)
1012 goto out_clk_put; 909 goto out_clk_put;
1013 } 910 }
1014 911
1015 mmc->f_min = clk_get_rate(host->clk_per) >> 16; 912 mmc->f_min = clk_get_rate(host->clk) >> 16;
1016 mmc->f_max = clk_get_rate(host->clk_per) >> 1; 913 mmc->f_max = clk_get_rate(host->clk) >> 1;
1017 914
1018 /* recommended in data sheet */ 915 /* recommended in data sheet */
1019 writew(0x2db4, host->base + MMC_REG_READ_TO); 916 writew(0x2db4, host->base + MMC_REG_READ_TO);
@@ -1054,10 +951,6 @@ static int mxcmci_probe(struct platform_device *pdev)
1054 951
1055 mmc_add_host(mmc); 952 mmc_add_host(mmc);
1056 953
1057 init_timer(&host->watchdog);
1058 host->watchdog.function = &mxcmci_watchdog;
1059 host->watchdog.data = (unsigned long)mmc;
1060
1061 return 0; 954 return 0;
1062 955
1063out_free_irq: 956out_free_irq:
@@ -1066,8 +959,8 @@ out_free_dma:
1066 if (host->dma) 959 if (host->dma)
1067 dma_release_channel(host->dma); 960 dma_release_channel(host->dma);
1068out_clk_put: 961out_clk_put:
1069 clk_disable_unprepare(host->clk_per); 962 clk_disable(host->clk);
1070 clk_disable_unprepare(host->clk_ipg); 963 clk_put(host->clk);
1071out_iounmap: 964out_iounmap:
1072 iounmap(host->base); 965 iounmap(host->base);
1073out_free: 966out_free:
@@ -1098,8 +991,8 @@ static int mxcmci_remove(struct platform_device *pdev)
1098 if (host->dma) 991 if (host->dma)
1099 dma_release_channel(host->dma); 992 dma_release_channel(host->dma);
1100 993
1101 clk_disable_unprepare(host->clk_per); 994 clk_disable(host->clk);
1102 clk_disable_unprepare(host->clk_ipg); 995 clk_put(host->clk);
1103 996
1104 release_mem_region(host->res->start, resource_size(host->res)); 997 release_mem_region(host->res->start, resource_size(host->res));
1105 998
@@ -1117,8 +1010,7 @@ static int mxcmci_suspend(struct device *dev)
1117 1010
1118 if (mmc) 1011 if (mmc)
1119 ret = mmc_suspend_host(mmc); 1012 ret = mmc_suspend_host(mmc);
1120 clk_disable_unprepare(host->clk_per); 1013 clk_disable(host->clk);
1121 clk_disable_unprepare(host->clk_ipg);
1122 1014
1123 return ret; 1015 return ret;
1124} 1016}
@@ -1129,8 +1021,7 @@ static int mxcmci_resume(struct device *dev)
1129 struct mxcmci_host *host = mmc_priv(mmc); 1021 struct mxcmci_host *host = mmc_priv(mmc);
1130 int ret = 0; 1022 int ret = 0;
1131 1023
1132 clk_prepare_enable(host->clk_per); 1024 clk_enable(host->clk);
1133 clk_prepare_enable(host->clk_ipg);
1134 if (mmc) 1025 if (mmc)
1135 ret = mmc_resume_host(mmc); 1026 ret = mmc_resume_host(mmc);
1136 1027
@@ -1146,7 +1037,6 @@ static const struct dev_pm_ops mxcmci_pm_ops = {
1146static struct platform_driver mxcmci_driver = { 1037static struct platform_driver mxcmci_driver = {
1147 .probe = mxcmci_probe, 1038 .probe = mxcmci_probe,
1148 .remove = mxcmci_remove, 1039 .remove = mxcmci_remove,
1149 .id_table = mxcmci_devtype,
1150 .driver = { 1040 .driver = {
1151 .name = DRIVER_NAME, 1041 .name = DRIVER_NAME,
1152 .owner = THIS_MODULE, 1042 .owner = THIS_MODULE,
@@ -1156,9 +1046,20 @@ static struct platform_driver mxcmci_driver = {
1156 } 1046 }
1157}; 1047};
1158 1048
1159module_platform_driver(mxcmci_driver); 1049static int __init mxcmci_init(void)
1050{
1051 return platform_driver_register(&mxcmci_driver);
1052}
1053
1054static void __exit mxcmci_exit(void)
1055{
1056 platform_driver_unregister(&mxcmci_driver);
1057}
1058
1059module_init(mxcmci_init);
1060module_exit(mxcmci_exit);
1160 1061
1161MODULE_DESCRIPTION("i.MX Multimedia Card Interface Driver"); 1062MODULE_DESCRIPTION("i.MX Multimedia Card Interface Driver");
1162MODULE_AUTHOR("Sascha Hauer, Pengutronix"); 1063MODULE_AUTHOR("Sascha Hauer, Pengutronix");
1163MODULE_LICENSE("GPL"); 1064MODULE_LICENSE("GPL");
1164MODULE_ALIAS("platform:mxc-mmc"); 1065MODULE_ALIAS("platform:imx-mmc");