pata_hpt366.c revision fecfda5d88dcc3775f72d6f3a55d11b77c67f878
1669a5db411d85a14f86cd92bc16bf7ab5b8aa235Jeff Garzik/*
2669a5db411d85a14f86cd92bc16bf7ab5b8aa235Jeff Garzik * Libata driver for the highpoint 366 and 368 UDMA66 ATA controllers.
3669a5db411d85a14f86cd92bc16bf7ab5b8aa235Jeff Garzik *
4669a5db411d85a14f86cd92bc16bf7ab5b8aa235Jeff Garzik * This driver is heavily based upon:
5669a5db411d85a14f86cd92bc16bf7ab5b8aa235Jeff Garzik *
6669a5db411d85a14f86cd92bc16bf7ab5b8aa235Jeff Garzik * linux/drivers/ide/pci/hpt366.c		Version 0.36	April 25, 2003
7669a5db411d85a14f86cd92bc16bf7ab5b8aa235Jeff Garzik *
8669a5db411d85a14f86cd92bc16bf7ab5b8aa235Jeff Garzik * Copyright (C) 1999-2003		Andre Hedrick <andre@linux-ide.org>
9669a5db411d85a14f86cd92bc16bf7ab5b8aa235Jeff Garzik * Portions Copyright (C) 2001	        Sun Microsystems, Inc.
10669a5db411d85a14f86cd92bc16bf7ab5b8aa235Jeff Garzik * Portions Copyright (C) 2003		Red Hat Inc
11669a5db411d85a14f86cd92bc16bf7ab5b8aa235Jeff Garzik *
12669a5db411d85a14f86cd92bc16bf7ab5b8aa235Jeff Garzik *
13669a5db411d85a14f86cd92bc16bf7ab5b8aa235Jeff Garzik * TODO
14669a5db411d85a14f86cd92bc16bf7ab5b8aa235Jeff Garzik *	Maybe PLL mode
15669a5db411d85a14f86cd92bc16bf7ab5b8aa235Jeff Garzik *	Look into engine reset on timeout errors. Should not be
16669a5db411d85a14f86cd92bc16bf7ab5b8aa235Jeff Garzik *		required.
17669a5db411d85a14f86cd92bc16bf7ab5b8aa235Jeff Garzik */
18669a5db411d85a14f86cd92bc16bf7ab5b8aa235Jeff Garzik
19669a5db411d85a14f86cd92bc16bf7ab5b8aa235Jeff Garzik
20669a5db411d85a14f86cd92bc16bf7ab5b8aa235Jeff Garzik#include <linux/kernel.h>
21669a5db411d85a14f86cd92bc16bf7ab5b8aa235Jeff Garzik#include <linux/module.h>
22669a5db411d85a14f86cd92bc16bf7ab5b8aa235Jeff Garzik#include <linux/pci.h>
23669a5db411d85a14f86cd92bc16bf7ab5b8aa235Jeff Garzik#include <linux/init.h>
24669a5db411d85a14f86cd92bc16bf7ab5b8aa235Jeff Garzik#include <linux/blkdev.h>
25669a5db411d85a14f86cd92bc16bf7ab5b8aa235Jeff Garzik#include <linux/delay.h>
26669a5db411d85a14f86cd92bc16bf7ab5b8aa235Jeff Garzik#include <scsi/scsi_host.h>
27669a5db411d85a14f86cd92bc16bf7ab5b8aa235Jeff Garzik#include <linux/libata.h>
28669a5db411d85a14f86cd92bc16bf7ab5b8aa235Jeff Garzik
29669a5db411d85a14f86cd92bc16bf7ab5b8aa235Jeff Garzik#define DRV_NAME	"pata_hpt366"
30fecfda5d88dcc3775f72d6f3a55d11b77c67f878Alan Cox#define DRV_VERSION	"0.6.1"
31669a5db411d85a14f86cd92bc16bf7ab5b8aa235Jeff Garzik
32669a5db411d85a14f86cd92bc16bf7ab5b8aa235Jeff Garzikstruct hpt_clock {
33669a5db411d85a14f86cd92bc16bf7ab5b8aa235Jeff Garzik	u8	xfer_speed;
34669a5db411d85a14f86cd92bc16bf7ab5b8aa235Jeff Garzik	u32	timing;
35669a5db411d85a14f86cd92bc16bf7ab5b8aa235Jeff Garzik};
36669a5db411d85a14f86cd92bc16bf7ab5b8aa235Jeff Garzik
37669a5db411d85a14f86cd92bc16bf7ab5b8aa235Jeff Garzik/* key for bus clock timings
38669a5db411d85a14f86cd92bc16bf7ab5b8aa235Jeff Garzik * bit
39669a5db411d85a14f86cd92bc16bf7ab5b8aa235Jeff Garzik * 0:3    data_high_time. inactive time of DIOW_/DIOR_ for PIO and MW
40669a5db411d85a14f86cd92bc16bf7ab5b8aa235Jeff Garzik *        DMA. cycles = value + 1
41669a5db411d85a14f86cd92bc16bf7ab5b8aa235Jeff Garzik * 4:8    data_low_time. active time of DIOW_/DIOR_ for PIO and MW
42669a5db411d85a14f86cd92bc16bf7ab5b8aa235Jeff Garzik *        DMA. cycles = value + 1
43669a5db411d85a14f86cd92bc16bf7ab5b8aa235Jeff Garzik * 9:12   cmd_high_time. inactive time of DIOW_/DIOR_ during task file
44669a5db411d85a14f86cd92bc16bf7ab5b8aa235Jeff Garzik *        register access.
45669a5db411d85a14f86cd92bc16bf7ab5b8aa235Jeff Garzik * 13:17  cmd_low_time. active time of DIOW_/DIOR_ during task file
46669a5db411d85a14f86cd92bc16bf7ab5b8aa235Jeff Garzik *        register access.
47669a5db411d85a14f86cd92bc16bf7ab5b8aa235Jeff Garzik * 18:21  udma_cycle_time. clock freq and clock cycles for UDMA xfer.
48669a5db411d85a14f86cd92bc16bf7ab5b8aa235Jeff Garzik *        during task file register access.
49669a5db411d85a14f86cd92bc16bf7ab5b8aa235Jeff Garzik * 22:24  pre_high_time. time to initialize 1st cycle for PIO and MW DMA
50669a5db411d85a14f86cd92bc16bf7ab5b8aa235Jeff Garzik *        xfer.
51669a5db411d85a14f86cd92bc16bf7ab5b8aa235Jeff Garzik * 25:27  cmd_pre_high_time. time to initialize 1st PIO cycle for task
52669a5db411d85a14f86cd92bc16bf7ab5b8aa235Jeff Garzik *        register access.
53669a5db411d85a14f86cd92bc16bf7ab5b8aa235Jeff Garzik * 28     UDMA enable
54669a5db411d85a14f86cd92bc16bf7ab5b8aa235Jeff Garzik * 29     DMA enable
55669a5db411d85a14f86cd92bc16bf7ab5b8aa235Jeff Garzik * 30     PIO_MST enable. if set, the chip is in bus master mode during
56669a5db411d85a14f86cd92bc16bf7ab5b8aa235Jeff Garzik *        PIO.
57669a5db411d85a14f86cd92bc16bf7ab5b8aa235Jeff Garzik * 31     FIFO enable.
58669a5db411d85a14f86cd92bc16bf7ab5b8aa235Jeff Garzik */
59669a5db411d85a14f86cd92bc16bf7ab5b8aa235Jeff Garzik
60669a5db411d85a14f86cd92bc16bf7ab5b8aa235Jeff Garzikstatic const struct hpt_clock hpt366_40[] = {
61669a5db411d85a14f86cd92bc16bf7ab5b8aa235Jeff Garzik	{	XFER_UDMA_4,	0x900fd943	},
62669a5db411d85a14f86cd92bc16bf7ab5b8aa235Jeff Garzik	{	XFER_UDMA_3,	0x900ad943	},
63669a5db411d85a14f86cd92bc16bf7ab5b8aa235Jeff Garzik	{	XFER_UDMA_2,	0x900bd943	},
64669a5db411d85a14f86cd92bc16bf7ab5b8aa235Jeff Garzik	{	XFER_UDMA_1,	0x9008d943	},
65669a5db411d85a14f86cd92bc16bf7ab5b8aa235Jeff Garzik	{	XFER_UDMA_0,	0x9008d943	},
66669a5db411d85a14f86cd92bc16bf7ab5b8aa235Jeff Garzik
67669a5db411d85a14f86cd92bc16bf7ab5b8aa235Jeff Garzik	{	XFER_MW_DMA_2,	0xa008d943	},
68669a5db411d85a14f86cd92bc16bf7ab5b8aa235Jeff Garzik	{	XFER_MW_DMA_1,	0xa010d955	},
69669a5db411d85a14f86cd92bc16bf7ab5b8aa235Jeff Garzik	{	XFER_MW_DMA_0,	0xa010d9fc	},
70669a5db411d85a14f86cd92bc16bf7ab5b8aa235Jeff Garzik
71669a5db411d85a14f86cd92bc16bf7ab5b8aa235Jeff Garzik	{	XFER_PIO_4,	0xc008d963	},
72669a5db411d85a14f86cd92bc16bf7ab5b8aa235Jeff Garzik	{	XFER_PIO_3,	0xc010d974	},
73669a5db411d85a14f86cd92bc16bf7ab5b8aa235Jeff Garzik	{	XFER_PIO_2,	0xc010d997	},
74669a5db411d85a14f86cd92bc16bf7ab5b8aa235Jeff Garzik	{	XFER_PIO_1,	0xc010d9c7	},
75669a5db411d85a14f86cd92bc16bf7ab5b8aa235Jeff Garzik	{	XFER_PIO_0,	0xc018d9d9	},
76669a5db411d85a14f86cd92bc16bf7ab5b8aa235Jeff Garzik	{	0,		0x0120d9d9	}
77669a5db411d85a14f86cd92bc16bf7ab5b8aa235Jeff Garzik};
78669a5db411d85a14f86cd92bc16bf7ab5b8aa235Jeff Garzik
79669a5db411d85a14f86cd92bc16bf7ab5b8aa235Jeff Garzikstatic const struct hpt_clock hpt366_33[] = {
80669a5db411d85a14f86cd92bc16bf7ab5b8aa235Jeff Garzik	{	XFER_UDMA_4,	0x90c9a731	},
81669a5db411d85a14f86cd92bc16bf7ab5b8aa235Jeff Garzik	{	XFER_UDMA_3,	0x90cfa731	},
82669a5db411d85a14f86cd92bc16bf7ab5b8aa235Jeff Garzik	{	XFER_UDMA_2,	0x90caa731	},
83669a5db411d85a14f86cd92bc16bf7ab5b8aa235Jeff Garzik	{	XFER_UDMA_1,	0x90cba731	},
84669a5db411d85a14f86cd92bc16bf7ab5b8aa235Jeff Garzik	{	XFER_UDMA_0,	0x90c8a731	},
85669a5db411d85a14f86cd92bc16bf7ab5b8aa235Jeff Garzik
86669a5db411d85a14f86cd92bc16bf7ab5b8aa235Jeff Garzik	{	XFER_MW_DMA_2,	0xa0c8a731	},
87669a5db411d85a14f86cd92bc16bf7ab5b8aa235Jeff Garzik	{	XFER_MW_DMA_1,	0xa0c8a732	},	/* 0xa0c8a733 */
88669a5db411d85a14f86cd92bc16bf7ab5b8aa235Jeff Garzik	{	XFER_MW_DMA_0,	0xa0c8a797	},
89669a5db411d85a14f86cd92bc16bf7ab5b8aa235Jeff Garzik
90669a5db411d85a14f86cd92bc16bf7ab5b8aa235Jeff Garzik	{	XFER_PIO_4,	0xc0c8a731	},
91669a5db411d85a14f86cd92bc16bf7ab5b8aa235Jeff Garzik	{	XFER_PIO_3,	0xc0c8a742	},
92669a5db411d85a14f86cd92bc16bf7ab5b8aa235Jeff Garzik	{	XFER_PIO_2,	0xc0d0a753	},
93669a5db411d85a14f86cd92bc16bf7ab5b8aa235Jeff Garzik	{	XFER_PIO_1,	0xc0d0a7a3	},	/* 0xc0d0a793 */
94669a5db411d85a14f86cd92bc16bf7ab5b8aa235Jeff Garzik	{	XFER_PIO_0,	0xc0d0a7aa	},	/* 0xc0d0a7a7 */
95669a5db411d85a14f86cd92bc16bf7ab5b8aa235Jeff Garzik	{	0,		0x0120a7a7	}
96669a5db411d85a14f86cd92bc16bf7ab5b8aa235Jeff Garzik};
97669a5db411d85a14f86cd92bc16bf7ab5b8aa235Jeff Garzik
98669a5db411d85a14f86cd92bc16bf7ab5b8aa235Jeff Garzikstatic const struct hpt_clock hpt366_25[] = {
99669a5db411d85a14f86cd92bc16bf7ab5b8aa235Jeff Garzik	{	XFER_UDMA_4,	0x90c98521	},
100669a5db411d85a14f86cd92bc16bf7ab5b8aa235Jeff Garzik	{	XFER_UDMA_3,	0x90cf8521	},
101669a5db411d85a14f86cd92bc16bf7ab5b8aa235Jeff Garzik	{	XFER_UDMA_2,	0x90cf8521	},
102669a5db411d85a14f86cd92bc16bf7ab5b8aa235Jeff Garzik	{	XFER_UDMA_1,	0x90cb8521	},
103669a5db411d85a14f86cd92bc16bf7ab5b8aa235Jeff Garzik	{	XFER_UDMA_0,	0x90cb8521	},
104669a5db411d85a14f86cd92bc16bf7ab5b8aa235Jeff Garzik
105669a5db411d85a14f86cd92bc16bf7ab5b8aa235Jeff Garzik	{	XFER_MW_DMA_2,	0xa0ca8521	},
106669a5db411d85a14f86cd92bc16bf7ab5b8aa235Jeff Garzik	{	XFER_MW_DMA_1,	0xa0ca8532	},
107669a5db411d85a14f86cd92bc16bf7ab5b8aa235Jeff Garzik	{	XFER_MW_DMA_0,	0xa0ca8575	},
108669a5db411d85a14f86cd92bc16bf7ab5b8aa235Jeff Garzik
109669a5db411d85a14f86cd92bc16bf7ab5b8aa235Jeff Garzik	{	XFER_PIO_4,	0xc0ca8521	},
110669a5db411d85a14f86cd92bc16bf7ab5b8aa235Jeff Garzik	{	XFER_PIO_3,	0xc0ca8532	},
111669a5db411d85a14f86cd92bc16bf7ab5b8aa235Jeff Garzik	{	XFER_PIO_2,	0xc0ca8542	},
112669a5db411d85a14f86cd92bc16bf7ab5b8aa235Jeff Garzik	{	XFER_PIO_1,	0xc0d08572	},
113669a5db411d85a14f86cd92bc16bf7ab5b8aa235Jeff Garzik	{	XFER_PIO_0,	0xc0d08585	},
114669a5db411d85a14f86cd92bc16bf7ab5b8aa235Jeff Garzik	{	0,		0x01208585	}
115669a5db411d85a14f86cd92bc16bf7ab5b8aa235Jeff Garzik};
116669a5db411d85a14f86cd92bc16bf7ab5b8aa235Jeff Garzik
117669a5db411d85a14f86cd92bc16bf7ab5b8aa235Jeff Garzikstatic const char *bad_ata33[] = {
118669a5db411d85a14f86cd92bc16bf7ab5b8aa235Jeff Garzik	"Maxtor 92720U8", "Maxtor 92040U6", "Maxtor 91360U4", "Maxtor 91020U3", "Maxtor 90845U3", "Maxtor 90650U2",
119669a5db411d85a14f86cd92bc16bf7ab5b8aa235Jeff Garzik	"Maxtor 91360D8", "Maxtor 91190D7", "Maxtor 91020D6", "Maxtor 90845D5", "Maxtor 90680D4", "Maxtor 90510D3", "Maxtor 90340D2",
120669a5db411d85a14f86cd92bc16bf7ab5b8aa235Jeff Garzik	"Maxtor 91152D8", "Maxtor 91008D7", "Maxtor 90845D6", "Maxtor 90840D6", "Maxtor 90720D5", "Maxtor 90648D5", "Maxtor 90576D4",
121669a5db411d85a14f86cd92bc16bf7ab5b8aa235Jeff Garzik	"Maxtor 90510D4",
122669a5db411d85a14f86cd92bc16bf7ab5b8aa235Jeff Garzik	"Maxtor 90432D3", "Maxtor 90288D2", "Maxtor 90256D2",
123669a5db411d85a14f86cd92bc16bf7ab5b8aa235Jeff Garzik	"Maxtor 91000D8", "Maxtor 90910D8", "Maxtor 90875D7", "Maxtor 90840D7", "Maxtor 90750D6", "Maxtor 90625D5", "Maxtor 90500D4",
124669a5db411d85a14f86cd92bc16bf7ab5b8aa235Jeff Garzik	"Maxtor 91728D8", "Maxtor 91512D7", "Maxtor 91303D6", "Maxtor 91080D5", "Maxtor 90845D4", "Maxtor 90680D4", "Maxtor 90648D3", "Maxtor 90432D2",
125669a5db411d85a14f86cd92bc16bf7ab5b8aa235Jeff Garzik	NULL
126669a5db411d85a14f86cd92bc16bf7ab5b8aa235Jeff Garzik};
127669a5db411d85a14f86cd92bc16bf7ab5b8aa235Jeff Garzik
128669a5db411d85a14f86cd92bc16bf7ab5b8aa235Jeff Garzikstatic const char *bad_ata66_4[] = {
129669a5db411d85a14f86cd92bc16bf7ab5b8aa235Jeff Garzik	"IBM-DTLA-307075",
130669a5db411d85a14f86cd92bc16bf7ab5b8aa235Jeff Garzik	"IBM-DTLA-307060",
131669a5db411d85a14f86cd92bc16bf7ab5b8aa235Jeff Garzik	"IBM-DTLA-307045",
132669a5db411d85a14f86cd92bc16bf7ab5b8aa235Jeff Garzik	"IBM-DTLA-307030",
133669a5db411d85a14f86cd92bc16bf7ab5b8aa235Jeff Garzik	"IBM-DTLA-307020",
134669a5db411d85a14f86cd92bc16bf7ab5b8aa235Jeff Garzik	"IBM-DTLA-307015",
135669a5db411d85a14f86cd92bc16bf7ab5b8aa235Jeff Garzik	"IBM-DTLA-305040",
136669a5db411d85a14f86cd92bc16bf7ab5b8aa235Jeff Garzik	"IBM-DTLA-305030",
137669a5db411d85a14f86cd92bc16bf7ab5b8aa235Jeff Garzik	"IBM-DTLA-305020",
138669a5db411d85a14f86cd92bc16bf7ab5b8aa235Jeff Garzik	"IC35L010AVER07-0",
139669a5db411d85a14f86cd92bc16bf7ab5b8aa235Jeff Garzik	"IC35L020AVER07-0",
140669a5db411d85a14f86cd92bc16bf7ab5b8aa235Jeff Garzik	"IC35L030AVER07-0",
141669a5db411d85a14f86cd92bc16bf7ab5b8aa235Jeff Garzik	"IC35L040AVER07-0",
142669a5db411d85a14f86cd92bc16bf7ab5b8aa235Jeff Garzik	"IC35L060AVER07-0",
143669a5db411d85a14f86cd92bc16bf7ab5b8aa235Jeff Garzik	"WDC AC310200R",
144669a5db411d85a14f86cd92bc16bf7ab5b8aa235Jeff Garzik	NULL
145669a5db411d85a14f86cd92bc16bf7ab5b8aa235Jeff Garzik};
146669a5db411d85a14f86cd92bc16bf7ab5b8aa235Jeff Garzik
147669a5db411d85a14f86cd92bc16bf7ab5b8aa235Jeff Garzikstatic const char *bad_ata66_3[] = {
148669a5db411d85a14f86cd92bc16bf7ab5b8aa235Jeff Garzik	"WDC AC310200R",
149669a5db411d85a14f86cd92bc16bf7ab5b8aa235Jeff Garzik	NULL
150669a5db411d85a14f86cd92bc16bf7ab5b8aa235Jeff Garzik};
151669a5db411d85a14f86cd92bc16bf7ab5b8aa235Jeff Garzik
152669a5db411d85a14f86cd92bc16bf7ab5b8aa235Jeff Garzikstatic int hpt_dma_blacklisted(const struct ata_device *dev, char *modestr, const char *list[])
153669a5db411d85a14f86cd92bc16bf7ab5b8aa235Jeff Garzik{
1548bfa79fcb81d2bdb043f60ab4171704467808b55Tejun Heo	unsigned char model_num[ATA_ID_PROD_LEN + 1];
155669a5db411d85a14f86cd92bc16bf7ab5b8aa235Jeff Garzik	int i = 0;
156669a5db411d85a14f86cd92bc16bf7ab5b8aa235Jeff Garzik
1578bfa79fcb81d2bdb043f60ab4171704467808b55Tejun Heo	ata_id_c_string(dev->id, model_num, ATA_ID_PROD, sizeof(model_num));
158669a5db411d85a14f86cd92bc16bf7ab5b8aa235Jeff Garzik
1598bfa79fcb81d2bdb043f60ab4171704467808b55Tejun Heo	while (list[i] != NULL) {
1608bfa79fcb81d2bdb043f60ab4171704467808b55Tejun Heo		if (!strcmp(list[i], model_num)) {
16185cd7251b9112e3dabeac9fd3b175601ca607241Jeff Garzik			printk(KERN_WARNING DRV_NAME ": %s is not supported for %s.\n",
162669a5db411d85a14f86cd92bc16bf7ab5b8aa235Jeff Garzik				modestr, list[i]);
163669a5db411d85a14f86cd92bc16bf7ab5b8aa235Jeff Garzik			return 1;
164669a5db411d85a14f86cd92bc16bf7ab5b8aa235Jeff Garzik		}
165669a5db411d85a14f86cd92bc16bf7ab5b8aa235Jeff Garzik		i++;
166669a5db411d85a14f86cd92bc16bf7ab5b8aa235Jeff Garzik	}
167669a5db411d85a14f86cd92bc16bf7ab5b8aa235Jeff Garzik	return 0;
168669a5db411d85a14f86cd92bc16bf7ab5b8aa235Jeff Garzik}
169669a5db411d85a14f86cd92bc16bf7ab5b8aa235Jeff Garzik
170669a5db411d85a14f86cd92bc16bf7ab5b8aa235Jeff Garzik/**
171669a5db411d85a14f86cd92bc16bf7ab5b8aa235Jeff Garzik *	hpt366_filter	-	mode selection filter
172669a5db411d85a14f86cd92bc16bf7ab5b8aa235Jeff Garzik *	@ap: ATA interface
173669a5db411d85a14f86cd92bc16bf7ab5b8aa235Jeff Garzik *	@adev: ATA device
174669a5db411d85a14f86cd92bc16bf7ab5b8aa235Jeff Garzik *
175669a5db411d85a14f86cd92bc16bf7ab5b8aa235Jeff Garzik *	Block UDMA on devices that cause trouble with this controller.
176669a5db411d85a14f86cd92bc16bf7ab5b8aa235Jeff Garzik */
17785cd7251b9112e3dabeac9fd3b175601ca607241Jeff Garzik
178669a5db411d85a14f86cd92bc16bf7ab5b8aa235Jeff Garzikstatic unsigned long hpt366_filter(const struct ata_port *ap, struct ata_device *adev, unsigned long mask)
179669a5db411d85a14f86cd92bc16bf7ab5b8aa235Jeff Garzik{
180669a5db411d85a14f86cd92bc16bf7ab5b8aa235Jeff Garzik	if (adev->class == ATA_DEV_ATA) {
181669a5db411d85a14f86cd92bc16bf7ab5b8aa235Jeff Garzik		if (hpt_dma_blacklisted(adev, "UDMA",  bad_ata33))
182669a5db411d85a14f86cd92bc16bf7ab5b8aa235Jeff Garzik			mask &= ~ATA_MASK_UDMA;
183669a5db411d85a14f86cd92bc16bf7ab5b8aa235Jeff Garzik		if (hpt_dma_blacklisted(adev, "UDMA3", bad_ata66_3))
184669a5db411d85a14f86cd92bc16bf7ab5b8aa235Jeff Garzik			mask &= ~(0x07 << ATA_SHIFT_UDMA);
185669a5db411d85a14f86cd92bc16bf7ab5b8aa235Jeff Garzik		if (hpt_dma_blacklisted(adev, "UDMA4", bad_ata66_4))
186669a5db411d85a14f86cd92bc16bf7ab5b8aa235Jeff Garzik			mask &= ~(0x0F << ATA_SHIFT_UDMA);
187669a5db411d85a14f86cd92bc16bf7ab5b8aa235Jeff Garzik	}
188669a5db411d85a14f86cd92bc16bf7ab5b8aa235Jeff Garzik	return ata_pci_default_filter(ap, adev, mask);
189669a5db411d85a14f86cd92bc16bf7ab5b8aa235Jeff Garzik}
190669a5db411d85a14f86cd92bc16bf7ab5b8aa235Jeff Garzik
191669a5db411d85a14f86cd92bc16bf7ab5b8aa235Jeff Garzik/**
192669a5db411d85a14f86cd92bc16bf7ab5b8aa235Jeff Garzik *	hpt36x_find_mode	-	reset the hpt36x bus
193669a5db411d85a14f86cd92bc16bf7ab5b8aa235Jeff Garzik *	@ap: ATA port
194669a5db411d85a14f86cd92bc16bf7ab5b8aa235Jeff Garzik *	@speed: transfer mode
195669a5db411d85a14f86cd92bc16bf7ab5b8aa235Jeff Garzik *
196669a5db411d85a14f86cd92bc16bf7ab5b8aa235Jeff Garzik *	Return the 32bit register programming information for this channel
197669a5db411d85a14f86cd92bc16bf7ab5b8aa235Jeff Garzik *	that matches the speed provided.
198669a5db411d85a14f86cd92bc16bf7ab5b8aa235Jeff Garzik */
19985cd7251b9112e3dabeac9fd3b175601ca607241Jeff Garzik
200669a5db411d85a14f86cd92bc16bf7ab5b8aa235Jeff Garzikstatic u32 hpt36x_find_mode(struct ata_port *ap, int speed)
201669a5db411d85a14f86cd92bc16bf7ab5b8aa235Jeff Garzik{
202669a5db411d85a14f86cd92bc16bf7ab5b8aa235Jeff Garzik	struct hpt_clock *clocks = ap->host->private_data;
20385cd7251b9112e3dabeac9fd3b175601ca607241Jeff Garzik
204669a5db411d85a14f86cd92bc16bf7ab5b8aa235Jeff Garzik	while(clocks->xfer_speed) {
205669a5db411d85a14f86cd92bc16bf7ab5b8aa235Jeff Garzik		if (clocks->xfer_speed == speed)
206669a5db411d85a14f86cd92bc16bf7ab5b8aa235Jeff Garzik			return clocks->timing;
207669a5db411d85a14f86cd92bc16bf7ab5b8aa235Jeff Garzik		clocks++;
208669a5db411d85a14f86cd92bc16bf7ab5b8aa235Jeff Garzik	}
209669a5db411d85a14f86cd92bc16bf7ab5b8aa235Jeff Garzik	BUG();
210669a5db411d85a14f86cd92bc16bf7ab5b8aa235Jeff Garzik	return 0xffffffffU;	/* silence compiler warning */
211669a5db411d85a14f86cd92bc16bf7ab5b8aa235Jeff Garzik}
21285cd7251b9112e3dabeac9fd3b175601ca607241Jeff Garzik
213fecfda5d88dcc3775f72d6f3a55d11b77c67f878Alan Coxstatic int hpt36x_cable_detect(struct ata_port *ap)
214fecfda5d88dcc3775f72d6f3a55d11b77c67f878Alan Cox{
215fecfda5d88dcc3775f72d6f3a55d11b77c67f878Alan Cox	u8 ata66;
216fecfda5d88dcc3775f72d6f3a55d11b77c67f878Alan Cox	struct pci_dev *pdev = to_pci_dev(ap->host->dev);
217fecfda5d88dcc3775f72d6f3a55d11b77c67f878Alan Cox
218fecfda5d88dcc3775f72d6f3a55d11b77c67f878Alan Cox	pci_read_config_byte(pdev, 0x5A, &ata66);
219fecfda5d88dcc3775f72d6f3a55d11b77c67f878Alan Cox	if (ata66 & (1 << ap->port_no))
220fecfda5d88dcc3775f72d6f3a55d11b77c67f878Alan Cox		return ATA_CBL_PATA40;
221fecfda5d88dcc3775f72d6f3a55d11b77c67f878Alan Cox	return ATA_CBL_PATA80;
222fecfda5d88dcc3775f72d6f3a55d11b77c67f878Alan Cox}
223fecfda5d88dcc3775f72d6f3a55d11b77c67f878Alan Cox
224669a5db411d85a14f86cd92bc16bf7ab5b8aa235Jeff Garzikstatic int hpt36x_pre_reset(struct ata_port *ap)
225669a5db411d85a14f86cd92bc16bf7ab5b8aa235Jeff Garzik{
22654083f114efad2d4fa993c52024f8973c70b9edbAlan Cox	static const struct pci_bits hpt36x_enable_bits[] = {
22754083f114efad2d4fa993c52024f8973c70b9edbAlan Cox		{ 0x50, 1, 0x04, 0x04 },
22854083f114efad2d4fa993c52024f8973c70b9edbAlan Cox		{ 0x54, 1, 0x04, 0x04 }
22954083f114efad2d4fa993c52024f8973c70b9edbAlan Cox	};
230669a5db411d85a14f86cd92bc16bf7ab5b8aa235Jeff Garzik	struct pci_dev *pdev = to_pci_dev(ap->host->dev);
23185cd7251b9112e3dabeac9fd3b175601ca607241Jeff Garzik
23254083f114efad2d4fa993c52024f8973c70b9edbAlan Cox	if (!pci_test_config_bits(pdev, &hpt36x_enable_bits[ap->port_no]))
23354083f114efad2d4fa993c52024f8973c70b9edbAlan Cox		return -ENOENT;
234f20b16ff7c19d1c369ee07470952aca093551ed0Jeff Garzik
235669a5db411d85a14f86cd92bc16bf7ab5b8aa235Jeff Garzik	return ata_std_prereset(ap);
236669a5db411d85a14f86cd92bc16bf7ab5b8aa235Jeff Garzik}
237669a5db411d85a14f86cd92bc16bf7ab5b8aa235Jeff Garzik
238669a5db411d85a14f86cd92bc16bf7ab5b8aa235Jeff Garzik/**
239669a5db411d85a14f86cd92bc16bf7ab5b8aa235Jeff Garzik *	hpt36x_error_handler	-	reset the hpt36x bus
240669a5db411d85a14f86cd92bc16bf7ab5b8aa235Jeff Garzik *	@ap: ATA port to reset
241669a5db411d85a14f86cd92bc16bf7ab5b8aa235Jeff Garzik *
242669a5db411d85a14f86cd92bc16bf7ab5b8aa235Jeff Garzik *	Perform the reset handling for the 366/368
243669a5db411d85a14f86cd92bc16bf7ab5b8aa235Jeff Garzik */
24485cd7251b9112e3dabeac9fd3b175601ca607241Jeff Garzik
245669a5db411d85a14f86cd92bc16bf7ab5b8aa235Jeff Garzikstatic void hpt36x_error_handler(struct ata_port *ap)
246669a5db411d85a14f86cd92bc16bf7ab5b8aa235Jeff Garzik{
247669a5db411d85a14f86cd92bc16bf7ab5b8aa235Jeff Garzik	ata_bmdma_drive_eh(ap, hpt36x_pre_reset, ata_std_softreset, NULL, ata_std_postreset);
248669a5db411d85a14f86cd92bc16bf7ab5b8aa235Jeff Garzik}
249669a5db411d85a14f86cd92bc16bf7ab5b8aa235Jeff Garzik
250669a5db411d85a14f86cd92bc16bf7ab5b8aa235Jeff Garzik/**
251669a5db411d85a14f86cd92bc16bf7ab5b8aa235Jeff Garzik *	hpt366_set_piomode		-	PIO setup
252669a5db411d85a14f86cd92bc16bf7ab5b8aa235Jeff Garzik *	@ap: ATA interface
253669a5db411d85a14f86cd92bc16bf7ab5b8aa235Jeff Garzik *	@adev: device on the interface
254669a5db411d85a14f86cd92bc16bf7ab5b8aa235Jeff Garzik *
25585cd7251b9112e3dabeac9fd3b175601ca607241Jeff Garzik *	Perform PIO mode setup.
256669a5db411d85a14f86cd92bc16bf7ab5b8aa235Jeff Garzik */
25785cd7251b9112e3dabeac9fd3b175601ca607241Jeff Garzik
258669a5db411d85a14f86cd92bc16bf7ab5b8aa235Jeff Garzikstatic void hpt366_set_piomode(struct ata_port *ap, struct ata_device *adev)
259669a5db411d85a14f86cd92bc16bf7ab5b8aa235Jeff Garzik{
260669a5db411d85a14f86cd92bc16bf7ab5b8aa235Jeff Garzik	struct pci_dev *pdev = to_pci_dev(ap->host->dev);
261669a5db411d85a14f86cd92bc16bf7ab5b8aa235Jeff Garzik	u32 addr1, addr2;
262669a5db411d85a14f86cd92bc16bf7ab5b8aa235Jeff Garzik	u32 reg;
263669a5db411d85a14f86cd92bc16bf7ab5b8aa235Jeff Garzik	u32 mode;
264669a5db411d85a14f86cd92bc16bf7ab5b8aa235Jeff Garzik	u8 fast;
265669a5db411d85a14f86cd92bc16bf7ab5b8aa235Jeff Garzik
266669a5db411d85a14f86cd92bc16bf7ab5b8aa235Jeff Garzik	addr1 = 0x40 + 4 * (adev->devno + 2 * ap->port_no);
267669a5db411d85a14f86cd92bc16bf7ab5b8aa235Jeff Garzik	addr2 = 0x51 + 4 * ap->port_no;
26885cd7251b9112e3dabeac9fd3b175601ca607241Jeff Garzik
269669a5db411d85a14f86cd92bc16bf7ab5b8aa235Jeff Garzik	/* Fast interrupt prediction disable, hold off interrupt disable */
270669a5db411d85a14f86cd92bc16bf7ab5b8aa235Jeff Garzik	pci_read_config_byte(pdev, addr2, &fast);
271669a5db411d85a14f86cd92bc16bf7ab5b8aa235Jeff Garzik	if (fast & 0x80) {
272669a5db411d85a14f86cd92bc16bf7ab5b8aa235Jeff Garzik		fast &= ~0x80;
273669a5db411d85a14f86cd92bc16bf7ab5b8aa235Jeff Garzik		pci_write_config_byte(pdev, addr2, fast);
274669a5db411d85a14f86cd92bc16bf7ab5b8aa235Jeff Garzik	}
27585cd7251b9112e3dabeac9fd3b175601ca607241Jeff Garzik
276669a5db411d85a14f86cd92bc16bf7ab5b8aa235Jeff Garzik	pci_read_config_dword(pdev, addr1, &reg);
277669a5db411d85a14f86cd92bc16bf7ab5b8aa235Jeff Garzik	mode = hpt36x_find_mode(ap, adev->pio_mode);
278669a5db411d85a14f86cd92bc16bf7ab5b8aa235Jeff Garzik	mode &= ~0x8000000;	/* No FIFO in PIO */
279669a5db411d85a14f86cd92bc16bf7ab5b8aa235Jeff Garzik	mode &= ~0x30070000;	/* Leave config bits alone */
280669a5db411d85a14f86cd92bc16bf7ab5b8aa235Jeff Garzik	reg &= 0x30070000;	/* Strip timing bits */
281669a5db411d85a14f86cd92bc16bf7ab5b8aa235Jeff Garzik	pci_write_config_dword(pdev, addr1, reg | mode);
282669a5db411d85a14f86cd92bc16bf7ab5b8aa235Jeff Garzik}
283669a5db411d85a14f86cd92bc16bf7ab5b8aa235Jeff Garzik
284669a5db411d85a14f86cd92bc16bf7ab5b8aa235Jeff Garzik/**
285669a5db411d85a14f86cd92bc16bf7ab5b8aa235Jeff Garzik *	hpt366_set_dmamode		-	DMA timing setup
286669a5db411d85a14f86cd92bc16bf7ab5b8aa235Jeff Garzik *	@ap: ATA interface
287669a5db411d85a14f86cd92bc16bf7ab5b8aa235Jeff Garzik *	@adev: Device being configured
288669a5db411d85a14f86cd92bc16bf7ab5b8aa235Jeff Garzik *
289669a5db411d85a14f86cd92bc16bf7ab5b8aa235Jeff Garzik *	Set up the channel for MWDMA or UDMA modes. Much the same as with
290669a5db411d85a14f86cd92bc16bf7ab5b8aa235Jeff Garzik *	PIO, load the mode number and then set MWDMA or UDMA flag.
291669a5db411d85a14f86cd92bc16bf7ab5b8aa235Jeff Garzik */
29285cd7251b9112e3dabeac9fd3b175601ca607241Jeff Garzik
293669a5db411d85a14f86cd92bc16bf7ab5b8aa235Jeff Garzikstatic void hpt366_set_dmamode(struct ata_port *ap, struct ata_device *adev)
294669a5db411d85a14f86cd92bc16bf7ab5b8aa235Jeff Garzik{
295669a5db411d85a14f86cd92bc16bf7ab5b8aa235Jeff Garzik	struct pci_dev *pdev = to_pci_dev(ap->host->dev);
296669a5db411d85a14f86cd92bc16bf7ab5b8aa235Jeff Garzik	u32 addr1, addr2;
297669a5db411d85a14f86cd92bc16bf7ab5b8aa235Jeff Garzik	u32 reg;
298669a5db411d85a14f86cd92bc16bf7ab5b8aa235Jeff Garzik	u32 mode;
299669a5db411d85a14f86cd92bc16bf7ab5b8aa235Jeff Garzik	u8 fast;
300669a5db411d85a14f86cd92bc16bf7ab5b8aa235Jeff Garzik
301669a5db411d85a14f86cd92bc16bf7ab5b8aa235Jeff Garzik	addr1 = 0x40 + 4 * (adev->devno + 2 * ap->port_no);
302669a5db411d85a14f86cd92bc16bf7ab5b8aa235Jeff Garzik	addr2 = 0x51 + 4 * ap->port_no;
30385cd7251b9112e3dabeac9fd3b175601ca607241Jeff Garzik
304669a5db411d85a14f86cd92bc16bf7ab5b8aa235Jeff Garzik	/* Fast interrupt prediction disable, hold off interrupt disable */
305669a5db411d85a14f86cd92bc16bf7ab5b8aa235Jeff Garzik	pci_read_config_byte(pdev, addr2, &fast);
306669a5db411d85a14f86cd92bc16bf7ab5b8aa235Jeff Garzik	if (fast & 0x80) {
307669a5db411d85a14f86cd92bc16bf7ab5b8aa235Jeff Garzik		fast &= ~0x80;
308669a5db411d85a14f86cd92bc16bf7ab5b8aa235Jeff Garzik		pci_write_config_byte(pdev, addr2, fast);
309669a5db411d85a14f86cd92bc16bf7ab5b8aa235Jeff Garzik	}
31085cd7251b9112e3dabeac9fd3b175601ca607241Jeff Garzik
311669a5db411d85a14f86cd92bc16bf7ab5b8aa235Jeff Garzik	pci_read_config_dword(pdev, addr1, &reg);
312669a5db411d85a14f86cd92bc16bf7ab5b8aa235Jeff Garzik	mode = hpt36x_find_mode(ap, adev->dma_mode);
313669a5db411d85a14f86cd92bc16bf7ab5b8aa235Jeff Garzik	mode |= 0x8000000;	/* FIFO in MWDMA or UDMA */
314669a5db411d85a14f86cd92bc16bf7ab5b8aa235Jeff Garzik	mode &= ~0xC0000000;	/* Leave config bits alone */
315669a5db411d85a14f86cd92bc16bf7ab5b8aa235Jeff Garzik	reg &= 0xC0000000;	/* Strip timing bits */
316669a5db411d85a14f86cd92bc16bf7ab5b8aa235Jeff Garzik	pci_write_config_dword(pdev, addr1, reg | mode);
317669a5db411d85a14f86cd92bc16bf7ab5b8aa235Jeff Garzik}
318669a5db411d85a14f86cd92bc16bf7ab5b8aa235Jeff Garzik
319669a5db411d85a14f86cd92bc16bf7ab5b8aa235Jeff Garzikstatic struct scsi_host_template hpt36x_sht = {
320669a5db411d85a14f86cd92bc16bf7ab5b8aa235Jeff Garzik	.module			= THIS_MODULE,
321669a5db411d85a14f86cd92bc16bf7ab5b8aa235Jeff Garzik	.name			= DRV_NAME,
322669a5db411d85a14f86cd92bc16bf7ab5b8aa235Jeff Garzik	.ioctl			= ata_scsi_ioctl,
323669a5db411d85a14f86cd92bc16bf7ab5b8aa235Jeff Garzik	.queuecommand		= ata_scsi_queuecmd,
324669a5db411d85a14f86cd92bc16bf7ab5b8aa235Jeff Garzik	.can_queue		= ATA_DEF_QUEUE,
325669a5db411d85a14f86cd92bc16bf7ab5b8aa235Jeff Garzik	.this_id		= ATA_SHT_THIS_ID,
326669a5db411d85a14f86cd92bc16bf7ab5b8aa235Jeff Garzik	.sg_tablesize		= LIBATA_MAX_PRD,
327669a5db411d85a14f86cd92bc16bf7ab5b8aa235Jeff Garzik	.cmd_per_lun		= ATA_SHT_CMD_PER_LUN,
328669a5db411d85a14f86cd92bc16bf7ab5b8aa235Jeff Garzik	.emulated		= ATA_SHT_EMULATED,
329669a5db411d85a14f86cd92bc16bf7ab5b8aa235Jeff Garzik	.use_clustering		= ATA_SHT_USE_CLUSTERING,
330669a5db411d85a14f86cd92bc16bf7ab5b8aa235Jeff Garzik	.proc_name		= DRV_NAME,
331669a5db411d85a14f86cd92bc16bf7ab5b8aa235Jeff Garzik	.dma_boundary		= ATA_DMA_BOUNDARY,
332669a5db411d85a14f86cd92bc16bf7ab5b8aa235Jeff Garzik	.slave_configure	= ata_scsi_slave_config,
333afdfe899e6420eac6c5eb3bc8c89456dff38d40eTejun Heo	.slave_destroy		= ata_scsi_slave_destroy,
334669a5db411d85a14f86cd92bc16bf7ab5b8aa235Jeff Garzik	.bios_param		= ata_std_bios_param,
335438ac6d5e3f8106a6bd1a5682c508d660294a85dTejun Heo#ifdef CONFIG_PM
336aa54ab1eff30f1e5859acf4e15f0730288373ee5Alan Cox	.resume			= ata_scsi_device_resume,
337aa54ab1eff30f1e5859acf4e15f0730288373ee5Alan Cox	.suspend		= ata_scsi_device_suspend,
338438ac6d5e3f8106a6bd1a5682c508d660294a85dTejun Heo#endif
339669a5db411d85a14f86cd92bc16bf7ab5b8aa235Jeff Garzik};
340669a5db411d85a14f86cd92bc16bf7ab5b8aa235Jeff Garzik
341669a5db411d85a14f86cd92bc16bf7ab5b8aa235Jeff Garzik/*
342669a5db411d85a14f86cd92bc16bf7ab5b8aa235Jeff Garzik *	Configuration for HPT366/68
343669a5db411d85a14f86cd92bc16bf7ab5b8aa235Jeff Garzik */
34485cd7251b9112e3dabeac9fd3b175601ca607241Jeff Garzik
345669a5db411d85a14f86cd92bc16bf7ab5b8aa235Jeff Garzikstatic struct ata_port_operations hpt366_port_ops = {
346669a5db411d85a14f86cd92bc16bf7ab5b8aa235Jeff Garzik	.port_disable	= ata_port_disable,
347669a5db411d85a14f86cd92bc16bf7ab5b8aa235Jeff Garzik	.set_piomode	= hpt366_set_piomode,
348669a5db411d85a14f86cd92bc16bf7ab5b8aa235Jeff Garzik	.set_dmamode	= hpt366_set_dmamode,
349669a5db411d85a14f86cd92bc16bf7ab5b8aa235Jeff Garzik	.mode_filter	= hpt366_filter,
35085cd7251b9112e3dabeac9fd3b175601ca607241Jeff Garzik
351669a5db411d85a14f86cd92bc16bf7ab5b8aa235Jeff Garzik	.tf_load	= ata_tf_load,
352669a5db411d85a14f86cd92bc16bf7ab5b8aa235Jeff Garzik	.tf_read	= ata_tf_read,
353669a5db411d85a14f86cd92bc16bf7ab5b8aa235Jeff Garzik	.check_status 	= ata_check_status,
354669a5db411d85a14f86cd92bc16bf7ab5b8aa235Jeff Garzik	.exec_command	= ata_exec_command,
355669a5db411d85a14f86cd92bc16bf7ab5b8aa235Jeff Garzik	.dev_select 	= ata_std_dev_select,
356669a5db411d85a14f86cd92bc16bf7ab5b8aa235Jeff Garzik
357669a5db411d85a14f86cd92bc16bf7ab5b8aa235Jeff Garzik	.freeze		= ata_bmdma_freeze,
358669a5db411d85a14f86cd92bc16bf7ab5b8aa235Jeff Garzik	.thaw		= ata_bmdma_thaw,
359669a5db411d85a14f86cd92bc16bf7ab5b8aa235Jeff Garzik	.error_handler	= hpt36x_error_handler,
360669a5db411d85a14f86cd92bc16bf7ab5b8aa235Jeff Garzik	.post_internal_cmd = ata_bmdma_post_internal_cmd,
361fecfda5d88dcc3775f72d6f3a55d11b77c67f878Alan Cox	.cable_detect	= hpt36x_cable_detect,
362669a5db411d85a14f86cd92bc16bf7ab5b8aa235Jeff Garzik
363669a5db411d85a14f86cd92bc16bf7ab5b8aa235Jeff Garzik	.bmdma_setup 	= ata_bmdma_setup,
364669a5db411d85a14f86cd92bc16bf7ab5b8aa235Jeff Garzik	.bmdma_start 	= ata_bmdma_start,
365669a5db411d85a14f86cd92bc16bf7ab5b8aa235Jeff Garzik	.bmdma_stop	= ata_bmdma_stop,
366669a5db411d85a14f86cd92bc16bf7ab5b8aa235Jeff Garzik	.bmdma_status 	= ata_bmdma_status,
367669a5db411d85a14f86cd92bc16bf7ab5b8aa235Jeff Garzik
368669a5db411d85a14f86cd92bc16bf7ab5b8aa235Jeff Garzik	.qc_prep 	= ata_qc_prep,
369669a5db411d85a14f86cd92bc16bf7ab5b8aa235Jeff Garzik	.qc_issue	= ata_qc_issue_prot,
370bda3028813bd07f34f30288a492fbf6f7b8712ddJeff Garzik
3710d5ff566779f894ca9937231a181eb31e4adff0eTejun Heo	.data_xfer	= ata_data_xfer,
372669a5db411d85a14f86cd92bc16bf7ab5b8aa235Jeff Garzik
373669a5db411d85a14f86cd92bc16bf7ab5b8aa235Jeff Garzik	.irq_handler	= ata_interrupt,
374669a5db411d85a14f86cd92bc16bf7ab5b8aa235Jeff Garzik	.irq_clear	= ata_bmdma_irq_clear,
375246ce3b675843e0369643cceb4faeb6cf6d19a30Akira Iguchi	.irq_on		= ata_irq_on,
376246ce3b675843e0369643cceb4faeb6cf6d19a30Akira Iguchi	.irq_ack	= ata_irq_ack,
377669a5db411d85a14f86cd92bc16bf7ab5b8aa235Jeff Garzik
378669a5db411d85a14f86cd92bc16bf7ab5b8aa235Jeff Garzik	.port_start	= ata_port_start,
37985cd7251b9112e3dabeac9fd3b175601ca607241Jeff Garzik};
380669a5db411d85a14f86cd92bc16bf7ab5b8aa235Jeff Garzik
381669a5db411d85a14f86cd92bc16bf7ab5b8aa235Jeff Garzik/**
382aa54ab1eff30f1e5859acf4e15f0730288373ee5Alan Cox *	hpt36x_init_chipset	-	common chip setup
383aa54ab1eff30f1e5859acf4e15f0730288373ee5Alan Cox *	@dev: PCI device
384aa54ab1eff30f1e5859acf4e15f0730288373ee5Alan Cox *
385aa54ab1eff30f1e5859acf4e15f0730288373ee5Alan Cox *	Perform the chip setup work that must be done at both init and
386aa54ab1eff30f1e5859acf4e15f0730288373ee5Alan Cox *	resume time
387aa54ab1eff30f1e5859acf4e15f0730288373ee5Alan Cox */
388aa54ab1eff30f1e5859acf4e15f0730288373ee5Alan Cox
389aa54ab1eff30f1e5859acf4e15f0730288373ee5Alan Coxstatic void hpt36x_init_chipset(struct pci_dev *dev)
390aa54ab1eff30f1e5859acf4e15f0730288373ee5Alan Cox{
391aa54ab1eff30f1e5859acf4e15f0730288373ee5Alan Cox	u8 drive_fast;
392aa54ab1eff30f1e5859acf4e15f0730288373ee5Alan Cox	pci_write_config_byte(dev, PCI_CACHE_LINE_SIZE, (L1_CACHE_BYTES / 4));
393aa54ab1eff30f1e5859acf4e15f0730288373ee5Alan Cox	pci_write_config_byte(dev, PCI_LATENCY_TIMER, 0x78);
394aa54ab1eff30f1e5859acf4e15f0730288373ee5Alan Cox	pci_write_config_byte(dev, PCI_MIN_GNT, 0x08);
395aa54ab1eff30f1e5859acf4e15f0730288373ee5Alan Cox	pci_write_config_byte(dev, PCI_MAX_LAT, 0x08);
396aa54ab1eff30f1e5859acf4e15f0730288373ee5Alan Cox
397aa54ab1eff30f1e5859acf4e15f0730288373ee5Alan Cox	pci_read_config_byte(dev, 0x51, &drive_fast);
398aa54ab1eff30f1e5859acf4e15f0730288373ee5Alan Cox	if (drive_fast & 0x80)
399aa54ab1eff30f1e5859acf4e15f0730288373ee5Alan Cox		pci_write_config_byte(dev, 0x51, drive_fast & ~0x80);
400aa54ab1eff30f1e5859acf4e15f0730288373ee5Alan Cox}
401aa54ab1eff30f1e5859acf4e15f0730288373ee5Alan Cox
402aa54ab1eff30f1e5859acf4e15f0730288373ee5Alan Cox/**
403669a5db411d85a14f86cd92bc16bf7ab5b8aa235Jeff Garzik *	hpt36x_init_one		-	Initialise an HPT366/368
404669a5db411d85a14f86cd92bc16bf7ab5b8aa235Jeff Garzik *	@dev: PCI device
405669a5db411d85a14f86cd92bc16bf7ab5b8aa235Jeff Garzik *	@id: Entry in match table
406669a5db411d85a14f86cd92bc16bf7ab5b8aa235Jeff Garzik *
407669a5db411d85a14f86cd92bc16bf7ab5b8aa235Jeff Garzik *	Initialise an HPT36x device. There are some interesting complications
408669a5db411d85a14f86cd92bc16bf7ab5b8aa235Jeff Garzik *	here. Firstly the chip may report 366 and be one of several variants.
409669a5db411d85a14f86cd92bc16bf7ab5b8aa235Jeff Garzik *	Secondly all the timings depend on the clock for the chip which we must
410669a5db411d85a14f86cd92bc16bf7ab5b8aa235Jeff Garzik *	detect and look up
411669a5db411d85a14f86cd92bc16bf7ab5b8aa235Jeff Garzik *
412669a5db411d85a14f86cd92bc16bf7ab5b8aa235Jeff Garzik *	This is the known chip mappings. It may be missing a couple of later
413669a5db411d85a14f86cd92bc16bf7ab5b8aa235Jeff Garzik *	releases.
414669a5db411d85a14f86cd92bc16bf7ab5b8aa235Jeff Garzik *
415669a5db411d85a14f86cd92bc16bf7ab5b8aa235Jeff Garzik *	Chip version		PCI		Rev	Notes
416669a5db411d85a14f86cd92bc16bf7ab5b8aa235Jeff Garzik *	HPT366			4 (HPT366)	0	UDMA66
417669a5db411d85a14f86cd92bc16bf7ab5b8aa235Jeff Garzik *	HPT366			4 (HPT366)	1	UDMA66
418669a5db411d85a14f86cd92bc16bf7ab5b8aa235Jeff Garzik *	HPT368			4 (HPT366)	2	UDMA66
419669a5db411d85a14f86cd92bc16bf7ab5b8aa235Jeff Garzik *	HPT37x/30x		4 (HPT366)	3+	Other driver
420669a5db411d85a14f86cd92bc16bf7ab5b8aa235Jeff Garzik *
421669a5db411d85a14f86cd92bc16bf7ab5b8aa235Jeff Garzik */
42285cd7251b9112e3dabeac9fd3b175601ca607241Jeff Garzik
423669a5db411d85a14f86cd92bc16bf7ab5b8aa235Jeff Garzikstatic int hpt36x_init_one(struct pci_dev *dev, const struct pci_device_id *id)
424669a5db411d85a14f86cd92bc16bf7ab5b8aa235Jeff Garzik{
425669a5db411d85a14f86cd92bc16bf7ab5b8aa235Jeff Garzik	static struct ata_port_info info_hpt366 = {
426669a5db411d85a14f86cd92bc16bf7ab5b8aa235Jeff Garzik		.sht = &hpt36x_sht,
427669a5db411d85a14f86cd92bc16bf7ab5b8aa235Jeff Garzik		.flags = ATA_FLAG_SLAVE_POSS | ATA_FLAG_SRST,
428669a5db411d85a14f86cd92bc16bf7ab5b8aa235Jeff Garzik		.pio_mask = 0x1f,
429669a5db411d85a14f86cd92bc16bf7ab5b8aa235Jeff Garzik		.mwdma_mask = 0x07,
430669a5db411d85a14f86cd92bc16bf7ab5b8aa235Jeff Garzik		.udma_mask = 0x1f,
431669a5db411d85a14f86cd92bc16bf7ab5b8aa235Jeff Garzik		.port_ops = &hpt366_port_ops
432669a5db411d85a14f86cd92bc16bf7ab5b8aa235Jeff Garzik	};
433669a5db411d85a14f86cd92bc16bf7ab5b8aa235Jeff Garzik	struct ata_port_info *port_info[2] = {&info_hpt366, &info_hpt366};
434669a5db411d85a14f86cd92bc16bf7ab5b8aa235Jeff Garzik
435669a5db411d85a14f86cd92bc16bf7ab5b8aa235Jeff Garzik	u32 class_rev;
436669a5db411d85a14f86cd92bc16bf7ab5b8aa235Jeff Garzik	u32 reg1;
437669a5db411d85a14f86cd92bc16bf7ab5b8aa235Jeff Garzik
438669a5db411d85a14f86cd92bc16bf7ab5b8aa235Jeff Garzik	pci_read_config_dword(dev, PCI_CLASS_REVISION, &class_rev);
439669a5db411d85a14f86cd92bc16bf7ab5b8aa235Jeff Garzik	class_rev &= 0xFF;
44085cd7251b9112e3dabeac9fd3b175601ca607241Jeff Garzik
441669a5db411d85a14f86cd92bc16bf7ab5b8aa235Jeff Garzik	/* May be a later chip in disguise. Check */
442669a5db411d85a14f86cd92bc16bf7ab5b8aa235Jeff Garzik	/* Newer chips are not in the HPT36x driver. Ignore them */
443669a5db411d85a14f86cd92bc16bf7ab5b8aa235Jeff Garzik	if (class_rev > 2)
444669a5db411d85a14f86cd92bc16bf7ab5b8aa235Jeff Garzik			return -ENODEV;
445669a5db411d85a14f86cd92bc16bf7ab5b8aa235Jeff Garzik
446aa54ab1eff30f1e5859acf4e15f0730288373ee5Alan Cox	hpt36x_init_chipset(dev);
447669a5db411d85a14f86cd92bc16bf7ab5b8aa235Jeff Garzik
448669a5db411d85a14f86cd92bc16bf7ab5b8aa235Jeff Garzik	pci_read_config_dword(dev, 0x40,  &reg1);
44985cd7251b9112e3dabeac9fd3b175601ca607241Jeff Garzik
450669a5db411d85a14f86cd92bc16bf7ab5b8aa235Jeff Garzik	/* PCI clocking determines the ATA timing values to use */
451669a5db411d85a14f86cd92bc16bf7ab5b8aa235Jeff Garzik	/* info_hpt366 is safe against re-entry so we can scribble on it */
4522c136efcf6f58d07512c4df83eb494597fe0d229OGAWA Hirofumi	switch((reg1 & 0x700) >> 8) {
453669a5db411d85a14f86cd92bc16bf7ab5b8aa235Jeff Garzik		case 5:
454669a5db411d85a14f86cd92bc16bf7ab5b8aa235Jeff Garzik			info_hpt366.private_data = &hpt366_40;
455669a5db411d85a14f86cd92bc16bf7ab5b8aa235Jeff Garzik			break;
456669a5db411d85a14f86cd92bc16bf7ab5b8aa235Jeff Garzik		case 9:
457669a5db411d85a14f86cd92bc16bf7ab5b8aa235Jeff Garzik			info_hpt366.private_data = &hpt366_25;
458669a5db411d85a14f86cd92bc16bf7ab5b8aa235Jeff Garzik			break;
459669a5db411d85a14f86cd92bc16bf7ab5b8aa235Jeff Garzik		default:
460669a5db411d85a14f86cd92bc16bf7ab5b8aa235Jeff Garzik			info_hpt366.private_data = &hpt366_33;
461669a5db411d85a14f86cd92bc16bf7ab5b8aa235Jeff Garzik			break;
462669a5db411d85a14f86cd92bc16bf7ab5b8aa235Jeff Garzik	}
463669a5db411d85a14f86cd92bc16bf7ab5b8aa235Jeff Garzik	/* Now kick off ATA set up */
464669a5db411d85a14f86cd92bc16bf7ab5b8aa235Jeff Garzik	return ata_pci_init_one(dev, port_info, 2);
465669a5db411d85a14f86cd92bc16bf7ab5b8aa235Jeff Garzik}
466669a5db411d85a14f86cd92bc16bf7ab5b8aa235Jeff Garzik
467438ac6d5e3f8106a6bd1a5682c508d660294a85dTejun Heo#ifdef CONFIG_PM
468aa54ab1eff30f1e5859acf4e15f0730288373ee5Alan Coxstatic int hpt36x_reinit_one(struct pci_dev *dev)
469aa54ab1eff30f1e5859acf4e15f0730288373ee5Alan Cox{
470aa54ab1eff30f1e5859acf4e15f0730288373ee5Alan Cox	hpt36x_init_chipset(dev);
471aa54ab1eff30f1e5859acf4e15f0730288373ee5Alan Cox	return ata_pci_device_resume(dev);
472aa54ab1eff30f1e5859acf4e15f0730288373ee5Alan Cox}
473438ac6d5e3f8106a6bd1a5682c508d660294a85dTejun Heo#endif
474aa54ab1eff30f1e5859acf4e15f0730288373ee5Alan Cox
4752d2744fc8be620a2dc469cf48349e3e704119f1bJeff Garzikstatic const struct pci_device_id hpt36x[] = {
4762d2744fc8be620a2dc469cf48349e3e704119f1bJeff Garzik	{ PCI_VDEVICE(TTI, PCI_DEVICE_ID_TTI_HPT366), },
4772d2744fc8be620a2dc469cf48349e3e704119f1bJeff Garzik	{ },
478669a5db411d85a14f86cd92bc16bf7ab5b8aa235Jeff Garzik};
479669a5db411d85a14f86cd92bc16bf7ab5b8aa235Jeff Garzik
480669a5db411d85a14f86cd92bc16bf7ab5b8aa235Jeff Garzikstatic struct pci_driver hpt36x_pci_driver = {
4812d2744fc8be620a2dc469cf48349e3e704119f1bJeff Garzik	.name 		= DRV_NAME,
482669a5db411d85a14f86cd92bc16bf7ab5b8aa235Jeff Garzik	.id_table	= hpt36x,
483669a5db411d85a14f86cd92bc16bf7ab5b8aa235Jeff Garzik	.probe 		= hpt36x_init_one,
484aa54ab1eff30f1e5859acf4e15f0730288373ee5Alan Cox	.remove		= ata_pci_remove_one,
485438ac6d5e3f8106a6bd1a5682c508d660294a85dTejun Heo#ifdef CONFIG_PM
486aa54ab1eff30f1e5859acf4e15f0730288373ee5Alan Cox	.suspend	= ata_pci_device_suspend,
487aa54ab1eff30f1e5859acf4e15f0730288373ee5Alan Cox	.resume		= hpt36x_reinit_one,
488438ac6d5e3f8106a6bd1a5682c508d660294a85dTejun Heo#endif
489669a5db411d85a14f86cd92bc16bf7ab5b8aa235Jeff Garzik};
490669a5db411d85a14f86cd92bc16bf7ab5b8aa235Jeff Garzik
491669a5db411d85a14f86cd92bc16bf7ab5b8aa235Jeff Garzikstatic int __init hpt36x_init(void)
492669a5db411d85a14f86cd92bc16bf7ab5b8aa235Jeff Garzik{
493669a5db411d85a14f86cd92bc16bf7ab5b8aa235Jeff Garzik	return pci_register_driver(&hpt36x_pci_driver);
494669a5db411d85a14f86cd92bc16bf7ab5b8aa235Jeff Garzik}
495669a5db411d85a14f86cd92bc16bf7ab5b8aa235Jeff Garzik
496669a5db411d85a14f86cd92bc16bf7ab5b8aa235Jeff Garzikstatic void __exit hpt36x_exit(void)
497669a5db411d85a14f86cd92bc16bf7ab5b8aa235Jeff Garzik{
498669a5db411d85a14f86cd92bc16bf7ab5b8aa235Jeff Garzik	pci_unregister_driver(&hpt36x_pci_driver);
499669a5db411d85a14f86cd92bc16bf7ab5b8aa235Jeff Garzik}
500669a5db411d85a14f86cd92bc16bf7ab5b8aa235Jeff Garzik
501669a5db411d85a14f86cd92bc16bf7ab5b8aa235Jeff GarzikMODULE_AUTHOR("Alan Cox");
502669a5db411d85a14f86cd92bc16bf7ab5b8aa235Jeff GarzikMODULE_DESCRIPTION("low-level driver for the Highpoint HPT366/368");
503669a5db411d85a14f86cd92bc16bf7ab5b8aa235Jeff GarzikMODULE_LICENSE("GPL");
504669a5db411d85a14f86cd92bc16bf7ab5b8aa235Jeff GarzikMODULE_DEVICE_TABLE(pci, hpt36x);
505669a5db411d85a14f86cd92bc16bf7ab5b8aa235Jeff GarzikMODULE_VERSION(DRV_VERSION);
506669a5db411d85a14f86cd92bc16bf7ab5b8aa235Jeff Garzik
507669a5db411d85a14f86cd92bc16bf7ab5b8aa235Jeff Garzikmodule_init(hpt36x_init);
508669a5db411d85a14f86cd92bc16bf7ab5b8aa235Jeff Garzikmodule_exit(hpt36x_exit);
509