| Linus Torvalds | 1da177e | 2005-04-16 15:20:36 -0700 | [diff] [blame] | 1 | /* | 
| Jeff Garzik | af36d7f | 2005-08-28 20:18:39 -0400 | [diff] [blame] | 2 | *    ata_piix.c - Intel PATA/SATA controllers | 
|  | 3 | * | 
|  | 4 | *    Maintained by:  Jeff Garzik <jgarzik@pobox.com> | 
|  | 5 | *    		    Please ALWAYS copy linux-ide@vger.kernel.org | 
|  | 6 | *		    on emails. | 
|  | 7 | * | 
|  | 8 | * | 
|  | 9 | *	Copyright 2003-2005 Red Hat Inc | 
|  | 10 | *	Copyright 2003-2005 Jeff Garzik | 
|  | 11 | * | 
|  | 12 | * | 
|  | 13 | *	Copyright header from piix.c: | 
|  | 14 | * | 
|  | 15 | *  Copyright (C) 1998-1999 Andrzej Krzysztofowicz, Author and Maintainer | 
|  | 16 | *  Copyright (C) 1998-2000 Andre Hedrick <andre@linux-ide.org> | 
| Alan Cox | ab77163 | 2008-10-27 15:09:10 +0000 | [diff] [blame] | 17 | *  Copyright (C) 2003 Red Hat Inc | 
| Jeff Garzik | af36d7f | 2005-08-28 20:18:39 -0400 | [diff] [blame] | 18 | * | 
|  | 19 | * | 
|  | 20 | *  This program is free software; you can redistribute it and/or modify | 
|  | 21 | *  it under the terms of the GNU General Public License as published by | 
|  | 22 | *  the Free Software Foundation; either version 2, or (at your option) | 
|  | 23 | *  any later version. | 
|  | 24 | * | 
|  | 25 | *  This program is distributed in the hope that it will be useful, | 
|  | 26 | *  but WITHOUT ANY WARRANTY; without even the implied warranty of | 
|  | 27 | *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the | 
|  | 28 | *  GNU General Public License for more details. | 
|  | 29 | * | 
|  | 30 | *  You should have received a copy of the GNU General Public License | 
|  | 31 | *  along with this program; see the file COPYING.  If not, write to | 
|  | 32 | *  the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. | 
|  | 33 | * | 
|  | 34 | * | 
|  | 35 | *  libata documentation is available via 'make {ps|pdf}docs', | 
|  | 36 | *  as Documentation/DocBook/libata.* | 
|  | 37 | * | 
|  | 38 | *  Hardware documentation available at http://developer.intel.com/ | 
|  | 39 | * | 
| Alan Cox | d96212e | 2005-12-08 19:19:50 +0000 | [diff] [blame] | 40 | * Documentation | 
|  | 41 | *	Publically available from Intel web site. Errata documentation | 
|  | 42 | * is also publically available. As an aide to anyone hacking on this | 
| Alan | 2c5ff67 | 2006-12-04 16:33:20 +0000 | [diff] [blame] | 43 | * driver the list of errata that are relevant is below, going back to | 
| Alan Cox | d96212e | 2005-12-08 19:19:50 +0000 | [diff] [blame] | 44 | * PIIX4. Older device documentation is now a bit tricky to find. | 
|  | 45 | * | 
| Thomas Weber | 8839316 | 2010-03-16 11:47:56 +0100 | [diff] [blame] | 46 | * The chipsets all follow very much the same design. The original Triton | 
| Alan Cox | d96212e | 2005-12-08 19:19:50 +0000 | [diff] [blame] | 47 | * series chipsets do _not_ support independant device timings, but this | 
|  | 48 | * is fixed in Triton II. With the odd mobile exception the chips then | 
|  | 49 | * change little except in gaining more modes until SATA arrives. This | 
|  | 50 | * driver supports only the chips with independant timing (that is those | 
|  | 51 | * with SITRE and the 0x44 timing register). See pata_oldpiix and pata_mpiix | 
|  | 52 | * for the early chip drivers. | 
|  | 53 | * | 
|  | 54 | * Errata of note: | 
|  | 55 | * | 
|  | 56 | * Unfixable | 
|  | 57 | *	PIIX4    errata #9	- Only on ultra obscure hw | 
|  | 58 | *	ICH3	 errata #13     - Not observed to affect real hw | 
|  | 59 | *				  by Intel | 
|  | 60 | * | 
|  | 61 | * Things we must deal with | 
|  | 62 | *	PIIX4	errata #10	- BM IDE hang with non UDMA | 
|  | 63 | *				  (must stop/start dma to recover) | 
|  | 64 | *	440MX   errata #15	- As PIIX4 errata #10 | 
|  | 65 | *	PIIX4	errata #15	- Must not read control registers | 
|  | 66 | * 				  during a PIO transfer | 
|  | 67 | *	440MX   errata #13	- As PIIX4 errata #15 | 
|  | 68 | *	ICH2	errata #21	- DMA mode 0 doesn't work right | 
|  | 69 | *	ICH0/1  errata #55	- As ICH2 errata #21 | 
|  | 70 | *	ICH2	spec c #9	- Extra operations needed to handle | 
|  | 71 | *				  drive hotswap [NOT YET SUPPORTED] | 
|  | 72 | *	ICH2    spec c #20	- IDE PRD must not cross a 64K boundary | 
|  | 73 | *				  and must be dword aligned | 
|  | 74 | *	ICH2    spec c #24	- UDMA mode 4,5 t85/86 should be 6ns not 3.3 | 
| Alan Cox | c611bed | 2009-05-06 17:08:44 +0100 | [diff] [blame] | 75 | *	ICH7	errata #16	- MWDMA1 timings are incorrect | 
| Alan Cox | d96212e | 2005-12-08 19:19:50 +0000 | [diff] [blame] | 76 | * | 
|  | 77 | * Should have been BIOS fixed: | 
|  | 78 | *	450NX:	errata #19	- DMA hangs on old 450NX | 
|  | 79 | *	450NX:  errata #20	- DMA hangs on old 450NX | 
|  | 80 | *	450NX:  errata #25	- Corruption with DMA on old 450NX | 
|  | 81 | *	ICH3    errata #15      - IDE deadlock under high load | 
|  | 82 | *				  (BIOS must set dev 31 fn 0 bit 23) | 
|  | 83 | *	ICH3	errata #18	- Don't use native mode | 
| Linus Torvalds | 1da177e | 2005-04-16 15:20:36 -0700 | [diff] [blame] | 84 | */ | 
|  | 85 |  | 
|  | 86 | #include <linux/kernel.h> | 
|  | 87 | #include <linux/module.h> | 
|  | 88 | #include <linux/pci.h> | 
|  | 89 | #include <linux/init.h> | 
|  | 90 | #include <linux/blkdev.h> | 
|  | 91 | #include <linux/delay.h> | 
| Jeff Garzik | 6248e64 | 2005-10-30 06:42:18 -0500 | [diff] [blame] | 92 | #include <linux/device.h> | 
| Tejun Heo | 5a0e3ad | 2010-03-24 17:04:11 +0900 | [diff] [blame] | 93 | #include <linux/gfp.h> | 
| Linus Torvalds | 1da177e | 2005-04-16 15:20:36 -0700 | [diff] [blame] | 94 | #include <scsi/scsi_host.h> | 
|  | 95 | #include <linux/libata.h> | 
| Tejun Heo | b8b275e | 2007-07-10 15:55:43 +0900 | [diff] [blame] | 96 | #include <linux/dmi.h> | 
| Linus Torvalds | 1da177e | 2005-04-16 15:20:36 -0700 | [diff] [blame] | 97 |  | 
|  | 98 | #define DRV_NAME	"ata_piix" | 
| Alan Cox | c611bed | 2009-05-06 17:08:44 +0100 | [diff] [blame] | 99 | #define DRV_VERSION	"2.13" | 
| Linus Torvalds | 1da177e | 2005-04-16 15:20:36 -0700 | [diff] [blame] | 100 |  | 
|  | 101 | enum { | 
|  | 102 | PIIX_IOCFG		= 0x54, /* IDE I/O configuration register */ | 
|  | 103 | ICH5_PMR		= 0x90, /* port mapping register */ | 
|  | 104 | ICH5_PCS		= 0x92,	/* port control and status */ | 
| Tejun Heo | c729072 | 2008-01-18 18:36:30 +0900 | [diff] [blame] | 105 | PIIX_SIDPR_BAR		= 5, | 
|  | 106 | PIIX_SIDPR_LEN		= 16, | 
|  | 107 | PIIX_SIDPR_IDX		= 0, | 
|  | 108 | PIIX_SIDPR_DATA		= 4, | 
| Linus Torvalds | 1da177e | 2005-04-16 15:20:36 -0700 | [diff] [blame] | 109 |  | 
| Tejun Heo | ff0fc14 | 2005-12-18 17:17:07 +0900 | [diff] [blame] | 110 | PIIX_FLAG_CHECKINTR	= (1 << 28), /* make sure PCI INTx enabled */ | 
| Tejun Heo | c729072 | 2008-01-18 18:36:30 +0900 | [diff] [blame] | 111 | PIIX_FLAG_SIDPR		= (1 << 29), /* SATA idx/data pair regs */ | 
| Linus Torvalds | 1da177e | 2005-04-16 15:20:36 -0700 | [diff] [blame] | 112 |  | 
| Tejun Heo | 800b399 | 2006-12-03 21:34:13 +0900 | [diff] [blame] | 113 | PIIX_PATA_FLAGS		= ATA_FLAG_SLAVE_POSS, | 
|  | 114 | PIIX_SATA_FLAGS		= ATA_FLAG_SATA | PIIX_FLAG_CHECKINTR, | 
| Tejun Heo | b3362f8 | 2006-11-10 18:08:10 +0900 | [diff] [blame] | 115 |  | 
| Linus Torvalds | 1da177e | 2005-04-16 15:20:36 -0700 | [diff] [blame] | 116 | PIIX_80C_PRI		= (1 << 5) | (1 << 4), | 
|  | 117 | PIIX_80C_SEC		= (1 << 7) | (1 << 6), | 
|  | 118 |  | 
| Tejun Heo | d33f58b | 2006-03-01 01:25:39 +0900 | [diff] [blame] | 119 | /* constants for mapping table */ | 
|  | 120 | P0			= 0,  /* port 0 */ | 
|  | 121 | P1			= 1,  /* port 1 */ | 
|  | 122 | P2			= 2,  /* port 2 */ | 
|  | 123 | P3			= 3,  /* port 3 */ | 
|  | 124 | IDE			= -1, /* IDE */ | 
|  | 125 | NA			= -2, /* not avaliable */ | 
|  | 126 | RV			= -3, /* reserved */ | 
|  | 127 |  | 
| Greg Felix | 7b6dbd6 | 2005-07-28 15:54:15 -0400 | [diff] [blame] | 128 | PIIX_AHCI_DEVICE	= 6, | 
| Tejun Heo | b8b275e | 2007-07-10 15:55:43 +0900 | [diff] [blame] | 129 |  | 
|  | 130 | /* host->flags bits */ | 
|  | 131 | PIIX_HOST_BROKEN_SUSPEND = (1 << 24), | 
| Linus Torvalds | 1da177e | 2005-04-16 15:20:36 -0700 | [diff] [blame] | 132 | }; | 
|  | 133 |  | 
| Tejun Heo | 9cde9ed1 | 2007-11-24 21:16:07 +0900 | [diff] [blame] | 134 | enum piix_controller_ids { | 
|  | 135 | /* controller IDs */ | 
|  | 136 | piix_pata_mwdma,	/* PIIX3 MWDMA only */ | 
|  | 137 | piix_pata_33,		/* PIIX4 at 33Mhz */ | 
|  | 138 | ich_pata_33,		/* ICH up to UDMA 33 only */ | 
|  | 139 | ich_pata_66,		/* ICH up to 66 Mhz */ | 
|  | 140 | ich_pata_100,		/* ICH up to UDMA 100 */ | 
| Alan Cox | c611bed | 2009-05-06 17:08:44 +0100 | [diff] [blame] | 141 | ich_pata_100_nomwdma1,	/* ICH up to UDMA 100 but with no MWDMA1*/ | 
| Tejun Heo | 9cde9ed1 | 2007-11-24 21:16:07 +0900 | [diff] [blame] | 142 | ich5_sata, | 
|  | 143 | ich6_sata, | 
| Tejun Heo | 9c0bf67 | 2008-03-26 16:00:58 +0900 | [diff] [blame] | 144 | ich6m_sata, | 
|  | 145 | ich8_sata, | 
| Tejun Heo | 9cde9ed1 | 2007-11-24 21:16:07 +0900 | [diff] [blame] | 146 | ich8_2port_sata, | 
| Tejun Heo | 9c0bf67 | 2008-03-26 16:00:58 +0900 | [diff] [blame] | 147 | ich8m_apple_sata,	/* locks up on second port enable */ | 
|  | 148 | tolapai_sata, | 
| Tejun Heo | 9cde9ed1 | 2007-11-24 21:16:07 +0900 | [diff] [blame] | 149 | piix_pata_vmw,			/* PIIX4 for VMware, spurious DMA_ERR */ | 
|  | 150 | }; | 
|  | 151 |  | 
| Tejun Heo | d33f58b | 2006-03-01 01:25:39 +0900 | [diff] [blame] | 152 | struct piix_map_db { | 
|  | 153 | const u32 mask; | 
| Jeff Garzik | 73291a1 | 2006-07-11 13:11:17 -0400 | [diff] [blame] | 154 | const u16 port_enable; | 
| Tejun Heo | d33f58b | 2006-03-01 01:25:39 +0900 | [diff] [blame] | 155 | const int map[][4]; | 
|  | 156 | }; | 
|  | 157 |  | 
| Tejun Heo | d96715c | 2006-06-29 01:58:28 +0900 | [diff] [blame] | 158 | struct piix_host_priv { | 
|  | 159 | const int *map; | 
| Tejun Heo | 2852bcf | 2009-01-02 12:04:48 +0900 | [diff] [blame] | 160 | u32 saved_iocfg; | 
| Tejun Heo | c729072 | 2008-01-18 18:36:30 +0900 | [diff] [blame] | 161 | void __iomem *sidpr; | 
| Tejun Heo | d96715c | 2006-06-29 01:58:28 +0900 | [diff] [blame] | 162 | }; | 
|  | 163 |  | 
| Jeff Garzik | 2dcb407 | 2007-10-19 06:42:56 -0400 | [diff] [blame] | 164 | static int piix_init_one(struct pci_dev *pdev, | 
|  | 165 | const struct pci_device_id *ent); | 
| Tejun Heo | 2852bcf | 2009-01-02 12:04:48 +0900 | [diff] [blame] | 166 | static void piix_remove_one(struct pci_dev *pdev); | 
| Tejun Heo | a1efdab | 2008-03-25 12:22:50 +0900 | [diff] [blame] | 167 | static int piix_pata_prereset(struct ata_link *link, unsigned long deadline); | 
| Jeff Garzik | 2dcb407 | 2007-10-19 06:42:56 -0400 | [diff] [blame] | 168 | static void piix_set_piomode(struct ata_port *ap, struct ata_device *adev); | 
|  | 169 | static void piix_set_dmamode(struct ata_port *ap, struct ata_device *adev); | 
|  | 170 | static void ich_set_dmamode(struct ata_port *ap, struct ata_device *adev); | 
| Alan Cox | eb4a2c7 | 2007-04-11 00:04:20 +0100 | [diff] [blame] | 171 | static int ich_pata_cable_detect(struct ata_port *ap); | 
| Tejun Heo | 25f9813 | 2008-01-07 19:38:53 +0900 | [diff] [blame] | 172 | static u8 piix_vmw_bmdma_status(struct ata_port *ap); | 
| Tejun Heo | 82ef04f | 2008-07-31 17:02:40 +0900 | [diff] [blame] | 173 | static int piix_sidpr_scr_read(struct ata_link *link, | 
|  | 174 | unsigned int reg, u32 *val); | 
|  | 175 | static int piix_sidpr_scr_write(struct ata_link *link, | 
|  | 176 | unsigned int reg, u32 val); | 
| Tejun Heo | a97c4006 | 2010-09-01 17:50:08 +0200 | [diff] [blame] | 177 | static int piix_sidpr_set_lpm(struct ata_link *link, enum ata_lpm_policy policy, | 
|  | 178 | unsigned hints); | 
| Tejun Heo | 2794362 | 2010-01-19 10:49:19 +0900 | [diff] [blame] | 179 | static bool piix_irq_check(struct ata_port *ap); | 
| Tejun Heo | b8b275e | 2007-07-10 15:55:43 +0900 | [diff] [blame] | 180 | #ifdef CONFIG_PM | 
|  | 181 | static int piix_pci_device_suspend(struct pci_dev *pdev, pm_message_t mesg); | 
|  | 182 | static int piix_pci_device_resume(struct pci_dev *pdev); | 
|  | 183 | #endif | 
| Linus Torvalds | 1da177e | 2005-04-16 15:20:36 -0700 | [diff] [blame] | 184 |  | 
|  | 185 | static unsigned int in_module_init = 1; | 
|  | 186 |  | 
| Jeff Garzik | 3b7d697 | 2005-11-10 11:04:11 -0500 | [diff] [blame] | 187 | static const struct pci_device_id piix_pci_tbl[] = { | 
| Alan | d2cdfc0 | 2007-01-10 17:13:38 +0000 | [diff] [blame] | 188 | /* Intel PIIX3 for the 430HX etc */ | 
|  | 189 | { 0x8086, 0x7010, PCI_ANY_ID, PCI_ANY_ID, 0, 0, piix_pata_mwdma }, | 
| Tejun Heo | 25f9813 | 2008-01-07 19:38:53 +0900 | [diff] [blame] | 190 | /* VMware ICH4 */ | 
|  | 191 | { 0x8086, 0x7111, 0x15ad, 0x1976, 0, 0, piix_pata_vmw }, | 
| Jeff Garzik | 669a5db | 2006-08-29 18:12:40 -0400 | [diff] [blame] | 192 | /* Intel PIIX4 for the 430TX/440BX/MX chipset: UDMA 33 */ | 
|  | 193 | /* Also PIIX4E (fn3 rev 2) and PIIX4M (fn3 rev 3) */ | 
|  | 194 | { 0x8086, 0x7111, PCI_ANY_ID, PCI_ANY_ID, 0, 0, piix_pata_33 }, | 
| Jeff Garzik | 669a5db | 2006-08-29 18:12:40 -0400 | [diff] [blame] | 195 | /* Intel PIIX4 */ | 
|  | 196 | { 0x8086, 0x7199, PCI_ANY_ID, PCI_ANY_ID, 0, 0, piix_pata_33 }, | 
|  | 197 | /* Intel PIIX4 */ | 
|  | 198 | { 0x8086, 0x7601, PCI_ANY_ID, PCI_ANY_ID, 0, 0, piix_pata_33 }, | 
|  | 199 | /* Intel PIIX */ | 
|  | 200 | { 0x8086, 0x84CA, PCI_ANY_ID, PCI_ANY_ID, 0, 0, piix_pata_33 }, | 
|  | 201 | /* Intel ICH (i810, i815, i840) UDMA 66*/ | 
|  | 202 | { 0x8086, 0x2411, PCI_ANY_ID, PCI_ANY_ID, 0, 0, ich_pata_66 }, | 
|  | 203 | /* Intel ICH0 : UDMA 33*/ | 
|  | 204 | { 0x8086, 0x2421, PCI_ANY_ID, PCI_ANY_ID, 0, 0, ich_pata_33 }, | 
|  | 205 | /* Intel ICH2M */ | 
|  | 206 | { 0x8086, 0x244A, PCI_ANY_ID, PCI_ANY_ID, 0, 0, ich_pata_100 }, | 
|  | 207 | /* Intel ICH2 (i810E2, i845, 850, 860) UDMA 100 */ | 
|  | 208 | { 0x8086, 0x244B, PCI_ANY_ID, PCI_ANY_ID, 0, 0, ich_pata_100 }, | 
|  | 209 | /*  Intel ICH3M */ | 
|  | 210 | { 0x8086, 0x248A, PCI_ANY_ID, PCI_ANY_ID, 0, 0, ich_pata_100 }, | 
|  | 211 | /* Intel ICH3 (E7500/1) UDMA 100 */ | 
|  | 212 | { 0x8086, 0x248B, PCI_ANY_ID, PCI_ANY_ID, 0, 0, ich_pata_100 }, | 
| Ben Hutchings | 4bb969d | 2010-10-10 22:42:21 +0100 | [diff] [blame] | 213 | /* Intel ICH4-L */ | 
|  | 214 | { 0x8086, 0x24C1, PCI_ANY_ID, PCI_ANY_ID, 0, 0, ich_pata_100 }, | 
| Jeff Garzik | 669a5db | 2006-08-29 18:12:40 -0400 | [diff] [blame] | 215 | /* Intel ICH4 (i845GV, i845E, i852, i855) UDMA 100 */ | 
|  | 216 | { 0x8086, 0x24CA, PCI_ANY_ID, PCI_ANY_ID, 0, 0, ich_pata_100 }, | 
|  | 217 | { 0x8086, 0x24CB, PCI_ANY_ID, PCI_ANY_ID, 0, 0, ich_pata_100 }, | 
|  | 218 | /* Intel ICH5 */ | 
| Christian Lamparter | 2eb829e | 2007-08-10 13:59:51 -0700 | [diff] [blame] | 219 | { 0x8086, 0x24DB, PCI_ANY_ID, PCI_ANY_ID, 0, 0, ich_pata_100 }, | 
| Jeff Garzik | 669a5db | 2006-08-29 18:12:40 -0400 | [diff] [blame] | 220 | /* C-ICH (i810E2) */ | 
|  | 221 | { 0x8086, 0x245B, PCI_ANY_ID, PCI_ANY_ID, 0, 0, ich_pata_100 }, | 
| Jeff Garzik | 85cd725 | 2006-08-31 00:03:49 -0400 | [diff] [blame] | 222 | /* ESB (855GME/875P + 6300ESB) UDMA 100  */ | 
| Jeff Garzik | 669a5db | 2006-08-29 18:12:40 -0400 | [diff] [blame] | 223 | { 0x8086, 0x25A2, PCI_ANY_ID, PCI_ANY_ID, 0, 0, ich_pata_100 }, | 
|  | 224 | /* ICH6 (and 6) (i915) UDMA 100 */ | 
|  | 225 | { 0x8086, 0x266F, PCI_ANY_ID, PCI_ANY_ID, 0, 0, ich_pata_100 }, | 
|  | 226 | /* ICH7/7-R (i945, i975) UDMA 100*/ | 
| Alan Cox | c611bed | 2009-05-06 17:08:44 +0100 | [diff] [blame] | 227 | { 0x8086, 0x27DF, PCI_ANY_ID, PCI_ANY_ID, 0, 0, ich_pata_100_nomwdma1 }, | 
|  | 228 | { 0x8086, 0x269E, PCI_ANY_ID, PCI_ANY_ID, 0, 0, ich_pata_100_nomwdma1 }, | 
| Christian Lamparter | c1e6f28 | 2007-07-03 10:19:20 -0400 | [diff] [blame] | 229 | /* ICH8 Mobile PATA Controller */ | 
|  | 230 | { 0x8086, 0x2850, PCI_ANY_ID, PCI_ANY_ID, 0, 0, ich_pata_100 }, | 
| Linus Torvalds | 1da177e | 2005-04-16 15:20:36 -0700 | [diff] [blame] | 231 |  | 
| Alan Cox | 7654db1 | 2009-05-06 17:10:17 +0100 | [diff] [blame] | 232 | /* SATA ports */ | 
|  | 233 |  | 
| Tejun Heo | 1d076e5 | 2006-03-01 01:25:39 +0900 | [diff] [blame] | 234 | /* 82801EB (ICH5) */ | 
| Linus Torvalds | 1da177e | 2005-04-16 15:20:36 -0700 | [diff] [blame] | 235 | { 0x8086, 0x24d1, PCI_ANY_ID, PCI_ANY_ID, 0, 0, ich5_sata }, | 
| Tejun Heo | 1d076e5 | 2006-03-01 01:25:39 +0900 | [diff] [blame] | 236 | /* 82801EB (ICH5) */ | 
| Linus Torvalds | 1da177e | 2005-04-16 15:20:36 -0700 | [diff] [blame] | 237 | { 0x8086, 0x24df, PCI_ANY_ID, PCI_ANY_ID, 0, 0, ich5_sata }, | 
| Tejun Heo | 1d076e5 | 2006-03-01 01:25:39 +0900 | [diff] [blame] | 238 | /* 6300ESB (ICH5 variant with broken PCS present bits) */ | 
| Tejun Heo | 5e56a37 | 2006-11-10 18:08:10 +0900 | [diff] [blame] | 239 | { 0x8086, 0x25a3, PCI_ANY_ID, PCI_ANY_ID, 0, 0, ich5_sata }, | 
| Tejun Heo | 1d076e5 | 2006-03-01 01:25:39 +0900 | [diff] [blame] | 240 | /* 6300ESB pretending RAID */ | 
| Tejun Heo | 5e56a37 | 2006-11-10 18:08:10 +0900 | [diff] [blame] | 241 | { 0x8086, 0x25b0, PCI_ANY_ID, PCI_ANY_ID, 0, 0, ich5_sata }, | 
| Tejun Heo | 1d076e5 | 2006-03-01 01:25:39 +0900 | [diff] [blame] | 242 | /* 82801FB/FW (ICH6/ICH6W) */ | 
| Linus Torvalds | 1da177e | 2005-04-16 15:20:36 -0700 | [diff] [blame] | 243 | { 0x8086, 0x2651, PCI_ANY_ID, PCI_ANY_ID, 0, 0, ich6_sata }, | 
| Tejun Heo | 1d076e5 | 2006-03-01 01:25:39 +0900 | [diff] [blame] | 244 | /* 82801FR/FRW (ICH6R/ICH6RW) */ | 
| Tejun Heo | 9c0bf67 | 2008-03-26 16:00:58 +0900 | [diff] [blame] | 245 | { 0x8086, 0x2652, PCI_ANY_ID, PCI_ANY_ID, 0, 0, ich6_sata }, | 
| Tejun Heo | 5016d7d | 2008-03-26 15:46:58 +0900 | [diff] [blame] | 246 | /* 82801FBM ICH6M (ICH6R with only port 0 and 2 implemented). | 
|  | 247 | * Attach iff the controller is in IDE mode. */ | 
|  | 248 | { 0x8086, 0x2653, PCI_ANY_ID, PCI_ANY_ID, | 
| Tejun Heo | 9c0bf67 | 2008-03-26 16:00:58 +0900 | [diff] [blame] | 249 | PCI_CLASS_STORAGE_IDE << 8, 0xffff00, ich6m_sata }, | 
| Tejun Heo | 1d076e5 | 2006-03-01 01:25:39 +0900 | [diff] [blame] | 250 | /* 82801GB/GR/GH (ICH7, identical to ICH6) */ | 
| Tejun Heo | 9c0bf67 | 2008-03-26 16:00:58 +0900 | [diff] [blame] | 251 | { 0x8086, 0x27c0, PCI_ANY_ID, PCI_ANY_ID, 0, 0, ich6_sata }, | 
| Tejun Heo | 1d076e5 | 2006-03-01 01:25:39 +0900 | [diff] [blame] | 252 | /* 2801GBM/GHM (ICH7M, identical to ICH6M) */ | 
| Tejun Heo | 9c0bf67 | 2008-03-26 16:00:58 +0900 | [diff] [blame] | 253 | { 0x8086, 0x27c4, PCI_ANY_ID, PCI_ANY_ID, 0, 0, ich6m_sata }, | 
| Jason Gaston | f98b657 | 2006-12-07 08:57:32 -0800 | [diff] [blame] | 254 | /* Enterprise Southbridge 2 (631xESB/632xESB) */ | 
| Tejun Heo | 9c0bf67 | 2008-03-26 16:00:58 +0900 | [diff] [blame] | 255 | { 0x8086, 0x2680, PCI_ANY_ID, PCI_ANY_ID, 0, 0, ich6_sata }, | 
| Jason Gaston | f98b657 | 2006-12-07 08:57:32 -0800 | [diff] [blame] | 256 | /* SATA Controller 1 IDE (ICH8) */ | 
| Tejun Heo | 9c0bf67 | 2008-03-26 16:00:58 +0900 | [diff] [blame] | 257 | { 0x8086, 0x2820, PCI_ANY_ID, PCI_ANY_ID, 0, 0, ich8_sata }, | 
| Jason Gaston | f98b657 | 2006-12-07 08:57:32 -0800 | [diff] [blame] | 258 | /* SATA Controller 2 IDE (ICH8) */ | 
| Tejun Heo | 00242ec | 2007-11-19 11:24:25 +0900 | [diff] [blame] | 259 | { 0x8086, 0x2825, PCI_ANY_ID, PCI_ANY_ID, 0, 0, ich8_2port_sata }, | 
| Thomas Rohwer | 8d8ef2f | 2007-11-19 11:54:24 +0900 | [diff] [blame] | 260 | /* Mobile SATA Controller IDE (ICH8M), Apple */ | 
| Tejun Heo | 9c0bf67 | 2008-03-26 16:00:58 +0900 | [diff] [blame] | 261 | { 0x8086, 0x2828, 0x106b, 0x00a0, 0, 0, ich8m_apple_sata }, | 
| Tejun Heo | 23cf296 | 2008-05-29 22:04:22 +0900 | [diff] [blame] | 262 | { 0x8086, 0x2828, 0x106b, 0x00a1, 0, 0, ich8m_apple_sata }, | 
| Tejun Heo | 487eff6 | 2008-07-29 15:06:26 +0900 | [diff] [blame] | 263 | { 0x8086, 0x2828, 0x106b, 0x00a3, 0, 0, ich8m_apple_sata }, | 
| Tejun Heo | 23cf296 | 2008-05-29 22:04:22 +0900 | [diff] [blame] | 264 | /* Mobile SATA Controller IDE (ICH8M) */ | 
|  | 265 | { 0x8086, 0x2828, PCI_ANY_ID, PCI_ANY_ID, 0, 0, ich8_sata }, | 
| Jason Gaston | f98b657 | 2006-12-07 08:57:32 -0800 | [diff] [blame] | 266 | /* SATA Controller IDE (ICH9) */ | 
| Tejun Heo | 9c0bf67 | 2008-03-26 16:00:58 +0900 | [diff] [blame] | 267 | { 0x8086, 0x2920, PCI_ANY_ID, PCI_ANY_ID, 0, 0, ich8_sata }, | 
| Jason Gaston | f98b657 | 2006-12-07 08:57:32 -0800 | [diff] [blame] | 268 | /* SATA Controller IDE (ICH9) */ | 
| Tejun Heo | 00242ec | 2007-11-19 11:24:25 +0900 | [diff] [blame] | 269 | { 0x8086, 0x2921, PCI_ANY_ID, PCI_ANY_ID, 0, 0, ich8_2port_sata }, | 
| Jason Gaston | f98b657 | 2006-12-07 08:57:32 -0800 | [diff] [blame] | 270 | /* SATA Controller IDE (ICH9) */ | 
| Tejun Heo | 00242ec | 2007-11-19 11:24:25 +0900 | [diff] [blame] | 271 | { 0x8086, 0x2926, PCI_ANY_ID, PCI_ANY_ID, 0, 0, ich8_2port_sata }, | 
| Jason Gaston | f98b657 | 2006-12-07 08:57:32 -0800 | [diff] [blame] | 272 | /* SATA Controller IDE (ICH9M) */ | 
| Tejun Heo | 00242ec | 2007-11-19 11:24:25 +0900 | [diff] [blame] | 273 | { 0x8086, 0x2928, PCI_ANY_ID, PCI_ANY_ID, 0, 0, ich8_2port_sata }, | 
| Jason Gaston | f98b657 | 2006-12-07 08:57:32 -0800 | [diff] [blame] | 274 | /* SATA Controller IDE (ICH9M) */ | 
| Tejun Heo | 00242ec | 2007-11-19 11:24:25 +0900 | [diff] [blame] | 275 | { 0x8086, 0x292d, PCI_ANY_ID, PCI_ANY_ID, 0, 0, ich8_2port_sata }, | 
| Jason Gaston | f98b657 | 2006-12-07 08:57:32 -0800 | [diff] [blame] | 276 | /* SATA Controller IDE (ICH9M) */ | 
| Tejun Heo | 9c0bf67 | 2008-03-26 16:00:58 +0900 | [diff] [blame] | 277 | { 0x8086, 0x292e, PCI_ANY_ID, PCI_ANY_ID, 0, 0, ich8_sata }, | 
| Jason Gaston | c5cf0ff | 2007-08-30 21:36:56 -0700 | [diff] [blame] | 278 | /* SATA Controller IDE (Tolapai) */ | 
| Tejun Heo | 9c0bf67 | 2008-03-26 16:00:58 +0900 | [diff] [blame] | 279 | { 0x8086, 0x5028, PCI_ANY_ID, PCI_ANY_ID, 0, 0, tolapai_sata }, | 
| Jason Gaston | bf7f22b | 2008-01-28 17:36:45 -0800 | [diff] [blame] | 280 | /* SATA Controller IDE (ICH10) */ | 
| Tejun Heo | 9c0bf67 | 2008-03-26 16:00:58 +0900 | [diff] [blame] | 281 | { 0x8086, 0x3a00, PCI_ANY_ID, PCI_ANY_ID, 0, 0, ich8_sata }, | 
| Jason Gaston | bf7f22b | 2008-01-28 17:36:45 -0800 | [diff] [blame] | 282 | /* SATA Controller IDE (ICH10) */ | 
|  | 283 | { 0x8086, 0x3a06, PCI_ANY_ID, PCI_ANY_ID, 0, 0, ich8_2port_sata }, | 
|  | 284 | /* SATA Controller IDE (ICH10) */ | 
| Tejun Heo | 9c0bf67 | 2008-03-26 16:00:58 +0900 | [diff] [blame] | 285 | { 0x8086, 0x3a20, PCI_ANY_ID, PCI_ANY_ID, 0, 0, ich8_sata }, | 
| Jason Gaston | bf7f22b | 2008-01-28 17:36:45 -0800 | [diff] [blame] | 286 | /* SATA Controller IDE (ICH10) */ | 
|  | 287 | { 0x8086, 0x3a26, PCI_ANY_ID, PCI_ANY_ID, 0, 0, ich8_2port_sata }, | 
| Seth Heasley | c6c6a1a | 2008-08-11 17:03:18 -0700 | [diff] [blame] | 288 | /* SATA Controller IDE (PCH) */ | 
|  | 289 | { 0x8086, 0x3b20, PCI_ANY_ID, PCI_ANY_ID, 0, 0, ich8_sata }, | 
|  | 290 | /* SATA Controller IDE (PCH) */ | 
| Seth Heasley | 0395e61 | 2008-08-27 16:40:06 -0700 | [diff] [blame] | 291 | { 0x8086, 0x3b21, PCI_ANY_ID, PCI_ANY_ID, 0, 0, ich8_2port_sata }, | 
|  | 292 | /* SATA Controller IDE (PCH) */ | 
| Seth Heasley | c6c6a1a | 2008-08-11 17:03:18 -0700 | [diff] [blame] | 293 | { 0x8086, 0x3b26, PCI_ANY_ID, PCI_ANY_ID, 0, 0, ich8_2port_sata }, | 
|  | 294 | /* SATA Controller IDE (PCH) */ | 
| Seth Heasley | 0395e61 | 2008-08-27 16:40:06 -0700 | [diff] [blame] | 295 | { 0x8086, 0x3b28, PCI_ANY_ID, PCI_ANY_ID, 0, 0, ich8_sata }, | 
|  | 296 | /* SATA Controller IDE (PCH) */ | 
| Seth Heasley | c6c6a1a | 2008-08-11 17:03:18 -0700 | [diff] [blame] | 297 | { 0x8086, 0x3b2d, PCI_ANY_ID, PCI_ANY_ID, 0, 0, ich8_2port_sata }, | 
|  | 298 | /* SATA Controller IDE (PCH) */ | 
|  | 299 | { 0x8086, 0x3b2e, PCI_ANY_ID, PCI_ANY_ID, 0, 0, ich8_sata }, | 
| Seth Heasley | 88e8201 | 2010-01-12 17:01:28 -0800 | [diff] [blame] | 300 | /* SATA Controller IDE (CPT) */ | 
|  | 301 | { 0x8086, 0x1c00, PCI_ANY_ID, PCI_ANY_ID, 0, 0, ich8_sata }, | 
|  | 302 | /* SATA Controller IDE (CPT) */ | 
|  | 303 | { 0x8086, 0x1c01, PCI_ANY_ID, PCI_ANY_ID, 0, 0, ich8_sata }, | 
|  | 304 | /* SATA Controller IDE (CPT) */ | 
|  | 305 | { 0x8086, 0x1c08, PCI_ANY_ID, PCI_ANY_ID, 0, 0, ich8_2port_sata }, | 
|  | 306 | /* SATA Controller IDE (CPT) */ | 
|  | 307 | { 0x8086, 0x1c09, PCI_ANY_ID, PCI_ANY_ID, 0, 0, ich8_2port_sata }, | 
| Seth Heasley | 238e149 | 2010-09-09 09:42:40 -0700 | [diff] [blame] | 308 | /* SATA Controller IDE (PBG) */ | 
|  | 309 | { 0x8086, 0x1d00, PCI_ANY_ID, PCI_ANY_ID, 0, 0, ich8_sata }, | 
|  | 310 | /* SATA Controller IDE (PBG) */ | 
|  | 311 | { 0x8086, 0x1d08, PCI_ANY_ID, PCI_ANY_ID, 0, 0, ich8_2port_sata }, | 
| Linus Torvalds | 1da177e | 2005-04-16 15:20:36 -0700 | [diff] [blame] | 312 | { }	/* terminate list */ | 
|  | 313 | }; | 
|  | 314 |  | 
|  | 315 | static struct pci_driver piix_pci_driver = { | 
|  | 316 | .name			= DRV_NAME, | 
|  | 317 | .id_table		= piix_pci_tbl, | 
|  | 318 | .probe			= piix_init_one, | 
| Tejun Heo | 2852bcf | 2009-01-02 12:04:48 +0900 | [diff] [blame] | 319 | .remove			= piix_remove_one, | 
| Tejun Heo | 438ac6d | 2007-03-02 17:31:26 +0900 | [diff] [blame] | 320 | #ifdef CONFIG_PM | 
| Tejun Heo | b8b275e | 2007-07-10 15:55:43 +0900 | [diff] [blame] | 321 | .suspend		= piix_pci_device_suspend, | 
|  | 322 | .resume			= piix_pci_device_resume, | 
| Tejun Heo | 438ac6d | 2007-03-02 17:31:26 +0900 | [diff] [blame] | 323 | #endif | 
| Linus Torvalds | 1da177e | 2005-04-16 15:20:36 -0700 | [diff] [blame] | 324 | }; | 
|  | 325 |  | 
| Jeff Garzik | 193515d | 2005-11-07 00:59:37 -0500 | [diff] [blame] | 326 | static struct scsi_host_template piix_sht = { | 
| Tejun Heo | 68d1d07 | 2008-03-25 12:22:49 +0900 | [diff] [blame] | 327 | ATA_BMDMA_SHT(DRV_NAME), | 
| Linus Torvalds | 1da177e | 2005-04-16 15:20:36 -0700 | [diff] [blame] | 328 | }; | 
|  | 329 |  | 
| Tejun Heo | 2794362 | 2010-01-19 10:49:19 +0900 | [diff] [blame] | 330 | static struct ata_port_operations piix_sata_ops = { | 
| Alan Cox | 871af12 | 2009-01-05 14:16:39 +0000 | [diff] [blame] | 331 | .inherits		= &ata_bmdma32_port_ops, | 
| Tejun Heo | 2794362 | 2010-01-19 10:49:19 +0900 | [diff] [blame] | 332 | .sff_irq_check		= piix_irq_check, | 
|  | 333 | }; | 
|  | 334 |  | 
|  | 335 | static struct ata_port_operations piix_pata_ops = { | 
|  | 336 | .inherits		= &piix_sata_ops, | 
| Alan Cox | eb4a2c7 | 2007-04-11 00:04:20 +0100 | [diff] [blame] | 337 | .cable_detect		= ata_cable_40wire, | 
| Tejun Heo | 25f9813 | 2008-01-07 19:38:53 +0900 | [diff] [blame] | 338 | .set_piomode		= piix_set_piomode, | 
|  | 339 | .set_dmamode		= piix_set_dmamode, | 
| Tejun Heo | a1efdab | 2008-03-25 12:22:50 +0900 | [diff] [blame] | 340 | .prereset		= piix_pata_prereset, | 
| Tejun Heo | 029cfd6 | 2008-03-25 12:22:49 +0900 | [diff] [blame] | 341 | }; | 
| Tejun Heo | 25f9813 | 2008-01-07 19:38:53 +0900 | [diff] [blame] | 342 |  | 
| Tejun Heo | 029cfd6 | 2008-03-25 12:22:49 +0900 | [diff] [blame] | 343 | static struct ata_port_operations piix_vmw_ops = { | 
|  | 344 | .inherits		= &piix_pata_ops, | 
| Tejun Heo | 25f9813 | 2008-01-07 19:38:53 +0900 | [diff] [blame] | 345 | .bmdma_status		= piix_vmw_bmdma_status, | 
| Tejun Heo | 25f9813 | 2008-01-07 19:38:53 +0900 | [diff] [blame] | 346 | }; | 
|  | 347 |  | 
| Tejun Heo | 029cfd6 | 2008-03-25 12:22:49 +0900 | [diff] [blame] | 348 | static struct ata_port_operations ich_pata_ops = { | 
|  | 349 | .inherits		= &piix_pata_ops, | 
|  | 350 | .cable_detect		= ich_pata_cable_detect, | 
|  | 351 | .set_dmamode		= ich_set_dmamode, | 
|  | 352 | }; | 
| Tejun Heo | c729072 | 2008-01-18 18:36:30 +0900 | [diff] [blame] | 353 |  | 
| Tejun Heo | a97c4006 | 2010-09-01 17:50:08 +0200 | [diff] [blame] | 354 | static struct device_attribute *piix_sidpr_shost_attrs[] = { | 
|  | 355 | &dev_attr_link_power_management_policy, | 
|  | 356 | NULL | 
|  | 357 | }; | 
|  | 358 |  | 
|  | 359 | static struct scsi_host_template piix_sidpr_sht = { | 
|  | 360 | ATA_BMDMA_SHT(DRV_NAME), | 
|  | 361 | .shost_attrs		= piix_sidpr_shost_attrs, | 
|  | 362 | }; | 
|  | 363 |  | 
| Tejun Heo | 029cfd6 | 2008-03-25 12:22:49 +0900 | [diff] [blame] | 364 | static struct ata_port_operations piix_sidpr_sata_ops = { | 
|  | 365 | .inherits		= &piix_sata_ops, | 
| Tejun Heo | 57c9efd | 2008-04-07 22:47:19 +0900 | [diff] [blame] | 366 | .hardreset		= sata_std_hardreset, | 
| Tejun Heo | c729072 | 2008-01-18 18:36:30 +0900 | [diff] [blame] | 367 | .scr_read		= piix_sidpr_scr_read, | 
|  | 368 | .scr_write		= piix_sidpr_scr_write, | 
| Tejun Heo | a97c4006 | 2010-09-01 17:50:08 +0200 | [diff] [blame] | 369 | .set_lpm		= piix_sidpr_set_lpm, | 
| Tejun Heo | c729072 | 2008-01-18 18:36:30 +0900 | [diff] [blame] | 370 | }; | 
|  | 371 |  | 
| Tejun Heo | d96715c | 2006-06-29 01:58:28 +0900 | [diff] [blame] | 372 | static const struct piix_map_db ich5_map_db = { | 
| Tejun Heo | d33f58b | 2006-03-01 01:25:39 +0900 | [diff] [blame] | 373 | .mask = 0x7, | 
| Jeff Garzik | ea35d29 | 2006-07-11 11:48:50 -0400 | [diff] [blame] | 374 | .port_enable = 0x3, | 
| Tejun Heo | d33f58b | 2006-03-01 01:25:39 +0900 | [diff] [blame] | 375 | .map = { | 
|  | 376 | /* PM   PS   SM   SS       MAP  */ | 
|  | 377 | {  P0,  NA,  P1,  NA }, /* 000b */ | 
|  | 378 | {  P1,  NA,  P0,  NA }, /* 001b */ | 
|  | 379 | {  RV,  RV,  RV,  RV }, | 
|  | 380 | {  RV,  RV,  RV,  RV }, | 
|  | 381 | {  P0,  P1, IDE, IDE }, /* 100b */ | 
|  | 382 | {  P1,  P0, IDE, IDE }, /* 101b */ | 
|  | 383 | { IDE, IDE,  P0,  P1 }, /* 110b */ | 
|  | 384 | { IDE, IDE,  P1,  P0 }, /* 111b */ | 
|  | 385 | }, | 
|  | 386 | }; | 
|  | 387 |  | 
| Tejun Heo | d96715c | 2006-06-29 01:58:28 +0900 | [diff] [blame] | 388 | static const struct piix_map_db ich6_map_db = { | 
| Tejun Heo | d33f58b | 2006-03-01 01:25:39 +0900 | [diff] [blame] | 389 | .mask = 0x3, | 
| Jeff Garzik | ea35d29 | 2006-07-11 11:48:50 -0400 | [diff] [blame] | 390 | .port_enable = 0xf, | 
| Tejun Heo | d33f58b | 2006-03-01 01:25:39 +0900 | [diff] [blame] | 391 | .map = { | 
|  | 392 | /* PM   PS   SM   SS       MAP */ | 
| Tejun Heo | 79ea24e | 2006-03-31 20:01:50 +0900 | [diff] [blame] | 393 | {  P0,  P2,  P1,  P3 }, /* 00b */ | 
| Tejun Heo | d33f58b | 2006-03-01 01:25:39 +0900 | [diff] [blame] | 394 | { IDE, IDE,  P1,  P3 }, /* 01b */ | 
|  | 395 | {  P0,  P2, IDE, IDE }, /* 10b */ | 
|  | 396 | {  RV,  RV,  RV,  RV }, | 
|  | 397 | }, | 
|  | 398 | }; | 
|  | 399 |  | 
| Tejun Heo | d96715c | 2006-06-29 01:58:28 +0900 | [diff] [blame] | 400 | static const struct piix_map_db ich6m_map_db = { | 
| Tejun Heo | d33f58b | 2006-03-01 01:25:39 +0900 | [diff] [blame] | 401 | .mask = 0x3, | 
| Jeff Garzik | ea35d29 | 2006-07-11 11:48:50 -0400 | [diff] [blame] | 402 | .port_enable = 0x5, | 
| Tejun Heo | 6708374 | 2006-09-11 06:29:03 +0900 | [diff] [blame] | 403 |  | 
|  | 404 | /* Map 01b isn't specified in the doc but some notebooks use | 
| Tejun Heo | c6446a4 | 2006-10-09 13:23:58 +0900 | [diff] [blame] | 405 | * it anyway.  MAP 01b have been spotted on both ICH6M and | 
|  | 406 | * ICH7M. | 
| Tejun Heo | 6708374 | 2006-09-11 06:29:03 +0900 | [diff] [blame] | 407 | */ | 
|  | 408 | .map = { | 
|  | 409 | /* PM   PS   SM   SS       MAP */ | 
| Tejun Heo | e04b3b9 | 2007-07-10 17:58:21 +0900 | [diff] [blame] | 410 | {  P0,  P2,  NA,  NA }, /* 00b */ | 
| Tejun Heo | 6708374 | 2006-09-11 06:29:03 +0900 | [diff] [blame] | 411 | { IDE, IDE,  P1,  P3 }, /* 01b */ | 
|  | 412 | {  P0,  P2, IDE, IDE }, /* 10b */ | 
|  | 413 | {  RV,  RV,  RV,  RV }, | 
|  | 414 | }, | 
|  | 415 | }; | 
|  | 416 |  | 
| Jeff Garzik | 08f12ed | 2006-07-11 11:57:44 -0400 | [diff] [blame] | 417 | static const struct piix_map_db ich8_map_db = { | 
|  | 418 | .mask = 0x3, | 
| Tejun Heo | a0ce9ac | 2007-11-19 12:06:37 +0900 | [diff] [blame] | 419 | .port_enable = 0xf, | 
| Jeff Garzik | 08f12ed | 2006-07-11 11:57:44 -0400 | [diff] [blame] | 420 | .map = { | 
|  | 421 | /* PM   PS   SM   SS       MAP */ | 
| Kristen Carlson Accardi | 158f30c8 | 2006-10-19 13:27:39 -0700 | [diff] [blame] | 422 | {  P0,  P2,  P1,  P3 }, /* 00b (hardwired when in AHCI) */ | 
| Jeff Garzik | 08f12ed | 2006-07-11 11:57:44 -0400 | [diff] [blame] | 423 | {  RV,  RV,  RV,  RV }, | 
| Tejun Heo | ac2b043 | 2007-08-07 02:43:27 +0900 | [diff] [blame] | 424 | {  P0,  P2, IDE, IDE }, /* 10b (IDE mode) */ | 
| Jeff Garzik | 08f12ed | 2006-07-11 11:57:44 -0400 | [diff] [blame] | 425 | {  RV,  RV,  RV,  RV }, | 
|  | 426 | }, | 
|  | 427 | }; | 
|  | 428 |  | 
| Tejun Heo | 00242ec | 2007-11-19 11:24:25 +0900 | [diff] [blame] | 429 | static const struct piix_map_db ich8_2port_map_db = { | 
| Jason Gaston | e2d352a | 2007-09-07 17:21:03 -0700 | [diff] [blame] | 430 | .mask = 0x3, | 
|  | 431 | .port_enable = 0x3, | 
|  | 432 | .map = { | 
|  | 433 | /* PM   PS   SM   SS       MAP */ | 
|  | 434 | {  P0,  NA,  P1,  NA }, /* 00b */ | 
|  | 435 | {  RV,  RV,  RV,  RV }, /* 01b */ | 
|  | 436 | {  RV,  RV,  RV,  RV }, /* 10b */ | 
|  | 437 | {  RV,  RV,  RV,  RV }, | 
|  | 438 | }, | 
| Jason Gaston | c5cf0ff | 2007-08-30 21:36:56 -0700 | [diff] [blame] | 439 | }; | 
|  | 440 |  | 
| Thomas Rohwer | 8d8ef2f | 2007-11-19 11:54:24 +0900 | [diff] [blame] | 441 | static const struct piix_map_db ich8m_apple_map_db = { | 
|  | 442 | .mask = 0x3, | 
|  | 443 | .port_enable = 0x1, | 
|  | 444 | .map = { | 
|  | 445 | /* PM   PS   SM   SS       MAP */ | 
|  | 446 | {  P0,  NA,  NA,  NA }, /* 00b */ | 
|  | 447 | {  RV,  RV,  RV,  RV }, | 
|  | 448 | {  P0,  P2, IDE, IDE }, /* 10b */ | 
|  | 449 | {  RV,  RV,  RV,  RV }, | 
|  | 450 | }, | 
|  | 451 | }; | 
|  | 452 |  | 
| Tejun Heo | 00242ec | 2007-11-19 11:24:25 +0900 | [diff] [blame] | 453 | static const struct piix_map_db tolapai_map_db = { | 
| Jason Gaston | 8f73a68 | 2007-10-11 16:05:15 -0700 | [diff] [blame] | 454 | .mask = 0x3, | 
|  | 455 | .port_enable = 0x3, | 
|  | 456 | .map = { | 
|  | 457 | /* PM   PS   SM   SS       MAP */ | 
|  | 458 | {  P0,  NA,  P1,  NA }, /* 00b */ | 
|  | 459 | {  RV,  RV,  RV,  RV }, /* 01b */ | 
|  | 460 | {  RV,  RV,  RV,  RV }, /* 10b */ | 
|  | 461 | {  RV,  RV,  RV,  RV }, | 
|  | 462 | }, | 
|  | 463 | }; | 
|  | 464 |  | 
| Tejun Heo | d96715c | 2006-06-29 01:58:28 +0900 | [diff] [blame] | 465 | static const struct piix_map_db *piix_map_db_table[] = { | 
|  | 466 | [ich5_sata]		= &ich5_map_db, | 
| Tejun Heo | d96715c | 2006-06-29 01:58:28 +0900 | [diff] [blame] | 467 | [ich6_sata]		= &ich6_map_db, | 
| Tejun Heo | 9c0bf67 | 2008-03-26 16:00:58 +0900 | [diff] [blame] | 468 | [ich6m_sata]		= &ich6m_map_db, | 
|  | 469 | [ich8_sata]		= &ich8_map_db, | 
| Tejun Heo | 00242ec | 2007-11-19 11:24:25 +0900 | [diff] [blame] | 470 | [ich8_2port_sata]	= &ich8_2port_map_db, | 
| Tejun Heo | 9c0bf67 | 2008-03-26 16:00:58 +0900 | [diff] [blame] | 471 | [ich8m_apple_sata]	= &ich8m_apple_map_db, | 
|  | 472 | [tolapai_sata]		= &tolapai_map_db, | 
| Tejun Heo | d96715c | 2006-06-29 01:58:28 +0900 | [diff] [blame] | 473 | }; | 
|  | 474 |  | 
| Linus Torvalds | 1da177e | 2005-04-16 15:20:36 -0700 | [diff] [blame] | 475 | static struct ata_port_info piix_port_info[] = { | 
| Tejun Heo | 00242ec | 2007-11-19 11:24:25 +0900 | [diff] [blame] | 476 | [piix_pata_mwdma] = 	/* PIIX3 MWDMA only */ | 
|  | 477 | { | 
| Tejun Heo | 00242ec | 2007-11-19 11:24:25 +0900 | [diff] [blame] | 478 | .flags		= PIIX_PATA_FLAGS, | 
| Erik Inge Bolsø | 14bdef9 | 2009-03-14 21:38:24 +0100 | [diff] [blame] | 479 | .pio_mask	= ATA_PIO4, | 
|  | 480 | .mwdma_mask	= ATA_MWDMA12_ONLY, /* mwdma1-2 ?? CHECK 0 should be ok but slow */ | 
| Tejun Heo | 00242ec | 2007-11-19 11:24:25 +0900 | [diff] [blame] | 481 | .port_ops	= &piix_pata_ops, | 
|  | 482 | }, | 
|  | 483 |  | 
| Jeff Garzik | ec300d9 | 2007-09-01 07:17:36 -0400 | [diff] [blame] | 484 | [piix_pata_33] =	/* PIIX4 at 33MHz */ | 
| Tejun Heo | 1d076e5 | 2006-03-01 01:25:39 +0900 | [diff] [blame] | 485 | { | 
| Tejun Heo | b3362f8 | 2006-11-10 18:08:10 +0900 | [diff] [blame] | 486 | .flags		= PIIX_PATA_FLAGS, | 
| Erik Inge Bolsø | 14bdef9 | 2009-03-14 21:38:24 +0100 | [diff] [blame] | 487 | .pio_mask	= ATA_PIO4, | 
|  | 488 | .mwdma_mask	= ATA_MWDMA12_ONLY, /* mwdma1-2 ?? CHECK 0 should be ok but slow */ | 
|  | 489 | .udma_mask	= ATA_UDMA2, | 
| Tejun Heo | 1d076e5 | 2006-03-01 01:25:39 +0900 | [diff] [blame] | 490 | .port_ops	= &piix_pata_ops, | 
|  | 491 | }, | 
|  | 492 |  | 
| Jeff Garzik | ec300d9 | 2007-09-01 07:17:36 -0400 | [diff] [blame] | 493 | [ich_pata_33] = 	/* ICH0 - ICH at 33Mhz*/ | 
| Linus Torvalds | 1da177e | 2005-04-16 15:20:36 -0700 | [diff] [blame] | 494 | { | 
| Tejun Heo | b3362f8 | 2006-11-10 18:08:10 +0900 | [diff] [blame] | 495 | .flags		= PIIX_PATA_FLAGS, | 
| Erik Inge Bolsø | 14bdef9 | 2009-03-14 21:38:24 +0100 | [diff] [blame] | 496 | .pio_mask 	= ATA_PIO4, | 
|  | 497 | .mwdma_mask	= ATA_MWDMA12_ONLY, /* Check: maybe MWDMA0 is ok  */ | 
|  | 498 | .udma_mask	= ATA_UDMA2, | 
| Jeff Garzik | 669a5db | 2006-08-29 18:12:40 -0400 | [diff] [blame] | 499 | .port_ops	= &ich_pata_ops, | 
|  | 500 | }, | 
| Jeff Garzik | ec300d9 | 2007-09-01 07:17:36 -0400 | [diff] [blame] | 501 |  | 
|  | 502 | [ich_pata_66] = 	/* ICH controllers up to 66MHz */ | 
| Jeff Garzik | 669a5db | 2006-08-29 18:12:40 -0400 | [diff] [blame] | 503 | { | 
| Tejun Heo | b3362f8 | 2006-11-10 18:08:10 +0900 | [diff] [blame] | 504 | .flags		= PIIX_PATA_FLAGS, | 
| Erik Inge Bolsø | 14bdef9 | 2009-03-14 21:38:24 +0100 | [diff] [blame] | 505 | .pio_mask 	= ATA_PIO4, | 
|  | 506 | .mwdma_mask	= ATA_MWDMA12_ONLY, /* MWDMA0 is broken on chip */ | 
| Jeff Garzik | 669a5db | 2006-08-29 18:12:40 -0400 | [diff] [blame] | 507 | .udma_mask	= ATA_UDMA4, | 
|  | 508 | .port_ops	= &ich_pata_ops, | 
|  | 509 | }, | 
| Jeff Garzik | 85cd725 | 2006-08-31 00:03:49 -0400 | [diff] [blame] | 510 |  | 
| Jeff Garzik | ec300d9 | 2007-09-01 07:17:36 -0400 | [diff] [blame] | 511 | [ich_pata_100] = | 
| Jeff Garzik | 669a5db | 2006-08-29 18:12:40 -0400 | [diff] [blame] | 512 | { | 
| Tejun Heo | b3362f8 | 2006-11-10 18:08:10 +0900 | [diff] [blame] | 513 | .flags		= PIIX_PATA_FLAGS | PIIX_FLAG_CHECKINTR, | 
| Erik Inge Bolsø | 14bdef9 | 2009-03-14 21:38:24 +0100 | [diff] [blame] | 514 | .pio_mask	= ATA_PIO4, | 
|  | 515 | .mwdma_mask	= ATA_MWDMA12_ONLY, | 
|  | 516 | .udma_mask	= ATA_UDMA5, | 
| Jeff Garzik | 669a5db | 2006-08-29 18:12:40 -0400 | [diff] [blame] | 517 | .port_ops	= &ich_pata_ops, | 
| Linus Torvalds | 1da177e | 2005-04-16 15:20:36 -0700 | [diff] [blame] | 518 | }, | 
|  | 519 |  | 
| Alan Cox | c611bed | 2009-05-06 17:08:44 +0100 | [diff] [blame] | 520 | [ich_pata_100_nomwdma1] = | 
|  | 521 | { | 
|  | 522 | .flags		= PIIX_PATA_FLAGS | PIIX_FLAG_CHECKINTR, | 
|  | 523 | .pio_mask	= ATA_PIO4, | 
|  | 524 | .mwdma_mask	= ATA_MWDMA2_ONLY, | 
|  | 525 | .udma_mask	= ATA_UDMA5, | 
|  | 526 | .port_ops	= &ich_pata_ops, | 
|  | 527 | }, | 
|  | 528 |  | 
| Jeff Garzik | ec300d9 | 2007-09-01 07:17:36 -0400 | [diff] [blame] | 529 | [ich5_sata] = | 
| Linus Torvalds | 1da177e | 2005-04-16 15:20:36 -0700 | [diff] [blame] | 530 | { | 
| Tejun Heo | 228c159 | 2006-11-10 18:08:10 +0900 | [diff] [blame] | 531 | .flags		= PIIX_SATA_FLAGS, | 
| Erik Inge Bolsø | 14bdef9 | 2009-03-14 21:38:24 +0100 | [diff] [blame] | 532 | .pio_mask	= ATA_PIO4, | 
|  | 533 | .mwdma_mask	= ATA_MWDMA2, | 
| Jeff Garzik | bf6263a | 2007-07-09 12:16:50 -0400 | [diff] [blame] | 534 | .udma_mask	= ATA_UDMA6, | 
| Linus Torvalds | 1da177e | 2005-04-16 15:20:36 -0700 | [diff] [blame] | 535 | .port_ops	= &piix_sata_ops, | 
|  | 536 | }, | 
|  | 537 |  | 
| Jeff Garzik | ec300d9 | 2007-09-01 07:17:36 -0400 | [diff] [blame] | 538 | [ich6_sata] = | 
| Linus Torvalds | 1da177e | 2005-04-16 15:20:36 -0700 | [diff] [blame] | 539 | { | 
| Tejun Heo | 723159c | 2008-01-04 18:42:20 +0900 | [diff] [blame] | 540 | .flags		= PIIX_SATA_FLAGS, | 
| Erik Inge Bolsø | 14bdef9 | 2009-03-14 21:38:24 +0100 | [diff] [blame] | 541 | .pio_mask	= ATA_PIO4, | 
|  | 542 | .mwdma_mask	= ATA_MWDMA2, | 
| Jeff Garzik | bf6263a | 2007-07-09 12:16:50 -0400 | [diff] [blame] | 543 | .udma_mask	= ATA_UDMA6, | 
| Linus Torvalds | 1da177e | 2005-04-16 15:20:36 -0700 | [diff] [blame] | 544 | .port_ops	= &piix_sata_ops, | 
|  | 545 | }, | 
|  | 546 |  | 
| Tejun Heo | 9c0bf67 | 2008-03-26 16:00:58 +0900 | [diff] [blame] | 547 | [ich6m_sata] = | 
| Jason Gaston | c368ca4 | 2005-04-16 15:24:44 -0700 | [diff] [blame] | 548 | { | 
| Tejun Heo | 5016d7d | 2008-03-26 15:46:58 +0900 | [diff] [blame] | 549 | .flags		= PIIX_SATA_FLAGS, | 
| Erik Inge Bolsø | 14bdef9 | 2009-03-14 21:38:24 +0100 | [diff] [blame] | 550 | .pio_mask	= ATA_PIO4, | 
|  | 551 | .mwdma_mask	= ATA_MWDMA2, | 
| Jeff Garzik | bf6263a | 2007-07-09 12:16:50 -0400 | [diff] [blame] | 552 | .udma_mask	= ATA_UDMA6, | 
| Jason Gaston | c368ca4 | 2005-04-16 15:24:44 -0700 | [diff] [blame] | 553 | .port_ops	= &piix_sata_ops, | 
|  | 554 | }, | 
| Tejun Heo | 1d076e5 | 2006-03-01 01:25:39 +0900 | [diff] [blame] | 555 |  | 
| Tejun Heo | 9c0bf67 | 2008-03-26 16:00:58 +0900 | [diff] [blame] | 556 | [ich8_sata] = | 
| Jeff Garzik | 08f12ed | 2006-07-11 11:57:44 -0400 | [diff] [blame] | 557 | { | 
| Tejun Heo | 5016d7d | 2008-03-26 15:46:58 +0900 | [diff] [blame] | 558 | .flags		= PIIX_SATA_FLAGS | PIIX_FLAG_SIDPR, | 
| Erik Inge Bolsø | 14bdef9 | 2009-03-14 21:38:24 +0100 | [diff] [blame] | 559 | .pio_mask	= ATA_PIO4, | 
|  | 560 | .mwdma_mask	= ATA_MWDMA2, | 
| Jeff Garzik | bf6263a | 2007-07-09 12:16:50 -0400 | [diff] [blame] | 561 | .udma_mask	= ATA_UDMA6, | 
| Jeff Garzik | 08f12ed | 2006-07-11 11:57:44 -0400 | [diff] [blame] | 562 | .port_ops	= &piix_sata_ops, | 
|  | 563 | }, | 
| Jeff Garzik | 669a5db | 2006-08-29 18:12:40 -0400 | [diff] [blame] | 564 |  | 
| Tejun Heo | 00242ec | 2007-11-19 11:24:25 +0900 | [diff] [blame] | 565 | [ich8_2port_sata] = | 
| Jason Gaston | c5cf0ff | 2007-08-30 21:36:56 -0700 | [diff] [blame] | 566 | { | 
| Tejun Heo | 5016d7d | 2008-03-26 15:46:58 +0900 | [diff] [blame] | 567 | .flags		= PIIX_SATA_FLAGS | PIIX_FLAG_SIDPR, | 
| Erik Inge Bolsø | 14bdef9 | 2009-03-14 21:38:24 +0100 | [diff] [blame] | 568 | .pio_mask	= ATA_PIO4, | 
|  | 569 | .mwdma_mask	= ATA_MWDMA2, | 
| Jason Gaston | c5cf0ff | 2007-08-30 21:36:56 -0700 | [diff] [blame] | 570 | .udma_mask	= ATA_UDMA6, | 
|  | 571 | .port_ops	= &piix_sata_ops, | 
|  | 572 | }, | 
| Jason Gaston | 8f73a68 | 2007-10-11 16:05:15 -0700 | [diff] [blame] | 573 |  | 
| Tejun Heo | 9c0bf67 | 2008-03-26 16:00:58 +0900 | [diff] [blame] | 574 | [tolapai_sata] = | 
| Jason Gaston | 8f73a68 | 2007-10-11 16:05:15 -0700 | [diff] [blame] | 575 | { | 
| Tejun Heo | 5016d7d | 2008-03-26 15:46:58 +0900 | [diff] [blame] | 576 | .flags		= PIIX_SATA_FLAGS, | 
| Erik Inge Bolsø | 14bdef9 | 2009-03-14 21:38:24 +0100 | [diff] [blame] | 577 | .pio_mask	= ATA_PIO4, | 
|  | 578 | .mwdma_mask	= ATA_MWDMA2, | 
| Jason Gaston | 8f73a68 | 2007-10-11 16:05:15 -0700 | [diff] [blame] | 579 | .udma_mask	= ATA_UDMA6, | 
|  | 580 | .port_ops	= &piix_sata_ops, | 
|  | 581 | }, | 
| Thomas Rohwer | 8d8ef2f | 2007-11-19 11:54:24 +0900 | [diff] [blame] | 582 |  | 
| Tejun Heo | 9c0bf67 | 2008-03-26 16:00:58 +0900 | [diff] [blame] | 583 | [ich8m_apple_sata] = | 
| Thomas Rohwer | 8d8ef2f | 2007-11-19 11:54:24 +0900 | [diff] [blame] | 584 | { | 
| Tejun Heo | 23cf296 | 2008-05-29 22:04:22 +0900 | [diff] [blame] | 585 | .flags		= PIIX_SATA_FLAGS, | 
| Erik Inge Bolsø | 14bdef9 | 2009-03-14 21:38:24 +0100 | [diff] [blame] | 586 | .pio_mask	= ATA_PIO4, | 
|  | 587 | .mwdma_mask	= ATA_MWDMA2, | 
| Thomas Rohwer | 8d8ef2f | 2007-11-19 11:54:24 +0900 | [diff] [blame] | 588 | .udma_mask	= ATA_UDMA6, | 
|  | 589 | .port_ops	= &piix_sata_ops, | 
|  | 590 | }, | 
|  | 591 |  | 
| Tejun Heo | 25f9813 | 2008-01-07 19:38:53 +0900 | [diff] [blame] | 592 | [piix_pata_vmw] = | 
|  | 593 | { | 
| Tejun Heo | 25f9813 | 2008-01-07 19:38:53 +0900 | [diff] [blame] | 594 | .flags		= PIIX_PATA_FLAGS, | 
| Erik Inge Bolsø | 14bdef9 | 2009-03-14 21:38:24 +0100 | [diff] [blame] | 595 | .pio_mask	= ATA_PIO4, | 
|  | 596 | .mwdma_mask	= ATA_MWDMA12_ONLY, /* mwdma1-2 ?? CHECK 0 should be ok but slow */ | 
|  | 597 | .udma_mask	= ATA_UDMA2, | 
| Tejun Heo | 25f9813 | 2008-01-07 19:38:53 +0900 | [diff] [blame] | 598 | .port_ops	= &piix_vmw_ops, | 
|  | 599 | }, | 
|  | 600 |  | 
| Linus Torvalds | 1da177e | 2005-04-16 15:20:36 -0700 | [diff] [blame] | 601 | }; | 
|  | 602 |  | 
|  | 603 | static struct pci_bits piix_enable_bits[] = { | 
|  | 604 | { 0x41U, 1U, 0x80UL, 0x80UL },	/* port 0 */ | 
|  | 605 | { 0x43U, 1U, 0x80UL, 0x80UL },	/* port 1 */ | 
|  | 606 | }; | 
|  | 607 |  | 
|  | 608 | MODULE_AUTHOR("Andre Hedrick, Alan Cox, Andrzej Krzysztofowicz, Jeff Garzik"); | 
|  | 609 | MODULE_DESCRIPTION("SCSI low-level driver for Intel PIIX/ICH ATA controllers"); | 
|  | 610 | MODULE_LICENSE("GPL"); | 
|  | 611 | MODULE_DEVICE_TABLE(pci, piix_pci_tbl); | 
|  | 612 | MODULE_VERSION(DRV_VERSION); | 
|  | 613 |  | 
| Alan Cox | fc08515 | 2006-10-10 14:28:11 -0700 | [diff] [blame] | 614 | struct ich_laptop { | 
|  | 615 | u16 device; | 
|  | 616 | u16 subvendor; | 
|  | 617 | u16 subdevice; | 
|  | 618 | }; | 
|  | 619 |  | 
|  | 620 | /* | 
|  | 621 | *	List of laptops that use short cables rather than 80 wire | 
|  | 622 | */ | 
|  | 623 |  | 
|  | 624 | static const struct ich_laptop ich_laptop[] = { | 
|  | 625 | /* devid, subvendor, subdev */ | 
|  | 626 | { 0x27DF, 0x0005, 0x0280 },	/* ICH7 on Acer 5602WLMi */ | 
| Alan Cox | 2655e2c | 2007-11-05 22:51:09 +0000 | [diff] [blame] | 627 | { 0x27DF, 0x1025, 0x0102 },	/* ICH7 on Acer 5602aWLMi */ | 
| J J | babfb68 | 2007-01-09 02:26:30 +0900 | [diff] [blame] | 628 | { 0x27DF, 0x1025, 0x0110 },	/* ICH7 on Acer 3682WLMi */ | 
| Steve Conklin | 6034734 | 2009-07-16 16:27:56 -0500 | [diff] [blame] | 629 | { 0x27DF, 0x1028, 0x02b0 },	/* ICH7 on unknown Dell */ | 
| Robin H\. Johnson | 1234010 | 2007-03-28 18:02:07 -0700 | [diff] [blame] | 630 | { 0x27DF, 0x1043, 0x1267 },	/* ICH7 on Asus W5F */ | 
| Jeff Garzik | 54174db | 2007-09-29 04:01:43 -0400 | [diff] [blame] | 631 | { 0x27DF, 0x103C, 0x30A1 },	/* ICH7 on HP Compaq nc2400 */ | 
| André Goddard Rosa | af901ca | 2009-11-14 13:09:05 -0200 | [diff] [blame] | 632 | { 0x27DF, 0x103C, 0x361a },	/* ICH7 on unknown HP  */ | 
| Herton Ronaldo Krzesinski | d09addf | 2008-09-17 14:29:05 -0300 | [diff] [blame] | 633 | { 0x27DF, 0x1071, 0xD221 },	/* ICH7 on Hercules EC-900 */ | 
| Steve Conklin | 6034734 | 2009-07-16 16:27:56 -0500 | [diff] [blame] | 634 | { 0x27DF, 0x152D, 0x0778 },	/* ICH7 on unknown Intel */ | 
| Tejun Heo | b33620f | 2007-05-22 11:34:22 +0200 | [diff] [blame] | 635 | { 0x24CA, 0x1025, 0x0061 },	/* ICH4 on ACER Aspire 2023WLMi */ | 
| Colin Ian King | e1fefea | 2008-06-03 18:59:02 +0200 | [diff] [blame] | 636 | { 0x24CA, 0x1025, 0x003d },	/* ICH4 on ACER TM290 */ | 
|  | 637 | { 0x266F, 0x1025, 0x0066 },	/* ICH6 on ACER Aspire 1694WLMi */ | 
| Dan McGee | 01ce260 | 2008-04-20 22:03:27 -0500 | [diff] [blame] | 638 | { 0x2653, 0x1043, 0x82D8 },	/* ICH6M on Asus Eee 701 */ | 
| Alan Cox | 124a6ee | 2009-05-06 17:09:41 +0100 | [diff] [blame] | 639 | { 0x27df, 0x104d, 0x900e },	/* ICH7 on Sony TZ-90 */ | 
| Alan Cox | fc08515 | 2006-10-10 14:28:11 -0700 | [diff] [blame] | 640 | /* end marker */ | 
|  | 641 | { 0, } | 
|  | 642 | }; | 
|  | 643 |  | 
| Linus Torvalds | 1da177e | 2005-04-16 15:20:36 -0700 | [diff] [blame] | 644 | /** | 
| Alan Cox | eb4a2c7 | 2007-04-11 00:04:20 +0100 | [diff] [blame] | 645 | *	ich_pata_cable_detect - Probe host controller cable detect info | 
| Linus Torvalds | 1da177e | 2005-04-16 15:20:36 -0700 | [diff] [blame] | 646 | *	@ap: Port for which cable detect info is desired | 
|  | 647 | * | 
|  | 648 | *	Read 80c cable indicator from ATA PCI device's PCI config | 
|  | 649 | *	register.  This register is normally set by firmware (BIOS). | 
|  | 650 | * | 
|  | 651 | *	LOCKING: | 
|  | 652 | *	None (inherited from caller). | 
|  | 653 | */ | 
| Jeff Garzik | 669a5db | 2006-08-29 18:12:40 -0400 | [diff] [blame] | 654 |  | 
| Alan Cox | eb4a2c7 | 2007-04-11 00:04:20 +0100 | [diff] [blame] | 655 | static int ich_pata_cable_detect(struct ata_port *ap) | 
| Linus Torvalds | 1da177e | 2005-04-16 15:20:36 -0700 | [diff] [blame] | 656 | { | 
| Jeff Garzik | cca3974 | 2006-08-24 03:19:22 -0400 | [diff] [blame] | 657 | struct pci_dev *pdev = to_pci_dev(ap->host->dev); | 
| Tejun Heo | 2852bcf | 2009-01-02 12:04:48 +0900 | [diff] [blame] | 658 | struct piix_host_priv *hpriv = ap->host->private_data; | 
| Alan Cox | fc08515 | 2006-10-10 14:28:11 -0700 | [diff] [blame] | 659 | const struct ich_laptop *lap = &ich_laptop[0]; | 
| Tejun Heo | 2852bcf | 2009-01-02 12:04:48 +0900 | [diff] [blame] | 660 | u8 mask; | 
| Linus Torvalds | 1da177e | 2005-04-16 15:20:36 -0700 | [diff] [blame] | 661 |  | 
| Alan Cox | fc08515 | 2006-10-10 14:28:11 -0700 | [diff] [blame] | 662 | /* Check for specials - Acer Aspire 5602WLMi */ | 
|  | 663 | while (lap->device) { | 
|  | 664 | if (lap->device == pdev->device && | 
|  | 665 | lap->subvendor == pdev->subsystem_vendor && | 
| Jeff Garzik | 2dcb407 | 2007-10-19 06:42:56 -0400 | [diff] [blame] | 666 | lap->subdevice == pdev->subsystem_device) | 
| Alan Cox | eb4a2c7 | 2007-04-11 00:04:20 +0100 | [diff] [blame] | 667 | return ATA_CBL_PATA40_SHORT; | 
| Jeff Garzik | 2dcb407 | 2007-10-19 06:42:56 -0400 | [diff] [blame] | 668 |  | 
| Alan Cox | fc08515 | 2006-10-10 14:28:11 -0700 | [diff] [blame] | 669 | lap++; | 
|  | 670 | } | 
|  | 671 |  | 
| Linus Torvalds | 1da177e | 2005-04-16 15:20:36 -0700 | [diff] [blame] | 672 | /* check BIOS cable detect results */ | 
| Tejun Heo | 2a88d1a | 2006-08-10 16:59:16 +0900 | [diff] [blame] | 673 | mask = ap->port_no == 0 ? PIIX_80C_PRI : PIIX_80C_SEC; | 
| Tejun Heo | 2852bcf | 2009-01-02 12:04:48 +0900 | [diff] [blame] | 674 | if ((hpriv->saved_iocfg & mask) == 0) | 
| Alan Cox | eb4a2c7 | 2007-04-11 00:04:20 +0100 | [diff] [blame] | 675 | return ATA_CBL_PATA40; | 
|  | 676 | return ATA_CBL_PATA80; | 
| Linus Torvalds | 1da177e | 2005-04-16 15:20:36 -0700 | [diff] [blame] | 677 | } | 
|  | 678 |  | 
|  | 679 | /** | 
| Tejun Heo | ccc4672 | 2006-05-31 18:28:14 +0900 | [diff] [blame] | 680 | *	piix_pata_prereset - prereset for PATA host controller | 
| Tejun Heo | cc0680a | 2007-08-06 18:36:23 +0900 | [diff] [blame] | 681 | *	@link: Target link | 
| Tejun Heo | d4b2bab | 2007-02-02 16:50:52 +0900 | [diff] [blame] | 682 | *	@deadline: deadline jiffies for the operation | 
| Linus Torvalds | 1da177e | 2005-04-16 15:20:36 -0700 | [diff] [blame] | 683 | * | 
| Linus Torvalds | 1da177e | 2005-04-16 15:20:36 -0700 | [diff] [blame] | 684 | *	LOCKING: | 
|  | 685 | *	None (inherited from caller). | 
|  | 686 | */ | 
| Tejun Heo | cc0680a | 2007-08-06 18:36:23 +0900 | [diff] [blame] | 687 | static int piix_pata_prereset(struct ata_link *link, unsigned long deadline) | 
| Linus Torvalds | 1da177e | 2005-04-16 15:20:36 -0700 | [diff] [blame] | 688 | { | 
| Tejun Heo | cc0680a | 2007-08-06 18:36:23 +0900 | [diff] [blame] | 689 | struct ata_port *ap = link->ap; | 
| Jeff Garzik | cca3974 | 2006-08-24 03:19:22 -0400 | [diff] [blame] | 690 | struct pci_dev *pdev = to_pci_dev(ap->host->dev); | 
| Linus Torvalds | 1da177e | 2005-04-16 15:20:36 -0700 | [diff] [blame] | 691 |  | 
| Alan Cox | c961922 | 2006-09-26 17:53:38 +0100 | [diff] [blame] | 692 | if (!pci_test_config_bits(pdev, &piix_enable_bits[ap->port_no])) | 
|  | 693 | return -ENOENT; | 
| Tejun Heo | 9363c38 | 2008-04-07 22:47:16 +0900 | [diff] [blame] | 694 | return ata_sff_prereset(link, deadline); | 
| Tejun Heo | ccc4672 | 2006-05-31 18:28:14 +0900 | [diff] [blame] | 695 | } | 
|  | 696 |  | 
| Bartlomiej Zolnierkiewicz | 60c3be3 | 2009-08-30 14:56:30 +0200 | [diff] [blame] | 697 | static DEFINE_SPINLOCK(piix_lock); | 
|  | 698 |  | 
| Linus Torvalds | 1da177e | 2005-04-16 15:20:36 -0700 | [diff] [blame] | 699 | /** | 
|  | 700 | *	piix_set_piomode - Initialize host controller PATA PIO timings | 
|  | 701 | *	@ap: Port whose timings we are configuring | 
|  | 702 | *	@adev: um | 
| Linus Torvalds | 1da177e | 2005-04-16 15:20:36 -0700 | [diff] [blame] | 703 | * | 
|  | 704 | *	Set PIO mode for device, in host controller PCI config space. | 
|  | 705 | * | 
|  | 706 | *	LOCKING: | 
|  | 707 | *	None (inherited from caller). | 
|  | 708 | */ | 
|  | 709 |  | 
| Jeff Garzik | 2dcb407 | 2007-10-19 06:42:56 -0400 | [diff] [blame] | 710 | static void piix_set_piomode(struct ata_port *ap, struct ata_device *adev) | 
| Linus Torvalds | 1da177e | 2005-04-16 15:20:36 -0700 | [diff] [blame] | 711 | { | 
| Jeff Garzik | cca3974 | 2006-08-24 03:19:22 -0400 | [diff] [blame] | 712 | struct pci_dev *dev	= to_pci_dev(ap->host->dev); | 
| Bartlomiej Zolnierkiewicz | 60c3be3 | 2009-08-30 14:56:30 +0200 | [diff] [blame] | 713 | unsigned long flags; | 
|  | 714 | unsigned int pio	= adev->pio_mode - XFER_PIO_0; | 
| Linus Torvalds | 1da177e | 2005-04-16 15:20:36 -0700 | [diff] [blame] | 715 | unsigned int is_slave	= (adev->devno != 0); | 
| Tejun Heo | 2a88d1a | 2006-08-10 16:59:16 +0900 | [diff] [blame] | 716 | unsigned int master_port= ap->port_no ? 0x42 : 0x40; | 
| Linus Torvalds | 1da177e | 2005-04-16 15:20:36 -0700 | [diff] [blame] | 717 | unsigned int slave_port	= 0x44; | 
|  | 718 | u16 master_data; | 
|  | 719 | u8 slave_data; | 
| Jeff Garzik | 669a5db | 2006-08-29 18:12:40 -0400 | [diff] [blame] | 720 | u8 udma_enable; | 
|  | 721 | int control = 0; | 
| Jeff Garzik | 85cd725 | 2006-08-31 00:03:49 -0400 | [diff] [blame] | 722 |  | 
| Jeff Garzik | 669a5db | 2006-08-29 18:12:40 -0400 | [diff] [blame] | 723 | /* | 
|  | 724 | *	See Intel Document 298600-004 for the timing programing rules | 
|  | 725 | *	for ICH controllers. | 
|  | 726 | */ | 
| Linus Torvalds | 1da177e | 2005-04-16 15:20:36 -0700 | [diff] [blame] | 727 |  | 
|  | 728 | static const	 /* ISP  RTC */ | 
|  | 729 | u8 timings[][2]	= { { 0, 0 }, | 
|  | 730 | { 0, 0 }, | 
|  | 731 | { 1, 0 }, | 
|  | 732 | { 2, 1 }, | 
|  | 733 | { 2, 3 }, }; | 
|  | 734 |  | 
| Jeff Garzik | 669a5db | 2006-08-29 18:12:40 -0400 | [diff] [blame] | 735 | if (pio >= 2) | 
|  | 736 | control |= 1;	/* TIME1 enable */ | 
|  | 737 | if (ata_pio_need_iordy(adev)) | 
|  | 738 | control |= 2;	/* IE enable */ | 
|  | 739 |  | 
| Jeff Garzik | 85cd725 | 2006-08-31 00:03:49 -0400 | [diff] [blame] | 740 | /* Intel specifies that the PPE functionality is for disk only */ | 
| Jeff Garzik | 669a5db | 2006-08-29 18:12:40 -0400 | [diff] [blame] | 741 | if (adev->class == ATA_DEV_ATA) | 
|  | 742 | control |= 4;	/* PPE enable */ | 
|  | 743 |  | 
| Bartlomiej Zolnierkiewicz | 60c3be3 | 2009-08-30 14:56:30 +0200 | [diff] [blame] | 744 | spin_lock_irqsave(&piix_lock, flags); | 
|  | 745 |  | 
| Tejun Heo | a5bf5f5 | 2007-05-25 19:16:58 +0200 | [diff] [blame] | 746 | /* PIO configuration clears DTE unconditionally.  It will be | 
|  | 747 | * programmed in set_dmamode which is guaranteed to be called | 
|  | 748 | * after set_piomode if any DMA mode is available. | 
|  | 749 | */ | 
| Linus Torvalds | 1da177e | 2005-04-16 15:20:36 -0700 | [diff] [blame] | 750 | pci_read_config_word(dev, master_port, &master_data); | 
|  | 751 | if (is_slave) { | 
| Tejun Heo | a5bf5f5 | 2007-05-25 19:16:58 +0200 | [diff] [blame] | 752 | /* clear TIME1|IE1|PPE1|DTE1 */ | 
|  | 753 | master_data &= 0xff0f; | 
| Joe Perches | 1967b7f | 2008-02-03 17:08:11 +0200 | [diff] [blame] | 754 | /* Enable SITRE (separate slave timing register) */ | 
| Linus Torvalds | 1da177e | 2005-04-16 15:20:36 -0700 | [diff] [blame] | 755 | master_data |= 0x4000; | 
| Jeff Garzik | 669a5db | 2006-08-29 18:12:40 -0400 | [diff] [blame] | 756 | /* enable PPE1, IE1 and TIME1 as needed */ | 
|  | 757 | master_data |= (control << 4); | 
| Linus Torvalds | 1da177e | 2005-04-16 15:20:36 -0700 | [diff] [blame] | 758 | pci_read_config_byte(dev, slave_port, &slave_data); | 
| Tejun Heo | 2a88d1a | 2006-08-10 16:59:16 +0900 | [diff] [blame] | 759 | slave_data &= (ap->port_no ? 0x0f : 0xf0); | 
| Jeff Garzik | 669a5db | 2006-08-29 18:12:40 -0400 | [diff] [blame] | 760 | /* Load the timing nibble for this slave */ | 
| Tejun Heo | a5bf5f5 | 2007-05-25 19:16:58 +0200 | [diff] [blame] | 761 | slave_data |= ((timings[pio][0] << 2) | timings[pio][1]) | 
|  | 762 | << (ap->port_no ? 4 : 0); | 
| Linus Torvalds | 1da177e | 2005-04-16 15:20:36 -0700 | [diff] [blame] | 763 | } else { | 
| Tejun Heo | a5bf5f5 | 2007-05-25 19:16:58 +0200 | [diff] [blame] | 764 | /* clear ISP|RCT|TIME0|IE0|PPE0|DTE0 */ | 
|  | 765 | master_data &= 0xccf0; | 
| Jeff Garzik | 669a5db | 2006-08-29 18:12:40 -0400 | [diff] [blame] | 766 | /* Enable PPE, IE and TIME as appropriate */ | 
|  | 767 | master_data |= control; | 
| Tejun Heo | a5bf5f5 | 2007-05-25 19:16:58 +0200 | [diff] [blame] | 768 | /* load ISP and RCT */ | 
| Linus Torvalds | 1da177e | 2005-04-16 15:20:36 -0700 | [diff] [blame] | 769 | master_data |= | 
|  | 770 | (timings[pio][0] << 12) | | 
|  | 771 | (timings[pio][1] << 8); | 
|  | 772 | } | 
|  | 773 | pci_write_config_word(dev, master_port, master_data); | 
|  | 774 | if (is_slave) | 
|  | 775 | pci_write_config_byte(dev, slave_port, slave_data); | 
| Jeff Garzik | 669a5db | 2006-08-29 18:12:40 -0400 | [diff] [blame] | 776 |  | 
|  | 777 | /* Ensure the UDMA bit is off - it will be turned back on if | 
|  | 778 | UDMA is selected */ | 
| Jeff Garzik | 85cd725 | 2006-08-31 00:03:49 -0400 | [diff] [blame] | 779 |  | 
| Jeff Garzik | 669a5db | 2006-08-29 18:12:40 -0400 | [diff] [blame] | 780 | if (ap->udma_mask) { | 
|  | 781 | pci_read_config_byte(dev, 0x48, &udma_enable); | 
|  | 782 | udma_enable &= ~(1 << (2 * ap->port_no + adev->devno)); | 
|  | 783 | pci_write_config_byte(dev, 0x48, udma_enable); | 
|  | 784 | } | 
| Bartlomiej Zolnierkiewicz | 60c3be3 | 2009-08-30 14:56:30 +0200 | [diff] [blame] | 785 |  | 
|  | 786 | spin_unlock_irqrestore(&piix_lock, flags); | 
| Linus Torvalds | 1da177e | 2005-04-16 15:20:36 -0700 | [diff] [blame] | 787 | } | 
|  | 788 |  | 
|  | 789 | /** | 
| Jeff Garzik | 669a5db | 2006-08-29 18:12:40 -0400 | [diff] [blame] | 790 | *	do_pata_set_dmamode - Initialize host controller PATA PIO timings | 
| Linus Torvalds | 1da177e | 2005-04-16 15:20:36 -0700 | [diff] [blame] | 791 | *	@ap: Port whose timings we are configuring | 
| Jeff Garzik | 669a5db | 2006-08-29 18:12:40 -0400 | [diff] [blame] | 792 | *	@adev: Drive in question | 
| Henne | c32a8fd | 2006-09-25 22:00:46 +0200 | [diff] [blame] | 793 | *	@isich: set if the chip is an ICH device | 
| Linus Torvalds | 1da177e | 2005-04-16 15:20:36 -0700 | [diff] [blame] | 794 | * | 
|  | 795 | *	Set UDMA mode for device, in host controller PCI config space. | 
|  | 796 | * | 
|  | 797 | *	LOCKING: | 
|  | 798 | *	None (inherited from caller). | 
|  | 799 | */ | 
|  | 800 |  | 
| Jeff Garzik | 2dcb407 | 2007-10-19 06:42:56 -0400 | [diff] [blame] | 801 | static void do_pata_set_dmamode(struct ata_port *ap, struct ata_device *adev, int isich) | 
| Linus Torvalds | 1da177e | 2005-04-16 15:20:36 -0700 | [diff] [blame] | 802 | { | 
| Jeff Garzik | cca3974 | 2006-08-24 03:19:22 -0400 | [diff] [blame] | 803 | struct pci_dev *dev	= to_pci_dev(ap->host->dev); | 
| Bartlomiej Zolnierkiewicz | 60c3be3 | 2009-08-30 14:56:30 +0200 | [diff] [blame] | 804 | unsigned long flags; | 
| Jeff Garzik | 669a5db | 2006-08-29 18:12:40 -0400 | [diff] [blame] | 805 | u8 master_port		= ap->port_no ? 0x42 : 0x40; | 
|  | 806 | u16 master_data; | 
|  | 807 | u8 speed		= adev->dma_mode; | 
|  | 808 | int devid		= adev->devno + 2 * ap->port_no; | 
| Andrew Morton | dedf61d | 2007-01-10 17:20:34 -0800 | [diff] [blame] | 809 | u8 udma_enable		= 0; | 
| Jeff Garzik | 85cd725 | 2006-08-31 00:03:49 -0400 | [diff] [blame] | 810 |  | 
| Jeff Garzik | 669a5db | 2006-08-29 18:12:40 -0400 | [diff] [blame] | 811 | static const	 /* ISP  RTC */ | 
|  | 812 | u8 timings[][2]	= { { 0, 0 }, | 
|  | 813 | { 0, 0 }, | 
|  | 814 | { 1, 0 }, | 
|  | 815 | { 2, 1 }, | 
|  | 816 | { 2, 3 }, }; | 
| Linus Torvalds | 1da177e | 2005-04-16 15:20:36 -0700 | [diff] [blame] | 817 |  | 
| Bartlomiej Zolnierkiewicz | 60c3be3 | 2009-08-30 14:56:30 +0200 | [diff] [blame] | 818 | spin_lock_irqsave(&piix_lock, flags); | 
|  | 819 |  | 
| Jeff Garzik | 669a5db | 2006-08-29 18:12:40 -0400 | [diff] [blame] | 820 | pci_read_config_word(dev, master_port, &master_data); | 
| Alan | d2cdfc0 | 2007-01-10 17:13:38 +0000 | [diff] [blame] | 821 | if (ap->udma_mask) | 
|  | 822 | pci_read_config_byte(dev, 0x48, &udma_enable); | 
| Linus Torvalds | 1da177e | 2005-04-16 15:20:36 -0700 | [diff] [blame] | 823 |  | 
|  | 824 | if (speed >= XFER_UDMA_0) { | 
| Jeff Garzik | 669a5db | 2006-08-29 18:12:40 -0400 | [diff] [blame] | 825 | unsigned int udma = adev->dma_mode - XFER_UDMA_0; | 
|  | 826 | u16 udma_timing; | 
|  | 827 | u16 ideconf; | 
|  | 828 | int u_clock, u_speed; | 
| Jeff Garzik | 85cd725 | 2006-08-31 00:03:49 -0400 | [diff] [blame] | 829 |  | 
| Jeff Garzik | 669a5db | 2006-08-29 18:12:40 -0400 | [diff] [blame] | 830 | /* | 
| Jeff Garzik | 2dcb407 | 2007-10-19 06:42:56 -0400 | [diff] [blame] | 831 | * UDMA is handled by a combination of clock switching and | 
| Jeff Garzik | 85cd725 | 2006-08-31 00:03:49 -0400 | [diff] [blame] | 832 | * selection of dividers | 
|  | 833 | * | 
| Jeff Garzik | 669a5db | 2006-08-29 18:12:40 -0400 | [diff] [blame] | 834 | * Handy rule: Odd modes are UDMATIMx 01, even are 02 | 
| Jeff Garzik | 85cd725 | 2006-08-31 00:03:49 -0400 | [diff] [blame] | 835 | *	       except UDMA0 which is 00 | 
| Jeff Garzik | 669a5db | 2006-08-29 18:12:40 -0400 | [diff] [blame] | 836 | */ | 
|  | 837 | u_speed = min(2 - (udma & 1), udma); | 
|  | 838 | if (udma == 5) | 
|  | 839 | u_clock = 0x1000;	/* 100Mhz */ | 
|  | 840 | else if (udma > 2) | 
|  | 841 | u_clock = 1;		/* 66Mhz */ | 
|  | 842 | else | 
|  | 843 | u_clock = 0;		/* 33Mhz */ | 
| Jeff Garzik | 85cd725 | 2006-08-31 00:03:49 -0400 | [diff] [blame] | 844 |  | 
| Jeff Garzik | 669a5db | 2006-08-29 18:12:40 -0400 | [diff] [blame] | 845 | udma_enable |= (1 << devid); | 
| Jeff Garzik | 85cd725 | 2006-08-31 00:03:49 -0400 | [diff] [blame] | 846 |  | 
| Jeff Garzik | 669a5db | 2006-08-29 18:12:40 -0400 | [diff] [blame] | 847 | /* Load the CT/RP selection */ | 
|  | 848 | pci_read_config_word(dev, 0x4A, &udma_timing); | 
|  | 849 | udma_timing &= ~(3 << (4 * devid)); | 
|  | 850 | udma_timing |= u_speed << (4 * devid); | 
|  | 851 | pci_write_config_word(dev, 0x4A, udma_timing); | 
|  | 852 |  | 
| Jeff Garzik | 85cd725 | 2006-08-31 00:03:49 -0400 | [diff] [blame] | 853 | if (isich) { | 
| Jeff Garzik | 669a5db | 2006-08-29 18:12:40 -0400 | [diff] [blame] | 854 | /* Select a 33/66/100Mhz clock */ | 
|  | 855 | pci_read_config_word(dev, 0x54, &ideconf); | 
|  | 856 | ideconf &= ~(0x1001 << devid); | 
|  | 857 | ideconf |= u_clock << devid; | 
|  | 858 | /* For ICH or later we should set bit 10 for better | 
|  | 859 | performance (WR_PingPong_En) */ | 
|  | 860 | pci_write_config_word(dev, 0x54, ideconf); | 
| Linus Torvalds | 1da177e | 2005-04-16 15:20:36 -0700 | [diff] [blame] | 861 | } | 
| Linus Torvalds | 1da177e | 2005-04-16 15:20:36 -0700 | [diff] [blame] | 862 | } else { | 
| Jeff Garzik | 669a5db | 2006-08-29 18:12:40 -0400 | [diff] [blame] | 863 | /* | 
|  | 864 | * MWDMA is driven by the PIO timings. We must also enable | 
|  | 865 | * IORDY unconditionally along with TIME1. PPE has already | 
|  | 866 | * been set when the PIO timing was set. | 
|  | 867 | */ | 
|  | 868 | unsigned int mwdma	= adev->dma_mode - XFER_MW_DMA_0; | 
|  | 869 | unsigned int control; | 
|  | 870 | u8 slave_data; | 
|  | 871 | const unsigned int needed_pio[3] = { | 
|  | 872 | XFER_PIO_0, XFER_PIO_3, XFER_PIO_4 | 
|  | 873 | }; | 
|  | 874 | int pio = needed_pio[mwdma] - XFER_PIO_0; | 
| Jeff Garzik | 85cd725 | 2006-08-31 00:03:49 -0400 | [diff] [blame] | 875 |  | 
| Jeff Garzik | 669a5db | 2006-08-29 18:12:40 -0400 | [diff] [blame] | 876 | control = 3;	/* IORDY|TIME1 */ | 
| Jeff Garzik | 85cd725 | 2006-08-31 00:03:49 -0400 | [diff] [blame] | 877 |  | 
| Jeff Garzik | 669a5db | 2006-08-29 18:12:40 -0400 | [diff] [blame] | 878 | /* If the drive MWDMA is faster than it can do PIO then | 
|  | 879 | we must force PIO into PIO0 */ | 
| Jeff Garzik | 85cd725 | 2006-08-31 00:03:49 -0400 | [diff] [blame] | 880 |  | 
| Jeff Garzik | 669a5db | 2006-08-29 18:12:40 -0400 | [diff] [blame] | 881 | if (adev->pio_mode < needed_pio[mwdma]) | 
|  | 882 | /* Enable DMA timing only */ | 
|  | 883 | control |= 8;	/* PIO cycles in PIO0 */ | 
|  | 884 |  | 
|  | 885 | if (adev->devno) {	/* Slave */ | 
|  | 886 | master_data &= 0xFF4F;  /* Mask out IORDY|TIME1|DMAONLY */ | 
|  | 887 | master_data |= control << 4; | 
|  | 888 | pci_read_config_byte(dev, 0x44, &slave_data); | 
| Tejun Heo | a5bf5f5 | 2007-05-25 19:16:58 +0200 | [diff] [blame] | 889 | slave_data &= (ap->port_no ? 0x0f : 0xf0); | 
| Jeff Garzik | 669a5db | 2006-08-29 18:12:40 -0400 | [diff] [blame] | 890 | /* Load the matching timing */ | 
|  | 891 | slave_data |= ((timings[pio][0] << 2) | timings[pio][1]) << (ap->port_no ? 4 : 0); | 
|  | 892 | pci_write_config_byte(dev, 0x44, slave_data); | 
|  | 893 | } else { 	/* Master */ | 
| Jeff Garzik | 85cd725 | 2006-08-31 00:03:49 -0400 | [diff] [blame] | 894 | master_data &= 0xCCF4;	/* Mask out IORDY|TIME1|DMAONLY | 
| Jeff Garzik | 669a5db | 2006-08-29 18:12:40 -0400 | [diff] [blame] | 895 | and master timing bits */ | 
|  | 896 | master_data |= control; | 
|  | 897 | master_data |= | 
|  | 898 | (timings[pio][0] << 12) | | 
|  | 899 | (timings[pio][1] << 8); | 
|  | 900 | } | 
| Tejun Heo | a5bf5f5 | 2007-05-25 19:16:58 +0200 | [diff] [blame] | 901 |  | 
| Bartlomiej Zolnierkiewicz | 6938594 | 2009-12-03 20:32:08 +0100 | [diff] [blame] | 902 | if (ap->udma_mask) | 
| Tejun Heo | a5bf5f5 | 2007-05-25 19:16:58 +0200 | [diff] [blame] | 903 | udma_enable &= ~(1 << devid); | 
| Bartlomiej Zolnierkiewicz | 6938594 | 2009-12-03 20:32:08 +0100 | [diff] [blame] | 904 |  | 
|  | 905 | pci_write_config_word(dev, master_port, master_data); | 
| Linus Torvalds | 1da177e | 2005-04-16 15:20:36 -0700 | [diff] [blame] | 906 | } | 
| Jeff Garzik | 669a5db | 2006-08-29 18:12:40 -0400 | [diff] [blame] | 907 | /* Don't scribble on 0x48 if the controller does not support UDMA */ | 
|  | 908 | if (ap->udma_mask) | 
|  | 909 | pci_write_config_byte(dev, 0x48, udma_enable); | 
| Bartlomiej Zolnierkiewicz | 60c3be3 | 2009-08-30 14:56:30 +0200 | [diff] [blame] | 910 |  | 
|  | 911 | spin_unlock_irqrestore(&piix_lock, flags); | 
| Jeff Garzik | 669a5db | 2006-08-29 18:12:40 -0400 | [diff] [blame] | 912 | } | 
|  | 913 |  | 
|  | 914 | /** | 
|  | 915 | *	piix_set_dmamode - Initialize host controller PATA DMA timings | 
|  | 916 | *	@ap: Port whose timings we are configuring | 
|  | 917 | *	@adev: um | 
|  | 918 | * | 
|  | 919 | *	Set MW/UDMA mode for device, in host controller PCI config space. | 
|  | 920 | * | 
|  | 921 | *	LOCKING: | 
|  | 922 | *	None (inherited from caller). | 
|  | 923 | */ | 
|  | 924 |  | 
| Jeff Garzik | 2dcb407 | 2007-10-19 06:42:56 -0400 | [diff] [blame] | 925 | static void piix_set_dmamode(struct ata_port *ap, struct ata_device *adev) | 
| Jeff Garzik | 669a5db | 2006-08-29 18:12:40 -0400 | [diff] [blame] | 926 | { | 
|  | 927 | do_pata_set_dmamode(ap, adev, 0); | 
|  | 928 | } | 
|  | 929 |  | 
|  | 930 | /** | 
|  | 931 | *	ich_set_dmamode - Initialize host controller PATA DMA timings | 
|  | 932 | *	@ap: Port whose timings we are configuring | 
|  | 933 | *	@adev: um | 
|  | 934 | * | 
|  | 935 | *	Set MW/UDMA mode for device, in host controller PCI config space. | 
|  | 936 | * | 
|  | 937 | *	LOCKING: | 
|  | 938 | *	None (inherited from caller). | 
|  | 939 | */ | 
|  | 940 |  | 
| Jeff Garzik | 2dcb407 | 2007-10-19 06:42:56 -0400 | [diff] [blame] | 941 | static void ich_set_dmamode(struct ata_port *ap, struct ata_device *adev) | 
| Jeff Garzik | 669a5db | 2006-08-29 18:12:40 -0400 | [diff] [blame] | 942 | { | 
|  | 943 | do_pata_set_dmamode(ap, adev, 1); | 
| Linus Torvalds | 1da177e | 2005-04-16 15:20:36 -0700 | [diff] [blame] | 944 | } | 
|  | 945 |  | 
| Tejun Heo | c729072 | 2008-01-18 18:36:30 +0900 | [diff] [blame] | 946 | /* | 
|  | 947 | * Serial ATA Index/Data Pair Superset Registers access | 
|  | 948 | * | 
|  | 949 | * Beginning from ICH8, there's a sane way to access SCRs using index | 
| Tejun Heo | be77e43 | 2008-07-31 17:02:44 +0900 | [diff] [blame] | 950 | * and data register pair located at BAR5 which means that we have | 
|  | 951 | * separate SCRs for master and slave.  This is handled using libata | 
|  | 952 | * slave_link facility. | 
| Tejun Heo | c729072 | 2008-01-18 18:36:30 +0900 | [diff] [blame] | 953 | */ | 
|  | 954 | static const int piix_sidx_map[] = { | 
|  | 955 | [SCR_STATUS]	= 0, | 
|  | 956 | [SCR_ERROR]	= 2, | 
|  | 957 | [SCR_CONTROL]	= 1, | 
|  | 958 | }; | 
|  | 959 |  | 
| Tejun Heo | be77e43 | 2008-07-31 17:02:44 +0900 | [diff] [blame] | 960 | static void piix_sidpr_sel(struct ata_link *link, unsigned int reg) | 
| Tejun Heo | c729072 | 2008-01-18 18:36:30 +0900 | [diff] [blame] | 961 | { | 
| Tejun Heo | be77e43 | 2008-07-31 17:02:44 +0900 | [diff] [blame] | 962 | struct ata_port *ap = link->ap; | 
| Tejun Heo | c729072 | 2008-01-18 18:36:30 +0900 | [diff] [blame] | 963 | struct piix_host_priv *hpriv = ap->host->private_data; | 
|  | 964 |  | 
| Tejun Heo | be77e43 | 2008-07-31 17:02:44 +0900 | [diff] [blame] | 965 | iowrite32(((ap->port_no * 2 + link->pmp) << 8) | piix_sidx_map[reg], | 
| Tejun Heo | c729072 | 2008-01-18 18:36:30 +0900 | [diff] [blame] | 966 | hpriv->sidpr + PIIX_SIDPR_IDX); | 
|  | 967 | } | 
|  | 968 |  | 
| Tejun Heo | 82ef04f | 2008-07-31 17:02:40 +0900 | [diff] [blame] | 969 | static int piix_sidpr_scr_read(struct ata_link *link, | 
|  | 970 | unsigned int reg, u32 *val) | 
| Tejun Heo | c729072 | 2008-01-18 18:36:30 +0900 | [diff] [blame] | 971 | { | 
| Tejun Heo | be77e43 | 2008-07-31 17:02:44 +0900 | [diff] [blame] | 972 | struct piix_host_priv *hpriv = link->ap->host->private_data; | 
| Tejun Heo | c729072 | 2008-01-18 18:36:30 +0900 | [diff] [blame] | 973 |  | 
|  | 974 | if (reg >= ARRAY_SIZE(piix_sidx_map)) | 
|  | 975 | return -EINVAL; | 
|  | 976 |  | 
| Tejun Heo | be77e43 | 2008-07-31 17:02:44 +0900 | [diff] [blame] | 977 | piix_sidpr_sel(link, reg); | 
|  | 978 | *val = ioread32(hpriv->sidpr + PIIX_SIDPR_DATA); | 
| Tejun Heo | c729072 | 2008-01-18 18:36:30 +0900 | [diff] [blame] | 979 | return 0; | 
|  | 980 | } | 
|  | 981 |  | 
| Tejun Heo | 82ef04f | 2008-07-31 17:02:40 +0900 | [diff] [blame] | 982 | static int piix_sidpr_scr_write(struct ata_link *link, | 
|  | 983 | unsigned int reg, u32 val) | 
| Tejun Heo | c729072 | 2008-01-18 18:36:30 +0900 | [diff] [blame] | 984 | { | 
| Tejun Heo | be77e43 | 2008-07-31 17:02:44 +0900 | [diff] [blame] | 985 | struct piix_host_priv *hpriv = link->ap->host->private_data; | 
| Tejun Heo | 82ef04f | 2008-07-31 17:02:40 +0900 | [diff] [blame] | 986 |  | 
| Tejun Heo | c729072 | 2008-01-18 18:36:30 +0900 | [diff] [blame] | 987 | if (reg >= ARRAY_SIZE(piix_sidx_map)) | 
|  | 988 | return -EINVAL; | 
|  | 989 |  | 
| Tejun Heo | be77e43 | 2008-07-31 17:02:44 +0900 | [diff] [blame] | 990 | piix_sidpr_sel(link, reg); | 
|  | 991 | iowrite32(val, hpriv->sidpr + PIIX_SIDPR_DATA); | 
| Tejun Heo | c729072 | 2008-01-18 18:36:30 +0900 | [diff] [blame] | 992 | return 0; | 
|  | 993 | } | 
|  | 994 |  | 
| Tejun Heo | a97c4006 | 2010-09-01 17:50:08 +0200 | [diff] [blame] | 995 | static int piix_sidpr_set_lpm(struct ata_link *link, enum ata_lpm_policy policy, | 
|  | 996 | unsigned hints) | 
|  | 997 | { | 
|  | 998 | return sata_link_scr_lpm(link, policy, false); | 
|  | 999 | } | 
|  | 1000 |  | 
| Tejun Heo | 2794362 | 2010-01-19 10:49:19 +0900 | [diff] [blame] | 1001 | static bool piix_irq_check(struct ata_port *ap) | 
|  | 1002 | { | 
|  | 1003 | if (unlikely(!ap->ioaddr.bmdma_addr)) | 
|  | 1004 | return false; | 
|  | 1005 |  | 
|  | 1006 | return ap->ops->bmdma_status(ap) & ATA_DMA_INTR; | 
|  | 1007 | } | 
|  | 1008 |  | 
| Tejun Heo | b8b275e | 2007-07-10 15:55:43 +0900 | [diff] [blame] | 1009 | #ifdef CONFIG_PM | 
| Tejun Heo | 8c3832e | 2007-07-27 14:53:28 +0900 | [diff] [blame] | 1010 | static int piix_broken_suspend(void) | 
|  | 1011 | { | 
| Jeff Garzik | 1855256 | 2007-10-03 15:15:40 -0400 | [diff] [blame] | 1012 | static const struct dmi_system_id sysids[] = { | 
| Tejun Heo | 8c3832e | 2007-07-27 14:53:28 +0900 | [diff] [blame] | 1013 | { | 
| Tejun Heo | 4c74d4e | 2007-09-30 01:11:20 -0700 | [diff] [blame] | 1014 | .ident = "TECRA M3", | 
|  | 1015 | .matches = { | 
|  | 1016 | DMI_MATCH(DMI_SYS_VENDOR, "TOSHIBA"), | 
|  | 1017 | DMI_MATCH(DMI_PRODUCT_NAME, "TECRA M3"), | 
|  | 1018 | }, | 
|  | 1019 | }, | 
|  | 1020 | { | 
| Peter Schwenke | 04d86d6 | 2007-11-30 15:28:29 +0900 | [diff] [blame] | 1021 | .ident = "TECRA M3", | 
|  | 1022 | .matches = { | 
|  | 1023 | DMI_MATCH(DMI_SYS_VENDOR, "TOSHIBA"), | 
|  | 1024 | DMI_MATCH(DMI_PRODUCT_NAME, "Tecra M3"), | 
|  | 1025 | }, | 
|  | 1026 | }, | 
|  | 1027 | { | 
| Peter Schwenke | d1aa690 | 2007-12-05 10:39:49 +0900 | [diff] [blame] | 1028 | .ident = "TECRA M4", | 
|  | 1029 | .matches = { | 
|  | 1030 | DMI_MATCH(DMI_SYS_VENDOR, "TOSHIBA"), | 
|  | 1031 | DMI_MATCH(DMI_PRODUCT_NAME, "Tecra M4"), | 
|  | 1032 | }, | 
|  | 1033 | }, | 
|  | 1034 | { | 
| Tejun Heo | 040dee5 | 2008-06-13 18:05:02 +0900 | [diff] [blame] | 1035 | .ident = "TECRA M4", | 
|  | 1036 | .matches = { | 
|  | 1037 | DMI_MATCH(DMI_SYS_VENDOR, "TOSHIBA"), | 
|  | 1038 | DMI_MATCH(DMI_PRODUCT_NAME, "TECRA M4"), | 
|  | 1039 | }, | 
|  | 1040 | }, | 
|  | 1041 | { | 
| Tejun Heo | 8c3832e | 2007-07-27 14:53:28 +0900 | [diff] [blame] | 1042 | .ident = "TECRA M5", | 
|  | 1043 | .matches = { | 
|  | 1044 | DMI_MATCH(DMI_SYS_VENDOR, "TOSHIBA"), | 
|  | 1045 | DMI_MATCH(DMI_PRODUCT_NAME, "TECRA M5"), | 
|  | 1046 | }, | 
| Tejun Heo | b8b275e | 2007-07-10 15:55:43 +0900 | [diff] [blame] | 1047 | }, | 
| Tejun Heo | 8c3832e | 2007-07-27 14:53:28 +0900 | [diff] [blame] | 1048 | { | 
| Peter Schwenke | ffe188d | 2008-01-17 23:08:55 +1000 | [diff] [blame] | 1049 | .ident = "TECRA M6", | 
|  | 1050 | .matches = { | 
|  | 1051 | DMI_MATCH(DMI_SYS_VENDOR, "TOSHIBA"), | 
|  | 1052 | DMI_MATCH(DMI_PRODUCT_NAME, "TECRA M6"), | 
|  | 1053 | }, | 
|  | 1054 | }, | 
|  | 1055 | { | 
| Tejun Heo | 5c08ea0 | 2007-08-14 19:56:04 +0900 | [diff] [blame] | 1056 | .ident = "TECRA M7", | 
|  | 1057 | .matches = { | 
|  | 1058 | DMI_MATCH(DMI_SYS_VENDOR, "TOSHIBA"), | 
|  | 1059 | DMI_MATCH(DMI_PRODUCT_NAME, "TECRA M7"), | 
|  | 1060 | }, | 
|  | 1061 | }, | 
|  | 1062 | { | 
| Peter Schwenke | 04d86d6 | 2007-11-30 15:28:29 +0900 | [diff] [blame] | 1063 | .ident = "TECRA A8", | 
|  | 1064 | .matches = { | 
|  | 1065 | DMI_MATCH(DMI_SYS_VENDOR, "TOSHIBA"), | 
|  | 1066 | DMI_MATCH(DMI_PRODUCT_NAME, "TECRA A8"), | 
|  | 1067 | }, | 
|  | 1068 | }, | 
|  | 1069 | { | 
| Peter Schwenke | ffe188d | 2008-01-17 23:08:55 +1000 | [diff] [blame] | 1070 | .ident = "Satellite R20", | 
|  | 1071 | .matches = { | 
|  | 1072 | DMI_MATCH(DMI_SYS_VENDOR, "TOSHIBA"), | 
|  | 1073 | DMI_MATCH(DMI_PRODUCT_NAME, "Satellite R20"), | 
|  | 1074 | }, | 
|  | 1075 | }, | 
|  | 1076 | { | 
| Peter Schwenke | 04d86d6 | 2007-11-30 15:28:29 +0900 | [diff] [blame] | 1077 | .ident = "Satellite R25", | 
|  | 1078 | .matches = { | 
|  | 1079 | DMI_MATCH(DMI_SYS_VENDOR, "TOSHIBA"), | 
|  | 1080 | DMI_MATCH(DMI_PRODUCT_NAME, "Satellite R25"), | 
|  | 1081 | }, | 
|  | 1082 | }, | 
|  | 1083 | { | 
| Tejun Heo | 3cc0b9d | 2007-08-25 08:31:02 +0900 | [diff] [blame] | 1084 | .ident = "Satellite U200", | 
|  | 1085 | .matches = { | 
|  | 1086 | DMI_MATCH(DMI_SYS_VENDOR, "TOSHIBA"), | 
|  | 1087 | DMI_MATCH(DMI_PRODUCT_NAME, "Satellite U200"), | 
|  | 1088 | }, | 
|  | 1089 | }, | 
|  | 1090 | { | 
| Peter Schwenke | 04d86d6 | 2007-11-30 15:28:29 +0900 | [diff] [blame] | 1091 | .ident = "Satellite U200", | 
|  | 1092 | .matches = { | 
|  | 1093 | DMI_MATCH(DMI_SYS_VENDOR, "TOSHIBA"), | 
|  | 1094 | DMI_MATCH(DMI_PRODUCT_NAME, "SATELLITE U200"), | 
|  | 1095 | }, | 
|  | 1096 | }, | 
|  | 1097 | { | 
| Yann Chachkoff | 62320e2 | 2007-11-07 12:02:27 +0900 | [diff] [blame] | 1098 | .ident = "Satellite Pro U200", | 
|  | 1099 | .matches = { | 
|  | 1100 | DMI_MATCH(DMI_SYS_VENDOR, "TOSHIBA"), | 
|  | 1101 | DMI_MATCH(DMI_PRODUCT_NAME, "SATELLITE PRO U200"), | 
|  | 1102 | }, | 
|  | 1103 | }, | 
|  | 1104 | { | 
| Tejun Heo | 8c3832e | 2007-07-27 14:53:28 +0900 | [diff] [blame] | 1105 | .ident = "Satellite U205", | 
|  | 1106 | .matches = { | 
|  | 1107 | DMI_MATCH(DMI_SYS_VENDOR, "TOSHIBA"), | 
|  | 1108 | DMI_MATCH(DMI_PRODUCT_NAME, "Satellite U205"), | 
|  | 1109 | }, | 
| Tejun Heo | b8b275e | 2007-07-10 15:55:43 +0900 | [diff] [blame] | 1110 | }, | 
| Tejun Heo | 8c3832e | 2007-07-27 14:53:28 +0900 | [diff] [blame] | 1111 | { | 
| Tejun Heo | de753e5 | 2007-11-12 17:56:24 +0900 | [diff] [blame] | 1112 | .ident = "SATELLITE U205", | 
|  | 1113 | .matches = { | 
|  | 1114 | DMI_MATCH(DMI_SYS_VENDOR, "TOSHIBA"), | 
|  | 1115 | DMI_MATCH(DMI_PRODUCT_NAME, "SATELLITE U205"), | 
|  | 1116 | }, | 
|  | 1117 | }, | 
|  | 1118 | { | 
| Tejun Heo | 8c3832e | 2007-07-27 14:53:28 +0900 | [diff] [blame] | 1119 | .ident = "Portege M500", | 
|  | 1120 | .matches = { | 
|  | 1121 | DMI_MATCH(DMI_SYS_VENDOR, "TOSHIBA"), | 
|  | 1122 | DMI_MATCH(DMI_PRODUCT_NAME, "PORTEGE M500"), | 
|  | 1123 | }, | 
| Tejun Heo | b8b275e | 2007-07-10 15:55:43 +0900 | [diff] [blame] | 1124 | }, | 
| Tejun Heo | c3f93b8 | 2009-03-31 10:44:34 +0900 | [diff] [blame] | 1125 | { | 
|  | 1126 | .ident = "VGN-BX297XP", | 
|  | 1127 | .matches = { | 
|  | 1128 | DMI_MATCH(DMI_SYS_VENDOR, "Sony Corporation"), | 
|  | 1129 | DMI_MATCH(DMI_PRODUCT_NAME, "VGN-BX297XP"), | 
|  | 1130 | }, | 
|  | 1131 | }, | 
| Jeff Garzik | 7d05154 | 2007-09-01 06:48:52 -0400 | [diff] [blame] | 1132 |  | 
|  | 1133 | { }	/* terminate list */ | 
| Tejun Heo | 8c3832e | 2007-07-27 14:53:28 +0900 | [diff] [blame] | 1134 | }; | 
| Tejun Heo | 7abe79c | 2007-07-27 14:55:07 +0900 | [diff] [blame] | 1135 | static const char *oemstrs[] = { | 
|  | 1136 | "Tecra M3,", | 
|  | 1137 | }; | 
|  | 1138 | int i; | 
| Tejun Heo | 8c3832e | 2007-07-27 14:53:28 +0900 | [diff] [blame] | 1139 |  | 
|  | 1140 | if (dmi_check_system(sysids)) | 
|  | 1141 | return 1; | 
|  | 1142 |  | 
| Tejun Heo | 7abe79c | 2007-07-27 14:55:07 +0900 | [diff] [blame] | 1143 | for (i = 0; i < ARRAY_SIZE(oemstrs); i++) | 
|  | 1144 | if (dmi_find_device(DMI_DEV_TYPE_OEM_STRING, oemstrs[i], NULL)) | 
|  | 1145 | return 1; | 
|  | 1146 |  | 
| Tejun Heo | 1eedb4a | 2008-11-29 22:37:21 +0900 | [diff] [blame] | 1147 | /* TECRA M4 sometimes forgets its identify and reports bogus | 
|  | 1148 | * DMI information.  As the bogus information is a bit | 
|  | 1149 | * generic, match as many entries as possible.  This manual | 
|  | 1150 | * matching is necessary because dmi_system_id.matches is | 
|  | 1151 | * limited to four entries. | 
|  | 1152 | */ | 
| Jiri Slaby | 3c38773 | 2008-12-10 14:07:22 +0100 | [diff] [blame] | 1153 | if (dmi_match(DMI_SYS_VENDOR, "TOSHIBA") && | 
|  | 1154 | dmi_match(DMI_PRODUCT_NAME, "000000") && | 
|  | 1155 | dmi_match(DMI_PRODUCT_VERSION, "000000") && | 
|  | 1156 | dmi_match(DMI_PRODUCT_SERIAL, "000000") && | 
|  | 1157 | dmi_match(DMI_BOARD_VENDOR, "TOSHIBA") && | 
|  | 1158 | dmi_match(DMI_BOARD_NAME, "Portable PC") && | 
|  | 1159 | dmi_match(DMI_BOARD_VERSION, "Version A0")) | 
| Tejun Heo | 1eedb4a | 2008-11-29 22:37:21 +0900 | [diff] [blame] | 1160 | return 1; | 
|  | 1161 |  | 
| Tejun Heo | 8c3832e | 2007-07-27 14:53:28 +0900 | [diff] [blame] | 1162 | return 0; | 
|  | 1163 | } | 
| Tejun Heo | b8b275e | 2007-07-10 15:55:43 +0900 | [diff] [blame] | 1164 |  | 
|  | 1165 | static int piix_pci_device_suspend(struct pci_dev *pdev, pm_message_t mesg) | 
|  | 1166 | { | 
|  | 1167 | struct ata_host *host = dev_get_drvdata(&pdev->dev); | 
|  | 1168 | unsigned long flags; | 
|  | 1169 | int rc = 0; | 
|  | 1170 |  | 
|  | 1171 | rc = ata_host_suspend(host, mesg); | 
|  | 1172 | if (rc) | 
|  | 1173 | return rc; | 
|  | 1174 |  | 
|  | 1175 | /* Some braindamaged ACPI suspend implementations expect the | 
|  | 1176 | * controller to be awake on entry; otherwise, it burns cpu | 
|  | 1177 | * cycles and power trying to do something to the sleeping | 
|  | 1178 | * beauty. | 
|  | 1179 | */ | 
| Rafael J. Wysocki | 3a2d5b7 | 2008-02-23 19:13:25 +0100 | [diff] [blame] | 1180 | if (piix_broken_suspend() && (mesg.event & PM_EVENT_SLEEP)) { | 
| Tejun Heo | b8b275e | 2007-07-10 15:55:43 +0900 | [diff] [blame] | 1181 | pci_save_state(pdev); | 
|  | 1182 |  | 
|  | 1183 | /* mark its power state as "unknown", since we don't | 
|  | 1184 | * know if e.g. the BIOS will change its device state | 
|  | 1185 | * when we suspend. | 
|  | 1186 | */ | 
|  | 1187 | if (pdev->current_state == PCI_D0) | 
|  | 1188 | pdev->current_state = PCI_UNKNOWN; | 
|  | 1189 |  | 
|  | 1190 | /* tell resume that it's waking up from broken suspend */ | 
|  | 1191 | spin_lock_irqsave(&host->lock, flags); | 
|  | 1192 | host->flags |= PIIX_HOST_BROKEN_SUSPEND; | 
|  | 1193 | spin_unlock_irqrestore(&host->lock, flags); | 
|  | 1194 | } else | 
|  | 1195 | ata_pci_device_do_suspend(pdev, mesg); | 
|  | 1196 |  | 
|  | 1197 | return 0; | 
|  | 1198 | } | 
|  | 1199 |  | 
|  | 1200 | static int piix_pci_device_resume(struct pci_dev *pdev) | 
|  | 1201 | { | 
|  | 1202 | struct ata_host *host = dev_get_drvdata(&pdev->dev); | 
|  | 1203 | unsigned long flags; | 
|  | 1204 | int rc; | 
|  | 1205 |  | 
|  | 1206 | if (host->flags & PIIX_HOST_BROKEN_SUSPEND) { | 
|  | 1207 | spin_lock_irqsave(&host->lock, flags); | 
|  | 1208 | host->flags &= ~PIIX_HOST_BROKEN_SUSPEND; | 
|  | 1209 | spin_unlock_irqrestore(&host->lock, flags); | 
|  | 1210 |  | 
|  | 1211 | pci_set_power_state(pdev, PCI_D0); | 
|  | 1212 | pci_restore_state(pdev); | 
|  | 1213 |  | 
|  | 1214 | /* PCI device wasn't disabled during suspend.  Use | 
| Tejun Heo | 0b62e13 | 2007-07-27 14:43:35 +0900 | [diff] [blame] | 1215 | * pci_reenable_device() to avoid affecting the enable | 
|  | 1216 | * count. | 
| Tejun Heo | b8b275e | 2007-07-10 15:55:43 +0900 | [diff] [blame] | 1217 | */ | 
| Tejun Heo | 0b62e13 | 2007-07-27 14:43:35 +0900 | [diff] [blame] | 1218 | rc = pci_reenable_device(pdev); | 
| Tejun Heo | b8b275e | 2007-07-10 15:55:43 +0900 | [diff] [blame] | 1219 | if (rc) | 
|  | 1220 | dev_printk(KERN_ERR, &pdev->dev, "failed to enable " | 
|  | 1221 | "device after resume (%d)\n", rc); | 
|  | 1222 | } else | 
|  | 1223 | rc = ata_pci_device_do_resume(pdev); | 
|  | 1224 |  | 
|  | 1225 | if (rc == 0) | 
|  | 1226 | ata_host_resume(host); | 
|  | 1227 |  | 
|  | 1228 | return rc; | 
|  | 1229 | } | 
|  | 1230 | #endif | 
|  | 1231 |  | 
| Tejun Heo | 25f9813 | 2008-01-07 19:38:53 +0900 | [diff] [blame] | 1232 | static u8 piix_vmw_bmdma_status(struct ata_port *ap) | 
|  | 1233 | { | 
|  | 1234 | return ata_bmdma_status(ap) & ~ATA_DMA_ERR; | 
|  | 1235 | } | 
|  | 1236 |  | 
| Linus Torvalds | 1da177e | 2005-04-16 15:20:36 -0700 | [diff] [blame] | 1237 | #define AHCI_PCI_BAR 5 | 
|  | 1238 | #define AHCI_GLOBAL_CTL 0x04 | 
|  | 1239 | #define AHCI_ENABLE (1 << 31) | 
|  | 1240 | static int piix_disable_ahci(struct pci_dev *pdev) | 
|  | 1241 | { | 
| Jeff Garzik | ea6ba10 | 2005-08-30 05:18:18 -0400 | [diff] [blame] | 1242 | void __iomem *mmio; | 
| Linus Torvalds | 1da177e | 2005-04-16 15:20:36 -0700 | [diff] [blame] | 1243 | u32 tmp; | 
|  | 1244 | int rc = 0; | 
|  | 1245 |  | 
|  | 1246 | /* BUG: pci_enable_device has not yet been called.  This | 
|  | 1247 | * works because this device is usually set up by BIOS. | 
|  | 1248 | */ | 
|  | 1249 |  | 
| Jeff Garzik | 374b187 | 2005-08-30 05:42:52 -0400 | [diff] [blame] | 1250 | if (!pci_resource_start(pdev, AHCI_PCI_BAR) || | 
|  | 1251 | !pci_resource_len(pdev, AHCI_PCI_BAR)) | 
| Linus Torvalds | 1da177e | 2005-04-16 15:20:36 -0700 | [diff] [blame] | 1252 | return 0; | 
| Greg Felix | 7b6dbd6 | 2005-07-28 15:54:15 -0400 | [diff] [blame] | 1253 |  | 
| Jeff Garzik | 374b187 | 2005-08-30 05:42:52 -0400 | [diff] [blame] | 1254 | mmio = pci_iomap(pdev, AHCI_PCI_BAR, 64); | 
| Linus Torvalds | 1da177e | 2005-04-16 15:20:36 -0700 | [diff] [blame] | 1255 | if (!mmio) | 
|  | 1256 | return -ENOMEM; | 
| Greg Felix | 7b6dbd6 | 2005-07-28 15:54:15 -0400 | [diff] [blame] | 1257 |  | 
| Alan Cox | c47a631 | 2007-11-19 14:28:28 +0000 | [diff] [blame] | 1258 | tmp = ioread32(mmio + AHCI_GLOBAL_CTL); | 
| Linus Torvalds | 1da177e | 2005-04-16 15:20:36 -0700 | [diff] [blame] | 1259 | if (tmp & AHCI_ENABLE) { | 
|  | 1260 | tmp &= ~AHCI_ENABLE; | 
| Alan Cox | c47a631 | 2007-11-19 14:28:28 +0000 | [diff] [blame] | 1261 | iowrite32(tmp, mmio + AHCI_GLOBAL_CTL); | 
| Linus Torvalds | 1da177e | 2005-04-16 15:20:36 -0700 | [diff] [blame] | 1262 |  | 
| Alan Cox | c47a631 | 2007-11-19 14:28:28 +0000 | [diff] [blame] | 1263 | tmp = ioread32(mmio + AHCI_GLOBAL_CTL); | 
| Linus Torvalds | 1da177e | 2005-04-16 15:20:36 -0700 | [diff] [blame] | 1264 | if (tmp & AHCI_ENABLE) | 
|  | 1265 | rc = -EIO; | 
|  | 1266 | } | 
| Greg Felix | 7b6dbd6 | 2005-07-28 15:54:15 -0400 | [diff] [blame] | 1267 |  | 
| Jeff Garzik | 374b187 | 2005-08-30 05:42:52 -0400 | [diff] [blame] | 1268 | pci_iounmap(pdev, mmio); | 
| Linus Torvalds | 1da177e | 2005-04-16 15:20:36 -0700 | [diff] [blame] | 1269 | return rc; | 
|  | 1270 | } | 
|  | 1271 |  | 
|  | 1272 | /** | 
| Alan Cox | c621b14 | 2005-12-08 19:22:28 +0000 | [diff] [blame] | 1273 | *	piix_check_450nx_errata	-	Check for problem 450NX setup | 
| Randy Dunlap | c893a3a | 2006-01-28 13:15:32 -0500 | [diff] [blame] | 1274 | *	@ata_dev: the PCI device to check | 
| Jeff Garzik | 2e9edbf | 2006-03-24 09:56:57 -0500 | [diff] [blame] | 1275 | * | 
| Alan Cox | c621b14 | 2005-12-08 19:22:28 +0000 | [diff] [blame] | 1276 | *	Check for the present of 450NX errata #19 and errata #25. If | 
|  | 1277 | *	they are found return an error code so we can turn off DMA | 
|  | 1278 | */ | 
|  | 1279 |  | 
|  | 1280 | static int __devinit piix_check_450nx_errata(struct pci_dev *ata_dev) | 
|  | 1281 | { | 
|  | 1282 | struct pci_dev *pdev = NULL; | 
|  | 1283 | u16 cfg; | 
| Alan Cox | c621b14 | 2005-12-08 19:22:28 +0000 | [diff] [blame] | 1284 | int no_piix_dma = 0; | 
| Jeff Garzik | 2e9edbf | 2006-03-24 09:56:57 -0500 | [diff] [blame] | 1285 |  | 
| Jeff Garzik | 2dcb407 | 2007-10-19 06:42:56 -0400 | [diff] [blame] | 1286 | while ((pdev = pci_get_device(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_82454NX, pdev)) != NULL) { | 
| Alan Cox | c621b14 | 2005-12-08 19:22:28 +0000 | [diff] [blame] | 1287 | /* Look for 450NX PXB. Check for problem configurations | 
|  | 1288 | A PCI quirk checks bit 6 already */ | 
| Alan Cox | c621b14 | 2005-12-08 19:22:28 +0000 | [diff] [blame] | 1289 | pci_read_config_word(pdev, 0x41, &cfg); | 
|  | 1290 | /* Only on the original revision: IDE DMA can hang */ | 
| Auke Kok | 44c1013 | 2007-06-08 15:46:36 -0700 | [diff] [blame] | 1291 | if (pdev->revision == 0x00) | 
| Alan Cox | c621b14 | 2005-12-08 19:22:28 +0000 | [diff] [blame] | 1292 | no_piix_dma = 1; | 
|  | 1293 | /* On all revisions below 5 PXB bus lock must be disabled for IDE */ | 
| Auke Kok | 44c1013 | 2007-06-08 15:46:36 -0700 | [diff] [blame] | 1294 | else if (cfg & (1<<14) && pdev->revision < 5) | 
| Alan Cox | c621b14 | 2005-12-08 19:22:28 +0000 | [diff] [blame] | 1295 | no_piix_dma = 2; | 
|  | 1296 | } | 
| Alan Cox | 31a34fe | 2006-05-22 22:58:14 +0100 | [diff] [blame] | 1297 | if (no_piix_dma) | 
| Alan Cox | c621b14 | 2005-12-08 19:22:28 +0000 | [diff] [blame] | 1298 | dev_printk(KERN_WARNING, &ata_dev->dev, "450NX errata present, disabling IDE DMA.\n"); | 
| Alan Cox | 31a34fe | 2006-05-22 22:58:14 +0100 | [diff] [blame] | 1299 | if (no_piix_dma == 2) | 
| Alan Cox | c621b14 | 2005-12-08 19:22:28 +0000 | [diff] [blame] | 1300 | dev_printk(KERN_WARNING, &ata_dev->dev, "A BIOS update may resolve this.\n"); | 
|  | 1301 | return no_piix_dma; | 
| Jeff Garzik | 2e9edbf | 2006-03-24 09:56:57 -0500 | [diff] [blame] | 1302 | } | 
| Alan Cox | c621b14 | 2005-12-08 19:22:28 +0000 | [diff] [blame] | 1303 |  | 
| Tejun Heo | 8b09f0d | 2008-01-18 18:36:29 +0900 | [diff] [blame] | 1304 | static void __devinit piix_init_pcs(struct ata_host *host, | 
| Jeff Garzik | ea35d29 | 2006-07-11 11:48:50 -0400 | [diff] [blame] | 1305 | const struct piix_map_db *map_db) | 
|  | 1306 | { | 
| Tejun Heo | 8b09f0d | 2008-01-18 18:36:29 +0900 | [diff] [blame] | 1307 | struct pci_dev *pdev = to_pci_dev(host->dev); | 
| Jeff Garzik | ea35d29 | 2006-07-11 11:48:50 -0400 | [diff] [blame] | 1308 | u16 pcs, new_pcs; | 
|  | 1309 |  | 
|  | 1310 | pci_read_config_word(pdev, ICH5_PCS, &pcs); | 
|  | 1311 |  | 
|  | 1312 | new_pcs = pcs | map_db->port_enable; | 
|  | 1313 |  | 
|  | 1314 | if (new_pcs != pcs) { | 
|  | 1315 | DPRINTK("updating PCS from 0x%x to 0x%x\n", pcs, new_pcs); | 
|  | 1316 | pci_write_config_word(pdev, ICH5_PCS, new_pcs); | 
|  | 1317 | msleep(150); | 
|  | 1318 | } | 
|  | 1319 | } | 
|  | 1320 |  | 
| Tejun Heo | 8b09f0d | 2008-01-18 18:36:29 +0900 | [diff] [blame] | 1321 | static const int *__devinit piix_init_sata_map(struct pci_dev *pdev, | 
|  | 1322 | struct ata_port_info *pinfo, | 
|  | 1323 | const struct piix_map_db *map_db) | 
| Tejun Heo | d33f58b | 2006-03-01 01:25:39 +0900 | [diff] [blame] | 1324 | { | 
| Al Viro | b4482a4 | 2007-10-14 19:35:40 +0100 | [diff] [blame] | 1325 | const int *map; | 
| Tejun Heo | d33f58b | 2006-03-01 01:25:39 +0900 | [diff] [blame] | 1326 | int i, invalid_map = 0; | 
|  | 1327 | u8 map_value; | 
|  | 1328 |  | 
|  | 1329 | pci_read_config_byte(pdev, ICH5_PMR, &map_value); | 
|  | 1330 |  | 
|  | 1331 | map = map_db->map[map_value & map_db->mask]; | 
|  | 1332 |  | 
|  | 1333 | dev_printk(KERN_INFO, &pdev->dev, "MAP ["); | 
|  | 1334 | for (i = 0; i < 4; i++) { | 
|  | 1335 | switch (map[i]) { | 
|  | 1336 | case RV: | 
|  | 1337 | invalid_map = 1; | 
|  | 1338 | printk(" XX"); | 
|  | 1339 | break; | 
|  | 1340 |  | 
|  | 1341 | case NA: | 
|  | 1342 | printk(" --"); | 
|  | 1343 | break; | 
|  | 1344 |  | 
|  | 1345 | case IDE: | 
|  | 1346 | WARN_ON((i & 1) || map[i + 1] != IDE); | 
| Jeff Garzik | 669a5db | 2006-08-29 18:12:40 -0400 | [diff] [blame] | 1347 | pinfo[i / 2] = piix_port_info[ich_pata_100]; | 
| Tejun Heo | d33f58b | 2006-03-01 01:25:39 +0900 | [diff] [blame] | 1348 | i++; | 
|  | 1349 | printk(" IDE IDE"); | 
|  | 1350 | break; | 
|  | 1351 |  | 
|  | 1352 | default: | 
|  | 1353 | printk(" P%d", map[i]); | 
|  | 1354 | if (i & 1) | 
| Jeff Garzik | cca3974 | 2006-08-24 03:19:22 -0400 | [diff] [blame] | 1355 | pinfo[i / 2].flags |= ATA_FLAG_SLAVE_POSS; | 
| Tejun Heo | d33f58b | 2006-03-01 01:25:39 +0900 | [diff] [blame] | 1356 | break; | 
|  | 1357 | } | 
|  | 1358 | } | 
|  | 1359 | printk(" ]\n"); | 
|  | 1360 |  | 
|  | 1361 | if (invalid_map) | 
|  | 1362 | dev_printk(KERN_ERR, &pdev->dev, | 
|  | 1363 | "invalid MAP value %u\n", map_value); | 
|  | 1364 |  | 
| Tejun Heo | 8b09f0d | 2008-01-18 18:36:29 +0900 | [diff] [blame] | 1365 | return map; | 
| Tejun Heo | d33f58b | 2006-03-01 01:25:39 +0900 | [diff] [blame] | 1366 | } | 
|  | 1367 |  | 
| Tejun Heo | e9c1670 | 2009-03-03 13:52:16 +0900 | [diff] [blame] | 1368 | static bool piix_no_sidpr(struct ata_host *host) | 
|  | 1369 | { | 
|  | 1370 | struct pci_dev *pdev = to_pci_dev(host->dev); | 
|  | 1371 |  | 
|  | 1372 | /* | 
|  | 1373 | * Samsung DB-P70 only has three ATA ports exposed and | 
|  | 1374 | * curiously the unconnected first port reports link online | 
|  | 1375 | * while not responding to SRST protocol causing excessive | 
|  | 1376 | * detection delay. | 
|  | 1377 | * | 
|  | 1378 | * Unfortunately, the system doesn't carry enough DMI | 
|  | 1379 | * information to identify the machine but does have subsystem | 
|  | 1380 | * vendor and device set.  As it's unclear whether the | 
|  | 1381 | * subsystem vendor/device is used only for this specific | 
|  | 1382 | * board, the port can't be disabled solely with the | 
|  | 1383 | * information; however, turning off SIDPR access works around | 
|  | 1384 | * the problem.  Turn it off. | 
|  | 1385 | * | 
|  | 1386 | * This problem is reported in bnc#441240. | 
|  | 1387 | * | 
|  | 1388 | * https://bugzilla.novell.com/show_bug.cgi?id=441420 | 
|  | 1389 | */ | 
|  | 1390 | if (pdev->vendor == PCI_VENDOR_ID_INTEL && pdev->device == 0x2920 && | 
|  | 1391 | pdev->subsystem_vendor == PCI_VENDOR_ID_SAMSUNG && | 
|  | 1392 | pdev->subsystem_device == 0xb049) { | 
|  | 1393 | dev_printk(KERN_WARNING, host->dev, | 
|  | 1394 | "Samsung DB-P70 detected, disabling SIDPR\n"); | 
|  | 1395 | return true; | 
|  | 1396 | } | 
|  | 1397 |  | 
|  | 1398 | return false; | 
|  | 1399 | } | 
|  | 1400 |  | 
| Tejun Heo | be77e43 | 2008-07-31 17:02:44 +0900 | [diff] [blame] | 1401 | static int __devinit piix_init_sidpr(struct ata_host *host) | 
| Tejun Heo | c729072 | 2008-01-18 18:36:30 +0900 | [diff] [blame] | 1402 | { | 
|  | 1403 | struct pci_dev *pdev = to_pci_dev(host->dev); | 
|  | 1404 | struct piix_host_priv *hpriv = host->private_data; | 
| Tejun Heo | be77e43 | 2008-07-31 17:02:44 +0900 | [diff] [blame] | 1405 | struct ata_link *link0 = &host->ports[0]->link; | 
| Tejun Heo | cb6716c | 2008-05-01 10:03:08 +0900 | [diff] [blame] | 1406 | u32 scontrol; | 
| Tejun Heo | be77e43 | 2008-07-31 17:02:44 +0900 | [diff] [blame] | 1407 | int i, rc; | 
| Tejun Heo | c729072 | 2008-01-18 18:36:30 +0900 | [diff] [blame] | 1408 |  | 
|  | 1409 | /* check for availability */ | 
|  | 1410 | for (i = 0; i < 4; i++) | 
|  | 1411 | if (hpriv->map[i] == IDE) | 
| Tejun Heo | be77e43 | 2008-07-31 17:02:44 +0900 | [diff] [blame] | 1412 | return 0; | 
| Tejun Heo | c729072 | 2008-01-18 18:36:30 +0900 | [diff] [blame] | 1413 |  | 
| Tejun Heo | e9c1670 | 2009-03-03 13:52:16 +0900 | [diff] [blame] | 1414 | /* is it blacklisted? */ | 
|  | 1415 | if (piix_no_sidpr(host)) | 
|  | 1416 | return 0; | 
|  | 1417 |  | 
| Tejun Heo | c729072 | 2008-01-18 18:36:30 +0900 | [diff] [blame] | 1418 | if (!(host->ports[0]->flags & PIIX_FLAG_SIDPR)) | 
| Tejun Heo | be77e43 | 2008-07-31 17:02:44 +0900 | [diff] [blame] | 1419 | return 0; | 
| Tejun Heo | c729072 | 2008-01-18 18:36:30 +0900 | [diff] [blame] | 1420 |  | 
|  | 1421 | if (pci_resource_start(pdev, PIIX_SIDPR_BAR) == 0 || | 
|  | 1422 | pci_resource_len(pdev, PIIX_SIDPR_BAR) != PIIX_SIDPR_LEN) | 
| Tejun Heo | be77e43 | 2008-07-31 17:02:44 +0900 | [diff] [blame] | 1423 | return 0; | 
| Tejun Heo | c729072 | 2008-01-18 18:36:30 +0900 | [diff] [blame] | 1424 |  | 
|  | 1425 | if (pcim_iomap_regions(pdev, 1 << PIIX_SIDPR_BAR, DRV_NAME)) | 
| Tejun Heo | be77e43 | 2008-07-31 17:02:44 +0900 | [diff] [blame] | 1426 | return 0; | 
| Tejun Heo | c729072 | 2008-01-18 18:36:30 +0900 | [diff] [blame] | 1427 |  | 
|  | 1428 | hpriv->sidpr = pcim_iomap_table(pdev)[PIIX_SIDPR_BAR]; | 
| Tejun Heo | cb6716c | 2008-05-01 10:03:08 +0900 | [diff] [blame] | 1429 |  | 
|  | 1430 | /* SCR access via SIDPR doesn't work on some configurations. | 
|  | 1431 | * Give it a test drive by inhibiting power save modes which | 
|  | 1432 | * we'll do anyway. | 
|  | 1433 | */ | 
| Tejun Heo | be77e43 | 2008-07-31 17:02:44 +0900 | [diff] [blame] | 1434 | piix_sidpr_scr_read(link0, SCR_CONTROL, &scontrol); | 
| Tejun Heo | cb6716c | 2008-05-01 10:03:08 +0900 | [diff] [blame] | 1435 |  | 
|  | 1436 | /* if IPM is already 3, SCR access is probably working.  Don't | 
|  | 1437 | * un-inhibit power save modes as BIOS might have inhibited | 
|  | 1438 | * them for a reason. | 
|  | 1439 | */ | 
|  | 1440 | if ((scontrol & 0xf00) != 0x300) { | 
|  | 1441 | scontrol |= 0x300; | 
| Tejun Heo | be77e43 | 2008-07-31 17:02:44 +0900 | [diff] [blame] | 1442 | piix_sidpr_scr_write(link0, SCR_CONTROL, scontrol); | 
|  | 1443 | piix_sidpr_scr_read(link0, SCR_CONTROL, &scontrol); | 
| Tejun Heo | cb6716c | 2008-05-01 10:03:08 +0900 | [diff] [blame] | 1444 |  | 
|  | 1445 | if ((scontrol & 0xf00) != 0x300) { | 
|  | 1446 | dev_printk(KERN_INFO, host->dev, "SCR access via " | 
|  | 1447 | "SIDPR is available but doesn't work\n"); | 
| Tejun Heo | be77e43 | 2008-07-31 17:02:44 +0900 | [diff] [blame] | 1448 | return 0; | 
| Tejun Heo | cb6716c | 2008-05-01 10:03:08 +0900 | [diff] [blame] | 1449 | } | 
|  | 1450 | } | 
|  | 1451 |  | 
| Tejun Heo | be77e43 | 2008-07-31 17:02:44 +0900 | [diff] [blame] | 1452 | /* okay, SCRs available, set ops and ask libata for slave_link */ | 
|  | 1453 | for (i = 0; i < 2; i++) { | 
|  | 1454 | struct ata_port *ap = host->ports[i]; | 
|  | 1455 |  | 
|  | 1456 | ap->ops = &piix_sidpr_sata_ops; | 
|  | 1457 |  | 
|  | 1458 | if (ap->flags & ATA_FLAG_SLAVE_POSS) { | 
|  | 1459 | rc = ata_slave_link_init(ap); | 
|  | 1460 | if (rc) | 
|  | 1461 | return rc; | 
|  | 1462 | } | 
|  | 1463 | } | 
|  | 1464 |  | 
|  | 1465 | return 0; | 
| Tejun Heo | c729072 | 2008-01-18 18:36:30 +0900 | [diff] [blame] | 1466 | } | 
|  | 1467 |  | 
| Tejun Heo | 2852bcf | 2009-01-02 12:04:48 +0900 | [diff] [blame] | 1468 | static void piix_iocfg_bit18_quirk(struct ata_host *host) | 
| Tejun Heo | 43a98f0 | 2007-08-23 10:15:18 +0900 | [diff] [blame] | 1469 | { | 
| Jeff Garzik | 1855256 | 2007-10-03 15:15:40 -0400 | [diff] [blame] | 1470 | static const struct dmi_system_id sysids[] = { | 
| Tejun Heo | 43a98f0 | 2007-08-23 10:15:18 +0900 | [diff] [blame] | 1471 | { | 
|  | 1472 | /* Clevo M570U sets IOCFG bit 18 if the cdrom | 
|  | 1473 | * isn't used to boot the system which | 
|  | 1474 | * disables the channel. | 
|  | 1475 | */ | 
|  | 1476 | .ident = "M570U", | 
|  | 1477 | .matches = { | 
|  | 1478 | DMI_MATCH(DMI_SYS_VENDOR, "Clevo Co."), | 
|  | 1479 | DMI_MATCH(DMI_PRODUCT_NAME, "M570U"), | 
|  | 1480 | }, | 
|  | 1481 | }, | 
| Jeff Garzik | 7d05154 | 2007-09-01 06:48:52 -0400 | [diff] [blame] | 1482 |  | 
|  | 1483 | { }	/* terminate list */ | 
| Tejun Heo | 43a98f0 | 2007-08-23 10:15:18 +0900 | [diff] [blame] | 1484 | }; | 
| Tejun Heo | 2852bcf | 2009-01-02 12:04:48 +0900 | [diff] [blame] | 1485 | struct pci_dev *pdev = to_pci_dev(host->dev); | 
|  | 1486 | struct piix_host_priv *hpriv = host->private_data; | 
| Tejun Heo | 43a98f0 | 2007-08-23 10:15:18 +0900 | [diff] [blame] | 1487 |  | 
|  | 1488 | if (!dmi_check_system(sysids)) | 
|  | 1489 | return; | 
|  | 1490 |  | 
|  | 1491 | /* The datasheet says that bit 18 is NOOP but certain systems | 
|  | 1492 | * seem to use it to disable a channel.  Clear the bit on the | 
|  | 1493 | * affected systems. | 
|  | 1494 | */ | 
| Tejun Heo | 2852bcf | 2009-01-02 12:04:48 +0900 | [diff] [blame] | 1495 | if (hpriv->saved_iocfg & (1 << 18)) { | 
| Tejun Heo | 43a98f0 | 2007-08-23 10:15:18 +0900 | [diff] [blame] | 1496 | dev_printk(KERN_INFO, &pdev->dev, | 
|  | 1497 | "applying IOCFG bit18 quirk\n"); | 
| Tejun Heo | 2852bcf | 2009-01-02 12:04:48 +0900 | [diff] [blame] | 1498 | pci_write_config_dword(pdev, PIIX_IOCFG, | 
|  | 1499 | hpriv->saved_iocfg & ~(1 << 18)); | 
| Tejun Heo | 43a98f0 | 2007-08-23 10:15:18 +0900 | [diff] [blame] | 1500 | } | 
|  | 1501 | } | 
|  | 1502 |  | 
| Rafael J. Wysocki | 5f451fe | 2009-01-19 20:59:22 +0100 | [diff] [blame] | 1503 | static bool piix_broken_system_poweroff(struct pci_dev *pdev) | 
|  | 1504 | { | 
|  | 1505 | static const struct dmi_system_id broken_systems[] = { | 
|  | 1506 | { | 
|  | 1507 | .ident = "HP Compaq 2510p", | 
|  | 1508 | .matches = { | 
|  | 1509 | DMI_MATCH(DMI_SYS_VENDOR, "Hewlett-Packard"), | 
|  | 1510 | DMI_MATCH(DMI_PRODUCT_NAME, "HP Compaq 2510p"), | 
|  | 1511 | }, | 
|  | 1512 | /* PCI slot number of the controller */ | 
|  | 1513 | .driver_data = (void *)0x1FUL, | 
|  | 1514 | }, | 
| Ville Syrjala | 65e3164 | 2009-05-19 01:37:44 +0300 | [diff] [blame] | 1515 | { | 
|  | 1516 | .ident = "HP Compaq nc6000", | 
|  | 1517 | .matches = { | 
|  | 1518 | DMI_MATCH(DMI_SYS_VENDOR, "Hewlett-Packard"), | 
|  | 1519 | DMI_MATCH(DMI_PRODUCT_NAME, "HP Compaq nc6000"), | 
|  | 1520 | }, | 
|  | 1521 | /* PCI slot number of the controller */ | 
|  | 1522 | .driver_data = (void *)0x1FUL, | 
|  | 1523 | }, | 
| Rafael J. Wysocki | 5f451fe | 2009-01-19 20:59:22 +0100 | [diff] [blame] | 1524 |  | 
|  | 1525 | { }	/* terminate list */ | 
|  | 1526 | }; | 
|  | 1527 | const struct dmi_system_id *dmi = dmi_first_match(broken_systems); | 
|  | 1528 |  | 
|  | 1529 | if (dmi) { | 
|  | 1530 | unsigned long slot = (unsigned long)dmi->driver_data; | 
|  | 1531 | /* apply the quirk only to on-board controllers */ | 
|  | 1532 | return slot == PCI_SLOT(pdev->devfn); | 
|  | 1533 | } | 
|  | 1534 |  | 
|  | 1535 | return false; | 
|  | 1536 | } | 
|  | 1537 |  | 
| Alan Cox | c621b14 | 2005-12-08 19:22:28 +0000 | [diff] [blame] | 1538 | /** | 
| Linus Torvalds | 1da177e | 2005-04-16 15:20:36 -0700 | [diff] [blame] | 1539 | *	piix_init_one - Register PIIX ATA PCI device with kernel services | 
|  | 1540 | *	@pdev: PCI device to register | 
|  | 1541 | *	@ent: Entry in piix_pci_tbl matching with @pdev | 
|  | 1542 | * | 
|  | 1543 | *	Called from kernel PCI layer.  We probe for combined mode (sigh), | 
|  | 1544 | *	and then hand over control to libata, for it to do the rest. | 
|  | 1545 | * | 
|  | 1546 | *	LOCKING: | 
|  | 1547 | *	Inherited from PCI layer (may sleep). | 
|  | 1548 | * | 
|  | 1549 | *	RETURNS: | 
|  | 1550 | *	Zero on success, or -ERRNO value. | 
|  | 1551 | */ | 
|  | 1552 |  | 
| Adrian Bunk | bc5468f | 2008-01-30 22:02:02 +0200 | [diff] [blame] | 1553 | static int __devinit piix_init_one(struct pci_dev *pdev, | 
|  | 1554 | const struct pci_device_id *ent) | 
| Linus Torvalds | 1da177e | 2005-04-16 15:20:36 -0700 | [diff] [blame] | 1555 | { | 
|  | 1556 | static int printed_version; | 
| Tejun Heo | 24dc5f3 | 2007-01-20 16:00:28 +0900 | [diff] [blame] | 1557 | struct device *dev = &pdev->dev; | 
| Tejun Heo | d33f58b | 2006-03-01 01:25:39 +0900 | [diff] [blame] | 1558 | struct ata_port_info port_info[2]; | 
| Tejun Heo | 1626aeb | 2007-05-04 12:43:58 +0200 | [diff] [blame] | 1559 | const struct ata_port_info *ppi[] = { &port_info[0], &port_info[1] }; | 
| Tejun Heo | a97c4006 | 2010-09-01 17:50:08 +0200 | [diff] [blame] | 1560 | struct scsi_host_template *sht = &piix_sht; | 
| Jeff Garzik | cca3974 | 2006-08-24 03:19:22 -0400 | [diff] [blame] | 1561 | unsigned long port_flags; | 
| Tejun Heo | 8b09f0d | 2008-01-18 18:36:29 +0900 | [diff] [blame] | 1562 | struct ata_host *host; | 
|  | 1563 | struct piix_host_priv *hpriv; | 
|  | 1564 | int rc; | 
| Linus Torvalds | 1da177e | 2005-04-16 15:20:36 -0700 | [diff] [blame] | 1565 |  | 
|  | 1566 | if (!printed_version++) | 
| Jeff Garzik | 6248e64 | 2005-10-30 06:42:18 -0500 | [diff] [blame] | 1567 | dev_printk(KERN_DEBUG, &pdev->dev, | 
|  | 1568 | "version " DRV_VERSION "\n"); | 
| Linus Torvalds | 1da177e | 2005-04-16 15:20:36 -0700 | [diff] [blame] | 1569 |  | 
| Alan Cox | 347979a | 2009-05-06 17:10:08 +0100 | [diff] [blame] | 1570 | /* no hotplugging support for later devices (FIXME) */ | 
|  | 1571 | if (!in_module_init && ent->driver_data >= ich5_sata) | 
| Linus Torvalds | 1da177e | 2005-04-16 15:20:36 -0700 | [diff] [blame] | 1572 | return -ENODEV; | 
|  | 1573 |  | 
| Rafael J. Wysocki | 5f451fe | 2009-01-19 20:59:22 +0100 | [diff] [blame] | 1574 | if (piix_broken_system_poweroff(pdev)) { | 
|  | 1575 | piix_port_info[ent->driver_data].flags |= | 
|  | 1576 | ATA_FLAG_NO_POWEROFF_SPINDOWN | | 
|  | 1577 | ATA_FLAG_NO_HIBERNATE_SPINDOWN; | 
|  | 1578 | dev_info(&pdev->dev, "quirky BIOS, skipping spindown " | 
|  | 1579 | "on poweroff and hibernation\n"); | 
|  | 1580 | } | 
|  | 1581 |  | 
| Tejun Heo | 8b09f0d | 2008-01-18 18:36:29 +0900 | [diff] [blame] | 1582 | port_info[0] = piix_port_info[ent->driver_data]; | 
|  | 1583 | port_info[1] = piix_port_info[ent->driver_data]; | 
|  | 1584 |  | 
|  | 1585 | port_flags = port_info[0].flags; | 
|  | 1586 |  | 
|  | 1587 | /* enable device and prepare host */ | 
|  | 1588 | rc = pcim_enable_device(pdev); | 
|  | 1589 | if (rc) | 
|  | 1590 | return rc; | 
|  | 1591 |  | 
| Tejun Heo | 2852bcf | 2009-01-02 12:04:48 +0900 | [diff] [blame] | 1592 | hpriv = devm_kzalloc(dev, sizeof(*hpriv), GFP_KERNEL); | 
|  | 1593 | if (!hpriv) | 
|  | 1594 | return -ENOMEM; | 
|  | 1595 |  | 
|  | 1596 | /* Save IOCFG, this will be used for cable detection, quirk | 
|  | 1597 | * detection and restoration on detach.  This is necessary | 
|  | 1598 | * because some ACPI implementations mess up cable related | 
|  | 1599 | * bits on _STM.  Reported on kernel bz#11879. | 
|  | 1600 | */ | 
|  | 1601 | pci_read_config_dword(pdev, PIIX_IOCFG, &hpriv->saved_iocfg); | 
|  | 1602 |  | 
| Tejun Heo | 5016d7d | 2008-03-26 15:46:58 +0900 | [diff] [blame] | 1603 | /* ICH6R may be driven by either ata_piix or ahci driver | 
|  | 1604 | * regardless of BIOS configuration.  Make sure AHCI mode is | 
|  | 1605 | * off. | 
|  | 1606 | */ | 
|  | 1607 | if (pdev->vendor == PCI_VENDOR_ID_INTEL && pdev->device == 0x2652) { | 
| Stephen Hemminger | da3ceb2 | 2008-09-08 09:31:39 -0700 | [diff] [blame] | 1608 | rc = piix_disable_ahci(pdev); | 
| Tejun Heo | 5016d7d | 2008-03-26 15:46:58 +0900 | [diff] [blame] | 1609 | if (rc) | 
|  | 1610 | return rc; | 
|  | 1611 | } | 
|  | 1612 |  | 
| Tejun Heo | 8b09f0d | 2008-01-18 18:36:29 +0900 | [diff] [blame] | 1613 | /* SATA map init can change port_info, do it before prepping host */ | 
| Tejun Heo | 8b09f0d | 2008-01-18 18:36:29 +0900 | [diff] [blame] | 1614 | if (port_flags & ATA_FLAG_SATA) | 
|  | 1615 | hpriv->map = piix_init_sata_map(pdev, port_info, | 
|  | 1616 | piix_map_db_table[ent->driver_data]); | 
| Linus Torvalds | 1da177e | 2005-04-16 15:20:36 -0700 | [diff] [blame] | 1617 |  | 
| Tejun Heo | 1c5afdf | 2010-05-19 22:10:22 +0200 | [diff] [blame] | 1618 | rc = ata_pci_bmdma_prepare_host(pdev, ppi, &host); | 
| Tejun Heo | 8b09f0d | 2008-01-18 18:36:29 +0900 | [diff] [blame] | 1619 | if (rc) | 
|  | 1620 | return rc; | 
|  | 1621 | host->private_data = hpriv; | 
| Tejun Heo | ff0fc14 | 2005-12-18 17:17:07 +0900 | [diff] [blame] | 1622 |  | 
| Tejun Heo | 8b09f0d | 2008-01-18 18:36:29 +0900 | [diff] [blame] | 1623 | /* initialize controller */ | 
| Tejun Heo | c729072 | 2008-01-18 18:36:30 +0900 | [diff] [blame] | 1624 | if (port_flags & ATA_FLAG_SATA) { | 
| Tejun Heo | 8b09f0d | 2008-01-18 18:36:29 +0900 | [diff] [blame] | 1625 | piix_init_pcs(host, piix_map_db_table[ent->driver_data]); | 
| Tejun Heo | be77e43 | 2008-07-31 17:02:44 +0900 | [diff] [blame] | 1626 | rc = piix_init_sidpr(host); | 
|  | 1627 | if (rc) | 
|  | 1628 | return rc; | 
| Tejun Heo | a97c4006 | 2010-09-01 17:50:08 +0200 | [diff] [blame] | 1629 | if (host->ports[0]->ops == &piix_sidpr_sata_ops) | 
|  | 1630 | sht = &piix_sidpr_sht; | 
| Tejun Heo | c729072 | 2008-01-18 18:36:30 +0900 | [diff] [blame] | 1631 | } | 
| Linus Torvalds | 1da177e | 2005-04-16 15:20:36 -0700 | [diff] [blame] | 1632 |  | 
| Tejun Heo | 43a98f0 | 2007-08-23 10:15:18 +0900 | [diff] [blame] | 1633 | /* apply IOCFG bit18 quirk */ | 
| Tejun Heo | 2852bcf | 2009-01-02 12:04:48 +0900 | [diff] [blame] | 1634 | piix_iocfg_bit18_quirk(host); | 
| Tejun Heo | 43a98f0 | 2007-08-23 10:15:18 +0900 | [diff] [blame] | 1635 |  | 
| Linus Torvalds | 1da177e | 2005-04-16 15:20:36 -0700 | [diff] [blame] | 1636 | /* On ICH5, some BIOSen disable the interrupt using the | 
|  | 1637 | * PCI_COMMAND_INTX_DISABLE bit added in PCI 2.3. | 
|  | 1638 | * On ICH6, this bit has the same effect, but only when | 
|  | 1639 | * MSI is disabled (and it is disabled, as we don't use | 
|  | 1640 | * message-signalled interrupts currently). | 
|  | 1641 | */ | 
| Jeff Garzik | cca3974 | 2006-08-24 03:19:22 -0400 | [diff] [blame] | 1642 | if (port_flags & PIIX_FLAG_CHECKINTR) | 
| Brett M Russ | a04ce0f | 2005-08-15 15:23:41 -0400 | [diff] [blame] | 1643 | pci_intx(pdev, 1); | 
| Linus Torvalds | 1da177e | 2005-04-16 15:20:36 -0700 | [diff] [blame] | 1644 |  | 
| Alan Cox | c621b14 | 2005-12-08 19:22:28 +0000 | [diff] [blame] | 1645 | if (piix_check_450nx_errata(pdev)) { | 
|  | 1646 | /* This writes into the master table but it does not | 
|  | 1647 | really matter for this errata as we will apply it to | 
|  | 1648 | all the PIIX devices on the board */ | 
| Tejun Heo | 8b09f0d | 2008-01-18 18:36:29 +0900 | [diff] [blame] | 1649 | host->ports[0]->mwdma_mask = 0; | 
|  | 1650 | host->ports[0]->udma_mask = 0; | 
|  | 1651 | host->ports[1]->mwdma_mask = 0; | 
|  | 1652 | host->ports[1]->udma_mask = 0; | 
| Alan Cox | c621b14 | 2005-12-08 19:22:28 +0000 | [diff] [blame] | 1653 | } | 
| Arjan van de Ven | 517d3cc | 2009-05-13 15:02:42 +0100 | [diff] [blame] | 1654 | host->flags |= ATA_HOST_PARALLEL_SCAN; | 
| Tejun Heo | 8b09f0d | 2008-01-18 18:36:29 +0900 | [diff] [blame] | 1655 |  | 
|  | 1656 | pci_set_master(pdev); | 
| Tejun Heo | a97c4006 | 2010-09-01 17:50:08 +0200 | [diff] [blame] | 1657 | return ata_pci_sff_activate_host(host, ata_bmdma_interrupt, sht); | 
| Linus Torvalds | 1da177e | 2005-04-16 15:20:36 -0700 | [diff] [blame] | 1658 | } | 
|  | 1659 |  | 
| Tejun Heo | 2852bcf | 2009-01-02 12:04:48 +0900 | [diff] [blame] | 1660 | static void piix_remove_one(struct pci_dev *pdev) | 
|  | 1661 | { | 
|  | 1662 | struct ata_host *host = dev_get_drvdata(&pdev->dev); | 
|  | 1663 | struct piix_host_priv *hpriv = host->private_data; | 
|  | 1664 |  | 
|  | 1665 | pci_write_config_dword(pdev, PIIX_IOCFG, hpriv->saved_iocfg); | 
|  | 1666 |  | 
|  | 1667 | ata_pci_remove_one(pdev); | 
|  | 1668 | } | 
|  | 1669 |  | 
| Linus Torvalds | 1da177e | 2005-04-16 15:20:36 -0700 | [diff] [blame] | 1670 | static int __init piix_init(void) | 
|  | 1671 | { | 
|  | 1672 | int rc; | 
|  | 1673 |  | 
| Pavel Roskin | b788719 | 2006-08-10 18:13:18 +0900 | [diff] [blame] | 1674 | DPRINTK("pci_register_driver\n"); | 
|  | 1675 | rc = pci_register_driver(&piix_pci_driver); | 
| Linus Torvalds | 1da177e | 2005-04-16 15:20:36 -0700 | [diff] [blame] | 1676 | if (rc) | 
|  | 1677 | return rc; | 
|  | 1678 |  | 
|  | 1679 | in_module_init = 0; | 
|  | 1680 |  | 
|  | 1681 | DPRINTK("done\n"); | 
|  | 1682 | return 0; | 
|  | 1683 | } | 
|  | 1684 |  | 
| Linus Torvalds | 1da177e | 2005-04-16 15:20:36 -0700 | [diff] [blame] | 1685 | static void __exit piix_exit(void) | 
|  | 1686 | { | 
|  | 1687 | pci_unregister_driver(&piix_pci_driver); | 
|  | 1688 | } | 
|  | 1689 |  | 
|  | 1690 | module_init(piix_init); | 
|  | 1691 | module_exit(piix_exit); |