xref: /openbmc/linux/drivers/ata/ata_piix.c (revision 1ac731c529cd4d6adbce134754b51ff7d822b145)
1c82ee6d3SThomas Gleixner // SPDX-License-Identifier: GPL-2.0-or-later
2c6fd2807SJeff Garzik /*
3c6fd2807SJeff Garzik  *    ata_piix.c - Intel PATA/SATA controllers
4c6fd2807SJeff Garzik  *
58c3d3d4bSTejun Heo  *    Maintained by:  Tejun Heo <tj@kernel.org>
6c6fd2807SJeff Garzik  *    		    Please ALWAYS copy linux-ide@vger.kernel.org
7c6fd2807SJeff Garzik  *		    on emails.
8c6fd2807SJeff Garzik  *
9c6fd2807SJeff Garzik  *	Copyright 2003-2005 Red Hat Inc
10c6fd2807SJeff Garzik  *	Copyright 2003-2005 Jeff Garzik
11c6fd2807SJeff Garzik  *
12c6fd2807SJeff Garzik  *	Copyright header from piix.c:
13c6fd2807SJeff Garzik  *
14c6fd2807SJeff Garzik  *  Copyright (C) 1998-1999 Andrzej Krzysztofowicz, Author and Maintainer
15c6fd2807SJeff Garzik  *  Copyright (C) 1998-2000 Andre Hedrick <andre@linux-ide.org>
16ab771630SAlan Cox  *  Copyright (C) 2003 Red Hat Inc
17c6fd2807SJeff Garzik  *
18c6fd2807SJeff Garzik  *  libata documentation is available via 'make {ps|pdf}docs',
1919285f3cSMauro Carvalho Chehab  *  as Documentation/driver-api/libata.rst
20c6fd2807SJeff Garzik  *
21c6fd2807SJeff Garzik  *  Hardware documentation available at http://developer.intel.com/
22c6fd2807SJeff Garzik  *
23c6fd2807SJeff Garzik  * Documentation
2425985edcSLucas De Marchi  *	Publicly available from Intel web site. Errata documentation
2525985edcSLucas De Marchi  * is also publicly available. As an aide to anyone hacking on this
262c5ff671SAlan  * driver the list of errata that are relevant is below, going back to
27c6fd2807SJeff Garzik  * PIIX4. Older device documentation is now a bit tricky to find.
28c6fd2807SJeff Garzik  *
2988393161SThomas Weber  * The chipsets all follow very much the same design. The original Triton
3025985edcSLucas De Marchi  * series chipsets do _not_ support independent device timings, but this
31c6fd2807SJeff Garzik  * is fixed in Triton II. With the odd mobile exception the chips then
32c6fd2807SJeff Garzik  * change little except in gaining more modes until SATA arrives. This
3325985edcSLucas De Marchi  * driver supports only the chips with independent timing (that is those
34c6fd2807SJeff Garzik  * with SITRE and the 0x44 timing register). See pata_oldpiix and pata_mpiix
35c6fd2807SJeff Garzik  * for the early chip drivers.
36c6fd2807SJeff Garzik  *
37c6fd2807SJeff Garzik  * Errata of note:
38c6fd2807SJeff Garzik  *
39c6fd2807SJeff Garzik  * Unfixable
40c6fd2807SJeff Garzik  *	PIIX4    errata #9	- Only on ultra obscure hw
41c6fd2807SJeff Garzik  *	ICH3	 errata #13     - Not observed to affect real hw
42c6fd2807SJeff Garzik  *				  by Intel
43c6fd2807SJeff Garzik  *
44c6fd2807SJeff Garzik  * Things we must deal with
45c6fd2807SJeff Garzik  *	PIIX4	errata #10	- BM IDE hang with non UDMA
46c6fd2807SJeff Garzik  *				  (must stop/start dma to recover)
47c6fd2807SJeff Garzik  *	440MX   errata #15	- As PIIX4 errata #10
48c6fd2807SJeff Garzik  *	PIIX4	errata #15	- Must not read control registers
49c6fd2807SJeff Garzik  * 				  during a PIO transfer
50c6fd2807SJeff Garzik  *	440MX   errata #13	- As PIIX4 errata #15
51c6fd2807SJeff Garzik  *	ICH2	errata #21	- DMA mode 0 doesn't work right
52c6fd2807SJeff Garzik  *	ICH0/1  errata #55	- As ICH2 errata #21
53c6fd2807SJeff Garzik  *	ICH2	spec c #9	- Extra operations needed to handle
54c6fd2807SJeff Garzik  *				  drive hotswap [NOT YET SUPPORTED]
55c6fd2807SJeff Garzik  *	ICH2    spec c #20	- IDE PRD must not cross a 64K boundary
56c6fd2807SJeff Garzik  *				  and must be dword aligned
57c6fd2807SJeff Garzik  *	ICH2    spec c #24	- UDMA mode 4,5 t85/86 should be 6ns not 3.3
58c611bed7SAlan Cox  *	ICH7	errata #16	- MWDMA1 timings are incorrect
59c6fd2807SJeff Garzik  *
60c6fd2807SJeff Garzik  * Should have been BIOS fixed:
61c6fd2807SJeff Garzik  *	450NX:	errata #19	- DMA hangs on old 450NX
62c6fd2807SJeff Garzik  *	450NX:  errata #20	- DMA hangs on old 450NX
63c6fd2807SJeff Garzik  *	450NX:  errata #25	- Corruption with DMA on old 450NX
64c6fd2807SJeff Garzik  *	ICH3    errata #15      - IDE deadlock under high load
65c6fd2807SJeff Garzik  *				  (BIOS must set dev 31 fn 0 bit 23)
66c6fd2807SJeff Garzik  *	ICH3	errata #18	- Don't use native mode
67c6fd2807SJeff Garzik  */
68c6fd2807SJeff Garzik 
69c6fd2807SJeff Garzik #include <linux/kernel.h>
70c6fd2807SJeff Garzik #include <linux/module.h>
71c6fd2807SJeff Garzik #include <linux/pci.h>
72c6fd2807SJeff Garzik #include <linux/init.h>
73c6fd2807SJeff Garzik #include <linux/blkdev.h>
74c6fd2807SJeff Garzik #include <linux/delay.h>
75c6fd2807SJeff Garzik #include <linux/device.h>
765a0e3ad6STejun Heo #include <linux/gfp.h>
77c6fd2807SJeff Garzik #include <scsi/scsi_host.h>
78c6fd2807SJeff Garzik #include <linux/libata.h>
79b8b275efSTejun Heo #include <linux/dmi.h>
80c206a389SHannes Reinecke #include <trace/events/libata.h>
81c6fd2807SJeff Garzik 
82c6fd2807SJeff Garzik #define DRV_NAME	"ata_piix"
83c611bed7SAlan Cox #define DRV_VERSION	"2.13"
84c6fd2807SJeff Garzik 
85c6fd2807SJeff Garzik enum {
86c6fd2807SJeff Garzik 	PIIX_IOCFG		= 0x54, /* IDE I/O configuration register */
8789951f22SLevente Kurusa 	ICH5_PMR		= 0x90, /* address map register */
88c6fd2807SJeff Garzik 	ICH5_PCS		= 0x92,	/* port control and status */
89c7290724STejun Heo 	PIIX_SIDPR_BAR		= 5,
90c7290724STejun Heo 	PIIX_SIDPR_LEN		= 16,
91c7290724STejun Heo 	PIIX_SIDPR_IDX		= 0,
92c7290724STejun Heo 	PIIX_SIDPR_DATA		= 4,
93c6fd2807SJeff Garzik 
94c6fd2807SJeff Garzik 	PIIX_FLAG_CHECKINTR	= (1 << 28), /* make sure PCI INTx enabled */
95c7290724STejun Heo 	PIIX_FLAG_SIDPR		= (1 << 29), /* SATA idx/data pair regs */
96c6fd2807SJeff Garzik 
97800b3996STejun Heo 	PIIX_PATA_FLAGS		= ATA_FLAG_SLAVE_POSS,
98800b3996STejun Heo 	PIIX_SATA_FLAGS		= ATA_FLAG_SATA | PIIX_FLAG_CHECKINTR,
99b3362f88STejun Heo 
1005e5a4f5dSMing Lei 	PIIX_FLAG_PIO16		= (1 << 30), /*support 16bit PIO only*/
1015e5a4f5dSMing Lei 
102c6fd2807SJeff Garzik 	PIIX_80C_PRI		= (1 << 5) | (1 << 4),
103c6fd2807SJeff Garzik 	PIIX_80C_SEC		= (1 << 7) | (1 << 6),
104c6fd2807SJeff Garzik 
105c6fd2807SJeff Garzik 	/* constants for mapping table */
106c6fd2807SJeff Garzik 	P0			= 0,  /* port 0 */
107c6fd2807SJeff Garzik 	P1			= 1,  /* port 1 */
108c6fd2807SJeff Garzik 	P2			= 2,  /* port 2 */
109c6fd2807SJeff Garzik 	P3			= 3,  /* port 3 */
110c6fd2807SJeff Garzik 	IDE			= -1, /* IDE */
11125985edcSLucas De Marchi 	NA			= -2, /* not available */
112c6fd2807SJeff Garzik 	RV			= -3, /* reserved */
113c6fd2807SJeff Garzik 
114c6fd2807SJeff Garzik 	PIIX_AHCI_DEVICE	= 6,
115b8b275efSTejun Heo 
116b8b275efSTejun Heo 	/* host->flags bits */
117b8b275efSTejun Heo 	PIIX_HOST_BROKEN_SUSPEND = (1 << 24),
118c6fd2807SJeff Garzik };
119c6fd2807SJeff Garzik 
1209cde9ed1STejun Heo enum piix_controller_ids {
1219cde9ed1STejun Heo 	/* controller IDs */
1229cde9ed1STejun Heo 	piix_pata_mwdma,	/* PIIX3 MWDMA only */
1239cde9ed1STejun Heo 	piix_pata_33,		/* PIIX4 at 33Mhz */
1249cde9ed1STejun Heo 	ich_pata_33,		/* ICH up to UDMA 33 only */
1259cde9ed1STejun Heo 	ich_pata_66,		/* ICH up to 66 Mhz */
1269cde9ed1STejun Heo 	ich_pata_100,		/* ICH up to UDMA 100 */
127c611bed7SAlan Cox 	ich_pata_100_nomwdma1,	/* ICH up to UDMA 100 but with no MWDMA1*/
1289cde9ed1STejun Heo 	ich5_sata,
1299cde9ed1STejun Heo 	ich6_sata,
1309c0bf675STejun Heo 	ich6m_sata,
1319c0bf675STejun Heo 	ich8_sata,
1329cde9ed1STejun Heo 	ich8_2port_sata,
1339c0bf675STejun Heo 	ich8m_apple_sata,	/* locks up on second port enable */
1349c0bf675STejun Heo 	tolapai_sata,
1359cde9ed1STejun Heo 	piix_pata_vmw,			/* PIIX4 for VMware, spurious DMA_ERR */
1365e5a4f5dSMing Lei 	ich8_sata_snb,
137b55f84e2SYouquan Song 	ich8_2port_sata_snb,
138fca8c90dSChew, Chiau Ee 	ich8_2port_sata_byt,
1399cde9ed1STejun Heo };
1409cde9ed1STejun Heo 
141c6fd2807SJeff Garzik struct piix_map_db {
142c6fd2807SJeff Garzik 	const u32 mask;
143c6fd2807SJeff Garzik 	const u16 port_enable;
144c6fd2807SJeff Garzik 	const int map[][4];
145c6fd2807SJeff Garzik };
146c6fd2807SJeff Garzik 
147c6fd2807SJeff Garzik struct piix_host_priv {
148c6fd2807SJeff Garzik 	const int *map;
1492852bcf7STejun Heo 	u32 saved_iocfg;
150c7290724STejun Heo 	void __iomem *sidpr;
151c6fd2807SJeff Garzik };
152c6fd2807SJeff Garzik 
153c6fd2807SJeff Garzik static unsigned int in_module_init = 1;
154c6fd2807SJeff Garzik 
155c6fd2807SJeff Garzik static const struct pci_device_id piix_pci_tbl[] = {
156d2cdfc0dSAlan 	/* Intel PIIX3 for the 430HX etc */
157d2cdfc0dSAlan 	{ 0x8086, 0x7010, PCI_ANY_ID, PCI_ANY_ID, 0, 0, piix_pata_mwdma },
15825f98131STejun Heo 	/* VMware ICH4 */
15925f98131STejun Heo 	{ 0x8086, 0x7111, 0x15ad, 0x1976, 0, 0, piix_pata_vmw },
160669a5db4SJeff Garzik 	/* Intel PIIX4 for the 430TX/440BX/MX chipset: UDMA 33 */
161669a5db4SJeff Garzik 	/* Also PIIX4E (fn3 rev 2) and PIIX4M (fn3 rev 3) */
162669a5db4SJeff Garzik 	{ 0x8086, 0x7111, PCI_ANY_ID, PCI_ANY_ID, 0, 0, piix_pata_33 },
163669a5db4SJeff Garzik 	/* Intel PIIX4 */
164669a5db4SJeff Garzik 	{ 0x8086, 0x7199, PCI_ANY_ID, PCI_ANY_ID, 0, 0, piix_pata_33 },
165669a5db4SJeff Garzik 	/* Intel PIIX4 */
166669a5db4SJeff Garzik 	{ 0x8086, 0x7601, PCI_ANY_ID, PCI_ANY_ID, 0, 0, piix_pata_33 },
167669a5db4SJeff Garzik 	/* Intel PIIX */
168669a5db4SJeff Garzik 	{ 0x8086, 0x84CA, PCI_ANY_ID, PCI_ANY_ID, 0, 0, piix_pata_33 },
169669a5db4SJeff Garzik 	/* Intel ICH (i810, i815, i840) UDMA 66*/
170669a5db4SJeff Garzik 	{ 0x8086, 0x2411, PCI_ANY_ID, PCI_ANY_ID, 0, 0, ich_pata_66 },
171669a5db4SJeff Garzik 	/* Intel ICH0 : UDMA 33*/
172669a5db4SJeff Garzik 	{ 0x8086, 0x2421, PCI_ANY_ID, PCI_ANY_ID, 0, 0, ich_pata_33 },
173669a5db4SJeff Garzik 	/* Intel ICH2M */
174669a5db4SJeff Garzik 	{ 0x8086, 0x244A, PCI_ANY_ID, PCI_ANY_ID, 0, 0, ich_pata_100 },
175669a5db4SJeff Garzik 	/* Intel ICH2 (i810E2, i845, 850, 860) UDMA 100 */
176669a5db4SJeff Garzik 	{ 0x8086, 0x244B, PCI_ANY_ID, PCI_ANY_ID, 0, 0, ich_pata_100 },
177669a5db4SJeff Garzik 	/*  Intel ICH3M */
178669a5db4SJeff Garzik 	{ 0x8086, 0x248A, PCI_ANY_ID, PCI_ANY_ID, 0, 0, ich_pata_100 },
179669a5db4SJeff Garzik 	/* Intel ICH3 (E7500/1) UDMA 100 */
180669a5db4SJeff Garzik 	{ 0x8086, 0x248B, PCI_ANY_ID, PCI_ANY_ID, 0, 0, ich_pata_100 },
1814bb969dbSBen Hutchings 	/* Intel ICH4-L */
1824bb969dbSBen Hutchings 	{ 0x8086, 0x24C1, PCI_ANY_ID, PCI_ANY_ID, 0, 0, ich_pata_100 },
183669a5db4SJeff Garzik 	/* Intel ICH4 (i845GV, i845E, i852, i855) UDMA 100 */
184669a5db4SJeff Garzik 	{ 0x8086, 0x24CA, PCI_ANY_ID, PCI_ANY_ID, 0, 0, ich_pata_100 },
185669a5db4SJeff Garzik 	{ 0x8086, 0x24CB, PCI_ANY_ID, PCI_ANY_ID, 0, 0, ich_pata_100 },
186669a5db4SJeff Garzik 	/* Intel ICH5 */
1872eb829e9SChristian Lamparter 	{ 0x8086, 0x24DB, PCI_ANY_ID, PCI_ANY_ID, 0, 0, ich_pata_100 },
188669a5db4SJeff Garzik 	/* C-ICH (i810E2) */
189669a5db4SJeff Garzik 	{ 0x8086, 0x245B, PCI_ANY_ID, PCI_ANY_ID, 0, 0, ich_pata_100 },
190669a5db4SJeff Garzik 	/* ESB (855GME/875P + 6300ESB) UDMA 100  */
191669a5db4SJeff Garzik 	{ 0x8086, 0x25A2, PCI_ANY_ID, PCI_ANY_ID, 0, 0, ich_pata_100 },
192669a5db4SJeff Garzik 	/* ICH6 (and 6) (i915) UDMA 100 */
193669a5db4SJeff Garzik 	{ 0x8086, 0x266F, PCI_ANY_ID, PCI_ANY_ID, 0, 0, ich_pata_100 },
194669a5db4SJeff Garzik 	/* ICH7/7-R (i945, i975) UDMA 100*/
195c611bed7SAlan Cox 	{ 0x8086, 0x27DF, PCI_ANY_ID, PCI_ANY_ID, 0, 0, ich_pata_100_nomwdma1 },
196c611bed7SAlan Cox 	{ 0x8086, 0x269E, PCI_ANY_ID, PCI_ANY_ID, 0, 0, ich_pata_100_nomwdma1 },
197c1e6f28cSChristian Lamparter 	/* ICH8 Mobile PATA Controller */
198c1e6f28cSChristian Lamparter 	{ 0x8086, 0x2850, PCI_ANY_ID, PCI_ANY_ID, 0, 0, ich_pata_100 },
199c6fd2807SJeff Garzik 
2007654db1aSAlan Cox 	/* SATA ports */
201c6fd2807SJeff Garzik 
202c6fd2807SJeff Garzik 	/* 82801EB (ICH5) */
203c6fd2807SJeff Garzik 	{ 0x8086, 0x24d1, PCI_ANY_ID, PCI_ANY_ID, 0, 0, ich5_sata },
204c6fd2807SJeff Garzik 	/* 82801EB (ICH5) */
205c6fd2807SJeff Garzik 	{ 0x8086, 0x24df, PCI_ANY_ID, PCI_ANY_ID, 0, 0, ich5_sata },
206c6fd2807SJeff Garzik 	/* 6300ESB (ICH5 variant with broken PCS present bits) */
2075e56a37cSTejun Heo 	{ 0x8086, 0x25a3, PCI_ANY_ID, PCI_ANY_ID, 0, 0, ich5_sata },
208c6fd2807SJeff Garzik 	/* 6300ESB pretending RAID */
2095e56a37cSTejun Heo 	{ 0x8086, 0x25b0, PCI_ANY_ID, PCI_ANY_ID, 0, 0, ich5_sata },
210c6fd2807SJeff Garzik 	/* 82801FB/FW (ICH6/ICH6W) */
211c6fd2807SJeff Garzik 	{ 0x8086, 0x2651, PCI_ANY_ID, PCI_ANY_ID, 0, 0, ich6_sata },
212c6fd2807SJeff Garzik 	/* 82801FR/FRW (ICH6R/ICH6RW) */
2139c0bf675STejun Heo 	{ 0x8086, 0x2652, PCI_ANY_ID, PCI_ANY_ID, 0, 0, ich6_sata },
2145016d7d2STejun Heo 	/* 82801FBM ICH6M (ICH6R with only port 0 and 2 implemented).
2155016d7d2STejun Heo 	 * Attach iff the controller is in IDE mode. */
2165016d7d2STejun Heo 	{ 0x8086, 0x2653, PCI_ANY_ID, PCI_ANY_ID,
2179c0bf675STejun Heo 	  PCI_CLASS_STORAGE_IDE << 8, 0xffff00, ich6m_sata },
218c6fd2807SJeff Garzik 	/* 82801GB/GR/GH (ICH7, identical to ICH6) */
2199c0bf675STejun Heo 	{ 0x8086, 0x27c0, PCI_ANY_ID, PCI_ANY_ID, 0, 0, ich6_sata },
22089951f22SLevente Kurusa 	/* 82801GBM/GHM (ICH7M, identical to ICH6M)  */
2219c0bf675STejun Heo 	{ 0x8086, 0x27c4, PCI_ANY_ID, PCI_ANY_ID, 0, 0, ich6m_sata },
222f98b6573SJason Gaston 	/* Enterprise Southbridge 2 (631xESB/632xESB) */
2239c0bf675STejun Heo 	{ 0x8086, 0x2680, PCI_ANY_ID, PCI_ANY_ID, 0, 0, ich6_sata },
224f98b6573SJason Gaston 	/* SATA Controller 1 IDE (ICH8) */
2259c0bf675STejun Heo 	{ 0x8086, 0x2820, PCI_ANY_ID, PCI_ANY_ID, 0, 0, ich8_sata },
226f98b6573SJason Gaston 	/* SATA Controller 2 IDE (ICH8) */
22700242ec8STejun Heo 	{ 0x8086, 0x2825, PCI_ANY_ID, PCI_ANY_ID, 0, 0, ich8_2port_sata },
2288d8ef2fbSThomas Rohwer 	/* Mobile SATA Controller IDE (ICH8M), Apple */
2299c0bf675STejun Heo 	{ 0x8086, 0x2828, 0x106b, 0x00a0, 0, 0, ich8m_apple_sata },
23023cf296eSTejun Heo 	{ 0x8086, 0x2828, 0x106b, 0x00a1, 0, 0, ich8m_apple_sata },
231487eff68STejun Heo 	{ 0x8086, 0x2828, 0x106b, 0x00a3, 0, 0, ich8m_apple_sata },
23223cf296eSTejun Heo 	/* Mobile SATA Controller IDE (ICH8M) */
23323cf296eSTejun Heo 	{ 0x8086, 0x2828, PCI_ANY_ID, PCI_ANY_ID, 0, 0, ich8_sata },
234f98b6573SJason Gaston 	/* SATA Controller IDE (ICH9) */
2359c0bf675STejun Heo 	{ 0x8086, 0x2920, PCI_ANY_ID, PCI_ANY_ID, 0, 0, ich8_sata },
236f98b6573SJason Gaston 	/* SATA Controller IDE (ICH9) */
23700242ec8STejun Heo 	{ 0x8086, 0x2921, PCI_ANY_ID, PCI_ANY_ID, 0, 0, ich8_2port_sata },
238f98b6573SJason Gaston 	/* SATA Controller IDE (ICH9) */
23900242ec8STejun Heo 	{ 0x8086, 0x2926, PCI_ANY_ID, PCI_ANY_ID, 0, 0, ich8_2port_sata },
240f98b6573SJason Gaston 	/* SATA Controller IDE (ICH9M) */
24100242ec8STejun Heo 	{ 0x8086, 0x2928, PCI_ANY_ID, PCI_ANY_ID, 0, 0, ich8_2port_sata },
242f98b6573SJason Gaston 	/* SATA Controller IDE (ICH9M) */
24300242ec8STejun Heo 	{ 0x8086, 0x292d, PCI_ANY_ID, PCI_ANY_ID, 0, 0, ich8_2port_sata },
244f98b6573SJason Gaston 	/* SATA Controller IDE (ICH9M) */
2459c0bf675STejun Heo 	{ 0x8086, 0x292e, PCI_ANY_ID, PCI_ANY_ID, 0, 0, ich8_sata },
246c5cf0ffaSJason Gaston 	/* SATA Controller IDE (Tolapai) */
2479c0bf675STejun Heo 	{ 0x8086, 0x5028, PCI_ANY_ID, PCI_ANY_ID, 0, 0, tolapai_sata },
248bf7f22b9SJason Gaston 	/* SATA Controller IDE (ICH10) */
2499c0bf675STejun Heo 	{ 0x8086, 0x3a00, PCI_ANY_ID, PCI_ANY_ID, 0, 0, ich8_sata },
250bf7f22b9SJason Gaston 	/* SATA Controller IDE (ICH10) */
251bf7f22b9SJason Gaston 	{ 0x8086, 0x3a06, PCI_ANY_ID, PCI_ANY_ID, 0, 0, ich8_2port_sata },
252bf7f22b9SJason Gaston 	/* SATA Controller IDE (ICH10) */
2539c0bf675STejun Heo 	{ 0x8086, 0x3a20, PCI_ANY_ID, PCI_ANY_ID, 0, 0, ich8_sata },
254bf7f22b9SJason Gaston 	/* SATA Controller IDE (ICH10) */
255bf7f22b9SJason Gaston 	{ 0x8086, 0x3a26, PCI_ANY_ID, PCI_ANY_ID, 0, 0, ich8_2port_sata },
256c6c6a1afSSeth Heasley 	/* SATA Controller IDE (PCH) */
257c6c6a1afSSeth Heasley 	{ 0x8086, 0x3b20, PCI_ANY_ID, PCI_ANY_ID, 0, 0, ich8_sata },
258c6c6a1afSSeth Heasley 	/* SATA Controller IDE (PCH) */
2590395e61bSSeth Heasley 	{ 0x8086, 0x3b21, PCI_ANY_ID, PCI_ANY_ID, 0, 0, ich8_2port_sata },
2600395e61bSSeth Heasley 	/* SATA Controller IDE (PCH) */
261c6c6a1afSSeth Heasley 	{ 0x8086, 0x3b26, PCI_ANY_ID, PCI_ANY_ID, 0, 0, ich8_2port_sata },
262c6c6a1afSSeth Heasley 	/* SATA Controller IDE (PCH) */
2630395e61bSSeth Heasley 	{ 0x8086, 0x3b28, PCI_ANY_ID, PCI_ANY_ID, 0, 0, ich8_sata },
2640395e61bSSeth Heasley 	/* SATA Controller IDE (PCH) */
265c6c6a1afSSeth Heasley 	{ 0x8086, 0x3b2d, PCI_ANY_ID, PCI_ANY_ID, 0, 0, ich8_2port_sata },
266c6c6a1afSSeth Heasley 	/* SATA Controller IDE (PCH) */
267c6c6a1afSSeth Heasley 	{ 0x8086, 0x3b2e, PCI_ANY_ID, PCI_ANY_ID, 0, 0, ich8_sata },
26888e8201eSSeth Heasley 	/* SATA Controller IDE (CPT) */
2695e5a4f5dSMing Lei 	{ 0x8086, 0x1c00, PCI_ANY_ID, PCI_ANY_ID, 0, 0, ich8_sata_snb },
27088e8201eSSeth Heasley 	/* SATA Controller IDE (CPT) */
2715e5a4f5dSMing Lei 	{ 0x8086, 0x1c01, PCI_ANY_ID, PCI_ANY_ID, 0, 0, ich8_sata_snb },
27288e8201eSSeth Heasley 	/* SATA Controller IDE (CPT) */
27388e8201eSSeth Heasley 	{ 0x8086, 0x1c08, PCI_ANY_ID, PCI_ANY_ID, 0, 0, ich8_2port_sata },
27488e8201eSSeth Heasley 	/* SATA Controller IDE (CPT) */
27588e8201eSSeth Heasley 	{ 0x8086, 0x1c09, PCI_ANY_ID, PCI_ANY_ID, 0, 0, ich8_2port_sata },
276238e149cSSeth Heasley 	/* SATA Controller IDE (PBG) */
2775e5a4f5dSMing Lei 	{ 0x8086, 0x1d00, PCI_ANY_ID, PCI_ANY_ID, 0, 0, ich8_sata_snb },
278238e149cSSeth Heasley 	/* SATA Controller IDE (PBG) */
279238e149cSSeth Heasley 	{ 0x8086, 0x1d08, PCI_ANY_ID, PCI_ANY_ID, 0, 0, ich8_2port_sata },
2804a836c70SSeth Heasley 	/* SATA Controller IDE (Panther Point) */
2815e5a4f5dSMing Lei 	{ 0x8086, 0x1e00, PCI_ANY_ID, PCI_ANY_ID, 0, 0, ich8_sata_snb },
2824a836c70SSeth Heasley 	/* SATA Controller IDE (Panther Point) */
2835e5a4f5dSMing Lei 	{ 0x8086, 0x1e01, PCI_ANY_ID, PCI_ANY_ID, 0, 0, ich8_sata_snb },
2844a836c70SSeth Heasley 	/* SATA Controller IDE (Panther Point) */
2854a836c70SSeth Heasley 	{ 0x8086, 0x1e08, PCI_ANY_ID, PCI_ANY_ID, 0, 0, ich8_2port_sata },
2864a836c70SSeth Heasley 	/* SATA Controller IDE (Panther Point) */
2874a836c70SSeth Heasley 	{ 0x8086, 0x1e09, PCI_ANY_ID, PCI_ANY_ID, 0, 0, ich8_2port_sata },
28878140cfeSSeth Heasley 	/* SATA Controller IDE (Lynx Point) */
28978140cfeSSeth Heasley 	{ 0x8086, 0x8c00, PCI_ANY_ID, PCI_ANY_ID, 0, 0, ich8_sata_snb },
29078140cfeSSeth Heasley 	/* SATA Controller IDE (Lynx Point) */
29178140cfeSSeth Heasley 	{ 0x8086, 0x8c01, PCI_ANY_ID, PCI_ANY_ID, 0, 0, ich8_sata_snb },
29278140cfeSSeth Heasley 	/* SATA Controller IDE (Lynx Point) */
293b55f84e2SYouquan Song 	{ 0x8086, 0x8c08, PCI_ANY_ID, PCI_ANY_ID, 0, 0, ich8_2port_sata_snb },
29478140cfeSSeth Heasley 	/* SATA Controller IDE (Lynx Point) */
29578140cfeSSeth Heasley 	{ 0x8086, 0x8c09, PCI_ANY_ID, PCI_ANY_ID, 0, 0, ich8_2port_sata },
296389cd784SJames Ralston 	/* SATA Controller IDE (Lynx Point-LP) */
297389cd784SJames Ralston 	{ 0x8086, 0x9c00, PCI_ANY_ID, PCI_ANY_ID, 0, 0, ich8_sata_snb },
298389cd784SJames Ralston 	/* SATA Controller IDE (Lynx Point-LP) */
299389cd784SJames Ralston 	{ 0x8086, 0x9c01, PCI_ANY_ID, PCI_ANY_ID, 0, 0, ich8_sata_snb },
300389cd784SJames Ralston 	/* SATA Controller IDE (Lynx Point-LP) */
301389cd784SJames Ralston 	{ 0x8086, 0x9c08, PCI_ANY_ID, PCI_ANY_ID, 0, 0, ich8_2port_sata },
302389cd784SJames Ralston 	/* SATA Controller IDE (Lynx Point-LP) */
303389cd784SJames Ralston 	{ 0x8086, 0x9c09, PCI_ANY_ID, PCI_ANY_ID, 0, 0, ich8_2port_sata },
30496d5d96aSSeth Heasley 	/* SATA Controller IDE (DH89xxCC) */
30596d5d96aSSeth Heasley 	{ 0x8086, 0x2326, PCI_ANY_ID, PCI_ANY_ID, 0, 0, ich8_2port_sata },
306aaa51527SSeth Heasley 	/* SATA Controller IDE (Avoton) */
307aaa51527SSeth Heasley 	{ 0x8086, 0x1f20, PCI_ANY_ID, PCI_ANY_ID, 0, 0, ich8_sata_snb },
308aaa51527SSeth Heasley 	/* SATA Controller IDE (Avoton) */
309aaa51527SSeth Heasley 	{ 0x8086, 0x1f21, PCI_ANY_ID, PCI_ANY_ID, 0, 0, ich8_sata_snb },
310aaa51527SSeth Heasley 	/* SATA Controller IDE (Avoton) */
311aaa51527SSeth Heasley 	{ 0x8086, 0x1f30, PCI_ANY_ID, PCI_ANY_ID, 0, 0, ich8_2port_sata },
312aaa51527SSeth Heasley 	/* SATA Controller IDE (Avoton) */
313aaa51527SSeth Heasley 	{ 0x8086, 0x1f31, PCI_ANY_ID, PCI_ANY_ID, 0, 0, ich8_2port_sata },
3143aee8bc5SJames Ralston 	/* SATA Controller IDE (Wellsburg) */
3153aee8bc5SJames Ralston 	{ 0x8086, 0x8d00, PCI_ANY_ID, PCI_ANY_ID, 0, 0, ich8_sata_snb },
3163aee8bc5SJames Ralston 	/* SATA Controller IDE (Wellsburg) */
317eac27f04SYouquan Song 	{ 0x8086, 0x8d08, PCI_ANY_ID, PCI_ANY_ID, 0, 0, ich8_2port_sata_snb },
3183aee8bc5SJames Ralston 	/* SATA Controller IDE (Wellsburg) */
3193aee8bc5SJames Ralston 	{ 0x8086, 0x8d60, PCI_ANY_ID, PCI_ANY_ID, 0, 0, ich8_sata_snb },
3203aee8bc5SJames Ralston 	/* SATA Controller IDE (Wellsburg) */
3213aee8bc5SJames Ralston 	{ 0x8086, 0x8d68, PCI_ANY_ID, PCI_ANY_ID, 0, 0, ich8_2port_sata },
322fca8c90dSChew, Chiau Ee 	/* SATA Controller IDE (BayTrail) */
323fca8c90dSChew, Chiau Ee 	{ 0x8086, 0x0F20, PCI_ANY_ID, PCI_ANY_ID, 0, 0, ich8_2port_sata_byt },
324fca8c90dSChew, Chiau Ee 	{ 0x8086, 0x0F21, PCI_ANY_ID, PCI_ANY_ID, 0, 0, ich8_2port_sata_byt },
325c7e8695bSSeth Heasley 	/* SATA Controller IDE (Coleto Creek) */
326c7e8695bSSeth Heasley 	{ 0x8086, 0x23a6, PCI_ANY_ID, PCI_ANY_ID, 0, 0, ich8_2port_sata },
3276cad1376SJames Ralston 	/* SATA Controller IDE (9 Series) */
3286cad1376SJames Ralston 	{ 0x8086, 0x8c88, PCI_ANY_ID, PCI_ANY_ID, 0, 0, ich8_2port_sata_snb },
3296cad1376SJames Ralston 	/* SATA Controller IDE (9 Series) */
3306cad1376SJames Ralston 	{ 0x8086, 0x8c89, PCI_ANY_ID, PCI_ANY_ID, 0, 0, ich8_2port_sata_snb },
3316cad1376SJames Ralston 	/* SATA Controller IDE (9 Series) */
3326cad1376SJames Ralston 	{ 0x8086, 0x8c80, PCI_ANY_ID, PCI_ANY_ID, 0, 0, ich8_sata_snb },
3336cad1376SJames Ralston 	/* SATA Controller IDE (9 Series) */
3346cad1376SJames Ralston 	{ 0x8086, 0x8c81, PCI_ANY_ID, PCI_ANY_ID, 0, 0, ich8_sata_snb },
3353aee8bc5SJames Ralston 
336c6fd2807SJeff Garzik 	{ }	/* terminate list */
337c6fd2807SJeff Garzik };
338c6fd2807SJeff Garzik 
339c6fd2807SJeff Garzik static const struct piix_map_db ich5_map_db = {
340c6fd2807SJeff Garzik 	.mask = 0x7,
341c6fd2807SJeff Garzik 	.port_enable = 0x3,
342c6fd2807SJeff Garzik 	.map = {
343c6fd2807SJeff Garzik 		/* PM   PS   SM   SS       MAP  */
344c6fd2807SJeff Garzik 		{  P0,  NA,  P1,  NA }, /* 000b */
345c6fd2807SJeff Garzik 		{  P1,  NA,  P0,  NA }, /* 001b */
346c6fd2807SJeff Garzik 		{  RV,  RV,  RV,  RV },
347c6fd2807SJeff Garzik 		{  RV,  RV,  RV,  RV },
348c6fd2807SJeff Garzik 		{  P0,  P1, IDE, IDE }, /* 100b */
349c6fd2807SJeff Garzik 		{  P1,  P0, IDE, IDE }, /* 101b */
350c6fd2807SJeff Garzik 		{ IDE, IDE,  P0,  P1 }, /* 110b */
351c6fd2807SJeff Garzik 		{ IDE, IDE,  P1,  P0 }, /* 111b */
352c6fd2807SJeff Garzik 	},
353c6fd2807SJeff Garzik };
354c6fd2807SJeff Garzik 
355c6fd2807SJeff Garzik static const struct piix_map_db ich6_map_db = {
356c6fd2807SJeff Garzik 	.mask = 0x3,
357c6fd2807SJeff Garzik 	.port_enable = 0xf,
358c6fd2807SJeff Garzik 	.map = {
359c6fd2807SJeff Garzik 		/* PM   PS   SM   SS       MAP */
360c6fd2807SJeff Garzik 		{  P0,  P2,  P1,  P3 }, /* 00b */
361c6fd2807SJeff Garzik 		{ IDE, IDE,  P1,  P3 }, /* 01b */
362c6fd2807SJeff Garzik 		{  P0,  P2, IDE, IDE }, /* 10b */
363c6fd2807SJeff Garzik 		{  RV,  RV,  RV,  RV },
364c6fd2807SJeff Garzik 	},
365c6fd2807SJeff Garzik };
366c6fd2807SJeff Garzik 
367c6fd2807SJeff Garzik static const struct piix_map_db ich6m_map_db = {
368c6fd2807SJeff Garzik 	.mask = 0x3,
369c6fd2807SJeff Garzik 	.port_enable = 0x5,
370dd1dc802SJeff Garzik 
371dd1dc802SJeff Garzik 	/* Map 01b isn't specified in the doc but some notebooks use
372c6446a4cSTejun Heo 	 * it anyway.  MAP 01b have been spotted on both ICH6M and
373c6446a4cSTejun Heo 	 * ICH7M.
374dd1dc802SJeff Garzik 	 */
375dd1dc802SJeff Garzik 	.map = {
376dd1dc802SJeff Garzik 		/* PM   PS   SM   SS       MAP */
377e04b3b9dSTejun Heo 		{  P0,  P2,  NA,  NA }, /* 00b */
378dd1dc802SJeff Garzik 		{ IDE, IDE,  P1,  P3 }, /* 01b */
379dd1dc802SJeff Garzik 		{  P0,  P2, IDE, IDE }, /* 10b */
380dd1dc802SJeff Garzik 		{  RV,  RV,  RV,  RV },
381dd1dc802SJeff Garzik 	},
382dd1dc802SJeff Garzik };
383dd1dc802SJeff Garzik 
384c6fd2807SJeff Garzik static const struct piix_map_db ich8_map_db = {
385c6fd2807SJeff Garzik 	.mask = 0x3,
386a0ce9acaSTejun Heo 	.port_enable = 0xf,
387c6fd2807SJeff Garzik 	.map = {
388c6fd2807SJeff Garzik 		/* PM   PS   SM   SS       MAP */
389158f30c8SKristen Carlson Accardi 		{  P0,  P2,  P1,  P3 }, /* 00b (hardwired when in AHCI) */
390c6fd2807SJeff Garzik 		{  RV,  RV,  RV,  RV },
391ac2b0437STejun Heo 		{  P0,  P2, IDE, IDE }, /* 10b (IDE mode) */
392c6fd2807SJeff Garzik 		{  RV,  RV,  RV,  RV },
393c6fd2807SJeff Garzik 	},
394c6fd2807SJeff Garzik };
395c6fd2807SJeff Garzik 
39600242ec8STejun Heo static const struct piix_map_db ich8_2port_map_db = {
397c5cf0ffaSJason Gaston 	.mask = 0x3,
398c5cf0ffaSJason Gaston 	.port_enable = 0x3,
399c5cf0ffaSJason Gaston 	.map = {
400c5cf0ffaSJason Gaston 		/* PM   PS   SM   SS       MAP */
401c5cf0ffaSJason Gaston 		{  P0,  NA,  P1,  NA }, /* 00b */
402c5cf0ffaSJason Gaston 		{  RV,  RV,  RV,  RV }, /* 01b */
403c5cf0ffaSJason Gaston 		{  RV,  RV,  RV,  RV }, /* 10b */
404c5cf0ffaSJason Gaston 		{  RV,  RV,  RV,  RV },
405c5cf0ffaSJason Gaston 	},
406c5cf0ffaSJason Gaston };
407c5cf0ffaSJason Gaston 
4088d8ef2fbSThomas Rohwer static const struct piix_map_db ich8m_apple_map_db = {
4098d8ef2fbSThomas Rohwer 	.mask = 0x3,
4108d8ef2fbSThomas Rohwer 	.port_enable = 0x1,
4118d8ef2fbSThomas Rohwer 	.map = {
4128d8ef2fbSThomas Rohwer 		/* PM   PS   SM   SS       MAP */
4138d8ef2fbSThomas Rohwer 		{  P0,  NA,  NA,  NA }, /* 00b */
4148d8ef2fbSThomas Rohwer 		{  RV,  RV,  RV,  RV },
4158d8ef2fbSThomas Rohwer 		{  P0,  P2, IDE, IDE }, /* 10b */
4168d8ef2fbSThomas Rohwer 		{  RV,  RV,  RV,  RV },
4178d8ef2fbSThomas Rohwer 	},
4188d8ef2fbSThomas Rohwer };
4198d8ef2fbSThomas Rohwer 
42000242ec8STejun Heo static const struct piix_map_db tolapai_map_db = {
4218f73a688SJason Gaston 	.mask = 0x3,
4228f73a688SJason Gaston 	.port_enable = 0x3,
4238f73a688SJason Gaston 	.map = {
4248f73a688SJason Gaston 		/* PM   PS   SM   SS       MAP */
4258f73a688SJason Gaston 		{  P0,  NA,  P1,  NA }, /* 00b */
4268f73a688SJason Gaston 		{  RV,  RV,  RV,  RV }, /* 01b */
4278f73a688SJason Gaston 		{  RV,  RV,  RV,  RV }, /* 10b */
4288f73a688SJason Gaston 		{  RV,  RV,  RV,  RV },
4298f73a688SJason Gaston 	},
4308f73a688SJason Gaston };
4318f73a688SJason Gaston 
432c6fd2807SJeff Garzik static const struct piix_map_db *piix_map_db_table[] = {
433c6fd2807SJeff Garzik 	[ich5_sata]		= &ich5_map_db,
434c6fd2807SJeff Garzik 	[ich6_sata]		= &ich6_map_db,
4359c0bf675STejun Heo 	[ich6m_sata]		= &ich6m_map_db,
4369c0bf675STejun Heo 	[ich8_sata]		= &ich8_map_db,
43700242ec8STejun Heo 	[ich8_2port_sata]	= &ich8_2port_map_db,
4389c0bf675STejun Heo 	[ich8m_apple_sata]	= &ich8m_apple_map_db,
4399c0bf675STejun Heo 	[tolapai_sata]		= &tolapai_map_db,
4405e5a4f5dSMing Lei 	[ich8_sata_snb]		= &ich8_map_db,
441b55f84e2SYouquan Song 	[ich8_2port_sata_snb]	= &ich8_2port_map_db,
442fca8c90dSChew, Chiau Ee 	[ich8_2port_sata_byt]	= &ich8_2port_map_db,
443c6fd2807SJeff Garzik };
444c6fd2807SJeff Garzik 
445494fd076SArvind Yadav static const struct pci_bits piix_enable_bits[] = {
446c6fd2807SJeff Garzik 	{ 0x41U, 1U, 0x80UL, 0x80UL },	/* port 0 */
447c6fd2807SJeff Garzik 	{ 0x43U, 1U, 0x80UL, 0x80UL },	/* port 1 */
448c6fd2807SJeff Garzik };
449c6fd2807SJeff Garzik 
450c6fd2807SJeff Garzik MODULE_AUTHOR("Andre Hedrick, Alan Cox, Andrzej Krzysztofowicz, Jeff Garzik");
451c6fd2807SJeff Garzik MODULE_DESCRIPTION("SCSI low-level driver for Intel PIIX/ICH ATA controllers");
452c6fd2807SJeff Garzik MODULE_LICENSE("GPL");
453c6fd2807SJeff Garzik MODULE_DEVICE_TABLE(pci, piix_pci_tbl);
454c6fd2807SJeff Garzik MODULE_VERSION(DRV_VERSION);
455c6fd2807SJeff Garzik 
456fc085150SAlan Cox struct ich_laptop {
457fc085150SAlan Cox 	u16 device;
458fc085150SAlan Cox 	u16 subvendor;
459fc085150SAlan Cox 	u16 subdevice;
460fc085150SAlan Cox };
461fc085150SAlan Cox 
462fc085150SAlan Cox /*
463fc085150SAlan Cox  *	List of laptops that use short cables rather than 80 wire
464fc085150SAlan Cox  */
465fc085150SAlan Cox 
466fc085150SAlan Cox static const struct ich_laptop ich_laptop[] = {
467fc085150SAlan Cox 	/* devid, subvendor, subdev */
468fc085150SAlan Cox 	{ 0x27DF, 0x0005, 0x0280 },	/* ICH7 on Acer 5602WLMi */
4692655e2ceSAlan Cox 	{ 0x27DF, 0x1025, 0x0102 },	/* ICH7 on Acer 5602aWLMi */
470babfb682SJ J 	{ 0x27DF, 0x1025, 0x0110 },	/* ICH7 on Acer 3682WLMi */
4716034734dSSteve Conklin 	{ 0x27DF, 0x1028, 0x02b0 },	/* ICH7 on unknown Dell */
47212340106SRobin H\. Johnson 	{ 0x27DF, 0x1043, 0x1267 },	/* ICH7 on Asus W5F */
47354174db3SJeff Garzik 	{ 0x27DF, 0x103C, 0x30A1 },	/* ICH7 on HP Compaq nc2400 */
474af901ca1SAndré Goddard Rosa 	{ 0x27DF, 0x103C, 0x361a },	/* ICH7 on unknown HP  */
475d09addf6SHerton Ronaldo Krzesinski 	{ 0x27DF, 0x1071, 0xD221 },	/* ICH7 on Hercules EC-900 */
4766034734dSSteve Conklin 	{ 0x27DF, 0x152D, 0x0778 },	/* ICH7 on unknown Intel */
477b33620f9STejun Heo 	{ 0x24CA, 0x1025, 0x0061 },	/* ICH4 on ACER Aspire 2023WLMi */
478e1fefea9SColin Ian King 	{ 0x24CA, 0x1025, 0x003d },	/* ICH4 on ACER TM290 */
47980a921e2SVille Syrjälä 	{ 0x24CA, 0x10CF, 0x11AB },	/* ICH4M on Fujitsu-Siemens Lifebook S6120 */
480e1fefea9SColin Ian King 	{ 0x266F, 0x1025, 0x0066 },	/* ICH6 on ACER Aspire 1694WLMi */
48101ce2601SDan McGee 	{ 0x2653, 0x1043, 0x82D8 },	/* ICH6M on Asus Eee 701 */
482124a6eecSAlan Cox 	{ 0x27df, 0x104d, 0x900e },	/* ICH7 on Sony TZ-90 */
483fc085150SAlan Cox 	/* end marker */
484fc085150SAlan Cox 	{ 0, }
485fc085150SAlan Cox };
486fc085150SAlan Cox 
piix_port_start(struct ata_port * ap)4875e5a4f5dSMing Lei static int piix_port_start(struct ata_port *ap)
4885e5a4f5dSMing Lei {
4895e5a4f5dSMing Lei 	if (!(ap->flags & PIIX_FLAG_PIO16))
4905e5a4f5dSMing Lei 		ap->pflags |= ATA_PFLAG_PIO32 | ATA_PFLAG_PIO32CHANGE;
4915e5a4f5dSMing Lei 
4925e5a4f5dSMing Lei 	return ata_bmdma_port_start(ap);
4935e5a4f5dSMing Lei }
4945e5a4f5dSMing Lei 
495c6fd2807SJeff Garzik /**
496eb4a2c7fSAlan Cox  *	ich_pata_cable_detect - Probe host controller cable detect info
497c6fd2807SJeff Garzik  *	@ap: Port for which cable detect info is desired
498c6fd2807SJeff Garzik  *
499c6fd2807SJeff Garzik  *	Read 80c cable indicator from ATA PCI device's PCI config
500c6fd2807SJeff Garzik  *	register.  This register is normally set by firmware (BIOS).
501c6fd2807SJeff Garzik  *
502c6fd2807SJeff Garzik  *	LOCKING:
503c6fd2807SJeff Garzik  *	None (inherited from caller).
504c6fd2807SJeff Garzik  */
505669a5db4SJeff Garzik 
ich_pata_cable_detect(struct ata_port * ap)506eb4a2c7fSAlan Cox static int ich_pata_cable_detect(struct ata_port *ap)
507c6fd2807SJeff Garzik {
508cca3974eSJeff Garzik 	struct pci_dev *pdev = to_pci_dev(ap->host->dev);
5092852bcf7STejun Heo 	struct piix_host_priv *hpriv = ap->host->private_data;
510fc085150SAlan Cox 	const struct ich_laptop *lap = &ich_laptop[0];
5112852bcf7STejun Heo 	u8 mask;
512c6fd2807SJeff Garzik 
51389951f22SLevente Kurusa 	/* Check for specials */
514fc085150SAlan Cox 	while (lap->device) {
515fc085150SAlan Cox 		if (lap->device == pdev->device &&
516fc085150SAlan Cox 		    lap->subvendor == pdev->subsystem_vendor &&
5172dcb407eSJeff Garzik 		    lap->subdevice == pdev->subsystem_device)
518eb4a2c7fSAlan Cox 			return ATA_CBL_PATA40_SHORT;
5192dcb407eSJeff Garzik 
520fc085150SAlan Cox 		lap++;
521fc085150SAlan Cox 	}
522fc085150SAlan Cox 
523c6fd2807SJeff Garzik 	/* check BIOS cable detect results */
524c6fd2807SJeff Garzik 	mask = ap->port_no == 0 ? PIIX_80C_PRI : PIIX_80C_SEC;
5252852bcf7STejun Heo 	if ((hpriv->saved_iocfg & mask) == 0)
526eb4a2c7fSAlan Cox 		return ATA_CBL_PATA40;
527eb4a2c7fSAlan Cox 	return ATA_CBL_PATA80;
528c6fd2807SJeff Garzik }
529c6fd2807SJeff Garzik 
530c6fd2807SJeff Garzik /**
531c6fd2807SJeff Garzik  *	piix_pata_prereset - prereset for PATA host controller
532cc0680a5STejun Heo  *	@link: Target link
533d4b2bab4STejun Heo  *	@deadline: deadline jiffies for the operation
534c6fd2807SJeff Garzik  *
535c6fd2807SJeff Garzik  *	LOCKING:
536c6fd2807SJeff Garzik  *	None (inherited from caller).
537c6fd2807SJeff Garzik  */
piix_pata_prereset(struct ata_link * link,unsigned long deadline)538cc0680a5STejun Heo static int piix_pata_prereset(struct ata_link *link, unsigned long deadline)
539c6fd2807SJeff Garzik {
540cc0680a5STejun Heo 	struct ata_port *ap = link->ap;
541cca3974eSJeff Garzik 	struct pci_dev *pdev = to_pci_dev(ap->host->dev);
542c6fd2807SJeff Garzik 
543c961922bSAlan Cox 	if (!pci_test_config_bits(pdev, &piix_enable_bits[ap->port_no]))
544c961922bSAlan Cox 		return -ENOENT;
5459363c382STejun Heo 	return ata_sff_prereset(link, deadline);
546c6fd2807SJeff Garzik }
547c6fd2807SJeff Garzik 
54860c3be38SBartlomiej Zolnierkiewicz static DEFINE_SPINLOCK(piix_lock);
54960c3be38SBartlomiej Zolnierkiewicz 
piix_set_timings(struct ata_port * ap,struct ata_device * adev,u8 pio)5506a94a746SBartlomiej Zolnierkiewicz static void piix_set_timings(struct ata_port *ap, struct ata_device *adev,
5516a94a746SBartlomiej Zolnierkiewicz 			     u8 pio)
552c6fd2807SJeff Garzik {
553cca3974eSJeff Garzik 	struct pci_dev *dev	= to_pci_dev(ap->host->dev);
55460c3be38SBartlomiej Zolnierkiewicz 	unsigned long flags;
555c6fd2807SJeff Garzik 	unsigned int is_slave	= (adev->devno != 0);
556c6fd2807SJeff Garzik 	unsigned int master_port= ap->port_no ? 0x42 : 0x40;
557c6fd2807SJeff Garzik 	unsigned int slave_port	= 0x44;
558c6fd2807SJeff Garzik 	u16 master_data;
559c6fd2807SJeff Garzik 	u8 slave_data;
560669a5db4SJeff Garzik 	u8 udma_enable;
561669a5db4SJeff Garzik 	int control = 0;
562669a5db4SJeff Garzik 
563669a5db4SJeff Garzik 	/*
564669a5db4SJeff Garzik 	 *	See Intel Document 298600-004 for the timing programing rules
565669a5db4SJeff Garzik 	 *	for ICH controllers.
566669a5db4SJeff Garzik 	 */
567669a5db4SJeff Garzik 
568669a5db4SJeff Garzik 	static const	 /* ISP  RTC */
569669a5db4SJeff Garzik 	u8 timings[][2]	= { { 0, 0 },
570669a5db4SJeff Garzik 			    { 0, 0 },
571669a5db4SJeff Garzik 			    { 1, 0 },
572669a5db4SJeff Garzik 			    { 2, 1 },
573669a5db4SJeff Garzik 			    { 2, 3 }, };
574669a5db4SJeff Garzik 
575669a5db4SJeff Garzik 	if (pio >= 2)
576669a5db4SJeff Garzik 		control |= 1;	/* TIME1 enable */
577669a5db4SJeff Garzik 	if (ata_pio_need_iordy(adev))
578669a5db4SJeff Garzik 		control |= 2;	/* IE enable */
579669a5db4SJeff Garzik 	/* Intel specifies that the PPE functionality is for disk only */
580669a5db4SJeff Garzik 	if (adev->class == ATA_DEV_ATA)
581669a5db4SJeff Garzik 		control |= 4;	/* PPE enable */
5826a94a746SBartlomiej Zolnierkiewicz 	/*
5836a94a746SBartlomiej Zolnierkiewicz 	 * If the drive MWDMA is faster than it can do PIO then
5846a94a746SBartlomiej Zolnierkiewicz 	 * we must force PIO into PIO0
5856a94a746SBartlomiej Zolnierkiewicz 	 */
5866a94a746SBartlomiej Zolnierkiewicz 	if (adev->pio_mode < XFER_PIO_0 + pio)
5876a94a746SBartlomiej Zolnierkiewicz 		/* Enable DMA timing only */
5886a94a746SBartlomiej Zolnierkiewicz 		control |= 8;	/* PIO cycles in PIO0 */
589669a5db4SJeff Garzik 
59060c3be38SBartlomiej Zolnierkiewicz 	spin_lock_irqsave(&piix_lock, flags);
59160c3be38SBartlomiej Zolnierkiewicz 
592a5bf5f5aSTejun Heo 	/* PIO configuration clears DTE unconditionally.  It will be
593a5bf5f5aSTejun Heo 	 * programmed in set_dmamode which is guaranteed to be called
594a5bf5f5aSTejun Heo 	 * after set_piomode if any DMA mode is available.
595a5bf5f5aSTejun Heo 	 */
596669a5db4SJeff Garzik 	pci_read_config_word(dev, master_port, &master_data);
597669a5db4SJeff Garzik 	if (is_slave) {
598a5bf5f5aSTejun Heo 		/* clear TIME1|IE1|PPE1|DTE1 */
599a5bf5f5aSTejun Heo 		master_data &= 0xff0f;
600669a5db4SJeff Garzik 		/* enable PPE1, IE1 and TIME1 as needed */
601669a5db4SJeff Garzik 		master_data |= (control << 4);
602669a5db4SJeff Garzik 		pci_read_config_byte(dev, slave_port, &slave_data);
603669a5db4SJeff Garzik 		slave_data &= (ap->port_no ? 0x0f : 0xf0);
604669a5db4SJeff Garzik 		/* Load the timing nibble for this slave */
605a5bf5f5aSTejun Heo 		slave_data |= ((timings[pio][0] << 2) | timings[pio][1])
606a5bf5f5aSTejun Heo 						<< (ap->port_no ? 4 : 0);
607669a5db4SJeff Garzik 	} else {
608a5bf5f5aSTejun Heo 		/* clear ISP|RCT|TIME0|IE0|PPE0|DTE0 */
609a5bf5f5aSTejun Heo 		master_data &= 0xccf0;
610669a5db4SJeff Garzik 		/* Enable PPE, IE and TIME as appropriate */
611669a5db4SJeff Garzik 		master_data |= control;
612a5bf5f5aSTejun Heo 		/* load ISP and RCT */
613669a5db4SJeff Garzik 		master_data |=
614669a5db4SJeff Garzik 			(timings[pio][0] << 12) |
615669a5db4SJeff Garzik 			(timings[pio][1] << 8);
616669a5db4SJeff Garzik 	}
617ce986690SBartlomiej Zolnierkiewicz 
618ce986690SBartlomiej Zolnierkiewicz 	/* Enable SITRE (separate slave timing register) */
619ce986690SBartlomiej Zolnierkiewicz 	master_data |= 0x4000;
620669a5db4SJeff Garzik 	pci_write_config_word(dev, master_port, master_data);
621669a5db4SJeff Garzik 	if (is_slave)
622669a5db4SJeff Garzik 		pci_write_config_byte(dev, slave_port, slave_data);
623669a5db4SJeff Garzik 
624669a5db4SJeff Garzik 	/* Ensure the UDMA bit is off - it will be turned back on if
625669a5db4SJeff Garzik 	   UDMA is selected */
626669a5db4SJeff Garzik 
627669a5db4SJeff Garzik 	if (ap->udma_mask) {
628669a5db4SJeff Garzik 		pci_read_config_byte(dev, 0x48, &udma_enable);
629669a5db4SJeff Garzik 		udma_enable &= ~(1 << (2 * ap->port_no + adev->devno));
630669a5db4SJeff Garzik 		pci_write_config_byte(dev, 0x48, udma_enable);
631669a5db4SJeff Garzik 	}
63260c3be38SBartlomiej Zolnierkiewicz 
63360c3be38SBartlomiej Zolnierkiewicz 	spin_unlock_irqrestore(&piix_lock, flags);
634669a5db4SJeff Garzik }
635669a5db4SJeff Garzik 
636669a5db4SJeff Garzik /**
6376a94a746SBartlomiej Zolnierkiewicz  *	piix_set_piomode - Initialize host controller PATA PIO timings
6386a94a746SBartlomiej Zolnierkiewicz  *	@ap: Port whose timings we are configuring
6396a94a746SBartlomiej Zolnierkiewicz  *	@adev: Drive in question
6406a94a746SBartlomiej Zolnierkiewicz  *
6416a94a746SBartlomiej Zolnierkiewicz  *	Set PIO mode for device, in host controller PCI config space.
6426a94a746SBartlomiej Zolnierkiewicz  *
6436a94a746SBartlomiej Zolnierkiewicz  *	LOCKING:
6446a94a746SBartlomiej Zolnierkiewicz  *	None (inherited from caller).
6456a94a746SBartlomiej Zolnierkiewicz  */
6466a94a746SBartlomiej Zolnierkiewicz 
piix_set_piomode(struct ata_port * ap,struct ata_device * adev)6476a94a746SBartlomiej Zolnierkiewicz static void piix_set_piomode(struct ata_port *ap, struct ata_device *adev)
6486a94a746SBartlomiej Zolnierkiewicz {
6496a94a746SBartlomiej Zolnierkiewicz 	piix_set_timings(ap, adev, adev->pio_mode - XFER_PIO_0);
6506a94a746SBartlomiej Zolnierkiewicz }
6516a94a746SBartlomiej Zolnierkiewicz 
6526a94a746SBartlomiej Zolnierkiewicz /**
653669a5db4SJeff Garzik  *	do_pata_set_dmamode - Initialize host controller PATA PIO timings
654669a5db4SJeff Garzik  *	@ap: Port whose timings we are configuring
655669a5db4SJeff Garzik  *	@adev: Drive in question
656c32a8fd7SHenne  *	@isich: set if the chip is an ICH device
657669a5db4SJeff Garzik  *
658669a5db4SJeff Garzik  *	Set UDMA mode for device, in host controller PCI config space.
659669a5db4SJeff Garzik  *
660669a5db4SJeff Garzik  *	LOCKING:
661669a5db4SJeff Garzik  *	None (inherited from caller).
662669a5db4SJeff Garzik  */
663669a5db4SJeff Garzik 
do_pata_set_dmamode(struct ata_port * ap,struct ata_device * adev,int isich)664669a5db4SJeff Garzik static void do_pata_set_dmamode(struct ata_port *ap, struct ata_device *adev, int isich)
665669a5db4SJeff Garzik {
666669a5db4SJeff Garzik 	struct pci_dev *dev	= to_pci_dev(ap->host->dev);
66760c3be38SBartlomiej Zolnierkiewicz 	unsigned long flags;
668669a5db4SJeff Garzik 	u8 speed		= adev->dma_mode;
669669a5db4SJeff Garzik 	int devid		= adev->devno + 2 * ap->port_no;
670dedf61dbSAndrew Morton 	u8 udma_enable		= 0;
671c6fd2807SJeff Garzik 
672669a5db4SJeff Garzik 	if (speed >= XFER_UDMA_0) {
6736a94a746SBartlomiej Zolnierkiewicz 		unsigned int udma = speed - XFER_UDMA_0;
674669a5db4SJeff Garzik 		u16 udma_timing;
675669a5db4SJeff Garzik 		u16 ideconf;
676669a5db4SJeff Garzik 		int u_clock, u_speed;
677669a5db4SJeff Garzik 
6786a94a746SBartlomiej Zolnierkiewicz 		spin_lock_irqsave(&piix_lock, flags);
6796a94a746SBartlomiej Zolnierkiewicz 
6806a94a746SBartlomiej Zolnierkiewicz 		pci_read_config_byte(dev, 0x48, &udma_enable);
6816a94a746SBartlomiej Zolnierkiewicz 
682669a5db4SJeff Garzik 		/*
683669a5db4SJeff Garzik 		 * UDMA is handled by a combination of clock switching and
684669a5db4SJeff Garzik 		 * selection of dividers
685669a5db4SJeff Garzik 		 *
686669a5db4SJeff Garzik 		 * Handy rule: Odd modes are UDMATIMx 01, even are 02
687669a5db4SJeff Garzik 		 *	       except UDMA0 which is 00
688669a5db4SJeff Garzik 		 */
689669a5db4SJeff Garzik 		u_speed = min(2 - (udma & 1), udma);
690669a5db4SJeff Garzik 		if (udma == 5)
691669a5db4SJeff Garzik 			u_clock = 0x1000;	/* 100Mhz */
692669a5db4SJeff Garzik 		else if (udma > 2)
693669a5db4SJeff Garzik 			u_clock = 1;		/* 66Mhz */
694669a5db4SJeff Garzik 		else
695669a5db4SJeff Garzik 			u_clock = 0;		/* 33Mhz */
696669a5db4SJeff Garzik 
697669a5db4SJeff Garzik 		udma_enable |= (1 << devid);
698669a5db4SJeff Garzik 
699669a5db4SJeff Garzik 		/* Load the CT/RP selection */
700669a5db4SJeff Garzik 		pci_read_config_word(dev, 0x4A, &udma_timing);
701669a5db4SJeff Garzik 		udma_timing &= ~(3 << (4 * devid));
702669a5db4SJeff Garzik 		udma_timing |= u_speed << (4 * devid);
703669a5db4SJeff Garzik 		pci_write_config_word(dev, 0x4A, udma_timing);
704669a5db4SJeff Garzik 
705669a5db4SJeff Garzik 		if (isich) {
706669a5db4SJeff Garzik 			/* Select a 33/66/100Mhz clock */
707669a5db4SJeff Garzik 			pci_read_config_word(dev, 0x54, &ideconf);
708669a5db4SJeff Garzik 			ideconf &= ~(0x1001 << devid);
709669a5db4SJeff Garzik 			ideconf |= u_clock << devid;
710669a5db4SJeff Garzik 			/* For ICH or later we should set bit 10 for better
711669a5db4SJeff Garzik 			   performance (WR_PingPong_En) */
712669a5db4SJeff Garzik 			pci_write_config_word(dev, 0x54, ideconf);
713669a5db4SJeff Garzik 		}
7146a94a746SBartlomiej Zolnierkiewicz 
7156a94a746SBartlomiej Zolnierkiewicz 		pci_write_config_byte(dev, 0x48, udma_enable);
7166a94a746SBartlomiej Zolnierkiewicz 
7176a94a746SBartlomiej Zolnierkiewicz 		spin_unlock_irqrestore(&piix_lock, flags);
718c6fd2807SJeff Garzik 	} else {
7196a94a746SBartlomiej Zolnierkiewicz 		/* MWDMA is driven by the PIO timings. */
7206a94a746SBartlomiej Zolnierkiewicz 		unsigned int mwdma = speed - XFER_MW_DMA_0;
721669a5db4SJeff Garzik 		const unsigned int needed_pio[3] = {
722669a5db4SJeff Garzik 			XFER_PIO_0, XFER_PIO_3, XFER_PIO_4
723669a5db4SJeff Garzik 		};
724669a5db4SJeff Garzik 		int pio = needed_pio[mwdma] - XFER_PIO_0;
725669a5db4SJeff Garzik 
7266a94a746SBartlomiej Zolnierkiewicz 		/* XFER_PIO_0 is never used currently */
7276a94a746SBartlomiej Zolnierkiewicz 		piix_set_timings(ap, adev, pio);
728c6fd2807SJeff Garzik 	}
729c6fd2807SJeff Garzik }
730c6fd2807SJeff Garzik 
731c6fd2807SJeff Garzik /**
732669a5db4SJeff Garzik  *	piix_set_dmamode - Initialize host controller PATA DMA timings
733c6fd2807SJeff Garzik  *	@ap: Port whose timings we are configuring
734c6fd2807SJeff Garzik  *	@adev: um
735c6fd2807SJeff Garzik  *
736669a5db4SJeff Garzik  *	Set MW/UDMA mode for device, in host controller PCI config space.
737c6fd2807SJeff Garzik  *
738c6fd2807SJeff Garzik  *	LOCKING:
739c6fd2807SJeff Garzik  *	None (inherited from caller).
740c6fd2807SJeff Garzik  */
741c6fd2807SJeff Garzik 
piix_set_dmamode(struct ata_port * ap,struct ata_device * adev)742c6fd2807SJeff Garzik static void piix_set_dmamode(struct ata_port *ap, struct ata_device *adev)
743c6fd2807SJeff Garzik {
744669a5db4SJeff Garzik 	do_pata_set_dmamode(ap, adev, 0);
745c6fd2807SJeff Garzik }
746c6fd2807SJeff Garzik 
747669a5db4SJeff Garzik /**
748669a5db4SJeff Garzik  *	ich_set_dmamode - Initialize host controller PATA DMA timings
749669a5db4SJeff Garzik  *	@ap: Port whose timings we are configuring
750669a5db4SJeff Garzik  *	@adev: um
751669a5db4SJeff Garzik  *
752669a5db4SJeff Garzik  *	Set MW/UDMA mode for device, in host controller PCI config space.
753669a5db4SJeff Garzik  *
754669a5db4SJeff Garzik  *	LOCKING:
755669a5db4SJeff Garzik  *	None (inherited from caller).
756669a5db4SJeff Garzik  */
757669a5db4SJeff Garzik 
ich_set_dmamode(struct ata_port * ap,struct ata_device * adev)758669a5db4SJeff Garzik static void ich_set_dmamode(struct ata_port *ap, struct ata_device *adev)
759669a5db4SJeff Garzik {
760669a5db4SJeff Garzik 	do_pata_set_dmamode(ap, adev, 1);
761c6fd2807SJeff Garzik }
762c6fd2807SJeff Garzik 
763c7290724STejun Heo /*
764c7290724STejun Heo  * Serial ATA Index/Data Pair Superset Registers access
765c7290724STejun Heo  *
766c7290724STejun Heo  * Beginning from ICH8, there's a sane way to access SCRs using index
767be77e43aSTejun Heo  * and data register pair located at BAR5 which means that we have
768be77e43aSTejun Heo  * separate SCRs for master and slave.  This is handled using libata
769be77e43aSTejun Heo  * slave_link facility.
770c7290724STejun Heo  */
771c7290724STejun Heo static const int piix_sidx_map[] = {
772c7290724STejun Heo 	[SCR_STATUS]	= 0,
773c7290724STejun Heo 	[SCR_ERROR]	= 2,
774c7290724STejun Heo 	[SCR_CONTROL]	= 1,
775c7290724STejun Heo };
776c7290724STejun Heo 
piix_sidpr_sel(struct ata_link * link,unsigned int reg)777be77e43aSTejun Heo static void piix_sidpr_sel(struct ata_link *link, unsigned int reg)
778c7290724STejun Heo {
779be77e43aSTejun Heo 	struct ata_port *ap = link->ap;
780c7290724STejun Heo 	struct piix_host_priv *hpriv = ap->host->private_data;
781c7290724STejun Heo 
782be77e43aSTejun Heo 	iowrite32(((ap->port_no * 2 + link->pmp) << 8) | piix_sidx_map[reg],
783c7290724STejun Heo 		  hpriv->sidpr + PIIX_SIDPR_IDX);
784c7290724STejun Heo }
785c7290724STejun Heo 
piix_sidpr_scr_read(struct ata_link * link,unsigned int reg,u32 * val)78682ef04fbSTejun Heo static int piix_sidpr_scr_read(struct ata_link *link,
78782ef04fbSTejun Heo 			       unsigned int reg, u32 *val)
788c7290724STejun Heo {
789be77e43aSTejun Heo 	struct piix_host_priv *hpriv = link->ap->host->private_data;
790c7290724STejun Heo 
791c7290724STejun Heo 	if (reg >= ARRAY_SIZE(piix_sidx_map))
792c7290724STejun Heo 		return -EINVAL;
793c7290724STejun Heo 
794be77e43aSTejun Heo 	piix_sidpr_sel(link, reg);
795be77e43aSTejun Heo 	*val = ioread32(hpriv->sidpr + PIIX_SIDPR_DATA);
796c7290724STejun Heo 	return 0;
797c7290724STejun Heo }
798c7290724STejun Heo 
piix_sidpr_scr_write(struct ata_link * link,unsigned int reg,u32 val)79982ef04fbSTejun Heo static int piix_sidpr_scr_write(struct ata_link *link,
80082ef04fbSTejun Heo 				unsigned int reg, u32 val)
801c7290724STejun Heo {
802be77e43aSTejun Heo 	struct piix_host_priv *hpriv = link->ap->host->private_data;
80382ef04fbSTejun Heo 
804c7290724STejun Heo 	if (reg >= ARRAY_SIZE(piix_sidx_map))
805c7290724STejun Heo 		return -EINVAL;
806c7290724STejun Heo 
807be77e43aSTejun Heo 	piix_sidpr_sel(link, reg);
808be77e43aSTejun Heo 	iowrite32(val, hpriv->sidpr + PIIX_SIDPR_DATA);
809c7290724STejun Heo 	return 0;
810c7290724STejun Heo }
811c7290724STejun Heo 
piix_sidpr_set_lpm(struct ata_link * link,enum ata_lpm_policy policy,unsigned hints)812a97c4006STejun Heo static int piix_sidpr_set_lpm(struct ata_link *link, enum ata_lpm_policy policy,
813a97c4006STejun Heo 			      unsigned hints)
814a97c4006STejun Heo {
815a97c4006STejun Heo 	return sata_link_scr_lpm(link, policy, false);
816a97c4006STejun Heo }
817a97c4006STejun Heo 
piix_irq_check(struct ata_port * ap)81827943620STejun Heo static bool piix_irq_check(struct ata_port *ap)
81927943620STejun Heo {
820c206a389SHannes Reinecke 	unsigned char host_stat;
821c206a389SHannes Reinecke 
82227943620STejun Heo 	if (unlikely(!ap->ioaddr.bmdma_addr))
82327943620STejun Heo 		return false;
82427943620STejun Heo 
825c206a389SHannes Reinecke 	host_stat = ap->ops->bmdma_status(ap);
826c206a389SHannes Reinecke 	trace_ata_bmdma_status(ap, host_stat);
827c206a389SHannes Reinecke 
828c206a389SHannes Reinecke 	return host_stat & ATA_DMA_INTR;
82927943620STejun Heo }
83027943620STejun Heo 
83158eb8cd5SBartlomiej Zolnierkiewicz #ifdef CONFIG_PM_SLEEP
piix_broken_suspend(void)8328c3832ebSTejun Heo static int piix_broken_suspend(void)
8338c3832ebSTejun Heo {
8341855256cSJeff Garzik 	static const struct dmi_system_id sysids[] = {
835b8b275efSTejun Heo 		{
8364c74d4ecSTejun Heo 			.ident = "TECRA M3",
8374c74d4ecSTejun Heo 			.matches = {
8384c74d4ecSTejun Heo 				DMI_MATCH(DMI_SYS_VENDOR, "TOSHIBA"),
8394c74d4ecSTejun Heo 				DMI_MATCH(DMI_PRODUCT_NAME, "TECRA M3"),
8404c74d4ecSTejun Heo 			},
8414c74d4ecSTejun Heo 		},
8424c74d4ecSTejun Heo 		{
84304d86d6fSPeter Schwenke 			.ident = "TECRA M3",
84404d86d6fSPeter Schwenke 			.matches = {
84504d86d6fSPeter Schwenke 				DMI_MATCH(DMI_SYS_VENDOR, "TOSHIBA"),
84604d86d6fSPeter Schwenke 				DMI_MATCH(DMI_PRODUCT_NAME, "Tecra M3"),
84704d86d6fSPeter Schwenke 			},
84804d86d6fSPeter Schwenke 		},
84904d86d6fSPeter Schwenke 		{
850dee58fe8SMichał Mirosław 			.ident = "TECRA M3",
851dee58fe8SMichał Mirosław 			.matches = {
852dee58fe8SMichał Mirosław 				DMI_MATCH(DMI_OEM_STRING, "Tecra M3,"),
853dee58fe8SMichał Mirosław 			},
854dee58fe8SMichał Mirosław 		},
855dee58fe8SMichał Mirosław 		{
856d1aa690aSPeter Schwenke 			.ident = "TECRA M4",
857d1aa690aSPeter Schwenke 			.matches = {
858d1aa690aSPeter Schwenke 				DMI_MATCH(DMI_SYS_VENDOR, "TOSHIBA"),
859d1aa690aSPeter Schwenke 				DMI_MATCH(DMI_PRODUCT_NAME, "Tecra M4"),
860d1aa690aSPeter Schwenke 			},
861d1aa690aSPeter Schwenke 		},
862d1aa690aSPeter Schwenke 		{
863040dee53STejun Heo 			.ident = "TECRA M4",
864040dee53STejun Heo 			.matches = {
865040dee53STejun Heo 				DMI_MATCH(DMI_SYS_VENDOR, "TOSHIBA"),
866040dee53STejun Heo 				DMI_MATCH(DMI_PRODUCT_NAME, "TECRA M4"),
867040dee53STejun Heo 			},
868040dee53STejun Heo 		},
869040dee53STejun Heo 		{
870b8b275efSTejun Heo 			.ident = "TECRA M5",
871b8b275efSTejun Heo 			.matches = {
872b8b275efSTejun Heo 				DMI_MATCH(DMI_SYS_VENDOR, "TOSHIBA"),
873b8b275efSTejun Heo 				DMI_MATCH(DMI_PRODUCT_NAME, "TECRA M5"),
874b8b275efSTejun Heo 			},
875b8b275efSTejun Heo 		},
876b8b275efSTejun Heo 		{
877ffe188ddSPeter Schwenke 			.ident = "TECRA M6",
878ffe188ddSPeter Schwenke 			.matches = {
879ffe188ddSPeter Schwenke 				DMI_MATCH(DMI_SYS_VENDOR, "TOSHIBA"),
880ffe188ddSPeter Schwenke 				DMI_MATCH(DMI_PRODUCT_NAME, "TECRA M6"),
881ffe188ddSPeter Schwenke 			},
882ffe188ddSPeter Schwenke 		},
883ffe188ddSPeter Schwenke 		{
8845c08ea01STejun Heo 			.ident = "TECRA M7",
8855c08ea01STejun Heo 			.matches = {
8865c08ea01STejun Heo 				DMI_MATCH(DMI_SYS_VENDOR, "TOSHIBA"),
8875c08ea01STejun Heo 				DMI_MATCH(DMI_PRODUCT_NAME, "TECRA M7"),
8885c08ea01STejun Heo 			},
8895c08ea01STejun Heo 		},
8905c08ea01STejun Heo 		{
89104d86d6fSPeter Schwenke 			.ident = "TECRA A8",
89204d86d6fSPeter Schwenke 			.matches = {
89304d86d6fSPeter Schwenke 				DMI_MATCH(DMI_SYS_VENDOR, "TOSHIBA"),
89404d86d6fSPeter Schwenke 				DMI_MATCH(DMI_PRODUCT_NAME, "TECRA A8"),
89504d86d6fSPeter Schwenke 			},
89604d86d6fSPeter Schwenke 		},
89704d86d6fSPeter Schwenke 		{
898ffe188ddSPeter Schwenke 			.ident = "Satellite R20",
899ffe188ddSPeter Schwenke 			.matches = {
900ffe188ddSPeter Schwenke 				DMI_MATCH(DMI_SYS_VENDOR, "TOSHIBA"),
901ffe188ddSPeter Schwenke 				DMI_MATCH(DMI_PRODUCT_NAME, "Satellite R20"),
902ffe188ddSPeter Schwenke 			},
903ffe188ddSPeter Schwenke 		},
904ffe188ddSPeter Schwenke 		{
90504d86d6fSPeter Schwenke 			.ident = "Satellite R25",
90604d86d6fSPeter Schwenke 			.matches = {
90704d86d6fSPeter Schwenke 				DMI_MATCH(DMI_SYS_VENDOR, "TOSHIBA"),
90804d86d6fSPeter Schwenke 				DMI_MATCH(DMI_PRODUCT_NAME, "Satellite R25"),
90904d86d6fSPeter Schwenke 			},
91004d86d6fSPeter Schwenke 		},
91104d86d6fSPeter Schwenke 		{
9123cc0b9d3STejun Heo 			.ident = "Satellite U200",
9133cc0b9d3STejun Heo 			.matches = {
9143cc0b9d3STejun Heo 				DMI_MATCH(DMI_SYS_VENDOR, "TOSHIBA"),
9153cc0b9d3STejun Heo 				DMI_MATCH(DMI_PRODUCT_NAME, "Satellite U200"),
9163cc0b9d3STejun Heo 			},
9173cc0b9d3STejun Heo 		},
9183cc0b9d3STejun Heo 		{
91904d86d6fSPeter Schwenke 			.ident = "Satellite U200",
92004d86d6fSPeter Schwenke 			.matches = {
92104d86d6fSPeter Schwenke 				DMI_MATCH(DMI_SYS_VENDOR, "TOSHIBA"),
92204d86d6fSPeter Schwenke 				DMI_MATCH(DMI_PRODUCT_NAME, "SATELLITE U200"),
92304d86d6fSPeter Schwenke 			},
92404d86d6fSPeter Schwenke 		},
92504d86d6fSPeter Schwenke 		{
92662320e23SYann Chachkoff 			.ident = "Satellite Pro U200",
92762320e23SYann Chachkoff 			.matches = {
92862320e23SYann Chachkoff 				DMI_MATCH(DMI_SYS_VENDOR, "TOSHIBA"),
92962320e23SYann Chachkoff 				DMI_MATCH(DMI_PRODUCT_NAME, "SATELLITE PRO U200"),
93062320e23SYann Chachkoff 			},
93162320e23SYann Chachkoff 		},
93262320e23SYann Chachkoff 		{
933b8b275efSTejun Heo 			.ident = "Satellite U205",
934b8b275efSTejun Heo 			.matches = {
935b8b275efSTejun Heo 				DMI_MATCH(DMI_SYS_VENDOR, "TOSHIBA"),
936b8b275efSTejun Heo 				DMI_MATCH(DMI_PRODUCT_NAME, "Satellite U205"),
937b8b275efSTejun Heo 			},
938b8b275efSTejun Heo 		},
939b8b275efSTejun Heo 		{
940de753e5eSTejun Heo 			.ident = "SATELLITE U205",
941de753e5eSTejun Heo 			.matches = {
942de753e5eSTejun Heo 				DMI_MATCH(DMI_SYS_VENDOR, "TOSHIBA"),
943de753e5eSTejun Heo 				DMI_MATCH(DMI_PRODUCT_NAME, "SATELLITE U205"),
944de753e5eSTejun Heo 			},
945de753e5eSTejun Heo 		},
946de753e5eSTejun Heo 		{
947b73fa463SBenjamin Larsson 			.ident = "Satellite Pro A120",
948b73fa463SBenjamin Larsson 			.matches = {
949b73fa463SBenjamin Larsson 				DMI_MATCH(DMI_SYS_VENDOR, "TOSHIBA"),
950b73fa463SBenjamin Larsson 				DMI_MATCH(DMI_PRODUCT_NAME, "Satellite Pro A120"),
951b73fa463SBenjamin Larsson 			},
952b73fa463SBenjamin Larsson 		},
953b73fa463SBenjamin Larsson 		{
954b8b275efSTejun Heo 			.ident = "Portege M500",
955b8b275efSTejun Heo 			.matches = {
956b8b275efSTejun Heo 				DMI_MATCH(DMI_SYS_VENDOR, "TOSHIBA"),
957b8b275efSTejun Heo 				DMI_MATCH(DMI_PRODUCT_NAME, "PORTEGE M500"),
958b8b275efSTejun Heo 			},
959b8b275efSTejun Heo 		},
960c3f93b8fSTejun Heo 		{
961c3f93b8fSTejun Heo 			.ident = "VGN-BX297XP",
962c3f93b8fSTejun Heo 			.matches = {
963c3f93b8fSTejun Heo 				DMI_MATCH(DMI_SYS_VENDOR, "Sony Corporation"),
964c3f93b8fSTejun Heo 				DMI_MATCH(DMI_PRODUCT_NAME, "VGN-BX297XP"),
965c3f93b8fSTejun Heo 			},
966c3f93b8fSTejun Heo 		},
9677d051548SJeff Garzik 
9687d051548SJeff Garzik 		{ }	/* terminate list */
969b8b275efSTejun Heo 	};
970b8b275efSTejun Heo 
9718c3832ebSTejun Heo 	if (dmi_check_system(sysids))
9728c3832ebSTejun Heo 		return 1;
9738c3832ebSTejun Heo 
9741eedb4a9STejun Heo 	/* TECRA M4 sometimes forgets its identify and reports bogus
9751eedb4a9STejun Heo 	 * DMI information.  As the bogus information is a bit
9761eedb4a9STejun Heo 	 * generic, match as many entries as possible.  This manual
9771eedb4a9STejun Heo 	 * matching is necessary because dmi_system_id.matches is
9781eedb4a9STejun Heo 	 * limited to four entries.
9791eedb4a9STejun Heo 	 */
9803c387730SJiri Slaby 	if (dmi_match(DMI_SYS_VENDOR, "TOSHIBA") &&
9813c387730SJiri Slaby 	    dmi_match(DMI_PRODUCT_NAME, "000000") &&
9823c387730SJiri Slaby 	    dmi_match(DMI_PRODUCT_VERSION, "000000") &&
9833c387730SJiri Slaby 	    dmi_match(DMI_PRODUCT_SERIAL, "000000") &&
9843c387730SJiri Slaby 	    dmi_match(DMI_BOARD_VENDOR, "TOSHIBA") &&
9853c387730SJiri Slaby 	    dmi_match(DMI_BOARD_NAME, "Portable PC") &&
9863c387730SJiri Slaby 	    dmi_match(DMI_BOARD_VERSION, "Version A0"))
9871eedb4a9STejun Heo 		return 1;
9881eedb4a9STejun Heo 
9898c3832ebSTejun Heo 	return 0;
9908c3832ebSTejun Heo }
9918c3832ebSTejun Heo 
piix_pci_device_suspend(struct pci_dev * pdev,pm_message_t mesg)992b8b275efSTejun Heo static int piix_pci_device_suspend(struct pci_dev *pdev, pm_message_t mesg)
993b8b275efSTejun Heo {
9940a86e1c8SJingoo Han 	struct ata_host *host = pci_get_drvdata(pdev);
995b8b275efSTejun Heo 	unsigned long flags;
996b8b275efSTejun Heo 
997ec87cf37SSergey Shtylyov 	ata_host_suspend(host, mesg);
998b8b275efSTejun Heo 
999b8b275efSTejun Heo 	/* Some braindamaged ACPI suspend implementations expect the
1000b8b275efSTejun Heo 	 * controller to be awake on entry; otherwise, it burns cpu
1001b8b275efSTejun Heo 	 * cycles and power trying to do something to the sleeping
1002b8b275efSTejun Heo 	 * beauty.
1003b8b275efSTejun Heo 	 */
10043a2d5b70SRafael J. Wysocki 	if (piix_broken_suspend() && (mesg.event & PM_EVENT_SLEEP)) {
1005b8b275efSTejun Heo 		pci_save_state(pdev);
1006b8b275efSTejun Heo 
1007b8b275efSTejun Heo 		/* mark its power state as "unknown", since we don't
1008b8b275efSTejun Heo 		 * know if e.g. the BIOS will change its device state
1009b8b275efSTejun Heo 		 * when we suspend.
1010b8b275efSTejun Heo 		 */
1011b8b275efSTejun Heo 		if (pdev->current_state == PCI_D0)
1012b8b275efSTejun Heo 			pdev->current_state = PCI_UNKNOWN;
1013b8b275efSTejun Heo 
1014b8b275efSTejun Heo 		/* tell resume that it's waking up from broken suspend */
1015b8b275efSTejun Heo 		spin_lock_irqsave(&host->lock, flags);
1016b8b275efSTejun Heo 		host->flags |= PIIX_HOST_BROKEN_SUSPEND;
1017b8b275efSTejun Heo 		spin_unlock_irqrestore(&host->lock, flags);
1018b8b275efSTejun Heo 	} else
1019b8b275efSTejun Heo 		ata_pci_device_do_suspend(pdev, mesg);
1020b8b275efSTejun Heo 
1021b8b275efSTejun Heo 	return 0;
1022b8b275efSTejun Heo }
1023b8b275efSTejun Heo 
piix_pci_device_resume(struct pci_dev * pdev)1024b8b275efSTejun Heo static int piix_pci_device_resume(struct pci_dev *pdev)
1025b8b275efSTejun Heo {
10260a86e1c8SJingoo Han 	struct ata_host *host = pci_get_drvdata(pdev);
1027b8b275efSTejun Heo 	unsigned long flags;
1028b8b275efSTejun Heo 	int rc;
1029b8b275efSTejun Heo 
1030b8b275efSTejun Heo 	if (host->flags & PIIX_HOST_BROKEN_SUSPEND) {
1031b8b275efSTejun Heo 		spin_lock_irqsave(&host->lock, flags);
1032b8b275efSTejun Heo 		host->flags &= ~PIIX_HOST_BROKEN_SUSPEND;
1033b8b275efSTejun Heo 		spin_unlock_irqrestore(&host->lock, flags);
1034b8b275efSTejun Heo 
1035b8b275efSTejun Heo 		pci_set_power_state(pdev, PCI_D0);
1036b8b275efSTejun Heo 		pci_restore_state(pdev);
1037b8b275efSTejun Heo 
1038b8b275efSTejun Heo 		/* PCI device wasn't disabled during suspend.  Use
10390b62e13bSTejun Heo 		 * pci_reenable_device() to avoid affecting the enable
10400b62e13bSTejun Heo 		 * count.
1041b8b275efSTejun Heo 		 */
10420b62e13bSTejun Heo 		rc = pci_reenable_device(pdev);
1043b8b275efSTejun Heo 		if (rc)
1044a44fec1fSJoe Perches 			dev_err(&pdev->dev,
1045a44fec1fSJoe Perches 				"failed to enable device after resume (%d)\n",
1046a44fec1fSJoe Perches 				rc);
1047b8b275efSTejun Heo 	} else
1048b8b275efSTejun Heo 		rc = ata_pci_device_do_resume(pdev);
1049b8b275efSTejun Heo 
1050b8b275efSTejun Heo 	if (rc == 0)
1051b8b275efSTejun Heo 		ata_host_resume(host);
1052b8b275efSTejun Heo 
1053b8b275efSTejun Heo 	return rc;
1054b8b275efSTejun Heo }
1055b8b275efSTejun Heo #endif
1056b8b275efSTejun Heo 
piix_vmw_bmdma_status(struct ata_port * ap)105725f98131STejun Heo static u8 piix_vmw_bmdma_status(struct ata_port *ap)
105825f98131STejun Heo {
105925f98131STejun Heo 	return ata_bmdma_status(ap) & ~ATA_DMA_ERR;
106025f98131STejun Heo }
106125f98131STejun Heo 
1062*25df73d9SBart Van Assche static const struct scsi_host_template piix_sht = {
1063f295be25SBartlomiej Zolnierkiewicz 	ATA_BMDMA_SHT(DRV_NAME),
1064f295be25SBartlomiej Zolnierkiewicz };
1065f295be25SBartlomiej Zolnierkiewicz 
1066f295be25SBartlomiej Zolnierkiewicz static struct ata_port_operations piix_sata_ops = {
1067f295be25SBartlomiej Zolnierkiewicz 	.inherits		= &ata_bmdma32_port_ops,
1068f295be25SBartlomiej Zolnierkiewicz 	.sff_irq_check		= piix_irq_check,
1069f295be25SBartlomiej Zolnierkiewicz 	.port_start		= piix_port_start,
1070f295be25SBartlomiej Zolnierkiewicz };
1071f295be25SBartlomiej Zolnierkiewicz 
1072f295be25SBartlomiej Zolnierkiewicz static struct ata_port_operations piix_pata_ops = {
1073f295be25SBartlomiej Zolnierkiewicz 	.inherits		= &piix_sata_ops,
1074f295be25SBartlomiej Zolnierkiewicz 	.cable_detect		= ata_cable_40wire,
1075f295be25SBartlomiej Zolnierkiewicz 	.set_piomode		= piix_set_piomode,
1076f295be25SBartlomiej Zolnierkiewicz 	.set_dmamode		= piix_set_dmamode,
1077f295be25SBartlomiej Zolnierkiewicz 	.prereset		= piix_pata_prereset,
1078f295be25SBartlomiej Zolnierkiewicz };
1079f295be25SBartlomiej Zolnierkiewicz 
1080f295be25SBartlomiej Zolnierkiewicz static struct ata_port_operations piix_vmw_ops = {
1081f295be25SBartlomiej Zolnierkiewicz 	.inherits		= &piix_pata_ops,
1082f295be25SBartlomiej Zolnierkiewicz 	.bmdma_status		= piix_vmw_bmdma_status,
1083f295be25SBartlomiej Zolnierkiewicz };
1084f295be25SBartlomiej Zolnierkiewicz 
1085f295be25SBartlomiej Zolnierkiewicz static struct ata_port_operations ich_pata_ops = {
1086f295be25SBartlomiej Zolnierkiewicz 	.inherits		= &piix_pata_ops,
1087f295be25SBartlomiej Zolnierkiewicz 	.cable_detect		= ich_pata_cable_detect,
1088f295be25SBartlomiej Zolnierkiewicz 	.set_dmamode		= ich_set_dmamode,
1089f295be25SBartlomiej Zolnierkiewicz };
1090f295be25SBartlomiej Zolnierkiewicz 
1091c3f69c7fSBart Van Assche static struct attribute *piix_sidpr_shost_attrs[] = {
1092c3f69c7fSBart Van Assche 	&dev_attr_link_power_management_policy.attr,
1093f295be25SBartlomiej Zolnierkiewicz 	NULL
1094f295be25SBartlomiej Zolnierkiewicz };
1095f295be25SBartlomiej Zolnierkiewicz 
1096c3f69c7fSBart Van Assche ATTRIBUTE_GROUPS(piix_sidpr_shost);
1097c3f69c7fSBart Van Assche 
1098*25df73d9SBart Van Assche static const struct scsi_host_template piix_sidpr_sht = {
1099f295be25SBartlomiej Zolnierkiewicz 	ATA_BMDMA_SHT(DRV_NAME),
1100c3f69c7fSBart Van Assche 	.shost_groups		= piix_sidpr_shost_groups,
1101f295be25SBartlomiej Zolnierkiewicz };
1102f295be25SBartlomiej Zolnierkiewicz 
1103f295be25SBartlomiej Zolnierkiewicz static struct ata_port_operations piix_sidpr_sata_ops = {
1104f295be25SBartlomiej Zolnierkiewicz 	.inherits		= &piix_sata_ops,
1105f295be25SBartlomiej Zolnierkiewicz 	.hardreset		= sata_std_hardreset,
1106f295be25SBartlomiej Zolnierkiewicz 	.scr_read		= piix_sidpr_scr_read,
1107f295be25SBartlomiej Zolnierkiewicz 	.scr_write		= piix_sidpr_scr_write,
1108f295be25SBartlomiej Zolnierkiewicz 	.set_lpm		= piix_sidpr_set_lpm,
1109f295be25SBartlomiej Zolnierkiewicz };
1110f295be25SBartlomiej Zolnierkiewicz 
1111f295be25SBartlomiej Zolnierkiewicz static struct ata_port_info piix_port_info[] = {
1112f295be25SBartlomiej Zolnierkiewicz 	[piix_pata_mwdma] =	/* PIIX3 MWDMA only */
1113f295be25SBartlomiej Zolnierkiewicz 	{
1114f295be25SBartlomiej Zolnierkiewicz 		.flags		= PIIX_PATA_FLAGS,
1115f295be25SBartlomiej Zolnierkiewicz 		.pio_mask	= ATA_PIO4,
1116f295be25SBartlomiej Zolnierkiewicz 		.mwdma_mask	= ATA_MWDMA12_ONLY, /* mwdma1-2 ?? CHECK 0 should be ok but slow */
1117f295be25SBartlomiej Zolnierkiewicz 		.port_ops	= &piix_pata_ops,
1118f295be25SBartlomiej Zolnierkiewicz 	},
1119f295be25SBartlomiej Zolnierkiewicz 
1120f295be25SBartlomiej Zolnierkiewicz 	[piix_pata_33] =	/* PIIX4 at 33MHz */
1121f295be25SBartlomiej Zolnierkiewicz 	{
1122f295be25SBartlomiej Zolnierkiewicz 		.flags		= PIIX_PATA_FLAGS,
1123f295be25SBartlomiej Zolnierkiewicz 		.pio_mask	= ATA_PIO4,
1124f295be25SBartlomiej Zolnierkiewicz 		.mwdma_mask	= ATA_MWDMA12_ONLY, /* mwdma1-2 ?? CHECK 0 should be ok but slow */
1125f295be25SBartlomiej Zolnierkiewicz 		.udma_mask	= ATA_UDMA2,
1126f295be25SBartlomiej Zolnierkiewicz 		.port_ops	= &piix_pata_ops,
1127f295be25SBartlomiej Zolnierkiewicz 	},
1128f295be25SBartlomiej Zolnierkiewicz 
1129f295be25SBartlomiej Zolnierkiewicz 	[ich_pata_33] =		/* ICH0 - ICH at 33Mhz*/
1130f295be25SBartlomiej Zolnierkiewicz 	{
1131f295be25SBartlomiej Zolnierkiewicz 		.flags		= PIIX_PATA_FLAGS,
1132f295be25SBartlomiej Zolnierkiewicz 		.pio_mask	= ATA_PIO4,
1133f295be25SBartlomiej Zolnierkiewicz 		.mwdma_mask	= ATA_MWDMA12_ONLY, /* Check: maybe MWDMA0 is ok  */
1134f295be25SBartlomiej Zolnierkiewicz 		.udma_mask	= ATA_UDMA2,
1135f295be25SBartlomiej Zolnierkiewicz 		.port_ops	= &ich_pata_ops,
1136f295be25SBartlomiej Zolnierkiewicz 	},
1137f295be25SBartlomiej Zolnierkiewicz 
1138f295be25SBartlomiej Zolnierkiewicz 	[ich_pata_66] =		/* ICH controllers up to 66MHz */
1139f295be25SBartlomiej Zolnierkiewicz 	{
1140f295be25SBartlomiej Zolnierkiewicz 		.flags		= PIIX_PATA_FLAGS,
1141f295be25SBartlomiej Zolnierkiewicz 		.pio_mask	= ATA_PIO4,
1142f295be25SBartlomiej Zolnierkiewicz 		.mwdma_mask	= ATA_MWDMA12_ONLY, /* MWDMA0 is broken on chip */
1143f295be25SBartlomiej Zolnierkiewicz 		.udma_mask	= ATA_UDMA4,
1144f295be25SBartlomiej Zolnierkiewicz 		.port_ops	= &ich_pata_ops,
1145f295be25SBartlomiej Zolnierkiewicz 	},
1146f295be25SBartlomiej Zolnierkiewicz 
1147f295be25SBartlomiej Zolnierkiewicz 	[ich_pata_100] =
1148f295be25SBartlomiej Zolnierkiewicz 	{
1149f295be25SBartlomiej Zolnierkiewicz 		.flags		= PIIX_PATA_FLAGS | PIIX_FLAG_CHECKINTR,
1150f295be25SBartlomiej Zolnierkiewicz 		.pio_mask	= ATA_PIO4,
1151f295be25SBartlomiej Zolnierkiewicz 		.mwdma_mask	= ATA_MWDMA12_ONLY,
1152f295be25SBartlomiej Zolnierkiewicz 		.udma_mask	= ATA_UDMA5,
1153f295be25SBartlomiej Zolnierkiewicz 		.port_ops	= &ich_pata_ops,
1154f295be25SBartlomiej Zolnierkiewicz 	},
1155f295be25SBartlomiej Zolnierkiewicz 
1156f295be25SBartlomiej Zolnierkiewicz 	[ich_pata_100_nomwdma1] =
1157f295be25SBartlomiej Zolnierkiewicz 	{
1158f295be25SBartlomiej Zolnierkiewicz 		.flags		= PIIX_PATA_FLAGS | PIIX_FLAG_CHECKINTR,
1159f295be25SBartlomiej Zolnierkiewicz 		.pio_mask	= ATA_PIO4,
1160f295be25SBartlomiej Zolnierkiewicz 		.mwdma_mask	= ATA_MWDMA2_ONLY,
1161f295be25SBartlomiej Zolnierkiewicz 		.udma_mask	= ATA_UDMA5,
1162f295be25SBartlomiej Zolnierkiewicz 		.port_ops	= &ich_pata_ops,
1163f295be25SBartlomiej Zolnierkiewicz 	},
1164f295be25SBartlomiej Zolnierkiewicz 
1165f295be25SBartlomiej Zolnierkiewicz 	[ich5_sata] =
1166f295be25SBartlomiej Zolnierkiewicz 	{
1167f295be25SBartlomiej Zolnierkiewicz 		.flags		= PIIX_SATA_FLAGS,
1168f295be25SBartlomiej Zolnierkiewicz 		.pio_mask	= ATA_PIO4,
1169f295be25SBartlomiej Zolnierkiewicz 		.mwdma_mask	= ATA_MWDMA2,
1170f295be25SBartlomiej Zolnierkiewicz 		.udma_mask	= ATA_UDMA6,
1171f295be25SBartlomiej Zolnierkiewicz 		.port_ops	= &piix_sata_ops,
1172f295be25SBartlomiej Zolnierkiewicz 	},
1173f295be25SBartlomiej Zolnierkiewicz 
1174f295be25SBartlomiej Zolnierkiewicz 	[ich6_sata] =
1175f295be25SBartlomiej Zolnierkiewicz 	{
1176f295be25SBartlomiej Zolnierkiewicz 		.flags		= PIIX_SATA_FLAGS,
1177f295be25SBartlomiej Zolnierkiewicz 		.pio_mask	= ATA_PIO4,
1178f295be25SBartlomiej Zolnierkiewicz 		.mwdma_mask	= ATA_MWDMA2,
1179f295be25SBartlomiej Zolnierkiewicz 		.udma_mask	= ATA_UDMA6,
1180f295be25SBartlomiej Zolnierkiewicz 		.port_ops	= &piix_sata_ops,
1181f295be25SBartlomiej Zolnierkiewicz 	},
1182f295be25SBartlomiej Zolnierkiewicz 
1183f295be25SBartlomiej Zolnierkiewicz 	[ich6m_sata] =
1184f295be25SBartlomiej Zolnierkiewicz 	{
1185f295be25SBartlomiej Zolnierkiewicz 		.flags		= PIIX_SATA_FLAGS,
1186f295be25SBartlomiej Zolnierkiewicz 		.pio_mask	= ATA_PIO4,
1187f295be25SBartlomiej Zolnierkiewicz 		.mwdma_mask	= ATA_MWDMA2,
1188f295be25SBartlomiej Zolnierkiewicz 		.udma_mask	= ATA_UDMA6,
1189f295be25SBartlomiej Zolnierkiewicz 		.port_ops	= &piix_sata_ops,
1190f295be25SBartlomiej Zolnierkiewicz 	},
1191f295be25SBartlomiej Zolnierkiewicz 
1192f295be25SBartlomiej Zolnierkiewicz 	[ich8_sata] =
1193f295be25SBartlomiej Zolnierkiewicz 	{
1194f295be25SBartlomiej Zolnierkiewicz 		.flags		= PIIX_SATA_FLAGS | PIIX_FLAG_SIDPR,
1195f295be25SBartlomiej Zolnierkiewicz 		.pio_mask	= ATA_PIO4,
1196f295be25SBartlomiej Zolnierkiewicz 		.mwdma_mask	= ATA_MWDMA2,
1197f295be25SBartlomiej Zolnierkiewicz 		.udma_mask	= ATA_UDMA6,
1198f295be25SBartlomiej Zolnierkiewicz 		.port_ops	= &piix_sata_ops,
1199f295be25SBartlomiej Zolnierkiewicz 	},
1200f295be25SBartlomiej Zolnierkiewicz 
1201f295be25SBartlomiej Zolnierkiewicz 	[ich8_2port_sata] =
1202f295be25SBartlomiej Zolnierkiewicz 	{
1203f295be25SBartlomiej Zolnierkiewicz 		.flags		= PIIX_SATA_FLAGS | PIIX_FLAG_SIDPR,
1204f295be25SBartlomiej Zolnierkiewicz 		.pio_mask	= ATA_PIO4,
1205f295be25SBartlomiej Zolnierkiewicz 		.mwdma_mask	= ATA_MWDMA2,
1206f295be25SBartlomiej Zolnierkiewicz 		.udma_mask	= ATA_UDMA6,
1207f295be25SBartlomiej Zolnierkiewicz 		.port_ops	= &piix_sata_ops,
1208f295be25SBartlomiej Zolnierkiewicz 	},
1209f295be25SBartlomiej Zolnierkiewicz 
1210f295be25SBartlomiej Zolnierkiewicz 	[tolapai_sata] =
1211f295be25SBartlomiej Zolnierkiewicz 	{
1212f295be25SBartlomiej Zolnierkiewicz 		.flags		= PIIX_SATA_FLAGS,
1213f295be25SBartlomiej Zolnierkiewicz 		.pio_mask	= ATA_PIO4,
1214f295be25SBartlomiej Zolnierkiewicz 		.mwdma_mask	= ATA_MWDMA2,
1215f295be25SBartlomiej Zolnierkiewicz 		.udma_mask	= ATA_UDMA6,
1216f295be25SBartlomiej Zolnierkiewicz 		.port_ops	= &piix_sata_ops,
1217f295be25SBartlomiej Zolnierkiewicz 	},
1218f295be25SBartlomiej Zolnierkiewicz 
1219f295be25SBartlomiej Zolnierkiewicz 	[ich8m_apple_sata] =
1220f295be25SBartlomiej Zolnierkiewicz 	{
1221f295be25SBartlomiej Zolnierkiewicz 		.flags		= PIIX_SATA_FLAGS,
1222f295be25SBartlomiej Zolnierkiewicz 		.pio_mask	= ATA_PIO4,
1223f295be25SBartlomiej Zolnierkiewicz 		.mwdma_mask	= ATA_MWDMA2,
1224f295be25SBartlomiej Zolnierkiewicz 		.udma_mask	= ATA_UDMA6,
1225f295be25SBartlomiej Zolnierkiewicz 		.port_ops	= &piix_sata_ops,
1226f295be25SBartlomiej Zolnierkiewicz 	},
1227f295be25SBartlomiej Zolnierkiewicz 
1228f295be25SBartlomiej Zolnierkiewicz 	[piix_pata_vmw] =
1229f295be25SBartlomiej Zolnierkiewicz 	{
1230f295be25SBartlomiej Zolnierkiewicz 		.flags		= PIIX_PATA_FLAGS,
1231f295be25SBartlomiej Zolnierkiewicz 		.pio_mask	= ATA_PIO4,
1232f295be25SBartlomiej Zolnierkiewicz 		.mwdma_mask	= ATA_MWDMA12_ONLY, /* mwdma1-2 ?? CHECK 0 should be ok but slow */
1233f295be25SBartlomiej Zolnierkiewicz 		.udma_mask	= ATA_UDMA2,
1234f295be25SBartlomiej Zolnierkiewicz 		.port_ops	= &piix_vmw_ops,
1235f295be25SBartlomiej Zolnierkiewicz 	},
1236f295be25SBartlomiej Zolnierkiewicz 
1237f295be25SBartlomiej Zolnierkiewicz 	/*
1238f295be25SBartlomiej Zolnierkiewicz 	 * some Sandybridge chipsets have broken 32 mode up to now,
1239f295be25SBartlomiej Zolnierkiewicz 	 * see https://bugzilla.kernel.org/show_bug.cgi?id=40592
1240f295be25SBartlomiej Zolnierkiewicz 	 */
1241f295be25SBartlomiej Zolnierkiewicz 	[ich8_sata_snb] =
1242f295be25SBartlomiej Zolnierkiewicz 	{
1243f295be25SBartlomiej Zolnierkiewicz 		.flags		= PIIX_SATA_FLAGS | PIIX_FLAG_SIDPR | PIIX_FLAG_PIO16,
1244f295be25SBartlomiej Zolnierkiewicz 		.pio_mask	= ATA_PIO4,
1245f295be25SBartlomiej Zolnierkiewicz 		.mwdma_mask	= ATA_MWDMA2,
1246f295be25SBartlomiej Zolnierkiewicz 		.udma_mask	= ATA_UDMA6,
1247f295be25SBartlomiej Zolnierkiewicz 		.port_ops	= &piix_sata_ops,
1248f295be25SBartlomiej Zolnierkiewicz 	},
1249b55f84e2SYouquan Song 
1250b55f84e2SYouquan Song 	[ich8_2port_sata_snb] =
1251b55f84e2SYouquan Song 	{
1252b55f84e2SYouquan Song 		.flags		= PIIX_SATA_FLAGS | PIIX_FLAG_SIDPR
1253b55f84e2SYouquan Song 					| PIIX_FLAG_PIO16,
1254b55f84e2SYouquan Song 		.pio_mask	= ATA_PIO4,
1255b55f84e2SYouquan Song 		.mwdma_mask	= ATA_MWDMA2,
1256b55f84e2SYouquan Song 		.udma_mask	= ATA_UDMA6,
1257b55f84e2SYouquan Song 		.port_ops	= &piix_sata_ops,
1258b55f84e2SYouquan Song 	},
1259fca8c90dSChew, Chiau Ee 
1260fca8c90dSChew, Chiau Ee 	[ich8_2port_sata_byt] =
1261fca8c90dSChew, Chiau Ee 	{
1262fca8c90dSChew, Chiau Ee 		.flags          = PIIX_SATA_FLAGS | PIIX_FLAG_SIDPR | PIIX_FLAG_PIO16,
1263fca8c90dSChew, Chiau Ee 		.pio_mask       = ATA_PIO4,
1264fca8c90dSChew, Chiau Ee 		.mwdma_mask     = ATA_MWDMA2,
1265fca8c90dSChew, Chiau Ee 		.udma_mask      = ATA_UDMA6,
1266fca8c90dSChew, Chiau Ee 		.port_ops       = &piix_sata_ops,
1267fca8c90dSChew, Chiau Ee 	},
1268fca8c90dSChew, Chiau Ee 
1269f295be25SBartlomiej Zolnierkiewicz };
1270f295be25SBartlomiej Zolnierkiewicz 
1271c6fd2807SJeff Garzik #define AHCI_PCI_BAR 5
1272c6fd2807SJeff Garzik #define AHCI_GLOBAL_CTL 0x04
1273c6fd2807SJeff Garzik #define AHCI_ENABLE (1 << 31)
piix_disable_ahci(struct pci_dev * pdev)1274c6fd2807SJeff Garzik static int piix_disable_ahci(struct pci_dev *pdev)
1275c6fd2807SJeff Garzik {
1276c6fd2807SJeff Garzik 	void __iomem *mmio;
1277c6fd2807SJeff Garzik 	u32 tmp;
1278c6fd2807SJeff Garzik 	int rc = 0;
1279c6fd2807SJeff Garzik 
1280c6fd2807SJeff Garzik 	/* BUG: pci_enable_device has not yet been called.  This
1281c6fd2807SJeff Garzik 	 * works because this device is usually set up by BIOS.
1282c6fd2807SJeff Garzik 	 */
1283c6fd2807SJeff Garzik 
1284c6fd2807SJeff Garzik 	if (!pci_resource_start(pdev, AHCI_PCI_BAR) ||
1285c6fd2807SJeff Garzik 	    !pci_resource_len(pdev, AHCI_PCI_BAR))
1286c6fd2807SJeff Garzik 		return 0;
1287c6fd2807SJeff Garzik 
1288c6fd2807SJeff Garzik 	mmio = pci_iomap(pdev, AHCI_PCI_BAR, 64);
1289c6fd2807SJeff Garzik 	if (!mmio)
1290c6fd2807SJeff Garzik 		return -ENOMEM;
1291c6fd2807SJeff Garzik 
1292c47a631fSAlan Cox 	tmp = ioread32(mmio + AHCI_GLOBAL_CTL);
1293c6fd2807SJeff Garzik 	if (tmp & AHCI_ENABLE) {
1294c6fd2807SJeff Garzik 		tmp &= ~AHCI_ENABLE;
1295c47a631fSAlan Cox 		iowrite32(tmp, mmio + AHCI_GLOBAL_CTL);
1296c6fd2807SJeff Garzik 
1297c47a631fSAlan Cox 		tmp = ioread32(mmio + AHCI_GLOBAL_CTL);
1298c6fd2807SJeff Garzik 		if (tmp & AHCI_ENABLE)
1299c6fd2807SJeff Garzik 			rc = -EIO;
1300c6fd2807SJeff Garzik 	}
1301c6fd2807SJeff Garzik 
1302c6fd2807SJeff Garzik 	pci_iounmap(pdev, mmio);
1303c6fd2807SJeff Garzik 	return rc;
1304c6fd2807SJeff Garzik }
1305c6fd2807SJeff Garzik 
1306c6fd2807SJeff Garzik /**
1307c6fd2807SJeff Garzik  *	piix_check_450nx_errata	-	Check for problem 450NX setup
1308c6fd2807SJeff Garzik  *	@ata_dev: the PCI device to check
1309c6fd2807SJeff Garzik  *
1310c6fd2807SJeff Garzik  *	Check for the present of 450NX errata #19 and errata #25. If
1311c6fd2807SJeff Garzik  *	they are found return an error code so we can turn off DMA
1312c6fd2807SJeff Garzik  */
1313c6fd2807SJeff Garzik 
piix_check_450nx_errata(struct pci_dev * ata_dev)13140ec24914SGreg Kroah-Hartman static int piix_check_450nx_errata(struct pci_dev *ata_dev)
1315c6fd2807SJeff Garzik {
1316c6fd2807SJeff Garzik 	struct pci_dev *pdev = NULL;
1317c6fd2807SJeff Garzik 	u16 cfg;
1318c6fd2807SJeff Garzik 	int no_piix_dma = 0;
1319c6fd2807SJeff Garzik 
13202dcb407eSJeff Garzik 	while ((pdev = pci_get_device(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_82454NX, pdev)) != NULL) {
1321c6fd2807SJeff Garzik 		/* Look for 450NX PXB. Check for problem configurations
1322c6fd2807SJeff Garzik 		   A PCI quirk checks bit 6 already */
1323c6fd2807SJeff Garzik 		pci_read_config_word(pdev, 0x41, &cfg);
1324c6fd2807SJeff Garzik 		/* Only on the original revision: IDE DMA can hang */
132544c10138SAuke Kok 		if (pdev->revision == 0x00)
1326c6fd2807SJeff Garzik 			no_piix_dma = 1;
1327c6fd2807SJeff Garzik 		/* On all revisions below 5 PXB bus lock must be disabled for IDE */
132844c10138SAuke Kok 		else if (cfg & (1<<14) && pdev->revision < 5)
1329c6fd2807SJeff Garzik 			no_piix_dma = 2;
1330c6fd2807SJeff Garzik 	}
1331c6fd2807SJeff Garzik 	if (no_piix_dma)
1332a44fec1fSJoe Perches 		dev_warn(&ata_dev->dev,
1333a44fec1fSJoe Perches 			 "450NX errata present, disabling IDE DMA%s\n",
1334a44fec1fSJoe Perches 			 no_piix_dma == 2 ? " - a BIOS update may resolve this"
1335a44fec1fSJoe Perches 			 : "");
1336a44fec1fSJoe Perches 
1337c6fd2807SJeff Garzik 	return no_piix_dma;
1338c6fd2807SJeff Garzik }
1339c6fd2807SJeff Garzik 
piix_init_pcs(struct ata_host * host,const struct piix_map_db * map_db)13400ec24914SGreg Kroah-Hartman static void piix_init_pcs(struct ata_host *host,
1341c6fd2807SJeff Garzik 			  const struct piix_map_db *map_db)
1342c6fd2807SJeff Garzik {
13438b09f0daSTejun Heo 	struct pci_dev *pdev = to_pci_dev(host->dev);
1344c6fd2807SJeff Garzik 	u16 pcs, new_pcs;
1345c6fd2807SJeff Garzik 
1346c6fd2807SJeff Garzik 	pci_read_config_word(pdev, ICH5_PCS, &pcs);
1347c6fd2807SJeff Garzik 
1348c6fd2807SJeff Garzik 	new_pcs = pcs | map_db->port_enable;
1349c6fd2807SJeff Garzik 
1350c6fd2807SJeff Garzik 	if (new_pcs != pcs) {
1351c6fd2807SJeff Garzik 		pci_write_config_word(pdev, ICH5_PCS, new_pcs);
1352c6fd2807SJeff Garzik 		msleep(150);
1353c6fd2807SJeff Garzik 	}
1354c6fd2807SJeff Garzik }
1355c6fd2807SJeff Garzik 
piix_init_sata_map(struct pci_dev * pdev,struct ata_port_info * pinfo,const struct piix_map_db * map_db)13560ec24914SGreg Kroah-Hartman static const int *piix_init_sata_map(struct pci_dev *pdev,
1357c6fd2807SJeff Garzik 				     struct ata_port_info *pinfo,
1358c6fd2807SJeff Garzik 				     const struct piix_map_db *map_db)
1359c6fd2807SJeff Garzik {
1360b4482a4bSAl Viro 	const int *map;
1361c6fd2807SJeff Garzik 	int i, invalid_map = 0;
1362c6fd2807SJeff Garzik 	u8 map_value;
136389951f22SLevente Kurusa 	char buf[32];
136489951f22SLevente Kurusa 	char *p = buf, *end = buf + sizeof(buf);
1365c6fd2807SJeff Garzik 
1366c6fd2807SJeff Garzik 	pci_read_config_byte(pdev, ICH5_PMR, &map_value);
1367c6fd2807SJeff Garzik 
1368c6fd2807SJeff Garzik 	map = map_db->map[map_value & map_db->mask];
1369c6fd2807SJeff Garzik 
1370c6fd2807SJeff Garzik 	for (i = 0; i < 4; i++) {
1371c6fd2807SJeff Garzik 		switch (map[i]) {
1372c6fd2807SJeff Garzik 		case RV:
1373c6fd2807SJeff Garzik 			invalid_map = 1;
137489951f22SLevente Kurusa 			p += scnprintf(p, end - p, " XX");
1375c6fd2807SJeff Garzik 			break;
1376c6fd2807SJeff Garzik 
1377c6fd2807SJeff Garzik 		case NA:
137889951f22SLevente Kurusa 			p += scnprintf(p, end - p, " --");
1379c6fd2807SJeff Garzik 			break;
1380c6fd2807SJeff Garzik 
1381c6fd2807SJeff Garzik 		case IDE:
1382c6fd2807SJeff Garzik 			WARN_ON((i & 1) || map[i + 1] != IDE);
1383669a5db4SJeff Garzik 			pinfo[i / 2] = piix_port_info[ich_pata_100];
1384c6fd2807SJeff Garzik 			i++;
138589951f22SLevente Kurusa 			p += scnprintf(p, end - p, " IDE IDE");
1386c6fd2807SJeff Garzik 			break;
1387c6fd2807SJeff Garzik 
1388c6fd2807SJeff Garzik 		default:
138989951f22SLevente Kurusa 			p += scnprintf(p, end - p, " P%d", map[i]);
1390c6fd2807SJeff Garzik 			if (i & 1)
1391cca3974eSJeff Garzik 				pinfo[i / 2].flags |= ATA_FLAG_SLAVE_POSS;
1392c6fd2807SJeff Garzik 			break;
1393c6fd2807SJeff Garzik 		}
1394c6fd2807SJeff Garzik 	}
139589951f22SLevente Kurusa 	dev_info(&pdev->dev, "MAP [%s ]\n", buf);
1396c6fd2807SJeff Garzik 
1397c6fd2807SJeff Garzik 	if (invalid_map)
1398a44fec1fSJoe Perches 		dev_err(&pdev->dev, "invalid MAP value %u\n", map_value);
1399c6fd2807SJeff Garzik 
14008b09f0daSTejun Heo 	return map;
1401c6fd2807SJeff Garzik }
1402c6fd2807SJeff Garzik 
piix_no_sidpr(struct ata_host * host)1403e9c1670cSTejun Heo static bool piix_no_sidpr(struct ata_host *host)
1404e9c1670cSTejun Heo {
1405e9c1670cSTejun Heo 	struct pci_dev *pdev = to_pci_dev(host->dev);
1406e9c1670cSTejun Heo 
1407e9c1670cSTejun Heo 	/*
1408e9c1670cSTejun Heo 	 * Samsung DB-P70 only has three ATA ports exposed and
1409e9c1670cSTejun Heo 	 * curiously the unconnected first port reports link online
1410e9c1670cSTejun Heo 	 * while not responding to SRST protocol causing excessive
1411e9c1670cSTejun Heo 	 * detection delay.
1412e9c1670cSTejun Heo 	 *
1413e9c1670cSTejun Heo 	 * Unfortunately, the system doesn't carry enough DMI
1414e9c1670cSTejun Heo 	 * information to identify the machine but does have subsystem
1415e9c1670cSTejun Heo 	 * vendor and device set.  As it's unclear whether the
1416e9c1670cSTejun Heo 	 * subsystem vendor/device is used only for this specific
1417e9c1670cSTejun Heo 	 * board, the port can't be disabled solely with the
1418e9c1670cSTejun Heo 	 * information; however, turning off SIDPR access works around
1419e9c1670cSTejun Heo 	 * the problem.  Turn it off.
1420e9c1670cSTejun Heo 	 *
1421e9c1670cSTejun Heo 	 * This problem is reported in bnc#441240.
1422e9c1670cSTejun Heo 	 *
1423e9c1670cSTejun Heo 	 * https://bugzilla.novell.com/show_bug.cgi?id=441420
1424e9c1670cSTejun Heo 	 */
1425e9c1670cSTejun Heo 	if (pdev->vendor == PCI_VENDOR_ID_INTEL && pdev->device == 0x2920 &&
1426e9c1670cSTejun Heo 	    pdev->subsystem_vendor == PCI_VENDOR_ID_SAMSUNG &&
1427e9c1670cSTejun Heo 	    pdev->subsystem_device == 0xb049) {
1428a44fec1fSJoe Perches 		dev_warn(host->dev,
1429e9c1670cSTejun Heo 			 "Samsung DB-P70 detected, disabling SIDPR\n");
1430e9c1670cSTejun Heo 		return true;
1431e9c1670cSTejun Heo 	}
1432e9c1670cSTejun Heo 
1433e9c1670cSTejun Heo 	return false;
1434e9c1670cSTejun Heo }
1435e9c1670cSTejun Heo 
piix_init_sidpr(struct ata_host * host)14360ec24914SGreg Kroah-Hartman static int piix_init_sidpr(struct ata_host *host)
1437c7290724STejun Heo {
1438c7290724STejun Heo 	struct pci_dev *pdev = to_pci_dev(host->dev);
1439c7290724STejun Heo 	struct piix_host_priv *hpriv = host->private_data;
1440be77e43aSTejun Heo 	struct ata_link *link0 = &host->ports[0]->link;
1441cb6716c8STejun Heo 	u32 scontrol;
1442be77e43aSTejun Heo 	int i, rc;
1443c7290724STejun Heo 
1444c7290724STejun Heo 	/* check for availability */
1445c7290724STejun Heo 	for (i = 0; i < 4; i++)
1446c7290724STejun Heo 		if (hpriv->map[i] == IDE)
1447be77e43aSTejun Heo 			return 0;
1448c7290724STejun Heo 
1449e9c1670cSTejun Heo 	/* is it blacklisted? */
1450e9c1670cSTejun Heo 	if (piix_no_sidpr(host))
1451e9c1670cSTejun Heo 		return 0;
1452e9c1670cSTejun Heo 
1453c7290724STejun Heo 	if (!(host->ports[0]->flags & PIIX_FLAG_SIDPR))
1454be77e43aSTejun Heo 		return 0;
1455c7290724STejun Heo 
1456c7290724STejun Heo 	if (pci_resource_start(pdev, PIIX_SIDPR_BAR) == 0 ||
1457c7290724STejun Heo 	    pci_resource_len(pdev, PIIX_SIDPR_BAR) != PIIX_SIDPR_LEN)
1458be77e43aSTejun Heo 		return 0;
1459c7290724STejun Heo 
1460c7290724STejun Heo 	if (pcim_iomap_regions(pdev, 1 << PIIX_SIDPR_BAR, DRV_NAME))
1461be77e43aSTejun Heo 		return 0;
1462c7290724STejun Heo 
1463c7290724STejun Heo 	hpriv->sidpr = pcim_iomap_table(pdev)[PIIX_SIDPR_BAR];
1464cb6716c8STejun Heo 
1465cb6716c8STejun Heo 	/* SCR access via SIDPR doesn't work on some configurations.
1466cb6716c8STejun Heo 	 * Give it a test drive by inhibiting power save modes which
1467cb6716c8STejun Heo 	 * we'll do anyway.
1468cb6716c8STejun Heo 	 */
1469be77e43aSTejun Heo 	piix_sidpr_scr_read(link0, SCR_CONTROL, &scontrol);
1470cb6716c8STejun Heo 
1471cb6716c8STejun Heo 	/* if IPM is already 3, SCR access is probably working.  Don't
1472cb6716c8STejun Heo 	 * un-inhibit power save modes as BIOS might have inhibited
1473cb6716c8STejun Heo 	 * them for a reason.
1474cb6716c8STejun Heo 	 */
1475cb6716c8STejun Heo 	if ((scontrol & 0xf00) != 0x300) {
1476cb6716c8STejun Heo 		scontrol |= 0x300;
1477be77e43aSTejun Heo 		piix_sidpr_scr_write(link0, SCR_CONTROL, scontrol);
1478be77e43aSTejun Heo 		piix_sidpr_scr_read(link0, SCR_CONTROL, &scontrol);
1479cb6716c8STejun Heo 
1480cb6716c8STejun Heo 		if ((scontrol & 0xf00) != 0x300) {
1481a44fec1fSJoe Perches 			dev_info(host->dev,
1482a44fec1fSJoe Perches 				 "SCR access via SIDPR is available but doesn't work\n");
1483be77e43aSTejun Heo 			return 0;
1484cb6716c8STejun Heo 		}
1485cb6716c8STejun Heo 	}
1486cb6716c8STejun Heo 
1487be77e43aSTejun Heo 	/* okay, SCRs available, set ops and ask libata for slave_link */
1488be77e43aSTejun Heo 	for (i = 0; i < 2; i++) {
1489be77e43aSTejun Heo 		struct ata_port *ap = host->ports[i];
1490be77e43aSTejun Heo 
1491be77e43aSTejun Heo 		ap->ops = &piix_sidpr_sata_ops;
1492be77e43aSTejun Heo 
1493be77e43aSTejun Heo 		if (ap->flags & ATA_FLAG_SLAVE_POSS) {
1494be77e43aSTejun Heo 			rc = ata_slave_link_init(ap);
1495be77e43aSTejun Heo 			if (rc)
1496be77e43aSTejun Heo 				return rc;
1497be77e43aSTejun Heo 		}
1498be77e43aSTejun Heo 	}
1499be77e43aSTejun Heo 
1500be77e43aSTejun Heo 	return 0;
1501c7290724STejun Heo }
1502c7290724STejun Heo 
piix_iocfg_bit18_quirk(struct ata_host * host)15032852bcf7STejun Heo static void piix_iocfg_bit18_quirk(struct ata_host *host)
150443a98f05STejun Heo {
15051855256cSJeff Garzik 	static const struct dmi_system_id sysids[] = {
150643a98f05STejun Heo 		{
150743a98f05STejun Heo 			/* Clevo M570U sets IOCFG bit 18 if the cdrom
150843a98f05STejun Heo 			 * isn't used to boot the system which
150943a98f05STejun Heo 			 * disables the channel.
151043a98f05STejun Heo 			 */
151143a98f05STejun Heo 			.ident = "M570U",
151243a98f05STejun Heo 			.matches = {
151343a98f05STejun Heo 				DMI_MATCH(DMI_SYS_VENDOR, "Clevo Co."),
151443a98f05STejun Heo 				DMI_MATCH(DMI_PRODUCT_NAME, "M570U"),
151543a98f05STejun Heo 			},
151643a98f05STejun Heo 		},
15177d051548SJeff Garzik 
15187d051548SJeff Garzik 		{ }	/* terminate list */
151943a98f05STejun Heo 	};
15202852bcf7STejun Heo 	struct pci_dev *pdev = to_pci_dev(host->dev);
15212852bcf7STejun Heo 	struct piix_host_priv *hpriv = host->private_data;
152243a98f05STejun Heo 
152343a98f05STejun Heo 	if (!dmi_check_system(sysids))
152443a98f05STejun Heo 		return;
152543a98f05STejun Heo 
152643a98f05STejun Heo 	/* The datasheet says that bit 18 is NOOP but certain systems
152743a98f05STejun Heo 	 * seem to use it to disable a channel.  Clear the bit on the
152843a98f05STejun Heo 	 * affected systems.
152943a98f05STejun Heo 	 */
15302852bcf7STejun Heo 	if (hpriv->saved_iocfg & (1 << 18)) {
1531a44fec1fSJoe Perches 		dev_info(&pdev->dev, "applying IOCFG bit18 quirk\n");
15322852bcf7STejun Heo 		pci_write_config_dword(pdev, PIIX_IOCFG,
15332852bcf7STejun Heo 				       hpriv->saved_iocfg & ~(1 << 18));
153443a98f05STejun Heo 	}
153543a98f05STejun Heo }
153643a98f05STejun Heo 
piix_broken_system_poweroff(struct pci_dev * pdev)15375f451fe1SRafael J. Wysocki static bool piix_broken_system_poweroff(struct pci_dev *pdev)
15385f451fe1SRafael J. Wysocki {
15395f451fe1SRafael J. Wysocki 	static const struct dmi_system_id broken_systems[] = {
15405f451fe1SRafael J. Wysocki 		{
15415f451fe1SRafael J. Wysocki 			.ident = "HP Compaq 2510p",
15425f451fe1SRafael J. Wysocki 			.matches = {
15435f451fe1SRafael J. Wysocki 				DMI_MATCH(DMI_SYS_VENDOR, "Hewlett-Packard"),
15445f451fe1SRafael J. Wysocki 				DMI_MATCH(DMI_PRODUCT_NAME, "HP Compaq 2510p"),
15455f451fe1SRafael J. Wysocki 			},
15465f451fe1SRafael J. Wysocki 			/* PCI slot number of the controller */
15475f451fe1SRafael J. Wysocki 			.driver_data = (void *)0x1FUL,
15485f451fe1SRafael J. Wysocki 		},
154965e31643SVille Syrjala 		{
155065e31643SVille Syrjala 			.ident = "HP Compaq nc6000",
155165e31643SVille Syrjala 			.matches = {
155265e31643SVille Syrjala 				DMI_MATCH(DMI_SYS_VENDOR, "Hewlett-Packard"),
155365e31643SVille Syrjala 				DMI_MATCH(DMI_PRODUCT_NAME, "HP Compaq nc6000"),
155465e31643SVille Syrjala 			},
155565e31643SVille Syrjala 			/* PCI slot number of the controller */
155665e31643SVille Syrjala 			.driver_data = (void *)0x1FUL,
155765e31643SVille Syrjala 		},
15585f451fe1SRafael J. Wysocki 
15595f451fe1SRafael J. Wysocki 		{ }	/* terminate list */
15605f451fe1SRafael J. Wysocki 	};
15615f451fe1SRafael J. Wysocki 	const struct dmi_system_id *dmi = dmi_first_match(broken_systems);
15625f451fe1SRafael J. Wysocki 
15635f451fe1SRafael J. Wysocki 	if (dmi) {
15645f451fe1SRafael J. Wysocki 		unsigned long slot = (unsigned long)dmi->driver_data;
15655f451fe1SRafael J. Wysocki 		/* apply the quirk only to on-board controllers */
15665f451fe1SRafael J. Wysocki 		return slot == PCI_SLOT(pdev->devfn);
15675f451fe1SRafael J. Wysocki 	}
15685f451fe1SRafael J. Wysocki 
15695f451fe1SRafael J. Wysocki 	return false;
15705f451fe1SRafael J. Wysocki }
15715f451fe1SRafael J. Wysocki 
1572cd006086SAndy Whitcroft static int prefer_ms_hyperv = 1;
1573cd006086SAndy Whitcroft module_param(prefer_ms_hyperv, int, 0);
157479e7654cSAndrew Brownfield MODULE_PARM_DESC(prefer_ms_hyperv,
157579e7654cSAndrew Brownfield 	"Prefer Hyper-V paravirtualization drivers instead of ATA, "
157679e7654cSAndrew Brownfield 	"0 - Use ATA drivers, "
157779e7654cSAndrew Brownfield 	"1 (Default) - Use the paravirtualization drivers.");
1578cd006086SAndy Whitcroft 
piix_ignore_devices_quirk(struct ata_host * host)1579cd006086SAndy Whitcroft static void piix_ignore_devices_quirk(struct ata_host *host)
1580cd006086SAndy Whitcroft {
1581cd006086SAndy Whitcroft #if IS_ENABLED(CONFIG_HYPERV_STORAGE)
1582cd006086SAndy Whitcroft 	static const struct dmi_system_id ignore_hyperv[] = {
1583cd006086SAndy Whitcroft 		{
1584cd006086SAndy Whitcroft 			/* On Hyper-V hypervisors the disks are exposed on
1585cd006086SAndy Whitcroft 			 * both the emulated SATA controller and on the
1586cd006086SAndy Whitcroft 			 * paravirtualised drivers.  The CD/DVD devices
1587cd006086SAndy Whitcroft 			 * are only exposed on the emulated controller.
1588cd006086SAndy Whitcroft 			 * Request we ignore ATA devices on this host.
1589cd006086SAndy Whitcroft 			 */
1590cd006086SAndy Whitcroft 			.ident = "Hyper-V Virtual Machine",
1591cd006086SAndy Whitcroft 			.matches = {
1592cd006086SAndy Whitcroft 				DMI_MATCH(DMI_SYS_VENDOR,
1593cd006086SAndy Whitcroft 						"Microsoft Corporation"),
1594cd006086SAndy Whitcroft 				DMI_MATCH(DMI_PRODUCT_NAME, "Virtual Machine"),
1595cd006086SAndy Whitcroft 			},
1596cd006086SAndy Whitcroft 		},
1597cd006086SAndy Whitcroft 		{ }	/* terminate list */
1598cd006086SAndy Whitcroft 	};
1599d9904344SOlaf Hering 	static const struct dmi_system_id allow_virtual_pc[] = {
1600d9904344SOlaf Hering 		{
1601d9904344SOlaf Hering 			/* In MS Virtual PC guests the DMI ident is nearly
1602d9904344SOlaf Hering 			 * identical to a Hyper-V guest. One difference is the
1603d9904344SOlaf Hering 			 * product version which is used here to identify
1604d9904344SOlaf Hering 			 * a Virtual PC guest. This entry allows ata_piix to
1605d9904344SOlaf Hering 			 * drive the emulated hardware.
1606d9904344SOlaf Hering 			 */
1607d9904344SOlaf Hering 			.ident = "MS Virtual PC 2007",
1608d9904344SOlaf Hering 			.matches = {
1609d9904344SOlaf Hering 				DMI_MATCH(DMI_SYS_VENDOR,
1610d9904344SOlaf Hering 						"Microsoft Corporation"),
1611d9904344SOlaf Hering 				DMI_MATCH(DMI_PRODUCT_NAME, "Virtual Machine"),
1612d9904344SOlaf Hering 				DMI_MATCH(DMI_PRODUCT_VERSION, "VS2005R2"),
1613d9904344SOlaf Hering 			},
1614d9904344SOlaf Hering 		},
1615d9904344SOlaf Hering 		{ }	/* terminate list */
1616d9904344SOlaf Hering 	};
1617d9904344SOlaf Hering 	const struct dmi_system_id *ignore = dmi_first_match(ignore_hyperv);
1618d9904344SOlaf Hering 	const struct dmi_system_id *allow = dmi_first_match(allow_virtual_pc);
1619cd006086SAndy Whitcroft 
1620d9904344SOlaf Hering 	if (ignore && !allow && prefer_ms_hyperv) {
1621cd006086SAndy Whitcroft 		host->flags |= ATA_HOST_IGNORE_ATA;
1622cd006086SAndy Whitcroft 		dev_info(host->dev, "%s detected, ATA device ignore set\n",
1623d9904344SOlaf Hering 			ignore->ident);
1624cd006086SAndy Whitcroft 	}
1625cd006086SAndy Whitcroft #endif
1626cd006086SAndy Whitcroft }
1627cd006086SAndy Whitcroft 
1628c6fd2807SJeff Garzik /**
1629c6fd2807SJeff Garzik  *	piix_init_one - Register PIIX ATA PCI device with kernel services
1630c6fd2807SJeff Garzik  *	@pdev: PCI device to register
1631c6fd2807SJeff Garzik  *	@ent: Entry in piix_pci_tbl matching with @pdev
1632c6fd2807SJeff Garzik  *
1633c6fd2807SJeff Garzik  *	Called from kernel PCI layer.  We probe for combined mode (sigh),
1634c6fd2807SJeff Garzik  *	and then hand over control to libata, for it to do the rest.
1635c6fd2807SJeff Garzik  *
1636c6fd2807SJeff Garzik  *	LOCKING:
1637c6fd2807SJeff Garzik  *	Inherited from PCI layer (may sleep).
1638c6fd2807SJeff Garzik  *
1639c6fd2807SJeff Garzik  *	RETURNS:
1640c6fd2807SJeff Garzik  *	Zero on success, or -ERRNO value.
1641c6fd2807SJeff Garzik  */
1642c6fd2807SJeff Garzik 
piix_init_one(struct pci_dev * pdev,const struct pci_device_id * ent)16430ec24914SGreg Kroah-Hartman static int piix_init_one(struct pci_dev *pdev, const struct pci_device_id *ent)
1644c6fd2807SJeff Garzik {
164524dc5f33STejun Heo 	struct device *dev = &pdev->dev;
1646c6fd2807SJeff Garzik 	struct ata_port_info port_info[2];
16471626aeb8STejun Heo 	const struct ata_port_info *ppi[] = { &port_info[0], &port_info[1] };
1648*25df73d9SBart Van Assche 	const struct scsi_host_template *sht = &piix_sht;
1649cca3974eSJeff Garzik 	unsigned long port_flags;
16508b09f0daSTejun Heo 	struct ata_host *host;
16518b09f0daSTejun Heo 	struct piix_host_priv *hpriv;
16528b09f0daSTejun Heo 	int rc;
1653c6fd2807SJeff Garzik 
165406296a1eSJoe Perches 	ata_print_version_once(&pdev->dev, DRV_VERSION);
1655c6fd2807SJeff Garzik 
1656347979a0SAlan Cox 	/* no hotplugging support for later devices (FIXME) */
1657347979a0SAlan Cox 	if (!in_module_init && ent->driver_data >= ich5_sata)
1658c6fd2807SJeff Garzik 		return -ENODEV;
1659c6fd2807SJeff Garzik 
16605f451fe1SRafael J. Wysocki 	if (piix_broken_system_poweroff(pdev)) {
16615f451fe1SRafael J. Wysocki 		piix_port_info[ent->driver_data].flags |=
16625f451fe1SRafael J. Wysocki 				ATA_FLAG_NO_POWEROFF_SPINDOWN |
16635f451fe1SRafael J. Wysocki 					ATA_FLAG_NO_HIBERNATE_SPINDOWN;
16645f451fe1SRafael J. Wysocki 		dev_info(&pdev->dev, "quirky BIOS, skipping spindown "
16655f451fe1SRafael J. Wysocki 				"on poweroff and hibernation\n");
16665f451fe1SRafael J. Wysocki 	}
16675f451fe1SRafael J. Wysocki 
16688b09f0daSTejun Heo 	port_info[0] = piix_port_info[ent->driver_data];
16698b09f0daSTejun Heo 	port_info[1] = piix_port_info[ent->driver_data];
16708b09f0daSTejun Heo 
16718b09f0daSTejun Heo 	port_flags = port_info[0].flags;
16728b09f0daSTejun Heo 
16738b09f0daSTejun Heo 	/* enable device and prepare host */
16748b09f0daSTejun Heo 	rc = pcim_enable_device(pdev);
16758b09f0daSTejun Heo 	if (rc)
16768b09f0daSTejun Heo 		return rc;
16778b09f0daSTejun Heo 
16782852bcf7STejun Heo 	hpriv = devm_kzalloc(dev, sizeof(*hpriv), GFP_KERNEL);
16792852bcf7STejun Heo 	if (!hpriv)
16802852bcf7STejun Heo 		return -ENOMEM;
16812852bcf7STejun Heo 
16822852bcf7STejun Heo 	/* Save IOCFG, this will be used for cable detection, quirk
16832852bcf7STejun Heo 	 * detection and restoration on detach.  This is necessary
16842852bcf7STejun Heo 	 * because some ACPI implementations mess up cable related
16852852bcf7STejun Heo 	 * bits on _STM.  Reported on kernel bz#11879.
16862852bcf7STejun Heo 	 */
16872852bcf7STejun Heo 	pci_read_config_dword(pdev, PIIX_IOCFG, &hpriv->saved_iocfg);
16882852bcf7STejun Heo 
16895016d7d2STejun Heo 	/* ICH6R may be driven by either ata_piix or ahci driver
16905016d7d2STejun Heo 	 * regardless of BIOS configuration.  Make sure AHCI mode is
16915016d7d2STejun Heo 	 * off.
16925016d7d2STejun Heo 	 */
16935016d7d2STejun Heo 	if (pdev->vendor == PCI_VENDOR_ID_INTEL && pdev->device == 0x2652) {
1694da3ceb22SStephen Hemminger 		rc = piix_disable_ahci(pdev);
16955016d7d2STejun Heo 		if (rc)
16965016d7d2STejun Heo 			return rc;
16975016d7d2STejun Heo 	}
16985016d7d2STejun Heo 
16998b09f0daSTejun Heo 	/* SATA map init can change port_info, do it before prepping host */
17008b09f0daSTejun Heo 	if (port_flags & ATA_FLAG_SATA)
17018b09f0daSTejun Heo 		hpriv->map = piix_init_sata_map(pdev, port_info,
17028b09f0daSTejun Heo 					piix_map_db_table[ent->driver_data]);
1703c6fd2807SJeff Garzik 
17041c5afdf7STejun Heo 	rc = ata_pci_bmdma_prepare_host(pdev, ppi, &host);
17058b09f0daSTejun Heo 	if (rc)
17068b09f0daSTejun Heo 		return rc;
17078b09f0daSTejun Heo 	host->private_data = hpriv;
1708c6fd2807SJeff Garzik 
17098b09f0daSTejun Heo 	/* initialize controller */
1710c7290724STejun Heo 	if (port_flags & ATA_FLAG_SATA) {
17118b09f0daSTejun Heo 		piix_init_pcs(host, piix_map_db_table[ent->driver_data]);
1712be77e43aSTejun Heo 		rc = piix_init_sidpr(host);
1713be77e43aSTejun Heo 		if (rc)
1714be77e43aSTejun Heo 			return rc;
1715a97c4006STejun Heo 		if (host->ports[0]->ops == &piix_sidpr_sata_ops)
1716a97c4006STejun Heo 			sht = &piix_sidpr_sht;
1717c7290724STejun Heo 	}
1718c6fd2807SJeff Garzik 
171943a98f05STejun Heo 	/* apply IOCFG bit18 quirk */
17202852bcf7STejun Heo 	piix_iocfg_bit18_quirk(host);
172143a98f05STejun Heo 
1722c6fd2807SJeff Garzik 	/* On ICH5, some BIOSen disable the interrupt using the
1723c6fd2807SJeff Garzik 	 * PCI_COMMAND_INTX_DISABLE bit added in PCI 2.3.
1724c6fd2807SJeff Garzik 	 * On ICH6, this bit has the same effect, but only when
1725c6fd2807SJeff Garzik 	 * MSI is disabled (and it is disabled, as we don't use
1726c6fd2807SJeff Garzik 	 * message-signalled interrupts currently).
1727c6fd2807SJeff Garzik 	 */
1728cca3974eSJeff Garzik 	if (port_flags & PIIX_FLAG_CHECKINTR)
1729c6fd2807SJeff Garzik 		pci_intx(pdev, 1);
1730c6fd2807SJeff Garzik 
1731c6fd2807SJeff Garzik 	if (piix_check_450nx_errata(pdev)) {
1732c6fd2807SJeff Garzik 		/* This writes into the master table but it does not
1733c6fd2807SJeff Garzik 		   really matter for this errata as we will apply it to
1734c6fd2807SJeff Garzik 		   all the PIIX devices on the board */
17358b09f0daSTejun Heo 		host->ports[0]->mwdma_mask = 0;
17368b09f0daSTejun Heo 		host->ports[0]->udma_mask = 0;
17378b09f0daSTejun Heo 		host->ports[1]->mwdma_mask = 0;
17388b09f0daSTejun Heo 		host->ports[1]->udma_mask = 0;
1739c6fd2807SJeff Garzik 	}
1740517d3cc1SArjan van de Ven 	host->flags |= ATA_HOST_PARALLEL_SCAN;
17418b09f0daSTejun Heo 
1742cd006086SAndy Whitcroft 	/* Allow hosts to specify device types to ignore when scanning. */
1743cd006086SAndy Whitcroft 	piix_ignore_devices_quirk(host);
1744cd006086SAndy Whitcroft 
17458b09f0daSTejun Heo 	pci_set_master(pdev);
1746a97c4006STejun Heo 	return ata_pci_sff_activate_host(host, ata_bmdma_interrupt, sht);
1747c6fd2807SJeff Garzik }
1748c6fd2807SJeff Garzik 
piix_remove_one(struct pci_dev * pdev)17492852bcf7STejun Heo static void piix_remove_one(struct pci_dev *pdev)
17502852bcf7STejun Heo {
17510a86e1c8SJingoo Han 	struct ata_host *host = pci_get_drvdata(pdev);
17522852bcf7STejun Heo 	struct piix_host_priv *hpriv = host->private_data;
17532852bcf7STejun Heo 
17542852bcf7STejun Heo 	pci_write_config_dword(pdev, PIIX_IOCFG, hpriv->saved_iocfg);
17552852bcf7STejun Heo 
17562852bcf7STejun Heo 	ata_pci_remove_one(pdev);
17572852bcf7STejun Heo }
17582852bcf7STejun Heo 
1759f295be25SBartlomiej Zolnierkiewicz static struct pci_driver piix_pci_driver = {
1760f295be25SBartlomiej Zolnierkiewicz 	.name			= DRV_NAME,
1761f295be25SBartlomiej Zolnierkiewicz 	.id_table		= piix_pci_tbl,
1762f295be25SBartlomiej Zolnierkiewicz 	.probe			= piix_init_one,
1763f295be25SBartlomiej Zolnierkiewicz 	.remove			= piix_remove_one,
176458eb8cd5SBartlomiej Zolnierkiewicz #ifdef CONFIG_PM_SLEEP
1765f295be25SBartlomiej Zolnierkiewicz 	.suspend		= piix_pci_device_suspend,
1766f295be25SBartlomiej Zolnierkiewicz 	.resume			= piix_pci_device_resume,
1767f295be25SBartlomiej Zolnierkiewicz #endif
1768f295be25SBartlomiej Zolnierkiewicz };
1769f295be25SBartlomiej Zolnierkiewicz 
piix_init(void)1770c6fd2807SJeff Garzik static int __init piix_init(void)
1771c6fd2807SJeff Garzik {
1772c6fd2807SJeff Garzik 	int rc;
1773c6fd2807SJeff Garzik 
1774c6fd2807SJeff Garzik 	rc = pci_register_driver(&piix_pci_driver);
1775c6fd2807SJeff Garzik 	if (rc)
1776c6fd2807SJeff Garzik 		return rc;
1777c6fd2807SJeff Garzik 
1778c6fd2807SJeff Garzik 	in_module_init = 0;
1779c6fd2807SJeff Garzik 
1780c6fd2807SJeff Garzik 	return 0;
1781c6fd2807SJeff Garzik }
1782c6fd2807SJeff Garzik 
piix_exit(void)1783c6fd2807SJeff Garzik static void __exit piix_exit(void)
1784c6fd2807SJeff Garzik {
1785c6fd2807SJeff Garzik 	pci_unregister_driver(&piix_pci_driver);
1786c6fd2807SJeff Garzik }
1787c6fd2807SJeff Garzik 
1788c6fd2807SJeff Garzik module_init(piix_init);
1789c6fd2807SJeff Garzik module_exit(piix_exit);
1790