1c6fd2807SJeff Garzik /* 2c6fd2807SJeff Garzik * ahci.c - AHCI SATA support 3c6fd2807SJeff Garzik * 4c6fd2807SJeff Garzik * Maintained by: Jeff Garzik <jgarzik@pobox.com> 5c6fd2807SJeff Garzik * Please ALWAYS copy linux-ide@vger.kernel.org 6c6fd2807SJeff Garzik * on emails. 7c6fd2807SJeff Garzik * 8c6fd2807SJeff Garzik * Copyright 2004-2005 Red Hat, Inc. 9c6fd2807SJeff Garzik * 10c6fd2807SJeff Garzik * 11c6fd2807SJeff Garzik * This program is free software; you can redistribute it and/or modify 12c6fd2807SJeff Garzik * it under the terms of the GNU General Public License as published by 13c6fd2807SJeff Garzik * the Free Software Foundation; either version 2, or (at your option) 14c6fd2807SJeff Garzik * any later version. 15c6fd2807SJeff Garzik * 16c6fd2807SJeff Garzik * This program is distributed in the hope that it will be useful, 17c6fd2807SJeff Garzik * but WITHOUT ANY WARRANTY; without even the implied warranty of 18c6fd2807SJeff Garzik * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 19c6fd2807SJeff Garzik * GNU General Public License for more details. 20c6fd2807SJeff Garzik * 21c6fd2807SJeff Garzik * You should have received a copy of the GNU General Public License 22c6fd2807SJeff Garzik * along with this program; see the file COPYING. If not, write to 23c6fd2807SJeff Garzik * the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. 24c6fd2807SJeff Garzik * 25c6fd2807SJeff Garzik * 26c6fd2807SJeff Garzik * libata documentation is available via 'make {ps|pdf}docs', 27c6fd2807SJeff Garzik * as Documentation/DocBook/libata.* 28c6fd2807SJeff Garzik * 29c6fd2807SJeff Garzik * AHCI hardware documentation: 30c6fd2807SJeff Garzik * http://www.intel.com/technology/serialata/pdf/rev1_0.pdf 31c6fd2807SJeff Garzik * http://www.intel.com/technology/serialata/pdf/rev1_1.pdf 32c6fd2807SJeff Garzik * 33c6fd2807SJeff Garzik */ 34c6fd2807SJeff Garzik 35c6fd2807SJeff Garzik #include <linux/kernel.h> 36c6fd2807SJeff Garzik #include <linux/module.h> 37c6fd2807SJeff Garzik #include <linux/pci.h> 38c6fd2807SJeff Garzik #include <linux/init.h> 39c6fd2807SJeff Garzik #include <linux/blkdev.h> 40c6fd2807SJeff Garzik #include <linux/delay.h> 41c6fd2807SJeff Garzik #include <linux/interrupt.h> 42c6fd2807SJeff Garzik #include <linux/dma-mapping.h> 43c6fd2807SJeff Garzik #include <linux/device.h> 44edc93052STejun Heo #include <linux/dmi.h> 455a0e3ad6STejun Heo #include <linux/gfp.h> 46c6fd2807SJeff Garzik #include <scsi/scsi_host.h> 47c6fd2807SJeff Garzik #include <scsi/scsi_cmnd.h> 48c6fd2807SJeff Garzik #include <linux/libata.h> 49365cfa1eSAnton Vorontsov #include "ahci.h" 50c6fd2807SJeff Garzik 51c6fd2807SJeff Garzik #define DRV_NAME "ahci" 527d50b60bSTejun Heo #define DRV_VERSION "3.0" 53c6fd2807SJeff Garzik 54c6fd2807SJeff Garzik enum { 55318893e1SAlessandro Rubini AHCI_PCI_BAR_STA2X11 = 0, 567f9c9f8eSHugh Daschbach AHCI_PCI_BAR_ENMOTUS = 2, 57318893e1SAlessandro Rubini AHCI_PCI_BAR_STANDARD = 5, 58441577efSTejun Heo }; 59c6fd2807SJeff Garzik 60441577efSTejun Heo enum board_ids { 61441577efSTejun Heo /* board IDs by feature in alphabetical order */ 62441577efSTejun Heo board_ahci, 63441577efSTejun Heo board_ahci_ign_iferr, 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); 86a1efdabaSTejun Heo static int ahci_p5wdh_hardreset(struct ata_link *link, unsigned int *class, 87a1efdabaSTejun Heo unsigned long deadline); 88438ac6d5STejun Heo #ifdef CONFIG_PM 89c6fd2807SJeff Garzik static int ahci_pci_device_suspend(struct pci_dev *pdev, pm_message_t mesg); 90c6fd2807SJeff Garzik static int ahci_pci_device_resume(struct pci_dev *pdev); 91438ac6d5STejun Heo #endif 92c6fd2807SJeff Garzik 93fad16e7aSTejun Heo static struct scsi_host_template ahci_sht = { 94fad16e7aSTejun Heo AHCI_SHT("ahci"), 95fad16e7aSTejun Heo }; 96fad16e7aSTejun Heo 97029cfd6bSTejun Heo static struct ata_port_operations ahci_vt8251_ops = { 98029cfd6bSTejun Heo .inherits = &ahci_ops, 99a1efdabaSTejun Heo .hardreset = ahci_vt8251_hardreset, 100ad616ffbSTejun Heo }; 101ad616ffbSTejun Heo 102029cfd6bSTejun Heo static struct ata_port_operations ahci_p5wdh_ops = { 103029cfd6bSTejun Heo .inherits = &ahci_ops, 104a1efdabaSTejun Heo .hardreset = ahci_p5wdh_hardreset, 105edc93052STejun Heo }; 106edc93052STejun Heo 107c6fd2807SJeff Garzik static const struct ata_port_info ahci_port_info[] = { 108441577efSTejun Heo /* by features */ 109facb8fa6SJeffrin Jose [board_ahci] = { 1101188c0d8STejun Heo .flags = AHCI_FLAG_COMMON, 11114bdef98SErik Inge Bolsø .pio_mask = ATA_PIO4, 112469248abSJeff Garzik .udma_mask = ATA_UDMA6, 113c6fd2807SJeff Garzik .port_ops = &ahci_ops, 114c6fd2807SJeff Garzik }, 115facb8fa6SJeffrin Jose [board_ahci_ign_iferr] = { 116417a1a6dSTejun Heo AHCI_HFLAGS (AHCI_HFLAG_IGN_IRQ_IF_ERR), 117417a1a6dSTejun Heo .flags = AHCI_FLAG_COMMON, 11814bdef98SErik Inge Bolsø .pio_mask = ATA_PIO4, 119469248abSJeff Garzik .udma_mask = ATA_UDMA6, 12041669553STejun Heo .port_ops = &ahci_ops, 12141669553STejun Heo }, 122facb8fa6SJeffrin Jose [board_ahci_nosntf] = { 123441577efSTejun Heo AHCI_HFLAGS (AHCI_HFLAG_NO_SNTF), 124441577efSTejun Heo .flags = AHCI_FLAG_COMMON, 125441577efSTejun Heo .pio_mask = ATA_PIO4, 126441577efSTejun Heo .udma_mask = ATA_UDMA6, 127441577efSTejun Heo .port_ops = &ahci_ops, 128441577efSTejun Heo }, 129facb8fa6SJeffrin Jose [board_ahci_yes_fbs] = { 1305f173107STejun Heo AHCI_HFLAGS (AHCI_HFLAG_YES_FBS), 1315f173107STejun Heo .flags = AHCI_FLAG_COMMON, 1325f173107STejun Heo .pio_mask = ATA_PIO4, 1335f173107STejun Heo .udma_mask = ATA_UDMA6, 1345f173107STejun Heo .port_ops = &ahci_ops, 1355f173107STejun Heo }, 136441577efSTejun Heo /* by chipsets */ 137facb8fa6SJeffrin Jose [board_ahci_mcp65] = { 13883f2b963STejun Heo AHCI_HFLAGS (AHCI_HFLAG_NO_FPDMA_AA | AHCI_HFLAG_NO_PMP | 13983f2b963STejun Heo AHCI_HFLAG_YES_NCQ), 140ae01b249STejun Heo .flags = AHCI_FLAG_COMMON | ATA_FLAG_NO_DIPM, 14183f2b963STejun Heo .pio_mask = ATA_PIO4, 14283f2b963STejun Heo .udma_mask = ATA_UDMA6, 14383f2b963STejun Heo .port_ops = &ahci_ops, 14483f2b963STejun Heo }, 145facb8fa6SJeffrin Jose [board_ahci_mcp77] = { 14683f2b963STejun Heo AHCI_HFLAGS (AHCI_HFLAG_NO_FPDMA_AA | AHCI_HFLAG_NO_PMP), 14783f2b963STejun Heo .flags = AHCI_FLAG_COMMON, 14883f2b963STejun Heo .pio_mask = ATA_PIO4, 14983f2b963STejun Heo .udma_mask = ATA_UDMA6, 15083f2b963STejun Heo .port_ops = &ahci_ops, 15183f2b963STejun Heo }, 152facb8fa6SJeffrin Jose [board_ahci_mcp89] = { 15383f2b963STejun Heo AHCI_HFLAGS (AHCI_HFLAG_NO_FPDMA_AA), 154441577efSTejun Heo .flags = AHCI_FLAG_COMMON, 155441577efSTejun Heo .pio_mask = ATA_PIO4, 156441577efSTejun Heo .udma_mask = ATA_UDMA6, 157441577efSTejun Heo .port_ops = &ahci_ops, 158441577efSTejun Heo }, 159facb8fa6SJeffrin Jose [board_ahci_mv] = { 160441577efSTejun Heo AHCI_HFLAGS (AHCI_HFLAG_NO_NCQ | AHCI_HFLAG_NO_MSI | 161441577efSTejun Heo AHCI_HFLAG_MV_PATA | AHCI_HFLAG_NO_PMP), 1629cbe056fSSergei Shtylyov .flags = ATA_FLAG_SATA | ATA_FLAG_PIO_DMA, 163441577efSTejun Heo .pio_mask = ATA_PIO4, 164441577efSTejun Heo .udma_mask = ATA_UDMA6, 165441577efSTejun Heo .port_ops = &ahci_ops, 166441577efSTejun Heo }, 167facb8fa6SJeffrin Jose [board_ahci_sb600] = { 168417a1a6dSTejun Heo AHCI_HFLAGS (AHCI_HFLAG_IGN_SERR_INTERNAL | 1692fcad9d2STejun Heo AHCI_HFLAG_NO_MSI | AHCI_HFLAG_SECT255 | 1702fcad9d2STejun Heo AHCI_HFLAG_32BIT_ONLY), 171417a1a6dSTejun Heo .flags = AHCI_FLAG_COMMON, 17214bdef98SErik Inge Bolsø .pio_mask = ATA_PIO4, 173469248abSJeff Garzik .udma_mask = ATA_UDMA6, 174345347c5SYuan-Hsin Chen .port_ops = &ahci_pmp_retry_srst_ops, 17555a61604SConke Hu }, 176facb8fa6SJeffrin Jose [board_ahci_sb700] = { /* for SB700 and SB800 */ 177bd17243aSShane Huang AHCI_HFLAGS (AHCI_HFLAG_IGN_SERR_INTERNAL), 178e39fc8c9SShane Huang .flags = AHCI_FLAG_COMMON, 17914bdef98SErik Inge Bolsø .pio_mask = ATA_PIO4, 180e39fc8c9SShane Huang .udma_mask = ATA_UDMA6, 181345347c5SYuan-Hsin Chen .port_ops = &ahci_pmp_retry_srst_ops, 182e39fc8c9SShane Huang }, 183facb8fa6SJeffrin Jose [board_ahci_vt8251] = { 184441577efSTejun Heo AHCI_HFLAGS (AHCI_HFLAG_NO_NCQ | AHCI_HFLAG_NO_PMP), 185e297d99eSTejun Heo .flags = AHCI_FLAG_COMMON, 18614bdef98SErik Inge Bolsø .pio_mask = ATA_PIO4, 187e297d99eSTejun Heo .udma_mask = ATA_UDMA6, 188441577efSTejun Heo .port_ops = &ahci_vt8251_ops, 1891b677afdSShaohua Li }, 190c6fd2807SJeff Garzik }; 191c6fd2807SJeff Garzik 192c6fd2807SJeff Garzik static const struct pci_device_id ahci_pci_tbl[] = { 193c6fd2807SJeff Garzik /* Intel */ 19454bb3a94SJeff Garzik { PCI_VDEVICE(INTEL, 0x2652), board_ahci }, /* ICH6 */ 19554bb3a94SJeff Garzik { PCI_VDEVICE(INTEL, 0x2653), board_ahci }, /* ICH6M */ 19654bb3a94SJeff Garzik { PCI_VDEVICE(INTEL, 0x27c1), board_ahci }, /* ICH7 */ 19754bb3a94SJeff Garzik { PCI_VDEVICE(INTEL, 0x27c5), board_ahci }, /* ICH7M */ 19854bb3a94SJeff Garzik { PCI_VDEVICE(INTEL, 0x27c3), board_ahci }, /* ICH7R */ 19982490c09STejun Heo { PCI_VDEVICE(AL, 0x5288), board_ahci_ign_iferr }, /* ULi M5288 */ 20054bb3a94SJeff Garzik { PCI_VDEVICE(INTEL, 0x2681), board_ahci }, /* ESB2 */ 20154bb3a94SJeff Garzik { PCI_VDEVICE(INTEL, 0x2682), board_ahci }, /* ESB2 */ 20254bb3a94SJeff Garzik { PCI_VDEVICE(INTEL, 0x2683), board_ahci }, /* ESB2 */ 20354bb3a94SJeff Garzik { PCI_VDEVICE(INTEL, 0x27c6), board_ahci }, /* ICH7-M DH */ 2047a234affSTejun Heo { PCI_VDEVICE(INTEL, 0x2821), board_ahci }, /* ICH8 */ 2051b677afdSShaohua Li { PCI_VDEVICE(INTEL, 0x2822), board_ahci_nosntf }, /* ICH8 */ 2067a234affSTejun Heo { PCI_VDEVICE(INTEL, 0x2824), board_ahci }, /* ICH8 */ 2077a234affSTejun Heo { PCI_VDEVICE(INTEL, 0x2829), board_ahci }, /* ICH8M */ 2087a234affSTejun Heo { PCI_VDEVICE(INTEL, 0x282a), board_ahci }, /* ICH8M */ 2097a234affSTejun Heo { PCI_VDEVICE(INTEL, 0x2922), board_ahci }, /* ICH9 */ 2107a234affSTejun Heo { PCI_VDEVICE(INTEL, 0x2923), board_ahci }, /* ICH9 */ 2117a234affSTejun Heo { PCI_VDEVICE(INTEL, 0x2924), board_ahci }, /* ICH9 */ 2127a234affSTejun Heo { PCI_VDEVICE(INTEL, 0x2925), board_ahci }, /* ICH9 */ 2137a234affSTejun Heo { PCI_VDEVICE(INTEL, 0x2927), board_ahci }, /* ICH9 */ 2147a234affSTejun Heo { PCI_VDEVICE(INTEL, 0x2929), board_ahci }, /* ICH9M */ 2157a234affSTejun Heo { PCI_VDEVICE(INTEL, 0x292a), board_ahci }, /* ICH9M */ 2167a234affSTejun Heo { PCI_VDEVICE(INTEL, 0x292b), board_ahci }, /* ICH9M */ 2177a234affSTejun Heo { PCI_VDEVICE(INTEL, 0x292c), board_ahci }, /* ICH9M */ 2187a234affSTejun Heo { PCI_VDEVICE(INTEL, 0x292f), board_ahci }, /* ICH9M */ 2197a234affSTejun Heo { PCI_VDEVICE(INTEL, 0x294d), board_ahci }, /* ICH9 */ 2207a234affSTejun Heo { PCI_VDEVICE(INTEL, 0x294e), board_ahci }, /* ICH9M */ 221d4155e6fSJason Gaston { PCI_VDEVICE(INTEL, 0x502a), board_ahci }, /* Tolapai */ 222d4155e6fSJason Gaston { PCI_VDEVICE(INTEL, 0x502b), board_ahci }, /* Tolapai */ 22316ad1ad9SJason Gaston { PCI_VDEVICE(INTEL, 0x3a05), board_ahci }, /* ICH10 */ 224b2dde6afSMark Goodwin { PCI_VDEVICE(INTEL, 0x3a22), board_ahci }, /* ICH10 */ 22516ad1ad9SJason Gaston { PCI_VDEVICE(INTEL, 0x3a25), board_ahci }, /* ICH10 */ 226c1f57d9bSDavid Milburn { PCI_VDEVICE(INTEL, 0x3b22), board_ahci }, /* PCH AHCI */ 227c1f57d9bSDavid Milburn { PCI_VDEVICE(INTEL, 0x3b23), board_ahci }, /* PCH AHCI */ 228adcb5308SSeth Heasley { PCI_VDEVICE(INTEL, 0x3b24), board_ahci }, /* PCH RAID */ 2298e48b6b3SSeth Heasley { PCI_VDEVICE(INTEL, 0x3b25), board_ahci }, /* PCH RAID */ 230c1f57d9bSDavid Milburn { PCI_VDEVICE(INTEL, 0x3b29), board_ahci }, /* PCH AHCI */ 231adcb5308SSeth Heasley { PCI_VDEVICE(INTEL, 0x3b2b), board_ahci }, /* PCH RAID */ 2328e48b6b3SSeth Heasley { PCI_VDEVICE(INTEL, 0x3b2c), board_ahci }, /* PCH RAID */ 233c1f57d9bSDavid Milburn { PCI_VDEVICE(INTEL, 0x3b2f), board_ahci }, /* PCH AHCI */ 2345623cab8SSeth Heasley { PCI_VDEVICE(INTEL, 0x1c02), board_ahci }, /* CPT AHCI */ 2355623cab8SSeth Heasley { PCI_VDEVICE(INTEL, 0x1c03), board_ahci }, /* CPT AHCI */ 2365623cab8SSeth Heasley { PCI_VDEVICE(INTEL, 0x1c04), board_ahci }, /* CPT RAID */ 2375623cab8SSeth Heasley { PCI_VDEVICE(INTEL, 0x1c05), board_ahci }, /* CPT RAID */ 2385623cab8SSeth Heasley { PCI_VDEVICE(INTEL, 0x1c06), board_ahci }, /* CPT RAID */ 2395623cab8SSeth Heasley { PCI_VDEVICE(INTEL, 0x1c07), board_ahci }, /* CPT RAID */ 240992b3fb9SSeth Heasley { PCI_VDEVICE(INTEL, 0x1d02), board_ahci }, /* PBG AHCI */ 241992b3fb9SSeth Heasley { PCI_VDEVICE(INTEL, 0x1d04), board_ahci }, /* PBG RAID */ 242992b3fb9SSeth Heasley { PCI_VDEVICE(INTEL, 0x1d06), board_ahci }, /* PBG RAID */ 24364a3903dSSeth Heasley { PCI_VDEVICE(INTEL, 0x2826), board_ahci }, /* PBG RAID */ 244a4a461a6SSeth Heasley { PCI_VDEVICE(INTEL, 0x2323), board_ahci }, /* DH89xxCC AHCI */ 245181e3ceaSSeth Heasley { PCI_VDEVICE(INTEL, 0x1e02), board_ahci }, /* Panther Point AHCI */ 246181e3ceaSSeth Heasley { PCI_VDEVICE(INTEL, 0x1e03), board_ahci }, /* Panther Point AHCI */ 247181e3ceaSSeth Heasley { PCI_VDEVICE(INTEL, 0x1e04), board_ahci }, /* Panther Point RAID */ 248181e3ceaSSeth Heasley { PCI_VDEVICE(INTEL, 0x1e05), board_ahci }, /* Panther Point RAID */ 249181e3ceaSSeth Heasley { PCI_VDEVICE(INTEL, 0x1e06), board_ahci }, /* Panther Point RAID */ 250181e3ceaSSeth Heasley { PCI_VDEVICE(INTEL, 0x1e07), board_ahci }, /* Panther Point RAID */ 2512cab7a4cSSeth Heasley { PCI_VDEVICE(INTEL, 0x1e0e), board_ahci }, /* Panther Point RAID */ 252ea4ace66SSeth Heasley { PCI_VDEVICE(INTEL, 0x8c02), board_ahci }, /* Lynx Point AHCI */ 253ea4ace66SSeth Heasley { PCI_VDEVICE(INTEL, 0x8c03), board_ahci }, /* Lynx Point AHCI */ 254ea4ace66SSeth Heasley { PCI_VDEVICE(INTEL, 0x8c04), board_ahci }, /* Lynx Point RAID */ 255ea4ace66SSeth Heasley { PCI_VDEVICE(INTEL, 0x8c05), board_ahci }, /* Lynx Point RAID */ 256ea4ace66SSeth Heasley { PCI_VDEVICE(INTEL, 0x8c06), board_ahci }, /* Lynx Point RAID */ 257ea4ace66SSeth Heasley { PCI_VDEVICE(INTEL, 0x8c07), board_ahci }, /* Lynx Point RAID */ 258ea4ace66SSeth Heasley { PCI_VDEVICE(INTEL, 0x8c0e), board_ahci }, /* Lynx Point RAID */ 259ea4ace66SSeth Heasley { PCI_VDEVICE(INTEL, 0x8c0f), board_ahci }, /* Lynx Point RAID */ 26077b12bc9SJames Ralston { PCI_VDEVICE(INTEL, 0x9c02), board_ahci }, /* Lynx Point-LP AHCI */ 26177b12bc9SJames Ralston { PCI_VDEVICE(INTEL, 0x9c03), board_ahci }, /* Lynx Point-LP AHCI */ 26277b12bc9SJames Ralston { PCI_VDEVICE(INTEL, 0x9c04), board_ahci }, /* Lynx Point-LP RAID */ 26377b12bc9SJames Ralston { PCI_VDEVICE(INTEL, 0x9c05), board_ahci }, /* Lynx Point-LP RAID */ 26477b12bc9SJames Ralston { PCI_VDEVICE(INTEL, 0x9c06), board_ahci }, /* Lynx Point-LP RAID */ 26577b12bc9SJames Ralston { PCI_VDEVICE(INTEL, 0x9c07), board_ahci }, /* Lynx Point-LP RAID */ 26677b12bc9SJames Ralston { PCI_VDEVICE(INTEL, 0x9c0e), board_ahci }, /* Lynx Point-LP RAID */ 26777b12bc9SJames Ralston { PCI_VDEVICE(INTEL, 0x9c0f), board_ahci }, /* Lynx Point-LP RAID */ 26829e674ddSSeth Heasley { PCI_VDEVICE(INTEL, 0x1f22), board_ahci }, /* Avoton AHCI */ 26929e674ddSSeth Heasley { PCI_VDEVICE(INTEL, 0x1f23), board_ahci }, /* Avoton AHCI */ 27029e674ddSSeth Heasley { PCI_VDEVICE(INTEL, 0x1f24), board_ahci }, /* Avoton RAID */ 27129e674ddSSeth Heasley { PCI_VDEVICE(INTEL, 0x1f25), board_ahci }, /* Avoton RAID */ 27229e674ddSSeth Heasley { PCI_VDEVICE(INTEL, 0x1f26), board_ahci }, /* Avoton RAID */ 27329e674ddSSeth Heasley { PCI_VDEVICE(INTEL, 0x1f27), board_ahci }, /* Avoton RAID */ 27429e674ddSSeth Heasley { PCI_VDEVICE(INTEL, 0x1f2e), board_ahci }, /* Avoton RAID */ 27529e674ddSSeth Heasley { PCI_VDEVICE(INTEL, 0x1f2f), board_ahci }, /* Avoton RAID */ 27629e674ddSSeth Heasley { PCI_VDEVICE(INTEL, 0x1f32), board_ahci }, /* Avoton AHCI */ 27729e674ddSSeth Heasley { PCI_VDEVICE(INTEL, 0x1f33), board_ahci }, /* Avoton AHCI */ 27829e674ddSSeth Heasley { PCI_VDEVICE(INTEL, 0x1f34), board_ahci }, /* Avoton RAID */ 27929e674ddSSeth Heasley { PCI_VDEVICE(INTEL, 0x1f35), board_ahci }, /* Avoton RAID */ 28029e674ddSSeth Heasley { PCI_VDEVICE(INTEL, 0x1f36), board_ahci }, /* Avoton RAID */ 28129e674ddSSeth Heasley { PCI_VDEVICE(INTEL, 0x1f37), board_ahci }, /* Avoton RAID */ 28229e674ddSSeth Heasley { PCI_VDEVICE(INTEL, 0x1f3e), board_ahci }, /* Avoton RAID */ 28329e674ddSSeth Heasley { PCI_VDEVICE(INTEL, 0x1f3f), board_ahci }, /* Avoton RAID */ 284efda332cSJames Ralston { PCI_VDEVICE(INTEL, 0x2823), board_ahci }, /* Wellsburg RAID */ 285efda332cSJames Ralston { PCI_VDEVICE(INTEL, 0x2827), board_ahci }, /* Wellsburg RAID */ 286151743fdSJames Ralston { PCI_VDEVICE(INTEL, 0x8d02), board_ahci }, /* Wellsburg AHCI */ 287151743fdSJames Ralston { PCI_VDEVICE(INTEL, 0x8d04), board_ahci }, /* Wellsburg RAID */ 288151743fdSJames Ralston { PCI_VDEVICE(INTEL, 0x8d06), board_ahci }, /* Wellsburg RAID */ 289151743fdSJames Ralston { PCI_VDEVICE(INTEL, 0x8d0e), board_ahci }, /* Wellsburg RAID */ 290151743fdSJames Ralston { PCI_VDEVICE(INTEL, 0x8d62), board_ahci }, /* Wellsburg AHCI */ 291151743fdSJames Ralston { PCI_VDEVICE(INTEL, 0x8d64), board_ahci }, /* Wellsburg RAID */ 292151743fdSJames Ralston { PCI_VDEVICE(INTEL, 0x8d66), board_ahci }, /* Wellsburg RAID */ 293151743fdSJames Ralston { PCI_VDEVICE(INTEL, 0x8d6e), board_ahci }, /* Wellsburg RAID */ 294c6fd2807SJeff Garzik 295e34bb370STejun Heo /* JMicron 360/1/3/5/6, match class to avoid IDE function */ 296e34bb370STejun Heo { PCI_VENDOR_ID_JMICRON, PCI_ANY_ID, PCI_ANY_ID, PCI_ANY_ID, 297e34bb370STejun Heo PCI_CLASS_STORAGE_SATA_AHCI, 0xffffff, board_ahci_ign_iferr }, 2981fefb8fdSBen Hutchings /* JMicron 362B and 362C have an AHCI function with IDE class code */ 2991fefb8fdSBen Hutchings { PCI_VDEVICE(JMICRON, 0x2362), board_ahci_ign_iferr }, 3001fefb8fdSBen Hutchings { PCI_VDEVICE(JMICRON, 0x236f), board_ahci_ign_iferr }, 301c6fd2807SJeff Garzik 302c6fd2807SJeff Garzik /* ATI */ 303c65ec1c2SConke Hu { PCI_VDEVICE(ATI, 0x4380), board_ahci_sb600 }, /* ATI SB600 */ 304e39fc8c9SShane Huang { PCI_VDEVICE(ATI, 0x4390), board_ahci_sb700 }, /* ATI SB700/800 */ 305e39fc8c9SShane Huang { PCI_VDEVICE(ATI, 0x4391), board_ahci_sb700 }, /* ATI SB700/800 */ 306e39fc8c9SShane Huang { PCI_VDEVICE(ATI, 0x4392), board_ahci_sb700 }, /* ATI SB700/800 */ 307e39fc8c9SShane Huang { PCI_VDEVICE(ATI, 0x4393), board_ahci_sb700 }, /* ATI SB700/800 */ 308e39fc8c9SShane Huang { PCI_VDEVICE(ATI, 0x4394), board_ahci_sb700 }, /* ATI SB700/800 */ 309e39fc8c9SShane Huang { PCI_VDEVICE(ATI, 0x4395), board_ahci_sb700 }, /* ATI SB700/800 */ 310c6fd2807SJeff Garzik 311e2dd90b1SShane Huang /* AMD */ 3125deab536SShane Huang { PCI_VDEVICE(AMD, 0x7800), board_ahci }, /* AMD Hudson-2 */ 313e2dd90b1SShane Huang /* AMD is using RAID class only for ahci controllers */ 314e2dd90b1SShane Huang { PCI_VENDOR_ID_AMD, PCI_ANY_ID, PCI_ANY_ID, PCI_ANY_ID, 315e2dd90b1SShane Huang PCI_CLASS_STORAGE_RAID << 8, 0xffffff, board_ahci }, 316e2dd90b1SShane Huang 317c6fd2807SJeff Garzik /* VIA */ 31854bb3a94SJeff Garzik { PCI_VDEVICE(VIA, 0x3349), board_ahci_vt8251 }, /* VIA VT8251 */ 319bf335542STejun Heo { PCI_VDEVICE(VIA, 0x6287), board_ahci_vt8251 }, /* VIA VT8251 */ 320c6fd2807SJeff Garzik 321c6fd2807SJeff Garzik /* NVIDIA */ 322e297d99eSTejun Heo { PCI_VDEVICE(NVIDIA, 0x044c), board_ahci_mcp65 }, /* MCP65 */ 323e297d99eSTejun Heo { PCI_VDEVICE(NVIDIA, 0x044d), board_ahci_mcp65 }, /* MCP65 */ 324e297d99eSTejun Heo { PCI_VDEVICE(NVIDIA, 0x044e), board_ahci_mcp65 }, /* MCP65 */ 325e297d99eSTejun Heo { PCI_VDEVICE(NVIDIA, 0x044f), board_ahci_mcp65 }, /* MCP65 */ 326e297d99eSTejun Heo { PCI_VDEVICE(NVIDIA, 0x045c), board_ahci_mcp65 }, /* MCP65 */ 327e297d99eSTejun Heo { PCI_VDEVICE(NVIDIA, 0x045d), board_ahci_mcp65 }, /* MCP65 */ 328e297d99eSTejun Heo { PCI_VDEVICE(NVIDIA, 0x045e), board_ahci_mcp65 }, /* MCP65 */ 329e297d99eSTejun Heo { PCI_VDEVICE(NVIDIA, 0x045f), board_ahci_mcp65 }, /* MCP65 */ 330441577efSTejun Heo { PCI_VDEVICE(NVIDIA, 0x0550), board_ahci_mcp67 }, /* MCP67 */ 331441577efSTejun Heo { PCI_VDEVICE(NVIDIA, 0x0551), board_ahci_mcp67 }, /* MCP67 */ 332441577efSTejun Heo { PCI_VDEVICE(NVIDIA, 0x0552), board_ahci_mcp67 }, /* MCP67 */ 333441577efSTejun Heo { PCI_VDEVICE(NVIDIA, 0x0553), board_ahci_mcp67 }, /* MCP67 */ 334441577efSTejun Heo { PCI_VDEVICE(NVIDIA, 0x0554), board_ahci_mcp67 }, /* MCP67 */ 335441577efSTejun Heo { PCI_VDEVICE(NVIDIA, 0x0555), board_ahci_mcp67 }, /* MCP67 */ 336441577efSTejun Heo { PCI_VDEVICE(NVIDIA, 0x0556), board_ahci_mcp67 }, /* MCP67 */ 337441577efSTejun Heo { PCI_VDEVICE(NVIDIA, 0x0557), board_ahci_mcp67 }, /* MCP67 */ 338441577efSTejun Heo { PCI_VDEVICE(NVIDIA, 0x0558), board_ahci_mcp67 }, /* MCP67 */ 339441577efSTejun Heo { PCI_VDEVICE(NVIDIA, 0x0559), board_ahci_mcp67 }, /* MCP67 */ 340441577efSTejun Heo { PCI_VDEVICE(NVIDIA, 0x055a), board_ahci_mcp67 }, /* MCP67 */ 341441577efSTejun Heo { PCI_VDEVICE(NVIDIA, 0x055b), board_ahci_mcp67 }, /* MCP67 */ 342441577efSTejun Heo { PCI_VDEVICE(NVIDIA, 0x0580), board_ahci_mcp_linux }, /* Linux ID */ 343441577efSTejun Heo { PCI_VDEVICE(NVIDIA, 0x0581), board_ahci_mcp_linux }, /* Linux ID */ 344441577efSTejun Heo { PCI_VDEVICE(NVIDIA, 0x0582), board_ahci_mcp_linux }, /* Linux ID */ 345441577efSTejun Heo { PCI_VDEVICE(NVIDIA, 0x0583), board_ahci_mcp_linux }, /* Linux ID */ 346441577efSTejun Heo { PCI_VDEVICE(NVIDIA, 0x0584), board_ahci_mcp_linux }, /* Linux ID */ 347441577efSTejun Heo { PCI_VDEVICE(NVIDIA, 0x0585), board_ahci_mcp_linux }, /* Linux ID */ 348441577efSTejun Heo { PCI_VDEVICE(NVIDIA, 0x0586), board_ahci_mcp_linux }, /* Linux ID */ 349441577efSTejun Heo { PCI_VDEVICE(NVIDIA, 0x0587), board_ahci_mcp_linux }, /* Linux ID */ 350441577efSTejun Heo { PCI_VDEVICE(NVIDIA, 0x0588), board_ahci_mcp_linux }, /* Linux ID */ 351441577efSTejun Heo { PCI_VDEVICE(NVIDIA, 0x0589), board_ahci_mcp_linux }, /* Linux ID */ 352441577efSTejun Heo { PCI_VDEVICE(NVIDIA, 0x058a), board_ahci_mcp_linux }, /* Linux ID */ 353441577efSTejun Heo { PCI_VDEVICE(NVIDIA, 0x058b), board_ahci_mcp_linux }, /* Linux ID */ 354441577efSTejun Heo { PCI_VDEVICE(NVIDIA, 0x058c), board_ahci_mcp_linux }, /* Linux ID */ 355441577efSTejun Heo { PCI_VDEVICE(NVIDIA, 0x058d), board_ahci_mcp_linux }, /* Linux ID */ 356441577efSTejun Heo { PCI_VDEVICE(NVIDIA, 0x058e), board_ahci_mcp_linux }, /* Linux ID */ 357441577efSTejun Heo { PCI_VDEVICE(NVIDIA, 0x058f), board_ahci_mcp_linux }, /* Linux ID */ 358441577efSTejun Heo { PCI_VDEVICE(NVIDIA, 0x07f0), board_ahci_mcp73 }, /* MCP73 */ 359441577efSTejun Heo { PCI_VDEVICE(NVIDIA, 0x07f1), board_ahci_mcp73 }, /* MCP73 */ 360441577efSTejun Heo { PCI_VDEVICE(NVIDIA, 0x07f2), board_ahci_mcp73 }, /* MCP73 */ 361441577efSTejun Heo { PCI_VDEVICE(NVIDIA, 0x07f3), board_ahci_mcp73 }, /* MCP73 */ 362441577efSTejun Heo { PCI_VDEVICE(NVIDIA, 0x07f4), board_ahci_mcp73 }, /* MCP73 */ 363441577efSTejun Heo { PCI_VDEVICE(NVIDIA, 0x07f5), board_ahci_mcp73 }, /* MCP73 */ 364441577efSTejun Heo { PCI_VDEVICE(NVIDIA, 0x07f6), board_ahci_mcp73 }, /* MCP73 */ 365441577efSTejun Heo { PCI_VDEVICE(NVIDIA, 0x07f7), board_ahci_mcp73 }, /* MCP73 */ 366441577efSTejun Heo { PCI_VDEVICE(NVIDIA, 0x07f8), board_ahci_mcp73 }, /* MCP73 */ 367441577efSTejun Heo { PCI_VDEVICE(NVIDIA, 0x07f9), board_ahci_mcp73 }, /* MCP73 */ 368441577efSTejun Heo { PCI_VDEVICE(NVIDIA, 0x07fa), board_ahci_mcp73 }, /* MCP73 */ 369441577efSTejun Heo { PCI_VDEVICE(NVIDIA, 0x07fb), board_ahci_mcp73 }, /* MCP73 */ 370441577efSTejun Heo { PCI_VDEVICE(NVIDIA, 0x0ad0), board_ahci_mcp77 }, /* MCP77 */ 371441577efSTejun Heo { PCI_VDEVICE(NVIDIA, 0x0ad1), board_ahci_mcp77 }, /* MCP77 */ 372441577efSTejun Heo { PCI_VDEVICE(NVIDIA, 0x0ad2), board_ahci_mcp77 }, /* MCP77 */ 373441577efSTejun Heo { PCI_VDEVICE(NVIDIA, 0x0ad3), board_ahci_mcp77 }, /* MCP77 */ 374441577efSTejun Heo { PCI_VDEVICE(NVIDIA, 0x0ad4), board_ahci_mcp77 }, /* MCP77 */ 375441577efSTejun Heo { PCI_VDEVICE(NVIDIA, 0x0ad5), board_ahci_mcp77 }, /* MCP77 */ 376441577efSTejun Heo { PCI_VDEVICE(NVIDIA, 0x0ad6), board_ahci_mcp77 }, /* MCP77 */ 377441577efSTejun Heo { PCI_VDEVICE(NVIDIA, 0x0ad7), board_ahci_mcp77 }, /* MCP77 */ 378441577efSTejun Heo { PCI_VDEVICE(NVIDIA, 0x0ad8), board_ahci_mcp77 }, /* MCP77 */ 379441577efSTejun Heo { PCI_VDEVICE(NVIDIA, 0x0ad9), board_ahci_mcp77 }, /* MCP77 */ 380441577efSTejun Heo { PCI_VDEVICE(NVIDIA, 0x0ada), board_ahci_mcp77 }, /* MCP77 */ 381441577efSTejun Heo { PCI_VDEVICE(NVIDIA, 0x0adb), board_ahci_mcp77 }, /* MCP77 */ 382441577efSTejun Heo { PCI_VDEVICE(NVIDIA, 0x0ab4), board_ahci_mcp79 }, /* MCP79 */ 383441577efSTejun Heo { PCI_VDEVICE(NVIDIA, 0x0ab5), board_ahci_mcp79 }, /* MCP79 */ 384441577efSTejun Heo { PCI_VDEVICE(NVIDIA, 0x0ab6), board_ahci_mcp79 }, /* MCP79 */ 385441577efSTejun Heo { PCI_VDEVICE(NVIDIA, 0x0ab7), board_ahci_mcp79 }, /* MCP79 */ 386441577efSTejun Heo { PCI_VDEVICE(NVIDIA, 0x0ab8), board_ahci_mcp79 }, /* MCP79 */ 387441577efSTejun Heo { PCI_VDEVICE(NVIDIA, 0x0ab9), board_ahci_mcp79 }, /* MCP79 */ 388441577efSTejun Heo { PCI_VDEVICE(NVIDIA, 0x0aba), board_ahci_mcp79 }, /* MCP79 */ 389441577efSTejun Heo { PCI_VDEVICE(NVIDIA, 0x0abb), board_ahci_mcp79 }, /* MCP79 */ 390441577efSTejun Heo { PCI_VDEVICE(NVIDIA, 0x0abc), board_ahci_mcp79 }, /* MCP79 */ 391441577efSTejun Heo { PCI_VDEVICE(NVIDIA, 0x0abd), board_ahci_mcp79 }, /* MCP79 */ 392441577efSTejun Heo { PCI_VDEVICE(NVIDIA, 0x0abe), board_ahci_mcp79 }, /* MCP79 */ 393441577efSTejun Heo { PCI_VDEVICE(NVIDIA, 0x0abf), board_ahci_mcp79 }, /* MCP79 */ 394441577efSTejun Heo { PCI_VDEVICE(NVIDIA, 0x0d84), board_ahci_mcp89 }, /* MCP89 */ 395441577efSTejun Heo { PCI_VDEVICE(NVIDIA, 0x0d85), board_ahci_mcp89 }, /* MCP89 */ 396441577efSTejun Heo { PCI_VDEVICE(NVIDIA, 0x0d86), board_ahci_mcp89 }, /* MCP89 */ 397441577efSTejun Heo { PCI_VDEVICE(NVIDIA, 0x0d87), board_ahci_mcp89 }, /* MCP89 */ 398441577efSTejun Heo { PCI_VDEVICE(NVIDIA, 0x0d88), board_ahci_mcp89 }, /* MCP89 */ 399441577efSTejun Heo { PCI_VDEVICE(NVIDIA, 0x0d89), board_ahci_mcp89 }, /* MCP89 */ 400441577efSTejun Heo { PCI_VDEVICE(NVIDIA, 0x0d8a), board_ahci_mcp89 }, /* MCP89 */ 401441577efSTejun Heo { PCI_VDEVICE(NVIDIA, 0x0d8b), board_ahci_mcp89 }, /* MCP89 */ 402441577efSTejun Heo { PCI_VDEVICE(NVIDIA, 0x0d8c), board_ahci_mcp89 }, /* MCP89 */ 403441577efSTejun Heo { PCI_VDEVICE(NVIDIA, 0x0d8d), board_ahci_mcp89 }, /* MCP89 */ 404441577efSTejun Heo { PCI_VDEVICE(NVIDIA, 0x0d8e), board_ahci_mcp89 }, /* MCP89 */ 405441577efSTejun Heo { PCI_VDEVICE(NVIDIA, 0x0d8f), board_ahci_mcp89 }, /* MCP89 */ 406c6fd2807SJeff Garzik 407c6fd2807SJeff Garzik /* SiS */ 40820e2de4aSTejun Heo { PCI_VDEVICE(SI, 0x1184), board_ahci }, /* SiS 966 */ 40920e2de4aSTejun Heo { PCI_VDEVICE(SI, 0x1185), board_ahci }, /* SiS 968 */ 41020e2de4aSTejun Heo { PCI_VDEVICE(SI, 0x0186), board_ahci }, /* SiS 968 */ 411c6fd2807SJeff Garzik 412318893e1SAlessandro Rubini /* ST Microelectronics */ 413318893e1SAlessandro Rubini { PCI_VDEVICE(STMICRO, 0xCC06), board_ahci }, /* ST ConneXt */ 414318893e1SAlessandro Rubini 415cd70c266SJeff Garzik /* Marvell */ 416cd70c266SJeff Garzik { PCI_VDEVICE(MARVELL, 0x6145), board_ahci_mv }, /* 6145 */ 417c40e7cb8SJose Alberto Reguero { PCI_VDEVICE(MARVELL, 0x6121), board_ahci_mv }, /* 6121 */ 41869fd3157SMyron Stowe { PCI_DEVICE(PCI_VENDOR_ID_MARVELL_EXT, 0x9123), 41910aca06cSAnssi Hannula .class = PCI_CLASS_STORAGE_SATA_AHCI, 42010aca06cSAnssi Hannula .class_mask = 0xffffff, 4215f173107STejun Heo .driver_data = board_ahci_yes_fbs }, /* 88se9128 */ 42269fd3157SMyron Stowe { PCI_DEVICE(PCI_VENDOR_ID_MARVELL_EXT, 0x9125), 423467b41c6SPer Jessen .driver_data = board_ahci_yes_fbs }, /* 88se9125 */ 42469fd3157SMyron Stowe { PCI_DEVICE(PCI_VENDOR_ID_MARVELL_EXT, 0x917a), 425642d8925SMatt Johnson .driver_data = board_ahci_yes_fbs }, /* 88se9172 */ 42669fd3157SMyron Stowe { PCI_DEVICE(PCI_VENDOR_ID_MARVELL_EXT, 0x9192), 42717c60c6bSAlan Cox .driver_data = board_ahci_yes_fbs }, /* 88se9172 on some Gigabyte */ 42869fd3157SMyron Stowe { PCI_DEVICE(PCI_VENDOR_ID_MARVELL_EXT, 0x91a3), 42950be5e36STejun Heo .driver_data = board_ahci_yes_fbs }, 430cd70c266SJeff Garzik 431c77a036bSMark Nelson /* Promise */ 432c77a036bSMark Nelson { PCI_VDEVICE(PROMISE, 0x3f20), board_ahci }, /* PDC42819 */ 433c77a036bSMark Nelson 434c9703765SKeng-Yu Lin /* Asmedia */ 4357b4f6ecaSAlan Cox { PCI_VDEVICE(ASMEDIA, 0x0601), board_ahci }, /* ASM1060 */ 4367b4f6ecaSAlan Cox { PCI_VDEVICE(ASMEDIA, 0x0602), board_ahci }, /* ASM1060 */ 4377b4f6ecaSAlan Cox { PCI_VDEVICE(ASMEDIA, 0x0611), board_ahci }, /* ASM1061 */ 4387b4f6ecaSAlan Cox { PCI_VDEVICE(ASMEDIA, 0x0612), board_ahci }, /* ASM1062 */ 439c9703765SKeng-Yu Lin 4407f9c9f8eSHugh Daschbach /* Enmotus */ 4417f9c9f8eSHugh Daschbach { PCI_DEVICE(0x1c44, 0x8000), board_ahci }, 4427f9c9f8eSHugh Daschbach 443415ae2b5SJeff Garzik /* Generic, PCI class code for AHCI */ 444415ae2b5SJeff Garzik { PCI_ANY_ID, PCI_ANY_ID, PCI_ANY_ID, PCI_ANY_ID, 445c9f89475SConke Hu PCI_CLASS_STORAGE_SATA_AHCI, 0xffffff, board_ahci }, 446415ae2b5SJeff Garzik 447c6fd2807SJeff Garzik { } /* terminate list */ 448c6fd2807SJeff Garzik }; 449c6fd2807SJeff Garzik 450c6fd2807SJeff Garzik 451c6fd2807SJeff Garzik static struct pci_driver ahci_pci_driver = { 452c6fd2807SJeff Garzik .name = DRV_NAME, 453c6fd2807SJeff Garzik .id_table = ahci_pci_tbl, 454c6fd2807SJeff Garzik .probe = ahci_init_one, 45524dc5f33STejun Heo .remove = ata_pci_remove_one, 456438ac6d5STejun Heo #ifdef CONFIG_PM 457c6fd2807SJeff Garzik .suspend = ahci_pci_device_suspend, 458c6fd2807SJeff Garzik .resume = ahci_pci_device_resume, 459438ac6d5STejun Heo #endif 460c6fd2807SJeff Garzik }; 461c6fd2807SJeff Garzik 4625b66c829SAlan Cox #if defined(CONFIG_PATA_MARVELL) || defined(CONFIG_PATA_MARVELL_MODULE) 4635b66c829SAlan Cox static int marvell_enable; 4645b66c829SAlan Cox #else 4655b66c829SAlan Cox static int marvell_enable = 1; 4665b66c829SAlan Cox #endif 4675b66c829SAlan Cox module_param(marvell_enable, int, 0644); 4685b66c829SAlan Cox MODULE_PARM_DESC(marvell_enable, "Marvell SATA via AHCI (1 = enabled)"); 4695b66c829SAlan Cox 4705b66c829SAlan Cox 471394d6e53SAnton Vorontsov static void ahci_pci_save_initial_config(struct pci_dev *pdev, 472394d6e53SAnton Vorontsov struct ahci_host_priv *hpriv) 473394d6e53SAnton Vorontsov { 474394d6e53SAnton Vorontsov unsigned int force_port_map = 0; 475394d6e53SAnton Vorontsov unsigned int mask_port_map = 0; 476394d6e53SAnton Vorontsov 477394d6e53SAnton Vorontsov if (pdev->vendor == PCI_VENDOR_ID_JMICRON && pdev->device == 0x2361) { 478394d6e53SAnton Vorontsov dev_info(&pdev->dev, "JMB361 has only one port\n"); 479394d6e53SAnton Vorontsov force_port_map = 1; 480394d6e53SAnton Vorontsov } 481394d6e53SAnton Vorontsov 482394d6e53SAnton Vorontsov /* 483394d6e53SAnton Vorontsov * Temporary Marvell 6145 hack: PATA port presence 484394d6e53SAnton Vorontsov * is asserted through the standard AHCI port 485394d6e53SAnton Vorontsov * presence register, as bit 4 (counting from 0) 486394d6e53SAnton Vorontsov */ 487394d6e53SAnton Vorontsov if (hpriv->flags & AHCI_HFLAG_MV_PATA) { 488394d6e53SAnton Vorontsov if (pdev->device == 0x6121) 489394d6e53SAnton Vorontsov mask_port_map = 0x3; 490394d6e53SAnton Vorontsov else 491394d6e53SAnton Vorontsov mask_port_map = 0xf; 492394d6e53SAnton Vorontsov dev_info(&pdev->dev, 493394d6e53SAnton Vorontsov "Disabling your PATA port. Use the boot option 'ahci.marvell_enable=0' to avoid this.\n"); 494394d6e53SAnton Vorontsov } 495394d6e53SAnton Vorontsov 4961d513358SAnton Vorontsov ahci_save_initial_config(&pdev->dev, hpriv, force_port_map, 4971d513358SAnton Vorontsov mask_port_map); 498394d6e53SAnton Vorontsov } 499394d6e53SAnton Vorontsov 5003303040dSAnton Vorontsov static int ahci_pci_reset_controller(struct ata_host *host) 5013303040dSAnton Vorontsov { 5023303040dSAnton Vorontsov struct pci_dev *pdev = to_pci_dev(host->dev); 5033303040dSAnton Vorontsov 5043303040dSAnton Vorontsov ahci_reset_controller(host); 5053303040dSAnton Vorontsov 506c6fd2807SJeff Garzik if (pdev->vendor == PCI_VENDOR_ID_INTEL) { 5073303040dSAnton Vorontsov struct ahci_host_priv *hpriv = host->private_data; 508c6fd2807SJeff Garzik u16 tmp16; 509c6fd2807SJeff Garzik 510c6fd2807SJeff Garzik /* configure PCS */ 511c6fd2807SJeff Garzik pci_read_config_word(pdev, 0x92, &tmp16); 51249f29090STejun Heo if ((tmp16 & hpriv->port_map) != hpriv->port_map) { 51349f29090STejun Heo tmp16 |= hpriv->port_map; 514c6fd2807SJeff Garzik pci_write_config_word(pdev, 0x92, tmp16); 515c6fd2807SJeff Garzik } 51649f29090STejun Heo } 517c6fd2807SJeff Garzik 518c6fd2807SJeff Garzik return 0; 519c6fd2807SJeff Garzik } 520c6fd2807SJeff Garzik 521781d6550SAnton Vorontsov static void ahci_pci_init_controller(struct ata_host *host) 522781d6550SAnton Vorontsov { 523781d6550SAnton Vorontsov struct ahci_host_priv *hpriv = host->private_data; 524781d6550SAnton Vorontsov struct pci_dev *pdev = to_pci_dev(host->dev); 525781d6550SAnton Vorontsov void __iomem *port_mmio; 526781d6550SAnton Vorontsov u32 tmp; 527c40e7cb8SJose Alberto Reguero int mv; 5282bcd866bSJeff Garzik 529417a1a6dSTejun Heo if (hpriv->flags & AHCI_HFLAG_MV_PATA) { 530c40e7cb8SJose Alberto Reguero if (pdev->device == 0x6121) 531c40e7cb8SJose Alberto Reguero mv = 2; 532c40e7cb8SJose Alberto Reguero else 533c40e7cb8SJose Alberto Reguero mv = 4; 534c40e7cb8SJose Alberto Reguero port_mmio = __ahci_port_base(host, mv); 535cd70c266SJeff Garzik 536cd70c266SJeff Garzik writel(0, port_mmio + PORT_IRQ_MASK); 537cd70c266SJeff Garzik 538cd70c266SJeff Garzik /* clear port IRQ */ 539cd70c266SJeff Garzik tmp = readl(port_mmio + PORT_IRQ_STAT); 540cd70c266SJeff Garzik VPRINTK("PORT_IRQ_STAT 0x%x\n", tmp); 541cd70c266SJeff Garzik if (tmp) 542cd70c266SJeff Garzik writel(tmp, port_mmio + PORT_IRQ_STAT); 543cd70c266SJeff Garzik } 544cd70c266SJeff Garzik 545781d6550SAnton Vorontsov ahci_init_controller(host); 546c6fd2807SJeff Garzik } 547c6fd2807SJeff Garzik 548cc0680a5STejun Heo static int ahci_vt8251_hardreset(struct ata_link *link, unsigned int *class, 549d4b2bab4STejun Heo unsigned long deadline) 550ad616ffbSTejun Heo { 551cc0680a5STejun Heo struct ata_port *ap = link->ap; 5529dadd45bSTejun Heo bool online; 553ad616ffbSTejun Heo int rc; 554ad616ffbSTejun Heo 555ad616ffbSTejun Heo DPRINTK("ENTER\n"); 556ad616ffbSTejun Heo 5574447d351STejun Heo ahci_stop_engine(ap); 558ad616ffbSTejun Heo 559cc0680a5STejun Heo rc = sata_link_hardreset(link, sata_ehc_deb_timing(&link->eh_context), 5609dadd45bSTejun Heo deadline, &online, NULL); 561ad616ffbSTejun Heo 5624447d351STejun Heo ahci_start_engine(ap); 563ad616ffbSTejun Heo 564ad616ffbSTejun Heo DPRINTK("EXIT, rc=%d, class=%u\n", rc, *class); 565ad616ffbSTejun Heo 566ad616ffbSTejun Heo /* vt8251 doesn't clear BSY on signature FIS reception, 567ad616ffbSTejun Heo * request follow-up softreset. 568ad616ffbSTejun Heo */ 5699dadd45bSTejun Heo return online ? -EAGAIN : rc; 570ad616ffbSTejun Heo } 571ad616ffbSTejun Heo 572edc93052STejun Heo static int ahci_p5wdh_hardreset(struct ata_link *link, unsigned int *class, 573edc93052STejun Heo unsigned long deadline) 574edc93052STejun Heo { 575edc93052STejun Heo struct ata_port *ap = link->ap; 576edc93052STejun Heo struct ahci_port_priv *pp = ap->private_data; 577edc93052STejun Heo u8 *d2h_fis = pp->rx_fis + RX_FIS_D2H_REG; 578edc93052STejun Heo struct ata_taskfile tf; 5799dadd45bSTejun Heo bool online; 580edc93052STejun Heo int rc; 581edc93052STejun Heo 582edc93052STejun Heo ahci_stop_engine(ap); 583edc93052STejun Heo 584edc93052STejun Heo /* clear D2H reception area to properly wait for D2H FIS */ 585edc93052STejun Heo ata_tf_init(link->device, &tf); 586edc93052STejun Heo tf.command = 0x80; 587edc93052STejun Heo ata_tf_to_fis(&tf, 0, 0, d2h_fis); 588edc93052STejun Heo 589edc93052STejun Heo rc = sata_link_hardreset(link, sata_ehc_deb_timing(&link->eh_context), 5909dadd45bSTejun Heo deadline, &online, NULL); 591edc93052STejun Heo 592edc93052STejun Heo ahci_start_engine(ap); 593edc93052STejun Heo 594edc93052STejun Heo /* The pseudo configuration device on SIMG4726 attached to 595edc93052STejun Heo * ASUS P5W-DH Deluxe doesn't send signature FIS after 596edc93052STejun Heo * hardreset if no device is attached to the first downstream 597edc93052STejun Heo * port && the pseudo device locks up on SRST w/ PMP==0. To 598edc93052STejun Heo * work around this, wait for !BSY only briefly. If BSY isn't 599edc93052STejun Heo * cleared, perform CLO and proceed to IDENTIFY (achieved by 600edc93052STejun Heo * ATA_LFLAG_NO_SRST and ATA_LFLAG_ASSUME_ATA). 601edc93052STejun Heo * 602edc93052STejun Heo * Wait for two seconds. Devices attached to downstream port 603edc93052STejun Heo * which can't process the following IDENTIFY after this will 604edc93052STejun Heo * have to be reset again. For most cases, this should 605edc93052STejun Heo * suffice while making probing snappish enough. 606edc93052STejun Heo */ 6079dadd45bSTejun Heo if (online) { 6089dadd45bSTejun Heo rc = ata_wait_after_reset(link, jiffies + 2 * HZ, 6099dadd45bSTejun Heo ahci_check_ready); 610edc93052STejun Heo if (rc) 61178d5ae39SShane Huang ahci_kick_engine(ap); 6129dadd45bSTejun Heo } 6139dadd45bSTejun Heo return rc; 614edc93052STejun Heo } 615edc93052STejun Heo 616438ac6d5STejun Heo #ifdef CONFIG_PM 617c6fd2807SJeff Garzik static int ahci_pci_device_suspend(struct pci_dev *pdev, pm_message_t mesg) 618c6fd2807SJeff Garzik { 619*0a86e1c8SJingoo Han struct ata_host *host = pci_get_drvdata(pdev); 6209b10ae86STejun Heo struct ahci_host_priv *hpriv = host->private_data; 621d8993349SAnton Vorontsov void __iomem *mmio = hpriv->mmio; 622c6fd2807SJeff Garzik u32 ctl; 623c6fd2807SJeff Garzik 6249b10ae86STejun Heo if (mesg.event & PM_EVENT_SUSPEND && 6259b10ae86STejun Heo hpriv->flags & AHCI_HFLAG_NO_SUSPEND) { 626a44fec1fSJoe Perches dev_err(&pdev->dev, 6279b10ae86STejun Heo "BIOS update required for suspend/resume\n"); 6289b10ae86STejun Heo return -EIO; 6299b10ae86STejun Heo } 6309b10ae86STejun Heo 6313a2d5b70SRafael J. Wysocki if (mesg.event & PM_EVENT_SLEEP) { 632c6fd2807SJeff Garzik /* AHCI spec rev1.1 section 8.3.3: 633c6fd2807SJeff Garzik * Software must disable interrupts prior to requesting a 634c6fd2807SJeff Garzik * transition of the HBA to D3 state. 635c6fd2807SJeff Garzik */ 636c6fd2807SJeff Garzik ctl = readl(mmio + HOST_CTL); 637c6fd2807SJeff Garzik ctl &= ~HOST_IRQ_EN; 638c6fd2807SJeff Garzik writel(ctl, mmio + HOST_CTL); 639c6fd2807SJeff Garzik readl(mmio + HOST_CTL); /* flush */ 640c6fd2807SJeff Garzik } 641c6fd2807SJeff Garzik 642c6fd2807SJeff Garzik return ata_pci_device_suspend(pdev, mesg); 643c6fd2807SJeff Garzik } 644c6fd2807SJeff Garzik 645c6fd2807SJeff Garzik static int ahci_pci_device_resume(struct pci_dev *pdev) 646c6fd2807SJeff Garzik { 647*0a86e1c8SJingoo Han struct ata_host *host = pci_get_drvdata(pdev); 648c6fd2807SJeff Garzik int rc; 649c6fd2807SJeff Garzik 650553c4aa6STejun Heo rc = ata_pci_device_do_resume(pdev); 651553c4aa6STejun Heo if (rc) 652553c4aa6STejun Heo return rc; 653c6fd2807SJeff Garzik 654c6fd2807SJeff Garzik if (pdev->dev.power.power_state.event == PM_EVENT_SUSPEND) { 6553303040dSAnton Vorontsov rc = ahci_pci_reset_controller(host); 656c6fd2807SJeff Garzik if (rc) 657c6fd2807SJeff Garzik return rc; 658c6fd2807SJeff Garzik 659781d6550SAnton Vorontsov ahci_pci_init_controller(host); 660c6fd2807SJeff Garzik } 661c6fd2807SJeff Garzik 662cca3974eSJeff Garzik ata_host_resume(host); 663c6fd2807SJeff Garzik 664c6fd2807SJeff Garzik return 0; 665c6fd2807SJeff Garzik } 666438ac6d5STejun Heo #endif 667c6fd2807SJeff Garzik 6684447d351STejun Heo static int ahci_configure_dma_masks(struct pci_dev *pdev, int using_dac) 669c6fd2807SJeff Garzik { 670c6fd2807SJeff Garzik int rc; 671c6fd2807SJeff Garzik 672318893e1SAlessandro Rubini /* 673318893e1SAlessandro Rubini * If the device fixup already set the dma_mask to some non-standard 674318893e1SAlessandro Rubini * value, don't extend it here. This happens on STA2X11, for example. 675318893e1SAlessandro Rubini */ 676318893e1SAlessandro Rubini if (pdev->dma_mask && pdev->dma_mask < DMA_BIT_MASK(32)) 677318893e1SAlessandro Rubini return 0; 678318893e1SAlessandro Rubini 679c6fd2807SJeff Garzik if (using_dac && 6806a35528aSYang Hongyang !pci_set_dma_mask(pdev, DMA_BIT_MASK(64))) { 6816a35528aSYang Hongyang rc = pci_set_consistent_dma_mask(pdev, DMA_BIT_MASK(64)); 682c6fd2807SJeff Garzik if (rc) { 683284901a9SYang Hongyang rc = pci_set_consistent_dma_mask(pdev, DMA_BIT_MASK(32)); 684c6fd2807SJeff Garzik if (rc) { 685a44fec1fSJoe Perches dev_err(&pdev->dev, 686c6fd2807SJeff Garzik "64-bit DMA enable failed\n"); 687c6fd2807SJeff Garzik return rc; 688c6fd2807SJeff Garzik } 689c6fd2807SJeff Garzik } 690c6fd2807SJeff Garzik } else { 691284901a9SYang Hongyang rc = pci_set_dma_mask(pdev, DMA_BIT_MASK(32)); 692c6fd2807SJeff Garzik if (rc) { 693a44fec1fSJoe Perches dev_err(&pdev->dev, "32-bit DMA enable failed\n"); 694c6fd2807SJeff Garzik return rc; 695c6fd2807SJeff Garzik } 696284901a9SYang Hongyang rc = pci_set_consistent_dma_mask(pdev, DMA_BIT_MASK(32)); 697c6fd2807SJeff Garzik if (rc) { 698a44fec1fSJoe Perches dev_err(&pdev->dev, 699c6fd2807SJeff Garzik "32-bit consistent DMA enable failed\n"); 700c6fd2807SJeff Garzik return rc; 701c6fd2807SJeff Garzik } 702c6fd2807SJeff Garzik } 703c6fd2807SJeff Garzik return 0; 704c6fd2807SJeff Garzik } 705c6fd2807SJeff Garzik 706439fcaecSAnton Vorontsov static void ahci_pci_print_info(struct ata_host *host) 707439fcaecSAnton Vorontsov { 708439fcaecSAnton Vorontsov struct pci_dev *pdev = to_pci_dev(host->dev); 709439fcaecSAnton Vorontsov u16 cc; 710439fcaecSAnton Vorontsov const char *scc_s; 711439fcaecSAnton Vorontsov 712439fcaecSAnton Vorontsov pci_read_config_word(pdev, 0x0a, &cc); 713439fcaecSAnton Vorontsov if (cc == PCI_CLASS_STORAGE_IDE) 714439fcaecSAnton Vorontsov scc_s = "IDE"; 715439fcaecSAnton Vorontsov else if (cc == PCI_CLASS_STORAGE_SATA) 716439fcaecSAnton Vorontsov scc_s = "SATA"; 717439fcaecSAnton Vorontsov else if (cc == PCI_CLASS_STORAGE_RAID) 718439fcaecSAnton Vorontsov scc_s = "RAID"; 719439fcaecSAnton Vorontsov else 720439fcaecSAnton Vorontsov scc_s = "unknown"; 721439fcaecSAnton Vorontsov 722439fcaecSAnton Vorontsov ahci_print_info(host, scc_s); 723439fcaecSAnton Vorontsov } 724439fcaecSAnton Vorontsov 725edc93052STejun Heo /* On ASUS P5W DH Deluxe, the second port of PCI device 00:1f.2 is 726edc93052STejun Heo * hardwired to on-board SIMG 4726. The chipset is ICH8 and doesn't 727edc93052STejun Heo * support PMP and the 4726 either directly exports the device 728edc93052STejun Heo * attached to the first downstream port or acts as a hardware storage 729edc93052STejun Heo * controller and emulate a single ATA device (can be RAID 0/1 or some 730edc93052STejun Heo * other configuration). 731edc93052STejun Heo * 732edc93052STejun Heo * When there's no device attached to the first downstream port of the 733edc93052STejun Heo * 4726, "Config Disk" appears, which is a pseudo ATA device to 734edc93052STejun Heo * configure the 4726. However, ATA emulation of the device is very 735edc93052STejun Heo * lame. It doesn't send signature D2H Reg FIS after the initial 736edc93052STejun Heo * hardreset, pukes on SRST w/ PMP==0 and has bunch of other issues. 737edc93052STejun Heo * 738edc93052STejun Heo * The following function works around the problem by always using 739edc93052STejun Heo * hardreset on the port and not depending on receiving signature FIS 740edc93052STejun Heo * afterward. If signature FIS isn't received soon, ATA class is 741edc93052STejun Heo * assumed without follow-up softreset. 742edc93052STejun Heo */ 743edc93052STejun Heo static void ahci_p5wdh_workaround(struct ata_host *host) 744edc93052STejun Heo { 745edc93052STejun Heo static struct dmi_system_id sysids[] = { 746edc93052STejun Heo { 747edc93052STejun Heo .ident = "P5W DH Deluxe", 748edc93052STejun Heo .matches = { 749edc93052STejun Heo DMI_MATCH(DMI_SYS_VENDOR, 750edc93052STejun Heo "ASUSTEK COMPUTER INC"), 751edc93052STejun Heo DMI_MATCH(DMI_PRODUCT_NAME, "P5W DH Deluxe"), 752edc93052STejun Heo }, 753edc93052STejun Heo }, 754edc93052STejun Heo { } 755edc93052STejun Heo }; 756edc93052STejun Heo struct pci_dev *pdev = to_pci_dev(host->dev); 757edc93052STejun Heo 758edc93052STejun Heo if (pdev->bus->number == 0 && pdev->devfn == PCI_DEVFN(0x1f, 2) && 759edc93052STejun Heo dmi_check_system(sysids)) { 760edc93052STejun Heo struct ata_port *ap = host->ports[1]; 761edc93052STejun Heo 762a44fec1fSJoe Perches dev_info(&pdev->dev, 763a44fec1fSJoe Perches "enabling ASUS P5W DH Deluxe on-board SIMG4726 workaround\n"); 764edc93052STejun Heo 765edc93052STejun Heo ap->ops = &ahci_p5wdh_ops; 766edc93052STejun Heo ap->link.flags |= ATA_LFLAG_NO_SRST | ATA_LFLAG_ASSUME_ATA; 767edc93052STejun Heo } 768edc93052STejun Heo } 769edc93052STejun Heo 7702fcad9d2STejun Heo /* only some SB600 ahci controllers can do 64bit DMA */ 7712fcad9d2STejun Heo static bool ahci_sb600_enable_64bit(struct pci_dev *pdev) 77258a09b38SShane Huang { 77358a09b38SShane Huang static const struct dmi_system_id sysids[] = { 77403d783bfSTejun Heo /* 77503d783bfSTejun Heo * The oldest version known to be broken is 0901 and 77603d783bfSTejun Heo * working is 1501 which was released on 2007-10-26. 7772fcad9d2STejun Heo * Enable 64bit DMA on 1501 and anything newer. 7782fcad9d2STejun Heo * 77903d783bfSTejun Heo * Please read bko#9412 for more info. 78003d783bfSTejun Heo */ 78158a09b38SShane Huang { 78258a09b38SShane Huang .ident = "ASUS M2A-VM", 78358a09b38SShane Huang .matches = { 78458a09b38SShane Huang DMI_MATCH(DMI_BOARD_VENDOR, 78558a09b38SShane Huang "ASUSTeK Computer INC."), 78658a09b38SShane Huang DMI_MATCH(DMI_BOARD_NAME, "M2A-VM"), 78758a09b38SShane Huang }, 78803d783bfSTejun Heo .driver_data = "20071026", /* yyyymmdd */ 78958a09b38SShane Huang }, 790e65cc194SMark Nelson /* 791e65cc194SMark Nelson * All BIOS versions for the MSI K9A2 Platinum (MS-7376) 792e65cc194SMark Nelson * support 64bit DMA. 793e65cc194SMark Nelson * 794e65cc194SMark Nelson * BIOS versions earlier than 1.5 had the Manufacturer DMI 795e65cc194SMark Nelson * fields as "MICRO-STAR INTERANTIONAL CO.,LTD". 796e65cc194SMark Nelson * This spelling mistake was fixed in BIOS version 1.5, so 797e65cc194SMark Nelson * 1.5 and later have the Manufacturer as 798e65cc194SMark Nelson * "MICRO-STAR INTERNATIONAL CO.,LTD". 799e65cc194SMark Nelson * So try to match on DMI_BOARD_VENDOR of "MICRO-STAR INTER". 800e65cc194SMark Nelson * 801e65cc194SMark Nelson * BIOS versions earlier than 1.9 had a Board Product Name 802e65cc194SMark Nelson * DMI field of "MS-7376". This was changed to be 803e65cc194SMark Nelson * "K9A2 Platinum (MS-7376)" in version 1.9, but we can still 804e65cc194SMark Nelson * match on DMI_BOARD_NAME of "MS-7376". 805e65cc194SMark Nelson */ 806e65cc194SMark Nelson { 807e65cc194SMark Nelson .ident = "MSI K9A2 Platinum", 808e65cc194SMark Nelson .matches = { 809e65cc194SMark Nelson DMI_MATCH(DMI_BOARD_VENDOR, 810e65cc194SMark Nelson "MICRO-STAR INTER"), 811e65cc194SMark Nelson DMI_MATCH(DMI_BOARD_NAME, "MS-7376"), 812e65cc194SMark Nelson }, 813e65cc194SMark Nelson }, 8143c4aa91fSMark Nelson /* 815ff0173c1SMark Nelson * All BIOS versions for the MSI K9AGM2 (MS-7327) support 816ff0173c1SMark Nelson * 64bit DMA. 817ff0173c1SMark Nelson * 818ff0173c1SMark Nelson * This board also had the typo mentioned above in the 819ff0173c1SMark Nelson * Manufacturer DMI field (fixed in BIOS version 1.5), so 820ff0173c1SMark Nelson * match on DMI_BOARD_VENDOR of "MICRO-STAR INTER" again. 821ff0173c1SMark Nelson */ 822ff0173c1SMark Nelson { 823ff0173c1SMark Nelson .ident = "MSI K9AGM2", 824ff0173c1SMark Nelson .matches = { 825ff0173c1SMark Nelson DMI_MATCH(DMI_BOARD_VENDOR, 826ff0173c1SMark Nelson "MICRO-STAR INTER"), 827ff0173c1SMark Nelson DMI_MATCH(DMI_BOARD_NAME, "MS-7327"), 828ff0173c1SMark Nelson }, 829ff0173c1SMark Nelson }, 830ff0173c1SMark Nelson /* 8313c4aa91fSMark Nelson * All BIOS versions for the Asus M3A support 64bit DMA. 8323c4aa91fSMark Nelson * (all release versions from 0301 to 1206 were tested) 8333c4aa91fSMark Nelson */ 8343c4aa91fSMark Nelson { 8353c4aa91fSMark Nelson .ident = "ASUS M3A", 8363c4aa91fSMark Nelson .matches = { 8373c4aa91fSMark Nelson DMI_MATCH(DMI_BOARD_VENDOR, 8383c4aa91fSMark Nelson "ASUSTeK Computer INC."), 8393c4aa91fSMark Nelson DMI_MATCH(DMI_BOARD_NAME, "M3A"), 8403c4aa91fSMark Nelson }, 8413c4aa91fSMark Nelson }, 84258a09b38SShane Huang { } 84358a09b38SShane Huang }; 84403d783bfSTejun Heo const struct dmi_system_id *match; 8452fcad9d2STejun Heo int year, month, date; 8462fcad9d2STejun Heo char buf[9]; 84758a09b38SShane Huang 84803d783bfSTejun Heo match = dmi_first_match(sysids); 84958a09b38SShane Huang if (pdev->bus->number != 0 || pdev->devfn != PCI_DEVFN(0x12, 0) || 85003d783bfSTejun Heo !match) 85158a09b38SShane Huang return false; 85258a09b38SShane Huang 853e65cc194SMark Nelson if (!match->driver_data) 854e65cc194SMark Nelson goto enable_64bit; 855e65cc194SMark Nelson 85603d783bfSTejun Heo dmi_get_date(DMI_BIOS_DATE, &year, &month, &date); 85703d783bfSTejun Heo snprintf(buf, sizeof(buf), "%04d%02d%02d", year, month, date); 85803d783bfSTejun Heo 859e65cc194SMark Nelson if (strcmp(buf, match->driver_data) >= 0) 860e65cc194SMark Nelson goto enable_64bit; 861e65cc194SMark Nelson else { 862a44fec1fSJoe Perches dev_warn(&pdev->dev, 863a44fec1fSJoe Perches "%s: BIOS too old, forcing 32bit DMA, update BIOS\n", 864a44fec1fSJoe Perches match->ident); 8652fcad9d2STejun Heo return false; 8662fcad9d2STejun Heo } 867e65cc194SMark Nelson 868e65cc194SMark Nelson enable_64bit: 869a44fec1fSJoe Perches dev_warn(&pdev->dev, "%s: enabling 64bit DMA\n", match->ident); 870e65cc194SMark Nelson return true; 87158a09b38SShane Huang } 87258a09b38SShane Huang 8731fd68434SRafael J. Wysocki static bool ahci_broken_system_poweroff(struct pci_dev *pdev) 8741fd68434SRafael J. Wysocki { 8751fd68434SRafael J. Wysocki static const struct dmi_system_id broken_systems[] = { 8761fd68434SRafael J. Wysocki { 8771fd68434SRafael J. Wysocki .ident = "HP Compaq nx6310", 8781fd68434SRafael J. Wysocki .matches = { 8791fd68434SRafael J. Wysocki DMI_MATCH(DMI_SYS_VENDOR, "Hewlett-Packard"), 8801fd68434SRafael J. Wysocki DMI_MATCH(DMI_PRODUCT_NAME, "HP Compaq nx6310"), 8811fd68434SRafael J. Wysocki }, 8821fd68434SRafael J. Wysocki /* PCI slot number of the controller */ 8831fd68434SRafael J. Wysocki .driver_data = (void *)0x1FUL, 8841fd68434SRafael J. Wysocki }, 885d2f9c061SMaciej Rutecki { 886d2f9c061SMaciej Rutecki .ident = "HP Compaq 6720s", 887d2f9c061SMaciej Rutecki .matches = { 888d2f9c061SMaciej Rutecki DMI_MATCH(DMI_SYS_VENDOR, "Hewlett-Packard"), 889d2f9c061SMaciej Rutecki DMI_MATCH(DMI_PRODUCT_NAME, "HP Compaq 6720s"), 890d2f9c061SMaciej Rutecki }, 891d2f9c061SMaciej Rutecki /* PCI slot number of the controller */ 892d2f9c061SMaciej Rutecki .driver_data = (void *)0x1FUL, 893d2f9c061SMaciej Rutecki }, 8941fd68434SRafael J. Wysocki 8951fd68434SRafael J. Wysocki { } /* terminate list */ 8961fd68434SRafael J. Wysocki }; 8971fd68434SRafael J. Wysocki const struct dmi_system_id *dmi = dmi_first_match(broken_systems); 8981fd68434SRafael J. Wysocki 8991fd68434SRafael J. Wysocki if (dmi) { 9001fd68434SRafael J. Wysocki unsigned long slot = (unsigned long)dmi->driver_data; 9011fd68434SRafael J. Wysocki /* apply the quirk only to on-board controllers */ 9021fd68434SRafael J. Wysocki return slot == PCI_SLOT(pdev->devfn); 9031fd68434SRafael J. Wysocki } 9041fd68434SRafael J. Wysocki 9051fd68434SRafael J. Wysocki return false; 9061fd68434SRafael J. Wysocki } 9071fd68434SRafael J. Wysocki 9089b10ae86STejun Heo static bool ahci_broken_suspend(struct pci_dev *pdev) 9099b10ae86STejun Heo { 9109b10ae86STejun Heo static const struct dmi_system_id sysids[] = { 9119b10ae86STejun Heo /* 9129b10ae86STejun Heo * On HP dv[4-6] and HDX18 with earlier BIOSen, link 9139b10ae86STejun Heo * to the harddisk doesn't become online after 9149b10ae86STejun Heo * resuming from STR. Warn and fail suspend. 9159deb3431STejun Heo * 9169deb3431STejun Heo * http://bugzilla.kernel.org/show_bug.cgi?id=12276 9179deb3431STejun Heo * 9189deb3431STejun Heo * Use dates instead of versions to match as HP is 9199deb3431STejun Heo * apparently recycling both product and version 9209deb3431STejun Heo * strings. 9219deb3431STejun Heo * 9229deb3431STejun Heo * http://bugzilla.kernel.org/show_bug.cgi?id=15462 9239b10ae86STejun Heo */ 9249b10ae86STejun Heo { 9259b10ae86STejun Heo .ident = "dv4", 9269b10ae86STejun Heo .matches = { 9279b10ae86STejun Heo DMI_MATCH(DMI_SYS_VENDOR, "Hewlett-Packard"), 9289b10ae86STejun Heo DMI_MATCH(DMI_PRODUCT_NAME, 9299b10ae86STejun Heo "HP Pavilion dv4 Notebook PC"), 9309b10ae86STejun Heo }, 9319deb3431STejun Heo .driver_data = "20090105", /* F.30 */ 9329b10ae86STejun Heo }, 9339b10ae86STejun Heo { 9349b10ae86STejun Heo .ident = "dv5", 9359b10ae86STejun Heo .matches = { 9369b10ae86STejun Heo DMI_MATCH(DMI_SYS_VENDOR, "Hewlett-Packard"), 9379b10ae86STejun Heo DMI_MATCH(DMI_PRODUCT_NAME, 9389b10ae86STejun Heo "HP Pavilion dv5 Notebook PC"), 9399b10ae86STejun Heo }, 9409deb3431STejun Heo .driver_data = "20090506", /* F.16 */ 9419b10ae86STejun Heo }, 9429b10ae86STejun Heo { 9439b10ae86STejun Heo .ident = "dv6", 9449b10ae86STejun Heo .matches = { 9459b10ae86STejun Heo DMI_MATCH(DMI_SYS_VENDOR, "Hewlett-Packard"), 9469b10ae86STejun Heo DMI_MATCH(DMI_PRODUCT_NAME, 9479b10ae86STejun Heo "HP Pavilion dv6 Notebook PC"), 9489b10ae86STejun Heo }, 9499deb3431STejun Heo .driver_data = "20090423", /* F.21 */ 9509b10ae86STejun Heo }, 9519b10ae86STejun Heo { 9529b10ae86STejun Heo .ident = "HDX18", 9539b10ae86STejun Heo .matches = { 9549b10ae86STejun Heo DMI_MATCH(DMI_SYS_VENDOR, "Hewlett-Packard"), 9559b10ae86STejun Heo DMI_MATCH(DMI_PRODUCT_NAME, 9569b10ae86STejun Heo "HP HDX18 Notebook PC"), 9579b10ae86STejun Heo }, 9589deb3431STejun Heo .driver_data = "20090430", /* F.23 */ 9599b10ae86STejun Heo }, 960cedc9bf9STejun Heo /* 961cedc9bf9STejun Heo * Acer eMachines G725 has the same problem. BIOS 962cedc9bf9STejun Heo * V1.03 is known to be broken. V3.04 is known to 96325985edcSLucas De Marchi * work. Between, there are V1.06, V2.06 and V3.03 964cedc9bf9STejun Heo * that we don't have much idea about. For now, 965cedc9bf9STejun Heo * blacklist anything older than V3.04. 9669deb3431STejun Heo * 9679deb3431STejun Heo * http://bugzilla.kernel.org/show_bug.cgi?id=15104 968cedc9bf9STejun Heo */ 969cedc9bf9STejun Heo { 970cedc9bf9STejun Heo .ident = "G725", 971cedc9bf9STejun Heo .matches = { 972cedc9bf9STejun Heo DMI_MATCH(DMI_SYS_VENDOR, "eMachines"), 973cedc9bf9STejun Heo DMI_MATCH(DMI_PRODUCT_NAME, "eMachines G725"), 974cedc9bf9STejun Heo }, 9759deb3431STejun Heo .driver_data = "20091216", /* V3.04 */ 976cedc9bf9STejun Heo }, 9779b10ae86STejun Heo { } /* terminate list */ 9789b10ae86STejun Heo }; 9799b10ae86STejun Heo const struct dmi_system_id *dmi = dmi_first_match(sysids); 9809deb3431STejun Heo int year, month, date; 9819deb3431STejun Heo char buf[9]; 9829b10ae86STejun Heo 9839b10ae86STejun Heo if (!dmi || pdev->bus->number || pdev->devfn != PCI_DEVFN(0x1f, 2)) 9849b10ae86STejun Heo return false; 9859b10ae86STejun Heo 9869deb3431STejun Heo dmi_get_date(DMI_BIOS_DATE, &year, &month, &date); 9879deb3431STejun Heo snprintf(buf, sizeof(buf), "%04d%02d%02d", year, month, date); 9889b10ae86STejun Heo 9899deb3431STejun Heo return strcmp(buf, dmi->driver_data) < 0; 9909b10ae86STejun Heo } 9919b10ae86STejun Heo 9925594639aSTejun Heo static bool ahci_broken_online(struct pci_dev *pdev) 9935594639aSTejun Heo { 9945594639aSTejun Heo #define ENCODE_BUSDEVFN(bus, slot, func) \ 9955594639aSTejun Heo (void *)(unsigned long)(((bus) << 8) | PCI_DEVFN((slot), (func))) 9965594639aSTejun Heo static const struct dmi_system_id sysids[] = { 9975594639aSTejun Heo /* 9985594639aSTejun Heo * There are several gigabyte boards which use 9995594639aSTejun Heo * SIMG5723s configured as hardware RAID. Certain 10005594639aSTejun Heo * 5723 firmware revisions shipped there keep the link 10015594639aSTejun Heo * online but fail to answer properly to SRST or 10025594639aSTejun Heo * IDENTIFY when no device is attached downstream 10035594639aSTejun Heo * causing libata to retry quite a few times leading 10045594639aSTejun Heo * to excessive detection delay. 10055594639aSTejun Heo * 10065594639aSTejun Heo * As these firmwares respond to the second reset try 10075594639aSTejun Heo * with invalid device signature, considering unknown 10085594639aSTejun Heo * sig as offline works around the problem acceptably. 10095594639aSTejun Heo */ 10105594639aSTejun Heo { 10115594639aSTejun Heo .ident = "EP45-DQ6", 10125594639aSTejun Heo .matches = { 10135594639aSTejun Heo DMI_MATCH(DMI_BOARD_VENDOR, 10145594639aSTejun Heo "Gigabyte Technology Co., Ltd."), 10155594639aSTejun Heo DMI_MATCH(DMI_BOARD_NAME, "EP45-DQ6"), 10165594639aSTejun Heo }, 10175594639aSTejun Heo .driver_data = ENCODE_BUSDEVFN(0x0a, 0x00, 0), 10185594639aSTejun Heo }, 10195594639aSTejun Heo { 10205594639aSTejun Heo .ident = "EP45-DS5", 10215594639aSTejun Heo .matches = { 10225594639aSTejun Heo DMI_MATCH(DMI_BOARD_VENDOR, 10235594639aSTejun Heo "Gigabyte Technology Co., Ltd."), 10245594639aSTejun Heo DMI_MATCH(DMI_BOARD_NAME, "EP45-DS5"), 10255594639aSTejun Heo }, 10265594639aSTejun Heo .driver_data = ENCODE_BUSDEVFN(0x03, 0x00, 0), 10275594639aSTejun Heo }, 10285594639aSTejun Heo { } /* terminate list */ 10295594639aSTejun Heo }; 10305594639aSTejun Heo #undef ENCODE_BUSDEVFN 10315594639aSTejun Heo const struct dmi_system_id *dmi = dmi_first_match(sysids); 10325594639aSTejun Heo unsigned int val; 10335594639aSTejun Heo 10345594639aSTejun Heo if (!dmi) 10355594639aSTejun Heo return false; 10365594639aSTejun Heo 10375594639aSTejun Heo val = (unsigned long)dmi->driver_data; 10385594639aSTejun Heo 10395594639aSTejun Heo return pdev->bus->number == (val >> 8) && pdev->devfn == (val & 0xff); 10405594639aSTejun Heo } 10415594639aSTejun Heo 10428e513217SMarkus Trippelsdorf #ifdef CONFIG_ATA_ACPI 1043f80ae7e4STejun Heo static void ahci_gtf_filter_workaround(struct ata_host *host) 1044f80ae7e4STejun Heo { 1045f80ae7e4STejun Heo static const struct dmi_system_id sysids[] = { 1046f80ae7e4STejun Heo /* 1047f80ae7e4STejun Heo * Aspire 3810T issues a bunch of SATA enable commands 1048f80ae7e4STejun Heo * via _GTF including an invalid one and one which is 1049f80ae7e4STejun Heo * rejected by the device. Among the successful ones 1050f80ae7e4STejun Heo * is FPDMA non-zero offset enable which when enabled 1051f80ae7e4STejun Heo * only on the drive side leads to NCQ command 1052f80ae7e4STejun Heo * failures. Filter it out. 1053f80ae7e4STejun Heo */ 1054f80ae7e4STejun Heo { 1055f80ae7e4STejun Heo .ident = "Aspire 3810T", 1056f80ae7e4STejun Heo .matches = { 1057f80ae7e4STejun Heo DMI_MATCH(DMI_SYS_VENDOR, "Acer"), 1058f80ae7e4STejun Heo DMI_MATCH(DMI_PRODUCT_NAME, "Aspire 3810T"), 1059f80ae7e4STejun Heo }, 1060f80ae7e4STejun Heo .driver_data = (void *)ATA_ACPI_FILTER_FPDMA_OFFSET, 1061f80ae7e4STejun Heo }, 1062f80ae7e4STejun Heo { } 1063f80ae7e4STejun Heo }; 1064f80ae7e4STejun Heo const struct dmi_system_id *dmi = dmi_first_match(sysids); 1065f80ae7e4STejun Heo unsigned int filter; 1066f80ae7e4STejun Heo int i; 1067f80ae7e4STejun Heo 1068f80ae7e4STejun Heo if (!dmi) 1069f80ae7e4STejun Heo return; 1070f80ae7e4STejun Heo 1071f80ae7e4STejun Heo filter = (unsigned long)dmi->driver_data; 1072a44fec1fSJoe Perches dev_info(host->dev, "applying extra ACPI _GTF filter 0x%x for %s\n", 1073f80ae7e4STejun Heo filter, dmi->ident); 1074f80ae7e4STejun Heo 1075f80ae7e4STejun Heo for (i = 0; i < host->n_ports; i++) { 1076f80ae7e4STejun Heo struct ata_port *ap = host->ports[i]; 1077f80ae7e4STejun Heo struct ata_link *link; 1078f80ae7e4STejun Heo struct ata_device *dev; 1079f80ae7e4STejun Heo 1080f80ae7e4STejun Heo ata_for_each_link(link, ap, EDGE) 1081f80ae7e4STejun Heo ata_for_each_dev(dev, link, ALL) 1082f80ae7e4STejun Heo dev->gtf_filter |= filter; 1083f80ae7e4STejun Heo } 1084f80ae7e4STejun Heo } 10858e513217SMarkus Trippelsdorf #else 10868e513217SMarkus Trippelsdorf static inline void ahci_gtf_filter_workaround(struct ata_host *host) 10878e513217SMarkus Trippelsdorf {} 10888e513217SMarkus Trippelsdorf #endif 1089f80ae7e4STejun Heo 10905ca72c4fSAlexander Gordeev int ahci_init_interrupts(struct pci_dev *pdev, struct ahci_host_priv *hpriv) 10915ca72c4fSAlexander Gordeev { 10925ca72c4fSAlexander Gordeev int rc; 10935ca72c4fSAlexander Gordeev unsigned int maxvec; 10945ca72c4fSAlexander Gordeev 10955ca72c4fSAlexander Gordeev if (!(hpriv->flags & AHCI_HFLAG_NO_MSI)) { 10965ca72c4fSAlexander Gordeev rc = pci_enable_msi_block_auto(pdev, &maxvec); 10975ca72c4fSAlexander Gordeev if (rc > 0) { 10985ca72c4fSAlexander Gordeev if ((rc == maxvec) || (rc == 1)) 10995ca72c4fSAlexander Gordeev return rc; 11005ca72c4fSAlexander Gordeev /* 11015ca72c4fSAlexander Gordeev * Assume that advantage of multipe MSIs is negated, 11025ca72c4fSAlexander Gordeev * so fallback to single MSI mode to save resources 11035ca72c4fSAlexander Gordeev */ 11045ca72c4fSAlexander Gordeev pci_disable_msi(pdev); 11055ca72c4fSAlexander Gordeev if (!pci_enable_msi(pdev)) 11065ca72c4fSAlexander Gordeev return 1; 11075ca72c4fSAlexander Gordeev } 11085ca72c4fSAlexander Gordeev } 11095ca72c4fSAlexander Gordeev 11105ca72c4fSAlexander Gordeev pci_intx(pdev, 1); 11115ca72c4fSAlexander Gordeev return 0; 11125ca72c4fSAlexander Gordeev } 11135ca72c4fSAlexander Gordeev 11145ca72c4fSAlexander Gordeev /** 11155ca72c4fSAlexander Gordeev * ahci_host_activate - start AHCI host, request IRQs and register it 11165ca72c4fSAlexander Gordeev * @host: target ATA host 11175ca72c4fSAlexander Gordeev * @irq: base IRQ number to request 11185ca72c4fSAlexander Gordeev * @n_msis: number of MSIs allocated for this host 11195ca72c4fSAlexander Gordeev * @irq_handler: irq_handler used when requesting IRQs 11205ca72c4fSAlexander Gordeev * @irq_flags: irq_flags used when requesting IRQs 11215ca72c4fSAlexander Gordeev * 11225ca72c4fSAlexander Gordeev * Similar to ata_host_activate, but requests IRQs according to AHCI-1.1 11235ca72c4fSAlexander Gordeev * when multiple MSIs were allocated. That is one MSI per port, starting 11245ca72c4fSAlexander Gordeev * from @irq. 11255ca72c4fSAlexander Gordeev * 11265ca72c4fSAlexander Gordeev * LOCKING: 11275ca72c4fSAlexander Gordeev * Inherited from calling layer (may sleep). 11285ca72c4fSAlexander Gordeev * 11295ca72c4fSAlexander Gordeev * RETURNS: 11305ca72c4fSAlexander Gordeev * 0 on success, -errno otherwise. 11315ca72c4fSAlexander Gordeev */ 11325ca72c4fSAlexander Gordeev int ahci_host_activate(struct ata_host *host, int irq, unsigned int n_msis) 11335ca72c4fSAlexander Gordeev { 11345ca72c4fSAlexander Gordeev int i, rc; 11355ca72c4fSAlexander Gordeev 11365ca72c4fSAlexander Gordeev /* Sharing Last Message among several ports is not supported */ 11375ca72c4fSAlexander Gordeev if (n_msis < host->n_ports) 11385ca72c4fSAlexander Gordeev return -EINVAL; 11395ca72c4fSAlexander Gordeev 11405ca72c4fSAlexander Gordeev rc = ata_host_start(host); 11415ca72c4fSAlexander Gordeev if (rc) 11425ca72c4fSAlexander Gordeev return rc; 11435ca72c4fSAlexander Gordeev 11445ca72c4fSAlexander Gordeev for (i = 0; i < host->n_ports; i++) { 1145b29900e6SAlexander Gordeev struct ahci_port_priv *pp = host->ports[i]->private_data; 1146b29900e6SAlexander Gordeev 11475ca72c4fSAlexander Gordeev rc = devm_request_threaded_irq(host->dev, 11485ca72c4fSAlexander Gordeev irq + i, ahci_hw_interrupt, ahci_thread_fn, IRQF_SHARED, 1149b29900e6SAlexander Gordeev pp->irq_desc, host->ports[i]); 11505ca72c4fSAlexander Gordeev if (rc) 11515ca72c4fSAlexander Gordeev goto out_free_irqs; 11525ca72c4fSAlexander Gordeev } 11535ca72c4fSAlexander Gordeev 11545ca72c4fSAlexander Gordeev for (i = 0; i < host->n_ports; i++) 11555ca72c4fSAlexander Gordeev ata_port_desc(host->ports[i], "irq %d", irq + i); 11565ca72c4fSAlexander Gordeev 11575ca72c4fSAlexander Gordeev rc = ata_host_register(host, &ahci_sht); 11585ca72c4fSAlexander Gordeev if (rc) 11595ca72c4fSAlexander Gordeev goto out_free_all_irqs; 11605ca72c4fSAlexander Gordeev 11615ca72c4fSAlexander Gordeev return 0; 11625ca72c4fSAlexander Gordeev 11635ca72c4fSAlexander Gordeev out_free_all_irqs: 11645ca72c4fSAlexander Gordeev i = host->n_ports; 11655ca72c4fSAlexander Gordeev out_free_irqs: 11665ca72c4fSAlexander Gordeev for (i--; i >= 0; i--) 11675ca72c4fSAlexander Gordeev devm_free_irq(host->dev, irq + i, host->ports[i]); 11685ca72c4fSAlexander Gordeev 11695ca72c4fSAlexander Gordeev return rc; 11705ca72c4fSAlexander Gordeev } 11715ca72c4fSAlexander Gordeev 1172c6fd2807SJeff Garzik static int ahci_init_one(struct pci_dev *pdev, const struct pci_device_id *ent) 1173c6fd2807SJeff Garzik { 1174e297d99eSTejun Heo unsigned int board_id = ent->driver_data; 1175e297d99eSTejun Heo struct ata_port_info pi = ahci_port_info[board_id]; 11764447d351STejun Heo const struct ata_port_info *ppi[] = { &pi, NULL }; 117724dc5f33STejun Heo struct device *dev = &pdev->dev; 1178c6fd2807SJeff Garzik struct ahci_host_priv *hpriv; 11794447d351STejun Heo struct ata_host *host; 11805ca72c4fSAlexander Gordeev int n_ports, n_msis, i, rc; 1181318893e1SAlessandro Rubini int ahci_pci_bar = AHCI_PCI_BAR_STANDARD; 1182c6fd2807SJeff Garzik 1183c6fd2807SJeff Garzik VPRINTK("ENTER\n"); 1184c6fd2807SJeff Garzik 1185b429dd59SJustin P. Mattock WARN_ON((int)ATA_MAX_QUEUE > AHCI_MAX_CMDS); 1186c6fd2807SJeff Garzik 118706296a1eSJoe Perches ata_print_version_once(&pdev->dev, DRV_VERSION); 1188c6fd2807SJeff Garzik 11895b66c829SAlan Cox /* The AHCI driver can only drive the SATA ports, the PATA driver 11905b66c829SAlan Cox can drive them all so if both drivers are selected make sure 11915b66c829SAlan Cox AHCI stays out of the way */ 11925b66c829SAlan Cox if (pdev->vendor == PCI_VENDOR_ID_MARVELL && !marvell_enable) 11935b66c829SAlan Cox return -ENODEV; 11945b66c829SAlan Cox 1195c6353b45STejun Heo /* 1196c6353b45STejun Heo * For some reason, MCP89 on MacBook 7,1 doesn't work with 1197c6353b45STejun Heo * ahci, use ata_generic instead. 1198c6353b45STejun Heo */ 1199c6353b45STejun Heo if (pdev->vendor == PCI_VENDOR_ID_NVIDIA && 1200c6353b45STejun Heo pdev->device == PCI_DEVICE_ID_NVIDIA_NFORCE_MCP89_SATA && 1201c6353b45STejun Heo pdev->subsystem_vendor == PCI_VENDOR_ID_APPLE && 1202c6353b45STejun Heo pdev->subsystem_device == 0xcb89) 1203c6353b45STejun Heo return -ENODEV; 1204c6353b45STejun Heo 12057a02267eSMark Nelson /* Promise's PDC42819 is a SAS/SATA controller that has an AHCI mode. 12067a02267eSMark Nelson * At the moment, we can only use the AHCI mode. Let the users know 12077a02267eSMark Nelson * that for SAS drives they're out of luck. 12087a02267eSMark Nelson */ 12097a02267eSMark Nelson if (pdev->vendor == PCI_VENDOR_ID_PROMISE) 1210a44fec1fSJoe Perches dev_info(&pdev->dev, 1211a44fec1fSJoe Perches "PDC42819 can only drive SATA devices with this driver\n"); 12127a02267eSMark Nelson 12137f9c9f8eSHugh Daschbach /* Both Connext and Enmotus devices use non-standard BARs */ 1214318893e1SAlessandro Rubini if (pdev->vendor == PCI_VENDOR_ID_STMICRO && pdev->device == 0xCC06) 1215318893e1SAlessandro Rubini ahci_pci_bar = AHCI_PCI_BAR_STA2X11; 12167f9c9f8eSHugh Daschbach else if (pdev->vendor == 0x1c44 && pdev->device == 0x8000) 12177f9c9f8eSHugh Daschbach ahci_pci_bar = AHCI_PCI_BAR_ENMOTUS; 1218318893e1SAlessandro Rubini 12194447d351STejun Heo /* acquire resources */ 122024dc5f33STejun Heo rc = pcim_enable_device(pdev); 1221c6fd2807SJeff Garzik if (rc) 1222c6fd2807SJeff Garzik return rc; 1223c6fd2807SJeff Garzik 1224dea55137STejun Heo /* AHCI controllers often implement SFF compatible interface. 1225dea55137STejun Heo * Grab all PCI BARs just in case. 1226dea55137STejun Heo */ 1227318893e1SAlessandro Rubini rc = pcim_iomap_regions_request_all(pdev, 1 << ahci_pci_bar, DRV_NAME); 12280d5ff566STejun Heo if (rc == -EBUSY) 122924dc5f33STejun Heo pcim_pin_device(pdev); 12300d5ff566STejun Heo if (rc) 123124dc5f33STejun Heo return rc; 1232c6fd2807SJeff Garzik 1233c4f7792cSTejun Heo if (pdev->vendor == PCI_VENDOR_ID_INTEL && 1234c4f7792cSTejun Heo (pdev->device == 0x2652 || pdev->device == 0x2653)) { 1235c4f7792cSTejun Heo u8 map; 1236c4f7792cSTejun Heo 1237c4f7792cSTejun Heo /* ICH6s share the same PCI ID for both piix and ahci 1238c4f7792cSTejun Heo * modes. Enabling ahci mode while MAP indicates 1239c4f7792cSTejun Heo * combined mode is a bad idea. Yield to ata_piix. 1240c4f7792cSTejun Heo */ 1241c4f7792cSTejun Heo pci_read_config_byte(pdev, ICH_MAP, &map); 1242c4f7792cSTejun Heo if (map & 0x3) { 1243a44fec1fSJoe Perches dev_info(&pdev->dev, 1244a44fec1fSJoe Perches "controller is in combined mode, can't enable AHCI mode\n"); 1245c4f7792cSTejun Heo return -ENODEV; 1246c4f7792cSTejun Heo } 1247c4f7792cSTejun Heo } 1248c4f7792cSTejun Heo 124924dc5f33STejun Heo hpriv = devm_kzalloc(dev, sizeof(*hpriv), GFP_KERNEL); 125024dc5f33STejun Heo if (!hpriv) 125124dc5f33STejun Heo return -ENOMEM; 1252417a1a6dSTejun Heo hpriv->flags |= (unsigned long)pi.private_data; 1253417a1a6dSTejun Heo 1254e297d99eSTejun Heo /* MCP65 revision A1 and A2 can't do MSI */ 1255e297d99eSTejun Heo if (board_id == board_ahci_mcp65 && 1256e297d99eSTejun Heo (pdev->revision == 0xa1 || pdev->revision == 0xa2)) 1257e297d99eSTejun Heo hpriv->flags |= AHCI_HFLAG_NO_MSI; 1258e297d99eSTejun Heo 1259e427fe04SShane Huang /* SB800 does NOT need the workaround to ignore SERR_INTERNAL */ 1260e427fe04SShane Huang if (board_id == board_ahci_sb700 && pdev->revision >= 0x40) 1261e427fe04SShane Huang hpriv->flags &= ~AHCI_HFLAG_IGN_SERR_INTERNAL; 1262e427fe04SShane Huang 12632fcad9d2STejun Heo /* only some SB600s can do 64bit DMA */ 12642fcad9d2STejun Heo if (ahci_sb600_enable_64bit(pdev)) 12652fcad9d2STejun Heo hpriv->flags &= ~AHCI_HFLAG_32BIT_ONLY; 126658a09b38SShane Huang 1267318893e1SAlessandro Rubini hpriv->mmio = pcim_iomap_table(pdev)[ahci_pci_bar]; 1268d8993349SAnton Vorontsov 12695ca72c4fSAlexander Gordeev n_msis = ahci_init_interrupts(pdev, hpriv); 12705ca72c4fSAlexander Gordeev if (n_msis > 1) 12715ca72c4fSAlexander Gordeev hpriv->flags |= AHCI_HFLAG_MULTI_MSI; 12725ca72c4fSAlexander Gordeev 12734447d351STejun Heo /* save initial config */ 1274394d6e53SAnton Vorontsov ahci_pci_save_initial_config(pdev, hpriv); 1275c6fd2807SJeff Garzik 12764447d351STejun Heo /* prepare host */ 1277453d3131SRobert Hancock if (hpriv->cap & HOST_CAP_NCQ) { 1278453d3131SRobert Hancock pi.flags |= ATA_FLAG_NCQ; 127983f2b963STejun Heo /* 128083f2b963STejun Heo * Auto-activate optimization is supposed to be 128183f2b963STejun Heo * supported on all AHCI controllers indicating NCQ 128283f2b963STejun Heo * capability, but it seems to be broken on some 128383f2b963STejun Heo * chipsets including NVIDIAs. 128483f2b963STejun Heo */ 128583f2b963STejun Heo if (!(hpriv->flags & AHCI_HFLAG_NO_FPDMA_AA)) 1286453d3131SRobert Hancock pi.flags |= ATA_FLAG_FPDMA_AA; 1287453d3131SRobert Hancock } 12884447d351STejun Heo 12897d50b60bSTejun Heo if (hpriv->cap & HOST_CAP_PMP) 12907d50b60bSTejun Heo pi.flags |= ATA_FLAG_PMP; 12917d50b60bSTejun Heo 12920cbb0e77SAnton Vorontsov ahci_set_em_messages(hpriv, &pi); 129318f7ba4cSKristen Carlson Accardi 12941fd68434SRafael J. Wysocki if (ahci_broken_system_poweroff(pdev)) { 12951fd68434SRafael J. Wysocki pi.flags |= ATA_FLAG_NO_POWEROFF_SPINDOWN; 12961fd68434SRafael J. Wysocki dev_info(&pdev->dev, 12971fd68434SRafael J. Wysocki "quirky BIOS, skipping spindown on poweroff\n"); 12981fd68434SRafael J. Wysocki } 12991fd68434SRafael J. Wysocki 13009b10ae86STejun Heo if (ahci_broken_suspend(pdev)) { 13019b10ae86STejun Heo hpriv->flags |= AHCI_HFLAG_NO_SUSPEND; 1302a44fec1fSJoe Perches dev_warn(&pdev->dev, 13039b10ae86STejun Heo "BIOS update required for suspend/resume\n"); 13049b10ae86STejun Heo } 13059b10ae86STejun Heo 13065594639aSTejun Heo if (ahci_broken_online(pdev)) { 13075594639aSTejun Heo hpriv->flags |= AHCI_HFLAG_SRST_TOUT_IS_OFFLINE; 13085594639aSTejun Heo dev_info(&pdev->dev, 13095594639aSTejun Heo "online status unreliable, applying workaround\n"); 13105594639aSTejun Heo } 13115594639aSTejun Heo 1312837f5f8fSTejun Heo /* CAP.NP sometimes indicate the index of the last enabled 1313837f5f8fSTejun Heo * port, at other times, that of the last possible port, so 1314837f5f8fSTejun Heo * determining the maximum port number requires looking at 1315837f5f8fSTejun Heo * both CAP.NP and port_map. 1316837f5f8fSTejun Heo */ 1317837f5f8fSTejun Heo n_ports = max(ahci_nr_ports(hpriv->cap), fls(hpriv->port_map)); 1318837f5f8fSTejun Heo 1319837f5f8fSTejun Heo host = ata_host_alloc_pinfo(&pdev->dev, ppi, n_ports); 13204447d351STejun Heo if (!host) 13214447d351STejun Heo return -ENOMEM; 13224447d351STejun Heo host->private_data = hpriv; 13234447d351STejun Heo 1324f3d7f23fSArjan van de Ven if (!(hpriv->cap & HOST_CAP_SSS) || ahci_ignore_sss) 1325886ad09fSArjan van de Ven host->flags |= ATA_HOST_PARALLEL_SCAN; 1326f3d7f23fSArjan van de Ven else 1327f3d7f23fSArjan van de Ven printk(KERN_INFO "ahci: SSS flag set, parallel bus scan disabled\n"); 1328886ad09fSArjan van de Ven 132918f7ba4cSKristen Carlson Accardi if (pi.flags & ATA_FLAG_EM) 133018f7ba4cSKristen Carlson Accardi ahci_reset_em(host); 133118f7ba4cSKristen Carlson Accardi 13324447d351STejun Heo for (i = 0; i < host->n_ports; i++) { 13334447d351STejun Heo struct ata_port *ap = host->ports[i]; 13344447d351STejun Heo 1335318893e1SAlessandro Rubini ata_port_pbar_desc(ap, ahci_pci_bar, -1, "abar"); 1336318893e1SAlessandro Rubini ata_port_pbar_desc(ap, ahci_pci_bar, 1337cbcdd875STejun Heo 0x100 + ap->port_no * 0x80, "port"); 1338cbcdd875STejun Heo 133918f7ba4cSKristen Carlson Accardi /* set enclosure management message type */ 134018f7ba4cSKristen Carlson Accardi if (ap->flags & ATA_FLAG_EM) 1341008dbd61SHarry Zhang ap->em_message_type = hpriv->em_msg_type; 134218f7ba4cSKristen Carlson Accardi 134318f7ba4cSKristen Carlson Accardi 1344dab632e8SJeff Garzik /* disabled/not-implemented port */ 1345350756f6STejun Heo if (!(hpriv->port_map & (1 << i))) 1346dab632e8SJeff Garzik ap->ops = &ata_dummy_port_ops; 13474447d351STejun Heo } 1348c6fd2807SJeff Garzik 1349edc93052STejun Heo /* apply workaround for ASUS P5W DH Deluxe mainboard */ 1350edc93052STejun Heo ahci_p5wdh_workaround(host); 1351edc93052STejun Heo 1352f80ae7e4STejun Heo /* apply gtf filter quirk */ 1353f80ae7e4STejun Heo ahci_gtf_filter_workaround(host); 1354f80ae7e4STejun Heo 1355c6fd2807SJeff Garzik /* initialize adapter */ 13564447d351STejun Heo rc = ahci_configure_dma_masks(pdev, hpriv->cap & HOST_CAP_64); 1357c6fd2807SJeff Garzik if (rc) 135824dc5f33STejun Heo return rc; 1359c6fd2807SJeff Garzik 13603303040dSAnton Vorontsov rc = ahci_pci_reset_controller(host); 13614447d351STejun Heo if (rc) 13624447d351STejun Heo return rc; 1363c6fd2807SJeff Garzik 1364781d6550SAnton Vorontsov ahci_pci_init_controller(host); 1365439fcaecSAnton Vorontsov ahci_pci_print_info(host); 1366c6fd2807SJeff Garzik 13674447d351STejun Heo pci_set_master(pdev); 13685ca72c4fSAlexander Gordeev 13695ca72c4fSAlexander Gordeev if (hpriv->flags & AHCI_HFLAG_MULTI_MSI) 13705ca72c4fSAlexander Gordeev return ahci_host_activate(host, pdev->irq, n_msis); 13715ca72c4fSAlexander Gordeev 13724447d351STejun Heo return ata_host_activate(host, pdev->irq, ahci_interrupt, IRQF_SHARED, 13734447d351STejun Heo &ahci_sht); 1374c6fd2807SJeff Garzik } 1375c6fd2807SJeff Garzik 13762fc75da0SAxel Lin module_pci_driver(ahci_pci_driver); 1377c6fd2807SJeff Garzik 1378c6fd2807SJeff Garzik MODULE_AUTHOR("Jeff Garzik"); 1379c6fd2807SJeff Garzik MODULE_DESCRIPTION("AHCI SATA low-level driver"); 1380c6fd2807SJeff Garzik MODULE_LICENSE("GPL"); 1381c6fd2807SJeff Garzik MODULE_DEVICE_TABLE(pci, ahci_pci_tbl); 1382c6fd2807SJeff Garzik MODULE_VERSION(DRV_VERSION); 1383