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 */ 608f6e4aca0SLennert Buytenhek { PCI_VDEVICE(ASMEDIA, 0x0601), board_ahci_43bit_dma }, /* ASM1060 */ 609f6e4aca0SLennert Buytenhek { PCI_VDEVICE(ASMEDIA, 0x0602), board_ahci_43bit_dma }, /* ASM1060 */ 610b0dd4d7aSLennert Buytenhek { PCI_VDEVICE(ASMEDIA, 0x0611), board_ahci_43bit_dma }, /* ASM1061 */ 611b0dd4d7aSLennert Buytenhek { PCI_VDEVICE(ASMEDIA, 0x0612), board_ahci_43bit_dma }, /* ASM1061/1062 */ 612f6e4aca0SLennert Buytenhek { PCI_VDEVICE(ASMEDIA, 0x0621), board_ahci_43bit_dma }, /* ASM1061R */ 613f6e4aca0SLennert Buytenhek { PCI_VDEVICE(ASMEDIA, 0x0622), board_ahci_43bit_dma }, /* ASM1062R */ 614f6e4aca0SLennert Buytenhek { PCI_VDEVICE(ASMEDIA, 0x0624), board_ahci_43bit_dma }, /* ASM1062+JMB575 */ 6151f9b7a5dSSzuying Chen { PCI_VDEVICE(ASMEDIA, 0x1062), board_ahci }, /* ASM1062A */ 6161f9b7a5dSSzuying Chen { PCI_VDEVICE(ASMEDIA, 0x1064), board_ahci }, /* ASM1064 */ 6171f9b7a5dSSzuying Chen { PCI_VDEVICE(ASMEDIA, 0x1164), board_ahci }, /* ASM1164 */ 6181f9b7a5dSSzuying Chen { PCI_VDEVICE(ASMEDIA, 0x1165), board_ahci }, /* ASM1165 */ 6191f9b7a5dSSzuying 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 { 673394d6e53SAnton Vorontsov if (pdev->vendor == PCI_VENDOR_ID_JMICRON && pdev->device == 0x2361) { 674394d6e53SAnton Vorontsov dev_info(&pdev->dev, "JMB361 has only one port\n"); 67588589772SSerge Semin hpriv->saved_port_map = 1; 676394d6e53SAnton Vorontsov } 677394d6e53SAnton Vorontsov 678394d6e53SAnton Vorontsov /* 679394d6e53SAnton Vorontsov * Temporary Marvell 6145 hack: PATA port presence 680394d6e53SAnton Vorontsov * is asserted through the standard AHCI port 681394d6e53SAnton Vorontsov * presence register, as bit 4 (counting from 0) 682394d6e53SAnton Vorontsov */ 683394d6e53SAnton Vorontsov if (hpriv->flags & AHCI_HFLAG_MV_PATA) { 684394d6e53SAnton Vorontsov if (pdev->device == 0x6121) 6859a23c1d6SAntoine Tenart hpriv->mask_port_map = 0x3; 686394d6e53SAnton Vorontsov else 6879a23c1d6SAntoine Tenart hpriv->mask_port_map = 0xf; 688394d6e53SAnton Vorontsov dev_info(&pdev->dev, 689394d6e53SAnton Vorontsov "Disabling your PATA port. Use the boot option 'ahci.marvell_enable=0' to avoid this.\n"); 690394d6e53SAnton Vorontsov } 691394d6e53SAnton Vorontsov 692725c7b57SAntoine Ténart ahci_save_initial_config(&pdev->dev, hpriv); 693394d6e53SAnton Vorontsov } 694394d6e53SAnton Vorontsov 69537e14e4fSAdam Vodopjan static int ahci_pci_reset_controller(struct ata_host *host) 69637e14e4fSAdam Vodopjan { 69737e14e4fSAdam Vodopjan struct pci_dev *pdev = to_pci_dev(host->dev); 69837e14e4fSAdam Vodopjan struct ahci_host_priv *hpriv = host->private_data; 69937e14e4fSAdam Vodopjan int rc; 70037e14e4fSAdam Vodopjan 70137e14e4fSAdam Vodopjan rc = ahci_reset_controller(host); 70237e14e4fSAdam Vodopjan if (rc) 70337e14e4fSAdam Vodopjan return rc; 70437e14e4fSAdam Vodopjan 70537e14e4fSAdam Vodopjan /* 70637e14e4fSAdam Vodopjan * If platform firmware failed to enable ports, try to enable 70737e14e4fSAdam Vodopjan * them here. 70837e14e4fSAdam Vodopjan */ 70937e14e4fSAdam Vodopjan ahci_intel_pcs_quirk(pdev, hpriv); 71037e14e4fSAdam Vodopjan 71137e14e4fSAdam Vodopjan return 0; 71237e14e4fSAdam Vodopjan } 71337e14e4fSAdam Vodopjan 714781d6550SAnton Vorontsov static void ahci_pci_init_controller(struct ata_host *host) 715781d6550SAnton Vorontsov { 716781d6550SAnton Vorontsov struct ahci_host_priv *hpriv = host->private_data; 717781d6550SAnton Vorontsov struct pci_dev *pdev = to_pci_dev(host->dev); 718781d6550SAnton Vorontsov void __iomem *port_mmio; 719781d6550SAnton Vorontsov u32 tmp; 720c40e7cb8SJose Alberto Reguero int mv; 7212bcd866bSJeff Garzik 722417a1a6dSTejun Heo if (hpriv->flags & AHCI_HFLAG_MV_PATA) { 723c40e7cb8SJose Alberto Reguero if (pdev->device == 0x6121) 724c40e7cb8SJose Alberto Reguero mv = 2; 725c40e7cb8SJose Alberto Reguero else 726c40e7cb8SJose Alberto Reguero mv = 4; 7277cbbfbe0SSerge Semin port_mmio = __ahci_port_base(hpriv, mv); 728cd70c266SJeff Garzik 729cd70c266SJeff Garzik writel(0, port_mmio + PORT_IRQ_MASK); 730cd70c266SJeff Garzik 731cd70c266SJeff Garzik /* clear port IRQ */ 732cd70c266SJeff Garzik tmp = readl(port_mmio + PORT_IRQ_STAT); 73393c77114SHannes Reinecke dev_dbg(&pdev->dev, "PORT_IRQ_STAT 0x%x\n", tmp); 734cd70c266SJeff Garzik if (tmp) 735cd70c266SJeff Garzik writel(tmp, port_mmio + PORT_IRQ_STAT); 736cd70c266SJeff Garzik } 737cd70c266SJeff Garzik 738781d6550SAnton Vorontsov ahci_init_controller(host); 739c6fd2807SJeff Garzik } 740c6fd2807SJeff Garzik 741cc0680a5STejun Heo static int ahci_vt8251_hardreset(struct ata_link *link, unsigned int *class, 742d4b2bab4STejun Heo unsigned long deadline) 743ad616ffbSTejun Heo { 744cc0680a5STejun Heo struct ata_port *ap = link->ap; 745039ece38SHans de Goede struct ahci_host_priv *hpriv = ap->host->private_data; 7469dadd45bSTejun Heo bool online; 747ad616ffbSTejun Heo int rc; 748ad616ffbSTejun Heo 749fa89f53bSEvan Wang hpriv->stop_engine(ap); 750ad616ffbSTejun Heo 751cc0680a5STejun Heo rc = sata_link_hardreset(link, sata_ehc_deb_timing(&link->eh_context), 7529dadd45bSTejun Heo deadline, &online, NULL); 753ad616ffbSTejun Heo 754039ece38SHans de Goede hpriv->start_engine(ap); 755ad616ffbSTejun Heo 756ad616ffbSTejun Heo /* vt8251 doesn't clear BSY on signature FIS reception, 757ad616ffbSTejun Heo * request follow-up softreset. 758ad616ffbSTejun Heo */ 7599dadd45bSTejun Heo return online ? -EAGAIN : rc; 760ad616ffbSTejun Heo } 761ad616ffbSTejun Heo 762edc93052STejun Heo static int ahci_p5wdh_hardreset(struct ata_link *link, unsigned int *class, 763edc93052STejun Heo unsigned long deadline) 764edc93052STejun Heo { 765edc93052STejun Heo struct ata_port *ap = link->ap; 766edc93052STejun Heo struct ahci_port_priv *pp = ap->private_data; 767039ece38SHans de Goede struct ahci_host_priv *hpriv = ap->host->private_data; 768edc93052STejun Heo u8 *d2h_fis = pp->rx_fis + RX_FIS_D2H_REG; 769edc93052STejun Heo struct ata_taskfile tf; 7709dadd45bSTejun Heo bool online; 771edc93052STejun Heo int rc; 772edc93052STejun Heo 773fa89f53bSEvan Wang hpriv->stop_engine(ap); 774edc93052STejun Heo 775edc93052STejun Heo /* clear D2H reception area to properly wait for D2H FIS */ 776edc93052STejun Heo ata_tf_init(link->device, &tf); 777efcef265SSergey Shtylyov tf.status = ATA_BUSY; 778edc93052STejun Heo ata_tf_to_fis(&tf, 0, 0, d2h_fis); 779edc93052STejun Heo 780edc93052STejun Heo rc = sata_link_hardreset(link, sata_ehc_deb_timing(&link->eh_context), 7819dadd45bSTejun Heo deadline, &online, NULL); 782edc93052STejun Heo 783039ece38SHans de Goede hpriv->start_engine(ap); 784edc93052STejun Heo 785edc93052STejun Heo /* The pseudo configuration device on SIMG4726 attached to 786edc93052STejun Heo * ASUS P5W-DH Deluxe doesn't send signature FIS after 787edc93052STejun Heo * hardreset if no device is attached to the first downstream 788edc93052STejun Heo * port && the pseudo device locks up on SRST w/ PMP==0. To 789edc93052STejun Heo * work around this, wait for !BSY only briefly. If BSY isn't 790edc93052STejun Heo * cleared, perform CLO and proceed to IDENTIFY (achieved by 791edc93052STejun Heo * ATA_LFLAG_NO_SRST and ATA_LFLAG_ASSUME_ATA). 792edc93052STejun Heo * 793edc93052STejun Heo * Wait for two seconds. Devices attached to downstream port 794edc93052STejun Heo * which can't process the following IDENTIFY after this will 795edc93052STejun Heo * have to be reset again. For most cases, this should 796edc93052STejun Heo * suffice while making probing snappish enough. 797edc93052STejun Heo */ 7989dadd45bSTejun Heo if (online) { 7999dadd45bSTejun Heo rc = ata_wait_after_reset(link, jiffies + 2 * HZ, 8009dadd45bSTejun Heo ahci_check_ready); 801edc93052STejun Heo if (rc) 80278d5ae39SShane Huang ahci_kick_engine(ap); 8039dadd45bSTejun Heo } 8049dadd45bSTejun Heo return rc; 805edc93052STejun Heo } 806edc93052STejun Heo 807dbfe8ef5SDan Williams /* 808dbfe8ef5SDan Williams * ahci_avn_hardreset - attempt more aggressive recovery of Avoton ports. 809dbfe8ef5SDan Williams * 810dbfe8ef5SDan Williams * It has been observed with some SSDs that the timing of events in the 811dbfe8ef5SDan Williams * link synchronization phase can leave the port in a state that can not 812dbfe8ef5SDan Williams * be recovered by a SATA-hard-reset alone. The failing signature is 813dbfe8ef5SDan Williams * SStatus.DET stuck at 1 ("Device presence detected but Phy 814dbfe8ef5SDan Williams * communication not established"). It was found that unloading and 815dbfe8ef5SDan Williams * reloading the driver when this problem occurs allows the drive 816dbfe8ef5SDan Williams * connection to be recovered (DET advanced to 0x3). The critical 817dbfe8ef5SDan Williams * component of reloading the driver is that the port state machines are 818dbfe8ef5SDan Williams * reset by bouncing "port enable" in the AHCI PCS configuration 819dbfe8ef5SDan Williams * register. So, reproduce that effect by bouncing a port whenever we 820dbfe8ef5SDan Williams * see DET==1 after a reset. 821dbfe8ef5SDan Williams */ 822dbfe8ef5SDan Williams static int ahci_avn_hardreset(struct ata_link *link, unsigned int *class, 823dbfe8ef5SDan Williams unsigned long deadline) 824dbfe8ef5SDan Williams { 825d14d41ccSSergey Shtylyov const unsigned int *timing = sata_ehc_deb_timing(&link->eh_context); 826dbfe8ef5SDan Williams struct ata_port *ap = link->ap; 827dbfe8ef5SDan Williams struct ahci_port_priv *pp = ap->private_data; 828dbfe8ef5SDan Williams struct ahci_host_priv *hpriv = ap->host->private_data; 829dbfe8ef5SDan Williams u8 *d2h_fis = pp->rx_fis + RX_FIS_D2H_REG; 830dbfe8ef5SDan Williams unsigned long tmo = deadline - jiffies; 831dbfe8ef5SDan Williams struct ata_taskfile tf; 832dbfe8ef5SDan Williams bool online; 833dbfe8ef5SDan Williams int rc, i; 834dbfe8ef5SDan Williams 835fa89f53bSEvan Wang hpriv->stop_engine(ap); 836dbfe8ef5SDan Williams 837dbfe8ef5SDan Williams for (i = 0; i < 2; i++) { 838dbfe8ef5SDan Williams u16 val; 839dbfe8ef5SDan Williams u32 sstatus; 840dbfe8ef5SDan Williams int port = ap->port_no; 841dbfe8ef5SDan Williams struct ata_host *host = ap->host; 842dbfe8ef5SDan Williams struct pci_dev *pdev = to_pci_dev(host->dev); 843dbfe8ef5SDan Williams 844dbfe8ef5SDan Williams /* clear D2H reception area to properly wait for D2H FIS */ 845dbfe8ef5SDan Williams ata_tf_init(link->device, &tf); 846efcef265SSergey Shtylyov tf.status = ATA_BUSY; 847dbfe8ef5SDan Williams ata_tf_to_fis(&tf, 0, 0, d2h_fis); 848dbfe8ef5SDan Williams 849dbfe8ef5SDan Williams rc = sata_link_hardreset(link, timing, deadline, &online, 850dbfe8ef5SDan Williams ahci_check_ready); 851dbfe8ef5SDan Williams 852dbfe8ef5SDan Williams if (sata_scr_read(link, SCR_STATUS, &sstatus) != 0 || 853dbfe8ef5SDan Williams (sstatus & 0xf) != 1) 854dbfe8ef5SDan Williams break; 855dbfe8ef5SDan Williams 856e276c9bdSXu Wang ata_link_info(link, "avn bounce port%d\n", port); 857dbfe8ef5SDan Williams 858dbfe8ef5SDan Williams pci_read_config_word(pdev, 0x92, &val); 859dbfe8ef5SDan Williams val &= ~(1 << port); 860dbfe8ef5SDan Williams pci_write_config_word(pdev, 0x92, val); 861dbfe8ef5SDan Williams ata_msleep(ap, 1000); 862dbfe8ef5SDan Williams val |= 1 << port; 863dbfe8ef5SDan Williams pci_write_config_word(pdev, 0x92, val); 864dbfe8ef5SDan Williams deadline += tmo; 865dbfe8ef5SDan Williams } 866dbfe8ef5SDan Williams 867dbfe8ef5SDan Williams hpriv->start_engine(ap); 868dbfe8ef5SDan Williams 869dbfe8ef5SDan Williams if (online) 870dbfe8ef5SDan Williams *class = ahci_dev_classify(ap); 871dbfe8ef5SDan Williams 872dbfe8ef5SDan Williams return rc; 873dbfe8ef5SDan Williams } 874dbfe8ef5SDan Williams 875dbfe8ef5SDan Williams 87602e53293SMika Westerberg #ifdef CONFIG_PM 87702e53293SMika Westerberg static void ahci_pci_disable_interrupts(struct ata_host *host) 878c6fd2807SJeff Garzik { 8799b10ae86STejun Heo struct ahci_host_priv *hpriv = host->private_data; 880d8993349SAnton Vorontsov void __iomem *mmio = hpriv->mmio; 881c6fd2807SJeff Garzik u32 ctl; 882c6fd2807SJeff Garzik 883c6fd2807SJeff Garzik /* AHCI spec rev1.1 section 8.3.3: 884c6fd2807SJeff Garzik * Software must disable interrupts prior to requesting a 885c6fd2807SJeff Garzik * transition of the HBA to D3 state. 886c6fd2807SJeff Garzik */ 887c6fd2807SJeff Garzik ctl = readl(mmio + HOST_CTL); 888c6fd2807SJeff Garzik ctl &= ~HOST_IRQ_EN; 889c6fd2807SJeff Garzik writel(ctl, mmio + HOST_CTL); 890c6fd2807SJeff Garzik readl(mmio + HOST_CTL); /* flush */ 89102e53293SMika Westerberg } 892f1d848f9SMika Westerberg 89302e53293SMika Westerberg static int ahci_pci_device_runtime_suspend(struct device *dev) 89402e53293SMika Westerberg { 89502e53293SMika Westerberg struct pci_dev *pdev = to_pci_dev(dev); 89602e53293SMika Westerberg struct ata_host *host = pci_get_drvdata(pdev); 89702e53293SMika Westerberg 89802e53293SMika Westerberg ahci_pci_disable_interrupts(host); 89902e53293SMika Westerberg return 0; 90002e53293SMika Westerberg } 90102e53293SMika Westerberg 90202e53293SMika Westerberg static int ahci_pci_device_runtime_resume(struct device *dev) 90302e53293SMika Westerberg { 90402e53293SMika Westerberg struct pci_dev *pdev = to_pci_dev(dev); 90502e53293SMika Westerberg struct ata_host *host = pci_get_drvdata(pdev); 90602e53293SMika Westerberg int rc; 90702e53293SMika Westerberg 90837e14e4fSAdam Vodopjan rc = ahci_pci_reset_controller(host); 90902e53293SMika Westerberg if (rc) 91002e53293SMika Westerberg return rc; 91102e53293SMika Westerberg ahci_pci_init_controller(host); 91202e53293SMika Westerberg return 0; 91302e53293SMika Westerberg } 91402e53293SMika Westerberg 91502e53293SMika Westerberg #ifdef CONFIG_PM_SLEEP 91602e53293SMika Westerberg static int ahci_pci_device_suspend(struct device *dev) 91702e53293SMika Westerberg { 91802e53293SMika Westerberg struct pci_dev *pdev = to_pci_dev(dev); 91902e53293SMika Westerberg struct ata_host *host = pci_get_drvdata(pdev); 92002e53293SMika Westerberg struct ahci_host_priv *hpriv = host->private_data; 92102e53293SMika Westerberg 92202e53293SMika Westerberg if (hpriv->flags & AHCI_HFLAG_NO_SUSPEND) { 92302e53293SMika Westerberg dev_err(&pdev->dev, 92402e53293SMika Westerberg "BIOS update required for suspend/resume\n"); 92502e53293SMika Westerberg return -EIO; 92602e53293SMika Westerberg } 92702e53293SMika Westerberg 92802e53293SMika Westerberg ahci_pci_disable_interrupts(host); 929ec87cf37SSergey Shtylyov ata_host_suspend(host, PMSG_SUSPEND); 930ec87cf37SSergey Shtylyov return 0; 931c6fd2807SJeff Garzik } 932c6fd2807SJeff Garzik 933f1d848f9SMika Westerberg static int ahci_pci_device_resume(struct device *dev) 934c6fd2807SJeff Garzik { 935f1d848f9SMika Westerberg struct pci_dev *pdev = to_pci_dev(dev); 9360a86e1c8SJingoo Han struct ata_host *host = pci_get_drvdata(pdev); 937c6fd2807SJeff Garzik int rc; 938c6fd2807SJeff Garzik 939cb85696dSJames Laird /* Apple BIOS helpfully mangles the registers on resume */ 940cb85696dSJames Laird if (is_mcp89_apple(pdev)) 941cb85696dSJames Laird ahci_mcp89_apple_enable(pdev); 942cb85696dSJames Laird 943c6fd2807SJeff Garzik if (pdev->dev.power.power_state.event == PM_EVENT_SUSPEND) { 94437e14e4fSAdam Vodopjan rc = ahci_pci_reset_controller(host); 945c6fd2807SJeff Garzik if (rc) 946c6fd2807SJeff Garzik return rc; 947c6fd2807SJeff Garzik 948781d6550SAnton Vorontsov ahci_pci_init_controller(host); 949c6fd2807SJeff Garzik } 950c6fd2807SJeff Garzik 951cca3974eSJeff Garzik ata_host_resume(host); 952c6fd2807SJeff Garzik 953c6fd2807SJeff Garzik return 0; 954c6fd2807SJeff Garzik } 955438ac6d5STejun Heo #endif 956c6fd2807SJeff Garzik 95702e53293SMika Westerberg #endif /* CONFIG_PM */ 95802e53293SMika Westerberg 959b0dd4d7aSLennert Buytenhek static int ahci_configure_dma_masks(struct pci_dev *pdev, 960b0dd4d7aSLennert Buytenhek struct ahci_host_priv *hpriv) 961c6fd2807SJeff Garzik { 962b0dd4d7aSLennert Buytenhek int dma_bits; 963c6fd2807SJeff Garzik int rc; 964c6fd2807SJeff Garzik 965b0dd4d7aSLennert Buytenhek if (hpriv->cap & HOST_CAP_64) { 966b0dd4d7aSLennert Buytenhek dma_bits = 64; 967b0dd4d7aSLennert Buytenhek if (hpriv->flags & AHCI_HFLAG_43BIT_ONLY) 968b0dd4d7aSLennert Buytenhek dma_bits = 43; 969b0dd4d7aSLennert Buytenhek } else { 970b0dd4d7aSLennert Buytenhek dma_bits = 32; 971b0dd4d7aSLennert Buytenhek } 972b0dd4d7aSLennert Buytenhek 973318893e1SAlessandro Rubini /* 974318893e1SAlessandro Rubini * If the device fixup already set the dma_mask to some non-standard 975318893e1SAlessandro Rubini * value, don't extend it here. This happens on STA2X11, for example. 976b1716871SChristoph Hellwig * 977b1716871SChristoph Hellwig * XXX: manipulating the DMA mask from platform code is completely 978a7ba70f1SNicolas Saenz Julienne * bogus, platform code should use dev->bus_dma_limit instead.. 979318893e1SAlessandro Rubini */ 980318893e1SAlessandro Rubini if (pdev->dma_mask && pdev->dma_mask < DMA_BIT_MASK(32)) 981318893e1SAlessandro Rubini return 0; 982318893e1SAlessandro Rubini 983b1716871SChristoph Hellwig rc = dma_set_mask_and_coherent(&pdev->dev, DMA_BIT_MASK(dma_bits)); 984b1716871SChristoph Hellwig if (rc) 985b1716871SChristoph Hellwig dev_err(&pdev->dev, "DMA enable failed\n"); 986c6fd2807SJeff Garzik return rc; 987c6fd2807SJeff Garzik } 988c6fd2807SJeff Garzik 989439fcaecSAnton Vorontsov static void ahci_pci_print_info(struct ata_host *host) 990439fcaecSAnton Vorontsov { 991439fcaecSAnton Vorontsov struct pci_dev *pdev = to_pci_dev(host->dev); 992439fcaecSAnton Vorontsov u16 cc; 993439fcaecSAnton Vorontsov const char *scc_s; 994439fcaecSAnton Vorontsov 995439fcaecSAnton Vorontsov pci_read_config_word(pdev, 0x0a, &cc); 996439fcaecSAnton Vorontsov if (cc == PCI_CLASS_STORAGE_IDE) 997439fcaecSAnton Vorontsov scc_s = "IDE"; 998439fcaecSAnton Vorontsov else if (cc == PCI_CLASS_STORAGE_SATA) 999439fcaecSAnton Vorontsov scc_s = "SATA"; 1000439fcaecSAnton Vorontsov else if (cc == PCI_CLASS_STORAGE_RAID) 1001439fcaecSAnton Vorontsov scc_s = "RAID"; 1002439fcaecSAnton Vorontsov else 1003439fcaecSAnton Vorontsov scc_s = "unknown"; 1004439fcaecSAnton Vorontsov 1005439fcaecSAnton Vorontsov ahci_print_info(host, scc_s); 1006439fcaecSAnton Vorontsov } 1007439fcaecSAnton Vorontsov 1008edc93052STejun Heo /* On ASUS P5W DH Deluxe, the second port of PCI device 00:1f.2 is 1009edc93052STejun Heo * hardwired to on-board SIMG 4726. The chipset is ICH8 and doesn't 1010edc93052STejun Heo * support PMP and the 4726 either directly exports the device 1011edc93052STejun Heo * attached to the first downstream port or acts as a hardware storage 1012edc93052STejun Heo * controller and emulate a single ATA device (can be RAID 0/1 or some 1013edc93052STejun Heo * other configuration). 1014edc93052STejun Heo * 1015edc93052STejun Heo * When there's no device attached to the first downstream port of the 1016edc93052STejun Heo * 4726, "Config Disk" appears, which is a pseudo ATA device to 1017edc93052STejun Heo * configure the 4726. However, ATA emulation of the device is very 1018edc93052STejun Heo * lame. It doesn't send signature D2H Reg FIS after the initial 1019edc93052STejun Heo * hardreset, pukes on SRST w/ PMP==0 and has bunch of other issues. 1020edc93052STejun Heo * 1021edc93052STejun Heo * The following function works around the problem by always using 1022edc93052STejun Heo * hardreset on the port and not depending on receiving signature FIS 1023edc93052STejun Heo * afterward. If signature FIS isn't received soon, ATA class is 1024edc93052STejun Heo * assumed without follow-up softreset. 1025edc93052STejun Heo */ 1026edc93052STejun Heo static void ahci_p5wdh_workaround(struct ata_host *host) 1027edc93052STejun Heo { 10281bd06867SMathias Krause static const struct dmi_system_id sysids[] = { 1029edc93052STejun Heo { 1030edc93052STejun Heo .ident = "P5W DH Deluxe", 1031edc93052STejun Heo .matches = { 1032edc93052STejun Heo DMI_MATCH(DMI_SYS_VENDOR, 1033edc93052STejun Heo "ASUSTEK COMPUTER INC"), 1034edc93052STejun Heo DMI_MATCH(DMI_PRODUCT_NAME, "P5W DH Deluxe"), 1035edc93052STejun Heo }, 1036edc93052STejun Heo }, 1037edc93052STejun Heo { } 1038edc93052STejun Heo }; 1039edc93052STejun Heo struct pci_dev *pdev = to_pci_dev(host->dev); 1040edc93052STejun Heo 1041edc93052STejun Heo if (pdev->bus->number == 0 && pdev->devfn == PCI_DEVFN(0x1f, 2) && 1042edc93052STejun Heo dmi_check_system(sysids)) { 1043edc93052STejun Heo struct ata_port *ap = host->ports[1]; 1044edc93052STejun Heo 1045a44fec1fSJoe Perches dev_info(&pdev->dev, 1046a44fec1fSJoe Perches "enabling ASUS P5W DH Deluxe on-board SIMG4726 workaround\n"); 1047edc93052STejun Heo 1048edc93052STejun Heo ap->ops = &ahci_p5wdh_ops; 1049edc93052STejun Heo ap->link.flags |= ATA_LFLAG_NO_SRST | ATA_LFLAG_ASSUME_ATA; 1050edc93052STejun Heo } 1051edc93052STejun Heo } 1052edc93052STejun Heo 1053cb85696dSJames Laird /* 1054cb85696dSJames Laird * Macbook7,1 firmware forcibly disables MCP89 AHCI and changes PCI ID when 1055cb85696dSJames Laird * booting in BIOS compatibility mode. We restore the registers but not ID. 1056cb85696dSJames Laird */ 1057cb85696dSJames Laird static void ahci_mcp89_apple_enable(struct pci_dev *pdev) 1058cb85696dSJames Laird { 1059cb85696dSJames Laird u32 val; 1060cb85696dSJames Laird 1061cb85696dSJames Laird printk(KERN_INFO "ahci: enabling MCP89 AHCI mode\n"); 1062cb85696dSJames Laird 1063cb85696dSJames Laird pci_read_config_dword(pdev, 0xf8, &val); 1064cb85696dSJames Laird val |= 1 << 0x1b; 1065cb85696dSJames Laird /* the following changes the device ID, but appears not to affect function */ 1066cb85696dSJames Laird /* val = (val & ~0xf0000000) | 0x80000000; */ 1067cb85696dSJames Laird pci_write_config_dword(pdev, 0xf8, val); 1068cb85696dSJames Laird 1069cb85696dSJames Laird pci_read_config_dword(pdev, 0x54c, &val); 1070cb85696dSJames Laird val |= 1 << 0xc; 1071cb85696dSJames Laird pci_write_config_dword(pdev, 0x54c, val); 1072cb85696dSJames Laird 1073cb85696dSJames Laird pci_read_config_dword(pdev, 0x4a4, &val); 1074cb85696dSJames Laird val &= 0xff; 1075cb85696dSJames Laird val |= 0x01060100; 1076cb85696dSJames Laird pci_write_config_dword(pdev, 0x4a4, val); 1077cb85696dSJames Laird 1078cb85696dSJames Laird pci_read_config_dword(pdev, 0x54c, &val); 1079cb85696dSJames Laird val &= ~(1 << 0xc); 1080cb85696dSJames Laird pci_write_config_dword(pdev, 0x54c, val); 1081cb85696dSJames Laird 1082cb85696dSJames Laird pci_read_config_dword(pdev, 0xf8, &val); 1083cb85696dSJames Laird val &= ~(1 << 0x1b); 1084cb85696dSJames Laird pci_write_config_dword(pdev, 0xf8, val); 1085cb85696dSJames Laird } 1086cb85696dSJames Laird 1087cb85696dSJames Laird static bool is_mcp89_apple(struct pci_dev *pdev) 1088cb85696dSJames Laird { 1089cb85696dSJames Laird return pdev->vendor == PCI_VENDOR_ID_NVIDIA && 1090cb85696dSJames Laird pdev->device == PCI_DEVICE_ID_NVIDIA_NFORCE_MCP89_SATA && 1091cb85696dSJames Laird pdev->subsystem_vendor == PCI_VENDOR_ID_APPLE && 1092cb85696dSJames Laird pdev->subsystem_device == 0xcb89; 1093cb85696dSJames Laird } 1094cb85696dSJames Laird 10952fcad9d2STejun Heo /* only some SB600 ahci controllers can do 64bit DMA */ 10962fcad9d2STejun Heo static bool ahci_sb600_enable_64bit(struct pci_dev *pdev) 109758a09b38SShane Huang { 109858a09b38SShane Huang static const struct dmi_system_id sysids[] = { 109903d783bfSTejun Heo /* 110003d783bfSTejun Heo * The oldest version known to be broken is 0901 and 110103d783bfSTejun Heo * working is 1501 which was released on 2007-10-26. 11022fcad9d2STejun Heo * Enable 64bit DMA on 1501 and anything newer. 11032fcad9d2STejun Heo * 110403d783bfSTejun Heo * Please read bko#9412 for more info. 110503d783bfSTejun Heo */ 110658a09b38SShane Huang { 110758a09b38SShane Huang .ident = "ASUS M2A-VM", 110858a09b38SShane Huang .matches = { 110958a09b38SShane Huang DMI_MATCH(DMI_BOARD_VENDOR, 111058a09b38SShane Huang "ASUSTeK Computer INC."), 111158a09b38SShane Huang DMI_MATCH(DMI_BOARD_NAME, "M2A-VM"), 111258a09b38SShane Huang }, 111303d783bfSTejun Heo .driver_data = "20071026", /* yyyymmdd */ 111458a09b38SShane Huang }, 1115e65cc194SMark Nelson /* 1116e65cc194SMark Nelson * All BIOS versions for the MSI K9A2 Platinum (MS-7376) 1117e65cc194SMark Nelson * support 64bit DMA. 1118e65cc194SMark Nelson * 1119e65cc194SMark Nelson * BIOS versions earlier than 1.5 had the Manufacturer DMI 1120e65cc194SMark Nelson * fields as "MICRO-STAR INTERANTIONAL CO.,LTD". 1121e65cc194SMark Nelson * This spelling mistake was fixed in BIOS version 1.5, so 1122e65cc194SMark Nelson * 1.5 and later have the Manufacturer as 1123e65cc194SMark Nelson * "MICRO-STAR INTERNATIONAL CO.,LTD". 1124e65cc194SMark Nelson * So try to match on DMI_BOARD_VENDOR of "MICRO-STAR INTER". 1125e65cc194SMark Nelson * 1126e65cc194SMark Nelson * BIOS versions earlier than 1.9 had a Board Product Name 1127e65cc194SMark Nelson * DMI field of "MS-7376". This was changed to be 1128e65cc194SMark Nelson * "K9A2 Platinum (MS-7376)" in version 1.9, but we can still 1129e65cc194SMark Nelson * match on DMI_BOARD_NAME of "MS-7376". 1130e65cc194SMark Nelson */ 1131e65cc194SMark Nelson { 1132e65cc194SMark Nelson .ident = "MSI K9A2 Platinum", 1133e65cc194SMark Nelson .matches = { 1134e65cc194SMark Nelson DMI_MATCH(DMI_BOARD_VENDOR, 1135e65cc194SMark Nelson "MICRO-STAR INTER"), 1136e65cc194SMark Nelson DMI_MATCH(DMI_BOARD_NAME, "MS-7376"), 1137e65cc194SMark Nelson }, 1138e65cc194SMark Nelson }, 11393c4aa91fSMark Nelson /* 1140ff0173c1SMark Nelson * All BIOS versions for the MSI K9AGM2 (MS-7327) support 1141ff0173c1SMark Nelson * 64bit DMA. 1142ff0173c1SMark Nelson * 1143ff0173c1SMark Nelson * This board also had the typo mentioned above in the 1144ff0173c1SMark Nelson * Manufacturer DMI field (fixed in BIOS version 1.5), so 1145ff0173c1SMark Nelson * match on DMI_BOARD_VENDOR of "MICRO-STAR INTER" again. 1146ff0173c1SMark Nelson */ 1147ff0173c1SMark Nelson { 1148ff0173c1SMark Nelson .ident = "MSI K9AGM2", 1149ff0173c1SMark Nelson .matches = { 1150ff0173c1SMark Nelson DMI_MATCH(DMI_BOARD_VENDOR, 1151ff0173c1SMark Nelson "MICRO-STAR INTER"), 1152ff0173c1SMark Nelson DMI_MATCH(DMI_BOARD_NAME, "MS-7327"), 1153ff0173c1SMark Nelson }, 1154ff0173c1SMark Nelson }, 1155ff0173c1SMark Nelson /* 11563c4aa91fSMark Nelson * All BIOS versions for the Asus M3A support 64bit DMA. 11573c4aa91fSMark Nelson * (all release versions from 0301 to 1206 were tested) 11583c4aa91fSMark Nelson */ 11593c4aa91fSMark Nelson { 11603c4aa91fSMark Nelson .ident = "ASUS M3A", 11613c4aa91fSMark Nelson .matches = { 11623c4aa91fSMark Nelson DMI_MATCH(DMI_BOARD_VENDOR, 11633c4aa91fSMark Nelson "ASUSTeK Computer INC."), 11643c4aa91fSMark Nelson DMI_MATCH(DMI_BOARD_NAME, "M3A"), 11653c4aa91fSMark Nelson }, 11663c4aa91fSMark Nelson }, 116758a09b38SShane Huang { } 116858a09b38SShane Huang }; 116903d783bfSTejun Heo const struct dmi_system_id *match; 11702fcad9d2STejun Heo int year, month, date; 11712fcad9d2STejun Heo char buf[9]; 117258a09b38SShane Huang 117303d783bfSTejun Heo match = dmi_first_match(sysids); 117458a09b38SShane Huang if (pdev->bus->number != 0 || pdev->devfn != PCI_DEVFN(0x12, 0) || 117503d783bfSTejun Heo !match) 117658a09b38SShane Huang return false; 117758a09b38SShane Huang 1178e65cc194SMark Nelson if (!match->driver_data) 1179e65cc194SMark Nelson goto enable_64bit; 1180e65cc194SMark Nelson 118103d783bfSTejun Heo dmi_get_date(DMI_BIOS_DATE, &year, &month, &date); 118203d783bfSTejun Heo snprintf(buf, sizeof(buf), "%04d%02d%02d", year, month, date); 118303d783bfSTejun Heo 1184e65cc194SMark Nelson if (strcmp(buf, match->driver_data) >= 0) 1185e65cc194SMark Nelson goto enable_64bit; 1186e65cc194SMark Nelson else { 1187a44fec1fSJoe Perches dev_warn(&pdev->dev, 1188a44fec1fSJoe Perches "%s: BIOS too old, forcing 32bit DMA, update BIOS\n", 1189a44fec1fSJoe Perches match->ident); 11902fcad9d2STejun Heo return false; 11912fcad9d2STejun Heo } 1192e65cc194SMark Nelson 1193e65cc194SMark Nelson enable_64bit: 1194a44fec1fSJoe Perches dev_warn(&pdev->dev, "%s: enabling 64bit DMA\n", match->ident); 1195e65cc194SMark Nelson return true; 119658a09b38SShane Huang } 119758a09b38SShane Huang 11981fd68434SRafael J. Wysocki static bool ahci_broken_system_poweroff(struct pci_dev *pdev) 11991fd68434SRafael J. Wysocki { 12001fd68434SRafael J. Wysocki static const struct dmi_system_id broken_systems[] = { 12011fd68434SRafael J. Wysocki { 12021fd68434SRafael J. Wysocki .ident = "HP Compaq nx6310", 12031fd68434SRafael J. Wysocki .matches = { 12041fd68434SRafael J. Wysocki DMI_MATCH(DMI_SYS_VENDOR, "Hewlett-Packard"), 12051fd68434SRafael J. Wysocki DMI_MATCH(DMI_PRODUCT_NAME, "HP Compaq nx6310"), 12061fd68434SRafael J. Wysocki }, 12071fd68434SRafael J. Wysocki /* PCI slot number of the controller */ 12081fd68434SRafael J. Wysocki .driver_data = (void *)0x1FUL, 12091fd68434SRafael J. Wysocki }, 1210d2f9c061SMaciej Rutecki { 1211d2f9c061SMaciej Rutecki .ident = "HP Compaq 6720s", 1212d2f9c061SMaciej Rutecki .matches = { 1213d2f9c061SMaciej Rutecki DMI_MATCH(DMI_SYS_VENDOR, "Hewlett-Packard"), 1214d2f9c061SMaciej Rutecki DMI_MATCH(DMI_PRODUCT_NAME, "HP Compaq 6720s"), 1215d2f9c061SMaciej Rutecki }, 1216d2f9c061SMaciej Rutecki /* PCI slot number of the controller */ 1217d2f9c061SMaciej Rutecki .driver_data = (void *)0x1FUL, 1218d2f9c061SMaciej Rutecki }, 12191fd68434SRafael J. Wysocki 12201fd68434SRafael J. Wysocki { } /* terminate list */ 12211fd68434SRafael J. Wysocki }; 12221fd68434SRafael J. Wysocki const struct dmi_system_id *dmi = dmi_first_match(broken_systems); 12231fd68434SRafael J. Wysocki 12241fd68434SRafael J. Wysocki if (dmi) { 12251fd68434SRafael J. Wysocki unsigned long slot = (unsigned long)dmi->driver_data; 12261fd68434SRafael J. Wysocki /* apply the quirk only to on-board controllers */ 12271fd68434SRafael J. Wysocki return slot == PCI_SLOT(pdev->devfn); 12281fd68434SRafael J. Wysocki } 12291fd68434SRafael J. Wysocki 12301fd68434SRafael J. Wysocki return false; 12311fd68434SRafael J. Wysocki } 12321fd68434SRafael J. Wysocki 12339b10ae86STejun Heo static bool ahci_broken_suspend(struct pci_dev *pdev) 12349b10ae86STejun Heo { 12359b10ae86STejun Heo static const struct dmi_system_id sysids[] = { 12369b10ae86STejun Heo /* 12379b10ae86STejun Heo * On HP dv[4-6] and HDX18 with earlier BIOSen, link 12389b10ae86STejun Heo * to the harddisk doesn't become online after 12399b10ae86STejun Heo * resuming from STR. Warn and fail suspend. 12409deb3431STejun Heo * 12419deb3431STejun Heo * http://bugzilla.kernel.org/show_bug.cgi?id=12276 12429deb3431STejun Heo * 12439deb3431STejun Heo * Use dates instead of versions to match as HP is 12449deb3431STejun Heo * apparently recycling both product and version 12459deb3431STejun Heo * strings. 12469deb3431STejun Heo * 12479deb3431STejun Heo * http://bugzilla.kernel.org/show_bug.cgi?id=15462 12489b10ae86STejun Heo */ 12499b10ae86STejun Heo { 12509b10ae86STejun Heo .ident = "dv4", 12519b10ae86STejun Heo .matches = { 12529b10ae86STejun Heo DMI_MATCH(DMI_SYS_VENDOR, "Hewlett-Packard"), 12539b10ae86STejun Heo DMI_MATCH(DMI_PRODUCT_NAME, 12549b10ae86STejun Heo "HP Pavilion dv4 Notebook PC"), 12559b10ae86STejun Heo }, 12569deb3431STejun Heo .driver_data = "20090105", /* F.30 */ 12579b10ae86STejun Heo }, 12589b10ae86STejun Heo { 12599b10ae86STejun Heo .ident = "dv5", 12609b10ae86STejun Heo .matches = { 12619b10ae86STejun Heo DMI_MATCH(DMI_SYS_VENDOR, "Hewlett-Packard"), 12629b10ae86STejun Heo DMI_MATCH(DMI_PRODUCT_NAME, 12639b10ae86STejun Heo "HP Pavilion dv5 Notebook PC"), 12649b10ae86STejun Heo }, 12659deb3431STejun Heo .driver_data = "20090506", /* F.16 */ 12669b10ae86STejun Heo }, 12679b10ae86STejun Heo { 12689b10ae86STejun Heo .ident = "dv6", 12699b10ae86STejun Heo .matches = { 12709b10ae86STejun Heo DMI_MATCH(DMI_SYS_VENDOR, "Hewlett-Packard"), 12719b10ae86STejun Heo DMI_MATCH(DMI_PRODUCT_NAME, 12729b10ae86STejun Heo "HP Pavilion dv6 Notebook PC"), 12739b10ae86STejun Heo }, 12749deb3431STejun Heo .driver_data = "20090423", /* F.21 */ 12759b10ae86STejun Heo }, 12769b10ae86STejun Heo { 12779b10ae86STejun Heo .ident = "HDX18", 12789b10ae86STejun Heo .matches = { 12799b10ae86STejun Heo DMI_MATCH(DMI_SYS_VENDOR, "Hewlett-Packard"), 12809b10ae86STejun Heo DMI_MATCH(DMI_PRODUCT_NAME, 12819b10ae86STejun Heo "HP HDX18 Notebook PC"), 12829b10ae86STejun Heo }, 12839deb3431STejun Heo .driver_data = "20090430", /* F.23 */ 12849b10ae86STejun Heo }, 1285cedc9bf9STejun Heo /* 1286cedc9bf9STejun Heo * Acer eMachines G725 has the same problem. BIOS 1287cedc9bf9STejun Heo * V1.03 is known to be broken. V3.04 is known to 128825985edcSLucas De Marchi * work. Between, there are V1.06, V2.06 and V3.03 1289cedc9bf9STejun Heo * that we don't have much idea about. For now, 1290cedc9bf9STejun Heo * blacklist anything older than V3.04. 12919deb3431STejun Heo * 12929deb3431STejun Heo * http://bugzilla.kernel.org/show_bug.cgi?id=15104 1293cedc9bf9STejun Heo */ 1294cedc9bf9STejun Heo { 1295cedc9bf9STejun Heo .ident = "G725", 1296cedc9bf9STejun Heo .matches = { 1297cedc9bf9STejun Heo DMI_MATCH(DMI_SYS_VENDOR, "eMachines"), 1298cedc9bf9STejun Heo DMI_MATCH(DMI_PRODUCT_NAME, "eMachines G725"), 1299cedc9bf9STejun Heo }, 13009deb3431STejun Heo .driver_data = "20091216", /* V3.04 */ 1301cedc9bf9STejun Heo }, 13029b10ae86STejun Heo { } /* terminate list */ 13039b10ae86STejun Heo }; 13049b10ae86STejun Heo const struct dmi_system_id *dmi = dmi_first_match(sysids); 13059deb3431STejun Heo int year, month, date; 13069deb3431STejun Heo char buf[9]; 13079b10ae86STejun Heo 13089b10ae86STejun Heo if (!dmi || pdev->bus->number || pdev->devfn != PCI_DEVFN(0x1f, 2)) 13099b10ae86STejun Heo return false; 13109b10ae86STejun Heo 13119deb3431STejun Heo dmi_get_date(DMI_BIOS_DATE, &year, &month, &date); 13129deb3431STejun Heo snprintf(buf, sizeof(buf), "%04d%02d%02d", year, month, date); 13139b10ae86STejun Heo 13149deb3431STejun Heo return strcmp(buf, dmi->driver_data) < 0; 13159b10ae86STejun Heo } 13169b10ae86STejun Heo 1317240630e6SHans de Goede static bool ahci_broken_lpm(struct pci_dev *pdev) 1318240630e6SHans de Goede { 1319240630e6SHans de Goede static const struct dmi_system_id sysids[] = { 1320240630e6SHans de Goede /* Various Lenovo 50 series have LPM issues with older BIOSen */ 1321240630e6SHans de Goede { 1322240630e6SHans de Goede .matches = { 1323240630e6SHans de Goede DMI_MATCH(DMI_SYS_VENDOR, "LENOVO"), 1324240630e6SHans de Goede DMI_MATCH(DMI_PRODUCT_VERSION, "ThinkPad X250"), 1325240630e6SHans de Goede }, 1326240630e6SHans de Goede .driver_data = "20180406", /* 1.31 */ 1327240630e6SHans de Goede }, 1328240630e6SHans de Goede { 1329240630e6SHans de Goede .matches = { 1330240630e6SHans de Goede DMI_MATCH(DMI_SYS_VENDOR, "LENOVO"), 1331240630e6SHans de Goede DMI_MATCH(DMI_PRODUCT_VERSION, "ThinkPad L450"), 1332240630e6SHans de Goede }, 1333240630e6SHans de Goede .driver_data = "20180420", /* 1.28 */ 1334240630e6SHans de Goede }, 1335240630e6SHans de Goede { 1336240630e6SHans de Goede .matches = { 1337240630e6SHans de Goede DMI_MATCH(DMI_SYS_VENDOR, "LENOVO"), 1338240630e6SHans de Goede DMI_MATCH(DMI_PRODUCT_VERSION, "ThinkPad T450s"), 1339240630e6SHans de Goede }, 1340240630e6SHans de Goede .driver_data = "20180315", /* 1.33 */ 1341240630e6SHans de Goede }, 1342240630e6SHans de Goede { 1343240630e6SHans de Goede .matches = { 1344240630e6SHans de Goede DMI_MATCH(DMI_SYS_VENDOR, "LENOVO"), 1345240630e6SHans de Goede DMI_MATCH(DMI_PRODUCT_VERSION, "ThinkPad W541"), 1346240630e6SHans de Goede }, 1347240630e6SHans de Goede /* 1348240630e6SHans de Goede * Note date based on release notes, 2.35 has been 1349240630e6SHans de Goede * reported to be good, but I've been unable to get 1350240630e6SHans de Goede * a hold of the reporter to get the DMI BIOS date. 1351240630e6SHans de Goede * TODO: fix this. 1352240630e6SHans de Goede */ 1353240630e6SHans de Goede .driver_data = "20180310", /* 2.35 */ 1354240630e6SHans de Goede }, 1355240630e6SHans de Goede { } /* terminate list */ 1356240630e6SHans de Goede }; 1357240630e6SHans de Goede const struct dmi_system_id *dmi = dmi_first_match(sysids); 1358240630e6SHans de Goede int year, month, date; 1359240630e6SHans de Goede char buf[9]; 1360240630e6SHans de Goede 1361240630e6SHans de Goede if (!dmi) 1362240630e6SHans de Goede return false; 1363240630e6SHans de Goede 1364240630e6SHans de Goede dmi_get_date(DMI_BIOS_DATE, &year, &month, &date); 1365240630e6SHans de Goede snprintf(buf, sizeof(buf), "%04d%02d%02d", year, month, date); 1366240630e6SHans de Goede 1367240630e6SHans de Goede return strcmp(buf, dmi->driver_data) < 0; 1368240630e6SHans de Goede } 1369240630e6SHans de Goede 13705594639aSTejun Heo static bool ahci_broken_online(struct pci_dev *pdev) 13715594639aSTejun Heo { 13725594639aSTejun Heo #define ENCODE_BUSDEVFN(bus, slot, func) \ 13735594639aSTejun Heo (void *)(unsigned long)(((bus) << 8) | PCI_DEVFN((slot), (func))) 13745594639aSTejun Heo static const struct dmi_system_id sysids[] = { 13755594639aSTejun Heo /* 13765594639aSTejun Heo * There are several gigabyte boards which use 13775594639aSTejun Heo * SIMG5723s configured as hardware RAID. Certain 13785594639aSTejun Heo * 5723 firmware revisions shipped there keep the link 13795594639aSTejun Heo * online but fail to answer properly to SRST or 13805594639aSTejun Heo * IDENTIFY when no device is attached downstream 13815594639aSTejun Heo * causing libata to retry quite a few times leading 13825594639aSTejun Heo * to excessive detection delay. 13835594639aSTejun Heo * 13845594639aSTejun Heo * As these firmwares respond to the second reset try 13855594639aSTejun Heo * with invalid device signature, considering unknown 13865594639aSTejun Heo * sig as offline works around the problem acceptably. 13875594639aSTejun Heo */ 13885594639aSTejun Heo { 13895594639aSTejun Heo .ident = "EP45-DQ6", 13905594639aSTejun Heo .matches = { 13915594639aSTejun Heo DMI_MATCH(DMI_BOARD_VENDOR, 13925594639aSTejun Heo "Gigabyte Technology Co., Ltd."), 13935594639aSTejun Heo DMI_MATCH(DMI_BOARD_NAME, "EP45-DQ6"), 13945594639aSTejun Heo }, 13955594639aSTejun Heo .driver_data = ENCODE_BUSDEVFN(0x0a, 0x00, 0), 13965594639aSTejun Heo }, 13975594639aSTejun Heo { 13985594639aSTejun Heo .ident = "EP45-DS5", 13995594639aSTejun Heo .matches = { 14005594639aSTejun Heo DMI_MATCH(DMI_BOARD_VENDOR, 14015594639aSTejun Heo "Gigabyte Technology Co., Ltd."), 14025594639aSTejun Heo DMI_MATCH(DMI_BOARD_NAME, "EP45-DS5"), 14035594639aSTejun Heo }, 14045594639aSTejun Heo .driver_data = ENCODE_BUSDEVFN(0x03, 0x00, 0), 14055594639aSTejun Heo }, 14065594639aSTejun Heo { } /* terminate list */ 14075594639aSTejun Heo }; 14085594639aSTejun Heo #undef ENCODE_BUSDEVFN 14095594639aSTejun Heo const struct dmi_system_id *dmi = dmi_first_match(sysids); 14105594639aSTejun Heo unsigned int val; 14115594639aSTejun Heo 14125594639aSTejun Heo if (!dmi) 14135594639aSTejun Heo return false; 14145594639aSTejun Heo 14155594639aSTejun Heo val = (unsigned long)dmi->driver_data; 14165594639aSTejun Heo 14175594639aSTejun Heo return pdev->bus->number == (val >> 8) && pdev->devfn == (val & 0xff); 14185594639aSTejun Heo } 14195594639aSTejun Heo 14200cf4a7d6SJacob Pan static bool ahci_broken_devslp(struct pci_dev *pdev) 14210cf4a7d6SJacob Pan { 14220cf4a7d6SJacob Pan /* device with broken DEVSLP but still showing SDS capability */ 14230cf4a7d6SJacob Pan static const struct pci_device_id ids[] = { 14240cf4a7d6SJacob Pan { PCI_VDEVICE(INTEL, 0x0f23)}, /* Valleyview SoC */ 14250cf4a7d6SJacob Pan {} 14260cf4a7d6SJacob Pan }; 14270cf4a7d6SJacob Pan 14280cf4a7d6SJacob Pan return pci_match_id(ids, pdev); 14290cf4a7d6SJacob Pan } 14300cf4a7d6SJacob Pan 14318e513217SMarkus Trippelsdorf #ifdef CONFIG_ATA_ACPI 1432f80ae7e4STejun Heo static void ahci_gtf_filter_workaround(struct ata_host *host) 1433f80ae7e4STejun Heo { 1434f80ae7e4STejun Heo static const struct dmi_system_id sysids[] = { 1435f80ae7e4STejun Heo /* 1436f80ae7e4STejun Heo * Aspire 3810T issues a bunch of SATA enable commands 1437f80ae7e4STejun Heo * via _GTF including an invalid one and one which is 1438f80ae7e4STejun Heo * rejected by the device. Among the successful ones 1439f80ae7e4STejun Heo * is FPDMA non-zero offset enable which when enabled 1440f80ae7e4STejun Heo * only on the drive side leads to NCQ command 1441f80ae7e4STejun Heo * failures. Filter it out. 1442f80ae7e4STejun Heo */ 1443f80ae7e4STejun Heo { 1444f80ae7e4STejun Heo .ident = "Aspire 3810T", 1445f80ae7e4STejun Heo .matches = { 1446f80ae7e4STejun Heo DMI_MATCH(DMI_SYS_VENDOR, "Acer"), 1447f80ae7e4STejun Heo DMI_MATCH(DMI_PRODUCT_NAME, "Aspire 3810T"), 1448f80ae7e4STejun Heo }, 1449f80ae7e4STejun Heo .driver_data = (void *)ATA_ACPI_FILTER_FPDMA_OFFSET, 1450f80ae7e4STejun Heo }, 1451f80ae7e4STejun Heo { } 1452f80ae7e4STejun Heo }; 1453f80ae7e4STejun Heo const struct dmi_system_id *dmi = dmi_first_match(sysids); 1454f80ae7e4STejun Heo unsigned int filter; 1455f80ae7e4STejun Heo int i; 1456f80ae7e4STejun Heo 1457f80ae7e4STejun Heo if (!dmi) 1458f80ae7e4STejun Heo return; 1459f80ae7e4STejun Heo 1460f80ae7e4STejun Heo filter = (unsigned long)dmi->driver_data; 1461a44fec1fSJoe Perches dev_info(host->dev, "applying extra ACPI _GTF filter 0x%x for %s\n", 1462f80ae7e4STejun Heo filter, dmi->ident); 1463f80ae7e4STejun Heo 1464f80ae7e4STejun Heo for (i = 0; i < host->n_ports; i++) { 1465f80ae7e4STejun Heo struct ata_port *ap = host->ports[i]; 1466f80ae7e4STejun Heo struct ata_link *link; 1467f80ae7e4STejun Heo struct ata_device *dev; 1468f80ae7e4STejun Heo 1469f80ae7e4STejun Heo ata_for_each_link(link, ap, EDGE) 1470f80ae7e4STejun Heo ata_for_each_dev(dev, link, ALL) 1471f80ae7e4STejun Heo dev->gtf_filter |= filter; 1472f80ae7e4STejun Heo } 1473f80ae7e4STejun Heo } 14748e513217SMarkus Trippelsdorf #else 14758e513217SMarkus Trippelsdorf static inline void ahci_gtf_filter_workaround(struct ata_host *host) 14768e513217SMarkus Trippelsdorf {} 14778e513217SMarkus Trippelsdorf #endif 1478f80ae7e4STejun Heo 14798bfd1743SSui Chen /* 14808bfd1743SSui Chen * On the Acer Aspire Switch Alpha 12, sometimes all SATA ports are detected 14818bfd1743SSui Chen * as DUMMY, or detected but eventually get a "link down" and never get up 14828bfd1743SSui Chen * again. When this happens, CAP.NP may hold a value of 0x00 or 0x01, and the 14838bfd1743SSui Chen * port_map may hold a value of 0x00. 14848bfd1743SSui Chen * 14858bfd1743SSui Chen * Overriding CAP.NP to 0x02 and the port_map to 0x7 will reveal all 3 ports 14868bfd1743SSui Chen * and can significantly reduce the occurrence of the problem. 14878bfd1743SSui Chen * 14888bfd1743SSui Chen * https://bugzilla.kernel.org/show_bug.cgi?id=189471 14898bfd1743SSui Chen */ 14908bfd1743SSui Chen static void acer_sa5_271_workaround(struct ahci_host_priv *hpriv, 14918bfd1743SSui Chen struct pci_dev *pdev) 14928bfd1743SSui Chen { 14938bfd1743SSui Chen static const struct dmi_system_id sysids[] = { 14948bfd1743SSui Chen { 14958bfd1743SSui Chen .ident = "Acer Switch Alpha 12", 14968bfd1743SSui Chen .matches = { 14978bfd1743SSui Chen DMI_MATCH(DMI_SYS_VENDOR, "Acer"), 14988bfd1743SSui Chen DMI_MATCH(DMI_PRODUCT_NAME, "Switch SA5-271") 14998bfd1743SSui Chen }, 15008bfd1743SSui Chen }, 15018bfd1743SSui Chen { } 15028bfd1743SSui Chen }; 15038bfd1743SSui Chen 15048bfd1743SSui Chen if (dmi_check_system(sysids)) { 15058bfd1743SSui Chen dev_info(&pdev->dev, "enabling Acer Switch Alpha 12 workaround\n"); 15068bfd1743SSui Chen if ((hpriv->saved_cap & 0xC734FF00) == 0xC734FF00) { 15078bfd1743SSui Chen hpriv->port_map = 0x7; 15088bfd1743SSui Chen hpriv->cap = 0xC734FF02; 15098bfd1743SSui Chen } 15108bfd1743SSui Chen } 15118bfd1743SSui Chen } 15128bfd1743SSui Chen 1513d243bed3STirumalesh Chalamarla #ifdef CONFIG_ARM64 1514d243bed3STirumalesh Chalamarla /* 1515d243bed3STirumalesh Chalamarla * Due to ERRATA#22536, ThunderX needs to handle HOST_IRQ_STAT differently. 1516d243bed3STirumalesh Chalamarla * Workaround is to make sure all pending IRQs are served before leaving 1517d243bed3STirumalesh Chalamarla * handler. 1518d243bed3STirumalesh Chalamarla */ 1519d243bed3STirumalesh Chalamarla static irqreturn_t ahci_thunderx_irq_handler(int irq, void *dev_instance) 1520d243bed3STirumalesh Chalamarla { 1521d243bed3STirumalesh Chalamarla struct ata_host *host = dev_instance; 1522d243bed3STirumalesh Chalamarla struct ahci_host_priv *hpriv; 1523d243bed3STirumalesh Chalamarla unsigned int rc = 0; 1524d243bed3STirumalesh Chalamarla void __iomem *mmio; 1525d243bed3STirumalesh Chalamarla u32 irq_stat, irq_masked; 1526d243bed3STirumalesh Chalamarla unsigned int handled = 1; 1527d243bed3STirumalesh Chalamarla 1528d243bed3STirumalesh Chalamarla hpriv = host->private_data; 1529d243bed3STirumalesh Chalamarla mmio = hpriv->mmio; 1530d243bed3STirumalesh Chalamarla irq_stat = readl(mmio + HOST_IRQ_STAT); 1531d243bed3STirumalesh Chalamarla if (!irq_stat) 1532d243bed3STirumalesh Chalamarla return IRQ_NONE; 1533d243bed3STirumalesh Chalamarla 1534d243bed3STirumalesh Chalamarla do { 1535d243bed3STirumalesh Chalamarla irq_masked = irq_stat & hpriv->port_map; 1536d243bed3STirumalesh Chalamarla spin_lock(&host->lock); 1537d243bed3STirumalesh Chalamarla rc = ahci_handle_port_intr(host, irq_masked); 1538d243bed3STirumalesh Chalamarla if (!rc) 1539d243bed3STirumalesh Chalamarla handled = 0; 1540d243bed3STirumalesh Chalamarla writel(irq_stat, mmio + HOST_IRQ_STAT); 1541d243bed3STirumalesh Chalamarla irq_stat = readl(mmio + HOST_IRQ_STAT); 1542d243bed3STirumalesh Chalamarla spin_unlock(&host->lock); 1543d243bed3STirumalesh Chalamarla } while (irq_stat); 1544d243bed3STirumalesh Chalamarla 1545d243bed3STirumalesh Chalamarla return IRQ_RETVAL(handled); 1546d243bed3STirumalesh Chalamarla } 1547d243bed3STirumalesh Chalamarla #endif 1548d243bed3STirumalesh Chalamarla 1549aecec8b6SChristoph Hellwig static void ahci_remap_check(struct pci_dev *pdev, int bar, 1550aecec8b6SChristoph Hellwig struct ahci_host_priv *hpriv) 1551aecec8b6SChristoph Hellwig { 1552894fba7fSKai-Heng Feng int i; 1553aecec8b6SChristoph Hellwig u32 cap; 1554aecec8b6SChristoph Hellwig 1555aecec8b6SChristoph Hellwig /* 1556aecec8b6SChristoph Hellwig * Check if this device might have remapped nvme devices. 1557aecec8b6SChristoph Hellwig */ 1558aecec8b6SChristoph Hellwig if (pdev->vendor != PCI_VENDOR_ID_INTEL || 1559aecec8b6SChristoph Hellwig pci_resource_len(pdev, bar) < SZ_512K || 1560aecec8b6SChristoph Hellwig bar != AHCI_PCI_BAR_STANDARD || 1561aecec8b6SChristoph Hellwig !(readl(hpriv->mmio + AHCI_VSCAP) & 1)) 1562aecec8b6SChristoph Hellwig return; 1563aecec8b6SChristoph Hellwig 1564aecec8b6SChristoph Hellwig cap = readq(hpriv->mmio + AHCI_REMAP_CAP); 1565aecec8b6SChristoph Hellwig for (i = 0; i < AHCI_MAX_REMAP; i++) { 1566aecec8b6SChristoph Hellwig if ((cap & (1 << i)) == 0) 1567aecec8b6SChristoph Hellwig continue; 1568aecec8b6SChristoph Hellwig if (readl(hpriv->mmio + ahci_remap_dcc(i)) 1569aecec8b6SChristoph Hellwig != PCI_CLASS_STORAGE_EXPRESS) 1570aecec8b6SChristoph Hellwig continue; 1571aecec8b6SChristoph Hellwig 1572aecec8b6SChristoph Hellwig /* We've found a remapped device */ 1573894fba7fSKai-Heng Feng hpriv->remapped_nvme++; 1574aecec8b6SChristoph Hellwig } 1575aecec8b6SChristoph Hellwig 1576894fba7fSKai-Heng Feng if (!hpriv->remapped_nvme) 1577aecec8b6SChristoph Hellwig return; 1578aecec8b6SChristoph Hellwig 1579894fba7fSKai-Heng Feng dev_warn(&pdev->dev, "Found %u remapped NVMe devices.\n", 1580894fba7fSKai-Heng Feng hpriv->remapped_nvme); 1581f723fa4eSChristoph Hellwig dev_warn(&pdev->dev, 1582f723fa4eSChristoph Hellwig "Switch your BIOS from RAID to AHCI mode to use them.\n"); 1583f723fa4eSChristoph Hellwig 1584f723fa4eSChristoph Hellwig /* 1585f723fa4eSChristoph Hellwig * Don't rely on the msi-x capability in the remap case, 1586f723fa4eSChristoph Hellwig * share the legacy interrupt across ahci and remapped devices. 1587f723fa4eSChristoph Hellwig */ 1588f723fa4eSChristoph Hellwig hpriv->flags |= AHCI_HFLAG_NO_MSI; 1589aecec8b6SChristoph Hellwig } 1590aecec8b6SChristoph Hellwig 15910b9e2988SChristoph Hellwig static int ahci_get_irq_vector(struct ata_host *host, int port) 1592ee2aad42SRobert Richter { 15930b9e2988SChristoph Hellwig return pci_irq_vector(to_pci_dev(host->dev), port); 1594ee2aad42SRobert Richter } 1595ee2aad42SRobert Richter 1596a1c82311SRobert Richter static int ahci_init_msi(struct pci_dev *pdev, unsigned int n_ports, 15977b92b4f6SAlexander Gordeev struct ahci_host_priv *hpriv) 15985ca72c4fSAlexander Gordeev { 15990b9e2988SChristoph Hellwig int nvec; 16005ca72c4fSAlexander Gordeev 16017b92b4f6SAlexander Gordeev if (hpriv->flags & AHCI_HFLAG_NO_MSI) 1602a1c82311SRobert Richter return -ENODEV; 16037b92b4f6SAlexander Gordeev 16045ca72c4fSAlexander Gordeev /* 16057b92b4f6SAlexander Gordeev * If number of MSIs is less than number of ports then Sharing Last 16067b92b4f6SAlexander Gordeev * Message mode could be enforced. In this case assume that advantage 16077b92b4f6SAlexander Gordeev * of multipe MSIs is negated and use single MSI mode instead. 16085ca72c4fSAlexander Gordeev */ 160917a51f12SChristoph Hellwig if (n_ports > 1) { 16100b9e2988SChristoph Hellwig nvec = pci_alloc_irq_vectors(pdev, n_ports, INT_MAX, 16110b9e2988SChristoph Hellwig PCI_IRQ_MSIX | PCI_IRQ_MSI); 16120b9e2988SChristoph Hellwig if (nvec > 0) { 16130b9e2988SChristoph Hellwig if (!(readl(hpriv->mmio + HOST_CTL) & HOST_MRSM)) { 16140b9e2988SChristoph Hellwig hpriv->get_irq_vector = ahci_get_irq_vector; 1615c3ebd6a9SAlexander Gordeev hpriv->flags |= AHCI_HFLAG_MULTI_MSI; 161621bfd1aaSRobert Richter return nvec; 1617a1c82311SRobert Richter } 1618a1c82311SRobert Richter 1619d684a90dSDan Williams /* 162017a51f12SChristoph Hellwig * Fallback to single MSI mode if the controller 162117a51f12SChristoph Hellwig * enforced MRSM mode. 1622d684a90dSDan Williams */ 162317a51f12SChristoph Hellwig printk(KERN_INFO 162417a51f12SChristoph Hellwig "ahci: MRSM is on, fallback to single MSI\n"); 16250b9e2988SChristoph Hellwig pci_free_irq_vectors(pdev); 16260b9e2988SChristoph Hellwig } 1627a478b097SChristoph Hellwig } 1628d684a90dSDan Williams 16290b9e2988SChristoph Hellwig /* 16300b9e2988SChristoph Hellwig * If the host is not capable of supporting per-port vectors, fall 16310b9e2988SChristoph Hellwig * back to single MSI before finally attempting single MSI-X. 16320b9e2988SChristoph Hellwig */ 16330b9e2988SChristoph Hellwig nvec = pci_alloc_irq_vectors(pdev, 1, 1, PCI_IRQ_MSI); 16340b9e2988SChristoph Hellwig if (nvec == 1) 1635a1c82311SRobert Richter return nvec; 16360b9e2988SChristoph Hellwig return pci_alloc_irq_vectors(pdev, 1, 1, PCI_IRQ_MSIX); 16375ca72c4fSAlexander Gordeev } 16385ca72c4fSAlexander Gordeev 1639b1a9585cSSrinivas Pandruvada static void ahci_update_initial_lpm_policy(struct ata_port *ap, 1640b1a9585cSSrinivas Pandruvada struct ahci_host_priv *hpriv) 1641b1a9585cSSrinivas Pandruvada { 164255b01415SMario Limonciello int policy = CONFIG_SATA_MOBILE_LPM_POLICY; 1643b1a9585cSSrinivas Pandruvada 1644b1a9585cSSrinivas Pandruvada 1645e5c89479SMario Limonciello /* Ignore processing for chipsets that don't use policy */ 1646e5c89479SMario Limonciello if (!(hpriv->flags & AHCI_HFLAG_USE_LPM_POLICY)) 1647b1a9585cSSrinivas Pandruvada return; 1648b1a9585cSSrinivas Pandruvada 1649b1a9585cSSrinivas Pandruvada /* user modified policy via module param */ 1650b1a9585cSSrinivas Pandruvada if (mobile_lpm_policy != -1) { 1651b1a9585cSSrinivas Pandruvada policy = mobile_lpm_policy; 1652b1a9585cSSrinivas Pandruvada goto update_policy; 1653b1a9585cSSrinivas Pandruvada } 1654b1a9585cSSrinivas Pandruvada 1655fee60730SRafael J. Wysocki if (policy > ATA_LPM_MED_POWER && pm_suspend_default_s2idle()) { 1656b1a9585cSSrinivas Pandruvada if (hpriv->cap & HOST_CAP_PART) 1657b1a9585cSSrinivas Pandruvada policy = ATA_LPM_MIN_POWER_WITH_PARTIAL; 1658b1a9585cSSrinivas Pandruvada else if (hpriv->cap & HOST_CAP_SSC) 1659b1a9585cSSrinivas Pandruvada policy = ATA_LPM_MIN_POWER; 1660b1a9585cSSrinivas Pandruvada } 1661b1a9585cSSrinivas Pandruvada 1662b1a9585cSSrinivas Pandruvada update_policy: 1663b1a9585cSSrinivas Pandruvada if (policy >= ATA_LPM_UNKNOWN && policy <= ATA_LPM_MIN_POWER) 1664b1a9585cSSrinivas Pandruvada ap->target_lpm_policy = policy; 1665b1a9585cSSrinivas Pandruvada } 1666b1a9585cSSrinivas Pandruvada 1667c312ef17SDan Williams static void ahci_intel_pcs_quirk(struct pci_dev *pdev, struct ahci_host_priv *hpriv) 1668c312ef17SDan Williams { 1669c312ef17SDan Williams const struct pci_device_id *id = pci_match_id(ahci_pci_tbl, pdev); 1670c312ef17SDan Williams u16 tmp16; 1671c312ef17SDan Williams 1672c312ef17SDan Williams /* 1673c312ef17SDan Williams * Only apply the 6-port PCS quirk for known legacy platforms. 1674c312ef17SDan Williams */ 1675c312ef17SDan Williams if (!id || id->vendor != PCI_VENDOR_ID_INTEL) 1676c312ef17SDan Williams return; 167709d6ac8dSDan Williams 167809d6ac8dSDan Williams /* Skip applying the quirk on Denverton and beyond */ 167909d6ac8dSDan Williams if (((enum board_ids) id->driver_data) >= board_ahci_pcs7) 1680c312ef17SDan Williams return; 1681c312ef17SDan Williams 1682c312ef17SDan Williams /* 1683c312ef17SDan Williams * port_map is determined from PORTS_IMPL PCI register which is 1684c312ef17SDan Williams * implemented as write or write-once register. If the register 1685c312ef17SDan Williams * isn't programmed, ahci automatically generates it from number 1686c312ef17SDan Williams * of ports, which is good enough for PCS programming. It is 1687c312ef17SDan Williams * otherwise expected that platform firmware enables the ports 1688c312ef17SDan Williams * before the OS boots. 1689c312ef17SDan Williams */ 1690c312ef17SDan Williams pci_read_config_word(pdev, PCS_6, &tmp16); 1691c312ef17SDan Williams if ((tmp16 & hpriv->port_map) != hpriv->port_map) { 1692c312ef17SDan Williams tmp16 |= hpriv->port_map; 1693c312ef17SDan Williams pci_write_config_word(pdev, PCS_6, tmp16); 1694c312ef17SDan Williams } 1695c312ef17SDan Williams } 1696c312ef17SDan Williams 1697894fba7fSKai-Heng Feng static ssize_t remapped_nvme_show(struct device *dev, 1698894fba7fSKai-Heng Feng struct device_attribute *attr, 1699894fba7fSKai-Heng Feng char *buf) 1700894fba7fSKai-Heng Feng { 1701894fba7fSKai-Heng Feng struct ata_host *host = dev_get_drvdata(dev); 1702894fba7fSKai-Heng Feng struct ahci_host_priv *hpriv = host->private_data; 1703894fba7fSKai-Heng Feng 1704179a0282SDamien Le Moal return sysfs_emit(buf, "%u\n", hpriv->remapped_nvme); 1705894fba7fSKai-Heng Feng } 1706894fba7fSKai-Heng Feng 1707894fba7fSKai-Heng Feng static DEVICE_ATTR_RO(remapped_nvme); 1708894fba7fSKai-Heng Feng 1709c6fd2807SJeff Garzik static int ahci_init_one(struct pci_dev *pdev, const struct pci_device_id *ent) 1710c6fd2807SJeff Garzik { 1711e297d99eSTejun Heo unsigned int board_id = ent->driver_data; 1712e297d99eSTejun Heo struct ata_port_info pi = ahci_port_info[board_id]; 17134447d351STejun Heo const struct ata_port_info *ppi[] = { &pi, NULL }; 171424dc5f33STejun Heo struct device *dev = &pdev->dev; 1715c6fd2807SJeff Garzik struct ahci_host_priv *hpriv; 17164447d351STejun Heo struct ata_host *host; 1717c3ebd6a9SAlexander Gordeev int n_ports, i, rc; 1718318893e1SAlessandro Rubini int ahci_pci_bar = AHCI_PCI_BAR_STANDARD; 1719c6fd2807SJeff Garzik 1720b429dd59SJustin P. Mattock WARN_ON((int)ATA_MAX_QUEUE > AHCI_MAX_CMDS); 1721c6fd2807SJeff Garzik 172206296a1eSJoe Perches ata_print_version_once(&pdev->dev, DRV_VERSION); 1723c6fd2807SJeff Garzik 17245b66c829SAlan Cox /* The AHCI driver can only drive the SATA ports, the PATA driver 17255b66c829SAlan Cox can drive them all so if both drivers are selected make sure 17265b66c829SAlan Cox AHCI stays out of the way */ 17275b66c829SAlan Cox if (pdev->vendor == PCI_VENDOR_ID_MARVELL && !marvell_enable) 17285b66c829SAlan Cox return -ENODEV; 17295b66c829SAlan Cox 1730cb85696dSJames Laird /* Apple BIOS on MCP89 prevents us using AHCI */ 1731cb85696dSJames Laird if (is_mcp89_apple(pdev)) 1732cb85696dSJames Laird ahci_mcp89_apple_enable(pdev); 1733c6353b45STejun Heo 17347a02267eSMark Nelson /* Promise's PDC42819 is a SAS/SATA controller that has an AHCI mode. 17357a02267eSMark Nelson * At the moment, we can only use the AHCI mode. Let the users know 17367a02267eSMark Nelson * that for SAS drives they're out of luck. 17377a02267eSMark Nelson */ 17387a02267eSMark Nelson if (pdev->vendor == PCI_VENDOR_ID_PROMISE) 1739a44fec1fSJoe Perches dev_info(&pdev->dev, 1740a44fec1fSJoe Perches "PDC42819 can only drive SATA devices with this driver\n"); 17417a02267eSMark Nelson 1742b7ae128dSRobert Richter /* Some devices use non-standard BARs */ 1743318893e1SAlessandro Rubini if (pdev->vendor == PCI_VENDOR_ID_STMICRO && pdev->device == 0xCC06) 1744318893e1SAlessandro Rubini ahci_pci_bar = AHCI_PCI_BAR_STA2X11; 17457f9c9f8eSHugh Daschbach else if (pdev->vendor == 0x1c44 && pdev->device == 0x8000) 17467f9c9f8eSHugh Daschbach ahci_pci_bar = AHCI_PCI_BAR_ENMOTUS; 1747b1314e3fSRadha Mohan Chintakuntla else if (pdev->vendor == PCI_VENDOR_ID_CAVIUM) { 1748b1314e3fSRadha Mohan Chintakuntla if (pdev->device == 0xa01c) 1749b7ae128dSRobert Richter ahci_pci_bar = AHCI_PCI_BAR_CAVIUM; 1750b1314e3fSRadha Mohan Chintakuntla if (pdev->device == 0xa084) 1751b1314e3fSRadha Mohan Chintakuntla ahci_pci_bar = AHCI_PCI_BAR_CAVIUM_GEN5; 1752e49bd683STiezhu Yang } else if (pdev->vendor == PCI_VENDOR_ID_LOONGSON) { 1753e49bd683STiezhu Yang if (pdev->device == 0x7a08) 1754e49bd683STiezhu Yang ahci_pci_bar = AHCI_PCI_BAR_LOONGSON; 1755b1314e3fSRadha Mohan Chintakuntla } 1756318893e1SAlessandro Rubini 17574447d351STejun Heo /* acquire resources */ 175824dc5f33STejun Heo rc = pcim_enable_device(pdev); 1759c6fd2807SJeff Garzik if (rc) 1760c6fd2807SJeff Garzik return rc; 1761c6fd2807SJeff Garzik 1762c4f7792cSTejun Heo if (pdev->vendor == PCI_VENDOR_ID_INTEL && 1763c4f7792cSTejun Heo (pdev->device == 0x2652 || pdev->device == 0x2653)) { 1764c4f7792cSTejun Heo u8 map; 1765c4f7792cSTejun Heo 1766c4f7792cSTejun Heo /* ICH6s share the same PCI ID for both piix and ahci 1767c4f7792cSTejun Heo * modes. Enabling ahci mode while MAP indicates 1768c4f7792cSTejun Heo * combined mode is a bad idea. Yield to ata_piix. 1769c4f7792cSTejun Heo */ 1770c4f7792cSTejun Heo pci_read_config_byte(pdev, ICH_MAP, &map); 1771c4f7792cSTejun Heo if (map & 0x3) { 1772a44fec1fSJoe Perches dev_info(&pdev->dev, 1773a44fec1fSJoe Perches "controller is in combined mode, can't enable AHCI mode\n"); 1774c4f7792cSTejun Heo return -ENODEV; 1775c4f7792cSTejun Heo } 1776c4f7792cSTejun Heo } 1777c4f7792cSTejun Heo 17786fec8871SPaul Bolle /* AHCI controllers often implement SFF compatible interface. 17796fec8871SPaul Bolle * Grab all PCI BARs just in case. 17806fec8871SPaul Bolle */ 17816fec8871SPaul Bolle rc = pcim_iomap_regions_request_all(pdev, 1 << ahci_pci_bar, DRV_NAME); 17826fec8871SPaul Bolle if (rc == -EBUSY) 17836fec8871SPaul Bolle pcim_pin_device(pdev); 17846fec8871SPaul Bolle if (rc) 17856fec8871SPaul Bolle return rc; 17866fec8871SPaul Bolle 178724dc5f33STejun Heo hpriv = devm_kzalloc(dev, sizeof(*hpriv), GFP_KERNEL); 178824dc5f33STejun Heo if (!hpriv) 178924dc5f33STejun Heo return -ENOMEM; 1790417a1a6dSTejun Heo hpriv->flags |= (unsigned long)pi.private_data; 1791417a1a6dSTejun Heo 1792e297d99eSTejun Heo /* MCP65 revision A1 and A2 can't do MSI */ 1793e297d99eSTejun Heo if (board_id == board_ahci_mcp65 && 1794e297d99eSTejun Heo (pdev->revision == 0xa1 || pdev->revision == 0xa2)) 1795e297d99eSTejun Heo hpriv->flags |= AHCI_HFLAG_NO_MSI; 1796e297d99eSTejun Heo 1797e427fe04SShane Huang /* SB800 does NOT need the workaround to ignore SERR_INTERNAL */ 1798e427fe04SShane Huang if (board_id == board_ahci_sb700 && pdev->revision >= 0x40) 1799e427fe04SShane Huang hpriv->flags &= ~AHCI_HFLAG_IGN_SERR_INTERNAL; 1800e427fe04SShane Huang 18012fcad9d2STejun Heo /* only some SB600s can do 64bit DMA */ 18022fcad9d2STejun Heo if (ahci_sb600_enable_64bit(pdev)) 18032fcad9d2STejun Heo hpriv->flags &= ~AHCI_HFLAG_32BIT_ONLY; 180458a09b38SShane Huang 1805318893e1SAlessandro Rubini hpriv->mmio = pcim_iomap_table(pdev)[ahci_pci_bar]; 1806d8993349SAnton Vorontsov 1807aecec8b6SChristoph Hellwig /* detect remapped nvme devices */ 1808aecec8b6SChristoph Hellwig ahci_remap_check(pdev, ahci_pci_bar, hpriv); 1809aecec8b6SChristoph Hellwig 1810894fba7fSKai-Heng Feng sysfs_add_file_to_group(&pdev->dev.kobj, 1811894fba7fSKai-Heng Feng &dev_attr_remapped_nvme.attr, 1812894fba7fSKai-Heng Feng NULL); 1813894fba7fSKai-Heng Feng 18140cf4a7d6SJacob Pan /* must set flag prior to save config in order to take effect */ 18150cf4a7d6SJacob Pan if (ahci_broken_devslp(pdev)) 18160cf4a7d6SJacob Pan hpriv->flags |= AHCI_HFLAG_NO_DEVSLP; 18170cf4a7d6SJacob Pan 1818d243bed3STirumalesh Chalamarla #ifdef CONFIG_ARM64 1819234e6d2cSXingui Yang if (pdev->vendor == PCI_VENDOR_ID_HUAWEI && 1820234e6d2cSXingui Yang pdev->device == 0xa235 && 1821234e6d2cSXingui Yang pdev->revision < 0x30) 1822234e6d2cSXingui Yang hpriv->flags |= AHCI_HFLAG_NO_SXS; 1823234e6d2cSXingui Yang 1824d243bed3STirumalesh Chalamarla if (pdev->vendor == 0x177d && pdev->device == 0xa01c) 1825d243bed3STirumalesh Chalamarla hpriv->irq_handler = ahci_thunderx_irq_handler; 1826d243bed3STirumalesh Chalamarla #endif 1827d243bed3STirumalesh Chalamarla 18284447d351STejun Heo /* save initial config */ 1829394d6e53SAnton Vorontsov ahci_pci_save_initial_config(pdev, hpriv); 1830c6fd2807SJeff Garzik 18314447d351STejun Heo /* prepare host */ 1832453d3131SRobert Hancock if (hpriv->cap & HOST_CAP_NCQ) { 1833453d3131SRobert Hancock pi.flags |= ATA_FLAG_NCQ; 183483f2b963STejun Heo /* 183583f2b963STejun Heo * Auto-activate optimization is supposed to be 183683f2b963STejun Heo * supported on all AHCI controllers indicating NCQ 183783f2b963STejun Heo * capability, but it seems to be broken on some 183883f2b963STejun Heo * chipsets including NVIDIAs. 183983f2b963STejun Heo */ 184083f2b963STejun Heo if (!(hpriv->flags & AHCI_HFLAG_NO_FPDMA_AA)) 1841453d3131SRobert Hancock pi.flags |= ATA_FLAG_FPDMA_AA; 184240fb59e7SMarc Carino 184340fb59e7SMarc Carino /* 184440fb59e7SMarc Carino * All AHCI controllers should be forward-compatible 184540fb59e7SMarc Carino * with the new auxiliary field. This code should be 184640fb59e7SMarc Carino * conditionalized if any buggy AHCI controllers are 184740fb59e7SMarc Carino * encountered. 184840fb59e7SMarc Carino */ 184940fb59e7SMarc Carino pi.flags |= ATA_FLAG_FPDMA_AUX; 1850453d3131SRobert Hancock } 18514447d351STejun Heo 18527d50b60bSTejun Heo if (hpriv->cap & HOST_CAP_PMP) 18537d50b60bSTejun Heo pi.flags |= ATA_FLAG_PMP; 18547d50b60bSTejun Heo 18550cbb0e77SAnton Vorontsov ahci_set_em_messages(hpriv, &pi); 185618f7ba4cSKristen Carlson Accardi 18571fd68434SRafael J. Wysocki if (ahci_broken_system_poweroff(pdev)) { 18581fd68434SRafael J. Wysocki pi.flags |= ATA_FLAG_NO_POWEROFF_SPINDOWN; 18591fd68434SRafael J. Wysocki dev_info(&pdev->dev, 18601fd68434SRafael J. Wysocki "quirky BIOS, skipping spindown on poweroff\n"); 18611fd68434SRafael J. Wysocki } 18621fd68434SRafael J. Wysocki 1863240630e6SHans de Goede if (ahci_broken_lpm(pdev)) { 1864240630e6SHans de Goede pi.flags |= ATA_FLAG_NO_LPM; 1865240630e6SHans de Goede dev_warn(&pdev->dev, 1866240630e6SHans de Goede "BIOS update required for Link Power Management support\n"); 1867240630e6SHans de Goede } 1868240630e6SHans de Goede 18699b10ae86STejun Heo if (ahci_broken_suspend(pdev)) { 18709b10ae86STejun Heo hpriv->flags |= AHCI_HFLAG_NO_SUSPEND; 1871a44fec1fSJoe Perches dev_warn(&pdev->dev, 18729b10ae86STejun Heo "BIOS update required for suspend/resume\n"); 18739b10ae86STejun Heo } 18749b10ae86STejun Heo 18755594639aSTejun Heo if (ahci_broken_online(pdev)) { 18765594639aSTejun Heo hpriv->flags |= AHCI_HFLAG_SRST_TOUT_IS_OFFLINE; 18775594639aSTejun Heo dev_info(&pdev->dev, 18785594639aSTejun Heo "online status unreliable, applying workaround\n"); 18795594639aSTejun Heo } 18805594639aSTejun Heo 18818bfd1743SSui Chen 18828bfd1743SSui Chen /* Acer SA5-271 workaround modifies private_data */ 18838bfd1743SSui Chen acer_sa5_271_workaround(hpriv, pdev); 18848bfd1743SSui Chen 1885837f5f8fSTejun Heo /* CAP.NP sometimes indicate the index of the last enabled 1886837f5f8fSTejun Heo * port, at other times, that of the last possible port, so 1887837f5f8fSTejun Heo * determining the maximum port number requires looking at 1888837f5f8fSTejun Heo * both CAP.NP and port_map. 1889837f5f8fSTejun Heo */ 1890837f5f8fSTejun Heo n_ports = max(ahci_nr_ports(hpriv->cap), fls(hpriv->port_map)); 1891837f5f8fSTejun Heo 1892837f5f8fSTejun Heo host = ata_host_alloc_pinfo(&pdev->dev, ppi, n_ports); 1893*d8d54126SNiklas Cassel if (!host) { 1894*d8d54126SNiklas Cassel rc = -ENOMEM; 1895*d8d54126SNiklas Cassel goto err_rm_sysfs_file; 1896*d8d54126SNiklas Cassel } 18974447d351STejun Heo host->private_data = hpriv; 18980b9e2988SChristoph Hellwig 18990b9e2988SChristoph Hellwig if (ahci_init_msi(pdev, n_ports, hpriv) < 0) { 19000b9e2988SChristoph Hellwig /* legacy intx interrupts */ 19010b9e2988SChristoph Hellwig pci_intx(pdev, 1); 19020b9e2988SChristoph Hellwig } 19030ce57f8aSChristoph Hellwig hpriv->irq = pci_irq_vector(pdev, 0); 190421bfd1aaSRobert Richter 1905f3d7f23fSArjan van de Ven if (!(hpriv->cap & HOST_CAP_SSS) || ahci_ignore_sss) 1906886ad09fSArjan van de Ven host->flags |= ATA_HOST_PARALLEL_SCAN; 1907f3d7f23fSArjan van de Ven else 1908d2782d96SJingoo Han dev_info(&pdev->dev, "SSS flag set, parallel bus scan disabled\n"); 1909886ad09fSArjan van de Ven 191024e0e61dSNiklas Cassel if (!(hpriv->cap & HOST_CAP_PART)) 191124e0e61dSNiklas Cassel host->flags |= ATA_HOST_NO_PART; 191224e0e61dSNiklas Cassel 191324e0e61dSNiklas Cassel if (!(hpriv->cap & HOST_CAP_SSC)) 191424e0e61dSNiklas Cassel host->flags |= ATA_HOST_NO_SSC; 191524e0e61dSNiklas Cassel 191624e0e61dSNiklas Cassel if (!(hpriv->cap2 & HOST_CAP2_SDS)) 191724e0e61dSNiklas Cassel host->flags |= ATA_HOST_NO_DEVSLP; 191824e0e61dSNiklas Cassel 191918f7ba4cSKristen Carlson Accardi if (pi.flags & ATA_FLAG_EM) 192018f7ba4cSKristen Carlson Accardi ahci_reset_em(host); 192118f7ba4cSKristen Carlson Accardi 19224447d351STejun Heo for (i = 0; i < host->n_ports; i++) { 19234447d351STejun Heo struct ata_port *ap = host->ports[i]; 19244447d351STejun Heo 1925318893e1SAlessandro Rubini ata_port_pbar_desc(ap, ahci_pci_bar, -1, "abar"); 1926318893e1SAlessandro Rubini ata_port_pbar_desc(ap, ahci_pci_bar, 1927cbcdd875STejun Heo 0x100 + ap->port_no * 0x80, "port"); 1928cbcdd875STejun Heo 192918f7ba4cSKristen Carlson Accardi /* set enclosure management message type */ 193018f7ba4cSKristen Carlson Accardi if (ap->flags & ATA_FLAG_EM) 1931008dbd61SHarry Zhang ap->em_message_type = hpriv->em_msg_type; 193218f7ba4cSKristen Carlson Accardi 1933b1a9585cSSrinivas Pandruvada ahci_update_initial_lpm_policy(ap, hpriv); 193418f7ba4cSKristen Carlson Accardi 1935dab632e8SJeff Garzik /* disabled/not-implemented port */ 1936350756f6STejun Heo if (!(hpriv->port_map & (1 << i))) 1937dab632e8SJeff Garzik ap->ops = &ata_dummy_port_ops; 19384447d351STejun Heo } 1939c6fd2807SJeff Garzik 1940edc93052STejun Heo /* apply workaround for ASUS P5W DH Deluxe mainboard */ 1941edc93052STejun Heo ahci_p5wdh_workaround(host); 1942edc93052STejun Heo 1943f80ae7e4STejun Heo /* apply gtf filter quirk */ 1944f80ae7e4STejun Heo ahci_gtf_filter_workaround(host); 1945f80ae7e4STejun Heo 1946c6fd2807SJeff Garzik /* initialize adapter */ 1947b0dd4d7aSLennert Buytenhek rc = ahci_configure_dma_masks(pdev, hpriv); 1948c6fd2807SJeff Garzik if (rc) 1949*d8d54126SNiklas Cassel goto err_rm_sysfs_file; 1950c6fd2807SJeff Garzik 195137e14e4fSAdam Vodopjan rc = ahci_pci_reset_controller(host); 19524447d351STejun Heo if (rc) 1953*d8d54126SNiklas Cassel goto err_rm_sysfs_file; 1954c6fd2807SJeff Garzik 1955781d6550SAnton Vorontsov ahci_pci_init_controller(host); 1956439fcaecSAnton Vorontsov ahci_pci_print_info(host); 1957c6fd2807SJeff Garzik 19584447d351STejun Heo pci_set_master(pdev); 19595ca72c4fSAlexander Gordeev 196002e53293SMika Westerberg rc = ahci_host_activate(host, &ahci_sht); 196102e53293SMika Westerberg if (rc) 1962*d8d54126SNiklas Cassel goto err_rm_sysfs_file; 196302e53293SMika Westerberg 196402e53293SMika Westerberg pm_runtime_put_noidle(&pdev->dev); 196502e53293SMika Westerberg return 0; 1966*d8d54126SNiklas Cassel 1967*d8d54126SNiklas Cassel err_rm_sysfs_file: 1968*d8d54126SNiklas Cassel sysfs_remove_file_from_group(&pdev->dev.kobj, 1969*d8d54126SNiklas Cassel &dev_attr_remapped_nvme.attr, NULL); 1970*d8d54126SNiklas Cassel return rc; 197102e53293SMika Westerberg } 197202e53293SMika Westerberg 197310a663a1SPrabhakar Kushwaha static void ahci_shutdown_one(struct pci_dev *pdev) 197410a663a1SPrabhakar Kushwaha { 197510a663a1SPrabhakar Kushwaha ata_pci_shutdown_one(pdev); 197610a663a1SPrabhakar Kushwaha } 197710a663a1SPrabhakar Kushwaha 197802e53293SMika Westerberg static void ahci_remove_one(struct pci_dev *pdev) 197902e53293SMika Westerberg { 1980894fba7fSKai-Heng Feng sysfs_remove_file_from_group(&pdev->dev.kobj, 1981894fba7fSKai-Heng Feng &dev_attr_remapped_nvme.attr, 1982894fba7fSKai-Heng Feng NULL); 198302e53293SMika Westerberg pm_runtime_get_noresume(&pdev->dev); 198402e53293SMika Westerberg ata_pci_remove_one(pdev); 1985c6fd2807SJeff Garzik } 1986c6fd2807SJeff Garzik 19872fc75da0SAxel Lin module_pci_driver(ahci_pci_driver); 1988c6fd2807SJeff Garzik 1989c6fd2807SJeff Garzik MODULE_AUTHOR("Jeff Garzik"); 1990c6fd2807SJeff Garzik MODULE_DESCRIPTION("AHCI SATA low-level driver"); 1991c6fd2807SJeff Garzik MODULE_LICENSE("GPL"); 1992c6fd2807SJeff Garzik MODULE_DEVICE_TABLE(pci, ahci_pci_tbl); 1993c6fd2807SJeff Garzik MODULE_VERSION(DRV_VERSION); 1994