xref: /openbmc/linux/drivers/ata/ahci.c (revision ff0173c1a3ce003e361a8045ded905c285c3f08f)
1c6fd2807SJeff Garzik /*
2c6fd2807SJeff Garzik  *  ahci.c - AHCI SATA support
3c6fd2807SJeff Garzik  *
4c6fd2807SJeff Garzik  *  Maintained by:  Jeff Garzik <jgarzik@pobox.com>
5c6fd2807SJeff Garzik  *    		    Please ALWAYS copy linux-ide@vger.kernel.org
6c6fd2807SJeff Garzik  *		    on emails.
7c6fd2807SJeff Garzik  *
8c6fd2807SJeff Garzik  *  Copyright 2004-2005 Red Hat, Inc.
9c6fd2807SJeff Garzik  *
10c6fd2807SJeff Garzik  *
11c6fd2807SJeff Garzik  *  This program is free software; you can redistribute it and/or modify
12c6fd2807SJeff Garzik  *  it under the terms of the GNU General Public License as published by
13c6fd2807SJeff Garzik  *  the Free Software Foundation; either version 2, or (at your option)
14c6fd2807SJeff Garzik  *  any later version.
15c6fd2807SJeff Garzik  *
16c6fd2807SJeff Garzik  *  This program is distributed in the hope that it will be useful,
17c6fd2807SJeff Garzik  *  but WITHOUT ANY WARRANTY; without even the implied warranty of
18c6fd2807SJeff Garzik  *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
19c6fd2807SJeff Garzik  *  GNU General Public License for more details.
20c6fd2807SJeff Garzik  *
21c6fd2807SJeff Garzik  *  You should have received a copy of the GNU General Public License
22c6fd2807SJeff Garzik  *  along with this program; see the file COPYING.  If not, write to
23c6fd2807SJeff Garzik  *  the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA.
24c6fd2807SJeff Garzik  *
25c6fd2807SJeff Garzik  *
26c6fd2807SJeff Garzik  * libata documentation is available via 'make {ps|pdf}docs',
27c6fd2807SJeff Garzik  * as Documentation/DocBook/libata.*
28c6fd2807SJeff Garzik  *
29c6fd2807SJeff Garzik  * AHCI hardware documentation:
30c6fd2807SJeff Garzik  * http://www.intel.com/technology/serialata/pdf/rev1_0.pdf
31c6fd2807SJeff Garzik  * http://www.intel.com/technology/serialata/pdf/rev1_1.pdf
32c6fd2807SJeff Garzik  *
33c6fd2807SJeff Garzik  */
34c6fd2807SJeff Garzik 
35c6fd2807SJeff Garzik #include <linux/kernel.h>
36c6fd2807SJeff Garzik #include <linux/module.h>
37c6fd2807SJeff Garzik #include <linux/pci.h>
38c6fd2807SJeff Garzik #include <linux/init.h>
39c6fd2807SJeff Garzik #include <linux/blkdev.h>
40c6fd2807SJeff Garzik #include <linux/delay.h>
41c6fd2807SJeff Garzik #include <linux/interrupt.h>
42c6fd2807SJeff Garzik #include <linux/dma-mapping.h>
43c6fd2807SJeff Garzik #include <linux/device.h>
44edc93052STejun Heo #include <linux/dmi.h>
455a0e3ad6STejun Heo #include <linux/gfp.h>
46c6fd2807SJeff Garzik #include <scsi/scsi_host.h>
47c6fd2807SJeff Garzik #include <scsi/scsi_cmnd.h>
48c6fd2807SJeff Garzik #include <linux/libata.h>
49365cfa1eSAnton Vorontsov #include "ahci.h"
50c6fd2807SJeff Garzik 
51c6fd2807SJeff Garzik #define DRV_NAME	"ahci"
527d50b60bSTejun Heo #define DRV_VERSION	"3.0"
53c6fd2807SJeff Garzik 
54c6fd2807SJeff Garzik enum {
55318893e1SAlessandro Rubini 	AHCI_PCI_BAR_STA2X11	= 0,
56318893e1SAlessandro Rubini 	AHCI_PCI_BAR_STANDARD	= 5,
57441577efSTejun Heo };
58c6fd2807SJeff Garzik 
59441577efSTejun Heo enum board_ids {
60441577efSTejun Heo 	/* board IDs by feature in alphabetical order */
61441577efSTejun Heo 	board_ahci,
62441577efSTejun Heo 	board_ahci_ign_iferr,
63441577efSTejun Heo 	board_ahci_nosntf,
645f173107STejun Heo 	board_ahci_yes_fbs,
65441577efSTejun Heo 
66441577efSTejun Heo 	/* board IDs for specific chipsets in alphabetical order */
67441577efSTejun Heo 	board_ahci_mcp65,
6883f2b963STejun Heo 	board_ahci_mcp77,
6983f2b963STejun Heo 	board_ahci_mcp89,
70441577efSTejun Heo 	board_ahci_mv,
71441577efSTejun Heo 	board_ahci_sb600,
72441577efSTejun Heo 	board_ahci_sb700,	/* for SB700 and SB800 */
73441577efSTejun Heo 	board_ahci_vt8251,
74441577efSTejun Heo 
75441577efSTejun Heo 	/* aliases */
76441577efSTejun Heo 	board_ahci_mcp_linux	= board_ahci_mcp65,
77441577efSTejun Heo 	board_ahci_mcp67	= board_ahci_mcp65,
78441577efSTejun Heo 	board_ahci_mcp73	= board_ahci_mcp65,
7983f2b963STejun Heo 	board_ahci_mcp79	= board_ahci_mcp77,
80c6fd2807SJeff Garzik };
81c6fd2807SJeff Garzik 
82c6fd2807SJeff Garzik static int ahci_init_one(struct pci_dev *pdev, const struct pci_device_id *ent);
83a1efdabaSTejun Heo static int ahci_vt8251_hardreset(struct ata_link *link, unsigned int *class,
84a1efdabaSTejun Heo 				 unsigned long deadline);
85a1efdabaSTejun Heo static int ahci_p5wdh_hardreset(struct ata_link *link, unsigned int *class,
86a1efdabaSTejun Heo 				unsigned long deadline);
87438ac6d5STejun Heo #ifdef CONFIG_PM
88c6fd2807SJeff Garzik static int ahci_pci_device_suspend(struct pci_dev *pdev, pm_message_t mesg);
89c6fd2807SJeff Garzik static int ahci_pci_device_resume(struct pci_dev *pdev);
90438ac6d5STejun Heo #endif
91c6fd2807SJeff Garzik 
92fad16e7aSTejun Heo static struct scsi_host_template ahci_sht = {
93fad16e7aSTejun Heo 	AHCI_SHT("ahci"),
94fad16e7aSTejun Heo };
95fad16e7aSTejun Heo 
96029cfd6bSTejun Heo static struct ata_port_operations ahci_vt8251_ops = {
97029cfd6bSTejun Heo 	.inherits		= &ahci_ops,
98a1efdabaSTejun Heo 	.hardreset		= ahci_vt8251_hardreset,
99ad616ffbSTejun Heo };
100ad616ffbSTejun Heo 
101029cfd6bSTejun Heo static struct ata_port_operations ahci_p5wdh_ops = {
102029cfd6bSTejun Heo 	.inherits		= &ahci_ops,
103a1efdabaSTejun Heo 	.hardreset		= ahci_p5wdh_hardreset,
104edc93052STejun Heo };
105edc93052STejun Heo 
106c6fd2807SJeff Garzik static const struct ata_port_info ahci_port_info[] = {
107441577efSTejun Heo 	/* by features */
1084da646b7SJeff Garzik 	[board_ahci] =
109c6fd2807SJeff Garzik 	{
1101188c0d8STejun Heo 		.flags		= AHCI_FLAG_COMMON,
11114bdef98SErik Inge Bolsø 		.pio_mask	= ATA_PIO4,
112469248abSJeff Garzik 		.udma_mask	= ATA_UDMA6,
113c6fd2807SJeff Garzik 		.port_ops	= &ahci_ops,
114c6fd2807SJeff Garzik 	},
1154da646b7SJeff Garzik 	[board_ahci_ign_iferr] =
11641669553STejun Heo 	{
117417a1a6dSTejun Heo 		AHCI_HFLAGS	(AHCI_HFLAG_IGN_IRQ_IF_ERR),
118417a1a6dSTejun Heo 		.flags		= AHCI_FLAG_COMMON,
11914bdef98SErik Inge Bolsø 		.pio_mask	= ATA_PIO4,
120469248abSJeff Garzik 		.udma_mask	= ATA_UDMA6,
12141669553STejun Heo 		.port_ops	= &ahci_ops,
12241669553STejun Heo 	},
123441577efSTejun Heo 	[board_ahci_nosntf] =
124441577efSTejun Heo 	{
125441577efSTejun Heo 		AHCI_HFLAGS	(AHCI_HFLAG_NO_SNTF),
126441577efSTejun Heo 		.flags		= AHCI_FLAG_COMMON,
127441577efSTejun Heo 		.pio_mask	= ATA_PIO4,
128441577efSTejun Heo 		.udma_mask	= ATA_UDMA6,
129441577efSTejun Heo 		.port_ops	= &ahci_ops,
130441577efSTejun Heo 	},
1315f173107STejun Heo 	[board_ahci_yes_fbs] =
1325f173107STejun Heo 	{
1335f173107STejun Heo 		AHCI_HFLAGS	(AHCI_HFLAG_YES_FBS),
1345f173107STejun Heo 		.flags		= AHCI_FLAG_COMMON,
1355f173107STejun Heo 		.pio_mask	= ATA_PIO4,
1365f173107STejun Heo 		.udma_mask	= ATA_UDMA6,
1375f173107STejun Heo 		.port_ops	= &ahci_ops,
1385f173107STejun Heo 	},
139441577efSTejun Heo 	/* by chipsets */
140441577efSTejun Heo 	[board_ahci_mcp65] =
141441577efSTejun Heo 	{
14283f2b963STejun Heo 		AHCI_HFLAGS	(AHCI_HFLAG_NO_FPDMA_AA | AHCI_HFLAG_NO_PMP |
14383f2b963STejun Heo 				 AHCI_HFLAG_YES_NCQ),
144ae01b249STejun Heo 		.flags		= AHCI_FLAG_COMMON | ATA_FLAG_NO_DIPM,
14583f2b963STejun Heo 		.pio_mask	= ATA_PIO4,
14683f2b963STejun Heo 		.udma_mask	= ATA_UDMA6,
14783f2b963STejun Heo 		.port_ops	= &ahci_ops,
14883f2b963STejun Heo 	},
14983f2b963STejun Heo 	[board_ahci_mcp77] =
15083f2b963STejun Heo 	{
15183f2b963STejun Heo 		AHCI_HFLAGS	(AHCI_HFLAG_NO_FPDMA_AA | AHCI_HFLAG_NO_PMP),
15283f2b963STejun Heo 		.flags		= AHCI_FLAG_COMMON,
15383f2b963STejun Heo 		.pio_mask	= ATA_PIO4,
15483f2b963STejun Heo 		.udma_mask	= ATA_UDMA6,
15583f2b963STejun Heo 		.port_ops	= &ahci_ops,
15683f2b963STejun Heo 	},
15783f2b963STejun Heo 	[board_ahci_mcp89] =
15883f2b963STejun Heo 	{
15983f2b963STejun Heo 		AHCI_HFLAGS	(AHCI_HFLAG_NO_FPDMA_AA),
160441577efSTejun Heo 		.flags		= AHCI_FLAG_COMMON,
161441577efSTejun Heo 		.pio_mask	= ATA_PIO4,
162441577efSTejun Heo 		.udma_mask	= ATA_UDMA6,
163441577efSTejun Heo 		.port_ops	= &ahci_ops,
164441577efSTejun Heo 	},
165441577efSTejun Heo 	[board_ahci_mv] =
166441577efSTejun Heo 	{
167441577efSTejun Heo 		AHCI_HFLAGS	(AHCI_HFLAG_NO_NCQ | AHCI_HFLAG_NO_MSI |
168441577efSTejun Heo 				 AHCI_HFLAG_MV_PATA | AHCI_HFLAG_NO_PMP),
1699cbe056fSSergei Shtylyov 		.flags		= ATA_FLAG_SATA | ATA_FLAG_PIO_DMA,
170441577efSTejun Heo 		.pio_mask	= ATA_PIO4,
171441577efSTejun Heo 		.udma_mask	= ATA_UDMA6,
172441577efSTejun Heo 		.port_ops	= &ahci_ops,
173441577efSTejun Heo 	},
1744da646b7SJeff Garzik 	[board_ahci_sb600] =
17555a61604SConke Hu 	{
176417a1a6dSTejun Heo 		AHCI_HFLAGS	(AHCI_HFLAG_IGN_SERR_INTERNAL |
1772fcad9d2STejun Heo 				 AHCI_HFLAG_NO_MSI | AHCI_HFLAG_SECT255 |
1782fcad9d2STejun Heo 				 AHCI_HFLAG_32BIT_ONLY),
179417a1a6dSTejun Heo 		.flags		= AHCI_FLAG_COMMON,
18014bdef98SErik Inge Bolsø 		.pio_mask	= ATA_PIO4,
181469248abSJeff Garzik 		.udma_mask	= ATA_UDMA6,
182345347c5SYuan-Hsin Chen 		.port_ops	= &ahci_pmp_retry_srst_ops,
18355a61604SConke Hu 	},
1844da646b7SJeff Garzik 	[board_ahci_sb700] =	/* for SB700 and SB800 */
185e39fc8c9SShane Huang 	{
186bd17243aSShane Huang 		AHCI_HFLAGS	(AHCI_HFLAG_IGN_SERR_INTERNAL),
187e39fc8c9SShane Huang 		.flags		= AHCI_FLAG_COMMON,
18814bdef98SErik Inge Bolsø 		.pio_mask	= ATA_PIO4,
189e39fc8c9SShane Huang 		.udma_mask	= ATA_UDMA6,
190345347c5SYuan-Hsin Chen 		.port_ops	= &ahci_pmp_retry_srst_ops,
191e39fc8c9SShane Huang 	},
192441577efSTejun Heo 	[board_ahci_vt8251] =
193e297d99eSTejun Heo 	{
194441577efSTejun Heo 		AHCI_HFLAGS	(AHCI_HFLAG_NO_NCQ | AHCI_HFLAG_NO_PMP),
195e297d99eSTejun Heo 		.flags		= AHCI_FLAG_COMMON,
19614bdef98SErik Inge Bolsø 		.pio_mask	= ATA_PIO4,
197e297d99eSTejun Heo 		.udma_mask	= ATA_UDMA6,
198441577efSTejun Heo 		.port_ops	= &ahci_vt8251_ops,
1991b677afdSShaohua Li 	},
200c6fd2807SJeff Garzik };
201c6fd2807SJeff Garzik 
202c6fd2807SJeff Garzik static const struct pci_device_id ahci_pci_tbl[] = {
203c6fd2807SJeff Garzik 	/* Intel */
20454bb3a94SJeff Garzik 	{ PCI_VDEVICE(INTEL, 0x2652), board_ahci }, /* ICH6 */
20554bb3a94SJeff Garzik 	{ PCI_VDEVICE(INTEL, 0x2653), board_ahci }, /* ICH6M */
20654bb3a94SJeff Garzik 	{ PCI_VDEVICE(INTEL, 0x27c1), board_ahci }, /* ICH7 */
20754bb3a94SJeff Garzik 	{ PCI_VDEVICE(INTEL, 0x27c5), board_ahci }, /* ICH7M */
20854bb3a94SJeff Garzik 	{ PCI_VDEVICE(INTEL, 0x27c3), board_ahci }, /* ICH7R */
20982490c09STejun Heo 	{ PCI_VDEVICE(AL, 0x5288), board_ahci_ign_iferr }, /* ULi M5288 */
21054bb3a94SJeff Garzik 	{ PCI_VDEVICE(INTEL, 0x2681), board_ahci }, /* ESB2 */
21154bb3a94SJeff Garzik 	{ PCI_VDEVICE(INTEL, 0x2682), board_ahci }, /* ESB2 */
21254bb3a94SJeff Garzik 	{ PCI_VDEVICE(INTEL, 0x2683), board_ahci }, /* ESB2 */
21354bb3a94SJeff Garzik 	{ PCI_VDEVICE(INTEL, 0x27c6), board_ahci }, /* ICH7-M DH */
2147a234affSTejun Heo 	{ PCI_VDEVICE(INTEL, 0x2821), board_ahci }, /* ICH8 */
2151b677afdSShaohua Li 	{ PCI_VDEVICE(INTEL, 0x2822), board_ahci_nosntf }, /* ICH8 */
2167a234affSTejun Heo 	{ PCI_VDEVICE(INTEL, 0x2824), board_ahci }, /* ICH8 */
2177a234affSTejun Heo 	{ PCI_VDEVICE(INTEL, 0x2829), board_ahci }, /* ICH8M */
2187a234affSTejun Heo 	{ PCI_VDEVICE(INTEL, 0x282a), board_ahci }, /* ICH8M */
2197a234affSTejun Heo 	{ PCI_VDEVICE(INTEL, 0x2922), board_ahci }, /* ICH9 */
2207a234affSTejun Heo 	{ PCI_VDEVICE(INTEL, 0x2923), board_ahci }, /* ICH9 */
2217a234affSTejun Heo 	{ PCI_VDEVICE(INTEL, 0x2924), board_ahci }, /* ICH9 */
2227a234affSTejun Heo 	{ PCI_VDEVICE(INTEL, 0x2925), board_ahci }, /* ICH9 */
2237a234affSTejun Heo 	{ PCI_VDEVICE(INTEL, 0x2927), board_ahci }, /* ICH9 */
2247a234affSTejun Heo 	{ PCI_VDEVICE(INTEL, 0x2929), board_ahci }, /* ICH9M */
2257a234affSTejun Heo 	{ PCI_VDEVICE(INTEL, 0x292a), board_ahci }, /* ICH9M */
2267a234affSTejun Heo 	{ PCI_VDEVICE(INTEL, 0x292b), board_ahci }, /* ICH9M */
2277a234affSTejun Heo 	{ PCI_VDEVICE(INTEL, 0x292c), board_ahci }, /* ICH9M */
2287a234affSTejun Heo 	{ PCI_VDEVICE(INTEL, 0x292f), board_ahci }, /* ICH9M */
2297a234affSTejun Heo 	{ PCI_VDEVICE(INTEL, 0x294d), board_ahci }, /* ICH9 */
2307a234affSTejun Heo 	{ PCI_VDEVICE(INTEL, 0x294e), board_ahci }, /* ICH9M */
231d4155e6fSJason Gaston 	{ PCI_VDEVICE(INTEL, 0x502a), board_ahci }, /* Tolapai */
232d4155e6fSJason Gaston 	{ PCI_VDEVICE(INTEL, 0x502b), board_ahci }, /* Tolapai */
23316ad1ad9SJason Gaston 	{ PCI_VDEVICE(INTEL, 0x3a05), board_ahci }, /* ICH10 */
234b2dde6afSMark Goodwin 	{ PCI_VDEVICE(INTEL, 0x3a22), board_ahci }, /* ICH10 */
23516ad1ad9SJason Gaston 	{ PCI_VDEVICE(INTEL, 0x3a25), board_ahci }, /* ICH10 */
236c1f57d9bSDavid Milburn 	{ PCI_VDEVICE(INTEL, 0x3b22), board_ahci }, /* PCH AHCI */
237c1f57d9bSDavid Milburn 	{ PCI_VDEVICE(INTEL, 0x3b23), board_ahci }, /* PCH AHCI */
238adcb5308SSeth Heasley 	{ PCI_VDEVICE(INTEL, 0x3b24), board_ahci }, /* PCH RAID */
2398e48b6b3SSeth Heasley 	{ PCI_VDEVICE(INTEL, 0x3b25), board_ahci }, /* PCH RAID */
240c1f57d9bSDavid Milburn 	{ PCI_VDEVICE(INTEL, 0x3b29), board_ahci }, /* PCH AHCI */
241adcb5308SSeth Heasley 	{ PCI_VDEVICE(INTEL, 0x3b2b), board_ahci }, /* PCH RAID */
2428e48b6b3SSeth Heasley 	{ PCI_VDEVICE(INTEL, 0x3b2c), board_ahci }, /* PCH RAID */
243c1f57d9bSDavid Milburn 	{ PCI_VDEVICE(INTEL, 0x3b2f), board_ahci }, /* PCH AHCI */
2445623cab8SSeth Heasley 	{ PCI_VDEVICE(INTEL, 0x1c02), board_ahci }, /* CPT AHCI */
2455623cab8SSeth Heasley 	{ PCI_VDEVICE(INTEL, 0x1c03), board_ahci }, /* CPT AHCI */
2465623cab8SSeth Heasley 	{ PCI_VDEVICE(INTEL, 0x1c04), board_ahci }, /* CPT RAID */
2475623cab8SSeth Heasley 	{ PCI_VDEVICE(INTEL, 0x1c05), board_ahci }, /* CPT RAID */
2485623cab8SSeth Heasley 	{ PCI_VDEVICE(INTEL, 0x1c06), board_ahci }, /* CPT RAID */
2495623cab8SSeth Heasley 	{ PCI_VDEVICE(INTEL, 0x1c07), board_ahci }, /* CPT RAID */
250992b3fb9SSeth Heasley 	{ PCI_VDEVICE(INTEL, 0x1d02), board_ahci }, /* PBG AHCI */
251992b3fb9SSeth Heasley 	{ PCI_VDEVICE(INTEL, 0x1d04), board_ahci }, /* PBG RAID */
252992b3fb9SSeth Heasley 	{ PCI_VDEVICE(INTEL, 0x1d06), board_ahci }, /* PBG RAID */
25364a3903dSSeth Heasley 	{ PCI_VDEVICE(INTEL, 0x2826), board_ahci }, /* PBG RAID */
254a4a461a6SSeth Heasley 	{ PCI_VDEVICE(INTEL, 0x2323), board_ahci }, /* DH89xxCC AHCI */
255181e3ceaSSeth Heasley 	{ PCI_VDEVICE(INTEL, 0x1e02), board_ahci }, /* Panther Point AHCI */
256181e3ceaSSeth Heasley 	{ PCI_VDEVICE(INTEL, 0x1e03), board_ahci }, /* Panther Point AHCI */
257181e3ceaSSeth Heasley 	{ PCI_VDEVICE(INTEL, 0x1e04), board_ahci }, /* Panther Point RAID */
258181e3ceaSSeth Heasley 	{ PCI_VDEVICE(INTEL, 0x1e05), board_ahci }, /* Panther Point RAID */
259181e3ceaSSeth Heasley 	{ PCI_VDEVICE(INTEL, 0x1e06), board_ahci }, /* Panther Point RAID */
260181e3ceaSSeth Heasley 	{ PCI_VDEVICE(INTEL, 0x1e07), board_ahci }, /* Panther Point RAID */
2612cab7a4cSSeth Heasley 	{ PCI_VDEVICE(INTEL, 0x1e0e), board_ahci }, /* Panther Point RAID */
262ea4ace66SSeth Heasley 	{ PCI_VDEVICE(INTEL, 0x8c02), board_ahci }, /* Lynx Point AHCI */
263ea4ace66SSeth Heasley 	{ PCI_VDEVICE(INTEL, 0x8c03), board_ahci }, /* Lynx Point AHCI */
264ea4ace66SSeth Heasley 	{ PCI_VDEVICE(INTEL, 0x8c04), board_ahci }, /* Lynx Point RAID */
265ea4ace66SSeth Heasley 	{ PCI_VDEVICE(INTEL, 0x8c05), board_ahci }, /* Lynx Point RAID */
266ea4ace66SSeth Heasley 	{ PCI_VDEVICE(INTEL, 0x8c06), board_ahci }, /* Lynx Point RAID */
267ea4ace66SSeth Heasley 	{ PCI_VDEVICE(INTEL, 0x8c07), board_ahci }, /* Lynx Point RAID */
268ea4ace66SSeth Heasley 	{ PCI_VDEVICE(INTEL, 0x8c0e), board_ahci }, /* Lynx Point RAID */
269ea4ace66SSeth Heasley 	{ PCI_VDEVICE(INTEL, 0x8c0f), board_ahci }, /* Lynx Point RAID */
270c6fd2807SJeff Garzik 
271e34bb370STejun Heo 	/* JMicron 360/1/3/5/6, match class to avoid IDE function */
272e34bb370STejun Heo 	{ PCI_VENDOR_ID_JMICRON, PCI_ANY_ID, PCI_ANY_ID, PCI_ANY_ID,
273e34bb370STejun Heo 	  PCI_CLASS_STORAGE_SATA_AHCI, 0xffffff, board_ahci_ign_iferr },
274c6fd2807SJeff Garzik 
275c6fd2807SJeff Garzik 	/* ATI */
276c65ec1c2SConke Hu 	{ PCI_VDEVICE(ATI, 0x4380), board_ahci_sb600 }, /* ATI SB600 */
277e39fc8c9SShane Huang 	{ PCI_VDEVICE(ATI, 0x4390), board_ahci_sb700 }, /* ATI SB700/800 */
278e39fc8c9SShane Huang 	{ PCI_VDEVICE(ATI, 0x4391), board_ahci_sb700 }, /* ATI SB700/800 */
279e39fc8c9SShane Huang 	{ PCI_VDEVICE(ATI, 0x4392), board_ahci_sb700 }, /* ATI SB700/800 */
280e39fc8c9SShane Huang 	{ PCI_VDEVICE(ATI, 0x4393), board_ahci_sb700 }, /* ATI SB700/800 */
281e39fc8c9SShane Huang 	{ PCI_VDEVICE(ATI, 0x4394), board_ahci_sb700 }, /* ATI SB700/800 */
282e39fc8c9SShane Huang 	{ PCI_VDEVICE(ATI, 0x4395), board_ahci_sb700 }, /* ATI SB700/800 */
283c6fd2807SJeff Garzik 
284e2dd90b1SShane Huang 	/* AMD */
2855deab536SShane Huang 	{ PCI_VDEVICE(AMD, 0x7800), board_ahci }, /* AMD Hudson-2 */
286e2dd90b1SShane Huang 	/* AMD is using RAID class only for ahci controllers */
287e2dd90b1SShane Huang 	{ PCI_VENDOR_ID_AMD, PCI_ANY_ID, PCI_ANY_ID, PCI_ANY_ID,
288e2dd90b1SShane Huang 	  PCI_CLASS_STORAGE_RAID << 8, 0xffffff, board_ahci },
289e2dd90b1SShane Huang 
290c6fd2807SJeff Garzik 	/* VIA */
29154bb3a94SJeff Garzik 	{ PCI_VDEVICE(VIA, 0x3349), board_ahci_vt8251 }, /* VIA VT8251 */
292bf335542STejun Heo 	{ PCI_VDEVICE(VIA, 0x6287), board_ahci_vt8251 }, /* VIA VT8251 */
293c6fd2807SJeff Garzik 
294c6fd2807SJeff Garzik 	/* NVIDIA */
295e297d99eSTejun Heo 	{ PCI_VDEVICE(NVIDIA, 0x044c), board_ahci_mcp65 },	/* MCP65 */
296e297d99eSTejun Heo 	{ PCI_VDEVICE(NVIDIA, 0x044d), board_ahci_mcp65 },	/* MCP65 */
297e297d99eSTejun Heo 	{ PCI_VDEVICE(NVIDIA, 0x044e), board_ahci_mcp65 },	/* MCP65 */
298e297d99eSTejun Heo 	{ PCI_VDEVICE(NVIDIA, 0x044f), board_ahci_mcp65 },	/* MCP65 */
299e297d99eSTejun Heo 	{ PCI_VDEVICE(NVIDIA, 0x045c), board_ahci_mcp65 },	/* MCP65 */
300e297d99eSTejun Heo 	{ PCI_VDEVICE(NVIDIA, 0x045d), board_ahci_mcp65 },	/* MCP65 */
301e297d99eSTejun Heo 	{ PCI_VDEVICE(NVIDIA, 0x045e), board_ahci_mcp65 },	/* MCP65 */
302e297d99eSTejun Heo 	{ PCI_VDEVICE(NVIDIA, 0x045f), board_ahci_mcp65 },	/* MCP65 */
303441577efSTejun Heo 	{ PCI_VDEVICE(NVIDIA, 0x0550), board_ahci_mcp67 },	/* MCP67 */
304441577efSTejun Heo 	{ PCI_VDEVICE(NVIDIA, 0x0551), board_ahci_mcp67 },	/* MCP67 */
305441577efSTejun Heo 	{ PCI_VDEVICE(NVIDIA, 0x0552), board_ahci_mcp67 },	/* MCP67 */
306441577efSTejun Heo 	{ PCI_VDEVICE(NVIDIA, 0x0553), board_ahci_mcp67 },	/* MCP67 */
307441577efSTejun Heo 	{ PCI_VDEVICE(NVIDIA, 0x0554), board_ahci_mcp67 },	/* MCP67 */
308441577efSTejun Heo 	{ PCI_VDEVICE(NVIDIA, 0x0555), board_ahci_mcp67 },	/* MCP67 */
309441577efSTejun Heo 	{ PCI_VDEVICE(NVIDIA, 0x0556), board_ahci_mcp67 },	/* MCP67 */
310441577efSTejun Heo 	{ PCI_VDEVICE(NVIDIA, 0x0557), board_ahci_mcp67 },	/* MCP67 */
311441577efSTejun Heo 	{ PCI_VDEVICE(NVIDIA, 0x0558), board_ahci_mcp67 },	/* MCP67 */
312441577efSTejun Heo 	{ PCI_VDEVICE(NVIDIA, 0x0559), board_ahci_mcp67 },	/* MCP67 */
313441577efSTejun Heo 	{ PCI_VDEVICE(NVIDIA, 0x055a), board_ahci_mcp67 },	/* MCP67 */
314441577efSTejun Heo 	{ PCI_VDEVICE(NVIDIA, 0x055b), board_ahci_mcp67 },	/* MCP67 */
315441577efSTejun Heo 	{ PCI_VDEVICE(NVIDIA, 0x0580), board_ahci_mcp_linux },	/* Linux ID */
316441577efSTejun Heo 	{ PCI_VDEVICE(NVIDIA, 0x0581), board_ahci_mcp_linux },	/* Linux ID */
317441577efSTejun Heo 	{ PCI_VDEVICE(NVIDIA, 0x0582), board_ahci_mcp_linux },	/* Linux ID */
318441577efSTejun Heo 	{ PCI_VDEVICE(NVIDIA, 0x0583), board_ahci_mcp_linux },	/* Linux ID */
319441577efSTejun Heo 	{ PCI_VDEVICE(NVIDIA, 0x0584), board_ahci_mcp_linux },	/* Linux ID */
320441577efSTejun Heo 	{ PCI_VDEVICE(NVIDIA, 0x0585), board_ahci_mcp_linux },	/* Linux ID */
321441577efSTejun Heo 	{ PCI_VDEVICE(NVIDIA, 0x0586), board_ahci_mcp_linux },	/* Linux ID */
322441577efSTejun Heo 	{ PCI_VDEVICE(NVIDIA, 0x0587), board_ahci_mcp_linux },	/* Linux ID */
323441577efSTejun Heo 	{ PCI_VDEVICE(NVIDIA, 0x0588), board_ahci_mcp_linux },	/* Linux ID */
324441577efSTejun Heo 	{ PCI_VDEVICE(NVIDIA, 0x0589), board_ahci_mcp_linux },	/* Linux ID */
325441577efSTejun Heo 	{ PCI_VDEVICE(NVIDIA, 0x058a), board_ahci_mcp_linux },	/* Linux ID */
326441577efSTejun Heo 	{ PCI_VDEVICE(NVIDIA, 0x058b), board_ahci_mcp_linux },	/* Linux ID */
327441577efSTejun Heo 	{ PCI_VDEVICE(NVIDIA, 0x058c), board_ahci_mcp_linux },	/* Linux ID */
328441577efSTejun Heo 	{ PCI_VDEVICE(NVIDIA, 0x058d), board_ahci_mcp_linux },	/* Linux ID */
329441577efSTejun Heo 	{ PCI_VDEVICE(NVIDIA, 0x058e), board_ahci_mcp_linux },	/* Linux ID */
330441577efSTejun Heo 	{ PCI_VDEVICE(NVIDIA, 0x058f), board_ahci_mcp_linux },	/* Linux ID */
331441577efSTejun Heo 	{ PCI_VDEVICE(NVIDIA, 0x07f0), board_ahci_mcp73 },	/* MCP73 */
332441577efSTejun Heo 	{ PCI_VDEVICE(NVIDIA, 0x07f1), board_ahci_mcp73 },	/* MCP73 */
333441577efSTejun Heo 	{ PCI_VDEVICE(NVIDIA, 0x07f2), board_ahci_mcp73 },	/* MCP73 */
334441577efSTejun Heo 	{ PCI_VDEVICE(NVIDIA, 0x07f3), board_ahci_mcp73 },	/* MCP73 */
335441577efSTejun Heo 	{ PCI_VDEVICE(NVIDIA, 0x07f4), board_ahci_mcp73 },	/* MCP73 */
336441577efSTejun Heo 	{ PCI_VDEVICE(NVIDIA, 0x07f5), board_ahci_mcp73 },	/* MCP73 */
337441577efSTejun Heo 	{ PCI_VDEVICE(NVIDIA, 0x07f6), board_ahci_mcp73 },	/* MCP73 */
338441577efSTejun Heo 	{ PCI_VDEVICE(NVIDIA, 0x07f7), board_ahci_mcp73 },	/* MCP73 */
339441577efSTejun Heo 	{ PCI_VDEVICE(NVIDIA, 0x07f8), board_ahci_mcp73 },	/* MCP73 */
340441577efSTejun Heo 	{ PCI_VDEVICE(NVIDIA, 0x07f9), board_ahci_mcp73 },	/* MCP73 */
341441577efSTejun Heo 	{ PCI_VDEVICE(NVIDIA, 0x07fa), board_ahci_mcp73 },	/* MCP73 */
342441577efSTejun Heo 	{ PCI_VDEVICE(NVIDIA, 0x07fb), board_ahci_mcp73 },	/* MCP73 */
343441577efSTejun Heo 	{ PCI_VDEVICE(NVIDIA, 0x0ad0), board_ahci_mcp77 },	/* MCP77 */
344441577efSTejun Heo 	{ PCI_VDEVICE(NVIDIA, 0x0ad1), board_ahci_mcp77 },	/* MCP77 */
345441577efSTejun Heo 	{ PCI_VDEVICE(NVIDIA, 0x0ad2), board_ahci_mcp77 },	/* MCP77 */
346441577efSTejun Heo 	{ PCI_VDEVICE(NVIDIA, 0x0ad3), board_ahci_mcp77 },	/* MCP77 */
347441577efSTejun Heo 	{ PCI_VDEVICE(NVIDIA, 0x0ad4), board_ahci_mcp77 },	/* MCP77 */
348441577efSTejun Heo 	{ PCI_VDEVICE(NVIDIA, 0x0ad5), board_ahci_mcp77 },	/* MCP77 */
349441577efSTejun Heo 	{ PCI_VDEVICE(NVIDIA, 0x0ad6), board_ahci_mcp77 },	/* MCP77 */
350441577efSTejun Heo 	{ PCI_VDEVICE(NVIDIA, 0x0ad7), board_ahci_mcp77 },	/* MCP77 */
351441577efSTejun Heo 	{ PCI_VDEVICE(NVIDIA, 0x0ad8), board_ahci_mcp77 },	/* MCP77 */
352441577efSTejun Heo 	{ PCI_VDEVICE(NVIDIA, 0x0ad9), board_ahci_mcp77 },	/* MCP77 */
353441577efSTejun Heo 	{ PCI_VDEVICE(NVIDIA, 0x0ada), board_ahci_mcp77 },	/* MCP77 */
354441577efSTejun Heo 	{ PCI_VDEVICE(NVIDIA, 0x0adb), board_ahci_mcp77 },	/* MCP77 */
355441577efSTejun Heo 	{ PCI_VDEVICE(NVIDIA, 0x0ab4), board_ahci_mcp79 },	/* MCP79 */
356441577efSTejun Heo 	{ PCI_VDEVICE(NVIDIA, 0x0ab5), board_ahci_mcp79 },	/* MCP79 */
357441577efSTejun Heo 	{ PCI_VDEVICE(NVIDIA, 0x0ab6), board_ahci_mcp79 },	/* MCP79 */
358441577efSTejun Heo 	{ PCI_VDEVICE(NVIDIA, 0x0ab7), board_ahci_mcp79 },	/* MCP79 */
359441577efSTejun Heo 	{ PCI_VDEVICE(NVIDIA, 0x0ab8), board_ahci_mcp79 },	/* MCP79 */
360441577efSTejun Heo 	{ PCI_VDEVICE(NVIDIA, 0x0ab9), board_ahci_mcp79 },	/* MCP79 */
361441577efSTejun Heo 	{ PCI_VDEVICE(NVIDIA, 0x0aba), board_ahci_mcp79 },	/* MCP79 */
362441577efSTejun Heo 	{ PCI_VDEVICE(NVIDIA, 0x0abb), board_ahci_mcp79 },	/* MCP79 */
363441577efSTejun Heo 	{ PCI_VDEVICE(NVIDIA, 0x0abc), board_ahci_mcp79 },	/* MCP79 */
364441577efSTejun Heo 	{ PCI_VDEVICE(NVIDIA, 0x0abd), board_ahci_mcp79 },	/* MCP79 */
365441577efSTejun Heo 	{ PCI_VDEVICE(NVIDIA, 0x0abe), board_ahci_mcp79 },	/* MCP79 */
366441577efSTejun Heo 	{ PCI_VDEVICE(NVIDIA, 0x0abf), board_ahci_mcp79 },	/* MCP79 */
367441577efSTejun Heo 	{ PCI_VDEVICE(NVIDIA, 0x0d84), board_ahci_mcp89 },	/* MCP89 */
368441577efSTejun Heo 	{ PCI_VDEVICE(NVIDIA, 0x0d85), board_ahci_mcp89 },	/* MCP89 */
369441577efSTejun Heo 	{ PCI_VDEVICE(NVIDIA, 0x0d86), board_ahci_mcp89 },	/* MCP89 */
370441577efSTejun Heo 	{ PCI_VDEVICE(NVIDIA, 0x0d87), board_ahci_mcp89 },	/* MCP89 */
371441577efSTejun Heo 	{ PCI_VDEVICE(NVIDIA, 0x0d88), board_ahci_mcp89 },	/* MCP89 */
372441577efSTejun Heo 	{ PCI_VDEVICE(NVIDIA, 0x0d89), board_ahci_mcp89 },	/* MCP89 */
373441577efSTejun Heo 	{ PCI_VDEVICE(NVIDIA, 0x0d8a), board_ahci_mcp89 },	/* MCP89 */
374441577efSTejun Heo 	{ PCI_VDEVICE(NVIDIA, 0x0d8b), board_ahci_mcp89 },	/* MCP89 */
375441577efSTejun Heo 	{ PCI_VDEVICE(NVIDIA, 0x0d8c), board_ahci_mcp89 },	/* MCP89 */
376441577efSTejun Heo 	{ PCI_VDEVICE(NVIDIA, 0x0d8d), board_ahci_mcp89 },	/* MCP89 */
377441577efSTejun Heo 	{ PCI_VDEVICE(NVIDIA, 0x0d8e), board_ahci_mcp89 },	/* MCP89 */
378441577efSTejun Heo 	{ PCI_VDEVICE(NVIDIA, 0x0d8f), board_ahci_mcp89 },	/* MCP89 */
379c6fd2807SJeff Garzik 
380c6fd2807SJeff Garzik 	/* SiS */
38120e2de4aSTejun Heo 	{ PCI_VDEVICE(SI, 0x1184), board_ahci },		/* SiS 966 */
38220e2de4aSTejun Heo 	{ PCI_VDEVICE(SI, 0x1185), board_ahci },		/* SiS 968 */
38320e2de4aSTejun Heo 	{ PCI_VDEVICE(SI, 0x0186), board_ahci },		/* SiS 968 */
384c6fd2807SJeff Garzik 
385318893e1SAlessandro Rubini 	/* ST Microelectronics */
386318893e1SAlessandro Rubini 	{ PCI_VDEVICE(STMICRO, 0xCC06), board_ahci },		/* ST ConneXt */
387318893e1SAlessandro Rubini 
388cd70c266SJeff Garzik 	/* Marvell */
389cd70c266SJeff Garzik 	{ PCI_VDEVICE(MARVELL, 0x6145), board_ahci_mv },	/* 6145 */
390c40e7cb8SJose Alberto Reguero 	{ PCI_VDEVICE(MARVELL, 0x6121), board_ahci_mv },	/* 6121 */
3915f173107STejun Heo 	{ PCI_DEVICE(0x1b4b, 0x9123),
39210aca06cSAnssi Hannula 	  .class = PCI_CLASS_STORAGE_SATA_AHCI,
39310aca06cSAnssi Hannula 	  .class_mask = 0xffffff,
3945f173107STejun Heo 	  .driver_data = board_ahci_yes_fbs },			/* 88se9128 */
395467b41c6SPer Jessen 	{ PCI_DEVICE(0x1b4b, 0x9125),
396467b41c6SPer Jessen 	  .driver_data = board_ahci_yes_fbs },			/* 88se9125 */
397642d8925SMatt Johnson 	{ PCI_DEVICE(0x1b4b, 0x917a),
398642d8925SMatt Johnson 	  .driver_data = board_ahci_yes_fbs },			/* 88se9172 */
39950be5e36STejun Heo 	{ PCI_DEVICE(0x1b4b, 0x91a3),
40050be5e36STejun Heo 	  .driver_data = board_ahci_yes_fbs },
401cd70c266SJeff Garzik 
402c77a036bSMark Nelson 	/* Promise */
403c77a036bSMark Nelson 	{ PCI_VDEVICE(PROMISE, 0x3f20), board_ahci },	/* PDC42819 */
404c77a036bSMark Nelson 
405c9703765SKeng-Yu Lin 	/* Asmedia */
406c9703765SKeng-Yu Lin 	{ PCI_VDEVICE(ASMEDIA, 0x0612), board_ahci },	/* ASM1061 */
407c9703765SKeng-Yu Lin 
408415ae2b5SJeff Garzik 	/* Generic, PCI class code for AHCI */
409415ae2b5SJeff Garzik 	{ PCI_ANY_ID, PCI_ANY_ID, PCI_ANY_ID, PCI_ANY_ID,
410c9f89475SConke Hu 	  PCI_CLASS_STORAGE_SATA_AHCI, 0xffffff, board_ahci },
411415ae2b5SJeff Garzik 
412c6fd2807SJeff Garzik 	{ }	/* terminate list */
413c6fd2807SJeff Garzik };
414c6fd2807SJeff Garzik 
415c6fd2807SJeff Garzik 
416c6fd2807SJeff Garzik static struct pci_driver ahci_pci_driver = {
417c6fd2807SJeff Garzik 	.name			= DRV_NAME,
418c6fd2807SJeff Garzik 	.id_table		= ahci_pci_tbl,
419c6fd2807SJeff Garzik 	.probe			= ahci_init_one,
42024dc5f33STejun Heo 	.remove			= ata_pci_remove_one,
421438ac6d5STejun Heo #ifdef CONFIG_PM
422c6fd2807SJeff Garzik 	.suspend		= ahci_pci_device_suspend,
423c6fd2807SJeff Garzik 	.resume			= ahci_pci_device_resume,
424438ac6d5STejun Heo #endif
425c6fd2807SJeff Garzik };
426c6fd2807SJeff Garzik 
4275b66c829SAlan Cox #if defined(CONFIG_PATA_MARVELL) || defined(CONFIG_PATA_MARVELL_MODULE)
4285b66c829SAlan Cox static int marvell_enable;
4295b66c829SAlan Cox #else
4305b66c829SAlan Cox static int marvell_enable = 1;
4315b66c829SAlan Cox #endif
4325b66c829SAlan Cox module_param(marvell_enable, int, 0644);
4335b66c829SAlan Cox MODULE_PARM_DESC(marvell_enable, "Marvell SATA via AHCI (1 = enabled)");
4345b66c829SAlan Cox 
4355b66c829SAlan Cox 
436394d6e53SAnton Vorontsov static void ahci_pci_save_initial_config(struct pci_dev *pdev,
437394d6e53SAnton Vorontsov 					 struct ahci_host_priv *hpriv)
438394d6e53SAnton Vorontsov {
439394d6e53SAnton Vorontsov 	unsigned int force_port_map = 0;
440394d6e53SAnton Vorontsov 	unsigned int mask_port_map = 0;
441394d6e53SAnton Vorontsov 
442394d6e53SAnton Vorontsov 	if (pdev->vendor == PCI_VENDOR_ID_JMICRON && pdev->device == 0x2361) {
443394d6e53SAnton Vorontsov 		dev_info(&pdev->dev, "JMB361 has only one port\n");
444394d6e53SAnton Vorontsov 		force_port_map = 1;
445394d6e53SAnton Vorontsov 	}
446394d6e53SAnton Vorontsov 
447394d6e53SAnton Vorontsov 	/*
448394d6e53SAnton Vorontsov 	 * Temporary Marvell 6145 hack: PATA port presence
449394d6e53SAnton Vorontsov 	 * is asserted through the standard AHCI port
450394d6e53SAnton Vorontsov 	 * presence register, as bit 4 (counting from 0)
451394d6e53SAnton Vorontsov 	 */
452394d6e53SAnton Vorontsov 	if (hpriv->flags & AHCI_HFLAG_MV_PATA) {
453394d6e53SAnton Vorontsov 		if (pdev->device == 0x6121)
454394d6e53SAnton Vorontsov 			mask_port_map = 0x3;
455394d6e53SAnton Vorontsov 		else
456394d6e53SAnton Vorontsov 			mask_port_map = 0xf;
457394d6e53SAnton Vorontsov 		dev_info(&pdev->dev,
458394d6e53SAnton Vorontsov 			  "Disabling your PATA port. Use the boot option 'ahci.marvell_enable=0' to avoid this.\n");
459394d6e53SAnton Vorontsov 	}
460394d6e53SAnton Vorontsov 
4611d513358SAnton Vorontsov 	ahci_save_initial_config(&pdev->dev, hpriv, force_port_map,
4621d513358SAnton Vorontsov 				 mask_port_map);
463394d6e53SAnton Vorontsov }
464394d6e53SAnton Vorontsov 
4653303040dSAnton Vorontsov static int ahci_pci_reset_controller(struct ata_host *host)
4663303040dSAnton Vorontsov {
4673303040dSAnton Vorontsov 	struct pci_dev *pdev = to_pci_dev(host->dev);
4683303040dSAnton Vorontsov 
4693303040dSAnton Vorontsov 	ahci_reset_controller(host);
4703303040dSAnton Vorontsov 
471c6fd2807SJeff Garzik 	if (pdev->vendor == PCI_VENDOR_ID_INTEL) {
4723303040dSAnton Vorontsov 		struct ahci_host_priv *hpriv = host->private_data;
473c6fd2807SJeff Garzik 		u16 tmp16;
474c6fd2807SJeff Garzik 
475c6fd2807SJeff Garzik 		/* configure PCS */
476c6fd2807SJeff Garzik 		pci_read_config_word(pdev, 0x92, &tmp16);
47749f29090STejun Heo 		if ((tmp16 & hpriv->port_map) != hpriv->port_map) {
47849f29090STejun Heo 			tmp16 |= hpriv->port_map;
479c6fd2807SJeff Garzik 			pci_write_config_word(pdev, 0x92, tmp16);
480c6fd2807SJeff Garzik 		}
48149f29090STejun Heo 	}
482c6fd2807SJeff Garzik 
483c6fd2807SJeff Garzik 	return 0;
484c6fd2807SJeff Garzik }
485c6fd2807SJeff Garzik 
486781d6550SAnton Vorontsov static void ahci_pci_init_controller(struct ata_host *host)
487781d6550SAnton Vorontsov {
488781d6550SAnton Vorontsov 	struct ahci_host_priv *hpriv = host->private_data;
489781d6550SAnton Vorontsov 	struct pci_dev *pdev = to_pci_dev(host->dev);
490781d6550SAnton Vorontsov 	void __iomem *port_mmio;
491781d6550SAnton Vorontsov 	u32 tmp;
492c40e7cb8SJose Alberto Reguero 	int mv;
4932bcd866bSJeff Garzik 
494417a1a6dSTejun Heo 	if (hpriv->flags & AHCI_HFLAG_MV_PATA) {
495c40e7cb8SJose Alberto Reguero 		if (pdev->device == 0x6121)
496c40e7cb8SJose Alberto Reguero 			mv = 2;
497c40e7cb8SJose Alberto Reguero 		else
498c40e7cb8SJose Alberto Reguero 			mv = 4;
499c40e7cb8SJose Alberto Reguero 		port_mmio = __ahci_port_base(host, mv);
500cd70c266SJeff Garzik 
501cd70c266SJeff Garzik 		writel(0, port_mmio + PORT_IRQ_MASK);
502cd70c266SJeff Garzik 
503cd70c266SJeff Garzik 		/* clear port IRQ */
504cd70c266SJeff Garzik 		tmp = readl(port_mmio + PORT_IRQ_STAT);
505cd70c266SJeff Garzik 		VPRINTK("PORT_IRQ_STAT 0x%x\n", tmp);
506cd70c266SJeff Garzik 		if (tmp)
507cd70c266SJeff Garzik 			writel(tmp, port_mmio + PORT_IRQ_STAT);
508cd70c266SJeff Garzik 	}
509cd70c266SJeff Garzik 
510781d6550SAnton Vorontsov 	ahci_init_controller(host);
511c6fd2807SJeff Garzik }
512c6fd2807SJeff Garzik 
513cc0680a5STejun Heo static int ahci_vt8251_hardreset(struct ata_link *link, unsigned int *class,
514d4b2bab4STejun Heo 				 unsigned long deadline)
515ad616ffbSTejun Heo {
516cc0680a5STejun Heo 	struct ata_port *ap = link->ap;
5179dadd45bSTejun Heo 	bool online;
518ad616ffbSTejun Heo 	int rc;
519ad616ffbSTejun Heo 
520ad616ffbSTejun Heo 	DPRINTK("ENTER\n");
521ad616ffbSTejun Heo 
5224447d351STejun Heo 	ahci_stop_engine(ap);
523ad616ffbSTejun Heo 
524cc0680a5STejun Heo 	rc = sata_link_hardreset(link, sata_ehc_deb_timing(&link->eh_context),
5259dadd45bSTejun Heo 				 deadline, &online, NULL);
526ad616ffbSTejun Heo 
5274447d351STejun Heo 	ahci_start_engine(ap);
528ad616ffbSTejun Heo 
529ad616ffbSTejun Heo 	DPRINTK("EXIT, rc=%d, class=%u\n", rc, *class);
530ad616ffbSTejun Heo 
531ad616ffbSTejun Heo 	/* vt8251 doesn't clear BSY on signature FIS reception,
532ad616ffbSTejun Heo 	 * request follow-up softreset.
533ad616ffbSTejun Heo 	 */
5349dadd45bSTejun Heo 	return online ? -EAGAIN : rc;
535ad616ffbSTejun Heo }
536ad616ffbSTejun Heo 
537edc93052STejun Heo static int ahci_p5wdh_hardreset(struct ata_link *link, unsigned int *class,
538edc93052STejun Heo 				unsigned long deadline)
539edc93052STejun Heo {
540edc93052STejun Heo 	struct ata_port *ap = link->ap;
541edc93052STejun Heo 	struct ahci_port_priv *pp = ap->private_data;
542edc93052STejun Heo 	u8 *d2h_fis = pp->rx_fis + RX_FIS_D2H_REG;
543edc93052STejun Heo 	struct ata_taskfile tf;
5449dadd45bSTejun Heo 	bool online;
545edc93052STejun Heo 	int rc;
546edc93052STejun Heo 
547edc93052STejun Heo 	ahci_stop_engine(ap);
548edc93052STejun Heo 
549edc93052STejun Heo 	/* clear D2H reception area to properly wait for D2H FIS */
550edc93052STejun Heo 	ata_tf_init(link->device, &tf);
551edc93052STejun Heo 	tf.command = 0x80;
552edc93052STejun Heo 	ata_tf_to_fis(&tf, 0, 0, d2h_fis);
553edc93052STejun Heo 
554edc93052STejun Heo 	rc = sata_link_hardreset(link, sata_ehc_deb_timing(&link->eh_context),
5559dadd45bSTejun Heo 				 deadline, &online, NULL);
556edc93052STejun Heo 
557edc93052STejun Heo 	ahci_start_engine(ap);
558edc93052STejun Heo 
559edc93052STejun Heo 	/* The pseudo configuration device on SIMG4726 attached to
560edc93052STejun Heo 	 * ASUS P5W-DH Deluxe doesn't send signature FIS after
561edc93052STejun Heo 	 * hardreset if no device is attached to the first downstream
562edc93052STejun Heo 	 * port && the pseudo device locks up on SRST w/ PMP==0.  To
563edc93052STejun Heo 	 * work around this, wait for !BSY only briefly.  If BSY isn't
564edc93052STejun Heo 	 * cleared, perform CLO and proceed to IDENTIFY (achieved by
565edc93052STejun Heo 	 * ATA_LFLAG_NO_SRST and ATA_LFLAG_ASSUME_ATA).
566edc93052STejun Heo 	 *
567edc93052STejun Heo 	 * Wait for two seconds.  Devices attached to downstream port
568edc93052STejun Heo 	 * which can't process the following IDENTIFY after this will
569edc93052STejun Heo 	 * have to be reset again.  For most cases, this should
570edc93052STejun Heo 	 * suffice while making probing snappish enough.
571edc93052STejun Heo 	 */
5729dadd45bSTejun Heo 	if (online) {
5739dadd45bSTejun Heo 		rc = ata_wait_after_reset(link, jiffies + 2 * HZ,
5749dadd45bSTejun Heo 					  ahci_check_ready);
575edc93052STejun Heo 		if (rc)
57678d5ae39SShane Huang 			ahci_kick_engine(ap);
5779dadd45bSTejun Heo 	}
5789dadd45bSTejun Heo 	return rc;
579edc93052STejun Heo }
580edc93052STejun Heo 
581438ac6d5STejun Heo #ifdef CONFIG_PM
582c6fd2807SJeff Garzik static int ahci_pci_device_suspend(struct pci_dev *pdev, pm_message_t mesg)
583c6fd2807SJeff Garzik {
584cca3974eSJeff Garzik 	struct ata_host *host = dev_get_drvdata(&pdev->dev);
5859b10ae86STejun Heo 	struct ahci_host_priv *hpriv = host->private_data;
586d8993349SAnton Vorontsov 	void __iomem *mmio = hpriv->mmio;
587c6fd2807SJeff Garzik 	u32 ctl;
588c6fd2807SJeff Garzik 
5899b10ae86STejun Heo 	if (mesg.event & PM_EVENT_SUSPEND &&
5909b10ae86STejun Heo 	    hpriv->flags & AHCI_HFLAG_NO_SUSPEND) {
591a44fec1fSJoe Perches 		dev_err(&pdev->dev,
5929b10ae86STejun Heo 			"BIOS update required for suspend/resume\n");
5939b10ae86STejun Heo 		return -EIO;
5949b10ae86STejun Heo 	}
5959b10ae86STejun Heo 
5963a2d5b70SRafael J. Wysocki 	if (mesg.event & PM_EVENT_SLEEP) {
597c6fd2807SJeff Garzik 		/* AHCI spec rev1.1 section 8.3.3:
598c6fd2807SJeff Garzik 		 * Software must disable interrupts prior to requesting a
599c6fd2807SJeff Garzik 		 * transition of the HBA to D3 state.
600c6fd2807SJeff Garzik 		 */
601c6fd2807SJeff Garzik 		ctl = readl(mmio + HOST_CTL);
602c6fd2807SJeff Garzik 		ctl &= ~HOST_IRQ_EN;
603c6fd2807SJeff Garzik 		writel(ctl, mmio + HOST_CTL);
604c6fd2807SJeff Garzik 		readl(mmio + HOST_CTL); /* flush */
605c6fd2807SJeff Garzik 	}
606c6fd2807SJeff Garzik 
607c6fd2807SJeff Garzik 	return ata_pci_device_suspend(pdev, mesg);
608c6fd2807SJeff Garzik }
609c6fd2807SJeff Garzik 
610c6fd2807SJeff Garzik static int ahci_pci_device_resume(struct pci_dev *pdev)
611c6fd2807SJeff Garzik {
612cca3974eSJeff Garzik 	struct ata_host *host = dev_get_drvdata(&pdev->dev);
613c6fd2807SJeff Garzik 	int rc;
614c6fd2807SJeff Garzik 
615553c4aa6STejun Heo 	rc = ata_pci_device_do_resume(pdev);
616553c4aa6STejun Heo 	if (rc)
617553c4aa6STejun Heo 		return rc;
618c6fd2807SJeff Garzik 
619c6fd2807SJeff Garzik 	if (pdev->dev.power.power_state.event == PM_EVENT_SUSPEND) {
6203303040dSAnton Vorontsov 		rc = ahci_pci_reset_controller(host);
621c6fd2807SJeff Garzik 		if (rc)
622c6fd2807SJeff Garzik 			return rc;
623c6fd2807SJeff Garzik 
624781d6550SAnton Vorontsov 		ahci_pci_init_controller(host);
625c6fd2807SJeff Garzik 	}
626c6fd2807SJeff Garzik 
627cca3974eSJeff Garzik 	ata_host_resume(host);
628c6fd2807SJeff Garzik 
629c6fd2807SJeff Garzik 	return 0;
630c6fd2807SJeff Garzik }
631438ac6d5STejun Heo #endif
632c6fd2807SJeff Garzik 
6334447d351STejun Heo static int ahci_configure_dma_masks(struct pci_dev *pdev, int using_dac)
634c6fd2807SJeff Garzik {
635c6fd2807SJeff Garzik 	int rc;
636c6fd2807SJeff Garzik 
637318893e1SAlessandro Rubini 	/*
638318893e1SAlessandro Rubini 	 * If the device fixup already set the dma_mask to some non-standard
639318893e1SAlessandro Rubini 	 * value, don't extend it here. This happens on STA2X11, for example.
640318893e1SAlessandro Rubini 	 */
641318893e1SAlessandro Rubini 	if (pdev->dma_mask && pdev->dma_mask < DMA_BIT_MASK(32))
642318893e1SAlessandro Rubini 		return 0;
643318893e1SAlessandro Rubini 
644c6fd2807SJeff Garzik 	if (using_dac &&
6456a35528aSYang Hongyang 	    !pci_set_dma_mask(pdev, DMA_BIT_MASK(64))) {
6466a35528aSYang Hongyang 		rc = pci_set_consistent_dma_mask(pdev, DMA_BIT_MASK(64));
647c6fd2807SJeff Garzik 		if (rc) {
648284901a9SYang Hongyang 			rc = pci_set_consistent_dma_mask(pdev, DMA_BIT_MASK(32));
649c6fd2807SJeff Garzik 			if (rc) {
650a44fec1fSJoe Perches 				dev_err(&pdev->dev,
651c6fd2807SJeff Garzik 					"64-bit DMA enable failed\n");
652c6fd2807SJeff Garzik 				return rc;
653c6fd2807SJeff Garzik 			}
654c6fd2807SJeff Garzik 		}
655c6fd2807SJeff Garzik 	} else {
656284901a9SYang Hongyang 		rc = pci_set_dma_mask(pdev, DMA_BIT_MASK(32));
657c6fd2807SJeff Garzik 		if (rc) {
658a44fec1fSJoe Perches 			dev_err(&pdev->dev, "32-bit DMA enable failed\n");
659c6fd2807SJeff Garzik 			return rc;
660c6fd2807SJeff Garzik 		}
661284901a9SYang Hongyang 		rc = pci_set_consistent_dma_mask(pdev, DMA_BIT_MASK(32));
662c6fd2807SJeff Garzik 		if (rc) {
663a44fec1fSJoe Perches 			dev_err(&pdev->dev,
664c6fd2807SJeff Garzik 				"32-bit consistent DMA enable failed\n");
665c6fd2807SJeff Garzik 			return rc;
666c6fd2807SJeff Garzik 		}
667c6fd2807SJeff Garzik 	}
668c6fd2807SJeff Garzik 	return 0;
669c6fd2807SJeff Garzik }
670c6fd2807SJeff Garzik 
671439fcaecSAnton Vorontsov static void ahci_pci_print_info(struct ata_host *host)
672439fcaecSAnton Vorontsov {
673439fcaecSAnton Vorontsov 	struct pci_dev *pdev = to_pci_dev(host->dev);
674439fcaecSAnton Vorontsov 	u16 cc;
675439fcaecSAnton Vorontsov 	const char *scc_s;
676439fcaecSAnton Vorontsov 
677439fcaecSAnton Vorontsov 	pci_read_config_word(pdev, 0x0a, &cc);
678439fcaecSAnton Vorontsov 	if (cc == PCI_CLASS_STORAGE_IDE)
679439fcaecSAnton Vorontsov 		scc_s = "IDE";
680439fcaecSAnton Vorontsov 	else if (cc == PCI_CLASS_STORAGE_SATA)
681439fcaecSAnton Vorontsov 		scc_s = "SATA";
682439fcaecSAnton Vorontsov 	else if (cc == PCI_CLASS_STORAGE_RAID)
683439fcaecSAnton Vorontsov 		scc_s = "RAID";
684439fcaecSAnton Vorontsov 	else
685439fcaecSAnton Vorontsov 		scc_s = "unknown";
686439fcaecSAnton Vorontsov 
687439fcaecSAnton Vorontsov 	ahci_print_info(host, scc_s);
688439fcaecSAnton Vorontsov }
689439fcaecSAnton Vorontsov 
690edc93052STejun Heo /* On ASUS P5W DH Deluxe, the second port of PCI device 00:1f.2 is
691edc93052STejun Heo  * hardwired to on-board SIMG 4726.  The chipset is ICH8 and doesn't
692edc93052STejun Heo  * support PMP and the 4726 either directly exports the device
693edc93052STejun Heo  * attached to the first downstream port or acts as a hardware storage
694edc93052STejun Heo  * controller and emulate a single ATA device (can be RAID 0/1 or some
695edc93052STejun Heo  * other configuration).
696edc93052STejun Heo  *
697edc93052STejun Heo  * When there's no device attached to the first downstream port of the
698edc93052STejun Heo  * 4726, "Config Disk" appears, which is a pseudo ATA device to
699edc93052STejun Heo  * configure the 4726.  However, ATA emulation of the device is very
700edc93052STejun Heo  * lame.  It doesn't send signature D2H Reg FIS after the initial
701edc93052STejun Heo  * hardreset, pukes on SRST w/ PMP==0 and has bunch of other issues.
702edc93052STejun Heo  *
703edc93052STejun Heo  * The following function works around the problem by always using
704edc93052STejun Heo  * hardreset on the port and not depending on receiving signature FIS
705edc93052STejun Heo  * afterward.  If signature FIS isn't received soon, ATA class is
706edc93052STejun Heo  * assumed without follow-up softreset.
707edc93052STejun Heo  */
708edc93052STejun Heo static void ahci_p5wdh_workaround(struct ata_host *host)
709edc93052STejun Heo {
710edc93052STejun Heo 	static struct dmi_system_id sysids[] = {
711edc93052STejun Heo 		{
712edc93052STejun Heo 			.ident = "P5W DH Deluxe",
713edc93052STejun Heo 			.matches = {
714edc93052STejun Heo 				DMI_MATCH(DMI_SYS_VENDOR,
715edc93052STejun Heo 					  "ASUSTEK COMPUTER INC"),
716edc93052STejun Heo 				DMI_MATCH(DMI_PRODUCT_NAME, "P5W DH Deluxe"),
717edc93052STejun Heo 			},
718edc93052STejun Heo 		},
719edc93052STejun Heo 		{ }
720edc93052STejun Heo 	};
721edc93052STejun Heo 	struct pci_dev *pdev = to_pci_dev(host->dev);
722edc93052STejun Heo 
723edc93052STejun Heo 	if (pdev->bus->number == 0 && pdev->devfn == PCI_DEVFN(0x1f, 2) &&
724edc93052STejun Heo 	    dmi_check_system(sysids)) {
725edc93052STejun Heo 		struct ata_port *ap = host->ports[1];
726edc93052STejun Heo 
727a44fec1fSJoe Perches 		dev_info(&pdev->dev,
728a44fec1fSJoe Perches 			 "enabling ASUS P5W DH Deluxe on-board SIMG4726 workaround\n");
729edc93052STejun Heo 
730edc93052STejun Heo 		ap->ops = &ahci_p5wdh_ops;
731edc93052STejun Heo 		ap->link.flags |= ATA_LFLAG_NO_SRST | ATA_LFLAG_ASSUME_ATA;
732edc93052STejun Heo 	}
733edc93052STejun Heo }
734edc93052STejun Heo 
7352fcad9d2STejun Heo /* only some SB600 ahci controllers can do 64bit DMA */
7362fcad9d2STejun Heo static bool ahci_sb600_enable_64bit(struct pci_dev *pdev)
73758a09b38SShane Huang {
73858a09b38SShane Huang 	static const struct dmi_system_id sysids[] = {
73903d783bfSTejun Heo 		/*
74003d783bfSTejun Heo 		 * The oldest version known to be broken is 0901 and
74103d783bfSTejun Heo 		 * working is 1501 which was released on 2007-10-26.
7422fcad9d2STejun Heo 		 * Enable 64bit DMA on 1501 and anything newer.
7432fcad9d2STejun Heo 		 *
74403d783bfSTejun Heo 		 * Please read bko#9412 for more info.
74503d783bfSTejun Heo 		 */
74658a09b38SShane Huang 		{
74758a09b38SShane Huang 			.ident = "ASUS M2A-VM",
74858a09b38SShane Huang 			.matches = {
74958a09b38SShane Huang 				DMI_MATCH(DMI_BOARD_VENDOR,
75058a09b38SShane Huang 					  "ASUSTeK Computer INC."),
75158a09b38SShane Huang 				DMI_MATCH(DMI_BOARD_NAME, "M2A-VM"),
75258a09b38SShane Huang 			},
75303d783bfSTejun Heo 			.driver_data = "20071026",	/* yyyymmdd */
75458a09b38SShane Huang 		},
755e65cc194SMark Nelson 		/*
756e65cc194SMark Nelson 		 * All BIOS versions for the MSI K9A2 Platinum (MS-7376)
757e65cc194SMark Nelson 		 * support 64bit DMA.
758e65cc194SMark Nelson 		 *
759e65cc194SMark Nelson 		 * BIOS versions earlier than 1.5 had the Manufacturer DMI
760e65cc194SMark Nelson 		 * fields as "MICRO-STAR INTERANTIONAL CO.,LTD".
761e65cc194SMark Nelson 		 * This spelling mistake was fixed in BIOS version 1.5, so
762e65cc194SMark Nelson 		 * 1.5 and later have the Manufacturer as
763e65cc194SMark Nelson 		 * "MICRO-STAR INTERNATIONAL CO.,LTD".
764e65cc194SMark Nelson 		 * So try to match on DMI_BOARD_VENDOR of "MICRO-STAR INTER".
765e65cc194SMark Nelson 		 *
766e65cc194SMark Nelson 		 * BIOS versions earlier than 1.9 had a Board Product Name
767e65cc194SMark Nelson 		 * DMI field of "MS-7376". This was changed to be
768e65cc194SMark Nelson 		 * "K9A2 Platinum (MS-7376)" in version 1.9, but we can still
769e65cc194SMark Nelson 		 * match on DMI_BOARD_NAME of "MS-7376".
770e65cc194SMark Nelson 		 */
771e65cc194SMark Nelson 		{
772e65cc194SMark Nelson 			.ident = "MSI K9A2 Platinum",
773e65cc194SMark Nelson 			.matches = {
774e65cc194SMark Nelson 				DMI_MATCH(DMI_BOARD_VENDOR,
775e65cc194SMark Nelson 					  "MICRO-STAR INTER"),
776e65cc194SMark Nelson 				DMI_MATCH(DMI_BOARD_NAME, "MS-7376"),
777e65cc194SMark Nelson 			},
778e65cc194SMark Nelson 		},
7793c4aa91fSMark Nelson 		/*
780*ff0173c1SMark Nelson 		 * All BIOS versions for the MSI K9AGM2 (MS-7327) support
781*ff0173c1SMark Nelson 		 * 64bit DMA.
782*ff0173c1SMark Nelson 		 *
783*ff0173c1SMark Nelson 		 * This board also had the typo mentioned above in the
784*ff0173c1SMark Nelson 		 * Manufacturer DMI field (fixed in BIOS version 1.5), so
785*ff0173c1SMark Nelson 		 * match on DMI_BOARD_VENDOR of "MICRO-STAR INTER" again.
786*ff0173c1SMark Nelson 		 */
787*ff0173c1SMark Nelson 		{
788*ff0173c1SMark Nelson 			.ident = "MSI K9AGM2",
789*ff0173c1SMark Nelson 			.matches = {
790*ff0173c1SMark Nelson 				DMI_MATCH(DMI_BOARD_VENDOR,
791*ff0173c1SMark Nelson 					  "MICRO-STAR INTER"),
792*ff0173c1SMark Nelson 				DMI_MATCH(DMI_BOARD_NAME, "MS-7327"),
793*ff0173c1SMark Nelson 			},
794*ff0173c1SMark Nelson 		},
795*ff0173c1SMark Nelson 		/*
7963c4aa91fSMark Nelson 		 * All BIOS versions for the Asus M3A support 64bit DMA.
7973c4aa91fSMark Nelson 		 * (all release versions from 0301 to 1206 were tested)
7983c4aa91fSMark Nelson 		 */
7993c4aa91fSMark Nelson 		{
8003c4aa91fSMark Nelson 			.ident = "ASUS M3A",
8013c4aa91fSMark Nelson 			.matches = {
8023c4aa91fSMark Nelson 				DMI_MATCH(DMI_BOARD_VENDOR,
8033c4aa91fSMark Nelson 					  "ASUSTeK Computer INC."),
8043c4aa91fSMark Nelson 				DMI_MATCH(DMI_BOARD_NAME, "M3A"),
8053c4aa91fSMark Nelson 			},
8063c4aa91fSMark Nelson 		},
80758a09b38SShane Huang 		{ }
80858a09b38SShane Huang 	};
80903d783bfSTejun Heo 	const struct dmi_system_id *match;
8102fcad9d2STejun Heo 	int year, month, date;
8112fcad9d2STejun Heo 	char buf[9];
81258a09b38SShane Huang 
81303d783bfSTejun Heo 	match = dmi_first_match(sysids);
81458a09b38SShane Huang 	if (pdev->bus->number != 0 || pdev->devfn != PCI_DEVFN(0x12, 0) ||
81503d783bfSTejun Heo 	    !match)
81658a09b38SShane Huang 		return false;
81758a09b38SShane Huang 
818e65cc194SMark Nelson 	if (!match->driver_data)
819e65cc194SMark Nelson 		goto enable_64bit;
820e65cc194SMark Nelson 
82103d783bfSTejun Heo 	dmi_get_date(DMI_BIOS_DATE, &year, &month, &date);
82203d783bfSTejun Heo 	snprintf(buf, sizeof(buf), "%04d%02d%02d", year, month, date);
82303d783bfSTejun Heo 
824e65cc194SMark Nelson 	if (strcmp(buf, match->driver_data) >= 0)
825e65cc194SMark Nelson 		goto enable_64bit;
826e65cc194SMark Nelson 	else {
827a44fec1fSJoe Perches 		dev_warn(&pdev->dev,
828a44fec1fSJoe Perches 			 "%s: BIOS too old, forcing 32bit DMA, update BIOS\n",
829a44fec1fSJoe Perches 			 match->ident);
8302fcad9d2STejun Heo 		return false;
8312fcad9d2STejun Heo 	}
832e65cc194SMark Nelson 
833e65cc194SMark Nelson enable_64bit:
834a44fec1fSJoe Perches 	dev_warn(&pdev->dev, "%s: enabling 64bit DMA\n", match->ident);
835e65cc194SMark Nelson 	return true;
83658a09b38SShane Huang }
83758a09b38SShane Huang 
8381fd68434SRafael J. Wysocki static bool ahci_broken_system_poweroff(struct pci_dev *pdev)
8391fd68434SRafael J. Wysocki {
8401fd68434SRafael J. Wysocki 	static const struct dmi_system_id broken_systems[] = {
8411fd68434SRafael J. Wysocki 		{
8421fd68434SRafael J. Wysocki 			.ident = "HP Compaq nx6310",
8431fd68434SRafael J. Wysocki 			.matches = {
8441fd68434SRafael J. Wysocki 				DMI_MATCH(DMI_SYS_VENDOR, "Hewlett-Packard"),
8451fd68434SRafael J. Wysocki 				DMI_MATCH(DMI_PRODUCT_NAME, "HP Compaq nx6310"),
8461fd68434SRafael J. Wysocki 			},
8471fd68434SRafael J. Wysocki 			/* PCI slot number of the controller */
8481fd68434SRafael J. Wysocki 			.driver_data = (void *)0x1FUL,
8491fd68434SRafael J. Wysocki 		},
850d2f9c061SMaciej Rutecki 		{
851d2f9c061SMaciej Rutecki 			.ident = "HP Compaq 6720s",
852d2f9c061SMaciej Rutecki 			.matches = {
853d2f9c061SMaciej Rutecki 				DMI_MATCH(DMI_SYS_VENDOR, "Hewlett-Packard"),
854d2f9c061SMaciej Rutecki 				DMI_MATCH(DMI_PRODUCT_NAME, "HP Compaq 6720s"),
855d2f9c061SMaciej Rutecki 			},
856d2f9c061SMaciej Rutecki 			/* PCI slot number of the controller */
857d2f9c061SMaciej Rutecki 			.driver_data = (void *)0x1FUL,
858d2f9c061SMaciej Rutecki 		},
8591fd68434SRafael J. Wysocki 
8601fd68434SRafael J. Wysocki 		{ }	/* terminate list */
8611fd68434SRafael J. Wysocki 	};
8621fd68434SRafael J. Wysocki 	const struct dmi_system_id *dmi = dmi_first_match(broken_systems);
8631fd68434SRafael J. Wysocki 
8641fd68434SRafael J. Wysocki 	if (dmi) {
8651fd68434SRafael J. Wysocki 		unsigned long slot = (unsigned long)dmi->driver_data;
8661fd68434SRafael J. Wysocki 		/* apply the quirk only to on-board controllers */
8671fd68434SRafael J. Wysocki 		return slot == PCI_SLOT(pdev->devfn);
8681fd68434SRafael J. Wysocki 	}
8691fd68434SRafael J. Wysocki 
8701fd68434SRafael J. Wysocki 	return false;
8711fd68434SRafael J. Wysocki }
8721fd68434SRafael J. Wysocki 
8739b10ae86STejun Heo static bool ahci_broken_suspend(struct pci_dev *pdev)
8749b10ae86STejun Heo {
8759b10ae86STejun Heo 	static const struct dmi_system_id sysids[] = {
8769b10ae86STejun Heo 		/*
8779b10ae86STejun Heo 		 * On HP dv[4-6] and HDX18 with earlier BIOSen, link
8789b10ae86STejun Heo 		 * to the harddisk doesn't become online after
8799b10ae86STejun Heo 		 * resuming from STR.  Warn and fail suspend.
8809deb3431STejun Heo 		 *
8819deb3431STejun Heo 		 * http://bugzilla.kernel.org/show_bug.cgi?id=12276
8829deb3431STejun Heo 		 *
8839deb3431STejun Heo 		 * Use dates instead of versions to match as HP is
8849deb3431STejun Heo 		 * apparently recycling both product and version
8859deb3431STejun Heo 		 * strings.
8869deb3431STejun Heo 		 *
8879deb3431STejun Heo 		 * http://bugzilla.kernel.org/show_bug.cgi?id=15462
8889b10ae86STejun Heo 		 */
8899b10ae86STejun Heo 		{
8909b10ae86STejun Heo 			.ident = "dv4",
8919b10ae86STejun Heo 			.matches = {
8929b10ae86STejun Heo 				DMI_MATCH(DMI_SYS_VENDOR, "Hewlett-Packard"),
8939b10ae86STejun Heo 				DMI_MATCH(DMI_PRODUCT_NAME,
8949b10ae86STejun Heo 					  "HP Pavilion dv4 Notebook PC"),
8959b10ae86STejun Heo 			},
8969deb3431STejun Heo 			.driver_data = "20090105",	/* F.30 */
8979b10ae86STejun Heo 		},
8989b10ae86STejun Heo 		{
8999b10ae86STejun Heo 			.ident = "dv5",
9009b10ae86STejun Heo 			.matches = {
9019b10ae86STejun Heo 				DMI_MATCH(DMI_SYS_VENDOR, "Hewlett-Packard"),
9029b10ae86STejun Heo 				DMI_MATCH(DMI_PRODUCT_NAME,
9039b10ae86STejun Heo 					  "HP Pavilion dv5 Notebook PC"),
9049b10ae86STejun Heo 			},
9059deb3431STejun Heo 			.driver_data = "20090506",	/* F.16 */
9069b10ae86STejun Heo 		},
9079b10ae86STejun Heo 		{
9089b10ae86STejun Heo 			.ident = "dv6",
9099b10ae86STejun Heo 			.matches = {
9109b10ae86STejun Heo 				DMI_MATCH(DMI_SYS_VENDOR, "Hewlett-Packard"),
9119b10ae86STejun Heo 				DMI_MATCH(DMI_PRODUCT_NAME,
9129b10ae86STejun Heo 					  "HP Pavilion dv6 Notebook PC"),
9139b10ae86STejun Heo 			},
9149deb3431STejun Heo 			.driver_data = "20090423",	/* F.21 */
9159b10ae86STejun Heo 		},
9169b10ae86STejun Heo 		{
9179b10ae86STejun Heo 			.ident = "HDX18",
9189b10ae86STejun Heo 			.matches = {
9199b10ae86STejun Heo 				DMI_MATCH(DMI_SYS_VENDOR, "Hewlett-Packard"),
9209b10ae86STejun Heo 				DMI_MATCH(DMI_PRODUCT_NAME,
9219b10ae86STejun Heo 					  "HP HDX18 Notebook PC"),
9229b10ae86STejun Heo 			},
9239deb3431STejun Heo 			.driver_data = "20090430",	/* F.23 */
9249b10ae86STejun Heo 		},
925cedc9bf9STejun Heo 		/*
926cedc9bf9STejun Heo 		 * Acer eMachines G725 has the same problem.  BIOS
927cedc9bf9STejun Heo 		 * V1.03 is known to be broken.  V3.04 is known to
92825985edcSLucas De Marchi 		 * work.  Between, there are V1.06, V2.06 and V3.03
929cedc9bf9STejun Heo 		 * that we don't have much idea about.  For now,
930cedc9bf9STejun Heo 		 * blacklist anything older than V3.04.
9319deb3431STejun Heo 		 *
9329deb3431STejun Heo 		 * http://bugzilla.kernel.org/show_bug.cgi?id=15104
933cedc9bf9STejun Heo 		 */
934cedc9bf9STejun Heo 		{
935cedc9bf9STejun Heo 			.ident = "G725",
936cedc9bf9STejun Heo 			.matches = {
937cedc9bf9STejun Heo 				DMI_MATCH(DMI_SYS_VENDOR, "eMachines"),
938cedc9bf9STejun Heo 				DMI_MATCH(DMI_PRODUCT_NAME, "eMachines G725"),
939cedc9bf9STejun Heo 			},
9409deb3431STejun Heo 			.driver_data = "20091216",	/* V3.04 */
941cedc9bf9STejun Heo 		},
9429b10ae86STejun Heo 		{ }	/* terminate list */
9439b10ae86STejun Heo 	};
9449b10ae86STejun Heo 	const struct dmi_system_id *dmi = dmi_first_match(sysids);
9459deb3431STejun Heo 	int year, month, date;
9469deb3431STejun Heo 	char buf[9];
9479b10ae86STejun Heo 
9489b10ae86STejun Heo 	if (!dmi || pdev->bus->number || pdev->devfn != PCI_DEVFN(0x1f, 2))
9499b10ae86STejun Heo 		return false;
9509b10ae86STejun Heo 
9519deb3431STejun Heo 	dmi_get_date(DMI_BIOS_DATE, &year, &month, &date);
9529deb3431STejun Heo 	snprintf(buf, sizeof(buf), "%04d%02d%02d", year, month, date);
9539b10ae86STejun Heo 
9549deb3431STejun Heo 	return strcmp(buf, dmi->driver_data) < 0;
9559b10ae86STejun Heo }
9569b10ae86STejun Heo 
9575594639aSTejun Heo static bool ahci_broken_online(struct pci_dev *pdev)
9585594639aSTejun Heo {
9595594639aSTejun Heo #define ENCODE_BUSDEVFN(bus, slot, func)			\
9605594639aSTejun Heo 	(void *)(unsigned long)(((bus) << 8) | PCI_DEVFN((slot), (func)))
9615594639aSTejun Heo 	static const struct dmi_system_id sysids[] = {
9625594639aSTejun Heo 		/*
9635594639aSTejun Heo 		 * There are several gigabyte boards which use
9645594639aSTejun Heo 		 * SIMG5723s configured as hardware RAID.  Certain
9655594639aSTejun Heo 		 * 5723 firmware revisions shipped there keep the link
9665594639aSTejun Heo 		 * online but fail to answer properly to SRST or
9675594639aSTejun Heo 		 * IDENTIFY when no device is attached downstream
9685594639aSTejun Heo 		 * causing libata to retry quite a few times leading
9695594639aSTejun Heo 		 * to excessive detection delay.
9705594639aSTejun Heo 		 *
9715594639aSTejun Heo 		 * As these firmwares respond to the second reset try
9725594639aSTejun Heo 		 * with invalid device signature, considering unknown
9735594639aSTejun Heo 		 * sig as offline works around the problem acceptably.
9745594639aSTejun Heo 		 */
9755594639aSTejun Heo 		{
9765594639aSTejun Heo 			.ident = "EP45-DQ6",
9775594639aSTejun Heo 			.matches = {
9785594639aSTejun Heo 				DMI_MATCH(DMI_BOARD_VENDOR,
9795594639aSTejun Heo 					  "Gigabyte Technology Co., Ltd."),
9805594639aSTejun Heo 				DMI_MATCH(DMI_BOARD_NAME, "EP45-DQ6"),
9815594639aSTejun Heo 			},
9825594639aSTejun Heo 			.driver_data = ENCODE_BUSDEVFN(0x0a, 0x00, 0),
9835594639aSTejun Heo 		},
9845594639aSTejun Heo 		{
9855594639aSTejun Heo 			.ident = "EP45-DS5",
9865594639aSTejun Heo 			.matches = {
9875594639aSTejun Heo 				DMI_MATCH(DMI_BOARD_VENDOR,
9885594639aSTejun Heo 					  "Gigabyte Technology Co., Ltd."),
9895594639aSTejun Heo 				DMI_MATCH(DMI_BOARD_NAME, "EP45-DS5"),
9905594639aSTejun Heo 			},
9915594639aSTejun Heo 			.driver_data = ENCODE_BUSDEVFN(0x03, 0x00, 0),
9925594639aSTejun Heo 		},
9935594639aSTejun Heo 		{ }	/* terminate list */
9945594639aSTejun Heo 	};
9955594639aSTejun Heo #undef ENCODE_BUSDEVFN
9965594639aSTejun Heo 	const struct dmi_system_id *dmi = dmi_first_match(sysids);
9975594639aSTejun Heo 	unsigned int val;
9985594639aSTejun Heo 
9995594639aSTejun Heo 	if (!dmi)
10005594639aSTejun Heo 		return false;
10015594639aSTejun Heo 
10025594639aSTejun Heo 	val = (unsigned long)dmi->driver_data;
10035594639aSTejun Heo 
10045594639aSTejun Heo 	return pdev->bus->number == (val >> 8) && pdev->devfn == (val & 0xff);
10055594639aSTejun Heo }
10065594639aSTejun Heo 
10078e513217SMarkus Trippelsdorf #ifdef CONFIG_ATA_ACPI
1008f80ae7e4STejun Heo static void ahci_gtf_filter_workaround(struct ata_host *host)
1009f80ae7e4STejun Heo {
1010f80ae7e4STejun Heo 	static const struct dmi_system_id sysids[] = {
1011f80ae7e4STejun Heo 		/*
1012f80ae7e4STejun Heo 		 * Aspire 3810T issues a bunch of SATA enable commands
1013f80ae7e4STejun Heo 		 * via _GTF including an invalid one and one which is
1014f80ae7e4STejun Heo 		 * rejected by the device.  Among the successful ones
1015f80ae7e4STejun Heo 		 * is FPDMA non-zero offset enable which when enabled
1016f80ae7e4STejun Heo 		 * only on the drive side leads to NCQ command
1017f80ae7e4STejun Heo 		 * failures.  Filter it out.
1018f80ae7e4STejun Heo 		 */
1019f80ae7e4STejun Heo 		{
1020f80ae7e4STejun Heo 			.ident = "Aspire 3810T",
1021f80ae7e4STejun Heo 			.matches = {
1022f80ae7e4STejun Heo 				DMI_MATCH(DMI_SYS_VENDOR, "Acer"),
1023f80ae7e4STejun Heo 				DMI_MATCH(DMI_PRODUCT_NAME, "Aspire 3810T"),
1024f80ae7e4STejun Heo 			},
1025f80ae7e4STejun Heo 			.driver_data = (void *)ATA_ACPI_FILTER_FPDMA_OFFSET,
1026f80ae7e4STejun Heo 		},
1027f80ae7e4STejun Heo 		{ }
1028f80ae7e4STejun Heo 	};
1029f80ae7e4STejun Heo 	const struct dmi_system_id *dmi = dmi_first_match(sysids);
1030f80ae7e4STejun Heo 	unsigned int filter;
1031f80ae7e4STejun Heo 	int i;
1032f80ae7e4STejun Heo 
1033f80ae7e4STejun Heo 	if (!dmi)
1034f80ae7e4STejun Heo 		return;
1035f80ae7e4STejun Heo 
1036f80ae7e4STejun Heo 	filter = (unsigned long)dmi->driver_data;
1037a44fec1fSJoe Perches 	dev_info(host->dev, "applying extra ACPI _GTF filter 0x%x for %s\n",
1038f80ae7e4STejun Heo 		 filter, dmi->ident);
1039f80ae7e4STejun Heo 
1040f80ae7e4STejun Heo 	for (i = 0; i < host->n_ports; i++) {
1041f80ae7e4STejun Heo 		struct ata_port *ap = host->ports[i];
1042f80ae7e4STejun Heo 		struct ata_link *link;
1043f80ae7e4STejun Heo 		struct ata_device *dev;
1044f80ae7e4STejun Heo 
1045f80ae7e4STejun Heo 		ata_for_each_link(link, ap, EDGE)
1046f80ae7e4STejun Heo 			ata_for_each_dev(dev, link, ALL)
1047f80ae7e4STejun Heo 				dev->gtf_filter |= filter;
1048f80ae7e4STejun Heo 	}
1049f80ae7e4STejun Heo }
10508e513217SMarkus Trippelsdorf #else
10518e513217SMarkus Trippelsdorf static inline void ahci_gtf_filter_workaround(struct ata_host *host)
10528e513217SMarkus Trippelsdorf {}
10538e513217SMarkus Trippelsdorf #endif
1054f80ae7e4STejun Heo 
1055c6fd2807SJeff Garzik static int ahci_init_one(struct pci_dev *pdev, const struct pci_device_id *ent)
1056c6fd2807SJeff Garzik {
1057e297d99eSTejun Heo 	unsigned int board_id = ent->driver_data;
1058e297d99eSTejun Heo 	struct ata_port_info pi = ahci_port_info[board_id];
10594447d351STejun Heo 	const struct ata_port_info *ppi[] = { &pi, NULL };
106024dc5f33STejun Heo 	struct device *dev = &pdev->dev;
1061c6fd2807SJeff Garzik 	struct ahci_host_priv *hpriv;
10624447d351STejun Heo 	struct ata_host *host;
1063837f5f8fSTejun Heo 	int n_ports, i, rc;
1064318893e1SAlessandro Rubini 	int ahci_pci_bar = AHCI_PCI_BAR_STANDARD;
1065c6fd2807SJeff Garzik 
1066c6fd2807SJeff Garzik 	VPRINTK("ENTER\n");
1067c6fd2807SJeff Garzik 
1068b429dd59SJustin P. Mattock 	WARN_ON((int)ATA_MAX_QUEUE > AHCI_MAX_CMDS);
1069c6fd2807SJeff Garzik 
107006296a1eSJoe Perches 	ata_print_version_once(&pdev->dev, DRV_VERSION);
1071c6fd2807SJeff Garzik 
10725b66c829SAlan Cox 	/* The AHCI driver can only drive the SATA ports, the PATA driver
10735b66c829SAlan Cox 	   can drive them all so if both drivers are selected make sure
10745b66c829SAlan Cox 	   AHCI stays out of the way */
10755b66c829SAlan Cox 	if (pdev->vendor == PCI_VENDOR_ID_MARVELL && !marvell_enable)
10765b66c829SAlan Cox 		return -ENODEV;
10775b66c829SAlan Cox 
1078c6353b45STejun Heo 	/*
1079c6353b45STejun Heo 	 * For some reason, MCP89 on MacBook 7,1 doesn't work with
1080c6353b45STejun Heo 	 * ahci, use ata_generic instead.
1081c6353b45STejun Heo 	 */
1082c6353b45STejun Heo 	if (pdev->vendor == PCI_VENDOR_ID_NVIDIA &&
1083c6353b45STejun Heo 	    pdev->device == PCI_DEVICE_ID_NVIDIA_NFORCE_MCP89_SATA &&
1084c6353b45STejun Heo 	    pdev->subsystem_vendor == PCI_VENDOR_ID_APPLE &&
1085c6353b45STejun Heo 	    pdev->subsystem_device == 0xcb89)
1086c6353b45STejun Heo 		return -ENODEV;
1087c6353b45STejun Heo 
10887a02267eSMark Nelson 	/* Promise's PDC42819 is a SAS/SATA controller that has an AHCI mode.
10897a02267eSMark Nelson 	 * At the moment, we can only use the AHCI mode. Let the users know
10907a02267eSMark Nelson 	 * that for SAS drives they're out of luck.
10917a02267eSMark Nelson 	 */
10927a02267eSMark Nelson 	if (pdev->vendor == PCI_VENDOR_ID_PROMISE)
1093a44fec1fSJoe Perches 		dev_info(&pdev->dev,
1094a44fec1fSJoe Perches 			 "PDC42819 can only drive SATA devices with this driver\n");
10957a02267eSMark Nelson 
1096318893e1SAlessandro Rubini 	/* The Connext uses non-standard BAR */
1097318893e1SAlessandro Rubini 	if (pdev->vendor == PCI_VENDOR_ID_STMICRO && pdev->device == 0xCC06)
1098318893e1SAlessandro Rubini 		ahci_pci_bar = AHCI_PCI_BAR_STA2X11;
1099318893e1SAlessandro Rubini 
11004447d351STejun Heo 	/* acquire resources */
110124dc5f33STejun Heo 	rc = pcim_enable_device(pdev);
1102c6fd2807SJeff Garzik 	if (rc)
1103c6fd2807SJeff Garzik 		return rc;
1104c6fd2807SJeff Garzik 
1105dea55137STejun Heo 	/* AHCI controllers often implement SFF compatible interface.
1106dea55137STejun Heo 	 * Grab all PCI BARs just in case.
1107dea55137STejun Heo 	 */
1108318893e1SAlessandro Rubini 	rc = pcim_iomap_regions_request_all(pdev, 1 << ahci_pci_bar, DRV_NAME);
11090d5ff566STejun Heo 	if (rc == -EBUSY)
111024dc5f33STejun Heo 		pcim_pin_device(pdev);
11110d5ff566STejun Heo 	if (rc)
111224dc5f33STejun Heo 		return rc;
1113c6fd2807SJeff Garzik 
1114c4f7792cSTejun Heo 	if (pdev->vendor == PCI_VENDOR_ID_INTEL &&
1115c4f7792cSTejun Heo 	    (pdev->device == 0x2652 || pdev->device == 0x2653)) {
1116c4f7792cSTejun Heo 		u8 map;
1117c4f7792cSTejun Heo 
1118c4f7792cSTejun Heo 		/* ICH6s share the same PCI ID for both piix and ahci
1119c4f7792cSTejun Heo 		 * modes.  Enabling ahci mode while MAP indicates
1120c4f7792cSTejun Heo 		 * combined mode is a bad idea.  Yield to ata_piix.
1121c4f7792cSTejun Heo 		 */
1122c4f7792cSTejun Heo 		pci_read_config_byte(pdev, ICH_MAP, &map);
1123c4f7792cSTejun Heo 		if (map & 0x3) {
1124a44fec1fSJoe Perches 			dev_info(&pdev->dev,
1125a44fec1fSJoe Perches 				 "controller is in combined mode, can't enable AHCI mode\n");
1126c4f7792cSTejun Heo 			return -ENODEV;
1127c4f7792cSTejun Heo 		}
1128c4f7792cSTejun Heo 	}
1129c4f7792cSTejun Heo 
113024dc5f33STejun Heo 	hpriv = devm_kzalloc(dev, sizeof(*hpriv), GFP_KERNEL);
113124dc5f33STejun Heo 	if (!hpriv)
113224dc5f33STejun Heo 		return -ENOMEM;
1133417a1a6dSTejun Heo 	hpriv->flags |= (unsigned long)pi.private_data;
1134417a1a6dSTejun Heo 
1135e297d99eSTejun Heo 	/* MCP65 revision A1 and A2 can't do MSI */
1136e297d99eSTejun Heo 	if (board_id == board_ahci_mcp65 &&
1137e297d99eSTejun Heo 	    (pdev->revision == 0xa1 || pdev->revision == 0xa2))
1138e297d99eSTejun Heo 		hpriv->flags |= AHCI_HFLAG_NO_MSI;
1139e297d99eSTejun Heo 
1140e427fe04SShane Huang 	/* SB800 does NOT need the workaround to ignore SERR_INTERNAL */
1141e427fe04SShane Huang 	if (board_id == board_ahci_sb700 && pdev->revision >= 0x40)
1142e427fe04SShane Huang 		hpriv->flags &= ~AHCI_HFLAG_IGN_SERR_INTERNAL;
1143e427fe04SShane Huang 
11442fcad9d2STejun Heo 	/* only some SB600s can do 64bit DMA */
11452fcad9d2STejun Heo 	if (ahci_sb600_enable_64bit(pdev))
11462fcad9d2STejun Heo 		hpriv->flags &= ~AHCI_HFLAG_32BIT_ONLY;
114758a09b38SShane Huang 
114831b239adSTejun Heo 	if ((hpriv->flags & AHCI_HFLAG_NO_MSI) || pci_enable_msi(pdev))
114931b239adSTejun Heo 		pci_intx(pdev, 1);
1150c6fd2807SJeff Garzik 
1151318893e1SAlessandro Rubini 	hpriv->mmio = pcim_iomap_table(pdev)[ahci_pci_bar];
1152d8993349SAnton Vorontsov 
11534447d351STejun Heo 	/* save initial config */
1154394d6e53SAnton Vorontsov 	ahci_pci_save_initial_config(pdev, hpriv);
1155c6fd2807SJeff Garzik 
11564447d351STejun Heo 	/* prepare host */
1157453d3131SRobert Hancock 	if (hpriv->cap & HOST_CAP_NCQ) {
1158453d3131SRobert Hancock 		pi.flags |= ATA_FLAG_NCQ;
115983f2b963STejun Heo 		/*
116083f2b963STejun Heo 		 * Auto-activate optimization is supposed to be
116183f2b963STejun Heo 		 * supported on all AHCI controllers indicating NCQ
116283f2b963STejun Heo 		 * capability, but it seems to be broken on some
116383f2b963STejun Heo 		 * chipsets including NVIDIAs.
116483f2b963STejun Heo 		 */
116583f2b963STejun Heo 		if (!(hpriv->flags & AHCI_HFLAG_NO_FPDMA_AA))
1166453d3131SRobert Hancock 			pi.flags |= ATA_FLAG_FPDMA_AA;
1167453d3131SRobert Hancock 	}
11684447d351STejun Heo 
11697d50b60bSTejun Heo 	if (hpriv->cap & HOST_CAP_PMP)
11707d50b60bSTejun Heo 		pi.flags |= ATA_FLAG_PMP;
11717d50b60bSTejun Heo 
11720cbb0e77SAnton Vorontsov 	ahci_set_em_messages(hpriv, &pi);
117318f7ba4cSKristen Carlson Accardi 
11741fd68434SRafael J. Wysocki 	if (ahci_broken_system_poweroff(pdev)) {
11751fd68434SRafael J. Wysocki 		pi.flags |= ATA_FLAG_NO_POWEROFF_SPINDOWN;
11761fd68434SRafael J. Wysocki 		dev_info(&pdev->dev,
11771fd68434SRafael J. Wysocki 			"quirky BIOS, skipping spindown on poweroff\n");
11781fd68434SRafael J. Wysocki 	}
11791fd68434SRafael J. Wysocki 
11809b10ae86STejun Heo 	if (ahci_broken_suspend(pdev)) {
11819b10ae86STejun Heo 		hpriv->flags |= AHCI_HFLAG_NO_SUSPEND;
1182a44fec1fSJoe Perches 		dev_warn(&pdev->dev,
11839b10ae86STejun Heo 			 "BIOS update required for suspend/resume\n");
11849b10ae86STejun Heo 	}
11859b10ae86STejun Heo 
11865594639aSTejun Heo 	if (ahci_broken_online(pdev)) {
11875594639aSTejun Heo 		hpriv->flags |= AHCI_HFLAG_SRST_TOUT_IS_OFFLINE;
11885594639aSTejun Heo 		dev_info(&pdev->dev,
11895594639aSTejun Heo 			 "online status unreliable, applying workaround\n");
11905594639aSTejun Heo 	}
11915594639aSTejun Heo 
1192837f5f8fSTejun Heo 	/* CAP.NP sometimes indicate the index of the last enabled
1193837f5f8fSTejun Heo 	 * port, at other times, that of the last possible port, so
1194837f5f8fSTejun Heo 	 * determining the maximum port number requires looking at
1195837f5f8fSTejun Heo 	 * both CAP.NP and port_map.
1196837f5f8fSTejun Heo 	 */
1197837f5f8fSTejun Heo 	n_ports = max(ahci_nr_ports(hpriv->cap), fls(hpriv->port_map));
1198837f5f8fSTejun Heo 
1199837f5f8fSTejun Heo 	host = ata_host_alloc_pinfo(&pdev->dev, ppi, n_ports);
12004447d351STejun Heo 	if (!host)
12014447d351STejun Heo 		return -ENOMEM;
12024447d351STejun Heo 	host->private_data = hpriv;
12034447d351STejun Heo 
1204f3d7f23fSArjan van de Ven 	if (!(hpriv->cap & HOST_CAP_SSS) || ahci_ignore_sss)
1205886ad09fSArjan van de Ven 		host->flags |= ATA_HOST_PARALLEL_SCAN;
1206f3d7f23fSArjan van de Ven 	else
1207f3d7f23fSArjan van de Ven 		printk(KERN_INFO "ahci: SSS flag set, parallel bus scan disabled\n");
1208886ad09fSArjan van de Ven 
120918f7ba4cSKristen Carlson Accardi 	if (pi.flags & ATA_FLAG_EM)
121018f7ba4cSKristen Carlson Accardi 		ahci_reset_em(host);
121118f7ba4cSKristen Carlson Accardi 
12124447d351STejun Heo 	for (i = 0; i < host->n_ports; i++) {
12134447d351STejun Heo 		struct ata_port *ap = host->ports[i];
12144447d351STejun Heo 
1215318893e1SAlessandro Rubini 		ata_port_pbar_desc(ap, ahci_pci_bar, -1, "abar");
1216318893e1SAlessandro Rubini 		ata_port_pbar_desc(ap, ahci_pci_bar,
1217cbcdd875STejun Heo 				   0x100 + ap->port_no * 0x80, "port");
1218cbcdd875STejun Heo 
121918f7ba4cSKristen Carlson Accardi 		/* set enclosure management message type */
122018f7ba4cSKristen Carlson Accardi 		if (ap->flags & ATA_FLAG_EM)
1221008dbd61SHarry Zhang 			ap->em_message_type = hpriv->em_msg_type;
122218f7ba4cSKristen Carlson Accardi 
122318f7ba4cSKristen Carlson Accardi 
1224dab632e8SJeff Garzik 		/* disabled/not-implemented port */
1225350756f6STejun Heo 		if (!(hpriv->port_map & (1 << i)))
1226dab632e8SJeff Garzik 			ap->ops = &ata_dummy_port_ops;
12274447d351STejun Heo 	}
1228c6fd2807SJeff Garzik 
1229edc93052STejun Heo 	/* apply workaround for ASUS P5W DH Deluxe mainboard */
1230edc93052STejun Heo 	ahci_p5wdh_workaround(host);
1231edc93052STejun Heo 
1232f80ae7e4STejun Heo 	/* apply gtf filter quirk */
1233f80ae7e4STejun Heo 	ahci_gtf_filter_workaround(host);
1234f80ae7e4STejun Heo 
1235c6fd2807SJeff Garzik 	/* initialize adapter */
12364447d351STejun Heo 	rc = ahci_configure_dma_masks(pdev, hpriv->cap & HOST_CAP_64);
1237c6fd2807SJeff Garzik 	if (rc)
123824dc5f33STejun Heo 		return rc;
1239c6fd2807SJeff Garzik 
12403303040dSAnton Vorontsov 	rc = ahci_pci_reset_controller(host);
12414447d351STejun Heo 	if (rc)
12424447d351STejun Heo 		return rc;
1243c6fd2807SJeff Garzik 
1244781d6550SAnton Vorontsov 	ahci_pci_init_controller(host);
1245439fcaecSAnton Vorontsov 	ahci_pci_print_info(host);
1246c6fd2807SJeff Garzik 
12474447d351STejun Heo 	pci_set_master(pdev);
12484447d351STejun Heo 	return ata_host_activate(host, pdev->irq, ahci_interrupt, IRQF_SHARED,
12494447d351STejun Heo 				 &ahci_sht);
1250c6fd2807SJeff Garzik }
1251c6fd2807SJeff Garzik 
1252c6fd2807SJeff Garzik static int __init ahci_init(void)
1253c6fd2807SJeff Garzik {
1254c6fd2807SJeff Garzik 	return pci_register_driver(&ahci_pci_driver);
1255c6fd2807SJeff Garzik }
1256c6fd2807SJeff Garzik 
1257c6fd2807SJeff Garzik static void __exit ahci_exit(void)
1258c6fd2807SJeff Garzik {
1259c6fd2807SJeff Garzik 	pci_unregister_driver(&ahci_pci_driver);
1260c6fd2807SJeff Garzik }
1261c6fd2807SJeff Garzik 
1262c6fd2807SJeff Garzik 
1263c6fd2807SJeff Garzik MODULE_AUTHOR("Jeff Garzik");
1264c6fd2807SJeff Garzik MODULE_DESCRIPTION("AHCI SATA low-level driver");
1265c6fd2807SJeff Garzik MODULE_LICENSE("GPL");
1266c6fd2807SJeff Garzik MODULE_DEVICE_TABLE(pci, ahci_pci_tbl);
1267c6fd2807SJeff Garzik MODULE_VERSION(DRV_VERSION);
1268c6fd2807SJeff Garzik 
1269c6fd2807SJeff Garzik module_init(ahci_init);
1270c6fd2807SJeff Garzik module_exit(ahci_exit);
1271