aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/mmc/core/core.c
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/mmc/core/core.c')
-rw-r--r--drivers/mmc/core/core.c147
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 @@
35extern int mmc_attach_mmc(struct mmc_host *host, u32 ocr); 36extern int mmc_attach_mmc(struct mmc_host *host, u32 ocr);
36extern int mmc_attach_sd(struct mmc_host *host, u32 ocr); 37extern int mmc_attach_sd(struct mmc_host *host, u32 ocr);
37 38
39static struct workqueue_struct *workqueue;
40
41/*
42 * Internal function. Schedule delayed work in the MMC work queue.
43 */
44static 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 */
53static 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 */
374struct 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)
512EXPORT_SYMBOL(mmc_detect_change); 516EXPORT_SYMBOL(mmc_detect_change);
513 517
514 518
515static void mmc_rescan(struct work_struct *work) 519void 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 568void 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 */
572struct 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
598EXPORT_SYMBOL(mmc_alloc_host);
599
600/**
601 * mmc_add_host - initialise host hardware
602 * @host: mmc host
603 */
604int 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
617EXPORT_SYMBOL(mmc_add_host); 574void 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 */
626void 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
654EXPORT_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 */
662void mmc_free_host(struct mmc_host *host)
663{
664 mmc_free_host_sysfs(host);
665}
666
667EXPORT_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
661static 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
678static void __exit mmc_exit(void)
679{
680 mmc_unregister_host_class();
681 mmc_unregister_bus();
682 destroy_workqueue(workqueue);
683}
684
685module_init(mmc_init);
686module_exit(mmc_exit);
687
729MODULE_LICENSE("GPL"); 688MODULE_LICENSE("GPL");