1c6fd2807SJeff Garzik /* 2c6fd2807SJeff Garzik * ahci.c - AHCI SATA support 3c6fd2807SJeff Garzik * 48c3d3d4bSTejun Heo * Maintained by: Tejun Heo <tj@kernel.org> 5c6fd2807SJeff Garzik * Please ALWAYS copy linux-ide@vger.kernel.org 6c6fd2807SJeff Garzik * on emails. 7c6fd2807SJeff Garzik * 8c6fd2807SJeff Garzik * Copyright 2004-2005 Red Hat, Inc. 9c6fd2807SJeff Garzik * 10c6fd2807SJeff Garzik * 11c6fd2807SJeff Garzik * This program is free software; you can redistribute it and/or modify 12c6fd2807SJeff Garzik * it under the terms of the GNU General Public License as published by 13c6fd2807SJeff Garzik * the Free Software Foundation; either version 2, or (at your option) 14c6fd2807SJeff Garzik * any later version. 15c6fd2807SJeff Garzik * 16c6fd2807SJeff Garzik * This program is distributed in the hope that it will be useful, 17c6fd2807SJeff Garzik * but WITHOUT ANY WARRANTY; without even the implied warranty of 18c6fd2807SJeff Garzik * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 19c6fd2807SJeff Garzik * GNU General Public License for more details. 20c6fd2807SJeff Garzik * 21c6fd2807SJeff Garzik * You should have received a copy of the GNU General Public License 22c6fd2807SJeff Garzik * along with this program; see the file COPYING. If not, write to 23c6fd2807SJeff Garzik * the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. 24c6fd2807SJeff Garzik * 25c6fd2807SJeff Garzik * 26c6fd2807SJeff Garzik * libata documentation is available via 'make {ps|pdf}docs', 27c6fd2807SJeff Garzik * as Documentation/DocBook/libata.* 28c6fd2807SJeff Garzik * 29c6fd2807SJeff Garzik * AHCI hardware documentation: 30c6fd2807SJeff Garzik * http://www.intel.com/technology/serialata/pdf/rev1_0.pdf 31c6fd2807SJeff Garzik * http://www.intel.com/technology/serialata/pdf/rev1_1.pdf 32c6fd2807SJeff Garzik * 33c6fd2807SJeff Garzik */ 34c6fd2807SJeff Garzik 35c6fd2807SJeff Garzik #include <linux/kernel.h> 36c6fd2807SJeff Garzik #include <linux/module.h> 37c6fd2807SJeff Garzik #include <linux/pci.h> 38c6fd2807SJeff Garzik #include <linux/blkdev.h> 39c6fd2807SJeff Garzik #include <linux/delay.h> 40c6fd2807SJeff Garzik #include <linux/interrupt.h> 41c6fd2807SJeff Garzik #include <linux/dma-mapping.h> 42c6fd2807SJeff Garzik #include <linux/device.h> 43edc93052STejun Heo #include <linux/dmi.h> 445a0e3ad6STejun Heo #include <linux/gfp.h> 45c6fd2807SJeff Garzik #include <scsi/scsi_host.h> 46c6fd2807SJeff Garzik #include <scsi/scsi_cmnd.h> 47c6fd2807SJeff Garzik #include <linux/libata.h> 48365cfa1eSAnton Vorontsov #include "ahci.h" 49c6fd2807SJeff Garzik 50c6fd2807SJeff Garzik #define DRV_NAME "ahci" 517d50b60bSTejun Heo #define DRV_VERSION "3.0" 52c6fd2807SJeff Garzik 53c6fd2807SJeff Garzik enum { 54318893e1SAlessandro Rubini AHCI_PCI_BAR_STA2X11 = 0, 557f9c9f8eSHugh Daschbach AHCI_PCI_BAR_ENMOTUS = 2, 56318893e1SAlessandro Rubini AHCI_PCI_BAR_STANDARD = 5, 57441577efSTejun Heo }; 58c6fd2807SJeff Garzik 59441577efSTejun Heo enum board_ids { 60441577efSTejun Heo /* board IDs by feature in alphabetical order */ 61441577efSTejun Heo board_ahci, 62441577efSTejun Heo board_ahci_ign_iferr, 6366a7cbc3STejun Heo board_ahci_nomsi, 6467809f85SLevente Kurusa board_ahci_noncq, 65441577efSTejun Heo board_ahci_nosntf, 665f173107STejun Heo board_ahci_yes_fbs, 67441577efSTejun Heo 68441577efSTejun Heo /* board IDs for specific chipsets in alphabetical order */ 69*dbfe8ef5SDan Williams board_ahci_avn, 70441577efSTejun Heo board_ahci_mcp65, 7183f2b963STejun Heo board_ahci_mcp77, 7283f2b963STejun Heo board_ahci_mcp89, 73441577efSTejun Heo board_ahci_mv, 74441577efSTejun Heo board_ahci_sb600, 75441577efSTejun Heo board_ahci_sb700, /* for SB700 and SB800 */ 76441577efSTejun Heo board_ahci_vt8251, 77441577efSTejun Heo 78441577efSTejun Heo /* aliases */ 79441577efSTejun Heo board_ahci_mcp_linux = board_ahci_mcp65, 80441577efSTejun Heo board_ahci_mcp67 = board_ahci_mcp65, 81441577efSTejun Heo board_ahci_mcp73 = board_ahci_mcp65, 8283f2b963STejun Heo board_ahci_mcp79 = board_ahci_mcp77, 83c6fd2807SJeff Garzik }; 84c6fd2807SJeff Garzik 85c6fd2807SJeff Garzik static int ahci_init_one(struct pci_dev *pdev, const struct pci_device_id *ent); 86a1efdabaSTejun Heo static int ahci_vt8251_hardreset(struct ata_link *link, unsigned int *class, 87a1efdabaSTejun Heo unsigned long deadline); 88*dbfe8ef5SDan Williams static int ahci_avn_hardreset(struct ata_link *link, unsigned int *class, 89*dbfe8ef5SDan Williams unsigned long deadline); 90cb85696dSJames Laird static void ahci_mcp89_apple_enable(struct pci_dev *pdev); 91cb85696dSJames Laird static bool is_mcp89_apple(struct pci_dev *pdev); 92a1efdabaSTejun Heo static int ahci_p5wdh_hardreset(struct ata_link *link, unsigned int *class, 93a1efdabaSTejun Heo unsigned long deadline); 94438ac6d5STejun Heo #ifdef CONFIG_PM 95c6fd2807SJeff Garzik static int ahci_pci_device_suspend(struct pci_dev *pdev, pm_message_t mesg); 96c6fd2807SJeff Garzik static int ahci_pci_device_resume(struct pci_dev *pdev); 97438ac6d5STejun Heo #endif 98c6fd2807SJeff Garzik 99fad16e7aSTejun Heo static struct scsi_host_template ahci_sht = { 100fad16e7aSTejun Heo AHCI_SHT("ahci"), 101fad16e7aSTejun Heo }; 102fad16e7aSTejun Heo 103029cfd6bSTejun Heo static struct ata_port_operations ahci_vt8251_ops = { 104029cfd6bSTejun Heo .inherits = &ahci_ops, 105a1efdabaSTejun Heo .hardreset = ahci_vt8251_hardreset, 106ad616ffbSTejun Heo }; 107ad616ffbSTejun Heo 108029cfd6bSTejun Heo static struct ata_port_operations ahci_p5wdh_ops = { 109029cfd6bSTejun Heo .inherits = &ahci_ops, 110a1efdabaSTejun Heo .hardreset = ahci_p5wdh_hardreset, 111edc93052STejun Heo }; 112edc93052STejun Heo 113*dbfe8ef5SDan Williams static struct ata_port_operations ahci_avn_ops = { 114*dbfe8ef5SDan Williams .inherits = &ahci_ops, 115*dbfe8ef5SDan Williams .hardreset = ahci_avn_hardreset, 116*dbfe8ef5SDan Williams }; 117*dbfe8ef5SDan Williams 118c6fd2807SJeff Garzik static const struct ata_port_info ahci_port_info[] = { 119441577efSTejun Heo /* by features */ 120facb8fa6SJeffrin Jose [board_ahci] = { 1211188c0d8STejun Heo .flags = AHCI_FLAG_COMMON, 12214bdef98SErik Inge Bolsø .pio_mask = ATA_PIO4, 123469248abSJeff Garzik .udma_mask = ATA_UDMA6, 124c6fd2807SJeff Garzik .port_ops = &ahci_ops, 125c6fd2807SJeff Garzik }, 126facb8fa6SJeffrin Jose [board_ahci_ign_iferr] = { 127417a1a6dSTejun Heo AHCI_HFLAGS (AHCI_HFLAG_IGN_IRQ_IF_ERR), 128417a1a6dSTejun Heo .flags = AHCI_FLAG_COMMON, 12914bdef98SErik Inge Bolsø .pio_mask = ATA_PIO4, 130469248abSJeff Garzik .udma_mask = ATA_UDMA6, 13141669553STejun Heo .port_ops = &ahci_ops, 13241669553STejun Heo }, 13366a7cbc3STejun Heo [board_ahci_nomsi] = { 13466a7cbc3STejun Heo AHCI_HFLAGS (AHCI_HFLAG_NO_MSI), 13566a7cbc3STejun Heo .flags = AHCI_FLAG_COMMON, 13666a7cbc3STejun Heo .pio_mask = ATA_PIO4, 13766a7cbc3STejun Heo .udma_mask = ATA_UDMA6, 13866a7cbc3STejun Heo .port_ops = &ahci_ops, 13966a7cbc3STejun Heo }, 14067809f85SLevente Kurusa [board_ahci_noncq] = { 14167809f85SLevente Kurusa AHCI_HFLAGS (AHCI_HFLAG_NO_NCQ), 14267809f85SLevente Kurusa .flags = AHCI_FLAG_COMMON, 14367809f85SLevente Kurusa .pio_mask = ATA_PIO4, 14467809f85SLevente Kurusa .udma_mask = ATA_UDMA6, 14567809f85SLevente Kurusa .port_ops = &ahci_ops, 14667809f85SLevente Kurusa }, 147facb8fa6SJeffrin Jose [board_ahci_nosntf] = { 148441577efSTejun Heo AHCI_HFLAGS (AHCI_HFLAG_NO_SNTF), 149441577efSTejun Heo .flags = AHCI_FLAG_COMMON, 150441577efSTejun Heo .pio_mask = ATA_PIO4, 151441577efSTejun Heo .udma_mask = ATA_UDMA6, 152441577efSTejun Heo .port_ops = &ahci_ops, 153441577efSTejun Heo }, 154facb8fa6SJeffrin Jose [board_ahci_yes_fbs] = { 1555f173107STejun Heo AHCI_HFLAGS (AHCI_HFLAG_YES_FBS), 1565f173107STejun Heo .flags = AHCI_FLAG_COMMON, 1575f173107STejun Heo .pio_mask = ATA_PIO4, 1585f173107STejun Heo .udma_mask = ATA_UDMA6, 1595f173107STejun Heo .port_ops = &ahci_ops, 1605f173107STejun Heo }, 161441577efSTejun Heo /* by chipsets */ 162*dbfe8ef5SDan Williams [board_ahci_avn] = { 163*dbfe8ef5SDan Williams .flags = AHCI_FLAG_COMMON, 164*dbfe8ef5SDan Williams .pio_mask = ATA_PIO4, 165*dbfe8ef5SDan Williams .udma_mask = ATA_UDMA6, 166*dbfe8ef5SDan Williams .port_ops = &ahci_avn_ops, 167*dbfe8ef5SDan Williams }, 168facb8fa6SJeffrin Jose [board_ahci_mcp65] = { 16983f2b963STejun Heo AHCI_HFLAGS (AHCI_HFLAG_NO_FPDMA_AA | AHCI_HFLAG_NO_PMP | 17083f2b963STejun Heo AHCI_HFLAG_YES_NCQ), 171ae01b249STejun Heo .flags = AHCI_FLAG_COMMON | ATA_FLAG_NO_DIPM, 17283f2b963STejun Heo .pio_mask = ATA_PIO4, 17383f2b963STejun Heo .udma_mask = ATA_UDMA6, 17483f2b963STejun Heo .port_ops = &ahci_ops, 17583f2b963STejun Heo }, 176facb8fa6SJeffrin Jose [board_ahci_mcp77] = { 17783f2b963STejun Heo AHCI_HFLAGS (AHCI_HFLAG_NO_FPDMA_AA | AHCI_HFLAG_NO_PMP), 17883f2b963STejun Heo .flags = AHCI_FLAG_COMMON, 17983f2b963STejun Heo .pio_mask = ATA_PIO4, 18083f2b963STejun Heo .udma_mask = ATA_UDMA6, 18183f2b963STejun Heo .port_ops = &ahci_ops, 18283f2b963STejun Heo }, 183facb8fa6SJeffrin Jose [board_ahci_mcp89] = { 18483f2b963STejun Heo AHCI_HFLAGS (AHCI_HFLAG_NO_FPDMA_AA), 185441577efSTejun Heo .flags = AHCI_FLAG_COMMON, 186441577efSTejun Heo .pio_mask = ATA_PIO4, 187441577efSTejun Heo .udma_mask = ATA_UDMA6, 188441577efSTejun Heo .port_ops = &ahci_ops, 189441577efSTejun Heo }, 190facb8fa6SJeffrin Jose [board_ahci_mv] = { 191441577efSTejun Heo AHCI_HFLAGS (AHCI_HFLAG_NO_NCQ | AHCI_HFLAG_NO_MSI | 192441577efSTejun Heo AHCI_HFLAG_MV_PATA | AHCI_HFLAG_NO_PMP), 1939cbe056fSSergei Shtylyov .flags = ATA_FLAG_SATA | ATA_FLAG_PIO_DMA, 194441577efSTejun Heo .pio_mask = ATA_PIO4, 195441577efSTejun Heo .udma_mask = ATA_UDMA6, 196441577efSTejun Heo .port_ops = &ahci_ops, 197441577efSTejun Heo }, 198facb8fa6SJeffrin Jose [board_ahci_sb600] = { 199417a1a6dSTejun Heo AHCI_HFLAGS (AHCI_HFLAG_IGN_SERR_INTERNAL | 2002fcad9d2STejun Heo AHCI_HFLAG_NO_MSI | AHCI_HFLAG_SECT255 | 2012fcad9d2STejun Heo AHCI_HFLAG_32BIT_ONLY), 202417a1a6dSTejun Heo .flags = AHCI_FLAG_COMMON, 20314bdef98SErik Inge Bolsø .pio_mask = ATA_PIO4, 204469248abSJeff Garzik .udma_mask = ATA_UDMA6, 205345347c5SYuan-Hsin Chen .port_ops = &ahci_pmp_retry_srst_ops, 20655a61604SConke Hu }, 207facb8fa6SJeffrin Jose [board_ahci_sb700] = { /* for SB700 and SB800 */ 208bd17243aSShane Huang AHCI_HFLAGS (AHCI_HFLAG_IGN_SERR_INTERNAL), 209e39fc8c9SShane Huang .flags = AHCI_FLAG_COMMON, 21014bdef98SErik Inge Bolsø .pio_mask = ATA_PIO4, 211e39fc8c9SShane Huang .udma_mask = ATA_UDMA6, 212345347c5SYuan-Hsin Chen .port_ops = &ahci_pmp_retry_srst_ops, 213e39fc8c9SShane Huang }, 214facb8fa6SJeffrin Jose [board_ahci_vt8251] = { 215441577efSTejun Heo AHCI_HFLAGS (AHCI_HFLAG_NO_NCQ | AHCI_HFLAG_NO_PMP), 216e297d99eSTejun Heo .flags = AHCI_FLAG_COMMON, 21714bdef98SErik Inge Bolsø .pio_mask = ATA_PIO4, 218e297d99eSTejun Heo .udma_mask = ATA_UDMA6, 219441577efSTejun Heo .port_ops = &ahci_vt8251_ops, 2201b677afdSShaohua Li }, 221c6fd2807SJeff Garzik }; 222c6fd2807SJeff Garzik 223c6fd2807SJeff Garzik static const struct pci_device_id ahci_pci_tbl[] = { 224c6fd2807SJeff Garzik /* Intel */ 22554bb3a94SJeff Garzik { PCI_VDEVICE(INTEL, 0x2652), board_ahci }, /* ICH6 */ 22654bb3a94SJeff Garzik { PCI_VDEVICE(INTEL, 0x2653), board_ahci }, /* ICH6M */ 22754bb3a94SJeff Garzik { PCI_VDEVICE(INTEL, 0x27c1), board_ahci }, /* ICH7 */ 22854bb3a94SJeff Garzik { PCI_VDEVICE(INTEL, 0x27c5), board_ahci }, /* ICH7M */ 22954bb3a94SJeff Garzik { PCI_VDEVICE(INTEL, 0x27c3), board_ahci }, /* ICH7R */ 23082490c09STejun Heo { PCI_VDEVICE(AL, 0x5288), board_ahci_ign_iferr }, /* ULi M5288 */ 23154bb3a94SJeff Garzik { PCI_VDEVICE(INTEL, 0x2681), board_ahci }, /* ESB2 */ 23254bb3a94SJeff Garzik { PCI_VDEVICE(INTEL, 0x2682), board_ahci }, /* ESB2 */ 23354bb3a94SJeff Garzik { PCI_VDEVICE(INTEL, 0x2683), board_ahci }, /* ESB2 */ 23454bb3a94SJeff Garzik { PCI_VDEVICE(INTEL, 0x27c6), board_ahci }, /* ICH7-M DH */ 2357a234affSTejun Heo { PCI_VDEVICE(INTEL, 0x2821), board_ahci }, /* ICH8 */ 2361b677afdSShaohua Li { PCI_VDEVICE(INTEL, 0x2822), board_ahci_nosntf }, /* ICH8 */ 2377a234affSTejun Heo { PCI_VDEVICE(INTEL, 0x2824), board_ahci }, /* ICH8 */ 2387a234affSTejun Heo { PCI_VDEVICE(INTEL, 0x2829), board_ahci }, /* ICH8M */ 2397a234affSTejun Heo { PCI_VDEVICE(INTEL, 0x282a), board_ahci }, /* ICH8M */ 2407a234affSTejun Heo { PCI_VDEVICE(INTEL, 0x2922), board_ahci }, /* ICH9 */ 2417a234affSTejun Heo { PCI_VDEVICE(INTEL, 0x2923), board_ahci }, /* ICH9 */ 2427a234affSTejun Heo { PCI_VDEVICE(INTEL, 0x2924), board_ahci }, /* ICH9 */ 2437a234affSTejun Heo { PCI_VDEVICE(INTEL, 0x2925), board_ahci }, /* ICH9 */ 2447a234affSTejun Heo { PCI_VDEVICE(INTEL, 0x2927), board_ahci }, /* ICH9 */ 2457a234affSTejun Heo { PCI_VDEVICE(INTEL, 0x2929), board_ahci }, /* ICH9M */ 2467a234affSTejun Heo { PCI_VDEVICE(INTEL, 0x292a), board_ahci }, /* ICH9M */ 2477a234affSTejun Heo { PCI_VDEVICE(INTEL, 0x292b), board_ahci }, /* ICH9M */ 2487a234affSTejun Heo { PCI_VDEVICE(INTEL, 0x292c), board_ahci }, /* ICH9M */ 2497a234affSTejun Heo { PCI_VDEVICE(INTEL, 0x292f), board_ahci }, /* ICH9M */ 2507a234affSTejun Heo { PCI_VDEVICE(INTEL, 0x294d), board_ahci }, /* ICH9 */ 2517a234affSTejun Heo { PCI_VDEVICE(INTEL, 0x294e), board_ahci }, /* ICH9M */ 252d4155e6fSJason Gaston { PCI_VDEVICE(INTEL, 0x502a), board_ahci }, /* Tolapai */ 253d4155e6fSJason Gaston { PCI_VDEVICE(INTEL, 0x502b), board_ahci }, /* Tolapai */ 25416ad1ad9SJason Gaston { PCI_VDEVICE(INTEL, 0x3a05), board_ahci }, /* ICH10 */ 255b2dde6afSMark Goodwin { PCI_VDEVICE(INTEL, 0x3a22), board_ahci }, /* ICH10 */ 25616ad1ad9SJason Gaston { PCI_VDEVICE(INTEL, 0x3a25), board_ahci }, /* ICH10 */ 257c1f57d9bSDavid Milburn { PCI_VDEVICE(INTEL, 0x3b22), board_ahci }, /* PCH AHCI */ 258c1f57d9bSDavid Milburn { PCI_VDEVICE(INTEL, 0x3b23), board_ahci }, /* PCH AHCI */ 259adcb5308SSeth Heasley { PCI_VDEVICE(INTEL, 0x3b24), board_ahci }, /* PCH RAID */ 2608e48b6b3SSeth Heasley { PCI_VDEVICE(INTEL, 0x3b25), board_ahci }, /* PCH RAID */ 261c1f57d9bSDavid Milburn { PCI_VDEVICE(INTEL, 0x3b29), board_ahci }, /* PCH AHCI */ 262adcb5308SSeth Heasley { PCI_VDEVICE(INTEL, 0x3b2b), board_ahci }, /* PCH RAID */ 2638e48b6b3SSeth Heasley { PCI_VDEVICE(INTEL, 0x3b2c), board_ahci }, /* PCH RAID */ 264c1f57d9bSDavid Milburn { PCI_VDEVICE(INTEL, 0x3b2f), board_ahci }, /* PCH AHCI */ 2655623cab8SSeth Heasley { PCI_VDEVICE(INTEL, 0x1c02), board_ahci }, /* CPT AHCI */ 2665623cab8SSeth Heasley { PCI_VDEVICE(INTEL, 0x1c03), board_ahci }, /* CPT AHCI */ 2675623cab8SSeth Heasley { PCI_VDEVICE(INTEL, 0x1c04), board_ahci }, /* CPT RAID */ 2685623cab8SSeth Heasley { PCI_VDEVICE(INTEL, 0x1c05), board_ahci }, /* CPT RAID */ 2695623cab8SSeth Heasley { PCI_VDEVICE(INTEL, 0x1c06), board_ahci }, /* CPT RAID */ 2705623cab8SSeth Heasley { PCI_VDEVICE(INTEL, 0x1c07), board_ahci }, /* CPT RAID */ 271992b3fb9SSeth Heasley { PCI_VDEVICE(INTEL, 0x1d02), board_ahci }, /* PBG AHCI */ 272992b3fb9SSeth Heasley { PCI_VDEVICE(INTEL, 0x1d04), board_ahci }, /* PBG RAID */ 273992b3fb9SSeth Heasley { PCI_VDEVICE(INTEL, 0x1d06), board_ahci }, /* PBG RAID */ 27464a3903dSSeth Heasley { PCI_VDEVICE(INTEL, 0x2826), board_ahci }, /* PBG RAID */ 275a4a461a6SSeth Heasley { PCI_VDEVICE(INTEL, 0x2323), board_ahci }, /* DH89xxCC AHCI */ 276181e3ceaSSeth Heasley { PCI_VDEVICE(INTEL, 0x1e02), board_ahci }, /* Panther Point AHCI */ 277181e3ceaSSeth Heasley { PCI_VDEVICE(INTEL, 0x1e03), board_ahci }, /* Panther Point AHCI */ 278181e3ceaSSeth Heasley { PCI_VDEVICE(INTEL, 0x1e04), board_ahci }, /* Panther Point RAID */ 279181e3ceaSSeth Heasley { PCI_VDEVICE(INTEL, 0x1e05), board_ahci }, /* Panther Point RAID */ 280181e3ceaSSeth Heasley { PCI_VDEVICE(INTEL, 0x1e06), board_ahci }, /* Panther Point RAID */ 281181e3ceaSSeth Heasley { PCI_VDEVICE(INTEL, 0x1e07), board_ahci }, /* Panther Point RAID */ 2822cab7a4cSSeth Heasley { PCI_VDEVICE(INTEL, 0x1e0e), board_ahci }, /* Panther Point RAID */ 283ea4ace66SSeth Heasley { PCI_VDEVICE(INTEL, 0x8c02), board_ahci }, /* Lynx Point AHCI */ 284ea4ace66SSeth Heasley { PCI_VDEVICE(INTEL, 0x8c03), board_ahci }, /* Lynx Point AHCI */ 285ea4ace66SSeth Heasley { PCI_VDEVICE(INTEL, 0x8c04), board_ahci }, /* Lynx Point RAID */ 286ea4ace66SSeth Heasley { PCI_VDEVICE(INTEL, 0x8c05), board_ahci }, /* Lynx Point RAID */ 287ea4ace66SSeth Heasley { PCI_VDEVICE(INTEL, 0x8c06), board_ahci }, /* Lynx Point RAID */ 288ea4ace66SSeth Heasley { PCI_VDEVICE(INTEL, 0x8c07), board_ahci }, /* Lynx Point RAID */ 289ea4ace66SSeth Heasley { PCI_VDEVICE(INTEL, 0x8c0e), board_ahci }, /* Lynx Point RAID */ 290ea4ace66SSeth Heasley { PCI_VDEVICE(INTEL, 0x8c0f), board_ahci }, /* Lynx Point RAID */ 29177b12bc9SJames Ralston { PCI_VDEVICE(INTEL, 0x9c02), board_ahci }, /* Lynx Point-LP AHCI */ 29277b12bc9SJames Ralston { PCI_VDEVICE(INTEL, 0x9c03), board_ahci }, /* Lynx Point-LP AHCI */ 29377b12bc9SJames Ralston { PCI_VDEVICE(INTEL, 0x9c04), board_ahci }, /* Lynx Point-LP RAID */ 29477b12bc9SJames Ralston { PCI_VDEVICE(INTEL, 0x9c05), board_ahci }, /* Lynx Point-LP RAID */ 29577b12bc9SJames Ralston { PCI_VDEVICE(INTEL, 0x9c06), board_ahci }, /* Lynx Point-LP RAID */ 29677b12bc9SJames Ralston { PCI_VDEVICE(INTEL, 0x9c07), board_ahci }, /* Lynx Point-LP RAID */ 29777b12bc9SJames Ralston { PCI_VDEVICE(INTEL, 0x9c0e), board_ahci }, /* Lynx Point-LP RAID */ 29877b12bc9SJames Ralston { PCI_VDEVICE(INTEL, 0x9c0f), board_ahci }, /* Lynx Point-LP RAID */ 29929e674ddSSeth Heasley { PCI_VDEVICE(INTEL, 0x1f22), board_ahci }, /* Avoton AHCI */ 30029e674ddSSeth Heasley { PCI_VDEVICE(INTEL, 0x1f23), board_ahci }, /* Avoton AHCI */ 30129e674ddSSeth Heasley { PCI_VDEVICE(INTEL, 0x1f24), board_ahci }, /* Avoton RAID */ 30229e674ddSSeth Heasley { PCI_VDEVICE(INTEL, 0x1f25), board_ahci }, /* Avoton RAID */ 30329e674ddSSeth Heasley { PCI_VDEVICE(INTEL, 0x1f26), board_ahci }, /* Avoton RAID */ 30429e674ddSSeth Heasley { PCI_VDEVICE(INTEL, 0x1f27), board_ahci }, /* Avoton RAID */ 30529e674ddSSeth Heasley { PCI_VDEVICE(INTEL, 0x1f2e), board_ahci }, /* Avoton RAID */ 30629e674ddSSeth Heasley { PCI_VDEVICE(INTEL, 0x1f2f), board_ahci }, /* Avoton RAID */ 307*dbfe8ef5SDan Williams { PCI_VDEVICE(INTEL, 0x1f32), board_ahci_avn }, /* Avoton AHCI */ 308*dbfe8ef5SDan Williams { PCI_VDEVICE(INTEL, 0x1f33), board_ahci_avn }, /* Avoton AHCI */ 309*dbfe8ef5SDan Williams { PCI_VDEVICE(INTEL, 0x1f34), board_ahci_avn }, /* Avoton RAID */ 310*dbfe8ef5SDan Williams { PCI_VDEVICE(INTEL, 0x1f35), board_ahci_avn }, /* Avoton RAID */ 311*dbfe8ef5SDan Williams { PCI_VDEVICE(INTEL, 0x1f36), board_ahci_avn }, /* Avoton RAID */ 312*dbfe8ef5SDan Williams { PCI_VDEVICE(INTEL, 0x1f37), board_ahci_avn }, /* Avoton RAID */ 313*dbfe8ef5SDan Williams { PCI_VDEVICE(INTEL, 0x1f3e), board_ahci_avn }, /* Avoton RAID */ 314*dbfe8ef5SDan Williams { PCI_VDEVICE(INTEL, 0x1f3f), board_ahci_avn }, /* Avoton RAID */ 315efda332cSJames Ralston { PCI_VDEVICE(INTEL, 0x2823), board_ahci }, /* Wellsburg RAID */ 316efda332cSJames Ralston { PCI_VDEVICE(INTEL, 0x2827), board_ahci }, /* Wellsburg RAID */ 317151743fdSJames Ralston { PCI_VDEVICE(INTEL, 0x8d02), board_ahci }, /* Wellsburg AHCI */ 318151743fdSJames Ralston { PCI_VDEVICE(INTEL, 0x8d04), board_ahci }, /* Wellsburg RAID */ 319151743fdSJames Ralston { PCI_VDEVICE(INTEL, 0x8d06), board_ahci }, /* Wellsburg RAID */ 320151743fdSJames Ralston { PCI_VDEVICE(INTEL, 0x8d0e), board_ahci }, /* Wellsburg RAID */ 321151743fdSJames Ralston { PCI_VDEVICE(INTEL, 0x8d62), board_ahci }, /* Wellsburg AHCI */ 322151743fdSJames Ralston { PCI_VDEVICE(INTEL, 0x8d64), board_ahci }, /* Wellsburg RAID */ 323151743fdSJames Ralston { PCI_VDEVICE(INTEL, 0x8d66), board_ahci }, /* Wellsburg RAID */ 324151743fdSJames Ralston { PCI_VDEVICE(INTEL, 0x8d6e), board_ahci }, /* Wellsburg RAID */ 3251cfc7df3SSeth Heasley { PCI_VDEVICE(INTEL, 0x23a3), board_ahci }, /* Coleto Creek AHCI */ 3269f961a5fSJames Ralston { PCI_VDEVICE(INTEL, 0x9c83), board_ahci }, /* Wildcat Point-LP AHCI */ 3279f961a5fSJames Ralston { PCI_VDEVICE(INTEL, 0x9c85), board_ahci }, /* Wildcat Point-LP RAID */ 3289f961a5fSJames Ralston { PCI_VDEVICE(INTEL, 0x9c87), board_ahci }, /* Wildcat Point-LP RAID */ 3299f961a5fSJames Ralston { PCI_VDEVICE(INTEL, 0x9c8f), board_ahci }, /* Wildcat Point-LP RAID */ 3301b071a09SJames Ralston { PCI_VDEVICE(INTEL, 0x8c82), board_ahci }, /* 9 Series AHCI */ 3311b071a09SJames Ralston { PCI_VDEVICE(INTEL, 0x8c83), board_ahci }, /* 9 Series AHCI */ 3321b071a09SJames Ralston { PCI_VDEVICE(INTEL, 0x8c84), board_ahci }, /* 9 Series RAID */ 3331b071a09SJames Ralston { PCI_VDEVICE(INTEL, 0x8c85), board_ahci }, /* 9 Series RAID */ 3341b071a09SJames Ralston { PCI_VDEVICE(INTEL, 0x8c86), board_ahci }, /* 9 Series RAID */ 3351b071a09SJames Ralston { PCI_VDEVICE(INTEL, 0x8c87), board_ahci }, /* 9 Series RAID */ 3361b071a09SJames Ralston { PCI_VDEVICE(INTEL, 0x8c8e), board_ahci }, /* 9 Series RAID */ 3371b071a09SJames Ralston { PCI_VDEVICE(INTEL, 0x8c8f), board_ahci }, /* 9 Series RAID */ 338249cd0a1SDevin Ryles { PCI_VDEVICE(INTEL, 0x9d03), board_ahci }, /* Sunrise Point-LP AHCI */ 339249cd0a1SDevin Ryles { PCI_VDEVICE(INTEL, 0x9d05), board_ahci }, /* Sunrise Point-LP RAID */ 340249cd0a1SDevin Ryles { PCI_VDEVICE(INTEL, 0x9d07), board_ahci }, /* Sunrise Point-LP RAID */ 341690000b9SJames Ralston { PCI_VDEVICE(INTEL, 0xa103), board_ahci }, /* Sunrise Point-H AHCI */ 342690000b9SJames Ralston { PCI_VDEVICE(INTEL, 0xa105), board_ahci }, /* Sunrise Point-H RAID */ 343690000b9SJames Ralston { PCI_VDEVICE(INTEL, 0xa107), board_ahci }, /* Sunrise Point-H RAID */ 344690000b9SJames Ralston { PCI_VDEVICE(INTEL, 0xa10f), board_ahci }, /* Sunrise Point-H RAID */ 345c6fd2807SJeff Garzik 346e34bb370STejun Heo /* JMicron 360/1/3/5/6, match class to avoid IDE function */ 347e34bb370STejun Heo { PCI_VENDOR_ID_JMICRON, PCI_ANY_ID, PCI_ANY_ID, PCI_ANY_ID, 348e34bb370STejun Heo PCI_CLASS_STORAGE_SATA_AHCI, 0xffffff, board_ahci_ign_iferr }, 3491fefb8fdSBen Hutchings /* JMicron 362B and 362C have an AHCI function with IDE class code */ 3501fefb8fdSBen Hutchings { PCI_VDEVICE(JMICRON, 0x2362), board_ahci_ign_iferr }, 3511fefb8fdSBen Hutchings { PCI_VDEVICE(JMICRON, 0x236f), board_ahci_ign_iferr }, 352c6fd2807SJeff Garzik 353c6fd2807SJeff Garzik /* ATI */ 354c65ec1c2SConke Hu { PCI_VDEVICE(ATI, 0x4380), board_ahci_sb600 }, /* ATI SB600 */ 355e39fc8c9SShane Huang { PCI_VDEVICE(ATI, 0x4390), board_ahci_sb700 }, /* ATI SB700/800 */ 356e39fc8c9SShane Huang { PCI_VDEVICE(ATI, 0x4391), board_ahci_sb700 }, /* ATI SB700/800 */ 357e39fc8c9SShane Huang { PCI_VDEVICE(ATI, 0x4392), board_ahci_sb700 }, /* ATI SB700/800 */ 358e39fc8c9SShane Huang { PCI_VDEVICE(ATI, 0x4393), board_ahci_sb700 }, /* ATI SB700/800 */ 359e39fc8c9SShane Huang { PCI_VDEVICE(ATI, 0x4394), board_ahci_sb700 }, /* ATI SB700/800 */ 360e39fc8c9SShane Huang { PCI_VDEVICE(ATI, 0x4395), board_ahci_sb700 }, /* ATI SB700/800 */ 361c6fd2807SJeff Garzik 362e2dd90b1SShane Huang /* AMD */ 3635deab536SShane Huang { PCI_VDEVICE(AMD, 0x7800), board_ahci }, /* AMD Hudson-2 */ 364fafe5c3dSShane Huang { PCI_VDEVICE(AMD, 0x7900), board_ahci }, /* AMD CZ */ 365e2dd90b1SShane Huang /* AMD is using RAID class only for ahci controllers */ 366e2dd90b1SShane Huang { PCI_VENDOR_ID_AMD, PCI_ANY_ID, PCI_ANY_ID, PCI_ANY_ID, 367e2dd90b1SShane Huang PCI_CLASS_STORAGE_RAID << 8, 0xffffff, board_ahci }, 368e2dd90b1SShane Huang 369c6fd2807SJeff Garzik /* VIA */ 37054bb3a94SJeff Garzik { PCI_VDEVICE(VIA, 0x3349), board_ahci_vt8251 }, /* VIA VT8251 */ 371bf335542STejun Heo { PCI_VDEVICE(VIA, 0x6287), board_ahci_vt8251 }, /* VIA VT8251 */ 372c6fd2807SJeff Garzik 373c6fd2807SJeff Garzik /* NVIDIA */ 374e297d99eSTejun Heo { PCI_VDEVICE(NVIDIA, 0x044c), board_ahci_mcp65 }, /* MCP65 */ 375e297d99eSTejun Heo { PCI_VDEVICE(NVIDIA, 0x044d), board_ahci_mcp65 }, /* MCP65 */ 376e297d99eSTejun Heo { PCI_VDEVICE(NVIDIA, 0x044e), board_ahci_mcp65 }, /* MCP65 */ 377e297d99eSTejun Heo { PCI_VDEVICE(NVIDIA, 0x044f), board_ahci_mcp65 }, /* MCP65 */ 378e297d99eSTejun Heo { PCI_VDEVICE(NVIDIA, 0x045c), board_ahci_mcp65 }, /* MCP65 */ 379e297d99eSTejun Heo { PCI_VDEVICE(NVIDIA, 0x045d), board_ahci_mcp65 }, /* MCP65 */ 380e297d99eSTejun Heo { PCI_VDEVICE(NVIDIA, 0x045e), board_ahci_mcp65 }, /* MCP65 */ 381e297d99eSTejun Heo { PCI_VDEVICE(NVIDIA, 0x045f), board_ahci_mcp65 }, /* MCP65 */ 382441577efSTejun Heo { PCI_VDEVICE(NVIDIA, 0x0550), board_ahci_mcp67 }, /* MCP67 */ 383441577efSTejun Heo { PCI_VDEVICE(NVIDIA, 0x0551), board_ahci_mcp67 }, /* MCP67 */ 384441577efSTejun Heo { PCI_VDEVICE(NVIDIA, 0x0552), board_ahci_mcp67 }, /* MCP67 */ 385441577efSTejun Heo { PCI_VDEVICE(NVIDIA, 0x0553), board_ahci_mcp67 }, /* MCP67 */ 386441577efSTejun Heo { PCI_VDEVICE(NVIDIA, 0x0554), board_ahci_mcp67 }, /* MCP67 */ 387441577efSTejun Heo { PCI_VDEVICE(NVIDIA, 0x0555), board_ahci_mcp67 }, /* MCP67 */ 388441577efSTejun Heo { PCI_VDEVICE(NVIDIA, 0x0556), board_ahci_mcp67 }, /* MCP67 */ 389441577efSTejun Heo { PCI_VDEVICE(NVIDIA, 0x0557), board_ahci_mcp67 }, /* MCP67 */ 390441577efSTejun Heo { PCI_VDEVICE(NVIDIA, 0x0558), board_ahci_mcp67 }, /* MCP67 */ 391441577efSTejun Heo { PCI_VDEVICE(NVIDIA, 0x0559), board_ahci_mcp67 }, /* MCP67 */ 392441577efSTejun Heo { PCI_VDEVICE(NVIDIA, 0x055a), board_ahci_mcp67 }, /* MCP67 */ 393441577efSTejun Heo { PCI_VDEVICE(NVIDIA, 0x055b), board_ahci_mcp67 }, /* MCP67 */ 394441577efSTejun Heo { PCI_VDEVICE(NVIDIA, 0x0580), board_ahci_mcp_linux }, /* Linux ID */ 395441577efSTejun Heo { PCI_VDEVICE(NVIDIA, 0x0581), board_ahci_mcp_linux }, /* Linux ID */ 396441577efSTejun Heo { PCI_VDEVICE(NVIDIA, 0x0582), board_ahci_mcp_linux }, /* Linux ID */ 397441577efSTejun Heo { PCI_VDEVICE(NVIDIA, 0x0583), board_ahci_mcp_linux }, /* Linux ID */ 398441577efSTejun Heo { PCI_VDEVICE(NVIDIA, 0x0584), board_ahci_mcp_linux }, /* Linux ID */ 399441577efSTejun Heo { PCI_VDEVICE(NVIDIA, 0x0585), board_ahci_mcp_linux }, /* Linux ID */ 400441577efSTejun Heo { PCI_VDEVICE(NVIDIA, 0x0586), board_ahci_mcp_linux }, /* Linux ID */ 401441577efSTejun Heo { PCI_VDEVICE(NVIDIA, 0x0587), board_ahci_mcp_linux }, /* Linux ID */ 402441577efSTejun Heo { PCI_VDEVICE(NVIDIA, 0x0588), board_ahci_mcp_linux }, /* Linux ID */ 403441577efSTejun Heo { PCI_VDEVICE(NVIDIA, 0x0589), board_ahci_mcp_linux }, /* Linux ID */ 404441577efSTejun Heo { PCI_VDEVICE(NVIDIA, 0x058a), board_ahci_mcp_linux }, /* Linux ID */ 405441577efSTejun Heo { PCI_VDEVICE(NVIDIA, 0x058b), board_ahci_mcp_linux }, /* Linux ID */ 406441577efSTejun Heo { PCI_VDEVICE(NVIDIA, 0x058c), board_ahci_mcp_linux }, /* Linux ID */ 407441577efSTejun Heo { PCI_VDEVICE(NVIDIA, 0x058d), board_ahci_mcp_linux }, /* Linux ID */ 408441577efSTejun Heo { PCI_VDEVICE(NVIDIA, 0x058e), board_ahci_mcp_linux }, /* Linux ID */ 409441577efSTejun Heo { PCI_VDEVICE(NVIDIA, 0x058f), board_ahci_mcp_linux }, /* Linux ID */ 410441577efSTejun Heo { PCI_VDEVICE(NVIDIA, 0x07f0), board_ahci_mcp73 }, /* MCP73 */ 411441577efSTejun Heo { PCI_VDEVICE(NVIDIA, 0x07f1), board_ahci_mcp73 }, /* MCP73 */ 412441577efSTejun Heo { PCI_VDEVICE(NVIDIA, 0x07f2), board_ahci_mcp73 }, /* MCP73 */ 413441577efSTejun Heo { PCI_VDEVICE(NVIDIA, 0x07f3), board_ahci_mcp73 }, /* MCP73 */ 414441577efSTejun Heo { PCI_VDEVICE(NVIDIA, 0x07f4), board_ahci_mcp73 }, /* MCP73 */ 415441577efSTejun Heo { PCI_VDEVICE(NVIDIA, 0x07f5), board_ahci_mcp73 }, /* MCP73 */ 416441577efSTejun Heo { PCI_VDEVICE(NVIDIA, 0x07f6), board_ahci_mcp73 }, /* MCP73 */ 417441577efSTejun Heo { PCI_VDEVICE(NVIDIA, 0x07f7), board_ahci_mcp73 }, /* MCP73 */ 418441577efSTejun Heo { PCI_VDEVICE(NVIDIA, 0x07f8), board_ahci_mcp73 }, /* MCP73 */ 419441577efSTejun Heo { PCI_VDEVICE(NVIDIA, 0x07f9), board_ahci_mcp73 }, /* MCP73 */ 420441577efSTejun Heo { PCI_VDEVICE(NVIDIA, 0x07fa), board_ahci_mcp73 }, /* MCP73 */ 421441577efSTejun Heo { PCI_VDEVICE(NVIDIA, 0x07fb), board_ahci_mcp73 }, /* MCP73 */ 422441577efSTejun Heo { PCI_VDEVICE(NVIDIA, 0x0ad0), board_ahci_mcp77 }, /* MCP77 */ 423441577efSTejun Heo { PCI_VDEVICE(NVIDIA, 0x0ad1), board_ahci_mcp77 }, /* MCP77 */ 424441577efSTejun Heo { PCI_VDEVICE(NVIDIA, 0x0ad2), board_ahci_mcp77 }, /* MCP77 */ 425441577efSTejun Heo { PCI_VDEVICE(NVIDIA, 0x0ad3), board_ahci_mcp77 }, /* MCP77 */ 426441577efSTejun Heo { PCI_VDEVICE(NVIDIA, 0x0ad4), board_ahci_mcp77 }, /* MCP77 */ 427441577efSTejun Heo { PCI_VDEVICE(NVIDIA, 0x0ad5), board_ahci_mcp77 }, /* MCP77 */ 428441577efSTejun Heo { PCI_VDEVICE(NVIDIA, 0x0ad6), board_ahci_mcp77 }, /* MCP77 */ 429441577efSTejun Heo { PCI_VDEVICE(NVIDIA, 0x0ad7), board_ahci_mcp77 }, /* MCP77 */ 430441577efSTejun Heo { PCI_VDEVICE(NVIDIA, 0x0ad8), board_ahci_mcp77 }, /* MCP77 */ 431441577efSTejun Heo { PCI_VDEVICE(NVIDIA, 0x0ad9), board_ahci_mcp77 }, /* MCP77 */ 432441577efSTejun Heo { PCI_VDEVICE(NVIDIA, 0x0ada), board_ahci_mcp77 }, /* MCP77 */ 433441577efSTejun Heo { PCI_VDEVICE(NVIDIA, 0x0adb), board_ahci_mcp77 }, /* MCP77 */ 434441577efSTejun Heo { PCI_VDEVICE(NVIDIA, 0x0ab4), board_ahci_mcp79 }, /* MCP79 */ 435441577efSTejun Heo { PCI_VDEVICE(NVIDIA, 0x0ab5), board_ahci_mcp79 }, /* MCP79 */ 436441577efSTejun Heo { PCI_VDEVICE(NVIDIA, 0x0ab6), board_ahci_mcp79 }, /* MCP79 */ 437441577efSTejun Heo { PCI_VDEVICE(NVIDIA, 0x0ab7), board_ahci_mcp79 }, /* MCP79 */ 438441577efSTejun Heo { PCI_VDEVICE(NVIDIA, 0x0ab8), board_ahci_mcp79 }, /* MCP79 */ 439441577efSTejun Heo { PCI_VDEVICE(NVIDIA, 0x0ab9), board_ahci_mcp79 }, /* MCP79 */ 440441577efSTejun Heo { PCI_VDEVICE(NVIDIA, 0x0aba), board_ahci_mcp79 }, /* MCP79 */ 441441577efSTejun Heo { PCI_VDEVICE(NVIDIA, 0x0abb), board_ahci_mcp79 }, /* MCP79 */ 442441577efSTejun Heo { PCI_VDEVICE(NVIDIA, 0x0abc), board_ahci_mcp79 }, /* MCP79 */ 443441577efSTejun Heo { PCI_VDEVICE(NVIDIA, 0x0abd), board_ahci_mcp79 }, /* MCP79 */ 444441577efSTejun Heo { PCI_VDEVICE(NVIDIA, 0x0abe), board_ahci_mcp79 }, /* MCP79 */ 445441577efSTejun Heo { PCI_VDEVICE(NVIDIA, 0x0abf), board_ahci_mcp79 }, /* MCP79 */ 446441577efSTejun Heo { PCI_VDEVICE(NVIDIA, 0x0d84), board_ahci_mcp89 }, /* MCP89 */ 447441577efSTejun Heo { PCI_VDEVICE(NVIDIA, 0x0d85), board_ahci_mcp89 }, /* MCP89 */ 448441577efSTejun Heo { PCI_VDEVICE(NVIDIA, 0x0d86), board_ahci_mcp89 }, /* MCP89 */ 449441577efSTejun Heo { PCI_VDEVICE(NVIDIA, 0x0d87), board_ahci_mcp89 }, /* MCP89 */ 450441577efSTejun Heo { PCI_VDEVICE(NVIDIA, 0x0d88), board_ahci_mcp89 }, /* MCP89 */ 451441577efSTejun Heo { PCI_VDEVICE(NVIDIA, 0x0d89), board_ahci_mcp89 }, /* MCP89 */ 452441577efSTejun Heo { PCI_VDEVICE(NVIDIA, 0x0d8a), board_ahci_mcp89 }, /* MCP89 */ 453441577efSTejun Heo { PCI_VDEVICE(NVIDIA, 0x0d8b), board_ahci_mcp89 }, /* MCP89 */ 454441577efSTejun Heo { PCI_VDEVICE(NVIDIA, 0x0d8c), board_ahci_mcp89 }, /* MCP89 */ 455441577efSTejun Heo { PCI_VDEVICE(NVIDIA, 0x0d8d), board_ahci_mcp89 }, /* MCP89 */ 456441577efSTejun Heo { PCI_VDEVICE(NVIDIA, 0x0d8e), board_ahci_mcp89 }, /* MCP89 */ 457441577efSTejun Heo { PCI_VDEVICE(NVIDIA, 0x0d8f), board_ahci_mcp89 }, /* MCP89 */ 458c6fd2807SJeff Garzik 459c6fd2807SJeff Garzik /* SiS */ 46020e2de4aSTejun Heo { PCI_VDEVICE(SI, 0x1184), board_ahci }, /* SiS 966 */ 46120e2de4aSTejun Heo { PCI_VDEVICE(SI, 0x1185), board_ahci }, /* SiS 968 */ 46220e2de4aSTejun Heo { PCI_VDEVICE(SI, 0x0186), board_ahci }, /* SiS 968 */ 463c6fd2807SJeff Garzik 464318893e1SAlessandro Rubini /* ST Microelectronics */ 465318893e1SAlessandro Rubini { PCI_VDEVICE(STMICRO, 0xCC06), board_ahci }, /* ST ConneXt */ 466318893e1SAlessandro Rubini 467cd70c266SJeff Garzik /* Marvell */ 468cd70c266SJeff Garzik { PCI_VDEVICE(MARVELL, 0x6145), board_ahci_mv }, /* 6145 */ 469c40e7cb8SJose Alberto Reguero { PCI_VDEVICE(MARVELL, 0x6121), board_ahci_mv }, /* 6121 */ 47069fd3157SMyron Stowe { PCI_DEVICE(PCI_VENDOR_ID_MARVELL_EXT, 0x9123), 47110aca06cSAnssi Hannula .class = PCI_CLASS_STORAGE_SATA_AHCI, 47210aca06cSAnssi Hannula .class_mask = 0xffffff, 4735f173107STejun Heo .driver_data = board_ahci_yes_fbs }, /* 88se9128 */ 47469fd3157SMyron Stowe { PCI_DEVICE(PCI_VENDOR_ID_MARVELL_EXT, 0x9125), 475467b41c6SPer Jessen .driver_data = board_ahci_yes_fbs }, /* 88se9125 */ 476e098f5cbSSimon Guinot { PCI_DEVICE_SUB(PCI_VENDOR_ID_MARVELL_EXT, 0x9178, 477e098f5cbSSimon Guinot PCI_VENDOR_ID_MARVELL_EXT, 0x9170), 478e098f5cbSSimon Guinot .driver_data = board_ahci_yes_fbs }, /* 88se9170 */ 47969fd3157SMyron Stowe { PCI_DEVICE(PCI_VENDOR_ID_MARVELL_EXT, 0x917a), 480642d8925SMatt Johnson .driver_data = board_ahci_yes_fbs }, /* 88se9172 */ 481fcce9a35SGeorge Spelvin { PCI_DEVICE(PCI_VENDOR_ID_MARVELL_EXT, 0x9172), 482c5edfff9SMurali Karicheri .driver_data = board_ahci_yes_fbs }, /* 88se9182 */ 483c5edfff9SMurali Karicheri { PCI_DEVICE(PCI_VENDOR_ID_MARVELL_EXT, 0x9182), 484fcce9a35SGeorge Spelvin .driver_data = board_ahci_yes_fbs }, /* 88se9172 */ 48569fd3157SMyron Stowe { PCI_DEVICE(PCI_VENDOR_ID_MARVELL_EXT, 0x9192), 48617c60c6bSAlan Cox .driver_data = board_ahci_yes_fbs }, /* 88se9172 on some Gigabyte */ 487754a292fSAndreas Schrägle { PCI_DEVICE(PCI_VENDOR_ID_MARVELL_EXT, 0x91a0), 488754a292fSAndreas Schrägle .driver_data = board_ahci_yes_fbs }, 48969fd3157SMyron Stowe { PCI_DEVICE(PCI_VENDOR_ID_MARVELL_EXT, 0x91a3), 49050be5e36STejun Heo .driver_data = board_ahci_yes_fbs }, 4916d5278a6SSamir Benmendil { PCI_DEVICE(PCI_VENDOR_ID_MARVELL_EXT, 0x9230), 4926d5278a6SSamir Benmendil .driver_data = board_ahci_yes_fbs }, 493d2518365SJérôme Carretero { PCI_DEVICE(PCI_VENDOR_ID_TTI, 0x0642), 494d2518365SJérôme Carretero .driver_data = board_ahci_yes_fbs }, 495cd70c266SJeff Garzik 496c77a036bSMark Nelson /* Promise */ 497c77a036bSMark Nelson { PCI_VDEVICE(PROMISE, 0x3f20), board_ahci }, /* PDC42819 */ 498b32bfc06SRomain Degez { PCI_VDEVICE(PROMISE, 0x3781), board_ahci }, /* FastTrak TX8660 ahci-mode */ 499c77a036bSMark Nelson 500c9703765SKeng-Yu Lin /* Asmedia */ 5017b4f6ecaSAlan Cox { PCI_VDEVICE(ASMEDIA, 0x0601), board_ahci }, /* ASM1060 */ 5027b4f6ecaSAlan Cox { PCI_VDEVICE(ASMEDIA, 0x0602), board_ahci }, /* ASM1060 */ 5037b4f6ecaSAlan Cox { PCI_VDEVICE(ASMEDIA, 0x0611), board_ahci }, /* ASM1061 */ 5047b4f6ecaSAlan Cox { PCI_VDEVICE(ASMEDIA, 0x0612), board_ahci }, /* ASM1062 */ 505c9703765SKeng-Yu Lin 50667809f85SLevente Kurusa /* 50766a7cbc3STejun Heo * Samsung SSDs found on some macbooks. NCQ times out if MSI is 50866a7cbc3STejun Heo * enabled. https://bugzilla.kernel.org/show_bug.cgi?id=60731 50967809f85SLevente Kurusa */ 51066a7cbc3STejun Heo { PCI_VDEVICE(SAMSUNG, 0x1600), board_ahci_nomsi }, 5112b21ef0aSTejun Heo { PCI_VDEVICE(SAMSUNG, 0xa800), board_ahci_nomsi }, 51267809f85SLevente Kurusa 5137f9c9f8eSHugh Daschbach /* Enmotus */ 5147f9c9f8eSHugh Daschbach { PCI_DEVICE(0x1c44, 0x8000), board_ahci }, 5157f9c9f8eSHugh Daschbach 516415ae2b5SJeff Garzik /* Generic, PCI class code for AHCI */ 517415ae2b5SJeff Garzik { PCI_ANY_ID, PCI_ANY_ID, PCI_ANY_ID, PCI_ANY_ID, 518c9f89475SConke Hu PCI_CLASS_STORAGE_SATA_AHCI, 0xffffff, board_ahci }, 519415ae2b5SJeff Garzik 520c6fd2807SJeff Garzik { } /* terminate list */ 521c6fd2807SJeff Garzik }; 522c6fd2807SJeff Garzik 523c6fd2807SJeff Garzik 524c6fd2807SJeff Garzik static struct pci_driver ahci_pci_driver = { 525c6fd2807SJeff Garzik .name = DRV_NAME, 526c6fd2807SJeff Garzik .id_table = ahci_pci_tbl, 527c6fd2807SJeff Garzik .probe = ahci_init_one, 52824dc5f33STejun Heo .remove = ata_pci_remove_one, 529438ac6d5STejun Heo #ifdef CONFIG_PM 530c6fd2807SJeff Garzik .suspend = ahci_pci_device_suspend, 531c6fd2807SJeff Garzik .resume = ahci_pci_device_resume, 532438ac6d5STejun Heo #endif 533c6fd2807SJeff Garzik }; 534c6fd2807SJeff Garzik 5355b66c829SAlan Cox #if defined(CONFIG_PATA_MARVELL) || defined(CONFIG_PATA_MARVELL_MODULE) 5365b66c829SAlan Cox static int marvell_enable; 5375b66c829SAlan Cox #else 5385b66c829SAlan Cox static int marvell_enable = 1; 5395b66c829SAlan Cox #endif 5405b66c829SAlan Cox module_param(marvell_enable, int, 0644); 5415b66c829SAlan Cox MODULE_PARM_DESC(marvell_enable, "Marvell SATA via AHCI (1 = enabled)"); 5425b66c829SAlan Cox 5435b66c829SAlan Cox 544394d6e53SAnton Vorontsov static void ahci_pci_save_initial_config(struct pci_dev *pdev, 545394d6e53SAnton Vorontsov struct ahci_host_priv *hpriv) 546394d6e53SAnton Vorontsov { 547394d6e53SAnton Vorontsov if (pdev->vendor == PCI_VENDOR_ID_JMICRON && pdev->device == 0x2361) { 548394d6e53SAnton Vorontsov dev_info(&pdev->dev, "JMB361 has only one port\n"); 5499a23c1d6SAntoine Tenart hpriv->force_port_map = 1; 550394d6e53SAnton Vorontsov } 551394d6e53SAnton Vorontsov 552394d6e53SAnton Vorontsov /* 553394d6e53SAnton Vorontsov * Temporary Marvell 6145 hack: PATA port presence 554394d6e53SAnton Vorontsov * is asserted through the standard AHCI port 555394d6e53SAnton Vorontsov * presence register, as bit 4 (counting from 0) 556394d6e53SAnton Vorontsov */ 557394d6e53SAnton Vorontsov if (hpriv->flags & AHCI_HFLAG_MV_PATA) { 558394d6e53SAnton Vorontsov if (pdev->device == 0x6121) 5599a23c1d6SAntoine Tenart hpriv->mask_port_map = 0x3; 560394d6e53SAnton Vorontsov else 5619a23c1d6SAntoine Tenart hpriv->mask_port_map = 0xf; 562394d6e53SAnton Vorontsov dev_info(&pdev->dev, 563394d6e53SAnton Vorontsov "Disabling your PATA port. Use the boot option 'ahci.marvell_enable=0' to avoid this.\n"); 564394d6e53SAnton Vorontsov } 565394d6e53SAnton Vorontsov 566725c7b57SAntoine Ténart ahci_save_initial_config(&pdev->dev, hpriv); 567394d6e53SAnton Vorontsov } 568394d6e53SAnton Vorontsov 5693303040dSAnton Vorontsov static int ahci_pci_reset_controller(struct ata_host *host) 5703303040dSAnton Vorontsov { 5713303040dSAnton Vorontsov struct pci_dev *pdev = to_pci_dev(host->dev); 5723303040dSAnton Vorontsov 5733303040dSAnton Vorontsov ahci_reset_controller(host); 5743303040dSAnton Vorontsov 575c6fd2807SJeff Garzik if (pdev->vendor == PCI_VENDOR_ID_INTEL) { 5763303040dSAnton Vorontsov struct ahci_host_priv *hpriv = host->private_data; 577c6fd2807SJeff Garzik u16 tmp16; 578c6fd2807SJeff Garzik 579c6fd2807SJeff Garzik /* configure PCS */ 580c6fd2807SJeff Garzik pci_read_config_word(pdev, 0x92, &tmp16); 58149f29090STejun Heo if ((tmp16 & hpriv->port_map) != hpriv->port_map) { 58249f29090STejun Heo tmp16 |= hpriv->port_map; 583c6fd2807SJeff Garzik pci_write_config_word(pdev, 0x92, tmp16); 584c6fd2807SJeff Garzik } 58549f29090STejun Heo } 586c6fd2807SJeff Garzik 587c6fd2807SJeff Garzik return 0; 588c6fd2807SJeff Garzik } 589c6fd2807SJeff Garzik 590781d6550SAnton Vorontsov static void ahci_pci_init_controller(struct ata_host *host) 591781d6550SAnton Vorontsov { 592781d6550SAnton Vorontsov struct ahci_host_priv *hpriv = host->private_data; 593781d6550SAnton Vorontsov struct pci_dev *pdev = to_pci_dev(host->dev); 594781d6550SAnton Vorontsov void __iomem *port_mmio; 595781d6550SAnton Vorontsov u32 tmp; 596c40e7cb8SJose Alberto Reguero int mv; 5972bcd866bSJeff Garzik 598417a1a6dSTejun Heo if (hpriv->flags & AHCI_HFLAG_MV_PATA) { 599c40e7cb8SJose Alberto Reguero if (pdev->device == 0x6121) 600c40e7cb8SJose Alberto Reguero mv = 2; 601c40e7cb8SJose Alberto Reguero else 602c40e7cb8SJose Alberto Reguero mv = 4; 603c40e7cb8SJose Alberto Reguero port_mmio = __ahci_port_base(host, mv); 604cd70c266SJeff Garzik 605cd70c266SJeff Garzik writel(0, port_mmio + PORT_IRQ_MASK); 606cd70c266SJeff Garzik 607cd70c266SJeff Garzik /* clear port IRQ */ 608cd70c266SJeff Garzik tmp = readl(port_mmio + PORT_IRQ_STAT); 609cd70c266SJeff Garzik VPRINTK("PORT_IRQ_STAT 0x%x\n", tmp); 610cd70c266SJeff Garzik if (tmp) 611cd70c266SJeff Garzik writel(tmp, port_mmio + PORT_IRQ_STAT); 612cd70c266SJeff Garzik } 613cd70c266SJeff Garzik 614781d6550SAnton Vorontsov ahci_init_controller(host); 615c6fd2807SJeff Garzik } 616c6fd2807SJeff Garzik 617cc0680a5STejun Heo static int ahci_vt8251_hardreset(struct ata_link *link, unsigned int *class, 618d4b2bab4STejun Heo unsigned long deadline) 619ad616ffbSTejun Heo { 620cc0680a5STejun Heo struct ata_port *ap = link->ap; 621039ece38SHans de Goede struct ahci_host_priv *hpriv = ap->host->private_data; 6229dadd45bSTejun Heo bool online; 623ad616ffbSTejun Heo int rc; 624ad616ffbSTejun Heo 625ad616ffbSTejun Heo DPRINTK("ENTER\n"); 626ad616ffbSTejun Heo 6274447d351STejun Heo ahci_stop_engine(ap); 628ad616ffbSTejun Heo 629cc0680a5STejun Heo rc = sata_link_hardreset(link, sata_ehc_deb_timing(&link->eh_context), 6309dadd45bSTejun Heo deadline, &online, NULL); 631ad616ffbSTejun Heo 632039ece38SHans de Goede hpriv->start_engine(ap); 633ad616ffbSTejun Heo 634ad616ffbSTejun Heo DPRINTK("EXIT, rc=%d, class=%u\n", rc, *class); 635ad616ffbSTejun Heo 636ad616ffbSTejun Heo /* vt8251 doesn't clear BSY on signature FIS reception, 637ad616ffbSTejun Heo * request follow-up softreset. 638ad616ffbSTejun Heo */ 6399dadd45bSTejun Heo return online ? -EAGAIN : rc; 640ad616ffbSTejun Heo } 641ad616ffbSTejun Heo 642edc93052STejun Heo static int ahci_p5wdh_hardreset(struct ata_link *link, unsigned int *class, 643edc93052STejun Heo unsigned long deadline) 644edc93052STejun Heo { 645edc93052STejun Heo struct ata_port *ap = link->ap; 646edc93052STejun Heo struct ahci_port_priv *pp = ap->private_data; 647039ece38SHans de Goede struct ahci_host_priv *hpriv = ap->host->private_data; 648edc93052STejun Heo u8 *d2h_fis = pp->rx_fis + RX_FIS_D2H_REG; 649edc93052STejun Heo struct ata_taskfile tf; 6509dadd45bSTejun Heo bool online; 651edc93052STejun Heo int rc; 652edc93052STejun Heo 653edc93052STejun Heo ahci_stop_engine(ap); 654edc93052STejun Heo 655edc93052STejun Heo /* clear D2H reception area to properly wait for D2H FIS */ 656edc93052STejun Heo ata_tf_init(link->device, &tf); 6579bbb1b0eSSergei Shtylyov tf.command = ATA_BUSY; 658edc93052STejun Heo ata_tf_to_fis(&tf, 0, 0, d2h_fis); 659edc93052STejun Heo 660edc93052STejun Heo rc = sata_link_hardreset(link, sata_ehc_deb_timing(&link->eh_context), 6619dadd45bSTejun Heo deadline, &online, NULL); 662edc93052STejun Heo 663039ece38SHans de Goede hpriv->start_engine(ap); 664edc93052STejun Heo 665edc93052STejun Heo /* The pseudo configuration device on SIMG4726 attached to 666edc93052STejun Heo * ASUS P5W-DH Deluxe doesn't send signature FIS after 667edc93052STejun Heo * hardreset if no device is attached to the first downstream 668edc93052STejun Heo * port && the pseudo device locks up on SRST w/ PMP==0. To 669edc93052STejun Heo * work around this, wait for !BSY only briefly. If BSY isn't 670edc93052STejun Heo * cleared, perform CLO and proceed to IDENTIFY (achieved by 671edc93052STejun Heo * ATA_LFLAG_NO_SRST and ATA_LFLAG_ASSUME_ATA). 672edc93052STejun Heo * 673edc93052STejun Heo * Wait for two seconds. Devices attached to downstream port 674edc93052STejun Heo * which can't process the following IDENTIFY after this will 675edc93052STejun Heo * have to be reset again. For most cases, this should 676edc93052STejun Heo * suffice while making probing snappish enough. 677edc93052STejun Heo */ 6789dadd45bSTejun Heo if (online) { 6799dadd45bSTejun Heo rc = ata_wait_after_reset(link, jiffies + 2 * HZ, 6809dadd45bSTejun Heo ahci_check_ready); 681edc93052STejun Heo if (rc) 68278d5ae39SShane Huang ahci_kick_engine(ap); 6839dadd45bSTejun Heo } 6849dadd45bSTejun Heo return rc; 685edc93052STejun Heo } 686edc93052STejun Heo 687*dbfe8ef5SDan Williams /* 688*dbfe8ef5SDan Williams * ahci_avn_hardreset - attempt more aggressive recovery of Avoton ports. 689*dbfe8ef5SDan Williams * 690*dbfe8ef5SDan Williams * It has been observed with some SSDs that the timing of events in the 691*dbfe8ef5SDan Williams * link synchronization phase can leave the port in a state that can not 692*dbfe8ef5SDan Williams * be recovered by a SATA-hard-reset alone. The failing signature is 693*dbfe8ef5SDan Williams * SStatus.DET stuck at 1 ("Device presence detected but Phy 694*dbfe8ef5SDan Williams * communication not established"). It was found that unloading and 695*dbfe8ef5SDan Williams * reloading the driver when this problem occurs allows the drive 696*dbfe8ef5SDan Williams * connection to be recovered (DET advanced to 0x3). The critical 697*dbfe8ef5SDan Williams * component of reloading the driver is that the port state machines are 698*dbfe8ef5SDan Williams * reset by bouncing "port enable" in the AHCI PCS configuration 699*dbfe8ef5SDan Williams * register. So, reproduce that effect by bouncing a port whenever we 700*dbfe8ef5SDan Williams * see DET==1 after a reset. 701*dbfe8ef5SDan Williams */ 702*dbfe8ef5SDan Williams static int ahci_avn_hardreset(struct ata_link *link, unsigned int *class, 703*dbfe8ef5SDan Williams unsigned long deadline) 704*dbfe8ef5SDan Williams { 705*dbfe8ef5SDan Williams const unsigned long *timing = sata_ehc_deb_timing(&link->eh_context); 706*dbfe8ef5SDan Williams struct ata_port *ap = link->ap; 707*dbfe8ef5SDan Williams struct ahci_port_priv *pp = ap->private_data; 708*dbfe8ef5SDan Williams struct ahci_host_priv *hpriv = ap->host->private_data; 709*dbfe8ef5SDan Williams u8 *d2h_fis = pp->rx_fis + RX_FIS_D2H_REG; 710*dbfe8ef5SDan Williams unsigned long tmo = deadline - jiffies; 711*dbfe8ef5SDan Williams struct ata_taskfile tf; 712*dbfe8ef5SDan Williams bool online; 713*dbfe8ef5SDan Williams int rc, i; 714*dbfe8ef5SDan Williams 715*dbfe8ef5SDan Williams DPRINTK("ENTER\n"); 716*dbfe8ef5SDan Williams 717*dbfe8ef5SDan Williams ahci_stop_engine(ap); 718*dbfe8ef5SDan Williams 719*dbfe8ef5SDan Williams for (i = 0; i < 2; i++) { 720*dbfe8ef5SDan Williams u16 val; 721*dbfe8ef5SDan Williams u32 sstatus; 722*dbfe8ef5SDan Williams int port = ap->port_no; 723*dbfe8ef5SDan Williams struct ata_host *host = ap->host; 724*dbfe8ef5SDan Williams struct pci_dev *pdev = to_pci_dev(host->dev); 725*dbfe8ef5SDan Williams 726*dbfe8ef5SDan Williams /* clear D2H reception area to properly wait for D2H FIS */ 727*dbfe8ef5SDan Williams ata_tf_init(link->device, &tf); 728*dbfe8ef5SDan Williams tf.command = ATA_BUSY; 729*dbfe8ef5SDan Williams ata_tf_to_fis(&tf, 0, 0, d2h_fis); 730*dbfe8ef5SDan Williams 731*dbfe8ef5SDan Williams rc = sata_link_hardreset(link, timing, deadline, &online, 732*dbfe8ef5SDan Williams ahci_check_ready); 733*dbfe8ef5SDan Williams 734*dbfe8ef5SDan Williams if (sata_scr_read(link, SCR_STATUS, &sstatus) != 0 || 735*dbfe8ef5SDan Williams (sstatus & 0xf) != 1) 736*dbfe8ef5SDan Williams break; 737*dbfe8ef5SDan Williams 738*dbfe8ef5SDan Williams ata_link_printk(link, KERN_INFO, "avn bounce port%d\n", 739*dbfe8ef5SDan Williams port); 740*dbfe8ef5SDan Williams 741*dbfe8ef5SDan Williams pci_read_config_word(pdev, 0x92, &val); 742*dbfe8ef5SDan Williams val &= ~(1 << port); 743*dbfe8ef5SDan Williams pci_write_config_word(pdev, 0x92, val); 744*dbfe8ef5SDan Williams ata_msleep(ap, 1000); 745*dbfe8ef5SDan Williams val |= 1 << port; 746*dbfe8ef5SDan Williams pci_write_config_word(pdev, 0x92, val); 747*dbfe8ef5SDan Williams deadline += tmo; 748*dbfe8ef5SDan Williams } 749*dbfe8ef5SDan Williams 750*dbfe8ef5SDan Williams hpriv->start_engine(ap); 751*dbfe8ef5SDan Williams 752*dbfe8ef5SDan Williams if (online) 753*dbfe8ef5SDan Williams *class = ahci_dev_classify(ap); 754*dbfe8ef5SDan Williams 755*dbfe8ef5SDan Williams DPRINTK("EXIT, rc=%d, class=%u\n", rc, *class); 756*dbfe8ef5SDan Williams return rc; 757*dbfe8ef5SDan Williams } 758*dbfe8ef5SDan Williams 759*dbfe8ef5SDan Williams 760438ac6d5STejun Heo #ifdef CONFIG_PM 761c6fd2807SJeff Garzik static int ahci_pci_device_suspend(struct pci_dev *pdev, pm_message_t mesg) 762c6fd2807SJeff Garzik { 7630a86e1c8SJingoo Han struct ata_host *host = pci_get_drvdata(pdev); 7649b10ae86STejun Heo struct ahci_host_priv *hpriv = host->private_data; 765d8993349SAnton Vorontsov void __iomem *mmio = hpriv->mmio; 766c6fd2807SJeff Garzik u32 ctl; 767c6fd2807SJeff Garzik 7689b10ae86STejun Heo if (mesg.event & PM_EVENT_SUSPEND && 7699b10ae86STejun Heo hpriv->flags & AHCI_HFLAG_NO_SUSPEND) { 770a44fec1fSJoe Perches dev_err(&pdev->dev, 7719b10ae86STejun Heo "BIOS update required for suspend/resume\n"); 7729b10ae86STejun Heo return -EIO; 7739b10ae86STejun Heo } 7749b10ae86STejun Heo 7753a2d5b70SRafael J. Wysocki if (mesg.event & PM_EVENT_SLEEP) { 776c6fd2807SJeff Garzik /* AHCI spec rev1.1 section 8.3.3: 777c6fd2807SJeff Garzik * Software must disable interrupts prior to requesting a 778c6fd2807SJeff Garzik * transition of the HBA to D3 state. 779c6fd2807SJeff Garzik */ 780c6fd2807SJeff Garzik ctl = readl(mmio + HOST_CTL); 781c6fd2807SJeff Garzik ctl &= ~HOST_IRQ_EN; 782c6fd2807SJeff Garzik writel(ctl, mmio + HOST_CTL); 783c6fd2807SJeff Garzik readl(mmio + HOST_CTL); /* flush */ 784c6fd2807SJeff Garzik } 785c6fd2807SJeff Garzik 786c6fd2807SJeff Garzik return ata_pci_device_suspend(pdev, mesg); 787c6fd2807SJeff Garzik } 788c6fd2807SJeff Garzik 789c6fd2807SJeff Garzik static int ahci_pci_device_resume(struct pci_dev *pdev) 790c6fd2807SJeff Garzik { 7910a86e1c8SJingoo Han struct ata_host *host = pci_get_drvdata(pdev); 792c6fd2807SJeff Garzik int rc; 793c6fd2807SJeff Garzik 794553c4aa6STejun Heo rc = ata_pci_device_do_resume(pdev); 795553c4aa6STejun Heo if (rc) 796553c4aa6STejun Heo return rc; 797c6fd2807SJeff Garzik 798cb85696dSJames Laird /* Apple BIOS helpfully mangles the registers on resume */ 799cb85696dSJames Laird if (is_mcp89_apple(pdev)) 800cb85696dSJames Laird ahci_mcp89_apple_enable(pdev); 801cb85696dSJames Laird 802c6fd2807SJeff Garzik if (pdev->dev.power.power_state.event == PM_EVENT_SUSPEND) { 8033303040dSAnton Vorontsov rc = ahci_pci_reset_controller(host); 804c6fd2807SJeff Garzik if (rc) 805c6fd2807SJeff Garzik return rc; 806c6fd2807SJeff Garzik 807781d6550SAnton Vorontsov ahci_pci_init_controller(host); 808c6fd2807SJeff Garzik } 809c6fd2807SJeff Garzik 810cca3974eSJeff Garzik ata_host_resume(host); 811c6fd2807SJeff Garzik 812c6fd2807SJeff Garzik return 0; 813c6fd2807SJeff Garzik } 814438ac6d5STejun Heo #endif 815c6fd2807SJeff Garzik 8164447d351STejun Heo static int ahci_configure_dma_masks(struct pci_dev *pdev, int using_dac) 817c6fd2807SJeff Garzik { 818c6fd2807SJeff Garzik int rc; 819c6fd2807SJeff Garzik 820318893e1SAlessandro Rubini /* 821318893e1SAlessandro Rubini * If the device fixup already set the dma_mask to some non-standard 822318893e1SAlessandro Rubini * value, don't extend it here. This happens on STA2X11, for example. 823318893e1SAlessandro Rubini */ 824318893e1SAlessandro Rubini if (pdev->dma_mask && pdev->dma_mask < DMA_BIT_MASK(32)) 825318893e1SAlessandro Rubini return 0; 826318893e1SAlessandro Rubini 827c6fd2807SJeff Garzik if (using_dac && 828c54c719bSQuentin Lambert !dma_set_mask(&pdev->dev, DMA_BIT_MASK(64))) { 829c54c719bSQuentin Lambert rc = dma_set_coherent_mask(&pdev->dev, DMA_BIT_MASK(64)); 830c6fd2807SJeff Garzik if (rc) { 831c54c719bSQuentin Lambert rc = dma_set_coherent_mask(&pdev->dev, DMA_BIT_MASK(32)); 832c6fd2807SJeff Garzik if (rc) { 833a44fec1fSJoe Perches dev_err(&pdev->dev, 834c6fd2807SJeff Garzik "64-bit DMA enable failed\n"); 835c6fd2807SJeff Garzik return rc; 836c6fd2807SJeff Garzik } 837c6fd2807SJeff Garzik } 838c6fd2807SJeff Garzik } else { 839c54c719bSQuentin Lambert rc = dma_set_mask(&pdev->dev, DMA_BIT_MASK(32)); 840c6fd2807SJeff Garzik if (rc) { 841a44fec1fSJoe Perches dev_err(&pdev->dev, "32-bit DMA enable failed\n"); 842c6fd2807SJeff Garzik return rc; 843c6fd2807SJeff Garzik } 844c54c719bSQuentin Lambert rc = dma_set_coherent_mask(&pdev->dev, DMA_BIT_MASK(32)); 845c6fd2807SJeff Garzik if (rc) { 846a44fec1fSJoe Perches dev_err(&pdev->dev, 847c6fd2807SJeff Garzik "32-bit consistent DMA enable failed\n"); 848c6fd2807SJeff Garzik return rc; 849c6fd2807SJeff Garzik } 850c6fd2807SJeff Garzik } 851c6fd2807SJeff Garzik return 0; 852c6fd2807SJeff Garzik } 853c6fd2807SJeff Garzik 854439fcaecSAnton Vorontsov static void ahci_pci_print_info(struct ata_host *host) 855439fcaecSAnton Vorontsov { 856439fcaecSAnton Vorontsov struct pci_dev *pdev = to_pci_dev(host->dev); 857439fcaecSAnton Vorontsov u16 cc; 858439fcaecSAnton Vorontsov const char *scc_s; 859439fcaecSAnton Vorontsov 860439fcaecSAnton Vorontsov pci_read_config_word(pdev, 0x0a, &cc); 861439fcaecSAnton Vorontsov if (cc == PCI_CLASS_STORAGE_IDE) 862439fcaecSAnton Vorontsov scc_s = "IDE"; 863439fcaecSAnton Vorontsov else if (cc == PCI_CLASS_STORAGE_SATA) 864439fcaecSAnton Vorontsov scc_s = "SATA"; 865439fcaecSAnton Vorontsov else if (cc == PCI_CLASS_STORAGE_RAID) 866439fcaecSAnton Vorontsov scc_s = "RAID"; 867439fcaecSAnton Vorontsov else 868439fcaecSAnton Vorontsov scc_s = "unknown"; 869439fcaecSAnton Vorontsov 870439fcaecSAnton Vorontsov ahci_print_info(host, scc_s); 871439fcaecSAnton Vorontsov } 872439fcaecSAnton Vorontsov 873edc93052STejun Heo /* On ASUS P5W DH Deluxe, the second port of PCI device 00:1f.2 is 874edc93052STejun Heo * hardwired to on-board SIMG 4726. The chipset is ICH8 and doesn't 875edc93052STejun Heo * support PMP and the 4726 either directly exports the device 876edc93052STejun Heo * attached to the first downstream port or acts as a hardware storage 877edc93052STejun Heo * controller and emulate a single ATA device (can be RAID 0/1 or some 878edc93052STejun Heo * other configuration). 879edc93052STejun Heo * 880edc93052STejun Heo * When there's no device attached to the first downstream port of the 881edc93052STejun Heo * 4726, "Config Disk" appears, which is a pseudo ATA device to 882edc93052STejun Heo * configure the 4726. However, ATA emulation of the device is very 883edc93052STejun Heo * lame. It doesn't send signature D2H Reg FIS after the initial 884edc93052STejun Heo * hardreset, pukes on SRST w/ PMP==0 and has bunch of other issues. 885edc93052STejun Heo * 886edc93052STejun Heo * The following function works around the problem by always using 887edc93052STejun Heo * hardreset on the port and not depending on receiving signature FIS 888edc93052STejun Heo * afterward. If signature FIS isn't received soon, ATA class is 889edc93052STejun Heo * assumed without follow-up softreset. 890edc93052STejun Heo */ 891edc93052STejun Heo static void ahci_p5wdh_workaround(struct ata_host *host) 892edc93052STejun Heo { 8931bd06867SMathias Krause static const struct dmi_system_id sysids[] = { 894edc93052STejun Heo { 895edc93052STejun Heo .ident = "P5W DH Deluxe", 896edc93052STejun Heo .matches = { 897edc93052STejun Heo DMI_MATCH(DMI_SYS_VENDOR, 898edc93052STejun Heo "ASUSTEK COMPUTER INC"), 899edc93052STejun Heo DMI_MATCH(DMI_PRODUCT_NAME, "P5W DH Deluxe"), 900edc93052STejun Heo }, 901edc93052STejun Heo }, 902edc93052STejun Heo { } 903edc93052STejun Heo }; 904edc93052STejun Heo struct pci_dev *pdev = to_pci_dev(host->dev); 905edc93052STejun Heo 906edc93052STejun Heo if (pdev->bus->number == 0 && pdev->devfn == PCI_DEVFN(0x1f, 2) && 907edc93052STejun Heo dmi_check_system(sysids)) { 908edc93052STejun Heo struct ata_port *ap = host->ports[1]; 909edc93052STejun Heo 910a44fec1fSJoe Perches dev_info(&pdev->dev, 911a44fec1fSJoe Perches "enabling ASUS P5W DH Deluxe on-board SIMG4726 workaround\n"); 912edc93052STejun Heo 913edc93052STejun Heo ap->ops = &ahci_p5wdh_ops; 914edc93052STejun Heo ap->link.flags |= ATA_LFLAG_NO_SRST | ATA_LFLAG_ASSUME_ATA; 915edc93052STejun Heo } 916edc93052STejun Heo } 917edc93052STejun Heo 918cb85696dSJames Laird /* 919cb85696dSJames Laird * Macbook7,1 firmware forcibly disables MCP89 AHCI and changes PCI ID when 920cb85696dSJames Laird * booting in BIOS compatibility mode. We restore the registers but not ID. 921cb85696dSJames Laird */ 922cb85696dSJames Laird static void ahci_mcp89_apple_enable(struct pci_dev *pdev) 923cb85696dSJames Laird { 924cb85696dSJames Laird u32 val; 925cb85696dSJames Laird 926cb85696dSJames Laird printk(KERN_INFO "ahci: enabling MCP89 AHCI mode\n"); 927cb85696dSJames Laird 928cb85696dSJames Laird pci_read_config_dword(pdev, 0xf8, &val); 929cb85696dSJames Laird val |= 1 << 0x1b; 930cb85696dSJames Laird /* the following changes the device ID, but appears not to affect function */ 931cb85696dSJames Laird /* val = (val & ~0xf0000000) | 0x80000000; */ 932cb85696dSJames Laird pci_write_config_dword(pdev, 0xf8, val); 933cb85696dSJames Laird 934cb85696dSJames Laird pci_read_config_dword(pdev, 0x54c, &val); 935cb85696dSJames Laird val |= 1 << 0xc; 936cb85696dSJames Laird pci_write_config_dword(pdev, 0x54c, val); 937cb85696dSJames Laird 938cb85696dSJames Laird pci_read_config_dword(pdev, 0x4a4, &val); 939cb85696dSJames Laird val &= 0xff; 940cb85696dSJames Laird val |= 0x01060100; 941cb85696dSJames Laird pci_write_config_dword(pdev, 0x4a4, val); 942cb85696dSJames Laird 943cb85696dSJames Laird pci_read_config_dword(pdev, 0x54c, &val); 944cb85696dSJames Laird val &= ~(1 << 0xc); 945cb85696dSJames Laird pci_write_config_dword(pdev, 0x54c, val); 946cb85696dSJames Laird 947cb85696dSJames Laird pci_read_config_dword(pdev, 0xf8, &val); 948cb85696dSJames Laird val &= ~(1 << 0x1b); 949cb85696dSJames Laird pci_write_config_dword(pdev, 0xf8, val); 950cb85696dSJames Laird } 951cb85696dSJames Laird 952cb85696dSJames Laird static bool is_mcp89_apple(struct pci_dev *pdev) 953cb85696dSJames Laird { 954cb85696dSJames Laird return pdev->vendor == PCI_VENDOR_ID_NVIDIA && 955cb85696dSJames Laird pdev->device == PCI_DEVICE_ID_NVIDIA_NFORCE_MCP89_SATA && 956cb85696dSJames Laird pdev->subsystem_vendor == PCI_VENDOR_ID_APPLE && 957cb85696dSJames Laird pdev->subsystem_device == 0xcb89; 958cb85696dSJames Laird } 959cb85696dSJames Laird 9602fcad9d2STejun Heo /* only some SB600 ahci controllers can do 64bit DMA */ 9612fcad9d2STejun Heo static bool ahci_sb600_enable_64bit(struct pci_dev *pdev) 96258a09b38SShane Huang { 96358a09b38SShane Huang static const struct dmi_system_id sysids[] = { 96403d783bfSTejun Heo /* 96503d783bfSTejun Heo * The oldest version known to be broken is 0901 and 96603d783bfSTejun Heo * working is 1501 which was released on 2007-10-26. 9672fcad9d2STejun Heo * Enable 64bit DMA on 1501 and anything newer. 9682fcad9d2STejun Heo * 96903d783bfSTejun Heo * Please read bko#9412 for more info. 97003d783bfSTejun Heo */ 97158a09b38SShane Huang { 97258a09b38SShane Huang .ident = "ASUS M2A-VM", 97358a09b38SShane Huang .matches = { 97458a09b38SShane Huang DMI_MATCH(DMI_BOARD_VENDOR, 97558a09b38SShane Huang "ASUSTeK Computer INC."), 97658a09b38SShane Huang DMI_MATCH(DMI_BOARD_NAME, "M2A-VM"), 97758a09b38SShane Huang }, 97803d783bfSTejun Heo .driver_data = "20071026", /* yyyymmdd */ 97958a09b38SShane Huang }, 980e65cc194SMark Nelson /* 981e65cc194SMark Nelson * All BIOS versions for the MSI K9A2 Platinum (MS-7376) 982e65cc194SMark Nelson * support 64bit DMA. 983e65cc194SMark Nelson * 984e65cc194SMark Nelson * BIOS versions earlier than 1.5 had the Manufacturer DMI 985e65cc194SMark Nelson * fields as "MICRO-STAR INTERANTIONAL CO.,LTD". 986e65cc194SMark Nelson * This spelling mistake was fixed in BIOS version 1.5, so 987e65cc194SMark Nelson * 1.5 and later have the Manufacturer as 988e65cc194SMark Nelson * "MICRO-STAR INTERNATIONAL CO.,LTD". 989e65cc194SMark Nelson * So try to match on DMI_BOARD_VENDOR of "MICRO-STAR INTER". 990e65cc194SMark Nelson * 991e65cc194SMark Nelson * BIOS versions earlier than 1.9 had a Board Product Name 992e65cc194SMark Nelson * DMI field of "MS-7376". This was changed to be 993e65cc194SMark Nelson * "K9A2 Platinum (MS-7376)" in version 1.9, but we can still 994e65cc194SMark Nelson * match on DMI_BOARD_NAME of "MS-7376". 995e65cc194SMark Nelson */ 996e65cc194SMark Nelson { 997e65cc194SMark Nelson .ident = "MSI K9A2 Platinum", 998e65cc194SMark Nelson .matches = { 999e65cc194SMark Nelson DMI_MATCH(DMI_BOARD_VENDOR, 1000e65cc194SMark Nelson "MICRO-STAR INTER"), 1001e65cc194SMark Nelson DMI_MATCH(DMI_BOARD_NAME, "MS-7376"), 1002e65cc194SMark Nelson }, 1003e65cc194SMark Nelson }, 10043c4aa91fSMark Nelson /* 1005ff0173c1SMark Nelson * All BIOS versions for the MSI K9AGM2 (MS-7327) support 1006ff0173c1SMark Nelson * 64bit DMA. 1007ff0173c1SMark Nelson * 1008ff0173c1SMark Nelson * This board also had the typo mentioned above in the 1009ff0173c1SMark Nelson * Manufacturer DMI field (fixed in BIOS version 1.5), so 1010ff0173c1SMark Nelson * match on DMI_BOARD_VENDOR of "MICRO-STAR INTER" again. 1011ff0173c1SMark Nelson */ 1012ff0173c1SMark Nelson { 1013ff0173c1SMark Nelson .ident = "MSI K9AGM2", 1014ff0173c1SMark Nelson .matches = { 1015ff0173c1SMark Nelson DMI_MATCH(DMI_BOARD_VENDOR, 1016ff0173c1SMark Nelson "MICRO-STAR INTER"), 1017ff0173c1SMark Nelson DMI_MATCH(DMI_BOARD_NAME, "MS-7327"), 1018ff0173c1SMark Nelson }, 1019ff0173c1SMark Nelson }, 1020ff0173c1SMark Nelson /* 10213c4aa91fSMark Nelson * All BIOS versions for the Asus M3A support 64bit DMA. 10223c4aa91fSMark Nelson * (all release versions from 0301 to 1206 were tested) 10233c4aa91fSMark Nelson */ 10243c4aa91fSMark Nelson { 10253c4aa91fSMark Nelson .ident = "ASUS M3A", 10263c4aa91fSMark Nelson .matches = { 10273c4aa91fSMark Nelson DMI_MATCH(DMI_BOARD_VENDOR, 10283c4aa91fSMark Nelson "ASUSTeK Computer INC."), 10293c4aa91fSMark Nelson DMI_MATCH(DMI_BOARD_NAME, "M3A"), 10303c4aa91fSMark Nelson }, 10313c4aa91fSMark Nelson }, 103258a09b38SShane Huang { } 103358a09b38SShane Huang }; 103403d783bfSTejun Heo const struct dmi_system_id *match; 10352fcad9d2STejun Heo int year, month, date; 10362fcad9d2STejun Heo char buf[9]; 103758a09b38SShane Huang 103803d783bfSTejun Heo match = dmi_first_match(sysids); 103958a09b38SShane Huang if (pdev->bus->number != 0 || pdev->devfn != PCI_DEVFN(0x12, 0) || 104003d783bfSTejun Heo !match) 104158a09b38SShane Huang return false; 104258a09b38SShane Huang 1043e65cc194SMark Nelson if (!match->driver_data) 1044e65cc194SMark Nelson goto enable_64bit; 1045e65cc194SMark Nelson 104603d783bfSTejun Heo dmi_get_date(DMI_BIOS_DATE, &year, &month, &date); 104703d783bfSTejun Heo snprintf(buf, sizeof(buf), "%04d%02d%02d", year, month, date); 104803d783bfSTejun Heo 1049e65cc194SMark Nelson if (strcmp(buf, match->driver_data) >= 0) 1050e65cc194SMark Nelson goto enable_64bit; 1051e65cc194SMark Nelson else { 1052a44fec1fSJoe Perches dev_warn(&pdev->dev, 1053a44fec1fSJoe Perches "%s: BIOS too old, forcing 32bit DMA, update BIOS\n", 1054a44fec1fSJoe Perches match->ident); 10552fcad9d2STejun Heo return false; 10562fcad9d2STejun Heo } 1057e65cc194SMark Nelson 1058e65cc194SMark Nelson enable_64bit: 1059a44fec1fSJoe Perches dev_warn(&pdev->dev, "%s: enabling 64bit DMA\n", match->ident); 1060e65cc194SMark Nelson return true; 106158a09b38SShane Huang } 106258a09b38SShane Huang 10631fd68434SRafael J. Wysocki static bool ahci_broken_system_poweroff(struct pci_dev *pdev) 10641fd68434SRafael J. Wysocki { 10651fd68434SRafael J. Wysocki static const struct dmi_system_id broken_systems[] = { 10661fd68434SRafael J. Wysocki { 10671fd68434SRafael J. Wysocki .ident = "HP Compaq nx6310", 10681fd68434SRafael J. Wysocki .matches = { 10691fd68434SRafael J. Wysocki DMI_MATCH(DMI_SYS_VENDOR, "Hewlett-Packard"), 10701fd68434SRafael J. Wysocki DMI_MATCH(DMI_PRODUCT_NAME, "HP Compaq nx6310"), 10711fd68434SRafael J. Wysocki }, 10721fd68434SRafael J. Wysocki /* PCI slot number of the controller */ 10731fd68434SRafael J. Wysocki .driver_data = (void *)0x1FUL, 10741fd68434SRafael J. Wysocki }, 1075d2f9c061SMaciej Rutecki { 1076d2f9c061SMaciej Rutecki .ident = "HP Compaq 6720s", 1077d2f9c061SMaciej Rutecki .matches = { 1078d2f9c061SMaciej Rutecki DMI_MATCH(DMI_SYS_VENDOR, "Hewlett-Packard"), 1079d2f9c061SMaciej Rutecki DMI_MATCH(DMI_PRODUCT_NAME, "HP Compaq 6720s"), 1080d2f9c061SMaciej Rutecki }, 1081d2f9c061SMaciej Rutecki /* PCI slot number of the controller */ 1082d2f9c061SMaciej Rutecki .driver_data = (void *)0x1FUL, 1083d2f9c061SMaciej Rutecki }, 10841fd68434SRafael J. Wysocki 10851fd68434SRafael J. Wysocki { } /* terminate list */ 10861fd68434SRafael J. Wysocki }; 10871fd68434SRafael J. Wysocki const struct dmi_system_id *dmi = dmi_first_match(broken_systems); 10881fd68434SRafael J. Wysocki 10891fd68434SRafael J. Wysocki if (dmi) { 10901fd68434SRafael J. Wysocki unsigned long slot = (unsigned long)dmi->driver_data; 10911fd68434SRafael J. Wysocki /* apply the quirk only to on-board controllers */ 10921fd68434SRafael J. Wysocki return slot == PCI_SLOT(pdev->devfn); 10931fd68434SRafael J. Wysocki } 10941fd68434SRafael J. Wysocki 10951fd68434SRafael J. Wysocki return false; 10961fd68434SRafael J. Wysocki } 10971fd68434SRafael J. Wysocki 10989b10ae86STejun Heo static bool ahci_broken_suspend(struct pci_dev *pdev) 10999b10ae86STejun Heo { 11009b10ae86STejun Heo static const struct dmi_system_id sysids[] = { 11019b10ae86STejun Heo /* 11029b10ae86STejun Heo * On HP dv[4-6] and HDX18 with earlier BIOSen, link 11039b10ae86STejun Heo * to the harddisk doesn't become online after 11049b10ae86STejun Heo * resuming from STR. Warn and fail suspend. 11059deb3431STejun Heo * 11069deb3431STejun Heo * http://bugzilla.kernel.org/show_bug.cgi?id=12276 11079deb3431STejun Heo * 11089deb3431STejun Heo * Use dates instead of versions to match as HP is 11099deb3431STejun Heo * apparently recycling both product and version 11109deb3431STejun Heo * strings. 11119deb3431STejun Heo * 11129deb3431STejun Heo * http://bugzilla.kernel.org/show_bug.cgi?id=15462 11139b10ae86STejun Heo */ 11149b10ae86STejun Heo { 11159b10ae86STejun Heo .ident = "dv4", 11169b10ae86STejun Heo .matches = { 11179b10ae86STejun Heo DMI_MATCH(DMI_SYS_VENDOR, "Hewlett-Packard"), 11189b10ae86STejun Heo DMI_MATCH(DMI_PRODUCT_NAME, 11199b10ae86STejun Heo "HP Pavilion dv4 Notebook PC"), 11209b10ae86STejun Heo }, 11219deb3431STejun Heo .driver_data = "20090105", /* F.30 */ 11229b10ae86STejun Heo }, 11239b10ae86STejun Heo { 11249b10ae86STejun Heo .ident = "dv5", 11259b10ae86STejun Heo .matches = { 11269b10ae86STejun Heo DMI_MATCH(DMI_SYS_VENDOR, "Hewlett-Packard"), 11279b10ae86STejun Heo DMI_MATCH(DMI_PRODUCT_NAME, 11289b10ae86STejun Heo "HP Pavilion dv5 Notebook PC"), 11299b10ae86STejun Heo }, 11309deb3431STejun Heo .driver_data = "20090506", /* F.16 */ 11319b10ae86STejun Heo }, 11329b10ae86STejun Heo { 11339b10ae86STejun Heo .ident = "dv6", 11349b10ae86STejun Heo .matches = { 11359b10ae86STejun Heo DMI_MATCH(DMI_SYS_VENDOR, "Hewlett-Packard"), 11369b10ae86STejun Heo DMI_MATCH(DMI_PRODUCT_NAME, 11379b10ae86STejun Heo "HP Pavilion dv6 Notebook PC"), 11389b10ae86STejun Heo }, 11399deb3431STejun Heo .driver_data = "20090423", /* F.21 */ 11409b10ae86STejun Heo }, 11419b10ae86STejun Heo { 11429b10ae86STejun Heo .ident = "HDX18", 11439b10ae86STejun Heo .matches = { 11449b10ae86STejun Heo DMI_MATCH(DMI_SYS_VENDOR, "Hewlett-Packard"), 11459b10ae86STejun Heo DMI_MATCH(DMI_PRODUCT_NAME, 11469b10ae86STejun Heo "HP HDX18 Notebook PC"), 11479b10ae86STejun Heo }, 11489deb3431STejun Heo .driver_data = "20090430", /* F.23 */ 11499b10ae86STejun Heo }, 1150cedc9bf9STejun Heo /* 1151cedc9bf9STejun Heo * Acer eMachines G725 has the same problem. BIOS 1152cedc9bf9STejun Heo * V1.03 is known to be broken. V3.04 is known to 115325985edcSLucas De Marchi * work. Between, there are V1.06, V2.06 and V3.03 1154cedc9bf9STejun Heo * that we don't have much idea about. For now, 1155cedc9bf9STejun Heo * blacklist anything older than V3.04. 11569deb3431STejun Heo * 11579deb3431STejun Heo * http://bugzilla.kernel.org/show_bug.cgi?id=15104 1158cedc9bf9STejun Heo */ 1159cedc9bf9STejun Heo { 1160cedc9bf9STejun Heo .ident = "G725", 1161cedc9bf9STejun Heo .matches = { 1162cedc9bf9STejun Heo DMI_MATCH(DMI_SYS_VENDOR, "eMachines"), 1163cedc9bf9STejun Heo DMI_MATCH(DMI_PRODUCT_NAME, "eMachines G725"), 1164cedc9bf9STejun Heo }, 11659deb3431STejun Heo .driver_data = "20091216", /* V3.04 */ 1166cedc9bf9STejun Heo }, 11679b10ae86STejun Heo { } /* terminate list */ 11689b10ae86STejun Heo }; 11699b10ae86STejun Heo const struct dmi_system_id *dmi = dmi_first_match(sysids); 11709deb3431STejun Heo int year, month, date; 11719deb3431STejun Heo char buf[9]; 11729b10ae86STejun Heo 11739b10ae86STejun Heo if (!dmi || pdev->bus->number || pdev->devfn != PCI_DEVFN(0x1f, 2)) 11749b10ae86STejun Heo return false; 11759b10ae86STejun Heo 11769deb3431STejun Heo dmi_get_date(DMI_BIOS_DATE, &year, &month, &date); 11779deb3431STejun Heo snprintf(buf, sizeof(buf), "%04d%02d%02d", year, month, date); 11789b10ae86STejun Heo 11799deb3431STejun Heo return strcmp(buf, dmi->driver_data) < 0; 11809b10ae86STejun Heo } 11819b10ae86STejun Heo 11825594639aSTejun Heo static bool ahci_broken_online(struct pci_dev *pdev) 11835594639aSTejun Heo { 11845594639aSTejun Heo #define ENCODE_BUSDEVFN(bus, slot, func) \ 11855594639aSTejun Heo (void *)(unsigned long)(((bus) << 8) | PCI_DEVFN((slot), (func))) 11865594639aSTejun Heo static const struct dmi_system_id sysids[] = { 11875594639aSTejun Heo /* 11885594639aSTejun Heo * There are several gigabyte boards which use 11895594639aSTejun Heo * SIMG5723s configured as hardware RAID. Certain 11905594639aSTejun Heo * 5723 firmware revisions shipped there keep the link 11915594639aSTejun Heo * online but fail to answer properly to SRST or 11925594639aSTejun Heo * IDENTIFY when no device is attached downstream 11935594639aSTejun Heo * causing libata to retry quite a few times leading 11945594639aSTejun Heo * to excessive detection delay. 11955594639aSTejun Heo * 11965594639aSTejun Heo * As these firmwares respond to the second reset try 11975594639aSTejun Heo * with invalid device signature, considering unknown 11985594639aSTejun Heo * sig as offline works around the problem acceptably. 11995594639aSTejun Heo */ 12005594639aSTejun Heo { 12015594639aSTejun Heo .ident = "EP45-DQ6", 12025594639aSTejun Heo .matches = { 12035594639aSTejun Heo DMI_MATCH(DMI_BOARD_VENDOR, 12045594639aSTejun Heo "Gigabyte Technology Co., Ltd."), 12055594639aSTejun Heo DMI_MATCH(DMI_BOARD_NAME, "EP45-DQ6"), 12065594639aSTejun Heo }, 12075594639aSTejun Heo .driver_data = ENCODE_BUSDEVFN(0x0a, 0x00, 0), 12085594639aSTejun Heo }, 12095594639aSTejun Heo { 12105594639aSTejun Heo .ident = "EP45-DS5", 12115594639aSTejun Heo .matches = { 12125594639aSTejun Heo DMI_MATCH(DMI_BOARD_VENDOR, 12135594639aSTejun Heo "Gigabyte Technology Co., Ltd."), 12145594639aSTejun Heo DMI_MATCH(DMI_BOARD_NAME, "EP45-DS5"), 12155594639aSTejun Heo }, 12165594639aSTejun Heo .driver_data = ENCODE_BUSDEVFN(0x03, 0x00, 0), 12175594639aSTejun Heo }, 12185594639aSTejun Heo { } /* terminate list */ 12195594639aSTejun Heo }; 12205594639aSTejun Heo #undef ENCODE_BUSDEVFN 12215594639aSTejun Heo const struct dmi_system_id *dmi = dmi_first_match(sysids); 12225594639aSTejun Heo unsigned int val; 12235594639aSTejun Heo 12245594639aSTejun Heo if (!dmi) 12255594639aSTejun Heo return false; 12265594639aSTejun Heo 12275594639aSTejun Heo val = (unsigned long)dmi->driver_data; 12285594639aSTejun Heo 12295594639aSTejun Heo return pdev->bus->number == (val >> 8) && pdev->devfn == (val & 0xff); 12305594639aSTejun Heo } 12315594639aSTejun Heo 12320cf4a7d6SJacob Pan static bool ahci_broken_devslp(struct pci_dev *pdev) 12330cf4a7d6SJacob Pan { 12340cf4a7d6SJacob Pan /* device with broken DEVSLP but still showing SDS capability */ 12350cf4a7d6SJacob Pan static const struct pci_device_id ids[] = { 12360cf4a7d6SJacob Pan { PCI_VDEVICE(INTEL, 0x0f23)}, /* Valleyview SoC */ 12370cf4a7d6SJacob Pan {} 12380cf4a7d6SJacob Pan }; 12390cf4a7d6SJacob Pan 12400cf4a7d6SJacob Pan return pci_match_id(ids, pdev); 12410cf4a7d6SJacob Pan } 12420cf4a7d6SJacob Pan 12438e513217SMarkus Trippelsdorf #ifdef CONFIG_ATA_ACPI 1244f80ae7e4STejun Heo static void ahci_gtf_filter_workaround(struct ata_host *host) 1245f80ae7e4STejun Heo { 1246f80ae7e4STejun Heo static const struct dmi_system_id sysids[] = { 1247f80ae7e4STejun Heo /* 1248f80ae7e4STejun Heo * Aspire 3810T issues a bunch of SATA enable commands 1249f80ae7e4STejun Heo * via _GTF including an invalid one and one which is 1250f80ae7e4STejun Heo * rejected by the device. Among the successful ones 1251f80ae7e4STejun Heo * is FPDMA non-zero offset enable which when enabled 1252f80ae7e4STejun Heo * only on the drive side leads to NCQ command 1253f80ae7e4STejun Heo * failures. Filter it out. 1254f80ae7e4STejun Heo */ 1255f80ae7e4STejun Heo { 1256f80ae7e4STejun Heo .ident = "Aspire 3810T", 1257f80ae7e4STejun Heo .matches = { 1258f80ae7e4STejun Heo DMI_MATCH(DMI_SYS_VENDOR, "Acer"), 1259f80ae7e4STejun Heo DMI_MATCH(DMI_PRODUCT_NAME, "Aspire 3810T"), 1260f80ae7e4STejun Heo }, 1261f80ae7e4STejun Heo .driver_data = (void *)ATA_ACPI_FILTER_FPDMA_OFFSET, 1262f80ae7e4STejun Heo }, 1263f80ae7e4STejun Heo { } 1264f80ae7e4STejun Heo }; 1265f80ae7e4STejun Heo const struct dmi_system_id *dmi = dmi_first_match(sysids); 1266f80ae7e4STejun Heo unsigned int filter; 1267f80ae7e4STejun Heo int i; 1268f80ae7e4STejun Heo 1269f80ae7e4STejun Heo if (!dmi) 1270f80ae7e4STejun Heo return; 1271f80ae7e4STejun Heo 1272f80ae7e4STejun Heo filter = (unsigned long)dmi->driver_data; 1273a44fec1fSJoe Perches dev_info(host->dev, "applying extra ACPI _GTF filter 0x%x for %s\n", 1274f80ae7e4STejun Heo filter, dmi->ident); 1275f80ae7e4STejun Heo 1276f80ae7e4STejun Heo for (i = 0; i < host->n_ports; i++) { 1277f80ae7e4STejun Heo struct ata_port *ap = host->ports[i]; 1278f80ae7e4STejun Heo struct ata_link *link; 1279f80ae7e4STejun Heo struct ata_device *dev; 1280f80ae7e4STejun Heo 1281f80ae7e4STejun Heo ata_for_each_link(link, ap, EDGE) 1282f80ae7e4STejun Heo ata_for_each_dev(dev, link, ALL) 1283f80ae7e4STejun Heo dev->gtf_filter |= filter; 1284f80ae7e4STejun Heo } 1285f80ae7e4STejun Heo } 12868e513217SMarkus Trippelsdorf #else 12878e513217SMarkus Trippelsdorf static inline void ahci_gtf_filter_workaround(struct ata_host *host) 12888e513217SMarkus Trippelsdorf {} 12898e513217SMarkus Trippelsdorf #endif 1290f80ae7e4STejun Heo 1291e1ba8459SLinus Torvalds static int ahci_init_interrupts(struct pci_dev *pdev, unsigned int n_ports, 12927b92b4f6SAlexander Gordeev struct ahci_host_priv *hpriv) 12935ca72c4fSAlexander Gordeev { 1294ccf8f53cSAlexander Gordeev int rc, nvec; 12955ca72c4fSAlexander Gordeev 12967b92b4f6SAlexander Gordeev if (hpriv->flags & AHCI_HFLAG_NO_MSI) 12977b92b4f6SAlexander Gordeev goto intx; 12987b92b4f6SAlexander Gordeev 1299fc061d96SAlexander Gordeev nvec = pci_msi_vec_count(pdev); 1300fc061d96SAlexander Gordeev if (nvec < 0) 13017b92b4f6SAlexander Gordeev goto intx; 13027b92b4f6SAlexander Gordeev 13035ca72c4fSAlexander Gordeev /* 13047b92b4f6SAlexander Gordeev * If number of MSIs is less than number of ports then Sharing Last 13057b92b4f6SAlexander Gordeev * Message mode could be enforced. In this case assume that advantage 13067b92b4f6SAlexander Gordeev * of multipe MSIs is negated and use single MSI mode instead. 13075ca72c4fSAlexander Gordeev */ 1308fc061d96SAlexander Gordeev if (nvec < n_ports) 13097b92b4f6SAlexander Gordeev goto single_msi; 13105ca72c4fSAlexander Gordeev 1311ccf8f53cSAlexander Gordeev rc = pci_enable_msi_exact(pdev, nvec); 1312ccf8f53cSAlexander Gordeev if (rc == -ENOSPC) 1313fc40363bSAlexander Gordeev goto single_msi; 1314ccf8f53cSAlexander Gordeev else if (rc < 0) 1315fc061d96SAlexander Gordeev goto intx; 1316ab0f9e78SAlexander Gordeev 1317ab0f9e78SAlexander Gordeev /* fallback to single MSI mode if the controller enforced MRSM mode */ 1318ab0f9e78SAlexander Gordeev if (readl(hpriv->mmio + HOST_CTL) & HOST_MRSM) { 1319ab0f9e78SAlexander Gordeev pci_disable_msi(pdev); 1320ab0f9e78SAlexander Gordeev printk(KERN_INFO "ahci: MRSM is on, fallback to single MSI\n"); 1321ab0f9e78SAlexander Gordeev goto single_msi; 1322ab0f9e78SAlexander Gordeev } 13237b92b4f6SAlexander Gordeev 1324c3ebd6a9SAlexander Gordeev if (nvec > 1) 1325c3ebd6a9SAlexander Gordeev hpriv->flags |= AHCI_HFLAG_MULTI_MSI; 1326c3ebd6a9SAlexander Gordeev 13277b92b4f6SAlexander Gordeev return nvec; 13287b92b4f6SAlexander Gordeev 13297b92b4f6SAlexander Gordeev single_msi: 1330fc061d96SAlexander Gordeev if (pci_enable_msi(pdev)) 13317b92b4f6SAlexander Gordeev goto intx; 13327b92b4f6SAlexander Gordeev return 1; 13337b92b4f6SAlexander Gordeev 13347b92b4f6SAlexander Gordeev intx: 13355ca72c4fSAlexander Gordeev pci_intx(pdev, 1); 13365ca72c4fSAlexander Gordeev return 0; 13375ca72c4fSAlexander Gordeev } 13385ca72c4fSAlexander Gordeev 1339c6fd2807SJeff Garzik static int ahci_init_one(struct pci_dev *pdev, const struct pci_device_id *ent) 1340c6fd2807SJeff Garzik { 1341e297d99eSTejun Heo unsigned int board_id = ent->driver_data; 1342e297d99eSTejun Heo struct ata_port_info pi = ahci_port_info[board_id]; 13434447d351STejun Heo const struct ata_port_info *ppi[] = { &pi, NULL }; 134424dc5f33STejun Heo struct device *dev = &pdev->dev; 1345c6fd2807SJeff Garzik struct ahci_host_priv *hpriv; 13464447d351STejun Heo struct ata_host *host; 1347c3ebd6a9SAlexander Gordeev int n_ports, i, rc; 1348318893e1SAlessandro Rubini int ahci_pci_bar = AHCI_PCI_BAR_STANDARD; 1349c6fd2807SJeff Garzik 1350c6fd2807SJeff Garzik VPRINTK("ENTER\n"); 1351c6fd2807SJeff Garzik 1352b429dd59SJustin P. Mattock WARN_ON((int)ATA_MAX_QUEUE > AHCI_MAX_CMDS); 1353c6fd2807SJeff Garzik 135406296a1eSJoe Perches ata_print_version_once(&pdev->dev, DRV_VERSION); 1355c6fd2807SJeff Garzik 13565b66c829SAlan Cox /* The AHCI driver can only drive the SATA ports, the PATA driver 13575b66c829SAlan Cox can drive them all so if both drivers are selected make sure 13585b66c829SAlan Cox AHCI stays out of the way */ 13595b66c829SAlan Cox if (pdev->vendor == PCI_VENDOR_ID_MARVELL && !marvell_enable) 13605b66c829SAlan Cox return -ENODEV; 13615b66c829SAlan Cox 1362cb85696dSJames Laird /* Apple BIOS on MCP89 prevents us using AHCI */ 1363cb85696dSJames Laird if (is_mcp89_apple(pdev)) 1364cb85696dSJames Laird ahci_mcp89_apple_enable(pdev); 1365c6353b45STejun Heo 13667a02267eSMark Nelson /* Promise's PDC42819 is a SAS/SATA controller that has an AHCI mode. 13677a02267eSMark Nelson * At the moment, we can only use the AHCI mode. Let the users know 13687a02267eSMark Nelson * that for SAS drives they're out of luck. 13697a02267eSMark Nelson */ 13707a02267eSMark Nelson if (pdev->vendor == PCI_VENDOR_ID_PROMISE) 1371a44fec1fSJoe Perches dev_info(&pdev->dev, 1372a44fec1fSJoe Perches "PDC42819 can only drive SATA devices with this driver\n"); 13737a02267eSMark Nelson 13747f9c9f8eSHugh Daschbach /* Both Connext and Enmotus devices use non-standard BARs */ 1375318893e1SAlessandro Rubini if (pdev->vendor == PCI_VENDOR_ID_STMICRO && pdev->device == 0xCC06) 1376318893e1SAlessandro Rubini ahci_pci_bar = AHCI_PCI_BAR_STA2X11; 13777f9c9f8eSHugh Daschbach else if (pdev->vendor == 0x1c44 && pdev->device == 0x8000) 13787f9c9f8eSHugh Daschbach ahci_pci_bar = AHCI_PCI_BAR_ENMOTUS; 1379318893e1SAlessandro Rubini 1380e6b7e41cSChuansheng Liu /* 1381e6b7e41cSChuansheng Liu * The JMicron chip 361/363 contains one SATA controller and one 1382e6b7e41cSChuansheng Liu * PATA controller,for powering on these both controllers, we must 1383e6b7e41cSChuansheng Liu * follow the sequence one by one, otherwise one of them can not be 1384e6b7e41cSChuansheng Liu * powered on successfully, so here we disable the async suspend 1385e6b7e41cSChuansheng Liu * method for these chips. 1386e6b7e41cSChuansheng Liu */ 1387e6b7e41cSChuansheng Liu if (pdev->vendor == PCI_VENDOR_ID_JMICRON && 1388e6b7e41cSChuansheng Liu (pdev->device == PCI_DEVICE_ID_JMICRON_JMB363 || 1389e6b7e41cSChuansheng Liu pdev->device == PCI_DEVICE_ID_JMICRON_JMB361)) 1390e6b7e41cSChuansheng Liu device_disable_async_suspend(&pdev->dev); 1391e6b7e41cSChuansheng Liu 13924447d351STejun Heo /* acquire resources */ 139324dc5f33STejun Heo rc = pcim_enable_device(pdev); 1394c6fd2807SJeff Garzik if (rc) 1395c6fd2807SJeff Garzik return rc; 1396c6fd2807SJeff Garzik 1397c4f7792cSTejun Heo if (pdev->vendor == PCI_VENDOR_ID_INTEL && 1398c4f7792cSTejun Heo (pdev->device == 0x2652 || pdev->device == 0x2653)) { 1399c4f7792cSTejun Heo u8 map; 1400c4f7792cSTejun Heo 1401c4f7792cSTejun Heo /* ICH6s share the same PCI ID for both piix and ahci 1402c4f7792cSTejun Heo * modes. Enabling ahci mode while MAP indicates 1403c4f7792cSTejun Heo * combined mode is a bad idea. Yield to ata_piix. 1404c4f7792cSTejun Heo */ 1405c4f7792cSTejun Heo pci_read_config_byte(pdev, ICH_MAP, &map); 1406c4f7792cSTejun Heo if (map & 0x3) { 1407a44fec1fSJoe Perches dev_info(&pdev->dev, 1408a44fec1fSJoe Perches "controller is in combined mode, can't enable AHCI mode\n"); 1409c4f7792cSTejun Heo return -ENODEV; 1410c4f7792cSTejun Heo } 1411c4f7792cSTejun Heo } 1412c4f7792cSTejun Heo 14136fec8871SPaul Bolle /* AHCI controllers often implement SFF compatible interface. 14146fec8871SPaul Bolle * Grab all PCI BARs just in case. 14156fec8871SPaul Bolle */ 14166fec8871SPaul Bolle rc = pcim_iomap_regions_request_all(pdev, 1 << ahci_pci_bar, DRV_NAME); 14176fec8871SPaul Bolle if (rc == -EBUSY) 14186fec8871SPaul Bolle pcim_pin_device(pdev); 14196fec8871SPaul Bolle if (rc) 14206fec8871SPaul Bolle return rc; 14216fec8871SPaul Bolle 142224dc5f33STejun Heo hpriv = devm_kzalloc(dev, sizeof(*hpriv), GFP_KERNEL); 142324dc5f33STejun Heo if (!hpriv) 142424dc5f33STejun Heo return -ENOMEM; 1425417a1a6dSTejun Heo hpriv->flags |= (unsigned long)pi.private_data; 1426417a1a6dSTejun Heo 1427e297d99eSTejun Heo /* MCP65 revision A1 and A2 can't do MSI */ 1428e297d99eSTejun Heo if (board_id == board_ahci_mcp65 && 1429e297d99eSTejun Heo (pdev->revision == 0xa1 || pdev->revision == 0xa2)) 1430e297d99eSTejun Heo hpriv->flags |= AHCI_HFLAG_NO_MSI; 1431e297d99eSTejun Heo 1432e427fe04SShane Huang /* SB800 does NOT need the workaround to ignore SERR_INTERNAL */ 1433e427fe04SShane Huang if (board_id == board_ahci_sb700 && pdev->revision >= 0x40) 1434e427fe04SShane Huang hpriv->flags &= ~AHCI_HFLAG_IGN_SERR_INTERNAL; 1435e427fe04SShane Huang 14362fcad9d2STejun Heo /* only some SB600s can do 64bit DMA */ 14372fcad9d2STejun Heo if (ahci_sb600_enable_64bit(pdev)) 14382fcad9d2STejun Heo hpriv->flags &= ~AHCI_HFLAG_32BIT_ONLY; 143958a09b38SShane Huang 1440318893e1SAlessandro Rubini hpriv->mmio = pcim_iomap_table(pdev)[ahci_pci_bar]; 1441d8993349SAnton Vorontsov 14420cf4a7d6SJacob Pan /* must set flag prior to save config in order to take effect */ 14430cf4a7d6SJacob Pan if (ahci_broken_devslp(pdev)) 14440cf4a7d6SJacob Pan hpriv->flags |= AHCI_HFLAG_NO_DEVSLP; 14450cf4a7d6SJacob Pan 14464447d351STejun Heo /* save initial config */ 1447394d6e53SAnton Vorontsov ahci_pci_save_initial_config(pdev, hpriv); 1448c6fd2807SJeff Garzik 14494447d351STejun Heo /* prepare host */ 1450453d3131SRobert Hancock if (hpriv->cap & HOST_CAP_NCQ) { 1451453d3131SRobert Hancock pi.flags |= ATA_FLAG_NCQ; 145283f2b963STejun Heo /* 145383f2b963STejun Heo * Auto-activate optimization is supposed to be 145483f2b963STejun Heo * supported on all AHCI controllers indicating NCQ 145583f2b963STejun Heo * capability, but it seems to be broken on some 145683f2b963STejun Heo * chipsets including NVIDIAs. 145783f2b963STejun Heo */ 145883f2b963STejun Heo if (!(hpriv->flags & AHCI_HFLAG_NO_FPDMA_AA)) 1459453d3131SRobert Hancock pi.flags |= ATA_FLAG_FPDMA_AA; 146040fb59e7SMarc Carino 146140fb59e7SMarc Carino /* 146240fb59e7SMarc Carino * All AHCI controllers should be forward-compatible 146340fb59e7SMarc Carino * with the new auxiliary field. This code should be 146440fb59e7SMarc Carino * conditionalized if any buggy AHCI controllers are 146540fb59e7SMarc Carino * encountered. 146640fb59e7SMarc Carino */ 146740fb59e7SMarc Carino pi.flags |= ATA_FLAG_FPDMA_AUX; 1468453d3131SRobert Hancock } 14694447d351STejun Heo 14707d50b60bSTejun Heo if (hpriv->cap & HOST_CAP_PMP) 14717d50b60bSTejun Heo pi.flags |= ATA_FLAG_PMP; 14727d50b60bSTejun Heo 14730cbb0e77SAnton Vorontsov ahci_set_em_messages(hpriv, &pi); 147418f7ba4cSKristen Carlson Accardi 14751fd68434SRafael J. Wysocki if (ahci_broken_system_poweroff(pdev)) { 14761fd68434SRafael J. Wysocki pi.flags |= ATA_FLAG_NO_POWEROFF_SPINDOWN; 14771fd68434SRafael J. Wysocki dev_info(&pdev->dev, 14781fd68434SRafael J. Wysocki "quirky BIOS, skipping spindown on poweroff\n"); 14791fd68434SRafael J. Wysocki } 14801fd68434SRafael J. Wysocki 14819b10ae86STejun Heo if (ahci_broken_suspend(pdev)) { 14829b10ae86STejun Heo hpriv->flags |= AHCI_HFLAG_NO_SUSPEND; 1483a44fec1fSJoe Perches dev_warn(&pdev->dev, 14849b10ae86STejun Heo "BIOS update required for suspend/resume\n"); 14859b10ae86STejun Heo } 14869b10ae86STejun Heo 14875594639aSTejun Heo if (ahci_broken_online(pdev)) { 14885594639aSTejun Heo hpriv->flags |= AHCI_HFLAG_SRST_TOUT_IS_OFFLINE; 14895594639aSTejun Heo dev_info(&pdev->dev, 14905594639aSTejun Heo "online status unreliable, applying workaround\n"); 14915594639aSTejun Heo } 14925594639aSTejun Heo 1493837f5f8fSTejun Heo /* CAP.NP sometimes indicate the index of the last enabled 1494837f5f8fSTejun Heo * port, at other times, that of the last possible port, so 1495837f5f8fSTejun Heo * determining the maximum port number requires looking at 1496837f5f8fSTejun Heo * both CAP.NP and port_map. 1497837f5f8fSTejun Heo */ 1498837f5f8fSTejun Heo n_ports = max(ahci_nr_ports(hpriv->cap), fls(hpriv->port_map)); 1499837f5f8fSTejun Heo 1500c3ebd6a9SAlexander Gordeev ahci_init_interrupts(pdev, n_ports, hpriv); 15017b92b4f6SAlexander Gordeev 1502837f5f8fSTejun Heo host = ata_host_alloc_pinfo(&pdev->dev, ppi, n_ports); 15034447d351STejun Heo if (!host) 15044447d351STejun Heo return -ENOMEM; 15054447d351STejun Heo host->private_data = hpriv; 15064447d351STejun Heo 1507f3d7f23fSArjan van de Ven if (!(hpriv->cap & HOST_CAP_SSS) || ahci_ignore_sss) 1508886ad09fSArjan van de Ven host->flags |= ATA_HOST_PARALLEL_SCAN; 1509f3d7f23fSArjan van de Ven else 1510d2782d96SJingoo Han dev_info(&pdev->dev, "SSS flag set, parallel bus scan disabled\n"); 1511886ad09fSArjan van de Ven 151218f7ba4cSKristen Carlson Accardi if (pi.flags & ATA_FLAG_EM) 151318f7ba4cSKristen Carlson Accardi ahci_reset_em(host); 151418f7ba4cSKristen Carlson Accardi 15154447d351STejun Heo for (i = 0; i < host->n_ports; i++) { 15164447d351STejun Heo struct ata_port *ap = host->ports[i]; 15174447d351STejun Heo 1518318893e1SAlessandro Rubini ata_port_pbar_desc(ap, ahci_pci_bar, -1, "abar"); 1519318893e1SAlessandro Rubini ata_port_pbar_desc(ap, ahci_pci_bar, 1520cbcdd875STejun Heo 0x100 + ap->port_no * 0x80, "port"); 1521cbcdd875STejun Heo 152218f7ba4cSKristen Carlson Accardi /* set enclosure management message type */ 152318f7ba4cSKristen Carlson Accardi if (ap->flags & ATA_FLAG_EM) 1524008dbd61SHarry Zhang ap->em_message_type = hpriv->em_msg_type; 152518f7ba4cSKristen Carlson Accardi 152618f7ba4cSKristen Carlson Accardi 1527dab632e8SJeff Garzik /* disabled/not-implemented port */ 1528350756f6STejun Heo if (!(hpriv->port_map & (1 << i))) 1529dab632e8SJeff Garzik ap->ops = &ata_dummy_port_ops; 15304447d351STejun Heo } 1531c6fd2807SJeff Garzik 1532edc93052STejun Heo /* apply workaround for ASUS P5W DH Deluxe mainboard */ 1533edc93052STejun Heo ahci_p5wdh_workaround(host); 1534edc93052STejun Heo 1535f80ae7e4STejun Heo /* apply gtf filter quirk */ 1536f80ae7e4STejun Heo ahci_gtf_filter_workaround(host); 1537f80ae7e4STejun Heo 1538c6fd2807SJeff Garzik /* initialize adapter */ 15394447d351STejun Heo rc = ahci_configure_dma_masks(pdev, hpriv->cap & HOST_CAP_64); 1540c6fd2807SJeff Garzik if (rc) 154124dc5f33STejun Heo return rc; 1542c6fd2807SJeff Garzik 15433303040dSAnton Vorontsov rc = ahci_pci_reset_controller(host); 15444447d351STejun Heo if (rc) 15454447d351STejun Heo return rc; 1546c6fd2807SJeff Garzik 1547781d6550SAnton Vorontsov ahci_pci_init_controller(host); 1548439fcaecSAnton Vorontsov ahci_pci_print_info(host); 1549c6fd2807SJeff Garzik 15504447d351STejun Heo pci_set_master(pdev); 15515ca72c4fSAlexander Gordeev 1552a6849b9fSAlexander Gordeev return ahci_host_activate(host, pdev->irq, &ahci_sht); 1553c6fd2807SJeff Garzik } 1554c6fd2807SJeff Garzik 15552fc75da0SAxel Lin module_pci_driver(ahci_pci_driver); 1556c6fd2807SJeff Garzik 1557c6fd2807SJeff Garzik MODULE_AUTHOR("Jeff Garzik"); 1558c6fd2807SJeff Garzik MODULE_DESCRIPTION("AHCI SATA low-level driver"); 1559c6fd2807SJeff Garzik MODULE_LICENSE("GPL"); 1560c6fd2807SJeff Garzik MODULE_DEVICE_TABLE(pci, ahci_pci_tbl); 1561c6fd2807SJeff Garzik MODULE_VERSION(DRV_VERSION); 1562