diff options
author | David S. Miller <davem@davemloft.net> | 2010-01-23 01:45:46 -0500 |
---|---|---|
committer | David S. Miller <davem@davemloft.net> | 2010-01-23 01:45:46 -0500 |
commit | 6be325719b3e54624397e413efd4b33a997e55a3 (patch) | |
tree | 57f321a56794cab2222e179b16731e0d76a4a68a /drivers/ata/pata_hpt3x2n.c | |
parent | 26d92f9276a56d55511a427fb70bd70886af647a (diff) | |
parent | 92dcffb916d309aa01778bf8963a6932e4014d07 (diff) |
Merge branch 'master' of /home/davem/src/GIT/linux-2.6/
Diffstat (limited to 'drivers/ata/pata_hpt3x2n.c')
-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. |