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, 6367809f85SLevente Kurusa board_ahci_noncq, 64441577efSTejun Heo board_ahci_nosntf, 655f173107STejun Heo board_ahci_yes_fbs, 66441577efSTejun Heo 67441577efSTejun Heo /* board IDs for specific chipsets in alphabetical order */ 68441577efSTejun Heo board_ahci_mcp65, 6983f2b963STejun Heo board_ahci_mcp77, 7083f2b963STejun Heo board_ahci_mcp89, 71441577efSTejun Heo board_ahci_mv, 72441577efSTejun Heo board_ahci_sb600, 73441577efSTejun Heo board_ahci_sb700, /* for SB700 and SB800 */ 74441577efSTejun Heo board_ahci_vt8251, 75441577efSTejun Heo 76441577efSTejun Heo /* aliases */ 77441577efSTejun Heo board_ahci_mcp_linux = board_ahci_mcp65, 78441577efSTejun Heo board_ahci_mcp67 = board_ahci_mcp65, 79441577efSTejun Heo board_ahci_mcp73 = board_ahci_mcp65, 8083f2b963STejun Heo board_ahci_mcp79 = board_ahci_mcp77, 81c6fd2807SJeff Garzik }; 82c6fd2807SJeff Garzik 83c6fd2807SJeff Garzik static int ahci_init_one(struct pci_dev *pdev, const struct pci_device_id *ent); 84a1efdabaSTejun Heo static int ahci_vt8251_hardreset(struct ata_link *link, unsigned int *class, 85a1efdabaSTejun Heo unsigned long deadline); 86cb85696dSJames Laird static void ahci_mcp89_apple_enable(struct pci_dev *pdev); 87cb85696dSJames Laird static bool is_mcp89_apple(struct pci_dev *pdev); 88a1efdabaSTejun Heo static int ahci_p5wdh_hardreset(struct ata_link *link, unsigned int *class, 89a1efdabaSTejun Heo unsigned long deadline); 90438ac6d5STejun Heo #ifdef CONFIG_PM 91c6fd2807SJeff Garzik static int ahci_pci_device_suspend(struct pci_dev *pdev, pm_message_t mesg); 92c6fd2807SJeff Garzik static int ahci_pci_device_resume(struct pci_dev *pdev); 93438ac6d5STejun Heo #endif 94c6fd2807SJeff Garzik 95fad16e7aSTejun Heo static struct scsi_host_template ahci_sht = { 96fad16e7aSTejun Heo AHCI_SHT("ahci"), 97fad16e7aSTejun Heo }; 98fad16e7aSTejun Heo 99029cfd6bSTejun Heo static struct ata_port_operations ahci_vt8251_ops = { 100029cfd6bSTejun Heo .inherits = &ahci_ops, 101a1efdabaSTejun Heo .hardreset = ahci_vt8251_hardreset, 102ad616ffbSTejun Heo }; 103ad616ffbSTejun Heo 104029cfd6bSTejun Heo static struct ata_port_operations ahci_p5wdh_ops = { 105029cfd6bSTejun Heo .inherits = &ahci_ops, 106a1efdabaSTejun Heo .hardreset = ahci_p5wdh_hardreset, 107edc93052STejun Heo }; 108edc93052STejun Heo 109c6fd2807SJeff Garzik static const struct ata_port_info ahci_port_info[] = { 110441577efSTejun Heo /* by features */ 111facb8fa6SJeffrin Jose [board_ahci] = { 1121188c0d8STejun Heo .flags = AHCI_FLAG_COMMON, 11314bdef98SErik Inge Bolsø .pio_mask = ATA_PIO4, 114469248abSJeff Garzik .udma_mask = ATA_UDMA6, 115c6fd2807SJeff Garzik .port_ops = &ahci_ops, 116c6fd2807SJeff Garzik }, 117facb8fa6SJeffrin Jose [board_ahci_ign_iferr] = { 118417a1a6dSTejun Heo AHCI_HFLAGS (AHCI_HFLAG_IGN_IRQ_IF_ERR), 119417a1a6dSTejun Heo .flags = AHCI_FLAG_COMMON, 12014bdef98SErik Inge Bolsø .pio_mask = ATA_PIO4, 121469248abSJeff Garzik .udma_mask = ATA_UDMA6, 12241669553STejun Heo .port_ops = &ahci_ops, 12341669553STejun Heo }, 12467809f85SLevente Kurusa [board_ahci_noncq] = { 12567809f85SLevente Kurusa AHCI_HFLAGS (AHCI_HFLAG_NO_NCQ), 12667809f85SLevente Kurusa .flags = AHCI_FLAG_COMMON, 12767809f85SLevente Kurusa .pio_mask = ATA_PIO4, 12867809f85SLevente Kurusa .udma_mask = ATA_UDMA6, 12967809f85SLevente Kurusa .port_ops = &ahci_ops, 13067809f85SLevente Kurusa }, 131facb8fa6SJeffrin Jose [board_ahci_nosntf] = { 132441577efSTejun Heo AHCI_HFLAGS (AHCI_HFLAG_NO_SNTF), 133441577efSTejun Heo .flags = AHCI_FLAG_COMMON, 134441577efSTejun Heo .pio_mask = ATA_PIO4, 135441577efSTejun Heo .udma_mask = ATA_UDMA6, 136441577efSTejun Heo .port_ops = &ahci_ops, 137441577efSTejun Heo }, 138facb8fa6SJeffrin Jose [board_ahci_yes_fbs] = { 1395f173107STejun Heo AHCI_HFLAGS (AHCI_HFLAG_YES_FBS), 1405f173107STejun Heo .flags = AHCI_FLAG_COMMON, 1415f173107STejun Heo .pio_mask = ATA_PIO4, 1425f173107STejun Heo .udma_mask = ATA_UDMA6, 1435f173107STejun Heo .port_ops = &ahci_ops, 1445f173107STejun Heo }, 145441577efSTejun Heo /* by chipsets */ 146facb8fa6SJeffrin Jose [board_ahci_mcp65] = { 14783f2b963STejun Heo AHCI_HFLAGS (AHCI_HFLAG_NO_FPDMA_AA | AHCI_HFLAG_NO_PMP | 14883f2b963STejun Heo AHCI_HFLAG_YES_NCQ), 149ae01b249STejun Heo .flags = AHCI_FLAG_COMMON | ATA_FLAG_NO_DIPM, 15083f2b963STejun Heo .pio_mask = ATA_PIO4, 15183f2b963STejun Heo .udma_mask = ATA_UDMA6, 15283f2b963STejun Heo .port_ops = &ahci_ops, 15383f2b963STejun Heo }, 154facb8fa6SJeffrin Jose [board_ahci_mcp77] = { 15583f2b963STejun Heo AHCI_HFLAGS (AHCI_HFLAG_NO_FPDMA_AA | AHCI_HFLAG_NO_PMP), 15683f2b963STejun Heo .flags = AHCI_FLAG_COMMON, 15783f2b963STejun Heo .pio_mask = ATA_PIO4, 15883f2b963STejun Heo .udma_mask = ATA_UDMA6, 15983f2b963STejun Heo .port_ops = &ahci_ops, 16083f2b963STejun Heo }, 161facb8fa6SJeffrin Jose [board_ahci_mcp89] = { 16283f2b963STejun Heo AHCI_HFLAGS (AHCI_HFLAG_NO_FPDMA_AA), 163441577efSTejun Heo .flags = AHCI_FLAG_COMMON, 164441577efSTejun Heo .pio_mask = ATA_PIO4, 165441577efSTejun Heo .udma_mask = ATA_UDMA6, 166441577efSTejun Heo .port_ops = &ahci_ops, 167441577efSTejun Heo }, 168facb8fa6SJeffrin Jose [board_ahci_mv] = { 169441577efSTejun Heo AHCI_HFLAGS (AHCI_HFLAG_NO_NCQ | AHCI_HFLAG_NO_MSI | 170441577efSTejun Heo AHCI_HFLAG_MV_PATA | AHCI_HFLAG_NO_PMP), 1719cbe056fSSergei Shtylyov .flags = ATA_FLAG_SATA | ATA_FLAG_PIO_DMA, 172441577efSTejun Heo .pio_mask = ATA_PIO4, 173441577efSTejun Heo .udma_mask = ATA_UDMA6, 174441577efSTejun Heo .port_ops = &ahci_ops, 175441577efSTejun Heo }, 176facb8fa6SJeffrin Jose [board_ahci_sb600] = { 177417a1a6dSTejun Heo AHCI_HFLAGS (AHCI_HFLAG_IGN_SERR_INTERNAL | 1782fcad9d2STejun Heo AHCI_HFLAG_NO_MSI | AHCI_HFLAG_SECT255 | 1792fcad9d2STejun Heo AHCI_HFLAG_32BIT_ONLY), 180417a1a6dSTejun Heo .flags = AHCI_FLAG_COMMON, 18114bdef98SErik Inge Bolsø .pio_mask = ATA_PIO4, 182469248abSJeff Garzik .udma_mask = ATA_UDMA6, 183345347c5SYuan-Hsin Chen .port_ops = &ahci_pmp_retry_srst_ops, 18455a61604SConke Hu }, 185facb8fa6SJeffrin Jose [board_ahci_sb700] = { /* for SB700 and SB800 */ 186bd17243aSShane Huang AHCI_HFLAGS (AHCI_HFLAG_IGN_SERR_INTERNAL), 187e39fc8c9SShane Huang .flags = AHCI_FLAG_COMMON, 18814bdef98SErik Inge Bolsø .pio_mask = ATA_PIO4, 189e39fc8c9SShane Huang .udma_mask = ATA_UDMA6, 190345347c5SYuan-Hsin Chen .port_ops = &ahci_pmp_retry_srst_ops, 191e39fc8c9SShane Huang }, 192facb8fa6SJeffrin Jose [board_ahci_vt8251] = { 193441577efSTejun Heo AHCI_HFLAGS (AHCI_HFLAG_NO_NCQ | AHCI_HFLAG_NO_PMP), 194e297d99eSTejun Heo .flags = AHCI_FLAG_COMMON, 19514bdef98SErik Inge Bolsø .pio_mask = ATA_PIO4, 196e297d99eSTejun Heo .udma_mask = ATA_UDMA6, 197441577efSTejun Heo .port_ops = &ahci_vt8251_ops, 1981b677afdSShaohua Li }, 199c6fd2807SJeff Garzik }; 200c6fd2807SJeff Garzik 201c6fd2807SJeff Garzik static const struct pci_device_id ahci_pci_tbl[] = { 202c6fd2807SJeff Garzik /* Intel */ 20354bb3a94SJeff Garzik { PCI_VDEVICE(INTEL, 0x2652), board_ahci }, /* ICH6 */ 20454bb3a94SJeff Garzik { PCI_VDEVICE(INTEL, 0x2653), board_ahci }, /* ICH6M */ 20554bb3a94SJeff Garzik { PCI_VDEVICE(INTEL, 0x27c1), board_ahci }, /* ICH7 */ 20654bb3a94SJeff Garzik { PCI_VDEVICE(INTEL, 0x27c5), board_ahci }, /* ICH7M */ 20754bb3a94SJeff Garzik { PCI_VDEVICE(INTEL, 0x27c3), board_ahci }, /* ICH7R */ 20882490c09STejun Heo { PCI_VDEVICE(AL, 0x5288), board_ahci_ign_iferr }, /* ULi M5288 */ 20954bb3a94SJeff Garzik { PCI_VDEVICE(INTEL, 0x2681), board_ahci }, /* ESB2 */ 21054bb3a94SJeff Garzik { PCI_VDEVICE(INTEL, 0x2682), board_ahci }, /* ESB2 */ 21154bb3a94SJeff Garzik { PCI_VDEVICE(INTEL, 0x2683), board_ahci }, /* ESB2 */ 21254bb3a94SJeff Garzik { PCI_VDEVICE(INTEL, 0x27c6), board_ahci }, /* ICH7-M DH */ 2137a234affSTejun Heo { PCI_VDEVICE(INTEL, 0x2821), board_ahci }, /* ICH8 */ 2141b677afdSShaohua Li { PCI_VDEVICE(INTEL, 0x2822), board_ahci_nosntf }, /* ICH8 */ 2157a234affSTejun Heo { PCI_VDEVICE(INTEL, 0x2824), board_ahci }, /* ICH8 */ 2167a234affSTejun Heo { PCI_VDEVICE(INTEL, 0x2829), board_ahci }, /* ICH8M */ 2177a234affSTejun Heo { PCI_VDEVICE(INTEL, 0x282a), board_ahci }, /* ICH8M */ 2187a234affSTejun Heo { PCI_VDEVICE(INTEL, 0x2922), board_ahci }, /* ICH9 */ 2197a234affSTejun Heo { PCI_VDEVICE(INTEL, 0x2923), board_ahci }, /* ICH9 */ 2207a234affSTejun Heo { PCI_VDEVICE(INTEL, 0x2924), board_ahci }, /* ICH9 */ 2217a234affSTejun Heo { PCI_VDEVICE(INTEL, 0x2925), board_ahci }, /* ICH9 */ 2227a234affSTejun Heo { PCI_VDEVICE(INTEL, 0x2927), board_ahci }, /* ICH9 */ 2237a234affSTejun Heo { PCI_VDEVICE(INTEL, 0x2929), board_ahci }, /* ICH9M */ 2247a234affSTejun Heo { PCI_VDEVICE(INTEL, 0x292a), board_ahci }, /* ICH9M */ 2257a234affSTejun Heo { PCI_VDEVICE(INTEL, 0x292b), board_ahci }, /* ICH9M */ 2267a234affSTejun Heo { PCI_VDEVICE(INTEL, 0x292c), board_ahci }, /* ICH9M */ 2277a234affSTejun Heo { PCI_VDEVICE(INTEL, 0x292f), board_ahci }, /* ICH9M */ 2287a234affSTejun Heo { PCI_VDEVICE(INTEL, 0x294d), board_ahci }, /* ICH9 */ 2297a234affSTejun Heo { PCI_VDEVICE(INTEL, 0x294e), board_ahci }, /* ICH9M */ 230d4155e6fSJason Gaston { PCI_VDEVICE(INTEL, 0x502a), board_ahci }, /* Tolapai */ 231d4155e6fSJason Gaston { PCI_VDEVICE(INTEL, 0x502b), board_ahci }, /* Tolapai */ 23216ad1ad9SJason Gaston { PCI_VDEVICE(INTEL, 0x3a05), board_ahci }, /* ICH10 */ 233b2dde6afSMark Goodwin { PCI_VDEVICE(INTEL, 0x3a22), board_ahci }, /* ICH10 */ 23416ad1ad9SJason Gaston { PCI_VDEVICE(INTEL, 0x3a25), board_ahci }, /* ICH10 */ 235c1f57d9bSDavid Milburn { PCI_VDEVICE(INTEL, 0x3b22), board_ahci }, /* PCH AHCI */ 236c1f57d9bSDavid Milburn { PCI_VDEVICE(INTEL, 0x3b23), board_ahci }, /* PCH AHCI */ 237adcb5308SSeth Heasley { PCI_VDEVICE(INTEL, 0x3b24), board_ahci }, /* PCH RAID */ 2388e48b6b3SSeth Heasley { PCI_VDEVICE(INTEL, 0x3b25), board_ahci }, /* PCH RAID */ 239c1f57d9bSDavid Milburn { PCI_VDEVICE(INTEL, 0x3b29), board_ahci }, /* PCH AHCI */ 240adcb5308SSeth Heasley { PCI_VDEVICE(INTEL, 0x3b2b), board_ahci }, /* PCH RAID */ 2418e48b6b3SSeth Heasley { PCI_VDEVICE(INTEL, 0x3b2c), board_ahci }, /* PCH RAID */ 242c1f57d9bSDavid Milburn { PCI_VDEVICE(INTEL, 0x3b2f), board_ahci }, /* PCH AHCI */ 2435623cab8SSeth Heasley { PCI_VDEVICE(INTEL, 0x1c02), board_ahci }, /* CPT AHCI */ 2445623cab8SSeth Heasley { PCI_VDEVICE(INTEL, 0x1c03), board_ahci }, /* CPT AHCI */ 2455623cab8SSeth Heasley { PCI_VDEVICE(INTEL, 0x1c04), board_ahci }, /* CPT RAID */ 2465623cab8SSeth Heasley { PCI_VDEVICE(INTEL, 0x1c05), board_ahci }, /* CPT RAID */ 2475623cab8SSeth Heasley { PCI_VDEVICE(INTEL, 0x1c06), board_ahci }, /* CPT RAID */ 2485623cab8SSeth Heasley { PCI_VDEVICE(INTEL, 0x1c07), board_ahci }, /* CPT RAID */ 249992b3fb9SSeth Heasley { PCI_VDEVICE(INTEL, 0x1d02), board_ahci }, /* PBG AHCI */ 250992b3fb9SSeth Heasley { PCI_VDEVICE(INTEL, 0x1d04), board_ahci }, /* PBG RAID */ 251992b3fb9SSeth Heasley { PCI_VDEVICE(INTEL, 0x1d06), board_ahci }, /* PBG RAID */ 25264a3903dSSeth Heasley { PCI_VDEVICE(INTEL, 0x2826), board_ahci }, /* PBG RAID */ 253a4a461a6SSeth Heasley { PCI_VDEVICE(INTEL, 0x2323), board_ahci }, /* DH89xxCC AHCI */ 254181e3ceaSSeth Heasley { PCI_VDEVICE(INTEL, 0x1e02), board_ahci }, /* Panther Point AHCI */ 255181e3ceaSSeth Heasley { PCI_VDEVICE(INTEL, 0x1e03), board_ahci }, /* Panther Point AHCI */ 256181e3ceaSSeth Heasley { PCI_VDEVICE(INTEL, 0x1e04), board_ahci }, /* Panther Point RAID */ 257181e3ceaSSeth Heasley { PCI_VDEVICE(INTEL, 0x1e05), board_ahci }, /* Panther Point RAID */ 258181e3ceaSSeth Heasley { PCI_VDEVICE(INTEL, 0x1e06), board_ahci }, /* Panther Point RAID */ 259181e3ceaSSeth Heasley { PCI_VDEVICE(INTEL, 0x1e07), board_ahci }, /* Panther Point RAID */ 2602cab7a4cSSeth Heasley { PCI_VDEVICE(INTEL, 0x1e0e), board_ahci }, /* Panther Point RAID */ 261ea4ace66SSeth Heasley { PCI_VDEVICE(INTEL, 0x8c02), board_ahci }, /* Lynx Point AHCI */ 262ea4ace66SSeth Heasley { PCI_VDEVICE(INTEL, 0x8c03), board_ahci }, /* Lynx Point AHCI */ 263ea4ace66SSeth Heasley { PCI_VDEVICE(INTEL, 0x8c04), board_ahci }, /* Lynx Point RAID */ 264ea4ace66SSeth Heasley { PCI_VDEVICE(INTEL, 0x8c05), board_ahci }, /* Lynx Point RAID */ 265ea4ace66SSeth Heasley { PCI_VDEVICE(INTEL, 0x8c06), board_ahci }, /* Lynx Point RAID */ 266ea4ace66SSeth Heasley { PCI_VDEVICE(INTEL, 0x8c07), board_ahci }, /* Lynx Point RAID */ 267ea4ace66SSeth Heasley { PCI_VDEVICE(INTEL, 0x8c0e), board_ahci }, /* Lynx Point RAID */ 268ea4ace66SSeth Heasley { PCI_VDEVICE(INTEL, 0x8c0f), board_ahci }, /* Lynx Point RAID */ 26977b12bc9SJames Ralston { PCI_VDEVICE(INTEL, 0x9c02), board_ahci }, /* Lynx Point-LP AHCI */ 27077b12bc9SJames Ralston { PCI_VDEVICE(INTEL, 0x9c03), board_ahci }, /* Lynx Point-LP AHCI */ 27177b12bc9SJames Ralston { PCI_VDEVICE(INTEL, 0x9c04), board_ahci }, /* Lynx Point-LP RAID */ 27277b12bc9SJames Ralston { PCI_VDEVICE(INTEL, 0x9c05), board_ahci }, /* Lynx Point-LP RAID */ 27377b12bc9SJames Ralston { PCI_VDEVICE(INTEL, 0x9c06), board_ahci }, /* Lynx Point-LP RAID */ 27477b12bc9SJames Ralston { PCI_VDEVICE(INTEL, 0x9c07), board_ahci }, /* Lynx Point-LP RAID */ 27577b12bc9SJames Ralston { PCI_VDEVICE(INTEL, 0x9c0e), board_ahci }, /* Lynx Point-LP RAID */ 27677b12bc9SJames Ralston { PCI_VDEVICE(INTEL, 0x9c0f), board_ahci }, /* Lynx Point-LP RAID */ 27729e674ddSSeth Heasley { PCI_VDEVICE(INTEL, 0x1f22), board_ahci }, /* Avoton AHCI */ 27829e674ddSSeth Heasley { PCI_VDEVICE(INTEL, 0x1f23), board_ahci }, /* Avoton AHCI */ 27929e674ddSSeth Heasley { PCI_VDEVICE(INTEL, 0x1f24), board_ahci }, /* Avoton RAID */ 28029e674ddSSeth Heasley { PCI_VDEVICE(INTEL, 0x1f25), board_ahci }, /* Avoton RAID */ 28129e674ddSSeth Heasley { PCI_VDEVICE(INTEL, 0x1f26), board_ahci }, /* Avoton RAID */ 28229e674ddSSeth Heasley { PCI_VDEVICE(INTEL, 0x1f27), board_ahci }, /* Avoton RAID */ 28329e674ddSSeth Heasley { PCI_VDEVICE(INTEL, 0x1f2e), board_ahci }, /* Avoton RAID */ 28429e674ddSSeth Heasley { PCI_VDEVICE(INTEL, 0x1f2f), board_ahci }, /* Avoton RAID */ 28529e674ddSSeth Heasley { PCI_VDEVICE(INTEL, 0x1f32), board_ahci }, /* Avoton AHCI */ 28629e674ddSSeth Heasley { PCI_VDEVICE(INTEL, 0x1f33), board_ahci }, /* Avoton AHCI */ 28729e674ddSSeth Heasley { PCI_VDEVICE(INTEL, 0x1f34), board_ahci }, /* Avoton RAID */ 28829e674ddSSeth Heasley { PCI_VDEVICE(INTEL, 0x1f35), board_ahci }, /* Avoton RAID */ 28929e674ddSSeth Heasley { PCI_VDEVICE(INTEL, 0x1f36), board_ahci }, /* Avoton RAID */ 29029e674ddSSeth Heasley { PCI_VDEVICE(INTEL, 0x1f37), board_ahci }, /* Avoton RAID */ 29129e674ddSSeth Heasley { PCI_VDEVICE(INTEL, 0x1f3e), board_ahci }, /* Avoton RAID */ 29229e674ddSSeth Heasley { PCI_VDEVICE(INTEL, 0x1f3f), board_ahci }, /* Avoton RAID */ 293efda332cSJames Ralston { PCI_VDEVICE(INTEL, 0x2823), board_ahci }, /* Wellsburg RAID */ 294efda332cSJames Ralston { PCI_VDEVICE(INTEL, 0x2827), board_ahci }, /* Wellsburg RAID */ 295151743fdSJames Ralston { PCI_VDEVICE(INTEL, 0x8d02), board_ahci }, /* Wellsburg AHCI */ 296151743fdSJames Ralston { PCI_VDEVICE(INTEL, 0x8d04), board_ahci }, /* Wellsburg RAID */ 297151743fdSJames Ralston { PCI_VDEVICE(INTEL, 0x8d06), board_ahci }, /* Wellsburg RAID */ 298151743fdSJames Ralston { PCI_VDEVICE(INTEL, 0x8d0e), board_ahci }, /* Wellsburg RAID */ 299151743fdSJames Ralston { PCI_VDEVICE(INTEL, 0x8d62), board_ahci }, /* Wellsburg AHCI */ 300151743fdSJames Ralston { PCI_VDEVICE(INTEL, 0x8d64), board_ahci }, /* Wellsburg RAID */ 301151743fdSJames Ralston { PCI_VDEVICE(INTEL, 0x8d66), board_ahci }, /* Wellsburg RAID */ 302151743fdSJames Ralston { PCI_VDEVICE(INTEL, 0x8d6e), board_ahci }, /* Wellsburg RAID */ 3031cfc7df3SSeth Heasley { PCI_VDEVICE(INTEL, 0x23a3), board_ahci }, /* Coleto Creek AHCI */ 3049f961a5fSJames Ralston { PCI_VDEVICE(INTEL, 0x9c83), board_ahci }, /* Wildcat Point-LP AHCI */ 3059f961a5fSJames Ralston { PCI_VDEVICE(INTEL, 0x9c85), board_ahci }, /* Wildcat Point-LP RAID */ 3069f961a5fSJames Ralston { PCI_VDEVICE(INTEL, 0x9c87), board_ahci }, /* Wildcat Point-LP RAID */ 3079f961a5fSJames Ralston { PCI_VDEVICE(INTEL, 0x9c8f), board_ahci }, /* Wildcat Point-LP RAID */ 3081b071a09SJames Ralston { PCI_VDEVICE(INTEL, 0x8c82), board_ahci }, /* 9 Series AHCI */ 3091b071a09SJames Ralston { PCI_VDEVICE(INTEL, 0x8c83), board_ahci }, /* 9 Series AHCI */ 3101b071a09SJames Ralston { PCI_VDEVICE(INTEL, 0x8c84), board_ahci }, /* 9 Series RAID */ 3111b071a09SJames Ralston { PCI_VDEVICE(INTEL, 0x8c85), board_ahci }, /* 9 Series RAID */ 3121b071a09SJames Ralston { PCI_VDEVICE(INTEL, 0x8c86), board_ahci }, /* 9 Series RAID */ 3131b071a09SJames Ralston { PCI_VDEVICE(INTEL, 0x8c87), board_ahci }, /* 9 Series RAID */ 3141b071a09SJames Ralston { PCI_VDEVICE(INTEL, 0x8c8e), board_ahci }, /* 9 Series RAID */ 3151b071a09SJames Ralston { PCI_VDEVICE(INTEL, 0x8c8f), board_ahci }, /* 9 Series RAID */ 316c6fd2807SJeff Garzik 317e34bb370STejun Heo /* JMicron 360/1/3/5/6, match class to avoid IDE function */ 318e34bb370STejun Heo { PCI_VENDOR_ID_JMICRON, PCI_ANY_ID, PCI_ANY_ID, PCI_ANY_ID, 319e34bb370STejun Heo PCI_CLASS_STORAGE_SATA_AHCI, 0xffffff, board_ahci_ign_iferr }, 3201fefb8fdSBen Hutchings /* JMicron 362B and 362C have an AHCI function with IDE class code */ 3211fefb8fdSBen Hutchings { PCI_VDEVICE(JMICRON, 0x2362), board_ahci_ign_iferr }, 3221fefb8fdSBen Hutchings { PCI_VDEVICE(JMICRON, 0x236f), board_ahci_ign_iferr }, 323c6fd2807SJeff Garzik 324c6fd2807SJeff Garzik /* ATI */ 325c65ec1c2SConke Hu { PCI_VDEVICE(ATI, 0x4380), board_ahci_sb600 }, /* ATI SB600 */ 326e39fc8c9SShane Huang { PCI_VDEVICE(ATI, 0x4390), board_ahci_sb700 }, /* ATI SB700/800 */ 327e39fc8c9SShane Huang { PCI_VDEVICE(ATI, 0x4391), board_ahci_sb700 }, /* ATI SB700/800 */ 328e39fc8c9SShane Huang { PCI_VDEVICE(ATI, 0x4392), board_ahci_sb700 }, /* ATI SB700/800 */ 329e39fc8c9SShane Huang { PCI_VDEVICE(ATI, 0x4393), board_ahci_sb700 }, /* ATI SB700/800 */ 330e39fc8c9SShane Huang { PCI_VDEVICE(ATI, 0x4394), board_ahci_sb700 }, /* ATI SB700/800 */ 331e39fc8c9SShane Huang { PCI_VDEVICE(ATI, 0x4395), board_ahci_sb700 }, /* ATI SB700/800 */ 332c6fd2807SJeff Garzik 333e2dd90b1SShane Huang /* AMD */ 3345deab536SShane Huang { PCI_VDEVICE(AMD, 0x7800), board_ahci }, /* AMD Hudson-2 */ 335fafe5c3dSShane Huang { PCI_VDEVICE(AMD, 0x7900), board_ahci }, /* AMD CZ */ 336e2dd90b1SShane Huang /* AMD is using RAID class only for ahci controllers */ 337e2dd90b1SShane Huang { PCI_VENDOR_ID_AMD, PCI_ANY_ID, PCI_ANY_ID, PCI_ANY_ID, 338e2dd90b1SShane Huang PCI_CLASS_STORAGE_RAID << 8, 0xffffff, board_ahci }, 339e2dd90b1SShane Huang 340c6fd2807SJeff Garzik /* VIA */ 34154bb3a94SJeff Garzik { PCI_VDEVICE(VIA, 0x3349), board_ahci_vt8251 }, /* VIA VT8251 */ 342bf335542STejun Heo { PCI_VDEVICE(VIA, 0x6287), board_ahci_vt8251 }, /* VIA VT8251 */ 343c6fd2807SJeff Garzik 344c6fd2807SJeff Garzik /* NVIDIA */ 345e297d99eSTejun Heo { PCI_VDEVICE(NVIDIA, 0x044c), board_ahci_mcp65 }, /* MCP65 */ 346e297d99eSTejun Heo { PCI_VDEVICE(NVIDIA, 0x044d), board_ahci_mcp65 }, /* MCP65 */ 347e297d99eSTejun Heo { PCI_VDEVICE(NVIDIA, 0x044e), board_ahci_mcp65 }, /* MCP65 */ 348e297d99eSTejun Heo { PCI_VDEVICE(NVIDIA, 0x044f), board_ahci_mcp65 }, /* MCP65 */ 349e297d99eSTejun Heo { PCI_VDEVICE(NVIDIA, 0x045c), board_ahci_mcp65 }, /* MCP65 */ 350e297d99eSTejun Heo { PCI_VDEVICE(NVIDIA, 0x045d), board_ahci_mcp65 }, /* MCP65 */ 351e297d99eSTejun Heo { PCI_VDEVICE(NVIDIA, 0x045e), board_ahci_mcp65 }, /* MCP65 */ 352e297d99eSTejun Heo { PCI_VDEVICE(NVIDIA, 0x045f), board_ahci_mcp65 }, /* MCP65 */ 353441577efSTejun Heo { PCI_VDEVICE(NVIDIA, 0x0550), board_ahci_mcp67 }, /* MCP67 */ 354441577efSTejun Heo { PCI_VDEVICE(NVIDIA, 0x0551), board_ahci_mcp67 }, /* MCP67 */ 355441577efSTejun Heo { PCI_VDEVICE(NVIDIA, 0x0552), board_ahci_mcp67 }, /* MCP67 */ 356441577efSTejun Heo { PCI_VDEVICE(NVIDIA, 0x0553), board_ahci_mcp67 }, /* MCP67 */ 357441577efSTejun Heo { PCI_VDEVICE(NVIDIA, 0x0554), board_ahci_mcp67 }, /* MCP67 */ 358441577efSTejun Heo { PCI_VDEVICE(NVIDIA, 0x0555), board_ahci_mcp67 }, /* MCP67 */ 359441577efSTejun Heo { PCI_VDEVICE(NVIDIA, 0x0556), board_ahci_mcp67 }, /* MCP67 */ 360441577efSTejun Heo { PCI_VDEVICE(NVIDIA, 0x0557), board_ahci_mcp67 }, /* MCP67 */ 361441577efSTejun Heo { PCI_VDEVICE(NVIDIA, 0x0558), board_ahci_mcp67 }, /* MCP67 */ 362441577efSTejun Heo { PCI_VDEVICE(NVIDIA, 0x0559), board_ahci_mcp67 }, /* MCP67 */ 363441577efSTejun Heo { PCI_VDEVICE(NVIDIA, 0x055a), board_ahci_mcp67 }, /* MCP67 */ 364441577efSTejun Heo { PCI_VDEVICE(NVIDIA, 0x055b), board_ahci_mcp67 }, /* MCP67 */ 365441577efSTejun Heo { PCI_VDEVICE(NVIDIA, 0x0580), board_ahci_mcp_linux }, /* Linux ID */ 366441577efSTejun Heo { PCI_VDEVICE(NVIDIA, 0x0581), board_ahci_mcp_linux }, /* Linux ID */ 367441577efSTejun Heo { PCI_VDEVICE(NVIDIA, 0x0582), board_ahci_mcp_linux }, /* Linux ID */ 368441577efSTejun Heo { PCI_VDEVICE(NVIDIA, 0x0583), board_ahci_mcp_linux }, /* Linux ID */ 369441577efSTejun Heo { PCI_VDEVICE(NVIDIA, 0x0584), board_ahci_mcp_linux }, /* Linux ID */ 370441577efSTejun Heo { PCI_VDEVICE(NVIDIA, 0x0585), board_ahci_mcp_linux }, /* Linux ID */ 371441577efSTejun Heo { PCI_VDEVICE(NVIDIA, 0x0586), board_ahci_mcp_linux }, /* Linux ID */ 372441577efSTejun Heo { PCI_VDEVICE(NVIDIA, 0x0587), board_ahci_mcp_linux }, /* Linux ID */ 373441577efSTejun Heo { PCI_VDEVICE(NVIDIA, 0x0588), board_ahci_mcp_linux }, /* Linux ID */ 374441577efSTejun Heo { PCI_VDEVICE(NVIDIA, 0x0589), board_ahci_mcp_linux }, /* Linux ID */ 375441577efSTejun Heo { PCI_VDEVICE(NVIDIA, 0x058a), board_ahci_mcp_linux }, /* Linux ID */ 376441577efSTejun Heo { PCI_VDEVICE(NVIDIA, 0x058b), board_ahci_mcp_linux }, /* Linux ID */ 377441577efSTejun Heo { PCI_VDEVICE(NVIDIA, 0x058c), board_ahci_mcp_linux }, /* Linux ID */ 378441577efSTejun Heo { PCI_VDEVICE(NVIDIA, 0x058d), board_ahci_mcp_linux }, /* Linux ID */ 379441577efSTejun Heo { PCI_VDEVICE(NVIDIA, 0x058e), board_ahci_mcp_linux }, /* Linux ID */ 380441577efSTejun Heo { PCI_VDEVICE(NVIDIA, 0x058f), board_ahci_mcp_linux }, /* Linux ID */ 381441577efSTejun Heo { PCI_VDEVICE(NVIDIA, 0x07f0), board_ahci_mcp73 }, /* MCP73 */ 382441577efSTejun Heo { PCI_VDEVICE(NVIDIA, 0x07f1), board_ahci_mcp73 }, /* MCP73 */ 383441577efSTejun Heo { PCI_VDEVICE(NVIDIA, 0x07f2), board_ahci_mcp73 }, /* MCP73 */ 384441577efSTejun Heo { PCI_VDEVICE(NVIDIA, 0x07f3), board_ahci_mcp73 }, /* MCP73 */ 385441577efSTejun Heo { PCI_VDEVICE(NVIDIA, 0x07f4), board_ahci_mcp73 }, /* MCP73 */ 386441577efSTejun Heo { PCI_VDEVICE(NVIDIA, 0x07f5), board_ahci_mcp73 }, /* MCP73 */ 387441577efSTejun Heo { PCI_VDEVICE(NVIDIA, 0x07f6), board_ahci_mcp73 }, /* MCP73 */ 388441577efSTejun Heo { PCI_VDEVICE(NVIDIA, 0x07f7), board_ahci_mcp73 }, /* MCP73 */ 389441577efSTejun Heo { PCI_VDEVICE(NVIDIA, 0x07f8), board_ahci_mcp73 }, /* MCP73 */ 390441577efSTejun Heo { PCI_VDEVICE(NVIDIA, 0x07f9), board_ahci_mcp73 }, /* MCP73 */ 391441577efSTejun Heo { PCI_VDEVICE(NVIDIA, 0x07fa), board_ahci_mcp73 }, /* MCP73 */ 392441577efSTejun Heo { PCI_VDEVICE(NVIDIA, 0x07fb), board_ahci_mcp73 }, /* MCP73 */ 393441577efSTejun Heo { PCI_VDEVICE(NVIDIA, 0x0ad0), board_ahci_mcp77 }, /* MCP77 */ 394441577efSTejun Heo { PCI_VDEVICE(NVIDIA, 0x0ad1), board_ahci_mcp77 }, /* MCP77 */ 395441577efSTejun Heo { PCI_VDEVICE(NVIDIA, 0x0ad2), board_ahci_mcp77 }, /* MCP77 */ 396441577efSTejun Heo { PCI_VDEVICE(NVIDIA, 0x0ad3), board_ahci_mcp77 }, /* MCP77 */ 397441577efSTejun Heo { PCI_VDEVICE(NVIDIA, 0x0ad4), board_ahci_mcp77 }, /* MCP77 */ 398441577efSTejun Heo { PCI_VDEVICE(NVIDIA, 0x0ad5), board_ahci_mcp77 }, /* MCP77 */ 399441577efSTejun Heo { PCI_VDEVICE(NVIDIA, 0x0ad6), board_ahci_mcp77 }, /* MCP77 */ 400441577efSTejun Heo { PCI_VDEVICE(NVIDIA, 0x0ad7), board_ahci_mcp77 }, /* MCP77 */ 401441577efSTejun Heo { PCI_VDEVICE(NVIDIA, 0x0ad8), board_ahci_mcp77 }, /* MCP77 */ 402441577efSTejun Heo { PCI_VDEVICE(NVIDIA, 0x0ad9), board_ahci_mcp77 }, /* MCP77 */ 403441577efSTejun Heo { PCI_VDEVICE(NVIDIA, 0x0ada), board_ahci_mcp77 }, /* MCP77 */ 404441577efSTejun Heo { PCI_VDEVICE(NVIDIA, 0x0adb), board_ahci_mcp77 }, /* MCP77 */ 405441577efSTejun Heo { PCI_VDEVICE(NVIDIA, 0x0ab4), board_ahci_mcp79 }, /* MCP79 */ 406441577efSTejun Heo { PCI_VDEVICE(NVIDIA, 0x0ab5), board_ahci_mcp79 }, /* MCP79 */ 407441577efSTejun Heo { PCI_VDEVICE(NVIDIA, 0x0ab6), board_ahci_mcp79 }, /* MCP79 */ 408441577efSTejun Heo { PCI_VDEVICE(NVIDIA, 0x0ab7), board_ahci_mcp79 }, /* MCP79 */ 409441577efSTejun Heo { PCI_VDEVICE(NVIDIA, 0x0ab8), board_ahci_mcp79 }, /* MCP79 */ 410441577efSTejun Heo { PCI_VDEVICE(NVIDIA, 0x0ab9), board_ahci_mcp79 }, /* MCP79 */ 411441577efSTejun Heo { PCI_VDEVICE(NVIDIA, 0x0aba), board_ahci_mcp79 }, /* MCP79 */ 412441577efSTejun Heo { PCI_VDEVICE(NVIDIA, 0x0abb), board_ahci_mcp79 }, /* MCP79 */ 413441577efSTejun Heo { PCI_VDEVICE(NVIDIA, 0x0abc), board_ahci_mcp79 }, /* MCP79 */ 414441577efSTejun Heo { PCI_VDEVICE(NVIDIA, 0x0abd), board_ahci_mcp79 }, /* MCP79 */ 415441577efSTejun Heo { PCI_VDEVICE(NVIDIA, 0x0abe), board_ahci_mcp79 }, /* MCP79 */ 416441577efSTejun Heo { PCI_VDEVICE(NVIDIA, 0x0abf), board_ahci_mcp79 }, /* MCP79 */ 417441577efSTejun Heo { PCI_VDEVICE(NVIDIA, 0x0d84), board_ahci_mcp89 }, /* MCP89 */ 418441577efSTejun Heo { PCI_VDEVICE(NVIDIA, 0x0d85), board_ahci_mcp89 }, /* MCP89 */ 419441577efSTejun Heo { PCI_VDEVICE(NVIDIA, 0x0d86), board_ahci_mcp89 }, /* MCP89 */ 420441577efSTejun Heo { PCI_VDEVICE(NVIDIA, 0x0d87), board_ahci_mcp89 }, /* MCP89 */ 421441577efSTejun Heo { PCI_VDEVICE(NVIDIA, 0x0d88), board_ahci_mcp89 }, /* MCP89 */ 422441577efSTejun Heo { PCI_VDEVICE(NVIDIA, 0x0d89), board_ahci_mcp89 }, /* MCP89 */ 423441577efSTejun Heo { PCI_VDEVICE(NVIDIA, 0x0d8a), board_ahci_mcp89 }, /* MCP89 */ 424441577efSTejun Heo { PCI_VDEVICE(NVIDIA, 0x0d8b), board_ahci_mcp89 }, /* MCP89 */ 425441577efSTejun Heo { PCI_VDEVICE(NVIDIA, 0x0d8c), board_ahci_mcp89 }, /* MCP89 */ 426441577efSTejun Heo { PCI_VDEVICE(NVIDIA, 0x0d8d), board_ahci_mcp89 }, /* MCP89 */ 427441577efSTejun Heo { PCI_VDEVICE(NVIDIA, 0x0d8e), board_ahci_mcp89 }, /* MCP89 */ 428441577efSTejun Heo { PCI_VDEVICE(NVIDIA, 0x0d8f), board_ahci_mcp89 }, /* MCP89 */ 429c6fd2807SJeff Garzik 430c6fd2807SJeff Garzik /* SiS */ 43120e2de4aSTejun Heo { PCI_VDEVICE(SI, 0x1184), board_ahci }, /* SiS 966 */ 43220e2de4aSTejun Heo { PCI_VDEVICE(SI, 0x1185), board_ahci }, /* SiS 968 */ 43320e2de4aSTejun Heo { PCI_VDEVICE(SI, 0x0186), board_ahci }, /* SiS 968 */ 434c6fd2807SJeff Garzik 435318893e1SAlessandro Rubini /* ST Microelectronics */ 436318893e1SAlessandro Rubini { PCI_VDEVICE(STMICRO, 0xCC06), board_ahci }, /* ST ConneXt */ 437318893e1SAlessandro Rubini 438cd70c266SJeff Garzik /* Marvell */ 439cd70c266SJeff Garzik { PCI_VDEVICE(MARVELL, 0x6145), board_ahci_mv }, /* 6145 */ 440c40e7cb8SJose Alberto Reguero { PCI_VDEVICE(MARVELL, 0x6121), board_ahci_mv }, /* 6121 */ 44169fd3157SMyron Stowe { PCI_DEVICE(PCI_VENDOR_ID_MARVELL_EXT, 0x9123), 44210aca06cSAnssi Hannula .class = PCI_CLASS_STORAGE_SATA_AHCI, 44310aca06cSAnssi Hannula .class_mask = 0xffffff, 4445f173107STejun Heo .driver_data = board_ahci_yes_fbs }, /* 88se9128 */ 44569fd3157SMyron Stowe { PCI_DEVICE(PCI_VENDOR_ID_MARVELL_EXT, 0x9125), 446467b41c6SPer Jessen .driver_data = board_ahci_yes_fbs }, /* 88se9125 */ 447e098f5cbSSimon Guinot { PCI_DEVICE_SUB(PCI_VENDOR_ID_MARVELL_EXT, 0x9178, 448e098f5cbSSimon Guinot PCI_VENDOR_ID_MARVELL_EXT, 0x9170), 449e098f5cbSSimon Guinot .driver_data = board_ahci_yes_fbs }, /* 88se9170 */ 45069fd3157SMyron Stowe { PCI_DEVICE(PCI_VENDOR_ID_MARVELL_EXT, 0x917a), 451642d8925SMatt Johnson .driver_data = board_ahci_yes_fbs }, /* 88se9172 */ 452fcce9a35SGeorge Spelvin { PCI_DEVICE(PCI_VENDOR_ID_MARVELL_EXT, 0x9172), 453*c5edfff9SMurali Karicheri .driver_data = board_ahci_yes_fbs }, /* 88se9182 */ 454*c5edfff9SMurali Karicheri { PCI_DEVICE(PCI_VENDOR_ID_MARVELL_EXT, 0x9182), 455fcce9a35SGeorge Spelvin .driver_data = board_ahci_yes_fbs }, /* 88se9172 */ 45669fd3157SMyron Stowe { PCI_DEVICE(PCI_VENDOR_ID_MARVELL_EXT, 0x9192), 45717c60c6bSAlan Cox .driver_data = board_ahci_yes_fbs }, /* 88se9172 on some Gigabyte */ 458754a292fSAndreas Schrägle { PCI_DEVICE(PCI_VENDOR_ID_MARVELL_EXT, 0x91a0), 459754a292fSAndreas Schrägle .driver_data = board_ahci_yes_fbs }, 46069fd3157SMyron Stowe { PCI_DEVICE(PCI_VENDOR_ID_MARVELL_EXT, 0x91a3), 46150be5e36STejun Heo .driver_data = board_ahci_yes_fbs }, 4626d5278a6SSamir Benmendil { PCI_DEVICE(PCI_VENDOR_ID_MARVELL_EXT, 0x9230), 4636d5278a6SSamir Benmendil .driver_data = board_ahci_yes_fbs }, 464d2518365SJérôme Carretero { PCI_DEVICE(PCI_VENDOR_ID_TTI, 0x0642), 465d2518365SJérôme Carretero .driver_data = board_ahci_yes_fbs }, 466cd70c266SJeff Garzik 467c77a036bSMark Nelson /* Promise */ 468c77a036bSMark Nelson { PCI_VDEVICE(PROMISE, 0x3f20), board_ahci }, /* PDC42819 */ 469b32bfc06SRomain Degez { PCI_VDEVICE(PROMISE, 0x3781), board_ahci }, /* FastTrak TX8660 ahci-mode */ 470c77a036bSMark Nelson 471c9703765SKeng-Yu Lin /* Asmedia */ 4727b4f6ecaSAlan Cox { PCI_VDEVICE(ASMEDIA, 0x0601), board_ahci }, /* ASM1060 */ 4737b4f6ecaSAlan Cox { PCI_VDEVICE(ASMEDIA, 0x0602), board_ahci }, /* ASM1060 */ 4747b4f6ecaSAlan Cox { PCI_VDEVICE(ASMEDIA, 0x0611), board_ahci }, /* ASM1061 */ 4757b4f6ecaSAlan Cox { PCI_VDEVICE(ASMEDIA, 0x0612), board_ahci }, /* ASM1062 */ 476c9703765SKeng-Yu Lin 47767809f85SLevente Kurusa /* 47867809f85SLevente Kurusa * Samsung SSDs found on some macbooks. NCQ times out. 47967809f85SLevente Kurusa * https://bugzilla.kernel.org/show_bug.cgi?id=60731 48067809f85SLevente Kurusa */ 48167809f85SLevente Kurusa { PCI_VDEVICE(SAMSUNG, 0x1600), board_ahci_noncq }, 48267809f85SLevente Kurusa 4837f9c9f8eSHugh Daschbach /* Enmotus */ 4847f9c9f8eSHugh Daschbach { PCI_DEVICE(0x1c44, 0x8000), board_ahci }, 4857f9c9f8eSHugh Daschbach 486415ae2b5SJeff Garzik /* Generic, PCI class code for AHCI */ 487415ae2b5SJeff Garzik { PCI_ANY_ID, PCI_ANY_ID, PCI_ANY_ID, PCI_ANY_ID, 488c9f89475SConke Hu PCI_CLASS_STORAGE_SATA_AHCI, 0xffffff, board_ahci }, 489415ae2b5SJeff Garzik 490c6fd2807SJeff Garzik { } /* terminate list */ 491c6fd2807SJeff Garzik }; 492c6fd2807SJeff Garzik 493c6fd2807SJeff Garzik 494c6fd2807SJeff Garzik static struct pci_driver ahci_pci_driver = { 495c6fd2807SJeff Garzik .name = DRV_NAME, 496c6fd2807SJeff Garzik .id_table = ahci_pci_tbl, 497c6fd2807SJeff Garzik .probe = ahci_init_one, 49824dc5f33STejun Heo .remove = ata_pci_remove_one, 499438ac6d5STejun Heo #ifdef CONFIG_PM 500c6fd2807SJeff Garzik .suspend = ahci_pci_device_suspend, 501c6fd2807SJeff Garzik .resume = ahci_pci_device_resume, 502438ac6d5STejun Heo #endif 503c6fd2807SJeff Garzik }; 504c6fd2807SJeff Garzik 5055b66c829SAlan Cox #if defined(CONFIG_PATA_MARVELL) || defined(CONFIG_PATA_MARVELL_MODULE) 5065b66c829SAlan Cox static int marvell_enable; 5075b66c829SAlan Cox #else 5085b66c829SAlan Cox static int marvell_enable = 1; 5095b66c829SAlan Cox #endif 5105b66c829SAlan Cox module_param(marvell_enable, int, 0644); 5115b66c829SAlan Cox MODULE_PARM_DESC(marvell_enable, "Marvell SATA via AHCI (1 = enabled)"); 5125b66c829SAlan Cox 5135b66c829SAlan Cox 514394d6e53SAnton Vorontsov static void ahci_pci_save_initial_config(struct pci_dev *pdev, 515394d6e53SAnton Vorontsov struct ahci_host_priv *hpriv) 516394d6e53SAnton Vorontsov { 517394d6e53SAnton Vorontsov unsigned int force_port_map = 0; 518394d6e53SAnton Vorontsov unsigned int mask_port_map = 0; 519394d6e53SAnton Vorontsov 520394d6e53SAnton Vorontsov if (pdev->vendor == PCI_VENDOR_ID_JMICRON && pdev->device == 0x2361) { 521394d6e53SAnton Vorontsov dev_info(&pdev->dev, "JMB361 has only one port\n"); 522394d6e53SAnton Vorontsov force_port_map = 1; 523394d6e53SAnton Vorontsov } 524394d6e53SAnton Vorontsov 525394d6e53SAnton Vorontsov /* 526394d6e53SAnton Vorontsov * Temporary Marvell 6145 hack: PATA port presence 527394d6e53SAnton Vorontsov * is asserted through the standard AHCI port 528394d6e53SAnton Vorontsov * presence register, as bit 4 (counting from 0) 529394d6e53SAnton Vorontsov */ 530394d6e53SAnton Vorontsov if (hpriv->flags & AHCI_HFLAG_MV_PATA) { 531394d6e53SAnton Vorontsov if (pdev->device == 0x6121) 532394d6e53SAnton Vorontsov mask_port_map = 0x3; 533394d6e53SAnton Vorontsov else 534394d6e53SAnton Vorontsov mask_port_map = 0xf; 535394d6e53SAnton Vorontsov dev_info(&pdev->dev, 536394d6e53SAnton Vorontsov "Disabling your PATA port. Use the boot option 'ahci.marvell_enable=0' to avoid this.\n"); 537394d6e53SAnton Vorontsov } 538394d6e53SAnton Vorontsov 539725c7b57SAntoine Ténart ahci_save_initial_config(&pdev->dev, hpriv); 540394d6e53SAnton Vorontsov } 541394d6e53SAnton Vorontsov 5423303040dSAnton Vorontsov static int ahci_pci_reset_controller(struct ata_host *host) 5433303040dSAnton Vorontsov { 5443303040dSAnton Vorontsov struct pci_dev *pdev = to_pci_dev(host->dev); 5453303040dSAnton Vorontsov 5463303040dSAnton Vorontsov ahci_reset_controller(host); 5473303040dSAnton Vorontsov 548c6fd2807SJeff Garzik if (pdev->vendor == PCI_VENDOR_ID_INTEL) { 5493303040dSAnton Vorontsov struct ahci_host_priv *hpriv = host->private_data; 550c6fd2807SJeff Garzik u16 tmp16; 551c6fd2807SJeff Garzik 552c6fd2807SJeff Garzik /* configure PCS */ 553c6fd2807SJeff Garzik pci_read_config_word(pdev, 0x92, &tmp16); 55449f29090STejun Heo if ((tmp16 & hpriv->port_map) != hpriv->port_map) { 55549f29090STejun Heo tmp16 |= hpriv->port_map; 556c6fd2807SJeff Garzik pci_write_config_word(pdev, 0x92, tmp16); 557c6fd2807SJeff Garzik } 55849f29090STejun Heo } 559c6fd2807SJeff Garzik 560c6fd2807SJeff Garzik return 0; 561c6fd2807SJeff Garzik } 562c6fd2807SJeff Garzik 563781d6550SAnton Vorontsov static void ahci_pci_init_controller(struct ata_host *host) 564781d6550SAnton Vorontsov { 565781d6550SAnton Vorontsov struct ahci_host_priv *hpriv = host->private_data; 566781d6550SAnton Vorontsov struct pci_dev *pdev = to_pci_dev(host->dev); 567781d6550SAnton Vorontsov void __iomem *port_mmio; 568781d6550SAnton Vorontsov u32 tmp; 569c40e7cb8SJose Alberto Reguero int mv; 5702bcd866bSJeff Garzik 571417a1a6dSTejun Heo if (hpriv->flags & AHCI_HFLAG_MV_PATA) { 572c40e7cb8SJose Alberto Reguero if (pdev->device == 0x6121) 573c40e7cb8SJose Alberto Reguero mv = 2; 574c40e7cb8SJose Alberto Reguero else 575c40e7cb8SJose Alberto Reguero mv = 4; 576c40e7cb8SJose Alberto Reguero port_mmio = __ahci_port_base(host, mv); 577cd70c266SJeff Garzik 578cd70c266SJeff Garzik writel(0, port_mmio + PORT_IRQ_MASK); 579cd70c266SJeff Garzik 580cd70c266SJeff Garzik /* clear port IRQ */ 581cd70c266SJeff Garzik tmp = readl(port_mmio + PORT_IRQ_STAT); 582cd70c266SJeff Garzik VPRINTK("PORT_IRQ_STAT 0x%x\n", tmp); 583cd70c266SJeff Garzik if (tmp) 584cd70c266SJeff Garzik writel(tmp, port_mmio + PORT_IRQ_STAT); 585cd70c266SJeff Garzik } 586cd70c266SJeff Garzik 587781d6550SAnton Vorontsov ahci_init_controller(host); 588c6fd2807SJeff Garzik } 589c6fd2807SJeff Garzik 590cc0680a5STejun Heo static int ahci_vt8251_hardreset(struct ata_link *link, unsigned int *class, 591d4b2bab4STejun Heo unsigned long deadline) 592ad616ffbSTejun Heo { 593cc0680a5STejun Heo struct ata_port *ap = link->ap; 594039ece38SHans de Goede struct ahci_host_priv *hpriv = ap->host->private_data; 5959dadd45bSTejun Heo bool online; 596ad616ffbSTejun Heo int rc; 597ad616ffbSTejun Heo 598ad616ffbSTejun Heo DPRINTK("ENTER\n"); 599ad616ffbSTejun Heo 6004447d351STejun Heo ahci_stop_engine(ap); 601ad616ffbSTejun Heo 602cc0680a5STejun Heo rc = sata_link_hardreset(link, sata_ehc_deb_timing(&link->eh_context), 6039dadd45bSTejun Heo deadline, &online, NULL); 604ad616ffbSTejun Heo 605039ece38SHans de Goede hpriv->start_engine(ap); 606ad616ffbSTejun Heo 607ad616ffbSTejun Heo DPRINTK("EXIT, rc=%d, class=%u\n", rc, *class); 608ad616ffbSTejun Heo 609ad616ffbSTejun Heo /* vt8251 doesn't clear BSY on signature FIS reception, 610ad616ffbSTejun Heo * request follow-up softreset. 611ad616ffbSTejun Heo */ 6129dadd45bSTejun Heo return online ? -EAGAIN : rc; 613ad616ffbSTejun Heo } 614ad616ffbSTejun Heo 615edc93052STejun Heo static int ahci_p5wdh_hardreset(struct ata_link *link, unsigned int *class, 616edc93052STejun Heo unsigned long deadline) 617edc93052STejun Heo { 618edc93052STejun Heo struct ata_port *ap = link->ap; 619edc93052STejun Heo struct ahci_port_priv *pp = ap->private_data; 620039ece38SHans de Goede struct ahci_host_priv *hpriv = ap->host->private_data; 621edc93052STejun Heo u8 *d2h_fis = pp->rx_fis + RX_FIS_D2H_REG; 622edc93052STejun Heo struct ata_taskfile tf; 6239dadd45bSTejun Heo bool online; 624edc93052STejun Heo int rc; 625edc93052STejun Heo 626edc93052STejun Heo ahci_stop_engine(ap); 627edc93052STejun Heo 628edc93052STejun Heo /* clear D2H reception area to properly wait for D2H FIS */ 629edc93052STejun Heo ata_tf_init(link->device, &tf); 6309bbb1b0eSSergei Shtylyov tf.command = ATA_BUSY; 631edc93052STejun Heo ata_tf_to_fis(&tf, 0, 0, d2h_fis); 632edc93052STejun Heo 633edc93052STejun Heo rc = sata_link_hardreset(link, sata_ehc_deb_timing(&link->eh_context), 6349dadd45bSTejun Heo deadline, &online, NULL); 635edc93052STejun Heo 636039ece38SHans de Goede hpriv->start_engine(ap); 637edc93052STejun Heo 638edc93052STejun Heo /* The pseudo configuration device on SIMG4726 attached to 639edc93052STejun Heo * ASUS P5W-DH Deluxe doesn't send signature FIS after 640edc93052STejun Heo * hardreset if no device is attached to the first downstream 641edc93052STejun Heo * port && the pseudo device locks up on SRST w/ PMP==0. To 642edc93052STejun Heo * work around this, wait for !BSY only briefly. If BSY isn't 643edc93052STejun Heo * cleared, perform CLO and proceed to IDENTIFY (achieved by 644edc93052STejun Heo * ATA_LFLAG_NO_SRST and ATA_LFLAG_ASSUME_ATA). 645edc93052STejun Heo * 646edc93052STejun Heo * Wait for two seconds. Devices attached to downstream port 647edc93052STejun Heo * which can't process the following IDENTIFY after this will 648edc93052STejun Heo * have to be reset again. For most cases, this should 649edc93052STejun Heo * suffice while making probing snappish enough. 650edc93052STejun Heo */ 6519dadd45bSTejun Heo if (online) { 6529dadd45bSTejun Heo rc = ata_wait_after_reset(link, jiffies + 2 * HZ, 6539dadd45bSTejun Heo ahci_check_ready); 654edc93052STejun Heo if (rc) 65578d5ae39SShane Huang ahci_kick_engine(ap); 6569dadd45bSTejun Heo } 6579dadd45bSTejun Heo return rc; 658edc93052STejun Heo } 659edc93052STejun Heo 660438ac6d5STejun Heo #ifdef CONFIG_PM 661c6fd2807SJeff Garzik static int ahci_pci_device_suspend(struct pci_dev *pdev, pm_message_t mesg) 662c6fd2807SJeff Garzik { 6630a86e1c8SJingoo Han struct ata_host *host = pci_get_drvdata(pdev); 6649b10ae86STejun Heo struct ahci_host_priv *hpriv = host->private_data; 665d8993349SAnton Vorontsov void __iomem *mmio = hpriv->mmio; 666c6fd2807SJeff Garzik u32 ctl; 667c6fd2807SJeff Garzik 6689b10ae86STejun Heo if (mesg.event & PM_EVENT_SUSPEND && 6699b10ae86STejun Heo hpriv->flags & AHCI_HFLAG_NO_SUSPEND) { 670a44fec1fSJoe Perches dev_err(&pdev->dev, 6719b10ae86STejun Heo "BIOS update required for suspend/resume\n"); 6729b10ae86STejun Heo return -EIO; 6739b10ae86STejun Heo } 6749b10ae86STejun Heo 6753a2d5b70SRafael J. Wysocki if (mesg.event & PM_EVENT_SLEEP) { 676c6fd2807SJeff Garzik /* AHCI spec rev1.1 section 8.3.3: 677c6fd2807SJeff Garzik * Software must disable interrupts prior to requesting a 678c6fd2807SJeff Garzik * transition of the HBA to D3 state. 679c6fd2807SJeff Garzik */ 680c6fd2807SJeff Garzik ctl = readl(mmio + HOST_CTL); 681c6fd2807SJeff Garzik ctl &= ~HOST_IRQ_EN; 682c6fd2807SJeff Garzik writel(ctl, mmio + HOST_CTL); 683c6fd2807SJeff Garzik readl(mmio + HOST_CTL); /* flush */ 684c6fd2807SJeff Garzik } 685c6fd2807SJeff Garzik 686c6fd2807SJeff Garzik return ata_pci_device_suspend(pdev, mesg); 687c6fd2807SJeff Garzik } 688c6fd2807SJeff Garzik 689c6fd2807SJeff Garzik static int ahci_pci_device_resume(struct pci_dev *pdev) 690c6fd2807SJeff Garzik { 6910a86e1c8SJingoo Han struct ata_host *host = pci_get_drvdata(pdev); 692c6fd2807SJeff Garzik int rc; 693c6fd2807SJeff Garzik 694553c4aa6STejun Heo rc = ata_pci_device_do_resume(pdev); 695553c4aa6STejun Heo if (rc) 696553c4aa6STejun Heo return rc; 697c6fd2807SJeff Garzik 698cb85696dSJames Laird /* Apple BIOS helpfully mangles the registers on resume */ 699cb85696dSJames Laird if (is_mcp89_apple(pdev)) 700cb85696dSJames Laird ahci_mcp89_apple_enable(pdev); 701cb85696dSJames Laird 702c6fd2807SJeff Garzik if (pdev->dev.power.power_state.event == PM_EVENT_SUSPEND) { 7033303040dSAnton Vorontsov rc = ahci_pci_reset_controller(host); 704c6fd2807SJeff Garzik if (rc) 705c6fd2807SJeff Garzik return rc; 706c6fd2807SJeff Garzik 707781d6550SAnton Vorontsov ahci_pci_init_controller(host); 708c6fd2807SJeff Garzik } 709c6fd2807SJeff Garzik 710cca3974eSJeff Garzik ata_host_resume(host); 711c6fd2807SJeff Garzik 712c6fd2807SJeff Garzik return 0; 713c6fd2807SJeff Garzik } 714438ac6d5STejun Heo #endif 715c6fd2807SJeff Garzik 7164447d351STejun Heo static int ahci_configure_dma_masks(struct pci_dev *pdev, int using_dac) 717c6fd2807SJeff Garzik { 718c6fd2807SJeff Garzik int rc; 719c6fd2807SJeff Garzik 720318893e1SAlessandro Rubini /* 721318893e1SAlessandro Rubini * If the device fixup already set the dma_mask to some non-standard 722318893e1SAlessandro Rubini * value, don't extend it here. This happens on STA2X11, for example. 723318893e1SAlessandro Rubini */ 724318893e1SAlessandro Rubini if (pdev->dma_mask && pdev->dma_mask < DMA_BIT_MASK(32)) 725318893e1SAlessandro Rubini return 0; 726318893e1SAlessandro Rubini 727c6fd2807SJeff Garzik if (using_dac && 7286a35528aSYang Hongyang !pci_set_dma_mask(pdev, DMA_BIT_MASK(64))) { 7296a35528aSYang Hongyang rc = pci_set_consistent_dma_mask(pdev, DMA_BIT_MASK(64)); 730c6fd2807SJeff Garzik if (rc) { 731284901a9SYang Hongyang rc = pci_set_consistent_dma_mask(pdev, DMA_BIT_MASK(32)); 732c6fd2807SJeff Garzik if (rc) { 733a44fec1fSJoe Perches dev_err(&pdev->dev, 734c6fd2807SJeff Garzik "64-bit DMA enable failed\n"); 735c6fd2807SJeff Garzik return rc; 736c6fd2807SJeff Garzik } 737c6fd2807SJeff Garzik } 738c6fd2807SJeff Garzik } else { 739284901a9SYang Hongyang rc = pci_set_dma_mask(pdev, DMA_BIT_MASK(32)); 740c6fd2807SJeff Garzik if (rc) { 741a44fec1fSJoe Perches dev_err(&pdev->dev, "32-bit DMA enable failed\n"); 742c6fd2807SJeff Garzik return rc; 743c6fd2807SJeff Garzik } 744284901a9SYang Hongyang rc = pci_set_consistent_dma_mask(pdev, DMA_BIT_MASK(32)); 745c6fd2807SJeff Garzik if (rc) { 746a44fec1fSJoe Perches dev_err(&pdev->dev, 747c6fd2807SJeff Garzik "32-bit consistent DMA enable failed\n"); 748c6fd2807SJeff Garzik return rc; 749c6fd2807SJeff Garzik } 750c6fd2807SJeff Garzik } 751c6fd2807SJeff Garzik return 0; 752c6fd2807SJeff Garzik } 753c6fd2807SJeff Garzik 754439fcaecSAnton Vorontsov static void ahci_pci_print_info(struct ata_host *host) 755439fcaecSAnton Vorontsov { 756439fcaecSAnton Vorontsov struct pci_dev *pdev = to_pci_dev(host->dev); 757439fcaecSAnton Vorontsov u16 cc; 758439fcaecSAnton Vorontsov const char *scc_s; 759439fcaecSAnton Vorontsov 760439fcaecSAnton Vorontsov pci_read_config_word(pdev, 0x0a, &cc); 761439fcaecSAnton Vorontsov if (cc == PCI_CLASS_STORAGE_IDE) 762439fcaecSAnton Vorontsov scc_s = "IDE"; 763439fcaecSAnton Vorontsov else if (cc == PCI_CLASS_STORAGE_SATA) 764439fcaecSAnton Vorontsov scc_s = "SATA"; 765439fcaecSAnton Vorontsov else if (cc == PCI_CLASS_STORAGE_RAID) 766439fcaecSAnton Vorontsov scc_s = "RAID"; 767439fcaecSAnton Vorontsov else 768439fcaecSAnton Vorontsov scc_s = "unknown"; 769439fcaecSAnton Vorontsov 770439fcaecSAnton Vorontsov ahci_print_info(host, scc_s); 771439fcaecSAnton Vorontsov } 772439fcaecSAnton Vorontsov 773edc93052STejun Heo /* On ASUS P5W DH Deluxe, the second port of PCI device 00:1f.2 is 774edc93052STejun Heo * hardwired to on-board SIMG 4726. The chipset is ICH8 and doesn't 775edc93052STejun Heo * support PMP and the 4726 either directly exports the device 776edc93052STejun Heo * attached to the first downstream port or acts as a hardware storage 777edc93052STejun Heo * controller and emulate a single ATA device (can be RAID 0/1 or some 778edc93052STejun Heo * other configuration). 779edc93052STejun Heo * 780edc93052STejun Heo * When there's no device attached to the first downstream port of the 781edc93052STejun Heo * 4726, "Config Disk" appears, which is a pseudo ATA device to 782edc93052STejun Heo * configure the 4726. However, ATA emulation of the device is very 783edc93052STejun Heo * lame. It doesn't send signature D2H Reg FIS after the initial 784edc93052STejun Heo * hardreset, pukes on SRST w/ PMP==0 and has bunch of other issues. 785edc93052STejun Heo * 786edc93052STejun Heo * The following function works around the problem by always using 787edc93052STejun Heo * hardreset on the port and not depending on receiving signature FIS 788edc93052STejun Heo * afterward. If signature FIS isn't received soon, ATA class is 789edc93052STejun Heo * assumed without follow-up softreset. 790edc93052STejun Heo */ 791edc93052STejun Heo static void ahci_p5wdh_workaround(struct ata_host *host) 792edc93052STejun Heo { 793edc93052STejun Heo static struct dmi_system_id sysids[] = { 794edc93052STejun Heo { 795edc93052STejun Heo .ident = "P5W DH Deluxe", 796edc93052STejun Heo .matches = { 797edc93052STejun Heo DMI_MATCH(DMI_SYS_VENDOR, 798edc93052STejun Heo "ASUSTEK COMPUTER INC"), 799edc93052STejun Heo DMI_MATCH(DMI_PRODUCT_NAME, "P5W DH Deluxe"), 800edc93052STejun Heo }, 801edc93052STejun Heo }, 802edc93052STejun Heo { } 803edc93052STejun Heo }; 804edc93052STejun Heo struct pci_dev *pdev = to_pci_dev(host->dev); 805edc93052STejun Heo 806edc93052STejun Heo if (pdev->bus->number == 0 && pdev->devfn == PCI_DEVFN(0x1f, 2) && 807edc93052STejun Heo dmi_check_system(sysids)) { 808edc93052STejun Heo struct ata_port *ap = host->ports[1]; 809edc93052STejun Heo 810a44fec1fSJoe Perches dev_info(&pdev->dev, 811a44fec1fSJoe Perches "enabling ASUS P5W DH Deluxe on-board SIMG4726 workaround\n"); 812edc93052STejun Heo 813edc93052STejun Heo ap->ops = &ahci_p5wdh_ops; 814edc93052STejun Heo ap->link.flags |= ATA_LFLAG_NO_SRST | ATA_LFLAG_ASSUME_ATA; 815edc93052STejun Heo } 816edc93052STejun Heo } 817edc93052STejun Heo 818cb85696dSJames Laird /* 819cb85696dSJames Laird * Macbook7,1 firmware forcibly disables MCP89 AHCI and changes PCI ID when 820cb85696dSJames Laird * booting in BIOS compatibility mode. We restore the registers but not ID. 821cb85696dSJames Laird */ 822cb85696dSJames Laird static void ahci_mcp89_apple_enable(struct pci_dev *pdev) 823cb85696dSJames Laird { 824cb85696dSJames Laird u32 val; 825cb85696dSJames Laird 826cb85696dSJames Laird printk(KERN_INFO "ahci: enabling MCP89 AHCI mode\n"); 827cb85696dSJames Laird 828cb85696dSJames Laird pci_read_config_dword(pdev, 0xf8, &val); 829cb85696dSJames Laird val |= 1 << 0x1b; 830cb85696dSJames Laird /* the following changes the device ID, but appears not to affect function */ 831cb85696dSJames Laird /* val = (val & ~0xf0000000) | 0x80000000; */ 832cb85696dSJames Laird pci_write_config_dword(pdev, 0xf8, val); 833cb85696dSJames Laird 834cb85696dSJames Laird pci_read_config_dword(pdev, 0x54c, &val); 835cb85696dSJames Laird val |= 1 << 0xc; 836cb85696dSJames Laird pci_write_config_dword(pdev, 0x54c, val); 837cb85696dSJames Laird 838cb85696dSJames Laird pci_read_config_dword(pdev, 0x4a4, &val); 839cb85696dSJames Laird val &= 0xff; 840cb85696dSJames Laird val |= 0x01060100; 841cb85696dSJames Laird pci_write_config_dword(pdev, 0x4a4, val); 842cb85696dSJames Laird 843cb85696dSJames Laird pci_read_config_dword(pdev, 0x54c, &val); 844cb85696dSJames Laird val &= ~(1 << 0xc); 845cb85696dSJames Laird pci_write_config_dword(pdev, 0x54c, val); 846cb85696dSJames Laird 847cb85696dSJames Laird pci_read_config_dword(pdev, 0xf8, &val); 848cb85696dSJames Laird val &= ~(1 << 0x1b); 849cb85696dSJames Laird pci_write_config_dword(pdev, 0xf8, val); 850cb85696dSJames Laird } 851cb85696dSJames Laird 852cb85696dSJames Laird static bool is_mcp89_apple(struct pci_dev *pdev) 853cb85696dSJames Laird { 854cb85696dSJames Laird return pdev->vendor == PCI_VENDOR_ID_NVIDIA && 855cb85696dSJames Laird pdev->device == PCI_DEVICE_ID_NVIDIA_NFORCE_MCP89_SATA && 856cb85696dSJames Laird pdev->subsystem_vendor == PCI_VENDOR_ID_APPLE && 857cb85696dSJames Laird pdev->subsystem_device == 0xcb89; 858cb85696dSJames Laird } 859cb85696dSJames Laird 8602fcad9d2STejun Heo /* only some SB600 ahci controllers can do 64bit DMA */ 8612fcad9d2STejun Heo static bool ahci_sb600_enable_64bit(struct pci_dev *pdev) 86258a09b38SShane Huang { 86358a09b38SShane Huang static const struct dmi_system_id sysids[] = { 86403d783bfSTejun Heo /* 86503d783bfSTejun Heo * The oldest version known to be broken is 0901 and 86603d783bfSTejun Heo * working is 1501 which was released on 2007-10-26. 8672fcad9d2STejun Heo * Enable 64bit DMA on 1501 and anything newer. 8682fcad9d2STejun Heo * 86903d783bfSTejun Heo * Please read bko#9412 for more info. 87003d783bfSTejun Heo */ 87158a09b38SShane Huang { 87258a09b38SShane Huang .ident = "ASUS M2A-VM", 87358a09b38SShane Huang .matches = { 87458a09b38SShane Huang DMI_MATCH(DMI_BOARD_VENDOR, 87558a09b38SShane Huang "ASUSTeK Computer INC."), 87658a09b38SShane Huang DMI_MATCH(DMI_BOARD_NAME, "M2A-VM"), 87758a09b38SShane Huang }, 87803d783bfSTejun Heo .driver_data = "20071026", /* yyyymmdd */ 87958a09b38SShane Huang }, 880e65cc194SMark Nelson /* 881e65cc194SMark Nelson * All BIOS versions for the MSI K9A2 Platinum (MS-7376) 882e65cc194SMark Nelson * support 64bit DMA. 883e65cc194SMark Nelson * 884e65cc194SMark Nelson * BIOS versions earlier than 1.5 had the Manufacturer DMI 885e65cc194SMark Nelson * fields as "MICRO-STAR INTERANTIONAL CO.,LTD". 886e65cc194SMark Nelson * This spelling mistake was fixed in BIOS version 1.5, so 887e65cc194SMark Nelson * 1.5 and later have the Manufacturer as 888e65cc194SMark Nelson * "MICRO-STAR INTERNATIONAL CO.,LTD". 889e65cc194SMark Nelson * So try to match on DMI_BOARD_VENDOR of "MICRO-STAR INTER". 890e65cc194SMark Nelson * 891e65cc194SMark Nelson * BIOS versions earlier than 1.9 had a Board Product Name 892e65cc194SMark Nelson * DMI field of "MS-7376". This was changed to be 893e65cc194SMark Nelson * "K9A2 Platinum (MS-7376)" in version 1.9, but we can still 894e65cc194SMark Nelson * match on DMI_BOARD_NAME of "MS-7376". 895e65cc194SMark Nelson */ 896e65cc194SMark Nelson { 897e65cc194SMark Nelson .ident = "MSI K9A2 Platinum", 898e65cc194SMark Nelson .matches = { 899e65cc194SMark Nelson DMI_MATCH(DMI_BOARD_VENDOR, 900e65cc194SMark Nelson "MICRO-STAR INTER"), 901e65cc194SMark Nelson DMI_MATCH(DMI_BOARD_NAME, "MS-7376"), 902e65cc194SMark Nelson }, 903e65cc194SMark Nelson }, 9043c4aa91fSMark Nelson /* 905ff0173c1SMark Nelson * All BIOS versions for the MSI K9AGM2 (MS-7327) support 906ff0173c1SMark Nelson * 64bit DMA. 907ff0173c1SMark Nelson * 908ff0173c1SMark Nelson * This board also had the typo mentioned above in the 909ff0173c1SMark Nelson * Manufacturer DMI field (fixed in BIOS version 1.5), so 910ff0173c1SMark Nelson * match on DMI_BOARD_VENDOR of "MICRO-STAR INTER" again. 911ff0173c1SMark Nelson */ 912ff0173c1SMark Nelson { 913ff0173c1SMark Nelson .ident = "MSI K9AGM2", 914ff0173c1SMark Nelson .matches = { 915ff0173c1SMark Nelson DMI_MATCH(DMI_BOARD_VENDOR, 916ff0173c1SMark Nelson "MICRO-STAR INTER"), 917ff0173c1SMark Nelson DMI_MATCH(DMI_BOARD_NAME, "MS-7327"), 918ff0173c1SMark Nelson }, 919ff0173c1SMark Nelson }, 920ff0173c1SMark Nelson /* 9213c4aa91fSMark Nelson * All BIOS versions for the Asus M3A support 64bit DMA. 9223c4aa91fSMark Nelson * (all release versions from 0301 to 1206 were tested) 9233c4aa91fSMark Nelson */ 9243c4aa91fSMark Nelson { 9253c4aa91fSMark Nelson .ident = "ASUS M3A", 9263c4aa91fSMark Nelson .matches = { 9273c4aa91fSMark Nelson DMI_MATCH(DMI_BOARD_VENDOR, 9283c4aa91fSMark Nelson "ASUSTeK Computer INC."), 9293c4aa91fSMark Nelson DMI_MATCH(DMI_BOARD_NAME, "M3A"), 9303c4aa91fSMark Nelson }, 9313c4aa91fSMark Nelson }, 93258a09b38SShane Huang { } 93358a09b38SShane Huang }; 93403d783bfSTejun Heo const struct dmi_system_id *match; 9352fcad9d2STejun Heo int year, month, date; 9362fcad9d2STejun Heo char buf[9]; 93758a09b38SShane Huang 93803d783bfSTejun Heo match = dmi_first_match(sysids); 93958a09b38SShane Huang if (pdev->bus->number != 0 || pdev->devfn != PCI_DEVFN(0x12, 0) || 94003d783bfSTejun Heo !match) 94158a09b38SShane Huang return false; 94258a09b38SShane Huang 943e65cc194SMark Nelson if (!match->driver_data) 944e65cc194SMark Nelson goto enable_64bit; 945e65cc194SMark Nelson 94603d783bfSTejun Heo dmi_get_date(DMI_BIOS_DATE, &year, &month, &date); 94703d783bfSTejun Heo snprintf(buf, sizeof(buf), "%04d%02d%02d", year, month, date); 94803d783bfSTejun Heo 949e65cc194SMark Nelson if (strcmp(buf, match->driver_data) >= 0) 950e65cc194SMark Nelson goto enable_64bit; 951e65cc194SMark Nelson else { 952a44fec1fSJoe Perches dev_warn(&pdev->dev, 953a44fec1fSJoe Perches "%s: BIOS too old, forcing 32bit DMA, update BIOS\n", 954a44fec1fSJoe Perches match->ident); 9552fcad9d2STejun Heo return false; 9562fcad9d2STejun Heo } 957e65cc194SMark Nelson 958e65cc194SMark Nelson enable_64bit: 959a44fec1fSJoe Perches dev_warn(&pdev->dev, "%s: enabling 64bit DMA\n", match->ident); 960e65cc194SMark Nelson return true; 96158a09b38SShane Huang } 96258a09b38SShane Huang 9631fd68434SRafael J. Wysocki static bool ahci_broken_system_poweroff(struct pci_dev *pdev) 9641fd68434SRafael J. Wysocki { 9651fd68434SRafael J. Wysocki static const struct dmi_system_id broken_systems[] = { 9661fd68434SRafael J. Wysocki { 9671fd68434SRafael J. Wysocki .ident = "HP Compaq nx6310", 9681fd68434SRafael J. Wysocki .matches = { 9691fd68434SRafael J. Wysocki DMI_MATCH(DMI_SYS_VENDOR, "Hewlett-Packard"), 9701fd68434SRafael J. Wysocki DMI_MATCH(DMI_PRODUCT_NAME, "HP Compaq nx6310"), 9711fd68434SRafael J. Wysocki }, 9721fd68434SRafael J. Wysocki /* PCI slot number of the controller */ 9731fd68434SRafael J. Wysocki .driver_data = (void *)0x1FUL, 9741fd68434SRafael J. Wysocki }, 975d2f9c061SMaciej Rutecki { 976d2f9c061SMaciej Rutecki .ident = "HP Compaq 6720s", 977d2f9c061SMaciej Rutecki .matches = { 978d2f9c061SMaciej Rutecki DMI_MATCH(DMI_SYS_VENDOR, "Hewlett-Packard"), 979d2f9c061SMaciej Rutecki DMI_MATCH(DMI_PRODUCT_NAME, "HP Compaq 6720s"), 980d2f9c061SMaciej Rutecki }, 981d2f9c061SMaciej Rutecki /* PCI slot number of the controller */ 982d2f9c061SMaciej Rutecki .driver_data = (void *)0x1FUL, 983d2f9c061SMaciej Rutecki }, 9841fd68434SRafael J. Wysocki 9851fd68434SRafael J. Wysocki { } /* terminate list */ 9861fd68434SRafael J. Wysocki }; 9871fd68434SRafael J. Wysocki const struct dmi_system_id *dmi = dmi_first_match(broken_systems); 9881fd68434SRafael J. Wysocki 9891fd68434SRafael J. Wysocki if (dmi) { 9901fd68434SRafael J. Wysocki unsigned long slot = (unsigned long)dmi->driver_data; 9911fd68434SRafael J. Wysocki /* apply the quirk only to on-board controllers */ 9921fd68434SRafael J. Wysocki return slot == PCI_SLOT(pdev->devfn); 9931fd68434SRafael J. Wysocki } 9941fd68434SRafael J. Wysocki 9951fd68434SRafael J. Wysocki return false; 9961fd68434SRafael J. Wysocki } 9971fd68434SRafael J. Wysocki 9989b10ae86STejun Heo static bool ahci_broken_suspend(struct pci_dev *pdev) 9999b10ae86STejun Heo { 10009b10ae86STejun Heo static const struct dmi_system_id sysids[] = { 10019b10ae86STejun Heo /* 10029b10ae86STejun Heo * On HP dv[4-6] and HDX18 with earlier BIOSen, link 10039b10ae86STejun Heo * to the harddisk doesn't become online after 10049b10ae86STejun Heo * resuming from STR. Warn and fail suspend. 10059deb3431STejun Heo * 10069deb3431STejun Heo * http://bugzilla.kernel.org/show_bug.cgi?id=12276 10079deb3431STejun Heo * 10089deb3431STejun Heo * Use dates instead of versions to match as HP is 10099deb3431STejun Heo * apparently recycling both product and version 10109deb3431STejun Heo * strings. 10119deb3431STejun Heo * 10129deb3431STejun Heo * http://bugzilla.kernel.org/show_bug.cgi?id=15462 10139b10ae86STejun Heo */ 10149b10ae86STejun Heo { 10159b10ae86STejun Heo .ident = "dv4", 10169b10ae86STejun Heo .matches = { 10179b10ae86STejun Heo DMI_MATCH(DMI_SYS_VENDOR, "Hewlett-Packard"), 10189b10ae86STejun Heo DMI_MATCH(DMI_PRODUCT_NAME, 10199b10ae86STejun Heo "HP Pavilion dv4 Notebook PC"), 10209b10ae86STejun Heo }, 10219deb3431STejun Heo .driver_data = "20090105", /* F.30 */ 10229b10ae86STejun Heo }, 10239b10ae86STejun Heo { 10249b10ae86STejun Heo .ident = "dv5", 10259b10ae86STejun Heo .matches = { 10269b10ae86STejun Heo DMI_MATCH(DMI_SYS_VENDOR, "Hewlett-Packard"), 10279b10ae86STejun Heo DMI_MATCH(DMI_PRODUCT_NAME, 10289b10ae86STejun Heo "HP Pavilion dv5 Notebook PC"), 10299b10ae86STejun Heo }, 10309deb3431STejun Heo .driver_data = "20090506", /* F.16 */ 10319b10ae86STejun Heo }, 10329b10ae86STejun Heo { 10339b10ae86STejun Heo .ident = "dv6", 10349b10ae86STejun Heo .matches = { 10359b10ae86STejun Heo DMI_MATCH(DMI_SYS_VENDOR, "Hewlett-Packard"), 10369b10ae86STejun Heo DMI_MATCH(DMI_PRODUCT_NAME, 10379b10ae86STejun Heo "HP Pavilion dv6 Notebook PC"), 10389b10ae86STejun Heo }, 10399deb3431STejun Heo .driver_data = "20090423", /* F.21 */ 10409b10ae86STejun Heo }, 10419b10ae86STejun Heo { 10429b10ae86STejun Heo .ident = "HDX18", 10439b10ae86STejun Heo .matches = { 10449b10ae86STejun Heo DMI_MATCH(DMI_SYS_VENDOR, "Hewlett-Packard"), 10459b10ae86STejun Heo DMI_MATCH(DMI_PRODUCT_NAME, 10469b10ae86STejun Heo "HP HDX18 Notebook PC"), 10479b10ae86STejun Heo }, 10489deb3431STejun Heo .driver_data = "20090430", /* F.23 */ 10499b10ae86STejun Heo }, 1050cedc9bf9STejun Heo /* 1051cedc9bf9STejun Heo * Acer eMachines G725 has the same problem. BIOS 1052cedc9bf9STejun Heo * V1.03 is known to be broken. V3.04 is known to 105325985edcSLucas De Marchi * work. Between, there are V1.06, V2.06 and V3.03 1054cedc9bf9STejun Heo * that we don't have much idea about. For now, 1055cedc9bf9STejun Heo * blacklist anything older than V3.04. 10569deb3431STejun Heo * 10579deb3431STejun Heo * http://bugzilla.kernel.org/show_bug.cgi?id=15104 1058cedc9bf9STejun Heo */ 1059cedc9bf9STejun Heo { 1060cedc9bf9STejun Heo .ident = "G725", 1061cedc9bf9STejun Heo .matches = { 1062cedc9bf9STejun Heo DMI_MATCH(DMI_SYS_VENDOR, "eMachines"), 1063cedc9bf9STejun Heo DMI_MATCH(DMI_PRODUCT_NAME, "eMachines G725"), 1064cedc9bf9STejun Heo }, 10659deb3431STejun Heo .driver_data = "20091216", /* V3.04 */ 1066cedc9bf9STejun Heo }, 10679b10ae86STejun Heo { } /* terminate list */ 10689b10ae86STejun Heo }; 10699b10ae86STejun Heo const struct dmi_system_id *dmi = dmi_first_match(sysids); 10709deb3431STejun Heo int year, month, date; 10719deb3431STejun Heo char buf[9]; 10729b10ae86STejun Heo 10739b10ae86STejun Heo if (!dmi || pdev->bus->number || pdev->devfn != PCI_DEVFN(0x1f, 2)) 10749b10ae86STejun Heo return false; 10759b10ae86STejun Heo 10769deb3431STejun Heo dmi_get_date(DMI_BIOS_DATE, &year, &month, &date); 10779deb3431STejun Heo snprintf(buf, sizeof(buf), "%04d%02d%02d", year, month, date); 10789b10ae86STejun Heo 10799deb3431STejun Heo return strcmp(buf, dmi->driver_data) < 0; 10809b10ae86STejun Heo } 10819b10ae86STejun Heo 10825594639aSTejun Heo static bool ahci_broken_online(struct pci_dev *pdev) 10835594639aSTejun Heo { 10845594639aSTejun Heo #define ENCODE_BUSDEVFN(bus, slot, func) \ 10855594639aSTejun Heo (void *)(unsigned long)(((bus) << 8) | PCI_DEVFN((slot), (func))) 10865594639aSTejun Heo static const struct dmi_system_id sysids[] = { 10875594639aSTejun Heo /* 10885594639aSTejun Heo * There are several gigabyte boards which use 10895594639aSTejun Heo * SIMG5723s configured as hardware RAID. Certain 10905594639aSTejun Heo * 5723 firmware revisions shipped there keep the link 10915594639aSTejun Heo * online but fail to answer properly to SRST or 10925594639aSTejun Heo * IDENTIFY when no device is attached downstream 10935594639aSTejun Heo * causing libata to retry quite a few times leading 10945594639aSTejun Heo * to excessive detection delay. 10955594639aSTejun Heo * 10965594639aSTejun Heo * As these firmwares respond to the second reset try 10975594639aSTejun Heo * with invalid device signature, considering unknown 10985594639aSTejun Heo * sig as offline works around the problem acceptably. 10995594639aSTejun Heo */ 11005594639aSTejun Heo { 11015594639aSTejun Heo .ident = "EP45-DQ6", 11025594639aSTejun Heo .matches = { 11035594639aSTejun Heo DMI_MATCH(DMI_BOARD_VENDOR, 11045594639aSTejun Heo "Gigabyte Technology Co., Ltd."), 11055594639aSTejun Heo DMI_MATCH(DMI_BOARD_NAME, "EP45-DQ6"), 11065594639aSTejun Heo }, 11075594639aSTejun Heo .driver_data = ENCODE_BUSDEVFN(0x0a, 0x00, 0), 11085594639aSTejun Heo }, 11095594639aSTejun Heo { 11105594639aSTejun Heo .ident = "EP45-DS5", 11115594639aSTejun Heo .matches = { 11125594639aSTejun Heo DMI_MATCH(DMI_BOARD_VENDOR, 11135594639aSTejun Heo "Gigabyte Technology Co., Ltd."), 11145594639aSTejun Heo DMI_MATCH(DMI_BOARD_NAME, "EP45-DS5"), 11155594639aSTejun Heo }, 11165594639aSTejun Heo .driver_data = ENCODE_BUSDEVFN(0x03, 0x00, 0), 11175594639aSTejun Heo }, 11185594639aSTejun Heo { } /* terminate list */ 11195594639aSTejun Heo }; 11205594639aSTejun Heo #undef ENCODE_BUSDEVFN 11215594639aSTejun Heo const struct dmi_system_id *dmi = dmi_first_match(sysids); 11225594639aSTejun Heo unsigned int val; 11235594639aSTejun Heo 11245594639aSTejun Heo if (!dmi) 11255594639aSTejun Heo return false; 11265594639aSTejun Heo 11275594639aSTejun Heo val = (unsigned long)dmi->driver_data; 11285594639aSTejun Heo 11295594639aSTejun Heo return pdev->bus->number == (val >> 8) && pdev->devfn == (val & 0xff); 11305594639aSTejun Heo } 11315594639aSTejun Heo 11320cf4a7d6SJacob Pan static bool ahci_broken_devslp(struct pci_dev *pdev) 11330cf4a7d6SJacob Pan { 11340cf4a7d6SJacob Pan /* device with broken DEVSLP but still showing SDS capability */ 11350cf4a7d6SJacob Pan static const struct pci_device_id ids[] = { 11360cf4a7d6SJacob Pan { PCI_VDEVICE(INTEL, 0x0f23)}, /* Valleyview SoC */ 11370cf4a7d6SJacob Pan {} 11380cf4a7d6SJacob Pan }; 11390cf4a7d6SJacob Pan 11400cf4a7d6SJacob Pan return pci_match_id(ids, pdev); 11410cf4a7d6SJacob Pan } 11420cf4a7d6SJacob Pan 11438e513217SMarkus Trippelsdorf #ifdef CONFIG_ATA_ACPI 1144f80ae7e4STejun Heo static void ahci_gtf_filter_workaround(struct ata_host *host) 1145f80ae7e4STejun Heo { 1146f80ae7e4STejun Heo static const struct dmi_system_id sysids[] = { 1147f80ae7e4STejun Heo /* 1148f80ae7e4STejun Heo * Aspire 3810T issues a bunch of SATA enable commands 1149f80ae7e4STejun Heo * via _GTF including an invalid one and one which is 1150f80ae7e4STejun Heo * rejected by the device. Among the successful ones 1151f80ae7e4STejun Heo * is FPDMA non-zero offset enable which when enabled 1152f80ae7e4STejun Heo * only on the drive side leads to NCQ command 1153f80ae7e4STejun Heo * failures. Filter it out. 1154f80ae7e4STejun Heo */ 1155f80ae7e4STejun Heo { 1156f80ae7e4STejun Heo .ident = "Aspire 3810T", 1157f80ae7e4STejun Heo .matches = { 1158f80ae7e4STejun Heo DMI_MATCH(DMI_SYS_VENDOR, "Acer"), 1159f80ae7e4STejun Heo DMI_MATCH(DMI_PRODUCT_NAME, "Aspire 3810T"), 1160f80ae7e4STejun Heo }, 1161f80ae7e4STejun Heo .driver_data = (void *)ATA_ACPI_FILTER_FPDMA_OFFSET, 1162f80ae7e4STejun Heo }, 1163f80ae7e4STejun Heo { } 1164f80ae7e4STejun Heo }; 1165f80ae7e4STejun Heo const struct dmi_system_id *dmi = dmi_first_match(sysids); 1166f80ae7e4STejun Heo unsigned int filter; 1167f80ae7e4STejun Heo int i; 1168f80ae7e4STejun Heo 1169f80ae7e4STejun Heo if (!dmi) 1170f80ae7e4STejun Heo return; 1171f80ae7e4STejun Heo 1172f80ae7e4STejun Heo filter = (unsigned long)dmi->driver_data; 1173a44fec1fSJoe Perches dev_info(host->dev, "applying extra ACPI _GTF filter 0x%x for %s\n", 1174f80ae7e4STejun Heo filter, dmi->ident); 1175f80ae7e4STejun Heo 1176f80ae7e4STejun Heo for (i = 0; i < host->n_ports; i++) { 1177f80ae7e4STejun Heo struct ata_port *ap = host->ports[i]; 1178f80ae7e4STejun Heo struct ata_link *link; 1179f80ae7e4STejun Heo struct ata_device *dev; 1180f80ae7e4STejun Heo 1181f80ae7e4STejun Heo ata_for_each_link(link, ap, EDGE) 1182f80ae7e4STejun Heo ata_for_each_dev(dev, link, ALL) 1183f80ae7e4STejun Heo dev->gtf_filter |= filter; 1184f80ae7e4STejun Heo } 1185f80ae7e4STejun Heo } 11868e513217SMarkus Trippelsdorf #else 11878e513217SMarkus Trippelsdorf static inline void ahci_gtf_filter_workaround(struct ata_host *host) 11888e513217SMarkus Trippelsdorf {} 11898e513217SMarkus Trippelsdorf #endif 1190f80ae7e4STejun Heo 1191e1ba8459SLinus Torvalds static int ahci_init_interrupts(struct pci_dev *pdev, unsigned int n_ports, 11927b92b4f6SAlexander Gordeev struct ahci_host_priv *hpriv) 11935ca72c4fSAlexander Gordeev { 1194ccf8f53cSAlexander Gordeev int rc, nvec; 11955ca72c4fSAlexander Gordeev 11967b92b4f6SAlexander Gordeev if (hpriv->flags & AHCI_HFLAG_NO_MSI) 11977b92b4f6SAlexander Gordeev goto intx; 11987b92b4f6SAlexander Gordeev 1199fc061d96SAlexander Gordeev nvec = pci_msi_vec_count(pdev); 1200fc061d96SAlexander Gordeev if (nvec < 0) 12017b92b4f6SAlexander Gordeev goto intx; 12027b92b4f6SAlexander Gordeev 12035ca72c4fSAlexander Gordeev /* 12047b92b4f6SAlexander Gordeev * If number of MSIs is less than number of ports then Sharing Last 12057b92b4f6SAlexander Gordeev * Message mode could be enforced. In this case assume that advantage 12067b92b4f6SAlexander Gordeev * of multipe MSIs is negated and use single MSI mode instead. 12075ca72c4fSAlexander Gordeev */ 1208fc061d96SAlexander Gordeev if (nvec < n_ports) 12097b92b4f6SAlexander Gordeev goto single_msi; 12105ca72c4fSAlexander Gordeev 1211ccf8f53cSAlexander Gordeev rc = pci_enable_msi_exact(pdev, nvec); 1212ccf8f53cSAlexander Gordeev if (rc == -ENOSPC) 1213fc40363bSAlexander Gordeev goto single_msi; 1214ccf8f53cSAlexander Gordeev else if (rc < 0) 1215fc061d96SAlexander Gordeev goto intx; 1216ab0f9e78SAlexander Gordeev 1217ab0f9e78SAlexander Gordeev /* fallback to single MSI mode if the controller enforced MRSM mode */ 1218ab0f9e78SAlexander Gordeev if (readl(hpriv->mmio + HOST_CTL) & HOST_MRSM) { 1219ab0f9e78SAlexander Gordeev pci_disable_msi(pdev); 1220ab0f9e78SAlexander Gordeev printk(KERN_INFO "ahci: MRSM is on, fallback to single MSI\n"); 1221ab0f9e78SAlexander Gordeev goto single_msi; 1222ab0f9e78SAlexander Gordeev } 12237b92b4f6SAlexander Gordeev 12247b92b4f6SAlexander Gordeev return nvec; 12257b92b4f6SAlexander Gordeev 12267b92b4f6SAlexander Gordeev single_msi: 1227fc061d96SAlexander Gordeev if (pci_enable_msi(pdev)) 12287b92b4f6SAlexander Gordeev goto intx; 12297b92b4f6SAlexander Gordeev return 1; 12307b92b4f6SAlexander Gordeev 12317b92b4f6SAlexander Gordeev intx: 12325ca72c4fSAlexander Gordeev pci_intx(pdev, 1); 12335ca72c4fSAlexander Gordeev return 0; 12345ca72c4fSAlexander Gordeev } 12355ca72c4fSAlexander Gordeev 12365ca72c4fSAlexander Gordeev /** 12375ca72c4fSAlexander Gordeev * ahci_host_activate - start AHCI host, request IRQs and register it 12385ca72c4fSAlexander Gordeev * @host: target ATA host 12395ca72c4fSAlexander Gordeev * @irq: base IRQ number to request 12405ca72c4fSAlexander Gordeev * @n_msis: number of MSIs allocated for this host 12415ca72c4fSAlexander Gordeev * @irq_handler: irq_handler used when requesting IRQs 12425ca72c4fSAlexander Gordeev * @irq_flags: irq_flags used when requesting IRQs 12435ca72c4fSAlexander Gordeev * 12445ca72c4fSAlexander Gordeev * Similar to ata_host_activate, but requests IRQs according to AHCI-1.1 12455ca72c4fSAlexander Gordeev * when multiple MSIs were allocated. That is one MSI per port, starting 12465ca72c4fSAlexander Gordeev * from @irq. 12475ca72c4fSAlexander Gordeev * 12485ca72c4fSAlexander Gordeev * LOCKING: 12495ca72c4fSAlexander Gordeev * Inherited from calling layer (may sleep). 12505ca72c4fSAlexander Gordeev * 12515ca72c4fSAlexander Gordeev * RETURNS: 12525ca72c4fSAlexander Gordeev * 0 on success, -errno otherwise. 12535ca72c4fSAlexander Gordeev */ 12545ca72c4fSAlexander Gordeev int ahci_host_activate(struct ata_host *host, int irq, unsigned int n_msis) 12555ca72c4fSAlexander Gordeev { 12565ca72c4fSAlexander Gordeev int i, rc; 12575ca72c4fSAlexander Gordeev 12585ca72c4fSAlexander Gordeev /* Sharing Last Message among several ports is not supported */ 12595ca72c4fSAlexander Gordeev if (n_msis < host->n_ports) 12605ca72c4fSAlexander Gordeev return -EINVAL; 12615ca72c4fSAlexander Gordeev 12625ca72c4fSAlexander Gordeev rc = ata_host_start(host); 12635ca72c4fSAlexander Gordeev if (rc) 12645ca72c4fSAlexander Gordeev return rc; 12655ca72c4fSAlexander Gordeev 12665ca72c4fSAlexander Gordeev for (i = 0; i < host->n_ports; i++) { 1267b29900e6SAlexander Gordeev struct ahci_port_priv *pp = host->ports[i]->private_data; 1268b29900e6SAlexander Gordeev 12692cf532f5SAlexander Gordeev /* Do not receive interrupts sent by dummy ports */ 12702cf532f5SAlexander Gordeev if (!pp) { 12712cf532f5SAlexander Gordeev disable_irq(irq + i); 12722cf532f5SAlexander Gordeev continue; 12732cf532f5SAlexander Gordeev } 12742cf532f5SAlexander Gordeev 12752cf532f5SAlexander Gordeev rc = devm_request_threaded_irq(host->dev, irq + i, 12762cf532f5SAlexander Gordeev ahci_hw_interrupt, 12779ae794acSDavid Milburn ahci_thread_fn, IRQF_SHARED, 12789ae794acSDavid Milburn pp->irq_desc, host->ports[i]); 12795ca72c4fSAlexander Gordeev if (rc) 12805ca72c4fSAlexander Gordeev goto out_free_irqs; 12815ca72c4fSAlexander Gordeev } 12825ca72c4fSAlexander Gordeev 12835ca72c4fSAlexander Gordeev for (i = 0; i < host->n_ports; i++) 12845ca72c4fSAlexander Gordeev ata_port_desc(host->ports[i], "irq %d", irq + i); 12855ca72c4fSAlexander Gordeev 12865ca72c4fSAlexander Gordeev rc = ata_host_register(host, &ahci_sht); 12875ca72c4fSAlexander Gordeev if (rc) 12885ca72c4fSAlexander Gordeev goto out_free_all_irqs; 12895ca72c4fSAlexander Gordeev 12905ca72c4fSAlexander Gordeev return 0; 12915ca72c4fSAlexander Gordeev 12925ca72c4fSAlexander Gordeev out_free_all_irqs: 12935ca72c4fSAlexander Gordeev i = host->n_ports; 12945ca72c4fSAlexander Gordeev out_free_irqs: 12955ca72c4fSAlexander Gordeev for (i--; i >= 0; i--) 12965ca72c4fSAlexander Gordeev devm_free_irq(host->dev, irq + i, host->ports[i]); 12975ca72c4fSAlexander Gordeev 12985ca72c4fSAlexander Gordeev return rc; 12995ca72c4fSAlexander Gordeev } 13005ca72c4fSAlexander Gordeev 1301c6fd2807SJeff Garzik static int ahci_init_one(struct pci_dev *pdev, const struct pci_device_id *ent) 1302c6fd2807SJeff Garzik { 1303e297d99eSTejun Heo unsigned int board_id = ent->driver_data; 1304e297d99eSTejun Heo struct ata_port_info pi = ahci_port_info[board_id]; 13054447d351STejun Heo const struct ata_port_info *ppi[] = { &pi, NULL }; 130624dc5f33STejun Heo struct device *dev = &pdev->dev; 1307c6fd2807SJeff Garzik struct ahci_host_priv *hpriv; 13084447d351STejun Heo struct ata_host *host; 13095ca72c4fSAlexander Gordeev int n_ports, n_msis, i, rc; 1310318893e1SAlessandro Rubini int ahci_pci_bar = AHCI_PCI_BAR_STANDARD; 1311c6fd2807SJeff Garzik 1312c6fd2807SJeff Garzik VPRINTK("ENTER\n"); 1313c6fd2807SJeff Garzik 1314b429dd59SJustin P. Mattock WARN_ON((int)ATA_MAX_QUEUE > AHCI_MAX_CMDS); 1315c6fd2807SJeff Garzik 131606296a1eSJoe Perches ata_print_version_once(&pdev->dev, DRV_VERSION); 1317c6fd2807SJeff Garzik 13185b66c829SAlan Cox /* The AHCI driver can only drive the SATA ports, the PATA driver 13195b66c829SAlan Cox can drive them all so if both drivers are selected make sure 13205b66c829SAlan Cox AHCI stays out of the way */ 13215b66c829SAlan Cox if (pdev->vendor == PCI_VENDOR_ID_MARVELL && !marvell_enable) 13225b66c829SAlan Cox return -ENODEV; 13235b66c829SAlan Cox 1324cb85696dSJames Laird /* Apple BIOS on MCP89 prevents us using AHCI */ 1325cb85696dSJames Laird if (is_mcp89_apple(pdev)) 1326cb85696dSJames Laird ahci_mcp89_apple_enable(pdev); 1327c6353b45STejun Heo 13287a02267eSMark Nelson /* Promise's PDC42819 is a SAS/SATA controller that has an AHCI mode. 13297a02267eSMark Nelson * At the moment, we can only use the AHCI mode. Let the users know 13307a02267eSMark Nelson * that for SAS drives they're out of luck. 13317a02267eSMark Nelson */ 13327a02267eSMark Nelson if (pdev->vendor == PCI_VENDOR_ID_PROMISE) 1333a44fec1fSJoe Perches dev_info(&pdev->dev, 1334a44fec1fSJoe Perches "PDC42819 can only drive SATA devices with this driver\n"); 13357a02267eSMark Nelson 13367f9c9f8eSHugh Daschbach /* Both Connext and Enmotus devices use non-standard BARs */ 1337318893e1SAlessandro Rubini if (pdev->vendor == PCI_VENDOR_ID_STMICRO && pdev->device == 0xCC06) 1338318893e1SAlessandro Rubini ahci_pci_bar = AHCI_PCI_BAR_STA2X11; 13397f9c9f8eSHugh Daschbach else if (pdev->vendor == 0x1c44 && pdev->device == 0x8000) 13407f9c9f8eSHugh Daschbach ahci_pci_bar = AHCI_PCI_BAR_ENMOTUS; 1341318893e1SAlessandro Rubini 1342e6b7e41cSChuansheng Liu /* 1343e6b7e41cSChuansheng Liu * The JMicron chip 361/363 contains one SATA controller and one 1344e6b7e41cSChuansheng Liu * PATA controller,for powering on these both controllers, we must 1345e6b7e41cSChuansheng Liu * follow the sequence one by one, otherwise one of them can not be 1346e6b7e41cSChuansheng Liu * powered on successfully, so here we disable the async suspend 1347e6b7e41cSChuansheng Liu * method for these chips. 1348e6b7e41cSChuansheng Liu */ 1349e6b7e41cSChuansheng Liu if (pdev->vendor == PCI_VENDOR_ID_JMICRON && 1350e6b7e41cSChuansheng Liu (pdev->device == PCI_DEVICE_ID_JMICRON_JMB363 || 1351e6b7e41cSChuansheng Liu pdev->device == PCI_DEVICE_ID_JMICRON_JMB361)) 1352e6b7e41cSChuansheng Liu device_disable_async_suspend(&pdev->dev); 1353e6b7e41cSChuansheng Liu 13544447d351STejun Heo /* acquire resources */ 135524dc5f33STejun Heo rc = pcim_enable_device(pdev); 1356c6fd2807SJeff Garzik if (rc) 1357c6fd2807SJeff Garzik return rc; 1358c6fd2807SJeff Garzik 1359c4f7792cSTejun Heo if (pdev->vendor == PCI_VENDOR_ID_INTEL && 1360c4f7792cSTejun Heo (pdev->device == 0x2652 || pdev->device == 0x2653)) { 1361c4f7792cSTejun Heo u8 map; 1362c4f7792cSTejun Heo 1363c4f7792cSTejun Heo /* ICH6s share the same PCI ID for both piix and ahci 1364c4f7792cSTejun Heo * modes. Enabling ahci mode while MAP indicates 1365c4f7792cSTejun Heo * combined mode is a bad idea. Yield to ata_piix. 1366c4f7792cSTejun Heo */ 1367c4f7792cSTejun Heo pci_read_config_byte(pdev, ICH_MAP, &map); 1368c4f7792cSTejun Heo if (map & 0x3) { 1369a44fec1fSJoe Perches dev_info(&pdev->dev, 1370a44fec1fSJoe Perches "controller is in combined mode, can't enable AHCI mode\n"); 1371c4f7792cSTejun Heo return -ENODEV; 1372c4f7792cSTejun Heo } 1373c4f7792cSTejun Heo } 1374c4f7792cSTejun Heo 13756fec8871SPaul Bolle /* AHCI controllers often implement SFF compatible interface. 13766fec8871SPaul Bolle * Grab all PCI BARs just in case. 13776fec8871SPaul Bolle */ 13786fec8871SPaul Bolle rc = pcim_iomap_regions_request_all(pdev, 1 << ahci_pci_bar, DRV_NAME); 13796fec8871SPaul Bolle if (rc == -EBUSY) 13806fec8871SPaul Bolle pcim_pin_device(pdev); 13816fec8871SPaul Bolle if (rc) 13826fec8871SPaul Bolle return rc; 13836fec8871SPaul Bolle 138424dc5f33STejun Heo hpriv = devm_kzalloc(dev, sizeof(*hpriv), GFP_KERNEL); 138524dc5f33STejun Heo if (!hpriv) 138624dc5f33STejun Heo return -ENOMEM; 1387417a1a6dSTejun Heo hpriv->flags |= (unsigned long)pi.private_data; 1388417a1a6dSTejun Heo 1389e297d99eSTejun Heo /* MCP65 revision A1 and A2 can't do MSI */ 1390e297d99eSTejun Heo if (board_id == board_ahci_mcp65 && 1391e297d99eSTejun Heo (pdev->revision == 0xa1 || pdev->revision == 0xa2)) 1392e297d99eSTejun Heo hpriv->flags |= AHCI_HFLAG_NO_MSI; 1393e297d99eSTejun Heo 1394e427fe04SShane Huang /* SB800 does NOT need the workaround to ignore SERR_INTERNAL */ 1395e427fe04SShane Huang if (board_id == board_ahci_sb700 && pdev->revision >= 0x40) 1396e427fe04SShane Huang hpriv->flags &= ~AHCI_HFLAG_IGN_SERR_INTERNAL; 1397e427fe04SShane Huang 13982fcad9d2STejun Heo /* only some SB600s can do 64bit DMA */ 13992fcad9d2STejun Heo if (ahci_sb600_enable_64bit(pdev)) 14002fcad9d2STejun Heo hpriv->flags &= ~AHCI_HFLAG_32BIT_ONLY; 140158a09b38SShane Huang 1402318893e1SAlessandro Rubini hpriv->mmio = pcim_iomap_table(pdev)[ahci_pci_bar]; 1403d8993349SAnton Vorontsov 14040cf4a7d6SJacob Pan /* must set flag prior to save config in order to take effect */ 14050cf4a7d6SJacob Pan if (ahci_broken_devslp(pdev)) 14060cf4a7d6SJacob Pan hpriv->flags |= AHCI_HFLAG_NO_DEVSLP; 14070cf4a7d6SJacob Pan 14084447d351STejun Heo /* save initial config */ 1409394d6e53SAnton Vorontsov ahci_pci_save_initial_config(pdev, hpriv); 1410c6fd2807SJeff Garzik 14114447d351STejun Heo /* prepare host */ 1412453d3131SRobert Hancock if (hpriv->cap & HOST_CAP_NCQ) { 1413453d3131SRobert Hancock pi.flags |= ATA_FLAG_NCQ; 141483f2b963STejun Heo /* 141583f2b963STejun Heo * Auto-activate optimization is supposed to be 141683f2b963STejun Heo * supported on all AHCI controllers indicating NCQ 141783f2b963STejun Heo * capability, but it seems to be broken on some 141883f2b963STejun Heo * chipsets including NVIDIAs. 141983f2b963STejun Heo */ 142083f2b963STejun Heo if (!(hpriv->flags & AHCI_HFLAG_NO_FPDMA_AA)) 1421453d3131SRobert Hancock pi.flags |= ATA_FLAG_FPDMA_AA; 142240fb59e7SMarc Carino 142340fb59e7SMarc Carino /* 142440fb59e7SMarc Carino * All AHCI controllers should be forward-compatible 142540fb59e7SMarc Carino * with the new auxiliary field. This code should be 142640fb59e7SMarc Carino * conditionalized if any buggy AHCI controllers are 142740fb59e7SMarc Carino * encountered. 142840fb59e7SMarc Carino */ 142940fb59e7SMarc Carino pi.flags |= ATA_FLAG_FPDMA_AUX; 1430453d3131SRobert Hancock } 14314447d351STejun Heo 14327d50b60bSTejun Heo if (hpriv->cap & HOST_CAP_PMP) 14337d50b60bSTejun Heo pi.flags |= ATA_FLAG_PMP; 14347d50b60bSTejun Heo 14350cbb0e77SAnton Vorontsov ahci_set_em_messages(hpriv, &pi); 143618f7ba4cSKristen Carlson Accardi 14371fd68434SRafael J. Wysocki if (ahci_broken_system_poweroff(pdev)) { 14381fd68434SRafael J. Wysocki pi.flags |= ATA_FLAG_NO_POWEROFF_SPINDOWN; 14391fd68434SRafael J. Wysocki dev_info(&pdev->dev, 14401fd68434SRafael J. Wysocki "quirky BIOS, skipping spindown on poweroff\n"); 14411fd68434SRafael J. Wysocki } 14421fd68434SRafael J. Wysocki 14439b10ae86STejun Heo if (ahci_broken_suspend(pdev)) { 14449b10ae86STejun Heo hpriv->flags |= AHCI_HFLAG_NO_SUSPEND; 1445a44fec1fSJoe Perches dev_warn(&pdev->dev, 14469b10ae86STejun Heo "BIOS update required for suspend/resume\n"); 14479b10ae86STejun Heo } 14489b10ae86STejun Heo 14495594639aSTejun Heo if (ahci_broken_online(pdev)) { 14505594639aSTejun Heo hpriv->flags |= AHCI_HFLAG_SRST_TOUT_IS_OFFLINE; 14515594639aSTejun Heo dev_info(&pdev->dev, 14525594639aSTejun Heo "online status unreliable, applying workaround\n"); 14535594639aSTejun Heo } 14545594639aSTejun Heo 1455837f5f8fSTejun Heo /* CAP.NP sometimes indicate the index of the last enabled 1456837f5f8fSTejun Heo * port, at other times, that of the last possible port, so 1457837f5f8fSTejun Heo * determining the maximum port number requires looking at 1458837f5f8fSTejun Heo * both CAP.NP and port_map. 1459837f5f8fSTejun Heo */ 1460837f5f8fSTejun Heo n_ports = max(ahci_nr_ports(hpriv->cap), fls(hpriv->port_map)); 1461837f5f8fSTejun Heo 14627b92b4f6SAlexander Gordeev n_msis = ahci_init_interrupts(pdev, n_ports, hpriv); 14637b92b4f6SAlexander Gordeev if (n_msis > 1) 14647b92b4f6SAlexander Gordeev hpriv->flags |= AHCI_HFLAG_MULTI_MSI; 14657b92b4f6SAlexander Gordeev 1466837f5f8fSTejun Heo host = ata_host_alloc_pinfo(&pdev->dev, ppi, n_ports); 14674447d351STejun Heo if (!host) 14684447d351STejun Heo return -ENOMEM; 14694447d351STejun Heo host->private_data = hpriv; 14704447d351STejun Heo 1471f3d7f23fSArjan van de Ven if (!(hpriv->cap & HOST_CAP_SSS) || ahci_ignore_sss) 1472886ad09fSArjan van de Ven host->flags |= ATA_HOST_PARALLEL_SCAN; 1473f3d7f23fSArjan van de Ven else 1474d2782d96SJingoo Han dev_info(&pdev->dev, "SSS flag set, parallel bus scan disabled\n"); 1475886ad09fSArjan van de Ven 147618f7ba4cSKristen Carlson Accardi if (pi.flags & ATA_FLAG_EM) 147718f7ba4cSKristen Carlson Accardi ahci_reset_em(host); 147818f7ba4cSKristen Carlson Accardi 14794447d351STejun Heo for (i = 0; i < host->n_ports; i++) { 14804447d351STejun Heo struct ata_port *ap = host->ports[i]; 14814447d351STejun Heo 1482318893e1SAlessandro Rubini ata_port_pbar_desc(ap, ahci_pci_bar, -1, "abar"); 1483318893e1SAlessandro Rubini ata_port_pbar_desc(ap, ahci_pci_bar, 1484cbcdd875STejun Heo 0x100 + ap->port_no * 0x80, "port"); 1485cbcdd875STejun Heo 148618f7ba4cSKristen Carlson Accardi /* set enclosure management message type */ 148718f7ba4cSKristen Carlson Accardi if (ap->flags & ATA_FLAG_EM) 1488008dbd61SHarry Zhang ap->em_message_type = hpriv->em_msg_type; 148918f7ba4cSKristen Carlson Accardi 149018f7ba4cSKristen Carlson Accardi 1491dab632e8SJeff Garzik /* disabled/not-implemented port */ 1492350756f6STejun Heo if (!(hpriv->port_map & (1 << i))) 1493dab632e8SJeff Garzik ap->ops = &ata_dummy_port_ops; 14944447d351STejun Heo } 1495c6fd2807SJeff Garzik 1496edc93052STejun Heo /* apply workaround for ASUS P5W DH Deluxe mainboard */ 1497edc93052STejun Heo ahci_p5wdh_workaround(host); 1498edc93052STejun Heo 1499f80ae7e4STejun Heo /* apply gtf filter quirk */ 1500f80ae7e4STejun Heo ahci_gtf_filter_workaround(host); 1501f80ae7e4STejun Heo 1502c6fd2807SJeff Garzik /* initialize adapter */ 15034447d351STejun Heo rc = ahci_configure_dma_masks(pdev, hpriv->cap & HOST_CAP_64); 1504c6fd2807SJeff Garzik if (rc) 150524dc5f33STejun Heo return rc; 1506c6fd2807SJeff Garzik 15073303040dSAnton Vorontsov rc = ahci_pci_reset_controller(host); 15084447d351STejun Heo if (rc) 15094447d351STejun Heo return rc; 1510c6fd2807SJeff Garzik 1511781d6550SAnton Vorontsov ahci_pci_init_controller(host); 1512439fcaecSAnton Vorontsov ahci_pci_print_info(host); 1513c6fd2807SJeff Garzik 15144447d351STejun Heo pci_set_master(pdev); 15155ca72c4fSAlexander Gordeev 15165ca72c4fSAlexander Gordeev if (hpriv->flags & AHCI_HFLAG_MULTI_MSI) 15175ca72c4fSAlexander Gordeev return ahci_host_activate(host, pdev->irq, n_msis); 15185ca72c4fSAlexander Gordeev 15194447d351STejun Heo return ata_host_activate(host, pdev->irq, ahci_interrupt, IRQF_SHARED, 15204447d351STejun Heo &ahci_sht); 1521c6fd2807SJeff Garzik } 1522c6fd2807SJeff Garzik 15232fc75da0SAxel Lin module_pci_driver(ahci_pci_driver); 1524c6fd2807SJeff Garzik 1525c6fd2807SJeff Garzik MODULE_AUTHOR("Jeff Garzik"); 1526c6fd2807SJeff Garzik MODULE_DESCRIPTION("AHCI SATA low-level driver"); 1527c6fd2807SJeff Garzik MODULE_LICENSE("GPL"); 1528c6fd2807SJeff Garzik MODULE_DEVICE_TABLE(pci, ahci_pci_tbl); 1529c6fd2807SJeff Garzik MODULE_VERSION(DRV_VERSION); 1530