/*
* 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/init.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