/*
* Libata driver for the highpoint 37x and 30x UDMA66 ATA controllers.
*
* This driver is heavily based upon:
*
* linux/drivers/ide/pci/hpt366.c Version 0.36 April 25, 2003
*
* 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-2010 MontaVista Software, Inc.
*
* TODO
* Look into engine reset on timeout errors. Should not be required.
*/
#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
#include <linux/kernel.h>
#include <linux/module.h>
#include <linux/pci.h>
#include <linux/blkdev.h>
#include <linux/delay.h>
#include <scsi/scsi_host.h>
#include <linux/libata.h>
#define DRV_NAME "pata_hpt37x"
#define DRV_VERSION "0.6.23"
struct hpt_clock {
u8 xfer_speed;
u32 timing;
};
struct hpt_chip {
const char *name;
unsigned int base;
struct hpt_clock const *clocks[4];
};
/* key for bus clock timings
* bit
* 0:3 data_high_time. Inactive time of DIOW_/DIOR_ for PIO and MW DMA.
* cycles = value + 1
* 4:8 data_low_time. Active time of DIOW_/DIOR_ for PIO and MW DMA.
* cycles = value + 1
* 9:12 cmd_high_time. Inactive time of DIOW_/DIOR_ during task file
* register access.
* 13:17 cmd_low_time. Active time of DIOW_/DIOR_ during task file
* register access.
* 18:20 udma_cycle_time. Clock cycles for UDMA xfer.
* 21 CLK frequency for UDMA: 0=ATA clock, 1=dual ATA clock.
* 22:24 pre_high_time. Time to initialize 1st cycle for PIO and MW DMA xfer.
* 25:27 cmd_pre_high_time. Time to initialize 1st PIO cycle for task file
* register access.
* 28 UDMA enable.
* 29 DMA enable.
* 30 PIO_MST enable. If set, the chip is in bus master mode during
* PIO xfer.
* 31 FIFO enable. Only for PIO.
*/
static struct hpt_clock hpt37x_timings_33[] = {
{ XFER_UDMA_6, 0x12446231 }, /* 0x12646231 ?? */
{ XFER_UDMA_5, 0x12446231 },
{ XFER_UDMA_4, 0x12446231 },
{ XFER_UDMA_3, 0x126c6231 },
{ XFER_UDMA_2, 0x12486231 },
{ XFER_UDMA_1, 0x124c6233 },
{ XFER_UDMA_0, 0x12506297 },
{ XFER_MW_DMA_2, 0x22406c31 },
{ XFER_MW_DMA_1, 0x22406c33 },
{ XFER_MW_DMA_0, 0x22406c97 },
{ XFER_PIO_4, 0x06414e31 },
{ XFER_PIO_3, 0x06414e42 },
{ XFER_PIO_2, 0x06414e53 },
{ XFER_PIO_1, 0x06814e93 },
{ XFER_PIO_0, 0x06814ea7 }
};
static struct hpt_clock hpt37x_timings_50[] = {
{ XFER_UDMA_6, 0x12848242 },
{ XFER_UDMA_5, 0x12848242 },
{ XFER_UDMA_4, 0x12ac8242 },
{ XFER_UDMA_3, 0x128c8242 },
{ XFER_UDMA_2, 0x120c8242 },
{ XFER_UDMA_1, 0x12148254 },
{ XFER_UDMA_0, 0x121882ea },
{ XFER_MW_DMA_2, 0x22808242 },
{ XFER_MW_DMA_1, 0x22808254 },
{ XFER_MW_DMA_0, 0x228082ea },
{ XFER_PIO_4, 0x0a81f442 },
{ XFER_PIO_3, 0x0a81f443 },
{ XFER_PIO_2, 0x0a81f454 },
{ XFER_PIO_1, 0x0ac1f465 },
{ XFER_PIO_0, 0x0ac1f48a }
};
static struct hpt_clock hpt37x_timings_66[] = {
{ XFER_UDMA_6, 0x1c869c62 },
{ XFER_UDMA_5, 0x1cae9c62 }, /* 0x1c8a9c62 */
{ XFER_UDMA_4, 0x1c8a9c62 },
{ XFER_UDMA_3, 0x1c8e9c62 },
{ XFER_UDMA_2, 0x1c929c62 },
{ XFER_UDMA_1, 0x1c9a9c62 },
{ XFER_UDMA_0, 0x1c829c62 },
{ XFER_MW_DMA_2, 0x2c829c62 },
{ XFER_MW_DMA_1, 0x2c829c66 },
{ XFER_MW_DMA_0, 0x2c829d2e },
{ XFER_PIO_4, 0x0c829c62 },
{ XFER_PIO_3, 0x0c829c84 },
{ XFER_PIO_2, 0x0c829ca6 },
{ XFER_PIO_1, 0x0d029d26 },
{ XFER_PIO_0, 0x0d029d5e }
};
static const struct hpt_chip hpt370 = {
"HPT370",
48,
{
hpt37x_timings_33,
NULL,
NULL,
NULL
}
};
static const struct hpt_chip hpt370a = {
"HPT370A",
48,
{
hpt37x_timings_33,
NULL,
hpt37x_timings_50,
NULL
}
};
static const struct hpt_chip hpt372 = {
"HPT372",
55,
{
hpt37x_timings_33,
NULL,
hpt37x_timings_50,
hpt37x_timings_66
}
};
static const struct hpt_chip hpt302 = {
"HPT302",
66,
{
hpt37x_timings_33,
NULL,
hpt37x_timings_50,
hpt37x_timings_66
}
};
static const struct hpt_chip hpt371 = {
"HPT371",
66,
{
hpt37x_timings_33,
NULL,
hpt37x_timings_50,
hpt37x_timings_66
}
};
static const struct hpt_chip hpt372a = {
"HPT372A",
66,
{
hpt37x_timings_33,
NULL,
hpt37x_timings_50,
hpt37x_timings_66
}
};
static const struct hpt_chip hpt374 = {
"HPT374",
48,
{
hpt37x_timings_33,
NULL,
NULL,
NULL
}
};
/**
* hpt37x_find_mode - reset the hpt37x bus
* @ap: ATA port
* @speed: transfer mode
*
* Return the 32bit register programming information for this channel
* that matches the speed provided.
*/
static u32 hpt37x_find_mode(struct ata_port *ap, int speed)
{
struct hpt_clock *clocks = ap->host->private_data;
while (clocks->xfer_speed) {
if (clocks->xfer_speed == speed)
return clocks->timing;
clocks++;
}
BUG();
return 0xffffffffU; /* silence compiler warning */
}
static int hpt_dma_blacklisted(const struct ata_device *dev, char *modestr,
const char * const list[])
{
unsigned char model_num[ATA_ID_PROD_LEN + 1];
int i;
ata_id_c_string(dev->id, model_num, ATA_ID_PROD, sizeof(model_num));
i = match_string(list, -1, model_num);
if (i >= 0) {
pr_warn("%s is not supported for %s\n", modestr, list[i]);
return 1;
}
return 0;
}
static const char * const bad_ata33[] = {
"Maxtor 92720U8", "Maxtor 92040U6", "Maxtor 91360U4", "Maxtor 91020U3",
"Maxtor 90845U3", "Maxtor 90650U2",
"Maxtor 91360D8&qu