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 { 55c6fd2807SJeff Garzik AHCI_PCI_BAR = 5, 56441577efSTejun Heo }; 57c6fd2807SJeff Garzik 58441577efSTejun Heo enum board_ids { 59441577efSTejun Heo /* board IDs by feature in alphabetical order */ 60441577efSTejun Heo board_ahci, 61441577efSTejun Heo board_ahci_ign_iferr, 62441577efSTejun Heo board_ahci_nosntf, 63441577efSTejun Heo 64441577efSTejun Heo /* board IDs for specific chipsets in alphabetical order */ 65441577efSTejun Heo board_ahci_mcp65, 6683f2b963STejun Heo board_ahci_mcp77, 6783f2b963STejun Heo board_ahci_mcp89, 68441577efSTejun Heo board_ahci_mv, 69441577efSTejun Heo board_ahci_sb600, 70441577efSTejun Heo board_ahci_sb700, /* for SB700 and SB800 */ 71441577efSTejun Heo board_ahci_vt8251, 72441577efSTejun Heo 73441577efSTejun Heo /* aliases */ 74441577efSTejun Heo board_ahci_mcp_linux = board_ahci_mcp65, 75441577efSTejun Heo board_ahci_mcp67 = board_ahci_mcp65, 76441577efSTejun Heo board_ahci_mcp73 = board_ahci_mcp65, 7783f2b963STejun Heo board_ahci_mcp79 = board_ahci_mcp77, 78c6fd2807SJeff Garzik }; 79c6fd2807SJeff Garzik 80c6fd2807SJeff Garzik static int ahci_init_one(struct pci_dev *pdev, const struct pci_device_id *ent); 81bd17243aSShane Huang static int ahci_sb600_softreset(struct ata_link *link, unsigned int *class, 82bd17243aSShane Huang unsigned long deadline); 83a1efdabaSTejun Heo static int ahci_vt8251_hardreset(struct ata_link *link, unsigned int *class, 84a1efdabaSTejun Heo unsigned long deadline); 85a1efdabaSTejun Heo static int ahci_p5wdh_hardreset(struct ata_link *link, unsigned int *class, 86a1efdabaSTejun Heo unsigned long deadline); 87438ac6d5STejun Heo #ifdef CONFIG_PM 88c6fd2807SJeff Garzik static int ahci_pci_device_suspend(struct pci_dev *pdev, pm_message_t mesg); 89c6fd2807SJeff Garzik static int ahci_pci_device_resume(struct pci_dev *pdev); 90438ac6d5STejun Heo #endif 91c6fd2807SJeff Garzik 92029cfd6bSTejun Heo static struct ata_port_operations ahci_vt8251_ops = { 93029cfd6bSTejun Heo .inherits = &ahci_ops, 94a1efdabaSTejun Heo .hardreset = ahci_vt8251_hardreset, 95ad616ffbSTejun Heo }; 96ad616ffbSTejun Heo 97029cfd6bSTejun Heo static struct ata_port_operations ahci_p5wdh_ops = { 98029cfd6bSTejun Heo .inherits = &ahci_ops, 99a1efdabaSTejun Heo .hardreset = ahci_p5wdh_hardreset, 100edc93052STejun Heo }; 101edc93052STejun Heo 102bd17243aSShane Huang static struct ata_port_operations ahci_sb600_ops = { 103bd17243aSShane Huang .inherits = &ahci_ops, 104bd17243aSShane Huang .softreset = ahci_sb600_softreset, 105bd17243aSShane Huang .pmp_softreset = ahci_sb600_softreset, 106bd17243aSShane Huang }; 107bd17243aSShane Huang 108417a1a6dSTejun Heo #define AHCI_HFLAGS(flags) .private_data = (void *)(flags) 109417a1a6dSTejun Heo 110c6fd2807SJeff Garzik static const struct ata_port_info ahci_port_info[] = { 111441577efSTejun Heo /* by features */ 1124da646b7SJeff Garzik [board_ahci] = 113c6fd2807SJeff Garzik { 1141188c0d8STejun Heo .flags = AHCI_FLAG_COMMON, 11514bdef98SErik Inge Bolsø .pio_mask = ATA_PIO4, 116469248abSJeff Garzik .udma_mask = ATA_UDMA6, 117c6fd2807SJeff Garzik .port_ops = &ahci_ops, 118c6fd2807SJeff Garzik }, 1194da646b7SJeff Garzik [board_ahci_ign_iferr] = 12041669553STejun Heo { 121417a1a6dSTejun Heo AHCI_HFLAGS (AHCI_HFLAG_IGN_IRQ_IF_ERR), 122417a1a6dSTejun Heo .flags = AHCI_FLAG_COMMON, 12314bdef98SErik Inge Bolsø .pio_mask = ATA_PIO4, 124469248abSJeff Garzik .udma_mask = ATA_UDMA6, 12541669553STejun Heo .port_ops = &ahci_ops, 12641669553STejun Heo }, 127441577efSTejun Heo [board_ahci_nosntf] = 128441577efSTejun Heo { 129441577efSTejun Heo AHCI_HFLAGS (AHCI_HFLAG_NO_SNTF), 130441577efSTejun Heo .flags = AHCI_FLAG_COMMON, 131441577efSTejun Heo .pio_mask = ATA_PIO4, 132441577efSTejun Heo .udma_mask = ATA_UDMA6, 133441577efSTejun Heo .port_ops = &ahci_ops, 134441577efSTejun Heo }, 135441577efSTejun Heo /* by chipsets */ 136441577efSTejun Heo [board_ahci_mcp65] = 137441577efSTejun Heo { 13883f2b963STejun Heo AHCI_HFLAGS (AHCI_HFLAG_NO_FPDMA_AA | AHCI_HFLAG_NO_PMP | 13983f2b963STejun Heo AHCI_HFLAG_YES_NCQ), 14083f2b963STejun Heo .flags = AHCI_FLAG_COMMON, 14183f2b963STejun Heo .pio_mask = ATA_PIO4, 14283f2b963STejun Heo .udma_mask = ATA_UDMA6, 14383f2b963STejun Heo .port_ops = &ahci_ops, 14483f2b963STejun Heo }, 14583f2b963STejun Heo [board_ahci_mcp77] = 14683f2b963STejun Heo { 14783f2b963STejun Heo AHCI_HFLAGS (AHCI_HFLAG_NO_FPDMA_AA | AHCI_HFLAG_NO_PMP), 14883f2b963STejun Heo .flags = AHCI_FLAG_COMMON, 14983f2b963STejun Heo .pio_mask = ATA_PIO4, 15083f2b963STejun Heo .udma_mask = ATA_UDMA6, 15183f2b963STejun Heo .port_ops = &ahci_ops, 15283f2b963STejun Heo }, 15383f2b963STejun Heo [board_ahci_mcp89] = 15483f2b963STejun Heo { 15583f2b963STejun Heo AHCI_HFLAGS (AHCI_HFLAG_NO_FPDMA_AA), 156441577efSTejun Heo .flags = AHCI_FLAG_COMMON, 157441577efSTejun Heo .pio_mask = ATA_PIO4, 158441577efSTejun Heo .udma_mask = ATA_UDMA6, 159441577efSTejun Heo .port_ops = &ahci_ops, 160441577efSTejun Heo }, 161441577efSTejun Heo [board_ahci_mv] = 162441577efSTejun Heo { 163441577efSTejun Heo AHCI_HFLAGS (AHCI_HFLAG_NO_NCQ | AHCI_HFLAG_NO_MSI | 164441577efSTejun Heo AHCI_HFLAG_MV_PATA | AHCI_HFLAG_NO_PMP), 165441577efSTejun Heo .flags = ATA_FLAG_SATA | ATA_FLAG_NO_LEGACY | 166441577efSTejun Heo ATA_FLAG_MMIO | ATA_FLAG_PIO_DMA, 167441577efSTejun Heo .pio_mask = ATA_PIO4, 168441577efSTejun Heo .udma_mask = ATA_UDMA6, 169441577efSTejun Heo .port_ops = &ahci_ops, 170441577efSTejun Heo }, 1714da646b7SJeff Garzik [board_ahci_sb600] = 17255a61604SConke Hu { 173417a1a6dSTejun Heo AHCI_HFLAGS (AHCI_HFLAG_IGN_SERR_INTERNAL | 1742fcad9d2STejun Heo AHCI_HFLAG_NO_MSI | AHCI_HFLAG_SECT255 | 1752fcad9d2STejun Heo AHCI_HFLAG_32BIT_ONLY), 176417a1a6dSTejun Heo .flags = AHCI_FLAG_COMMON, 17714bdef98SErik Inge Bolsø .pio_mask = ATA_PIO4, 178469248abSJeff Garzik .udma_mask = ATA_UDMA6, 179bd17243aSShane Huang .port_ops = &ahci_sb600_ops, 18055a61604SConke Hu }, 1814da646b7SJeff Garzik [board_ahci_sb700] = /* for SB700 and SB800 */ 182e39fc8c9SShane Huang { 183bd17243aSShane Huang AHCI_HFLAGS (AHCI_HFLAG_IGN_SERR_INTERNAL), 184e39fc8c9SShane Huang .flags = AHCI_FLAG_COMMON, 18514bdef98SErik Inge Bolsø .pio_mask = ATA_PIO4, 186e39fc8c9SShane Huang .udma_mask = ATA_UDMA6, 187bd17243aSShane Huang .port_ops = &ahci_sb600_ops, 188e39fc8c9SShane Huang }, 189441577efSTejun Heo [board_ahci_vt8251] = 190e297d99eSTejun Heo { 191441577efSTejun Heo AHCI_HFLAGS (AHCI_HFLAG_NO_NCQ | AHCI_HFLAG_NO_PMP), 192e297d99eSTejun Heo .flags = AHCI_FLAG_COMMON, 19314bdef98SErik Inge Bolsø .pio_mask = ATA_PIO4, 194e297d99eSTejun Heo .udma_mask = ATA_UDMA6, 195441577efSTejun Heo .port_ops = &ahci_vt8251_ops, 1961b677afdSShaohua Li }, 197c6fd2807SJeff Garzik }; 198c6fd2807SJeff Garzik 199c6fd2807SJeff Garzik static const struct pci_device_id ahci_pci_tbl[] = { 200c6fd2807SJeff Garzik /* Intel */ 20154bb3a94SJeff Garzik { PCI_VDEVICE(INTEL, 0x2652), board_ahci }, /* ICH6 */ 20254bb3a94SJeff Garzik { PCI_VDEVICE(INTEL, 0x2653), board_ahci }, /* ICH6M */ 20354bb3a94SJeff Garzik { PCI_VDEVICE(INTEL, 0x27c1), board_ahci }, /* ICH7 */ 20454bb3a94SJeff Garzik { PCI_VDEVICE(INTEL, 0x27c5), board_ahci }, /* ICH7M */ 20554bb3a94SJeff Garzik { PCI_VDEVICE(INTEL, 0x27c3), board_ahci }, /* ICH7R */ 20682490c09STejun Heo { PCI_VDEVICE(AL, 0x5288), board_ahci_ign_iferr }, /* ULi M5288 */ 20754bb3a94SJeff Garzik { PCI_VDEVICE(INTEL, 0x2681), board_ahci }, /* ESB2 */ 20854bb3a94SJeff Garzik { PCI_VDEVICE(INTEL, 0x2682), board_ahci }, /* ESB2 */ 20954bb3a94SJeff Garzik { PCI_VDEVICE(INTEL, 0x2683), board_ahci }, /* ESB2 */ 21054bb3a94SJeff Garzik { PCI_VDEVICE(INTEL, 0x27c6), board_ahci }, /* ICH7-M DH */ 2117a234affSTejun Heo { PCI_VDEVICE(INTEL, 0x2821), board_ahci }, /* ICH8 */ 2121b677afdSShaohua Li { PCI_VDEVICE(INTEL, 0x2822), board_ahci_nosntf }, /* ICH8 */ 2137a234affSTejun Heo { PCI_VDEVICE(INTEL, 0x2824), board_ahci }, /* ICH8 */ 2147a234affSTejun Heo { PCI_VDEVICE(INTEL, 0x2829), board_ahci }, /* ICH8M */ 2157a234affSTejun Heo { PCI_VDEVICE(INTEL, 0x282a), board_ahci }, /* ICH8M */ 2167a234affSTejun Heo { PCI_VDEVICE(INTEL, 0x2922), board_ahci }, /* ICH9 */ 2177a234affSTejun Heo { PCI_VDEVICE(INTEL, 0x2923), board_ahci }, /* ICH9 */ 2187a234affSTejun Heo { PCI_VDEVICE(INTEL, 0x2924), board_ahci }, /* ICH9 */ 2197a234affSTejun Heo { PCI_VDEVICE(INTEL, 0x2925), board_ahci }, /* ICH9 */ 2207a234affSTejun Heo { PCI_VDEVICE(INTEL, 0x2927), board_ahci }, /* ICH9 */ 2217a234affSTejun Heo { PCI_VDEVICE(INTEL, 0x2929), board_ahci }, /* ICH9M */ 2227a234affSTejun Heo { PCI_VDEVICE(INTEL, 0x292a), board_ahci }, /* ICH9M */ 2237a234affSTejun Heo { PCI_VDEVICE(INTEL, 0x292b), board_ahci }, /* ICH9M */ 2247a234affSTejun Heo { PCI_VDEVICE(INTEL, 0x292c), board_ahci }, /* ICH9M */ 2257a234affSTejun Heo { PCI_VDEVICE(INTEL, 0x292f), board_ahci }, /* ICH9M */ 2267a234affSTejun Heo { PCI_VDEVICE(INTEL, 0x294d), board_ahci }, /* ICH9 */ 2277a234affSTejun Heo { PCI_VDEVICE(INTEL, 0x294e), board_ahci }, /* ICH9M */ 228d4155e6fSJason Gaston { PCI_VDEVICE(INTEL, 0x502a), board_ahci }, /* Tolapai */ 229d4155e6fSJason Gaston { PCI_VDEVICE(INTEL, 0x502b), board_ahci }, /* Tolapai */ 23016ad1ad9SJason Gaston { PCI_VDEVICE(INTEL, 0x3a05), board_ahci }, /* ICH10 */ 231b2dde6afSMark Goodwin { PCI_VDEVICE(INTEL, 0x3a22), board_ahci }, /* ICH10 */ 23216ad1ad9SJason Gaston { PCI_VDEVICE(INTEL, 0x3a25), board_ahci }, /* ICH10 */ 233c1f57d9bSDavid Milburn { PCI_VDEVICE(INTEL, 0x3b22), board_ahci }, /* PCH AHCI */ 234c1f57d9bSDavid Milburn { PCI_VDEVICE(INTEL, 0x3b23), board_ahci }, /* PCH AHCI */ 235adcb5308SSeth Heasley { PCI_VDEVICE(INTEL, 0x3b24), board_ahci }, /* PCH RAID */ 2368e48b6b3SSeth Heasley { PCI_VDEVICE(INTEL, 0x3b25), board_ahci }, /* PCH RAID */ 237c1f57d9bSDavid Milburn { PCI_VDEVICE(INTEL, 0x3b29), board_ahci }, /* PCH AHCI */ 238adcb5308SSeth Heasley { PCI_VDEVICE(INTEL, 0x3b2b), board_ahci }, /* PCH RAID */ 2398e48b6b3SSeth Heasley { PCI_VDEVICE(INTEL, 0x3b2c), board_ahci }, /* PCH RAID */ 240c1f57d9bSDavid Milburn { PCI_VDEVICE(INTEL, 0x3b2f), board_ahci }, /* PCH AHCI */ 2415623cab8SSeth Heasley { PCI_VDEVICE(INTEL, 0x1c02), board_ahci }, /* CPT AHCI */ 2425623cab8SSeth Heasley { PCI_VDEVICE(INTEL, 0x1c03), board_ahci }, /* CPT AHCI */ 2435623cab8SSeth Heasley { PCI_VDEVICE(INTEL, 0x1c04), board_ahci }, /* CPT RAID */ 2445623cab8SSeth Heasley { PCI_VDEVICE(INTEL, 0x1c05), board_ahci }, /* CPT RAID */ 2455623cab8SSeth Heasley { PCI_VDEVICE(INTEL, 0x1c06), board_ahci }, /* CPT RAID */ 2465623cab8SSeth Heasley { PCI_VDEVICE(INTEL, 0x1c07), board_ahci }, /* CPT RAID */ 247c6fd2807SJeff Garzik 248e34bb370STejun Heo /* JMicron 360/1/3/5/6, match class to avoid IDE function */ 249e34bb370STejun Heo { PCI_VENDOR_ID_JMICRON, PCI_ANY_ID, PCI_ANY_ID, PCI_ANY_ID, 250e34bb370STejun Heo PCI_CLASS_STORAGE_SATA_AHCI, 0xffffff, board_ahci_ign_iferr }, 251c6fd2807SJeff Garzik 252c6fd2807SJeff Garzik /* ATI */ 253c65ec1c2SConke Hu { PCI_VDEVICE(ATI, 0x4380), board_ahci_sb600 }, /* ATI SB600 */ 254e39fc8c9SShane Huang { PCI_VDEVICE(ATI, 0x4390), board_ahci_sb700 }, /* ATI SB700/800 */ 255e39fc8c9SShane Huang { PCI_VDEVICE(ATI, 0x4391), board_ahci_sb700 }, /* ATI SB700/800 */ 256e39fc8c9SShane Huang { PCI_VDEVICE(ATI, 0x4392), board_ahci_sb700 }, /* ATI SB700/800 */ 257e39fc8c9SShane Huang { PCI_VDEVICE(ATI, 0x4393), board_ahci_sb700 }, /* ATI SB700/800 */ 258e39fc8c9SShane Huang { PCI_VDEVICE(ATI, 0x4394), board_ahci_sb700 }, /* ATI SB700/800 */ 259e39fc8c9SShane Huang { PCI_VDEVICE(ATI, 0x4395), board_ahci_sb700 }, /* ATI SB700/800 */ 260c6fd2807SJeff Garzik 261e2dd90b1SShane Huang /* AMD */ 2625deab536SShane Huang { PCI_VDEVICE(AMD, 0x7800), board_ahci }, /* AMD Hudson-2 */ 263e2dd90b1SShane Huang /* AMD is using RAID class only for ahci controllers */ 264e2dd90b1SShane Huang { PCI_VENDOR_ID_AMD, PCI_ANY_ID, PCI_ANY_ID, PCI_ANY_ID, 265e2dd90b1SShane Huang PCI_CLASS_STORAGE_RAID << 8, 0xffffff, board_ahci }, 266e2dd90b1SShane Huang 267c6fd2807SJeff Garzik /* VIA */ 26854bb3a94SJeff Garzik { PCI_VDEVICE(VIA, 0x3349), board_ahci_vt8251 }, /* VIA VT8251 */ 269bf335542STejun Heo { PCI_VDEVICE(VIA, 0x6287), board_ahci_vt8251 }, /* VIA VT8251 */ 270c6fd2807SJeff Garzik 271c6fd2807SJeff Garzik /* NVIDIA */ 272e297d99eSTejun Heo { PCI_VDEVICE(NVIDIA, 0x044c), board_ahci_mcp65 }, /* MCP65 */ 273e297d99eSTejun Heo { PCI_VDEVICE(NVIDIA, 0x044d), board_ahci_mcp65 }, /* MCP65 */ 274e297d99eSTejun Heo { PCI_VDEVICE(NVIDIA, 0x044e), board_ahci_mcp65 }, /* MCP65 */ 275e297d99eSTejun Heo { PCI_VDEVICE(NVIDIA, 0x044f), board_ahci_mcp65 }, /* MCP65 */ 276e297d99eSTejun Heo { PCI_VDEVICE(NVIDIA, 0x045c), board_ahci_mcp65 }, /* MCP65 */ 277e297d99eSTejun Heo { PCI_VDEVICE(NVIDIA, 0x045d), board_ahci_mcp65 }, /* MCP65 */ 278e297d99eSTejun Heo { PCI_VDEVICE(NVIDIA, 0x045e), board_ahci_mcp65 }, /* MCP65 */ 279e297d99eSTejun Heo { PCI_VDEVICE(NVIDIA, 0x045f), board_ahci_mcp65 }, /* MCP65 */ 280441577efSTejun Heo { PCI_VDEVICE(NVIDIA, 0x0550), board_ahci_mcp67 }, /* MCP67 */ 281441577efSTejun Heo { PCI_VDEVICE(NVIDIA, 0x0551), board_ahci_mcp67 }, /* MCP67 */ 282441577efSTejun Heo { PCI_VDEVICE(NVIDIA, 0x0552), board_ahci_mcp67 }, /* MCP67 */ 283441577efSTejun Heo { PCI_VDEVICE(NVIDIA, 0x0553), board_ahci_mcp67 }, /* MCP67 */ 284441577efSTejun Heo { PCI_VDEVICE(NVIDIA, 0x0554), board_ahci_mcp67 }, /* MCP67 */ 285441577efSTejun Heo { PCI_VDEVICE(NVIDIA, 0x0555), board_ahci_mcp67 }, /* MCP67 */ 286441577efSTejun Heo { PCI_VDEVICE(NVIDIA, 0x0556), board_ahci_mcp67 }, /* MCP67 */ 287441577efSTejun Heo { PCI_VDEVICE(NVIDIA, 0x0557), board_ahci_mcp67 }, /* MCP67 */ 288441577efSTejun Heo { PCI_VDEVICE(NVIDIA, 0x0558), board_ahci_mcp67 }, /* MCP67 */ 289441577efSTejun Heo { PCI_VDEVICE(NVIDIA, 0x0559), board_ahci_mcp67 }, /* MCP67 */ 290441577efSTejun Heo { PCI_VDEVICE(NVIDIA, 0x055a), board_ahci_mcp67 }, /* MCP67 */ 291441577efSTejun Heo { PCI_VDEVICE(NVIDIA, 0x055b), board_ahci_mcp67 }, /* MCP67 */ 292441577efSTejun Heo { PCI_VDEVICE(NVIDIA, 0x0580), board_ahci_mcp_linux }, /* Linux ID */ 293441577efSTejun Heo { PCI_VDEVICE(NVIDIA, 0x0581), board_ahci_mcp_linux }, /* Linux ID */ 294441577efSTejun Heo { PCI_VDEVICE(NVIDIA, 0x0582), board_ahci_mcp_linux }, /* Linux ID */ 295441577efSTejun Heo { PCI_VDEVICE(NVIDIA, 0x0583), board_ahci_mcp_linux }, /* Linux ID */ 296441577efSTejun Heo { PCI_VDEVICE(NVIDIA, 0x0584), board_ahci_mcp_linux }, /* Linux ID */ 297441577efSTejun Heo { PCI_VDEVICE(NVIDIA, 0x0585), board_ahci_mcp_linux }, /* Linux ID */ 298441577efSTejun Heo { PCI_VDEVICE(NVIDIA, 0x0586), board_ahci_mcp_linux }, /* Linux ID */ 299441577efSTejun Heo { PCI_VDEVICE(NVIDIA, 0x0587), board_ahci_mcp_linux }, /* Linux ID */ 300441577efSTejun Heo { PCI_VDEVICE(NVIDIA, 0x0588), board_ahci_mcp_linux }, /* Linux ID */ 301441577efSTejun Heo { PCI_VDEVICE(NVIDIA, 0x0589), board_ahci_mcp_linux }, /* Linux ID */ 302441577efSTejun Heo { PCI_VDEVICE(NVIDIA, 0x058a), board_ahci_mcp_linux }, /* Linux ID */ 303441577efSTejun Heo { PCI_VDEVICE(NVIDIA, 0x058b), board_ahci_mcp_linux }, /* Linux ID */ 304441577efSTejun Heo { PCI_VDEVICE(NVIDIA, 0x058c), board_ahci_mcp_linux }, /* Linux ID */ 305441577efSTejun Heo { PCI_VDEVICE(NVIDIA, 0x058d), board_ahci_mcp_linux }, /* Linux ID */ 306441577efSTejun Heo { PCI_VDEVICE(NVIDIA, 0x058e), board_ahci_mcp_linux }, /* Linux ID */ 307441577efSTejun Heo { PCI_VDEVICE(NVIDIA, 0x058f), board_ahci_mcp_linux }, /* Linux ID */ 308441577efSTejun Heo { PCI_VDEVICE(NVIDIA, 0x07f0), board_ahci_mcp73 }, /* MCP73 */ 309441577efSTejun Heo { PCI_VDEVICE(NVIDIA, 0x07f1), board_ahci_mcp73 }, /* MCP73 */ 310441577efSTejun Heo { PCI_VDEVICE(NVIDIA, 0x07f2), board_ahci_mcp73 }, /* MCP73 */ 311441577efSTejun Heo { PCI_VDEVICE(NVIDIA, 0x07f3), board_ahci_mcp73 }, /* MCP73 */ 312441577efSTejun Heo { PCI_VDEVICE(NVIDIA, 0x07f4), board_ahci_mcp73 }, /* MCP73 */ 313441577efSTejun Heo { PCI_VDEVICE(NVIDIA, 0x07f5), board_ahci_mcp73 }, /* MCP73 */ 314441577efSTejun Heo { PCI_VDEVICE(NVIDIA, 0x07f6), board_ahci_mcp73 }, /* MCP73 */ 315441577efSTejun Heo { PCI_VDEVICE(NVIDIA, 0x07f7), board_ahci_mcp73 }, /* MCP73 */ 316441577efSTejun Heo { PCI_VDEVICE(NVIDIA, 0x07f8), board_ahci_mcp73 }, /* MCP73 */ 317441577efSTejun Heo { PCI_VDEVICE(NVIDIA, 0x07f9), board_ahci_mcp73 }, /* MCP73 */ 318441577efSTejun Heo { PCI_VDEVICE(NVIDIA, 0x07fa), board_ahci_mcp73 }, /* MCP73 */ 319441577efSTejun Heo { PCI_VDEVICE(NVIDIA, 0x07fb), board_ahci_mcp73 }, /* MCP73 */ 320441577efSTejun Heo { PCI_VDEVICE(NVIDIA, 0x0ad0), board_ahci_mcp77 }, /* MCP77 */ 321441577efSTejun Heo { PCI_VDEVICE(NVIDIA, 0x0ad1), board_ahci_mcp77 }, /* MCP77 */ 322441577efSTejun Heo { PCI_VDEVICE(NVIDIA, 0x0ad2), board_ahci_mcp77 }, /* MCP77 */ 323441577efSTejun Heo { PCI_VDEVICE(NVIDIA, 0x0ad3), board_ahci_mcp77 }, /* MCP77 */ 324441577efSTejun Heo { PCI_VDEVICE(NVIDIA, 0x0ad4), board_ahci_mcp77 }, /* MCP77 */ 325441577efSTejun Heo { PCI_VDEVICE(NVIDIA, 0x0ad5), board_ahci_mcp77 }, /* MCP77 */ 326441577efSTejun Heo { PCI_VDEVICE(NVIDIA, 0x0ad6), board_ahci_mcp77 }, /* MCP77 */ 327441577efSTejun Heo { PCI_VDEVICE(NVIDIA, 0x0ad7), board_ahci_mcp77 }, /* MCP77 */ 328441577efSTejun Heo { PCI_VDEVICE(NVIDIA, 0x0ad8), board_ahci_mcp77 }, /* MCP77 */ 329441577efSTejun Heo { PCI_VDEVICE(NVIDIA, 0x0ad9), board_ahci_mcp77 }, /* MCP77 */ 330441577efSTejun Heo { PCI_VDEVICE(NVIDIA, 0x0ada), board_ahci_mcp77 }, /* MCP77 */ 331441577efSTejun Heo { PCI_VDEVICE(NVIDIA, 0x0adb), board_ahci_mcp77 }, /* MCP77 */ 332441577efSTejun Heo { PCI_VDEVICE(NVIDIA, 0x0ab4), board_ahci_mcp79 }, /* MCP79 */ 333441577efSTejun Heo { PCI_VDEVICE(NVIDIA, 0x0ab5), board_ahci_mcp79 }, /* MCP79 */ 334441577efSTejun Heo { PCI_VDEVICE(NVIDIA, 0x0ab6), board_ahci_mcp79 }, /* MCP79 */ 335441577efSTejun Heo { PCI_VDEVICE(NVIDIA, 0x0ab7), board_ahci_mcp79 }, /* MCP79 */ 336441577efSTejun Heo { PCI_VDEVICE(NVIDIA, 0x0ab8), board_ahci_mcp79 }, /* MCP79 */ 337441577efSTejun Heo { PCI_VDEVICE(NVIDIA, 0x0ab9), board_ahci_mcp79 }, /* MCP79 */ 338441577efSTejun Heo { PCI_VDEVICE(NVIDIA, 0x0aba), board_ahci_mcp79 }, /* MCP79 */ 339441577efSTejun Heo { PCI_VDEVICE(NVIDIA, 0x0abb), board_ahci_mcp79 }, /* MCP79 */ 340441577efSTejun Heo { PCI_VDEVICE(NVIDIA, 0x0abc), board_ahci_mcp79 }, /* MCP79 */ 341441577efSTejun Heo { PCI_VDEVICE(NVIDIA, 0x0abd), board_ahci_mcp79 }, /* MCP79 */ 342441577efSTejun Heo { PCI_VDEVICE(NVIDIA, 0x0abe), board_ahci_mcp79 }, /* MCP79 */ 343441577efSTejun Heo { PCI_VDEVICE(NVIDIA, 0x0abf), board_ahci_mcp79 }, /* MCP79 */ 344441577efSTejun Heo { PCI_VDEVICE(NVIDIA, 0x0d84), board_ahci_mcp89 }, /* MCP89 */ 345441577efSTejun Heo { PCI_VDEVICE(NVIDIA, 0x0d85), board_ahci_mcp89 }, /* MCP89 */ 346441577efSTejun Heo { PCI_VDEVICE(NVIDIA, 0x0d86), board_ahci_mcp89 }, /* MCP89 */ 347441577efSTejun Heo { PCI_VDEVICE(NVIDIA, 0x0d87), board_ahci_mcp89 }, /* MCP89 */ 348441577efSTejun Heo { PCI_VDEVICE(NVIDIA, 0x0d88), board_ahci_mcp89 }, /* MCP89 */ 349441577efSTejun Heo { PCI_VDEVICE(NVIDIA, 0x0d89), board_ahci_mcp89 }, /* MCP89 */ 350441577efSTejun Heo { PCI_VDEVICE(NVIDIA, 0x0d8a), board_ahci_mcp89 }, /* MCP89 */ 351441577efSTejun Heo { PCI_VDEVICE(NVIDIA, 0x0d8b), board_ahci_mcp89 }, /* MCP89 */ 352441577efSTejun Heo { PCI_VDEVICE(NVIDIA, 0x0d8c), board_ahci_mcp89 }, /* MCP89 */ 353441577efSTejun Heo { PCI_VDEVICE(NVIDIA, 0x0d8d), board_ahci_mcp89 }, /* MCP89 */ 354441577efSTejun Heo { PCI_VDEVICE(NVIDIA, 0x0d8e), board_ahci_mcp89 }, /* MCP89 */ 355441577efSTejun Heo { PCI_VDEVICE(NVIDIA, 0x0d8f), board_ahci_mcp89 }, /* MCP89 */ 356c6fd2807SJeff Garzik 357c6fd2807SJeff Garzik /* SiS */ 35820e2de4aSTejun Heo { PCI_VDEVICE(SI, 0x1184), board_ahci }, /* SiS 966 */ 35920e2de4aSTejun Heo { PCI_VDEVICE(SI, 0x1185), board_ahci }, /* SiS 968 */ 36020e2de4aSTejun Heo { PCI_VDEVICE(SI, 0x0186), board_ahci }, /* SiS 968 */ 361c6fd2807SJeff Garzik 362cd70c266SJeff Garzik /* Marvell */ 363cd70c266SJeff Garzik { PCI_VDEVICE(MARVELL, 0x6145), board_ahci_mv }, /* 6145 */ 364c40e7cb8SJose Alberto Reguero { PCI_VDEVICE(MARVELL, 0x6121), board_ahci_mv }, /* 6121 */ 365cd70c266SJeff Garzik 366c77a036bSMark Nelson /* Promise */ 367c77a036bSMark Nelson { PCI_VDEVICE(PROMISE, 0x3f20), board_ahci }, /* PDC42819 */ 368c77a036bSMark Nelson 369415ae2b5SJeff Garzik /* Generic, PCI class code for AHCI */ 370415ae2b5SJeff Garzik { PCI_ANY_ID, PCI_ANY_ID, PCI_ANY_ID, PCI_ANY_ID, 371c9f89475SConke Hu PCI_CLASS_STORAGE_SATA_AHCI, 0xffffff, board_ahci }, 372415ae2b5SJeff Garzik 373c6fd2807SJeff Garzik { } /* terminate list */ 374c6fd2807SJeff Garzik }; 375c6fd2807SJeff Garzik 376c6fd2807SJeff Garzik 377c6fd2807SJeff Garzik static struct pci_driver ahci_pci_driver = { 378c6fd2807SJeff Garzik .name = DRV_NAME, 379c6fd2807SJeff Garzik .id_table = ahci_pci_tbl, 380c6fd2807SJeff Garzik .probe = ahci_init_one, 38124dc5f33STejun Heo .remove = ata_pci_remove_one, 382438ac6d5STejun Heo #ifdef CONFIG_PM 383c6fd2807SJeff Garzik .suspend = ahci_pci_device_suspend, 384c6fd2807SJeff Garzik .resume = ahci_pci_device_resume, 385438ac6d5STejun Heo #endif 386c6fd2807SJeff Garzik }; 387c6fd2807SJeff Garzik 3885b66c829SAlan Cox #if defined(CONFIG_PATA_MARVELL) || defined(CONFIG_PATA_MARVELL_MODULE) 3895b66c829SAlan Cox static int marvell_enable; 3905b66c829SAlan Cox #else 3915b66c829SAlan Cox static int marvell_enable = 1; 3925b66c829SAlan Cox #endif 3935b66c829SAlan Cox module_param(marvell_enable, int, 0644); 3945b66c829SAlan Cox MODULE_PARM_DESC(marvell_enable, "Marvell SATA via AHCI (1 = enabled)"); 3955b66c829SAlan Cox 3965b66c829SAlan Cox 397394d6e53SAnton Vorontsov static void ahci_pci_save_initial_config(struct pci_dev *pdev, 398394d6e53SAnton Vorontsov struct ahci_host_priv *hpriv) 399394d6e53SAnton Vorontsov { 400394d6e53SAnton Vorontsov unsigned int force_port_map = 0; 401394d6e53SAnton Vorontsov unsigned int mask_port_map = 0; 402394d6e53SAnton Vorontsov 403394d6e53SAnton Vorontsov if (pdev->vendor == PCI_VENDOR_ID_JMICRON && pdev->device == 0x2361) { 404394d6e53SAnton Vorontsov dev_info(&pdev->dev, "JMB361 has only one port\n"); 405394d6e53SAnton Vorontsov force_port_map = 1; 406394d6e53SAnton Vorontsov } 407394d6e53SAnton Vorontsov 408394d6e53SAnton Vorontsov /* 409394d6e53SAnton Vorontsov * Temporary Marvell 6145 hack: PATA port presence 410394d6e53SAnton Vorontsov * is asserted through the standard AHCI port 411394d6e53SAnton Vorontsov * presence register, as bit 4 (counting from 0) 412394d6e53SAnton Vorontsov */ 413394d6e53SAnton Vorontsov if (hpriv->flags & AHCI_HFLAG_MV_PATA) { 414394d6e53SAnton Vorontsov if (pdev->device == 0x6121) 415394d6e53SAnton Vorontsov mask_port_map = 0x3; 416394d6e53SAnton Vorontsov else 417394d6e53SAnton Vorontsov mask_port_map = 0xf; 418394d6e53SAnton Vorontsov dev_info(&pdev->dev, 419394d6e53SAnton Vorontsov "Disabling your PATA port. Use the boot option 'ahci.marvell_enable=0' to avoid this.\n"); 420394d6e53SAnton Vorontsov } 421394d6e53SAnton Vorontsov 4221d513358SAnton Vorontsov ahci_save_initial_config(&pdev->dev, hpriv, force_port_map, 4231d513358SAnton Vorontsov mask_port_map); 424394d6e53SAnton Vorontsov } 425394d6e53SAnton Vorontsov 4263303040dSAnton Vorontsov static int ahci_pci_reset_controller(struct ata_host *host) 4273303040dSAnton Vorontsov { 4283303040dSAnton Vorontsov struct pci_dev *pdev = to_pci_dev(host->dev); 4293303040dSAnton Vorontsov 4303303040dSAnton Vorontsov ahci_reset_controller(host); 4313303040dSAnton Vorontsov 432c6fd2807SJeff Garzik if (pdev->vendor == PCI_VENDOR_ID_INTEL) { 4333303040dSAnton Vorontsov struct ahci_host_priv *hpriv = host->private_data; 434c6fd2807SJeff Garzik u16 tmp16; 435c6fd2807SJeff Garzik 436c6fd2807SJeff Garzik /* configure PCS */ 437c6fd2807SJeff Garzik pci_read_config_word(pdev, 0x92, &tmp16); 43849f29090STejun Heo if ((tmp16 & hpriv->port_map) != hpriv->port_map) { 43949f29090STejun Heo tmp16 |= hpriv->port_map; 440c6fd2807SJeff Garzik pci_write_config_word(pdev, 0x92, tmp16); 441c6fd2807SJeff Garzik } 44249f29090STejun Heo } 443c6fd2807SJeff Garzik 444c6fd2807SJeff Garzik return 0; 445c6fd2807SJeff Garzik } 446c6fd2807SJeff Garzik 447781d6550SAnton Vorontsov static void ahci_pci_init_controller(struct ata_host *host) 448781d6550SAnton Vorontsov { 449781d6550SAnton Vorontsov struct ahci_host_priv *hpriv = host->private_data; 450781d6550SAnton Vorontsov struct pci_dev *pdev = to_pci_dev(host->dev); 451781d6550SAnton Vorontsov void __iomem *port_mmio; 452781d6550SAnton Vorontsov u32 tmp; 453c40e7cb8SJose Alberto Reguero int mv; 4542bcd866bSJeff Garzik 455417a1a6dSTejun Heo if (hpriv->flags & AHCI_HFLAG_MV_PATA) { 456c40e7cb8SJose Alberto Reguero if (pdev->device == 0x6121) 457c40e7cb8SJose Alberto Reguero mv = 2; 458c40e7cb8SJose Alberto Reguero else 459c40e7cb8SJose Alberto Reguero mv = 4; 460c40e7cb8SJose Alberto Reguero port_mmio = __ahci_port_base(host, mv); 461cd70c266SJeff Garzik 462cd70c266SJeff Garzik writel(0, port_mmio + PORT_IRQ_MASK); 463cd70c266SJeff Garzik 464cd70c266SJeff Garzik /* clear port IRQ */ 465cd70c266SJeff Garzik tmp = readl(port_mmio + PORT_IRQ_STAT); 466cd70c266SJeff Garzik VPRINTK("PORT_IRQ_STAT 0x%x\n", tmp); 467cd70c266SJeff Garzik if (tmp) 468cd70c266SJeff Garzik writel(tmp, port_mmio + PORT_IRQ_STAT); 469cd70c266SJeff Garzik } 470cd70c266SJeff Garzik 471781d6550SAnton Vorontsov ahci_init_controller(host); 472c6fd2807SJeff Garzik } 473c6fd2807SJeff Garzik 474bd17243aSShane Huang static int ahci_sb600_check_ready(struct ata_link *link) 475bd17243aSShane Huang { 476bd17243aSShane Huang void __iomem *port_mmio = ahci_port_base(link->ap); 477bd17243aSShane Huang u8 status = readl(port_mmio + PORT_TFDATA) & 0xFF; 478bd17243aSShane Huang u32 irq_status = readl(port_mmio + PORT_IRQ_STAT); 479bd17243aSShane Huang 480bd17243aSShane Huang /* 481bd17243aSShane Huang * There is no need to check TFDATA if BAD PMP is found due to HW bug, 482bd17243aSShane Huang * which can save timeout delay. 483bd17243aSShane Huang */ 484bd17243aSShane Huang if (irq_status & PORT_IRQ_BAD_PMP) 485bd17243aSShane Huang return -EIO; 486bd17243aSShane Huang 487bd17243aSShane Huang return ata_check_ready(status); 488bd17243aSShane Huang } 489bd17243aSShane Huang 490bd17243aSShane Huang static int ahci_sb600_softreset(struct ata_link *link, unsigned int *class, 491bd17243aSShane Huang unsigned long deadline) 492bd17243aSShane Huang { 493bd17243aSShane Huang struct ata_port *ap = link->ap; 494bd17243aSShane Huang void __iomem *port_mmio = ahci_port_base(ap); 495bd17243aSShane Huang int pmp = sata_srst_pmp(link); 496bd17243aSShane Huang int rc; 497bd17243aSShane Huang u32 irq_sts; 498bd17243aSShane Huang 499bd17243aSShane Huang DPRINTK("ENTER\n"); 500bd17243aSShane Huang 501bd17243aSShane Huang rc = ahci_do_softreset(link, class, pmp, deadline, 502bd17243aSShane Huang ahci_sb600_check_ready); 503bd17243aSShane Huang 504bd17243aSShane Huang /* 505bd17243aSShane Huang * Soft reset fails on some ATI chips with IPMS set when PMP 506bd17243aSShane Huang * is enabled but SATA HDD/ODD is connected to SATA port, 507bd17243aSShane Huang * do soft reset again to port 0. 508bd17243aSShane Huang */ 509bd17243aSShane Huang if (rc == -EIO) { 510bd17243aSShane Huang irq_sts = readl(port_mmio + PORT_IRQ_STAT); 511bd17243aSShane Huang if (irq_sts & PORT_IRQ_BAD_PMP) { 512bd17243aSShane Huang ata_link_printk(link, KERN_WARNING, 513b6931c1fSShane Huang "applying SB600 PMP SRST workaround " 514b6931c1fSShane Huang "and retrying\n"); 515bd17243aSShane Huang rc = ahci_do_softreset(link, class, 0, deadline, 516bd17243aSShane Huang ahci_check_ready); 517bd17243aSShane Huang } 518bd17243aSShane Huang } 519bd17243aSShane Huang 520bd17243aSShane Huang return rc; 521bd17243aSShane Huang } 522bd17243aSShane Huang 523cc0680a5STejun Heo static int ahci_vt8251_hardreset(struct ata_link *link, unsigned int *class, 524d4b2bab4STejun Heo unsigned long deadline) 525ad616ffbSTejun Heo { 526cc0680a5STejun Heo struct ata_port *ap = link->ap; 5279dadd45bSTejun Heo bool online; 528ad616ffbSTejun Heo int rc; 529ad616ffbSTejun Heo 530ad616ffbSTejun Heo DPRINTK("ENTER\n"); 531ad616ffbSTejun Heo 5324447d351STejun Heo ahci_stop_engine(ap); 533ad616ffbSTejun Heo 534cc0680a5STejun Heo rc = sata_link_hardreset(link, sata_ehc_deb_timing(&link->eh_context), 5359dadd45bSTejun Heo deadline, &online, NULL); 536ad616ffbSTejun Heo 5374447d351STejun Heo ahci_start_engine(ap); 538ad616ffbSTejun Heo 539ad616ffbSTejun Heo DPRINTK("EXIT, rc=%d, class=%u\n", rc, *class); 540ad616ffbSTejun Heo 541ad616ffbSTejun Heo /* vt8251 doesn't clear BSY on signature FIS reception, 542ad616ffbSTejun Heo * request follow-up softreset. 543ad616ffbSTejun Heo */ 5449dadd45bSTejun Heo return online ? -EAGAIN : rc; 545ad616ffbSTejun Heo } 546ad616ffbSTejun Heo 547edc93052STejun Heo static int ahci_p5wdh_hardreset(struct ata_link *link, unsigned int *class, 548edc93052STejun Heo unsigned long deadline) 549edc93052STejun Heo { 550edc93052STejun Heo struct ata_port *ap = link->ap; 551edc93052STejun Heo struct ahci_port_priv *pp = ap->private_data; 552edc93052STejun Heo u8 *d2h_fis = pp->rx_fis + RX_FIS_D2H_REG; 553edc93052STejun Heo struct ata_taskfile tf; 5549dadd45bSTejun Heo bool online; 555edc93052STejun Heo int rc; 556edc93052STejun Heo 557edc93052STejun Heo ahci_stop_engine(ap); 558edc93052STejun Heo 559edc93052STejun Heo /* clear D2H reception area to properly wait for D2H FIS */ 560edc93052STejun Heo ata_tf_init(link->device, &tf); 561edc93052STejun Heo tf.command = 0x80; 562edc93052STejun Heo ata_tf_to_fis(&tf, 0, 0, d2h_fis); 563edc93052STejun Heo 564edc93052STejun Heo rc = sata_link_hardreset(link, sata_ehc_deb_timing(&link->eh_context), 5659dadd45bSTejun Heo deadline, &online, NULL); 566edc93052STejun Heo 567edc93052STejun Heo ahci_start_engine(ap); 568edc93052STejun Heo 569edc93052STejun Heo /* The pseudo configuration device on SIMG4726 attached to 570edc93052STejun Heo * ASUS P5W-DH Deluxe doesn't send signature FIS after 571edc93052STejun Heo * hardreset if no device is attached to the first downstream 572edc93052STejun Heo * port && the pseudo device locks up on SRST w/ PMP==0. To 573edc93052STejun Heo * work around this, wait for !BSY only briefly. If BSY isn't 574edc93052STejun Heo * cleared, perform CLO and proceed to IDENTIFY (achieved by 575edc93052STejun Heo * ATA_LFLAG_NO_SRST and ATA_LFLAG_ASSUME_ATA). 576edc93052STejun Heo * 577edc93052STejun Heo * Wait for two seconds. Devices attached to downstream port 578edc93052STejun Heo * which can't process the following IDENTIFY after this will 579edc93052STejun Heo * have to be reset again. For most cases, this should 580edc93052STejun Heo * suffice while making probing snappish enough. 581edc93052STejun Heo */ 5829dadd45bSTejun Heo if (online) { 5839dadd45bSTejun Heo rc = ata_wait_after_reset(link, jiffies + 2 * HZ, 5849dadd45bSTejun Heo ahci_check_ready); 585edc93052STejun Heo if (rc) 58678d5ae39SShane Huang ahci_kick_engine(ap); 5879dadd45bSTejun Heo } 5889dadd45bSTejun Heo return rc; 589edc93052STejun Heo } 590edc93052STejun Heo 591438ac6d5STejun Heo #ifdef CONFIG_PM 592c6fd2807SJeff Garzik static int ahci_pci_device_suspend(struct pci_dev *pdev, pm_message_t mesg) 593c6fd2807SJeff Garzik { 594cca3974eSJeff Garzik struct ata_host *host = dev_get_drvdata(&pdev->dev); 5959b10ae86STejun Heo struct ahci_host_priv *hpriv = host->private_data; 596d8993349SAnton Vorontsov void __iomem *mmio = hpriv->mmio; 597c6fd2807SJeff Garzik u32 ctl; 598c6fd2807SJeff Garzik 5999b10ae86STejun Heo if (mesg.event & PM_EVENT_SUSPEND && 6009b10ae86STejun Heo hpriv->flags & AHCI_HFLAG_NO_SUSPEND) { 6019b10ae86STejun Heo dev_printk(KERN_ERR, &pdev->dev, 6029b10ae86STejun Heo "BIOS update required for suspend/resume\n"); 6039b10ae86STejun Heo return -EIO; 6049b10ae86STejun Heo } 6059b10ae86STejun Heo 6063a2d5b70SRafael J. Wysocki if (mesg.event & PM_EVENT_SLEEP) { 607c6fd2807SJeff Garzik /* AHCI spec rev1.1 section 8.3.3: 608c6fd2807SJeff Garzik * Software must disable interrupts prior to requesting a 609c6fd2807SJeff Garzik * transition of the HBA to D3 state. 610c6fd2807SJeff Garzik */ 611c6fd2807SJeff Garzik ctl = readl(mmio + HOST_CTL); 612c6fd2807SJeff Garzik ctl &= ~HOST_IRQ_EN; 613c6fd2807SJeff Garzik writel(ctl, mmio + HOST_CTL); 614c6fd2807SJeff Garzik readl(mmio + HOST_CTL); /* flush */ 615c6fd2807SJeff Garzik } 616c6fd2807SJeff Garzik 617c6fd2807SJeff Garzik return ata_pci_device_suspend(pdev, mesg); 618c6fd2807SJeff Garzik } 619c6fd2807SJeff Garzik 620c6fd2807SJeff Garzik static int ahci_pci_device_resume(struct pci_dev *pdev) 621c6fd2807SJeff Garzik { 622cca3974eSJeff Garzik struct ata_host *host = dev_get_drvdata(&pdev->dev); 623c6fd2807SJeff Garzik int rc; 624c6fd2807SJeff Garzik 625553c4aa6STejun Heo rc = ata_pci_device_do_resume(pdev); 626553c4aa6STejun Heo if (rc) 627553c4aa6STejun Heo return rc; 628c6fd2807SJeff Garzik 629c6fd2807SJeff Garzik if (pdev->dev.power.power_state.event == PM_EVENT_SUSPEND) { 6303303040dSAnton Vorontsov rc = ahci_pci_reset_controller(host); 631c6fd2807SJeff Garzik if (rc) 632c6fd2807SJeff Garzik return rc; 633c6fd2807SJeff Garzik 634781d6550SAnton Vorontsov ahci_pci_init_controller(host); 635c6fd2807SJeff Garzik } 636c6fd2807SJeff Garzik 637cca3974eSJeff Garzik ata_host_resume(host); 638c6fd2807SJeff Garzik 639c6fd2807SJeff Garzik return 0; 640c6fd2807SJeff Garzik } 641438ac6d5STejun Heo #endif 642c6fd2807SJeff Garzik 6434447d351STejun Heo static int ahci_configure_dma_masks(struct pci_dev *pdev, int using_dac) 644c6fd2807SJeff Garzik { 645c6fd2807SJeff Garzik int rc; 646c6fd2807SJeff Garzik 647c6fd2807SJeff Garzik if (using_dac && 6486a35528aSYang Hongyang !pci_set_dma_mask(pdev, DMA_BIT_MASK(64))) { 6496a35528aSYang Hongyang rc = pci_set_consistent_dma_mask(pdev, DMA_BIT_MASK(64)); 650c6fd2807SJeff Garzik if (rc) { 651284901a9SYang Hongyang rc = pci_set_consistent_dma_mask(pdev, DMA_BIT_MASK(32)); 652c6fd2807SJeff Garzik if (rc) { 653c6fd2807SJeff Garzik dev_printk(KERN_ERR, &pdev->dev, 654c6fd2807SJeff Garzik "64-bit DMA enable failed\n"); 655c6fd2807SJeff Garzik return rc; 656c6fd2807SJeff Garzik } 657c6fd2807SJeff Garzik } 658c6fd2807SJeff Garzik } else { 659284901a9SYang Hongyang rc = pci_set_dma_mask(pdev, DMA_BIT_MASK(32)); 660c6fd2807SJeff Garzik if (rc) { 661c6fd2807SJeff Garzik dev_printk(KERN_ERR, &pdev->dev, 662c6fd2807SJeff Garzik "32-bit DMA enable failed\n"); 663c6fd2807SJeff Garzik return rc; 664c6fd2807SJeff Garzik } 665284901a9SYang Hongyang rc = pci_set_consistent_dma_mask(pdev, DMA_BIT_MASK(32)); 666c6fd2807SJeff Garzik if (rc) { 667c6fd2807SJeff Garzik dev_printk(KERN_ERR, &pdev->dev, 668c6fd2807SJeff Garzik "32-bit consistent DMA enable failed\n"); 669c6fd2807SJeff Garzik return rc; 670c6fd2807SJeff Garzik } 671c6fd2807SJeff Garzik } 672c6fd2807SJeff Garzik return 0; 673c6fd2807SJeff Garzik } 674c6fd2807SJeff Garzik 675439fcaecSAnton Vorontsov static void ahci_pci_print_info(struct ata_host *host) 676439fcaecSAnton Vorontsov { 677439fcaecSAnton Vorontsov struct pci_dev *pdev = to_pci_dev(host->dev); 678439fcaecSAnton Vorontsov u16 cc; 679439fcaecSAnton Vorontsov const char *scc_s; 680439fcaecSAnton Vorontsov 681439fcaecSAnton Vorontsov pci_read_config_word(pdev, 0x0a, &cc); 682439fcaecSAnton Vorontsov if (cc == PCI_CLASS_STORAGE_IDE) 683439fcaecSAnton Vorontsov scc_s = "IDE"; 684439fcaecSAnton Vorontsov else if (cc == PCI_CLASS_STORAGE_SATA) 685439fcaecSAnton Vorontsov scc_s = "SATA"; 686439fcaecSAnton Vorontsov else if (cc == PCI_CLASS_STORAGE_RAID) 687439fcaecSAnton Vorontsov scc_s = "RAID"; 688439fcaecSAnton Vorontsov else 689439fcaecSAnton Vorontsov scc_s = "unknown"; 690439fcaecSAnton Vorontsov 691439fcaecSAnton Vorontsov ahci_print_info(host, scc_s); 692439fcaecSAnton Vorontsov } 693439fcaecSAnton Vorontsov 694edc93052STejun Heo /* On ASUS P5W DH Deluxe, the second port of PCI device 00:1f.2 is 695edc93052STejun Heo * hardwired to on-board SIMG 4726. The chipset is ICH8 and doesn't 696edc93052STejun Heo * support PMP and the 4726 either directly exports the device 697edc93052STejun Heo * attached to the first downstream port or acts as a hardware storage 698edc93052STejun Heo * controller and emulate a single ATA device (can be RAID 0/1 or some 699edc93052STejun Heo * other configuration). 700edc93052STejun Heo * 701edc93052STejun Heo * When there's no device attached to the first downstream port of the 702edc93052STejun Heo * 4726, "Config Disk" appears, which is a pseudo ATA device to 703edc93052STejun Heo * configure the 4726. However, ATA emulation of the device is very 704edc93052STejun Heo * lame. It doesn't send signature D2H Reg FIS after the initial 705edc93052STejun Heo * hardreset, pukes on SRST w/ PMP==0 and has bunch of other issues. 706edc93052STejun Heo * 707edc93052STejun Heo * The following function works around the problem by always using 708edc93052STejun Heo * hardreset on the port and not depending on receiving signature FIS 709edc93052STejun Heo * afterward. If signature FIS isn't received soon, ATA class is 710edc93052STejun Heo * assumed without follow-up softreset. 711edc93052STejun Heo */ 712edc93052STejun Heo static void ahci_p5wdh_workaround(struct ata_host *host) 713edc93052STejun Heo { 714edc93052STejun Heo static struct dmi_system_id sysids[] = { 715edc93052STejun Heo { 716edc93052STejun Heo .ident = "P5W DH Deluxe", 717edc93052STejun Heo .matches = { 718edc93052STejun Heo DMI_MATCH(DMI_SYS_VENDOR, 719edc93052STejun Heo "ASUSTEK COMPUTER INC"), 720edc93052STejun Heo DMI_MATCH(DMI_PRODUCT_NAME, "P5W DH Deluxe"), 721edc93052STejun Heo }, 722edc93052STejun Heo }, 723edc93052STejun Heo { } 724edc93052STejun Heo }; 725edc93052STejun Heo struct pci_dev *pdev = to_pci_dev(host->dev); 726edc93052STejun Heo 727edc93052STejun Heo if (pdev->bus->number == 0 && pdev->devfn == PCI_DEVFN(0x1f, 2) && 728edc93052STejun Heo dmi_check_system(sysids)) { 729edc93052STejun Heo struct ata_port *ap = host->ports[1]; 730edc93052STejun Heo 731edc93052STejun Heo dev_printk(KERN_INFO, &pdev->dev, "enabling ASUS P5W DH " 732edc93052STejun Heo "Deluxe on-board SIMG4726 workaround\n"); 733edc93052STejun Heo 734edc93052STejun Heo ap->ops = &ahci_p5wdh_ops; 735edc93052STejun Heo ap->link.flags |= ATA_LFLAG_NO_SRST | ATA_LFLAG_ASSUME_ATA; 736edc93052STejun Heo } 737edc93052STejun Heo } 738edc93052STejun Heo 7392fcad9d2STejun Heo /* only some SB600 ahci controllers can do 64bit DMA */ 7402fcad9d2STejun Heo static bool ahci_sb600_enable_64bit(struct pci_dev *pdev) 74158a09b38SShane Huang { 74258a09b38SShane Huang static const struct dmi_system_id sysids[] = { 74303d783bfSTejun Heo /* 74403d783bfSTejun Heo * The oldest version known to be broken is 0901 and 74503d783bfSTejun Heo * working is 1501 which was released on 2007-10-26. 7462fcad9d2STejun Heo * Enable 64bit DMA on 1501 and anything newer. 7472fcad9d2STejun Heo * 74803d783bfSTejun Heo * Please read bko#9412 for more info. 74903d783bfSTejun Heo */ 75058a09b38SShane Huang { 75158a09b38SShane Huang .ident = "ASUS M2A-VM", 75258a09b38SShane Huang .matches = { 75358a09b38SShane Huang DMI_MATCH(DMI_BOARD_VENDOR, 75458a09b38SShane Huang "ASUSTeK Computer INC."), 75558a09b38SShane Huang DMI_MATCH(DMI_BOARD_NAME, "M2A-VM"), 75658a09b38SShane Huang }, 75703d783bfSTejun Heo .driver_data = "20071026", /* yyyymmdd */ 75858a09b38SShane Huang }, 759e65cc194SMark Nelson /* 760e65cc194SMark Nelson * All BIOS versions for the MSI K9A2 Platinum (MS-7376) 761e65cc194SMark Nelson * support 64bit DMA. 762e65cc194SMark Nelson * 763e65cc194SMark Nelson * BIOS versions earlier than 1.5 had the Manufacturer DMI 764e65cc194SMark Nelson * fields as "MICRO-STAR INTERANTIONAL CO.,LTD". 765e65cc194SMark Nelson * This spelling mistake was fixed in BIOS version 1.5, so 766e65cc194SMark Nelson * 1.5 and later have the Manufacturer as 767e65cc194SMark Nelson * "MICRO-STAR INTERNATIONAL CO.,LTD". 768e65cc194SMark Nelson * So try to match on DMI_BOARD_VENDOR of "MICRO-STAR INTER". 769e65cc194SMark Nelson * 770e65cc194SMark Nelson * BIOS versions earlier than 1.9 had a Board Product Name 771e65cc194SMark Nelson * DMI field of "MS-7376". This was changed to be 772e65cc194SMark Nelson * "K9A2 Platinum (MS-7376)" in version 1.9, but we can still 773e65cc194SMark Nelson * match on DMI_BOARD_NAME of "MS-7376". 774e65cc194SMark Nelson */ 775e65cc194SMark Nelson { 776e65cc194SMark Nelson .ident = "MSI K9A2 Platinum", 777e65cc194SMark Nelson .matches = { 778e65cc194SMark Nelson DMI_MATCH(DMI_BOARD_VENDOR, 779e65cc194SMark Nelson "MICRO-STAR INTER"), 780e65cc194SMark Nelson DMI_MATCH(DMI_BOARD_NAME, "MS-7376"), 781e65cc194SMark Nelson }, 782e65cc194SMark Nelson }, 78358a09b38SShane Huang { } 78458a09b38SShane Huang }; 78503d783bfSTejun Heo const struct dmi_system_id *match; 7862fcad9d2STejun Heo int year, month, date; 7872fcad9d2STejun Heo char buf[9]; 78858a09b38SShane Huang 78903d783bfSTejun Heo match = dmi_first_match(sysids); 79058a09b38SShane Huang if (pdev->bus->number != 0 || pdev->devfn != PCI_DEVFN(0x12, 0) || 79103d783bfSTejun Heo !match) 79258a09b38SShane Huang return false; 79358a09b38SShane Huang 794e65cc194SMark Nelson if (!match->driver_data) 795e65cc194SMark Nelson goto enable_64bit; 796e65cc194SMark Nelson 79703d783bfSTejun Heo dmi_get_date(DMI_BIOS_DATE, &year, &month, &date); 79803d783bfSTejun Heo snprintf(buf, sizeof(buf), "%04d%02d%02d", year, month, date); 79903d783bfSTejun Heo 800e65cc194SMark Nelson if (strcmp(buf, match->driver_data) >= 0) 801e65cc194SMark Nelson goto enable_64bit; 802e65cc194SMark Nelson else { 80303d783bfSTejun Heo dev_printk(KERN_WARNING, &pdev->dev, "%s: BIOS too old, " 80403d783bfSTejun Heo "forcing 32bit DMA, update BIOS\n", match->ident); 8052fcad9d2STejun Heo return false; 8062fcad9d2STejun Heo } 807e65cc194SMark Nelson 808e65cc194SMark Nelson enable_64bit: 809e65cc194SMark Nelson dev_printk(KERN_WARNING, &pdev->dev, "%s: enabling 64bit DMA\n", 810e65cc194SMark Nelson match->ident); 811e65cc194SMark Nelson return true; 81258a09b38SShane Huang } 81358a09b38SShane Huang 8141fd68434SRafael J. Wysocki static bool ahci_broken_system_poweroff(struct pci_dev *pdev) 8151fd68434SRafael J. Wysocki { 8161fd68434SRafael J. Wysocki static const struct dmi_system_id broken_systems[] = { 8171fd68434SRafael J. Wysocki { 8181fd68434SRafael J. Wysocki .ident = "HP Compaq nx6310", 8191fd68434SRafael J. Wysocki .matches = { 8201fd68434SRafael J. Wysocki DMI_MATCH(DMI_SYS_VENDOR, "Hewlett-Packard"), 8211fd68434SRafael J. Wysocki DMI_MATCH(DMI_PRODUCT_NAME, "HP Compaq nx6310"), 8221fd68434SRafael J. Wysocki }, 8231fd68434SRafael J. Wysocki /* PCI slot number of the controller */ 8241fd68434SRafael J. Wysocki .driver_data = (void *)0x1FUL, 8251fd68434SRafael J. Wysocki }, 826d2f9c061SMaciej Rutecki { 827d2f9c061SMaciej Rutecki .ident = "HP Compaq 6720s", 828d2f9c061SMaciej Rutecki .matches = { 829d2f9c061SMaciej Rutecki DMI_MATCH(DMI_SYS_VENDOR, "Hewlett-Packard"), 830d2f9c061SMaciej Rutecki DMI_MATCH(DMI_PRODUCT_NAME, "HP Compaq 6720s"), 831d2f9c061SMaciej Rutecki }, 832d2f9c061SMaciej Rutecki /* PCI slot number of the controller */ 833d2f9c061SMaciej Rutecki .driver_data = (void *)0x1FUL, 834d2f9c061SMaciej Rutecki }, 8351fd68434SRafael J. Wysocki 8361fd68434SRafael J. Wysocki { } /* terminate list */ 8371fd68434SRafael J. Wysocki }; 8381fd68434SRafael J. Wysocki const struct dmi_system_id *dmi = dmi_first_match(broken_systems); 8391fd68434SRafael J. Wysocki 8401fd68434SRafael J. Wysocki if (dmi) { 8411fd68434SRafael J. Wysocki unsigned long slot = (unsigned long)dmi->driver_data; 8421fd68434SRafael J. Wysocki /* apply the quirk only to on-board controllers */ 8431fd68434SRafael J. Wysocki return slot == PCI_SLOT(pdev->devfn); 8441fd68434SRafael J. Wysocki } 8451fd68434SRafael J. Wysocki 8461fd68434SRafael J. Wysocki return false; 8471fd68434SRafael J. Wysocki } 8481fd68434SRafael J. Wysocki 8499b10ae86STejun Heo static bool ahci_broken_suspend(struct pci_dev *pdev) 8509b10ae86STejun Heo { 8519b10ae86STejun Heo static const struct dmi_system_id sysids[] = { 8529b10ae86STejun Heo /* 8539b10ae86STejun Heo * On HP dv[4-6] and HDX18 with earlier BIOSen, link 8549b10ae86STejun Heo * to the harddisk doesn't become online after 8559b10ae86STejun Heo * resuming from STR. Warn and fail suspend. 8569deb3431STejun Heo * 8579deb3431STejun Heo * http://bugzilla.kernel.org/show_bug.cgi?id=12276 8589deb3431STejun Heo * 8599deb3431STejun Heo * Use dates instead of versions to match as HP is 8609deb3431STejun Heo * apparently recycling both product and version 8619deb3431STejun Heo * strings. 8629deb3431STejun Heo * 8639deb3431STejun Heo * http://bugzilla.kernel.org/show_bug.cgi?id=15462 8649b10ae86STejun Heo */ 8659b10ae86STejun Heo { 8669b10ae86STejun Heo .ident = "dv4", 8679b10ae86STejun Heo .matches = { 8689b10ae86STejun Heo DMI_MATCH(DMI_SYS_VENDOR, "Hewlett-Packard"), 8699b10ae86STejun Heo DMI_MATCH(DMI_PRODUCT_NAME, 8709b10ae86STejun Heo "HP Pavilion dv4 Notebook PC"), 8719b10ae86STejun Heo }, 8729deb3431STejun Heo .driver_data = "20090105", /* F.30 */ 8739b10ae86STejun Heo }, 8749b10ae86STejun Heo { 8759b10ae86STejun Heo .ident = "dv5", 8769b10ae86STejun Heo .matches = { 8779b10ae86STejun Heo DMI_MATCH(DMI_SYS_VENDOR, "Hewlett-Packard"), 8789b10ae86STejun Heo DMI_MATCH(DMI_PRODUCT_NAME, 8799b10ae86STejun Heo "HP Pavilion dv5 Notebook PC"), 8809b10ae86STejun Heo }, 8819deb3431STejun Heo .driver_data = "20090506", /* F.16 */ 8829b10ae86STejun Heo }, 8839b10ae86STejun Heo { 8849b10ae86STejun Heo .ident = "dv6", 8859b10ae86STejun Heo .matches = { 8869b10ae86STejun Heo DMI_MATCH(DMI_SYS_VENDOR, "Hewlett-Packard"), 8879b10ae86STejun Heo DMI_MATCH(DMI_PRODUCT_NAME, 8889b10ae86STejun Heo "HP Pavilion dv6 Notebook PC"), 8899b10ae86STejun Heo }, 8909deb3431STejun Heo .driver_data = "20090423", /* F.21 */ 8919b10ae86STejun Heo }, 8929b10ae86STejun Heo { 8939b10ae86STejun Heo .ident = "HDX18", 8949b10ae86STejun Heo .matches = { 8959b10ae86STejun Heo DMI_MATCH(DMI_SYS_VENDOR, "Hewlett-Packard"), 8969b10ae86STejun Heo DMI_MATCH(DMI_PRODUCT_NAME, 8979b10ae86STejun Heo "HP HDX18 Notebook PC"), 8989b10ae86STejun Heo }, 8999deb3431STejun Heo .driver_data = "20090430", /* F.23 */ 9009b10ae86STejun Heo }, 901cedc9bf9STejun Heo /* 902cedc9bf9STejun Heo * Acer eMachines G725 has the same problem. BIOS 903cedc9bf9STejun Heo * V1.03 is known to be broken. V3.04 is known to 904cedc9bf9STejun Heo * work. Inbetween, there are V1.06, V2.06 and V3.03 905cedc9bf9STejun Heo * that we don't have much idea about. For now, 906cedc9bf9STejun Heo * blacklist anything older than V3.04. 9079deb3431STejun Heo * 9089deb3431STejun Heo * http://bugzilla.kernel.org/show_bug.cgi?id=15104 909cedc9bf9STejun Heo */ 910cedc9bf9STejun Heo { 911cedc9bf9STejun Heo .ident = "G725", 912cedc9bf9STejun Heo .matches = { 913cedc9bf9STejun Heo DMI_MATCH(DMI_SYS_VENDOR, "eMachines"), 914cedc9bf9STejun Heo DMI_MATCH(DMI_PRODUCT_NAME, "eMachines G725"), 915cedc9bf9STejun Heo }, 9169deb3431STejun Heo .driver_data = "20091216", /* V3.04 */ 917cedc9bf9STejun Heo }, 9189b10ae86STejun Heo { } /* terminate list */ 9199b10ae86STejun Heo }; 9209b10ae86STejun Heo const struct dmi_system_id *dmi = dmi_first_match(sysids); 9219deb3431STejun Heo int year, month, date; 9229deb3431STejun Heo char buf[9]; 9239b10ae86STejun Heo 9249b10ae86STejun Heo if (!dmi || pdev->bus->number || pdev->devfn != PCI_DEVFN(0x1f, 2)) 9259b10ae86STejun Heo return false; 9269b10ae86STejun Heo 9279deb3431STejun Heo dmi_get_date(DMI_BIOS_DATE, &year, &month, &date); 9289deb3431STejun Heo snprintf(buf, sizeof(buf), "%04d%02d%02d", year, month, date); 9299b10ae86STejun Heo 9309deb3431STejun Heo return strcmp(buf, dmi->driver_data) < 0; 9319b10ae86STejun Heo } 9329b10ae86STejun Heo 9335594639aSTejun Heo static bool ahci_broken_online(struct pci_dev *pdev) 9345594639aSTejun Heo { 9355594639aSTejun Heo #define ENCODE_BUSDEVFN(bus, slot, func) \ 9365594639aSTejun Heo (void *)(unsigned long)(((bus) << 8) | PCI_DEVFN((slot), (func))) 9375594639aSTejun Heo static const struct dmi_system_id sysids[] = { 9385594639aSTejun Heo /* 9395594639aSTejun Heo * There are several gigabyte boards which use 9405594639aSTejun Heo * SIMG5723s configured as hardware RAID. Certain 9415594639aSTejun Heo * 5723 firmware revisions shipped there keep the link 9425594639aSTejun Heo * online but fail to answer properly to SRST or 9435594639aSTejun Heo * IDENTIFY when no device is attached downstream 9445594639aSTejun Heo * causing libata to retry quite a few times leading 9455594639aSTejun Heo * to excessive detection delay. 9465594639aSTejun Heo * 9475594639aSTejun Heo * As these firmwares respond to the second reset try 9485594639aSTejun Heo * with invalid device signature, considering unknown 9495594639aSTejun Heo * sig as offline works around the problem acceptably. 9505594639aSTejun Heo */ 9515594639aSTejun Heo { 9525594639aSTejun Heo .ident = "EP45-DQ6", 9535594639aSTejun Heo .matches = { 9545594639aSTejun Heo DMI_MATCH(DMI_BOARD_VENDOR, 9555594639aSTejun Heo "Gigabyte Technology Co., Ltd."), 9565594639aSTejun Heo DMI_MATCH(DMI_BOARD_NAME, "EP45-DQ6"), 9575594639aSTejun Heo }, 9585594639aSTejun Heo .driver_data = ENCODE_BUSDEVFN(0x0a, 0x00, 0), 9595594639aSTejun Heo }, 9605594639aSTejun Heo { 9615594639aSTejun Heo .ident = "EP45-DS5", 9625594639aSTejun Heo .matches = { 9635594639aSTejun Heo DMI_MATCH(DMI_BOARD_VENDOR, 9645594639aSTejun Heo "Gigabyte Technology Co., Ltd."), 9655594639aSTejun Heo DMI_MATCH(DMI_BOARD_NAME, "EP45-DS5"), 9665594639aSTejun Heo }, 9675594639aSTejun Heo .driver_data = ENCODE_BUSDEVFN(0x03, 0x00, 0), 9685594639aSTejun Heo }, 9695594639aSTejun Heo { } /* terminate list */ 9705594639aSTejun Heo }; 9715594639aSTejun Heo #undef ENCODE_BUSDEVFN 9725594639aSTejun Heo const struct dmi_system_id *dmi = dmi_first_match(sysids); 9735594639aSTejun Heo unsigned int val; 9745594639aSTejun Heo 9755594639aSTejun Heo if (!dmi) 9765594639aSTejun Heo return false; 9775594639aSTejun Heo 9785594639aSTejun Heo val = (unsigned long)dmi->driver_data; 9795594639aSTejun Heo 9805594639aSTejun Heo return pdev->bus->number == (val >> 8) && pdev->devfn == (val & 0xff); 9815594639aSTejun Heo } 9825594639aSTejun Heo 9838e513217SMarkus Trippelsdorf #ifdef CONFIG_ATA_ACPI 984f80ae7e4STejun Heo static void ahci_gtf_filter_workaround(struct ata_host *host) 985f80ae7e4STejun Heo { 986f80ae7e4STejun Heo static const struct dmi_system_id sysids[] = { 987f80ae7e4STejun Heo /* 988f80ae7e4STejun Heo * Aspire 3810T issues a bunch of SATA enable commands 989f80ae7e4STejun Heo * via _GTF including an invalid one and one which is 990f80ae7e4STejun Heo * rejected by the device. Among the successful ones 991f80ae7e4STejun Heo * is FPDMA non-zero offset enable which when enabled 992f80ae7e4STejun Heo * only on the drive side leads to NCQ command 993f80ae7e4STejun Heo * failures. Filter it out. 994f80ae7e4STejun Heo */ 995f80ae7e4STejun Heo { 996f80ae7e4STejun Heo .ident = "Aspire 3810T", 997f80ae7e4STejun Heo .matches = { 998f80ae7e4STejun Heo DMI_MATCH(DMI_SYS_VENDOR, "Acer"), 999f80ae7e4STejun Heo DMI_MATCH(DMI_PRODUCT_NAME, "Aspire 3810T"), 1000f80ae7e4STejun Heo }, 1001f80ae7e4STejun Heo .driver_data = (void *)ATA_ACPI_FILTER_FPDMA_OFFSET, 1002f80ae7e4STejun Heo }, 1003f80ae7e4STejun Heo { } 1004f80ae7e4STejun Heo }; 1005f80ae7e4STejun Heo const struct dmi_system_id *dmi = dmi_first_match(sysids); 1006f80ae7e4STejun Heo unsigned int filter; 1007f80ae7e4STejun Heo int i; 1008f80ae7e4STejun Heo 1009f80ae7e4STejun Heo if (!dmi) 1010f80ae7e4STejun Heo return; 1011f80ae7e4STejun Heo 1012f80ae7e4STejun Heo filter = (unsigned long)dmi->driver_data; 1013f80ae7e4STejun Heo dev_printk(KERN_INFO, host->dev, 1014f80ae7e4STejun Heo "applying extra ACPI _GTF filter 0x%x for %s\n", 1015f80ae7e4STejun Heo filter, dmi->ident); 1016f80ae7e4STejun Heo 1017f80ae7e4STejun Heo for (i = 0; i < host->n_ports; i++) { 1018f80ae7e4STejun Heo struct ata_port *ap = host->ports[i]; 1019f80ae7e4STejun Heo struct ata_link *link; 1020f80ae7e4STejun Heo struct ata_device *dev; 1021f80ae7e4STejun Heo 1022f80ae7e4STejun Heo ata_for_each_link(link, ap, EDGE) 1023f80ae7e4STejun Heo ata_for_each_dev(dev, link, ALL) 1024f80ae7e4STejun Heo dev->gtf_filter |= filter; 1025f80ae7e4STejun Heo } 1026f80ae7e4STejun Heo } 10278e513217SMarkus Trippelsdorf #else 10288e513217SMarkus Trippelsdorf static inline void ahci_gtf_filter_workaround(struct ata_host *host) 10298e513217SMarkus Trippelsdorf {} 10308e513217SMarkus Trippelsdorf #endif 1031f80ae7e4STejun Heo 1032c6fd2807SJeff Garzik static int ahci_init_one(struct pci_dev *pdev, const struct pci_device_id *ent) 1033c6fd2807SJeff Garzik { 1034c6fd2807SJeff Garzik static int printed_version; 1035e297d99eSTejun Heo unsigned int board_id = ent->driver_data; 1036e297d99eSTejun Heo struct ata_port_info pi = ahci_port_info[board_id]; 10374447d351STejun Heo const struct ata_port_info *ppi[] = { &pi, NULL }; 103824dc5f33STejun Heo struct device *dev = &pdev->dev; 1039c6fd2807SJeff Garzik struct ahci_host_priv *hpriv; 10404447d351STejun Heo struct ata_host *host; 1041837f5f8fSTejun Heo int n_ports, i, rc; 1042c6fd2807SJeff Garzik 1043c6fd2807SJeff Garzik VPRINTK("ENTER\n"); 1044c6fd2807SJeff Garzik 1045c6fd2807SJeff Garzik WARN_ON(ATA_MAX_QUEUE > AHCI_MAX_CMDS); 1046c6fd2807SJeff Garzik 1047c6fd2807SJeff Garzik if (!printed_version++) 1048c6fd2807SJeff Garzik dev_printk(KERN_DEBUG, &pdev->dev, "version " DRV_VERSION "\n"); 1049c6fd2807SJeff Garzik 10505b66c829SAlan Cox /* The AHCI driver can only drive the SATA ports, the PATA driver 10515b66c829SAlan Cox can drive them all so if both drivers are selected make sure 10525b66c829SAlan Cox AHCI stays out of the way */ 10535b66c829SAlan Cox if (pdev->vendor == PCI_VENDOR_ID_MARVELL && !marvell_enable) 10545b66c829SAlan Cox return -ENODEV; 10555b66c829SAlan Cox 1056*c6353b45STejun Heo /* 1057*c6353b45STejun Heo * For some reason, MCP89 on MacBook 7,1 doesn't work with 1058*c6353b45STejun Heo * ahci, use ata_generic instead. 1059*c6353b45STejun Heo */ 1060*c6353b45STejun Heo if (pdev->vendor == PCI_VENDOR_ID_NVIDIA && 1061*c6353b45STejun Heo pdev->device == PCI_DEVICE_ID_NVIDIA_NFORCE_MCP89_SATA && 1062*c6353b45STejun Heo pdev->subsystem_vendor == PCI_VENDOR_ID_APPLE && 1063*c6353b45STejun Heo pdev->subsystem_device == 0xcb89) 1064*c6353b45STejun Heo return -ENODEV; 1065*c6353b45STejun Heo 10667a02267eSMark Nelson /* Promise's PDC42819 is a SAS/SATA controller that has an AHCI mode. 10677a02267eSMark Nelson * At the moment, we can only use the AHCI mode. Let the users know 10687a02267eSMark Nelson * that for SAS drives they're out of luck. 10697a02267eSMark Nelson */ 10707a02267eSMark Nelson if (pdev->vendor == PCI_VENDOR_ID_PROMISE) 10717a02267eSMark Nelson dev_printk(KERN_INFO, &pdev->dev, "PDC42819 " 10727a02267eSMark Nelson "can only drive SATA devices with this driver\n"); 10737a02267eSMark Nelson 10744447d351STejun Heo /* acquire resources */ 107524dc5f33STejun Heo rc = pcim_enable_device(pdev); 1076c6fd2807SJeff Garzik if (rc) 1077c6fd2807SJeff Garzik return rc; 1078c6fd2807SJeff Garzik 1079dea55137STejun Heo /* AHCI controllers often implement SFF compatible interface. 1080dea55137STejun Heo * Grab all PCI BARs just in case. 1081dea55137STejun Heo */ 1082dea55137STejun Heo rc = pcim_iomap_regions_request_all(pdev, 1 << AHCI_PCI_BAR, DRV_NAME); 10830d5ff566STejun Heo if (rc == -EBUSY) 108424dc5f33STejun Heo pcim_pin_device(pdev); 10850d5ff566STejun Heo if (rc) 108624dc5f33STejun Heo return rc; 1087c6fd2807SJeff Garzik 1088c4f7792cSTejun Heo if (pdev->vendor == PCI_VENDOR_ID_INTEL && 1089c4f7792cSTejun Heo (pdev->device == 0x2652 || pdev->device == 0x2653)) { 1090c4f7792cSTejun Heo u8 map; 1091c4f7792cSTejun Heo 1092c4f7792cSTejun Heo /* ICH6s share the same PCI ID for both piix and ahci 1093c4f7792cSTejun Heo * modes. Enabling ahci mode while MAP indicates 1094c4f7792cSTejun Heo * combined mode is a bad idea. Yield to ata_piix. 1095c4f7792cSTejun Heo */ 1096c4f7792cSTejun Heo pci_read_config_byte(pdev, ICH_MAP, &map); 1097c4f7792cSTejun Heo if (map & 0x3) { 1098c4f7792cSTejun Heo dev_printk(KERN_INFO, &pdev->dev, "controller is in " 1099c4f7792cSTejun Heo "combined mode, can't enable AHCI mode\n"); 1100c4f7792cSTejun Heo return -ENODEV; 1101c4f7792cSTejun Heo } 1102c4f7792cSTejun Heo } 1103c4f7792cSTejun Heo 110424dc5f33STejun Heo hpriv = devm_kzalloc(dev, sizeof(*hpriv), GFP_KERNEL); 110524dc5f33STejun Heo if (!hpriv) 110624dc5f33STejun Heo return -ENOMEM; 1107417a1a6dSTejun Heo hpriv->flags |= (unsigned long)pi.private_data; 1108417a1a6dSTejun Heo 1109e297d99eSTejun Heo /* MCP65 revision A1 and A2 can't do MSI */ 1110e297d99eSTejun Heo if (board_id == board_ahci_mcp65 && 1111e297d99eSTejun Heo (pdev->revision == 0xa1 || pdev->revision == 0xa2)) 1112e297d99eSTejun Heo hpriv->flags |= AHCI_HFLAG_NO_MSI; 1113e297d99eSTejun Heo 1114e427fe04SShane Huang /* SB800 does NOT need the workaround to ignore SERR_INTERNAL */ 1115e427fe04SShane Huang if (board_id == board_ahci_sb700 && pdev->revision >= 0x40) 1116e427fe04SShane Huang hpriv->flags &= ~AHCI_HFLAG_IGN_SERR_INTERNAL; 1117e427fe04SShane Huang 11182fcad9d2STejun Heo /* only some SB600s can do 64bit DMA */ 11192fcad9d2STejun Heo if (ahci_sb600_enable_64bit(pdev)) 11202fcad9d2STejun Heo hpriv->flags &= ~AHCI_HFLAG_32BIT_ONLY; 112158a09b38SShane Huang 112231b239adSTejun Heo if ((hpriv->flags & AHCI_HFLAG_NO_MSI) || pci_enable_msi(pdev)) 112331b239adSTejun Heo pci_intx(pdev, 1); 1124c6fd2807SJeff Garzik 1125d8993349SAnton Vorontsov hpriv->mmio = pcim_iomap_table(pdev)[AHCI_PCI_BAR]; 1126d8993349SAnton Vorontsov 11274447d351STejun Heo /* save initial config */ 1128394d6e53SAnton Vorontsov ahci_pci_save_initial_config(pdev, hpriv); 1129c6fd2807SJeff Garzik 11304447d351STejun Heo /* prepare host */ 1131453d3131SRobert Hancock if (hpriv->cap & HOST_CAP_NCQ) { 1132453d3131SRobert Hancock pi.flags |= ATA_FLAG_NCQ; 113383f2b963STejun Heo /* 113483f2b963STejun Heo * Auto-activate optimization is supposed to be 113583f2b963STejun Heo * supported on all AHCI controllers indicating NCQ 113683f2b963STejun Heo * capability, but it seems to be broken on some 113783f2b963STejun Heo * chipsets including NVIDIAs. 113883f2b963STejun Heo */ 113983f2b963STejun Heo if (!(hpriv->flags & AHCI_HFLAG_NO_FPDMA_AA)) 1140453d3131SRobert Hancock pi.flags |= ATA_FLAG_FPDMA_AA; 1141453d3131SRobert Hancock } 11424447d351STejun Heo 11437d50b60bSTejun Heo if (hpriv->cap & HOST_CAP_PMP) 11447d50b60bSTejun Heo pi.flags |= ATA_FLAG_PMP; 11457d50b60bSTejun Heo 11460cbb0e77SAnton Vorontsov ahci_set_em_messages(hpriv, &pi); 114718f7ba4cSKristen Carlson Accardi 11481fd68434SRafael J. Wysocki if (ahci_broken_system_poweroff(pdev)) { 11491fd68434SRafael J. Wysocki pi.flags |= ATA_FLAG_NO_POWEROFF_SPINDOWN; 11501fd68434SRafael J. Wysocki dev_info(&pdev->dev, 11511fd68434SRafael J. Wysocki "quirky BIOS, skipping spindown on poweroff\n"); 11521fd68434SRafael J. Wysocki } 11531fd68434SRafael J. Wysocki 11549b10ae86STejun Heo if (ahci_broken_suspend(pdev)) { 11559b10ae86STejun Heo hpriv->flags |= AHCI_HFLAG_NO_SUSPEND; 11569b10ae86STejun Heo dev_printk(KERN_WARNING, &pdev->dev, 11579b10ae86STejun Heo "BIOS update required for suspend/resume\n"); 11589b10ae86STejun Heo } 11599b10ae86STejun Heo 11605594639aSTejun Heo if (ahci_broken_online(pdev)) { 11615594639aSTejun Heo hpriv->flags |= AHCI_HFLAG_SRST_TOUT_IS_OFFLINE; 11625594639aSTejun Heo dev_info(&pdev->dev, 11635594639aSTejun Heo "online status unreliable, applying workaround\n"); 11645594639aSTejun Heo } 11655594639aSTejun Heo 1166837f5f8fSTejun Heo /* CAP.NP sometimes indicate the index of the last enabled 1167837f5f8fSTejun Heo * port, at other times, that of the last possible port, so 1168837f5f8fSTejun Heo * determining the maximum port number requires looking at 1169837f5f8fSTejun Heo * both CAP.NP and port_map. 1170837f5f8fSTejun Heo */ 1171837f5f8fSTejun Heo n_ports = max(ahci_nr_ports(hpriv->cap), fls(hpriv->port_map)); 1172837f5f8fSTejun Heo 1173837f5f8fSTejun Heo host = ata_host_alloc_pinfo(&pdev->dev, ppi, n_ports); 11744447d351STejun Heo if (!host) 11754447d351STejun Heo return -ENOMEM; 11764447d351STejun Heo host->private_data = hpriv; 11774447d351STejun Heo 1178f3d7f23fSArjan van de Ven if (!(hpriv->cap & HOST_CAP_SSS) || ahci_ignore_sss) 1179886ad09fSArjan van de Ven host->flags |= ATA_HOST_PARALLEL_SCAN; 1180f3d7f23fSArjan van de Ven else 1181f3d7f23fSArjan van de Ven printk(KERN_INFO "ahci: SSS flag set, parallel bus scan disabled\n"); 1182886ad09fSArjan van de Ven 118318f7ba4cSKristen Carlson Accardi if (pi.flags & ATA_FLAG_EM) 118418f7ba4cSKristen Carlson Accardi ahci_reset_em(host); 118518f7ba4cSKristen Carlson Accardi 11864447d351STejun Heo for (i = 0; i < host->n_ports; i++) { 11874447d351STejun Heo struct ata_port *ap = host->ports[i]; 11884447d351STejun Heo 1189cbcdd875STejun Heo ata_port_pbar_desc(ap, AHCI_PCI_BAR, -1, "abar"); 1190cbcdd875STejun Heo ata_port_pbar_desc(ap, AHCI_PCI_BAR, 1191cbcdd875STejun Heo 0x100 + ap->port_no * 0x80, "port"); 1192cbcdd875STejun Heo 119331556594SKristen Carlson Accardi /* set initial link pm policy */ 119431556594SKristen Carlson Accardi ap->pm_policy = NOT_AVAILABLE; 119531556594SKristen Carlson Accardi 119618f7ba4cSKristen Carlson Accardi /* set enclosure management message type */ 119718f7ba4cSKristen Carlson Accardi if (ap->flags & ATA_FLAG_EM) 1198008dbd61SHarry Zhang ap->em_message_type = hpriv->em_msg_type; 119918f7ba4cSKristen Carlson Accardi 120018f7ba4cSKristen Carlson Accardi 1201dab632e8SJeff Garzik /* disabled/not-implemented port */ 1202350756f6STejun Heo if (!(hpriv->port_map & (1 << i))) 1203dab632e8SJeff Garzik ap->ops = &ata_dummy_port_ops; 12044447d351STejun Heo } 1205c6fd2807SJeff Garzik 1206edc93052STejun Heo /* apply workaround for ASUS P5W DH Deluxe mainboard */ 1207edc93052STejun Heo ahci_p5wdh_workaround(host); 1208edc93052STejun Heo 1209f80ae7e4STejun Heo /* apply gtf filter quirk */ 1210f80ae7e4STejun Heo ahci_gtf_filter_workaround(host); 1211f80ae7e4STejun Heo 1212c6fd2807SJeff Garzik /* initialize adapter */ 12134447d351STejun Heo rc = ahci_configure_dma_masks(pdev, hpriv->cap & HOST_CAP_64); 1214c6fd2807SJeff Garzik if (rc) 121524dc5f33STejun Heo return rc; 1216c6fd2807SJeff Garzik 12173303040dSAnton Vorontsov rc = ahci_pci_reset_controller(host); 12184447d351STejun Heo if (rc) 12194447d351STejun Heo return rc; 1220c6fd2807SJeff Garzik 1221781d6550SAnton Vorontsov ahci_pci_init_controller(host); 1222439fcaecSAnton Vorontsov ahci_pci_print_info(host); 1223c6fd2807SJeff Garzik 12244447d351STejun Heo pci_set_master(pdev); 12254447d351STejun Heo return ata_host_activate(host, pdev->irq, ahci_interrupt, IRQF_SHARED, 12264447d351STejun Heo &ahci_sht); 1227c6fd2807SJeff Garzik } 1228c6fd2807SJeff Garzik 1229c6fd2807SJeff Garzik static int __init ahci_init(void) 1230c6fd2807SJeff Garzik { 1231c6fd2807SJeff Garzik return pci_register_driver(&ahci_pci_driver); 1232c6fd2807SJeff Garzik } 1233c6fd2807SJeff Garzik 1234c6fd2807SJeff Garzik static void __exit ahci_exit(void) 1235c6fd2807SJeff Garzik { 1236c6fd2807SJeff Garzik pci_unregister_driver(&ahci_pci_driver); 1237c6fd2807SJeff Garzik } 1238c6fd2807SJeff Garzik 1239c6fd2807SJeff Garzik 1240c6fd2807SJeff Garzik MODULE_AUTHOR("Jeff Garzik"); 1241c6fd2807SJeff Garzik MODULE_DESCRIPTION("AHCI SATA low-level driver"); 1242c6fd2807SJeff Garzik MODULE_LICENSE("GPL"); 1243c6fd2807SJeff Garzik MODULE_DEVICE_TABLE(pci, ahci_pci_tbl); 1244c6fd2807SJeff Garzik MODULE_VERSION(DRV_VERSION); 1245c6fd2807SJeff Garzik 1246c6fd2807SJeff Garzik module_init(ahci_init); 1247c6fd2807SJeff Garzik module_exit(ahci_exit); 1248