diff options
Diffstat (limited to 'drivers/memstick/host/jmb38x_ms.c')
-rw-r--r-- | drivers/memstick/host/jmb38x_ms.c | 67 |
1 files changed, 49 insertions, 18 deletions
diff --git a/drivers/memstick/host/jmb38x_ms.c b/drivers/memstick/host/jmb38x_ms.c index 4e3bfbcdf155..9d82e67737db 100644 --- a/drivers/memstick/host/jmb38x_ms.c +++ b/drivers/memstick/host/jmb38x_ms.c | |||
@@ -609,36 +609,68 @@ static void jmb38x_ms_request(struct memstick_host *msh) | |||
609 | spin_unlock_irqrestore(&host->lock, flags); | 609 | spin_unlock_irqrestore(&host->lock, flags); |
610 | } | 610 | } |
611 | 611 | ||
612 | static void jmb38x_ms_reset(struct jmb38x_ms_host *host) | 612 | static int jmb38x_ms_reset(struct jmb38x_ms_host *host) |
613 | { | 613 | { |
614 | unsigned int host_ctl = readl(host->addr + HOST_CONTROL); | 614 | int cnt; |
615 | 615 | ||
616 | writel(HOST_CONTROL_RESET_REQ, host->addr + HOST_CONTROL); | 616 | writel(HOST_CONTROL_RESET_REQ | HOST_CONTROL_CLOCK_EN |
617 | | readl(host->addr + HOST_CONTROL), | ||
618 | host->addr + HOST_CONTROL); | ||
619 | mmiowb(); | ||
620 | |||
621 | for (cnt = 0; cnt < 20; ++cnt) { | ||
622 | if (!(HOST_CONTROL_RESET_REQ | ||
623 | & readl(host->addr + HOST_CONTROL))) | ||
624 | goto reset_next; | ||
617 | 625 | ||
618 | while (HOST_CONTROL_RESET_REQ | ||
619 | & (host_ctl = readl(host->addr + HOST_CONTROL))) { | ||
620 | ndelay(20); | 626 | ndelay(20); |
621 | dev_dbg(&host->chip->pdev->dev, "reset %08x\n", host_ctl); | ||
622 | } | 627 | } |
628 | dev_dbg(&host->chip->pdev->dev, "reset_req timeout\n"); | ||
629 | return -EIO; | ||
623 | 630 | ||
624 | writel(HOST_CONTROL_RESET, host->addr + HOST_CONTROL); | 631 | reset_next: |
632 | writel(HOST_CONTROL_RESET | HOST_CONTROL_CLOCK_EN | ||
633 | | readl(host->addr + HOST_CONTROL), | ||
634 | host->addr + HOST_CONTROL); | ||
635 | mmiowb(); | ||
636 | |||
637 | for (cnt = 0; cnt < 20; ++cnt) { | ||
638 | if (!(HOST_CONTROL_RESET | ||
639 | & readl(host->addr + HOST_CONTROL))) | ||
640 | goto reset_ok; | ||
641 | |||
642 | ndelay(20); | ||
643 | } | ||
644 | dev_dbg(&host->chip->pdev->dev, "reset timeout\n"); | ||
645 | return -EIO; | ||
646 | |||
647 | reset_ok: | ||
625 | mmiowb(); | 648 | mmiowb(); |
626 | writel(INT_STATUS_ALL, host->addr + INT_SIGNAL_ENABLE); | 649 | writel(INT_STATUS_ALL, host->addr + INT_SIGNAL_ENABLE); |
627 | writel(INT_STATUS_ALL, host->addr + INT_STATUS_ENABLE); | 650 | writel(INT_STATUS_ALL, host->addr + INT_STATUS_ENABLE); |
651 | return 0; | ||
628 | } | 652 | } |
629 | 653 | ||
630 | static void jmb38x_ms_set_param(struct memstick_host *msh, | 654 | static int jmb38x_ms_set_param(struct memstick_host *msh, |
631 | enum memstick_param param, | 655 | enum memstick_param param, |
632 | int value) | 656 | int value) |
633 | { | 657 | { |
634 | struct jmb38x_ms_host *host = memstick_priv(msh); | 658 | struct jmb38x_ms_host *host = memstick_priv(msh); |
635 | unsigned int host_ctl = readl(host->addr + HOST_CONTROL); | 659 | unsigned int host_ctl = readl(host->addr + HOST_CONTROL); |
636 | unsigned int clock_ctl = CLOCK_CONTROL_40MHZ, clock_delay = 0; | 660 | unsigned int clock_ctl = CLOCK_CONTROL_40MHZ, clock_delay = 0; |
661 | int rc = 0; | ||
637 | 662 | ||
638 | switch (param) { | 663 | switch (param) { |
639 | case MEMSTICK_POWER: | 664 | case MEMSTICK_POWER: |
640 | if (value == MEMSTICK_POWER_ON) { | 665 | if (value == MEMSTICK_POWER_ON) { |
641 | jmb38x_ms_reset(host); | 666 | rc = jmb38x_ms_reset(host); |
667 | if (rc) | ||
668 | return rc; | ||
669 | |||
670 | host_ctl = 7; | ||
671 | host_ctl |= HOST_CONTROL_POWER_EN | ||
672 | | HOST_CONTROL_CLOCK_EN; | ||
673 | writel(host_ctl, host->addr + HOST_CONTROL); | ||
642 | 674 | ||
643 | writel(host->id ? PAD_PU_PD_ON_MS_SOCK1 | 675 | writel(host->id ? PAD_PU_PD_ON_MS_SOCK1 |
644 | : PAD_PU_PD_ON_MS_SOCK0, | 676 | : PAD_PU_PD_ON_MS_SOCK0, |
@@ -647,11 +679,7 @@ static void jmb38x_ms_set_param(struct memstick_host *msh, | |||
647 | writel(PAD_OUTPUT_ENABLE_MS, | 679 | writel(PAD_OUTPUT_ENABLE_MS, |
648 | host->addr + PAD_OUTPUT_ENABLE); | 680 | host->addr + PAD_OUTPUT_ENABLE); |
649 | 681 | ||
650 | host_ctl = 7; | 682 | 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"); | 683 | dev_dbg(&host->chip->pdev->dev, "power on\n"); |
656 | } else if (value == MEMSTICK_POWER_OFF) { | 684 | } else if (value == MEMSTICK_POWER_OFF) { |
657 | host_ctl &= ~(HOST_CONTROL_POWER_EN | 685 | host_ctl &= ~(HOST_CONTROL_POWER_EN |
@@ -660,7 +688,8 @@ static void jmb38x_ms_set_param(struct memstick_host *msh, | |||
660 | writel(0, host->addr + PAD_OUTPUT_ENABLE); | 688 | writel(0, host->addr + PAD_OUTPUT_ENABLE); |
661 | writel(PAD_PU_PD_OFF, host->addr + PAD_PU_PD); | 689 | writel(PAD_PU_PD_OFF, host->addr + PAD_PU_PD); |
662 | dev_dbg(&host->chip->pdev->dev, "power off\n"); | 690 | dev_dbg(&host->chip->pdev->dev, "power off\n"); |
663 | } | 691 | } else |
692 | return -EINVAL; | ||
664 | break; | 693 | break; |
665 | case MEMSTICK_INTERFACE: | 694 | case MEMSTICK_INTERFACE: |
666 | host_ctl &= ~(3 << HOST_CONTROL_IF_SHIFT); | 695 | host_ctl &= ~(3 << HOST_CONTROL_IF_SHIFT); |
@@ -686,12 +715,14 @@ static void jmb38x_ms_set_param(struct memstick_host *msh, | |||
686 | host_ctl &= ~HOST_CONTROL_REI; | 715 | host_ctl &= ~HOST_CONTROL_REI; |
687 | clock_ctl = CLOCK_CONTROL_60MHZ; | 716 | clock_ctl = CLOCK_CONTROL_60MHZ; |
688 | clock_delay = 0; | 717 | clock_delay = 0; |
689 | } | 718 | } else |
719 | return -EINVAL; | ||
690 | writel(host_ctl, host->addr + HOST_CONTROL); | 720 | writel(host_ctl, host->addr + HOST_CONTROL); |
691 | writel(clock_ctl, host->addr + CLOCK_CONTROL); | 721 | writel(clock_ctl, host->addr + CLOCK_CONTROL); |
692 | writel(clock_delay, host->addr + CLOCK_DELAY); | 722 | writel(clock_delay, host->addr + CLOCK_DELAY); |
693 | break; | 723 | break; |
694 | }; | 724 | }; |
725 | return 0; | ||
695 | } | 726 | } |
696 | 727 | ||
697 | #ifdef CONFIG_PM | 728 | #ifdef CONFIG_PM |