xref: /openbmc/linux/drivers/ata/pata_hpt366.c (revision 1ac731c529cd4d6adbce134754b51ff7d822b145)
109c434b8SThomas Gleixner // SPDX-License-Identifier: GPL-2.0-only
2669a5db4SJeff Garzik /*
3669a5db4SJeff Garzik  * Libata driver for the highpoint 366 and 368 UDMA66 ATA controllers.
4669a5db4SJeff Garzik  *
5669a5db4SJeff Garzik  * This driver is heavily based upon:
6669a5db4SJeff Garzik  *
7669a5db4SJeff Garzik  * linux/drivers/ide/pci/hpt366.c		Version 0.36	April 25, 2003
8669a5db4SJeff Garzik  *
9669a5db4SJeff Garzik  * Copyright (C) 1999-2003		Andre Hedrick <andre@linux-ide.org>
10669a5db4SJeff Garzik  * Portions Copyright (C) 2001	        Sun Microsystems, Inc.
11669a5db4SJeff Garzik  * Portions Copyright (C) 2003		Red Hat Inc
12669a5db4SJeff Garzik  *
13669a5db4SJeff Garzik  *
14669a5db4SJeff Garzik  * TODO
15d817898cSSergei Shtylyov  *	Look into engine reset on timeout errors. Should not be required.
16669a5db4SJeff Garzik  */
17669a5db4SJeff Garzik #include <linux/kernel.h>
18669a5db4SJeff Garzik #include <linux/module.h>
19669a5db4SJeff Garzik #include <linux/pci.h>
20669a5db4SJeff Garzik #include <linux/blkdev.h>
21669a5db4SJeff Garzik #include <linux/delay.h>
22669a5db4SJeff Garzik #include <scsi/scsi_host.h>
23669a5db4SJeff Garzik #include <linux/libata.h>
24669a5db4SJeff Garzik 
25669a5db4SJeff Garzik #define DRV_NAME	"pata_hpt366"
26a58ff050SSergey Shtylyov #define DRV_VERSION	"0.6.13"
27669a5db4SJeff Garzik 
28669a5db4SJeff Garzik struct hpt_clock {
296ecb6f25STejun Heo 	u8	xfer_mode;
30669a5db4SJeff Garzik 	u32	timing;
31669a5db4SJeff Garzik };
32669a5db4SJeff Garzik 
33669a5db4SJeff Garzik /* key for bus clock timings
34669a5db4SJeff Garzik  * bit
3582beb5d8SSergei Shtylyov  * 0:3    data_high_time. Inactive time of DIOW_/DIOR_ for PIO and MW DMA.
3682beb5d8SSergei Shtylyov  *        cycles = value + 1
3782beb5d8SSergei Shtylyov  * 4:7    data_low_time. Active time of DIOW_/DIOR_ for PIO and MW DMA.
3882beb5d8SSergei Shtylyov  *        cycles = value + 1
3982beb5d8SSergei Shtylyov  * 8:11   cmd_high_time. Inactive time of DIOW_/DIOR_ during task file
40669a5db4SJeff Garzik  *        register access.
4182beb5d8SSergei Shtylyov  * 12:15  cmd_low_time. Active time of DIOW_/DIOR_ during task file
42669a5db4SJeff Garzik  *        register access.
4382beb5d8SSergei Shtylyov  * 16:18  udma_cycle_time. Clock cycles for UDMA xfer?
4482beb5d8SSergei Shtylyov  * 19:21  pre_high_time. Time to initialize 1st cycle for PIO and MW DMA xfer.
4582beb5d8SSergei Shtylyov  * 22:24  cmd_pre_high_time. Time to initialize 1st PIO cycle for task file
46669a5db4SJeff Garzik  *        register access.
4782beb5d8SSergei Shtylyov  * 28     UDMA enable.
4882beb5d8SSergei Shtylyov  * 29     DMA  enable.
4982beb5d8SSergei Shtylyov  * 30     PIO_MST enable. If set, the chip is in bus master mode during
5082beb5d8SSergei Shtylyov  *        PIO xfer.
51669a5db4SJeff Garzik  * 31     FIFO enable.
52669a5db4SJeff Garzik  */
53669a5db4SJeff Garzik 
54669a5db4SJeff Garzik static const struct hpt_clock hpt366_40[] = {
55669a5db4SJeff Garzik 	{	XFER_UDMA_4,	0x900fd943	},
56669a5db4SJeff Garzik 	{	XFER_UDMA_3,	0x900ad943	},
57669a5db4SJeff Garzik 	{	XFER_UDMA_2,	0x900bd943	},
58669a5db4SJeff Garzik 	{	XFER_UDMA_1,	0x9008d943	},
59669a5db4SJeff Garzik 	{	XFER_UDMA_0,	0x9008d943	},
60669a5db4SJeff Garzik 
61669a5db4SJeff Garzik 	{	XFER_MW_DMA_2,	0xa008d943	},
62669a5db4SJeff Garzik 	{	XFER_MW_DMA_1,	0xa010d955	},
63669a5db4SJeff Garzik 	{	XFER_MW_DMA_0,	0xa010d9fc	},
64669a5db4SJeff Garzik 
65669a5db4SJeff Garzik 	{	XFER_PIO_4,	0xc008d963	},
66669a5db4SJeff Garzik 	{	XFER_PIO_3,	0xc010d974	},
67669a5db4SJeff Garzik 	{	XFER_PIO_2,	0xc010d997	},
68669a5db4SJeff Garzik 	{	XFER_PIO_1,	0xc010d9c7	},
69669a5db4SJeff Garzik 	{	XFER_PIO_0,	0xc018d9d9	},
70669a5db4SJeff Garzik 	{	0,		0x0120d9d9	}
71669a5db4SJeff Garzik };
72669a5db4SJeff Garzik 
73669a5db4SJeff Garzik static const struct hpt_clock hpt366_33[] = {
74669a5db4SJeff Garzik 	{	XFER_UDMA_4,	0x90c9a731	},
75669a5db4SJeff Garzik 	{	XFER_UDMA_3,	0x90cfa731	},
76669a5db4SJeff Garzik 	{	XFER_UDMA_2,	0x90caa731	},
77669a5db4SJeff Garzik 	{	XFER_UDMA_1,	0x90cba731	},
78669a5db4SJeff Garzik 	{	XFER_UDMA_0,	0x90c8a731	},
79669a5db4SJeff Garzik 
80669a5db4SJeff Garzik 	{	XFER_MW_DMA_2,	0xa0c8a731	},
81669a5db4SJeff Garzik 	{	XFER_MW_DMA_1,	0xa0c8a732	},	/* 0xa0c8a733 */
82669a5db4SJeff Garzik 	{	XFER_MW_DMA_0,	0xa0c8a797	},
83669a5db4SJeff Garzik 
84669a5db4SJeff Garzik 	{	XFER_PIO_4,	0xc0c8a731	},
85669a5db4SJeff Garzik 	{	XFER_PIO_3,	0xc0c8a742	},
86669a5db4SJeff Garzik 	{	XFER_PIO_2,	0xc0d0a753	},
87669a5db4SJeff Garzik 	{	XFER_PIO_1,	0xc0d0a7a3	},	/* 0xc0d0a793 */
88669a5db4SJeff Garzik 	{	XFER_PIO_0,	0xc0d0a7aa	},	/* 0xc0d0a7a7 */
89669a5db4SJeff Garzik 	{	0,		0x0120a7a7	}
90669a5db4SJeff Garzik };
91669a5db4SJeff Garzik 
92669a5db4SJeff Garzik static const struct hpt_clock hpt366_25[] = {
93669a5db4SJeff Garzik 	{	XFER_UDMA_4,	0x90c98521	},
94669a5db4SJeff Garzik 	{	XFER_UDMA_3,	0x90cf8521	},
95669a5db4SJeff Garzik 	{	XFER_UDMA_2,	0x90cf8521	},
96669a5db4SJeff Garzik 	{	XFER_UDMA_1,	0x90cb8521	},
97669a5db4SJeff Garzik 	{	XFER_UDMA_0,	0x90cb8521	},
98669a5db4SJeff Garzik 
99669a5db4SJeff Garzik 	{	XFER_MW_DMA_2,	0xa0ca8521	},
100669a5db4SJeff Garzik 	{	XFER_MW_DMA_1,	0xa0ca8532	},
101669a5db4SJeff Garzik 	{	XFER_MW_DMA_0,	0xa0ca8575	},
102669a5db4SJeff Garzik 
103669a5db4SJeff Garzik 	{	XFER_PIO_4,	0xc0ca8521	},
104669a5db4SJeff Garzik 	{	XFER_PIO_3,	0xc0ca8532	},
105669a5db4SJeff Garzik 	{	XFER_PIO_2,	0xc0ca8542	},
106669a5db4SJeff Garzik 	{	XFER_PIO_1,	0xc0d08572	},
107669a5db4SJeff Garzik 	{	XFER_PIO_0,	0xc0d08585	},
108669a5db4SJeff Garzik 	{	0,		0x01208585	}
109669a5db4SJeff Garzik };
110669a5db4SJeff Garzik 
111dc5e44ecSBartlomiej Zolnierkiewicz /**
112dc5e44ecSBartlomiej Zolnierkiewicz  *	hpt36x_find_mode	-	find the hpt36x timing
113dc5e44ecSBartlomiej Zolnierkiewicz  *	@ap: ATA port
114dc5e44ecSBartlomiej Zolnierkiewicz  *	@speed: transfer mode
115dc5e44ecSBartlomiej Zolnierkiewicz  *
116dc5e44ecSBartlomiej Zolnierkiewicz  *	Return the 32bit register programming information for this channel
117dc5e44ecSBartlomiej Zolnierkiewicz  *	that matches the speed provided.
118dc5e44ecSBartlomiej Zolnierkiewicz  */
119dc5e44ecSBartlomiej Zolnierkiewicz 
hpt36x_find_mode(struct ata_port * ap,int speed)120dc5e44ecSBartlomiej Zolnierkiewicz static u32 hpt36x_find_mode(struct ata_port *ap, int speed)
121dc5e44ecSBartlomiej Zolnierkiewicz {
122dc5e44ecSBartlomiej Zolnierkiewicz 	struct hpt_clock *clocks = ap->host->private_data;
123dc5e44ecSBartlomiej Zolnierkiewicz 
124dc5e44ecSBartlomiej Zolnierkiewicz 	while (clocks->xfer_mode) {
125dc5e44ecSBartlomiej Zolnierkiewicz 		if (clocks->xfer_mode == speed)
126dc5e44ecSBartlomiej Zolnierkiewicz 			return clocks->timing;
127dc5e44ecSBartlomiej Zolnierkiewicz 		clocks++;
128dc5e44ecSBartlomiej Zolnierkiewicz 	}
129dc5e44ecSBartlomiej Zolnierkiewicz 	BUG();
130dc5e44ecSBartlomiej Zolnierkiewicz 	return 0xffffffffU;	/* silence compiler warning */
131dc5e44ecSBartlomiej Zolnierkiewicz }
132dc5e44ecSBartlomiej Zolnierkiewicz 
13328cd4b6bSSergei Shtylyov static const char * const bad_ata33[] = {
13428cd4b6bSSergei Shtylyov 	"Maxtor 92720U8", "Maxtor 92040U6", "Maxtor 91360U4", "Maxtor 91020U3",
13528cd4b6bSSergei Shtylyov 	"Maxtor 90845U3", "Maxtor 90650U2",
13628cd4b6bSSergei Shtylyov 	"Maxtor 91360D8", "Maxtor 91190D7", "Maxtor 91020D6", "Maxtor 90845D5",
13728cd4b6bSSergei Shtylyov 	"Maxtor 90680D4", "Maxtor 90510D3", "Maxtor 90340D2",
13828cd4b6bSSergei Shtylyov 	"Maxtor 91152D8", "Maxtor 91008D7", "Maxtor 90845D6", "Maxtor 90840D6",
13928cd4b6bSSergei Shtylyov 	"Maxtor 90720D5", "Maxtor 90648D5", "Maxtor 90576D4",
140669a5db4SJeff Garzik 	"Maxtor 90510D4",
141669a5db4SJeff Garzik 	"Maxtor 90432D3", "Maxtor 90288D2", "Maxtor 90256D2",
14228cd4b6bSSergei Shtylyov 	"Maxtor 91000D8", "Maxtor 90910D8", "Maxtor 90875D7", "Maxtor 90840D7",
14328cd4b6bSSergei Shtylyov 	"Maxtor 90750D6", "Maxtor 90625D5", "Maxtor 90500D4",
14428cd4b6bSSergei Shtylyov 	"Maxtor 91728D8", "Maxtor 91512D7", "Maxtor 91303D6", "Maxtor 91080D5",
14528cd4b6bSSergei Shtylyov 	"Maxtor 90845D4", "Maxtor 90680D4", "Maxtor 90648D3", "Maxtor 90432D2",
146669a5db4SJeff Garzik 	NULL
147669a5db4SJeff Garzik };
148669a5db4SJeff Garzik 
14928cd4b6bSSergei Shtylyov static const char * const bad_ata66_4[] = {
150669a5db4SJeff Garzik 	"IBM-DTLA-307075",
151669a5db4SJeff Garzik 	"IBM-DTLA-307060",
152669a5db4SJeff Garzik 	"IBM-DTLA-307045",
153669a5db4SJeff Garzik 	"IBM-DTLA-307030",
154669a5db4SJeff Garzik 	"IBM-DTLA-307020",
155669a5db4SJeff Garzik 	"IBM-DTLA-307015",
156669a5db4SJeff Garzik 	"IBM-DTLA-305040",
157669a5db4SJeff Garzik 	"IBM-DTLA-305030",
158669a5db4SJeff Garzik 	"IBM-DTLA-305020",
159669a5db4SJeff Garzik 	"IC35L010AVER07-0",
160669a5db4SJeff Garzik 	"IC35L020AVER07-0",
161669a5db4SJeff Garzik 	"IC35L030AVER07-0",
162669a5db4SJeff Garzik 	"IC35L040AVER07-0",
163669a5db4SJeff Garzik 	"IC35L060AVER07-0",
164669a5db4SJeff Garzik 	"WDC AC310200R",
165669a5db4SJeff Garzik 	NULL
166669a5db4SJeff Garzik };
167669a5db4SJeff Garzik 
16828cd4b6bSSergei Shtylyov static const char * const bad_ata66_3[] = {
169669a5db4SJeff Garzik 	"WDC AC310200R",
170669a5db4SJeff Garzik 	NULL
171669a5db4SJeff Garzik };
172669a5db4SJeff Garzik 
hpt_dma_blacklisted(const struct ata_device * dev,char * modestr,const char * const list[])17328cd4b6bSSergei Shtylyov static int hpt_dma_blacklisted(const struct ata_device *dev, char *modestr,
17428cd4b6bSSergei Shtylyov 			       const char * const list[])
175669a5db4SJeff Garzik {
1768bfa79fcSTejun Heo 	unsigned char model_num[ATA_ID_PROD_LEN + 1];
177908913bdSAndy Shevchenko 	int i;
178669a5db4SJeff Garzik 
1798bfa79fcSTejun Heo 	ata_id_c_string(dev->id, model_num, ATA_ID_PROD, sizeof(model_num));
180669a5db4SJeff Garzik 
181908913bdSAndy Shevchenko 	i = match_string(list, -1, model_num);
182908913bdSAndy Shevchenko 	if (i >= 0) {
183cbc59b8cSHannes Reinecke 		ata_dev_warn(dev, "%s is not supported for %s\n", modestr, list[i]);
184669a5db4SJeff Garzik 		return 1;
185669a5db4SJeff Garzik 	}
186669a5db4SJeff Garzik 	return 0;
187669a5db4SJeff Garzik }
188669a5db4SJeff Garzik 
189669a5db4SJeff Garzik /**
190669a5db4SJeff Garzik  *	hpt366_filter	-	mode selection filter
191669a5db4SJeff Garzik  *	@adev: ATA device
192d6c2aaaeSLee Jones  *	@mask: Current mask to manipulate and pass back
193669a5db4SJeff Garzik  *
194669a5db4SJeff Garzik  *	Block UDMA on devices that cause trouble with this controller.
195669a5db4SJeff Garzik  */
196669a5db4SJeff Garzik 
hpt366_filter(struct ata_device * adev,unsigned int mask)197f0a6d77bSSergey Shtylyov static unsigned int hpt366_filter(struct ata_device *adev, unsigned int mask)
198669a5db4SJeff Garzik {
199669a5db4SJeff Garzik 	if (adev->class == ATA_DEV_ATA) {
200669a5db4SJeff Garzik 		if (hpt_dma_blacklisted(adev, "UDMA",  bad_ata33))
201669a5db4SJeff Garzik 			mask &= ~ATA_MASK_UDMA;
202669a5db4SJeff Garzik 		if (hpt_dma_blacklisted(adev, "UDMA3", bad_ata66_3))
2036ddd6861SAlan Cox 			mask &= ~(0xF8 << ATA_SHIFT_UDMA);
204669a5db4SJeff Garzik 		if (hpt_dma_blacklisted(adev, "UDMA4", bad_ata66_4))
2056ddd6861SAlan Cox 			mask &= ~(0xF0 << ATA_SHIFT_UDMA);
2063ee89f17STejun Heo 	} else if (adev->class == ATA_DEV_ATAPI)
2073ee89f17STejun Heo 		mask &= ~(ATA_MASK_MWDMA | ATA_MASK_UDMA);
2083ee89f17STejun Heo 
209c7087652STejun Heo 	return mask;
210669a5db4SJeff Garzik }
211669a5db4SJeff Garzik 
hpt36x_cable_detect(struct ata_port * ap)212fecfda5dSAlan Cox static int hpt36x_cable_detect(struct ata_port *ap)
213fecfda5dSAlan Cox {
214fecfda5dSAlan Cox 	struct pci_dev *pdev = to_pci_dev(ap->host->dev);
215bab5b32aSTejun Heo 	u8 ata66;
216fecfda5dSAlan Cox 
217bab5b32aSTejun Heo 	/*
218bab5b32aSTejun Heo 	 * Each channel of pata_hpt366 occupies separate PCI function
219bab5b32aSTejun Heo 	 * as the primary channel and bit1 indicates the cable type.
220bab5b32aSTejun Heo 	 */
221fecfda5dSAlan Cox 	pci_read_config_byte(pdev, 0x5A, &ata66);
222bab5b32aSTejun Heo 	if (ata66 & 2)
223fecfda5dSAlan Cox 		return ATA_CBL_PATA40;
224fecfda5dSAlan Cox 	return ATA_CBL_PATA80;
225fecfda5dSAlan Cox }
226fecfda5dSAlan Cox 
hpt366_set_mode(struct ata_port * ap,struct ata_device * adev,u8 mode)2276ecb6f25STejun Heo static void hpt366_set_mode(struct ata_port *ap, struct ata_device *adev,
2286ecb6f25STejun Heo 			    u8 mode)
2296ecb6f25STejun Heo {
2306ecb6f25STejun Heo 	struct pci_dev *pdev = to_pci_dev(ap->host->dev);
231859faa87SSergei Shtylyov 	u32 addr = 0x40 + 4 * adev->devno;
232dc5e44ecSBartlomiej Zolnierkiewicz 	u32 mask, reg, t;
2336ecb6f25STejun Heo 
2346ecb6f25STejun Heo 	/* determine timing mask and find matching clock entry */
2356ecb6f25STejun Heo 	if (mode < XFER_MW_DMA_0)
2366ecb6f25STejun Heo 		mask = 0xc1f8ffff;
2376ecb6f25STejun Heo 	else if (mode < XFER_UDMA_0)
2386ecb6f25STejun Heo 		mask = 0x303800ff;
2396ecb6f25STejun Heo 	else
2406ecb6f25STejun Heo 		mask = 0x30070000;
2416ecb6f25STejun Heo 
242dc5e44ecSBartlomiej Zolnierkiewicz 	t = hpt36x_find_mode(ap, mode);
2436ecb6f25STejun Heo 
2446ecb6f25STejun Heo 	/*
2456ecb6f25STejun Heo 	 * Combine new mode bits with old config bits and disable
2466ecb6f25STejun Heo 	 * on-chip PIO FIFO/buffer (and PIO MST mode as well) to avoid
2476ecb6f25STejun Heo 	 * problems handling I/O errors later.
2486ecb6f25STejun Heo 	 */
249859faa87SSergei Shtylyov 	pci_read_config_dword(pdev, addr, &reg);
250dc5e44ecSBartlomiej Zolnierkiewicz 	reg = ((reg & ~mask) | (t & mask)) & ~0xc0000000;
251859faa87SSergei Shtylyov 	pci_write_config_dword(pdev, addr, reg);
2526ecb6f25STejun Heo }
2536ecb6f25STejun Heo 
254669a5db4SJeff Garzik /**
255669a5db4SJeff Garzik  *	hpt366_set_piomode		-	PIO setup
256669a5db4SJeff Garzik  *	@ap: ATA interface
257669a5db4SJeff Garzik  *	@adev: device on the interface
258669a5db4SJeff Garzik  *
259669a5db4SJeff Garzik  *	Perform PIO mode setup.
260669a5db4SJeff Garzik  */
261669a5db4SJeff Garzik 
hpt366_set_piomode(struct ata_port * ap,struct ata_device * adev)262669a5db4SJeff Garzik static void hpt366_set_piomode(struct ata_port *ap, struct ata_device *adev)
263669a5db4SJeff Garzik {
2646ecb6f25STejun Heo 	hpt366_set_mode(ap, adev, adev->pio_mode);
265669a5db4SJeff Garzik }
266669a5db4SJeff Garzik 
267669a5db4SJeff Garzik /**
268669a5db4SJeff Garzik  *	hpt366_set_dmamode		-	DMA timing setup
269669a5db4SJeff Garzik  *	@ap: ATA interface
270669a5db4SJeff Garzik  *	@adev: Device being configured
271669a5db4SJeff Garzik  *
272669a5db4SJeff Garzik  *	Set up the channel for MWDMA or UDMA modes. Much the same as with
273669a5db4SJeff Garzik  *	PIO, load the mode number and then set MWDMA or UDMA flag.
274669a5db4SJeff Garzik  */
275669a5db4SJeff Garzik 
hpt366_set_dmamode(struct ata_port * ap,struct ata_device * adev)276669a5db4SJeff Garzik static void hpt366_set_dmamode(struct ata_port *ap, struct ata_device *adev)
277669a5db4SJeff Garzik {
2786ecb6f25STejun Heo 	hpt366_set_mode(ap, adev, adev->dma_mode);
279669a5db4SJeff Garzik }
280669a5db4SJeff Garzik 
281f79ca455SSergey Shtylyov /**
282f79ca455SSergey Shtylyov  *	hpt366_prereset		-	reset the hpt36x bus
283f79ca455SSergey Shtylyov  *	@link: ATA link to reset
284f79ca455SSergey Shtylyov  *	@deadline: deadline jiffies for the operation
285f79ca455SSergey Shtylyov  *
286f79ca455SSergey Shtylyov  *	Perform the initial reset handling for the 36x series controllers.
287f79ca455SSergey Shtylyov  *	Reset the hardware and state machine,
288f79ca455SSergey Shtylyov  */
289f79ca455SSergey Shtylyov 
hpt366_prereset(struct ata_link * link,unsigned long deadline)290f79ca455SSergey Shtylyov static int hpt366_prereset(struct ata_link *link, unsigned long deadline)
291f79ca455SSergey Shtylyov {
292f79ca455SSergey Shtylyov 	struct ata_port *ap = link->ap;
293f79ca455SSergey Shtylyov 	struct pci_dev *pdev = to_pci_dev(ap->host->dev);
294f79ca455SSergey Shtylyov 	/*
295f79ca455SSergey Shtylyov 	 * HPT36x chips have one channel per function and have
296f79ca455SSergey Shtylyov 	 * both channel enable bits located differently and visible
297f79ca455SSergey Shtylyov 	 * to both functions -- really stupid design decision... :-(
298f79ca455SSergey Shtylyov 	 * Bit 4 is for the primary channel, bit 5 for the secondary.
299f79ca455SSergey Shtylyov 	 */
300f79ca455SSergey Shtylyov 	static const struct pci_bits hpt366_enable_bits = {
301f79ca455SSergey Shtylyov 		0x50, 1, 0x30, 0x30
302f79ca455SSergey Shtylyov 	};
303a58ff050SSergey Shtylyov 	u8 mcr2;
304f79ca455SSergey Shtylyov 
305f79ca455SSergey Shtylyov 	if (!pci_test_config_bits(pdev, &hpt366_enable_bits))
306f79ca455SSergey Shtylyov 		return -ENOENT;
307f79ca455SSergey Shtylyov 
308a58ff050SSergey Shtylyov 	pci_read_config_byte(pdev, 0x51, &mcr2);
309a58ff050SSergey Shtylyov 	if (mcr2 & 0x80)
310a58ff050SSergey Shtylyov 		pci_write_config_byte(pdev, 0x51, mcr2 & ~0x80);
311a58ff050SSergey Shtylyov 
312f79ca455SSergey Shtylyov 	return ata_sff_prereset(link, deadline);
313f79ca455SSergey Shtylyov }
314f79ca455SSergey Shtylyov 
315*25df73d9SBart Van Assche static const struct scsi_host_template hpt36x_sht = {
31668d1d07bSTejun Heo 	ATA_BMDMA_SHT(DRV_NAME),
317669a5db4SJeff Garzik };
318669a5db4SJeff Garzik 
319669a5db4SJeff Garzik /*
320669a5db4SJeff Garzik  *	Configuration for HPT366/68
321669a5db4SJeff Garzik  */
322669a5db4SJeff Garzik 
323669a5db4SJeff Garzik static struct ata_port_operations hpt366_port_ops = {
324029cfd6bSTejun Heo 	.inherits	= &ata_bmdma_port_ops,
325f79ca455SSergey Shtylyov 	.prereset	= hpt366_prereset,
326029cfd6bSTejun Heo 	.cable_detect	= hpt36x_cable_detect,
327029cfd6bSTejun Heo 	.mode_filter	= hpt366_filter,
328669a5db4SJeff Garzik 	.set_piomode	= hpt366_set_piomode,
329669a5db4SJeff Garzik 	.set_dmamode	= hpt366_set_dmamode,
330669a5db4SJeff Garzik };
331669a5db4SJeff Garzik 
332669a5db4SJeff Garzik /**
333aa54ab1eSAlan  *	hpt36x_init_chipset	-	common chip setup
334aa54ab1eSAlan  *	@dev: PCI device
335aa54ab1eSAlan  *
336aa54ab1eSAlan  *	Perform the chip setup work that must be done at both init and
337aa54ab1eSAlan  *	resume time
338aa54ab1eSAlan  */
339aa54ab1eSAlan 
hpt36x_init_chipset(struct pci_dev * dev)340aa54ab1eSAlan static void hpt36x_init_chipset(struct pci_dev *dev)
341aa54ab1eSAlan {
342a58ff050SSergey Shtylyov 	u8 mcr1;
34328cd4b6bSSergei Shtylyov 
344aa54ab1eSAlan 	pci_write_config_byte(dev, PCI_CACHE_LINE_SIZE, (L1_CACHE_BYTES / 4));
345aa54ab1eSAlan 	pci_write_config_byte(dev, PCI_LATENCY_TIMER, 0x78);
346aa54ab1eSAlan 	pci_write_config_byte(dev, PCI_MIN_GNT, 0x08);
347aa54ab1eSAlan 	pci_write_config_byte(dev, PCI_MAX_LAT, 0x08);
348aa54ab1eSAlan 
349f79ca455SSergey Shtylyov 	/*
350f79ca455SSergey Shtylyov 	 * Now we'll have to force both channels enabled if at least one
351f79ca455SSergey Shtylyov 	 * of them has been enabled by BIOS...
352f79ca455SSergey Shtylyov 	 */
353f79ca455SSergey Shtylyov 	pci_read_config_byte(dev, 0x50, &mcr1);
354f79ca455SSergey Shtylyov 	if (mcr1 & 0x30)
355f79ca455SSergey Shtylyov 		pci_write_config_byte(dev, 0x50, mcr1 | 0x30);
356aa54ab1eSAlan }
357aa54ab1eSAlan 
358aa54ab1eSAlan /**
359669a5db4SJeff Garzik  *	hpt36x_init_one		-	Initialise an HPT366/368
360669a5db4SJeff Garzik  *	@dev: PCI device
361669a5db4SJeff Garzik  *	@id: Entry in match table
362669a5db4SJeff Garzik  *
363669a5db4SJeff Garzik  *	Initialise an HPT36x device. There are some interesting complications
364669a5db4SJeff Garzik  *	here. Firstly the chip may report 366 and be one of several variants.
365669a5db4SJeff Garzik  *	Secondly all the timings depend on the clock for the chip which we must
366669a5db4SJeff Garzik  *	detect and look up
367669a5db4SJeff Garzik  *
368669a5db4SJeff Garzik  *	This is the known chip mappings. It may be missing a couple of later
369669a5db4SJeff Garzik  *	releases.
370669a5db4SJeff Garzik  *
371669a5db4SJeff Garzik  *	Chip version		PCI		Rev	Notes
372669a5db4SJeff Garzik  *	HPT366			4 (HPT366)	0	UDMA66
373669a5db4SJeff Garzik  *	HPT366			4 (HPT366)	1	UDMA66
374669a5db4SJeff Garzik  *	HPT368			4 (HPT366)	2	UDMA66
375669a5db4SJeff Garzik  *	HPT37x/30x		4 (HPT366)	3+	Other driver
376669a5db4SJeff Garzik  *
377669a5db4SJeff Garzik  */
378669a5db4SJeff Garzik 
hpt36x_init_one(struct pci_dev * dev,const struct pci_device_id * id)379669a5db4SJeff Garzik static int hpt36x_init_one(struct pci_dev *dev, const struct pci_device_id *id)
380669a5db4SJeff Garzik {
3811626aeb8STejun Heo 	static const struct ata_port_info info_hpt366 = {
3821d2808fdSJeff Garzik 		.flags = ATA_FLAG_SLAVE_POSS,
38314bdef98SErik Inge Bolsø 		.pio_mask = ATA_PIO4,
38414bdef98SErik Inge Bolsø 		.mwdma_mask = ATA_MWDMA2,
385bf6263a8SJeff Garzik 		.udma_mask = ATA_UDMA4,
386669a5db4SJeff Garzik 		.port_ops = &hpt366_port_ops
387669a5db4SJeff Garzik 	};
388887125e3STejun Heo 	const struct ata_port_info *ppi[] = { &info_hpt366, NULL };
389669a5db4SJeff Garzik 
3906ec0a86cSArnd Bergmann 	const void *hpriv = NULL;
391669a5db4SJeff Garzik 	u32 reg1;
392f08048e9STejun Heo 	int rc;
393f08048e9STejun Heo 
394f08048e9STejun Heo 	rc = pcim_enable_device(dev);
395f08048e9STejun Heo 	if (rc)
396f08048e9STejun Heo 		return rc;
397669a5db4SJeff Garzik 
398669a5db4SJeff Garzik 	/* May be a later chip in disguise. Check */
399669a5db4SJeff Garzik 	/* Newer chips are not in the HPT36x driver. Ignore them */
40089d3b360SSergei Shtylyov 	if (dev->revision > 2)
401669a5db4SJeff Garzik 		return -ENODEV;
402669a5db4SJeff Garzik 
403aa54ab1eSAlan 	hpt36x_init_chipset(dev);
404669a5db4SJeff Garzik 
405669a5db4SJeff Garzik 	pci_read_config_dword(dev, 0x40,  &reg1);
406669a5db4SJeff Garzik 
407669a5db4SJeff Garzik 	/* PCI clocking determines the ATA timing values to use */
408669a5db4SJeff Garzik 	/* info_hpt366 is safe against re-entry so we can scribble on it */
409a548cc00SColin Ian King 	switch ((reg1 & 0xf00) >> 8) {
4102456eb81STejun Heo 	case 9:
411887125e3STejun Heo 		hpriv = &hpt366_40;
412669a5db4SJeff Garzik 		break;
4132456eb81STejun Heo 	case 5:
414887125e3STejun Heo 		hpriv = &hpt366_25;
415669a5db4SJeff Garzik 		break;
416669a5db4SJeff Garzik 	default:
417887125e3STejun Heo 		hpriv = &hpt366_33;
418669a5db4SJeff Garzik 		break;
419669a5db4SJeff Garzik 	}
420669a5db4SJeff Garzik 	/* Now kick off ATA set up */
4216ec0a86cSArnd Bergmann 	return ata_pci_bmdma_init_one(dev, ppi, &hpt36x_sht, (void *)hpriv, 0);
422669a5db4SJeff Garzik }
423669a5db4SJeff Garzik 
42458eb8cd5SBartlomiej Zolnierkiewicz #ifdef CONFIG_PM_SLEEP
hpt36x_reinit_one(struct pci_dev * dev)425aa54ab1eSAlan static int hpt36x_reinit_one(struct pci_dev *dev)
426aa54ab1eSAlan {
4270a86e1c8SJingoo Han 	struct ata_host *host = pci_get_drvdata(dev);
428f08048e9STejun Heo 	int rc;
429f08048e9STejun Heo 
430f08048e9STejun Heo 	rc = ata_pci_device_do_resume(dev);
431f08048e9STejun Heo 	if (rc)
432f08048e9STejun Heo 		return rc;
433aa54ab1eSAlan 	hpt36x_init_chipset(dev);
434f08048e9STejun Heo 	ata_host_resume(host);
435f08048e9STejun Heo 	return 0;
436aa54ab1eSAlan }
437438ac6d5STejun Heo #endif
438aa54ab1eSAlan 
4392d2744fcSJeff Garzik static const struct pci_device_id hpt36x[] = {
4402d2744fcSJeff Garzik 	{ PCI_VDEVICE(TTI, PCI_DEVICE_ID_TTI_HPT366), },
4412d2744fcSJeff Garzik 	{ },
442669a5db4SJeff Garzik };
443669a5db4SJeff Garzik 
444669a5db4SJeff Garzik static struct pci_driver hpt36x_pci_driver = {
445669a5db4SJeff Garzik 	.name		= DRV_NAME,
446669a5db4SJeff Garzik 	.id_table	= hpt36x,
447669a5db4SJeff Garzik 	.probe		= hpt36x_init_one,
448aa54ab1eSAlan 	.remove		= ata_pci_remove_one,
44958eb8cd5SBartlomiej Zolnierkiewicz #ifdef CONFIG_PM_SLEEP
450aa54ab1eSAlan 	.suspend	= ata_pci_device_suspend,
451aa54ab1eSAlan 	.resume		= hpt36x_reinit_one,
452438ac6d5STejun Heo #endif
453669a5db4SJeff Garzik };
454669a5db4SJeff Garzik 
4552fc75da0SAxel Lin module_pci_driver(hpt36x_pci_driver);
456669a5db4SJeff Garzik 
457669a5db4SJeff Garzik MODULE_AUTHOR("Alan Cox");
458669a5db4SJeff Garzik MODULE_DESCRIPTION("low-level driver for the Highpoint HPT366/368");
459669a5db4SJeff Garzik MODULE_LICENSE("GPL");
460669a5db4SJeff Garzik MODULE_DEVICE_TABLE(pci, hpt36x);
461669a5db4SJeff Garzik MODULE_VERSION(DRV_VERSION);
462