diff options
Diffstat (limited to 'drivers/ata/pata_hpt3x2n.c')
-rw-r--r-- | drivers/ata/pata_hpt3x2n.c | 74 |
1 files changed, 58 insertions, 16 deletions
diff --git a/drivers/ata/pata_hpt3x2n.c b/drivers/ata/pata_hpt3x2n.c index 65f2e180e7fa..6a34521b9e01 100644 --- a/drivers/ata/pata_hpt3x2n.c +++ b/drivers/ata/pata_hpt3x2n.c | |||
@@ -8,10 +8,10 @@ | |||
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-2006 MontaVista Software, Inc. | ||
11 | * | 12 | * |
12 | * | 13 | * |
13 | * TODO | 14 | * TODO |
14 | * 371N | ||
15 | * Work out best PLL policy | 15 | * Work out best PLL policy |
16 | */ | 16 | */ |
17 | 17 | ||
@@ -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.2" | 28 | #define DRV_VERSION "0.3.3" |
29 | 29 | ||
30 | enum { | 30 | enum { |
31 | HPT_PCI_FAST = (1 << 31), | 31 | HPT_PCI_FAST = (1 << 31), |
@@ -115,14 +115,13 @@ static u32 hpt3x2n_find_mode(struct ata_port *ap, int speed) | |||
115 | } | 115 | } |
116 | 116 | ||
117 | /** | 117 | /** |
118 | * hpt3x2n_pre_reset - reset the hpt3x2n bus | 118 | * hpt3x2n_cable_detect - Detect the cable type |
119 | * @ap: ATA port to reset | 119 | * @ap: ATA port to detect on |
120 | * | 120 | * |
121 | * Perform the initial reset handling for the 3x2n series controllers. | 121 | * Return the cable type attached to this port |
122 | * Reset the hardware and state machine, obtain the cable type. | ||
123 | */ | 122 | */ |
124 | 123 | ||
125 | static int hpt3xn_pre_reset(struct ata_port *ap) | 124 | static int hpt3x2n_cable_detect(struct ata_port *ap) |
126 | { | 125 | { |
127 | u8 scr2, ata66; | 126 | u8 scr2, ata66; |
128 | struct pci_dev *pdev = to_pci_dev(ap->host->dev); | 127 | struct pci_dev *pdev = to_pci_dev(ap->host->dev); |
@@ -135,15 +134,26 @@ static int hpt3xn_pre_reset(struct ata_port *ap) | |||
135 | pci_write_config_byte(pdev, 0x5B, scr2); | 134 | pci_write_config_byte(pdev, 0x5B, scr2); |
136 | 135 | ||
137 | if (ata66 & (1 << ap->port_no)) | 136 | if (ata66 & (1 << ap->port_no)) |
138 | ap->cbl = ATA_CBL_PATA40; | 137 | return ATA_CBL_PATA40; |
139 | else | 138 | else |
140 | ap->cbl = ATA_CBL_PATA80; | 139 | return ATA_CBL_PATA80; |
140 | } | ||
141 | |||
142 | /** | ||
143 | * hpt3x2n_pre_reset - reset the hpt3x2n bus | ||
144 | * @ap: ATA port to reset | ||
145 | * @deadline: deadline jiffies for the operation | ||
146 | * | ||
147 | * Perform the initial reset handling for the 3x2n series controllers. | ||
148 | * Reset the hardware and state machine, | ||
149 | */ | ||
141 | 150 | ||
151 | static int hpt3xn_pre_reset(struct ata_port *ap) | ||
152 | { | ||
153 | struct pci_dev *pdev = to_pci_dev(ap->host->dev); | ||
142 | /* Reset the state machine */ | 154 | /* Reset the state machine */ |
143 | pci_write_config_byte(pdev, 0x50, 0x37); | 155 | pci_write_config_byte(pdev, 0x50 + 4 * ap->port_no, 0x37); |
144 | pci_write_config_byte(pdev, 0x54, 0x37); | ||
145 | udelay(100); | 156 | udelay(100); |
146 | |||
147 | return ata_std_prereset(ap); | 157 | return ata_std_prereset(ap); |
148 | } | 158 | } |
149 | 159 | ||
@@ -364,6 +374,7 @@ static struct ata_port_operations hpt3x2n_port_ops = { | |||
364 | .thaw = ata_bmdma_thaw, | 374 | .thaw = ata_bmdma_thaw, |
365 | .error_handler = hpt3x2n_error_handler, | 375 | .error_handler = hpt3x2n_error_handler, |
366 | .post_internal_cmd = ata_bmdma_post_internal_cmd, | 376 | .post_internal_cmd = ata_bmdma_post_internal_cmd, |
377 | .cable_detect = hpt3x2n_cable_detect, | ||
367 | 378 | ||
368 | .bmdma_setup = ata_bmdma_setup, | 379 | .bmdma_setup = ata_bmdma_setup, |
369 | .bmdma_start = ata_bmdma_start, | 380 | .bmdma_start = ata_bmdma_start, |
@@ -422,8 +433,9 @@ static int hpt3x2n_pci_clock(struct pci_dev *pdev) | |||
422 | { | 433 | { |
423 | unsigned long freq; | 434 | unsigned long freq; |
424 | u32 fcnt; | 435 | u32 fcnt; |
436 | unsigned long iobase = pci_resource_start(pdev, 4); | ||
425 | 437 | ||
426 | pci_read_config_dword(pdev, 0x70/*CHECKME*/, &fcnt); | 438 | fcnt = inl(iobase + 0x90); /* Not PCI readable for some chips */ |
427 | if ((fcnt >> 12) != 0xABCDE) { | 439 | if ((fcnt >> 12) != 0xABCDE) { |
428 | printk(KERN_WARNING "hpt3xn: BIOS clock data not set.\n"); | 440 | printk(KERN_WARNING "hpt3xn: BIOS clock data not set.\n"); |
429 | return 33; /* Not BIOS set */ | 441 | return 33; /* Not BIOS set */ |
@@ -492,6 +504,7 @@ static int hpt3x2n_init_one(struct pci_dev *dev, const struct pci_device_id *id) | |||
492 | unsigned int pci_mhz; | 504 | unsigned int pci_mhz; |
493 | unsigned int f_low, f_high; | 505 | unsigned int f_low, f_high; |
494 | int adjust; | 506 | int adjust; |
507 | unsigned long iobase = pci_resource_start(dev, 4); | ||
495 | 508 | ||
496 | pci_read_config_dword(dev, PCI_CLASS_REVISION, &class_rev); | 509 | pci_read_config_dword(dev, PCI_CLASS_REVISION, &class_rev); |
497 | class_rev &= 0xFF; | 510 | class_rev &= 0xFF; |
@@ -501,6 +514,11 @@ static int hpt3x2n_init_one(struct pci_dev *dev, const struct pci_device_id *id) | |||
501 | if (class_rev < 6) | 514 | if (class_rev < 6) |
502 | return -ENODEV; | 515 | return -ENODEV; |
503 | break; | 516 | break; |
517 | case PCI_DEVICE_ID_TTI_HPT371: | ||
518 | if (class_rev < 2) | ||
519 | return -ENODEV; | ||
520 | /* 371N if rev > 1 */ | ||
521 | break; | ||
504 | case PCI_DEVICE_ID_TTI_HPT372: | 522 | case PCI_DEVICE_ID_TTI_HPT372: |
505 | /* 372N if rev >= 1*/ | 523 | /* 372N if rev >= 1*/ |
506 | if (class_rev == 0) | 524 | if (class_rev == 0) |
@@ -528,6 +546,19 @@ static int hpt3x2n_init_one(struct pci_dev *dev, const struct pci_device_id *id) | |||
528 | irqmask &= ~0x10; | 546 | irqmask &= ~0x10; |
529 | pci_write_config_byte(dev, 0x5a, irqmask); | 547 | pci_write_config_byte(dev, 0x5a, irqmask); |
530 | 548 | ||
549 | /* | ||
550 | * HPT371 chips physically have only one channel, the secondary one, | ||
551 | * but the primary channel registers do exist! Go figure... | ||
552 | * So, we manually disable the non-existing channel here | ||
553 | * (if the BIOS hasn't done this already). | ||
554 | */ | ||
555 | if (dev->device == PCI_DEVICE_ID_TTI_HPT371) { | ||
556 | u8 mcr1; | ||
557 | pci_read_config_byte(dev, 0x50, &mcr1); | ||
558 | mcr1 &= ~0x04; | ||
559 | pci_write_config_byte(dev, 0x50, mcr1); | ||
560 | } | ||
561 | |||
531 | /* Tune the PLL. HPT recommend using 75 for SATA, 66 for UDMA133 or | 562 | /* Tune the PLL. HPT recommend using 75 for SATA, 66 for UDMA133 or |
532 | 50 for UDMA100. Right now we always use 66 */ | 563 | 50 for UDMA100. Right now we always use 66 */ |
533 | 564 | ||
@@ -546,14 +577,24 @@ static int hpt3x2n_init_one(struct pci_dev *dev, const struct pci_device_id *id) | |||
546 | break; | 577 | break; |
547 | pci_write_config_dword(dev, 0x5C, (f_high << 16) | f_low); | 578 | pci_write_config_dword(dev, 0x5C, (f_high << 16) | f_low); |
548 | } | 579 | } |
549 | if (adjust == 8) | 580 | if (adjust == 8) { |
550 | printk(KERN_WARNING "hpt3xn: DPLL did not stabilize.\n"); | 581 | printk(KERN_WARNING "hpt3x2n: DPLL did not stabilize.\n"); |
582 | return -ENODEV; | ||
583 | } | ||
551 | 584 | ||
552 | /* Set our private data up. We only need a few flags so we use | 585 | /* Set our private data up. We only need a few flags so we use |
553 | it directly */ | 586 | it directly */ |
554 | port->private_data = NULL; | 587 | port->private_data = NULL; |
555 | if (pci_mhz > 60) | 588 | if (pci_mhz > 60) { |
556 | port->private_data = (void *)PCI66; | 589 | port->private_data = (void *)PCI66; |
590 | /* | ||
591 | * On HPT371N, if ATA clock is 66 MHz we must set bit 2 in | ||
592 | * the MISC. register to stretch the UltraDMA Tss timing. | ||
593 | * NOTE: This register is only writeable via I/O space. | ||
594 | */ | ||
595 | if (dev->device == PCI_DEVICE_ID_TTI_HPT371) | ||
596 | outb(inb(iobase + 0x9c) | 0x04, iobase + 0x9c); | ||
597 | } | ||
557 | 598 | ||
558 | /* Now kick off ATA set up */ | 599 | /* Now kick off ATA set up */ |
559 | port_info[0] = port_info[1] = port; | 600 | port_info[0] = port_info[1] = port; |
@@ -562,6 +603,7 @@ static int hpt3x2n_init_one(struct pci_dev *dev, const struct pci_device_id *id) | |||
562 | 603 | ||
563 | static const struct pci_device_id hpt3x2n[] = { | 604 | static const struct pci_device_id hpt3x2n[] = { |
564 | { PCI_VDEVICE(TTI, PCI_DEVICE_ID_TTI_HPT366), }, | 605 | { PCI_VDEVICE(TTI, PCI_DEVICE_ID_TTI_HPT366), }, |
606 | { PCI_VDEVICE(TTI, PCI_DEVICE_ID_TTI_HPT371), }, | ||
565 | { PCI_VDEVICE(TTI, PCI_DEVICE_ID_TTI_HPT372), }, | 607 | { PCI_VDEVICE(TTI, PCI_DEVICE_ID_TTI_HPT372), }, |
566 | { PCI_VDEVICE(TTI, PCI_DEVICE_ID_TTI_HPT302), }, | 608 | { PCI_VDEVICE(TTI, PCI_DEVICE_ID_TTI_HPT302), }, |
567 | { PCI_VDEVICE(TTI, PCI_DEVICE_ID_TTI_HPT372N), }, | 609 | { PCI_VDEVICE(TTI, PCI_DEVICE_ID_TTI_HPT372N), }, |