diff options
author | Bartlomiej Zolnierkiewicz <bzolnier@gmail.com> | 2011-10-13 07:05:24 -0400 |
---|---|---|
committer | Jeff Garzik <jgarzik@redhat.com> | 2012-01-08 19:14:58 -0500 |
commit | d63e94a442df14c4e7b02763c3230374218b41f1 (patch) | |
tree | cc7483203a367109b2aa31e9585362b1b140557b /drivers/ata/pata_cs5536.c | |
parent | 002ae08448e241ea8e304008f9cb4bc836f9ff16 (diff) |
pata_cs5536: forward port changes from cs5536
* Fix cable detection to also account for the slave device cable bit.
* Disable UDMA when programming MWDMA in cs5536_set_dmamode().
* Don't change UDMA settings in cs5536_set_piomode().
* Add cs5536_program_dtc() helper.
* Cleanup and uninline cs5536_[read,write]() methods.
Cc: Martin K. Petersen <mkp@mkp.net>
Signed-off-by: Bartlomiej Zolnierkiewicz <bzolnier@gmail.com>
Signed-off-by: Jeff Garzik <jgarzik@redhat.com>
Diffstat (limited to 'drivers/ata/pata_cs5536.c')
-rw-r--r-- | drivers/ata/pata_cs5536.c | 99 |
1 files changed, 42 insertions, 57 deletions
diff --git a/drivers/ata/pata_cs5536.c b/drivers/ata/pata_cs5536.c index 628c8fae5937..7a402c75ab90 100644 --- a/drivers/ata/pata_cs5536.c +++ b/drivers/ata/pata_cs5536.c | |||
@@ -1,6 +1,7 @@ | |||
1 | /* | 1 | /* |
2 | * pata_cs5536.c - CS5536 PATA for new ATA layer | 2 | * pata_cs5536.c - CS5536 PATA for new ATA layer |
3 | * (C) 2007 Martin K. Petersen <mkp@mkp.net> | 3 | * (C) 2007 Martin K. Petersen <mkp@mkp.net> |
4 | * (C) 2011 Bartlomiej Zolnierkiewicz | ||
4 | * | 5 | * |
5 | * This program is free software; you can redistribute it and/or modify | 6 | * This program is free software; you can redistribute it and/or modify |
6 | * it under the terms of the GNU General Public License version 2 as | 7 | * it under the terms of the GNU General Public License version 2 as |
@@ -55,24 +56,16 @@ MODULE_PARM_DESC(msr, "Force using MSR to configure IDE function (Default: 0)"); | |||
55 | #define DRV_VERSION "0.0.8" | 56 | #define DRV_VERSION "0.0.8" |
56 | 57 | ||
57 | enum { | 58 | enum { |
58 | CFG = 0, | 59 | MSR_IDE_CFG = 0x51300010, |
59 | DTC = 1, | ||
60 | CAST = 2, | ||
61 | ETC = 3, | ||
62 | |||
63 | MSR_IDE_BASE = 0x51300000, | ||
64 | MSR_IDE_CFG = (MSR_IDE_BASE + 0x10), | ||
65 | MSR_IDE_DTC = (MSR_IDE_BASE + 0x12), | ||
66 | MSR_IDE_CAST = (MSR_IDE_BASE + 0x13), | ||
67 | MSR_IDE_ETC = (MSR_IDE_BASE + 0x14), | ||
68 | |||
69 | PCI_IDE_CFG = 0x40, | 60 | PCI_IDE_CFG = 0x40, |
70 | PCI_IDE_DTC = 0x48, | ||
71 | PCI_IDE_CAST = 0x4c, | ||
72 | PCI_IDE_ETC = 0x50, | ||
73 | 61 | ||
74 | IDE_CFG_CHANEN = 0x2, | 62 | CFG = 0, |
75 | IDE_CFG_CABLE = 0x10000, | 63 | DTC = 2, |
64 | CAST = 3, | ||
65 | ETC = 4, | ||
66 | |||
67 | IDE_CFG_CHANEN = (1 << 1), | ||
68 | IDE_CFG_CABLE = (1 << 17) | (1 << 16), | ||
76 | 69 | ||
77 | IDE_D0_SHIFT = 24, | 70 | IDE_D0_SHIFT = 24, |
78 | IDE_D1_SHIFT = 16, | 71 | IDE_D1_SHIFT = 16, |
@@ -84,45 +77,50 @@ enum { | |||
84 | IDE_CAST_CMD_MASK = 0xff, | 77 | IDE_CAST_CMD_MASK = 0xff, |
85 | IDE_CAST_CMD_SHIFT = 24, | 78 | IDE_CAST_CMD_SHIFT = 24, |
86 | 79 | ||
87 | IDE_ETC_NODMA = 0x03, | 80 | IDE_ETC_UDMA_MASK = 0xc0, |
88 | }; | ||
89 | |||
90 | static const u32 msr_reg[4] = { | ||
91 | MSR_IDE_CFG, MSR_IDE_DTC, MSR_IDE_CAST, MSR_IDE_ETC, | ||
92 | }; | ||
93 | |||
94 | static const u8 pci_reg[4] = { | ||
95 | PCI_IDE_CFG, PCI_IDE_DTC, PCI_IDE_CAST, PCI_IDE_ETC, | ||
96 | }; | 81 | }; |
97 | 82 | ||
98 | static inline int cs5536_read(struct pci_dev *pdev, int reg, u32 *val) | 83 | static int cs5536_read(struct pci_dev *pdev, int reg, u32 *val) |
99 | { | 84 | { |
100 | if (unlikely(use_msr)) { | 85 | if (unlikely(use_msr)) { |
101 | u32 dummy __maybe_unused; | 86 | u32 dummy __maybe_unused; |
102 | 87 | ||
103 | rdmsr(msr_reg[reg], *val, dummy); | 88 | rdmsr(MSR_IDE_CFG + reg, *val, dummy); |
104 | return 0; | 89 | return 0; |
105 | } | 90 | } |
106 | 91 | ||
107 | return pci_read_config_dword(pdev, pci_reg[reg], val); | 92 | return pci_read_config_dword(pdev, PCI_IDE_CFG + reg * 4, val); |
108 | } | 93 | } |
109 | 94 | ||
110 | static inline int cs5536_write(struct pci_dev *pdev, int reg, int val) | 95 | static int cs5536_write(struct pci_dev *pdev, int reg, int val) |
111 | { | 96 | { |
112 | if (unlikely(use_msr)) { | 97 | if (unlikely(use_msr)) { |
113 | wrmsr(msr_reg[reg], val, 0); | 98 | wrmsr(MSR_IDE_CFG + reg, val, 0); |
114 | return 0; | 99 | return 0; |
115 | } | 100 | } |
116 | 101 | ||
117 | return pci_write_config_dword(pdev, pci_reg[reg], val); | 102 | return pci_write_config_dword(pdev, PCI_IDE_CFG + reg * 4, val); |
103 | } | ||
104 | |||
105 | static void cs5536_program_dtc(struct ata_device *adev, u8 tim) | ||
106 | { | ||
107 | struct pci_dev *pdev = to_pci_dev(adev->link->ap->host->dev); | ||
108 | int dshift = adev->devno ? IDE_D1_SHIFT : IDE_D0_SHIFT; | ||
109 | u32 dtc; | ||
110 | |||
111 | cs5536_read(pdev, DTC, &dtc); | ||
112 | dtc &= ~(IDE_DRV_MASK << dshift); | ||
113 | dtc |= tim << dshift; | ||
114 | cs5536_write(pdev, DTC, dtc); | ||
118 | } | 115 | } |
119 | 116 | ||
120 | /** | 117 | /** |
121 | * cs5536_cable_detect - detect cable type | 118 | * cs5536_cable_detect - detect cable type |
122 | * @ap: Port to detect on | 119 | * @ap: Port to detect on |
123 | * | 120 | * |
124 | * Perform cable detection for ATA66 capable cable. Return a libata | 121 | * Perform cable detection for ATA66 capable cable. |
125 | * cable type. | 122 | * |
123 | * Returns a cable type. | ||
126 | */ | 124 | */ |
127 | 125 | ||
128 | static int cs5536_cable_detect(struct ata_port *ap) | 126 | static int cs5536_cable_detect(struct ata_port *ap) |
@@ -132,7 +130,7 @@ static int cs5536_cable_detect(struct ata_port *ap) | |||
132 | 130 | ||
133 | cs5536_read(pdev, CFG, &cfg); | 131 | cs5536_read(pdev, CFG, &cfg); |
134 | 132 | ||
135 | if (cfg & (IDE_CFG_CABLE << ap->port_no)) | 133 | if (cfg & IDE_CFG_CABLE) |
136 | return ATA_CBL_PATA80; | 134 | return ATA_CBL_PATA80; |
137 | else | 135 | else |
138 | return ATA_CBL_PATA40; | 136 | return ATA_CBL_PATA40; |
@@ -162,19 +160,15 @@ static void cs5536_set_piomode(struct ata_port *ap, struct ata_device *adev) | |||
162 | struct ata_device *pair = ata_dev_pair(adev); | 160 | struct ata_device *pair = ata_dev_pair(adev); |
163 | int mode = adev->pio_mode - XFER_PIO_0; | 161 | int mode = adev->pio_mode - XFER_PIO_0; |
164 | int cmdmode = mode; | 162 | int cmdmode = mode; |
165 | int dshift = adev->devno ? IDE_D1_SHIFT : IDE_D0_SHIFT; | ||
166 | int cshift = adev->devno ? IDE_CAST_D1_SHIFT : IDE_CAST_D0_SHIFT; | 163 | int cshift = adev->devno ? IDE_CAST_D1_SHIFT : IDE_CAST_D0_SHIFT; |
167 | u32 dtc, cast, etc; | 164 | u32 cast; |
168 | 165 | ||
169 | if (pair) | 166 | if (pair) |
170 | cmdmode = min(mode, pair->pio_mode - XFER_PIO_0); | 167 | cmdmode = min(mode, pair->pio_mode - XFER_PIO_0); |
171 | 168 | ||
172 | cs5536_read(pdev, DTC, &dtc); | 169 | cs5536_program_dtc(adev, drv_timings[mode]); |
173 | cs5536_read(pdev, CAST, &cast); | ||
174 | cs5536_read(pdev, ETC, &etc); | ||
175 | 170 | ||
176 | dtc &= ~(IDE_DRV_MASK << dshift); | 171 | cs5536_read(pdev, CAST, &cast); |
177 | dtc |= drv_timings[mode] << dshift; | ||
178 | 172 | ||
179 | cast &= ~(IDE_CAST_DRV_MASK << cshift); | 173 | cast &= ~(IDE_CAST_DRV_MASK << cshift); |
180 | cast |= addr_timings[mode] << cshift; | 174 | cast |= addr_timings[mode] << cshift; |
@@ -182,12 +176,7 @@ static void cs5536_set_piomode(struct ata_port *ap, struct ata_device *adev) | |||
182 | cast &= ~(IDE_CAST_CMD_MASK << IDE_CAST_CMD_SHIFT); | 176 | cast &= ~(IDE_CAST_CMD_MASK << IDE_CAST_CMD_SHIFT); |
183 | cast |= cmd_timings[cmdmode] << IDE_CAST_CMD_SHIFT; | 177 | cast |= cmd_timings[cmdmode] << IDE_CAST_CMD_SHIFT; |
184 | 178 | ||
185 | etc &= ~(IDE_DRV_MASK << dshift); | ||
186 | etc |= IDE_ETC_NODMA << dshift; | ||
187 | |||
188 | cs5536_write(pdev, DTC, dtc); | ||
189 | cs5536_write(pdev, CAST, cast); | 179 | cs5536_write(pdev, CAST, cast); |
190 | cs5536_write(pdev, ETC, etc); | ||
191 | } | 180 | } |
192 | 181 | ||
193 | /** | 182 | /** |
@@ -208,25 +197,21 @@ static void cs5536_set_dmamode(struct ata_port *ap, struct ata_device *adev) | |||
208 | }; | 197 | }; |
209 | 198 | ||
210 | struct pci_dev *pdev = to_pci_dev(ap->host->dev); | 199 | struct pci_dev *pdev = to_pci_dev(ap->host->dev); |
211 | u32 dtc, etc; | 200 | u32 etc; |
212 | int mode = adev->dma_mode; | 201 | int mode = adev->dma_mode; |
213 | int dshift = adev->devno ? IDE_D1_SHIFT : IDE_D0_SHIFT; | 202 | int dshift = adev->devno ? IDE_D1_SHIFT : IDE_D0_SHIFT; |
214 | 203 | ||
215 | if (mode >= XFER_UDMA_0) { | 204 | cs5536_read(pdev, ETC, &etc); |
216 | cs5536_read(pdev, ETC, &etc); | ||
217 | 205 | ||
206 | if (mode >= XFER_UDMA_0) { | ||
218 | etc &= ~(IDE_DRV_MASK << dshift); | 207 | etc &= ~(IDE_DRV_MASK << dshift); |
219 | etc |= udma_timings[mode - XFER_UDMA_0] << dshift; | 208 | etc |= udma_timings[mode - XFER_UDMA_0] << dshift; |
220 | |||
221 | cs5536_write(pdev, ETC, etc); | ||
222 | } else { /* MWDMA */ | 209 | } else { /* MWDMA */ |
223 | cs5536_read(pdev, DTC, &dtc); | 210 | etc &= ~(IDE_ETC_UDMA_MASK << dshift); |
224 | 211 | cs5536_program_dtc(adev, mwdma_timings[mode - XFER_MW_DMA_0]); | |
225 | dtc &= ~(IDE_DRV_MASK << dshift); | ||
226 | dtc |= mwdma_timings[mode - XFER_MW_DMA_0] << dshift; | ||
227 | |||
228 | cs5536_write(pdev, DTC, dtc); | ||
229 | } | 212 | } |
213 | |||
214 | cs5536_write(pdev, ETC, etc); | ||
230 | } | 215 | } |
231 | 216 | ||
232 | static struct scsi_host_template cs5536_sht = { | 217 | static struct scsi_host_template cs5536_sht = { |