diff options
| -rw-r--r-- | drivers/ata/pata_hpt3x2n.c | 64 |
1 files changed, 35 insertions, 29 deletions
diff --git a/drivers/ata/pata_hpt3x2n.c b/drivers/ata/pata_hpt3x2n.c index 9a09a1b11ca5..dd26bc73bd9a 100644 --- a/drivers/ata/pata_hpt3x2n.c +++ b/drivers/ata/pata_hpt3x2n.c | |||
| @@ -8,7 +8,7 @@ | |||
| 8 | * Copyright (C) 1999-2003 Andre Hedrick <andre@linux-ide.org> | 8 | * Copyright (C) 1999-2003 Andre Hedrick <andre@linux-ide.org> |
| 9 | * Portions Copyright (C) 2001 Sun Microsystems, Inc. | 9 | * Portions Copyright (C) 2001 Sun Microsystems, Inc. |
| 10 | * Portions Copyright (C) 2003 Red Hat Inc | 10 | * Portions Copyright (C) 2003 Red Hat Inc |
| 11 | * Portions Copyright (C) 2005-2007 MontaVista Software, Inc. | 11 | * Portions Copyright (C) 2005-2009 MontaVista Software, Inc. |
| 12 | * | 12 | * |
| 13 | * | 13 | * |
| 14 | * TODO | 14 | * TODO |
| @@ -25,7 +25,7 @@ | |||
| 25 | #include <linux/libata.h> | 25 | #include <linux/libata.h> |
| 26 | 26 | ||
| 27 | #define DRV_NAME "pata_hpt3x2n" | 27 | #define DRV_NAME "pata_hpt3x2n" |
| 28 | #define DRV_VERSION "0.3.7" | 28 | #define DRV_VERSION "0.3.8" |
| 29 | 29 | ||
| 30 | enum { | 30 | enum { |
| 31 | HPT_PCI_FAST = (1 << 31), | 31 | HPT_PCI_FAST = (1 << 31), |
| @@ -264,7 +264,7 @@ static void hpt3x2n_bmdma_stop(struct ata_queued_cmd *qc) | |||
| 264 | 264 | ||
| 265 | static void hpt3x2n_set_clock(struct ata_port *ap, int source) | 265 | static void hpt3x2n_set_clock(struct ata_port *ap, int source) |
| 266 | { | 266 | { |
| 267 | void __iomem *bmdma = ap->ioaddr.bmdma_addr; | 267 | void __iomem *bmdma = ap->ioaddr.bmdma_addr - ap->port_no * 8; |
| 268 | 268 | ||
| 269 | /* Tristate the bus */ | 269 | /* Tristate the bus */ |
| 270 | iowrite8(0x80, bmdma+0x73); | 270 | iowrite8(0x80, bmdma+0x73); |
| @@ -274,9 +274,9 @@ static void hpt3x2n_set_clock(struct ata_port *ap, int source) | |||
| 274 | iowrite8(source, bmdma+0x7B); | 274 | iowrite8(source, bmdma+0x7B); |
| 275 | iowrite8(0xC0, bmdma+0x79); | 275 | iowrite8(0xC0, bmdma+0x79); |
| 276 | 276 | ||
| 277 | /* Reset state machines */ | 277 | /* Reset state machines, avoid enabling the disabled channels */ |
| 278 | iowrite8(0x37, bmdma+0x70); | 278 | iowrite8(ioread8(bmdma+0x70) | 0x32, bmdma+0x70); |
| 279 | iowrite8(0x37, bmdma+0x74); | 279 | iowrite8(ioread8(bmdma+0x74) | 0x32, bmdma+0x74); |
| 280 | 280 | ||
| 281 | /* Complete reset */ | 281 | /* Complete reset */ |
| 282 | iowrite8(0x00, bmdma+0x79); | 282 | iowrite8(0x00, bmdma+0x79); |
| @@ -286,21 +286,10 @@ static void hpt3x2n_set_clock(struct ata_port *ap, int source) | |||
| 286 | iowrite8(0x00, bmdma+0x77); | 286 | iowrite8(0x00, bmdma+0x77); |
| 287 | } | 287 | } |
| 288 | 288 | ||
| 289 | /* Check if our partner interface is busy */ | ||
| 290 | |||
| 291 | static int hpt3x2n_pair_idle(struct ata_port *ap) | ||
| 292 | { | ||
| 293 | struct ata_host *host = ap->host; | ||
| 294 | struct ata_port *pair = host->ports[ap->port_no ^ 1]; | ||
| 295 | |||
| 296 | if (pair->hsm_task_state == HSM_ST_IDLE) | ||
| 297 | return 1; | ||
| 298 | return 0; | ||
| 299 | } | ||
| 300 | |||
| 301 | static int hpt3x2n_use_dpll(struct ata_port *ap, int writing) | 289 | static int hpt3x2n_use_dpll(struct ata_port *ap, int writing) |
| 302 | { | 290 | { |
| 303 | long flags = (long)ap->host->private_data; | 291 | long flags = (long)ap->host->private_data; |
| 292 | |||
| 304 | /* See if we should use the DPLL */ | 293 | /* See if we should use the DPLL */ |
| 305 | if (writing) | 294 | if (writing) |
| 306 | return USE_DPLL; /* Needed for write */ | 295 | return USE_DPLL; /* Needed for write */ |
| @@ -309,20 +298,35 @@ static int hpt3x2n_use_dpll(struct ata_port *ap, int writing) | |||
| 309 | return 0; | 298 | return 0; |
| 310 | } | 299 | } |
| 311 | 300 | ||
| 301 | static int hpt3x2n_qc_defer(struct ata_queued_cmd *qc) | ||
| 302 | { | ||
| 303 | struct ata_port *ap = qc->ap; | ||
| 304 | struct ata_port *alt = ap->host->ports[ap->port_no ^ 1]; | ||
| 305 | int rc, flags = (long)ap->host->private_data; | ||
| 306 | int dpll = hpt3x2n_use_dpll(ap, qc->tf.flags & ATA_TFLAG_WRITE); | ||
| 307 | |||
| 308 | /* First apply the usual rules */ | ||
| 309 | rc = ata_std_qc_defer(qc); | ||
| 310 | if (rc != 0) | ||
| 311 | return rc; | ||
| 312 | |||
| 313 | if ((flags & USE_DPLL) != dpll && alt->qc_active) | ||
| 314 | return ATA_DEFER_PORT; | ||
| 315 | return 0; | ||
| 316 | } | ||
| 317 | |||
| 312 | static unsigned int hpt3x2n_qc_issue(struct ata_queued_cmd *qc) | 318 | static unsigned int hpt3x2n_qc_issue(struct ata_queued_cmd *qc) |
| 313 | { | 319 | { |
| 314 | struct ata_taskfile *tf = &qc->tf; | ||
| 315 | struct ata_port *ap = qc->ap; | 320 | struct ata_port *ap = qc->ap; |
| 316 | int flags = (long)ap->host->private_data; | 321 | int flags = (long)ap->host->private_data; |
| 322 | int dpll = hpt3x2n_use_dpll(ap, qc->tf.flags & ATA_TFLAG_WRITE); | ||
| 317 | 323 | ||
| 318 | if (hpt3x2n_pair_idle(ap)) { | 324 | if ((flags & USE_DPLL) != dpll) { |
| 319 | int dpll = hpt3x2n_use_dpll(ap, (tf->flags & ATA_TFLAG_WRITE)); | 325 | flags &= ~USE_DPLL; |
| 320 | if ((flags & USE_DPLL) != dpll) { | 326 | flags |= dpll; |
| 321 | if (dpll == 1) | 327 | ap->host->private_data = (void *)(long)flags; |
| 322 | hpt3x2n_set_clock(ap, 0x21); | 328 | |
| 323 | else | 329 | hpt3x2n_set_clock(ap, dpll ? 0x21 : 0x23); |
| 324 | hpt3x2n_set_clock(ap, 0x23); | ||
| 325 | } | ||
| 326 | } | 330 | } |
| 327 | return ata_sff_qc_issue(qc); | 331 | return ata_sff_qc_issue(qc); |
| 328 | } | 332 | } |
| @@ -339,6 +343,8 @@ static struct ata_port_operations hpt3x2n_port_ops = { | |||
| 339 | .inherits = &ata_bmdma_port_ops, | 343 | .inherits = &ata_bmdma_port_ops, |
| 340 | 344 | ||
| 341 | .bmdma_stop = hpt3x2n_bmdma_stop, | 345 | .bmdma_stop = hpt3x2n_bmdma_stop, |
| 346 | |||
| 347 | .qc_defer = hpt3x2n_qc_defer, | ||
| 342 | .qc_issue = hpt3x2n_qc_issue, | 348 | .qc_issue = hpt3x2n_qc_issue, |
| 343 | 349 | ||
| 344 | .cable_detect = hpt3x2n_cable_detect, | 350 | .cable_detect = hpt3x2n_cable_detect, |
| @@ -454,7 +460,7 @@ static int hpt3x2n_init_one(struct pci_dev *dev, const struct pci_device_id *id) | |||
| 454 | unsigned int f_low, f_high; | 460 | unsigned int f_low, f_high; |
| 455 | int adjust; | 461 | int adjust; |
| 456 | unsigned long iobase = pci_resource_start(dev, 4); | 462 | unsigned long iobase = pci_resource_start(dev, 4); |
| 457 | void *hpriv = NULL; | 463 | void *hpriv = (void *)USE_DPLL; |
| 458 | int rc; | 464 | int rc; |
| 459 | 465 | ||
| 460 | rc = pcim_enable_device(dev); | 466 | rc = pcim_enable_device(dev); |
| @@ -539,7 +545,7 @@ static int hpt3x2n_init_one(struct pci_dev *dev, const struct pci_device_id *id) | |||
| 539 | /* Set our private data up. We only need a few flags so we use | 545 | /* Set our private data up. We only need a few flags so we use |
| 540 | it directly */ | 546 | it directly */ |
| 541 | if (pci_mhz > 60) { | 547 | if (pci_mhz > 60) { |
| 542 | hpriv = (void *)PCI66; | 548 | hpriv = (void *)(PCI66 | USE_DPLL); |
| 543 | /* | 549 | /* |
| 544 | * On HPT371N, if ATA clock is 66 MHz we must set bit 2 in | 550 | * On HPT371N, if ATA clock is 66 MHz we must set bit 2 in |
| 545 | * the MISC. register to stretch the UltraDMA Tss timing. | 551 | * the MISC. register to stretch the UltraDMA Tss timing. |
