1c82ee6d3SThomas 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 68c312ef17SDan Williams /* 69c312ef17SDan Williams * board IDs for Intel chipsets that support more than 6 ports 70c312ef17SDan Williams * *and* end up needing the PCS quirk. 71c312ef17SDan Williams */ 72c312ef17SDan Williams board_ahci_pcs7, 73c312ef17SDan Williams 74441577efSTejun Heo /* aliases */ 75441577efSTejun Heo board_ahci_mcp_linux = board_ahci_mcp65, 76441577efSTejun Heo board_ahci_mcp67 = board_ahci_mcp65, 77441577efSTejun Heo board_ahci_mcp73 = board_ahci_mcp65, 7883f2b963STejun Heo board_ahci_mcp79 = board_ahci_mcp77, 79c6fd2807SJeff Garzik }; 80c6fd2807SJeff Garzik 81c6fd2807SJeff Garzik static int ahci_init_one(struct pci_dev *pdev, const struct pci_device_id *ent); 8202e53293SMika Westerberg static void ahci_remove_one(struct pci_dev *dev); 83a1efdabaSTejun Heo static int ahci_vt8251_hardreset(struct ata_link *link, unsigned int *class, 84a1efdabaSTejun Heo unsigned long deadline); 85dbfe8ef5SDan Williams static int ahci_avn_hardreset(struct ata_link *link, unsigned int *class, 86dbfe8ef5SDan Williams unsigned long deadline); 87cb85696dSJames Laird static void ahci_mcp89_apple_enable(struct pci_dev *pdev); 88cb85696dSJames Laird static bool is_mcp89_apple(struct pci_dev *pdev); 89a1efdabaSTejun Heo static int ahci_p5wdh_hardreset(struct ata_link *link, unsigned int *class, 90a1efdabaSTejun Heo unsigned long deadline); 9102e53293SMika Westerberg #ifdef CONFIG_PM 9202e53293SMika Westerberg static int ahci_pci_device_runtime_suspend(struct device *dev); 9302e53293SMika Westerberg static int ahci_pci_device_runtime_resume(struct device *dev); 94f1d848f9SMika Westerberg #ifdef CONFIG_PM_SLEEP 95f1d848f9SMika Westerberg static int ahci_pci_device_suspend(struct device *dev); 96f1d848f9SMika Westerberg static int ahci_pci_device_resume(struct device *dev); 97438ac6d5STejun Heo #endif 9802e53293SMika Westerberg #endif /* CONFIG_PM */ 99c6fd2807SJeff Garzik 100fad16e7aSTejun Heo static struct scsi_host_template ahci_sht = { 101fad16e7aSTejun Heo AHCI_SHT("ahci"), 102fad16e7aSTejun Heo }; 103fad16e7aSTejun Heo 104029cfd6bSTejun Heo static struct ata_port_operations ahci_vt8251_ops = { 105029cfd6bSTejun Heo .inherits = &ahci_ops, 106a1efdabaSTejun Heo .hardreset = ahci_vt8251_hardreset, 107ad616ffbSTejun Heo }; 108ad616ffbSTejun Heo 109029cfd6bSTejun Heo static struct ata_port_operations ahci_p5wdh_ops = { 110029cfd6bSTejun Heo .inherits = &ahci_ops, 111a1efdabaSTejun Heo .hardreset = ahci_p5wdh_hardreset, 112edc93052STejun Heo }; 113edc93052STejun Heo 114dbfe8ef5SDan Williams static struct ata_port_operations ahci_avn_ops = { 115dbfe8ef5SDan Williams .inherits = &ahci_ops, 116dbfe8ef5SDan Williams .hardreset = ahci_avn_hardreset, 117dbfe8ef5SDan Williams }; 118dbfe8ef5SDan Williams 119c6fd2807SJeff Garzik static const struct ata_port_info ahci_port_info[] = { 120441577efSTejun Heo /* by features */ 121facb8fa6SJeffrin Jose [board_ahci] = { 1221188c0d8STejun Heo .flags = AHCI_FLAG_COMMON, 12314bdef98SErik Inge Bolsø .pio_mask = ATA_PIO4, 124469248abSJeff Garzik .udma_mask = ATA_UDMA6, 125c6fd2807SJeff Garzik .port_ops = &ahci_ops, 126c6fd2807SJeff Garzik }, 127facb8fa6SJeffrin Jose [board_ahci_ign_iferr] = { 128417a1a6dSTejun Heo AHCI_HFLAGS (AHCI_HFLAG_IGN_IRQ_IF_ERR), 129417a1a6dSTejun Heo .flags = AHCI_FLAG_COMMON, 13014bdef98SErik Inge Bolsø .pio_mask = ATA_PIO4, 131469248abSJeff Garzik .udma_mask = ATA_UDMA6, 13241669553STejun Heo .port_ops = &ahci_ops, 13341669553STejun Heo }, 134ebb82e3cSHans de Goede [board_ahci_mobile] = { 135ebb82e3cSHans de Goede AHCI_HFLAGS (AHCI_HFLAG_IS_MOBILE), 136ebb82e3cSHans de Goede .flags = AHCI_FLAG_COMMON, 137ebb82e3cSHans de Goede .pio_mask = ATA_PIO4, 138ebb82e3cSHans de Goede .udma_mask = ATA_UDMA6, 139ebb82e3cSHans de Goede .port_ops = &ahci_ops, 140ebb82e3cSHans de Goede }, 14166a7cbc3STejun Heo [board_ahci_nomsi] = { 14266a7cbc3STejun Heo AHCI_HFLAGS (AHCI_HFLAG_NO_MSI), 14366a7cbc3STejun Heo .flags = AHCI_FLAG_COMMON, 14466a7cbc3STejun Heo .pio_mask = ATA_PIO4, 14566a7cbc3STejun Heo .udma_mask = ATA_UDMA6, 14666a7cbc3STejun Heo .port_ops = &ahci_ops, 14766a7cbc3STejun Heo }, 14867809f85SLevente Kurusa [board_ahci_noncq] = { 14967809f85SLevente Kurusa AHCI_HFLAGS (AHCI_HFLAG_NO_NCQ), 15067809f85SLevente Kurusa .flags = AHCI_FLAG_COMMON, 15167809f85SLevente Kurusa .pio_mask = ATA_PIO4, 15267809f85SLevente Kurusa .udma_mask = ATA_UDMA6, 15367809f85SLevente Kurusa .port_ops = &ahci_ops, 15467809f85SLevente Kurusa }, 155facb8fa6SJeffrin Jose [board_ahci_nosntf] = { 156441577efSTejun Heo AHCI_HFLAGS (AHCI_HFLAG_NO_SNTF), 157441577efSTejun Heo .flags = AHCI_FLAG_COMMON, 158441577efSTejun Heo .pio_mask = ATA_PIO4, 159441577efSTejun Heo .udma_mask = ATA_UDMA6, 160441577efSTejun Heo .port_ops = &ahci_ops, 161441577efSTejun Heo }, 162facb8fa6SJeffrin Jose [board_ahci_yes_fbs] = { 1635f173107STejun Heo AHCI_HFLAGS (AHCI_HFLAG_YES_FBS), 1645f173107STejun Heo .flags = AHCI_FLAG_COMMON, 1655f173107STejun Heo .pio_mask = ATA_PIO4, 1665f173107STejun Heo .udma_mask = ATA_UDMA6, 1675f173107STejun Heo .port_ops = &ahci_ops, 1685f173107STejun Heo }, 169441577efSTejun Heo /* by chipsets */ 170dbfe8ef5SDan Williams [board_ahci_avn] = { 171dbfe8ef5SDan Williams .flags = AHCI_FLAG_COMMON, 172dbfe8ef5SDan Williams .pio_mask = ATA_PIO4, 173dbfe8ef5SDan Williams .udma_mask = ATA_UDMA6, 174dbfe8ef5SDan Williams .port_ops = &ahci_avn_ops, 175dbfe8ef5SDan Williams }, 176facb8fa6SJeffrin Jose [board_ahci_mcp65] = { 17783f2b963STejun Heo AHCI_HFLAGS (AHCI_HFLAG_NO_FPDMA_AA | AHCI_HFLAG_NO_PMP | 17883f2b963STejun Heo AHCI_HFLAG_YES_NCQ), 179ae01b249STejun Heo .flags = AHCI_FLAG_COMMON | ATA_FLAG_NO_DIPM, 18083f2b963STejun Heo .pio_mask = ATA_PIO4, 18183f2b963STejun Heo .udma_mask = ATA_UDMA6, 18283f2b963STejun Heo .port_ops = &ahci_ops, 18383f2b963STejun Heo }, 184facb8fa6SJeffrin Jose [board_ahci_mcp77] = { 18583f2b963STejun Heo AHCI_HFLAGS (AHCI_HFLAG_NO_FPDMA_AA | AHCI_HFLAG_NO_PMP), 18683f2b963STejun Heo .flags = AHCI_FLAG_COMMON, 18783f2b963STejun Heo .pio_mask = ATA_PIO4, 18883f2b963STejun Heo .udma_mask = ATA_UDMA6, 18983f2b963STejun Heo .port_ops = &ahci_ops, 19083f2b963STejun Heo }, 191facb8fa6SJeffrin Jose [board_ahci_mcp89] = { 19283f2b963STejun Heo AHCI_HFLAGS (AHCI_HFLAG_NO_FPDMA_AA), 193441577efSTejun Heo .flags = AHCI_FLAG_COMMON, 194441577efSTejun Heo .pio_mask = ATA_PIO4, 195441577efSTejun Heo .udma_mask = ATA_UDMA6, 196441577efSTejun Heo .port_ops = &ahci_ops, 197441577efSTejun Heo }, 198facb8fa6SJeffrin Jose [board_ahci_mv] = { 199441577efSTejun Heo AHCI_HFLAGS (AHCI_HFLAG_NO_NCQ | AHCI_HFLAG_NO_MSI | 200441577efSTejun Heo AHCI_HFLAG_MV_PATA | AHCI_HFLAG_NO_PMP), 2019cbe056fSSergei Shtylyov .flags = ATA_FLAG_SATA | ATA_FLAG_PIO_DMA, 202441577efSTejun Heo .pio_mask = ATA_PIO4, 203441577efSTejun Heo .udma_mask = ATA_UDMA6, 204441577efSTejun Heo .port_ops = &ahci_ops, 205441577efSTejun Heo }, 206facb8fa6SJeffrin Jose [board_ahci_sb600] = { 207417a1a6dSTejun Heo AHCI_HFLAGS (AHCI_HFLAG_IGN_SERR_INTERNAL | 2082fcad9d2STejun Heo AHCI_HFLAG_NO_MSI | AHCI_HFLAG_SECT255 | 2092fcad9d2STejun Heo AHCI_HFLAG_32BIT_ONLY), 210417a1a6dSTejun Heo .flags = AHCI_FLAG_COMMON, 21114bdef98SErik Inge Bolsø .pio_mask = ATA_PIO4, 212469248abSJeff Garzik .udma_mask = ATA_UDMA6, 213345347c5SYuan-Hsin Chen .port_ops = &ahci_pmp_retry_srst_ops, 21455a61604SConke Hu }, 215facb8fa6SJeffrin Jose [board_ahci_sb700] = { /* for SB700 and SB800 */ 216bd17243aSShane Huang AHCI_HFLAGS (AHCI_HFLAG_IGN_SERR_INTERNAL), 217e39fc8c9SShane Huang .flags = AHCI_FLAG_COMMON, 21814bdef98SErik Inge Bolsø .pio_mask = ATA_PIO4, 219e39fc8c9SShane Huang .udma_mask = ATA_UDMA6, 220345347c5SYuan-Hsin Chen .port_ops = &ahci_pmp_retry_srst_ops, 221e39fc8c9SShane Huang }, 222facb8fa6SJeffrin Jose [board_ahci_vt8251] = { 223441577efSTejun Heo AHCI_HFLAGS (AHCI_HFLAG_NO_NCQ | AHCI_HFLAG_NO_PMP), 224e297d99eSTejun Heo .flags = AHCI_FLAG_COMMON, 22514bdef98SErik Inge Bolsø .pio_mask = ATA_PIO4, 226e297d99eSTejun Heo .udma_mask = ATA_UDMA6, 227441577efSTejun Heo .port_ops = &ahci_vt8251_ops, 2281b677afdSShaohua Li }, 229c312ef17SDan Williams [board_ahci_pcs7] = { 230c312ef17SDan Williams .flags = AHCI_FLAG_COMMON, 231c312ef17SDan Williams .pio_mask = ATA_PIO4, 232c312ef17SDan Williams .udma_mask = ATA_UDMA6, 233c312ef17SDan Williams .port_ops = &ahci_ops, 234c312ef17SDan Williams }, 235c6fd2807SJeff Garzik }; 236c6fd2807SJeff Garzik 237c6fd2807SJeff Garzik static const struct pci_device_id ahci_pci_tbl[] = { 238c6fd2807SJeff Garzik /* Intel */ 23954bb3a94SJeff Garzik { PCI_VDEVICE(INTEL, 0x2652), board_ahci }, /* ICH6 */ 24054bb3a94SJeff Garzik { PCI_VDEVICE(INTEL, 0x2653), board_ahci }, /* ICH6M */ 24154bb3a94SJeff Garzik { PCI_VDEVICE(INTEL, 0x27c1), board_ahci }, /* ICH7 */ 24254bb3a94SJeff Garzik { PCI_VDEVICE(INTEL, 0x27c5), board_ahci }, /* ICH7M */ 24354bb3a94SJeff Garzik { PCI_VDEVICE(INTEL, 0x27c3), board_ahci }, /* ICH7R */ 24482490c09STejun Heo { PCI_VDEVICE(AL, 0x5288), board_ahci_ign_iferr }, /* ULi M5288 */ 24554bb3a94SJeff Garzik { PCI_VDEVICE(INTEL, 0x2681), board_ahci }, /* ESB2 */ 24654bb3a94SJeff Garzik { PCI_VDEVICE(INTEL, 0x2682), board_ahci }, /* ESB2 */ 24754bb3a94SJeff Garzik { PCI_VDEVICE(INTEL, 0x2683), board_ahci }, /* ESB2 */ 24854bb3a94SJeff Garzik { PCI_VDEVICE(INTEL, 0x27c6), board_ahci }, /* ICH7-M DH */ 2497a234affSTejun Heo { PCI_VDEVICE(INTEL, 0x2821), board_ahci }, /* ICH8 */ 2501b677afdSShaohua Li { PCI_VDEVICE(INTEL, 0x2822), board_ahci_nosntf }, /* ICH8 */ 2517a234affSTejun Heo { PCI_VDEVICE(INTEL, 0x2824), board_ahci }, /* ICH8 */ 2527a234affSTejun Heo { PCI_VDEVICE(INTEL, 0x2829), board_ahci }, /* ICH8M */ 2537a234affSTejun Heo { PCI_VDEVICE(INTEL, 0x282a), board_ahci }, /* ICH8M */ 2547a234affSTejun Heo { PCI_VDEVICE(INTEL, 0x2922), board_ahci }, /* ICH9 */ 2557a234affSTejun Heo { PCI_VDEVICE(INTEL, 0x2923), board_ahci }, /* ICH9 */ 2567a234affSTejun Heo { PCI_VDEVICE(INTEL, 0x2924), board_ahci }, /* ICH9 */ 2577a234affSTejun Heo { PCI_VDEVICE(INTEL, 0x2925), board_ahci }, /* ICH9 */ 2587a234affSTejun Heo { PCI_VDEVICE(INTEL, 0x2927), board_ahci }, /* ICH9 */ 259ebb82e3cSHans de Goede { PCI_VDEVICE(INTEL, 0x2929), board_ahci_mobile }, /* ICH9M */ 260ebb82e3cSHans de Goede { PCI_VDEVICE(INTEL, 0x292a), board_ahci_mobile }, /* ICH9M */ 261ebb82e3cSHans de Goede { PCI_VDEVICE(INTEL, 0x292b), board_ahci_mobile }, /* ICH9M */ 262ebb82e3cSHans de Goede { PCI_VDEVICE(INTEL, 0x292c), board_ahci_mobile }, /* ICH9M */ 263ebb82e3cSHans de Goede { PCI_VDEVICE(INTEL, 0x292f), board_ahci_mobile }, /* ICH9M */ 2647a234affSTejun Heo { PCI_VDEVICE(INTEL, 0x294d), board_ahci }, /* ICH9 */ 265ebb82e3cSHans de Goede { PCI_VDEVICE(INTEL, 0x294e), board_ahci_mobile }, /* ICH9M */ 266d4155e6fSJason Gaston { PCI_VDEVICE(INTEL, 0x502a), board_ahci }, /* Tolapai */ 267d4155e6fSJason Gaston { PCI_VDEVICE(INTEL, 0x502b), board_ahci }, /* Tolapai */ 26816ad1ad9SJason Gaston { PCI_VDEVICE(INTEL, 0x3a05), board_ahci }, /* ICH10 */ 269b2dde6afSMark Goodwin { PCI_VDEVICE(INTEL, 0x3a22), board_ahci }, /* ICH10 */ 27016ad1ad9SJason Gaston { PCI_VDEVICE(INTEL, 0x3a25), board_ahci }, /* ICH10 */ 271c1f57d9bSDavid Milburn { PCI_VDEVICE(INTEL, 0x3b22), board_ahci }, /* PCH AHCI */ 272c1f57d9bSDavid Milburn { PCI_VDEVICE(INTEL, 0x3b23), board_ahci }, /* PCH AHCI */ 273adcb5308SSeth Heasley { PCI_VDEVICE(INTEL, 0x3b24), board_ahci }, /* PCH RAID */ 2748e48b6b3SSeth Heasley { PCI_VDEVICE(INTEL, 0x3b25), board_ahci }, /* PCH RAID */ 275ebb82e3cSHans de Goede { PCI_VDEVICE(INTEL, 0x3b29), board_ahci_mobile }, /* PCH M AHCI */ 276adcb5308SSeth Heasley { PCI_VDEVICE(INTEL, 0x3b2b), board_ahci }, /* PCH RAID */ 277ebb82e3cSHans de Goede { PCI_VDEVICE(INTEL, 0x3b2c), board_ahci_mobile }, /* PCH M RAID */ 278c1f57d9bSDavid Milburn { PCI_VDEVICE(INTEL, 0x3b2f), board_ahci }, /* PCH AHCI */ 279c312ef17SDan Williams { PCI_VDEVICE(INTEL, 0x19b0), board_ahci_pcs7 }, /* DNV AHCI */ 280c312ef17SDan Williams { PCI_VDEVICE(INTEL, 0x19b1), board_ahci_pcs7 }, /* DNV AHCI */ 281c312ef17SDan Williams { PCI_VDEVICE(INTEL, 0x19b2), board_ahci_pcs7 }, /* DNV AHCI */ 282c312ef17SDan Williams { PCI_VDEVICE(INTEL, 0x19b3), board_ahci_pcs7 }, /* DNV AHCI */ 283c312ef17SDan Williams { PCI_VDEVICE(INTEL, 0x19b4), board_ahci_pcs7 }, /* DNV AHCI */ 284c312ef17SDan Williams { PCI_VDEVICE(INTEL, 0x19b5), board_ahci_pcs7 }, /* DNV AHCI */ 285c312ef17SDan Williams { PCI_VDEVICE(INTEL, 0x19b6), board_ahci_pcs7 }, /* DNV AHCI */ 286c312ef17SDan Williams { PCI_VDEVICE(INTEL, 0x19b7), board_ahci_pcs7 }, /* DNV AHCI */ 287c312ef17SDan Williams { PCI_VDEVICE(INTEL, 0x19bE), board_ahci_pcs7 }, /* DNV AHCI */ 288c312ef17SDan Williams { PCI_VDEVICE(INTEL, 0x19bF), board_ahci_pcs7 }, /* DNV AHCI */ 289c312ef17SDan Williams { PCI_VDEVICE(INTEL, 0x19c0), board_ahci_pcs7 }, /* DNV AHCI */ 290c312ef17SDan Williams { PCI_VDEVICE(INTEL, 0x19c1), board_ahci_pcs7 }, /* DNV AHCI */ 291c312ef17SDan Williams { PCI_VDEVICE(INTEL, 0x19c2), board_ahci_pcs7 }, /* DNV AHCI */ 292c312ef17SDan Williams { PCI_VDEVICE(INTEL, 0x19c3), board_ahci_pcs7 }, /* DNV AHCI */ 293c312ef17SDan Williams { PCI_VDEVICE(INTEL, 0x19c4), board_ahci_pcs7 }, /* DNV AHCI */ 294c312ef17SDan Williams { PCI_VDEVICE(INTEL, 0x19c5), board_ahci_pcs7 }, /* DNV AHCI */ 295c312ef17SDan Williams { PCI_VDEVICE(INTEL, 0x19c6), board_ahci_pcs7 }, /* DNV AHCI */ 296c312ef17SDan Williams { PCI_VDEVICE(INTEL, 0x19c7), board_ahci_pcs7 }, /* DNV AHCI */ 297c312ef17SDan Williams { PCI_VDEVICE(INTEL, 0x19cE), board_ahci_pcs7 }, /* DNV AHCI */ 298c312ef17SDan Williams { PCI_VDEVICE(INTEL, 0x19cF), board_ahci_pcs7 }, /* DNV AHCI */ 2995623cab8SSeth Heasley { PCI_VDEVICE(INTEL, 0x1c02), board_ahci }, /* CPT AHCI */ 300ebb82e3cSHans de Goede { PCI_VDEVICE(INTEL, 0x1c03), board_ahci_mobile }, /* CPT M AHCI */ 3015623cab8SSeth Heasley { PCI_VDEVICE(INTEL, 0x1c04), board_ahci }, /* CPT RAID */ 302ebb82e3cSHans de Goede { PCI_VDEVICE(INTEL, 0x1c05), board_ahci_mobile }, /* CPT M RAID */ 3035623cab8SSeth Heasley { PCI_VDEVICE(INTEL, 0x1c06), board_ahci }, /* CPT RAID */ 3045623cab8SSeth Heasley { PCI_VDEVICE(INTEL, 0x1c07), board_ahci }, /* CPT RAID */ 305992b3fb9SSeth Heasley { PCI_VDEVICE(INTEL, 0x1d02), board_ahci }, /* PBG AHCI */ 306992b3fb9SSeth Heasley { PCI_VDEVICE(INTEL, 0x1d04), board_ahci }, /* PBG RAID */ 307992b3fb9SSeth Heasley { PCI_VDEVICE(INTEL, 0x1d06), board_ahci }, /* PBG RAID */ 30864a3903dSSeth Heasley { PCI_VDEVICE(INTEL, 0x2826), board_ahci }, /* PBG RAID */ 309a4a461a6SSeth Heasley { PCI_VDEVICE(INTEL, 0x2323), board_ahci }, /* DH89xxCC AHCI */ 310181e3ceaSSeth Heasley { PCI_VDEVICE(INTEL, 0x1e02), board_ahci }, /* Panther Point AHCI */ 311ebb82e3cSHans de Goede { PCI_VDEVICE(INTEL, 0x1e03), board_ahci_mobile }, /* Panther M AHCI */ 312181e3ceaSSeth Heasley { PCI_VDEVICE(INTEL, 0x1e04), board_ahci }, /* Panther Point RAID */ 313181e3ceaSSeth Heasley { PCI_VDEVICE(INTEL, 0x1e05), board_ahci }, /* Panther Point RAID */ 314181e3ceaSSeth Heasley { PCI_VDEVICE(INTEL, 0x1e06), board_ahci }, /* Panther Point RAID */ 315ebb82e3cSHans de Goede { PCI_VDEVICE(INTEL, 0x1e07), board_ahci_mobile }, /* Panther M RAID */ 3162cab7a4cSSeth Heasley { PCI_VDEVICE(INTEL, 0x1e0e), board_ahci }, /* Panther Point RAID */ 317ea4ace66SSeth Heasley { PCI_VDEVICE(INTEL, 0x8c02), board_ahci }, /* Lynx Point AHCI */ 318ebb82e3cSHans de Goede { PCI_VDEVICE(INTEL, 0x8c03), board_ahci_mobile }, /* Lynx M AHCI */ 319ea4ace66SSeth Heasley { PCI_VDEVICE(INTEL, 0x8c04), board_ahci }, /* Lynx Point RAID */ 320ebb82e3cSHans de Goede { PCI_VDEVICE(INTEL, 0x8c05), board_ahci_mobile }, /* Lynx M RAID */ 321ea4ace66SSeth Heasley { PCI_VDEVICE(INTEL, 0x8c06), board_ahci }, /* Lynx Point RAID */ 322ebb82e3cSHans de Goede { PCI_VDEVICE(INTEL, 0x8c07), board_ahci_mobile }, /* Lynx M RAID */ 323ea4ace66SSeth Heasley { PCI_VDEVICE(INTEL, 0x8c0e), board_ahci }, /* Lynx Point RAID */ 324ebb82e3cSHans de Goede { PCI_VDEVICE(INTEL, 0x8c0f), board_ahci_mobile }, /* Lynx M RAID */ 325ebb82e3cSHans de Goede { PCI_VDEVICE(INTEL, 0x9c02), board_ahci_mobile }, /* Lynx LP AHCI */ 326ebb82e3cSHans de Goede { PCI_VDEVICE(INTEL, 0x9c03), board_ahci_mobile }, /* Lynx LP AHCI */ 327ebb82e3cSHans de Goede { PCI_VDEVICE(INTEL, 0x9c04), board_ahci_mobile }, /* Lynx LP RAID */ 328ebb82e3cSHans de Goede { PCI_VDEVICE(INTEL, 0x9c05), board_ahci_mobile }, /* Lynx LP RAID */ 329ebb82e3cSHans de Goede { PCI_VDEVICE(INTEL, 0x9c06), board_ahci_mobile }, /* Lynx LP RAID */ 330ebb82e3cSHans de Goede { PCI_VDEVICE(INTEL, 0x9c07), board_ahci_mobile }, /* Lynx LP RAID */ 331ebb82e3cSHans de Goede { PCI_VDEVICE(INTEL, 0x9c0e), board_ahci_mobile }, /* Lynx LP RAID */ 332ebb82e3cSHans de Goede { PCI_VDEVICE(INTEL, 0x9c0f), board_ahci_mobile }, /* Lynx LP RAID */ 3334544e403SMika Westerberg { PCI_VDEVICE(INTEL, 0x9dd3), board_ahci_mobile }, /* Cannon Lake PCH-LP AHCI */ 33429e674ddSSeth Heasley { PCI_VDEVICE(INTEL, 0x1f22), board_ahci }, /* Avoton AHCI */ 33529e674ddSSeth Heasley { PCI_VDEVICE(INTEL, 0x1f23), board_ahci }, /* Avoton AHCI */ 33629e674ddSSeth Heasley { PCI_VDEVICE(INTEL, 0x1f24), board_ahci }, /* Avoton RAID */ 33729e674ddSSeth Heasley { PCI_VDEVICE(INTEL, 0x1f25), board_ahci }, /* Avoton RAID */ 33829e674ddSSeth Heasley { PCI_VDEVICE(INTEL, 0x1f26), board_ahci }, /* Avoton RAID */ 33929e674ddSSeth Heasley { PCI_VDEVICE(INTEL, 0x1f27), board_ahci }, /* Avoton RAID */ 34029e674ddSSeth Heasley { PCI_VDEVICE(INTEL, 0x1f2e), board_ahci }, /* Avoton RAID */ 34129e674ddSSeth Heasley { PCI_VDEVICE(INTEL, 0x1f2f), board_ahci }, /* Avoton RAID */ 342dbfe8ef5SDan Williams { PCI_VDEVICE(INTEL, 0x1f32), board_ahci_avn }, /* Avoton AHCI */ 343dbfe8ef5SDan Williams { PCI_VDEVICE(INTEL, 0x1f33), board_ahci_avn }, /* Avoton AHCI */ 344dbfe8ef5SDan Williams { PCI_VDEVICE(INTEL, 0x1f34), board_ahci_avn }, /* Avoton RAID */ 345dbfe8ef5SDan Williams { PCI_VDEVICE(INTEL, 0x1f35), board_ahci_avn }, /* Avoton RAID */ 346dbfe8ef5SDan Williams { PCI_VDEVICE(INTEL, 0x1f36), board_ahci_avn }, /* Avoton RAID */ 347dbfe8ef5SDan Williams { PCI_VDEVICE(INTEL, 0x1f37), board_ahci_avn }, /* Avoton RAID */ 348dbfe8ef5SDan Williams { PCI_VDEVICE(INTEL, 0x1f3e), board_ahci_avn }, /* Avoton RAID */ 349dbfe8ef5SDan Williams { PCI_VDEVICE(INTEL, 0x1f3f), board_ahci_avn }, /* Avoton RAID */ 350efda332cSJames Ralston { PCI_VDEVICE(INTEL, 0x2823), board_ahci }, /* Wellsburg RAID */ 351efda332cSJames Ralston { PCI_VDEVICE(INTEL, 0x2827), board_ahci }, /* Wellsburg RAID */ 352151743fdSJames Ralston { PCI_VDEVICE(INTEL, 0x8d02), board_ahci }, /* Wellsburg AHCI */ 353151743fdSJames Ralston { PCI_VDEVICE(INTEL, 0x8d04), board_ahci }, /* Wellsburg RAID */ 354151743fdSJames Ralston { PCI_VDEVICE(INTEL, 0x8d06), board_ahci }, /* Wellsburg RAID */ 355151743fdSJames Ralston { PCI_VDEVICE(INTEL, 0x8d0e), board_ahci }, /* Wellsburg RAID */ 356151743fdSJames Ralston { PCI_VDEVICE(INTEL, 0x8d62), board_ahci }, /* Wellsburg AHCI */ 357151743fdSJames Ralston { PCI_VDEVICE(INTEL, 0x8d64), board_ahci }, /* Wellsburg RAID */ 358151743fdSJames Ralston { PCI_VDEVICE(INTEL, 0x8d66), board_ahci }, /* Wellsburg RAID */ 359151743fdSJames Ralston { PCI_VDEVICE(INTEL, 0x8d6e), board_ahci }, /* Wellsburg RAID */ 3601cfc7df3SSeth Heasley { PCI_VDEVICE(INTEL, 0x23a3), board_ahci }, /* Coleto Creek AHCI */ 361ebb82e3cSHans de Goede { PCI_VDEVICE(INTEL, 0x9c83), board_ahci_mobile }, /* Wildcat LP AHCI */ 362ebb82e3cSHans de Goede { PCI_VDEVICE(INTEL, 0x9c85), board_ahci_mobile }, /* Wildcat LP RAID */ 363ebb82e3cSHans de Goede { PCI_VDEVICE(INTEL, 0x9c87), board_ahci_mobile }, /* Wildcat LP RAID */ 364ebb82e3cSHans de Goede { PCI_VDEVICE(INTEL, 0x9c8f), board_ahci_mobile }, /* Wildcat LP RAID */ 3651b071a09SJames Ralston { PCI_VDEVICE(INTEL, 0x8c82), board_ahci }, /* 9 Series AHCI */ 366ebb82e3cSHans de Goede { PCI_VDEVICE(INTEL, 0x8c83), board_ahci_mobile }, /* 9 Series M AHCI */ 3671b071a09SJames Ralston { PCI_VDEVICE(INTEL, 0x8c84), board_ahci }, /* 9 Series RAID */ 368ebb82e3cSHans de Goede { PCI_VDEVICE(INTEL, 0x8c85), board_ahci_mobile }, /* 9 Series M RAID */ 3691b071a09SJames Ralston { PCI_VDEVICE(INTEL, 0x8c86), board_ahci }, /* 9 Series RAID */ 370ebb82e3cSHans de Goede { PCI_VDEVICE(INTEL, 0x8c87), board_ahci_mobile }, /* 9 Series M RAID */ 3711b071a09SJames Ralston { PCI_VDEVICE(INTEL, 0x8c8e), board_ahci }, /* 9 Series RAID */ 372ebb82e3cSHans de Goede { PCI_VDEVICE(INTEL, 0x8c8f), board_ahci_mobile }, /* 9 Series M RAID */ 373ebb82e3cSHans de Goede { PCI_VDEVICE(INTEL, 0x9d03), board_ahci_mobile }, /* Sunrise LP AHCI */ 374ebb82e3cSHans de Goede { PCI_VDEVICE(INTEL, 0x9d05), board_ahci_mobile }, /* Sunrise LP RAID */ 375ebb82e3cSHans de Goede { PCI_VDEVICE(INTEL, 0x9d07), board_ahci_mobile }, /* Sunrise LP RAID */ 376c5967b79SCharles_Rose@Dell.com { PCI_VDEVICE(INTEL, 0xa102), board_ahci }, /* Sunrise Point-H AHCI */ 377ebb82e3cSHans de Goede { PCI_VDEVICE(INTEL, 0xa103), board_ahci_mobile }, /* Sunrise M AHCI */ 378690000b9SJames Ralston { PCI_VDEVICE(INTEL, 0xa105), board_ahci }, /* Sunrise Point-H RAID */ 379c5967b79SCharles_Rose@Dell.com { PCI_VDEVICE(INTEL, 0xa106), board_ahci }, /* Sunrise Point-H RAID */ 380ebb82e3cSHans de Goede { PCI_VDEVICE(INTEL, 0xa107), board_ahci_mobile }, /* Sunrise M RAID */ 381690000b9SJames Ralston { PCI_VDEVICE(INTEL, 0xa10f), board_ahci }, /* Sunrise Point-H RAID */ 3824d92f009SAlexandra Yates { PCI_VDEVICE(INTEL, 0x2822), board_ahci }, /* Lewisburg RAID*/ 383f5bdd66cSAlexandra Yates { PCI_VDEVICE(INTEL, 0x2823), board_ahci }, /* Lewisburg AHCI*/ 3844d92f009SAlexandra Yates { PCI_VDEVICE(INTEL, 0x2826), board_ahci }, /* Lewisburg RAID*/ 385f5bdd66cSAlexandra Yates { PCI_VDEVICE(INTEL, 0x2827), board_ahci }, /* Lewisburg RAID*/ 3864d92f009SAlexandra Yates { PCI_VDEVICE(INTEL, 0xa182), board_ahci }, /* Lewisburg AHCI*/ 3874d92f009SAlexandra Yates { PCI_VDEVICE(INTEL, 0xa186), board_ahci }, /* Lewisburg RAID*/ 388f5bdd66cSAlexandra Yates { PCI_VDEVICE(INTEL, 0xa1d2), board_ahci }, /* Lewisburg RAID*/ 389f5bdd66cSAlexandra Yates { PCI_VDEVICE(INTEL, 0xa1d6), board_ahci }, /* Lewisburg RAID*/ 3904d92f009SAlexandra Yates { PCI_VDEVICE(INTEL, 0xa202), board_ahci }, /* Lewisburg AHCI*/ 3914d92f009SAlexandra Yates { PCI_VDEVICE(INTEL, 0xa206), board_ahci }, /* Lewisburg RAID*/ 392f5bdd66cSAlexandra Yates { PCI_VDEVICE(INTEL, 0xa252), board_ahci }, /* Lewisburg RAID*/ 393f5bdd66cSAlexandra Yates { PCI_VDEVICE(INTEL, 0xa256), board_ahci }, /* Lewisburg RAID*/ 394f919dde0SMika Westerberg { PCI_VDEVICE(INTEL, 0xa356), board_ahci }, /* Cannon Lake PCH-H RAID */ 395ebb82e3cSHans de Goede { PCI_VDEVICE(INTEL, 0x0f22), board_ahci_mobile }, /* Bay Trail AHCI */ 396ebb82e3cSHans de Goede { PCI_VDEVICE(INTEL, 0x0f23), board_ahci_mobile }, /* Bay Trail AHCI */ 397ebb82e3cSHans de Goede { PCI_VDEVICE(INTEL, 0x22a3), board_ahci_mobile }, /* Cherry Tr. AHCI */ 398ebb82e3cSHans de Goede { PCI_VDEVICE(INTEL, 0x5ae3), board_ahci_mobile }, /* ApolloLake AHCI */ 399ba445791SMika Westerberg { PCI_VDEVICE(INTEL, 0x34d3), board_ahci_mobile }, /* Ice Lake LP AHCI */ 400c6fd2807SJeff Garzik 401e34bb370STejun Heo /* JMicron 360/1/3/5/6, match class to avoid IDE function */ 402e34bb370STejun Heo { PCI_VENDOR_ID_JMICRON, PCI_ANY_ID, PCI_ANY_ID, PCI_ANY_ID, 403e34bb370STejun Heo PCI_CLASS_STORAGE_SATA_AHCI, 0xffffff, board_ahci_ign_iferr }, 4041fefb8fdSBen Hutchings /* JMicron 362B and 362C have an AHCI function with IDE class code */ 4051fefb8fdSBen Hutchings { PCI_VDEVICE(JMICRON, 0x2362), board_ahci_ign_iferr }, 4061fefb8fdSBen Hutchings { PCI_VDEVICE(JMICRON, 0x236f), board_ahci_ign_iferr }, 40791f15fb3SZhang Rui /* May need to update quirk_jmicron_async_suspend() for additions */ 408c6fd2807SJeff Garzik 409c6fd2807SJeff Garzik /* ATI */ 410c65ec1c2SConke Hu { PCI_VDEVICE(ATI, 0x4380), board_ahci_sb600 }, /* ATI SB600 */ 411e39fc8c9SShane Huang { PCI_VDEVICE(ATI, 0x4390), board_ahci_sb700 }, /* ATI SB700/800 */ 412e39fc8c9SShane Huang { PCI_VDEVICE(ATI, 0x4391), board_ahci_sb700 }, /* ATI SB700/800 */ 413e39fc8c9SShane Huang { PCI_VDEVICE(ATI, 0x4392), board_ahci_sb700 }, /* ATI SB700/800 */ 414e39fc8c9SShane Huang { PCI_VDEVICE(ATI, 0x4393), board_ahci_sb700 }, /* ATI SB700/800 */ 415e39fc8c9SShane Huang { PCI_VDEVICE(ATI, 0x4394), board_ahci_sb700 }, /* ATI SB700/800 */ 416e39fc8c9SShane Huang { PCI_VDEVICE(ATI, 0x4395), board_ahci_sb700 }, /* ATI SB700/800 */ 417c6fd2807SJeff Garzik 418e2dd90b1SShane Huang /* AMD */ 4195deab536SShane Huang { PCI_VDEVICE(AMD, 0x7800), board_ahci }, /* AMD Hudson-2 */ 420fafe5c3dSShane Huang { PCI_VDEVICE(AMD, 0x7900), board_ahci }, /* AMD CZ */ 421e2dd90b1SShane Huang /* AMD is using RAID class only for ahci controllers */ 422e2dd90b1SShane Huang { PCI_VENDOR_ID_AMD, PCI_ANY_ID, PCI_ANY_ID, PCI_ANY_ID, 423e2dd90b1SShane Huang PCI_CLASS_STORAGE_RAID << 8, 0xffffff, board_ahci }, 424e2dd90b1SShane Huang 425c6fd2807SJeff Garzik /* VIA */ 42654bb3a94SJeff Garzik { PCI_VDEVICE(VIA, 0x3349), board_ahci_vt8251 }, /* VIA VT8251 */ 427bf335542STejun Heo { PCI_VDEVICE(VIA, 0x6287), board_ahci_vt8251 }, /* VIA VT8251 */ 428c6fd2807SJeff Garzik 429c6fd2807SJeff Garzik /* NVIDIA */ 430e297d99eSTejun Heo { PCI_VDEVICE(NVIDIA, 0x044c), board_ahci_mcp65 }, /* MCP65 */ 431e297d99eSTejun Heo { PCI_VDEVICE(NVIDIA, 0x044d), board_ahci_mcp65 }, /* MCP65 */ 432e297d99eSTejun Heo { PCI_VDEVICE(NVIDIA, 0x044e), board_ahci_mcp65 }, /* MCP65 */ 433e297d99eSTejun Heo { PCI_VDEVICE(NVIDIA, 0x044f), board_ahci_mcp65 }, /* MCP65 */ 434e297d99eSTejun Heo { PCI_VDEVICE(NVIDIA, 0x045c), board_ahci_mcp65 }, /* MCP65 */ 435e297d99eSTejun Heo { PCI_VDEVICE(NVIDIA, 0x045d), board_ahci_mcp65 }, /* MCP65 */ 436e297d99eSTejun Heo { PCI_VDEVICE(NVIDIA, 0x045e), board_ahci_mcp65 }, /* MCP65 */ 437e297d99eSTejun Heo { PCI_VDEVICE(NVIDIA, 0x045f), board_ahci_mcp65 }, /* MCP65 */ 438441577efSTejun Heo { PCI_VDEVICE(NVIDIA, 0x0550), board_ahci_mcp67 }, /* MCP67 */ 439441577efSTejun Heo { PCI_VDEVICE(NVIDIA, 0x0551), board_ahci_mcp67 }, /* MCP67 */ 440441577efSTejun Heo { PCI_VDEVICE(NVIDIA, 0x0552), board_ahci_mcp67 }, /* MCP67 */ 441441577efSTejun Heo { PCI_VDEVICE(NVIDIA, 0x0553), board_ahci_mcp67 }, /* MCP67 */ 442441577efSTejun Heo { PCI_VDEVICE(NVIDIA, 0x0554), board_ahci_mcp67 }, /* MCP67 */ 443441577efSTejun Heo { PCI_VDEVICE(NVIDIA, 0x0555), board_ahci_mcp67 }, /* MCP67 */ 444441577efSTejun Heo { PCI_VDEVICE(NVIDIA, 0x0556), board_ahci_mcp67 }, /* MCP67 */ 445441577efSTejun Heo { PCI_VDEVICE(NVIDIA, 0x0557), board_ahci_mcp67 }, /* MCP67 */ 446441577efSTejun Heo { PCI_VDEVICE(NVIDIA, 0x0558), board_ahci_mcp67 }, /* MCP67 */ 447441577efSTejun Heo { PCI_VDEVICE(NVIDIA, 0x0559), board_ahci_mcp67 }, /* MCP67 */ 448441577efSTejun Heo { PCI_VDEVICE(NVIDIA, 0x055a), board_ahci_mcp67 }, /* MCP67 */ 449441577efSTejun Heo { PCI_VDEVICE(NVIDIA, 0x055b), board_ahci_mcp67 }, /* MCP67 */ 450441577efSTejun Heo { PCI_VDEVICE(NVIDIA, 0x0580), board_ahci_mcp_linux }, /* Linux ID */ 451441577efSTejun Heo { PCI_VDEVICE(NVIDIA, 0x0581), board_ahci_mcp_linux }, /* Linux ID */ 452441577efSTejun Heo { PCI_VDEVICE(NVIDIA, 0x0582), board_ahci_mcp_linux }, /* Linux ID */ 453441577efSTejun Heo { PCI_VDEVICE(NVIDIA, 0x0583), board_ahci_mcp_linux }, /* Linux ID */ 454441577efSTejun Heo { PCI_VDEVICE(NVIDIA, 0x0584), board_ahci_mcp_linux }, /* Linux ID */ 455441577efSTejun Heo { PCI_VDEVICE(NVIDIA, 0x0585), board_ahci_mcp_linux }, /* Linux ID */ 456441577efSTejun Heo { PCI_VDEVICE(NVIDIA, 0x0586), board_ahci_mcp_linux }, /* Linux ID */ 457441577efSTejun Heo { PCI_VDEVICE(NVIDIA, 0x0587), board_ahci_mcp_linux }, /* Linux ID */ 458441577efSTejun Heo { PCI_VDEVICE(NVIDIA, 0x0588), board_ahci_mcp_linux }, /* Linux ID */ 459441577efSTejun Heo { PCI_VDEVICE(NVIDIA, 0x0589), board_ahci_mcp_linux }, /* Linux ID */ 460441577efSTejun Heo { PCI_VDEVICE(NVIDIA, 0x058a), board_ahci_mcp_linux }, /* Linux ID */ 461441577efSTejun Heo { PCI_VDEVICE(NVIDIA, 0x058b), board_ahci_mcp_linux }, /* Linux ID */ 462441577efSTejun Heo { PCI_VDEVICE(NVIDIA, 0x058c), board_ahci_mcp_linux }, /* Linux ID */ 463441577efSTejun Heo { PCI_VDEVICE(NVIDIA, 0x058d), board_ahci_mcp_linux }, /* Linux ID */ 464441577efSTejun Heo { PCI_VDEVICE(NVIDIA, 0x058e), board_ahci_mcp_linux }, /* Linux ID */ 465441577efSTejun Heo { PCI_VDEVICE(NVIDIA, 0x058f), board_ahci_mcp_linux }, /* Linux ID */ 466441577efSTejun Heo { PCI_VDEVICE(NVIDIA, 0x07f0), board_ahci_mcp73 }, /* MCP73 */ 467441577efSTejun Heo { PCI_VDEVICE(NVIDIA, 0x07f1), board_ahci_mcp73 }, /* MCP73 */ 468441577efSTejun Heo { PCI_VDEVICE(NVIDIA, 0x07f2), board_ahci_mcp73 }, /* MCP73 */ 469441577efSTejun Heo { PCI_VDEVICE(NVIDIA, 0x07f3), board_ahci_mcp73 }, /* MCP73 */ 470441577efSTejun Heo { PCI_VDEVICE(NVIDIA, 0x07f4), board_ahci_mcp73 }, /* MCP73 */ 471441577efSTejun Heo { PCI_VDEVICE(NVIDIA, 0x07f5), board_ahci_mcp73 }, /* MCP73 */ 472441577efSTejun Heo { PCI_VDEVICE(NVIDIA, 0x07f6), board_ahci_mcp73 }, /* MCP73 */ 473441577efSTejun Heo { PCI_VDEVICE(NVIDIA, 0x07f7), board_ahci_mcp73 }, /* MCP73 */ 474441577efSTejun Heo { PCI_VDEVICE(NVIDIA, 0x07f8), board_ahci_mcp73 }, /* MCP73 */ 475441577efSTejun Heo { PCI_VDEVICE(NVIDIA, 0x07f9), board_ahci_mcp73 }, /* MCP73 */ 476441577efSTejun Heo { PCI_VDEVICE(NVIDIA, 0x07fa), board_ahci_mcp73 }, /* MCP73 */ 477441577efSTejun Heo { PCI_VDEVICE(NVIDIA, 0x07fb), board_ahci_mcp73 }, /* MCP73 */ 478441577efSTejun Heo { PCI_VDEVICE(NVIDIA, 0x0ad0), board_ahci_mcp77 }, /* MCP77 */ 479441577efSTejun Heo { PCI_VDEVICE(NVIDIA, 0x0ad1), board_ahci_mcp77 }, /* MCP77 */ 480441577efSTejun Heo { PCI_VDEVICE(NVIDIA, 0x0ad2), board_ahci_mcp77 }, /* MCP77 */ 481441577efSTejun Heo { PCI_VDEVICE(NVIDIA, 0x0ad3), board_ahci_mcp77 }, /* MCP77 */ 482441577efSTejun Heo { PCI_VDEVICE(NVIDIA, 0x0ad4), board_ahci_mcp77 }, /* MCP77 */ 483441577efSTejun Heo { PCI_VDEVICE(NVIDIA, 0x0ad5), board_ahci_mcp77 }, /* MCP77 */ 484441577efSTejun Heo { PCI_VDEVICE(NVIDIA, 0x0ad6), board_ahci_mcp77 }, /* MCP77 */ 485441577efSTejun Heo { PCI_VDEVICE(NVIDIA, 0x0ad7), board_ahci_mcp77 }, /* MCP77 */ 486441577efSTejun Heo { PCI_VDEVICE(NVIDIA, 0x0ad8), board_ahci_mcp77 }, /* MCP77 */ 487441577efSTejun Heo { PCI_VDEVICE(NVIDIA, 0x0ad9), board_ahci_mcp77 }, /* MCP77 */ 488441577efSTejun Heo { PCI_VDEVICE(NVIDIA, 0x0ada), board_ahci_mcp77 }, /* MCP77 */ 489441577efSTejun Heo { PCI_VDEVICE(NVIDIA, 0x0adb), board_ahci_mcp77 }, /* MCP77 */ 490441577efSTejun Heo { PCI_VDEVICE(NVIDIA, 0x0ab4), board_ahci_mcp79 }, /* MCP79 */ 491441577efSTejun Heo { PCI_VDEVICE(NVIDIA, 0x0ab5), board_ahci_mcp79 }, /* MCP79 */ 492441577efSTejun Heo { PCI_VDEVICE(NVIDIA, 0x0ab6), board_ahci_mcp79 }, /* MCP79 */ 493441577efSTejun Heo { PCI_VDEVICE(NVIDIA, 0x0ab7), board_ahci_mcp79 }, /* MCP79 */ 494441577efSTejun Heo { PCI_VDEVICE(NVIDIA, 0x0ab8), board_ahci_mcp79 }, /* MCP79 */ 495441577efSTejun Heo { PCI_VDEVICE(NVIDIA, 0x0ab9), board_ahci_mcp79 }, /* MCP79 */ 496441577efSTejun Heo { PCI_VDEVICE(NVIDIA, 0x0aba), board_ahci_mcp79 }, /* MCP79 */ 497441577efSTejun Heo { PCI_VDEVICE(NVIDIA, 0x0abb), board_ahci_mcp79 }, /* MCP79 */ 498441577efSTejun Heo { PCI_VDEVICE(NVIDIA, 0x0abc), board_ahci_mcp79 }, /* MCP79 */ 499441577efSTejun Heo { PCI_VDEVICE(NVIDIA, 0x0abd), board_ahci_mcp79 }, /* MCP79 */ 500441577efSTejun Heo { PCI_VDEVICE(NVIDIA, 0x0abe), board_ahci_mcp79 }, /* MCP79 */ 501441577efSTejun Heo { PCI_VDEVICE(NVIDIA, 0x0abf), board_ahci_mcp79 }, /* MCP79 */ 502441577efSTejun Heo { PCI_VDEVICE(NVIDIA, 0x0d84), board_ahci_mcp89 }, /* MCP89 */ 503441577efSTejun Heo { PCI_VDEVICE(NVIDIA, 0x0d85), board_ahci_mcp89 }, /* MCP89 */ 504441577efSTejun Heo { PCI_VDEVICE(NVIDIA, 0x0d86), board_ahci_mcp89 }, /* MCP89 */ 505441577efSTejun Heo { PCI_VDEVICE(NVIDIA, 0x0d87), board_ahci_mcp89 }, /* MCP89 */ 506441577efSTejun Heo { PCI_VDEVICE(NVIDIA, 0x0d88), board_ahci_mcp89 }, /* MCP89 */ 507441577efSTejun Heo { PCI_VDEVICE(NVIDIA, 0x0d89), board_ahci_mcp89 }, /* MCP89 */ 508441577efSTejun Heo { PCI_VDEVICE(NVIDIA, 0x0d8a), board_ahci_mcp89 }, /* MCP89 */ 509441577efSTejun Heo { PCI_VDEVICE(NVIDIA, 0x0d8b), board_ahci_mcp89 }, /* MCP89 */ 510441577efSTejun Heo { PCI_VDEVICE(NVIDIA, 0x0d8c), board_ahci_mcp89 }, /* MCP89 */ 511441577efSTejun Heo { PCI_VDEVICE(NVIDIA, 0x0d8d), board_ahci_mcp89 }, /* MCP89 */ 512441577efSTejun Heo { PCI_VDEVICE(NVIDIA, 0x0d8e), board_ahci_mcp89 }, /* MCP89 */ 513441577efSTejun Heo { PCI_VDEVICE(NVIDIA, 0x0d8f), board_ahci_mcp89 }, /* MCP89 */ 514c6fd2807SJeff Garzik 515c6fd2807SJeff Garzik /* SiS */ 51620e2de4aSTejun Heo { PCI_VDEVICE(SI, 0x1184), board_ahci }, /* SiS 966 */ 51720e2de4aSTejun Heo { PCI_VDEVICE(SI, 0x1185), board_ahci }, /* SiS 968 */ 51820e2de4aSTejun Heo { PCI_VDEVICE(SI, 0x0186), board_ahci }, /* SiS 968 */ 519c6fd2807SJeff Garzik 520318893e1SAlessandro Rubini /* ST Microelectronics */ 521318893e1SAlessandro Rubini { PCI_VDEVICE(STMICRO, 0xCC06), board_ahci }, /* ST ConneXt */ 522318893e1SAlessandro Rubini 523cd70c266SJeff Garzik /* Marvell */ 524cd70c266SJeff Garzik { PCI_VDEVICE(MARVELL, 0x6145), board_ahci_mv }, /* 6145 */ 525c40e7cb8SJose Alberto Reguero { PCI_VDEVICE(MARVELL, 0x6121), board_ahci_mv }, /* 6121 */ 52669fd3157SMyron Stowe { PCI_DEVICE(PCI_VENDOR_ID_MARVELL_EXT, 0x9123), 52710aca06cSAnssi Hannula .class = PCI_CLASS_STORAGE_SATA_AHCI, 52810aca06cSAnssi Hannula .class_mask = 0xffffff, 5295f173107STejun Heo .driver_data = board_ahci_yes_fbs }, /* 88se9128 */ 53069fd3157SMyron Stowe { PCI_DEVICE(PCI_VENDOR_ID_MARVELL_EXT, 0x9125), 531467b41c6SPer Jessen .driver_data = board_ahci_yes_fbs }, /* 88se9125 */ 532e098f5cbSSimon Guinot { PCI_DEVICE_SUB(PCI_VENDOR_ID_MARVELL_EXT, 0x9178, 533e098f5cbSSimon Guinot PCI_VENDOR_ID_MARVELL_EXT, 0x9170), 534e098f5cbSSimon Guinot .driver_data = board_ahci_yes_fbs }, /* 88se9170 */ 53569fd3157SMyron Stowe { PCI_DEVICE(PCI_VENDOR_ID_MARVELL_EXT, 0x917a), 536642d8925SMatt Johnson .driver_data = board_ahci_yes_fbs }, /* 88se9172 */ 537fcce9a35SGeorge Spelvin { PCI_DEVICE(PCI_VENDOR_ID_MARVELL_EXT, 0x9172), 538c5edfff9SMurali Karicheri .driver_data = board_ahci_yes_fbs }, /* 88se9182 */ 539c5edfff9SMurali Karicheri { PCI_DEVICE(PCI_VENDOR_ID_MARVELL_EXT, 0x9182), 540fcce9a35SGeorge Spelvin .driver_data = board_ahci_yes_fbs }, /* 88se9172 */ 54169fd3157SMyron Stowe { PCI_DEVICE(PCI_VENDOR_ID_MARVELL_EXT, 0x9192), 54217c60c6bSAlan Cox .driver_data = board_ahci_yes_fbs }, /* 88se9172 on some Gigabyte */ 543754a292fSAndreas Schrägle { PCI_DEVICE(PCI_VENDOR_ID_MARVELL_EXT, 0x91a0), 544754a292fSAndreas Schrägle .driver_data = board_ahci_yes_fbs }, 545a40cf3f3SJohannes Thumshirn { PCI_DEVICE(PCI_VENDOR_ID_MARVELL_EXT, 0x91a2), /* 88se91a2 */ 546a40cf3f3SJohannes Thumshirn .driver_data = board_ahci_yes_fbs }, 54769fd3157SMyron Stowe { PCI_DEVICE(PCI_VENDOR_ID_MARVELL_EXT, 0x91a3), 54850be5e36STejun Heo .driver_data = board_ahci_yes_fbs }, 5496d5278a6SSamir Benmendil { PCI_DEVICE(PCI_VENDOR_ID_MARVELL_EXT, 0x9230), 5506d5278a6SSamir Benmendil .driver_data = board_ahci_yes_fbs }, 55128b2182dSHans de Goede { PCI_DEVICE(PCI_VENDOR_ID_TTI, 0x0642), /* highpoint rocketraid 642L */ 55228b2182dSHans de Goede .driver_data = board_ahci_yes_fbs }, 55328b2182dSHans de Goede { PCI_DEVICE(PCI_VENDOR_ID_TTI, 0x0645), /* highpoint rocketraid 644L */ 554d2518365SJérôme Carretero .driver_data = board_ahci_yes_fbs }, 555cd70c266SJeff Garzik 556c77a036bSMark Nelson /* Promise */ 557c77a036bSMark Nelson { PCI_VDEVICE(PROMISE, 0x3f20), board_ahci }, /* PDC42819 */ 558b32bfc06SRomain Degez { PCI_VDEVICE(PROMISE, 0x3781), board_ahci }, /* FastTrak TX8660 ahci-mode */ 559c77a036bSMark Nelson 560c9703765SKeng-Yu Lin /* Asmedia */ 5617b4f6ecaSAlan Cox { PCI_VDEVICE(ASMEDIA, 0x0601), board_ahci }, /* ASM1060 */ 5627b4f6ecaSAlan Cox { PCI_VDEVICE(ASMEDIA, 0x0602), board_ahci }, /* ASM1060 */ 5637b4f6ecaSAlan Cox { PCI_VDEVICE(ASMEDIA, 0x0611), board_ahci }, /* ASM1061 */ 5647b4f6ecaSAlan Cox { PCI_VDEVICE(ASMEDIA, 0x0612), board_ahci }, /* ASM1062 */ 5650ce968f3SShawn Lin { PCI_VDEVICE(ASMEDIA, 0x0621), board_ahci }, /* ASM1061R */ 5660ce968f3SShawn Lin { PCI_VDEVICE(ASMEDIA, 0x0622), board_ahci }, /* ASM1062R */ 567c9703765SKeng-Yu Lin 56867809f85SLevente Kurusa /* 56966a7cbc3STejun Heo * Samsung SSDs found on some macbooks. NCQ times out if MSI is 57066a7cbc3STejun Heo * enabled. https://bugzilla.kernel.org/show_bug.cgi?id=60731 57167809f85SLevente Kurusa */ 57266a7cbc3STejun Heo { PCI_VDEVICE(SAMSUNG, 0x1600), board_ahci_nomsi }, 5732b21ef0aSTejun Heo { PCI_VDEVICE(SAMSUNG, 0xa800), board_ahci_nomsi }, 57467809f85SLevente Kurusa 5757f9c9f8eSHugh Daschbach /* Enmotus */ 5767f9c9f8eSHugh Daschbach { PCI_DEVICE(0x1c44, 0x8000), board_ahci }, 5777f9c9f8eSHugh Daschbach 578415ae2b5SJeff Garzik /* Generic, PCI class code for AHCI */ 579415ae2b5SJeff Garzik { PCI_ANY_ID, PCI_ANY_ID, PCI_ANY_ID, PCI_ANY_ID, 580c9f89475SConke Hu PCI_CLASS_STORAGE_SATA_AHCI, 0xffffff, board_ahci }, 581415ae2b5SJeff Garzik 582c6fd2807SJeff Garzik { } /* terminate list */ 583c6fd2807SJeff Garzik }; 584c6fd2807SJeff Garzik 585f1d848f9SMika Westerberg static const struct dev_pm_ops ahci_pci_pm_ops = { 586f1d848f9SMika Westerberg SET_SYSTEM_SLEEP_PM_OPS(ahci_pci_device_suspend, ahci_pci_device_resume) 58702e53293SMika Westerberg SET_RUNTIME_PM_OPS(ahci_pci_device_runtime_suspend, 58802e53293SMika Westerberg ahci_pci_device_runtime_resume, NULL) 589f1d848f9SMika Westerberg }; 590c6fd2807SJeff Garzik 591c6fd2807SJeff Garzik static struct pci_driver ahci_pci_driver = { 592c6fd2807SJeff Garzik .name = DRV_NAME, 593c6fd2807SJeff Garzik .id_table = ahci_pci_tbl, 594c6fd2807SJeff Garzik .probe = ahci_init_one, 59502e53293SMika Westerberg .remove = ahci_remove_one, 596f1d848f9SMika Westerberg .driver = { 597f1d848f9SMika Westerberg .pm = &ahci_pci_pm_ops, 598f1d848f9SMika Westerberg }, 599c6fd2807SJeff Garzik }; 600c6fd2807SJeff Garzik 6015219d653SJavier Martinez Canillas #if IS_ENABLED(CONFIG_PATA_MARVELL) 6025b66c829SAlan Cox static int marvell_enable; 6035b66c829SAlan Cox #else 6045b66c829SAlan Cox static int marvell_enable = 1; 6055b66c829SAlan Cox #endif 6065b66c829SAlan Cox module_param(marvell_enable, int, 0644); 6075b66c829SAlan Cox MODULE_PARM_DESC(marvell_enable, "Marvell SATA via AHCI (1 = enabled)"); 6085b66c829SAlan Cox 609b1a9585cSSrinivas Pandruvada static int mobile_lpm_policy = -1; 610ebb82e3cSHans de Goede module_param(mobile_lpm_policy, int, 0644); 611ebb82e3cSHans de Goede MODULE_PARM_DESC(mobile_lpm_policy, "Default LPM policy for mobile chipsets"); 6125b66c829SAlan Cox 613394d6e53SAnton Vorontsov static void ahci_pci_save_initial_config(struct pci_dev *pdev, 614394d6e53SAnton Vorontsov struct ahci_host_priv *hpriv) 615394d6e53SAnton Vorontsov { 616394d6e53SAnton Vorontsov if (pdev->vendor == PCI_VENDOR_ID_JMICRON && pdev->device == 0x2361) { 617394d6e53SAnton Vorontsov dev_info(&pdev->dev, "JMB361 has only one port\n"); 6189a23c1d6SAntoine Tenart hpriv->force_port_map = 1; 619394d6e53SAnton Vorontsov } 620394d6e53SAnton Vorontsov 621394d6e53SAnton Vorontsov /* 622394d6e53SAnton Vorontsov * Temporary Marvell 6145 hack: PATA port presence 623394d6e53SAnton Vorontsov * is asserted through the standard AHCI port 624394d6e53SAnton Vorontsov * presence register, as bit 4 (counting from 0) 625394d6e53SAnton Vorontsov */ 626394d6e53SAnton Vorontsov if (hpriv->flags & AHCI_HFLAG_MV_PATA) { 627394d6e53SAnton Vorontsov if (pdev->device == 0x6121) 6289a23c1d6SAntoine Tenart hpriv->mask_port_map = 0x3; 629394d6e53SAnton Vorontsov else 6309a23c1d6SAntoine Tenart hpriv->mask_port_map = 0xf; 631394d6e53SAnton Vorontsov dev_info(&pdev->dev, 632394d6e53SAnton Vorontsov "Disabling your PATA port. Use the boot option 'ahci.marvell_enable=0' to avoid this.\n"); 633394d6e53SAnton Vorontsov } 634394d6e53SAnton Vorontsov 635725c7b57SAntoine Ténart ahci_save_initial_config(&pdev->dev, hpriv); 636394d6e53SAnton Vorontsov } 637394d6e53SAnton Vorontsov 638781d6550SAnton Vorontsov static void ahci_pci_init_controller(struct ata_host *host) 639781d6550SAnton Vorontsov { 640781d6550SAnton Vorontsov struct ahci_host_priv *hpriv = host->private_data; 641781d6550SAnton Vorontsov struct pci_dev *pdev = to_pci_dev(host->dev); 642781d6550SAnton Vorontsov void __iomem *port_mmio; 643781d6550SAnton Vorontsov u32 tmp; 644c40e7cb8SJose Alberto Reguero int mv; 6452bcd866bSJeff Garzik 646417a1a6dSTejun Heo if (hpriv->flags & AHCI_HFLAG_MV_PATA) { 647c40e7cb8SJose Alberto Reguero if (pdev->device == 0x6121) 648c40e7cb8SJose Alberto Reguero mv = 2; 649c40e7cb8SJose Alberto Reguero else 650c40e7cb8SJose Alberto Reguero mv = 4; 651c40e7cb8SJose Alberto Reguero port_mmio = __ahci_port_base(host, mv); 652cd70c266SJeff Garzik 653cd70c266SJeff Garzik writel(0, port_mmio + PORT_IRQ_MASK); 654cd70c266SJeff Garzik 655cd70c266SJeff Garzik /* clear port IRQ */ 656cd70c266SJeff Garzik tmp = readl(port_mmio + PORT_IRQ_STAT); 657cd70c266SJeff Garzik VPRINTK("PORT_IRQ_STAT 0x%x\n", tmp); 658cd70c266SJeff Garzik if (tmp) 659cd70c266SJeff Garzik writel(tmp, port_mmio + PORT_IRQ_STAT); 660cd70c266SJeff Garzik } 661cd70c266SJeff Garzik 662781d6550SAnton Vorontsov ahci_init_controller(host); 663c6fd2807SJeff Garzik } 664c6fd2807SJeff Garzik 665cc0680a5STejun Heo static int ahci_vt8251_hardreset(struct ata_link *link, unsigned int *class, 666d4b2bab4STejun Heo unsigned long deadline) 667ad616ffbSTejun Heo { 668cc0680a5STejun Heo struct ata_port *ap = link->ap; 669039ece38SHans de Goede struct ahci_host_priv *hpriv = ap->host->private_data; 6709dadd45bSTejun Heo bool online; 671ad616ffbSTejun Heo int rc; 672ad616ffbSTejun Heo 673ad616ffbSTejun Heo DPRINTK("ENTER\n"); 674ad616ffbSTejun Heo 675fa89f53bSEvan Wang hpriv->stop_engine(ap); 676ad616ffbSTejun Heo 677cc0680a5STejun Heo rc = sata_link_hardreset(link, sata_ehc_deb_timing(&link->eh_context), 6789dadd45bSTejun Heo deadline, &online, NULL); 679ad616ffbSTejun Heo 680039ece38SHans de Goede hpriv->start_engine(ap); 681ad616ffbSTejun Heo 682ad616ffbSTejun Heo DPRINTK("EXIT, rc=%d, class=%u\n", rc, *class); 683ad616ffbSTejun Heo 684ad616ffbSTejun Heo /* vt8251 doesn't clear BSY on signature FIS reception, 685ad616ffbSTejun Heo * request follow-up softreset. 686ad616ffbSTejun Heo */ 6879dadd45bSTejun Heo return online ? -EAGAIN : rc; 688ad616ffbSTejun Heo } 689ad616ffbSTejun Heo 690edc93052STejun Heo static int ahci_p5wdh_hardreset(struct ata_link *link, unsigned int *class, 691edc93052STejun Heo unsigned long deadline) 692edc93052STejun Heo { 693edc93052STejun Heo struct ata_port *ap = link->ap; 694edc93052STejun Heo struct ahci_port_priv *pp = ap->private_data; 695039ece38SHans de Goede struct ahci_host_priv *hpriv = ap->host->private_data; 696edc93052STejun Heo u8 *d2h_fis = pp->rx_fis + RX_FIS_D2H_REG; 697edc93052STejun Heo struct ata_taskfile tf; 6989dadd45bSTejun Heo bool online; 699edc93052STejun Heo int rc; 700edc93052STejun Heo 701fa89f53bSEvan Wang hpriv->stop_engine(ap); 702edc93052STejun Heo 703edc93052STejun Heo /* clear D2H reception area to properly wait for D2H FIS */ 704edc93052STejun Heo ata_tf_init(link->device, &tf); 7059bbb1b0eSSergei Shtylyov tf.command = ATA_BUSY; 706edc93052STejun Heo ata_tf_to_fis(&tf, 0, 0, d2h_fis); 707edc93052STejun Heo 708edc93052STejun Heo rc = sata_link_hardreset(link, sata_ehc_deb_timing(&link->eh_context), 7099dadd45bSTejun Heo deadline, &online, NULL); 710edc93052STejun Heo 711039ece38SHans de Goede hpriv->start_engine(ap); 712edc93052STejun Heo 713edc93052STejun Heo /* The pseudo configuration device on SIMG4726 attached to 714edc93052STejun Heo * ASUS P5W-DH Deluxe doesn't send signature FIS after 715edc93052STejun Heo * hardreset if no device is attached to the first downstream 716edc93052STejun Heo * port && the pseudo device locks up on SRST w/ PMP==0. To 717edc93052STejun Heo * work around this, wait for !BSY only briefly. If BSY isn't 718edc93052STejun Heo * cleared, perform CLO and proceed to IDENTIFY (achieved by 719edc93052STejun Heo * ATA_LFLAG_NO_SRST and ATA_LFLAG_ASSUME_ATA). 720edc93052STejun Heo * 721edc93052STejun Heo * Wait for two seconds. Devices attached to downstream port 722edc93052STejun Heo * which can't process the following IDENTIFY after this will 723edc93052STejun Heo * have to be reset again. For most cases, this should 724edc93052STejun Heo * suffice while making probing snappish enough. 725edc93052STejun Heo */ 7269dadd45bSTejun Heo if (online) { 7279dadd45bSTejun Heo rc = ata_wait_after_reset(link, jiffies + 2 * HZ, 7289dadd45bSTejun Heo ahci_check_ready); 729edc93052STejun Heo if (rc) 73078d5ae39SShane Huang ahci_kick_engine(ap); 7319dadd45bSTejun Heo } 7329dadd45bSTejun Heo return rc; 733edc93052STejun Heo } 734edc93052STejun Heo 735dbfe8ef5SDan Williams /* 736dbfe8ef5SDan Williams * ahci_avn_hardreset - attempt more aggressive recovery of Avoton ports. 737dbfe8ef5SDan Williams * 738dbfe8ef5SDan Williams * It has been observed with some SSDs that the timing of events in the 739dbfe8ef5SDan Williams * link synchronization phase can leave the port in a state that can not 740dbfe8ef5SDan Williams * be recovered by a SATA-hard-reset alone. The failing signature is 741dbfe8ef5SDan Williams * SStatus.DET stuck at 1 ("Device presence detected but Phy 742dbfe8ef5SDan Williams * communication not established"). It was found that unloading and 743dbfe8ef5SDan Williams * reloading the driver when this problem occurs allows the drive 744dbfe8ef5SDan Williams * connection to be recovered (DET advanced to 0x3). The critical 745dbfe8ef5SDan Williams * component of reloading the driver is that the port state machines are 746dbfe8ef5SDan Williams * reset by bouncing "port enable" in the AHCI PCS configuration 747dbfe8ef5SDan Williams * register. So, reproduce that effect by bouncing a port whenever we 748dbfe8ef5SDan Williams * see DET==1 after a reset. 749dbfe8ef5SDan Williams */ 750dbfe8ef5SDan Williams static int ahci_avn_hardreset(struct ata_link *link, unsigned int *class, 751dbfe8ef5SDan Williams unsigned long deadline) 752dbfe8ef5SDan Williams { 753dbfe8ef5SDan Williams const unsigned long *timing = sata_ehc_deb_timing(&link->eh_context); 754dbfe8ef5SDan Williams struct ata_port *ap = link->ap; 755dbfe8ef5SDan Williams struct ahci_port_priv *pp = ap->private_data; 756dbfe8ef5SDan Williams struct ahci_host_priv *hpriv = ap->host->private_data; 757dbfe8ef5SDan Williams u8 *d2h_fis = pp->rx_fis + RX_FIS_D2H_REG; 758dbfe8ef5SDan Williams unsigned long tmo = deadline - jiffies; 759dbfe8ef5SDan Williams struct ata_taskfile tf; 760dbfe8ef5SDan Williams bool online; 761dbfe8ef5SDan Williams int rc, i; 762dbfe8ef5SDan Williams 763dbfe8ef5SDan Williams DPRINTK("ENTER\n"); 764dbfe8ef5SDan Williams 765fa89f53bSEvan Wang hpriv->stop_engine(ap); 766dbfe8ef5SDan Williams 767dbfe8ef5SDan Williams for (i = 0; i < 2; i++) { 768dbfe8ef5SDan Williams u16 val; 769dbfe8ef5SDan Williams u32 sstatus; 770dbfe8ef5SDan Williams int port = ap->port_no; 771dbfe8ef5SDan Williams struct ata_host *host = ap->host; 772dbfe8ef5SDan Williams struct pci_dev *pdev = to_pci_dev(host->dev); 773dbfe8ef5SDan Williams 774dbfe8ef5SDan Williams /* clear D2H reception area to properly wait for D2H FIS */ 775dbfe8ef5SDan Williams ata_tf_init(link->device, &tf); 776dbfe8ef5SDan Williams tf.command = ATA_BUSY; 777dbfe8ef5SDan Williams ata_tf_to_fis(&tf, 0, 0, d2h_fis); 778dbfe8ef5SDan Williams 779dbfe8ef5SDan Williams rc = sata_link_hardreset(link, timing, deadline, &online, 780dbfe8ef5SDan Williams ahci_check_ready); 781dbfe8ef5SDan Williams 782dbfe8ef5SDan Williams if (sata_scr_read(link, SCR_STATUS, &sstatus) != 0 || 783dbfe8ef5SDan Williams (sstatus & 0xf) != 1) 784dbfe8ef5SDan Williams break; 785dbfe8ef5SDan Williams 786dbfe8ef5SDan Williams ata_link_printk(link, KERN_INFO, "avn bounce port%d\n", 787dbfe8ef5SDan Williams port); 788dbfe8ef5SDan Williams 789dbfe8ef5SDan Williams pci_read_config_word(pdev, 0x92, &val); 790dbfe8ef5SDan Williams val &= ~(1 << port); 791dbfe8ef5SDan Williams pci_write_config_word(pdev, 0x92, val); 792dbfe8ef5SDan Williams ata_msleep(ap, 1000); 793dbfe8ef5SDan Williams val |= 1 << port; 794dbfe8ef5SDan Williams pci_write_config_word(pdev, 0x92, val); 795dbfe8ef5SDan Williams deadline += tmo; 796dbfe8ef5SDan Williams } 797dbfe8ef5SDan Williams 798dbfe8ef5SDan Williams hpriv->start_engine(ap); 799dbfe8ef5SDan Williams 800dbfe8ef5SDan Williams if (online) 801dbfe8ef5SDan Williams *class = ahci_dev_classify(ap); 802dbfe8ef5SDan Williams 803dbfe8ef5SDan Williams DPRINTK("EXIT, rc=%d, class=%u\n", rc, *class); 804dbfe8ef5SDan Williams return rc; 805dbfe8ef5SDan Williams } 806dbfe8ef5SDan Williams 807dbfe8ef5SDan Williams 80802e53293SMika Westerberg #ifdef CONFIG_PM 80902e53293SMika Westerberg static void ahci_pci_disable_interrupts(struct ata_host *host) 810c6fd2807SJeff Garzik { 8119b10ae86STejun Heo struct ahci_host_priv *hpriv = host->private_data; 812d8993349SAnton Vorontsov void __iomem *mmio = hpriv->mmio; 813c6fd2807SJeff Garzik u32 ctl; 814c6fd2807SJeff Garzik 815c6fd2807SJeff Garzik /* AHCI spec rev1.1 section 8.3.3: 816c6fd2807SJeff Garzik * Software must disable interrupts prior to requesting a 817c6fd2807SJeff Garzik * transition of the HBA to D3 state. 818c6fd2807SJeff Garzik */ 819c6fd2807SJeff Garzik ctl = readl(mmio + HOST_CTL); 820c6fd2807SJeff Garzik ctl &= ~HOST_IRQ_EN; 821c6fd2807SJeff Garzik writel(ctl, mmio + HOST_CTL); 822c6fd2807SJeff Garzik readl(mmio + HOST_CTL); /* flush */ 82302e53293SMika Westerberg } 824f1d848f9SMika Westerberg 82502e53293SMika Westerberg static int ahci_pci_device_runtime_suspend(struct device *dev) 82602e53293SMika Westerberg { 82702e53293SMika Westerberg struct pci_dev *pdev = to_pci_dev(dev); 82802e53293SMika Westerberg struct ata_host *host = pci_get_drvdata(pdev); 82902e53293SMika Westerberg 83002e53293SMika Westerberg ahci_pci_disable_interrupts(host); 83102e53293SMika Westerberg return 0; 83202e53293SMika Westerberg } 83302e53293SMika Westerberg 83402e53293SMika Westerberg static int ahci_pci_device_runtime_resume(struct device *dev) 83502e53293SMika Westerberg { 83602e53293SMika Westerberg struct pci_dev *pdev = to_pci_dev(dev); 83702e53293SMika Westerberg struct ata_host *host = pci_get_drvdata(pdev); 83802e53293SMika Westerberg int rc; 83902e53293SMika Westerberg 840c312ef17SDan Williams rc = ahci_reset_controller(host); 84102e53293SMika Westerberg if (rc) 84202e53293SMika Westerberg return rc; 84302e53293SMika Westerberg ahci_pci_init_controller(host); 84402e53293SMika Westerberg return 0; 84502e53293SMika Westerberg } 84602e53293SMika Westerberg 84702e53293SMika Westerberg #ifdef CONFIG_PM_SLEEP 84802e53293SMika Westerberg static int ahci_pci_device_suspend(struct device *dev) 84902e53293SMika Westerberg { 85002e53293SMika Westerberg struct pci_dev *pdev = to_pci_dev(dev); 85102e53293SMika Westerberg struct ata_host *host = pci_get_drvdata(pdev); 85202e53293SMika Westerberg struct ahci_host_priv *hpriv = host->private_data; 85302e53293SMika Westerberg 85402e53293SMika Westerberg if (hpriv->flags & AHCI_HFLAG_NO_SUSPEND) { 85502e53293SMika Westerberg dev_err(&pdev->dev, 85602e53293SMika Westerberg "BIOS update required for suspend/resume\n"); 85702e53293SMika Westerberg return -EIO; 85802e53293SMika Westerberg } 85902e53293SMika Westerberg 86002e53293SMika Westerberg ahci_pci_disable_interrupts(host); 861f1d848f9SMika Westerberg return ata_host_suspend(host, PMSG_SUSPEND); 862c6fd2807SJeff Garzik } 863c6fd2807SJeff Garzik 864f1d848f9SMika Westerberg static int ahci_pci_device_resume(struct device *dev) 865c6fd2807SJeff Garzik { 866f1d848f9SMika Westerberg struct pci_dev *pdev = to_pci_dev(dev); 8670a86e1c8SJingoo Han struct ata_host *host = pci_get_drvdata(pdev); 868c6fd2807SJeff Garzik int rc; 869c6fd2807SJeff Garzik 870cb85696dSJames Laird /* Apple BIOS helpfully mangles the registers on resume */ 871cb85696dSJames Laird if (is_mcp89_apple(pdev)) 872cb85696dSJames Laird ahci_mcp89_apple_enable(pdev); 873cb85696dSJames Laird 874c6fd2807SJeff Garzik if (pdev->dev.power.power_state.event == PM_EVENT_SUSPEND) { 875c312ef17SDan Williams rc = ahci_reset_controller(host); 876c6fd2807SJeff Garzik if (rc) 877c6fd2807SJeff Garzik return rc; 878c6fd2807SJeff Garzik 879781d6550SAnton Vorontsov ahci_pci_init_controller(host); 880c6fd2807SJeff Garzik } 881c6fd2807SJeff Garzik 882cca3974eSJeff Garzik ata_host_resume(host); 883c6fd2807SJeff Garzik 884c6fd2807SJeff Garzik return 0; 885c6fd2807SJeff Garzik } 886438ac6d5STejun Heo #endif 887c6fd2807SJeff Garzik 88802e53293SMika Westerberg #endif /* CONFIG_PM */ 88902e53293SMika Westerberg 8904447d351STejun Heo static int ahci_configure_dma_masks(struct pci_dev *pdev, int using_dac) 891c6fd2807SJeff Garzik { 892b1716871SChristoph Hellwig const int dma_bits = using_dac ? 64 : 32; 893c6fd2807SJeff Garzik int rc; 894c6fd2807SJeff Garzik 895318893e1SAlessandro Rubini /* 896318893e1SAlessandro Rubini * If the device fixup already set the dma_mask to some non-standard 897318893e1SAlessandro Rubini * value, don't extend it here. This happens on STA2X11, for example. 898b1716871SChristoph Hellwig * 899b1716871SChristoph Hellwig * XXX: manipulating the DMA mask from platform code is completely 900*a7ba70f1SNicolas Saenz Julienne * bogus, platform code should use dev->bus_dma_limit instead.. 901318893e1SAlessandro Rubini */ 902318893e1SAlessandro Rubini if (pdev->dma_mask && pdev->dma_mask < DMA_BIT_MASK(32)) 903318893e1SAlessandro Rubini return 0; 904318893e1SAlessandro Rubini 905b1716871SChristoph Hellwig rc = dma_set_mask_and_coherent(&pdev->dev, DMA_BIT_MASK(dma_bits)); 906b1716871SChristoph Hellwig if (rc) 907b1716871SChristoph Hellwig dev_err(&pdev->dev, "DMA enable failed\n"); 908c6fd2807SJeff Garzik return rc; 909c6fd2807SJeff Garzik } 910c6fd2807SJeff Garzik 911439fcaecSAnton Vorontsov static void ahci_pci_print_info(struct ata_host *host) 912439fcaecSAnton Vorontsov { 913439fcaecSAnton Vorontsov struct pci_dev *pdev = to_pci_dev(host->dev); 914439fcaecSAnton Vorontsov u16 cc; 915439fcaecSAnton Vorontsov const char *scc_s; 916439fcaecSAnton Vorontsov 917439fcaecSAnton Vorontsov pci_read_config_word(pdev, 0x0a, &cc); 918439fcaecSAnton Vorontsov if (cc == PCI_CLASS_STORAGE_IDE) 919439fcaecSAnton Vorontsov scc_s = "IDE"; 920439fcaecSAnton Vorontsov else if (cc == PCI_CLASS_STORAGE_SATA) 921439fcaecSAnton Vorontsov scc_s = "SATA"; 922439fcaecSAnton Vorontsov else if (cc == PCI_CLASS_STORAGE_RAID) 923439fcaecSAnton Vorontsov scc_s = "RAID"; 924439fcaecSAnton Vorontsov else 925439fcaecSAnton Vorontsov scc_s = "unknown"; 926439fcaecSAnton Vorontsov 927439fcaecSAnton Vorontsov ahci_print_info(host, scc_s); 928439fcaecSAnton Vorontsov } 929439fcaecSAnton Vorontsov 930edc93052STejun Heo /* On ASUS P5W DH Deluxe, the second port of PCI device 00:1f.2 is 931edc93052STejun Heo * hardwired to on-board SIMG 4726. The chipset is ICH8 and doesn't 932edc93052STejun Heo * support PMP and the 4726 either directly exports the device 933edc93052STejun Heo * attached to the first downstream port or acts as a hardware storage 934edc93052STejun Heo * controller and emulate a single ATA device (can be RAID 0/1 or some 935edc93052STejun Heo * other configuration). 936edc93052STejun Heo * 937edc93052STejun Heo * When there's no device attached to the first downstream port of the 938edc93052STejun Heo * 4726, "Config Disk" appears, which is a pseudo ATA device to 939edc93052STejun Heo * configure the 4726. However, ATA emulation of the device is very 940edc93052STejun Heo * lame. It doesn't send signature D2H Reg FIS after the initial 941edc93052STejun Heo * hardreset, pukes on SRST w/ PMP==0 and has bunch of other issues. 942edc93052STejun Heo * 943edc93052STejun Heo * The following function works around the problem by always using 944edc93052STejun Heo * hardreset on the port and not depending on receiving signature FIS 945edc93052STejun Heo * afterward. If signature FIS isn't received soon, ATA class is 946edc93052STejun Heo * assumed without follow-up softreset. 947edc93052STejun Heo */ 948edc93052STejun Heo static void ahci_p5wdh_workaround(struct ata_host *host) 949edc93052STejun Heo { 9501bd06867SMathias Krause static const struct dmi_system_id sysids[] = { 951edc93052STejun Heo { 952edc93052STejun Heo .ident = "P5W DH Deluxe", 953edc93052STejun Heo .matches = { 954edc93052STejun Heo DMI_MATCH(DMI_SYS_VENDOR, 955edc93052STejun Heo "ASUSTEK COMPUTER INC"), 956edc93052STejun Heo DMI_MATCH(DMI_PRODUCT_NAME, "P5W DH Deluxe"), 957edc93052STejun Heo }, 958edc93052STejun Heo }, 959edc93052STejun Heo { } 960edc93052STejun Heo }; 961edc93052STejun Heo struct pci_dev *pdev = to_pci_dev(host->dev); 962edc93052STejun Heo 963edc93052STejun Heo if (pdev->bus->number == 0 && pdev->devfn == PCI_DEVFN(0x1f, 2) && 964edc93052STejun Heo dmi_check_system(sysids)) { 965edc93052STejun Heo struct ata_port *ap = host->ports[1]; 966edc93052STejun Heo 967a44fec1fSJoe Perches dev_info(&pdev->dev, 968a44fec1fSJoe Perches "enabling ASUS P5W DH Deluxe on-board SIMG4726 workaround\n"); 969edc93052STejun Heo 970edc93052STejun Heo ap->ops = &ahci_p5wdh_ops; 971edc93052STejun Heo ap->link.flags |= ATA_LFLAG_NO_SRST | ATA_LFLAG_ASSUME_ATA; 972edc93052STejun Heo } 973edc93052STejun Heo } 974edc93052STejun Heo 975cb85696dSJames Laird /* 976cb85696dSJames Laird * Macbook7,1 firmware forcibly disables MCP89 AHCI and changes PCI ID when 977cb85696dSJames Laird * booting in BIOS compatibility mode. We restore the registers but not ID. 978cb85696dSJames Laird */ 979cb85696dSJames Laird static void ahci_mcp89_apple_enable(struct pci_dev *pdev) 980cb85696dSJames Laird { 981cb85696dSJames Laird u32 val; 982cb85696dSJames Laird 983cb85696dSJames Laird printk(KERN_INFO "ahci: enabling MCP89 AHCI mode\n"); 984cb85696dSJames Laird 985cb85696dSJames Laird pci_read_config_dword(pdev, 0xf8, &val); 986cb85696dSJames Laird val |= 1 << 0x1b; 987cb85696dSJames Laird /* the following changes the device ID, but appears not to affect function */ 988cb85696dSJames Laird /* val = (val & ~0xf0000000) | 0x80000000; */ 989cb85696dSJames Laird pci_write_config_dword(pdev, 0xf8, val); 990cb85696dSJames Laird 991cb85696dSJames Laird pci_read_config_dword(pdev, 0x54c, &val); 992cb85696dSJames Laird val |= 1 << 0xc; 993cb85696dSJames Laird pci_write_config_dword(pdev, 0x54c, val); 994cb85696dSJames Laird 995cb85696dSJames Laird pci_read_config_dword(pdev, 0x4a4, &val); 996cb85696dSJames Laird val &= 0xff; 997cb85696dSJames Laird val |= 0x01060100; 998cb85696dSJames Laird pci_write_config_dword(pdev, 0x4a4, val); 999cb85696dSJames Laird 1000cb85696dSJames Laird pci_read_config_dword(pdev, 0x54c, &val); 1001cb85696dSJames Laird val &= ~(1 << 0xc); 1002cb85696dSJames Laird pci_write_config_dword(pdev, 0x54c, val); 1003cb85696dSJames Laird 1004cb85696dSJames Laird pci_read_config_dword(pdev, 0xf8, &val); 1005cb85696dSJames Laird val &= ~(1 << 0x1b); 1006cb85696dSJames Laird pci_write_config_dword(pdev, 0xf8, val); 1007cb85696dSJames Laird } 1008cb85696dSJames Laird 1009cb85696dSJames Laird static bool is_mcp89_apple(struct pci_dev *pdev) 1010cb85696dSJames Laird { 1011cb85696dSJames Laird return pdev->vendor == PCI_VENDOR_ID_NVIDIA && 1012cb85696dSJames Laird pdev->device == PCI_DEVICE_ID_NVIDIA_NFORCE_MCP89_SATA && 1013cb85696dSJames Laird pdev->subsystem_vendor == PCI_VENDOR_ID_APPLE && 1014cb85696dSJames Laird pdev->subsystem_device == 0xcb89; 1015cb85696dSJames Laird } 1016cb85696dSJames Laird 10172fcad9d2STejun Heo /* only some SB600 ahci controllers can do 64bit DMA */ 10182fcad9d2STejun Heo static bool ahci_sb600_enable_64bit(struct pci_dev *pdev) 101958a09b38SShane Huang { 102058a09b38SShane Huang static const struct dmi_system_id sysids[] = { 102103d783bfSTejun Heo /* 102203d783bfSTejun Heo * The oldest version known to be broken is 0901 and 102303d783bfSTejun Heo * working is 1501 which was released on 2007-10-26. 10242fcad9d2STejun Heo * Enable 64bit DMA on 1501 and anything newer. 10252fcad9d2STejun Heo * 102603d783bfSTejun Heo * Please read bko#9412 for more info. 102703d783bfSTejun Heo */ 102858a09b38SShane Huang { 102958a09b38SShane Huang .ident = "ASUS M2A-VM", 103058a09b38SShane Huang .matches = { 103158a09b38SShane Huang DMI_MATCH(DMI_BOARD_VENDOR, 103258a09b38SShane Huang "ASUSTeK Computer INC."), 103358a09b38SShane Huang DMI_MATCH(DMI_BOARD_NAME, "M2A-VM"), 103458a09b38SShane Huang }, 103503d783bfSTejun Heo .driver_data = "20071026", /* yyyymmdd */ 103658a09b38SShane Huang }, 1037e65cc194SMark Nelson /* 1038e65cc194SMark Nelson * All BIOS versions for the MSI K9A2 Platinum (MS-7376) 1039e65cc194SMark Nelson * support 64bit DMA. 1040e65cc194SMark Nelson * 1041e65cc194SMark Nelson * BIOS versions earlier than 1.5 had the Manufacturer DMI 1042e65cc194SMark Nelson * fields as "MICRO-STAR INTERANTIONAL CO.,LTD". 1043e65cc194SMark Nelson * This spelling mistake was fixed in BIOS version 1.5, so 1044e65cc194SMark Nelson * 1.5 and later have the Manufacturer as 1045e65cc194SMark Nelson * "MICRO-STAR INTERNATIONAL CO.,LTD". 1046e65cc194SMark Nelson * So try to match on DMI_BOARD_VENDOR of "MICRO-STAR INTER". 1047e65cc194SMark Nelson * 1048e65cc194SMark Nelson * BIOS versions earlier than 1.9 had a Board Product Name 1049e65cc194SMark Nelson * DMI field of "MS-7376". This was changed to be 1050e65cc194SMark Nelson * "K9A2 Platinum (MS-7376)" in version 1.9, but we can still 1051e65cc194SMark Nelson * match on DMI_BOARD_NAME of "MS-7376". 1052e65cc194SMark Nelson */ 1053e65cc194SMark Nelson { 1054e65cc194SMark Nelson .ident = "MSI K9A2 Platinum", 1055e65cc194SMark Nelson .matches = { 1056e65cc194SMark Nelson DMI_MATCH(DMI_BOARD_VENDOR, 1057e65cc194SMark Nelson "MICRO-STAR INTER"), 1058e65cc194SMark Nelson DMI_MATCH(DMI_BOARD_NAME, "MS-7376"), 1059e65cc194SMark Nelson }, 1060e65cc194SMark Nelson }, 10613c4aa91fSMark Nelson /* 1062ff0173c1SMark Nelson * All BIOS versions for the MSI K9AGM2 (MS-7327) support 1063ff0173c1SMark Nelson * 64bit DMA. 1064ff0173c1SMark Nelson * 1065ff0173c1SMark Nelson * This board also had the typo mentioned above in the 1066ff0173c1SMark Nelson * Manufacturer DMI field (fixed in BIOS version 1.5), so 1067ff0173c1SMark Nelson * match on DMI_BOARD_VENDOR of "MICRO-STAR INTER" again. 1068ff0173c1SMark Nelson */ 1069ff0173c1SMark Nelson { 1070ff0173c1SMark Nelson .ident = "MSI K9AGM2", 1071ff0173c1SMark Nelson .matches = { 1072ff0173c1SMark Nelson DMI_MATCH(DMI_BOARD_VENDOR, 1073ff0173c1SMark Nelson "MICRO-STAR INTER"), 1074ff0173c1SMark Nelson DMI_MATCH(DMI_BOARD_NAME, "MS-7327"), 1075ff0173c1SMark Nelson }, 1076ff0173c1SMark Nelson }, 1077ff0173c1SMark Nelson /* 10783c4aa91fSMark Nelson * All BIOS versions for the Asus M3A support 64bit DMA. 10793c4aa91fSMark Nelson * (all release versions from 0301 to 1206 were tested) 10803c4aa91fSMark Nelson */ 10813c4aa91fSMark Nelson { 10823c4aa91fSMark Nelson .ident = "ASUS M3A", 10833c4aa91fSMark Nelson .matches = { 10843c4aa91fSMark Nelson DMI_MATCH(DMI_BOARD_VENDOR, 10853c4aa91fSMark Nelson "ASUSTeK Computer INC."), 10863c4aa91fSMark Nelson DMI_MATCH(DMI_BOARD_NAME, "M3A"), 10873c4aa91fSMark Nelson }, 10883c4aa91fSMark Nelson }, 108958a09b38SShane Huang { } 109058a09b38SShane Huang }; 109103d783bfSTejun Heo const struct dmi_system_id *match; 10922fcad9d2STejun Heo int year, month, date; 10932fcad9d2STejun Heo char buf[9]; 109458a09b38SShane Huang 109503d783bfSTejun Heo match = dmi_first_match(sysids); 109658a09b38SShane Huang if (pdev->bus->number != 0 || pdev->devfn != PCI_DEVFN(0x12, 0) || 109703d783bfSTejun Heo !match) 109858a09b38SShane Huang return false; 109958a09b38SShane Huang 1100e65cc194SMark Nelson if (!match->driver_data) 1101e65cc194SMark Nelson goto enable_64bit; 1102e65cc194SMark Nelson 110303d783bfSTejun Heo dmi_get_date(DMI_BIOS_DATE, &year, &month, &date); 110403d783bfSTejun Heo snprintf(buf, sizeof(buf), "%04d%02d%02d", year, month, date); 110503d783bfSTejun Heo 1106e65cc194SMark Nelson if (strcmp(buf, match->driver_data) >= 0) 1107e65cc194SMark Nelson goto enable_64bit; 1108e65cc194SMark Nelson else { 1109a44fec1fSJoe Perches dev_warn(&pdev->dev, 1110a44fec1fSJoe Perches "%s: BIOS too old, forcing 32bit DMA, update BIOS\n", 1111a44fec1fSJoe Perches match->ident); 11122fcad9d2STejun Heo return false; 11132fcad9d2STejun Heo } 1114e65cc194SMark Nelson 1115e65cc194SMark Nelson enable_64bit: 1116a44fec1fSJoe Perches dev_warn(&pdev->dev, "%s: enabling 64bit DMA\n", match->ident); 1117e65cc194SMark Nelson return true; 111858a09b38SShane Huang } 111958a09b38SShane Huang 11201fd68434SRafael J. Wysocki static bool ahci_broken_system_poweroff(struct pci_dev *pdev) 11211fd68434SRafael J. Wysocki { 11221fd68434SRafael J. Wysocki static const struct dmi_system_id broken_systems[] = { 11231fd68434SRafael J. Wysocki { 11241fd68434SRafael J. Wysocki .ident = "HP Compaq nx6310", 11251fd68434SRafael J. Wysocki .matches = { 11261fd68434SRafael J. Wysocki DMI_MATCH(DMI_SYS_VENDOR, "Hewlett-Packard"), 11271fd68434SRafael J. Wysocki DMI_MATCH(DMI_PRODUCT_NAME, "HP Compaq nx6310"), 11281fd68434SRafael J. Wysocki }, 11291fd68434SRafael J. Wysocki /* PCI slot number of the controller */ 11301fd68434SRafael J. Wysocki .driver_data = (void *)0x1FUL, 11311fd68434SRafael J. Wysocki }, 1132d2f9c061SMaciej Rutecki { 1133d2f9c061SMaciej Rutecki .ident = "HP Compaq 6720s", 1134d2f9c061SMaciej Rutecki .matches = { 1135d2f9c061SMaciej Rutecki DMI_MATCH(DMI_SYS_VENDOR, "Hewlett-Packard"), 1136d2f9c061SMaciej Rutecki DMI_MATCH(DMI_PRODUCT_NAME, "HP Compaq 6720s"), 1137d2f9c061SMaciej Rutecki }, 1138d2f9c061SMaciej Rutecki /* PCI slot number of the controller */ 1139d2f9c061SMaciej Rutecki .driver_data = (void *)0x1FUL, 1140d2f9c061SMaciej Rutecki }, 11411fd68434SRafael J. Wysocki 11421fd68434SRafael J. Wysocki { } /* terminate list */ 11431fd68434SRafael J. Wysocki }; 11441fd68434SRafael J. Wysocki const struct dmi_system_id *dmi = dmi_first_match(broken_systems); 11451fd68434SRafael J. Wysocki 11461fd68434SRafael J. Wysocki if (dmi) { 11471fd68434SRafael J. Wysocki unsigned long slot = (unsigned long)dmi->driver_data; 11481fd68434SRafael J. Wysocki /* apply the quirk only to on-board controllers */ 11491fd68434SRafael J. Wysocki return slot == PCI_SLOT(pdev->devfn); 11501fd68434SRafael J. Wysocki } 11511fd68434SRafael J. Wysocki 11521fd68434SRafael J. Wysocki return false; 11531fd68434SRafael J. Wysocki } 11541fd68434SRafael J. Wysocki 11559b10ae86STejun Heo static bool ahci_broken_suspend(struct pci_dev *pdev) 11569b10ae86STejun Heo { 11579b10ae86STejun Heo static const struct dmi_system_id sysids[] = { 11589b10ae86STejun Heo /* 11599b10ae86STejun Heo * On HP dv[4-6] and HDX18 with earlier BIOSen, link 11609b10ae86STejun Heo * to the harddisk doesn't become online after 11619b10ae86STejun Heo * resuming from STR. Warn and fail suspend. 11629deb3431STejun Heo * 11639deb3431STejun Heo * http://bugzilla.kernel.org/show_bug.cgi?id=12276 11649deb3431STejun Heo * 11659deb3431STejun Heo * Use dates instead of versions to match as HP is 11669deb3431STejun Heo * apparently recycling both product and version 11679deb3431STejun Heo * strings. 11689deb3431STejun Heo * 11699deb3431STejun Heo * http://bugzilla.kernel.org/show_bug.cgi?id=15462 11709b10ae86STejun Heo */ 11719b10ae86STejun Heo { 11729b10ae86STejun Heo .ident = "dv4", 11739b10ae86STejun Heo .matches = { 11749b10ae86STejun Heo DMI_MATCH(DMI_SYS_VENDOR, "Hewlett-Packard"), 11759b10ae86STejun Heo DMI_MATCH(DMI_PRODUCT_NAME, 11769b10ae86STejun Heo "HP Pavilion dv4 Notebook PC"), 11779b10ae86STejun Heo }, 11789deb3431STejun Heo .driver_data = "20090105", /* F.30 */ 11799b10ae86STejun Heo }, 11809b10ae86STejun Heo { 11819b10ae86STejun Heo .ident = "dv5", 11829b10ae86STejun Heo .matches = { 11839b10ae86STejun Heo DMI_MATCH(DMI_SYS_VENDOR, "Hewlett-Packard"), 11849b10ae86STejun Heo DMI_MATCH(DMI_PRODUCT_NAME, 11859b10ae86STejun Heo "HP Pavilion dv5 Notebook PC"), 11869b10ae86STejun Heo }, 11879deb3431STejun Heo .driver_data = "20090506", /* F.16 */ 11889b10ae86STejun Heo }, 11899b10ae86STejun Heo { 11909b10ae86STejun Heo .ident = "dv6", 11919b10ae86STejun Heo .matches = { 11929b10ae86STejun Heo DMI_MATCH(DMI_SYS_VENDOR, "Hewlett-Packard"), 11939b10ae86STejun Heo DMI_MATCH(DMI_PRODUCT_NAME, 11949b10ae86STejun Heo "HP Pavilion dv6 Notebook PC"), 11959b10ae86STejun Heo }, 11969deb3431STejun Heo .driver_data = "20090423", /* F.21 */ 11979b10ae86STejun Heo }, 11989b10ae86STejun Heo { 11999b10ae86STejun Heo .ident = "HDX18", 12009b10ae86STejun Heo .matches = { 12019b10ae86STejun Heo DMI_MATCH(DMI_SYS_VENDOR, "Hewlett-Packard"), 12029b10ae86STejun Heo DMI_MATCH(DMI_PRODUCT_NAME, 12039b10ae86STejun Heo "HP HDX18 Notebook PC"), 12049b10ae86STejun Heo }, 12059deb3431STejun Heo .driver_data = "20090430", /* F.23 */ 12069b10ae86STejun Heo }, 1207cedc9bf9STejun Heo /* 1208cedc9bf9STejun Heo * Acer eMachines G725 has the same problem. BIOS 1209cedc9bf9STejun Heo * V1.03 is known to be broken. V3.04 is known to 121025985edcSLucas De Marchi * work. Between, there are V1.06, V2.06 and V3.03 1211cedc9bf9STejun Heo * that we don't have much idea about. For now, 1212cedc9bf9STejun Heo * blacklist anything older than V3.04. 12139deb3431STejun Heo * 12149deb3431STejun Heo * http://bugzilla.kernel.org/show_bug.cgi?id=15104 1215cedc9bf9STejun Heo */ 1216cedc9bf9STejun Heo { 1217cedc9bf9STejun Heo .ident = "G725", 1218cedc9bf9STejun Heo .matches = { 1219cedc9bf9STejun Heo DMI_MATCH(DMI_SYS_VENDOR, "eMachines"), 1220cedc9bf9STejun Heo DMI_MATCH(DMI_PRODUCT_NAME, "eMachines G725"), 1221cedc9bf9STejun Heo }, 12229deb3431STejun Heo .driver_data = "20091216", /* V3.04 */ 1223cedc9bf9STejun Heo }, 12249b10ae86STejun Heo { } /* terminate list */ 12259b10ae86STejun Heo }; 12269b10ae86STejun Heo const struct dmi_system_id *dmi = dmi_first_match(sysids); 12279deb3431STejun Heo int year, month, date; 12289deb3431STejun Heo char buf[9]; 12299b10ae86STejun Heo 12309b10ae86STejun Heo if (!dmi || pdev->bus->number || pdev->devfn != PCI_DEVFN(0x1f, 2)) 12319b10ae86STejun Heo return false; 12329b10ae86STejun Heo 12339deb3431STejun Heo dmi_get_date(DMI_BIOS_DATE, &year, &month, &date); 12349deb3431STejun Heo snprintf(buf, sizeof(buf), "%04d%02d%02d", year, month, date); 12359b10ae86STejun Heo 12369deb3431STejun Heo return strcmp(buf, dmi->driver_data) < 0; 12379b10ae86STejun Heo } 12389b10ae86STejun Heo 1239240630e6SHans de Goede static bool ahci_broken_lpm(struct pci_dev *pdev) 1240240630e6SHans de Goede { 1241240630e6SHans de Goede static const struct dmi_system_id sysids[] = { 1242240630e6SHans de Goede /* Various Lenovo 50 series have LPM issues with older BIOSen */ 1243240630e6SHans de Goede { 1244240630e6SHans de Goede .matches = { 1245240630e6SHans de Goede DMI_MATCH(DMI_SYS_VENDOR, "LENOVO"), 1246240630e6SHans de Goede DMI_MATCH(DMI_PRODUCT_VERSION, "ThinkPad X250"), 1247240630e6SHans de Goede }, 1248240630e6SHans de Goede .driver_data = "20180406", /* 1.31 */ 1249240630e6SHans de Goede }, 1250240630e6SHans de Goede { 1251240630e6SHans de Goede .matches = { 1252240630e6SHans de Goede DMI_MATCH(DMI_SYS_VENDOR, "LENOVO"), 1253240630e6SHans de Goede DMI_MATCH(DMI_PRODUCT_VERSION, "ThinkPad L450"), 1254240630e6SHans de Goede }, 1255240630e6SHans de Goede .driver_data = "20180420", /* 1.28 */ 1256240630e6SHans de Goede }, 1257240630e6SHans de Goede { 1258240630e6SHans de Goede .matches = { 1259240630e6SHans de Goede DMI_MATCH(DMI_SYS_VENDOR, "LENOVO"), 1260240630e6SHans de Goede DMI_MATCH(DMI_PRODUCT_VERSION, "ThinkPad T450s"), 1261240630e6SHans de Goede }, 1262240630e6SHans de Goede .driver_data = "20180315", /* 1.33 */ 1263240630e6SHans de Goede }, 1264240630e6SHans de Goede { 1265240630e6SHans de Goede .matches = { 1266240630e6SHans de Goede DMI_MATCH(DMI_SYS_VENDOR, "LENOVO"), 1267240630e6SHans de Goede DMI_MATCH(DMI_PRODUCT_VERSION, "ThinkPad W541"), 1268240630e6SHans de Goede }, 1269240630e6SHans de Goede /* 1270240630e6SHans de Goede * Note date based on release notes, 2.35 has been 1271240630e6SHans de Goede * reported to be good, but I've been unable to get 1272240630e6SHans de Goede * a hold of the reporter to get the DMI BIOS date. 1273240630e6SHans de Goede * TODO: fix this. 1274240630e6SHans de Goede */ 1275240630e6SHans de Goede .driver_data = "20180310", /* 2.35 */ 1276240630e6SHans de Goede }, 1277240630e6SHans de Goede { } /* terminate list */ 1278240630e6SHans de Goede }; 1279240630e6SHans de Goede const struct dmi_system_id *dmi = dmi_first_match(sysids); 1280240630e6SHans de Goede int year, month, date; 1281240630e6SHans de Goede char buf[9]; 1282240630e6SHans de Goede 1283240630e6SHans de Goede if (!dmi) 1284240630e6SHans de Goede return false; 1285240630e6SHans de Goede 1286240630e6SHans de Goede dmi_get_date(DMI_BIOS_DATE, &year, &month, &date); 1287240630e6SHans de Goede snprintf(buf, sizeof(buf), "%04d%02d%02d", year, month, date); 1288240630e6SHans de Goede 1289240630e6SHans de Goede return strcmp(buf, dmi->driver_data) < 0; 1290240630e6SHans de Goede } 1291240630e6SHans de Goede 12925594639aSTejun Heo static bool ahci_broken_online(struct pci_dev *pdev) 12935594639aSTejun Heo { 12945594639aSTejun Heo #define ENCODE_BUSDEVFN(bus, slot, func) \ 12955594639aSTejun Heo (void *)(unsigned long)(((bus) << 8) | PCI_DEVFN((slot), (func))) 12965594639aSTejun Heo static const struct dmi_system_id sysids[] = { 12975594639aSTejun Heo /* 12985594639aSTejun Heo * There are several gigabyte boards which use 12995594639aSTejun Heo * SIMG5723s configured as hardware RAID. Certain 13005594639aSTejun Heo * 5723 firmware revisions shipped there keep the link 13015594639aSTejun Heo * online but fail to answer properly to SRST or 13025594639aSTejun Heo * IDENTIFY when no device is attached downstream 13035594639aSTejun Heo * causing libata to retry quite a few times leading 13045594639aSTejun Heo * to excessive detection delay. 13055594639aSTejun Heo * 13065594639aSTejun Heo * As these firmwares respond to the second reset try 13075594639aSTejun Heo * with invalid device signature, considering unknown 13085594639aSTejun Heo * sig as offline works around the problem acceptably. 13095594639aSTejun Heo */ 13105594639aSTejun Heo { 13115594639aSTejun Heo .ident = "EP45-DQ6", 13125594639aSTejun Heo .matches = { 13135594639aSTejun Heo DMI_MATCH(DMI_BOARD_VENDOR, 13145594639aSTejun Heo "Gigabyte Technology Co., Ltd."), 13155594639aSTejun Heo DMI_MATCH(DMI_BOARD_NAME, "EP45-DQ6"), 13165594639aSTejun Heo }, 13175594639aSTejun Heo .driver_data = ENCODE_BUSDEVFN(0x0a, 0x00, 0), 13185594639aSTejun Heo }, 13195594639aSTejun Heo { 13205594639aSTejun Heo .ident = "EP45-DS5", 13215594639aSTejun Heo .matches = { 13225594639aSTejun Heo DMI_MATCH(DMI_BOARD_VENDOR, 13235594639aSTejun Heo "Gigabyte Technology Co., Ltd."), 13245594639aSTejun Heo DMI_MATCH(DMI_BOARD_NAME, "EP45-DS5"), 13255594639aSTejun Heo }, 13265594639aSTejun Heo .driver_data = ENCODE_BUSDEVFN(0x03, 0x00, 0), 13275594639aSTejun Heo }, 13285594639aSTejun Heo { } /* terminate list */ 13295594639aSTejun Heo }; 13305594639aSTejun Heo #undef ENCODE_BUSDEVFN 13315594639aSTejun Heo const struct dmi_system_id *dmi = dmi_first_match(sysids); 13325594639aSTejun Heo unsigned int val; 13335594639aSTejun Heo 13345594639aSTejun Heo if (!dmi) 13355594639aSTejun Heo return false; 13365594639aSTejun Heo 13375594639aSTejun Heo val = (unsigned long)dmi->driver_data; 13385594639aSTejun Heo 13395594639aSTejun Heo return pdev->bus->number == (val >> 8) && pdev->devfn == (val & 0xff); 13405594639aSTejun Heo } 13415594639aSTejun Heo 13420cf4a7d6SJacob Pan static bool ahci_broken_devslp(struct pci_dev *pdev) 13430cf4a7d6SJacob Pan { 13440cf4a7d6SJacob Pan /* device with broken DEVSLP but still showing SDS capability */ 13450cf4a7d6SJacob Pan static const struct pci_device_id ids[] = { 13460cf4a7d6SJacob Pan { PCI_VDEVICE(INTEL, 0x0f23)}, /* Valleyview SoC */ 13470cf4a7d6SJacob Pan {} 13480cf4a7d6SJacob Pan }; 13490cf4a7d6SJacob Pan 13500cf4a7d6SJacob Pan return pci_match_id(ids, pdev); 13510cf4a7d6SJacob Pan } 13520cf4a7d6SJacob Pan 13538e513217SMarkus Trippelsdorf #ifdef CONFIG_ATA_ACPI 1354f80ae7e4STejun Heo static void ahci_gtf_filter_workaround(struct ata_host *host) 1355f80ae7e4STejun Heo { 1356f80ae7e4STejun Heo static const struct dmi_system_id sysids[] = { 1357f80ae7e4STejun Heo /* 1358f80ae7e4STejun Heo * Aspire 3810T issues a bunch of SATA enable commands 1359f80ae7e4STejun Heo * via _GTF including an invalid one and one which is 1360f80ae7e4STejun Heo * rejected by the device. Among the successful ones 1361f80ae7e4STejun Heo * is FPDMA non-zero offset enable which when enabled 1362f80ae7e4STejun Heo * only on the drive side leads to NCQ command 1363f80ae7e4STejun Heo * failures. Filter it out. 1364f80ae7e4STejun Heo */ 1365f80ae7e4STejun Heo { 1366f80ae7e4STejun Heo .ident = "Aspire 3810T", 1367f80ae7e4STejun Heo .matches = { 1368f80ae7e4STejun Heo DMI_MATCH(DMI_SYS_VENDOR, "Acer"), 1369f80ae7e4STejun Heo DMI_MATCH(DMI_PRODUCT_NAME, "Aspire 3810T"), 1370f80ae7e4STejun Heo }, 1371f80ae7e4STejun Heo .driver_data = (void *)ATA_ACPI_FILTER_FPDMA_OFFSET, 1372f80ae7e4STejun Heo }, 1373f80ae7e4STejun Heo { } 1374f80ae7e4STejun Heo }; 1375f80ae7e4STejun Heo const struct dmi_system_id *dmi = dmi_first_match(sysids); 1376f80ae7e4STejun Heo unsigned int filter; 1377f80ae7e4STejun Heo int i; 1378f80ae7e4STejun Heo 1379f80ae7e4STejun Heo if (!dmi) 1380f80ae7e4STejun Heo return; 1381f80ae7e4STejun Heo 1382f80ae7e4STejun Heo filter = (unsigned long)dmi->driver_data; 1383a44fec1fSJoe Perches dev_info(host->dev, "applying extra ACPI _GTF filter 0x%x for %s\n", 1384f80ae7e4STejun Heo filter, dmi->ident); 1385f80ae7e4STejun Heo 1386f80ae7e4STejun Heo for (i = 0; i < host->n_ports; i++) { 1387f80ae7e4STejun Heo struct ata_port *ap = host->ports[i]; 1388f80ae7e4STejun Heo struct ata_link *link; 1389f80ae7e4STejun Heo struct ata_device *dev; 1390f80ae7e4STejun Heo 1391f80ae7e4STejun Heo ata_for_each_link(link, ap, EDGE) 1392f80ae7e4STejun Heo ata_for_each_dev(dev, link, ALL) 1393f80ae7e4STejun Heo dev->gtf_filter |= filter; 1394f80ae7e4STejun Heo } 1395f80ae7e4STejun Heo } 13968e513217SMarkus Trippelsdorf #else 13978e513217SMarkus Trippelsdorf static inline void ahci_gtf_filter_workaround(struct ata_host *host) 13988e513217SMarkus Trippelsdorf {} 13998e513217SMarkus Trippelsdorf #endif 1400f80ae7e4STejun Heo 14018bfd1743SSui Chen /* 14028bfd1743SSui Chen * On the Acer Aspire Switch Alpha 12, sometimes all SATA ports are detected 14038bfd1743SSui Chen * as DUMMY, or detected but eventually get a "link down" and never get up 14048bfd1743SSui Chen * again. When this happens, CAP.NP may hold a value of 0x00 or 0x01, and the 14058bfd1743SSui Chen * port_map may hold a value of 0x00. 14068bfd1743SSui Chen * 14078bfd1743SSui Chen * Overriding CAP.NP to 0x02 and the port_map to 0x7 will reveal all 3 ports 14088bfd1743SSui Chen * and can significantly reduce the occurrence of the problem. 14098bfd1743SSui Chen * 14108bfd1743SSui Chen * https://bugzilla.kernel.org/show_bug.cgi?id=189471 14118bfd1743SSui Chen */ 14128bfd1743SSui Chen static void acer_sa5_271_workaround(struct ahci_host_priv *hpriv, 14138bfd1743SSui Chen struct pci_dev *pdev) 14148bfd1743SSui Chen { 14158bfd1743SSui Chen static const struct dmi_system_id sysids[] = { 14168bfd1743SSui Chen { 14178bfd1743SSui Chen .ident = "Acer Switch Alpha 12", 14188bfd1743SSui Chen .matches = { 14198bfd1743SSui Chen DMI_MATCH(DMI_SYS_VENDOR, "Acer"), 14208bfd1743SSui Chen DMI_MATCH(DMI_PRODUCT_NAME, "Switch SA5-271") 14218bfd1743SSui Chen }, 14228bfd1743SSui Chen }, 14238bfd1743SSui Chen { } 14248bfd1743SSui Chen }; 14258bfd1743SSui Chen 14268bfd1743SSui Chen if (dmi_check_system(sysids)) { 14278bfd1743SSui Chen dev_info(&pdev->dev, "enabling Acer Switch Alpha 12 workaround\n"); 14288bfd1743SSui Chen if ((hpriv->saved_cap & 0xC734FF00) == 0xC734FF00) { 14298bfd1743SSui Chen hpriv->port_map = 0x7; 14308bfd1743SSui Chen hpriv->cap = 0xC734FF02; 14318bfd1743SSui Chen } 14328bfd1743SSui Chen } 14338bfd1743SSui Chen } 14348bfd1743SSui Chen 1435d243bed3STirumalesh Chalamarla #ifdef CONFIG_ARM64 1436d243bed3STirumalesh Chalamarla /* 1437d243bed3STirumalesh Chalamarla * Due to ERRATA#22536, ThunderX needs to handle HOST_IRQ_STAT differently. 1438d243bed3STirumalesh Chalamarla * Workaround is to make sure all pending IRQs are served before leaving 1439d243bed3STirumalesh Chalamarla * handler. 1440d243bed3STirumalesh Chalamarla */ 1441d243bed3STirumalesh Chalamarla static irqreturn_t ahci_thunderx_irq_handler(int irq, void *dev_instance) 1442d243bed3STirumalesh Chalamarla { 1443d243bed3STirumalesh Chalamarla struct ata_host *host = dev_instance; 1444d243bed3STirumalesh Chalamarla struct ahci_host_priv *hpriv; 1445d243bed3STirumalesh Chalamarla unsigned int rc = 0; 1446d243bed3STirumalesh Chalamarla void __iomem *mmio; 1447d243bed3STirumalesh Chalamarla u32 irq_stat, irq_masked; 1448d243bed3STirumalesh Chalamarla unsigned int handled = 1; 1449d243bed3STirumalesh Chalamarla 1450d243bed3STirumalesh Chalamarla VPRINTK("ENTER\n"); 1451d243bed3STirumalesh Chalamarla hpriv = host->private_data; 1452d243bed3STirumalesh Chalamarla mmio = hpriv->mmio; 1453d243bed3STirumalesh Chalamarla irq_stat = readl(mmio + HOST_IRQ_STAT); 1454d243bed3STirumalesh Chalamarla if (!irq_stat) 1455d243bed3STirumalesh Chalamarla return IRQ_NONE; 1456d243bed3STirumalesh Chalamarla 1457d243bed3STirumalesh Chalamarla do { 1458d243bed3STirumalesh Chalamarla irq_masked = irq_stat & hpriv->port_map; 1459d243bed3STirumalesh Chalamarla spin_lock(&host->lock); 1460d243bed3STirumalesh Chalamarla rc = ahci_handle_port_intr(host, irq_masked); 1461d243bed3STirumalesh Chalamarla if (!rc) 1462d243bed3STirumalesh Chalamarla handled = 0; 1463d243bed3STirumalesh Chalamarla writel(irq_stat, mmio + HOST_IRQ_STAT); 1464d243bed3STirumalesh Chalamarla irq_stat = readl(mmio + HOST_IRQ_STAT); 1465d243bed3STirumalesh Chalamarla spin_unlock(&host->lock); 1466d243bed3STirumalesh Chalamarla } while (irq_stat); 1467d243bed3STirumalesh Chalamarla VPRINTK("EXIT\n"); 1468d243bed3STirumalesh Chalamarla 1469d243bed3STirumalesh Chalamarla return IRQ_RETVAL(handled); 1470d243bed3STirumalesh Chalamarla } 1471d243bed3STirumalesh Chalamarla #endif 1472d243bed3STirumalesh Chalamarla 1473aecec8b6SChristoph Hellwig static void ahci_remap_check(struct pci_dev *pdev, int bar, 1474aecec8b6SChristoph Hellwig struct ahci_host_priv *hpriv) 1475aecec8b6SChristoph Hellwig { 1476aecec8b6SChristoph Hellwig int i, count = 0; 1477aecec8b6SChristoph Hellwig u32 cap; 1478aecec8b6SChristoph Hellwig 1479aecec8b6SChristoph Hellwig /* 1480aecec8b6SChristoph Hellwig * Check if this device might have remapped nvme devices. 1481aecec8b6SChristoph Hellwig */ 1482aecec8b6SChristoph Hellwig if (pdev->vendor != PCI_VENDOR_ID_INTEL || 1483aecec8b6SChristoph Hellwig pci_resource_len(pdev, bar) < SZ_512K || 1484aecec8b6SChristoph Hellwig bar != AHCI_PCI_BAR_STANDARD || 1485aecec8b6SChristoph Hellwig !(readl(hpriv->mmio + AHCI_VSCAP) & 1)) 1486aecec8b6SChristoph Hellwig return; 1487aecec8b6SChristoph Hellwig 1488aecec8b6SChristoph Hellwig cap = readq(hpriv->mmio + AHCI_REMAP_CAP); 1489aecec8b6SChristoph Hellwig for (i = 0; i < AHCI_MAX_REMAP; i++) { 1490aecec8b6SChristoph Hellwig if ((cap & (1 << i)) == 0) 1491aecec8b6SChristoph Hellwig continue; 1492aecec8b6SChristoph Hellwig if (readl(hpriv->mmio + ahci_remap_dcc(i)) 1493aecec8b6SChristoph Hellwig != PCI_CLASS_STORAGE_EXPRESS) 1494aecec8b6SChristoph Hellwig continue; 1495aecec8b6SChristoph Hellwig 1496aecec8b6SChristoph Hellwig /* We've found a remapped device */ 1497aecec8b6SChristoph Hellwig count++; 1498aecec8b6SChristoph Hellwig } 1499aecec8b6SChristoph Hellwig 1500aecec8b6SChristoph Hellwig if (!count) 1501aecec8b6SChristoph Hellwig return; 1502aecec8b6SChristoph Hellwig 1503aecec8b6SChristoph Hellwig dev_warn(&pdev->dev, "Found %d remapped NVMe devices.\n", count); 1504f723fa4eSChristoph Hellwig dev_warn(&pdev->dev, 1505f723fa4eSChristoph Hellwig "Switch your BIOS from RAID to AHCI mode to use them.\n"); 1506f723fa4eSChristoph Hellwig 1507f723fa4eSChristoph Hellwig /* 1508f723fa4eSChristoph Hellwig * Don't rely on the msi-x capability in the remap case, 1509f723fa4eSChristoph Hellwig * share the legacy interrupt across ahci and remapped devices. 1510f723fa4eSChristoph Hellwig */ 1511f723fa4eSChristoph Hellwig hpriv->flags |= AHCI_HFLAG_NO_MSI; 1512aecec8b6SChristoph Hellwig } 1513aecec8b6SChristoph Hellwig 15140b9e2988SChristoph Hellwig static int ahci_get_irq_vector(struct ata_host *host, int port) 1515ee2aad42SRobert Richter { 15160b9e2988SChristoph Hellwig return pci_irq_vector(to_pci_dev(host->dev), port); 1517ee2aad42SRobert Richter } 1518ee2aad42SRobert Richter 1519a1c82311SRobert Richter static int ahci_init_msi(struct pci_dev *pdev, unsigned int n_ports, 15207b92b4f6SAlexander Gordeev struct ahci_host_priv *hpriv) 15215ca72c4fSAlexander Gordeev { 15220b9e2988SChristoph Hellwig int nvec; 15235ca72c4fSAlexander Gordeev 15247b92b4f6SAlexander Gordeev if (hpriv->flags & AHCI_HFLAG_NO_MSI) 1525a1c82311SRobert Richter return -ENODEV; 15267b92b4f6SAlexander Gordeev 15275ca72c4fSAlexander Gordeev /* 15287b92b4f6SAlexander Gordeev * If number of MSIs is less than number of ports then Sharing Last 15297b92b4f6SAlexander Gordeev * Message mode could be enforced. In this case assume that advantage 15307b92b4f6SAlexander Gordeev * of multipe MSIs is negated and use single MSI mode instead. 15315ca72c4fSAlexander Gordeev */ 153217a51f12SChristoph Hellwig if (n_ports > 1) { 15330b9e2988SChristoph Hellwig nvec = pci_alloc_irq_vectors(pdev, n_ports, INT_MAX, 15340b9e2988SChristoph Hellwig PCI_IRQ_MSIX | PCI_IRQ_MSI); 15350b9e2988SChristoph Hellwig if (nvec > 0) { 15360b9e2988SChristoph Hellwig if (!(readl(hpriv->mmio + HOST_CTL) & HOST_MRSM)) { 15370b9e2988SChristoph Hellwig hpriv->get_irq_vector = ahci_get_irq_vector; 1538c3ebd6a9SAlexander Gordeev hpriv->flags |= AHCI_HFLAG_MULTI_MSI; 153921bfd1aaSRobert Richter return nvec; 1540a1c82311SRobert Richter } 1541a1c82311SRobert Richter 1542d684a90dSDan Williams /* 154317a51f12SChristoph Hellwig * Fallback to single MSI mode if the controller 154417a51f12SChristoph Hellwig * enforced MRSM mode. 1545d684a90dSDan Williams */ 154617a51f12SChristoph Hellwig printk(KERN_INFO 154717a51f12SChristoph Hellwig "ahci: MRSM is on, fallback to single MSI\n"); 15480b9e2988SChristoph Hellwig pci_free_irq_vectors(pdev); 15490b9e2988SChristoph Hellwig } 1550a478b097SChristoph Hellwig } 1551d684a90dSDan Williams 15520b9e2988SChristoph Hellwig /* 15530b9e2988SChristoph Hellwig * If the host is not capable of supporting per-port vectors, fall 15540b9e2988SChristoph Hellwig * back to single MSI before finally attempting single MSI-X. 15550b9e2988SChristoph Hellwig */ 15560b9e2988SChristoph Hellwig nvec = pci_alloc_irq_vectors(pdev, 1, 1, PCI_IRQ_MSI); 15570b9e2988SChristoph Hellwig if (nvec == 1) 1558a1c82311SRobert Richter return nvec; 15590b9e2988SChristoph Hellwig return pci_alloc_irq_vectors(pdev, 1, 1, PCI_IRQ_MSIX); 15605ca72c4fSAlexander Gordeev } 15615ca72c4fSAlexander Gordeev 1562b1a9585cSSrinivas Pandruvada static void ahci_update_initial_lpm_policy(struct ata_port *ap, 1563b1a9585cSSrinivas Pandruvada struct ahci_host_priv *hpriv) 1564b1a9585cSSrinivas Pandruvada { 1565b1a9585cSSrinivas Pandruvada int policy = CONFIG_SATA_MOBILE_LPM_POLICY; 1566b1a9585cSSrinivas Pandruvada 1567b1a9585cSSrinivas Pandruvada 1568b1a9585cSSrinivas Pandruvada /* Ignore processing for non mobile platforms */ 1569b1a9585cSSrinivas Pandruvada if (!(hpriv->flags & AHCI_HFLAG_IS_MOBILE)) 1570b1a9585cSSrinivas Pandruvada return; 1571b1a9585cSSrinivas Pandruvada 1572b1a9585cSSrinivas Pandruvada /* user modified policy via module param */ 1573b1a9585cSSrinivas Pandruvada if (mobile_lpm_policy != -1) { 1574b1a9585cSSrinivas Pandruvada policy = mobile_lpm_policy; 1575b1a9585cSSrinivas Pandruvada goto update_policy; 1576b1a9585cSSrinivas Pandruvada } 1577b1a9585cSSrinivas Pandruvada 1578b1a9585cSSrinivas Pandruvada #ifdef CONFIG_ACPI 1579b1a9585cSSrinivas Pandruvada if (policy > ATA_LPM_MED_POWER && 1580b1a9585cSSrinivas Pandruvada (acpi_gbl_FADT.flags & ACPI_FADT_LOW_POWER_S0)) { 1581b1a9585cSSrinivas Pandruvada if (hpriv->cap & HOST_CAP_PART) 1582b1a9585cSSrinivas Pandruvada policy = ATA_LPM_MIN_POWER_WITH_PARTIAL; 1583b1a9585cSSrinivas Pandruvada else if (hpriv->cap & HOST_CAP_SSC) 1584b1a9585cSSrinivas Pandruvada policy = ATA_LPM_MIN_POWER; 1585b1a9585cSSrinivas Pandruvada } 1586b1a9585cSSrinivas Pandruvada #endif 1587b1a9585cSSrinivas Pandruvada 1588b1a9585cSSrinivas Pandruvada update_policy: 1589b1a9585cSSrinivas Pandruvada if (policy >= ATA_LPM_UNKNOWN && policy <= ATA_LPM_MIN_POWER) 1590b1a9585cSSrinivas Pandruvada ap->target_lpm_policy = policy; 1591b1a9585cSSrinivas Pandruvada } 1592b1a9585cSSrinivas Pandruvada 1593c312ef17SDan Williams static void ahci_intel_pcs_quirk(struct pci_dev *pdev, struct ahci_host_priv *hpriv) 1594c312ef17SDan Williams { 1595c312ef17SDan Williams const struct pci_device_id *id = pci_match_id(ahci_pci_tbl, pdev); 1596c312ef17SDan Williams u16 tmp16; 1597c312ef17SDan Williams 1598c312ef17SDan Williams /* 1599c312ef17SDan Williams * Only apply the 6-port PCS quirk for known legacy platforms. 1600c312ef17SDan Williams */ 1601c312ef17SDan Williams if (!id || id->vendor != PCI_VENDOR_ID_INTEL) 1602c312ef17SDan Williams return; 160309d6ac8dSDan Williams 160409d6ac8dSDan Williams /* Skip applying the quirk on Denverton and beyond */ 160509d6ac8dSDan Williams if (((enum board_ids) id->driver_data) >= board_ahci_pcs7) 1606c312ef17SDan Williams return; 1607c312ef17SDan Williams 1608c312ef17SDan Williams /* 1609c312ef17SDan Williams * port_map is determined from PORTS_IMPL PCI register which is 1610c312ef17SDan Williams * implemented as write or write-once register. If the register 1611c312ef17SDan Williams * isn't programmed, ahci automatically generates it from number 1612c312ef17SDan Williams * of ports, which is good enough for PCS programming. It is 1613c312ef17SDan Williams * otherwise expected that platform firmware enables the ports 1614c312ef17SDan Williams * before the OS boots. 1615c312ef17SDan Williams */ 1616c312ef17SDan Williams pci_read_config_word(pdev, PCS_6, &tmp16); 1617c312ef17SDan Williams if ((tmp16 & hpriv->port_map) != hpriv->port_map) { 1618c312ef17SDan Williams tmp16 |= hpriv->port_map; 1619c312ef17SDan Williams pci_write_config_word(pdev, PCS_6, tmp16); 1620c312ef17SDan Williams } 1621c312ef17SDan Williams } 1622c312ef17SDan Williams 1623c6fd2807SJeff Garzik static int ahci_init_one(struct pci_dev *pdev, const struct pci_device_id *ent) 1624c6fd2807SJeff Garzik { 1625e297d99eSTejun Heo unsigned int board_id = ent->driver_data; 1626e297d99eSTejun Heo struct ata_port_info pi = ahci_port_info[board_id]; 16274447d351STejun Heo const struct ata_port_info *ppi[] = { &pi, NULL }; 162824dc5f33STejun Heo struct device *dev = &pdev->dev; 1629c6fd2807SJeff Garzik struct ahci_host_priv *hpriv; 16304447d351STejun Heo struct ata_host *host; 1631c3ebd6a9SAlexander Gordeev int n_ports, i, rc; 1632318893e1SAlessandro Rubini int ahci_pci_bar = AHCI_PCI_BAR_STANDARD; 1633c6fd2807SJeff Garzik 1634c6fd2807SJeff Garzik VPRINTK("ENTER\n"); 1635c6fd2807SJeff Garzik 1636b429dd59SJustin P. Mattock WARN_ON((int)ATA_MAX_QUEUE > AHCI_MAX_CMDS); 1637c6fd2807SJeff Garzik 163806296a1eSJoe Perches ata_print_version_once(&pdev->dev, DRV_VERSION); 1639c6fd2807SJeff Garzik 16405b66c829SAlan Cox /* The AHCI driver can only drive the SATA ports, the PATA driver 16415b66c829SAlan Cox can drive them all so if both drivers are selected make sure 16425b66c829SAlan Cox AHCI stays out of the way */ 16435b66c829SAlan Cox if (pdev->vendor == PCI_VENDOR_ID_MARVELL && !marvell_enable) 16445b66c829SAlan Cox return -ENODEV; 16455b66c829SAlan Cox 1646cb85696dSJames Laird /* Apple BIOS on MCP89 prevents us using AHCI */ 1647cb85696dSJames Laird if (is_mcp89_apple(pdev)) 1648cb85696dSJames Laird ahci_mcp89_apple_enable(pdev); 1649c6353b45STejun Heo 16507a02267eSMark Nelson /* Promise's PDC42819 is a SAS/SATA controller that has an AHCI mode. 16517a02267eSMark Nelson * At the moment, we can only use the AHCI mode. Let the users know 16527a02267eSMark Nelson * that for SAS drives they're out of luck. 16537a02267eSMark Nelson */ 16547a02267eSMark Nelson if (pdev->vendor == PCI_VENDOR_ID_PROMISE) 1655a44fec1fSJoe Perches dev_info(&pdev->dev, 1656a44fec1fSJoe Perches "PDC42819 can only drive SATA devices with this driver\n"); 16577a02267eSMark Nelson 1658b7ae128dSRobert Richter /* Some devices use non-standard BARs */ 1659318893e1SAlessandro Rubini if (pdev->vendor == PCI_VENDOR_ID_STMICRO && pdev->device == 0xCC06) 1660318893e1SAlessandro Rubini ahci_pci_bar = AHCI_PCI_BAR_STA2X11; 16617f9c9f8eSHugh Daschbach else if (pdev->vendor == 0x1c44 && pdev->device == 0x8000) 16627f9c9f8eSHugh Daschbach ahci_pci_bar = AHCI_PCI_BAR_ENMOTUS; 1663b1314e3fSRadha Mohan Chintakuntla else if (pdev->vendor == PCI_VENDOR_ID_CAVIUM) { 1664b1314e3fSRadha Mohan Chintakuntla if (pdev->device == 0xa01c) 1665b7ae128dSRobert Richter ahci_pci_bar = AHCI_PCI_BAR_CAVIUM; 1666b1314e3fSRadha Mohan Chintakuntla if (pdev->device == 0xa084) 1667b1314e3fSRadha Mohan Chintakuntla ahci_pci_bar = AHCI_PCI_BAR_CAVIUM_GEN5; 1668b1314e3fSRadha Mohan Chintakuntla } 1669318893e1SAlessandro Rubini 16704447d351STejun Heo /* acquire resources */ 167124dc5f33STejun Heo rc = pcim_enable_device(pdev); 1672c6fd2807SJeff Garzik if (rc) 1673c6fd2807SJeff Garzik return rc; 1674c6fd2807SJeff Garzik 1675c4f7792cSTejun Heo if (pdev->vendor == PCI_VENDOR_ID_INTEL && 1676c4f7792cSTejun Heo (pdev->device == 0x2652 || pdev->device == 0x2653)) { 1677c4f7792cSTejun Heo u8 map; 1678c4f7792cSTejun Heo 1679c4f7792cSTejun Heo /* ICH6s share the same PCI ID for both piix and ahci 1680c4f7792cSTejun Heo * modes. Enabling ahci mode while MAP indicates 1681c4f7792cSTejun Heo * combined mode is a bad idea. Yield to ata_piix. 1682c4f7792cSTejun Heo */ 1683c4f7792cSTejun Heo pci_read_config_byte(pdev, ICH_MAP, &map); 1684c4f7792cSTejun Heo if (map & 0x3) { 1685a44fec1fSJoe Perches dev_info(&pdev->dev, 1686a44fec1fSJoe Perches "controller is in combined mode, can't enable AHCI mode\n"); 1687c4f7792cSTejun Heo return -ENODEV; 1688c4f7792cSTejun Heo } 1689c4f7792cSTejun Heo } 1690c4f7792cSTejun Heo 16916fec8871SPaul Bolle /* AHCI controllers often implement SFF compatible interface. 16926fec8871SPaul Bolle * Grab all PCI BARs just in case. 16936fec8871SPaul Bolle */ 16946fec8871SPaul Bolle rc = pcim_iomap_regions_request_all(pdev, 1 << ahci_pci_bar, DRV_NAME); 16956fec8871SPaul Bolle if (rc == -EBUSY) 16966fec8871SPaul Bolle pcim_pin_device(pdev); 16976fec8871SPaul Bolle if (rc) 16986fec8871SPaul Bolle return rc; 16996fec8871SPaul Bolle 170024dc5f33STejun Heo hpriv = devm_kzalloc(dev, sizeof(*hpriv), GFP_KERNEL); 170124dc5f33STejun Heo if (!hpriv) 170224dc5f33STejun Heo return -ENOMEM; 1703417a1a6dSTejun Heo hpriv->flags |= (unsigned long)pi.private_data; 1704417a1a6dSTejun Heo 1705e297d99eSTejun Heo /* MCP65 revision A1 and A2 can't do MSI */ 1706e297d99eSTejun Heo if (board_id == board_ahci_mcp65 && 1707e297d99eSTejun Heo (pdev->revision == 0xa1 || pdev->revision == 0xa2)) 1708e297d99eSTejun Heo hpriv->flags |= AHCI_HFLAG_NO_MSI; 1709e297d99eSTejun Heo 1710e427fe04SShane Huang /* SB800 does NOT need the workaround to ignore SERR_INTERNAL */ 1711e427fe04SShane Huang if (board_id == board_ahci_sb700 && pdev->revision >= 0x40) 1712e427fe04SShane Huang hpriv->flags &= ~AHCI_HFLAG_IGN_SERR_INTERNAL; 1713e427fe04SShane Huang 17142fcad9d2STejun Heo /* only some SB600s can do 64bit DMA */ 17152fcad9d2STejun Heo if (ahci_sb600_enable_64bit(pdev)) 17162fcad9d2STejun Heo hpriv->flags &= ~AHCI_HFLAG_32BIT_ONLY; 171758a09b38SShane Huang 1718318893e1SAlessandro Rubini hpriv->mmio = pcim_iomap_table(pdev)[ahci_pci_bar]; 1719d8993349SAnton Vorontsov 1720aecec8b6SChristoph Hellwig /* detect remapped nvme devices */ 1721aecec8b6SChristoph Hellwig ahci_remap_check(pdev, ahci_pci_bar, hpriv); 1722aecec8b6SChristoph Hellwig 17230cf4a7d6SJacob Pan /* must set flag prior to save config in order to take effect */ 17240cf4a7d6SJacob Pan if (ahci_broken_devslp(pdev)) 17250cf4a7d6SJacob Pan hpriv->flags |= AHCI_HFLAG_NO_DEVSLP; 17260cf4a7d6SJacob Pan 1727d243bed3STirumalesh Chalamarla #ifdef CONFIG_ARM64 1728d243bed3STirumalesh Chalamarla if (pdev->vendor == 0x177d && pdev->device == 0xa01c) 1729d243bed3STirumalesh Chalamarla hpriv->irq_handler = ahci_thunderx_irq_handler; 1730d243bed3STirumalesh Chalamarla #endif 1731d243bed3STirumalesh Chalamarla 17324447d351STejun Heo /* save initial config */ 1733394d6e53SAnton Vorontsov ahci_pci_save_initial_config(pdev, hpriv); 1734c6fd2807SJeff Garzik 1735c312ef17SDan Williams /* 1736c312ef17SDan Williams * If platform firmware failed to enable ports, try to enable 1737c312ef17SDan Williams * them here. 1738c312ef17SDan Williams */ 1739c312ef17SDan Williams ahci_intel_pcs_quirk(pdev, hpriv); 1740c312ef17SDan Williams 17414447d351STejun Heo /* prepare host */ 1742453d3131SRobert Hancock if (hpriv->cap & HOST_CAP_NCQ) { 1743453d3131SRobert Hancock pi.flags |= ATA_FLAG_NCQ; 174483f2b963STejun Heo /* 174583f2b963STejun Heo * Auto-activate optimization is supposed to be 174683f2b963STejun Heo * supported on all AHCI controllers indicating NCQ 174783f2b963STejun Heo * capability, but it seems to be broken on some 174883f2b963STejun Heo * chipsets including NVIDIAs. 174983f2b963STejun Heo */ 175083f2b963STejun Heo if (!(hpriv->flags & AHCI_HFLAG_NO_FPDMA_AA)) 1751453d3131SRobert Hancock pi.flags |= ATA_FLAG_FPDMA_AA; 175240fb59e7SMarc Carino 175340fb59e7SMarc Carino /* 175440fb59e7SMarc Carino * All AHCI controllers should be forward-compatible 175540fb59e7SMarc Carino * with the new auxiliary field. This code should be 175640fb59e7SMarc Carino * conditionalized if any buggy AHCI controllers are 175740fb59e7SMarc Carino * encountered. 175840fb59e7SMarc Carino */ 175940fb59e7SMarc Carino pi.flags |= ATA_FLAG_FPDMA_AUX; 1760453d3131SRobert Hancock } 17614447d351STejun Heo 17627d50b60bSTejun Heo if (hpriv->cap & HOST_CAP_PMP) 17637d50b60bSTejun Heo pi.flags |= ATA_FLAG_PMP; 17647d50b60bSTejun Heo 17650cbb0e77SAnton Vorontsov ahci_set_em_messages(hpriv, &pi); 176618f7ba4cSKristen Carlson Accardi 17671fd68434SRafael J. Wysocki if (ahci_broken_system_poweroff(pdev)) { 17681fd68434SRafael J. Wysocki pi.flags |= ATA_FLAG_NO_POWEROFF_SPINDOWN; 17691fd68434SRafael J. Wysocki dev_info(&pdev->dev, 17701fd68434SRafael J. Wysocki "quirky BIOS, skipping spindown on poweroff\n"); 17711fd68434SRafael J. Wysocki } 17721fd68434SRafael J. Wysocki 1773240630e6SHans de Goede if (ahci_broken_lpm(pdev)) { 1774240630e6SHans de Goede pi.flags |= ATA_FLAG_NO_LPM; 1775240630e6SHans de Goede dev_warn(&pdev->dev, 1776240630e6SHans de Goede "BIOS update required for Link Power Management support\n"); 1777240630e6SHans de Goede } 1778240630e6SHans de Goede 17799b10ae86STejun Heo if (ahci_broken_suspend(pdev)) { 17809b10ae86STejun Heo hpriv->flags |= AHCI_HFLAG_NO_SUSPEND; 1781a44fec1fSJoe Perches dev_warn(&pdev->dev, 17829b10ae86STejun Heo "BIOS update required for suspend/resume\n"); 17839b10ae86STejun Heo } 17849b10ae86STejun Heo 17855594639aSTejun Heo if (ahci_broken_online(pdev)) { 17865594639aSTejun Heo hpriv->flags |= AHCI_HFLAG_SRST_TOUT_IS_OFFLINE; 17875594639aSTejun Heo dev_info(&pdev->dev, 17885594639aSTejun Heo "online status unreliable, applying workaround\n"); 17895594639aSTejun Heo } 17905594639aSTejun Heo 17918bfd1743SSui Chen 17928bfd1743SSui Chen /* Acer SA5-271 workaround modifies private_data */ 17938bfd1743SSui Chen acer_sa5_271_workaround(hpriv, pdev); 17948bfd1743SSui Chen 1795837f5f8fSTejun Heo /* CAP.NP sometimes indicate the index of the last enabled 1796837f5f8fSTejun Heo * port, at other times, that of the last possible port, so 1797837f5f8fSTejun Heo * determining the maximum port number requires looking at 1798837f5f8fSTejun Heo * both CAP.NP and port_map. 1799837f5f8fSTejun Heo */ 1800837f5f8fSTejun Heo n_ports = max(ahci_nr_ports(hpriv->cap), fls(hpriv->port_map)); 1801837f5f8fSTejun Heo 1802837f5f8fSTejun Heo host = ata_host_alloc_pinfo(&pdev->dev, ppi, n_ports); 18034447d351STejun Heo if (!host) 18044447d351STejun Heo return -ENOMEM; 18054447d351STejun Heo host->private_data = hpriv; 18060b9e2988SChristoph Hellwig 18070b9e2988SChristoph Hellwig if (ahci_init_msi(pdev, n_ports, hpriv) < 0) { 18080b9e2988SChristoph Hellwig /* legacy intx interrupts */ 18090b9e2988SChristoph Hellwig pci_intx(pdev, 1); 18100b9e2988SChristoph Hellwig } 18110ce57f8aSChristoph Hellwig hpriv->irq = pci_irq_vector(pdev, 0); 181221bfd1aaSRobert Richter 1813f3d7f23fSArjan van de Ven if (!(hpriv->cap & HOST_CAP_SSS) || ahci_ignore_sss) 1814886ad09fSArjan van de Ven host->flags |= ATA_HOST_PARALLEL_SCAN; 1815f3d7f23fSArjan van de Ven else 1816d2782d96SJingoo Han dev_info(&pdev->dev, "SSS flag set, parallel bus scan disabled\n"); 1817886ad09fSArjan van de Ven 181818f7ba4cSKristen Carlson Accardi if (pi.flags & ATA_FLAG_EM) 181918f7ba4cSKristen Carlson Accardi ahci_reset_em(host); 182018f7ba4cSKristen Carlson Accardi 18214447d351STejun Heo for (i = 0; i < host->n_ports; i++) { 18224447d351STejun Heo struct ata_port *ap = host->ports[i]; 18234447d351STejun Heo 1824318893e1SAlessandro Rubini ata_port_pbar_desc(ap, ahci_pci_bar, -1, "abar"); 1825318893e1SAlessandro Rubini ata_port_pbar_desc(ap, ahci_pci_bar, 1826cbcdd875STejun Heo 0x100 + ap->port_no * 0x80, "port"); 1827cbcdd875STejun Heo 182818f7ba4cSKristen Carlson Accardi /* set enclosure management message type */ 182918f7ba4cSKristen Carlson Accardi if (ap->flags & ATA_FLAG_EM) 1830008dbd61SHarry Zhang ap->em_message_type = hpriv->em_msg_type; 183118f7ba4cSKristen Carlson Accardi 1832b1a9585cSSrinivas Pandruvada ahci_update_initial_lpm_policy(ap, hpriv); 183318f7ba4cSKristen Carlson Accardi 1834dab632e8SJeff Garzik /* disabled/not-implemented port */ 1835350756f6STejun Heo if (!(hpriv->port_map & (1 << i))) 1836dab632e8SJeff Garzik ap->ops = &ata_dummy_port_ops; 18374447d351STejun Heo } 1838c6fd2807SJeff Garzik 1839edc93052STejun Heo /* apply workaround for ASUS P5W DH Deluxe mainboard */ 1840edc93052STejun Heo ahci_p5wdh_workaround(host); 1841edc93052STejun Heo 1842f80ae7e4STejun Heo /* apply gtf filter quirk */ 1843f80ae7e4STejun Heo ahci_gtf_filter_workaround(host); 1844f80ae7e4STejun Heo 1845c6fd2807SJeff Garzik /* initialize adapter */ 18464447d351STejun Heo rc = ahci_configure_dma_masks(pdev, hpriv->cap & HOST_CAP_64); 1847c6fd2807SJeff Garzik if (rc) 184824dc5f33STejun Heo return rc; 1849c6fd2807SJeff Garzik 1850c312ef17SDan Williams rc = ahci_reset_controller(host); 18514447d351STejun Heo if (rc) 18524447d351STejun Heo return rc; 1853c6fd2807SJeff Garzik 1854781d6550SAnton Vorontsov ahci_pci_init_controller(host); 1855439fcaecSAnton Vorontsov ahci_pci_print_info(host); 1856c6fd2807SJeff Garzik 18574447d351STejun Heo pci_set_master(pdev); 18585ca72c4fSAlexander Gordeev 185902e53293SMika Westerberg rc = ahci_host_activate(host, &ahci_sht); 186002e53293SMika Westerberg if (rc) 186102e53293SMika Westerberg return rc; 186202e53293SMika Westerberg 186302e53293SMika Westerberg pm_runtime_put_noidle(&pdev->dev); 186402e53293SMika Westerberg return 0; 186502e53293SMika Westerberg } 186602e53293SMika Westerberg 186702e53293SMika Westerberg static void ahci_remove_one(struct pci_dev *pdev) 186802e53293SMika Westerberg { 186902e53293SMika Westerberg pm_runtime_get_noresume(&pdev->dev); 187002e53293SMika Westerberg ata_pci_remove_one(pdev); 1871c6fd2807SJeff Garzik } 1872c6fd2807SJeff Garzik 18732fc75da0SAxel Lin module_pci_driver(ahci_pci_driver); 1874c6fd2807SJeff Garzik 1875c6fd2807SJeff Garzik MODULE_AUTHOR("Jeff Garzik"); 1876c6fd2807SJeff Garzik MODULE_DESCRIPTION("AHCI SATA low-level driver"); 1877c6fd2807SJeff Garzik MODULE_LICENSE("GPL"); 1878c6fd2807SJeff Garzik MODULE_DEVICE_TABLE(pci, ahci_pci_tbl); 1879c6fd2807SJeff Garzik MODULE_VERSION(DRV_VERSION); 1880