aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/mmc/host/sdhci-esdhc-imx.c
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/mmc/host/sdhci-esdhc-imx.c')
-rw-r--r--drivers/mmc/host/sdhci-esdhc-imx.c233
1 files changed, 79 insertions, 154 deletions
diff --git a/drivers/mmc/host/sdhci-esdhc-imx.c b/drivers/mmc/host/sdhci-esdhc-imx.c
index e07df812ff1..4dc0028086a 100644
--- a/drivers/mmc/host/sdhci-esdhc-imx.c
+++ b/drivers/mmc/host/sdhci-esdhc-imx.c
@@ -24,8 +24,7 @@
24#include <linux/of.h> 24#include <linux/of.h>
25#include <linux/of_device.h> 25#include <linux/of_device.h>
26#include <linux/of_gpio.h> 26#include <linux/of_gpio.h>
27#include <linux/pinctrl/consumer.h> 27#include <mach/esdhc.h>
28#include <linux/platform_data/mmc-esdhc-imx.h>
29#include "sdhci-pltfm.h" 28#include "sdhci-pltfm.h"
30#include "sdhci-esdhc.h" 29#include "sdhci-esdhc.h"
31 30
@@ -33,16 +32,6 @@
33/* VENDOR SPEC register */ 32/* VENDOR SPEC register */
34#define SDHCI_VENDOR_SPEC 0xC0 33#define SDHCI_VENDOR_SPEC 0xC0
35#define SDHCI_VENDOR_SPEC_SDIO_QUIRK 0x00000002 34#define SDHCI_VENDOR_SPEC_SDIO_QUIRK 0x00000002
36#define SDHCI_WTMK_LVL 0x44
37#define SDHCI_MIX_CTRL 0x48
38
39/*
40 * There is an INT DMA ERR mis-match between eSDHC and STD SDHC SPEC:
41 * Bit25 is used in STD SPEC, and is reserved in fsl eSDHC design,
42 * but bit28 is used as the INT DMA ERR in fsl eSDHC design.
43 * Define this macro DMA error INT for fsl eSDHC
44 */
45#define SDHCI_INT_VENDOR_SPEC_DMA_ERR 0x10000000
46 35
47/* 36/*
48 * The CMDTYPE of the CMD register (offset 0xE) should be set to 37 * The CMDTYPE of the CMD register (offset 0xE) should be set to
@@ -62,18 +51,13 @@ enum imx_esdhc_type {
62 IMX35_ESDHC, 51 IMX35_ESDHC,
63 IMX51_ESDHC, 52 IMX51_ESDHC,
64 IMX53_ESDHC, 53 IMX53_ESDHC,
65 IMX6Q_USDHC,
66}; 54};
67 55
68struct pltfm_imx_data { 56struct pltfm_imx_data {
69 int flags; 57 int flags;
70 u32 scratchpad; 58 u32 scratchpad;
71 enum imx_esdhc_type devtype; 59 enum imx_esdhc_type devtype;
72 struct pinctrl *pinctrl;
73 struct esdhc_platform_data boarddata; 60 struct esdhc_platform_data boarddata;
74 struct clk *clk_ipg;
75 struct clk *clk_ahb;
76 struct clk *clk_per;
77}; 61};
78 62
79static struct platform_device_id imx_esdhc_devtype[] = { 63static struct platform_device_id imx_esdhc_devtype[] = {
@@ -90,9 +74,6 @@ static struct platform_device_id imx_esdhc_devtype[] = {
90 .name = "sdhci-esdhc-imx53", 74 .name = "sdhci-esdhc-imx53",
91 .driver_data = IMX53_ESDHC, 75 .driver_data = IMX53_ESDHC,
92 }, { 76 }, {
93 .name = "sdhci-usdhc-imx6q",
94 .driver_data = IMX6Q_USDHC,
95 }, {
96 /* sentinel */ 77 /* sentinel */
97 } 78 }
98}; 79};
@@ -103,7 +84,6 @@ static const struct of_device_id imx_esdhc_dt_ids[] = {
103 { .compatible = "fsl,imx35-esdhc", .data = &imx_esdhc_devtype[IMX35_ESDHC], }, 84 { .compatible = "fsl,imx35-esdhc", .data = &imx_esdhc_devtype[IMX35_ESDHC], },
104 { .compatible = "fsl,imx51-esdhc", .data = &imx_esdhc_devtype[IMX51_ESDHC], }, 85 { .compatible = "fsl,imx51-esdhc", .data = &imx_esdhc_devtype[IMX51_ESDHC], },
105 { .compatible = "fsl,imx53-esdhc", .data = &imx_esdhc_devtype[IMX53_ESDHC], }, 86 { .compatible = "fsl,imx53-esdhc", .data = &imx_esdhc_devtype[IMX53_ESDHC], },
106 { .compatible = "fsl,imx6q-usdhc", .data = &imx_esdhc_devtype[IMX6Q_USDHC], },
107 { /* sentinel */ } 87 { /* sentinel */ }
108}; 88};
109MODULE_DEVICE_TABLE(of, imx_esdhc_dt_ids); 89MODULE_DEVICE_TABLE(of, imx_esdhc_dt_ids);
@@ -128,11 +108,6 @@ static inline int is_imx53_esdhc(struct pltfm_imx_data *data)
128 return data->devtype == IMX53_ESDHC; 108 return data->devtype == IMX53_ESDHC;
129} 109}
130 110
131static inline int is_imx6q_usdhc(struct pltfm_imx_data *data)
132{
133 return data->devtype == IMX6Q_USDHC;
134}
135
136static inline void esdhc_clrset_le(struct sdhci_host *host, u32 mask, u32 val, int reg) 111static inline void esdhc_clrset_le(struct sdhci_host *host, u32 mask, u32 val, int reg)
137{ 112{
138 void __iomem *base = host->ioaddr + (reg & ~0x3); 113 void __iomem *base = host->ioaddr + (reg & ~0x3);
@@ -160,27 +135,6 @@ static u32 esdhc_readl_le(struct sdhci_host *host, int reg)
160 val |= SDHCI_CARD_PRESENT; 135 val |= SDHCI_CARD_PRESENT;
161 } 136 }
162 137
163 if (unlikely(reg == SDHCI_CAPABILITIES)) {
164 /* In FSL esdhc IC module, only bit20 is used to indicate the
165 * ADMA2 capability of esdhc, but this bit is messed up on
166 * some SOCs (e.g. on MX25, MX35 this bit is set, but they
167 * don't actually support ADMA2). So set the BROKEN_ADMA
168 * uirk on MX25/35 platforms.
169 */
170
171 if (val & SDHCI_CAN_DO_ADMA1) {
172 val &= ~SDHCI_CAN_DO_ADMA1;
173 val |= SDHCI_CAN_DO_ADMA2;
174 }
175 }
176
177 if (unlikely(reg == SDHCI_INT_STATUS)) {
178 if (val & SDHCI_INT_VENDOR_SPEC_DMA_ERR) {
179 val &= ~SDHCI_INT_VENDOR_SPEC_DMA_ERR;
180 val |= SDHCI_INT_ADMA_ERROR;
181 }
182 }
183
184 return val; 138 return val;
185} 139}
186 140
@@ -225,28 +179,13 @@ static void esdhc_writel_le(struct sdhci_host *host, u32 val, int reg)
225 writel(v, host->ioaddr + SDHCI_VENDOR_SPEC); 179 writel(v, host->ioaddr + SDHCI_VENDOR_SPEC);
226 } 180 }
227 181
228 if (unlikely(reg == SDHCI_INT_ENABLE || reg == SDHCI_SIGNAL_ENABLE)) {
229 if (val & SDHCI_INT_ADMA_ERROR) {
230 val &= ~SDHCI_INT_ADMA_ERROR;
231 val |= SDHCI_INT_VENDOR_SPEC_DMA_ERR;
232 }
233 }
234
235 writel(val, host->ioaddr + reg); 182 writel(val, host->ioaddr + reg);
236} 183}
237 184
238static u16 esdhc_readw_le(struct sdhci_host *host, int reg) 185static u16 esdhc_readw_le(struct sdhci_host *host, int reg)
239{ 186{
240 if (unlikely(reg == SDHCI_HOST_VERSION)) { 187 if (unlikely(reg == SDHCI_HOST_VERSION))
241 u16 val = readw(host->ioaddr + (reg ^ 2)); 188 reg ^= 2;
242 /*
243 * uSDHC supports SDHCI v3.0, but it's encoded as value
244 * 0x3 in host controller version register, which violates
245 * SDHCI_SPEC_300 definition. Work it around here.
246 */
247 if ((val & SDHCI_SPEC_VER_MASK) == 3)
248 return --val;
249 }
250 189
251 return readw(host->ioaddr + reg); 190 return readw(host->ioaddr + reg);
252} 191}
@@ -274,21 +213,11 @@ static void esdhc_writew_le(struct sdhci_host *host, u16 val, int reg)
274 imx_data->scratchpad = val; 213 imx_data->scratchpad = val;
275 return; 214 return;
276 case SDHCI_COMMAND: 215 case SDHCI_COMMAND:
277 if ((host->cmd->opcode == MMC_STOP_TRANSMISSION || 216 if ((host->cmd->opcode == MMC_STOP_TRANSMISSION)
278 host->cmd->opcode == MMC_SET_BLOCK_COUNT) && 217 && (imx_data->flags & ESDHC_FLAG_MULTIBLK_NO_INT))
279 (imx_data->flags & ESDHC_FLAG_MULTIBLK_NO_INT))
280 val |= SDHCI_CMD_ABORTCMD; 218 val |= SDHCI_CMD_ABORTCMD;
281 219 writel(val << 16 | imx_data->scratchpad,
282 if (is_imx6q_usdhc(imx_data)) { 220 host->ioaddr + SDHCI_TRANSFER_MODE);
283 u32 m = readl(host->ioaddr + SDHCI_MIX_CTRL);
284 m = imx_data->scratchpad | (m & 0xffff0000);
285 writel(m, host->ioaddr + SDHCI_MIX_CTRL);
286 writel(val << 16,
287 host->ioaddr + SDHCI_TRANSFER_MODE);
288 } else {
289 writel(val << 16 | imx_data->scratchpad,
290 host->ioaddr + SDHCI_TRANSFER_MODE);
291 }
292 return; 221 return;
293 case SDHCI_BLOCK_SIZE: 222 case SDHCI_BLOCK_SIZE:
294 val &= ~SDHCI_MAKE_BLKSZ(0x7, 0); 223 val &= ~SDHCI_MAKE_BLKSZ(0x7, 0);
@@ -299,8 +228,6 @@ static void esdhc_writew_le(struct sdhci_host *host, u16 val, int reg)
299 228
300static void esdhc_writeb_le(struct sdhci_host *host, u8 val, int reg) 229static void esdhc_writeb_le(struct sdhci_host *host, u8 val, int reg)
301{ 230{
302 struct sdhci_pltfm_host *pltfm_host = sdhci_priv(host);
303 struct pltfm_imx_data *imx_data = pltfm_host->priv;
304 u32 new_val; 231 u32 new_val;
305 232
306 switch (reg) { 233 switch (reg) {
@@ -315,13 +242,10 @@ static void esdhc_writeb_le(struct sdhci_host *host, u8 val, int reg)
315 new_val = val & (SDHCI_CTRL_LED | \ 242 new_val = val & (SDHCI_CTRL_LED | \
316 SDHCI_CTRL_4BITBUS | \ 243 SDHCI_CTRL_4BITBUS | \
317 SDHCI_CTRL_D3CD); 244 SDHCI_CTRL_D3CD);
318 /* ensure the endianness */ 245 /* ensure the endianess */
319 new_val |= ESDHC_HOST_CONTROL_LE; 246 new_val |= ESDHC_HOST_CONTROL_LE;
320 /* bits 8&9 are reserved on mx25 */ 247 /* DMA mode bits are shifted */
321 if (!is_imx25_esdhc(imx_data)) { 248 new_val |= (val & SDHCI_CTRL_DMA_MASK) << 5;
322 /* DMA mode bits are shifted */
323 new_val |= (val & SDHCI_CTRL_DMA_MASK) << 5;
324 }
325 249
326 esdhc_clrset_le(host, 0xffff, new_val, reg); 250 esdhc_clrset_le(host, 0xffff, new_val, reg);
327 return; 251 return;
@@ -387,10 +311,9 @@ static struct sdhci_ops sdhci_esdhc_ops = {
387}; 311};
388 312
389static struct sdhci_pltfm_data sdhci_esdhc_imx_pdata = { 313static struct sdhci_pltfm_data sdhci_esdhc_imx_pdata = {
390 .quirks = ESDHC_DEFAULT_QUIRKS | SDHCI_QUIRK_NO_HISPD_BIT 314 .quirks = ESDHC_DEFAULT_QUIRKS | SDHCI_QUIRK_BROKEN_ADMA
391 | SDHCI_QUIRK_NO_ENDATTR_IN_NOPDESC
392 | SDHCI_QUIRK_BROKEN_ADMA_ZEROLEN_DESC
393 | SDHCI_QUIRK_BROKEN_CARD_DETECTION, 315 | SDHCI_QUIRK_BROKEN_CARD_DETECTION,
316 /* ADMA has issues. Might be fixable */
394 .ops = &sdhci_esdhc_ops, 317 .ops = &sdhci_esdhc_ops,
395}; 318};
396 319
@@ -403,7 +326,7 @@ static irqreturn_t cd_irq(int irq, void *data)
403}; 326};
404 327
405#ifdef CONFIG_OF 328#ifdef CONFIG_OF
406static int 329static int __devinit
407sdhci_esdhc_imx_probe_dt(struct platform_device *pdev, 330sdhci_esdhc_imx_probe_dt(struct platform_device *pdev,
408 struct esdhc_platform_data *boarddata) 331 struct esdhc_platform_data *boarddata)
409{ 332{
@@ -412,7 +335,7 @@ sdhci_esdhc_imx_probe_dt(struct platform_device *pdev,
412 if (!np) 335 if (!np)
413 return -ENODEV; 336 return -ENODEV;
414 337
415 if (of_get_property(np, "non-removable", NULL)) 338 if (of_get_property(np, "fsl,card-wired", NULL))
416 boarddata->cd_type = ESDHC_CD_PERMANENT; 339 boarddata->cd_type = ESDHC_CD_PERMANENT;
417 340
418 if (of_get_property(np, "fsl,cd-controller", NULL)) 341 if (of_get_property(np, "fsl,cd-controller", NULL))
@@ -440,13 +363,14 @@ sdhci_esdhc_imx_probe_dt(struct platform_device *pdev,
440} 363}
441#endif 364#endif
442 365
443static int sdhci_esdhc_imx_probe(struct platform_device *pdev) 366static int __devinit sdhci_esdhc_imx_probe(struct platform_device *pdev)
444{ 367{
445 const struct of_device_id *of_id = 368 const struct of_device_id *of_id =
446 of_match_device(imx_esdhc_dt_ids, &pdev->dev); 369 of_match_device(imx_esdhc_dt_ids, &pdev->dev);
447 struct sdhci_pltfm_host *pltfm_host; 370 struct sdhci_pltfm_host *pltfm_host;
448 struct sdhci_host *host; 371 struct sdhci_host *host;
449 struct esdhc_platform_data *boarddata; 372 struct esdhc_platform_data *boarddata;
373 struct clk *clk;
450 int err; 374 int err;
451 struct pltfm_imx_data *imx_data; 375 struct pltfm_imx_data *imx_data;
452 376
@@ -456,10 +380,10 @@ static int sdhci_esdhc_imx_probe(struct platform_device *pdev)
456 380
457 pltfm_host = sdhci_priv(host); 381 pltfm_host = sdhci_priv(host);
458 382
459 imx_data = devm_kzalloc(&pdev->dev, sizeof(*imx_data), GFP_KERNEL); 383 imx_data = kzalloc(sizeof(struct pltfm_imx_data), GFP_KERNEL);
460 if (!imx_data) { 384 if (!imx_data) {
461 err = -ENOMEM; 385 err = -ENOMEM;
462 goto free_sdhci; 386 goto err_imx_data;
463 } 387 }
464 388
465 if (of_id) 389 if (of_id)
@@ -467,59 +391,31 @@ static int sdhci_esdhc_imx_probe(struct platform_device *pdev)
467 imx_data->devtype = pdev->id_entry->driver_data; 391 imx_data->devtype = pdev->id_entry->driver_data;
468 pltfm_host->priv = imx_data; 392 pltfm_host->priv = imx_data;
469 393
470 imx_data->clk_ipg = devm_clk_get(&pdev->dev, "ipg"); 394 clk = clk_get(mmc_dev(host->mmc), NULL);
471 if (IS_ERR(imx_data->clk_ipg)) { 395 if (IS_ERR(clk)) {
472 err = PTR_ERR(imx_data->clk_ipg); 396 dev_err(mmc_dev(host->mmc), "clk err\n");
473 goto free_sdhci; 397 err = PTR_ERR(clk);
474 } 398 goto err_clk_get;
475
476 imx_data->clk_ahb = devm_clk_get(&pdev->dev, "ahb");
477 if (IS_ERR(imx_data->clk_ahb)) {
478 err = PTR_ERR(imx_data->clk_ahb);
479 goto free_sdhci;
480 } 399 }
400 clk_enable(clk);
401 pltfm_host->clk = clk;
481 402
482 imx_data->clk_per = devm_clk_get(&pdev->dev, "per"); 403 if (!is_imx25_esdhc(imx_data))
483 if (IS_ERR(imx_data->clk_per)) { 404 host->quirks |= SDHCI_QUIRK_BROKEN_TIMEOUT_VAL;
484 err = PTR_ERR(imx_data->clk_per);
485 goto free_sdhci;
486 }
487
488 pltfm_host->clk = imx_data->clk_per;
489
490 clk_prepare_enable(imx_data->clk_per);
491 clk_prepare_enable(imx_data->clk_ipg);
492 clk_prepare_enable(imx_data->clk_ahb);
493
494 imx_data->pinctrl = devm_pinctrl_get_select_default(&pdev->dev);
495 if (IS_ERR(imx_data->pinctrl)) {
496 err = PTR_ERR(imx_data->pinctrl);
497 goto disable_clk;
498 }
499
500 host->quirks |= SDHCI_QUIRK_BROKEN_TIMEOUT_VAL;
501 405
502 if (is_imx25_esdhc(imx_data) || is_imx35_esdhc(imx_data)) 406 if (is_imx25_esdhc(imx_data) || is_imx35_esdhc(imx_data))
503 /* Fix errata ENGcm07207 present on i.MX25 and i.MX35 */ 407 /* Fix errata ENGcm07207 present on i.MX25 and i.MX35 */
504 host->quirks |= SDHCI_QUIRK_NO_MULTIBLOCK 408 host->quirks |= SDHCI_QUIRK_NO_MULTIBLOCK;
505 | SDHCI_QUIRK_BROKEN_ADMA;
506 409
507 if (is_imx53_esdhc(imx_data)) 410 if (is_imx53_esdhc(imx_data))
508 imx_data->flags |= ESDHC_FLAG_MULTIBLK_NO_INT; 411 imx_data->flags |= ESDHC_FLAG_MULTIBLK_NO_INT;
509 412
510 /*
511 * The imx6q ROM code will change the default watermark level setting
512 * to something insane. Change it back here.
513 */
514 if (is_imx6q_usdhc(imx_data))
515 writel(0x08100810, host->ioaddr + SDHCI_WTMK_LVL);
516
517 boarddata = &imx_data->boarddata; 413 boarddata = &imx_data->boarddata;
518 if (sdhci_esdhc_imx_probe_dt(pdev, boarddata) < 0) { 414 if (sdhci_esdhc_imx_probe_dt(pdev, boarddata) < 0) {
519 if (!host->mmc->parent->platform_data) { 415 if (!host->mmc->parent->platform_data) {
520 dev_err(mmc_dev(host->mmc), "no board data!\n"); 416 dev_err(mmc_dev(host->mmc), "no board data!\n");
521 err = -EINVAL; 417 err = -EINVAL;
522 goto disable_clk; 418 goto no_board_data;
523 } 419 }
524 imx_data->boarddata = *((struct esdhc_platform_data *) 420 imx_data->boarddata = *((struct esdhc_platform_data *)
525 host->mmc->parent->platform_data); 421 host->mmc->parent->platform_data);
@@ -527,8 +423,7 @@ static int sdhci_esdhc_imx_probe(struct platform_device *pdev)
527 423
528 /* write_protect */ 424 /* write_protect */
529 if (boarddata->wp_type == ESDHC_WP_GPIO) { 425 if (boarddata->wp_type == ESDHC_WP_GPIO) {
530 err = devm_gpio_request_one(&pdev->dev, boarddata->wp_gpio, 426 err = gpio_request_one(boarddata->wp_gpio, GPIOF_IN, "ESDHC_WP");
531 GPIOF_IN, "ESDHC_WP");
532 if (err) { 427 if (err) {
533 dev_warn(mmc_dev(host->mmc), 428 dev_warn(mmc_dev(host->mmc),
534 "no write-protect pin available!\n"); 429 "no write-protect pin available!\n");
@@ -544,21 +439,19 @@ static int sdhci_esdhc_imx_probe(struct platform_device *pdev)
544 439
545 switch (boarddata->cd_type) { 440 switch (boarddata->cd_type) {
546 case ESDHC_CD_GPIO: 441 case ESDHC_CD_GPIO:
547 err = devm_gpio_request_one(&pdev->dev, boarddata->cd_gpio, 442 err = gpio_request_one(boarddata->cd_gpio, GPIOF_IN, "ESDHC_CD");
548 GPIOF_IN, "ESDHC_CD");
549 if (err) { 443 if (err) {
550 dev_err(mmc_dev(host->mmc), 444 dev_err(mmc_dev(host->mmc),
551 "no card-detect pin available!\n"); 445 "no card-detect pin available!\n");
552 goto disable_clk; 446 goto no_card_detect_pin;
553 } 447 }
554 448
555 err = devm_request_irq(&pdev->dev, 449 err = request_irq(gpio_to_irq(boarddata->cd_gpio), cd_irq,
556 gpio_to_irq(boarddata->cd_gpio), cd_irq,
557 IRQF_TRIGGER_FALLING | IRQF_TRIGGER_RISING, 450 IRQF_TRIGGER_FALLING | IRQF_TRIGGER_RISING,
558 mmc_hostname(host->mmc), host); 451 mmc_hostname(host->mmc), host);
559 if (err) { 452 if (err) {
560 dev_err(mmc_dev(host->mmc), "request irq error\n"); 453 dev_err(mmc_dev(host->mmc), "request irq error\n");
561 goto disable_clk; 454 goto no_card_detect_irq;
562 } 455 }
563 /* fall through */ 456 /* fall through */
564 457
@@ -577,31 +470,50 @@ static int sdhci_esdhc_imx_probe(struct platform_device *pdev)
577 470
578 err = sdhci_add_host(host); 471 err = sdhci_add_host(host);
579 if (err) 472 if (err)
580 goto disable_clk; 473 goto err_add_host;
581 474
582 return 0; 475 return 0;
583 476
584disable_clk: 477err_add_host:
585 clk_disable_unprepare(imx_data->clk_per); 478 if (gpio_is_valid(boarddata->cd_gpio))
586 clk_disable_unprepare(imx_data->clk_ipg); 479 free_irq(gpio_to_irq(boarddata->cd_gpio), host);
587 clk_disable_unprepare(imx_data->clk_ahb); 480no_card_detect_irq:
588free_sdhci: 481 if (gpio_is_valid(boarddata->cd_gpio))
482 gpio_free(boarddata->cd_gpio);
483 if (gpio_is_valid(boarddata->wp_gpio))
484 gpio_free(boarddata->wp_gpio);
485no_card_detect_pin:
486no_board_data:
487 clk_disable(pltfm_host->clk);
488 clk_put(pltfm_host->clk);
489err_clk_get:
490 kfree(imx_data);
491err_imx_data:
589 sdhci_pltfm_free(pdev); 492 sdhci_pltfm_free(pdev);
590 return err; 493 return err;
591} 494}
592 495
593static int sdhci_esdhc_imx_remove(struct platform_device *pdev) 496static int __devexit sdhci_esdhc_imx_remove(struct platform_device *pdev)
594{ 497{
595 struct sdhci_host *host = platform_get_drvdata(pdev); 498 struct sdhci_host *host = platform_get_drvdata(pdev);
596 struct sdhci_pltfm_host *pltfm_host = sdhci_priv(host); 499 struct sdhci_pltfm_host *pltfm_host = sdhci_priv(host);
597 struct pltfm_imx_data *imx_data = pltfm_host->priv; 500 struct pltfm_imx_data *imx_data = pltfm_host->priv;
501 struct esdhc_platform_data *boarddata = &imx_data->boarddata;
598 int dead = (readl(host->ioaddr + SDHCI_INT_STATUS) == 0xffffffff); 502 int dead = (readl(host->ioaddr + SDHCI_INT_STATUS) == 0xffffffff);
599 503
600 sdhci_remove_host(host, dead); 504 sdhci_remove_host(host, dead);
601 505
602 clk_disable_unprepare(imx_data->clk_per); 506 if (gpio_is_valid(boarddata->wp_gpio))
603 clk_disable_unprepare(imx_data->clk_ipg); 507 gpio_free(boarddata->wp_gpio);
604 clk_disable_unprepare(imx_data->clk_ahb); 508
509 if (gpio_is_valid(boarddata->cd_gpio)) {
510 free_irq(gpio_to_irq(boarddata->cd_gpio), host);
511 gpio_free(boarddata->cd_gpio);
512 }
513
514 clk_disable(pltfm_host->clk);
515 clk_put(pltfm_host->clk);
516 kfree(imx_data);
605 517
606 sdhci_pltfm_free(pdev); 518 sdhci_pltfm_free(pdev);
607 519
@@ -613,14 +525,27 @@ static struct platform_driver sdhci_esdhc_imx_driver = {
613 .name = "sdhci-esdhc-imx", 525 .name = "sdhci-esdhc-imx",
614 .owner = THIS_MODULE, 526 .owner = THIS_MODULE,
615 .of_match_table = imx_esdhc_dt_ids, 527 .of_match_table = imx_esdhc_dt_ids,
616 .pm = SDHCI_PLTFM_PMOPS,
617 }, 528 },
618 .id_table = imx_esdhc_devtype, 529 .id_table = imx_esdhc_devtype,
619 .probe = sdhci_esdhc_imx_probe, 530 .probe = sdhci_esdhc_imx_probe,
620 .remove = sdhci_esdhc_imx_remove, 531 .remove = __devexit_p(sdhci_esdhc_imx_remove),
532#ifdef CONFIG_PM
533 .suspend = sdhci_pltfm_suspend,
534 .resume = sdhci_pltfm_resume,
535#endif
621}; 536};
622 537
623module_platform_driver(sdhci_esdhc_imx_driver); 538static int __init sdhci_esdhc_imx_init(void)
539{
540 return platform_driver_register(&sdhci_esdhc_imx_driver);
541}
542module_init(sdhci_esdhc_imx_init);
543
544static void __exit sdhci_esdhc_imx_exit(void)
545{
546 platform_driver_unregister(&sdhci_esdhc_imx_driver);
547}
548module_exit(sdhci_esdhc_imx_exit);
624 549
625MODULE_DESCRIPTION("SDHCI driver for Freescale i.MX eSDHC"); 550MODULE_DESCRIPTION("SDHCI driver for Freescale i.MX eSDHC");
626MODULE_AUTHOR("Wolfram Sang <w.sang@pengutronix.de>"); 551MODULE_AUTHOR("Wolfram Sang <w.sang@pengutronix.de>");