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> 29c6fd2807SJeff Garzik #include <scsi/scsi_host.h> 30c6fd2807SJeff Garzik #include <scsi/scsi_cmnd.h> 31c6fd2807SJeff Garzik #include <linux/libata.h> 32aecec8b6SChristoph Hellwig #include <linux/ahci-remap.h> 33aecec8b6SChristoph Hellwig #include <linux/io-64-nonatomic-lo-hi.h> 34365cfa1eSAnton Vorontsov #include "ahci.h" 35c6fd2807SJeff Garzik 36c6fd2807SJeff Garzik #define DRV_NAME "ahci" 377d50b60bSTejun Heo #define DRV_VERSION "3.0" 38c6fd2807SJeff Garzik 39c6fd2807SJeff Garzik enum { 40318893e1SAlessandro Rubini AHCI_PCI_BAR_STA2X11 = 0, 41b7ae128dSRobert Richter AHCI_PCI_BAR_CAVIUM = 0, 42e49bd683STiezhu Yang AHCI_PCI_BAR_LOONGSON = 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, 51b0dd4d7aSLennert Buytenhek board_ahci_43bit_dma, 52441577efSTejun Heo board_ahci_ign_iferr, 53099849afSMario Limonciello board_ahci_low_power, 54a17ab7abSPaul Menzel board_ahci_no_debounce_delay, 5566a7cbc3STejun Heo board_ahci_nomsi, 5667809f85SLevente Kurusa board_ahci_noncq, 57441577efSTejun Heo board_ahci_nosntf, 585f173107STejun Heo board_ahci_yes_fbs, 59441577efSTejun Heo 60441577efSTejun Heo /* board IDs for specific chipsets in alphabetical order */ 617d523bdcSHanna Hawa board_ahci_al, 62dbfe8ef5SDan Williams board_ahci_avn, 63441577efSTejun Heo board_ahci_mcp65, 6483f2b963STejun Heo board_ahci_mcp77, 6583f2b963STejun Heo board_ahci_mcp89, 66441577efSTejun Heo board_ahci_mv, 67441577efSTejun Heo board_ahci_sb600, 68441577efSTejun Heo board_ahci_sb700, /* for SB700 and SB800 */ 69441577efSTejun Heo board_ahci_vt8251, 70441577efSTejun Heo 71c312ef17SDan Williams /* 72c312ef17SDan Williams * board IDs for Intel chipsets that support more than 6 ports 73c312ef17SDan Williams * *and* end up needing the PCS quirk. 74c312ef17SDan Williams */ 75c312ef17SDan Williams board_ahci_pcs7, 76c312ef17SDan Williams 77441577efSTejun Heo /* aliases */ 78441577efSTejun Heo board_ahci_mcp_linux = board_ahci_mcp65, 79441577efSTejun Heo board_ahci_mcp67 = board_ahci_mcp65, 80441577efSTejun Heo board_ahci_mcp73 = board_ahci_mcp65, 8183f2b963STejun Heo board_ahci_mcp79 = board_ahci_mcp77, 82c6fd2807SJeff Garzik }; 83c6fd2807SJeff Garzik 84c6fd2807SJeff Garzik static int ahci_init_one(struct pci_dev *pdev, const struct pci_device_id *ent); 8502e53293SMika Westerberg static void ahci_remove_one(struct pci_dev *dev); 8610a663a1SPrabhakar Kushwaha static void ahci_shutdown_one(struct pci_dev *dev); 8737e14e4fSAdam Vodopjan static void ahci_intel_pcs_quirk(struct pci_dev *pdev, struct ahci_host_priv *hpriv); 88a1efdabaSTejun Heo static int ahci_vt8251_hardreset(struct ata_link *link, unsigned int *class, 89a1efdabaSTejun Heo unsigned long deadline); 90dbfe8ef5SDan Williams static int ahci_avn_hardreset(struct ata_link *link, unsigned int *class, 91dbfe8ef5SDan Williams unsigned long deadline); 92cb85696dSJames Laird static void ahci_mcp89_apple_enable(struct pci_dev *pdev); 93cb85696dSJames Laird static bool is_mcp89_apple(struct pci_dev *pdev); 94a1efdabaSTejun Heo static int ahci_p5wdh_hardreset(struct ata_link *link, unsigned int *class, 95a1efdabaSTejun Heo unsigned long deadline); 9602e53293SMika Westerberg #ifdef CONFIG_PM 9702e53293SMika Westerberg static int ahci_pci_device_runtime_suspend(struct device *dev); 9802e53293SMika Westerberg static int ahci_pci_device_runtime_resume(struct device *dev); 99f1d848f9SMika Westerberg #ifdef CONFIG_PM_SLEEP 100f1d848f9SMika Westerberg static int ahci_pci_device_suspend(struct device *dev); 101f1d848f9SMika Westerberg static int ahci_pci_device_resume(struct device *dev); 102438ac6d5STejun Heo #endif 10302e53293SMika Westerberg #endif /* CONFIG_PM */ 104c6fd2807SJeff Garzik 10525df73d9SBart Van Assche static const struct scsi_host_template ahci_sht = { 106fad16e7aSTejun Heo AHCI_SHT("ahci"), 107fad16e7aSTejun Heo }; 108fad16e7aSTejun Heo 109029cfd6bSTejun Heo static struct ata_port_operations ahci_vt8251_ops = { 110029cfd6bSTejun Heo .inherits = &ahci_ops, 111a1efdabaSTejun Heo .hardreset = ahci_vt8251_hardreset, 112ad616ffbSTejun Heo }; 113ad616ffbSTejun Heo 114029cfd6bSTejun Heo static struct ata_port_operations ahci_p5wdh_ops = { 115029cfd6bSTejun Heo .inherits = &ahci_ops, 116a1efdabaSTejun Heo .hardreset = ahci_p5wdh_hardreset, 117edc93052STejun Heo }; 118edc93052STejun Heo 119dbfe8ef5SDan Williams static struct ata_port_operations ahci_avn_ops = { 120dbfe8ef5SDan Williams .inherits = &ahci_ops, 121dbfe8ef5SDan Williams .hardreset = ahci_avn_hardreset, 122dbfe8ef5SDan Williams }; 123dbfe8ef5SDan Williams 124c6fd2807SJeff Garzik static const struct ata_port_info ahci_port_info[] = { 125441577efSTejun Heo /* by features */ 126facb8fa6SJeffrin Jose [board_ahci] = { 1271188c0d8STejun Heo .flags = AHCI_FLAG_COMMON, 12814bdef98SErik Inge Bolsø .pio_mask = ATA_PIO4, 129469248abSJeff Garzik .udma_mask = ATA_UDMA6, 130c6fd2807SJeff Garzik .port_ops = &ahci_ops, 131c6fd2807SJeff Garzik }, 132b0dd4d7aSLennert Buytenhek [board_ahci_43bit_dma] = { 133b0dd4d7aSLennert Buytenhek AHCI_HFLAGS (AHCI_HFLAG_43BIT_ONLY), 134b0dd4d7aSLennert Buytenhek .flags = AHCI_FLAG_COMMON, 135b0dd4d7aSLennert Buytenhek .pio_mask = ATA_PIO4, 136b0dd4d7aSLennert Buytenhek .udma_mask = ATA_UDMA6, 137b0dd4d7aSLennert Buytenhek .port_ops = &ahci_ops, 138b0dd4d7aSLennert Buytenhek }, 139facb8fa6SJeffrin Jose [board_ahci_ign_iferr] = { 140417a1a6dSTejun Heo AHCI_HFLAGS (AHCI_HFLAG_IGN_IRQ_IF_ERR), 141417a1a6dSTejun Heo .flags = AHCI_FLAG_COMMON, 14214bdef98SErik Inge Bolsø .pio_mask = ATA_PIO4, 143469248abSJeff Garzik .udma_mask = ATA_UDMA6, 14441669553STejun Heo .port_ops = &ahci_ops, 14541669553STejun Heo }, 146099849afSMario Limonciello [board_ahci_low_power] = { 147e5c89479SMario Limonciello AHCI_HFLAGS (AHCI_HFLAG_USE_LPM_POLICY), 148ebb82e3cSHans de Goede .flags = AHCI_FLAG_COMMON, 149ebb82e3cSHans de Goede .pio_mask = ATA_PIO4, 150ebb82e3cSHans de Goede .udma_mask = ATA_UDMA6, 151ebb82e3cSHans de Goede .port_ops = &ahci_ops, 152ebb82e3cSHans de Goede }, 153a17ab7abSPaul Menzel [board_ahci_no_debounce_delay] = { 154a17ab7abSPaul Menzel .flags = AHCI_FLAG_COMMON, 155a17ab7abSPaul Menzel .link_flags = ATA_LFLAG_NO_DEBOUNCE_DELAY, 156a17ab7abSPaul Menzel .pio_mask = ATA_PIO4, 157a17ab7abSPaul Menzel .udma_mask = ATA_UDMA6, 158a17ab7abSPaul Menzel .port_ops = &ahci_ops, 159a17ab7abSPaul Menzel }, 16066a7cbc3STejun Heo [board_ahci_nomsi] = { 16166a7cbc3STejun Heo AHCI_HFLAGS (AHCI_HFLAG_NO_MSI), 16266a7cbc3STejun Heo .flags = AHCI_FLAG_COMMON, 16366a7cbc3STejun Heo .pio_mask = ATA_PIO4, 16466a7cbc3STejun Heo .udma_mask = ATA_UDMA6, 16566a7cbc3STejun Heo .port_ops = &ahci_ops, 16666a7cbc3STejun Heo }, 16767809f85SLevente Kurusa [board_ahci_noncq] = { 16867809f85SLevente Kurusa AHCI_HFLAGS (AHCI_HFLAG_NO_NCQ), 16967809f85SLevente Kurusa .flags = AHCI_FLAG_COMMON, 17067809f85SLevente Kurusa .pio_mask = ATA_PIO4, 17167809f85SLevente Kurusa .udma_mask = ATA_UDMA6, 17267809f85SLevente Kurusa .port_ops = &ahci_ops, 17367809f85SLevente Kurusa }, 174facb8fa6SJeffrin Jose [board_ahci_nosntf] = { 175441577efSTejun Heo AHCI_HFLAGS (AHCI_HFLAG_NO_SNTF), 176441577efSTejun Heo .flags = AHCI_FLAG_COMMON, 177441577efSTejun Heo .pio_mask = ATA_PIO4, 178441577efSTejun Heo .udma_mask = ATA_UDMA6, 179441577efSTejun Heo .port_ops = &ahci_ops, 180441577efSTejun Heo }, 181facb8fa6SJeffrin Jose [board_ahci_yes_fbs] = { 1825f173107STejun Heo AHCI_HFLAGS (AHCI_HFLAG_YES_FBS), 1835f173107STejun Heo .flags = AHCI_FLAG_COMMON, 1845f173107STejun Heo .pio_mask = ATA_PIO4, 1855f173107STejun Heo .udma_mask = ATA_UDMA6, 1865f173107STejun Heo .port_ops = &ahci_ops, 1875f173107STejun Heo }, 188441577efSTejun Heo /* by chipsets */ 1897d523bdcSHanna Hawa [board_ahci_al] = { 1907d523bdcSHanna Hawa AHCI_HFLAGS (AHCI_HFLAG_NO_PMP | AHCI_HFLAG_NO_MSI), 1917d523bdcSHanna Hawa .flags = AHCI_FLAG_COMMON, 1927d523bdcSHanna Hawa .pio_mask = ATA_PIO4, 1937d523bdcSHanna Hawa .udma_mask = ATA_UDMA6, 1947d523bdcSHanna Hawa .port_ops = &ahci_ops, 1957d523bdcSHanna Hawa }, 196dbfe8ef5SDan Williams [board_ahci_avn] = { 197dbfe8ef5SDan Williams .flags = AHCI_FLAG_COMMON, 198dbfe8ef5SDan Williams .pio_mask = ATA_PIO4, 199dbfe8ef5SDan Williams .udma_mask = ATA_UDMA6, 200dbfe8ef5SDan Williams .port_ops = &ahci_avn_ops, 201dbfe8ef5SDan Williams }, 202facb8fa6SJeffrin Jose [board_ahci_mcp65] = { 20383f2b963STejun Heo AHCI_HFLAGS (AHCI_HFLAG_NO_FPDMA_AA | AHCI_HFLAG_NO_PMP | 20483f2b963STejun Heo AHCI_HFLAG_YES_NCQ), 205ae01b249STejun Heo .flags = AHCI_FLAG_COMMON | ATA_FLAG_NO_DIPM, 20683f2b963STejun Heo .pio_mask = ATA_PIO4, 20783f2b963STejun Heo .udma_mask = ATA_UDMA6, 20883f2b963STejun Heo .port_ops = &ahci_ops, 20983f2b963STejun Heo }, 210facb8fa6SJeffrin Jose [board_ahci_mcp77] = { 21183f2b963STejun Heo AHCI_HFLAGS (AHCI_HFLAG_NO_FPDMA_AA | AHCI_HFLAG_NO_PMP), 21283f2b963STejun Heo .flags = AHCI_FLAG_COMMON, 21383f2b963STejun Heo .pio_mask = ATA_PIO4, 21483f2b963STejun Heo .udma_mask = ATA_UDMA6, 21583f2b963STejun Heo .port_ops = &ahci_ops, 21683f2b963STejun Heo }, 217facb8fa6SJeffrin Jose [board_ahci_mcp89] = { 21883f2b963STejun Heo AHCI_HFLAGS (AHCI_HFLAG_NO_FPDMA_AA), 219441577efSTejun Heo .flags = AHCI_FLAG_COMMON, 220441577efSTejun Heo .pio_mask = ATA_PIO4, 221441577efSTejun Heo .udma_mask = ATA_UDMA6, 222441577efSTejun Heo .port_ops = &ahci_ops, 223441577efSTejun Heo }, 224facb8fa6SJeffrin Jose [board_ahci_mv] = { 225441577efSTejun Heo AHCI_HFLAGS (AHCI_HFLAG_NO_NCQ | AHCI_HFLAG_NO_MSI | 226441577efSTejun Heo AHCI_HFLAG_MV_PATA | AHCI_HFLAG_NO_PMP), 2279cbe056fSSergei Shtylyov .flags = ATA_FLAG_SATA | ATA_FLAG_PIO_DMA, 228441577efSTejun Heo .pio_mask = ATA_PIO4, 229441577efSTejun Heo .udma_mask = ATA_UDMA6, 230441577efSTejun Heo .port_ops = &ahci_ops, 231441577efSTejun Heo }, 232facb8fa6SJeffrin Jose [board_ahci_sb600] = { 233417a1a6dSTejun Heo AHCI_HFLAGS (AHCI_HFLAG_IGN_SERR_INTERNAL | 2342fcad9d2STejun Heo AHCI_HFLAG_NO_MSI | AHCI_HFLAG_SECT255 | 2352fcad9d2STejun Heo AHCI_HFLAG_32BIT_ONLY), 236417a1a6dSTejun Heo .flags = AHCI_FLAG_COMMON, 23714bdef98SErik Inge Bolsø .pio_mask = ATA_PIO4, 238469248abSJeff Garzik .udma_mask = ATA_UDMA6, 239345347c5SYuan-Hsin Chen .port_ops = &ahci_pmp_retry_srst_ops, 24055a61604SConke Hu }, 241facb8fa6SJeffrin Jose [board_ahci_sb700] = { /* for SB700 and SB800 */ 242bd17243aSShane Huang AHCI_HFLAGS (AHCI_HFLAG_IGN_SERR_INTERNAL), 243e39fc8c9SShane Huang .flags = AHCI_FLAG_COMMON, 24414bdef98SErik Inge Bolsø .pio_mask = ATA_PIO4, 245e39fc8c9SShane Huang .udma_mask = ATA_UDMA6, 246345347c5SYuan-Hsin Chen .port_ops = &ahci_pmp_retry_srst_ops, 247e39fc8c9SShane Huang }, 248facb8fa6SJeffrin Jose [board_ahci_vt8251] = { 249441577efSTejun Heo AHCI_HFLAGS (AHCI_HFLAG_NO_NCQ | AHCI_HFLAG_NO_PMP), 250e297d99eSTejun Heo .flags = AHCI_FLAG_COMMON, 25114bdef98SErik Inge Bolsø .pio_mask = ATA_PIO4, 252e297d99eSTejun Heo .udma_mask = ATA_UDMA6, 253441577efSTejun Heo .port_ops = &ahci_vt8251_ops, 2541b677afdSShaohua Li }, 255c312ef17SDan Williams [board_ahci_pcs7] = { 256c312ef17SDan Williams .flags = AHCI_FLAG_COMMON, 257c312ef17SDan Williams .pio_mask = ATA_PIO4, 258c312ef17SDan Williams .udma_mask = ATA_UDMA6, 259c312ef17SDan Williams .port_ops = &ahci_ops, 260c312ef17SDan Williams }, 261c6fd2807SJeff Garzik }; 262c6fd2807SJeff Garzik 263c6fd2807SJeff Garzik static const struct pci_device_id ahci_pci_tbl[] = { 264c6fd2807SJeff Garzik /* Intel */ 2655e125d13SMika Westerberg { PCI_VDEVICE(INTEL, 0x06d6), board_ahci }, /* Comet Lake PCH-H RAID */ 26654bb3a94SJeff Garzik { PCI_VDEVICE(INTEL, 0x2652), board_ahci }, /* ICH6 */ 26754bb3a94SJeff Garzik { PCI_VDEVICE(INTEL, 0x2653), board_ahci }, /* ICH6M */ 26854bb3a94SJeff Garzik { PCI_VDEVICE(INTEL, 0x27c1), board_ahci }, /* ICH7 */ 26954bb3a94SJeff Garzik { PCI_VDEVICE(INTEL, 0x27c5), board_ahci }, /* ICH7M */ 27054bb3a94SJeff Garzik { PCI_VDEVICE(INTEL, 0x27c3), board_ahci }, /* ICH7R */ 27182490c09STejun Heo { PCI_VDEVICE(AL, 0x5288), board_ahci_ign_iferr }, /* ULi M5288 */ 27254bb3a94SJeff Garzik { PCI_VDEVICE(INTEL, 0x2681), board_ahci }, /* ESB2 */ 27354bb3a94SJeff Garzik { PCI_VDEVICE(INTEL, 0x2682), board_ahci }, /* ESB2 */ 27454bb3a94SJeff Garzik { PCI_VDEVICE(INTEL, 0x2683), board_ahci }, /* ESB2 */ 27554bb3a94SJeff Garzik { PCI_VDEVICE(INTEL, 0x27c6), board_ahci }, /* ICH7-M DH */ 2767a234affSTejun Heo { PCI_VDEVICE(INTEL, 0x2821), board_ahci }, /* ICH8 */ 2770e96dc47SKrzysztof Kozlowski { PCI_VDEVICE(INTEL, 0x2822), board_ahci_nosntf }, /* ICH8/Lewisburg RAID*/ 2787a234affSTejun Heo { PCI_VDEVICE(INTEL, 0x2824), board_ahci }, /* ICH8 */ 2797a234affSTejun Heo { PCI_VDEVICE(INTEL, 0x2829), board_ahci }, /* ICH8M */ 2807a234affSTejun Heo { PCI_VDEVICE(INTEL, 0x282a), board_ahci }, /* ICH8M */ 2817a234affSTejun Heo { PCI_VDEVICE(INTEL, 0x2922), board_ahci }, /* ICH9 */ 2827a234affSTejun Heo { PCI_VDEVICE(INTEL, 0x2923), board_ahci }, /* ICH9 */ 2837a234affSTejun Heo { PCI_VDEVICE(INTEL, 0x2924), board_ahci }, /* ICH9 */ 2847a234affSTejun Heo { PCI_VDEVICE(INTEL, 0x2925), board_ahci }, /* ICH9 */ 2857a234affSTejun Heo { PCI_VDEVICE(INTEL, 0x2927), board_ahci }, /* ICH9 */ 286099849afSMario Limonciello { PCI_VDEVICE(INTEL, 0x2929), board_ahci_low_power }, /* ICH9M */ 287099849afSMario Limonciello { PCI_VDEVICE(INTEL, 0x292a), board_ahci_low_power }, /* ICH9M */ 288099849afSMario Limonciello { PCI_VDEVICE(INTEL, 0x292b), board_ahci_low_power }, /* ICH9M */ 289099849afSMario Limonciello { PCI_VDEVICE(INTEL, 0x292c), board_ahci_low_power }, /* ICH9M */ 290099849afSMario Limonciello { PCI_VDEVICE(INTEL, 0x292f), board_ahci_low_power }, /* ICH9M */ 2917a234affSTejun Heo { PCI_VDEVICE(INTEL, 0x294d), board_ahci }, /* ICH9 */ 292099849afSMario Limonciello { PCI_VDEVICE(INTEL, 0x294e), board_ahci_low_power }, /* ICH9M */ 293d4155e6fSJason Gaston { PCI_VDEVICE(INTEL, 0x502a), board_ahci }, /* Tolapai */ 294d4155e6fSJason Gaston { PCI_VDEVICE(INTEL, 0x502b), board_ahci }, /* Tolapai */ 29516ad1ad9SJason Gaston { PCI_VDEVICE(INTEL, 0x3a05), board_ahci }, /* ICH10 */ 296b2dde6afSMark Goodwin { PCI_VDEVICE(INTEL, 0x3a22), board_ahci }, /* ICH10 */ 29716ad1ad9SJason Gaston { PCI_VDEVICE(INTEL, 0x3a25), board_ahci }, /* ICH10 */ 298c1f57d9bSDavid Milburn { PCI_VDEVICE(INTEL, 0x3b22), board_ahci }, /* PCH AHCI */ 299c1f57d9bSDavid Milburn { PCI_VDEVICE(INTEL, 0x3b23), board_ahci }, /* PCH AHCI */ 300adcb5308SSeth Heasley { PCI_VDEVICE(INTEL, 0x3b24), board_ahci }, /* PCH RAID */ 3018e48b6b3SSeth Heasley { PCI_VDEVICE(INTEL, 0x3b25), board_ahci }, /* PCH RAID */ 302099849afSMario Limonciello { PCI_VDEVICE(INTEL, 0x3b29), board_ahci_low_power }, /* PCH M AHCI */ 303adcb5308SSeth Heasley { PCI_VDEVICE(INTEL, 0x3b2b), board_ahci }, /* PCH RAID */ 304099849afSMario Limonciello { PCI_VDEVICE(INTEL, 0x3b2c), board_ahci_low_power }, /* PCH M RAID */ 305c1f57d9bSDavid Milburn { PCI_VDEVICE(INTEL, 0x3b2f), board_ahci }, /* PCH AHCI */ 306c312ef17SDan Williams { PCI_VDEVICE(INTEL, 0x19b0), board_ahci_pcs7 }, /* DNV AHCI */ 307c312ef17SDan Williams { PCI_VDEVICE(INTEL, 0x19b1), board_ahci_pcs7 }, /* DNV AHCI */ 308c312ef17SDan Williams { PCI_VDEVICE(INTEL, 0x19b2), board_ahci_pcs7 }, /* DNV AHCI */ 309c312ef17SDan Williams { PCI_VDEVICE(INTEL, 0x19b3), board_ahci_pcs7 }, /* DNV AHCI */ 310c312ef17SDan Williams { PCI_VDEVICE(INTEL, 0x19b4), board_ahci_pcs7 }, /* DNV AHCI */ 311c312ef17SDan Williams { PCI_VDEVICE(INTEL, 0x19b5), board_ahci_pcs7 }, /* DNV AHCI */ 312c312ef17SDan Williams { PCI_VDEVICE(INTEL, 0x19b6), board_ahci_pcs7 }, /* DNV AHCI */ 313c312ef17SDan Williams { PCI_VDEVICE(INTEL, 0x19b7), board_ahci_pcs7 }, /* DNV AHCI */ 314c312ef17SDan Williams { PCI_VDEVICE(INTEL, 0x19bE), board_ahci_pcs7 }, /* DNV AHCI */ 315c312ef17SDan Williams { PCI_VDEVICE(INTEL, 0x19bF), board_ahci_pcs7 }, /* DNV AHCI */ 316c312ef17SDan Williams { PCI_VDEVICE(INTEL, 0x19c0), board_ahci_pcs7 }, /* DNV AHCI */ 317c312ef17SDan Williams { PCI_VDEVICE(INTEL, 0x19c1), board_ahci_pcs7 }, /* DNV AHCI */ 318c312ef17SDan Williams { PCI_VDEVICE(INTEL, 0x19c2), board_ahci_pcs7 }, /* DNV AHCI */ 319c312ef17SDan Williams { PCI_VDEVICE(INTEL, 0x19c3), board_ahci_pcs7 }, /* DNV AHCI */ 320c312ef17SDan Williams { PCI_VDEVICE(INTEL, 0x19c4), board_ahci_pcs7 }, /* DNV AHCI */ 321c312ef17SDan Williams { PCI_VDEVICE(INTEL, 0x19c5), board_ahci_pcs7 }, /* DNV AHCI */ 322c312ef17SDan Williams { PCI_VDEVICE(INTEL, 0x19c6), board_ahci_pcs7 }, /* DNV AHCI */ 323c312ef17SDan Williams { PCI_VDEVICE(INTEL, 0x19c7), board_ahci_pcs7 }, /* DNV AHCI */ 324c312ef17SDan Williams { PCI_VDEVICE(INTEL, 0x19cE), board_ahci_pcs7 }, /* DNV AHCI */ 325c312ef17SDan Williams { PCI_VDEVICE(INTEL, 0x19cF), board_ahci_pcs7 }, /* DNV AHCI */ 3265623cab8SSeth Heasley { PCI_VDEVICE(INTEL, 0x1c02), board_ahci }, /* CPT AHCI */ 327099849afSMario Limonciello { PCI_VDEVICE(INTEL, 0x1c03), board_ahci_low_power }, /* CPT M AHCI */ 3285623cab8SSeth Heasley { PCI_VDEVICE(INTEL, 0x1c04), board_ahci }, /* CPT RAID */ 329099849afSMario Limonciello { PCI_VDEVICE(INTEL, 0x1c05), board_ahci_low_power }, /* CPT M RAID */ 3305623cab8SSeth Heasley { PCI_VDEVICE(INTEL, 0x1c06), board_ahci }, /* CPT RAID */ 3315623cab8SSeth Heasley { PCI_VDEVICE(INTEL, 0x1c07), board_ahci }, /* CPT RAID */ 332992b3fb9SSeth Heasley { PCI_VDEVICE(INTEL, 0x1d02), board_ahci }, /* PBG AHCI */ 333992b3fb9SSeth Heasley { PCI_VDEVICE(INTEL, 0x1d04), board_ahci }, /* PBG RAID */ 334992b3fb9SSeth Heasley { PCI_VDEVICE(INTEL, 0x1d06), board_ahci }, /* PBG RAID */ 335a4a461a6SSeth Heasley { PCI_VDEVICE(INTEL, 0x2323), board_ahci }, /* DH89xxCC AHCI */ 336181e3ceaSSeth Heasley { PCI_VDEVICE(INTEL, 0x1e02), board_ahci }, /* Panther Point AHCI */ 337099849afSMario Limonciello { PCI_VDEVICE(INTEL, 0x1e03), board_ahci_low_power }, /* Panther M AHCI */ 338181e3ceaSSeth Heasley { PCI_VDEVICE(INTEL, 0x1e04), board_ahci }, /* Panther Point RAID */ 339181e3ceaSSeth Heasley { PCI_VDEVICE(INTEL, 0x1e05), board_ahci }, /* Panther Point RAID */ 340181e3ceaSSeth Heasley { PCI_VDEVICE(INTEL, 0x1e06), board_ahci }, /* Panther Point RAID */ 341099849afSMario Limonciello { PCI_VDEVICE(INTEL, 0x1e07), board_ahci_low_power }, /* Panther M RAID */ 3422cab7a4cSSeth Heasley { PCI_VDEVICE(INTEL, 0x1e0e), board_ahci }, /* Panther Point RAID */ 343ea4ace66SSeth Heasley { PCI_VDEVICE(INTEL, 0x8c02), board_ahci }, /* Lynx Point AHCI */ 344099849afSMario Limonciello { PCI_VDEVICE(INTEL, 0x8c03), board_ahci_low_power }, /* Lynx M AHCI */ 345ea4ace66SSeth Heasley { PCI_VDEVICE(INTEL, 0x8c04), board_ahci }, /* Lynx Point RAID */ 346099849afSMario Limonciello { PCI_VDEVICE(INTEL, 0x8c05), board_ahci_low_power }, /* Lynx M RAID */ 347ea4ace66SSeth Heasley { PCI_VDEVICE(INTEL, 0x8c06), board_ahci }, /* Lynx Point RAID */ 348099849afSMario Limonciello { PCI_VDEVICE(INTEL, 0x8c07), board_ahci_low_power }, /* Lynx M RAID */ 349ea4ace66SSeth Heasley { PCI_VDEVICE(INTEL, 0x8c0e), board_ahci }, /* Lynx Point RAID */ 350099849afSMario Limonciello { PCI_VDEVICE(INTEL, 0x8c0f), board_ahci_low_power }, /* Lynx M RAID */ 351099849afSMario Limonciello { PCI_VDEVICE(INTEL, 0x9c02), board_ahci_low_power }, /* Lynx LP AHCI */ 352099849afSMario Limonciello { PCI_VDEVICE(INTEL, 0x9c03), board_ahci_low_power }, /* Lynx LP AHCI */ 353099849afSMario Limonciello { PCI_VDEVICE(INTEL, 0x9c04), board_ahci_low_power }, /* Lynx LP RAID */ 354099849afSMario Limonciello { PCI_VDEVICE(INTEL, 0x9c05), board_ahci_low_power }, /* Lynx LP RAID */ 355099849afSMario Limonciello { PCI_VDEVICE(INTEL, 0x9c06), board_ahci_low_power }, /* Lynx LP RAID */ 356099849afSMario Limonciello { PCI_VDEVICE(INTEL, 0x9c07), board_ahci_low_power }, /* Lynx LP RAID */ 357099849afSMario Limonciello { PCI_VDEVICE(INTEL, 0x9c0e), board_ahci_low_power }, /* Lynx LP RAID */ 358099849afSMario Limonciello { PCI_VDEVICE(INTEL, 0x9c0f), board_ahci_low_power }, /* Lynx LP RAID */ 359099849afSMario Limonciello { PCI_VDEVICE(INTEL, 0x9dd3), board_ahci_low_power }, /* Cannon Lake PCH-LP AHCI */ 36029e674ddSSeth Heasley { PCI_VDEVICE(INTEL, 0x1f22), board_ahci }, /* Avoton AHCI */ 36129e674ddSSeth Heasley { PCI_VDEVICE(INTEL, 0x1f23), board_ahci }, /* Avoton AHCI */ 36229e674ddSSeth Heasley { PCI_VDEVICE(INTEL, 0x1f24), board_ahci }, /* Avoton RAID */ 36329e674ddSSeth Heasley { PCI_VDEVICE(INTEL, 0x1f25), board_ahci }, /* Avoton RAID */ 36429e674ddSSeth Heasley { PCI_VDEVICE(INTEL, 0x1f26), board_ahci }, /* Avoton RAID */ 36529e674ddSSeth Heasley { PCI_VDEVICE(INTEL, 0x1f27), board_ahci }, /* Avoton RAID */ 36629e674ddSSeth Heasley { PCI_VDEVICE(INTEL, 0x1f2e), board_ahci }, /* Avoton RAID */ 36729e674ddSSeth Heasley { PCI_VDEVICE(INTEL, 0x1f2f), board_ahci }, /* Avoton RAID */ 368dbfe8ef5SDan Williams { PCI_VDEVICE(INTEL, 0x1f32), board_ahci_avn }, /* Avoton AHCI */ 369dbfe8ef5SDan Williams { PCI_VDEVICE(INTEL, 0x1f33), board_ahci_avn }, /* Avoton AHCI */ 370dbfe8ef5SDan Williams { PCI_VDEVICE(INTEL, 0x1f34), board_ahci_avn }, /* Avoton RAID */ 371dbfe8ef5SDan Williams { PCI_VDEVICE(INTEL, 0x1f35), board_ahci_avn }, /* Avoton RAID */ 372dbfe8ef5SDan Williams { PCI_VDEVICE(INTEL, 0x1f36), board_ahci_avn }, /* Avoton RAID */ 373dbfe8ef5SDan Williams { PCI_VDEVICE(INTEL, 0x1f37), board_ahci_avn }, /* Avoton RAID */ 374dbfe8ef5SDan Williams { PCI_VDEVICE(INTEL, 0x1f3e), board_ahci_avn }, /* Avoton RAID */ 375dbfe8ef5SDan Williams { PCI_VDEVICE(INTEL, 0x1f3f), board_ahci_avn }, /* Avoton RAID */ 3760e96dc47SKrzysztof Kozlowski { PCI_VDEVICE(INTEL, 0x2823), board_ahci }, /* Wellsburg/Lewisburg AHCI*/ 3775716fb0dSDan Williams { PCI_VDEVICE(INTEL, 0x2826), board_ahci }, /* *burg SATA0 'RAID' */ 3785716fb0dSDan Williams { PCI_VDEVICE(INTEL, 0x2827), board_ahci }, /* *burg SATA1 'RAID' */ 3795716fb0dSDan Williams { PCI_VDEVICE(INTEL, 0x282f), board_ahci }, /* *burg SATA2 'RAID' */ 3808e85f605SMika Westerberg { PCI_VDEVICE(INTEL, 0x43d4), board_ahci }, /* Rocket Lake PCH-H RAID */ 3818e85f605SMika Westerberg { PCI_VDEVICE(INTEL, 0x43d5), board_ahci }, /* Rocket Lake PCH-H RAID */ 3828e85f605SMika Westerberg { PCI_VDEVICE(INTEL, 0x43d6), board_ahci }, /* Rocket Lake PCH-H RAID */ 3838e85f605SMika Westerberg { PCI_VDEVICE(INTEL, 0x43d7), board_ahci }, /* Rocket Lake PCH-H RAID */ 384151743fdSJames Ralston { PCI_VDEVICE(INTEL, 0x8d02), board_ahci }, /* Wellsburg AHCI */ 385151743fdSJames Ralston { PCI_VDEVICE(INTEL, 0x8d04), board_ahci }, /* Wellsburg RAID */ 386151743fdSJames Ralston { PCI_VDEVICE(INTEL, 0x8d06), board_ahci }, /* Wellsburg RAID */ 387151743fdSJames Ralston { PCI_VDEVICE(INTEL, 0x8d0e), board_ahci }, /* Wellsburg RAID */ 388151743fdSJames Ralston { PCI_VDEVICE(INTEL, 0x8d62), board_ahci }, /* Wellsburg AHCI */ 389151743fdSJames Ralston { PCI_VDEVICE(INTEL, 0x8d64), board_ahci }, /* Wellsburg RAID */ 390151743fdSJames Ralston { PCI_VDEVICE(INTEL, 0x8d66), board_ahci }, /* Wellsburg RAID */ 391151743fdSJames Ralston { PCI_VDEVICE(INTEL, 0x8d6e), board_ahci }, /* Wellsburg RAID */ 3921cfc7df3SSeth Heasley { PCI_VDEVICE(INTEL, 0x23a3), board_ahci }, /* Coleto Creek AHCI */ 393099849afSMario Limonciello { PCI_VDEVICE(INTEL, 0x9c83), board_ahci_low_power }, /* Wildcat LP AHCI */ 394099849afSMario Limonciello { PCI_VDEVICE(INTEL, 0x9c85), board_ahci_low_power }, /* Wildcat LP RAID */ 395099849afSMario Limonciello { PCI_VDEVICE(INTEL, 0x9c87), board_ahci_low_power }, /* Wildcat LP RAID */ 396099849afSMario Limonciello { PCI_VDEVICE(INTEL, 0x9c8f), board_ahci_low_power }, /* Wildcat LP RAID */ 3971b071a09SJames Ralston { PCI_VDEVICE(INTEL, 0x8c82), board_ahci }, /* 9 Series AHCI */ 398099849afSMario Limonciello { PCI_VDEVICE(INTEL, 0x8c83), board_ahci_low_power }, /* 9 Series M AHCI */ 3991b071a09SJames Ralston { PCI_VDEVICE(INTEL, 0x8c84), board_ahci }, /* 9 Series RAID */ 400099849afSMario Limonciello { PCI_VDEVICE(INTEL, 0x8c85), board_ahci_low_power }, /* 9 Series M RAID */ 4011b071a09SJames Ralston { PCI_VDEVICE(INTEL, 0x8c86), board_ahci }, /* 9 Series RAID */ 402099849afSMario Limonciello { PCI_VDEVICE(INTEL, 0x8c87), board_ahci_low_power }, /* 9 Series M RAID */ 4031b071a09SJames Ralston { PCI_VDEVICE(INTEL, 0x8c8e), board_ahci }, /* 9 Series RAID */ 404099849afSMario Limonciello { PCI_VDEVICE(INTEL, 0x8c8f), board_ahci_low_power }, /* 9 Series M RAID */ 405099849afSMario Limonciello { PCI_VDEVICE(INTEL, 0x9d03), board_ahci_low_power }, /* Sunrise LP AHCI */ 406099849afSMario Limonciello { PCI_VDEVICE(INTEL, 0x9d05), board_ahci_low_power }, /* Sunrise LP RAID */ 407099849afSMario Limonciello { PCI_VDEVICE(INTEL, 0x9d07), board_ahci_low_power }, /* Sunrise LP RAID */ 408c5967b79SCharles_Rose@Dell.com { PCI_VDEVICE(INTEL, 0xa102), board_ahci }, /* Sunrise Point-H AHCI */ 409099849afSMario Limonciello { PCI_VDEVICE(INTEL, 0xa103), board_ahci_low_power }, /* Sunrise M AHCI */ 410690000b9SJames Ralston { PCI_VDEVICE(INTEL, 0xa105), board_ahci }, /* Sunrise Point-H RAID */ 411c5967b79SCharles_Rose@Dell.com { PCI_VDEVICE(INTEL, 0xa106), board_ahci }, /* Sunrise Point-H RAID */ 412099849afSMario Limonciello { PCI_VDEVICE(INTEL, 0xa107), board_ahci_low_power }, /* Sunrise M RAID */ 413690000b9SJames Ralston { PCI_VDEVICE(INTEL, 0xa10f), board_ahci }, /* Sunrise Point-H RAID */ 4144d92f009SAlexandra Yates { PCI_VDEVICE(INTEL, 0xa182), board_ahci }, /* Lewisburg AHCI*/ 4154d92f009SAlexandra Yates { PCI_VDEVICE(INTEL, 0xa186), board_ahci }, /* Lewisburg RAID*/ 416f5bdd66cSAlexandra Yates { PCI_VDEVICE(INTEL, 0xa1d2), board_ahci }, /* Lewisburg RAID*/ 417f5bdd66cSAlexandra Yates { PCI_VDEVICE(INTEL, 0xa1d6), board_ahci }, /* Lewisburg RAID*/ 4184d92f009SAlexandra Yates { PCI_VDEVICE(INTEL, 0xa202), board_ahci }, /* Lewisburg AHCI*/ 4194d92f009SAlexandra Yates { PCI_VDEVICE(INTEL, 0xa206), board_ahci }, /* Lewisburg RAID*/ 420f5bdd66cSAlexandra Yates { PCI_VDEVICE(INTEL, 0xa252), board_ahci }, /* Lewisburg RAID*/ 421f5bdd66cSAlexandra Yates { PCI_VDEVICE(INTEL, 0xa256), board_ahci }, /* Lewisburg RAID*/ 422f919dde0SMika Westerberg { PCI_VDEVICE(INTEL, 0xa356), board_ahci }, /* Cannon Lake PCH-H RAID */ 42332d25454SKai-Heng Feng { PCI_VDEVICE(INTEL, 0x06d7), board_ahci }, /* Comet Lake-H RAID */ 42458c42b0bSMika Westerberg { PCI_VDEVICE(INTEL, 0xa386), board_ahci }, /* Comet Lake PCH-V RAID */ 425099849afSMario Limonciello { PCI_VDEVICE(INTEL, 0x0f22), board_ahci_low_power }, /* Bay Trail AHCI */ 426099849afSMario Limonciello { PCI_VDEVICE(INTEL, 0x0f23), board_ahci_low_power }, /* Bay Trail AHCI */ 427099849afSMario Limonciello { PCI_VDEVICE(INTEL, 0x22a3), board_ahci_low_power }, /* Cherry Tr. AHCI */ 428099849afSMario Limonciello { PCI_VDEVICE(INTEL, 0x5ae3), board_ahci_low_power }, /* ApolloLake AHCI */ 429099849afSMario Limonciello { PCI_VDEVICE(INTEL, 0x34d3), board_ahci_low_power }, /* Ice Lake LP AHCI */ 430099849afSMario Limonciello { PCI_VDEVICE(INTEL, 0x02d3), board_ahci_low_power }, /* Comet Lake PCH-U AHCI */ 431099849afSMario Limonciello { PCI_VDEVICE(INTEL, 0x02d7), board_ahci_low_power }, /* Comet Lake PCH RAID */ 4322a2df98eSWerner Fischer /* Elkhart Lake IDs 0x4b60 & 0x4b62 https://sata-io.org/product/8803 not tested yet */ 4332a2df98eSWerner Fischer { PCI_VDEVICE(INTEL, 0x4b63), board_ahci_low_power }, /* Elkhart Lake AHCI */ 434c6fd2807SJeff Garzik 435e34bb370STejun Heo /* JMicron 360/1/3/5/6, match class to avoid IDE function */ 436e34bb370STejun Heo { PCI_VENDOR_ID_JMICRON, PCI_ANY_ID, PCI_ANY_ID, PCI_ANY_ID, 437e34bb370STejun Heo PCI_CLASS_STORAGE_SATA_AHCI, 0xffffff, board_ahci_ign_iferr }, 4381fefb8fdSBen Hutchings /* JMicron 362B and 362C have an AHCI function with IDE class code */ 4391fefb8fdSBen Hutchings { PCI_VDEVICE(JMICRON, 0x2362), board_ahci_ign_iferr }, 4401fefb8fdSBen Hutchings { PCI_VDEVICE(JMICRON, 0x236f), board_ahci_ign_iferr }, 44191f15fb3SZhang Rui /* May need to update quirk_jmicron_async_suspend() for additions */ 442c6fd2807SJeff Garzik 443c6fd2807SJeff Garzik /* ATI */ 444c65ec1c2SConke Hu { PCI_VDEVICE(ATI, 0x4380), board_ahci_sb600 }, /* ATI SB600 */ 445e39fc8c9SShane Huang { PCI_VDEVICE(ATI, 0x4390), board_ahci_sb700 }, /* ATI SB700/800 */ 446e39fc8c9SShane Huang { PCI_VDEVICE(ATI, 0x4391), board_ahci_sb700 }, /* ATI SB700/800 */ 447e39fc8c9SShane Huang { PCI_VDEVICE(ATI, 0x4392), board_ahci_sb700 }, /* ATI SB700/800 */ 448e39fc8c9SShane Huang { PCI_VDEVICE(ATI, 0x4393), board_ahci_sb700 }, /* ATI SB700/800 */ 449e39fc8c9SShane Huang { PCI_VDEVICE(ATI, 0x4394), board_ahci_sb700 }, /* ATI SB700/800 */ 450e39fc8c9SShane Huang { PCI_VDEVICE(ATI, 0x4395), board_ahci_sb700 }, /* ATI SB700/800 */ 451c6fd2807SJeff Garzik 4527d523bdcSHanna Hawa /* Amazon's Annapurna Labs support */ 4537d523bdcSHanna Hawa { PCI_DEVICE(PCI_VENDOR_ID_AMAZON_ANNAPURNA_LABS, 0x0031), 4547d523bdcSHanna Hawa .class = PCI_CLASS_STORAGE_SATA_AHCI, 4557d523bdcSHanna Hawa .class_mask = 0xffffff, 4567d523bdcSHanna Hawa board_ahci_al }, 457e2dd90b1SShane Huang /* AMD */ 4585deab536SShane Huang { PCI_VDEVICE(AMD, 0x7800), board_ahci }, /* AMD Hudson-2 */ 459a17ab7abSPaul Menzel { PCI_VDEVICE(AMD, 0x7801), board_ahci_no_debounce_delay }, /* AMD Hudson-2 (AHCI mode) */ 460fafe5c3dSShane Huang { PCI_VDEVICE(AMD, 0x7900), board_ahci }, /* AMD CZ */ 461099849afSMario Limonciello { PCI_VDEVICE(AMD, 0x7901), board_ahci_low_power }, /* AMD Green Sardine */ 462e2dd90b1SShane Huang /* AMD is using RAID class only for ahci controllers */ 463e2dd90b1SShane Huang { PCI_VENDOR_ID_AMD, PCI_ANY_ID, PCI_ANY_ID, PCI_ANY_ID, 464e2dd90b1SShane Huang PCI_CLASS_STORAGE_RAID << 8, 0xffffff, board_ahci }, 465e2dd90b1SShane Huang 4669c54cd10SCharles Rose /* Dell S140/S150 */ 4679c54cd10SCharles Rose { PCI_VENDOR_ID_INTEL, PCI_ANY_ID, PCI_SUBVENDOR_ID_DELL, PCI_ANY_ID, 4689c54cd10SCharles Rose PCI_CLASS_STORAGE_RAID << 8, 0xffffff, board_ahci }, 4699c54cd10SCharles Rose 470c6fd2807SJeff Garzik /* VIA */ 47154bb3a94SJeff Garzik { PCI_VDEVICE(VIA, 0x3349), board_ahci_vt8251 }, /* VIA VT8251 */ 472bf335542STejun Heo { PCI_VDEVICE(VIA, 0x6287), board_ahci_vt8251 }, /* VIA VT8251 */ 473c6fd2807SJeff Garzik 474c6fd2807SJeff Garzik /* NVIDIA */ 475e297d99eSTejun Heo { PCI_VDEVICE(NVIDIA, 0x044c), board_ahci_mcp65 }, /* MCP65 */ 476e297d99eSTejun Heo { PCI_VDEVICE(NVIDIA, 0x044d), board_ahci_mcp65 }, /* MCP65 */ 477e297d99eSTejun Heo { PCI_VDEVICE(NVIDIA, 0x044e), board_ahci_mcp65 }, /* MCP65 */ 478e297d99eSTejun Heo { PCI_VDEVICE(NVIDIA, 0x044f), board_ahci_mcp65 }, /* MCP65 */ 479e297d99eSTejun Heo { PCI_VDEVICE(NVIDIA, 0x045c), board_ahci_mcp65 }, /* MCP65 */ 480e297d99eSTejun Heo { PCI_VDEVICE(NVIDIA, 0x045d), board_ahci_mcp65 }, /* MCP65 */ 481e297d99eSTejun Heo { PCI_VDEVICE(NVIDIA, 0x045e), board_ahci_mcp65 }, /* MCP65 */ 482e297d99eSTejun Heo { PCI_VDEVICE(NVIDIA, 0x045f), board_ahci_mcp65 }, /* MCP65 */ 483441577efSTejun Heo { PCI_VDEVICE(NVIDIA, 0x0550), board_ahci_mcp67 }, /* MCP67 */ 484441577efSTejun Heo { PCI_VDEVICE(NVIDIA, 0x0551), board_ahci_mcp67 }, /* MCP67 */ 485441577efSTejun Heo { PCI_VDEVICE(NVIDIA, 0x0552), board_ahci_mcp67 }, /* MCP67 */ 486441577efSTejun Heo { PCI_VDEVICE(NVIDIA, 0x0553), board_ahci_mcp67 }, /* MCP67 */ 487441577efSTejun Heo { PCI_VDEVICE(NVIDIA, 0x0554), board_ahci_mcp67 }, /* MCP67 */ 488441577efSTejun Heo { PCI_VDEVICE(NVIDIA, 0x0555), board_ahci_mcp67 }, /* MCP67 */ 489441577efSTejun Heo { PCI_VDEVICE(NVIDIA, 0x0556), board_ahci_mcp67 }, /* MCP67 */ 490441577efSTejun Heo { PCI_VDEVICE(NVIDIA, 0x0557), board_ahci_mcp67 }, /* MCP67 */ 491441577efSTejun Heo { PCI_VDEVICE(NVIDIA, 0x0558), board_ahci_mcp67 }, /* MCP67 */ 492441577efSTejun Heo { PCI_VDEVICE(NVIDIA, 0x0559), board_ahci_mcp67 }, /* MCP67 */ 493441577efSTejun Heo { PCI_VDEVICE(NVIDIA, 0x055a), board_ahci_mcp67 }, /* MCP67 */ 494441577efSTejun Heo { PCI_VDEVICE(NVIDIA, 0x055b), board_ahci_mcp67 }, /* MCP67 */ 495441577efSTejun Heo { PCI_VDEVICE(NVIDIA, 0x0580), board_ahci_mcp_linux }, /* Linux ID */ 496441577efSTejun Heo { PCI_VDEVICE(NVIDIA, 0x0581), board_ahci_mcp_linux }, /* Linux ID */ 497441577efSTejun Heo { PCI_VDEVICE(NVIDIA, 0x0582), board_ahci_mcp_linux }, /* Linux ID */ 498441577efSTejun Heo { PCI_VDEVICE(NVIDIA, 0x0583), board_ahci_mcp_linux }, /* Linux ID */ 499441577efSTejun Heo { PCI_VDEVICE(NVIDIA, 0x0584), board_ahci_mcp_linux }, /* Linux ID */ 500441577efSTejun Heo { PCI_VDEVICE(NVIDIA, 0x0585), board_ahci_mcp_linux }, /* Linux ID */ 501441577efSTejun Heo { PCI_VDEVICE(NVIDIA, 0x0586), board_ahci_mcp_linux }, /* Linux ID */ 502441577efSTejun Heo { PCI_VDEVICE(NVIDIA, 0x0587), board_ahci_mcp_linux }, /* Linux ID */ 503441577efSTejun Heo { PCI_VDEVICE(NVIDIA, 0x0588), board_ahci_mcp_linux }, /* Linux ID */ 504441577efSTejun Heo { PCI_VDEVICE(NVIDIA, 0x0589), board_ahci_mcp_linux }, /* Linux ID */ 505441577efSTejun Heo { PCI_VDEVICE(NVIDIA, 0x058a), board_ahci_mcp_linux }, /* Linux ID */ 506441577efSTejun Heo { PCI_VDEVICE(NVIDIA, 0x058b), board_ahci_mcp_linux }, /* Linux ID */ 507441577efSTejun Heo { PCI_VDEVICE(NVIDIA, 0x058c), board_ahci_mcp_linux }, /* Linux ID */ 508441577efSTejun Heo { PCI_VDEVICE(NVIDIA, 0x058d), board_ahci_mcp_linux }, /* Linux ID */ 509441577efSTejun Heo { PCI_VDEVICE(NVIDIA, 0x058e), board_ahci_mcp_linux }, /* Linux ID */ 510441577efSTejun Heo { PCI_VDEVICE(NVIDIA, 0x058f), board_ahci_mcp_linux }, /* Linux ID */ 511441577efSTejun Heo { PCI_VDEVICE(NVIDIA, 0x07f0), board_ahci_mcp73 }, /* MCP73 */ 512441577efSTejun Heo { PCI_VDEVICE(NVIDIA, 0x07f1), board_ahci_mcp73 }, /* MCP73 */ 513441577efSTejun Heo { PCI_VDEVICE(NVIDIA, 0x07f2), board_ahci_mcp73 }, /* MCP73 */ 514441577efSTejun Heo { PCI_VDEVICE(NVIDIA, 0x07f3), board_ahci_mcp73 }, /* MCP73 */ 515441577efSTejun Heo { PCI_VDEVICE(NVIDIA, 0x07f4), board_ahci_mcp73 }, /* MCP73 */ 516441577efSTejun Heo { PCI_VDEVICE(NVIDIA, 0x07f5), board_ahci_mcp73 }, /* MCP73 */ 517441577efSTejun Heo { PCI_VDEVICE(NVIDIA, 0x07f6), board_ahci_mcp73 }, /* MCP73 */ 518441577efSTejun Heo { PCI_VDEVICE(NVIDIA, 0x07f7), board_ahci_mcp73 }, /* MCP73 */ 519441577efSTejun Heo { PCI_VDEVICE(NVIDIA, 0x07f8), board_ahci_mcp73 }, /* MCP73 */ 520441577efSTejun Heo { PCI_VDEVICE(NVIDIA, 0x07f9), board_ahci_mcp73 }, /* MCP73 */ 521441577efSTejun Heo { PCI_VDEVICE(NVIDIA, 0x07fa), board_ahci_mcp73 }, /* MCP73 */ 522441577efSTejun Heo { PCI_VDEVICE(NVIDIA, 0x07fb), board_ahci_mcp73 }, /* MCP73 */ 523441577efSTejun Heo { PCI_VDEVICE(NVIDIA, 0x0ad0), board_ahci_mcp77 }, /* MCP77 */ 524441577efSTejun Heo { PCI_VDEVICE(NVIDIA, 0x0ad1), board_ahci_mcp77 }, /* MCP77 */ 525441577efSTejun Heo { PCI_VDEVICE(NVIDIA, 0x0ad2), board_ahci_mcp77 }, /* MCP77 */ 526441577efSTejun Heo { PCI_VDEVICE(NVIDIA, 0x0ad3), board_ahci_mcp77 }, /* MCP77 */ 527441577efSTejun Heo { PCI_VDEVICE(NVIDIA, 0x0ad4), board_ahci_mcp77 }, /* MCP77 */ 528441577efSTejun Heo { PCI_VDEVICE(NVIDIA, 0x0ad5), board_ahci_mcp77 }, /* MCP77 */ 529441577efSTejun Heo { PCI_VDEVICE(NVIDIA, 0x0ad6), board_ahci_mcp77 }, /* MCP77 */ 530441577efSTejun Heo { PCI_VDEVICE(NVIDIA, 0x0ad7), board_ahci_mcp77 }, /* MCP77 */ 531441577efSTejun Heo { PCI_VDEVICE(NVIDIA, 0x0ad8), board_ahci_mcp77 }, /* MCP77 */ 532441577efSTejun Heo { PCI_VDEVICE(NVIDIA, 0x0ad9), board_ahci_mcp77 }, /* MCP77 */ 533441577efSTejun Heo { PCI_VDEVICE(NVIDIA, 0x0ada), board_ahci_mcp77 }, /* MCP77 */ 534441577efSTejun Heo { PCI_VDEVICE(NVIDIA, 0x0adb), board_ahci_mcp77 }, /* MCP77 */ 535441577efSTejun Heo { PCI_VDEVICE(NVIDIA, 0x0ab4), board_ahci_mcp79 }, /* MCP79 */ 536441577efSTejun Heo { PCI_VDEVICE(NVIDIA, 0x0ab5), board_ahci_mcp79 }, /* MCP79 */ 537441577efSTejun Heo { PCI_VDEVICE(NVIDIA, 0x0ab6), board_ahci_mcp79 }, /* MCP79 */ 538441577efSTejun Heo { PCI_VDEVICE(NVIDIA, 0x0ab7), board_ahci_mcp79 }, /* MCP79 */ 539441577efSTejun Heo { PCI_VDEVICE(NVIDIA, 0x0ab8), board_ahci_mcp79 }, /* MCP79 */ 540441577efSTejun Heo { PCI_VDEVICE(NVIDIA, 0x0ab9), board_ahci_mcp79 }, /* MCP79 */ 541441577efSTejun Heo { PCI_VDEVICE(NVIDIA, 0x0aba), board_ahci_mcp79 }, /* MCP79 */ 542441577efSTejun Heo { PCI_VDEVICE(NVIDIA, 0x0abb), board_ahci_mcp79 }, /* MCP79 */ 543441577efSTejun Heo { PCI_VDEVICE(NVIDIA, 0x0abc), board_ahci_mcp79 }, /* MCP79 */ 544441577efSTejun Heo { PCI_VDEVICE(NVIDIA, 0x0abd), board_ahci_mcp79 }, /* MCP79 */ 545441577efSTejun Heo { PCI_VDEVICE(NVIDIA, 0x0abe), board_ahci_mcp79 }, /* MCP79 */ 546441577efSTejun Heo { PCI_VDEVICE(NVIDIA, 0x0abf), board_ahci_mcp79 }, /* MCP79 */ 547441577efSTejun Heo { PCI_VDEVICE(NVIDIA, 0x0d84), board_ahci_mcp89 }, /* MCP89 */ 548441577efSTejun Heo { PCI_VDEVICE(NVIDIA, 0x0d85), board_ahci_mcp89 }, /* MCP89 */ 549441577efSTejun Heo { PCI_VDEVICE(NVIDIA, 0x0d86), board_ahci_mcp89 }, /* MCP89 */ 550441577efSTejun Heo { PCI_VDEVICE(NVIDIA, 0x0d87), board_ahci_mcp89 }, /* MCP89 */ 551441577efSTejun Heo { PCI_VDEVICE(NVIDIA, 0x0d88), board_ahci_mcp89 }, /* MCP89 */ 552441577efSTejun Heo { PCI_VDEVICE(NVIDIA, 0x0d89), board_ahci_mcp89 }, /* MCP89 */ 553441577efSTejun Heo { PCI_VDEVICE(NVIDIA, 0x0d8a), board_ahci_mcp89 }, /* MCP89 */ 554441577efSTejun Heo { PCI_VDEVICE(NVIDIA, 0x0d8b), board_ahci_mcp89 }, /* MCP89 */ 555441577efSTejun Heo { PCI_VDEVICE(NVIDIA, 0x0d8c), board_ahci_mcp89 }, /* MCP89 */ 556441577efSTejun Heo { PCI_VDEVICE(NVIDIA, 0x0d8d), board_ahci_mcp89 }, /* MCP89 */ 557441577efSTejun Heo { PCI_VDEVICE(NVIDIA, 0x0d8e), board_ahci_mcp89 }, /* MCP89 */ 558441577efSTejun Heo { PCI_VDEVICE(NVIDIA, 0x0d8f), board_ahci_mcp89 }, /* MCP89 */ 559c6fd2807SJeff Garzik 560c6fd2807SJeff Garzik /* SiS */ 56120e2de4aSTejun Heo { PCI_VDEVICE(SI, 0x1184), board_ahci }, /* SiS 966 */ 56220e2de4aSTejun Heo { PCI_VDEVICE(SI, 0x1185), board_ahci }, /* SiS 968 */ 56320e2de4aSTejun Heo { PCI_VDEVICE(SI, 0x0186), board_ahci }, /* SiS 968 */ 564c6fd2807SJeff Garzik 565318893e1SAlessandro Rubini /* ST Microelectronics */ 566318893e1SAlessandro Rubini { PCI_VDEVICE(STMICRO, 0xCC06), board_ahci }, /* ST ConneXt */ 567318893e1SAlessandro Rubini 568cd70c266SJeff Garzik /* Marvell */ 569cd70c266SJeff Garzik { PCI_VDEVICE(MARVELL, 0x6145), board_ahci_mv }, /* 6145 */ 570c40e7cb8SJose Alberto Reguero { PCI_VDEVICE(MARVELL, 0x6121), board_ahci_mv }, /* 6121 */ 57169fd3157SMyron Stowe { PCI_DEVICE(PCI_VENDOR_ID_MARVELL_EXT, 0x9123), 57210aca06cSAnssi Hannula .class = PCI_CLASS_STORAGE_SATA_AHCI, 57310aca06cSAnssi Hannula .class_mask = 0xffffff, 5745f173107STejun Heo .driver_data = board_ahci_yes_fbs }, /* 88se9128 */ 57569fd3157SMyron Stowe { PCI_DEVICE(PCI_VENDOR_ID_MARVELL_EXT, 0x9125), 576467b41c6SPer Jessen .driver_data = board_ahci_yes_fbs }, /* 88se9125 */ 577e098f5cbSSimon Guinot { PCI_DEVICE_SUB(PCI_VENDOR_ID_MARVELL_EXT, 0x9178, 578e098f5cbSSimon Guinot PCI_VENDOR_ID_MARVELL_EXT, 0x9170), 579e098f5cbSSimon Guinot .driver_data = board_ahci_yes_fbs }, /* 88se9170 */ 58069fd3157SMyron Stowe { PCI_DEVICE(PCI_VENDOR_ID_MARVELL_EXT, 0x917a), 581642d8925SMatt Johnson .driver_data = board_ahci_yes_fbs }, /* 88se9172 */ 582fcce9a35SGeorge Spelvin { PCI_DEVICE(PCI_VENDOR_ID_MARVELL_EXT, 0x9172), 583c5edfff9SMurali Karicheri .driver_data = board_ahci_yes_fbs }, /* 88se9182 */ 584c5edfff9SMurali Karicheri { PCI_DEVICE(PCI_VENDOR_ID_MARVELL_EXT, 0x9182), 585fcce9a35SGeorge Spelvin .driver_data = board_ahci_yes_fbs }, /* 88se9172 */ 58669fd3157SMyron Stowe { PCI_DEVICE(PCI_VENDOR_ID_MARVELL_EXT, 0x9192), 58717c60c6bSAlan Cox .driver_data = board_ahci_yes_fbs }, /* 88se9172 on some Gigabyte */ 588754a292fSAndreas Schrägle { PCI_DEVICE(PCI_VENDOR_ID_MARVELL_EXT, 0x91a0), 589754a292fSAndreas Schrägle .driver_data = board_ahci_yes_fbs }, 590a40cf3f3SJohannes Thumshirn { PCI_DEVICE(PCI_VENDOR_ID_MARVELL_EXT, 0x91a2), /* 88se91a2 */ 591a40cf3f3SJohannes Thumshirn .driver_data = board_ahci_yes_fbs }, 59269fd3157SMyron Stowe { PCI_DEVICE(PCI_VENDOR_ID_MARVELL_EXT, 0x91a3), 59350be5e36STejun Heo .driver_data = board_ahci_yes_fbs }, 5946d5278a6SSamir Benmendil { PCI_DEVICE(PCI_VENDOR_ID_MARVELL_EXT, 0x9230), 5956d5278a6SSamir Benmendil .driver_data = board_ahci_yes_fbs }, 596f4a8d4f2SPaul Menzel { PCI_DEVICE(PCI_VENDOR_ID_MARVELL_EXT, 0x9235), 597f4a8d4f2SPaul Menzel .driver_data = board_ahci_no_debounce_delay }, 59828b2182dSHans de Goede { PCI_DEVICE(PCI_VENDOR_ID_TTI, 0x0642), /* highpoint rocketraid 642L */ 59928b2182dSHans de Goede .driver_data = board_ahci_yes_fbs }, 60028b2182dSHans de Goede { PCI_DEVICE(PCI_VENDOR_ID_TTI, 0x0645), /* highpoint rocketraid 644L */ 601d2518365SJérôme Carretero .driver_data = board_ahci_yes_fbs }, 602cd70c266SJeff Garzik 603c77a036bSMark Nelson /* Promise */ 604c77a036bSMark Nelson { PCI_VDEVICE(PROMISE, 0x3f20), board_ahci }, /* PDC42819 */ 605b32bfc06SRomain Degez { PCI_VDEVICE(PROMISE, 0x3781), board_ahci }, /* FastTrak TX8660 ahci-mode */ 606c77a036bSMark Nelson 607b0dd4d7aSLennert Buytenhek /* ASMedia */ 6087b4f6ecaSAlan Cox { PCI_VDEVICE(ASMEDIA, 0x0601), board_ahci }, /* ASM1060 */ 6097b4f6ecaSAlan Cox { PCI_VDEVICE(ASMEDIA, 0x0602), board_ahci }, /* ASM1060 */ 610b0dd4d7aSLennert Buytenhek { PCI_VDEVICE(ASMEDIA, 0x0611), board_ahci_43bit_dma }, /* ASM1061 */ 611b0dd4d7aSLennert Buytenhek { PCI_VDEVICE(ASMEDIA, 0x0612), board_ahci_43bit_dma }, /* ASM1061/1062 */ 6120ce968f3SShawn Lin { PCI_VDEVICE(ASMEDIA, 0x0621), board_ahci }, /* ASM1061R */ 6130ce968f3SShawn Lin { PCI_VDEVICE(ASMEDIA, 0x0622), board_ahci }, /* ASM1062R */ 6148c0ff6afSIstván Pongrácz { PCI_VDEVICE(ASMEDIA, 0x0624), board_ahci }, /* ASM1062+JMB575 */ 615*1f9b7a5dSSzuying Chen { PCI_VDEVICE(ASMEDIA, 0x1062), board_ahci }, /* ASM1062A */ 616*1f9b7a5dSSzuying Chen { PCI_VDEVICE(ASMEDIA, 0x1064), board_ahci }, /* ASM1064 */ 617*1f9b7a5dSSzuying Chen { PCI_VDEVICE(ASMEDIA, 0x1164), board_ahci }, /* ASM1164 */ 618*1f9b7a5dSSzuying Chen { PCI_VDEVICE(ASMEDIA, 0x1165), board_ahci }, /* ASM1165 */ 619*1f9b7a5dSSzuying Chen { PCI_VDEVICE(ASMEDIA, 0x1166), board_ahci }, /* ASM1166 */ 620c9703765SKeng-Yu Lin 62167809f85SLevente Kurusa /* 62266a7cbc3STejun Heo * Samsung SSDs found on some macbooks. NCQ times out if MSI is 62366a7cbc3STejun Heo * enabled. https://bugzilla.kernel.org/show_bug.cgi?id=60731 62467809f85SLevente Kurusa */ 62566a7cbc3STejun Heo { PCI_VDEVICE(SAMSUNG, 0x1600), board_ahci_nomsi }, 6262b21ef0aSTejun Heo { PCI_VDEVICE(SAMSUNG, 0xa800), board_ahci_nomsi }, 62767809f85SLevente Kurusa 6287f9c9f8eSHugh Daschbach /* Enmotus */ 6297f9c9f8eSHugh Daschbach { PCI_DEVICE(0x1c44, 0x8000), board_ahci }, 6307f9c9f8eSHugh Daschbach 631e49bd683STiezhu Yang /* Loongson */ 632e49bd683STiezhu Yang { PCI_VDEVICE(LOONGSON, 0x7a08), board_ahci }, 633e49bd683STiezhu Yang 634415ae2b5SJeff Garzik /* Generic, PCI class code for AHCI */ 635415ae2b5SJeff Garzik { PCI_ANY_ID, PCI_ANY_ID, PCI_ANY_ID, PCI_ANY_ID, 636c9f89475SConke Hu PCI_CLASS_STORAGE_SATA_AHCI, 0xffffff, board_ahci }, 637415ae2b5SJeff Garzik 638c6fd2807SJeff Garzik { } /* terminate list */ 639c6fd2807SJeff Garzik }; 640c6fd2807SJeff Garzik 641f1d848f9SMika Westerberg static const struct dev_pm_ops ahci_pci_pm_ops = { 642f1d848f9SMika Westerberg SET_SYSTEM_SLEEP_PM_OPS(ahci_pci_device_suspend, ahci_pci_device_resume) 64302e53293SMika Westerberg SET_RUNTIME_PM_OPS(ahci_pci_device_runtime_suspend, 64402e53293SMika Westerberg ahci_pci_device_runtime_resume, NULL) 645f1d848f9SMika Westerberg }; 646c6fd2807SJeff Garzik 647c6fd2807SJeff Garzik static struct pci_driver ahci_pci_driver = { 648c6fd2807SJeff Garzik .name = DRV_NAME, 649c6fd2807SJeff Garzik .id_table = ahci_pci_tbl, 650c6fd2807SJeff Garzik .probe = ahci_init_one, 65102e53293SMika Westerberg .remove = ahci_remove_one, 65210a663a1SPrabhakar Kushwaha .shutdown = ahci_shutdown_one, 653f1d848f9SMika Westerberg .driver = { 654f1d848f9SMika Westerberg .pm = &ahci_pci_pm_ops, 655f1d848f9SMika Westerberg }, 656c6fd2807SJeff Garzik }; 657c6fd2807SJeff Garzik 6585219d653SJavier Martinez Canillas #if IS_ENABLED(CONFIG_PATA_MARVELL) 6595b66c829SAlan Cox static int marvell_enable; 6605b66c829SAlan Cox #else 6615b66c829SAlan Cox static int marvell_enable = 1; 6625b66c829SAlan Cox #endif 6635b66c829SAlan Cox module_param(marvell_enable, int, 0644); 6645b66c829SAlan Cox MODULE_PARM_DESC(marvell_enable, "Marvell SATA via AHCI (1 = enabled)"); 6655b66c829SAlan Cox 666b1a9585cSSrinivas Pandruvada static int mobile_lpm_policy = -1; 667ebb82e3cSHans de Goede module_param(mobile_lpm_policy, int, 0644); 668ebb82e3cSHans de Goede MODULE_PARM_DESC(mobile_lpm_policy, "Default LPM policy for mobile chipsets"); 6695b66c829SAlan Cox 670394d6e53SAnton Vorontsov static void ahci_pci_save_initial_config(struct pci_dev *pdev, 671394d6e53SAnton Vorontsov struct ahci_host_priv *hpriv) 672394d6e53SAnton Vorontsov { 67389f67051SConrad Kostecki if (pdev->vendor == PCI_VENDOR_ID_ASMEDIA && pdev->device == 0x1166) { 67489f67051SConrad Kostecki dev_info(&pdev->dev, "ASM1166 has only six ports\n"); 67589f67051SConrad Kostecki hpriv->saved_port_map = 0x3f; 67689f67051SConrad Kostecki } 67789f67051SConrad Kostecki 678394d6e53SAnton Vorontsov if (pdev->vendor == PCI_VENDOR_ID_JMICRON && pdev->device == 0x2361) { 679394d6e53SAnton Vorontsov dev_info(&pdev->dev, "JMB361 has only one port\n"); 68088589772SSerge Semin hpriv->saved_port_map = 1; 681394d6e53SAnton Vorontsov } 682394d6e53SAnton Vorontsov 683394d6e53SAnton Vorontsov /* 684394d6e53SAnton Vorontsov * Temporary Marvell 6145 hack: PATA port presence 685394d6e53SAnton Vorontsov * is asserted through the standard AHCI port 686394d6e53SAnton Vorontsov * presence register, as bit 4 (counting from 0) 687394d6e53SAnton Vorontsov */ 688394d6e53SAnton Vorontsov if (hpriv->flags & AHCI_HFLAG_MV_PATA) { 689394d6e53SAnton Vorontsov if (pdev->device == 0x6121) 6909a23c1d6SAntoine Tenart hpriv->mask_port_map = 0x3; 691394d6e53SAnton Vorontsov else 6929a23c1d6SAntoine Tenart hpriv->mask_port_map = 0xf; 693394d6e53SAnton Vorontsov dev_info(&pdev->dev, 694394d6e53SAnton Vorontsov "Disabling your PATA port. Use the boot option 'ahci.marvell_enable=0' to avoid this.\n"); 695394d6e53SAnton Vorontsov } 696394d6e53SAnton Vorontsov 697725c7b57SAntoine Ténart ahci_save_initial_config(&pdev->dev, hpriv); 698394d6e53SAnton Vorontsov } 699394d6e53SAnton Vorontsov 70037e14e4fSAdam Vodopjan static int ahci_pci_reset_controller(struct ata_host *host) 70137e14e4fSAdam Vodopjan { 70237e14e4fSAdam Vodopjan struct pci_dev *pdev = to_pci_dev(host->dev); 70337e14e4fSAdam Vodopjan struct ahci_host_priv *hpriv = host->private_data; 70437e14e4fSAdam Vodopjan int rc; 70537e14e4fSAdam Vodopjan 70637e14e4fSAdam Vodopjan rc = ahci_reset_controller(host); 70737e14e4fSAdam Vodopjan if (rc) 70837e14e4fSAdam Vodopjan return rc; 70937e14e4fSAdam Vodopjan 71037e14e4fSAdam Vodopjan /* 71137e14e4fSAdam Vodopjan * If platform firmware failed to enable ports, try to enable 71237e14e4fSAdam Vodopjan * them here. 71337e14e4fSAdam Vodopjan */ 71437e14e4fSAdam Vodopjan ahci_intel_pcs_quirk(pdev, hpriv); 71537e14e4fSAdam Vodopjan 71637e14e4fSAdam Vodopjan return 0; 71737e14e4fSAdam Vodopjan } 71837e14e4fSAdam Vodopjan 719781d6550SAnton Vorontsov static void ahci_pci_init_controller(struct ata_host *host) 720781d6550SAnton Vorontsov { 721781d6550SAnton Vorontsov struct ahci_host_priv *hpriv = host->private_data; 722781d6550SAnton Vorontsov struct pci_dev *pdev = to_pci_dev(host->dev); 723781d6550SAnton Vorontsov void __iomem *port_mmio; 724781d6550SAnton Vorontsov u32 tmp; 725c40e7cb8SJose Alberto Reguero int mv; 7262bcd866bSJeff Garzik 727417a1a6dSTejun Heo if (hpriv->flags & AHCI_HFLAG_MV_PATA) { 728c40e7cb8SJose Alberto Reguero if (pdev->device == 0x6121) 729c40e7cb8SJose Alberto Reguero mv = 2; 730c40e7cb8SJose Alberto Reguero else 731c40e7cb8SJose Alberto Reguero mv = 4; 7327cbbfbe0SSerge Semin port_mmio = __ahci_port_base(hpriv, mv); 733cd70c266SJeff Garzik 734cd70c266SJeff Garzik writel(0, port_mmio + PORT_IRQ_MASK); 735cd70c266SJeff Garzik 736cd70c266SJeff Garzik /* clear port IRQ */ 737cd70c266SJeff Garzik tmp = readl(port_mmio + PORT_IRQ_STAT); 73893c77114SHannes Reinecke dev_dbg(&pdev->dev, "PORT_IRQ_STAT 0x%x\n", tmp); 739cd70c266SJeff Garzik if (tmp) 740cd70c266SJeff Garzik writel(tmp, port_mmio + PORT_IRQ_STAT); 741cd70c266SJeff Garzik } 742cd70c266SJeff Garzik 743781d6550SAnton Vorontsov ahci_init_controller(host); 744c6fd2807SJeff Garzik } 745c6fd2807SJeff Garzik 746cc0680a5STejun Heo static int ahci_vt8251_hardreset(struct ata_link *link, unsigned int *class, 747d4b2bab4STejun Heo unsigned long deadline) 748ad616ffbSTejun Heo { 749cc0680a5STejun Heo struct ata_port *ap = link->ap; 750039ece38SHans de Goede struct ahci_host_priv *hpriv = ap->host->private_data; 7519dadd45bSTejun Heo bool online; 752ad616ffbSTejun Heo int rc; 753ad616ffbSTejun Heo 754fa89f53bSEvan Wang hpriv->stop_engine(ap); 755ad616ffbSTejun Heo 756cc0680a5STejun Heo rc = sata_link_hardreset(link, sata_ehc_deb_timing(&link->eh_context), 7579dadd45bSTejun Heo deadline, &online, NULL); 758ad616ffbSTejun Heo 759039ece38SHans de Goede hpriv->start_engine(ap); 760ad616ffbSTejun Heo 761ad616ffbSTejun Heo /* vt8251 doesn't clear BSY on signature FIS reception, 762ad616ffbSTejun Heo * request follow-up softreset. 763ad616ffbSTejun Heo */ 7649dadd45bSTejun Heo return online ? -EAGAIN : rc; 765ad616ffbSTejun Heo } 766ad616ffbSTejun Heo 767edc93052STejun Heo static int ahci_p5wdh_hardreset(struct ata_link *link, unsigned int *class, 768edc93052STejun Heo unsigned long deadline) 769edc93052STejun Heo { 770edc93052STejun Heo struct ata_port *ap = link->ap; 771edc93052STejun Heo struct ahci_port_priv *pp = ap->private_data; 772039ece38SHans de Goede struct ahci_host_priv *hpriv = ap->host->private_data; 773edc93052STejun Heo u8 *d2h_fis = pp->rx_fis + RX_FIS_D2H_REG; 774edc93052STejun Heo struct ata_taskfile tf; 7759dadd45bSTejun Heo bool online; 776edc93052STejun Heo int rc; 777edc93052STejun Heo 778fa89f53bSEvan Wang hpriv->stop_engine(ap); 779edc93052STejun Heo 780edc93052STejun Heo /* clear D2H reception area to properly wait for D2H FIS */ 781edc93052STejun Heo ata_tf_init(link->device, &tf); 782efcef265SSergey Shtylyov tf.status = ATA_BUSY; 783edc93052STejun Heo ata_tf_to_fis(&tf, 0, 0, d2h_fis); 784edc93052STejun Heo 785edc93052STejun Heo rc = sata_link_hardreset(link, sata_ehc_deb_timing(&link->eh_context), 7869dadd45bSTejun Heo deadline, &online, NULL); 787edc93052STejun Heo 788039ece38SHans de Goede hpriv->start_engine(ap); 789edc93052STejun Heo 790edc93052STejun Heo /* The pseudo configuration device on SIMG4726 attached to 791edc93052STejun Heo * ASUS P5W-DH Deluxe doesn't send signature FIS after 792edc93052STejun Heo * hardreset if no device is attached to the first downstream 793edc93052STejun Heo * port && the pseudo device locks up on SRST w/ PMP==0. To 794edc93052STejun Heo * work around this, wait for !BSY only briefly. If BSY isn't 795edc93052STejun Heo * cleared, perform CLO and proceed to IDENTIFY (achieved by 796edc93052STejun Heo * ATA_LFLAG_NO_SRST and ATA_LFLAG_ASSUME_ATA). 797edc93052STejun Heo * 798edc93052STejun Heo * Wait for two seconds. Devices attached to downstream port 799edc93052STejun Heo * which can't process the following IDENTIFY after this will 800edc93052STejun Heo * have to be reset again. For most cases, this should 801edc93052STejun Heo * suffice while making probing snappish enough. 802edc93052STejun Heo */ 8039dadd45bSTejun Heo if (online) { 8049dadd45bSTejun Heo rc = ata_wait_after_reset(link, jiffies + 2 * HZ, 8059dadd45bSTejun Heo ahci_check_ready); 806edc93052STejun Heo if (rc) 80778d5ae39SShane Huang ahci_kick_engine(ap); 8089dadd45bSTejun Heo } 8099dadd45bSTejun Heo return rc; 810edc93052STejun Heo } 811edc93052STejun Heo 812dbfe8ef5SDan Williams /* 813dbfe8ef5SDan Williams * ahci_avn_hardreset - attempt more aggressive recovery of Avoton ports. 814dbfe8ef5SDan Williams * 815dbfe8ef5SDan Williams * It has been observed with some SSDs that the timing of events in the 816dbfe8ef5SDan Williams * link synchronization phase can leave the port in a state that can not 817dbfe8ef5SDan Williams * be recovered by a SATA-hard-reset alone. The failing signature is 818dbfe8ef5SDan Williams * SStatus.DET stuck at 1 ("Device presence detected but Phy 819dbfe8ef5SDan Williams * communication not established"). It was found that unloading and 820dbfe8ef5SDan Williams * reloading the driver when this problem occurs allows the drive 821dbfe8ef5SDan Williams * connection to be recovered (DET advanced to 0x3). The critical 822dbfe8ef5SDan Williams * component of reloading the driver is that the port state machines are 823dbfe8ef5SDan Williams * reset by bouncing "port enable" in the AHCI PCS configuration 824dbfe8ef5SDan Williams * register. So, reproduce that effect by bouncing a port whenever we 825dbfe8ef5SDan Williams * see DET==1 after a reset. 826dbfe8ef5SDan Williams */ 827dbfe8ef5SDan Williams static int ahci_avn_hardreset(struct ata_link *link, unsigned int *class, 828dbfe8ef5SDan Williams unsigned long deadline) 829dbfe8ef5SDan Williams { 830d14d41ccSSergey Shtylyov const unsigned int *timing = sata_ehc_deb_timing(&link->eh_context); 831dbfe8ef5SDan Williams struct ata_port *ap = link->ap; 832dbfe8ef5SDan Williams struct ahci_port_priv *pp = ap->private_data; 833dbfe8ef5SDan Williams struct ahci_host_priv *hpriv = ap->host->private_data; 834dbfe8ef5SDan Williams u8 *d2h_fis = pp->rx_fis + RX_FIS_D2H_REG; 835dbfe8ef5SDan Williams unsigned long tmo = deadline - jiffies; 836dbfe8ef5SDan Williams struct ata_taskfile tf; 837dbfe8ef5SDan Williams bool online; 838dbfe8ef5SDan Williams int rc, i; 839dbfe8ef5SDan Williams 840fa89f53bSEvan Wang hpriv->stop_engine(ap); 841dbfe8ef5SDan Williams 842dbfe8ef5SDan Williams for (i = 0; i < 2; i++) { 843dbfe8ef5SDan Williams u16 val; 844dbfe8ef5SDan Williams u32 sstatus; 845dbfe8ef5SDan Williams int port = ap->port_no; 846dbfe8ef5SDan Williams struct ata_host *host = ap->host; 847dbfe8ef5SDan Williams struct pci_dev *pdev = to_pci_dev(host->dev); 848dbfe8ef5SDan Williams 849dbfe8ef5SDan Williams /* clear D2H reception area to properly wait for D2H FIS */ 850dbfe8ef5SDan Williams ata_tf_init(link->device, &tf); 851efcef265SSergey Shtylyov tf.status = ATA_BUSY; 852dbfe8ef5SDan Williams ata_tf_to_fis(&tf, 0, 0, d2h_fis); 853dbfe8ef5SDan Williams 854dbfe8ef5SDan Williams rc = sata_link_hardreset(link, timing, deadline, &online, 855dbfe8ef5SDan Williams ahci_check_ready); 856dbfe8ef5SDan Williams 857dbfe8ef5SDan Williams if (sata_scr_read(link, SCR_STATUS, &sstatus) != 0 || 858dbfe8ef5SDan Williams (sstatus & 0xf) != 1) 859dbfe8ef5SDan Williams break; 860dbfe8ef5SDan Williams 861e276c9bdSXu Wang ata_link_info(link, "avn bounce port%d\n", port); 862dbfe8ef5SDan Williams 863dbfe8ef5SDan Williams pci_read_config_word(pdev, 0x92, &val); 864dbfe8ef5SDan Williams val &= ~(1 << port); 865dbfe8ef5SDan Williams pci_write_config_word(pdev, 0x92, val); 866dbfe8ef5SDan Williams ata_msleep(ap, 1000); 867dbfe8ef5SDan Williams val |= 1 << port; 868dbfe8ef5SDan Williams pci_write_config_word(pdev, 0x92, val); 869dbfe8ef5SDan Williams deadline += tmo; 870dbfe8ef5SDan Williams } 871dbfe8ef5SDan Williams 872dbfe8ef5SDan Williams hpriv->start_engine(ap); 873dbfe8ef5SDan Williams 874dbfe8ef5SDan Williams if (online) 875dbfe8ef5SDan Williams *class = ahci_dev_classify(ap); 876dbfe8ef5SDan Williams 877dbfe8ef5SDan Williams return rc; 878dbfe8ef5SDan Williams } 879dbfe8ef5SDan Williams 880dbfe8ef5SDan Williams 88102e53293SMika Westerberg #ifdef CONFIG_PM 88202e53293SMika Westerberg static void ahci_pci_disable_interrupts(struct ata_host *host) 883c6fd2807SJeff Garzik { 8849b10ae86STejun Heo struct ahci_host_priv *hpriv = host->private_data; 885d8993349SAnton Vorontsov void __iomem *mmio = hpriv->mmio; 886c6fd2807SJeff Garzik u32 ctl; 887c6fd2807SJeff Garzik 888c6fd2807SJeff Garzik /* AHCI spec rev1.1 section 8.3.3: 889c6fd2807SJeff Garzik * Software must disable interrupts prior to requesting a 890c6fd2807SJeff Garzik * transition of the HBA to D3 state. 891c6fd2807SJeff Garzik */ 892c6fd2807SJeff Garzik ctl = readl(mmio + HOST_CTL); 893c6fd2807SJeff Garzik ctl &= ~HOST_IRQ_EN; 894c6fd2807SJeff Garzik writel(ctl, mmio + HOST_CTL); 895c6fd2807SJeff Garzik readl(mmio + HOST_CTL); /* flush */ 89602e53293SMika Westerberg } 897f1d848f9SMika Westerberg 89802e53293SMika Westerberg static int ahci_pci_device_runtime_suspend(struct device *dev) 89902e53293SMika Westerberg { 90002e53293SMika Westerberg struct pci_dev *pdev = to_pci_dev(dev); 90102e53293SMika Westerberg struct ata_host *host = pci_get_drvdata(pdev); 90202e53293SMika Westerberg 90302e53293SMika Westerberg ahci_pci_disable_interrupts(host); 90402e53293SMika Westerberg return 0; 90502e53293SMika Westerberg } 90602e53293SMika Westerberg 90702e53293SMika Westerberg static int ahci_pci_device_runtime_resume(struct device *dev) 90802e53293SMika Westerberg { 90902e53293SMika Westerberg struct pci_dev *pdev = to_pci_dev(dev); 91002e53293SMika Westerberg struct ata_host *host = pci_get_drvdata(pdev); 91102e53293SMika Westerberg int rc; 91202e53293SMika Westerberg 91337e14e4fSAdam Vodopjan rc = ahci_pci_reset_controller(host); 91402e53293SMika Westerberg if (rc) 91502e53293SMika Westerberg return rc; 91602e53293SMika Westerberg ahci_pci_init_controller(host); 91702e53293SMika Westerberg return 0; 91802e53293SMika Westerberg } 91902e53293SMika Westerberg 92002e53293SMika Westerberg #ifdef CONFIG_PM_SLEEP 92102e53293SMika Westerberg static int ahci_pci_device_suspend(struct device *dev) 92202e53293SMika Westerberg { 92302e53293SMika Westerberg struct pci_dev *pdev = to_pci_dev(dev); 92402e53293SMika Westerberg struct ata_host *host = pci_get_drvdata(pdev); 92502e53293SMika Westerberg struct ahci_host_priv *hpriv = host->private_data; 92602e53293SMika Westerberg 92702e53293SMika Westerberg if (hpriv->flags & AHCI_HFLAG_NO_SUSPEND) { 92802e53293SMika Westerberg dev_err(&pdev->dev, 92902e53293SMika Westerberg "BIOS update required for suspend/resume\n"); 93002e53293SMika Westerberg return -EIO; 93102e53293SMika Westerberg } 93202e53293SMika Westerberg 93302e53293SMika Westerberg ahci_pci_disable_interrupts(host); 934ec87cf37SSergey Shtylyov ata_host_suspend(host, PMSG_SUSPEND); 935ec87cf37SSergey Shtylyov return 0; 936c6fd2807SJeff Garzik } 937c6fd2807SJeff Garzik 938f1d848f9SMika Westerberg static int ahci_pci_device_resume(struct device *dev) 939c6fd2807SJeff Garzik { 940f1d848f9SMika Westerberg struct pci_dev *pdev = to_pci_dev(dev); 9410a86e1c8SJingoo Han struct ata_host *host = pci_get_drvdata(pdev); 942c6fd2807SJeff Garzik int rc; 943c6fd2807SJeff Garzik 944cb85696dSJames Laird /* Apple BIOS helpfully mangles the registers on resume */ 945cb85696dSJames Laird if (is_mcp89_apple(pdev)) 946cb85696dSJames Laird ahci_mcp89_apple_enable(pdev); 947cb85696dSJames Laird 948c6fd2807SJeff Garzik if (pdev->dev.power.power_state.event == PM_EVENT_SUSPEND) { 94937e14e4fSAdam Vodopjan rc = ahci_pci_reset_controller(host); 950c6fd2807SJeff Garzik if (rc) 951c6fd2807SJeff Garzik return rc; 952c6fd2807SJeff Garzik 953781d6550SAnton Vorontsov ahci_pci_init_controller(host); 954c6fd2807SJeff Garzik } 955c6fd2807SJeff Garzik 956cca3974eSJeff Garzik ata_host_resume(host); 957c6fd2807SJeff Garzik 958c6fd2807SJeff Garzik return 0; 959c6fd2807SJeff Garzik } 960438ac6d5STejun Heo #endif 961c6fd2807SJeff Garzik 96202e53293SMika Westerberg #endif /* CONFIG_PM */ 96302e53293SMika Westerberg 964b0dd4d7aSLennert Buytenhek static int ahci_configure_dma_masks(struct pci_dev *pdev, 965b0dd4d7aSLennert Buytenhek struct ahci_host_priv *hpriv) 966c6fd2807SJeff Garzik { 967b0dd4d7aSLennert Buytenhek int dma_bits; 968c6fd2807SJeff Garzik int rc; 969c6fd2807SJeff Garzik 970b0dd4d7aSLennert Buytenhek if (hpriv->cap & HOST_CAP_64) { 971b0dd4d7aSLennert Buytenhek dma_bits = 64; 972b0dd4d7aSLennert Buytenhek if (hpriv->flags & AHCI_HFLAG_43BIT_ONLY) 973b0dd4d7aSLennert Buytenhek dma_bits = 43; 974b0dd4d7aSLennert Buytenhek } else { 975b0dd4d7aSLennert Buytenhek dma_bits = 32; 976b0dd4d7aSLennert Buytenhek } 977b0dd4d7aSLennert Buytenhek 978318893e1SAlessandro Rubini /* 979318893e1SAlessandro Rubini * If the device fixup already set the dma_mask to some non-standard 980318893e1SAlessandro Rubini * value, don't extend it here. This happens on STA2X11, for example. 981b1716871SChristoph Hellwig * 982b1716871SChristoph Hellwig * XXX: manipulating the DMA mask from platform code is completely 983a7ba70f1SNicolas Saenz Julienne * bogus, platform code should use dev->bus_dma_limit instead.. 984318893e1SAlessandro Rubini */ 985318893e1SAlessandro Rubini if (pdev->dma_mask && pdev->dma_mask < DMA_BIT_MASK(32)) 986318893e1SAlessandro Rubini return 0; 987318893e1SAlessandro Rubini 988b1716871SChristoph Hellwig rc = dma_set_mask_and_coherent(&pdev->dev, DMA_BIT_MASK(dma_bits)); 989b1716871SChristoph Hellwig if (rc) 990b1716871SChristoph Hellwig dev_err(&pdev->dev, "DMA enable failed\n"); 991c6fd2807SJeff Garzik return rc; 992c6fd2807SJeff Garzik } 993c6fd2807SJeff Garzik 994439fcaecSAnton Vorontsov static void ahci_pci_print_info(struct ata_host *host) 995439fcaecSAnton Vorontsov { 996439fcaecSAnton Vorontsov struct pci_dev *pdev = to_pci_dev(host->dev); 997439fcaecSAnton Vorontsov u16 cc; 998439fcaecSAnton Vorontsov const char *scc_s; 999439fcaecSAnton Vorontsov 1000439fcaecSAnton Vorontsov pci_read_config_word(pdev, 0x0a, &cc); 1001439fcaecSAnton Vorontsov if (cc == PCI_CLASS_STORAGE_IDE) 1002439fcaecSAnton Vorontsov scc_s = "IDE"; 1003439fcaecSAnton Vorontsov else if (cc == PCI_CLASS_STORAGE_SATA) 1004439fcaecSAnton Vorontsov scc_s = "SATA"; 1005439fcaecSAnton Vorontsov else if (cc == PCI_CLASS_STORAGE_RAID) 1006439fcaecSAnton Vorontsov scc_s = "RAID"; 1007439fcaecSAnton Vorontsov else 1008439fcaecSAnton Vorontsov scc_s = "unknown"; 1009439fcaecSAnton Vorontsov 1010439fcaecSAnton Vorontsov ahci_print_info(host, scc_s); 1011439fcaecSAnton Vorontsov } 1012439fcaecSAnton Vorontsov 1013edc93052STejun Heo /* On ASUS P5W DH Deluxe, the second port of PCI device 00:1f.2 is 1014edc93052STejun Heo * hardwired to on-board SIMG 4726. The chipset is ICH8 and doesn't 1015edc93052STejun Heo * support PMP and the 4726 either directly exports the device 1016edc93052STejun Heo * attached to the first downstream port or acts as a hardware storage 1017edc93052STejun Heo * controller and emulate a single ATA device (can be RAID 0/1 or some 1018edc93052STejun Heo * other configuration). 1019edc93052STejun Heo * 1020edc93052STejun Heo * When there's no device attached to the first downstream port of the 1021edc93052STejun Heo * 4726, "Config Disk" appears, which is a pseudo ATA device to 1022edc93052STejun Heo * configure the 4726. However, ATA emulation of the device is very 1023edc93052STejun Heo * lame. It doesn't send signature D2H Reg FIS after the initial 1024edc93052STejun Heo * hardreset, pukes on SRST w/ PMP==0 and has bunch of other issues. 1025edc93052STejun Heo * 1026edc93052STejun Heo * The following function works around the problem by always using 1027edc93052STejun Heo * hardreset on the port and not depending on receiving signature FIS 1028edc93052STejun Heo * afterward. If signature FIS isn't received soon, ATA class is 1029edc93052STejun Heo * assumed without follow-up softreset. 1030edc93052STejun Heo */ 1031edc93052STejun Heo static void ahci_p5wdh_workaround(struct ata_host *host) 1032edc93052STejun Heo { 10331bd06867SMathias Krause static const struct dmi_system_id sysids[] = { 1034edc93052STejun Heo { 1035edc93052STejun Heo .ident = "P5W DH Deluxe", 1036edc93052STejun Heo .matches = { 1037edc93052STejun Heo DMI_MATCH(DMI_SYS_VENDOR, 1038edc93052STejun Heo "ASUSTEK COMPUTER INC"), 1039edc93052STejun Heo DMI_MATCH(DMI_PRODUCT_NAME, "P5W DH Deluxe"), 1040edc93052STejun Heo }, 1041edc93052STejun Heo }, 1042edc93052STejun Heo { } 1043edc93052STejun Heo }; 1044edc93052STejun Heo struct pci_dev *pdev = to_pci_dev(host->dev); 1045edc93052STejun Heo 1046edc93052STejun Heo if (pdev->bus->number == 0 && pdev->devfn == PCI_DEVFN(0x1f, 2) && 1047edc93052STejun Heo dmi_check_system(sysids)) { 1048edc93052STejun Heo struct ata_port *ap = host->ports[1]; 1049edc93052STejun Heo 1050a44fec1fSJoe Perches dev_info(&pdev->dev, 1051a44fec1fSJoe Perches "enabling ASUS P5W DH Deluxe on-board SIMG4726 workaround\n"); 1052edc93052STejun Heo 1053edc93052STejun Heo ap->ops = &ahci_p5wdh_ops; 1054edc93052STejun Heo ap->link.flags |= ATA_LFLAG_NO_SRST | ATA_LFLAG_ASSUME_ATA; 1055edc93052STejun Heo } 1056edc93052STejun Heo } 1057edc93052STejun Heo 1058cb85696dSJames Laird /* 1059cb85696dSJames Laird * Macbook7,1 firmware forcibly disables MCP89 AHCI and changes PCI ID when 1060cb85696dSJames Laird * booting in BIOS compatibility mode. We restore the registers but not ID. 1061cb85696dSJames Laird */ 1062cb85696dSJames Laird static void ahci_mcp89_apple_enable(struct pci_dev *pdev) 1063cb85696dSJames Laird { 1064cb85696dSJames Laird u32 val; 1065cb85696dSJames Laird 1066cb85696dSJames Laird printk(KERN_INFO "ahci: enabling MCP89 AHCI mode\n"); 1067cb85696dSJames Laird 1068cb85696dSJames Laird pci_read_config_dword(pdev, 0xf8, &val); 1069cb85696dSJames Laird val |= 1 << 0x1b; 1070cb85696dSJames Laird /* the following changes the device ID, but appears not to affect function */ 1071cb85696dSJames Laird /* val = (val & ~0xf0000000) | 0x80000000; */ 1072cb85696dSJames Laird pci_write_config_dword(pdev, 0xf8, val); 1073cb85696dSJames Laird 1074cb85696dSJames Laird pci_read_config_dword(pdev, 0x54c, &val); 1075cb85696dSJames Laird val |= 1 << 0xc; 1076cb85696dSJames Laird pci_write_config_dword(pdev, 0x54c, val); 1077cb85696dSJames Laird 1078cb85696dSJames Laird pci_read_config_dword(pdev, 0x4a4, &val); 1079cb85696dSJames Laird val &= 0xff; 1080cb85696dSJames Laird val |= 0x01060100; 1081cb85696dSJames Laird pci_write_config_dword(pdev, 0x4a4, val); 1082cb85696dSJames Laird 1083cb85696dSJames Laird pci_read_config_dword(pdev, 0x54c, &val); 1084cb85696dSJames Laird val &= ~(1 << 0xc); 1085cb85696dSJames Laird pci_write_config_dword(pdev, 0x54c, val); 1086cb85696dSJames Laird 1087cb85696dSJames Laird pci_read_config_dword(pdev, 0xf8, &val); 1088cb85696dSJames Laird val &= ~(1 << 0x1b); 1089cb85696dSJames Laird pci_write_config_dword(pdev, 0xf8, val); 1090cb85696dSJames Laird } 1091cb85696dSJames Laird 1092cb85696dSJames Laird static bool is_mcp89_apple(struct pci_dev *pdev) 1093cb85696dSJames Laird { 1094cb85696dSJames Laird return pdev->vendor == PCI_VENDOR_ID_NVIDIA && 1095cb85696dSJames Laird pdev->device == PCI_DEVICE_ID_NVIDIA_NFORCE_MCP89_SATA && 1096cb85696dSJames Laird pdev->subsystem_vendor == PCI_VENDOR_ID_APPLE && 1097cb85696dSJames Laird pdev->subsystem_device == 0xcb89; 1098cb85696dSJames Laird } 1099cb85696dSJames Laird 11002fcad9d2STejun Heo /* only some SB600 ahci controllers can do 64bit DMA */ 11012fcad9d2STejun Heo static bool ahci_sb600_enable_64bit(struct pci_dev *pdev) 110258a09b38SShane Huang { 110358a09b38SShane Huang static const struct dmi_system_id sysids[] = { 110403d783bfSTejun Heo /* 110503d783bfSTejun Heo * The oldest version known to be broken is 0901 and 110603d783bfSTejun Heo * working is 1501 which was released on 2007-10-26. 11072fcad9d2STejun Heo * Enable 64bit DMA on 1501 and anything newer. 11082fcad9d2STejun Heo * 110903d783bfSTejun Heo * Please read bko#9412 for more info. 111003d783bfSTejun Heo */ 111158a09b38SShane Huang { 111258a09b38SShane Huang .ident = "ASUS M2A-VM", 111358a09b38SShane Huang .matches = { 111458a09b38SShane Huang DMI_MATCH(DMI_BOARD_VENDOR, 111558a09b38SShane Huang "ASUSTeK Computer INC."), 111658a09b38SShane Huang DMI_MATCH(DMI_BOARD_NAME, "M2A-VM"), 111758a09b38SShane Huang }, 111803d783bfSTejun Heo .driver_data = "20071026", /* yyyymmdd */ 111958a09b38SShane Huang }, 1120e65cc194SMark Nelson /* 1121e65cc194SMark Nelson * All BIOS versions for the MSI K9A2 Platinum (MS-7376) 1122e65cc194SMark Nelson * support 64bit DMA. 1123e65cc194SMark Nelson * 1124e65cc194SMark Nelson * BIOS versions earlier than 1.5 had the Manufacturer DMI 1125e65cc194SMark Nelson * fields as "MICRO-STAR INTERANTIONAL CO.,LTD". 1126e65cc194SMark Nelson * This spelling mistake was fixed in BIOS version 1.5, so 1127e65cc194SMark Nelson * 1.5 and later have the Manufacturer as 1128e65cc194SMark Nelson * "MICRO-STAR INTERNATIONAL CO.,LTD". 1129e65cc194SMark Nelson * So try to match on DMI_BOARD_VENDOR of "MICRO-STAR INTER". 1130e65cc194SMark Nelson * 1131e65cc194SMark Nelson * BIOS versions earlier than 1.9 had a Board Product Name 1132e65cc194SMark Nelson * DMI field of "MS-7376". This was changed to be 1133e65cc194SMark Nelson * "K9A2 Platinum (MS-7376)" in version 1.9, but we can still 1134e65cc194SMark Nelson * match on DMI_BOARD_NAME of "MS-7376". 1135e65cc194SMark Nelson */ 1136e65cc194SMark Nelson { 1137e65cc194SMark Nelson .ident = "MSI K9A2 Platinum", 1138e65cc194SMark Nelson .matches = { 1139e65cc194SMark Nelson DMI_MATCH(DMI_BOARD_VENDOR, 1140e65cc194SMark Nelson "MICRO-STAR INTER"), 1141e65cc194SMark Nelson DMI_MATCH(DMI_BOARD_NAME, "MS-7376"), 1142e65cc194SMark Nelson }, 1143e65cc194SMark Nelson }, 11443c4aa91fSMark Nelson /* 1145ff0173c1SMark Nelson * All BIOS versions for the MSI K9AGM2 (MS-7327) support 1146ff0173c1SMark Nelson * 64bit DMA. 1147ff0173c1SMark Nelson * 1148ff0173c1SMark Nelson * This board also had the typo mentioned above in the 1149ff0173c1SMark Nelson * Manufacturer DMI field (fixed in BIOS version 1.5), so 1150ff0173c1SMark Nelson * match on DMI_BOARD_VENDOR of "MICRO-STAR INTER" again. 1151ff0173c1SMark Nelson */ 1152ff0173c1SMark Nelson { 1153ff0173c1SMark Nelson .ident = "MSI K9AGM2", 1154ff0173c1SMark Nelson .matches = { 1155ff0173c1SMark Nelson DMI_MATCH(DMI_BOARD_VENDOR, 1156ff0173c1SMark Nelson "MICRO-STAR INTER"), 1157ff0173c1SMark Nelson DMI_MATCH(DMI_BOARD_NAME, "MS-7327"), 1158ff0173c1SMark Nelson }, 1159ff0173c1SMark Nelson }, 1160ff0173c1SMark Nelson /* 11613c4aa91fSMark Nelson * All BIOS versions for the Asus M3A support 64bit DMA. 11623c4aa91fSMark Nelson * (all release versions from 0301 to 1206 were tested) 11633c4aa91fSMark Nelson */ 11643c4aa91fSMark Nelson { 11653c4aa91fSMark Nelson .ident = "ASUS M3A", 11663c4aa91fSMark Nelson .matches = { 11673c4aa91fSMark Nelson DMI_MATCH(DMI_BOARD_VENDOR, 11683c4aa91fSMark Nelson "ASUSTeK Computer INC."), 11693c4aa91fSMark Nelson DMI_MATCH(DMI_BOARD_NAME, "M3A"), 11703c4aa91fSMark Nelson }, 11713c4aa91fSMark Nelson }, 117258a09b38SShane Huang { } 117358a09b38SShane Huang }; 117403d783bfSTejun Heo const struct dmi_system_id *match; 11752fcad9d2STejun Heo int year, month, date; 11762fcad9d2STejun Heo char buf[9]; 117758a09b38SShane Huang 117803d783bfSTejun Heo match = dmi_first_match(sysids); 117958a09b38SShane Huang if (pdev->bus->number != 0 || pdev->devfn != PCI_DEVFN(0x12, 0) || 118003d783bfSTejun Heo !match) 118158a09b38SShane Huang return false; 118258a09b38SShane Huang 1183e65cc194SMark Nelson if (!match->driver_data) 1184e65cc194SMark Nelson goto enable_64bit; 1185e65cc194SMark Nelson 118603d783bfSTejun Heo dmi_get_date(DMI_BIOS_DATE, &year, &month, &date); 118703d783bfSTejun Heo snprintf(buf, sizeof(buf), "%04d%02d%02d", year, month, date); 118803d783bfSTejun Heo 1189e65cc194SMark Nelson if (strcmp(buf, match->driver_data) >= 0) 1190e65cc194SMark Nelson goto enable_64bit; 1191e65cc194SMark Nelson else { 1192a44fec1fSJoe Perches dev_warn(&pdev->dev, 1193a44fec1fSJoe Perches "%s: BIOS too old, forcing 32bit DMA, update BIOS\n", 1194a44fec1fSJoe Perches match->ident); 11952fcad9d2STejun Heo return false; 11962fcad9d2STejun Heo } 1197e65cc194SMark Nelson 1198e65cc194SMark Nelson enable_64bit: 1199a44fec1fSJoe Perches dev_warn(&pdev->dev, "%s: enabling 64bit DMA\n", match->ident); 1200e65cc194SMark Nelson return true; 120158a09b38SShane Huang } 120258a09b38SShane Huang 12031fd68434SRafael J. Wysocki static bool ahci_broken_system_poweroff(struct pci_dev *pdev) 12041fd68434SRafael J. Wysocki { 12051fd68434SRafael J. Wysocki static const struct dmi_system_id broken_systems[] = { 12061fd68434SRafael J. Wysocki { 12071fd68434SRafael J. Wysocki .ident = "HP Compaq nx6310", 12081fd68434SRafael J. Wysocki .matches = { 12091fd68434SRafael J. Wysocki DMI_MATCH(DMI_SYS_VENDOR, "Hewlett-Packard"), 12101fd68434SRafael J. Wysocki DMI_MATCH(DMI_PRODUCT_NAME, "HP Compaq nx6310"), 12111fd68434SRafael J. Wysocki }, 12121fd68434SRafael J. Wysocki /* PCI slot number of the controller */ 12131fd68434SRafael J. Wysocki .driver_data = (void *)0x1FUL, 12141fd68434SRafael J. Wysocki }, 1215d2f9c061SMaciej Rutecki { 1216d2f9c061SMaciej Rutecki .ident = "HP Compaq 6720s", 1217d2f9c061SMaciej Rutecki .matches = { 1218d2f9c061SMaciej Rutecki DMI_MATCH(DMI_SYS_VENDOR, "Hewlett-Packard"), 1219d2f9c061SMaciej Rutecki DMI_MATCH(DMI_PRODUCT_NAME, "HP Compaq 6720s"), 1220d2f9c061SMaciej Rutecki }, 1221d2f9c061SMaciej Rutecki /* PCI slot number of the controller */ 1222d2f9c061SMaciej Rutecki .driver_data = (void *)0x1FUL, 1223d2f9c061SMaciej Rutecki }, 12241fd68434SRafael J. Wysocki 12251fd68434SRafael J. Wysocki { } /* terminate list */ 12261fd68434SRafael J. Wysocki }; 12271fd68434SRafael J. Wysocki const struct dmi_system_id *dmi = dmi_first_match(broken_systems); 12281fd68434SRafael J. Wysocki 12291fd68434SRafael J. Wysocki if (dmi) { 12301fd68434SRafael J. Wysocki unsigned long slot = (unsigned long)dmi->driver_data; 12311fd68434SRafael J. Wysocki /* apply the quirk only to on-board controllers */ 12321fd68434SRafael J. Wysocki return slot == PCI_SLOT(pdev->devfn); 12331fd68434SRafael J. Wysocki } 12341fd68434SRafael J. Wysocki 12351fd68434SRafael J. Wysocki return false; 12361fd68434SRafael J. Wysocki } 12371fd68434SRafael J. Wysocki 12389b10ae86STejun Heo static bool ahci_broken_suspend(struct pci_dev *pdev) 12399b10ae86STejun Heo { 12409b10ae86STejun Heo static const struct dmi_system_id sysids[] = { 12419b10ae86STejun Heo /* 12429b10ae86STejun Heo * On HP dv[4-6] and HDX18 with earlier BIOSen, link 12439b10ae86STejun Heo * to the harddisk doesn't become online after 12449b10ae86STejun Heo * resuming from STR. Warn and fail suspend. 12459deb3431STejun Heo * 12469deb3431STejun Heo * http://bugzilla.kernel.org/show_bug.cgi?id=12276 12479deb3431STejun Heo * 12489deb3431STejun Heo * Use dates instead of versions to match as HP is 12499deb3431STejun Heo * apparently recycling both product and version 12509deb3431STejun Heo * strings. 12519deb3431STejun Heo * 12529deb3431STejun Heo * http://bugzilla.kernel.org/show_bug.cgi?id=15462 12539b10ae86STejun Heo */ 12549b10ae86STejun Heo { 12559b10ae86STejun Heo .ident = "dv4", 12569b10ae86STejun Heo .matches = { 12579b10ae86STejun Heo DMI_MATCH(DMI_SYS_VENDOR, "Hewlett-Packard"), 12589b10ae86STejun Heo DMI_MATCH(DMI_PRODUCT_NAME, 12599b10ae86STejun Heo "HP Pavilion dv4 Notebook PC"), 12609b10ae86STejun Heo }, 12619deb3431STejun Heo .driver_data = "20090105", /* F.30 */ 12629b10ae86STejun Heo }, 12639b10ae86STejun Heo { 12649b10ae86STejun Heo .ident = "dv5", 12659b10ae86STejun Heo .matches = { 12669b10ae86STejun Heo DMI_MATCH(DMI_SYS_VENDOR, "Hewlett-Packard"), 12679b10ae86STejun Heo DMI_MATCH(DMI_PRODUCT_NAME, 12689b10ae86STejun Heo "HP Pavilion dv5 Notebook PC"), 12699b10ae86STejun Heo }, 12709deb3431STejun Heo .driver_data = "20090506", /* F.16 */ 12719b10ae86STejun Heo }, 12729b10ae86STejun Heo { 12739b10ae86STejun Heo .ident = "dv6", 12749b10ae86STejun Heo .matches = { 12759b10ae86STejun Heo DMI_MATCH(DMI_SYS_VENDOR, "Hewlett-Packard"), 12769b10ae86STejun Heo DMI_MATCH(DMI_PRODUCT_NAME, 12779b10ae86STejun Heo "HP Pavilion dv6 Notebook PC"), 12789b10ae86STejun Heo }, 12799deb3431STejun Heo .driver_data = "20090423", /* F.21 */ 12809b10ae86STejun Heo }, 12819b10ae86STejun Heo { 12829b10ae86STejun Heo .ident = "HDX18", 12839b10ae86STejun Heo .matches = { 12849b10ae86STejun Heo DMI_MATCH(DMI_SYS_VENDOR, "Hewlett-Packard"), 12859b10ae86STejun Heo DMI_MATCH(DMI_PRODUCT_NAME, 12869b10ae86STejun Heo "HP HDX18 Notebook PC"), 12879b10ae86STejun Heo }, 12889deb3431STejun Heo .driver_data = "20090430", /* F.23 */ 12899b10ae86STejun Heo }, 1290cedc9bf9STejun Heo /* 1291cedc9bf9STejun Heo * Acer eMachines G725 has the same problem. BIOS 1292cedc9bf9STejun Heo * V1.03 is known to be broken. V3.04 is known to 129325985edcSLucas De Marchi * work. Between, there are V1.06, V2.06 and V3.03 1294cedc9bf9STejun Heo * that we don't have much idea about. For now, 1295cedc9bf9STejun Heo * blacklist anything older than V3.04. 12969deb3431STejun Heo * 12979deb3431STejun Heo * http://bugzilla.kernel.org/show_bug.cgi?id=15104 1298cedc9bf9STejun Heo */ 1299cedc9bf9STejun Heo { 1300cedc9bf9STejun Heo .ident = "G725", 1301cedc9bf9STejun Heo .matches = { 1302cedc9bf9STejun Heo DMI_MATCH(DMI_SYS_VENDOR, "eMachines"), 1303cedc9bf9STejun Heo DMI_MATCH(DMI_PRODUCT_NAME, "eMachines G725"), 1304cedc9bf9STejun Heo }, 13059deb3431STejun Heo .driver_data = "20091216", /* V3.04 */ 1306cedc9bf9STejun Heo }, 13079b10ae86STejun Heo { } /* terminate list */ 13089b10ae86STejun Heo }; 13099b10ae86STejun Heo const struct dmi_system_id *dmi = dmi_first_match(sysids); 13109deb3431STejun Heo int year, month, date; 13119deb3431STejun Heo char buf[9]; 13129b10ae86STejun Heo 13139b10ae86STejun Heo if (!dmi || pdev->bus->number || pdev->devfn != PCI_DEVFN(0x1f, 2)) 13149b10ae86STejun Heo return false; 13159b10ae86STejun Heo 13169deb3431STejun Heo dmi_get_date(DMI_BIOS_DATE, &year, &month, &date); 13179deb3431STejun Heo snprintf(buf, sizeof(buf), "%04d%02d%02d", year, month, date); 13189b10ae86STejun Heo 13199deb3431STejun Heo return strcmp(buf, dmi->driver_data) < 0; 13209b10ae86STejun Heo } 13219b10ae86STejun Heo 1322240630e6SHans de Goede static bool ahci_broken_lpm(struct pci_dev *pdev) 1323240630e6SHans de Goede { 1324240630e6SHans de Goede static const struct dmi_system_id sysids[] = { 1325240630e6SHans de Goede /* Various Lenovo 50 series have LPM issues with older BIOSen */ 1326240630e6SHans de Goede { 1327240630e6SHans de Goede .matches = { 1328240630e6SHans de Goede DMI_MATCH(DMI_SYS_VENDOR, "LENOVO"), 1329240630e6SHans de Goede DMI_MATCH(DMI_PRODUCT_VERSION, "ThinkPad X250"), 1330240630e6SHans de Goede }, 1331240630e6SHans de Goede .driver_data = "20180406", /* 1.31 */ 1332240630e6SHans de Goede }, 1333240630e6SHans de Goede { 1334240630e6SHans de Goede .matches = { 1335240630e6SHans de Goede DMI_MATCH(DMI_SYS_VENDOR, "LENOVO"), 1336240630e6SHans de Goede DMI_MATCH(DMI_PRODUCT_VERSION, "ThinkPad L450"), 1337240630e6SHans de Goede }, 1338240630e6SHans de Goede .driver_data = "20180420", /* 1.28 */ 1339240630e6SHans de Goede }, 1340240630e6SHans de Goede { 1341240630e6SHans de Goede .matches = { 1342240630e6SHans de Goede DMI_MATCH(DMI_SYS_VENDOR, "LENOVO"), 1343240630e6SHans de Goede DMI_MATCH(DMI_PRODUCT_VERSION, "ThinkPad T450s"), 1344240630e6SHans de Goede }, 1345240630e6SHans de Goede .driver_data = "20180315", /* 1.33 */ 1346240630e6SHans de Goede }, 1347240630e6SHans de Goede { 1348240630e6SHans de Goede .matches = { 1349240630e6SHans de Goede DMI_MATCH(DMI_SYS_VENDOR, "LENOVO"), 1350240630e6SHans de Goede DMI_MATCH(DMI_PRODUCT_VERSION, "ThinkPad W541"), 1351240630e6SHans de Goede }, 1352240630e6SHans de Goede /* 1353240630e6SHans de Goede * Note date based on release notes, 2.35 has been 1354240630e6SHans de Goede * reported to be good, but I've been unable to get 1355240630e6SHans de Goede * a hold of the reporter to get the DMI BIOS date. 1356240630e6SHans de Goede * TODO: fix this. 1357240630e6SHans de Goede */ 1358240630e6SHans de Goede .driver_data = "20180310", /* 2.35 */ 1359240630e6SHans de Goede }, 1360240630e6SHans de Goede { } /* terminate list */ 1361240630e6SHans de Goede }; 1362240630e6SHans de Goede const struct dmi_system_id *dmi = dmi_first_match(sysids); 1363240630e6SHans de Goede int year, month, date; 1364240630e6SHans de Goede char buf[9]; 1365240630e6SHans de Goede 1366240630e6SHans de Goede if (!dmi) 1367240630e6SHans de Goede return false; 1368240630e6SHans de Goede 1369240630e6SHans de Goede dmi_get_date(DMI_BIOS_DATE, &year, &month, &date); 1370240630e6SHans de Goede snprintf(buf, sizeof(buf), "%04d%02d%02d", year, month, date); 1371240630e6SHans de Goede 1372240630e6SHans de Goede return strcmp(buf, dmi->driver_data) < 0; 1373240630e6SHans de Goede } 1374240630e6SHans de Goede 13755594639aSTejun Heo static bool ahci_broken_online(struct pci_dev *pdev) 13765594639aSTejun Heo { 13775594639aSTejun Heo #define ENCODE_BUSDEVFN(bus, slot, func) \ 13785594639aSTejun Heo (void *)(unsigned long)(((bus) << 8) | PCI_DEVFN((slot), (func))) 13795594639aSTejun Heo static const struct dmi_system_id sysids[] = { 13805594639aSTejun Heo /* 13815594639aSTejun Heo * There are several gigabyte boards which use 13825594639aSTejun Heo * SIMG5723s configured as hardware RAID. Certain 13835594639aSTejun Heo * 5723 firmware revisions shipped there keep the link 13845594639aSTejun Heo * online but fail to answer properly to SRST or 13855594639aSTejun Heo * IDENTIFY when no device is attached downstream 13865594639aSTejun Heo * causing libata to retry quite a few times leading 13875594639aSTejun Heo * to excessive detection delay. 13885594639aSTejun Heo * 13895594639aSTejun Heo * As these firmwares respond to the second reset try 13905594639aSTejun Heo * with invalid device signature, considering unknown 13915594639aSTejun Heo * sig as offline works around the problem acceptably. 13925594639aSTejun Heo */ 13935594639aSTejun Heo { 13945594639aSTejun Heo .ident = "EP45-DQ6", 13955594639aSTejun Heo .matches = { 13965594639aSTejun Heo DMI_MATCH(DMI_BOARD_VENDOR, 13975594639aSTejun Heo "Gigabyte Technology Co., Ltd."), 13985594639aSTejun Heo DMI_MATCH(DMI_BOARD_NAME, "EP45-DQ6"), 13995594639aSTejun Heo }, 14005594639aSTejun Heo .driver_data = ENCODE_BUSDEVFN(0x0a, 0x00, 0), 14015594639aSTejun Heo }, 14025594639aSTejun Heo { 14035594639aSTejun Heo .ident = "EP45-DS5", 14045594639aSTejun Heo .matches = { 14055594639aSTejun Heo DMI_MATCH(DMI_BOARD_VENDOR, 14065594639aSTejun Heo "Gigabyte Technology Co., Ltd."), 14075594639aSTejun Heo DMI_MATCH(DMI_BOARD_NAME, "EP45-DS5"), 14085594639aSTejun Heo }, 14095594639aSTejun Heo .driver_data = ENCODE_BUSDEVFN(0x03, 0x00, 0), 14105594639aSTejun Heo }, 14115594639aSTejun Heo { } /* terminate list */ 14125594639aSTejun Heo }; 14135594639aSTejun Heo #undef ENCODE_BUSDEVFN 14145594639aSTejun Heo const struct dmi_system_id *dmi = dmi_first_match(sysids); 14155594639aSTejun Heo unsigned int val; 14165594639aSTejun Heo 14175594639aSTejun Heo if (!dmi) 14185594639aSTejun Heo return false; 14195594639aSTejun Heo 14205594639aSTejun Heo val = (unsigned long)dmi->driver_data; 14215594639aSTejun Heo 14225594639aSTejun Heo return pdev->bus->number == (val >> 8) && pdev->devfn == (val & 0xff); 14235594639aSTejun Heo } 14245594639aSTejun Heo 14250cf4a7d6SJacob Pan static bool ahci_broken_devslp(struct pci_dev *pdev) 14260cf4a7d6SJacob Pan { 14270cf4a7d6SJacob Pan /* device with broken DEVSLP but still showing SDS capability */ 14280cf4a7d6SJacob Pan static const struct pci_device_id ids[] = { 14290cf4a7d6SJacob Pan { PCI_VDEVICE(INTEL, 0x0f23)}, /* Valleyview SoC */ 14300cf4a7d6SJacob Pan {} 14310cf4a7d6SJacob Pan }; 14320cf4a7d6SJacob Pan 14330cf4a7d6SJacob Pan return pci_match_id(ids, pdev); 14340cf4a7d6SJacob Pan } 14350cf4a7d6SJacob Pan 14368e513217SMarkus Trippelsdorf #ifdef CONFIG_ATA_ACPI 1437f80ae7e4STejun Heo static void ahci_gtf_filter_workaround(struct ata_host *host) 1438f80ae7e4STejun Heo { 1439f80ae7e4STejun Heo static const struct dmi_system_id sysids[] = { 1440f80ae7e4STejun Heo /* 1441f80ae7e4STejun Heo * Aspire 3810T issues a bunch of SATA enable commands 1442f80ae7e4STejun Heo * via _GTF including an invalid one and one which is 1443f80ae7e4STejun Heo * rejected by the device. Among the successful ones 1444f80ae7e4STejun Heo * is FPDMA non-zero offset enable which when enabled 1445f80ae7e4STejun Heo * only on the drive side leads to NCQ command 1446f80ae7e4STejun Heo * failures. Filter it out. 1447f80ae7e4STejun Heo */ 1448f80ae7e4STejun Heo { 1449f80ae7e4STejun Heo .ident = "Aspire 3810T", 1450f80ae7e4STejun Heo .matches = { 1451f80ae7e4STejun Heo DMI_MATCH(DMI_SYS_VENDOR, "Acer"), 1452f80ae7e4STejun Heo DMI_MATCH(DMI_PRODUCT_NAME, "Aspire 3810T"), 1453f80ae7e4STejun Heo }, 1454f80ae7e4STejun Heo .driver_data = (void *)ATA_ACPI_FILTER_FPDMA_OFFSET, 1455f80ae7e4STejun Heo }, 1456f80ae7e4STejun Heo { } 1457f80ae7e4STejun Heo }; 1458f80ae7e4STejun Heo const struct dmi_system_id *dmi = dmi_first_match(sysids); 1459f80ae7e4STejun Heo unsigned int filter; 1460f80ae7e4STejun Heo int i; 1461f80ae7e4STejun Heo 1462f80ae7e4STejun Heo if (!dmi) 1463f80ae7e4STejun Heo return; 1464f80ae7e4STejun Heo 1465f80ae7e4STejun Heo filter = (unsigned long)dmi->driver_data; 1466a44fec1fSJoe Perches dev_info(host->dev, "applying extra ACPI _GTF filter 0x%x for %s\n", 1467f80ae7e4STejun Heo filter, dmi->ident); 1468f80ae7e4STejun Heo 1469f80ae7e4STejun Heo for (i = 0; i < host->n_ports; i++) { 1470f80ae7e4STejun Heo struct ata_port *ap = host->ports[i]; 1471f80ae7e4STejun Heo struct ata_link *link; 1472f80ae7e4STejun Heo struct ata_device *dev; 1473f80ae7e4STejun Heo 1474f80ae7e4STejun Heo ata_for_each_link(link, ap, EDGE) 1475f80ae7e4STejun Heo ata_for_each_dev(dev, link, ALL) 1476f80ae7e4STejun Heo dev->gtf_filter |= filter; 1477f80ae7e4STejun Heo } 1478f80ae7e4STejun Heo } 14798e513217SMarkus Trippelsdorf #else 14808e513217SMarkus Trippelsdorf static inline void ahci_gtf_filter_workaround(struct ata_host *host) 14818e513217SMarkus Trippelsdorf {} 14828e513217SMarkus Trippelsdorf #endif 1483f80ae7e4STejun Heo 14848bfd1743SSui Chen /* 14858bfd1743SSui Chen * On the Acer Aspire Switch Alpha 12, sometimes all SATA ports are detected 14868bfd1743SSui Chen * as DUMMY, or detected but eventually get a "link down" and never get up 14878bfd1743SSui Chen * again. When this happens, CAP.NP may hold a value of 0x00 or 0x01, and the 14888bfd1743SSui Chen * port_map may hold a value of 0x00. 14898bfd1743SSui Chen * 14908bfd1743SSui Chen * Overriding CAP.NP to 0x02 and the port_map to 0x7 will reveal all 3 ports 14918bfd1743SSui Chen * and can significantly reduce the occurrence of the problem. 14928bfd1743SSui Chen * 14938bfd1743SSui Chen * https://bugzilla.kernel.org/show_bug.cgi?id=189471 14948bfd1743SSui Chen */ 14958bfd1743SSui Chen static void acer_sa5_271_workaround(struct ahci_host_priv *hpriv, 14968bfd1743SSui Chen struct pci_dev *pdev) 14978bfd1743SSui Chen { 14988bfd1743SSui Chen static const struct dmi_system_id sysids[] = { 14998bfd1743SSui Chen { 15008bfd1743SSui Chen .ident = "Acer Switch Alpha 12", 15018bfd1743SSui Chen .matches = { 15028bfd1743SSui Chen DMI_MATCH(DMI_SYS_VENDOR, "Acer"), 15038bfd1743SSui Chen DMI_MATCH(DMI_PRODUCT_NAME, "Switch SA5-271") 15048bfd1743SSui Chen }, 15058bfd1743SSui Chen }, 15068bfd1743SSui Chen { } 15078bfd1743SSui Chen }; 15088bfd1743SSui Chen 15098bfd1743SSui Chen if (dmi_check_system(sysids)) { 15108bfd1743SSui Chen dev_info(&pdev->dev, "enabling Acer Switch Alpha 12 workaround\n"); 15118bfd1743SSui Chen if ((hpriv->saved_cap & 0xC734FF00) == 0xC734FF00) { 15128bfd1743SSui Chen hpriv->port_map = 0x7; 15138bfd1743SSui Chen hpriv->cap = 0xC734FF02; 15148bfd1743SSui Chen } 15158bfd1743SSui Chen } 15168bfd1743SSui Chen } 15178bfd1743SSui Chen 1518d243bed3STirumalesh Chalamarla #ifdef CONFIG_ARM64 1519d243bed3STirumalesh Chalamarla /* 1520d243bed3STirumalesh Chalamarla * Due to ERRATA#22536, ThunderX needs to handle HOST_IRQ_STAT differently. 1521d243bed3STirumalesh Chalamarla * Workaround is to make sure all pending IRQs are served before leaving 1522d243bed3STirumalesh Chalamarla * handler. 1523d243bed3STirumalesh Chalamarla */ 1524d243bed3STirumalesh Chalamarla static irqreturn_t ahci_thunderx_irq_handler(int irq, void *dev_instance) 1525d243bed3STirumalesh Chalamarla { 1526d243bed3STirumalesh Chalamarla struct ata_host *host = dev_instance; 1527d243bed3STirumalesh Chalamarla struct ahci_host_priv *hpriv; 1528d243bed3STirumalesh Chalamarla unsigned int rc = 0; 1529d243bed3STirumalesh Chalamarla void __iomem *mmio; 1530d243bed3STirumalesh Chalamarla u32 irq_stat, irq_masked; 1531d243bed3STirumalesh Chalamarla unsigned int handled = 1; 1532d243bed3STirumalesh Chalamarla 1533d243bed3STirumalesh Chalamarla hpriv = host->private_data; 1534d243bed3STirumalesh Chalamarla mmio = hpriv->mmio; 1535d243bed3STirumalesh Chalamarla irq_stat = readl(mmio + HOST_IRQ_STAT); 1536d243bed3STirumalesh Chalamarla if (!irq_stat) 1537d243bed3STirumalesh Chalamarla return IRQ_NONE; 1538d243bed3STirumalesh Chalamarla 1539d243bed3STirumalesh Chalamarla do { 1540d243bed3STirumalesh Chalamarla irq_masked = irq_stat & hpriv->port_map; 1541d243bed3STirumalesh Chalamarla spin_lock(&host->lock); 1542d243bed3STirumalesh Chalamarla rc = ahci_handle_port_intr(host, irq_masked); 1543d243bed3STirumalesh Chalamarla if (!rc) 1544d243bed3STirumalesh Chalamarla handled = 0; 1545d243bed3STirumalesh Chalamarla writel(irq_stat, mmio + HOST_IRQ_STAT); 1546d243bed3STirumalesh Chalamarla irq_stat = readl(mmio + HOST_IRQ_STAT); 1547d243bed3STirumalesh Chalamarla spin_unlock(&host->lock); 1548d243bed3STirumalesh Chalamarla } while (irq_stat); 1549d243bed3STirumalesh Chalamarla 1550d243bed3STirumalesh Chalamarla return IRQ_RETVAL(handled); 1551d243bed3STirumalesh Chalamarla } 1552d243bed3STirumalesh Chalamarla #endif 1553d243bed3STirumalesh Chalamarla 1554aecec8b6SChristoph Hellwig static void ahci_remap_check(struct pci_dev *pdev, int bar, 1555aecec8b6SChristoph Hellwig struct ahci_host_priv *hpriv) 1556aecec8b6SChristoph Hellwig { 1557894fba7fSKai-Heng Feng int i; 1558aecec8b6SChristoph Hellwig u32 cap; 1559aecec8b6SChristoph Hellwig 1560aecec8b6SChristoph Hellwig /* 1561aecec8b6SChristoph Hellwig * Check if this device might have remapped nvme devices. 1562aecec8b6SChristoph Hellwig */ 1563aecec8b6SChristoph Hellwig if (pdev->vendor != PCI_VENDOR_ID_INTEL || 1564aecec8b6SChristoph Hellwig pci_resource_len(pdev, bar) < SZ_512K || 1565aecec8b6SChristoph Hellwig bar != AHCI_PCI_BAR_STANDARD || 1566aecec8b6SChristoph Hellwig !(readl(hpriv->mmio + AHCI_VSCAP) & 1)) 1567aecec8b6SChristoph Hellwig return; 1568aecec8b6SChristoph Hellwig 1569aecec8b6SChristoph Hellwig cap = readq(hpriv->mmio + AHCI_REMAP_CAP); 1570aecec8b6SChristoph Hellwig for (i = 0; i < AHCI_MAX_REMAP; i++) { 1571aecec8b6SChristoph Hellwig if ((cap & (1 << i)) == 0) 1572aecec8b6SChristoph Hellwig continue; 1573aecec8b6SChristoph Hellwig if (readl(hpriv->mmio + ahci_remap_dcc(i)) 1574aecec8b6SChristoph Hellwig != PCI_CLASS_STORAGE_EXPRESS) 1575aecec8b6SChristoph Hellwig continue; 1576aecec8b6SChristoph Hellwig 1577aecec8b6SChristoph Hellwig /* We've found a remapped device */ 1578894fba7fSKai-Heng Feng hpriv->remapped_nvme++; 1579aecec8b6SChristoph Hellwig } 1580aecec8b6SChristoph Hellwig 1581894fba7fSKai-Heng Feng if (!hpriv->remapped_nvme) 1582aecec8b6SChristoph Hellwig return; 1583aecec8b6SChristoph Hellwig 1584894fba7fSKai-Heng Feng dev_warn(&pdev->dev, "Found %u remapped NVMe devices.\n", 1585894fba7fSKai-Heng Feng hpriv->remapped_nvme); 1586f723fa4eSChristoph Hellwig dev_warn(&pdev->dev, 1587f723fa4eSChristoph Hellwig "Switch your BIOS from RAID to AHCI mode to use them.\n"); 1588f723fa4eSChristoph Hellwig 1589f723fa4eSChristoph Hellwig /* 1590f723fa4eSChristoph Hellwig * Don't rely on the msi-x capability in the remap case, 1591f723fa4eSChristoph Hellwig * share the legacy interrupt across ahci and remapped devices. 1592f723fa4eSChristoph Hellwig */ 1593f723fa4eSChristoph Hellwig hpriv->flags |= AHCI_HFLAG_NO_MSI; 1594aecec8b6SChristoph Hellwig } 1595aecec8b6SChristoph Hellwig 15960b9e2988SChristoph Hellwig static int ahci_get_irq_vector(struct ata_host *host, int port) 1597ee2aad42SRobert Richter { 15980b9e2988SChristoph Hellwig return pci_irq_vector(to_pci_dev(host->dev), port); 1599ee2aad42SRobert Richter } 1600ee2aad42SRobert Richter 1601a1c82311SRobert Richter static int ahci_init_msi(struct pci_dev *pdev, unsigned int n_ports, 16027b92b4f6SAlexander Gordeev struct ahci_host_priv *hpriv) 16035ca72c4fSAlexander Gordeev { 16040b9e2988SChristoph Hellwig int nvec; 16055ca72c4fSAlexander Gordeev 16067b92b4f6SAlexander Gordeev if (hpriv->flags & AHCI_HFLAG_NO_MSI) 1607a1c82311SRobert Richter return -ENODEV; 16087b92b4f6SAlexander Gordeev 16095ca72c4fSAlexander Gordeev /* 16107b92b4f6SAlexander Gordeev * If number of MSIs is less than number of ports then Sharing Last 16117b92b4f6SAlexander Gordeev * Message mode could be enforced. In this case assume that advantage 16127b92b4f6SAlexander Gordeev * of multipe MSIs is negated and use single MSI mode instead. 16135ca72c4fSAlexander Gordeev */ 161417a51f12SChristoph Hellwig if (n_ports > 1) { 16150b9e2988SChristoph Hellwig nvec = pci_alloc_irq_vectors(pdev, n_ports, INT_MAX, 16160b9e2988SChristoph Hellwig PCI_IRQ_MSIX | PCI_IRQ_MSI); 16170b9e2988SChristoph Hellwig if (nvec > 0) { 16180b9e2988SChristoph Hellwig if (!(readl(hpriv->mmio + HOST_CTL) & HOST_MRSM)) { 16190b9e2988SChristoph Hellwig hpriv->get_irq_vector = ahci_get_irq_vector; 1620c3ebd6a9SAlexander Gordeev hpriv->flags |= AHCI_HFLAG_MULTI_MSI; 162121bfd1aaSRobert Richter return nvec; 1622a1c82311SRobert Richter } 1623a1c82311SRobert Richter 1624d684a90dSDan Williams /* 162517a51f12SChristoph Hellwig * Fallback to single MSI mode if the controller 162617a51f12SChristoph Hellwig * enforced MRSM mode. 1627d684a90dSDan Williams */ 162817a51f12SChristoph Hellwig printk(KERN_INFO 162917a51f12SChristoph Hellwig "ahci: MRSM is on, fallback to single MSI\n"); 16300b9e2988SChristoph Hellwig pci_free_irq_vectors(pdev); 16310b9e2988SChristoph Hellwig } 1632a478b097SChristoph Hellwig } 1633d684a90dSDan Williams 16340b9e2988SChristoph Hellwig /* 16350b9e2988SChristoph Hellwig * If the host is not capable of supporting per-port vectors, fall 16360b9e2988SChristoph Hellwig * back to single MSI before finally attempting single MSI-X. 16370b9e2988SChristoph Hellwig */ 16380b9e2988SChristoph Hellwig nvec = pci_alloc_irq_vectors(pdev, 1, 1, PCI_IRQ_MSI); 16390b9e2988SChristoph Hellwig if (nvec == 1) 1640a1c82311SRobert Richter return nvec; 16410b9e2988SChristoph Hellwig return pci_alloc_irq_vectors(pdev, 1, 1, PCI_IRQ_MSIX); 16425ca72c4fSAlexander Gordeev } 16435ca72c4fSAlexander Gordeev 1644b1a9585cSSrinivas Pandruvada static void ahci_update_initial_lpm_policy(struct ata_port *ap, 1645b1a9585cSSrinivas Pandruvada struct ahci_host_priv *hpriv) 1646b1a9585cSSrinivas Pandruvada { 164755b01415SMario Limonciello int policy = CONFIG_SATA_MOBILE_LPM_POLICY; 1648b1a9585cSSrinivas Pandruvada 1649b1a9585cSSrinivas Pandruvada 1650e5c89479SMario Limonciello /* Ignore processing for chipsets that don't use policy */ 1651e5c89479SMario Limonciello if (!(hpriv->flags & AHCI_HFLAG_USE_LPM_POLICY)) 1652b1a9585cSSrinivas Pandruvada return; 1653b1a9585cSSrinivas Pandruvada 1654b1a9585cSSrinivas Pandruvada /* user modified policy via module param */ 1655b1a9585cSSrinivas Pandruvada if (mobile_lpm_policy != -1) { 1656b1a9585cSSrinivas Pandruvada policy = mobile_lpm_policy; 1657b1a9585cSSrinivas Pandruvada goto update_policy; 1658b1a9585cSSrinivas Pandruvada } 1659b1a9585cSSrinivas Pandruvada 1660fee60730SRafael J. Wysocki if (policy > ATA_LPM_MED_POWER && pm_suspend_default_s2idle()) { 1661b1a9585cSSrinivas Pandruvada if (hpriv->cap & HOST_CAP_PART) 1662b1a9585cSSrinivas Pandruvada policy = ATA_LPM_MIN_POWER_WITH_PARTIAL; 1663b1a9585cSSrinivas Pandruvada else if (hpriv->cap & HOST_CAP_SSC) 1664b1a9585cSSrinivas Pandruvada policy = ATA_LPM_MIN_POWER; 1665b1a9585cSSrinivas Pandruvada } 1666b1a9585cSSrinivas Pandruvada 1667b1a9585cSSrinivas Pandruvada update_policy: 1668b1a9585cSSrinivas Pandruvada if (policy >= ATA_LPM_UNKNOWN && policy <= ATA_LPM_MIN_POWER) 1669b1a9585cSSrinivas Pandruvada ap->target_lpm_policy = policy; 1670b1a9585cSSrinivas Pandruvada } 1671b1a9585cSSrinivas Pandruvada 1672c312ef17SDan Williams static void ahci_intel_pcs_quirk(struct pci_dev *pdev, struct ahci_host_priv *hpriv) 1673c312ef17SDan Williams { 1674c312ef17SDan Williams const struct pci_device_id *id = pci_match_id(ahci_pci_tbl, pdev); 1675c312ef17SDan Williams u16 tmp16; 1676c312ef17SDan Williams 1677c312ef17SDan Williams /* 1678c312ef17SDan Williams * Only apply the 6-port PCS quirk for known legacy platforms. 1679c312ef17SDan Williams */ 1680c312ef17SDan Williams if (!id || id->vendor != PCI_VENDOR_ID_INTEL) 1681c312ef17SDan Williams return; 168209d6ac8dSDan Williams 168309d6ac8dSDan Williams /* Skip applying the quirk on Denverton and beyond */ 168409d6ac8dSDan Williams if (((enum board_ids) id->driver_data) >= board_ahci_pcs7) 1685c312ef17SDan Williams return; 1686c312ef17SDan Williams 1687c312ef17SDan Williams /* 1688c312ef17SDan Williams * port_map is determined from PORTS_IMPL PCI register which is 1689c312ef17SDan Williams * implemented as write or write-once register. If the register 1690c312ef17SDan Williams * isn't programmed, ahci automatically generates it from number 1691c312ef17SDan Williams * of ports, which is good enough for PCS programming. It is 1692c312ef17SDan Williams * otherwise expected that platform firmware enables the ports 1693c312ef17SDan Williams * before the OS boots. 1694c312ef17SDan Williams */ 1695c312ef17SDan Williams pci_read_config_word(pdev, PCS_6, &tmp16); 1696c312ef17SDan Williams if ((tmp16 & hpriv->port_map) != hpriv->port_map) { 1697c312ef17SDan Williams tmp16 |= hpriv->port_map; 1698c312ef17SDan Williams pci_write_config_word(pdev, PCS_6, tmp16); 1699c312ef17SDan Williams } 1700c312ef17SDan Williams } 1701c312ef17SDan Williams 1702894fba7fSKai-Heng Feng static ssize_t remapped_nvme_show(struct device *dev, 1703894fba7fSKai-Heng Feng struct device_attribute *attr, 1704894fba7fSKai-Heng Feng char *buf) 1705894fba7fSKai-Heng Feng { 1706894fba7fSKai-Heng Feng struct ata_host *host = dev_get_drvdata(dev); 1707894fba7fSKai-Heng Feng struct ahci_host_priv *hpriv = host->private_data; 1708894fba7fSKai-Heng Feng 1709179a0282SDamien Le Moal return sysfs_emit(buf, "%u\n", hpriv->remapped_nvme); 1710894fba7fSKai-Heng Feng } 1711894fba7fSKai-Heng Feng 1712894fba7fSKai-Heng Feng static DEVICE_ATTR_RO(remapped_nvme); 1713894fba7fSKai-Heng Feng 1714c6fd2807SJeff Garzik static int ahci_init_one(struct pci_dev *pdev, const struct pci_device_id *ent) 1715c6fd2807SJeff Garzik { 1716e297d99eSTejun Heo unsigned int board_id = ent->driver_data; 1717e297d99eSTejun Heo struct ata_port_info pi = ahci_port_info[board_id]; 17184447d351STejun Heo const struct ata_port_info *ppi[] = { &pi, NULL }; 171924dc5f33STejun Heo struct device *dev = &pdev->dev; 1720c6fd2807SJeff Garzik struct ahci_host_priv *hpriv; 17214447d351STejun Heo struct ata_host *host; 1722c3ebd6a9SAlexander Gordeev int n_ports, i, rc; 1723318893e1SAlessandro Rubini int ahci_pci_bar = AHCI_PCI_BAR_STANDARD; 1724c6fd2807SJeff Garzik 1725b429dd59SJustin P. Mattock WARN_ON((int)ATA_MAX_QUEUE > AHCI_MAX_CMDS); 1726c6fd2807SJeff Garzik 172706296a1eSJoe Perches ata_print_version_once(&pdev->dev, DRV_VERSION); 1728c6fd2807SJeff Garzik 17295b66c829SAlan Cox /* The AHCI driver can only drive the SATA ports, the PATA driver 17305b66c829SAlan Cox can drive them all so if both drivers are selected make sure 17315b66c829SAlan Cox AHCI stays out of the way */ 17325b66c829SAlan Cox if (pdev->vendor == PCI_VENDOR_ID_MARVELL && !marvell_enable) 17335b66c829SAlan Cox return -ENODEV; 17345b66c829SAlan Cox 1735cb85696dSJames Laird /* Apple BIOS on MCP89 prevents us using AHCI */ 1736cb85696dSJames Laird if (is_mcp89_apple(pdev)) 1737cb85696dSJames Laird ahci_mcp89_apple_enable(pdev); 1738c6353b45STejun Heo 17397a02267eSMark Nelson /* Promise's PDC42819 is a SAS/SATA controller that has an AHCI mode. 17407a02267eSMark Nelson * At the moment, we can only use the AHCI mode. Let the users know 17417a02267eSMark Nelson * that for SAS drives they're out of luck. 17427a02267eSMark Nelson */ 17437a02267eSMark Nelson if (pdev->vendor == PCI_VENDOR_ID_PROMISE) 1744a44fec1fSJoe Perches dev_info(&pdev->dev, 1745a44fec1fSJoe Perches "PDC42819 can only drive SATA devices with this driver\n"); 17467a02267eSMark Nelson 1747b7ae128dSRobert Richter /* Some devices use non-standard BARs */ 1748318893e1SAlessandro Rubini if (pdev->vendor == PCI_VENDOR_ID_STMICRO && pdev->device == 0xCC06) 1749318893e1SAlessandro Rubini ahci_pci_bar = AHCI_PCI_BAR_STA2X11; 17507f9c9f8eSHugh Daschbach else if (pdev->vendor == 0x1c44 && pdev->device == 0x8000) 17517f9c9f8eSHugh Daschbach ahci_pci_bar = AHCI_PCI_BAR_ENMOTUS; 1752b1314e3fSRadha Mohan Chintakuntla else if (pdev->vendor == PCI_VENDOR_ID_CAVIUM) { 1753b1314e3fSRadha Mohan Chintakuntla if (pdev->device == 0xa01c) 1754b7ae128dSRobert Richter ahci_pci_bar = AHCI_PCI_BAR_CAVIUM; 1755b1314e3fSRadha Mohan Chintakuntla if (pdev->device == 0xa084) 1756b1314e3fSRadha Mohan Chintakuntla ahci_pci_bar = AHCI_PCI_BAR_CAVIUM_GEN5; 1757e49bd683STiezhu Yang } else if (pdev->vendor == PCI_VENDOR_ID_LOONGSON) { 1758e49bd683STiezhu Yang if (pdev->device == 0x7a08) 1759e49bd683STiezhu Yang ahci_pci_bar = AHCI_PCI_BAR_LOONGSON; 1760b1314e3fSRadha Mohan Chintakuntla } 1761318893e1SAlessandro Rubini 17624447d351STejun Heo /* acquire resources */ 176324dc5f33STejun Heo rc = pcim_enable_device(pdev); 1764c6fd2807SJeff Garzik if (rc) 1765c6fd2807SJeff Garzik return rc; 1766c6fd2807SJeff Garzik 1767c4f7792cSTejun Heo if (pdev->vendor == PCI_VENDOR_ID_INTEL && 1768c4f7792cSTejun Heo (pdev->device == 0x2652 || pdev->device == 0x2653)) { 1769c4f7792cSTejun Heo u8 map; 1770c4f7792cSTejun Heo 1771c4f7792cSTejun Heo /* ICH6s share the same PCI ID for both piix and ahci 1772c4f7792cSTejun Heo * modes. Enabling ahci mode while MAP indicates 1773c4f7792cSTejun Heo * combined mode is a bad idea. Yield to ata_piix. 1774c4f7792cSTejun Heo */ 1775c4f7792cSTejun Heo pci_read_config_byte(pdev, ICH_MAP, &map); 1776c4f7792cSTejun Heo if (map & 0x3) { 1777a44fec1fSJoe Perches dev_info(&pdev->dev, 1778a44fec1fSJoe Perches "controller is in combined mode, can't enable AHCI mode\n"); 1779c4f7792cSTejun Heo return -ENODEV; 1780c4f7792cSTejun Heo } 1781c4f7792cSTejun Heo } 1782c4f7792cSTejun Heo 17836fec8871SPaul Bolle /* AHCI controllers often implement SFF compatible interface. 17846fec8871SPaul Bolle * Grab all PCI BARs just in case. 17856fec8871SPaul Bolle */ 17866fec8871SPaul Bolle rc = pcim_iomap_regions_request_all(pdev, 1 << ahci_pci_bar, DRV_NAME); 17876fec8871SPaul Bolle if (rc == -EBUSY) 17886fec8871SPaul Bolle pcim_pin_device(pdev); 17896fec8871SPaul Bolle if (rc) 17906fec8871SPaul Bolle return rc; 17916fec8871SPaul Bolle 179224dc5f33STejun Heo hpriv = devm_kzalloc(dev, sizeof(*hpriv), GFP_KERNEL); 179324dc5f33STejun Heo if (!hpriv) 179424dc5f33STejun Heo return -ENOMEM; 1795417a1a6dSTejun Heo hpriv->flags |= (unsigned long)pi.private_data; 1796417a1a6dSTejun Heo 1797e297d99eSTejun Heo /* MCP65 revision A1 and A2 can't do MSI */ 1798e297d99eSTejun Heo if (board_id == board_ahci_mcp65 && 1799e297d99eSTejun Heo (pdev->revision == 0xa1 || pdev->revision == 0xa2)) 1800e297d99eSTejun Heo hpriv->flags |= AHCI_HFLAG_NO_MSI; 1801e297d99eSTejun Heo 1802e427fe04SShane Huang /* SB800 does NOT need the workaround to ignore SERR_INTERNAL */ 1803e427fe04SShane Huang if (board_id == board_ahci_sb700 && pdev->revision >= 0x40) 1804e427fe04SShane Huang hpriv->flags &= ~AHCI_HFLAG_IGN_SERR_INTERNAL; 1805e427fe04SShane Huang 18062fcad9d2STejun Heo /* only some SB600s can do 64bit DMA */ 18072fcad9d2STejun Heo if (ahci_sb600_enable_64bit(pdev)) 18082fcad9d2STejun Heo hpriv->flags &= ~AHCI_HFLAG_32BIT_ONLY; 180958a09b38SShane Huang 1810318893e1SAlessandro Rubini hpriv->mmio = pcim_iomap_table(pdev)[ahci_pci_bar]; 1811d8993349SAnton Vorontsov 1812aecec8b6SChristoph Hellwig /* detect remapped nvme devices */ 1813aecec8b6SChristoph Hellwig ahci_remap_check(pdev, ahci_pci_bar, hpriv); 1814aecec8b6SChristoph Hellwig 1815894fba7fSKai-Heng Feng sysfs_add_file_to_group(&pdev->dev.kobj, 1816894fba7fSKai-Heng Feng &dev_attr_remapped_nvme.attr, 1817894fba7fSKai-Heng Feng NULL); 1818894fba7fSKai-Heng Feng 18190cf4a7d6SJacob Pan /* must set flag prior to save config in order to take effect */ 18200cf4a7d6SJacob Pan if (ahci_broken_devslp(pdev)) 18210cf4a7d6SJacob Pan hpriv->flags |= AHCI_HFLAG_NO_DEVSLP; 18220cf4a7d6SJacob Pan 1823d243bed3STirumalesh Chalamarla #ifdef CONFIG_ARM64 1824234e6d2cSXingui Yang if (pdev->vendor == PCI_VENDOR_ID_HUAWEI && 1825234e6d2cSXingui Yang pdev->device == 0xa235 && 1826234e6d2cSXingui Yang pdev->revision < 0x30) 1827234e6d2cSXingui Yang hpriv->flags |= AHCI_HFLAG_NO_SXS; 1828234e6d2cSXingui Yang 1829d243bed3STirumalesh Chalamarla if (pdev->vendor == 0x177d && pdev->device == 0xa01c) 1830d243bed3STirumalesh Chalamarla hpriv->irq_handler = ahci_thunderx_irq_handler; 1831d243bed3STirumalesh Chalamarla #endif 1832d243bed3STirumalesh Chalamarla 18334447d351STejun Heo /* save initial config */ 1834394d6e53SAnton Vorontsov ahci_pci_save_initial_config(pdev, hpriv); 1835c6fd2807SJeff Garzik 18364447d351STejun Heo /* prepare host */ 1837453d3131SRobert Hancock if (hpriv->cap & HOST_CAP_NCQ) { 1838453d3131SRobert Hancock pi.flags |= ATA_FLAG_NCQ; 183983f2b963STejun Heo /* 184083f2b963STejun Heo * Auto-activate optimization is supposed to be 184183f2b963STejun Heo * supported on all AHCI controllers indicating NCQ 184283f2b963STejun Heo * capability, but it seems to be broken on some 184383f2b963STejun Heo * chipsets including NVIDIAs. 184483f2b963STejun Heo */ 184583f2b963STejun Heo if (!(hpriv->flags & AHCI_HFLAG_NO_FPDMA_AA)) 1846453d3131SRobert Hancock pi.flags |= ATA_FLAG_FPDMA_AA; 184740fb59e7SMarc Carino 184840fb59e7SMarc Carino /* 184940fb59e7SMarc Carino * All AHCI controllers should be forward-compatible 185040fb59e7SMarc Carino * with the new auxiliary field. This code should be 185140fb59e7SMarc Carino * conditionalized if any buggy AHCI controllers are 185240fb59e7SMarc Carino * encountered. 185340fb59e7SMarc Carino */ 185440fb59e7SMarc Carino pi.flags |= ATA_FLAG_FPDMA_AUX; 1855453d3131SRobert Hancock } 18564447d351STejun Heo 18577d50b60bSTejun Heo if (hpriv->cap & HOST_CAP_PMP) 18587d50b60bSTejun Heo pi.flags |= ATA_FLAG_PMP; 18597d50b60bSTejun Heo 18600cbb0e77SAnton Vorontsov ahci_set_em_messages(hpriv, &pi); 186118f7ba4cSKristen Carlson Accardi 18621fd68434SRafael J. Wysocki if (ahci_broken_system_poweroff(pdev)) { 18631fd68434SRafael J. Wysocki pi.flags |= ATA_FLAG_NO_POWEROFF_SPINDOWN; 18641fd68434SRafael J. Wysocki dev_info(&pdev->dev, 18651fd68434SRafael J. Wysocki "quirky BIOS, skipping spindown on poweroff\n"); 18661fd68434SRafael J. Wysocki } 18671fd68434SRafael J. Wysocki 1868240630e6SHans de Goede if (ahci_broken_lpm(pdev)) { 1869240630e6SHans de Goede pi.flags |= ATA_FLAG_NO_LPM; 1870240630e6SHans de Goede dev_warn(&pdev->dev, 1871240630e6SHans de Goede "BIOS update required for Link Power Management support\n"); 1872240630e6SHans de Goede } 1873240630e6SHans de Goede 18749b10ae86STejun Heo if (ahci_broken_suspend(pdev)) { 18759b10ae86STejun Heo hpriv->flags |= AHCI_HFLAG_NO_SUSPEND; 1876a44fec1fSJoe Perches dev_warn(&pdev->dev, 18779b10ae86STejun Heo "BIOS update required for suspend/resume\n"); 18789b10ae86STejun Heo } 18799b10ae86STejun Heo 18805594639aSTejun Heo if (ahci_broken_online(pdev)) { 18815594639aSTejun Heo hpriv->flags |= AHCI_HFLAG_SRST_TOUT_IS_OFFLINE; 18825594639aSTejun Heo dev_info(&pdev->dev, 18835594639aSTejun Heo "online status unreliable, applying workaround\n"); 18845594639aSTejun Heo } 18855594639aSTejun Heo 18868bfd1743SSui Chen 18878bfd1743SSui Chen /* Acer SA5-271 workaround modifies private_data */ 18888bfd1743SSui Chen acer_sa5_271_workaround(hpriv, pdev); 18898bfd1743SSui Chen 1890837f5f8fSTejun Heo /* CAP.NP sometimes indicate the index of the last enabled 1891837f5f8fSTejun Heo * port, at other times, that of the last possible port, so 1892837f5f8fSTejun Heo * determining the maximum port number requires looking at 1893837f5f8fSTejun Heo * both CAP.NP and port_map. 1894837f5f8fSTejun Heo */ 1895837f5f8fSTejun Heo n_ports = max(ahci_nr_ports(hpriv->cap), fls(hpriv->port_map)); 1896837f5f8fSTejun Heo 1897837f5f8fSTejun Heo host = ata_host_alloc_pinfo(&pdev->dev, ppi, n_ports); 18984447d351STejun Heo if (!host) 18994447d351STejun Heo return -ENOMEM; 19004447d351STejun Heo host->private_data = hpriv; 19010b9e2988SChristoph Hellwig 19020b9e2988SChristoph Hellwig if (ahci_init_msi(pdev, n_ports, hpriv) < 0) { 19030b9e2988SChristoph Hellwig /* legacy intx interrupts */ 19040b9e2988SChristoph Hellwig pci_intx(pdev, 1); 19050b9e2988SChristoph Hellwig } 19060ce57f8aSChristoph Hellwig hpriv->irq = pci_irq_vector(pdev, 0); 190721bfd1aaSRobert Richter 1908f3d7f23fSArjan van de Ven if (!(hpriv->cap & HOST_CAP_SSS) || ahci_ignore_sss) 1909886ad09fSArjan van de Ven host->flags |= ATA_HOST_PARALLEL_SCAN; 1910f3d7f23fSArjan van de Ven else 1911d2782d96SJingoo Han dev_info(&pdev->dev, "SSS flag set, parallel bus scan disabled\n"); 1912886ad09fSArjan van de Ven 191324e0e61dSNiklas Cassel if (!(hpriv->cap & HOST_CAP_PART)) 191424e0e61dSNiklas Cassel host->flags |= ATA_HOST_NO_PART; 191524e0e61dSNiklas Cassel 191624e0e61dSNiklas Cassel if (!(hpriv->cap & HOST_CAP_SSC)) 191724e0e61dSNiklas Cassel host->flags |= ATA_HOST_NO_SSC; 191824e0e61dSNiklas Cassel 191924e0e61dSNiklas Cassel if (!(hpriv->cap2 & HOST_CAP2_SDS)) 192024e0e61dSNiklas Cassel host->flags |= ATA_HOST_NO_DEVSLP; 192124e0e61dSNiklas Cassel 192218f7ba4cSKristen Carlson Accardi if (pi.flags & ATA_FLAG_EM) 192318f7ba4cSKristen Carlson Accardi ahci_reset_em(host); 192418f7ba4cSKristen Carlson Accardi 19254447d351STejun Heo for (i = 0; i < host->n_ports; i++) { 19264447d351STejun Heo struct ata_port *ap = host->ports[i]; 19274447d351STejun Heo 1928318893e1SAlessandro Rubini ata_port_pbar_desc(ap, ahci_pci_bar, -1, "abar"); 1929318893e1SAlessandro Rubini ata_port_pbar_desc(ap, ahci_pci_bar, 1930cbcdd875STejun Heo 0x100 + ap->port_no * 0x80, "port"); 1931cbcdd875STejun Heo 193218f7ba4cSKristen Carlson Accardi /* set enclosure management message type */ 193318f7ba4cSKristen Carlson Accardi if (ap->flags & ATA_FLAG_EM) 1934008dbd61SHarry Zhang ap->em_message_type = hpriv->em_msg_type; 193518f7ba4cSKristen Carlson Accardi 1936b1a9585cSSrinivas Pandruvada ahci_update_initial_lpm_policy(ap, hpriv); 193718f7ba4cSKristen Carlson Accardi 1938dab632e8SJeff Garzik /* disabled/not-implemented port */ 1939350756f6STejun Heo if (!(hpriv->port_map & (1 << i))) 1940dab632e8SJeff Garzik ap->ops = &ata_dummy_port_ops; 19414447d351STejun Heo } 1942c6fd2807SJeff Garzik 1943edc93052STejun Heo /* apply workaround for ASUS P5W DH Deluxe mainboard */ 1944edc93052STejun Heo ahci_p5wdh_workaround(host); 1945edc93052STejun Heo 1946f80ae7e4STejun Heo /* apply gtf filter quirk */ 1947f80ae7e4STejun Heo ahci_gtf_filter_workaround(host); 1948f80ae7e4STejun Heo 1949c6fd2807SJeff Garzik /* initialize adapter */ 1950b0dd4d7aSLennert Buytenhek rc = ahci_configure_dma_masks(pdev, hpriv); 1951c6fd2807SJeff Garzik if (rc) 195224dc5f33STejun Heo return rc; 1953c6fd2807SJeff Garzik 195437e14e4fSAdam Vodopjan rc = ahci_pci_reset_controller(host); 19554447d351STejun Heo if (rc) 19564447d351STejun Heo return rc; 1957c6fd2807SJeff Garzik 1958781d6550SAnton Vorontsov ahci_pci_init_controller(host); 1959439fcaecSAnton Vorontsov ahci_pci_print_info(host); 1960c6fd2807SJeff Garzik 19614447d351STejun Heo pci_set_master(pdev); 19625ca72c4fSAlexander Gordeev 196302e53293SMika Westerberg rc = ahci_host_activate(host, &ahci_sht); 196402e53293SMika Westerberg if (rc) 196502e53293SMika Westerberg return rc; 196602e53293SMika Westerberg 196702e53293SMika Westerberg pm_runtime_put_noidle(&pdev->dev); 196802e53293SMika Westerberg return 0; 196902e53293SMika Westerberg } 197002e53293SMika Westerberg 197110a663a1SPrabhakar Kushwaha static void ahci_shutdown_one(struct pci_dev *pdev) 197210a663a1SPrabhakar Kushwaha { 197310a663a1SPrabhakar Kushwaha ata_pci_shutdown_one(pdev); 197410a663a1SPrabhakar Kushwaha } 197510a663a1SPrabhakar Kushwaha 197602e53293SMika Westerberg static void ahci_remove_one(struct pci_dev *pdev) 197702e53293SMika Westerberg { 1978894fba7fSKai-Heng Feng sysfs_remove_file_from_group(&pdev->dev.kobj, 1979894fba7fSKai-Heng Feng &dev_attr_remapped_nvme.attr, 1980894fba7fSKai-Heng Feng NULL); 198102e53293SMika Westerberg pm_runtime_get_noresume(&pdev->dev); 198202e53293SMika Westerberg ata_pci_remove_one(pdev); 1983c6fd2807SJeff Garzik } 1984c6fd2807SJeff Garzik 19852fc75da0SAxel Lin module_pci_driver(ahci_pci_driver); 1986c6fd2807SJeff Garzik 1987c6fd2807SJeff Garzik MODULE_AUTHOR("Jeff Garzik"); 1988c6fd2807SJeff Garzik MODULE_DESCRIPTION("AHCI SATA low-level driver"); 1989c6fd2807SJeff Garzik MODULE_LICENSE("GPL"); 1990c6fd2807SJeff Garzik MODULE_DEVICE_TABLE(pci, ahci_pci_tbl); 1991c6fd2807SJeff Garzik MODULE_VERSION(DRV_VERSION); 1992