pata_hpt3x2n: Add HPT371N support and other bits
Yes its no longer 3x2n but 3xxn, I can rename it if you want Jeff - Don't reset both ports each time (Sergei) - If we can't get a DPLL then abort entirely - Use ioport access for clock (from drivers/ide) - Add HPT371N support (from drivers/ide) Signed-off-by: Alan Cox <alan@redhat.com> Signed-off-by: Andrew Morton <akpm@linux-foundation.org> Signed-off-by: Jeff Garzik <jeff@garzik.org>
This commit is contained in:
parent
bd1d5ec64f
commit
28e21c8c0d
1 changed files with 38 additions and 7 deletions
|
@ -8,10 +8,10 @@
|
|||
* Copyright (C) 1999-2003 Andre Hedrick <andre@linux-ide.org>
|
||||
* 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
|
||||
*/
|
||||
|
||||
|
@ -142,6 +142,7 @@ static int hpt3x2n_cable_detect(struct ata_port *ap)
|
|||
/**
|
||||
* 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,
|
||||
|
@ -151,8 +152,7 @@ static int hpt3xn_pre_reset(struct ata_port *ap)
|
|||
{
|
||||
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);
|
||||
}
|
||||
|
@ -433,8 +433,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 */
|
||||
|
@ -503,6 +504,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;
|
||||
|
@ -512,6 +514,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)
|
||||
|
@ -539,6 +546,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 */
|
||||
|
||||
|
@ -557,14 +577,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;
|
||||
|
@ -573,6 +603,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), },
|
||||
|
|
Loading…
Reference in a new issue