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, 43e49bd683STiezhu Yang AHCI_PCI_BAR_LOONGSON = 0, 447f9c9f8eSHugh Daschbach AHCI_PCI_BAR_ENMOTUS = 2, 45b1314e3fSRadha Mohan Chintakuntla AHCI_PCI_BAR_CAVIUM_GEN5 = 4, 46318893e1SAlessandro Rubini AHCI_PCI_BAR_STANDARD = 5, 47441577efSTejun Heo }; 48c6fd2807SJeff Garzik 49441577efSTejun Heo enum board_ids { 50441577efSTejun Heo /* board IDs by feature in alphabetical order */ 51441577efSTejun Heo board_ahci, 52441577efSTejun Heo board_ahci_ign_iferr, 53ebb82e3cSHans de Goede board_ahci_mobile, 5466a7cbc3STejun Heo board_ahci_nomsi, 5567809f85SLevente Kurusa board_ahci_noncq, 56441577efSTejun Heo board_ahci_nosntf, 575f173107STejun Heo board_ahci_yes_fbs, 58441577efSTejun Heo 59441577efSTejun Heo /* board IDs for specific chipsets in alphabetical order */ 607d523bdcSHanna Hawa board_ahci_al, 61dbfe8ef5SDan Williams board_ahci_avn, 62441577efSTejun Heo board_ahci_mcp65, 6383f2b963STejun Heo board_ahci_mcp77, 6483f2b963STejun Heo board_ahci_mcp89, 65441577efSTejun Heo board_ahci_mv, 66441577efSTejun Heo board_ahci_sb600, 67441577efSTejun Heo board_ahci_sb700, /* for SB700 and SB800 */ 68441577efSTejun Heo board_ahci_vt8251, 69441577efSTejun Heo 70c312ef17SDan Williams /* 71c312ef17SDan Williams * board IDs for Intel chipsets that support more than 6 ports 72c312ef17SDan Williams * *and* end up needing the PCS quirk. 73c312ef17SDan Williams */ 74c312ef17SDan Williams board_ahci_pcs7, 75c312ef17SDan Williams 76441577efSTejun Heo /* aliases */ 77441577efSTejun Heo board_ahci_mcp_linux = board_ahci_mcp65, 78441577efSTejun Heo board_ahci_mcp67 = board_ahci_mcp65, 79441577efSTejun Heo board_ahci_mcp73 = board_ahci_mcp65, 8083f2b963STejun Heo board_ahci_mcp79 = board_ahci_mcp77, 81c6fd2807SJeff Garzik }; 82c6fd2807SJeff Garzik 83c6fd2807SJeff Garzik static int ahci_init_one(struct pci_dev *pdev, const struct pci_device_id *ent); 8402e53293SMika Westerberg static void ahci_remove_one(struct pci_dev *dev); 8510a663a1SPrabhakar Kushwaha static void ahci_shutdown_one(struct pci_dev *dev); 86a1efdabaSTejun Heo static int ahci_vt8251_hardreset(struct ata_link *link, unsigned int *class, 87a1efdabaSTejun Heo unsigned long deadline); 88dbfe8ef5SDan Williams static int ahci_avn_hardreset(struct ata_link *link, unsigned int *class, 89dbfe8ef5SDan Williams unsigned long deadline); 90cb85696dSJames Laird static void ahci_mcp89_apple_enable(struct pci_dev *pdev); 91cb85696dSJames Laird static bool is_mcp89_apple(struct pci_dev *pdev); 92a1efdabaSTejun Heo static int ahci_p5wdh_hardreset(struct ata_link *link, unsigned int *class, 93a1efdabaSTejun Heo unsigned long deadline); 9402e53293SMika Westerberg #ifdef CONFIG_PM 9502e53293SMika Westerberg static int ahci_pci_device_runtime_suspend(struct device *dev); 9602e53293SMika Westerberg static int ahci_pci_device_runtime_resume(struct device *dev); 97f1d848f9SMika Westerberg #ifdef CONFIG_PM_SLEEP 98f1d848f9SMika Westerberg static int ahci_pci_device_suspend(struct device *dev); 99f1d848f9SMika Westerberg static int ahci_pci_device_resume(struct device *dev); 100438ac6d5STejun Heo #endif 10102e53293SMika Westerberg #endif /* CONFIG_PM */ 102c6fd2807SJeff Garzik 103fad16e7aSTejun Heo static struct scsi_host_template ahci_sht = { 104fad16e7aSTejun Heo AHCI_SHT("ahci"), 105fad16e7aSTejun Heo }; 106fad16e7aSTejun Heo 107029cfd6bSTejun Heo static struct ata_port_operations ahci_vt8251_ops = { 108029cfd6bSTejun Heo .inherits = &ahci_ops, 109a1efdabaSTejun Heo .hardreset = ahci_vt8251_hardreset, 110ad616ffbSTejun Heo }; 111ad616ffbSTejun Heo 112029cfd6bSTejun Heo static struct ata_port_operations ahci_p5wdh_ops = { 113029cfd6bSTejun Heo .inherits = &ahci_ops, 114a1efdabaSTejun Heo .hardreset = ahci_p5wdh_hardreset, 115edc93052STejun Heo }; 116edc93052STejun Heo 117dbfe8ef5SDan Williams static struct ata_port_operations ahci_avn_ops = { 118dbfe8ef5SDan Williams .inherits = &ahci_ops, 119dbfe8ef5SDan Williams .hardreset = ahci_avn_hardreset, 120dbfe8ef5SDan Williams }; 121dbfe8ef5SDan Williams 122c6fd2807SJeff Garzik static const struct ata_port_info ahci_port_info[] = { 123441577efSTejun Heo /* by features */ 124facb8fa6SJeffrin Jose [board_ahci] = { 1251188c0d8STejun Heo .flags = AHCI_FLAG_COMMON, 12614bdef98SErik Inge Bolsø .pio_mask = ATA_PIO4, 127469248abSJeff Garzik .udma_mask = ATA_UDMA6, 128c6fd2807SJeff Garzik .port_ops = &ahci_ops, 129c6fd2807SJeff Garzik }, 130facb8fa6SJeffrin Jose [board_ahci_ign_iferr] = { 131417a1a6dSTejun Heo AHCI_HFLAGS (AHCI_HFLAG_IGN_IRQ_IF_ERR), 132417a1a6dSTejun Heo .flags = AHCI_FLAG_COMMON, 13314bdef98SErik Inge Bolsø .pio_mask = ATA_PIO4, 134469248abSJeff Garzik .udma_mask = ATA_UDMA6, 13541669553STejun Heo .port_ops = &ahci_ops, 13641669553STejun Heo }, 137ebb82e3cSHans de Goede [board_ahci_mobile] = { 138ebb82e3cSHans de Goede AHCI_HFLAGS (AHCI_HFLAG_IS_MOBILE), 139ebb82e3cSHans de Goede .flags = AHCI_FLAG_COMMON, 140ebb82e3cSHans de Goede .pio_mask = ATA_PIO4, 141ebb82e3cSHans de Goede .udma_mask = ATA_UDMA6, 142ebb82e3cSHans de Goede .port_ops = &ahci_ops, 143ebb82e3cSHans de Goede }, 14466a7cbc3STejun Heo [board_ahci_nomsi] = { 14566a7cbc3STejun Heo AHCI_HFLAGS (AHCI_HFLAG_NO_MSI), 14666a7cbc3STejun Heo .flags = AHCI_FLAG_COMMON, 14766a7cbc3STejun Heo .pio_mask = ATA_PIO4, 14866a7cbc3STejun Heo .udma_mask = ATA_UDMA6, 14966a7cbc3STejun Heo .port_ops = &ahci_ops, 15066a7cbc3STejun Heo }, 15167809f85SLevente Kurusa [board_ahci_noncq] = { 15267809f85SLevente Kurusa AHCI_HFLAGS (AHCI_HFLAG_NO_NCQ), 15367809f85SLevente Kurusa .flags = AHCI_FLAG_COMMON, 15467809f85SLevente Kurusa .pio_mask = ATA_PIO4, 15567809f85SLevente Kurusa .udma_mask = ATA_UDMA6, 15667809f85SLevente Kurusa .port_ops = &ahci_ops, 15767809f85SLevente Kurusa }, 158facb8fa6SJeffrin Jose [board_ahci_nosntf] = { 159441577efSTejun Heo AHCI_HFLAGS (AHCI_HFLAG_NO_SNTF), 160441577efSTejun Heo .flags = AHCI_FLAG_COMMON, 161441577efSTejun Heo .pio_mask = ATA_PIO4, 162441577efSTejun Heo .udma_mask = ATA_UDMA6, 163441577efSTejun Heo .port_ops = &ahci_ops, 164441577efSTejun Heo }, 165facb8fa6SJeffrin Jose [board_ahci_yes_fbs] = { 1665f173107STejun Heo AHCI_HFLAGS (AHCI_HFLAG_YES_FBS), 1675f173107STejun Heo .flags = AHCI_FLAG_COMMON, 1685f173107STejun Heo .pio_mask = ATA_PIO4, 1695f173107STejun Heo .udma_mask = ATA_UDMA6, 1705f173107STejun Heo .port_ops = &ahci_ops, 1715f173107STejun Heo }, 172441577efSTejun Heo /* by chipsets */ 1737d523bdcSHanna Hawa [board_ahci_al] = { 1747d523bdcSHanna Hawa AHCI_HFLAGS (AHCI_HFLAG_NO_PMP | AHCI_HFLAG_NO_MSI), 1757d523bdcSHanna Hawa .flags = AHCI_FLAG_COMMON, 1767d523bdcSHanna Hawa .pio_mask = ATA_PIO4, 1777d523bdcSHanna Hawa .udma_mask = ATA_UDMA6, 1787d523bdcSHanna Hawa .port_ops = &ahci_ops, 1797d523bdcSHanna Hawa }, 180dbfe8ef5SDan Williams [board_ahci_avn] = { 181dbfe8ef5SDan Williams .flags = AHCI_FLAG_COMMON, 182dbfe8ef5SDan Williams .pio_mask = ATA_PIO4, 183dbfe8ef5SDan Williams .udma_mask = ATA_UDMA6, 184dbfe8ef5SDan Williams .port_ops = &ahci_avn_ops, 185dbfe8ef5SDan Williams }, 186facb8fa6SJeffrin Jose [board_ahci_mcp65] = { 18783f2b963STejun Heo AHCI_HFLAGS (AHCI_HFLAG_NO_FPDMA_AA | AHCI_HFLAG_NO_PMP | 18883f2b963STejun Heo AHCI_HFLAG_YES_NCQ), 189ae01b249STejun Heo .flags = AHCI_FLAG_COMMON | ATA_FLAG_NO_DIPM, 19083f2b963STejun Heo .pio_mask = ATA_PIO4, 19183f2b963STejun Heo .udma_mask = ATA_UDMA6, 19283f2b963STejun Heo .port_ops = &ahci_ops, 19383f2b963STejun Heo }, 194facb8fa6SJeffrin Jose [board_ahci_mcp77] = { 19583f2b963STejun Heo AHCI_HFLAGS (AHCI_HFLAG_NO_FPDMA_AA | AHCI_HFLAG_NO_PMP), 19683f2b963STejun Heo .flags = AHCI_FLAG_COMMON, 19783f2b963STejun Heo .pio_mask = ATA_PIO4, 19883f2b963STejun Heo .udma_mask = ATA_UDMA6, 19983f2b963STejun Heo .port_ops = &ahci_ops, 20083f2b963STejun Heo }, 201facb8fa6SJeffrin Jose [board_ahci_mcp89] = { 20283f2b963STejun Heo AHCI_HFLAGS (AHCI_HFLAG_NO_FPDMA_AA), 203441577efSTejun Heo .flags = AHCI_FLAG_COMMON, 204441577efSTejun Heo .pio_mask = ATA_PIO4, 205441577efSTejun Heo .udma_mask = ATA_UDMA6, 206441577efSTejun Heo .port_ops = &ahci_ops, 207441577efSTejun Heo }, 208facb8fa6SJeffrin Jose [board_ahci_mv] = { 209441577efSTejun Heo AHCI_HFLAGS (AHCI_HFLAG_NO_NCQ | AHCI_HFLAG_NO_MSI | 210441577efSTejun Heo AHCI_HFLAG_MV_PATA | AHCI_HFLAG_NO_PMP), 2119cbe056fSSergei Shtylyov .flags = ATA_FLAG_SATA | ATA_FLAG_PIO_DMA, 212441577efSTejun Heo .pio_mask = ATA_PIO4, 213441577efSTejun Heo .udma_mask = ATA_UDMA6, 214441577efSTejun Heo .port_ops = &ahci_ops, 215441577efSTejun Heo }, 216facb8fa6SJeffrin Jose [board_ahci_sb600] = { 217417a1a6dSTejun Heo AHCI_HFLAGS (AHCI_HFLAG_IGN_SERR_INTERNAL | 2182fcad9d2STejun Heo AHCI_HFLAG_NO_MSI | AHCI_HFLAG_SECT255 | 2192fcad9d2STejun Heo AHCI_HFLAG_32BIT_ONLY), 220417a1a6dSTejun Heo .flags = AHCI_FLAG_COMMON, 22114bdef98SErik Inge Bolsø .pio_mask = ATA_PIO4, 222469248abSJeff Garzik .udma_mask = ATA_UDMA6, 223345347c5SYuan-Hsin Chen .port_ops = &ahci_pmp_retry_srst_ops, 22455a61604SConke Hu }, 225facb8fa6SJeffrin Jose [board_ahci_sb700] = { /* for SB700 and SB800 */ 226bd17243aSShane Huang AHCI_HFLAGS (AHCI_HFLAG_IGN_SERR_INTERNAL), 227e39fc8c9SShane Huang .flags = AHCI_FLAG_COMMON, 22814bdef98SErik Inge Bolsø .pio_mask = ATA_PIO4, 229e39fc8c9SShane Huang .udma_mask = ATA_UDMA6, 230345347c5SYuan-Hsin Chen .port_ops = &ahci_pmp_retry_srst_ops, 231e39fc8c9SShane Huang }, 232facb8fa6SJeffrin Jose [board_ahci_vt8251] = { 233441577efSTejun Heo AHCI_HFLAGS (AHCI_HFLAG_NO_NCQ | AHCI_HFLAG_NO_PMP), 234e297d99eSTejun Heo .flags = AHCI_FLAG_COMMON, 23514bdef98SErik Inge Bolsø .pio_mask = ATA_PIO4, 236e297d99eSTejun Heo .udma_mask = ATA_UDMA6, 237441577efSTejun Heo .port_ops = &ahci_vt8251_ops, 2381b677afdSShaohua Li }, 239c312ef17SDan Williams [board_ahci_pcs7] = { 240c312ef17SDan Williams .flags = AHCI_FLAG_COMMON, 241c312ef17SDan Williams .pio_mask = ATA_PIO4, 242c312ef17SDan Williams .udma_mask = ATA_UDMA6, 243c312ef17SDan Williams .port_ops = &ahci_ops, 244c312ef17SDan Williams }, 245c6fd2807SJeff Garzik }; 246c6fd2807SJeff Garzik 247c6fd2807SJeff Garzik static const struct pci_device_id ahci_pci_tbl[] = { 248c6fd2807SJeff Garzik /* Intel */ 2495e125d13SMika Westerberg { PCI_VDEVICE(INTEL, 0x06d6), board_ahci }, /* Comet Lake PCH-H RAID */ 25054bb3a94SJeff Garzik { PCI_VDEVICE(INTEL, 0x2652), board_ahci }, /* ICH6 */ 25154bb3a94SJeff Garzik { PCI_VDEVICE(INTEL, 0x2653), board_ahci }, /* ICH6M */ 25254bb3a94SJeff Garzik { PCI_VDEVICE(INTEL, 0x27c1), board_ahci }, /* ICH7 */ 25354bb3a94SJeff Garzik { PCI_VDEVICE(INTEL, 0x27c5), board_ahci }, /* ICH7M */ 25454bb3a94SJeff Garzik { PCI_VDEVICE(INTEL, 0x27c3), board_ahci }, /* ICH7R */ 25582490c09STejun Heo { PCI_VDEVICE(AL, 0x5288), board_ahci_ign_iferr }, /* ULi M5288 */ 25654bb3a94SJeff Garzik { PCI_VDEVICE(INTEL, 0x2681), board_ahci }, /* ESB2 */ 25754bb3a94SJeff Garzik { PCI_VDEVICE(INTEL, 0x2682), board_ahci }, /* ESB2 */ 25854bb3a94SJeff Garzik { PCI_VDEVICE(INTEL, 0x2683), board_ahci }, /* ESB2 */ 25954bb3a94SJeff Garzik { PCI_VDEVICE(INTEL, 0x27c6), board_ahci }, /* ICH7-M DH */ 2607a234affSTejun Heo { PCI_VDEVICE(INTEL, 0x2821), board_ahci }, /* ICH8 */ 2611b677afdSShaohua Li { PCI_VDEVICE(INTEL, 0x2822), board_ahci_nosntf }, /* ICH8 */ 2627a234affSTejun Heo { PCI_VDEVICE(INTEL, 0x2824), board_ahci }, /* ICH8 */ 2637a234affSTejun Heo { PCI_VDEVICE(INTEL, 0x2829), board_ahci }, /* ICH8M */ 2647a234affSTejun Heo { PCI_VDEVICE(INTEL, 0x282a), board_ahci }, /* ICH8M */ 2657a234affSTejun Heo { PCI_VDEVICE(INTEL, 0x2922), board_ahci }, /* ICH9 */ 2667a234affSTejun Heo { PCI_VDEVICE(INTEL, 0x2923), board_ahci }, /* ICH9 */ 2677a234affSTejun Heo { PCI_VDEVICE(INTEL, 0x2924), board_ahci }, /* ICH9 */ 2687a234affSTejun Heo { PCI_VDEVICE(INTEL, 0x2925), board_ahci }, /* ICH9 */ 2697a234affSTejun Heo { PCI_VDEVICE(INTEL, 0x2927), board_ahci }, /* ICH9 */ 270ebb82e3cSHans de Goede { PCI_VDEVICE(INTEL, 0x2929), board_ahci_mobile }, /* ICH9M */ 271ebb82e3cSHans de Goede { PCI_VDEVICE(INTEL, 0x292a), board_ahci_mobile }, /* ICH9M */ 272ebb82e3cSHans de Goede { PCI_VDEVICE(INTEL, 0x292b), board_ahci_mobile }, /* ICH9M */ 273ebb82e3cSHans de Goede { PCI_VDEVICE(INTEL, 0x292c), board_ahci_mobile }, /* ICH9M */ 274ebb82e3cSHans de Goede { PCI_VDEVICE(INTEL, 0x292f), board_ahci_mobile }, /* ICH9M */ 2757a234affSTejun Heo { PCI_VDEVICE(INTEL, 0x294d), board_ahci }, /* ICH9 */ 276ebb82e3cSHans de Goede { PCI_VDEVICE(INTEL, 0x294e), board_ahci_mobile }, /* ICH9M */ 277d4155e6fSJason Gaston { PCI_VDEVICE(INTEL, 0x502a), board_ahci }, /* Tolapai */ 278d4155e6fSJason Gaston { PCI_VDEVICE(INTEL, 0x502b), board_ahci }, /* Tolapai */ 27916ad1ad9SJason Gaston { PCI_VDEVICE(INTEL, 0x3a05), board_ahci }, /* ICH10 */ 280b2dde6afSMark Goodwin { PCI_VDEVICE(INTEL, 0x3a22), board_ahci }, /* ICH10 */ 28116ad1ad9SJason Gaston { PCI_VDEVICE(INTEL, 0x3a25), board_ahci }, /* ICH10 */ 282c1f57d9bSDavid Milburn { PCI_VDEVICE(INTEL, 0x3b22), board_ahci }, /* PCH AHCI */ 283c1f57d9bSDavid Milburn { PCI_VDEVICE(INTEL, 0x3b23), board_ahci }, /* PCH AHCI */ 284adcb5308SSeth Heasley { PCI_VDEVICE(INTEL, 0x3b24), board_ahci }, /* PCH RAID */ 2858e48b6b3SSeth Heasley { PCI_VDEVICE(INTEL, 0x3b25), board_ahci }, /* PCH RAID */ 286ebb82e3cSHans de Goede { PCI_VDEVICE(INTEL, 0x3b29), board_ahci_mobile }, /* PCH M AHCI */ 287adcb5308SSeth Heasley { PCI_VDEVICE(INTEL, 0x3b2b), board_ahci }, /* PCH RAID */ 288ebb82e3cSHans de Goede { PCI_VDEVICE(INTEL, 0x3b2c), board_ahci_mobile }, /* PCH M RAID */ 289c1f57d9bSDavid Milburn { PCI_VDEVICE(INTEL, 0x3b2f), board_ahci }, /* PCH AHCI */ 290c312ef17SDan Williams { PCI_VDEVICE(INTEL, 0x19b0), board_ahci_pcs7 }, /* DNV AHCI */ 291c312ef17SDan Williams { PCI_VDEVICE(INTEL, 0x19b1), board_ahci_pcs7 }, /* DNV AHCI */ 292c312ef17SDan Williams { PCI_VDEVICE(INTEL, 0x19b2), board_ahci_pcs7 }, /* DNV AHCI */ 293c312ef17SDan Williams { PCI_VDEVICE(INTEL, 0x19b3), board_ahci_pcs7 }, /* DNV AHCI */ 294c312ef17SDan Williams { PCI_VDEVICE(INTEL, 0x19b4), board_ahci_pcs7 }, /* DNV AHCI */ 295c312ef17SDan Williams { PCI_VDEVICE(INTEL, 0x19b5), board_ahci_pcs7 }, /* DNV AHCI */ 296c312ef17SDan Williams { PCI_VDEVICE(INTEL, 0x19b6), board_ahci_pcs7 }, /* DNV AHCI */ 297c312ef17SDan Williams { PCI_VDEVICE(INTEL, 0x19b7), board_ahci_pcs7 }, /* DNV AHCI */ 298c312ef17SDan Williams { PCI_VDEVICE(INTEL, 0x19bE), board_ahci_pcs7 }, /* DNV AHCI */ 299c312ef17SDan Williams { PCI_VDEVICE(INTEL, 0x19bF), board_ahci_pcs7 }, /* DNV AHCI */ 300c312ef17SDan Williams { PCI_VDEVICE(INTEL, 0x19c0), board_ahci_pcs7 }, /* DNV AHCI */ 301c312ef17SDan Williams { PCI_VDEVICE(INTEL, 0x19c1), board_ahci_pcs7 }, /* DNV AHCI */ 302c312ef17SDan Williams { PCI_VDEVICE(INTEL, 0x19c2), board_ahci_pcs7 }, /* DNV AHCI */ 303c312ef17SDan Williams { PCI_VDEVICE(INTEL, 0x19c3), board_ahci_pcs7 }, /* DNV AHCI */ 304c312ef17SDan Williams { PCI_VDEVICE(INTEL, 0x19c4), board_ahci_pcs7 }, /* DNV AHCI */ 305c312ef17SDan Williams { PCI_VDEVICE(INTEL, 0x19c5), board_ahci_pcs7 }, /* DNV AHCI */ 306c312ef17SDan Williams { PCI_VDEVICE(INTEL, 0x19c6), board_ahci_pcs7 }, /* DNV AHCI */ 307c312ef17SDan Williams { PCI_VDEVICE(INTEL, 0x19c7), board_ahci_pcs7 }, /* DNV AHCI */ 308c312ef17SDan Williams { PCI_VDEVICE(INTEL, 0x19cE), board_ahci_pcs7 }, /* DNV AHCI */ 309c312ef17SDan Williams { PCI_VDEVICE(INTEL, 0x19cF), board_ahci_pcs7 }, /* DNV AHCI */ 3105623cab8SSeth Heasley { PCI_VDEVICE(INTEL, 0x1c02), board_ahci }, /* CPT AHCI */ 311ebb82e3cSHans de Goede { PCI_VDEVICE(INTEL, 0x1c03), board_ahci_mobile }, /* CPT M AHCI */ 3125623cab8SSeth Heasley { PCI_VDEVICE(INTEL, 0x1c04), board_ahci }, /* CPT RAID */ 313ebb82e3cSHans de Goede { PCI_VDEVICE(INTEL, 0x1c05), board_ahci_mobile }, /* CPT M RAID */ 3145623cab8SSeth Heasley { PCI_VDEVICE(INTEL, 0x1c06), board_ahci }, /* CPT RAID */ 3155623cab8SSeth Heasley { PCI_VDEVICE(INTEL, 0x1c07), board_ahci }, /* CPT RAID */ 316992b3fb9SSeth Heasley { PCI_VDEVICE(INTEL, 0x1d02), board_ahci }, /* PBG AHCI */ 317992b3fb9SSeth Heasley { PCI_VDEVICE(INTEL, 0x1d04), board_ahci }, /* PBG RAID */ 318992b3fb9SSeth Heasley { PCI_VDEVICE(INTEL, 0x1d06), board_ahci }, /* PBG RAID */ 31964a3903dSSeth Heasley { PCI_VDEVICE(INTEL, 0x2826), board_ahci }, /* PBG RAID */ 320a4a461a6SSeth Heasley { PCI_VDEVICE(INTEL, 0x2323), board_ahci }, /* DH89xxCC AHCI */ 321181e3ceaSSeth Heasley { PCI_VDEVICE(INTEL, 0x1e02), board_ahci }, /* Panther Point AHCI */ 322ebb82e3cSHans de Goede { PCI_VDEVICE(INTEL, 0x1e03), board_ahci_mobile }, /* Panther M AHCI */ 323181e3ceaSSeth Heasley { PCI_VDEVICE(INTEL, 0x1e04), board_ahci }, /* Panther Point RAID */ 324181e3ceaSSeth Heasley { PCI_VDEVICE(INTEL, 0x1e05), board_ahci }, /* Panther Point RAID */ 325181e3ceaSSeth Heasley { PCI_VDEVICE(INTEL, 0x1e06), board_ahci }, /* Panther Point RAID */ 326ebb82e3cSHans de Goede { PCI_VDEVICE(INTEL, 0x1e07), board_ahci_mobile }, /* Panther M RAID */ 3272cab7a4cSSeth Heasley { PCI_VDEVICE(INTEL, 0x1e0e), board_ahci }, /* Panther Point RAID */ 328ea4ace66SSeth Heasley { PCI_VDEVICE(INTEL, 0x8c02), board_ahci }, /* Lynx Point AHCI */ 329ebb82e3cSHans de Goede { PCI_VDEVICE(INTEL, 0x8c03), board_ahci_mobile }, /* Lynx M AHCI */ 330ea4ace66SSeth Heasley { PCI_VDEVICE(INTEL, 0x8c04), board_ahci }, /* Lynx Point RAID */ 331ebb82e3cSHans de Goede { PCI_VDEVICE(INTEL, 0x8c05), board_ahci_mobile }, /* Lynx M RAID */ 332ea4ace66SSeth Heasley { PCI_VDEVICE(INTEL, 0x8c06), board_ahci }, /* Lynx Point RAID */ 333ebb82e3cSHans de Goede { PCI_VDEVICE(INTEL, 0x8c07), board_ahci_mobile }, /* Lynx M RAID */ 334ea4ace66SSeth Heasley { PCI_VDEVICE(INTEL, 0x8c0e), board_ahci }, /* Lynx Point RAID */ 335ebb82e3cSHans de Goede { PCI_VDEVICE(INTEL, 0x8c0f), board_ahci_mobile }, /* Lynx M RAID */ 336ebb82e3cSHans de Goede { PCI_VDEVICE(INTEL, 0x9c02), board_ahci_mobile }, /* Lynx LP AHCI */ 337ebb82e3cSHans de Goede { PCI_VDEVICE(INTEL, 0x9c03), board_ahci_mobile }, /* Lynx LP AHCI */ 338ebb82e3cSHans de Goede { PCI_VDEVICE(INTEL, 0x9c04), board_ahci_mobile }, /* Lynx LP RAID */ 339ebb82e3cSHans de Goede { PCI_VDEVICE(INTEL, 0x9c05), board_ahci_mobile }, /* Lynx LP RAID */ 340ebb82e3cSHans de Goede { PCI_VDEVICE(INTEL, 0x9c06), board_ahci_mobile }, /* Lynx LP RAID */ 341ebb82e3cSHans de Goede { PCI_VDEVICE(INTEL, 0x9c07), board_ahci_mobile }, /* Lynx LP RAID */ 342ebb82e3cSHans de Goede { PCI_VDEVICE(INTEL, 0x9c0e), board_ahci_mobile }, /* Lynx LP RAID */ 343ebb82e3cSHans de Goede { PCI_VDEVICE(INTEL, 0x9c0f), board_ahci_mobile }, /* Lynx LP RAID */ 3444544e403SMika Westerberg { PCI_VDEVICE(INTEL, 0x9dd3), board_ahci_mobile }, /* Cannon Lake PCH-LP AHCI */ 34529e674ddSSeth Heasley { PCI_VDEVICE(INTEL, 0x1f22), board_ahci }, /* Avoton AHCI */ 34629e674ddSSeth Heasley { PCI_VDEVICE(INTEL, 0x1f23), board_ahci }, /* Avoton AHCI */ 34729e674ddSSeth Heasley { PCI_VDEVICE(INTEL, 0x1f24), board_ahci }, /* Avoton RAID */ 34829e674ddSSeth Heasley { PCI_VDEVICE(INTEL, 0x1f25), board_ahci }, /* Avoton RAID */ 34929e674ddSSeth Heasley { PCI_VDEVICE(INTEL, 0x1f26), board_ahci }, /* Avoton RAID */ 35029e674ddSSeth Heasley { PCI_VDEVICE(INTEL, 0x1f27), board_ahci }, /* Avoton RAID */ 35129e674ddSSeth Heasley { PCI_VDEVICE(INTEL, 0x1f2e), board_ahci }, /* Avoton RAID */ 35229e674ddSSeth Heasley { PCI_VDEVICE(INTEL, 0x1f2f), board_ahci }, /* Avoton RAID */ 353dbfe8ef5SDan Williams { PCI_VDEVICE(INTEL, 0x1f32), board_ahci_avn }, /* Avoton AHCI */ 354dbfe8ef5SDan Williams { PCI_VDEVICE(INTEL, 0x1f33), board_ahci_avn }, /* Avoton AHCI */ 355dbfe8ef5SDan Williams { PCI_VDEVICE(INTEL, 0x1f34), board_ahci_avn }, /* Avoton RAID */ 356dbfe8ef5SDan Williams { PCI_VDEVICE(INTEL, 0x1f35), board_ahci_avn }, /* Avoton RAID */ 357dbfe8ef5SDan Williams { PCI_VDEVICE(INTEL, 0x1f36), board_ahci_avn }, /* Avoton RAID */ 358dbfe8ef5SDan Williams { PCI_VDEVICE(INTEL, 0x1f37), board_ahci_avn }, /* Avoton RAID */ 359dbfe8ef5SDan Williams { PCI_VDEVICE(INTEL, 0x1f3e), board_ahci_avn }, /* Avoton RAID */ 360dbfe8ef5SDan Williams { PCI_VDEVICE(INTEL, 0x1f3f), board_ahci_avn }, /* Avoton RAID */ 361efda332cSJames Ralston { PCI_VDEVICE(INTEL, 0x2823), board_ahci }, /* Wellsburg RAID */ 362efda332cSJames Ralston { PCI_VDEVICE(INTEL, 0x2827), board_ahci }, /* Wellsburg RAID */ 363151743fdSJames Ralston { PCI_VDEVICE(INTEL, 0x8d02), board_ahci }, /* Wellsburg AHCI */ 364151743fdSJames Ralston { PCI_VDEVICE(INTEL, 0x8d04), board_ahci }, /* Wellsburg RAID */ 365151743fdSJames Ralston { PCI_VDEVICE(INTEL, 0x8d06), board_ahci }, /* Wellsburg RAID */ 366151743fdSJames Ralston { PCI_VDEVICE(INTEL, 0x8d0e), board_ahci }, /* Wellsburg RAID */ 367151743fdSJames Ralston { PCI_VDEVICE(INTEL, 0x8d62), board_ahci }, /* Wellsburg AHCI */ 368151743fdSJames Ralston { PCI_VDEVICE(INTEL, 0x8d64), board_ahci }, /* Wellsburg RAID */ 369151743fdSJames Ralston { PCI_VDEVICE(INTEL, 0x8d66), board_ahci }, /* Wellsburg RAID */ 370151743fdSJames Ralston { PCI_VDEVICE(INTEL, 0x8d6e), board_ahci }, /* Wellsburg RAID */ 3711cfc7df3SSeth Heasley { PCI_VDEVICE(INTEL, 0x23a3), board_ahci }, /* Coleto Creek AHCI */ 372ebb82e3cSHans de Goede { PCI_VDEVICE(INTEL, 0x9c83), board_ahci_mobile }, /* Wildcat LP AHCI */ 373ebb82e3cSHans de Goede { PCI_VDEVICE(INTEL, 0x9c85), board_ahci_mobile }, /* Wildcat LP RAID */ 374ebb82e3cSHans de Goede { PCI_VDEVICE(INTEL, 0x9c87), board_ahci_mobile }, /* Wildcat LP RAID */ 375ebb82e3cSHans de Goede { PCI_VDEVICE(INTEL, 0x9c8f), board_ahci_mobile }, /* Wildcat LP RAID */ 3761b071a09SJames Ralston { PCI_VDEVICE(INTEL, 0x8c82), board_ahci }, /* 9 Series AHCI */ 377ebb82e3cSHans de Goede { PCI_VDEVICE(INTEL, 0x8c83), board_ahci_mobile }, /* 9 Series M AHCI */ 3781b071a09SJames Ralston { PCI_VDEVICE(INTEL, 0x8c84), board_ahci }, /* 9 Series RAID */ 379ebb82e3cSHans de Goede { PCI_VDEVICE(INTEL, 0x8c85), board_ahci_mobile }, /* 9 Series M RAID */ 3801b071a09SJames Ralston { PCI_VDEVICE(INTEL, 0x8c86), board_ahci }, /* 9 Series RAID */ 381ebb82e3cSHans de Goede { PCI_VDEVICE(INTEL, 0x8c87), board_ahci_mobile }, /* 9 Series M RAID */ 3821b071a09SJames Ralston { PCI_VDEVICE(INTEL, 0x8c8e), board_ahci }, /* 9 Series RAID */ 383ebb82e3cSHans de Goede { PCI_VDEVICE(INTEL, 0x8c8f), board_ahci_mobile }, /* 9 Series M RAID */ 384ebb82e3cSHans de Goede { PCI_VDEVICE(INTEL, 0x9d03), board_ahci_mobile }, /* Sunrise LP AHCI */ 385ebb82e3cSHans de Goede { PCI_VDEVICE(INTEL, 0x9d05), board_ahci_mobile }, /* Sunrise LP RAID */ 386ebb82e3cSHans de Goede { PCI_VDEVICE(INTEL, 0x9d07), board_ahci_mobile }, /* Sunrise LP RAID */ 387c5967b79SCharles_Rose@Dell.com { PCI_VDEVICE(INTEL, 0xa102), board_ahci }, /* Sunrise Point-H AHCI */ 388ebb82e3cSHans de Goede { PCI_VDEVICE(INTEL, 0xa103), board_ahci_mobile }, /* Sunrise M AHCI */ 389690000b9SJames Ralston { PCI_VDEVICE(INTEL, 0xa105), board_ahci }, /* Sunrise Point-H RAID */ 390c5967b79SCharles_Rose@Dell.com { PCI_VDEVICE(INTEL, 0xa106), board_ahci }, /* Sunrise Point-H RAID */ 391ebb82e3cSHans de Goede { PCI_VDEVICE(INTEL, 0xa107), board_ahci_mobile }, /* Sunrise M RAID */ 392690000b9SJames Ralston { PCI_VDEVICE(INTEL, 0xa10f), board_ahci }, /* Sunrise Point-H RAID */ 3934d92f009SAlexandra Yates { PCI_VDEVICE(INTEL, 0x2822), board_ahci }, /* Lewisburg RAID*/ 394f5bdd66cSAlexandra Yates { PCI_VDEVICE(INTEL, 0x2823), board_ahci }, /* Lewisburg AHCI*/ 3954d92f009SAlexandra Yates { PCI_VDEVICE(INTEL, 0x2826), board_ahci }, /* Lewisburg RAID*/ 396f5bdd66cSAlexandra Yates { PCI_VDEVICE(INTEL, 0x2827), board_ahci }, /* Lewisburg RAID*/ 3974d92f009SAlexandra Yates { PCI_VDEVICE(INTEL, 0xa182), board_ahci }, /* Lewisburg AHCI*/ 3984d92f009SAlexandra Yates { PCI_VDEVICE(INTEL, 0xa186), board_ahci }, /* Lewisburg RAID*/ 399f5bdd66cSAlexandra Yates { PCI_VDEVICE(INTEL, 0xa1d2), board_ahci }, /* Lewisburg RAID*/ 400f5bdd66cSAlexandra Yates { PCI_VDEVICE(INTEL, 0xa1d6), board_ahci }, /* Lewisburg RAID*/ 4014d92f009SAlexandra Yates { PCI_VDEVICE(INTEL, 0xa202), board_ahci }, /* Lewisburg AHCI*/ 4024d92f009SAlexandra Yates { PCI_VDEVICE(INTEL, 0xa206), board_ahci }, /* Lewisburg RAID*/ 403f5bdd66cSAlexandra Yates { PCI_VDEVICE(INTEL, 0xa252), board_ahci }, /* Lewisburg RAID*/ 404f5bdd66cSAlexandra Yates { PCI_VDEVICE(INTEL, 0xa256), board_ahci }, /* Lewisburg RAID*/ 405f919dde0SMika Westerberg { PCI_VDEVICE(INTEL, 0xa356), board_ahci }, /* Cannon Lake PCH-H RAID */ 40632d25454SKai-Heng Feng { PCI_VDEVICE(INTEL, 0x06d7), board_ahci }, /* Comet Lake-H RAID */ 40758c42b0bSMika Westerberg { PCI_VDEVICE(INTEL, 0xa386), board_ahci }, /* Comet Lake PCH-V RAID */ 408ebb82e3cSHans de Goede { PCI_VDEVICE(INTEL, 0x0f22), board_ahci_mobile }, /* Bay Trail AHCI */ 409ebb82e3cSHans de Goede { PCI_VDEVICE(INTEL, 0x0f23), board_ahci_mobile }, /* Bay Trail AHCI */ 410ebb82e3cSHans de Goede { PCI_VDEVICE(INTEL, 0x22a3), board_ahci_mobile }, /* Cherry Tr. AHCI */ 411ebb82e3cSHans de Goede { PCI_VDEVICE(INTEL, 0x5ae3), board_ahci_mobile }, /* ApolloLake AHCI */ 412ba445791SMika Westerberg { PCI_VDEVICE(INTEL, 0x34d3), board_ahci_mobile }, /* Ice Lake LP AHCI */ 4131f2ef049SKai-Heng Feng { PCI_VDEVICE(INTEL, 0x02d3), board_ahci_mobile }, /* Comet Lake PCH-U AHCI */ 4147667e63cSJian-Hong Pan { PCI_VDEVICE(INTEL, 0x02d7), board_ahci_mobile }, /* Comet Lake PCH RAID */ 415c6fd2807SJeff Garzik 416e34bb370STejun Heo /* JMicron 360/1/3/5/6, match class to avoid IDE function */ 417e34bb370STejun Heo { PCI_VENDOR_ID_JMICRON, PCI_ANY_ID, PCI_ANY_ID, PCI_ANY_ID, 418e34bb370STejun Heo PCI_CLASS_STORAGE_SATA_AHCI, 0xffffff, board_ahci_ign_iferr }, 4191fefb8fdSBen Hutchings /* JMicron 362B and 362C have an AHCI function with IDE class code */ 4201fefb8fdSBen Hutchings { PCI_VDEVICE(JMICRON, 0x2362), board_ahci_ign_iferr }, 4211fefb8fdSBen Hutchings { PCI_VDEVICE(JMICRON, 0x236f), board_ahci_ign_iferr }, 42291f15fb3SZhang Rui /* May need to update quirk_jmicron_async_suspend() for additions */ 423c6fd2807SJeff Garzik 424c6fd2807SJeff Garzik /* ATI */ 425c65ec1c2SConke Hu { PCI_VDEVICE(ATI, 0x4380), board_ahci_sb600 }, /* ATI SB600 */ 426e39fc8c9SShane Huang { PCI_VDEVICE(ATI, 0x4390), board_ahci_sb700 }, /* ATI SB700/800 */ 427e39fc8c9SShane Huang { PCI_VDEVICE(ATI, 0x4391), board_ahci_sb700 }, /* ATI SB700/800 */ 428e39fc8c9SShane Huang { PCI_VDEVICE(ATI, 0x4392), board_ahci_sb700 }, /* ATI SB700/800 */ 429e39fc8c9SShane Huang { PCI_VDEVICE(ATI, 0x4393), board_ahci_sb700 }, /* ATI SB700/800 */ 430e39fc8c9SShane Huang { PCI_VDEVICE(ATI, 0x4394), board_ahci_sb700 }, /* ATI SB700/800 */ 431e39fc8c9SShane Huang { PCI_VDEVICE(ATI, 0x4395), board_ahci_sb700 }, /* ATI SB700/800 */ 432c6fd2807SJeff Garzik 4337d523bdcSHanna Hawa /* Amazon's Annapurna Labs support */ 4347d523bdcSHanna Hawa { PCI_DEVICE(PCI_VENDOR_ID_AMAZON_ANNAPURNA_LABS, 0x0031), 4357d523bdcSHanna Hawa .class = PCI_CLASS_STORAGE_SATA_AHCI, 4367d523bdcSHanna Hawa .class_mask = 0xffffff, 4377d523bdcSHanna Hawa board_ahci_al }, 438e2dd90b1SShane Huang /* AMD */ 4395deab536SShane Huang { PCI_VDEVICE(AMD, 0x7800), board_ahci }, /* AMD Hudson-2 */ 440fafe5c3dSShane Huang { PCI_VDEVICE(AMD, 0x7900), board_ahci }, /* AMD CZ */ 441e2dd90b1SShane Huang /* AMD is using RAID class only for ahci controllers */ 442e2dd90b1SShane Huang { PCI_VENDOR_ID_AMD, PCI_ANY_ID, PCI_ANY_ID, PCI_ANY_ID, 443e2dd90b1SShane Huang PCI_CLASS_STORAGE_RAID << 8, 0xffffff, board_ahci }, 444e2dd90b1SShane Huang 445c6fd2807SJeff Garzik /* VIA */ 44654bb3a94SJeff Garzik { PCI_VDEVICE(VIA, 0x3349), board_ahci_vt8251 }, /* VIA VT8251 */ 447bf335542STejun Heo { PCI_VDEVICE(VIA, 0x6287), board_ahci_vt8251 }, /* VIA VT8251 */ 448c6fd2807SJeff Garzik 449c6fd2807SJeff Garzik /* NVIDIA */ 450e297d99eSTejun Heo { PCI_VDEVICE(NVIDIA, 0x044c), board_ahci_mcp65 }, /* MCP65 */ 451e297d99eSTejun Heo { PCI_VDEVICE(NVIDIA, 0x044d), board_ahci_mcp65 }, /* MCP65 */ 452e297d99eSTejun Heo { PCI_VDEVICE(NVIDIA, 0x044e), board_ahci_mcp65 }, /* MCP65 */ 453e297d99eSTejun Heo { PCI_VDEVICE(NVIDIA, 0x044f), board_ahci_mcp65 }, /* MCP65 */ 454e297d99eSTejun Heo { PCI_VDEVICE(NVIDIA, 0x045c), board_ahci_mcp65 }, /* MCP65 */ 455e297d99eSTejun Heo { PCI_VDEVICE(NVIDIA, 0x045d), board_ahci_mcp65 }, /* MCP65 */ 456e297d99eSTejun Heo { PCI_VDEVICE(NVIDIA, 0x045e), board_ahci_mcp65 }, /* MCP65 */ 457e297d99eSTejun Heo { PCI_VDEVICE(NVIDIA, 0x045f), board_ahci_mcp65 }, /* MCP65 */ 458441577efSTejun Heo { PCI_VDEVICE(NVIDIA, 0x0550), board_ahci_mcp67 }, /* MCP67 */ 459441577efSTejun Heo { PCI_VDEVICE(NVIDIA, 0x0551), board_ahci_mcp67 }, /* MCP67 */ 460441577efSTejun Heo { PCI_VDEVICE(NVIDIA, 0x0552), board_ahci_mcp67 }, /* MCP67 */ 461441577efSTejun Heo { PCI_VDEVICE(NVIDIA, 0x0553), board_ahci_mcp67 }, /* MCP67 */ 462441577efSTejun Heo { PCI_VDEVICE(NVIDIA, 0x0554), board_ahci_mcp67 }, /* MCP67 */ 463441577efSTejun Heo { PCI_VDEVICE(NVIDIA, 0x0555), board_ahci_mcp67 }, /* MCP67 */ 464441577efSTejun Heo { PCI_VDEVICE(NVIDIA, 0x0556), board_ahci_mcp67 }, /* MCP67 */ 465441577efSTejun Heo { PCI_VDEVICE(NVIDIA, 0x0557), board_ahci_mcp67 }, /* MCP67 */ 466441577efSTejun Heo { PCI_VDEVICE(NVIDIA, 0x0558), board_ahci_mcp67 }, /* MCP67 */ 467441577efSTejun Heo { PCI_VDEVICE(NVIDIA, 0x0559), board_ahci_mcp67 }, /* MCP67 */ 468441577efSTejun Heo { PCI_VDEVICE(NVIDIA, 0x055a), board_ahci_mcp67 }, /* MCP67 */ 469441577efSTejun Heo { PCI_VDEVICE(NVIDIA, 0x055b), board_ahci_mcp67 }, /* MCP67 */ 470441577efSTejun Heo { PCI_VDEVICE(NVIDIA, 0x0580), board_ahci_mcp_linux }, /* Linux ID */ 471441577efSTejun Heo { PCI_VDEVICE(NVIDIA, 0x0581), board_ahci_mcp_linux }, /* Linux ID */ 472441577efSTejun Heo { PCI_VDEVICE(NVIDIA, 0x0582), board_ahci_mcp_linux }, /* Linux ID */ 473441577efSTejun Heo { PCI_VDEVICE(NVIDIA, 0x0583), board_ahci_mcp_linux }, /* Linux ID */ 474441577efSTejun Heo { PCI_VDEVICE(NVIDIA, 0x0584), board_ahci_mcp_linux }, /* Linux ID */ 475441577efSTejun Heo { PCI_VDEVICE(NVIDIA, 0x0585), board_ahci_mcp_linux }, /* Linux ID */ 476441577efSTejun Heo { PCI_VDEVICE(NVIDIA, 0x0586), board_ahci_mcp_linux }, /* Linux ID */ 477441577efSTejun Heo { PCI_VDEVICE(NVIDIA, 0x0587), board_ahci_mcp_linux }, /* Linux ID */ 478441577efSTejun Heo { PCI_VDEVICE(NVIDIA, 0x0588), board_ahci_mcp_linux }, /* Linux ID */ 479441577efSTejun Heo { PCI_VDEVICE(NVIDIA, 0x0589), board_ahci_mcp_linux }, /* Linux ID */ 480441577efSTejun Heo { PCI_VDEVICE(NVIDIA, 0x058a), board_ahci_mcp_linux }, /* Linux ID */ 481441577efSTejun Heo { PCI_VDEVICE(NVIDIA, 0x058b), board_ahci_mcp_linux }, /* Linux ID */ 482441577efSTejun Heo { PCI_VDEVICE(NVIDIA, 0x058c), board_ahci_mcp_linux }, /* Linux ID */ 483441577efSTejun Heo { PCI_VDEVICE(NVIDIA, 0x058d), board_ahci_mcp_linux }, /* Linux ID */ 484441577efSTejun Heo { PCI_VDEVICE(NVIDIA, 0x058e), board_ahci_mcp_linux }, /* Linux ID */ 485441577efSTejun Heo { PCI_VDEVICE(NVIDIA, 0x058f), board_ahci_mcp_linux }, /* Linux ID */ 486441577efSTejun Heo { PCI_VDEVICE(NVIDIA, 0x07f0), board_ahci_mcp73 }, /* MCP73 */ 487441577efSTejun Heo { PCI_VDEVICE(NVIDIA, 0x07f1), board_ahci_mcp73 }, /* MCP73 */ 488441577efSTejun Heo { PCI_VDEVICE(NVIDIA, 0x07f2), board_ahci_mcp73 }, /* MCP73 */ 489441577efSTejun Heo { PCI_VDEVICE(NVIDIA, 0x07f3), board_ahci_mcp73 }, /* MCP73 */ 490441577efSTejun Heo { PCI_VDEVICE(NVIDIA, 0x07f4), board_ahci_mcp73 }, /* MCP73 */ 491441577efSTejun Heo { PCI_VDEVICE(NVIDIA, 0x07f5), board_ahci_mcp73 }, /* MCP73 */ 492441577efSTejun Heo { PCI_VDEVICE(NVIDIA, 0x07f6), board_ahci_mcp73 }, /* MCP73 */ 493441577efSTejun Heo { PCI_VDEVICE(NVIDIA, 0x07f7), board_ahci_mcp73 }, /* MCP73 */ 494441577efSTejun Heo { PCI_VDEVICE(NVIDIA, 0x07f8), board_ahci_mcp73 }, /* MCP73 */ 495441577efSTejun Heo { PCI_VDEVICE(NVIDIA, 0x07f9), board_ahci_mcp73 }, /* MCP73 */ 496441577efSTejun Heo { PCI_VDEVICE(NVIDIA, 0x07fa), board_ahci_mcp73 }, /* MCP73 */ 497441577efSTejun Heo { PCI_VDEVICE(NVIDIA, 0x07fb), board_ahci_mcp73 }, /* MCP73 */ 498441577efSTejun Heo { PCI_VDEVICE(NVIDIA, 0x0ad0), board_ahci_mcp77 }, /* MCP77 */ 499441577efSTejun Heo { PCI_VDEVICE(NVIDIA, 0x0ad1), board_ahci_mcp77 }, /* MCP77 */ 500441577efSTejun Heo { PCI_VDEVICE(NVIDIA, 0x0ad2), board_ahci_mcp77 }, /* MCP77 */ 501441577efSTejun Heo { PCI_VDEVICE(NVIDIA, 0x0ad3), board_ahci_mcp77 }, /* MCP77 */ 502441577efSTejun Heo { PCI_VDEVICE(NVIDIA, 0x0ad4), board_ahci_mcp77 }, /* MCP77 */ 503441577efSTejun Heo { PCI_VDEVICE(NVIDIA, 0x0ad5), board_ahci_mcp77 }, /* MCP77 */ 504441577efSTejun Heo { PCI_VDEVICE(NVIDIA, 0x0ad6), board_ahci_mcp77 }, /* MCP77 */ 505441577efSTejun Heo { PCI_VDEVICE(NVIDIA, 0x0ad7), board_ahci_mcp77 }, /* MCP77 */ 506441577efSTejun Heo { PCI_VDEVICE(NVIDIA, 0x0ad8), board_ahci_mcp77 }, /* MCP77 */ 507441577efSTejun Heo { PCI_VDEVICE(NVIDIA, 0x0ad9), board_ahci_mcp77 }, /* MCP77 */ 508441577efSTejun Heo { PCI_VDEVICE(NVIDIA, 0x0ada), board_ahci_mcp77 }, /* MCP77 */ 509441577efSTejun Heo { PCI_VDEVICE(NVIDIA, 0x0adb), board_ahci_mcp77 }, /* MCP77 */ 510441577efSTejun Heo { PCI_VDEVICE(NVIDIA, 0x0ab4), board_ahci_mcp79 }, /* MCP79 */ 511441577efSTejun Heo { PCI_VDEVICE(NVIDIA, 0x0ab5), board_ahci_mcp79 }, /* MCP79 */ 512441577efSTejun Heo { PCI_VDEVICE(NVIDIA, 0x0ab6), board_ahci_mcp79 }, /* MCP79 */ 513441577efSTejun Heo { PCI_VDEVICE(NVIDIA, 0x0ab7), board_ahci_mcp79 }, /* MCP79 */ 514441577efSTejun Heo { PCI_VDEVICE(NVIDIA, 0x0ab8), board_ahci_mcp79 }, /* MCP79 */ 515441577efSTejun Heo { PCI_VDEVICE(NVIDIA, 0x0ab9), board_ahci_mcp79 }, /* MCP79 */ 516441577efSTejun Heo { PCI_VDEVICE(NVIDIA, 0x0aba), board_ahci_mcp79 }, /* MCP79 */ 517441577efSTejun Heo { PCI_VDEVICE(NVIDIA, 0x0abb), board_ahci_mcp79 }, /* MCP79 */ 518441577efSTejun Heo { PCI_VDEVICE(NVIDIA, 0x0abc), board_ahci_mcp79 }, /* MCP79 */ 519441577efSTejun Heo { PCI_VDEVICE(NVIDIA, 0x0abd), board_ahci_mcp79 }, /* MCP79 */ 520441577efSTejun Heo { PCI_VDEVICE(NVIDIA, 0x0abe), board_ahci_mcp79 }, /* MCP79 */ 521441577efSTejun Heo { PCI_VDEVICE(NVIDIA, 0x0abf), board_ahci_mcp79 }, /* MCP79 */ 522441577efSTejun Heo { PCI_VDEVICE(NVIDIA, 0x0d84), board_ahci_mcp89 }, /* MCP89 */ 523441577efSTejun Heo { PCI_VDEVICE(NVIDIA, 0x0d85), board_ahci_mcp89 }, /* MCP89 */ 524441577efSTejun Heo { PCI_VDEVICE(NVIDIA, 0x0d86), board_ahci_mcp89 }, /* MCP89 */ 525441577efSTejun Heo { PCI_VDEVICE(NVIDIA, 0x0d87), board_ahci_mcp89 }, /* MCP89 */ 526441577efSTejun Heo { PCI_VDEVICE(NVIDIA, 0x0d88), board_ahci_mcp89 }, /* MCP89 */ 527441577efSTejun Heo { PCI_VDEVICE(NVIDIA, 0x0d89), board_ahci_mcp89 }, /* MCP89 */ 528441577efSTejun Heo { PCI_VDEVICE(NVIDIA, 0x0d8a), board_ahci_mcp89 }, /* MCP89 */ 529441577efSTejun Heo { PCI_VDEVICE(NVIDIA, 0x0d8b), board_ahci_mcp89 }, /* MCP89 */ 530441577efSTejun Heo { PCI_VDEVICE(NVIDIA, 0x0d8c), board_ahci_mcp89 }, /* MCP89 */ 531441577efSTejun Heo { PCI_VDEVICE(NVIDIA, 0x0d8d), board_ahci_mcp89 }, /* MCP89 */ 532441577efSTejun Heo { PCI_VDEVICE(NVIDIA, 0x0d8e), board_ahci_mcp89 }, /* MCP89 */ 533441577efSTejun Heo { PCI_VDEVICE(NVIDIA, 0x0d8f), board_ahci_mcp89 }, /* MCP89 */ 534c6fd2807SJeff Garzik 535c6fd2807SJeff Garzik /* SiS */ 53620e2de4aSTejun Heo { PCI_VDEVICE(SI, 0x1184), board_ahci }, /* SiS 966 */ 53720e2de4aSTejun Heo { PCI_VDEVICE(SI, 0x1185), board_ahci }, /* SiS 968 */ 53820e2de4aSTejun Heo { PCI_VDEVICE(SI, 0x0186), board_ahci }, /* SiS 968 */ 539c6fd2807SJeff Garzik 540318893e1SAlessandro Rubini /* ST Microelectronics */ 541318893e1SAlessandro Rubini { PCI_VDEVICE(STMICRO, 0xCC06), board_ahci }, /* ST ConneXt */ 542318893e1SAlessandro Rubini 543cd70c266SJeff Garzik /* Marvell */ 544cd70c266SJeff Garzik { PCI_VDEVICE(MARVELL, 0x6145), board_ahci_mv }, /* 6145 */ 545c40e7cb8SJose Alberto Reguero { PCI_VDEVICE(MARVELL, 0x6121), board_ahci_mv }, /* 6121 */ 54669fd3157SMyron Stowe { PCI_DEVICE(PCI_VENDOR_ID_MARVELL_EXT, 0x9123), 54710aca06cSAnssi Hannula .class = PCI_CLASS_STORAGE_SATA_AHCI, 54810aca06cSAnssi Hannula .class_mask = 0xffffff, 5495f173107STejun Heo .driver_data = board_ahci_yes_fbs }, /* 88se9128 */ 55069fd3157SMyron Stowe { PCI_DEVICE(PCI_VENDOR_ID_MARVELL_EXT, 0x9125), 551467b41c6SPer Jessen .driver_data = board_ahci_yes_fbs }, /* 88se9125 */ 552e098f5cbSSimon Guinot { PCI_DEVICE_SUB(PCI_VENDOR_ID_MARVELL_EXT, 0x9178, 553e098f5cbSSimon Guinot PCI_VENDOR_ID_MARVELL_EXT, 0x9170), 554e098f5cbSSimon Guinot .driver_data = board_ahci_yes_fbs }, /* 88se9170 */ 55569fd3157SMyron Stowe { PCI_DEVICE(PCI_VENDOR_ID_MARVELL_EXT, 0x917a), 556642d8925SMatt Johnson .driver_data = board_ahci_yes_fbs }, /* 88se9172 */ 557fcce9a35SGeorge Spelvin { PCI_DEVICE(PCI_VENDOR_ID_MARVELL_EXT, 0x9172), 558c5edfff9SMurali Karicheri .driver_data = board_ahci_yes_fbs }, /* 88se9182 */ 559c5edfff9SMurali Karicheri { PCI_DEVICE(PCI_VENDOR_ID_MARVELL_EXT, 0x9182), 560fcce9a35SGeorge Spelvin .driver_data = board_ahci_yes_fbs }, /* 88se9172 */ 56169fd3157SMyron Stowe { PCI_DEVICE(PCI_VENDOR_ID_MARVELL_EXT, 0x9192), 56217c60c6bSAlan Cox .driver_data = board_ahci_yes_fbs }, /* 88se9172 on some Gigabyte */ 563754a292fSAndreas Schrägle { PCI_DEVICE(PCI_VENDOR_ID_MARVELL_EXT, 0x91a0), 564754a292fSAndreas Schrägle .driver_data = board_ahci_yes_fbs }, 565a40cf3f3SJohannes Thumshirn { PCI_DEVICE(PCI_VENDOR_ID_MARVELL_EXT, 0x91a2), /* 88se91a2 */ 566a40cf3f3SJohannes Thumshirn .driver_data = board_ahci_yes_fbs }, 56769fd3157SMyron Stowe { PCI_DEVICE(PCI_VENDOR_ID_MARVELL_EXT, 0x91a3), 56850be5e36STejun Heo .driver_data = board_ahci_yes_fbs }, 5696d5278a6SSamir Benmendil { PCI_DEVICE(PCI_VENDOR_ID_MARVELL_EXT, 0x9230), 5706d5278a6SSamir Benmendil .driver_data = board_ahci_yes_fbs }, 57128b2182dSHans de Goede { PCI_DEVICE(PCI_VENDOR_ID_TTI, 0x0642), /* highpoint rocketraid 642L */ 57228b2182dSHans de Goede .driver_data = board_ahci_yes_fbs }, 57328b2182dSHans de Goede { PCI_DEVICE(PCI_VENDOR_ID_TTI, 0x0645), /* highpoint rocketraid 644L */ 574d2518365SJérôme Carretero .driver_data = board_ahci_yes_fbs }, 575cd70c266SJeff Garzik 576c77a036bSMark Nelson /* Promise */ 577c77a036bSMark Nelson { PCI_VDEVICE(PROMISE, 0x3f20), board_ahci }, /* PDC42819 */ 578b32bfc06SRomain Degez { PCI_VDEVICE(PROMISE, 0x3781), board_ahci }, /* FastTrak TX8660 ahci-mode */ 579c77a036bSMark Nelson 580c9703765SKeng-Yu Lin /* Asmedia */ 5817b4f6ecaSAlan Cox { PCI_VDEVICE(ASMEDIA, 0x0601), board_ahci }, /* ASM1060 */ 5827b4f6ecaSAlan Cox { PCI_VDEVICE(ASMEDIA, 0x0602), board_ahci }, /* ASM1060 */ 5837b4f6ecaSAlan Cox { PCI_VDEVICE(ASMEDIA, 0x0611), board_ahci }, /* ASM1061 */ 5847b4f6ecaSAlan Cox { PCI_VDEVICE(ASMEDIA, 0x0612), board_ahci }, /* ASM1062 */ 5850ce968f3SShawn Lin { PCI_VDEVICE(ASMEDIA, 0x0621), board_ahci }, /* ASM1061R */ 5860ce968f3SShawn Lin { PCI_VDEVICE(ASMEDIA, 0x0622), board_ahci }, /* ASM1062R */ 587c9703765SKeng-Yu Lin 58867809f85SLevente Kurusa /* 58966a7cbc3STejun Heo * Samsung SSDs found on some macbooks. NCQ times out if MSI is 59066a7cbc3STejun Heo * enabled. https://bugzilla.kernel.org/show_bug.cgi?id=60731 59167809f85SLevente Kurusa */ 59266a7cbc3STejun Heo { PCI_VDEVICE(SAMSUNG, 0x1600), board_ahci_nomsi }, 5932b21ef0aSTejun Heo { PCI_VDEVICE(SAMSUNG, 0xa800), board_ahci_nomsi }, 59467809f85SLevente Kurusa 5957f9c9f8eSHugh Daschbach /* Enmotus */ 5967f9c9f8eSHugh Daschbach { PCI_DEVICE(0x1c44, 0x8000), board_ahci }, 5977f9c9f8eSHugh Daschbach 598e49bd683STiezhu Yang /* Loongson */ 599e49bd683STiezhu Yang { PCI_VDEVICE(LOONGSON, 0x7a08), board_ahci }, 600e49bd683STiezhu Yang 601415ae2b5SJeff Garzik /* Generic, PCI class code for AHCI */ 602415ae2b5SJeff Garzik { PCI_ANY_ID, PCI_ANY_ID, PCI_ANY_ID, PCI_ANY_ID, 603c9f89475SConke Hu PCI_CLASS_STORAGE_SATA_AHCI, 0xffffff, board_ahci }, 604415ae2b5SJeff Garzik 605c6fd2807SJeff Garzik { } /* terminate list */ 606c6fd2807SJeff Garzik }; 607c6fd2807SJeff Garzik 608f1d848f9SMika Westerberg static const struct dev_pm_ops ahci_pci_pm_ops = { 609f1d848f9SMika Westerberg SET_SYSTEM_SLEEP_PM_OPS(ahci_pci_device_suspend, ahci_pci_device_resume) 61002e53293SMika Westerberg SET_RUNTIME_PM_OPS(ahci_pci_device_runtime_suspend, 61102e53293SMika Westerberg ahci_pci_device_runtime_resume, NULL) 612f1d848f9SMika Westerberg }; 613c6fd2807SJeff Garzik 614c6fd2807SJeff Garzik static struct pci_driver ahci_pci_driver = { 615c6fd2807SJeff Garzik .name = DRV_NAME, 616c6fd2807SJeff Garzik .id_table = ahci_pci_tbl, 617c6fd2807SJeff Garzik .probe = ahci_init_one, 61802e53293SMika Westerberg .remove = ahci_remove_one, 61910a663a1SPrabhakar Kushwaha .shutdown = ahci_shutdown_one, 620f1d848f9SMika Westerberg .driver = { 621f1d848f9SMika Westerberg .pm = &ahci_pci_pm_ops, 622f1d848f9SMika Westerberg }, 623c6fd2807SJeff Garzik }; 624c6fd2807SJeff Garzik 6255219d653SJavier Martinez Canillas #if IS_ENABLED(CONFIG_PATA_MARVELL) 6265b66c829SAlan Cox static int marvell_enable; 6275b66c829SAlan Cox #else 6285b66c829SAlan Cox static int marvell_enable = 1; 6295b66c829SAlan Cox #endif 6305b66c829SAlan Cox module_param(marvell_enable, int, 0644); 6315b66c829SAlan Cox MODULE_PARM_DESC(marvell_enable, "Marvell SATA via AHCI (1 = enabled)"); 6325b66c829SAlan Cox 633b1a9585cSSrinivas Pandruvada static int mobile_lpm_policy = -1; 634ebb82e3cSHans de Goede module_param(mobile_lpm_policy, int, 0644); 635ebb82e3cSHans de Goede MODULE_PARM_DESC(mobile_lpm_policy, "Default LPM policy for mobile chipsets"); 6365b66c829SAlan Cox 637394d6e53SAnton Vorontsov static void ahci_pci_save_initial_config(struct pci_dev *pdev, 638394d6e53SAnton Vorontsov struct ahci_host_priv *hpriv) 639394d6e53SAnton Vorontsov { 640394d6e53SAnton Vorontsov if (pdev->vendor == PCI_VENDOR_ID_JMICRON && pdev->device == 0x2361) { 641394d6e53SAnton Vorontsov dev_info(&pdev->dev, "JMB361 has only one port\n"); 6429a23c1d6SAntoine Tenart hpriv->force_port_map = 1; 643394d6e53SAnton Vorontsov } 644394d6e53SAnton Vorontsov 645394d6e53SAnton Vorontsov /* 646394d6e53SAnton Vorontsov * Temporary Marvell 6145 hack: PATA port presence 647394d6e53SAnton Vorontsov * is asserted through the standard AHCI port 648394d6e53SAnton Vorontsov * presence register, as bit 4 (counting from 0) 649394d6e53SAnton Vorontsov */ 650394d6e53SAnton Vorontsov if (hpriv->flags & AHCI_HFLAG_MV_PATA) { 651394d6e53SAnton Vorontsov if (pdev->device == 0x6121) 6529a23c1d6SAntoine Tenart hpriv->mask_port_map = 0x3; 653394d6e53SAnton Vorontsov else 6549a23c1d6SAntoine Tenart hpriv->mask_port_map = 0xf; 655394d6e53SAnton Vorontsov dev_info(&pdev->dev, 656394d6e53SAnton Vorontsov "Disabling your PATA port. Use the boot option 'ahci.marvell_enable=0' to avoid this.\n"); 657394d6e53SAnton Vorontsov } 658394d6e53SAnton Vorontsov 659725c7b57SAntoine Ténart ahci_save_initial_config(&pdev->dev, hpriv); 660394d6e53SAnton Vorontsov } 661394d6e53SAnton Vorontsov 662781d6550SAnton Vorontsov static void ahci_pci_init_controller(struct ata_host *host) 663781d6550SAnton Vorontsov { 664781d6550SAnton Vorontsov struct ahci_host_priv *hpriv = host->private_data; 665781d6550SAnton Vorontsov struct pci_dev *pdev = to_pci_dev(host->dev); 666781d6550SAnton Vorontsov void __iomem *port_mmio; 667781d6550SAnton Vorontsov u32 tmp; 668c40e7cb8SJose Alberto Reguero int mv; 6692bcd866bSJeff Garzik 670417a1a6dSTejun Heo if (hpriv->flags & AHCI_HFLAG_MV_PATA) { 671c40e7cb8SJose Alberto Reguero if (pdev->device == 0x6121) 672c40e7cb8SJose Alberto Reguero mv = 2; 673c40e7cb8SJose Alberto Reguero else 674c40e7cb8SJose Alberto Reguero mv = 4; 675c40e7cb8SJose Alberto Reguero port_mmio = __ahci_port_base(host, mv); 676cd70c266SJeff Garzik 677cd70c266SJeff Garzik writel(0, port_mmio + PORT_IRQ_MASK); 678cd70c266SJeff Garzik 679cd70c266SJeff Garzik /* clear port IRQ */ 680cd70c266SJeff Garzik tmp = readl(port_mmio + PORT_IRQ_STAT); 681cd70c266SJeff Garzik VPRINTK("PORT_IRQ_STAT 0x%x\n", tmp); 682cd70c266SJeff Garzik if (tmp) 683cd70c266SJeff Garzik writel(tmp, port_mmio + PORT_IRQ_STAT); 684cd70c266SJeff Garzik } 685cd70c266SJeff Garzik 686781d6550SAnton Vorontsov ahci_init_controller(host); 687c6fd2807SJeff Garzik } 688c6fd2807SJeff Garzik 689cc0680a5STejun Heo static int ahci_vt8251_hardreset(struct ata_link *link, unsigned int *class, 690d4b2bab4STejun Heo unsigned long deadline) 691ad616ffbSTejun Heo { 692cc0680a5STejun Heo struct ata_port *ap = link->ap; 693039ece38SHans de Goede struct ahci_host_priv *hpriv = ap->host->private_data; 6949dadd45bSTejun Heo bool online; 695ad616ffbSTejun Heo int rc; 696ad616ffbSTejun Heo 697ad616ffbSTejun Heo DPRINTK("ENTER\n"); 698ad616ffbSTejun Heo 699fa89f53bSEvan Wang hpriv->stop_engine(ap); 700ad616ffbSTejun Heo 701cc0680a5STejun Heo rc = sata_link_hardreset(link, sata_ehc_deb_timing(&link->eh_context), 7029dadd45bSTejun Heo deadline, &online, NULL); 703ad616ffbSTejun Heo 704039ece38SHans de Goede hpriv->start_engine(ap); 705ad616ffbSTejun Heo 706ad616ffbSTejun Heo DPRINTK("EXIT, rc=%d, class=%u\n", rc, *class); 707ad616ffbSTejun Heo 708ad616ffbSTejun Heo /* vt8251 doesn't clear BSY on signature FIS reception, 709ad616ffbSTejun Heo * request follow-up softreset. 710ad616ffbSTejun Heo */ 7119dadd45bSTejun Heo return online ? -EAGAIN : rc; 712ad616ffbSTejun Heo } 713ad616ffbSTejun Heo 714edc93052STejun Heo static int ahci_p5wdh_hardreset(struct ata_link *link, unsigned int *class, 715edc93052STejun Heo unsigned long deadline) 716edc93052STejun Heo { 717edc93052STejun Heo struct ata_port *ap = link->ap; 718edc93052STejun Heo struct ahci_port_priv *pp = ap->private_data; 719039ece38SHans de Goede struct ahci_host_priv *hpriv = ap->host->private_data; 720edc93052STejun Heo u8 *d2h_fis = pp->rx_fis + RX_FIS_D2H_REG; 721edc93052STejun Heo struct ata_taskfile tf; 7229dadd45bSTejun Heo bool online; 723edc93052STejun Heo int rc; 724edc93052STejun Heo 725fa89f53bSEvan Wang hpriv->stop_engine(ap); 726edc93052STejun Heo 727edc93052STejun Heo /* clear D2H reception area to properly wait for D2H FIS */ 728edc93052STejun Heo ata_tf_init(link->device, &tf); 7299bbb1b0eSSergei Shtylyov tf.command = ATA_BUSY; 730edc93052STejun Heo ata_tf_to_fis(&tf, 0, 0, d2h_fis); 731edc93052STejun Heo 732edc93052STejun Heo rc = sata_link_hardreset(link, sata_ehc_deb_timing(&link->eh_context), 7339dadd45bSTejun Heo deadline, &online, NULL); 734edc93052STejun Heo 735039ece38SHans de Goede hpriv->start_engine(ap); 736edc93052STejun Heo 737edc93052STejun Heo /* The pseudo configuration device on SIMG4726 attached to 738edc93052STejun Heo * ASUS P5W-DH Deluxe doesn't send signature FIS after 739edc93052STejun Heo * hardreset if no device is attached to the first downstream 740edc93052STejun Heo * port && the pseudo device locks up on SRST w/ PMP==0. To 741edc93052STejun Heo * work around this, wait for !BSY only briefly. If BSY isn't 742edc93052STejun Heo * cleared, perform CLO and proceed to IDENTIFY (achieved by 743edc93052STejun Heo * ATA_LFLAG_NO_SRST and ATA_LFLAG_ASSUME_ATA). 744edc93052STejun Heo * 745edc93052STejun Heo * Wait for two seconds. Devices attached to downstream port 746edc93052STejun Heo * which can't process the following IDENTIFY after this will 747edc93052STejun Heo * have to be reset again. For most cases, this should 748edc93052STejun Heo * suffice while making probing snappish enough. 749edc93052STejun Heo */ 7509dadd45bSTejun Heo if (online) { 7519dadd45bSTejun Heo rc = ata_wait_after_reset(link, jiffies + 2 * HZ, 7529dadd45bSTejun Heo ahci_check_ready); 753edc93052STejun Heo if (rc) 75478d5ae39SShane Huang ahci_kick_engine(ap); 7559dadd45bSTejun Heo } 7569dadd45bSTejun Heo return rc; 757edc93052STejun Heo } 758edc93052STejun Heo 759dbfe8ef5SDan Williams /* 760dbfe8ef5SDan Williams * ahci_avn_hardreset - attempt more aggressive recovery of Avoton ports. 761dbfe8ef5SDan Williams * 762dbfe8ef5SDan Williams * It has been observed with some SSDs that the timing of events in the 763dbfe8ef5SDan Williams * link synchronization phase can leave the port in a state that can not 764dbfe8ef5SDan Williams * be recovered by a SATA-hard-reset alone. The failing signature is 765dbfe8ef5SDan Williams * SStatus.DET stuck at 1 ("Device presence detected but Phy 766dbfe8ef5SDan Williams * communication not established"). It was found that unloading and 767dbfe8ef5SDan Williams * reloading the driver when this problem occurs allows the drive 768dbfe8ef5SDan Williams * connection to be recovered (DET advanced to 0x3). The critical 769dbfe8ef5SDan Williams * component of reloading the driver is that the port state machines are 770dbfe8ef5SDan Williams * reset by bouncing "port enable" in the AHCI PCS configuration 771dbfe8ef5SDan Williams * register. So, reproduce that effect by bouncing a port whenever we 772dbfe8ef5SDan Williams * see DET==1 after a reset. 773dbfe8ef5SDan Williams */ 774dbfe8ef5SDan Williams static int ahci_avn_hardreset(struct ata_link *link, unsigned int *class, 775dbfe8ef5SDan Williams unsigned long deadline) 776dbfe8ef5SDan Williams { 777dbfe8ef5SDan Williams const unsigned long *timing = sata_ehc_deb_timing(&link->eh_context); 778dbfe8ef5SDan Williams struct ata_port *ap = link->ap; 779dbfe8ef5SDan Williams struct ahci_port_priv *pp = ap->private_data; 780dbfe8ef5SDan Williams struct ahci_host_priv *hpriv = ap->host->private_data; 781dbfe8ef5SDan Williams u8 *d2h_fis = pp->rx_fis + RX_FIS_D2H_REG; 782dbfe8ef5SDan Williams unsigned long tmo = deadline - jiffies; 783dbfe8ef5SDan Williams struct ata_taskfile tf; 784dbfe8ef5SDan Williams bool online; 785dbfe8ef5SDan Williams int rc, i; 786dbfe8ef5SDan Williams 787dbfe8ef5SDan Williams DPRINTK("ENTER\n"); 788dbfe8ef5SDan Williams 789fa89f53bSEvan Wang hpriv->stop_engine(ap); 790dbfe8ef5SDan Williams 791dbfe8ef5SDan Williams for (i = 0; i < 2; i++) { 792dbfe8ef5SDan Williams u16 val; 793dbfe8ef5SDan Williams u32 sstatus; 794dbfe8ef5SDan Williams int port = ap->port_no; 795dbfe8ef5SDan Williams struct ata_host *host = ap->host; 796dbfe8ef5SDan Williams struct pci_dev *pdev = to_pci_dev(host->dev); 797dbfe8ef5SDan Williams 798dbfe8ef5SDan Williams /* clear D2H reception area to properly wait for D2H FIS */ 799dbfe8ef5SDan Williams ata_tf_init(link->device, &tf); 800dbfe8ef5SDan Williams tf.command = ATA_BUSY; 801dbfe8ef5SDan Williams ata_tf_to_fis(&tf, 0, 0, d2h_fis); 802dbfe8ef5SDan Williams 803dbfe8ef5SDan Williams rc = sata_link_hardreset(link, timing, deadline, &online, 804dbfe8ef5SDan Williams ahci_check_ready); 805dbfe8ef5SDan Williams 806dbfe8ef5SDan Williams if (sata_scr_read(link, SCR_STATUS, &sstatus) != 0 || 807dbfe8ef5SDan Williams (sstatus & 0xf) != 1) 808dbfe8ef5SDan Williams break; 809dbfe8ef5SDan Williams 810*e276c9bdSXu Wang ata_link_info(link, "avn bounce port%d\n", port); 811dbfe8ef5SDan Williams 812dbfe8ef5SDan Williams pci_read_config_word(pdev, 0x92, &val); 813dbfe8ef5SDan Williams val &= ~(1 << port); 814dbfe8ef5SDan Williams pci_write_config_word(pdev, 0x92, val); 815dbfe8ef5SDan Williams ata_msleep(ap, 1000); 816dbfe8ef5SDan Williams val |= 1 << port; 817dbfe8ef5SDan Williams pci_write_config_word(pdev, 0x92, val); 818dbfe8ef5SDan Williams deadline += tmo; 819dbfe8ef5SDan Williams } 820dbfe8ef5SDan Williams 821dbfe8ef5SDan Williams hpriv->start_engine(ap); 822dbfe8ef5SDan Williams 823dbfe8ef5SDan Williams if (online) 824dbfe8ef5SDan Williams *class = ahci_dev_classify(ap); 825dbfe8ef5SDan Williams 826dbfe8ef5SDan Williams DPRINTK("EXIT, rc=%d, class=%u\n", rc, *class); 827dbfe8ef5SDan Williams return rc; 828dbfe8ef5SDan Williams } 829dbfe8ef5SDan Williams 830dbfe8ef5SDan Williams 83102e53293SMika Westerberg #ifdef CONFIG_PM 83202e53293SMika Westerberg static void ahci_pci_disable_interrupts(struct ata_host *host) 833c6fd2807SJeff Garzik { 8349b10ae86STejun Heo struct ahci_host_priv *hpriv = host->private_data; 835d8993349SAnton Vorontsov void __iomem *mmio = hpriv->mmio; 836c6fd2807SJeff Garzik u32 ctl; 837c6fd2807SJeff Garzik 838c6fd2807SJeff Garzik /* AHCI spec rev1.1 section 8.3.3: 839c6fd2807SJeff Garzik * Software must disable interrupts prior to requesting a 840c6fd2807SJeff Garzik * transition of the HBA to D3 state. 841c6fd2807SJeff Garzik */ 842c6fd2807SJeff Garzik ctl = readl(mmio + HOST_CTL); 843c6fd2807SJeff Garzik ctl &= ~HOST_IRQ_EN; 844c6fd2807SJeff Garzik writel(ctl, mmio + HOST_CTL); 845c6fd2807SJeff Garzik readl(mmio + HOST_CTL); /* flush */ 84602e53293SMika Westerberg } 847f1d848f9SMika Westerberg 84802e53293SMika Westerberg static int ahci_pci_device_runtime_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 85302e53293SMika Westerberg ahci_pci_disable_interrupts(host); 85402e53293SMika Westerberg return 0; 85502e53293SMika Westerberg } 85602e53293SMika Westerberg 85702e53293SMika Westerberg static int ahci_pci_device_runtime_resume(struct device *dev) 85802e53293SMika Westerberg { 85902e53293SMika Westerberg struct pci_dev *pdev = to_pci_dev(dev); 86002e53293SMika Westerberg struct ata_host *host = pci_get_drvdata(pdev); 86102e53293SMika Westerberg int rc; 86202e53293SMika Westerberg 863c312ef17SDan Williams rc = ahci_reset_controller(host); 86402e53293SMika Westerberg if (rc) 86502e53293SMika Westerberg return rc; 86602e53293SMika Westerberg ahci_pci_init_controller(host); 86702e53293SMika Westerberg return 0; 86802e53293SMika Westerberg } 86902e53293SMika Westerberg 87002e53293SMika Westerberg #ifdef CONFIG_PM_SLEEP 87102e53293SMika Westerberg static int ahci_pci_device_suspend(struct device *dev) 87202e53293SMika Westerberg { 87302e53293SMika Westerberg struct pci_dev *pdev = to_pci_dev(dev); 87402e53293SMika Westerberg struct ata_host *host = pci_get_drvdata(pdev); 87502e53293SMika Westerberg struct ahci_host_priv *hpriv = host->private_data; 87602e53293SMika Westerberg 87702e53293SMika Westerberg if (hpriv->flags & AHCI_HFLAG_NO_SUSPEND) { 87802e53293SMika Westerberg dev_err(&pdev->dev, 87902e53293SMika Westerberg "BIOS update required for suspend/resume\n"); 88002e53293SMika Westerberg return -EIO; 88102e53293SMika Westerberg } 88202e53293SMika Westerberg 88302e53293SMika Westerberg ahci_pci_disable_interrupts(host); 884f1d848f9SMika Westerberg return ata_host_suspend(host, PMSG_SUSPEND); 885c6fd2807SJeff Garzik } 886c6fd2807SJeff Garzik 887f1d848f9SMika Westerberg static int ahci_pci_device_resume(struct device *dev) 888c6fd2807SJeff Garzik { 889f1d848f9SMika Westerberg struct pci_dev *pdev = to_pci_dev(dev); 8900a86e1c8SJingoo Han struct ata_host *host = pci_get_drvdata(pdev); 891c6fd2807SJeff Garzik int rc; 892c6fd2807SJeff Garzik 893cb85696dSJames Laird /* Apple BIOS helpfully mangles the registers on resume */ 894cb85696dSJames Laird if (is_mcp89_apple(pdev)) 895cb85696dSJames Laird ahci_mcp89_apple_enable(pdev); 896cb85696dSJames Laird 897c6fd2807SJeff Garzik if (pdev->dev.power.power_state.event == PM_EVENT_SUSPEND) { 898c312ef17SDan Williams rc = ahci_reset_controller(host); 899c6fd2807SJeff Garzik if (rc) 900c6fd2807SJeff Garzik return rc; 901c6fd2807SJeff Garzik 902781d6550SAnton Vorontsov ahci_pci_init_controller(host); 903c6fd2807SJeff Garzik } 904c6fd2807SJeff Garzik 905cca3974eSJeff Garzik ata_host_resume(host); 906c6fd2807SJeff Garzik 907c6fd2807SJeff Garzik return 0; 908c6fd2807SJeff Garzik } 909438ac6d5STejun Heo #endif 910c6fd2807SJeff Garzik 91102e53293SMika Westerberg #endif /* CONFIG_PM */ 91202e53293SMika Westerberg 9134447d351STejun Heo static int ahci_configure_dma_masks(struct pci_dev *pdev, int using_dac) 914c6fd2807SJeff Garzik { 915b1716871SChristoph Hellwig const int dma_bits = using_dac ? 64 : 32; 916c6fd2807SJeff Garzik int rc; 917c6fd2807SJeff Garzik 918318893e1SAlessandro Rubini /* 919318893e1SAlessandro Rubini * If the device fixup already set the dma_mask to some non-standard 920318893e1SAlessandro Rubini * value, don't extend it here. This happens on STA2X11, for example. 921b1716871SChristoph Hellwig * 922b1716871SChristoph Hellwig * XXX: manipulating the DMA mask from platform code is completely 923a7ba70f1SNicolas Saenz Julienne * bogus, platform code should use dev->bus_dma_limit instead.. 924318893e1SAlessandro Rubini */ 925318893e1SAlessandro Rubini if (pdev->dma_mask && pdev->dma_mask < DMA_BIT_MASK(32)) 926318893e1SAlessandro Rubini return 0; 927318893e1SAlessandro Rubini 928b1716871SChristoph Hellwig rc = dma_set_mask_and_coherent(&pdev->dev, DMA_BIT_MASK(dma_bits)); 929b1716871SChristoph Hellwig if (rc) 930b1716871SChristoph Hellwig dev_err(&pdev->dev, "DMA enable failed\n"); 931c6fd2807SJeff Garzik return rc; 932c6fd2807SJeff Garzik } 933c6fd2807SJeff Garzik 934439fcaecSAnton Vorontsov static void ahci_pci_print_info(struct ata_host *host) 935439fcaecSAnton Vorontsov { 936439fcaecSAnton Vorontsov struct pci_dev *pdev = to_pci_dev(host->dev); 937439fcaecSAnton Vorontsov u16 cc; 938439fcaecSAnton Vorontsov const char *scc_s; 939439fcaecSAnton Vorontsov 940439fcaecSAnton Vorontsov pci_read_config_word(pdev, 0x0a, &cc); 941439fcaecSAnton Vorontsov if (cc == PCI_CLASS_STORAGE_IDE) 942439fcaecSAnton Vorontsov scc_s = "IDE"; 943439fcaecSAnton Vorontsov else if (cc == PCI_CLASS_STORAGE_SATA) 944439fcaecSAnton Vorontsov scc_s = "SATA"; 945439fcaecSAnton Vorontsov else if (cc == PCI_CLASS_STORAGE_RAID) 946439fcaecSAnton Vorontsov scc_s = "RAID"; 947439fcaecSAnton Vorontsov else 948439fcaecSAnton Vorontsov scc_s = "unknown"; 949439fcaecSAnton Vorontsov 950439fcaecSAnton Vorontsov ahci_print_info(host, scc_s); 951439fcaecSAnton Vorontsov } 952439fcaecSAnton Vorontsov 953edc93052STejun Heo /* On ASUS P5W DH Deluxe, the second port of PCI device 00:1f.2 is 954edc93052STejun Heo * hardwired to on-board SIMG 4726. The chipset is ICH8 and doesn't 955edc93052STejun Heo * support PMP and the 4726 either directly exports the device 956edc93052STejun Heo * attached to the first downstream port or acts as a hardware storage 957edc93052STejun Heo * controller and emulate a single ATA device (can be RAID 0/1 or some 958edc93052STejun Heo * other configuration). 959edc93052STejun Heo * 960edc93052STejun Heo * When there's no device attached to the first downstream port of the 961edc93052STejun Heo * 4726, "Config Disk" appears, which is a pseudo ATA device to 962edc93052STejun Heo * configure the 4726. However, ATA emulation of the device is very 963edc93052STejun Heo * lame. It doesn't send signature D2H Reg FIS after the initial 964edc93052STejun Heo * hardreset, pukes on SRST w/ PMP==0 and has bunch of other issues. 965edc93052STejun Heo * 966edc93052STejun Heo * The following function works around the problem by always using 967edc93052STejun Heo * hardreset on the port and not depending on receiving signature FIS 968edc93052STejun Heo * afterward. If signature FIS isn't received soon, ATA class is 969edc93052STejun Heo * assumed without follow-up softreset. 970edc93052STejun Heo */ 971edc93052STejun Heo static void ahci_p5wdh_workaround(struct ata_host *host) 972edc93052STejun Heo { 9731bd06867SMathias Krause static const struct dmi_system_id sysids[] = { 974edc93052STejun Heo { 975edc93052STejun Heo .ident = "P5W DH Deluxe", 976edc93052STejun Heo .matches = { 977edc93052STejun Heo DMI_MATCH(DMI_SYS_VENDOR, 978edc93052STejun Heo "ASUSTEK COMPUTER INC"), 979edc93052STejun Heo DMI_MATCH(DMI_PRODUCT_NAME, "P5W DH Deluxe"), 980edc93052STejun Heo }, 981edc93052STejun Heo }, 982edc93052STejun Heo { } 983edc93052STejun Heo }; 984edc93052STejun Heo struct pci_dev *pdev = to_pci_dev(host->dev); 985edc93052STejun Heo 986edc93052STejun Heo if (pdev->bus->number == 0 && pdev->devfn == PCI_DEVFN(0x1f, 2) && 987edc93052STejun Heo dmi_check_system(sysids)) { 988edc93052STejun Heo struct ata_port *ap = host->ports[1]; 989edc93052STejun Heo 990a44fec1fSJoe Perches dev_info(&pdev->dev, 991a44fec1fSJoe Perches "enabling ASUS P5W DH Deluxe on-board SIMG4726 workaround\n"); 992edc93052STejun Heo 993edc93052STejun Heo ap->ops = &ahci_p5wdh_ops; 994edc93052STejun Heo ap->link.flags |= ATA_LFLAG_NO_SRST | ATA_LFLAG_ASSUME_ATA; 995edc93052STejun Heo } 996edc93052STejun Heo } 997edc93052STejun Heo 998cb85696dSJames Laird /* 999cb85696dSJames Laird * Macbook7,1 firmware forcibly disables MCP89 AHCI and changes PCI ID when 1000cb85696dSJames Laird * booting in BIOS compatibility mode. We restore the registers but not ID. 1001cb85696dSJames Laird */ 1002cb85696dSJames Laird static void ahci_mcp89_apple_enable(struct pci_dev *pdev) 1003cb85696dSJames Laird { 1004cb85696dSJames Laird u32 val; 1005cb85696dSJames Laird 1006cb85696dSJames Laird printk(KERN_INFO "ahci: enabling MCP89 AHCI mode\n"); 1007cb85696dSJames Laird 1008cb85696dSJames Laird pci_read_config_dword(pdev, 0xf8, &val); 1009cb85696dSJames Laird val |= 1 << 0x1b; 1010cb85696dSJames Laird /* the following changes the device ID, but appears not to affect function */ 1011cb85696dSJames Laird /* val = (val & ~0xf0000000) | 0x80000000; */ 1012cb85696dSJames Laird pci_write_config_dword(pdev, 0xf8, val); 1013cb85696dSJames Laird 1014cb85696dSJames Laird pci_read_config_dword(pdev, 0x54c, &val); 1015cb85696dSJames Laird val |= 1 << 0xc; 1016cb85696dSJames Laird pci_write_config_dword(pdev, 0x54c, val); 1017cb85696dSJames Laird 1018cb85696dSJames Laird pci_read_config_dword(pdev, 0x4a4, &val); 1019cb85696dSJames Laird val &= 0xff; 1020cb85696dSJames Laird val |= 0x01060100; 1021cb85696dSJames Laird pci_write_config_dword(pdev, 0x4a4, val); 1022cb85696dSJames Laird 1023cb85696dSJames Laird pci_read_config_dword(pdev, 0x54c, &val); 1024cb85696dSJames Laird val &= ~(1 << 0xc); 1025cb85696dSJames Laird pci_write_config_dword(pdev, 0x54c, val); 1026cb85696dSJames Laird 1027cb85696dSJames Laird pci_read_config_dword(pdev, 0xf8, &val); 1028cb85696dSJames Laird val &= ~(1 << 0x1b); 1029cb85696dSJames Laird pci_write_config_dword(pdev, 0xf8, val); 1030cb85696dSJames Laird } 1031cb85696dSJames Laird 1032cb85696dSJames Laird static bool is_mcp89_apple(struct pci_dev *pdev) 1033cb85696dSJames Laird { 1034cb85696dSJames Laird return pdev->vendor == PCI_VENDOR_ID_NVIDIA && 1035cb85696dSJames Laird pdev->device == PCI_DEVICE_ID_NVIDIA_NFORCE_MCP89_SATA && 1036cb85696dSJames Laird pdev->subsystem_vendor == PCI_VENDOR_ID_APPLE && 1037cb85696dSJames Laird pdev->subsystem_device == 0xcb89; 1038cb85696dSJames Laird } 1039cb85696dSJames Laird 10402fcad9d2STejun Heo /* only some SB600 ahci controllers can do 64bit DMA */ 10412fcad9d2STejun Heo static bool ahci_sb600_enable_64bit(struct pci_dev *pdev) 104258a09b38SShane Huang { 104358a09b38SShane Huang static const struct dmi_system_id sysids[] = { 104403d783bfSTejun Heo /* 104503d783bfSTejun Heo * The oldest version known to be broken is 0901 and 104603d783bfSTejun Heo * working is 1501 which was released on 2007-10-26. 10472fcad9d2STejun Heo * Enable 64bit DMA on 1501 and anything newer. 10482fcad9d2STejun Heo * 104903d783bfSTejun Heo * Please read bko#9412 for more info. 105003d783bfSTejun Heo */ 105158a09b38SShane Huang { 105258a09b38SShane Huang .ident = "ASUS M2A-VM", 105358a09b38SShane Huang .matches = { 105458a09b38SShane Huang DMI_MATCH(DMI_BOARD_VENDOR, 105558a09b38SShane Huang "ASUSTeK Computer INC."), 105658a09b38SShane Huang DMI_MATCH(DMI_BOARD_NAME, "M2A-VM"), 105758a09b38SShane Huang }, 105803d783bfSTejun Heo .driver_data = "20071026", /* yyyymmdd */ 105958a09b38SShane Huang }, 1060e65cc194SMark Nelson /* 1061e65cc194SMark Nelson * All BIOS versions for the MSI K9A2 Platinum (MS-7376) 1062e65cc194SMark Nelson * support 64bit DMA. 1063e65cc194SMark Nelson * 1064e65cc194SMark Nelson * BIOS versions earlier than 1.5 had the Manufacturer DMI 1065e65cc194SMark Nelson * fields as "MICRO-STAR INTERANTIONAL CO.,LTD". 1066e65cc194SMark Nelson * This spelling mistake was fixed in BIOS version 1.5, so 1067e65cc194SMark Nelson * 1.5 and later have the Manufacturer as 1068e65cc194SMark Nelson * "MICRO-STAR INTERNATIONAL CO.,LTD". 1069e65cc194SMark Nelson * So try to match on DMI_BOARD_VENDOR of "MICRO-STAR INTER". 1070e65cc194SMark Nelson * 1071e65cc194SMark Nelson * BIOS versions earlier than 1.9 had a Board Product Name 1072e65cc194SMark Nelson * DMI field of "MS-7376". This was changed to be 1073e65cc194SMark Nelson * "K9A2 Platinum (MS-7376)" in version 1.9, but we can still 1074e65cc194SMark Nelson * match on DMI_BOARD_NAME of "MS-7376". 1075e65cc194SMark Nelson */ 1076e65cc194SMark Nelson { 1077e65cc194SMark Nelson .ident = "MSI K9A2 Platinum", 1078e65cc194SMark Nelson .matches = { 1079e65cc194SMark Nelson DMI_MATCH(DMI_BOARD_VENDOR, 1080e65cc194SMark Nelson "MICRO-STAR INTER"), 1081e65cc194SMark Nelson DMI_MATCH(DMI_BOARD_NAME, "MS-7376"), 1082e65cc194SMark Nelson }, 1083e65cc194SMark Nelson }, 10843c4aa91fSMark Nelson /* 1085ff0173c1SMark Nelson * All BIOS versions for the MSI K9AGM2 (MS-7327) support 1086ff0173c1SMark Nelson * 64bit DMA. 1087ff0173c1SMark Nelson * 1088ff0173c1SMark Nelson * This board also had the typo mentioned above in the 1089ff0173c1SMark Nelson * Manufacturer DMI field (fixed in BIOS version 1.5), so 1090ff0173c1SMark Nelson * match on DMI_BOARD_VENDOR of "MICRO-STAR INTER" again. 1091ff0173c1SMark Nelson */ 1092ff0173c1SMark Nelson { 1093ff0173c1SMark Nelson .ident = "MSI K9AGM2", 1094ff0173c1SMark Nelson .matches = { 1095ff0173c1SMark Nelson DMI_MATCH(DMI_BOARD_VENDOR, 1096ff0173c1SMark Nelson "MICRO-STAR INTER"), 1097ff0173c1SMark Nelson DMI_MATCH(DMI_BOARD_NAME, "MS-7327"), 1098ff0173c1SMark Nelson }, 1099ff0173c1SMark Nelson }, 1100ff0173c1SMark Nelson /* 11013c4aa91fSMark Nelson * All BIOS versions for the Asus M3A support 64bit DMA. 11023c4aa91fSMark Nelson * (all release versions from 0301 to 1206 were tested) 11033c4aa91fSMark Nelson */ 11043c4aa91fSMark Nelson { 11053c4aa91fSMark Nelson .ident = "ASUS M3A", 11063c4aa91fSMark Nelson .matches = { 11073c4aa91fSMark Nelson DMI_MATCH(DMI_BOARD_VENDOR, 11083c4aa91fSMark Nelson "ASUSTeK Computer INC."), 11093c4aa91fSMark Nelson DMI_MATCH(DMI_BOARD_NAME, "M3A"), 11103c4aa91fSMark Nelson }, 11113c4aa91fSMark Nelson }, 111258a09b38SShane Huang { } 111358a09b38SShane Huang }; 111403d783bfSTejun Heo const struct dmi_system_id *match; 11152fcad9d2STejun Heo int year, month, date; 11162fcad9d2STejun Heo char buf[9]; 111758a09b38SShane Huang 111803d783bfSTejun Heo match = dmi_first_match(sysids); 111958a09b38SShane Huang if (pdev->bus->number != 0 || pdev->devfn != PCI_DEVFN(0x12, 0) || 112003d783bfSTejun Heo !match) 112158a09b38SShane Huang return false; 112258a09b38SShane Huang 1123e65cc194SMark Nelson if (!match->driver_data) 1124e65cc194SMark Nelson goto enable_64bit; 1125e65cc194SMark Nelson 112603d783bfSTejun Heo dmi_get_date(DMI_BIOS_DATE, &year, &month, &date); 112703d783bfSTejun Heo snprintf(buf, sizeof(buf), "%04d%02d%02d", year, month, date); 112803d783bfSTejun Heo 1129e65cc194SMark Nelson if (strcmp(buf, match->driver_data) >= 0) 1130e65cc194SMark Nelson goto enable_64bit; 1131e65cc194SMark Nelson else { 1132a44fec1fSJoe Perches dev_warn(&pdev->dev, 1133a44fec1fSJoe Perches "%s: BIOS too old, forcing 32bit DMA, update BIOS\n", 1134a44fec1fSJoe Perches match->ident); 11352fcad9d2STejun Heo return false; 11362fcad9d2STejun Heo } 1137e65cc194SMark Nelson 1138e65cc194SMark Nelson enable_64bit: 1139a44fec1fSJoe Perches dev_warn(&pdev->dev, "%s: enabling 64bit DMA\n", match->ident); 1140e65cc194SMark Nelson return true; 114158a09b38SShane Huang } 114258a09b38SShane Huang 11431fd68434SRafael J. Wysocki static bool ahci_broken_system_poweroff(struct pci_dev *pdev) 11441fd68434SRafael J. Wysocki { 11451fd68434SRafael J. Wysocki static const struct dmi_system_id broken_systems[] = { 11461fd68434SRafael J. Wysocki { 11471fd68434SRafael J. Wysocki .ident = "HP Compaq nx6310", 11481fd68434SRafael J. Wysocki .matches = { 11491fd68434SRafael J. Wysocki DMI_MATCH(DMI_SYS_VENDOR, "Hewlett-Packard"), 11501fd68434SRafael J. Wysocki DMI_MATCH(DMI_PRODUCT_NAME, "HP Compaq nx6310"), 11511fd68434SRafael J. Wysocki }, 11521fd68434SRafael J. Wysocki /* PCI slot number of the controller */ 11531fd68434SRafael J. Wysocki .driver_data = (void *)0x1FUL, 11541fd68434SRafael J. Wysocki }, 1155d2f9c061SMaciej Rutecki { 1156d2f9c061SMaciej Rutecki .ident = "HP Compaq 6720s", 1157d2f9c061SMaciej Rutecki .matches = { 1158d2f9c061SMaciej Rutecki DMI_MATCH(DMI_SYS_VENDOR, "Hewlett-Packard"), 1159d2f9c061SMaciej Rutecki DMI_MATCH(DMI_PRODUCT_NAME, "HP Compaq 6720s"), 1160d2f9c061SMaciej Rutecki }, 1161d2f9c061SMaciej Rutecki /* PCI slot number of the controller */ 1162d2f9c061SMaciej Rutecki .driver_data = (void *)0x1FUL, 1163d2f9c061SMaciej Rutecki }, 11641fd68434SRafael J. Wysocki 11651fd68434SRafael J. Wysocki { } /* terminate list */ 11661fd68434SRafael J. Wysocki }; 11671fd68434SRafael J. Wysocki const struct dmi_system_id *dmi = dmi_first_match(broken_systems); 11681fd68434SRafael J. Wysocki 11691fd68434SRafael J. Wysocki if (dmi) { 11701fd68434SRafael J. Wysocki unsigned long slot = (unsigned long)dmi->driver_data; 11711fd68434SRafael J. Wysocki /* apply the quirk only to on-board controllers */ 11721fd68434SRafael J. Wysocki return slot == PCI_SLOT(pdev->devfn); 11731fd68434SRafael J. Wysocki } 11741fd68434SRafael J. Wysocki 11751fd68434SRafael J. Wysocki return false; 11761fd68434SRafael J. Wysocki } 11771fd68434SRafael J. Wysocki 11789b10ae86STejun Heo static bool ahci_broken_suspend(struct pci_dev *pdev) 11799b10ae86STejun Heo { 11809b10ae86STejun Heo static const struct dmi_system_id sysids[] = { 11819b10ae86STejun Heo /* 11829b10ae86STejun Heo * On HP dv[4-6] and HDX18 with earlier BIOSen, link 11839b10ae86STejun Heo * to the harddisk doesn't become online after 11849b10ae86STejun Heo * resuming from STR. Warn and fail suspend. 11859deb3431STejun Heo * 11869deb3431STejun Heo * http://bugzilla.kernel.org/show_bug.cgi?id=12276 11879deb3431STejun Heo * 11889deb3431STejun Heo * Use dates instead of versions to match as HP is 11899deb3431STejun Heo * apparently recycling both product and version 11909deb3431STejun Heo * strings. 11919deb3431STejun Heo * 11929deb3431STejun Heo * http://bugzilla.kernel.org/show_bug.cgi?id=15462 11939b10ae86STejun Heo */ 11949b10ae86STejun Heo { 11959b10ae86STejun Heo .ident = "dv4", 11969b10ae86STejun Heo .matches = { 11979b10ae86STejun Heo DMI_MATCH(DMI_SYS_VENDOR, "Hewlett-Packard"), 11989b10ae86STejun Heo DMI_MATCH(DMI_PRODUCT_NAME, 11999b10ae86STejun Heo "HP Pavilion dv4 Notebook PC"), 12009b10ae86STejun Heo }, 12019deb3431STejun Heo .driver_data = "20090105", /* F.30 */ 12029b10ae86STejun Heo }, 12039b10ae86STejun Heo { 12049b10ae86STejun Heo .ident = "dv5", 12059b10ae86STejun Heo .matches = { 12069b10ae86STejun Heo DMI_MATCH(DMI_SYS_VENDOR, "Hewlett-Packard"), 12079b10ae86STejun Heo DMI_MATCH(DMI_PRODUCT_NAME, 12089b10ae86STejun Heo "HP Pavilion dv5 Notebook PC"), 12099b10ae86STejun Heo }, 12109deb3431STejun Heo .driver_data = "20090506", /* F.16 */ 12119b10ae86STejun Heo }, 12129b10ae86STejun Heo { 12139b10ae86STejun Heo .ident = "dv6", 12149b10ae86STejun Heo .matches = { 12159b10ae86STejun Heo DMI_MATCH(DMI_SYS_VENDOR, "Hewlett-Packard"), 12169b10ae86STejun Heo DMI_MATCH(DMI_PRODUCT_NAME, 12179b10ae86STejun Heo "HP Pavilion dv6 Notebook PC"), 12189b10ae86STejun Heo }, 12199deb3431STejun Heo .driver_data = "20090423", /* F.21 */ 12209b10ae86STejun Heo }, 12219b10ae86STejun Heo { 12229b10ae86STejun Heo .ident = "HDX18", 12239b10ae86STejun Heo .matches = { 12249b10ae86STejun Heo DMI_MATCH(DMI_SYS_VENDOR, "Hewlett-Packard"), 12259b10ae86STejun Heo DMI_MATCH(DMI_PRODUCT_NAME, 12269b10ae86STejun Heo "HP HDX18 Notebook PC"), 12279b10ae86STejun Heo }, 12289deb3431STejun Heo .driver_data = "20090430", /* F.23 */ 12299b10ae86STejun Heo }, 1230cedc9bf9STejun Heo /* 1231cedc9bf9STejun Heo * Acer eMachines G725 has the same problem. BIOS 1232cedc9bf9STejun Heo * V1.03 is known to be broken. V3.04 is known to 123325985edcSLucas De Marchi * work. Between, there are V1.06, V2.06 and V3.03 1234cedc9bf9STejun Heo * that we don't have much idea about. For now, 1235cedc9bf9STejun Heo * blacklist anything older than V3.04. 12369deb3431STejun Heo * 12379deb3431STejun Heo * http://bugzilla.kernel.org/show_bug.cgi?id=15104 1238cedc9bf9STejun Heo */ 1239cedc9bf9STejun Heo { 1240cedc9bf9STejun Heo .ident = "G725", 1241cedc9bf9STejun Heo .matches = { 1242cedc9bf9STejun Heo DMI_MATCH(DMI_SYS_VENDOR, "eMachines"), 1243cedc9bf9STejun Heo DMI_MATCH(DMI_PRODUCT_NAME, "eMachines G725"), 1244cedc9bf9STejun Heo }, 12459deb3431STejun Heo .driver_data = "20091216", /* V3.04 */ 1246cedc9bf9STejun Heo }, 12479b10ae86STejun Heo { } /* terminate list */ 12489b10ae86STejun Heo }; 12499b10ae86STejun Heo const struct dmi_system_id *dmi = dmi_first_match(sysids); 12509deb3431STejun Heo int year, month, date; 12519deb3431STejun Heo char buf[9]; 12529b10ae86STejun Heo 12539b10ae86STejun Heo if (!dmi || pdev->bus->number || pdev->devfn != PCI_DEVFN(0x1f, 2)) 12549b10ae86STejun Heo return false; 12559b10ae86STejun Heo 12569deb3431STejun Heo dmi_get_date(DMI_BIOS_DATE, &year, &month, &date); 12579deb3431STejun Heo snprintf(buf, sizeof(buf), "%04d%02d%02d", year, month, date); 12589b10ae86STejun Heo 12599deb3431STejun Heo return strcmp(buf, dmi->driver_data) < 0; 12609b10ae86STejun Heo } 12619b10ae86STejun Heo 1262240630e6SHans de Goede static bool ahci_broken_lpm(struct pci_dev *pdev) 1263240630e6SHans de Goede { 1264240630e6SHans de Goede static const struct dmi_system_id sysids[] = { 1265240630e6SHans de Goede /* Various Lenovo 50 series have LPM issues with older BIOSen */ 1266240630e6SHans de Goede { 1267240630e6SHans de Goede .matches = { 1268240630e6SHans de Goede DMI_MATCH(DMI_SYS_VENDOR, "LENOVO"), 1269240630e6SHans de Goede DMI_MATCH(DMI_PRODUCT_VERSION, "ThinkPad X250"), 1270240630e6SHans de Goede }, 1271240630e6SHans de Goede .driver_data = "20180406", /* 1.31 */ 1272240630e6SHans de Goede }, 1273240630e6SHans de Goede { 1274240630e6SHans de Goede .matches = { 1275240630e6SHans de Goede DMI_MATCH(DMI_SYS_VENDOR, "LENOVO"), 1276240630e6SHans de Goede DMI_MATCH(DMI_PRODUCT_VERSION, "ThinkPad L450"), 1277240630e6SHans de Goede }, 1278240630e6SHans de Goede .driver_data = "20180420", /* 1.28 */ 1279240630e6SHans de Goede }, 1280240630e6SHans de Goede { 1281240630e6SHans de Goede .matches = { 1282240630e6SHans de Goede DMI_MATCH(DMI_SYS_VENDOR, "LENOVO"), 1283240630e6SHans de Goede DMI_MATCH(DMI_PRODUCT_VERSION, "ThinkPad T450s"), 1284240630e6SHans de Goede }, 1285240630e6SHans de Goede .driver_data = "20180315", /* 1.33 */ 1286240630e6SHans de Goede }, 1287240630e6SHans de Goede { 1288240630e6SHans de Goede .matches = { 1289240630e6SHans de Goede DMI_MATCH(DMI_SYS_VENDOR, "LENOVO"), 1290240630e6SHans de Goede DMI_MATCH(DMI_PRODUCT_VERSION, "ThinkPad W541"), 1291240630e6SHans de Goede }, 1292240630e6SHans de Goede /* 1293240630e6SHans de Goede * Note date based on release notes, 2.35 has been 1294240630e6SHans de Goede * reported to be good, but I've been unable to get 1295240630e6SHans de Goede * a hold of the reporter to get the DMI BIOS date. 1296240630e6SHans de Goede * TODO: fix this. 1297240630e6SHans de Goede */ 1298240630e6SHans de Goede .driver_data = "20180310", /* 2.35 */ 1299240630e6SHans de Goede }, 1300240630e6SHans de Goede { } /* terminate list */ 1301240630e6SHans de Goede }; 1302240630e6SHans de Goede const struct dmi_system_id *dmi = dmi_first_match(sysids); 1303240630e6SHans de Goede int year, month, date; 1304240630e6SHans de Goede char buf[9]; 1305240630e6SHans de Goede 1306240630e6SHans de Goede if (!dmi) 1307240630e6SHans de Goede return false; 1308240630e6SHans de Goede 1309240630e6SHans de Goede dmi_get_date(DMI_BIOS_DATE, &year, &month, &date); 1310240630e6SHans de Goede snprintf(buf, sizeof(buf), "%04d%02d%02d", year, month, date); 1311240630e6SHans de Goede 1312240630e6SHans de Goede return strcmp(buf, dmi->driver_data) < 0; 1313240630e6SHans de Goede } 1314240630e6SHans de Goede 13155594639aSTejun Heo static bool ahci_broken_online(struct pci_dev *pdev) 13165594639aSTejun Heo { 13175594639aSTejun Heo #define ENCODE_BUSDEVFN(bus, slot, func) \ 13185594639aSTejun Heo (void *)(unsigned long)(((bus) << 8) | PCI_DEVFN((slot), (func))) 13195594639aSTejun Heo static const struct dmi_system_id sysids[] = { 13205594639aSTejun Heo /* 13215594639aSTejun Heo * There are several gigabyte boards which use 13225594639aSTejun Heo * SIMG5723s configured as hardware RAID. Certain 13235594639aSTejun Heo * 5723 firmware revisions shipped there keep the link 13245594639aSTejun Heo * online but fail to answer properly to SRST or 13255594639aSTejun Heo * IDENTIFY when no device is attached downstream 13265594639aSTejun Heo * causing libata to retry quite a few times leading 13275594639aSTejun Heo * to excessive detection delay. 13285594639aSTejun Heo * 13295594639aSTejun Heo * As these firmwares respond to the second reset try 13305594639aSTejun Heo * with invalid device signature, considering unknown 13315594639aSTejun Heo * sig as offline works around the problem acceptably. 13325594639aSTejun Heo */ 13335594639aSTejun Heo { 13345594639aSTejun Heo .ident = "EP45-DQ6", 13355594639aSTejun Heo .matches = { 13365594639aSTejun Heo DMI_MATCH(DMI_BOARD_VENDOR, 13375594639aSTejun Heo "Gigabyte Technology Co., Ltd."), 13385594639aSTejun Heo DMI_MATCH(DMI_BOARD_NAME, "EP45-DQ6"), 13395594639aSTejun Heo }, 13405594639aSTejun Heo .driver_data = ENCODE_BUSDEVFN(0x0a, 0x00, 0), 13415594639aSTejun Heo }, 13425594639aSTejun Heo { 13435594639aSTejun Heo .ident = "EP45-DS5", 13445594639aSTejun Heo .matches = { 13455594639aSTejun Heo DMI_MATCH(DMI_BOARD_VENDOR, 13465594639aSTejun Heo "Gigabyte Technology Co., Ltd."), 13475594639aSTejun Heo DMI_MATCH(DMI_BOARD_NAME, "EP45-DS5"), 13485594639aSTejun Heo }, 13495594639aSTejun Heo .driver_data = ENCODE_BUSDEVFN(0x03, 0x00, 0), 13505594639aSTejun Heo }, 13515594639aSTejun Heo { } /* terminate list */ 13525594639aSTejun Heo }; 13535594639aSTejun Heo #undef ENCODE_BUSDEVFN 13545594639aSTejun Heo const struct dmi_system_id *dmi = dmi_first_match(sysids); 13555594639aSTejun Heo unsigned int val; 13565594639aSTejun Heo 13575594639aSTejun Heo if (!dmi) 13585594639aSTejun Heo return false; 13595594639aSTejun Heo 13605594639aSTejun Heo val = (unsigned long)dmi->driver_data; 13615594639aSTejun Heo 13625594639aSTejun Heo return pdev->bus->number == (val >> 8) && pdev->devfn == (val & 0xff); 13635594639aSTejun Heo } 13645594639aSTejun Heo 13650cf4a7d6SJacob Pan static bool ahci_broken_devslp(struct pci_dev *pdev) 13660cf4a7d6SJacob Pan { 13670cf4a7d6SJacob Pan /* device with broken DEVSLP but still showing SDS capability */ 13680cf4a7d6SJacob Pan static const struct pci_device_id ids[] = { 13690cf4a7d6SJacob Pan { PCI_VDEVICE(INTEL, 0x0f23)}, /* Valleyview SoC */ 13700cf4a7d6SJacob Pan {} 13710cf4a7d6SJacob Pan }; 13720cf4a7d6SJacob Pan 13730cf4a7d6SJacob Pan return pci_match_id(ids, pdev); 13740cf4a7d6SJacob Pan } 13750cf4a7d6SJacob Pan 13768e513217SMarkus Trippelsdorf #ifdef CONFIG_ATA_ACPI 1377f80ae7e4STejun Heo static void ahci_gtf_filter_workaround(struct ata_host *host) 1378f80ae7e4STejun Heo { 1379f80ae7e4STejun Heo static const struct dmi_system_id sysids[] = { 1380f80ae7e4STejun Heo /* 1381f80ae7e4STejun Heo * Aspire 3810T issues a bunch of SATA enable commands 1382f80ae7e4STejun Heo * via _GTF including an invalid one and one which is 1383f80ae7e4STejun Heo * rejected by the device. Among the successful ones 1384f80ae7e4STejun Heo * is FPDMA non-zero offset enable which when enabled 1385f80ae7e4STejun Heo * only on the drive side leads to NCQ command 1386f80ae7e4STejun Heo * failures. Filter it out. 1387f80ae7e4STejun Heo */ 1388f80ae7e4STejun Heo { 1389f80ae7e4STejun Heo .ident = "Aspire 3810T", 1390f80ae7e4STejun Heo .matches = { 1391f80ae7e4STejun Heo DMI_MATCH(DMI_SYS_VENDOR, "Acer"), 1392f80ae7e4STejun Heo DMI_MATCH(DMI_PRODUCT_NAME, "Aspire 3810T"), 1393f80ae7e4STejun Heo }, 1394f80ae7e4STejun Heo .driver_data = (void *)ATA_ACPI_FILTER_FPDMA_OFFSET, 1395f80ae7e4STejun Heo }, 1396f80ae7e4STejun Heo { } 1397f80ae7e4STejun Heo }; 1398f80ae7e4STejun Heo const struct dmi_system_id *dmi = dmi_first_match(sysids); 1399f80ae7e4STejun Heo unsigned int filter; 1400f80ae7e4STejun Heo int i; 1401f80ae7e4STejun Heo 1402f80ae7e4STejun Heo if (!dmi) 1403f80ae7e4STejun Heo return; 1404f80ae7e4STejun Heo 1405f80ae7e4STejun Heo filter = (unsigned long)dmi->driver_data; 1406a44fec1fSJoe Perches dev_info(host->dev, "applying extra ACPI _GTF filter 0x%x for %s\n", 1407f80ae7e4STejun Heo filter, dmi->ident); 1408f80ae7e4STejun Heo 1409f80ae7e4STejun Heo for (i = 0; i < host->n_ports; i++) { 1410f80ae7e4STejun Heo struct ata_port *ap = host->ports[i]; 1411f80ae7e4STejun Heo struct ata_link *link; 1412f80ae7e4STejun Heo struct ata_device *dev; 1413f80ae7e4STejun Heo 1414f80ae7e4STejun Heo ata_for_each_link(link, ap, EDGE) 1415f80ae7e4STejun Heo ata_for_each_dev(dev, link, ALL) 1416f80ae7e4STejun Heo dev->gtf_filter |= filter; 1417f80ae7e4STejun Heo } 1418f80ae7e4STejun Heo } 14198e513217SMarkus Trippelsdorf #else 14208e513217SMarkus Trippelsdorf static inline void ahci_gtf_filter_workaround(struct ata_host *host) 14218e513217SMarkus Trippelsdorf {} 14228e513217SMarkus Trippelsdorf #endif 1423f80ae7e4STejun Heo 14248bfd1743SSui Chen /* 14258bfd1743SSui Chen * On the Acer Aspire Switch Alpha 12, sometimes all SATA ports are detected 14268bfd1743SSui Chen * as DUMMY, or detected but eventually get a "link down" and never get up 14278bfd1743SSui Chen * again. When this happens, CAP.NP may hold a value of 0x00 or 0x01, and the 14288bfd1743SSui Chen * port_map may hold a value of 0x00. 14298bfd1743SSui Chen * 14308bfd1743SSui Chen * Overriding CAP.NP to 0x02 and the port_map to 0x7 will reveal all 3 ports 14318bfd1743SSui Chen * and can significantly reduce the occurrence of the problem. 14328bfd1743SSui Chen * 14338bfd1743SSui Chen * https://bugzilla.kernel.org/show_bug.cgi?id=189471 14348bfd1743SSui Chen */ 14358bfd1743SSui Chen static void acer_sa5_271_workaround(struct ahci_host_priv *hpriv, 14368bfd1743SSui Chen struct pci_dev *pdev) 14378bfd1743SSui Chen { 14388bfd1743SSui Chen static const struct dmi_system_id sysids[] = { 14398bfd1743SSui Chen { 14408bfd1743SSui Chen .ident = "Acer Switch Alpha 12", 14418bfd1743SSui Chen .matches = { 14428bfd1743SSui Chen DMI_MATCH(DMI_SYS_VENDOR, "Acer"), 14438bfd1743SSui Chen DMI_MATCH(DMI_PRODUCT_NAME, "Switch SA5-271") 14448bfd1743SSui Chen }, 14458bfd1743SSui Chen }, 14468bfd1743SSui Chen { } 14478bfd1743SSui Chen }; 14488bfd1743SSui Chen 14498bfd1743SSui Chen if (dmi_check_system(sysids)) { 14508bfd1743SSui Chen dev_info(&pdev->dev, "enabling Acer Switch Alpha 12 workaround\n"); 14518bfd1743SSui Chen if ((hpriv->saved_cap & 0xC734FF00) == 0xC734FF00) { 14528bfd1743SSui Chen hpriv->port_map = 0x7; 14538bfd1743SSui Chen hpriv->cap = 0xC734FF02; 14548bfd1743SSui Chen } 14558bfd1743SSui Chen } 14568bfd1743SSui Chen } 14578bfd1743SSui Chen 1458d243bed3STirumalesh Chalamarla #ifdef CONFIG_ARM64 1459d243bed3STirumalesh Chalamarla /* 1460d243bed3STirumalesh Chalamarla * Due to ERRATA#22536, ThunderX needs to handle HOST_IRQ_STAT differently. 1461d243bed3STirumalesh Chalamarla * Workaround is to make sure all pending IRQs are served before leaving 1462d243bed3STirumalesh Chalamarla * handler. 1463d243bed3STirumalesh Chalamarla */ 1464d243bed3STirumalesh Chalamarla static irqreturn_t ahci_thunderx_irq_handler(int irq, void *dev_instance) 1465d243bed3STirumalesh Chalamarla { 1466d243bed3STirumalesh Chalamarla struct ata_host *host = dev_instance; 1467d243bed3STirumalesh Chalamarla struct ahci_host_priv *hpriv; 1468d243bed3STirumalesh Chalamarla unsigned int rc = 0; 1469d243bed3STirumalesh Chalamarla void __iomem *mmio; 1470d243bed3STirumalesh Chalamarla u32 irq_stat, irq_masked; 1471d243bed3STirumalesh Chalamarla unsigned int handled = 1; 1472d243bed3STirumalesh Chalamarla 1473d243bed3STirumalesh Chalamarla VPRINTK("ENTER\n"); 1474d243bed3STirumalesh Chalamarla hpriv = host->private_data; 1475d243bed3STirumalesh Chalamarla mmio = hpriv->mmio; 1476d243bed3STirumalesh Chalamarla irq_stat = readl(mmio + HOST_IRQ_STAT); 1477d243bed3STirumalesh Chalamarla if (!irq_stat) 1478d243bed3STirumalesh Chalamarla return IRQ_NONE; 1479d243bed3STirumalesh Chalamarla 1480d243bed3STirumalesh Chalamarla do { 1481d243bed3STirumalesh Chalamarla irq_masked = irq_stat & hpriv->port_map; 1482d243bed3STirumalesh Chalamarla spin_lock(&host->lock); 1483d243bed3STirumalesh Chalamarla rc = ahci_handle_port_intr(host, irq_masked); 1484d243bed3STirumalesh Chalamarla if (!rc) 1485d243bed3STirumalesh Chalamarla handled = 0; 1486d243bed3STirumalesh Chalamarla writel(irq_stat, mmio + HOST_IRQ_STAT); 1487d243bed3STirumalesh Chalamarla irq_stat = readl(mmio + HOST_IRQ_STAT); 1488d243bed3STirumalesh Chalamarla spin_unlock(&host->lock); 1489d243bed3STirumalesh Chalamarla } while (irq_stat); 1490d243bed3STirumalesh Chalamarla VPRINTK("EXIT\n"); 1491d243bed3STirumalesh Chalamarla 1492d243bed3STirumalesh Chalamarla return IRQ_RETVAL(handled); 1493d243bed3STirumalesh Chalamarla } 1494d243bed3STirumalesh Chalamarla #endif 1495d243bed3STirumalesh Chalamarla 1496aecec8b6SChristoph Hellwig static void ahci_remap_check(struct pci_dev *pdev, int bar, 1497aecec8b6SChristoph Hellwig struct ahci_host_priv *hpriv) 1498aecec8b6SChristoph Hellwig { 1499894fba7fSKai-Heng Feng int i; 1500aecec8b6SChristoph Hellwig u32 cap; 1501aecec8b6SChristoph Hellwig 1502aecec8b6SChristoph Hellwig /* 1503aecec8b6SChristoph Hellwig * Check if this device might have remapped nvme devices. 1504aecec8b6SChristoph Hellwig */ 1505aecec8b6SChristoph Hellwig if (pdev->vendor != PCI_VENDOR_ID_INTEL || 1506aecec8b6SChristoph Hellwig pci_resource_len(pdev, bar) < SZ_512K || 1507aecec8b6SChristoph Hellwig bar != AHCI_PCI_BAR_STANDARD || 1508aecec8b6SChristoph Hellwig !(readl(hpriv->mmio + AHCI_VSCAP) & 1)) 1509aecec8b6SChristoph Hellwig return; 1510aecec8b6SChristoph Hellwig 1511aecec8b6SChristoph Hellwig cap = readq(hpriv->mmio + AHCI_REMAP_CAP); 1512aecec8b6SChristoph Hellwig for (i = 0; i < AHCI_MAX_REMAP; i++) { 1513aecec8b6SChristoph Hellwig if ((cap & (1 << i)) == 0) 1514aecec8b6SChristoph Hellwig continue; 1515aecec8b6SChristoph Hellwig if (readl(hpriv->mmio + ahci_remap_dcc(i)) 1516aecec8b6SChristoph Hellwig != PCI_CLASS_STORAGE_EXPRESS) 1517aecec8b6SChristoph Hellwig continue; 1518aecec8b6SChristoph Hellwig 1519aecec8b6SChristoph Hellwig /* We've found a remapped device */ 1520894fba7fSKai-Heng Feng hpriv->remapped_nvme++; 1521aecec8b6SChristoph Hellwig } 1522aecec8b6SChristoph Hellwig 1523894fba7fSKai-Heng Feng if (!hpriv->remapped_nvme) 1524aecec8b6SChristoph Hellwig return; 1525aecec8b6SChristoph Hellwig 1526894fba7fSKai-Heng Feng dev_warn(&pdev->dev, "Found %u remapped NVMe devices.\n", 1527894fba7fSKai-Heng Feng hpriv->remapped_nvme); 1528f723fa4eSChristoph Hellwig dev_warn(&pdev->dev, 1529f723fa4eSChristoph Hellwig "Switch your BIOS from RAID to AHCI mode to use them.\n"); 1530f723fa4eSChristoph Hellwig 1531f723fa4eSChristoph Hellwig /* 1532f723fa4eSChristoph Hellwig * Don't rely on the msi-x capability in the remap case, 1533f723fa4eSChristoph Hellwig * share the legacy interrupt across ahci and remapped devices. 1534f723fa4eSChristoph Hellwig */ 1535f723fa4eSChristoph Hellwig hpriv->flags |= AHCI_HFLAG_NO_MSI; 1536aecec8b6SChristoph Hellwig } 1537aecec8b6SChristoph Hellwig 15380b9e2988SChristoph Hellwig static int ahci_get_irq_vector(struct ata_host *host, int port) 1539ee2aad42SRobert Richter { 15400b9e2988SChristoph Hellwig return pci_irq_vector(to_pci_dev(host->dev), port); 1541ee2aad42SRobert Richter } 1542ee2aad42SRobert Richter 1543a1c82311SRobert Richter static int ahci_init_msi(struct pci_dev *pdev, unsigned int n_ports, 15447b92b4f6SAlexander Gordeev struct ahci_host_priv *hpriv) 15455ca72c4fSAlexander Gordeev { 15460b9e2988SChristoph Hellwig int nvec; 15475ca72c4fSAlexander Gordeev 15487b92b4f6SAlexander Gordeev if (hpriv->flags & AHCI_HFLAG_NO_MSI) 1549a1c82311SRobert Richter return -ENODEV; 15507b92b4f6SAlexander Gordeev 15515ca72c4fSAlexander Gordeev /* 15527b92b4f6SAlexander Gordeev * If number of MSIs is less than number of ports then Sharing Last 15537b92b4f6SAlexander Gordeev * Message mode could be enforced. In this case assume that advantage 15547b92b4f6SAlexander Gordeev * of multipe MSIs is negated and use single MSI mode instead. 15555ca72c4fSAlexander Gordeev */ 155617a51f12SChristoph Hellwig if (n_ports > 1) { 15570b9e2988SChristoph Hellwig nvec = pci_alloc_irq_vectors(pdev, n_ports, INT_MAX, 15580b9e2988SChristoph Hellwig PCI_IRQ_MSIX | PCI_IRQ_MSI); 15590b9e2988SChristoph Hellwig if (nvec > 0) { 15600b9e2988SChristoph Hellwig if (!(readl(hpriv->mmio + HOST_CTL) & HOST_MRSM)) { 15610b9e2988SChristoph Hellwig hpriv->get_irq_vector = ahci_get_irq_vector; 1562c3ebd6a9SAlexander Gordeev hpriv->flags |= AHCI_HFLAG_MULTI_MSI; 156321bfd1aaSRobert Richter return nvec; 1564a1c82311SRobert Richter } 1565a1c82311SRobert Richter 1566d684a90dSDan Williams /* 156717a51f12SChristoph Hellwig * Fallback to single MSI mode if the controller 156817a51f12SChristoph Hellwig * enforced MRSM mode. 1569d684a90dSDan Williams */ 157017a51f12SChristoph Hellwig printk(KERN_INFO 157117a51f12SChristoph Hellwig "ahci: MRSM is on, fallback to single MSI\n"); 15720b9e2988SChristoph Hellwig pci_free_irq_vectors(pdev); 15730b9e2988SChristoph Hellwig } 1574a478b097SChristoph Hellwig } 1575d684a90dSDan Williams 15760b9e2988SChristoph Hellwig /* 15770b9e2988SChristoph Hellwig * If the host is not capable of supporting per-port vectors, fall 15780b9e2988SChristoph Hellwig * back to single MSI before finally attempting single MSI-X. 15790b9e2988SChristoph Hellwig */ 15800b9e2988SChristoph Hellwig nvec = pci_alloc_irq_vectors(pdev, 1, 1, PCI_IRQ_MSI); 15810b9e2988SChristoph Hellwig if (nvec == 1) 1582a1c82311SRobert Richter return nvec; 15830b9e2988SChristoph Hellwig return pci_alloc_irq_vectors(pdev, 1, 1, PCI_IRQ_MSIX); 15845ca72c4fSAlexander Gordeev } 15855ca72c4fSAlexander Gordeev 1586b1a9585cSSrinivas Pandruvada static void ahci_update_initial_lpm_policy(struct ata_port *ap, 1587b1a9585cSSrinivas Pandruvada struct ahci_host_priv *hpriv) 1588b1a9585cSSrinivas Pandruvada { 1589b1a9585cSSrinivas Pandruvada int policy = CONFIG_SATA_MOBILE_LPM_POLICY; 1590b1a9585cSSrinivas Pandruvada 1591b1a9585cSSrinivas Pandruvada 1592b1a9585cSSrinivas Pandruvada /* Ignore processing for non mobile platforms */ 1593b1a9585cSSrinivas Pandruvada if (!(hpriv->flags & AHCI_HFLAG_IS_MOBILE)) 1594b1a9585cSSrinivas Pandruvada return; 1595b1a9585cSSrinivas Pandruvada 1596b1a9585cSSrinivas Pandruvada /* user modified policy via module param */ 1597b1a9585cSSrinivas Pandruvada if (mobile_lpm_policy != -1) { 1598b1a9585cSSrinivas Pandruvada policy = mobile_lpm_policy; 1599b1a9585cSSrinivas Pandruvada goto update_policy; 1600b1a9585cSSrinivas Pandruvada } 1601b1a9585cSSrinivas Pandruvada 1602b1a9585cSSrinivas Pandruvada #ifdef CONFIG_ACPI 1603b1a9585cSSrinivas Pandruvada if (policy > ATA_LPM_MED_POWER && 1604b1a9585cSSrinivas Pandruvada (acpi_gbl_FADT.flags & ACPI_FADT_LOW_POWER_S0)) { 1605b1a9585cSSrinivas Pandruvada if (hpriv->cap & HOST_CAP_PART) 1606b1a9585cSSrinivas Pandruvada policy = ATA_LPM_MIN_POWER_WITH_PARTIAL; 1607b1a9585cSSrinivas Pandruvada else if (hpriv->cap & HOST_CAP_SSC) 1608b1a9585cSSrinivas Pandruvada policy = ATA_LPM_MIN_POWER; 1609b1a9585cSSrinivas Pandruvada } 1610b1a9585cSSrinivas Pandruvada #endif 1611b1a9585cSSrinivas Pandruvada 1612b1a9585cSSrinivas Pandruvada update_policy: 1613b1a9585cSSrinivas Pandruvada if (policy >= ATA_LPM_UNKNOWN && policy <= ATA_LPM_MIN_POWER) 1614b1a9585cSSrinivas Pandruvada ap->target_lpm_policy = policy; 1615b1a9585cSSrinivas Pandruvada } 1616b1a9585cSSrinivas Pandruvada 1617c312ef17SDan Williams static void ahci_intel_pcs_quirk(struct pci_dev *pdev, struct ahci_host_priv *hpriv) 1618c312ef17SDan Williams { 1619c312ef17SDan Williams const struct pci_device_id *id = pci_match_id(ahci_pci_tbl, pdev); 1620c312ef17SDan Williams u16 tmp16; 1621c312ef17SDan Williams 1622c312ef17SDan Williams /* 1623c312ef17SDan Williams * Only apply the 6-port PCS quirk for known legacy platforms. 1624c312ef17SDan Williams */ 1625c312ef17SDan Williams if (!id || id->vendor != PCI_VENDOR_ID_INTEL) 1626c312ef17SDan Williams return; 162709d6ac8dSDan Williams 162809d6ac8dSDan Williams /* Skip applying the quirk on Denverton and beyond */ 162909d6ac8dSDan Williams if (((enum board_ids) id->driver_data) >= board_ahci_pcs7) 1630c312ef17SDan Williams return; 1631c312ef17SDan Williams 1632c312ef17SDan Williams /* 1633c312ef17SDan Williams * port_map is determined from PORTS_IMPL PCI register which is 1634c312ef17SDan Williams * implemented as write or write-once register. If the register 1635c312ef17SDan Williams * isn't programmed, ahci automatically generates it from number 1636c312ef17SDan Williams * of ports, which is good enough for PCS programming. It is 1637c312ef17SDan Williams * otherwise expected that platform firmware enables the ports 1638c312ef17SDan Williams * before the OS boots. 1639c312ef17SDan Williams */ 1640c312ef17SDan Williams pci_read_config_word(pdev, PCS_6, &tmp16); 1641c312ef17SDan Williams if ((tmp16 & hpriv->port_map) != hpriv->port_map) { 1642c312ef17SDan Williams tmp16 |= hpriv->port_map; 1643c312ef17SDan Williams pci_write_config_word(pdev, PCS_6, tmp16); 1644c312ef17SDan Williams } 1645c312ef17SDan Williams } 1646c312ef17SDan Williams 1647894fba7fSKai-Heng Feng static ssize_t remapped_nvme_show(struct device *dev, 1648894fba7fSKai-Heng Feng struct device_attribute *attr, 1649894fba7fSKai-Heng Feng char *buf) 1650894fba7fSKai-Heng Feng { 1651894fba7fSKai-Heng Feng struct ata_host *host = dev_get_drvdata(dev); 1652894fba7fSKai-Heng Feng struct ahci_host_priv *hpriv = host->private_data; 1653894fba7fSKai-Heng Feng 1654894fba7fSKai-Heng Feng return sprintf(buf, "%u\n", hpriv->remapped_nvme); 1655894fba7fSKai-Heng Feng } 1656894fba7fSKai-Heng Feng 1657894fba7fSKai-Heng Feng static DEVICE_ATTR_RO(remapped_nvme); 1658894fba7fSKai-Heng Feng 1659c6fd2807SJeff Garzik static int ahci_init_one(struct pci_dev *pdev, const struct pci_device_id *ent) 1660c6fd2807SJeff Garzik { 1661e297d99eSTejun Heo unsigned int board_id = ent->driver_data; 1662e297d99eSTejun Heo struct ata_port_info pi = ahci_port_info[board_id]; 16634447d351STejun Heo const struct ata_port_info *ppi[] = { &pi, NULL }; 166424dc5f33STejun Heo struct device *dev = &pdev->dev; 1665c6fd2807SJeff Garzik struct ahci_host_priv *hpriv; 16664447d351STejun Heo struct ata_host *host; 1667c3ebd6a9SAlexander Gordeev int n_ports, i, rc; 1668318893e1SAlessandro Rubini int ahci_pci_bar = AHCI_PCI_BAR_STANDARD; 1669c6fd2807SJeff Garzik 1670c6fd2807SJeff Garzik VPRINTK("ENTER\n"); 1671c6fd2807SJeff Garzik 1672b429dd59SJustin P. Mattock WARN_ON((int)ATA_MAX_QUEUE > AHCI_MAX_CMDS); 1673c6fd2807SJeff Garzik 167406296a1eSJoe Perches ata_print_version_once(&pdev->dev, DRV_VERSION); 1675c6fd2807SJeff Garzik 16765b66c829SAlan Cox /* The AHCI driver can only drive the SATA ports, the PATA driver 16775b66c829SAlan Cox can drive them all so if both drivers are selected make sure 16785b66c829SAlan Cox AHCI stays out of the way */ 16795b66c829SAlan Cox if (pdev->vendor == PCI_VENDOR_ID_MARVELL && !marvell_enable) 16805b66c829SAlan Cox return -ENODEV; 16815b66c829SAlan Cox 1682cb85696dSJames Laird /* Apple BIOS on MCP89 prevents us using AHCI */ 1683cb85696dSJames Laird if (is_mcp89_apple(pdev)) 1684cb85696dSJames Laird ahci_mcp89_apple_enable(pdev); 1685c6353b45STejun Heo 16867a02267eSMark Nelson /* Promise's PDC42819 is a SAS/SATA controller that has an AHCI mode. 16877a02267eSMark Nelson * At the moment, we can only use the AHCI mode. Let the users know 16887a02267eSMark Nelson * that for SAS drives they're out of luck. 16897a02267eSMark Nelson */ 16907a02267eSMark Nelson if (pdev->vendor == PCI_VENDOR_ID_PROMISE) 1691a44fec1fSJoe Perches dev_info(&pdev->dev, 1692a44fec1fSJoe Perches "PDC42819 can only drive SATA devices with this driver\n"); 16937a02267eSMark Nelson 1694b7ae128dSRobert Richter /* Some devices use non-standard BARs */ 1695318893e1SAlessandro Rubini if (pdev->vendor == PCI_VENDOR_ID_STMICRO && pdev->device == 0xCC06) 1696318893e1SAlessandro Rubini ahci_pci_bar = AHCI_PCI_BAR_STA2X11; 16977f9c9f8eSHugh Daschbach else if (pdev->vendor == 0x1c44 && pdev->device == 0x8000) 16987f9c9f8eSHugh Daschbach ahci_pci_bar = AHCI_PCI_BAR_ENMOTUS; 1699b1314e3fSRadha Mohan Chintakuntla else if (pdev->vendor == PCI_VENDOR_ID_CAVIUM) { 1700b1314e3fSRadha Mohan Chintakuntla if (pdev->device == 0xa01c) 1701b7ae128dSRobert Richter ahci_pci_bar = AHCI_PCI_BAR_CAVIUM; 1702b1314e3fSRadha Mohan Chintakuntla if (pdev->device == 0xa084) 1703b1314e3fSRadha Mohan Chintakuntla ahci_pci_bar = AHCI_PCI_BAR_CAVIUM_GEN5; 1704e49bd683STiezhu Yang } else if (pdev->vendor == PCI_VENDOR_ID_LOONGSON) { 1705e49bd683STiezhu Yang if (pdev->device == 0x7a08) 1706e49bd683STiezhu Yang ahci_pci_bar = AHCI_PCI_BAR_LOONGSON; 1707b1314e3fSRadha Mohan Chintakuntla } 1708318893e1SAlessandro Rubini 17094447d351STejun Heo /* acquire resources */ 171024dc5f33STejun Heo rc = pcim_enable_device(pdev); 1711c6fd2807SJeff Garzik if (rc) 1712c6fd2807SJeff Garzik return rc; 1713c6fd2807SJeff Garzik 1714c4f7792cSTejun Heo if (pdev->vendor == PCI_VENDOR_ID_INTEL && 1715c4f7792cSTejun Heo (pdev->device == 0x2652 || pdev->device == 0x2653)) { 1716c4f7792cSTejun Heo u8 map; 1717c4f7792cSTejun Heo 1718c4f7792cSTejun Heo /* ICH6s share the same PCI ID for both piix and ahci 1719c4f7792cSTejun Heo * modes. Enabling ahci mode while MAP indicates 1720c4f7792cSTejun Heo * combined mode is a bad idea. Yield to ata_piix. 1721c4f7792cSTejun Heo */ 1722c4f7792cSTejun Heo pci_read_config_byte(pdev, ICH_MAP, &map); 1723c4f7792cSTejun Heo if (map & 0x3) { 1724a44fec1fSJoe Perches dev_info(&pdev->dev, 1725a44fec1fSJoe Perches "controller is in combined mode, can't enable AHCI mode\n"); 1726c4f7792cSTejun Heo return -ENODEV; 1727c4f7792cSTejun Heo } 1728c4f7792cSTejun Heo } 1729c4f7792cSTejun Heo 17306fec8871SPaul Bolle /* AHCI controllers often implement SFF compatible interface. 17316fec8871SPaul Bolle * Grab all PCI BARs just in case. 17326fec8871SPaul Bolle */ 17336fec8871SPaul Bolle rc = pcim_iomap_regions_request_all(pdev, 1 << ahci_pci_bar, DRV_NAME); 17346fec8871SPaul Bolle if (rc == -EBUSY) 17356fec8871SPaul Bolle pcim_pin_device(pdev); 17366fec8871SPaul Bolle if (rc) 17376fec8871SPaul Bolle return rc; 17386fec8871SPaul Bolle 173924dc5f33STejun Heo hpriv = devm_kzalloc(dev, sizeof(*hpriv), GFP_KERNEL); 174024dc5f33STejun Heo if (!hpriv) 174124dc5f33STejun Heo return -ENOMEM; 1742417a1a6dSTejun Heo hpriv->flags |= (unsigned long)pi.private_data; 1743417a1a6dSTejun Heo 1744e297d99eSTejun Heo /* MCP65 revision A1 and A2 can't do MSI */ 1745e297d99eSTejun Heo if (board_id == board_ahci_mcp65 && 1746e297d99eSTejun Heo (pdev->revision == 0xa1 || pdev->revision == 0xa2)) 1747e297d99eSTejun Heo hpriv->flags |= AHCI_HFLAG_NO_MSI; 1748e297d99eSTejun Heo 1749e427fe04SShane Huang /* SB800 does NOT need the workaround to ignore SERR_INTERNAL */ 1750e427fe04SShane Huang if (board_id == board_ahci_sb700 && pdev->revision >= 0x40) 1751e427fe04SShane Huang hpriv->flags &= ~AHCI_HFLAG_IGN_SERR_INTERNAL; 1752e427fe04SShane Huang 17532fcad9d2STejun Heo /* only some SB600s can do 64bit DMA */ 17542fcad9d2STejun Heo if (ahci_sb600_enable_64bit(pdev)) 17552fcad9d2STejun Heo hpriv->flags &= ~AHCI_HFLAG_32BIT_ONLY; 175658a09b38SShane Huang 1757318893e1SAlessandro Rubini hpriv->mmio = pcim_iomap_table(pdev)[ahci_pci_bar]; 1758d8993349SAnton Vorontsov 1759aecec8b6SChristoph Hellwig /* detect remapped nvme devices */ 1760aecec8b6SChristoph Hellwig ahci_remap_check(pdev, ahci_pci_bar, hpriv); 1761aecec8b6SChristoph Hellwig 1762894fba7fSKai-Heng Feng sysfs_add_file_to_group(&pdev->dev.kobj, 1763894fba7fSKai-Heng Feng &dev_attr_remapped_nvme.attr, 1764894fba7fSKai-Heng Feng NULL); 1765894fba7fSKai-Heng Feng 17660cf4a7d6SJacob Pan /* must set flag prior to save config in order to take effect */ 17670cf4a7d6SJacob Pan if (ahci_broken_devslp(pdev)) 17680cf4a7d6SJacob Pan hpriv->flags |= AHCI_HFLAG_NO_DEVSLP; 17690cf4a7d6SJacob Pan 1770d243bed3STirumalesh Chalamarla #ifdef CONFIG_ARM64 1771d243bed3STirumalesh Chalamarla if (pdev->vendor == 0x177d && pdev->device == 0xa01c) 1772d243bed3STirumalesh Chalamarla hpriv->irq_handler = ahci_thunderx_irq_handler; 1773d243bed3STirumalesh Chalamarla #endif 1774d243bed3STirumalesh Chalamarla 17754447d351STejun Heo /* save initial config */ 1776394d6e53SAnton Vorontsov ahci_pci_save_initial_config(pdev, hpriv); 1777c6fd2807SJeff Garzik 1778c312ef17SDan Williams /* 1779c312ef17SDan Williams * If platform firmware failed to enable ports, try to enable 1780c312ef17SDan Williams * them here. 1781c312ef17SDan Williams */ 1782c312ef17SDan Williams ahci_intel_pcs_quirk(pdev, hpriv); 1783c312ef17SDan Williams 17844447d351STejun Heo /* prepare host */ 1785453d3131SRobert Hancock if (hpriv->cap & HOST_CAP_NCQ) { 1786453d3131SRobert Hancock pi.flags |= ATA_FLAG_NCQ; 178783f2b963STejun Heo /* 178883f2b963STejun Heo * Auto-activate optimization is supposed to be 178983f2b963STejun Heo * supported on all AHCI controllers indicating NCQ 179083f2b963STejun Heo * capability, but it seems to be broken on some 179183f2b963STejun Heo * chipsets including NVIDIAs. 179283f2b963STejun Heo */ 179383f2b963STejun Heo if (!(hpriv->flags & AHCI_HFLAG_NO_FPDMA_AA)) 1794453d3131SRobert Hancock pi.flags |= ATA_FLAG_FPDMA_AA; 179540fb59e7SMarc Carino 179640fb59e7SMarc Carino /* 179740fb59e7SMarc Carino * All AHCI controllers should be forward-compatible 179840fb59e7SMarc Carino * with the new auxiliary field. This code should be 179940fb59e7SMarc Carino * conditionalized if any buggy AHCI controllers are 180040fb59e7SMarc Carino * encountered. 180140fb59e7SMarc Carino */ 180240fb59e7SMarc Carino pi.flags |= ATA_FLAG_FPDMA_AUX; 1803453d3131SRobert Hancock } 18044447d351STejun Heo 18057d50b60bSTejun Heo if (hpriv->cap & HOST_CAP_PMP) 18067d50b60bSTejun Heo pi.flags |= ATA_FLAG_PMP; 18077d50b60bSTejun Heo 18080cbb0e77SAnton Vorontsov ahci_set_em_messages(hpriv, &pi); 180918f7ba4cSKristen Carlson Accardi 18101fd68434SRafael J. Wysocki if (ahci_broken_system_poweroff(pdev)) { 18111fd68434SRafael J. Wysocki pi.flags |= ATA_FLAG_NO_POWEROFF_SPINDOWN; 18121fd68434SRafael J. Wysocki dev_info(&pdev->dev, 18131fd68434SRafael J. Wysocki "quirky BIOS, skipping spindown on poweroff\n"); 18141fd68434SRafael J. Wysocki } 18151fd68434SRafael J. Wysocki 1816240630e6SHans de Goede if (ahci_broken_lpm(pdev)) { 1817240630e6SHans de Goede pi.flags |= ATA_FLAG_NO_LPM; 1818240630e6SHans de Goede dev_warn(&pdev->dev, 1819240630e6SHans de Goede "BIOS update required for Link Power Management support\n"); 1820240630e6SHans de Goede } 1821240630e6SHans de Goede 18229b10ae86STejun Heo if (ahci_broken_suspend(pdev)) { 18239b10ae86STejun Heo hpriv->flags |= AHCI_HFLAG_NO_SUSPEND; 1824a44fec1fSJoe Perches dev_warn(&pdev->dev, 18259b10ae86STejun Heo "BIOS update required for suspend/resume\n"); 18269b10ae86STejun Heo } 18279b10ae86STejun Heo 18285594639aSTejun Heo if (ahci_broken_online(pdev)) { 18295594639aSTejun Heo hpriv->flags |= AHCI_HFLAG_SRST_TOUT_IS_OFFLINE; 18305594639aSTejun Heo dev_info(&pdev->dev, 18315594639aSTejun Heo "online status unreliable, applying workaround\n"); 18325594639aSTejun Heo } 18335594639aSTejun Heo 18348bfd1743SSui Chen 18358bfd1743SSui Chen /* Acer SA5-271 workaround modifies private_data */ 18368bfd1743SSui Chen acer_sa5_271_workaround(hpriv, pdev); 18378bfd1743SSui Chen 1838837f5f8fSTejun Heo /* CAP.NP sometimes indicate the index of the last enabled 1839837f5f8fSTejun Heo * port, at other times, that of the last possible port, so 1840837f5f8fSTejun Heo * determining the maximum port number requires looking at 1841837f5f8fSTejun Heo * both CAP.NP and port_map. 1842837f5f8fSTejun Heo */ 1843837f5f8fSTejun Heo n_ports = max(ahci_nr_ports(hpriv->cap), fls(hpriv->port_map)); 1844837f5f8fSTejun Heo 1845837f5f8fSTejun Heo host = ata_host_alloc_pinfo(&pdev->dev, ppi, n_ports); 18464447d351STejun Heo if (!host) 18474447d351STejun Heo return -ENOMEM; 18484447d351STejun Heo host->private_data = hpriv; 18490b9e2988SChristoph Hellwig 18500b9e2988SChristoph Hellwig if (ahci_init_msi(pdev, n_ports, hpriv) < 0) { 18510b9e2988SChristoph Hellwig /* legacy intx interrupts */ 18520b9e2988SChristoph Hellwig pci_intx(pdev, 1); 18530b9e2988SChristoph Hellwig } 18540ce57f8aSChristoph Hellwig hpriv->irq = pci_irq_vector(pdev, 0); 185521bfd1aaSRobert Richter 1856f3d7f23fSArjan van de Ven if (!(hpriv->cap & HOST_CAP_SSS) || ahci_ignore_sss) 1857886ad09fSArjan van de Ven host->flags |= ATA_HOST_PARALLEL_SCAN; 1858f3d7f23fSArjan van de Ven else 1859d2782d96SJingoo Han dev_info(&pdev->dev, "SSS flag set, parallel bus scan disabled\n"); 1860886ad09fSArjan van de Ven 186118f7ba4cSKristen Carlson Accardi if (pi.flags & ATA_FLAG_EM) 186218f7ba4cSKristen Carlson Accardi ahci_reset_em(host); 186318f7ba4cSKristen Carlson Accardi 18644447d351STejun Heo for (i = 0; i < host->n_ports; i++) { 18654447d351STejun Heo struct ata_port *ap = host->ports[i]; 18664447d351STejun Heo 1867318893e1SAlessandro Rubini ata_port_pbar_desc(ap, ahci_pci_bar, -1, "abar"); 1868318893e1SAlessandro Rubini ata_port_pbar_desc(ap, ahci_pci_bar, 1869cbcdd875STejun Heo 0x100 + ap->port_no * 0x80, "port"); 1870cbcdd875STejun Heo 187118f7ba4cSKristen Carlson Accardi /* set enclosure management message type */ 187218f7ba4cSKristen Carlson Accardi if (ap->flags & ATA_FLAG_EM) 1873008dbd61SHarry Zhang ap->em_message_type = hpriv->em_msg_type; 187418f7ba4cSKristen Carlson Accardi 1875b1a9585cSSrinivas Pandruvada ahci_update_initial_lpm_policy(ap, hpriv); 187618f7ba4cSKristen Carlson Accardi 1877dab632e8SJeff Garzik /* disabled/not-implemented port */ 1878350756f6STejun Heo if (!(hpriv->port_map & (1 << i))) 1879dab632e8SJeff Garzik ap->ops = &ata_dummy_port_ops; 18804447d351STejun Heo } 1881c6fd2807SJeff Garzik 1882edc93052STejun Heo /* apply workaround for ASUS P5W DH Deluxe mainboard */ 1883edc93052STejun Heo ahci_p5wdh_workaround(host); 1884edc93052STejun Heo 1885f80ae7e4STejun Heo /* apply gtf filter quirk */ 1886f80ae7e4STejun Heo ahci_gtf_filter_workaround(host); 1887f80ae7e4STejun Heo 1888c6fd2807SJeff Garzik /* initialize adapter */ 18894447d351STejun Heo rc = ahci_configure_dma_masks(pdev, hpriv->cap & HOST_CAP_64); 1890c6fd2807SJeff Garzik if (rc) 189124dc5f33STejun Heo return rc; 1892c6fd2807SJeff Garzik 1893c312ef17SDan Williams rc = ahci_reset_controller(host); 18944447d351STejun Heo if (rc) 18954447d351STejun Heo return rc; 1896c6fd2807SJeff Garzik 1897781d6550SAnton Vorontsov ahci_pci_init_controller(host); 1898439fcaecSAnton Vorontsov ahci_pci_print_info(host); 1899c6fd2807SJeff Garzik 19004447d351STejun Heo pci_set_master(pdev); 19015ca72c4fSAlexander Gordeev 190202e53293SMika Westerberg rc = ahci_host_activate(host, &ahci_sht); 190302e53293SMika Westerberg if (rc) 190402e53293SMika Westerberg return rc; 190502e53293SMika Westerberg 190602e53293SMika Westerberg pm_runtime_put_noidle(&pdev->dev); 190702e53293SMika Westerberg return 0; 190802e53293SMika Westerberg } 190902e53293SMika Westerberg 191010a663a1SPrabhakar Kushwaha static void ahci_shutdown_one(struct pci_dev *pdev) 191110a663a1SPrabhakar Kushwaha { 191210a663a1SPrabhakar Kushwaha ata_pci_shutdown_one(pdev); 191310a663a1SPrabhakar Kushwaha } 191410a663a1SPrabhakar Kushwaha 191502e53293SMika Westerberg static void ahci_remove_one(struct pci_dev *pdev) 191602e53293SMika Westerberg { 1917894fba7fSKai-Heng Feng sysfs_remove_file_from_group(&pdev->dev.kobj, 1918894fba7fSKai-Heng Feng &dev_attr_remapped_nvme.attr, 1919894fba7fSKai-Heng Feng NULL); 192002e53293SMika Westerberg pm_runtime_get_noresume(&pdev->dev); 192102e53293SMika Westerberg ata_pci_remove_one(pdev); 1922c6fd2807SJeff Garzik } 1923c6fd2807SJeff Garzik 19242fc75da0SAxel Lin module_pci_driver(ahci_pci_driver); 1925c6fd2807SJeff Garzik 1926c6fd2807SJeff Garzik MODULE_AUTHOR("Jeff Garzik"); 1927c6fd2807SJeff Garzik MODULE_DESCRIPTION("AHCI SATA low-level driver"); 1928c6fd2807SJeff Garzik MODULE_LICENSE("GPL"); 1929c6fd2807SJeff Garzik MODULE_DEVICE_TABLE(pci, ahci_pci_tbl); 1930c6fd2807SJeff Garzik MODULE_VERSION(DRV_VERSION); 1931