blob: 6ca4bc0fcae322c849a42953567a54adbc6f8785 [file] [log] [blame]
Linus Torvalds1da177e2005-04-16 15:20:36 -07001/*
2 * ahci.c - AHCI SATA support
3 *
Jeff Garzikaf36d7f2005-08-28 20:18:39 -04004 * Maintained by: Jeff Garzik <jgarzik@pobox.com>
5 * Please ALWAYS copy linux-ide@vger.kernel.org
6 * on emails.
Linus Torvalds1da177e2005-04-16 15:20:36 -07007 *
Jeff Garzikaf36d7f2005-08-28 20:18:39 -04008 * Copyright 2004-2005 Red Hat, Inc.
Linus Torvalds1da177e2005-04-16 15:20:36 -07009 *
Linus Torvalds1da177e2005-04-16 15:20:36 -070010 *
Jeff Garzikaf36d7f2005-08-28 20:18:39 -040011 * This program is free software; you can redistribute it and/or modify
12 * it under the terms of the GNU General Public License as published by
13 * the Free Software Foundation; either version 2, or (at your option)
14 * any later version.
15 *
16 * This program is distributed in the hope that it will be useful,
17 * but WITHOUT ANY WARRANTY; without even the implied warranty of
18 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
19 * GNU General Public License for more details.
20 *
21 * You should have received a copy of the GNU General Public License
22 * along with this program; see the file COPYING. If not, write to
23 * the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA.
24 *
25 *
26 * libata documentation is available via 'make {ps|pdf}docs',
27 * as Documentation/DocBook/libata.*
28 *
29 * AHCI hardware documentation:
Linus Torvalds1da177e2005-04-16 15:20:36 -070030 * http://www.intel.com/technology/serialata/pdf/rev1_0.pdf
Jeff Garzikaf36d7f2005-08-28 20:18:39 -040031 * http://www.intel.com/technology/serialata/pdf/rev1_1.pdf
Linus Torvalds1da177e2005-04-16 15:20:36 -070032 *
33 */
34
35#include <linux/kernel.h>
36#include <linux/module.h>
37#include <linux/pci.h>
38#include <linux/init.h>
39#include <linux/blkdev.h>
40#include <linux/delay.h>
41#include <linux/interrupt.h>
domen@coderock.org87507cf2005-04-08 09:53:06 +020042#include <linux/dma-mapping.h>
Jeff Garzika9524a72005-10-30 14:39:11 -050043#include <linux/device.h>
Tejun Heoedc93052007-10-25 14:59:16 +090044#include <linux/dmi.h>
Linus Torvalds1da177e2005-04-16 15:20:36 -070045#include <scsi/scsi_host.h>
Jeff Garzik193515d2005-11-07 00:59:37 -050046#include <scsi/scsi_cmnd.h>
Linus Torvalds1da177e2005-04-16 15:20:36 -070047#include <linux/libata.h>
Linus Torvalds1da177e2005-04-16 15:20:36 -070048
49#define DRV_NAME "ahci"
Tejun Heo7d50b602007-09-23 13:19:54 +090050#define DRV_VERSION "3.0"
Linus Torvalds1da177e2005-04-16 15:20:36 -070051
David Milburn87943ac2008-10-13 14:38:36 -050052/* Enclosure Management Control */
53#define EM_CTRL_MSG_TYPE 0x000f0000
54
55/* Enclosure Management LED Message Type */
56#define EM_MSG_LED_HBA_PORT 0x0000000f
57#define EM_MSG_LED_PMP_SLOT 0x0000ff00
58#define EM_MSG_LED_VALUE 0xffff0000
59#define EM_MSG_LED_VALUE_ACTIVITY 0x00070000
60#define EM_MSG_LED_VALUE_OFF 0xfff80000
61#define EM_MSG_LED_VALUE_ON 0x00010000
62
Tejun Heoa22e6442008-03-10 10:25:25 +090063static int ahci_skip_host_reset;
Arjan van de Venf3d7f232009-01-26 02:05:44 -080064static int ahci_ignore_sss;
65
Tejun Heoa22e6442008-03-10 10:25:25 +090066module_param_named(skip_host_reset, ahci_skip_host_reset, int, 0444);
67MODULE_PARM_DESC(skip_host_reset, "skip global host reset (0=don't skip, 1=skip)");
68
Arjan van de Venf3d7f232009-01-26 02:05:44 -080069module_param_named(ignore_sss, ahci_ignore_sss, int, 0444);
70MODULE_PARM_DESC(ignore_sss, "Ignore staggered spinup flag (0=don't ignore, 1=ignore)");
71
Kristen Carlson Accardi31556592007-10-25 01:33:26 -040072static int ahci_enable_alpm(struct ata_port *ap,
73 enum link_pm policy);
74static void ahci_disable_alpm(struct ata_port *ap);
Kristen Carlson Accardi18f7ba42008-06-03 10:33:55 -070075static ssize_t ahci_led_show(struct ata_port *ap, char *buf);
76static ssize_t ahci_led_store(struct ata_port *ap, const char *buf,
77 size_t size);
78static ssize_t ahci_transmit_led_message(struct ata_port *ap, u32 state,
79 ssize_t size);
80#define MAX_SLOTS 8
David Milburn4c1e9aa2009-04-03 15:36:41 -050081#define MAX_RETRY 15
Linus Torvalds1da177e2005-04-16 15:20:36 -070082
83enum {
84 AHCI_PCI_BAR = 5,
Tejun Heo648a88b2006-11-09 15:08:40 +090085 AHCI_MAX_PORTS = 32,
Linus Torvalds1da177e2005-04-16 15:20:36 -070086 AHCI_MAX_SG = 168, /* hardware max is 64K */
87 AHCI_DMA_BOUNDARY = 0xffffffff,
Tejun Heo12fad3f2006-05-15 21:03:55 +090088 AHCI_MAX_CMDS = 32,
Tejun Heodd410ff2006-05-15 21:03:50 +090089 AHCI_CMD_SZ = 32,
Tejun Heo12fad3f2006-05-15 21:03:55 +090090 AHCI_CMD_SLOT_SZ = AHCI_MAX_CMDS * AHCI_CMD_SZ,
Linus Torvalds1da177e2005-04-16 15:20:36 -070091 AHCI_RX_FIS_SZ = 256,
Jeff Garzika0ea7322005-06-04 01:13:15 -040092 AHCI_CMD_TBL_CDB = 0x40,
Tejun Heodd410ff2006-05-15 21:03:50 +090093 AHCI_CMD_TBL_HDR_SZ = 0x80,
94 AHCI_CMD_TBL_SZ = AHCI_CMD_TBL_HDR_SZ + (AHCI_MAX_SG * 16),
95 AHCI_CMD_TBL_AR_SZ = AHCI_CMD_TBL_SZ * AHCI_MAX_CMDS,
96 AHCI_PORT_PRIV_DMA_SZ = AHCI_CMD_SLOT_SZ + AHCI_CMD_TBL_AR_SZ +
Linus Torvalds1da177e2005-04-16 15:20:36 -070097 AHCI_RX_FIS_SZ,
98 AHCI_IRQ_ON_SG = (1 << 31),
99 AHCI_CMD_ATAPI = (1 << 5),
100 AHCI_CMD_WRITE = (1 << 6),
Tejun Heo4b10e552006-03-12 11:25:27 +0900101 AHCI_CMD_PREFETCH = (1 << 7),
Tejun Heo22b49982006-01-23 21:38:44 +0900102 AHCI_CMD_RESET = (1 << 8),
103 AHCI_CMD_CLR_BUSY = (1 << 10),
Linus Torvalds1da177e2005-04-16 15:20:36 -0700104
105 RX_FIS_D2H_REG = 0x40, /* offset of D2H Register FIS data */
Tejun Heo0291f952007-01-25 19:16:28 +0900106 RX_FIS_SDB = 0x58, /* offset of SDB FIS data */
Tejun Heo78cd52d2006-05-15 20:58:29 +0900107 RX_FIS_UNK = 0x60, /* offset of Unknown FIS data */
Linus Torvalds1da177e2005-04-16 15:20:36 -0700108
109 board_ahci = 0,
Tejun Heo7a234af2007-09-03 12:44:57 +0900110 board_ahci_vt8251 = 1,
111 board_ahci_ign_iferr = 2,
112 board_ahci_sb600 = 3,
113 board_ahci_mv = 4,
Shane Huange427fe02008-12-30 10:53:41 +0800114 board_ahci_sb700 = 5, /* for SB700 and SB800 */
Tejun Heoe297d992008-06-10 00:13:04 +0900115 board_ahci_mcp65 = 6,
Tejun Heo9a3b1032008-06-18 20:56:58 -0400116 board_ahci_nopmp = 7,
Linus Torvalds1da177e2005-04-16 15:20:36 -0700117
118 /* global controller registers */
119 HOST_CAP = 0x00, /* host capabilities */
120 HOST_CTL = 0x04, /* global host control */
121 HOST_IRQ_STAT = 0x08, /* interrupt status */
122 HOST_PORTS_IMPL = 0x0c, /* bitmap of implemented ports */
123 HOST_VERSION = 0x10, /* AHCI spec. version compliancy */
Kristen Carlson Accardi18f7ba42008-06-03 10:33:55 -0700124 HOST_EM_LOC = 0x1c, /* Enclosure Management location */
125 HOST_EM_CTL = 0x20, /* Enclosure Management Control */
Linus Torvalds1da177e2005-04-16 15:20:36 -0700126
127 /* HOST_CTL bits */
128 HOST_RESET = (1 << 0), /* reset controller; self-clear */
129 HOST_IRQ_EN = (1 << 1), /* global IRQ enable */
130 HOST_AHCI_EN = (1 << 31), /* AHCI enabled */
131
132 /* HOST_CAP bits */
Kristen Carlson Accardi18f7ba42008-06-03 10:33:55 -0700133 HOST_CAP_EMS = (1 << 6), /* Enclosure Management support */
Tejun Heo0be0aa92006-07-26 15:59:26 +0900134 HOST_CAP_SSC = (1 << 14), /* Slumber capable */
Tejun Heo7d50b602007-09-23 13:19:54 +0900135 HOST_CAP_PMP = (1 << 17), /* Port Multiplier support */
Tejun Heo22b49982006-01-23 21:38:44 +0900136 HOST_CAP_CLO = (1 << 24), /* Command List Override support */
Kristen Carlson Accardi31556592007-10-25 01:33:26 -0400137 HOST_CAP_ALPM = (1 << 26), /* Aggressive Link PM support */
Tejun Heo0be0aa92006-07-26 15:59:26 +0900138 HOST_CAP_SSS = (1 << 27), /* Staggered Spin-up */
Tejun Heo203ef6c2007-07-16 14:29:40 +0900139 HOST_CAP_SNTF = (1 << 29), /* SNotification register */
Tejun Heo979db802006-05-15 21:03:52 +0900140 HOST_CAP_NCQ = (1 << 30), /* Native Command Queueing */
Tejun Heodd410ff2006-05-15 21:03:50 +0900141 HOST_CAP_64 = (1 << 31), /* PCI DAC (64-bit DMA) support */
Linus Torvalds1da177e2005-04-16 15:20:36 -0700142
143 /* registers for each SATA port */
144 PORT_LST_ADDR = 0x00, /* command list DMA addr */
145 PORT_LST_ADDR_HI = 0x04, /* command list DMA addr hi */
146 PORT_FIS_ADDR = 0x08, /* FIS rx buf addr */
147 PORT_FIS_ADDR_HI = 0x0c, /* FIS rx buf addr hi */
148 PORT_IRQ_STAT = 0x10, /* interrupt status */
149 PORT_IRQ_MASK = 0x14, /* interrupt enable/disable mask */
150 PORT_CMD = 0x18, /* port command */
151 PORT_TFDATA = 0x20, /* taskfile data */
152 PORT_SIG = 0x24, /* device TF signature */
153 PORT_CMD_ISSUE = 0x38, /* command issue */
Linus Torvalds1da177e2005-04-16 15:20:36 -0700154 PORT_SCR_STAT = 0x28, /* SATA phy register: SStatus */
155 PORT_SCR_CTL = 0x2c, /* SATA phy register: SControl */
156 PORT_SCR_ERR = 0x30, /* SATA phy register: SError */
157 PORT_SCR_ACT = 0x34, /* SATA phy register: SActive */
Tejun Heo203ef6c2007-07-16 14:29:40 +0900158 PORT_SCR_NTF = 0x3c, /* SATA phy register: SNotification */
Linus Torvalds1da177e2005-04-16 15:20:36 -0700159
160 /* PORT_IRQ_{STAT,MASK} bits */
161 PORT_IRQ_COLD_PRES = (1 << 31), /* cold presence detect */
162 PORT_IRQ_TF_ERR = (1 << 30), /* task file error */
163 PORT_IRQ_HBUS_ERR = (1 << 29), /* host bus fatal error */
164 PORT_IRQ_HBUS_DATA_ERR = (1 << 28), /* host bus data error */
165 PORT_IRQ_IF_ERR = (1 << 27), /* interface fatal error */
166 PORT_IRQ_IF_NONFATAL = (1 << 26), /* interface non-fatal error */
167 PORT_IRQ_OVERFLOW = (1 << 24), /* xfer exhausted available S/G */
168 PORT_IRQ_BAD_PMP = (1 << 23), /* incorrect port multiplier */
169
170 PORT_IRQ_PHYRDY = (1 << 22), /* PhyRdy changed */
171 PORT_IRQ_DEV_ILCK = (1 << 7), /* device interlock */
172 PORT_IRQ_CONNECT = (1 << 6), /* port connect change status */
173 PORT_IRQ_SG_DONE = (1 << 5), /* descriptor processed */
174 PORT_IRQ_UNK_FIS = (1 << 4), /* unknown FIS rx'd */
175 PORT_IRQ_SDB_FIS = (1 << 3), /* Set Device Bits FIS rx'd */
176 PORT_IRQ_DMAS_FIS = (1 << 2), /* DMA Setup FIS rx'd */
177 PORT_IRQ_PIOS_FIS = (1 << 1), /* PIO Setup FIS rx'd */
178 PORT_IRQ_D2H_REG_FIS = (1 << 0), /* D2H Register FIS rx'd */
179
Tejun Heo78cd52d2006-05-15 20:58:29 +0900180 PORT_IRQ_FREEZE = PORT_IRQ_HBUS_ERR |
181 PORT_IRQ_IF_ERR |
182 PORT_IRQ_CONNECT |
Tejun Heo42969712006-05-31 18:28:18 +0900183 PORT_IRQ_PHYRDY |
Tejun Heo7d50b602007-09-23 13:19:54 +0900184 PORT_IRQ_UNK_FIS |
185 PORT_IRQ_BAD_PMP,
Tejun Heo78cd52d2006-05-15 20:58:29 +0900186 PORT_IRQ_ERROR = PORT_IRQ_FREEZE |
187 PORT_IRQ_TF_ERR |
188 PORT_IRQ_HBUS_DATA_ERR,
189 DEF_PORT_IRQ = PORT_IRQ_ERROR | PORT_IRQ_SG_DONE |
190 PORT_IRQ_SDB_FIS | PORT_IRQ_DMAS_FIS |
191 PORT_IRQ_PIOS_FIS | PORT_IRQ_D2H_REG_FIS,
Linus Torvalds1da177e2005-04-16 15:20:36 -0700192
193 /* PORT_CMD bits */
Kristen Carlson Accardi31556592007-10-25 01:33:26 -0400194 PORT_CMD_ASP = (1 << 27), /* Aggressive Slumber/Partial */
195 PORT_CMD_ALPE = (1 << 26), /* Aggressive Link PM enable */
Jeff Garzik02eaa662005-11-12 01:32:19 -0500196 PORT_CMD_ATAPI = (1 << 24), /* Device is ATAPI */
Tejun Heo7d50b602007-09-23 13:19:54 +0900197 PORT_CMD_PMP = (1 << 17), /* PMP attached */
Linus Torvalds1da177e2005-04-16 15:20:36 -0700198 PORT_CMD_LIST_ON = (1 << 15), /* cmd list DMA engine running */
199 PORT_CMD_FIS_ON = (1 << 14), /* FIS DMA engine running */
200 PORT_CMD_FIS_RX = (1 << 4), /* Enable FIS receive DMA engine */
Tejun Heo22b49982006-01-23 21:38:44 +0900201 PORT_CMD_CLO = (1 << 3), /* Command list override */
Linus Torvalds1da177e2005-04-16 15:20:36 -0700202 PORT_CMD_POWER_ON = (1 << 2), /* Power up device */
203 PORT_CMD_SPIN_UP = (1 << 1), /* Spin up device */
204 PORT_CMD_START = (1 << 0), /* Enable port DMA engine */
205
Tejun Heo0be0aa92006-07-26 15:59:26 +0900206 PORT_CMD_ICC_MASK = (0xf << 28), /* i/f ICC state mask */
Linus Torvalds1da177e2005-04-16 15:20:36 -0700207 PORT_CMD_ICC_ACTIVE = (0x1 << 28), /* Put i/f in active state */
208 PORT_CMD_ICC_PARTIAL = (0x2 << 28), /* Put i/f in partial state */
209 PORT_CMD_ICC_SLUMBER = (0x6 << 28), /* Put i/f in slumber state */
Jeff Garzik4b0060f2005-06-04 00:50:22 -0400210
Tejun Heo417a1a62007-09-23 13:19:55 +0900211 /* hpriv->flags bits */
212 AHCI_HFLAG_NO_NCQ = (1 << 0),
213 AHCI_HFLAG_IGN_IRQ_IF_ERR = (1 << 1), /* ignore IRQ_IF_ERR */
214 AHCI_HFLAG_IGN_SERR_INTERNAL = (1 << 2), /* ignore SERR_INTERNAL */
215 AHCI_HFLAG_32BIT_ONLY = (1 << 3), /* force 32bit */
216 AHCI_HFLAG_MV_PATA = (1 << 4), /* PATA port */
217 AHCI_HFLAG_NO_MSI = (1 << 5), /* no PCI MSI */
Tejun Heo6949b912007-09-23 13:19:55 +0900218 AHCI_HFLAG_NO_PMP = (1 << 6), /* no PMP */
Kristen Carlson Accardi31556592007-10-25 01:33:26 -0400219 AHCI_HFLAG_NO_HOTPLUG = (1 << 7), /* ignore PxSERR.DIAG.N */
Jeff Garzika8785392008-02-28 15:43:48 -0500220 AHCI_HFLAG_SECT255 = (1 << 8), /* max 255 sectors */
Tejun Heoe297d992008-06-10 00:13:04 +0900221 AHCI_HFLAG_YES_NCQ = (1 << 9), /* force NCQ cap on */
Tejun Heo417a1a62007-09-23 13:19:55 +0900222
Bastiaan Jacquesbf2af2a2006-04-17 14:17:59 +0200223 /* ap->flags bits */
Tejun Heo1188c0d2007-04-23 02:41:05 +0900224
225 AHCI_FLAG_COMMON = ATA_FLAG_SATA | ATA_FLAG_NO_LEGACY |
226 ATA_FLAG_MMIO | ATA_FLAG_PIO_DMA |
Kristen Carlson Accardi31556592007-10-25 01:33:26 -0400227 ATA_FLAG_ACPI_SATA | ATA_FLAG_AN |
228 ATA_FLAG_IPM,
Tejun Heoc4f77922007-12-06 15:09:43 +0900229
230 ICH_MAP = 0x90, /* ICH MAP register */
Kristen Carlson Accardi18f7ba42008-06-03 10:33:55 -0700231
232 /* em_ctl bits */
233 EM_CTL_RST = (1 << 9), /* Reset */
234 EM_CTL_TM = (1 << 8), /* Transmit Message */
235 EM_CTL_ALHD = (1 << 26), /* Activity LED */
Linus Torvalds1da177e2005-04-16 15:20:36 -0700236};
237
238struct ahci_cmd_hdr {
Al Viro4ca4e432007-12-30 09:32:22 +0000239 __le32 opts;
240 __le32 status;
241 __le32 tbl_addr;
242 __le32 tbl_addr_hi;
243 __le32 reserved[4];
Linus Torvalds1da177e2005-04-16 15:20:36 -0700244};
245
246struct ahci_sg {
Al Viro4ca4e432007-12-30 09:32:22 +0000247 __le32 addr;
248 __le32 addr_hi;
249 __le32 reserved;
250 __le32 flags_size;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700251};
252
Kristen Carlson Accardi18f7ba42008-06-03 10:33:55 -0700253struct ahci_em_priv {
254 enum sw_activity blink_policy;
255 struct timer_list timer;
256 unsigned long saved_activity;
257 unsigned long activity;
258 unsigned long led_state;
259};
260
Linus Torvalds1da177e2005-04-16 15:20:36 -0700261struct ahci_host_priv {
Tejun Heo417a1a62007-09-23 13:19:55 +0900262 unsigned int flags; /* AHCI_HFLAG_* */
Tejun Heod447df12007-03-18 22:15:33 +0900263 u32 cap; /* cap to use */
264 u32 port_map; /* port map to use */
265 u32 saved_cap; /* saved initial cap */
266 u32 saved_port_map; /* saved initial port_map */
Kristen Carlson Accardi18f7ba42008-06-03 10:33:55 -0700267 u32 em_loc; /* enclosure management location */
Linus Torvalds1da177e2005-04-16 15:20:36 -0700268};
269
270struct ahci_port_priv {
Tejun Heo7d50b602007-09-23 13:19:54 +0900271 struct ata_link *active_link;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700272 struct ahci_cmd_hdr *cmd_slot;
273 dma_addr_t cmd_slot_dma;
274 void *cmd_tbl;
275 dma_addr_t cmd_tbl_dma;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700276 void *rx_fis;
277 dma_addr_t rx_fis_dma;
Tejun Heo0291f952007-01-25 19:16:28 +0900278 /* for NCQ spurious interrupt analysis */
Tejun Heo0291f952007-01-25 19:16:28 +0900279 unsigned int ncq_saw_d2h:1;
280 unsigned int ncq_saw_dmas:1;
Tejun Heoafb2d552007-02-27 13:24:19 +0900281 unsigned int ncq_saw_sdb:1;
Kristen Carlson Accardia7384922007-08-09 14:23:41 -0700282 u32 intr_mask; /* interrupts to enable */
Kristen Carlson Accardi18f7ba42008-06-03 10:33:55 -0700283 struct ahci_em_priv em_priv[MAX_SLOTS];/* enclosure management info
284 * per PM slot */
Linus Torvalds1da177e2005-04-16 15:20:36 -0700285};
286
Tejun Heo82ef04f2008-07-31 17:02:40 +0900287static int ahci_scr_read(struct ata_link *link, unsigned int sc_reg, u32 *val);
288static int ahci_scr_write(struct ata_link *link, unsigned int sc_reg, u32 val);
Jeff Garzik2dcb4072007-10-19 06:42:56 -0400289static int ahci_init_one(struct pci_dev *pdev, const struct pci_device_id *ent);
Tejun Heo9a3d9eb2006-01-23 13:09:36 +0900290static unsigned int ahci_qc_issue(struct ata_queued_cmd *qc);
Tejun Heo4c9bf4e2008-04-07 22:47:20 +0900291static bool ahci_qc_fill_rtf(struct ata_queued_cmd *qc);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700292static int ahci_port_start(struct ata_port *ap);
293static void ahci_port_stop(struct ata_port *ap);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700294static void ahci_qc_prep(struct ata_queued_cmd *qc);
Tejun Heo78cd52d2006-05-15 20:58:29 +0900295static void ahci_freeze(struct ata_port *ap);
296static void ahci_thaw(struct ata_port *ap);
Tejun Heo7d50b602007-09-23 13:19:54 +0900297static void ahci_pmp_attach(struct ata_port *ap);
298static void ahci_pmp_detach(struct ata_port *ap);
Tejun Heoa1efdab2008-03-25 12:22:50 +0900299static int ahci_softreset(struct ata_link *link, unsigned int *class,
300 unsigned long deadline);
Shane Huangbd172432008-06-10 15:52:04 +0800301static int ahci_sb600_softreset(struct ata_link *link, unsigned int *class,
302 unsigned long deadline);
Tejun Heoa1efdab2008-03-25 12:22:50 +0900303static int ahci_hardreset(struct ata_link *link, unsigned int *class,
304 unsigned long deadline);
305static int ahci_vt8251_hardreset(struct ata_link *link, unsigned int *class,
306 unsigned long deadline);
307static int ahci_p5wdh_hardreset(struct ata_link *link, unsigned int *class,
308 unsigned long deadline);
309static void ahci_postreset(struct ata_link *link, unsigned int *class);
Tejun Heo78cd52d2006-05-15 20:58:29 +0900310static void ahci_error_handler(struct ata_port *ap);
311static void ahci_post_internal_cmd(struct ata_queued_cmd *qc);
Jeff Garzikdf69c9c2007-05-26 20:46:51 -0400312static int ahci_port_resume(struct ata_port *ap);
Jeff Garzika8785392008-02-28 15:43:48 -0500313static void ahci_dev_config(struct ata_device *dev);
Jeff Garzikdab632e2007-05-28 08:33:01 -0400314static unsigned int ahci_fill_sg(struct ata_queued_cmd *qc, void *cmd_tbl);
315static void ahci_fill_cmd_slot(struct ahci_port_priv *pp, unsigned int tag,
316 u32 opts);
Tejun Heo438ac6d2007-03-02 17:31:26 +0900317#ifdef CONFIG_PM
Tejun Heoc1332872006-07-26 15:59:26 +0900318static int ahci_port_suspend(struct ata_port *ap, pm_message_t mesg);
Tejun Heoc1332872006-07-26 15:59:26 +0900319static int ahci_pci_device_suspend(struct pci_dev *pdev, pm_message_t mesg);
320static int ahci_pci_device_resume(struct pci_dev *pdev);
Tejun Heo438ac6d2007-03-02 17:31:26 +0900321#endif
Kristen Carlson Accardi18f7ba42008-06-03 10:33:55 -0700322static ssize_t ahci_activity_show(struct ata_device *dev, char *buf);
323static ssize_t ahci_activity_store(struct ata_device *dev,
324 enum sw_activity val);
325static void ahci_init_sw_activity(struct ata_link *link);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700326
Tony Jonesee959b02008-02-22 00:13:36 +0100327static struct device_attribute *ahci_shost_attrs[] = {
328 &dev_attr_link_power_management_policy,
Kristen Carlson Accardi18f7ba42008-06-03 10:33:55 -0700329 &dev_attr_em_message_type,
330 &dev_attr_em_message,
331 NULL
332};
333
334static struct device_attribute *ahci_sdev_attrs[] = {
335 &dev_attr_sw_activity,
Elias Oltmanns45fabbb2008-09-21 11:54:08 +0200336 &dev_attr_unload_heads,
Kristen Carlson Accardi31556592007-10-25 01:33:26 -0400337 NULL
338};
339
Jeff Garzik193515d2005-11-07 00:59:37 -0500340static struct scsi_host_template ahci_sht = {
Tejun Heo68d1d072008-03-25 12:22:49 +0900341 ATA_NCQ_SHT(DRV_NAME),
Tejun Heo12fad3f2006-05-15 21:03:55 +0900342 .can_queue = AHCI_MAX_CMDS - 1,
Linus Torvalds1da177e2005-04-16 15:20:36 -0700343 .sg_tablesize = AHCI_MAX_SG,
Linus Torvalds1da177e2005-04-16 15:20:36 -0700344 .dma_boundary = AHCI_DMA_BOUNDARY,
Kristen Carlson Accardi31556592007-10-25 01:33:26 -0400345 .shost_attrs = ahci_shost_attrs,
Kristen Carlson Accardi18f7ba42008-06-03 10:33:55 -0700346 .sdev_attrs = ahci_sdev_attrs,
Linus Torvalds1da177e2005-04-16 15:20:36 -0700347};
348
Tejun Heo029cfd62008-03-25 12:22:49 +0900349static struct ata_port_operations ahci_ops = {
350 .inherits = &sata_pmp_port_ops,
351
Tejun Heo7d50b602007-09-23 13:19:54 +0900352 .qc_defer = sata_pmp_qc_defer_cmd_switch,
Linus Torvalds1da177e2005-04-16 15:20:36 -0700353 .qc_prep = ahci_qc_prep,
354 .qc_issue = ahci_qc_issue,
Tejun Heo4c9bf4e2008-04-07 22:47:20 +0900355 .qc_fill_rtf = ahci_qc_fill_rtf,
Linus Torvalds1da177e2005-04-16 15:20:36 -0700356
Tejun Heo78cd52d2006-05-15 20:58:29 +0900357 .freeze = ahci_freeze,
358 .thaw = ahci_thaw,
Tejun Heoa1efdab2008-03-25 12:22:50 +0900359 .softreset = ahci_softreset,
360 .hardreset = ahci_hardreset,
361 .postreset = ahci_postreset,
Tejun Heo071f44b2008-04-07 22:47:22 +0900362 .pmp_softreset = ahci_softreset,
Tejun Heo78cd52d2006-05-15 20:58:29 +0900363 .error_handler = ahci_error_handler,
364 .post_internal_cmd = ahci_post_internal_cmd,
Tejun Heo029cfd62008-03-25 12:22:49 +0900365 .dev_config = ahci_dev_config,
Tejun Heo78cd52d2006-05-15 20:58:29 +0900366
Tejun Heo029cfd62008-03-25 12:22:49 +0900367 .scr_read = ahci_scr_read,
368 .scr_write = ahci_scr_write,
Tejun Heo7d50b602007-09-23 13:19:54 +0900369 .pmp_attach = ahci_pmp_attach,
370 .pmp_detach = ahci_pmp_detach,
Tejun Heo7d50b602007-09-23 13:19:54 +0900371
Tejun Heo029cfd62008-03-25 12:22:49 +0900372 .enable_pm = ahci_enable_alpm,
373 .disable_pm = ahci_disable_alpm,
Kristen Carlson Accardi18f7ba42008-06-03 10:33:55 -0700374 .em_show = ahci_led_show,
375 .em_store = ahci_led_store,
376 .sw_activity_show = ahci_activity_show,
377 .sw_activity_store = ahci_activity_store,
Tejun Heo438ac6d2007-03-02 17:31:26 +0900378#ifdef CONFIG_PM
Tejun Heoc1332872006-07-26 15:59:26 +0900379 .port_suspend = ahci_port_suspend,
380 .port_resume = ahci_port_resume,
Tejun Heo438ac6d2007-03-02 17:31:26 +0900381#endif
Linus Torvalds1da177e2005-04-16 15:20:36 -0700382 .port_start = ahci_port_start,
383 .port_stop = ahci_port_stop,
Linus Torvalds1da177e2005-04-16 15:20:36 -0700384};
385
Tejun Heo029cfd62008-03-25 12:22:49 +0900386static struct ata_port_operations ahci_vt8251_ops = {
387 .inherits = &ahci_ops,
Tejun Heoa1efdab2008-03-25 12:22:50 +0900388 .hardreset = ahci_vt8251_hardreset,
Tejun Heoad616ff2006-11-01 18:00:24 +0900389};
390
Tejun Heo029cfd62008-03-25 12:22:49 +0900391static struct ata_port_operations ahci_p5wdh_ops = {
392 .inherits = &ahci_ops,
Tejun Heoa1efdab2008-03-25 12:22:50 +0900393 .hardreset = ahci_p5wdh_hardreset,
Tejun Heoedc93052007-10-25 14:59:16 +0900394};
395
Shane Huangbd172432008-06-10 15:52:04 +0800396static struct ata_port_operations ahci_sb600_ops = {
397 .inherits = &ahci_ops,
398 .softreset = ahci_sb600_softreset,
399 .pmp_softreset = ahci_sb600_softreset,
400};
401
Tejun Heo417a1a62007-09-23 13:19:55 +0900402#define AHCI_HFLAGS(flags) .private_data = (void *)(flags)
403
Arjan van de Ven98ac62d2005-11-28 10:06:23 +0100404static const struct ata_port_info ahci_port_info[] = {
Linus Torvalds1da177e2005-04-16 15:20:36 -0700405 /* board_ahci */
406 {
Tejun Heo1188c0d2007-04-23 02:41:05 +0900407 .flags = AHCI_FLAG_COMMON,
Erik Inge Bolsø14bdef92009-03-14 21:38:24 +0100408 .pio_mask = ATA_PIO4,
Jeff Garzik469248a2007-07-08 01:13:16 -0400409 .udma_mask = ATA_UDMA6,
Linus Torvalds1da177e2005-04-16 15:20:36 -0700410 .port_ops = &ahci_ops,
411 },
Bastiaan Jacquesbf2af2a2006-04-17 14:17:59 +0200412 /* board_ahci_vt8251 */
413 {
Tejun Heo6949b912007-09-23 13:19:55 +0900414 AHCI_HFLAGS (AHCI_HFLAG_NO_NCQ | AHCI_HFLAG_NO_PMP),
Tejun Heo417a1a62007-09-23 13:19:55 +0900415 .flags = AHCI_FLAG_COMMON,
Erik Inge Bolsø14bdef92009-03-14 21:38:24 +0100416 .pio_mask = ATA_PIO4,
Jeff Garzik469248a2007-07-08 01:13:16 -0400417 .udma_mask = ATA_UDMA6,
Tejun Heoad616ff2006-11-01 18:00:24 +0900418 .port_ops = &ahci_vt8251_ops,
Bastiaan Jacquesbf2af2a2006-04-17 14:17:59 +0200419 },
Tejun Heo41669552006-11-29 11:33:14 +0900420 /* board_ahci_ign_iferr */
421 {
Tejun Heo417a1a62007-09-23 13:19:55 +0900422 AHCI_HFLAGS (AHCI_HFLAG_IGN_IRQ_IF_ERR),
423 .flags = AHCI_FLAG_COMMON,
Erik Inge Bolsø14bdef92009-03-14 21:38:24 +0100424 .pio_mask = ATA_PIO4,
Jeff Garzik469248a2007-07-08 01:13:16 -0400425 .udma_mask = ATA_UDMA6,
Tejun Heo41669552006-11-29 11:33:14 +0900426 .port_ops = &ahci_ops,
427 },
Conke Hu55a61602007-03-27 18:33:05 +0800428 /* board_ahci_sb600 */
429 {
Tejun Heo417a1a62007-09-23 13:19:55 +0900430 AHCI_HFLAGS (AHCI_HFLAG_IGN_SERR_INTERNAL |
Tejun Heo22b5e7a2008-04-29 16:09:22 +0900431 AHCI_HFLAG_32BIT_ONLY | AHCI_HFLAG_NO_MSI |
Shane Huangbd172432008-06-10 15:52:04 +0800432 AHCI_HFLAG_SECT255),
Tejun Heo417a1a62007-09-23 13:19:55 +0900433 .flags = AHCI_FLAG_COMMON,
Erik Inge Bolsø14bdef92009-03-14 21:38:24 +0100434 .pio_mask = ATA_PIO4,
Jeff Garzik469248a2007-07-08 01:13:16 -0400435 .udma_mask = ATA_UDMA6,
Shane Huangbd172432008-06-10 15:52:04 +0800436 .port_ops = &ahci_sb600_ops,
Conke Hu55a61602007-03-27 18:33:05 +0800437 },
Jeff Garzikcd70c262007-07-08 02:29:42 -0400438 /* board_ahci_mv */
439 {
Tejun Heo417a1a62007-09-23 13:19:55 +0900440 AHCI_HFLAGS (AHCI_HFLAG_NO_NCQ | AHCI_HFLAG_NO_MSI |
Tejun Heo17248462008-08-29 16:03:59 +0200441 AHCI_HFLAG_MV_PATA | AHCI_HFLAG_NO_PMP),
Jeff Garzikcd70c262007-07-08 02:29:42 -0400442 .flags = ATA_FLAG_SATA | ATA_FLAG_NO_LEGACY |
Tejun Heo417a1a62007-09-23 13:19:55 +0900443 ATA_FLAG_MMIO | ATA_FLAG_PIO_DMA,
Erik Inge Bolsø14bdef92009-03-14 21:38:24 +0100444 .pio_mask = ATA_PIO4,
Jeff Garzikcd70c262007-07-08 02:29:42 -0400445 .udma_mask = ATA_UDMA6,
446 .port_ops = &ahci_ops,
447 },
Shane Huange427fe02008-12-30 10:53:41 +0800448 /* board_ahci_sb700, for SB700 and SB800 */
Shane Huange39fc8c2008-02-22 05:00:31 -0800449 {
Shane Huangbd172432008-06-10 15:52:04 +0800450 AHCI_HFLAGS (AHCI_HFLAG_IGN_SERR_INTERNAL),
Shane Huange39fc8c2008-02-22 05:00:31 -0800451 .flags = AHCI_FLAG_COMMON,
Erik Inge Bolsø14bdef92009-03-14 21:38:24 +0100452 .pio_mask = ATA_PIO4,
Shane Huange39fc8c2008-02-22 05:00:31 -0800453 .udma_mask = ATA_UDMA6,
Shane Huangbd172432008-06-10 15:52:04 +0800454 .port_ops = &ahci_sb600_ops,
Shane Huange39fc8c2008-02-22 05:00:31 -0800455 },
Tejun Heoe297d992008-06-10 00:13:04 +0900456 /* board_ahci_mcp65 */
457 {
458 AHCI_HFLAGS (AHCI_HFLAG_YES_NCQ),
459 .flags = AHCI_FLAG_COMMON,
Erik Inge Bolsø14bdef92009-03-14 21:38:24 +0100460 .pio_mask = ATA_PIO4,
Tejun Heoe297d992008-06-10 00:13:04 +0900461 .udma_mask = ATA_UDMA6,
462 .port_ops = &ahci_ops,
463 },
Tejun Heo9a3b1032008-06-18 20:56:58 -0400464 /* board_ahci_nopmp */
465 {
466 AHCI_HFLAGS (AHCI_HFLAG_NO_PMP),
467 .flags = AHCI_FLAG_COMMON,
Erik Inge Bolsø14bdef92009-03-14 21:38:24 +0100468 .pio_mask = ATA_PIO4,
Tejun Heo9a3b1032008-06-18 20:56:58 -0400469 .udma_mask = ATA_UDMA6,
470 .port_ops = &ahci_ops,
471 },
Linus Torvalds1da177e2005-04-16 15:20:36 -0700472};
473
Jeff Garzik3b7d6972005-11-10 11:04:11 -0500474static const struct pci_device_id ahci_pci_tbl[] = {
Jeff Garzikfe7fa312006-06-22 23:05:36 -0400475 /* Intel */
Jeff Garzik54bb3a942006-09-27 22:20:11 -0400476 { PCI_VDEVICE(INTEL, 0x2652), board_ahci }, /* ICH6 */
477 { PCI_VDEVICE(INTEL, 0x2653), board_ahci }, /* ICH6M */
478 { PCI_VDEVICE(INTEL, 0x27c1), board_ahci }, /* ICH7 */
479 { PCI_VDEVICE(INTEL, 0x27c5), board_ahci }, /* ICH7M */
480 { PCI_VDEVICE(INTEL, 0x27c3), board_ahci }, /* ICH7R */
Tejun Heo82490c02007-01-23 15:13:39 +0900481 { PCI_VDEVICE(AL, 0x5288), board_ahci_ign_iferr }, /* ULi M5288 */
Jeff Garzik54bb3a942006-09-27 22:20:11 -0400482 { PCI_VDEVICE(INTEL, 0x2681), board_ahci }, /* ESB2 */
483 { PCI_VDEVICE(INTEL, 0x2682), board_ahci }, /* ESB2 */
484 { PCI_VDEVICE(INTEL, 0x2683), board_ahci }, /* ESB2 */
485 { PCI_VDEVICE(INTEL, 0x27c6), board_ahci }, /* ICH7-M DH */
Tejun Heo7a234af2007-09-03 12:44:57 +0900486 { PCI_VDEVICE(INTEL, 0x2821), board_ahci }, /* ICH8 */
487 { PCI_VDEVICE(INTEL, 0x2822), board_ahci }, /* ICH8 */
488 { PCI_VDEVICE(INTEL, 0x2824), board_ahci }, /* ICH8 */
489 { PCI_VDEVICE(INTEL, 0x2829), board_ahci }, /* ICH8M */
490 { PCI_VDEVICE(INTEL, 0x282a), board_ahci }, /* ICH8M */
491 { PCI_VDEVICE(INTEL, 0x2922), board_ahci }, /* ICH9 */
492 { PCI_VDEVICE(INTEL, 0x2923), board_ahci }, /* ICH9 */
493 { PCI_VDEVICE(INTEL, 0x2924), board_ahci }, /* ICH9 */
494 { PCI_VDEVICE(INTEL, 0x2925), board_ahci }, /* ICH9 */
495 { PCI_VDEVICE(INTEL, 0x2927), board_ahci }, /* ICH9 */
496 { PCI_VDEVICE(INTEL, 0x2929), board_ahci }, /* ICH9M */
497 { PCI_VDEVICE(INTEL, 0x292a), board_ahci }, /* ICH9M */
498 { PCI_VDEVICE(INTEL, 0x292b), board_ahci }, /* ICH9M */
499 { PCI_VDEVICE(INTEL, 0x292c), board_ahci }, /* ICH9M */
500 { PCI_VDEVICE(INTEL, 0x292f), board_ahci }, /* ICH9M */
501 { PCI_VDEVICE(INTEL, 0x294d), board_ahci }, /* ICH9 */
502 { PCI_VDEVICE(INTEL, 0x294e), board_ahci }, /* ICH9M */
Jason Gastond4155e62007-09-20 17:35:00 -0400503 { PCI_VDEVICE(INTEL, 0x502a), board_ahci }, /* Tolapai */
504 { PCI_VDEVICE(INTEL, 0x502b), board_ahci }, /* Tolapai */
Jason Gaston16ad1ad2008-01-28 17:34:14 -0800505 { PCI_VDEVICE(INTEL, 0x3a05), board_ahci }, /* ICH10 */
506 { PCI_VDEVICE(INTEL, 0x3a25), board_ahci }, /* ICH10 */
Seth Heasleyadcb5302008-08-11 17:03:09 -0700507 { PCI_VDEVICE(INTEL, 0x3b24), board_ahci }, /* PCH RAID */
Seth Heasley8e48b6b2008-08-27 16:47:22 -0700508 { PCI_VDEVICE(INTEL, 0x3b25), board_ahci }, /* PCH RAID */
Seth Heasleyadcb5302008-08-11 17:03:09 -0700509 { PCI_VDEVICE(INTEL, 0x3b2b), board_ahci }, /* PCH RAID */
Seth Heasley8e48b6b2008-08-27 16:47:22 -0700510 { PCI_VDEVICE(INTEL, 0x3b2c), board_ahci }, /* PCH RAID */
Jeff Garzikfe7fa312006-06-22 23:05:36 -0400511
Tejun Heoe34bb372007-02-26 20:24:03 +0900512 /* JMicron 360/1/3/5/6, match class to avoid IDE function */
513 { PCI_VENDOR_ID_JMICRON, PCI_ANY_ID, PCI_ANY_ID, PCI_ANY_ID,
514 PCI_CLASS_STORAGE_SATA_AHCI, 0xffffff, board_ahci_ign_iferr },
Jeff Garzikfe7fa312006-06-22 23:05:36 -0400515
516 /* ATI */
Conke Huc65ec1c2007-04-11 18:23:14 +0800517 { PCI_VDEVICE(ATI, 0x4380), board_ahci_sb600 }, /* ATI SB600 */
Shane Huange39fc8c2008-02-22 05:00:31 -0800518 { PCI_VDEVICE(ATI, 0x4390), board_ahci_sb700 }, /* ATI SB700/800 */
519 { PCI_VDEVICE(ATI, 0x4391), board_ahci_sb700 }, /* ATI SB700/800 */
520 { PCI_VDEVICE(ATI, 0x4392), board_ahci_sb700 }, /* ATI SB700/800 */
521 { PCI_VDEVICE(ATI, 0x4393), board_ahci_sb700 }, /* ATI SB700/800 */
522 { PCI_VDEVICE(ATI, 0x4394), board_ahci_sb700 }, /* ATI SB700/800 */
523 { PCI_VDEVICE(ATI, 0x4395), board_ahci_sb700 }, /* ATI SB700/800 */
Jeff Garzikfe7fa312006-06-22 23:05:36 -0400524
525 /* VIA */
Jeff Garzik54bb3a942006-09-27 22:20:11 -0400526 { PCI_VDEVICE(VIA, 0x3349), board_ahci_vt8251 }, /* VIA VT8251 */
Tejun Heobf335542007-04-11 17:27:14 +0900527 { PCI_VDEVICE(VIA, 0x6287), board_ahci_vt8251 }, /* VIA VT8251 */
Jeff Garzikfe7fa312006-06-22 23:05:36 -0400528
529 /* NVIDIA */
Tejun Heoe297d992008-06-10 00:13:04 +0900530 { PCI_VDEVICE(NVIDIA, 0x044c), board_ahci_mcp65 }, /* MCP65 */
531 { PCI_VDEVICE(NVIDIA, 0x044d), board_ahci_mcp65 }, /* MCP65 */
532 { PCI_VDEVICE(NVIDIA, 0x044e), board_ahci_mcp65 }, /* MCP65 */
533 { PCI_VDEVICE(NVIDIA, 0x044f), board_ahci_mcp65 }, /* MCP65 */
534 { PCI_VDEVICE(NVIDIA, 0x045c), board_ahci_mcp65 }, /* MCP65 */
535 { PCI_VDEVICE(NVIDIA, 0x045d), board_ahci_mcp65 }, /* MCP65 */
536 { PCI_VDEVICE(NVIDIA, 0x045e), board_ahci_mcp65 }, /* MCP65 */
537 { PCI_VDEVICE(NVIDIA, 0x045f), board_ahci_mcp65 }, /* MCP65 */
Peer Chen6fbf5ba2006-12-20 14:18:00 -0500538 { PCI_VDEVICE(NVIDIA, 0x0550), board_ahci }, /* MCP67 */
539 { PCI_VDEVICE(NVIDIA, 0x0551), board_ahci }, /* MCP67 */
540 { PCI_VDEVICE(NVIDIA, 0x0552), board_ahci }, /* MCP67 */
541 { PCI_VDEVICE(NVIDIA, 0x0553), board_ahci }, /* MCP67 */
Peer Chen895663c2006-11-02 17:59:46 -0500542 { PCI_VDEVICE(NVIDIA, 0x0554), board_ahci }, /* MCP67 */
543 { PCI_VDEVICE(NVIDIA, 0x0555), board_ahci }, /* MCP67 */
544 { PCI_VDEVICE(NVIDIA, 0x0556), board_ahci }, /* MCP67 */
545 { PCI_VDEVICE(NVIDIA, 0x0557), board_ahci }, /* MCP67 */
546 { PCI_VDEVICE(NVIDIA, 0x0558), board_ahci }, /* MCP67 */
547 { PCI_VDEVICE(NVIDIA, 0x0559), board_ahci }, /* MCP67 */
548 { PCI_VDEVICE(NVIDIA, 0x055a), board_ahci }, /* MCP67 */
549 { PCI_VDEVICE(NVIDIA, 0x055b), board_ahci }, /* MCP67 */
Peer Chen0522b282007-06-07 18:05:12 +0800550 { PCI_VDEVICE(NVIDIA, 0x07f0), board_ahci }, /* MCP73 */
551 { PCI_VDEVICE(NVIDIA, 0x07f1), board_ahci }, /* MCP73 */
552 { PCI_VDEVICE(NVIDIA, 0x07f2), board_ahci }, /* MCP73 */
553 { PCI_VDEVICE(NVIDIA, 0x07f3), board_ahci }, /* MCP73 */
554 { PCI_VDEVICE(NVIDIA, 0x07f4), board_ahci }, /* MCP73 */
555 { PCI_VDEVICE(NVIDIA, 0x07f5), board_ahci }, /* MCP73 */
556 { PCI_VDEVICE(NVIDIA, 0x07f6), board_ahci }, /* MCP73 */
557 { PCI_VDEVICE(NVIDIA, 0x07f7), board_ahci }, /* MCP73 */
558 { PCI_VDEVICE(NVIDIA, 0x07f8), board_ahci }, /* MCP73 */
559 { PCI_VDEVICE(NVIDIA, 0x07f9), board_ahci }, /* MCP73 */
560 { PCI_VDEVICE(NVIDIA, 0x07fa), board_ahci }, /* MCP73 */
561 { PCI_VDEVICE(NVIDIA, 0x07fb), board_ahci }, /* MCP73 */
562 { PCI_VDEVICE(NVIDIA, 0x0ad0), board_ahci }, /* MCP77 */
563 { PCI_VDEVICE(NVIDIA, 0x0ad1), board_ahci }, /* MCP77 */
564 { PCI_VDEVICE(NVIDIA, 0x0ad2), board_ahci }, /* MCP77 */
565 { PCI_VDEVICE(NVIDIA, 0x0ad3), board_ahci }, /* MCP77 */
566 { PCI_VDEVICE(NVIDIA, 0x0ad4), board_ahci }, /* MCP77 */
567 { PCI_VDEVICE(NVIDIA, 0x0ad5), board_ahci }, /* MCP77 */
568 { PCI_VDEVICE(NVIDIA, 0x0ad6), board_ahci }, /* MCP77 */
569 { PCI_VDEVICE(NVIDIA, 0x0ad7), board_ahci }, /* MCP77 */
570 { PCI_VDEVICE(NVIDIA, 0x0ad8), board_ahci }, /* MCP77 */
571 { PCI_VDEVICE(NVIDIA, 0x0ad9), board_ahci }, /* MCP77 */
572 { PCI_VDEVICE(NVIDIA, 0x0ada), board_ahci }, /* MCP77 */
573 { PCI_VDEVICE(NVIDIA, 0x0adb), board_ahci }, /* MCP77 */
peerchen6ba86952007-12-03 22:20:37 +0800574 { PCI_VDEVICE(NVIDIA, 0x0ab4), board_ahci }, /* MCP79 */
575 { PCI_VDEVICE(NVIDIA, 0x0ab5), board_ahci }, /* MCP79 */
576 { PCI_VDEVICE(NVIDIA, 0x0ab6), board_ahci }, /* MCP79 */
577 { PCI_VDEVICE(NVIDIA, 0x0ab7), board_ahci }, /* MCP79 */
Peer Chen71008192007-09-24 10:16:25 +0800578 { PCI_VDEVICE(NVIDIA, 0x0ab8), board_ahci }, /* MCP79 */
579 { PCI_VDEVICE(NVIDIA, 0x0ab9), board_ahci }, /* MCP79 */
580 { PCI_VDEVICE(NVIDIA, 0x0aba), board_ahci }, /* MCP79 */
581 { PCI_VDEVICE(NVIDIA, 0x0abb), board_ahci }, /* MCP79 */
582 { PCI_VDEVICE(NVIDIA, 0x0abc), board_ahci }, /* MCP79 */
583 { PCI_VDEVICE(NVIDIA, 0x0abd), board_ahci }, /* MCP79 */
584 { PCI_VDEVICE(NVIDIA, 0x0abe), board_ahci }, /* MCP79 */
585 { PCI_VDEVICE(NVIDIA, 0x0abf), board_ahci }, /* MCP79 */
peerchen7adbe462009-02-27 16:58:41 +0800586 { PCI_VDEVICE(NVIDIA, 0x0d84), board_ahci }, /* MCP89 */
587 { PCI_VDEVICE(NVIDIA, 0x0d85), board_ahci }, /* MCP89 */
588 { PCI_VDEVICE(NVIDIA, 0x0d86), board_ahci }, /* MCP89 */
589 { PCI_VDEVICE(NVIDIA, 0x0d87), board_ahci }, /* MCP89 */
590 { PCI_VDEVICE(NVIDIA, 0x0d88), board_ahci }, /* MCP89 */
591 { PCI_VDEVICE(NVIDIA, 0x0d89), board_ahci }, /* MCP89 */
592 { PCI_VDEVICE(NVIDIA, 0x0d8a), board_ahci }, /* MCP89 */
593 { PCI_VDEVICE(NVIDIA, 0x0d8b), board_ahci }, /* MCP89 */
594 { PCI_VDEVICE(NVIDIA, 0x0d8c), board_ahci }, /* MCP89 */
595 { PCI_VDEVICE(NVIDIA, 0x0d8d), board_ahci }, /* MCP89 */
596 { PCI_VDEVICE(NVIDIA, 0x0d8e), board_ahci }, /* MCP89 */
597 { PCI_VDEVICE(NVIDIA, 0x0d8f), board_ahci }, /* MCP89 */
Jeff Garzikfe7fa312006-06-22 23:05:36 -0400598
Jeff Garzik95916ed2006-07-29 04:10:14 -0400599 /* SiS */
Tejun Heo20e2de42008-08-01 12:51:43 +0900600 { PCI_VDEVICE(SI, 0x1184), board_ahci }, /* SiS 966 */
601 { PCI_VDEVICE(SI, 0x1185), board_ahci }, /* SiS 968 */
602 { PCI_VDEVICE(SI, 0x0186), board_ahci }, /* SiS 968 */
Jeff Garzik95916ed2006-07-29 04:10:14 -0400603
Jeff Garzikcd70c262007-07-08 02:29:42 -0400604 /* Marvell */
605 { PCI_VDEVICE(MARVELL, 0x6145), board_ahci_mv }, /* 6145 */
Jose Alberto Regueroc40e7cb2008-03-13 23:22:24 +0100606 { PCI_VDEVICE(MARVELL, 0x6121), board_ahci_mv }, /* 6121 */
Jeff Garzikcd70c262007-07-08 02:29:42 -0400607
Mark Nelsonc77a0362008-10-23 14:08:16 +1100608 /* Promise */
609 { PCI_VDEVICE(PROMISE, 0x3f20), board_ahci }, /* PDC42819 */
610
Jeff Garzik415ae2b2006-11-01 05:10:42 -0500611 /* Generic, PCI class code for AHCI */
612 { PCI_ANY_ID, PCI_ANY_ID, PCI_ANY_ID, PCI_ANY_ID,
Conke Huc9f89472007-01-09 05:32:51 -0500613 PCI_CLASS_STORAGE_SATA_AHCI, 0xffffff, board_ahci },
Jeff Garzik415ae2b2006-11-01 05:10:42 -0500614
Linus Torvalds1da177e2005-04-16 15:20:36 -0700615 { } /* terminate list */
616};
617
618
619static struct pci_driver ahci_pci_driver = {
620 .name = DRV_NAME,
621 .id_table = ahci_pci_tbl,
622 .probe = ahci_init_one,
Tejun Heo24dc5f32007-01-20 16:00:28 +0900623 .remove = ata_pci_remove_one,
Tejun Heo438ac6d2007-03-02 17:31:26 +0900624#ifdef CONFIG_PM
Tejun Heoc1332872006-07-26 15:59:26 +0900625 .suspend = ahci_pci_device_suspend,
626 .resume = ahci_pci_device_resume,
Tejun Heo438ac6d2007-03-02 17:31:26 +0900627#endif
Linus Torvalds1da177e2005-04-16 15:20:36 -0700628};
629
Kristen Carlson Accardi18f7ba42008-06-03 10:33:55 -0700630static int ahci_em_messages = 1;
631module_param(ahci_em_messages, int, 0444);
632/* add other LED protocol types when they become supported */
633MODULE_PARM_DESC(ahci_em_messages,
634 "Set AHCI Enclosure Management Message type (0 = disabled, 1 = LED");
Linus Torvalds1da177e2005-04-16 15:20:36 -0700635
Alan Cox5b66c822008-09-03 14:48:34 +0100636#if defined(CONFIG_PATA_MARVELL) || defined(CONFIG_PATA_MARVELL_MODULE)
637static int marvell_enable;
638#else
639static int marvell_enable = 1;
640#endif
641module_param(marvell_enable, int, 0644);
642MODULE_PARM_DESC(marvell_enable, "Marvell SATA via AHCI (1 = enabled)");
643
644
Tejun Heo98fa4b62006-11-02 12:17:23 +0900645static inline int ahci_nr_ports(u32 cap)
646{
647 return (cap & 0x1f) + 1;
648}
649
Jeff Garzikdab632e2007-05-28 08:33:01 -0400650static inline void __iomem *__ahci_port_base(struct ata_host *host,
651 unsigned int port_no)
652{
653 void __iomem *mmio = host->iomap[AHCI_PCI_BAR];
654
655 return mmio + 0x100 + (port_no * 0x80);
656}
657
Tejun Heo4447d352007-04-17 23:44:08 +0900658static inline void __iomem *ahci_port_base(struct ata_port *ap)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700659{
Jeff Garzikdab632e2007-05-28 08:33:01 -0400660 return __ahci_port_base(ap->host, ap->port_no);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700661}
662
Tejun Heob710a1f2008-01-05 23:11:57 +0900663static void ahci_enable_ahci(void __iomem *mmio)
664{
Tejun Heo15fe9822008-04-23 20:52:58 +0900665 int i;
Tejun Heob710a1f2008-01-05 23:11:57 +0900666 u32 tmp;
667
668 /* turn on AHCI_EN */
669 tmp = readl(mmio + HOST_CTL);
Tejun Heo15fe9822008-04-23 20:52:58 +0900670 if (tmp & HOST_AHCI_EN)
671 return;
672
673 /* Some controllers need AHCI_EN to be written multiple times.
674 * Try a few times before giving up.
675 */
676 for (i = 0; i < 5; i++) {
Tejun Heob710a1f2008-01-05 23:11:57 +0900677 tmp |= HOST_AHCI_EN;
678 writel(tmp, mmio + HOST_CTL);
679 tmp = readl(mmio + HOST_CTL); /* flush && sanity check */
Tejun Heo15fe9822008-04-23 20:52:58 +0900680 if (tmp & HOST_AHCI_EN)
681 return;
682 msleep(10);
Tejun Heob710a1f2008-01-05 23:11:57 +0900683 }
Tejun Heo15fe9822008-04-23 20:52:58 +0900684
685 WARN_ON(1);
Tejun Heob710a1f2008-01-05 23:11:57 +0900686}
687
Tejun Heod447df12007-03-18 22:15:33 +0900688/**
689 * ahci_save_initial_config - Save and fixup initial config values
Tejun Heo4447d352007-04-17 23:44:08 +0900690 * @pdev: target PCI device
Tejun Heo4447d352007-04-17 23:44:08 +0900691 * @hpriv: host private area to store config values
Tejun Heod447df12007-03-18 22:15:33 +0900692 *
693 * Some registers containing configuration info might be setup by
694 * BIOS and might be cleared on reset. This function saves the
695 * initial values of those registers into @hpriv such that they
696 * can be restored after controller reset.
697 *
698 * If inconsistent, config values are fixed up by this function.
699 *
700 * LOCKING:
701 * None.
702 */
Tejun Heo4447d352007-04-17 23:44:08 +0900703static void ahci_save_initial_config(struct pci_dev *pdev,
Tejun Heo4447d352007-04-17 23:44:08 +0900704 struct ahci_host_priv *hpriv)
Tejun Heod447df12007-03-18 22:15:33 +0900705{
Tejun Heo4447d352007-04-17 23:44:08 +0900706 void __iomem *mmio = pcim_iomap_table(pdev)[AHCI_PCI_BAR];
Tejun Heod447df12007-03-18 22:15:33 +0900707 u32 cap, port_map;
Tejun Heo17199b12007-03-18 22:26:53 +0900708 int i;
Jose Alberto Regueroc40e7cb2008-03-13 23:22:24 +0100709 int mv;
Tejun Heod447df12007-03-18 22:15:33 +0900710
Tejun Heob710a1f2008-01-05 23:11:57 +0900711 /* make sure AHCI mode is enabled before accessing CAP */
712 ahci_enable_ahci(mmio);
713
Tejun Heod447df12007-03-18 22:15:33 +0900714 /* Values prefixed with saved_ are written back to host after
715 * reset. Values without are used for driver operation.
716 */
717 hpriv->saved_cap = cap = readl(mmio + HOST_CAP);
718 hpriv->saved_port_map = port_map = readl(mmio + HOST_PORTS_IMPL);
719
Tejun Heo274c1fd2007-07-16 14:29:40 +0900720 /* some chips have errata preventing 64bit use */
Tejun Heo417a1a62007-09-23 13:19:55 +0900721 if ((cap & HOST_CAP_64) && (hpriv->flags & AHCI_HFLAG_32BIT_ONLY)) {
Tejun Heoc7a42152007-05-18 16:23:19 +0200722 dev_printk(KERN_INFO, &pdev->dev,
723 "controller can't do 64bit DMA, forcing 32bit\n");
724 cap &= ~HOST_CAP_64;
725 }
726
Tejun Heo417a1a62007-09-23 13:19:55 +0900727 if ((cap & HOST_CAP_NCQ) && (hpriv->flags & AHCI_HFLAG_NO_NCQ)) {
Tejun Heo274c1fd2007-07-16 14:29:40 +0900728 dev_printk(KERN_INFO, &pdev->dev,
729 "controller can't do NCQ, turning off CAP_NCQ\n");
730 cap &= ~HOST_CAP_NCQ;
731 }
732
Tejun Heoe297d992008-06-10 00:13:04 +0900733 if (!(cap & HOST_CAP_NCQ) && (hpriv->flags & AHCI_HFLAG_YES_NCQ)) {
734 dev_printk(KERN_INFO, &pdev->dev,
735 "controller can do NCQ, turning on CAP_NCQ\n");
736 cap |= HOST_CAP_NCQ;
737 }
738
Roel Kluin258cd842008-03-09 21:42:40 +0100739 if ((cap & HOST_CAP_PMP) && (hpriv->flags & AHCI_HFLAG_NO_PMP)) {
Tejun Heo6949b912007-09-23 13:19:55 +0900740 dev_printk(KERN_INFO, &pdev->dev,
741 "controller can't do PMP, turning off CAP_PMP\n");
742 cap &= ~HOST_CAP_PMP;
743 }
744
Tejun Heod799e082008-06-17 12:46:30 +0900745 if (pdev->vendor == PCI_VENDOR_ID_JMICRON && pdev->device == 0x2361 &&
746 port_map != 1) {
747 dev_printk(KERN_INFO, &pdev->dev,
748 "JMB361 has only one port, port_map 0x%x -> 0x%x\n",
749 port_map, 1);
750 port_map = 1;
751 }
752
Jeff Garzikcd70c262007-07-08 02:29:42 -0400753 /*
754 * Temporary Marvell 6145 hack: PATA port presence
755 * is asserted through the standard AHCI port
756 * presence register, as bit 4 (counting from 0)
757 */
Tejun Heo417a1a62007-09-23 13:19:55 +0900758 if (hpriv->flags & AHCI_HFLAG_MV_PATA) {
Jose Alberto Regueroc40e7cb2008-03-13 23:22:24 +0100759 if (pdev->device == 0x6121)
760 mv = 0x3;
761 else
762 mv = 0xf;
Jeff Garzikcd70c262007-07-08 02:29:42 -0400763 dev_printk(KERN_ERR, &pdev->dev,
764 "MV_AHCI HACK: port_map %x -> %x\n",
Jose Alberto Regueroc40e7cb2008-03-13 23:22:24 +0100765 port_map,
766 port_map & mv);
Alan Cox5b66c822008-09-03 14:48:34 +0100767 dev_printk(KERN_ERR, &pdev->dev,
768 "Disabling your PATA port. Use the boot option 'ahci.marvell_enable=0' to avoid this.\n");
Jeff Garzikcd70c262007-07-08 02:29:42 -0400769
Jose Alberto Regueroc40e7cb2008-03-13 23:22:24 +0100770 port_map &= mv;
Jeff Garzikcd70c262007-07-08 02:29:42 -0400771 }
772
Tejun Heo17199b12007-03-18 22:26:53 +0900773 /* cross check port_map and cap.n_ports */
Tejun Heo7a234af2007-09-03 12:44:57 +0900774 if (port_map) {
Tejun Heo837f5f82008-02-06 15:13:51 +0900775 int map_ports = 0;
Tejun Heo17199b12007-03-18 22:26:53 +0900776
Tejun Heo837f5f82008-02-06 15:13:51 +0900777 for (i = 0; i < AHCI_MAX_PORTS; i++)
778 if (port_map & (1 << i))
779 map_ports++;
Tejun Heo17199b12007-03-18 22:26:53 +0900780
Tejun Heo837f5f82008-02-06 15:13:51 +0900781 /* If PI has more ports than n_ports, whine, clear
782 * port_map and let it be generated from n_ports.
Tejun Heo17199b12007-03-18 22:26:53 +0900783 */
Tejun Heo837f5f82008-02-06 15:13:51 +0900784 if (map_ports > ahci_nr_ports(cap)) {
Tejun Heo4447d352007-04-17 23:44:08 +0900785 dev_printk(KERN_WARNING, &pdev->dev,
Tejun Heo837f5f82008-02-06 15:13:51 +0900786 "implemented port map (0x%x) contains more "
787 "ports than nr_ports (%u), using nr_ports\n",
788 port_map, ahci_nr_ports(cap));
Tejun Heo7a234af2007-09-03 12:44:57 +0900789 port_map = 0;
790 }
791 }
792
793 /* fabricate port_map from cap.nr_ports */
794 if (!port_map) {
Tejun Heo17199b12007-03-18 22:26:53 +0900795 port_map = (1 << ahci_nr_ports(cap)) - 1;
Tejun Heo7a234af2007-09-03 12:44:57 +0900796 dev_printk(KERN_WARNING, &pdev->dev,
797 "forcing PORTS_IMPL to 0x%x\n", port_map);
798
799 /* write the fixed up value to the PI register */
800 hpriv->saved_port_map = port_map;
Tejun Heo17199b12007-03-18 22:26:53 +0900801 }
802
Tejun Heod447df12007-03-18 22:15:33 +0900803 /* record values to use during operation */
804 hpriv->cap = cap;
805 hpriv->port_map = port_map;
806}
807
808/**
809 * ahci_restore_initial_config - Restore initial config
Tejun Heo4447d352007-04-17 23:44:08 +0900810 * @host: target ATA host
Tejun Heod447df12007-03-18 22:15:33 +0900811 *
812 * Restore initial config stored by ahci_save_initial_config().
813 *
814 * LOCKING:
815 * None.
816 */
Tejun Heo4447d352007-04-17 23:44:08 +0900817static void ahci_restore_initial_config(struct ata_host *host)
Tejun Heod447df12007-03-18 22:15:33 +0900818{
Tejun Heo4447d352007-04-17 23:44:08 +0900819 struct ahci_host_priv *hpriv = host->private_data;
820 void __iomem *mmio = host->iomap[AHCI_PCI_BAR];
821
Tejun Heod447df12007-03-18 22:15:33 +0900822 writel(hpriv->saved_cap, mmio + HOST_CAP);
823 writel(hpriv->saved_port_map, mmio + HOST_PORTS_IMPL);
824 (void) readl(mmio + HOST_PORTS_IMPL); /* flush */
825}
826
Tejun Heo203ef6c2007-07-16 14:29:40 +0900827static unsigned ahci_scr_offset(struct ata_port *ap, unsigned int sc_reg)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700828{
Tejun Heo203ef6c2007-07-16 14:29:40 +0900829 static const int offset[] = {
830 [SCR_STATUS] = PORT_SCR_STAT,
831 [SCR_CONTROL] = PORT_SCR_CTL,
832 [SCR_ERROR] = PORT_SCR_ERR,
833 [SCR_ACTIVE] = PORT_SCR_ACT,
834 [SCR_NOTIFICATION] = PORT_SCR_NTF,
835 };
836 struct ahci_host_priv *hpriv = ap->host->private_data;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700837
Tejun Heo203ef6c2007-07-16 14:29:40 +0900838 if (sc_reg < ARRAY_SIZE(offset) &&
839 (sc_reg != SCR_NOTIFICATION || (hpriv->cap & HOST_CAP_SNTF)))
840 return offset[sc_reg];
Tejun Heoda3dbb12007-07-16 14:29:40 +0900841 return 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700842}
843
Tejun Heo82ef04f2008-07-31 17:02:40 +0900844static int ahci_scr_read(struct ata_link *link, unsigned int sc_reg, u32 *val)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700845{
Tejun Heo82ef04f2008-07-31 17:02:40 +0900846 void __iomem *port_mmio = ahci_port_base(link->ap);
847 int offset = ahci_scr_offset(link->ap, sc_reg);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700848
Tejun Heo203ef6c2007-07-16 14:29:40 +0900849 if (offset) {
850 *val = readl(port_mmio + offset);
851 return 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700852 }
Tejun Heo203ef6c2007-07-16 14:29:40 +0900853 return -EINVAL;
854}
Linus Torvalds1da177e2005-04-16 15:20:36 -0700855
Tejun Heo82ef04f2008-07-31 17:02:40 +0900856static int ahci_scr_write(struct ata_link *link, unsigned int sc_reg, u32 val)
Tejun Heo203ef6c2007-07-16 14:29:40 +0900857{
Tejun Heo82ef04f2008-07-31 17:02:40 +0900858 void __iomem *port_mmio = ahci_port_base(link->ap);
859 int offset = ahci_scr_offset(link->ap, sc_reg);
Tejun Heo203ef6c2007-07-16 14:29:40 +0900860
861 if (offset) {
862 writel(val, port_mmio + offset);
863 return 0;
864 }
865 return -EINVAL;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700866}
867
Tejun Heo4447d352007-04-17 23:44:08 +0900868static void ahci_start_engine(struct ata_port *ap)
Tejun Heo7c76d1e2005-12-19 22:36:34 +0900869{
Tejun Heo4447d352007-04-17 23:44:08 +0900870 void __iomem *port_mmio = ahci_port_base(ap);
Tejun Heo7c76d1e2005-12-19 22:36:34 +0900871 u32 tmp;
872
Tejun Heod8fcd112006-07-26 15:59:25 +0900873 /* start DMA */
Tejun Heo9f592052006-07-26 15:59:26 +0900874 tmp = readl(port_mmio + PORT_CMD);
Tejun Heo7c76d1e2005-12-19 22:36:34 +0900875 tmp |= PORT_CMD_START;
876 writel(tmp, port_mmio + PORT_CMD);
877 readl(port_mmio + PORT_CMD); /* flush */
878}
879
Tejun Heo4447d352007-04-17 23:44:08 +0900880static int ahci_stop_engine(struct ata_port *ap)
Tejun Heo254950c2006-07-26 15:59:25 +0900881{
Tejun Heo4447d352007-04-17 23:44:08 +0900882 void __iomem *port_mmio = ahci_port_base(ap);
Tejun Heo254950c2006-07-26 15:59:25 +0900883 u32 tmp;
884
885 tmp = readl(port_mmio + PORT_CMD);
886
Tejun Heod8fcd112006-07-26 15:59:25 +0900887 /* check if the HBA is idle */
Tejun Heo254950c2006-07-26 15:59:25 +0900888 if ((tmp & (PORT_CMD_START | PORT_CMD_LIST_ON)) == 0)
889 return 0;
890
Tejun Heod8fcd112006-07-26 15:59:25 +0900891 /* setting HBA to idle */
Tejun Heo254950c2006-07-26 15:59:25 +0900892 tmp &= ~PORT_CMD_START;
893 writel(tmp, port_mmio + PORT_CMD);
894
Tejun Heod8fcd112006-07-26 15:59:25 +0900895 /* wait for engine to stop. This could be as long as 500 msec */
Tejun Heo254950c2006-07-26 15:59:25 +0900896 tmp = ata_wait_register(port_mmio + PORT_CMD,
Jeff Garzik2dcb4072007-10-19 06:42:56 -0400897 PORT_CMD_LIST_ON, PORT_CMD_LIST_ON, 1, 500);
Tejun Heod8fcd112006-07-26 15:59:25 +0900898 if (tmp & PORT_CMD_LIST_ON)
Tejun Heo254950c2006-07-26 15:59:25 +0900899 return -EIO;
900
901 return 0;
902}
903
Tejun Heo4447d352007-04-17 23:44:08 +0900904static void ahci_start_fis_rx(struct ata_port *ap)
Tejun Heo0be0aa92006-07-26 15:59:26 +0900905{
Tejun Heo4447d352007-04-17 23:44:08 +0900906 void __iomem *port_mmio = ahci_port_base(ap);
907 struct ahci_host_priv *hpriv = ap->host->private_data;
908 struct ahci_port_priv *pp = ap->private_data;
Tejun Heo0be0aa92006-07-26 15:59:26 +0900909 u32 tmp;
910
911 /* set FIS registers */
Tejun Heo4447d352007-04-17 23:44:08 +0900912 if (hpriv->cap & HOST_CAP_64)
913 writel((pp->cmd_slot_dma >> 16) >> 16,
914 port_mmio + PORT_LST_ADDR_HI);
915 writel(pp->cmd_slot_dma & 0xffffffff, port_mmio + PORT_LST_ADDR);
Tejun Heo0be0aa92006-07-26 15:59:26 +0900916
Tejun Heo4447d352007-04-17 23:44:08 +0900917 if (hpriv->cap & HOST_CAP_64)
918 writel((pp->rx_fis_dma >> 16) >> 16,
919 port_mmio + PORT_FIS_ADDR_HI);
920 writel(pp->rx_fis_dma & 0xffffffff, port_mmio + PORT_FIS_ADDR);
Tejun Heo0be0aa92006-07-26 15:59:26 +0900921
922 /* enable FIS reception */
923 tmp = readl(port_mmio + PORT_CMD);
924 tmp |= PORT_CMD_FIS_RX;
925 writel(tmp, port_mmio + PORT_CMD);
926
927 /* flush */
928 readl(port_mmio + PORT_CMD);
929}
930
Tejun Heo4447d352007-04-17 23:44:08 +0900931static int ahci_stop_fis_rx(struct ata_port *ap)
Tejun Heo0be0aa92006-07-26 15:59:26 +0900932{
Tejun Heo4447d352007-04-17 23:44:08 +0900933 void __iomem *port_mmio = ahci_port_base(ap);
Tejun Heo0be0aa92006-07-26 15:59:26 +0900934 u32 tmp;
935
936 /* disable FIS reception */
937 tmp = readl(port_mmio + PORT_CMD);
938 tmp &= ~PORT_CMD_FIS_RX;
939 writel(tmp, port_mmio + PORT_CMD);
940
941 /* wait for completion, spec says 500ms, give it 1000 */
942 tmp = ata_wait_register(port_mmio + PORT_CMD, PORT_CMD_FIS_ON,
943 PORT_CMD_FIS_ON, 10, 1000);
944 if (tmp & PORT_CMD_FIS_ON)
945 return -EBUSY;
946
947 return 0;
948}
949
Tejun Heo4447d352007-04-17 23:44:08 +0900950static void ahci_power_up(struct ata_port *ap)
Tejun Heo0be0aa92006-07-26 15:59:26 +0900951{
Tejun Heo4447d352007-04-17 23:44:08 +0900952 struct ahci_host_priv *hpriv = ap->host->private_data;
953 void __iomem *port_mmio = ahci_port_base(ap);
Tejun Heo0be0aa92006-07-26 15:59:26 +0900954 u32 cmd;
955
956 cmd = readl(port_mmio + PORT_CMD) & ~PORT_CMD_ICC_MASK;
957
958 /* spin up device */
Tejun Heo4447d352007-04-17 23:44:08 +0900959 if (hpriv->cap & HOST_CAP_SSS) {
Tejun Heo0be0aa92006-07-26 15:59:26 +0900960 cmd |= PORT_CMD_SPIN_UP;
961 writel(cmd, port_mmio + PORT_CMD);
962 }
963
964 /* wake up link */
965 writel(cmd | PORT_CMD_ICC_ACTIVE, port_mmio + PORT_CMD);
966}
967
Kristen Carlson Accardi31556592007-10-25 01:33:26 -0400968static void ahci_disable_alpm(struct ata_port *ap)
969{
970 struct ahci_host_priv *hpriv = ap->host->private_data;
971 void __iomem *port_mmio = ahci_port_base(ap);
972 u32 cmd;
973 struct ahci_port_priv *pp = ap->private_data;
974
975 /* IPM bits should be disabled by libata-core */
976 /* get the existing command bits */
977 cmd = readl(port_mmio + PORT_CMD);
978
979 /* disable ALPM and ASP */
980 cmd &= ~PORT_CMD_ASP;
981 cmd &= ~PORT_CMD_ALPE;
982
983 /* force the interface back to active */
984 cmd |= PORT_CMD_ICC_ACTIVE;
985
986 /* write out new cmd value */
987 writel(cmd, port_mmio + PORT_CMD);
988 cmd = readl(port_mmio + PORT_CMD);
989
990 /* wait 10ms to be sure we've come out of any low power state */
991 msleep(10);
992
993 /* clear out any PhyRdy stuff from interrupt status */
994 writel(PORT_IRQ_PHYRDY, port_mmio + PORT_IRQ_STAT);
995
996 /* go ahead and clean out PhyRdy Change from Serror too */
Tejun Heo82ef04f2008-07-31 17:02:40 +0900997 ahci_scr_write(&ap->link, SCR_ERROR, ((1 << 16) | (1 << 18)));
Kristen Carlson Accardi31556592007-10-25 01:33:26 -0400998
999 /*
1000 * Clear flag to indicate that we should ignore all PhyRdy
1001 * state changes
1002 */
1003 hpriv->flags &= ~AHCI_HFLAG_NO_HOTPLUG;
1004
1005 /*
1006 * Enable interrupts on Phy Ready.
1007 */
1008 pp->intr_mask |= PORT_IRQ_PHYRDY;
1009 writel(pp->intr_mask, port_mmio + PORT_IRQ_MASK);
1010
1011 /*
1012 * don't change the link pm policy - we can be called
1013 * just to turn of link pm temporarily
1014 */
1015}
1016
1017static int ahci_enable_alpm(struct ata_port *ap,
1018 enum link_pm policy)
1019{
1020 struct ahci_host_priv *hpriv = ap->host->private_data;
1021 void __iomem *port_mmio = ahci_port_base(ap);
1022 u32 cmd;
1023 struct ahci_port_priv *pp = ap->private_data;
1024 u32 asp;
1025
1026 /* Make sure the host is capable of link power management */
1027 if (!(hpriv->cap & HOST_CAP_ALPM))
1028 return -EINVAL;
1029
1030 switch (policy) {
1031 case MAX_PERFORMANCE:
1032 case NOT_AVAILABLE:
1033 /*
1034 * if we came here with NOT_AVAILABLE,
1035 * it just means this is the first time we
1036 * have tried to enable - default to max performance,
1037 * and let the user go to lower power modes on request.
1038 */
1039 ahci_disable_alpm(ap);
1040 return 0;
1041 case MIN_POWER:
1042 /* configure HBA to enter SLUMBER */
1043 asp = PORT_CMD_ASP;
1044 break;
1045 case MEDIUM_POWER:
1046 /* configure HBA to enter PARTIAL */
1047 asp = 0;
1048 break;
1049 default:
1050 return -EINVAL;
1051 }
1052
1053 /*
1054 * Disable interrupts on Phy Ready. This keeps us from
1055 * getting woken up due to spurious phy ready interrupts
1056 * TBD - Hot plug should be done via polling now, is
1057 * that even supported?
1058 */
1059 pp->intr_mask &= ~PORT_IRQ_PHYRDY;
1060 writel(pp->intr_mask, port_mmio + PORT_IRQ_MASK);
1061
1062 /*
1063 * Set a flag to indicate that we should ignore all PhyRdy
1064 * state changes since these can happen now whenever we
1065 * change link state
1066 */
1067 hpriv->flags |= AHCI_HFLAG_NO_HOTPLUG;
1068
1069 /* get the existing command bits */
1070 cmd = readl(port_mmio + PORT_CMD);
1071
1072 /*
1073 * Set ASP based on Policy
1074 */
1075 cmd |= asp;
1076
1077 /*
1078 * Setting this bit will instruct the HBA to aggressively
1079 * enter a lower power link state when it's appropriate and
1080 * based on the value set above for ASP
1081 */
1082 cmd |= PORT_CMD_ALPE;
1083
1084 /* write out new cmd value */
1085 writel(cmd, port_mmio + PORT_CMD);
1086 cmd = readl(port_mmio + PORT_CMD);
1087
1088 /* IPM bits should be set by libata-core */
1089 return 0;
1090}
1091
Tejun Heo438ac6d2007-03-02 17:31:26 +09001092#ifdef CONFIG_PM
Tejun Heo4447d352007-04-17 23:44:08 +09001093static void ahci_power_down(struct ata_port *ap)
Tejun Heo0be0aa92006-07-26 15:59:26 +09001094{
Tejun Heo4447d352007-04-17 23:44:08 +09001095 struct ahci_host_priv *hpriv = ap->host->private_data;
1096 void __iomem *port_mmio = ahci_port_base(ap);
Tejun Heo0be0aa92006-07-26 15:59:26 +09001097 u32 cmd, scontrol;
1098
Tejun Heo4447d352007-04-17 23:44:08 +09001099 if (!(hpriv->cap & HOST_CAP_SSS))
Tejun Heo07c53da2007-01-21 02:10:11 +09001100 return;
1101
1102 /* put device into listen mode, first set PxSCTL.DET to 0 */
1103 scontrol = readl(port_mmio + PORT_SCR_CTL);
1104 scontrol &= ~0xf;
1105 writel(scontrol, port_mmio + PORT_SCR_CTL);
1106
1107 /* then set PxCMD.SUD to 0 */
Tejun Heo0be0aa92006-07-26 15:59:26 +09001108 cmd = readl(port_mmio + PORT_CMD) & ~PORT_CMD_ICC_MASK;
Tejun Heo07c53da2007-01-21 02:10:11 +09001109 cmd &= ~PORT_CMD_SPIN_UP;
1110 writel(cmd, port_mmio + PORT_CMD);
Tejun Heo0be0aa92006-07-26 15:59:26 +09001111}
Tejun Heo438ac6d2007-03-02 17:31:26 +09001112#endif
Tejun Heo0be0aa92006-07-26 15:59:26 +09001113
Jeff Garzikdf69c9c2007-05-26 20:46:51 -04001114static void ahci_start_port(struct ata_port *ap)
Tejun Heo0be0aa92006-07-26 15:59:26 +09001115{
Kristen Carlson Accardi18f7ba42008-06-03 10:33:55 -07001116 struct ahci_port_priv *pp = ap->private_data;
1117 struct ata_link *link;
1118 struct ahci_em_priv *emp;
David Milburn4c1e9aa2009-04-03 15:36:41 -05001119 ssize_t rc;
1120 int i;
Kristen Carlson Accardi18f7ba42008-06-03 10:33:55 -07001121
Tejun Heo0be0aa92006-07-26 15:59:26 +09001122 /* enable FIS reception */
Tejun Heo4447d352007-04-17 23:44:08 +09001123 ahci_start_fis_rx(ap);
Tejun Heo0be0aa92006-07-26 15:59:26 +09001124
1125 /* enable DMA */
Tejun Heo4447d352007-04-17 23:44:08 +09001126 ahci_start_engine(ap);
Kristen Carlson Accardi18f7ba42008-06-03 10:33:55 -07001127
1128 /* turn on LEDs */
1129 if (ap->flags & ATA_FLAG_EM) {
Tejun Heo1eca4362008-11-03 20:03:17 +09001130 ata_for_each_link(link, ap, EDGE) {
Kristen Carlson Accardi18f7ba42008-06-03 10:33:55 -07001131 emp = &pp->em_priv[link->pmp];
David Milburn4c1e9aa2009-04-03 15:36:41 -05001132
1133 /* EM Transmit bit maybe busy during init */
1134 for (i = 0; i < MAX_RETRY; i++) {
1135 rc = ahci_transmit_led_message(ap,
1136 emp->led_state,
1137 4);
1138 if (rc == -EBUSY)
1139 udelay(100);
1140 else
1141 break;
1142 }
Kristen Carlson Accardi18f7ba42008-06-03 10:33:55 -07001143 }
1144 }
1145
1146 if (ap->flags & ATA_FLAG_SW_ACTIVITY)
Tejun Heo1eca4362008-11-03 20:03:17 +09001147 ata_for_each_link(link, ap, EDGE)
Kristen Carlson Accardi18f7ba42008-06-03 10:33:55 -07001148 ahci_init_sw_activity(link);
1149
Tejun Heo0be0aa92006-07-26 15:59:26 +09001150}
1151
Tejun Heo4447d352007-04-17 23:44:08 +09001152static int ahci_deinit_port(struct ata_port *ap, const char **emsg)
Tejun Heo0be0aa92006-07-26 15:59:26 +09001153{
1154 int rc;
1155
1156 /* disable DMA */
Tejun Heo4447d352007-04-17 23:44:08 +09001157 rc = ahci_stop_engine(ap);
Tejun Heo0be0aa92006-07-26 15:59:26 +09001158 if (rc) {
1159 *emsg = "failed to stop engine";
1160 return rc;
1161 }
1162
1163 /* disable FIS reception */
Tejun Heo4447d352007-04-17 23:44:08 +09001164 rc = ahci_stop_fis_rx(ap);
Tejun Heo0be0aa92006-07-26 15:59:26 +09001165 if (rc) {
1166 *emsg = "failed stop FIS RX";
1167 return rc;
1168 }
1169
Tejun Heo0be0aa92006-07-26 15:59:26 +09001170 return 0;
1171}
1172
Tejun Heo4447d352007-04-17 23:44:08 +09001173static int ahci_reset_controller(struct ata_host *host)
Tejun Heod91542c2006-07-26 15:59:26 +09001174{
Tejun Heo4447d352007-04-17 23:44:08 +09001175 struct pci_dev *pdev = to_pci_dev(host->dev);
Tejun Heo49f29092007-11-19 16:03:44 +09001176 struct ahci_host_priv *hpriv = host->private_data;
Tejun Heo4447d352007-04-17 23:44:08 +09001177 void __iomem *mmio = host->iomap[AHCI_PCI_BAR];
Tejun Heod447df12007-03-18 22:15:33 +09001178 u32 tmp;
Tejun Heod91542c2006-07-26 15:59:26 +09001179
Jeff Garzik3cc3eb12007-09-26 00:02:41 -04001180 /* we must be in AHCI mode, before using anything
1181 * AHCI-specific, such as HOST_RESET.
1182 */
Tejun Heob710a1f2008-01-05 23:11:57 +09001183 ahci_enable_ahci(mmio);
Jeff Garzik3cc3eb12007-09-26 00:02:41 -04001184
1185 /* global controller reset */
Tejun Heoa22e6442008-03-10 10:25:25 +09001186 if (!ahci_skip_host_reset) {
1187 tmp = readl(mmio + HOST_CTL);
1188 if ((tmp & HOST_RESET) == 0) {
1189 writel(tmp | HOST_RESET, mmio + HOST_CTL);
1190 readl(mmio + HOST_CTL); /* flush */
1191 }
Tejun Heod91542c2006-07-26 15:59:26 +09001192
Zhang Rui24920c82008-07-04 13:32:17 +08001193 /*
1194 * to perform host reset, OS should set HOST_RESET
1195 * and poll until this bit is read to be "0".
1196 * reset must complete within 1 second, or
Tejun Heoa22e6442008-03-10 10:25:25 +09001197 * the hardware should be considered fried.
1198 */
Zhang Rui24920c82008-07-04 13:32:17 +08001199 tmp = ata_wait_register(mmio + HOST_CTL, HOST_RESET,
1200 HOST_RESET, 10, 1000);
Tejun Heod91542c2006-07-26 15:59:26 +09001201
Tejun Heoa22e6442008-03-10 10:25:25 +09001202 if (tmp & HOST_RESET) {
1203 dev_printk(KERN_ERR, host->dev,
1204 "controller reset failed (0x%x)\n", tmp);
1205 return -EIO;
1206 }
Tejun Heod91542c2006-07-26 15:59:26 +09001207
Tejun Heoa22e6442008-03-10 10:25:25 +09001208 /* turn on AHCI mode */
1209 ahci_enable_ahci(mmio);
Tejun Heo98fa4b62006-11-02 12:17:23 +09001210
Tejun Heoa22e6442008-03-10 10:25:25 +09001211 /* Some registers might be cleared on reset. Restore
1212 * initial values.
1213 */
1214 ahci_restore_initial_config(host);
1215 } else
1216 dev_printk(KERN_INFO, host->dev,
1217 "skipping global host reset\n");
Tejun Heod91542c2006-07-26 15:59:26 +09001218
1219 if (pdev->vendor == PCI_VENDOR_ID_INTEL) {
1220 u16 tmp16;
1221
1222 /* configure PCS */
1223 pci_read_config_word(pdev, 0x92, &tmp16);
Tejun Heo49f29092007-11-19 16:03:44 +09001224 if ((tmp16 & hpriv->port_map) != hpriv->port_map) {
1225 tmp16 |= hpriv->port_map;
1226 pci_write_config_word(pdev, 0x92, tmp16);
1227 }
Tejun Heod91542c2006-07-26 15:59:26 +09001228 }
1229
1230 return 0;
1231}
1232
Kristen Carlson Accardi18f7ba42008-06-03 10:33:55 -07001233static void ahci_sw_activity(struct ata_link *link)
1234{
1235 struct ata_port *ap = link->ap;
1236 struct ahci_port_priv *pp = ap->private_data;
1237 struct ahci_em_priv *emp = &pp->em_priv[link->pmp];
1238
1239 if (!(link->flags & ATA_LFLAG_SW_ACTIVITY))
1240 return;
1241
1242 emp->activity++;
1243 if (!timer_pending(&emp->timer))
1244 mod_timer(&emp->timer, jiffies + msecs_to_jiffies(10));
1245}
1246
1247static void ahci_sw_activity_blink(unsigned long arg)
1248{
1249 struct ata_link *link = (struct ata_link *)arg;
1250 struct ata_port *ap = link->ap;
1251 struct ahci_port_priv *pp = ap->private_data;
1252 struct ahci_em_priv *emp = &pp->em_priv[link->pmp];
1253 unsigned long led_message = emp->led_state;
1254 u32 activity_led_state;
David Milburneb409632008-10-16 09:26:19 -05001255 unsigned long flags;
Kristen Carlson Accardi18f7ba42008-06-03 10:33:55 -07001256
David Milburn87943ac2008-10-13 14:38:36 -05001257 led_message &= EM_MSG_LED_VALUE;
Kristen Carlson Accardi18f7ba42008-06-03 10:33:55 -07001258 led_message |= ap->port_no | (link->pmp << 8);
1259
1260 /* check to see if we've had activity. If so,
1261 * toggle state of LED and reset timer. If not,
1262 * turn LED to desired idle state.
1263 */
David Milburneb409632008-10-16 09:26:19 -05001264 spin_lock_irqsave(ap->lock, flags);
Kristen Carlson Accardi18f7ba42008-06-03 10:33:55 -07001265 if (emp->saved_activity != emp->activity) {
1266 emp->saved_activity = emp->activity;
1267 /* get the current LED state */
David Milburn87943ac2008-10-13 14:38:36 -05001268 activity_led_state = led_message & EM_MSG_LED_VALUE_ON;
Kristen Carlson Accardi18f7ba42008-06-03 10:33:55 -07001269
1270 if (activity_led_state)
1271 activity_led_state = 0;
1272 else
1273 activity_led_state = 1;
1274
1275 /* clear old state */
David Milburn87943ac2008-10-13 14:38:36 -05001276 led_message &= ~EM_MSG_LED_VALUE_ACTIVITY;
Kristen Carlson Accardi18f7ba42008-06-03 10:33:55 -07001277
1278 /* toggle state */
1279 led_message |= (activity_led_state << 16);
1280 mod_timer(&emp->timer, jiffies + msecs_to_jiffies(100));
1281 } else {
1282 /* switch to idle */
David Milburn87943ac2008-10-13 14:38:36 -05001283 led_message &= ~EM_MSG_LED_VALUE_ACTIVITY;
Kristen Carlson Accardi18f7ba42008-06-03 10:33:55 -07001284 if (emp->blink_policy == BLINK_OFF)
1285 led_message |= (1 << 16);
1286 }
David Milburneb409632008-10-16 09:26:19 -05001287 spin_unlock_irqrestore(ap->lock, flags);
Kristen Carlson Accardi18f7ba42008-06-03 10:33:55 -07001288 ahci_transmit_led_message(ap, led_message, 4);
1289}
1290
1291static void ahci_init_sw_activity(struct ata_link *link)
1292{
1293 struct ata_port *ap = link->ap;
1294 struct ahci_port_priv *pp = ap->private_data;
1295 struct ahci_em_priv *emp = &pp->em_priv[link->pmp];
1296
1297 /* init activity stats, setup timer */
1298 emp->saved_activity = emp->activity = 0;
1299 setup_timer(&emp->timer, ahci_sw_activity_blink, (unsigned long)link);
1300
1301 /* check our blink policy and set flag for link if it's enabled */
1302 if (emp->blink_policy)
1303 link->flags |= ATA_LFLAG_SW_ACTIVITY;
1304}
1305
1306static int ahci_reset_em(struct ata_host *host)
1307{
1308 void __iomem *mmio = host->iomap[AHCI_PCI_BAR];
1309 u32 em_ctl;
1310
1311 em_ctl = readl(mmio + HOST_EM_CTL);
1312 if ((em_ctl & EM_CTL_TM) || (em_ctl & EM_CTL_RST))
1313 return -EINVAL;
1314
1315 writel(em_ctl | EM_CTL_RST, mmio + HOST_EM_CTL);
1316 return 0;
1317}
1318
1319static ssize_t ahci_transmit_led_message(struct ata_port *ap, u32 state,
1320 ssize_t size)
1321{
1322 struct ahci_host_priv *hpriv = ap->host->private_data;
1323 struct ahci_port_priv *pp = ap->private_data;
1324 void __iomem *mmio = ap->host->iomap[AHCI_PCI_BAR];
1325 u32 em_ctl;
1326 u32 message[] = {0, 0};
Linus Torvalds93082f02008-07-25 10:56:36 -07001327 unsigned long flags;
Kristen Carlson Accardi18f7ba42008-06-03 10:33:55 -07001328 int pmp;
1329 struct ahci_em_priv *emp;
1330
1331 /* get the slot number from the message */
David Milburn87943ac2008-10-13 14:38:36 -05001332 pmp = (state & EM_MSG_LED_PMP_SLOT) >> 8;
Kristen Carlson Accardi18f7ba42008-06-03 10:33:55 -07001333 if (pmp < MAX_SLOTS)
1334 emp = &pp->em_priv[pmp];
1335 else
1336 return -EINVAL;
1337
1338 spin_lock_irqsave(ap->lock, flags);
1339
1340 /*
1341 * if we are still busy transmitting a previous message,
1342 * do not allow
1343 */
1344 em_ctl = readl(mmio + HOST_EM_CTL);
1345 if (em_ctl & EM_CTL_TM) {
1346 spin_unlock_irqrestore(ap->lock, flags);
David Milburn4c1e9aa2009-04-03 15:36:41 -05001347 return -EBUSY;
Kristen Carlson Accardi18f7ba42008-06-03 10:33:55 -07001348 }
1349
1350 /*
1351 * create message header - this is all zero except for
1352 * the message size, which is 4 bytes.
1353 */
1354 message[0] |= (4 << 8);
1355
1356 /* ignore 0:4 of byte zero, fill in port info yourself */
David Milburn87943ac2008-10-13 14:38:36 -05001357 message[1] = ((state & ~EM_MSG_LED_HBA_PORT) | ap->port_no);
Kristen Carlson Accardi18f7ba42008-06-03 10:33:55 -07001358
1359 /* write message to EM_LOC */
1360 writel(message[0], mmio + hpriv->em_loc);
1361 writel(message[1], mmio + hpriv->em_loc+4);
1362
1363 /* save off new led state for port/slot */
David Milburn208f2a82009-03-20 14:14:23 -05001364 emp->led_state = state;
Kristen Carlson Accardi18f7ba42008-06-03 10:33:55 -07001365
1366 /*
1367 * tell hardware to transmit the message
1368 */
1369 writel(em_ctl | EM_CTL_TM, mmio + HOST_EM_CTL);
1370
1371 spin_unlock_irqrestore(ap->lock, flags);
1372 return size;
1373}
1374
1375static ssize_t ahci_led_show(struct ata_port *ap, char *buf)
1376{
1377 struct ahci_port_priv *pp = ap->private_data;
1378 struct ata_link *link;
1379 struct ahci_em_priv *emp;
1380 int rc = 0;
1381
Tejun Heo1eca4362008-11-03 20:03:17 +09001382 ata_for_each_link(link, ap, EDGE) {
Kristen Carlson Accardi18f7ba42008-06-03 10:33:55 -07001383 emp = &pp->em_priv[link->pmp];
1384 rc += sprintf(buf, "%lx\n", emp->led_state);
1385 }
1386 return rc;
1387}
1388
1389static ssize_t ahci_led_store(struct ata_port *ap, const char *buf,
1390 size_t size)
1391{
1392 int state;
1393 int pmp;
1394 struct ahci_port_priv *pp = ap->private_data;
1395 struct ahci_em_priv *emp;
1396
1397 state = simple_strtoul(buf, NULL, 0);
1398
1399 /* get the slot number from the message */
David Milburn87943ac2008-10-13 14:38:36 -05001400 pmp = (state & EM_MSG_LED_PMP_SLOT) >> 8;
Kristen Carlson Accardi18f7ba42008-06-03 10:33:55 -07001401 if (pmp < MAX_SLOTS)
1402 emp = &pp->em_priv[pmp];
1403 else
1404 return -EINVAL;
1405
1406 /* mask off the activity bits if we are in sw_activity
1407 * mode, user should turn off sw_activity before setting
1408 * activity led through em_message
1409 */
1410 if (emp->blink_policy)
David Milburn87943ac2008-10-13 14:38:36 -05001411 state &= ~EM_MSG_LED_VALUE_ACTIVITY;
Kristen Carlson Accardi18f7ba42008-06-03 10:33:55 -07001412
1413 return ahci_transmit_led_message(ap, state, size);
1414}
1415
1416static ssize_t ahci_activity_store(struct ata_device *dev, enum sw_activity val)
1417{
1418 struct ata_link *link = dev->link;
1419 struct ata_port *ap = link->ap;
1420 struct ahci_port_priv *pp = ap->private_data;
1421 struct ahci_em_priv *emp = &pp->em_priv[link->pmp];
1422 u32 port_led_state = emp->led_state;
1423
1424 /* save the desired Activity LED behavior */
1425 if (val == OFF) {
1426 /* clear LFLAG */
1427 link->flags &= ~(ATA_LFLAG_SW_ACTIVITY);
1428
1429 /* set the LED to OFF */
David Milburn87943ac2008-10-13 14:38:36 -05001430 port_led_state &= EM_MSG_LED_VALUE_OFF;
Kristen Carlson Accardi18f7ba42008-06-03 10:33:55 -07001431 port_led_state |= (ap->port_no | (link->pmp << 8));
1432 ahci_transmit_led_message(ap, port_led_state, 4);
1433 } else {
1434 link->flags |= ATA_LFLAG_SW_ACTIVITY;
1435 if (val == BLINK_OFF) {
1436 /* set LED to ON for idle */
David Milburn87943ac2008-10-13 14:38:36 -05001437 port_led_state &= EM_MSG_LED_VALUE_OFF;
Kristen Carlson Accardi18f7ba42008-06-03 10:33:55 -07001438 port_led_state |= (ap->port_no | (link->pmp << 8));
David Milburn87943ac2008-10-13 14:38:36 -05001439 port_led_state |= EM_MSG_LED_VALUE_ON; /* check this */
Kristen Carlson Accardi18f7ba42008-06-03 10:33:55 -07001440 ahci_transmit_led_message(ap, port_led_state, 4);
1441 }
1442 }
1443 emp->blink_policy = val;
1444 return 0;
1445}
1446
1447static ssize_t ahci_activity_show(struct ata_device *dev, char *buf)
1448{
1449 struct ata_link *link = dev->link;
1450 struct ata_port *ap = link->ap;
1451 struct ahci_port_priv *pp = ap->private_data;
1452 struct ahci_em_priv *emp = &pp->em_priv[link->pmp];
1453
1454 /* display the saved value of activity behavior for this
1455 * disk.
1456 */
1457 return sprintf(buf, "%d\n", emp->blink_policy);
1458}
1459
Jeff Garzik2bcd8662007-05-28 07:45:27 -04001460static void ahci_port_init(struct pci_dev *pdev, struct ata_port *ap,
1461 int port_no, void __iomem *mmio,
1462 void __iomem *port_mmio)
1463{
1464 const char *emsg = NULL;
1465 int rc;
1466 u32 tmp;
1467
1468 /* make sure port is not active */
1469 rc = ahci_deinit_port(ap, &emsg);
1470 if (rc)
1471 dev_printk(KERN_WARNING, &pdev->dev,
1472 "%s (%d)\n", emsg, rc);
1473
1474 /* clear SError */
1475 tmp = readl(port_mmio + PORT_SCR_ERR);
1476 VPRINTK("PORT_SCR_ERR 0x%x\n", tmp);
1477 writel(tmp, port_mmio + PORT_SCR_ERR);
1478
1479 /* clear port IRQ */
1480 tmp = readl(port_mmio + PORT_IRQ_STAT);
1481 VPRINTK("PORT_IRQ_STAT 0x%x\n", tmp);
1482 if (tmp)
1483 writel(tmp, port_mmio + PORT_IRQ_STAT);
1484
1485 writel(1 << port_no, mmio + HOST_IRQ_STAT);
1486}
1487
Tejun Heo4447d352007-04-17 23:44:08 +09001488static void ahci_init_controller(struct ata_host *host)
Tejun Heod91542c2006-07-26 15:59:26 +09001489{
Tejun Heo417a1a62007-09-23 13:19:55 +09001490 struct ahci_host_priv *hpriv = host->private_data;
Tejun Heo4447d352007-04-17 23:44:08 +09001491 struct pci_dev *pdev = to_pci_dev(host->dev);
1492 void __iomem *mmio = host->iomap[AHCI_PCI_BAR];
Jeff Garzik2bcd8662007-05-28 07:45:27 -04001493 int i;
Jeff Garzikcd70c262007-07-08 02:29:42 -04001494 void __iomem *port_mmio;
Tejun Heod91542c2006-07-26 15:59:26 +09001495 u32 tmp;
Jose Alberto Regueroc40e7cb2008-03-13 23:22:24 +01001496 int mv;
Tejun Heod91542c2006-07-26 15:59:26 +09001497
Tejun Heo417a1a62007-09-23 13:19:55 +09001498 if (hpriv->flags & AHCI_HFLAG_MV_PATA) {
Jose Alberto Regueroc40e7cb2008-03-13 23:22:24 +01001499 if (pdev->device == 0x6121)
1500 mv = 2;
1501 else
1502 mv = 4;
1503 port_mmio = __ahci_port_base(host, mv);
Jeff Garzikcd70c262007-07-08 02:29:42 -04001504
1505 writel(0, port_mmio + PORT_IRQ_MASK);
1506
1507 /* clear port IRQ */
1508 tmp = readl(port_mmio + PORT_IRQ_STAT);
1509 VPRINTK("PORT_IRQ_STAT 0x%x\n", tmp);
1510 if (tmp)
1511 writel(tmp, port_mmio + PORT_IRQ_STAT);
1512 }
1513
Tejun Heo4447d352007-04-17 23:44:08 +09001514 for (i = 0; i < host->n_ports; i++) {
1515 struct ata_port *ap = host->ports[i];
Tejun Heod91542c2006-07-26 15:59:26 +09001516
Jeff Garzikcd70c262007-07-08 02:29:42 -04001517 port_mmio = ahci_port_base(ap);
Tejun Heo4447d352007-04-17 23:44:08 +09001518 if (ata_port_is_dummy(ap))
Tejun Heod91542c2006-07-26 15:59:26 +09001519 continue;
Tejun Heod91542c2006-07-26 15:59:26 +09001520
Jeff Garzik2bcd8662007-05-28 07:45:27 -04001521 ahci_port_init(pdev, ap, i, mmio, port_mmio);
Tejun Heod91542c2006-07-26 15:59:26 +09001522 }
1523
1524 tmp = readl(mmio + HOST_CTL);
1525 VPRINTK("HOST_CTL 0x%x\n", tmp);
1526 writel(tmp | HOST_IRQ_EN, mmio + HOST_CTL);
1527 tmp = readl(mmio + HOST_CTL);
1528 VPRINTK("HOST_CTL 0x%x\n", tmp);
1529}
1530
Jeff Garzika8785392008-02-28 15:43:48 -05001531static void ahci_dev_config(struct ata_device *dev)
1532{
1533 struct ahci_host_priv *hpriv = dev->link->ap->host->private_data;
1534
Jeff Garzik4cde32f2008-03-24 22:40:40 -04001535 if (hpriv->flags & AHCI_HFLAG_SECT255) {
Jeff Garzika8785392008-02-28 15:43:48 -05001536 dev->max_sectors = 255;
Jeff Garzik4cde32f2008-03-24 22:40:40 -04001537 ata_dev_printk(dev, KERN_INFO,
1538 "SB600 AHCI: limiting to 255 sectors per cmd\n");
1539 }
Jeff Garzika8785392008-02-28 15:43:48 -05001540}
1541
Tejun Heo422b7592005-12-19 22:37:17 +09001542static unsigned int ahci_dev_classify(struct ata_port *ap)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001543{
Tejun Heo4447d352007-04-17 23:44:08 +09001544 void __iomem *port_mmio = ahci_port_base(ap);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001545 struct ata_taskfile tf;
Tejun Heo422b7592005-12-19 22:37:17 +09001546 u32 tmp;
1547
1548 tmp = readl(port_mmio + PORT_SIG);
1549 tf.lbah = (tmp >> 24) & 0xff;
1550 tf.lbam = (tmp >> 16) & 0xff;
1551 tf.lbal = (tmp >> 8) & 0xff;
1552 tf.nsect = (tmp) & 0xff;
1553
1554 return ata_dev_classify(&tf);
1555}
1556
Tejun Heo12fad3f2006-05-15 21:03:55 +09001557static void ahci_fill_cmd_slot(struct ahci_port_priv *pp, unsigned int tag,
1558 u32 opts)
Tejun Heocc9278e2006-02-10 17:25:47 +09001559{
Tejun Heo12fad3f2006-05-15 21:03:55 +09001560 dma_addr_t cmd_tbl_dma;
1561
1562 cmd_tbl_dma = pp->cmd_tbl_dma + tag * AHCI_CMD_TBL_SZ;
1563
1564 pp->cmd_slot[tag].opts = cpu_to_le32(opts);
1565 pp->cmd_slot[tag].status = 0;
1566 pp->cmd_slot[tag].tbl_addr = cpu_to_le32(cmd_tbl_dma & 0xffffffff);
1567 pp->cmd_slot[tag].tbl_addr_hi = cpu_to_le32((cmd_tbl_dma >> 16) >> 16);
Tejun Heocc9278e2006-02-10 17:25:47 +09001568}
1569
Tejun Heod2e75df2007-07-16 14:29:39 +09001570static int ahci_kick_engine(struct ata_port *ap, int force_restart)
Bastiaan Jacquesbf2af2a2006-04-17 14:17:59 +02001571{
Tejun Heo350756f2008-04-07 22:47:21 +09001572 void __iomem *port_mmio = ahci_port_base(ap);
Jeff Garzikcca39742006-08-24 03:19:22 -04001573 struct ahci_host_priv *hpriv = ap->host->private_data;
Tejun Heo520d06f2008-04-07 22:47:21 +09001574 u8 status = readl(port_mmio + PORT_TFDATA) & 0xFF;
Bastiaan Jacquesbf2af2a2006-04-17 14:17:59 +02001575 u32 tmp;
Tejun Heod2e75df2007-07-16 14:29:39 +09001576 int busy, rc;
Bastiaan Jacquesbf2af2a2006-04-17 14:17:59 +02001577
Tejun Heod2e75df2007-07-16 14:29:39 +09001578 /* do we need to kick the port? */
Tejun Heo520d06f2008-04-07 22:47:21 +09001579 busy = status & (ATA_BUSY | ATA_DRQ);
Tejun Heod2e75df2007-07-16 14:29:39 +09001580 if (!busy && !force_restart)
1581 return 0;
Bastiaan Jacquesbf2af2a2006-04-17 14:17:59 +02001582
Tejun Heod2e75df2007-07-16 14:29:39 +09001583 /* stop engine */
1584 rc = ahci_stop_engine(ap);
1585 if (rc)
1586 goto out_restart;
1587
1588 /* need to do CLO? */
1589 if (!busy) {
1590 rc = 0;
1591 goto out_restart;
1592 }
1593
1594 if (!(hpriv->cap & HOST_CAP_CLO)) {
1595 rc = -EOPNOTSUPP;
1596 goto out_restart;
1597 }
1598
1599 /* perform CLO */
Bastiaan Jacquesbf2af2a2006-04-17 14:17:59 +02001600 tmp = readl(port_mmio + PORT_CMD);
1601 tmp |= PORT_CMD_CLO;
1602 writel(tmp, port_mmio + PORT_CMD);
1603
Tejun Heod2e75df2007-07-16 14:29:39 +09001604 rc = 0;
Bastiaan Jacquesbf2af2a2006-04-17 14:17:59 +02001605 tmp = ata_wait_register(port_mmio + PORT_CMD,
1606 PORT_CMD_CLO, PORT_CMD_CLO, 1, 500);
1607 if (tmp & PORT_CMD_CLO)
Tejun Heod2e75df2007-07-16 14:29:39 +09001608 rc = -EIO;
Bastiaan Jacquesbf2af2a2006-04-17 14:17:59 +02001609
Tejun Heod2e75df2007-07-16 14:29:39 +09001610 /* restart engine */
1611 out_restart:
1612 ahci_start_engine(ap);
1613 return rc;
Bastiaan Jacquesbf2af2a2006-04-17 14:17:59 +02001614}
1615
Tejun Heo91c4a2e2007-07-16 14:29:39 +09001616static int ahci_exec_polled_cmd(struct ata_port *ap, int pmp,
1617 struct ata_taskfile *tf, int is_cmd, u16 flags,
1618 unsigned long timeout_msec)
1619{
1620 const u32 cmd_fis_len = 5; /* five dwords */
1621 struct ahci_port_priv *pp = ap->private_data;
1622 void __iomem *port_mmio = ahci_port_base(ap);
1623 u8 *fis = pp->cmd_tbl;
1624 u32 tmp;
1625
1626 /* prep the command */
1627 ata_tf_to_fis(tf, pmp, is_cmd, fis);
1628 ahci_fill_cmd_slot(pp, 0, cmd_fis_len | flags | (pmp << 12));
1629
1630 /* issue & wait */
1631 writel(1, port_mmio + PORT_CMD_ISSUE);
1632
1633 if (timeout_msec) {
1634 tmp = ata_wait_register(port_mmio + PORT_CMD_ISSUE, 0x1, 0x1,
1635 1, timeout_msec);
1636 if (tmp & 0x1) {
1637 ahci_kick_engine(ap, 1);
1638 return -EBUSY;
1639 }
1640 } else
1641 readl(port_mmio + PORT_CMD_ISSUE); /* flush */
1642
1643 return 0;
1644}
1645
Shane Huangbd172432008-06-10 15:52:04 +08001646static int ahci_do_softreset(struct ata_link *link, unsigned int *class,
1647 int pmp, unsigned long deadline,
1648 int (*check_ready)(struct ata_link *link))
Tejun Heo4658f792006-03-22 21:07:03 +09001649{
Tejun Heocc0680a2007-08-06 18:36:23 +09001650 struct ata_port *ap = link->ap;
Tejun Heo4658f792006-03-22 21:07:03 +09001651 const char *reason = NULL;
Tejun Heo2cbb79e2007-07-16 14:29:38 +09001652 unsigned long now, msecs;
Tejun Heo4658f792006-03-22 21:07:03 +09001653 struct ata_taskfile tf;
Tejun Heo4658f792006-03-22 21:07:03 +09001654 int rc;
1655
1656 DPRINTK("ENTER\n");
1657
1658 /* prepare for SRST (AHCI-1.1 10.4.1) */
Tejun Heod2e75df2007-07-16 14:29:39 +09001659 rc = ahci_kick_engine(ap, 1);
Tejun Heo994056d2007-12-06 15:02:48 +09001660 if (rc && rc != -EOPNOTSUPP)
Tejun Heocc0680a2007-08-06 18:36:23 +09001661 ata_link_printk(link, KERN_WARNING,
Tejun Heo994056d2007-12-06 15:02:48 +09001662 "failed to reset engine (errno=%d)\n", rc);
Tejun Heo4658f792006-03-22 21:07:03 +09001663
Tejun Heocc0680a2007-08-06 18:36:23 +09001664 ata_tf_init(link->device, &tf);
Tejun Heo4658f792006-03-22 21:07:03 +09001665
1666 /* issue the first D2H Register FIS */
Tejun Heo2cbb79e2007-07-16 14:29:38 +09001667 msecs = 0;
1668 now = jiffies;
1669 if (time_after(now, deadline))
1670 msecs = jiffies_to_msecs(deadline - now);
1671
Tejun Heo4658f792006-03-22 21:07:03 +09001672 tf.ctl |= ATA_SRST;
Tejun Heoa9cf5e82007-07-16 14:29:39 +09001673 if (ahci_exec_polled_cmd(ap, pmp, &tf, 0,
Tejun Heo91c4a2e2007-07-16 14:29:39 +09001674 AHCI_CMD_RESET | AHCI_CMD_CLR_BUSY, msecs)) {
Tejun Heo4658f792006-03-22 21:07:03 +09001675 rc = -EIO;
1676 reason = "1st FIS failed";
1677 goto fail;
1678 }
1679
1680 /* spec says at least 5us, but be generous and sleep for 1ms */
1681 msleep(1);
1682
1683 /* issue the second D2H Register FIS */
Tejun Heo4658f792006-03-22 21:07:03 +09001684 tf.ctl &= ~ATA_SRST;
Tejun Heoa9cf5e82007-07-16 14:29:39 +09001685 ahci_exec_polled_cmd(ap, pmp, &tf, 0, 0, 0);
Tejun Heo4658f792006-03-22 21:07:03 +09001686
Tejun Heo705e76b2008-04-07 22:47:19 +09001687 /* wait for link to become ready */
Shane Huangbd172432008-06-10 15:52:04 +08001688 rc = ata_wait_after_reset(link, deadline, check_ready);
Tejun Heo9b893912007-02-02 16:50:52 +09001689 /* link occupied, -ENODEV too is an error */
1690 if (rc) {
1691 reason = "device not ready";
1692 goto fail;
Tejun Heo4658f792006-03-22 21:07:03 +09001693 }
Tejun Heo9b893912007-02-02 16:50:52 +09001694 *class = ahci_dev_classify(ap);
Tejun Heo4658f792006-03-22 21:07:03 +09001695
1696 DPRINTK("EXIT, class=%u\n", *class);
1697 return 0;
1698
Tejun Heo4658f792006-03-22 21:07:03 +09001699 fail:
Tejun Heocc0680a2007-08-06 18:36:23 +09001700 ata_link_printk(link, KERN_ERR, "softreset failed (%s)\n", reason);
Tejun Heo4658f792006-03-22 21:07:03 +09001701 return rc;
1702}
1703
Shane Huangbd172432008-06-10 15:52:04 +08001704static int ahci_check_ready(struct ata_link *link)
1705{
1706 void __iomem *port_mmio = ahci_port_base(link->ap);
1707 u8 status = readl(port_mmio + PORT_TFDATA) & 0xFF;
1708
1709 return ata_check_ready(status);
1710}
1711
1712static int ahci_softreset(struct ata_link *link, unsigned int *class,
1713 unsigned long deadline)
1714{
1715 int pmp = sata_srst_pmp(link);
1716
1717 DPRINTK("ENTER\n");
1718
1719 return ahci_do_softreset(link, class, pmp, deadline, ahci_check_ready);
1720}
1721
1722static int ahci_sb600_check_ready(struct ata_link *link)
1723{
1724 void __iomem *port_mmio = ahci_port_base(link->ap);
1725 u8 status = readl(port_mmio + PORT_TFDATA) & 0xFF;
1726 u32 irq_status = readl(port_mmio + PORT_IRQ_STAT);
1727
1728 /*
1729 * There is no need to check TFDATA if BAD PMP is found due to HW bug,
1730 * which can save timeout delay.
1731 */
1732 if (irq_status & PORT_IRQ_BAD_PMP)
1733 return -EIO;
1734
1735 return ata_check_ready(status);
1736}
1737
1738static int ahci_sb600_softreset(struct ata_link *link, unsigned int *class,
1739 unsigned long deadline)
1740{
1741 struct ata_port *ap = link->ap;
1742 void __iomem *port_mmio = ahci_port_base(ap);
1743 int pmp = sata_srst_pmp(link);
1744 int rc;
1745 u32 irq_sts;
1746
1747 DPRINTK("ENTER\n");
1748
1749 rc = ahci_do_softreset(link, class, pmp, deadline,
1750 ahci_sb600_check_ready);
1751
1752 /*
1753 * Soft reset fails on some ATI chips with IPMS set when PMP
1754 * is enabled but SATA HDD/ODD is connected to SATA port,
1755 * do soft reset again to port 0.
1756 */
1757 if (rc == -EIO) {
1758 irq_sts = readl(port_mmio + PORT_IRQ_STAT);
1759 if (irq_sts & PORT_IRQ_BAD_PMP) {
1760 ata_link_printk(link, KERN_WARNING,
1761 "failed due to HW bug, retry pmp=0\n");
1762 rc = ahci_do_softreset(link, class, 0, deadline,
1763 ahci_check_ready);
1764 }
1765 }
1766
1767 return rc;
1768}
1769
Tejun Heocc0680a2007-08-06 18:36:23 +09001770static int ahci_hardreset(struct ata_link *link, unsigned int *class,
Tejun Heod4b2bab2007-02-02 16:50:52 +09001771 unsigned long deadline)
Tejun Heo422b7592005-12-19 22:37:17 +09001772{
Tejun Heo9dadd452008-04-07 22:47:19 +09001773 const unsigned long *timing = sata_ehc_deb_timing(&link->eh_context);
Tejun Heocc0680a2007-08-06 18:36:23 +09001774 struct ata_port *ap = link->ap;
Tejun Heo42969712006-05-31 18:28:18 +09001775 struct ahci_port_priv *pp = ap->private_data;
1776 u8 *d2h_fis = pp->rx_fis + RX_FIS_D2H_REG;
1777 struct ata_taskfile tf;
Tejun Heo9dadd452008-04-07 22:47:19 +09001778 bool online;
Tejun Heo4bd00f62006-02-11 16:26:02 +09001779 int rc;
1780
1781 DPRINTK("ENTER\n");
Linus Torvalds1da177e2005-04-16 15:20:36 -07001782
Tejun Heo4447d352007-04-17 23:44:08 +09001783 ahci_stop_engine(ap);
Tejun Heo42969712006-05-31 18:28:18 +09001784
1785 /* clear D2H reception area to properly wait for D2H FIS */
Tejun Heocc0680a2007-08-06 18:36:23 +09001786 ata_tf_init(link->device, &tf);
Tejun Heodfd7a3d2007-01-26 15:37:20 +09001787 tf.command = 0x80;
Tejun Heo99771262007-07-16 14:29:38 +09001788 ata_tf_to_fis(&tf, 0, 0, d2h_fis);
Tejun Heo42969712006-05-31 18:28:18 +09001789
Tejun Heo9dadd452008-04-07 22:47:19 +09001790 rc = sata_link_hardreset(link, timing, deadline, &online,
1791 ahci_check_ready);
Tejun Heo42969712006-05-31 18:28:18 +09001792
Tejun Heo4447d352007-04-17 23:44:08 +09001793 ahci_start_engine(ap);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001794
Tejun Heo9dadd452008-04-07 22:47:19 +09001795 if (online)
Tejun Heo4bd00f62006-02-11 16:26:02 +09001796 *class = ahci_dev_classify(ap);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001797
Tejun Heo4bd00f62006-02-11 16:26:02 +09001798 DPRINTK("EXIT, rc=%d, class=%u\n", rc, *class);
1799 return rc;
1800}
1801
Tejun Heocc0680a2007-08-06 18:36:23 +09001802static int ahci_vt8251_hardreset(struct ata_link *link, unsigned int *class,
Tejun Heod4b2bab2007-02-02 16:50:52 +09001803 unsigned long deadline)
Tejun Heoad616ff2006-11-01 18:00:24 +09001804{
Tejun Heocc0680a2007-08-06 18:36:23 +09001805 struct ata_port *ap = link->ap;
Tejun Heo9dadd452008-04-07 22:47:19 +09001806 bool online;
Tejun Heoad616ff2006-11-01 18:00:24 +09001807 int rc;
1808
1809 DPRINTK("ENTER\n");
1810
Tejun Heo4447d352007-04-17 23:44:08 +09001811 ahci_stop_engine(ap);
Tejun Heoad616ff2006-11-01 18:00:24 +09001812
Tejun Heocc0680a2007-08-06 18:36:23 +09001813 rc = sata_link_hardreset(link, sata_ehc_deb_timing(&link->eh_context),
Tejun Heo9dadd452008-04-07 22:47:19 +09001814 deadline, &online, NULL);
Tejun Heoad616ff2006-11-01 18:00:24 +09001815
Tejun Heo4447d352007-04-17 23:44:08 +09001816 ahci_start_engine(ap);
Tejun Heoad616ff2006-11-01 18:00:24 +09001817
1818 DPRINTK("EXIT, rc=%d, class=%u\n", rc, *class);
1819
1820 /* vt8251 doesn't clear BSY on signature FIS reception,
1821 * request follow-up softreset.
1822 */
Tejun Heo9dadd452008-04-07 22:47:19 +09001823 return online ? -EAGAIN : rc;
Tejun Heoad616ff2006-11-01 18:00:24 +09001824}
1825
Tejun Heoedc93052007-10-25 14:59:16 +09001826static int ahci_p5wdh_hardreset(struct ata_link *link, unsigned int *class,
1827 unsigned long deadline)
1828{
1829 struct ata_port *ap = link->ap;
1830 struct ahci_port_priv *pp = ap->private_data;
1831 u8 *d2h_fis = pp->rx_fis + RX_FIS_D2H_REG;
1832 struct ata_taskfile tf;
Tejun Heo9dadd452008-04-07 22:47:19 +09001833 bool online;
Tejun Heoedc93052007-10-25 14:59:16 +09001834 int rc;
1835
1836 ahci_stop_engine(ap);
1837
1838 /* clear D2H reception area to properly wait for D2H FIS */
1839 ata_tf_init(link->device, &tf);
1840 tf.command = 0x80;
1841 ata_tf_to_fis(&tf, 0, 0, d2h_fis);
1842
1843 rc = sata_link_hardreset(link, sata_ehc_deb_timing(&link->eh_context),
Tejun Heo9dadd452008-04-07 22:47:19 +09001844 deadline, &online, NULL);
Tejun Heoedc93052007-10-25 14:59:16 +09001845
1846 ahci_start_engine(ap);
1847
Tejun Heoedc93052007-10-25 14:59:16 +09001848 /* The pseudo configuration device on SIMG4726 attached to
1849 * ASUS P5W-DH Deluxe doesn't send signature FIS after
1850 * hardreset if no device is attached to the first downstream
1851 * port && the pseudo device locks up on SRST w/ PMP==0. To
1852 * work around this, wait for !BSY only briefly. If BSY isn't
1853 * cleared, perform CLO and proceed to IDENTIFY (achieved by
1854 * ATA_LFLAG_NO_SRST and ATA_LFLAG_ASSUME_ATA).
1855 *
1856 * Wait for two seconds. Devices attached to downstream port
1857 * which can't process the following IDENTIFY after this will
1858 * have to be reset again. For most cases, this should
1859 * suffice while making probing snappish enough.
1860 */
Tejun Heo9dadd452008-04-07 22:47:19 +09001861 if (online) {
1862 rc = ata_wait_after_reset(link, jiffies + 2 * HZ,
1863 ahci_check_ready);
1864 if (rc)
1865 ahci_kick_engine(ap, 0);
1866 }
Tejun Heo9dadd452008-04-07 22:47:19 +09001867 return rc;
Tejun Heoedc93052007-10-25 14:59:16 +09001868}
1869
Tejun Heocc0680a2007-08-06 18:36:23 +09001870static void ahci_postreset(struct ata_link *link, unsigned int *class)
Tejun Heo4bd00f62006-02-11 16:26:02 +09001871{
Tejun Heocc0680a2007-08-06 18:36:23 +09001872 struct ata_port *ap = link->ap;
Tejun Heo4447d352007-04-17 23:44:08 +09001873 void __iomem *port_mmio = ahci_port_base(ap);
Tejun Heo4bd00f62006-02-11 16:26:02 +09001874 u32 new_tmp, tmp;
1875
Tejun Heo203c75b2008-04-07 22:47:18 +09001876 ata_std_postreset(link, class);
Jeff Garzik02eaa662005-11-12 01:32:19 -05001877
1878 /* Make sure port's ATAPI bit is set appropriately */
1879 new_tmp = tmp = readl(port_mmio + PORT_CMD);
Tejun Heo4bd00f62006-02-11 16:26:02 +09001880 if (*class == ATA_DEV_ATAPI)
Jeff Garzik02eaa662005-11-12 01:32:19 -05001881 new_tmp |= PORT_CMD_ATAPI;
1882 else
1883 new_tmp &= ~PORT_CMD_ATAPI;
1884 if (new_tmp != tmp) {
1885 writel(new_tmp, port_mmio + PORT_CMD);
1886 readl(port_mmio + PORT_CMD); /* flush */
1887 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07001888}
1889
Tejun Heo12fad3f2006-05-15 21:03:55 +09001890static unsigned int ahci_fill_sg(struct ata_queued_cmd *qc, void *cmd_tbl)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001891{
Jeff Garzikcedc9a42005-10-05 07:13:30 -04001892 struct scatterlist *sg;
Tejun Heoff2aeb12007-12-05 16:43:11 +09001893 struct ahci_sg *ahci_sg = cmd_tbl + AHCI_CMD_TBL_HDR_SZ;
1894 unsigned int si;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001895
1896 VPRINTK("ENTER\n");
1897
1898 /*
1899 * Next, the S/G list.
1900 */
Tejun Heoff2aeb12007-12-05 16:43:11 +09001901 for_each_sg(qc->sg, sg, qc->n_elem, si) {
Jeff Garzikcedc9a42005-10-05 07:13:30 -04001902 dma_addr_t addr = sg_dma_address(sg);
1903 u32 sg_len = sg_dma_len(sg);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001904
Tejun Heoff2aeb12007-12-05 16:43:11 +09001905 ahci_sg[si].addr = cpu_to_le32(addr & 0xffffffff);
1906 ahci_sg[si].addr_hi = cpu_to_le32((addr >> 16) >> 16);
1907 ahci_sg[si].flags_size = cpu_to_le32(sg_len - 1);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001908 }
Jeff Garzik828d09d2005-11-12 01:27:07 -05001909
Tejun Heoff2aeb12007-12-05 16:43:11 +09001910 return si;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001911}
1912
1913static void ahci_qc_prep(struct ata_queued_cmd *qc)
1914{
Jeff Garzika0ea7322005-06-04 01:13:15 -04001915 struct ata_port *ap = qc->ap;
1916 struct ahci_port_priv *pp = ap->private_data;
Tejun Heo405e66b2007-11-27 19:28:53 +09001917 int is_atapi = ata_is_atapi(qc->tf.protocol);
Tejun Heo12fad3f2006-05-15 21:03:55 +09001918 void *cmd_tbl;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001919 u32 opts;
1920 const u32 cmd_fis_len = 5; /* five dwords */
Jeff Garzik828d09d2005-11-12 01:27:07 -05001921 unsigned int n_elem;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001922
1923 /*
Linus Torvalds1da177e2005-04-16 15:20:36 -07001924 * Fill in command table information. First, the header,
1925 * a SATA Register - Host to Device command FIS.
1926 */
Tejun Heo12fad3f2006-05-15 21:03:55 +09001927 cmd_tbl = pp->cmd_tbl + qc->tag * AHCI_CMD_TBL_SZ;
1928
Tejun Heo7d50b602007-09-23 13:19:54 +09001929 ata_tf_to_fis(&qc->tf, qc->dev->link->pmp, 1, cmd_tbl);
Tejun Heocc9278e2006-02-10 17:25:47 +09001930 if (is_atapi) {
Tejun Heo12fad3f2006-05-15 21:03:55 +09001931 memset(cmd_tbl + AHCI_CMD_TBL_CDB, 0, 32);
1932 memcpy(cmd_tbl + AHCI_CMD_TBL_CDB, qc->cdb, qc->dev->cdb_len);
Jeff Garzika0ea7322005-06-04 01:13:15 -04001933 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07001934
Tejun Heocc9278e2006-02-10 17:25:47 +09001935 n_elem = 0;
1936 if (qc->flags & ATA_QCFLAG_DMAMAP)
Tejun Heo12fad3f2006-05-15 21:03:55 +09001937 n_elem = ahci_fill_sg(qc, cmd_tbl);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001938
Tejun Heocc9278e2006-02-10 17:25:47 +09001939 /*
1940 * Fill in command slot information.
1941 */
Tejun Heo7d50b602007-09-23 13:19:54 +09001942 opts = cmd_fis_len | n_elem << 16 | (qc->dev->link->pmp << 12);
Tejun Heocc9278e2006-02-10 17:25:47 +09001943 if (qc->tf.flags & ATA_TFLAG_WRITE)
1944 opts |= AHCI_CMD_WRITE;
1945 if (is_atapi)
Tejun Heo4b10e552006-03-12 11:25:27 +09001946 opts |= AHCI_CMD_ATAPI | AHCI_CMD_PREFETCH;
Jeff Garzik828d09d2005-11-12 01:27:07 -05001947
Tejun Heo12fad3f2006-05-15 21:03:55 +09001948 ahci_fill_cmd_slot(pp, qc->tag, opts);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001949}
1950
Tejun Heo78cd52d2006-05-15 20:58:29 +09001951static void ahci_error_intr(struct ata_port *ap, u32 irq_stat)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001952{
Tejun Heo417a1a62007-09-23 13:19:55 +09001953 struct ahci_host_priv *hpriv = ap->host->private_data;
Tejun Heo78cd52d2006-05-15 20:58:29 +09001954 struct ahci_port_priv *pp = ap->private_data;
Tejun Heo7d50b602007-09-23 13:19:54 +09001955 struct ata_eh_info *host_ehi = &ap->link.eh_info;
1956 struct ata_link *link = NULL;
1957 struct ata_queued_cmd *active_qc;
1958 struct ata_eh_info *active_ehi;
Tejun Heo78cd52d2006-05-15 20:58:29 +09001959 u32 serror;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001960
Tejun Heo7d50b602007-09-23 13:19:54 +09001961 /* determine active link */
Tejun Heo1eca4362008-11-03 20:03:17 +09001962 ata_for_each_link(link, ap, EDGE)
Tejun Heo7d50b602007-09-23 13:19:54 +09001963 if (ata_link_active(link))
1964 break;
1965 if (!link)
1966 link = &ap->link;
1967
1968 active_qc = ata_qc_from_tag(ap, link->active_tag);
1969 active_ehi = &link->eh_info;
1970
1971 /* record irq stat */
1972 ata_ehi_clear_desc(host_ehi);
1973 ata_ehi_push_desc(host_ehi, "irq_stat 0x%08x", irq_stat);
Jeff Garzik9f68a242005-11-15 14:03:47 -05001974
Tejun Heo78cd52d2006-05-15 20:58:29 +09001975 /* AHCI needs SError cleared; otherwise, it might lock up */
Tejun Heo82ef04f2008-07-31 17:02:40 +09001976 ahci_scr_read(&ap->link, SCR_ERROR, &serror);
1977 ahci_scr_write(&ap->link, SCR_ERROR, serror);
Tejun Heo7d50b602007-09-23 13:19:54 +09001978 host_ehi->serror |= serror;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001979
Tejun Heo41669552006-11-29 11:33:14 +09001980 /* some controllers set IRQ_IF_ERR on device errors, ignore it */
Tejun Heo417a1a62007-09-23 13:19:55 +09001981 if (hpriv->flags & AHCI_HFLAG_IGN_IRQ_IF_ERR)
Tejun Heo41669552006-11-29 11:33:14 +09001982 irq_stat &= ~PORT_IRQ_IF_ERR;
1983
Conke Hu55a61602007-03-27 18:33:05 +08001984 if (irq_stat & PORT_IRQ_TF_ERR) {
Tejun Heo7d50b602007-09-23 13:19:54 +09001985 /* If qc is active, charge it; otherwise, the active
1986 * link. There's no active qc on NCQ errors. It will
1987 * be determined by EH by reading log page 10h.
1988 */
1989 if (active_qc)
1990 active_qc->err_mask |= AC_ERR_DEV;
1991 else
1992 active_ehi->err_mask |= AC_ERR_DEV;
1993
Tejun Heo417a1a62007-09-23 13:19:55 +09001994 if (hpriv->flags & AHCI_HFLAG_IGN_SERR_INTERNAL)
Tejun Heo7d50b602007-09-23 13:19:54 +09001995 host_ehi->serror &= ~SERR_INTERNAL;
Tejun Heo78cd52d2006-05-15 20:58:29 +09001996 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07001997
Tejun Heo78cd52d2006-05-15 20:58:29 +09001998 if (irq_stat & PORT_IRQ_UNK_FIS) {
1999 u32 *unk = (u32 *)(pp->rx_fis + RX_FIS_UNK);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002000
Tejun Heo7d50b602007-09-23 13:19:54 +09002001 active_ehi->err_mask |= AC_ERR_HSM;
Tejun Heocf480622008-01-24 00:05:14 +09002002 active_ehi->action |= ATA_EH_RESET;
Tejun Heo7d50b602007-09-23 13:19:54 +09002003 ata_ehi_push_desc(active_ehi,
2004 "unknown FIS %08x %08x %08x %08x" ,
Tejun Heo78cd52d2006-05-15 20:58:29 +09002005 unk[0], unk[1], unk[2], unk[3]);
2006 }
Jeff Garzikb8f61532005-08-25 22:01:20 -04002007
Tejun Heo071f44b2008-04-07 22:47:22 +09002008 if (sata_pmp_attached(ap) && (irq_stat & PORT_IRQ_BAD_PMP)) {
Tejun Heo7d50b602007-09-23 13:19:54 +09002009 active_ehi->err_mask |= AC_ERR_HSM;
Tejun Heocf480622008-01-24 00:05:14 +09002010 active_ehi->action |= ATA_EH_RESET;
Tejun Heo7d50b602007-09-23 13:19:54 +09002011 ata_ehi_push_desc(active_ehi, "incorrect PMP");
2012 }
Tejun Heo78cd52d2006-05-15 20:58:29 +09002013
Tejun Heo7d50b602007-09-23 13:19:54 +09002014 if (irq_stat & (PORT_IRQ_HBUS_ERR | PORT_IRQ_HBUS_DATA_ERR)) {
2015 host_ehi->err_mask |= AC_ERR_HOST_BUS;
Tejun Heocf480622008-01-24 00:05:14 +09002016 host_ehi->action |= ATA_EH_RESET;
Tejun Heo7d50b602007-09-23 13:19:54 +09002017 ata_ehi_push_desc(host_ehi, "host bus error");
2018 }
2019
2020 if (irq_stat & PORT_IRQ_IF_ERR) {
2021 host_ehi->err_mask |= AC_ERR_ATA_BUS;
Tejun Heocf480622008-01-24 00:05:14 +09002022 host_ehi->action |= ATA_EH_RESET;
Tejun Heo7d50b602007-09-23 13:19:54 +09002023 ata_ehi_push_desc(host_ehi, "interface fatal error");
2024 }
2025
2026 if (irq_stat & (PORT_IRQ_CONNECT | PORT_IRQ_PHYRDY)) {
2027 ata_ehi_hotplugged(host_ehi);
2028 ata_ehi_push_desc(host_ehi, "%s",
2029 irq_stat & PORT_IRQ_CONNECT ?
2030 "connection status changed" : "PHY RDY changed");
2031 }
2032
2033 /* okay, let's hand over to EH */
Linus Torvalds1da177e2005-04-16 15:20:36 -07002034
Tejun Heo78cd52d2006-05-15 20:58:29 +09002035 if (irq_stat & PORT_IRQ_FREEZE)
2036 ata_port_freeze(ap);
2037 else
2038 ata_port_abort(ap);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002039}
2040
Jeff Garzikdf69c9c2007-05-26 20:46:51 -04002041static void ahci_port_intr(struct ata_port *ap)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002042{
Tejun Heo350756f2008-04-07 22:47:21 +09002043 void __iomem *port_mmio = ahci_port_base(ap);
Tejun Heo9af5c9c2007-08-06 18:36:22 +09002044 struct ata_eh_info *ehi = &ap->link.eh_info;
Tejun Heo0291f952007-01-25 19:16:28 +09002045 struct ahci_port_priv *pp = ap->private_data;
Tejun Heo5f226c62007-10-09 15:02:23 +09002046 struct ahci_host_priv *hpriv = ap->host->private_data;
Tejun Heob06ce3e2007-10-09 15:06:48 +09002047 int resetting = !!(ap->pflags & ATA_PFLAG_RESETTING);
Tejun Heo12fad3f2006-05-15 21:03:55 +09002048 u32 status, qc_active;
Tejun Heo459ad682007-12-07 12:46:23 +09002049 int rc;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002050
2051 status = readl(port_mmio + PORT_IRQ_STAT);
2052 writel(status, port_mmio + PORT_IRQ_STAT);
2053
Tejun Heob06ce3e2007-10-09 15:06:48 +09002054 /* ignore BAD_PMP while resetting */
2055 if (unlikely(resetting))
2056 status &= ~PORT_IRQ_BAD_PMP;
2057
Kristen Carlson Accardi31556592007-10-25 01:33:26 -04002058 /* If we are getting PhyRdy, this is
2059 * just a power state change, we should
2060 * clear out this, plus the PhyRdy/Comm
2061 * Wake bits from Serror
2062 */
2063 if ((hpriv->flags & AHCI_HFLAG_NO_HOTPLUG) &&
2064 (status & PORT_IRQ_PHYRDY)) {
2065 status &= ~PORT_IRQ_PHYRDY;
Tejun Heo82ef04f2008-07-31 17:02:40 +09002066 ahci_scr_write(&ap->link, SCR_ERROR, ((1 << 16) | (1 << 18)));
Kristen Carlson Accardi31556592007-10-25 01:33:26 -04002067 }
2068
Tejun Heo78cd52d2006-05-15 20:58:29 +09002069 if (unlikely(status & PORT_IRQ_ERROR)) {
2070 ahci_error_intr(ap, status);
2071 return;
2072 }
2073
Kristen Carlson Accardi2f294962007-08-15 04:11:25 -04002074 if (status & PORT_IRQ_SDB_FIS) {
Tejun Heo5f226c62007-10-09 15:02:23 +09002075 /* If SNotification is available, leave notification
2076 * handling to sata_async_notification(). If not,
2077 * emulate it by snooping SDB FIS RX area.
2078 *
2079 * Snooping FIS RX area is probably cheaper than
2080 * poking SNotification but some constrollers which
2081 * implement SNotification, ICH9 for example, don't
2082 * store AN SDB FIS into receive area.
Kristen Carlson Accardi2f294962007-08-15 04:11:25 -04002083 */
Tejun Heo5f226c62007-10-09 15:02:23 +09002084 if (hpriv->cap & HOST_CAP_SNTF)
Tejun Heo7d77b242007-09-23 13:14:13 +09002085 sata_async_notification(ap);
Tejun Heo5f226c62007-10-09 15:02:23 +09002086 else {
2087 /* If the 'N' bit in word 0 of the FIS is set,
2088 * we just received asynchronous notification.
2089 * Tell libata about it.
2090 */
2091 const __le32 *f = pp->rx_fis + RX_FIS_SDB;
2092 u32 f0 = le32_to_cpu(f[0]);
2093
2094 if (f0 & (1 << 15))
2095 sata_async_notification(ap);
2096 }
Kristen Carlson Accardi2f294962007-08-15 04:11:25 -04002097 }
2098
Tejun Heo7d50b602007-09-23 13:19:54 +09002099 /* pp->active_link is valid iff any command is in flight */
2100 if (ap->qc_active && pp->active_link->sactive)
Tejun Heo12fad3f2006-05-15 21:03:55 +09002101 qc_active = readl(port_mmio + PORT_SCR_ACT);
2102 else
2103 qc_active = readl(port_mmio + PORT_CMD_ISSUE);
2104
Tejun Heo79f97da2008-04-07 22:47:20 +09002105 rc = ata_qc_complete_multiple(ap, qc_active);
Tejun Heob06ce3e2007-10-09 15:06:48 +09002106
Tejun Heo459ad682007-12-07 12:46:23 +09002107 /* while resetting, invalid completions are expected */
2108 if (unlikely(rc < 0 && !resetting)) {
Tejun Heo12fad3f2006-05-15 21:03:55 +09002109 ehi->err_mask |= AC_ERR_HSM;
Tejun Heocf480622008-01-24 00:05:14 +09002110 ehi->action |= ATA_EH_RESET;
Tejun Heo12fad3f2006-05-15 21:03:55 +09002111 ata_port_freeze(ap);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002112 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07002113}
2114
David Howells7d12e782006-10-05 14:55:46 +01002115static irqreturn_t ahci_interrupt(int irq, void *dev_instance)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002116{
Jeff Garzikcca39742006-08-24 03:19:22 -04002117 struct ata_host *host = dev_instance;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002118 struct ahci_host_priv *hpriv;
2119 unsigned int i, handled = 0;
Jeff Garzikea6ba102005-08-30 05:18:18 -04002120 void __iomem *mmio;
Tejun Heod28f87a2008-07-05 13:10:50 +09002121 u32 irq_stat, irq_masked;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002122
2123 VPRINTK("ENTER\n");
2124
Jeff Garzikcca39742006-08-24 03:19:22 -04002125 hpriv = host->private_data;
Tejun Heo0d5ff562007-02-01 15:06:36 +09002126 mmio = host->iomap[AHCI_PCI_BAR];
Linus Torvalds1da177e2005-04-16 15:20:36 -07002127
2128 /* sigh. 0xffffffff is a valid return from h/w */
2129 irq_stat = readl(mmio + HOST_IRQ_STAT);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002130 if (!irq_stat)
2131 return IRQ_NONE;
2132
Tejun Heod28f87a2008-07-05 13:10:50 +09002133 irq_masked = irq_stat & hpriv->port_map;
2134
Jeff Garzik2dcb4072007-10-19 06:42:56 -04002135 spin_lock(&host->lock);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002136
Jeff Garzik2dcb4072007-10-19 06:42:56 -04002137 for (i = 0; i < host->n_ports; i++) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07002138 struct ata_port *ap;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002139
Tejun Heod28f87a2008-07-05 13:10:50 +09002140 if (!(irq_masked & (1 << i)))
Jeff Garzik67846b32005-10-05 02:58:32 -04002141 continue;
2142
Jeff Garzikcca39742006-08-24 03:19:22 -04002143 ap = host->ports[i];
Jeff Garzik67846b32005-10-05 02:58:32 -04002144 if (ap) {
Jeff Garzikdf69c9c2007-05-26 20:46:51 -04002145 ahci_port_intr(ap);
Jeff Garzik67846b32005-10-05 02:58:32 -04002146 VPRINTK("port %u\n", i);
2147 } else {
2148 VPRINTK("port %u (no irq)\n", i);
Tejun Heo6971ed12006-03-11 12:47:54 +09002149 if (ata_ratelimit())
Jeff Garzikcca39742006-08-24 03:19:22 -04002150 dev_printk(KERN_WARNING, host->dev,
Jeff Garzika9524a72005-10-30 14:39:11 -05002151 "interrupt on disabled port %u\n", i);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002152 }
Jeff Garzik67846b32005-10-05 02:58:32 -04002153
Linus Torvalds1da177e2005-04-16 15:20:36 -07002154 handled = 1;
2155 }
2156
Tejun Heod28f87a2008-07-05 13:10:50 +09002157 /* HOST_IRQ_STAT behaves as level triggered latch meaning that
2158 * it should be cleared after all the port events are cleared;
2159 * otherwise, it will raise a spurious interrupt after each
2160 * valid one. Please read section 10.6.2 of ahci 1.1 for more
2161 * information.
2162 *
2163 * Also, use the unmasked value to clear interrupt as spurious
2164 * pending event on a dummy port might cause screaming IRQ.
2165 */
Tejun Heoea0c62f2008-06-28 01:49:02 +09002166 writel(irq_stat, mmio + HOST_IRQ_STAT);
2167
Jeff Garzikcca39742006-08-24 03:19:22 -04002168 spin_unlock(&host->lock);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002169
2170 VPRINTK("EXIT\n");
2171
2172 return IRQ_RETVAL(handled);
2173}
2174
Tejun Heo9a3d9eb2006-01-23 13:09:36 +09002175static unsigned int ahci_qc_issue(struct ata_queued_cmd *qc)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002176{
2177 struct ata_port *ap = qc->ap;
Tejun Heo4447d352007-04-17 23:44:08 +09002178 void __iomem *port_mmio = ahci_port_base(ap);
Tejun Heo7d50b602007-09-23 13:19:54 +09002179 struct ahci_port_priv *pp = ap->private_data;
2180
2181 /* Keep track of the currently active link. It will be used
2182 * in completion path to determine whether NCQ phase is in
2183 * progress.
2184 */
2185 pp->active_link = qc->dev->link;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002186
Tejun Heo12fad3f2006-05-15 21:03:55 +09002187 if (qc->tf.protocol == ATA_PROT_NCQ)
2188 writel(1 << qc->tag, port_mmio + PORT_SCR_ACT);
2189 writel(1 << qc->tag, port_mmio + PORT_CMD_ISSUE);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002190
Kristen Carlson Accardi18f7ba42008-06-03 10:33:55 -07002191 ahci_sw_activity(qc->dev->link);
2192
Linus Torvalds1da177e2005-04-16 15:20:36 -07002193 return 0;
2194}
2195
Tejun Heo4c9bf4e2008-04-07 22:47:20 +09002196static bool ahci_qc_fill_rtf(struct ata_queued_cmd *qc)
2197{
2198 struct ahci_port_priv *pp = qc->ap->private_data;
2199 u8 *d2h_fis = pp->rx_fis + RX_FIS_D2H_REG;
2200
2201 ata_tf_from_fis(d2h_fis, &qc->result_tf);
2202 return true;
2203}
2204
Tejun Heo78cd52d2006-05-15 20:58:29 +09002205static void ahci_freeze(struct ata_port *ap)
2206{
Tejun Heo4447d352007-04-17 23:44:08 +09002207 void __iomem *port_mmio = ahci_port_base(ap);
Tejun Heo78cd52d2006-05-15 20:58:29 +09002208
2209 /* turn IRQ off */
2210 writel(0, port_mmio + PORT_IRQ_MASK);
2211}
2212
2213static void ahci_thaw(struct ata_port *ap)
2214{
Tejun Heo0d5ff562007-02-01 15:06:36 +09002215 void __iomem *mmio = ap->host->iomap[AHCI_PCI_BAR];
Tejun Heo4447d352007-04-17 23:44:08 +09002216 void __iomem *port_mmio = ahci_port_base(ap);
Tejun Heo78cd52d2006-05-15 20:58:29 +09002217 u32 tmp;
Kristen Carlson Accardia7384922007-08-09 14:23:41 -07002218 struct ahci_port_priv *pp = ap->private_data;
Tejun Heo78cd52d2006-05-15 20:58:29 +09002219
2220 /* clear IRQ */
2221 tmp = readl(port_mmio + PORT_IRQ_STAT);
2222 writel(tmp, port_mmio + PORT_IRQ_STAT);
Tejun Heoa7187282007-01-27 11:04:26 +09002223 writel(1 << ap->port_no, mmio + HOST_IRQ_STAT);
Tejun Heo78cd52d2006-05-15 20:58:29 +09002224
Tejun Heo1c954a42007-10-09 15:01:37 +09002225 /* turn IRQ back on */
2226 writel(pp->intr_mask, port_mmio + PORT_IRQ_MASK);
Tejun Heo78cd52d2006-05-15 20:58:29 +09002227}
2228
2229static void ahci_error_handler(struct ata_port *ap)
2230{
Tejun Heob51e9e52006-06-29 01:29:30 +09002231 if (!(ap->pflags & ATA_PFLAG_FROZEN)) {
Tejun Heo78cd52d2006-05-15 20:58:29 +09002232 /* restart engine */
Tejun Heo4447d352007-04-17 23:44:08 +09002233 ahci_stop_engine(ap);
2234 ahci_start_engine(ap);
Tejun Heo78cd52d2006-05-15 20:58:29 +09002235 }
2236
Tejun Heoa1efdab2008-03-25 12:22:50 +09002237 sata_pmp_error_handler(ap);
Tejun Heoedc93052007-10-25 14:59:16 +09002238}
2239
Tejun Heo78cd52d2006-05-15 20:58:29 +09002240static void ahci_post_internal_cmd(struct ata_queued_cmd *qc)
2241{
2242 struct ata_port *ap = qc->ap;
2243
Tejun Heod2e75df2007-07-16 14:29:39 +09002244 /* make DMA engine forget about the failed command */
2245 if (qc->flags & ATA_QCFLAG_FAILED)
2246 ahci_kick_engine(ap, 1);
Tejun Heo78cd52d2006-05-15 20:58:29 +09002247}
2248
Tejun Heo7d50b602007-09-23 13:19:54 +09002249static void ahci_pmp_attach(struct ata_port *ap)
2250{
2251 void __iomem *port_mmio = ahci_port_base(ap);
Tejun Heo1c954a42007-10-09 15:01:37 +09002252 struct ahci_port_priv *pp = ap->private_data;
Tejun Heo7d50b602007-09-23 13:19:54 +09002253 u32 cmd;
2254
2255 cmd = readl(port_mmio + PORT_CMD);
2256 cmd |= PORT_CMD_PMP;
2257 writel(cmd, port_mmio + PORT_CMD);
Tejun Heo1c954a42007-10-09 15:01:37 +09002258
2259 pp->intr_mask |= PORT_IRQ_BAD_PMP;
2260 writel(pp->intr_mask, port_mmio + PORT_IRQ_MASK);
Tejun Heo7d50b602007-09-23 13:19:54 +09002261}
2262
2263static void ahci_pmp_detach(struct ata_port *ap)
2264{
2265 void __iomem *port_mmio = ahci_port_base(ap);
Tejun Heo1c954a42007-10-09 15:01:37 +09002266 struct ahci_port_priv *pp = ap->private_data;
Tejun Heo7d50b602007-09-23 13:19:54 +09002267 u32 cmd;
2268
2269 cmd = readl(port_mmio + PORT_CMD);
2270 cmd &= ~PORT_CMD_PMP;
2271 writel(cmd, port_mmio + PORT_CMD);
Tejun Heo1c954a42007-10-09 15:01:37 +09002272
2273 pp->intr_mask &= ~PORT_IRQ_BAD_PMP;
2274 writel(pp->intr_mask, port_mmio + PORT_IRQ_MASK);
Tejun Heo7d50b602007-09-23 13:19:54 +09002275}
2276
Alexey Dobriyan028a2592007-07-17 23:48:48 +04002277static int ahci_port_resume(struct ata_port *ap)
2278{
2279 ahci_power_up(ap);
2280 ahci_start_port(ap);
2281
Tejun Heo071f44b2008-04-07 22:47:22 +09002282 if (sata_pmp_attached(ap))
Tejun Heo7d50b602007-09-23 13:19:54 +09002283 ahci_pmp_attach(ap);
2284 else
2285 ahci_pmp_detach(ap);
2286
Alexey Dobriyan028a2592007-07-17 23:48:48 +04002287 return 0;
2288}
2289
Tejun Heo438ac6d2007-03-02 17:31:26 +09002290#ifdef CONFIG_PM
Tejun Heoc1332872006-07-26 15:59:26 +09002291static int ahci_port_suspend(struct ata_port *ap, pm_message_t mesg)
2292{
Tejun Heoc1332872006-07-26 15:59:26 +09002293 const char *emsg = NULL;
2294 int rc;
2295
Tejun Heo4447d352007-04-17 23:44:08 +09002296 rc = ahci_deinit_port(ap, &emsg);
Tejun Heo8e16f942006-11-20 15:42:36 +09002297 if (rc == 0)
Tejun Heo4447d352007-04-17 23:44:08 +09002298 ahci_power_down(ap);
Tejun Heo8e16f942006-11-20 15:42:36 +09002299 else {
Tejun Heoc1332872006-07-26 15:59:26 +09002300 ata_port_printk(ap, KERN_ERR, "%s (%d)\n", emsg, rc);
Jeff Garzikdf69c9c2007-05-26 20:46:51 -04002301 ahci_start_port(ap);
Tejun Heoc1332872006-07-26 15:59:26 +09002302 }
2303
2304 return rc;
2305}
2306
Tejun Heoc1332872006-07-26 15:59:26 +09002307static int ahci_pci_device_suspend(struct pci_dev *pdev, pm_message_t mesg)
2308{
Jeff Garzikcca39742006-08-24 03:19:22 -04002309 struct ata_host *host = dev_get_drvdata(&pdev->dev);
Tejun Heo0d5ff562007-02-01 15:06:36 +09002310 void __iomem *mmio = host->iomap[AHCI_PCI_BAR];
Tejun Heoc1332872006-07-26 15:59:26 +09002311 u32 ctl;
2312
Rafael J. Wysocki3a2d5b72008-02-23 19:13:25 +01002313 if (mesg.event & PM_EVENT_SLEEP) {
Tejun Heoc1332872006-07-26 15:59:26 +09002314 /* AHCI spec rev1.1 section 8.3.3:
2315 * Software must disable interrupts prior to requesting a
2316 * transition of the HBA to D3 state.
2317 */
2318 ctl = readl(mmio + HOST_CTL);
2319 ctl &= ~HOST_IRQ_EN;
2320 writel(ctl, mmio + HOST_CTL);
2321 readl(mmio + HOST_CTL); /* flush */
2322 }
2323
2324 return ata_pci_device_suspend(pdev, mesg);
2325}
2326
2327static int ahci_pci_device_resume(struct pci_dev *pdev)
2328{
Jeff Garzikcca39742006-08-24 03:19:22 -04002329 struct ata_host *host = dev_get_drvdata(&pdev->dev);
Tejun Heoc1332872006-07-26 15:59:26 +09002330 int rc;
2331
Tejun Heo553c4aa2006-12-26 19:39:50 +09002332 rc = ata_pci_device_do_resume(pdev);
2333 if (rc)
2334 return rc;
Tejun Heoc1332872006-07-26 15:59:26 +09002335
2336 if (pdev->dev.power.power_state.event == PM_EVENT_SUSPEND) {
Tejun Heo4447d352007-04-17 23:44:08 +09002337 rc = ahci_reset_controller(host);
Tejun Heoc1332872006-07-26 15:59:26 +09002338 if (rc)
2339 return rc;
2340
Tejun Heo4447d352007-04-17 23:44:08 +09002341 ahci_init_controller(host);
Tejun Heoc1332872006-07-26 15:59:26 +09002342 }
2343
Jeff Garzikcca39742006-08-24 03:19:22 -04002344 ata_host_resume(host);
Tejun Heoc1332872006-07-26 15:59:26 +09002345
2346 return 0;
2347}
Tejun Heo438ac6d2007-03-02 17:31:26 +09002348#endif
Tejun Heoc1332872006-07-26 15:59:26 +09002349
Tejun Heo254950c2006-07-26 15:59:25 +09002350static int ahci_port_start(struct ata_port *ap)
2351{
Jeff Garzikcca39742006-08-24 03:19:22 -04002352 struct device *dev = ap->host->dev;
Tejun Heo254950c2006-07-26 15:59:25 +09002353 struct ahci_port_priv *pp;
Tejun Heo254950c2006-07-26 15:59:25 +09002354 void *mem;
2355 dma_addr_t mem_dma;
Tejun Heo254950c2006-07-26 15:59:25 +09002356
Tejun Heo24dc5f32007-01-20 16:00:28 +09002357 pp = devm_kzalloc(dev, sizeof(*pp), GFP_KERNEL);
Tejun Heo254950c2006-07-26 15:59:25 +09002358 if (!pp)
2359 return -ENOMEM;
Tejun Heo254950c2006-07-26 15:59:25 +09002360
Tejun Heo24dc5f32007-01-20 16:00:28 +09002361 mem = dmam_alloc_coherent(dev, AHCI_PORT_PRIV_DMA_SZ, &mem_dma,
2362 GFP_KERNEL);
2363 if (!mem)
Tejun Heo254950c2006-07-26 15:59:25 +09002364 return -ENOMEM;
Tejun Heo254950c2006-07-26 15:59:25 +09002365 memset(mem, 0, AHCI_PORT_PRIV_DMA_SZ);
2366
2367 /*
2368 * First item in chunk of DMA memory: 32-slot command table,
2369 * 32 bytes each in size
2370 */
2371 pp->cmd_slot = mem;
2372 pp->cmd_slot_dma = mem_dma;
2373
2374 mem += AHCI_CMD_SLOT_SZ;
2375 mem_dma += AHCI_CMD_SLOT_SZ;
2376
2377 /*
2378 * Second item: Received-FIS area
2379 */
2380 pp->rx_fis = mem;
2381 pp->rx_fis_dma = mem_dma;
2382
2383 mem += AHCI_RX_FIS_SZ;
2384 mem_dma += AHCI_RX_FIS_SZ;
2385
2386 /*
2387 * Third item: data area for storing a single command
2388 * and its scatter-gather table
2389 */
2390 pp->cmd_tbl = mem;
2391 pp->cmd_tbl_dma = mem_dma;
2392
Kristen Carlson Accardia7384922007-08-09 14:23:41 -07002393 /*
Jeff Garzik2dcb4072007-10-19 06:42:56 -04002394 * Save off initial list of interrupts to be enabled.
2395 * This could be changed later
2396 */
Kristen Carlson Accardia7384922007-08-09 14:23:41 -07002397 pp->intr_mask = DEF_PORT_IRQ;
2398
Tejun Heo254950c2006-07-26 15:59:25 +09002399 ap->private_data = pp;
2400
Jeff Garzikdf69c9c2007-05-26 20:46:51 -04002401 /* engage engines, captain */
2402 return ahci_port_resume(ap);
Tejun Heo254950c2006-07-26 15:59:25 +09002403}
2404
2405static void ahci_port_stop(struct ata_port *ap)
2406{
Tejun Heo0be0aa92006-07-26 15:59:26 +09002407 const char *emsg = NULL;
2408 int rc;
Tejun Heo254950c2006-07-26 15:59:25 +09002409
Tejun Heo0be0aa92006-07-26 15:59:26 +09002410 /* de-initialize port */
Tejun Heo4447d352007-04-17 23:44:08 +09002411 rc = ahci_deinit_port(ap, &emsg);
Tejun Heo0be0aa92006-07-26 15:59:26 +09002412 if (rc)
2413 ata_port_printk(ap, KERN_WARNING, "%s (%d)\n", emsg, rc);
Tejun Heo254950c2006-07-26 15:59:25 +09002414}
2415
Tejun Heo4447d352007-04-17 23:44:08 +09002416static int ahci_configure_dma_masks(struct pci_dev *pdev, int using_dac)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002417{
Linus Torvalds1da177e2005-04-16 15:20:36 -07002418 int rc;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002419
Linus Torvalds1da177e2005-04-16 15:20:36 -07002420 if (using_dac &&
2421 !pci_set_dma_mask(pdev, DMA_64BIT_MASK)) {
2422 rc = pci_set_consistent_dma_mask(pdev, DMA_64BIT_MASK);
2423 if (rc) {
2424 rc = pci_set_consistent_dma_mask(pdev, DMA_32BIT_MASK);
2425 if (rc) {
Jeff Garzika9524a72005-10-30 14:39:11 -05002426 dev_printk(KERN_ERR, &pdev->dev,
2427 "64-bit DMA enable failed\n");
Linus Torvalds1da177e2005-04-16 15:20:36 -07002428 return rc;
2429 }
2430 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07002431 } else {
2432 rc = pci_set_dma_mask(pdev, DMA_32BIT_MASK);
2433 if (rc) {
Jeff Garzika9524a72005-10-30 14:39:11 -05002434 dev_printk(KERN_ERR, &pdev->dev,
2435 "32-bit DMA enable failed\n");
Linus Torvalds1da177e2005-04-16 15:20:36 -07002436 return rc;
2437 }
2438 rc = pci_set_consistent_dma_mask(pdev, DMA_32BIT_MASK);
2439 if (rc) {
Jeff Garzika9524a72005-10-30 14:39:11 -05002440 dev_printk(KERN_ERR, &pdev->dev,
2441 "32-bit consistent DMA enable failed\n");
Linus Torvalds1da177e2005-04-16 15:20:36 -07002442 return rc;
2443 }
2444 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07002445 return 0;
2446}
2447
Tejun Heo4447d352007-04-17 23:44:08 +09002448static void ahci_print_info(struct ata_host *host)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002449{
Tejun Heo4447d352007-04-17 23:44:08 +09002450 struct ahci_host_priv *hpriv = host->private_data;
2451 struct pci_dev *pdev = to_pci_dev(host->dev);
2452 void __iomem *mmio = host->iomap[AHCI_PCI_BAR];
Linus Torvalds1da177e2005-04-16 15:20:36 -07002453 u32 vers, cap, impl, speed;
2454 const char *speed_s;
2455 u16 cc;
2456 const char *scc_s;
2457
2458 vers = readl(mmio + HOST_VERSION);
2459 cap = hpriv->cap;
2460 impl = hpriv->port_map;
2461
2462 speed = (cap >> 20) & 0xf;
2463 if (speed == 1)
2464 speed_s = "1.5";
2465 else if (speed == 2)
2466 speed_s = "3";
Shane Huang8522ee22008-12-30 11:00:37 +08002467 else if (speed == 3)
2468 speed_s = "6";
Linus Torvalds1da177e2005-04-16 15:20:36 -07002469 else
2470 speed_s = "?";
2471
2472 pci_read_config_word(pdev, 0x0a, &cc);
Conke Huc9f89472007-01-09 05:32:51 -05002473 if (cc == PCI_CLASS_STORAGE_IDE)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002474 scc_s = "IDE";
Conke Huc9f89472007-01-09 05:32:51 -05002475 else if (cc == PCI_CLASS_STORAGE_SATA)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002476 scc_s = "SATA";
Conke Huc9f89472007-01-09 05:32:51 -05002477 else if (cc == PCI_CLASS_STORAGE_RAID)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002478 scc_s = "RAID";
2479 else
2480 scc_s = "unknown";
2481
Jeff Garzika9524a72005-10-30 14:39:11 -05002482 dev_printk(KERN_INFO, &pdev->dev,
2483 "AHCI %02x%02x.%02x%02x "
Linus Torvalds1da177e2005-04-16 15:20:36 -07002484 "%u slots %u ports %s Gbps 0x%x impl %s mode\n"
Jeff Garzik2dcb4072007-10-19 06:42:56 -04002485 ,
Linus Torvalds1da177e2005-04-16 15:20:36 -07002486
Jeff Garzik2dcb4072007-10-19 06:42:56 -04002487 (vers >> 24) & 0xff,
2488 (vers >> 16) & 0xff,
2489 (vers >> 8) & 0xff,
2490 vers & 0xff,
Linus Torvalds1da177e2005-04-16 15:20:36 -07002491
2492 ((cap >> 8) & 0x1f) + 1,
2493 (cap & 0x1f) + 1,
2494 speed_s,
2495 impl,
2496 scc_s);
2497
Jeff Garzika9524a72005-10-30 14:39:11 -05002498 dev_printk(KERN_INFO, &pdev->dev,
2499 "flags: "
Tejun Heo203ef6c2007-07-16 14:29:40 +09002500 "%s%s%s%s%s%s%s"
Kristen Carlson Accardi18f7ba42008-06-03 10:33:55 -07002501 "%s%s%s%s%s%s%s"
2502 "%s\n"
Jeff Garzik2dcb4072007-10-19 06:42:56 -04002503 ,
Linus Torvalds1da177e2005-04-16 15:20:36 -07002504
2505 cap & (1 << 31) ? "64bit " : "",
2506 cap & (1 << 30) ? "ncq " : "",
Tejun Heo203ef6c2007-07-16 14:29:40 +09002507 cap & (1 << 29) ? "sntf " : "",
Linus Torvalds1da177e2005-04-16 15:20:36 -07002508 cap & (1 << 28) ? "ilck " : "",
2509 cap & (1 << 27) ? "stag " : "",
2510 cap & (1 << 26) ? "pm " : "",
2511 cap & (1 << 25) ? "led " : "",
2512
2513 cap & (1 << 24) ? "clo " : "",
2514 cap & (1 << 19) ? "nz " : "",
2515 cap & (1 << 18) ? "only " : "",
2516 cap & (1 << 17) ? "pmp " : "",
2517 cap & (1 << 15) ? "pio " : "",
2518 cap & (1 << 14) ? "slum " : "",
Kristen Carlson Accardi18f7ba42008-06-03 10:33:55 -07002519 cap & (1 << 13) ? "part " : "",
2520 cap & (1 << 6) ? "ems ": ""
Linus Torvalds1da177e2005-04-16 15:20:36 -07002521 );
2522}
2523
Tejun Heoedc93052007-10-25 14:59:16 +09002524/* On ASUS P5W DH Deluxe, the second port of PCI device 00:1f.2 is
2525 * hardwired to on-board SIMG 4726. The chipset is ICH8 and doesn't
2526 * support PMP and the 4726 either directly exports the device
2527 * attached to the first downstream port or acts as a hardware storage
2528 * controller and emulate a single ATA device (can be RAID 0/1 or some
2529 * other configuration).
2530 *
2531 * When there's no device attached to the first downstream port of the
2532 * 4726, "Config Disk" appears, which is a pseudo ATA device to
2533 * configure the 4726. However, ATA emulation of the device is very
2534 * lame. It doesn't send signature D2H Reg FIS after the initial
2535 * hardreset, pukes on SRST w/ PMP==0 and has bunch of other issues.
2536 *
2537 * The following function works around the problem by always using
2538 * hardreset on the port and not depending on receiving signature FIS
2539 * afterward. If signature FIS isn't received soon, ATA class is
2540 * assumed without follow-up softreset.
2541 */
2542static void ahci_p5wdh_workaround(struct ata_host *host)
2543{
2544 static struct dmi_system_id sysids[] = {
2545 {
2546 .ident = "P5W DH Deluxe",
2547 .matches = {
2548 DMI_MATCH(DMI_SYS_VENDOR,
2549 "ASUSTEK COMPUTER INC"),
2550 DMI_MATCH(DMI_PRODUCT_NAME, "P5W DH Deluxe"),
2551 },
2552 },
2553 { }
2554 };
2555 struct pci_dev *pdev = to_pci_dev(host->dev);
2556
2557 if (pdev->bus->number == 0 && pdev->devfn == PCI_DEVFN(0x1f, 2) &&
2558 dmi_check_system(sysids)) {
2559 struct ata_port *ap = host->ports[1];
2560
2561 dev_printk(KERN_INFO, &pdev->dev, "enabling ASUS P5W DH "
2562 "Deluxe on-board SIMG4726 workaround\n");
2563
2564 ap->ops = &ahci_p5wdh_ops;
2565 ap->link.flags |= ATA_LFLAG_NO_SRST | ATA_LFLAG_ASSUME_ATA;
2566 }
2567}
2568
Rafael J. Wysocki1fd68432009-01-19 20:57:36 +01002569static bool ahci_broken_system_poweroff(struct pci_dev *pdev)
2570{
2571 static const struct dmi_system_id broken_systems[] = {
2572 {
2573 .ident = "HP Compaq nx6310",
2574 .matches = {
2575 DMI_MATCH(DMI_SYS_VENDOR, "Hewlett-Packard"),
2576 DMI_MATCH(DMI_PRODUCT_NAME, "HP Compaq nx6310"),
2577 },
2578 /* PCI slot number of the controller */
2579 .driver_data = (void *)0x1FUL,
2580 },
Maciej Ruteckid2f9c062009-03-20 00:06:46 +01002581 {
2582 .ident = "HP Compaq 6720s",
2583 .matches = {
2584 DMI_MATCH(DMI_SYS_VENDOR, "Hewlett-Packard"),
2585 DMI_MATCH(DMI_PRODUCT_NAME, "HP Compaq 6720s"),
2586 },
2587 /* PCI slot number of the controller */
2588 .driver_data = (void *)0x1FUL,
2589 },
Rafael J. Wysocki1fd68432009-01-19 20:57:36 +01002590
2591 { } /* terminate list */
2592 };
2593 const struct dmi_system_id *dmi = dmi_first_match(broken_systems);
2594
2595 if (dmi) {
2596 unsigned long slot = (unsigned long)dmi->driver_data;
2597 /* apply the quirk only to on-board controllers */
2598 return slot == PCI_SLOT(pdev->devfn);
2599 }
2600
2601 return false;
2602}
2603
Tejun Heo24dc5f32007-01-20 16:00:28 +09002604static int ahci_init_one(struct pci_dev *pdev, const struct pci_device_id *ent)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002605{
2606 static int printed_version;
Tejun Heoe297d992008-06-10 00:13:04 +09002607 unsigned int board_id = ent->driver_data;
2608 struct ata_port_info pi = ahci_port_info[board_id];
Tejun Heo4447d352007-04-17 23:44:08 +09002609 const struct ata_port_info *ppi[] = { &pi, NULL };
Tejun Heo24dc5f32007-01-20 16:00:28 +09002610 struct device *dev = &pdev->dev;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002611 struct ahci_host_priv *hpriv;
Tejun Heo4447d352007-04-17 23:44:08 +09002612 struct ata_host *host;
Tejun Heo837f5f82008-02-06 15:13:51 +09002613 int n_ports, i, rc;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002614
2615 VPRINTK("ENTER\n");
2616
Tejun Heo12fad3f2006-05-15 21:03:55 +09002617 WARN_ON(ATA_MAX_QUEUE > AHCI_MAX_CMDS);
2618
Linus Torvalds1da177e2005-04-16 15:20:36 -07002619 if (!printed_version++)
Jeff Garzika9524a72005-10-30 14:39:11 -05002620 dev_printk(KERN_DEBUG, &pdev->dev, "version " DRV_VERSION "\n");
Linus Torvalds1da177e2005-04-16 15:20:36 -07002621
Alan Cox5b66c822008-09-03 14:48:34 +01002622 /* The AHCI driver can only drive the SATA ports, the PATA driver
2623 can drive them all so if both drivers are selected make sure
2624 AHCI stays out of the way */
2625 if (pdev->vendor == PCI_VENDOR_ID_MARVELL && !marvell_enable)
2626 return -ENODEV;
2627
Tejun Heo4447d352007-04-17 23:44:08 +09002628 /* acquire resources */
Tejun Heo24dc5f32007-01-20 16:00:28 +09002629 rc = pcim_enable_device(pdev);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002630 if (rc)
2631 return rc;
2632
Tejun Heodea55132008-03-11 19:52:31 +09002633 /* AHCI controllers often implement SFF compatible interface.
2634 * Grab all PCI BARs just in case.
2635 */
2636 rc = pcim_iomap_regions_request_all(pdev, 1 << AHCI_PCI_BAR, DRV_NAME);
Tejun Heo0d5ff562007-02-01 15:06:36 +09002637 if (rc == -EBUSY)
Tejun Heo24dc5f32007-01-20 16:00:28 +09002638 pcim_pin_device(pdev);
Tejun Heo0d5ff562007-02-01 15:06:36 +09002639 if (rc)
Tejun Heo24dc5f32007-01-20 16:00:28 +09002640 return rc;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002641
Tejun Heoc4f77922007-12-06 15:09:43 +09002642 if (pdev->vendor == PCI_VENDOR_ID_INTEL &&
2643 (pdev->device == 0x2652 || pdev->device == 0x2653)) {
2644 u8 map;
2645
2646 /* ICH6s share the same PCI ID for both piix and ahci
2647 * modes. Enabling ahci mode while MAP indicates
2648 * combined mode is a bad idea. Yield to ata_piix.
2649 */
2650 pci_read_config_byte(pdev, ICH_MAP, &map);
2651 if (map & 0x3) {
2652 dev_printk(KERN_INFO, &pdev->dev, "controller is in "
2653 "combined mode, can't enable AHCI mode\n");
2654 return -ENODEV;
2655 }
2656 }
2657
Tejun Heo24dc5f32007-01-20 16:00:28 +09002658 hpriv = devm_kzalloc(dev, sizeof(*hpriv), GFP_KERNEL);
2659 if (!hpriv)
2660 return -ENOMEM;
Tejun Heo417a1a62007-09-23 13:19:55 +09002661 hpriv->flags |= (unsigned long)pi.private_data;
2662
Tejun Heoe297d992008-06-10 00:13:04 +09002663 /* MCP65 revision A1 and A2 can't do MSI */
2664 if (board_id == board_ahci_mcp65 &&
2665 (pdev->revision == 0xa1 || pdev->revision == 0xa2))
2666 hpriv->flags |= AHCI_HFLAG_NO_MSI;
2667
Shane Huange427fe02008-12-30 10:53:41 +08002668 /* SB800 does NOT need the workaround to ignore SERR_INTERNAL */
2669 if (board_id == board_ahci_sb700 && pdev->revision >= 0x40)
2670 hpriv->flags &= ~AHCI_HFLAG_IGN_SERR_INTERNAL;
2671
Tejun Heoa5bfc472009-01-23 11:31:39 +09002672 if (!(hpriv->flags & AHCI_HFLAG_NO_MSI))
2673 pci_enable_msi(pdev);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002674
Tejun Heo4447d352007-04-17 23:44:08 +09002675 /* save initial config */
Tejun Heo417a1a62007-09-23 13:19:55 +09002676 ahci_save_initial_config(pdev, hpriv);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002677
Tejun Heo4447d352007-04-17 23:44:08 +09002678 /* prepare host */
Tejun Heo274c1fd2007-07-16 14:29:40 +09002679 if (hpriv->cap & HOST_CAP_NCQ)
Tejun Heo4447d352007-04-17 23:44:08 +09002680 pi.flags |= ATA_FLAG_NCQ;
2681
Tejun Heo7d50b602007-09-23 13:19:54 +09002682 if (hpriv->cap & HOST_CAP_PMP)
2683 pi.flags |= ATA_FLAG_PMP;
2684
Kristen Carlson Accardi18f7ba42008-06-03 10:33:55 -07002685 if (ahci_em_messages && (hpriv->cap & HOST_CAP_EMS)) {
2686 u8 messages;
2687 void __iomem *mmio = pcim_iomap_table(pdev)[AHCI_PCI_BAR];
2688 u32 em_loc = readl(mmio + HOST_EM_LOC);
2689 u32 em_ctl = readl(mmio + HOST_EM_CTL);
2690
David Milburn87943ac2008-10-13 14:38:36 -05002691 messages = (em_ctl & EM_CTRL_MSG_TYPE) >> 16;
Kristen Carlson Accardi18f7ba42008-06-03 10:33:55 -07002692
2693 /* we only support LED message type right now */
2694 if ((messages & 0x01) && (ahci_em_messages == 1)) {
2695 /* store em_loc */
2696 hpriv->em_loc = ((em_loc >> 16) * 4);
2697 pi.flags |= ATA_FLAG_EM;
2698 if (!(em_ctl & EM_CTL_ALHD))
2699 pi.flags |= ATA_FLAG_SW_ACTIVITY;
2700 }
2701 }
2702
Rafael J. Wysocki1fd68432009-01-19 20:57:36 +01002703 if (ahci_broken_system_poweroff(pdev)) {
2704 pi.flags |= ATA_FLAG_NO_POWEROFF_SPINDOWN;
2705 dev_info(&pdev->dev,
2706 "quirky BIOS, skipping spindown on poweroff\n");
2707 }
2708
Tejun Heo837f5f82008-02-06 15:13:51 +09002709 /* CAP.NP sometimes indicate the index of the last enabled
2710 * port, at other times, that of the last possible port, so
2711 * determining the maximum port number requires looking at
2712 * both CAP.NP and port_map.
2713 */
2714 n_ports = max(ahci_nr_ports(hpriv->cap), fls(hpriv->port_map));
2715
2716 host = ata_host_alloc_pinfo(&pdev->dev, ppi, n_ports);
Tejun Heo4447d352007-04-17 23:44:08 +09002717 if (!host)
2718 return -ENOMEM;
2719 host->iomap = pcim_iomap_table(pdev);
2720 host->private_data = hpriv;
2721
Arjan van de Venf3d7f232009-01-26 02:05:44 -08002722 if (!(hpriv->cap & HOST_CAP_SSS) || ahci_ignore_sss)
Arjan van de Ven886ad092009-01-09 15:54:07 -08002723 host->flags |= ATA_HOST_PARALLEL_SCAN;
Arjan van de Venf3d7f232009-01-26 02:05:44 -08002724 else
2725 printk(KERN_INFO "ahci: SSS flag set, parallel bus scan disabled\n");
Arjan van de Ven886ad092009-01-09 15:54:07 -08002726
Kristen Carlson Accardi18f7ba42008-06-03 10:33:55 -07002727 if (pi.flags & ATA_FLAG_EM)
2728 ahci_reset_em(host);
2729
Tejun Heo4447d352007-04-17 23:44:08 +09002730 for (i = 0; i < host->n_ports; i++) {
Jeff Garzikdab632e2007-05-28 08:33:01 -04002731 struct ata_port *ap = host->ports[i];
Tejun Heo4447d352007-04-17 23:44:08 +09002732
Tejun Heocbcdd872007-08-18 13:14:55 +09002733 ata_port_pbar_desc(ap, AHCI_PCI_BAR, -1, "abar");
2734 ata_port_pbar_desc(ap, AHCI_PCI_BAR,
2735 0x100 + ap->port_no * 0x80, "port");
2736
Kristen Carlson Accardi31556592007-10-25 01:33:26 -04002737 /* set initial link pm policy */
2738 ap->pm_policy = NOT_AVAILABLE;
2739
Kristen Carlson Accardi18f7ba42008-06-03 10:33:55 -07002740 /* set enclosure management message type */
2741 if (ap->flags & ATA_FLAG_EM)
2742 ap->em_message_type = ahci_em_messages;
2743
2744
Jeff Garzikdab632e2007-05-28 08:33:01 -04002745 /* disabled/not-implemented port */
Tejun Heo350756f2008-04-07 22:47:21 +09002746 if (!(hpriv->port_map & (1 << i)))
Jeff Garzikdab632e2007-05-28 08:33:01 -04002747 ap->ops = &ata_dummy_port_ops;
Tejun Heo4447d352007-04-17 23:44:08 +09002748 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07002749
Tejun Heoedc93052007-10-25 14:59:16 +09002750 /* apply workaround for ASUS P5W DH Deluxe mainboard */
2751 ahci_p5wdh_workaround(host);
2752
Linus Torvalds1da177e2005-04-16 15:20:36 -07002753 /* initialize adapter */
Tejun Heo4447d352007-04-17 23:44:08 +09002754 rc = ahci_configure_dma_masks(pdev, hpriv->cap & HOST_CAP_64);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002755 if (rc)
Tejun Heo24dc5f32007-01-20 16:00:28 +09002756 return rc;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002757
Tejun Heo4447d352007-04-17 23:44:08 +09002758 rc = ahci_reset_controller(host);
2759 if (rc)
2760 return rc;
Tejun Heo12fad3f2006-05-15 21:03:55 +09002761
Tejun Heo4447d352007-04-17 23:44:08 +09002762 ahci_init_controller(host);
2763 ahci_print_info(host);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002764
Tejun Heo4447d352007-04-17 23:44:08 +09002765 pci_set_master(pdev);
2766 return ata_host_activate(host, pdev->irq, ahci_interrupt, IRQF_SHARED,
2767 &ahci_sht);
Jeff Garzik907f4672005-05-12 15:03:42 -04002768}
Linus Torvalds1da177e2005-04-16 15:20:36 -07002769
2770static int __init ahci_init(void)
2771{
Pavel Roskinb7887192006-08-10 18:13:18 +09002772 return pci_register_driver(&ahci_pci_driver);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002773}
2774
Linus Torvalds1da177e2005-04-16 15:20:36 -07002775static void __exit ahci_exit(void)
2776{
2777 pci_unregister_driver(&ahci_pci_driver);
2778}
2779
2780
2781MODULE_AUTHOR("Jeff Garzik");
2782MODULE_DESCRIPTION("AHCI SATA low-level driver");
2783MODULE_LICENSE("GPL");
2784MODULE_DEVICE_TABLE(pci, ahci_pci_tbl);
Jeff Garzik68854332005-08-23 02:53:51 -04002785MODULE_VERSION(DRV_VERSION);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002786
2787module_init(ahci_init);
2788module_exit(ahci_exit);