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