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, 635f173107STejun Heo board_ahci_yes_fbs, 64441577efSTejun Heo 65441577efSTejun Heo /* board IDs for specific chipsets in alphabetical order */ 66441577efSTejun Heo board_ahci_mcp65, 6783f2b963STejun Heo board_ahci_mcp77, 6883f2b963STejun Heo board_ahci_mcp89, 69441577efSTejun Heo board_ahci_mv, 70441577efSTejun Heo board_ahci_sb600, 71441577efSTejun Heo board_ahci_sb700, /* for SB700 and SB800 */ 72441577efSTejun Heo board_ahci_vt8251, 73441577efSTejun Heo 74441577efSTejun Heo /* aliases */ 75441577efSTejun Heo board_ahci_mcp_linux = board_ahci_mcp65, 76441577efSTejun Heo board_ahci_mcp67 = board_ahci_mcp65, 77441577efSTejun Heo board_ahci_mcp73 = board_ahci_mcp65, 7883f2b963STejun Heo board_ahci_mcp79 = board_ahci_mcp77, 79c6fd2807SJeff Garzik }; 80c6fd2807SJeff Garzik 81c6fd2807SJeff Garzik static int ahci_init_one(struct pci_dev *pdev, const struct pci_device_id *ent); 82bd17243aSShane Huang static int ahci_sb600_softreset(struct ata_link *link, unsigned int *class, 83bd17243aSShane Huang unsigned long deadline); 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 107bd17243aSShane Huang static struct ata_port_operations ahci_sb600_ops = { 108bd17243aSShane Huang .inherits = &ahci_ops, 109bd17243aSShane Huang .softreset = ahci_sb600_softreset, 110bd17243aSShane Huang .pmp_softreset = ahci_sb600_softreset, 111bd17243aSShane Huang }; 112bd17243aSShane Huang 113417a1a6dSTejun Heo #define AHCI_HFLAGS(flags) .private_data = (void *)(flags) 114417a1a6dSTejun Heo 115c6fd2807SJeff Garzik static const struct ata_port_info ahci_port_info[] = { 116441577efSTejun Heo /* by features */ 1174da646b7SJeff Garzik [board_ahci] = 118c6fd2807SJeff Garzik { 1191188c0d8STejun Heo .flags = AHCI_FLAG_COMMON, 12014bdef98SErik Inge Bolsø .pio_mask = ATA_PIO4, 121469248abSJeff Garzik .udma_mask = ATA_UDMA6, 122c6fd2807SJeff Garzik .port_ops = &ahci_ops, 123c6fd2807SJeff Garzik }, 1244da646b7SJeff Garzik [board_ahci_ign_iferr] = 12541669553STejun Heo { 126417a1a6dSTejun Heo AHCI_HFLAGS (AHCI_HFLAG_IGN_IRQ_IF_ERR), 127417a1a6dSTejun Heo .flags = AHCI_FLAG_COMMON, 12814bdef98SErik Inge Bolsø .pio_mask = ATA_PIO4, 129469248abSJeff Garzik .udma_mask = ATA_UDMA6, 13041669553STejun Heo .port_ops = &ahci_ops, 13141669553STejun Heo }, 132441577efSTejun Heo [board_ahci_nosntf] = 133441577efSTejun Heo { 134441577efSTejun Heo AHCI_HFLAGS (AHCI_HFLAG_NO_SNTF), 135441577efSTejun Heo .flags = AHCI_FLAG_COMMON, 136441577efSTejun Heo .pio_mask = ATA_PIO4, 137441577efSTejun Heo .udma_mask = ATA_UDMA6, 138441577efSTejun Heo .port_ops = &ahci_ops, 139441577efSTejun Heo }, 1405f173107STejun Heo [board_ahci_yes_fbs] = 1415f173107STejun Heo { 1425f173107STejun Heo AHCI_HFLAGS (AHCI_HFLAG_YES_FBS), 1435f173107STejun Heo .flags = AHCI_FLAG_COMMON, 1445f173107STejun Heo .pio_mask = ATA_PIO4, 1455f173107STejun Heo .udma_mask = ATA_UDMA6, 1465f173107STejun Heo .port_ops = &ahci_ops, 1475f173107STejun Heo }, 148441577efSTejun Heo /* by chipsets */ 149441577efSTejun Heo [board_ahci_mcp65] = 150441577efSTejun Heo { 15183f2b963STejun Heo AHCI_HFLAGS (AHCI_HFLAG_NO_FPDMA_AA | AHCI_HFLAG_NO_PMP | 15283f2b963STejun Heo AHCI_HFLAG_YES_NCQ), 15383f2b963STejun Heo .flags = AHCI_FLAG_COMMON, 15483f2b963STejun Heo .pio_mask = ATA_PIO4, 15583f2b963STejun Heo .udma_mask = ATA_UDMA6, 15683f2b963STejun Heo .port_ops = &ahci_ops, 15783f2b963STejun Heo }, 15883f2b963STejun Heo [board_ahci_mcp77] = 15983f2b963STejun Heo { 16083f2b963STejun Heo AHCI_HFLAGS (AHCI_HFLAG_NO_FPDMA_AA | AHCI_HFLAG_NO_PMP), 16183f2b963STejun Heo .flags = AHCI_FLAG_COMMON, 16283f2b963STejun Heo .pio_mask = ATA_PIO4, 16383f2b963STejun Heo .udma_mask = ATA_UDMA6, 16483f2b963STejun Heo .port_ops = &ahci_ops, 16583f2b963STejun Heo }, 16683f2b963STejun Heo [board_ahci_mcp89] = 16783f2b963STejun Heo { 16883f2b963STejun Heo AHCI_HFLAGS (AHCI_HFLAG_NO_FPDMA_AA), 169441577efSTejun Heo .flags = AHCI_FLAG_COMMON, 170441577efSTejun Heo .pio_mask = ATA_PIO4, 171441577efSTejun Heo .udma_mask = ATA_UDMA6, 172441577efSTejun Heo .port_ops = &ahci_ops, 173441577efSTejun Heo }, 174441577efSTejun Heo [board_ahci_mv] = 175441577efSTejun Heo { 176441577efSTejun Heo AHCI_HFLAGS (AHCI_HFLAG_NO_NCQ | AHCI_HFLAG_NO_MSI | 177441577efSTejun Heo AHCI_HFLAG_MV_PATA | AHCI_HFLAG_NO_PMP), 1789cbe056fSSergei Shtylyov .flags = ATA_FLAG_SATA | ATA_FLAG_PIO_DMA, 179441577efSTejun Heo .pio_mask = ATA_PIO4, 180441577efSTejun Heo .udma_mask = ATA_UDMA6, 181441577efSTejun Heo .port_ops = &ahci_ops, 182441577efSTejun Heo }, 1834da646b7SJeff Garzik [board_ahci_sb600] = 18455a61604SConke Hu { 185417a1a6dSTejun Heo AHCI_HFLAGS (AHCI_HFLAG_IGN_SERR_INTERNAL | 1862fcad9d2STejun Heo AHCI_HFLAG_NO_MSI | AHCI_HFLAG_SECT255 | 1872fcad9d2STejun Heo AHCI_HFLAG_32BIT_ONLY), 188417a1a6dSTejun Heo .flags = AHCI_FLAG_COMMON, 18914bdef98SErik Inge Bolsø .pio_mask = ATA_PIO4, 190469248abSJeff Garzik .udma_mask = ATA_UDMA6, 191bd17243aSShane Huang .port_ops = &ahci_sb600_ops, 19255a61604SConke Hu }, 1934da646b7SJeff Garzik [board_ahci_sb700] = /* for SB700 and SB800 */ 194e39fc8c9SShane Huang { 195bd17243aSShane Huang AHCI_HFLAGS (AHCI_HFLAG_IGN_SERR_INTERNAL), 196e39fc8c9SShane Huang .flags = AHCI_FLAG_COMMON, 19714bdef98SErik Inge Bolsø .pio_mask = ATA_PIO4, 198e39fc8c9SShane Huang .udma_mask = ATA_UDMA6, 199bd17243aSShane Huang .port_ops = &ahci_sb600_ops, 200e39fc8c9SShane Huang }, 201441577efSTejun Heo [board_ahci_vt8251] = 202e297d99eSTejun Heo { 203441577efSTejun Heo AHCI_HFLAGS (AHCI_HFLAG_NO_NCQ | AHCI_HFLAG_NO_PMP), 204e297d99eSTejun Heo .flags = AHCI_FLAG_COMMON, 20514bdef98SErik Inge Bolsø .pio_mask = ATA_PIO4, 206e297d99eSTejun Heo .udma_mask = ATA_UDMA6, 207441577efSTejun Heo .port_ops = &ahci_vt8251_ops, 2081b677afdSShaohua Li }, 209c6fd2807SJeff Garzik }; 210c6fd2807SJeff Garzik 211c6fd2807SJeff Garzik static const struct pci_device_id ahci_pci_tbl[] = { 212c6fd2807SJeff Garzik /* Intel */ 21354bb3a94SJeff Garzik { PCI_VDEVICE(INTEL, 0x2652), board_ahci }, /* ICH6 */ 21454bb3a94SJeff Garzik { PCI_VDEVICE(INTEL, 0x2653), board_ahci }, /* ICH6M */ 21554bb3a94SJeff Garzik { PCI_VDEVICE(INTEL, 0x27c1), board_ahci }, /* ICH7 */ 21654bb3a94SJeff Garzik { PCI_VDEVICE(INTEL, 0x27c5), board_ahci }, /* ICH7M */ 21754bb3a94SJeff Garzik { PCI_VDEVICE(INTEL, 0x27c3), board_ahci }, /* ICH7R */ 21882490c09STejun Heo { PCI_VDEVICE(AL, 0x5288), board_ahci_ign_iferr }, /* ULi M5288 */ 21954bb3a94SJeff Garzik { PCI_VDEVICE(INTEL, 0x2681), board_ahci }, /* ESB2 */ 22054bb3a94SJeff Garzik { PCI_VDEVICE(INTEL, 0x2682), board_ahci }, /* ESB2 */ 22154bb3a94SJeff Garzik { PCI_VDEVICE(INTEL, 0x2683), board_ahci }, /* ESB2 */ 22254bb3a94SJeff Garzik { PCI_VDEVICE(INTEL, 0x27c6), board_ahci }, /* ICH7-M DH */ 2237a234affSTejun Heo { PCI_VDEVICE(INTEL, 0x2821), board_ahci }, /* ICH8 */ 2241b677afdSShaohua Li { PCI_VDEVICE(INTEL, 0x2822), board_ahci_nosntf }, /* ICH8 */ 2257a234affSTejun Heo { PCI_VDEVICE(INTEL, 0x2824), board_ahci }, /* ICH8 */ 2267a234affSTejun Heo { PCI_VDEVICE(INTEL, 0x2829), board_ahci }, /* ICH8M */ 2277a234affSTejun Heo { PCI_VDEVICE(INTEL, 0x282a), board_ahci }, /* ICH8M */ 2287a234affSTejun Heo { PCI_VDEVICE(INTEL, 0x2922), board_ahci }, /* ICH9 */ 2297a234affSTejun Heo { PCI_VDEVICE(INTEL, 0x2923), board_ahci }, /* ICH9 */ 2307a234affSTejun Heo { PCI_VDEVICE(INTEL, 0x2924), board_ahci }, /* ICH9 */ 2317a234affSTejun Heo { PCI_VDEVICE(INTEL, 0x2925), board_ahci }, /* ICH9 */ 2327a234affSTejun Heo { PCI_VDEVICE(INTEL, 0x2927), board_ahci }, /* ICH9 */ 2337a234affSTejun Heo { PCI_VDEVICE(INTEL, 0x2929), board_ahci }, /* ICH9M */ 2347a234affSTejun Heo { PCI_VDEVICE(INTEL, 0x292a), board_ahci }, /* ICH9M */ 2357a234affSTejun Heo { PCI_VDEVICE(INTEL, 0x292b), board_ahci }, /* ICH9M */ 2367a234affSTejun Heo { PCI_VDEVICE(INTEL, 0x292c), board_ahci }, /* ICH9M */ 2377a234affSTejun Heo { PCI_VDEVICE(INTEL, 0x292f), board_ahci }, /* ICH9M */ 2387a234affSTejun Heo { PCI_VDEVICE(INTEL, 0x294d), board_ahci }, /* ICH9 */ 2397a234affSTejun Heo { PCI_VDEVICE(INTEL, 0x294e), board_ahci }, /* ICH9M */ 240d4155e6fSJason Gaston { PCI_VDEVICE(INTEL, 0x502a), board_ahci }, /* Tolapai */ 241d4155e6fSJason Gaston { PCI_VDEVICE(INTEL, 0x502b), board_ahci }, /* Tolapai */ 24216ad1ad9SJason Gaston { PCI_VDEVICE(INTEL, 0x3a05), board_ahci }, /* ICH10 */ 243b2dde6afSMark Goodwin { PCI_VDEVICE(INTEL, 0x3a22), board_ahci }, /* ICH10 */ 24416ad1ad9SJason Gaston { PCI_VDEVICE(INTEL, 0x3a25), board_ahci }, /* ICH10 */ 245c1f57d9bSDavid Milburn { PCI_VDEVICE(INTEL, 0x3b22), board_ahci }, /* PCH AHCI */ 246c1f57d9bSDavid Milburn { PCI_VDEVICE(INTEL, 0x3b23), board_ahci }, /* PCH AHCI */ 247adcb5308SSeth Heasley { PCI_VDEVICE(INTEL, 0x3b24), board_ahci }, /* PCH RAID */ 2488e48b6b3SSeth Heasley { PCI_VDEVICE(INTEL, 0x3b25), board_ahci }, /* PCH RAID */ 249c1f57d9bSDavid Milburn { PCI_VDEVICE(INTEL, 0x3b29), board_ahci }, /* PCH AHCI */ 250adcb5308SSeth Heasley { PCI_VDEVICE(INTEL, 0x3b2b), board_ahci }, /* PCH RAID */ 2518e48b6b3SSeth Heasley { PCI_VDEVICE(INTEL, 0x3b2c), board_ahci }, /* PCH RAID */ 252c1f57d9bSDavid Milburn { PCI_VDEVICE(INTEL, 0x3b2f), board_ahci }, /* PCH AHCI */ 2535623cab8SSeth Heasley { PCI_VDEVICE(INTEL, 0x1c02), board_ahci }, /* CPT AHCI */ 2545623cab8SSeth Heasley { PCI_VDEVICE(INTEL, 0x1c03), board_ahci }, /* CPT AHCI */ 2555623cab8SSeth Heasley { PCI_VDEVICE(INTEL, 0x1c04), board_ahci }, /* CPT RAID */ 2565623cab8SSeth Heasley { PCI_VDEVICE(INTEL, 0x1c05), board_ahci }, /* CPT RAID */ 2575623cab8SSeth Heasley { PCI_VDEVICE(INTEL, 0x1c06), board_ahci }, /* CPT RAID */ 2585623cab8SSeth Heasley { PCI_VDEVICE(INTEL, 0x1c07), board_ahci }, /* CPT RAID */ 259992b3fb9SSeth Heasley { PCI_VDEVICE(INTEL, 0x1d02), board_ahci }, /* PBG AHCI */ 260992b3fb9SSeth Heasley { PCI_VDEVICE(INTEL, 0x1d04), board_ahci }, /* PBG RAID */ 261992b3fb9SSeth Heasley { PCI_VDEVICE(INTEL, 0x1d06), board_ahci }, /* PBG RAID */ 26264a3903dSSeth Heasley { PCI_VDEVICE(INTEL, 0x2826), board_ahci }, /* PBG RAID */ 263a4a461a6SSeth Heasley { PCI_VDEVICE(INTEL, 0x2323), board_ahci }, /* DH89xxCC AHCI */ 264c6fd2807SJeff Garzik 265e34bb370STejun Heo /* JMicron 360/1/3/5/6, match class to avoid IDE function */ 266e34bb370STejun Heo { PCI_VENDOR_ID_JMICRON, PCI_ANY_ID, PCI_ANY_ID, PCI_ANY_ID, 267e34bb370STejun Heo PCI_CLASS_STORAGE_SATA_AHCI, 0xffffff, board_ahci_ign_iferr }, 268c6fd2807SJeff Garzik 269c6fd2807SJeff Garzik /* ATI */ 270c65ec1c2SConke Hu { PCI_VDEVICE(ATI, 0x4380), board_ahci_sb600 }, /* ATI SB600 */ 271e39fc8c9SShane Huang { PCI_VDEVICE(ATI, 0x4390), board_ahci_sb700 }, /* ATI SB700/800 */ 272e39fc8c9SShane Huang { PCI_VDEVICE(ATI, 0x4391), board_ahci_sb700 }, /* ATI SB700/800 */ 273e39fc8c9SShane Huang { PCI_VDEVICE(ATI, 0x4392), board_ahci_sb700 }, /* ATI SB700/800 */ 274e39fc8c9SShane Huang { PCI_VDEVICE(ATI, 0x4393), board_ahci_sb700 }, /* ATI SB700/800 */ 275e39fc8c9SShane Huang { PCI_VDEVICE(ATI, 0x4394), board_ahci_sb700 }, /* ATI SB700/800 */ 276e39fc8c9SShane Huang { PCI_VDEVICE(ATI, 0x4395), board_ahci_sb700 }, /* ATI SB700/800 */ 277c6fd2807SJeff Garzik 278e2dd90b1SShane Huang /* AMD */ 2795deab536SShane Huang { PCI_VDEVICE(AMD, 0x7800), board_ahci }, /* AMD Hudson-2 */ 280e2dd90b1SShane Huang /* AMD is using RAID class only for ahci controllers */ 281e2dd90b1SShane Huang { PCI_VENDOR_ID_AMD, PCI_ANY_ID, PCI_ANY_ID, PCI_ANY_ID, 282e2dd90b1SShane Huang PCI_CLASS_STORAGE_RAID << 8, 0xffffff, board_ahci }, 283e2dd90b1SShane Huang 284c6fd2807SJeff Garzik /* VIA */ 28554bb3a94SJeff Garzik { PCI_VDEVICE(VIA, 0x3349), board_ahci_vt8251 }, /* VIA VT8251 */ 286bf335542STejun Heo { PCI_VDEVICE(VIA, 0x6287), board_ahci_vt8251 }, /* VIA VT8251 */ 287c6fd2807SJeff Garzik 288c6fd2807SJeff Garzik /* NVIDIA */ 289e297d99eSTejun Heo { PCI_VDEVICE(NVIDIA, 0x044c), board_ahci_mcp65 }, /* MCP65 */ 290e297d99eSTejun Heo { PCI_VDEVICE(NVIDIA, 0x044d), board_ahci_mcp65 }, /* MCP65 */ 291e297d99eSTejun Heo { PCI_VDEVICE(NVIDIA, 0x044e), board_ahci_mcp65 }, /* MCP65 */ 292e297d99eSTejun Heo { PCI_VDEVICE(NVIDIA, 0x044f), board_ahci_mcp65 }, /* MCP65 */ 293e297d99eSTejun Heo { PCI_VDEVICE(NVIDIA, 0x045c), board_ahci_mcp65 }, /* MCP65 */ 294e297d99eSTejun Heo { PCI_VDEVICE(NVIDIA, 0x045d), board_ahci_mcp65 }, /* MCP65 */ 295e297d99eSTejun Heo { PCI_VDEVICE(NVIDIA, 0x045e), board_ahci_mcp65 }, /* MCP65 */ 296e297d99eSTejun Heo { PCI_VDEVICE(NVIDIA, 0x045f), board_ahci_mcp65 }, /* MCP65 */ 297441577efSTejun Heo { PCI_VDEVICE(NVIDIA, 0x0550), board_ahci_mcp67 }, /* MCP67 */ 298441577efSTejun Heo { PCI_VDEVICE(NVIDIA, 0x0551), board_ahci_mcp67 }, /* MCP67 */ 299441577efSTejun Heo { PCI_VDEVICE(NVIDIA, 0x0552), board_ahci_mcp67 }, /* MCP67 */ 300441577efSTejun Heo { PCI_VDEVICE(NVIDIA, 0x0553), board_ahci_mcp67 }, /* MCP67 */ 301441577efSTejun Heo { PCI_VDEVICE(NVIDIA, 0x0554), board_ahci_mcp67 }, /* MCP67 */ 302441577efSTejun Heo { PCI_VDEVICE(NVIDIA, 0x0555), board_ahci_mcp67 }, /* MCP67 */ 303441577efSTejun Heo { PCI_VDEVICE(NVIDIA, 0x0556), board_ahci_mcp67 }, /* MCP67 */ 304441577efSTejun Heo { PCI_VDEVICE(NVIDIA, 0x0557), board_ahci_mcp67 }, /* MCP67 */ 305441577efSTejun Heo { PCI_VDEVICE(NVIDIA, 0x0558), board_ahci_mcp67 }, /* MCP67 */ 306441577efSTejun Heo { PCI_VDEVICE(NVIDIA, 0x0559), board_ahci_mcp67 }, /* MCP67 */ 307441577efSTejun Heo { PCI_VDEVICE(NVIDIA, 0x055a), board_ahci_mcp67 }, /* MCP67 */ 308441577efSTejun Heo { PCI_VDEVICE(NVIDIA, 0x055b), board_ahci_mcp67 }, /* MCP67 */ 309441577efSTejun Heo { PCI_VDEVICE(NVIDIA, 0x0580), board_ahci_mcp_linux }, /* Linux ID */ 310441577efSTejun Heo { PCI_VDEVICE(NVIDIA, 0x0581), board_ahci_mcp_linux }, /* Linux ID */ 311441577efSTejun Heo { PCI_VDEVICE(NVIDIA, 0x0582), board_ahci_mcp_linux }, /* Linux ID */ 312441577efSTejun Heo { PCI_VDEVICE(NVIDIA, 0x0583), board_ahci_mcp_linux }, /* Linux ID */ 313441577efSTejun Heo { PCI_VDEVICE(NVIDIA, 0x0584), board_ahci_mcp_linux }, /* Linux ID */ 314441577efSTejun Heo { PCI_VDEVICE(NVIDIA, 0x0585), board_ahci_mcp_linux }, /* Linux ID */ 315441577efSTejun Heo { PCI_VDEVICE(NVIDIA, 0x0586), board_ahci_mcp_linux }, /* Linux ID */ 316441577efSTejun Heo { PCI_VDEVICE(NVIDIA, 0x0587), board_ahci_mcp_linux }, /* Linux ID */ 317441577efSTejun Heo { PCI_VDEVICE(NVIDIA, 0x0588), board_ahci_mcp_linux }, /* Linux ID */ 318441577efSTejun Heo { PCI_VDEVICE(NVIDIA, 0x0589), board_ahci_mcp_linux }, /* Linux ID */ 319441577efSTejun Heo { PCI_VDEVICE(NVIDIA, 0x058a), board_ahci_mcp_linux }, /* Linux ID */ 320441577efSTejun Heo { PCI_VDEVICE(NVIDIA, 0x058b), board_ahci_mcp_linux }, /* Linux ID */ 321441577efSTejun Heo { PCI_VDEVICE(NVIDIA, 0x058c), board_ahci_mcp_linux }, /* Linux ID */ 322441577efSTejun Heo { PCI_VDEVICE(NVIDIA, 0x058d), board_ahci_mcp_linux }, /* Linux ID */ 323441577efSTejun Heo { PCI_VDEVICE(NVIDIA, 0x058e), board_ahci_mcp_linux }, /* Linux ID */ 324441577efSTejun Heo { PCI_VDEVICE(NVIDIA, 0x058f), board_ahci_mcp_linux }, /* Linux ID */ 325441577efSTejun Heo { PCI_VDEVICE(NVIDIA, 0x07f0), board_ahci_mcp73 }, /* MCP73 */ 326441577efSTejun Heo { PCI_VDEVICE(NVIDIA, 0x07f1), board_ahci_mcp73 }, /* MCP73 */ 327441577efSTejun Heo { PCI_VDEVICE(NVIDIA, 0x07f2), board_ahci_mcp73 }, /* MCP73 */ 328441577efSTejun Heo { PCI_VDEVICE(NVIDIA, 0x07f3), board_ahci_mcp73 }, /* MCP73 */ 329441577efSTejun Heo { PCI_VDEVICE(NVIDIA, 0x07f4), board_ahci_mcp73 }, /* MCP73 */ 330441577efSTejun Heo { PCI_VDEVICE(NVIDIA, 0x07f5), board_ahci_mcp73 }, /* MCP73 */ 331441577efSTejun Heo { PCI_VDEVICE(NVIDIA, 0x07f6), board_ahci_mcp73 }, /* MCP73 */ 332441577efSTejun Heo { PCI_VDEVICE(NVIDIA, 0x07f7), board_ahci_mcp73 }, /* MCP73 */ 333441577efSTejun Heo { PCI_VDEVICE(NVIDIA, 0x07f8), board_ahci_mcp73 }, /* MCP73 */ 334441577efSTejun Heo { PCI_VDEVICE(NVIDIA, 0x07f9), board_ahci_mcp73 }, /* MCP73 */ 335441577efSTejun Heo { PCI_VDEVICE(NVIDIA, 0x07fa), board_ahci_mcp73 }, /* MCP73 */ 336441577efSTejun Heo { PCI_VDEVICE(NVIDIA, 0x07fb), board_ahci_mcp73 }, /* MCP73 */ 337441577efSTejun Heo { PCI_VDEVICE(NVIDIA, 0x0ad0), board_ahci_mcp77 }, /* MCP77 */ 338441577efSTejun Heo { PCI_VDEVICE(NVIDIA, 0x0ad1), board_ahci_mcp77 }, /* MCP77 */ 339441577efSTejun Heo { PCI_VDEVICE(NVIDIA, 0x0ad2), board_ahci_mcp77 }, /* MCP77 */ 340441577efSTejun Heo { PCI_VDEVICE(NVIDIA, 0x0ad3), board_ahci_mcp77 }, /* MCP77 */ 341441577efSTejun Heo { PCI_VDEVICE(NVIDIA, 0x0ad4), board_ahci_mcp77 }, /* MCP77 */ 342441577efSTejun Heo { PCI_VDEVICE(NVIDIA, 0x0ad5), board_ahci_mcp77 }, /* MCP77 */ 343441577efSTejun Heo { PCI_VDEVICE(NVIDIA, 0x0ad6), board_ahci_mcp77 }, /* MCP77 */ 344441577efSTejun Heo { PCI_VDEVICE(NVIDIA, 0x0ad7), board_ahci_mcp77 }, /* MCP77 */ 345441577efSTejun Heo { PCI_VDEVICE(NVIDIA, 0x0ad8), board_ahci_mcp77 }, /* MCP77 */ 346441577efSTejun Heo { PCI_VDEVICE(NVIDIA, 0x0ad9), board_ahci_mcp77 }, /* MCP77 */ 347441577efSTejun Heo { PCI_VDEVICE(NVIDIA, 0x0ada), board_ahci_mcp77 }, /* MCP77 */ 348441577efSTejun Heo { PCI_VDEVICE(NVIDIA, 0x0adb), board_ahci_mcp77 }, /* MCP77 */ 349441577efSTejun Heo { PCI_VDEVICE(NVIDIA, 0x0ab4), board_ahci_mcp79 }, /* MCP79 */ 350441577efSTejun Heo { PCI_VDEVICE(NVIDIA, 0x0ab5), board_ahci_mcp79 }, /* MCP79 */ 351441577efSTejun Heo { PCI_VDEVICE(NVIDIA, 0x0ab6), board_ahci_mcp79 }, /* MCP79 */ 352441577efSTejun Heo { PCI_VDEVICE(NVIDIA, 0x0ab7), board_ahci_mcp79 }, /* MCP79 */ 353441577efSTejun Heo { PCI_VDEVICE(NVIDIA, 0x0ab8), board_ahci_mcp79 }, /* MCP79 */ 354441577efSTejun Heo { PCI_VDEVICE(NVIDIA, 0x0ab9), board_ahci_mcp79 }, /* MCP79 */ 355441577efSTejun Heo { PCI_VDEVICE(NVIDIA, 0x0aba), board_ahci_mcp79 }, /* MCP79 */ 356441577efSTejun Heo { PCI_VDEVICE(NVIDIA, 0x0abb), board_ahci_mcp79 }, /* MCP79 */ 357441577efSTejun Heo { PCI_VDEVICE(NVIDIA, 0x0abc), board_ahci_mcp79 }, /* MCP79 */ 358441577efSTejun Heo { PCI_VDEVICE(NVIDIA, 0x0abd), board_ahci_mcp79 }, /* MCP79 */ 359441577efSTejun Heo { PCI_VDEVICE(NVIDIA, 0x0abe), board_ahci_mcp79 }, /* MCP79 */ 360441577efSTejun Heo { PCI_VDEVICE(NVIDIA, 0x0abf), board_ahci_mcp79 }, /* MCP79 */ 361441577efSTejun Heo { PCI_VDEVICE(NVIDIA, 0x0d84), board_ahci_mcp89 }, /* MCP89 */ 362441577efSTejun Heo { PCI_VDEVICE(NVIDIA, 0x0d85), board_ahci_mcp89 }, /* MCP89 */ 363441577efSTejun Heo { PCI_VDEVICE(NVIDIA, 0x0d86), board_ahci_mcp89 }, /* MCP89 */ 364441577efSTejun Heo { PCI_VDEVICE(NVIDIA, 0x0d87), board_ahci_mcp89 }, /* MCP89 */ 365441577efSTejun Heo { PCI_VDEVICE(NVIDIA, 0x0d88), board_ahci_mcp89 }, /* MCP89 */ 366441577efSTejun Heo { PCI_VDEVICE(NVIDIA, 0x0d89), board_ahci_mcp89 }, /* MCP89 */ 367441577efSTejun Heo { PCI_VDEVICE(NVIDIA, 0x0d8a), board_ahci_mcp89 }, /* MCP89 */ 368441577efSTejun Heo { PCI_VDEVICE(NVIDIA, 0x0d8b), board_ahci_mcp89 }, /* MCP89 */ 369441577efSTejun Heo { PCI_VDEVICE(NVIDIA, 0x0d8c), board_ahci_mcp89 }, /* MCP89 */ 370441577efSTejun Heo { PCI_VDEVICE(NVIDIA, 0x0d8d), board_ahci_mcp89 }, /* MCP89 */ 371441577efSTejun Heo { PCI_VDEVICE(NVIDIA, 0x0d8e), board_ahci_mcp89 }, /* MCP89 */ 372441577efSTejun Heo { PCI_VDEVICE(NVIDIA, 0x0d8f), board_ahci_mcp89 }, /* MCP89 */ 373c6fd2807SJeff Garzik 374c6fd2807SJeff Garzik /* SiS */ 37520e2de4aSTejun Heo { PCI_VDEVICE(SI, 0x1184), board_ahci }, /* SiS 966 */ 37620e2de4aSTejun Heo { PCI_VDEVICE(SI, 0x1185), board_ahci }, /* SiS 968 */ 37720e2de4aSTejun Heo { PCI_VDEVICE(SI, 0x0186), board_ahci }, /* SiS 968 */ 378c6fd2807SJeff Garzik 379cd70c266SJeff Garzik /* Marvell */ 380cd70c266SJeff Garzik { PCI_VDEVICE(MARVELL, 0x6145), board_ahci_mv }, /* 6145 */ 381c40e7cb8SJose Alberto Reguero { PCI_VDEVICE(MARVELL, 0x6121), board_ahci_mv }, /* 6121 */ 3825f173107STejun Heo { PCI_DEVICE(0x1b4b, 0x9123), 38310aca06cSAnssi Hannula .class = PCI_CLASS_STORAGE_SATA_AHCI, 38410aca06cSAnssi Hannula .class_mask = 0xffffff, 3855f173107STejun Heo .driver_data = board_ahci_yes_fbs }, /* 88se9128 */ 386467b41c6SPer Jessen { PCI_DEVICE(0x1b4b, 0x9125), 387467b41c6SPer Jessen .driver_data = board_ahci_yes_fbs }, /* 88se9125 */ 38850be5e36STejun Heo { PCI_DEVICE(0x1b4b, 0x91a3), 38950be5e36STejun Heo .driver_data = board_ahci_yes_fbs }, 390cd70c266SJeff Garzik 391c77a036bSMark Nelson /* Promise */ 392c77a036bSMark Nelson { PCI_VDEVICE(PROMISE, 0x3f20), board_ahci }, /* PDC42819 */ 393c77a036bSMark Nelson 394415ae2b5SJeff Garzik /* Generic, PCI class code for AHCI */ 395415ae2b5SJeff Garzik { PCI_ANY_ID, PCI_ANY_ID, PCI_ANY_ID, PCI_ANY_ID, 396c9f89475SConke Hu PCI_CLASS_STORAGE_SATA_AHCI, 0xffffff, board_ahci }, 397415ae2b5SJeff Garzik 398c6fd2807SJeff Garzik { } /* terminate list */ 399c6fd2807SJeff Garzik }; 400c6fd2807SJeff Garzik 401c6fd2807SJeff Garzik 402c6fd2807SJeff Garzik static struct pci_driver ahci_pci_driver = { 403c6fd2807SJeff Garzik .name = DRV_NAME, 404c6fd2807SJeff Garzik .id_table = ahci_pci_tbl, 405c6fd2807SJeff Garzik .probe = ahci_init_one, 40624dc5f33STejun Heo .remove = ata_pci_remove_one, 407438ac6d5STejun Heo #ifdef CONFIG_PM 408c6fd2807SJeff Garzik .suspend = ahci_pci_device_suspend, 409c6fd2807SJeff Garzik .resume = ahci_pci_device_resume, 410438ac6d5STejun Heo #endif 411c6fd2807SJeff Garzik }; 412c6fd2807SJeff Garzik 4135b66c829SAlan Cox #if defined(CONFIG_PATA_MARVELL) || defined(CONFIG_PATA_MARVELL_MODULE) 4145b66c829SAlan Cox static int marvell_enable; 4155b66c829SAlan Cox #else 4165b66c829SAlan Cox static int marvell_enable = 1; 4175b66c829SAlan Cox #endif 4185b66c829SAlan Cox module_param(marvell_enable, int, 0644); 4195b66c829SAlan Cox MODULE_PARM_DESC(marvell_enable, "Marvell SATA via AHCI (1 = enabled)"); 4205b66c829SAlan Cox 4215b66c829SAlan Cox 422394d6e53SAnton Vorontsov static void ahci_pci_save_initial_config(struct pci_dev *pdev, 423394d6e53SAnton Vorontsov struct ahci_host_priv *hpriv) 424394d6e53SAnton Vorontsov { 425394d6e53SAnton Vorontsov unsigned int force_port_map = 0; 426394d6e53SAnton Vorontsov unsigned int mask_port_map = 0; 427394d6e53SAnton Vorontsov 428394d6e53SAnton Vorontsov if (pdev->vendor == PCI_VENDOR_ID_JMICRON && pdev->device == 0x2361) { 429394d6e53SAnton Vorontsov dev_info(&pdev->dev, "JMB361 has only one port\n"); 430394d6e53SAnton Vorontsov force_port_map = 1; 431394d6e53SAnton Vorontsov } 432394d6e53SAnton Vorontsov 433394d6e53SAnton Vorontsov /* 434394d6e53SAnton Vorontsov * Temporary Marvell 6145 hack: PATA port presence 435394d6e53SAnton Vorontsov * is asserted through the standard AHCI port 436394d6e53SAnton Vorontsov * presence register, as bit 4 (counting from 0) 437394d6e53SAnton Vorontsov */ 438394d6e53SAnton Vorontsov if (hpriv->flags & AHCI_HFLAG_MV_PATA) { 439394d6e53SAnton Vorontsov if (pdev->device == 0x6121) 440394d6e53SAnton Vorontsov mask_port_map = 0x3; 441394d6e53SAnton Vorontsov else 442394d6e53SAnton Vorontsov mask_port_map = 0xf; 443394d6e53SAnton Vorontsov dev_info(&pdev->dev, 444394d6e53SAnton Vorontsov "Disabling your PATA port. Use the boot option 'ahci.marvell_enable=0' to avoid this.\n"); 445394d6e53SAnton Vorontsov } 446394d6e53SAnton Vorontsov 4471d513358SAnton Vorontsov ahci_save_initial_config(&pdev->dev, hpriv, force_port_map, 4481d513358SAnton Vorontsov mask_port_map); 449394d6e53SAnton Vorontsov } 450394d6e53SAnton Vorontsov 4513303040dSAnton Vorontsov static int ahci_pci_reset_controller(struct ata_host *host) 4523303040dSAnton Vorontsov { 4533303040dSAnton Vorontsov struct pci_dev *pdev = to_pci_dev(host->dev); 4543303040dSAnton Vorontsov 4553303040dSAnton Vorontsov ahci_reset_controller(host); 4563303040dSAnton Vorontsov 457c6fd2807SJeff Garzik if (pdev->vendor == PCI_VENDOR_ID_INTEL) { 4583303040dSAnton Vorontsov struct ahci_host_priv *hpriv = host->private_data; 459c6fd2807SJeff Garzik u16 tmp16; 460c6fd2807SJeff Garzik 461c6fd2807SJeff Garzik /* configure PCS */ 462c6fd2807SJeff Garzik pci_read_config_word(pdev, 0x92, &tmp16); 46349f29090STejun Heo if ((tmp16 & hpriv->port_map) != hpriv->port_map) { 46449f29090STejun Heo tmp16 |= hpriv->port_map; 465c6fd2807SJeff Garzik pci_write_config_word(pdev, 0x92, tmp16); 466c6fd2807SJeff Garzik } 46749f29090STejun Heo } 468c6fd2807SJeff Garzik 469c6fd2807SJeff Garzik return 0; 470c6fd2807SJeff Garzik } 471c6fd2807SJeff Garzik 472781d6550SAnton Vorontsov static void ahci_pci_init_controller(struct ata_host *host) 473781d6550SAnton Vorontsov { 474781d6550SAnton Vorontsov struct ahci_host_priv *hpriv = host->private_data; 475781d6550SAnton Vorontsov struct pci_dev *pdev = to_pci_dev(host->dev); 476781d6550SAnton Vorontsov void __iomem *port_mmio; 477781d6550SAnton Vorontsov u32 tmp; 478c40e7cb8SJose Alberto Reguero int mv; 4792bcd866bSJeff Garzik 480417a1a6dSTejun Heo if (hpriv->flags & AHCI_HFLAG_MV_PATA) { 481c40e7cb8SJose Alberto Reguero if (pdev->device == 0x6121) 482c40e7cb8SJose Alberto Reguero mv = 2; 483c40e7cb8SJose Alberto Reguero else 484c40e7cb8SJose Alberto Reguero mv = 4; 485c40e7cb8SJose Alberto Reguero port_mmio = __ahci_port_base(host, mv); 486cd70c266SJeff Garzik 487cd70c266SJeff Garzik writel(0, port_mmio + PORT_IRQ_MASK); 488cd70c266SJeff Garzik 489cd70c266SJeff Garzik /* clear port IRQ */ 490cd70c266SJeff Garzik tmp = readl(port_mmio + PORT_IRQ_STAT); 491cd70c266SJeff Garzik VPRINTK("PORT_IRQ_STAT 0x%x\n", tmp); 492cd70c266SJeff Garzik if (tmp) 493cd70c266SJeff Garzik writel(tmp, port_mmio + PORT_IRQ_STAT); 494cd70c266SJeff Garzik } 495cd70c266SJeff Garzik 496781d6550SAnton Vorontsov ahci_init_controller(host); 497c6fd2807SJeff Garzik } 498c6fd2807SJeff Garzik 499bd17243aSShane Huang static int ahci_sb600_check_ready(struct ata_link *link) 500bd17243aSShane Huang { 501bd17243aSShane Huang void __iomem *port_mmio = ahci_port_base(link->ap); 502bd17243aSShane Huang u8 status = readl(port_mmio + PORT_TFDATA) & 0xFF; 503bd17243aSShane Huang u32 irq_status = readl(port_mmio + PORT_IRQ_STAT); 504bd17243aSShane Huang 505bd17243aSShane Huang /* 506bd17243aSShane Huang * There is no need to check TFDATA if BAD PMP is found due to HW bug, 507bd17243aSShane Huang * which can save timeout delay. 508bd17243aSShane Huang */ 509bd17243aSShane Huang if (irq_status & PORT_IRQ_BAD_PMP) 510bd17243aSShane Huang return -EIO; 511bd17243aSShane Huang 512bd17243aSShane Huang return ata_check_ready(status); 513bd17243aSShane Huang } 514bd17243aSShane Huang 515bd17243aSShane Huang static int ahci_sb600_softreset(struct ata_link *link, unsigned int *class, 516bd17243aSShane Huang unsigned long deadline) 517bd17243aSShane Huang { 518bd17243aSShane Huang struct ata_port *ap = link->ap; 519bd17243aSShane Huang void __iomem *port_mmio = ahci_port_base(ap); 520bd17243aSShane Huang int pmp = sata_srst_pmp(link); 521bd17243aSShane Huang int rc; 522bd17243aSShane Huang u32 irq_sts; 523bd17243aSShane Huang 524bd17243aSShane Huang DPRINTK("ENTER\n"); 525bd17243aSShane Huang 526bd17243aSShane Huang rc = ahci_do_softreset(link, class, pmp, deadline, 527bd17243aSShane Huang ahci_sb600_check_ready); 528bd17243aSShane Huang 529bd17243aSShane Huang /* 530bd17243aSShane Huang * Soft reset fails on some ATI chips with IPMS set when PMP 531bd17243aSShane Huang * is enabled but SATA HDD/ODD is connected to SATA port, 532bd17243aSShane Huang * do soft reset again to port 0. 533bd17243aSShane Huang */ 534bd17243aSShane Huang if (rc == -EIO) { 535bd17243aSShane Huang irq_sts = readl(port_mmio + PORT_IRQ_STAT); 536bd17243aSShane Huang if (irq_sts & PORT_IRQ_BAD_PMP) { 537bd17243aSShane Huang ata_link_printk(link, KERN_WARNING, 538b6931c1fSShane Huang "applying SB600 PMP SRST workaround " 539b6931c1fSShane Huang "and retrying\n"); 540bd17243aSShane Huang rc = ahci_do_softreset(link, class, 0, deadline, 541bd17243aSShane Huang ahci_check_ready); 542bd17243aSShane Huang } 543bd17243aSShane Huang } 544bd17243aSShane Huang 545bd17243aSShane Huang return rc; 546bd17243aSShane Huang } 547bd17243aSShane Huang 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 { 619cca3974eSJeff Garzik struct ata_host *host = dev_get_drvdata(&pdev->dev); 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) { 6269b10ae86STejun Heo dev_printk(KERN_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 { 647cca3974eSJeff Garzik struct ata_host *host = dev_get_drvdata(&pdev->dev); 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 672c6fd2807SJeff Garzik if (using_dac && 6736a35528aSYang Hongyang !pci_set_dma_mask(pdev, DMA_BIT_MASK(64))) { 6746a35528aSYang Hongyang rc = pci_set_consistent_dma_mask(pdev, DMA_BIT_MASK(64)); 675c6fd2807SJeff Garzik if (rc) { 676284901a9SYang Hongyang rc = pci_set_consistent_dma_mask(pdev, DMA_BIT_MASK(32)); 677c6fd2807SJeff Garzik if (rc) { 678c6fd2807SJeff Garzik dev_printk(KERN_ERR, &pdev->dev, 679c6fd2807SJeff Garzik "64-bit DMA enable failed\n"); 680c6fd2807SJeff Garzik return rc; 681c6fd2807SJeff Garzik } 682c6fd2807SJeff Garzik } 683c6fd2807SJeff Garzik } else { 684284901a9SYang Hongyang rc = pci_set_dma_mask(pdev, DMA_BIT_MASK(32)); 685c6fd2807SJeff Garzik if (rc) { 686c6fd2807SJeff Garzik dev_printk(KERN_ERR, &pdev->dev, 687c6fd2807SJeff Garzik "32-bit DMA enable failed\n"); 688c6fd2807SJeff Garzik return rc; 689c6fd2807SJeff Garzik } 690284901a9SYang Hongyang rc = pci_set_consistent_dma_mask(pdev, DMA_BIT_MASK(32)); 691c6fd2807SJeff Garzik if (rc) { 692c6fd2807SJeff Garzik dev_printk(KERN_ERR, &pdev->dev, 693c6fd2807SJeff Garzik "32-bit consistent DMA enable failed\n"); 694c6fd2807SJeff Garzik return rc; 695c6fd2807SJeff Garzik } 696c6fd2807SJeff Garzik } 697c6fd2807SJeff Garzik return 0; 698c6fd2807SJeff Garzik } 699c6fd2807SJeff Garzik 700439fcaecSAnton Vorontsov static void ahci_pci_print_info(struct ata_host *host) 701439fcaecSAnton Vorontsov { 702439fcaecSAnton Vorontsov struct pci_dev *pdev = to_pci_dev(host->dev); 703439fcaecSAnton Vorontsov u16 cc; 704439fcaecSAnton Vorontsov const char *scc_s; 705439fcaecSAnton Vorontsov 706439fcaecSAnton Vorontsov pci_read_config_word(pdev, 0x0a, &cc); 707439fcaecSAnton Vorontsov if (cc == PCI_CLASS_STORAGE_IDE) 708439fcaecSAnton Vorontsov scc_s = "IDE"; 709439fcaecSAnton Vorontsov else if (cc == PCI_CLASS_STORAGE_SATA) 710439fcaecSAnton Vorontsov scc_s = "SATA"; 711439fcaecSAnton Vorontsov else if (cc == PCI_CLASS_STORAGE_RAID) 712439fcaecSAnton Vorontsov scc_s = "RAID"; 713439fcaecSAnton Vorontsov else 714439fcaecSAnton Vorontsov scc_s = "unknown"; 715439fcaecSAnton Vorontsov 716439fcaecSAnton Vorontsov ahci_print_info(host, scc_s); 717439fcaecSAnton Vorontsov } 718439fcaecSAnton Vorontsov 719edc93052STejun Heo /* On ASUS P5W DH Deluxe, the second port of PCI device 00:1f.2 is 720edc93052STejun Heo * hardwired to on-board SIMG 4726. The chipset is ICH8 and doesn't 721edc93052STejun Heo * support PMP and the 4726 either directly exports the device 722edc93052STejun Heo * attached to the first downstream port or acts as a hardware storage 723edc93052STejun Heo * controller and emulate a single ATA device (can be RAID 0/1 or some 724edc93052STejun Heo * other configuration). 725edc93052STejun Heo * 726edc93052STejun Heo * When there's no device attached to the first downstream port of the 727edc93052STejun Heo * 4726, "Config Disk" appears, which is a pseudo ATA device to 728edc93052STejun Heo * configure the 4726. However, ATA emulation of the device is very 729edc93052STejun Heo * lame. It doesn't send signature D2H Reg FIS after the initial 730edc93052STejun Heo * hardreset, pukes on SRST w/ PMP==0 and has bunch of other issues. 731edc93052STejun Heo * 732edc93052STejun Heo * The following function works around the problem by always using 733edc93052STejun Heo * hardreset on the port and not depending on receiving signature FIS 734edc93052STejun Heo * afterward. If signature FIS isn't received soon, ATA class is 735edc93052STejun Heo * assumed without follow-up softreset. 736edc93052STejun Heo */ 737edc93052STejun Heo static void ahci_p5wdh_workaround(struct ata_host *host) 738edc93052STejun Heo { 739edc93052STejun Heo static struct dmi_system_id sysids[] = { 740edc93052STejun Heo { 741edc93052STejun Heo .ident = "P5W DH Deluxe", 742edc93052STejun Heo .matches = { 743edc93052STejun Heo DMI_MATCH(DMI_SYS_VENDOR, 744edc93052STejun Heo "ASUSTEK COMPUTER INC"), 745edc93052STejun Heo DMI_MATCH(DMI_PRODUCT_NAME, "P5W DH Deluxe"), 746edc93052STejun Heo }, 747edc93052STejun Heo }, 748edc93052STejun Heo { } 749edc93052STejun Heo }; 750edc93052STejun Heo struct pci_dev *pdev = to_pci_dev(host->dev); 751edc93052STejun Heo 752edc93052STejun Heo if (pdev->bus->number == 0 && pdev->devfn == PCI_DEVFN(0x1f, 2) && 753edc93052STejun Heo dmi_check_system(sysids)) { 754edc93052STejun Heo struct ata_port *ap = host->ports[1]; 755edc93052STejun Heo 756edc93052STejun Heo dev_printk(KERN_INFO, &pdev->dev, "enabling ASUS P5W DH " 757edc93052STejun Heo "Deluxe on-board SIMG4726 workaround\n"); 758edc93052STejun Heo 759edc93052STejun Heo ap->ops = &ahci_p5wdh_ops; 760edc93052STejun Heo ap->link.flags |= ATA_LFLAG_NO_SRST | ATA_LFLAG_ASSUME_ATA; 761edc93052STejun Heo } 762edc93052STejun Heo } 763edc93052STejun Heo 7642fcad9d2STejun Heo /* only some SB600 ahci controllers can do 64bit DMA */ 7652fcad9d2STejun Heo static bool ahci_sb600_enable_64bit(struct pci_dev *pdev) 76658a09b38SShane Huang { 76758a09b38SShane Huang static const struct dmi_system_id sysids[] = { 76803d783bfSTejun Heo /* 76903d783bfSTejun Heo * The oldest version known to be broken is 0901 and 77003d783bfSTejun Heo * working is 1501 which was released on 2007-10-26. 7712fcad9d2STejun Heo * Enable 64bit DMA on 1501 and anything newer. 7722fcad9d2STejun Heo * 77303d783bfSTejun Heo * Please read bko#9412 for more info. 77403d783bfSTejun Heo */ 77558a09b38SShane Huang { 77658a09b38SShane Huang .ident = "ASUS M2A-VM", 77758a09b38SShane Huang .matches = { 77858a09b38SShane Huang DMI_MATCH(DMI_BOARD_VENDOR, 77958a09b38SShane Huang "ASUSTeK Computer INC."), 78058a09b38SShane Huang DMI_MATCH(DMI_BOARD_NAME, "M2A-VM"), 78158a09b38SShane Huang }, 78203d783bfSTejun Heo .driver_data = "20071026", /* yyyymmdd */ 78358a09b38SShane Huang }, 784e65cc194SMark Nelson /* 785e65cc194SMark Nelson * All BIOS versions for the MSI K9A2 Platinum (MS-7376) 786e65cc194SMark Nelson * support 64bit DMA. 787e65cc194SMark Nelson * 788e65cc194SMark Nelson * BIOS versions earlier than 1.5 had the Manufacturer DMI 789e65cc194SMark Nelson * fields as "MICRO-STAR INTERANTIONAL CO.,LTD". 790e65cc194SMark Nelson * This spelling mistake was fixed in BIOS version 1.5, so 791e65cc194SMark Nelson * 1.5 and later have the Manufacturer as 792e65cc194SMark Nelson * "MICRO-STAR INTERNATIONAL CO.,LTD". 793e65cc194SMark Nelson * So try to match on DMI_BOARD_VENDOR of "MICRO-STAR INTER". 794e65cc194SMark Nelson * 795e65cc194SMark Nelson * BIOS versions earlier than 1.9 had a Board Product Name 796e65cc194SMark Nelson * DMI field of "MS-7376". This was changed to be 797e65cc194SMark Nelson * "K9A2 Platinum (MS-7376)" in version 1.9, but we can still 798e65cc194SMark Nelson * match on DMI_BOARD_NAME of "MS-7376". 799e65cc194SMark Nelson */ 800e65cc194SMark Nelson { 801e65cc194SMark Nelson .ident = "MSI K9A2 Platinum", 802e65cc194SMark Nelson .matches = { 803e65cc194SMark Nelson DMI_MATCH(DMI_BOARD_VENDOR, 804e65cc194SMark Nelson "MICRO-STAR INTER"), 805e65cc194SMark Nelson DMI_MATCH(DMI_BOARD_NAME, "MS-7376"), 806e65cc194SMark Nelson }, 807e65cc194SMark Nelson }, 80858a09b38SShane Huang { } 80958a09b38SShane Huang }; 81003d783bfSTejun Heo const struct dmi_system_id *match; 8112fcad9d2STejun Heo int year, month, date; 8122fcad9d2STejun Heo char buf[9]; 81358a09b38SShane Huang 81403d783bfSTejun Heo match = dmi_first_match(sysids); 81558a09b38SShane Huang if (pdev->bus->number != 0 || pdev->devfn != PCI_DEVFN(0x12, 0) || 81603d783bfSTejun Heo !match) 81758a09b38SShane Huang return false; 81858a09b38SShane Huang 819e65cc194SMark Nelson if (!match->driver_data) 820e65cc194SMark Nelson goto enable_64bit; 821e65cc194SMark Nelson 82203d783bfSTejun Heo dmi_get_date(DMI_BIOS_DATE, &year, &month, &date); 82303d783bfSTejun Heo snprintf(buf, sizeof(buf), "%04d%02d%02d", year, month, date); 82403d783bfSTejun Heo 825e65cc194SMark Nelson if (strcmp(buf, match->driver_data) >= 0) 826e65cc194SMark Nelson goto enable_64bit; 827e65cc194SMark Nelson else { 82803d783bfSTejun Heo dev_printk(KERN_WARNING, &pdev->dev, "%s: BIOS too old, " 82903d783bfSTejun Heo "forcing 32bit DMA, update BIOS\n", match->ident); 8302fcad9d2STejun Heo return false; 8312fcad9d2STejun Heo } 832e65cc194SMark Nelson 833e65cc194SMark Nelson enable_64bit: 834e65cc194SMark Nelson dev_printk(KERN_WARNING, &pdev->dev, "%s: enabling 64bit DMA\n", 835e65cc194SMark Nelson match->ident); 836e65cc194SMark Nelson return true; 83758a09b38SShane Huang } 83858a09b38SShane Huang 8391fd68434SRafael J. Wysocki static bool ahci_broken_system_poweroff(struct pci_dev *pdev) 8401fd68434SRafael J. Wysocki { 8411fd68434SRafael J. Wysocki static const struct dmi_system_id broken_systems[] = { 8421fd68434SRafael J. Wysocki { 8431fd68434SRafael J. Wysocki .ident = "HP Compaq nx6310", 8441fd68434SRafael J. Wysocki .matches = { 8451fd68434SRafael J. Wysocki DMI_MATCH(DMI_SYS_VENDOR, "Hewlett-Packard"), 8461fd68434SRafael J. Wysocki DMI_MATCH(DMI_PRODUCT_NAME, "HP Compaq nx6310"), 8471fd68434SRafael J. Wysocki }, 8481fd68434SRafael J. Wysocki /* PCI slot number of the controller */ 8491fd68434SRafael J. Wysocki .driver_data = (void *)0x1FUL, 8501fd68434SRafael J. Wysocki }, 851d2f9c061SMaciej Rutecki { 852d2f9c061SMaciej Rutecki .ident = "HP Compaq 6720s", 853d2f9c061SMaciej Rutecki .matches = { 854d2f9c061SMaciej Rutecki DMI_MATCH(DMI_SYS_VENDOR, "Hewlett-Packard"), 855d2f9c061SMaciej Rutecki DMI_MATCH(DMI_PRODUCT_NAME, "HP Compaq 6720s"), 856d2f9c061SMaciej Rutecki }, 857d2f9c061SMaciej Rutecki /* PCI slot number of the controller */ 858d2f9c061SMaciej Rutecki .driver_data = (void *)0x1FUL, 859d2f9c061SMaciej Rutecki }, 8601fd68434SRafael J. Wysocki 8611fd68434SRafael J. Wysocki { } /* terminate list */ 8621fd68434SRafael J. Wysocki }; 8631fd68434SRafael J. Wysocki const struct dmi_system_id *dmi = dmi_first_match(broken_systems); 8641fd68434SRafael J. Wysocki 8651fd68434SRafael J. Wysocki if (dmi) { 8661fd68434SRafael J. Wysocki unsigned long slot = (unsigned long)dmi->driver_data; 8671fd68434SRafael J. Wysocki /* apply the quirk only to on-board controllers */ 8681fd68434SRafael J. Wysocki return slot == PCI_SLOT(pdev->devfn); 8691fd68434SRafael J. Wysocki } 8701fd68434SRafael J. Wysocki 8711fd68434SRafael J. Wysocki return false; 8721fd68434SRafael J. Wysocki } 8731fd68434SRafael J. Wysocki 8749b10ae86STejun Heo static bool ahci_broken_suspend(struct pci_dev *pdev) 8759b10ae86STejun Heo { 8769b10ae86STejun Heo static const struct dmi_system_id sysids[] = { 8779b10ae86STejun Heo /* 8789b10ae86STejun Heo * On HP dv[4-6] and HDX18 with earlier BIOSen, link 8799b10ae86STejun Heo * to the harddisk doesn't become online after 8809b10ae86STejun Heo * resuming from STR. Warn and fail suspend. 8819deb3431STejun Heo * 8829deb3431STejun Heo * http://bugzilla.kernel.org/show_bug.cgi?id=12276 8839deb3431STejun Heo * 8849deb3431STejun Heo * Use dates instead of versions to match as HP is 8859deb3431STejun Heo * apparently recycling both product and version 8869deb3431STejun Heo * strings. 8879deb3431STejun Heo * 8889deb3431STejun Heo * http://bugzilla.kernel.org/show_bug.cgi?id=15462 8899b10ae86STejun Heo */ 8909b10ae86STejun Heo { 8919b10ae86STejun Heo .ident = "dv4", 8929b10ae86STejun Heo .matches = { 8939b10ae86STejun Heo DMI_MATCH(DMI_SYS_VENDOR, "Hewlett-Packard"), 8949b10ae86STejun Heo DMI_MATCH(DMI_PRODUCT_NAME, 8959b10ae86STejun Heo "HP Pavilion dv4 Notebook PC"), 8969b10ae86STejun Heo }, 8979deb3431STejun Heo .driver_data = "20090105", /* F.30 */ 8989b10ae86STejun Heo }, 8999b10ae86STejun Heo { 9009b10ae86STejun Heo .ident = "dv5", 9019b10ae86STejun Heo .matches = { 9029b10ae86STejun Heo DMI_MATCH(DMI_SYS_VENDOR, "Hewlett-Packard"), 9039b10ae86STejun Heo DMI_MATCH(DMI_PRODUCT_NAME, 9049b10ae86STejun Heo "HP Pavilion dv5 Notebook PC"), 9059b10ae86STejun Heo }, 9069deb3431STejun Heo .driver_data = "20090506", /* F.16 */ 9079b10ae86STejun Heo }, 9089b10ae86STejun Heo { 9099b10ae86STejun Heo .ident = "dv6", 9109b10ae86STejun Heo .matches = { 9119b10ae86STejun Heo DMI_MATCH(DMI_SYS_VENDOR, "Hewlett-Packard"), 9129b10ae86STejun Heo DMI_MATCH(DMI_PRODUCT_NAME, 9139b10ae86STejun Heo "HP Pavilion dv6 Notebook PC"), 9149b10ae86STejun Heo }, 9159deb3431STejun Heo .driver_data = "20090423", /* F.21 */ 9169b10ae86STejun Heo }, 9179b10ae86STejun Heo { 9189b10ae86STejun Heo .ident = "HDX18", 9199b10ae86STejun Heo .matches = { 9209b10ae86STejun Heo DMI_MATCH(DMI_SYS_VENDOR, "Hewlett-Packard"), 9219b10ae86STejun Heo DMI_MATCH(DMI_PRODUCT_NAME, 9229b10ae86STejun Heo "HP HDX18 Notebook PC"), 9239b10ae86STejun Heo }, 9249deb3431STejun Heo .driver_data = "20090430", /* F.23 */ 9259b10ae86STejun Heo }, 926cedc9bf9STejun Heo /* 927cedc9bf9STejun Heo * Acer eMachines G725 has the same problem. BIOS 928cedc9bf9STejun Heo * V1.03 is known to be broken. V3.04 is known to 929*25985edcSLucas De Marchi * work. Between, there are V1.06, V2.06 and V3.03 930cedc9bf9STejun Heo * that we don't have much idea about. For now, 931cedc9bf9STejun Heo * blacklist anything older than V3.04. 9329deb3431STejun Heo * 9339deb3431STejun Heo * http://bugzilla.kernel.org/show_bug.cgi?id=15104 934cedc9bf9STejun Heo */ 935cedc9bf9STejun Heo { 936cedc9bf9STejun Heo .ident = "G725", 937cedc9bf9STejun Heo .matches = { 938cedc9bf9STejun Heo DMI_MATCH(DMI_SYS_VENDOR, "eMachines"), 939cedc9bf9STejun Heo DMI_MATCH(DMI_PRODUCT_NAME, "eMachines G725"), 940cedc9bf9STejun Heo }, 9419deb3431STejun Heo .driver_data = "20091216", /* V3.04 */ 942cedc9bf9STejun Heo }, 9439b10ae86STejun Heo { } /* terminate list */ 9449b10ae86STejun Heo }; 9459b10ae86STejun Heo const struct dmi_system_id *dmi = dmi_first_match(sysids); 9469deb3431STejun Heo int year, month, date; 9479deb3431STejun Heo char buf[9]; 9489b10ae86STejun Heo 9499b10ae86STejun Heo if (!dmi || pdev->bus->number || pdev->devfn != PCI_DEVFN(0x1f, 2)) 9509b10ae86STejun Heo return false; 9519b10ae86STejun Heo 9529deb3431STejun Heo dmi_get_date(DMI_BIOS_DATE, &year, &month, &date); 9539deb3431STejun Heo snprintf(buf, sizeof(buf), "%04d%02d%02d", year, month, date); 9549b10ae86STejun Heo 9559deb3431STejun Heo return strcmp(buf, dmi->driver_data) < 0; 9569b10ae86STejun Heo } 9579b10ae86STejun Heo 9585594639aSTejun Heo static bool ahci_broken_online(struct pci_dev *pdev) 9595594639aSTejun Heo { 9605594639aSTejun Heo #define ENCODE_BUSDEVFN(bus, slot, func) \ 9615594639aSTejun Heo (void *)(unsigned long)(((bus) << 8) | PCI_DEVFN((slot), (func))) 9625594639aSTejun Heo static const struct dmi_system_id sysids[] = { 9635594639aSTejun Heo /* 9645594639aSTejun Heo * There are several gigabyte boards which use 9655594639aSTejun Heo * SIMG5723s configured as hardware RAID. Certain 9665594639aSTejun Heo * 5723 firmware revisions shipped there keep the link 9675594639aSTejun Heo * online but fail to answer properly to SRST or 9685594639aSTejun Heo * IDENTIFY when no device is attached downstream 9695594639aSTejun Heo * causing libata to retry quite a few times leading 9705594639aSTejun Heo * to excessive detection delay. 9715594639aSTejun Heo * 9725594639aSTejun Heo * As these firmwares respond to the second reset try 9735594639aSTejun Heo * with invalid device signature, considering unknown 9745594639aSTejun Heo * sig as offline works around the problem acceptably. 9755594639aSTejun Heo */ 9765594639aSTejun Heo { 9775594639aSTejun Heo .ident = "EP45-DQ6", 9785594639aSTejun Heo .matches = { 9795594639aSTejun Heo DMI_MATCH(DMI_BOARD_VENDOR, 9805594639aSTejun Heo "Gigabyte Technology Co., Ltd."), 9815594639aSTejun Heo DMI_MATCH(DMI_BOARD_NAME, "EP45-DQ6"), 9825594639aSTejun Heo }, 9835594639aSTejun Heo .driver_data = ENCODE_BUSDEVFN(0x0a, 0x00, 0), 9845594639aSTejun Heo }, 9855594639aSTejun Heo { 9865594639aSTejun Heo .ident = "EP45-DS5", 9875594639aSTejun Heo .matches = { 9885594639aSTejun Heo DMI_MATCH(DMI_BOARD_VENDOR, 9895594639aSTejun Heo "Gigabyte Technology Co., Ltd."), 9905594639aSTejun Heo DMI_MATCH(DMI_BOARD_NAME, "EP45-DS5"), 9915594639aSTejun Heo }, 9925594639aSTejun Heo .driver_data = ENCODE_BUSDEVFN(0x03, 0x00, 0), 9935594639aSTejun Heo }, 9945594639aSTejun Heo { } /* terminate list */ 9955594639aSTejun Heo }; 9965594639aSTejun Heo #undef ENCODE_BUSDEVFN 9975594639aSTejun Heo const struct dmi_system_id *dmi = dmi_first_match(sysids); 9985594639aSTejun Heo unsigned int val; 9995594639aSTejun Heo 10005594639aSTejun Heo if (!dmi) 10015594639aSTejun Heo return false; 10025594639aSTejun Heo 10035594639aSTejun Heo val = (unsigned long)dmi->driver_data; 10045594639aSTejun Heo 10055594639aSTejun Heo return pdev->bus->number == (val >> 8) && pdev->devfn == (val & 0xff); 10065594639aSTejun Heo } 10075594639aSTejun Heo 10088e513217SMarkus Trippelsdorf #ifdef CONFIG_ATA_ACPI 1009f80ae7e4STejun Heo static void ahci_gtf_filter_workaround(struct ata_host *host) 1010f80ae7e4STejun Heo { 1011f80ae7e4STejun Heo static const struct dmi_system_id sysids[] = { 1012f80ae7e4STejun Heo /* 1013f80ae7e4STejun Heo * Aspire 3810T issues a bunch of SATA enable commands 1014f80ae7e4STejun Heo * via _GTF including an invalid one and one which is 1015f80ae7e4STejun Heo * rejected by the device. Among the successful ones 1016f80ae7e4STejun Heo * is FPDMA non-zero offset enable which when enabled 1017f80ae7e4STejun Heo * only on the drive side leads to NCQ command 1018f80ae7e4STejun Heo * failures. Filter it out. 1019f80ae7e4STejun Heo */ 1020f80ae7e4STejun Heo { 1021f80ae7e4STejun Heo .ident = "Aspire 3810T", 1022f80ae7e4STejun Heo .matches = { 1023f80ae7e4STejun Heo DMI_MATCH(DMI_SYS_VENDOR, "Acer"), 1024f80ae7e4STejun Heo DMI_MATCH(DMI_PRODUCT_NAME, "Aspire 3810T"), 1025f80ae7e4STejun Heo }, 1026f80ae7e4STejun Heo .driver_data = (void *)ATA_ACPI_FILTER_FPDMA_OFFSET, 1027f80ae7e4STejun Heo }, 1028f80ae7e4STejun Heo { } 1029f80ae7e4STejun Heo }; 1030f80ae7e4STejun Heo const struct dmi_system_id *dmi = dmi_first_match(sysids); 1031f80ae7e4STejun Heo unsigned int filter; 1032f80ae7e4STejun Heo int i; 1033f80ae7e4STejun Heo 1034f80ae7e4STejun Heo if (!dmi) 1035f80ae7e4STejun Heo return; 1036f80ae7e4STejun Heo 1037f80ae7e4STejun Heo filter = (unsigned long)dmi->driver_data; 1038f80ae7e4STejun Heo dev_printk(KERN_INFO, host->dev, 1039f80ae7e4STejun Heo "applying extra ACPI _GTF filter 0x%x for %s\n", 1040f80ae7e4STejun Heo filter, dmi->ident); 1041f80ae7e4STejun Heo 1042f80ae7e4STejun Heo for (i = 0; i < host->n_ports; i++) { 1043f80ae7e4STejun Heo struct ata_port *ap = host->ports[i]; 1044f80ae7e4STejun Heo struct ata_link *link; 1045f80ae7e4STejun Heo struct ata_device *dev; 1046f80ae7e4STejun Heo 1047f80ae7e4STejun Heo ata_for_each_link(link, ap, EDGE) 1048f80ae7e4STejun Heo ata_for_each_dev(dev, link, ALL) 1049f80ae7e4STejun Heo dev->gtf_filter |= filter; 1050f80ae7e4STejun Heo } 1051f80ae7e4STejun Heo } 10528e513217SMarkus Trippelsdorf #else 10538e513217SMarkus Trippelsdorf static inline void ahci_gtf_filter_workaround(struct ata_host *host) 10548e513217SMarkus Trippelsdorf {} 10558e513217SMarkus Trippelsdorf #endif 1056f80ae7e4STejun Heo 1057c6fd2807SJeff Garzik static int ahci_init_one(struct pci_dev *pdev, const struct pci_device_id *ent) 1058c6fd2807SJeff Garzik { 1059c6fd2807SJeff Garzik static int printed_version; 1060e297d99eSTejun Heo unsigned int board_id = ent->driver_data; 1061e297d99eSTejun Heo struct ata_port_info pi = ahci_port_info[board_id]; 10624447d351STejun Heo const struct ata_port_info *ppi[] = { &pi, NULL }; 106324dc5f33STejun Heo struct device *dev = &pdev->dev; 1064c6fd2807SJeff Garzik struct ahci_host_priv *hpriv; 10654447d351STejun Heo struct ata_host *host; 1066837f5f8fSTejun Heo int n_ports, i, rc; 1067c6fd2807SJeff Garzik 1068c6fd2807SJeff Garzik VPRINTK("ENTER\n"); 1069c6fd2807SJeff Garzik 1070b429dd59SJustin P. Mattock WARN_ON((int)ATA_MAX_QUEUE > AHCI_MAX_CMDS); 1071c6fd2807SJeff Garzik 1072c6fd2807SJeff Garzik if (!printed_version++) 1073c6fd2807SJeff Garzik dev_printk(KERN_DEBUG, &pdev->dev, "version " DRV_VERSION "\n"); 1074c6fd2807SJeff Garzik 10755b66c829SAlan Cox /* The AHCI driver can only drive the SATA ports, the PATA driver 10765b66c829SAlan Cox can drive them all so if both drivers are selected make sure 10775b66c829SAlan Cox AHCI stays out of the way */ 10785b66c829SAlan Cox if (pdev->vendor == PCI_VENDOR_ID_MARVELL && !marvell_enable) 10795b66c829SAlan Cox return -ENODEV; 10805b66c829SAlan Cox 1081c6353b45STejun Heo /* 1082c6353b45STejun Heo * For some reason, MCP89 on MacBook 7,1 doesn't work with 1083c6353b45STejun Heo * ahci, use ata_generic instead. 1084c6353b45STejun Heo */ 1085c6353b45STejun Heo if (pdev->vendor == PCI_VENDOR_ID_NVIDIA && 1086c6353b45STejun Heo pdev->device == PCI_DEVICE_ID_NVIDIA_NFORCE_MCP89_SATA && 1087c6353b45STejun Heo pdev->subsystem_vendor == PCI_VENDOR_ID_APPLE && 1088c6353b45STejun Heo pdev->subsystem_device == 0xcb89) 1089c6353b45STejun Heo return -ENODEV; 1090c6353b45STejun Heo 10917a02267eSMark Nelson /* Promise's PDC42819 is a SAS/SATA controller that has an AHCI mode. 10927a02267eSMark Nelson * At the moment, we can only use the AHCI mode. Let the users know 10937a02267eSMark Nelson * that for SAS drives they're out of luck. 10947a02267eSMark Nelson */ 10957a02267eSMark Nelson if (pdev->vendor == PCI_VENDOR_ID_PROMISE) 10967a02267eSMark Nelson dev_printk(KERN_INFO, &pdev->dev, "PDC42819 " 10977a02267eSMark Nelson "can only drive SATA devices with this driver\n"); 10987a02267eSMark Nelson 10994447d351STejun Heo /* acquire resources */ 110024dc5f33STejun Heo rc = pcim_enable_device(pdev); 1101c6fd2807SJeff Garzik if (rc) 1102c6fd2807SJeff Garzik return rc; 1103c6fd2807SJeff Garzik 1104dea55137STejun Heo /* AHCI controllers often implement SFF compatible interface. 1105dea55137STejun Heo * Grab all PCI BARs just in case. 1106dea55137STejun Heo */ 1107dea55137STejun Heo rc = pcim_iomap_regions_request_all(pdev, 1 << AHCI_PCI_BAR, DRV_NAME); 11080d5ff566STejun Heo if (rc == -EBUSY) 110924dc5f33STejun Heo pcim_pin_device(pdev); 11100d5ff566STejun Heo if (rc) 111124dc5f33STejun Heo return rc; 1112c6fd2807SJeff Garzik 1113c4f7792cSTejun Heo if (pdev->vendor == PCI_VENDOR_ID_INTEL && 1114c4f7792cSTejun Heo (pdev->device == 0x2652 || pdev->device == 0x2653)) { 1115c4f7792cSTejun Heo u8 map; 1116c4f7792cSTejun Heo 1117c4f7792cSTejun Heo /* ICH6s share the same PCI ID for both piix and ahci 1118c4f7792cSTejun Heo * modes. Enabling ahci mode while MAP indicates 1119c4f7792cSTejun Heo * combined mode is a bad idea. Yield to ata_piix. 1120c4f7792cSTejun Heo */ 1121c4f7792cSTejun Heo pci_read_config_byte(pdev, ICH_MAP, &map); 1122c4f7792cSTejun Heo if (map & 0x3) { 1123c4f7792cSTejun Heo dev_printk(KERN_INFO, &pdev->dev, "controller is in " 1124c4f7792cSTejun Heo "combined mode, can't enable AHCI mode\n"); 1125c4f7792cSTejun Heo return -ENODEV; 1126c4f7792cSTejun Heo } 1127c4f7792cSTejun Heo } 1128c4f7792cSTejun Heo 112924dc5f33STejun Heo hpriv = devm_kzalloc(dev, sizeof(*hpriv), GFP_KERNEL); 113024dc5f33STejun Heo if (!hpriv) 113124dc5f33STejun Heo return -ENOMEM; 1132417a1a6dSTejun Heo hpriv->flags |= (unsigned long)pi.private_data; 1133417a1a6dSTejun Heo 1134e297d99eSTejun Heo /* MCP65 revision A1 and A2 can't do MSI */ 1135e297d99eSTejun Heo if (board_id == board_ahci_mcp65 && 1136e297d99eSTejun Heo (pdev->revision == 0xa1 || pdev->revision == 0xa2)) 1137e297d99eSTejun Heo hpriv->flags |= AHCI_HFLAG_NO_MSI; 1138e297d99eSTejun Heo 1139e427fe04SShane Huang /* SB800 does NOT need the workaround to ignore SERR_INTERNAL */ 1140e427fe04SShane Huang if (board_id == board_ahci_sb700 && pdev->revision >= 0x40) 1141e427fe04SShane Huang hpriv->flags &= ~AHCI_HFLAG_IGN_SERR_INTERNAL; 1142e427fe04SShane Huang 11432fcad9d2STejun Heo /* only some SB600s can do 64bit DMA */ 11442fcad9d2STejun Heo if (ahci_sb600_enable_64bit(pdev)) 11452fcad9d2STejun Heo hpriv->flags &= ~AHCI_HFLAG_32BIT_ONLY; 114658a09b38SShane Huang 114731b239adSTejun Heo if ((hpriv->flags & AHCI_HFLAG_NO_MSI) || pci_enable_msi(pdev)) 114831b239adSTejun Heo pci_intx(pdev, 1); 1149c6fd2807SJeff Garzik 1150d8993349SAnton Vorontsov hpriv->mmio = pcim_iomap_table(pdev)[AHCI_PCI_BAR]; 1151d8993349SAnton Vorontsov 11524447d351STejun Heo /* save initial config */ 1153394d6e53SAnton Vorontsov ahci_pci_save_initial_config(pdev, hpriv); 1154c6fd2807SJeff Garzik 11554447d351STejun Heo /* prepare host */ 1156453d3131SRobert Hancock if (hpriv->cap & HOST_CAP_NCQ) { 1157453d3131SRobert Hancock pi.flags |= ATA_FLAG_NCQ; 115883f2b963STejun Heo /* 115983f2b963STejun Heo * Auto-activate optimization is supposed to be 116083f2b963STejun Heo * supported on all AHCI controllers indicating NCQ 116183f2b963STejun Heo * capability, but it seems to be broken on some 116283f2b963STejun Heo * chipsets including NVIDIAs. 116383f2b963STejun Heo */ 116483f2b963STejun Heo if (!(hpriv->flags & AHCI_HFLAG_NO_FPDMA_AA)) 1165453d3131SRobert Hancock pi.flags |= ATA_FLAG_FPDMA_AA; 1166453d3131SRobert Hancock } 11674447d351STejun Heo 11687d50b60bSTejun Heo if (hpriv->cap & HOST_CAP_PMP) 11697d50b60bSTejun Heo pi.flags |= ATA_FLAG_PMP; 11707d50b60bSTejun Heo 11710cbb0e77SAnton Vorontsov ahci_set_em_messages(hpriv, &pi); 117218f7ba4cSKristen Carlson Accardi 11731fd68434SRafael J. Wysocki if (ahci_broken_system_poweroff(pdev)) { 11741fd68434SRafael J. Wysocki pi.flags |= ATA_FLAG_NO_POWEROFF_SPINDOWN; 11751fd68434SRafael J. Wysocki dev_info(&pdev->dev, 11761fd68434SRafael J. Wysocki "quirky BIOS, skipping spindown on poweroff\n"); 11771fd68434SRafael J. Wysocki } 11781fd68434SRafael J. Wysocki 11799b10ae86STejun Heo if (ahci_broken_suspend(pdev)) { 11809b10ae86STejun Heo hpriv->flags |= AHCI_HFLAG_NO_SUSPEND; 11819b10ae86STejun Heo dev_printk(KERN_WARNING, &pdev->dev, 11829b10ae86STejun Heo "BIOS update required for suspend/resume\n"); 11839b10ae86STejun Heo } 11849b10ae86STejun Heo 11855594639aSTejun Heo if (ahci_broken_online(pdev)) { 11865594639aSTejun Heo hpriv->flags |= AHCI_HFLAG_SRST_TOUT_IS_OFFLINE; 11875594639aSTejun Heo dev_info(&pdev->dev, 11885594639aSTejun Heo "online status unreliable, applying workaround\n"); 11895594639aSTejun Heo } 11905594639aSTejun Heo 1191837f5f8fSTejun Heo /* CAP.NP sometimes indicate the index of the last enabled 1192837f5f8fSTejun Heo * port, at other times, that of the last possible port, so 1193837f5f8fSTejun Heo * determining the maximum port number requires looking at 1194837f5f8fSTejun Heo * both CAP.NP and port_map. 1195837f5f8fSTejun Heo */ 1196837f5f8fSTejun Heo n_ports = max(ahci_nr_ports(hpriv->cap), fls(hpriv->port_map)); 1197837f5f8fSTejun Heo 1198837f5f8fSTejun Heo host = ata_host_alloc_pinfo(&pdev->dev, ppi, n_ports); 11994447d351STejun Heo if (!host) 12004447d351STejun Heo return -ENOMEM; 12014447d351STejun Heo host->private_data = hpriv; 12024447d351STejun Heo 1203f3d7f23fSArjan van de Ven if (!(hpriv->cap & HOST_CAP_SSS) || ahci_ignore_sss) 1204886ad09fSArjan van de Ven host->flags |= ATA_HOST_PARALLEL_SCAN; 1205f3d7f23fSArjan van de Ven else 1206f3d7f23fSArjan van de Ven printk(KERN_INFO "ahci: SSS flag set, parallel bus scan disabled\n"); 1207886ad09fSArjan van de Ven 120818f7ba4cSKristen Carlson Accardi if (pi.flags & ATA_FLAG_EM) 120918f7ba4cSKristen Carlson Accardi ahci_reset_em(host); 121018f7ba4cSKristen Carlson Accardi 12114447d351STejun Heo for (i = 0; i < host->n_ports; i++) { 12124447d351STejun Heo struct ata_port *ap = host->ports[i]; 12134447d351STejun Heo 1214cbcdd875STejun Heo ata_port_pbar_desc(ap, AHCI_PCI_BAR, -1, "abar"); 1215cbcdd875STejun Heo ata_port_pbar_desc(ap, AHCI_PCI_BAR, 1216cbcdd875STejun Heo 0x100 + ap->port_no * 0x80, "port"); 1217cbcdd875STejun Heo 121818f7ba4cSKristen Carlson Accardi /* set enclosure management message type */ 121918f7ba4cSKristen Carlson Accardi if (ap->flags & ATA_FLAG_EM) 1220008dbd61SHarry Zhang ap->em_message_type = hpriv->em_msg_type; 122118f7ba4cSKristen Carlson Accardi 122218f7ba4cSKristen Carlson Accardi 1223dab632e8SJeff Garzik /* disabled/not-implemented port */ 1224350756f6STejun Heo if (!(hpriv->port_map & (1 << i))) 1225dab632e8SJeff Garzik ap->ops = &ata_dummy_port_ops; 12264447d351STejun Heo } 1227c6fd2807SJeff Garzik 1228edc93052STejun Heo /* apply workaround for ASUS P5W DH Deluxe mainboard */ 1229edc93052STejun Heo ahci_p5wdh_workaround(host); 1230edc93052STejun Heo 1231f80ae7e4STejun Heo /* apply gtf filter quirk */ 1232f80ae7e4STejun Heo ahci_gtf_filter_workaround(host); 1233f80ae7e4STejun Heo 1234c6fd2807SJeff Garzik /* initialize adapter */ 12354447d351STejun Heo rc = ahci_configure_dma_masks(pdev, hpriv->cap & HOST_CAP_64); 1236c6fd2807SJeff Garzik if (rc) 123724dc5f33STejun Heo return rc; 1238c6fd2807SJeff Garzik 12393303040dSAnton Vorontsov rc = ahci_pci_reset_controller(host); 12404447d351STejun Heo if (rc) 12414447d351STejun Heo return rc; 1242c6fd2807SJeff Garzik 1243781d6550SAnton Vorontsov ahci_pci_init_controller(host); 1244439fcaecSAnton Vorontsov ahci_pci_print_info(host); 1245c6fd2807SJeff Garzik 12464447d351STejun Heo pci_set_master(pdev); 12474447d351STejun Heo return ata_host_activate(host, pdev->irq, ahci_interrupt, IRQF_SHARED, 12484447d351STejun Heo &ahci_sht); 1249c6fd2807SJeff Garzik } 1250c6fd2807SJeff Garzik 1251c6fd2807SJeff Garzik static int __init ahci_init(void) 1252c6fd2807SJeff Garzik { 1253c6fd2807SJeff Garzik return pci_register_driver(&ahci_pci_driver); 1254c6fd2807SJeff Garzik } 1255c6fd2807SJeff Garzik 1256c6fd2807SJeff Garzik static void __exit ahci_exit(void) 1257c6fd2807SJeff Garzik { 1258c6fd2807SJeff Garzik pci_unregister_driver(&ahci_pci_driver); 1259c6fd2807SJeff Garzik } 1260c6fd2807SJeff Garzik 1261c6fd2807SJeff Garzik 1262c6fd2807SJeff Garzik MODULE_AUTHOR("Jeff Garzik"); 1263c6fd2807SJeff Garzik MODULE_DESCRIPTION("AHCI SATA low-level driver"); 1264c6fd2807SJeff Garzik MODULE_LICENSE("GPL"); 1265c6fd2807SJeff Garzik MODULE_DEVICE_TABLE(pci, ahci_pci_tbl); 1266c6fd2807SJeff Garzik MODULE_VERSION(DRV_VERSION); 1267c6fd2807SJeff Garzik 1268c6fd2807SJeff Garzik module_init(ahci_init); 1269c6fd2807SJeff Garzik module_exit(ahci_exit); 1270