X-Git-Url: http://git.rot13.org/?a=blobdiff_plain;f=drivers%2Fata%2Fpata_hpt3x2n.c;h=ea1037d6786028bbaaf1312a504ee407b66148e6;hb=d4b2bab4f26345ea1803feb23ea92fbe3f6b77bc;hp=f6817b4093a4e8ff3d74a5dc2e487858a9d00c79;hpb=cfee47f99bc14a6d7c6b0be2284db2cef310a815;p=powerpc.git diff --git a/drivers/ata/pata_hpt3x2n.c b/drivers/ata/pata_hpt3x2n.c index f6817b4093..ea1037d678 100644 --- a/drivers/ata/pata_hpt3x2n.c +++ b/drivers/ata/pata_hpt3x2n.c @@ -8,10 +8,10 @@ * Copyright (C) 1999-2003 Andre Hedrick * Portions Copyright (C) 2001 Sun Microsystems, Inc. * Portions Copyright (C) 2003 Red Hat Inc + * Portions Copyright (C) 2005-2006 MontaVista Software, Inc. * * * TODO - * 371N * Work out best PLL policy */ @@ -25,7 +25,7 @@ #include #define DRV_NAME "pata_hpt3x2n" -#define DRV_VERSION "0.3" +#define DRV_VERSION "0.3.3" enum { HPT_PCI_FAST = (1 << 31), @@ -115,14 +115,13 @@ static u32 hpt3x2n_find_mode(struct ata_port *ap, int speed) } /** - * hpt3x2n_pre_reset - reset the hpt3x2n bus - * @ap: ATA port to reset + * hpt3x2n_cable_detect - Detect the cable type + * @ap: ATA port to detect on * - * Perform the initial reset handling for the 3x2n series controllers. - * Reset the hardware and state machine, obtain the cable type. + * Return the cable type attached to this port */ -static int hpt3xn_pre_reset(struct ata_port *ap) +static int hpt3x2n_cable_detect(struct ata_port *ap) { u8 scr2, ata66; struct pci_dev *pdev = to_pci_dev(ap->host->dev); @@ -135,16 +134,28 @@ static int hpt3xn_pre_reset(struct ata_port *ap) pci_write_config_byte(pdev, 0x5B, scr2); if (ata66 & (1 << ap->port_no)) - ap->cbl = ATA_CBL_PATA40; + return ATA_CBL_PATA40; else - ap->cbl = ATA_CBL_PATA80; + return ATA_CBL_PATA80; +} + +/** + * hpt3x2n_pre_reset - reset the hpt3x2n bus + * @ap: ATA port to reset + * @deadline: deadline jiffies for the operation + * + * Perform the initial reset handling for the 3x2n series controllers. + * Reset the hardware and state machine, + */ +static int hpt3xn_pre_reset(struct ata_port *ap, unsigned long deadline) +{ + struct pci_dev *pdev = to_pci_dev(ap->host->dev); /* Reset the state machine */ - pci_write_config_byte(pdev, 0x50, 0x37); - pci_write_config_byte(pdev, 0x54, 0x37); + pci_write_config_byte(pdev, 0x50 + 4 * ap->port_no, 0x37); udelay(100); - return ata_std_prereset(ap); + return ata_std_prereset(ap, deadline); } /** @@ -263,26 +274,26 @@ static void hpt3x2n_bmdma_stop(struct ata_queued_cmd *qc) static void hpt3x2n_set_clock(struct ata_port *ap, int source) { - unsigned long bmdma = ap->ioaddr.bmdma_addr; + void __iomem *bmdma = ap->ioaddr.bmdma_addr; /* Tristate the bus */ - outb(0x80, bmdma+0x73); - outb(0x80, bmdma+0x77); + iowrite8(0x80, bmdma+0x73); + iowrite8(0x80, bmdma+0x77); /* Switch clock and reset channels */ - outb(source, bmdma+0x7B); - outb(0xC0, bmdma+0x79); + iowrite8(source, bmdma+0x7B); + iowrite8(0xC0, bmdma+0x79); /* Reset state machines */ - outb(0x37, bmdma+0x70); - outb(0x37, bmdma+0x74); + iowrite8(0x37, bmdma+0x70); + iowrite8(0x37, bmdma+0x74); /* Complete reset */ - outb(0x00, bmdma+0x79); + iowrite8(0x00, bmdma+0x79); /* Reconnect channels to bus */ - outb(0x00, bmdma+0x73); - outb(0x00, bmdma+0x77); + iowrite8(0x00, bmdma+0x73); + iowrite8(0x00, bmdma+0x77); } /* Check if our partner interface is busy */ @@ -297,11 +308,11 @@ static int hpt3x2n_pair_idle(struct ata_port *ap) return 0; } -static int hpt3x2n_use_dpll(struct ata_port *ap, int reading) +static int hpt3x2n_use_dpll(struct ata_port *ap, int writing) { long flags = (long)ap->host->private_data; /* See if we should use the DPLL */ - if (reading == 0) + if (writing) return USE_DPLL; /* Needed for write */ if (flags & PCI66) return USE_DPLL; /* Needed at 66Mhz */ @@ -364,6 +375,7 @@ static struct ata_port_operations hpt3x2n_port_ops = { .thaw = ata_bmdma_thaw, .error_handler = hpt3x2n_error_handler, .post_internal_cmd = ata_bmdma_post_internal_cmd, + .cable_detect = hpt3x2n_cable_detect, .bmdma_setup = ata_bmdma_setup, .bmdma_start = ata_bmdma_start, @@ -373,14 +385,14 @@ static struct ata_port_operations hpt3x2n_port_ops = { .qc_prep = ata_qc_prep, .qc_issue = hpt3x2n_qc_issue_prot, - .data_xfer = ata_pio_data_xfer, + .data_xfer = ata_data_xfer, .irq_handler = ata_interrupt, .irq_clear = ata_bmdma_irq_clear, + .irq_on = ata_irq_on, + .irq_ack = ata_irq_ack, .port_start = ata_port_start, - .port_stop = ata_port_stop, - .host_stop = ata_host_stop }; /** @@ -422,8 +434,9 @@ static int hpt3x2n_pci_clock(struct pci_dev *pdev) { unsigned long freq; u32 fcnt; + unsigned long iobase = pci_resource_start(pdev, 4); - pci_read_config_dword(pdev, 0x70/*CHECKME*/, &fcnt); + fcnt = inl(iobase + 0x90); /* Not PCI readable for some chips */ if ((fcnt >> 12) != 0xABCDE) { printk(KERN_WARNING "hpt3xn: BIOS clock data not set.\n"); return 33; /* Not BIOS set */ @@ -492,6 +505,7 @@ static int hpt3x2n_init_one(struct pci_dev *dev, const struct pci_device_id *id) unsigned int pci_mhz; unsigned int f_low, f_high; int adjust; + unsigned long iobase = pci_resource_start(dev, 4); pci_read_config_dword(dev, PCI_CLASS_REVISION, &class_rev); class_rev &= 0xFF; @@ -501,6 +515,11 @@ static int hpt3x2n_init_one(struct pci_dev *dev, const struct pci_device_id *id) if (class_rev < 6) return -ENODEV; break; + case PCI_DEVICE_ID_TTI_HPT371: + if (class_rev < 2) + return -ENODEV; + /* 371N if rev > 1 */ + break; case PCI_DEVICE_ID_TTI_HPT372: /* 372N if rev >= 1*/ if (class_rev == 0) @@ -528,6 +547,19 @@ static int hpt3x2n_init_one(struct pci_dev *dev, const struct pci_device_id *id) irqmask &= ~0x10; pci_write_config_byte(dev, 0x5a, irqmask); + /* + * HPT371 chips physically have only one channel, the secondary one, + * but the primary channel registers do exist! Go figure... + * So, we manually disable the non-existing channel here + * (if the BIOS hasn't done this already). + */ + if (dev->device == PCI_DEVICE_ID_TTI_HPT371) { + u8 mcr1; + pci_read_config_byte(dev, 0x50, &mcr1); + mcr1 &= ~0x04; + pci_write_config_byte(dev, 0x50, mcr1); + } + /* Tune the PLL. HPT recommend using 75 for SATA, 66 for UDMA133 or 50 for UDMA100. Right now we always use 66 */ @@ -546,14 +578,24 @@ static int hpt3x2n_init_one(struct pci_dev *dev, const struct pci_device_id *id) break; pci_write_config_dword(dev, 0x5C, (f_high << 16) | f_low); } - if (adjust == 8) - printk(KERN_WARNING "hpt3xn: DPLL did not stabilize.\n"); + if (adjust == 8) { + printk(KERN_WARNING "hpt3x2n: DPLL did not stabilize.\n"); + return -ENODEV; + } /* Set our private data up. We only need a few flags so we use it directly */ port->private_data = NULL; - if (pci_mhz > 60) + if (pci_mhz > 60) { port->private_data = (void *)PCI66; + /* + * On HPT371N, if ATA clock is 66 MHz we must set bit 2 in + * the MISC. register to stretch the UltraDMA Tss timing. + * NOTE: This register is only writeable via I/O space. + */ + if (dev->device == PCI_DEVICE_ID_TTI_HPT371) + outb(inb(iobase + 0x9c) | 0x04, iobase + 0x9c); + } /* Now kick off ATA set up */ port_info[0] = port_info[1] = port; @@ -562,6 +604,7 @@ static int hpt3x2n_init_one(struct pci_dev *dev, const struct pci_device_id *id) static const struct pci_device_id hpt3x2n[] = { { PCI_VDEVICE(TTI, PCI_DEVICE_ID_TTI_HPT366), }, + { PCI_VDEVICE(TTI, PCI_DEVICE_ID_TTI_HPT371), }, { PCI_VDEVICE(TTI, PCI_DEVICE_ID_TTI_HPT372), }, { PCI_VDEVICE(TTI, PCI_DEVICE_ID_TTI_HPT302), }, { PCI_VDEVICE(TTI, PCI_DEVICE_ID_TTI_HPT372N), },