diff options
author | Alan Cox <alan@redhat.com> | 2009-01-05 09:12:51 -0500 |
---|---|---|
committer | Jeff Garzik <jgarzik@redhat.com> | 2009-01-08 16:08:56 -0500 |
commit | 978ff6db23279422046c1b3f89fe2045c234dc91 (patch) | |
tree | 69da222db791998823afcc68160dab4d7458ea92 | |
parent | 85da1fb545e5fe51c35e0576f71780cc557f4277 (diff) |
pata_hpt3x3: Workarounds for chipset
Correct the DMA bit flags (UDMA and MWDMA were swapped)
Add workarounds so that we clear ERR and INTR bits before issuing a DMA
Add workarounds so that we stop a live DMA before touching the CTL register
Signed-off-by: Alan Cox <alan@redhat.com>
Signed-off-by: Jeff Garzik <jgarzik@redhat.com>
-rw-r--r-- | drivers/ata/pata_hpt3x3.c | 51 |
1 files changed, 45 insertions, 6 deletions
diff --git a/drivers/ata/pata_hpt3x3.c b/drivers/ata/pata_hpt3x3.c index f11a320337c0..1c9016edf87a 100644 --- a/drivers/ata/pata_hpt3x3.c +++ b/drivers/ata/pata_hpt3x3.c | |||
@@ -23,7 +23,7 @@ | |||
23 | #include <linux/libata.h> | 23 | #include <linux/libata.h> |
24 | 24 | ||
25 | #define DRV_NAME "pata_hpt3x3" | 25 | #define DRV_NAME "pata_hpt3x3" |
26 | #define DRV_VERSION "0.5.3" | 26 | #define DRV_VERSION "0.6.1" |
27 | 27 | ||
28 | /** | 28 | /** |
29 | * hpt3x3_set_piomode - PIO setup | 29 | * hpt3x3_set_piomode - PIO setup |
@@ -80,14 +80,48 @@ static void hpt3x3_set_dmamode(struct ata_port *ap, struct ata_device *adev) | |||
80 | r2 &= ~(0x11 << dn); /* Clear MWDMA and UDMA bits */ | 80 | r2 &= ~(0x11 << dn); /* Clear MWDMA and UDMA bits */ |
81 | 81 | ||
82 | if (adev->dma_mode >= XFER_UDMA_0) | 82 | if (adev->dma_mode >= XFER_UDMA_0) |
83 | r2 |= (0x10 << dn); /* Ultra mode */ | 83 | r2 |= (0x01 << dn); /* Ultra mode */ |
84 | else | 84 | else |
85 | r2 |= (0x01 << dn); /* MWDMA */ | 85 | r2 |= (0x10 << dn); /* MWDMA */ |
86 | 86 | ||
87 | pci_write_config_dword(pdev, 0x44, r1); | 87 | pci_write_config_dword(pdev, 0x44, r1); |
88 | pci_write_config_dword(pdev, 0x48, r2); | 88 | pci_write_config_dword(pdev, 0x48, r2); |
89 | } | 89 | } |
90 | #endif /* CONFIG_PATA_HPT3X3_DMA */ | 90 | |
91 | /** | ||
92 | * hpt3x3_freeze - DMA workaround | ||
93 | * @ap: port to freeze | ||
94 | * | ||
95 | * When freezing an HPT3x3 we must stop any pending DMA before | ||
96 | * writing to the control register or the chip will hang | ||
97 | */ | ||
98 | |||
99 | static int hpt3x3_freeze(struct ata_port *ap) | ||
100 | { | ||
101 | void __iomem *mmio = ap->ioaddr.bmdma_addr; | ||
102 | |||
103 | iowrite8(ioread8(mmio + ATA_DMA_CMD) & ~ ATA_DMA_START, | ||
104 | mmio + ATA_DMA_CMD); | ||
105 | ata_sff_dma_pause(ap); | ||
106 | ata_sff_freeze(ap); | ||
107 | } | ||
108 | |||
109 | /** | ||
110 | * hpt3x3_bmdma_setup - DMA workaround | ||
111 | * @qc: Queued command | ||
112 | * | ||
113 | * When issuing BMDMA we must clean up the error/active bits in | ||
114 | * software on this device | ||
115 | */ | ||
116 | |||
117 | static void hpt3x3_bmdma_setup(struct ata_queued_cmd *qc) | ||
118 | { | ||
119 | struct ata_port *ap = qc->ap; | ||
120 | u8 r = ioread8(ap->ioaddr.bmdma_addr + ATA_DMA_STATUS); | ||
121 | r |= ATA_DMA_INTR | ATA_DMA_ERR; | ||
122 | iowrite8(r, ap->ioaddr.bmdma_addr + ATA_DMA_STATUS); | ||
123 | return ata_bmdma_setup(qc); | ||
124 | } | ||
91 | 125 | ||
92 | /** | 126 | /** |
93 | * hpt3x3_atapi_dma - ATAPI DMA check | 127 | * hpt3x3_atapi_dma - ATAPI DMA check |
@@ -101,18 +135,23 @@ static int hpt3x3_atapi_dma(struct ata_queued_cmd *qc) | |||
101 | return 1; | 135 | return 1; |
102 | } | 136 | } |
103 | 137 | ||
138 | #endif /* CONFIG_PATA_HPT3X3_DMA */ | ||
139 | |||
104 | static struct scsi_host_template hpt3x3_sht = { | 140 | static struct scsi_host_template hpt3x3_sht = { |
105 | ATA_BMDMA_SHT(DRV_NAME), | 141 | ATA_BMDMA_SHT(DRV_NAME), |
106 | }; | 142 | }; |
107 | 143 | ||
108 | static struct ata_port_operations hpt3x3_port_ops = { | 144 | static struct ata_port_operations hpt3x3_port_ops = { |
109 | .inherits = &ata_bmdma_port_ops, | 145 | .inherits = &ata_bmdma_port_ops, |
110 | .check_atapi_dma= hpt3x3_atapi_dma, | ||
111 | .cable_detect = ata_cable_40wire, | 146 | .cable_detect = ata_cable_40wire, |
112 | .set_piomode = hpt3x3_set_piomode, | 147 | .set_piomode = hpt3x3_set_piomode, |
113 | #if defined(CONFIG_PATA_HPT3X3_DMA) | 148 | #if defined(CONFIG_PATA_HPT3X3_DMA) |
114 | .set_dmamode = hpt3x3_set_dmamode, | 149 | .set_dmamode = hpt3x3_set_dmamode, |
150 | .bmdma_setup = hpt3x3_bmdma_setup, | ||
151 | .check_atapi_dma= hpt3x3_atapi_dma, | ||
152 | .freeze = hpt3x3_freeze, | ||
115 | #endif | 153 | #endif |
154 | |||
116 | }; | 155 | }; |
117 | 156 | ||
118 | /** | 157 | /** |
@@ -257,4 +296,4 @@ MODULE_DEVICE_TABLE(pci, hpt3x3); | |||
257 | MODULE_VERSION(DRV_VERSION); | 296 | MODULE_VERSION(DRV_VERSION); |
258 | 297 | ||
259 | module_init(hpt3x3_init); | 298 | module_init(hpt3x3_init); |
260 | module_exit(hpt3x3_exit); | 299 | module_exit(hpt3x3_exit); \ No newline at end of file |