aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/ata/pata_cmd64x.c
diff options
context:
space:
mode:
authorSergei Shtylyov <sshtylyov@ru.mvista.com>2012-03-11 15:25:30 -0400
committerJeff Garzik <jgarzik@redhat.com>2012-03-13 16:42:54 -0400
commit8a686bc984454c1eba6788d0d97dec72ad87f052 (patch)
tree7baf4fe0f2c88cc5e3cdea779e507daa6a2731e4 /drivers/ata/pata_cmd64x.c
parent8fcfa7bd1b77514cfdce77751c980460535f56b4 (diff)
pata_cmd64x: use interrupt status from MRDMODE register
Start using faster version of the bmdma_stop() method for the PCI0646U and newer chips that have the duplicate interrupt status bits in the I/O mapped MRDMODE register. Use the old, slow bmdma_stop() method on the older chips, taking into account that the interrupt bits are not coupled to DMA and that's enough to read the register to clear the interrupt (on the older chips). Determine what method to use at the driver load time. Fix kernel-doc of the bmdma_stop() methods, while at it. Signed-off-by: Sergei Shtylyov <sshtylyov@ru.mvista.com> Signed-off-by: Jeff Garzik <jgarzik@redhat.com>
Diffstat (limited to 'drivers/ata/pata_cmd64x.c')
-rw-r--r--drivers/ata/pata_cmd64x.c73
1 files changed, 56 insertions, 17 deletions
diff --git a/drivers/ata/pata_cmd64x.c b/drivers/ata/pata_cmd64x.c
index 028638c7c1d..f0dcb7056b1 100644
--- a/drivers/ata/pata_cmd64x.c
+++ b/drivers/ata/pata_cmd64x.c
@@ -3,6 +3,7 @@
3 * (C) 2005 Red Hat Inc 3 * (C) 2005 Red Hat Inc
4 * Alan Cox <alan@lxorguk.ukuu.org.uk> 4 * Alan Cox <alan@lxorguk.ukuu.org.uk>
5 * (C) 2009-2010 Bartlomiej Zolnierkiewicz 5 * (C) 2009-2010 Bartlomiej Zolnierkiewicz
6 * (C) 2012 MontaVista Software, LLC <source@mvista.com>
6 * 7 *
7 * Based upon 8 * Based upon
8 * linux/drivers/ide/pci/cmd64x.c Version 1.30 Sept 10, 2002 9 * linux/drivers/ide/pci/cmd64x.c Version 1.30 Sept 10, 2002
@@ -32,7 +33,7 @@
32#include <linux/libata.h> 33#include <linux/libata.h>
33 34
34#define DRV_NAME "pata_cmd64x" 35#define DRV_NAME "pata_cmd64x"
35#define DRV_VERSION "0.2.15" 36#define DRV_VERSION "0.2.16"
36 37
37/* 38/*
38 * CMD64x specific registers definition. 39 * CMD64x specific registers definition.
@@ -229,7 +230,27 @@ static void cmd64x_set_dmamode(struct ata_port *ap, struct ata_device *adev)
229} 230}
230 231
231/** 232/**
232 * cmd648_dma_stop - DMA stop callback 233 * cmd64x_bmdma_stop - DMA stop callback
234 * @qc: Command in progress
235 *
236 * DMA has completed.
237 */
238
239static void cmd64x_bmdma_stop(struct ata_queued_cmd *qc)
240{
241 struct ata_port *ap = qc->ap;
242 struct pci_dev *pdev = to_pci_dev(ap->host->dev);
243 int irq_reg = ap->port_no ? ARTTIM23 : CFR;
244 u8 irq_stat;
245
246 ata_bmdma_stop(qc);
247
248 /* Reading the register should be enough to clear the interrupt */
249 pci_read_config_byte(pdev, irq_reg, &irq_stat);
250}
251
252/**
253 * cmd648_bmdma_stop - DMA stop callback
233 * @qc: Command in progress 254 * @qc: Command in progress
234 * 255 *
235 * DMA has completed. 256 * DMA has completed.
@@ -239,18 +260,20 @@ static void cmd648_bmdma_stop(struct ata_queued_cmd *qc)
239{ 260{
240 struct ata_port *ap = qc->ap; 261 struct ata_port *ap = qc->ap;
241 struct pci_dev *pdev = to_pci_dev(ap->host->dev); 262 struct pci_dev *pdev = to_pci_dev(ap->host->dev);
242 u8 dma_intr; 263 unsigned long base = pci_resource_start(pdev, 4);
243 int dma_mask = ap->port_no ? ARTTIM23_INTR_CH1 : CFR_INTR_CH0; 264 int irq_mask = ap->port_no ? MRDMODE_INTR_CH1 : MRDMODE_INTR_CH0;
244 int dma_reg = ap->port_no ? ARTTIM23 : CFR; 265 u8 mrdmode;
245 266
246 ata_bmdma_stop(qc); 267 ata_bmdma_stop(qc);
247 268
248 pci_read_config_byte(pdev, dma_reg, &dma_intr); 269 /* Clear this port's interrupt bit (leaving the other port alone) */
249 pci_write_config_byte(pdev, dma_reg, dma_intr | dma_mask); 270 mrdmode = inb(base + 1);
271 mrdmode &= ~(MRDMODE_INTR_CH0 | MRDMODE_INTR_CH1);
272 outb(mrdmode | irq_mask, base + 1);
250} 273}
251 274
252/** 275/**
253 * cmd646r1_dma_stop - DMA stop callback 276 * cmd646r1_bmdma_stop - DMA stop callback
254 * @qc: Command in progress 277 * @qc: Command in progress
255 * 278 *
256 * Stub for now while investigating the r1 quirk in the old driver. 279 * Stub for now while investigating the r1 quirk in the old driver.
@@ -273,6 +296,7 @@ static const struct ata_port_operations cmd64x_base_ops = {
273 296
274static struct ata_port_operations cmd64x_port_ops = { 297static struct ata_port_operations cmd64x_port_ops = {
275 .inherits = &cmd64x_base_ops, 298 .inherits = &cmd64x_base_ops,
299 .bmdma_stop = cmd64x_bmdma_stop,
276 .cable_detect = ata_cable_40wire, 300 .cable_detect = ata_cable_40wire,
277}; 301};
278 302
@@ -282,6 +306,12 @@ static struct ata_port_operations cmd646r1_port_ops = {
282 .cable_detect = ata_cable_40wire, 306 .cable_detect = ata_cable_40wire,
283}; 307};
284 308
309static struct ata_port_operations cmd646r3_port_ops = {
310 .inherits = &cmd64x_base_ops,
311 .bmdma_stop = cmd648_bmdma_stop,
312 .cable_detect = ata_cable_40wire,
313};
314
285static struct ata_port_operations cmd648_port_ops = { 315static struct ata_port_operations cmd648_port_ops = {
286 .inherits = &cmd64x_base_ops, 316 .inherits = &cmd64x_base_ops,
287 .bmdma_stop = cmd648_bmdma_stop, 317 .bmdma_stop = cmd648_bmdma_stop,
@@ -306,7 +336,7 @@ static void cmd64x_fixup(struct pci_dev *pdev)
306 336
307static int cmd64x_init_one(struct pci_dev *pdev, const struct pci_device_id *id) 337static int cmd64x_init_one(struct pci_dev *pdev, const struct pci_device_id *id)
308{ 338{
309 static const struct ata_port_info cmd_info[6] = { 339 static const struct ata_port_info cmd_info[7] = {
310 { /* CMD 643 - no UDMA */ 340 { /* CMD 643 - no UDMA */
311 .flags = ATA_FLAG_SLAVE_POSS, 341 .flags = ATA_FLAG_SLAVE_POSS,
312 .pio_mask = ATA_PIO4, 342 .pio_mask = ATA_PIO4,
@@ -319,12 +349,18 @@ static int cmd64x_init_one(struct pci_dev *pdev, const struct pci_device_id *id)
319 .mwdma_mask = ATA_MWDMA2, 349 .mwdma_mask = ATA_MWDMA2,
320 .port_ops = &cmd64x_port_ops 350 .port_ops = &cmd64x_port_ops
321 }, 351 },
322 { /* CMD 646 with working UDMA */ 352 { /* CMD 646U with broken UDMA */
353 .flags = ATA_FLAG_SLAVE_POSS,
354 .pio_mask = ATA_PIO4,
355 .mwdma_mask = ATA_MWDMA2,
356 .port_ops = &cmd646r3_port_ops
357 },
358 { /* CMD 646U2 with working UDMA */
323 .flags = ATA_FLAG_SLAVE_POSS, 359 .flags = ATA_FLAG_SLAVE_POSS,
324 .pio_mask = ATA_PIO4, 360 .pio_mask = ATA_PIO4,
325 .mwdma_mask = ATA_MWDMA2, 361 .mwdma_mask = ATA_MWDMA2,
326 .udma_mask = ATA_UDMA2, 362 .udma_mask = ATA_UDMA2,
327 .port_ops = &cmd64x_port_ops 363 .port_ops = &cmd646r3_port_ops
328 }, 364 },
329 { /* CMD 646 rev 1 */ 365 { /* CMD 646 rev 1 */
330 .flags = ATA_FLAG_SLAVE_POSS, 366 .flags = ATA_FLAG_SLAVE_POSS,
@@ -372,16 +408,19 @@ static int cmd64x_init_one(struct pci_dev *pdev, const struct pci_device_id *id)
372 switch (pdev->revision) { 408 switch (pdev->revision) {
373 /* UDMA works since rev 5 */ 409 /* UDMA works since rev 5 */
374 default: 410 default:
375 ppi[0] = &cmd_info[2]; 411 ppi[0] = &cmd_info[3];
376 ppi[1] = &cmd_info[2]; 412 ppi[1] = &cmd_info[3];
377 break; 413 break;
414 /* Interrupts in MRDMODE since rev 3 */
378 case 3: 415 case 3:
379 case 4: 416 case 4:
417 ppi[0] = &cmd_info[2];
418 ppi[1] = &cmd_info[2];
380 break; 419 break;
381 /* Rev 1 with other problems? */ 420 /* Rev 1 with other problems? */
382 case 1: 421 case 1:
383 ppi[0] = &cmd_info[3]; 422 ppi[0] = &cmd_info[4];
384 ppi[1] = &cmd_info[3]; 423 ppi[1] = &cmd_info[4];
385 /* FALL THRU */ 424 /* FALL THRU */
386 /* Early revs have no CNTRL_CH0 */ 425 /* Early revs have no CNTRL_CH0 */
387 case 2: 426 case 2:
@@ -429,8 +468,8 @@ static int cmd64x_reinit_one(struct pci_dev *pdev)
429static const struct pci_device_id cmd64x[] = { 468static const struct pci_device_id cmd64x[] = {
430 { PCI_VDEVICE(CMD, PCI_DEVICE_ID_CMD_643), 0 }, 469 { PCI_VDEVICE(CMD, PCI_DEVICE_ID_CMD_643), 0 },
431 { PCI_VDEVICE(CMD, PCI_DEVICE_ID_CMD_646), 1 }, 470 { PCI_VDEVICE(CMD, PCI_DEVICE_ID_CMD_646), 1 },
432 { PCI_VDEVICE(CMD, PCI_DEVICE_ID_CMD_648), 4 }, 471 { PCI_VDEVICE(CMD, PCI_DEVICE_ID_CMD_648), 5 },
433 { PCI_VDEVICE(CMD, PCI_DEVICE_ID_CMD_649), 5 }, 472 { PCI_VDEVICE(CMD, PCI_DEVICE_ID_CMD_649), 6 },
434 473
435 { }, 474 { },
436}; 475};