xref: /openbmc/linux/drivers/ata/ahci.c (revision 66a7cbc303f4d28f201529b06061944d51ab530c)
1c6fd2807SJeff Garzik /*
2c6fd2807SJeff Garzik  *  ahci.c - AHCI SATA support
3c6fd2807SJeff Garzik  *
48c3d3d4bSTejun Heo  *  Maintained by:  Tejun Heo <tj@kernel.org>
5c6fd2807SJeff Garzik  *    		    Please ALWAYS copy linux-ide@vger.kernel.org
6c6fd2807SJeff Garzik  *		    on emails.
7c6fd2807SJeff Garzik  *
8c6fd2807SJeff Garzik  *  Copyright 2004-2005 Red Hat, Inc.
9c6fd2807SJeff Garzik  *
10c6fd2807SJeff Garzik  *
11c6fd2807SJeff Garzik  *  This program is free software; you can redistribute it and/or modify
12c6fd2807SJeff Garzik  *  it under the terms of the GNU General Public License as published by
13c6fd2807SJeff Garzik  *  the Free Software Foundation; either version 2, or (at your option)
14c6fd2807SJeff Garzik  *  any later version.
15c6fd2807SJeff Garzik  *
16c6fd2807SJeff Garzik  *  This program is distributed in the hope that it will be useful,
17c6fd2807SJeff Garzik  *  but WITHOUT ANY WARRANTY; without even the implied warranty of
18c6fd2807SJeff Garzik  *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
19c6fd2807SJeff Garzik  *  GNU General Public License for more details.
20c6fd2807SJeff Garzik  *
21c6fd2807SJeff Garzik  *  You should have received a copy of the GNU General Public License
22c6fd2807SJeff Garzik  *  along with this program; see the file COPYING.  If not, write to
23c6fd2807SJeff Garzik  *  the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA.
24c6fd2807SJeff Garzik  *
25c6fd2807SJeff Garzik  *
26c6fd2807SJeff Garzik  * libata documentation is available via 'make {ps|pdf}docs',
27c6fd2807SJeff Garzik  * as Documentation/DocBook/libata.*
28c6fd2807SJeff Garzik  *
29c6fd2807SJeff Garzik  * AHCI hardware documentation:
30c6fd2807SJeff Garzik  * http://www.intel.com/technology/serialata/pdf/rev1_0.pdf
31c6fd2807SJeff Garzik  * http://www.intel.com/technology/serialata/pdf/rev1_1.pdf
32c6fd2807SJeff Garzik  *
33c6fd2807SJeff Garzik  */
34c6fd2807SJeff Garzik 
35c6fd2807SJeff Garzik #include <linux/kernel.h>
36c6fd2807SJeff Garzik #include <linux/module.h>
37c6fd2807SJeff Garzik #include <linux/pci.h>
38c6fd2807SJeff Garzik #include <linux/blkdev.h>
39c6fd2807SJeff Garzik #include <linux/delay.h>
40c6fd2807SJeff Garzik #include <linux/interrupt.h>
41c6fd2807SJeff Garzik #include <linux/dma-mapping.h>
42c6fd2807SJeff Garzik #include <linux/device.h>
43edc93052STejun Heo #include <linux/dmi.h>
445a0e3ad6STejun Heo #include <linux/gfp.h>
45c6fd2807SJeff Garzik #include <scsi/scsi_host.h>
46c6fd2807SJeff Garzik #include <scsi/scsi_cmnd.h>
47c6fd2807SJeff Garzik #include <linux/libata.h>
48365cfa1eSAnton Vorontsov #include "ahci.h"
49c6fd2807SJeff Garzik 
50c6fd2807SJeff Garzik #define DRV_NAME	"ahci"
517d50b60bSTejun Heo #define DRV_VERSION	"3.0"
52c6fd2807SJeff Garzik 
53c6fd2807SJeff Garzik enum {
54318893e1SAlessandro Rubini 	AHCI_PCI_BAR_STA2X11	= 0,
557f9c9f8eSHugh Daschbach 	AHCI_PCI_BAR_ENMOTUS	= 2,
56318893e1SAlessandro Rubini 	AHCI_PCI_BAR_STANDARD	= 5,
57441577efSTejun Heo };
58c6fd2807SJeff Garzik 
59441577efSTejun Heo enum board_ids {
60441577efSTejun Heo 	/* board IDs by feature in alphabetical order */
61441577efSTejun Heo 	board_ahci,
62441577efSTejun Heo 	board_ahci_ign_iferr,
63*66a7cbc3STejun Heo 	board_ahci_nomsi,
6467809f85SLevente Kurusa 	board_ahci_noncq,
65441577efSTejun Heo 	board_ahci_nosntf,
665f173107STejun Heo 	board_ahci_yes_fbs,
67441577efSTejun Heo 
68441577efSTejun Heo 	/* board IDs for specific chipsets in alphabetical order */
69441577efSTejun Heo 	board_ahci_mcp65,
7083f2b963STejun Heo 	board_ahci_mcp77,
7183f2b963STejun Heo 	board_ahci_mcp89,
72441577efSTejun Heo 	board_ahci_mv,
73441577efSTejun Heo 	board_ahci_sb600,
74441577efSTejun Heo 	board_ahci_sb700,	/* for SB700 and SB800 */
75441577efSTejun Heo 	board_ahci_vt8251,
76441577efSTejun Heo 
77441577efSTejun Heo 	/* aliases */
78441577efSTejun Heo 	board_ahci_mcp_linux	= board_ahci_mcp65,
79441577efSTejun Heo 	board_ahci_mcp67	= board_ahci_mcp65,
80441577efSTejun Heo 	board_ahci_mcp73	= board_ahci_mcp65,
8183f2b963STejun Heo 	board_ahci_mcp79	= board_ahci_mcp77,
82c6fd2807SJeff Garzik };
83c6fd2807SJeff Garzik 
84c6fd2807SJeff Garzik static int ahci_init_one(struct pci_dev *pdev, const struct pci_device_id *ent);
85a1efdabaSTejun Heo static int ahci_vt8251_hardreset(struct ata_link *link, unsigned int *class,
86a1efdabaSTejun Heo 				 unsigned long deadline);
87cb85696dSJames Laird static void ahci_mcp89_apple_enable(struct pci_dev *pdev);
88cb85696dSJames Laird static bool is_mcp89_apple(struct pci_dev *pdev);
89a1efdabaSTejun Heo static int ahci_p5wdh_hardreset(struct ata_link *link, unsigned int *class,
90a1efdabaSTejun Heo 				unsigned long deadline);
91438ac6d5STejun Heo #ifdef CONFIG_PM
92c6fd2807SJeff Garzik static int ahci_pci_device_suspend(struct pci_dev *pdev, pm_message_t mesg);
93c6fd2807SJeff Garzik static int ahci_pci_device_resume(struct pci_dev *pdev);
94438ac6d5STejun Heo #endif
95c6fd2807SJeff Garzik 
96fad16e7aSTejun Heo static struct scsi_host_template ahci_sht = {
97fad16e7aSTejun Heo 	AHCI_SHT("ahci"),
98fad16e7aSTejun Heo };
99fad16e7aSTejun Heo 
100029cfd6bSTejun Heo static struct ata_port_operations ahci_vt8251_ops = {
101029cfd6bSTejun Heo 	.inherits		= &ahci_ops,
102a1efdabaSTejun Heo 	.hardreset		= ahci_vt8251_hardreset,
103ad616ffbSTejun Heo };
104ad616ffbSTejun Heo 
105029cfd6bSTejun Heo static struct ata_port_operations ahci_p5wdh_ops = {
106029cfd6bSTejun Heo 	.inherits		= &ahci_ops,
107a1efdabaSTejun Heo 	.hardreset		= ahci_p5wdh_hardreset,
108edc93052STejun Heo };
109edc93052STejun Heo 
110c6fd2807SJeff Garzik static const struct ata_port_info ahci_port_info[] = {
111441577efSTejun Heo 	/* by features */
112facb8fa6SJeffrin Jose 	[board_ahci] = {
1131188c0d8STejun Heo 		.flags		= AHCI_FLAG_COMMON,
11414bdef98SErik Inge Bolsø 		.pio_mask	= ATA_PIO4,
115469248abSJeff Garzik 		.udma_mask	= ATA_UDMA6,
116c6fd2807SJeff Garzik 		.port_ops	= &ahci_ops,
117c6fd2807SJeff Garzik 	},
118facb8fa6SJeffrin Jose 	[board_ahci_ign_iferr] = {
119417a1a6dSTejun Heo 		AHCI_HFLAGS	(AHCI_HFLAG_IGN_IRQ_IF_ERR),
120417a1a6dSTejun Heo 		.flags		= AHCI_FLAG_COMMON,
12114bdef98SErik Inge Bolsø 		.pio_mask	= ATA_PIO4,
122469248abSJeff Garzik 		.udma_mask	= ATA_UDMA6,
12341669553STejun Heo 		.port_ops	= &ahci_ops,
12441669553STejun Heo 	},
125*66a7cbc3STejun Heo 	[board_ahci_nomsi] = {
126*66a7cbc3STejun Heo 		AHCI_HFLAGS	(AHCI_HFLAG_NO_MSI),
127*66a7cbc3STejun Heo 		.flags		= AHCI_FLAG_COMMON,
128*66a7cbc3STejun Heo 		.pio_mask	= ATA_PIO4,
129*66a7cbc3STejun Heo 		.udma_mask	= ATA_UDMA6,
130*66a7cbc3STejun Heo 		.port_ops	= &ahci_ops,
131*66a7cbc3STejun Heo 	},
13267809f85SLevente Kurusa 	[board_ahci_noncq] = {
13367809f85SLevente Kurusa 		AHCI_HFLAGS	(AHCI_HFLAG_NO_NCQ),
13467809f85SLevente Kurusa 		.flags		= AHCI_FLAG_COMMON,
13567809f85SLevente Kurusa 		.pio_mask	= ATA_PIO4,
13667809f85SLevente Kurusa 		.udma_mask	= ATA_UDMA6,
13767809f85SLevente Kurusa 		.port_ops	= &ahci_ops,
13867809f85SLevente Kurusa 	},
139facb8fa6SJeffrin Jose 	[board_ahci_nosntf] = {
140441577efSTejun Heo 		AHCI_HFLAGS	(AHCI_HFLAG_NO_SNTF),
141441577efSTejun Heo 		.flags		= AHCI_FLAG_COMMON,
142441577efSTejun Heo 		.pio_mask	= ATA_PIO4,
143441577efSTejun Heo 		.udma_mask	= ATA_UDMA6,
144441577efSTejun Heo 		.port_ops	= &ahci_ops,
145441577efSTejun Heo 	},
146facb8fa6SJeffrin Jose 	[board_ahci_yes_fbs] = {
1475f173107STejun Heo 		AHCI_HFLAGS	(AHCI_HFLAG_YES_FBS),
1485f173107STejun Heo 		.flags		= AHCI_FLAG_COMMON,
1495f173107STejun Heo 		.pio_mask	= ATA_PIO4,
1505f173107STejun Heo 		.udma_mask	= ATA_UDMA6,
1515f173107STejun Heo 		.port_ops	= &ahci_ops,
1525f173107STejun Heo 	},
153441577efSTejun Heo 	/* by chipsets */
154facb8fa6SJeffrin Jose 	[board_ahci_mcp65] = {
15583f2b963STejun Heo 		AHCI_HFLAGS	(AHCI_HFLAG_NO_FPDMA_AA | AHCI_HFLAG_NO_PMP |
15683f2b963STejun Heo 				 AHCI_HFLAG_YES_NCQ),
157ae01b249STejun Heo 		.flags		= AHCI_FLAG_COMMON | ATA_FLAG_NO_DIPM,
15883f2b963STejun Heo 		.pio_mask	= ATA_PIO4,
15983f2b963STejun Heo 		.udma_mask	= ATA_UDMA6,
16083f2b963STejun Heo 		.port_ops	= &ahci_ops,
16183f2b963STejun Heo 	},
162facb8fa6SJeffrin Jose 	[board_ahci_mcp77] = {
16383f2b963STejun Heo 		AHCI_HFLAGS	(AHCI_HFLAG_NO_FPDMA_AA | AHCI_HFLAG_NO_PMP),
16483f2b963STejun Heo 		.flags		= AHCI_FLAG_COMMON,
16583f2b963STejun Heo 		.pio_mask	= ATA_PIO4,
16683f2b963STejun Heo 		.udma_mask	= ATA_UDMA6,
16783f2b963STejun Heo 		.port_ops	= &ahci_ops,
16883f2b963STejun Heo 	},
169facb8fa6SJeffrin Jose 	[board_ahci_mcp89] = {
17083f2b963STejun Heo 		AHCI_HFLAGS	(AHCI_HFLAG_NO_FPDMA_AA),
171441577efSTejun Heo 		.flags		= AHCI_FLAG_COMMON,
172441577efSTejun Heo 		.pio_mask	= ATA_PIO4,
173441577efSTejun Heo 		.udma_mask	= ATA_UDMA6,
174441577efSTejun Heo 		.port_ops	= &ahci_ops,
175441577efSTejun Heo 	},
176facb8fa6SJeffrin Jose 	[board_ahci_mv] = {
177441577efSTejun Heo 		AHCI_HFLAGS	(AHCI_HFLAG_NO_NCQ | AHCI_HFLAG_NO_MSI |
178441577efSTejun Heo 				 AHCI_HFLAG_MV_PATA | AHCI_HFLAG_NO_PMP),
1799cbe056fSSergei Shtylyov 		.flags		= ATA_FLAG_SATA | ATA_FLAG_PIO_DMA,
180441577efSTejun Heo 		.pio_mask	= ATA_PIO4,
181441577efSTejun Heo 		.udma_mask	= ATA_UDMA6,
182441577efSTejun Heo 		.port_ops	= &ahci_ops,
183441577efSTejun Heo 	},
184facb8fa6SJeffrin Jose 	[board_ahci_sb600] = {
185417a1a6dSTejun Heo 		AHCI_HFLAGS	(AHCI_HFLAG_IGN_SERR_INTERNAL |
1862fcad9d2STejun Heo 				 AHCI_HFLAG_NO_MSI | AHCI_HFLAG_SECT255 |
1872fcad9d2STejun Heo 				 AHCI_HFLAG_32BIT_ONLY),
188417a1a6dSTejun Heo 		.flags		= AHCI_FLAG_COMMON,
18914bdef98SErik Inge Bolsø 		.pio_mask	= ATA_PIO4,
190469248abSJeff Garzik 		.udma_mask	= ATA_UDMA6,
191345347c5SYuan-Hsin Chen 		.port_ops	= &ahci_pmp_retry_srst_ops,
19255a61604SConke Hu 	},
193facb8fa6SJeffrin Jose 	[board_ahci_sb700] = {	/* for SB700 and SB800 */
194bd17243aSShane Huang 		AHCI_HFLAGS	(AHCI_HFLAG_IGN_SERR_INTERNAL),
195e39fc8c9SShane Huang 		.flags		= AHCI_FLAG_COMMON,
19614bdef98SErik Inge Bolsø 		.pio_mask	= ATA_PIO4,
197e39fc8c9SShane Huang 		.udma_mask	= ATA_UDMA6,
198345347c5SYuan-Hsin Chen 		.port_ops	= &ahci_pmp_retry_srst_ops,
199e39fc8c9SShane Huang 	},
200facb8fa6SJeffrin Jose 	[board_ahci_vt8251] = {
201441577efSTejun Heo 		AHCI_HFLAGS	(AHCI_HFLAG_NO_NCQ | AHCI_HFLAG_NO_PMP),
202e297d99eSTejun Heo 		.flags		= AHCI_FLAG_COMMON,
20314bdef98SErik Inge Bolsø 		.pio_mask	= ATA_PIO4,
204e297d99eSTejun Heo 		.udma_mask	= ATA_UDMA6,
205441577efSTejun Heo 		.port_ops	= &ahci_vt8251_ops,
2061b677afdSShaohua Li 	},
207c6fd2807SJeff Garzik };
208c6fd2807SJeff Garzik 
209c6fd2807SJeff Garzik static const struct pci_device_id ahci_pci_tbl[] = {
210c6fd2807SJeff Garzik 	/* Intel */
21154bb3a94SJeff Garzik 	{ PCI_VDEVICE(INTEL, 0x2652), board_ahci }, /* ICH6 */
21254bb3a94SJeff Garzik 	{ PCI_VDEVICE(INTEL, 0x2653), board_ahci }, /* ICH6M */
21354bb3a94SJeff Garzik 	{ PCI_VDEVICE(INTEL, 0x27c1), board_ahci }, /* ICH7 */
21454bb3a94SJeff Garzik 	{ PCI_VDEVICE(INTEL, 0x27c5), board_ahci }, /* ICH7M */
21554bb3a94SJeff Garzik 	{ PCI_VDEVICE(INTEL, 0x27c3), board_ahci }, /* ICH7R */
21682490c09STejun Heo 	{ PCI_VDEVICE(AL, 0x5288), board_ahci_ign_iferr }, /* ULi M5288 */
21754bb3a94SJeff Garzik 	{ PCI_VDEVICE(INTEL, 0x2681), board_ahci }, /* ESB2 */
21854bb3a94SJeff Garzik 	{ PCI_VDEVICE(INTEL, 0x2682), board_ahci }, /* ESB2 */
21954bb3a94SJeff Garzik 	{ PCI_VDEVICE(INTEL, 0x2683), board_ahci }, /* ESB2 */
22054bb3a94SJeff Garzik 	{ PCI_VDEVICE(INTEL, 0x27c6), board_ahci }, /* ICH7-M DH */
2217a234affSTejun Heo 	{ PCI_VDEVICE(INTEL, 0x2821), board_ahci }, /* ICH8 */
2221b677afdSShaohua Li 	{ PCI_VDEVICE(INTEL, 0x2822), board_ahci_nosntf }, /* ICH8 */
2237a234affSTejun Heo 	{ PCI_VDEVICE(INTEL, 0x2824), board_ahci }, /* ICH8 */
2247a234affSTejun Heo 	{ PCI_VDEVICE(INTEL, 0x2829), board_ahci }, /* ICH8M */
2257a234affSTejun Heo 	{ PCI_VDEVICE(INTEL, 0x282a), board_ahci }, /* ICH8M */
2267a234affSTejun Heo 	{ PCI_VDEVICE(INTEL, 0x2922), board_ahci }, /* ICH9 */
2277a234affSTejun Heo 	{ PCI_VDEVICE(INTEL, 0x2923), board_ahci }, /* ICH9 */
2287a234affSTejun Heo 	{ PCI_VDEVICE(INTEL, 0x2924), board_ahci }, /* ICH9 */
2297a234affSTejun Heo 	{ PCI_VDEVICE(INTEL, 0x2925), board_ahci }, /* ICH9 */
2307a234affSTejun Heo 	{ PCI_VDEVICE(INTEL, 0x2927), board_ahci }, /* ICH9 */
2317a234affSTejun Heo 	{ PCI_VDEVICE(INTEL, 0x2929), board_ahci }, /* ICH9M */
2327a234affSTejun Heo 	{ PCI_VDEVICE(INTEL, 0x292a), board_ahci }, /* ICH9M */
2337a234affSTejun Heo 	{ PCI_VDEVICE(INTEL, 0x292b), board_ahci }, /* ICH9M */
2347a234affSTejun Heo 	{ PCI_VDEVICE(INTEL, 0x292c), board_ahci }, /* ICH9M */
2357a234affSTejun Heo 	{ PCI_VDEVICE(INTEL, 0x292f), board_ahci }, /* ICH9M */
2367a234affSTejun Heo 	{ PCI_VDEVICE(INTEL, 0x294d), board_ahci }, /* ICH9 */
2377a234affSTejun Heo 	{ PCI_VDEVICE(INTEL, 0x294e), board_ahci }, /* ICH9M */
238d4155e6fSJason Gaston 	{ PCI_VDEVICE(INTEL, 0x502a), board_ahci }, /* Tolapai */
239d4155e6fSJason Gaston 	{ PCI_VDEVICE(INTEL, 0x502b), board_ahci }, /* Tolapai */
24016ad1ad9SJason Gaston 	{ PCI_VDEVICE(INTEL, 0x3a05), board_ahci }, /* ICH10 */
241b2dde6afSMark Goodwin 	{ PCI_VDEVICE(INTEL, 0x3a22), board_ahci }, /* ICH10 */
24216ad1ad9SJason Gaston 	{ PCI_VDEVICE(INTEL, 0x3a25), board_ahci }, /* ICH10 */
243c1f57d9bSDavid Milburn 	{ PCI_VDEVICE(INTEL, 0x3b22), board_ahci }, /* PCH AHCI */
244c1f57d9bSDavid Milburn 	{ PCI_VDEVICE(INTEL, 0x3b23), board_ahci }, /* PCH AHCI */
245adcb5308SSeth Heasley 	{ PCI_VDEVICE(INTEL, 0x3b24), board_ahci }, /* PCH RAID */
2468e48b6b3SSeth Heasley 	{ PCI_VDEVICE(INTEL, 0x3b25), board_ahci }, /* PCH RAID */
247c1f57d9bSDavid Milburn 	{ PCI_VDEVICE(INTEL, 0x3b29), board_ahci }, /* PCH AHCI */
248adcb5308SSeth Heasley 	{ PCI_VDEVICE(INTEL, 0x3b2b), board_ahci }, /* PCH RAID */
2498e48b6b3SSeth Heasley 	{ PCI_VDEVICE(INTEL, 0x3b2c), board_ahci }, /* PCH RAID */
250c1f57d9bSDavid Milburn 	{ PCI_VDEVICE(INTEL, 0x3b2f), board_ahci }, /* PCH AHCI */
2515623cab8SSeth Heasley 	{ PCI_VDEVICE(INTEL, 0x1c02), board_ahci }, /* CPT AHCI */
2525623cab8SSeth Heasley 	{ PCI_VDEVICE(INTEL, 0x1c03), board_ahci }, /* CPT AHCI */
2535623cab8SSeth Heasley 	{ PCI_VDEVICE(INTEL, 0x1c04), board_ahci }, /* CPT RAID */
2545623cab8SSeth Heasley 	{ PCI_VDEVICE(INTEL, 0x1c05), board_ahci }, /* CPT RAID */
2555623cab8SSeth Heasley 	{ PCI_VDEVICE(INTEL, 0x1c06), board_ahci }, /* CPT RAID */
2565623cab8SSeth Heasley 	{ PCI_VDEVICE(INTEL, 0x1c07), board_ahci }, /* CPT RAID */
257992b3fb9SSeth Heasley 	{ PCI_VDEVICE(INTEL, 0x1d02), board_ahci }, /* PBG AHCI */
258992b3fb9SSeth Heasley 	{ PCI_VDEVICE(INTEL, 0x1d04), board_ahci }, /* PBG RAID */
259992b3fb9SSeth Heasley 	{ PCI_VDEVICE(INTEL, 0x1d06), board_ahci }, /* PBG RAID */
26064a3903dSSeth Heasley 	{ PCI_VDEVICE(INTEL, 0x2826), board_ahci }, /* PBG RAID */
261a4a461a6SSeth Heasley 	{ PCI_VDEVICE(INTEL, 0x2323), board_ahci }, /* DH89xxCC AHCI */
262181e3ceaSSeth Heasley 	{ PCI_VDEVICE(INTEL, 0x1e02), board_ahci }, /* Panther Point AHCI */
263181e3ceaSSeth Heasley 	{ PCI_VDEVICE(INTEL, 0x1e03), board_ahci }, /* Panther Point AHCI */
264181e3ceaSSeth Heasley 	{ PCI_VDEVICE(INTEL, 0x1e04), board_ahci }, /* Panther Point RAID */
265181e3ceaSSeth Heasley 	{ PCI_VDEVICE(INTEL, 0x1e05), board_ahci }, /* Panther Point RAID */
266181e3ceaSSeth Heasley 	{ PCI_VDEVICE(INTEL, 0x1e06), board_ahci }, /* Panther Point RAID */
267181e3ceaSSeth Heasley 	{ PCI_VDEVICE(INTEL, 0x1e07), board_ahci }, /* Panther Point RAID */
2682cab7a4cSSeth Heasley 	{ PCI_VDEVICE(INTEL, 0x1e0e), board_ahci }, /* Panther Point RAID */
269ea4ace66SSeth Heasley 	{ PCI_VDEVICE(INTEL, 0x8c02), board_ahci }, /* Lynx Point AHCI */
270ea4ace66SSeth Heasley 	{ PCI_VDEVICE(INTEL, 0x8c03), board_ahci }, /* Lynx Point AHCI */
271ea4ace66SSeth Heasley 	{ PCI_VDEVICE(INTEL, 0x8c04), board_ahci }, /* Lynx Point RAID */
272ea4ace66SSeth Heasley 	{ PCI_VDEVICE(INTEL, 0x8c05), board_ahci }, /* Lynx Point RAID */
273ea4ace66SSeth Heasley 	{ PCI_VDEVICE(INTEL, 0x8c06), board_ahci }, /* Lynx Point RAID */
274ea4ace66SSeth Heasley 	{ PCI_VDEVICE(INTEL, 0x8c07), board_ahci }, /* Lynx Point RAID */
275ea4ace66SSeth Heasley 	{ PCI_VDEVICE(INTEL, 0x8c0e), board_ahci }, /* Lynx Point RAID */
276ea4ace66SSeth Heasley 	{ PCI_VDEVICE(INTEL, 0x8c0f), board_ahci }, /* Lynx Point RAID */
27777b12bc9SJames Ralston 	{ PCI_VDEVICE(INTEL, 0x9c02), board_ahci }, /* Lynx Point-LP AHCI */
27877b12bc9SJames Ralston 	{ PCI_VDEVICE(INTEL, 0x9c03), board_ahci }, /* Lynx Point-LP AHCI */
27977b12bc9SJames Ralston 	{ PCI_VDEVICE(INTEL, 0x9c04), board_ahci }, /* Lynx Point-LP RAID */
28077b12bc9SJames Ralston 	{ PCI_VDEVICE(INTEL, 0x9c05), board_ahci }, /* Lynx Point-LP RAID */
28177b12bc9SJames Ralston 	{ PCI_VDEVICE(INTEL, 0x9c06), board_ahci }, /* Lynx Point-LP RAID */
28277b12bc9SJames Ralston 	{ PCI_VDEVICE(INTEL, 0x9c07), board_ahci }, /* Lynx Point-LP RAID */
28377b12bc9SJames Ralston 	{ PCI_VDEVICE(INTEL, 0x9c0e), board_ahci }, /* Lynx Point-LP RAID */
28477b12bc9SJames Ralston 	{ PCI_VDEVICE(INTEL, 0x9c0f), board_ahci }, /* Lynx Point-LP RAID */
28529e674ddSSeth Heasley 	{ PCI_VDEVICE(INTEL, 0x1f22), board_ahci }, /* Avoton AHCI */
28629e674ddSSeth Heasley 	{ PCI_VDEVICE(INTEL, 0x1f23), board_ahci }, /* Avoton AHCI */
28729e674ddSSeth Heasley 	{ PCI_VDEVICE(INTEL, 0x1f24), board_ahci }, /* Avoton RAID */
28829e674ddSSeth Heasley 	{ PCI_VDEVICE(INTEL, 0x1f25), board_ahci }, /* Avoton RAID */
28929e674ddSSeth Heasley 	{ PCI_VDEVICE(INTEL, 0x1f26), board_ahci }, /* Avoton RAID */
29029e674ddSSeth Heasley 	{ PCI_VDEVICE(INTEL, 0x1f27), board_ahci }, /* Avoton RAID */
29129e674ddSSeth Heasley 	{ PCI_VDEVICE(INTEL, 0x1f2e), board_ahci }, /* Avoton RAID */
29229e674ddSSeth Heasley 	{ PCI_VDEVICE(INTEL, 0x1f2f), board_ahci }, /* Avoton RAID */
29329e674ddSSeth Heasley 	{ PCI_VDEVICE(INTEL, 0x1f32), board_ahci }, /* Avoton AHCI */
29429e674ddSSeth Heasley 	{ PCI_VDEVICE(INTEL, 0x1f33), board_ahci }, /* Avoton AHCI */
29529e674ddSSeth Heasley 	{ PCI_VDEVICE(INTEL, 0x1f34), board_ahci }, /* Avoton RAID */
29629e674ddSSeth Heasley 	{ PCI_VDEVICE(INTEL, 0x1f35), board_ahci }, /* Avoton RAID */
29729e674ddSSeth Heasley 	{ PCI_VDEVICE(INTEL, 0x1f36), board_ahci }, /* Avoton RAID */
29829e674ddSSeth Heasley 	{ PCI_VDEVICE(INTEL, 0x1f37), board_ahci }, /* Avoton RAID */
29929e674ddSSeth Heasley 	{ PCI_VDEVICE(INTEL, 0x1f3e), board_ahci }, /* Avoton RAID */
30029e674ddSSeth Heasley 	{ PCI_VDEVICE(INTEL, 0x1f3f), board_ahci }, /* Avoton RAID */
301efda332cSJames Ralston 	{ PCI_VDEVICE(INTEL, 0x2823), board_ahci }, /* Wellsburg RAID */
302efda332cSJames Ralston 	{ PCI_VDEVICE(INTEL, 0x2827), board_ahci }, /* Wellsburg RAID */
303151743fdSJames Ralston 	{ PCI_VDEVICE(INTEL, 0x8d02), board_ahci }, /* Wellsburg AHCI */
304151743fdSJames Ralston 	{ PCI_VDEVICE(INTEL, 0x8d04), board_ahci }, /* Wellsburg RAID */
305151743fdSJames Ralston 	{ PCI_VDEVICE(INTEL, 0x8d06), board_ahci }, /* Wellsburg RAID */
306151743fdSJames Ralston 	{ PCI_VDEVICE(INTEL, 0x8d0e), board_ahci }, /* Wellsburg RAID */
307151743fdSJames Ralston 	{ PCI_VDEVICE(INTEL, 0x8d62), board_ahci }, /* Wellsburg AHCI */
308151743fdSJames Ralston 	{ PCI_VDEVICE(INTEL, 0x8d64), board_ahci }, /* Wellsburg RAID */
309151743fdSJames Ralston 	{ PCI_VDEVICE(INTEL, 0x8d66), board_ahci }, /* Wellsburg RAID */
310151743fdSJames Ralston 	{ PCI_VDEVICE(INTEL, 0x8d6e), board_ahci }, /* Wellsburg RAID */
3111cfc7df3SSeth Heasley 	{ PCI_VDEVICE(INTEL, 0x23a3), board_ahci }, /* Coleto Creek AHCI */
3129f961a5fSJames Ralston 	{ PCI_VDEVICE(INTEL, 0x9c83), board_ahci }, /* Wildcat Point-LP AHCI */
3139f961a5fSJames Ralston 	{ PCI_VDEVICE(INTEL, 0x9c85), board_ahci }, /* Wildcat Point-LP RAID */
3149f961a5fSJames Ralston 	{ PCI_VDEVICE(INTEL, 0x9c87), board_ahci }, /* Wildcat Point-LP RAID */
3159f961a5fSJames Ralston 	{ PCI_VDEVICE(INTEL, 0x9c8f), board_ahci }, /* Wildcat Point-LP RAID */
3161b071a09SJames Ralston 	{ PCI_VDEVICE(INTEL, 0x8c82), board_ahci }, /* 9 Series AHCI */
3171b071a09SJames Ralston 	{ PCI_VDEVICE(INTEL, 0x8c83), board_ahci }, /* 9 Series AHCI */
3181b071a09SJames Ralston 	{ PCI_VDEVICE(INTEL, 0x8c84), board_ahci }, /* 9 Series RAID */
3191b071a09SJames Ralston 	{ PCI_VDEVICE(INTEL, 0x8c85), board_ahci }, /* 9 Series RAID */
3201b071a09SJames Ralston 	{ PCI_VDEVICE(INTEL, 0x8c86), board_ahci }, /* 9 Series RAID */
3211b071a09SJames Ralston 	{ PCI_VDEVICE(INTEL, 0x8c87), board_ahci }, /* 9 Series RAID */
3221b071a09SJames Ralston 	{ PCI_VDEVICE(INTEL, 0x8c8e), board_ahci }, /* 9 Series RAID */
3231b071a09SJames Ralston 	{ PCI_VDEVICE(INTEL, 0x8c8f), board_ahci }, /* 9 Series RAID */
324c6fd2807SJeff Garzik 
325e34bb370STejun Heo 	/* JMicron 360/1/3/5/6, match class to avoid IDE function */
326e34bb370STejun Heo 	{ PCI_VENDOR_ID_JMICRON, PCI_ANY_ID, PCI_ANY_ID, PCI_ANY_ID,
327e34bb370STejun Heo 	  PCI_CLASS_STORAGE_SATA_AHCI, 0xffffff, board_ahci_ign_iferr },
3281fefb8fdSBen Hutchings 	/* JMicron 362B and 362C have an AHCI function with IDE class code */
3291fefb8fdSBen Hutchings 	{ PCI_VDEVICE(JMICRON, 0x2362), board_ahci_ign_iferr },
3301fefb8fdSBen Hutchings 	{ PCI_VDEVICE(JMICRON, 0x236f), board_ahci_ign_iferr },
331c6fd2807SJeff Garzik 
332c6fd2807SJeff Garzik 	/* ATI */
333c65ec1c2SConke Hu 	{ PCI_VDEVICE(ATI, 0x4380), board_ahci_sb600 }, /* ATI SB600 */
334e39fc8c9SShane Huang 	{ PCI_VDEVICE(ATI, 0x4390), board_ahci_sb700 }, /* ATI SB700/800 */
335e39fc8c9SShane Huang 	{ PCI_VDEVICE(ATI, 0x4391), board_ahci_sb700 }, /* ATI SB700/800 */
336e39fc8c9SShane Huang 	{ PCI_VDEVICE(ATI, 0x4392), board_ahci_sb700 }, /* ATI SB700/800 */
337e39fc8c9SShane Huang 	{ PCI_VDEVICE(ATI, 0x4393), board_ahci_sb700 }, /* ATI SB700/800 */
338e39fc8c9SShane Huang 	{ PCI_VDEVICE(ATI, 0x4394), board_ahci_sb700 }, /* ATI SB700/800 */
339e39fc8c9SShane Huang 	{ PCI_VDEVICE(ATI, 0x4395), board_ahci_sb700 }, /* ATI SB700/800 */
340c6fd2807SJeff Garzik 
341e2dd90b1SShane Huang 	/* AMD */
3425deab536SShane Huang 	{ PCI_VDEVICE(AMD, 0x7800), board_ahci }, /* AMD Hudson-2 */
343fafe5c3dSShane Huang 	{ PCI_VDEVICE(AMD, 0x7900), board_ahci }, /* AMD CZ */
344e2dd90b1SShane Huang 	/* AMD is using RAID class only for ahci controllers */
345e2dd90b1SShane Huang 	{ PCI_VENDOR_ID_AMD, PCI_ANY_ID, PCI_ANY_ID, PCI_ANY_ID,
346e2dd90b1SShane Huang 	  PCI_CLASS_STORAGE_RAID << 8, 0xffffff, board_ahci },
347e2dd90b1SShane Huang 
348c6fd2807SJeff Garzik 	/* VIA */
34954bb3a94SJeff Garzik 	{ PCI_VDEVICE(VIA, 0x3349), board_ahci_vt8251 }, /* VIA VT8251 */
350bf335542STejun Heo 	{ PCI_VDEVICE(VIA, 0x6287), board_ahci_vt8251 }, /* VIA VT8251 */
351c6fd2807SJeff Garzik 
352c6fd2807SJeff Garzik 	/* NVIDIA */
353e297d99eSTejun Heo 	{ PCI_VDEVICE(NVIDIA, 0x044c), board_ahci_mcp65 },	/* MCP65 */
354e297d99eSTejun Heo 	{ PCI_VDEVICE(NVIDIA, 0x044d), board_ahci_mcp65 },	/* MCP65 */
355e297d99eSTejun Heo 	{ PCI_VDEVICE(NVIDIA, 0x044e), board_ahci_mcp65 },	/* MCP65 */
356e297d99eSTejun Heo 	{ PCI_VDEVICE(NVIDIA, 0x044f), board_ahci_mcp65 },	/* MCP65 */
357e297d99eSTejun Heo 	{ PCI_VDEVICE(NVIDIA, 0x045c), board_ahci_mcp65 },	/* MCP65 */
358e297d99eSTejun Heo 	{ PCI_VDEVICE(NVIDIA, 0x045d), board_ahci_mcp65 },	/* MCP65 */
359e297d99eSTejun Heo 	{ PCI_VDEVICE(NVIDIA, 0x045e), board_ahci_mcp65 },	/* MCP65 */
360e297d99eSTejun Heo 	{ PCI_VDEVICE(NVIDIA, 0x045f), board_ahci_mcp65 },	/* MCP65 */
361441577efSTejun Heo 	{ PCI_VDEVICE(NVIDIA, 0x0550), board_ahci_mcp67 },	/* MCP67 */
362441577efSTejun Heo 	{ PCI_VDEVICE(NVIDIA, 0x0551), board_ahci_mcp67 },	/* MCP67 */
363441577efSTejun Heo 	{ PCI_VDEVICE(NVIDIA, 0x0552), board_ahci_mcp67 },	/* MCP67 */
364441577efSTejun Heo 	{ PCI_VDEVICE(NVIDIA, 0x0553), board_ahci_mcp67 },	/* MCP67 */
365441577efSTejun Heo 	{ PCI_VDEVICE(NVIDIA, 0x0554), board_ahci_mcp67 },	/* MCP67 */
366441577efSTejun Heo 	{ PCI_VDEVICE(NVIDIA, 0x0555), board_ahci_mcp67 },	/* MCP67 */
367441577efSTejun Heo 	{ PCI_VDEVICE(NVIDIA, 0x0556), board_ahci_mcp67 },	/* MCP67 */
368441577efSTejun Heo 	{ PCI_VDEVICE(NVIDIA, 0x0557), board_ahci_mcp67 },	/* MCP67 */
369441577efSTejun Heo 	{ PCI_VDEVICE(NVIDIA, 0x0558), board_ahci_mcp67 },	/* MCP67 */
370441577efSTejun Heo 	{ PCI_VDEVICE(NVIDIA, 0x0559), board_ahci_mcp67 },	/* MCP67 */
371441577efSTejun Heo 	{ PCI_VDEVICE(NVIDIA, 0x055a), board_ahci_mcp67 },	/* MCP67 */
372441577efSTejun Heo 	{ PCI_VDEVICE(NVIDIA, 0x055b), board_ahci_mcp67 },	/* MCP67 */
373441577efSTejun Heo 	{ PCI_VDEVICE(NVIDIA, 0x0580), board_ahci_mcp_linux },	/* Linux ID */
374441577efSTejun Heo 	{ PCI_VDEVICE(NVIDIA, 0x0581), board_ahci_mcp_linux },	/* Linux ID */
375441577efSTejun Heo 	{ PCI_VDEVICE(NVIDIA, 0x0582), board_ahci_mcp_linux },	/* Linux ID */
376441577efSTejun Heo 	{ PCI_VDEVICE(NVIDIA, 0x0583), board_ahci_mcp_linux },	/* Linux ID */
377441577efSTejun Heo 	{ PCI_VDEVICE(NVIDIA, 0x0584), board_ahci_mcp_linux },	/* Linux ID */
378441577efSTejun Heo 	{ PCI_VDEVICE(NVIDIA, 0x0585), board_ahci_mcp_linux },	/* Linux ID */
379441577efSTejun Heo 	{ PCI_VDEVICE(NVIDIA, 0x0586), board_ahci_mcp_linux },	/* Linux ID */
380441577efSTejun Heo 	{ PCI_VDEVICE(NVIDIA, 0x0587), board_ahci_mcp_linux },	/* Linux ID */
381441577efSTejun Heo 	{ PCI_VDEVICE(NVIDIA, 0x0588), board_ahci_mcp_linux },	/* Linux ID */
382441577efSTejun Heo 	{ PCI_VDEVICE(NVIDIA, 0x0589), board_ahci_mcp_linux },	/* Linux ID */
383441577efSTejun Heo 	{ PCI_VDEVICE(NVIDIA, 0x058a), board_ahci_mcp_linux },	/* Linux ID */
384441577efSTejun Heo 	{ PCI_VDEVICE(NVIDIA, 0x058b), board_ahci_mcp_linux },	/* Linux ID */
385441577efSTejun Heo 	{ PCI_VDEVICE(NVIDIA, 0x058c), board_ahci_mcp_linux },	/* Linux ID */
386441577efSTejun Heo 	{ PCI_VDEVICE(NVIDIA, 0x058d), board_ahci_mcp_linux },	/* Linux ID */
387441577efSTejun Heo 	{ PCI_VDEVICE(NVIDIA, 0x058e), board_ahci_mcp_linux },	/* Linux ID */
388441577efSTejun Heo 	{ PCI_VDEVICE(NVIDIA, 0x058f), board_ahci_mcp_linux },	/* Linux ID */
389441577efSTejun Heo 	{ PCI_VDEVICE(NVIDIA, 0x07f0), board_ahci_mcp73 },	/* MCP73 */
390441577efSTejun Heo 	{ PCI_VDEVICE(NVIDIA, 0x07f1), board_ahci_mcp73 },	/* MCP73 */
391441577efSTejun Heo 	{ PCI_VDEVICE(NVIDIA, 0x07f2), board_ahci_mcp73 },	/* MCP73 */
392441577efSTejun Heo 	{ PCI_VDEVICE(NVIDIA, 0x07f3), board_ahci_mcp73 },	/* MCP73 */
393441577efSTejun Heo 	{ PCI_VDEVICE(NVIDIA, 0x07f4), board_ahci_mcp73 },	/* MCP73 */
394441577efSTejun Heo 	{ PCI_VDEVICE(NVIDIA, 0x07f5), board_ahci_mcp73 },	/* MCP73 */
395441577efSTejun Heo 	{ PCI_VDEVICE(NVIDIA, 0x07f6), board_ahci_mcp73 },	/* MCP73 */
396441577efSTejun Heo 	{ PCI_VDEVICE(NVIDIA, 0x07f7), board_ahci_mcp73 },	/* MCP73 */
397441577efSTejun Heo 	{ PCI_VDEVICE(NVIDIA, 0x07f8), board_ahci_mcp73 },	/* MCP73 */
398441577efSTejun Heo 	{ PCI_VDEVICE(NVIDIA, 0x07f9), board_ahci_mcp73 },	/* MCP73 */
399441577efSTejun Heo 	{ PCI_VDEVICE(NVIDIA, 0x07fa), board_ahci_mcp73 },	/* MCP73 */
400441577efSTejun Heo 	{ PCI_VDEVICE(NVIDIA, 0x07fb), board_ahci_mcp73 },	/* MCP73 */
401441577efSTejun Heo 	{ PCI_VDEVICE(NVIDIA, 0x0ad0), board_ahci_mcp77 },	/* MCP77 */
402441577efSTejun Heo 	{ PCI_VDEVICE(NVIDIA, 0x0ad1), board_ahci_mcp77 },	/* MCP77 */
403441577efSTejun Heo 	{ PCI_VDEVICE(NVIDIA, 0x0ad2), board_ahci_mcp77 },	/* MCP77 */
404441577efSTejun Heo 	{ PCI_VDEVICE(NVIDIA, 0x0ad3), board_ahci_mcp77 },	/* MCP77 */
405441577efSTejun Heo 	{ PCI_VDEVICE(NVIDIA, 0x0ad4), board_ahci_mcp77 },	/* MCP77 */
406441577efSTejun Heo 	{ PCI_VDEVICE(NVIDIA, 0x0ad5), board_ahci_mcp77 },	/* MCP77 */
407441577efSTejun Heo 	{ PCI_VDEVICE(NVIDIA, 0x0ad6), board_ahci_mcp77 },	/* MCP77 */
408441577efSTejun Heo 	{ PCI_VDEVICE(NVIDIA, 0x0ad7), board_ahci_mcp77 },	/* MCP77 */
409441577efSTejun Heo 	{ PCI_VDEVICE(NVIDIA, 0x0ad8), board_ahci_mcp77 },	/* MCP77 */
410441577efSTejun Heo 	{ PCI_VDEVICE(NVIDIA, 0x0ad9), board_ahci_mcp77 },	/* MCP77 */
411441577efSTejun Heo 	{ PCI_VDEVICE(NVIDIA, 0x0ada), board_ahci_mcp77 },	/* MCP77 */
412441577efSTejun Heo 	{ PCI_VDEVICE(NVIDIA, 0x0adb), board_ahci_mcp77 },	/* MCP77 */
413441577efSTejun Heo 	{ PCI_VDEVICE(NVIDIA, 0x0ab4), board_ahci_mcp79 },	/* MCP79 */
414441577efSTejun Heo 	{ PCI_VDEVICE(NVIDIA, 0x0ab5), board_ahci_mcp79 },	/* MCP79 */
415441577efSTejun Heo 	{ PCI_VDEVICE(NVIDIA, 0x0ab6), board_ahci_mcp79 },	/* MCP79 */
416441577efSTejun Heo 	{ PCI_VDEVICE(NVIDIA, 0x0ab7), board_ahci_mcp79 },	/* MCP79 */
417441577efSTejun Heo 	{ PCI_VDEVICE(NVIDIA, 0x0ab8), board_ahci_mcp79 },	/* MCP79 */
418441577efSTejun Heo 	{ PCI_VDEVICE(NVIDIA, 0x0ab9), board_ahci_mcp79 },	/* MCP79 */
419441577efSTejun Heo 	{ PCI_VDEVICE(NVIDIA, 0x0aba), board_ahci_mcp79 },	/* MCP79 */
420441577efSTejun Heo 	{ PCI_VDEVICE(NVIDIA, 0x0abb), board_ahci_mcp79 },	/* MCP79 */
421441577efSTejun Heo 	{ PCI_VDEVICE(NVIDIA, 0x0abc), board_ahci_mcp79 },	/* MCP79 */
422441577efSTejun Heo 	{ PCI_VDEVICE(NVIDIA, 0x0abd), board_ahci_mcp79 },	/* MCP79 */
423441577efSTejun Heo 	{ PCI_VDEVICE(NVIDIA, 0x0abe), board_ahci_mcp79 },	/* MCP79 */
424441577efSTejun Heo 	{ PCI_VDEVICE(NVIDIA, 0x0abf), board_ahci_mcp79 },	/* MCP79 */
425441577efSTejun Heo 	{ PCI_VDEVICE(NVIDIA, 0x0d84), board_ahci_mcp89 },	/* MCP89 */
426441577efSTejun Heo 	{ PCI_VDEVICE(NVIDIA, 0x0d85), board_ahci_mcp89 },	/* MCP89 */
427441577efSTejun Heo 	{ PCI_VDEVICE(NVIDIA, 0x0d86), board_ahci_mcp89 },	/* MCP89 */
428441577efSTejun Heo 	{ PCI_VDEVICE(NVIDIA, 0x0d87), board_ahci_mcp89 },	/* MCP89 */
429441577efSTejun Heo 	{ PCI_VDEVICE(NVIDIA, 0x0d88), board_ahci_mcp89 },	/* MCP89 */
430441577efSTejun Heo 	{ PCI_VDEVICE(NVIDIA, 0x0d89), board_ahci_mcp89 },	/* MCP89 */
431441577efSTejun Heo 	{ PCI_VDEVICE(NVIDIA, 0x0d8a), board_ahci_mcp89 },	/* MCP89 */
432441577efSTejun Heo 	{ PCI_VDEVICE(NVIDIA, 0x0d8b), board_ahci_mcp89 },	/* MCP89 */
433441577efSTejun Heo 	{ PCI_VDEVICE(NVIDIA, 0x0d8c), board_ahci_mcp89 },	/* MCP89 */
434441577efSTejun Heo 	{ PCI_VDEVICE(NVIDIA, 0x0d8d), board_ahci_mcp89 },	/* MCP89 */
435441577efSTejun Heo 	{ PCI_VDEVICE(NVIDIA, 0x0d8e), board_ahci_mcp89 },	/* MCP89 */
436441577efSTejun Heo 	{ PCI_VDEVICE(NVIDIA, 0x0d8f), board_ahci_mcp89 },	/* MCP89 */
437c6fd2807SJeff Garzik 
438c6fd2807SJeff Garzik 	/* SiS */
43920e2de4aSTejun Heo 	{ PCI_VDEVICE(SI, 0x1184), board_ahci },		/* SiS 966 */
44020e2de4aSTejun Heo 	{ PCI_VDEVICE(SI, 0x1185), board_ahci },		/* SiS 968 */
44120e2de4aSTejun Heo 	{ PCI_VDEVICE(SI, 0x0186), board_ahci },		/* SiS 968 */
442c6fd2807SJeff Garzik 
443318893e1SAlessandro Rubini 	/* ST Microelectronics */
444318893e1SAlessandro Rubini 	{ PCI_VDEVICE(STMICRO, 0xCC06), board_ahci },		/* ST ConneXt */
445318893e1SAlessandro Rubini 
446cd70c266SJeff Garzik 	/* Marvell */
447cd70c266SJeff Garzik 	{ PCI_VDEVICE(MARVELL, 0x6145), board_ahci_mv },	/* 6145 */
448c40e7cb8SJose Alberto Reguero 	{ PCI_VDEVICE(MARVELL, 0x6121), board_ahci_mv },	/* 6121 */
44969fd3157SMyron Stowe 	{ PCI_DEVICE(PCI_VENDOR_ID_MARVELL_EXT, 0x9123),
45010aca06cSAnssi Hannula 	  .class = PCI_CLASS_STORAGE_SATA_AHCI,
45110aca06cSAnssi Hannula 	  .class_mask = 0xffffff,
4525f173107STejun Heo 	  .driver_data = board_ahci_yes_fbs },			/* 88se9128 */
45369fd3157SMyron Stowe 	{ PCI_DEVICE(PCI_VENDOR_ID_MARVELL_EXT, 0x9125),
454467b41c6SPer Jessen 	  .driver_data = board_ahci_yes_fbs },			/* 88se9125 */
455e098f5cbSSimon Guinot 	{ PCI_DEVICE_SUB(PCI_VENDOR_ID_MARVELL_EXT, 0x9178,
456e098f5cbSSimon Guinot 			 PCI_VENDOR_ID_MARVELL_EXT, 0x9170),
457e098f5cbSSimon Guinot 	  .driver_data = board_ahci_yes_fbs },			/* 88se9170 */
45869fd3157SMyron Stowe 	{ PCI_DEVICE(PCI_VENDOR_ID_MARVELL_EXT, 0x917a),
459642d8925SMatt Johnson 	  .driver_data = board_ahci_yes_fbs },			/* 88se9172 */
460fcce9a35SGeorge Spelvin 	{ PCI_DEVICE(PCI_VENDOR_ID_MARVELL_EXT, 0x9172),
461c5edfff9SMurali Karicheri 	  .driver_data = board_ahci_yes_fbs },			/* 88se9182 */
462c5edfff9SMurali Karicheri 	{ PCI_DEVICE(PCI_VENDOR_ID_MARVELL_EXT, 0x9182),
463fcce9a35SGeorge Spelvin 	  .driver_data = board_ahci_yes_fbs },			/* 88se9172 */
46469fd3157SMyron Stowe 	{ PCI_DEVICE(PCI_VENDOR_ID_MARVELL_EXT, 0x9192),
46517c60c6bSAlan Cox 	  .driver_data = board_ahci_yes_fbs },			/* 88se9172 on some Gigabyte */
466754a292fSAndreas Schrägle 	{ PCI_DEVICE(PCI_VENDOR_ID_MARVELL_EXT, 0x91a0),
467754a292fSAndreas Schrägle 	  .driver_data = board_ahci_yes_fbs },
46869fd3157SMyron Stowe 	{ PCI_DEVICE(PCI_VENDOR_ID_MARVELL_EXT, 0x91a3),
46950be5e36STejun Heo 	  .driver_data = board_ahci_yes_fbs },
4706d5278a6SSamir Benmendil 	{ PCI_DEVICE(PCI_VENDOR_ID_MARVELL_EXT, 0x9230),
4716d5278a6SSamir Benmendil 	  .driver_data = board_ahci_yes_fbs },
472d2518365SJérôme Carretero 	{ PCI_DEVICE(PCI_VENDOR_ID_TTI, 0x0642),
473d2518365SJérôme Carretero 	  .driver_data = board_ahci_yes_fbs },
474cd70c266SJeff Garzik 
475c77a036bSMark Nelson 	/* Promise */
476c77a036bSMark Nelson 	{ PCI_VDEVICE(PROMISE, 0x3f20), board_ahci },	/* PDC42819 */
477b32bfc06SRomain Degez 	{ PCI_VDEVICE(PROMISE, 0x3781), board_ahci },   /* FastTrak TX8660 ahci-mode */
478c77a036bSMark Nelson 
479c9703765SKeng-Yu Lin 	/* Asmedia */
4807b4f6ecaSAlan Cox 	{ PCI_VDEVICE(ASMEDIA, 0x0601), board_ahci },	/* ASM1060 */
4817b4f6ecaSAlan Cox 	{ PCI_VDEVICE(ASMEDIA, 0x0602), board_ahci },	/* ASM1060 */
4827b4f6ecaSAlan Cox 	{ PCI_VDEVICE(ASMEDIA, 0x0611), board_ahci },	/* ASM1061 */
4837b4f6ecaSAlan Cox 	{ PCI_VDEVICE(ASMEDIA, 0x0612), board_ahci },	/* ASM1062 */
484c9703765SKeng-Yu Lin 
48567809f85SLevente Kurusa 	/*
486*66a7cbc3STejun Heo 	 * Samsung SSDs found on some macbooks.  NCQ times out if MSI is
487*66a7cbc3STejun Heo 	 * enabled.  https://bugzilla.kernel.org/show_bug.cgi?id=60731
48867809f85SLevente Kurusa 	 */
489*66a7cbc3STejun Heo 	{ PCI_VDEVICE(SAMSUNG, 0x1600), board_ahci_nomsi },
49067809f85SLevente Kurusa 
4917f9c9f8eSHugh Daschbach 	/* Enmotus */
4927f9c9f8eSHugh Daschbach 	{ PCI_DEVICE(0x1c44, 0x8000), board_ahci },
4937f9c9f8eSHugh Daschbach 
494415ae2b5SJeff Garzik 	/* Generic, PCI class code for AHCI */
495415ae2b5SJeff Garzik 	{ PCI_ANY_ID, PCI_ANY_ID, PCI_ANY_ID, PCI_ANY_ID,
496c9f89475SConke Hu 	  PCI_CLASS_STORAGE_SATA_AHCI, 0xffffff, board_ahci },
497415ae2b5SJeff Garzik 
498c6fd2807SJeff Garzik 	{ }	/* terminate list */
499c6fd2807SJeff Garzik };
500c6fd2807SJeff Garzik 
501c6fd2807SJeff Garzik 
502c6fd2807SJeff Garzik static struct pci_driver ahci_pci_driver = {
503c6fd2807SJeff Garzik 	.name			= DRV_NAME,
504c6fd2807SJeff Garzik 	.id_table		= ahci_pci_tbl,
505c6fd2807SJeff Garzik 	.probe			= ahci_init_one,
50624dc5f33STejun Heo 	.remove			= ata_pci_remove_one,
507438ac6d5STejun Heo #ifdef CONFIG_PM
508c6fd2807SJeff Garzik 	.suspend		= ahci_pci_device_suspend,
509c6fd2807SJeff Garzik 	.resume			= ahci_pci_device_resume,
510438ac6d5STejun Heo #endif
511c6fd2807SJeff Garzik };
512c6fd2807SJeff Garzik 
5135b66c829SAlan Cox #if defined(CONFIG_PATA_MARVELL) || defined(CONFIG_PATA_MARVELL_MODULE)
5145b66c829SAlan Cox static int marvell_enable;
5155b66c829SAlan Cox #else
5165b66c829SAlan Cox static int marvell_enable = 1;
5175b66c829SAlan Cox #endif
5185b66c829SAlan Cox module_param(marvell_enable, int, 0644);
5195b66c829SAlan Cox MODULE_PARM_DESC(marvell_enable, "Marvell SATA via AHCI (1 = enabled)");
5205b66c829SAlan Cox 
5215b66c829SAlan Cox 
522394d6e53SAnton Vorontsov static void ahci_pci_save_initial_config(struct pci_dev *pdev,
523394d6e53SAnton Vorontsov 					 struct ahci_host_priv *hpriv)
524394d6e53SAnton Vorontsov {
525394d6e53SAnton Vorontsov 	unsigned int force_port_map = 0;
526394d6e53SAnton Vorontsov 	unsigned int mask_port_map = 0;
527394d6e53SAnton Vorontsov 
528394d6e53SAnton Vorontsov 	if (pdev->vendor == PCI_VENDOR_ID_JMICRON && pdev->device == 0x2361) {
529394d6e53SAnton Vorontsov 		dev_info(&pdev->dev, "JMB361 has only one port\n");
530394d6e53SAnton Vorontsov 		force_port_map = 1;
531394d6e53SAnton Vorontsov 	}
532394d6e53SAnton Vorontsov 
533394d6e53SAnton Vorontsov 	/*
534394d6e53SAnton Vorontsov 	 * Temporary Marvell 6145 hack: PATA port presence
535394d6e53SAnton Vorontsov 	 * is asserted through the standard AHCI port
536394d6e53SAnton Vorontsov 	 * presence register, as bit 4 (counting from 0)
537394d6e53SAnton Vorontsov 	 */
538394d6e53SAnton Vorontsov 	if (hpriv->flags & AHCI_HFLAG_MV_PATA) {
539394d6e53SAnton Vorontsov 		if (pdev->device == 0x6121)
540394d6e53SAnton Vorontsov 			mask_port_map = 0x3;
541394d6e53SAnton Vorontsov 		else
542394d6e53SAnton Vorontsov 			mask_port_map = 0xf;
543394d6e53SAnton Vorontsov 		dev_info(&pdev->dev,
544394d6e53SAnton Vorontsov 			  "Disabling your PATA port. Use the boot option 'ahci.marvell_enable=0' to avoid this.\n");
545394d6e53SAnton Vorontsov 	}
546394d6e53SAnton Vorontsov 
547725c7b57SAntoine Ténart 	ahci_save_initial_config(&pdev->dev, hpriv);
548394d6e53SAnton Vorontsov }
549394d6e53SAnton Vorontsov 
5503303040dSAnton Vorontsov static int ahci_pci_reset_controller(struct ata_host *host)
5513303040dSAnton Vorontsov {
5523303040dSAnton Vorontsov 	struct pci_dev *pdev = to_pci_dev(host->dev);
5533303040dSAnton Vorontsov 
5543303040dSAnton Vorontsov 	ahci_reset_controller(host);
5553303040dSAnton Vorontsov 
556c6fd2807SJeff Garzik 	if (pdev->vendor == PCI_VENDOR_ID_INTEL) {
5573303040dSAnton Vorontsov 		struct ahci_host_priv *hpriv = host->private_data;
558c6fd2807SJeff Garzik 		u16 tmp16;
559c6fd2807SJeff Garzik 
560c6fd2807SJeff Garzik 		/* configure PCS */
561c6fd2807SJeff Garzik 		pci_read_config_word(pdev, 0x92, &tmp16);
56249f29090STejun Heo 		if ((tmp16 & hpriv->port_map) != hpriv->port_map) {
56349f29090STejun Heo 			tmp16 |= hpriv->port_map;
564c6fd2807SJeff Garzik 			pci_write_config_word(pdev, 0x92, tmp16);
565c6fd2807SJeff Garzik 		}
56649f29090STejun Heo 	}
567c6fd2807SJeff Garzik 
568c6fd2807SJeff Garzik 	return 0;
569c6fd2807SJeff Garzik }
570c6fd2807SJeff Garzik 
571781d6550SAnton Vorontsov static void ahci_pci_init_controller(struct ata_host *host)
572781d6550SAnton Vorontsov {
573781d6550SAnton Vorontsov 	struct ahci_host_priv *hpriv = host->private_data;
574781d6550SAnton Vorontsov 	struct pci_dev *pdev = to_pci_dev(host->dev);
575781d6550SAnton Vorontsov 	void __iomem *port_mmio;
576781d6550SAnton Vorontsov 	u32 tmp;
577c40e7cb8SJose Alberto Reguero 	int mv;
5782bcd866bSJeff Garzik 
579417a1a6dSTejun Heo 	if (hpriv->flags & AHCI_HFLAG_MV_PATA) {
580c40e7cb8SJose Alberto Reguero 		if (pdev->device == 0x6121)
581c40e7cb8SJose Alberto Reguero 			mv = 2;
582c40e7cb8SJose Alberto Reguero 		else
583c40e7cb8SJose Alberto Reguero 			mv = 4;
584c40e7cb8SJose Alberto Reguero 		port_mmio = __ahci_port_base(host, mv);
585cd70c266SJeff Garzik 
586cd70c266SJeff Garzik 		writel(0, port_mmio + PORT_IRQ_MASK);
587cd70c266SJeff Garzik 
588cd70c266SJeff Garzik 		/* clear port IRQ */
589cd70c266SJeff Garzik 		tmp = readl(port_mmio + PORT_IRQ_STAT);
590cd70c266SJeff Garzik 		VPRINTK("PORT_IRQ_STAT 0x%x\n", tmp);
591cd70c266SJeff Garzik 		if (tmp)
592cd70c266SJeff Garzik 			writel(tmp, port_mmio + PORT_IRQ_STAT);
593cd70c266SJeff Garzik 	}
594cd70c266SJeff Garzik 
595781d6550SAnton Vorontsov 	ahci_init_controller(host);
596c6fd2807SJeff Garzik }
597c6fd2807SJeff Garzik 
598cc0680a5STejun Heo static int ahci_vt8251_hardreset(struct ata_link *link, unsigned int *class,
599d4b2bab4STejun Heo 				 unsigned long deadline)
600ad616ffbSTejun Heo {
601cc0680a5STejun Heo 	struct ata_port *ap = link->ap;
602039ece38SHans de Goede 	struct ahci_host_priv *hpriv = ap->host->private_data;
6039dadd45bSTejun Heo 	bool online;
604ad616ffbSTejun Heo 	int rc;
605ad616ffbSTejun Heo 
606ad616ffbSTejun Heo 	DPRINTK("ENTER\n");
607ad616ffbSTejun Heo 
6084447d351STejun Heo 	ahci_stop_engine(ap);
609ad616ffbSTejun Heo 
610cc0680a5STejun Heo 	rc = sata_link_hardreset(link, sata_ehc_deb_timing(&link->eh_context),
6119dadd45bSTejun Heo 				 deadline, &online, NULL);
612ad616ffbSTejun Heo 
613039ece38SHans de Goede 	hpriv->start_engine(ap);
614ad616ffbSTejun Heo 
615ad616ffbSTejun Heo 	DPRINTK("EXIT, rc=%d, class=%u\n", rc, *class);
616ad616ffbSTejun Heo 
617ad616ffbSTejun Heo 	/* vt8251 doesn't clear BSY on signature FIS reception,
618ad616ffbSTejun Heo 	 * request follow-up softreset.
619ad616ffbSTejun Heo 	 */
6209dadd45bSTejun Heo 	return online ? -EAGAIN : rc;
621ad616ffbSTejun Heo }
622ad616ffbSTejun Heo 
623edc93052STejun Heo static int ahci_p5wdh_hardreset(struct ata_link *link, unsigned int *class,
624edc93052STejun Heo 				unsigned long deadline)
625edc93052STejun Heo {
626edc93052STejun Heo 	struct ata_port *ap = link->ap;
627edc93052STejun Heo 	struct ahci_port_priv *pp = ap->private_data;
628039ece38SHans de Goede 	struct ahci_host_priv *hpriv = ap->host->private_data;
629edc93052STejun Heo 	u8 *d2h_fis = pp->rx_fis + RX_FIS_D2H_REG;
630edc93052STejun Heo 	struct ata_taskfile tf;
6319dadd45bSTejun Heo 	bool online;
632edc93052STejun Heo 	int rc;
633edc93052STejun Heo 
634edc93052STejun Heo 	ahci_stop_engine(ap);
635edc93052STejun Heo 
636edc93052STejun Heo 	/* clear D2H reception area to properly wait for D2H FIS */
637edc93052STejun Heo 	ata_tf_init(link->device, &tf);
6389bbb1b0eSSergei Shtylyov 	tf.command = ATA_BUSY;
639edc93052STejun Heo 	ata_tf_to_fis(&tf, 0, 0, d2h_fis);
640edc93052STejun Heo 
641edc93052STejun Heo 	rc = sata_link_hardreset(link, sata_ehc_deb_timing(&link->eh_context),
6429dadd45bSTejun Heo 				 deadline, &online, NULL);
643edc93052STejun Heo 
644039ece38SHans de Goede 	hpriv->start_engine(ap);
645edc93052STejun Heo 
646edc93052STejun Heo 	/* The pseudo configuration device on SIMG4726 attached to
647edc93052STejun Heo 	 * ASUS P5W-DH Deluxe doesn't send signature FIS after
648edc93052STejun Heo 	 * hardreset if no device is attached to the first downstream
649edc93052STejun Heo 	 * port && the pseudo device locks up on SRST w/ PMP==0.  To
650edc93052STejun Heo 	 * work around this, wait for !BSY only briefly.  If BSY isn't
651edc93052STejun Heo 	 * cleared, perform CLO and proceed to IDENTIFY (achieved by
652edc93052STejun Heo 	 * ATA_LFLAG_NO_SRST and ATA_LFLAG_ASSUME_ATA).
653edc93052STejun Heo 	 *
654edc93052STejun Heo 	 * Wait for two seconds.  Devices attached to downstream port
655edc93052STejun Heo 	 * which can't process the following IDENTIFY after this will
656edc93052STejun Heo 	 * have to be reset again.  For most cases, this should
657edc93052STejun Heo 	 * suffice while making probing snappish enough.
658edc93052STejun Heo 	 */
6599dadd45bSTejun Heo 	if (online) {
6609dadd45bSTejun Heo 		rc = ata_wait_after_reset(link, jiffies + 2 * HZ,
6619dadd45bSTejun Heo 					  ahci_check_ready);
662edc93052STejun Heo 		if (rc)
66378d5ae39SShane Huang 			ahci_kick_engine(ap);
6649dadd45bSTejun Heo 	}
6659dadd45bSTejun Heo 	return rc;
666edc93052STejun Heo }
667edc93052STejun Heo 
668438ac6d5STejun Heo #ifdef CONFIG_PM
669c6fd2807SJeff Garzik static int ahci_pci_device_suspend(struct pci_dev *pdev, pm_message_t mesg)
670c6fd2807SJeff Garzik {
6710a86e1c8SJingoo Han 	struct ata_host *host = pci_get_drvdata(pdev);
6729b10ae86STejun Heo 	struct ahci_host_priv *hpriv = host->private_data;
673d8993349SAnton Vorontsov 	void __iomem *mmio = hpriv->mmio;
674c6fd2807SJeff Garzik 	u32 ctl;
675c6fd2807SJeff Garzik 
6769b10ae86STejun Heo 	if (mesg.event & PM_EVENT_SUSPEND &&
6779b10ae86STejun Heo 	    hpriv->flags & AHCI_HFLAG_NO_SUSPEND) {
678a44fec1fSJoe Perches 		dev_err(&pdev->dev,
6799b10ae86STejun Heo 			"BIOS update required for suspend/resume\n");
6809b10ae86STejun Heo 		return -EIO;
6819b10ae86STejun Heo 	}
6829b10ae86STejun Heo 
6833a2d5b70SRafael J. Wysocki 	if (mesg.event & PM_EVENT_SLEEP) {
684c6fd2807SJeff Garzik 		/* AHCI spec rev1.1 section 8.3.3:
685c6fd2807SJeff Garzik 		 * Software must disable interrupts prior to requesting a
686c6fd2807SJeff Garzik 		 * transition of the HBA to D3 state.
687c6fd2807SJeff Garzik 		 */
688c6fd2807SJeff Garzik 		ctl = readl(mmio + HOST_CTL);
689c6fd2807SJeff Garzik 		ctl &= ~HOST_IRQ_EN;
690c6fd2807SJeff Garzik 		writel(ctl, mmio + HOST_CTL);
691c6fd2807SJeff Garzik 		readl(mmio + HOST_CTL); /* flush */
692c6fd2807SJeff Garzik 	}
693c6fd2807SJeff Garzik 
694c6fd2807SJeff Garzik 	return ata_pci_device_suspend(pdev, mesg);
695c6fd2807SJeff Garzik }
696c6fd2807SJeff Garzik 
697c6fd2807SJeff Garzik static int ahci_pci_device_resume(struct pci_dev *pdev)
698c6fd2807SJeff Garzik {
6990a86e1c8SJingoo Han 	struct ata_host *host = pci_get_drvdata(pdev);
700c6fd2807SJeff Garzik 	int rc;
701c6fd2807SJeff Garzik 
702553c4aa6STejun Heo 	rc = ata_pci_device_do_resume(pdev);
703553c4aa6STejun Heo 	if (rc)
704553c4aa6STejun Heo 		return rc;
705c6fd2807SJeff Garzik 
706cb85696dSJames Laird 	/* Apple BIOS helpfully mangles the registers on resume */
707cb85696dSJames Laird 	if (is_mcp89_apple(pdev))
708cb85696dSJames Laird 		ahci_mcp89_apple_enable(pdev);
709cb85696dSJames Laird 
710c6fd2807SJeff Garzik 	if (pdev->dev.power.power_state.event == PM_EVENT_SUSPEND) {
7113303040dSAnton Vorontsov 		rc = ahci_pci_reset_controller(host);
712c6fd2807SJeff Garzik 		if (rc)
713c6fd2807SJeff Garzik 			return rc;
714c6fd2807SJeff Garzik 
715781d6550SAnton Vorontsov 		ahci_pci_init_controller(host);
716c6fd2807SJeff Garzik 	}
717c6fd2807SJeff Garzik 
718cca3974eSJeff Garzik 	ata_host_resume(host);
719c6fd2807SJeff Garzik 
720c6fd2807SJeff Garzik 	return 0;
721c6fd2807SJeff Garzik }
722438ac6d5STejun Heo #endif
723c6fd2807SJeff Garzik 
7244447d351STejun Heo static int ahci_configure_dma_masks(struct pci_dev *pdev, int using_dac)
725c6fd2807SJeff Garzik {
726c6fd2807SJeff Garzik 	int rc;
727c6fd2807SJeff Garzik 
728318893e1SAlessandro Rubini 	/*
729318893e1SAlessandro Rubini 	 * If the device fixup already set the dma_mask to some non-standard
730318893e1SAlessandro Rubini 	 * value, don't extend it here. This happens on STA2X11, for example.
731318893e1SAlessandro Rubini 	 */
732318893e1SAlessandro Rubini 	if (pdev->dma_mask && pdev->dma_mask < DMA_BIT_MASK(32))
733318893e1SAlessandro Rubini 		return 0;
734318893e1SAlessandro Rubini 
735c6fd2807SJeff Garzik 	if (using_dac &&
7366a35528aSYang Hongyang 	    !pci_set_dma_mask(pdev, DMA_BIT_MASK(64))) {
7376a35528aSYang Hongyang 		rc = pci_set_consistent_dma_mask(pdev, DMA_BIT_MASK(64));
738c6fd2807SJeff Garzik 		if (rc) {
739284901a9SYang Hongyang 			rc = pci_set_consistent_dma_mask(pdev, DMA_BIT_MASK(32));
740c6fd2807SJeff Garzik 			if (rc) {
741a44fec1fSJoe Perches 				dev_err(&pdev->dev,
742c6fd2807SJeff Garzik 					"64-bit DMA enable failed\n");
743c6fd2807SJeff Garzik 				return rc;
744c6fd2807SJeff Garzik 			}
745c6fd2807SJeff Garzik 		}
746c6fd2807SJeff Garzik 	} else {
747284901a9SYang Hongyang 		rc = pci_set_dma_mask(pdev, DMA_BIT_MASK(32));
748c6fd2807SJeff Garzik 		if (rc) {
749a44fec1fSJoe Perches 			dev_err(&pdev->dev, "32-bit DMA enable failed\n");
750c6fd2807SJeff Garzik 			return rc;
751c6fd2807SJeff Garzik 		}
752284901a9SYang Hongyang 		rc = pci_set_consistent_dma_mask(pdev, DMA_BIT_MASK(32));
753c6fd2807SJeff Garzik 		if (rc) {
754a44fec1fSJoe Perches 			dev_err(&pdev->dev,
755c6fd2807SJeff Garzik 				"32-bit consistent DMA enable failed\n");
756c6fd2807SJeff Garzik 			return rc;
757c6fd2807SJeff Garzik 		}
758c6fd2807SJeff Garzik 	}
759c6fd2807SJeff Garzik 	return 0;
760c6fd2807SJeff Garzik }
761c6fd2807SJeff Garzik 
762439fcaecSAnton Vorontsov static void ahci_pci_print_info(struct ata_host *host)
763439fcaecSAnton Vorontsov {
764439fcaecSAnton Vorontsov 	struct pci_dev *pdev = to_pci_dev(host->dev);
765439fcaecSAnton Vorontsov 	u16 cc;
766439fcaecSAnton Vorontsov 	const char *scc_s;
767439fcaecSAnton Vorontsov 
768439fcaecSAnton Vorontsov 	pci_read_config_word(pdev, 0x0a, &cc);
769439fcaecSAnton Vorontsov 	if (cc == PCI_CLASS_STORAGE_IDE)
770439fcaecSAnton Vorontsov 		scc_s = "IDE";
771439fcaecSAnton Vorontsov 	else if (cc == PCI_CLASS_STORAGE_SATA)
772439fcaecSAnton Vorontsov 		scc_s = "SATA";
773439fcaecSAnton Vorontsov 	else if (cc == PCI_CLASS_STORAGE_RAID)
774439fcaecSAnton Vorontsov 		scc_s = "RAID";
775439fcaecSAnton Vorontsov 	else
776439fcaecSAnton Vorontsov 		scc_s = "unknown";
777439fcaecSAnton Vorontsov 
778439fcaecSAnton Vorontsov 	ahci_print_info(host, scc_s);
779439fcaecSAnton Vorontsov }
780439fcaecSAnton Vorontsov 
781edc93052STejun Heo /* On ASUS P5W DH Deluxe, the second port of PCI device 00:1f.2 is
782edc93052STejun Heo  * hardwired to on-board SIMG 4726.  The chipset is ICH8 and doesn't
783edc93052STejun Heo  * support PMP and the 4726 either directly exports the device
784edc93052STejun Heo  * attached to the first downstream port or acts as a hardware storage
785edc93052STejun Heo  * controller and emulate a single ATA device (can be RAID 0/1 or some
786edc93052STejun Heo  * other configuration).
787edc93052STejun Heo  *
788edc93052STejun Heo  * When there's no device attached to the first downstream port of the
789edc93052STejun Heo  * 4726, "Config Disk" appears, which is a pseudo ATA device to
790edc93052STejun Heo  * configure the 4726.  However, ATA emulation of the device is very
791edc93052STejun Heo  * lame.  It doesn't send signature D2H Reg FIS after the initial
792edc93052STejun Heo  * hardreset, pukes on SRST w/ PMP==0 and has bunch of other issues.
793edc93052STejun Heo  *
794edc93052STejun Heo  * The following function works around the problem by always using
795edc93052STejun Heo  * hardreset on the port and not depending on receiving signature FIS
796edc93052STejun Heo  * afterward.  If signature FIS isn't received soon, ATA class is
797edc93052STejun Heo  * assumed without follow-up softreset.
798edc93052STejun Heo  */
799edc93052STejun Heo static void ahci_p5wdh_workaround(struct ata_host *host)
800edc93052STejun Heo {
8011bd06867SMathias Krause 	static const struct dmi_system_id sysids[] = {
802edc93052STejun Heo 		{
803edc93052STejun Heo 			.ident = "P5W DH Deluxe",
804edc93052STejun Heo 			.matches = {
805edc93052STejun Heo 				DMI_MATCH(DMI_SYS_VENDOR,
806edc93052STejun Heo 					  "ASUSTEK COMPUTER INC"),
807edc93052STejun Heo 				DMI_MATCH(DMI_PRODUCT_NAME, "P5W DH Deluxe"),
808edc93052STejun Heo 			},
809edc93052STejun Heo 		},
810edc93052STejun Heo 		{ }
811edc93052STejun Heo 	};
812edc93052STejun Heo 	struct pci_dev *pdev = to_pci_dev(host->dev);
813edc93052STejun Heo 
814edc93052STejun Heo 	if (pdev->bus->number == 0 && pdev->devfn == PCI_DEVFN(0x1f, 2) &&
815edc93052STejun Heo 	    dmi_check_system(sysids)) {
816edc93052STejun Heo 		struct ata_port *ap = host->ports[1];
817edc93052STejun Heo 
818a44fec1fSJoe Perches 		dev_info(&pdev->dev,
819a44fec1fSJoe Perches 			 "enabling ASUS P5W DH Deluxe on-board SIMG4726 workaround\n");
820edc93052STejun Heo 
821edc93052STejun Heo 		ap->ops = &ahci_p5wdh_ops;
822edc93052STejun Heo 		ap->link.flags |= ATA_LFLAG_NO_SRST | ATA_LFLAG_ASSUME_ATA;
823edc93052STejun Heo 	}
824edc93052STejun Heo }
825edc93052STejun Heo 
826cb85696dSJames Laird /*
827cb85696dSJames Laird  * Macbook7,1 firmware forcibly disables MCP89 AHCI and changes PCI ID when
828cb85696dSJames Laird  * booting in BIOS compatibility mode.  We restore the registers but not ID.
829cb85696dSJames Laird  */
830cb85696dSJames Laird static void ahci_mcp89_apple_enable(struct pci_dev *pdev)
831cb85696dSJames Laird {
832cb85696dSJames Laird 	u32 val;
833cb85696dSJames Laird 
834cb85696dSJames Laird 	printk(KERN_INFO "ahci: enabling MCP89 AHCI mode\n");
835cb85696dSJames Laird 
836cb85696dSJames Laird 	pci_read_config_dword(pdev, 0xf8, &val);
837cb85696dSJames Laird 	val |= 1 << 0x1b;
838cb85696dSJames Laird 	/* the following changes the device ID, but appears not to affect function */
839cb85696dSJames Laird 	/* val = (val & ~0xf0000000) | 0x80000000; */
840cb85696dSJames Laird 	pci_write_config_dword(pdev, 0xf8, val);
841cb85696dSJames Laird 
842cb85696dSJames Laird 	pci_read_config_dword(pdev, 0x54c, &val);
843cb85696dSJames Laird 	val |= 1 << 0xc;
844cb85696dSJames Laird 	pci_write_config_dword(pdev, 0x54c, val);
845cb85696dSJames Laird 
846cb85696dSJames Laird 	pci_read_config_dword(pdev, 0x4a4, &val);
847cb85696dSJames Laird 	val &= 0xff;
848cb85696dSJames Laird 	val |= 0x01060100;
849cb85696dSJames Laird 	pci_write_config_dword(pdev, 0x4a4, val);
850cb85696dSJames Laird 
851cb85696dSJames Laird 	pci_read_config_dword(pdev, 0x54c, &val);
852cb85696dSJames Laird 	val &= ~(1 << 0xc);
853cb85696dSJames Laird 	pci_write_config_dword(pdev, 0x54c, val);
854cb85696dSJames Laird 
855cb85696dSJames Laird 	pci_read_config_dword(pdev, 0xf8, &val);
856cb85696dSJames Laird 	val &= ~(1 << 0x1b);
857cb85696dSJames Laird 	pci_write_config_dword(pdev, 0xf8, val);
858cb85696dSJames Laird }
859cb85696dSJames Laird 
860cb85696dSJames Laird static bool is_mcp89_apple(struct pci_dev *pdev)
861cb85696dSJames Laird {
862cb85696dSJames Laird 	return pdev->vendor == PCI_VENDOR_ID_NVIDIA &&
863cb85696dSJames Laird 		pdev->device == PCI_DEVICE_ID_NVIDIA_NFORCE_MCP89_SATA &&
864cb85696dSJames Laird 		pdev->subsystem_vendor == PCI_VENDOR_ID_APPLE &&
865cb85696dSJames Laird 		pdev->subsystem_device == 0xcb89;
866cb85696dSJames Laird }
867cb85696dSJames Laird 
8682fcad9d2STejun Heo /* only some SB600 ahci controllers can do 64bit DMA */
8692fcad9d2STejun Heo static bool ahci_sb600_enable_64bit(struct pci_dev *pdev)
87058a09b38SShane Huang {
87158a09b38SShane Huang 	static const struct dmi_system_id sysids[] = {
87203d783bfSTejun Heo 		/*
87303d783bfSTejun Heo 		 * The oldest version known to be broken is 0901 and
87403d783bfSTejun Heo 		 * working is 1501 which was released on 2007-10-26.
8752fcad9d2STejun Heo 		 * Enable 64bit DMA on 1501 and anything newer.
8762fcad9d2STejun Heo 		 *
87703d783bfSTejun Heo 		 * Please read bko#9412 for more info.
87803d783bfSTejun Heo 		 */
87958a09b38SShane Huang 		{
88058a09b38SShane Huang 			.ident = "ASUS M2A-VM",
88158a09b38SShane Huang 			.matches = {
88258a09b38SShane Huang 				DMI_MATCH(DMI_BOARD_VENDOR,
88358a09b38SShane Huang 					  "ASUSTeK Computer INC."),
88458a09b38SShane Huang 				DMI_MATCH(DMI_BOARD_NAME, "M2A-VM"),
88558a09b38SShane Huang 			},
88603d783bfSTejun Heo 			.driver_data = "20071026",	/* yyyymmdd */
88758a09b38SShane Huang 		},
888e65cc194SMark Nelson 		/*
889e65cc194SMark Nelson 		 * All BIOS versions for the MSI K9A2 Platinum (MS-7376)
890e65cc194SMark Nelson 		 * support 64bit DMA.
891e65cc194SMark Nelson 		 *
892e65cc194SMark Nelson 		 * BIOS versions earlier than 1.5 had the Manufacturer DMI
893e65cc194SMark Nelson 		 * fields as "MICRO-STAR INTERANTIONAL CO.,LTD".
894e65cc194SMark Nelson 		 * This spelling mistake was fixed in BIOS version 1.5, so
895e65cc194SMark Nelson 		 * 1.5 and later have the Manufacturer as
896e65cc194SMark Nelson 		 * "MICRO-STAR INTERNATIONAL CO.,LTD".
897e65cc194SMark Nelson 		 * So try to match on DMI_BOARD_VENDOR of "MICRO-STAR INTER".
898e65cc194SMark Nelson 		 *
899e65cc194SMark Nelson 		 * BIOS versions earlier than 1.9 had a Board Product Name
900e65cc194SMark Nelson 		 * DMI field of "MS-7376". This was changed to be
901e65cc194SMark Nelson 		 * "K9A2 Platinum (MS-7376)" in version 1.9, but we can still
902e65cc194SMark Nelson 		 * match on DMI_BOARD_NAME of "MS-7376".
903e65cc194SMark Nelson 		 */
904e65cc194SMark Nelson 		{
905e65cc194SMark Nelson 			.ident = "MSI K9A2 Platinum",
906e65cc194SMark Nelson 			.matches = {
907e65cc194SMark Nelson 				DMI_MATCH(DMI_BOARD_VENDOR,
908e65cc194SMark Nelson 					  "MICRO-STAR INTER"),
909e65cc194SMark Nelson 				DMI_MATCH(DMI_BOARD_NAME, "MS-7376"),
910e65cc194SMark Nelson 			},
911e65cc194SMark Nelson 		},
9123c4aa91fSMark Nelson 		/*
913ff0173c1SMark Nelson 		 * All BIOS versions for the MSI K9AGM2 (MS-7327) support
914ff0173c1SMark Nelson 		 * 64bit DMA.
915ff0173c1SMark Nelson 		 *
916ff0173c1SMark Nelson 		 * This board also had the typo mentioned above in the
917ff0173c1SMark Nelson 		 * Manufacturer DMI field (fixed in BIOS version 1.5), so
918ff0173c1SMark Nelson 		 * match on DMI_BOARD_VENDOR of "MICRO-STAR INTER" again.
919ff0173c1SMark Nelson 		 */
920ff0173c1SMark Nelson 		{
921ff0173c1SMark Nelson 			.ident = "MSI K9AGM2",
922ff0173c1SMark Nelson 			.matches = {
923ff0173c1SMark Nelson 				DMI_MATCH(DMI_BOARD_VENDOR,
924ff0173c1SMark Nelson 					  "MICRO-STAR INTER"),
925ff0173c1SMark Nelson 				DMI_MATCH(DMI_BOARD_NAME, "MS-7327"),
926ff0173c1SMark Nelson 			},
927ff0173c1SMark Nelson 		},
928ff0173c1SMark Nelson 		/*
9293c4aa91fSMark Nelson 		 * All BIOS versions for the Asus M3A support 64bit DMA.
9303c4aa91fSMark Nelson 		 * (all release versions from 0301 to 1206 were tested)
9313c4aa91fSMark Nelson 		 */
9323c4aa91fSMark Nelson 		{
9333c4aa91fSMark Nelson 			.ident = "ASUS M3A",
9343c4aa91fSMark Nelson 			.matches = {
9353c4aa91fSMark Nelson 				DMI_MATCH(DMI_BOARD_VENDOR,
9363c4aa91fSMark Nelson 					  "ASUSTeK Computer INC."),
9373c4aa91fSMark Nelson 				DMI_MATCH(DMI_BOARD_NAME, "M3A"),
9383c4aa91fSMark Nelson 			},
9393c4aa91fSMark Nelson 		},
94058a09b38SShane Huang 		{ }
94158a09b38SShane Huang 	};
94203d783bfSTejun Heo 	const struct dmi_system_id *match;
9432fcad9d2STejun Heo 	int year, month, date;
9442fcad9d2STejun Heo 	char buf[9];
94558a09b38SShane Huang 
94603d783bfSTejun Heo 	match = dmi_first_match(sysids);
94758a09b38SShane Huang 	if (pdev->bus->number != 0 || pdev->devfn != PCI_DEVFN(0x12, 0) ||
94803d783bfSTejun Heo 	    !match)
94958a09b38SShane Huang 		return false;
95058a09b38SShane Huang 
951e65cc194SMark Nelson 	if (!match->driver_data)
952e65cc194SMark Nelson 		goto enable_64bit;
953e65cc194SMark Nelson 
95403d783bfSTejun Heo 	dmi_get_date(DMI_BIOS_DATE, &year, &month, &date);
95503d783bfSTejun Heo 	snprintf(buf, sizeof(buf), "%04d%02d%02d", year, month, date);
95603d783bfSTejun Heo 
957e65cc194SMark Nelson 	if (strcmp(buf, match->driver_data) >= 0)
958e65cc194SMark Nelson 		goto enable_64bit;
959e65cc194SMark Nelson 	else {
960a44fec1fSJoe Perches 		dev_warn(&pdev->dev,
961a44fec1fSJoe Perches 			 "%s: BIOS too old, forcing 32bit DMA, update BIOS\n",
962a44fec1fSJoe Perches 			 match->ident);
9632fcad9d2STejun Heo 		return false;
9642fcad9d2STejun Heo 	}
965e65cc194SMark Nelson 
966e65cc194SMark Nelson enable_64bit:
967a44fec1fSJoe Perches 	dev_warn(&pdev->dev, "%s: enabling 64bit DMA\n", match->ident);
968e65cc194SMark Nelson 	return true;
96958a09b38SShane Huang }
97058a09b38SShane Huang 
9711fd68434SRafael J. Wysocki static bool ahci_broken_system_poweroff(struct pci_dev *pdev)
9721fd68434SRafael J. Wysocki {
9731fd68434SRafael J. Wysocki 	static const struct dmi_system_id broken_systems[] = {
9741fd68434SRafael J. Wysocki 		{
9751fd68434SRafael J. Wysocki 			.ident = "HP Compaq nx6310",
9761fd68434SRafael J. Wysocki 			.matches = {
9771fd68434SRafael J. Wysocki 				DMI_MATCH(DMI_SYS_VENDOR, "Hewlett-Packard"),
9781fd68434SRafael J. Wysocki 				DMI_MATCH(DMI_PRODUCT_NAME, "HP Compaq nx6310"),
9791fd68434SRafael J. Wysocki 			},
9801fd68434SRafael J. Wysocki 			/* PCI slot number of the controller */
9811fd68434SRafael J. Wysocki 			.driver_data = (void *)0x1FUL,
9821fd68434SRafael J. Wysocki 		},
983d2f9c061SMaciej Rutecki 		{
984d2f9c061SMaciej Rutecki 			.ident = "HP Compaq 6720s",
985d2f9c061SMaciej Rutecki 			.matches = {
986d2f9c061SMaciej Rutecki 				DMI_MATCH(DMI_SYS_VENDOR, "Hewlett-Packard"),
987d2f9c061SMaciej Rutecki 				DMI_MATCH(DMI_PRODUCT_NAME, "HP Compaq 6720s"),
988d2f9c061SMaciej Rutecki 			},
989d2f9c061SMaciej Rutecki 			/* PCI slot number of the controller */
990d2f9c061SMaciej Rutecki 			.driver_data = (void *)0x1FUL,
991d2f9c061SMaciej Rutecki 		},
9921fd68434SRafael J. Wysocki 
9931fd68434SRafael J. Wysocki 		{ }	/* terminate list */
9941fd68434SRafael J. Wysocki 	};
9951fd68434SRafael J. Wysocki 	const struct dmi_system_id *dmi = dmi_first_match(broken_systems);
9961fd68434SRafael J. Wysocki 
9971fd68434SRafael J. Wysocki 	if (dmi) {
9981fd68434SRafael J. Wysocki 		unsigned long slot = (unsigned long)dmi->driver_data;
9991fd68434SRafael J. Wysocki 		/* apply the quirk only to on-board controllers */
10001fd68434SRafael J. Wysocki 		return slot == PCI_SLOT(pdev->devfn);
10011fd68434SRafael J. Wysocki 	}
10021fd68434SRafael J. Wysocki 
10031fd68434SRafael J. Wysocki 	return false;
10041fd68434SRafael J. Wysocki }
10051fd68434SRafael J. Wysocki 
10069b10ae86STejun Heo static bool ahci_broken_suspend(struct pci_dev *pdev)
10079b10ae86STejun Heo {
10089b10ae86STejun Heo 	static const struct dmi_system_id sysids[] = {
10099b10ae86STejun Heo 		/*
10109b10ae86STejun Heo 		 * On HP dv[4-6] and HDX18 with earlier BIOSen, link
10119b10ae86STejun Heo 		 * to the harddisk doesn't become online after
10129b10ae86STejun Heo 		 * resuming from STR.  Warn and fail suspend.
10139deb3431STejun Heo 		 *
10149deb3431STejun Heo 		 * http://bugzilla.kernel.org/show_bug.cgi?id=12276
10159deb3431STejun Heo 		 *
10169deb3431STejun Heo 		 * Use dates instead of versions to match as HP is
10179deb3431STejun Heo 		 * apparently recycling both product and version
10189deb3431STejun Heo 		 * strings.
10199deb3431STejun Heo 		 *
10209deb3431STejun Heo 		 * http://bugzilla.kernel.org/show_bug.cgi?id=15462
10219b10ae86STejun Heo 		 */
10229b10ae86STejun Heo 		{
10239b10ae86STejun Heo 			.ident = "dv4",
10249b10ae86STejun Heo 			.matches = {
10259b10ae86STejun Heo 				DMI_MATCH(DMI_SYS_VENDOR, "Hewlett-Packard"),
10269b10ae86STejun Heo 				DMI_MATCH(DMI_PRODUCT_NAME,
10279b10ae86STejun Heo 					  "HP Pavilion dv4 Notebook PC"),
10289b10ae86STejun Heo 			},
10299deb3431STejun Heo 			.driver_data = "20090105",	/* F.30 */
10309b10ae86STejun Heo 		},
10319b10ae86STejun Heo 		{
10329b10ae86STejun Heo 			.ident = "dv5",
10339b10ae86STejun Heo 			.matches = {
10349b10ae86STejun Heo 				DMI_MATCH(DMI_SYS_VENDOR, "Hewlett-Packard"),
10359b10ae86STejun Heo 				DMI_MATCH(DMI_PRODUCT_NAME,
10369b10ae86STejun Heo 					  "HP Pavilion dv5 Notebook PC"),
10379b10ae86STejun Heo 			},
10389deb3431STejun Heo 			.driver_data = "20090506",	/* F.16 */
10399b10ae86STejun Heo 		},
10409b10ae86STejun Heo 		{
10419b10ae86STejun Heo 			.ident = "dv6",
10429b10ae86STejun Heo 			.matches = {
10439b10ae86STejun Heo 				DMI_MATCH(DMI_SYS_VENDOR, "Hewlett-Packard"),
10449b10ae86STejun Heo 				DMI_MATCH(DMI_PRODUCT_NAME,
10459b10ae86STejun Heo 					  "HP Pavilion dv6 Notebook PC"),
10469b10ae86STejun Heo 			},
10479deb3431STejun Heo 			.driver_data = "20090423",	/* F.21 */
10489b10ae86STejun Heo 		},
10499b10ae86STejun Heo 		{
10509b10ae86STejun Heo 			.ident = "HDX18",
10519b10ae86STejun Heo 			.matches = {
10529b10ae86STejun Heo 				DMI_MATCH(DMI_SYS_VENDOR, "Hewlett-Packard"),
10539b10ae86STejun Heo 				DMI_MATCH(DMI_PRODUCT_NAME,
10549b10ae86STejun Heo 					  "HP HDX18 Notebook PC"),
10559b10ae86STejun Heo 			},
10569deb3431STejun Heo 			.driver_data = "20090430",	/* F.23 */
10579b10ae86STejun Heo 		},
1058cedc9bf9STejun Heo 		/*
1059cedc9bf9STejun Heo 		 * Acer eMachines G725 has the same problem.  BIOS
1060cedc9bf9STejun Heo 		 * V1.03 is known to be broken.  V3.04 is known to
106125985edcSLucas De Marchi 		 * work.  Between, there are V1.06, V2.06 and V3.03
1062cedc9bf9STejun Heo 		 * that we don't have much idea about.  For now,
1063cedc9bf9STejun Heo 		 * blacklist anything older than V3.04.
10649deb3431STejun Heo 		 *
10659deb3431STejun Heo 		 * http://bugzilla.kernel.org/show_bug.cgi?id=15104
1066cedc9bf9STejun Heo 		 */
1067cedc9bf9STejun Heo 		{
1068cedc9bf9STejun Heo 			.ident = "G725",
1069cedc9bf9STejun Heo 			.matches = {
1070cedc9bf9STejun Heo 				DMI_MATCH(DMI_SYS_VENDOR, "eMachines"),
1071cedc9bf9STejun Heo 				DMI_MATCH(DMI_PRODUCT_NAME, "eMachines G725"),
1072cedc9bf9STejun Heo 			},
10739deb3431STejun Heo 			.driver_data = "20091216",	/* V3.04 */
1074cedc9bf9STejun Heo 		},
10759b10ae86STejun Heo 		{ }	/* terminate list */
10769b10ae86STejun Heo 	};
10779b10ae86STejun Heo 	const struct dmi_system_id *dmi = dmi_first_match(sysids);
10789deb3431STejun Heo 	int year, month, date;
10799deb3431STejun Heo 	char buf[9];
10809b10ae86STejun Heo 
10819b10ae86STejun Heo 	if (!dmi || pdev->bus->number || pdev->devfn != PCI_DEVFN(0x1f, 2))
10829b10ae86STejun Heo 		return false;
10839b10ae86STejun Heo 
10849deb3431STejun Heo 	dmi_get_date(DMI_BIOS_DATE, &year, &month, &date);
10859deb3431STejun Heo 	snprintf(buf, sizeof(buf), "%04d%02d%02d", year, month, date);
10869b10ae86STejun Heo 
10879deb3431STejun Heo 	return strcmp(buf, dmi->driver_data) < 0;
10889b10ae86STejun Heo }
10899b10ae86STejun Heo 
10905594639aSTejun Heo static bool ahci_broken_online(struct pci_dev *pdev)
10915594639aSTejun Heo {
10925594639aSTejun Heo #define ENCODE_BUSDEVFN(bus, slot, func)			\
10935594639aSTejun Heo 	(void *)(unsigned long)(((bus) << 8) | PCI_DEVFN((slot), (func)))
10945594639aSTejun Heo 	static const struct dmi_system_id sysids[] = {
10955594639aSTejun Heo 		/*
10965594639aSTejun Heo 		 * There are several gigabyte boards which use
10975594639aSTejun Heo 		 * SIMG5723s configured as hardware RAID.  Certain
10985594639aSTejun Heo 		 * 5723 firmware revisions shipped there keep the link
10995594639aSTejun Heo 		 * online but fail to answer properly to SRST or
11005594639aSTejun Heo 		 * IDENTIFY when no device is attached downstream
11015594639aSTejun Heo 		 * causing libata to retry quite a few times leading
11025594639aSTejun Heo 		 * to excessive detection delay.
11035594639aSTejun Heo 		 *
11045594639aSTejun Heo 		 * As these firmwares respond to the second reset try
11055594639aSTejun Heo 		 * with invalid device signature, considering unknown
11065594639aSTejun Heo 		 * sig as offline works around the problem acceptably.
11075594639aSTejun Heo 		 */
11085594639aSTejun Heo 		{
11095594639aSTejun Heo 			.ident = "EP45-DQ6",
11105594639aSTejun Heo 			.matches = {
11115594639aSTejun Heo 				DMI_MATCH(DMI_BOARD_VENDOR,
11125594639aSTejun Heo 					  "Gigabyte Technology Co., Ltd."),
11135594639aSTejun Heo 				DMI_MATCH(DMI_BOARD_NAME, "EP45-DQ6"),
11145594639aSTejun Heo 			},
11155594639aSTejun Heo 			.driver_data = ENCODE_BUSDEVFN(0x0a, 0x00, 0),
11165594639aSTejun Heo 		},
11175594639aSTejun Heo 		{
11185594639aSTejun Heo 			.ident = "EP45-DS5",
11195594639aSTejun Heo 			.matches = {
11205594639aSTejun Heo 				DMI_MATCH(DMI_BOARD_VENDOR,
11215594639aSTejun Heo 					  "Gigabyte Technology Co., Ltd."),
11225594639aSTejun Heo 				DMI_MATCH(DMI_BOARD_NAME, "EP45-DS5"),
11235594639aSTejun Heo 			},
11245594639aSTejun Heo 			.driver_data = ENCODE_BUSDEVFN(0x03, 0x00, 0),
11255594639aSTejun Heo 		},
11265594639aSTejun Heo 		{ }	/* terminate list */
11275594639aSTejun Heo 	};
11285594639aSTejun Heo #undef ENCODE_BUSDEVFN
11295594639aSTejun Heo 	const struct dmi_system_id *dmi = dmi_first_match(sysids);
11305594639aSTejun Heo 	unsigned int val;
11315594639aSTejun Heo 
11325594639aSTejun Heo 	if (!dmi)
11335594639aSTejun Heo 		return false;
11345594639aSTejun Heo 
11355594639aSTejun Heo 	val = (unsigned long)dmi->driver_data;
11365594639aSTejun Heo 
11375594639aSTejun Heo 	return pdev->bus->number == (val >> 8) && pdev->devfn == (val & 0xff);
11385594639aSTejun Heo }
11395594639aSTejun Heo 
11400cf4a7d6SJacob Pan static bool ahci_broken_devslp(struct pci_dev *pdev)
11410cf4a7d6SJacob Pan {
11420cf4a7d6SJacob Pan 	/* device with broken DEVSLP but still showing SDS capability */
11430cf4a7d6SJacob Pan 	static const struct pci_device_id ids[] = {
11440cf4a7d6SJacob Pan 		{ PCI_VDEVICE(INTEL, 0x0f23)}, /* Valleyview SoC */
11450cf4a7d6SJacob Pan 		{}
11460cf4a7d6SJacob Pan 	};
11470cf4a7d6SJacob Pan 
11480cf4a7d6SJacob Pan 	return pci_match_id(ids, pdev);
11490cf4a7d6SJacob Pan }
11500cf4a7d6SJacob Pan 
11518e513217SMarkus Trippelsdorf #ifdef CONFIG_ATA_ACPI
1152f80ae7e4STejun Heo static void ahci_gtf_filter_workaround(struct ata_host *host)
1153f80ae7e4STejun Heo {
1154f80ae7e4STejun Heo 	static const struct dmi_system_id sysids[] = {
1155f80ae7e4STejun Heo 		/*
1156f80ae7e4STejun Heo 		 * Aspire 3810T issues a bunch of SATA enable commands
1157f80ae7e4STejun Heo 		 * via _GTF including an invalid one and one which is
1158f80ae7e4STejun Heo 		 * rejected by the device.  Among the successful ones
1159f80ae7e4STejun Heo 		 * is FPDMA non-zero offset enable which when enabled
1160f80ae7e4STejun Heo 		 * only on the drive side leads to NCQ command
1161f80ae7e4STejun Heo 		 * failures.  Filter it out.
1162f80ae7e4STejun Heo 		 */
1163f80ae7e4STejun Heo 		{
1164f80ae7e4STejun Heo 			.ident = "Aspire 3810T",
1165f80ae7e4STejun Heo 			.matches = {
1166f80ae7e4STejun Heo 				DMI_MATCH(DMI_SYS_VENDOR, "Acer"),
1167f80ae7e4STejun Heo 				DMI_MATCH(DMI_PRODUCT_NAME, "Aspire 3810T"),
1168f80ae7e4STejun Heo 			},
1169f80ae7e4STejun Heo 			.driver_data = (void *)ATA_ACPI_FILTER_FPDMA_OFFSET,
1170f80ae7e4STejun Heo 		},
1171f80ae7e4STejun Heo 		{ }
1172f80ae7e4STejun Heo 	};
1173f80ae7e4STejun Heo 	const struct dmi_system_id *dmi = dmi_first_match(sysids);
1174f80ae7e4STejun Heo 	unsigned int filter;
1175f80ae7e4STejun Heo 	int i;
1176f80ae7e4STejun Heo 
1177f80ae7e4STejun Heo 	if (!dmi)
1178f80ae7e4STejun Heo 		return;
1179f80ae7e4STejun Heo 
1180f80ae7e4STejun Heo 	filter = (unsigned long)dmi->driver_data;
1181a44fec1fSJoe Perches 	dev_info(host->dev, "applying extra ACPI _GTF filter 0x%x for %s\n",
1182f80ae7e4STejun Heo 		 filter, dmi->ident);
1183f80ae7e4STejun Heo 
1184f80ae7e4STejun Heo 	for (i = 0; i < host->n_ports; i++) {
1185f80ae7e4STejun Heo 		struct ata_port *ap = host->ports[i];
1186f80ae7e4STejun Heo 		struct ata_link *link;
1187f80ae7e4STejun Heo 		struct ata_device *dev;
1188f80ae7e4STejun Heo 
1189f80ae7e4STejun Heo 		ata_for_each_link(link, ap, EDGE)
1190f80ae7e4STejun Heo 			ata_for_each_dev(dev, link, ALL)
1191f80ae7e4STejun Heo 				dev->gtf_filter |= filter;
1192f80ae7e4STejun Heo 	}
1193f80ae7e4STejun Heo }
11948e513217SMarkus Trippelsdorf #else
11958e513217SMarkus Trippelsdorf static inline void ahci_gtf_filter_workaround(struct ata_host *host)
11968e513217SMarkus Trippelsdorf {}
11978e513217SMarkus Trippelsdorf #endif
1198f80ae7e4STejun Heo 
1199e1ba8459SLinus Torvalds static int ahci_init_interrupts(struct pci_dev *pdev, unsigned int n_ports,
12007b92b4f6SAlexander Gordeev 				struct ahci_host_priv *hpriv)
12015ca72c4fSAlexander Gordeev {
1202ccf8f53cSAlexander Gordeev 	int rc, nvec;
12035ca72c4fSAlexander Gordeev 
12047b92b4f6SAlexander Gordeev 	if (hpriv->flags & AHCI_HFLAG_NO_MSI)
12057b92b4f6SAlexander Gordeev 		goto intx;
12067b92b4f6SAlexander Gordeev 
1207fc061d96SAlexander Gordeev 	nvec = pci_msi_vec_count(pdev);
1208fc061d96SAlexander Gordeev 	if (nvec < 0)
12097b92b4f6SAlexander Gordeev 		goto intx;
12107b92b4f6SAlexander Gordeev 
12115ca72c4fSAlexander Gordeev 	/*
12127b92b4f6SAlexander Gordeev 	 * If number of MSIs is less than number of ports then Sharing Last
12137b92b4f6SAlexander Gordeev 	 * Message mode could be enforced. In this case assume that advantage
12147b92b4f6SAlexander Gordeev 	 * of multipe MSIs is negated and use single MSI mode instead.
12155ca72c4fSAlexander Gordeev 	 */
1216fc061d96SAlexander Gordeev 	if (nvec < n_ports)
12177b92b4f6SAlexander Gordeev 		goto single_msi;
12185ca72c4fSAlexander Gordeev 
1219ccf8f53cSAlexander Gordeev 	rc = pci_enable_msi_exact(pdev, nvec);
1220ccf8f53cSAlexander Gordeev 	if (rc == -ENOSPC)
1221fc40363bSAlexander Gordeev 		goto single_msi;
1222ccf8f53cSAlexander Gordeev 	else if (rc < 0)
1223fc061d96SAlexander Gordeev 		goto intx;
1224ab0f9e78SAlexander Gordeev 
1225ab0f9e78SAlexander Gordeev 	/* fallback to single MSI mode if the controller enforced MRSM mode */
1226ab0f9e78SAlexander Gordeev 	if (readl(hpriv->mmio + HOST_CTL) & HOST_MRSM) {
1227ab0f9e78SAlexander Gordeev 		pci_disable_msi(pdev);
1228ab0f9e78SAlexander Gordeev 		printk(KERN_INFO "ahci: MRSM is on, fallback to single MSI\n");
1229ab0f9e78SAlexander Gordeev 		goto single_msi;
1230ab0f9e78SAlexander Gordeev 	}
12317b92b4f6SAlexander Gordeev 
1232c3ebd6a9SAlexander Gordeev 	if (nvec > 1)
1233c3ebd6a9SAlexander Gordeev 		hpriv->flags |= AHCI_HFLAG_MULTI_MSI;
1234c3ebd6a9SAlexander Gordeev 
12357b92b4f6SAlexander Gordeev 	return nvec;
12367b92b4f6SAlexander Gordeev 
12377b92b4f6SAlexander Gordeev single_msi:
1238fc061d96SAlexander Gordeev 	if (pci_enable_msi(pdev))
12397b92b4f6SAlexander Gordeev 		goto intx;
12407b92b4f6SAlexander Gordeev 	return 1;
12417b92b4f6SAlexander Gordeev 
12427b92b4f6SAlexander Gordeev intx:
12435ca72c4fSAlexander Gordeev 	pci_intx(pdev, 1);
12445ca72c4fSAlexander Gordeev 	return 0;
12455ca72c4fSAlexander Gordeev }
12465ca72c4fSAlexander Gordeev 
1247c6fd2807SJeff Garzik static int ahci_init_one(struct pci_dev *pdev, const struct pci_device_id *ent)
1248c6fd2807SJeff Garzik {
1249e297d99eSTejun Heo 	unsigned int board_id = ent->driver_data;
1250e297d99eSTejun Heo 	struct ata_port_info pi = ahci_port_info[board_id];
12514447d351STejun Heo 	const struct ata_port_info *ppi[] = { &pi, NULL };
125224dc5f33STejun Heo 	struct device *dev = &pdev->dev;
1253c6fd2807SJeff Garzik 	struct ahci_host_priv *hpriv;
12544447d351STejun Heo 	struct ata_host *host;
1255c3ebd6a9SAlexander Gordeev 	int n_ports, i, rc;
1256318893e1SAlessandro Rubini 	int ahci_pci_bar = AHCI_PCI_BAR_STANDARD;
1257c6fd2807SJeff Garzik 
1258c6fd2807SJeff Garzik 	VPRINTK("ENTER\n");
1259c6fd2807SJeff Garzik 
1260b429dd59SJustin P. Mattock 	WARN_ON((int)ATA_MAX_QUEUE > AHCI_MAX_CMDS);
1261c6fd2807SJeff Garzik 
126206296a1eSJoe Perches 	ata_print_version_once(&pdev->dev, DRV_VERSION);
1263c6fd2807SJeff Garzik 
12645b66c829SAlan Cox 	/* The AHCI driver can only drive the SATA ports, the PATA driver
12655b66c829SAlan Cox 	   can drive them all so if both drivers are selected make sure
12665b66c829SAlan Cox 	   AHCI stays out of the way */
12675b66c829SAlan Cox 	if (pdev->vendor == PCI_VENDOR_ID_MARVELL && !marvell_enable)
12685b66c829SAlan Cox 		return -ENODEV;
12695b66c829SAlan Cox 
1270cb85696dSJames Laird 	/* Apple BIOS on MCP89 prevents us using AHCI */
1271cb85696dSJames Laird 	if (is_mcp89_apple(pdev))
1272cb85696dSJames Laird 		ahci_mcp89_apple_enable(pdev);
1273c6353b45STejun Heo 
12747a02267eSMark Nelson 	/* Promise's PDC42819 is a SAS/SATA controller that has an AHCI mode.
12757a02267eSMark Nelson 	 * At the moment, we can only use the AHCI mode. Let the users know
12767a02267eSMark Nelson 	 * that for SAS drives they're out of luck.
12777a02267eSMark Nelson 	 */
12787a02267eSMark Nelson 	if (pdev->vendor == PCI_VENDOR_ID_PROMISE)
1279a44fec1fSJoe Perches 		dev_info(&pdev->dev,
1280a44fec1fSJoe Perches 			 "PDC42819 can only drive SATA devices with this driver\n");
12817a02267eSMark Nelson 
12827f9c9f8eSHugh Daschbach 	/* Both Connext and Enmotus devices use non-standard BARs */
1283318893e1SAlessandro Rubini 	if (pdev->vendor == PCI_VENDOR_ID_STMICRO && pdev->device == 0xCC06)
1284318893e1SAlessandro Rubini 		ahci_pci_bar = AHCI_PCI_BAR_STA2X11;
12857f9c9f8eSHugh Daschbach 	else if (pdev->vendor == 0x1c44 && pdev->device == 0x8000)
12867f9c9f8eSHugh Daschbach 		ahci_pci_bar = AHCI_PCI_BAR_ENMOTUS;
1287318893e1SAlessandro Rubini 
1288e6b7e41cSChuansheng Liu 	/*
1289e6b7e41cSChuansheng Liu 	 * The JMicron chip 361/363 contains one SATA controller and one
1290e6b7e41cSChuansheng Liu 	 * PATA controller,for powering on these both controllers, we must
1291e6b7e41cSChuansheng Liu 	 * follow the sequence one by one, otherwise one of them can not be
1292e6b7e41cSChuansheng Liu 	 * powered on successfully, so here we disable the async suspend
1293e6b7e41cSChuansheng Liu 	 * method for these chips.
1294e6b7e41cSChuansheng Liu 	 */
1295e6b7e41cSChuansheng Liu 	if (pdev->vendor == PCI_VENDOR_ID_JMICRON &&
1296e6b7e41cSChuansheng Liu 		(pdev->device == PCI_DEVICE_ID_JMICRON_JMB363 ||
1297e6b7e41cSChuansheng Liu 		pdev->device == PCI_DEVICE_ID_JMICRON_JMB361))
1298e6b7e41cSChuansheng Liu 		device_disable_async_suspend(&pdev->dev);
1299e6b7e41cSChuansheng Liu 
13004447d351STejun Heo 	/* acquire resources */
130124dc5f33STejun Heo 	rc = pcim_enable_device(pdev);
1302c6fd2807SJeff Garzik 	if (rc)
1303c6fd2807SJeff Garzik 		return rc;
1304c6fd2807SJeff Garzik 
1305c4f7792cSTejun Heo 	if (pdev->vendor == PCI_VENDOR_ID_INTEL &&
1306c4f7792cSTejun Heo 	    (pdev->device == 0x2652 || pdev->device == 0x2653)) {
1307c4f7792cSTejun Heo 		u8 map;
1308c4f7792cSTejun Heo 
1309c4f7792cSTejun Heo 		/* ICH6s share the same PCI ID for both piix and ahci
1310c4f7792cSTejun Heo 		 * modes.  Enabling ahci mode while MAP indicates
1311c4f7792cSTejun Heo 		 * combined mode is a bad idea.  Yield to ata_piix.
1312c4f7792cSTejun Heo 		 */
1313c4f7792cSTejun Heo 		pci_read_config_byte(pdev, ICH_MAP, &map);
1314c4f7792cSTejun Heo 		if (map & 0x3) {
1315a44fec1fSJoe Perches 			dev_info(&pdev->dev,
1316a44fec1fSJoe Perches 				 "controller is in combined mode, can't enable AHCI mode\n");
1317c4f7792cSTejun Heo 			return -ENODEV;
1318c4f7792cSTejun Heo 		}
1319c4f7792cSTejun Heo 	}
1320c4f7792cSTejun Heo 
13216fec8871SPaul Bolle 	/* AHCI controllers often implement SFF compatible interface.
13226fec8871SPaul Bolle 	 * Grab all PCI BARs just in case.
13236fec8871SPaul Bolle 	 */
13246fec8871SPaul Bolle 	rc = pcim_iomap_regions_request_all(pdev, 1 << ahci_pci_bar, DRV_NAME);
13256fec8871SPaul Bolle 	if (rc == -EBUSY)
13266fec8871SPaul Bolle 		pcim_pin_device(pdev);
13276fec8871SPaul Bolle 	if (rc)
13286fec8871SPaul Bolle 		return rc;
13296fec8871SPaul Bolle 
133024dc5f33STejun Heo 	hpriv = devm_kzalloc(dev, sizeof(*hpriv), GFP_KERNEL);
133124dc5f33STejun Heo 	if (!hpriv)
133224dc5f33STejun Heo 		return -ENOMEM;
1333417a1a6dSTejun Heo 	hpriv->flags |= (unsigned long)pi.private_data;
1334417a1a6dSTejun Heo 
1335e297d99eSTejun Heo 	/* MCP65 revision A1 and A2 can't do MSI */
1336e297d99eSTejun Heo 	if (board_id == board_ahci_mcp65 &&
1337e297d99eSTejun Heo 	    (pdev->revision == 0xa1 || pdev->revision == 0xa2))
1338e297d99eSTejun Heo 		hpriv->flags |= AHCI_HFLAG_NO_MSI;
1339e297d99eSTejun Heo 
1340e427fe04SShane Huang 	/* SB800 does NOT need the workaround to ignore SERR_INTERNAL */
1341e427fe04SShane Huang 	if (board_id == board_ahci_sb700 && pdev->revision >= 0x40)
1342e427fe04SShane Huang 		hpriv->flags &= ~AHCI_HFLAG_IGN_SERR_INTERNAL;
1343e427fe04SShane Huang 
13442fcad9d2STejun Heo 	/* only some SB600s can do 64bit DMA */
13452fcad9d2STejun Heo 	if (ahci_sb600_enable_64bit(pdev))
13462fcad9d2STejun Heo 		hpriv->flags &= ~AHCI_HFLAG_32BIT_ONLY;
134758a09b38SShane Huang 
1348318893e1SAlessandro Rubini 	hpriv->mmio = pcim_iomap_table(pdev)[ahci_pci_bar];
1349d8993349SAnton Vorontsov 
13500cf4a7d6SJacob Pan 	/* must set flag prior to save config in order to take effect */
13510cf4a7d6SJacob Pan 	if (ahci_broken_devslp(pdev))
13520cf4a7d6SJacob Pan 		hpriv->flags |= AHCI_HFLAG_NO_DEVSLP;
13530cf4a7d6SJacob Pan 
13544447d351STejun Heo 	/* save initial config */
1355394d6e53SAnton Vorontsov 	ahci_pci_save_initial_config(pdev, hpriv);
1356c6fd2807SJeff Garzik 
13574447d351STejun Heo 	/* prepare host */
1358453d3131SRobert Hancock 	if (hpriv->cap & HOST_CAP_NCQ) {
1359453d3131SRobert Hancock 		pi.flags |= ATA_FLAG_NCQ;
136083f2b963STejun Heo 		/*
136183f2b963STejun Heo 		 * Auto-activate optimization is supposed to be
136283f2b963STejun Heo 		 * supported on all AHCI controllers indicating NCQ
136383f2b963STejun Heo 		 * capability, but it seems to be broken on some
136483f2b963STejun Heo 		 * chipsets including NVIDIAs.
136583f2b963STejun Heo 		 */
136683f2b963STejun Heo 		if (!(hpriv->flags & AHCI_HFLAG_NO_FPDMA_AA))
1367453d3131SRobert Hancock 			pi.flags |= ATA_FLAG_FPDMA_AA;
136840fb59e7SMarc Carino 
136940fb59e7SMarc Carino 		/*
137040fb59e7SMarc Carino 		 * All AHCI controllers should be forward-compatible
137140fb59e7SMarc Carino 		 * with the new auxiliary field. This code should be
137240fb59e7SMarc Carino 		 * conditionalized if any buggy AHCI controllers are
137340fb59e7SMarc Carino 		 * encountered.
137440fb59e7SMarc Carino 		 */
137540fb59e7SMarc Carino 		pi.flags |= ATA_FLAG_FPDMA_AUX;
1376453d3131SRobert Hancock 	}
13774447d351STejun Heo 
13787d50b60bSTejun Heo 	if (hpriv->cap & HOST_CAP_PMP)
13797d50b60bSTejun Heo 		pi.flags |= ATA_FLAG_PMP;
13807d50b60bSTejun Heo 
13810cbb0e77SAnton Vorontsov 	ahci_set_em_messages(hpriv, &pi);
138218f7ba4cSKristen Carlson Accardi 
13831fd68434SRafael J. Wysocki 	if (ahci_broken_system_poweroff(pdev)) {
13841fd68434SRafael J. Wysocki 		pi.flags |= ATA_FLAG_NO_POWEROFF_SPINDOWN;
13851fd68434SRafael J. Wysocki 		dev_info(&pdev->dev,
13861fd68434SRafael J. Wysocki 			"quirky BIOS, skipping spindown on poweroff\n");
13871fd68434SRafael J. Wysocki 	}
13881fd68434SRafael J. Wysocki 
13899b10ae86STejun Heo 	if (ahci_broken_suspend(pdev)) {
13909b10ae86STejun Heo 		hpriv->flags |= AHCI_HFLAG_NO_SUSPEND;
1391a44fec1fSJoe Perches 		dev_warn(&pdev->dev,
13929b10ae86STejun Heo 			 "BIOS update required for suspend/resume\n");
13939b10ae86STejun Heo 	}
13949b10ae86STejun Heo 
13955594639aSTejun Heo 	if (ahci_broken_online(pdev)) {
13965594639aSTejun Heo 		hpriv->flags |= AHCI_HFLAG_SRST_TOUT_IS_OFFLINE;
13975594639aSTejun Heo 		dev_info(&pdev->dev,
13985594639aSTejun Heo 			 "online status unreliable, applying workaround\n");
13995594639aSTejun Heo 	}
14005594639aSTejun Heo 
1401837f5f8fSTejun Heo 	/* CAP.NP sometimes indicate the index of the last enabled
1402837f5f8fSTejun Heo 	 * port, at other times, that of the last possible port, so
1403837f5f8fSTejun Heo 	 * determining the maximum port number requires looking at
1404837f5f8fSTejun Heo 	 * both CAP.NP and port_map.
1405837f5f8fSTejun Heo 	 */
1406837f5f8fSTejun Heo 	n_ports = max(ahci_nr_ports(hpriv->cap), fls(hpriv->port_map));
1407837f5f8fSTejun Heo 
1408c3ebd6a9SAlexander Gordeev 	ahci_init_interrupts(pdev, n_ports, hpriv);
14097b92b4f6SAlexander Gordeev 
1410837f5f8fSTejun Heo 	host = ata_host_alloc_pinfo(&pdev->dev, ppi, n_ports);
14114447d351STejun Heo 	if (!host)
14124447d351STejun Heo 		return -ENOMEM;
14134447d351STejun Heo 	host->private_data = hpriv;
14144447d351STejun Heo 
1415f3d7f23fSArjan van de Ven 	if (!(hpriv->cap & HOST_CAP_SSS) || ahci_ignore_sss)
1416886ad09fSArjan van de Ven 		host->flags |= ATA_HOST_PARALLEL_SCAN;
1417f3d7f23fSArjan van de Ven 	else
1418d2782d96SJingoo Han 		dev_info(&pdev->dev, "SSS flag set, parallel bus scan disabled\n");
1419886ad09fSArjan van de Ven 
142018f7ba4cSKristen Carlson Accardi 	if (pi.flags & ATA_FLAG_EM)
142118f7ba4cSKristen Carlson Accardi 		ahci_reset_em(host);
142218f7ba4cSKristen Carlson Accardi 
14234447d351STejun Heo 	for (i = 0; i < host->n_ports; i++) {
14244447d351STejun Heo 		struct ata_port *ap = host->ports[i];
14254447d351STejun Heo 
1426318893e1SAlessandro Rubini 		ata_port_pbar_desc(ap, ahci_pci_bar, -1, "abar");
1427318893e1SAlessandro Rubini 		ata_port_pbar_desc(ap, ahci_pci_bar,
1428cbcdd875STejun Heo 				   0x100 + ap->port_no * 0x80, "port");
1429cbcdd875STejun Heo 
143018f7ba4cSKristen Carlson Accardi 		/* set enclosure management message type */
143118f7ba4cSKristen Carlson Accardi 		if (ap->flags & ATA_FLAG_EM)
1432008dbd61SHarry Zhang 			ap->em_message_type = hpriv->em_msg_type;
143318f7ba4cSKristen Carlson Accardi 
143418f7ba4cSKristen Carlson Accardi 
1435dab632e8SJeff Garzik 		/* disabled/not-implemented port */
1436350756f6STejun Heo 		if (!(hpriv->port_map & (1 << i)))
1437dab632e8SJeff Garzik 			ap->ops = &ata_dummy_port_ops;
14384447d351STejun Heo 	}
1439c6fd2807SJeff Garzik 
1440edc93052STejun Heo 	/* apply workaround for ASUS P5W DH Deluxe mainboard */
1441edc93052STejun Heo 	ahci_p5wdh_workaround(host);
1442edc93052STejun Heo 
1443f80ae7e4STejun Heo 	/* apply gtf filter quirk */
1444f80ae7e4STejun Heo 	ahci_gtf_filter_workaround(host);
1445f80ae7e4STejun Heo 
1446c6fd2807SJeff Garzik 	/* initialize adapter */
14474447d351STejun Heo 	rc = ahci_configure_dma_masks(pdev, hpriv->cap & HOST_CAP_64);
1448c6fd2807SJeff Garzik 	if (rc)
144924dc5f33STejun Heo 		return rc;
1450c6fd2807SJeff Garzik 
14513303040dSAnton Vorontsov 	rc = ahci_pci_reset_controller(host);
14524447d351STejun Heo 	if (rc)
14534447d351STejun Heo 		return rc;
1454c6fd2807SJeff Garzik 
1455781d6550SAnton Vorontsov 	ahci_pci_init_controller(host);
1456439fcaecSAnton Vorontsov 	ahci_pci_print_info(host);
1457c6fd2807SJeff Garzik 
14584447d351STejun Heo 	pci_set_master(pdev);
14595ca72c4fSAlexander Gordeev 
1460a6849b9fSAlexander Gordeev 	return ahci_host_activate(host, pdev->irq, &ahci_sht);
1461c6fd2807SJeff Garzik }
1462c6fd2807SJeff Garzik 
14632fc75da0SAxel Lin module_pci_driver(ahci_pci_driver);
1464c6fd2807SJeff Garzik 
1465c6fd2807SJeff Garzik MODULE_AUTHOR("Jeff Garzik");
1466c6fd2807SJeff Garzik MODULE_DESCRIPTION("AHCI SATA low-level driver");
1467c6fd2807SJeff Garzik MODULE_LICENSE("GPL");
1468c6fd2807SJeff Garzik MODULE_DEVICE_TABLE(pci, ahci_pci_tbl);
1469c6fd2807SJeff Garzik MODULE_VERSION(DRV_VERSION);
1470