aboutsummaryrefslogtreecommitdiffstats
path: root/drivers
diff options
context:
space:
mode:
authorAlex Dubov <oakad@yahoo.com>2006-12-08 00:50:51 -0500
committerPierre Ossman <drzeus@drzeus.cx>2007-02-04 14:54:07 -0500
commit8e02f8581cd2f9c12a03be7641d5c2c427170feb (patch)
treeeef042716811ef6dcb15be51352a2405a6cc4a96 /drivers
parent83d420ba92bdd52127e4548ae8050a48f655ce3b (diff)
tifm_sd: restructure initialization, removal and command handling
In order to support correct suspend and resume several changes were needed: 1. Switch from work_struct to tasklet for command handling. When device suspend is called workqueues are already frozen and can not be used. 2. Separate host initialization code from driver's probe and don't rely on interrupts for host initialization. This, in turn, addresses two problems: a) Resume needs to re-initialize the host, but can not assume that device interrupts were already re-armed. b) Previously, probe will return successfully before really knowing the state of the host, as host interrupts were not armed in time. Now it uses polling to determine the real host state before returning. 3. Separate termination code from driver's remove. Termination may be caused by resume, if media changed type or became unavailable during suspend. Signed-off-by: Alex Dubov <oakad@yahoo.com> Signed-off-by: Pierre Ossman <drzeus@drzeus.cx>
Diffstat (limited to 'drivers')
-rw-r--r--drivers/misc/tifm_7xx1.c3
-rw-r--r--drivers/misc/tifm_core.c11
-rw-r--r--drivers/mmc/tifm_sd.c205
3 files changed, 114 insertions, 105 deletions
diff --git a/drivers/misc/tifm_7xx1.c b/drivers/misc/tifm_7xx1.c
index 2ab7add78f94..50c4cdabb654 100644
--- a/drivers/misc/tifm_7xx1.c
+++ b/drivers/misc/tifm_7xx1.c
@@ -201,11 +201,12 @@ static void tifm_7xx1_insert_media(struct work_struct *work)
201 fm->max_sockets == 2); 201 fm->max_sockets == 2);
202 if (media_id) { 202 if (media_id) {
203 ok_to_register = 0; 203 ok_to_register = 0;
204 new_sock = tifm_alloc_device(fm, cnt); 204 new_sock = tifm_alloc_device(fm);
205 if (new_sock) { 205 if (new_sock) {
206 new_sock->addr = tifm_7xx1_sock_addr(fm->addr, 206 new_sock->addr = tifm_7xx1_sock_addr(fm->addr,
207 cnt); 207 cnt);
208 new_sock->media_id = media_id; 208 new_sock->media_id = media_id;
209 new_sock->socket_id = cnt;
209 switch (media_id) { 210 switch (media_id) {
210 case 1: 211 case 1:
211 card_name = "xd"; 212 card_name = "xd";
diff --git a/drivers/misc/tifm_core.c b/drivers/misc/tifm_core.c
index d61df5c3ac36..21eb0ab7c329 100644
--- a/drivers/misc/tifm_core.c
+++ b/drivers/misc/tifm_core.c
@@ -141,24 +141,17 @@ EXPORT_SYMBOL(tifm_remove_adapter);
141void tifm_free_device(struct device *dev) 141void tifm_free_device(struct device *dev)
142{ 142{
143 struct tifm_dev *fm_dev = container_of(dev, struct tifm_dev, dev); 143 struct tifm_dev *fm_dev = container_of(dev, struct tifm_dev, dev);
144 if (fm_dev->wq)
145 destroy_workqueue(fm_dev->wq);
146 kfree(fm_dev); 144 kfree(fm_dev);
147} 145}
148EXPORT_SYMBOL(tifm_free_device); 146EXPORT_SYMBOL(tifm_free_device);
149 147
150struct tifm_dev *tifm_alloc_device(struct tifm_adapter *fm, unsigned int id) 148struct tifm_dev *tifm_alloc_device(struct tifm_adapter *fm)
151{ 149{
152 struct tifm_dev *dev = kzalloc(sizeof(struct tifm_dev), GFP_KERNEL); 150 struct tifm_dev *dev = kzalloc(sizeof(struct tifm_dev), GFP_KERNEL);
153 151
154 if (dev) { 152 if (dev) {
155 spin_lock_init(&dev->lock); 153 spin_lock_init(&dev->lock);
156 snprintf(dev->wq_name, KOBJ_NAME_LEN, "tifm%u:%u", fm->id, id); 154
157 dev->wq = create_singlethread_workqueue(dev->wq_name);
158 if (!dev->wq) {
159 kfree(dev);
160 return NULL;
161 }
162 dev->dev.parent = fm->dev; 155 dev->dev.parent = fm->dev;
163 dev->dev.bus = &tifm_bus_type; 156 dev->dev.bus = &tifm_bus_type;
164 dev->dev.release = tifm_free_device; 157 dev->dev.release = tifm_free_device;
diff --git a/drivers/mmc/tifm_sd.c b/drivers/mmc/tifm_sd.c
index 5817a138a1e4..85a5974318b4 100644
--- a/drivers/mmc/tifm_sd.c
+++ b/drivers/mmc/tifm_sd.c
@@ -79,7 +79,6 @@ typedef enum {
79 79
80enum { 80enum {
81 FIFO_RDY = 0x0001, /* hardware dependent value */ 81 FIFO_RDY = 0x0001, /* hardware dependent value */
82 HOST_REG = 0x0002,
83 EJECT = 0x0004, 82 EJECT = 0x0004,
84 EJECT_DONE = 0x0008, 83 EJECT_DONE = 0x0008,
85 CARD_BUSY = 0x0010, 84 CARD_BUSY = 0x0010,
@@ -97,10 +96,10 @@ struct tifm_sd {
97 unsigned int clk_div; 96 unsigned int clk_div;
98 unsigned long timeout_jiffies; 97 unsigned long timeout_jiffies;
99 98
99 struct tasklet_struct finish_tasklet;
100 struct timer_list timer; 100 struct timer_list timer;
101 struct mmc_request *req; 101 struct mmc_request *req;
102 struct work_struct cmd_handler; 102 wait_queue_head_t notify;
103 wait_queue_head_t can_eject;
104 103
105 size_t written_blocks; 104 size_t written_blocks;
106 size_t buffer_size; 105 size_t buffer_size;
@@ -317,7 +316,7 @@ change_state:
317 } 316 }
318 break; 317 break;
319 case READY: 318 case READY:
320 queue_work(sock->wq, &host->cmd_handler); 319 tasklet_schedule(&host->finish_tasklet);
321 return; 320 return;
322 } 321 }
323 322
@@ -345,8 +344,6 @@ static unsigned int tifm_sd_signal_irq(struct tifm_dev *sock,
345 host_status = readl(sock->addr + SOCK_MMCSD_STATUS); 344 host_status = readl(sock->addr + SOCK_MMCSD_STATUS);
346 writel(host_status, sock->addr + SOCK_MMCSD_STATUS); 345 writel(host_status, sock->addr + SOCK_MMCSD_STATUS);
347 346
348 if (!(host->flags & HOST_REG))
349 queue_work(sock->wq, &host->cmd_handler);
350 if (!host->req) 347 if (!host->req)
351 goto done; 348 goto done;
352 349
@@ -517,9 +514,9 @@ err_out:
517 mmc_request_done(mmc, mrq); 514 mmc_request_done(mmc, mrq);
518} 515}
519 516
520static void tifm_sd_end_cmd(struct work_struct *work) 517static void tifm_sd_end_cmd(unsigned long data)
521{ 518{
522 struct tifm_sd *host = container_of(work, struct tifm_sd, cmd_handler); 519 struct tifm_sd *host = (struct tifm_sd*)data;
523 struct tifm_dev *sock = host->dev; 520 struct tifm_dev *sock = host->dev;
524 struct mmc_host *mmc = tifm_get_drvdata(sock); 521 struct mmc_host *mmc = tifm_get_drvdata(sock);
525 struct mmc_request *mrq; 522 struct mmc_request *mrq;
@@ -616,9 +613,9 @@ err_out:
616 mmc_request_done(mmc, mrq); 613 mmc_request_done(mmc, mrq);
617} 614}
618 615
619static void tifm_sd_end_cmd_nodma(struct work_struct *work) 616static void tifm_sd_end_cmd_nodma(unsigned long data)
620{ 617{
621 struct tifm_sd *host = container_of(work, struct tifm_sd, cmd_handler); 618 struct tifm_sd *host = (struct tifm_sd*)data;
622 struct tifm_dev *sock = host->dev; 619 struct tifm_dev *sock = host->dev;
623 struct mmc_host *mmc = tifm_get_drvdata(sock); 620 struct mmc_host *mmc = tifm_get_drvdata(sock);
624 struct mmc_request *mrq; 621 struct mmc_request *mrq;
@@ -666,11 +663,33 @@ static void tifm_sd_end_cmd_nodma(struct work_struct *work)
666 mmc_request_done(mmc, mrq); 663 mmc_request_done(mmc, mrq);
667} 664}
668 665
666static void tifm_sd_terminate(struct tifm_sd *host)
667{
668 struct tifm_dev *sock = host->dev;
669 unsigned long flags;
670
671 writel(0, sock->addr + SOCK_MMCSD_INT_ENABLE);
672 mmiowb();
673 spin_lock_irqsave(&sock->lock, flags);
674 host->flags |= EJECT;
675 if (host->req) {
676 writel(TIFM_FIFO_INT_SETALL,
677 sock->addr + SOCK_DMA_FIFO_INT_ENABLE_CLEAR);
678 writel(0, sock->addr + SOCK_DMA_FIFO_INT_ENABLE_SET);
679 tasklet_schedule(&host->finish_tasklet);
680 }
681 spin_unlock_irqrestore(&sock->lock, flags);
682}
683
669static void tifm_sd_abort(unsigned long data) 684static void tifm_sd_abort(unsigned long data)
670{ 685{
686 struct tifm_sd *host = (struct tifm_sd*)data;
687
671 printk(KERN_ERR DRIVER_NAME 688 printk(KERN_ERR DRIVER_NAME
672 ": card failed to respond for a long period of time"); 689 ": card failed to respond for a long period of time");
673 tifm_eject(((struct tifm_sd*)data)->dev); 690
691 tifm_sd_terminate(host);
692 tifm_eject(host->dev);
674} 693}
675 694
676static void tifm_sd_ios(struct mmc_host *mmc, struct mmc_ios *ios) 695static void tifm_sd_ios(struct mmc_host *mmc, struct mmc_ios *ios)
@@ -739,7 +758,7 @@ static void tifm_sd_ios(struct mmc_host *mmc, struct mmc_ios *ios)
739 // allow removal. 758 // allow removal.
740 if ((host->flags & EJECT) && ios->power_mode == MMC_POWER_OFF) { 759 if ((host->flags & EJECT) && ios->power_mode == MMC_POWER_OFF) {
741 host->flags |= EJECT_DONE; 760 host->flags |= EJECT_DONE;
742 wake_up_all(&host->can_eject); 761 wake_up_all(&host->notify);
743 } 762 }
744 763
745 spin_unlock_irqrestore(&sock->lock, flags); 764 spin_unlock_irqrestore(&sock->lock, flags);
@@ -767,21 +786,67 @@ static struct mmc_host_ops tifm_sd_ops = {
767 .get_ro = tifm_sd_ro 786 .get_ro = tifm_sd_ro
768}; 787};
769 788
770static void tifm_sd_register_host(struct work_struct *work) 789static int tifm_sd_initialize_host(struct tifm_sd *host)
771{ 790{
772 struct tifm_sd *host = container_of(work, struct tifm_sd, cmd_handler); 791 int rc;
792 unsigned int host_status = 0;
773 struct tifm_dev *sock = host->dev; 793 struct tifm_dev *sock = host->dev;
774 struct mmc_host *mmc = tifm_get_drvdata(sock);
775 unsigned long flags;
776 794
777 spin_lock_irqsave(&sock->lock, flags); 795 writel(0, sock->addr + SOCK_MMCSD_INT_ENABLE);
778 del_timer(&host->timer); 796 mmiowb();
779 host->flags |= HOST_REG; 797 host->clk_div = 61;
780 PREPARE_WORK(&host->cmd_handler, 798 host->clk_freq = 20000000;
781 no_dma ? tifm_sd_end_cmd_nodma : tifm_sd_end_cmd); 799 writel(TIFM_MMCSD_RESET, sock->addr + SOCK_MMCSD_SYSTEM_CONTROL);
782 spin_unlock_irqrestore(&sock->lock, flags); 800 writel(host->clk_div | TIFM_MMCSD_POWER,
783 dev_dbg(&sock->dev, "adding host\n"); 801 sock->addr + SOCK_MMCSD_CONFIG);
784 mmc_add_host(mmc); 802
803 /* wait up to 0.51 sec for reset */
804 for (rc = 2; rc <= 256; rc <<= 1) {
805 if (1 & readl(sock->addr + SOCK_MMCSD_SYSTEM_STATUS)) {
806 rc = 0;
807 break;
808 }
809 msleep(rc);
810 }
811
812 if (rc) {
813 printk(KERN_ERR DRIVER_NAME
814 ": controller failed to reset\n");
815 return -ENODEV;
816 }
817
818 writel(0, sock->addr + SOCK_MMCSD_NUM_BLOCKS);
819 writel(host->clk_div | TIFM_MMCSD_POWER,
820 sock->addr + SOCK_MMCSD_CONFIG);
821 writel(TIFM_MMCSD_RXDE, sock->addr + SOCK_MMCSD_BUFFER_CONFIG);
822
823 // command timeout fixed to 64 clocks for now
824 writel(64, sock->addr + SOCK_MMCSD_COMMAND_TO);
825 writel(TIFM_MMCSD_INAB, sock->addr + SOCK_MMCSD_COMMAND);
826
827 /* INAB should take much less than reset */
828 for (rc = 1; rc <= 16; rc <<= 1) {
829 host_status = readl(sock->addr + SOCK_MMCSD_STATUS);
830 writel(host_status, sock->addr + SOCK_MMCSD_STATUS);
831 if (!(host_status & TIFM_MMCSD_ERRMASK)
832 && (host_status & TIFM_MMCSD_EOC)) {
833 rc = 0;
834 break;
835 }
836 msleep(rc);
837 }
838
839 if (rc) {
840 printk(KERN_ERR DRIVER_NAME
841 ": card not ready - probe failed on initialization\n");
842 return -ENODEV;
843 }
844
845 writel(TIFM_MMCSD_DATAMASK | TIFM_MMCSD_ERRMASK,
846 sock->addr + SOCK_MMCSD_INT_ENABLE);
847 mmiowb();
848
849 return 0;
785} 850}
786 851
787static int tifm_sd_probe(struct tifm_dev *sock) 852static int tifm_sd_probe(struct tifm_dev *sock)
@@ -801,77 +866,37 @@ static int tifm_sd_probe(struct tifm_dev *sock)
801 return -ENOMEM; 866 return -ENOMEM;
802 867
803 host = mmc_priv(mmc); 868 host = mmc_priv(mmc);
804 host->dev = sock;
805 host->clk_div = 61;
806 init_waitqueue_head(&host->can_eject);
807 INIT_WORK(&host->cmd_handler, tifm_sd_register_host);
808 setup_timer(&host->timer, tifm_sd_abort, (unsigned long)host);
809
810 tifm_set_drvdata(sock, mmc); 869 tifm_set_drvdata(sock, mmc);
811 sock->signal_irq = tifm_sd_signal_irq; 870 host->dev = sock;
812
813 host->clk_freq = 20000000;
814 host->timeout_jiffies = msecs_to_jiffies(1000); 871 host->timeout_jiffies = msecs_to_jiffies(1000);
815 872
873 init_waitqueue_head(&host->notify);
874 tasklet_init(&host->finish_tasklet,
875 no_dma ? tifm_sd_end_cmd_nodma : tifm_sd_end_cmd,
876 (unsigned long)host);
877 setup_timer(&host->timer, tifm_sd_abort, (unsigned long)host);
878
816 tifm_sd_ops.request = no_dma ? tifm_sd_request_nodma : tifm_sd_request; 879 tifm_sd_ops.request = no_dma ? tifm_sd_request_nodma : tifm_sd_request;
817 mmc->ops = &tifm_sd_ops; 880 mmc->ops = &tifm_sd_ops;
818 mmc->ocr_avail = MMC_VDD_32_33 | MMC_VDD_33_34; 881 mmc->ocr_avail = MMC_VDD_32_33 | MMC_VDD_33_34;
819 mmc->caps = MMC_CAP_4_BIT_DATA; 882 mmc->caps = MMC_CAP_4_BIT_DATA | MMC_CAP_MULTIWRITE;
820 mmc->f_min = 20000000 / 60; 883 mmc->f_min = 20000000 / 60;
821 mmc->f_max = 24000000; 884 mmc->f_max = 24000000;
822 mmc->max_hw_segs = 1; 885 mmc->max_hw_segs = 1;
823 mmc->max_phys_segs = 1; 886 mmc->max_phys_segs = 1;
824 mmc->max_sectors = 127; 887 mmc->max_sectors = 127;
825 mmc->max_seg_size = mmc->max_sectors << 11; //2k maximum hw block length 888 mmc->max_seg_size = mmc->max_sectors << 11; //2k maximum hw block length
889 sock->signal_irq = tifm_sd_signal_irq;
890 rc = tifm_sd_initialize_host(host);
826 891
827 writel(0, sock->addr + SOCK_MMCSD_INT_ENABLE); 892 if (!rc)
828 writel(TIFM_MMCSD_RESET, sock->addr + SOCK_MMCSD_SYSTEM_CONTROL); 893 rc = mmc_add_host(mmc);
829 writel(host->clk_div | TIFM_MMCSD_POWER, 894 if (rc)
830 sock->addr + SOCK_MMCSD_CONFIG); 895 goto out_free_mmc;
831
832 for (rc = 0; rc < 50; rc++) {
833 /* Wait for reset ack */
834 if (1 & readl(sock->addr + SOCK_MMCSD_SYSTEM_STATUS)) {
835 rc = 0;
836 break;
837 }
838 msleep(10);
839 }
840
841 if (rc) {
842 printk(KERN_ERR DRIVER_NAME
843 ": card not ready - probe failed\n");
844 mmc_free_host(mmc);
845 return -ENODEV;
846 }
847
848 writel(0, sock->addr + SOCK_MMCSD_NUM_BLOCKS);
849 writel(host->clk_div | TIFM_MMCSD_POWER,
850 sock->addr + SOCK_MMCSD_CONFIG);
851 writel(TIFM_MMCSD_RXDE, sock->addr + SOCK_MMCSD_BUFFER_CONFIG);
852 writel(TIFM_MMCSD_DATAMASK | TIFM_MMCSD_ERRMASK,
853 sock->addr + SOCK_MMCSD_INT_ENABLE);
854
855 writel(64, sock->addr + SOCK_MMCSD_COMMAND_TO); // command timeout 64 clocks for now
856 writel(TIFM_MMCSD_INAB, sock->addr + SOCK_MMCSD_COMMAND);
857 writel(host->clk_div | TIFM_MMCSD_POWER,
858 sock->addr + SOCK_MMCSD_CONFIG);
859
860 mod_timer(&host->timer, jiffies + host->timeout_jiffies);
861 896
862 return 0; 897 return 0;
863} 898out_free_mmc:
864 899 mmc_free_host(mmc);
865static int tifm_sd_host_is_down(struct tifm_dev *sock)
866{
867 struct mmc_host *mmc = tifm_get_drvdata(sock);
868 struct tifm_sd *host = mmc_priv(mmc);
869 unsigned long flags;
870 int rc = 0;
871
872 spin_lock_irqsave(&sock->lock, flags);
873 rc = (host->flags & EJECT_DONE);
874 spin_unlock_irqrestore(&sock->lock, flags);
875 return rc; 900 return rc;
876} 901}
877 902
@@ -879,27 +904,17 @@ static void tifm_sd_remove(struct tifm_dev *sock)
879{ 904{
880 struct mmc_host *mmc = tifm_get_drvdata(sock); 905 struct mmc_host *mmc = tifm_get_drvdata(sock);
881 struct tifm_sd *host = mmc_priv(mmc); 906 struct tifm_sd *host = mmc_priv(mmc);
882 unsigned long flags;
883 907
884 del_timer_sync(&host->timer); 908 del_timer_sync(&host->timer);
885 spin_lock_irqsave(&sock->lock, flags); 909 tifm_sd_terminate(host);
886 host->flags |= EJECT; 910 wait_event_timeout(host->notify, host->flags & EJECT_DONE,
887 if (host->req) 911 host->timeout_jiffies);
888 queue_work(sock->wq, &host->cmd_handler); 912 tasklet_kill(&host->finish_tasklet);
889 spin_unlock_irqrestore(&sock->lock, flags); 913 mmc_remove_host(mmc);
890 wait_event_timeout(host->can_eject, tifm_sd_host_is_down(sock),
891 host->timeout_jiffies);
892
893 if (host->flags & HOST_REG)
894 mmc_remove_host(mmc);
895 914
896 /* The meaning of the bit majority in this constant is unknown. */ 915 /* The meaning of the bit majority in this constant is unknown. */
897 writel(0xfff8 & readl(sock->addr + SOCK_CONTROL), 916 writel(0xfff8 & readl(sock->addr + SOCK_CONTROL),
898 sock->addr + SOCK_CONTROL); 917 sock->addr + SOCK_CONTROL);
899 writel(0, sock->addr + SOCK_MMCSD_INT_ENABLE);
900 writel(TIFM_FIFO_INT_SETALL,
901 sock->addr + SOCK_DMA_FIFO_INT_ENABLE_CLEAR);
902 writel(0, sock->addr + SOCK_DMA_FIFO_INT_ENABLE_SET);
903 918
904 tifm_set_drvdata(sock, NULL); 919 tifm_set_drvdata(sock, NULL);
905 mmc_free_host(mmc); 920 mmc_free_host(mmc);