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 /drivers/memstick | |
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>
Diffstat (limited to 'drivers/memstick')
-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; |