1*c82ee6d3SThomas Gleixner // SPDX-License-Identifier: GPL-2.0-or-later 2c6fd2807SJeff Garzik /* 3c6fd2807SJeff Garzik * ahci.c - AHCI SATA support 4c6fd2807SJeff Garzik * 58c3d3d4bSTejun Heo * Maintained by: Tejun Heo <tj@kernel.org> 6c6fd2807SJeff Garzik * Please ALWAYS copy linux-ide@vger.kernel.org 7c6fd2807SJeff Garzik * on emails. 8c6fd2807SJeff Garzik * 9c6fd2807SJeff Garzik * Copyright 2004-2005 Red Hat, Inc. 10c6fd2807SJeff Garzik * 11c6fd2807SJeff Garzik * libata documentation is available via 'make {ps|pdf}docs', 1219285f3cSMauro Carvalho Chehab * as Documentation/driver-api/libata.rst 13c6fd2807SJeff Garzik * 14c6fd2807SJeff Garzik * AHCI hardware documentation: 15c6fd2807SJeff Garzik * http://www.intel.com/technology/serialata/pdf/rev1_0.pdf 16c6fd2807SJeff Garzik * http://www.intel.com/technology/serialata/pdf/rev1_1.pdf 17c6fd2807SJeff Garzik */ 18c6fd2807SJeff Garzik 19c6fd2807SJeff Garzik #include <linux/kernel.h> 20c6fd2807SJeff Garzik #include <linux/module.h> 21c6fd2807SJeff Garzik #include <linux/pci.h> 22c6fd2807SJeff Garzik #include <linux/blkdev.h> 23c6fd2807SJeff Garzik #include <linux/delay.h> 24c6fd2807SJeff Garzik #include <linux/interrupt.h> 25c6fd2807SJeff Garzik #include <linux/dma-mapping.h> 26c6fd2807SJeff Garzik #include <linux/device.h> 27edc93052STejun Heo #include <linux/dmi.h> 285a0e3ad6STejun Heo #include <linux/gfp.h> 29ee2aad42SRobert Richter #include <linux/msi.h> 30c6fd2807SJeff Garzik #include <scsi/scsi_host.h> 31c6fd2807SJeff Garzik #include <scsi/scsi_cmnd.h> 32c6fd2807SJeff Garzik #include <linux/libata.h> 33aecec8b6SChristoph Hellwig #include <linux/ahci-remap.h> 34aecec8b6SChristoph Hellwig #include <linux/io-64-nonatomic-lo-hi.h> 35365cfa1eSAnton Vorontsov #include "ahci.h" 36c6fd2807SJeff Garzik 37c6fd2807SJeff Garzik #define DRV_NAME "ahci" 387d50b60bSTejun Heo #define DRV_VERSION "3.0" 39c6fd2807SJeff Garzik 40c6fd2807SJeff Garzik enum { 41318893e1SAlessandro Rubini AHCI_PCI_BAR_STA2X11 = 0, 42b7ae128dSRobert Richter AHCI_PCI_BAR_CAVIUM = 0, 437f9c9f8eSHugh Daschbach AHCI_PCI_BAR_ENMOTUS = 2, 44b1314e3fSRadha Mohan Chintakuntla AHCI_PCI_BAR_CAVIUM_GEN5 = 4, 45318893e1SAlessandro Rubini AHCI_PCI_BAR_STANDARD = 5, 46441577efSTejun Heo }; 47c6fd2807SJeff Garzik 48441577efSTejun Heo enum board_ids { 49441577efSTejun Heo /* board IDs by feature in alphabetical order */ 50441577efSTejun Heo board_ahci, 51441577efSTejun Heo board_ahci_ign_iferr, 52ebb82e3cSHans de Goede board_ahci_mobile, 5366a7cbc3STejun Heo board_ahci_nomsi, 5467809f85SLevente Kurusa board_ahci_noncq, 55441577efSTejun Heo board_ahci_nosntf, 565f173107STejun Heo board_ahci_yes_fbs, 57441577efSTejun Heo 58441577efSTejun Heo /* board IDs for specific chipsets in alphabetical order */ 59dbfe8ef5SDan Williams board_ahci_avn, 60441577efSTejun Heo board_ahci_mcp65, 6183f2b963STejun Heo board_ahci_mcp77, 6283f2b963STejun Heo board_ahci_mcp89, 63441577efSTejun Heo board_ahci_mv, 64441577efSTejun Heo board_ahci_sb600, 65441577efSTejun Heo board_ahci_sb700, /* for SB700 and SB800 */ 66441577efSTejun Heo board_ahci_vt8251, 67441577efSTejun Heo 68441577efSTejun Heo /* aliases */ 69441577efSTejun Heo board_ahci_mcp_linux = board_ahci_mcp65, 70441577efSTejun Heo board_ahci_mcp67 = board_ahci_mcp65, 71441577efSTejun Heo board_ahci_mcp73 = board_ahci_mcp65, 7283f2b963STejun Heo board_ahci_mcp79 = board_ahci_mcp77, 73c6fd2807SJeff Garzik }; 74c6fd2807SJeff Garzik 75c6fd2807SJeff Garzik static int ahci_init_one(struct pci_dev *pdev, const struct pci_device_id *ent); 7602e53293SMika Westerberg static void ahci_remove_one(struct pci_dev *dev); 77a1efdabaSTejun Heo static int ahci_vt8251_hardreset(struct ata_link *link, unsigned int *class, 78a1efdabaSTejun Heo unsigned long deadline); 79dbfe8ef5SDan Williams static int ahci_avn_hardreset(struct ata_link *link, unsigned int *class, 80dbfe8ef5SDan Williams unsigned long deadline); 81cb85696dSJames Laird static void ahci_mcp89_apple_enable(struct pci_dev *pdev); 82cb85696dSJames Laird static bool is_mcp89_apple(struct pci_dev *pdev); 83a1efdabaSTejun Heo static int ahci_p5wdh_hardreset(struct ata_link *link, unsigned int *class, 84a1efdabaSTejun Heo unsigned long deadline); 8502e53293SMika Westerberg #ifdef CONFIG_PM 8602e53293SMika Westerberg static int ahci_pci_device_runtime_suspend(struct device *dev); 8702e53293SMika Westerberg static int ahci_pci_device_runtime_resume(struct device *dev); 88f1d848f9SMika Westerberg #ifdef CONFIG_PM_SLEEP 89f1d848f9SMika Westerberg static int ahci_pci_device_suspend(struct device *dev); 90f1d848f9SMika Westerberg static int ahci_pci_device_resume(struct device *dev); 91438ac6d5STejun Heo #endif 9202e53293SMika Westerberg #endif /* CONFIG_PM */ 93c6fd2807SJeff Garzik 94fad16e7aSTejun Heo static struct scsi_host_template ahci_sht = { 95fad16e7aSTejun Heo AHCI_SHT("ahci"), 96fad16e7aSTejun Heo }; 97fad16e7aSTejun Heo 98029cfd6bSTejun Heo static struct ata_port_operations ahci_vt8251_ops = { 99029cfd6bSTejun Heo .inherits = &ahci_ops, 100a1efdabaSTejun Heo .hardreset = ahci_vt8251_hardreset, 101ad616ffbSTejun Heo }; 102ad616ffbSTejun Heo 103029cfd6bSTejun Heo static struct ata_port_operations ahci_p5wdh_ops = { 104029cfd6bSTejun Heo .inherits = &ahci_ops, 105a1efdabaSTejun Heo .hardreset = ahci_p5wdh_hardreset, 106edc93052STejun Heo }; 107edc93052STejun Heo 108dbfe8ef5SDan Williams static struct ata_port_operations ahci_avn_ops = { 109dbfe8ef5SDan Williams .inherits = &ahci_ops, 110dbfe8ef5SDan Williams .hardreset = ahci_avn_hardreset, 111dbfe8ef5SDan Williams }; 112dbfe8ef5SDan Williams 113c6fd2807SJeff Garzik static const struct ata_port_info ahci_port_info[] = { 114441577efSTejun Heo /* by features */ 115facb8fa6SJeffrin Jose [board_ahci] = { 1161188c0d8STejun Heo .flags = AHCI_FLAG_COMMON, 11714bdef98SErik Inge Bolsø .pio_mask = ATA_PIO4, 118469248abSJeff Garzik .udma_mask = ATA_UDMA6, 119c6fd2807SJeff Garzik .port_ops = &ahci_ops, 120c6fd2807SJeff Garzik }, 121facb8fa6SJeffrin Jose [board_ahci_ign_iferr] = { 122417a1a6dSTejun Heo AHCI_HFLAGS (AHCI_HFLAG_IGN_IRQ_IF_ERR), 123417a1a6dSTejun Heo .flags = AHCI_FLAG_COMMON, 12414bdef98SErik Inge Bolsø .pio_mask = ATA_PIO4, 125469248abSJeff Garzik .udma_mask = ATA_UDMA6, 12641669553STejun Heo .port_ops = &ahci_ops, 12741669553STejun Heo }, 128ebb82e3cSHans de Goede [board_ahci_mobile] = { 129ebb82e3cSHans de Goede AHCI_HFLAGS (AHCI_HFLAG_IS_MOBILE), 130ebb82e3cSHans de Goede .flags = AHCI_FLAG_COMMON, 131ebb82e3cSHans de Goede .pio_mask = ATA_PIO4, 132ebb82e3cSHans de Goede .udma_mask = ATA_UDMA6, 133ebb82e3cSHans de Goede .port_ops = &ahci_ops, 134ebb82e3cSHans de Goede }, 13566a7cbc3STejun Heo [board_ahci_nomsi] = { 13666a7cbc3STejun Heo AHCI_HFLAGS (AHCI_HFLAG_NO_MSI), 13766a7cbc3STejun Heo .flags = AHCI_FLAG_COMMON, 13866a7cbc3STejun Heo .pio_mask = ATA_PIO4, 13966a7cbc3STejun Heo .udma_mask = ATA_UDMA6, 14066a7cbc3STejun Heo .port_ops = &ahci_ops, 14166a7cbc3STejun Heo }, 14267809f85SLevente Kurusa [board_ahci_noncq] = { 14367809f85SLevente Kurusa AHCI_HFLAGS (AHCI_HFLAG_NO_NCQ), 14467809f85SLevente Kurusa .flags = AHCI_FLAG_COMMON, 14567809f85SLevente Kurusa .pio_mask = ATA_PIO4, 14667809f85SLevente Kurusa .udma_mask = ATA_UDMA6, 14767809f85SLevente Kurusa .port_ops = &ahci_ops, 14867809f85SLevente Kurusa }, 149facb8fa6SJeffrin Jose [board_ahci_nosntf] = { 150441577efSTejun Heo AHCI_HFLAGS (AHCI_HFLAG_NO_SNTF), 151441577efSTejun Heo .flags = AHCI_FLAG_COMMON, 152441577efSTejun Heo .pio_mask = ATA_PIO4, 153441577efSTejun Heo .udma_mask = ATA_UDMA6, 154441577efSTejun Heo .port_ops = &ahci_ops, 155441577efSTejun Heo }, 156facb8fa6SJeffrin Jose [board_ahci_yes_fbs] = { 1575f173107STejun Heo AHCI_HFLAGS (AHCI_HFLAG_YES_FBS), 1585f173107STejun Heo .flags = AHCI_FLAG_COMMON, 1595f173107STejun Heo .pio_mask = ATA_PIO4, 1605f173107STejun Heo .udma_mask = ATA_UDMA6, 1615f173107STejun Heo .port_ops = &ahci_ops, 1625f173107STejun Heo }, 163441577efSTejun Heo /* by chipsets */ 164dbfe8ef5SDan Williams [board_ahci_avn] = { 165dbfe8ef5SDan Williams .flags = AHCI_FLAG_COMMON, 166dbfe8ef5SDan Williams .pio_mask = ATA_PIO4, 167dbfe8ef5SDan Williams .udma_mask = ATA_UDMA6, 168dbfe8ef5SDan Williams .port_ops = &ahci_avn_ops, 169dbfe8ef5SDan Williams }, 170facb8fa6SJeffrin Jose [board_ahci_mcp65] = { 17183f2b963STejun Heo AHCI_HFLAGS (AHCI_HFLAG_NO_FPDMA_AA | AHCI_HFLAG_NO_PMP | 17283f2b963STejun Heo AHCI_HFLAG_YES_NCQ), 173ae01b249STejun Heo .flags = AHCI_FLAG_COMMON | ATA_FLAG_NO_DIPM, 17483f2b963STejun Heo .pio_mask = ATA_PIO4, 17583f2b963STejun Heo .udma_mask = ATA_UDMA6, 17683f2b963STejun Heo .port_ops = &ahci_ops, 17783f2b963STejun Heo }, 178facb8fa6SJeffrin Jose [board_ahci_mcp77] = { 17983f2b963STejun Heo AHCI_HFLAGS (AHCI_HFLAG_NO_FPDMA_AA | AHCI_HFLAG_NO_PMP), 18083f2b963STejun Heo .flags = AHCI_FLAG_COMMON, 18183f2b963STejun Heo .pio_mask = ATA_PIO4, 18283f2b963STejun Heo .udma_mask = ATA_UDMA6, 18383f2b963STejun Heo .port_ops = &ahci_ops, 18483f2b963STejun Heo }, 185facb8fa6SJeffrin Jose [board_ahci_mcp89] = { 18683f2b963STejun Heo AHCI_HFLAGS (AHCI_HFLAG_NO_FPDMA_AA), 187441577efSTejun Heo .flags = AHCI_FLAG_COMMON, 188441577efSTejun Heo .pio_mask = ATA_PIO4, 189441577efSTejun Heo .udma_mask = ATA_UDMA6, 190441577efSTejun Heo .port_ops = &ahci_ops, 191441577efSTejun Heo }, 192facb8fa6SJeffrin Jose [board_ahci_mv] = { 193441577efSTejun Heo AHCI_HFLAGS (AHCI_HFLAG_NO_NCQ | AHCI_HFLAG_NO_MSI | 194441577efSTejun Heo AHCI_HFLAG_MV_PATA | AHCI_HFLAG_NO_PMP), 1959cbe056fSSergei Shtylyov .flags = ATA_FLAG_SATA | ATA_FLAG_PIO_DMA, 196441577efSTejun Heo .pio_mask = ATA_PIO4, 197441577efSTejun Heo .udma_mask = ATA_UDMA6, 198441577efSTejun Heo .port_ops = &ahci_ops, 199441577efSTejun Heo }, 200facb8fa6SJeffrin Jose [board_ahci_sb600] = { 201417a1a6dSTejun Heo AHCI_HFLAGS (AHCI_HFLAG_IGN_SERR_INTERNAL | 2022fcad9d2STejun Heo AHCI_HFLAG_NO_MSI | AHCI_HFLAG_SECT255 | 2032fcad9d2STejun Heo AHCI_HFLAG_32BIT_ONLY), 204417a1a6dSTejun Heo .flags = AHCI_FLAG_COMMON, 20514bdef98SErik Inge Bolsø .pio_mask = ATA_PIO4, 206469248abSJeff Garzik .udma_mask = ATA_UDMA6, 207345347c5SYuan-Hsin Chen .port_ops = &ahci_pmp_retry_srst_ops, 20855a61604SConke Hu }, 209facb8fa6SJeffrin Jose [board_ahci_sb700] = { /* for SB700 and SB800 */ 210bd17243aSShane Huang AHCI_HFLAGS (AHCI_HFLAG_IGN_SERR_INTERNAL), 211e39fc8c9SShane Huang .flags = AHCI_FLAG_COMMON, 21214bdef98SErik Inge Bolsø .pio_mask = ATA_PIO4, 213e39fc8c9SShane Huang .udma_mask = ATA_UDMA6, 214345347c5SYuan-Hsin Chen .port_ops = &ahci_pmp_retry_srst_ops, 215e39fc8c9SShane Huang }, 216facb8fa6SJeffrin Jose [board_ahci_vt8251] = { 217441577efSTejun Heo AHCI_HFLAGS (AHCI_HFLAG_NO_NCQ | AHCI_HFLAG_NO_PMP), 218e297d99eSTejun Heo .flags = AHCI_FLAG_COMMON, 21914bdef98SErik Inge Bolsø .pio_mask = ATA_PIO4, 220e297d99eSTejun Heo .udma_mask = ATA_UDMA6, 221441577efSTejun Heo .port_ops = &ahci_vt8251_ops, 2221b677afdSShaohua Li }, 223c6fd2807SJeff Garzik }; 224c6fd2807SJeff Garzik 225c6fd2807SJeff Garzik static const struct pci_device_id ahci_pci_tbl[] = { 226c6fd2807SJeff Garzik /* Intel */ 22754bb3a94SJeff Garzik { PCI_VDEVICE(INTEL, 0x2652), board_ahci }, /* ICH6 */ 22854bb3a94SJeff Garzik { PCI_VDEVICE(INTEL, 0x2653), board_ahci }, /* ICH6M */ 22954bb3a94SJeff Garzik { PCI_VDEVICE(INTEL, 0x27c1), board_ahci }, /* ICH7 */ 23054bb3a94SJeff Garzik { PCI_VDEVICE(INTEL, 0x27c5), board_ahci }, /* ICH7M */ 23154bb3a94SJeff Garzik { PCI_VDEVICE(INTEL, 0x27c3), board_ahci }, /* ICH7R */ 23282490c09STejun Heo { PCI_VDEVICE(AL, 0x5288), board_ahci_ign_iferr }, /* ULi M5288 */ 23354bb3a94SJeff Garzik { PCI_VDEVICE(INTEL, 0x2681), board_ahci }, /* ESB2 */ 23454bb3a94SJeff Garzik { PCI_VDEVICE(INTEL, 0x2682), board_ahci }, /* ESB2 */ 23554bb3a94SJeff Garzik { PCI_VDEVICE(INTEL, 0x2683), board_ahci }, /* ESB2 */ 23654bb3a94SJeff Garzik { PCI_VDEVICE(INTEL, 0x27c6), board_ahci }, /* ICH7-M DH */ 2377a234affSTejun Heo { PCI_VDEVICE(INTEL, 0x2821), board_ahci }, /* ICH8 */ 2381b677afdSShaohua Li { PCI_VDEVICE(INTEL, 0x2822), board_ahci_nosntf }, /* ICH8 */ 2397a234affSTejun Heo { PCI_VDEVICE(INTEL, 0x2824), board_ahci }, /* ICH8 */ 2407a234affSTejun Heo { PCI_VDEVICE(INTEL, 0x2829), board_ahci }, /* ICH8M */ 2417a234affSTejun Heo { PCI_VDEVICE(INTEL, 0x282a), board_ahci }, /* ICH8M */ 2427a234affSTejun Heo { PCI_VDEVICE(INTEL, 0x2922), board_ahci }, /* ICH9 */ 2437a234affSTejun Heo { PCI_VDEVICE(INTEL, 0x2923), board_ahci }, /* ICH9 */ 2447a234affSTejun Heo { PCI_VDEVICE(INTEL, 0x2924), board_ahci }, /* ICH9 */ 2457a234affSTejun Heo { PCI_VDEVICE(INTEL, 0x2925), board_ahci }, /* ICH9 */ 2467a234affSTejun Heo { PCI_VDEVICE(INTEL, 0x2927), board_ahci }, /* ICH9 */ 247ebb82e3cSHans de Goede { PCI_VDEVICE(INTEL, 0x2929), board_ahci_mobile }, /* ICH9M */ 248ebb82e3cSHans de Goede { PCI_VDEVICE(INTEL, 0x292a), board_ahci_mobile }, /* ICH9M */ 249ebb82e3cSHans de Goede { PCI_VDEVICE(INTEL, 0x292b), board_ahci_mobile }, /* ICH9M */ 250ebb82e3cSHans de Goede { PCI_VDEVICE(INTEL, 0x292c), board_ahci_mobile }, /* ICH9M */ 251ebb82e3cSHans de Goede { PCI_VDEVICE(INTEL, 0x292f), board_ahci_mobile }, /* ICH9M */ 2527a234affSTejun Heo { PCI_VDEVICE(INTEL, 0x294d), board_ahci }, /* ICH9 */ 253ebb82e3cSHans de Goede { PCI_VDEVICE(INTEL, 0x294e), board_ahci_mobile }, /* ICH9M */ 254d4155e6fSJason Gaston { PCI_VDEVICE(INTEL, 0x502a), board_ahci }, /* Tolapai */ 255d4155e6fSJason Gaston { PCI_VDEVICE(INTEL, 0x502b), board_ahci }, /* Tolapai */ 25616ad1ad9SJason Gaston { PCI_VDEVICE(INTEL, 0x3a05), board_ahci }, /* ICH10 */ 257b2dde6afSMark Goodwin { PCI_VDEVICE(INTEL, 0x3a22), board_ahci }, /* ICH10 */ 25816ad1ad9SJason Gaston { PCI_VDEVICE(INTEL, 0x3a25), board_ahci }, /* ICH10 */ 259c1f57d9bSDavid Milburn { PCI_VDEVICE(INTEL, 0x3b22), board_ahci }, /* PCH AHCI */ 260c1f57d9bSDavid Milburn { PCI_VDEVICE(INTEL, 0x3b23), board_ahci }, /* PCH AHCI */ 261adcb5308SSeth Heasley { PCI_VDEVICE(INTEL, 0x3b24), board_ahci }, /* PCH RAID */ 2628e48b6b3SSeth Heasley { PCI_VDEVICE(INTEL, 0x3b25), board_ahci }, /* PCH RAID */ 263ebb82e3cSHans de Goede { PCI_VDEVICE(INTEL, 0x3b29), board_ahci_mobile }, /* PCH M AHCI */ 264adcb5308SSeth Heasley { PCI_VDEVICE(INTEL, 0x3b2b), board_ahci }, /* PCH RAID */ 265ebb82e3cSHans de Goede { PCI_VDEVICE(INTEL, 0x3b2c), board_ahci_mobile }, /* PCH M RAID */ 266c1f57d9bSDavid Milburn { PCI_VDEVICE(INTEL, 0x3b2f), board_ahci }, /* PCH AHCI */ 267342decffSAlexandra Yates { PCI_VDEVICE(INTEL, 0x19b0), board_ahci }, /* DNV AHCI */ 268342decffSAlexandra Yates { PCI_VDEVICE(INTEL, 0x19b1), board_ahci }, /* DNV AHCI */ 269342decffSAlexandra Yates { PCI_VDEVICE(INTEL, 0x19b2), board_ahci }, /* DNV AHCI */ 270342decffSAlexandra Yates { PCI_VDEVICE(INTEL, 0x19b3), board_ahci }, /* DNV AHCI */ 271342decffSAlexandra Yates { PCI_VDEVICE(INTEL, 0x19b4), board_ahci }, /* DNV AHCI */ 272342decffSAlexandra Yates { PCI_VDEVICE(INTEL, 0x19b5), board_ahci }, /* DNV AHCI */ 273342decffSAlexandra Yates { PCI_VDEVICE(INTEL, 0x19b6), board_ahci }, /* DNV AHCI */ 274342decffSAlexandra Yates { PCI_VDEVICE(INTEL, 0x19b7), board_ahci }, /* DNV AHCI */ 275342decffSAlexandra Yates { PCI_VDEVICE(INTEL, 0x19bE), board_ahci }, /* DNV AHCI */ 276342decffSAlexandra Yates { PCI_VDEVICE(INTEL, 0x19bF), board_ahci }, /* DNV AHCI */ 277342decffSAlexandra Yates { PCI_VDEVICE(INTEL, 0x19c0), board_ahci }, /* DNV AHCI */ 278342decffSAlexandra Yates { PCI_VDEVICE(INTEL, 0x19c1), board_ahci }, /* DNV AHCI */ 279342decffSAlexandra Yates { PCI_VDEVICE(INTEL, 0x19c2), board_ahci }, /* DNV AHCI */ 280342decffSAlexandra Yates { PCI_VDEVICE(INTEL, 0x19c3), board_ahci }, /* DNV AHCI */ 281342decffSAlexandra Yates { PCI_VDEVICE(INTEL, 0x19c4), board_ahci }, /* DNV AHCI */ 282342decffSAlexandra Yates { PCI_VDEVICE(INTEL, 0x19c5), board_ahci }, /* DNV AHCI */ 283342decffSAlexandra Yates { PCI_VDEVICE(INTEL, 0x19c6), board_ahci }, /* DNV AHCI */ 284342decffSAlexandra Yates { PCI_VDEVICE(INTEL, 0x19c7), board_ahci }, /* DNV AHCI */ 285342decffSAlexandra Yates { PCI_VDEVICE(INTEL, 0x19cE), board_ahci }, /* DNV AHCI */ 286342decffSAlexandra Yates { PCI_VDEVICE(INTEL, 0x19cF), board_ahci }, /* DNV AHCI */ 2875623cab8SSeth Heasley { PCI_VDEVICE(INTEL, 0x1c02), board_ahci }, /* CPT AHCI */ 288ebb82e3cSHans de Goede { PCI_VDEVICE(INTEL, 0x1c03), board_ahci_mobile }, /* CPT M AHCI */ 2895623cab8SSeth Heasley { PCI_VDEVICE(INTEL, 0x1c04), board_ahci }, /* CPT RAID */ 290ebb82e3cSHans de Goede { PCI_VDEVICE(INTEL, 0x1c05), board_ahci_mobile }, /* CPT M RAID */ 2915623cab8SSeth Heasley { PCI_VDEVICE(INTEL, 0x1c06), board_ahci }, /* CPT RAID */ 2925623cab8SSeth Heasley { PCI_VDEVICE(INTEL, 0x1c07), board_ahci }, /* CPT RAID */ 293992b3fb9SSeth Heasley { PCI_VDEVICE(INTEL, 0x1d02), board_ahci }, /* PBG AHCI */ 294992b3fb9SSeth Heasley { PCI_VDEVICE(INTEL, 0x1d04), board_ahci }, /* PBG RAID */ 295992b3fb9SSeth Heasley { PCI_VDEVICE(INTEL, 0x1d06), board_ahci }, /* PBG RAID */ 29664a3903dSSeth Heasley { PCI_VDEVICE(INTEL, 0x2826), board_ahci }, /* PBG RAID */ 297a4a461a6SSeth Heasley { PCI_VDEVICE(INTEL, 0x2323), board_ahci }, /* DH89xxCC AHCI */ 298181e3ceaSSeth Heasley { PCI_VDEVICE(INTEL, 0x1e02), board_ahci }, /* Panther Point AHCI */ 299ebb82e3cSHans de Goede { PCI_VDEVICE(INTEL, 0x1e03), board_ahci_mobile }, /* Panther M AHCI */ 300181e3ceaSSeth Heasley { PCI_VDEVICE(INTEL, 0x1e04), board_ahci }, /* Panther Point RAID */ 301181e3ceaSSeth Heasley { PCI_VDEVICE(INTEL, 0x1e05), board_ahci }, /* Panther Point RAID */ 302181e3ceaSSeth Heasley { PCI_VDEVICE(INTEL, 0x1e06), board_ahci }, /* Panther Point RAID */ 303ebb82e3cSHans de Goede { PCI_VDEVICE(INTEL, 0x1e07), board_ahci_mobile }, /* Panther M RAID */ 3042cab7a4cSSeth Heasley { PCI_VDEVICE(INTEL, 0x1e0e), board_ahci }, /* Panther Point RAID */ 305ea4ace66SSeth Heasley { PCI_VDEVICE(INTEL, 0x8c02), board_ahci }, /* Lynx Point AHCI */ 306ebb82e3cSHans de Goede { PCI_VDEVICE(INTEL, 0x8c03), board_ahci_mobile }, /* Lynx M AHCI */ 307ea4ace66SSeth Heasley { PCI_VDEVICE(INTEL, 0x8c04), board_ahci }, /* Lynx Point RAID */ 308ebb82e3cSHans de Goede { PCI_VDEVICE(INTEL, 0x8c05), board_ahci_mobile }, /* Lynx M RAID */ 309ea4ace66SSeth Heasley { PCI_VDEVICE(INTEL, 0x8c06), board_ahci }, /* Lynx Point RAID */ 310ebb82e3cSHans de Goede { PCI_VDEVICE(INTEL, 0x8c07), board_ahci_mobile }, /* Lynx M RAID */ 311ea4ace66SSeth Heasley { PCI_VDEVICE(INTEL, 0x8c0e), board_ahci }, /* Lynx Point RAID */ 312ebb82e3cSHans de Goede { PCI_VDEVICE(INTEL, 0x8c0f), board_ahci_mobile }, /* Lynx M RAID */ 313ebb82e3cSHans de Goede { PCI_VDEVICE(INTEL, 0x9c02), board_ahci_mobile }, /* Lynx LP AHCI */ 314ebb82e3cSHans de Goede { PCI_VDEVICE(INTEL, 0x9c03), board_ahci_mobile }, /* Lynx LP AHCI */ 315ebb82e3cSHans de Goede { PCI_VDEVICE(INTEL, 0x9c04), board_ahci_mobile }, /* Lynx LP RAID */ 316ebb82e3cSHans de Goede { PCI_VDEVICE(INTEL, 0x9c05), board_ahci_mobile }, /* Lynx LP RAID */ 317ebb82e3cSHans de Goede { PCI_VDEVICE(INTEL, 0x9c06), board_ahci_mobile }, /* Lynx LP RAID */ 318ebb82e3cSHans de Goede { PCI_VDEVICE(INTEL, 0x9c07), board_ahci_mobile }, /* Lynx LP RAID */ 319ebb82e3cSHans de Goede { PCI_VDEVICE(INTEL, 0x9c0e), board_ahci_mobile }, /* Lynx LP RAID */ 320ebb82e3cSHans de Goede { PCI_VDEVICE(INTEL, 0x9c0f), board_ahci_mobile }, /* Lynx LP RAID */ 3214544e403SMika Westerberg { PCI_VDEVICE(INTEL, 0x9dd3), board_ahci_mobile }, /* Cannon Lake PCH-LP AHCI */ 32229e674ddSSeth Heasley { PCI_VDEVICE(INTEL, 0x1f22), board_ahci }, /* Avoton AHCI */ 32329e674ddSSeth Heasley { PCI_VDEVICE(INTEL, 0x1f23), board_ahci }, /* Avoton AHCI */ 32429e674ddSSeth Heasley { PCI_VDEVICE(INTEL, 0x1f24), board_ahci }, /* Avoton RAID */ 32529e674ddSSeth Heasley { PCI_VDEVICE(INTEL, 0x1f25), board_ahci }, /* Avoton RAID */ 32629e674ddSSeth Heasley { PCI_VDEVICE(INTEL, 0x1f26), board_ahci }, /* Avoton RAID */ 32729e674ddSSeth Heasley { PCI_VDEVICE(INTEL, 0x1f27), board_ahci }, /* Avoton RAID */ 32829e674ddSSeth Heasley { PCI_VDEVICE(INTEL, 0x1f2e), board_ahci }, /* Avoton RAID */ 32929e674ddSSeth Heasley { PCI_VDEVICE(INTEL, 0x1f2f), board_ahci }, /* Avoton RAID */ 330dbfe8ef5SDan Williams { PCI_VDEVICE(INTEL, 0x1f32), board_ahci_avn }, /* Avoton AHCI */ 331dbfe8ef5SDan Williams { PCI_VDEVICE(INTEL, 0x1f33), board_ahci_avn }, /* Avoton AHCI */ 332dbfe8ef5SDan Williams { PCI_VDEVICE(INTEL, 0x1f34), board_ahci_avn }, /* Avoton RAID */ 333dbfe8ef5SDan Williams { PCI_VDEVICE(INTEL, 0x1f35), board_ahci_avn }, /* Avoton RAID */ 334dbfe8ef5SDan Williams { PCI_VDEVICE(INTEL, 0x1f36), board_ahci_avn }, /* Avoton RAID */ 335dbfe8ef5SDan Williams { PCI_VDEVICE(INTEL, 0x1f37), board_ahci_avn }, /* Avoton RAID */ 336dbfe8ef5SDan Williams { PCI_VDEVICE(INTEL, 0x1f3e), board_ahci_avn }, /* Avoton RAID */ 337dbfe8ef5SDan Williams { PCI_VDEVICE(INTEL, 0x1f3f), board_ahci_avn }, /* Avoton RAID */ 338efda332cSJames Ralston { PCI_VDEVICE(INTEL, 0x2823), board_ahci }, /* Wellsburg RAID */ 339efda332cSJames Ralston { PCI_VDEVICE(INTEL, 0x2827), board_ahci }, /* Wellsburg RAID */ 340151743fdSJames Ralston { PCI_VDEVICE(INTEL, 0x8d02), board_ahci }, /* Wellsburg AHCI */ 341151743fdSJames Ralston { PCI_VDEVICE(INTEL, 0x8d04), board_ahci }, /* Wellsburg RAID */ 342151743fdSJames Ralston { PCI_VDEVICE(INTEL, 0x8d06), board_ahci }, /* Wellsburg RAID */ 343151743fdSJames Ralston { PCI_VDEVICE(INTEL, 0x8d0e), board_ahci }, /* Wellsburg RAID */ 344151743fdSJames Ralston { PCI_VDEVICE(INTEL, 0x8d62), board_ahci }, /* Wellsburg AHCI */ 345151743fdSJames Ralston { PCI_VDEVICE(INTEL, 0x8d64), board_ahci }, /* Wellsburg RAID */ 346151743fdSJames Ralston { PCI_VDEVICE(INTEL, 0x8d66), board_ahci }, /* Wellsburg RAID */ 347151743fdSJames Ralston { PCI_VDEVICE(INTEL, 0x8d6e), board_ahci }, /* Wellsburg RAID */ 3481cfc7df3SSeth Heasley { PCI_VDEVICE(INTEL, 0x23a3), board_ahci }, /* Coleto Creek AHCI */ 349ebb82e3cSHans de Goede { PCI_VDEVICE(INTEL, 0x9c83), board_ahci_mobile }, /* Wildcat LP AHCI */ 350ebb82e3cSHans de Goede { PCI_VDEVICE(INTEL, 0x9c85), board_ahci_mobile }, /* Wildcat LP RAID */ 351ebb82e3cSHans de Goede { PCI_VDEVICE(INTEL, 0x9c87), board_ahci_mobile }, /* Wildcat LP RAID */ 352ebb82e3cSHans de Goede { PCI_VDEVICE(INTEL, 0x9c8f), board_ahci_mobile }, /* Wildcat LP RAID */ 3531b071a09SJames Ralston { PCI_VDEVICE(INTEL, 0x8c82), board_ahci }, /* 9 Series AHCI */ 354ebb82e3cSHans de Goede { PCI_VDEVICE(INTEL, 0x8c83), board_ahci_mobile }, /* 9 Series M AHCI */ 3551b071a09SJames Ralston { PCI_VDEVICE(INTEL, 0x8c84), board_ahci }, /* 9 Series RAID */ 356ebb82e3cSHans de Goede { PCI_VDEVICE(INTEL, 0x8c85), board_ahci_mobile }, /* 9 Series M RAID */ 3571b071a09SJames Ralston { PCI_VDEVICE(INTEL, 0x8c86), board_ahci }, /* 9 Series RAID */ 358ebb82e3cSHans de Goede { PCI_VDEVICE(INTEL, 0x8c87), board_ahci_mobile }, /* 9 Series M RAID */ 3591b071a09SJames Ralston { PCI_VDEVICE(INTEL, 0x8c8e), board_ahci }, /* 9 Series RAID */ 360ebb82e3cSHans de Goede { PCI_VDEVICE(INTEL, 0x8c8f), board_ahci_mobile }, /* 9 Series M RAID */ 361ebb82e3cSHans de Goede { PCI_VDEVICE(INTEL, 0x9d03), board_ahci_mobile }, /* Sunrise LP AHCI */ 362ebb82e3cSHans de Goede { PCI_VDEVICE(INTEL, 0x9d05), board_ahci_mobile }, /* Sunrise LP RAID */ 363ebb82e3cSHans de Goede { PCI_VDEVICE(INTEL, 0x9d07), board_ahci_mobile }, /* Sunrise LP RAID */ 364c5967b79SCharles_Rose@Dell.com { PCI_VDEVICE(INTEL, 0xa102), board_ahci }, /* Sunrise Point-H AHCI */ 365ebb82e3cSHans de Goede { PCI_VDEVICE(INTEL, 0xa103), board_ahci_mobile }, /* Sunrise M AHCI */ 366690000b9SJames Ralston { PCI_VDEVICE(INTEL, 0xa105), board_ahci }, /* Sunrise Point-H RAID */ 367c5967b79SCharles_Rose@Dell.com { PCI_VDEVICE(INTEL, 0xa106), board_ahci }, /* Sunrise Point-H RAID */ 368ebb82e3cSHans de Goede { PCI_VDEVICE(INTEL, 0xa107), board_ahci_mobile }, /* Sunrise M RAID */ 369690000b9SJames Ralston { PCI_VDEVICE(INTEL, 0xa10f), board_ahci }, /* Sunrise Point-H RAID */ 3704d92f009SAlexandra Yates { PCI_VDEVICE(INTEL, 0x2822), board_ahci }, /* Lewisburg RAID*/ 371f5bdd66cSAlexandra Yates { PCI_VDEVICE(INTEL, 0x2823), board_ahci }, /* Lewisburg AHCI*/ 3724d92f009SAlexandra Yates { PCI_VDEVICE(INTEL, 0x2826), board_ahci }, /* Lewisburg RAID*/ 373f5bdd66cSAlexandra Yates { PCI_VDEVICE(INTEL, 0x2827), board_ahci }, /* Lewisburg RAID*/ 3744d92f009SAlexandra Yates { PCI_VDEVICE(INTEL, 0xa182), board_ahci }, /* Lewisburg AHCI*/ 3754d92f009SAlexandra Yates { PCI_VDEVICE(INTEL, 0xa186), board_ahci }, /* Lewisburg RAID*/ 376f5bdd66cSAlexandra Yates { PCI_VDEVICE(INTEL, 0xa1d2), board_ahci }, /* Lewisburg RAID*/ 377f5bdd66cSAlexandra Yates { PCI_VDEVICE(INTEL, 0xa1d6), board_ahci }, /* Lewisburg RAID*/ 3784d92f009SAlexandra Yates { PCI_VDEVICE(INTEL, 0xa202), board_ahci }, /* Lewisburg AHCI*/ 3794d92f009SAlexandra Yates { PCI_VDEVICE(INTEL, 0xa206), board_ahci }, /* Lewisburg RAID*/ 380f5bdd66cSAlexandra Yates { PCI_VDEVICE(INTEL, 0xa252), board_ahci }, /* Lewisburg RAID*/ 381f5bdd66cSAlexandra Yates { PCI_VDEVICE(INTEL, 0xa256), board_ahci }, /* Lewisburg RAID*/ 382f919dde0SMika Westerberg { PCI_VDEVICE(INTEL, 0xa356), board_ahci }, /* Cannon Lake PCH-H RAID */ 383ebb82e3cSHans de Goede { PCI_VDEVICE(INTEL, 0x0f22), board_ahci_mobile }, /* Bay Trail AHCI */ 384ebb82e3cSHans de Goede { PCI_VDEVICE(INTEL, 0x0f23), board_ahci_mobile }, /* Bay Trail AHCI */ 385ebb82e3cSHans de Goede { PCI_VDEVICE(INTEL, 0x22a3), board_ahci_mobile }, /* Cherry Tr. AHCI */ 386ebb82e3cSHans de Goede { PCI_VDEVICE(INTEL, 0x5ae3), board_ahci_mobile }, /* ApolloLake AHCI */ 387ba445791SMika Westerberg { PCI_VDEVICE(INTEL, 0x34d3), board_ahci_mobile }, /* Ice Lake LP AHCI */ 388c6fd2807SJeff Garzik 389e34bb370STejun Heo /* JMicron 360/1/3/5/6, match class to avoid IDE function */ 390e34bb370STejun Heo { PCI_VENDOR_ID_JMICRON, PCI_ANY_ID, PCI_ANY_ID, PCI_ANY_ID, 391e34bb370STejun Heo PCI_CLASS_STORAGE_SATA_AHCI, 0xffffff, board_ahci_ign_iferr }, 3921fefb8fdSBen Hutchings /* JMicron 362B and 362C have an AHCI function with IDE class code */ 3931fefb8fdSBen Hutchings { PCI_VDEVICE(JMICRON, 0x2362), board_ahci_ign_iferr }, 3941fefb8fdSBen Hutchings { PCI_VDEVICE(JMICRON, 0x236f), board_ahci_ign_iferr }, 39591f15fb3SZhang Rui /* May need to update quirk_jmicron_async_suspend() for additions */ 396c6fd2807SJeff Garzik 397c6fd2807SJeff Garzik /* ATI */ 398c65ec1c2SConke Hu { PCI_VDEVICE(ATI, 0x4380), board_ahci_sb600 }, /* ATI SB600 */ 399e39fc8c9SShane Huang { PCI_VDEVICE(ATI, 0x4390), board_ahci_sb700 }, /* ATI SB700/800 */ 400e39fc8c9SShane Huang { PCI_VDEVICE(ATI, 0x4391), board_ahci_sb700 }, /* ATI SB700/800 */ 401e39fc8c9SShane Huang { PCI_VDEVICE(ATI, 0x4392), board_ahci_sb700 }, /* ATI SB700/800 */ 402e39fc8c9SShane Huang { PCI_VDEVICE(ATI, 0x4393), board_ahci_sb700 }, /* ATI SB700/800 */ 403e39fc8c9SShane Huang { PCI_VDEVICE(ATI, 0x4394), board_ahci_sb700 }, /* ATI SB700/800 */ 404e39fc8c9SShane Huang { PCI_VDEVICE(ATI, 0x4395), board_ahci_sb700 }, /* ATI SB700/800 */ 405c6fd2807SJeff Garzik 406e2dd90b1SShane Huang /* AMD */ 4075deab536SShane Huang { PCI_VDEVICE(AMD, 0x7800), board_ahci }, /* AMD Hudson-2 */ 408fafe5c3dSShane Huang { PCI_VDEVICE(AMD, 0x7900), board_ahci }, /* AMD CZ */ 409e2dd90b1SShane Huang /* AMD is using RAID class only for ahci controllers */ 410e2dd90b1SShane Huang { PCI_VENDOR_ID_AMD, PCI_ANY_ID, PCI_ANY_ID, PCI_ANY_ID, 411e2dd90b1SShane Huang PCI_CLASS_STORAGE_RAID << 8, 0xffffff, board_ahci }, 412e2dd90b1SShane Huang 413c6fd2807SJeff Garzik /* VIA */ 41454bb3a94SJeff Garzik { PCI_VDEVICE(VIA, 0x3349), board_ahci_vt8251 }, /* VIA VT8251 */ 415bf335542STejun Heo { PCI_VDEVICE(VIA, 0x6287), board_ahci_vt8251 }, /* VIA VT8251 */ 416c6fd2807SJeff Garzik 417c6fd2807SJeff Garzik /* NVIDIA */ 418e297d99eSTejun Heo { PCI_VDEVICE(NVIDIA, 0x044c), board_ahci_mcp65 }, /* MCP65 */ 419e297d99eSTejun Heo { PCI_VDEVICE(NVIDIA, 0x044d), board_ahci_mcp65 }, /* MCP65 */ 420e297d99eSTejun Heo { PCI_VDEVICE(NVIDIA, 0x044e), board_ahci_mcp65 }, /* MCP65 */ 421e297d99eSTejun Heo { PCI_VDEVICE(NVIDIA, 0x044f), board_ahci_mcp65 }, /* MCP65 */ 422e297d99eSTejun Heo { PCI_VDEVICE(NVIDIA, 0x045c), board_ahci_mcp65 }, /* MCP65 */ 423e297d99eSTejun Heo { PCI_VDEVICE(NVIDIA, 0x045d), board_ahci_mcp65 }, /* MCP65 */ 424e297d99eSTejun Heo { PCI_VDEVICE(NVIDIA, 0x045e), board_ahci_mcp65 }, /* MCP65 */ 425e297d99eSTejun Heo { PCI_VDEVICE(NVIDIA, 0x045f), board_ahci_mcp65 }, /* MCP65 */ 426441577efSTejun Heo { PCI_VDEVICE(NVIDIA, 0x0550), board_ahci_mcp67 }, /* MCP67 */ 427441577efSTejun Heo { PCI_VDEVICE(NVIDIA, 0x0551), board_ahci_mcp67 }, /* MCP67 */ 428441577efSTejun Heo { PCI_VDEVICE(NVIDIA, 0x0552), board_ahci_mcp67 }, /* MCP67 */ 429441577efSTejun Heo { PCI_VDEVICE(NVIDIA, 0x0553), board_ahci_mcp67 }, /* MCP67 */ 430441577efSTejun Heo { PCI_VDEVICE(NVIDIA, 0x0554), board_ahci_mcp67 }, /* MCP67 */ 431441577efSTejun Heo { PCI_VDEVICE(NVIDIA, 0x0555), board_ahci_mcp67 }, /* MCP67 */ 432441577efSTejun Heo { PCI_VDEVICE(NVIDIA, 0x0556), board_ahci_mcp67 }, /* MCP67 */ 433441577efSTejun Heo { PCI_VDEVICE(NVIDIA, 0x0557), board_ahci_mcp67 }, /* MCP67 */ 434441577efSTejun Heo { PCI_VDEVICE(NVIDIA, 0x0558), board_ahci_mcp67 }, /* MCP67 */ 435441577efSTejun Heo { PCI_VDEVICE(NVIDIA, 0x0559), board_ahci_mcp67 }, /* MCP67 */ 436441577efSTejun Heo { PCI_VDEVICE(NVIDIA, 0x055a), board_ahci_mcp67 }, /* MCP67 */ 437441577efSTejun Heo { PCI_VDEVICE(NVIDIA, 0x055b), board_ahci_mcp67 }, /* MCP67 */ 438441577efSTejun Heo { PCI_VDEVICE(NVIDIA, 0x0580), board_ahci_mcp_linux }, /* Linux ID */ 439441577efSTejun Heo { PCI_VDEVICE(NVIDIA, 0x0581), board_ahci_mcp_linux }, /* Linux ID */ 440441577efSTejun Heo { PCI_VDEVICE(NVIDIA, 0x0582), board_ahci_mcp_linux }, /* Linux ID */ 441441577efSTejun Heo { PCI_VDEVICE(NVIDIA, 0x0583), board_ahci_mcp_linux }, /* Linux ID */ 442441577efSTejun Heo { PCI_VDEVICE(NVIDIA, 0x0584), board_ahci_mcp_linux }, /* Linux ID */ 443441577efSTejun Heo { PCI_VDEVICE(NVIDIA, 0x0585), board_ahci_mcp_linux }, /* Linux ID */ 444441577efSTejun Heo { PCI_VDEVICE(NVIDIA, 0x0586), board_ahci_mcp_linux }, /* Linux ID */ 445441577efSTejun Heo { PCI_VDEVICE(NVIDIA, 0x0587), board_ahci_mcp_linux }, /* Linux ID */ 446441577efSTejun Heo { PCI_VDEVICE(NVIDIA, 0x0588), board_ahci_mcp_linux }, /* Linux ID */ 447441577efSTejun Heo { PCI_VDEVICE(NVIDIA, 0x0589), board_ahci_mcp_linux }, /* Linux ID */ 448441577efSTejun Heo { PCI_VDEVICE(NVIDIA, 0x058a), board_ahci_mcp_linux }, /* Linux ID */ 449441577efSTejun Heo { PCI_VDEVICE(NVIDIA, 0x058b), board_ahci_mcp_linux }, /* Linux ID */ 450441577efSTejun Heo { PCI_VDEVICE(NVIDIA, 0x058c), board_ahci_mcp_linux }, /* Linux ID */ 451441577efSTejun Heo { PCI_VDEVICE(NVIDIA, 0x058d), board_ahci_mcp_linux }, /* Linux ID */ 452441577efSTejun Heo { PCI_VDEVICE(NVIDIA, 0x058e), board_ahci_mcp_linux }, /* Linux ID */ 453441577efSTejun Heo { PCI_VDEVICE(NVIDIA, 0x058f), board_ahci_mcp_linux }, /* Linux ID */ 454441577efSTejun Heo { PCI_VDEVICE(NVIDIA, 0x07f0), board_ahci_mcp73 }, /* MCP73 */ 455441577efSTejun Heo { PCI_VDEVICE(NVIDIA, 0x07f1), board_ahci_mcp73 }, /* MCP73 */ 456441577efSTejun Heo { PCI_VDEVICE(NVIDIA, 0x07f2), board_ahci_mcp73 }, /* MCP73 */ 457441577efSTejun Heo { PCI_VDEVICE(NVIDIA, 0x07f3), board_ahci_mcp73 }, /* MCP73 */ 458441577efSTejun Heo { PCI_VDEVICE(NVIDIA, 0x07f4), board_ahci_mcp73 }, /* MCP73 */ 459441577efSTejun Heo { PCI_VDEVICE(NVIDIA, 0x07f5), board_ahci_mcp73 }, /* MCP73 */ 460441577efSTejun Heo { PCI_VDEVICE(NVIDIA, 0x07f6), board_ahci_mcp73 }, /* MCP73 */ 461441577efSTejun Heo { PCI_VDEVICE(NVIDIA, 0x07f7), board_ahci_mcp73 }, /* MCP73 */ 462441577efSTejun Heo { PCI_VDEVICE(NVIDIA, 0x07f8), board_ahci_mcp73 }, /* MCP73 */ 463441577efSTejun Heo { PCI_VDEVICE(NVIDIA, 0x07f9), board_ahci_mcp73 }, /* MCP73 */ 464441577efSTejun Heo { PCI_VDEVICE(NVIDIA, 0x07fa), board_ahci_mcp73 }, /* MCP73 */ 465441577efSTejun Heo { PCI_VDEVICE(NVIDIA, 0x07fb), board_ahci_mcp73 }, /* MCP73 */ 466441577efSTejun Heo { PCI_VDEVICE(NVIDIA, 0x0ad0), board_ahci_mcp77 }, /* MCP77 */ 467441577efSTejun Heo { PCI_VDEVICE(NVIDIA, 0x0ad1), board_ahci_mcp77 }, /* MCP77 */ 468441577efSTejun Heo { PCI_VDEVICE(NVIDIA, 0x0ad2), board_ahci_mcp77 }, /* MCP77 */ 469441577efSTejun Heo { PCI_VDEVICE(NVIDIA, 0x0ad3), board_ahci_mcp77 }, /* MCP77 */ 470441577efSTejun Heo { PCI_VDEVICE(NVIDIA, 0x0ad4), board_ahci_mcp77 }, /* MCP77 */ 471441577efSTejun Heo { PCI_VDEVICE(NVIDIA, 0x0ad5), board_ahci_mcp77 }, /* MCP77 */ 472441577efSTejun Heo { PCI_VDEVICE(NVIDIA, 0x0ad6), board_ahci_mcp77 }, /* MCP77 */ 473441577efSTejun Heo { PCI_VDEVICE(NVIDIA, 0x0ad7), board_ahci_mcp77 }, /* MCP77 */ 474441577efSTejun Heo { PCI_VDEVICE(NVIDIA, 0x0ad8), board_ahci_mcp77 }, /* MCP77 */ 475441577efSTejun Heo { PCI_VDEVICE(NVIDIA, 0x0ad9), board_ahci_mcp77 }, /* MCP77 */ 476441577efSTejun Heo { PCI_VDEVICE(NVIDIA, 0x0ada), board_ahci_mcp77 }, /* MCP77 */ 477441577efSTejun Heo { PCI_VDEVICE(NVIDIA, 0x0adb), board_ahci_mcp77 }, /* MCP77 */ 478441577efSTejun Heo { PCI_VDEVICE(NVIDIA, 0x0ab4), board_ahci_mcp79 }, /* MCP79 */ 479441577efSTejun Heo { PCI_VDEVICE(NVIDIA, 0x0ab5), board_ahci_mcp79 }, /* MCP79 */ 480441577efSTejun Heo { PCI_VDEVICE(NVIDIA, 0x0ab6), board_ahci_mcp79 }, /* MCP79 */ 481441577efSTejun Heo { PCI_VDEVICE(NVIDIA, 0x0ab7), board_ahci_mcp79 }, /* MCP79 */ 482441577efSTejun Heo { PCI_VDEVICE(NVIDIA, 0x0ab8), board_ahci_mcp79 }, /* MCP79 */ 483441577efSTejun Heo { PCI_VDEVICE(NVIDIA, 0x0ab9), board_ahci_mcp79 }, /* MCP79 */ 484441577efSTejun Heo { PCI_VDEVICE(NVIDIA, 0x0aba), board_ahci_mcp79 }, /* MCP79 */ 485441577efSTejun Heo { PCI_VDEVICE(NVIDIA, 0x0abb), board_ahci_mcp79 }, /* MCP79 */ 486441577efSTejun Heo { PCI_VDEVICE(NVIDIA, 0x0abc), board_ahci_mcp79 }, /* MCP79 */ 487441577efSTejun Heo { PCI_VDEVICE(NVIDIA, 0x0abd), board_ahci_mcp79 }, /* MCP79 */ 488441577efSTejun Heo { PCI_VDEVICE(NVIDIA, 0x0abe), board_ahci_mcp79 }, /* MCP79 */ 489441577efSTejun Heo { PCI_VDEVICE(NVIDIA, 0x0abf), board_ahci_mcp79 }, /* MCP79 */ 490441577efSTejun Heo { PCI_VDEVICE(NVIDIA, 0x0d84), board_ahci_mcp89 }, /* MCP89 */ 491441577efSTejun Heo { PCI_VDEVICE(NVIDIA, 0x0d85), board_ahci_mcp89 }, /* MCP89 */ 492441577efSTejun Heo { PCI_VDEVICE(NVIDIA, 0x0d86), board_ahci_mcp89 }, /* MCP89 */ 493441577efSTejun Heo { PCI_VDEVICE(NVIDIA, 0x0d87), board_ahci_mcp89 }, /* MCP89 */ 494441577efSTejun Heo { PCI_VDEVICE(NVIDIA, 0x0d88), board_ahci_mcp89 }, /* MCP89 */ 495441577efSTejun Heo { PCI_VDEVICE(NVIDIA, 0x0d89), board_ahci_mcp89 }, /* MCP89 */ 496441577efSTejun Heo { PCI_VDEVICE(NVIDIA, 0x0d8a), board_ahci_mcp89 }, /* MCP89 */ 497441577efSTejun Heo { PCI_VDEVICE(NVIDIA, 0x0d8b), board_ahci_mcp89 }, /* MCP89 */ 498441577efSTejun Heo { PCI_VDEVICE(NVIDIA, 0x0d8c), board_ahci_mcp89 }, /* MCP89 */ 499441577efSTejun Heo { PCI_VDEVICE(NVIDIA, 0x0d8d), board_ahci_mcp89 }, /* MCP89 */ 500441577efSTejun Heo { PCI_VDEVICE(NVIDIA, 0x0d8e), board_ahci_mcp89 }, /* MCP89 */ 501441577efSTejun Heo { PCI_VDEVICE(NVIDIA, 0x0d8f), board_ahci_mcp89 }, /* MCP89 */ 502c6fd2807SJeff Garzik 503c6fd2807SJeff Garzik /* SiS */ 50420e2de4aSTejun Heo { PCI_VDEVICE(SI, 0x1184), board_ahci }, /* SiS 966 */ 50520e2de4aSTejun Heo { PCI_VDEVICE(SI, 0x1185), board_ahci }, /* SiS 968 */ 50620e2de4aSTejun Heo { PCI_VDEVICE(SI, 0x0186), board_ahci }, /* SiS 968 */ 507c6fd2807SJeff Garzik 508318893e1SAlessandro Rubini /* ST Microelectronics */ 509318893e1SAlessandro Rubini { PCI_VDEVICE(STMICRO, 0xCC06), board_ahci }, /* ST ConneXt */ 510318893e1SAlessandro Rubini 511cd70c266SJeff Garzik /* Marvell */ 512cd70c266SJeff Garzik { PCI_VDEVICE(MARVELL, 0x6145), board_ahci_mv }, /* 6145 */ 513c40e7cb8SJose Alberto Reguero { PCI_VDEVICE(MARVELL, 0x6121), board_ahci_mv }, /* 6121 */ 51469fd3157SMyron Stowe { PCI_DEVICE(PCI_VENDOR_ID_MARVELL_EXT, 0x9123), 51510aca06cSAnssi Hannula .class = PCI_CLASS_STORAGE_SATA_AHCI, 51610aca06cSAnssi Hannula .class_mask = 0xffffff, 5175f173107STejun Heo .driver_data = board_ahci_yes_fbs }, /* 88se9128 */ 51869fd3157SMyron Stowe { PCI_DEVICE(PCI_VENDOR_ID_MARVELL_EXT, 0x9125), 519467b41c6SPer Jessen .driver_data = board_ahci_yes_fbs }, /* 88se9125 */ 520e098f5cbSSimon Guinot { PCI_DEVICE_SUB(PCI_VENDOR_ID_MARVELL_EXT, 0x9178, 521e098f5cbSSimon Guinot PCI_VENDOR_ID_MARVELL_EXT, 0x9170), 522e098f5cbSSimon Guinot .driver_data = board_ahci_yes_fbs }, /* 88se9170 */ 52369fd3157SMyron Stowe { PCI_DEVICE(PCI_VENDOR_ID_MARVELL_EXT, 0x917a), 524642d8925SMatt Johnson .driver_data = board_ahci_yes_fbs }, /* 88se9172 */ 525fcce9a35SGeorge Spelvin { PCI_DEVICE(PCI_VENDOR_ID_MARVELL_EXT, 0x9172), 526c5edfff9SMurali Karicheri .driver_data = board_ahci_yes_fbs }, /* 88se9182 */ 527c5edfff9SMurali Karicheri { PCI_DEVICE(PCI_VENDOR_ID_MARVELL_EXT, 0x9182), 528fcce9a35SGeorge Spelvin .driver_data = board_ahci_yes_fbs }, /* 88se9172 */ 52969fd3157SMyron Stowe { PCI_DEVICE(PCI_VENDOR_ID_MARVELL_EXT, 0x9192), 53017c60c6bSAlan Cox .driver_data = board_ahci_yes_fbs }, /* 88se9172 on some Gigabyte */ 531754a292fSAndreas Schrägle { PCI_DEVICE(PCI_VENDOR_ID_MARVELL_EXT, 0x91a0), 532754a292fSAndreas Schrägle .driver_data = board_ahci_yes_fbs }, 533a40cf3f3SJohannes Thumshirn { PCI_DEVICE(PCI_VENDOR_ID_MARVELL_EXT, 0x91a2), /* 88se91a2 */ 534a40cf3f3SJohannes Thumshirn .driver_data = board_ahci_yes_fbs }, 53569fd3157SMyron Stowe { PCI_DEVICE(PCI_VENDOR_ID_MARVELL_EXT, 0x91a3), 53650be5e36STejun Heo .driver_data = board_ahci_yes_fbs }, 5376d5278a6SSamir Benmendil { PCI_DEVICE(PCI_VENDOR_ID_MARVELL_EXT, 0x9230), 5386d5278a6SSamir Benmendil .driver_data = board_ahci_yes_fbs }, 53928b2182dSHans de Goede { PCI_DEVICE(PCI_VENDOR_ID_TTI, 0x0642), /* highpoint rocketraid 642L */ 54028b2182dSHans de Goede .driver_data = board_ahci_yes_fbs }, 54128b2182dSHans de Goede { PCI_DEVICE(PCI_VENDOR_ID_TTI, 0x0645), /* highpoint rocketraid 644L */ 542d2518365SJérôme Carretero .driver_data = board_ahci_yes_fbs }, 543cd70c266SJeff Garzik 544c77a036bSMark Nelson /* Promise */ 545c77a036bSMark Nelson { PCI_VDEVICE(PROMISE, 0x3f20), board_ahci }, /* PDC42819 */ 546b32bfc06SRomain Degez { PCI_VDEVICE(PROMISE, 0x3781), board_ahci }, /* FastTrak TX8660 ahci-mode */ 547c77a036bSMark Nelson 548c9703765SKeng-Yu Lin /* Asmedia */ 5497b4f6ecaSAlan Cox { PCI_VDEVICE(ASMEDIA, 0x0601), board_ahci }, /* ASM1060 */ 5507b4f6ecaSAlan Cox { PCI_VDEVICE(ASMEDIA, 0x0602), board_ahci }, /* ASM1060 */ 5517b4f6ecaSAlan Cox { PCI_VDEVICE(ASMEDIA, 0x0611), board_ahci }, /* ASM1061 */ 5527b4f6ecaSAlan Cox { PCI_VDEVICE(ASMEDIA, 0x0612), board_ahci }, /* ASM1062 */ 5530ce968f3SShawn Lin { PCI_VDEVICE(ASMEDIA, 0x0621), board_ahci }, /* ASM1061R */ 5540ce968f3SShawn Lin { PCI_VDEVICE(ASMEDIA, 0x0622), board_ahci }, /* ASM1062R */ 555c9703765SKeng-Yu Lin 55667809f85SLevente Kurusa /* 55766a7cbc3STejun Heo * Samsung SSDs found on some macbooks. NCQ times out if MSI is 55866a7cbc3STejun Heo * enabled. https://bugzilla.kernel.org/show_bug.cgi?id=60731 55967809f85SLevente Kurusa */ 56066a7cbc3STejun Heo { PCI_VDEVICE(SAMSUNG, 0x1600), board_ahci_nomsi }, 5612b21ef0aSTejun Heo { PCI_VDEVICE(SAMSUNG, 0xa800), board_ahci_nomsi }, 56267809f85SLevente Kurusa 5637f9c9f8eSHugh Daschbach /* Enmotus */ 5647f9c9f8eSHugh Daschbach { PCI_DEVICE(0x1c44, 0x8000), board_ahci }, 5657f9c9f8eSHugh Daschbach 566415ae2b5SJeff Garzik /* Generic, PCI class code for AHCI */ 567415ae2b5SJeff Garzik { PCI_ANY_ID, PCI_ANY_ID, PCI_ANY_ID, PCI_ANY_ID, 568c9f89475SConke Hu PCI_CLASS_STORAGE_SATA_AHCI, 0xffffff, board_ahci }, 569415ae2b5SJeff Garzik 570c6fd2807SJeff Garzik { } /* terminate list */ 571c6fd2807SJeff Garzik }; 572c6fd2807SJeff Garzik 573f1d848f9SMika Westerberg static const struct dev_pm_ops ahci_pci_pm_ops = { 574f1d848f9SMika Westerberg SET_SYSTEM_SLEEP_PM_OPS(ahci_pci_device_suspend, ahci_pci_device_resume) 57502e53293SMika Westerberg SET_RUNTIME_PM_OPS(ahci_pci_device_runtime_suspend, 57602e53293SMika Westerberg ahci_pci_device_runtime_resume, NULL) 577f1d848f9SMika Westerberg }; 578c6fd2807SJeff Garzik 579c6fd2807SJeff Garzik static struct pci_driver ahci_pci_driver = { 580c6fd2807SJeff Garzik .name = DRV_NAME, 581c6fd2807SJeff Garzik .id_table = ahci_pci_tbl, 582c6fd2807SJeff Garzik .probe = ahci_init_one, 58302e53293SMika Westerberg .remove = ahci_remove_one, 584f1d848f9SMika Westerberg .driver = { 585f1d848f9SMika Westerberg .pm = &ahci_pci_pm_ops, 586f1d848f9SMika Westerberg }, 587c6fd2807SJeff Garzik }; 588c6fd2807SJeff Garzik 5895219d653SJavier Martinez Canillas #if IS_ENABLED(CONFIG_PATA_MARVELL) 5905b66c829SAlan Cox static int marvell_enable; 5915b66c829SAlan Cox #else 5925b66c829SAlan Cox static int marvell_enable = 1; 5935b66c829SAlan Cox #endif 5945b66c829SAlan Cox module_param(marvell_enable, int, 0644); 5955b66c829SAlan Cox MODULE_PARM_DESC(marvell_enable, "Marvell SATA via AHCI (1 = enabled)"); 5965b66c829SAlan Cox 597b1a9585cSSrinivas Pandruvada static int mobile_lpm_policy = -1; 598ebb82e3cSHans de Goede module_param(mobile_lpm_policy, int, 0644); 599ebb82e3cSHans de Goede MODULE_PARM_DESC(mobile_lpm_policy, "Default LPM policy for mobile chipsets"); 6005b66c829SAlan Cox 601394d6e53SAnton Vorontsov static void ahci_pci_save_initial_config(struct pci_dev *pdev, 602394d6e53SAnton Vorontsov struct ahci_host_priv *hpriv) 603394d6e53SAnton Vorontsov { 604394d6e53SAnton Vorontsov if (pdev->vendor == PCI_VENDOR_ID_JMICRON && pdev->device == 0x2361) { 605394d6e53SAnton Vorontsov dev_info(&pdev->dev, "JMB361 has only one port\n"); 6069a23c1d6SAntoine Tenart hpriv->force_port_map = 1; 607394d6e53SAnton Vorontsov } 608394d6e53SAnton Vorontsov 609394d6e53SAnton Vorontsov /* 610394d6e53SAnton Vorontsov * Temporary Marvell 6145 hack: PATA port presence 611394d6e53SAnton Vorontsov * is asserted through the standard AHCI port 612394d6e53SAnton Vorontsov * presence register, as bit 4 (counting from 0) 613394d6e53SAnton Vorontsov */ 614394d6e53SAnton Vorontsov if (hpriv->flags & AHCI_HFLAG_MV_PATA) { 615394d6e53SAnton Vorontsov if (pdev->device == 0x6121) 6169a23c1d6SAntoine Tenart hpriv->mask_port_map = 0x3; 617394d6e53SAnton Vorontsov else 6189a23c1d6SAntoine Tenart hpriv->mask_port_map = 0xf; 619394d6e53SAnton Vorontsov dev_info(&pdev->dev, 620394d6e53SAnton Vorontsov "Disabling your PATA port. Use the boot option 'ahci.marvell_enable=0' to avoid this.\n"); 621394d6e53SAnton Vorontsov } 622394d6e53SAnton Vorontsov 623725c7b57SAntoine Ténart ahci_save_initial_config(&pdev->dev, hpriv); 624394d6e53SAnton Vorontsov } 625394d6e53SAnton Vorontsov 6263303040dSAnton Vorontsov static int ahci_pci_reset_controller(struct ata_host *host) 6273303040dSAnton Vorontsov { 6283303040dSAnton Vorontsov struct pci_dev *pdev = to_pci_dev(host->dev); 629d312fefeSArd Biesheuvel int rc; 6303303040dSAnton Vorontsov 631d312fefeSArd Biesheuvel rc = ahci_reset_controller(host); 632d312fefeSArd Biesheuvel if (rc) 633d312fefeSArd Biesheuvel return rc; 6343303040dSAnton Vorontsov 635c6fd2807SJeff Garzik if (pdev->vendor == PCI_VENDOR_ID_INTEL) { 6363303040dSAnton Vorontsov struct ahci_host_priv *hpriv = host->private_data; 637c6fd2807SJeff Garzik u16 tmp16; 638c6fd2807SJeff Garzik 639c6fd2807SJeff Garzik /* configure PCS */ 640c6fd2807SJeff Garzik pci_read_config_word(pdev, 0x92, &tmp16); 64149f29090STejun Heo if ((tmp16 & hpriv->port_map) != hpriv->port_map) { 64249f29090STejun Heo tmp16 |= hpriv->port_map; 643c6fd2807SJeff Garzik pci_write_config_word(pdev, 0x92, tmp16); 644c6fd2807SJeff Garzik } 64549f29090STejun Heo } 646c6fd2807SJeff Garzik 647c6fd2807SJeff Garzik return 0; 648c6fd2807SJeff Garzik } 649c6fd2807SJeff Garzik 650781d6550SAnton Vorontsov static void ahci_pci_init_controller(struct ata_host *host) 651781d6550SAnton Vorontsov { 652781d6550SAnton Vorontsov struct ahci_host_priv *hpriv = host->private_data; 653781d6550SAnton Vorontsov struct pci_dev *pdev = to_pci_dev(host->dev); 654781d6550SAnton Vorontsov void __iomem *port_mmio; 655781d6550SAnton Vorontsov u32 tmp; 656c40e7cb8SJose Alberto Reguero int mv; 6572bcd866bSJeff Garzik 658417a1a6dSTejun Heo if (hpriv->flags & AHCI_HFLAG_MV_PATA) { 659c40e7cb8SJose Alberto Reguero if (pdev->device == 0x6121) 660c40e7cb8SJose Alberto Reguero mv = 2; 661c40e7cb8SJose Alberto Reguero else 662c40e7cb8SJose Alberto Reguero mv = 4; 663c40e7cb8SJose Alberto Reguero port_mmio = __ahci_port_base(host, mv); 664cd70c266SJeff Garzik 665cd70c266SJeff Garzik writel(0, port_mmio + PORT_IRQ_MASK); 666cd70c266SJeff Garzik 667cd70c266SJeff Garzik /* clear port IRQ */ 668cd70c266SJeff Garzik tmp = readl(port_mmio + PORT_IRQ_STAT); 669cd70c266SJeff Garzik VPRINTK("PORT_IRQ_STAT 0x%x\n", tmp); 670cd70c266SJeff Garzik if (tmp) 671cd70c266SJeff Garzik writel(tmp, port_mmio + PORT_IRQ_STAT); 672cd70c266SJeff Garzik } 673cd70c266SJeff Garzik 674781d6550SAnton Vorontsov ahci_init_controller(host); 675c6fd2807SJeff Garzik } 676c6fd2807SJeff Garzik 677cc0680a5STejun Heo static int ahci_vt8251_hardreset(struct ata_link *link, unsigned int *class, 678d4b2bab4STejun Heo unsigned long deadline) 679ad616ffbSTejun Heo { 680cc0680a5STejun Heo struct ata_port *ap = link->ap; 681039ece38SHans de Goede struct ahci_host_priv *hpriv = ap->host->private_data; 6829dadd45bSTejun Heo bool online; 683ad616ffbSTejun Heo int rc; 684ad616ffbSTejun Heo 685ad616ffbSTejun Heo DPRINTK("ENTER\n"); 686ad616ffbSTejun Heo 687fa89f53bSEvan Wang hpriv->stop_engine(ap); 688ad616ffbSTejun Heo 689cc0680a5STejun Heo rc = sata_link_hardreset(link, sata_ehc_deb_timing(&link->eh_context), 6909dadd45bSTejun Heo deadline, &online, NULL); 691ad616ffbSTejun Heo 692039ece38SHans de Goede hpriv->start_engine(ap); 693ad616ffbSTejun Heo 694ad616ffbSTejun Heo DPRINTK("EXIT, rc=%d, class=%u\n", rc, *class); 695ad616ffbSTejun Heo 696ad616ffbSTejun Heo /* vt8251 doesn't clear BSY on signature FIS reception, 697ad616ffbSTejun Heo * request follow-up softreset. 698ad616ffbSTejun Heo */ 6999dadd45bSTejun Heo return online ? -EAGAIN : rc; 700ad616ffbSTejun Heo } 701ad616ffbSTejun Heo 702edc93052STejun Heo static int ahci_p5wdh_hardreset(struct ata_link *link, unsigned int *class, 703edc93052STejun Heo unsigned long deadline) 704edc93052STejun Heo { 705edc93052STejun Heo struct ata_port *ap = link->ap; 706edc93052STejun Heo struct ahci_port_priv *pp = ap->private_data; 707039ece38SHans de Goede struct ahci_host_priv *hpriv = ap->host->private_data; 708edc93052STejun Heo u8 *d2h_fis = pp->rx_fis + RX_FIS_D2H_REG; 709edc93052STejun Heo struct ata_taskfile tf; 7109dadd45bSTejun Heo bool online; 711edc93052STejun Heo int rc; 712edc93052STejun Heo 713fa89f53bSEvan Wang hpriv->stop_engine(ap); 714edc93052STejun Heo 715edc93052STejun Heo /* clear D2H reception area to properly wait for D2H FIS */ 716edc93052STejun Heo ata_tf_init(link->device, &tf); 7179bbb1b0eSSergei Shtylyov tf.command = ATA_BUSY; 718edc93052STejun Heo ata_tf_to_fis(&tf, 0, 0, d2h_fis); 719edc93052STejun Heo 720edc93052STejun Heo rc = sata_link_hardreset(link, sata_ehc_deb_timing(&link->eh_context), 7219dadd45bSTejun Heo deadline, &online, NULL); 722edc93052STejun Heo 723039ece38SHans de Goede hpriv->start_engine(ap); 724edc93052STejun Heo 725edc93052STejun Heo /* The pseudo configuration device on SIMG4726 attached to 726edc93052STejun Heo * ASUS P5W-DH Deluxe doesn't send signature FIS after 727edc93052STejun Heo * hardreset if no device is attached to the first downstream 728edc93052STejun Heo * port && the pseudo device locks up on SRST w/ PMP==0. To 729edc93052STejun Heo * work around this, wait for !BSY only briefly. If BSY isn't 730edc93052STejun Heo * cleared, perform CLO and proceed to IDENTIFY (achieved by 731edc93052STejun Heo * ATA_LFLAG_NO_SRST and ATA_LFLAG_ASSUME_ATA). 732edc93052STejun Heo * 733edc93052STejun Heo * Wait for two seconds. Devices attached to downstream port 734edc93052STejun Heo * which can't process the following IDENTIFY after this will 735edc93052STejun Heo * have to be reset again. For most cases, this should 736edc93052STejun Heo * suffice while making probing snappish enough. 737edc93052STejun Heo */ 7389dadd45bSTejun Heo if (online) { 7399dadd45bSTejun Heo rc = ata_wait_after_reset(link, jiffies + 2 * HZ, 7409dadd45bSTejun Heo ahci_check_ready); 741edc93052STejun Heo if (rc) 74278d5ae39SShane Huang ahci_kick_engine(ap); 7439dadd45bSTejun Heo } 7449dadd45bSTejun Heo return rc; 745edc93052STejun Heo } 746edc93052STejun Heo 747dbfe8ef5SDan Williams /* 748dbfe8ef5SDan Williams * ahci_avn_hardreset - attempt more aggressive recovery of Avoton ports. 749dbfe8ef5SDan Williams * 750dbfe8ef5SDan Williams * It has been observed with some SSDs that the timing of events in the 751dbfe8ef5SDan Williams * link synchronization phase can leave the port in a state that can not 752dbfe8ef5SDan Williams * be recovered by a SATA-hard-reset alone. The failing signature is 753dbfe8ef5SDan Williams * SStatus.DET stuck at 1 ("Device presence detected but Phy 754dbfe8ef5SDan Williams * communication not established"). It was found that unloading and 755dbfe8ef5SDan Williams * reloading the driver when this problem occurs allows the drive 756dbfe8ef5SDan Williams * connection to be recovered (DET advanced to 0x3). The critical 757dbfe8ef5SDan Williams * component of reloading the driver is that the port state machines are 758dbfe8ef5SDan Williams * reset by bouncing "port enable" in the AHCI PCS configuration 759dbfe8ef5SDan Williams * register. So, reproduce that effect by bouncing a port whenever we 760dbfe8ef5SDan Williams * see DET==1 after a reset. 761dbfe8ef5SDan Williams */ 762dbfe8ef5SDan Williams static int ahci_avn_hardreset(struct ata_link *link, unsigned int *class, 763dbfe8ef5SDan Williams unsigned long deadline) 764dbfe8ef5SDan Williams { 765dbfe8ef5SDan Williams const unsigned long *timing = sata_ehc_deb_timing(&link->eh_context); 766dbfe8ef5SDan Williams struct ata_port *ap = link->ap; 767dbfe8ef5SDan Williams struct ahci_port_priv *pp = ap->private_data; 768dbfe8ef5SDan Williams struct ahci_host_priv *hpriv = ap->host->private_data; 769dbfe8ef5SDan Williams u8 *d2h_fis = pp->rx_fis + RX_FIS_D2H_REG; 770dbfe8ef5SDan Williams unsigned long tmo = deadline - jiffies; 771dbfe8ef5SDan Williams struct ata_taskfile tf; 772dbfe8ef5SDan Williams bool online; 773dbfe8ef5SDan Williams int rc, i; 774dbfe8ef5SDan Williams 775dbfe8ef5SDan Williams DPRINTK("ENTER\n"); 776dbfe8ef5SDan Williams 777fa89f53bSEvan Wang hpriv->stop_engine(ap); 778dbfe8ef5SDan Williams 779dbfe8ef5SDan Williams for (i = 0; i < 2; i++) { 780dbfe8ef5SDan Williams u16 val; 781dbfe8ef5SDan Williams u32 sstatus; 782dbfe8ef5SDan Williams int port = ap->port_no; 783dbfe8ef5SDan Williams struct ata_host *host = ap->host; 784dbfe8ef5SDan Williams struct pci_dev *pdev = to_pci_dev(host->dev); 785dbfe8ef5SDan Williams 786dbfe8ef5SDan Williams /* clear D2H reception area to properly wait for D2H FIS */ 787dbfe8ef5SDan Williams ata_tf_init(link->device, &tf); 788dbfe8ef5SDan Williams tf.command = ATA_BUSY; 789dbfe8ef5SDan Williams ata_tf_to_fis(&tf, 0, 0, d2h_fis); 790dbfe8ef5SDan Williams 791dbfe8ef5SDan Williams rc = sata_link_hardreset(link, timing, deadline, &online, 792dbfe8ef5SDan Williams ahci_check_ready); 793dbfe8ef5SDan Williams 794dbfe8ef5SDan Williams if (sata_scr_read(link, SCR_STATUS, &sstatus) != 0 || 795dbfe8ef5SDan Williams (sstatus & 0xf) != 1) 796dbfe8ef5SDan Williams break; 797dbfe8ef5SDan Williams 798dbfe8ef5SDan Williams ata_link_printk(link, KERN_INFO, "avn bounce port%d\n", 799dbfe8ef5SDan Williams port); 800dbfe8ef5SDan Williams 801dbfe8ef5SDan Williams pci_read_config_word(pdev, 0x92, &val); 802dbfe8ef5SDan Williams val &= ~(1 << port); 803dbfe8ef5SDan Williams pci_write_config_word(pdev, 0x92, val); 804dbfe8ef5SDan Williams ata_msleep(ap, 1000); 805dbfe8ef5SDan Williams val |= 1 << port; 806dbfe8ef5SDan Williams pci_write_config_word(pdev, 0x92, val); 807dbfe8ef5SDan Williams deadline += tmo; 808dbfe8ef5SDan Williams } 809dbfe8ef5SDan Williams 810dbfe8ef5SDan Williams hpriv->start_engine(ap); 811dbfe8ef5SDan Williams 812dbfe8ef5SDan Williams if (online) 813dbfe8ef5SDan Williams *class = ahci_dev_classify(ap); 814dbfe8ef5SDan Williams 815dbfe8ef5SDan Williams DPRINTK("EXIT, rc=%d, class=%u\n", rc, *class); 816dbfe8ef5SDan Williams return rc; 817dbfe8ef5SDan Williams } 818dbfe8ef5SDan Williams 819dbfe8ef5SDan Williams 82002e53293SMika Westerberg #ifdef CONFIG_PM 82102e53293SMika Westerberg static void ahci_pci_disable_interrupts(struct ata_host *host) 822c6fd2807SJeff Garzik { 8239b10ae86STejun Heo struct ahci_host_priv *hpriv = host->private_data; 824d8993349SAnton Vorontsov void __iomem *mmio = hpriv->mmio; 825c6fd2807SJeff Garzik u32 ctl; 826c6fd2807SJeff Garzik 827c6fd2807SJeff Garzik /* AHCI spec rev1.1 section 8.3.3: 828c6fd2807SJeff Garzik * Software must disable interrupts prior to requesting a 829c6fd2807SJeff Garzik * transition of the HBA to D3 state. 830c6fd2807SJeff Garzik */ 831c6fd2807SJeff Garzik ctl = readl(mmio + HOST_CTL); 832c6fd2807SJeff Garzik ctl &= ~HOST_IRQ_EN; 833c6fd2807SJeff Garzik writel(ctl, mmio + HOST_CTL); 834c6fd2807SJeff Garzik readl(mmio + HOST_CTL); /* flush */ 83502e53293SMika Westerberg } 836f1d848f9SMika Westerberg 83702e53293SMika Westerberg static int ahci_pci_device_runtime_suspend(struct device *dev) 83802e53293SMika Westerberg { 83902e53293SMika Westerberg struct pci_dev *pdev = to_pci_dev(dev); 84002e53293SMika Westerberg struct ata_host *host = pci_get_drvdata(pdev); 84102e53293SMika Westerberg 84202e53293SMika Westerberg ahci_pci_disable_interrupts(host); 84302e53293SMika Westerberg return 0; 84402e53293SMika Westerberg } 84502e53293SMika Westerberg 84602e53293SMika Westerberg static int ahci_pci_device_runtime_resume(struct device *dev) 84702e53293SMika Westerberg { 84802e53293SMika Westerberg struct pci_dev *pdev = to_pci_dev(dev); 84902e53293SMika Westerberg struct ata_host *host = pci_get_drvdata(pdev); 85002e53293SMika Westerberg int rc; 85102e53293SMika Westerberg 85202e53293SMika Westerberg rc = ahci_pci_reset_controller(host); 85302e53293SMika Westerberg if (rc) 85402e53293SMika Westerberg return rc; 85502e53293SMika Westerberg ahci_pci_init_controller(host); 85602e53293SMika Westerberg return 0; 85702e53293SMika Westerberg } 85802e53293SMika Westerberg 85902e53293SMika Westerberg #ifdef CONFIG_PM_SLEEP 86002e53293SMika Westerberg static int ahci_pci_device_suspend(struct device *dev) 86102e53293SMika Westerberg { 86202e53293SMika Westerberg struct pci_dev *pdev = to_pci_dev(dev); 86302e53293SMika Westerberg struct ata_host *host = pci_get_drvdata(pdev); 86402e53293SMika Westerberg struct ahci_host_priv *hpriv = host->private_data; 86502e53293SMika Westerberg 86602e53293SMika Westerberg if (hpriv->flags & AHCI_HFLAG_NO_SUSPEND) { 86702e53293SMika Westerberg dev_err(&pdev->dev, 86802e53293SMika Westerberg "BIOS update required for suspend/resume\n"); 86902e53293SMika Westerberg return -EIO; 87002e53293SMika Westerberg } 87102e53293SMika Westerberg 87202e53293SMika Westerberg ahci_pci_disable_interrupts(host); 873f1d848f9SMika Westerberg return ata_host_suspend(host, PMSG_SUSPEND); 874c6fd2807SJeff Garzik } 875c6fd2807SJeff Garzik 876f1d848f9SMika Westerberg static int ahci_pci_device_resume(struct device *dev) 877c6fd2807SJeff Garzik { 878f1d848f9SMika Westerberg struct pci_dev *pdev = to_pci_dev(dev); 8790a86e1c8SJingoo Han struct ata_host *host = pci_get_drvdata(pdev); 880c6fd2807SJeff Garzik int rc; 881c6fd2807SJeff Garzik 882cb85696dSJames Laird /* Apple BIOS helpfully mangles the registers on resume */ 883cb85696dSJames Laird if (is_mcp89_apple(pdev)) 884cb85696dSJames Laird ahci_mcp89_apple_enable(pdev); 885cb85696dSJames Laird 886c6fd2807SJeff Garzik if (pdev->dev.power.power_state.event == PM_EVENT_SUSPEND) { 8873303040dSAnton Vorontsov rc = ahci_pci_reset_controller(host); 888c6fd2807SJeff Garzik if (rc) 889c6fd2807SJeff Garzik return rc; 890c6fd2807SJeff Garzik 891781d6550SAnton Vorontsov ahci_pci_init_controller(host); 892c6fd2807SJeff Garzik } 893c6fd2807SJeff Garzik 894cca3974eSJeff Garzik ata_host_resume(host); 895c6fd2807SJeff Garzik 896c6fd2807SJeff Garzik return 0; 897c6fd2807SJeff Garzik } 898438ac6d5STejun Heo #endif 899c6fd2807SJeff Garzik 90002e53293SMika Westerberg #endif /* CONFIG_PM */ 90102e53293SMika Westerberg 9024447d351STejun Heo static int ahci_configure_dma_masks(struct pci_dev *pdev, int using_dac) 903c6fd2807SJeff Garzik { 904c6fd2807SJeff Garzik int rc; 905c6fd2807SJeff Garzik 906318893e1SAlessandro Rubini /* 907318893e1SAlessandro Rubini * If the device fixup already set the dma_mask to some non-standard 908318893e1SAlessandro Rubini * value, don't extend it here. This happens on STA2X11, for example. 909318893e1SAlessandro Rubini */ 910318893e1SAlessandro Rubini if (pdev->dma_mask && pdev->dma_mask < DMA_BIT_MASK(32)) 911318893e1SAlessandro Rubini return 0; 912318893e1SAlessandro Rubini 913c6fd2807SJeff Garzik if (using_dac && 914c54c719bSQuentin Lambert !dma_set_mask(&pdev->dev, DMA_BIT_MASK(64))) { 915c54c719bSQuentin Lambert rc = dma_set_coherent_mask(&pdev->dev, DMA_BIT_MASK(64)); 916c6fd2807SJeff Garzik if (rc) { 917c54c719bSQuentin Lambert rc = dma_set_coherent_mask(&pdev->dev, DMA_BIT_MASK(32)); 918c6fd2807SJeff Garzik if (rc) { 919a44fec1fSJoe Perches dev_err(&pdev->dev, 920c6fd2807SJeff Garzik "64-bit DMA enable failed\n"); 921c6fd2807SJeff Garzik return rc; 922c6fd2807SJeff Garzik } 923c6fd2807SJeff Garzik } 924c6fd2807SJeff Garzik } else { 925c54c719bSQuentin Lambert rc = dma_set_mask(&pdev->dev, DMA_BIT_MASK(32)); 926c6fd2807SJeff Garzik if (rc) { 927a44fec1fSJoe Perches dev_err(&pdev->dev, "32-bit DMA enable failed\n"); 928c6fd2807SJeff Garzik return rc; 929c6fd2807SJeff Garzik } 930c54c719bSQuentin Lambert rc = dma_set_coherent_mask(&pdev->dev, DMA_BIT_MASK(32)); 931c6fd2807SJeff Garzik if (rc) { 932a44fec1fSJoe Perches dev_err(&pdev->dev, 933c6fd2807SJeff Garzik "32-bit consistent DMA enable failed\n"); 934c6fd2807SJeff Garzik return rc; 935c6fd2807SJeff Garzik } 936c6fd2807SJeff Garzik } 937c6fd2807SJeff Garzik return 0; 938c6fd2807SJeff Garzik } 939c6fd2807SJeff Garzik 940439fcaecSAnton Vorontsov static void ahci_pci_print_info(struct ata_host *host) 941439fcaecSAnton Vorontsov { 942439fcaecSAnton Vorontsov struct pci_dev *pdev = to_pci_dev(host->dev); 943439fcaecSAnton Vorontsov u16 cc; 944439fcaecSAnton Vorontsov const char *scc_s; 945439fcaecSAnton Vorontsov 946439fcaecSAnton Vorontsov pci_read_config_word(pdev, 0x0a, &cc); 947439fcaecSAnton Vorontsov if (cc == PCI_CLASS_STORAGE_IDE) 948439fcaecSAnton Vorontsov scc_s = "IDE"; 949439fcaecSAnton Vorontsov else if (cc == PCI_CLASS_STORAGE_SATA) 950439fcaecSAnton Vorontsov scc_s = "SATA"; 951439fcaecSAnton Vorontsov else if (cc == PCI_CLASS_STORAGE_RAID) 952439fcaecSAnton Vorontsov scc_s = "RAID"; 953439fcaecSAnton Vorontsov else 954439fcaecSAnton Vorontsov scc_s = "unknown"; 955439fcaecSAnton Vorontsov 956439fcaecSAnton Vorontsov ahci_print_info(host, scc_s); 957439fcaecSAnton Vorontsov } 958439fcaecSAnton Vorontsov 959edc93052STejun Heo /* On ASUS P5W DH Deluxe, the second port of PCI device 00:1f.2 is 960edc93052STejun Heo * hardwired to on-board SIMG 4726. The chipset is ICH8 and doesn't 961edc93052STejun Heo * support PMP and the 4726 either directly exports the device 962edc93052STejun Heo * attached to the first downstream port or acts as a hardware storage 963edc93052STejun Heo * controller and emulate a single ATA device (can be RAID 0/1 or some 964edc93052STejun Heo * other configuration). 965edc93052STejun Heo * 966edc93052STejun Heo * When there's no device attached to the first downstream port of the 967edc93052STejun Heo * 4726, "Config Disk" appears, which is a pseudo ATA device to 968edc93052STejun Heo * configure the 4726. However, ATA emulation of the device is very 969edc93052STejun Heo * lame. It doesn't send signature D2H Reg FIS after the initial 970edc93052STejun Heo * hardreset, pukes on SRST w/ PMP==0 and has bunch of other issues. 971edc93052STejun Heo * 972edc93052STejun Heo * The following function works around the problem by always using 973edc93052STejun Heo * hardreset on the port and not depending on receiving signature FIS 974edc93052STejun Heo * afterward. If signature FIS isn't received soon, ATA class is 975edc93052STejun Heo * assumed without follow-up softreset. 976edc93052STejun Heo */ 977edc93052STejun Heo static void ahci_p5wdh_workaround(struct ata_host *host) 978edc93052STejun Heo { 9791bd06867SMathias Krause static const struct dmi_system_id sysids[] = { 980edc93052STejun Heo { 981edc93052STejun Heo .ident = "P5W DH Deluxe", 982edc93052STejun Heo .matches = { 983edc93052STejun Heo DMI_MATCH(DMI_SYS_VENDOR, 984edc93052STejun Heo "ASUSTEK COMPUTER INC"), 985edc93052STejun Heo DMI_MATCH(DMI_PRODUCT_NAME, "P5W DH Deluxe"), 986edc93052STejun Heo }, 987edc93052STejun Heo }, 988edc93052STejun Heo { } 989edc93052STejun Heo }; 990edc93052STejun Heo struct pci_dev *pdev = to_pci_dev(host->dev); 991edc93052STejun Heo 992edc93052STejun Heo if (pdev->bus->number == 0 && pdev->devfn == PCI_DEVFN(0x1f, 2) && 993edc93052STejun Heo dmi_check_system(sysids)) { 994edc93052STejun Heo struct ata_port *ap = host->ports[1]; 995edc93052STejun Heo 996a44fec1fSJoe Perches dev_info(&pdev->dev, 997a44fec1fSJoe Perches "enabling ASUS P5W DH Deluxe on-board SIMG4726 workaround\n"); 998edc93052STejun Heo 999edc93052STejun Heo ap->ops = &ahci_p5wdh_ops; 1000edc93052STejun Heo ap->link.flags |= ATA_LFLAG_NO_SRST | ATA_LFLAG_ASSUME_ATA; 1001edc93052STejun Heo } 1002edc93052STejun Heo } 1003edc93052STejun Heo 1004cb85696dSJames Laird /* 1005cb85696dSJames Laird * Macbook7,1 firmware forcibly disables MCP89 AHCI and changes PCI ID when 1006cb85696dSJames Laird * booting in BIOS compatibility mode. We restore the registers but not ID. 1007cb85696dSJames Laird */ 1008cb85696dSJames Laird static void ahci_mcp89_apple_enable(struct pci_dev *pdev) 1009cb85696dSJames Laird { 1010cb85696dSJames Laird u32 val; 1011cb85696dSJames Laird 1012cb85696dSJames Laird printk(KERN_INFO "ahci: enabling MCP89 AHCI mode\n"); 1013cb85696dSJames Laird 1014cb85696dSJames Laird pci_read_config_dword(pdev, 0xf8, &val); 1015cb85696dSJames Laird val |= 1 << 0x1b; 1016cb85696dSJames Laird /* the following changes the device ID, but appears not to affect function */ 1017cb85696dSJames Laird /* val = (val & ~0xf0000000) | 0x80000000; */ 1018cb85696dSJames Laird pci_write_config_dword(pdev, 0xf8, val); 1019cb85696dSJames Laird 1020cb85696dSJames Laird pci_read_config_dword(pdev, 0x54c, &val); 1021cb85696dSJames Laird val |= 1 << 0xc; 1022cb85696dSJames Laird pci_write_config_dword(pdev, 0x54c, val); 1023cb85696dSJames Laird 1024cb85696dSJames Laird pci_read_config_dword(pdev, 0x4a4, &val); 1025cb85696dSJames Laird val &= 0xff; 1026cb85696dSJames Laird val |= 0x01060100; 1027cb85696dSJames Laird pci_write_config_dword(pdev, 0x4a4, val); 1028cb85696dSJames Laird 1029cb85696dSJames Laird pci_read_config_dword(pdev, 0x54c, &val); 1030cb85696dSJames Laird val &= ~(1 << 0xc); 1031cb85696dSJames Laird pci_write_config_dword(pdev, 0x54c, val); 1032cb85696dSJames Laird 1033cb85696dSJames Laird pci_read_config_dword(pdev, 0xf8, &val); 1034cb85696dSJames Laird val &= ~(1 << 0x1b); 1035cb85696dSJames Laird pci_write_config_dword(pdev, 0xf8, val); 1036cb85696dSJames Laird } 1037cb85696dSJames Laird 1038cb85696dSJames Laird static bool is_mcp89_apple(struct pci_dev *pdev) 1039cb85696dSJames Laird { 1040cb85696dSJames Laird return pdev->vendor == PCI_VENDOR_ID_NVIDIA && 1041cb85696dSJames Laird pdev->device == PCI_DEVICE_ID_NVIDIA_NFORCE_MCP89_SATA && 1042cb85696dSJames Laird pdev->subsystem_vendor == PCI_VENDOR_ID_APPLE && 1043cb85696dSJames Laird pdev->subsystem_device == 0xcb89; 1044cb85696dSJames Laird } 1045cb85696dSJames Laird 10462fcad9d2STejun Heo /* only some SB600 ahci controllers can do 64bit DMA */ 10472fcad9d2STejun Heo static bool ahci_sb600_enable_64bit(struct pci_dev *pdev) 104858a09b38SShane Huang { 104958a09b38SShane Huang static const struct dmi_system_id sysids[] = { 105003d783bfSTejun Heo /* 105103d783bfSTejun Heo * The oldest version known to be broken is 0901 and 105203d783bfSTejun Heo * working is 1501 which was released on 2007-10-26. 10532fcad9d2STejun Heo * Enable 64bit DMA on 1501 and anything newer. 10542fcad9d2STejun Heo * 105503d783bfSTejun Heo * Please read bko#9412 for more info. 105603d783bfSTejun Heo */ 105758a09b38SShane Huang { 105858a09b38SShane Huang .ident = "ASUS M2A-VM", 105958a09b38SShane Huang .matches = { 106058a09b38SShane Huang DMI_MATCH(DMI_BOARD_VENDOR, 106158a09b38SShane Huang "ASUSTeK Computer INC."), 106258a09b38SShane Huang DMI_MATCH(DMI_BOARD_NAME, "M2A-VM"), 106358a09b38SShane Huang }, 106403d783bfSTejun Heo .driver_data = "20071026", /* yyyymmdd */ 106558a09b38SShane Huang }, 1066e65cc194SMark Nelson /* 1067e65cc194SMark Nelson * All BIOS versions for the MSI K9A2 Platinum (MS-7376) 1068e65cc194SMark Nelson * support 64bit DMA. 1069e65cc194SMark Nelson * 1070e65cc194SMark Nelson * BIOS versions earlier than 1.5 had the Manufacturer DMI 1071e65cc194SMark Nelson * fields as "MICRO-STAR INTERANTIONAL CO.,LTD". 1072e65cc194SMark Nelson * This spelling mistake was fixed in BIOS version 1.5, so 1073e65cc194SMark Nelson * 1.5 and later have the Manufacturer as 1074e65cc194SMark Nelson * "MICRO-STAR INTERNATIONAL CO.,LTD". 1075e65cc194SMark Nelson * So try to match on DMI_BOARD_VENDOR of "MICRO-STAR INTER". 1076e65cc194SMark Nelson * 1077e65cc194SMark Nelson * BIOS versions earlier than 1.9 had a Board Product Name 1078e65cc194SMark Nelson * DMI field of "MS-7376". This was changed to be 1079e65cc194SMark Nelson * "K9A2 Platinum (MS-7376)" in version 1.9, but we can still 1080e65cc194SMark Nelson * match on DMI_BOARD_NAME of "MS-7376". 1081e65cc194SMark Nelson */ 1082e65cc194SMark Nelson { 1083e65cc194SMark Nelson .ident = "MSI K9A2 Platinum", 1084e65cc194SMark Nelson .matches = { 1085e65cc194SMark Nelson DMI_MATCH(DMI_BOARD_VENDOR, 1086e65cc194SMark Nelson "MICRO-STAR INTER"), 1087e65cc194SMark Nelson DMI_MATCH(DMI_BOARD_NAME, "MS-7376"), 1088e65cc194SMark Nelson }, 1089e65cc194SMark Nelson }, 10903c4aa91fSMark Nelson /* 1091ff0173c1SMark Nelson * All BIOS versions for the MSI K9AGM2 (MS-7327) support 1092ff0173c1SMark Nelson * 64bit DMA. 1093ff0173c1SMark Nelson * 1094ff0173c1SMark Nelson * This board also had the typo mentioned above in the 1095ff0173c1SMark Nelson * Manufacturer DMI field (fixed in BIOS version 1.5), so 1096ff0173c1SMark Nelson * match on DMI_BOARD_VENDOR of "MICRO-STAR INTER" again. 1097ff0173c1SMark Nelson */ 1098ff0173c1SMark Nelson { 1099ff0173c1SMark Nelson .ident = "MSI K9AGM2", 1100ff0173c1SMark Nelson .matches = { 1101ff0173c1SMark Nelson DMI_MATCH(DMI_BOARD_VENDOR, 1102ff0173c1SMark Nelson "MICRO-STAR INTER"), 1103ff0173c1SMark Nelson DMI_MATCH(DMI_BOARD_NAME, "MS-7327"), 1104ff0173c1SMark Nelson }, 1105ff0173c1SMark Nelson }, 1106ff0173c1SMark Nelson /* 11073c4aa91fSMark Nelson * All BIOS versions for the Asus M3A support 64bit DMA. 11083c4aa91fSMark Nelson * (all release versions from 0301 to 1206 were tested) 11093c4aa91fSMark Nelson */ 11103c4aa91fSMark Nelson { 11113c4aa91fSMark Nelson .ident = "ASUS M3A", 11123c4aa91fSMark Nelson .matches = { 11133c4aa91fSMark Nelson DMI_MATCH(DMI_BOARD_VENDOR, 11143c4aa91fSMark Nelson "ASUSTeK Computer INC."), 11153c4aa91fSMark Nelson DMI_MATCH(DMI_BOARD_NAME, "M3A"), 11163c4aa91fSMark Nelson }, 11173c4aa91fSMark Nelson }, 111858a09b38SShane Huang { } 111958a09b38SShane Huang }; 112003d783bfSTejun Heo const struct dmi_system_id *match; 11212fcad9d2STejun Heo int year, month, date; 11222fcad9d2STejun Heo char buf[9]; 112358a09b38SShane Huang 112403d783bfSTejun Heo match = dmi_first_match(sysids); 112558a09b38SShane Huang if (pdev->bus->number != 0 || pdev->devfn != PCI_DEVFN(0x12, 0) || 112603d783bfSTejun Heo !match) 112758a09b38SShane Huang return false; 112858a09b38SShane Huang 1129e65cc194SMark Nelson if (!match->driver_data) 1130e65cc194SMark Nelson goto enable_64bit; 1131e65cc194SMark Nelson 113203d783bfSTejun Heo dmi_get_date(DMI_BIOS_DATE, &year, &month, &date); 113303d783bfSTejun Heo snprintf(buf, sizeof(buf), "%04d%02d%02d", year, month, date); 113403d783bfSTejun Heo 1135e65cc194SMark Nelson if (strcmp(buf, match->driver_data) >= 0) 1136e65cc194SMark Nelson goto enable_64bit; 1137e65cc194SMark Nelson else { 1138a44fec1fSJoe Perches dev_warn(&pdev->dev, 1139a44fec1fSJoe Perches "%s: BIOS too old, forcing 32bit DMA, update BIOS\n", 1140a44fec1fSJoe Perches match->ident); 11412fcad9d2STejun Heo return false; 11422fcad9d2STejun Heo } 1143e65cc194SMark Nelson 1144e65cc194SMark Nelson enable_64bit: 1145a44fec1fSJoe Perches dev_warn(&pdev->dev, "%s: enabling 64bit DMA\n", match->ident); 1146e65cc194SMark Nelson return true; 114758a09b38SShane Huang } 114858a09b38SShane Huang 11491fd68434SRafael J. Wysocki static bool ahci_broken_system_poweroff(struct pci_dev *pdev) 11501fd68434SRafael J. Wysocki { 11511fd68434SRafael J. Wysocki static const struct dmi_system_id broken_systems[] = { 11521fd68434SRafael J. Wysocki { 11531fd68434SRafael J. Wysocki .ident = "HP Compaq nx6310", 11541fd68434SRafael J. Wysocki .matches = { 11551fd68434SRafael J. Wysocki DMI_MATCH(DMI_SYS_VENDOR, "Hewlett-Packard"), 11561fd68434SRafael J. Wysocki DMI_MATCH(DMI_PRODUCT_NAME, "HP Compaq nx6310"), 11571fd68434SRafael J. Wysocki }, 11581fd68434SRafael J. Wysocki /* PCI slot number of the controller */ 11591fd68434SRafael J. Wysocki .driver_data = (void *)0x1FUL, 11601fd68434SRafael J. Wysocki }, 1161d2f9c061SMaciej Rutecki { 1162d2f9c061SMaciej Rutecki .ident = "HP Compaq 6720s", 1163d2f9c061SMaciej Rutecki .matches = { 1164d2f9c061SMaciej Rutecki DMI_MATCH(DMI_SYS_VENDOR, "Hewlett-Packard"), 1165d2f9c061SMaciej Rutecki DMI_MATCH(DMI_PRODUCT_NAME, "HP Compaq 6720s"), 1166d2f9c061SMaciej Rutecki }, 1167d2f9c061SMaciej Rutecki /* PCI slot number of the controller */ 1168d2f9c061SMaciej Rutecki .driver_data = (void *)0x1FUL, 1169d2f9c061SMaciej Rutecki }, 11701fd68434SRafael J. Wysocki 11711fd68434SRafael J. Wysocki { } /* terminate list */ 11721fd68434SRafael J. Wysocki }; 11731fd68434SRafael J. Wysocki const struct dmi_system_id *dmi = dmi_first_match(broken_systems); 11741fd68434SRafael J. Wysocki 11751fd68434SRafael J. Wysocki if (dmi) { 11761fd68434SRafael J. Wysocki unsigned long slot = (unsigned long)dmi->driver_data; 11771fd68434SRafael J. Wysocki /* apply the quirk only to on-board controllers */ 11781fd68434SRafael J. Wysocki return slot == PCI_SLOT(pdev->devfn); 11791fd68434SRafael J. Wysocki } 11801fd68434SRafael J. Wysocki 11811fd68434SRafael J. Wysocki return false; 11821fd68434SRafael J. Wysocki } 11831fd68434SRafael J. Wysocki 11849b10ae86STejun Heo static bool ahci_broken_suspend(struct pci_dev *pdev) 11859b10ae86STejun Heo { 11869b10ae86STejun Heo static const struct dmi_system_id sysids[] = { 11879b10ae86STejun Heo /* 11889b10ae86STejun Heo * On HP dv[4-6] and HDX18 with earlier BIOSen, link 11899b10ae86STejun Heo * to the harddisk doesn't become online after 11909b10ae86STejun Heo * resuming from STR. Warn and fail suspend. 11919deb3431STejun Heo * 11929deb3431STejun Heo * http://bugzilla.kernel.org/show_bug.cgi?id=12276 11939deb3431STejun Heo * 11949deb3431STejun Heo * Use dates instead of versions to match as HP is 11959deb3431STejun Heo * apparently recycling both product and version 11969deb3431STejun Heo * strings. 11979deb3431STejun Heo * 11989deb3431STejun Heo * http://bugzilla.kernel.org/show_bug.cgi?id=15462 11999b10ae86STejun Heo */ 12009b10ae86STejun Heo { 12019b10ae86STejun Heo .ident = "dv4", 12029b10ae86STejun Heo .matches = { 12039b10ae86STejun Heo DMI_MATCH(DMI_SYS_VENDOR, "Hewlett-Packard"), 12049b10ae86STejun Heo DMI_MATCH(DMI_PRODUCT_NAME, 12059b10ae86STejun Heo "HP Pavilion dv4 Notebook PC"), 12069b10ae86STejun Heo }, 12079deb3431STejun Heo .driver_data = "20090105", /* F.30 */ 12089b10ae86STejun Heo }, 12099b10ae86STejun Heo { 12109b10ae86STejun Heo .ident = "dv5", 12119b10ae86STejun Heo .matches = { 12129b10ae86STejun Heo DMI_MATCH(DMI_SYS_VENDOR, "Hewlett-Packard"), 12139b10ae86STejun Heo DMI_MATCH(DMI_PRODUCT_NAME, 12149b10ae86STejun Heo "HP Pavilion dv5 Notebook PC"), 12159b10ae86STejun Heo }, 12169deb3431STejun Heo .driver_data = "20090506", /* F.16 */ 12179b10ae86STejun Heo }, 12189b10ae86STejun Heo { 12199b10ae86STejun Heo .ident = "dv6", 12209b10ae86STejun Heo .matches = { 12219b10ae86STejun Heo DMI_MATCH(DMI_SYS_VENDOR, "Hewlett-Packard"), 12229b10ae86STejun Heo DMI_MATCH(DMI_PRODUCT_NAME, 12239b10ae86STejun Heo "HP Pavilion dv6 Notebook PC"), 12249b10ae86STejun Heo }, 12259deb3431STejun Heo .driver_data = "20090423", /* F.21 */ 12269b10ae86STejun Heo }, 12279b10ae86STejun Heo { 12289b10ae86STejun Heo .ident = "HDX18", 12299b10ae86STejun Heo .matches = { 12309b10ae86STejun Heo DMI_MATCH(DMI_SYS_VENDOR, "Hewlett-Packard"), 12319b10ae86STejun Heo DMI_MATCH(DMI_PRODUCT_NAME, 12329b10ae86STejun Heo "HP HDX18 Notebook PC"), 12339b10ae86STejun Heo }, 12349deb3431STejun Heo .driver_data = "20090430", /* F.23 */ 12359b10ae86STejun Heo }, 1236cedc9bf9STejun Heo /* 1237cedc9bf9STejun Heo * Acer eMachines G725 has the same problem. BIOS 1238cedc9bf9STejun Heo * V1.03 is known to be broken. V3.04 is known to 123925985edcSLucas De Marchi * work. Between, there are V1.06, V2.06 and V3.03 1240cedc9bf9STejun Heo * that we don't have much idea about. For now, 1241cedc9bf9STejun Heo * blacklist anything older than V3.04. 12429deb3431STejun Heo * 12439deb3431STejun Heo * http://bugzilla.kernel.org/show_bug.cgi?id=15104 1244cedc9bf9STejun Heo */ 1245cedc9bf9STejun Heo { 1246cedc9bf9STejun Heo .ident = "G725", 1247cedc9bf9STejun Heo .matches = { 1248cedc9bf9STejun Heo DMI_MATCH(DMI_SYS_VENDOR, "eMachines"), 1249cedc9bf9STejun Heo DMI_MATCH(DMI_PRODUCT_NAME, "eMachines G725"), 1250cedc9bf9STejun Heo }, 12519deb3431STejun Heo .driver_data = "20091216", /* V3.04 */ 1252cedc9bf9STejun Heo }, 12539b10ae86STejun Heo { } /* terminate list */ 12549b10ae86STejun Heo }; 12559b10ae86STejun Heo const struct dmi_system_id *dmi = dmi_first_match(sysids); 12569deb3431STejun Heo int year, month, date; 12579deb3431STejun Heo char buf[9]; 12589b10ae86STejun Heo 12599b10ae86STejun Heo if (!dmi || pdev->bus->number || pdev->devfn != PCI_DEVFN(0x1f, 2)) 12609b10ae86STejun Heo return false; 12619b10ae86STejun Heo 12629deb3431STejun Heo dmi_get_date(DMI_BIOS_DATE, &year, &month, &date); 12639deb3431STejun Heo snprintf(buf, sizeof(buf), "%04d%02d%02d", year, month, date); 12649b10ae86STejun Heo 12659deb3431STejun Heo return strcmp(buf, dmi->driver_data) < 0; 12669b10ae86STejun Heo } 12679b10ae86STejun Heo 1268240630e6SHans de Goede static bool ahci_broken_lpm(struct pci_dev *pdev) 1269240630e6SHans de Goede { 1270240630e6SHans de Goede static const struct dmi_system_id sysids[] = { 1271240630e6SHans de Goede /* Various Lenovo 50 series have LPM issues with older BIOSen */ 1272240630e6SHans de Goede { 1273240630e6SHans de Goede .matches = { 1274240630e6SHans de Goede DMI_MATCH(DMI_SYS_VENDOR, "LENOVO"), 1275240630e6SHans de Goede DMI_MATCH(DMI_PRODUCT_VERSION, "ThinkPad X250"), 1276240630e6SHans de Goede }, 1277240630e6SHans de Goede .driver_data = "20180406", /* 1.31 */ 1278240630e6SHans de Goede }, 1279240630e6SHans de Goede { 1280240630e6SHans de Goede .matches = { 1281240630e6SHans de Goede DMI_MATCH(DMI_SYS_VENDOR, "LENOVO"), 1282240630e6SHans de Goede DMI_MATCH(DMI_PRODUCT_VERSION, "ThinkPad L450"), 1283240630e6SHans de Goede }, 1284240630e6SHans de Goede .driver_data = "20180420", /* 1.28 */ 1285240630e6SHans de Goede }, 1286240630e6SHans de Goede { 1287240630e6SHans de Goede .matches = { 1288240630e6SHans de Goede DMI_MATCH(DMI_SYS_VENDOR, "LENOVO"), 1289240630e6SHans de Goede DMI_MATCH(DMI_PRODUCT_VERSION, "ThinkPad T450s"), 1290240630e6SHans de Goede }, 1291240630e6SHans de Goede .driver_data = "20180315", /* 1.33 */ 1292240630e6SHans de Goede }, 1293240630e6SHans de Goede { 1294240630e6SHans de Goede .matches = { 1295240630e6SHans de Goede DMI_MATCH(DMI_SYS_VENDOR, "LENOVO"), 1296240630e6SHans de Goede DMI_MATCH(DMI_PRODUCT_VERSION, "ThinkPad W541"), 1297240630e6SHans de Goede }, 1298240630e6SHans de Goede /* 1299240630e6SHans de Goede * Note date based on release notes, 2.35 has been 1300240630e6SHans de Goede * reported to be good, but I've been unable to get 1301240630e6SHans de Goede * a hold of the reporter to get the DMI BIOS date. 1302240630e6SHans de Goede * TODO: fix this. 1303240630e6SHans de Goede */ 1304240630e6SHans de Goede .driver_data = "20180310", /* 2.35 */ 1305240630e6SHans de Goede }, 1306240630e6SHans de Goede { } /* terminate list */ 1307240630e6SHans de Goede }; 1308240630e6SHans de Goede const struct dmi_system_id *dmi = dmi_first_match(sysids); 1309240630e6SHans de Goede int year, month, date; 1310240630e6SHans de Goede char buf[9]; 1311240630e6SHans de Goede 1312240630e6SHans de Goede if (!dmi) 1313240630e6SHans de Goede return false; 1314240630e6SHans de Goede 1315240630e6SHans de Goede dmi_get_date(DMI_BIOS_DATE, &year, &month, &date); 1316240630e6SHans de Goede snprintf(buf, sizeof(buf), "%04d%02d%02d", year, month, date); 1317240630e6SHans de Goede 1318240630e6SHans de Goede return strcmp(buf, dmi->driver_data) < 0; 1319240630e6SHans de Goede } 1320240630e6SHans de Goede 13215594639aSTejun Heo static bool ahci_broken_online(struct pci_dev *pdev) 13225594639aSTejun Heo { 13235594639aSTejun Heo #define ENCODE_BUSDEVFN(bus, slot, func) \ 13245594639aSTejun Heo (void *)(unsigned long)(((bus) << 8) | PCI_DEVFN((slot), (func))) 13255594639aSTejun Heo static const struct dmi_system_id sysids[] = { 13265594639aSTejun Heo /* 13275594639aSTejun Heo * There are several gigabyte boards which use 13285594639aSTejun Heo * SIMG5723s configured as hardware RAID. Certain 13295594639aSTejun Heo * 5723 firmware revisions shipped there keep the link 13305594639aSTejun Heo * online but fail to answer properly to SRST or 13315594639aSTejun Heo * IDENTIFY when no device is attached downstream 13325594639aSTejun Heo * causing libata to retry quite a few times leading 13335594639aSTejun Heo * to excessive detection delay. 13345594639aSTejun Heo * 13355594639aSTejun Heo * As these firmwares respond to the second reset try 13365594639aSTejun Heo * with invalid device signature, considering unknown 13375594639aSTejun Heo * sig as offline works around the problem acceptably. 13385594639aSTejun Heo */ 13395594639aSTejun Heo { 13405594639aSTejun Heo .ident = "EP45-DQ6", 13415594639aSTejun Heo .matches = { 13425594639aSTejun Heo DMI_MATCH(DMI_BOARD_VENDOR, 13435594639aSTejun Heo "Gigabyte Technology Co., Ltd."), 13445594639aSTejun Heo DMI_MATCH(DMI_BOARD_NAME, "EP45-DQ6"), 13455594639aSTejun Heo }, 13465594639aSTejun Heo .driver_data = ENCODE_BUSDEVFN(0x0a, 0x00, 0), 13475594639aSTejun Heo }, 13485594639aSTejun Heo { 13495594639aSTejun Heo .ident = "EP45-DS5", 13505594639aSTejun Heo .matches = { 13515594639aSTejun Heo DMI_MATCH(DMI_BOARD_VENDOR, 13525594639aSTejun Heo "Gigabyte Technology Co., Ltd."), 13535594639aSTejun Heo DMI_MATCH(DMI_BOARD_NAME, "EP45-DS5"), 13545594639aSTejun Heo }, 13555594639aSTejun Heo .driver_data = ENCODE_BUSDEVFN(0x03, 0x00, 0), 13565594639aSTejun Heo }, 13575594639aSTejun Heo { } /* terminate list */ 13585594639aSTejun Heo }; 13595594639aSTejun Heo #undef ENCODE_BUSDEVFN 13605594639aSTejun Heo const struct dmi_system_id *dmi = dmi_first_match(sysids); 13615594639aSTejun Heo unsigned int val; 13625594639aSTejun Heo 13635594639aSTejun Heo if (!dmi) 13645594639aSTejun Heo return false; 13655594639aSTejun Heo 13665594639aSTejun Heo val = (unsigned long)dmi->driver_data; 13675594639aSTejun Heo 13685594639aSTejun Heo return pdev->bus->number == (val >> 8) && pdev->devfn == (val & 0xff); 13695594639aSTejun Heo } 13705594639aSTejun Heo 13710cf4a7d6SJacob Pan static bool ahci_broken_devslp(struct pci_dev *pdev) 13720cf4a7d6SJacob Pan { 13730cf4a7d6SJacob Pan /* device with broken DEVSLP but still showing SDS capability */ 13740cf4a7d6SJacob Pan static const struct pci_device_id ids[] = { 13750cf4a7d6SJacob Pan { PCI_VDEVICE(INTEL, 0x0f23)}, /* Valleyview SoC */ 13760cf4a7d6SJacob Pan {} 13770cf4a7d6SJacob Pan }; 13780cf4a7d6SJacob Pan 13790cf4a7d6SJacob Pan return pci_match_id(ids, pdev); 13800cf4a7d6SJacob Pan } 13810cf4a7d6SJacob Pan 13828e513217SMarkus Trippelsdorf #ifdef CONFIG_ATA_ACPI 1383f80ae7e4STejun Heo static void ahci_gtf_filter_workaround(struct ata_host *host) 1384f80ae7e4STejun Heo { 1385f80ae7e4STejun Heo static const struct dmi_system_id sysids[] = { 1386f80ae7e4STejun Heo /* 1387f80ae7e4STejun Heo * Aspire 3810T issues a bunch of SATA enable commands 1388f80ae7e4STejun Heo * via _GTF including an invalid one and one which is 1389f80ae7e4STejun Heo * rejected by the device. Among the successful ones 1390f80ae7e4STejun Heo * is FPDMA non-zero offset enable which when enabled 1391f80ae7e4STejun Heo * only on the drive side leads to NCQ command 1392f80ae7e4STejun Heo * failures. Filter it out. 1393f80ae7e4STejun Heo */ 1394f80ae7e4STejun Heo { 1395f80ae7e4STejun Heo .ident = "Aspire 3810T", 1396f80ae7e4STejun Heo .matches = { 1397f80ae7e4STejun Heo DMI_MATCH(DMI_SYS_VENDOR, "Acer"), 1398f80ae7e4STejun Heo DMI_MATCH(DMI_PRODUCT_NAME, "Aspire 3810T"), 1399f80ae7e4STejun Heo }, 1400f80ae7e4STejun Heo .driver_data = (void *)ATA_ACPI_FILTER_FPDMA_OFFSET, 1401f80ae7e4STejun Heo }, 1402f80ae7e4STejun Heo { } 1403f80ae7e4STejun Heo }; 1404f80ae7e4STejun Heo const struct dmi_system_id *dmi = dmi_first_match(sysids); 1405f80ae7e4STejun Heo unsigned int filter; 1406f80ae7e4STejun Heo int i; 1407f80ae7e4STejun Heo 1408f80ae7e4STejun Heo if (!dmi) 1409f80ae7e4STejun Heo return; 1410f80ae7e4STejun Heo 1411f80ae7e4STejun Heo filter = (unsigned long)dmi->driver_data; 1412a44fec1fSJoe Perches dev_info(host->dev, "applying extra ACPI _GTF filter 0x%x for %s\n", 1413f80ae7e4STejun Heo filter, dmi->ident); 1414f80ae7e4STejun Heo 1415f80ae7e4STejun Heo for (i = 0; i < host->n_ports; i++) { 1416f80ae7e4STejun Heo struct ata_port *ap = host->ports[i]; 1417f80ae7e4STejun Heo struct ata_link *link; 1418f80ae7e4STejun Heo struct ata_device *dev; 1419f80ae7e4STejun Heo 1420f80ae7e4STejun Heo ata_for_each_link(link, ap, EDGE) 1421f80ae7e4STejun Heo ata_for_each_dev(dev, link, ALL) 1422f80ae7e4STejun Heo dev->gtf_filter |= filter; 1423f80ae7e4STejun Heo } 1424f80ae7e4STejun Heo } 14258e513217SMarkus Trippelsdorf #else 14268e513217SMarkus Trippelsdorf static inline void ahci_gtf_filter_workaround(struct ata_host *host) 14278e513217SMarkus Trippelsdorf {} 14288e513217SMarkus Trippelsdorf #endif 1429f80ae7e4STejun Heo 14308bfd1743SSui Chen /* 14318bfd1743SSui Chen * On the Acer Aspire Switch Alpha 12, sometimes all SATA ports are detected 14328bfd1743SSui Chen * as DUMMY, or detected but eventually get a "link down" and never get up 14338bfd1743SSui Chen * again. When this happens, CAP.NP may hold a value of 0x00 or 0x01, and the 14348bfd1743SSui Chen * port_map may hold a value of 0x00. 14358bfd1743SSui Chen * 14368bfd1743SSui Chen * Overriding CAP.NP to 0x02 and the port_map to 0x7 will reveal all 3 ports 14378bfd1743SSui Chen * and can significantly reduce the occurrence of the problem. 14388bfd1743SSui Chen * 14398bfd1743SSui Chen * https://bugzilla.kernel.org/show_bug.cgi?id=189471 14408bfd1743SSui Chen */ 14418bfd1743SSui Chen static void acer_sa5_271_workaround(struct ahci_host_priv *hpriv, 14428bfd1743SSui Chen struct pci_dev *pdev) 14438bfd1743SSui Chen { 14448bfd1743SSui Chen static const struct dmi_system_id sysids[] = { 14458bfd1743SSui Chen { 14468bfd1743SSui Chen .ident = "Acer Switch Alpha 12", 14478bfd1743SSui Chen .matches = { 14488bfd1743SSui Chen DMI_MATCH(DMI_SYS_VENDOR, "Acer"), 14498bfd1743SSui Chen DMI_MATCH(DMI_PRODUCT_NAME, "Switch SA5-271") 14508bfd1743SSui Chen }, 14518bfd1743SSui Chen }, 14528bfd1743SSui Chen { } 14538bfd1743SSui Chen }; 14548bfd1743SSui Chen 14558bfd1743SSui Chen if (dmi_check_system(sysids)) { 14568bfd1743SSui Chen dev_info(&pdev->dev, "enabling Acer Switch Alpha 12 workaround\n"); 14578bfd1743SSui Chen if ((hpriv->saved_cap & 0xC734FF00) == 0xC734FF00) { 14588bfd1743SSui Chen hpriv->port_map = 0x7; 14598bfd1743SSui Chen hpriv->cap = 0xC734FF02; 14608bfd1743SSui Chen } 14618bfd1743SSui Chen } 14628bfd1743SSui Chen } 14638bfd1743SSui Chen 1464d243bed3STirumalesh Chalamarla #ifdef CONFIG_ARM64 1465d243bed3STirumalesh Chalamarla /* 1466d243bed3STirumalesh Chalamarla * Due to ERRATA#22536, ThunderX needs to handle HOST_IRQ_STAT differently. 1467d243bed3STirumalesh Chalamarla * Workaround is to make sure all pending IRQs are served before leaving 1468d243bed3STirumalesh Chalamarla * handler. 1469d243bed3STirumalesh Chalamarla */ 1470d243bed3STirumalesh Chalamarla static irqreturn_t ahci_thunderx_irq_handler(int irq, void *dev_instance) 1471d243bed3STirumalesh Chalamarla { 1472d243bed3STirumalesh Chalamarla struct ata_host *host = dev_instance; 1473d243bed3STirumalesh Chalamarla struct ahci_host_priv *hpriv; 1474d243bed3STirumalesh Chalamarla unsigned int rc = 0; 1475d243bed3STirumalesh Chalamarla void __iomem *mmio; 1476d243bed3STirumalesh Chalamarla u32 irq_stat, irq_masked; 1477d243bed3STirumalesh Chalamarla unsigned int handled = 1; 1478d243bed3STirumalesh Chalamarla 1479d243bed3STirumalesh Chalamarla VPRINTK("ENTER\n"); 1480d243bed3STirumalesh Chalamarla hpriv = host->private_data; 1481d243bed3STirumalesh Chalamarla mmio = hpriv->mmio; 1482d243bed3STirumalesh Chalamarla irq_stat = readl(mmio + HOST_IRQ_STAT); 1483d243bed3STirumalesh Chalamarla if (!irq_stat) 1484d243bed3STirumalesh Chalamarla return IRQ_NONE; 1485d243bed3STirumalesh Chalamarla 1486d243bed3STirumalesh Chalamarla do { 1487d243bed3STirumalesh Chalamarla irq_masked = irq_stat & hpriv->port_map; 1488d243bed3STirumalesh Chalamarla spin_lock(&host->lock); 1489d243bed3STirumalesh Chalamarla rc = ahci_handle_port_intr(host, irq_masked); 1490d243bed3STirumalesh Chalamarla if (!rc) 1491d243bed3STirumalesh Chalamarla handled = 0; 1492d243bed3STirumalesh Chalamarla writel(irq_stat, mmio + HOST_IRQ_STAT); 1493d243bed3STirumalesh Chalamarla irq_stat = readl(mmio + HOST_IRQ_STAT); 1494d243bed3STirumalesh Chalamarla spin_unlock(&host->lock); 1495d243bed3STirumalesh Chalamarla } while (irq_stat); 1496d243bed3STirumalesh Chalamarla VPRINTK("EXIT\n"); 1497d243bed3STirumalesh Chalamarla 1498d243bed3STirumalesh Chalamarla return IRQ_RETVAL(handled); 1499d243bed3STirumalesh Chalamarla } 1500d243bed3STirumalesh Chalamarla #endif 1501d243bed3STirumalesh Chalamarla 1502aecec8b6SChristoph Hellwig static void ahci_remap_check(struct pci_dev *pdev, int bar, 1503aecec8b6SChristoph Hellwig struct ahci_host_priv *hpriv) 1504aecec8b6SChristoph Hellwig { 1505aecec8b6SChristoph Hellwig int i, count = 0; 1506aecec8b6SChristoph Hellwig u32 cap; 1507aecec8b6SChristoph Hellwig 1508aecec8b6SChristoph Hellwig /* 1509aecec8b6SChristoph Hellwig * Check if this device might have remapped nvme devices. 1510aecec8b6SChristoph Hellwig */ 1511aecec8b6SChristoph Hellwig if (pdev->vendor != PCI_VENDOR_ID_INTEL || 1512aecec8b6SChristoph Hellwig pci_resource_len(pdev, bar) < SZ_512K || 1513aecec8b6SChristoph Hellwig bar != AHCI_PCI_BAR_STANDARD || 1514aecec8b6SChristoph Hellwig !(readl(hpriv->mmio + AHCI_VSCAP) & 1)) 1515aecec8b6SChristoph Hellwig return; 1516aecec8b6SChristoph Hellwig 1517aecec8b6SChristoph Hellwig cap = readq(hpriv->mmio + AHCI_REMAP_CAP); 1518aecec8b6SChristoph Hellwig for (i = 0; i < AHCI_MAX_REMAP; i++) { 1519aecec8b6SChristoph Hellwig if ((cap & (1 << i)) == 0) 1520aecec8b6SChristoph Hellwig continue; 1521aecec8b6SChristoph Hellwig if (readl(hpriv->mmio + ahci_remap_dcc(i)) 1522aecec8b6SChristoph Hellwig != PCI_CLASS_STORAGE_EXPRESS) 1523aecec8b6SChristoph Hellwig continue; 1524aecec8b6SChristoph Hellwig 1525aecec8b6SChristoph Hellwig /* We've found a remapped device */ 1526aecec8b6SChristoph Hellwig count++; 1527aecec8b6SChristoph Hellwig } 1528aecec8b6SChristoph Hellwig 1529aecec8b6SChristoph Hellwig if (!count) 1530aecec8b6SChristoph Hellwig return; 1531aecec8b6SChristoph Hellwig 1532aecec8b6SChristoph Hellwig dev_warn(&pdev->dev, "Found %d remapped NVMe devices.\n", count); 1533f723fa4eSChristoph Hellwig dev_warn(&pdev->dev, 1534f723fa4eSChristoph Hellwig "Switch your BIOS from RAID to AHCI mode to use them.\n"); 1535f723fa4eSChristoph Hellwig 1536f723fa4eSChristoph Hellwig /* 1537f723fa4eSChristoph Hellwig * Don't rely on the msi-x capability in the remap case, 1538f723fa4eSChristoph Hellwig * share the legacy interrupt across ahci and remapped devices. 1539f723fa4eSChristoph Hellwig */ 1540f723fa4eSChristoph Hellwig hpriv->flags |= AHCI_HFLAG_NO_MSI; 1541aecec8b6SChristoph Hellwig } 1542aecec8b6SChristoph Hellwig 15430b9e2988SChristoph Hellwig static int ahci_get_irq_vector(struct ata_host *host, int port) 1544ee2aad42SRobert Richter { 15450b9e2988SChristoph Hellwig return pci_irq_vector(to_pci_dev(host->dev), port); 1546ee2aad42SRobert Richter } 1547ee2aad42SRobert Richter 1548a1c82311SRobert Richter static int ahci_init_msi(struct pci_dev *pdev, unsigned int n_ports, 15497b92b4f6SAlexander Gordeev struct ahci_host_priv *hpriv) 15505ca72c4fSAlexander Gordeev { 15510b9e2988SChristoph Hellwig int nvec; 15525ca72c4fSAlexander Gordeev 15537b92b4f6SAlexander Gordeev if (hpriv->flags & AHCI_HFLAG_NO_MSI) 1554a1c82311SRobert Richter return -ENODEV; 15557b92b4f6SAlexander Gordeev 15565ca72c4fSAlexander Gordeev /* 15577b92b4f6SAlexander Gordeev * If number of MSIs is less than number of ports then Sharing Last 15587b92b4f6SAlexander Gordeev * Message mode could be enforced. In this case assume that advantage 15597b92b4f6SAlexander Gordeev * of multipe MSIs is negated and use single MSI mode instead. 15605ca72c4fSAlexander Gordeev */ 156117a51f12SChristoph Hellwig if (n_ports > 1) { 15620b9e2988SChristoph Hellwig nvec = pci_alloc_irq_vectors(pdev, n_ports, INT_MAX, 15630b9e2988SChristoph Hellwig PCI_IRQ_MSIX | PCI_IRQ_MSI); 15640b9e2988SChristoph Hellwig if (nvec > 0) { 15650b9e2988SChristoph Hellwig if (!(readl(hpriv->mmio + HOST_CTL) & HOST_MRSM)) { 15660b9e2988SChristoph Hellwig hpriv->get_irq_vector = ahci_get_irq_vector; 1567c3ebd6a9SAlexander Gordeev hpriv->flags |= AHCI_HFLAG_MULTI_MSI; 156821bfd1aaSRobert Richter return nvec; 1569a1c82311SRobert Richter } 1570a1c82311SRobert Richter 1571d684a90dSDan Williams /* 157217a51f12SChristoph Hellwig * Fallback to single MSI mode if the controller 157317a51f12SChristoph Hellwig * enforced MRSM mode. 1574d684a90dSDan Williams */ 157517a51f12SChristoph Hellwig printk(KERN_INFO 157617a51f12SChristoph Hellwig "ahci: MRSM is on, fallback to single MSI\n"); 15770b9e2988SChristoph Hellwig pci_free_irq_vectors(pdev); 15780b9e2988SChristoph Hellwig } 1579a478b097SChristoph Hellwig } 1580d684a90dSDan Williams 15810b9e2988SChristoph Hellwig /* 15820b9e2988SChristoph Hellwig * If the host is not capable of supporting per-port vectors, fall 15830b9e2988SChristoph Hellwig * back to single MSI before finally attempting single MSI-X. 15840b9e2988SChristoph Hellwig */ 15850b9e2988SChristoph Hellwig nvec = pci_alloc_irq_vectors(pdev, 1, 1, PCI_IRQ_MSI); 15860b9e2988SChristoph Hellwig if (nvec == 1) 1587a1c82311SRobert Richter return nvec; 15880b9e2988SChristoph Hellwig return pci_alloc_irq_vectors(pdev, 1, 1, PCI_IRQ_MSIX); 15895ca72c4fSAlexander Gordeev } 15905ca72c4fSAlexander Gordeev 1591b1a9585cSSrinivas Pandruvada static void ahci_update_initial_lpm_policy(struct ata_port *ap, 1592b1a9585cSSrinivas Pandruvada struct ahci_host_priv *hpriv) 1593b1a9585cSSrinivas Pandruvada { 1594b1a9585cSSrinivas Pandruvada int policy = CONFIG_SATA_MOBILE_LPM_POLICY; 1595b1a9585cSSrinivas Pandruvada 1596b1a9585cSSrinivas Pandruvada 1597b1a9585cSSrinivas Pandruvada /* Ignore processing for non mobile platforms */ 1598b1a9585cSSrinivas Pandruvada if (!(hpriv->flags & AHCI_HFLAG_IS_MOBILE)) 1599b1a9585cSSrinivas Pandruvada return; 1600b1a9585cSSrinivas Pandruvada 1601b1a9585cSSrinivas Pandruvada /* user modified policy via module param */ 1602b1a9585cSSrinivas Pandruvada if (mobile_lpm_policy != -1) { 1603b1a9585cSSrinivas Pandruvada policy = mobile_lpm_policy; 1604b1a9585cSSrinivas Pandruvada goto update_policy; 1605b1a9585cSSrinivas Pandruvada } 1606b1a9585cSSrinivas Pandruvada 1607b1a9585cSSrinivas Pandruvada #ifdef CONFIG_ACPI 1608b1a9585cSSrinivas Pandruvada if (policy > ATA_LPM_MED_POWER && 1609b1a9585cSSrinivas Pandruvada (acpi_gbl_FADT.flags & ACPI_FADT_LOW_POWER_S0)) { 1610b1a9585cSSrinivas Pandruvada if (hpriv->cap & HOST_CAP_PART) 1611b1a9585cSSrinivas Pandruvada policy = ATA_LPM_MIN_POWER_WITH_PARTIAL; 1612b1a9585cSSrinivas Pandruvada else if (hpriv->cap & HOST_CAP_SSC) 1613b1a9585cSSrinivas Pandruvada policy = ATA_LPM_MIN_POWER; 1614b1a9585cSSrinivas Pandruvada } 1615b1a9585cSSrinivas Pandruvada #endif 1616b1a9585cSSrinivas Pandruvada 1617b1a9585cSSrinivas Pandruvada update_policy: 1618b1a9585cSSrinivas Pandruvada if (policy >= ATA_LPM_UNKNOWN && policy <= ATA_LPM_MIN_POWER) 1619b1a9585cSSrinivas Pandruvada ap->target_lpm_policy = policy; 1620b1a9585cSSrinivas Pandruvada } 1621b1a9585cSSrinivas Pandruvada 1622c6fd2807SJeff Garzik static int ahci_init_one(struct pci_dev *pdev, const struct pci_device_id *ent) 1623c6fd2807SJeff Garzik { 1624e297d99eSTejun Heo unsigned int board_id = ent->driver_data; 1625e297d99eSTejun Heo struct ata_port_info pi = ahci_port_info[board_id]; 16264447d351STejun Heo const struct ata_port_info *ppi[] = { &pi, NULL }; 162724dc5f33STejun Heo struct device *dev = &pdev->dev; 1628c6fd2807SJeff Garzik struct ahci_host_priv *hpriv; 16294447d351STejun Heo struct ata_host *host; 1630c3ebd6a9SAlexander Gordeev int n_ports, i, rc; 1631318893e1SAlessandro Rubini int ahci_pci_bar = AHCI_PCI_BAR_STANDARD; 1632c6fd2807SJeff Garzik 1633c6fd2807SJeff Garzik VPRINTK("ENTER\n"); 1634c6fd2807SJeff Garzik 1635b429dd59SJustin P. Mattock WARN_ON((int)ATA_MAX_QUEUE > AHCI_MAX_CMDS); 1636c6fd2807SJeff Garzik 163706296a1eSJoe Perches ata_print_version_once(&pdev->dev, DRV_VERSION); 1638c6fd2807SJeff Garzik 16395b66c829SAlan Cox /* The AHCI driver can only drive the SATA ports, the PATA driver 16405b66c829SAlan Cox can drive them all so if both drivers are selected make sure 16415b66c829SAlan Cox AHCI stays out of the way */ 16425b66c829SAlan Cox if (pdev->vendor == PCI_VENDOR_ID_MARVELL && !marvell_enable) 16435b66c829SAlan Cox return -ENODEV; 16445b66c829SAlan Cox 1645cb85696dSJames Laird /* Apple BIOS on MCP89 prevents us using AHCI */ 1646cb85696dSJames Laird if (is_mcp89_apple(pdev)) 1647cb85696dSJames Laird ahci_mcp89_apple_enable(pdev); 1648c6353b45STejun Heo 16497a02267eSMark Nelson /* Promise's PDC42819 is a SAS/SATA controller that has an AHCI mode. 16507a02267eSMark Nelson * At the moment, we can only use the AHCI mode. Let the users know 16517a02267eSMark Nelson * that for SAS drives they're out of luck. 16527a02267eSMark Nelson */ 16537a02267eSMark Nelson if (pdev->vendor == PCI_VENDOR_ID_PROMISE) 1654a44fec1fSJoe Perches dev_info(&pdev->dev, 1655a44fec1fSJoe Perches "PDC42819 can only drive SATA devices with this driver\n"); 16567a02267eSMark Nelson 1657b7ae128dSRobert Richter /* Some devices use non-standard BARs */ 1658318893e1SAlessandro Rubini if (pdev->vendor == PCI_VENDOR_ID_STMICRO && pdev->device == 0xCC06) 1659318893e1SAlessandro Rubini ahci_pci_bar = AHCI_PCI_BAR_STA2X11; 16607f9c9f8eSHugh Daschbach else if (pdev->vendor == 0x1c44 && pdev->device == 0x8000) 16617f9c9f8eSHugh Daschbach ahci_pci_bar = AHCI_PCI_BAR_ENMOTUS; 1662b1314e3fSRadha Mohan Chintakuntla else if (pdev->vendor == PCI_VENDOR_ID_CAVIUM) { 1663b1314e3fSRadha Mohan Chintakuntla if (pdev->device == 0xa01c) 1664b7ae128dSRobert Richter ahci_pci_bar = AHCI_PCI_BAR_CAVIUM; 1665b1314e3fSRadha Mohan Chintakuntla if (pdev->device == 0xa084) 1666b1314e3fSRadha Mohan Chintakuntla ahci_pci_bar = AHCI_PCI_BAR_CAVIUM_GEN5; 1667b1314e3fSRadha Mohan Chintakuntla } 1668318893e1SAlessandro Rubini 16694447d351STejun Heo /* acquire resources */ 167024dc5f33STejun Heo rc = pcim_enable_device(pdev); 1671c6fd2807SJeff Garzik if (rc) 1672c6fd2807SJeff Garzik return rc; 1673c6fd2807SJeff Garzik 1674c4f7792cSTejun Heo if (pdev->vendor == PCI_VENDOR_ID_INTEL && 1675c4f7792cSTejun Heo (pdev->device == 0x2652 || pdev->device == 0x2653)) { 1676c4f7792cSTejun Heo u8 map; 1677c4f7792cSTejun Heo 1678c4f7792cSTejun Heo /* ICH6s share the same PCI ID for both piix and ahci 1679c4f7792cSTejun Heo * modes. Enabling ahci mode while MAP indicates 1680c4f7792cSTejun Heo * combined mode is a bad idea. Yield to ata_piix. 1681c4f7792cSTejun Heo */ 1682c4f7792cSTejun Heo pci_read_config_byte(pdev, ICH_MAP, &map); 1683c4f7792cSTejun Heo if (map & 0x3) { 1684a44fec1fSJoe Perches dev_info(&pdev->dev, 1685a44fec1fSJoe Perches "controller is in combined mode, can't enable AHCI mode\n"); 1686c4f7792cSTejun Heo return -ENODEV; 1687c4f7792cSTejun Heo } 1688c4f7792cSTejun Heo } 1689c4f7792cSTejun Heo 16906fec8871SPaul Bolle /* AHCI controllers often implement SFF compatible interface. 16916fec8871SPaul Bolle * Grab all PCI BARs just in case. 16926fec8871SPaul Bolle */ 16936fec8871SPaul Bolle rc = pcim_iomap_regions_request_all(pdev, 1 << ahci_pci_bar, DRV_NAME); 16946fec8871SPaul Bolle if (rc == -EBUSY) 16956fec8871SPaul Bolle pcim_pin_device(pdev); 16966fec8871SPaul Bolle if (rc) 16976fec8871SPaul Bolle return rc; 16986fec8871SPaul Bolle 169924dc5f33STejun Heo hpriv = devm_kzalloc(dev, sizeof(*hpriv), GFP_KERNEL); 170024dc5f33STejun Heo if (!hpriv) 170124dc5f33STejun Heo return -ENOMEM; 1702417a1a6dSTejun Heo hpriv->flags |= (unsigned long)pi.private_data; 1703417a1a6dSTejun Heo 1704e297d99eSTejun Heo /* MCP65 revision A1 and A2 can't do MSI */ 1705e297d99eSTejun Heo if (board_id == board_ahci_mcp65 && 1706e297d99eSTejun Heo (pdev->revision == 0xa1 || pdev->revision == 0xa2)) 1707e297d99eSTejun Heo hpriv->flags |= AHCI_HFLAG_NO_MSI; 1708e297d99eSTejun Heo 1709e427fe04SShane Huang /* SB800 does NOT need the workaround to ignore SERR_INTERNAL */ 1710e427fe04SShane Huang if (board_id == board_ahci_sb700 && pdev->revision >= 0x40) 1711e427fe04SShane Huang hpriv->flags &= ~AHCI_HFLAG_IGN_SERR_INTERNAL; 1712e427fe04SShane Huang 17132fcad9d2STejun Heo /* only some SB600s can do 64bit DMA */ 17142fcad9d2STejun Heo if (ahci_sb600_enable_64bit(pdev)) 17152fcad9d2STejun Heo hpriv->flags &= ~AHCI_HFLAG_32BIT_ONLY; 171658a09b38SShane Huang 1717318893e1SAlessandro Rubini hpriv->mmio = pcim_iomap_table(pdev)[ahci_pci_bar]; 1718d8993349SAnton Vorontsov 1719aecec8b6SChristoph Hellwig /* detect remapped nvme devices */ 1720aecec8b6SChristoph Hellwig ahci_remap_check(pdev, ahci_pci_bar, hpriv); 1721aecec8b6SChristoph Hellwig 17220cf4a7d6SJacob Pan /* must set flag prior to save config in order to take effect */ 17230cf4a7d6SJacob Pan if (ahci_broken_devslp(pdev)) 17240cf4a7d6SJacob Pan hpriv->flags |= AHCI_HFLAG_NO_DEVSLP; 17250cf4a7d6SJacob Pan 1726d243bed3STirumalesh Chalamarla #ifdef CONFIG_ARM64 1727d243bed3STirumalesh Chalamarla if (pdev->vendor == 0x177d && pdev->device == 0xa01c) 1728d243bed3STirumalesh Chalamarla hpriv->irq_handler = ahci_thunderx_irq_handler; 1729d243bed3STirumalesh Chalamarla #endif 1730d243bed3STirumalesh Chalamarla 17314447d351STejun Heo /* save initial config */ 1732394d6e53SAnton Vorontsov ahci_pci_save_initial_config(pdev, hpriv); 1733c6fd2807SJeff Garzik 17344447d351STejun Heo /* prepare host */ 1735453d3131SRobert Hancock if (hpriv->cap & HOST_CAP_NCQ) { 1736453d3131SRobert Hancock pi.flags |= ATA_FLAG_NCQ; 173783f2b963STejun Heo /* 173883f2b963STejun Heo * Auto-activate optimization is supposed to be 173983f2b963STejun Heo * supported on all AHCI controllers indicating NCQ 174083f2b963STejun Heo * capability, but it seems to be broken on some 174183f2b963STejun Heo * chipsets including NVIDIAs. 174283f2b963STejun Heo */ 174383f2b963STejun Heo if (!(hpriv->flags & AHCI_HFLAG_NO_FPDMA_AA)) 1744453d3131SRobert Hancock pi.flags |= ATA_FLAG_FPDMA_AA; 174540fb59e7SMarc Carino 174640fb59e7SMarc Carino /* 174740fb59e7SMarc Carino * All AHCI controllers should be forward-compatible 174840fb59e7SMarc Carino * with the new auxiliary field. This code should be 174940fb59e7SMarc Carino * conditionalized if any buggy AHCI controllers are 175040fb59e7SMarc Carino * encountered. 175140fb59e7SMarc Carino */ 175240fb59e7SMarc Carino pi.flags |= ATA_FLAG_FPDMA_AUX; 1753453d3131SRobert Hancock } 17544447d351STejun Heo 17557d50b60bSTejun Heo if (hpriv->cap & HOST_CAP_PMP) 17567d50b60bSTejun Heo pi.flags |= ATA_FLAG_PMP; 17577d50b60bSTejun Heo 17580cbb0e77SAnton Vorontsov ahci_set_em_messages(hpriv, &pi); 175918f7ba4cSKristen Carlson Accardi 17601fd68434SRafael J. Wysocki if (ahci_broken_system_poweroff(pdev)) { 17611fd68434SRafael J. Wysocki pi.flags |= ATA_FLAG_NO_POWEROFF_SPINDOWN; 17621fd68434SRafael J. Wysocki dev_info(&pdev->dev, 17631fd68434SRafael J. Wysocki "quirky BIOS, skipping spindown on poweroff\n"); 17641fd68434SRafael J. Wysocki } 17651fd68434SRafael J. Wysocki 1766240630e6SHans de Goede if (ahci_broken_lpm(pdev)) { 1767240630e6SHans de Goede pi.flags |= ATA_FLAG_NO_LPM; 1768240630e6SHans de Goede dev_warn(&pdev->dev, 1769240630e6SHans de Goede "BIOS update required for Link Power Management support\n"); 1770240630e6SHans de Goede } 1771240630e6SHans de Goede 17729b10ae86STejun Heo if (ahci_broken_suspend(pdev)) { 17739b10ae86STejun Heo hpriv->flags |= AHCI_HFLAG_NO_SUSPEND; 1774a44fec1fSJoe Perches dev_warn(&pdev->dev, 17759b10ae86STejun Heo "BIOS update required for suspend/resume\n"); 17769b10ae86STejun Heo } 17779b10ae86STejun Heo 17785594639aSTejun Heo if (ahci_broken_online(pdev)) { 17795594639aSTejun Heo hpriv->flags |= AHCI_HFLAG_SRST_TOUT_IS_OFFLINE; 17805594639aSTejun Heo dev_info(&pdev->dev, 17815594639aSTejun Heo "online status unreliable, applying workaround\n"); 17825594639aSTejun Heo } 17835594639aSTejun Heo 17848bfd1743SSui Chen 17858bfd1743SSui Chen /* Acer SA5-271 workaround modifies private_data */ 17868bfd1743SSui Chen acer_sa5_271_workaround(hpriv, pdev); 17878bfd1743SSui Chen 1788837f5f8fSTejun Heo /* CAP.NP sometimes indicate the index of the last enabled 1789837f5f8fSTejun Heo * port, at other times, that of the last possible port, so 1790837f5f8fSTejun Heo * determining the maximum port number requires looking at 1791837f5f8fSTejun Heo * both CAP.NP and port_map. 1792837f5f8fSTejun Heo */ 1793837f5f8fSTejun Heo n_ports = max(ahci_nr_ports(hpriv->cap), fls(hpriv->port_map)); 1794837f5f8fSTejun Heo 1795837f5f8fSTejun Heo host = ata_host_alloc_pinfo(&pdev->dev, ppi, n_ports); 17964447d351STejun Heo if (!host) 17974447d351STejun Heo return -ENOMEM; 17984447d351STejun Heo host->private_data = hpriv; 17990b9e2988SChristoph Hellwig 18000b9e2988SChristoph Hellwig if (ahci_init_msi(pdev, n_ports, hpriv) < 0) { 18010b9e2988SChristoph Hellwig /* legacy intx interrupts */ 18020b9e2988SChristoph Hellwig pci_intx(pdev, 1); 18030b9e2988SChristoph Hellwig } 18040ce57f8aSChristoph Hellwig hpriv->irq = pci_irq_vector(pdev, 0); 180521bfd1aaSRobert Richter 1806f3d7f23fSArjan van de Ven if (!(hpriv->cap & HOST_CAP_SSS) || ahci_ignore_sss) 1807886ad09fSArjan van de Ven host->flags |= ATA_HOST_PARALLEL_SCAN; 1808f3d7f23fSArjan van de Ven else 1809d2782d96SJingoo Han dev_info(&pdev->dev, "SSS flag set, parallel bus scan disabled\n"); 1810886ad09fSArjan van de Ven 181118f7ba4cSKristen Carlson Accardi if (pi.flags & ATA_FLAG_EM) 181218f7ba4cSKristen Carlson Accardi ahci_reset_em(host); 181318f7ba4cSKristen Carlson Accardi 18144447d351STejun Heo for (i = 0; i < host->n_ports; i++) { 18154447d351STejun Heo struct ata_port *ap = host->ports[i]; 18164447d351STejun Heo 1817318893e1SAlessandro Rubini ata_port_pbar_desc(ap, ahci_pci_bar, -1, "abar"); 1818318893e1SAlessandro Rubini ata_port_pbar_desc(ap, ahci_pci_bar, 1819cbcdd875STejun Heo 0x100 + ap->port_no * 0x80, "port"); 1820cbcdd875STejun Heo 182118f7ba4cSKristen Carlson Accardi /* set enclosure management message type */ 182218f7ba4cSKristen Carlson Accardi if (ap->flags & ATA_FLAG_EM) 1823008dbd61SHarry Zhang ap->em_message_type = hpriv->em_msg_type; 182418f7ba4cSKristen Carlson Accardi 1825b1a9585cSSrinivas Pandruvada ahci_update_initial_lpm_policy(ap, hpriv); 182618f7ba4cSKristen Carlson Accardi 1827dab632e8SJeff Garzik /* disabled/not-implemented port */ 1828350756f6STejun Heo if (!(hpriv->port_map & (1 << i))) 1829dab632e8SJeff Garzik ap->ops = &ata_dummy_port_ops; 18304447d351STejun Heo } 1831c6fd2807SJeff Garzik 1832edc93052STejun Heo /* apply workaround for ASUS P5W DH Deluxe mainboard */ 1833edc93052STejun Heo ahci_p5wdh_workaround(host); 1834edc93052STejun Heo 1835f80ae7e4STejun Heo /* apply gtf filter quirk */ 1836f80ae7e4STejun Heo ahci_gtf_filter_workaround(host); 1837f80ae7e4STejun Heo 1838c6fd2807SJeff Garzik /* initialize adapter */ 18394447d351STejun Heo rc = ahci_configure_dma_masks(pdev, hpriv->cap & HOST_CAP_64); 1840c6fd2807SJeff Garzik if (rc) 184124dc5f33STejun Heo return rc; 1842c6fd2807SJeff Garzik 18433303040dSAnton Vorontsov rc = ahci_pci_reset_controller(host); 18444447d351STejun Heo if (rc) 18454447d351STejun Heo return rc; 1846c6fd2807SJeff Garzik 1847781d6550SAnton Vorontsov ahci_pci_init_controller(host); 1848439fcaecSAnton Vorontsov ahci_pci_print_info(host); 1849c6fd2807SJeff Garzik 18504447d351STejun Heo pci_set_master(pdev); 18515ca72c4fSAlexander Gordeev 185202e53293SMika Westerberg rc = ahci_host_activate(host, &ahci_sht); 185302e53293SMika Westerberg if (rc) 185402e53293SMika Westerberg return rc; 185502e53293SMika Westerberg 185602e53293SMika Westerberg pm_runtime_put_noidle(&pdev->dev); 185702e53293SMika Westerberg return 0; 185802e53293SMika Westerberg } 185902e53293SMika Westerberg 186002e53293SMika Westerberg static void ahci_remove_one(struct pci_dev *pdev) 186102e53293SMika Westerberg { 186202e53293SMika Westerberg pm_runtime_get_noresume(&pdev->dev); 186302e53293SMika Westerberg ata_pci_remove_one(pdev); 1864c6fd2807SJeff Garzik } 1865c6fd2807SJeff Garzik 18662fc75da0SAxel Lin module_pci_driver(ahci_pci_driver); 1867c6fd2807SJeff Garzik 1868c6fd2807SJeff Garzik MODULE_AUTHOR("Jeff Garzik"); 1869c6fd2807SJeff Garzik MODULE_DESCRIPTION("AHCI SATA low-level driver"); 1870c6fd2807SJeff Garzik MODULE_LICENSE("GPL"); 1871c6fd2807SJeff Garzik MODULE_DEVICE_TABLE(pci, ahci_pci_tbl); 1872c6fd2807SJeff Garzik MODULE_VERSION(DRV_VERSION); 1873