From 9e87be9edd9114b65a9cf4f93a60b5d9134a972e Mon Sep 17 00:00:00 2001 From: Bartlomiej Zolnierkiewicz Date: Thu, 19 Nov 2009 19:10:44 +0100 Subject: pata_hpt37x: add proper cable detection methods Signed-off-by: Bartlomiej Zolnierkiewicz Signed-off-by: Jeff Garzik --- drivers/ata/pata_hpt37x.c | 86 ++++++++++++++++++++++++++++++----------------- 1 file changed, 56 insertions(+), 30 deletions(-) (limited to 'drivers/ata/pata_hpt37x.c') diff --git a/drivers/ata/pata_hpt37x.c b/drivers/ata/pata_hpt37x.c index d0a7df2e5ca..378a8f862e8 100644 --- a/drivers/ata/pata_hpt37x.c +++ b/drivers/ata/pata_hpt37x.c @@ -302,6 +302,59 @@ static unsigned long hpt370a_filter(struct ata_device *adev, unsigned long mask) return ata_bmdma_mode_filter(adev, mask); } +/** + * hpt37x_cable_detect - Detect the cable type + * @ap: ATA port to detect on + * + * Return the cable type attached to this port + */ + +static int hpt37x_cable_detect(struct ata_port *ap) +{ + struct pci_dev *pdev = to_pci_dev(ap->host->dev); + u8 scr2, ata66; + + pci_read_config_byte(pdev, 0x5B, &scr2); + pci_write_config_byte(pdev, 0x5B, scr2 & ~0x01); + /* Cable register now active */ + pci_read_config_byte(pdev, 0x5A, &ata66); + /* Restore state */ + pci_write_config_byte(pdev, 0x5B, scr2); + + if (ata66 & (2 >> ap->port_no)) + return ATA_CBL_PATA40; + else + return ATA_CBL_PATA80; +} + +/** + * hpt374_fn1_cable_detect - Detect the cable type + * @ap: ATA port to detect on + * + * Return the cable type attached to this port + */ + +static int hpt374_fn1_cable_detect(struct ata_port *ap) +{ + struct pci_dev *pdev = to_pci_dev(ap->host->dev); + unsigned int mcrbase = 0x50 + 4 * ap->port_no; + u16 mcr3; + u8 ata66; + + /* Do the extra channel work */ + pci_read_config_word(pdev, mcrbase + 2, &mcr3); + /* Set bit 15 of 0x52 to enable TCBLID as input */ + pci_write_config_word(pdev, mcrbase + 2, mcr3 | 0x8000); + pci_read_config_byte(pdev, 0x5A, &ata66); + /* Reset TCBLID/FCBLID to output */ + pci_write_config_word(pdev, mcrbase + 2, mcr3); + + if (ata66 & (2 >> ap->port_no)) + return ATA_CBL_PATA40; + else + return ATA_CBL_PATA80; +} + /** * hpt37x_pre_reset - reset the hpt37x bus * @link: ATA link to reset @@ -312,7 +365,6 @@ static unsigned long hpt370a_filter(struct ata_device *adev, unsigned long mask) static int hpt37x_pre_reset(struct ata_link *link, unsigned long deadline) { - u8 scr2, ata66; struct ata_port *ap = link->ap; struct pci_dev *pdev = to_pci_dev(ap->host->dev); static const struct pci_bits hpt37x_enable_bits[] = { @@ -322,18 +374,6 @@ static int hpt37x_pre_reset(struct ata_link *link, unsigned long deadline) if (!pci_test_config_bits(pdev, &hpt37x_enable_bits[ap->port_no])) return -ENOENT; - pci_read_config_byte(pdev, 0x5B, &scr2); - pci_write_config_byte(pdev, 0x5B, scr2 & ~0x01); - /* Cable register now active */ - pci_read_config_byte(pdev, 0x5A, &ata66); - /* Restore state */ - pci_write_config_byte(pdev, 0x5B, scr2); - - if (ata66 & (2 >> ap->port_no)) - ap->cbl = ATA_CBL_PATA40; - else - ap->cbl = ATA_CBL_PATA80; - /* Reset the state machine */ pci_write_config_byte(pdev, 0x50 + 4 * ap->port_no, 0x37); udelay(100); @@ -347,29 +387,12 @@ static int hpt374_fn1_pre_reset(struct ata_link *link, unsigned long deadline) { 0x50, 1, 0x04, 0x04 }, { 0x54, 1, 0x04, 0x04 } }; - u16 mcr3; - u8 ata66; struct ata_port *ap = link->ap; struct pci_dev *pdev = to_pci_dev(ap->host->dev); - unsigned int mcrbase = 0x50 + 4 * ap->port_no; if (!pci_test_config_bits(pdev, &hpt37x_enable_bits[ap->port_no])) return -ENOENT; - /* Do the extra channel work */ - pci_read_config_word(pdev, mcrbase + 2, &mcr3); - /* Set bit 15 of 0x52 to enable TCBLID as input - */ - pci_write_config_word(pdev, mcrbase + 2, mcr3 | 0x8000); - pci_read_config_byte(pdev, 0x5A, &ata66); - /* Reset TCBLID/FCBLID to output */ - pci_write_config_word(pdev, mcrbase + 2, mcr3); - - if (ata66 & (2 >> ap->port_no)) - ap->cbl = ATA_CBL_PATA40; - else - ap->cbl = ATA_CBL_PATA80; - /* Reset the state machine */ pci_write_config_byte(pdev, 0x50 + 4 * ap->port_no, 0x37); udelay(100); @@ -584,6 +607,7 @@ static struct ata_port_operations hpt370_port_ops = { .bmdma_stop = hpt370_bmdma_stop, .mode_filter = hpt370_filter, + .cable_detect = hpt37x_cable_detect, .set_piomode = hpt370_set_piomode, .set_dmamode = hpt370_set_dmamode, .prereset = hpt37x_pre_reset, @@ -608,6 +632,7 @@ static struct ata_port_operations hpt372_port_ops = { .bmdma_stop = hpt37x_bmdma_stop, + .cable_detect = hpt37x_cable_detect, .set_piomode = hpt372_set_piomode, .set_dmamode = hpt372_set_dmamode, .prereset = hpt37x_pre_reset, @@ -620,6 +645,7 @@ static struct ata_port_operations hpt372_port_ops = { static struct ata_port_operations hpt374_fn1_port_ops = { .inherits = &hpt372_port_ops, + .cable_detect = hpt374_fn1_cable_detect, .prereset = hpt374_fn1_pre_reset, }; -- cgit v1.2.3-18-g5258 From ab81a505ae6be069be5b67acd7e1bab3cfb53968 Mon Sep 17 00:00:00 2001 From: Bartlomiej Zolnierkiewicz Date: Thu, 19 Nov 2009 19:12:24 +0100 Subject: pata_hpt37x: unify ->pre_reset methods We can use the same ->pre_reset method for all HPT37x chipsets now. Signed-off-by: Bartlomiej Zolnierkiewicz Signed-off-by: Jeff Garzik --- drivers/ata/pata_hpt37x.c | 23 ++--------------------- 1 file changed, 2 insertions(+), 21 deletions(-) (limited to 'drivers/ata/pata_hpt37x.c') diff --git a/drivers/ata/pata_hpt37x.c b/drivers/ata/pata_hpt37x.c index 378a8f862e8..0921e8b30a0 100644 --- a/drivers/ata/pata_hpt37x.c +++ b/drivers/ata/pata_hpt37x.c @@ -360,7 +360,7 @@ static int hpt374_fn1_cable_detect(struct ata_port *ap) * @link: ATA link to reset * @deadline: deadline jiffies for the operation * - * Perform the initial reset handling for the 370/372 and 374 func 0 + * Perform the initial reset handling for the HPT37x. */ static int hpt37x_pre_reset(struct ata_link *link, unsigned long deadline) @@ -381,25 +381,6 @@ static int hpt37x_pre_reset(struct ata_link *link, unsigned long deadline) return ata_sff_prereset(link, deadline); } -static int hpt374_fn1_pre_reset(struct ata_link *link, unsigned long deadline) -{ - static const struct pci_bits hpt37x_enable_bits[] = { - { 0x50, 1, 0x04, 0x04 }, - { 0x54, 1, 0x04, 0x04 } - }; - struct ata_port *ap = link->ap; - struct pci_dev *pdev = to_pci_dev(ap->host->dev); - - if (!pci_test_config_bits(pdev, &hpt37x_enable_bits[ap->port_no])) - return -ENOENT; - - /* Reset the state machine */ - pci_write_config_byte(pdev, 0x50 + 4 * ap->port_no, 0x37); - udelay(100); - - return ata_sff_prereset(link, deadline); -} - /** * hpt370_set_piomode - PIO setup * @ap: ATA interface @@ -646,7 +627,7 @@ static struct ata_port_operations hpt372_port_ops = { static struct ata_port_operations hpt374_fn1_port_ops = { .inherits = &hpt372_port_ops, .cable_detect = hpt374_fn1_cable_detect, - .prereset = hpt374_fn1_pre_reset, + .prereset = hpt37x_pre_reset, }; /** -- cgit v1.2.3-18-g5258 From 10a9c969222de5302cff0bb41dd7f114f9aa8e5d Mon Sep 17 00:00:00 2001 From: Bartlomiej Zolnierkiewicz Date: Thu, 19 Nov 2009 20:31:31 +0100 Subject: pata_hpt{37x,3x2n}: add debounce delay to cable detection methods Alan Cox reported that cable detection sometimes works unreliably for HPT3xxN and that the issue is fixed by adding debounce delay as used by the vendor driver. Sergei Shtylyov also noticed that debounce delay is needed for all HPT37x and HPT3xxN chipsets according to vendor drivers. Signed-off-by: Bartlomiej Zolnierkiewicz Signed-off-by: Jeff Garzik --- drivers/ata/pata_hpt37x.c | 3 +++ 1 file changed, 3 insertions(+) (limited to 'drivers/ata/pata_hpt37x.c') diff --git a/drivers/ata/pata_hpt37x.c b/drivers/ata/pata_hpt37x.c index 0921e8b30a0..9f5189c700b 100644 --- a/drivers/ata/pata_hpt37x.c +++ b/drivers/ata/pata_hpt37x.c @@ -316,6 +316,9 @@ static int hpt37x_cable_detect(struct ata_port *ap) pci_read_config_byte(pdev, 0x5B, &scr2); pci_write_config_byte(pdev, 0x5B, scr2 & ~0x01); + + udelay(10); /* debounce */ + /* Cable register now active */ pci_read_config_byte(pdev, 0x5A, &ata66); /* Restore state */ -- cgit v1.2.3-18-g5258 From 5600c70e576199a7552e1c0fff43f3fe16f5566e Mon Sep 17 00:00:00 2001 From: Sergei Shtylyov Date: Fri, 27 Nov 2009 22:29:02 +0400 Subject: pata_hpt{37x|3x2n}: fix timing register masks (take 2) These drivers inherited from the older 'hpt366' IDE driver the buggy timing register masks in their set_piomode() metods. As a result, too low command cycle active time is programmed for slow PIO modes. Quite fortunately, it's later "fixed up" by the set_dmamode() methods which also "helpfully" reprogram the command timings, usually to PIO mode 4; unfortunately, setting an UltraDMA mode #N also reprograms already set PIO data timings, usually to MWDMA mode # max(N, 2) timings... However, the drivers added some breakage of their own too: the bit that they set/clear to control the FIFO is sometimes wrong -- it's actually the MSB of the command cycle setup time; also, setting it in DMA mode is wrong as this bit is only for PIO actually and clearing it for PIO modes is not needed as no mode in any timing table has it set... Fix all this, inverting the masks while at it, like in the 'hpt366' and 'pata_hpt366' drivers; bump the drivers' versions, accounting for recent patches that forgot to do it... Signed-off-by: Sergei Shtylyov Cc: stable@kernel.org Signed-off-by: Jeff Garzik --- drivers/ata/pata_hpt37x.c | 32 +++++++++++++++----------------- 1 file changed, 15 insertions(+), 17 deletions(-) (limited to 'drivers/ata/pata_hpt37x.c') diff --git a/drivers/ata/pata_hpt37x.c b/drivers/ata/pata_hpt37x.c index 9f5189c700b..defd9b8456e 100644 --- a/drivers/ata/pata_hpt37x.c +++ b/drivers/ata/pata_hpt37x.c @@ -24,7 +24,7 @@ #include #define DRV_NAME "pata_hpt37x" -#define DRV_VERSION "0.6.12" +#define DRV_VERSION "0.6.14" struct hpt_clock { u8 xfer_speed; @@ -411,9 +411,8 @@ static void hpt370_set_piomode(struct ata_port *ap, struct ata_device *adev) pci_read_config_dword(pdev, addr1, ®); mode = hpt37x_find_mode(ap, adev->pio_mode); - mode &= ~0x8000000; /* No FIFO in PIO */ - mode &= ~0x30070000; /* Leave config bits alone */ - reg &= 0x30070000; /* Strip timing bits */ + mode &= 0xCFC3FFFF; /* Leave DMA bits alone */ + reg &= ~0xCFC3FFFF; /* Strip timing bits */ pci_write_config_dword(pdev, addr1, reg | mode); } @@ -430,8 +429,7 @@ static void hpt370_set_dmamode(struct ata_port *ap, struct ata_device *adev) { struct pci_dev *pdev = to_pci_dev(ap->host->dev); u32 addr1, addr2; - u32 reg; - u32 mode; + u32 reg, mode, mask; u8 fast; addr1 = 0x40 + 4 * (adev->devno + 2 * ap->port_no); @@ -443,11 +441,12 @@ static void hpt370_set_dmamode(struct ata_port *ap, struct ata_device *adev) fast |= 0x01; pci_write_config_byte(pdev, addr2, fast); + mask = adev->dma_mode < XFER_UDMA_0 ? 0x31C001FF : 0x303C0000; + pci_read_config_dword(pdev, addr1, ®); mode = hpt37x_find_mode(ap, adev->dma_mode); - mode |= 0x8000000; /* FIFO in MWDMA or UDMA */ - mode &= ~0xC0000000; /* Leave config bits alone */ - reg &= 0xC0000000; /* Strip timing bits */ + mode &= mask; + reg &= ~mask; pci_write_config_dword(pdev, addr1, reg | mode); } @@ -515,9 +514,8 @@ static void hpt372_set_piomode(struct ata_port *ap, struct ata_device *adev) mode = hpt37x_find_mode(ap, adev->pio_mode); printk("Find mode for %d reports %X\n", adev->pio_mode, mode); - mode &= ~0x80000000; /* No FIFO in PIO */ - mode &= ~0x30070000; /* Leave config bits alone */ - reg &= 0x30070000; /* Strip timing bits */ + mode &= 0xCFC3FFFF; /* Leave DMA bits alone */ + reg &= ~0xCFC3FFFF; /* Strip timing bits */ pci_write_config_dword(pdev, addr1, reg | mode); } @@ -534,8 +532,7 @@ static void hpt372_set_dmamode(struct ata_port *ap, struct ata_device *adev) { struct pci_dev *pdev = to_pci_dev(ap->host->dev); u32 addr1, addr2; - u32 reg; - u32 mode; + u32 reg, mode, mask; u8 fast; addr1 = 0x40 + 4 * (adev->devno + 2 * ap->port_no); @@ -546,12 +543,13 @@ static void hpt372_set_dmamode(struct ata_port *ap, struct ata_device *adev) fast &= ~0x07; pci_write_config_byte(pdev, addr2, fast); + mask = adev->dma_mode < XFER_UDMA_0 ? 0x31C001FF : 0x303C0000; + pci_read_config_dword(pdev, addr1, ®); mode = hpt37x_find_mode(ap, adev->dma_mode); printk("Find mode for DMA %d reports %X\n", adev->dma_mode, mode); - mode &= ~0xC0000000; /* Leave config bits alone */ - mode |= 0x80000000; /* FIFO in MWDMA or UDMA */ - reg &= 0xC0000000; /* Strip timing bits */ + mode &= mask; + reg &= ~mask; pci_write_config_dword(pdev, addr1, reg | mode); } -- cgit v1.2.3-18-g5258 From 89d3b3603bfb648e0113d8682d4f84dd18a776bd Mon Sep 17 00:00:00 2001 From: Sergei Shtylyov Date: Tue, 24 Nov 2009 22:54:49 +0400 Subject: ata: use pci_dev->revision Some places were using PCI_CLASS_REVISION instead of PCI_REVISION_ID, so they weren't converted by commit 44c10138fd4bbc4b6d6bff0873c24902f2a9da65 (PCI: Change all drivers to use pci_device->revision). Signed-off-by: Sergei Shtylyov Signed-off-by: Jeff Garzik --- drivers/ata/pata_hpt37x.c | 21 +++++++++------------ 1 file changed, 9 insertions(+), 12 deletions(-) (limited to 'drivers/ata/pata_hpt37x.c') diff --git a/drivers/ata/pata_hpt37x.c b/drivers/ata/pata_hpt37x.c index defd9b8456e..4224cfccede 100644 --- a/drivers/ata/pata_hpt37x.c +++ b/drivers/ata/pata_hpt37x.c @@ -799,9 +799,8 @@ static int hpt37x_init_one(struct pci_dev *dev, const struct pci_device_id *id) static const int MHz[4] = { 33, 40, 50, 66 }; void *private_data = NULL; const struct ata_port_info *ppi[] = { NULL, NULL }; - + u8 rev = dev->revision; u8 irqmask; - u32 class_rev; u8 mcr1; u32 freq; int prefer_dpll = 1; @@ -816,19 +815,16 @@ static int hpt37x_init_one(struct pci_dev *dev, const struct pci_device_id *id) if (rc) return rc; - pci_read_config_dword(dev, PCI_CLASS_REVISION, &class_rev); - class_rev &= 0xFF; - if (dev->device == PCI_DEVICE_ID_TTI_HPT366) { /* May be a later chip in disguise. Check */ /* Older chips are in the HPT366 driver. Ignore them */ - if (class_rev < 3) + if (rev < 3) return -ENODEV; /* N series chips have their own driver. Ignore */ - if (class_rev == 6) + if (rev == 6) return -ENODEV; - switch(class_rev) { + switch(rev) { case 3: ppi[0] = &info_hpt370; chip_table = &hpt370; @@ -844,28 +840,29 @@ static int hpt37x_init_one(struct pci_dev *dev, const struct pci_device_id *id) chip_table = &hpt372; break; default: - printk(KERN_ERR "pata_hpt37x: Unknown HPT366 subtype please report (%d).\n", class_rev); + printk(KERN_ERR "pata_hpt37x: Unknown HPT366 " + "subtype, please report (%d).\n", rev); return -ENODEV; } } else { switch(dev->device) { case PCI_DEVICE_ID_TTI_HPT372: /* 372N if rev >= 2*/ - if (class_rev >= 2) + if (rev >= 2) return -ENODEV; ppi[0] = &info_hpt372; chip_table = &hpt372a; break; case PCI_DEVICE_ID_TTI_HPT302: /* 302N if rev > 1 */ - if (class_rev > 1) + if (rev > 1) return -ENODEV; ppi[0] = &info_hpt372; /* Check this */ chip_table = &hpt302; break; case PCI_DEVICE_ID_TTI_HPT371: - if (class_rev > 1) + if (rev > 1) return -ENODEV; ppi[0] = &info_hpt372; chip_table = &hpt371; -- cgit v1.2.3-18-g5258