diff options
| author | Takashi Iwai <tiwai@suse.de> | 2011-01-12 20:01:01 -0500 |
|---|---|---|
| committer | Linus Torvalds <torvalds@linux-foundation.org> | 2011-01-13 11:03:21 -0500 |
| commit | 23c5947ac3f7a610bb4cb9e433802b36edc80fdf (patch) | |
| tree | 6207b2375c61d2bd7e661cac5d1f0b60fb2b23e8 | |
| parent | 0193383a5833c1f082c738eaca868e4093a8df39 (diff) | |
memstick: fix setup for JMicron 38x controllers
This patch corrects the definition of clock values for JMicron 38x
controllers and sets the value properly per interface type.
Also, it adds a check for TPC errors in the interrupt handler.
Signed-off-by: Aries Lee <arieslee@jmicron.com>
Signed-off-by: Takashi Iwai <tiwai@suse.de>
Cc: Alex Dubov <oakad@yahoo.com>
Signed-off-by: Andrew Morton <akpm@linux-foundation.org>
Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org>
| -rw-r--r-- | drivers/memstick/host/jmb38x_ms.c | 66 |
1 files changed, 36 insertions, 30 deletions
diff --git a/drivers/memstick/host/jmb38x_ms.c b/drivers/memstick/host/jmb38x_ms.c index f2b894cd8b02..c90ba5082252 100644 --- a/drivers/memstick/host/jmb38x_ms.c +++ b/drivers/memstick/host/jmb38x_ms.c | |||
| @@ -61,6 +61,7 @@ struct jmb38x_ms_host { | |||
| 61 | struct memstick_request *req; | 61 | struct memstick_request *req; |
| 62 | unsigned char cmd_flags; | 62 | unsigned char cmd_flags; |
| 63 | unsigned char io_pos; | 63 | unsigned char io_pos; |
| 64 | unsigned char ifmode; | ||
| 64 | unsigned int io_word[2]; | 65 | unsigned int io_word[2]; |
| 65 | }; | 66 | }; |
| 66 | 67 | ||
| @@ -136,15 +137,14 @@ struct jmb38x_ms { | |||
| 136 | #define PAD_PU_PD_ON_MS_SOCK0 0x5f8f0000 | 137 | #define PAD_PU_PD_ON_MS_SOCK0 0x5f8f0000 |
| 137 | #define PAD_PU_PD_ON_MS_SOCK1 0x0f0f0000 | 138 | #define PAD_PU_PD_ON_MS_SOCK1 0x0f0f0000 |
| 138 | 139 | ||
| 140 | #define CLOCK_CONTROL_BY_MMIO 0x00000008 | ||
| 139 | #define CLOCK_CONTROL_40MHZ 0x00000001 | 141 | #define CLOCK_CONTROL_40MHZ 0x00000001 |
| 140 | #define CLOCK_CONTROL_50MHZ 0x0000000a | 142 | #define CLOCK_CONTROL_50MHZ 0x00000002 |
| 141 | #define CLOCK_CONTROL_60MHZ 0x00000008 | 143 | #define CLOCK_CONTROL_60MHZ 0x00000010 |
| 142 | #define CLOCK_CONTROL_62_5MHZ 0x0000000c | 144 | #define CLOCK_CONTROL_62_5MHZ 0x00000004 |
| 143 | #define CLOCK_CONTROL_OFF 0x00000000 | 145 | #define CLOCK_CONTROL_OFF 0x00000000 |
| 144 | 146 | ||
| 145 | #define PCI_CTL_CLOCK_DLY_ADDR 0x000000b0 | 147 | #define PCI_CTL_CLOCK_DLY_ADDR 0x000000b0 |
| 146 | #define PCI_CTL_CLOCK_DLY_MASK_A 0x00000f00 | ||
| 147 | #define PCI_CTL_CLOCK_DLY_MASK_B 0x0000f000 | ||
| 148 | 148 | ||
| 149 | enum { | 149 | enum { |
| 150 | CMD_READY = 0x01, | 150 | CMD_READY = 0x01, |
| @@ -390,8 +390,13 @@ static int jmb38x_ms_issue_cmd(struct memstick_host *msh) | |||
| 390 | 390 | ||
| 391 | if (host->req->data_dir == READ) | 391 | if (host->req->data_dir == READ) |
| 392 | cmd |= TPC_DIR; | 392 | cmd |= TPC_DIR; |
| 393 | if (host->req->need_card_int) | 393 | |
| 394 | cmd |= TPC_WAIT_INT; | 394 | if (host->req->need_card_int) { |
| 395 | if (host->ifmode == MEMSTICK_SERIAL) | ||
| 396 | cmd |= TPC_GET_INT; | ||
| 397 | else | ||
| 398 | cmd |= TPC_WAIT_INT; | ||
| 399 | } | ||
| 395 | 400 | ||
| 396 | data = host->req->data; | 401 | data = host->req->data; |
| 397 | 402 | ||
| @@ -529,7 +534,10 @@ static irqreturn_t jmb38x_ms_isr(int irq, void *dev_id) | |||
| 529 | if (irq_status & INT_STATUS_ANY_ERR) { | 534 | if (irq_status & INT_STATUS_ANY_ERR) { |
| 530 | if (irq_status & INT_STATUS_CRC_ERR) | 535 | if (irq_status & INT_STATUS_CRC_ERR) |
| 531 | host->req->error = -EILSEQ; | 536 | host->req->error = -EILSEQ; |
| 532 | else | 537 | else if (irq_status & INT_STATUS_TPC_ERR) { |
| 538 | dev_dbg(&host->chip->pdev->dev, "TPC_ERR\n"); | ||
| 539 | jmb38x_ms_complete_cmd(msh, 0); | ||
| 540 | } else | ||
| 533 | host->req->error = -ETIME; | 541 | host->req->error = -ETIME; |
| 534 | } else { | 542 | } else { |
| 535 | if (host->cmd_flags & DMA_DATA) { | 543 | if (host->cmd_flags & DMA_DATA) { |
| @@ -644,7 +652,6 @@ static int jmb38x_ms_reset(struct jmb38x_ms_host *host) | |||
| 644 | ndelay(20); | 652 | ndelay(20); |
| 645 | } | 653 | } |
| 646 | dev_dbg(&host->chip->pdev->dev, "reset_req timeout\n"); | 654 | dev_dbg(&host->chip->pdev->dev, "reset_req timeout\n"); |
| 647 | /* return -EIO; */ | ||
| 648 | 655 | ||
| 649 | reset_next: | 656 | reset_next: |
| 650 | writel(HOST_CONTROL_RESET | HOST_CONTROL_CLOCK_EN | 657 | writel(HOST_CONTROL_RESET | HOST_CONTROL_CLOCK_EN |
| @@ -675,7 +682,7 @@ static int jmb38x_ms_set_param(struct memstick_host *msh, | |||
| 675 | { | 682 | { |
| 676 | struct jmb38x_ms_host *host = memstick_priv(msh); | 683 | struct jmb38x_ms_host *host = memstick_priv(msh); |
| 677 | unsigned int host_ctl = readl(host->addr + HOST_CONTROL); | 684 | unsigned int host_ctl = readl(host->addr + HOST_CONTROL); |
| 678 | unsigned int clock_ctl = CLOCK_CONTROL_40MHZ, clock_delay = 0; | 685 | unsigned int clock_ctl = CLOCK_CONTROL_BY_MMIO, clock_delay = 0; |
| 679 | int rc = 0; | 686 | int rc = 0; |
| 680 | 687 | ||
| 681 | switch (param) { | 688 | switch (param) { |
| @@ -687,9 +694,7 @@ static int jmb38x_ms_set_param(struct memstick_host *msh, | |||
| 687 | 694 | ||
| 688 | host_ctl = 7; | 695 | host_ctl = 7; |
| 689 | host_ctl |= HOST_CONTROL_POWER_EN | 696 | host_ctl |= HOST_CONTROL_POWER_EN |
| 690 | | HOST_CONTROL_CLOCK_EN | 697 | | HOST_CONTROL_CLOCK_EN; |
| 691 | | HOST_CONTROL_HW_OC_P | ||
| 692 | | HOST_CONTROL_TDELAY_EN; | ||
| 693 | writel(host_ctl, host->addr + HOST_CONTROL); | 698 | writel(host_ctl, host->addr + HOST_CONTROL); |
| 694 | 699 | ||
| 695 | writel(host->id ? PAD_PU_PD_ON_MS_SOCK1 | 700 | writel(host->id ? PAD_PU_PD_ON_MS_SOCK1 |
| @@ -712,41 +717,42 @@ static int jmb38x_ms_set_param(struct memstick_host *msh, | |||
| 712 | return -EINVAL; | 717 | return -EINVAL; |
| 713 | break; | 718 | break; |
| 714 | case MEMSTICK_INTERFACE: | 719 | case MEMSTICK_INTERFACE: |
| 720 | dev_dbg(&host->chip->pdev->dev, | ||
| 721 | "Set Host Interface Mode to %d\n", value); | ||
| 722 | host_ctl &= ~(HOST_CONTROL_FAST_CLK | HOST_CONTROL_REI | | ||
| 723 | HOST_CONTROL_REO); | ||
| 724 | host_ctl |= HOST_CONTROL_TDELAY_EN | HOST_CONTROL_HW_OC_P; | ||
| 715 | host_ctl &= ~(3 << HOST_CONTROL_IF_SHIFT); | 725 | host_ctl &= ~(3 << HOST_CONTROL_IF_SHIFT); |
| 716 | pci_read_config_dword(host->chip->pdev, | ||
| 717 | PCI_CTL_CLOCK_DLY_ADDR, | ||
| 718 | &clock_delay); | ||
| 719 | clock_delay &= host->id ? ~PCI_CTL_CLOCK_DLY_MASK_B | ||
| 720 | : ~PCI_CTL_CLOCK_DLY_MASK_A; | ||
| 721 | 726 | ||
| 722 | if (value == MEMSTICK_SERIAL) { | 727 | if (value == MEMSTICK_SERIAL) { |
| 723 | host_ctl &= ~HOST_CONTROL_FAST_CLK; | ||
| 724 | host_ctl &= ~HOST_CONTROL_REO; | ||
| 725 | host_ctl |= HOST_CONTROL_IF_SERIAL | 728 | host_ctl |= HOST_CONTROL_IF_SERIAL |
| 726 | << HOST_CONTROL_IF_SHIFT; | 729 | << HOST_CONTROL_IF_SHIFT; |
| 727 | host_ctl |= HOST_CONTROL_REI; | 730 | host_ctl |= HOST_CONTROL_REI; |
| 728 | clock_ctl = CLOCK_CONTROL_40MHZ; | 731 | clock_ctl |= CLOCK_CONTROL_40MHZ; |
| 732 | clock_delay = 0; | ||
| 729 | } else if (value == MEMSTICK_PAR4) { | 733 | } else if (value == MEMSTICK_PAR4) { |
| 730 | host_ctl |= HOST_CONTROL_FAST_CLK | HOST_CONTROL_REO; | 734 | host_ctl |= HOST_CONTROL_FAST_CLK; |
| 731 | host_ctl |= HOST_CONTROL_IF_PAR4 | 735 | host_ctl |= HOST_CONTROL_IF_PAR4 |
| 732 | << HOST_CONTROL_IF_SHIFT; | 736 | << HOST_CONTROL_IF_SHIFT; |
| 733 | host_ctl &= ~HOST_CONTROL_REI; | 737 | host_ctl |= HOST_CONTROL_REO; |
| 734 | clock_ctl = CLOCK_CONTROL_40MHZ; | 738 | clock_ctl |= CLOCK_CONTROL_40MHZ; |
| 735 | clock_delay |= host->id ? (4 << 12) : (4 << 8); | 739 | clock_delay = 4; |
| 736 | } else if (value == MEMSTICK_PAR8) { | 740 | } else if (value == MEMSTICK_PAR8) { |
| 737 | host_ctl |= HOST_CONTROL_FAST_CLK; | 741 | host_ctl |= HOST_CONTROL_FAST_CLK; |
| 738 | host_ctl |= HOST_CONTROL_IF_PAR8 | 742 | host_ctl |= HOST_CONTROL_IF_PAR8 |
| 739 | << HOST_CONTROL_IF_SHIFT; | 743 | << HOST_CONTROL_IF_SHIFT; |
| 740 | host_ctl &= ~(HOST_CONTROL_REI | HOST_CONTROL_REO); | 744 | clock_ctl |= CLOCK_CONTROL_50MHZ; |
| 741 | clock_ctl = CLOCK_CONTROL_50MHZ; | 745 | clock_delay = 0; |
| 742 | } else | 746 | } else |
| 743 | return -EINVAL; | 747 | return -EINVAL; |
| 744 | 748 | ||
| 745 | writel(host_ctl, host->addr + HOST_CONTROL); | 749 | writel(host_ctl, host->addr + HOST_CONTROL); |
| 750 | writel(CLOCK_CONTROL_OFF, host->addr + CLOCK_CONTROL); | ||
| 746 | writel(clock_ctl, host->addr + CLOCK_CONTROL); | 751 | writel(clock_ctl, host->addr + CLOCK_CONTROL); |
| 747 | pci_write_config_dword(host->chip->pdev, | 752 | pci_write_config_byte(host->chip->pdev, |
| 748 | PCI_CTL_CLOCK_DLY_ADDR, | 753 | PCI_CTL_CLOCK_DLY_ADDR + 1, |
| 749 | clock_delay); | 754 | clock_delay); |
| 755 | host->ifmode = value; | ||
| 750 | break; | 756 | break; |
| 751 | }; | 757 | }; |
| 752 | return 0; | 758 | return 0; |
