xref: /openbmc/linux/drivers/ata/ahci.c (revision c82ee6d3beaa489058c1fe1ca710042a07df9d40)
1*c82ee6d3SThomas Gleixner // SPDX-License-Identifier: GPL-2.0-or-later
2c6fd2807SJeff Garzik /*
3c6fd2807SJeff Garzik  *  ahci.c - AHCI SATA support
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 2004-2005 Red Hat, Inc.
10c6fd2807SJeff Garzik  *
11c6fd2807SJeff Garzik  * libata documentation is available via 'make {ps|pdf}docs',
1219285f3cSMauro Carvalho Chehab  * as Documentation/driver-api/libata.rst
13c6fd2807SJeff Garzik  *
14c6fd2807SJeff Garzik  * AHCI hardware documentation:
15c6fd2807SJeff Garzik  * http://www.intel.com/technology/serialata/pdf/rev1_0.pdf
16c6fd2807SJeff Garzik  * http://www.intel.com/technology/serialata/pdf/rev1_1.pdf
17c6fd2807SJeff Garzik  */
18c6fd2807SJeff Garzik 
19c6fd2807SJeff Garzik #include <linux/kernel.h>
20c6fd2807SJeff Garzik #include <linux/module.h>
21c6fd2807SJeff Garzik #include <linux/pci.h>
22c6fd2807SJeff Garzik #include <linux/blkdev.h>
23c6fd2807SJeff Garzik #include <linux/delay.h>
24c6fd2807SJeff Garzik #include <linux/interrupt.h>
25c6fd2807SJeff Garzik #include <linux/dma-mapping.h>
26c6fd2807SJeff Garzik #include <linux/device.h>
27edc93052STejun Heo #include <linux/dmi.h>
285a0e3ad6STejun Heo #include <linux/gfp.h>
29ee2aad42SRobert Richter #include <linux/msi.h>
30c6fd2807SJeff Garzik #include <scsi/scsi_host.h>
31c6fd2807SJeff Garzik #include <scsi/scsi_cmnd.h>
32c6fd2807SJeff Garzik #include <linux/libata.h>
33aecec8b6SChristoph Hellwig #include <linux/ahci-remap.h>
34aecec8b6SChristoph Hellwig #include <linux/io-64-nonatomic-lo-hi.h>
35365cfa1eSAnton Vorontsov #include "ahci.h"
36c6fd2807SJeff Garzik 
37c6fd2807SJeff Garzik #define DRV_NAME	"ahci"
387d50b60bSTejun Heo #define DRV_VERSION	"3.0"
39c6fd2807SJeff Garzik 
40c6fd2807SJeff Garzik enum {
41318893e1SAlessandro Rubini 	AHCI_PCI_BAR_STA2X11	= 0,
42b7ae128dSRobert Richter 	AHCI_PCI_BAR_CAVIUM	= 0,
437f9c9f8eSHugh Daschbach 	AHCI_PCI_BAR_ENMOTUS	= 2,
44b1314e3fSRadha Mohan Chintakuntla 	AHCI_PCI_BAR_CAVIUM_GEN5	= 4,
45318893e1SAlessandro Rubini 	AHCI_PCI_BAR_STANDARD	= 5,
46441577efSTejun Heo };
47c6fd2807SJeff Garzik 
48441577efSTejun Heo enum board_ids {
49441577efSTejun Heo 	/* board IDs by feature in alphabetical order */
50441577efSTejun Heo 	board_ahci,
51441577efSTejun Heo 	board_ahci_ign_iferr,
52ebb82e3cSHans de Goede 	board_ahci_mobile,
5366a7cbc3STejun Heo 	board_ahci_nomsi,
5467809f85SLevente Kurusa 	board_ahci_noncq,
55441577efSTejun Heo 	board_ahci_nosntf,
565f173107STejun Heo 	board_ahci_yes_fbs,
57441577efSTejun Heo 
58441577efSTejun Heo 	/* board IDs for specific chipsets in alphabetical order */
59dbfe8ef5SDan Williams 	board_ahci_avn,
60441577efSTejun Heo 	board_ahci_mcp65,
6183f2b963STejun Heo 	board_ahci_mcp77,
6283f2b963STejun Heo 	board_ahci_mcp89,
63441577efSTejun Heo 	board_ahci_mv,
64441577efSTejun Heo 	board_ahci_sb600,
65441577efSTejun Heo 	board_ahci_sb700,	/* for SB700 and SB800 */
66441577efSTejun Heo 	board_ahci_vt8251,
67441577efSTejun Heo 
68441577efSTejun Heo 	/* aliases */
69441577efSTejun Heo 	board_ahci_mcp_linux	= board_ahci_mcp65,
70441577efSTejun Heo 	board_ahci_mcp67	= board_ahci_mcp65,
71441577efSTejun Heo 	board_ahci_mcp73	= board_ahci_mcp65,
7283f2b963STejun Heo 	board_ahci_mcp79	= board_ahci_mcp77,
73c6fd2807SJeff Garzik };
74c6fd2807SJeff Garzik 
75c6fd2807SJeff Garzik static int ahci_init_one(struct pci_dev *pdev, const struct pci_device_id *ent);
7602e53293SMika Westerberg static void ahci_remove_one(struct pci_dev *dev);
77a1efdabaSTejun Heo static int ahci_vt8251_hardreset(struct ata_link *link, unsigned int *class,
78a1efdabaSTejun Heo 				 unsigned long deadline);
79dbfe8ef5SDan Williams static int ahci_avn_hardreset(struct ata_link *link, unsigned int *class,
80dbfe8ef5SDan Williams 			      unsigned long deadline);
81cb85696dSJames Laird static void ahci_mcp89_apple_enable(struct pci_dev *pdev);
82cb85696dSJames Laird static bool is_mcp89_apple(struct pci_dev *pdev);
83a1efdabaSTejun Heo static int ahci_p5wdh_hardreset(struct ata_link *link, unsigned int *class,
84a1efdabaSTejun Heo 				unsigned long deadline);
8502e53293SMika Westerberg #ifdef CONFIG_PM
8602e53293SMika Westerberg static int ahci_pci_device_runtime_suspend(struct device *dev);
8702e53293SMika Westerberg static int ahci_pci_device_runtime_resume(struct device *dev);
88f1d848f9SMika Westerberg #ifdef CONFIG_PM_SLEEP
89f1d848f9SMika Westerberg static int ahci_pci_device_suspend(struct device *dev);
90f1d848f9SMika Westerberg static int ahci_pci_device_resume(struct device *dev);
91438ac6d5STejun Heo #endif
9202e53293SMika Westerberg #endif /* CONFIG_PM */
93c6fd2807SJeff Garzik 
94fad16e7aSTejun Heo static struct scsi_host_template ahci_sht = {
95fad16e7aSTejun Heo 	AHCI_SHT("ahci"),
96fad16e7aSTejun Heo };
97fad16e7aSTejun Heo 
98029cfd6bSTejun Heo static struct ata_port_operations ahci_vt8251_ops = {
99029cfd6bSTejun Heo 	.inherits		= &ahci_ops,
100a1efdabaSTejun Heo 	.hardreset		= ahci_vt8251_hardreset,
101ad616ffbSTejun Heo };
102ad616ffbSTejun Heo 
103029cfd6bSTejun Heo static struct ata_port_operations ahci_p5wdh_ops = {
104029cfd6bSTejun Heo 	.inherits		= &ahci_ops,
105a1efdabaSTejun Heo 	.hardreset		= ahci_p5wdh_hardreset,
106edc93052STejun Heo };
107edc93052STejun Heo 
108dbfe8ef5SDan Williams static struct ata_port_operations ahci_avn_ops = {
109dbfe8ef5SDan Williams 	.inherits		= &ahci_ops,
110dbfe8ef5SDan Williams 	.hardreset		= ahci_avn_hardreset,
111dbfe8ef5SDan Williams };
112dbfe8ef5SDan Williams 
113c6fd2807SJeff Garzik static const struct ata_port_info ahci_port_info[] = {
114441577efSTejun Heo 	/* by features */
115facb8fa6SJeffrin Jose 	[board_ahci] = {
1161188c0d8STejun Heo 		.flags		= AHCI_FLAG_COMMON,
11714bdef98SErik Inge Bolsø 		.pio_mask	= ATA_PIO4,
118469248abSJeff Garzik 		.udma_mask	= ATA_UDMA6,
119c6fd2807SJeff Garzik 		.port_ops	= &ahci_ops,
120c6fd2807SJeff Garzik 	},
121facb8fa6SJeffrin Jose 	[board_ahci_ign_iferr] = {
122417a1a6dSTejun Heo 		AHCI_HFLAGS	(AHCI_HFLAG_IGN_IRQ_IF_ERR),
123417a1a6dSTejun Heo 		.flags		= AHCI_FLAG_COMMON,
12414bdef98SErik Inge Bolsø 		.pio_mask	= ATA_PIO4,
125469248abSJeff Garzik 		.udma_mask	= ATA_UDMA6,
12641669553STejun Heo 		.port_ops	= &ahci_ops,
12741669553STejun Heo 	},
128ebb82e3cSHans de Goede 	[board_ahci_mobile] = {
129ebb82e3cSHans de Goede 		AHCI_HFLAGS	(AHCI_HFLAG_IS_MOBILE),
130ebb82e3cSHans de Goede 		.flags		= AHCI_FLAG_COMMON,
131ebb82e3cSHans de Goede 		.pio_mask	= ATA_PIO4,
132ebb82e3cSHans de Goede 		.udma_mask	= ATA_UDMA6,
133ebb82e3cSHans de Goede 		.port_ops	= &ahci_ops,
134ebb82e3cSHans de Goede 	},
13566a7cbc3STejun Heo 	[board_ahci_nomsi] = {
13666a7cbc3STejun Heo 		AHCI_HFLAGS	(AHCI_HFLAG_NO_MSI),
13766a7cbc3STejun Heo 		.flags		= AHCI_FLAG_COMMON,
13866a7cbc3STejun Heo 		.pio_mask	= ATA_PIO4,
13966a7cbc3STejun Heo 		.udma_mask	= ATA_UDMA6,
14066a7cbc3STejun Heo 		.port_ops	= &ahci_ops,
14166a7cbc3STejun Heo 	},
14267809f85SLevente Kurusa 	[board_ahci_noncq] = {
14367809f85SLevente Kurusa 		AHCI_HFLAGS	(AHCI_HFLAG_NO_NCQ),
14467809f85SLevente Kurusa 		.flags		= AHCI_FLAG_COMMON,
14567809f85SLevente Kurusa 		.pio_mask	= ATA_PIO4,
14667809f85SLevente Kurusa 		.udma_mask	= ATA_UDMA6,
14767809f85SLevente Kurusa 		.port_ops	= &ahci_ops,
14867809f85SLevente Kurusa 	},
149facb8fa6SJeffrin Jose 	[board_ahci_nosntf] = {
150441577efSTejun Heo 		AHCI_HFLAGS	(AHCI_HFLAG_NO_SNTF),
151441577efSTejun Heo 		.flags		= AHCI_FLAG_COMMON,
152441577efSTejun Heo 		.pio_mask	= ATA_PIO4,
153441577efSTejun Heo 		.udma_mask	= ATA_UDMA6,
154441577efSTejun Heo 		.port_ops	= &ahci_ops,
155441577efSTejun Heo 	},
156facb8fa6SJeffrin Jose 	[board_ahci_yes_fbs] = {
1575f173107STejun Heo 		AHCI_HFLAGS	(AHCI_HFLAG_YES_FBS),
1585f173107STejun Heo 		.flags		= AHCI_FLAG_COMMON,
1595f173107STejun Heo 		.pio_mask	= ATA_PIO4,
1605f173107STejun Heo 		.udma_mask	= ATA_UDMA6,
1615f173107STejun Heo 		.port_ops	= &ahci_ops,
1625f173107STejun Heo 	},
163441577efSTejun Heo 	/* by chipsets */
164dbfe8ef5SDan Williams 	[board_ahci_avn] = {
165dbfe8ef5SDan Williams 		.flags		= AHCI_FLAG_COMMON,
166dbfe8ef5SDan Williams 		.pio_mask	= ATA_PIO4,
167dbfe8ef5SDan Williams 		.udma_mask	= ATA_UDMA6,
168dbfe8ef5SDan Williams 		.port_ops	= &ahci_avn_ops,
169dbfe8ef5SDan Williams 	},
170facb8fa6SJeffrin Jose 	[board_ahci_mcp65] = {
17183f2b963STejun Heo 		AHCI_HFLAGS	(AHCI_HFLAG_NO_FPDMA_AA | AHCI_HFLAG_NO_PMP |
17283f2b963STejun Heo 				 AHCI_HFLAG_YES_NCQ),
173ae01b249STejun Heo 		.flags		= AHCI_FLAG_COMMON | ATA_FLAG_NO_DIPM,
17483f2b963STejun Heo 		.pio_mask	= ATA_PIO4,
17583f2b963STejun Heo 		.udma_mask	= ATA_UDMA6,
17683f2b963STejun Heo 		.port_ops	= &ahci_ops,
17783f2b963STejun Heo 	},
178facb8fa6SJeffrin Jose 	[board_ahci_mcp77] = {
17983f2b963STejun Heo 		AHCI_HFLAGS	(AHCI_HFLAG_NO_FPDMA_AA | AHCI_HFLAG_NO_PMP),
18083f2b963STejun Heo 		.flags		= AHCI_FLAG_COMMON,
18183f2b963STejun Heo 		.pio_mask	= ATA_PIO4,
18283f2b963STejun Heo 		.udma_mask	= ATA_UDMA6,
18383f2b963STejun Heo 		.port_ops	= &ahci_ops,
18483f2b963STejun Heo 	},
185facb8fa6SJeffrin Jose 	[board_ahci_mcp89] = {
18683f2b963STejun Heo 		AHCI_HFLAGS	(AHCI_HFLAG_NO_FPDMA_AA),
187441577efSTejun Heo 		.flags		= AHCI_FLAG_COMMON,
188441577efSTejun Heo 		.pio_mask	= ATA_PIO4,
189441577efSTejun Heo 		.udma_mask	= ATA_UDMA6,
190441577efSTejun Heo 		.port_ops	= &ahci_ops,
191441577efSTejun Heo 	},
192facb8fa6SJeffrin Jose 	[board_ahci_mv] = {
193441577efSTejun Heo 		AHCI_HFLAGS	(AHCI_HFLAG_NO_NCQ | AHCI_HFLAG_NO_MSI |
194441577efSTejun Heo 				 AHCI_HFLAG_MV_PATA | AHCI_HFLAG_NO_PMP),
1959cbe056fSSergei Shtylyov 		.flags		= ATA_FLAG_SATA | ATA_FLAG_PIO_DMA,
196441577efSTejun Heo 		.pio_mask	= ATA_PIO4,
197441577efSTejun Heo 		.udma_mask	= ATA_UDMA6,
198441577efSTejun Heo 		.port_ops	= &ahci_ops,
199441577efSTejun Heo 	},
200facb8fa6SJeffrin Jose 	[board_ahci_sb600] = {
201417a1a6dSTejun Heo 		AHCI_HFLAGS	(AHCI_HFLAG_IGN_SERR_INTERNAL |
2022fcad9d2STejun Heo 				 AHCI_HFLAG_NO_MSI | AHCI_HFLAG_SECT255 |
2032fcad9d2STejun Heo 				 AHCI_HFLAG_32BIT_ONLY),
204417a1a6dSTejun Heo 		.flags		= AHCI_FLAG_COMMON,
20514bdef98SErik Inge Bolsø 		.pio_mask	= ATA_PIO4,
206469248abSJeff Garzik 		.udma_mask	= ATA_UDMA6,
207345347c5SYuan-Hsin Chen 		.port_ops	= &ahci_pmp_retry_srst_ops,
20855a61604SConke Hu 	},
209facb8fa6SJeffrin Jose 	[board_ahci_sb700] = {	/* for SB700 and SB800 */
210bd17243aSShane Huang 		AHCI_HFLAGS	(AHCI_HFLAG_IGN_SERR_INTERNAL),
211e39fc8c9SShane Huang 		.flags		= AHCI_FLAG_COMMON,
21214bdef98SErik Inge Bolsø 		.pio_mask	= ATA_PIO4,
213e39fc8c9SShane Huang 		.udma_mask	= ATA_UDMA6,
214345347c5SYuan-Hsin Chen 		.port_ops	= &ahci_pmp_retry_srst_ops,
215e39fc8c9SShane Huang 	},
216facb8fa6SJeffrin Jose 	[board_ahci_vt8251] = {
217441577efSTejun Heo 		AHCI_HFLAGS	(AHCI_HFLAG_NO_NCQ | AHCI_HFLAG_NO_PMP),
218e297d99eSTejun Heo 		.flags		= AHCI_FLAG_COMMON,
21914bdef98SErik Inge Bolsø 		.pio_mask	= ATA_PIO4,
220e297d99eSTejun Heo 		.udma_mask	= ATA_UDMA6,
221441577efSTejun Heo 		.port_ops	= &ahci_vt8251_ops,
2221b677afdSShaohua Li 	},
223c6fd2807SJeff Garzik };
224c6fd2807SJeff Garzik 
225c6fd2807SJeff Garzik static const struct pci_device_id ahci_pci_tbl[] = {
226c6fd2807SJeff Garzik 	/* Intel */
22754bb3a94SJeff Garzik 	{ PCI_VDEVICE(INTEL, 0x2652), board_ahci }, /* ICH6 */
22854bb3a94SJeff Garzik 	{ PCI_VDEVICE(INTEL, 0x2653), board_ahci }, /* ICH6M */
22954bb3a94SJeff Garzik 	{ PCI_VDEVICE(INTEL, 0x27c1), board_ahci }, /* ICH7 */
23054bb3a94SJeff Garzik 	{ PCI_VDEVICE(INTEL, 0x27c5), board_ahci }, /* ICH7M */
23154bb3a94SJeff Garzik 	{ PCI_VDEVICE(INTEL, 0x27c3), board_ahci }, /* ICH7R */
23282490c09STejun Heo 	{ PCI_VDEVICE(AL, 0x5288), board_ahci_ign_iferr }, /* ULi M5288 */
23354bb3a94SJeff Garzik 	{ PCI_VDEVICE(INTEL, 0x2681), board_ahci }, /* ESB2 */
23454bb3a94SJeff Garzik 	{ PCI_VDEVICE(INTEL, 0x2682), board_ahci }, /* ESB2 */
23554bb3a94SJeff Garzik 	{ PCI_VDEVICE(INTEL, 0x2683), board_ahci }, /* ESB2 */
23654bb3a94SJeff Garzik 	{ PCI_VDEVICE(INTEL, 0x27c6), board_ahci }, /* ICH7-M DH */
2377a234affSTejun Heo 	{ PCI_VDEVICE(INTEL, 0x2821), board_ahci }, /* ICH8 */
2381b677afdSShaohua Li 	{ PCI_VDEVICE(INTEL, 0x2822), board_ahci_nosntf }, /* ICH8 */
2397a234affSTejun Heo 	{ PCI_VDEVICE(INTEL, 0x2824), board_ahci }, /* ICH8 */
2407a234affSTejun Heo 	{ PCI_VDEVICE(INTEL, 0x2829), board_ahci }, /* ICH8M */
2417a234affSTejun Heo 	{ PCI_VDEVICE(INTEL, 0x282a), board_ahci }, /* ICH8M */
2427a234affSTejun Heo 	{ PCI_VDEVICE(INTEL, 0x2922), board_ahci }, /* ICH9 */
2437a234affSTejun Heo 	{ PCI_VDEVICE(INTEL, 0x2923), board_ahci }, /* ICH9 */
2447a234affSTejun Heo 	{ PCI_VDEVICE(INTEL, 0x2924), board_ahci }, /* ICH9 */
2457a234affSTejun Heo 	{ PCI_VDEVICE(INTEL, 0x2925), board_ahci }, /* ICH9 */
2467a234affSTejun Heo 	{ PCI_VDEVICE(INTEL, 0x2927), board_ahci }, /* ICH9 */
247ebb82e3cSHans de Goede 	{ PCI_VDEVICE(INTEL, 0x2929), board_ahci_mobile }, /* ICH9M */
248ebb82e3cSHans de Goede 	{ PCI_VDEVICE(INTEL, 0x292a), board_ahci_mobile }, /* ICH9M */
249ebb82e3cSHans de Goede 	{ PCI_VDEVICE(INTEL, 0x292b), board_ahci_mobile }, /* ICH9M */
250ebb82e3cSHans de Goede 	{ PCI_VDEVICE(INTEL, 0x292c), board_ahci_mobile }, /* ICH9M */
251ebb82e3cSHans de Goede 	{ PCI_VDEVICE(INTEL, 0x292f), board_ahci_mobile }, /* ICH9M */
2527a234affSTejun Heo 	{ PCI_VDEVICE(INTEL, 0x294d), board_ahci }, /* ICH9 */
253ebb82e3cSHans de Goede 	{ PCI_VDEVICE(INTEL, 0x294e), board_ahci_mobile }, /* ICH9M */
254d4155e6fSJason Gaston 	{ PCI_VDEVICE(INTEL, 0x502a), board_ahci }, /* Tolapai */
255d4155e6fSJason Gaston 	{ PCI_VDEVICE(INTEL, 0x502b), board_ahci }, /* Tolapai */
25616ad1ad9SJason Gaston 	{ PCI_VDEVICE(INTEL, 0x3a05), board_ahci }, /* ICH10 */
257b2dde6afSMark Goodwin 	{ PCI_VDEVICE(INTEL, 0x3a22), board_ahci }, /* ICH10 */
25816ad1ad9SJason Gaston 	{ PCI_VDEVICE(INTEL, 0x3a25), board_ahci }, /* ICH10 */
259c1f57d9bSDavid Milburn 	{ PCI_VDEVICE(INTEL, 0x3b22), board_ahci }, /* PCH AHCI */
260c1f57d9bSDavid Milburn 	{ PCI_VDEVICE(INTEL, 0x3b23), board_ahci }, /* PCH AHCI */
261adcb5308SSeth Heasley 	{ PCI_VDEVICE(INTEL, 0x3b24), board_ahci }, /* PCH RAID */
2628e48b6b3SSeth Heasley 	{ PCI_VDEVICE(INTEL, 0x3b25), board_ahci }, /* PCH RAID */
263ebb82e3cSHans de Goede 	{ PCI_VDEVICE(INTEL, 0x3b29), board_ahci_mobile }, /* PCH M AHCI */
264adcb5308SSeth Heasley 	{ PCI_VDEVICE(INTEL, 0x3b2b), board_ahci }, /* PCH RAID */
265ebb82e3cSHans de Goede 	{ PCI_VDEVICE(INTEL, 0x3b2c), board_ahci_mobile }, /* PCH M RAID */
266c1f57d9bSDavid Milburn 	{ PCI_VDEVICE(INTEL, 0x3b2f), board_ahci }, /* PCH AHCI */
267342decffSAlexandra Yates 	{ PCI_VDEVICE(INTEL, 0x19b0), board_ahci }, /* DNV AHCI */
268342decffSAlexandra Yates 	{ PCI_VDEVICE(INTEL, 0x19b1), board_ahci }, /* DNV AHCI */
269342decffSAlexandra Yates 	{ PCI_VDEVICE(INTEL, 0x19b2), board_ahci }, /* DNV AHCI */
270342decffSAlexandra Yates 	{ PCI_VDEVICE(INTEL, 0x19b3), board_ahci }, /* DNV AHCI */
271342decffSAlexandra Yates 	{ PCI_VDEVICE(INTEL, 0x19b4), board_ahci }, /* DNV AHCI */
272342decffSAlexandra Yates 	{ PCI_VDEVICE(INTEL, 0x19b5), board_ahci }, /* DNV AHCI */
273342decffSAlexandra Yates 	{ PCI_VDEVICE(INTEL, 0x19b6), board_ahci }, /* DNV AHCI */
274342decffSAlexandra Yates 	{ PCI_VDEVICE(INTEL, 0x19b7), board_ahci }, /* DNV AHCI */
275342decffSAlexandra Yates 	{ PCI_VDEVICE(INTEL, 0x19bE), board_ahci }, /* DNV AHCI */
276342decffSAlexandra Yates 	{ PCI_VDEVICE(INTEL, 0x19bF), board_ahci }, /* DNV AHCI */
277342decffSAlexandra Yates 	{ PCI_VDEVICE(INTEL, 0x19c0), board_ahci }, /* DNV AHCI */
278342decffSAlexandra Yates 	{ PCI_VDEVICE(INTEL, 0x19c1), board_ahci }, /* DNV AHCI */
279342decffSAlexandra Yates 	{ PCI_VDEVICE(INTEL, 0x19c2), board_ahci }, /* DNV AHCI */
280342decffSAlexandra Yates 	{ PCI_VDEVICE(INTEL, 0x19c3), board_ahci }, /* DNV AHCI */
281342decffSAlexandra Yates 	{ PCI_VDEVICE(INTEL, 0x19c4), board_ahci }, /* DNV AHCI */
282342decffSAlexandra Yates 	{ PCI_VDEVICE(INTEL, 0x19c5), board_ahci }, /* DNV AHCI */
283342decffSAlexandra Yates 	{ PCI_VDEVICE(INTEL, 0x19c6), board_ahci }, /* DNV AHCI */
284342decffSAlexandra Yates 	{ PCI_VDEVICE(INTEL, 0x19c7), board_ahci }, /* DNV AHCI */
285342decffSAlexandra Yates 	{ PCI_VDEVICE(INTEL, 0x19cE), board_ahci }, /* DNV AHCI */
286342decffSAlexandra Yates 	{ PCI_VDEVICE(INTEL, 0x19cF), board_ahci }, /* DNV AHCI */
2875623cab8SSeth Heasley 	{ PCI_VDEVICE(INTEL, 0x1c02), board_ahci }, /* CPT AHCI */
288ebb82e3cSHans de Goede 	{ PCI_VDEVICE(INTEL, 0x1c03), board_ahci_mobile }, /* CPT M AHCI */
2895623cab8SSeth Heasley 	{ PCI_VDEVICE(INTEL, 0x1c04), board_ahci }, /* CPT RAID */
290ebb82e3cSHans de Goede 	{ PCI_VDEVICE(INTEL, 0x1c05), board_ahci_mobile }, /* CPT M RAID */
2915623cab8SSeth Heasley 	{ PCI_VDEVICE(INTEL, 0x1c06), board_ahci }, /* CPT RAID */
2925623cab8SSeth Heasley 	{ PCI_VDEVICE(INTEL, 0x1c07), board_ahci }, /* CPT RAID */
293992b3fb9SSeth Heasley 	{ PCI_VDEVICE(INTEL, 0x1d02), board_ahci }, /* PBG AHCI */
294992b3fb9SSeth Heasley 	{ PCI_VDEVICE(INTEL, 0x1d04), board_ahci }, /* PBG RAID */
295992b3fb9SSeth Heasley 	{ PCI_VDEVICE(INTEL, 0x1d06), board_ahci }, /* PBG RAID */
29664a3903dSSeth Heasley 	{ PCI_VDEVICE(INTEL, 0x2826), board_ahci }, /* PBG RAID */
297a4a461a6SSeth Heasley 	{ PCI_VDEVICE(INTEL, 0x2323), board_ahci }, /* DH89xxCC AHCI */
298181e3ceaSSeth Heasley 	{ PCI_VDEVICE(INTEL, 0x1e02), board_ahci }, /* Panther Point AHCI */
299ebb82e3cSHans de Goede 	{ PCI_VDEVICE(INTEL, 0x1e03), board_ahci_mobile }, /* Panther M AHCI */
300181e3ceaSSeth Heasley 	{ PCI_VDEVICE(INTEL, 0x1e04), board_ahci }, /* Panther Point RAID */
301181e3ceaSSeth Heasley 	{ PCI_VDEVICE(INTEL, 0x1e05), board_ahci }, /* Panther Point RAID */
302181e3ceaSSeth Heasley 	{ PCI_VDEVICE(INTEL, 0x1e06), board_ahci }, /* Panther Point RAID */
303ebb82e3cSHans de Goede 	{ PCI_VDEVICE(INTEL, 0x1e07), board_ahci_mobile }, /* Panther M RAID */
3042cab7a4cSSeth Heasley 	{ PCI_VDEVICE(INTEL, 0x1e0e), board_ahci }, /* Panther Point RAID */
305ea4ace66SSeth Heasley 	{ PCI_VDEVICE(INTEL, 0x8c02), board_ahci }, /* Lynx Point AHCI */
306ebb82e3cSHans de Goede 	{ PCI_VDEVICE(INTEL, 0x8c03), board_ahci_mobile }, /* Lynx M AHCI */
307ea4ace66SSeth Heasley 	{ PCI_VDEVICE(INTEL, 0x8c04), board_ahci }, /* Lynx Point RAID */
308ebb82e3cSHans de Goede 	{ PCI_VDEVICE(INTEL, 0x8c05), board_ahci_mobile }, /* Lynx M RAID */
309ea4ace66SSeth Heasley 	{ PCI_VDEVICE(INTEL, 0x8c06), board_ahci }, /* Lynx Point RAID */
310ebb82e3cSHans de Goede 	{ PCI_VDEVICE(INTEL, 0x8c07), board_ahci_mobile }, /* Lynx M RAID */
311ea4ace66SSeth Heasley 	{ PCI_VDEVICE(INTEL, 0x8c0e), board_ahci }, /* Lynx Point RAID */
312ebb82e3cSHans de Goede 	{ PCI_VDEVICE(INTEL, 0x8c0f), board_ahci_mobile }, /* Lynx M RAID */
313ebb82e3cSHans de Goede 	{ PCI_VDEVICE(INTEL, 0x9c02), board_ahci_mobile }, /* Lynx LP AHCI */
314ebb82e3cSHans de Goede 	{ PCI_VDEVICE(INTEL, 0x9c03), board_ahci_mobile }, /* Lynx LP AHCI */
315ebb82e3cSHans de Goede 	{ PCI_VDEVICE(INTEL, 0x9c04), board_ahci_mobile }, /* Lynx LP RAID */
316ebb82e3cSHans de Goede 	{ PCI_VDEVICE(INTEL, 0x9c05), board_ahci_mobile }, /* Lynx LP RAID */
317ebb82e3cSHans de Goede 	{ PCI_VDEVICE(INTEL, 0x9c06), board_ahci_mobile }, /* Lynx LP RAID */
318ebb82e3cSHans de Goede 	{ PCI_VDEVICE(INTEL, 0x9c07), board_ahci_mobile }, /* Lynx LP RAID */
319ebb82e3cSHans de Goede 	{ PCI_VDEVICE(INTEL, 0x9c0e), board_ahci_mobile }, /* Lynx LP RAID */
320ebb82e3cSHans de Goede 	{ PCI_VDEVICE(INTEL, 0x9c0f), board_ahci_mobile }, /* Lynx LP RAID */
3214544e403SMika Westerberg 	{ PCI_VDEVICE(INTEL, 0x9dd3), board_ahci_mobile }, /* Cannon Lake PCH-LP AHCI */
32229e674ddSSeth Heasley 	{ PCI_VDEVICE(INTEL, 0x1f22), board_ahci }, /* Avoton AHCI */
32329e674ddSSeth Heasley 	{ PCI_VDEVICE(INTEL, 0x1f23), board_ahci }, /* Avoton AHCI */
32429e674ddSSeth Heasley 	{ PCI_VDEVICE(INTEL, 0x1f24), board_ahci }, /* Avoton RAID */
32529e674ddSSeth Heasley 	{ PCI_VDEVICE(INTEL, 0x1f25), board_ahci }, /* Avoton RAID */
32629e674ddSSeth Heasley 	{ PCI_VDEVICE(INTEL, 0x1f26), board_ahci }, /* Avoton RAID */
32729e674ddSSeth Heasley 	{ PCI_VDEVICE(INTEL, 0x1f27), board_ahci }, /* Avoton RAID */
32829e674ddSSeth Heasley 	{ PCI_VDEVICE(INTEL, 0x1f2e), board_ahci }, /* Avoton RAID */
32929e674ddSSeth Heasley 	{ PCI_VDEVICE(INTEL, 0x1f2f), board_ahci }, /* Avoton RAID */
330dbfe8ef5SDan Williams 	{ PCI_VDEVICE(INTEL, 0x1f32), board_ahci_avn }, /* Avoton AHCI */
331dbfe8ef5SDan Williams 	{ PCI_VDEVICE(INTEL, 0x1f33), board_ahci_avn }, /* Avoton AHCI */
332dbfe8ef5SDan Williams 	{ PCI_VDEVICE(INTEL, 0x1f34), board_ahci_avn }, /* Avoton RAID */
333dbfe8ef5SDan Williams 	{ PCI_VDEVICE(INTEL, 0x1f35), board_ahci_avn }, /* Avoton RAID */
334dbfe8ef5SDan Williams 	{ PCI_VDEVICE(INTEL, 0x1f36), board_ahci_avn }, /* Avoton RAID */
335dbfe8ef5SDan Williams 	{ PCI_VDEVICE(INTEL, 0x1f37), board_ahci_avn }, /* Avoton RAID */
336dbfe8ef5SDan Williams 	{ PCI_VDEVICE(INTEL, 0x1f3e), board_ahci_avn }, /* Avoton RAID */
337dbfe8ef5SDan Williams 	{ PCI_VDEVICE(INTEL, 0x1f3f), board_ahci_avn }, /* Avoton RAID */
338efda332cSJames Ralston 	{ PCI_VDEVICE(INTEL, 0x2823), board_ahci }, /* Wellsburg RAID */
339efda332cSJames Ralston 	{ PCI_VDEVICE(INTEL, 0x2827), board_ahci }, /* Wellsburg RAID */
340151743fdSJames Ralston 	{ PCI_VDEVICE(INTEL, 0x8d02), board_ahci }, /* Wellsburg AHCI */
341151743fdSJames Ralston 	{ PCI_VDEVICE(INTEL, 0x8d04), board_ahci }, /* Wellsburg RAID */
342151743fdSJames Ralston 	{ PCI_VDEVICE(INTEL, 0x8d06), board_ahci }, /* Wellsburg RAID */
343151743fdSJames Ralston 	{ PCI_VDEVICE(INTEL, 0x8d0e), board_ahci }, /* Wellsburg RAID */
344151743fdSJames Ralston 	{ PCI_VDEVICE(INTEL, 0x8d62), board_ahci }, /* Wellsburg AHCI */
345151743fdSJames Ralston 	{ PCI_VDEVICE(INTEL, 0x8d64), board_ahci }, /* Wellsburg RAID */
346151743fdSJames Ralston 	{ PCI_VDEVICE(INTEL, 0x8d66), board_ahci }, /* Wellsburg RAID */
347151743fdSJames Ralston 	{ PCI_VDEVICE(INTEL, 0x8d6e), board_ahci }, /* Wellsburg RAID */
3481cfc7df3SSeth Heasley 	{ PCI_VDEVICE(INTEL, 0x23a3), board_ahci }, /* Coleto Creek AHCI */
349ebb82e3cSHans de Goede 	{ PCI_VDEVICE(INTEL, 0x9c83), board_ahci_mobile }, /* Wildcat LP AHCI */
350ebb82e3cSHans de Goede 	{ PCI_VDEVICE(INTEL, 0x9c85), board_ahci_mobile }, /* Wildcat LP RAID */
351ebb82e3cSHans de Goede 	{ PCI_VDEVICE(INTEL, 0x9c87), board_ahci_mobile }, /* Wildcat LP RAID */
352ebb82e3cSHans de Goede 	{ PCI_VDEVICE(INTEL, 0x9c8f), board_ahci_mobile }, /* Wildcat LP RAID */
3531b071a09SJames Ralston 	{ PCI_VDEVICE(INTEL, 0x8c82), board_ahci }, /* 9 Series AHCI */
354ebb82e3cSHans de Goede 	{ PCI_VDEVICE(INTEL, 0x8c83), board_ahci_mobile }, /* 9 Series M AHCI */
3551b071a09SJames Ralston 	{ PCI_VDEVICE(INTEL, 0x8c84), board_ahci }, /* 9 Series RAID */
356ebb82e3cSHans de Goede 	{ PCI_VDEVICE(INTEL, 0x8c85), board_ahci_mobile }, /* 9 Series M RAID */
3571b071a09SJames Ralston 	{ PCI_VDEVICE(INTEL, 0x8c86), board_ahci }, /* 9 Series RAID */
358ebb82e3cSHans de Goede 	{ PCI_VDEVICE(INTEL, 0x8c87), board_ahci_mobile }, /* 9 Series M RAID */
3591b071a09SJames Ralston 	{ PCI_VDEVICE(INTEL, 0x8c8e), board_ahci }, /* 9 Series RAID */
360ebb82e3cSHans de Goede 	{ PCI_VDEVICE(INTEL, 0x8c8f), board_ahci_mobile }, /* 9 Series M RAID */
361ebb82e3cSHans de Goede 	{ PCI_VDEVICE(INTEL, 0x9d03), board_ahci_mobile }, /* Sunrise LP AHCI */
362ebb82e3cSHans de Goede 	{ PCI_VDEVICE(INTEL, 0x9d05), board_ahci_mobile }, /* Sunrise LP RAID */
363ebb82e3cSHans de Goede 	{ PCI_VDEVICE(INTEL, 0x9d07), board_ahci_mobile }, /* Sunrise LP RAID */
364c5967b79SCharles_Rose@Dell.com 	{ PCI_VDEVICE(INTEL, 0xa102), board_ahci }, /* Sunrise Point-H AHCI */
365ebb82e3cSHans de Goede 	{ PCI_VDEVICE(INTEL, 0xa103), board_ahci_mobile }, /* Sunrise M AHCI */
366690000b9SJames Ralston 	{ PCI_VDEVICE(INTEL, 0xa105), board_ahci }, /* Sunrise Point-H RAID */
367c5967b79SCharles_Rose@Dell.com 	{ PCI_VDEVICE(INTEL, 0xa106), board_ahci }, /* Sunrise Point-H RAID */
368ebb82e3cSHans de Goede 	{ PCI_VDEVICE(INTEL, 0xa107), board_ahci_mobile }, /* Sunrise M RAID */
369690000b9SJames Ralston 	{ PCI_VDEVICE(INTEL, 0xa10f), board_ahci }, /* Sunrise Point-H RAID */
3704d92f009SAlexandra Yates 	{ PCI_VDEVICE(INTEL, 0x2822), board_ahci }, /* Lewisburg RAID*/
371f5bdd66cSAlexandra Yates 	{ PCI_VDEVICE(INTEL, 0x2823), board_ahci }, /* Lewisburg AHCI*/
3724d92f009SAlexandra Yates 	{ PCI_VDEVICE(INTEL, 0x2826), board_ahci }, /* Lewisburg RAID*/
373f5bdd66cSAlexandra Yates 	{ PCI_VDEVICE(INTEL, 0x2827), board_ahci }, /* Lewisburg RAID*/
3744d92f009SAlexandra Yates 	{ PCI_VDEVICE(INTEL, 0xa182), board_ahci }, /* Lewisburg AHCI*/
3754d92f009SAlexandra Yates 	{ PCI_VDEVICE(INTEL, 0xa186), board_ahci }, /* Lewisburg RAID*/
376f5bdd66cSAlexandra Yates 	{ PCI_VDEVICE(INTEL, 0xa1d2), board_ahci }, /* Lewisburg RAID*/
377f5bdd66cSAlexandra Yates 	{ PCI_VDEVICE(INTEL, 0xa1d6), board_ahci }, /* Lewisburg RAID*/
3784d92f009SAlexandra Yates 	{ PCI_VDEVICE(INTEL, 0xa202), board_ahci }, /* Lewisburg AHCI*/
3794d92f009SAlexandra Yates 	{ PCI_VDEVICE(INTEL, 0xa206), board_ahci }, /* Lewisburg RAID*/
380f5bdd66cSAlexandra Yates 	{ PCI_VDEVICE(INTEL, 0xa252), board_ahci }, /* Lewisburg RAID*/
381f5bdd66cSAlexandra Yates 	{ PCI_VDEVICE(INTEL, 0xa256), board_ahci }, /* Lewisburg RAID*/
382f919dde0SMika Westerberg 	{ PCI_VDEVICE(INTEL, 0xa356), board_ahci }, /* Cannon Lake PCH-H RAID */
383ebb82e3cSHans de Goede 	{ PCI_VDEVICE(INTEL, 0x0f22), board_ahci_mobile }, /* Bay Trail AHCI */
384ebb82e3cSHans de Goede 	{ PCI_VDEVICE(INTEL, 0x0f23), board_ahci_mobile }, /* Bay Trail AHCI */
385ebb82e3cSHans de Goede 	{ PCI_VDEVICE(INTEL, 0x22a3), board_ahci_mobile }, /* Cherry Tr. AHCI */
386ebb82e3cSHans de Goede 	{ PCI_VDEVICE(INTEL, 0x5ae3), board_ahci_mobile }, /* ApolloLake AHCI */
387ba445791SMika Westerberg 	{ PCI_VDEVICE(INTEL, 0x34d3), board_ahci_mobile }, /* Ice Lake LP AHCI */
388c6fd2807SJeff Garzik 
389e34bb370STejun Heo 	/* JMicron 360/1/3/5/6, match class to avoid IDE function */
390e34bb370STejun Heo 	{ PCI_VENDOR_ID_JMICRON, PCI_ANY_ID, PCI_ANY_ID, PCI_ANY_ID,
391e34bb370STejun Heo 	  PCI_CLASS_STORAGE_SATA_AHCI, 0xffffff, board_ahci_ign_iferr },
3921fefb8fdSBen Hutchings 	/* JMicron 362B and 362C have an AHCI function with IDE class code */
3931fefb8fdSBen Hutchings 	{ PCI_VDEVICE(JMICRON, 0x2362), board_ahci_ign_iferr },
3941fefb8fdSBen Hutchings 	{ PCI_VDEVICE(JMICRON, 0x236f), board_ahci_ign_iferr },
39591f15fb3SZhang Rui 	/* May need to update quirk_jmicron_async_suspend() for additions */
396c6fd2807SJeff Garzik 
397c6fd2807SJeff Garzik 	/* ATI */
398c65ec1c2SConke Hu 	{ PCI_VDEVICE(ATI, 0x4380), board_ahci_sb600 }, /* ATI SB600 */
399e39fc8c9SShane Huang 	{ PCI_VDEVICE(ATI, 0x4390), board_ahci_sb700 }, /* ATI SB700/800 */
400e39fc8c9SShane Huang 	{ PCI_VDEVICE(ATI, 0x4391), board_ahci_sb700 }, /* ATI SB700/800 */
401e39fc8c9SShane Huang 	{ PCI_VDEVICE(ATI, 0x4392), board_ahci_sb700 }, /* ATI SB700/800 */
402e39fc8c9SShane Huang 	{ PCI_VDEVICE(ATI, 0x4393), board_ahci_sb700 }, /* ATI SB700/800 */
403e39fc8c9SShane Huang 	{ PCI_VDEVICE(ATI, 0x4394), board_ahci_sb700 }, /* ATI SB700/800 */
404e39fc8c9SShane Huang 	{ PCI_VDEVICE(ATI, 0x4395), board_ahci_sb700 }, /* ATI SB700/800 */
405c6fd2807SJeff Garzik 
406e2dd90b1SShane Huang 	/* AMD */
4075deab536SShane Huang 	{ PCI_VDEVICE(AMD, 0x7800), board_ahci }, /* AMD Hudson-2 */
408fafe5c3dSShane Huang 	{ PCI_VDEVICE(AMD, 0x7900), board_ahci }, /* AMD CZ */
409e2dd90b1SShane Huang 	/* AMD is using RAID class only for ahci controllers */
410e2dd90b1SShane Huang 	{ PCI_VENDOR_ID_AMD, PCI_ANY_ID, PCI_ANY_ID, PCI_ANY_ID,
411e2dd90b1SShane Huang 	  PCI_CLASS_STORAGE_RAID << 8, 0xffffff, board_ahci },
412e2dd90b1SShane Huang 
413c6fd2807SJeff Garzik 	/* VIA */
41454bb3a94SJeff Garzik 	{ PCI_VDEVICE(VIA, 0x3349), board_ahci_vt8251 }, /* VIA VT8251 */
415bf335542STejun Heo 	{ PCI_VDEVICE(VIA, 0x6287), board_ahci_vt8251 }, /* VIA VT8251 */
416c6fd2807SJeff Garzik 
417c6fd2807SJeff Garzik 	/* NVIDIA */
418e297d99eSTejun Heo 	{ PCI_VDEVICE(NVIDIA, 0x044c), board_ahci_mcp65 },	/* MCP65 */
419e297d99eSTejun Heo 	{ PCI_VDEVICE(NVIDIA, 0x044d), board_ahci_mcp65 },	/* MCP65 */
420e297d99eSTejun Heo 	{ PCI_VDEVICE(NVIDIA, 0x044e), board_ahci_mcp65 },	/* MCP65 */
421e297d99eSTejun Heo 	{ PCI_VDEVICE(NVIDIA, 0x044f), board_ahci_mcp65 },	/* MCP65 */
422e297d99eSTejun Heo 	{ PCI_VDEVICE(NVIDIA, 0x045c), board_ahci_mcp65 },	/* MCP65 */
423e297d99eSTejun Heo 	{ PCI_VDEVICE(NVIDIA, 0x045d), board_ahci_mcp65 },	/* MCP65 */
424e297d99eSTejun Heo 	{ PCI_VDEVICE(NVIDIA, 0x045e), board_ahci_mcp65 },	/* MCP65 */
425e297d99eSTejun Heo 	{ PCI_VDEVICE(NVIDIA, 0x045f), board_ahci_mcp65 },	/* MCP65 */
426441577efSTejun Heo 	{ PCI_VDEVICE(NVIDIA, 0x0550), board_ahci_mcp67 },	/* MCP67 */
427441577efSTejun Heo 	{ PCI_VDEVICE(NVIDIA, 0x0551), board_ahci_mcp67 },	/* MCP67 */
428441577efSTejun Heo 	{ PCI_VDEVICE(NVIDIA, 0x0552), board_ahci_mcp67 },	/* MCP67 */
429441577efSTejun Heo 	{ PCI_VDEVICE(NVIDIA, 0x0553), board_ahci_mcp67 },	/* MCP67 */
430441577efSTejun Heo 	{ PCI_VDEVICE(NVIDIA, 0x0554), board_ahci_mcp67 },	/* MCP67 */
431441577efSTejun Heo 	{ PCI_VDEVICE(NVIDIA, 0x0555), board_ahci_mcp67 },	/* MCP67 */
432441577efSTejun Heo 	{ PCI_VDEVICE(NVIDIA, 0x0556), board_ahci_mcp67 },	/* MCP67 */
433441577efSTejun Heo 	{ PCI_VDEVICE(NVIDIA, 0x0557), board_ahci_mcp67 },	/* MCP67 */
434441577efSTejun Heo 	{ PCI_VDEVICE(NVIDIA, 0x0558), board_ahci_mcp67 },	/* MCP67 */
435441577efSTejun Heo 	{ PCI_VDEVICE(NVIDIA, 0x0559), board_ahci_mcp67 },	/* MCP67 */
436441577efSTejun Heo 	{ PCI_VDEVICE(NVIDIA, 0x055a), board_ahci_mcp67 },	/* MCP67 */
437441577efSTejun Heo 	{ PCI_VDEVICE(NVIDIA, 0x055b), board_ahci_mcp67 },	/* MCP67 */
438441577efSTejun Heo 	{ PCI_VDEVICE(NVIDIA, 0x0580), board_ahci_mcp_linux },	/* Linux ID */
439441577efSTejun Heo 	{ PCI_VDEVICE(NVIDIA, 0x0581), board_ahci_mcp_linux },	/* Linux ID */
440441577efSTejun Heo 	{ PCI_VDEVICE(NVIDIA, 0x0582), board_ahci_mcp_linux },	/* Linux ID */
441441577efSTejun Heo 	{ PCI_VDEVICE(NVIDIA, 0x0583), board_ahci_mcp_linux },	/* Linux ID */
442441577efSTejun Heo 	{ PCI_VDEVICE(NVIDIA, 0x0584), board_ahci_mcp_linux },	/* Linux ID */
443441577efSTejun Heo 	{ PCI_VDEVICE(NVIDIA, 0x0585), board_ahci_mcp_linux },	/* Linux ID */
444441577efSTejun Heo 	{ PCI_VDEVICE(NVIDIA, 0x0586), board_ahci_mcp_linux },	/* Linux ID */
445441577efSTejun Heo 	{ PCI_VDEVICE(NVIDIA, 0x0587), board_ahci_mcp_linux },	/* Linux ID */
446441577efSTejun Heo 	{ PCI_VDEVICE(NVIDIA, 0x0588), board_ahci_mcp_linux },	/* Linux ID */
447441577efSTejun Heo 	{ PCI_VDEVICE(NVIDIA, 0x0589), board_ahci_mcp_linux },	/* Linux ID */
448441577efSTejun Heo 	{ PCI_VDEVICE(NVIDIA, 0x058a), board_ahci_mcp_linux },	/* Linux ID */
449441577efSTejun Heo 	{ PCI_VDEVICE(NVIDIA, 0x058b), board_ahci_mcp_linux },	/* Linux ID */
450441577efSTejun Heo 	{ PCI_VDEVICE(NVIDIA, 0x058c), board_ahci_mcp_linux },	/* Linux ID */
451441577efSTejun Heo 	{ PCI_VDEVICE(NVIDIA, 0x058d), board_ahci_mcp_linux },	/* Linux ID */
452441577efSTejun Heo 	{ PCI_VDEVICE(NVIDIA, 0x058e), board_ahci_mcp_linux },	/* Linux ID */
453441577efSTejun Heo 	{ PCI_VDEVICE(NVIDIA, 0x058f), board_ahci_mcp_linux },	/* Linux ID */
454441577efSTejun Heo 	{ PCI_VDEVICE(NVIDIA, 0x07f0), board_ahci_mcp73 },	/* MCP73 */
455441577efSTejun Heo 	{ PCI_VDEVICE(NVIDIA, 0x07f1), board_ahci_mcp73 },	/* MCP73 */
456441577efSTejun Heo 	{ PCI_VDEVICE(NVIDIA, 0x07f2), board_ahci_mcp73 },	/* MCP73 */
457441577efSTejun Heo 	{ PCI_VDEVICE(NVIDIA, 0x07f3), board_ahci_mcp73 },	/* MCP73 */
458441577efSTejun Heo 	{ PCI_VDEVICE(NVIDIA, 0x07f4), board_ahci_mcp73 },	/* MCP73 */
459441577efSTejun Heo 	{ PCI_VDEVICE(NVIDIA, 0x07f5), board_ahci_mcp73 },	/* MCP73 */
460441577efSTejun Heo 	{ PCI_VDEVICE(NVIDIA, 0x07f6), board_ahci_mcp73 },	/* MCP73 */
461441577efSTejun Heo 	{ PCI_VDEVICE(NVIDIA, 0x07f7), board_ahci_mcp73 },	/* MCP73 */
462441577efSTejun Heo 	{ PCI_VDEVICE(NVIDIA, 0x07f8), board_ahci_mcp73 },	/* MCP73 */
463441577efSTejun Heo 	{ PCI_VDEVICE(NVIDIA, 0x07f9), board_ahci_mcp73 },	/* MCP73 */
464441577efSTejun Heo 	{ PCI_VDEVICE(NVIDIA, 0x07fa), board_ahci_mcp73 },	/* MCP73 */
465441577efSTejun Heo 	{ PCI_VDEVICE(NVIDIA, 0x07fb), board_ahci_mcp73 },	/* MCP73 */
466441577efSTejun Heo 	{ PCI_VDEVICE(NVIDIA, 0x0ad0), board_ahci_mcp77 },	/* MCP77 */
467441577efSTejun Heo 	{ PCI_VDEVICE(NVIDIA, 0x0ad1), board_ahci_mcp77 },	/* MCP77 */
468441577efSTejun Heo 	{ PCI_VDEVICE(NVIDIA, 0x0ad2), board_ahci_mcp77 },	/* MCP77 */
469441577efSTejun Heo 	{ PCI_VDEVICE(NVIDIA, 0x0ad3), board_ahci_mcp77 },	/* MCP77 */
470441577efSTejun Heo 	{ PCI_VDEVICE(NVIDIA, 0x0ad4), board_ahci_mcp77 },	/* MCP77 */
471441577efSTejun Heo 	{ PCI_VDEVICE(NVIDIA, 0x0ad5), board_ahci_mcp77 },	/* MCP77 */
472441577efSTejun Heo 	{ PCI_VDEVICE(NVIDIA, 0x0ad6), board_ahci_mcp77 },	/* MCP77 */
473441577efSTejun Heo 	{ PCI_VDEVICE(NVIDIA, 0x0ad7), board_ahci_mcp77 },	/* MCP77 */
474441577efSTejun Heo 	{ PCI_VDEVICE(NVIDIA, 0x0ad8), board_ahci_mcp77 },	/* MCP77 */
475441577efSTejun Heo 	{ PCI_VDEVICE(NVIDIA, 0x0ad9), board_ahci_mcp77 },	/* MCP77 */
476441577efSTejun Heo 	{ PCI_VDEVICE(NVIDIA, 0x0ada), board_ahci_mcp77 },	/* MCP77 */
477441577efSTejun Heo 	{ PCI_VDEVICE(NVIDIA, 0x0adb), board_ahci_mcp77 },	/* MCP77 */
478441577efSTejun Heo 	{ PCI_VDEVICE(NVIDIA, 0x0ab4), board_ahci_mcp79 },	/* MCP79 */
479441577efSTejun Heo 	{ PCI_VDEVICE(NVIDIA, 0x0ab5), board_ahci_mcp79 },	/* MCP79 */
480441577efSTejun Heo 	{ PCI_VDEVICE(NVIDIA, 0x0ab6), board_ahci_mcp79 },	/* MCP79 */
481441577efSTejun Heo 	{ PCI_VDEVICE(NVIDIA, 0x0ab7), board_ahci_mcp79 },	/* MCP79 */
482441577efSTejun Heo 	{ PCI_VDEVICE(NVIDIA, 0x0ab8), board_ahci_mcp79 },	/* MCP79 */
483441577efSTejun Heo 	{ PCI_VDEVICE(NVIDIA, 0x0ab9), board_ahci_mcp79 },	/* MCP79 */
484441577efSTejun Heo 	{ PCI_VDEVICE(NVIDIA, 0x0aba), board_ahci_mcp79 },	/* MCP79 */
485441577efSTejun Heo 	{ PCI_VDEVICE(NVIDIA, 0x0abb), board_ahci_mcp79 },	/* MCP79 */
486441577efSTejun Heo 	{ PCI_VDEVICE(NVIDIA, 0x0abc), board_ahci_mcp79 },	/* MCP79 */
487441577efSTejun Heo 	{ PCI_VDEVICE(NVIDIA, 0x0abd), board_ahci_mcp79 },	/* MCP79 */
488441577efSTejun Heo 	{ PCI_VDEVICE(NVIDIA, 0x0abe), board_ahci_mcp79 },	/* MCP79 */
489441577efSTejun Heo 	{ PCI_VDEVICE(NVIDIA, 0x0abf), board_ahci_mcp79 },	/* MCP79 */
490441577efSTejun Heo 	{ PCI_VDEVICE(NVIDIA, 0x0d84), board_ahci_mcp89 },	/* MCP89 */
491441577efSTejun Heo 	{ PCI_VDEVICE(NVIDIA, 0x0d85), board_ahci_mcp89 },	/* MCP89 */
492441577efSTejun Heo 	{ PCI_VDEVICE(NVIDIA, 0x0d86), board_ahci_mcp89 },	/* MCP89 */
493441577efSTejun Heo 	{ PCI_VDEVICE(NVIDIA, 0x0d87), board_ahci_mcp89 },	/* MCP89 */
494441577efSTejun Heo 	{ PCI_VDEVICE(NVIDIA, 0x0d88), board_ahci_mcp89 },	/* MCP89 */
495441577efSTejun Heo 	{ PCI_VDEVICE(NVIDIA, 0x0d89), board_ahci_mcp89 },	/* MCP89 */
496441577efSTejun Heo 	{ PCI_VDEVICE(NVIDIA, 0x0d8a), board_ahci_mcp89 },	/* MCP89 */
497441577efSTejun Heo 	{ PCI_VDEVICE(NVIDIA, 0x0d8b), board_ahci_mcp89 },	/* MCP89 */
498441577efSTejun Heo 	{ PCI_VDEVICE(NVIDIA, 0x0d8c), board_ahci_mcp89 },	/* MCP89 */
499441577efSTejun Heo 	{ PCI_VDEVICE(NVIDIA, 0x0d8d), board_ahci_mcp89 },	/* MCP89 */
500441577efSTejun Heo 	{ PCI_VDEVICE(NVIDIA, 0x0d8e), board_ahci_mcp89 },	/* MCP89 */
501441577efSTejun Heo 	{ PCI_VDEVICE(NVIDIA, 0x0d8f), board_ahci_mcp89 },	/* MCP89 */
502c6fd2807SJeff Garzik 
503c6fd2807SJeff Garzik 	/* SiS */
50420e2de4aSTejun Heo 	{ PCI_VDEVICE(SI, 0x1184), board_ahci },		/* SiS 966 */
50520e2de4aSTejun Heo 	{ PCI_VDEVICE(SI, 0x1185), board_ahci },		/* SiS 968 */
50620e2de4aSTejun Heo 	{ PCI_VDEVICE(SI, 0x0186), board_ahci },		/* SiS 968 */
507c6fd2807SJeff Garzik 
508318893e1SAlessandro Rubini 	/* ST Microelectronics */
509318893e1SAlessandro Rubini 	{ PCI_VDEVICE(STMICRO, 0xCC06), board_ahci },		/* ST ConneXt */
510318893e1SAlessandro Rubini 
511cd70c266SJeff Garzik 	/* Marvell */
512cd70c266SJeff Garzik 	{ PCI_VDEVICE(MARVELL, 0x6145), board_ahci_mv },	/* 6145 */
513c40e7cb8SJose Alberto Reguero 	{ PCI_VDEVICE(MARVELL, 0x6121), board_ahci_mv },	/* 6121 */
51469fd3157SMyron Stowe 	{ PCI_DEVICE(PCI_VENDOR_ID_MARVELL_EXT, 0x9123),
51510aca06cSAnssi Hannula 	  .class = PCI_CLASS_STORAGE_SATA_AHCI,
51610aca06cSAnssi Hannula 	  .class_mask = 0xffffff,
5175f173107STejun Heo 	  .driver_data = board_ahci_yes_fbs },			/* 88se9128 */
51869fd3157SMyron Stowe 	{ PCI_DEVICE(PCI_VENDOR_ID_MARVELL_EXT, 0x9125),
519467b41c6SPer Jessen 	  .driver_data = board_ahci_yes_fbs },			/* 88se9125 */
520e098f5cbSSimon Guinot 	{ PCI_DEVICE_SUB(PCI_VENDOR_ID_MARVELL_EXT, 0x9178,
521e098f5cbSSimon Guinot 			 PCI_VENDOR_ID_MARVELL_EXT, 0x9170),
522e098f5cbSSimon Guinot 	  .driver_data = board_ahci_yes_fbs },			/* 88se9170 */
52369fd3157SMyron Stowe 	{ PCI_DEVICE(PCI_VENDOR_ID_MARVELL_EXT, 0x917a),
524642d8925SMatt Johnson 	  .driver_data = board_ahci_yes_fbs },			/* 88se9172 */
525fcce9a35SGeorge Spelvin 	{ PCI_DEVICE(PCI_VENDOR_ID_MARVELL_EXT, 0x9172),
526c5edfff9SMurali Karicheri 	  .driver_data = board_ahci_yes_fbs },			/* 88se9182 */
527c5edfff9SMurali Karicheri 	{ PCI_DEVICE(PCI_VENDOR_ID_MARVELL_EXT, 0x9182),
528fcce9a35SGeorge Spelvin 	  .driver_data = board_ahci_yes_fbs },			/* 88se9172 */
52969fd3157SMyron Stowe 	{ PCI_DEVICE(PCI_VENDOR_ID_MARVELL_EXT, 0x9192),
53017c60c6bSAlan Cox 	  .driver_data = board_ahci_yes_fbs },			/* 88se9172 on some Gigabyte */
531754a292fSAndreas Schrägle 	{ PCI_DEVICE(PCI_VENDOR_ID_MARVELL_EXT, 0x91a0),
532754a292fSAndreas Schrägle 	  .driver_data = board_ahci_yes_fbs },
533a40cf3f3SJohannes Thumshirn 	{ PCI_DEVICE(PCI_VENDOR_ID_MARVELL_EXT, 0x91a2), 	/* 88se91a2 */
534a40cf3f3SJohannes Thumshirn 	  .driver_data = board_ahci_yes_fbs },
53569fd3157SMyron Stowe 	{ PCI_DEVICE(PCI_VENDOR_ID_MARVELL_EXT, 0x91a3),
53650be5e36STejun Heo 	  .driver_data = board_ahci_yes_fbs },
5376d5278a6SSamir Benmendil 	{ PCI_DEVICE(PCI_VENDOR_ID_MARVELL_EXT, 0x9230),
5386d5278a6SSamir Benmendil 	  .driver_data = board_ahci_yes_fbs },
53928b2182dSHans de Goede 	{ PCI_DEVICE(PCI_VENDOR_ID_TTI, 0x0642), /* highpoint rocketraid 642L */
54028b2182dSHans de Goede 	  .driver_data = board_ahci_yes_fbs },
54128b2182dSHans de Goede 	{ PCI_DEVICE(PCI_VENDOR_ID_TTI, 0x0645), /* highpoint rocketraid 644L */
542d2518365SJérôme Carretero 	  .driver_data = board_ahci_yes_fbs },
543cd70c266SJeff Garzik 
544c77a036bSMark Nelson 	/* Promise */
545c77a036bSMark Nelson 	{ PCI_VDEVICE(PROMISE, 0x3f20), board_ahci },	/* PDC42819 */
546b32bfc06SRomain Degez 	{ PCI_VDEVICE(PROMISE, 0x3781), board_ahci },   /* FastTrak TX8660 ahci-mode */
547c77a036bSMark Nelson 
548c9703765SKeng-Yu Lin 	/* Asmedia */
5497b4f6ecaSAlan Cox 	{ PCI_VDEVICE(ASMEDIA, 0x0601), board_ahci },	/* ASM1060 */
5507b4f6ecaSAlan Cox 	{ PCI_VDEVICE(ASMEDIA, 0x0602), board_ahci },	/* ASM1060 */
5517b4f6ecaSAlan Cox 	{ PCI_VDEVICE(ASMEDIA, 0x0611), board_ahci },	/* ASM1061 */
5527b4f6ecaSAlan Cox 	{ PCI_VDEVICE(ASMEDIA, 0x0612), board_ahci },	/* ASM1062 */
5530ce968f3SShawn Lin 	{ PCI_VDEVICE(ASMEDIA, 0x0621), board_ahci },   /* ASM1061R */
5540ce968f3SShawn Lin 	{ PCI_VDEVICE(ASMEDIA, 0x0622), board_ahci },   /* ASM1062R */
555c9703765SKeng-Yu Lin 
55667809f85SLevente Kurusa 	/*
55766a7cbc3STejun Heo 	 * Samsung SSDs found on some macbooks.  NCQ times out if MSI is
55866a7cbc3STejun Heo 	 * enabled.  https://bugzilla.kernel.org/show_bug.cgi?id=60731
55967809f85SLevente Kurusa 	 */
56066a7cbc3STejun Heo 	{ PCI_VDEVICE(SAMSUNG, 0x1600), board_ahci_nomsi },
5612b21ef0aSTejun Heo 	{ PCI_VDEVICE(SAMSUNG, 0xa800), board_ahci_nomsi },
56267809f85SLevente Kurusa 
5637f9c9f8eSHugh Daschbach 	/* Enmotus */
5647f9c9f8eSHugh Daschbach 	{ PCI_DEVICE(0x1c44, 0x8000), board_ahci },
5657f9c9f8eSHugh Daschbach 
566415ae2b5SJeff Garzik 	/* Generic, PCI class code for AHCI */
567415ae2b5SJeff Garzik 	{ PCI_ANY_ID, PCI_ANY_ID, PCI_ANY_ID, PCI_ANY_ID,
568c9f89475SConke Hu 	  PCI_CLASS_STORAGE_SATA_AHCI, 0xffffff, board_ahci },
569415ae2b5SJeff Garzik 
570c6fd2807SJeff Garzik 	{ }	/* terminate list */
571c6fd2807SJeff Garzik };
572c6fd2807SJeff Garzik 
573f1d848f9SMika Westerberg static const struct dev_pm_ops ahci_pci_pm_ops = {
574f1d848f9SMika Westerberg 	SET_SYSTEM_SLEEP_PM_OPS(ahci_pci_device_suspend, ahci_pci_device_resume)
57502e53293SMika Westerberg 	SET_RUNTIME_PM_OPS(ahci_pci_device_runtime_suspend,
57602e53293SMika Westerberg 			   ahci_pci_device_runtime_resume, NULL)
577f1d848f9SMika Westerberg };
578c6fd2807SJeff Garzik 
579c6fd2807SJeff Garzik static struct pci_driver ahci_pci_driver = {
580c6fd2807SJeff Garzik 	.name			= DRV_NAME,
581c6fd2807SJeff Garzik 	.id_table		= ahci_pci_tbl,
582c6fd2807SJeff Garzik 	.probe			= ahci_init_one,
58302e53293SMika Westerberg 	.remove			= ahci_remove_one,
584f1d848f9SMika Westerberg 	.driver = {
585f1d848f9SMika Westerberg 		.pm		= &ahci_pci_pm_ops,
586f1d848f9SMika Westerberg 	},
587c6fd2807SJeff Garzik };
588c6fd2807SJeff Garzik 
5895219d653SJavier Martinez Canillas #if IS_ENABLED(CONFIG_PATA_MARVELL)
5905b66c829SAlan Cox static int marvell_enable;
5915b66c829SAlan Cox #else
5925b66c829SAlan Cox static int marvell_enable = 1;
5935b66c829SAlan Cox #endif
5945b66c829SAlan Cox module_param(marvell_enable, int, 0644);
5955b66c829SAlan Cox MODULE_PARM_DESC(marvell_enable, "Marvell SATA via AHCI (1 = enabled)");
5965b66c829SAlan Cox 
597b1a9585cSSrinivas Pandruvada static int mobile_lpm_policy = -1;
598ebb82e3cSHans de Goede module_param(mobile_lpm_policy, int, 0644);
599ebb82e3cSHans de Goede MODULE_PARM_DESC(mobile_lpm_policy, "Default LPM policy for mobile chipsets");
6005b66c829SAlan Cox 
601394d6e53SAnton Vorontsov static void ahci_pci_save_initial_config(struct pci_dev *pdev,
602394d6e53SAnton Vorontsov 					 struct ahci_host_priv *hpriv)
603394d6e53SAnton Vorontsov {
604394d6e53SAnton Vorontsov 	if (pdev->vendor == PCI_VENDOR_ID_JMICRON && pdev->device == 0x2361) {
605394d6e53SAnton Vorontsov 		dev_info(&pdev->dev, "JMB361 has only one port\n");
6069a23c1d6SAntoine Tenart 		hpriv->force_port_map = 1;
607394d6e53SAnton Vorontsov 	}
608394d6e53SAnton Vorontsov 
609394d6e53SAnton Vorontsov 	/*
610394d6e53SAnton Vorontsov 	 * Temporary Marvell 6145 hack: PATA port presence
611394d6e53SAnton Vorontsov 	 * is asserted through the standard AHCI port
612394d6e53SAnton Vorontsov 	 * presence register, as bit 4 (counting from 0)
613394d6e53SAnton Vorontsov 	 */
614394d6e53SAnton Vorontsov 	if (hpriv->flags & AHCI_HFLAG_MV_PATA) {
615394d6e53SAnton Vorontsov 		if (pdev->device == 0x6121)
6169a23c1d6SAntoine Tenart 			hpriv->mask_port_map = 0x3;
617394d6e53SAnton Vorontsov 		else
6189a23c1d6SAntoine Tenart 			hpriv->mask_port_map = 0xf;
619394d6e53SAnton Vorontsov 		dev_info(&pdev->dev,
620394d6e53SAnton Vorontsov 			  "Disabling your PATA port. Use the boot option 'ahci.marvell_enable=0' to avoid this.\n");
621394d6e53SAnton Vorontsov 	}
622394d6e53SAnton Vorontsov 
623725c7b57SAntoine Ténart 	ahci_save_initial_config(&pdev->dev, hpriv);
624394d6e53SAnton Vorontsov }
625394d6e53SAnton Vorontsov 
6263303040dSAnton Vorontsov static int ahci_pci_reset_controller(struct ata_host *host)
6273303040dSAnton Vorontsov {
6283303040dSAnton Vorontsov 	struct pci_dev *pdev = to_pci_dev(host->dev);
629d312fefeSArd Biesheuvel 	int rc;
6303303040dSAnton Vorontsov 
631d312fefeSArd Biesheuvel 	rc = ahci_reset_controller(host);
632d312fefeSArd Biesheuvel 	if (rc)
633d312fefeSArd Biesheuvel 		return rc;
6343303040dSAnton Vorontsov 
635c6fd2807SJeff Garzik 	if (pdev->vendor == PCI_VENDOR_ID_INTEL) {
6363303040dSAnton Vorontsov 		struct ahci_host_priv *hpriv = host->private_data;
637c6fd2807SJeff Garzik 		u16 tmp16;
638c6fd2807SJeff Garzik 
639c6fd2807SJeff Garzik 		/* configure PCS */
640c6fd2807SJeff Garzik 		pci_read_config_word(pdev, 0x92, &tmp16);
64149f29090STejun Heo 		if ((tmp16 & hpriv->port_map) != hpriv->port_map) {
64249f29090STejun Heo 			tmp16 |= hpriv->port_map;
643c6fd2807SJeff Garzik 			pci_write_config_word(pdev, 0x92, tmp16);
644c6fd2807SJeff Garzik 		}
64549f29090STejun Heo 	}
646c6fd2807SJeff Garzik 
647c6fd2807SJeff Garzik 	return 0;
648c6fd2807SJeff Garzik }
649c6fd2807SJeff Garzik 
650781d6550SAnton Vorontsov static void ahci_pci_init_controller(struct ata_host *host)
651781d6550SAnton Vorontsov {
652781d6550SAnton Vorontsov 	struct ahci_host_priv *hpriv = host->private_data;
653781d6550SAnton Vorontsov 	struct pci_dev *pdev = to_pci_dev(host->dev);
654781d6550SAnton Vorontsov 	void __iomem *port_mmio;
655781d6550SAnton Vorontsov 	u32 tmp;
656c40e7cb8SJose Alberto Reguero 	int mv;
6572bcd866bSJeff Garzik 
658417a1a6dSTejun Heo 	if (hpriv->flags & AHCI_HFLAG_MV_PATA) {
659c40e7cb8SJose Alberto Reguero 		if (pdev->device == 0x6121)
660c40e7cb8SJose Alberto Reguero 			mv = 2;
661c40e7cb8SJose Alberto Reguero 		else
662c40e7cb8SJose Alberto Reguero 			mv = 4;
663c40e7cb8SJose Alberto Reguero 		port_mmio = __ahci_port_base(host, mv);
664cd70c266SJeff Garzik 
665cd70c266SJeff Garzik 		writel(0, port_mmio + PORT_IRQ_MASK);
666cd70c266SJeff Garzik 
667cd70c266SJeff Garzik 		/* clear port IRQ */
668cd70c266SJeff Garzik 		tmp = readl(port_mmio + PORT_IRQ_STAT);
669cd70c266SJeff Garzik 		VPRINTK("PORT_IRQ_STAT 0x%x\n", tmp);
670cd70c266SJeff Garzik 		if (tmp)
671cd70c266SJeff Garzik 			writel(tmp, port_mmio + PORT_IRQ_STAT);
672cd70c266SJeff Garzik 	}
673cd70c266SJeff Garzik 
674781d6550SAnton Vorontsov 	ahci_init_controller(host);
675c6fd2807SJeff Garzik }
676c6fd2807SJeff Garzik 
677cc0680a5STejun Heo static int ahci_vt8251_hardreset(struct ata_link *link, unsigned int *class,
678d4b2bab4STejun Heo 				 unsigned long deadline)
679ad616ffbSTejun Heo {
680cc0680a5STejun Heo 	struct ata_port *ap = link->ap;
681039ece38SHans de Goede 	struct ahci_host_priv *hpriv = ap->host->private_data;
6829dadd45bSTejun Heo 	bool online;
683ad616ffbSTejun Heo 	int rc;
684ad616ffbSTejun Heo 
685ad616ffbSTejun Heo 	DPRINTK("ENTER\n");
686ad616ffbSTejun Heo 
687fa89f53bSEvan Wang 	hpriv->stop_engine(ap);
688ad616ffbSTejun Heo 
689cc0680a5STejun Heo 	rc = sata_link_hardreset(link, sata_ehc_deb_timing(&link->eh_context),
6909dadd45bSTejun Heo 				 deadline, &online, NULL);
691ad616ffbSTejun Heo 
692039ece38SHans de Goede 	hpriv->start_engine(ap);
693ad616ffbSTejun Heo 
694ad616ffbSTejun Heo 	DPRINTK("EXIT, rc=%d, class=%u\n", rc, *class);
695ad616ffbSTejun Heo 
696ad616ffbSTejun Heo 	/* vt8251 doesn't clear BSY on signature FIS reception,
697ad616ffbSTejun Heo 	 * request follow-up softreset.
698ad616ffbSTejun Heo 	 */
6999dadd45bSTejun Heo 	return online ? -EAGAIN : rc;
700ad616ffbSTejun Heo }
701ad616ffbSTejun Heo 
702edc93052STejun Heo static int ahci_p5wdh_hardreset(struct ata_link *link, unsigned int *class,
703edc93052STejun Heo 				unsigned long deadline)
704edc93052STejun Heo {
705edc93052STejun Heo 	struct ata_port *ap = link->ap;
706edc93052STejun Heo 	struct ahci_port_priv *pp = ap->private_data;
707039ece38SHans de Goede 	struct ahci_host_priv *hpriv = ap->host->private_data;
708edc93052STejun Heo 	u8 *d2h_fis = pp->rx_fis + RX_FIS_D2H_REG;
709edc93052STejun Heo 	struct ata_taskfile tf;
7109dadd45bSTejun Heo 	bool online;
711edc93052STejun Heo 	int rc;
712edc93052STejun Heo 
713fa89f53bSEvan Wang 	hpriv->stop_engine(ap);
714edc93052STejun Heo 
715edc93052STejun Heo 	/* clear D2H reception area to properly wait for D2H FIS */
716edc93052STejun Heo 	ata_tf_init(link->device, &tf);
7179bbb1b0eSSergei Shtylyov 	tf.command = ATA_BUSY;
718edc93052STejun Heo 	ata_tf_to_fis(&tf, 0, 0, d2h_fis);
719edc93052STejun Heo 
720edc93052STejun Heo 	rc = sata_link_hardreset(link, sata_ehc_deb_timing(&link->eh_context),
7219dadd45bSTejun Heo 				 deadline, &online, NULL);
722edc93052STejun Heo 
723039ece38SHans de Goede 	hpriv->start_engine(ap);
724edc93052STejun Heo 
725edc93052STejun Heo 	/* The pseudo configuration device on SIMG4726 attached to
726edc93052STejun Heo 	 * ASUS P5W-DH Deluxe doesn't send signature FIS after
727edc93052STejun Heo 	 * hardreset if no device is attached to the first downstream
728edc93052STejun Heo 	 * port && the pseudo device locks up on SRST w/ PMP==0.  To
729edc93052STejun Heo 	 * work around this, wait for !BSY only briefly.  If BSY isn't
730edc93052STejun Heo 	 * cleared, perform CLO and proceed to IDENTIFY (achieved by
731edc93052STejun Heo 	 * ATA_LFLAG_NO_SRST and ATA_LFLAG_ASSUME_ATA).
732edc93052STejun Heo 	 *
733edc93052STejun Heo 	 * Wait for two seconds.  Devices attached to downstream port
734edc93052STejun Heo 	 * which can't process the following IDENTIFY after this will
735edc93052STejun Heo 	 * have to be reset again.  For most cases, this should
736edc93052STejun Heo 	 * suffice while making probing snappish enough.
737edc93052STejun Heo 	 */
7389dadd45bSTejun Heo 	if (online) {
7399dadd45bSTejun Heo 		rc = ata_wait_after_reset(link, jiffies + 2 * HZ,
7409dadd45bSTejun Heo 					  ahci_check_ready);
741edc93052STejun Heo 		if (rc)
74278d5ae39SShane Huang 			ahci_kick_engine(ap);
7439dadd45bSTejun Heo 	}
7449dadd45bSTejun Heo 	return rc;
745edc93052STejun Heo }
746edc93052STejun Heo 
747dbfe8ef5SDan Williams /*
748dbfe8ef5SDan Williams  * ahci_avn_hardreset - attempt more aggressive recovery of Avoton ports.
749dbfe8ef5SDan Williams  *
750dbfe8ef5SDan Williams  * It has been observed with some SSDs that the timing of events in the
751dbfe8ef5SDan Williams  * link synchronization phase can leave the port in a state that can not
752dbfe8ef5SDan Williams  * be recovered by a SATA-hard-reset alone.  The failing signature is
753dbfe8ef5SDan Williams  * SStatus.DET stuck at 1 ("Device presence detected but Phy
754dbfe8ef5SDan Williams  * communication not established").  It was found that unloading and
755dbfe8ef5SDan Williams  * reloading the driver when this problem occurs allows the drive
756dbfe8ef5SDan Williams  * connection to be recovered (DET advanced to 0x3).  The critical
757dbfe8ef5SDan Williams  * component of reloading the driver is that the port state machines are
758dbfe8ef5SDan Williams  * reset by bouncing "port enable" in the AHCI PCS configuration
759dbfe8ef5SDan Williams  * register.  So, reproduce that effect by bouncing a port whenever we
760dbfe8ef5SDan Williams  * see DET==1 after a reset.
761dbfe8ef5SDan Williams  */
762dbfe8ef5SDan Williams static int ahci_avn_hardreset(struct ata_link *link, unsigned int *class,
763dbfe8ef5SDan Williams 			      unsigned long deadline)
764dbfe8ef5SDan Williams {
765dbfe8ef5SDan Williams 	const unsigned long *timing = sata_ehc_deb_timing(&link->eh_context);
766dbfe8ef5SDan Williams 	struct ata_port *ap = link->ap;
767dbfe8ef5SDan Williams 	struct ahci_port_priv *pp = ap->private_data;
768dbfe8ef5SDan Williams 	struct ahci_host_priv *hpriv = ap->host->private_data;
769dbfe8ef5SDan Williams 	u8 *d2h_fis = pp->rx_fis + RX_FIS_D2H_REG;
770dbfe8ef5SDan Williams 	unsigned long tmo = deadline - jiffies;
771dbfe8ef5SDan Williams 	struct ata_taskfile tf;
772dbfe8ef5SDan Williams 	bool online;
773dbfe8ef5SDan Williams 	int rc, i;
774dbfe8ef5SDan Williams 
775dbfe8ef5SDan Williams 	DPRINTK("ENTER\n");
776dbfe8ef5SDan Williams 
777fa89f53bSEvan Wang 	hpriv->stop_engine(ap);
778dbfe8ef5SDan Williams 
779dbfe8ef5SDan Williams 	for (i = 0; i < 2; i++) {
780dbfe8ef5SDan Williams 		u16 val;
781dbfe8ef5SDan Williams 		u32 sstatus;
782dbfe8ef5SDan Williams 		int port = ap->port_no;
783dbfe8ef5SDan Williams 		struct ata_host *host = ap->host;
784dbfe8ef5SDan Williams 		struct pci_dev *pdev = to_pci_dev(host->dev);
785dbfe8ef5SDan Williams 
786dbfe8ef5SDan Williams 		/* clear D2H reception area to properly wait for D2H FIS */
787dbfe8ef5SDan Williams 		ata_tf_init(link->device, &tf);
788dbfe8ef5SDan Williams 		tf.command = ATA_BUSY;
789dbfe8ef5SDan Williams 		ata_tf_to_fis(&tf, 0, 0, d2h_fis);
790dbfe8ef5SDan Williams 
791dbfe8ef5SDan Williams 		rc = sata_link_hardreset(link, timing, deadline, &online,
792dbfe8ef5SDan Williams 				ahci_check_ready);
793dbfe8ef5SDan Williams 
794dbfe8ef5SDan Williams 		if (sata_scr_read(link, SCR_STATUS, &sstatus) != 0 ||
795dbfe8ef5SDan Williams 				(sstatus & 0xf) != 1)
796dbfe8ef5SDan Williams 			break;
797dbfe8ef5SDan Williams 
798dbfe8ef5SDan Williams 		ata_link_printk(link, KERN_INFO, "avn bounce port%d\n",
799dbfe8ef5SDan Williams 				port);
800dbfe8ef5SDan Williams 
801dbfe8ef5SDan Williams 		pci_read_config_word(pdev, 0x92, &val);
802dbfe8ef5SDan Williams 		val &= ~(1 << port);
803dbfe8ef5SDan Williams 		pci_write_config_word(pdev, 0x92, val);
804dbfe8ef5SDan Williams 		ata_msleep(ap, 1000);
805dbfe8ef5SDan Williams 		val |= 1 << port;
806dbfe8ef5SDan Williams 		pci_write_config_word(pdev, 0x92, val);
807dbfe8ef5SDan Williams 		deadline += tmo;
808dbfe8ef5SDan Williams 	}
809dbfe8ef5SDan Williams 
810dbfe8ef5SDan Williams 	hpriv->start_engine(ap);
811dbfe8ef5SDan Williams 
812dbfe8ef5SDan Williams 	if (online)
813dbfe8ef5SDan Williams 		*class = ahci_dev_classify(ap);
814dbfe8ef5SDan Williams 
815dbfe8ef5SDan Williams 	DPRINTK("EXIT, rc=%d, class=%u\n", rc, *class);
816dbfe8ef5SDan Williams 	return rc;
817dbfe8ef5SDan Williams }
818dbfe8ef5SDan Williams 
819dbfe8ef5SDan Williams 
82002e53293SMika Westerberg #ifdef CONFIG_PM
82102e53293SMika Westerberg static void ahci_pci_disable_interrupts(struct ata_host *host)
822c6fd2807SJeff Garzik {
8239b10ae86STejun Heo 	struct ahci_host_priv *hpriv = host->private_data;
824d8993349SAnton Vorontsov 	void __iomem *mmio = hpriv->mmio;
825c6fd2807SJeff Garzik 	u32 ctl;
826c6fd2807SJeff Garzik 
827c6fd2807SJeff Garzik 	/* AHCI spec rev1.1 section 8.3.3:
828c6fd2807SJeff Garzik 	 * Software must disable interrupts prior to requesting a
829c6fd2807SJeff Garzik 	 * transition of the HBA to D3 state.
830c6fd2807SJeff Garzik 	 */
831c6fd2807SJeff Garzik 	ctl = readl(mmio + HOST_CTL);
832c6fd2807SJeff Garzik 	ctl &= ~HOST_IRQ_EN;
833c6fd2807SJeff Garzik 	writel(ctl, mmio + HOST_CTL);
834c6fd2807SJeff Garzik 	readl(mmio + HOST_CTL); /* flush */
83502e53293SMika Westerberg }
836f1d848f9SMika Westerberg 
83702e53293SMika Westerberg static int ahci_pci_device_runtime_suspend(struct device *dev)
83802e53293SMika Westerberg {
83902e53293SMika Westerberg 	struct pci_dev *pdev = to_pci_dev(dev);
84002e53293SMika Westerberg 	struct ata_host *host = pci_get_drvdata(pdev);
84102e53293SMika Westerberg 
84202e53293SMika Westerberg 	ahci_pci_disable_interrupts(host);
84302e53293SMika Westerberg 	return 0;
84402e53293SMika Westerberg }
84502e53293SMika Westerberg 
84602e53293SMika Westerberg static int ahci_pci_device_runtime_resume(struct device *dev)
84702e53293SMika Westerberg {
84802e53293SMika Westerberg 	struct pci_dev *pdev = to_pci_dev(dev);
84902e53293SMika Westerberg 	struct ata_host *host = pci_get_drvdata(pdev);
85002e53293SMika Westerberg 	int rc;
85102e53293SMika Westerberg 
85202e53293SMika Westerberg 	rc = ahci_pci_reset_controller(host);
85302e53293SMika Westerberg 	if (rc)
85402e53293SMika Westerberg 		return rc;
85502e53293SMika Westerberg 	ahci_pci_init_controller(host);
85602e53293SMika Westerberg 	return 0;
85702e53293SMika Westerberg }
85802e53293SMika Westerberg 
85902e53293SMika Westerberg #ifdef CONFIG_PM_SLEEP
86002e53293SMika Westerberg static int ahci_pci_device_suspend(struct device *dev)
86102e53293SMika Westerberg {
86202e53293SMika Westerberg 	struct pci_dev *pdev = to_pci_dev(dev);
86302e53293SMika Westerberg 	struct ata_host *host = pci_get_drvdata(pdev);
86402e53293SMika Westerberg 	struct ahci_host_priv *hpriv = host->private_data;
86502e53293SMika Westerberg 
86602e53293SMika Westerberg 	if (hpriv->flags & AHCI_HFLAG_NO_SUSPEND) {
86702e53293SMika Westerberg 		dev_err(&pdev->dev,
86802e53293SMika Westerberg 			"BIOS update required for suspend/resume\n");
86902e53293SMika Westerberg 		return -EIO;
87002e53293SMika Westerberg 	}
87102e53293SMika Westerberg 
87202e53293SMika Westerberg 	ahci_pci_disable_interrupts(host);
873f1d848f9SMika Westerberg 	return ata_host_suspend(host, PMSG_SUSPEND);
874c6fd2807SJeff Garzik }
875c6fd2807SJeff Garzik 
876f1d848f9SMika Westerberg static int ahci_pci_device_resume(struct device *dev)
877c6fd2807SJeff Garzik {
878f1d848f9SMika Westerberg 	struct pci_dev *pdev = to_pci_dev(dev);
8790a86e1c8SJingoo Han 	struct ata_host *host = pci_get_drvdata(pdev);
880c6fd2807SJeff Garzik 	int rc;
881c6fd2807SJeff Garzik 
882cb85696dSJames Laird 	/* Apple BIOS helpfully mangles the registers on resume */
883cb85696dSJames Laird 	if (is_mcp89_apple(pdev))
884cb85696dSJames Laird 		ahci_mcp89_apple_enable(pdev);
885cb85696dSJames Laird 
886c6fd2807SJeff Garzik 	if (pdev->dev.power.power_state.event == PM_EVENT_SUSPEND) {
8873303040dSAnton Vorontsov 		rc = ahci_pci_reset_controller(host);
888c6fd2807SJeff Garzik 		if (rc)
889c6fd2807SJeff Garzik 			return rc;
890c6fd2807SJeff Garzik 
891781d6550SAnton Vorontsov 		ahci_pci_init_controller(host);
892c6fd2807SJeff Garzik 	}
893c6fd2807SJeff Garzik 
894cca3974eSJeff Garzik 	ata_host_resume(host);
895c6fd2807SJeff Garzik 
896c6fd2807SJeff Garzik 	return 0;
897c6fd2807SJeff Garzik }
898438ac6d5STejun Heo #endif
899c6fd2807SJeff Garzik 
90002e53293SMika Westerberg #endif /* CONFIG_PM */
90102e53293SMika Westerberg 
9024447d351STejun Heo static int ahci_configure_dma_masks(struct pci_dev *pdev, int using_dac)
903c6fd2807SJeff Garzik {
904c6fd2807SJeff Garzik 	int rc;
905c6fd2807SJeff Garzik 
906318893e1SAlessandro Rubini 	/*
907318893e1SAlessandro Rubini 	 * If the device fixup already set the dma_mask to some non-standard
908318893e1SAlessandro Rubini 	 * value, don't extend it here. This happens on STA2X11, for example.
909318893e1SAlessandro Rubini 	 */
910318893e1SAlessandro Rubini 	if (pdev->dma_mask && pdev->dma_mask < DMA_BIT_MASK(32))
911318893e1SAlessandro Rubini 		return 0;
912318893e1SAlessandro Rubini 
913c6fd2807SJeff Garzik 	if (using_dac &&
914c54c719bSQuentin Lambert 	    !dma_set_mask(&pdev->dev, DMA_BIT_MASK(64))) {
915c54c719bSQuentin Lambert 		rc = dma_set_coherent_mask(&pdev->dev, DMA_BIT_MASK(64));
916c6fd2807SJeff Garzik 		if (rc) {
917c54c719bSQuentin Lambert 			rc = dma_set_coherent_mask(&pdev->dev, DMA_BIT_MASK(32));
918c6fd2807SJeff Garzik 			if (rc) {
919a44fec1fSJoe Perches 				dev_err(&pdev->dev,
920c6fd2807SJeff Garzik 					"64-bit DMA enable failed\n");
921c6fd2807SJeff Garzik 				return rc;
922c6fd2807SJeff Garzik 			}
923c6fd2807SJeff Garzik 		}
924c6fd2807SJeff Garzik 	} else {
925c54c719bSQuentin Lambert 		rc = dma_set_mask(&pdev->dev, DMA_BIT_MASK(32));
926c6fd2807SJeff Garzik 		if (rc) {
927a44fec1fSJoe Perches 			dev_err(&pdev->dev, "32-bit DMA enable failed\n");
928c6fd2807SJeff Garzik 			return rc;
929c6fd2807SJeff Garzik 		}
930c54c719bSQuentin Lambert 		rc = dma_set_coherent_mask(&pdev->dev, DMA_BIT_MASK(32));
931c6fd2807SJeff Garzik 		if (rc) {
932a44fec1fSJoe Perches 			dev_err(&pdev->dev,
933c6fd2807SJeff Garzik 				"32-bit consistent DMA enable failed\n");
934c6fd2807SJeff Garzik 			return rc;
935c6fd2807SJeff Garzik 		}
936c6fd2807SJeff Garzik 	}
937c6fd2807SJeff Garzik 	return 0;
938c6fd2807SJeff Garzik }
939c6fd2807SJeff Garzik 
940439fcaecSAnton Vorontsov static void ahci_pci_print_info(struct ata_host *host)
941439fcaecSAnton Vorontsov {
942439fcaecSAnton Vorontsov 	struct pci_dev *pdev = to_pci_dev(host->dev);
943439fcaecSAnton Vorontsov 	u16 cc;
944439fcaecSAnton Vorontsov 	const char *scc_s;
945439fcaecSAnton Vorontsov 
946439fcaecSAnton Vorontsov 	pci_read_config_word(pdev, 0x0a, &cc);
947439fcaecSAnton Vorontsov 	if (cc == PCI_CLASS_STORAGE_IDE)
948439fcaecSAnton Vorontsov 		scc_s = "IDE";
949439fcaecSAnton Vorontsov 	else if (cc == PCI_CLASS_STORAGE_SATA)
950439fcaecSAnton Vorontsov 		scc_s = "SATA";
951439fcaecSAnton Vorontsov 	else if (cc == PCI_CLASS_STORAGE_RAID)
952439fcaecSAnton Vorontsov 		scc_s = "RAID";
953439fcaecSAnton Vorontsov 	else
954439fcaecSAnton Vorontsov 		scc_s = "unknown";
955439fcaecSAnton Vorontsov 
956439fcaecSAnton Vorontsov 	ahci_print_info(host, scc_s);
957439fcaecSAnton Vorontsov }
958439fcaecSAnton Vorontsov 
959edc93052STejun Heo /* On ASUS P5W DH Deluxe, the second port of PCI device 00:1f.2 is
960edc93052STejun Heo  * hardwired to on-board SIMG 4726.  The chipset is ICH8 and doesn't
961edc93052STejun Heo  * support PMP and the 4726 either directly exports the device
962edc93052STejun Heo  * attached to the first downstream port or acts as a hardware storage
963edc93052STejun Heo  * controller and emulate a single ATA device (can be RAID 0/1 or some
964edc93052STejun Heo  * other configuration).
965edc93052STejun Heo  *
966edc93052STejun Heo  * When there's no device attached to the first downstream port of the
967edc93052STejun Heo  * 4726, "Config Disk" appears, which is a pseudo ATA device to
968edc93052STejun Heo  * configure the 4726.  However, ATA emulation of the device is very
969edc93052STejun Heo  * lame.  It doesn't send signature D2H Reg FIS after the initial
970edc93052STejun Heo  * hardreset, pukes on SRST w/ PMP==0 and has bunch of other issues.
971edc93052STejun Heo  *
972edc93052STejun Heo  * The following function works around the problem by always using
973edc93052STejun Heo  * hardreset on the port and not depending on receiving signature FIS
974edc93052STejun Heo  * afterward.  If signature FIS isn't received soon, ATA class is
975edc93052STejun Heo  * assumed without follow-up softreset.
976edc93052STejun Heo  */
977edc93052STejun Heo static void ahci_p5wdh_workaround(struct ata_host *host)
978edc93052STejun Heo {
9791bd06867SMathias Krause 	static const struct dmi_system_id sysids[] = {
980edc93052STejun Heo 		{
981edc93052STejun Heo 			.ident = "P5W DH Deluxe",
982edc93052STejun Heo 			.matches = {
983edc93052STejun Heo 				DMI_MATCH(DMI_SYS_VENDOR,
984edc93052STejun Heo 					  "ASUSTEK COMPUTER INC"),
985edc93052STejun Heo 				DMI_MATCH(DMI_PRODUCT_NAME, "P5W DH Deluxe"),
986edc93052STejun Heo 			},
987edc93052STejun Heo 		},
988edc93052STejun Heo 		{ }
989edc93052STejun Heo 	};
990edc93052STejun Heo 	struct pci_dev *pdev = to_pci_dev(host->dev);
991edc93052STejun Heo 
992edc93052STejun Heo 	if (pdev->bus->number == 0 && pdev->devfn == PCI_DEVFN(0x1f, 2) &&
993edc93052STejun Heo 	    dmi_check_system(sysids)) {
994edc93052STejun Heo 		struct ata_port *ap = host->ports[1];
995edc93052STejun Heo 
996a44fec1fSJoe Perches 		dev_info(&pdev->dev,
997a44fec1fSJoe Perches 			 "enabling ASUS P5W DH Deluxe on-board SIMG4726 workaround\n");
998edc93052STejun Heo 
999edc93052STejun Heo 		ap->ops = &ahci_p5wdh_ops;
1000edc93052STejun Heo 		ap->link.flags |= ATA_LFLAG_NO_SRST | ATA_LFLAG_ASSUME_ATA;
1001edc93052STejun Heo 	}
1002edc93052STejun Heo }
1003edc93052STejun Heo 
1004cb85696dSJames Laird /*
1005cb85696dSJames Laird  * Macbook7,1 firmware forcibly disables MCP89 AHCI and changes PCI ID when
1006cb85696dSJames Laird  * booting in BIOS compatibility mode.  We restore the registers but not ID.
1007cb85696dSJames Laird  */
1008cb85696dSJames Laird static void ahci_mcp89_apple_enable(struct pci_dev *pdev)
1009cb85696dSJames Laird {
1010cb85696dSJames Laird 	u32 val;
1011cb85696dSJames Laird 
1012cb85696dSJames Laird 	printk(KERN_INFO "ahci: enabling MCP89 AHCI mode\n");
1013cb85696dSJames Laird 
1014cb85696dSJames Laird 	pci_read_config_dword(pdev, 0xf8, &val);
1015cb85696dSJames Laird 	val |= 1 << 0x1b;
1016cb85696dSJames Laird 	/* the following changes the device ID, but appears not to affect function */
1017cb85696dSJames Laird 	/* val = (val & ~0xf0000000) | 0x80000000; */
1018cb85696dSJames Laird 	pci_write_config_dword(pdev, 0xf8, val);
1019cb85696dSJames Laird 
1020cb85696dSJames Laird 	pci_read_config_dword(pdev, 0x54c, &val);
1021cb85696dSJames Laird 	val |= 1 << 0xc;
1022cb85696dSJames Laird 	pci_write_config_dword(pdev, 0x54c, val);
1023cb85696dSJames Laird 
1024cb85696dSJames Laird 	pci_read_config_dword(pdev, 0x4a4, &val);
1025cb85696dSJames Laird 	val &= 0xff;
1026cb85696dSJames Laird 	val |= 0x01060100;
1027cb85696dSJames Laird 	pci_write_config_dword(pdev, 0x4a4, val);
1028cb85696dSJames Laird 
1029cb85696dSJames Laird 	pci_read_config_dword(pdev, 0x54c, &val);
1030cb85696dSJames Laird 	val &= ~(1 << 0xc);
1031cb85696dSJames Laird 	pci_write_config_dword(pdev, 0x54c, val);
1032cb85696dSJames Laird 
1033cb85696dSJames Laird 	pci_read_config_dword(pdev, 0xf8, &val);
1034cb85696dSJames Laird 	val &= ~(1 << 0x1b);
1035cb85696dSJames Laird 	pci_write_config_dword(pdev, 0xf8, val);
1036cb85696dSJames Laird }
1037cb85696dSJames Laird 
1038cb85696dSJames Laird static bool is_mcp89_apple(struct pci_dev *pdev)
1039cb85696dSJames Laird {
1040cb85696dSJames Laird 	return pdev->vendor == PCI_VENDOR_ID_NVIDIA &&
1041cb85696dSJames Laird 		pdev->device == PCI_DEVICE_ID_NVIDIA_NFORCE_MCP89_SATA &&
1042cb85696dSJames Laird 		pdev->subsystem_vendor == PCI_VENDOR_ID_APPLE &&
1043cb85696dSJames Laird 		pdev->subsystem_device == 0xcb89;
1044cb85696dSJames Laird }
1045cb85696dSJames Laird 
10462fcad9d2STejun Heo /* only some SB600 ahci controllers can do 64bit DMA */
10472fcad9d2STejun Heo static bool ahci_sb600_enable_64bit(struct pci_dev *pdev)
104858a09b38SShane Huang {
104958a09b38SShane Huang 	static const struct dmi_system_id sysids[] = {
105003d783bfSTejun Heo 		/*
105103d783bfSTejun Heo 		 * The oldest version known to be broken is 0901 and
105203d783bfSTejun Heo 		 * working is 1501 which was released on 2007-10-26.
10532fcad9d2STejun Heo 		 * Enable 64bit DMA on 1501 and anything newer.
10542fcad9d2STejun Heo 		 *
105503d783bfSTejun Heo 		 * Please read bko#9412 for more info.
105603d783bfSTejun Heo 		 */
105758a09b38SShane Huang 		{
105858a09b38SShane Huang 			.ident = "ASUS M2A-VM",
105958a09b38SShane Huang 			.matches = {
106058a09b38SShane Huang 				DMI_MATCH(DMI_BOARD_VENDOR,
106158a09b38SShane Huang 					  "ASUSTeK Computer INC."),
106258a09b38SShane Huang 				DMI_MATCH(DMI_BOARD_NAME, "M2A-VM"),
106358a09b38SShane Huang 			},
106403d783bfSTejun Heo 			.driver_data = "20071026",	/* yyyymmdd */
106558a09b38SShane Huang 		},
1066e65cc194SMark Nelson 		/*
1067e65cc194SMark Nelson 		 * All BIOS versions for the MSI K9A2 Platinum (MS-7376)
1068e65cc194SMark Nelson 		 * support 64bit DMA.
1069e65cc194SMark Nelson 		 *
1070e65cc194SMark Nelson 		 * BIOS versions earlier than 1.5 had the Manufacturer DMI
1071e65cc194SMark Nelson 		 * fields as "MICRO-STAR INTERANTIONAL CO.,LTD".
1072e65cc194SMark Nelson 		 * This spelling mistake was fixed in BIOS version 1.5, so
1073e65cc194SMark Nelson 		 * 1.5 and later have the Manufacturer as
1074e65cc194SMark Nelson 		 * "MICRO-STAR INTERNATIONAL CO.,LTD".
1075e65cc194SMark Nelson 		 * So try to match on DMI_BOARD_VENDOR of "MICRO-STAR INTER".
1076e65cc194SMark Nelson 		 *
1077e65cc194SMark Nelson 		 * BIOS versions earlier than 1.9 had a Board Product Name
1078e65cc194SMark Nelson 		 * DMI field of "MS-7376". This was changed to be
1079e65cc194SMark Nelson 		 * "K9A2 Platinum (MS-7376)" in version 1.9, but we can still
1080e65cc194SMark Nelson 		 * match on DMI_BOARD_NAME of "MS-7376".
1081e65cc194SMark Nelson 		 */
1082e65cc194SMark Nelson 		{
1083e65cc194SMark Nelson 			.ident = "MSI K9A2 Platinum",
1084e65cc194SMark Nelson 			.matches = {
1085e65cc194SMark Nelson 				DMI_MATCH(DMI_BOARD_VENDOR,
1086e65cc194SMark Nelson 					  "MICRO-STAR INTER"),
1087e65cc194SMark Nelson 				DMI_MATCH(DMI_BOARD_NAME, "MS-7376"),
1088e65cc194SMark Nelson 			},
1089e65cc194SMark Nelson 		},
10903c4aa91fSMark Nelson 		/*
1091ff0173c1SMark Nelson 		 * All BIOS versions for the MSI K9AGM2 (MS-7327) support
1092ff0173c1SMark Nelson 		 * 64bit DMA.
1093ff0173c1SMark Nelson 		 *
1094ff0173c1SMark Nelson 		 * This board also had the typo mentioned above in the
1095ff0173c1SMark Nelson 		 * Manufacturer DMI field (fixed in BIOS version 1.5), so
1096ff0173c1SMark Nelson 		 * match on DMI_BOARD_VENDOR of "MICRO-STAR INTER" again.
1097ff0173c1SMark Nelson 		 */
1098ff0173c1SMark Nelson 		{
1099ff0173c1SMark Nelson 			.ident = "MSI K9AGM2",
1100ff0173c1SMark Nelson 			.matches = {
1101ff0173c1SMark Nelson 				DMI_MATCH(DMI_BOARD_VENDOR,
1102ff0173c1SMark Nelson 					  "MICRO-STAR INTER"),
1103ff0173c1SMark Nelson 				DMI_MATCH(DMI_BOARD_NAME, "MS-7327"),
1104ff0173c1SMark Nelson 			},
1105ff0173c1SMark Nelson 		},
1106ff0173c1SMark Nelson 		/*
11073c4aa91fSMark Nelson 		 * All BIOS versions for the Asus M3A support 64bit DMA.
11083c4aa91fSMark Nelson 		 * (all release versions from 0301 to 1206 were tested)
11093c4aa91fSMark Nelson 		 */
11103c4aa91fSMark Nelson 		{
11113c4aa91fSMark Nelson 			.ident = "ASUS M3A",
11123c4aa91fSMark Nelson 			.matches = {
11133c4aa91fSMark Nelson 				DMI_MATCH(DMI_BOARD_VENDOR,
11143c4aa91fSMark Nelson 					  "ASUSTeK Computer INC."),
11153c4aa91fSMark Nelson 				DMI_MATCH(DMI_BOARD_NAME, "M3A"),
11163c4aa91fSMark Nelson 			},
11173c4aa91fSMark Nelson 		},
111858a09b38SShane Huang 		{ }
111958a09b38SShane Huang 	};
112003d783bfSTejun Heo 	const struct dmi_system_id *match;
11212fcad9d2STejun Heo 	int year, month, date;
11222fcad9d2STejun Heo 	char buf[9];
112358a09b38SShane Huang 
112403d783bfSTejun Heo 	match = dmi_first_match(sysids);
112558a09b38SShane Huang 	if (pdev->bus->number != 0 || pdev->devfn != PCI_DEVFN(0x12, 0) ||
112603d783bfSTejun Heo 	    !match)
112758a09b38SShane Huang 		return false;
112858a09b38SShane Huang 
1129e65cc194SMark Nelson 	if (!match->driver_data)
1130e65cc194SMark Nelson 		goto enable_64bit;
1131e65cc194SMark Nelson 
113203d783bfSTejun Heo 	dmi_get_date(DMI_BIOS_DATE, &year, &month, &date);
113303d783bfSTejun Heo 	snprintf(buf, sizeof(buf), "%04d%02d%02d", year, month, date);
113403d783bfSTejun Heo 
1135e65cc194SMark Nelson 	if (strcmp(buf, match->driver_data) >= 0)
1136e65cc194SMark Nelson 		goto enable_64bit;
1137e65cc194SMark Nelson 	else {
1138a44fec1fSJoe Perches 		dev_warn(&pdev->dev,
1139a44fec1fSJoe Perches 			 "%s: BIOS too old, forcing 32bit DMA, update BIOS\n",
1140a44fec1fSJoe Perches 			 match->ident);
11412fcad9d2STejun Heo 		return false;
11422fcad9d2STejun Heo 	}
1143e65cc194SMark Nelson 
1144e65cc194SMark Nelson enable_64bit:
1145a44fec1fSJoe Perches 	dev_warn(&pdev->dev, "%s: enabling 64bit DMA\n", match->ident);
1146e65cc194SMark Nelson 	return true;
114758a09b38SShane Huang }
114858a09b38SShane Huang 
11491fd68434SRafael J. Wysocki static bool ahci_broken_system_poweroff(struct pci_dev *pdev)
11501fd68434SRafael J. Wysocki {
11511fd68434SRafael J. Wysocki 	static const struct dmi_system_id broken_systems[] = {
11521fd68434SRafael J. Wysocki 		{
11531fd68434SRafael J. Wysocki 			.ident = "HP Compaq nx6310",
11541fd68434SRafael J. Wysocki 			.matches = {
11551fd68434SRafael J. Wysocki 				DMI_MATCH(DMI_SYS_VENDOR, "Hewlett-Packard"),
11561fd68434SRafael J. Wysocki 				DMI_MATCH(DMI_PRODUCT_NAME, "HP Compaq nx6310"),
11571fd68434SRafael J. Wysocki 			},
11581fd68434SRafael J. Wysocki 			/* PCI slot number of the controller */
11591fd68434SRafael J. Wysocki 			.driver_data = (void *)0x1FUL,
11601fd68434SRafael J. Wysocki 		},
1161d2f9c061SMaciej Rutecki 		{
1162d2f9c061SMaciej Rutecki 			.ident = "HP Compaq 6720s",
1163d2f9c061SMaciej Rutecki 			.matches = {
1164d2f9c061SMaciej Rutecki 				DMI_MATCH(DMI_SYS_VENDOR, "Hewlett-Packard"),
1165d2f9c061SMaciej Rutecki 				DMI_MATCH(DMI_PRODUCT_NAME, "HP Compaq 6720s"),
1166d2f9c061SMaciej Rutecki 			},
1167d2f9c061SMaciej Rutecki 			/* PCI slot number of the controller */
1168d2f9c061SMaciej Rutecki 			.driver_data = (void *)0x1FUL,
1169d2f9c061SMaciej Rutecki 		},
11701fd68434SRafael J. Wysocki 
11711fd68434SRafael J. Wysocki 		{ }	/* terminate list */
11721fd68434SRafael J. Wysocki 	};
11731fd68434SRafael J. Wysocki 	const struct dmi_system_id *dmi = dmi_first_match(broken_systems);
11741fd68434SRafael J. Wysocki 
11751fd68434SRafael J. Wysocki 	if (dmi) {
11761fd68434SRafael J. Wysocki 		unsigned long slot = (unsigned long)dmi->driver_data;
11771fd68434SRafael J. Wysocki 		/* apply the quirk only to on-board controllers */
11781fd68434SRafael J. Wysocki 		return slot == PCI_SLOT(pdev->devfn);
11791fd68434SRafael J. Wysocki 	}
11801fd68434SRafael J. Wysocki 
11811fd68434SRafael J. Wysocki 	return false;
11821fd68434SRafael J. Wysocki }
11831fd68434SRafael J. Wysocki 
11849b10ae86STejun Heo static bool ahci_broken_suspend(struct pci_dev *pdev)
11859b10ae86STejun Heo {
11869b10ae86STejun Heo 	static const struct dmi_system_id sysids[] = {
11879b10ae86STejun Heo 		/*
11889b10ae86STejun Heo 		 * On HP dv[4-6] and HDX18 with earlier BIOSen, link
11899b10ae86STejun Heo 		 * to the harddisk doesn't become online after
11909b10ae86STejun Heo 		 * resuming from STR.  Warn and fail suspend.
11919deb3431STejun Heo 		 *
11929deb3431STejun Heo 		 * http://bugzilla.kernel.org/show_bug.cgi?id=12276
11939deb3431STejun Heo 		 *
11949deb3431STejun Heo 		 * Use dates instead of versions to match as HP is
11959deb3431STejun Heo 		 * apparently recycling both product and version
11969deb3431STejun Heo 		 * strings.
11979deb3431STejun Heo 		 *
11989deb3431STejun Heo 		 * http://bugzilla.kernel.org/show_bug.cgi?id=15462
11999b10ae86STejun Heo 		 */
12009b10ae86STejun Heo 		{
12019b10ae86STejun Heo 			.ident = "dv4",
12029b10ae86STejun Heo 			.matches = {
12039b10ae86STejun Heo 				DMI_MATCH(DMI_SYS_VENDOR, "Hewlett-Packard"),
12049b10ae86STejun Heo 				DMI_MATCH(DMI_PRODUCT_NAME,
12059b10ae86STejun Heo 					  "HP Pavilion dv4 Notebook PC"),
12069b10ae86STejun Heo 			},
12079deb3431STejun Heo 			.driver_data = "20090105",	/* F.30 */
12089b10ae86STejun Heo 		},
12099b10ae86STejun Heo 		{
12109b10ae86STejun Heo 			.ident = "dv5",
12119b10ae86STejun Heo 			.matches = {
12129b10ae86STejun Heo 				DMI_MATCH(DMI_SYS_VENDOR, "Hewlett-Packard"),
12139b10ae86STejun Heo 				DMI_MATCH(DMI_PRODUCT_NAME,
12149b10ae86STejun Heo 					  "HP Pavilion dv5 Notebook PC"),
12159b10ae86STejun Heo 			},
12169deb3431STejun Heo 			.driver_data = "20090506",	/* F.16 */
12179b10ae86STejun Heo 		},
12189b10ae86STejun Heo 		{
12199b10ae86STejun Heo 			.ident = "dv6",
12209b10ae86STejun Heo 			.matches = {
12219b10ae86STejun Heo 				DMI_MATCH(DMI_SYS_VENDOR, "Hewlett-Packard"),
12229b10ae86STejun Heo 				DMI_MATCH(DMI_PRODUCT_NAME,
12239b10ae86STejun Heo 					  "HP Pavilion dv6 Notebook PC"),
12249b10ae86STejun Heo 			},
12259deb3431STejun Heo 			.driver_data = "20090423",	/* F.21 */
12269b10ae86STejun Heo 		},
12279b10ae86STejun Heo 		{
12289b10ae86STejun Heo 			.ident = "HDX18",
12299b10ae86STejun Heo 			.matches = {
12309b10ae86STejun Heo 				DMI_MATCH(DMI_SYS_VENDOR, "Hewlett-Packard"),
12319b10ae86STejun Heo 				DMI_MATCH(DMI_PRODUCT_NAME,
12329b10ae86STejun Heo 					  "HP HDX18 Notebook PC"),
12339b10ae86STejun Heo 			},
12349deb3431STejun Heo 			.driver_data = "20090430",	/* F.23 */
12359b10ae86STejun Heo 		},
1236cedc9bf9STejun Heo 		/*
1237cedc9bf9STejun Heo 		 * Acer eMachines G725 has the same problem.  BIOS
1238cedc9bf9STejun Heo 		 * V1.03 is known to be broken.  V3.04 is known to
123925985edcSLucas De Marchi 		 * work.  Between, there are V1.06, V2.06 and V3.03
1240cedc9bf9STejun Heo 		 * that we don't have much idea about.  For now,
1241cedc9bf9STejun Heo 		 * blacklist anything older than V3.04.
12429deb3431STejun Heo 		 *
12439deb3431STejun Heo 		 * http://bugzilla.kernel.org/show_bug.cgi?id=15104
1244cedc9bf9STejun Heo 		 */
1245cedc9bf9STejun Heo 		{
1246cedc9bf9STejun Heo 			.ident = "G725",
1247cedc9bf9STejun Heo 			.matches = {
1248cedc9bf9STejun Heo 				DMI_MATCH(DMI_SYS_VENDOR, "eMachines"),
1249cedc9bf9STejun Heo 				DMI_MATCH(DMI_PRODUCT_NAME, "eMachines G725"),
1250cedc9bf9STejun Heo 			},
12519deb3431STejun Heo 			.driver_data = "20091216",	/* V3.04 */
1252cedc9bf9STejun Heo 		},
12539b10ae86STejun Heo 		{ }	/* terminate list */
12549b10ae86STejun Heo 	};
12559b10ae86STejun Heo 	const struct dmi_system_id *dmi = dmi_first_match(sysids);
12569deb3431STejun Heo 	int year, month, date;
12579deb3431STejun Heo 	char buf[9];
12589b10ae86STejun Heo 
12599b10ae86STejun Heo 	if (!dmi || pdev->bus->number || pdev->devfn != PCI_DEVFN(0x1f, 2))
12609b10ae86STejun Heo 		return false;
12619b10ae86STejun Heo 
12629deb3431STejun Heo 	dmi_get_date(DMI_BIOS_DATE, &year, &month, &date);
12639deb3431STejun Heo 	snprintf(buf, sizeof(buf), "%04d%02d%02d", year, month, date);
12649b10ae86STejun Heo 
12659deb3431STejun Heo 	return strcmp(buf, dmi->driver_data) < 0;
12669b10ae86STejun Heo }
12679b10ae86STejun Heo 
1268240630e6SHans de Goede static bool ahci_broken_lpm(struct pci_dev *pdev)
1269240630e6SHans de Goede {
1270240630e6SHans de Goede 	static const struct dmi_system_id sysids[] = {
1271240630e6SHans de Goede 		/* Various Lenovo 50 series have LPM issues with older BIOSen */
1272240630e6SHans de Goede 		{
1273240630e6SHans de Goede 			.matches = {
1274240630e6SHans de Goede 				DMI_MATCH(DMI_SYS_VENDOR, "LENOVO"),
1275240630e6SHans de Goede 				DMI_MATCH(DMI_PRODUCT_VERSION, "ThinkPad X250"),
1276240630e6SHans de Goede 			},
1277240630e6SHans de Goede 			.driver_data = "20180406", /* 1.31 */
1278240630e6SHans de Goede 		},
1279240630e6SHans de Goede 		{
1280240630e6SHans de Goede 			.matches = {
1281240630e6SHans de Goede 				DMI_MATCH(DMI_SYS_VENDOR, "LENOVO"),
1282240630e6SHans de Goede 				DMI_MATCH(DMI_PRODUCT_VERSION, "ThinkPad L450"),
1283240630e6SHans de Goede 			},
1284240630e6SHans de Goede 			.driver_data = "20180420", /* 1.28 */
1285240630e6SHans de Goede 		},
1286240630e6SHans de Goede 		{
1287240630e6SHans de Goede 			.matches = {
1288240630e6SHans de Goede 				DMI_MATCH(DMI_SYS_VENDOR, "LENOVO"),
1289240630e6SHans de Goede 				DMI_MATCH(DMI_PRODUCT_VERSION, "ThinkPad T450s"),
1290240630e6SHans de Goede 			},
1291240630e6SHans de Goede 			.driver_data = "20180315", /* 1.33 */
1292240630e6SHans de Goede 		},
1293240630e6SHans de Goede 		{
1294240630e6SHans de Goede 			.matches = {
1295240630e6SHans de Goede 				DMI_MATCH(DMI_SYS_VENDOR, "LENOVO"),
1296240630e6SHans de Goede 				DMI_MATCH(DMI_PRODUCT_VERSION, "ThinkPad W541"),
1297240630e6SHans de Goede 			},
1298240630e6SHans de Goede 			/*
1299240630e6SHans de Goede 			 * Note date based on release notes, 2.35 has been
1300240630e6SHans de Goede 			 * reported to be good, but I've been unable to get
1301240630e6SHans de Goede 			 * a hold of the reporter to get the DMI BIOS date.
1302240630e6SHans de Goede 			 * TODO: fix this.
1303240630e6SHans de Goede 			 */
1304240630e6SHans de Goede 			.driver_data = "20180310", /* 2.35 */
1305240630e6SHans de Goede 		},
1306240630e6SHans de Goede 		{ }	/* terminate list */
1307240630e6SHans de Goede 	};
1308240630e6SHans de Goede 	const struct dmi_system_id *dmi = dmi_first_match(sysids);
1309240630e6SHans de Goede 	int year, month, date;
1310240630e6SHans de Goede 	char buf[9];
1311240630e6SHans de Goede 
1312240630e6SHans de Goede 	if (!dmi)
1313240630e6SHans de Goede 		return false;
1314240630e6SHans de Goede 
1315240630e6SHans de Goede 	dmi_get_date(DMI_BIOS_DATE, &year, &month, &date);
1316240630e6SHans de Goede 	snprintf(buf, sizeof(buf), "%04d%02d%02d", year, month, date);
1317240630e6SHans de Goede 
1318240630e6SHans de Goede 	return strcmp(buf, dmi->driver_data) < 0;
1319240630e6SHans de Goede }
1320240630e6SHans de Goede 
13215594639aSTejun Heo static bool ahci_broken_online(struct pci_dev *pdev)
13225594639aSTejun Heo {
13235594639aSTejun Heo #define ENCODE_BUSDEVFN(bus, slot, func)			\
13245594639aSTejun Heo 	(void *)(unsigned long)(((bus) << 8) | PCI_DEVFN((slot), (func)))
13255594639aSTejun Heo 	static const struct dmi_system_id sysids[] = {
13265594639aSTejun Heo 		/*
13275594639aSTejun Heo 		 * There are several gigabyte boards which use
13285594639aSTejun Heo 		 * SIMG5723s configured as hardware RAID.  Certain
13295594639aSTejun Heo 		 * 5723 firmware revisions shipped there keep the link
13305594639aSTejun Heo 		 * online but fail to answer properly to SRST or
13315594639aSTejun Heo 		 * IDENTIFY when no device is attached downstream
13325594639aSTejun Heo 		 * causing libata to retry quite a few times leading
13335594639aSTejun Heo 		 * to excessive detection delay.
13345594639aSTejun Heo 		 *
13355594639aSTejun Heo 		 * As these firmwares respond to the second reset try
13365594639aSTejun Heo 		 * with invalid device signature, considering unknown
13375594639aSTejun Heo 		 * sig as offline works around the problem acceptably.
13385594639aSTejun Heo 		 */
13395594639aSTejun Heo 		{
13405594639aSTejun Heo 			.ident = "EP45-DQ6",
13415594639aSTejun Heo 			.matches = {
13425594639aSTejun Heo 				DMI_MATCH(DMI_BOARD_VENDOR,
13435594639aSTejun Heo 					  "Gigabyte Technology Co., Ltd."),
13445594639aSTejun Heo 				DMI_MATCH(DMI_BOARD_NAME, "EP45-DQ6"),
13455594639aSTejun Heo 			},
13465594639aSTejun Heo 			.driver_data = ENCODE_BUSDEVFN(0x0a, 0x00, 0),
13475594639aSTejun Heo 		},
13485594639aSTejun Heo 		{
13495594639aSTejun Heo 			.ident = "EP45-DS5",
13505594639aSTejun Heo 			.matches = {
13515594639aSTejun Heo 				DMI_MATCH(DMI_BOARD_VENDOR,
13525594639aSTejun Heo 					  "Gigabyte Technology Co., Ltd."),
13535594639aSTejun Heo 				DMI_MATCH(DMI_BOARD_NAME, "EP45-DS5"),
13545594639aSTejun Heo 			},
13555594639aSTejun Heo 			.driver_data = ENCODE_BUSDEVFN(0x03, 0x00, 0),
13565594639aSTejun Heo 		},
13575594639aSTejun Heo 		{ }	/* terminate list */
13585594639aSTejun Heo 	};
13595594639aSTejun Heo #undef ENCODE_BUSDEVFN
13605594639aSTejun Heo 	const struct dmi_system_id *dmi = dmi_first_match(sysids);
13615594639aSTejun Heo 	unsigned int val;
13625594639aSTejun Heo 
13635594639aSTejun Heo 	if (!dmi)
13645594639aSTejun Heo 		return false;
13655594639aSTejun Heo 
13665594639aSTejun Heo 	val = (unsigned long)dmi->driver_data;
13675594639aSTejun Heo 
13685594639aSTejun Heo 	return pdev->bus->number == (val >> 8) && pdev->devfn == (val & 0xff);
13695594639aSTejun Heo }
13705594639aSTejun Heo 
13710cf4a7d6SJacob Pan static bool ahci_broken_devslp(struct pci_dev *pdev)
13720cf4a7d6SJacob Pan {
13730cf4a7d6SJacob Pan 	/* device with broken DEVSLP but still showing SDS capability */
13740cf4a7d6SJacob Pan 	static const struct pci_device_id ids[] = {
13750cf4a7d6SJacob Pan 		{ PCI_VDEVICE(INTEL, 0x0f23)}, /* Valleyview SoC */
13760cf4a7d6SJacob Pan 		{}
13770cf4a7d6SJacob Pan 	};
13780cf4a7d6SJacob Pan 
13790cf4a7d6SJacob Pan 	return pci_match_id(ids, pdev);
13800cf4a7d6SJacob Pan }
13810cf4a7d6SJacob Pan 
13828e513217SMarkus Trippelsdorf #ifdef CONFIG_ATA_ACPI
1383f80ae7e4STejun Heo static void ahci_gtf_filter_workaround(struct ata_host *host)
1384f80ae7e4STejun Heo {
1385f80ae7e4STejun Heo 	static const struct dmi_system_id sysids[] = {
1386f80ae7e4STejun Heo 		/*
1387f80ae7e4STejun Heo 		 * Aspire 3810T issues a bunch of SATA enable commands
1388f80ae7e4STejun Heo 		 * via _GTF including an invalid one and one which is
1389f80ae7e4STejun Heo 		 * rejected by the device.  Among the successful ones
1390f80ae7e4STejun Heo 		 * is FPDMA non-zero offset enable which when enabled
1391f80ae7e4STejun Heo 		 * only on the drive side leads to NCQ command
1392f80ae7e4STejun Heo 		 * failures.  Filter it out.
1393f80ae7e4STejun Heo 		 */
1394f80ae7e4STejun Heo 		{
1395f80ae7e4STejun Heo 			.ident = "Aspire 3810T",
1396f80ae7e4STejun Heo 			.matches = {
1397f80ae7e4STejun Heo 				DMI_MATCH(DMI_SYS_VENDOR, "Acer"),
1398f80ae7e4STejun Heo 				DMI_MATCH(DMI_PRODUCT_NAME, "Aspire 3810T"),
1399f80ae7e4STejun Heo 			},
1400f80ae7e4STejun Heo 			.driver_data = (void *)ATA_ACPI_FILTER_FPDMA_OFFSET,
1401f80ae7e4STejun Heo 		},
1402f80ae7e4STejun Heo 		{ }
1403f80ae7e4STejun Heo 	};
1404f80ae7e4STejun Heo 	const struct dmi_system_id *dmi = dmi_first_match(sysids);
1405f80ae7e4STejun Heo 	unsigned int filter;
1406f80ae7e4STejun Heo 	int i;
1407f80ae7e4STejun Heo 
1408f80ae7e4STejun Heo 	if (!dmi)
1409f80ae7e4STejun Heo 		return;
1410f80ae7e4STejun Heo 
1411f80ae7e4STejun Heo 	filter = (unsigned long)dmi->driver_data;
1412a44fec1fSJoe Perches 	dev_info(host->dev, "applying extra ACPI _GTF filter 0x%x for %s\n",
1413f80ae7e4STejun Heo 		 filter, dmi->ident);
1414f80ae7e4STejun Heo 
1415f80ae7e4STejun Heo 	for (i = 0; i < host->n_ports; i++) {
1416f80ae7e4STejun Heo 		struct ata_port *ap = host->ports[i];
1417f80ae7e4STejun Heo 		struct ata_link *link;
1418f80ae7e4STejun Heo 		struct ata_device *dev;
1419f80ae7e4STejun Heo 
1420f80ae7e4STejun Heo 		ata_for_each_link(link, ap, EDGE)
1421f80ae7e4STejun Heo 			ata_for_each_dev(dev, link, ALL)
1422f80ae7e4STejun Heo 				dev->gtf_filter |= filter;
1423f80ae7e4STejun Heo 	}
1424f80ae7e4STejun Heo }
14258e513217SMarkus Trippelsdorf #else
14268e513217SMarkus Trippelsdorf static inline void ahci_gtf_filter_workaround(struct ata_host *host)
14278e513217SMarkus Trippelsdorf {}
14288e513217SMarkus Trippelsdorf #endif
1429f80ae7e4STejun Heo 
14308bfd1743SSui Chen /*
14318bfd1743SSui Chen  * On the Acer Aspire Switch Alpha 12, sometimes all SATA ports are detected
14328bfd1743SSui Chen  * as DUMMY, or detected but eventually get a "link down" and never get up
14338bfd1743SSui Chen  * again. When this happens, CAP.NP may hold a value of 0x00 or 0x01, and the
14348bfd1743SSui Chen  * port_map may hold a value of 0x00.
14358bfd1743SSui Chen  *
14368bfd1743SSui Chen  * Overriding CAP.NP to 0x02 and the port_map to 0x7 will reveal all 3 ports
14378bfd1743SSui Chen  * and can significantly reduce the occurrence of the problem.
14388bfd1743SSui Chen  *
14398bfd1743SSui Chen  * https://bugzilla.kernel.org/show_bug.cgi?id=189471
14408bfd1743SSui Chen  */
14418bfd1743SSui Chen static void acer_sa5_271_workaround(struct ahci_host_priv *hpriv,
14428bfd1743SSui Chen 				    struct pci_dev *pdev)
14438bfd1743SSui Chen {
14448bfd1743SSui Chen 	static const struct dmi_system_id sysids[] = {
14458bfd1743SSui Chen 		{
14468bfd1743SSui Chen 			.ident = "Acer Switch Alpha 12",
14478bfd1743SSui Chen 			.matches = {
14488bfd1743SSui Chen 				DMI_MATCH(DMI_SYS_VENDOR, "Acer"),
14498bfd1743SSui Chen 				DMI_MATCH(DMI_PRODUCT_NAME, "Switch SA5-271")
14508bfd1743SSui Chen 			},
14518bfd1743SSui Chen 		},
14528bfd1743SSui Chen 		{ }
14538bfd1743SSui Chen 	};
14548bfd1743SSui Chen 
14558bfd1743SSui Chen 	if (dmi_check_system(sysids)) {
14568bfd1743SSui Chen 		dev_info(&pdev->dev, "enabling Acer Switch Alpha 12 workaround\n");
14578bfd1743SSui Chen 		if ((hpriv->saved_cap & 0xC734FF00) == 0xC734FF00) {
14588bfd1743SSui Chen 			hpriv->port_map = 0x7;
14598bfd1743SSui Chen 			hpriv->cap = 0xC734FF02;
14608bfd1743SSui Chen 		}
14618bfd1743SSui Chen 	}
14628bfd1743SSui Chen }
14638bfd1743SSui Chen 
1464d243bed3STirumalesh Chalamarla #ifdef CONFIG_ARM64
1465d243bed3STirumalesh Chalamarla /*
1466d243bed3STirumalesh Chalamarla  * Due to ERRATA#22536, ThunderX needs to handle HOST_IRQ_STAT differently.
1467d243bed3STirumalesh Chalamarla  * Workaround is to make sure all pending IRQs are served before leaving
1468d243bed3STirumalesh Chalamarla  * handler.
1469d243bed3STirumalesh Chalamarla  */
1470d243bed3STirumalesh Chalamarla static irqreturn_t ahci_thunderx_irq_handler(int irq, void *dev_instance)
1471d243bed3STirumalesh Chalamarla {
1472d243bed3STirumalesh Chalamarla 	struct ata_host *host = dev_instance;
1473d243bed3STirumalesh Chalamarla 	struct ahci_host_priv *hpriv;
1474d243bed3STirumalesh Chalamarla 	unsigned int rc = 0;
1475d243bed3STirumalesh Chalamarla 	void __iomem *mmio;
1476d243bed3STirumalesh Chalamarla 	u32 irq_stat, irq_masked;
1477d243bed3STirumalesh Chalamarla 	unsigned int handled = 1;
1478d243bed3STirumalesh Chalamarla 
1479d243bed3STirumalesh Chalamarla 	VPRINTK("ENTER\n");
1480d243bed3STirumalesh Chalamarla 	hpriv = host->private_data;
1481d243bed3STirumalesh Chalamarla 	mmio = hpriv->mmio;
1482d243bed3STirumalesh Chalamarla 	irq_stat = readl(mmio + HOST_IRQ_STAT);
1483d243bed3STirumalesh Chalamarla 	if (!irq_stat)
1484d243bed3STirumalesh Chalamarla 		return IRQ_NONE;
1485d243bed3STirumalesh Chalamarla 
1486d243bed3STirumalesh Chalamarla 	do {
1487d243bed3STirumalesh Chalamarla 		irq_masked = irq_stat & hpriv->port_map;
1488d243bed3STirumalesh Chalamarla 		spin_lock(&host->lock);
1489d243bed3STirumalesh Chalamarla 		rc = ahci_handle_port_intr(host, irq_masked);
1490d243bed3STirumalesh Chalamarla 		if (!rc)
1491d243bed3STirumalesh Chalamarla 			handled = 0;
1492d243bed3STirumalesh Chalamarla 		writel(irq_stat, mmio + HOST_IRQ_STAT);
1493d243bed3STirumalesh Chalamarla 		irq_stat = readl(mmio + HOST_IRQ_STAT);
1494d243bed3STirumalesh Chalamarla 		spin_unlock(&host->lock);
1495d243bed3STirumalesh Chalamarla 	} while (irq_stat);
1496d243bed3STirumalesh Chalamarla 	VPRINTK("EXIT\n");
1497d243bed3STirumalesh Chalamarla 
1498d243bed3STirumalesh Chalamarla 	return IRQ_RETVAL(handled);
1499d243bed3STirumalesh Chalamarla }
1500d243bed3STirumalesh Chalamarla #endif
1501d243bed3STirumalesh Chalamarla 
1502aecec8b6SChristoph Hellwig static void ahci_remap_check(struct pci_dev *pdev, int bar,
1503aecec8b6SChristoph Hellwig 		struct ahci_host_priv *hpriv)
1504aecec8b6SChristoph Hellwig {
1505aecec8b6SChristoph Hellwig 	int i, count = 0;
1506aecec8b6SChristoph Hellwig 	u32 cap;
1507aecec8b6SChristoph Hellwig 
1508aecec8b6SChristoph Hellwig 	/*
1509aecec8b6SChristoph Hellwig 	 * Check if this device might have remapped nvme devices.
1510aecec8b6SChristoph Hellwig 	 */
1511aecec8b6SChristoph Hellwig 	if (pdev->vendor != PCI_VENDOR_ID_INTEL ||
1512aecec8b6SChristoph Hellwig 	    pci_resource_len(pdev, bar) < SZ_512K ||
1513aecec8b6SChristoph Hellwig 	    bar != AHCI_PCI_BAR_STANDARD ||
1514aecec8b6SChristoph Hellwig 	    !(readl(hpriv->mmio + AHCI_VSCAP) & 1))
1515aecec8b6SChristoph Hellwig 		return;
1516aecec8b6SChristoph Hellwig 
1517aecec8b6SChristoph Hellwig 	cap = readq(hpriv->mmio + AHCI_REMAP_CAP);
1518aecec8b6SChristoph Hellwig 	for (i = 0; i < AHCI_MAX_REMAP; i++) {
1519aecec8b6SChristoph Hellwig 		if ((cap & (1 << i)) == 0)
1520aecec8b6SChristoph Hellwig 			continue;
1521aecec8b6SChristoph Hellwig 		if (readl(hpriv->mmio + ahci_remap_dcc(i))
1522aecec8b6SChristoph Hellwig 				!= PCI_CLASS_STORAGE_EXPRESS)
1523aecec8b6SChristoph Hellwig 			continue;
1524aecec8b6SChristoph Hellwig 
1525aecec8b6SChristoph Hellwig 		/* We've found a remapped device */
1526aecec8b6SChristoph Hellwig 		count++;
1527aecec8b6SChristoph Hellwig 	}
1528aecec8b6SChristoph Hellwig 
1529aecec8b6SChristoph Hellwig 	if (!count)
1530aecec8b6SChristoph Hellwig 		return;
1531aecec8b6SChristoph Hellwig 
1532aecec8b6SChristoph Hellwig 	dev_warn(&pdev->dev, "Found %d remapped NVMe devices.\n", count);
1533f723fa4eSChristoph Hellwig 	dev_warn(&pdev->dev,
1534f723fa4eSChristoph Hellwig 		 "Switch your BIOS from RAID to AHCI mode to use them.\n");
1535f723fa4eSChristoph Hellwig 
1536f723fa4eSChristoph Hellwig 	/*
1537f723fa4eSChristoph Hellwig 	 * Don't rely on the msi-x capability in the remap case,
1538f723fa4eSChristoph Hellwig 	 * share the legacy interrupt across ahci and remapped devices.
1539f723fa4eSChristoph Hellwig 	 */
1540f723fa4eSChristoph Hellwig 	hpriv->flags |= AHCI_HFLAG_NO_MSI;
1541aecec8b6SChristoph Hellwig }
1542aecec8b6SChristoph Hellwig 
15430b9e2988SChristoph Hellwig static int ahci_get_irq_vector(struct ata_host *host, int port)
1544ee2aad42SRobert Richter {
15450b9e2988SChristoph Hellwig 	return pci_irq_vector(to_pci_dev(host->dev), port);
1546ee2aad42SRobert Richter }
1547ee2aad42SRobert Richter 
1548a1c82311SRobert Richter static int ahci_init_msi(struct pci_dev *pdev, unsigned int n_ports,
15497b92b4f6SAlexander Gordeev 			struct ahci_host_priv *hpriv)
15505ca72c4fSAlexander Gordeev {
15510b9e2988SChristoph Hellwig 	int nvec;
15525ca72c4fSAlexander Gordeev 
15537b92b4f6SAlexander Gordeev 	if (hpriv->flags & AHCI_HFLAG_NO_MSI)
1554a1c82311SRobert Richter 		return -ENODEV;
15557b92b4f6SAlexander Gordeev 
15565ca72c4fSAlexander Gordeev 	/*
15577b92b4f6SAlexander Gordeev 	 * If number of MSIs is less than number of ports then Sharing Last
15587b92b4f6SAlexander Gordeev 	 * Message mode could be enforced. In this case assume that advantage
15597b92b4f6SAlexander Gordeev 	 * of multipe MSIs is negated and use single MSI mode instead.
15605ca72c4fSAlexander Gordeev 	 */
156117a51f12SChristoph Hellwig 	if (n_ports > 1) {
15620b9e2988SChristoph Hellwig 		nvec = pci_alloc_irq_vectors(pdev, n_ports, INT_MAX,
15630b9e2988SChristoph Hellwig 				PCI_IRQ_MSIX | PCI_IRQ_MSI);
15640b9e2988SChristoph Hellwig 		if (nvec > 0) {
15650b9e2988SChristoph Hellwig 			if (!(readl(hpriv->mmio + HOST_CTL) & HOST_MRSM)) {
15660b9e2988SChristoph Hellwig 				hpriv->get_irq_vector = ahci_get_irq_vector;
1567c3ebd6a9SAlexander Gordeev 				hpriv->flags |= AHCI_HFLAG_MULTI_MSI;
156821bfd1aaSRobert Richter 				return nvec;
1569a1c82311SRobert Richter 			}
1570a1c82311SRobert Richter 
1571d684a90dSDan Williams 			/*
157217a51f12SChristoph Hellwig 			 * Fallback to single MSI mode if the controller
157317a51f12SChristoph Hellwig 			 * enforced MRSM mode.
1574d684a90dSDan Williams 			 */
157517a51f12SChristoph Hellwig 			printk(KERN_INFO
157617a51f12SChristoph Hellwig 				"ahci: MRSM is on, fallback to single MSI\n");
15770b9e2988SChristoph Hellwig 			pci_free_irq_vectors(pdev);
15780b9e2988SChristoph Hellwig 		}
1579a478b097SChristoph Hellwig 	}
1580d684a90dSDan Williams 
15810b9e2988SChristoph Hellwig 	/*
15820b9e2988SChristoph Hellwig 	 * If the host is not capable of supporting per-port vectors, fall
15830b9e2988SChristoph Hellwig 	 * back to single MSI before finally attempting single MSI-X.
15840b9e2988SChristoph Hellwig 	 */
15850b9e2988SChristoph Hellwig 	nvec = pci_alloc_irq_vectors(pdev, 1, 1, PCI_IRQ_MSI);
15860b9e2988SChristoph Hellwig 	if (nvec == 1)
1587a1c82311SRobert Richter 		return nvec;
15880b9e2988SChristoph Hellwig 	return pci_alloc_irq_vectors(pdev, 1, 1, PCI_IRQ_MSIX);
15895ca72c4fSAlexander Gordeev }
15905ca72c4fSAlexander Gordeev 
1591b1a9585cSSrinivas Pandruvada static void ahci_update_initial_lpm_policy(struct ata_port *ap,
1592b1a9585cSSrinivas Pandruvada 					   struct ahci_host_priv *hpriv)
1593b1a9585cSSrinivas Pandruvada {
1594b1a9585cSSrinivas Pandruvada 	int policy = CONFIG_SATA_MOBILE_LPM_POLICY;
1595b1a9585cSSrinivas Pandruvada 
1596b1a9585cSSrinivas Pandruvada 
1597b1a9585cSSrinivas Pandruvada 	/* Ignore processing for non mobile platforms */
1598b1a9585cSSrinivas Pandruvada 	if (!(hpriv->flags & AHCI_HFLAG_IS_MOBILE))
1599b1a9585cSSrinivas Pandruvada 		return;
1600b1a9585cSSrinivas Pandruvada 
1601b1a9585cSSrinivas Pandruvada 	/* user modified policy via module param */
1602b1a9585cSSrinivas Pandruvada 	if (mobile_lpm_policy != -1) {
1603b1a9585cSSrinivas Pandruvada 		policy = mobile_lpm_policy;
1604b1a9585cSSrinivas Pandruvada 		goto update_policy;
1605b1a9585cSSrinivas Pandruvada 	}
1606b1a9585cSSrinivas Pandruvada 
1607b1a9585cSSrinivas Pandruvada #ifdef CONFIG_ACPI
1608b1a9585cSSrinivas Pandruvada 	if (policy > ATA_LPM_MED_POWER &&
1609b1a9585cSSrinivas Pandruvada 	    (acpi_gbl_FADT.flags & ACPI_FADT_LOW_POWER_S0)) {
1610b1a9585cSSrinivas Pandruvada 		if (hpriv->cap & HOST_CAP_PART)
1611b1a9585cSSrinivas Pandruvada 			policy = ATA_LPM_MIN_POWER_WITH_PARTIAL;
1612b1a9585cSSrinivas Pandruvada 		else if (hpriv->cap & HOST_CAP_SSC)
1613b1a9585cSSrinivas Pandruvada 			policy = ATA_LPM_MIN_POWER;
1614b1a9585cSSrinivas Pandruvada 	}
1615b1a9585cSSrinivas Pandruvada #endif
1616b1a9585cSSrinivas Pandruvada 
1617b1a9585cSSrinivas Pandruvada update_policy:
1618b1a9585cSSrinivas Pandruvada 	if (policy >= ATA_LPM_UNKNOWN && policy <= ATA_LPM_MIN_POWER)
1619b1a9585cSSrinivas Pandruvada 		ap->target_lpm_policy = policy;
1620b1a9585cSSrinivas Pandruvada }
1621b1a9585cSSrinivas Pandruvada 
1622c6fd2807SJeff Garzik static int ahci_init_one(struct pci_dev *pdev, const struct pci_device_id *ent)
1623c6fd2807SJeff Garzik {
1624e297d99eSTejun Heo 	unsigned int board_id = ent->driver_data;
1625e297d99eSTejun Heo 	struct ata_port_info pi = ahci_port_info[board_id];
16264447d351STejun Heo 	const struct ata_port_info *ppi[] = { &pi, NULL };
162724dc5f33STejun Heo 	struct device *dev = &pdev->dev;
1628c6fd2807SJeff Garzik 	struct ahci_host_priv *hpriv;
16294447d351STejun Heo 	struct ata_host *host;
1630c3ebd6a9SAlexander Gordeev 	int n_ports, i, rc;
1631318893e1SAlessandro Rubini 	int ahci_pci_bar = AHCI_PCI_BAR_STANDARD;
1632c6fd2807SJeff Garzik 
1633c6fd2807SJeff Garzik 	VPRINTK("ENTER\n");
1634c6fd2807SJeff Garzik 
1635b429dd59SJustin P. Mattock 	WARN_ON((int)ATA_MAX_QUEUE > AHCI_MAX_CMDS);
1636c6fd2807SJeff Garzik 
163706296a1eSJoe Perches 	ata_print_version_once(&pdev->dev, DRV_VERSION);
1638c6fd2807SJeff Garzik 
16395b66c829SAlan Cox 	/* The AHCI driver can only drive the SATA ports, the PATA driver
16405b66c829SAlan Cox 	   can drive them all so if both drivers are selected make sure
16415b66c829SAlan Cox 	   AHCI stays out of the way */
16425b66c829SAlan Cox 	if (pdev->vendor == PCI_VENDOR_ID_MARVELL && !marvell_enable)
16435b66c829SAlan Cox 		return -ENODEV;
16445b66c829SAlan Cox 
1645cb85696dSJames Laird 	/* Apple BIOS on MCP89 prevents us using AHCI */
1646cb85696dSJames Laird 	if (is_mcp89_apple(pdev))
1647cb85696dSJames Laird 		ahci_mcp89_apple_enable(pdev);
1648c6353b45STejun Heo 
16497a02267eSMark Nelson 	/* Promise's PDC42819 is a SAS/SATA controller that has an AHCI mode.
16507a02267eSMark Nelson 	 * At the moment, we can only use the AHCI mode. Let the users know
16517a02267eSMark Nelson 	 * that for SAS drives they're out of luck.
16527a02267eSMark Nelson 	 */
16537a02267eSMark Nelson 	if (pdev->vendor == PCI_VENDOR_ID_PROMISE)
1654a44fec1fSJoe Perches 		dev_info(&pdev->dev,
1655a44fec1fSJoe Perches 			 "PDC42819 can only drive SATA devices with this driver\n");
16567a02267eSMark Nelson 
1657b7ae128dSRobert Richter 	/* Some devices use non-standard BARs */
1658318893e1SAlessandro Rubini 	if (pdev->vendor == PCI_VENDOR_ID_STMICRO && pdev->device == 0xCC06)
1659318893e1SAlessandro Rubini 		ahci_pci_bar = AHCI_PCI_BAR_STA2X11;
16607f9c9f8eSHugh Daschbach 	else if (pdev->vendor == 0x1c44 && pdev->device == 0x8000)
16617f9c9f8eSHugh Daschbach 		ahci_pci_bar = AHCI_PCI_BAR_ENMOTUS;
1662b1314e3fSRadha Mohan Chintakuntla 	else if (pdev->vendor == PCI_VENDOR_ID_CAVIUM) {
1663b1314e3fSRadha Mohan Chintakuntla 		if (pdev->device == 0xa01c)
1664b7ae128dSRobert Richter 			ahci_pci_bar = AHCI_PCI_BAR_CAVIUM;
1665b1314e3fSRadha Mohan Chintakuntla 		if (pdev->device == 0xa084)
1666b1314e3fSRadha Mohan Chintakuntla 			ahci_pci_bar = AHCI_PCI_BAR_CAVIUM_GEN5;
1667b1314e3fSRadha Mohan Chintakuntla 	}
1668318893e1SAlessandro Rubini 
16694447d351STejun Heo 	/* acquire resources */
167024dc5f33STejun Heo 	rc = pcim_enable_device(pdev);
1671c6fd2807SJeff Garzik 	if (rc)
1672c6fd2807SJeff Garzik 		return rc;
1673c6fd2807SJeff Garzik 
1674c4f7792cSTejun Heo 	if (pdev->vendor == PCI_VENDOR_ID_INTEL &&
1675c4f7792cSTejun Heo 	    (pdev->device == 0x2652 || pdev->device == 0x2653)) {
1676c4f7792cSTejun Heo 		u8 map;
1677c4f7792cSTejun Heo 
1678c4f7792cSTejun Heo 		/* ICH6s share the same PCI ID for both piix and ahci
1679c4f7792cSTejun Heo 		 * modes.  Enabling ahci mode while MAP indicates
1680c4f7792cSTejun Heo 		 * combined mode is a bad idea.  Yield to ata_piix.
1681c4f7792cSTejun Heo 		 */
1682c4f7792cSTejun Heo 		pci_read_config_byte(pdev, ICH_MAP, &map);
1683c4f7792cSTejun Heo 		if (map & 0x3) {
1684a44fec1fSJoe Perches 			dev_info(&pdev->dev,
1685a44fec1fSJoe Perches 				 "controller is in combined mode, can't enable AHCI mode\n");
1686c4f7792cSTejun Heo 			return -ENODEV;
1687c4f7792cSTejun Heo 		}
1688c4f7792cSTejun Heo 	}
1689c4f7792cSTejun Heo 
16906fec8871SPaul Bolle 	/* AHCI controllers often implement SFF compatible interface.
16916fec8871SPaul Bolle 	 * Grab all PCI BARs just in case.
16926fec8871SPaul Bolle 	 */
16936fec8871SPaul Bolle 	rc = pcim_iomap_regions_request_all(pdev, 1 << ahci_pci_bar, DRV_NAME);
16946fec8871SPaul Bolle 	if (rc == -EBUSY)
16956fec8871SPaul Bolle 		pcim_pin_device(pdev);
16966fec8871SPaul Bolle 	if (rc)
16976fec8871SPaul Bolle 		return rc;
16986fec8871SPaul Bolle 
169924dc5f33STejun Heo 	hpriv = devm_kzalloc(dev, sizeof(*hpriv), GFP_KERNEL);
170024dc5f33STejun Heo 	if (!hpriv)
170124dc5f33STejun Heo 		return -ENOMEM;
1702417a1a6dSTejun Heo 	hpriv->flags |= (unsigned long)pi.private_data;
1703417a1a6dSTejun Heo 
1704e297d99eSTejun Heo 	/* MCP65 revision A1 and A2 can't do MSI */
1705e297d99eSTejun Heo 	if (board_id == board_ahci_mcp65 &&
1706e297d99eSTejun Heo 	    (pdev->revision == 0xa1 || pdev->revision == 0xa2))
1707e297d99eSTejun Heo 		hpriv->flags |= AHCI_HFLAG_NO_MSI;
1708e297d99eSTejun Heo 
1709e427fe04SShane Huang 	/* SB800 does NOT need the workaround to ignore SERR_INTERNAL */
1710e427fe04SShane Huang 	if (board_id == board_ahci_sb700 && pdev->revision >= 0x40)
1711e427fe04SShane Huang 		hpriv->flags &= ~AHCI_HFLAG_IGN_SERR_INTERNAL;
1712e427fe04SShane Huang 
17132fcad9d2STejun Heo 	/* only some SB600s can do 64bit DMA */
17142fcad9d2STejun Heo 	if (ahci_sb600_enable_64bit(pdev))
17152fcad9d2STejun Heo 		hpriv->flags &= ~AHCI_HFLAG_32BIT_ONLY;
171658a09b38SShane Huang 
1717318893e1SAlessandro Rubini 	hpriv->mmio = pcim_iomap_table(pdev)[ahci_pci_bar];
1718d8993349SAnton Vorontsov 
1719aecec8b6SChristoph Hellwig 	/* detect remapped nvme devices */
1720aecec8b6SChristoph Hellwig 	ahci_remap_check(pdev, ahci_pci_bar, hpriv);
1721aecec8b6SChristoph Hellwig 
17220cf4a7d6SJacob Pan 	/* must set flag prior to save config in order to take effect */
17230cf4a7d6SJacob Pan 	if (ahci_broken_devslp(pdev))
17240cf4a7d6SJacob Pan 		hpriv->flags |= AHCI_HFLAG_NO_DEVSLP;
17250cf4a7d6SJacob Pan 
1726d243bed3STirumalesh Chalamarla #ifdef CONFIG_ARM64
1727d243bed3STirumalesh Chalamarla 	if (pdev->vendor == 0x177d && pdev->device == 0xa01c)
1728d243bed3STirumalesh Chalamarla 		hpriv->irq_handler = ahci_thunderx_irq_handler;
1729d243bed3STirumalesh Chalamarla #endif
1730d243bed3STirumalesh Chalamarla 
17314447d351STejun Heo 	/* save initial config */
1732394d6e53SAnton Vorontsov 	ahci_pci_save_initial_config(pdev, hpriv);
1733c6fd2807SJeff Garzik 
17344447d351STejun Heo 	/* prepare host */
1735453d3131SRobert Hancock 	if (hpriv->cap & HOST_CAP_NCQ) {
1736453d3131SRobert Hancock 		pi.flags |= ATA_FLAG_NCQ;
173783f2b963STejun Heo 		/*
173883f2b963STejun Heo 		 * Auto-activate optimization is supposed to be
173983f2b963STejun Heo 		 * supported on all AHCI controllers indicating NCQ
174083f2b963STejun Heo 		 * capability, but it seems to be broken on some
174183f2b963STejun Heo 		 * chipsets including NVIDIAs.
174283f2b963STejun Heo 		 */
174383f2b963STejun Heo 		if (!(hpriv->flags & AHCI_HFLAG_NO_FPDMA_AA))
1744453d3131SRobert Hancock 			pi.flags |= ATA_FLAG_FPDMA_AA;
174540fb59e7SMarc Carino 
174640fb59e7SMarc Carino 		/*
174740fb59e7SMarc Carino 		 * All AHCI controllers should be forward-compatible
174840fb59e7SMarc Carino 		 * with the new auxiliary field. This code should be
174940fb59e7SMarc Carino 		 * conditionalized if any buggy AHCI controllers are
175040fb59e7SMarc Carino 		 * encountered.
175140fb59e7SMarc Carino 		 */
175240fb59e7SMarc Carino 		pi.flags |= ATA_FLAG_FPDMA_AUX;
1753453d3131SRobert Hancock 	}
17544447d351STejun Heo 
17557d50b60bSTejun Heo 	if (hpriv->cap & HOST_CAP_PMP)
17567d50b60bSTejun Heo 		pi.flags |= ATA_FLAG_PMP;
17577d50b60bSTejun Heo 
17580cbb0e77SAnton Vorontsov 	ahci_set_em_messages(hpriv, &pi);
175918f7ba4cSKristen Carlson Accardi 
17601fd68434SRafael J. Wysocki 	if (ahci_broken_system_poweroff(pdev)) {
17611fd68434SRafael J. Wysocki 		pi.flags |= ATA_FLAG_NO_POWEROFF_SPINDOWN;
17621fd68434SRafael J. Wysocki 		dev_info(&pdev->dev,
17631fd68434SRafael J. Wysocki 			"quirky BIOS, skipping spindown on poweroff\n");
17641fd68434SRafael J. Wysocki 	}
17651fd68434SRafael J. Wysocki 
1766240630e6SHans de Goede 	if (ahci_broken_lpm(pdev)) {
1767240630e6SHans de Goede 		pi.flags |= ATA_FLAG_NO_LPM;
1768240630e6SHans de Goede 		dev_warn(&pdev->dev,
1769240630e6SHans de Goede 			 "BIOS update required for Link Power Management support\n");
1770240630e6SHans de Goede 	}
1771240630e6SHans de Goede 
17729b10ae86STejun Heo 	if (ahci_broken_suspend(pdev)) {
17739b10ae86STejun Heo 		hpriv->flags |= AHCI_HFLAG_NO_SUSPEND;
1774a44fec1fSJoe Perches 		dev_warn(&pdev->dev,
17759b10ae86STejun Heo 			 "BIOS update required for suspend/resume\n");
17769b10ae86STejun Heo 	}
17779b10ae86STejun Heo 
17785594639aSTejun Heo 	if (ahci_broken_online(pdev)) {
17795594639aSTejun Heo 		hpriv->flags |= AHCI_HFLAG_SRST_TOUT_IS_OFFLINE;
17805594639aSTejun Heo 		dev_info(&pdev->dev,
17815594639aSTejun Heo 			 "online status unreliable, applying workaround\n");
17825594639aSTejun Heo 	}
17835594639aSTejun Heo 
17848bfd1743SSui Chen 
17858bfd1743SSui Chen 	/* Acer SA5-271 workaround modifies private_data */
17868bfd1743SSui Chen 	acer_sa5_271_workaround(hpriv, pdev);
17878bfd1743SSui Chen 
1788837f5f8fSTejun Heo 	/* CAP.NP sometimes indicate the index of the last enabled
1789837f5f8fSTejun Heo 	 * port, at other times, that of the last possible port, so
1790837f5f8fSTejun Heo 	 * determining the maximum port number requires looking at
1791837f5f8fSTejun Heo 	 * both CAP.NP and port_map.
1792837f5f8fSTejun Heo 	 */
1793837f5f8fSTejun Heo 	n_ports = max(ahci_nr_ports(hpriv->cap), fls(hpriv->port_map));
1794837f5f8fSTejun Heo 
1795837f5f8fSTejun Heo 	host = ata_host_alloc_pinfo(&pdev->dev, ppi, n_ports);
17964447d351STejun Heo 	if (!host)
17974447d351STejun Heo 		return -ENOMEM;
17984447d351STejun Heo 	host->private_data = hpriv;
17990b9e2988SChristoph Hellwig 
18000b9e2988SChristoph Hellwig 	if (ahci_init_msi(pdev, n_ports, hpriv) < 0) {
18010b9e2988SChristoph Hellwig 		/* legacy intx interrupts */
18020b9e2988SChristoph Hellwig 		pci_intx(pdev, 1);
18030b9e2988SChristoph Hellwig 	}
18040ce57f8aSChristoph Hellwig 	hpriv->irq = pci_irq_vector(pdev, 0);
180521bfd1aaSRobert Richter 
1806f3d7f23fSArjan van de Ven 	if (!(hpriv->cap & HOST_CAP_SSS) || ahci_ignore_sss)
1807886ad09fSArjan van de Ven 		host->flags |= ATA_HOST_PARALLEL_SCAN;
1808f3d7f23fSArjan van de Ven 	else
1809d2782d96SJingoo Han 		dev_info(&pdev->dev, "SSS flag set, parallel bus scan disabled\n");
1810886ad09fSArjan van de Ven 
181118f7ba4cSKristen Carlson Accardi 	if (pi.flags & ATA_FLAG_EM)
181218f7ba4cSKristen Carlson Accardi 		ahci_reset_em(host);
181318f7ba4cSKristen Carlson Accardi 
18144447d351STejun Heo 	for (i = 0; i < host->n_ports; i++) {
18154447d351STejun Heo 		struct ata_port *ap = host->ports[i];
18164447d351STejun Heo 
1817318893e1SAlessandro Rubini 		ata_port_pbar_desc(ap, ahci_pci_bar, -1, "abar");
1818318893e1SAlessandro Rubini 		ata_port_pbar_desc(ap, ahci_pci_bar,
1819cbcdd875STejun Heo 				   0x100 + ap->port_no * 0x80, "port");
1820cbcdd875STejun Heo 
182118f7ba4cSKristen Carlson Accardi 		/* set enclosure management message type */
182218f7ba4cSKristen Carlson Accardi 		if (ap->flags & ATA_FLAG_EM)
1823008dbd61SHarry Zhang 			ap->em_message_type = hpriv->em_msg_type;
182418f7ba4cSKristen Carlson Accardi 
1825b1a9585cSSrinivas Pandruvada 		ahci_update_initial_lpm_policy(ap, hpriv);
182618f7ba4cSKristen Carlson Accardi 
1827dab632e8SJeff Garzik 		/* disabled/not-implemented port */
1828350756f6STejun Heo 		if (!(hpriv->port_map & (1 << i)))
1829dab632e8SJeff Garzik 			ap->ops = &ata_dummy_port_ops;
18304447d351STejun Heo 	}
1831c6fd2807SJeff Garzik 
1832edc93052STejun Heo 	/* apply workaround for ASUS P5W DH Deluxe mainboard */
1833edc93052STejun Heo 	ahci_p5wdh_workaround(host);
1834edc93052STejun Heo 
1835f80ae7e4STejun Heo 	/* apply gtf filter quirk */
1836f80ae7e4STejun Heo 	ahci_gtf_filter_workaround(host);
1837f80ae7e4STejun Heo 
1838c6fd2807SJeff Garzik 	/* initialize adapter */
18394447d351STejun Heo 	rc = ahci_configure_dma_masks(pdev, hpriv->cap & HOST_CAP_64);
1840c6fd2807SJeff Garzik 	if (rc)
184124dc5f33STejun Heo 		return rc;
1842c6fd2807SJeff Garzik 
18433303040dSAnton Vorontsov 	rc = ahci_pci_reset_controller(host);
18444447d351STejun Heo 	if (rc)
18454447d351STejun Heo 		return rc;
1846c6fd2807SJeff Garzik 
1847781d6550SAnton Vorontsov 	ahci_pci_init_controller(host);
1848439fcaecSAnton Vorontsov 	ahci_pci_print_info(host);
1849c6fd2807SJeff Garzik 
18504447d351STejun Heo 	pci_set_master(pdev);
18515ca72c4fSAlexander Gordeev 
185202e53293SMika Westerberg 	rc = ahci_host_activate(host, &ahci_sht);
185302e53293SMika Westerberg 	if (rc)
185402e53293SMika Westerberg 		return rc;
185502e53293SMika Westerberg 
185602e53293SMika Westerberg 	pm_runtime_put_noidle(&pdev->dev);
185702e53293SMika Westerberg 	return 0;
185802e53293SMika Westerberg }
185902e53293SMika Westerberg 
186002e53293SMika Westerberg static void ahci_remove_one(struct pci_dev *pdev)
186102e53293SMika Westerberg {
186202e53293SMika Westerberg 	pm_runtime_get_noresume(&pdev->dev);
186302e53293SMika Westerberg 	ata_pci_remove_one(pdev);
1864c6fd2807SJeff Garzik }
1865c6fd2807SJeff Garzik 
18662fc75da0SAxel Lin module_pci_driver(ahci_pci_driver);
1867c6fd2807SJeff Garzik 
1868c6fd2807SJeff Garzik MODULE_AUTHOR("Jeff Garzik");
1869c6fd2807SJeff Garzik MODULE_DESCRIPTION("AHCI SATA low-level driver");
1870c6fd2807SJeff Garzik MODULE_LICENSE("GPL");
1871c6fd2807SJeff Garzik MODULE_DEVICE_TABLE(pci, ahci_pci_tbl);
1872c6fd2807SJeff Garzik MODULE_VERSION(DRV_VERSION);
1873