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
14d817898c2fc73e6ea33b58498c87a43d7e9fcd7aSergei Shtylyov *	Look into engine reset on timeout errors. Should not be required.
15669a5db411d85a14f86cd92bc16bf7ab5b8aa235Jeff Garzik */
16669a5db411d85a14f86cd92bc16bf7ab5b8aa235Jeff Garzik
178d7b1c70b3c1aac4b63109f5c73f732f1d63fad6Joe Perches#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
18669a5db411d85a14f86cd92bc16bf7ab5b8aa235Jeff Garzik
19669a5db411d85a14f86cd92bc16bf7ab5b8aa235Jeff Garzik#include <linux/kernel.h>
20669a5db411d85a14f86cd92bc16bf7ab5b8aa235Jeff Garzik#include <linux/module.h>
21669a5db411d85a14f86cd92bc16bf7ab5b8aa235Jeff Garzik#include <linux/pci.h>
22669a5db411d85a14f86cd92bc16bf7ab5b8aa235Jeff Garzik#include <linux/init.h>
23669a5db411d85a14f86cd92bc16bf7ab5b8aa235Jeff Garzik#include <linux/blkdev.h>
24669a5db411d85a14f86cd92bc16bf7ab5b8aa235Jeff Garzik#include <linux/delay.h>
25669a5db411d85a14f86cd92bc16bf7ab5b8aa235Jeff Garzik#include <scsi/scsi_host.h>
26669a5db411d85a14f86cd92bc16bf7ab5b8aa235Jeff Garzik#include <linux/libata.h>
27669a5db411d85a14f86cd92bc16bf7ab5b8aa235Jeff Garzik
28669a5db411d85a14f86cd92bc16bf7ab5b8aa235Jeff Garzik#define DRV_NAME	"pata_hpt366"
298d7b1c70b3c1aac4b63109f5c73f732f1d63fad6Joe Perches#define DRV_VERSION	"0.6.11"
30669a5db411d85a14f86cd92bc16bf7ab5b8aa235Jeff Garzik
31669a5db411d85a14f86cd92bc16bf7ab5b8aa235Jeff Garzikstruct hpt_clock {
326ecb6f25d3a52c0d032aa73bde1ff9bc454aa66cTejun Heo	u8	xfer_mode;
33669a5db411d85a14f86cd92bc16bf7ab5b8aa235Jeff Garzik	u32	timing;
34669a5db411d85a14f86cd92bc16bf7ab5b8aa235Jeff Garzik};
35669a5db411d85a14f86cd92bc16bf7ab5b8aa235Jeff Garzik
36669a5db411d85a14f86cd92bc16bf7ab5b8aa235Jeff Garzik/* key for bus clock timings
37669a5db411d85a14f86cd92bc16bf7ab5b8aa235Jeff Garzik * bit
3882beb5d89456a4c8329676985004b93a7ded5b5aSergei Shtylyov * 0:3    data_high_time. Inactive time of DIOW_/DIOR_ for PIO and MW DMA.
3982beb5d89456a4c8329676985004b93a7ded5b5aSergei Shtylyov *        cycles = value + 1
4082beb5d89456a4c8329676985004b93a7ded5b5aSergei Shtylyov * 4:7    data_low_time. Active time of DIOW_/DIOR_ for PIO and MW DMA.
4182beb5d89456a4c8329676985004b93a7ded5b5aSergei Shtylyov *        cycles = value + 1
4282beb5d89456a4c8329676985004b93a7ded5b5aSergei Shtylyov * 8:11   cmd_high_time. Inactive time of DIOW_/DIOR_ during task file
43669a5db411d85a14f86cd92bc16bf7ab5b8aa235Jeff Garzik *        register access.
4482beb5d89456a4c8329676985004b93a7ded5b5aSergei Shtylyov * 12:15  cmd_low_time. Active time of DIOW_/DIOR_ during task file
45669a5db411d85a14f86cd92bc16bf7ab5b8aa235Jeff Garzik *        register access.
4682beb5d89456a4c8329676985004b93a7ded5b5aSergei Shtylyov * 16:18  udma_cycle_time. Clock cycles for UDMA xfer?
4782beb5d89456a4c8329676985004b93a7ded5b5aSergei Shtylyov * 19:21  pre_high_time. Time to initialize 1st cycle for PIO and MW DMA xfer.
4882beb5d89456a4c8329676985004b93a7ded5b5aSergei Shtylyov * 22:24  cmd_pre_high_time. Time to initialize 1st PIO cycle for task file
49669a5db411d85a14f86cd92bc16bf7ab5b8aa235Jeff Garzik *        register access.
5082beb5d89456a4c8329676985004b93a7ded5b5aSergei Shtylyov * 28     UDMA enable.
5182beb5d89456a4c8329676985004b93a7ded5b5aSergei Shtylyov * 29     DMA  enable.
5282beb5d89456a4c8329676985004b93a7ded5b5aSergei Shtylyov * 30     PIO_MST enable. If set, the chip is in bus master mode during
5382beb5d89456a4c8329676985004b93a7ded5b5aSergei Shtylyov *        PIO xfer.
54669a5db411d85a14f86cd92bc16bf7ab5b8aa235Jeff Garzik * 31     FIFO enable.
55669a5db411d85a14f86cd92bc16bf7ab5b8aa235Jeff Garzik */
56669a5db411d85a14f86cd92bc16bf7ab5b8aa235Jeff Garzik
57669a5db411d85a14f86cd92bc16bf7ab5b8aa235Jeff Garzikstatic const struct hpt_clock hpt366_40[] = {
58669a5db411d85a14f86cd92bc16bf7ab5b8aa235Jeff Garzik	{	XFER_UDMA_4,	0x900fd943	},
59669a5db411d85a14f86cd92bc16bf7ab5b8aa235Jeff Garzik	{	XFER_UDMA_3,	0x900ad943	},
60669a5db411d85a14f86cd92bc16bf7ab5b8aa235Jeff Garzik	{	XFER_UDMA_2,	0x900bd943	},
61669a5db411d85a14f86cd92bc16bf7ab5b8aa235Jeff Garzik	{	XFER_UDMA_1,	0x9008d943	},
62669a5db411d85a14f86cd92bc16bf7ab5b8aa235Jeff Garzik	{	XFER_UDMA_0,	0x9008d943	},
63669a5db411d85a14f86cd92bc16bf7ab5b8aa235Jeff Garzik
64669a5db411d85a14f86cd92bc16bf7ab5b8aa235Jeff Garzik	{	XFER_MW_DMA_2,	0xa008d943	},
65669a5db411d85a14f86cd92bc16bf7ab5b8aa235Jeff Garzik	{	XFER_MW_DMA_1,	0xa010d955	},
66669a5db411d85a14f86cd92bc16bf7ab5b8aa235Jeff Garzik	{	XFER_MW_DMA_0,	0xa010d9fc	},
67669a5db411d85a14f86cd92bc16bf7ab5b8aa235Jeff Garzik
68669a5db411d85a14f86cd92bc16bf7ab5b8aa235Jeff Garzik	{	XFER_PIO_4,	0xc008d963	},
69669a5db411d85a14f86cd92bc16bf7ab5b8aa235Jeff Garzik	{	XFER_PIO_3,	0xc010d974	},
70669a5db411d85a14f86cd92bc16bf7ab5b8aa235Jeff Garzik	{	XFER_PIO_2,	0xc010d997	},
71669a5db411d85a14f86cd92bc16bf7ab5b8aa235Jeff Garzik	{	XFER_PIO_1,	0xc010d9c7	},
72669a5db411d85a14f86cd92bc16bf7ab5b8aa235Jeff Garzik	{	XFER_PIO_0,	0xc018d9d9	},
73669a5db411d85a14f86cd92bc16bf7ab5b8aa235Jeff Garzik	{	0,		0x0120d9d9	}
74669a5db411d85a14f86cd92bc16bf7ab5b8aa235Jeff Garzik};
75669a5db411d85a14f86cd92bc16bf7ab5b8aa235Jeff Garzik
76669a5db411d85a14f86cd92bc16bf7ab5b8aa235Jeff Garzikstatic const struct hpt_clock hpt366_33[] = {
77669a5db411d85a14f86cd92bc16bf7ab5b8aa235Jeff Garzik	{	XFER_UDMA_4,	0x90c9a731	},
78669a5db411d85a14f86cd92bc16bf7ab5b8aa235Jeff Garzik	{	XFER_UDMA_3,	0x90cfa731	},
79669a5db411d85a14f86cd92bc16bf7ab5b8aa235Jeff Garzik	{	XFER_UDMA_2,	0x90caa731	},
80669a5db411d85a14f86cd92bc16bf7ab5b8aa235Jeff Garzik	{	XFER_UDMA_1,	0x90cba731	},
81669a5db411d85a14f86cd92bc16bf7ab5b8aa235Jeff Garzik	{	XFER_UDMA_0,	0x90c8a731	},
82669a5db411d85a14f86cd92bc16bf7ab5b8aa235Jeff Garzik
83669a5db411d85a14f86cd92bc16bf7ab5b8aa235Jeff Garzik	{	XFER_MW_DMA_2,	0xa0c8a731	},
84669a5db411d85a14f86cd92bc16bf7ab5b8aa235Jeff Garzik	{	XFER_MW_DMA_1,	0xa0c8a732	},	/* 0xa0c8a733 */
85669a5db411d85a14f86cd92bc16bf7ab5b8aa235Jeff Garzik	{	XFER_MW_DMA_0,	0xa0c8a797	},
86669a5db411d85a14f86cd92bc16bf7ab5b8aa235Jeff Garzik
87669a5db411d85a14f86cd92bc16bf7ab5b8aa235Jeff Garzik	{	XFER_PIO_4,	0xc0c8a731	},
88669a5db411d85a14f86cd92bc16bf7ab5b8aa235Jeff Garzik	{	XFER_PIO_3,	0xc0c8a742	},
89669a5db411d85a14f86cd92bc16bf7ab5b8aa235Jeff Garzik	{	XFER_PIO_2,	0xc0d0a753	},
90669a5db411d85a14f86cd92bc16bf7ab5b8aa235Jeff Garzik	{	XFER_PIO_1,	0xc0d0a7a3	},	/* 0xc0d0a793 */
91669a5db411d85a14f86cd92bc16bf7ab5b8aa235Jeff Garzik	{	XFER_PIO_0,	0xc0d0a7aa	},	/* 0xc0d0a7a7 */
92669a5db411d85a14f86cd92bc16bf7ab5b8aa235Jeff Garzik	{	0,		0x0120a7a7	}
93669a5db411d85a14f86cd92bc16bf7ab5b8aa235Jeff Garzik};
94669a5db411d85a14f86cd92bc16bf7ab5b8aa235Jeff Garzik
95669a5db411d85a14f86cd92bc16bf7ab5b8aa235Jeff Garzikstatic const struct hpt_clock hpt366_25[] = {
96669a5db411d85a14f86cd92bc16bf7ab5b8aa235Jeff Garzik	{	XFER_UDMA_4,	0x90c98521	},
97669a5db411d85a14f86cd92bc16bf7ab5b8aa235Jeff Garzik	{	XFER_UDMA_3,	0x90cf8521	},
98669a5db411d85a14f86cd92bc16bf7ab5b8aa235Jeff Garzik	{	XFER_UDMA_2,	0x90cf8521	},
99669a5db411d85a14f86cd92bc16bf7ab5b8aa235Jeff Garzik	{	XFER_UDMA_1,	0x90cb8521	},
100669a5db411d85a14f86cd92bc16bf7ab5b8aa235Jeff Garzik	{	XFER_UDMA_0,	0x90cb8521	},
101669a5db411d85a14f86cd92bc16bf7ab5b8aa235Jeff Garzik
102669a5db411d85a14f86cd92bc16bf7ab5b8aa235Jeff Garzik	{	XFER_MW_DMA_2,	0xa0ca8521	},
103669a5db411d85a14f86cd92bc16bf7ab5b8aa235Jeff Garzik	{	XFER_MW_DMA_1,	0xa0ca8532	},
104669a5db411d85a14f86cd92bc16bf7ab5b8aa235Jeff Garzik	{	XFER_MW_DMA_0,	0xa0ca8575	},
105669a5db411d85a14f86cd92bc16bf7ab5b8aa235Jeff Garzik
106669a5db411d85a14f86cd92bc16bf7ab5b8aa235Jeff Garzik	{	XFER_PIO_4,	0xc0ca8521	},
107669a5db411d85a14f86cd92bc16bf7ab5b8aa235Jeff Garzik	{	XFER_PIO_3,	0xc0ca8532	},
108669a5db411d85a14f86cd92bc16bf7ab5b8aa235Jeff Garzik	{	XFER_PIO_2,	0xc0ca8542	},
109669a5db411d85a14f86cd92bc16bf7ab5b8aa235Jeff Garzik	{	XFER_PIO_1,	0xc0d08572	},
110669a5db411d85a14f86cd92bc16bf7ab5b8aa235Jeff Garzik	{	XFER_PIO_0,	0xc0d08585	},
111669a5db411d85a14f86cd92bc16bf7ab5b8aa235Jeff Garzik	{	0,		0x01208585	}
112669a5db411d85a14f86cd92bc16bf7ab5b8aa235Jeff Garzik};
113669a5db411d85a14f86cd92bc16bf7ab5b8aa235Jeff Garzik
114dc5e44ec6f75d493df484728587b00b87a233482Bartlomiej Zolnierkiewicz/**
115dc5e44ec6f75d493df484728587b00b87a233482Bartlomiej Zolnierkiewicz *	hpt36x_find_mode	-	find the hpt36x timing
116dc5e44ec6f75d493df484728587b00b87a233482Bartlomiej Zolnierkiewicz *	@ap: ATA port
117dc5e44ec6f75d493df484728587b00b87a233482Bartlomiej Zolnierkiewicz *	@speed: transfer mode
118dc5e44ec6f75d493df484728587b00b87a233482Bartlomiej Zolnierkiewicz *
119dc5e44ec6f75d493df484728587b00b87a233482Bartlomiej Zolnierkiewicz *	Return the 32bit register programming information for this channel
120dc5e44ec6f75d493df484728587b00b87a233482Bartlomiej Zolnierkiewicz *	that matches the speed provided.
121dc5e44ec6f75d493df484728587b00b87a233482Bartlomiej Zolnierkiewicz */
122dc5e44ec6f75d493df484728587b00b87a233482Bartlomiej Zolnierkiewicz
123dc5e44ec6f75d493df484728587b00b87a233482Bartlomiej Zolnierkiewiczstatic u32 hpt36x_find_mode(struct ata_port *ap, int speed)
124dc5e44ec6f75d493df484728587b00b87a233482Bartlomiej Zolnierkiewicz{
125dc5e44ec6f75d493df484728587b00b87a233482Bartlomiej Zolnierkiewicz	struct hpt_clock *clocks = ap->host->private_data;
126dc5e44ec6f75d493df484728587b00b87a233482Bartlomiej Zolnierkiewicz
127dc5e44ec6f75d493df484728587b00b87a233482Bartlomiej Zolnierkiewicz	while (clocks->xfer_mode) {
128dc5e44ec6f75d493df484728587b00b87a233482Bartlomiej Zolnierkiewicz		if (clocks->xfer_mode == speed)
129dc5e44ec6f75d493df484728587b00b87a233482Bartlomiej Zolnierkiewicz			return clocks->timing;
130dc5e44ec6f75d493df484728587b00b87a233482Bartlomiej Zolnierkiewicz		clocks++;
131dc5e44ec6f75d493df484728587b00b87a233482Bartlomiej Zolnierkiewicz	}
132dc5e44ec6f75d493df484728587b00b87a233482Bartlomiej Zolnierkiewicz	BUG();
133dc5e44ec6f75d493df484728587b00b87a233482Bartlomiej Zolnierkiewicz	return 0xffffffffU;	/* silence compiler warning */
134dc5e44ec6f75d493df484728587b00b87a233482Bartlomiej Zolnierkiewicz}
135dc5e44ec6f75d493df484728587b00b87a233482Bartlomiej Zolnierkiewicz
13628cd4b6b4850d7588f1033c3808314b6bc2150d5Sergei Shtylyovstatic const char * const bad_ata33[] = {
13728cd4b6b4850d7588f1033c3808314b6bc2150d5Sergei Shtylyov	"Maxtor 92720U8", "Maxtor 92040U6", "Maxtor 91360U4", "Maxtor 91020U3",
13828cd4b6b4850d7588f1033c3808314b6bc2150d5Sergei Shtylyov	"Maxtor 90845U3", "Maxtor 90650U2",
13928cd4b6b4850d7588f1033c3808314b6bc2150d5Sergei Shtylyov	"Maxtor 91360D8", "Maxtor 91190D7", "Maxtor 91020D6", "Maxtor 90845D5",
14028cd4b6b4850d7588f1033c3808314b6bc2150d5Sergei Shtylyov	"Maxtor 90680D4", "Maxtor 90510D3", "Maxtor 90340D2",
14128cd4b6b4850d7588f1033c3808314b6bc2150d5Sergei Shtylyov	"Maxtor 91152D8", "Maxtor 91008D7", "Maxtor 90845D6", "Maxtor 90840D6",
14228cd4b6b4850d7588f1033c3808314b6bc2150d5Sergei Shtylyov	"Maxtor 90720D5", "Maxtor 90648D5", "Maxtor 90576D4",
143669a5db411d85a14f86cd92bc16bf7ab5b8aa235Jeff Garzik	"Maxtor 90510D4",
144669a5db411d85a14f86cd92bc16bf7ab5b8aa235Jeff Garzik	"Maxtor 90432D3", "Maxtor 90288D2", "Maxtor 90256D2",
14528cd4b6b4850d7588f1033c3808314b6bc2150d5Sergei Shtylyov	"Maxtor 91000D8", "Maxtor 90910D8", "Maxtor 90875D7", "Maxtor 90840D7",
14628cd4b6b4850d7588f1033c3808314b6bc2150d5Sergei Shtylyov	"Maxtor 90750D6", "Maxtor 90625D5", "Maxtor 90500D4",
14728cd4b6b4850d7588f1033c3808314b6bc2150d5Sergei Shtylyov	"Maxtor 91728D8", "Maxtor 91512D7", "Maxtor 91303D6", "Maxtor 91080D5",
14828cd4b6b4850d7588f1033c3808314b6bc2150d5Sergei Shtylyov	"Maxtor 90845D4", "Maxtor 90680D4", "Maxtor 90648D3", "Maxtor 90432D2",
149669a5db411d85a14f86cd92bc16bf7ab5b8aa235Jeff Garzik	NULL
150669a5db411d85a14f86cd92bc16bf7ab5b8aa235Jeff Garzik};
151669a5db411d85a14f86cd92bc16bf7ab5b8aa235Jeff Garzik
15228cd4b6b4850d7588f1033c3808314b6bc2150d5Sergei Shtylyovstatic const char * const bad_ata66_4[] = {
153669a5db411d85a14f86cd92bc16bf7ab5b8aa235Jeff Garzik	"IBM-DTLA-307075",
154669a5db411d85a14f86cd92bc16bf7ab5b8aa235Jeff Garzik	"IBM-DTLA-307060",
155669a5db411d85a14f86cd92bc16bf7ab5b8aa235Jeff Garzik	"IBM-DTLA-307045",
156669a5db411d85a14f86cd92bc16bf7ab5b8aa235Jeff Garzik	"IBM-DTLA-307030",
157669a5db411d85a14f86cd92bc16bf7ab5b8aa235Jeff Garzik	"IBM-DTLA-307020",
158669a5db411d85a14f86cd92bc16bf7ab5b8aa235Jeff Garzik	"IBM-DTLA-307015",
159669a5db411d85a14f86cd92bc16bf7ab5b8aa235Jeff Garzik	"IBM-DTLA-305040",
160669a5db411d85a14f86cd92bc16bf7ab5b8aa235Jeff Garzik	"IBM-DTLA-305030",
161669a5db411d85a14f86cd92bc16bf7ab5b8aa235Jeff Garzik	"IBM-DTLA-305020",
162669a5db411d85a14f86cd92bc16bf7ab5b8aa235Jeff Garzik	"IC35L010AVER07-0",
163669a5db411d85a14f86cd92bc16bf7ab5b8aa235Jeff Garzik	"IC35L020AVER07-0",
164669a5db411d85a14f86cd92bc16bf7ab5b8aa235Jeff Garzik	"IC35L030AVER07-0",
165669a5db411d85a14f86cd92bc16bf7ab5b8aa235Jeff Garzik	"IC35L040AVER07-0",
166669a5db411d85a14f86cd92bc16bf7ab5b8aa235Jeff Garzik	"IC35L060AVER07-0",
167669a5db411d85a14f86cd92bc16bf7ab5b8aa235Jeff Garzik	"WDC AC310200R",
168669a5db411d85a14f86cd92bc16bf7ab5b8aa235Jeff Garzik	NULL
169669a5db411d85a14f86cd92bc16bf7ab5b8aa235Jeff Garzik};
170669a5db411d85a14f86cd92bc16bf7ab5b8aa235Jeff Garzik
17128cd4b6b4850d7588f1033c3808314b6bc2150d5Sergei Shtylyovstatic const char * const bad_ata66_3[] = {
172669a5db411d85a14f86cd92bc16bf7ab5b8aa235Jeff Garzik	"WDC AC310200R",
173669a5db411d85a14f86cd92bc16bf7ab5b8aa235Jeff Garzik	NULL
174669a5db411d85a14f86cd92bc16bf7ab5b8aa235Jeff Garzik};
175669a5db411d85a14f86cd92bc16bf7ab5b8aa235Jeff Garzik
17628cd4b6b4850d7588f1033c3808314b6bc2150d5Sergei Shtylyovstatic int hpt_dma_blacklisted(const struct ata_device *dev, char *modestr,
17728cd4b6b4850d7588f1033c3808314b6bc2150d5Sergei Shtylyov			       const char * const list[])
178669a5db411d85a14f86cd92bc16bf7ab5b8aa235Jeff Garzik{
1798bfa79fcb81d2bdb043f60ab4171704467808b55Tejun Heo	unsigned char model_num[ATA_ID_PROD_LEN + 1];
180669a5db411d85a14f86cd92bc16bf7ab5b8aa235Jeff Garzik	int i = 0;
181669a5db411d85a14f86cd92bc16bf7ab5b8aa235Jeff Garzik
1828bfa79fcb81d2bdb043f60ab4171704467808b55Tejun Heo	ata_id_c_string(dev->id, model_num, ATA_ID_PROD, sizeof(model_num));
183669a5db411d85a14f86cd92bc16bf7ab5b8aa235Jeff Garzik
1848bfa79fcb81d2bdb043f60ab4171704467808b55Tejun Heo	while (list[i] != NULL) {
1858bfa79fcb81d2bdb043f60ab4171704467808b55Tejun Heo		if (!strcmp(list[i], model_num)) {
1868d7b1c70b3c1aac4b63109f5c73f732f1d63fad6Joe Perches			pr_warn("%s is not supported for %s\n",
1878d7b1c70b3c1aac4b63109f5c73f732f1d63fad6Joe Perches				modestr, list[i]);
188669a5db411d85a14f86cd92bc16bf7ab5b8aa235Jeff Garzik			return 1;
189669a5db411d85a14f86cd92bc16bf7ab5b8aa235Jeff Garzik		}
190669a5db411d85a14f86cd92bc16bf7ab5b8aa235Jeff Garzik		i++;
191669a5db411d85a14f86cd92bc16bf7ab5b8aa235Jeff Garzik	}
192669a5db411d85a14f86cd92bc16bf7ab5b8aa235Jeff Garzik	return 0;
193669a5db411d85a14f86cd92bc16bf7ab5b8aa235Jeff Garzik}
194669a5db411d85a14f86cd92bc16bf7ab5b8aa235Jeff Garzik
195669a5db411d85a14f86cd92bc16bf7ab5b8aa235Jeff Garzik/**
196669a5db411d85a14f86cd92bc16bf7ab5b8aa235Jeff Garzik *	hpt366_filter	-	mode selection filter
197669a5db411d85a14f86cd92bc16bf7ab5b8aa235Jeff Garzik *	@adev: ATA device
198669a5db411d85a14f86cd92bc16bf7ab5b8aa235Jeff Garzik *
199669a5db411d85a14f86cd92bc16bf7ab5b8aa235Jeff Garzik *	Block UDMA on devices that cause trouble with this controller.
200669a5db411d85a14f86cd92bc16bf7ab5b8aa235Jeff Garzik */
20185cd7251b9112e3dabeac9fd3b175601ca607241Jeff Garzik
202a76b62ca70662cd0ca98edf366c6637009a95f7dAlan Coxstatic unsigned long hpt366_filter(struct ata_device *adev, unsigned long mask)
203669a5db411d85a14f86cd92bc16bf7ab5b8aa235Jeff Garzik{
204669a5db411d85a14f86cd92bc16bf7ab5b8aa235Jeff Garzik	if (adev->class == ATA_DEV_ATA) {
205669a5db411d85a14f86cd92bc16bf7ab5b8aa235Jeff Garzik		if (hpt_dma_blacklisted(adev, "UDMA",  bad_ata33))
206669a5db411d85a14f86cd92bc16bf7ab5b8aa235Jeff Garzik			mask &= ~ATA_MASK_UDMA;
207669a5db411d85a14f86cd92bc16bf7ab5b8aa235Jeff Garzik		if (hpt_dma_blacklisted(adev, "UDMA3", bad_ata66_3))
2086ddd68615ae9b21096545d7d6ab0f04113ae8b42Alan Cox			mask &= ~(0xF8 << ATA_SHIFT_UDMA);
209669a5db411d85a14f86cd92bc16bf7ab5b8aa235Jeff Garzik		if (hpt_dma_blacklisted(adev, "UDMA4", bad_ata66_4))
2106ddd68615ae9b21096545d7d6ab0f04113ae8b42Alan Cox			mask &= ~(0xF0 << ATA_SHIFT_UDMA);
2113ee89f177e3cef0b5b024bcb6df683a3fa7d795fTejun Heo	} else if (adev->class == ATA_DEV_ATAPI)
2123ee89f177e3cef0b5b024bcb6df683a3fa7d795fTejun Heo		mask &= ~(ATA_MASK_MWDMA | ATA_MASK_UDMA);
2133ee89f177e3cef0b5b024bcb6df683a3fa7d795fTejun Heo
214c7087652e1890a3feef35b30ee1d4be68e1932cdTejun Heo	return mask;
215669a5db411d85a14f86cd92bc16bf7ab5b8aa235Jeff Garzik}
216669a5db411d85a14f86cd92bc16bf7ab5b8aa235Jeff Garzik
217fecfda5d88dcc3775f72d6f3a55d11b77c67f878Alan Coxstatic int hpt36x_cable_detect(struct ata_port *ap)
218fecfda5d88dcc3775f72d6f3a55d11b77c67f878Alan Cox{
219fecfda5d88dcc3775f72d6f3a55d11b77c67f878Alan Cox	struct pci_dev *pdev = to_pci_dev(ap->host->dev);
220bab5b32a537edc83ff86bff91e46f328339f49f8Tejun Heo	u8 ata66;
221fecfda5d88dcc3775f72d6f3a55d11b77c67f878Alan Cox
222bab5b32a537edc83ff86bff91e46f328339f49f8Tejun Heo	/*
223bab5b32a537edc83ff86bff91e46f328339f49f8Tejun Heo	 * Each channel of pata_hpt366 occupies separate PCI function
224bab5b32a537edc83ff86bff91e46f328339f49f8Tejun Heo	 * as the primary channel and bit1 indicates the cable type.
225bab5b32a537edc83ff86bff91e46f328339f49f8Tejun Heo	 */
226fecfda5d88dcc3775f72d6f3a55d11b77c67f878Alan Cox	pci_read_config_byte(pdev, 0x5A, &ata66);
227bab5b32a537edc83ff86bff91e46f328339f49f8Tejun Heo	if (ata66 & 2)
228fecfda5d88dcc3775f72d6f3a55d11b77c67f878Alan Cox		return ATA_CBL_PATA40;
229fecfda5d88dcc3775f72d6f3a55d11b77c67f878Alan Cox	return ATA_CBL_PATA80;
230fecfda5d88dcc3775f72d6f3a55d11b77c67f878Alan Cox}
231fecfda5d88dcc3775f72d6f3a55d11b77c67f878Alan Cox
2326ecb6f25d3a52c0d032aa73bde1ff9bc454aa66cTejun Heostatic void hpt366_set_mode(struct ata_port *ap, struct ata_device *adev,
2336ecb6f25d3a52c0d032aa73bde1ff9bc454aa66cTejun Heo			    u8 mode)
234669a5db411d85a14f86cd92bc16bf7ab5b8aa235Jeff Garzik{
235669a5db411d85a14f86cd92bc16bf7ab5b8aa235Jeff Garzik	struct pci_dev *pdev = to_pci_dev(ap->host->dev);
236859faa875ed6760fcdfaf6f1fec1155a7e43dc21Sergei Shtylyov	u32 addr = 0x40 + 4 * adev->devno;
237dc5e44ec6f75d493df484728587b00b87a233482Bartlomiej Zolnierkiewicz	u32 mask, reg, t;
23885cd7251b9112e3dabeac9fd3b175601ca607241Jeff Garzik
2396ecb6f25d3a52c0d032aa73bde1ff9bc454aa66cTejun Heo	/* determine timing mask and find matching clock entry */
2406ecb6f25d3a52c0d032aa73bde1ff9bc454aa66cTejun Heo	if (mode < XFER_MW_DMA_0)
2416ecb6f25d3a52c0d032aa73bde1ff9bc454aa66cTejun Heo		mask = 0xc1f8ffff;
2426ecb6f25d3a52c0d032aa73bde1ff9bc454aa66cTejun Heo	else if (mode < XFER_UDMA_0)
2436ecb6f25d3a52c0d032aa73bde1ff9bc454aa66cTejun Heo		mask = 0x303800ff;
2446ecb6f25d3a52c0d032aa73bde1ff9bc454aa66cTejun Heo	else
2456ecb6f25d3a52c0d032aa73bde1ff9bc454aa66cTejun Heo		mask = 0x30070000;
2466ecb6f25d3a52c0d032aa73bde1ff9bc454aa66cTejun Heo
247dc5e44ec6f75d493df484728587b00b87a233482Bartlomiej Zolnierkiewicz	t = hpt36x_find_mode(ap, mode);
2486ecb6f25d3a52c0d032aa73bde1ff9bc454aa66cTejun Heo
2496ecb6f25d3a52c0d032aa73bde1ff9bc454aa66cTejun Heo	/*
2506ecb6f25d3a52c0d032aa73bde1ff9bc454aa66cTejun Heo	 * Combine new mode bits with old config bits and disable
2516ecb6f25d3a52c0d032aa73bde1ff9bc454aa66cTejun Heo	 * on-chip PIO FIFO/buffer (and PIO MST mode as well) to avoid
2526ecb6f25d3a52c0d032aa73bde1ff9bc454aa66cTejun Heo	 * problems handling I/O errors later.
2536ecb6f25d3a52c0d032aa73bde1ff9bc454aa66cTejun Heo	 */
254859faa875ed6760fcdfaf6f1fec1155a7e43dc21Sergei Shtylyov	pci_read_config_dword(pdev, addr, &reg);
255dc5e44ec6f75d493df484728587b00b87a233482Bartlomiej Zolnierkiewicz	reg = ((reg & ~mask) | (t & mask)) & ~0xc0000000;
256859faa875ed6760fcdfaf6f1fec1155a7e43dc21Sergei Shtylyov	pci_write_config_dword(pdev, addr, reg);
2576ecb6f25d3a52c0d032aa73bde1ff9bc454aa66cTejun Heo}
2586ecb6f25d3a52c0d032aa73bde1ff9bc454aa66cTejun Heo
2596ecb6f25d3a52c0d032aa73bde1ff9bc454aa66cTejun Heo/**
2606ecb6f25d3a52c0d032aa73bde1ff9bc454aa66cTejun Heo *	hpt366_set_piomode		-	PIO setup
2616ecb6f25d3a52c0d032aa73bde1ff9bc454aa66cTejun Heo *	@ap: ATA interface
2626ecb6f25d3a52c0d032aa73bde1ff9bc454aa66cTejun Heo *	@adev: device on the interface
2636ecb6f25d3a52c0d032aa73bde1ff9bc454aa66cTejun Heo *
2646ecb6f25d3a52c0d032aa73bde1ff9bc454aa66cTejun Heo *	Perform PIO mode setup.
2656ecb6f25d3a52c0d032aa73bde1ff9bc454aa66cTejun Heo */
2666ecb6f25d3a52c0d032aa73bde1ff9bc454aa66cTejun Heo
2676ecb6f25d3a52c0d032aa73bde1ff9bc454aa66cTejun Heostatic void hpt366_set_piomode(struct ata_port *ap, struct ata_device *adev)
2686ecb6f25d3a52c0d032aa73bde1ff9bc454aa66cTejun Heo{
2696ecb6f25d3a52c0d032aa73bde1ff9bc454aa66cTejun Heo	hpt366_set_mode(ap, adev, adev->pio_mode);
270669a5db411d85a14f86cd92bc16bf7ab5b8aa235Jeff Garzik}
271669a5db411d85a14f86cd92bc16bf7ab5b8aa235Jeff Garzik
272669a5db411d85a14f86cd92bc16bf7ab5b8aa235Jeff Garzik/**
273669a5db411d85a14f86cd92bc16bf7ab5b8aa235Jeff Garzik *	hpt366_set_dmamode		-	DMA timing setup
274669a5db411d85a14f86cd92bc16bf7ab5b8aa235Jeff Garzik *	@ap: ATA interface
275669a5db411d85a14f86cd92bc16bf7ab5b8aa235Jeff Garzik *	@adev: Device being configured
276669a5db411d85a14f86cd92bc16bf7ab5b8aa235Jeff Garzik *
277669a5db411d85a14f86cd92bc16bf7ab5b8aa235Jeff Garzik *	Set up the channel for MWDMA or UDMA modes. Much the same as with
278669a5db411d85a14f86cd92bc16bf7ab5b8aa235Jeff Garzik *	PIO, load the mode number and then set MWDMA or UDMA flag.
279669a5db411d85a14f86cd92bc16bf7ab5b8aa235Jeff Garzik */
28085cd7251b9112e3dabeac9fd3b175601ca607241Jeff Garzik
281669a5db411d85a14f86cd92bc16bf7ab5b8aa235Jeff Garzikstatic void hpt366_set_dmamode(struct ata_port *ap, struct ata_device *adev)
282669a5db411d85a14f86cd92bc16bf7ab5b8aa235Jeff Garzik{
2836ecb6f25d3a52c0d032aa73bde1ff9bc454aa66cTejun Heo	hpt366_set_mode(ap, adev, adev->dma_mode);
284669a5db411d85a14f86cd92bc16bf7ab5b8aa235Jeff Garzik}
285669a5db411d85a14f86cd92bc16bf7ab5b8aa235Jeff Garzik
286669a5db411d85a14f86cd92bc16bf7ab5b8aa235Jeff Garzikstatic struct scsi_host_template hpt36x_sht = {
28768d1d07b510bb57a504588adc2bd2758adea0965Tejun Heo	ATA_BMDMA_SHT(DRV_NAME),
288669a5db411d85a14f86cd92bc16bf7ab5b8aa235Jeff Garzik};
289669a5db411d85a14f86cd92bc16bf7ab5b8aa235Jeff Garzik
290669a5db411d85a14f86cd92bc16bf7ab5b8aa235Jeff Garzik/*
291669a5db411d85a14f86cd92bc16bf7ab5b8aa235Jeff Garzik *	Configuration for HPT366/68
292669a5db411d85a14f86cd92bc16bf7ab5b8aa235Jeff Garzik */
29385cd7251b9112e3dabeac9fd3b175601ca607241Jeff Garzik
294669a5db411d85a14f86cd92bc16bf7ab5b8aa235Jeff Garzikstatic struct ata_port_operations hpt366_port_ops = {
295029cfd6b74fc5c517865fad78cf4a3ea8d9b664aTejun Heo	.inherits	= &ata_bmdma_port_ops,
296029cfd6b74fc5c517865fad78cf4a3ea8d9b664aTejun Heo	.cable_detect	= hpt36x_cable_detect,
297029cfd6b74fc5c517865fad78cf4a3ea8d9b664aTejun Heo	.mode_filter	= hpt366_filter,
298669a5db411d85a14f86cd92bc16bf7ab5b8aa235Jeff Garzik	.set_piomode	= hpt366_set_piomode,
299669a5db411d85a14f86cd92bc16bf7ab5b8aa235Jeff Garzik	.set_dmamode	= hpt366_set_dmamode,
30085cd7251b9112e3dabeac9fd3b175601ca607241Jeff Garzik};
301669a5db411d85a14f86cd92bc16bf7ab5b8aa235Jeff Garzik
302669a5db411d85a14f86cd92bc16bf7ab5b8aa235Jeff Garzik/**
303aa54ab1eff30f1e5859acf4e15f0730288373ee5Alan Cox *	hpt36x_init_chipset	-	common chip setup
304aa54ab1eff30f1e5859acf4e15f0730288373ee5Alan Cox *	@dev: PCI device
305aa54ab1eff30f1e5859acf4e15f0730288373ee5Alan Cox *
306aa54ab1eff30f1e5859acf4e15f0730288373ee5Alan Cox *	Perform the chip setup work that must be done at both init and
307aa54ab1eff30f1e5859acf4e15f0730288373ee5Alan Cox *	resume time
308aa54ab1eff30f1e5859acf4e15f0730288373ee5Alan Cox */
309aa54ab1eff30f1e5859acf4e15f0730288373ee5Alan Cox
310aa54ab1eff30f1e5859acf4e15f0730288373ee5Alan Coxstatic void hpt36x_init_chipset(struct pci_dev *dev)
311aa54ab1eff30f1e5859acf4e15f0730288373ee5Alan Cox{
312aa54ab1eff30f1e5859acf4e15f0730288373ee5Alan Cox	u8 drive_fast;
31328cd4b6b4850d7588f1033c3808314b6bc2150d5Sergei Shtylyov
314aa54ab1eff30f1e5859acf4e15f0730288373ee5Alan Cox	pci_write_config_byte(dev, PCI_CACHE_LINE_SIZE, (L1_CACHE_BYTES / 4));
315aa54ab1eff30f1e5859acf4e15f0730288373ee5Alan Cox	pci_write_config_byte(dev, PCI_LATENCY_TIMER, 0x78);
316aa54ab1eff30f1e5859acf4e15f0730288373ee5Alan Cox	pci_write_config_byte(dev, PCI_MIN_GNT, 0x08);
317aa54ab1eff30f1e5859acf4e15f0730288373ee5Alan Cox	pci_write_config_byte(dev, PCI_MAX_LAT, 0x08);
318aa54ab1eff30f1e5859acf4e15f0730288373ee5Alan Cox
319aa54ab1eff30f1e5859acf4e15f0730288373ee5Alan Cox	pci_read_config_byte(dev, 0x51, &drive_fast);
320aa54ab1eff30f1e5859acf4e15f0730288373ee5Alan Cox	if (drive_fast & 0x80)
321aa54ab1eff30f1e5859acf4e15f0730288373ee5Alan Cox		pci_write_config_byte(dev, 0x51, drive_fast & ~0x80);
322aa54ab1eff30f1e5859acf4e15f0730288373ee5Alan Cox}
323aa54ab1eff30f1e5859acf4e15f0730288373ee5Alan Cox
324aa54ab1eff30f1e5859acf4e15f0730288373ee5Alan Cox/**
325669a5db411d85a14f86cd92bc16bf7ab5b8aa235Jeff Garzik *	hpt36x_init_one		-	Initialise an HPT366/368
326669a5db411d85a14f86cd92bc16bf7ab5b8aa235Jeff Garzik *	@dev: PCI device
327669a5db411d85a14f86cd92bc16bf7ab5b8aa235Jeff Garzik *	@id: Entry in match table
328669a5db411d85a14f86cd92bc16bf7ab5b8aa235Jeff Garzik *
329669a5db411d85a14f86cd92bc16bf7ab5b8aa235Jeff Garzik *	Initialise an HPT36x device. There are some interesting complications
330669a5db411d85a14f86cd92bc16bf7ab5b8aa235Jeff Garzik *	here. Firstly the chip may report 366 and be one of several variants.
331669a5db411d85a14f86cd92bc16bf7ab5b8aa235Jeff Garzik *	Secondly all the timings depend on the clock for the chip which we must
332669a5db411d85a14f86cd92bc16bf7ab5b8aa235Jeff Garzik *	detect and look up
333669a5db411d85a14f86cd92bc16bf7ab5b8aa235Jeff Garzik *
334669a5db411d85a14f86cd92bc16bf7ab5b8aa235Jeff Garzik *	This is the known chip mappings. It may be missing a couple of later
335669a5db411d85a14f86cd92bc16bf7ab5b8aa235Jeff Garzik *	releases.
336669a5db411d85a14f86cd92bc16bf7ab5b8aa235Jeff Garzik *
337669a5db411d85a14f86cd92bc16bf7ab5b8aa235Jeff Garzik *	Chip version		PCI		Rev	Notes
338669a5db411d85a14f86cd92bc16bf7ab5b8aa235Jeff Garzik *	HPT366			4 (HPT366)	0	UDMA66
339669a5db411d85a14f86cd92bc16bf7ab5b8aa235Jeff Garzik *	HPT366			4 (HPT366)	1	UDMA66
340669a5db411d85a14f86cd92bc16bf7ab5b8aa235Jeff Garzik *	HPT368			4 (HPT366)	2	UDMA66
341669a5db411d85a14f86cd92bc16bf7ab5b8aa235Jeff Garzik *	HPT37x/30x		4 (HPT366)	3+	Other driver
342669a5db411d85a14f86cd92bc16bf7ab5b8aa235Jeff Garzik *
343669a5db411d85a14f86cd92bc16bf7ab5b8aa235Jeff Garzik */
34485cd7251b9112e3dabeac9fd3b175601ca607241Jeff Garzik
345669a5db411d85a14f86cd92bc16bf7ab5b8aa235Jeff Garzikstatic int hpt36x_init_one(struct pci_dev *dev, const struct pci_device_id *id)
346669a5db411d85a14f86cd92bc16bf7ab5b8aa235Jeff Garzik{
3471626aeb881236c8cb022b5e4ca594146a951d669Tejun Heo	static const struct ata_port_info info_hpt366 = {
3481d2808fd3d2d5d2c0483796a0f443d1cb3f11367Jeff Garzik		.flags = ATA_FLAG_SLAVE_POSS,
34914bdef982caeda19afe34010482867c18217c641Erik Inge Bolsø		.pio_mask = ATA_PIO4,
35014bdef982caeda19afe34010482867c18217c641Erik Inge Bolsø		.mwdma_mask = ATA_MWDMA2,
351bf6263a853c9c143bf03f0a6fdcc68ab714fb5f5Jeff Garzik		.udma_mask = ATA_UDMA4,
352669a5db411d85a14f86cd92bc16bf7ab5b8aa235Jeff Garzik		.port_ops = &hpt366_port_ops
353669a5db411d85a14f86cd92bc16bf7ab5b8aa235Jeff Garzik	};
354887125e3740283be25564bfc6fb5d24974b651abTejun Heo	const struct ata_port_info *ppi[] = { &info_hpt366, NULL };
355669a5db411d85a14f86cd92bc16bf7ab5b8aa235Jeff Garzik
356887125e3740283be25564bfc6fb5d24974b651abTejun Heo	void *hpriv = NULL;
357669a5db411d85a14f86cd92bc16bf7ab5b8aa235Jeff Garzik	u32 reg1;
358f08048e94564d009b19038cfbdd800aa83e79c7fTejun Heo	int rc;
359f08048e94564d009b19038cfbdd800aa83e79c7fTejun Heo
360f08048e94564d009b19038cfbdd800aa83e79c7fTejun Heo	rc = pcim_enable_device(dev);
361f08048e94564d009b19038cfbdd800aa83e79c7fTejun Heo	if (rc)
362f08048e94564d009b19038cfbdd800aa83e79c7fTejun Heo		return rc;
363669a5db411d85a14f86cd92bc16bf7ab5b8aa235Jeff Garzik
364669a5db411d85a14f86cd92bc16bf7ab5b8aa235Jeff Garzik	/* May be a later chip in disguise. Check */
365669a5db411d85a14f86cd92bc16bf7ab5b8aa235Jeff Garzik	/* Newer chips are not in the HPT36x driver. Ignore them */
36689d3b3603bfb648e0113d8682d4f84dd18a776bdSergei Shtylyov	if (dev->revision > 2)
36789d3b3603bfb648e0113d8682d4f84dd18a776bdSergei Shtylyov		return -ENODEV;
368669a5db411d85a14f86cd92bc16bf7ab5b8aa235Jeff Garzik
369aa54ab1eff30f1e5859acf4e15f0730288373ee5Alan Cox	hpt36x_init_chipset(dev);
370669a5db411d85a14f86cd92bc16bf7ab5b8aa235Jeff Garzik
371669a5db411d85a14f86cd92bc16bf7ab5b8aa235Jeff Garzik	pci_read_config_dword(dev, 0x40,  &reg1);
37285cd7251b9112e3dabeac9fd3b175601ca607241Jeff Garzik
373669a5db411d85a14f86cd92bc16bf7ab5b8aa235Jeff Garzik	/* PCI clocking determines the ATA timing values to use */
374669a5db411d85a14f86cd92bc16bf7ab5b8aa235Jeff Garzik	/* info_hpt366 is safe against re-entry so we can scribble on it */
37528cd4b6b4850d7588f1033c3808314b6bc2150d5Sergei Shtylyov	switch ((reg1 & 0x700) >> 8) {
37628cd4b6b4850d7588f1033c3808314b6bc2150d5Sergei Shtylyov	case 9:
37728cd4b6b4850d7588f1033c3808314b6bc2150d5Sergei Shtylyov		hpriv = &hpt366_40;
37828cd4b6b4850d7588f1033c3808314b6bc2150d5Sergei Shtylyov		break;
37928cd4b6b4850d7588f1033c3808314b6bc2150d5Sergei Shtylyov	case 5:
38028cd4b6b4850d7588f1033c3808314b6bc2150d5Sergei Shtylyov		hpriv = &hpt366_25;
38128cd4b6b4850d7588f1033c3808314b6bc2150d5Sergei Shtylyov		break;
38228cd4b6b4850d7588f1033c3808314b6bc2150d5Sergei Shtylyov	default:
38328cd4b6b4850d7588f1033c3808314b6bc2150d5Sergei Shtylyov		hpriv = &hpt366_33;
38428cd4b6b4850d7588f1033c3808314b6bc2150d5Sergei Shtylyov		break;
385669a5db411d85a14f86cd92bc16bf7ab5b8aa235Jeff Garzik	}
386669a5db411d85a14f86cd92bc16bf7ab5b8aa235Jeff Garzik	/* Now kick off ATA set up */
3871c5afdf7a629d2e77de8dd043b97a33dcd7e6dfaTejun Heo	return ata_pci_bmdma_init_one(dev, ppi, &hpt36x_sht, hpriv, 0);
388669a5db411d85a14f86cd92bc16bf7ab5b8aa235Jeff Garzik}
389669a5db411d85a14f86cd92bc16bf7ab5b8aa235Jeff Garzik
390438ac6d5e3f8106a6bd1a5682c508d660294a85dTejun Heo#ifdef CONFIG_PM
391aa54ab1eff30f1e5859acf4e15f0730288373ee5Alan Coxstatic int hpt36x_reinit_one(struct pci_dev *dev)
392aa54ab1eff30f1e5859acf4e15f0730288373ee5Alan Cox{
393f08048e94564d009b19038cfbdd800aa83e79c7fTejun Heo	struct ata_host *host = dev_get_drvdata(&dev->dev);
394f08048e94564d009b19038cfbdd800aa83e79c7fTejun Heo	int rc;
395f08048e94564d009b19038cfbdd800aa83e79c7fTejun Heo
396f08048e94564d009b19038cfbdd800aa83e79c7fTejun Heo	rc = ata_pci_device_do_resume(dev);
397f08048e94564d009b19038cfbdd800aa83e79c7fTejun Heo	if (rc)
398f08048e94564d009b19038cfbdd800aa83e79c7fTejun Heo		return rc;
399aa54ab1eff30f1e5859acf4e15f0730288373ee5Alan Cox	hpt36x_init_chipset(dev);
400f08048e94564d009b19038cfbdd800aa83e79c7fTejun Heo	ata_host_resume(host);
401f08048e94564d009b19038cfbdd800aa83e79c7fTejun Heo	return 0;
402aa54ab1eff30f1e5859acf4e15f0730288373ee5Alan Cox}
403438ac6d5e3f8106a6bd1a5682c508d660294a85dTejun Heo#endif
404aa54ab1eff30f1e5859acf4e15f0730288373ee5Alan Cox
4052d2744fc8be620a2dc469cf48349e3e704119f1bJeff Garzikstatic const struct pci_device_id hpt36x[] = {
4062d2744fc8be620a2dc469cf48349e3e704119f1bJeff Garzik	{ PCI_VDEVICE(TTI, PCI_DEVICE_ID_TTI_HPT366), },
4072d2744fc8be620a2dc469cf48349e3e704119f1bJeff Garzik	{ },
408669a5db411d85a14f86cd92bc16bf7ab5b8aa235Jeff Garzik};
409669a5db411d85a14f86cd92bc16bf7ab5b8aa235Jeff Garzik
410669a5db411d85a14f86cd92bc16bf7ab5b8aa235Jeff Garzikstatic struct pci_driver hpt36x_pci_driver = {
41128cd4b6b4850d7588f1033c3808314b6bc2150d5Sergei Shtylyov	.name		= DRV_NAME,
412669a5db411d85a14f86cd92bc16bf7ab5b8aa235Jeff Garzik	.id_table	= hpt36x,
41328cd4b6b4850d7588f1033c3808314b6bc2150d5Sergei Shtylyov	.probe		= hpt36x_init_one,
414aa54ab1eff30f1e5859acf4e15f0730288373ee5Alan Cox	.remove		= ata_pci_remove_one,
415438ac6d5e3f8106a6bd1a5682c508d660294a85dTejun Heo#ifdef CONFIG_PM
416aa54ab1eff30f1e5859acf4e15f0730288373ee5Alan Cox	.suspend	= ata_pci_device_suspend,
417aa54ab1eff30f1e5859acf4e15f0730288373ee5Alan Cox	.resume		= hpt36x_reinit_one,
418438ac6d5e3f8106a6bd1a5682c508d660294a85dTejun Heo#endif
419669a5db411d85a14f86cd92bc16bf7ab5b8aa235Jeff Garzik};
420669a5db411d85a14f86cd92bc16bf7ab5b8aa235Jeff Garzik
421669a5db411d85a14f86cd92bc16bf7ab5b8aa235Jeff Garzikstatic int __init hpt36x_init(void)
422669a5db411d85a14f86cd92bc16bf7ab5b8aa235Jeff Garzik{
423669a5db411d85a14f86cd92bc16bf7ab5b8aa235Jeff Garzik	return pci_register_driver(&hpt36x_pci_driver);
424669a5db411d85a14f86cd92bc16bf7ab5b8aa235Jeff Garzik}
425669a5db411d85a14f86cd92bc16bf7ab5b8aa235Jeff Garzik
426669a5db411d85a14f86cd92bc16bf7ab5b8aa235Jeff Garzikstatic void __exit hpt36x_exit(void)
427669a5db411d85a14f86cd92bc16bf7ab5b8aa235Jeff Garzik{
428669a5db411d85a14f86cd92bc16bf7ab5b8aa235Jeff Garzik	pci_unregister_driver(&hpt36x_pci_driver);
429669a5db411d85a14f86cd92bc16bf7ab5b8aa235Jeff Garzik}
430669a5db411d85a14f86cd92bc16bf7ab5b8aa235Jeff Garzik
431669a5db411d85a14f86cd92bc16bf7ab5b8aa235Jeff GarzikMODULE_AUTHOR("Alan Cox");
432669a5db411d85a14f86cd92bc16bf7ab5b8aa235Jeff GarzikMODULE_DESCRIPTION("low-level driver for the Highpoint HPT366/368");
433669a5db411d85a14f86cd92bc16bf7ab5b8aa235Jeff GarzikMODULE_LICENSE("GPL");
434669a5db411d85a14f86cd92bc16bf7ab5b8aa235Jeff GarzikMODULE_DEVICE_TABLE(pci, hpt36x);
435669a5db411d85a14f86cd92bc16bf7ab5b8aa235Jeff GarzikMODULE_VERSION(DRV_VERSION);
436669a5db411d85a14f86cd92bc16bf7ab5b8aa235Jeff Garzik
437669a5db411d85a14f86cd92bc16bf7ab5b8aa235Jeff Garzikmodule_init(hpt36x_init);
438669a5db411d85a14f86cd92bc16bf7ab5b8aa235Jeff Garzikmodule_exit(hpt36x_exit);
439