diff options
Diffstat (limited to 'drivers/mmc')
-rw-r--r-- | drivers/mmc/host/sh_mmcif.c | 117 |
1 files changed, 46 insertions, 71 deletions
diff --git a/drivers/mmc/host/sh_mmcif.c b/drivers/mmc/host/sh_mmcif.c index 3f492730ec05..74e7aca271d4 100644 --- a/drivers/mmc/host/sh_mmcif.c +++ b/drivers/mmc/host/sh_mmcif.c | |||
@@ -16,6 +16,8 @@ | |||
16 | * | 16 | * |
17 | */ | 17 | */ |
18 | 18 | ||
19 | #include <linux/clk.h> | ||
20 | #include <linux/completion.h> | ||
19 | #include <linux/dma-mapping.h> | 21 | #include <linux/dma-mapping.h> |
20 | #include <linux/mmc/host.h> | 22 | #include <linux/mmc/host.h> |
21 | #include <linux/mmc/card.h> | 23 | #include <linux/mmc/card.h> |
@@ -24,7 +26,6 @@ | |||
24 | #include <linux/mmc/sdio.h> | 26 | #include <linux/mmc/sdio.h> |
25 | #include <linux/delay.h> | 27 | #include <linux/delay.h> |
26 | #include <linux/platform_device.h> | 28 | #include <linux/platform_device.h> |
27 | #include <linux/clk.h> | ||
28 | #include <linux/mmc/sh_mmcif.h> | 29 | #include <linux/mmc/sh_mmcif.h> |
29 | 30 | ||
30 | #define DRIVER_NAME "sh_mmcif" | 31 | #define DRIVER_NAME "sh_mmcif" |
@@ -158,11 +159,10 @@ struct sh_mmcif_host { | |||
158 | struct clk *hclk; | 159 | struct clk *hclk; |
159 | unsigned int clk; | 160 | unsigned int clk; |
160 | int bus_width; | 161 | int bus_width; |
161 | u16 wait_int; | 162 | bool sd_error; |
162 | u16 sd_error; | ||
163 | long timeout; | 163 | long timeout; |
164 | void __iomem *addr; | 164 | void __iomem *addr; |
165 | wait_queue_head_t intr_wait; | 165 | struct completion intr_wait; |
166 | }; | 166 | }; |
167 | 167 | ||
168 | 168 | ||
@@ -216,8 +216,7 @@ static int sh_mmcif_error_manage(struct sh_mmcif_host *host) | |||
216 | u32 state1, state2; | 216 | u32 state1, state2; |
217 | int ret, timeout = 10000000; | 217 | int ret, timeout = 10000000; |
218 | 218 | ||
219 | host->sd_error = 0; | 219 | host->sd_error = false; |
220 | host->wait_int = 0; | ||
221 | 220 | ||
222 | state1 = sh_mmcif_readl(host->addr, MMCIF_CE_HOST_STS1); | 221 | state1 = sh_mmcif_readl(host->addr, MMCIF_CE_HOST_STS1); |
223 | state2 = sh_mmcif_readl(host->addr, MMCIF_CE_HOST_STS2); | 222 | state2 = sh_mmcif_readl(host->addr, MMCIF_CE_HOST_STS2); |
@@ -264,17 +263,13 @@ static int sh_mmcif_single_read(struct sh_mmcif_host *host, | |||
264 | long time; | 263 | long time; |
265 | u32 blocksize, i, *p = sg_virt(data->sg); | 264 | u32 blocksize, i, *p = sg_virt(data->sg); |
266 | 265 | ||
267 | host->wait_int = 0; | ||
268 | |||
269 | /* buf read enable */ | 266 | /* buf read enable */ |
270 | sh_mmcif_bitset(host, MMCIF_CE_INT_MASK, MASK_MBUFREN); | 267 | sh_mmcif_bitset(host, MMCIF_CE_INT_MASK, MASK_MBUFREN); |
271 | time = wait_event_interruptible_timeout(host->intr_wait, | 268 | time = wait_for_completion_interruptible_timeout(&host->intr_wait, |
272 | host->wait_int == 1 || | 269 | host->timeout); |
273 | host->sd_error == 1, host->timeout); | 270 | if (time <= 0 || host->sd_error) |
274 | if (host->wait_int != 1 && (time == 0 || host->sd_error != 0)) | ||
275 | return sh_mmcif_error_manage(host); | 271 | return sh_mmcif_error_manage(host); |
276 | 272 | ||
277 | host->wait_int = 0; | ||
278 | blocksize = (BLOCK_SIZE_MASK & | 273 | blocksize = (BLOCK_SIZE_MASK & |
279 | sh_mmcif_readl(host->addr, MMCIF_CE_BLOCK_SET)) + 3; | 274 | sh_mmcif_readl(host->addr, MMCIF_CE_BLOCK_SET)) + 3; |
280 | for (i = 0; i < blocksize / 4; i++) | 275 | for (i = 0; i < blocksize / 4; i++) |
@@ -282,13 +277,11 @@ static int sh_mmcif_single_read(struct sh_mmcif_host *host, | |||
282 | 277 | ||
283 | /* buffer read end */ | 278 | /* buffer read end */ |
284 | sh_mmcif_bitset(host, MMCIF_CE_INT_MASK, MASK_MBUFRE); | 279 | sh_mmcif_bitset(host, MMCIF_CE_INT_MASK, MASK_MBUFRE); |
285 | time = wait_event_interruptible_timeout(host->intr_wait, | 280 | time = wait_for_completion_interruptible_timeout(&host->intr_wait, |
286 | host->wait_int == 1 || | 281 | host->timeout); |
287 | host->sd_error == 1, host->timeout); | 282 | if (time <= 0 || host->sd_error) |
288 | if (host->wait_int != 1 && (time == 0 || host->sd_error != 0)) | ||
289 | return sh_mmcif_error_manage(host); | 283 | return sh_mmcif_error_manage(host); |
290 | 284 | ||
291 | host->wait_int = 0; | ||
292 | return 0; | 285 | return 0; |
293 | } | 286 | } |
294 | 287 | ||
@@ -303,19 +296,15 @@ static int sh_mmcif_multi_read(struct sh_mmcif_host *host, | |||
303 | MMCIF_CE_BLOCK_SET); | 296 | MMCIF_CE_BLOCK_SET); |
304 | for (j = 0; j < data->sg_len; j++) { | 297 | for (j = 0; j < data->sg_len; j++) { |
305 | p = sg_virt(data->sg); | 298 | p = sg_virt(data->sg); |
306 | host->wait_int = 0; | ||
307 | for (sec = 0; sec < data->sg->length / blocksize; sec++) { | 299 | for (sec = 0; sec < data->sg->length / blocksize; sec++) { |
308 | sh_mmcif_bitset(host, MMCIF_CE_INT_MASK, MASK_MBUFREN); | 300 | sh_mmcif_bitset(host, MMCIF_CE_INT_MASK, MASK_MBUFREN); |
309 | /* buf read enable */ | 301 | /* buf read enable */ |
310 | time = wait_event_interruptible_timeout(host->intr_wait, | 302 | time = wait_for_completion_interruptible_timeout(&host->intr_wait, |
311 | host->wait_int == 1 || | 303 | host->timeout); |
312 | host->sd_error == 1, host->timeout); | ||
313 | 304 | ||
314 | if (host->wait_int != 1 && | 305 | if (time <= 0 || host->sd_error) |
315 | (time == 0 || host->sd_error != 0)) | ||
316 | return sh_mmcif_error_manage(host); | 306 | return sh_mmcif_error_manage(host); |
317 | 307 | ||
318 | host->wait_int = 0; | ||
319 | for (i = 0; i < blocksize / 4; i++) | 308 | for (i = 0; i < blocksize / 4; i++) |
320 | *p++ = sh_mmcif_readl(host->addr, | 309 | *p++ = sh_mmcif_readl(host->addr, |
321 | MMCIF_CE_DATA); | 310 | MMCIF_CE_DATA); |
@@ -333,17 +322,14 @@ static int sh_mmcif_single_write(struct sh_mmcif_host *host, | |||
333 | long time; | 322 | long time; |
334 | u32 blocksize, i, *p = sg_virt(data->sg); | 323 | u32 blocksize, i, *p = sg_virt(data->sg); |
335 | 324 | ||
336 | host->wait_int = 0; | ||
337 | sh_mmcif_bitset(host, MMCIF_CE_INT_MASK, MASK_MBUFWEN); | 325 | sh_mmcif_bitset(host, MMCIF_CE_INT_MASK, MASK_MBUFWEN); |
338 | 326 | ||
339 | /* buf write enable */ | 327 | /* buf write enable */ |
340 | time = wait_event_interruptible_timeout(host->intr_wait, | 328 | time = wait_for_completion_interruptible_timeout(&host->intr_wait, |
341 | host->wait_int == 1 || | 329 | host->timeout); |
342 | host->sd_error == 1, host->timeout); | 330 | if (time <= 0 || host->sd_error) |
343 | if (host->wait_int != 1 && (time == 0 || host->sd_error != 0)) | ||
344 | return sh_mmcif_error_manage(host); | 331 | return sh_mmcif_error_manage(host); |
345 | 332 | ||
346 | host->wait_int = 0; | ||
347 | blocksize = (BLOCK_SIZE_MASK & | 333 | blocksize = (BLOCK_SIZE_MASK & |
348 | sh_mmcif_readl(host->addr, MMCIF_CE_BLOCK_SET)) + 3; | 334 | sh_mmcif_readl(host->addr, MMCIF_CE_BLOCK_SET)) + 3; |
349 | for (i = 0; i < blocksize / 4; i++) | 335 | for (i = 0; i < blocksize / 4; i++) |
@@ -352,13 +338,11 @@ static int sh_mmcif_single_write(struct sh_mmcif_host *host, | |||
352 | /* buffer write end */ | 338 | /* buffer write end */ |
353 | sh_mmcif_bitset(host, MMCIF_CE_INT_MASK, MASK_MDTRANE); | 339 | sh_mmcif_bitset(host, MMCIF_CE_INT_MASK, MASK_MDTRANE); |
354 | 340 | ||
355 | time = wait_event_interruptible_timeout(host->intr_wait, | 341 | time = wait_for_completion_interruptible_timeout(&host->intr_wait, |
356 | host->wait_int == 1 || | 342 | host->timeout); |
357 | host->sd_error == 1, host->timeout); | 343 | if (time <= 0 || host->sd_error) |
358 | if (host->wait_int != 1 && (time == 0 || host->sd_error != 0)) | ||
359 | return sh_mmcif_error_manage(host); | 344 | return sh_mmcif_error_manage(host); |
360 | 345 | ||
361 | host->wait_int = 0; | ||
362 | return 0; | 346 | return 0; |
363 | } | 347 | } |
364 | 348 | ||
@@ -374,19 +358,15 @@ static int sh_mmcif_multi_write(struct sh_mmcif_host *host, | |||
374 | 358 | ||
375 | for (j = 0; j < data->sg_len; j++) { | 359 | for (j = 0; j < data->sg_len; j++) { |
376 | p = sg_virt(data->sg); | 360 | p = sg_virt(data->sg); |
377 | host->wait_int = 0; | ||
378 | for (sec = 0; sec < data->sg->length / blocksize; sec++) { | 361 | for (sec = 0; sec < data->sg->length / blocksize; sec++) { |
379 | sh_mmcif_bitset(host, MMCIF_CE_INT_MASK, MASK_MBUFWEN); | 362 | sh_mmcif_bitset(host, MMCIF_CE_INT_MASK, MASK_MBUFWEN); |
380 | /* buf write enable*/ | 363 | /* buf write enable*/ |
381 | time = wait_event_interruptible_timeout(host->intr_wait, | 364 | time = wait_for_completion_interruptible_timeout(&host->intr_wait, |
382 | host->wait_int == 1 || | 365 | host->timeout); |
383 | host->sd_error == 1, host->timeout); | ||
384 | 366 | ||
385 | if (host->wait_int != 1 && | 367 | if (time <= 0 || host->sd_error) |
386 | (time == 0 || host->sd_error != 0)) | ||
387 | return sh_mmcif_error_manage(host); | 368 | return sh_mmcif_error_manage(host); |
388 | 369 | ||
389 | host->wait_int = 0; | ||
390 | for (i = 0; i < blocksize / 4; i++) | 370 | for (i = 0; i < blocksize / 4; i++) |
391 | sh_mmcif_writel(host->addr, | 371 | sh_mmcif_writel(host->addr, |
392 | MMCIF_CE_DATA, *p++); | 372 | MMCIF_CE_DATA, *p++); |
@@ -556,13 +536,12 @@ static void sh_mmcif_start_cmd(struct sh_mmcif_host *host, | |||
556 | sh_mmcif_writel(host->addr, MMCIF_CE_INT_MASK, mask); | 536 | sh_mmcif_writel(host->addr, MMCIF_CE_INT_MASK, mask); |
557 | /* set arg */ | 537 | /* set arg */ |
558 | sh_mmcif_writel(host->addr, MMCIF_CE_ARG, cmd->arg); | 538 | sh_mmcif_writel(host->addr, MMCIF_CE_ARG, cmd->arg); |
559 | host->wait_int = 0; | ||
560 | /* set cmd */ | 539 | /* set cmd */ |
561 | sh_mmcif_writel(host->addr, MMCIF_CE_CMD_SET, opc); | 540 | sh_mmcif_writel(host->addr, MMCIF_CE_CMD_SET, opc); |
562 | 541 | ||
563 | time = wait_event_interruptible_timeout(host->intr_wait, | 542 | time = wait_for_completion_interruptible_timeout(&host->intr_wait, |
564 | host->wait_int == 1 || host->sd_error == 1, host->timeout); | 543 | host->timeout); |
565 | if (host->wait_int != 1 && time == 0) { | 544 | if (time <= 0) { |
566 | cmd->error = sh_mmcif_error_manage(host); | 545 | cmd->error = sh_mmcif_error_manage(host); |
567 | return; | 546 | return; |
568 | } | 547 | } |
@@ -579,19 +558,14 @@ static void sh_mmcif_start_cmd(struct sh_mmcif_host *host, | |||
579 | cmd->error = sh_mmcif_error_manage(host); | 558 | cmd->error = sh_mmcif_error_manage(host); |
580 | break; | 559 | break; |
581 | } | 560 | } |
582 | host->sd_error = 0; | 561 | host->sd_error = false; |
583 | host->wait_int = 0; | ||
584 | return; | 562 | return; |
585 | } | 563 | } |
586 | if (!(cmd->flags & MMC_RSP_PRESENT)) { | 564 | if (!(cmd->flags & MMC_RSP_PRESENT)) { |
587 | cmd->error = ret; | 565 | cmd->error = ret; |
588 | host->wait_int = 0; | ||
589 | return; | 566 | return; |
590 | } | 567 | } |
591 | if (host->wait_int == 1) { | 568 | sh_mmcif_get_response(host, cmd); |
592 | sh_mmcif_get_response(host, cmd); | ||
593 | host->wait_int = 0; | ||
594 | } | ||
595 | if (host->data) { | 569 | if (host->data) { |
596 | ret = sh_mmcif_data_trans(host, mrq, cmd->opcode); | 570 | ret = sh_mmcif_data_trans(host, mrq, cmd->opcode); |
597 | if (ret < 0) | 571 | if (ret < 0) |
@@ -618,15 +592,13 @@ static void sh_mmcif_stop_cmd(struct sh_mmcif_host *host, | |||
618 | return; | 592 | return; |
619 | } | 593 | } |
620 | 594 | ||
621 | time = wait_event_interruptible_timeout(host->intr_wait, | 595 | time = wait_for_completion_interruptible_timeout(&host->intr_wait, |
622 | host->wait_int == 1 || | 596 | host->timeout); |
623 | host->sd_error == 1, host->timeout); | 597 | if (time <= 0 || host->sd_error) { |
624 | if (host->wait_int != 1 && (time == 0 || host->sd_error != 0)) { | ||
625 | cmd->error = sh_mmcif_error_manage(host); | 598 | cmd->error = sh_mmcif_error_manage(host); |
626 | return; | 599 | return; |
627 | } | 600 | } |
628 | sh_mmcif_get_cmd12response(host, cmd); | 601 | sh_mmcif_get_cmd12response(host, cmd); |
629 | host->wait_int = 0; | ||
630 | cmd->error = 0; | 602 | cmd->error = 0; |
631 | } | 603 | } |
632 | 604 | ||
@@ -712,7 +684,7 @@ static void sh_mmcif_detect(struct mmc_host *mmc) | |||
712 | static irqreturn_t sh_mmcif_intr(int irq, void *dev_id) | 684 | static irqreturn_t sh_mmcif_intr(int irq, void *dev_id) |
713 | { | 685 | { |
714 | struct sh_mmcif_host *host = dev_id; | 686 | struct sh_mmcif_host *host = dev_id; |
715 | u32 state = 0; | 687 | u32 state; |
716 | int err = 0; | 688 | int err = 0; |
717 | 689 | ||
718 | state = sh_mmcif_readl(host->addr, MMCIF_CE_INT); | 690 | state = sh_mmcif_readl(host->addr, MMCIF_CE_INT); |
@@ -757,11 +729,13 @@ static irqreturn_t sh_mmcif_intr(int irq, void *dev_id) | |||
757 | err = 1; | 729 | err = 1; |
758 | } | 730 | } |
759 | if (err) { | 731 | if (err) { |
760 | host->sd_error = 1; | 732 | host->sd_error = true; |
761 | pr_debug("%s: int err state = %08x\n", DRIVER_NAME, state); | 733 | pr_debug("%s: int err state = %08x\n", DRIVER_NAME, state); |
762 | } | 734 | } |
763 | host->wait_int = 1; | 735 | if (state & ~(INT_CMD12RBE | INT_CMD12CRE)) |
764 | wake_up(&host->intr_wait); | 736 | complete(&host->intr_wait); |
737 | else | ||
738 | dev_dbg(&host->pd->dev, "Unexpected IRQ 0x%x\n", state); | ||
765 | 739 | ||
766 | return IRQ_HANDLED; | 740 | return IRQ_HANDLED; |
767 | } | 741 | } |
@@ -819,7 +793,7 @@ static int __devinit sh_mmcif_probe(struct platform_device *pdev) | |||
819 | host->clk = clk_get_rate(host->hclk); | 793 | host->clk = clk_get_rate(host->hclk); |
820 | host->pd = pdev; | 794 | host->pd = pdev; |
821 | 795 | ||
822 | init_waitqueue_head(&host->intr_wait); | 796 | init_completion(&host->intr_wait); |
823 | 797 | ||
824 | mmc->ops = &sh_mmcif_ops; | 798 | mmc->ops = &sh_mmcif_ops; |
825 | mmc->f_max = host->clk; | 799 | mmc->f_max = host->clk; |
@@ -880,20 +854,21 @@ static int __devexit sh_mmcif_remove(struct platform_device *pdev) | |||
880 | struct sh_mmcif_host *host = platform_get_drvdata(pdev); | 854 | struct sh_mmcif_host *host = platform_get_drvdata(pdev); |
881 | int irq[2]; | 855 | int irq[2]; |
882 | 856 | ||
883 | sh_mmcif_writel(host->addr, MMCIF_CE_INT_MASK, MASK_ALL); | 857 | mmc_remove_host(host->mmc); |
884 | |||
885 | irq[0] = platform_get_irq(pdev, 0); | ||
886 | irq[1] = platform_get_irq(pdev, 1); | ||
887 | 858 | ||
888 | if (host->addr) | 859 | if (host->addr) |
889 | iounmap(host->addr); | 860 | iounmap(host->addr); |
890 | 861 | ||
891 | platform_set_drvdata(pdev, NULL); | 862 | sh_mmcif_writel(host->addr, MMCIF_CE_INT_MASK, MASK_ALL); |
892 | mmc_remove_host(host->mmc); | 863 | |
864 | irq[0] = platform_get_irq(pdev, 0); | ||
865 | irq[1] = platform_get_irq(pdev, 1); | ||
893 | 866 | ||
894 | free_irq(irq[0], host); | 867 | free_irq(irq[0], host); |
895 | free_irq(irq[1], host); | 868 | free_irq(irq[1], host); |
896 | 869 | ||
870 | platform_set_drvdata(pdev, NULL); | ||
871 | |||
897 | clk_disable(host->hclk); | 872 | clk_disable(host->hclk); |
898 | mmc_free_host(host->mmc); | 873 | mmc_free_host(host->mmc); |
899 | 874 | ||
@@ -924,5 +899,5 @@ module_exit(sh_mmcif_exit); | |||
924 | 899 | ||
925 | MODULE_DESCRIPTION("SuperH on-chip MMC/eMMC interface driver"); | 900 | MODULE_DESCRIPTION("SuperH on-chip MMC/eMMC interface driver"); |
926 | MODULE_LICENSE("GPL"); | 901 | MODULE_LICENSE("GPL"); |
927 | MODULE_ALIAS(DRIVER_NAME); | 902 | MODULE_ALIAS("platform:" DRIVER_NAME); |
928 | MODULE_AUTHOR("Yusuke Goda <yusuke.goda.sx@renesas.com>"); | 903 | MODULE_AUTHOR("Yusuke Goda <yusuke.goda.sx@renesas.com>"); |