xref: /openbmc/linux/drivers/ata/ahci.c (revision d8d54126880c59303ada80fcb2e1a715a140e84b)
1c82ee6d3SThomas 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>
29c6fd2807SJeff Garzik #include <scsi/scsi_host.h>
30c6fd2807SJeff Garzik #include <scsi/scsi_cmnd.h>
31c6fd2807SJeff Garzik #include <linux/libata.h>
32aecec8b6SChristoph Hellwig #include <linux/ahci-remap.h>
33aecec8b6SChristoph Hellwig #include <linux/io-64-nonatomic-lo-hi.h>
34365cfa1eSAnton Vorontsov #include "ahci.h"
35c6fd2807SJeff Garzik 
36c6fd2807SJeff Garzik #define DRV_NAME	"ahci"
377d50b60bSTejun Heo #define DRV_VERSION	"3.0"
38c6fd2807SJeff Garzik 
39c6fd2807SJeff Garzik enum {
40318893e1SAlessandro Rubini 	AHCI_PCI_BAR_STA2X11	= 0,
41b7ae128dSRobert Richter 	AHCI_PCI_BAR_CAVIUM	= 0,
42e49bd683STiezhu Yang 	AHCI_PCI_BAR_LOONGSON	= 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,
51b0dd4d7aSLennert Buytenhek 	board_ahci_43bit_dma,
52441577efSTejun Heo 	board_ahci_ign_iferr,
53099849afSMario Limonciello 	board_ahci_low_power,
54a17ab7abSPaul Menzel 	board_ahci_no_debounce_delay,
5566a7cbc3STejun Heo 	board_ahci_nomsi,
5667809f85SLevente Kurusa 	board_ahci_noncq,
57441577efSTejun Heo 	board_ahci_nosntf,
585f173107STejun Heo 	board_ahci_yes_fbs,
59441577efSTejun Heo 
60441577efSTejun Heo 	/* board IDs for specific chipsets in alphabetical order */
617d523bdcSHanna Hawa 	board_ahci_al,
62dbfe8ef5SDan Williams 	board_ahci_avn,
63441577efSTejun Heo 	board_ahci_mcp65,
6483f2b963STejun Heo 	board_ahci_mcp77,
6583f2b963STejun Heo 	board_ahci_mcp89,
66441577efSTejun Heo 	board_ahci_mv,
67441577efSTejun Heo 	board_ahci_sb600,
68441577efSTejun Heo 	board_ahci_sb700,	/* for SB700 and SB800 */
69441577efSTejun Heo 	board_ahci_vt8251,
70441577efSTejun Heo 
71c312ef17SDan Williams 	/*
72c312ef17SDan Williams 	 * board IDs for Intel chipsets that support more than 6 ports
73c312ef17SDan Williams 	 * *and* end up needing the PCS quirk.
74c312ef17SDan Williams 	 */
75c312ef17SDan Williams 	board_ahci_pcs7,
76c312ef17SDan Williams 
77441577efSTejun Heo 	/* aliases */
78441577efSTejun Heo 	board_ahci_mcp_linux	= board_ahci_mcp65,
79441577efSTejun Heo 	board_ahci_mcp67	= board_ahci_mcp65,
80441577efSTejun Heo 	board_ahci_mcp73	= board_ahci_mcp65,
8183f2b963STejun Heo 	board_ahci_mcp79	= board_ahci_mcp77,
82c6fd2807SJeff Garzik };
83c6fd2807SJeff Garzik 
84c6fd2807SJeff Garzik static int ahci_init_one(struct pci_dev *pdev, const struct pci_device_id *ent);
8502e53293SMika Westerberg static void ahci_remove_one(struct pci_dev *dev);
8610a663a1SPrabhakar Kushwaha static void ahci_shutdown_one(struct pci_dev *dev);
8737e14e4fSAdam Vodopjan static void ahci_intel_pcs_quirk(struct pci_dev *pdev, struct ahci_host_priv *hpriv);
88a1efdabaSTejun Heo static int ahci_vt8251_hardreset(struct ata_link *link, unsigned int *class,
89a1efdabaSTejun Heo 				 unsigned long deadline);
90dbfe8ef5SDan Williams static int ahci_avn_hardreset(struct ata_link *link, unsigned int *class,
91dbfe8ef5SDan Williams 			      unsigned long deadline);
92cb85696dSJames Laird static void ahci_mcp89_apple_enable(struct pci_dev *pdev);
93cb85696dSJames Laird static bool is_mcp89_apple(struct pci_dev *pdev);
94a1efdabaSTejun Heo static int ahci_p5wdh_hardreset(struct ata_link *link, unsigned int *class,
95a1efdabaSTejun Heo 				unsigned long deadline);
9602e53293SMika Westerberg #ifdef CONFIG_PM
9702e53293SMika Westerberg static int ahci_pci_device_runtime_suspend(struct device *dev);
9802e53293SMika Westerberg static int ahci_pci_device_runtime_resume(struct device *dev);
99f1d848f9SMika Westerberg #ifdef CONFIG_PM_SLEEP
100f1d848f9SMika Westerberg static int ahci_pci_device_suspend(struct device *dev);
101f1d848f9SMika Westerberg static int ahci_pci_device_resume(struct device *dev);
102438ac6d5STejun Heo #endif
10302e53293SMika Westerberg #endif /* CONFIG_PM */
104c6fd2807SJeff Garzik 
10525df73d9SBart Van Assche static const struct scsi_host_template ahci_sht = {
106fad16e7aSTejun Heo 	AHCI_SHT("ahci"),
107fad16e7aSTejun Heo };
108fad16e7aSTejun Heo 
109029cfd6bSTejun Heo static struct ata_port_operations ahci_vt8251_ops = {
110029cfd6bSTejun Heo 	.inherits		= &ahci_ops,
111a1efdabaSTejun Heo 	.hardreset		= ahci_vt8251_hardreset,
112ad616ffbSTejun Heo };
113ad616ffbSTejun Heo 
114029cfd6bSTejun Heo static struct ata_port_operations ahci_p5wdh_ops = {
115029cfd6bSTejun Heo 	.inherits		= &ahci_ops,
116a1efdabaSTejun Heo 	.hardreset		= ahci_p5wdh_hardreset,
117edc93052STejun Heo };
118edc93052STejun Heo 
119dbfe8ef5SDan Williams static struct ata_port_operations ahci_avn_ops = {
120dbfe8ef5SDan Williams 	.inherits		= &ahci_ops,
121dbfe8ef5SDan Williams 	.hardreset		= ahci_avn_hardreset,
122dbfe8ef5SDan Williams };
123dbfe8ef5SDan Williams 
124c6fd2807SJeff Garzik static const struct ata_port_info ahci_port_info[] = {
125441577efSTejun Heo 	/* by features */
126facb8fa6SJeffrin Jose 	[board_ahci] = {
1271188c0d8STejun Heo 		.flags		= AHCI_FLAG_COMMON,
12814bdef98SErik Inge Bolsø 		.pio_mask	= ATA_PIO4,
129469248abSJeff Garzik 		.udma_mask	= ATA_UDMA6,
130c6fd2807SJeff Garzik 		.port_ops	= &ahci_ops,
131c6fd2807SJeff Garzik 	},
132b0dd4d7aSLennert Buytenhek 	[board_ahci_43bit_dma] = {
133b0dd4d7aSLennert Buytenhek 		AHCI_HFLAGS	(AHCI_HFLAG_43BIT_ONLY),
134b0dd4d7aSLennert Buytenhek 		.flags		= AHCI_FLAG_COMMON,
135b0dd4d7aSLennert Buytenhek 		.pio_mask	= ATA_PIO4,
136b0dd4d7aSLennert Buytenhek 		.udma_mask	= ATA_UDMA6,
137b0dd4d7aSLennert Buytenhek 		.port_ops	= &ahci_ops,
138b0dd4d7aSLennert Buytenhek 	},
139facb8fa6SJeffrin Jose 	[board_ahci_ign_iferr] = {
140417a1a6dSTejun Heo 		AHCI_HFLAGS	(AHCI_HFLAG_IGN_IRQ_IF_ERR),
141417a1a6dSTejun Heo 		.flags		= AHCI_FLAG_COMMON,
14214bdef98SErik Inge Bolsø 		.pio_mask	= ATA_PIO4,
143469248abSJeff Garzik 		.udma_mask	= ATA_UDMA6,
14441669553STejun Heo 		.port_ops	= &ahci_ops,
14541669553STejun Heo 	},
146099849afSMario Limonciello 	[board_ahci_low_power] = {
147e5c89479SMario Limonciello 		AHCI_HFLAGS	(AHCI_HFLAG_USE_LPM_POLICY),
148ebb82e3cSHans de Goede 		.flags		= AHCI_FLAG_COMMON,
149ebb82e3cSHans de Goede 		.pio_mask	= ATA_PIO4,
150ebb82e3cSHans de Goede 		.udma_mask	= ATA_UDMA6,
151ebb82e3cSHans de Goede 		.port_ops	= &ahci_ops,
152ebb82e3cSHans de Goede 	},
153a17ab7abSPaul Menzel 	[board_ahci_no_debounce_delay] = {
154a17ab7abSPaul Menzel 		.flags		= AHCI_FLAG_COMMON,
155a17ab7abSPaul Menzel 		.link_flags	= ATA_LFLAG_NO_DEBOUNCE_DELAY,
156a17ab7abSPaul Menzel 		.pio_mask	= ATA_PIO4,
157a17ab7abSPaul Menzel 		.udma_mask	= ATA_UDMA6,
158a17ab7abSPaul Menzel 		.port_ops	= &ahci_ops,
159a17ab7abSPaul Menzel 	},
16066a7cbc3STejun Heo 	[board_ahci_nomsi] = {
16166a7cbc3STejun Heo 		AHCI_HFLAGS	(AHCI_HFLAG_NO_MSI),
16266a7cbc3STejun Heo 		.flags		= AHCI_FLAG_COMMON,
16366a7cbc3STejun Heo 		.pio_mask	= ATA_PIO4,
16466a7cbc3STejun Heo 		.udma_mask	= ATA_UDMA6,
16566a7cbc3STejun Heo 		.port_ops	= &ahci_ops,
16666a7cbc3STejun Heo 	},
16767809f85SLevente Kurusa 	[board_ahci_noncq] = {
16867809f85SLevente Kurusa 		AHCI_HFLAGS	(AHCI_HFLAG_NO_NCQ),
16967809f85SLevente Kurusa 		.flags		= AHCI_FLAG_COMMON,
17067809f85SLevente Kurusa 		.pio_mask	= ATA_PIO4,
17167809f85SLevente Kurusa 		.udma_mask	= ATA_UDMA6,
17267809f85SLevente Kurusa 		.port_ops	= &ahci_ops,
17367809f85SLevente Kurusa 	},
174facb8fa6SJeffrin Jose 	[board_ahci_nosntf] = {
175441577efSTejun Heo 		AHCI_HFLAGS	(AHCI_HFLAG_NO_SNTF),
176441577efSTejun Heo 		.flags		= AHCI_FLAG_COMMON,
177441577efSTejun Heo 		.pio_mask	= ATA_PIO4,
178441577efSTejun Heo 		.udma_mask	= ATA_UDMA6,
179441577efSTejun Heo 		.port_ops	= &ahci_ops,
180441577efSTejun Heo 	},
181facb8fa6SJeffrin Jose 	[board_ahci_yes_fbs] = {
1825f173107STejun Heo 		AHCI_HFLAGS	(AHCI_HFLAG_YES_FBS),
1835f173107STejun Heo 		.flags		= AHCI_FLAG_COMMON,
1845f173107STejun Heo 		.pio_mask	= ATA_PIO4,
1855f173107STejun Heo 		.udma_mask	= ATA_UDMA6,
1865f173107STejun Heo 		.port_ops	= &ahci_ops,
1875f173107STejun Heo 	},
188441577efSTejun Heo 	/* by chipsets */
1897d523bdcSHanna Hawa 	[board_ahci_al] = {
1907d523bdcSHanna Hawa 		AHCI_HFLAGS	(AHCI_HFLAG_NO_PMP | AHCI_HFLAG_NO_MSI),
1917d523bdcSHanna Hawa 		.flags		= AHCI_FLAG_COMMON,
1927d523bdcSHanna Hawa 		.pio_mask	= ATA_PIO4,
1937d523bdcSHanna Hawa 		.udma_mask	= ATA_UDMA6,
1947d523bdcSHanna Hawa 		.port_ops	= &ahci_ops,
1957d523bdcSHanna Hawa 	},
196dbfe8ef5SDan Williams 	[board_ahci_avn] = {
197dbfe8ef5SDan Williams 		.flags		= AHCI_FLAG_COMMON,
198dbfe8ef5SDan Williams 		.pio_mask	= ATA_PIO4,
199dbfe8ef5SDan Williams 		.udma_mask	= ATA_UDMA6,
200dbfe8ef5SDan Williams 		.port_ops	= &ahci_avn_ops,
201dbfe8ef5SDan Williams 	},
202facb8fa6SJeffrin Jose 	[board_ahci_mcp65] = {
20383f2b963STejun Heo 		AHCI_HFLAGS	(AHCI_HFLAG_NO_FPDMA_AA | AHCI_HFLAG_NO_PMP |
20483f2b963STejun Heo 				 AHCI_HFLAG_YES_NCQ),
205ae01b249STejun Heo 		.flags		= AHCI_FLAG_COMMON | ATA_FLAG_NO_DIPM,
20683f2b963STejun Heo 		.pio_mask	= ATA_PIO4,
20783f2b963STejun Heo 		.udma_mask	= ATA_UDMA6,
20883f2b963STejun Heo 		.port_ops	= &ahci_ops,
20983f2b963STejun Heo 	},
210facb8fa6SJeffrin Jose 	[board_ahci_mcp77] = {
21183f2b963STejun Heo 		AHCI_HFLAGS	(AHCI_HFLAG_NO_FPDMA_AA | AHCI_HFLAG_NO_PMP),
21283f2b963STejun Heo 		.flags		= AHCI_FLAG_COMMON,
21383f2b963STejun Heo 		.pio_mask	= ATA_PIO4,
21483f2b963STejun Heo 		.udma_mask	= ATA_UDMA6,
21583f2b963STejun Heo 		.port_ops	= &ahci_ops,
21683f2b963STejun Heo 	},
217facb8fa6SJeffrin Jose 	[board_ahci_mcp89] = {
21883f2b963STejun Heo 		AHCI_HFLAGS	(AHCI_HFLAG_NO_FPDMA_AA),
219441577efSTejun Heo 		.flags		= AHCI_FLAG_COMMON,
220441577efSTejun Heo 		.pio_mask	= ATA_PIO4,
221441577efSTejun Heo 		.udma_mask	= ATA_UDMA6,
222441577efSTejun Heo 		.port_ops	= &ahci_ops,
223441577efSTejun Heo 	},
224facb8fa6SJeffrin Jose 	[board_ahci_mv] = {
225441577efSTejun Heo 		AHCI_HFLAGS	(AHCI_HFLAG_NO_NCQ | AHCI_HFLAG_NO_MSI |
226441577efSTejun Heo 				 AHCI_HFLAG_MV_PATA | AHCI_HFLAG_NO_PMP),
2279cbe056fSSergei Shtylyov 		.flags		= ATA_FLAG_SATA | ATA_FLAG_PIO_DMA,
228441577efSTejun Heo 		.pio_mask	= ATA_PIO4,
229441577efSTejun Heo 		.udma_mask	= ATA_UDMA6,
230441577efSTejun Heo 		.port_ops	= &ahci_ops,
231441577efSTejun Heo 	},
232facb8fa6SJeffrin Jose 	[board_ahci_sb600] = {
233417a1a6dSTejun Heo 		AHCI_HFLAGS	(AHCI_HFLAG_IGN_SERR_INTERNAL |
2342fcad9d2STejun Heo 				 AHCI_HFLAG_NO_MSI | AHCI_HFLAG_SECT255 |
2352fcad9d2STejun Heo 				 AHCI_HFLAG_32BIT_ONLY),
236417a1a6dSTejun Heo 		.flags		= AHCI_FLAG_COMMON,
23714bdef98SErik Inge Bolsø 		.pio_mask	= ATA_PIO4,
238469248abSJeff Garzik 		.udma_mask	= ATA_UDMA6,
239345347c5SYuan-Hsin Chen 		.port_ops	= &ahci_pmp_retry_srst_ops,
24055a61604SConke Hu 	},
241facb8fa6SJeffrin Jose 	[board_ahci_sb700] = {	/* for SB700 and SB800 */
242bd17243aSShane Huang 		AHCI_HFLAGS	(AHCI_HFLAG_IGN_SERR_INTERNAL),
243e39fc8c9SShane Huang 		.flags		= AHCI_FLAG_COMMON,
24414bdef98SErik Inge Bolsø 		.pio_mask	= ATA_PIO4,
245e39fc8c9SShane Huang 		.udma_mask	= ATA_UDMA6,
246345347c5SYuan-Hsin Chen 		.port_ops	= &ahci_pmp_retry_srst_ops,
247e39fc8c9SShane Huang 	},
248facb8fa6SJeffrin Jose 	[board_ahci_vt8251] = {
249441577efSTejun Heo 		AHCI_HFLAGS	(AHCI_HFLAG_NO_NCQ | AHCI_HFLAG_NO_PMP),
250e297d99eSTejun Heo 		.flags		= AHCI_FLAG_COMMON,
25114bdef98SErik Inge Bolsø 		.pio_mask	= ATA_PIO4,
252e297d99eSTejun Heo 		.udma_mask	= ATA_UDMA6,
253441577efSTejun Heo 		.port_ops	= &ahci_vt8251_ops,
2541b677afdSShaohua Li 	},
255c312ef17SDan Williams 	[board_ahci_pcs7] = {
256c312ef17SDan Williams 		.flags		= AHCI_FLAG_COMMON,
257c312ef17SDan Williams 		.pio_mask	= ATA_PIO4,
258c312ef17SDan Williams 		.udma_mask	= ATA_UDMA6,
259c312ef17SDan Williams 		.port_ops	= &ahci_ops,
260c312ef17SDan Williams 	},
261c6fd2807SJeff Garzik };
262c6fd2807SJeff Garzik 
263c6fd2807SJeff Garzik static const struct pci_device_id ahci_pci_tbl[] = {
264c6fd2807SJeff Garzik 	/* Intel */
2655e125d13SMika Westerberg 	{ PCI_VDEVICE(INTEL, 0x06d6), board_ahci }, /* Comet Lake PCH-H RAID */
26654bb3a94SJeff Garzik 	{ PCI_VDEVICE(INTEL, 0x2652), board_ahci }, /* ICH6 */
26754bb3a94SJeff Garzik 	{ PCI_VDEVICE(INTEL, 0x2653), board_ahci }, /* ICH6M */
26854bb3a94SJeff Garzik 	{ PCI_VDEVICE(INTEL, 0x27c1), board_ahci }, /* ICH7 */
26954bb3a94SJeff Garzik 	{ PCI_VDEVICE(INTEL, 0x27c5), board_ahci }, /* ICH7M */
27054bb3a94SJeff Garzik 	{ PCI_VDEVICE(INTEL, 0x27c3), board_ahci }, /* ICH7R */
27182490c09STejun Heo 	{ PCI_VDEVICE(AL, 0x5288), board_ahci_ign_iferr }, /* ULi M5288 */
27254bb3a94SJeff Garzik 	{ PCI_VDEVICE(INTEL, 0x2681), board_ahci }, /* ESB2 */
27354bb3a94SJeff Garzik 	{ PCI_VDEVICE(INTEL, 0x2682), board_ahci }, /* ESB2 */
27454bb3a94SJeff Garzik 	{ PCI_VDEVICE(INTEL, 0x2683), board_ahci }, /* ESB2 */
27554bb3a94SJeff Garzik 	{ PCI_VDEVICE(INTEL, 0x27c6), board_ahci }, /* ICH7-M DH */
2767a234affSTejun Heo 	{ PCI_VDEVICE(INTEL, 0x2821), board_ahci }, /* ICH8 */
2770e96dc47SKrzysztof Kozlowski 	{ PCI_VDEVICE(INTEL, 0x2822), board_ahci_nosntf }, /* ICH8/Lewisburg RAID*/
2787a234affSTejun Heo 	{ PCI_VDEVICE(INTEL, 0x2824), board_ahci }, /* ICH8 */
2797a234affSTejun Heo 	{ PCI_VDEVICE(INTEL, 0x2829), board_ahci }, /* ICH8M */
2807a234affSTejun Heo 	{ PCI_VDEVICE(INTEL, 0x282a), board_ahci }, /* ICH8M */
2817a234affSTejun Heo 	{ PCI_VDEVICE(INTEL, 0x2922), board_ahci }, /* ICH9 */
2827a234affSTejun Heo 	{ PCI_VDEVICE(INTEL, 0x2923), board_ahci }, /* ICH9 */
2837a234affSTejun Heo 	{ PCI_VDEVICE(INTEL, 0x2924), board_ahci }, /* ICH9 */
2847a234affSTejun Heo 	{ PCI_VDEVICE(INTEL, 0x2925), board_ahci }, /* ICH9 */
2857a234affSTejun Heo 	{ PCI_VDEVICE(INTEL, 0x2927), board_ahci }, /* ICH9 */
286099849afSMario Limonciello 	{ PCI_VDEVICE(INTEL, 0x2929), board_ahci_low_power }, /* ICH9M */
287099849afSMario Limonciello 	{ PCI_VDEVICE(INTEL, 0x292a), board_ahci_low_power }, /* ICH9M */
288099849afSMario Limonciello 	{ PCI_VDEVICE(INTEL, 0x292b), board_ahci_low_power }, /* ICH9M */
289099849afSMario Limonciello 	{ PCI_VDEVICE(INTEL, 0x292c), board_ahci_low_power }, /* ICH9M */
290099849afSMario Limonciello 	{ PCI_VDEVICE(INTEL, 0x292f), board_ahci_low_power }, /* ICH9M */
2917a234affSTejun Heo 	{ PCI_VDEVICE(INTEL, 0x294d), board_ahci }, /* ICH9 */
292099849afSMario Limonciello 	{ PCI_VDEVICE(INTEL, 0x294e), board_ahci_low_power }, /* ICH9M */
293d4155e6fSJason Gaston 	{ PCI_VDEVICE(INTEL, 0x502a), board_ahci }, /* Tolapai */
294d4155e6fSJason Gaston 	{ PCI_VDEVICE(INTEL, 0x502b), board_ahci }, /* Tolapai */
29516ad1ad9SJason Gaston 	{ PCI_VDEVICE(INTEL, 0x3a05), board_ahci }, /* ICH10 */
296b2dde6afSMark Goodwin 	{ PCI_VDEVICE(INTEL, 0x3a22), board_ahci }, /* ICH10 */
29716ad1ad9SJason Gaston 	{ PCI_VDEVICE(INTEL, 0x3a25), board_ahci }, /* ICH10 */
298c1f57d9bSDavid Milburn 	{ PCI_VDEVICE(INTEL, 0x3b22), board_ahci }, /* PCH AHCI */
299c1f57d9bSDavid Milburn 	{ PCI_VDEVICE(INTEL, 0x3b23), board_ahci }, /* PCH AHCI */
300adcb5308SSeth Heasley 	{ PCI_VDEVICE(INTEL, 0x3b24), board_ahci }, /* PCH RAID */
3018e48b6b3SSeth Heasley 	{ PCI_VDEVICE(INTEL, 0x3b25), board_ahci }, /* PCH RAID */
302099849afSMario Limonciello 	{ PCI_VDEVICE(INTEL, 0x3b29), board_ahci_low_power }, /* PCH M AHCI */
303adcb5308SSeth Heasley 	{ PCI_VDEVICE(INTEL, 0x3b2b), board_ahci }, /* PCH RAID */
304099849afSMario Limonciello 	{ PCI_VDEVICE(INTEL, 0x3b2c), board_ahci_low_power }, /* PCH M RAID */
305c1f57d9bSDavid Milburn 	{ PCI_VDEVICE(INTEL, 0x3b2f), board_ahci }, /* PCH AHCI */
306c312ef17SDan Williams 	{ PCI_VDEVICE(INTEL, 0x19b0), board_ahci_pcs7 }, /* DNV AHCI */
307c312ef17SDan Williams 	{ PCI_VDEVICE(INTEL, 0x19b1), board_ahci_pcs7 }, /* DNV AHCI */
308c312ef17SDan Williams 	{ PCI_VDEVICE(INTEL, 0x19b2), board_ahci_pcs7 }, /* DNV AHCI */
309c312ef17SDan Williams 	{ PCI_VDEVICE(INTEL, 0x19b3), board_ahci_pcs7 }, /* DNV AHCI */
310c312ef17SDan Williams 	{ PCI_VDEVICE(INTEL, 0x19b4), board_ahci_pcs7 }, /* DNV AHCI */
311c312ef17SDan Williams 	{ PCI_VDEVICE(INTEL, 0x19b5), board_ahci_pcs7 }, /* DNV AHCI */
312c312ef17SDan Williams 	{ PCI_VDEVICE(INTEL, 0x19b6), board_ahci_pcs7 }, /* DNV AHCI */
313c312ef17SDan Williams 	{ PCI_VDEVICE(INTEL, 0x19b7), board_ahci_pcs7 }, /* DNV AHCI */
314c312ef17SDan Williams 	{ PCI_VDEVICE(INTEL, 0x19bE), board_ahci_pcs7 }, /* DNV AHCI */
315c312ef17SDan Williams 	{ PCI_VDEVICE(INTEL, 0x19bF), board_ahci_pcs7 }, /* DNV AHCI */
316c312ef17SDan Williams 	{ PCI_VDEVICE(INTEL, 0x19c0), board_ahci_pcs7 }, /* DNV AHCI */
317c312ef17SDan Williams 	{ PCI_VDEVICE(INTEL, 0x19c1), board_ahci_pcs7 }, /* DNV AHCI */
318c312ef17SDan Williams 	{ PCI_VDEVICE(INTEL, 0x19c2), board_ahci_pcs7 }, /* DNV AHCI */
319c312ef17SDan Williams 	{ PCI_VDEVICE(INTEL, 0x19c3), board_ahci_pcs7 }, /* DNV AHCI */
320c312ef17SDan Williams 	{ PCI_VDEVICE(INTEL, 0x19c4), board_ahci_pcs7 }, /* DNV AHCI */
321c312ef17SDan Williams 	{ PCI_VDEVICE(INTEL, 0x19c5), board_ahci_pcs7 }, /* DNV AHCI */
322c312ef17SDan Williams 	{ PCI_VDEVICE(INTEL, 0x19c6), board_ahci_pcs7 }, /* DNV AHCI */
323c312ef17SDan Williams 	{ PCI_VDEVICE(INTEL, 0x19c7), board_ahci_pcs7 }, /* DNV AHCI */
324c312ef17SDan Williams 	{ PCI_VDEVICE(INTEL, 0x19cE), board_ahci_pcs7 }, /* DNV AHCI */
325c312ef17SDan Williams 	{ PCI_VDEVICE(INTEL, 0x19cF), board_ahci_pcs7 }, /* DNV AHCI */
3265623cab8SSeth Heasley 	{ PCI_VDEVICE(INTEL, 0x1c02), board_ahci }, /* CPT AHCI */
327099849afSMario Limonciello 	{ PCI_VDEVICE(INTEL, 0x1c03), board_ahci_low_power }, /* CPT M AHCI */
3285623cab8SSeth Heasley 	{ PCI_VDEVICE(INTEL, 0x1c04), board_ahci }, /* CPT RAID */
329099849afSMario Limonciello 	{ PCI_VDEVICE(INTEL, 0x1c05), board_ahci_low_power }, /* CPT M RAID */
3305623cab8SSeth Heasley 	{ PCI_VDEVICE(INTEL, 0x1c06), board_ahci }, /* CPT RAID */
3315623cab8SSeth Heasley 	{ PCI_VDEVICE(INTEL, 0x1c07), board_ahci }, /* CPT RAID */
332992b3fb9SSeth Heasley 	{ PCI_VDEVICE(INTEL, 0x1d02), board_ahci }, /* PBG AHCI */
333992b3fb9SSeth Heasley 	{ PCI_VDEVICE(INTEL, 0x1d04), board_ahci }, /* PBG RAID */
334992b3fb9SSeth Heasley 	{ PCI_VDEVICE(INTEL, 0x1d06), board_ahci }, /* PBG RAID */
335a4a461a6SSeth Heasley 	{ PCI_VDEVICE(INTEL, 0x2323), board_ahci }, /* DH89xxCC AHCI */
336181e3ceaSSeth Heasley 	{ PCI_VDEVICE(INTEL, 0x1e02), board_ahci }, /* Panther Point AHCI */
337099849afSMario Limonciello 	{ PCI_VDEVICE(INTEL, 0x1e03), board_ahci_low_power }, /* Panther M AHCI */
338181e3ceaSSeth Heasley 	{ PCI_VDEVICE(INTEL, 0x1e04), board_ahci }, /* Panther Point RAID */
339181e3ceaSSeth Heasley 	{ PCI_VDEVICE(INTEL, 0x1e05), board_ahci }, /* Panther Point RAID */
340181e3ceaSSeth Heasley 	{ PCI_VDEVICE(INTEL, 0x1e06), board_ahci }, /* Panther Point RAID */
341099849afSMario Limonciello 	{ PCI_VDEVICE(INTEL, 0x1e07), board_ahci_low_power }, /* Panther M RAID */
3422cab7a4cSSeth Heasley 	{ PCI_VDEVICE(INTEL, 0x1e0e), board_ahci }, /* Panther Point RAID */
343ea4ace66SSeth Heasley 	{ PCI_VDEVICE(INTEL, 0x8c02), board_ahci }, /* Lynx Point AHCI */
344099849afSMario Limonciello 	{ PCI_VDEVICE(INTEL, 0x8c03), board_ahci_low_power }, /* Lynx M AHCI */
345ea4ace66SSeth Heasley 	{ PCI_VDEVICE(INTEL, 0x8c04), board_ahci }, /* Lynx Point RAID */
346099849afSMario Limonciello 	{ PCI_VDEVICE(INTEL, 0x8c05), board_ahci_low_power }, /* Lynx M RAID */
347ea4ace66SSeth Heasley 	{ PCI_VDEVICE(INTEL, 0x8c06), board_ahci }, /* Lynx Point RAID */
348099849afSMario Limonciello 	{ PCI_VDEVICE(INTEL, 0x8c07), board_ahci_low_power }, /* Lynx M RAID */
349ea4ace66SSeth Heasley 	{ PCI_VDEVICE(INTEL, 0x8c0e), board_ahci }, /* Lynx Point RAID */
350099849afSMario Limonciello 	{ PCI_VDEVICE(INTEL, 0x8c0f), board_ahci_low_power }, /* Lynx M RAID */
351099849afSMario Limonciello 	{ PCI_VDEVICE(INTEL, 0x9c02), board_ahci_low_power }, /* Lynx LP AHCI */
352099849afSMario Limonciello 	{ PCI_VDEVICE(INTEL, 0x9c03), board_ahci_low_power }, /* Lynx LP AHCI */
353099849afSMario Limonciello 	{ PCI_VDEVICE(INTEL, 0x9c04), board_ahci_low_power }, /* Lynx LP RAID */
354099849afSMario Limonciello 	{ PCI_VDEVICE(INTEL, 0x9c05), board_ahci_low_power }, /* Lynx LP RAID */
355099849afSMario Limonciello 	{ PCI_VDEVICE(INTEL, 0x9c06), board_ahci_low_power }, /* Lynx LP RAID */
356099849afSMario Limonciello 	{ PCI_VDEVICE(INTEL, 0x9c07), board_ahci_low_power }, /* Lynx LP RAID */
357099849afSMario Limonciello 	{ PCI_VDEVICE(INTEL, 0x9c0e), board_ahci_low_power }, /* Lynx LP RAID */
358099849afSMario Limonciello 	{ PCI_VDEVICE(INTEL, 0x9c0f), board_ahci_low_power }, /* Lynx LP RAID */
359099849afSMario Limonciello 	{ PCI_VDEVICE(INTEL, 0x9dd3), board_ahci_low_power }, /* Cannon Lake PCH-LP AHCI */
36029e674ddSSeth Heasley 	{ PCI_VDEVICE(INTEL, 0x1f22), board_ahci }, /* Avoton AHCI */
36129e674ddSSeth Heasley 	{ PCI_VDEVICE(INTEL, 0x1f23), board_ahci }, /* Avoton AHCI */
36229e674ddSSeth Heasley 	{ PCI_VDEVICE(INTEL, 0x1f24), board_ahci }, /* Avoton RAID */
36329e674ddSSeth Heasley 	{ PCI_VDEVICE(INTEL, 0x1f25), board_ahci }, /* Avoton RAID */
36429e674ddSSeth Heasley 	{ PCI_VDEVICE(INTEL, 0x1f26), board_ahci }, /* Avoton RAID */
36529e674ddSSeth Heasley 	{ PCI_VDEVICE(INTEL, 0x1f27), board_ahci }, /* Avoton RAID */
36629e674ddSSeth Heasley 	{ PCI_VDEVICE(INTEL, 0x1f2e), board_ahci }, /* Avoton RAID */
36729e674ddSSeth Heasley 	{ PCI_VDEVICE(INTEL, 0x1f2f), board_ahci }, /* Avoton RAID */
368dbfe8ef5SDan Williams 	{ PCI_VDEVICE(INTEL, 0x1f32), board_ahci_avn }, /* Avoton AHCI */
369dbfe8ef5SDan Williams 	{ PCI_VDEVICE(INTEL, 0x1f33), board_ahci_avn }, /* Avoton AHCI */
370dbfe8ef5SDan Williams 	{ PCI_VDEVICE(INTEL, 0x1f34), board_ahci_avn }, /* Avoton RAID */
371dbfe8ef5SDan Williams 	{ PCI_VDEVICE(INTEL, 0x1f35), board_ahci_avn }, /* Avoton RAID */
372dbfe8ef5SDan Williams 	{ PCI_VDEVICE(INTEL, 0x1f36), board_ahci_avn }, /* Avoton RAID */
373dbfe8ef5SDan Williams 	{ PCI_VDEVICE(INTEL, 0x1f37), board_ahci_avn }, /* Avoton RAID */
374dbfe8ef5SDan Williams 	{ PCI_VDEVICE(INTEL, 0x1f3e), board_ahci_avn }, /* Avoton RAID */
375dbfe8ef5SDan Williams 	{ PCI_VDEVICE(INTEL, 0x1f3f), board_ahci_avn }, /* Avoton RAID */
3760e96dc47SKrzysztof Kozlowski 	{ PCI_VDEVICE(INTEL, 0x2823), board_ahci }, /* Wellsburg/Lewisburg AHCI*/
3775716fb0dSDan Williams 	{ PCI_VDEVICE(INTEL, 0x2826), board_ahci }, /* *burg SATA0 'RAID' */
3785716fb0dSDan Williams 	{ PCI_VDEVICE(INTEL, 0x2827), board_ahci }, /* *burg SATA1 'RAID' */
3795716fb0dSDan Williams 	{ PCI_VDEVICE(INTEL, 0x282f), board_ahci }, /* *burg SATA2 'RAID' */
3808e85f605SMika Westerberg 	{ PCI_VDEVICE(INTEL, 0x43d4), board_ahci }, /* Rocket Lake PCH-H RAID */
3818e85f605SMika Westerberg 	{ PCI_VDEVICE(INTEL, 0x43d5), board_ahci }, /* Rocket Lake PCH-H RAID */
3828e85f605SMika Westerberg 	{ PCI_VDEVICE(INTEL, 0x43d6), board_ahci }, /* Rocket Lake PCH-H RAID */
3838e85f605SMika Westerberg 	{ PCI_VDEVICE(INTEL, 0x43d7), board_ahci }, /* Rocket Lake PCH-H RAID */
384151743fdSJames Ralston 	{ PCI_VDEVICE(INTEL, 0x8d02), board_ahci }, /* Wellsburg AHCI */
385151743fdSJames Ralston 	{ PCI_VDEVICE(INTEL, 0x8d04), board_ahci }, /* Wellsburg RAID */
386151743fdSJames Ralston 	{ PCI_VDEVICE(INTEL, 0x8d06), board_ahci }, /* Wellsburg RAID */
387151743fdSJames Ralston 	{ PCI_VDEVICE(INTEL, 0x8d0e), board_ahci }, /* Wellsburg RAID */
388151743fdSJames Ralston 	{ PCI_VDEVICE(INTEL, 0x8d62), board_ahci }, /* Wellsburg AHCI */
389151743fdSJames Ralston 	{ PCI_VDEVICE(INTEL, 0x8d64), board_ahci }, /* Wellsburg RAID */
390151743fdSJames Ralston 	{ PCI_VDEVICE(INTEL, 0x8d66), board_ahci }, /* Wellsburg RAID */
391151743fdSJames Ralston 	{ PCI_VDEVICE(INTEL, 0x8d6e), board_ahci }, /* Wellsburg RAID */
3921cfc7df3SSeth Heasley 	{ PCI_VDEVICE(INTEL, 0x23a3), board_ahci }, /* Coleto Creek AHCI */
393099849afSMario Limonciello 	{ PCI_VDEVICE(INTEL, 0x9c83), board_ahci_low_power }, /* Wildcat LP AHCI */
394099849afSMario Limonciello 	{ PCI_VDEVICE(INTEL, 0x9c85), board_ahci_low_power }, /* Wildcat LP RAID */
395099849afSMario Limonciello 	{ PCI_VDEVICE(INTEL, 0x9c87), board_ahci_low_power }, /* Wildcat LP RAID */
396099849afSMario Limonciello 	{ PCI_VDEVICE(INTEL, 0x9c8f), board_ahci_low_power }, /* Wildcat LP RAID */
3971b071a09SJames Ralston 	{ PCI_VDEVICE(INTEL, 0x8c82), board_ahci }, /* 9 Series AHCI */
398099849afSMario Limonciello 	{ PCI_VDEVICE(INTEL, 0x8c83), board_ahci_low_power }, /* 9 Series M AHCI */
3991b071a09SJames Ralston 	{ PCI_VDEVICE(INTEL, 0x8c84), board_ahci }, /* 9 Series RAID */
400099849afSMario Limonciello 	{ PCI_VDEVICE(INTEL, 0x8c85), board_ahci_low_power }, /* 9 Series M RAID */
4011b071a09SJames Ralston 	{ PCI_VDEVICE(INTEL, 0x8c86), board_ahci }, /* 9 Series RAID */
402099849afSMario Limonciello 	{ PCI_VDEVICE(INTEL, 0x8c87), board_ahci_low_power }, /* 9 Series M RAID */
4031b071a09SJames Ralston 	{ PCI_VDEVICE(INTEL, 0x8c8e), board_ahci }, /* 9 Series RAID */
404099849afSMario Limonciello 	{ PCI_VDEVICE(INTEL, 0x8c8f), board_ahci_low_power }, /* 9 Series M RAID */
405099849afSMario Limonciello 	{ PCI_VDEVICE(INTEL, 0x9d03), board_ahci_low_power }, /* Sunrise LP AHCI */
406099849afSMario Limonciello 	{ PCI_VDEVICE(INTEL, 0x9d05), board_ahci_low_power }, /* Sunrise LP RAID */
407099849afSMario Limonciello 	{ PCI_VDEVICE(INTEL, 0x9d07), board_ahci_low_power }, /* Sunrise LP RAID */
408c5967b79SCharles_Rose@Dell.com 	{ PCI_VDEVICE(INTEL, 0xa102), board_ahci }, /* Sunrise Point-H AHCI */
409099849afSMario Limonciello 	{ PCI_VDEVICE(INTEL, 0xa103), board_ahci_low_power }, /* Sunrise M AHCI */
410690000b9SJames Ralston 	{ PCI_VDEVICE(INTEL, 0xa105), board_ahci }, /* Sunrise Point-H RAID */
411c5967b79SCharles_Rose@Dell.com 	{ PCI_VDEVICE(INTEL, 0xa106), board_ahci }, /* Sunrise Point-H RAID */
412099849afSMario Limonciello 	{ PCI_VDEVICE(INTEL, 0xa107), board_ahci_low_power }, /* Sunrise M RAID */
413690000b9SJames Ralston 	{ PCI_VDEVICE(INTEL, 0xa10f), board_ahci }, /* Sunrise Point-H RAID */
4144d92f009SAlexandra Yates 	{ PCI_VDEVICE(INTEL, 0xa182), board_ahci }, /* Lewisburg AHCI*/
4154d92f009SAlexandra Yates 	{ PCI_VDEVICE(INTEL, 0xa186), board_ahci }, /* Lewisburg RAID*/
416f5bdd66cSAlexandra Yates 	{ PCI_VDEVICE(INTEL, 0xa1d2), board_ahci }, /* Lewisburg RAID*/
417f5bdd66cSAlexandra Yates 	{ PCI_VDEVICE(INTEL, 0xa1d6), board_ahci }, /* Lewisburg RAID*/
4184d92f009SAlexandra Yates 	{ PCI_VDEVICE(INTEL, 0xa202), board_ahci }, /* Lewisburg AHCI*/
4194d92f009SAlexandra Yates 	{ PCI_VDEVICE(INTEL, 0xa206), board_ahci }, /* Lewisburg RAID*/
420f5bdd66cSAlexandra Yates 	{ PCI_VDEVICE(INTEL, 0xa252), board_ahci }, /* Lewisburg RAID*/
421f5bdd66cSAlexandra Yates 	{ PCI_VDEVICE(INTEL, 0xa256), board_ahci }, /* Lewisburg RAID*/
422f919dde0SMika Westerberg 	{ PCI_VDEVICE(INTEL, 0xa356), board_ahci }, /* Cannon Lake PCH-H RAID */
42332d25454SKai-Heng Feng 	{ PCI_VDEVICE(INTEL, 0x06d7), board_ahci }, /* Comet Lake-H RAID */
42458c42b0bSMika Westerberg 	{ PCI_VDEVICE(INTEL, 0xa386), board_ahci }, /* Comet Lake PCH-V RAID */
425099849afSMario Limonciello 	{ PCI_VDEVICE(INTEL, 0x0f22), board_ahci_low_power }, /* Bay Trail AHCI */
426099849afSMario Limonciello 	{ PCI_VDEVICE(INTEL, 0x0f23), board_ahci_low_power }, /* Bay Trail AHCI */
427099849afSMario Limonciello 	{ PCI_VDEVICE(INTEL, 0x22a3), board_ahci_low_power }, /* Cherry Tr. AHCI */
428099849afSMario Limonciello 	{ PCI_VDEVICE(INTEL, 0x5ae3), board_ahci_low_power }, /* ApolloLake AHCI */
429099849afSMario Limonciello 	{ PCI_VDEVICE(INTEL, 0x34d3), board_ahci_low_power }, /* Ice Lake LP AHCI */
430099849afSMario Limonciello 	{ PCI_VDEVICE(INTEL, 0x02d3), board_ahci_low_power }, /* Comet Lake PCH-U AHCI */
431099849afSMario Limonciello 	{ PCI_VDEVICE(INTEL, 0x02d7), board_ahci_low_power }, /* Comet Lake PCH RAID */
4322a2df98eSWerner Fischer 	/* Elkhart Lake IDs 0x4b60 & 0x4b62 https://sata-io.org/product/8803 not tested yet */
4332a2df98eSWerner Fischer 	{ PCI_VDEVICE(INTEL, 0x4b63), board_ahci_low_power }, /* Elkhart Lake AHCI */
434c6fd2807SJeff Garzik 
435e34bb370STejun Heo 	/* JMicron 360/1/3/5/6, match class to avoid IDE function */
436e34bb370STejun Heo 	{ PCI_VENDOR_ID_JMICRON, PCI_ANY_ID, PCI_ANY_ID, PCI_ANY_ID,
437e34bb370STejun Heo 	  PCI_CLASS_STORAGE_SATA_AHCI, 0xffffff, board_ahci_ign_iferr },
4381fefb8fdSBen Hutchings 	/* JMicron 362B and 362C have an AHCI function with IDE class code */
4391fefb8fdSBen Hutchings 	{ PCI_VDEVICE(JMICRON, 0x2362), board_ahci_ign_iferr },
4401fefb8fdSBen Hutchings 	{ PCI_VDEVICE(JMICRON, 0x236f), board_ahci_ign_iferr },
44191f15fb3SZhang Rui 	/* May need to update quirk_jmicron_async_suspend() for additions */
442c6fd2807SJeff Garzik 
443c6fd2807SJeff Garzik 	/* ATI */
444c65ec1c2SConke Hu 	{ PCI_VDEVICE(ATI, 0x4380), board_ahci_sb600 }, /* ATI SB600 */
445e39fc8c9SShane Huang 	{ PCI_VDEVICE(ATI, 0x4390), board_ahci_sb700 }, /* ATI SB700/800 */
446e39fc8c9SShane Huang 	{ PCI_VDEVICE(ATI, 0x4391), board_ahci_sb700 }, /* ATI SB700/800 */
447e39fc8c9SShane Huang 	{ PCI_VDEVICE(ATI, 0x4392), board_ahci_sb700 }, /* ATI SB700/800 */
448e39fc8c9SShane Huang 	{ PCI_VDEVICE(ATI, 0x4393), board_ahci_sb700 }, /* ATI SB700/800 */
449e39fc8c9SShane Huang 	{ PCI_VDEVICE(ATI, 0x4394), board_ahci_sb700 }, /* ATI SB700/800 */
450e39fc8c9SShane Huang 	{ PCI_VDEVICE(ATI, 0x4395), board_ahci_sb700 }, /* ATI SB700/800 */
451c6fd2807SJeff Garzik 
4527d523bdcSHanna Hawa 	/* Amazon's Annapurna Labs support */
4537d523bdcSHanna Hawa 	{ PCI_DEVICE(PCI_VENDOR_ID_AMAZON_ANNAPURNA_LABS, 0x0031),
4547d523bdcSHanna Hawa 		.class = PCI_CLASS_STORAGE_SATA_AHCI,
4557d523bdcSHanna Hawa 		.class_mask = 0xffffff,
4567d523bdcSHanna Hawa 		board_ahci_al },
457e2dd90b1SShane Huang 	/* AMD */
4585deab536SShane Huang 	{ PCI_VDEVICE(AMD, 0x7800), board_ahci }, /* AMD Hudson-2 */
459a17ab7abSPaul Menzel 	{ PCI_VDEVICE(AMD, 0x7801), board_ahci_no_debounce_delay }, /* AMD Hudson-2 (AHCI mode) */
460fafe5c3dSShane Huang 	{ PCI_VDEVICE(AMD, 0x7900), board_ahci }, /* AMD CZ */
461099849afSMario Limonciello 	{ PCI_VDEVICE(AMD, 0x7901), board_ahci_low_power }, /* AMD Green Sardine */
462e2dd90b1SShane Huang 	/* AMD is using RAID class only for ahci controllers */
463e2dd90b1SShane Huang 	{ PCI_VENDOR_ID_AMD, PCI_ANY_ID, PCI_ANY_ID, PCI_ANY_ID,
464e2dd90b1SShane Huang 	  PCI_CLASS_STORAGE_RAID << 8, 0xffffff, board_ahci },
465e2dd90b1SShane Huang 
4669c54cd10SCharles Rose 	/* Dell S140/S150 */
4679c54cd10SCharles Rose 	{ PCI_VENDOR_ID_INTEL, PCI_ANY_ID, PCI_SUBVENDOR_ID_DELL, PCI_ANY_ID,
4689c54cd10SCharles Rose 	  PCI_CLASS_STORAGE_RAID << 8, 0xffffff, board_ahci },
4699c54cd10SCharles Rose 
470c6fd2807SJeff Garzik 	/* VIA */
47154bb3a94SJeff Garzik 	{ PCI_VDEVICE(VIA, 0x3349), board_ahci_vt8251 }, /* VIA VT8251 */
472bf335542STejun Heo 	{ PCI_VDEVICE(VIA, 0x6287), board_ahci_vt8251 }, /* VIA VT8251 */
473c6fd2807SJeff Garzik 
474c6fd2807SJeff Garzik 	/* NVIDIA */
475e297d99eSTejun Heo 	{ PCI_VDEVICE(NVIDIA, 0x044c), board_ahci_mcp65 },	/* MCP65 */
476e297d99eSTejun Heo 	{ PCI_VDEVICE(NVIDIA, 0x044d), board_ahci_mcp65 },	/* MCP65 */
477e297d99eSTejun Heo 	{ PCI_VDEVICE(NVIDIA, 0x044e), board_ahci_mcp65 },	/* MCP65 */
478e297d99eSTejun Heo 	{ PCI_VDEVICE(NVIDIA, 0x044f), board_ahci_mcp65 },	/* MCP65 */
479e297d99eSTejun Heo 	{ PCI_VDEVICE(NVIDIA, 0x045c), board_ahci_mcp65 },	/* MCP65 */
480e297d99eSTejun Heo 	{ PCI_VDEVICE(NVIDIA, 0x045d), board_ahci_mcp65 },	/* MCP65 */
481e297d99eSTejun Heo 	{ PCI_VDEVICE(NVIDIA, 0x045e), board_ahci_mcp65 },	/* MCP65 */
482e297d99eSTejun Heo 	{ PCI_VDEVICE(NVIDIA, 0x045f), board_ahci_mcp65 },	/* MCP65 */
483441577efSTejun Heo 	{ PCI_VDEVICE(NVIDIA, 0x0550), board_ahci_mcp67 },	/* MCP67 */
484441577efSTejun Heo 	{ PCI_VDEVICE(NVIDIA, 0x0551), board_ahci_mcp67 },	/* MCP67 */
485441577efSTejun Heo 	{ PCI_VDEVICE(NVIDIA, 0x0552), board_ahci_mcp67 },	/* MCP67 */
486441577efSTejun Heo 	{ PCI_VDEVICE(NVIDIA, 0x0553), board_ahci_mcp67 },	/* MCP67 */
487441577efSTejun Heo 	{ PCI_VDEVICE(NVIDIA, 0x0554), board_ahci_mcp67 },	/* MCP67 */
488441577efSTejun Heo 	{ PCI_VDEVICE(NVIDIA, 0x0555), board_ahci_mcp67 },	/* MCP67 */
489441577efSTejun Heo 	{ PCI_VDEVICE(NVIDIA, 0x0556), board_ahci_mcp67 },	/* MCP67 */
490441577efSTejun Heo 	{ PCI_VDEVICE(NVIDIA, 0x0557), board_ahci_mcp67 },	/* MCP67 */
491441577efSTejun Heo 	{ PCI_VDEVICE(NVIDIA, 0x0558), board_ahci_mcp67 },	/* MCP67 */
492441577efSTejun Heo 	{ PCI_VDEVICE(NVIDIA, 0x0559), board_ahci_mcp67 },	/* MCP67 */
493441577efSTejun Heo 	{ PCI_VDEVICE(NVIDIA, 0x055a), board_ahci_mcp67 },	/* MCP67 */
494441577efSTejun Heo 	{ PCI_VDEVICE(NVIDIA, 0x055b), board_ahci_mcp67 },	/* MCP67 */
495441577efSTejun Heo 	{ PCI_VDEVICE(NVIDIA, 0x0580), board_ahci_mcp_linux },	/* Linux ID */
496441577efSTejun Heo 	{ PCI_VDEVICE(NVIDIA, 0x0581), board_ahci_mcp_linux },	/* Linux ID */
497441577efSTejun Heo 	{ PCI_VDEVICE(NVIDIA, 0x0582), board_ahci_mcp_linux },	/* Linux ID */
498441577efSTejun Heo 	{ PCI_VDEVICE(NVIDIA, 0x0583), board_ahci_mcp_linux },	/* Linux ID */
499441577efSTejun Heo 	{ PCI_VDEVICE(NVIDIA, 0x0584), board_ahci_mcp_linux },	/* Linux ID */
500441577efSTejun Heo 	{ PCI_VDEVICE(NVIDIA, 0x0585), board_ahci_mcp_linux },	/* Linux ID */
501441577efSTejun Heo 	{ PCI_VDEVICE(NVIDIA, 0x0586), board_ahci_mcp_linux },	/* Linux ID */
502441577efSTejun Heo 	{ PCI_VDEVICE(NVIDIA, 0x0587), board_ahci_mcp_linux },	/* Linux ID */
503441577efSTejun Heo 	{ PCI_VDEVICE(NVIDIA, 0x0588), board_ahci_mcp_linux },	/* Linux ID */
504441577efSTejun Heo 	{ PCI_VDEVICE(NVIDIA, 0x0589), board_ahci_mcp_linux },	/* Linux ID */
505441577efSTejun Heo 	{ PCI_VDEVICE(NVIDIA, 0x058a), board_ahci_mcp_linux },	/* Linux ID */
506441577efSTejun Heo 	{ PCI_VDEVICE(NVIDIA, 0x058b), board_ahci_mcp_linux },	/* Linux ID */
507441577efSTejun Heo 	{ PCI_VDEVICE(NVIDIA, 0x058c), board_ahci_mcp_linux },	/* Linux ID */
508441577efSTejun Heo 	{ PCI_VDEVICE(NVIDIA, 0x058d), board_ahci_mcp_linux },	/* Linux ID */
509441577efSTejun Heo 	{ PCI_VDEVICE(NVIDIA, 0x058e), board_ahci_mcp_linux },	/* Linux ID */
510441577efSTejun Heo 	{ PCI_VDEVICE(NVIDIA, 0x058f), board_ahci_mcp_linux },	/* Linux ID */
511441577efSTejun Heo 	{ PCI_VDEVICE(NVIDIA, 0x07f0), board_ahci_mcp73 },	/* MCP73 */
512441577efSTejun Heo 	{ PCI_VDEVICE(NVIDIA, 0x07f1), board_ahci_mcp73 },	/* MCP73 */
513441577efSTejun Heo 	{ PCI_VDEVICE(NVIDIA, 0x07f2), board_ahci_mcp73 },	/* MCP73 */
514441577efSTejun Heo 	{ PCI_VDEVICE(NVIDIA, 0x07f3), board_ahci_mcp73 },	/* MCP73 */
515441577efSTejun Heo 	{ PCI_VDEVICE(NVIDIA, 0x07f4), board_ahci_mcp73 },	/* MCP73 */
516441577efSTejun Heo 	{ PCI_VDEVICE(NVIDIA, 0x07f5), board_ahci_mcp73 },	/* MCP73 */
517441577efSTejun Heo 	{ PCI_VDEVICE(NVIDIA, 0x07f6), board_ahci_mcp73 },	/* MCP73 */
518441577efSTejun Heo 	{ PCI_VDEVICE(NVIDIA, 0x07f7), board_ahci_mcp73 },	/* MCP73 */
519441577efSTejun Heo 	{ PCI_VDEVICE(NVIDIA, 0x07f8), board_ahci_mcp73 },	/* MCP73 */
520441577efSTejun Heo 	{ PCI_VDEVICE(NVIDIA, 0x07f9), board_ahci_mcp73 },	/* MCP73 */
521441577efSTejun Heo 	{ PCI_VDEVICE(NVIDIA, 0x07fa), board_ahci_mcp73 },	/* MCP73 */
522441577efSTejun Heo 	{ PCI_VDEVICE(NVIDIA, 0x07fb), board_ahci_mcp73 },	/* MCP73 */
523441577efSTejun Heo 	{ PCI_VDEVICE(NVIDIA, 0x0ad0), board_ahci_mcp77 },	/* MCP77 */
524441577efSTejun Heo 	{ PCI_VDEVICE(NVIDIA, 0x0ad1), board_ahci_mcp77 },	/* MCP77 */
525441577efSTejun Heo 	{ PCI_VDEVICE(NVIDIA, 0x0ad2), board_ahci_mcp77 },	/* MCP77 */
526441577efSTejun Heo 	{ PCI_VDEVICE(NVIDIA, 0x0ad3), board_ahci_mcp77 },	/* MCP77 */
527441577efSTejun Heo 	{ PCI_VDEVICE(NVIDIA, 0x0ad4), board_ahci_mcp77 },	/* MCP77 */
528441577efSTejun Heo 	{ PCI_VDEVICE(NVIDIA, 0x0ad5), board_ahci_mcp77 },	/* MCP77 */
529441577efSTejun Heo 	{ PCI_VDEVICE(NVIDIA, 0x0ad6), board_ahci_mcp77 },	/* MCP77 */
530441577efSTejun Heo 	{ PCI_VDEVICE(NVIDIA, 0x0ad7), board_ahci_mcp77 },	/* MCP77 */
531441577efSTejun Heo 	{ PCI_VDEVICE(NVIDIA, 0x0ad8), board_ahci_mcp77 },	/* MCP77 */
532441577efSTejun Heo 	{ PCI_VDEVICE(NVIDIA, 0x0ad9), board_ahci_mcp77 },	/* MCP77 */
533441577efSTejun Heo 	{ PCI_VDEVICE(NVIDIA, 0x0ada), board_ahci_mcp77 },	/* MCP77 */
534441577efSTejun Heo 	{ PCI_VDEVICE(NVIDIA, 0x0adb), board_ahci_mcp77 },	/* MCP77 */
535441577efSTejun Heo 	{ PCI_VDEVICE(NVIDIA, 0x0ab4), board_ahci_mcp79 },	/* MCP79 */
536441577efSTejun Heo 	{ PCI_VDEVICE(NVIDIA, 0x0ab5), board_ahci_mcp79 },	/* MCP79 */
537441577efSTejun Heo 	{ PCI_VDEVICE(NVIDIA, 0x0ab6), board_ahci_mcp79 },	/* MCP79 */
538441577efSTejun Heo 	{ PCI_VDEVICE(NVIDIA, 0x0ab7), board_ahci_mcp79 },	/* MCP79 */
539441577efSTejun Heo 	{ PCI_VDEVICE(NVIDIA, 0x0ab8), board_ahci_mcp79 },	/* MCP79 */
540441577efSTejun Heo 	{ PCI_VDEVICE(NVIDIA, 0x0ab9), board_ahci_mcp79 },	/* MCP79 */
541441577efSTejun Heo 	{ PCI_VDEVICE(NVIDIA, 0x0aba), board_ahci_mcp79 },	/* MCP79 */
542441577efSTejun Heo 	{ PCI_VDEVICE(NVIDIA, 0x0abb), board_ahci_mcp79 },	/* MCP79 */
543441577efSTejun Heo 	{ PCI_VDEVICE(NVIDIA, 0x0abc), board_ahci_mcp79 },	/* MCP79 */
544441577efSTejun Heo 	{ PCI_VDEVICE(NVIDIA, 0x0abd), board_ahci_mcp79 },	/* MCP79 */
545441577efSTejun Heo 	{ PCI_VDEVICE(NVIDIA, 0x0abe), board_ahci_mcp79 },	/* MCP79 */
546441577efSTejun Heo 	{ PCI_VDEVICE(NVIDIA, 0x0abf), board_ahci_mcp79 },	/* MCP79 */
547441577efSTejun Heo 	{ PCI_VDEVICE(NVIDIA, 0x0d84), board_ahci_mcp89 },	/* MCP89 */
548441577efSTejun Heo 	{ PCI_VDEVICE(NVIDIA, 0x0d85), board_ahci_mcp89 },	/* MCP89 */
549441577efSTejun Heo 	{ PCI_VDEVICE(NVIDIA, 0x0d86), board_ahci_mcp89 },	/* MCP89 */
550441577efSTejun Heo 	{ PCI_VDEVICE(NVIDIA, 0x0d87), board_ahci_mcp89 },	/* MCP89 */
551441577efSTejun Heo 	{ PCI_VDEVICE(NVIDIA, 0x0d88), board_ahci_mcp89 },	/* MCP89 */
552441577efSTejun Heo 	{ PCI_VDEVICE(NVIDIA, 0x0d89), board_ahci_mcp89 },	/* MCP89 */
553441577efSTejun Heo 	{ PCI_VDEVICE(NVIDIA, 0x0d8a), board_ahci_mcp89 },	/* MCP89 */
554441577efSTejun Heo 	{ PCI_VDEVICE(NVIDIA, 0x0d8b), board_ahci_mcp89 },	/* MCP89 */
555441577efSTejun Heo 	{ PCI_VDEVICE(NVIDIA, 0x0d8c), board_ahci_mcp89 },	/* MCP89 */
556441577efSTejun Heo 	{ PCI_VDEVICE(NVIDIA, 0x0d8d), board_ahci_mcp89 },	/* MCP89 */
557441577efSTejun Heo 	{ PCI_VDEVICE(NVIDIA, 0x0d8e), board_ahci_mcp89 },	/* MCP89 */
558441577efSTejun Heo 	{ PCI_VDEVICE(NVIDIA, 0x0d8f), board_ahci_mcp89 },	/* MCP89 */
559c6fd2807SJeff Garzik 
560c6fd2807SJeff Garzik 	/* SiS */
56120e2de4aSTejun Heo 	{ PCI_VDEVICE(SI, 0x1184), board_ahci },		/* SiS 966 */
56220e2de4aSTejun Heo 	{ PCI_VDEVICE(SI, 0x1185), board_ahci },		/* SiS 968 */
56320e2de4aSTejun Heo 	{ PCI_VDEVICE(SI, 0x0186), board_ahci },		/* SiS 968 */
564c6fd2807SJeff Garzik 
565318893e1SAlessandro Rubini 	/* ST Microelectronics */
566318893e1SAlessandro Rubini 	{ PCI_VDEVICE(STMICRO, 0xCC06), board_ahci },		/* ST ConneXt */
567318893e1SAlessandro Rubini 
568cd70c266SJeff Garzik 	/* Marvell */
569cd70c266SJeff Garzik 	{ PCI_VDEVICE(MARVELL, 0x6145), board_ahci_mv },	/* 6145 */
570c40e7cb8SJose Alberto Reguero 	{ PCI_VDEVICE(MARVELL, 0x6121), board_ahci_mv },	/* 6121 */
57169fd3157SMyron Stowe 	{ PCI_DEVICE(PCI_VENDOR_ID_MARVELL_EXT, 0x9123),
57210aca06cSAnssi Hannula 	  .class = PCI_CLASS_STORAGE_SATA_AHCI,
57310aca06cSAnssi Hannula 	  .class_mask = 0xffffff,
5745f173107STejun Heo 	  .driver_data = board_ahci_yes_fbs },			/* 88se9128 */
57569fd3157SMyron Stowe 	{ PCI_DEVICE(PCI_VENDOR_ID_MARVELL_EXT, 0x9125),
576467b41c6SPer Jessen 	  .driver_data = board_ahci_yes_fbs },			/* 88se9125 */
577e098f5cbSSimon Guinot 	{ PCI_DEVICE_SUB(PCI_VENDOR_ID_MARVELL_EXT, 0x9178,
578e098f5cbSSimon Guinot 			 PCI_VENDOR_ID_MARVELL_EXT, 0x9170),
579e098f5cbSSimon Guinot 	  .driver_data = board_ahci_yes_fbs },			/* 88se9170 */
58069fd3157SMyron Stowe 	{ PCI_DEVICE(PCI_VENDOR_ID_MARVELL_EXT, 0x917a),
581642d8925SMatt Johnson 	  .driver_data = board_ahci_yes_fbs },			/* 88se9172 */
582fcce9a35SGeorge Spelvin 	{ PCI_DEVICE(PCI_VENDOR_ID_MARVELL_EXT, 0x9172),
583c5edfff9SMurali Karicheri 	  .driver_data = board_ahci_yes_fbs },			/* 88se9182 */
584c5edfff9SMurali Karicheri 	{ PCI_DEVICE(PCI_VENDOR_ID_MARVELL_EXT, 0x9182),
585fcce9a35SGeorge Spelvin 	  .driver_data = board_ahci_yes_fbs },			/* 88se9172 */
58669fd3157SMyron Stowe 	{ PCI_DEVICE(PCI_VENDOR_ID_MARVELL_EXT, 0x9192),
58717c60c6bSAlan Cox 	  .driver_data = board_ahci_yes_fbs },			/* 88se9172 on some Gigabyte */
588754a292fSAndreas Schrägle 	{ PCI_DEVICE(PCI_VENDOR_ID_MARVELL_EXT, 0x91a0),
589754a292fSAndreas Schrägle 	  .driver_data = board_ahci_yes_fbs },
590a40cf3f3SJohannes Thumshirn 	{ PCI_DEVICE(PCI_VENDOR_ID_MARVELL_EXT, 0x91a2), 	/* 88se91a2 */
591a40cf3f3SJohannes Thumshirn 	  .driver_data = board_ahci_yes_fbs },
59269fd3157SMyron Stowe 	{ PCI_DEVICE(PCI_VENDOR_ID_MARVELL_EXT, 0x91a3),
59350be5e36STejun Heo 	  .driver_data = board_ahci_yes_fbs },
5946d5278a6SSamir Benmendil 	{ PCI_DEVICE(PCI_VENDOR_ID_MARVELL_EXT, 0x9230),
5956d5278a6SSamir Benmendil 	  .driver_data = board_ahci_yes_fbs },
596f4a8d4f2SPaul Menzel 	{ PCI_DEVICE(PCI_VENDOR_ID_MARVELL_EXT, 0x9235),
597f4a8d4f2SPaul Menzel 	  .driver_data = board_ahci_no_debounce_delay },
59828b2182dSHans de Goede 	{ PCI_DEVICE(PCI_VENDOR_ID_TTI, 0x0642), /* highpoint rocketraid 642L */
59928b2182dSHans de Goede 	  .driver_data = board_ahci_yes_fbs },
60028b2182dSHans de Goede 	{ PCI_DEVICE(PCI_VENDOR_ID_TTI, 0x0645), /* highpoint rocketraid 644L */
601d2518365SJérôme Carretero 	  .driver_data = board_ahci_yes_fbs },
602cd70c266SJeff Garzik 
603c77a036bSMark Nelson 	/* Promise */
604c77a036bSMark Nelson 	{ PCI_VDEVICE(PROMISE, 0x3f20), board_ahci },	/* PDC42819 */
605b32bfc06SRomain Degez 	{ PCI_VDEVICE(PROMISE, 0x3781), board_ahci },   /* FastTrak TX8660 ahci-mode */
606c77a036bSMark Nelson 
607b0dd4d7aSLennert Buytenhek 	/* ASMedia */
608f6e4aca0SLennert Buytenhek 	{ PCI_VDEVICE(ASMEDIA, 0x0601), board_ahci_43bit_dma },	/* ASM1060 */
609f6e4aca0SLennert Buytenhek 	{ PCI_VDEVICE(ASMEDIA, 0x0602), board_ahci_43bit_dma },	/* ASM1060 */
610b0dd4d7aSLennert Buytenhek 	{ PCI_VDEVICE(ASMEDIA, 0x0611), board_ahci_43bit_dma },	/* ASM1061 */
611b0dd4d7aSLennert Buytenhek 	{ PCI_VDEVICE(ASMEDIA, 0x0612), board_ahci_43bit_dma },	/* ASM1061/1062 */
612f6e4aca0SLennert Buytenhek 	{ PCI_VDEVICE(ASMEDIA, 0x0621), board_ahci_43bit_dma },	/* ASM1061R */
613f6e4aca0SLennert Buytenhek 	{ PCI_VDEVICE(ASMEDIA, 0x0622), board_ahci_43bit_dma },	/* ASM1062R */
614f6e4aca0SLennert Buytenhek 	{ PCI_VDEVICE(ASMEDIA, 0x0624), board_ahci_43bit_dma },	/* ASM1062+JMB575 */
6151f9b7a5dSSzuying Chen 	{ PCI_VDEVICE(ASMEDIA, 0x1062), board_ahci },	/* ASM1062A */
6161f9b7a5dSSzuying Chen 	{ PCI_VDEVICE(ASMEDIA, 0x1064), board_ahci },	/* ASM1064 */
6171f9b7a5dSSzuying Chen 	{ PCI_VDEVICE(ASMEDIA, 0x1164), board_ahci },   /* ASM1164 */
6181f9b7a5dSSzuying Chen 	{ PCI_VDEVICE(ASMEDIA, 0x1165), board_ahci },   /* ASM1165 */
6191f9b7a5dSSzuying Chen 	{ PCI_VDEVICE(ASMEDIA, 0x1166), board_ahci },   /* ASM1166 */
620c9703765SKeng-Yu Lin 
62167809f85SLevente Kurusa 	/*
62266a7cbc3STejun Heo 	 * Samsung SSDs found on some macbooks.  NCQ times out if MSI is
62366a7cbc3STejun Heo 	 * enabled.  https://bugzilla.kernel.org/show_bug.cgi?id=60731
62467809f85SLevente Kurusa 	 */
62566a7cbc3STejun Heo 	{ PCI_VDEVICE(SAMSUNG, 0x1600), board_ahci_nomsi },
6262b21ef0aSTejun Heo 	{ PCI_VDEVICE(SAMSUNG, 0xa800), board_ahci_nomsi },
62767809f85SLevente Kurusa 
6287f9c9f8eSHugh Daschbach 	/* Enmotus */
6297f9c9f8eSHugh Daschbach 	{ PCI_DEVICE(0x1c44, 0x8000), board_ahci },
6307f9c9f8eSHugh Daschbach 
631e49bd683STiezhu Yang 	/* Loongson */
632e49bd683STiezhu Yang 	{ PCI_VDEVICE(LOONGSON, 0x7a08), board_ahci },
633e49bd683STiezhu Yang 
634415ae2b5SJeff Garzik 	/* Generic, PCI class code for AHCI */
635415ae2b5SJeff Garzik 	{ PCI_ANY_ID, PCI_ANY_ID, PCI_ANY_ID, PCI_ANY_ID,
636c9f89475SConke Hu 	  PCI_CLASS_STORAGE_SATA_AHCI, 0xffffff, board_ahci },
637415ae2b5SJeff Garzik 
638c6fd2807SJeff Garzik 	{ }	/* terminate list */
639c6fd2807SJeff Garzik };
640c6fd2807SJeff Garzik 
641f1d848f9SMika Westerberg static const struct dev_pm_ops ahci_pci_pm_ops = {
642f1d848f9SMika Westerberg 	SET_SYSTEM_SLEEP_PM_OPS(ahci_pci_device_suspend, ahci_pci_device_resume)
64302e53293SMika Westerberg 	SET_RUNTIME_PM_OPS(ahci_pci_device_runtime_suspend,
64402e53293SMika Westerberg 			   ahci_pci_device_runtime_resume, NULL)
645f1d848f9SMika Westerberg };
646c6fd2807SJeff Garzik 
647c6fd2807SJeff Garzik static struct pci_driver ahci_pci_driver = {
648c6fd2807SJeff Garzik 	.name			= DRV_NAME,
649c6fd2807SJeff Garzik 	.id_table		= ahci_pci_tbl,
650c6fd2807SJeff Garzik 	.probe			= ahci_init_one,
65102e53293SMika Westerberg 	.remove			= ahci_remove_one,
65210a663a1SPrabhakar Kushwaha 	.shutdown		= ahci_shutdown_one,
653f1d848f9SMika Westerberg 	.driver = {
654f1d848f9SMika Westerberg 		.pm		= &ahci_pci_pm_ops,
655f1d848f9SMika Westerberg 	},
656c6fd2807SJeff Garzik };
657c6fd2807SJeff Garzik 
6585219d653SJavier Martinez Canillas #if IS_ENABLED(CONFIG_PATA_MARVELL)
6595b66c829SAlan Cox static int marvell_enable;
6605b66c829SAlan Cox #else
6615b66c829SAlan Cox static int marvell_enable = 1;
6625b66c829SAlan Cox #endif
6635b66c829SAlan Cox module_param(marvell_enable, int, 0644);
6645b66c829SAlan Cox MODULE_PARM_DESC(marvell_enable, "Marvell SATA via AHCI (1 = enabled)");
6655b66c829SAlan Cox 
666b1a9585cSSrinivas Pandruvada static int mobile_lpm_policy = -1;
667ebb82e3cSHans de Goede module_param(mobile_lpm_policy, int, 0644);
668ebb82e3cSHans de Goede MODULE_PARM_DESC(mobile_lpm_policy, "Default LPM policy for mobile chipsets");
6695b66c829SAlan Cox 
670394d6e53SAnton Vorontsov static void ahci_pci_save_initial_config(struct pci_dev *pdev,
671394d6e53SAnton Vorontsov 					 struct ahci_host_priv *hpriv)
672394d6e53SAnton Vorontsov {
673394d6e53SAnton Vorontsov 	if (pdev->vendor == PCI_VENDOR_ID_JMICRON && pdev->device == 0x2361) {
674394d6e53SAnton Vorontsov 		dev_info(&pdev->dev, "JMB361 has only one port\n");
67588589772SSerge Semin 		hpriv->saved_port_map = 1;
676394d6e53SAnton Vorontsov 	}
677394d6e53SAnton Vorontsov 
678394d6e53SAnton Vorontsov 	/*
679394d6e53SAnton Vorontsov 	 * Temporary Marvell 6145 hack: PATA port presence
680394d6e53SAnton Vorontsov 	 * is asserted through the standard AHCI port
681394d6e53SAnton Vorontsov 	 * presence register, as bit 4 (counting from 0)
682394d6e53SAnton Vorontsov 	 */
683394d6e53SAnton Vorontsov 	if (hpriv->flags & AHCI_HFLAG_MV_PATA) {
684394d6e53SAnton Vorontsov 		if (pdev->device == 0x6121)
6859a23c1d6SAntoine Tenart 			hpriv->mask_port_map = 0x3;
686394d6e53SAnton Vorontsov 		else
6879a23c1d6SAntoine Tenart 			hpriv->mask_port_map = 0xf;
688394d6e53SAnton Vorontsov 		dev_info(&pdev->dev,
689394d6e53SAnton Vorontsov 			  "Disabling your PATA port. Use the boot option 'ahci.marvell_enable=0' to avoid this.\n");
690394d6e53SAnton Vorontsov 	}
691394d6e53SAnton Vorontsov 
692725c7b57SAntoine Ténart 	ahci_save_initial_config(&pdev->dev, hpriv);
693394d6e53SAnton Vorontsov }
694394d6e53SAnton Vorontsov 
69537e14e4fSAdam Vodopjan static int ahci_pci_reset_controller(struct ata_host *host)
69637e14e4fSAdam Vodopjan {
69737e14e4fSAdam Vodopjan 	struct pci_dev *pdev = to_pci_dev(host->dev);
69837e14e4fSAdam Vodopjan 	struct ahci_host_priv *hpriv = host->private_data;
69937e14e4fSAdam Vodopjan 	int rc;
70037e14e4fSAdam Vodopjan 
70137e14e4fSAdam Vodopjan 	rc = ahci_reset_controller(host);
70237e14e4fSAdam Vodopjan 	if (rc)
70337e14e4fSAdam Vodopjan 		return rc;
70437e14e4fSAdam Vodopjan 
70537e14e4fSAdam Vodopjan 	/*
70637e14e4fSAdam Vodopjan 	 * If platform firmware failed to enable ports, try to enable
70737e14e4fSAdam Vodopjan 	 * them here.
70837e14e4fSAdam Vodopjan 	 */
70937e14e4fSAdam Vodopjan 	ahci_intel_pcs_quirk(pdev, hpriv);
71037e14e4fSAdam Vodopjan 
71137e14e4fSAdam Vodopjan 	return 0;
71237e14e4fSAdam Vodopjan }
71337e14e4fSAdam Vodopjan 
714781d6550SAnton Vorontsov static void ahci_pci_init_controller(struct ata_host *host)
715781d6550SAnton Vorontsov {
716781d6550SAnton Vorontsov 	struct ahci_host_priv *hpriv = host->private_data;
717781d6550SAnton Vorontsov 	struct pci_dev *pdev = to_pci_dev(host->dev);
718781d6550SAnton Vorontsov 	void __iomem *port_mmio;
719781d6550SAnton Vorontsov 	u32 tmp;
720c40e7cb8SJose Alberto Reguero 	int mv;
7212bcd866bSJeff Garzik 
722417a1a6dSTejun Heo 	if (hpriv->flags & AHCI_HFLAG_MV_PATA) {
723c40e7cb8SJose Alberto Reguero 		if (pdev->device == 0x6121)
724c40e7cb8SJose Alberto Reguero 			mv = 2;
725c40e7cb8SJose Alberto Reguero 		else
726c40e7cb8SJose Alberto Reguero 			mv = 4;
7277cbbfbe0SSerge Semin 		port_mmio = __ahci_port_base(hpriv, mv);
728cd70c266SJeff Garzik 
729cd70c266SJeff Garzik 		writel(0, port_mmio + PORT_IRQ_MASK);
730cd70c266SJeff Garzik 
731cd70c266SJeff Garzik 		/* clear port IRQ */
732cd70c266SJeff Garzik 		tmp = readl(port_mmio + PORT_IRQ_STAT);
73393c77114SHannes Reinecke 		dev_dbg(&pdev->dev, "PORT_IRQ_STAT 0x%x\n", tmp);
734cd70c266SJeff Garzik 		if (tmp)
735cd70c266SJeff Garzik 			writel(tmp, port_mmio + PORT_IRQ_STAT);
736cd70c266SJeff Garzik 	}
737cd70c266SJeff Garzik 
738781d6550SAnton Vorontsov 	ahci_init_controller(host);
739c6fd2807SJeff Garzik }
740c6fd2807SJeff Garzik 
741cc0680a5STejun Heo static int ahci_vt8251_hardreset(struct ata_link *link, unsigned int *class,
742d4b2bab4STejun Heo 				 unsigned long deadline)
743ad616ffbSTejun Heo {
744cc0680a5STejun Heo 	struct ata_port *ap = link->ap;
745039ece38SHans de Goede 	struct ahci_host_priv *hpriv = ap->host->private_data;
7469dadd45bSTejun Heo 	bool online;
747ad616ffbSTejun Heo 	int rc;
748ad616ffbSTejun Heo 
749fa89f53bSEvan Wang 	hpriv->stop_engine(ap);
750ad616ffbSTejun Heo 
751cc0680a5STejun Heo 	rc = sata_link_hardreset(link, sata_ehc_deb_timing(&link->eh_context),
7529dadd45bSTejun Heo 				 deadline, &online, NULL);
753ad616ffbSTejun Heo 
754039ece38SHans de Goede 	hpriv->start_engine(ap);
755ad616ffbSTejun Heo 
756ad616ffbSTejun Heo 	/* vt8251 doesn't clear BSY on signature FIS reception,
757ad616ffbSTejun Heo 	 * request follow-up softreset.
758ad616ffbSTejun Heo 	 */
7599dadd45bSTejun Heo 	return online ? -EAGAIN : rc;
760ad616ffbSTejun Heo }
761ad616ffbSTejun Heo 
762edc93052STejun Heo static int ahci_p5wdh_hardreset(struct ata_link *link, unsigned int *class,
763edc93052STejun Heo 				unsigned long deadline)
764edc93052STejun Heo {
765edc93052STejun Heo 	struct ata_port *ap = link->ap;
766edc93052STejun Heo 	struct ahci_port_priv *pp = ap->private_data;
767039ece38SHans de Goede 	struct ahci_host_priv *hpriv = ap->host->private_data;
768edc93052STejun Heo 	u8 *d2h_fis = pp->rx_fis + RX_FIS_D2H_REG;
769edc93052STejun Heo 	struct ata_taskfile tf;
7709dadd45bSTejun Heo 	bool online;
771edc93052STejun Heo 	int rc;
772edc93052STejun Heo 
773fa89f53bSEvan Wang 	hpriv->stop_engine(ap);
774edc93052STejun Heo 
775edc93052STejun Heo 	/* clear D2H reception area to properly wait for D2H FIS */
776edc93052STejun Heo 	ata_tf_init(link->device, &tf);
777efcef265SSergey Shtylyov 	tf.status = ATA_BUSY;
778edc93052STejun Heo 	ata_tf_to_fis(&tf, 0, 0, d2h_fis);
779edc93052STejun Heo 
780edc93052STejun Heo 	rc = sata_link_hardreset(link, sata_ehc_deb_timing(&link->eh_context),
7819dadd45bSTejun Heo 				 deadline, &online, NULL);
782edc93052STejun Heo 
783039ece38SHans de Goede 	hpriv->start_engine(ap);
784edc93052STejun Heo 
785edc93052STejun Heo 	/* The pseudo configuration device on SIMG4726 attached to
786edc93052STejun Heo 	 * ASUS P5W-DH Deluxe doesn't send signature FIS after
787edc93052STejun Heo 	 * hardreset if no device is attached to the first downstream
788edc93052STejun Heo 	 * port && the pseudo device locks up on SRST w/ PMP==0.  To
789edc93052STejun Heo 	 * work around this, wait for !BSY only briefly.  If BSY isn't
790edc93052STejun Heo 	 * cleared, perform CLO and proceed to IDENTIFY (achieved by
791edc93052STejun Heo 	 * ATA_LFLAG_NO_SRST and ATA_LFLAG_ASSUME_ATA).
792edc93052STejun Heo 	 *
793edc93052STejun Heo 	 * Wait for two seconds.  Devices attached to downstream port
794edc93052STejun Heo 	 * which can't process the following IDENTIFY after this will
795edc93052STejun Heo 	 * have to be reset again.  For most cases, this should
796edc93052STejun Heo 	 * suffice while making probing snappish enough.
797edc93052STejun Heo 	 */
7989dadd45bSTejun Heo 	if (online) {
7999dadd45bSTejun Heo 		rc = ata_wait_after_reset(link, jiffies + 2 * HZ,
8009dadd45bSTejun Heo 					  ahci_check_ready);
801edc93052STejun Heo 		if (rc)
80278d5ae39SShane Huang 			ahci_kick_engine(ap);
8039dadd45bSTejun Heo 	}
8049dadd45bSTejun Heo 	return rc;
805edc93052STejun Heo }
806edc93052STejun Heo 
807dbfe8ef5SDan Williams /*
808dbfe8ef5SDan Williams  * ahci_avn_hardreset - attempt more aggressive recovery of Avoton ports.
809dbfe8ef5SDan Williams  *
810dbfe8ef5SDan Williams  * It has been observed with some SSDs that the timing of events in the
811dbfe8ef5SDan Williams  * link synchronization phase can leave the port in a state that can not
812dbfe8ef5SDan Williams  * be recovered by a SATA-hard-reset alone.  The failing signature is
813dbfe8ef5SDan Williams  * SStatus.DET stuck at 1 ("Device presence detected but Phy
814dbfe8ef5SDan Williams  * communication not established").  It was found that unloading and
815dbfe8ef5SDan Williams  * reloading the driver when this problem occurs allows the drive
816dbfe8ef5SDan Williams  * connection to be recovered (DET advanced to 0x3).  The critical
817dbfe8ef5SDan Williams  * component of reloading the driver is that the port state machines are
818dbfe8ef5SDan Williams  * reset by bouncing "port enable" in the AHCI PCS configuration
819dbfe8ef5SDan Williams  * register.  So, reproduce that effect by bouncing a port whenever we
820dbfe8ef5SDan Williams  * see DET==1 after a reset.
821dbfe8ef5SDan Williams  */
822dbfe8ef5SDan Williams static int ahci_avn_hardreset(struct ata_link *link, unsigned int *class,
823dbfe8ef5SDan Williams 			      unsigned long deadline)
824dbfe8ef5SDan Williams {
825d14d41ccSSergey Shtylyov 	const unsigned int *timing = sata_ehc_deb_timing(&link->eh_context);
826dbfe8ef5SDan Williams 	struct ata_port *ap = link->ap;
827dbfe8ef5SDan Williams 	struct ahci_port_priv *pp = ap->private_data;
828dbfe8ef5SDan Williams 	struct ahci_host_priv *hpriv = ap->host->private_data;
829dbfe8ef5SDan Williams 	u8 *d2h_fis = pp->rx_fis + RX_FIS_D2H_REG;
830dbfe8ef5SDan Williams 	unsigned long tmo = deadline - jiffies;
831dbfe8ef5SDan Williams 	struct ata_taskfile tf;
832dbfe8ef5SDan Williams 	bool online;
833dbfe8ef5SDan Williams 	int rc, i;
834dbfe8ef5SDan Williams 
835fa89f53bSEvan Wang 	hpriv->stop_engine(ap);
836dbfe8ef5SDan Williams 
837dbfe8ef5SDan Williams 	for (i = 0; i < 2; i++) {
838dbfe8ef5SDan Williams 		u16 val;
839dbfe8ef5SDan Williams 		u32 sstatus;
840dbfe8ef5SDan Williams 		int port = ap->port_no;
841dbfe8ef5SDan Williams 		struct ata_host *host = ap->host;
842dbfe8ef5SDan Williams 		struct pci_dev *pdev = to_pci_dev(host->dev);
843dbfe8ef5SDan Williams 
844dbfe8ef5SDan Williams 		/* clear D2H reception area to properly wait for D2H FIS */
845dbfe8ef5SDan Williams 		ata_tf_init(link->device, &tf);
846efcef265SSergey Shtylyov 		tf.status = ATA_BUSY;
847dbfe8ef5SDan Williams 		ata_tf_to_fis(&tf, 0, 0, d2h_fis);
848dbfe8ef5SDan Williams 
849dbfe8ef5SDan Williams 		rc = sata_link_hardreset(link, timing, deadline, &online,
850dbfe8ef5SDan Williams 				ahci_check_ready);
851dbfe8ef5SDan Williams 
852dbfe8ef5SDan Williams 		if (sata_scr_read(link, SCR_STATUS, &sstatus) != 0 ||
853dbfe8ef5SDan Williams 				(sstatus & 0xf) != 1)
854dbfe8ef5SDan Williams 			break;
855dbfe8ef5SDan Williams 
856e276c9bdSXu Wang 		ata_link_info(link,  "avn bounce port%d\n", port);
857dbfe8ef5SDan Williams 
858dbfe8ef5SDan Williams 		pci_read_config_word(pdev, 0x92, &val);
859dbfe8ef5SDan Williams 		val &= ~(1 << port);
860dbfe8ef5SDan Williams 		pci_write_config_word(pdev, 0x92, val);
861dbfe8ef5SDan Williams 		ata_msleep(ap, 1000);
862dbfe8ef5SDan Williams 		val |= 1 << port;
863dbfe8ef5SDan Williams 		pci_write_config_word(pdev, 0x92, val);
864dbfe8ef5SDan Williams 		deadline += tmo;
865dbfe8ef5SDan Williams 	}
866dbfe8ef5SDan Williams 
867dbfe8ef5SDan Williams 	hpriv->start_engine(ap);
868dbfe8ef5SDan Williams 
869dbfe8ef5SDan Williams 	if (online)
870dbfe8ef5SDan Williams 		*class = ahci_dev_classify(ap);
871dbfe8ef5SDan Williams 
872dbfe8ef5SDan Williams 	return rc;
873dbfe8ef5SDan Williams }
874dbfe8ef5SDan Williams 
875dbfe8ef5SDan Williams 
87602e53293SMika Westerberg #ifdef CONFIG_PM
87702e53293SMika Westerberg static void ahci_pci_disable_interrupts(struct ata_host *host)
878c6fd2807SJeff Garzik {
8799b10ae86STejun Heo 	struct ahci_host_priv *hpriv = host->private_data;
880d8993349SAnton Vorontsov 	void __iomem *mmio = hpriv->mmio;
881c6fd2807SJeff Garzik 	u32 ctl;
882c6fd2807SJeff Garzik 
883c6fd2807SJeff Garzik 	/* AHCI spec rev1.1 section 8.3.3:
884c6fd2807SJeff Garzik 	 * Software must disable interrupts prior to requesting a
885c6fd2807SJeff Garzik 	 * transition of the HBA to D3 state.
886c6fd2807SJeff Garzik 	 */
887c6fd2807SJeff Garzik 	ctl = readl(mmio + HOST_CTL);
888c6fd2807SJeff Garzik 	ctl &= ~HOST_IRQ_EN;
889c6fd2807SJeff Garzik 	writel(ctl, mmio + HOST_CTL);
890c6fd2807SJeff Garzik 	readl(mmio + HOST_CTL); /* flush */
89102e53293SMika Westerberg }
892f1d848f9SMika Westerberg 
89302e53293SMika Westerberg static int ahci_pci_device_runtime_suspend(struct device *dev)
89402e53293SMika Westerberg {
89502e53293SMika Westerberg 	struct pci_dev *pdev = to_pci_dev(dev);
89602e53293SMika Westerberg 	struct ata_host *host = pci_get_drvdata(pdev);
89702e53293SMika Westerberg 
89802e53293SMika Westerberg 	ahci_pci_disable_interrupts(host);
89902e53293SMika Westerberg 	return 0;
90002e53293SMika Westerberg }
90102e53293SMika Westerberg 
90202e53293SMika Westerberg static int ahci_pci_device_runtime_resume(struct device *dev)
90302e53293SMika Westerberg {
90402e53293SMika Westerberg 	struct pci_dev *pdev = to_pci_dev(dev);
90502e53293SMika Westerberg 	struct ata_host *host = pci_get_drvdata(pdev);
90602e53293SMika Westerberg 	int rc;
90702e53293SMika Westerberg 
90837e14e4fSAdam Vodopjan 	rc = ahci_pci_reset_controller(host);
90902e53293SMika Westerberg 	if (rc)
91002e53293SMika Westerberg 		return rc;
91102e53293SMika Westerberg 	ahci_pci_init_controller(host);
91202e53293SMika Westerberg 	return 0;
91302e53293SMika Westerberg }
91402e53293SMika Westerberg 
91502e53293SMika Westerberg #ifdef CONFIG_PM_SLEEP
91602e53293SMika Westerberg static int ahci_pci_device_suspend(struct device *dev)
91702e53293SMika Westerberg {
91802e53293SMika Westerberg 	struct pci_dev *pdev = to_pci_dev(dev);
91902e53293SMika Westerberg 	struct ata_host *host = pci_get_drvdata(pdev);
92002e53293SMika Westerberg 	struct ahci_host_priv *hpriv = host->private_data;
92102e53293SMika Westerberg 
92202e53293SMika Westerberg 	if (hpriv->flags & AHCI_HFLAG_NO_SUSPEND) {
92302e53293SMika Westerberg 		dev_err(&pdev->dev,
92402e53293SMika Westerberg 			"BIOS update required for suspend/resume\n");
92502e53293SMika Westerberg 		return -EIO;
92602e53293SMika Westerberg 	}
92702e53293SMika Westerberg 
92802e53293SMika Westerberg 	ahci_pci_disable_interrupts(host);
929ec87cf37SSergey Shtylyov 	ata_host_suspend(host, PMSG_SUSPEND);
930ec87cf37SSergey Shtylyov 	return 0;
931c6fd2807SJeff Garzik }
932c6fd2807SJeff Garzik 
933f1d848f9SMika Westerberg static int ahci_pci_device_resume(struct device *dev)
934c6fd2807SJeff Garzik {
935f1d848f9SMika Westerberg 	struct pci_dev *pdev = to_pci_dev(dev);
9360a86e1c8SJingoo Han 	struct ata_host *host = pci_get_drvdata(pdev);
937c6fd2807SJeff Garzik 	int rc;
938c6fd2807SJeff Garzik 
939cb85696dSJames Laird 	/* Apple BIOS helpfully mangles the registers on resume */
940cb85696dSJames Laird 	if (is_mcp89_apple(pdev))
941cb85696dSJames Laird 		ahci_mcp89_apple_enable(pdev);
942cb85696dSJames Laird 
943c6fd2807SJeff Garzik 	if (pdev->dev.power.power_state.event == PM_EVENT_SUSPEND) {
94437e14e4fSAdam Vodopjan 		rc = ahci_pci_reset_controller(host);
945c6fd2807SJeff Garzik 		if (rc)
946c6fd2807SJeff Garzik 			return rc;
947c6fd2807SJeff Garzik 
948781d6550SAnton Vorontsov 		ahci_pci_init_controller(host);
949c6fd2807SJeff Garzik 	}
950c6fd2807SJeff Garzik 
951cca3974eSJeff Garzik 	ata_host_resume(host);
952c6fd2807SJeff Garzik 
953c6fd2807SJeff Garzik 	return 0;
954c6fd2807SJeff Garzik }
955438ac6d5STejun Heo #endif
956c6fd2807SJeff Garzik 
95702e53293SMika Westerberg #endif /* CONFIG_PM */
95802e53293SMika Westerberg 
959b0dd4d7aSLennert Buytenhek static int ahci_configure_dma_masks(struct pci_dev *pdev,
960b0dd4d7aSLennert Buytenhek 				    struct ahci_host_priv *hpriv)
961c6fd2807SJeff Garzik {
962b0dd4d7aSLennert Buytenhek 	int dma_bits;
963c6fd2807SJeff Garzik 	int rc;
964c6fd2807SJeff Garzik 
965b0dd4d7aSLennert Buytenhek 	if (hpriv->cap & HOST_CAP_64) {
966b0dd4d7aSLennert Buytenhek 		dma_bits = 64;
967b0dd4d7aSLennert Buytenhek 		if (hpriv->flags & AHCI_HFLAG_43BIT_ONLY)
968b0dd4d7aSLennert Buytenhek 			dma_bits = 43;
969b0dd4d7aSLennert Buytenhek 	} else {
970b0dd4d7aSLennert Buytenhek 		dma_bits = 32;
971b0dd4d7aSLennert Buytenhek 	}
972b0dd4d7aSLennert Buytenhek 
973318893e1SAlessandro Rubini 	/*
974318893e1SAlessandro Rubini 	 * If the device fixup already set the dma_mask to some non-standard
975318893e1SAlessandro Rubini 	 * value, don't extend it here. This happens on STA2X11, for example.
976b1716871SChristoph Hellwig 	 *
977b1716871SChristoph Hellwig 	 * XXX: manipulating the DMA mask from platform code is completely
978a7ba70f1SNicolas Saenz Julienne 	 * bogus, platform code should use dev->bus_dma_limit instead..
979318893e1SAlessandro Rubini 	 */
980318893e1SAlessandro Rubini 	if (pdev->dma_mask && pdev->dma_mask < DMA_BIT_MASK(32))
981318893e1SAlessandro Rubini 		return 0;
982318893e1SAlessandro Rubini 
983b1716871SChristoph Hellwig 	rc = dma_set_mask_and_coherent(&pdev->dev, DMA_BIT_MASK(dma_bits));
984b1716871SChristoph Hellwig 	if (rc)
985b1716871SChristoph Hellwig 		dev_err(&pdev->dev, "DMA enable failed\n");
986c6fd2807SJeff Garzik 	return rc;
987c6fd2807SJeff Garzik }
988c6fd2807SJeff Garzik 
989439fcaecSAnton Vorontsov static void ahci_pci_print_info(struct ata_host *host)
990439fcaecSAnton Vorontsov {
991439fcaecSAnton Vorontsov 	struct pci_dev *pdev = to_pci_dev(host->dev);
992439fcaecSAnton Vorontsov 	u16 cc;
993439fcaecSAnton Vorontsov 	const char *scc_s;
994439fcaecSAnton Vorontsov 
995439fcaecSAnton Vorontsov 	pci_read_config_word(pdev, 0x0a, &cc);
996439fcaecSAnton Vorontsov 	if (cc == PCI_CLASS_STORAGE_IDE)
997439fcaecSAnton Vorontsov 		scc_s = "IDE";
998439fcaecSAnton Vorontsov 	else if (cc == PCI_CLASS_STORAGE_SATA)
999439fcaecSAnton Vorontsov 		scc_s = "SATA";
1000439fcaecSAnton Vorontsov 	else if (cc == PCI_CLASS_STORAGE_RAID)
1001439fcaecSAnton Vorontsov 		scc_s = "RAID";
1002439fcaecSAnton Vorontsov 	else
1003439fcaecSAnton Vorontsov 		scc_s = "unknown";
1004439fcaecSAnton Vorontsov 
1005439fcaecSAnton Vorontsov 	ahci_print_info(host, scc_s);
1006439fcaecSAnton Vorontsov }
1007439fcaecSAnton Vorontsov 
1008edc93052STejun Heo /* On ASUS P5W DH Deluxe, the second port of PCI device 00:1f.2 is
1009edc93052STejun Heo  * hardwired to on-board SIMG 4726.  The chipset is ICH8 and doesn't
1010edc93052STejun Heo  * support PMP and the 4726 either directly exports the device
1011edc93052STejun Heo  * attached to the first downstream port or acts as a hardware storage
1012edc93052STejun Heo  * controller and emulate a single ATA device (can be RAID 0/1 or some
1013edc93052STejun Heo  * other configuration).
1014edc93052STejun Heo  *
1015edc93052STejun Heo  * When there's no device attached to the first downstream port of the
1016edc93052STejun Heo  * 4726, "Config Disk" appears, which is a pseudo ATA device to
1017edc93052STejun Heo  * configure the 4726.  However, ATA emulation of the device is very
1018edc93052STejun Heo  * lame.  It doesn't send signature D2H Reg FIS after the initial
1019edc93052STejun Heo  * hardreset, pukes on SRST w/ PMP==0 and has bunch of other issues.
1020edc93052STejun Heo  *
1021edc93052STejun Heo  * The following function works around the problem by always using
1022edc93052STejun Heo  * hardreset on the port and not depending on receiving signature FIS
1023edc93052STejun Heo  * afterward.  If signature FIS isn't received soon, ATA class is
1024edc93052STejun Heo  * assumed without follow-up softreset.
1025edc93052STejun Heo  */
1026edc93052STejun Heo static void ahci_p5wdh_workaround(struct ata_host *host)
1027edc93052STejun Heo {
10281bd06867SMathias Krause 	static const struct dmi_system_id sysids[] = {
1029edc93052STejun Heo 		{
1030edc93052STejun Heo 			.ident = "P5W DH Deluxe",
1031edc93052STejun Heo 			.matches = {
1032edc93052STejun Heo 				DMI_MATCH(DMI_SYS_VENDOR,
1033edc93052STejun Heo 					  "ASUSTEK COMPUTER INC"),
1034edc93052STejun Heo 				DMI_MATCH(DMI_PRODUCT_NAME, "P5W DH Deluxe"),
1035edc93052STejun Heo 			},
1036edc93052STejun Heo 		},
1037edc93052STejun Heo 		{ }
1038edc93052STejun Heo 	};
1039edc93052STejun Heo 	struct pci_dev *pdev = to_pci_dev(host->dev);
1040edc93052STejun Heo 
1041edc93052STejun Heo 	if (pdev->bus->number == 0 && pdev->devfn == PCI_DEVFN(0x1f, 2) &&
1042edc93052STejun Heo 	    dmi_check_system(sysids)) {
1043edc93052STejun Heo 		struct ata_port *ap = host->ports[1];
1044edc93052STejun Heo 
1045a44fec1fSJoe Perches 		dev_info(&pdev->dev,
1046a44fec1fSJoe Perches 			 "enabling ASUS P5W DH Deluxe on-board SIMG4726 workaround\n");
1047edc93052STejun Heo 
1048edc93052STejun Heo 		ap->ops = &ahci_p5wdh_ops;
1049edc93052STejun Heo 		ap->link.flags |= ATA_LFLAG_NO_SRST | ATA_LFLAG_ASSUME_ATA;
1050edc93052STejun Heo 	}
1051edc93052STejun Heo }
1052edc93052STejun Heo 
1053cb85696dSJames Laird /*
1054cb85696dSJames Laird  * Macbook7,1 firmware forcibly disables MCP89 AHCI and changes PCI ID when
1055cb85696dSJames Laird  * booting in BIOS compatibility mode.  We restore the registers but not ID.
1056cb85696dSJames Laird  */
1057cb85696dSJames Laird static void ahci_mcp89_apple_enable(struct pci_dev *pdev)
1058cb85696dSJames Laird {
1059cb85696dSJames Laird 	u32 val;
1060cb85696dSJames Laird 
1061cb85696dSJames Laird 	printk(KERN_INFO "ahci: enabling MCP89 AHCI mode\n");
1062cb85696dSJames Laird 
1063cb85696dSJames Laird 	pci_read_config_dword(pdev, 0xf8, &val);
1064cb85696dSJames Laird 	val |= 1 << 0x1b;
1065cb85696dSJames Laird 	/* the following changes the device ID, but appears not to affect function */
1066cb85696dSJames Laird 	/* val = (val & ~0xf0000000) | 0x80000000; */
1067cb85696dSJames Laird 	pci_write_config_dword(pdev, 0xf8, val);
1068cb85696dSJames Laird 
1069cb85696dSJames Laird 	pci_read_config_dword(pdev, 0x54c, &val);
1070cb85696dSJames Laird 	val |= 1 << 0xc;
1071cb85696dSJames Laird 	pci_write_config_dword(pdev, 0x54c, val);
1072cb85696dSJames Laird 
1073cb85696dSJames Laird 	pci_read_config_dword(pdev, 0x4a4, &val);
1074cb85696dSJames Laird 	val &= 0xff;
1075cb85696dSJames Laird 	val |= 0x01060100;
1076cb85696dSJames Laird 	pci_write_config_dword(pdev, 0x4a4, val);
1077cb85696dSJames Laird 
1078cb85696dSJames Laird 	pci_read_config_dword(pdev, 0x54c, &val);
1079cb85696dSJames Laird 	val &= ~(1 << 0xc);
1080cb85696dSJames Laird 	pci_write_config_dword(pdev, 0x54c, val);
1081cb85696dSJames Laird 
1082cb85696dSJames Laird 	pci_read_config_dword(pdev, 0xf8, &val);
1083cb85696dSJames Laird 	val &= ~(1 << 0x1b);
1084cb85696dSJames Laird 	pci_write_config_dword(pdev, 0xf8, val);
1085cb85696dSJames Laird }
1086cb85696dSJames Laird 
1087cb85696dSJames Laird static bool is_mcp89_apple(struct pci_dev *pdev)
1088cb85696dSJames Laird {
1089cb85696dSJames Laird 	return pdev->vendor == PCI_VENDOR_ID_NVIDIA &&
1090cb85696dSJames Laird 		pdev->device == PCI_DEVICE_ID_NVIDIA_NFORCE_MCP89_SATA &&
1091cb85696dSJames Laird 		pdev->subsystem_vendor == PCI_VENDOR_ID_APPLE &&
1092cb85696dSJames Laird 		pdev->subsystem_device == 0xcb89;
1093cb85696dSJames Laird }
1094cb85696dSJames Laird 
10952fcad9d2STejun Heo /* only some SB600 ahci controllers can do 64bit DMA */
10962fcad9d2STejun Heo static bool ahci_sb600_enable_64bit(struct pci_dev *pdev)
109758a09b38SShane Huang {
109858a09b38SShane Huang 	static const struct dmi_system_id sysids[] = {
109903d783bfSTejun Heo 		/*
110003d783bfSTejun Heo 		 * The oldest version known to be broken is 0901 and
110103d783bfSTejun Heo 		 * working is 1501 which was released on 2007-10-26.
11022fcad9d2STejun Heo 		 * Enable 64bit DMA on 1501 and anything newer.
11032fcad9d2STejun Heo 		 *
110403d783bfSTejun Heo 		 * Please read bko#9412 for more info.
110503d783bfSTejun Heo 		 */
110658a09b38SShane Huang 		{
110758a09b38SShane Huang 			.ident = "ASUS M2A-VM",
110858a09b38SShane Huang 			.matches = {
110958a09b38SShane Huang 				DMI_MATCH(DMI_BOARD_VENDOR,
111058a09b38SShane Huang 					  "ASUSTeK Computer INC."),
111158a09b38SShane Huang 				DMI_MATCH(DMI_BOARD_NAME, "M2A-VM"),
111258a09b38SShane Huang 			},
111303d783bfSTejun Heo 			.driver_data = "20071026",	/* yyyymmdd */
111458a09b38SShane Huang 		},
1115e65cc194SMark Nelson 		/*
1116e65cc194SMark Nelson 		 * All BIOS versions for the MSI K9A2 Platinum (MS-7376)
1117e65cc194SMark Nelson 		 * support 64bit DMA.
1118e65cc194SMark Nelson 		 *
1119e65cc194SMark Nelson 		 * BIOS versions earlier than 1.5 had the Manufacturer DMI
1120e65cc194SMark Nelson 		 * fields as "MICRO-STAR INTERANTIONAL CO.,LTD".
1121e65cc194SMark Nelson 		 * This spelling mistake was fixed in BIOS version 1.5, so
1122e65cc194SMark Nelson 		 * 1.5 and later have the Manufacturer as
1123e65cc194SMark Nelson 		 * "MICRO-STAR INTERNATIONAL CO.,LTD".
1124e65cc194SMark Nelson 		 * So try to match on DMI_BOARD_VENDOR of "MICRO-STAR INTER".
1125e65cc194SMark Nelson 		 *
1126e65cc194SMark Nelson 		 * BIOS versions earlier than 1.9 had a Board Product Name
1127e65cc194SMark Nelson 		 * DMI field of "MS-7376". This was changed to be
1128e65cc194SMark Nelson 		 * "K9A2 Platinum (MS-7376)" in version 1.9, but we can still
1129e65cc194SMark Nelson 		 * match on DMI_BOARD_NAME of "MS-7376".
1130e65cc194SMark Nelson 		 */
1131e65cc194SMark Nelson 		{
1132e65cc194SMark Nelson 			.ident = "MSI K9A2 Platinum",
1133e65cc194SMark Nelson 			.matches = {
1134e65cc194SMark Nelson 				DMI_MATCH(DMI_BOARD_VENDOR,
1135e65cc194SMark Nelson 					  "MICRO-STAR INTER"),
1136e65cc194SMark Nelson 				DMI_MATCH(DMI_BOARD_NAME, "MS-7376"),
1137e65cc194SMark Nelson 			},
1138e65cc194SMark Nelson 		},
11393c4aa91fSMark Nelson 		/*
1140ff0173c1SMark Nelson 		 * All BIOS versions for the MSI K9AGM2 (MS-7327) support
1141ff0173c1SMark Nelson 		 * 64bit DMA.
1142ff0173c1SMark Nelson 		 *
1143ff0173c1SMark Nelson 		 * This board also had the typo mentioned above in the
1144ff0173c1SMark Nelson 		 * Manufacturer DMI field (fixed in BIOS version 1.5), so
1145ff0173c1SMark Nelson 		 * match on DMI_BOARD_VENDOR of "MICRO-STAR INTER" again.
1146ff0173c1SMark Nelson 		 */
1147ff0173c1SMark Nelson 		{
1148ff0173c1SMark Nelson 			.ident = "MSI K9AGM2",
1149ff0173c1SMark Nelson 			.matches = {
1150ff0173c1SMark Nelson 				DMI_MATCH(DMI_BOARD_VENDOR,
1151ff0173c1SMark Nelson 					  "MICRO-STAR INTER"),
1152ff0173c1SMark Nelson 				DMI_MATCH(DMI_BOARD_NAME, "MS-7327"),
1153ff0173c1SMark Nelson 			},
1154ff0173c1SMark Nelson 		},
1155ff0173c1SMark Nelson 		/*
11563c4aa91fSMark Nelson 		 * All BIOS versions for the Asus M3A support 64bit DMA.
11573c4aa91fSMark Nelson 		 * (all release versions from 0301 to 1206 were tested)
11583c4aa91fSMark Nelson 		 */
11593c4aa91fSMark Nelson 		{
11603c4aa91fSMark Nelson 			.ident = "ASUS M3A",
11613c4aa91fSMark Nelson 			.matches = {
11623c4aa91fSMark Nelson 				DMI_MATCH(DMI_BOARD_VENDOR,
11633c4aa91fSMark Nelson 					  "ASUSTeK Computer INC."),
11643c4aa91fSMark Nelson 				DMI_MATCH(DMI_BOARD_NAME, "M3A"),
11653c4aa91fSMark Nelson 			},
11663c4aa91fSMark Nelson 		},
116758a09b38SShane Huang 		{ }
116858a09b38SShane Huang 	};
116903d783bfSTejun Heo 	const struct dmi_system_id *match;
11702fcad9d2STejun Heo 	int year, month, date;
11712fcad9d2STejun Heo 	char buf[9];
117258a09b38SShane Huang 
117303d783bfSTejun Heo 	match = dmi_first_match(sysids);
117458a09b38SShane Huang 	if (pdev->bus->number != 0 || pdev->devfn != PCI_DEVFN(0x12, 0) ||
117503d783bfSTejun Heo 	    !match)
117658a09b38SShane Huang 		return false;
117758a09b38SShane Huang 
1178e65cc194SMark Nelson 	if (!match->driver_data)
1179e65cc194SMark Nelson 		goto enable_64bit;
1180e65cc194SMark Nelson 
118103d783bfSTejun Heo 	dmi_get_date(DMI_BIOS_DATE, &year, &month, &date);
118203d783bfSTejun Heo 	snprintf(buf, sizeof(buf), "%04d%02d%02d", year, month, date);
118303d783bfSTejun Heo 
1184e65cc194SMark Nelson 	if (strcmp(buf, match->driver_data) >= 0)
1185e65cc194SMark Nelson 		goto enable_64bit;
1186e65cc194SMark Nelson 	else {
1187a44fec1fSJoe Perches 		dev_warn(&pdev->dev,
1188a44fec1fSJoe Perches 			 "%s: BIOS too old, forcing 32bit DMA, update BIOS\n",
1189a44fec1fSJoe Perches 			 match->ident);
11902fcad9d2STejun Heo 		return false;
11912fcad9d2STejun Heo 	}
1192e65cc194SMark Nelson 
1193e65cc194SMark Nelson enable_64bit:
1194a44fec1fSJoe Perches 	dev_warn(&pdev->dev, "%s: enabling 64bit DMA\n", match->ident);
1195e65cc194SMark Nelson 	return true;
119658a09b38SShane Huang }
119758a09b38SShane Huang 
11981fd68434SRafael J. Wysocki static bool ahci_broken_system_poweroff(struct pci_dev *pdev)
11991fd68434SRafael J. Wysocki {
12001fd68434SRafael J. Wysocki 	static const struct dmi_system_id broken_systems[] = {
12011fd68434SRafael J. Wysocki 		{
12021fd68434SRafael J. Wysocki 			.ident = "HP Compaq nx6310",
12031fd68434SRafael J. Wysocki 			.matches = {
12041fd68434SRafael J. Wysocki 				DMI_MATCH(DMI_SYS_VENDOR, "Hewlett-Packard"),
12051fd68434SRafael J. Wysocki 				DMI_MATCH(DMI_PRODUCT_NAME, "HP Compaq nx6310"),
12061fd68434SRafael J. Wysocki 			},
12071fd68434SRafael J. Wysocki 			/* PCI slot number of the controller */
12081fd68434SRafael J. Wysocki 			.driver_data = (void *)0x1FUL,
12091fd68434SRafael J. Wysocki 		},
1210d2f9c061SMaciej Rutecki 		{
1211d2f9c061SMaciej Rutecki 			.ident = "HP Compaq 6720s",
1212d2f9c061SMaciej Rutecki 			.matches = {
1213d2f9c061SMaciej Rutecki 				DMI_MATCH(DMI_SYS_VENDOR, "Hewlett-Packard"),
1214d2f9c061SMaciej Rutecki 				DMI_MATCH(DMI_PRODUCT_NAME, "HP Compaq 6720s"),
1215d2f9c061SMaciej Rutecki 			},
1216d2f9c061SMaciej Rutecki 			/* PCI slot number of the controller */
1217d2f9c061SMaciej Rutecki 			.driver_data = (void *)0x1FUL,
1218d2f9c061SMaciej Rutecki 		},
12191fd68434SRafael J. Wysocki 
12201fd68434SRafael J. Wysocki 		{ }	/* terminate list */
12211fd68434SRafael J. Wysocki 	};
12221fd68434SRafael J. Wysocki 	const struct dmi_system_id *dmi = dmi_first_match(broken_systems);
12231fd68434SRafael J. Wysocki 
12241fd68434SRafael J. Wysocki 	if (dmi) {
12251fd68434SRafael J. Wysocki 		unsigned long slot = (unsigned long)dmi->driver_data;
12261fd68434SRafael J. Wysocki 		/* apply the quirk only to on-board controllers */
12271fd68434SRafael J. Wysocki 		return slot == PCI_SLOT(pdev->devfn);
12281fd68434SRafael J. Wysocki 	}
12291fd68434SRafael J. Wysocki 
12301fd68434SRafael J. Wysocki 	return false;
12311fd68434SRafael J. Wysocki }
12321fd68434SRafael J. Wysocki 
12339b10ae86STejun Heo static bool ahci_broken_suspend(struct pci_dev *pdev)
12349b10ae86STejun Heo {
12359b10ae86STejun Heo 	static const struct dmi_system_id sysids[] = {
12369b10ae86STejun Heo 		/*
12379b10ae86STejun Heo 		 * On HP dv[4-6] and HDX18 with earlier BIOSen, link
12389b10ae86STejun Heo 		 * to the harddisk doesn't become online after
12399b10ae86STejun Heo 		 * resuming from STR.  Warn and fail suspend.
12409deb3431STejun Heo 		 *
12419deb3431STejun Heo 		 * http://bugzilla.kernel.org/show_bug.cgi?id=12276
12429deb3431STejun Heo 		 *
12439deb3431STejun Heo 		 * Use dates instead of versions to match as HP is
12449deb3431STejun Heo 		 * apparently recycling both product and version
12459deb3431STejun Heo 		 * strings.
12469deb3431STejun Heo 		 *
12479deb3431STejun Heo 		 * http://bugzilla.kernel.org/show_bug.cgi?id=15462
12489b10ae86STejun Heo 		 */
12499b10ae86STejun Heo 		{
12509b10ae86STejun Heo 			.ident = "dv4",
12519b10ae86STejun Heo 			.matches = {
12529b10ae86STejun Heo 				DMI_MATCH(DMI_SYS_VENDOR, "Hewlett-Packard"),
12539b10ae86STejun Heo 				DMI_MATCH(DMI_PRODUCT_NAME,
12549b10ae86STejun Heo 					  "HP Pavilion dv4 Notebook PC"),
12559b10ae86STejun Heo 			},
12569deb3431STejun Heo 			.driver_data = "20090105",	/* F.30 */
12579b10ae86STejun Heo 		},
12589b10ae86STejun Heo 		{
12599b10ae86STejun Heo 			.ident = "dv5",
12609b10ae86STejun Heo 			.matches = {
12619b10ae86STejun Heo 				DMI_MATCH(DMI_SYS_VENDOR, "Hewlett-Packard"),
12629b10ae86STejun Heo 				DMI_MATCH(DMI_PRODUCT_NAME,
12639b10ae86STejun Heo 					  "HP Pavilion dv5 Notebook PC"),
12649b10ae86STejun Heo 			},
12659deb3431STejun Heo 			.driver_data = "20090506",	/* F.16 */
12669b10ae86STejun Heo 		},
12679b10ae86STejun Heo 		{
12689b10ae86STejun Heo 			.ident = "dv6",
12699b10ae86STejun Heo 			.matches = {
12709b10ae86STejun Heo 				DMI_MATCH(DMI_SYS_VENDOR, "Hewlett-Packard"),
12719b10ae86STejun Heo 				DMI_MATCH(DMI_PRODUCT_NAME,
12729b10ae86STejun Heo 					  "HP Pavilion dv6 Notebook PC"),
12739b10ae86STejun Heo 			},
12749deb3431STejun Heo 			.driver_data = "20090423",	/* F.21 */
12759b10ae86STejun Heo 		},
12769b10ae86STejun Heo 		{
12779b10ae86STejun Heo 			.ident = "HDX18",
12789b10ae86STejun Heo 			.matches = {
12799b10ae86STejun Heo 				DMI_MATCH(DMI_SYS_VENDOR, "Hewlett-Packard"),
12809b10ae86STejun Heo 				DMI_MATCH(DMI_PRODUCT_NAME,
12819b10ae86STejun Heo 					  "HP HDX18 Notebook PC"),
12829b10ae86STejun Heo 			},
12839deb3431STejun Heo 			.driver_data = "20090430",	/* F.23 */
12849b10ae86STejun Heo 		},
1285cedc9bf9STejun Heo 		/*
1286cedc9bf9STejun Heo 		 * Acer eMachines G725 has the same problem.  BIOS
1287cedc9bf9STejun Heo 		 * V1.03 is known to be broken.  V3.04 is known to
128825985edcSLucas De Marchi 		 * work.  Between, there are V1.06, V2.06 and V3.03
1289cedc9bf9STejun Heo 		 * that we don't have much idea about.  For now,
1290cedc9bf9STejun Heo 		 * blacklist anything older than V3.04.
12919deb3431STejun Heo 		 *
12929deb3431STejun Heo 		 * http://bugzilla.kernel.org/show_bug.cgi?id=15104
1293cedc9bf9STejun Heo 		 */
1294cedc9bf9STejun Heo 		{
1295cedc9bf9STejun Heo 			.ident = "G725",
1296cedc9bf9STejun Heo 			.matches = {
1297cedc9bf9STejun Heo 				DMI_MATCH(DMI_SYS_VENDOR, "eMachines"),
1298cedc9bf9STejun Heo 				DMI_MATCH(DMI_PRODUCT_NAME, "eMachines G725"),
1299cedc9bf9STejun Heo 			},
13009deb3431STejun Heo 			.driver_data = "20091216",	/* V3.04 */
1301cedc9bf9STejun Heo 		},
13029b10ae86STejun Heo 		{ }	/* terminate list */
13039b10ae86STejun Heo 	};
13049b10ae86STejun Heo 	const struct dmi_system_id *dmi = dmi_first_match(sysids);
13059deb3431STejun Heo 	int year, month, date;
13069deb3431STejun Heo 	char buf[9];
13079b10ae86STejun Heo 
13089b10ae86STejun Heo 	if (!dmi || pdev->bus->number || pdev->devfn != PCI_DEVFN(0x1f, 2))
13099b10ae86STejun Heo 		return false;
13109b10ae86STejun Heo 
13119deb3431STejun Heo 	dmi_get_date(DMI_BIOS_DATE, &year, &month, &date);
13129deb3431STejun Heo 	snprintf(buf, sizeof(buf), "%04d%02d%02d", year, month, date);
13139b10ae86STejun Heo 
13149deb3431STejun Heo 	return strcmp(buf, dmi->driver_data) < 0;
13159b10ae86STejun Heo }
13169b10ae86STejun Heo 
1317240630e6SHans de Goede static bool ahci_broken_lpm(struct pci_dev *pdev)
1318240630e6SHans de Goede {
1319240630e6SHans de Goede 	static const struct dmi_system_id sysids[] = {
1320240630e6SHans de Goede 		/* Various Lenovo 50 series have LPM issues with older BIOSen */
1321240630e6SHans de Goede 		{
1322240630e6SHans de Goede 			.matches = {
1323240630e6SHans de Goede 				DMI_MATCH(DMI_SYS_VENDOR, "LENOVO"),
1324240630e6SHans de Goede 				DMI_MATCH(DMI_PRODUCT_VERSION, "ThinkPad X250"),
1325240630e6SHans de Goede 			},
1326240630e6SHans de Goede 			.driver_data = "20180406", /* 1.31 */
1327240630e6SHans de Goede 		},
1328240630e6SHans de Goede 		{
1329240630e6SHans de Goede 			.matches = {
1330240630e6SHans de Goede 				DMI_MATCH(DMI_SYS_VENDOR, "LENOVO"),
1331240630e6SHans de Goede 				DMI_MATCH(DMI_PRODUCT_VERSION, "ThinkPad L450"),
1332240630e6SHans de Goede 			},
1333240630e6SHans de Goede 			.driver_data = "20180420", /* 1.28 */
1334240630e6SHans de Goede 		},
1335240630e6SHans de Goede 		{
1336240630e6SHans de Goede 			.matches = {
1337240630e6SHans de Goede 				DMI_MATCH(DMI_SYS_VENDOR, "LENOVO"),
1338240630e6SHans de Goede 				DMI_MATCH(DMI_PRODUCT_VERSION, "ThinkPad T450s"),
1339240630e6SHans de Goede 			},
1340240630e6SHans de Goede 			.driver_data = "20180315", /* 1.33 */
1341240630e6SHans de Goede 		},
1342240630e6SHans de Goede 		{
1343240630e6SHans de Goede 			.matches = {
1344240630e6SHans de Goede 				DMI_MATCH(DMI_SYS_VENDOR, "LENOVO"),
1345240630e6SHans de Goede 				DMI_MATCH(DMI_PRODUCT_VERSION, "ThinkPad W541"),
1346240630e6SHans de Goede 			},
1347240630e6SHans de Goede 			/*
1348240630e6SHans de Goede 			 * Note date based on release notes, 2.35 has been
1349240630e6SHans de Goede 			 * reported to be good, but I've been unable to get
1350240630e6SHans de Goede 			 * a hold of the reporter to get the DMI BIOS date.
1351240630e6SHans de Goede 			 * TODO: fix this.
1352240630e6SHans de Goede 			 */
1353240630e6SHans de Goede 			.driver_data = "20180310", /* 2.35 */
1354240630e6SHans de Goede 		},
1355240630e6SHans de Goede 		{ }	/* terminate list */
1356240630e6SHans de Goede 	};
1357240630e6SHans de Goede 	const struct dmi_system_id *dmi = dmi_first_match(sysids);
1358240630e6SHans de Goede 	int year, month, date;
1359240630e6SHans de Goede 	char buf[9];
1360240630e6SHans de Goede 
1361240630e6SHans de Goede 	if (!dmi)
1362240630e6SHans de Goede 		return false;
1363240630e6SHans de Goede 
1364240630e6SHans de Goede 	dmi_get_date(DMI_BIOS_DATE, &year, &month, &date);
1365240630e6SHans de Goede 	snprintf(buf, sizeof(buf), "%04d%02d%02d", year, month, date);
1366240630e6SHans de Goede 
1367240630e6SHans de Goede 	return strcmp(buf, dmi->driver_data) < 0;
1368240630e6SHans de Goede }
1369240630e6SHans de Goede 
13705594639aSTejun Heo static bool ahci_broken_online(struct pci_dev *pdev)
13715594639aSTejun Heo {
13725594639aSTejun Heo #define ENCODE_BUSDEVFN(bus, slot, func)			\
13735594639aSTejun Heo 	(void *)(unsigned long)(((bus) << 8) | PCI_DEVFN((slot), (func)))
13745594639aSTejun Heo 	static const struct dmi_system_id sysids[] = {
13755594639aSTejun Heo 		/*
13765594639aSTejun Heo 		 * There are several gigabyte boards which use
13775594639aSTejun Heo 		 * SIMG5723s configured as hardware RAID.  Certain
13785594639aSTejun Heo 		 * 5723 firmware revisions shipped there keep the link
13795594639aSTejun Heo 		 * online but fail to answer properly to SRST or
13805594639aSTejun Heo 		 * IDENTIFY when no device is attached downstream
13815594639aSTejun Heo 		 * causing libata to retry quite a few times leading
13825594639aSTejun Heo 		 * to excessive detection delay.
13835594639aSTejun Heo 		 *
13845594639aSTejun Heo 		 * As these firmwares respond to the second reset try
13855594639aSTejun Heo 		 * with invalid device signature, considering unknown
13865594639aSTejun Heo 		 * sig as offline works around the problem acceptably.
13875594639aSTejun Heo 		 */
13885594639aSTejun Heo 		{
13895594639aSTejun Heo 			.ident = "EP45-DQ6",
13905594639aSTejun Heo 			.matches = {
13915594639aSTejun Heo 				DMI_MATCH(DMI_BOARD_VENDOR,
13925594639aSTejun Heo 					  "Gigabyte Technology Co., Ltd."),
13935594639aSTejun Heo 				DMI_MATCH(DMI_BOARD_NAME, "EP45-DQ6"),
13945594639aSTejun Heo 			},
13955594639aSTejun Heo 			.driver_data = ENCODE_BUSDEVFN(0x0a, 0x00, 0),
13965594639aSTejun Heo 		},
13975594639aSTejun Heo 		{
13985594639aSTejun Heo 			.ident = "EP45-DS5",
13995594639aSTejun Heo 			.matches = {
14005594639aSTejun Heo 				DMI_MATCH(DMI_BOARD_VENDOR,
14015594639aSTejun Heo 					  "Gigabyte Technology Co., Ltd."),
14025594639aSTejun Heo 				DMI_MATCH(DMI_BOARD_NAME, "EP45-DS5"),
14035594639aSTejun Heo 			},
14045594639aSTejun Heo 			.driver_data = ENCODE_BUSDEVFN(0x03, 0x00, 0),
14055594639aSTejun Heo 		},
14065594639aSTejun Heo 		{ }	/* terminate list */
14075594639aSTejun Heo 	};
14085594639aSTejun Heo #undef ENCODE_BUSDEVFN
14095594639aSTejun Heo 	const struct dmi_system_id *dmi = dmi_first_match(sysids);
14105594639aSTejun Heo 	unsigned int val;
14115594639aSTejun Heo 
14125594639aSTejun Heo 	if (!dmi)
14135594639aSTejun Heo 		return false;
14145594639aSTejun Heo 
14155594639aSTejun Heo 	val = (unsigned long)dmi->driver_data;
14165594639aSTejun Heo 
14175594639aSTejun Heo 	return pdev->bus->number == (val >> 8) && pdev->devfn == (val & 0xff);
14185594639aSTejun Heo }
14195594639aSTejun Heo 
14200cf4a7d6SJacob Pan static bool ahci_broken_devslp(struct pci_dev *pdev)
14210cf4a7d6SJacob Pan {
14220cf4a7d6SJacob Pan 	/* device with broken DEVSLP but still showing SDS capability */
14230cf4a7d6SJacob Pan 	static const struct pci_device_id ids[] = {
14240cf4a7d6SJacob Pan 		{ PCI_VDEVICE(INTEL, 0x0f23)}, /* Valleyview SoC */
14250cf4a7d6SJacob Pan 		{}
14260cf4a7d6SJacob Pan 	};
14270cf4a7d6SJacob Pan 
14280cf4a7d6SJacob Pan 	return pci_match_id(ids, pdev);
14290cf4a7d6SJacob Pan }
14300cf4a7d6SJacob Pan 
14318e513217SMarkus Trippelsdorf #ifdef CONFIG_ATA_ACPI
1432f80ae7e4STejun Heo static void ahci_gtf_filter_workaround(struct ata_host *host)
1433f80ae7e4STejun Heo {
1434f80ae7e4STejun Heo 	static const struct dmi_system_id sysids[] = {
1435f80ae7e4STejun Heo 		/*
1436f80ae7e4STejun Heo 		 * Aspire 3810T issues a bunch of SATA enable commands
1437f80ae7e4STejun Heo 		 * via _GTF including an invalid one and one which is
1438f80ae7e4STejun Heo 		 * rejected by the device.  Among the successful ones
1439f80ae7e4STejun Heo 		 * is FPDMA non-zero offset enable which when enabled
1440f80ae7e4STejun Heo 		 * only on the drive side leads to NCQ command
1441f80ae7e4STejun Heo 		 * failures.  Filter it out.
1442f80ae7e4STejun Heo 		 */
1443f80ae7e4STejun Heo 		{
1444f80ae7e4STejun Heo 			.ident = "Aspire 3810T",
1445f80ae7e4STejun Heo 			.matches = {
1446f80ae7e4STejun Heo 				DMI_MATCH(DMI_SYS_VENDOR, "Acer"),
1447f80ae7e4STejun Heo 				DMI_MATCH(DMI_PRODUCT_NAME, "Aspire 3810T"),
1448f80ae7e4STejun Heo 			},
1449f80ae7e4STejun Heo 			.driver_data = (void *)ATA_ACPI_FILTER_FPDMA_OFFSET,
1450f80ae7e4STejun Heo 		},
1451f80ae7e4STejun Heo 		{ }
1452f80ae7e4STejun Heo 	};
1453f80ae7e4STejun Heo 	const struct dmi_system_id *dmi = dmi_first_match(sysids);
1454f80ae7e4STejun Heo 	unsigned int filter;
1455f80ae7e4STejun Heo 	int i;
1456f80ae7e4STejun Heo 
1457f80ae7e4STejun Heo 	if (!dmi)
1458f80ae7e4STejun Heo 		return;
1459f80ae7e4STejun Heo 
1460f80ae7e4STejun Heo 	filter = (unsigned long)dmi->driver_data;
1461a44fec1fSJoe Perches 	dev_info(host->dev, "applying extra ACPI _GTF filter 0x%x for %s\n",
1462f80ae7e4STejun Heo 		 filter, dmi->ident);
1463f80ae7e4STejun Heo 
1464f80ae7e4STejun Heo 	for (i = 0; i < host->n_ports; i++) {
1465f80ae7e4STejun Heo 		struct ata_port *ap = host->ports[i];
1466f80ae7e4STejun Heo 		struct ata_link *link;
1467f80ae7e4STejun Heo 		struct ata_device *dev;
1468f80ae7e4STejun Heo 
1469f80ae7e4STejun Heo 		ata_for_each_link(link, ap, EDGE)
1470f80ae7e4STejun Heo 			ata_for_each_dev(dev, link, ALL)
1471f80ae7e4STejun Heo 				dev->gtf_filter |= filter;
1472f80ae7e4STejun Heo 	}
1473f80ae7e4STejun Heo }
14748e513217SMarkus Trippelsdorf #else
14758e513217SMarkus Trippelsdorf static inline void ahci_gtf_filter_workaround(struct ata_host *host)
14768e513217SMarkus Trippelsdorf {}
14778e513217SMarkus Trippelsdorf #endif
1478f80ae7e4STejun Heo 
14798bfd1743SSui Chen /*
14808bfd1743SSui Chen  * On the Acer Aspire Switch Alpha 12, sometimes all SATA ports are detected
14818bfd1743SSui Chen  * as DUMMY, or detected but eventually get a "link down" and never get up
14828bfd1743SSui Chen  * again. When this happens, CAP.NP may hold a value of 0x00 or 0x01, and the
14838bfd1743SSui Chen  * port_map may hold a value of 0x00.
14848bfd1743SSui Chen  *
14858bfd1743SSui Chen  * Overriding CAP.NP to 0x02 and the port_map to 0x7 will reveal all 3 ports
14868bfd1743SSui Chen  * and can significantly reduce the occurrence of the problem.
14878bfd1743SSui Chen  *
14888bfd1743SSui Chen  * https://bugzilla.kernel.org/show_bug.cgi?id=189471
14898bfd1743SSui Chen  */
14908bfd1743SSui Chen static void acer_sa5_271_workaround(struct ahci_host_priv *hpriv,
14918bfd1743SSui Chen 				    struct pci_dev *pdev)
14928bfd1743SSui Chen {
14938bfd1743SSui Chen 	static const struct dmi_system_id sysids[] = {
14948bfd1743SSui Chen 		{
14958bfd1743SSui Chen 			.ident = "Acer Switch Alpha 12",
14968bfd1743SSui Chen 			.matches = {
14978bfd1743SSui Chen 				DMI_MATCH(DMI_SYS_VENDOR, "Acer"),
14988bfd1743SSui Chen 				DMI_MATCH(DMI_PRODUCT_NAME, "Switch SA5-271")
14998bfd1743SSui Chen 			},
15008bfd1743SSui Chen 		},
15018bfd1743SSui Chen 		{ }
15028bfd1743SSui Chen 	};
15038bfd1743SSui Chen 
15048bfd1743SSui Chen 	if (dmi_check_system(sysids)) {
15058bfd1743SSui Chen 		dev_info(&pdev->dev, "enabling Acer Switch Alpha 12 workaround\n");
15068bfd1743SSui Chen 		if ((hpriv->saved_cap & 0xC734FF00) == 0xC734FF00) {
15078bfd1743SSui Chen 			hpriv->port_map = 0x7;
15088bfd1743SSui Chen 			hpriv->cap = 0xC734FF02;
15098bfd1743SSui Chen 		}
15108bfd1743SSui Chen 	}
15118bfd1743SSui Chen }
15128bfd1743SSui Chen 
1513d243bed3STirumalesh Chalamarla #ifdef CONFIG_ARM64
1514d243bed3STirumalesh Chalamarla /*
1515d243bed3STirumalesh Chalamarla  * Due to ERRATA#22536, ThunderX needs to handle HOST_IRQ_STAT differently.
1516d243bed3STirumalesh Chalamarla  * Workaround is to make sure all pending IRQs are served before leaving
1517d243bed3STirumalesh Chalamarla  * handler.
1518d243bed3STirumalesh Chalamarla  */
1519d243bed3STirumalesh Chalamarla static irqreturn_t ahci_thunderx_irq_handler(int irq, void *dev_instance)
1520d243bed3STirumalesh Chalamarla {
1521d243bed3STirumalesh Chalamarla 	struct ata_host *host = dev_instance;
1522d243bed3STirumalesh Chalamarla 	struct ahci_host_priv *hpriv;
1523d243bed3STirumalesh Chalamarla 	unsigned int rc = 0;
1524d243bed3STirumalesh Chalamarla 	void __iomem *mmio;
1525d243bed3STirumalesh Chalamarla 	u32 irq_stat, irq_masked;
1526d243bed3STirumalesh Chalamarla 	unsigned int handled = 1;
1527d243bed3STirumalesh Chalamarla 
1528d243bed3STirumalesh Chalamarla 	hpriv = host->private_data;
1529d243bed3STirumalesh Chalamarla 	mmio = hpriv->mmio;
1530d243bed3STirumalesh Chalamarla 	irq_stat = readl(mmio + HOST_IRQ_STAT);
1531d243bed3STirumalesh Chalamarla 	if (!irq_stat)
1532d243bed3STirumalesh Chalamarla 		return IRQ_NONE;
1533d243bed3STirumalesh Chalamarla 
1534d243bed3STirumalesh Chalamarla 	do {
1535d243bed3STirumalesh Chalamarla 		irq_masked = irq_stat & hpriv->port_map;
1536d243bed3STirumalesh Chalamarla 		spin_lock(&host->lock);
1537d243bed3STirumalesh Chalamarla 		rc = ahci_handle_port_intr(host, irq_masked);
1538d243bed3STirumalesh Chalamarla 		if (!rc)
1539d243bed3STirumalesh Chalamarla 			handled = 0;
1540d243bed3STirumalesh Chalamarla 		writel(irq_stat, mmio + HOST_IRQ_STAT);
1541d243bed3STirumalesh Chalamarla 		irq_stat = readl(mmio + HOST_IRQ_STAT);
1542d243bed3STirumalesh Chalamarla 		spin_unlock(&host->lock);
1543d243bed3STirumalesh Chalamarla 	} while (irq_stat);
1544d243bed3STirumalesh Chalamarla 
1545d243bed3STirumalesh Chalamarla 	return IRQ_RETVAL(handled);
1546d243bed3STirumalesh Chalamarla }
1547d243bed3STirumalesh Chalamarla #endif
1548d243bed3STirumalesh Chalamarla 
1549aecec8b6SChristoph Hellwig static void ahci_remap_check(struct pci_dev *pdev, int bar,
1550aecec8b6SChristoph Hellwig 		struct ahci_host_priv *hpriv)
1551aecec8b6SChristoph Hellwig {
1552894fba7fSKai-Heng Feng 	int i;
1553aecec8b6SChristoph Hellwig 	u32 cap;
1554aecec8b6SChristoph Hellwig 
1555aecec8b6SChristoph Hellwig 	/*
1556aecec8b6SChristoph Hellwig 	 * Check if this device might have remapped nvme devices.
1557aecec8b6SChristoph Hellwig 	 */
1558aecec8b6SChristoph Hellwig 	if (pdev->vendor != PCI_VENDOR_ID_INTEL ||
1559aecec8b6SChristoph Hellwig 	    pci_resource_len(pdev, bar) < SZ_512K ||
1560aecec8b6SChristoph Hellwig 	    bar != AHCI_PCI_BAR_STANDARD ||
1561aecec8b6SChristoph Hellwig 	    !(readl(hpriv->mmio + AHCI_VSCAP) & 1))
1562aecec8b6SChristoph Hellwig 		return;
1563aecec8b6SChristoph Hellwig 
1564aecec8b6SChristoph Hellwig 	cap = readq(hpriv->mmio + AHCI_REMAP_CAP);
1565aecec8b6SChristoph Hellwig 	for (i = 0; i < AHCI_MAX_REMAP; i++) {
1566aecec8b6SChristoph Hellwig 		if ((cap & (1 << i)) == 0)
1567aecec8b6SChristoph Hellwig 			continue;
1568aecec8b6SChristoph Hellwig 		if (readl(hpriv->mmio + ahci_remap_dcc(i))
1569aecec8b6SChristoph Hellwig 				!= PCI_CLASS_STORAGE_EXPRESS)
1570aecec8b6SChristoph Hellwig 			continue;
1571aecec8b6SChristoph Hellwig 
1572aecec8b6SChristoph Hellwig 		/* We've found a remapped device */
1573894fba7fSKai-Heng Feng 		hpriv->remapped_nvme++;
1574aecec8b6SChristoph Hellwig 	}
1575aecec8b6SChristoph Hellwig 
1576894fba7fSKai-Heng Feng 	if (!hpriv->remapped_nvme)
1577aecec8b6SChristoph Hellwig 		return;
1578aecec8b6SChristoph Hellwig 
1579894fba7fSKai-Heng Feng 	dev_warn(&pdev->dev, "Found %u remapped NVMe devices.\n",
1580894fba7fSKai-Heng Feng 		 hpriv->remapped_nvme);
1581f723fa4eSChristoph Hellwig 	dev_warn(&pdev->dev,
1582f723fa4eSChristoph Hellwig 		 "Switch your BIOS from RAID to AHCI mode to use them.\n");
1583f723fa4eSChristoph Hellwig 
1584f723fa4eSChristoph Hellwig 	/*
1585f723fa4eSChristoph Hellwig 	 * Don't rely on the msi-x capability in the remap case,
1586f723fa4eSChristoph Hellwig 	 * share the legacy interrupt across ahci and remapped devices.
1587f723fa4eSChristoph Hellwig 	 */
1588f723fa4eSChristoph Hellwig 	hpriv->flags |= AHCI_HFLAG_NO_MSI;
1589aecec8b6SChristoph Hellwig }
1590aecec8b6SChristoph Hellwig 
15910b9e2988SChristoph Hellwig static int ahci_get_irq_vector(struct ata_host *host, int port)
1592ee2aad42SRobert Richter {
15930b9e2988SChristoph Hellwig 	return pci_irq_vector(to_pci_dev(host->dev), port);
1594ee2aad42SRobert Richter }
1595ee2aad42SRobert Richter 
1596a1c82311SRobert Richter static int ahci_init_msi(struct pci_dev *pdev, unsigned int n_ports,
15977b92b4f6SAlexander Gordeev 			struct ahci_host_priv *hpriv)
15985ca72c4fSAlexander Gordeev {
15990b9e2988SChristoph Hellwig 	int nvec;
16005ca72c4fSAlexander Gordeev 
16017b92b4f6SAlexander Gordeev 	if (hpriv->flags & AHCI_HFLAG_NO_MSI)
1602a1c82311SRobert Richter 		return -ENODEV;
16037b92b4f6SAlexander Gordeev 
16045ca72c4fSAlexander Gordeev 	/*
16057b92b4f6SAlexander Gordeev 	 * If number of MSIs is less than number of ports then Sharing Last
16067b92b4f6SAlexander Gordeev 	 * Message mode could be enforced. In this case assume that advantage
16077b92b4f6SAlexander Gordeev 	 * of multipe MSIs is negated and use single MSI mode instead.
16085ca72c4fSAlexander Gordeev 	 */
160917a51f12SChristoph Hellwig 	if (n_ports > 1) {
16100b9e2988SChristoph Hellwig 		nvec = pci_alloc_irq_vectors(pdev, n_ports, INT_MAX,
16110b9e2988SChristoph Hellwig 				PCI_IRQ_MSIX | PCI_IRQ_MSI);
16120b9e2988SChristoph Hellwig 		if (nvec > 0) {
16130b9e2988SChristoph Hellwig 			if (!(readl(hpriv->mmio + HOST_CTL) & HOST_MRSM)) {
16140b9e2988SChristoph Hellwig 				hpriv->get_irq_vector = ahci_get_irq_vector;
1615c3ebd6a9SAlexander Gordeev 				hpriv->flags |= AHCI_HFLAG_MULTI_MSI;
161621bfd1aaSRobert Richter 				return nvec;
1617a1c82311SRobert Richter 			}
1618a1c82311SRobert Richter 
1619d684a90dSDan Williams 			/*
162017a51f12SChristoph Hellwig 			 * Fallback to single MSI mode if the controller
162117a51f12SChristoph Hellwig 			 * enforced MRSM mode.
1622d684a90dSDan Williams 			 */
162317a51f12SChristoph Hellwig 			printk(KERN_INFO
162417a51f12SChristoph Hellwig 				"ahci: MRSM is on, fallback to single MSI\n");
16250b9e2988SChristoph Hellwig 			pci_free_irq_vectors(pdev);
16260b9e2988SChristoph Hellwig 		}
1627a478b097SChristoph Hellwig 	}
1628d684a90dSDan Williams 
16290b9e2988SChristoph Hellwig 	/*
16300b9e2988SChristoph Hellwig 	 * If the host is not capable of supporting per-port vectors, fall
16310b9e2988SChristoph Hellwig 	 * back to single MSI before finally attempting single MSI-X.
16320b9e2988SChristoph Hellwig 	 */
16330b9e2988SChristoph Hellwig 	nvec = pci_alloc_irq_vectors(pdev, 1, 1, PCI_IRQ_MSI);
16340b9e2988SChristoph Hellwig 	if (nvec == 1)
1635a1c82311SRobert Richter 		return nvec;
16360b9e2988SChristoph Hellwig 	return pci_alloc_irq_vectors(pdev, 1, 1, PCI_IRQ_MSIX);
16375ca72c4fSAlexander Gordeev }
16385ca72c4fSAlexander Gordeev 
1639b1a9585cSSrinivas Pandruvada static void ahci_update_initial_lpm_policy(struct ata_port *ap,
1640b1a9585cSSrinivas Pandruvada 					   struct ahci_host_priv *hpriv)
1641b1a9585cSSrinivas Pandruvada {
164255b01415SMario Limonciello 	int policy = CONFIG_SATA_MOBILE_LPM_POLICY;
1643b1a9585cSSrinivas Pandruvada 
1644b1a9585cSSrinivas Pandruvada 
1645e5c89479SMario Limonciello 	/* Ignore processing for chipsets that don't use policy */
1646e5c89479SMario Limonciello 	if (!(hpriv->flags & AHCI_HFLAG_USE_LPM_POLICY))
1647b1a9585cSSrinivas Pandruvada 		return;
1648b1a9585cSSrinivas Pandruvada 
1649b1a9585cSSrinivas Pandruvada 	/* user modified policy via module param */
1650b1a9585cSSrinivas Pandruvada 	if (mobile_lpm_policy != -1) {
1651b1a9585cSSrinivas Pandruvada 		policy = mobile_lpm_policy;
1652b1a9585cSSrinivas Pandruvada 		goto update_policy;
1653b1a9585cSSrinivas Pandruvada 	}
1654b1a9585cSSrinivas Pandruvada 
1655fee60730SRafael J. Wysocki 	if (policy > ATA_LPM_MED_POWER && pm_suspend_default_s2idle()) {
1656b1a9585cSSrinivas Pandruvada 		if (hpriv->cap & HOST_CAP_PART)
1657b1a9585cSSrinivas Pandruvada 			policy = ATA_LPM_MIN_POWER_WITH_PARTIAL;
1658b1a9585cSSrinivas Pandruvada 		else if (hpriv->cap & HOST_CAP_SSC)
1659b1a9585cSSrinivas Pandruvada 			policy = ATA_LPM_MIN_POWER;
1660b1a9585cSSrinivas Pandruvada 	}
1661b1a9585cSSrinivas Pandruvada 
1662b1a9585cSSrinivas Pandruvada update_policy:
1663b1a9585cSSrinivas Pandruvada 	if (policy >= ATA_LPM_UNKNOWN && policy <= ATA_LPM_MIN_POWER)
1664b1a9585cSSrinivas Pandruvada 		ap->target_lpm_policy = policy;
1665b1a9585cSSrinivas Pandruvada }
1666b1a9585cSSrinivas Pandruvada 
1667c312ef17SDan Williams static void ahci_intel_pcs_quirk(struct pci_dev *pdev, struct ahci_host_priv *hpriv)
1668c312ef17SDan Williams {
1669c312ef17SDan Williams 	const struct pci_device_id *id = pci_match_id(ahci_pci_tbl, pdev);
1670c312ef17SDan Williams 	u16 tmp16;
1671c312ef17SDan Williams 
1672c312ef17SDan Williams 	/*
1673c312ef17SDan Williams 	 * Only apply the 6-port PCS quirk for known legacy platforms.
1674c312ef17SDan Williams 	 */
1675c312ef17SDan Williams 	if (!id || id->vendor != PCI_VENDOR_ID_INTEL)
1676c312ef17SDan Williams 		return;
167709d6ac8dSDan Williams 
167809d6ac8dSDan Williams 	/* Skip applying the quirk on Denverton and beyond */
167909d6ac8dSDan Williams 	if (((enum board_ids) id->driver_data) >= board_ahci_pcs7)
1680c312ef17SDan Williams 		return;
1681c312ef17SDan Williams 
1682c312ef17SDan Williams 	/*
1683c312ef17SDan Williams 	 * port_map is determined from PORTS_IMPL PCI register which is
1684c312ef17SDan Williams 	 * implemented as write or write-once register.  If the register
1685c312ef17SDan Williams 	 * isn't programmed, ahci automatically generates it from number
1686c312ef17SDan Williams 	 * of ports, which is good enough for PCS programming. It is
1687c312ef17SDan Williams 	 * otherwise expected that platform firmware enables the ports
1688c312ef17SDan Williams 	 * before the OS boots.
1689c312ef17SDan Williams 	 */
1690c312ef17SDan Williams 	pci_read_config_word(pdev, PCS_6, &tmp16);
1691c312ef17SDan Williams 	if ((tmp16 & hpriv->port_map) != hpriv->port_map) {
1692c312ef17SDan Williams 		tmp16 |= hpriv->port_map;
1693c312ef17SDan Williams 		pci_write_config_word(pdev, PCS_6, tmp16);
1694c312ef17SDan Williams 	}
1695c312ef17SDan Williams }
1696c312ef17SDan Williams 
1697894fba7fSKai-Heng Feng static ssize_t remapped_nvme_show(struct device *dev,
1698894fba7fSKai-Heng Feng 				  struct device_attribute *attr,
1699894fba7fSKai-Heng Feng 				  char *buf)
1700894fba7fSKai-Heng Feng {
1701894fba7fSKai-Heng Feng 	struct ata_host *host = dev_get_drvdata(dev);
1702894fba7fSKai-Heng Feng 	struct ahci_host_priv *hpriv = host->private_data;
1703894fba7fSKai-Heng Feng 
1704179a0282SDamien Le Moal 	return sysfs_emit(buf, "%u\n", hpriv->remapped_nvme);
1705894fba7fSKai-Heng Feng }
1706894fba7fSKai-Heng Feng 
1707894fba7fSKai-Heng Feng static DEVICE_ATTR_RO(remapped_nvme);
1708894fba7fSKai-Heng Feng 
1709c6fd2807SJeff Garzik static int ahci_init_one(struct pci_dev *pdev, const struct pci_device_id *ent)
1710c6fd2807SJeff Garzik {
1711e297d99eSTejun Heo 	unsigned int board_id = ent->driver_data;
1712e297d99eSTejun Heo 	struct ata_port_info pi = ahci_port_info[board_id];
17134447d351STejun Heo 	const struct ata_port_info *ppi[] = { &pi, NULL };
171424dc5f33STejun Heo 	struct device *dev = &pdev->dev;
1715c6fd2807SJeff Garzik 	struct ahci_host_priv *hpriv;
17164447d351STejun Heo 	struct ata_host *host;
1717c3ebd6a9SAlexander Gordeev 	int n_ports, i, rc;
1718318893e1SAlessandro Rubini 	int ahci_pci_bar = AHCI_PCI_BAR_STANDARD;
1719c6fd2807SJeff Garzik 
1720b429dd59SJustin P. Mattock 	WARN_ON((int)ATA_MAX_QUEUE > AHCI_MAX_CMDS);
1721c6fd2807SJeff Garzik 
172206296a1eSJoe Perches 	ata_print_version_once(&pdev->dev, DRV_VERSION);
1723c6fd2807SJeff Garzik 
17245b66c829SAlan Cox 	/* The AHCI driver can only drive the SATA ports, the PATA driver
17255b66c829SAlan Cox 	   can drive them all so if both drivers are selected make sure
17265b66c829SAlan Cox 	   AHCI stays out of the way */
17275b66c829SAlan Cox 	if (pdev->vendor == PCI_VENDOR_ID_MARVELL && !marvell_enable)
17285b66c829SAlan Cox 		return -ENODEV;
17295b66c829SAlan Cox 
1730cb85696dSJames Laird 	/* Apple BIOS on MCP89 prevents us using AHCI */
1731cb85696dSJames Laird 	if (is_mcp89_apple(pdev))
1732cb85696dSJames Laird 		ahci_mcp89_apple_enable(pdev);
1733c6353b45STejun Heo 
17347a02267eSMark Nelson 	/* Promise's PDC42819 is a SAS/SATA controller that has an AHCI mode.
17357a02267eSMark Nelson 	 * At the moment, we can only use the AHCI mode. Let the users know
17367a02267eSMark Nelson 	 * that for SAS drives they're out of luck.
17377a02267eSMark Nelson 	 */
17387a02267eSMark Nelson 	if (pdev->vendor == PCI_VENDOR_ID_PROMISE)
1739a44fec1fSJoe Perches 		dev_info(&pdev->dev,
1740a44fec1fSJoe Perches 			 "PDC42819 can only drive SATA devices with this driver\n");
17417a02267eSMark Nelson 
1742b7ae128dSRobert Richter 	/* Some devices use non-standard BARs */
1743318893e1SAlessandro Rubini 	if (pdev->vendor == PCI_VENDOR_ID_STMICRO && pdev->device == 0xCC06)
1744318893e1SAlessandro Rubini 		ahci_pci_bar = AHCI_PCI_BAR_STA2X11;
17457f9c9f8eSHugh Daschbach 	else if (pdev->vendor == 0x1c44 && pdev->device == 0x8000)
17467f9c9f8eSHugh Daschbach 		ahci_pci_bar = AHCI_PCI_BAR_ENMOTUS;
1747b1314e3fSRadha Mohan Chintakuntla 	else if (pdev->vendor == PCI_VENDOR_ID_CAVIUM) {
1748b1314e3fSRadha Mohan Chintakuntla 		if (pdev->device == 0xa01c)
1749b7ae128dSRobert Richter 			ahci_pci_bar = AHCI_PCI_BAR_CAVIUM;
1750b1314e3fSRadha Mohan Chintakuntla 		if (pdev->device == 0xa084)
1751b1314e3fSRadha Mohan Chintakuntla 			ahci_pci_bar = AHCI_PCI_BAR_CAVIUM_GEN5;
1752e49bd683STiezhu Yang 	} else if (pdev->vendor == PCI_VENDOR_ID_LOONGSON) {
1753e49bd683STiezhu Yang 		if (pdev->device == 0x7a08)
1754e49bd683STiezhu Yang 			ahci_pci_bar = AHCI_PCI_BAR_LOONGSON;
1755b1314e3fSRadha Mohan Chintakuntla 	}
1756318893e1SAlessandro Rubini 
17574447d351STejun Heo 	/* acquire resources */
175824dc5f33STejun Heo 	rc = pcim_enable_device(pdev);
1759c6fd2807SJeff Garzik 	if (rc)
1760c6fd2807SJeff Garzik 		return rc;
1761c6fd2807SJeff Garzik 
1762c4f7792cSTejun Heo 	if (pdev->vendor == PCI_VENDOR_ID_INTEL &&
1763c4f7792cSTejun Heo 	    (pdev->device == 0x2652 || pdev->device == 0x2653)) {
1764c4f7792cSTejun Heo 		u8 map;
1765c4f7792cSTejun Heo 
1766c4f7792cSTejun Heo 		/* ICH6s share the same PCI ID for both piix and ahci
1767c4f7792cSTejun Heo 		 * modes.  Enabling ahci mode while MAP indicates
1768c4f7792cSTejun Heo 		 * combined mode is a bad idea.  Yield to ata_piix.
1769c4f7792cSTejun Heo 		 */
1770c4f7792cSTejun Heo 		pci_read_config_byte(pdev, ICH_MAP, &map);
1771c4f7792cSTejun Heo 		if (map & 0x3) {
1772a44fec1fSJoe Perches 			dev_info(&pdev->dev,
1773a44fec1fSJoe Perches 				 "controller is in combined mode, can't enable AHCI mode\n");
1774c4f7792cSTejun Heo 			return -ENODEV;
1775c4f7792cSTejun Heo 		}
1776c4f7792cSTejun Heo 	}
1777c4f7792cSTejun Heo 
17786fec8871SPaul Bolle 	/* AHCI controllers often implement SFF compatible interface.
17796fec8871SPaul Bolle 	 * Grab all PCI BARs just in case.
17806fec8871SPaul Bolle 	 */
17816fec8871SPaul Bolle 	rc = pcim_iomap_regions_request_all(pdev, 1 << ahci_pci_bar, DRV_NAME);
17826fec8871SPaul Bolle 	if (rc == -EBUSY)
17836fec8871SPaul Bolle 		pcim_pin_device(pdev);
17846fec8871SPaul Bolle 	if (rc)
17856fec8871SPaul Bolle 		return rc;
17866fec8871SPaul Bolle 
178724dc5f33STejun Heo 	hpriv = devm_kzalloc(dev, sizeof(*hpriv), GFP_KERNEL);
178824dc5f33STejun Heo 	if (!hpriv)
178924dc5f33STejun Heo 		return -ENOMEM;
1790417a1a6dSTejun Heo 	hpriv->flags |= (unsigned long)pi.private_data;
1791417a1a6dSTejun Heo 
1792e297d99eSTejun Heo 	/* MCP65 revision A1 and A2 can't do MSI */
1793e297d99eSTejun Heo 	if (board_id == board_ahci_mcp65 &&
1794e297d99eSTejun Heo 	    (pdev->revision == 0xa1 || pdev->revision == 0xa2))
1795e297d99eSTejun Heo 		hpriv->flags |= AHCI_HFLAG_NO_MSI;
1796e297d99eSTejun Heo 
1797e427fe04SShane Huang 	/* SB800 does NOT need the workaround to ignore SERR_INTERNAL */
1798e427fe04SShane Huang 	if (board_id == board_ahci_sb700 && pdev->revision >= 0x40)
1799e427fe04SShane Huang 		hpriv->flags &= ~AHCI_HFLAG_IGN_SERR_INTERNAL;
1800e427fe04SShane Huang 
18012fcad9d2STejun Heo 	/* only some SB600s can do 64bit DMA */
18022fcad9d2STejun Heo 	if (ahci_sb600_enable_64bit(pdev))
18032fcad9d2STejun Heo 		hpriv->flags &= ~AHCI_HFLAG_32BIT_ONLY;
180458a09b38SShane Huang 
1805318893e1SAlessandro Rubini 	hpriv->mmio = pcim_iomap_table(pdev)[ahci_pci_bar];
1806d8993349SAnton Vorontsov 
1807aecec8b6SChristoph Hellwig 	/* detect remapped nvme devices */
1808aecec8b6SChristoph Hellwig 	ahci_remap_check(pdev, ahci_pci_bar, hpriv);
1809aecec8b6SChristoph Hellwig 
1810894fba7fSKai-Heng Feng 	sysfs_add_file_to_group(&pdev->dev.kobj,
1811894fba7fSKai-Heng Feng 				&dev_attr_remapped_nvme.attr,
1812894fba7fSKai-Heng Feng 				NULL);
1813894fba7fSKai-Heng Feng 
18140cf4a7d6SJacob Pan 	/* must set flag prior to save config in order to take effect */
18150cf4a7d6SJacob Pan 	if (ahci_broken_devslp(pdev))
18160cf4a7d6SJacob Pan 		hpriv->flags |= AHCI_HFLAG_NO_DEVSLP;
18170cf4a7d6SJacob Pan 
1818d243bed3STirumalesh Chalamarla #ifdef CONFIG_ARM64
1819234e6d2cSXingui Yang 	if (pdev->vendor == PCI_VENDOR_ID_HUAWEI &&
1820234e6d2cSXingui Yang 	    pdev->device == 0xa235 &&
1821234e6d2cSXingui Yang 	    pdev->revision < 0x30)
1822234e6d2cSXingui Yang 		hpriv->flags |= AHCI_HFLAG_NO_SXS;
1823234e6d2cSXingui Yang 
1824d243bed3STirumalesh Chalamarla 	if (pdev->vendor == 0x177d && pdev->device == 0xa01c)
1825d243bed3STirumalesh Chalamarla 		hpriv->irq_handler = ahci_thunderx_irq_handler;
1826d243bed3STirumalesh Chalamarla #endif
1827d243bed3STirumalesh Chalamarla 
18284447d351STejun Heo 	/* save initial config */
1829394d6e53SAnton Vorontsov 	ahci_pci_save_initial_config(pdev, hpriv);
1830c6fd2807SJeff Garzik 
18314447d351STejun Heo 	/* prepare host */
1832453d3131SRobert Hancock 	if (hpriv->cap & HOST_CAP_NCQ) {
1833453d3131SRobert Hancock 		pi.flags |= ATA_FLAG_NCQ;
183483f2b963STejun Heo 		/*
183583f2b963STejun Heo 		 * Auto-activate optimization is supposed to be
183683f2b963STejun Heo 		 * supported on all AHCI controllers indicating NCQ
183783f2b963STejun Heo 		 * capability, but it seems to be broken on some
183883f2b963STejun Heo 		 * chipsets including NVIDIAs.
183983f2b963STejun Heo 		 */
184083f2b963STejun Heo 		if (!(hpriv->flags & AHCI_HFLAG_NO_FPDMA_AA))
1841453d3131SRobert Hancock 			pi.flags |= ATA_FLAG_FPDMA_AA;
184240fb59e7SMarc Carino 
184340fb59e7SMarc Carino 		/*
184440fb59e7SMarc Carino 		 * All AHCI controllers should be forward-compatible
184540fb59e7SMarc Carino 		 * with the new auxiliary field. This code should be
184640fb59e7SMarc Carino 		 * conditionalized if any buggy AHCI controllers are
184740fb59e7SMarc Carino 		 * encountered.
184840fb59e7SMarc Carino 		 */
184940fb59e7SMarc Carino 		pi.flags |= ATA_FLAG_FPDMA_AUX;
1850453d3131SRobert Hancock 	}
18514447d351STejun Heo 
18527d50b60bSTejun Heo 	if (hpriv->cap & HOST_CAP_PMP)
18537d50b60bSTejun Heo 		pi.flags |= ATA_FLAG_PMP;
18547d50b60bSTejun Heo 
18550cbb0e77SAnton Vorontsov 	ahci_set_em_messages(hpriv, &pi);
185618f7ba4cSKristen Carlson Accardi 
18571fd68434SRafael J. Wysocki 	if (ahci_broken_system_poweroff(pdev)) {
18581fd68434SRafael J. Wysocki 		pi.flags |= ATA_FLAG_NO_POWEROFF_SPINDOWN;
18591fd68434SRafael J. Wysocki 		dev_info(&pdev->dev,
18601fd68434SRafael J. Wysocki 			"quirky BIOS, skipping spindown on poweroff\n");
18611fd68434SRafael J. Wysocki 	}
18621fd68434SRafael J. Wysocki 
1863240630e6SHans de Goede 	if (ahci_broken_lpm(pdev)) {
1864240630e6SHans de Goede 		pi.flags |= ATA_FLAG_NO_LPM;
1865240630e6SHans de Goede 		dev_warn(&pdev->dev,
1866240630e6SHans de Goede 			 "BIOS update required for Link Power Management support\n");
1867240630e6SHans de Goede 	}
1868240630e6SHans de Goede 
18699b10ae86STejun Heo 	if (ahci_broken_suspend(pdev)) {
18709b10ae86STejun Heo 		hpriv->flags |= AHCI_HFLAG_NO_SUSPEND;
1871a44fec1fSJoe Perches 		dev_warn(&pdev->dev,
18729b10ae86STejun Heo 			 "BIOS update required for suspend/resume\n");
18739b10ae86STejun Heo 	}
18749b10ae86STejun Heo 
18755594639aSTejun Heo 	if (ahci_broken_online(pdev)) {
18765594639aSTejun Heo 		hpriv->flags |= AHCI_HFLAG_SRST_TOUT_IS_OFFLINE;
18775594639aSTejun Heo 		dev_info(&pdev->dev,
18785594639aSTejun Heo 			 "online status unreliable, applying workaround\n");
18795594639aSTejun Heo 	}
18805594639aSTejun Heo 
18818bfd1743SSui Chen 
18828bfd1743SSui Chen 	/* Acer SA5-271 workaround modifies private_data */
18838bfd1743SSui Chen 	acer_sa5_271_workaround(hpriv, pdev);
18848bfd1743SSui Chen 
1885837f5f8fSTejun Heo 	/* CAP.NP sometimes indicate the index of the last enabled
1886837f5f8fSTejun Heo 	 * port, at other times, that of the last possible port, so
1887837f5f8fSTejun Heo 	 * determining the maximum port number requires looking at
1888837f5f8fSTejun Heo 	 * both CAP.NP and port_map.
1889837f5f8fSTejun Heo 	 */
1890837f5f8fSTejun Heo 	n_ports = max(ahci_nr_ports(hpriv->cap), fls(hpriv->port_map));
1891837f5f8fSTejun Heo 
1892837f5f8fSTejun Heo 	host = ata_host_alloc_pinfo(&pdev->dev, ppi, n_ports);
1893*d8d54126SNiklas Cassel 	if (!host) {
1894*d8d54126SNiklas Cassel 		rc = -ENOMEM;
1895*d8d54126SNiklas Cassel 		goto err_rm_sysfs_file;
1896*d8d54126SNiklas Cassel 	}
18974447d351STejun Heo 	host->private_data = hpriv;
18980b9e2988SChristoph Hellwig 
18990b9e2988SChristoph Hellwig 	if (ahci_init_msi(pdev, n_ports, hpriv) < 0) {
19000b9e2988SChristoph Hellwig 		/* legacy intx interrupts */
19010b9e2988SChristoph Hellwig 		pci_intx(pdev, 1);
19020b9e2988SChristoph Hellwig 	}
19030ce57f8aSChristoph Hellwig 	hpriv->irq = pci_irq_vector(pdev, 0);
190421bfd1aaSRobert Richter 
1905f3d7f23fSArjan van de Ven 	if (!(hpriv->cap & HOST_CAP_SSS) || ahci_ignore_sss)
1906886ad09fSArjan van de Ven 		host->flags |= ATA_HOST_PARALLEL_SCAN;
1907f3d7f23fSArjan van de Ven 	else
1908d2782d96SJingoo Han 		dev_info(&pdev->dev, "SSS flag set, parallel bus scan disabled\n");
1909886ad09fSArjan van de Ven 
191024e0e61dSNiklas Cassel 	if (!(hpriv->cap & HOST_CAP_PART))
191124e0e61dSNiklas Cassel 		host->flags |= ATA_HOST_NO_PART;
191224e0e61dSNiklas Cassel 
191324e0e61dSNiklas Cassel 	if (!(hpriv->cap & HOST_CAP_SSC))
191424e0e61dSNiklas Cassel 		host->flags |= ATA_HOST_NO_SSC;
191524e0e61dSNiklas Cassel 
191624e0e61dSNiklas Cassel 	if (!(hpriv->cap2 & HOST_CAP2_SDS))
191724e0e61dSNiklas Cassel 		host->flags |= ATA_HOST_NO_DEVSLP;
191824e0e61dSNiklas Cassel 
191918f7ba4cSKristen Carlson Accardi 	if (pi.flags & ATA_FLAG_EM)
192018f7ba4cSKristen Carlson Accardi 		ahci_reset_em(host);
192118f7ba4cSKristen Carlson Accardi 
19224447d351STejun Heo 	for (i = 0; i < host->n_ports; i++) {
19234447d351STejun Heo 		struct ata_port *ap = host->ports[i];
19244447d351STejun Heo 
1925318893e1SAlessandro Rubini 		ata_port_pbar_desc(ap, ahci_pci_bar, -1, "abar");
1926318893e1SAlessandro Rubini 		ata_port_pbar_desc(ap, ahci_pci_bar,
1927cbcdd875STejun Heo 				   0x100 + ap->port_no * 0x80, "port");
1928cbcdd875STejun Heo 
192918f7ba4cSKristen Carlson Accardi 		/* set enclosure management message type */
193018f7ba4cSKristen Carlson Accardi 		if (ap->flags & ATA_FLAG_EM)
1931008dbd61SHarry Zhang 			ap->em_message_type = hpriv->em_msg_type;
193218f7ba4cSKristen Carlson Accardi 
1933b1a9585cSSrinivas Pandruvada 		ahci_update_initial_lpm_policy(ap, hpriv);
193418f7ba4cSKristen Carlson Accardi 
1935dab632e8SJeff Garzik 		/* disabled/not-implemented port */
1936350756f6STejun Heo 		if (!(hpriv->port_map & (1 << i)))
1937dab632e8SJeff Garzik 			ap->ops = &ata_dummy_port_ops;
19384447d351STejun Heo 	}
1939c6fd2807SJeff Garzik 
1940edc93052STejun Heo 	/* apply workaround for ASUS P5W DH Deluxe mainboard */
1941edc93052STejun Heo 	ahci_p5wdh_workaround(host);
1942edc93052STejun Heo 
1943f80ae7e4STejun Heo 	/* apply gtf filter quirk */
1944f80ae7e4STejun Heo 	ahci_gtf_filter_workaround(host);
1945f80ae7e4STejun Heo 
1946c6fd2807SJeff Garzik 	/* initialize adapter */
1947b0dd4d7aSLennert Buytenhek 	rc = ahci_configure_dma_masks(pdev, hpriv);
1948c6fd2807SJeff Garzik 	if (rc)
1949*d8d54126SNiklas Cassel 		goto err_rm_sysfs_file;
1950c6fd2807SJeff Garzik 
195137e14e4fSAdam Vodopjan 	rc = ahci_pci_reset_controller(host);
19524447d351STejun Heo 	if (rc)
1953*d8d54126SNiklas Cassel 		goto err_rm_sysfs_file;
1954c6fd2807SJeff Garzik 
1955781d6550SAnton Vorontsov 	ahci_pci_init_controller(host);
1956439fcaecSAnton Vorontsov 	ahci_pci_print_info(host);
1957c6fd2807SJeff Garzik 
19584447d351STejun Heo 	pci_set_master(pdev);
19595ca72c4fSAlexander Gordeev 
196002e53293SMika Westerberg 	rc = ahci_host_activate(host, &ahci_sht);
196102e53293SMika Westerberg 	if (rc)
1962*d8d54126SNiklas Cassel 		goto err_rm_sysfs_file;
196302e53293SMika Westerberg 
196402e53293SMika Westerberg 	pm_runtime_put_noidle(&pdev->dev);
196502e53293SMika Westerberg 	return 0;
1966*d8d54126SNiklas Cassel 
1967*d8d54126SNiklas Cassel err_rm_sysfs_file:
1968*d8d54126SNiklas Cassel 	sysfs_remove_file_from_group(&pdev->dev.kobj,
1969*d8d54126SNiklas Cassel 				     &dev_attr_remapped_nvme.attr, NULL);
1970*d8d54126SNiklas Cassel 	return rc;
197102e53293SMika Westerberg }
197202e53293SMika Westerberg 
197310a663a1SPrabhakar Kushwaha static void ahci_shutdown_one(struct pci_dev *pdev)
197410a663a1SPrabhakar Kushwaha {
197510a663a1SPrabhakar Kushwaha 	ata_pci_shutdown_one(pdev);
197610a663a1SPrabhakar Kushwaha }
197710a663a1SPrabhakar Kushwaha 
197802e53293SMika Westerberg static void ahci_remove_one(struct pci_dev *pdev)
197902e53293SMika Westerberg {
1980894fba7fSKai-Heng Feng 	sysfs_remove_file_from_group(&pdev->dev.kobj,
1981894fba7fSKai-Heng Feng 				     &dev_attr_remapped_nvme.attr,
1982894fba7fSKai-Heng Feng 				     NULL);
198302e53293SMika Westerberg 	pm_runtime_get_noresume(&pdev->dev);
198402e53293SMika Westerberg 	ata_pci_remove_one(pdev);
1985c6fd2807SJeff Garzik }
1986c6fd2807SJeff Garzik 
19872fc75da0SAxel Lin module_pci_driver(ahci_pci_driver);
1988c6fd2807SJeff Garzik 
1989c6fd2807SJeff Garzik MODULE_AUTHOR("Jeff Garzik");
1990c6fd2807SJeff Garzik MODULE_DESCRIPTION("AHCI SATA low-level driver");
1991c6fd2807SJeff Garzik MODULE_LICENSE("GPL");
1992c6fd2807SJeff Garzik MODULE_DEVICE_TABLE(pci, ahci_pci_tbl);
1993c6fd2807SJeff Garzik MODULE_VERSION(DRV_VERSION);
1994