diff options
Diffstat (limited to 'drivers/mmc/host/mxcmmc.c')
-rw-r--r-- | drivers/mmc/host/mxcmmc.c | 183 |
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 | ||
115 | enum mxcmci_type { | ||
116 | IMX21_MMC, | ||
117 | IMX31_MMC, | ||
118 | }; | ||
119 | |||
120 | struct mxcmci_host { | 113 | struct 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 | |||
163 | static 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 | }; |
174 | MODULE_DEVICE_TABLE(platform, mxcmci_devtype); | ||
175 | |||
176 | static inline int is_imx31_mmc(struct mxcmci_host *host) | ||
177 | { | ||
178 | return host->devtype == IMX31_MMC; | ||
179 | } | ||
180 | 151 | ||
181 | static void mxcmci_set_clk_rate(struct mxcmci_host *host, unsigned int clk_ios); | 152 | static 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 | ||
305 | static void mxcmci_cmd_done(struct mxcmci_host *host, unsigned int stat); | ||
306 | static void mxcmci_data_done(struct mxcmci_host *host, unsigned int stat); | ||
307 | |||
308 | static 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 | |||
326 | static int mxcmci_start_cmd(struct mxcmci_host *host, struct mmc_command *cmd, | 269 | static 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 | ||
867 | static void mxcmci_init_card(struct mmc_host *host, struct mmc_card *card) | 803 | static 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 | ||
896 | static 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 | |||
924 | static const struct mmc_host_ops mxcmci_ops = { | 830 | static 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 | ||
1063 | out_free_irq: | 956 | out_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); |
1068 | out_clk_put: | 961 | out_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); |
1071 | out_iounmap: | 964 | out_iounmap: |
1072 | iounmap(host->base); | 965 | iounmap(host->base); |
1073 | out_free: | 966 | out_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 = { | |||
1146 | static struct platform_driver mxcmci_driver = { | 1037 | static 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 | ||
1159 | module_platform_driver(mxcmci_driver); | 1049 | static int __init mxcmci_init(void) |
1050 | { | ||
1051 | return platform_driver_register(&mxcmci_driver); | ||
1052 | } | ||
1053 | |||
1054 | static void __exit mxcmci_exit(void) | ||
1055 | { | ||
1056 | platform_driver_unregister(&mxcmci_driver); | ||
1057 | } | ||
1058 | |||
1059 | module_init(mxcmci_init); | ||
1060 | module_exit(mxcmci_exit); | ||
1160 | 1061 | ||
1161 | MODULE_DESCRIPTION("i.MX Multimedia Card Interface Driver"); | 1062 | MODULE_DESCRIPTION("i.MX Multimedia Card Interface Driver"); |
1162 | MODULE_AUTHOR("Sascha Hauer, Pengutronix"); | 1063 | MODULE_AUTHOR("Sascha Hauer, Pengutronix"); |
1163 | MODULE_LICENSE("GPL"); | 1064 | MODULE_LICENSE("GPL"); |
1164 | MODULE_ALIAS("platform:mxc-mmc"); | 1065 | MODULE_ALIAS("platform:imx-mmc"); |