diff options
Diffstat (limited to 'drivers/mmc/core/core.c')
-rw-r--r-- | drivers/mmc/core/core.c | 147 |
1 files changed, 53 insertions, 94 deletions
diff --git a/drivers/mmc/core/core.c b/drivers/mmc/core/core.c index 7385acfa1dd9..b5d8a6d90cca 100644 --- a/drivers/mmc/core/core.c +++ b/drivers/mmc/core/core.c | |||
@@ -27,7 +27,8 @@ | |||
27 | #include <linux/mmc/sd.h> | 27 | #include <linux/mmc/sd.h> |
28 | 28 | ||
29 | #include "core.h" | 29 | #include "core.h" |
30 | #include "sysfs.h" | 30 | #include "bus.h" |
31 | #include "host.h" | ||
31 | 32 | ||
32 | #include "mmc_ops.h" | 33 | #include "mmc_ops.h" |
33 | #include "sd_ops.h" | 34 | #include "sd_ops.h" |
@@ -35,6 +36,25 @@ | |||
35 | extern int mmc_attach_mmc(struct mmc_host *host, u32 ocr); | 36 | extern int mmc_attach_mmc(struct mmc_host *host, u32 ocr); |
36 | extern int mmc_attach_sd(struct mmc_host *host, u32 ocr); | 37 | extern int mmc_attach_sd(struct mmc_host *host, u32 ocr); |
37 | 38 | ||
39 | static struct workqueue_struct *workqueue; | ||
40 | |||
41 | /* | ||
42 | * Internal function. Schedule delayed work in the MMC work queue. | ||
43 | */ | ||
44 | static int mmc_schedule_delayed_work(struct delayed_work *work, | ||
45 | unsigned long delay) | ||
46 | { | ||
47 | return queue_delayed_work(workqueue, work, delay); | ||
48 | } | ||
49 | |||
50 | /* | ||
51 | * Internal function. Flush all scheduled work from the MMC work queue. | ||
52 | */ | ||
53 | static void mmc_flush_scheduled_work(void) | ||
54 | { | ||
55 | flush_workqueue(workqueue); | ||
56 | } | ||
57 | |||
38 | /** | 58 | /** |
39 | * mmc_request_done - finish processing an MMC request | 59 | * mmc_request_done - finish processing an MMC request |
40 | * @host: MMC host which completed request | 60 | * @host: MMC host which completed request |
@@ -369,22 +389,6 @@ void mmc_set_timing(struct mmc_host *host, unsigned int timing) | |||
369 | } | 389 | } |
370 | 390 | ||
371 | /* | 391 | /* |
372 | * Allocate a new MMC card | ||
373 | */ | ||
374 | struct mmc_card *mmc_alloc_card(struct mmc_host *host) | ||
375 | { | ||
376 | struct mmc_card *card; | ||
377 | |||
378 | card = kmalloc(sizeof(struct mmc_card), GFP_KERNEL); | ||
379 | if (!card) | ||
380 | return ERR_PTR(-ENOMEM); | ||
381 | |||
382 | mmc_init_card(card, host); | ||
383 | |||
384 | return card; | ||
385 | } | ||
386 | |||
387 | /* | ||
388 | * Apply power to the MMC stack. This is a two-stage process. | 392 | * Apply power to the MMC stack. This is a two-stage process. |
389 | * First, we enable power to the card without the clock running. | 393 | * First, we enable power to the card without the clock running. |
390 | * We then wait a bit for the power to stabilise. Finally, | 394 | * We then wait a bit for the power to stabilise. Finally, |
@@ -512,7 +516,7 @@ void mmc_detect_change(struct mmc_host *host, unsigned long delay) | |||
512 | EXPORT_SYMBOL(mmc_detect_change); | 516 | EXPORT_SYMBOL(mmc_detect_change); |
513 | 517 | ||
514 | 518 | ||
515 | static void mmc_rescan(struct work_struct *work) | 519 | void mmc_rescan(struct work_struct *work) |
516 | { | 520 | { |
517 | struct mmc_host *host = | 521 | struct mmc_host *host = |
518 | container_of(work, struct mmc_host, detect.work); | 522 | container_of(work, struct mmc_host, detect.work); |
@@ -561,69 +565,13 @@ static void mmc_rescan(struct work_struct *work) | |||
561 | } | 565 | } |
562 | } | 566 | } |
563 | 567 | ||
564 | 568 | void mmc_start_host(struct mmc_host *host) | |
565 | /** | ||
566 | * mmc_alloc_host - initialise the per-host structure. | ||
567 | * @extra: sizeof private data structure | ||
568 | * @dev: pointer to host device model structure | ||
569 | * | ||
570 | * Initialise the per-host structure. | ||
571 | */ | ||
572 | struct mmc_host *mmc_alloc_host(int extra, struct device *dev) | ||
573 | { | 569 | { |
574 | struct mmc_host *host; | 570 | mmc_power_off(host); |
575 | 571 | mmc_detect_change(host, 0); | |
576 | host = mmc_alloc_host_sysfs(extra, dev); | ||
577 | if (host) { | ||
578 | spin_lock_init(&host->lock); | ||
579 | init_waitqueue_head(&host->wq); | ||
580 | INIT_DELAYED_WORK(&host->detect, mmc_rescan); | ||
581 | |||
582 | /* | ||
583 | * By default, hosts do not support SGIO or large requests. | ||
584 | * They have to set these according to their abilities. | ||
585 | */ | ||
586 | host->max_hw_segs = 1; | ||
587 | host->max_phys_segs = 1; | ||
588 | host->max_seg_size = PAGE_CACHE_SIZE; | ||
589 | |||
590 | host->max_req_size = PAGE_CACHE_SIZE; | ||
591 | host->max_blk_size = 512; | ||
592 | host->max_blk_count = PAGE_CACHE_SIZE / 512; | ||
593 | } | ||
594 | |||
595 | return host; | ||
596 | } | ||
597 | |||
598 | EXPORT_SYMBOL(mmc_alloc_host); | ||
599 | |||
600 | /** | ||
601 | * mmc_add_host - initialise host hardware | ||
602 | * @host: mmc host | ||
603 | */ | ||
604 | int mmc_add_host(struct mmc_host *host) | ||
605 | { | ||
606 | int ret; | ||
607 | |||
608 | ret = mmc_add_host_sysfs(host); | ||
609 | if (ret == 0) { | ||
610 | mmc_power_off(host); | ||
611 | mmc_detect_change(host, 0); | ||
612 | } | ||
613 | |||
614 | return ret; | ||
615 | } | 572 | } |
616 | 573 | ||
617 | EXPORT_SYMBOL(mmc_add_host); | 574 | void mmc_stop_host(struct mmc_host *host) |
618 | |||
619 | /** | ||
620 | * mmc_remove_host - remove host hardware | ||
621 | * @host: mmc host | ||
622 | * | ||
623 | * Unregister and remove all cards associated with this host, | ||
624 | * and power down the MMC bus. | ||
625 | */ | ||
626 | void mmc_remove_host(struct mmc_host *host) | ||
627 | { | 575 | { |
628 | #ifdef CONFIG_MMC_DEBUG | 576 | #ifdef CONFIG_MMC_DEBUG |
629 | unsigned long flags; | 577 | unsigned long flags; |
@@ -648,24 +596,8 @@ void mmc_remove_host(struct mmc_host *host) | |||
648 | BUG_ON(host->card); | 596 | BUG_ON(host->card); |
649 | 597 | ||
650 | mmc_power_off(host); | 598 | mmc_power_off(host); |
651 | mmc_remove_host_sysfs(host); | ||
652 | } | 599 | } |
653 | 600 | ||
654 | EXPORT_SYMBOL(mmc_remove_host); | ||
655 | |||
656 | /** | ||
657 | * mmc_free_host - free the host structure | ||
658 | * @host: mmc host | ||
659 | * | ||
660 | * Free the host once all references to it have been dropped. | ||
661 | */ | ||
662 | void mmc_free_host(struct mmc_host *host) | ||
663 | { | ||
664 | mmc_free_host_sysfs(host); | ||
665 | } | ||
666 | |||
667 | EXPORT_SYMBOL(mmc_free_host); | ||
668 | |||
669 | #ifdef CONFIG_PM | 601 | #ifdef CONFIG_PM |
670 | 602 | ||
671 | /** | 603 | /** |
@@ -726,4 +658,31 @@ EXPORT_SYMBOL(mmc_resume_host); | |||
726 | 658 | ||
727 | #endif | 659 | #endif |
728 | 660 | ||
661 | static int __init mmc_init(void) | ||
662 | { | ||
663 | int ret; | ||
664 | |||
665 | workqueue = create_singlethread_workqueue("kmmcd"); | ||
666 | if (!workqueue) | ||
667 | return -ENOMEM; | ||
668 | |||
669 | ret = mmc_register_bus(); | ||
670 | if (ret == 0) { | ||
671 | ret = mmc_register_host_class(); | ||
672 | if (ret) | ||
673 | mmc_unregister_bus(); | ||
674 | } | ||
675 | return ret; | ||
676 | } | ||
677 | |||
678 | static void __exit mmc_exit(void) | ||
679 | { | ||
680 | mmc_unregister_host_class(); | ||
681 | mmc_unregister_bus(); | ||
682 | destroy_workqueue(workqueue); | ||
683 | } | ||
684 | |||
685 | module_init(mmc_init); | ||
686 | module_exit(mmc_exit); | ||
687 | |||
729 | MODULE_LICENSE("GPL"); | 688 | MODULE_LICENSE("GPL"); |