aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/memstick/host
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/memstick/host')
-rw-r--r--drivers/memstick/host/jmb38x_ms.c102
-rw-r--r--drivers/memstick/host/tifm_ms.c66
2 files changed, 111 insertions, 57 deletions
diff --git a/drivers/memstick/host/jmb38x_ms.c b/drivers/memstick/host/jmb38x_ms.c
index 4e3bfbcdf155..3485c63d20b0 100644
--- a/drivers/memstick/host/jmb38x_ms.c
+++ b/drivers/memstick/host/jmb38x_ms.c
@@ -50,6 +50,7 @@ struct jmb38x_ms_host {
50 struct jmb38x_ms *chip; 50 struct jmb38x_ms *chip;
51 void __iomem *addr; 51 void __iomem *addr;
52 spinlock_t lock; 52 spinlock_t lock;
53 struct tasklet_struct notify;
53 int id; 54 int id;
54 char host_id[32]; 55 char host_id[32];
55 int irq; 56 int irq;
@@ -590,55 +591,97 @@ static void jmb38x_ms_abort(unsigned long data)
590 spin_unlock_irqrestore(&host->lock, flags); 591 spin_unlock_irqrestore(&host->lock, flags);
591} 592}
592 593
593static void jmb38x_ms_request(struct memstick_host *msh) 594static void jmb38x_ms_req_tasklet(unsigned long data)
594{ 595{
596 struct memstick_host *msh = (struct memstick_host *)data;
595 struct jmb38x_ms_host *host = memstick_priv(msh); 597 struct jmb38x_ms_host *host = memstick_priv(msh);
596 unsigned long flags; 598 unsigned long flags;
597 int rc; 599 int rc;
598 600
599 spin_lock_irqsave(&host->lock, flags); 601 spin_lock_irqsave(&host->lock, flags);
600 if (host->req) { 602 if (!host->req) {
601 spin_unlock_irqrestore(&host->lock, flags); 603 do {
602 BUG(); 604 rc = memstick_next_req(msh, &host->req);
603 return; 605 dev_dbg(&host->chip->pdev->dev, "tasklet req %d\n", rc);
606 } while (!rc && jmb38x_ms_issue_cmd(msh));
604 } 607 }
605
606 do {
607 rc = memstick_next_req(msh, &host->req);
608 } while (!rc && jmb38x_ms_issue_cmd(msh));
609 spin_unlock_irqrestore(&host->lock, flags); 608 spin_unlock_irqrestore(&host->lock, flags);
610} 609}
611 610
612static void jmb38x_ms_reset(struct jmb38x_ms_host *host) 611static void jmb38x_ms_dummy_submit(struct memstick_host *msh)
613{ 612{
614 unsigned int host_ctl = readl(host->addr + HOST_CONTROL); 613 return;
614}
615
616static void jmb38x_ms_submit_req(struct memstick_host *msh)
617{
618 struct jmb38x_ms_host *host = memstick_priv(msh);
619
620 tasklet_schedule(&host->notify);
621}
622
623static int jmb38x_ms_reset(struct jmb38x_ms_host *host)
624{
625 int cnt;
626
627 writel(HOST_CONTROL_RESET_REQ | HOST_CONTROL_CLOCK_EN
628 | readl(host->addr + HOST_CONTROL),
629 host->addr + HOST_CONTROL);
630 mmiowb();
631
632 for (cnt = 0; cnt < 20; ++cnt) {
633 if (!(HOST_CONTROL_RESET_REQ
634 & readl(host->addr + HOST_CONTROL)))
635 goto reset_next;
615 636
616 writel(HOST_CONTROL_RESET_REQ, host->addr + HOST_CONTROL); 637 ndelay(20);
638 }
639 dev_dbg(&host->chip->pdev->dev, "reset_req timeout\n");
640 return -EIO;
641
642reset_next:
643 writel(HOST_CONTROL_RESET | HOST_CONTROL_CLOCK_EN
644 | readl(host->addr + HOST_CONTROL),
645 host->addr + HOST_CONTROL);
646 mmiowb();
647
648 for (cnt = 0; cnt < 20; ++cnt) {
649 if (!(HOST_CONTROL_RESET
650 & readl(host->addr + HOST_CONTROL)))
651 goto reset_ok;
617 652
618 while (HOST_CONTROL_RESET_REQ
619 & (host_ctl = readl(host->addr + HOST_CONTROL))) {
620 ndelay(20); 653 ndelay(20);
621 dev_dbg(&host->chip->pdev->dev, "reset %08x\n", host_ctl);
622 } 654 }
655 dev_dbg(&host->chip->pdev->dev, "reset timeout\n");
656 return -EIO;
623 657
624 writel(HOST_CONTROL_RESET, host->addr + HOST_CONTROL); 658reset_ok:
625 mmiowb(); 659 mmiowb();
626 writel(INT_STATUS_ALL, host->addr + INT_SIGNAL_ENABLE); 660 writel(INT_STATUS_ALL, host->addr + INT_SIGNAL_ENABLE);
627 writel(INT_STATUS_ALL, host->addr + INT_STATUS_ENABLE); 661 writel(INT_STATUS_ALL, host->addr + INT_STATUS_ENABLE);
662 return 0;
628} 663}
629 664
630static void jmb38x_ms_set_param(struct memstick_host *msh, 665static int jmb38x_ms_set_param(struct memstick_host *msh,
631 enum memstick_param param, 666 enum memstick_param param,
632 int value) 667 int value)
633{ 668{
634 struct jmb38x_ms_host *host = memstick_priv(msh); 669 struct jmb38x_ms_host *host = memstick_priv(msh);
635 unsigned int host_ctl = readl(host->addr + HOST_CONTROL); 670 unsigned int host_ctl = readl(host->addr + HOST_CONTROL);
636 unsigned int clock_ctl = CLOCK_CONTROL_40MHZ, clock_delay = 0; 671 unsigned int clock_ctl = CLOCK_CONTROL_40MHZ, clock_delay = 0;
672 int rc = 0;
637 673
638 switch (param) { 674 switch (param) {
639 case MEMSTICK_POWER: 675 case MEMSTICK_POWER:
640 if (value == MEMSTICK_POWER_ON) { 676 if (value == MEMSTICK_POWER_ON) {
641 jmb38x_ms_reset(host); 677 rc = jmb38x_ms_reset(host);
678 if (rc)
679 return rc;
680
681 host_ctl = 7;
682 host_ctl |= HOST_CONTROL_POWER_EN
683 | HOST_CONTROL_CLOCK_EN;
684 writel(host_ctl, host->addr + HOST_CONTROL);
642 685
643 writel(host->id ? PAD_PU_PD_ON_MS_SOCK1 686 writel(host->id ? PAD_PU_PD_ON_MS_SOCK1
644 : PAD_PU_PD_ON_MS_SOCK0, 687 : PAD_PU_PD_ON_MS_SOCK0,
@@ -647,11 +690,7 @@ static void jmb38x_ms_set_param(struct memstick_host *msh,
647 writel(PAD_OUTPUT_ENABLE_MS, 690 writel(PAD_OUTPUT_ENABLE_MS,
648 host->addr + PAD_OUTPUT_ENABLE); 691 host->addr + PAD_OUTPUT_ENABLE);
649 692
650 host_ctl = 7; 693 msleep(10);
651 host_ctl |= HOST_CONTROL_POWER_EN
652 | HOST_CONTROL_CLOCK_EN;
653 writel(host_ctl, host->addr + HOST_CONTROL);
654
655 dev_dbg(&host->chip->pdev->dev, "power on\n"); 694 dev_dbg(&host->chip->pdev->dev, "power on\n");
656 } else if (value == MEMSTICK_POWER_OFF) { 695 } else if (value == MEMSTICK_POWER_OFF) {
657 host_ctl &= ~(HOST_CONTROL_POWER_EN 696 host_ctl &= ~(HOST_CONTROL_POWER_EN
@@ -660,7 +699,8 @@ static void jmb38x_ms_set_param(struct memstick_host *msh,
660 writel(0, host->addr + PAD_OUTPUT_ENABLE); 699 writel(0, host->addr + PAD_OUTPUT_ENABLE);
661 writel(PAD_PU_PD_OFF, host->addr + PAD_PU_PD); 700 writel(PAD_PU_PD_OFF, host->addr + PAD_PU_PD);
662 dev_dbg(&host->chip->pdev->dev, "power off\n"); 701 dev_dbg(&host->chip->pdev->dev, "power off\n");
663 } 702 } else
703 return -EINVAL;
664 break; 704 break;
665 case MEMSTICK_INTERFACE: 705 case MEMSTICK_INTERFACE:
666 host_ctl &= ~(3 << HOST_CONTROL_IF_SHIFT); 706 host_ctl &= ~(3 << HOST_CONTROL_IF_SHIFT);
@@ -686,12 +726,14 @@ static void jmb38x_ms_set_param(struct memstick_host *msh,
686 host_ctl &= ~HOST_CONTROL_REI; 726 host_ctl &= ~HOST_CONTROL_REI;
687 clock_ctl = CLOCK_CONTROL_60MHZ; 727 clock_ctl = CLOCK_CONTROL_60MHZ;
688 clock_delay = 0; 728 clock_delay = 0;
689 } 729 } else
730 return -EINVAL;
690 writel(host_ctl, host->addr + HOST_CONTROL); 731 writel(host_ctl, host->addr + HOST_CONTROL);
691 writel(clock_ctl, host->addr + CLOCK_CONTROL); 732 writel(clock_ctl, host->addr + CLOCK_CONTROL);
692 writel(clock_delay, host->addr + CLOCK_DELAY); 733 writel(clock_delay, host->addr + CLOCK_DELAY);
693 break; 734 break;
694 }; 735 };
736 return 0;
695} 737}
696 738
697#ifdef CONFIG_PM 739#ifdef CONFIG_PM
@@ -785,7 +827,9 @@ static struct memstick_host *jmb38x_ms_alloc_host(struct jmb38x_ms *jm, int cnt)
785 host->id); 827 host->id);
786 host->irq = jm->pdev->irq; 828 host->irq = jm->pdev->irq;
787 host->timeout_jiffies = msecs_to_jiffies(1000); 829 host->timeout_jiffies = msecs_to_jiffies(1000);
788 msh->request = jmb38x_ms_request; 830
831 tasklet_init(&host->notify, jmb38x_ms_req_tasklet, (unsigned long)msh);
832 msh->request = jmb38x_ms_submit_req;
789 msh->set_param = jmb38x_ms_set_param; 833 msh->set_param = jmb38x_ms_set_param;
790 834
791 msh->caps = MEMSTICK_CAP_PAR4 | MEMSTICK_CAP_PAR8; 835 msh->caps = MEMSTICK_CAP_PAR4 | MEMSTICK_CAP_PAR8;
@@ -897,6 +941,8 @@ static void jmb38x_ms_remove(struct pci_dev *dev)
897 941
898 host = memstick_priv(jm->hosts[cnt]); 942 host = memstick_priv(jm->hosts[cnt]);
899 943
944 jm->hosts[cnt]->request = jmb38x_ms_dummy_submit;
945 tasklet_kill(&host->notify);
900 writel(0, host->addr + INT_SIGNAL_ENABLE); 946 writel(0, host->addr + INT_SIGNAL_ENABLE);
901 writel(0, host->addr + INT_STATUS_ENABLE); 947 writel(0, host->addr + INT_STATUS_ENABLE);
902 mmiowb(); 948 mmiowb();
diff --git a/drivers/memstick/host/tifm_ms.c b/drivers/memstick/host/tifm_ms.c
index 8577de4ebb0e..d32d6ad8f3fc 100644
--- a/drivers/memstick/host/tifm_ms.c
+++ b/drivers/memstick/host/tifm_ms.c
@@ -71,6 +71,7 @@ struct tifm_ms {
71 struct tifm_dev *dev; 71 struct tifm_dev *dev;
72 struct timer_list timer; 72 struct timer_list timer;
73 struct memstick_request *req; 73 struct memstick_request *req;
74 struct tasklet_struct notify;
74 unsigned int mode_mask; 75 unsigned int mode_mask;
75 unsigned int block_pos; 76 unsigned int block_pos;
76 unsigned long timeout_jiffies; 77 unsigned long timeout_jiffies;
@@ -455,49 +456,51 @@ static void tifm_ms_card_event(struct tifm_dev *sock)
455 return; 456 return;
456} 457}
457 458
458static void tifm_ms_request(struct memstick_host *msh) 459static void tifm_ms_req_tasklet(unsigned long data)
459{ 460{
461 struct memstick_host *msh = (struct memstick_host *)data;
460 struct tifm_ms *host = memstick_priv(msh); 462 struct tifm_ms *host = memstick_priv(msh);
461 struct tifm_dev *sock = host->dev; 463 struct tifm_dev *sock = host->dev;
462 unsigned long flags; 464 unsigned long flags;
463 int rc; 465 int rc;
464 466
465 spin_lock_irqsave(&sock->lock, flags); 467 spin_lock_irqsave(&sock->lock, flags);
466 if (host->req) { 468 if (!host->req) {
467 printk(KERN_ERR "%s : unfinished request detected\n", 469 if (host->eject) {
468 sock->dev.bus_id); 470 do {
469 spin_unlock_irqrestore(&sock->lock, flags); 471 rc = memstick_next_req(msh, &host->req);
470 tifm_eject(host->dev); 472 if (!rc)
471 return; 473 host->req->error = -ETIME;
472 } 474 } while (!rc);
475 spin_unlock_irqrestore(&sock->lock, flags);
476 return;
477 }
473 478
474 if (host->eject) {
475 do { 479 do {
476 rc = memstick_next_req(msh, &host->req); 480 rc = memstick_next_req(msh, &host->req);
477 if (!rc) 481 } while (!rc && tifm_ms_issue_cmd(host));
478 host->req->error = -ETIME;
479 } while (!rc);
480 spin_unlock_irqrestore(&sock->lock, flags);
481 return;
482 } 482 }
483
484 do {
485 rc = memstick_next_req(msh, &host->req);
486 } while (!rc && tifm_ms_issue_cmd(host));
487
488 spin_unlock_irqrestore(&sock->lock, flags); 483 spin_unlock_irqrestore(&sock->lock, flags);
484}
485
486static void tifm_ms_dummy_submit(struct memstick_host *msh)
487{
489 return; 488 return;
490} 489}
491 490
492static void tifm_ms_set_param(struct memstick_host *msh, 491static void tifm_ms_submit_req(struct memstick_host *msh)
493 enum memstick_param param,
494 int value)
495{ 492{
496 struct tifm_ms *host = memstick_priv(msh); 493 struct tifm_ms *host = memstick_priv(msh);
497 struct tifm_dev *sock = host->dev;
498 unsigned long flags;
499 494
500 spin_lock_irqsave(&sock->lock, flags); 495 tasklet_schedule(&host->notify);
496}
497
498static int tifm_ms_set_param(struct memstick_host *msh,
499 enum memstick_param param,
500 int value)
501{
502 struct tifm_ms *host = memstick_priv(msh);
503 struct tifm_dev *sock = host->dev;
501 504
502 switch (param) { 505 switch (param) {
503 case MEMSTICK_POWER: 506 case MEMSTICK_POWER:
@@ -512,7 +515,8 @@ static void tifm_ms_set_param(struct memstick_host *msh,
512 writel(TIFM_MS_SYS_FCLR | TIFM_MS_SYS_INTCLR, 515 writel(TIFM_MS_SYS_FCLR | TIFM_MS_SYS_INTCLR,
513 sock->addr + SOCK_MS_SYSTEM); 516 sock->addr + SOCK_MS_SYSTEM);
514 writel(0xffffffff, sock->addr + SOCK_MS_STATUS); 517 writel(0xffffffff, sock->addr + SOCK_MS_STATUS);
515 } 518 } else
519 return -EINVAL;
516 break; 520 break;
517 case MEMSTICK_INTERFACE: 521 case MEMSTICK_INTERFACE:
518 if (value == MEMSTICK_SERIAL) { 522 if (value == MEMSTICK_SERIAL) {
@@ -525,11 +529,12 @@ static void tifm_ms_set_param(struct memstick_host *msh,
525 writel(TIFM_CTRL_FAST_CLK 529 writel(TIFM_CTRL_FAST_CLK
526 | readl(sock->addr + SOCK_CONTROL), 530 | readl(sock->addr + SOCK_CONTROL),
527 sock->addr + SOCK_CONTROL); 531 sock->addr + SOCK_CONTROL);
528 } 532 } else
533 return -EINVAL;
529 break; 534 break;
530 }; 535 };
531 536
532 spin_unlock_irqrestore(&sock->lock, flags); 537 return 0;
533} 538}
534 539
535static void tifm_ms_abort(unsigned long data) 540static void tifm_ms_abort(unsigned long data)
@@ -570,8 +575,9 @@ static int tifm_ms_probe(struct tifm_dev *sock)
570 host->timeout_jiffies = msecs_to_jiffies(1000); 575 host->timeout_jiffies = msecs_to_jiffies(1000);
571 576
572 setup_timer(&host->timer, tifm_ms_abort, (unsigned long)host); 577 setup_timer(&host->timer, tifm_ms_abort, (unsigned long)host);
578 tasklet_init(&host->notify, tifm_ms_req_tasklet, (unsigned long)msh);
573 579
574 msh->request = tifm_ms_request; 580 msh->request = tifm_ms_submit_req;
575 msh->set_param = tifm_ms_set_param; 581 msh->set_param = tifm_ms_set_param;
576 sock->card_event = tifm_ms_card_event; 582 sock->card_event = tifm_ms_card_event;
577 sock->data_event = tifm_ms_data_event; 583 sock->data_event = tifm_ms_data_event;
@@ -593,6 +599,8 @@ static void tifm_ms_remove(struct tifm_dev *sock)
593 int rc = 0; 599 int rc = 0;
594 unsigned long flags; 600 unsigned long flags;
595 601
602 msh->request = tifm_ms_dummy_submit;
603 tasklet_kill(&host->notify);
596 spin_lock_irqsave(&sock->lock, flags); 604 spin_lock_irqsave(&sock->lock, flags);
597 host->eject = 1; 605 host->eject = 1;
598 if (host->req) { 606 if (host->req) {