diff options
Diffstat (limited to 'drivers/ata/pata_atp867x.c')
-rw-r--r-- | drivers/ata/pata_atp867x.c | 101 |
1 files changed, 70 insertions, 31 deletions
diff --git a/drivers/ata/pata_atp867x.c b/drivers/ata/pata_atp867x.c index 7990de925d2e..6fe7ded40c6a 100644 --- a/drivers/ata/pata_atp867x.c +++ b/drivers/ata/pata_atp867x.c | |||
@@ -118,20 +118,13 @@ struct atp867x_priv { | |||
118 | int pci66mhz; | 118 | int pci66mhz; |
119 | }; | 119 | }; |
120 | 120 | ||
121 | static inline u8 atp867x_speed_to_mode(u8 speed) | ||
122 | { | ||
123 | return speed - XFER_UDMA_0 + 1; | ||
124 | } | ||
125 | |||
126 | static void atp867x_set_dmamode(struct ata_port *ap, struct ata_device *adev) | 121 | static void atp867x_set_dmamode(struct ata_port *ap, struct ata_device *adev) |
127 | { | 122 | { |
128 | struct pci_dev *pdev = to_pci_dev(ap->host->dev); | 123 | struct pci_dev *pdev = to_pci_dev(ap->host->dev); |
129 | struct atp867x_priv *dp = ap->private_data; | 124 | struct atp867x_priv *dp = ap->private_data; |
130 | u8 speed = adev->dma_mode; | 125 | u8 speed = adev->dma_mode; |
131 | u8 b; | 126 | u8 b; |
132 | u8 mode; | 127 | u8 mode = speed - XFER_UDMA_0 + 1; |
133 | |||
134 | mode = atp867x_speed_to_mode(speed); | ||
135 | 128 | ||
136 | /* | 129 | /* |
137 | * Doc 6.6.9: decrease the udma mode value by 1 for safer UDMA speed | 130 | * Doc 6.6.9: decrease the udma mode value by 1 for safer UDMA speed |
@@ -156,25 +149,38 @@ static void atp867x_set_dmamode(struct ata_port *ap, struct ata_device *adev) | |||
156 | iowrite8(b, dp->dma_mode); | 149 | iowrite8(b, dp->dma_mode); |
157 | } | 150 | } |
158 | 151 | ||
159 | static int atp867x_get_active_clocks_shifted(unsigned int clk) | 152 | static int atp867x_get_active_clocks_shifted(struct ata_port *ap, |
153 | unsigned int clk) | ||
160 | { | 154 | { |
155 | struct atp867x_priv *dp = ap->private_data; | ||
161 | unsigned char clocks = clk; | 156 | unsigned char clocks = clk; |
162 | 157 | ||
158 | /* | ||
159 | * Doc 6.6.9: increase the clock value by 1 for safer PIO speed | ||
160 | * on 66MHz bus | ||
161 | */ | ||
162 | if (dp->pci66mhz) | ||
163 | clocks++; | ||
164 | |||
163 | switch (clocks) { | 165 | switch (clocks) { |
164 | case 0: | 166 | case 0: |
165 | clocks = 1; | 167 | clocks = 1; |
166 | break; | 168 | break; |
167 | case 1 ... 7: | 169 | case 1 ... 6: |
168 | break; | ||
169 | case 8 ... 12: | ||
170 | clocks = 7; | ||
171 | break; | 170 | break; |
172 | default: | 171 | default: |
173 | printk(KERN_WARNING "ATP867X: active %dclk is invalid. " | 172 | printk(KERN_WARNING "ATP867X: active %dclk is invalid. " |
174 | "Using default 8clk.\n", clk); | 173 | "Using 12clk.\n", clk); |
175 | clocks = 0; /* 8 clk */ | 174 | case 9 ... 12: |
175 | clocks = 7; /* 12 clk */ | ||
176 | break; | 176 | break; |
177 | case 7: | ||
178 | case 8: /* default 8 clk */ | ||
179 | clocks = 0; | ||
180 | goto active_clock_shift_done; | ||
177 | } | 181 | } |
182 | |||
183 | active_clock_shift_done: | ||
178 | return clocks << ATP867X_IO_PIOSPD_ACTIVE_SHIFT; | 184 | return clocks << ATP867X_IO_PIOSPD_ACTIVE_SHIFT; |
179 | } | 185 | } |
180 | 186 | ||
@@ -188,20 +194,20 @@ static int atp867x_get_recover_clocks_shifted(unsigned int clk) | |||
188 | break; | 194 | break; |
189 | case 1 ... 11: | 195 | case 1 ... 11: |
190 | break; | 196 | break; |
191 | case 12: | 197 | case 13: |
192 | clocks = 0; | 198 | case 14: |
193 | break; | 199 | --clocks; /* by the spec */ |
194 | case 13: case 14: | ||
195 | --clocks; | ||
196 | break; | 200 | break; |
197 | case 15: | 201 | case 15: |
198 | break; | 202 | break; |
199 | default: | 203 | default: |
200 | printk(KERN_WARNING "ATP867X: recover %dclk is invalid. " | 204 | printk(KERN_WARNING "ATP867X: recover %dclk is invalid. " |
201 | "Using default 15clk.\n", clk); | 205 | "Using default 12clk.\n", clk); |
202 | clocks = 0; /* 12 clk */ | 206 | case 12: /* default 12 clk */ |
207 | clocks = 0; | ||
203 | break; | 208 | break; |
204 | } | 209 | } |
210 | |||
205 | return clocks << ATP867X_IO_PIOSPD_RECOVER_SHIFT; | 211 | return clocks << ATP867X_IO_PIOSPD_RECOVER_SHIFT; |
206 | } | 212 | } |
207 | 213 | ||
@@ -230,25 +236,38 @@ static void atp867x_set_piomode(struct ata_port *ap, struct ata_device *adev) | |||
230 | b = (b & ~ATP867X_IO_DMAMODE_MSTR_MASK); | 236 | b = (b & ~ATP867X_IO_DMAMODE_MSTR_MASK); |
231 | iowrite8(b, dp->dma_mode); | 237 | iowrite8(b, dp->dma_mode); |
232 | 238 | ||
233 | b = atp867x_get_active_clocks_shifted(t.active) | | 239 | b = atp867x_get_active_clocks_shifted(ap, t.active) | |
234 | atp867x_get_recover_clocks_shifted(t.recover); | 240 | atp867x_get_recover_clocks_shifted(t.recover); |
235 | if (dp->pci66mhz) | ||
236 | b += 0x10; | ||
237 | 241 | ||
238 | if (adev->devno & 1) | 242 | if (adev->devno & 1) |
239 | iowrite8(b, dp->slave_piospd); | 243 | iowrite8(b, dp->slave_piospd); |
240 | else | 244 | else |
241 | iowrite8(b, dp->mstr_piospd); | 245 | iowrite8(b, dp->mstr_piospd); |
242 | 246 | ||
243 | /* | 247 | b = atp867x_get_active_clocks_shifted(ap, t.act8b) | |
244 | * use the same value for comand timing as for PIO timimg | 248 | atp867x_get_recover_clocks_shifted(t.rec8b); |
245 | */ | 249 | |
246 | iowrite8(b, dp->eightb_piospd); | 250 | iowrite8(b, dp->eightb_piospd); |
247 | } | 251 | } |
248 | 252 | ||
253 | static int atp867x_cable_override(struct pci_dev *pdev) | ||
254 | { | ||
255 | if (pdev->subsystem_vendor == PCI_VENDOR_ID_ARTOP && | ||
256 | (pdev->subsystem_device == PCI_DEVICE_ID_ARTOP_ATP867A || | ||
257 | pdev->subsystem_device == PCI_DEVICE_ID_ARTOP_ATP867B)) { | ||
258 | return 1; | ||
259 | } | ||
260 | return 0; | ||
261 | } | ||
262 | |||
249 | static int atp867x_cable_detect(struct ata_port *ap) | 263 | static int atp867x_cable_detect(struct ata_port *ap) |
250 | { | 264 | { |
251 | return ATA_CBL_PATA40_SHORT; | 265 | struct pci_dev *pdev = to_pci_dev(ap->host->dev); |
266 | |||
267 | if (atp867x_cable_override(pdev)) | ||
268 | return ATA_CBL_PATA40_SHORT; | ||
269 | |||
270 | return ATA_CBL_PATA_UNK; | ||
252 | } | 271 | } |
253 | 272 | ||
254 | static struct scsi_host_template atp867x_sht = { | 273 | static struct scsi_host_template atp867x_sht = { |
@@ -471,7 +490,6 @@ static int atp867x_init_one(struct pci_dev *pdev, | |||
471 | static const struct ata_port_info info_867x = { | 490 | static const struct ata_port_info info_867x = { |
472 | .flags = ATA_FLAG_SLAVE_POSS, | 491 | .flags = ATA_FLAG_SLAVE_POSS, |
473 | .pio_mask = ATA_PIO4, | 492 | .pio_mask = ATA_PIO4, |
474 | .mwdma_mask = ATA_MWDMA2, | ||
475 | .udma_mask = ATA_UDMA6, | 493 | .udma_mask = ATA_UDMA6, |
476 | .port_ops = &atp867x_ops, | 494 | .port_ops = &atp867x_ops, |
477 | }; | 495 | }; |
@@ -515,6 +533,23 @@ err_out: | |||
515 | return rc; | 533 | return rc; |
516 | } | 534 | } |
517 | 535 | ||
536 | #ifdef CONFIG_PM | ||
537 | static int atp867x_reinit_one(struct pci_dev *pdev) | ||
538 | { | ||
539 | struct ata_host *host = dev_get_drvdata(&pdev->dev); | ||
540 | int rc; | ||
541 | |||
542 | rc = ata_pci_device_do_resume(pdev); | ||
543 | if (rc) | ||
544 | return rc; | ||
545 | |||
546 | atp867x_fixup(host); | ||
547 | |||
548 | ata_host_resume(host); | ||
549 | return 0; | ||
550 | } | ||
551 | #endif | ||
552 | |||
518 | static struct pci_device_id atp867x_pci_tbl[] = { | 553 | static struct pci_device_id atp867x_pci_tbl[] = { |
519 | { PCI_VDEVICE(ARTOP, PCI_DEVICE_ID_ARTOP_ATP867A), 0 }, | 554 | { PCI_VDEVICE(ARTOP, PCI_DEVICE_ID_ARTOP_ATP867A), 0 }, |
520 | { PCI_VDEVICE(ARTOP, PCI_DEVICE_ID_ARTOP_ATP867B), 0 }, | 555 | { PCI_VDEVICE(ARTOP, PCI_DEVICE_ID_ARTOP_ATP867B), 0 }, |
@@ -526,6 +561,10 @@ static struct pci_driver atp867x_driver = { | |||
526 | .id_table = atp867x_pci_tbl, | 561 | .id_table = atp867x_pci_tbl, |
527 | .probe = atp867x_init_one, | 562 | .probe = atp867x_init_one, |
528 | .remove = ata_pci_remove_one, | 563 | .remove = ata_pci_remove_one, |
564 | #ifdef CONFIG_PM | ||
565 | .suspend = ata_pci_device_suspend, | ||
566 | .resume = atp867x_reinit_one, | ||
567 | #endif | ||
529 | }; | 568 | }; |
530 | 569 | ||
531 | static int __init atp867x_init(void) | 570 | static int __init atp867x_init(void) |