162306a36Sopenharmony_ci// SPDX-License-Identifier: GPL-2.0-or-later 262306a36Sopenharmony_ci/* 362306a36Sopenharmony_ci * ata_piix.c - Intel PATA/SATA controllers 462306a36Sopenharmony_ci * 562306a36Sopenharmony_ci * Maintained by: Tejun Heo <tj@kernel.org> 662306a36Sopenharmony_ci * Please ALWAYS copy linux-ide@vger.kernel.org 762306a36Sopenharmony_ci * on emails. 862306a36Sopenharmony_ci * 962306a36Sopenharmony_ci * Copyright 2003-2005 Red Hat Inc 1062306a36Sopenharmony_ci * Copyright 2003-2005 Jeff Garzik 1162306a36Sopenharmony_ci * 1262306a36Sopenharmony_ci * Copyright header from piix.c: 1362306a36Sopenharmony_ci * 1462306a36Sopenharmony_ci * Copyright (C) 1998-1999 Andrzej Krzysztofowicz, Author and Maintainer 1562306a36Sopenharmony_ci * Copyright (C) 1998-2000 Andre Hedrick <andre@linux-ide.org> 1662306a36Sopenharmony_ci * Copyright (C) 2003 Red Hat Inc 1762306a36Sopenharmony_ci * 1862306a36Sopenharmony_ci * libata documentation is available via 'make {ps|pdf}docs', 1962306a36Sopenharmony_ci * as Documentation/driver-api/libata.rst 2062306a36Sopenharmony_ci * 2162306a36Sopenharmony_ci * Hardware documentation available at http://developer.intel.com/ 2262306a36Sopenharmony_ci * 2362306a36Sopenharmony_ci * Documentation 2462306a36Sopenharmony_ci * Publicly available from Intel web site. Errata documentation 2562306a36Sopenharmony_ci * is also publicly available. As an aide to anyone hacking on this 2662306a36Sopenharmony_ci * driver the list of errata that are relevant is below, going back to 2762306a36Sopenharmony_ci * PIIX4. Older device documentation is now a bit tricky to find. 2862306a36Sopenharmony_ci * 2962306a36Sopenharmony_ci * The chipsets all follow very much the same design. The original Triton 3062306a36Sopenharmony_ci * series chipsets do _not_ support independent device timings, but this 3162306a36Sopenharmony_ci * is fixed in Triton II. With the odd mobile exception the chips then 3262306a36Sopenharmony_ci * change little except in gaining more modes until SATA arrives. This 3362306a36Sopenharmony_ci * driver supports only the chips with independent timing (that is those 3462306a36Sopenharmony_ci * with SITRE and the 0x44 timing register). See pata_oldpiix and pata_mpiix 3562306a36Sopenharmony_ci * for the early chip drivers. 3662306a36Sopenharmony_ci * 3762306a36Sopenharmony_ci * Errata of note: 3862306a36Sopenharmony_ci * 3962306a36Sopenharmony_ci * Unfixable 4062306a36Sopenharmony_ci * PIIX4 errata #9 - Only on ultra obscure hw 4162306a36Sopenharmony_ci * ICH3 errata #13 - Not observed to affect real hw 4262306a36Sopenharmony_ci * by Intel 4362306a36Sopenharmony_ci * 4462306a36Sopenharmony_ci * Things we must deal with 4562306a36Sopenharmony_ci * PIIX4 errata #10 - BM IDE hang with non UDMA 4662306a36Sopenharmony_ci * (must stop/start dma to recover) 4762306a36Sopenharmony_ci * 440MX errata #15 - As PIIX4 errata #10 4862306a36Sopenharmony_ci * PIIX4 errata #15 - Must not read control registers 4962306a36Sopenharmony_ci * during a PIO transfer 5062306a36Sopenharmony_ci * 440MX errata #13 - As PIIX4 errata #15 5162306a36Sopenharmony_ci * ICH2 errata #21 - DMA mode 0 doesn't work right 5262306a36Sopenharmony_ci * ICH0/1 errata #55 - As ICH2 errata #21 5362306a36Sopenharmony_ci * ICH2 spec c #9 - Extra operations needed to handle 5462306a36Sopenharmony_ci * drive hotswap [NOT YET SUPPORTED] 5562306a36Sopenharmony_ci * ICH2 spec c #20 - IDE PRD must not cross a 64K boundary 5662306a36Sopenharmony_ci * and must be dword aligned 5762306a36Sopenharmony_ci * ICH2 spec c #24 - UDMA mode 4,5 t85/86 should be 6ns not 3.3 5862306a36Sopenharmony_ci * ICH7 errata #16 - MWDMA1 timings are incorrect 5962306a36Sopenharmony_ci * 6062306a36Sopenharmony_ci * Should have been BIOS fixed: 6162306a36Sopenharmony_ci * 450NX: errata #19 - DMA hangs on old 450NX 6262306a36Sopenharmony_ci * 450NX: errata #20 - DMA hangs on old 450NX 6362306a36Sopenharmony_ci * 450NX: errata #25 - Corruption with DMA on old 450NX 6462306a36Sopenharmony_ci * ICH3 errata #15 - IDE deadlock under high load 6562306a36Sopenharmony_ci * (BIOS must set dev 31 fn 0 bit 23) 6662306a36Sopenharmony_ci * ICH3 errata #18 - Don't use native mode 6762306a36Sopenharmony_ci */ 6862306a36Sopenharmony_ci 6962306a36Sopenharmony_ci#include <linux/kernel.h> 7062306a36Sopenharmony_ci#include <linux/module.h> 7162306a36Sopenharmony_ci#include <linux/pci.h> 7262306a36Sopenharmony_ci#include <linux/init.h> 7362306a36Sopenharmony_ci#include <linux/blkdev.h> 7462306a36Sopenharmony_ci#include <linux/delay.h> 7562306a36Sopenharmony_ci#include <linux/device.h> 7662306a36Sopenharmony_ci#include <linux/gfp.h> 7762306a36Sopenharmony_ci#include <scsi/scsi_host.h> 7862306a36Sopenharmony_ci#include <linux/libata.h> 7962306a36Sopenharmony_ci#include <linux/dmi.h> 8062306a36Sopenharmony_ci#include <trace/events/libata.h> 8162306a36Sopenharmony_ci 8262306a36Sopenharmony_ci#define DRV_NAME "ata_piix" 8362306a36Sopenharmony_ci#define DRV_VERSION "2.13" 8462306a36Sopenharmony_ci 8562306a36Sopenharmony_cienum { 8662306a36Sopenharmony_ci PIIX_IOCFG = 0x54, /* IDE I/O configuration register */ 8762306a36Sopenharmony_ci ICH5_PMR = 0x90, /* address map register */ 8862306a36Sopenharmony_ci ICH5_PCS = 0x92, /* port control and status */ 8962306a36Sopenharmony_ci PIIX_SIDPR_BAR = 5, 9062306a36Sopenharmony_ci PIIX_SIDPR_LEN = 16, 9162306a36Sopenharmony_ci PIIX_SIDPR_IDX = 0, 9262306a36Sopenharmony_ci PIIX_SIDPR_DATA = 4, 9362306a36Sopenharmony_ci 9462306a36Sopenharmony_ci PIIX_FLAG_CHECKINTR = (1 << 28), /* make sure PCI INTx enabled */ 9562306a36Sopenharmony_ci PIIX_FLAG_SIDPR = (1 << 29), /* SATA idx/data pair regs */ 9662306a36Sopenharmony_ci 9762306a36Sopenharmony_ci PIIX_PATA_FLAGS = ATA_FLAG_SLAVE_POSS, 9862306a36Sopenharmony_ci PIIX_SATA_FLAGS = ATA_FLAG_SATA | PIIX_FLAG_CHECKINTR, 9962306a36Sopenharmony_ci 10062306a36Sopenharmony_ci PIIX_FLAG_PIO16 = (1 << 30), /*support 16bit PIO only*/ 10162306a36Sopenharmony_ci 10262306a36Sopenharmony_ci PIIX_80C_PRI = (1 << 5) | (1 << 4), 10362306a36Sopenharmony_ci PIIX_80C_SEC = (1 << 7) | (1 << 6), 10462306a36Sopenharmony_ci 10562306a36Sopenharmony_ci /* constants for mapping table */ 10662306a36Sopenharmony_ci P0 = 0, /* port 0 */ 10762306a36Sopenharmony_ci P1 = 1, /* port 1 */ 10862306a36Sopenharmony_ci P2 = 2, /* port 2 */ 10962306a36Sopenharmony_ci P3 = 3, /* port 3 */ 11062306a36Sopenharmony_ci IDE = -1, /* IDE */ 11162306a36Sopenharmony_ci NA = -2, /* not available */ 11262306a36Sopenharmony_ci RV = -3, /* reserved */ 11362306a36Sopenharmony_ci 11462306a36Sopenharmony_ci PIIX_AHCI_DEVICE = 6, 11562306a36Sopenharmony_ci 11662306a36Sopenharmony_ci /* host->flags bits */ 11762306a36Sopenharmony_ci PIIX_HOST_BROKEN_SUSPEND = (1 << 24), 11862306a36Sopenharmony_ci}; 11962306a36Sopenharmony_ci 12062306a36Sopenharmony_cienum piix_controller_ids { 12162306a36Sopenharmony_ci /* controller IDs */ 12262306a36Sopenharmony_ci piix_pata_mwdma, /* PIIX3 MWDMA only */ 12362306a36Sopenharmony_ci piix_pata_33, /* PIIX4 at 33Mhz */ 12462306a36Sopenharmony_ci ich_pata_33, /* ICH up to UDMA 33 only */ 12562306a36Sopenharmony_ci ich_pata_66, /* ICH up to 66 Mhz */ 12662306a36Sopenharmony_ci ich_pata_100, /* ICH up to UDMA 100 */ 12762306a36Sopenharmony_ci ich_pata_100_nomwdma1, /* ICH up to UDMA 100 but with no MWDMA1*/ 12862306a36Sopenharmony_ci ich5_sata, 12962306a36Sopenharmony_ci ich6_sata, 13062306a36Sopenharmony_ci ich6m_sata, 13162306a36Sopenharmony_ci ich8_sata, 13262306a36Sopenharmony_ci ich8_2port_sata, 13362306a36Sopenharmony_ci ich8m_apple_sata, /* locks up on second port enable */ 13462306a36Sopenharmony_ci tolapai_sata, 13562306a36Sopenharmony_ci piix_pata_vmw, /* PIIX4 for VMware, spurious DMA_ERR */ 13662306a36Sopenharmony_ci ich8_sata_snb, 13762306a36Sopenharmony_ci ich8_2port_sata_snb, 13862306a36Sopenharmony_ci ich8_2port_sata_byt, 13962306a36Sopenharmony_ci}; 14062306a36Sopenharmony_ci 14162306a36Sopenharmony_cistruct piix_map_db { 14262306a36Sopenharmony_ci const u32 mask; 14362306a36Sopenharmony_ci const u16 port_enable; 14462306a36Sopenharmony_ci const int map[][4]; 14562306a36Sopenharmony_ci}; 14662306a36Sopenharmony_ci 14762306a36Sopenharmony_cistruct piix_host_priv { 14862306a36Sopenharmony_ci const int *map; 14962306a36Sopenharmony_ci u32 saved_iocfg; 15062306a36Sopenharmony_ci void __iomem *sidpr; 15162306a36Sopenharmony_ci}; 15262306a36Sopenharmony_ci 15362306a36Sopenharmony_cistatic unsigned int in_module_init = 1; 15462306a36Sopenharmony_ci 15562306a36Sopenharmony_cistatic const struct pci_device_id piix_pci_tbl[] = { 15662306a36Sopenharmony_ci /* Intel PIIX3 for the 430HX etc */ 15762306a36Sopenharmony_ci { 0x8086, 0x7010, PCI_ANY_ID, PCI_ANY_ID, 0, 0, piix_pata_mwdma }, 15862306a36Sopenharmony_ci /* VMware ICH4 */ 15962306a36Sopenharmony_ci { 0x8086, 0x7111, 0x15ad, 0x1976, 0, 0, piix_pata_vmw }, 16062306a36Sopenharmony_ci /* Intel PIIX4 for the 430TX/440BX/MX chipset: UDMA 33 */ 16162306a36Sopenharmony_ci /* Also PIIX4E (fn3 rev 2) and PIIX4M (fn3 rev 3) */ 16262306a36Sopenharmony_ci { 0x8086, 0x7111, PCI_ANY_ID, PCI_ANY_ID, 0, 0, piix_pata_33 }, 16362306a36Sopenharmony_ci /* Intel PIIX4 */ 16462306a36Sopenharmony_ci { 0x8086, 0x7199, PCI_ANY_ID, PCI_ANY_ID, 0, 0, piix_pata_33 }, 16562306a36Sopenharmony_ci /* Intel PIIX4 */ 16662306a36Sopenharmony_ci { 0x8086, 0x7601, PCI_ANY_ID, PCI_ANY_ID, 0, 0, piix_pata_33 }, 16762306a36Sopenharmony_ci /* Intel PIIX */ 16862306a36Sopenharmony_ci { 0x8086, 0x84CA, PCI_ANY_ID, PCI_ANY_ID, 0, 0, piix_pata_33 }, 16962306a36Sopenharmony_ci /* Intel ICH (i810, i815, i840) UDMA 66*/ 17062306a36Sopenharmony_ci { 0x8086, 0x2411, PCI_ANY_ID, PCI_ANY_ID, 0, 0, ich_pata_66 }, 17162306a36Sopenharmony_ci /* Intel ICH0 : UDMA 33*/ 17262306a36Sopenharmony_ci { 0x8086, 0x2421, PCI_ANY_ID, PCI_ANY_ID, 0, 0, ich_pata_33 }, 17362306a36Sopenharmony_ci /* Intel ICH2M */ 17462306a36Sopenharmony_ci { 0x8086, 0x244A, PCI_ANY_ID, PCI_ANY_ID, 0, 0, ich_pata_100 }, 17562306a36Sopenharmony_ci /* Intel ICH2 (i810E2, i845, 850, 860) UDMA 100 */ 17662306a36Sopenharmony_ci { 0x8086, 0x244B, PCI_ANY_ID, PCI_ANY_ID, 0, 0, ich_pata_100 }, 17762306a36Sopenharmony_ci /* Intel ICH3M */ 17862306a36Sopenharmony_ci { 0x8086, 0x248A, PCI_ANY_ID, PCI_ANY_ID, 0, 0, ich_pata_100 }, 17962306a36Sopenharmony_ci /* Intel ICH3 (E7500/1) UDMA 100 */ 18062306a36Sopenharmony_ci { 0x8086, 0x248B, PCI_ANY_ID, PCI_ANY_ID, 0, 0, ich_pata_100 }, 18162306a36Sopenharmony_ci /* Intel ICH4-L */ 18262306a36Sopenharmony_ci { 0x8086, 0x24C1, PCI_ANY_ID, PCI_ANY_ID, 0, 0, ich_pata_100 }, 18362306a36Sopenharmony_ci /* Intel ICH4 (i845GV, i845E, i852, i855) UDMA 100 */ 18462306a36Sopenharmony_ci { 0x8086, 0x24CA, PCI_ANY_ID, PCI_ANY_ID, 0, 0, ich_pata_100 }, 18562306a36Sopenharmony_ci { 0x8086, 0x24CB, PCI_ANY_ID, PCI_ANY_ID, 0, 0, ich_pata_100 }, 18662306a36Sopenharmony_ci /* Intel ICH5 */ 18762306a36Sopenharmony_ci { 0x8086, 0x24DB, PCI_ANY_ID, PCI_ANY_ID, 0, 0, ich_pata_100 }, 18862306a36Sopenharmony_ci /* C-ICH (i810E2) */ 18962306a36Sopenharmony_ci { 0x8086, 0x245B, PCI_ANY_ID, PCI_ANY_ID, 0, 0, ich_pata_100 }, 19062306a36Sopenharmony_ci /* ESB (855GME/875P + 6300ESB) UDMA 100 */ 19162306a36Sopenharmony_ci { 0x8086, 0x25A2, PCI_ANY_ID, PCI_ANY_ID, 0, 0, ich_pata_100 }, 19262306a36Sopenharmony_ci /* ICH6 (and 6) (i915) UDMA 100 */ 19362306a36Sopenharmony_ci { 0x8086, 0x266F, PCI_ANY_ID, PCI_ANY_ID, 0, 0, ich_pata_100 }, 19462306a36Sopenharmony_ci /* ICH7/7-R (i945, i975) UDMA 100*/ 19562306a36Sopenharmony_ci { 0x8086, 0x27DF, PCI_ANY_ID, PCI_ANY_ID, 0, 0, ich_pata_100_nomwdma1 }, 19662306a36Sopenharmony_ci { 0x8086, 0x269E, PCI_ANY_ID, PCI_ANY_ID, 0, 0, ich_pata_100_nomwdma1 }, 19762306a36Sopenharmony_ci /* ICH8 Mobile PATA Controller */ 19862306a36Sopenharmony_ci { 0x8086, 0x2850, PCI_ANY_ID, PCI_ANY_ID, 0, 0, ich_pata_100 }, 19962306a36Sopenharmony_ci 20062306a36Sopenharmony_ci /* SATA ports */ 20162306a36Sopenharmony_ci 20262306a36Sopenharmony_ci /* 82801EB (ICH5) */ 20362306a36Sopenharmony_ci { 0x8086, 0x24d1, PCI_ANY_ID, PCI_ANY_ID, 0, 0, ich5_sata }, 20462306a36Sopenharmony_ci /* 82801EB (ICH5) */ 20562306a36Sopenharmony_ci { 0x8086, 0x24df, PCI_ANY_ID, PCI_ANY_ID, 0, 0, ich5_sata }, 20662306a36Sopenharmony_ci /* 6300ESB (ICH5 variant with broken PCS present bits) */ 20762306a36Sopenharmony_ci { 0x8086, 0x25a3, PCI_ANY_ID, PCI_ANY_ID, 0, 0, ich5_sata }, 20862306a36Sopenharmony_ci /* 6300ESB pretending RAID */ 20962306a36Sopenharmony_ci { 0x8086, 0x25b0, PCI_ANY_ID, PCI_ANY_ID, 0, 0, ich5_sata }, 21062306a36Sopenharmony_ci /* 82801FB/FW (ICH6/ICH6W) */ 21162306a36Sopenharmony_ci { 0x8086, 0x2651, PCI_ANY_ID, PCI_ANY_ID, 0, 0, ich6_sata }, 21262306a36Sopenharmony_ci /* 82801FR/FRW (ICH6R/ICH6RW) */ 21362306a36Sopenharmony_ci { 0x8086, 0x2652, PCI_ANY_ID, PCI_ANY_ID, 0, 0, ich6_sata }, 21462306a36Sopenharmony_ci /* 82801FBM ICH6M (ICH6R with only port 0 and 2 implemented). 21562306a36Sopenharmony_ci * Attach iff the controller is in IDE mode. */ 21662306a36Sopenharmony_ci { 0x8086, 0x2653, PCI_ANY_ID, PCI_ANY_ID, 21762306a36Sopenharmony_ci PCI_CLASS_STORAGE_IDE << 8, 0xffff00, ich6m_sata }, 21862306a36Sopenharmony_ci /* 82801GB/GR/GH (ICH7, identical to ICH6) */ 21962306a36Sopenharmony_ci { 0x8086, 0x27c0, PCI_ANY_ID, PCI_ANY_ID, 0, 0, ich6_sata }, 22062306a36Sopenharmony_ci /* 82801GBM/GHM (ICH7M, identical to ICH6M) */ 22162306a36Sopenharmony_ci { 0x8086, 0x27c4, PCI_ANY_ID, PCI_ANY_ID, 0, 0, ich6m_sata }, 22262306a36Sopenharmony_ci /* Enterprise Southbridge 2 (631xESB/632xESB) */ 22362306a36Sopenharmony_ci { 0x8086, 0x2680, PCI_ANY_ID, PCI_ANY_ID, 0, 0, ich6_sata }, 22462306a36Sopenharmony_ci /* SATA Controller 1 IDE (ICH8) */ 22562306a36Sopenharmony_ci { 0x8086, 0x2820, PCI_ANY_ID, PCI_ANY_ID, 0, 0, ich8_sata }, 22662306a36Sopenharmony_ci /* SATA Controller 2 IDE (ICH8) */ 22762306a36Sopenharmony_ci { 0x8086, 0x2825, PCI_ANY_ID, PCI_ANY_ID, 0, 0, ich8_2port_sata }, 22862306a36Sopenharmony_ci /* Mobile SATA Controller IDE (ICH8M), Apple */ 22962306a36Sopenharmony_ci { 0x8086, 0x2828, 0x106b, 0x00a0, 0, 0, ich8m_apple_sata }, 23062306a36Sopenharmony_ci { 0x8086, 0x2828, 0x106b, 0x00a1, 0, 0, ich8m_apple_sata }, 23162306a36Sopenharmony_ci { 0x8086, 0x2828, 0x106b, 0x00a3, 0, 0, ich8m_apple_sata }, 23262306a36Sopenharmony_ci /* Mobile SATA Controller IDE (ICH8M) */ 23362306a36Sopenharmony_ci { 0x8086, 0x2828, PCI_ANY_ID, PCI_ANY_ID, 0, 0, ich8_sata }, 23462306a36Sopenharmony_ci /* SATA Controller IDE (ICH9) */ 23562306a36Sopenharmony_ci { 0x8086, 0x2920, PCI_ANY_ID, PCI_ANY_ID, 0, 0, ich8_sata }, 23662306a36Sopenharmony_ci /* SATA Controller IDE (ICH9) */ 23762306a36Sopenharmony_ci { 0x8086, 0x2921, PCI_ANY_ID, PCI_ANY_ID, 0, 0, ich8_2port_sata }, 23862306a36Sopenharmony_ci /* SATA Controller IDE (ICH9) */ 23962306a36Sopenharmony_ci { 0x8086, 0x2926, PCI_ANY_ID, PCI_ANY_ID, 0, 0, ich8_2port_sata }, 24062306a36Sopenharmony_ci /* SATA Controller IDE (ICH9M) */ 24162306a36Sopenharmony_ci { 0x8086, 0x2928, PCI_ANY_ID, PCI_ANY_ID, 0, 0, ich8_2port_sata }, 24262306a36Sopenharmony_ci /* SATA Controller IDE (ICH9M) */ 24362306a36Sopenharmony_ci { 0x8086, 0x292d, PCI_ANY_ID, PCI_ANY_ID, 0, 0, ich8_2port_sata }, 24462306a36Sopenharmony_ci /* SATA Controller IDE (ICH9M) */ 24562306a36Sopenharmony_ci { 0x8086, 0x292e, PCI_ANY_ID, PCI_ANY_ID, 0, 0, ich8_sata }, 24662306a36Sopenharmony_ci /* SATA Controller IDE (Tolapai) */ 24762306a36Sopenharmony_ci { 0x8086, 0x5028, PCI_ANY_ID, PCI_ANY_ID, 0, 0, tolapai_sata }, 24862306a36Sopenharmony_ci /* SATA Controller IDE (ICH10) */ 24962306a36Sopenharmony_ci { 0x8086, 0x3a00, PCI_ANY_ID, PCI_ANY_ID, 0, 0, ich8_sata }, 25062306a36Sopenharmony_ci /* SATA Controller IDE (ICH10) */ 25162306a36Sopenharmony_ci { 0x8086, 0x3a06, PCI_ANY_ID, PCI_ANY_ID, 0, 0, ich8_2port_sata }, 25262306a36Sopenharmony_ci /* SATA Controller IDE (ICH10) */ 25362306a36Sopenharmony_ci { 0x8086, 0x3a20, PCI_ANY_ID, PCI_ANY_ID, 0, 0, ich8_sata }, 25462306a36Sopenharmony_ci /* SATA Controller IDE (ICH10) */ 25562306a36Sopenharmony_ci { 0x8086, 0x3a26, PCI_ANY_ID, PCI_ANY_ID, 0, 0, ich8_2port_sata }, 25662306a36Sopenharmony_ci /* SATA Controller IDE (PCH) */ 25762306a36Sopenharmony_ci { 0x8086, 0x3b20, PCI_ANY_ID, PCI_ANY_ID, 0, 0, ich8_sata }, 25862306a36Sopenharmony_ci /* SATA Controller IDE (PCH) */ 25962306a36Sopenharmony_ci { 0x8086, 0x3b21, PCI_ANY_ID, PCI_ANY_ID, 0, 0, ich8_2port_sata }, 26062306a36Sopenharmony_ci /* SATA Controller IDE (PCH) */ 26162306a36Sopenharmony_ci { 0x8086, 0x3b26, PCI_ANY_ID, PCI_ANY_ID, 0, 0, ich8_2port_sata }, 26262306a36Sopenharmony_ci /* SATA Controller IDE (PCH) */ 26362306a36Sopenharmony_ci { 0x8086, 0x3b28, PCI_ANY_ID, PCI_ANY_ID, 0, 0, ich8_sata }, 26462306a36Sopenharmony_ci /* SATA Controller IDE (PCH) */ 26562306a36Sopenharmony_ci { 0x8086, 0x3b2d, PCI_ANY_ID, PCI_ANY_ID, 0, 0, ich8_2port_sata }, 26662306a36Sopenharmony_ci /* SATA Controller IDE (PCH) */ 26762306a36Sopenharmony_ci { 0x8086, 0x3b2e, PCI_ANY_ID, PCI_ANY_ID, 0, 0, ich8_sata }, 26862306a36Sopenharmony_ci /* SATA Controller IDE (CPT) */ 26962306a36Sopenharmony_ci { 0x8086, 0x1c00, PCI_ANY_ID, PCI_ANY_ID, 0, 0, ich8_sata_snb }, 27062306a36Sopenharmony_ci /* SATA Controller IDE (CPT) */ 27162306a36Sopenharmony_ci { 0x8086, 0x1c01, PCI_ANY_ID, PCI_ANY_ID, 0, 0, ich8_sata_snb }, 27262306a36Sopenharmony_ci /* SATA Controller IDE (CPT) */ 27362306a36Sopenharmony_ci { 0x8086, 0x1c08, PCI_ANY_ID, PCI_ANY_ID, 0, 0, ich8_2port_sata }, 27462306a36Sopenharmony_ci /* SATA Controller IDE (CPT) */ 27562306a36Sopenharmony_ci { 0x8086, 0x1c09, PCI_ANY_ID, PCI_ANY_ID, 0, 0, ich8_2port_sata }, 27662306a36Sopenharmony_ci /* SATA Controller IDE (PBG) */ 27762306a36Sopenharmony_ci { 0x8086, 0x1d00, PCI_ANY_ID, PCI_ANY_ID, 0, 0, ich8_sata_snb }, 27862306a36Sopenharmony_ci /* SATA Controller IDE (PBG) */ 27962306a36Sopenharmony_ci { 0x8086, 0x1d08, PCI_ANY_ID, PCI_ANY_ID, 0, 0, ich8_2port_sata }, 28062306a36Sopenharmony_ci /* SATA Controller IDE (Panther Point) */ 28162306a36Sopenharmony_ci { 0x8086, 0x1e00, PCI_ANY_ID, PCI_ANY_ID, 0, 0, ich8_sata_snb }, 28262306a36Sopenharmony_ci /* SATA Controller IDE (Panther Point) */ 28362306a36Sopenharmony_ci { 0x8086, 0x1e01, PCI_ANY_ID, PCI_ANY_ID, 0, 0, ich8_sata_snb }, 28462306a36Sopenharmony_ci /* SATA Controller IDE (Panther Point) */ 28562306a36Sopenharmony_ci { 0x8086, 0x1e08, PCI_ANY_ID, PCI_ANY_ID, 0, 0, ich8_2port_sata }, 28662306a36Sopenharmony_ci /* SATA Controller IDE (Panther Point) */ 28762306a36Sopenharmony_ci { 0x8086, 0x1e09, PCI_ANY_ID, PCI_ANY_ID, 0, 0, ich8_2port_sata }, 28862306a36Sopenharmony_ci /* SATA Controller IDE (Lynx Point) */ 28962306a36Sopenharmony_ci { 0x8086, 0x8c00, PCI_ANY_ID, PCI_ANY_ID, 0, 0, ich8_sata_snb }, 29062306a36Sopenharmony_ci /* SATA Controller IDE (Lynx Point) */ 29162306a36Sopenharmony_ci { 0x8086, 0x8c01, PCI_ANY_ID, PCI_ANY_ID, 0, 0, ich8_sata_snb }, 29262306a36Sopenharmony_ci /* SATA Controller IDE (Lynx Point) */ 29362306a36Sopenharmony_ci { 0x8086, 0x8c08, PCI_ANY_ID, PCI_ANY_ID, 0, 0, ich8_2port_sata_snb }, 29462306a36Sopenharmony_ci /* SATA Controller IDE (Lynx Point) */ 29562306a36Sopenharmony_ci { 0x8086, 0x8c09, PCI_ANY_ID, PCI_ANY_ID, 0, 0, ich8_2port_sata }, 29662306a36Sopenharmony_ci /* SATA Controller IDE (Lynx Point-LP) */ 29762306a36Sopenharmony_ci { 0x8086, 0x9c00, PCI_ANY_ID, PCI_ANY_ID, 0, 0, ich8_sata_snb }, 29862306a36Sopenharmony_ci /* SATA Controller IDE (Lynx Point-LP) */ 29962306a36Sopenharmony_ci { 0x8086, 0x9c01, PCI_ANY_ID, PCI_ANY_ID, 0, 0, ich8_sata_snb }, 30062306a36Sopenharmony_ci /* SATA Controller IDE (Lynx Point-LP) */ 30162306a36Sopenharmony_ci { 0x8086, 0x9c08, PCI_ANY_ID, PCI_ANY_ID, 0, 0, ich8_2port_sata }, 30262306a36Sopenharmony_ci /* SATA Controller IDE (Lynx Point-LP) */ 30362306a36Sopenharmony_ci { 0x8086, 0x9c09, PCI_ANY_ID, PCI_ANY_ID, 0, 0, ich8_2port_sata }, 30462306a36Sopenharmony_ci /* SATA Controller IDE (DH89xxCC) */ 30562306a36Sopenharmony_ci { 0x8086, 0x2326, PCI_ANY_ID, PCI_ANY_ID, 0, 0, ich8_2port_sata }, 30662306a36Sopenharmony_ci /* SATA Controller IDE (Avoton) */ 30762306a36Sopenharmony_ci { 0x8086, 0x1f20, PCI_ANY_ID, PCI_ANY_ID, 0, 0, ich8_sata_snb }, 30862306a36Sopenharmony_ci /* SATA Controller IDE (Avoton) */ 30962306a36Sopenharmony_ci { 0x8086, 0x1f21, PCI_ANY_ID, PCI_ANY_ID, 0, 0, ich8_sata_snb }, 31062306a36Sopenharmony_ci /* SATA Controller IDE (Avoton) */ 31162306a36Sopenharmony_ci { 0x8086, 0x1f30, PCI_ANY_ID, PCI_ANY_ID, 0, 0, ich8_2port_sata }, 31262306a36Sopenharmony_ci /* SATA Controller IDE (Avoton) */ 31362306a36Sopenharmony_ci { 0x8086, 0x1f31, PCI_ANY_ID, PCI_ANY_ID, 0, 0, ich8_2port_sata }, 31462306a36Sopenharmony_ci /* SATA Controller IDE (Wellsburg) */ 31562306a36Sopenharmony_ci { 0x8086, 0x8d00, PCI_ANY_ID, PCI_ANY_ID, 0, 0, ich8_sata_snb }, 31662306a36Sopenharmony_ci /* SATA Controller IDE (Wellsburg) */ 31762306a36Sopenharmony_ci { 0x8086, 0x8d08, PCI_ANY_ID, PCI_ANY_ID, 0, 0, ich8_2port_sata_snb }, 31862306a36Sopenharmony_ci /* SATA Controller IDE (Wellsburg) */ 31962306a36Sopenharmony_ci { 0x8086, 0x8d60, PCI_ANY_ID, PCI_ANY_ID, 0, 0, ich8_sata_snb }, 32062306a36Sopenharmony_ci /* SATA Controller IDE (Wellsburg) */ 32162306a36Sopenharmony_ci { 0x8086, 0x8d68, PCI_ANY_ID, PCI_ANY_ID, 0, 0, ich8_2port_sata }, 32262306a36Sopenharmony_ci /* SATA Controller IDE (BayTrail) */ 32362306a36Sopenharmony_ci { 0x8086, 0x0F20, PCI_ANY_ID, PCI_ANY_ID, 0, 0, ich8_2port_sata_byt }, 32462306a36Sopenharmony_ci { 0x8086, 0x0F21, PCI_ANY_ID, PCI_ANY_ID, 0, 0, ich8_2port_sata_byt }, 32562306a36Sopenharmony_ci /* SATA Controller IDE (Coleto Creek) */ 32662306a36Sopenharmony_ci { 0x8086, 0x23a6, PCI_ANY_ID, PCI_ANY_ID, 0, 0, ich8_2port_sata }, 32762306a36Sopenharmony_ci /* SATA Controller IDE (9 Series) */ 32862306a36Sopenharmony_ci { 0x8086, 0x8c88, PCI_ANY_ID, PCI_ANY_ID, 0, 0, ich8_2port_sata_snb }, 32962306a36Sopenharmony_ci /* SATA Controller IDE (9 Series) */ 33062306a36Sopenharmony_ci { 0x8086, 0x8c89, PCI_ANY_ID, PCI_ANY_ID, 0, 0, ich8_2port_sata_snb }, 33162306a36Sopenharmony_ci /* SATA Controller IDE (9 Series) */ 33262306a36Sopenharmony_ci { 0x8086, 0x8c80, PCI_ANY_ID, PCI_ANY_ID, 0, 0, ich8_sata_snb }, 33362306a36Sopenharmony_ci /* SATA Controller IDE (9 Series) */ 33462306a36Sopenharmony_ci { 0x8086, 0x8c81, PCI_ANY_ID, PCI_ANY_ID, 0, 0, ich8_sata_snb }, 33562306a36Sopenharmony_ci 33662306a36Sopenharmony_ci { } /* terminate list */ 33762306a36Sopenharmony_ci}; 33862306a36Sopenharmony_ci 33962306a36Sopenharmony_cistatic const struct piix_map_db ich5_map_db = { 34062306a36Sopenharmony_ci .mask = 0x7, 34162306a36Sopenharmony_ci .port_enable = 0x3, 34262306a36Sopenharmony_ci .map = { 34362306a36Sopenharmony_ci /* PM PS SM SS MAP */ 34462306a36Sopenharmony_ci { P0, NA, P1, NA }, /* 000b */ 34562306a36Sopenharmony_ci { P1, NA, P0, NA }, /* 001b */ 34662306a36Sopenharmony_ci { RV, RV, RV, RV }, 34762306a36Sopenharmony_ci { RV, RV, RV, RV }, 34862306a36Sopenharmony_ci { P0, P1, IDE, IDE }, /* 100b */ 34962306a36Sopenharmony_ci { P1, P0, IDE, IDE }, /* 101b */ 35062306a36Sopenharmony_ci { IDE, IDE, P0, P1 }, /* 110b */ 35162306a36Sopenharmony_ci { IDE, IDE, P1, P0 }, /* 111b */ 35262306a36Sopenharmony_ci }, 35362306a36Sopenharmony_ci}; 35462306a36Sopenharmony_ci 35562306a36Sopenharmony_cistatic const struct piix_map_db ich6_map_db = { 35662306a36Sopenharmony_ci .mask = 0x3, 35762306a36Sopenharmony_ci .port_enable = 0xf, 35862306a36Sopenharmony_ci .map = { 35962306a36Sopenharmony_ci /* PM PS SM SS MAP */ 36062306a36Sopenharmony_ci { P0, P2, P1, P3 }, /* 00b */ 36162306a36Sopenharmony_ci { IDE, IDE, P1, P3 }, /* 01b */ 36262306a36Sopenharmony_ci { P0, P2, IDE, IDE }, /* 10b */ 36362306a36Sopenharmony_ci { RV, RV, RV, RV }, 36462306a36Sopenharmony_ci }, 36562306a36Sopenharmony_ci}; 36662306a36Sopenharmony_ci 36762306a36Sopenharmony_cistatic const struct piix_map_db ich6m_map_db = { 36862306a36Sopenharmony_ci .mask = 0x3, 36962306a36Sopenharmony_ci .port_enable = 0x5, 37062306a36Sopenharmony_ci 37162306a36Sopenharmony_ci /* Map 01b isn't specified in the doc but some notebooks use 37262306a36Sopenharmony_ci * it anyway. MAP 01b have been spotted on both ICH6M and 37362306a36Sopenharmony_ci * ICH7M. 37462306a36Sopenharmony_ci */ 37562306a36Sopenharmony_ci .map = { 37662306a36Sopenharmony_ci /* PM PS SM SS MAP */ 37762306a36Sopenharmony_ci { P0, P2, NA, NA }, /* 00b */ 37862306a36Sopenharmony_ci { IDE, IDE, P1, P3 }, /* 01b */ 37962306a36Sopenharmony_ci { P0, P2, IDE, IDE }, /* 10b */ 38062306a36Sopenharmony_ci { RV, RV, RV, RV }, 38162306a36Sopenharmony_ci }, 38262306a36Sopenharmony_ci}; 38362306a36Sopenharmony_ci 38462306a36Sopenharmony_cistatic const struct piix_map_db ich8_map_db = { 38562306a36Sopenharmony_ci .mask = 0x3, 38662306a36Sopenharmony_ci .port_enable = 0xf, 38762306a36Sopenharmony_ci .map = { 38862306a36Sopenharmony_ci /* PM PS SM SS MAP */ 38962306a36Sopenharmony_ci { P0, P2, P1, P3 }, /* 00b (hardwired when in AHCI) */ 39062306a36Sopenharmony_ci { RV, RV, RV, RV }, 39162306a36Sopenharmony_ci { P0, P2, IDE, IDE }, /* 10b (IDE mode) */ 39262306a36Sopenharmony_ci { RV, RV, RV, RV }, 39362306a36Sopenharmony_ci }, 39462306a36Sopenharmony_ci}; 39562306a36Sopenharmony_ci 39662306a36Sopenharmony_cistatic const struct piix_map_db ich8_2port_map_db = { 39762306a36Sopenharmony_ci .mask = 0x3, 39862306a36Sopenharmony_ci .port_enable = 0x3, 39962306a36Sopenharmony_ci .map = { 40062306a36Sopenharmony_ci /* PM PS SM SS MAP */ 40162306a36Sopenharmony_ci { P0, NA, P1, NA }, /* 00b */ 40262306a36Sopenharmony_ci { RV, RV, RV, RV }, /* 01b */ 40362306a36Sopenharmony_ci { RV, RV, RV, RV }, /* 10b */ 40462306a36Sopenharmony_ci { RV, RV, RV, RV }, 40562306a36Sopenharmony_ci }, 40662306a36Sopenharmony_ci}; 40762306a36Sopenharmony_ci 40862306a36Sopenharmony_cistatic const struct piix_map_db ich8m_apple_map_db = { 40962306a36Sopenharmony_ci .mask = 0x3, 41062306a36Sopenharmony_ci .port_enable = 0x1, 41162306a36Sopenharmony_ci .map = { 41262306a36Sopenharmony_ci /* PM PS SM SS MAP */ 41362306a36Sopenharmony_ci { P0, NA, NA, NA }, /* 00b */ 41462306a36Sopenharmony_ci { RV, RV, RV, RV }, 41562306a36Sopenharmony_ci { P0, P2, IDE, IDE }, /* 10b */ 41662306a36Sopenharmony_ci { RV, RV, RV, RV }, 41762306a36Sopenharmony_ci }, 41862306a36Sopenharmony_ci}; 41962306a36Sopenharmony_ci 42062306a36Sopenharmony_cistatic const struct piix_map_db tolapai_map_db = { 42162306a36Sopenharmony_ci .mask = 0x3, 42262306a36Sopenharmony_ci .port_enable = 0x3, 42362306a36Sopenharmony_ci .map = { 42462306a36Sopenharmony_ci /* PM PS SM SS MAP */ 42562306a36Sopenharmony_ci { P0, NA, P1, NA }, /* 00b */ 42662306a36Sopenharmony_ci { RV, RV, RV, RV }, /* 01b */ 42762306a36Sopenharmony_ci { RV, RV, RV, RV }, /* 10b */ 42862306a36Sopenharmony_ci { RV, RV, RV, RV }, 42962306a36Sopenharmony_ci }, 43062306a36Sopenharmony_ci}; 43162306a36Sopenharmony_ci 43262306a36Sopenharmony_cistatic const struct piix_map_db *piix_map_db_table[] = { 43362306a36Sopenharmony_ci [ich5_sata] = &ich5_map_db, 43462306a36Sopenharmony_ci [ich6_sata] = &ich6_map_db, 43562306a36Sopenharmony_ci [ich6m_sata] = &ich6m_map_db, 43662306a36Sopenharmony_ci [ich8_sata] = &ich8_map_db, 43762306a36Sopenharmony_ci [ich8_2port_sata] = &ich8_2port_map_db, 43862306a36Sopenharmony_ci [ich8m_apple_sata] = &ich8m_apple_map_db, 43962306a36Sopenharmony_ci [tolapai_sata] = &tolapai_map_db, 44062306a36Sopenharmony_ci [ich8_sata_snb] = &ich8_map_db, 44162306a36Sopenharmony_ci [ich8_2port_sata_snb] = &ich8_2port_map_db, 44262306a36Sopenharmony_ci [ich8_2port_sata_byt] = &ich8_2port_map_db, 44362306a36Sopenharmony_ci}; 44462306a36Sopenharmony_ci 44562306a36Sopenharmony_cistatic const struct pci_bits piix_enable_bits[] = { 44662306a36Sopenharmony_ci { 0x41U, 1U, 0x80UL, 0x80UL }, /* port 0 */ 44762306a36Sopenharmony_ci { 0x43U, 1U, 0x80UL, 0x80UL }, /* port 1 */ 44862306a36Sopenharmony_ci}; 44962306a36Sopenharmony_ci 45062306a36Sopenharmony_ciMODULE_AUTHOR("Andre Hedrick, Alan Cox, Andrzej Krzysztofowicz, Jeff Garzik"); 45162306a36Sopenharmony_ciMODULE_DESCRIPTION("SCSI low-level driver for Intel PIIX/ICH ATA controllers"); 45262306a36Sopenharmony_ciMODULE_LICENSE("GPL"); 45362306a36Sopenharmony_ciMODULE_DEVICE_TABLE(pci, piix_pci_tbl); 45462306a36Sopenharmony_ciMODULE_VERSION(DRV_VERSION); 45562306a36Sopenharmony_ci 45662306a36Sopenharmony_cistruct ich_laptop { 45762306a36Sopenharmony_ci u16 device; 45862306a36Sopenharmony_ci u16 subvendor; 45962306a36Sopenharmony_ci u16 subdevice; 46062306a36Sopenharmony_ci}; 46162306a36Sopenharmony_ci 46262306a36Sopenharmony_ci/* 46362306a36Sopenharmony_ci * List of laptops that use short cables rather than 80 wire 46462306a36Sopenharmony_ci */ 46562306a36Sopenharmony_ci 46662306a36Sopenharmony_cistatic const struct ich_laptop ich_laptop[] = { 46762306a36Sopenharmony_ci /* devid, subvendor, subdev */ 46862306a36Sopenharmony_ci { 0x27DF, 0x0005, 0x0280 }, /* ICH7 on Acer 5602WLMi */ 46962306a36Sopenharmony_ci { 0x27DF, 0x1025, 0x0102 }, /* ICH7 on Acer 5602aWLMi */ 47062306a36Sopenharmony_ci { 0x27DF, 0x1025, 0x0110 }, /* ICH7 on Acer 3682WLMi */ 47162306a36Sopenharmony_ci { 0x27DF, 0x1028, 0x02b0 }, /* ICH7 on unknown Dell */ 47262306a36Sopenharmony_ci { 0x27DF, 0x1043, 0x1267 }, /* ICH7 on Asus W5F */ 47362306a36Sopenharmony_ci { 0x27DF, 0x103C, 0x30A1 }, /* ICH7 on HP Compaq nc2400 */ 47462306a36Sopenharmony_ci { 0x27DF, 0x103C, 0x361a }, /* ICH7 on unknown HP */ 47562306a36Sopenharmony_ci { 0x27DF, 0x1071, 0xD221 }, /* ICH7 on Hercules EC-900 */ 47662306a36Sopenharmony_ci { 0x27DF, 0x152D, 0x0778 }, /* ICH7 on unknown Intel */ 47762306a36Sopenharmony_ci { 0x24CA, 0x1025, 0x0061 }, /* ICH4 on ACER Aspire 2023WLMi */ 47862306a36Sopenharmony_ci { 0x24CA, 0x1025, 0x003d }, /* ICH4 on ACER TM290 */ 47962306a36Sopenharmony_ci { 0x24CA, 0x10CF, 0x11AB }, /* ICH4M on Fujitsu-Siemens Lifebook S6120 */ 48062306a36Sopenharmony_ci { 0x266F, 0x1025, 0x0066 }, /* ICH6 on ACER Aspire 1694WLMi */ 48162306a36Sopenharmony_ci { 0x2653, 0x1043, 0x82D8 }, /* ICH6M on Asus Eee 701 */ 48262306a36Sopenharmony_ci { 0x27df, 0x104d, 0x900e }, /* ICH7 on Sony TZ-90 */ 48362306a36Sopenharmony_ci /* end marker */ 48462306a36Sopenharmony_ci { 0, } 48562306a36Sopenharmony_ci}; 48662306a36Sopenharmony_ci 48762306a36Sopenharmony_cistatic int piix_port_start(struct ata_port *ap) 48862306a36Sopenharmony_ci{ 48962306a36Sopenharmony_ci if (!(ap->flags & PIIX_FLAG_PIO16)) 49062306a36Sopenharmony_ci ap->pflags |= ATA_PFLAG_PIO32 | ATA_PFLAG_PIO32CHANGE; 49162306a36Sopenharmony_ci 49262306a36Sopenharmony_ci return ata_bmdma_port_start(ap); 49362306a36Sopenharmony_ci} 49462306a36Sopenharmony_ci 49562306a36Sopenharmony_ci/** 49662306a36Sopenharmony_ci * ich_pata_cable_detect - Probe host controller cable detect info 49762306a36Sopenharmony_ci * @ap: Port for which cable detect info is desired 49862306a36Sopenharmony_ci * 49962306a36Sopenharmony_ci * Read 80c cable indicator from ATA PCI device's PCI config 50062306a36Sopenharmony_ci * register. This register is normally set by firmware (BIOS). 50162306a36Sopenharmony_ci * 50262306a36Sopenharmony_ci * LOCKING: 50362306a36Sopenharmony_ci * None (inherited from caller). 50462306a36Sopenharmony_ci */ 50562306a36Sopenharmony_ci 50662306a36Sopenharmony_cistatic int ich_pata_cable_detect(struct ata_port *ap) 50762306a36Sopenharmony_ci{ 50862306a36Sopenharmony_ci struct pci_dev *pdev = to_pci_dev(ap->host->dev); 50962306a36Sopenharmony_ci struct piix_host_priv *hpriv = ap->host->private_data; 51062306a36Sopenharmony_ci const struct ich_laptop *lap = &ich_laptop[0]; 51162306a36Sopenharmony_ci u8 mask; 51262306a36Sopenharmony_ci 51362306a36Sopenharmony_ci /* Check for specials */ 51462306a36Sopenharmony_ci while (lap->device) { 51562306a36Sopenharmony_ci if (lap->device == pdev->device && 51662306a36Sopenharmony_ci lap->subvendor == pdev->subsystem_vendor && 51762306a36Sopenharmony_ci lap->subdevice == pdev->subsystem_device) 51862306a36Sopenharmony_ci return ATA_CBL_PATA40_SHORT; 51962306a36Sopenharmony_ci 52062306a36Sopenharmony_ci lap++; 52162306a36Sopenharmony_ci } 52262306a36Sopenharmony_ci 52362306a36Sopenharmony_ci /* check BIOS cable detect results */ 52462306a36Sopenharmony_ci mask = ap->port_no == 0 ? PIIX_80C_PRI : PIIX_80C_SEC; 52562306a36Sopenharmony_ci if ((hpriv->saved_iocfg & mask) == 0) 52662306a36Sopenharmony_ci return ATA_CBL_PATA40; 52762306a36Sopenharmony_ci return ATA_CBL_PATA80; 52862306a36Sopenharmony_ci} 52962306a36Sopenharmony_ci 53062306a36Sopenharmony_ci/** 53162306a36Sopenharmony_ci * piix_pata_prereset - prereset for PATA host controller 53262306a36Sopenharmony_ci * @link: Target link 53362306a36Sopenharmony_ci * @deadline: deadline jiffies for the operation 53462306a36Sopenharmony_ci * 53562306a36Sopenharmony_ci * LOCKING: 53662306a36Sopenharmony_ci * None (inherited from caller). 53762306a36Sopenharmony_ci */ 53862306a36Sopenharmony_cistatic int piix_pata_prereset(struct ata_link *link, unsigned long deadline) 53962306a36Sopenharmony_ci{ 54062306a36Sopenharmony_ci struct ata_port *ap = link->ap; 54162306a36Sopenharmony_ci struct pci_dev *pdev = to_pci_dev(ap->host->dev); 54262306a36Sopenharmony_ci 54362306a36Sopenharmony_ci if (!pci_test_config_bits(pdev, &piix_enable_bits[ap->port_no])) 54462306a36Sopenharmony_ci return -ENOENT; 54562306a36Sopenharmony_ci return ata_sff_prereset(link, deadline); 54662306a36Sopenharmony_ci} 54762306a36Sopenharmony_ci 54862306a36Sopenharmony_cistatic DEFINE_SPINLOCK(piix_lock); 54962306a36Sopenharmony_ci 55062306a36Sopenharmony_cistatic void piix_set_timings(struct ata_port *ap, struct ata_device *adev, 55162306a36Sopenharmony_ci u8 pio) 55262306a36Sopenharmony_ci{ 55362306a36Sopenharmony_ci struct pci_dev *dev = to_pci_dev(ap->host->dev); 55462306a36Sopenharmony_ci unsigned long flags; 55562306a36Sopenharmony_ci unsigned int is_slave = (adev->devno != 0); 55662306a36Sopenharmony_ci unsigned int master_port= ap->port_no ? 0x42 : 0x40; 55762306a36Sopenharmony_ci unsigned int slave_port = 0x44; 55862306a36Sopenharmony_ci u16 master_data; 55962306a36Sopenharmony_ci u8 slave_data; 56062306a36Sopenharmony_ci u8 udma_enable; 56162306a36Sopenharmony_ci int control = 0; 56262306a36Sopenharmony_ci 56362306a36Sopenharmony_ci /* 56462306a36Sopenharmony_ci * See Intel Document 298600-004 for the timing programing rules 56562306a36Sopenharmony_ci * for ICH controllers. 56662306a36Sopenharmony_ci */ 56762306a36Sopenharmony_ci 56862306a36Sopenharmony_ci static const /* ISP RTC */ 56962306a36Sopenharmony_ci u8 timings[][2] = { { 0, 0 }, 57062306a36Sopenharmony_ci { 0, 0 }, 57162306a36Sopenharmony_ci { 1, 0 }, 57262306a36Sopenharmony_ci { 2, 1 }, 57362306a36Sopenharmony_ci { 2, 3 }, }; 57462306a36Sopenharmony_ci 57562306a36Sopenharmony_ci if (pio >= 2) 57662306a36Sopenharmony_ci control |= 1; /* TIME1 enable */ 57762306a36Sopenharmony_ci if (ata_pio_need_iordy(adev)) 57862306a36Sopenharmony_ci control |= 2; /* IE enable */ 57962306a36Sopenharmony_ci /* Intel specifies that the PPE functionality is for disk only */ 58062306a36Sopenharmony_ci if (adev->class == ATA_DEV_ATA) 58162306a36Sopenharmony_ci control |= 4; /* PPE enable */ 58262306a36Sopenharmony_ci /* 58362306a36Sopenharmony_ci * If the drive MWDMA is faster than it can do PIO then 58462306a36Sopenharmony_ci * we must force PIO into PIO0 58562306a36Sopenharmony_ci */ 58662306a36Sopenharmony_ci if (adev->pio_mode < XFER_PIO_0 + pio) 58762306a36Sopenharmony_ci /* Enable DMA timing only */ 58862306a36Sopenharmony_ci control |= 8; /* PIO cycles in PIO0 */ 58962306a36Sopenharmony_ci 59062306a36Sopenharmony_ci spin_lock_irqsave(&piix_lock, flags); 59162306a36Sopenharmony_ci 59262306a36Sopenharmony_ci /* PIO configuration clears DTE unconditionally. It will be 59362306a36Sopenharmony_ci * programmed in set_dmamode which is guaranteed to be called 59462306a36Sopenharmony_ci * after set_piomode if any DMA mode is available. 59562306a36Sopenharmony_ci */ 59662306a36Sopenharmony_ci pci_read_config_word(dev, master_port, &master_data); 59762306a36Sopenharmony_ci if (is_slave) { 59862306a36Sopenharmony_ci /* clear TIME1|IE1|PPE1|DTE1 */ 59962306a36Sopenharmony_ci master_data &= 0xff0f; 60062306a36Sopenharmony_ci /* enable PPE1, IE1 and TIME1 as needed */ 60162306a36Sopenharmony_ci master_data |= (control << 4); 60262306a36Sopenharmony_ci pci_read_config_byte(dev, slave_port, &slave_data); 60362306a36Sopenharmony_ci slave_data &= (ap->port_no ? 0x0f : 0xf0); 60462306a36Sopenharmony_ci /* Load the timing nibble for this slave */ 60562306a36Sopenharmony_ci slave_data |= ((timings[pio][0] << 2) | timings[pio][1]) 60662306a36Sopenharmony_ci << (ap->port_no ? 4 : 0); 60762306a36Sopenharmony_ci } else { 60862306a36Sopenharmony_ci /* clear ISP|RCT|TIME0|IE0|PPE0|DTE0 */ 60962306a36Sopenharmony_ci master_data &= 0xccf0; 61062306a36Sopenharmony_ci /* Enable PPE, IE and TIME as appropriate */ 61162306a36Sopenharmony_ci master_data |= control; 61262306a36Sopenharmony_ci /* load ISP and RCT */ 61362306a36Sopenharmony_ci master_data |= 61462306a36Sopenharmony_ci (timings[pio][0] << 12) | 61562306a36Sopenharmony_ci (timings[pio][1] << 8); 61662306a36Sopenharmony_ci } 61762306a36Sopenharmony_ci 61862306a36Sopenharmony_ci /* Enable SITRE (separate slave timing register) */ 61962306a36Sopenharmony_ci master_data |= 0x4000; 62062306a36Sopenharmony_ci pci_write_config_word(dev, master_port, master_data); 62162306a36Sopenharmony_ci if (is_slave) 62262306a36Sopenharmony_ci pci_write_config_byte(dev, slave_port, slave_data); 62362306a36Sopenharmony_ci 62462306a36Sopenharmony_ci /* Ensure the UDMA bit is off - it will be turned back on if 62562306a36Sopenharmony_ci UDMA is selected */ 62662306a36Sopenharmony_ci 62762306a36Sopenharmony_ci if (ap->udma_mask) { 62862306a36Sopenharmony_ci pci_read_config_byte(dev, 0x48, &udma_enable); 62962306a36Sopenharmony_ci udma_enable &= ~(1 << (2 * ap->port_no + adev->devno)); 63062306a36Sopenharmony_ci pci_write_config_byte(dev, 0x48, udma_enable); 63162306a36Sopenharmony_ci } 63262306a36Sopenharmony_ci 63362306a36Sopenharmony_ci spin_unlock_irqrestore(&piix_lock, flags); 63462306a36Sopenharmony_ci} 63562306a36Sopenharmony_ci 63662306a36Sopenharmony_ci/** 63762306a36Sopenharmony_ci * piix_set_piomode - Initialize host controller PATA PIO timings 63862306a36Sopenharmony_ci * @ap: Port whose timings we are configuring 63962306a36Sopenharmony_ci * @adev: Drive in question 64062306a36Sopenharmony_ci * 64162306a36Sopenharmony_ci * Set PIO mode for device, in host controller PCI config space. 64262306a36Sopenharmony_ci * 64362306a36Sopenharmony_ci * LOCKING: 64462306a36Sopenharmony_ci * None (inherited from caller). 64562306a36Sopenharmony_ci */ 64662306a36Sopenharmony_ci 64762306a36Sopenharmony_cistatic void piix_set_piomode(struct ata_port *ap, struct ata_device *adev) 64862306a36Sopenharmony_ci{ 64962306a36Sopenharmony_ci piix_set_timings(ap, adev, adev->pio_mode - XFER_PIO_0); 65062306a36Sopenharmony_ci} 65162306a36Sopenharmony_ci 65262306a36Sopenharmony_ci/** 65362306a36Sopenharmony_ci * do_pata_set_dmamode - Initialize host controller PATA PIO timings 65462306a36Sopenharmony_ci * @ap: Port whose timings we are configuring 65562306a36Sopenharmony_ci * @adev: Drive in question 65662306a36Sopenharmony_ci * @isich: set if the chip is an ICH device 65762306a36Sopenharmony_ci * 65862306a36Sopenharmony_ci * Set UDMA mode for device, in host controller PCI config space. 65962306a36Sopenharmony_ci * 66062306a36Sopenharmony_ci * LOCKING: 66162306a36Sopenharmony_ci * None (inherited from caller). 66262306a36Sopenharmony_ci */ 66362306a36Sopenharmony_ci 66462306a36Sopenharmony_cistatic void do_pata_set_dmamode(struct ata_port *ap, struct ata_device *adev, int isich) 66562306a36Sopenharmony_ci{ 66662306a36Sopenharmony_ci struct pci_dev *dev = to_pci_dev(ap->host->dev); 66762306a36Sopenharmony_ci unsigned long flags; 66862306a36Sopenharmony_ci u8 speed = adev->dma_mode; 66962306a36Sopenharmony_ci int devid = adev->devno + 2 * ap->port_no; 67062306a36Sopenharmony_ci u8 udma_enable = 0; 67162306a36Sopenharmony_ci 67262306a36Sopenharmony_ci if (speed >= XFER_UDMA_0) { 67362306a36Sopenharmony_ci unsigned int udma = speed - XFER_UDMA_0; 67462306a36Sopenharmony_ci u16 udma_timing; 67562306a36Sopenharmony_ci u16 ideconf; 67662306a36Sopenharmony_ci int u_clock, u_speed; 67762306a36Sopenharmony_ci 67862306a36Sopenharmony_ci spin_lock_irqsave(&piix_lock, flags); 67962306a36Sopenharmony_ci 68062306a36Sopenharmony_ci pci_read_config_byte(dev, 0x48, &udma_enable); 68162306a36Sopenharmony_ci 68262306a36Sopenharmony_ci /* 68362306a36Sopenharmony_ci * UDMA is handled by a combination of clock switching and 68462306a36Sopenharmony_ci * selection of dividers 68562306a36Sopenharmony_ci * 68662306a36Sopenharmony_ci * Handy rule: Odd modes are UDMATIMx 01, even are 02 68762306a36Sopenharmony_ci * except UDMA0 which is 00 68862306a36Sopenharmony_ci */ 68962306a36Sopenharmony_ci u_speed = min(2 - (udma & 1), udma); 69062306a36Sopenharmony_ci if (udma == 5) 69162306a36Sopenharmony_ci u_clock = 0x1000; /* 100Mhz */ 69262306a36Sopenharmony_ci else if (udma > 2) 69362306a36Sopenharmony_ci u_clock = 1; /* 66Mhz */ 69462306a36Sopenharmony_ci else 69562306a36Sopenharmony_ci u_clock = 0; /* 33Mhz */ 69662306a36Sopenharmony_ci 69762306a36Sopenharmony_ci udma_enable |= (1 << devid); 69862306a36Sopenharmony_ci 69962306a36Sopenharmony_ci /* Load the CT/RP selection */ 70062306a36Sopenharmony_ci pci_read_config_word(dev, 0x4A, &udma_timing); 70162306a36Sopenharmony_ci udma_timing &= ~(3 << (4 * devid)); 70262306a36Sopenharmony_ci udma_timing |= u_speed << (4 * devid); 70362306a36Sopenharmony_ci pci_write_config_word(dev, 0x4A, udma_timing); 70462306a36Sopenharmony_ci 70562306a36Sopenharmony_ci if (isich) { 70662306a36Sopenharmony_ci /* Select a 33/66/100Mhz clock */ 70762306a36Sopenharmony_ci pci_read_config_word(dev, 0x54, &ideconf); 70862306a36Sopenharmony_ci ideconf &= ~(0x1001 << devid); 70962306a36Sopenharmony_ci ideconf |= u_clock << devid; 71062306a36Sopenharmony_ci /* For ICH or later we should set bit 10 for better 71162306a36Sopenharmony_ci performance (WR_PingPong_En) */ 71262306a36Sopenharmony_ci pci_write_config_word(dev, 0x54, ideconf); 71362306a36Sopenharmony_ci } 71462306a36Sopenharmony_ci 71562306a36Sopenharmony_ci pci_write_config_byte(dev, 0x48, udma_enable); 71662306a36Sopenharmony_ci 71762306a36Sopenharmony_ci spin_unlock_irqrestore(&piix_lock, flags); 71862306a36Sopenharmony_ci } else { 71962306a36Sopenharmony_ci /* MWDMA is driven by the PIO timings. */ 72062306a36Sopenharmony_ci unsigned int mwdma = speed - XFER_MW_DMA_0; 72162306a36Sopenharmony_ci const unsigned int needed_pio[3] = { 72262306a36Sopenharmony_ci XFER_PIO_0, XFER_PIO_3, XFER_PIO_4 72362306a36Sopenharmony_ci }; 72462306a36Sopenharmony_ci int pio = needed_pio[mwdma] - XFER_PIO_0; 72562306a36Sopenharmony_ci 72662306a36Sopenharmony_ci /* XFER_PIO_0 is never used currently */ 72762306a36Sopenharmony_ci piix_set_timings(ap, adev, pio); 72862306a36Sopenharmony_ci } 72962306a36Sopenharmony_ci} 73062306a36Sopenharmony_ci 73162306a36Sopenharmony_ci/** 73262306a36Sopenharmony_ci * piix_set_dmamode - Initialize host controller PATA DMA timings 73362306a36Sopenharmony_ci * @ap: Port whose timings we are configuring 73462306a36Sopenharmony_ci * @adev: um 73562306a36Sopenharmony_ci * 73662306a36Sopenharmony_ci * Set MW/UDMA mode for device, in host controller PCI config space. 73762306a36Sopenharmony_ci * 73862306a36Sopenharmony_ci * LOCKING: 73962306a36Sopenharmony_ci * None (inherited from caller). 74062306a36Sopenharmony_ci */ 74162306a36Sopenharmony_ci 74262306a36Sopenharmony_cistatic void piix_set_dmamode(struct ata_port *ap, struct ata_device *adev) 74362306a36Sopenharmony_ci{ 74462306a36Sopenharmony_ci do_pata_set_dmamode(ap, adev, 0); 74562306a36Sopenharmony_ci} 74662306a36Sopenharmony_ci 74762306a36Sopenharmony_ci/** 74862306a36Sopenharmony_ci * ich_set_dmamode - Initialize host controller PATA DMA timings 74962306a36Sopenharmony_ci * @ap: Port whose timings we are configuring 75062306a36Sopenharmony_ci * @adev: um 75162306a36Sopenharmony_ci * 75262306a36Sopenharmony_ci * Set MW/UDMA mode for device, in host controller PCI config space. 75362306a36Sopenharmony_ci * 75462306a36Sopenharmony_ci * LOCKING: 75562306a36Sopenharmony_ci * None (inherited from caller). 75662306a36Sopenharmony_ci */ 75762306a36Sopenharmony_ci 75862306a36Sopenharmony_cistatic void ich_set_dmamode(struct ata_port *ap, struct ata_device *adev) 75962306a36Sopenharmony_ci{ 76062306a36Sopenharmony_ci do_pata_set_dmamode(ap, adev, 1); 76162306a36Sopenharmony_ci} 76262306a36Sopenharmony_ci 76362306a36Sopenharmony_ci/* 76462306a36Sopenharmony_ci * Serial ATA Index/Data Pair Superset Registers access 76562306a36Sopenharmony_ci * 76662306a36Sopenharmony_ci * Beginning from ICH8, there's a sane way to access SCRs using index 76762306a36Sopenharmony_ci * and data register pair located at BAR5 which means that we have 76862306a36Sopenharmony_ci * separate SCRs for master and slave. This is handled using libata 76962306a36Sopenharmony_ci * slave_link facility. 77062306a36Sopenharmony_ci */ 77162306a36Sopenharmony_cistatic const int piix_sidx_map[] = { 77262306a36Sopenharmony_ci [SCR_STATUS] = 0, 77362306a36Sopenharmony_ci [SCR_ERROR] = 2, 77462306a36Sopenharmony_ci [SCR_CONTROL] = 1, 77562306a36Sopenharmony_ci}; 77662306a36Sopenharmony_ci 77762306a36Sopenharmony_cistatic void piix_sidpr_sel(struct ata_link *link, unsigned int reg) 77862306a36Sopenharmony_ci{ 77962306a36Sopenharmony_ci struct ata_port *ap = link->ap; 78062306a36Sopenharmony_ci struct piix_host_priv *hpriv = ap->host->private_data; 78162306a36Sopenharmony_ci 78262306a36Sopenharmony_ci iowrite32(((ap->port_no * 2 + link->pmp) << 8) | piix_sidx_map[reg], 78362306a36Sopenharmony_ci hpriv->sidpr + PIIX_SIDPR_IDX); 78462306a36Sopenharmony_ci} 78562306a36Sopenharmony_ci 78662306a36Sopenharmony_cistatic int piix_sidpr_scr_read(struct ata_link *link, 78762306a36Sopenharmony_ci unsigned int reg, u32 *val) 78862306a36Sopenharmony_ci{ 78962306a36Sopenharmony_ci struct piix_host_priv *hpriv = link->ap->host->private_data; 79062306a36Sopenharmony_ci 79162306a36Sopenharmony_ci if (reg >= ARRAY_SIZE(piix_sidx_map)) 79262306a36Sopenharmony_ci return -EINVAL; 79362306a36Sopenharmony_ci 79462306a36Sopenharmony_ci piix_sidpr_sel(link, reg); 79562306a36Sopenharmony_ci *val = ioread32(hpriv->sidpr + PIIX_SIDPR_DATA); 79662306a36Sopenharmony_ci return 0; 79762306a36Sopenharmony_ci} 79862306a36Sopenharmony_ci 79962306a36Sopenharmony_cistatic int piix_sidpr_scr_write(struct ata_link *link, 80062306a36Sopenharmony_ci unsigned int reg, u32 val) 80162306a36Sopenharmony_ci{ 80262306a36Sopenharmony_ci struct piix_host_priv *hpriv = link->ap->host->private_data; 80362306a36Sopenharmony_ci 80462306a36Sopenharmony_ci if (reg >= ARRAY_SIZE(piix_sidx_map)) 80562306a36Sopenharmony_ci return -EINVAL; 80662306a36Sopenharmony_ci 80762306a36Sopenharmony_ci piix_sidpr_sel(link, reg); 80862306a36Sopenharmony_ci iowrite32(val, hpriv->sidpr + PIIX_SIDPR_DATA); 80962306a36Sopenharmony_ci return 0; 81062306a36Sopenharmony_ci} 81162306a36Sopenharmony_ci 81262306a36Sopenharmony_cistatic int piix_sidpr_set_lpm(struct ata_link *link, enum ata_lpm_policy policy, 81362306a36Sopenharmony_ci unsigned hints) 81462306a36Sopenharmony_ci{ 81562306a36Sopenharmony_ci return sata_link_scr_lpm(link, policy, false); 81662306a36Sopenharmony_ci} 81762306a36Sopenharmony_ci 81862306a36Sopenharmony_cistatic bool piix_irq_check(struct ata_port *ap) 81962306a36Sopenharmony_ci{ 82062306a36Sopenharmony_ci unsigned char host_stat; 82162306a36Sopenharmony_ci 82262306a36Sopenharmony_ci if (unlikely(!ap->ioaddr.bmdma_addr)) 82362306a36Sopenharmony_ci return false; 82462306a36Sopenharmony_ci 82562306a36Sopenharmony_ci host_stat = ap->ops->bmdma_status(ap); 82662306a36Sopenharmony_ci trace_ata_bmdma_status(ap, host_stat); 82762306a36Sopenharmony_ci 82862306a36Sopenharmony_ci return host_stat & ATA_DMA_INTR; 82962306a36Sopenharmony_ci} 83062306a36Sopenharmony_ci 83162306a36Sopenharmony_ci#ifdef CONFIG_PM_SLEEP 83262306a36Sopenharmony_cistatic int piix_broken_suspend(void) 83362306a36Sopenharmony_ci{ 83462306a36Sopenharmony_ci static const struct dmi_system_id sysids[] = { 83562306a36Sopenharmony_ci { 83662306a36Sopenharmony_ci .ident = "TECRA M3", 83762306a36Sopenharmony_ci .matches = { 83862306a36Sopenharmony_ci DMI_MATCH(DMI_SYS_VENDOR, "TOSHIBA"), 83962306a36Sopenharmony_ci DMI_MATCH(DMI_PRODUCT_NAME, "TECRA M3"), 84062306a36Sopenharmony_ci }, 84162306a36Sopenharmony_ci }, 84262306a36Sopenharmony_ci { 84362306a36Sopenharmony_ci .ident = "TECRA M3", 84462306a36Sopenharmony_ci .matches = { 84562306a36Sopenharmony_ci DMI_MATCH(DMI_SYS_VENDOR, "TOSHIBA"), 84662306a36Sopenharmony_ci DMI_MATCH(DMI_PRODUCT_NAME, "Tecra M3"), 84762306a36Sopenharmony_ci }, 84862306a36Sopenharmony_ci }, 84962306a36Sopenharmony_ci { 85062306a36Sopenharmony_ci .ident = "TECRA M3", 85162306a36Sopenharmony_ci .matches = { 85262306a36Sopenharmony_ci DMI_MATCH(DMI_OEM_STRING, "Tecra M3,"), 85362306a36Sopenharmony_ci }, 85462306a36Sopenharmony_ci }, 85562306a36Sopenharmony_ci { 85662306a36Sopenharmony_ci .ident = "TECRA M4", 85762306a36Sopenharmony_ci .matches = { 85862306a36Sopenharmony_ci DMI_MATCH(DMI_SYS_VENDOR, "TOSHIBA"), 85962306a36Sopenharmony_ci DMI_MATCH(DMI_PRODUCT_NAME, "Tecra M4"), 86062306a36Sopenharmony_ci }, 86162306a36Sopenharmony_ci }, 86262306a36Sopenharmony_ci { 86362306a36Sopenharmony_ci .ident = "TECRA M4", 86462306a36Sopenharmony_ci .matches = { 86562306a36Sopenharmony_ci DMI_MATCH(DMI_SYS_VENDOR, "TOSHIBA"), 86662306a36Sopenharmony_ci DMI_MATCH(DMI_PRODUCT_NAME, "TECRA M4"), 86762306a36Sopenharmony_ci }, 86862306a36Sopenharmony_ci }, 86962306a36Sopenharmony_ci { 87062306a36Sopenharmony_ci .ident = "TECRA M5", 87162306a36Sopenharmony_ci .matches = { 87262306a36Sopenharmony_ci DMI_MATCH(DMI_SYS_VENDOR, "TOSHIBA"), 87362306a36Sopenharmony_ci DMI_MATCH(DMI_PRODUCT_NAME, "TECRA M5"), 87462306a36Sopenharmony_ci }, 87562306a36Sopenharmony_ci }, 87662306a36Sopenharmony_ci { 87762306a36Sopenharmony_ci .ident = "TECRA M6", 87862306a36Sopenharmony_ci .matches = { 87962306a36Sopenharmony_ci DMI_MATCH(DMI_SYS_VENDOR, "TOSHIBA"), 88062306a36Sopenharmony_ci DMI_MATCH(DMI_PRODUCT_NAME, "TECRA M6"), 88162306a36Sopenharmony_ci }, 88262306a36Sopenharmony_ci }, 88362306a36Sopenharmony_ci { 88462306a36Sopenharmony_ci .ident = "TECRA M7", 88562306a36Sopenharmony_ci .matches = { 88662306a36Sopenharmony_ci DMI_MATCH(DMI_SYS_VENDOR, "TOSHIBA"), 88762306a36Sopenharmony_ci DMI_MATCH(DMI_PRODUCT_NAME, "TECRA M7"), 88862306a36Sopenharmony_ci }, 88962306a36Sopenharmony_ci }, 89062306a36Sopenharmony_ci { 89162306a36Sopenharmony_ci .ident = "TECRA A8", 89262306a36Sopenharmony_ci .matches = { 89362306a36Sopenharmony_ci DMI_MATCH(DMI_SYS_VENDOR, "TOSHIBA"), 89462306a36Sopenharmony_ci DMI_MATCH(DMI_PRODUCT_NAME, "TECRA A8"), 89562306a36Sopenharmony_ci }, 89662306a36Sopenharmony_ci }, 89762306a36Sopenharmony_ci { 89862306a36Sopenharmony_ci .ident = "Satellite R20", 89962306a36Sopenharmony_ci .matches = { 90062306a36Sopenharmony_ci DMI_MATCH(DMI_SYS_VENDOR, "TOSHIBA"), 90162306a36Sopenharmony_ci DMI_MATCH(DMI_PRODUCT_NAME, "Satellite R20"), 90262306a36Sopenharmony_ci }, 90362306a36Sopenharmony_ci }, 90462306a36Sopenharmony_ci { 90562306a36Sopenharmony_ci .ident = "Satellite R25", 90662306a36Sopenharmony_ci .matches = { 90762306a36Sopenharmony_ci DMI_MATCH(DMI_SYS_VENDOR, "TOSHIBA"), 90862306a36Sopenharmony_ci DMI_MATCH(DMI_PRODUCT_NAME, "Satellite R25"), 90962306a36Sopenharmony_ci }, 91062306a36Sopenharmony_ci }, 91162306a36Sopenharmony_ci { 91262306a36Sopenharmony_ci .ident = "Satellite U200", 91362306a36Sopenharmony_ci .matches = { 91462306a36Sopenharmony_ci DMI_MATCH(DMI_SYS_VENDOR, "TOSHIBA"), 91562306a36Sopenharmony_ci DMI_MATCH(DMI_PRODUCT_NAME, "Satellite U200"), 91662306a36Sopenharmony_ci }, 91762306a36Sopenharmony_ci }, 91862306a36Sopenharmony_ci { 91962306a36Sopenharmony_ci .ident = "Satellite U200", 92062306a36Sopenharmony_ci .matches = { 92162306a36Sopenharmony_ci DMI_MATCH(DMI_SYS_VENDOR, "TOSHIBA"), 92262306a36Sopenharmony_ci DMI_MATCH(DMI_PRODUCT_NAME, "SATELLITE U200"), 92362306a36Sopenharmony_ci }, 92462306a36Sopenharmony_ci }, 92562306a36Sopenharmony_ci { 92662306a36Sopenharmony_ci .ident = "Satellite Pro U200", 92762306a36Sopenharmony_ci .matches = { 92862306a36Sopenharmony_ci DMI_MATCH(DMI_SYS_VENDOR, "TOSHIBA"), 92962306a36Sopenharmony_ci DMI_MATCH(DMI_PRODUCT_NAME, "SATELLITE PRO U200"), 93062306a36Sopenharmony_ci }, 93162306a36Sopenharmony_ci }, 93262306a36Sopenharmony_ci { 93362306a36Sopenharmony_ci .ident = "Satellite U205", 93462306a36Sopenharmony_ci .matches = { 93562306a36Sopenharmony_ci DMI_MATCH(DMI_SYS_VENDOR, "TOSHIBA"), 93662306a36Sopenharmony_ci DMI_MATCH(DMI_PRODUCT_NAME, "Satellite U205"), 93762306a36Sopenharmony_ci }, 93862306a36Sopenharmony_ci }, 93962306a36Sopenharmony_ci { 94062306a36Sopenharmony_ci .ident = "SATELLITE U205", 94162306a36Sopenharmony_ci .matches = { 94262306a36Sopenharmony_ci DMI_MATCH(DMI_SYS_VENDOR, "TOSHIBA"), 94362306a36Sopenharmony_ci DMI_MATCH(DMI_PRODUCT_NAME, "SATELLITE U205"), 94462306a36Sopenharmony_ci }, 94562306a36Sopenharmony_ci }, 94662306a36Sopenharmony_ci { 94762306a36Sopenharmony_ci .ident = "Satellite Pro A120", 94862306a36Sopenharmony_ci .matches = { 94962306a36Sopenharmony_ci DMI_MATCH(DMI_SYS_VENDOR, "TOSHIBA"), 95062306a36Sopenharmony_ci DMI_MATCH(DMI_PRODUCT_NAME, "Satellite Pro A120"), 95162306a36Sopenharmony_ci }, 95262306a36Sopenharmony_ci }, 95362306a36Sopenharmony_ci { 95462306a36Sopenharmony_ci .ident = "Portege M500", 95562306a36Sopenharmony_ci .matches = { 95662306a36Sopenharmony_ci DMI_MATCH(DMI_SYS_VENDOR, "TOSHIBA"), 95762306a36Sopenharmony_ci DMI_MATCH(DMI_PRODUCT_NAME, "PORTEGE M500"), 95862306a36Sopenharmony_ci }, 95962306a36Sopenharmony_ci }, 96062306a36Sopenharmony_ci { 96162306a36Sopenharmony_ci .ident = "VGN-BX297XP", 96262306a36Sopenharmony_ci .matches = { 96362306a36Sopenharmony_ci DMI_MATCH(DMI_SYS_VENDOR, "Sony Corporation"), 96462306a36Sopenharmony_ci DMI_MATCH(DMI_PRODUCT_NAME, "VGN-BX297XP"), 96562306a36Sopenharmony_ci }, 96662306a36Sopenharmony_ci }, 96762306a36Sopenharmony_ci 96862306a36Sopenharmony_ci { } /* terminate list */ 96962306a36Sopenharmony_ci }; 97062306a36Sopenharmony_ci 97162306a36Sopenharmony_ci if (dmi_check_system(sysids)) 97262306a36Sopenharmony_ci return 1; 97362306a36Sopenharmony_ci 97462306a36Sopenharmony_ci /* TECRA M4 sometimes forgets its identify and reports bogus 97562306a36Sopenharmony_ci * DMI information. As the bogus information is a bit 97662306a36Sopenharmony_ci * generic, match as many entries as possible. This manual 97762306a36Sopenharmony_ci * matching is necessary because dmi_system_id.matches is 97862306a36Sopenharmony_ci * limited to four entries. 97962306a36Sopenharmony_ci */ 98062306a36Sopenharmony_ci if (dmi_match(DMI_SYS_VENDOR, "TOSHIBA") && 98162306a36Sopenharmony_ci dmi_match(DMI_PRODUCT_NAME, "000000") && 98262306a36Sopenharmony_ci dmi_match(DMI_PRODUCT_VERSION, "000000") && 98362306a36Sopenharmony_ci dmi_match(DMI_PRODUCT_SERIAL, "000000") && 98462306a36Sopenharmony_ci dmi_match(DMI_BOARD_VENDOR, "TOSHIBA") && 98562306a36Sopenharmony_ci dmi_match(DMI_BOARD_NAME, "Portable PC") && 98662306a36Sopenharmony_ci dmi_match(DMI_BOARD_VERSION, "Version A0")) 98762306a36Sopenharmony_ci return 1; 98862306a36Sopenharmony_ci 98962306a36Sopenharmony_ci return 0; 99062306a36Sopenharmony_ci} 99162306a36Sopenharmony_ci 99262306a36Sopenharmony_cistatic int piix_pci_device_suspend(struct pci_dev *pdev, pm_message_t mesg) 99362306a36Sopenharmony_ci{ 99462306a36Sopenharmony_ci struct ata_host *host = pci_get_drvdata(pdev); 99562306a36Sopenharmony_ci unsigned long flags; 99662306a36Sopenharmony_ci 99762306a36Sopenharmony_ci ata_host_suspend(host, mesg); 99862306a36Sopenharmony_ci 99962306a36Sopenharmony_ci /* Some braindamaged ACPI suspend implementations expect the 100062306a36Sopenharmony_ci * controller to be awake on entry; otherwise, it burns cpu 100162306a36Sopenharmony_ci * cycles and power trying to do something to the sleeping 100262306a36Sopenharmony_ci * beauty. 100362306a36Sopenharmony_ci */ 100462306a36Sopenharmony_ci if (piix_broken_suspend() && (mesg.event & PM_EVENT_SLEEP)) { 100562306a36Sopenharmony_ci pci_save_state(pdev); 100662306a36Sopenharmony_ci 100762306a36Sopenharmony_ci /* mark its power state as "unknown", since we don't 100862306a36Sopenharmony_ci * know if e.g. the BIOS will change its device state 100962306a36Sopenharmony_ci * when we suspend. 101062306a36Sopenharmony_ci */ 101162306a36Sopenharmony_ci if (pdev->current_state == PCI_D0) 101262306a36Sopenharmony_ci pdev->current_state = PCI_UNKNOWN; 101362306a36Sopenharmony_ci 101462306a36Sopenharmony_ci /* tell resume that it's waking up from broken suspend */ 101562306a36Sopenharmony_ci spin_lock_irqsave(&host->lock, flags); 101662306a36Sopenharmony_ci host->flags |= PIIX_HOST_BROKEN_SUSPEND; 101762306a36Sopenharmony_ci spin_unlock_irqrestore(&host->lock, flags); 101862306a36Sopenharmony_ci } else 101962306a36Sopenharmony_ci ata_pci_device_do_suspend(pdev, mesg); 102062306a36Sopenharmony_ci 102162306a36Sopenharmony_ci return 0; 102262306a36Sopenharmony_ci} 102362306a36Sopenharmony_ci 102462306a36Sopenharmony_cistatic int piix_pci_device_resume(struct pci_dev *pdev) 102562306a36Sopenharmony_ci{ 102662306a36Sopenharmony_ci struct ata_host *host = pci_get_drvdata(pdev); 102762306a36Sopenharmony_ci unsigned long flags; 102862306a36Sopenharmony_ci int rc; 102962306a36Sopenharmony_ci 103062306a36Sopenharmony_ci if (host->flags & PIIX_HOST_BROKEN_SUSPEND) { 103162306a36Sopenharmony_ci spin_lock_irqsave(&host->lock, flags); 103262306a36Sopenharmony_ci host->flags &= ~PIIX_HOST_BROKEN_SUSPEND; 103362306a36Sopenharmony_ci spin_unlock_irqrestore(&host->lock, flags); 103462306a36Sopenharmony_ci 103562306a36Sopenharmony_ci pci_set_power_state(pdev, PCI_D0); 103662306a36Sopenharmony_ci pci_restore_state(pdev); 103762306a36Sopenharmony_ci 103862306a36Sopenharmony_ci /* PCI device wasn't disabled during suspend. Use 103962306a36Sopenharmony_ci * pci_reenable_device() to avoid affecting the enable 104062306a36Sopenharmony_ci * count. 104162306a36Sopenharmony_ci */ 104262306a36Sopenharmony_ci rc = pci_reenable_device(pdev); 104362306a36Sopenharmony_ci if (rc) 104462306a36Sopenharmony_ci dev_err(&pdev->dev, 104562306a36Sopenharmony_ci "failed to enable device after resume (%d)\n", 104662306a36Sopenharmony_ci rc); 104762306a36Sopenharmony_ci } else 104862306a36Sopenharmony_ci rc = ata_pci_device_do_resume(pdev); 104962306a36Sopenharmony_ci 105062306a36Sopenharmony_ci if (rc == 0) 105162306a36Sopenharmony_ci ata_host_resume(host); 105262306a36Sopenharmony_ci 105362306a36Sopenharmony_ci return rc; 105462306a36Sopenharmony_ci} 105562306a36Sopenharmony_ci#endif 105662306a36Sopenharmony_ci 105762306a36Sopenharmony_cistatic u8 piix_vmw_bmdma_status(struct ata_port *ap) 105862306a36Sopenharmony_ci{ 105962306a36Sopenharmony_ci return ata_bmdma_status(ap) & ~ATA_DMA_ERR; 106062306a36Sopenharmony_ci} 106162306a36Sopenharmony_ci 106262306a36Sopenharmony_cistatic const struct scsi_host_template piix_sht = { 106362306a36Sopenharmony_ci ATA_BMDMA_SHT(DRV_NAME), 106462306a36Sopenharmony_ci}; 106562306a36Sopenharmony_ci 106662306a36Sopenharmony_cistatic struct ata_port_operations piix_sata_ops = { 106762306a36Sopenharmony_ci .inherits = &ata_bmdma32_port_ops, 106862306a36Sopenharmony_ci .sff_irq_check = piix_irq_check, 106962306a36Sopenharmony_ci .port_start = piix_port_start, 107062306a36Sopenharmony_ci}; 107162306a36Sopenharmony_ci 107262306a36Sopenharmony_cistatic struct ata_port_operations piix_pata_ops = { 107362306a36Sopenharmony_ci .inherits = &piix_sata_ops, 107462306a36Sopenharmony_ci .cable_detect = ata_cable_40wire, 107562306a36Sopenharmony_ci .set_piomode = piix_set_piomode, 107662306a36Sopenharmony_ci .set_dmamode = piix_set_dmamode, 107762306a36Sopenharmony_ci .prereset = piix_pata_prereset, 107862306a36Sopenharmony_ci}; 107962306a36Sopenharmony_ci 108062306a36Sopenharmony_cistatic struct ata_port_operations piix_vmw_ops = { 108162306a36Sopenharmony_ci .inherits = &piix_pata_ops, 108262306a36Sopenharmony_ci .bmdma_status = piix_vmw_bmdma_status, 108362306a36Sopenharmony_ci}; 108462306a36Sopenharmony_ci 108562306a36Sopenharmony_cistatic struct ata_port_operations ich_pata_ops = { 108662306a36Sopenharmony_ci .inherits = &piix_pata_ops, 108762306a36Sopenharmony_ci .cable_detect = ich_pata_cable_detect, 108862306a36Sopenharmony_ci .set_dmamode = ich_set_dmamode, 108962306a36Sopenharmony_ci}; 109062306a36Sopenharmony_ci 109162306a36Sopenharmony_cistatic struct attribute *piix_sidpr_shost_attrs[] = { 109262306a36Sopenharmony_ci &dev_attr_link_power_management_policy.attr, 109362306a36Sopenharmony_ci NULL 109462306a36Sopenharmony_ci}; 109562306a36Sopenharmony_ci 109662306a36Sopenharmony_ciATTRIBUTE_GROUPS(piix_sidpr_shost); 109762306a36Sopenharmony_ci 109862306a36Sopenharmony_cistatic const struct scsi_host_template piix_sidpr_sht = { 109962306a36Sopenharmony_ci ATA_BMDMA_SHT(DRV_NAME), 110062306a36Sopenharmony_ci .shost_groups = piix_sidpr_shost_groups, 110162306a36Sopenharmony_ci}; 110262306a36Sopenharmony_ci 110362306a36Sopenharmony_cistatic struct ata_port_operations piix_sidpr_sata_ops = { 110462306a36Sopenharmony_ci .inherits = &piix_sata_ops, 110562306a36Sopenharmony_ci .hardreset = sata_std_hardreset, 110662306a36Sopenharmony_ci .scr_read = piix_sidpr_scr_read, 110762306a36Sopenharmony_ci .scr_write = piix_sidpr_scr_write, 110862306a36Sopenharmony_ci .set_lpm = piix_sidpr_set_lpm, 110962306a36Sopenharmony_ci}; 111062306a36Sopenharmony_ci 111162306a36Sopenharmony_cistatic struct ata_port_info piix_port_info[] = { 111262306a36Sopenharmony_ci [piix_pata_mwdma] = /* PIIX3 MWDMA only */ 111362306a36Sopenharmony_ci { 111462306a36Sopenharmony_ci .flags = PIIX_PATA_FLAGS, 111562306a36Sopenharmony_ci .pio_mask = ATA_PIO4, 111662306a36Sopenharmony_ci .mwdma_mask = ATA_MWDMA12_ONLY, /* mwdma1-2 ?? CHECK 0 should be ok but slow */ 111762306a36Sopenharmony_ci .port_ops = &piix_pata_ops, 111862306a36Sopenharmony_ci }, 111962306a36Sopenharmony_ci 112062306a36Sopenharmony_ci [piix_pata_33] = /* PIIX4 at 33MHz */ 112162306a36Sopenharmony_ci { 112262306a36Sopenharmony_ci .flags = PIIX_PATA_FLAGS, 112362306a36Sopenharmony_ci .pio_mask = ATA_PIO4, 112462306a36Sopenharmony_ci .mwdma_mask = ATA_MWDMA12_ONLY, /* mwdma1-2 ?? CHECK 0 should be ok but slow */ 112562306a36Sopenharmony_ci .udma_mask = ATA_UDMA2, 112662306a36Sopenharmony_ci .port_ops = &piix_pata_ops, 112762306a36Sopenharmony_ci }, 112862306a36Sopenharmony_ci 112962306a36Sopenharmony_ci [ich_pata_33] = /* ICH0 - ICH at 33Mhz*/ 113062306a36Sopenharmony_ci { 113162306a36Sopenharmony_ci .flags = PIIX_PATA_FLAGS, 113262306a36Sopenharmony_ci .pio_mask = ATA_PIO4, 113362306a36Sopenharmony_ci .mwdma_mask = ATA_MWDMA12_ONLY, /* Check: maybe MWDMA0 is ok */ 113462306a36Sopenharmony_ci .udma_mask = ATA_UDMA2, 113562306a36Sopenharmony_ci .port_ops = &ich_pata_ops, 113662306a36Sopenharmony_ci }, 113762306a36Sopenharmony_ci 113862306a36Sopenharmony_ci [ich_pata_66] = /* ICH controllers up to 66MHz */ 113962306a36Sopenharmony_ci { 114062306a36Sopenharmony_ci .flags = PIIX_PATA_FLAGS, 114162306a36Sopenharmony_ci .pio_mask = ATA_PIO4, 114262306a36Sopenharmony_ci .mwdma_mask = ATA_MWDMA12_ONLY, /* MWDMA0 is broken on chip */ 114362306a36Sopenharmony_ci .udma_mask = ATA_UDMA4, 114462306a36Sopenharmony_ci .port_ops = &ich_pata_ops, 114562306a36Sopenharmony_ci }, 114662306a36Sopenharmony_ci 114762306a36Sopenharmony_ci [ich_pata_100] = 114862306a36Sopenharmony_ci { 114962306a36Sopenharmony_ci .flags = PIIX_PATA_FLAGS | PIIX_FLAG_CHECKINTR, 115062306a36Sopenharmony_ci .pio_mask = ATA_PIO4, 115162306a36Sopenharmony_ci .mwdma_mask = ATA_MWDMA12_ONLY, 115262306a36Sopenharmony_ci .udma_mask = ATA_UDMA5, 115362306a36Sopenharmony_ci .port_ops = &ich_pata_ops, 115462306a36Sopenharmony_ci }, 115562306a36Sopenharmony_ci 115662306a36Sopenharmony_ci [ich_pata_100_nomwdma1] = 115762306a36Sopenharmony_ci { 115862306a36Sopenharmony_ci .flags = PIIX_PATA_FLAGS | PIIX_FLAG_CHECKINTR, 115962306a36Sopenharmony_ci .pio_mask = ATA_PIO4, 116062306a36Sopenharmony_ci .mwdma_mask = ATA_MWDMA2_ONLY, 116162306a36Sopenharmony_ci .udma_mask = ATA_UDMA5, 116262306a36Sopenharmony_ci .port_ops = &ich_pata_ops, 116362306a36Sopenharmony_ci }, 116462306a36Sopenharmony_ci 116562306a36Sopenharmony_ci [ich5_sata] = 116662306a36Sopenharmony_ci { 116762306a36Sopenharmony_ci .flags = PIIX_SATA_FLAGS, 116862306a36Sopenharmony_ci .pio_mask = ATA_PIO4, 116962306a36Sopenharmony_ci .mwdma_mask = ATA_MWDMA2, 117062306a36Sopenharmony_ci .udma_mask = ATA_UDMA6, 117162306a36Sopenharmony_ci .port_ops = &piix_sata_ops, 117262306a36Sopenharmony_ci }, 117362306a36Sopenharmony_ci 117462306a36Sopenharmony_ci [ich6_sata] = 117562306a36Sopenharmony_ci { 117662306a36Sopenharmony_ci .flags = PIIX_SATA_FLAGS, 117762306a36Sopenharmony_ci .pio_mask = ATA_PIO4, 117862306a36Sopenharmony_ci .mwdma_mask = ATA_MWDMA2, 117962306a36Sopenharmony_ci .udma_mask = ATA_UDMA6, 118062306a36Sopenharmony_ci .port_ops = &piix_sata_ops, 118162306a36Sopenharmony_ci }, 118262306a36Sopenharmony_ci 118362306a36Sopenharmony_ci [ich6m_sata] = 118462306a36Sopenharmony_ci { 118562306a36Sopenharmony_ci .flags = PIIX_SATA_FLAGS, 118662306a36Sopenharmony_ci .pio_mask = ATA_PIO4, 118762306a36Sopenharmony_ci .mwdma_mask = ATA_MWDMA2, 118862306a36Sopenharmony_ci .udma_mask = ATA_UDMA6, 118962306a36Sopenharmony_ci .port_ops = &piix_sata_ops, 119062306a36Sopenharmony_ci }, 119162306a36Sopenharmony_ci 119262306a36Sopenharmony_ci [ich8_sata] = 119362306a36Sopenharmony_ci { 119462306a36Sopenharmony_ci .flags = PIIX_SATA_FLAGS | PIIX_FLAG_SIDPR, 119562306a36Sopenharmony_ci .pio_mask = ATA_PIO4, 119662306a36Sopenharmony_ci .mwdma_mask = ATA_MWDMA2, 119762306a36Sopenharmony_ci .udma_mask = ATA_UDMA6, 119862306a36Sopenharmony_ci .port_ops = &piix_sata_ops, 119962306a36Sopenharmony_ci }, 120062306a36Sopenharmony_ci 120162306a36Sopenharmony_ci [ich8_2port_sata] = 120262306a36Sopenharmony_ci { 120362306a36Sopenharmony_ci .flags = PIIX_SATA_FLAGS | PIIX_FLAG_SIDPR, 120462306a36Sopenharmony_ci .pio_mask = ATA_PIO4, 120562306a36Sopenharmony_ci .mwdma_mask = ATA_MWDMA2, 120662306a36Sopenharmony_ci .udma_mask = ATA_UDMA6, 120762306a36Sopenharmony_ci .port_ops = &piix_sata_ops, 120862306a36Sopenharmony_ci }, 120962306a36Sopenharmony_ci 121062306a36Sopenharmony_ci [tolapai_sata] = 121162306a36Sopenharmony_ci { 121262306a36Sopenharmony_ci .flags = PIIX_SATA_FLAGS, 121362306a36Sopenharmony_ci .pio_mask = ATA_PIO4, 121462306a36Sopenharmony_ci .mwdma_mask = ATA_MWDMA2, 121562306a36Sopenharmony_ci .udma_mask = ATA_UDMA6, 121662306a36Sopenharmony_ci .port_ops = &piix_sata_ops, 121762306a36Sopenharmony_ci }, 121862306a36Sopenharmony_ci 121962306a36Sopenharmony_ci [ich8m_apple_sata] = 122062306a36Sopenharmony_ci { 122162306a36Sopenharmony_ci .flags = PIIX_SATA_FLAGS, 122262306a36Sopenharmony_ci .pio_mask = ATA_PIO4, 122362306a36Sopenharmony_ci .mwdma_mask = ATA_MWDMA2, 122462306a36Sopenharmony_ci .udma_mask = ATA_UDMA6, 122562306a36Sopenharmony_ci .port_ops = &piix_sata_ops, 122662306a36Sopenharmony_ci }, 122762306a36Sopenharmony_ci 122862306a36Sopenharmony_ci [piix_pata_vmw] = 122962306a36Sopenharmony_ci { 123062306a36Sopenharmony_ci .flags = PIIX_PATA_FLAGS, 123162306a36Sopenharmony_ci .pio_mask = ATA_PIO4, 123262306a36Sopenharmony_ci .mwdma_mask = ATA_MWDMA12_ONLY, /* mwdma1-2 ?? CHECK 0 should be ok but slow */ 123362306a36Sopenharmony_ci .udma_mask = ATA_UDMA2, 123462306a36Sopenharmony_ci .port_ops = &piix_vmw_ops, 123562306a36Sopenharmony_ci }, 123662306a36Sopenharmony_ci 123762306a36Sopenharmony_ci /* 123862306a36Sopenharmony_ci * some Sandybridge chipsets have broken 32 mode up to now, 123962306a36Sopenharmony_ci * see https://bugzilla.kernel.org/show_bug.cgi?id=40592 124062306a36Sopenharmony_ci */ 124162306a36Sopenharmony_ci [ich8_sata_snb] = 124262306a36Sopenharmony_ci { 124362306a36Sopenharmony_ci .flags = PIIX_SATA_FLAGS | PIIX_FLAG_SIDPR | PIIX_FLAG_PIO16, 124462306a36Sopenharmony_ci .pio_mask = ATA_PIO4, 124562306a36Sopenharmony_ci .mwdma_mask = ATA_MWDMA2, 124662306a36Sopenharmony_ci .udma_mask = ATA_UDMA6, 124762306a36Sopenharmony_ci .port_ops = &piix_sata_ops, 124862306a36Sopenharmony_ci }, 124962306a36Sopenharmony_ci 125062306a36Sopenharmony_ci [ich8_2port_sata_snb] = 125162306a36Sopenharmony_ci { 125262306a36Sopenharmony_ci .flags = PIIX_SATA_FLAGS | PIIX_FLAG_SIDPR 125362306a36Sopenharmony_ci | PIIX_FLAG_PIO16, 125462306a36Sopenharmony_ci .pio_mask = ATA_PIO4, 125562306a36Sopenharmony_ci .mwdma_mask = ATA_MWDMA2, 125662306a36Sopenharmony_ci .udma_mask = ATA_UDMA6, 125762306a36Sopenharmony_ci .port_ops = &piix_sata_ops, 125862306a36Sopenharmony_ci }, 125962306a36Sopenharmony_ci 126062306a36Sopenharmony_ci [ich8_2port_sata_byt] = 126162306a36Sopenharmony_ci { 126262306a36Sopenharmony_ci .flags = PIIX_SATA_FLAGS | PIIX_FLAG_SIDPR | PIIX_FLAG_PIO16, 126362306a36Sopenharmony_ci .pio_mask = ATA_PIO4, 126462306a36Sopenharmony_ci .mwdma_mask = ATA_MWDMA2, 126562306a36Sopenharmony_ci .udma_mask = ATA_UDMA6, 126662306a36Sopenharmony_ci .port_ops = &piix_sata_ops, 126762306a36Sopenharmony_ci }, 126862306a36Sopenharmony_ci 126962306a36Sopenharmony_ci}; 127062306a36Sopenharmony_ci 127162306a36Sopenharmony_ci#define AHCI_PCI_BAR 5 127262306a36Sopenharmony_ci#define AHCI_GLOBAL_CTL 0x04 127362306a36Sopenharmony_ci#define AHCI_ENABLE (1 << 31) 127462306a36Sopenharmony_cistatic int piix_disable_ahci(struct pci_dev *pdev) 127562306a36Sopenharmony_ci{ 127662306a36Sopenharmony_ci void __iomem *mmio; 127762306a36Sopenharmony_ci u32 tmp; 127862306a36Sopenharmony_ci int rc = 0; 127962306a36Sopenharmony_ci 128062306a36Sopenharmony_ci /* BUG: pci_enable_device has not yet been called. This 128162306a36Sopenharmony_ci * works because this device is usually set up by BIOS. 128262306a36Sopenharmony_ci */ 128362306a36Sopenharmony_ci 128462306a36Sopenharmony_ci if (!pci_resource_start(pdev, AHCI_PCI_BAR) || 128562306a36Sopenharmony_ci !pci_resource_len(pdev, AHCI_PCI_BAR)) 128662306a36Sopenharmony_ci return 0; 128762306a36Sopenharmony_ci 128862306a36Sopenharmony_ci mmio = pci_iomap(pdev, AHCI_PCI_BAR, 64); 128962306a36Sopenharmony_ci if (!mmio) 129062306a36Sopenharmony_ci return -ENOMEM; 129162306a36Sopenharmony_ci 129262306a36Sopenharmony_ci tmp = ioread32(mmio + AHCI_GLOBAL_CTL); 129362306a36Sopenharmony_ci if (tmp & AHCI_ENABLE) { 129462306a36Sopenharmony_ci tmp &= ~AHCI_ENABLE; 129562306a36Sopenharmony_ci iowrite32(tmp, mmio + AHCI_GLOBAL_CTL); 129662306a36Sopenharmony_ci 129762306a36Sopenharmony_ci tmp = ioread32(mmio + AHCI_GLOBAL_CTL); 129862306a36Sopenharmony_ci if (tmp & AHCI_ENABLE) 129962306a36Sopenharmony_ci rc = -EIO; 130062306a36Sopenharmony_ci } 130162306a36Sopenharmony_ci 130262306a36Sopenharmony_ci pci_iounmap(pdev, mmio); 130362306a36Sopenharmony_ci return rc; 130462306a36Sopenharmony_ci} 130562306a36Sopenharmony_ci 130662306a36Sopenharmony_ci/** 130762306a36Sopenharmony_ci * piix_check_450nx_errata - Check for problem 450NX setup 130862306a36Sopenharmony_ci * @ata_dev: the PCI device to check 130962306a36Sopenharmony_ci * 131062306a36Sopenharmony_ci * Check for the present of 450NX errata #19 and errata #25. If 131162306a36Sopenharmony_ci * they are found return an error code so we can turn off DMA 131262306a36Sopenharmony_ci */ 131362306a36Sopenharmony_ci 131462306a36Sopenharmony_cistatic int piix_check_450nx_errata(struct pci_dev *ata_dev) 131562306a36Sopenharmony_ci{ 131662306a36Sopenharmony_ci struct pci_dev *pdev = NULL; 131762306a36Sopenharmony_ci u16 cfg; 131862306a36Sopenharmony_ci int no_piix_dma = 0; 131962306a36Sopenharmony_ci 132062306a36Sopenharmony_ci while ((pdev = pci_get_device(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_82454NX, pdev)) != NULL) { 132162306a36Sopenharmony_ci /* Look for 450NX PXB. Check for problem configurations 132262306a36Sopenharmony_ci A PCI quirk checks bit 6 already */ 132362306a36Sopenharmony_ci pci_read_config_word(pdev, 0x41, &cfg); 132462306a36Sopenharmony_ci /* Only on the original revision: IDE DMA can hang */ 132562306a36Sopenharmony_ci if (pdev->revision == 0x00) 132662306a36Sopenharmony_ci no_piix_dma = 1; 132762306a36Sopenharmony_ci /* On all revisions below 5 PXB bus lock must be disabled for IDE */ 132862306a36Sopenharmony_ci else if (cfg & (1<<14) && pdev->revision < 5) 132962306a36Sopenharmony_ci no_piix_dma = 2; 133062306a36Sopenharmony_ci } 133162306a36Sopenharmony_ci if (no_piix_dma) 133262306a36Sopenharmony_ci dev_warn(&ata_dev->dev, 133362306a36Sopenharmony_ci "450NX errata present, disabling IDE DMA%s\n", 133462306a36Sopenharmony_ci no_piix_dma == 2 ? " - a BIOS update may resolve this" 133562306a36Sopenharmony_ci : ""); 133662306a36Sopenharmony_ci 133762306a36Sopenharmony_ci return no_piix_dma; 133862306a36Sopenharmony_ci} 133962306a36Sopenharmony_ci 134062306a36Sopenharmony_cistatic void piix_init_pcs(struct ata_host *host, 134162306a36Sopenharmony_ci const struct piix_map_db *map_db) 134262306a36Sopenharmony_ci{ 134362306a36Sopenharmony_ci struct pci_dev *pdev = to_pci_dev(host->dev); 134462306a36Sopenharmony_ci u16 pcs, new_pcs; 134562306a36Sopenharmony_ci 134662306a36Sopenharmony_ci pci_read_config_word(pdev, ICH5_PCS, &pcs); 134762306a36Sopenharmony_ci 134862306a36Sopenharmony_ci new_pcs = pcs | map_db->port_enable; 134962306a36Sopenharmony_ci 135062306a36Sopenharmony_ci if (new_pcs != pcs) { 135162306a36Sopenharmony_ci pci_write_config_word(pdev, ICH5_PCS, new_pcs); 135262306a36Sopenharmony_ci msleep(150); 135362306a36Sopenharmony_ci } 135462306a36Sopenharmony_ci} 135562306a36Sopenharmony_ci 135662306a36Sopenharmony_cistatic const int *piix_init_sata_map(struct pci_dev *pdev, 135762306a36Sopenharmony_ci struct ata_port_info *pinfo, 135862306a36Sopenharmony_ci const struct piix_map_db *map_db) 135962306a36Sopenharmony_ci{ 136062306a36Sopenharmony_ci const int *map; 136162306a36Sopenharmony_ci int i, invalid_map = 0; 136262306a36Sopenharmony_ci u8 map_value; 136362306a36Sopenharmony_ci char buf[32]; 136462306a36Sopenharmony_ci char *p = buf, *end = buf + sizeof(buf); 136562306a36Sopenharmony_ci 136662306a36Sopenharmony_ci pci_read_config_byte(pdev, ICH5_PMR, &map_value); 136762306a36Sopenharmony_ci 136862306a36Sopenharmony_ci map = map_db->map[map_value & map_db->mask]; 136962306a36Sopenharmony_ci 137062306a36Sopenharmony_ci for (i = 0; i < 4; i++) { 137162306a36Sopenharmony_ci switch (map[i]) { 137262306a36Sopenharmony_ci case RV: 137362306a36Sopenharmony_ci invalid_map = 1; 137462306a36Sopenharmony_ci p += scnprintf(p, end - p, " XX"); 137562306a36Sopenharmony_ci break; 137662306a36Sopenharmony_ci 137762306a36Sopenharmony_ci case NA: 137862306a36Sopenharmony_ci p += scnprintf(p, end - p, " --"); 137962306a36Sopenharmony_ci break; 138062306a36Sopenharmony_ci 138162306a36Sopenharmony_ci case IDE: 138262306a36Sopenharmony_ci WARN_ON((i & 1) || map[i + 1] != IDE); 138362306a36Sopenharmony_ci pinfo[i / 2] = piix_port_info[ich_pata_100]; 138462306a36Sopenharmony_ci i++; 138562306a36Sopenharmony_ci p += scnprintf(p, end - p, " IDE IDE"); 138662306a36Sopenharmony_ci break; 138762306a36Sopenharmony_ci 138862306a36Sopenharmony_ci default: 138962306a36Sopenharmony_ci p += scnprintf(p, end - p, " P%d", map[i]); 139062306a36Sopenharmony_ci if (i & 1) 139162306a36Sopenharmony_ci pinfo[i / 2].flags |= ATA_FLAG_SLAVE_POSS; 139262306a36Sopenharmony_ci break; 139362306a36Sopenharmony_ci } 139462306a36Sopenharmony_ci } 139562306a36Sopenharmony_ci dev_info(&pdev->dev, "MAP [%s ]\n", buf); 139662306a36Sopenharmony_ci 139762306a36Sopenharmony_ci if (invalid_map) 139862306a36Sopenharmony_ci dev_err(&pdev->dev, "invalid MAP value %u\n", map_value); 139962306a36Sopenharmony_ci 140062306a36Sopenharmony_ci return map; 140162306a36Sopenharmony_ci} 140262306a36Sopenharmony_ci 140362306a36Sopenharmony_cistatic bool piix_no_sidpr(struct ata_host *host) 140462306a36Sopenharmony_ci{ 140562306a36Sopenharmony_ci struct pci_dev *pdev = to_pci_dev(host->dev); 140662306a36Sopenharmony_ci 140762306a36Sopenharmony_ci /* 140862306a36Sopenharmony_ci * Samsung DB-P70 only has three ATA ports exposed and 140962306a36Sopenharmony_ci * curiously the unconnected first port reports link online 141062306a36Sopenharmony_ci * while not responding to SRST protocol causing excessive 141162306a36Sopenharmony_ci * detection delay. 141262306a36Sopenharmony_ci * 141362306a36Sopenharmony_ci * Unfortunately, the system doesn't carry enough DMI 141462306a36Sopenharmony_ci * information to identify the machine but does have subsystem 141562306a36Sopenharmony_ci * vendor and device set. As it's unclear whether the 141662306a36Sopenharmony_ci * subsystem vendor/device is used only for this specific 141762306a36Sopenharmony_ci * board, the port can't be disabled solely with the 141862306a36Sopenharmony_ci * information; however, turning off SIDPR access works around 141962306a36Sopenharmony_ci * the problem. Turn it off. 142062306a36Sopenharmony_ci * 142162306a36Sopenharmony_ci * This problem is reported in bnc#441240. 142262306a36Sopenharmony_ci * 142362306a36Sopenharmony_ci * https://bugzilla.novell.com/show_bug.cgi?id=441420 142462306a36Sopenharmony_ci */ 142562306a36Sopenharmony_ci if (pdev->vendor == PCI_VENDOR_ID_INTEL && pdev->device == 0x2920 && 142662306a36Sopenharmony_ci pdev->subsystem_vendor == PCI_VENDOR_ID_SAMSUNG && 142762306a36Sopenharmony_ci pdev->subsystem_device == 0xb049) { 142862306a36Sopenharmony_ci dev_warn(host->dev, 142962306a36Sopenharmony_ci "Samsung DB-P70 detected, disabling SIDPR\n"); 143062306a36Sopenharmony_ci return true; 143162306a36Sopenharmony_ci } 143262306a36Sopenharmony_ci 143362306a36Sopenharmony_ci return false; 143462306a36Sopenharmony_ci} 143562306a36Sopenharmony_ci 143662306a36Sopenharmony_cistatic int piix_init_sidpr(struct ata_host *host) 143762306a36Sopenharmony_ci{ 143862306a36Sopenharmony_ci struct pci_dev *pdev = to_pci_dev(host->dev); 143962306a36Sopenharmony_ci struct piix_host_priv *hpriv = host->private_data; 144062306a36Sopenharmony_ci struct ata_link *link0 = &host->ports[0]->link; 144162306a36Sopenharmony_ci u32 scontrol; 144262306a36Sopenharmony_ci int i, rc; 144362306a36Sopenharmony_ci 144462306a36Sopenharmony_ci /* check for availability */ 144562306a36Sopenharmony_ci for (i = 0; i < 4; i++) 144662306a36Sopenharmony_ci if (hpriv->map[i] == IDE) 144762306a36Sopenharmony_ci return 0; 144862306a36Sopenharmony_ci 144962306a36Sopenharmony_ci /* is it blacklisted? */ 145062306a36Sopenharmony_ci if (piix_no_sidpr(host)) 145162306a36Sopenharmony_ci return 0; 145262306a36Sopenharmony_ci 145362306a36Sopenharmony_ci if (!(host->ports[0]->flags & PIIX_FLAG_SIDPR)) 145462306a36Sopenharmony_ci return 0; 145562306a36Sopenharmony_ci 145662306a36Sopenharmony_ci if (pci_resource_start(pdev, PIIX_SIDPR_BAR) == 0 || 145762306a36Sopenharmony_ci pci_resource_len(pdev, PIIX_SIDPR_BAR) != PIIX_SIDPR_LEN) 145862306a36Sopenharmony_ci return 0; 145962306a36Sopenharmony_ci 146062306a36Sopenharmony_ci if (pcim_iomap_regions(pdev, 1 << PIIX_SIDPR_BAR, DRV_NAME)) 146162306a36Sopenharmony_ci return 0; 146262306a36Sopenharmony_ci 146362306a36Sopenharmony_ci hpriv->sidpr = pcim_iomap_table(pdev)[PIIX_SIDPR_BAR]; 146462306a36Sopenharmony_ci 146562306a36Sopenharmony_ci /* SCR access via SIDPR doesn't work on some configurations. 146662306a36Sopenharmony_ci * Give it a test drive by inhibiting power save modes which 146762306a36Sopenharmony_ci * we'll do anyway. 146862306a36Sopenharmony_ci */ 146962306a36Sopenharmony_ci piix_sidpr_scr_read(link0, SCR_CONTROL, &scontrol); 147062306a36Sopenharmony_ci 147162306a36Sopenharmony_ci /* if IPM is already 3, SCR access is probably working. Don't 147262306a36Sopenharmony_ci * un-inhibit power save modes as BIOS might have inhibited 147362306a36Sopenharmony_ci * them for a reason. 147462306a36Sopenharmony_ci */ 147562306a36Sopenharmony_ci if ((scontrol & 0xf00) != 0x300) { 147662306a36Sopenharmony_ci scontrol |= 0x300; 147762306a36Sopenharmony_ci piix_sidpr_scr_write(link0, SCR_CONTROL, scontrol); 147862306a36Sopenharmony_ci piix_sidpr_scr_read(link0, SCR_CONTROL, &scontrol); 147962306a36Sopenharmony_ci 148062306a36Sopenharmony_ci if ((scontrol & 0xf00) != 0x300) { 148162306a36Sopenharmony_ci dev_info(host->dev, 148262306a36Sopenharmony_ci "SCR access via SIDPR is available but doesn't work\n"); 148362306a36Sopenharmony_ci return 0; 148462306a36Sopenharmony_ci } 148562306a36Sopenharmony_ci } 148662306a36Sopenharmony_ci 148762306a36Sopenharmony_ci /* okay, SCRs available, set ops and ask libata for slave_link */ 148862306a36Sopenharmony_ci for (i = 0; i < 2; i++) { 148962306a36Sopenharmony_ci struct ata_port *ap = host->ports[i]; 149062306a36Sopenharmony_ci 149162306a36Sopenharmony_ci ap->ops = &piix_sidpr_sata_ops; 149262306a36Sopenharmony_ci 149362306a36Sopenharmony_ci if (ap->flags & ATA_FLAG_SLAVE_POSS) { 149462306a36Sopenharmony_ci rc = ata_slave_link_init(ap); 149562306a36Sopenharmony_ci if (rc) 149662306a36Sopenharmony_ci return rc; 149762306a36Sopenharmony_ci } 149862306a36Sopenharmony_ci } 149962306a36Sopenharmony_ci 150062306a36Sopenharmony_ci return 0; 150162306a36Sopenharmony_ci} 150262306a36Sopenharmony_ci 150362306a36Sopenharmony_cistatic void piix_iocfg_bit18_quirk(struct ata_host *host) 150462306a36Sopenharmony_ci{ 150562306a36Sopenharmony_ci static const struct dmi_system_id sysids[] = { 150662306a36Sopenharmony_ci { 150762306a36Sopenharmony_ci /* Clevo M570U sets IOCFG bit 18 if the cdrom 150862306a36Sopenharmony_ci * isn't used to boot the system which 150962306a36Sopenharmony_ci * disables the channel. 151062306a36Sopenharmony_ci */ 151162306a36Sopenharmony_ci .ident = "M570U", 151262306a36Sopenharmony_ci .matches = { 151362306a36Sopenharmony_ci DMI_MATCH(DMI_SYS_VENDOR, "Clevo Co."), 151462306a36Sopenharmony_ci DMI_MATCH(DMI_PRODUCT_NAME, "M570U"), 151562306a36Sopenharmony_ci }, 151662306a36Sopenharmony_ci }, 151762306a36Sopenharmony_ci 151862306a36Sopenharmony_ci { } /* terminate list */ 151962306a36Sopenharmony_ci }; 152062306a36Sopenharmony_ci struct pci_dev *pdev = to_pci_dev(host->dev); 152162306a36Sopenharmony_ci struct piix_host_priv *hpriv = host->private_data; 152262306a36Sopenharmony_ci 152362306a36Sopenharmony_ci if (!dmi_check_system(sysids)) 152462306a36Sopenharmony_ci return; 152562306a36Sopenharmony_ci 152662306a36Sopenharmony_ci /* The datasheet says that bit 18 is NOOP but certain systems 152762306a36Sopenharmony_ci * seem to use it to disable a channel. Clear the bit on the 152862306a36Sopenharmony_ci * affected systems. 152962306a36Sopenharmony_ci */ 153062306a36Sopenharmony_ci if (hpriv->saved_iocfg & (1 << 18)) { 153162306a36Sopenharmony_ci dev_info(&pdev->dev, "applying IOCFG bit18 quirk\n"); 153262306a36Sopenharmony_ci pci_write_config_dword(pdev, PIIX_IOCFG, 153362306a36Sopenharmony_ci hpriv->saved_iocfg & ~(1 << 18)); 153462306a36Sopenharmony_ci } 153562306a36Sopenharmony_ci} 153662306a36Sopenharmony_ci 153762306a36Sopenharmony_cistatic bool piix_broken_system_poweroff(struct pci_dev *pdev) 153862306a36Sopenharmony_ci{ 153962306a36Sopenharmony_ci static const struct dmi_system_id broken_systems[] = { 154062306a36Sopenharmony_ci { 154162306a36Sopenharmony_ci .ident = "HP Compaq 2510p", 154262306a36Sopenharmony_ci .matches = { 154362306a36Sopenharmony_ci DMI_MATCH(DMI_SYS_VENDOR, "Hewlett-Packard"), 154462306a36Sopenharmony_ci DMI_MATCH(DMI_PRODUCT_NAME, "HP Compaq 2510p"), 154562306a36Sopenharmony_ci }, 154662306a36Sopenharmony_ci /* PCI slot number of the controller */ 154762306a36Sopenharmony_ci .driver_data = (void *)0x1FUL, 154862306a36Sopenharmony_ci }, 154962306a36Sopenharmony_ci { 155062306a36Sopenharmony_ci .ident = "HP Compaq nc6000", 155162306a36Sopenharmony_ci .matches = { 155262306a36Sopenharmony_ci DMI_MATCH(DMI_SYS_VENDOR, "Hewlett-Packard"), 155362306a36Sopenharmony_ci DMI_MATCH(DMI_PRODUCT_NAME, "HP Compaq nc6000"), 155462306a36Sopenharmony_ci }, 155562306a36Sopenharmony_ci /* PCI slot number of the controller */ 155662306a36Sopenharmony_ci .driver_data = (void *)0x1FUL, 155762306a36Sopenharmony_ci }, 155862306a36Sopenharmony_ci 155962306a36Sopenharmony_ci { } /* terminate list */ 156062306a36Sopenharmony_ci }; 156162306a36Sopenharmony_ci const struct dmi_system_id *dmi = dmi_first_match(broken_systems); 156262306a36Sopenharmony_ci 156362306a36Sopenharmony_ci if (dmi) { 156462306a36Sopenharmony_ci unsigned long slot = (unsigned long)dmi->driver_data; 156562306a36Sopenharmony_ci /* apply the quirk only to on-board controllers */ 156662306a36Sopenharmony_ci return slot == PCI_SLOT(pdev->devfn); 156762306a36Sopenharmony_ci } 156862306a36Sopenharmony_ci 156962306a36Sopenharmony_ci return false; 157062306a36Sopenharmony_ci} 157162306a36Sopenharmony_ci 157262306a36Sopenharmony_cistatic int prefer_ms_hyperv = 1; 157362306a36Sopenharmony_cimodule_param(prefer_ms_hyperv, int, 0); 157462306a36Sopenharmony_ciMODULE_PARM_DESC(prefer_ms_hyperv, 157562306a36Sopenharmony_ci "Prefer Hyper-V paravirtualization drivers instead of ATA, " 157662306a36Sopenharmony_ci "0 - Use ATA drivers, " 157762306a36Sopenharmony_ci "1 (Default) - Use the paravirtualization drivers."); 157862306a36Sopenharmony_ci 157962306a36Sopenharmony_cistatic void piix_ignore_devices_quirk(struct ata_host *host) 158062306a36Sopenharmony_ci{ 158162306a36Sopenharmony_ci#if IS_ENABLED(CONFIG_HYPERV_STORAGE) 158262306a36Sopenharmony_ci static const struct dmi_system_id ignore_hyperv[] = { 158362306a36Sopenharmony_ci { 158462306a36Sopenharmony_ci /* On Hyper-V hypervisors the disks are exposed on 158562306a36Sopenharmony_ci * both the emulated SATA controller and on the 158662306a36Sopenharmony_ci * paravirtualised drivers. The CD/DVD devices 158762306a36Sopenharmony_ci * are only exposed on the emulated controller. 158862306a36Sopenharmony_ci * Request we ignore ATA devices on this host. 158962306a36Sopenharmony_ci */ 159062306a36Sopenharmony_ci .ident = "Hyper-V Virtual Machine", 159162306a36Sopenharmony_ci .matches = { 159262306a36Sopenharmony_ci DMI_MATCH(DMI_SYS_VENDOR, 159362306a36Sopenharmony_ci "Microsoft Corporation"), 159462306a36Sopenharmony_ci DMI_MATCH(DMI_PRODUCT_NAME, "Virtual Machine"), 159562306a36Sopenharmony_ci }, 159662306a36Sopenharmony_ci }, 159762306a36Sopenharmony_ci { } /* terminate list */ 159862306a36Sopenharmony_ci }; 159962306a36Sopenharmony_ci static const struct dmi_system_id allow_virtual_pc[] = { 160062306a36Sopenharmony_ci { 160162306a36Sopenharmony_ci /* In MS Virtual PC guests the DMI ident is nearly 160262306a36Sopenharmony_ci * identical to a Hyper-V guest. One difference is the 160362306a36Sopenharmony_ci * product version which is used here to identify 160462306a36Sopenharmony_ci * a Virtual PC guest. This entry allows ata_piix to 160562306a36Sopenharmony_ci * drive the emulated hardware. 160662306a36Sopenharmony_ci */ 160762306a36Sopenharmony_ci .ident = "MS Virtual PC 2007", 160862306a36Sopenharmony_ci .matches = { 160962306a36Sopenharmony_ci DMI_MATCH(DMI_SYS_VENDOR, 161062306a36Sopenharmony_ci "Microsoft Corporation"), 161162306a36Sopenharmony_ci DMI_MATCH(DMI_PRODUCT_NAME, "Virtual Machine"), 161262306a36Sopenharmony_ci DMI_MATCH(DMI_PRODUCT_VERSION, "VS2005R2"), 161362306a36Sopenharmony_ci }, 161462306a36Sopenharmony_ci }, 161562306a36Sopenharmony_ci { } /* terminate list */ 161662306a36Sopenharmony_ci }; 161762306a36Sopenharmony_ci const struct dmi_system_id *ignore = dmi_first_match(ignore_hyperv); 161862306a36Sopenharmony_ci const struct dmi_system_id *allow = dmi_first_match(allow_virtual_pc); 161962306a36Sopenharmony_ci 162062306a36Sopenharmony_ci if (ignore && !allow && prefer_ms_hyperv) { 162162306a36Sopenharmony_ci host->flags |= ATA_HOST_IGNORE_ATA; 162262306a36Sopenharmony_ci dev_info(host->dev, "%s detected, ATA device ignore set\n", 162362306a36Sopenharmony_ci ignore->ident); 162462306a36Sopenharmony_ci } 162562306a36Sopenharmony_ci#endif 162662306a36Sopenharmony_ci} 162762306a36Sopenharmony_ci 162862306a36Sopenharmony_ci/** 162962306a36Sopenharmony_ci * piix_init_one - Register PIIX ATA PCI device with kernel services 163062306a36Sopenharmony_ci * @pdev: PCI device to register 163162306a36Sopenharmony_ci * @ent: Entry in piix_pci_tbl matching with @pdev 163262306a36Sopenharmony_ci * 163362306a36Sopenharmony_ci * Called from kernel PCI layer. We probe for combined mode (sigh), 163462306a36Sopenharmony_ci * and then hand over control to libata, for it to do the rest. 163562306a36Sopenharmony_ci * 163662306a36Sopenharmony_ci * LOCKING: 163762306a36Sopenharmony_ci * Inherited from PCI layer (may sleep). 163862306a36Sopenharmony_ci * 163962306a36Sopenharmony_ci * RETURNS: 164062306a36Sopenharmony_ci * Zero on success, or -ERRNO value. 164162306a36Sopenharmony_ci */ 164262306a36Sopenharmony_ci 164362306a36Sopenharmony_cistatic int piix_init_one(struct pci_dev *pdev, const struct pci_device_id *ent) 164462306a36Sopenharmony_ci{ 164562306a36Sopenharmony_ci struct device *dev = &pdev->dev; 164662306a36Sopenharmony_ci struct ata_port_info port_info[2]; 164762306a36Sopenharmony_ci const struct ata_port_info *ppi[] = { &port_info[0], &port_info[1] }; 164862306a36Sopenharmony_ci const struct scsi_host_template *sht = &piix_sht; 164962306a36Sopenharmony_ci unsigned long port_flags; 165062306a36Sopenharmony_ci struct ata_host *host; 165162306a36Sopenharmony_ci struct piix_host_priv *hpriv; 165262306a36Sopenharmony_ci int rc; 165362306a36Sopenharmony_ci 165462306a36Sopenharmony_ci ata_print_version_once(&pdev->dev, DRV_VERSION); 165562306a36Sopenharmony_ci 165662306a36Sopenharmony_ci /* no hotplugging support for later devices (FIXME) */ 165762306a36Sopenharmony_ci if (!in_module_init && ent->driver_data >= ich5_sata) 165862306a36Sopenharmony_ci return -ENODEV; 165962306a36Sopenharmony_ci 166062306a36Sopenharmony_ci if (piix_broken_system_poweroff(pdev)) { 166162306a36Sopenharmony_ci piix_port_info[ent->driver_data].flags |= 166262306a36Sopenharmony_ci ATA_FLAG_NO_POWEROFF_SPINDOWN | 166362306a36Sopenharmony_ci ATA_FLAG_NO_HIBERNATE_SPINDOWN; 166462306a36Sopenharmony_ci dev_info(&pdev->dev, "quirky BIOS, skipping spindown " 166562306a36Sopenharmony_ci "on poweroff and hibernation\n"); 166662306a36Sopenharmony_ci } 166762306a36Sopenharmony_ci 166862306a36Sopenharmony_ci port_info[0] = piix_port_info[ent->driver_data]; 166962306a36Sopenharmony_ci port_info[1] = piix_port_info[ent->driver_data]; 167062306a36Sopenharmony_ci 167162306a36Sopenharmony_ci port_flags = port_info[0].flags; 167262306a36Sopenharmony_ci 167362306a36Sopenharmony_ci /* enable device and prepare host */ 167462306a36Sopenharmony_ci rc = pcim_enable_device(pdev); 167562306a36Sopenharmony_ci if (rc) 167662306a36Sopenharmony_ci return rc; 167762306a36Sopenharmony_ci 167862306a36Sopenharmony_ci hpriv = devm_kzalloc(dev, sizeof(*hpriv), GFP_KERNEL); 167962306a36Sopenharmony_ci if (!hpriv) 168062306a36Sopenharmony_ci return -ENOMEM; 168162306a36Sopenharmony_ci 168262306a36Sopenharmony_ci /* Save IOCFG, this will be used for cable detection, quirk 168362306a36Sopenharmony_ci * detection and restoration on detach. This is necessary 168462306a36Sopenharmony_ci * because some ACPI implementations mess up cable related 168562306a36Sopenharmony_ci * bits on _STM. Reported on kernel bz#11879. 168662306a36Sopenharmony_ci */ 168762306a36Sopenharmony_ci pci_read_config_dword(pdev, PIIX_IOCFG, &hpriv->saved_iocfg); 168862306a36Sopenharmony_ci 168962306a36Sopenharmony_ci /* ICH6R may be driven by either ata_piix or ahci driver 169062306a36Sopenharmony_ci * regardless of BIOS configuration. Make sure AHCI mode is 169162306a36Sopenharmony_ci * off. 169262306a36Sopenharmony_ci */ 169362306a36Sopenharmony_ci if (pdev->vendor == PCI_VENDOR_ID_INTEL && pdev->device == 0x2652) { 169462306a36Sopenharmony_ci rc = piix_disable_ahci(pdev); 169562306a36Sopenharmony_ci if (rc) 169662306a36Sopenharmony_ci return rc; 169762306a36Sopenharmony_ci } 169862306a36Sopenharmony_ci 169962306a36Sopenharmony_ci /* SATA map init can change port_info, do it before prepping host */ 170062306a36Sopenharmony_ci if (port_flags & ATA_FLAG_SATA) 170162306a36Sopenharmony_ci hpriv->map = piix_init_sata_map(pdev, port_info, 170262306a36Sopenharmony_ci piix_map_db_table[ent->driver_data]); 170362306a36Sopenharmony_ci 170462306a36Sopenharmony_ci rc = ata_pci_bmdma_prepare_host(pdev, ppi, &host); 170562306a36Sopenharmony_ci if (rc) 170662306a36Sopenharmony_ci return rc; 170762306a36Sopenharmony_ci host->private_data = hpriv; 170862306a36Sopenharmony_ci 170962306a36Sopenharmony_ci /* initialize controller */ 171062306a36Sopenharmony_ci if (port_flags & ATA_FLAG_SATA) { 171162306a36Sopenharmony_ci piix_init_pcs(host, piix_map_db_table[ent->driver_data]); 171262306a36Sopenharmony_ci rc = piix_init_sidpr(host); 171362306a36Sopenharmony_ci if (rc) 171462306a36Sopenharmony_ci return rc; 171562306a36Sopenharmony_ci if (host->ports[0]->ops == &piix_sidpr_sata_ops) 171662306a36Sopenharmony_ci sht = &piix_sidpr_sht; 171762306a36Sopenharmony_ci } 171862306a36Sopenharmony_ci 171962306a36Sopenharmony_ci /* apply IOCFG bit18 quirk */ 172062306a36Sopenharmony_ci piix_iocfg_bit18_quirk(host); 172162306a36Sopenharmony_ci 172262306a36Sopenharmony_ci /* On ICH5, some BIOSen disable the interrupt using the 172362306a36Sopenharmony_ci * PCI_COMMAND_INTX_DISABLE bit added in PCI 2.3. 172462306a36Sopenharmony_ci * On ICH6, this bit has the same effect, but only when 172562306a36Sopenharmony_ci * MSI is disabled (and it is disabled, as we don't use 172662306a36Sopenharmony_ci * message-signalled interrupts currently). 172762306a36Sopenharmony_ci */ 172862306a36Sopenharmony_ci if (port_flags & PIIX_FLAG_CHECKINTR) 172962306a36Sopenharmony_ci pci_intx(pdev, 1); 173062306a36Sopenharmony_ci 173162306a36Sopenharmony_ci if (piix_check_450nx_errata(pdev)) { 173262306a36Sopenharmony_ci /* This writes into the master table but it does not 173362306a36Sopenharmony_ci really matter for this errata as we will apply it to 173462306a36Sopenharmony_ci all the PIIX devices on the board */ 173562306a36Sopenharmony_ci host->ports[0]->mwdma_mask = 0; 173662306a36Sopenharmony_ci host->ports[0]->udma_mask = 0; 173762306a36Sopenharmony_ci host->ports[1]->mwdma_mask = 0; 173862306a36Sopenharmony_ci host->ports[1]->udma_mask = 0; 173962306a36Sopenharmony_ci } 174062306a36Sopenharmony_ci host->flags |= ATA_HOST_PARALLEL_SCAN; 174162306a36Sopenharmony_ci 174262306a36Sopenharmony_ci /* Allow hosts to specify device types to ignore when scanning. */ 174362306a36Sopenharmony_ci piix_ignore_devices_quirk(host); 174462306a36Sopenharmony_ci 174562306a36Sopenharmony_ci pci_set_master(pdev); 174662306a36Sopenharmony_ci return ata_pci_sff_activate_host(host, ata_bmdma_interrupt, sht); 174762306a36Sopenharmony_ci} 174862306a36Sopenharmony_ci 174962306a36Sopenharmony_cistatic void piix_remove_one(struct pci_dev *pdev) 175062306a36Sopenharmony_ci{ 175162306a36Sopenharmony_ci struct ata_host *host = pci_get_drvdata(pdev); 175262306a36Sopenharmony_ci struct piix_host_priv *hpriv = host->private_data; 175362306a36Sopenharmony_ci 175462306a36Sopenharmony_ci pci_write_config_dword(pdev, PIIX_IOCFG, hpriv->saved_iocfg); 175562306a36Sopenharmony_ci 175662306a36Sopenharmony_ci ata_pci_remove_one(pdev); 175762306a36Sopenharmony_ci} 175862306a36Sopenharmony_ci 175962306a36Sopenharmony_cistatic struct pci_driver piix_pci_driver = { 176062306a36Sopenharmony_ci .name = DRV_NAME, 176162306a36Sopenharmony_ci .id_table = piix_pci_tbl, 176262306a36Sopenharmony_ci .probe = piix_init_one, 176362306a36Sopenharmony_ci .remove = piix_remove_one, 176462306a36Sopenharmony_ci#ifdef CONFIG_PM_SLEEP 176562306a36Sopenharmony_ci .suspend = piix_pci_device_suspend, 176662306a36Sopenharmony_ci .resume = piix_pci_device_resume, 176762306a36Sopenharmony_ci#endif 176862306a36Sopenharmony_ci}; 176962306a36Sopenharmony_ci 177062306a36Sopenharmony_cistatic int __init piix_init(void) 177162306a36Sopenharmony_ci{ 177262306a36Sopenharmony_ci int rc; 177362306a36Sopenharmony_ci 177462306a36Sopenharmony_ci rc = pci_register_driver(&piix_pci_driver); 177562306a36Sopenharmony_ci if (rc) 177662306a36Sopenharmony_ci return rc; 177762306a36Sopenharmony_ci 177862306a36Sopenharmony_ci in_module_init = 0; 177962306a36Sopenharmony_ci 178062306a36Sopenharmony_ci return 0; 178162306a36Sopenharmony_ci} 178262306a36Sopenharmony_ci 178362306a36Sopenharmony_cistatic void __exit piix_exit(void) 178462306a36Sopenharmony_ci{ 178562306a36Sopenharmony_ci pci_unregister_driver(&piix_pci_driver); 178662306a36Sopenharmony_ci} 178762306a36Sopenharmony_ci 178862306a36Sopenharmony_cimodule_init(piix_init); 178962306a36Sopenharmony_cimodule_exit(piix_exit); 1790