1
0
Fork 0

pata_hpt{37x|3x2n}: SATA mode filtering

The Marvell bridge chips used on HighPoint SATA cards do not seem to support
the UltraDMA modes 1, 2, and 3 as well as any MWDMA modes;  these cards are
based on HPT372/372A/372N/374 chips (judging from the vendor drivers), so
the Linux drivers need to have a mode_filter() method for these chips...

Signed-off-by: Sergei Shtylyov <sshtylyov@ru.mvista.com>
Signed-off-by: Jeff Garzik <jgarzik@redhat.com>
hifive-unleashed-5.1
Sergei Shtylyov 2010-12-25 22:44:01 +03:00 committed by Jeff Garzik
parent b27dcfb067
commit 8e834c2e6d
2 changed files with 93 additions and 22 deletions

View File

@ -8,7 +8,7 @@
* 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-2009 MontaVista Software, Inc.
* Portions Copyright (C) 2005-2010 MontaVista Software, Inc.
*
* TODO
* Look into engine reset on timeout errors. Should not be required.
@ -24,7 +24,7 @@
#include <linux/libata.h>
#define DRV_NAME "pata_hpt37x"
#define DRV_VERSION "0.6.15"
#define DRV_VERSION "0.6.16"
struct hpt_clock {
u8 xfer_speed;
@ -301,6 +301,22 @@ static unsigned long hpt370a_filter(struct ata_device *adev, unsigned long mask)
return mask;
}
/**
* hpt372_filter - mode selection filter
* @adev: ATA device
* @mask: mode mask
*
* The Marvell bridge chips used on the HighPoint SATA cards do not seem
* to support the UltraDMA modes 1, 2, and 3 as well as any MWDMA modes...
*/
static unsigned long hpt372_filter(struct ata_device *adev, unsigned long mask)
{
if (ata_id_is_sata(adev->id))
mask &= ~((0xE << ATA_SHIFT_UDMA) | ATA_MASK_MWDMA);
return mask;
}
/**
* hpt37x_cable_detect - Detect the cable type
* @ap: ATA port to detect on
@ -586,11 +602,11 @@ static struct ata_port_operations hpt370a_port_ops = {
};
/*
* Configuration for HPT372, HPT371, HPT302. Slightly different PIO
* and DMA mode setting functionality.
* Configuration for HPT371 and HPT302. Slightly different PIO and DMA
* mode setting functionality.
*/
static struct ata_port_operations hpt372_port_ops = {
static struct ata_port_operations hpt302_port_ops = {
.inherits = &ata_bmdma_port_ops,
.bmdma_stop = hpt37x_bmdma_stop,
@ -602,7 +618,17 @@ static struct ata_port_operations hpt372_port_ops = {
};
/*
* Configuration for HPT374. Mode setting works like 372 and friends
* Configuration for HPT372. Mode setting works like 371 and 302
* but we have a mode filter.
*/
static struct ata_port_operations hpt372_port_ops = {
.inherits = &hpt302_port_ops,
.mode_filter = hpt372_filter,
};
/*
* Configuration for HPT374. Mode setting and filtering works like 372
* but we have a different cable detection procedure for function 1.
*/
@ -753,7 +779,7 @@ static int hpt37x_init_one(struct pci_dev *dev, const struct pci_device_id *id)
.udma_mask = ATA_UDMA5,
.port_ops = &hpt370a_port_ops
};
/* HPT371, 372 and friends - UDMA133 */
/* HPT372 - UDMA133 */
static const struct ata_port_info info_hpt372 = {
.flags = ATA_FLAG_SLAVE_POSS,
.pio_mask = ATA_PIO4,
@ -761,6 +787,14 @@ static int hpt37x_init_one(struct pci_dev *dev, const struct pci_device_id *id)
.udma_mask = ATA_UDMA6,
.port_ops = &hpt372_port_ops
};
/* HPT371, 302 - UDMA133 */
static const struct ata_port_info info_hpt302 = {
.flags = ATA_FLAG_SLAVE_POSS,
.pio_mask = ATA_PIO4,
.mwdma_mask = ATA_MWDMA2,
.udma_mask = ATA_UDMA6,
.port_ops = &hpt302_port_ops
};
/* HPT374 - UDMA100, function 1 uses different prereset method */
static const struct ata_port_info info_hpt374_fn0 = {
.flags = ATA_FLAG_SLAVE_POSS,
@ -828,7 +862,7 @@ static int hpt37x_init_one(struct pci_dev *dev, const struct pci_device_id *id)
} else {
switch(dev->device) {
case PCI_DEVICE_ID_TTI_HPT372:
/* 372N if rev >= 2*/
/* 372N if rev >= 2 */
if (rev >= 2)
return -ENODEV;
ppi[0] = &info_hpt372;
@ -838,14 +872,14 @@ static int hpt37x_init_one(struct pci_dev *dev, const struct pci_device_id *id)
/* 302N if rev > 1 */
if (rev > 1)
return -ENODEV;
ppi[0] = &info_hpt372;
ppi[0] = &info_hpt302;
/* Check this */
chip_table = &hpt302;
break;
case PCI_DEVICE_ID_TTI_HPT371:
if (rev > 1)
return -ENODEV;
ppi[0] = &info_hpt372;
ppi[0] = &info_hpt302;
chip_table = &hpt371;
/* Single channel device, master is not present
but the BIOS (or us for non x86) must mark it

View File

@ -8,7 +8,7 @@
* 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-2009 MontaVista Software, Inc.
* Portions Copyright (C) 2005-2010 MontaVista Software, Inc.
*
*
* TODO
@ -25,7 +25,7 @@
#include <linux/libata.h>
#define DRV_NAME "pata_hpt3x2n"
#define DRV_VERSION "0.3.10"
#define DRV_VERSION "0.3.11"
enum {
HPT_PCI_FAST = (1 << 31),
@ -112,6 +112,22 @@ static u32 hpt3x2n_find_mode(struct ata_port *ap, int speed)
return 0xffffffffU; /* silence compiler warning */
}
/**
* hpt372n_filter - mode selection filter
* @adev: ATA device
* @mask: mode mask
*
* The Marvell bridge chips used on the HighPoint SATA cards do not seem
* to support the UltraDMA modes 1, 2, and 3 as well as any MWDMA modes...
*/
static unsigned long hpt372n_filter(struct ata_device *adev, unsigned long mask)
{
if (ata_id_is_sata(adev->id))
mask &= ~((0xE << ATA_SHIFT_UDMA) | ATA_MASK_MWDMA);
return mask;
}
/**
* hpt3x2n_cable_detect - Detect the cable type
* @ap: ATA port to detect on
@ -328,10 +344,10 @@ static struct scsi_host_template hpt3x2n_sht = {
};
/*
* Configuration for HPT3x2n.
* Configuration for HPT302N/371N.
*/
static struct ata_port_operations hpt3x2n_port_ops = {
static struct ata_port_operations hpt3xxn_port_ops = {
.inherits = &ata_bmdma_port_ops,
.bmdma_stop = hpt3x2n_bmdma_stop,
@ -345,6 +361,15 @@ static struct ata_port_operations hpt3x2n_port_ops = {
.prereset = hpt3x2n_pre_reset,
};
/*
* Configuration for HPT372N. Same as 302N/371N but we have a mode filter.
*/
static struct ata_port_operations hpt372n_port_ops = {
.inherits = &hpt3xxn_port_ops,
.mode_filter = &hpt372n_filter,
};
/**
* hpt3xn_calibrate_dpll - Calibrate the DPLL loop
* @dev: PCI device
@ -437,15 +462,23 @@ static int hpt3x2n_pci_clock(struct pci_dev *pdev)
static int hpt3x2n_init_one(struct pci_dev *dev, const struct pci_device_id *id)
{
/* HPT372N and friends - UDMA133 */
static const struct ata_port_info info = {
/* HPT372N - UDMA133 */
static const struct ata_port_info info_hpt372n = {
.flags = ATA_FLAG_SLAVE_POSS,
.pio_mask = ATA_PIO4,
.mwdma_mask = ATA_MWDMA2,
.udma_mask = ATA_UDMA6,
.port_ops = &hpt3x2n_port_ops
.port_ops = &hpt372n_port_ops
};
const struct ata_port_info *ppi[] = { &info, NULL };
/* HPT302N and HPT371N - UDMA133 */
static const struct ata_port_info info_hpt3xxn = {
.flags = ATA_FLAG_SLAVE_POSS,
.pio_mask = ATA_PIO4,
.mwdma_mask = ATA_MWDMA2,
.udma_mask = ATA_UDMA6,
.port_ops = &hpt3xxn_port_ops
};
const struct ata_port_info *ppi[] = { &info_hpt3xxn, NULL };
u8 rev = dev->revision;
u8 irqmask;
unsigned int pci_mhz;
@ -461,24 +494,28 @@ static int hpt3x2n_init_one(struct pci_dev *dev, const struct pci_device_id *id)
switch(dev->device) {
case PCI_DEVICE_ID_TTI_HPT366:
/* 372N if rev >= 6 */
if (rev < 6)
return -ENODEV;
break;
goto hpt372n;
case PCI_DEVICE_ID_TTI_HPT371:
/* 371N if rev >= 2 */
if (rev < 2)
return -ENODEV;
/* 371N if rev > 1 */
break;
case PCI_DEVICE_ID_TTI_HPT372:
/* 372N if rev >= 2*/
/* 372N if rev >= 2 */
if (rev < 2)
return -ENODEV;
break;
goto hpt372n;
case PCI_DEVICE_ID_TTI_HPT302:
/* 302N if rev >= 2 */
if (rev < 2)
return -ENODEV;
break;
case PCI_DEVICE_ID_TTI_HPT372N:
hpt372n:
ppi[0] = &info_hpt372n;
break;
default:
printk(KERN_ERR "pata_hpt3x2n: PCI table is bogus please report (%d).\n", dev->device);