1c82ee6d3SThomas Gleixner // SPDX-License-Identifier: GPL-2.0-or-later 2c6fd2807SJeff Garzik /* 3c6fd2807SJeff Garzik * ahci.c - AHCI SATA support 4c6fd2807SJeff Garzik * 58c3d3d4bSTejun Heo * Maintained by: Tejun Heo <tj@kernel.org> 6c6fd2807SJeff Garzik * Please ALWAYS copy linux-ide@vger.kernel.org 7c6fd2807SJeff Garzik * on emails. 8c6fd2807SJeff Garzik * 9c6fd2807SJeff Garzik * Copyright 2004-2005 Red Hat, Inc. 10c6fd2807SJeff Garzik * 11c6fd2807SJeff Garzik * libata documentation is available via 'make {ps|pdf}docs', 1219285f3cSMauro Carvalho Chehab * as Documentation/driver-api/libata.rst 13c6fd2807SJeff Garzik * 14c6fd2807SJeff Garzik * AHCI hardware documentation: 15c6fd2807SJeff Garzik * http://www.intel.com/technology/serialata/pdf/rev1_0.pdf 16c6fd2807SJeff Garzik * http://www.intel.com/technology/serialata/pdf/rev1_1.pdf 17c6fd2807SJeff Garzik */ 18c6fd2807SJeff Garzik 19c6fd2807SJeff Garzik #include <linux/kernel.h> 20c6fd2807SJeff Garzik #include <linux/module.h> 21c6fd2807SJeff Garzik #include <linux/pci.h> 22c6fd2807SJeff Garzik #include <linux/blkdev.h> 23c6fd2807SJeff Garzik #include <linux/delay.h> 24c6fd2807SJeff Garzik #include <linux/interrupt.h> 25c6fd2807SJeff Garzik #include <linux/dma-mapping.h> 26c6fd2807SJeff Garzik #include <linux/device.h> 27edc93052STejun Heo #include <linux/dmi.h> 285a0e3ad6STejun Heo #include <linux/gfp.h> 29ee2aad42SRobert Richter #include <linux/msi.h> 30c6fd2807SJeff Garzik #include <scsi/scsi_host.h> 31c6fd2807SJeff Garzik #include <scsi/scsi_cmnd.h> 32c6fd2807SJeff Garzik #include <linux/libata.h> 33aecec8b6SChristoph Hellwig #include <linux/ahci-remap.h> 34aecec8b6SChristoph Hellwig #include <linux/io-64-nonatomic-lo-hi.h> 35365cfa1eSAnton Vorontsov #include "ahci.h" 36c6fd2807SJeff Garzik 37c6fd2807SJeff Garzik #define DRV_NAME "ahci" 387d50b60bSTejun Heo #define DRV_VERSION "3.0" 39c6fd2807SJeff Garzik 40c6fd2807SJeff Garzik enum { 41318893e1SAlessandro Rubini AHCI_PCI_BAR_STA2X11 = 0, 42b7ae128dSRobert Richter AHCI_PCI_BAR_CAVIUM = 0, 437f9c9f8eSHugh Daschbach AHCI_PCI_BAR_ENMOTUS = 2, 44b1314e3fSRadha Mohan Chintakuntla AHCI_PCI_BAR_CAVIUM_GEN5 = 4, 45318893e1SAlessandro Rubini AHCI_PCI_BAR_STANDARD = 5, 46441577efSTejun Heo }; 47c6fd2807SJeff Garzik 48441577efSTejun Heo enum board_ids { 49441577efSTejun Heo /* board IDs by feature in alphabetical order */ 50441577efSTejun Heo board_ahci, 51441577efSTejun Heo board_ahci_ign_iferr, 52ebb82e3cSHans de Goede board_ahci_mobile, 5366a7cbc3STejun Heo board_ahci_nomsi, 5467809f85SLevente Kurusa board_ahci_noncq, 55441577efSTejun Heo board_ahci_nosntf, 565f173107STejun Heo board_ahci_yes_fbs, 57441577efSTejun Heo 58441577efSTejun Heo /* board IDs for specific chipsets in alphabetical order */ 597d523bdcSHanna Hawa board_ahci_al, 60dbfe8ef5SDan Williams board_ahci_avn, 61441577efSTejun Heo board_ahci_mcp65, 6283f2b963STejun Heo board_ahci_mcp77, 6383f2b963STejun Heo board_ahci_mcp89, 64441577efSTejun Heo board_ahci_mv, 65441577efSTejun Heo board_ahci_sb600, 66441577efSTejun Heo board_ahci_sb700, /* for SB700 and SB800 */ 67441577efSTejun Heo board_ahci_vt8251, 68441577efSTejun Heo 69c312ef17SDan Williams /* 70c312ef17SDan Williams * board IDs for Intel chipsets that support more than 6 ports 71c312ef17SDan Williams * *and* end up needing the PCS quirk. 72c312ef17SDan Williams */ 73c312ef17SDan Williams board_ahci_pcs7, 74c312ef17SDan Williams 75441577efSTejun Heo /* aliases */ 76441577efSTejun Heo board_ahci_mcp_linux = board_ahci_mcp65, 77441577efSTejun Heo board_ahci_mcp67 = board_ahci_mcp65, 78441577efSTejun Heo board_ahci_mcp73 = board_ahci_mcp65, 7983f2b963STejun Heo board_ahci_mcp79 = board_ahci_mcp77, 80c6fd2807SJeff Garzik }; 81c6fd2807SJeff Garzik 82c6fd2807SJeff Garzik static int ahci_init_one(struct pci_dev *pdev, const struct pci_device_id *ent); 8302e53293SMika Westerberg static void ahci_remove_one(struct pci_dev *dev); 84*10a663a1SPrabhakar Kushwaha static void ahci_shutdown_one(struct pci_dev *dev); 85a1efdabaSTejun Heo static int ahci_vt8251_hardreset(struct ata_link *link, unsigned int *class, 86a1efdabaSTejun Heo unsigned long deadline); 87dbfe8ef5SDan Williams static int ahci_avn_hardreset(struct ata_link *link, unsigned int *class, 88dbfe8ef5SDan Williams unsigned long deadline); 89cb85696dSJames Laird static void ahci_mcp89_apple_enable(struct pci_dev *pdev); 90cb85696dSJames Laird static bool is_mcp89_apple(struct pci_dev *pdev); 91a1efdabaSTejun Heo static int ahci_p5wdh_hardreset(struct ata_link *link, unsigned int *class, 92a1efdabaSTejun Heo unsigned long deadline); 9302e53293SMika Westerberg #ifdef CONFIG_PM 9402e53293SMika Westerberg static int ahci_pci_device_runtime_suspend(struct device *dev); 9502e53293SMika Westerberg static int ahci_pci_device_runtime_resume(struct device *dev); 96f1d848f9SMika Westerberg #ifdef CONFIG_PM_SLEEP 97f1d848f9SMika Westerberg static int ahci_pci_device_suspend(struct device *dev); 98f1d848f9SMika Westerberg static int ahci_pci_device_resume(struct device *dev); 99438ac6d5STejun Heo #endif 10002e53293SMika Westerberg #endif /* CONFIG_PM */ 101c6fd2807SJeff Garzik 102fad16e7aSTejun Heo static struct scsi_host_template ahci_sht = { 103fad16e7aSTejun Heo AHCI_SHT("ahci"), 104fad16e7aSTejun Heo }; 105fad16e7aSTejun Heo 106029cfd6bSTejun Heo static struct ata_port_operations ahci_vt8251_ops = { 107029cfd6bSTejun Heo .inherits = &ahci_ops, 108a1efdabaSTejun Heo .hardreset = ahci_vt8251_hardreset, 109ad616ffbSTejun Heo }; 110ad616ffbSTejun Heo 111029cfd6bSTejun Heo static struct ata_port_operations ahci_p5wdh_ops = { 112029cfd6bSTejun Heo .inherits = &ahci_ops, 113a1efdabaSTejun Heo .hardreset = ahci_p5wdh_hardreset, 114edc93052STejun Heo }; 115edc93052STejun Heo 116dbfe8ef5SDan Williams static struct ata_port_operations ahci_avn_ops = { 117dbfe8ef5SDan Williams .inherits = &ahci_ops, 118dbfe8ef5SDan Williams .hardreset = ahci_avn_hardreset, 119dbfe8ef5SDan Williams }; 120dbfe8ef5SDan Williams 121c6fd2807SJeff Garzik static const struct ata_port_info ahci_port_info[] = { 122441577efSTejun Heo /* by features */ 123facb8fa6SJeffrin Jose [board_ahci] = { 1241188c0d8STejun Heo .flags = AHCI_FLAG_COMMON, 12514bdef98SErik Inge Bolsø .pio_mask = ATA_PIO4, 126469248abSJeff Garzik .udma_mask = ATA_UDMA6, 127c6fd2807SJeff Garzik .port_ops = &ahci_ops, 128c6fd2807SJeff Garzik }, 129facb8fa6SJeffrin Jose [board_ahci_ign_iferr] = { 130417a1a6dSTejun Heo AHCI_HFLAGS (AHCI_HFLAG_IGN_IRQ_IF_ERR), 131417a1a6dSTejun Heo .flags = AHCI_FLAG_COMMON, 13214bdef98SErik Inge Bolsø .pio_mask = ATA_PIO4, 133469248abSJeff Garzik .udma_mask = ATA_UDMA6, 13441669553STejun Heo .port_ops = &ahci_ops, 13541669553STejun Heo }, 136ebb82e3cSHans de Goede [board_ahci_mobile] = { 137ebb82e3cSHans de Goede AHCI_HFLAGS (AHCI_HFLAG_IS_MOBILE), 138ebb82e3cSHans de Goede .flags = AHCI_FLAG_COMMON, 139ebb82e3cSHans de Goede .pio_mask = ATA_PIO4, 140ebb82e3cSHans de Goede .udma_mask = ATA_UDMA6, 141ebb82e3cSHans de Goede .port_ops = &ahci_ops, 142ebb82e3cSHans de Goede }, 14366a7cbc3STejun Heo [board_ahci_nomsi] = { 14466a7cbc3STejun Heo AHCI_HFLAGS (AHCI_HFLAG_NO_MSI), 14566a7cbc3STejun Heo .flags = AHCI_FLAG_COMMON, 14666a7cbc3STejun Heo .pio_mask = ATA_PIO4, 14766a7cbc3STejun Heo .udma_mask = ATA_UDMA6, 14866a7cbc3STejun Heo .port_ops = &ahci_ops, 14966a7cbc3STejun Heo }, 15067809f85SLevente Kurusa [board_ahci_noncq] = { 15167809f85SLevente Kurusa AHCI_HFLAGS (AHCI_HFLAG_NO_NCQ), 15267809f85SLevente Kurusa .flags = AHCI_FLAG_COMMON, 15367809f85SLevente Kurusa .pio_mask = ATA_PIO4, 15467809f85SLevente Kurusa .udma_mask = ATA_UDMA6, 15567809f85SLevente Kurusa .port_ops = &ahci_ops, 15667809f85SLevente Kurusa }, 157facb8fa6SJeffrin Jose [board_ahci_nosntf] = { 158441577efSTejun Heo AHCI_HFLAGS (AHCI_HFLAG_NO_SNTF), 159441577efSTejun Heo .flags = AHCI_FLAG_COMMON, 160441577efSTejun Heo .pio_mask = ATA_PIO4, 161441577efSTejun Heo .udma_mask = ATA_UDMA6, 162441577efSTejun Heo .port_ops = &ahci_ops, 163441577efSTejun Heo }, 164facb8fa6SJeffrin Jose [board_ahci_yes_fbs] = { 1655f173107STejun Heo AHCI_HFLAGS (AHCI_HFLAG_YES_FBS), 1665f173107STejun Heo .flags = AHCI_FLAG_COMMON, 1675f173107STejun Heo .pio_mask = ATA_PIO4, 1685f173107STejun Heo .udma_mask = ATA_UDMA6, 1695f173107STejun Heo .port_ops = &ahci_ops, 1705f173107STejun Heo }, 171441577efSTejun Heo /* by chipsets */ 1727d523bdcSHanna Hawa [board_ahci_al] = { 1737d523bdcSHanna Hawa AHCI_HFLAGS (AHCI_HFLAG_NO_PMP | AHCI_HFLAG_NO_MSI), 1747d523bdcSHanna Hawa .flags = AHCI_FLAG_COMMON, 1757d523bdcSHanna Hawa .pio_mask = ATA_PIO4, 1767d523bdcSHanna Hawa .udma_mask = ATA_UDMA6, 1777d523bdcSHanna Hawa .port_ops = &ahci_ops, 1787d523bdcSHanna Hawa }, 179dbfe8ef5SDan Williams [board_ahci_avn] = { 180dbfe8ef5SDan Williams .flags = AHCI_FLAG_COMMON, 181dbfe8ef5SDan Williams .pio_mask = ATA_PIO4, 182dbfe8ef5SDan Williams .udma_mask = ATA_UDMA6, 183dbfe8ef5SDan Williams .port_ops = &ahci_avn_ops, 184dbfe8ef5SDan Williams }, 185facb8fa6SJeffrin Jose [board_ahci_mcp65] = { 18683f2b963STejun Heo AHCI_HFLAGS (AHCI_HFLAG_NO_FPDMA_AA | AHCI_HFLAG_NO_PMP | 18783f2b963STejun Heo AHCI_HFLAG_YES_NCQ), 188ae01b249STejun Heo .flags = AHCI_FLAG_COMMON | ATA_FLAG_NO_DIPM, 18983f2b963STejun Heo .pio_mask = ATA_PIO4, 19083f2b963STejun Heo .udma_mask = ATA_UDMA6, 19183f2b963STejun Heo .port_ops = &ahci_ops, 19283f2b963STejun Heo }, 193facb8fa6SJeffrin Jose [board_ahci_mcp77] = { 19483f2b963STejun Heo AHCI_HFLAGS (AHCI_HFLAG_NO_FPDMA_AA | AHCI_HFLAG_NO_PMP), 19583f2b963STejun Heo .flags = AHCI_FLAG_COMMON, 19683f2b963STejun Heo .pio_mask = ATA_PIO4, 19783f2b963STejun Heo .udma_mask = ATA_UDMA6, 19883f2b963STejun Heo .port_ops = &ahci_ops, 19983f2b963STejun Heo }, 200facb8fa6SJeffrin Jose [board_ahci_mcp89] = { 20183f2b963STejun Heo AHCI_HFLAGS (AHCI_HFLAG_NO_FPDMA_AA), 202441577efSTejun Heo .flags = AHCI_FLAG_COMMON, 203441577efSTejun Heo .pio_mask = ATA_PIO4, 204441577efSTejun Heo .udma_mask = ATA_UDMA6, 205441577efSTejun Heo .port_ops = &ahci_ops, 206441577efSTejun Heo }, 207facb8fa6SJeffrin Jose [board_ahci_mv] = { 208441577efSTejun Heo AHCI_HFLAGS (AHCI_HFLAG_NO_NCQ | AHCI_HFLAG_NO_MSI | 209441577efSTejun Heo AHCI_HFLAG_MV_PATA | AHCI_HFLAG_NO_PMP), 2109cbe056fSSergei Shtylyov .flags = ATA_FLAG_SATA | ATA_FLAG_PIO_DMA, 211441577efSTejun Heo .pio_mask = ATA_PIO4, 212441577efSTejun Heo .udma_mask = ATA_UDMA6, 213441577efSTejun Heo .port_ops = &ahci_ops, 214441577efSTejun Heo }, 215facb8fa6SJeffrin Jose [board_ahci_sb600] = { 216417a1a6dSTejun Heo AHCI_HFLAGS (AHCI_HFLAG_IGN_SERR_INTERNAL | 2172fcad9d2STejun Heo AHCI_HFLAG_NO_MSI | AHCI_HFLAG_SECT255 | 2182fcad9d2STejun Heo AHCI_HFLAG_32BIT_ONLY), 219417a1a6dSTejun Heo .flags = AHCI_FLAG_COMMON, 22014bdef98SErik Inge Bolsø .pio_mask = ATA_PIO4, 221469248abSJeff Garzik .udma_mask = ATA_UDMA6, 222345347c5SYuan-Hsin Chen .port_ops = &ahci_pmp_retry_srst_ops, 22355a61604SConke Hu }, 224facb8fa6SJeffrin Jose [board_ahci_sb700] = { /* for SB700 and SB800 */ 225bd17243aSShane Huang AHCI_HFLAGS (AHCI_HFLAG_IGN_SERR_INTERNAL), 226e39fc8c9SShane Huang .flags = AHCI_FLAG_COMMON, 22714bdef98SErik Inge Bolsø .pio_mask = ATA_PIO4, 228e39fc8c9SShane Huang .udma_mask = ATA_UDMA6, 229345347c5SYuan-Hsin Chen .port_ops = &ahci_pmp_retry_srst_ops, 230e39fc8c9SShane Huang }, 231facb8fa6SJeffrin Jose [board_ahci_vt8251] = { 232441577efSTejun Heo AHCI_HFLAGS (AHCI_HFLAG_NO_NCQ | AHCI_HFLAG_NO_PMP), 233e297d99eSTejun Heo .flags = AHCI_FLAG_COMMON, 23414bdef98SErik Inge Bolsø .pio_mask = ATA_PIO4, 235e297d99eSTejun Heo .udma_mask = ATA_UDMA6, 236441577efSTejun Heo .port_ops = &ahci_vt8251_ops, 2371b677afdSShaohua Li }, 238c312ef17SDan Williams [board_ahci_pcs7] = { 239c312ef17SDan Williams .flags = AHCI_FLAG_COMMON, 240c312ef17SDan Williams .pio_mask = ATA_PIO4, 241c312ef17SDan Williams .udma_mask = ATA_UDMA6, 242c312ef17SDan Williams .port_ops = &ahci_ops, 243c312ef17SDan Williams }, 244c6fd2807SJeff Garzik }; 245c6fd2807SJeff Garzik 246c6fd2807SJeff Garzik static const struct pci_device_id ahci_pci_tbl[] = { 247c6fd2807SJeff Garzik /* Intel */ 24854bb3a94SJeff Garzik { PCI_VDEVICE(INTEL, 0x2652), board_ahci }, /* ICH6 */ 24954bb3a94SJeff Garzik { PCI_VDEVICE(INTEL, 0x2653), board_ahci }, /* ICH6M */ 25054bb3a94SJeff Garzik { PCI_VDEVICE(INTEL, 0x27c1), board_ahci }, /* ICH7 */ 25154bb3a94SJeff Garzik { PCI_VDEVICE(INTEL, 0x27c5), board_ahci }, /* ICH7M */ 25254bb3a94SJeff Garzik { PCI_VDEVICE(INTEL, 0x27c3), board_ahci }, /* ICH7R */ 25382490c09STejun Heo { PCI_VDEVICE(AL, 0x5288), board_ahci_ign_iferr }, /* ULi M5288 */ 25454bb3a94SJeff Garzik { PCI_VDEVICE(INTEL, 0x2681), board_ahci }, /* ESB2 */ 25554bb3a94SJeff Garzik { PCI_VDEVICE(INTEL, 0x2682), board_ahci }, /* ESB2 */ 25654bb3a94SJeff Garzik { PCI_VDEVICE(INTEL, 0x2683), board_ahci }, /* ESB2 */ 25754bb3a94SJeff Garzik { PCI_VDEVICE(INTEL, 0x27c6), board_ahci }, /* ICH7-M DH */ 2587a234affSTejun Heo { PCI_VDEVICE(INTEL, 0x2821), board_ahci }, /* ICH8 */ 2591b677afdSShaohua Li { PCI_VDEVICE(INTEL, 0x2822), board_ahci_nosntf }, /* ICH8 */ 2607a234affSTejun Heo { PCI_VDEVICE(INTEL, 0x2824), board_ahci }, /* ICH8 */ 2617a234affSTejun Heo { PCI_VDEVICE(INTEL, 0x2829), board_ahci }, /* ICH8M */ 2627a234affSTejun Heo { PCI_VDEVICE(INTEL, 0x282a), board_ahci }, /* ICH8M */ 2637a234affSTejun Heo { PCI_VDEVICE(INTEL, 0x2922), board_ahci }, /* ICH9 */ 2647a234affSTejun Heo { PCI_VDEVICE(INTEL, 0x2923), board_ahci }, /* ICH9 */ 2657a234affSTejun Heo { PCI_VDEVICE(INTEL, 0x2924), board_ahci }, /* ICH9 */ 2667a234affSTejun Heo { PCI_VDEVICE(INTEL, 0x2925), board_ahci }, /* ICH9 */ 2677a234affSTejun Heo { PCI_VDEVICE(INTEL, 0x2927), board_ahci }, /* ICH9 */ 268ebb82e3cSHans de Goede { PCI_VDEVICE(INTEL, 0x2929), board_ahci_mobile }, /* ICH9M */ 269ebb82e3cSHans de Goede { PCI_VDEVICE(INTEL, 0x292a), board_ahci_mobile }, /* ICH9M */ 270ebb82e3cSHans de Goede { PCI_VDEVICE(INTEL, 0x292b), board_ahci_mobile }, /* ICH9M */ 271ebb82e3cSHans de Goede { PCI_VDEVICE(INTEL, 0x292c), board_ahci_mobile }, /* ICH9M */ 272ebb82e3cSHans de Goede { PCI_VDEVICE(INTEL, 0x292f), board_ahci_mobile }, /* ICH9M */ 2737a234affSTejun Heo { PCI_VDEVICE(INTEL, 0x294d), board_ahci }, /* ICH9 */ 274ebb82e3cSHans de Goede { PCI_VDEVICE(INTEL, 0x294e), board_ahci_mobile }, /* ICH9M */ 275d4155e6fSJason Gaston { PCI_VDEVICE(INTEL, 0x502a), board_ahci }, /* Tolapai */ 276d4155e6fSJason Gaston { PCI_VDEVICE(INTEL, 0x502b), board_ahci }, /* Tolapai */ 27716ad1ad9SJason Gaston { PCI_VDEVICE(INTEL, 0x3a05), board_ahci }, /* ICH10 */ 278b2dde6afSMark Goodwin { PCI_VDEVICE(INTEL, 0x3a22), board_ahci }, /* ICH10 */ 27916ad1ad9SJason Gaston { PCI_VDEVICE(INTEL, 0x3a25), board_ahci }, /* ICH10 */ 280c1f57d9bSDavid Milburn { PCI_VDEVICE(INTEL, 0x3b22), board_ahci }, /* PCH AHCI */ 281c1f57d9bSDavid Milburn { PCI_VDEVICE(INTEL, 0x3b23), board_ahci }, /* PCH AHCI */ 282adcb5308SSeth Heasley { PCI_VDEVICE(INTEL, 0x3b24), board_ahci }, /* PCH RAID */ 2838e48b6b3SSeth Heasley { PCI_VDEVICE(INTEL, 0x3b25), board_ahci }, /* PCH RAID */ 284ebb82e3cSHans de Goede { PCI_VDEVICE(INTEL, 0x3b29), board_ahci_mobile }, /* PCH M AHCI */ 285adcb5308SSeth Heasley { PCI_VDEVICE(INTEL, 0x3b2b), board_ahci }, /* PCH RAID */ 286ebb82e3cSHans de Goede { PCI_VDEVICE(INTEL, 0x3b2c), board_ahci_mobile }, /* PCH M RAID */ 287c1f57d9bSDavid Milburn { PCI_VDEVICE(INTEL, 0x3b2f), board_ahci }, /* PCH AHCI */ 288c312ef17SDan Williams { PCI_VDEVICE(INTEL, 0x19b0), board_ahci_pcs7 }, /* DNV AHCI */ 289c312ef17SDan Williams { PCI_VDEVICE(INTEL, 0x19b1), board_ahci_pcs7 }, /* DNV AHCI */ 290c312ef17SDan Williams { PCI_VDEVICE(INTEL, 0x19b2), board_ahci_pcs7 }, /* DNV AHCI */ 291c312ef17SDan Williams { PCI_VDEVICE(INTEL, 0x19b3), board_ahci_pcs7 }, /* DNV AHCI */ 292c312ef17SDan Williams { PCI_VDEVICE(INTEL, 0x19b4), board_ahci_pcs7 }, /* DNV AHCI */ 293c312ef17SDan Williams { PCI_VDEVICE(INTEL, 0x19b5), board_ahci_pcs7 }, /* DNV AHCI */ 294c312ef17SDan Williams { PCI_VDEVICE(INTEL, 0x19b6), board_ahci_pcs7 }, /* DNV AHCI */ 295c312ef17SDan Williams { PCI_VDEVICE(INTEL, 0x19b7), board_ahci_pcs7 }, /* DNV AHCI */ 296c312ef17SDan Williams { PCI_VDEVICE(INTEL, 0x19bE), board_ahci_pcs7 }, /* DNV AHCI */ 297c312ef17SDan Williams { PCI_VDEVICE(INTEL, 0x19bF), board_ahci_pcs7 }, /* DNV AHCI */ 298c312ef17SDan Williams { PCI_VDEVICE(INTEL, 0x19c0), board_ahci_pcs7 }, /* DNV AHCI */ 299c312ef17SDan Williams { PCI_VDEVICE(INTEL, 0x19c1), board_ahci_pcs7 }, /* DNV AHCI */ 300c312ef17SDan Williams { PCI_VDEVICE(INTEL, 0x19c2), board_ahci_pcs7 }, /* DNV AHCI */ 301c312ef17SDan Williams { PCI_VDEVICE(INTEL, 0x19c3), board_ahci_pcs7 }, /* DNV AHCI */ 302c312ef17SDan Williams { PCI_VDEVICE(INTEL, 0x19c4), board_ahci_pcs7 }, /* DNV AHCI */ 303c312ef17SDan Williams { PCI_VDEVICE(INTEL, 0x19c5), board_ahci_pcs7 }, /* DNV AHCI */ 304c312ef17SDan Williams { PCI_VDEVICE(INTEL, 0x19c6), board_ahci_pcs7 }, /* DNV AHCI */ 305c312ef17SDan Williams { PCI_VDEVICE(INTEL, 0x19c7), board_ahci_pcs7 }, /* DNV AHCI */ 306c312ef17SDan Williams { PCI_VDEVICE(INTEL, 0x19cE), board_ahci_pcs7 }, /* DNV AHCI */ 307c312ef17SDan Williams { PCI_VDEVICE(INTEL, 0x19cF), board_ahci_pcs7 }, /* DNV AHCI */ 3085623cab8SSeth Heasley { PCI_VDEVICE(INTEL, 0x1c02), board_ahci }, /* CPT AHCI */ 309ebb82e3cSHans de Goede { PCI_VDEVICE(INTEL, 0x1c03), board_ahci_mobile }, /* CPT M AHCI */ 3105623cab8SSeth Heasley { PCI_VDEVICE(INTEL, 0x1c04), board_ahci }, /* CPT RAID */ 311ebb82e3cSHans de Goede { PCI_VDEVICE(INTEL, 0x1c05), board_ahci_mobile }, /* CPT M RAID */ 3125623cab8SSeth Heasley { PCI_VDEVICE(INTEL, 0x1c06), board_ahci }, /* CPT RAID */ 3135623cab8SSeth Heasley { PCI_VDEVICE(INTEL, 0x1c07), board_ahci }, /* CPT RAID */ 314992b3fb9SSeth Heasley { PCI_VDEVICE(INTEL, 0x1d02), board_ahci }, /* PBG AHCI */ 315992b3fb9SSeth Heasley { PCI_VDEVICE(INTEL, 0x1d04), board_ahci }, /* PBG RAID */ 316992b3fb9SSeth Heasley { PCI_VDEVICE(INTEL, 0x1d06), board_ahci }, /* PBG RAID */ 31764a3903dSSeth Heasley { PCI_VDEVICE(INTEL, 0x2826), board_ahci }, /* PBG RAID */ 318a4a461a6SSeth Heasley { PCI_VDEVICE(INTEL, 0x2323), board_ahci }, /* DH89xxCC AHCI */ 319181e3ceaSSeth Heasley { PCI_VDEVICE(INTEL, 0x1e02), board_ahci }, /* Panther Point AHCI */ 320ebb82e3cSHans de Goede { PCI_VDEVICE(INTEL, 0x1e03), board_ahci_mobile }, /* Panther M AHCI */ 321181e3ceaSSeth Heasley { PCI_VDEVICE(INTEL, 0x1e04), board_ahci }, /* Panther Point RAID */ 322181e3ceaSSeth Heasley { PCI_VDEVICE(INTEL, 0x1e05), board_ahci }, /* Panther Point RAID */ 323181e3ceaSSeth Heasley { PCI_VDEVICE(INTEL, 0x1e06), board_ahci }, /* Panther Point RAID */ 324ebb82e3cSHans de Goede { PCI_VDEVICE(INTEL, 0x1e07), board_ahci_mobile }, /* Panther M RAID */ 3252cab7a4cSSeth Heasley { PCI_VDEVICE(INTEL, 0x1e0e), board_ahci }, /* Panther Point RAID */ 326ea4ace66SSeth Heasley { PCI_VDEVICE(INTEL, 0x8c02), board_ahci }, /* Lynx Point AHCI */ 327ebb82e3cSHans de Goede { PCI_VDEVICE(INTEL, 0x8c03), board_ahci_mobile }, /* Lynx M AHCI */ 328ea4ace66SSeth Heasley { PCI_VDEVICE(INTEL, 0x8c04), board_ahci }, /* Lynx Point RAID */ 329ebb82e3cSHans de Goede { PCI_VDEVICE(INTEL, 0x8c05), board_ahci_mobile }, /* Lynx M RAID */ 330ea4ace66SSeth Heasley { PCI_VDEVICE(INTEL, 0x8c06), board_ahci }, /* Lynx Point RAID */ 331ebb82e3cSHans de Goede { PCI_VDEVICE(INTEL, 0x8c07), board_ahci_mobile }, /* Lynx M RAID */ 332ea4ace66SSeth Heasley { PCI_VDEVICE(INTEL, 0x8c0e), board_ahci }, /* Lynx Point RAID */ 333ebb82e3cSHans de Goede { PCI_VDEVICE(INTEL, 0x8c0f), board_ahci_mobile }, /* Lynx M RAID */ 334ebb82e3cSHans de Goede { PCI_VDEVICE(INTEL, 0x9c02), board_ahci_mobile }, /* Lynx LP AHCI */ 335ebb82e3cSHans de Goede { PCI_VDEVICE(INTEL, 0x9c03), board_ahci_mobile }, /* Lynx LP AHCI */ 336ebb82e3cSHans de Goede { PCI_VDEVICE(INTEL, 0x9c04), board_ahci_mobile }, /* Lynx LP RAID */ 337ebb82e3cSHans de Goede { PCI_VDEVICE(INTEL, 0x9c05), board_ahci_mobile }, /* Lynx LP RAID */ 338ebb82e3cSHans de Goede { PCI_VDEVICE(INTEL, 0x9c06), board_ahci_mobile }, /* Lynx LP RAID */ 339ebb82e3cSHans de Goede { PCI_VDEVICE(INTEL, 0x9c07), board_ahci_mobile }, /* Lynx LP RAID */ 340ebb82e3cSHans de Goede { PCI_VDEVICE(INTEL, 0x9c0e), board_ahci_mobile }, /* Lynx LP RAID */ 341ebb82e3cSHans de Goede { PCI_VDEVICE(INTEL, 0x9c0f), board_ahci_mobile }, /* Lynx LP RAID */ 3424544e403SMika Westerberg { PCI_VDEVICE(INTEL, 0x9dd3), board_ahci_mobile }, /* Cannon Lake PCH-LP AHCI */ 34329e674ddSSeth Heasley { PCI_VDEVICE(INTEL, 0x1f22), board_ahci }, /* Avoton AHCI */ 34429e674ddSSeth Heasley { PCI_VDEVICE(INTEL, 0x1f23), board_ahci }, /* Avoton AHCI */ 34529e674ddSSeth Heasley { PCI_VDEVICE(INTEL, 0x1f24), board_ahci }, /* Avoton RAID */ 34629e674ddSSeth Heasley { PCI_VDEVICE(INTEL, 0x1f25), board_ahci }, /* Avoton RAID */ 34729e674ddSSeth Heasley { PCI_VDEVICE(INTEL, 0x1f26), board_ahci }, /* Avoton RAID */ 34829e674ddSSeth Heasley { PCI_VDEVICE(INTEL, 0x1f27), board_ahci }, /* Avoton RAID */ 34929e674ddSSeth Heasley { PCI_VDEVICE(INTEL, 0x1f2e), board_ahci }, /* Avoton RAID */ 35029e674ddSSeth Heasley { PCI_VDEVICE(INTEL, 0x1f2f), board_ahci }, /* Avoton RAID */ 351dbfe8ef5SDan Williams { PCI_VDEVICE(INTEL, 0x1f32), board_ahci_avn }, /* Avoton AHCI */ 352dbfe8ef5SDan Williams { PCI_VDEVICE(INTEL, 0x1f33), board_ahci_avn }, /* Avoton AHCI */ 353dbfe8ef5SDan Williams { PCI_VDEVICE(INTEL, 0x1f34), board_ahci_avn }, /* Avoton RAID */ 354dbfe8ef5SDan Williams { PCI_VDEVICE(INTEL, 0x1f35), board_ahci_avn }, /* Avoton RAID */ 355dbfe8ef5SDan Williams { PCI_VDEVICE(INTEL, 0x1f36), board_ahci_avn }, /* Avoton RAID */ 356dbfe8ef5SDan Williams { PCI_VDEVICE(INTEL, 0x1f37), board_ahci_avn }, /* Avoton RAID */ 357dbfe8ef5SDan Williams { PCI_VDEVICE(INTEL, 0x1f3e), board_ahci_avn }, /* Avoton RAID */ 358dbfe8ef5SDan Williams { PCI_VDEVICE(INTEL, 0x1f3f), board_ahci_avn }, /* Avoton RAID */ 359efda332cSJames Ralston { PCI_VDEVICE(INTEL, 0x2823), board_ahci }, /* Wellsburg RAID */ 360efda332cSJames Ralston { PCI_VDEVICE(INTEL, 0x2827), board_ahci }, /* Wellsburg RAID */ 361151743fdSJames Ralston { PCI_VDEVICE(INTEL, 0x8d02), board_ahci }, /* Wellsburg AHCI */ 362151743fdSJames Ralston { PCI_VDEVICE(INTEL, 0x8d04), board_ahci }, /* Wellsburg RAID */ 363151743fdSJames Ralston { PCI_VDEVICE(INTEL, 0x8d06), board_ahci }, /* Wellsburg RAID */ 364151743fdSJames Ralston { PCI_VDEVICE(INTEL, 0x8d0e), board_ahci }, /* Wellsburg RAID */ 365151743fdSJames Ralston { PCI_VDEVICE(INTEL, 0x8d62), board_ahci }, /* Wellsburg AHCI */ 366151743fdSJames Ralston { PCI_VDEVICE(INTEL, 0x8d64), board_ahci }, /* Wellsburg RAID */ 367151743fdSJames Ralston { PCI_VDEVICE(INTEL, 0x8d66), board_ahci }, /* Wellsburg RAID */ 368151743fdSJames Ralston { PCI_VDEVICE(INTEL, 0x8d6e), board_ahci }, /* Wellsburg RAID */ 3691cfc7df3SSeth Heasley { PCI_VDEVICE(INTEL, 0x23a3), board_ahci }, /* Coleto Creek AHCI */ 370ebb82e3cSHans de Goede { PCI_VDEVICE(INTEL, 0x9c83), board_ahci_mobile }, /* Wildcat LP AHCI */ 371ebb82e3cSHans de Goede { PCI_VDEVICE(INTEL, 0x9c85), board_ahci_mobile }, /* Wildcat LP RAID */ 372ebb82e3cSHans de Goede { PCI_VDEVICE(INTEL, 0x9c87), board_ahci_mobile }, /* Wildcat LP RAID */ 373ebb82e3cSHans de Goede { PCI_VDEVICE(INTEL, 0x9c8f), board_ahci_mobile }, /* Wildcat LP RAID */ 3741b071a09SJames Ralston { PCI_VDEVICE(INTEL, 0x8c82), board_ahci }, /* 9 Series AHCI */ 375ebb82e3cSHans de Goede { PCI_VDEVICE(INTEL, 0x8c83), board_ahci_mobile }, /* 9 Series M AHCI */ 3761b071a09SJames Ralston { PCI_VDEVICE(INTEL, 0x8c84), board_ahci }, /* 9 Series RAID */ 377ebb82e3cSHans de Goede { PCI_VDEVICE(INTEL, 0x8c85), board_ahci_mobile }, /* 9 Series M RAID */ 3781b071a09SJames Ralston { PCI_VDEVICE(INTEL, 0x8c86), board_ahci }, /* 9 Series RAID */ 379ebb82e3cSHans de Goede { PCI_VDEVICE(INTEL, 0x8c87), board_ahci_mobile }, /* 9 Series M RAID */ 3801b071a09SJames Ralston { PCI_VDEVICE(INTEL, 0x8c8e), board_ahci }, /* 9 Series RAID */ 381ebb82e3cSHans de Goede { PCI_VDEVICE(INTEL, 0x8c8f), board_ahci_mobile }, /* 9 Series M RAID */ 382ebb82e3cSHans de Goede { PCI_VDEVICE(INTEL, 0x9d03), board_ahci_mobile }, /* Sunrise LP AHCI */ 383ebb82e3cSHans de Goede { PCI_VDEVICE(INTEL, 0x9d05), board_ahci_mobile }, /* Sunrise LP RAID */ 384ebb82e3cSHans de Goede { PCI_VDEVICE(INTEL, 0x9d07), board_ahci_mobile }, /* Sunrise LP RAID */ 385c5967b79SCharles_Rose@Dell.com { PCI_VDEVICE(INTEL, 0xa102), board_ahci }, /* Sunrise Point-H AHCI */ 386ebb82e3cSHans de Goede { PCI_VDEVICE(INTEL, 0xa103), board_ahci_mobile }, /* Sunrise M AHCI */ 387690000b9SJames Ralston { PCI_VDEVICE(INTEL, 0xa105), board_ahci }, /* Sunrise Point-H RAID */ 388c5967b79SCharles_Rose@Dell.com { PCI_VDEVICE(INTEL, 0xa106), board_ahci }, /* Sunrise Point-H RAID */ 389ebb82e3cSHans de Goede { PCI_VDEVICE(INTEL, 0xa107), board_ahci_mobile }, /* Sunrise M RAID */ 390690000b9SJames Ralston { PCI_VDEVICE(INTEL, 0xa10f), board_ahci }, /* Sunrise Point-H RAID */ 3914d92f009SAlexandra Yates { PCI_VDEVICE(INTEL, 0x2822), board_ahci }, /* Lewisburg RAID*/ 392f5bdd66cSAlexandra Yates { PCI_VDEVICE(INTEL, 0x2823), board_ahci }, /* Lewisburg AHCI*/ 3934d92f009SAlexandra Yates { PCI_VDEVICE(INTEL, 0x2826), board_ahci }, /* Lewisburg RAID*/ 394f5bdd66cSAlexandra Yates { PCI_VDEVICE(INTEL, 0x2827), board_ahci }, /* Lewisburg RAID*/ 3954d92f009SAlexandra Yates { PCI_VDEVICE(INTEL, 0xa182), board_ahci }, /* Lewisburg AHCI*/ 3964d92f009SAlexandra Yates { PCI_VDEVICE(INTEL, 0xa186), board_ahci }, /* Lewisburg RAID*/ 397f5bdd66cSAlexandra Yates { PCI_VDEVICE(INTEL, 0xa1d2), board_ahci }, /* Lewisburg RAID*/ 398f5bdd66cSAlexandra Yates { PCI_VDEVICE(INTEL, 0xa1d6), board_ahci }, /* Lewisburg RAID*/ 3994d92f009SAlexandra Yates { PCI_VDEVICE(INTEL, 0xa202), board_ahci }, /* Lewisburg AHCI*/ 4004d92f009SAlexandra Yates { PCI_VDEVICE(INTEL, 0xa206), board_ahci }, /* Lewisburg RAID*/ 401f5bdd66cSAlexandra Yates { PCI_VDEVICE(INTEL, 0xa252), board_ahci }, /* Lewisburg RAID*/ 402f5bdd66cSAlexandra Yates { PCI_VDEVICE(INTEL, 0xa256), board_ahci }, /* Lewisburg RAID*/ 403f919dde0SMika Westerberg { PCI_VDEVICE(INTEL, 0xa356), board_ahci }, /* Cannon Lake PCH-H RAID */ 404ebb82e3cSHans de Goede { PCI_VDEVICE(INTEL, 0x0f22), board_ahci_mobile }, /* Bay Trail AHCI */ 405ebb82e3cSHans de Goede { PCI_VDEVICE(INTEL, 0x0f23), board_ahci_mobile }, /* Bay Trail AHCI */ 406ebb82e3cSHans de Goede { PCI_VDEVICE(INTEL, 0x22a3), board_ahci_mobile }, /* Cherry Tr. AHCI */ 407ebb82e3cSHans de Goede { PCI_VDEVICE(INTEL, 0x5ae3), board_ahci_mobile }, /* ApolloLake AHCI */ 408ba445791SMika Westerberg { PCI_VDEVICE(INTEL, 0x34d3), board_ahci_mobile }, /* Ice Lake LP AHCI */ 409c6fd2807SJeff Garzik 410e34bb370STejun Heo /* JMicron 360/1/3/5/6, match class to avoid IDE function */ 411e34bb370STejun Heo { PCI_VENDOR_ID_JMICRON, PCI_ANY_ID, PCI_ANY_ID, PCI_ANY_ID, 412e34bb370STejun Heo PCI_CLASS_STORAGE_SATA_AHCI, 0xffffff, board_ahci_ign_iferr }, 4131fefb8fdSBen Hutchings /* JMicron 362B and 362C have an AHCI function with IDE class code */ 4141fefb8fdSBen Hutchings { PCI_VDEVICE(JMICRON, 0x2362), board_ahci_ign_iferr }, 4151fefb8fdSBen Hutchings { PCI_VDEVICE(JMICRON, 0x236f), board_ahci_ign_iferr }, 41691f15fb3SZhang Rui /* May need to update quirk_jmicron_async_suspend() for additions */ 417c6fd2807SJeff Garzik 418c6fd2807SJeff Garzik /* ATI */ 419c65ec1c2SConke Hu { PCI_VDEVICE(ATI, 0x4380), board_ahci_sb600 }, /* ATI SB600 */ 420e39fc8c9SShane Huang { PCI_VDEVICE(ATI, 0x4390), board_ahci_sb700 }, /* ATI SB700/800 */ 421e39fc8c9SShane Huang { PCI_VDEVICE(ATI, 0x4391), board_ahci_sb700 }, /* ATI SB700/800 */ 422e39fc8c9SShane Huang { PCI_VDEVICE(ATI, 0x4392), board_ahci_sb700 }, /* ATI SB700/800 */ 423e39fc8c9SShane Huang { PCI_VDEVICE(ATI, 0x4393), board_ahci_sb700 }, /* ATI SB700/800 */ 424e39fc8c9SShane Huang { PCI_VDEVICE(ATI, 0x4394), board_ahci_sb700 }, /* ATI SB700/800 */ 425e39fc8c9SShane Huang { PCI_VDEVICE(ATI, 0x4395), board_ahci_sb700 }, /* ATI SB700/800 */ 426c6fd2807SJeff Garzik 4277d523bdcSHanna Hawa /* Amazon's Annapurna Labs support */ 4287d523bdcSHanna Hawa { PCI_DEVICE(PCI_VENDOR_ID_AMAZON_ANNAPURNA_LABS, 0x0031), 4297d523bdcSHanna Hawa .class = PCI_CLASS_STORAGE_SATA_AHCI, 4307d523bdcSHanna Hawa .class_mask = 0xffffff, 4317d523bdcSHanna Hawa board_ahci_al }, 432e2dd90b1SShane Huang /* AMD */ 4335deab536SShane Huang { PCI_VDEVICE(AMD, 0x7800), board_ahci }, /* AMD Hudson-2 */ 434fafe5c3dSShane Huang { PCI_VDEVICE(AMD, 0x7900), board_ahci }, /* AMD CZ */ 435e2dd90b1SShane Huang /* AMD is using RAID class only for ahci controllers */ 436e2dd90b1SShane Huang { PCI_VENDOR_ID_AMD, PCI_ANY_ID, PCI_ANY_ID, PCI_ANY_ID, 437e2dd90b1SShane Huang PCI_CLASS_STORAGE_RAID << 8, 0xffffff, board_ahci }, 438e2dd90b1SShane Huang 439c6fd2807SJeff Garzik /* VIA */ 44054bb3a94SJeff Garzik { PCI_VDEVICE(VIA, 0x3349), board_ahci_vt8251 }, /* VIA VT8251 */ 441bf335542STejun Heo { PCI_VDEVICE(VIA, 0x6287), board_ahci_vt8251 }, /* VIA VT8251 */ 442c6fd2807SJeff Garzik 443c6fd2807SJeff Garzik /* NVIDIA */ 444e297d99eSTejun Heo { PCI_VDEVICE(NVIDIA, 0x044c), board_ahci_mcp65 }, /* MCP65 */ 445e297d99eSTejun Heo { PCI_VDEVICE(NVIDIA, 0x044d), board_ahci_mcp65 }, /* MCP65 */ 446e297d99eSTejun Heo { PCI_VDEVICE(NVIDIA, 0x044e), board_ahci_mcp65 }, /* MCP65 */ 447e297d99eSTejun Heo { PCI_VDEVICE(NVIDIA, 0x044f), board_ahci_mcp65 }, /* MCP65 */ 448e297d99eSTejun Heo { PCI_VDEVICE(NVIDIA, 0x045c), board_ahci_mcp65 }, /* MCP65 */ 449e297d99eSTejun Heo { PCI_VDEVICE(NVIDIA, 0x045d), board_ahci_mcp65 }, /* MCP65 */ 450e297d99eSTejun Heo { PCI_VDEVICE(NVIDIA, 0x045e), board_ahci_mcp65 }, /* MCP65 */ 451e297d99eSTejun Heo { PCI_VDEVICE(NVIDIA, 0x045f), board_ahci_mcp65 }, /* MCP65 */ 452441577efSTejun Heo { PCI_VDEVICE(NVIDIA, 0x0550), board_ahci_mcp67 }, /* MCP67 */ 453441577efSTejun Heo { PCI_VDEVICE(NVIDIA, 0x0551), board_ahci_mcp67 }, /* MCP67 */ 454441577efSTejun Heo { PCI_VDEVICE(NVIDIA, 0x0552), board_ahci_mcp67 }, /* MCP67 */ 455441577efSTejun Heo { PCI_VDEVICE(NVIDIA, 0x0553), board_ahci_mcp67 }, /* MCP67 */ 456441577efSTejun Heo { PCI_VDEVICE(NVIDIA, 0x0554), board_ahci_mcp67 }, /* MCP67 */ 457441577efSTejun Heo { PCI_VDEVICE(NVIDIA, 0x0555), board_ahci_mcp67 }, /* MCP67 */ 458441577efSTejun Heo { PCI_VDEVICE(NVIDIA, 0x0556), board_ahci_mcp67 }, /* MCP67 */ 459441577efSTejun Heo { PCI_VDEVICE(NVIDIA, 0x0557), board_ahci_mcp67 }, /* MCP67 */ 460441577efSTejun Heo { PCI_VDEVICE(NVIDIA, 0x0558), board_ahci_mcp67 }, /* MCP67 */ 461441577efSTejun Heo { PCI_VDEVICE(NVIDIA, 0x0559), board_ahci_mcp67 }, /* MCP67 */ 462441577efSTejun Heo { PCI_VDEVICE(NVIDIA, 0x055a), board_ahci_mcp67 }, /* MCP67 */ 463441577efSTejun Heo { PCI_VDEVICE(NVIDIA, 0x055b), board_ahci_mcp67 }, /* MCP67 */ 464441577efSTejun Heo { PCI_VDEVICE(NVIDIA, 0x0580), board_ahci_mcp_linux }, /* Linux ID */ 465441577efSTejun Heo { PCI_VDEVICE(NVIDIA, 0x0581), board_ahci_mcp_linux }, /* Linux ID */ 466441577efSTejun Heo { PCI_VDEVICE(NVIDIA, 0x0582), board_ahci_mcp_linux }, /* Linux ID */ 467441577efSTejun Heo { PCI_VDEVICE(NVIDIA, 0x0583), board_ahci_mcp_linux }, /* Linux ID */ 468441577efSTejun Heo { PCI_VDEVICE(NVIDIA, 0x0584), board_ahci_mcp_linux }, /* Linux ID */ 469441577efSTejun Heo { PCI_VDEVICE(NVIDIA, 0x0585), board_ahci_mcp_linux }, /* Linux ID */ 470441577efSTejun Heo { PCI_VDEVICE(NVIDIA, 0x0586), board_ahci_mcp_linux }, /* Linux ID */ 471441577efSTejun Heo { PCI_VDEVICE(NVIDIA, 0x0587), board_ahci_mcp_linux }, /* Linux ID */ 472441577efSTejun Heo { PCI_VDEVICE(NVIDIA, 0x0588), board_ahci_mcp_linux }, /* Linux ID */ 473441577efSTejun Heo { PCI_VDEVICE(NVIDIA, 0x0589), board_ahci_mcp_linux }, /* Linux ID */ 474441577efSTejun Heo { PCI_VDEVICE(NVIDIA, 0x058a), board_ahci_mcp_linux }, /* Linux ID */ 475441577efSTejun Heo { PCI_VDEVICE(NVIDIA, 0x058b), board_ahci_mcp_linux }, /* Linux ID */ 476441577efSTejun Heo { PCI_VDEVICE(NVIDIA, 0x058c), board_ahci_mcp_linux }, /* Linux ID */ 477441577efSTejun Heo { PCI_VDEVICE(NVIDIA, 0x058d), board_ahci_mcp_linux }, /* Linux ID */ 478441577efSTejun Heo { PCI_VDEVICE(NVIDIA, 0x058e), board_ahci_mcp_linux }, /* Linux ID */ 479441577efSTejun Heo { PCI_VDEVICE(NVIDIA, 0x058f), board_ahci_mcp_linux }, /* Linux ID */ 480441577efSTejun Heo { PCI_VDEVICE(NVIDIA, 0x07f0), board_ahci_mcp73 }, /* MCP73 */ 481441577efSTejun Heo { PCI_VDEVICE(NVIDIA, 0x07f1), board_ahci_mcp73 }, /* MCP73 */ 482441577efSTejun Heo { PCI_VDEVICE(NVIDIA, 0x07f2), board_ahci_mcp73 }, /* MCP73 */ 483441577efSTejun Heo { PCI_VDEVICE(NVIDIA, 0x07f3), board_ahci_mcp73 }, /* MCP73 */ 484441577efSTejun Heo { PCI_VDEVICE(NVIDIA, 0x07f4), board_ahci_mcp73 }, /* MCP73 */ 485441577efSTejun Heo { PCI_VDEVICE(NVIDIA, 0x07f5), board_ahci_mcp73 }, /* MCP73 */ 486441577efSTejun Heo { PCI_VDEVICE(NVIDIA, 0x07f6), board_ahci_mcp73 }, /* MCP73 */ 487441577efSTejun Heo { PCI_VDEVICE(NVIDIA, 0x07f7), board_ahci_mcp73 }, /* MCP73 */ 488441577efSTejun Heo { PCI_VDEVICE(NVIDIA, 0x07f8), board_ahci_mcp73 }, /* MCP73 */ 489441577efSTejun Heo { PCI_VDEVICE(NVIDIA, 0x07f9), board_ahci_mcp73 }, /* MCP73 */ 490441577efSTejun Heo { PCI_VDEVICE(NVIDIA, 0x07fa), board_ahci_mcp73 }, /* MCP73 */ 491441577efSTejun Heo { PCI_VDEVICE(NVIDIA, 0x07fb), board_ahci_mcp73 }, /* MCP73 */ 492441577efSTejun Heo { PCI_VDEVICE(NVIDIA, 0x0ad0), board_ahci_mcp77 }, /* MCP77 */ 493441577efSTejun Heo { PCI_VDEVICE(NVIDIA, 0x0ad1), board_ahci_mcp77 }, /* MCP77 */ 494441577efSTejun Heo { PCI_VDEVICE(NVIDIA, 0x0ad2), board_ahci_mcp77 }, /* MCP77 */ 495441577efSTejun Heo { PCI_VDEVICE(NVIDIA, 0x0ad3), board_ahci_mcp77 }, /* MCP77 */ 496441577efSTejun Heo { PCI_VDEVICE(NVIDIA, 0x0ad4), board_ahci_mcp77 }, /* MCP77 */ 497441577efSTejun Heo { PCI_VDEVICE(NVIDIA, 0x0ad5), board_ahci_mcp77 }, /* MCP77 */ 498441577efSTejun Heo { PCI_VDEVICE(NVIDIA, 0x0ad6), board_ahci_mcp77 }, /* MCP77 */ 499441577efSTejun Heo { PCI_VDEVICE(NVIDIA, 0x0ad7), board_ahci_mcp77 }, /* MCP77 */ 500441577efSTejun Heo { PCI_VDEVICE(NVIDIA, 0x0ad8), board_ahci_mcp77 }, /* MCP77 */ 501441577efSTejun Heo { PCI_VDEVICE(NVIDIA, 0x0ad9), board_ahci_mcp77 }, /* MCP77 */ 502441577efSTejun Heo { PCI_VDEVICE(NVIDIA, 0x0ada), board_ahci_mcp77 }, /* MCP77 */ 503441577efSTejun Heo { PCI_VDEVICE(NVIDIA, 0x0adb), board_ahci_mcp77 }, /* MCP77 */ 504441577efSTejun Heo { PCI_VDEVICE(NVIDIA, 0x0ab4), board_ahci_mcp79 }, /* MCP79 */ 505441577efSTejun Heo { PCI_VDEVICE(NVIDIA, 0x0ab5), board_ahci_mcp79 }, /* MCP79 */ 506441577efSTejun Heo { PCI_VDEVICE(NVIDIA, 0x0ab6), board_ahci_mcp79 }, /* MCP79 */ 507441577efSTejun Heo { PCI_VDEVICE(NVIDIA, 0x0ab7), board_ahci_mcp79 }, /* MCP79 */ 508441577efSTejun Heo { PCI_VDEVICE(NVIDIA, 0x0ab8), board_ahci_mcp79 }, /* MCP79 */ 509441577efSTejun Heo { PCI_VDEVICE(NVIDIA, 0x0ab9), board_ahci_mcp79 }, /* MCP79 */ 510441577efSTejun Heo { PCI_VDEVICE(NVIDIA, 0x0aba), board_ahci_mcp79 }, /* MCP79 */ 511441577efSTejun Heo { PCI_VDEVICE(NVIDIA, 0x0abb), board_ahci_mcp79 }, /* MCP79 */ 512441577efSTejun Heo { PCI_VDEVICE(NVIDIA, 0x0abc), board_ahci_mcp79 }, /* MCP79 */ 513441577efSTejun Heo { PCI_VDEVICE(NVIDIA, 0x0abd), board_ahci_mcp79 }, /* MCP79 */ 514441577efSTejun Heo { PCI_VDEVICE(NVIDIA, 0x0abe), board_ahci_mcp79 }, /* MCP79 */ 515441577efSTejun Heo { PCI_VDEVICE(NVIDIA, 0x0abf), board_ahci_mcp79 }, /* MCP79 */ 516441577efSTejun Heo { PCI_VDEVICE(NVIDIA, 0x0d84), board_ahci_mcp89 }, /* MCP89 */ 517441577efSTejun Heo { PCI_VDEVICE(NVIDIA, 0x0d85), board_ahci_mcp89 }, /* MCP89 */ 518441577efSTejun Heo { PCI_VDEVICE(NVIDIA, 0x0d86), board_ahci_mcp89 }, /* MCP89 */ 519441577efSTejun Heo { PCI_VDEVICE(NVIDIA, 0x0d87), board_ahci_mcp89 }, /* MCP89 */ 520441577efSTejun Heo { PCI_VDEVICE(NVIDIA, 0x0d88), board_ahci_mcp89 }, /* MCP89 */ 521441577efSTejun Heo { PCI_VDEVICE(NVIDIA, 0x0d89), board_ahci_mcp89 }, /* MCP89 */ 522441577efSTejun Heo { PCI_VDEVICE(NVIDIA, 0x0d8a), board_ahci_mcp89 }, /* MCP89 */ 523441577efSTejun Heo { PCI_VDEVICE(NVIDIA, 0x0d8b), board_ahci_mcp89 }, /* MCP89 */ 524441577efSTejun Heo { PCI_VDEVICE(NVIDIA, 0x0d8c), board_ahci_mcp89 }, /* MCP89 */ 525441577efSTejun Heo { PCI_VDEVICE(NVIDIA, 0x0d8d), board_ahci_mcp89 }, /* MCP89 */ 526441577efSTejun Heo { PCI_VDEVICE(NVIDIA, 0x0d8e), board_ahci_mcp89 }, /* MCP89 */ 527441577efSTejun Heo { PCI_VDEVICE(NVIDIA, 0x0d8f), board_ahci_mcp89 }, /* MCP89 */ 528c6fd2807SJeff Garzik 529c6fd2807SJeff Garzik /* SiS */ 53020e2de4aSTejun Heo { PCI_VDEVICE(SI, 0x1184), board_ahci }, /* SiS 966 */ 53120e2de4aSTejun Heo { PCI_VDEVICE(SI, 0x1185), board_ahci }, /* SiS 968 */ 53220e2de4aSTejun Heo { PCI_VDEVICE(SI, 0x0186), board_ahci }, /* SiS 968 */ 533c6fd2807SJeff Garzik 534318893e1SAlessandro Rubini /* ST Microelectronics */ 535318893e1SAlessandro Rubini { PCI_VDEVICE(STMICRO, 0xCC06), board_ahci }, /* ST ConneXt */ 536318893e1SAlessandro Rubini 537cd70c266SJeff Garzik /* Marvell */ 538cd70c266SJeff Garzik { PCI_VDEVICE(MARVELL, 0x6145), board_ahci_mv }, /* 6145 */ 539c40e7cb8SJose Alberto Reguero { PCI_VDEVICE(MARVELL, 0x6121), board_ahci_mv }, /* 6121 */ 54069fd3157SMyron Stowe { PCI_DEVICE(PCI_VENDOR_ID_MARVELL_EXT, 0x9123), 54110aca06cSAnssi Hannula .class = PCI_CLASS_STORAGE_SATA_AHCI, 54210aca06cSAnssi Hannula .class_mask = 0xffffff, 5435f173107STejun Heo .driver_data = board_ahci_yes_fbs }, /* 88se9128 */ 54469fd3157SMyron Stowe { PCI_DEVICE(PCI_VENDOR_ID_MARVELL_EXT, 0x9125), 545467b41c6SPer Jessen .driver_data = board_ahci_yes_fbs }, /* 88se9125 */ 546e098f5cbSSimon Guinot { PCI_DEVICE_SUB(PCI_VENDOR_ID_MARVELL_EXT, 0x9178, 547e098f5cbSSimon Guinot PCI_VENDOR_ID_MARVELL_EXT, 0x9170), 548e098f5cbSSimon Guinot .driver_data = board_ahci_yes_fbs }, /* 88se9170 */ 54969fd3157SMyron Stowe { PCI_DEVICE(PCI_VENDOR_ID_MARVELL_EXT, 0x917a), 550642d8925SMatt Johnson .driver_data = board_ahci_yes_fbs }, /* 88se9172 */ 551fcce9a35SGeorge Spelvin { PCI_DEVICE(PCI_VENDOR_ID_MARVELL_EXT, 0x9172), 552c5edfff9SMurali Karicheri .driver_data = board_ahci_yes_fbs }, /* 88se9182 */ 553c5edfff9SMurali Karicheri { PCI_DEVICE(PCI_VENDOR_ID_MARVELL_EXT, 0x9182), 554fcce9a35SGeorge Spelvin .driver_data = board_ahci_yes_fbs }, /* 88se9172 */ 55569fd3157SMyron Stowe { PCI_DEVICE(PCI_VENDOR_ID_MARVELL_EXT, 0x9192), 55617c60c6bSAlan Cox .driver_data = board_ahci_yes_fbs }, /* 88se9172 on some Gigabyte */ 557754a292fSAndreas Schrägle { PCI_DEVICE(PCI_VENDOR_ID_MARVELL_EXT, 0x91a0), 558754a292fSAndreas Schrägle .driver_data = board_ahci_yes_fbs }, 559a40cf3f3SJohannes Thumshirn { PCI_DEVICE(PCI_VENDOR_ID_MARVELL_EXT, 0x91a2), /* 88se91a2 */ 560a40cf3f3SJohannes Thumshirn .driver_data = board_ahci_yes_fbs }, 56169fd3157SMyron Stowe { PCI_DEVICE(PCI_VENDOR_ID_MARVELL_EXT, 0x91a3), 56250be5e36STejun Heo .driver_data = board_ahci_yes_fbs }, 5636d5278a6SSamir Benmendil { PCI_DEVICE(PCI_VENDOR_ID_MARVELL_EXT, 0x9230), 5646d5278a6SSamir Benmendil .driver_data = board_ahci_yes_fbs }, 56528b2182dSHans de Goede { PCI_DEVICE(PCI_VENDOR_ID_TTI, 0x0642), /* highpoint rocketraid 642L */ 56628b2182dSHans de Goede .driver_data = board_ahci_yes_fbs }, 56728b2182dSHans de Goede { PCI_DEVICE(PCI_VENDOR_ID_TTI, 0x0645), /* highpoint rocketraid 644L */ 568d2518365SJérôme Carretero .driver_data = board_ahci_yes_fbs }, 569cd70c266SJeff Garzik 570c77a036bSMark Nelson /* Promise */ 571c77a036bSMark Nelson { PCI_VDEVICE(PROMISE, 0x3f20), board_ahci }, /* PDC42819 */ 572b32bfc06SRomain Degez { PCI_VDEVICE(PROMISE, 0x3781), board_ahci }, /* FastTrak TX8660 ahci-mode */ 573c77a036bSMark Nelson 574c9703765SKeng-Yu Lin /* Asmedia */ 5757b4f6ecaSAlan Cox { PCI_VDEVICE(ASMEDIA, 0x0601), board_ahci }, /* ASM1060 */ 5767b4f6ecaSAlan Cox { PCI_VDEVICE(ASMEDIA, 0x0602), board_ahci }, /* ASM1060 */ 5777b4f6ecaSAlan Cox { PCI_VDEVICE(ASMEDIA, 0x0611), board_ahci }, /* ASM1061 */ 5787b4f6ecaSAlan Cox { PCI_VDEVICE(ASMEDIA, 0x0612), board_ahci }, /* ASM1062 */ 5790ce968f3SShawn Lin { PCI_VDEVICE(ASMEDIA, 0x0621), board_ahci }, /* ASM1061R */ 5800ce968f3SShawn Lin { PCI_VDEVICE(ASMEDIA, 0x0622), board_ahci }, /* ASM1062R */ 581c9703765SKeng-Yu Lin 58267809f85SLevente Kurusa /* 58366a7cbc3STejun Heo * Samsung SSDs found on some macbooks. NCQ times out if MSI is 58466a7cbc3STejun Heo * enabled. https://bugzilla.kernel.org/show_bug.cgi?id=60731 58567809f85SLevente Kurusa */ 58666a7cbc3STejun Heo { PCI_VDEVICE(SAMSUNG, 0x1600), board_ahci_nomsi }, 5872b21ef0aSTejun Heo { PCI_VDEVICE(SAMSUNG, 0xa800), board_ahci_nomsi }, 58867809f85SLevente Kurusa 5897f9c9f8eSHugh Daschbach /* Enmotus */ 5907f9c9f8eSHugh Daschbach { PCI_DEVICE(0x1c44, 0x8000), board_ahci }, 5917f9c9f8eSHugh Daschbach 592415ae2b5SJeff Garzik /* Generic, PCI class code for AHCI */ 593415ae2b5SJeff Garzik { PCI_ANY_ID, PCI_ANY_ID, PCI_ANY_ID, PCI_ANY_ID, 594c9f89475SConke Hu PCI_CLASS_STORAGE_SATA_AHCI, 0xffffff, board_ahci }, 595415ae2b5SJeff Garzik 596c6fd2807SJeff Garzik { } /* terminate list */ 597c6fd2807SJeff Garzik }; 598c6fd2807SJeff Garzik 599f1d848f9SMika Westerberg static const struct dev_pm_ops ahci_pci_pm_ops = { 600f1d848f9SMika Westerberg SET_SYSTEM_SLEEP_PM_OPS(ahci_pci_device_suspend, ahci_pci_device_resume) 60102e53293SMika Westerberg SET_RUNTIME_PM_OPS(ahci_pci_device_runtime_suspend, 60202e53293SMika Westerberg ahci_pci_device_runtime_resume, NULL) 603f1d848f9SMika Westerberg }; 604c6fd2807SJeff Garzik 605c6fd2807SJeff Garzik static struct pci_driver ahci_pci_driver = { 606c6fd2807SJeff Garzik .name = DRV_NAME, 607c6fd2807SJeff Garzik .id_table = ahci_pci_tbl, 608c6fd2807SJeff Garzik .probe = ahci_init_one, 60902e53293SMika Westerberg .remove = ahci_remove_one, 610*10a663a1SPrabhakar Kushwaha .shutdown = ahci_shutdown_one, 611f1d848f9SMika Westerberg .driver = { 612f1d848f9SMika Westerberg .pm = &ahci_pci_pm_ops, 613f1d848f9SMika Westerberg }, 614c6fd2807SJeff Garzik }; 615c6fd2807SJeff Garzik 6165219d653SJavier Martinez Canillas #if IS_ENABLED(CONFIG_PATA_MARVELL) 6175b66c829SAlan Cox static int marvell_enable; 6185b66c829SAlan Cox #else 6195b66c829SAlan Cox static int marvell_enable = 1; 6205b66c829SAlan Cox #endif 6215b66c829SAlan Cox module_param(marvell_enable, int, 0644); 6225b66c829SAlan Cox MODULE_PARM_DESC(marvell_enable, "Marvell SATA via AHCI (1 = enabled)"); 6235b66c829SAlan Cox 624b1a9585cSSrinivas Pandruvada static int mobile_lpm_policy = -1; 625ebb82e3cSHans de Goede module_param(mobile_lpm_policy, int, 0644); 626ebb82e3cSHans de Goede MODULE_PARM_DESC(mobile_lpm_policy, "Default LPM policy for mobile chipsets"); 6275b66c829SAlan Cox 628394d6e53SAnton Vorontsov static void ahci_pci_save_initial_config(struct pci_dev *pdev, 629394d6e53SAnton Vorontsov struct ahci_host_priv *hpriv) 630394d6e53SAnton Vorontsov { 631394d6e53SAnton Vorontsov if (pdev->vendor == PCI_VENDOR_ID_JMICRON && pdev->device == 0x2361) { 632394d6e53SAnton Vorontsov dev_info(&pdev->dev, "JMB361 has only one port\n"); 6339a23c1d6SAntoine Tenart hpriv->force_port_map = 1; 634394d6e53SAnton Vorontsov } 635394d6e53SAnton Vorontsov 636394d6e53SAnton Vorontsov /* 637394d6e53SAnton Vorontsov * Temporary Marvell 6145 hack: PATA port presence 638394d6e53SAnton Vorontsov * is asserted through the standard AHCI port 639394d6e53SAnton Vorontsov * presence register, as bit 4 (counting from 0) 640394d6e53SAnton Vorontsov */ 641394d6e53SAnton Vorontsov if (hpriv->flags & AHCI_HFLAG_MV_PATA) { 642394d6e53SAnton Vorontsov if (pdev->device == 0x6121) 6439a23c1d6SAntoine Tenart hpriv->mask_port_map = 0x3; 644394d6e53SAnton Vorontsov else 6459a23c1d6SAntoine Tenart hpriv->mask_port_map = 0xf; 646394d6e53SAnton Vorontsov dev_info(&pdev->dev, 647394d6e53SAnton Vorontsov "Disabling your PATA port. Use the boot option 'ahci.marvell_enable=0' to avoid this.\n"); 648394d6e53SAnton Vorontsov } 649394d6e53SAnton Vorontsov 650725c7b57SAntoine Ténart ahci_save_initial_config(&pdev->dev, hpriv); 651394d6e53SAnton Vorontsov } 652394d6e53SAnton Vorontsov 653781d6550SAnton Vorontsov static void ahci_pci_init_controller(struct ata_host *host) 654781d6550SAnton Vorontsov { 655781d6550SAnton Vorontsov struct ahci_host_priv *hpriv = host->private_data; 656781d6550SAnton Vorontsov struct pci_dev *pdev = to_pci_dev(host->dev); 657781d6550SAnton Vorontsov void __iomem *port_mmio; 658781d6550SAnton Vorontsov u32 tmp; 659c40e7cb8SJose Alberto Reguero int mv; 6602bcd866bSJeff Garzik 661417a1a6dSTejun Heo if (hpriv->flags & AHCI_HFLAG_MV_PATA) { 662c40e7cb8SJose Alberto Reguero if (pdev->device == 0x6121) 663c40e7cb8SJose Alberto Reguero mv = 2; 664c40e7cb8SJose Alberto Reguero else 665c40e7cb8SJose Alberto Reguero mv = 4; 666c40e7cb8SJose Alberto Reguero port_mmio = __ahci_port_base(host, mv); 667cd70c266SJeff Garzik 668cd70c266SJeff Garzik writel(0, port_mmio + PORT_IRQ_MASK); 669cd70c266SJeff Garzik 670cd70c266SJeff Garzik /* clear port IRQ */ 671cd70c266SJeff Garzik tmp = readl(port_mmio + PORT_IRQ_STAT); 672cd70c266SJeff Garzik VPRINTK("PORT_IRQ_STAT 0x%x\n", tmp); 673cd70c266SJeff Garzik if (tmp) 674cd70c266SJeff Garzik writel(tmp, port_mmio + PORT_IRQ_STAT); 675cd70c266SJeff Garzik } 676cd70c266SJeff Garzik 677781d6550SAnton Vorontsov ahci_init_controller(host); 678c6fd2807SJeff Garzik } 679c6fd2807SJeff Garzik 680cc0680a5STejun Heo static int ahci_vt8251_hardreset(struct ata_link *link, unsigned int *class, 681d4b2bab4STejun Heo unsigned long deadline) 682ad616ffbSTejun Heo { 683cc0680a5STejun Heo struct ata_port *ap = link->ap; 684039ece38SHans de Goede struct ahci_host_priv *hpriv = ap->host->private_data; 6859dadd45bSTejun Heo bool online; 686ad616ffbSTejun Heo int rc; 687ad616ffbSTejun Heo 688ad616ffbSTejun Heo DPRINTK("ENTER\n"); 689ad616ffbSTejun Heo 690fa89f53bSEvan Wang hpriv->stop_engine(ap); 691ad616ffbSTejun Heo 692cc0680a5STejun Heo rc = sata_link_hardreset(link, sata_ehc_deb_timing(&link->eh_context), 6939dadd45bSTejun Heo deadline, &online, NULL); 694ad616ffbSTejun Heo 695039ece38SHans de Goede hpriv->start_engine(ap); 696ad616ffbSTejun Heo 697ad616ffbSTejun Heo DPRINTK("EXIT, rc=%d, class=%u\n", rc, *class); 698ad616ffbSTejun Heo 699ad616ffbSTejun Heo /* vt8251 doesn't clear BSY on signature FIS reception, 700ad616ffbSTejun Heo * request follow-up softreset. 701ad616ffbSTejun Heo */ 7029dadd45bSTejun Heo return online ? -EAGAIN : rc; 703ad616ffbSTejun Heo } 704ad616ffbSTejun Heo 705edc93052STejun Heo static int ahci_p5wdh_hardreset(struct ata_link *link, unsigned int *class, 706edc93052STejun Heo unsigned long deadline) 707edc93052STejun Heo { 708edc93052STejun Heo struct ata_port *ap = link->ap; 709edc93052STejun Heo struct ahci_port_priv *pp = ap->private_data; 710039ece38SHans de Goede struct ahci_host_priv *hpriv = ap->host->private_data; 711edc93052STejun Heo u8 *d2h_fis = pp->rx_fis + RX_FIS_D2H_REG; 712edc93052STejun Heo struct ata_taskfile tf; 7139dadd45bSTejun Heo bool online; 714edc93052STejun Heo int rc; 715edc93052STejun Heo 716fa89f53bSEvan Wang hpriv->stop_engine(ap); 717edc93052STejun Heo 718edc93052STejun Heo /* clear D2H reception area to properly wait for D2H FIS */ 719edc93052STejun Heo ata_tf_init(link->device, &tf); 7209bbb1b0eSSergei Shtylyov tf.command = ATA_BUSY; 721edc93052STejun Heo ata_tf_to_fis(&tf, 0, 0, d2h_fis); 722edc93052STejun Heo 723edc93052STejun Heo rc = sata_link_hardreset(link, sata_ehc_deb_timing(&link->eh_context), 7249dadd45bSTejun Heo deadline, &online, NULL); 725edc93052STejun Heo 726039ece38SHans de Goede hpriv->start_engine(ap); 727edc93052STejun Heo 728edc93052STejun Heo /* The pseudo configuration device on SIMG4726 attached to 729edc93052STejun Heo * ASUS P5W-DH Deluxe doesn't send signature FIS after 730edc93052STejun Heo * hardreset if no device is attached to the first downstream 731edc93052STejun Heo * port && the pseudo device locks up on SRST w/ PMP==0. To 732edc93052STejun Heo * work around this, wait for !BSY only briefly. If BSY isn't 733edc93052STejun Heo * cleared, perform CLO and proceed to IDENTIFY (achieved by 734edc93052STejun Heo * ATA_LFLAG_NO_SRST and ATA_LFLAG_ASSUME_ATA). 735edc93052STejun Heo * 736edc93052STejun Heo * Wait for two seconds. Devices attached to downstream port 737edc93052STejun Heo * which can't process the following IDENTIFY after this will 738edc93052STejun Heo * have to be reset again. For most cases, this should 739edc93052STejun Heo * suffice while making probing snappish enough. 740edc93052STejun Heo */ 7419dadd45bSTejun Heo if (online) { 7429dadd45bSTejun Heo rc = ata_wait_after_reset(link, jiffies + 2 * HZ, 7439dadd45bSTejun Heo ahci_check_ready); 744edc93052STejun Heo if (rc) 74578d5ae39SShane Huang ahci_kick_engine(ap); 7469dadd45bSTejun Heo } 7479dadd45bSTejun Heo return rc; 748edc93052STejun Heo } 749edc93052STejun Heo 750dbfe8ef5SDan Williams /* 751dbfe8ef5SDan Williams * ahci_avn_hardreset - attempt more aggressive recovery of Avoton ports. 752dbfe8ef5SDan Williams * 753dbfe8ef5SDan Williams * It has been observed with some SSDs that the timing of events in the 754dbfe8ef5SDan Williams * link synchronization phase can leave the port in a state that can not 755dbfe8ef5SDan Williams * be recovered by a SATA-hard-reset alone. The failing signature is 756dbfe8ef5SDan Williams * SStatus.DET stuck at 1 ("Device presence detected but Phy 757dbfe8ef5SDan Williams * communication not established"). It was found that unloading and 758dbfe8ef5SDan Williams * reloading the driver when this problem occurs allows the drive 759dbfe8ef5SDan Williams * connection to be recovered (DET advanced to 0x3). The critical 760dbfe8ef5SDan Williams * component of reloading the driver is that the port state machines are 761dbfe8ef5SDan Williams * reset by bouncing "port enable" in the AHCI PCS configuration 762dbfe8ef5SDan Williams * register. So, reproduce that effect by bouncing a port whenever we 763dbfe8ef5SDan Williams * see DET==1 after a reset. 764dbfe8ef5SDan Williams */ 765dbfe8ef5SDan Williams static int ahci_avn_hardreset(struct ata_link *link, unsigned int *class, 766dbfe8ef5SDan Williams unsigned long deadline) 767dbfe8ef5SDan Williams { 768dbfe8ef5SDan Williams const unsigned long *timing = sata_ehc_deb_timing(&link->eh_context); 769dbfe8ef5SDan Williams struct ata_port *ap = link->ap; 770dbfe8ef5SDan Williams struct ahci_port_priv *pp = ap->private_data; 771dbfe8ef5SDan Williams struct ahci_host_priv *hpriv = ap->host->private_data; 772dbfe8ef5SDan Williams u8 *d2h_fis = pp->rx_fis + RX_FIS_D2H_REG; 773dbfe8ef5SDan Williams unsigned long tmo = deadline - jiffies; 774dbfe8ef5SDan Williams struct ata_taskfile tf; 775dbfe8ef5SDan Williams bool online; 776dbfe8ef5SDan Williams int rc, i; 777dbfe8ef5SDan Williams 778dbfe8ef5SDan Williams DPRINTK("ENTER\n"); 779dbfe8ef5SDan Williams 780fa89f53bSEvan Wang hpriv->stop_engine(ap); 781dbfe8ef5SDan Williams 782dbfe8ef5SDan Williams for (i = 0; i < 2; i++) { 783dbfe8ef5SDan Williams u16 val; 784dbfe8ef5SDan Williams u32 sstatus; 785dbfe8ef5SDan Williams int port = ap->port_no; 786dbfe8ef5SDan Williams struct ata_host *host = ap->host; 787dbfe8ef5SDan Williams struct pci_dev *pdev = to_pci_dev(host->dev); 788dbfe8ef5SDan Williams 789dbfe8ef5SDan Williams /* clear D2H reception area to properly wait for D2H FIS */ 790dbfe8ef5SDan Williams ata_tf_init(link->device, &tf); 791dbfe8ef5SDan Williams tf.command = ATA_BUSY; 792dbfe8ef5SDan Williams ata_tf_to_fis(&tf, 0, 0, d2h_fis); 793dbfe8ef5SDan Williams 794dbfe8ef5SDan Williams rc = sata_link_hardreset(link, timing, deadline, &online, 795dbfe8ef5SDan Williams ahci_check_ready); 796dbfe8ef5SDan Williams 797dbfe8ef5SDan Williams if (sata_scr_read(link, SCR_STATUS, &sstatus) != 0 || 798dbfe8ef5SDan Williams (sstatus & 0xf) != 1) 799dbfe8ef5SDan Williams break; 800dbfe8ef5SDan Williams 801dbfe8ef5SDan Williams ata_link_printk(link, KERN_INFO, "avn bounce port%d\n", 802dbfe8ef5SDan Williams port); 803dbfe8ef5SDan Williams 804dbfe8ef5SDan Williams pci_read_config_word(pdev, 0x92, &val); 805dbfe8ef5SDan Williams val &= ~(1 << port); 806dbfe8ef5SDan Williams pci_write_config_word(pdev, 0x92, val); 807dbfe8ef5SDan Williams ata_msleep(ap, 1000); 808dbfe8ef5SDan Williams val |= 1 << port; 809dbfe8ef5SDan Williams pci_write_config_word(pdev, 0x92, val); 810dbfe8ef5SDan Williams deadline += tmo; 811dbfe8ef5SDan Williams } 812dbfe8ef5SDan Williams 813dbfe8ef5SDan Williams hpriv->start_engine(ap); 814dbfe8ef5SDan Williams 815dbfe8ef5SDan Williams if (online) 816dbfe8ef5SDan Williams *class = ahci_dev_classify(ap); 817dbfe8ef5SDan Williams 818dbfe8ef5SDan Williams DPRINTK("EXIT, rc=%d, class=%u\n", rc, *class); 819dbfe8ef5SDan Williams return rc; 820dbfe8ef5SDan Williams } 821dbfe8ef5SDan Williams 822dbfe8ef5SDan Williams 82302e53293SMika Westerberg #ifdef CONFIG_PM 82402e53293SMika Westerberg static void ahci_pci_disable_interrupts(struct ata_host *host) 825c6fd2807SJeff Garzik { 8269b10ae86STejun Heo struct ahci_host_priv *hpriv = host->private_data; 827d8993349SAnton Vorontsov void __iomem *mmio = hpriv->mmio; 828c6fd2807SJeff Garzik u32 ctl; 829c6fd2807SJeff Garzik 830c6fd2807SJeff Garzik /* AHCI spec rev1.1 section 8.3.3: 831c6fd2807SJeff Garzik * Software must disable interrupts prior to requesting a 832c6fd2807SJeff Garzik * transition of the HBA to D3 state. 833c6fd2807SJeff Garzik */ 834c6fd2807SJeff Garzik ctl = readl(mmio + HOST_CTL); 835c6fd2807SJeff Garzik ctl &= ~HOST_IRQ_EN; 836c6fd2807SJeff Garzik writel(ctl, mmio + HOST_CTL); 837c6fd2807SJeff Garzik readl(mmio + HOST_CTL); /* flush */ 83802e53293SMika Westerberg } 839f1d848f9SMika Westerberg 84002e53293SMika Westerberg static int ahci_pci_device_runtime_suspend(struct device *dev) 84102e53293SMika Westerberg { 84202e53293SMika Westerberg struct pci_dev *pdev = to_pci_dev(dev); 84302e53293SMika Westerberg struct ata_host *host = pci_get_drvdata(pdev); 84402e53293SMika Westerberg 84502e53293SMika Westerberg ahci_pci_disable_interrupts(host); 84602e53293SMika Westerberg return 0; 84702e53293SMika Westerberg } 84802e53293SMika Westerberg 84902e53293SMika Westerberg static int ahci_pci_device_runtime_resume(struct device *dev) 85002e53293SMika Westerberg { 85102e53293SMika Westerberg struct pci_dev *pdev = to_pci_dev(dev); 85202e53293SMika Westerberg struct ata_host *host = pci_get_drvdata(pdev); 85302e53293SMika Westerberg int rc; 85402e53293SMika Westerberg 855c312ef17SDan Williams rc = ahci_reset_controller(host); 85602e53293SMika Westerberg if (rc) 85702e53293SMika Westerberg return rc; 85802e53293SMika Westerberg ahci_pci_init_controller(host); 85902e53293SMika Westerberg return 0; 86002e53293SMika Westerberg } 86102e53293SMika Westerberg 86202e53293SMika Westerberg #ifdef CONFIG_PM_SLEEP 86302e53293SMika Westerberg static int ahci_pci_device_suspend(struct device *dev) 86402e53293SMika Westerberg { 86502e53293SMika Westerberg struct pci_dev *pdev = to_pci_dev(dev); 86602e53293SMika Westerberg struct ata_host *host = pci_get_drvdata(pdev); 86702e53293SMika Westerberg struct ahci_host_priv *hpriv = host->private_data; 86802e53293SMika Westerberg 86902e53293SMika Westerberg if (hpriv->flags & AHCI_HFLAG_NO_SUSPEND) { 87002e53293SMika Westerberg dev_err(&pdev->dev, 87102e53293SMika Westerberg "BIOS update required for suspend/resume\n"); 87202e53293SMika Westerberg return -EIO; 87302e53293SMika Westerberg } 87402e53293SMika Westerberg 87502e53293SMika Westerberg ahci_pci_disable_interrupts(host); 876f1d848f9SMika Westerberg return ata_host_suspend(host, PMSG_SUSPEND); 877c6fd2807SJeff Garzik } 878c6fd2807SJeff Garzik 879f1d848f9SMika Westerberg static int ahci_pci_device_resume(struct device *dev) 880c6fd2807SJeff Garzik { 881f1d848f9SMika Westerberg struct pci_dev *pdev = to_pci_dev(dev); 8820a86e1c8SJingoo Han struct ata_host *host = pci_get_drvdata(pdev); 883c6fd2807SJeff Garzik int rc; 884c6fd2807SJeff Garzik 885cb85696dSJames Laird /* Apple BIOS helpfully mangles the registers on resume */ 886cb85696dSJames Laird if (is_mcp89_apple(pdev)) 887cb85696dSJames Laird ahci_mcp89_apple_enable(pdev); 888cb85696dSJames Laird 889c6fd2807SJeff Garzik if (pdev->dev.power.power_state.event == PM_EVENT_SUSPEND) { 890c312ef17SDan Williams rc = ahci_reset_controller(host); 891c6fd2807SJeff Garzik if (rc) 892c6fd2807SJeff Garzik return rc; 893c6fd2807SJeff Garzik 894781d6550SAnton Vorontsov ahci_pci_init_controller(host); 895c6fd2807SJeff Garzik } 896c6fd2807SJeff Garzik 897cca3974eSJeff Garzik ata_host_resume(host); 898c6fd2807SJeff Garzik 899c6fd2807SJeff Garzik return 0; 900c6fd2807SJeff Garzik } 901438ac6d5STejun Heo #endif 902c6fd2807SJeff Garzik 90302e53293SMika Westerberg #endif /* CONFIG_PM */ 90402e53293SMika Westerberg 9054447d351STejun Heo static int ahci_configure_dma_masks(struct pci_dev *pdev, int using_dac) 906c6fd2807SJeff Garzik { 907b1716871SChristoph Hellwig const int dma_bits = using_dac ? 64 : 32; 908c6fd2807SJeff Garzik int rc; 909c6fd2807SJeff Garzik 910318893e1SAlessandro Rubini /* 911318893e1SAlessandro Rubini * If the device fixup already set the dma_mask to some non-standard 912318893e1SAlessandro Rubini * value, don't extend it here. This happens on STA2X11, for example. 913b1716871SChristoph Hellwig * 914b1716871SChristoph Hellwig * XXX: manipulating the DMA mask from platform code is completely 915a7ba70f1SNicolas Saenz Julienne * bogus, platform code should use dev->bus_dma_limit instead.. 916318893e1SAlessandro Rubini */ 917318893e1SAlessandro Rubini if (pdev->dma_mask && pdev->dma_mask < DMA_BIT_MASK(32)) 918318893e1SAlessandro Rubini return 0; 919318893e1SAlessandro Rubini 920b1716871SChristoph Hellwig rc = dma_set_mask_and_coherent(&pdev->dev, DMA_BIT_MASK(dma_bits)); 921b1716871SChristoph Hellwig if (rc) 922b1716871SChristoph Hellwig dev_err(&pdev->dev, "DMA enable failed\n"); 923c6fd2807SJeff Garzik return rc; 924c6fd2807SJeff Garzik } 925c6fd2807SJeff Garzik 926439fcaecSAnton Vorontsov static void ahci_pci_print_info(struct ata_host *host) 927439fcaecSAnton Vorontsov { 928439fcaecSAnton Vorontsov struct pci_dev *pdev = to_pci_dev(host->dev); 929439fcaecSAnton Vorontsov u16 cc; 930439fcaecSAnton Vorontsov const char *scc_s; 931439fcaecSAnton Vorontsov 932439fcaecSAnton Vorontsov pci_read_config_word(pdev, 0x0a, &cc); 933439fcaecSAnton Vorontsov if (cc == PCI_CLASS_STORAGE_IDE) 934439fcaecSAnton Vorontsov scc_s = "IDE"; 935439fcaecSAnton Vorontsov else if (cc == PCI_CLASS_STORAGE_SATA) 936439fcaecSAnton Vorontsov scc_s = "SATA"; 937439fcaecSAnton Vorontsov else if (cc == PCI_CLASS_STORAGE_RAID) 938439fcaecSAnton Vorontsov scc_s = "RAID"; 939439fcaecSAnton Vorontsov else 940439fcaecSAnton Vorontsov scc_s = "unknown"; 941439fcaecSAnton Vorontsov 942439fcaecSAnton Vorontsov ahci_print_info(host, scc_s); 943439fcaecSAnton Vorontsov } 944439fcaecSAnton Vorontsov 945edc93052STejun Heo /* On ASUS P5W DH Deluxe, the second port of PCI device 00:1f.2 is 946edc93052STejun Heo * hardwired to on-board SIMG 4726. The chipset is ICH8 and doesn't 947edc93052STejun Heo * support PMP and the 4726 either directly exports the device 948edc93052STejun Heo * attached to the first downstream port or acts as a hardware storage 949edc93052STejun Heo * controller and emulate a single ATA device (can be RAID 0/1 or some 950edc93052STejun Heo * other configuration). 951edc93052STejun Heo * 952edc93052STejun Heo * When there's no device attached to the first downstream port of the 953edc93052STejun Heo * 4726, "Config Disk" appears, which is a pseudo ATA device to 954edc93052STejun Heo * configure the 4726. However, ATA emulation of the device is very 955edc93052STejun Heo * lame. It doesn't send signature D2H Reg FIS after the initial 956edc93052STejun Heo * hardreset, pukes on SRST w/ PMP==0 and has bunch of other issues. 957edc93052STejun Heo * 958edc93052STejun Heo * The following function works around the problem by always using 959edc93052STejun Heo * hardreset on the port and not depending on receiving signature FIS 960edc93052STejun Heo * afterward. If signature FIS isn't received soon, ATA class is 961edc93052STejun Heo * assumed without follow-up softreset. 962edc93052STejun Heo */ 963edc93052STejun Heo static void ahci_p5wdh_workaround(struct ata_host *host) 964edc93052STejun Heo { 9651bd06867SMathias Krause static const struct dmi_system_id sysids[] = { 966edc93052STejun Heo { 967edc93052STejun Heo .ident = "P5W DH Deluxe", 968edc93052STejun Heo .matches = { 969edc93052STejun Heo DMI_MATCH(DMI_SYS_VENDOR, 970edc93052STejun Heo "ASUSTEK COMPUTER INC"), 971edc93052STejun Heo DMI_MATCH(DMI_PRODUCT_NAME, "P5W DH Deluxe"), 972edc93052STejun Heo }, 973edc93052STejun Heo }, 974edc93052STejun Heo { } 975edc93052STejun Heo }; 976edc93052STejun Heo struct pci_dev *pdev = to_pci_dev(host->dev); 977edc93052STejun Heo 978edc93052STejun Heo if (pdev->bus->number == 0 && pdev->devfn == PCI_DEVFN(0x1f, 2) && 979edc93052STejun Heo dmi_check_system(sysids)) { 980edc93052STejun Heo struct ata_port *ap = host->ports[1]; 981edc93052STejun Heo 982a44fec1fSJoe Perches dev_info(&pdev->dev, 983a44fec1fSJoe Perches "enabling ASUS P5W DH Deluxe on-board SIMG4726 workaround\n"); 984edc93052STejun Heo 985edc93052STejun Heo ap->ops = &ahci_p5wdh_ops; 986edc93052STejun Heo ap->link.flags |= ATA_LFLAG_NO_SRST | ATA_LFLAG_ASSUME_ATA; 987edc93052STejun Heo } 988edc93052STejun Heo } 989edc93052STejun Heo 990cb85696dSJames Laird /* 991cb85696dSJames Laird * Macbook7,1 firmware forcibly disables MCP89 AHCI and changes PCI ID when 992cb85696dSJames Laird * booting in BIOS compatibility mode. We restore the registers but not ID. 993cb85696dSJames Laird */ 994cb85696dSJames Laird static void ahci_mcp89_apple_enable(struct pci_dev *pdev) 995cb85696dSJames Laird { 996cb85696dSJames Laird u32 val; 997cb85696dSJames Laird 998cb85696dSJames Laird printk(KERN_INFO "ahci: enabling MCP89 AHCI mode\n"); 999cb85696dSJames Laird 1000cb85696dSJames Laird pci_read_config_dword(pdev, 0xf8, &val); 1001cb85696dSJames Laird val |= 1 << 0x1b; 1002cb85696dSJames Laird /* the following changes the device ID, but appears not to affect function */ 1003cb85696dSJames Laird /* val = (val & ~0xf0000000) | 0x80000000; */ 1004cb85696dSJames Laird pci_write_config_dword(pdev, 0xf8, val); 1005cb85696dSJames Laird 1006cb85696dSJames Laird pci_read_config_dword(pdev, 0x54c, &val); 1007cb85696dSJames Laird val |= 1 << 0xc; 1008cb85696dSJames Laird pci_write_config_dword(pdev, 0x54c, val); 1009cb85696dSJames Laird 1010cb85696dSJames Laird pci_read_config_dword(pdev, 0x4a4, &val); 1011cb85696dSJames Laird val &= 0xff; 1012cb85696dSJames Laird val |= 0x01060100; 1013cb85696dSJames Laird pci_write_config_dword(pdev, 0x4a4, val); 1014cb85696dSJames Laird 1015cb85696dSJames Laird pci_read_config_dword(pdev, 0x54c, &val); 1016cb85696dSJames Laird val &= ~(1 << 0xc); 1017cb85696dSJames Laird pci_write_config_dword(pdev, 0x54c, val); 1018cb85696dSJames Laird 1019cb85696dSJames Laird pci_read_config_dword(pdev, 0xf8, &val); 1020cb85696dSJames Laird val &= ~(1 << 0x1b); 1021cb85696dSJames Laird pci_write_config_dword(pdev, 0xf8, val); 1022cb85696dSJames Laird } 1023cb85696dSJames Laird 1024cb85696dSJames Laird static bool is_mcp89_apple(struct pci_dev *pdev) 1025cb85696dSJames Laird { 1026cb85696dSJames Laird return pdev->vendor == PCI_VENDOR_ID_NVIDIA && 1027cb85696dSJames Laird pdev->device == PCI_DEVICE_ID_NVIDIA_NFORCE_MCP89_SATA && 1028cb85696dSJames Laird pdev->subsystem_vendor == PCI_VENDOR_ID_APPLE && 1029cb85696dSJames Laird pdev->subsystem_device == 0xcb89; 1030cb85696dSJames Laird } 1031cb85696dSJames Laird 10322fcad9d2STejun Heo /* only some SB600 ahci controllers can do 64bit DMA */ 10332fcad9d2STejun Heo static bool ahci_sb600_enable_64bit(struct pci_dev *pdev) 103458a09b38SShane Huang { 103558a09b38SShane Huang static const struct dmi_system_id sysids[] = { 103603d783bfSTejun Heo /* 103703d783bfSTejun Heo * The oldest version known to be broken is 0901 and 103803d783bfSTejun Heo * working is 1501 which was released on 2007-10-26. 10392fcad9d2STejun Heo * Enable 64bit DMA on 1501 and anything newer. 10402fcad9d2STejun Heo * 104103d783bfSTejun Heo * Please read bko#9412 for more info. 104203d783bfSTejun Heo */ 104358a09b38SShane Huang { 104458a09b38SShane Huang .ident = "ASUS M2A-VM", 104558a09b38SShane Huang .matches = { 104658a09b38SShane Huang DMI_MATCH(DMI_BOARD_VENDOR, 104758a09b38SShane Huang "ASUSTeK Computer INC."), 104858a09b38SShane Huang DMI_MATCH(DMI_BOARD_NAME, "M2A-VM"), 104958a09b38SShane Huang }, 105003d783bfSTejun Heo .driver_data = "20071026", /* yyyymmdd */ 105158a09b38SShane Huang }, 1052e65cc194SMark Nelson /* 1053e65cc194SMark Nelson * All BIOS versions for the MSI K9A2 Platinum (MS-7376) 1054e65cc194SMark Nelson * support 64bit DMA. 1055e65cc194SMark Nelson * 1056e65cc194SMark Nelson * BIOS versions earlier than 1.5 had the Manufacturer DMI 1057e65cc194SMark Nelson * fields as "MICRO-STAR INTERANTIONAL CO.,LTD". 1058e65cc194SMark Nelson * This spelling mistake was fixed in BIOS version 1.5, so 1059e65cc194SMark Nelson * 1.5 and later have the Manufacturer as 1060e65cc194SMark Nelson * "MICRO-STAR INTERNATIONAL CO.,LTD". 1061e65cc194SMark Nelson * So try to match on DMI_BOARD_VENDOR of "MICRO-STAR INTER". 1062e65cc194SMark Nelson * 1063e65cc194SMark Nelson * BIOS versions earlier than 1.9 had a Board Product Name 1064e65cc194SMark Nelson * DMI field of "MS-7376". This was changed to be 1065e65cc194SMark Nelson * "K9A2 Platinum (MS-7376)" in version 1.9, but we can still 1066e65cc194SMark Nelson * match on DMI_BOARD_NAME of "MS-7376". 1067e65cc194SMark Nelson */ 1068e65cc194SMark Nelson { 1069e65cc194SMark Nelson .ident = "MSI K9A2 Platinum", 1070e65cc194SMark Nelson .matches = { 1071e65cc194SMark Nelson DMI_MATCH(DMI_BOARD_VENDOR, 1072e65cc194SMark Nelson "MICRO-STAR INTER"), 1073e65cc194SMark Nelson DMI_MATCH(DMI_BOARD_NAME, "MS-7376"), 1074e65cc194SMark Nelson }, 1075e65cc194SMark Nelson }, 10763c4aa91fSMark Nelson /* 1077ff0173c1SMark Nelson * All BIOS versions for the MSI K9AGM2 (MS-7327) support 1078ff0173c1SMark Nelson * 64bit DMA. 1079ff0173c1SMark Nelson * 1080ff0173c1SMark Nelson * This board also had the typo mentioned above in the 1081ff0173c1SMark Nelson * Manufacturer DMI field (fixed in BIOS version 1.5), so 1082ff0173c1SMark Nelson * match on DMI_BOARD_VENDOR of "MICRO-STAR INTER" again. 1083ff0173c1SMark Nelson */ 1084ff0173c1SMark Nelson { 1085ff0173c1SMark Nelson .ident = "MSI K9AGM2", 1086ff0173c1SMark Nelson .matches = { 1087ff0173c1SMark Nelson DMI_MATCH(DMI_BOARD_VENDOR, 1088ff0173c1SMark Nelson "MICRO-STAR INTER"), 1089ff0173c1SMark Nelson DMI_MATCH(DMI_BOARD_NAME, "MS-7327"), 1090ff0173c1SMark Nelson }, 1091ff0173c1SMark Nelson }, 1092ff0173c1SMark Nelson /* 10933c4aa91fSMark Nelson * All BIOS versions for the Asus M3A support 64bit DMA. 10943c4aa91fSMark Nelson * (all release versions from 0301 to 1206 were tested) 10953c4aa91fSMark Nelson */ 10963c4aa91fSMark Nelson { 10973c4aa91fSMark Nelson .ident = "ASUS M3A", 10983c4aa91fSMark Nelson .matches = { 10993c4aa91fSMark Nelson DMI_MATCH(DMI_BOARD_VENDOR, 11003c4aa91fSMark Nelson "ASUSTeK Computer INC."), 11013c4aa91fSMark Nelson DMI_MATCH(DMI_BOARD_NAME, "M3A"), 11023c4aa91fSMark Nelson }, 11033c4aa91fSMark Nelson }, 110458a09b38SShane Huang { } 110558a09b38SShane Huang }; 110603d783bfSTejun Heo const struct dmi_system_id *match; 11072fcad9d2STejun Heo int year, month, date; 11082fcad9d2STejun Heo char buf[9]; 110958a09b38SShane Huang 111003d783bfSTejun Heo match = dmi_first_match(sysids); 111158a09b38SShane Huang if (pdev->bus->number != 0 || pdev->devfn != PCI_DEVFN(0x12, 0) || 111203d783bfSTejun Heo !match) 111358a09b38SShane Huang return false; 111458a09b38SShane Huang 1115e65cc194SMark Nelson if (!match->driver_data) 1116e65cc194SMark Nelson goto enable_64bit; 1117e65cc194SMark Nelson 111803d783bfSTejun Heo dmi_get_date(DMI_BIOS_DATE, &year, &month, &date); 111903d783bfSTejun Heo snprintf(buf, sizeof(buf), "%04d%02d%02d", year, month, date); 112003d783bfSTejun Heo 1121e65cc194SMark Nelson if (strcmp(buf, match->driver_data) >= 0) 1122e65cc194SMark Nelson goto enable_64bit; 1123e65cc194SMark Nelson else { 1124a44fec1fSJoe Perches dev_warn(&pdev->dev, 1125a44fec1fSJoe Perches "%s: BIOS too old, forcing 32bit DMA, update BIOS\n", 1126a44fec1fSJoe Perches match->ident); 11272fcad9d2STejun Heo return false; 11282fcad9d2STejun Heo } 1129e65cc194SMark Nelson 1130e65cc194SMark Nelson enable_64bit: 1131a44fec1fSJoe Perches dev_warn(&pdev->dev, "%s: enabling 64bit DMA\n", match->ident); 1132e65cc194SMark Nelson return true; 113358a09b38SShane Huang } 113458a09b38SShane Huang 11351fd68434SRafael J. Wysocki static bool ahci_broken_system_poweroff(struct pci_dev *pdev) 11361fd68434SRafael J. Wysocki { 11371fd68434SRafael J. Wysocki static const struct dmi_system_id broken_systems[] = { 11381fd68434SRafael J. Wysocki { 11391fd68434SRafael J. Wysocki .ident = "HP Compaq nx6310", 11401fd68434SRafael J. Wysocki .matches = { 11411fd68434SRafael J. Wysocki DMI_MATCH(DMI_SYS_VENDOR, "Hewlett-Packard"), 11421fd68434SRafael J. Wysocki DMI_MATCH(DMI_PRODUCT_NAME, "HP Compaq nx6310"), 11431fd68434SRafael J. Wysocki }, 11441fd68434SRafael J. Wysocki /* PCI slot number of the controller */ 11451fd68434SRafael J. Wysocki .driver_data = (void *)0x1FUL, 11461fd68434SRafael J. Wysocki }, 1147d2f9c061SMaciej Rutecki { 1148d2f9c061SMaciej Rutecki .ident = "HP Compaq 6720s", 1149d2f9c061SMaciej Rutecki .matches = { 1150d2f9c061SMaciej Rutecki DMI_MATCH(DMI_SYS_VENDOR, "Hewlett-Packard"), 1151d2f9c061SMaciej Rutecki DMI_MATCH(DMI_PRODUCT_NAME, "HP Compaq 6720s"), 1152d2f9c061SMaciej Rutecki }, 1153d2f9c061SMaciej Rutecki /* PCI slot number of the controller */ 1154d2f9c061SMaciej Rutecki .driver_data = (void *)0x1FUL, 1155d2f9c061SMaciej Rutecki }, 11561fd68434SRafael J. Wysocki 11571fd68434SRafael J. Wysocki { } /* terminate list */ 11581fd68434SRafael J. Wysocki }; 11591fd68434SRafael J. Wysocki const struct dmi_system_id *dmi = dmi_first_match(broken_systems); 11601fd68434SRafael J. Wysocki 11611fd68434SRafael J. Wysocki if (dmi) { 11621fd68434SRafael J. Wysocki unsigned long slot = (unsigned long)dmi->driver_data; 11631fd68434SRafael J. Wysocki /* apply the quirk only to on-board controllers */ 11641fd68434SRafael J. Wysocki return slot == PCI_SLOT(pdev->devfn); 11651fd68434SRafael J. Wysocki } 11661fd68434SRafael J. Wysocki 11671fd68434SRafael J. Wysocki return false; 11681fd68434SRafael J. Wysocki } 11691fd68434SRafael J. Wysocki 11709b10ae86STejun Heo static bool ahci_broken_suspend(struct pci_dev *pdev) 11719b10ae86STejun Heo { 11729b10ae86STejun Heo static const struct dmi_system_id sysids[] = { 11739b10ae86STejun Heo /* 11749b10ae86STejun Heo * On HP dv[4-6] and HDX18 with earlier BIOSen, link 11759b10ae86STejun Heo * to the harddisk doesn't become online after 11769b10ae86STejun Heo * resuming from STR. Warn and fail suspend. 11779deb3431STejun Heo * 11789deb3431STejun Heo * http://bugzilla.kernel.org/show_bug.cgi?id=12276 11799deb3431STejun Heo * 11809deb3431STejun Heo * Use dates instead of versions to match as HP is 11819deb3431STejun Heo * apparently recycling both product and version 11829deb3431STejun Heo * strings. 11839deb3431STejun Heo * 11849deb3431STejun Heo * http://bugzilla.kernel.org/show_bug.cgi?id=15462 11859b10ae86STejun Heo */ 11869b10ae86STejun Heo { 11879b10ae86STejun Heo .ident = "dv4", 11889b10ae86STejun Heo .matches = { 11899b10ae86STejun Heo DMI_MATCH(DMI_SYS_VENDOR, "Hewlett-Packard"), 11909b10ae86STejun Heo DMI_MATCH(DMI_PRODUCT_NAME, 11919b10ae86STejun Heo "HP Pavilion dv4 Notebook PC"), 11929b10ae86STejun Heo }, 11939deb3431STejun Heo .driver_data = "20090105", /* F.30 */ 11949b10ae86STejun Heo }, 11959b10ae86STejun Heo { 11969b10ae86STejun Heo .ident = "dv5", 11979b10ae86STejun Heo .matches = { 11989b10ae86STejun Heo DMI_MATCH(DMI_SYS_VENDOR, "Hewlett-Packard"), 11999b10ae86STejun Heo DMI_MATCH(DMI_PRODUCT_NAME, 12009b10ae86STejun Heo "HP Pavilion dv5 Notebook PC"), 12019b10ae86STejun Heo }, 12029deb3431STejun Heo .driver_data = "20090506", /* F.16 */ 12039b10ae86STejun Heo }, 12049b10ae86STejun Heo { 12059b10ae86STejun Heo .ident = "dv6", 12069b10ae86STejun Heo .matches = { 12079b10ae86STejun Heo DMI_MATCH(DMI_SYS_VENDOR, "Hewlett-Packard"), 12089b10ae86STejun Heo DMI_MATCH(DMI_PRODUCT_NAME, 12099b10ae86STejun Heo "HP Pavilion dv6 Notebook PC"), 12109b10ae86STejun Heo }, 12119deb3431STejun Heo .driver_data = "20090423", /* F.21 */ 12129b10ae86STejun Heo }, 12139b10ae86STejun Heo { 12149b10ae86STejun Heo .ident = "HDX18", 12159b10ae86STejun Heo .matches = { 12169b10ae86STejun Heo DMI_MATCH(DMI_SYS_VENDOR, "Hewlett-Packard"), 12179b10ae86STejun Heo DMI_MATCH(DMI_PRODUCT_NAME, 12189b10ae86STejun Heo "HP HDX18 Notebook PC"), 12199b10ae86STejun Heo }, 12209deb3431STejun Heo .driver_data = "20090430", /* F.23 */ 12219b10ae86STejun Heo }, 1222cedc9bf9STejun Heo /* 1223cedc9bf9STejun Heo * Acer eMachines G725 has the same problem. BIOS 1224cedc9bf9STejun Heo * V1.03 is known to be broken. V3.04 is known to 122525985edcSLucas De Marchi * work. Between, there are V1.06, V2.06 and V3.03 1226cedc9bf9STejun Heo * that we don't have much idea about. For now, 1227cedc9bf9STejun Heo * blacklist anything older than V3.04. 12289deb3431STejun Heo * 12299deb3431STejun Heo * http://bugzilla.kernel.org/show_bug.cgi?id=15104 1230cedc9bf9STejun Heo */ 1231cedc9bf9STejun Heo { 1232cedc9bf9STejun Heo .ident = "G725", 1233cedc9bf9STejun Heo .matches = { 1234cedc9bf9STejun Heo DMI_MATCH(DMI_SYS_VENDOR, "eMachines"), 1235cedc9bf9STejun Heo DMI_MATCH(DMI_PRODUCT_NAME, "eMachines G725"), 1236cedc9bf9STejun Heo }, 12379deb3431STejun Heo .driver_data = "20091216", /* V3.04 */ 1238cedc9bf9STejun Heo }, 12399b10ae86STejun Heo { } /* terminate list */ 12409b10ae86STejun Heo }; 12419b10ae86STejun Heo const struct dmi_system_id *dmi = dmi_first_match(sysids); 12429deb3431STejun Heo int year, month, date; 12439deb3431STejun Heo char buf[9]; 12449b10ae86STejun Heo 12459b10ae86STejun Heo if (!dmi || pdev->bus->number || pdev->devfn != PCI_DEVFN(0x1f, 2)) 12469b10ae86STejun Heo return false; 12479b10ae86STejun Heo 12489deb3431STejun Heo dmi_get_date(DMI_BIOS_DATE, &year, &month, &date); 12499deb3431STejun Heo snprintf(buf, sizeof(buf), "%04d%02d%02d", year, month, date); 12509b10ae86STejun Heo 12519deb3431STejun Heo return strcmp(buf, dmi->driver_data) < 0; 12529b10ae86STejun Heo } 12539b10ae86STejun Heo 1254240630e6SHans de Goede static bool ahci_broken_lpm(struct pci_dev *pdev) 1255240630e6SHans de Goede { 1256240630e6SHans de Goede static const struct dmi_system_id sysids[] = { 1257240630e6SHans de Goede /* Various Lenovo 50 series have LPM issues with older BIOSen */ 1258240630e6SHans de Goede { 1259240630e6SHans de Goede .matches = { 1260240630e6SHans de Goede DMI_MATCH(DMI_SYS_VENDOR, "LENOVO"), 1261240630e6SHans de Goede DMI_MATCH(DMI_PRODUCT_VERSION, "ThinkPad X250"), 1262240630e6SHans de Goede }, 1263240630e6SHans de Goede .driver_data = "20180406", /* 1.31 */ 1264240630e6SHans de Goede }, 1265240630e6SHans de Goede { 1266240630e6SHans de Goede .matches = { 1267240630e6SHans de Goede DMI_MATCH(DMI_SYS_VENDOR, "LENOVO"), 1268240630e6SHans de Goede DMI_MATCH(DMI_PRODUCT_VERSION, "ThinkPad L450"), 1269240630e6SHans de Goede }, 1270240630e6SHans de Goede .driver_data = "20180420", /* 1.28 */ 1271240630e6SHans de Goede }, 1272240630e6SHans de Goede { 1273240630e6SHans de Goede .matches = { 1274240630e6SHans de Goede DMI_MATCH(DMI_SYS_VENDOR, "LENOVO"), 1275240630e6SHans de Goede DMI_MATCH(DMI_PRODUCT_VERSION, "ThinkPad T450s"), 1276240630e6SHans de Goede }, 1277240630e6SHans de Goede .driver_data = "20180315", /* 1.33 */ 1278240630e6SHans de Goede }, 1279240630e6SHans de Goede { 1280240630e6SHans de Goede .matches = { 1281240630e6SHans de Goede DMI_MATCH(DMI_SYS_VENDOR, "LENOVO"), 1282240630e6SHans de Goede DMI_MATCH(DMI_PRODUCT_VERSION, "ThinkPad W541"), 1283240630e6SHans de Goede }, 1284240630e6SHans de Goede /* 1285240630e6SHans de Goede * Note date based on release notes, 2.35 has been 1286240630e6SHans de Goede * reported to be good, but I've been unable to get 1287240630e6SHans de Goede * a hold of the reporter to get the DMI BIOS date. 1288240630e6SHans de Goede * TODO: fix this. 1289240630e6SHans de Goede */ 1290240630e6SHans de Goede .driver_data = "20180310", /* 2.35 */ 1291240630e6SHans de Goede }, 1292240630e6SHans de Goede { } /* terminate list */ 1293240630e6SHans de Goede }; 1294240630e6SHans de Goede const struct dmi_system_id *dmi = dmi_first_match(sysids); 1295240630e6SHans de Goede int year, month, date; 1296240630e6SHans de Goede char buf[9]; 1297240630e6SHans de Goede 1298240630e6SHans de Goede if (!dmi) 1299240630e6SHans de Goede return false; 1300240630e6SHans de Goede 1301240630e6SHans de Goede dmi_get_date(DMI_BIOS_DATE, &year, &month, &date); 1302240630e6SHans de Goede snprintf(buf, sizeof(buf), "%04d%02d%02d", year, month, date); 1303240630e6SHans de Goede 1304240630e6SHans de Goede return strcmp(buf, dmi->driver_data) < 0; 1305240630e6SHans de Goede } 1306240630e6SHans de Goede 13075594639aSTejun Heo static bool ahci_broken_online(struct pci_dev *pdev) 13085594639aSTejun Heo { 13095594639aSTejun Heo #define ENCODE_BUSDEVFN(bus, slot, func) \ 13105594639aSTejun Heo (void *)(unsigned long)(((bus) << 8) | PCI_DEVFN((slot), (func))) 13115594639aSTejun Heo static const struct dmi_system_id sysids[] = { 13125594639aSTejun Heo /* 13135594639aSTejun Heo * There are several gigabyte boards which use 13145594639aSTejun Heo * SIMG5723s configured as hardware RAID. Certain 13155594639aSTejun Heo * 5723 firmware revisions shipped there keep the link 13165594639aSTejun Heo * online but fail to answer properly to SRST or 13175594639aSTejun Heo * IDENTIFY when no device is attached downstream 13185594639aSTejun Heo * causing libata to retry quite a few times leading 13195594639aSTejun Heo * to excessive detection delay. 13205594639aSTejun Heo * 13215594639aSTejun Heo * As these firmwares respond to the second reset try 13225594639aSTejun Heo * with invalid device signature, considering unknown 13235594639aSTejun Heo * sig as offline works around the problem acceptably. 13245594639aSTejun Heo */ 13255594639aSTejun Heo { 13265594639aSTejun Heo .ident = "EP45-DQ6", 13275594639aSTejun Heo .matches = { 13285594639aSTejun Heo DMI_MATCH(DMI_BOARD_VENDOR, 13295594639aSTejun Heo "Gigabyte Technology Co., Ltd."), 13305594639aSTejun Heo DMI_MATCH(DMI_BOARD_NAME, "EP45-DQ6"), 13315594639aSTejun Heo }, 13325594639aSTejun Heo .driver_data = ENCODE_BUSDEVFN(0x0a, 0x00, 0), 13335594639aSTejun Heo }, 13345594639aSTejun Heo { 13355594639aSTejun Heo .ident = "EP45-DS5", 13365594639aSTejun Heo .matches = { 13375594639aSTejun Heo DMI_MATCH(DMI_BOARD_VENDOR, 13385594639aSTejun Heo "Gigabyte Technology Co., Ltd."), 13395594639aSTejun Heo DMI_MATCH(DMI_BOARD_NAME, "EP45-DS5"), 13405594639aSTejun Heo }, 13415594639aSTejun Heo .driver_data = ENCODE_BUSDEVFN(0x03, 0x00, 0), 13425594639aSTejun Heo }, 13435594639aSTejun Heo { } /* terminate list */ 13445594639aSTejun Heo }; 13455594639aSTejun Heo #undef ENCODE_BUSDEVFN 13465594639aSTejun Heo const struct dmi_system_id *dmi = dmi_first_match(sysids); 13475594639aSTejun Heo unsigned int val; 13485594639aSTejun Heo 13495594639aSTejun Heo if (!dmi) 13505594639aSTejun Heo return false; 13515594639aSTejun Heo 13525594639aSTejun Heo val = (unsigned long)dmi->driver_data; 13535594639aSTejun Heo 13545594639aSTejun Heo return pdev->bus->number == (val >> 8) && pdev->devfn == (val & 0xff); 13555594639aSTejun Heo } 13565594639aSTejun Heo 13570cf4a7d6SJacob Pan static bool ahci_broken_devslp(struct pci_dev *pdev) 13580cf4a7d6SJacob Pan { 13590cf4a7d6SJacob Pan /* device with broken DEVSLP but still showing SDS capability */ 13600cf4a7d6SJacob Pan static const struct pci_device_id ids[] = { 13610cf4a7d6SJacob Pan { PCI_VDEVICE(INTEL, 0x0f23)}, /* Valleyview SoC */ 13620cf4a7d6SJacob Pan {} 13630cf4a7d6SJacob Pan }; 13640cf4a7d6SJacob Pan 13650cf4a7d6SJacob Pan return pci_match_id(ids, pdev); 13660cf4a7d6SJacob Pan } 13670cf4a7d6SJacob Pan 13688e513217SMarkus Trippelsdorf #ifdef CONFIG_ATA_ACPI 1369f80ae7e4STejun Heo static void ahci_gtf_filter_workaround(struct ata_host *host) 1370f80ae7e4STejun Heo { 1371f80ae7e4STejun Heo static const struct dmi_system_id sysids[] = { 1372f80ae7e4STejun Heo /* 1373f80ae7e4STejun Heo * Aspire 3810T issues a bunch of SATA enable commands 1374f80ae7e4STejun Heo * via _GTF including an invalid one and one which is 1375f80ae7e4STejun Heo * rejected by the device. Among the successful ones 1376f80ae7e4STejun Heo * is FPDMA non-zero offset enable which when enabled 1377f80ae7e4STejun Heo * only on the drive side leads to NCQ command 1378f80ae7e4STejun Heo * failures. Filter it out. 1379f80ae7e4STejun Heo */ 1380f80ae7e4STejun Heo { 1381f80ae7e4STejun Heo .ident = "Aspire 3810T", 1382f80ae7e4STejun Heo .matches = { 1383f80ae7e4STejun Heo DMI_MATCH(DMI_SYS_VENDOR, "Acer"), 1384f80ae7e4STejun Heo DMI_MATCH(DMI_PRODUCT_NAME, "Aspire 3810T"), 1385f80ae7e4STejun Heo }, 1386f80ae7e4STejun Heo .driver_data = (void *)ATA_ACPI_FILTER_FPDMA_OFFSET, 1387f80ae7e4STejun Heo }, 1388f80ae7e4STejun Heo { } 1389f80ae7e4STejun Heo }; 1390f80ae7e4STejun Heo const struct dmi_system_id *dmi = dmi_first_match(sysids); 1391f80ae7e4STejun Heo unsigned int filter; 1392f80ae7e4STejun Heo int i; 1393f80ae7e4STejun Heo 1394f80ae7e4STejun Heo if (!dmi) 1395f80ae7e4STejun Heo return; 1396f80ae7e4STejun Heo 1397f80ae7e4STejun Heo filter = (unsigned long)dmi->driver_data; 1398a44fec1fSJoe Perches dev_info(host->dev, "applying extra ACPI _GTF filter 0x%x for %s\n", 1399f80ae7e4STejun Heo filter, dmi->ident); 1400f80ae7e4STejun Heo 1401f80ae7e4STejun Heo for (i = 0; i < host->n_ports; i++) { 1402f80ae7e4STejun Heo struct ata_port *ap = host->ports[i]; 1403f80ae7e4STejun Heo struct ata_link *link; 1404f80ae7e4STejun Heo struct ata_device *dev; 1405f80ae7e4STejun Heo 1406f80ae7e4STejun Heo ata_for_each_link(link, ap, EDGE) 1407f80ae7e4STejun Heo ata_for_each_dev(dev, link, ALL) 1408f80ae7e4STejun Heo dev->gtf_filter |= filter; 1409f80ae7e4STejun Heo } 1410f80ae7e4STejun Heo } 14118e513217SMarkus Trippelsdorf #else 14128e513217SMarkus Trippelsdorf static inline void ahci_gtf_filter_workaround(struct ata_host *host) 14138e513217SMarkus Trippelsdorf {} 14148e513217SMarkus Trippelsdorf #endif 1415f80ae7e4STejun Heo 14168bfd1743SSui Chen /* 14178bfd1743SSui Chen * On the Acer Aspire Switch Alpha 12, sometimes all SATA ports are detected 14188bfd1743SSui Chen * as DUMMY, or detected but eventually get a "link down" and never get up 14198bfd1743SSui Chen * again. When this happens, CAP.NP may hold a value of 0x00 or 0x01, and the 14208bfd1743SSui Chen * port_map may hold a value of 0x00. 14218bfd1743SSui Chen * 14228bfd1743SSui Chen * Overriding CAP.NP to 0x02 and the port_map to 0x7 will reveal all 3 ports 14238bfd1743SSui Chen * and can significantly reduce the occurrence of the problem. 14248bfd1743SSui Chen * 14258bfd1743SSui Chen * https://bugzilla.kernel.org/show_bug.cgi?id=189471 14268bfd1743SSui Chen */ 14278bfd1743SSui Chen static void acer_sa5_271_workaround(struct ahci_host_priv *hpriv, 14288bfd1743SSui Chen struct pci_dev *pdev) 14298bfd1743SSui Chen { 14308bfd1743SSui Chen static const struct dmi_system_id sysids[] = { 14318bfd1743SSui Chen { 14328bfd1743SSui Chen .ident = "Acer Switch Alpha 12", 14338bfd1743SSui Chen .matches = { 14348bfd1743SSui Chen DMI_MATCH(DMI_SYS_VENDOR, "Acer"), 14358bfd1743SSui Chen DMI_MATCH(DMI_PRODUCT_NAME, "Switch SA5-271") 14368bfd1743SSui Chen }, 14378bfd1743SSui Chen }, 14388bfd1743SSui Chen { } 14398bfd1743SSui Chen }; 14408bfd1743SSui Chen 14418bfd1743SSui Chen if (dmi_check_system(sysids)) { 14428bfd1743SSui Chen dev_info(&pdev->dev, "enabling Acer Switch Alpha 12 workaround\n"); 14438bfd1743SSui Chen if ((hpriv->saved_cap & 0xC734FF00) == 0xC734FF00) { 14448bfd1743SSui Chen hpriv->port_map = 0x7; 14458bfd1743SSui Chen hpriv->cap = 0xC734FF02; 14468bfd1743SSui Chen } 14478bfd1743SSui Chen } 14488bfd1743SSui Chen } 14498bfd1743SSui Chen 1450d243bed3STirumalesh Chalamarla #ifdef CONFIG_ARM64 1451d243bed3STirumalesh Chalamarla /* 1452d243bed3STirumalesh Chalamarla * Due to ERRATA#22536, ThunderX needs to handle HOST_IRQ_STAT differently. 1453d243bed3STirumalesh Chalamarla * Workaround is to make sure all pending IRQs are served before leaving 1454d243bed3STirumalesh Chalamarla * handler. 1455d243bed3STirumalesh Chalamarla */ 1456d243bed3STirumalesh Chalamarla static irqreturn_t ahci_thunderx_irq_handler(int irq, void *dev_instance) 1457d243bed3STirumalesh Chalamarla { 1458d243bed3STirumalesh Chalamarla struct ata_host *host = dev_instance; 1459d243bed3STirumalesh Chalamarla struct ahci_host_priv *hpriv; 1460d243bed3STirumalesh Chalamarla unsigned int rc = 0; 1461d243bed3STirumalesh Chalamarla void __iomem *mmio; 1462d243bed3STirumalesh Chalamarla u32 irq_stat, irq_masked; 1463d243bed3STirumalesh Chalamarla unsigned int handled = 1; 1464d243bed3STirumalesh Chalamarla 1465d243bed3STirumalesh Chalamarla VPRINTK("ENTER\n"); 1466d243bed3STirumalesh Chalamarla hpriv = host->private_data; 1467d243bed3STirumalesh Chalamarla mmio = hpriv->mmio; 1468d243bed3STirumalesh Chalamarla irq_stat = readl(mmio + HOST_IRQ_STAT); 1469d243bed3STirumalesh Chalamarla if (!irq_stat) 1470d243bed3STirumalesh Chalamarla return IRQ_NONE; 1471d243bed3STirumalesh Chalamarla 1472d243bed3STirumalesh Chalamarla do { 1473d243bed3STirumalesh Chalamarla irq_masked = irq_stat & hpriv->port_map; 1474d243bed3STirumalesh Chalamarla spin_lock(&host->lock); 1475d243bed3STirumalesh Chalamarla rc = ahci_handle_port_intr(host, irq_masked); 1476d243bed3STirumalesh Chalamarla if (!rc) 1477d243bed3STirumalesh Chalamarla handled = 0; 1478d243bed3STirumalesh Chalamarla writel(irq_stat, mmio + HOST_IRQ_STAT); 1479d243bed3STirumalesh Chalamarla irq_stat = readl(mmio + HOST_IRQ_STAT); 1480d243bed3STirumalesh Chalamarla spin_unlock(&host->lock); 1481d243bed3STirumalesh Chalamarla } while (irq_stat); 1482d243bed3STirumalesh Chalamarla VPRINTK("EXIT\n"); 1483d243bed3STirumalesh Chalamarla 1484d243bed3STirumalesh Chalamarla return IRQ_RETVAL(handled); 1485d243bed3STirumalesh Chalamarla } 1486d243bed3STirumalesh Chalamarla #endif 1487d243bed3STirumalesh Chalamarla 1488aecec8b6SChristoph Hellwig static void ahci_remap_check(struct pci_dev *pdev, int bar, 1489aecec8b6SChristoph Hellwig struct ahci_host_priv *hpriv) 1490aecec8b6SChristoph Hellwig { 1491aecec8b6SChristoph Hellwig int i, count = 0; 1492aecec8b6SChristoph Hellwig u32 cap; 1493aecec8b6SChristoph Hellwig 1494aecec8b6SChristoph Hellwig /* 1495aecec8b6SChristoph Hellwig * Check if this device might have remapped nvme devices. 1496aecec8b6SChristoph Hellwig */ 1497aecec8b6SChristoph Hellwig if (pdev->vendor != PCI_VENDOR_ID_INTEL || 1498aecec8b6SChristoph Hellwig pci_resource_len(pdev, bar) < SZ_512K || 1499aecec8b6SChristoph Hellwig bar != AHCI_PCI_BAR_STANDARD || 1500aecec8b6SChristoph Hellwig !(readl(hpriv->mmio + AHCI_VSCAP) & 1)) 1501aecec8b6SChristoph Hellwig return; 1502aecec8b6SChristoph Hellwig 1503aecec8b6SChristoph Hellwig cap = readq(hpriv->mmio + AHCI_REMAP_CAP); 1504aecec8b6SChristoph Hellwig for (i = 0; i < AHCI_MAX_REMAP; i++) { 1505aecec8b6SChristoph Hellwig if ((cap & (1 << i)) == 0) 1506aecec8b6SChristoph Hellwig continue; 1507aecec8b6SChristoph Hellwig if (readl(hpriv->mmio + ahci_remap_dcc(i)) 1508aecec8b6SChristoph Hellwig != PCI_CLASS_STORAGE_EXPRESS) 1509aecec8b6SChristoph Hellwig continue; 1510aecec8b6SChristoph Hellwig 1511aecec8b6SChristoph Hellwig /* We've found a remapped device */ 1512aecec8b6SChristoph Hellwig count++; 1513aecec8b6SChristoph Hellwig } 1514aecec8b6SChristoph Hellwig 1515aecec8b6SChristoph Hellwig if (!count) 1516aecec8b6SChristoph Hellwig return; 1517aecec8b6SChristoph Hellwig 1518aecec8b6SChristoph Hellwig dev_warn(&pdev->dev, "Found %d remapped NVMe devices.\n", count); 1519f723fa4eSChristoph Hellwig dev_warn(&pdev->dev, 1520f723fa4eSChristoph Hellwig "Switch your BIOS from RAID to AHCI mode to use them.\n"); 1521f723fa4eSChristoph Hellwig 1522f723fa4eSChristoph Hellwig /* 1523f723fa4eSChristoph Hellwig * Don't rely on the msi-x capability in the remap case, 1524f723fa4eSChristoph Hellwig * share the legacy interrupt across ahci and remapped devices. 1525f723fa4eSChristoph Hellwig */ 1526f723fa4eSChristoph Hellwig hpriv->flags |= AHCI_HFLAG_NO_MSI; 1527aecec8b6SChristoph Hellwig } 1528aecec8b6SChristoph Hellwig 15290b9e2988SChristoph Hellwig static int ahci_get_irq_vector(struct ata_host *host, int port) 1530ee2aad42SRobert Richter { 15310b9e2988SChristoph Hellwig return pci_irq_vector(to_pci_dev(host->dev), port); 1532ee2aad42SRobert Richter } 1533ee2aad42SRobert Richter 1534a1c82311SRobert Richter static int ahci_init_msi(struct pci_dev *pdev, unsigned int n_ports, 15357b92b4f6SAlexander Gordeev struct ahci_host_priv *hpriv) 15365ca72c4fSAlexander Gordeev { 15370b9e2988SChristoph Hellwig int nvec; 15385ca72c4fSAlexander Gordeev 15397b92b4f6SAlexander Gordeev if (hpriv->flags & AHCI_HFLAG_NO_MSI) 1540a1c82311SRobert Richter return -ENODEV; 15417b92b4f6SAlexander Gordeev 15425ca72c4fSAlexander Gordeev /* 15437b92b4f6SAlexander Gordeev * If number of MSIs is less than number of ports then Sharing Last 15447b92b4f6SAlexander Gordeev * Message mode could be enforced. In this case assume that advantage 15457b92b4f6SAlexander Gordeev * of multipe MSIs is negated and use single MSI mode instead. 15465ca72c4fSAlexander Gordeev */ 154717a51f12SChristoph Hellwig if (n_ports > 1) { 15480b9e2988SChristoph Hellwig nvec = pci_alloc_irq_vectors(pdev, n_ports, INT_MAX, 15490b9e2988SChristoph Hellwig PCI_IRQ_MSIX | PCI_IRQ_MSI); 15500b9e2988SChristoph Hellwig if (nvec > 0) { 15510b9e2988SChristoph Hellwig if (!(readl(hpriv->mmio + HOST_CTL) & HOST_MRSM)) { 15520b9e2988SChristoph Hellwig hpriv->get_irq_vector = ahci_get_irq_vector; 1553c3ebd6a9SAlexander Gordeev hpriv->flags |= AHCI_HFLAG_MULTI_MSI; 155421bfd1aaSRobert Richter return nvec; 1555a1c82311SRobert Richter } 1556a1c82311SRobert Richter 1557d684a90dSDan Williams /* 155817a51f12SChristoph Hellwig * Fallback to single MSI mode if the controller 155917a51f12SChristoph Hellwig * enforced MRSM mode. 1560d684a90dSDan Williams */ 156117a51f12SChristoph Hellwig printk(KERN_INFO 156217a51f12SChristoph Hellwig "ahci: MRSM is on, fallback to single MSI\n"); 15630b9e2988SChristoph Hellwig pci_free_irq_vectors(pdev); 15640b9e2988SChristoph Hellwig } 1565a478b097SChristoph Hellwig } 1566d684a90dSDan Williams 15670b9e2988SChristoph Hellwig /* 15680b9e2988SChristoph Hellwig * If the host is not capable of supporting per-port vectors, fall 15690b9e2988SChristoph Hellwig * back to single MSI before finally attempting single MSI-X. 15700b9e2988SChristoph Hellwig */ 15710b9e2988SChristoph Hellwig nvec = pci_alloc_irq_vectors(pdev, 1, 1, PCI_IRQ_MSI); 15720b9e2988SChristoph Hellwig if (nvec == 1) 1573a1c82311SRobert Richter return nvec; 15740b9e2988SChristoph Hellwig return pci_alloc_irq_vectors(pdev, 1, 1, PCI_IRQ_MSIX); 15755ca72c4fSAlexander Gordeev } 15765ca72c4fSAlexander Gordeev 1577b1a9585cSSrinivas Pandruvada static void ahci_update_initial_lpm_policy(struct ata_port *ap, 1578b1a9585cSSrinivas Pandruvada struct ahci_host_priv *hpriv) 1579b1a9585cSSrinivas Pandruvada { 1580b1a9585cSSrinivas Pandruvada int policy = CONFIG_SATA_MOBILE_LPM_POLICY; 1581b1a9585cSSrinivas Pandruvada 1582b1a9585cSSrinivas Pandruvada 1583b1a9585cSSrinivas Pandruvada /* Ignore processing for non mobile platforms */ 1584b1a9585cSSrinivas Pandruvada if (!(hpriv->flags & AHCI_HFLAG_IS_MOBILE)) 1585b1a9585cSSrinivas Pandruvada return; 1586b1a9585cSSrinivas Pandruvada 1587b1a9585cSSrinivas Pandruvada /* user modified policy via module param */ 1588b1a9585cSSrinivas Pandruvada if (mobile_lpm_policy != -1) { 1589b1a9585cSSrinivas Pandruvada policy = mobile_lpm_policy; 1590b1a9585cSSrinivas Pandruvada goto update_policy; 1591b1a9585cSSrinivas Pandruvada } 1592b1a9585cSSrinivas Pandruvada 1593b1a9585cSSrinivas Pandruvada #ifdef CONFIG_ACPI 1594b1a9585cSSrinivas Pandruvada if (policy > ATA_LPM_MED_POWER && 1595b1a9585cSSrinivas Pandruvada (acpi_gbl_FADT.flags & ACPI_FADT_LOW_POWER_S0)) { 1596b1a9585cSSrinivas Pandruvada if (hpriv->cap & HOST_CAP_PART) 1597b1a9585cSSrinivas Pandruvada policy = ATA_LPM_MIN_POWER_WITH_PARTIAL; 1598b1a9585cSSrinivas Pandruvada else if (hpriv->cap & HOST_CAP_SSC) 1599b1a9585cSSrinivas Pandruvada policy = ATA_LPM_MIN_POWER; 1600b1a9585cSSrinivas Pandruvada } 1601b1a9585cSSrinivas Pandruvada #endif 1602b1a9585cSSrinivas Pandruvada 1603b1a9585cSSrinivas Pandruvada update_policy: 1604b1a9585cSSrinivas Pandruvada if (policy >= ATA_LPM_UNKNOWN && policy <= ATA_LPM_MIN_POWER) 1605b1a9585cSSrinivas Pandruvada ap->target_lpm_policy = policy; 1606b1a9585cSSrinivas Pandruvada } 1607b1a9585cSSrinivas Pandruvada 1608c312ef17SDan Williams static void ahci_intel_pcs_quirk(struct pci_dev *pdev, struct ahci_host_priv *hpriv) 1609c312ef17SDan Williams { 1610c312ef17SDan Williams const struct pci_device_id *id = pci_match_id(ahci_pci_tbl, pdev); 1611c312ef17SDan Williams u16 tmp16; 1612c312ef17SDan Williams 1613c312ef17SDan Williams /* 1614c312ef17SDan Williams * Only apply the 6-port PCS quirk for known legacy platforms. 1615c312ef17SDan Williams */ 1616c312ef17SDan Williams if (!id || id->vendor != PCI_VENDOR_ID_INTEL) 1617c312ef17SDan Williams return; 161809d6ac8dSDan Williams 161909d6ac8dSDan Williams /* Skip applying the quirk on Denverton and beyond */ 162009d6ac8dSDan Williams if (((enum board_ids) id->driver_data) >= board_ahci_pcs7) 1621c312ef17SDan Williams return; 1622c312ef17SDan Williams 1623c312ef17SDan Williams /* 1624c312ef17SDan Williams * port_map is determined from PORTS_IMPL PCI register which is 1625c312ef17SDan Williams * implemented as write or write-once register. If the register 1626c312ef17SDan Williams * isn't programmed, ahci automatically generates it from number 1627c312ef17SDan Williams * of ports, which is good enough for PCS programming. It is 1628c312ef17SDan Williams * otherwise expected that platform firmware enables the ports 1629c312ef17SDan Williams * before the OS boots. 1630c312ef17SDan Williams */ 1631c312ef17SDan Williams pci_read_config_word(pdev, PCS_6, &tmp16); 1632c312ef17SDan Williams if ((tmp16 & hpriv->port_map) != hpriv->port_map) { 1633c312ef17SDan Williams tmp16 |= hpriv->port_map; 1634c312ef17SDan Williams pci_write_config_word(pdev, PCS_6, tmp16); 1635c312ef17SDan Williams } 1636c312ef17SDan Williams } 1637c312ef17SDan Williams 1638c6fd2807SJeff Garzik static int ahci_init_one(struct pci_dev *pdev, const struct pci_device_id *ent) 1639c6fd2807SJeff Garzik { 1640e297d99eSTejun Heo unsigned int board_id = ent->driver_data; 1641e297d99eSTejun Heo struct ata_port_info pi = ahci_port_info[board_id]; 16424447d351STejun Heo const struct ata_port_info *ppi[] = { &pi, NULL }; 164324dc5f33STejun Heo struct device *dev = &pdev->dev; 1644c6fd2807SJeff Garzik struct ahci_host_priv *hpriv; 16454447d351STejun Heo struct ata_host *host; 1646c3ebd6a9SAlexander Gordeev int n_ports, i, rc; 1647318893e1SAlessandro Rubini int ahci_pci_bar = AHCI_PCI_BAR_STANDARD; 1648c6fd2807SJeff Garzik 1649c6fd2807SJeff Garzik VPRINTK("ENTER\n"); 1650c6fd2807SJeff Garzik 1651b429dd59SJustin P. Mattock WARN_ON((int)ATA_MAX_QUEUE > AHCI_MAX_CMDS); 1652c6fd2807SJeff Garzik 165306296a1eSJoe Perches ata_print_version_once(&pdev->dev, DRV_VERSION); 1654c6fd2807SJeff Garzik 16555b66c829SAlan Cox /* The AHCI driver can only drive the SATA ports, the PATA driver 16565b66c829SAlan Cox can drive them all so if both drivers are selected make sure 16575b66c829SAlan Cox AHCI stays out of the way */ 16585b66c829SAlan Cox if (pdev->vendor == PCI_VENDOR_ID_MARVELL && !marvell_enable) 16595b66c829SAlan Cox return -ENODEV; 16605b66c829SAlan Cox 1661cb85696dSJames Laird /* Apple BIOS on MCP89 prevents us using AHCI */ 1662cb85696dSJames Laird if (is_mcp89_apple(pdev)) 1663cb85696dSJames Laird ahci_mcp89_apple_enable(pdev); 1664c6353b45STejun Heo 16657a02267eSMark Nelson /* Promise's PDC42819 is a SAS/SATA controller that has an AHCI mode. 16667a02267eSMark Nelson * At the moment, we can only use the AHCI mode. Let the users know 16677a02267eSMark Nelson * that for SAS drives they're out of luck. 16687a02267eSMark Nelson */ 16697a02267eSMark Nelson if (pdev->vendor == PCI_VENDOR_ID_PROMISE) 1670a44fec1fSJoe Perches dev_info(&pdev->dev, 1671a44fec1fSJoe Perches "PDC42819 can only drive SATA devices with this driver\n"); 16727a02267eSMark Nelson 1673b7ae128dSRobert Richter /* Some devices use non-standard BARs */ 1674318893e1SAlessandro Rubini if (pdev->vendor == PCI_VENDOR_ID_STMICRO && pdev->device == 0xCC06) 1675318893e1SAlessandro Rubini ahci_pci_bar = AHCI_PCI_BAR_STA2X11; 16767f9c9f8eSHugh Daschbach else if (pdev->vendor == 0x1c44 && pdev->device == 0x8000) 16777f9c9f8eSHugh Daschbach ahci_pci_bar = AHCI_PCI_BAR_ENMOTUS; 1678b1314e3fSRadha Mohan Chintakuntla else if (pdev->vendor == PCI_VENDOR_ID_CAVIUM) { 1679b1314e3fSRadha Mohan Chintakuntla if (pdev->device == 0xa01c) 1680b7ae128dSRobert Richter ahci_pci_bar = AHCI_PCI_BAR_CAVIUM; 1681b1314e3fSRadha Mohan Chintakuntla if (pdev->device == 0xa084) 1682b1314e3fSRadha Mohan Chintakuntla ahci_pci_bar = AHCI_PCI_BAR_CAVIUM_GEN5; 1683b1314e3fSRadha Mohan Chintakuntla } 1684318893e1SAlessandro Rubini 16854447d351STejun Heo /* acquire resources */ 168624dc5f33STejun Heo rc = pcim_enable_device(pdev); 1687c6fd2807SJeff Garzik if (rc) 1688c6fd2807SJeff Garzik return rc; 1689c6fd2807SJeff Garzik 1690c4f7792cSTejun Heo if (pdev->vendor == PCI_VENDOR_ID_INTEL && 1691c4f7792cSTejun Heo (pdev->device == 0x2652 || pdev->device == 0x2653)) { 1692c4f7792cSTejun Heo u8 map; 1693c4f7792cSTejun Heo 1694c4f7792cSTejun Heo /* ICH6s share the same PCI ID for both piix and ahci 1695c4f7792cSTejun Heo * modes. Enabling ahci mode while MAP indicates 1696c4f7792cSTejun Heo * combined mode is a bad idea. Yield to ata_piix. 1697c4f7792cSTejun Heo */ 1698c4f7792cSTejun Heo pci_read_config_byte(pdev, ICH_MAP, &map); 1699c4f7792cSTejun Heo if (map & 0x3) { 1700a44fec1fSJoe Perches dev_info(&pdev->dev, 1701a44fec1fSJoe Perches "controller is in combined mode, can't enable AHCI mode\n"); 1702c4f7792cSTejun Heo return -ENODEV; 1703c4f7792cSTejun Heo } 1704c4f7792cSTejun Heo } 1705c4f7792cSTejun Heo 17066fec8871SPaul Bolle /* AHCI controllers often implement SFF compatible interface. 17076fec8871SPaul Bolle * Grab all PCI BARs just in case. 17086fec8871SPaul Bolle */ 17096fec8871SPaul Bolle rc = pcim_iomap_regions_request_all(pdev, 1 << ahci_pci_bar, DRV_NAME); 17106fec8871SPaul Bolle if (rc == -EBUSY) 17116fec8871SPaul Bolle pcim_pin_device(pdev); 17126fec8871SPaul Bolle if (rc) 17136fec8871SPaul Bolle return rc; 17146fec8871SPaul Bolle 171524dc5f33STejun Heo hpriv = devm_kzalloc(dev, sizeof(*hpriv), GFP_KERNEL); 171624dc5f33STejun Heo if (!hpriv) 171724dc5f33STejun Heo return -ENOMEM; 1718417a1a6dSTejun Heo hpriv->flags |= (unsigned long)pi.private_data; 1719417a1a6dSTejun Heo 1720e297d99eSTejun Heo /* MCP65 revision A1 and A2 can't do MSI */ 1721e297d99eSTejun Heo if (board_id == board_ahci_mcp65 && 1722e297d99eSTejun Heo (pdev->revision == 0xa1 || pdev->revision == 0xa2)) 1723e297d99eSTejun Heo hpriv->flags |= AHCI_HFLAG_NO_MSI; 1724e297d99eSTejun Heo 1725e427fe04SShane Huang /* SB800 does NOT need the workaround to ignore SERR_INTERNAL */ 1726e427fe04SShane Huang if (board_id == board_ahci_sb700 && pdev->revision >= 0x40) 1727e427fe04SShane Huang hpriv->flags &= ~AHCI_HFLAG_IGN_SERR_INTERNAL; 1728e427fe04SShane Huang 17292fcad9d2STejun Heo /* only some SB600s can do 64bit DMA */ 17302fcad9d2STejun Heo if (ahci_sb600_enable_64bit(pdev)) 17312fcad9d2STejun Heo hpriv->flags &= ~AHCI_HFLAG_32BIT_ONLY; 173258a09b38SShane Huang 1733318893e1SAlessandro Rubini hpriv->mmio = pcim_iomap_table(pdev)[ahci_pci_bar]; 1734d8993349SAnton Vorontsov 1735aecec8b6SChristoph Hellwig /* detect remapped nvme devices */ 1736aecec8b6SChristoph Hellwig ahci_remap_check(pdev, ahci_pci_bar, hpriv); 1737aecec8b6SChristoph Hellwig 17380cf4a7d6SJacob Pan /* must set flag prior to save config in order to take effect */ 17390cf4a7d6SJacob Pan if (ahci_broken_devslp(pdev)) 17400cf4a7d6SJacob Pan hpriv->flags |= AHCI_HFLAG_NO_DEVSLP; 17410cf4a7d6SJacob Pan 1742d243bed3STirumalesh Chalamarla #ifdef CONFIG_ARM64 1743d243bed3STirumalesh Chalamarla if (pdev->vendor == 0x177d && pdev->device == 0xa01c) 1744d243bed3STirumalesh Chalamarla hpriv->irq_handler = ahci_thunderx_irq_handler; 1745d243bed3STirumalesh Chalamarla #endif 1746d243bed3STirumalesh Chalamarla 17474447d351STejun Heo /* save initial config */ 1748394d6e53SAnton Vorontsov ahci_pci_save_initial_config(pdev, hpriv); 1749c6fd2807SJeff Garzik 1750c312ef17SDan Williams /* 1751c312ef17SDan Williams * If platform firmware failed to enable ports, try to enable 1752c312ef17SDan Williams * them here. 1753c312ef17SDan Williams */ 1754c312ef17SDan Williams ahci_intel_pcs_quirk(pdev, hpriv); 1755c312ef17SDan Williams 17564447d351STejun Heo /* prepare host */ 1757453d3131SRobert Hancock if (hpriv->cap & HOST_CAP_NCQ) { 1758453d3131SRobert Hancock pi.flags |= ATA_FLAG_NCQ; 175983f2b963STejun Heo /* 176083f2b963STejun Heo * Auto-activate optimization is supposed to be 176183f2b963STejun Heo * supported on all AHCI controllers indicating NCQ 176283f2b963STejun Heo * capability, but it seems to be broken on some 176383f2b963STejun Heo * chipsets including NVIDIAs. 176483f2b963STejun Heo */ 176583f2b963STejun Heo if (!(hpriv->flags & AHCI_HFLAG_NO_FPDMA_AA)) 1766453d3131SRobert Hancock pi.flags |= ATA_FLAG_FPDMA_AA; 176740fb59e7SMarc Carino 176840fb59e7SMarc Carino /* 176940fb59e7SMarc Carino * All AHCI controllers should be forward-compatible 177040fb59e7SMarc Carino * with the new auxiliary field. This code should be 177140fb59e7SMarc Carino * conditionalized if any buggy AHCI controllers are 177240fb59e7SMarc Carino * encountered. 177340fb59e7SMarc Carino */ 177440fb59e7SMarc Carino pi.flags |= ATA_FLAG_FPDMA_AUX; 1775453d3131SRobert Hancock } 17764447d351STejun Heo 17777d50b60bSTejun Heo if (hpriv->cap & HOST_CAP_PMP) 17787d50b60bSTejun Heo pi.flags |= ATA_FLAG_PMP; 17797d50b60bSTejun Heo 17800cbb0e77SAnton Vorontsov ahci_set_em_messages(hpriv, &pi); 178118f7ba4cSKristen Carlson Accardi 17821fd68434SRafael J. Wysocki if (ahci_broken_system_poweroff(pdev)) { 17831fd68434SRafael J. Wysocki pi.flags |= ATA_FLAG_NO_POWEROFF_SPINDOWN; 17841fd68434SRafael J. Wysocki dev_info(&pdev->dev, 17851fd68434SRafael J. Wysocki "quirky BIOS, skipping spindown on poweroff\n"); 17861fd68434SRafael J. Wysocki } 17871fd68434SRafael J. Wysocki 1788240630e6SHans de Goede if (ahci_broken_lpm(pdev)) { 1789240630e6SHans de Goede pi.flags |= ATA_FLAG_NO_LPM; 1790240630e6SHans de Goede dev_warn(&pdev->dev, 1791240630e6SHans de Goede "BIOS update required for Link Power Management support\n"); 1792240630e6SHans de Goede } 1793240630e6SHans de Goede 17949b10ae86STejun Heo if (ahci_broken_suspend(pdev)) { 17959b10ae86STejun Heo hpriv->flags |= AHCI_HFLAG_NO_SUSPEND; 1796a44fec1fSJoe Perches dev_warn(&pdev->dev, 17979b10ae86STejun Heo "BIOS update required for suspend/resume\n"); 17989b10ae86STejun Heo } 17999b10ae86STejun Heo 18005594639aSTejun Heo if (ahci_broken_online(pdev)) { 18015594639aSTejun Heo hpriv->flags |= AHCI_HFLAG_SRST_TOUT_IS_OFFLINE; 18025594639aSTejun Heo dev_info(&pdev->dev, 18035594639aSTejun Heo "online status unreliable, applying workaround\n"); 18045594639aSTejun Heo } 18055594639aSTejun Heo 18068bfd1743SSui Chen 18078bfd1743SSui Chen /* Acer SA5-271 workaround modifies private_data */ 18088bfd1743SSui Chen acer_sa5_271_workaround(hpriv, pdev); 18098bfd1743SSui Chen 1810837f5f8fSTejun Heo /* CAP.NP sometimes indicate the index of the last enabled 1811837f5f8fSTejun Heo * port, at other times, that of the last possible port, so 1812837f5f8fSTejun Heo * determining the maximum port number requires looking at 1813837f5f8fSTejun Heo * both CAP.NP and port_map. 1814837f5f8fSTejun Heo */ 1815837f5f8fSTejun Heo n_ports = max(ahci_nr_ports(hpriv->cap), fls(hpriv->port_map)); 1816837f5f8fSTejun Heo 1817837f5f8fSTejun Heo host = ata_host_alloc_pinfo(&pdev->dev, ppi, n_ports); 18184447d351STejun Heo if (!host) 18194447d351STejun Heo return -ENOMEM; 18204447d351STejun Heo host->private_data = hpriv; 18210b9e2988SChristoph Hellwig 18220b9e2988SChristoph Hellwig if (ahci_init_msi(pdev, n_ports, hpriv) < 0) { 18230b9e2988SChristoph Hellwig /* legacy intx interrupts */ 18240b9e2988SChristoph Hellwig pci_intx(pdev, 1); 18250b9e2988SChristoph Hellwig } 18260ce57f8aSChristoph Hellwig hpriv->irq = pci_irq_vector(pdev, 0); 182721bfd1aaSRobert Richter 1828f3d7f23fSArjan van de Ven if (!(hpriv->cap & HOST_CAP_SSS) || ahci_ignore_sss) 1829886ad09fSArjan van de Ven host->flags |= ATA_HOST_PARALLEL_SCAN; 1830f3d7f23fSArjan van de Ven else 1831d2782d96SJingoo Han dev_info(&pdev->dev, "SSS flag set, parallel bus scan disabled\n"); 1832886ad09fSArjan van de Ven 183318f7ba4cSKristen Carlson Accardi if (pi.flags & ATA_FLAG_EM) 183418f7ba4cSKristen Carlson Accardi ahci_reset_em(host); 183518f7ba4cSKristen Carlson Accardi 18364447d351STejun Heo for (i = 0; i < host->n_ports; i++) { 18374447d351STejun Heo struct ata_port *ap = host->ports[i]; 18384447d351STejun Heo 1839318893e1SAlessandro Rubini ata_port_pbar_desc(ap, ahci_pci_bar, -1, "abar"); 1840318893e1SAlessandro Rubini ata_port_pbar_desc(ap, ahci_pci_bar, 1841cbcdd875STejun Heo 0x100 + ap->port_no * 0x80, "port"); 1842cbcdd875STejun Heo 184318f7ba4cSKristen Carlson Accardi /* set enclosure management message type */ 184418f7ba4cSKristen Carlson Accardi if (ap->flags & ATA_FLAG_EM) 1845008dbd61SHarry Zhang ap->em_message_type = hpriv->em_msg_type; 184618f7ba4cSKristen Carlson Accardi 1847b1a9585cSSrinivas Pandruvada ahci_update_initial_lpm_policy(ap, hpriv); 184818f7ba4cSKristen Carlson Accardi 1849dab632e8SJeff Garzik /* disabled/not-implemented port */ 1850350756f6STejun Heo if (!(hpriv->port_map & (1 << i))) 1851dab632e8SJeff Garzik ap->ops = &ata_dummy_port_ops; 18524447d351STejun Heo } 1853c6fd2807SJeff Garzik 1854edc93052STejun Heo /* apply workaround for ASUS P5W DH Deluxe mainboard */ 1855edc93052STejun Heo ahci_p5wdh_workaround(host); 1856edc93052STejun Heo 1857f80ae7e4STejun Heo /* apply gtf filter quirk */ 1858f80ae7e4STejun Heo ahci_gtf_filter_workaround(host); 1859f80ae7e4STejun Heo 1860c6fd2807SJeff Garzik /* initialize adapter */ 18614447d351STejun Heo rc = ahci_configure_dma_masks(pdev, hpriv->cap & HOST_CAP_64); 1862c6fd2807SJeff Garzik if (rc) 186324dc5f33STejun Heo return rc; 1864c6fd2807SJeff Garzik 1865c312ef17SDan Williams rc = ahci_reset_controller(host); 18664447d351STejun Heo if (rc) 18674447d351STejun Heo return rc; 1868c6fd2807SJeff Garzik 1869781d6550SAnton Vorontsov ahci_pci_init_controller(host); 1870439fcaecSAnton Vorontsov ahci_pci_print_info(host); 1871c6fd2807SJeff Garzik 18724447d351STejun Heo pci_set_master(pdev); 18735ca72c4fSAlexander Gordeev 187402e53293SMika Westerberg rc = ahci_host_activate(host, &ahci_sht); 187502e53293SMika Westerberg if (rc) 187602e53293SMika Westerberg return rc; 187702e53293SMika Westerberg 187802e53293SMika Westerberg pm_runtime_put_noidle(&pdev->dev); 187902e53293SMika Westerberg return 0; 188002e53293SMika Westerberg } 188102e53293SMika Westerberg 1882*10a663a1SPrabhakar Kushwaha static void ahci_shutdown_one(struct pci_dev *pdev) 1883*10a663a1SPrabhakar Kushwaha { 1884*10a663a1SPrabhakar Kushwaha ata_pci_shutdown_one(pdev); 1885*10a663a1SPrabhakar Kushwaha } 1886*10a663a1SPrabhakar Kushwaha 188702e53293SMika Westerberg static void ahci_remove_one(struct pci_dev *pdev) 188802e53293SMika Westerberg { 188902e53293SMika Westerberg pm_runtime_get_noresume(&pdev->dev); 189002e53293SMika Westerberg ata_pci_remove_one(pdev); 1891c6fd2807SJeff Garzik } 1892c6fd2807SJeff Garzik 18932fc75da0SAxel Lin module_pci_driver(ahci_pci_driver); 1894c6fd2807SJeff Garzik 1895c6fd2807SJeff Garzik MODULE_AUTHOR("Jeff Garzik"); 1896c6fd2807SJeff Garzik MODULE_DESCRIPTION("AHCI SATA low-level driver"); 1897c6fd2807SJeff Garzik MODULE_LICENSE("GPL"); 1898c6fd2807SJeff Garzik MODULE_DEVICE_TABLE(pci, ahci_pci_tbl); 1899c6fd2807SJeff Garzik MODULE_VERSION(DRV_VERSION); 1900