blob: bce26ee3806ea3c3cd7a94a25642ae830bc20661 [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
Tejun Heoa22e6442008-03-10 10:25:25 +090052static int ahci_skip_host_reset;
53module_param_named(skip_host_reset, ahci_skip_host_reset, int, 0444);
54MODULE_PARM_DESC(skip_host_reset, "skip global host reset (0=don't skip, 1=skip)");
55
Kristen Carlson Accardi31556592007-10-25 01:33:26 -040056static int ahci_enable_alpm(struct ata_port *ap,
57 enum link_pm policy);
58static void ahci_disable_alpm(struct ata_port *ap);
Kristen Carlson Accardi18f7ba42008-06-03 10:33:55 -070059static ssize_t ahci_led_show(struct ata_port *ap, char *buf);
60static ssize_t ahci_led_store(struct ata_port *ap, const char *buf,
61 size_t size);
62static ssize_t ahci_transmit_led_message(struct ata_port *ap, u32 state,
63 ssize_t size);
64#define MAX_SLOTS 8
Linus Torvalds1da177e2005-04-16 15:20:36 -070065
66enum {
67 AHCI_PCI_BAR = 5,
Tejun Heo648a88b2006-11-09 15:08:40 +090068 AHCI_MAX_PORTS = 32,
Linus Torvalds1da177e2005-04-16 15:20:36 -070069 AHCI_MAX_SG = 168, /* hardware max is 64K */
70 AHCI_DMA_BOUNDARY = 0xffffffff,
Tejun Heo12fad3f2006-05-15 21:03:55 +090071 AHCI_MAX_CMDS = 32,
Tejun Heodd410ff2006-05-15 21:03:50 +090072 AHCI_CMD_SZ = 32,
Tejun Heo12fad3f2006-05-15 21:03:55 +090073 AHCI_CMD_SLOT_SZ = AHCI_MAX_CMDS * AHCI_CMD_SZ,
Linus Torvalds1da177e2005-04-16 15:20:36 -070074 AHCI_RX_FIS_SZ = 256,
Jeff Garzika0ea7322005-06-04 01:13:15 -040075 AHCI_CMD_TBL_CDB = 0x40,
Tejun Heodd410ff2006-05-15 21:03:50 +090076 AHCI_CMD_TBL_HDR_SZ = 0x80,
77 AHCI_CMD_TBL_SZ = AHCI_CMD_TBL_HDR_SZ + (AHCI_MAX_SG * 16),
78 AHCI_CMD_TBL_AR_SZ = AHCI_CMD_TBL_SZ * AHCI_MAX_CMDS,
79 AHCI_PORT_PRIV_DMA_SZ = AHCI_CMD_SLOT_SZ + AHCI_CMD_TBL_AR_SZ +
Linus Torvalds1da177e2005-04-16 15:20:36 -070080 AHCI_RX_FIS_SZ,
81 AHCI_IRQ_ON_SG = (1 << 31),
82 AHCI_CMD_ATAPI = (1 << 5),
83 AHCI_CMD_WRITE = (1 << 6),
Tejun Heo4b10e552006-03-12 11:25:27 +090084 AHCI_CMD_PREFETCH = (1 << 7),
Tejun Heo22b49982006-01-23 21:38:44 +090085 AHCI_CMD_RESET = (1 << 8),
86 AHCI_CMD_CLR_BUSY = (1 << 10),
Linus Torvalds1da177e2005-04-16 15:20:36 -070087
88 RX_FIS_D2H_REG = 0x40, /* offset of D2H Register FIS data */
Tejun Heo0291f952007-01-25 19:16:28 +090089 RX_FIS_SDB = 0x58, /* offset of SDB FIS data */
Tejun Heo78cd52d2006-05-15 20:58:29 +090090 RX_FIS_UNK = 0x60, /* offset of Unknown FIS data */
Linus Torvalds1da177e2005-04-16 15:20:36 -070091
92 board_ahci = 0,
Tejun Heo7a234af2007-09-03 12:44:57 +090093 board_ahci_vt8251 = 1,
94 board_ahci_ign_iferr = 2,
95 board_ahci_sb600 = 3,
96 board_ahci_mv = 4,
Shane Huange39fc8c2008-02-22 05:00:31 -080097 board_ahci_sb700 = 5,
Tejun Heoe297d992008-06-10 00:13:04 +090098 board_ahci_mcp65 = 6,
Tejun Heo9a3b1032008-06-18 20:56:58 -040099 board_ahci_nopmp = 7,
Linus Torvalds1da177e2005-04-16 15:20:36 -0700100
101 /* global controller registers */
102 HOST_CAP = 0x00, /* host capabilities */
103 HOST_CTL = 0x04, /* global host control */
104 HOST_IRQ_STAT = 0x08, /* interrupt status */
105 HOST_PORTS_IMPL = 0x0c, /* bitmap of implemented ports */
106 HOST_VERSION = 0x10, /* AHCI spec. version compliancy */
Kristen Carlson Accardi18f7ba42008-06-03 10:33:55 -0700107 HOST_EM_LOC = 0x1c, /* Enclosure Management location */
108 HOST_EM_CTL = 0x20, /* Enclosure Management Control */
Linus Torvalds1da177e2005-04-16 15:20:36 -0700109
110 /* HOST_CTL bits */
111 HOST_RESET = (1 << 0), /* reset controller; self-clear */
112 HOST_IRQ_EN = (1 << 1), /* global IRQ enable */
113 HOST_AHCI_EN = (1 << 31), /* AHCI enabled */
114
115 /* HOST_CAP bits */
Kristen Carlson Accardi18f7ba42008-06-03 10:33:55 -0700116 HOST_CAP_EMS = (1 << 6), /* Enclosure Management support */
Tejun Heo0be0aa92006-07-26 15:59:26 +0900117 HOST_CAP_SSC = (1 << 14), /* Slumber capable */
Tejun Heo7d50b602007-09-23 13:19:54 +0900118 HOST_CAP_PMP = (1 << 17), /* Port Multiplier support */
Tejun Heo22b49982006-01-23 21:38:44 +0900119 HOST_CAP_CLO = (1 << 24), /* Command List Override support */
Kristen Carlson Accardi31556592007-10-25 01:33:26 -0400120 HOST_CAP_ALPM = (1 << 26), /* Aggressive Link PM support */
Tejun Heo0be0aa92006-07-26 15:59:26 +0900121 HOST_CAP_SSS = (1 << 27), /* Staggered Spin-up */
Tejun Heo203ef6c2007-07-16 14:29:40 +0900122 HOST_CAP_SNTF = (1 << 29), /* SNotification register */
Tejun Heo979db802006-05-15 21:03:52 +0900123 HOST_CAP_NCQ = (1 << 30), /* Native Command Queueing */
Tejun Heodd410ff2006-05-15 21:03:50 +0900124 HOST_CAP_64 = (1 << 31), /* PCI DAC (64-bit DMA) support */
Linus Torvalds1da177e2005-04-16 15:20:36 -0700125
126 /* registers for each SATA port */
127 PORT_LST_ADDR = 0x00, /* command list DMA addr */
128 PORT_LST_ADDR_HI = 0x04, /* command list DMA addr hi */
129 PORT_FIS_ADDR = 0x08, /* FIS rx buf addr */
130 PORT_FIS_ADDR_HI = 0x0c, /* FIS rx buf addr hi */
131 PORT_IRQ_STAT = 0x10, /* interrupt status */
132 PORT_IRQ_MASK = 0x14, /* interrupt enable/disable mask */
133 PORT_CMD = 0x18, /* port command */
134 PORT_TFDATA = 0x20, /* taskfile data */
135 PORT_SIG = 0x24, /* device TF signature */
136 PORT_CMD_ISSUE = 0x38, /* command issue */
Linus Torvalds1da177e2005-04-16 15:20:36 -0700137 PORT_SCR_STAT = 0x28, /* SATA phy register: SStatus */
138 PORT_SCR_CTL = 0x2c, /* SATA phy register: SControl */
139 PORT_SCR_ERR = 0x30, /* SATA phy register: SError */
140 PORT_SCR_ACT = 0x34, /* SATA phy register: SActive */
Tejun Heo203ef6c2007-07-16 14:29:40 +0900141 PORT_SCR_NTF = 0x3c, /* SATA phy register: SNotification */
Linus Torvalds1da177e2005-04-16 15:20:36 -0700142
143 /* PORT_IRQ_{STAT,MASK} bits */
144 PORT_IRQ_COLD_PRES = (1 << 31), /* cold presence detect */
145 PORT_IRQ_TF_ERR = (1 << 30), /* task file error */
146 PORT_IRQ_HBUS_ERR = (1 << 29), /* host bus fatal error */
147 PORT_IRQ_HBUS_DATA_ERR = (1 << 28), /* host bus data error */
148 PORT_IRQ_IF_ERR = (1 << 27), /* interface fatal error */
149 PORT_IRQ_IF_NONFATAL = (1 << 26), /* interface non-fatal error */
150 PORT_IRQ_OVERFLOW = (1 << 24), /* xfer exhausted available S/G */
151 PORT_IRQ_BAD_PMP = (1 << 23), /* incorrect port multiplier */
152
153 PORT_IRQ_PHYRDY = (1 << 22), /* PhyRdy changed */
154 PORT_IRQ_DEV_ILCK = (1 << 7), /* device interlock */
155 PORT_IRQ_CONNECT = (1 << 6), /* port connect change status */
156 PORT_IRQ_SG_DONE = (1 << 5), /* descriptor processed */
157 PORT_IRQ_UNK_FIS = (1 << 4), /* unknown FIS rx'd */
158 PORT_IRQ_SDB_FIS = (1 << 3), /* Set Device Bits FIS rx'd */
159 PORT_IRQ_DMAS_FIS = (1 << 2), /* DMA Setup FIS rx'd */
160 PORT_IRQ_PIOS_FIS = (1 << 1), /* PIO Setup FIS rx'd */
161 PORT_IRQ_D2H_REG_FIS = (1 << 0), /* D2H Register FIS rx'd */
162
Tejun Heo78cd52d2006-05-15 20:58:29 +0900163 PORT_IRQ_FREEZE = PORT_IRQ_HBUS_ERR |
164 PORT_IRQ_IF_ERR |
165 PORT_IRQ_CONNECT |
Tejun Heo42969712006-05-31 18:28:18 +0900166 PORT_IRQ_PHYRDY |
Tejun Heo7d50b602007-09-23 13:19:54 +0900167 PORT_IRQ_UNK_FIS |
168 PORT_IRQ_BAD_PMP,
Tejun Heo78cd52d2006-05-15 20:58:29 +0900169 PORT_IRQ_ERROR = PORT_IRQ_FREEZE |
170 PORT_IRQ_TF_ERR |
171 PORT_IRQ_HBUS_DATA_ERR,
172 DEF_PORT_IRQ = PORT_IRQ_ERROR | PORT_IRQ_SG_DONE |
173 PORT_IRQ_SDB_FIS | PORT_IRQ_DMAS_FIS |
174 PORT_IRQ_PIOS_FIS | PORT_IRQ_D2H_REG_FIS,
Linus Torvalds1da177e2005-04-16 15:20:36 -0700175
176 /* PORT_CMD bits */
Kristen Carlson Accardi31556592007-10-25 01:33:26 -0400177 PORT_CMD_ASP = (1 << 27), /* Aggressive Slumber/Partial */
178 PORT_CMD_ALPE = (1 << 26), /* Aggressive Link PM enable */
Jeff Garzik02eaa662005-11-12 01:32:19 -0500179 PORT_CMD_ATAPI = (1 << 24), /* Device is ATAPI */
Tejun Heo7d50b602007-09-23 13:19:54 +0900180 PORT_CMD_PMP = (1 << 17), /* PMP attached */
Linus Torvalds1da177e2005-04-16 15:20:36 -0700181 PORT_CMD_LIST_ON = (1 << 15), /* cmd list DMA engine running */
182 PORT_CMD_FIS_ON = (1 << 14), /* FIS DMA engine running */
183 PORT_CMD_FIS_RX = (1 << 4), /* Enable FIS receive DMA engine */
Tejun Heo22b49982006-01-23 21:38:44 +0900184 PORT_CMD_CLO = (1 << 3), /* Command list override */
Linus Torvalds1da177e2005-04-16 15:20:36 -0700185 PORT_CMD_POWER_ON = (1 << 2), /* Power up device */
186 PORT_CMD_SPIN_UP = (1 << 1), /* Spin up device */
187 PORT_CMD_START = (1 << 0), /* Enable port DMA engine */
188
Tejun Heo0be0aa92006-07-26 15:59:26 +0900189 PORT_CMD_ICC_MASK = (0xf << 28), /* i/f ICC state mask */
Linus Torvalds1da177e2005-04-16 15:20:36 -0700190 PORT_CMD_ICC_ACTIVE = (0x1 << 28), /* Put i/f in active state */
191 PORT_CMD_ICC_PARTIAL = (0x2 << 28), /* Put i/f in partial state */
192 PORT_CMD_ICC_SLUMBER = (0x6 << 28), /* Put i/f in slumber state */
Jeff Garzik4b0060f2005-06-04 00:50:22 -0400193
Tejun Heo417a1a62007-09-23 13:19:55 +0900194 /* hpriv->flags bits */
195 AHCI_HFLAG_NO_NCQ = (1 << 0),
196 AHCI_HFLAG_IGN_IRQ_IF_ERR = (1 << 1), /* ignore IRQ_IF_ERR */
197 AHCI_HFLAG_IGN_SERR_INTERNAL = (1 << 2), /* ignore SERR_INTERNAL */
198 AHCI_HFLAG_32BIT_ONLY = (1 << 3), /* force 32bit */
199 AHCI_HFLAG_MV_PATA = (1 << 4), /* PATA port */
200 AHCI_HFLAG_NO_MSI = (1 << 5), /* no PCI MSI */
Tejun Heo6949b912007-09-23 13:19:55 +0900201 AHCI_HFLAG_NO_PMP = (1 << 6), /* no PMP */
Kristen Carlson Accardi31556592007-10-25 01:33:26 -0400202 AHCI_HFLAG_NO_HOTPLUG = (1 << 7), /* ignore PxSERR.DIAG.N */
Jeff Garzika8785392008-02-28 15:43:48 -0500203 AHCI_HFLAG_SECT255 = (1 << 8), /* max 255 sectors */
Tejun Heoe297d992008-06-10 00:13:04 +0900204 AHCI_HFLAG_YES_NCQ = (1 << 9), /* force NCQ cap on */
Tejun Heo417a1a62007-09-23 13:19:55 +0900205
Bastiaan Jacquesbf2af2a2006-04-17 14:17:59 +0200206 /* ap->flags bits */
Tejun Heo1188c0d2007-04-23 02:41:05 +0900207
208 AHCI_FLAG_COMMON = ATA_FLAG_SATA | ATA_FLAG_NO_LEGACY |
209 ATA_FLAG_MMIO | ATA_FLAG_PIO_DMA |
Kristen Carlson Accardi31556592007-10-25 01:33:26 -0400210 ATA_FLAG_ACPI_SATA | ATA_FLAG_AN |
211 ATA_FLAG_IPM,
Tejun Heoc4f77922007-12-06 15:09:43 +0900212
213 ICH_MAP = 0x90, /* ICH MAP register */
Kristen Carlson Accardi18f7ba42008-06-03 10:33:55 -0700214
215 /* em_ctl bits */
216 EM_CTL_RST = (1 << 9), /* Reset */
217 EM_CTL_TM = (1 << 8), /* Transmit Message */
218 EM_CTL_ALHD = (1 << 26), /* Activity LED */
Linus Torvalds1da177e2005-04-16 15:20:36 -0700219};
220
221struct ahci_cmd_hdr {
Al Viro4ca4e432007-12-30 09:32:22 +0000222 __le32 opts;
223 __le32 status;
224 __le32 tbl_addr;
225 __le32 tbl_addr_hi;
226 __le32 reserved[4];
Linus Torvalds1da177e2005-04-16 15:20:36 -0700227};
228
229struct ahci_sg {
Al Viro4ca4e432007-12-30 09:32:22 +0000230 __le32 addr;
231 __le32 addr_hi;
232 __le32 reserved;
233 __le32 flags_size;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700234};
235
Kristen Carlson Accardi18f7ba42008-06-03 10:33:55 -0700236struct ahci_em_priv {
237 enum sw_activity blink_policy;
238 struct timer_list timer;
239 unsigned long saved_activity;
240 unsigned long activity;
241 unsigned long led_state;
242};
243
Linus Torvalds1da177e2005-04-16 15:20:36 -0700244struct ahci_host_priv {
Tejun Heo417a1a62007-09-23 13:19:55 +0900245 unsigned int flags; /* AHCI_HFLAG_* */
Tejun Heod447df12007-03-18 22:15:33 +0900246 u32 cap; /* cap to use */
247 u32 port_map; /* port map to use */
248 u32 saved_cap; /* saved initial cap */
249 u32 saved_port_map; /* saved initial port_map */
Kristen Carlson Accardi18f7ba42008-06-03 10:33:55 -0700250 u32 em_loc; /* enclosure management location */
Linus Torvalds1da177e2005-04-16 15:20:36 -0700251};
252
253struct ahci_port_priv {
Tejun Heo7d50b602007-09-23 13:19:54 +0900254 struct ata_link *active_link;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700255 struct ahci_cmd_hdr *cmd_slot;
256 dma_addr_t cmd_slot_dma;
257 void *cmd_tbl;
258 dma_addr_t cmd_tbl_dma;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700259 void *rx_fis;
260 dma_addr_t rx_fis_dma;
Tejun Heo0291f952007-01-25 19:16:28 +0900261 /* for NCQ spurious interrupt analysis */
Tejun Heo0291f952007-01-25 19:16:28 +0900262 unsigned int ncq_saw_d2h:1;
263 unsigned int ncq_saw_dmas:1;
Tejun Heoafb2d552007-02-27 13:24:19 +0900264 unsigned int ncq_saw_sdb:1;
Kristen Carlson Accardia7384922007-08-09 14:23:41 -0700265 u32 intr_mask; /* interrupts to enable */
Kristen Carlson Accardi18f7ba42008-06-03 10:33:55 -0700266 struct ahci_em_priv em_priv[MAX_SLOTS];/* enclosure management info
267 * per PM slot */
Linus Torvalds1da177e2005-04-16 15:20:36 -0700268};
269
Tejun Heoda3dbb12007-07-16 14:29:40 +0900270static int ahci_scr_read(struct ata_port *ap, unsigned int sc_reg, u32 *val);
271static int ahci_scr_write(struct ata_port *ap, unsigned int sc_reg, u32 val);
Jeff Garzik2dcb4072007-10-19 06:42:56 -0400272static int ahci_init_one(struct pci_dev *pdev, const struct pci_device_id *ent);
Tejun Heo9a3d9eb2006-01-23 13:09:36 +0900273static unsigned int ahci_qc_issue(struct ata_queued_cmd *qc);
Tejun Heo4c9bf4e2008-04-07 22:47:20 +0900274static bool ahci_qc_fill_rtf(struct ata_queued_cmd *qc);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700275static int ahci_port_start(struct ata_port *ap);
276static void ahci_port_stop(struct ata_port *ap);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700277static void ahci_qc_prep(struct ata_queued_cmd *qc);
Tejun Heo78cd52d2006-05-15 20:58:29 +0900278static void ahci_freeze(struct ata_port *ap);
279static void ahci_thaw(struct ata_port *ap);
Tejun Heo7d50b602007-09-23 13:19:54 +0900280static void ahci_pmp_attach(struct ata_port *ap);
281static void ahci_pmp_detach(struct ata_port *ap);
Tejun Heoa1efdab2008-03-25 12:22:50 +0900282static int ahci_softreset(struct ata_link *link, unsigned int *class,
283 unsigned long deadline);
Shane Huangbd172432008-06-10 15:52:04 +0800284static int ahci_sb600_softreset(struct ata_link *link, unsigned int *class,
285 unsigned long deadline);
Tejun Heoa1efdab2008-03-25 12:22:50 +0900286static int ahci_hardreset(struct ata_link *link, unsigned int *class,
287 unsigned long deadline);
288static int ahci_vt8251_hardreset(struct ata_link *link, unsigned int *class,
289 unsigned long deadline);
290static int ahci_p5wdh_hardreset(struct ata_link *link, unsigned int *class,
291 unsigned long deadline);
292static void ahci_postreset(struct ata_link *link, unsigned int *class);
Tejun Heo78cd52d2006-05-15 20:58:29 +0900293static void ahci_error_handler(struct ata_port *ap);
294static void ahci_post_internal_cmd(struct ata_queued_cmd *qc);
Jeff Garzikdf69c9c2007-05-26 20:46:51 -0400295static int ahci_port_resume(struct ata_port *ap);
Jeff Garzika8785392008-02-28 15:43:48 -0500296static void ahci_dev_config(struct ata_device *dev);
Jeff Garzikdab632e2007-05-28 08:33:01 -0400297static unsigned int ahci_fill_sg(struct ata_queued_cmd *qc, void *cmd_tbl);
298static void ahci_fill_cmd_slot(struct ahci_port_priv *pp, unsigned int tag,
299 u32 opts);
Tejun Heo438ac6d2007-03-02 17:31:26 +0900300#ifdef CONFIG_PM
Tejun Heoc1332872006-07-26 15:59:26 +0900301static int ahci_port_suspend(struct ata_port *ap, pm_message_t mesg);
Tejun Heoc1332872006-07-26 15:59:26 +0900302static int ahci_pci_device_suspend(struct pci_dev *pdev, pm_message_t mesg);
303static int ahci_pci_device_resume(struct pci_dev *pdev);
Tejun Heo438ac6d2007-03-02 17:31:26 +0900304#endif
Kristen Carlson Accardi18f7ba42008-06-03 10:33:55 -0700305static ssize_t ahci_activity_show(struct ata_device *dev, char *buf);
306static ssize_t ahci_activity_store(struct ata_device *dev,
307 enum sw_activity val);
308static void ahci_init_sw_activity(struct ata_link *link);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700309
Tony Jonesee959b02008-02-22 00:13:36 +0100310static struct device_attribute *ahci_shost_attrs[] = {
311 &dev_attr_link_power_management_policy,
Kristen Carlson Accardi18f7ba42008-06-03 10:33:55 -0700312 &dev_attr_em_message_type,
313 &dev_attr_em_message,
314 NULL
315};
316
317static struct device_attribute *ahci_sdev_attrs[] = {
318 &dev_attr_sw_activity,
Kristen Carlson Accardi31556592007-10-25 01:33:26 -0400319 NULL
320};
321
Jeff Garzik193515d2005-11-07 00:59:37 -0500322static struct scsi_host_template ahci_sht = {
Tejun Heo68d1d072008-03-25 12:22:49 +0900323 ATA_NCQ_SHT(DRV_NAME),
Tejun Heo12fad3f2006-05-15 21:03:55 +0900324 .can_queue = AHCI_MAX_CMDS - 1,
Linus Torvalds1da177e2005-04-16 15:20:36 -0700325 .sg_tablesize = AHCI_MAX_SG,
Linus Torvalds1da177e2005-04-16 15:20:36 -0700326 .dma_boundary = AHCI_DMA_BOUNDARY,
Kristen Carlson Accardi31556592007-10-25 01:33:26 -0400327 .shost_attrs = ahci_shost_attrs,
Kristen Carlson Accardi18f7ba42008-06-03 10:33:55 -0700328 .sdev_attrs = ahci_sdev_attrs,
Linus Torvalds1da177e2005-04-16 15:20:36 -0700329};
330
Tejun Heo029cfd62008-03-25 12:22:49 +0900331static struct ata_port_operations ahci_ops = {
332 .inherits = &sata_pmp_port_ops,
333
Tejun Heo7d50b602007-09-23 13:19:54 +0900334 .qc_defer = sata_pmp_qc_defer_cmd_switch,
Linus Torvalds1da177e2005-04-16 15:20:36 -0700335 .qc_prep = ahci_qc_prep,
336 .qc_issue = ahci_qc_issue,
Tejun Heo4c9bf4e2008-04-07 22:47:20 +0900337 .qc_fill_rtf = ahci_qc_fill_rtf,
Linus Torvalds1da177e2005-04-16 15:20:36 -0700338
Tejun Heo78cd52d2006-05-15 20:58:29 +0900339 .freeze = ahci_freeze,
340 .thaw = ahci_thaw,
Tejun Heoa1efdab2008-03-25 12:22:50 +0900341 .softreset = ahci_softreset,
342 .hardreset = ahci_hardreset,
343 .postreset = ahci_postreset,
Tejun Heo071f44b2008-04-07 22:47:22 +0900344 .pmp_softreset = ahci_softreset,
Tejun Heo78cd52d2006-05-15 20:58:29 +0900345 .error_handler = ahci_error_handler,
346 .post_internal_cmd = ahci_post_internal_cmd,
Tejun Heo029cfd62008-03-25 12:22:49 +0900347 .dev_config = ahci_dev_config,
Tejun Heo78cd52d2006-05-15 20:58:29 +0900348
Tejun Heo029cfd62008-03-25 12:22:49 +0900349 .scr_read = ahci_scr_read,
350 .scr_write = ahci_scr_write,
Tejun Heo7d50b602007-09-23 13:19:54 +0900351 .pmp_attach = ahci_pmp_attach,
352 .pmp_detach = ahci_pmp_detach,
Tejun Heo7d50b602007-09-23 13:19:54 +0900353
Tejun Heo029cfd62008-03-25 12:22:49 +0900354 .enable_pm = ahci_enable_alpm,
355 .disable_pm = ahci_disable_alpm,
Kristen Carlson Accardi18f7ba42008-06-03 10:33:55 -0700356 .em_show = ahci_led_show,
357 .em_store = ahci_led_store,
358 .sw_activity_show = ahci_activity_show,
359 .sw_activity_store = ahci_activity_store,
Tejun Heo438ac6d2007-03-02 17:31:26 +0900360#ifdef CONFIG_PM
Tejun Heoc1332872006-07-26 15:59:26 +0900361 .port_suspend = ahci_port_suspend,
362 .port_resume = ahci_port_resume,
Tejun Heo438ac6d2007-03-02 17:31:26 +0900363#endif
Linus Torvalds1da177e2005-04-16 15:20:36 -0700364 .port_start = ahci_port_start,
365 .port_stop = ahci_port_stop,
Linus Torvalds1da177e2005-04-16 15:20:36 -0700366};
367
Tejun Heo029cfd62008-03-25 12:22:49 +0900368static struct ata_port_operations ahci_vt8251_ops = {
369 .inherits = &ahci_ops,
Tejun Heoa1efdab2008-03-25 12:22:50 +0900370 .hardreset = ahci_vt8251_hardreset,
Tejun Heoad616ff2006-11-01 18:00:24 +0900371};
372
Tejun Heo029cfd62008-03-25 12:22:49 +0900373static struct ata_port_operations ahci_p5wdh_ops = {
374 .inherits = &ahci_ops,
Tejun Heoa1efdab2008-03-25 12:22:50 +0900375 .hardreset = ahci_p5wdh_hardreset,
Tejun Heoedc93052007-10-25 14:59:16 +0900376};
377
Shane Huangbd172432008-06-10 15:52:04 +0800378static struct ata_port_operations ahci_sb600_ops = {
379 .inherits = &ahci_ops,
380 .softreset = ahci_sb600_softreset,
381 .pmp_softreset = ahci_sb600_softreset,
382};
383
Tejun Heo417a1a62007-09-23 13:19:55 +0900384#define AHCI_HFLAGS(flags) .private_data = (void *)(flags)
385
Arjan van de Ven98ac62d2005-11-28 10:06:23 +0100386static const struct ata_port_info ahci_port_info[] = {
Linus Torvalds1da177e2005-04-16 15:20:36 -0700387 /* board_ahci */
388 {
Tejun Heo1188c0d2007-04-23 02:41:05 +0900389 .flags = AHCI_FLAG_COMMON,
Brett Russ7da79312005-09-01 21:53:34 -0400390 .pio_mask = 0x1f, /* pio0-4 */
Jeff Garzik469248a2007-07-08 01:13:16 -0400391 .udma_mask = ATA_UDMA6,
Linus Torvalds1da177e2005-04-16 15:20:36 -0700392 .port_ops = &ahci_ops,
393 },
Bastiaan Jacquesbf2af2a2006-04-17 14:17:59 +0200394 /* board_ahci_vt8251 */
395 {
Tejun Heo6949b912007-09-23 13:19:55 +0900396 AHCI_HFLAGS (AHCI_HFLAG_NO_NCQ | AHCI_HFLAG_NO_PMP),
Tejun Heo417a1a62007-09-23 13:19:55 +0900397 .flags = AHCI_FLAG_COMMON,
Bastiaan Jacquesbf2af2a2006-04-17 14:17:59 +0200398 .pio_mask = 0x1f, /* pio0-4 */
Jeff Garzik469248a2007-07-08 01:13:16 -0400399 .udma_mask = ATA_UDMA6,
Tejun Heoad616ff2006-11-01 18:00:24 +0900400 .port_ops = &ahci_vt8251_ops,
Bastiaan Jacquesbf2af2a2006-04-17 14:17:59 +0200401 },
Tejun Heo41669552006-11-29 11:33:14 +0900402 /* board_ahci_ign_iferr */
403 {
Tejun Heo417a1a62007-09-23 13:19:55 +0900404 AHCI_HFLAGS (AHCI_HFLAG_IGN_IRQ_IF_ERR),
405 .flags = AHCI_FLAG_COMMON,
Tejun Heo41669552006-11-29 11:33:14 +0900406 .pio_mask = 0x1f, /* pio0-4 */
Jeff Garzik469248a2007-07-08 01:13:16 -0400407 .udma_mask = ATA_UDMA6,
Tejun Heo41669552006-11-29 11:33:14 +0900408 .port_ops = &ahci_ops,
409 },
Conke Hu55a61602007-03-27 18:33:05 +0800410 /* board_ahci_sb600 */
411 {
Tejun Heo417a1a62007-09-23 13:19:55 +0900412 AHCI_HFLAGS (AHCI_HFLAG_IGN_SERR_INTERNAL |
Tejun Heo22b5e7a2008-04-29 16:09:22 +0900413 AHCI_HFLAG_32BIT_ONLY | AHCI_HFLAG_NO_MSI |
Shane Huangbd172432008-06-10 15:52:04 +0800414 AHCI_HFLAG_SECT255),
Tejun Heo417a1a62007-09-23 13:19:55 +0900415 .flags = AHCI_FLAG_COMMON,
Conke Hu55a61602007-03-27 18:33:05 +0800416 .pio_mask = 0x1f, /* pio0-4 */
Jeff Garzik469248a2007-07-08 01:13:16 -0400417 .udma_mask = ATA_UDMA6,
Shane Huangbd172432008-06-10 15:52:04 +0800418 .port_ops = &ahci_sb600_ops,
Conke Hu55a61602007-03-27 18:33:05 +0800419 },
Jeff Garzikcd70c262007-07-08 02:29:42 -0400420 /* board_ahci_mv */
421 {
Tejun Heo417a1a62007-09-23 13:19:55 +0900422 AHCI_HFLAGS (AHCI_HFLAG_NO_NCQ | AHCI_HFLAG_NO_MSI |
423 AHCI_HFLAG_MV_PATA),
Jeff Garzikcd70c262007-07-08 02:29:42 -0400424 .flags = ATA_FLAG_SATA | ATA_FLAG_NO_LEGACY |
Tejun Heo417a1a62007-09-23 13:19:55 +0900425 ATA_FLAG_MMIO | ATA_FLAG_PIO_DMA,
Jeff Garzikcd70c262007-07-08 02:29:42 -0400426 .pio_mask = 0x1f, /* pio0-4 */
427 .udma_mask = ATA_UDMA6,
428 .port_ops = &ahci_ops,
429 },
Shane Huange39fc8c2008-02-22 05:00:31 -0800430 /* board_ahci_sb700 */
431 {
Shane Huangbd172432008-06-10 15:52:04 +0800432 AHCI_HFLAGS (AHCI_HFLAG_IGN_SERR_INTERNAL),
Shane Huange39fc8c2008-02-22 05:00:31 -0800433 .flags = AHCI_FLAG_COMMON,
Shane Huange39fc8c2008-02-22 05:00:31 -0800434 .pio_mask = 0x1f, /* pio0-4 */
435 .udma_mask = ATA_UDMA6,
Shane Huangbd172432008-06-10 15:52:04 +0800436 .port_ops = &ahci_sb600_ops,
Shane Huange39fc8c2008-02-22 05:00:31 -0800437 },
Tejun Heoe297d992008-06-10 00:13:04 +0900438 /* board_ahci_mcp65 */
439 {
440 AHCI_HFLAGS (AHCI_HFLAG_YES_NCQ),
441 .flags = AHCI_FLAG_COMMON,
442 .pio_mask = 0x1f, /* pio0-4 */
443 .udma_mask = ATA_UDMA6,
444 .port_ops = &ahci_ops,
445 },
Tejun Heo9a3b1032008-06-18 20:56:58 -0400446 /* board_ahci_nopmp */
447 {
448 AHCI_HFLAGS (AHCI_HFLAG_NO_PMP),
449 .flags = AHCI_FLAG_COMMON,
450 .pio_mask = 0x1f, /* pio0-4 */
451 .udma_mask = ATA_UDMA6,
452 .port_ops = &ahci_ops,
453 },
Linus Torvalds1da177e2005-04-16 15:20:36 -0700454};
455
Jeff Garzik3b7d6972005-11-10 11:04:11 -0500456static const struct pci_device_id ahci_pci_tbl[] = {
Jeff Garzikfe7fa312006-06-22 23:05:36 -0400457 /* Intel */
Jeff Garzik54bb3a942006-09-27 22:20:11 -0400458 { PCI_VDEVICE(INTEL, 0x2652), board_ahci }, /* ICH6 */
459 { PCI_VDEVICE(INTEL, 0x2653), board_ahci }, /* ICH6M */
460 { PCI_VDEVICE(INTEL, 0x27c1), board_ahci }, /* ICH7 */
461 { PCI_VDEVICE(INTEL, 0x27c5), board_ahci }, /* ICH7M */
462 { PCI_VDEVICE(INTEL, 0x27c3), board_ahci }, /* ICH7R */
Tejun Heo82490c02007-01-23 15:13:39 +0900463 { PCI_VDEVICE(AL, 0x5288), board_ahci_ign_iferr }, /* ULi M5288 */
Jeff Garzik54bb3a942006-09-27 22:20:11 -0400464 { PCI_VDEVICE(INTEL, 0x2681), board_ahci }, /* ESB2 */
465 { PCI_VDEVICE(INTEL, 0x2682), board_ahci }, /* ESB2 */
466 { PCI_VDEVICE(INTEL, 0x2683), board_ahci }, /* ESB2 */
467 { PCI_VDEVICE(INTEL, 0x27c6), board_ahci }, /* ICH7-M DH */
Tejun Heo7a234af2007-09-03 12:44:57 +0900468 { PCI_VDEVICE(INTEL, 0x2821), board_ahci }, /* ICH8 */
469 { PCI_VDEVICE(INTEL, 0x2822), board_ahci }, /* ICH8 */
470 { PCI_VDEVICE(INTEL, 0x2824), board_ahci }, /* ICH8 */
471 { PCI_VDEVICE(INTEL, 0x2829), board_ahci }, /* ICH8M */
472 { PCI_VDEVICE(INTEL, 0x282a), board_ahci }, /* ICH8M */
473 { PCI_VDEVICE(INTEL, 0x2922), board_ahci }, /* ICH9 */
474 { PCI_VDEVICE(INTEL, 0x2923), board_ahci }, /* ICH9 */
475 { PCI_VDEVICE(INTEL, 0x2924), board_ahci }, /* ICH9 */
476 { PCI_VDEVICE(INTEL, 0x2925), board_ahci }, /* ICH9 */
477 { PCI_VDEVICE(INTEL, 0x2927), board_ahci }, /* ICH9 */
478 { PCI_VDEVICE(INTEL, 0x2929), board_ahci }, /* ICH9M */
479 { PCI_VDEVICE(INTEL, 0x292a), board_ahci }, /* ICH9M */
480 { PCI_VDEVICE(INTEL, 0x292b), board_ahci }, /* ICH9M */
481 { PCI_VDEVICE(INTEL, 0x292c), board_ahci }, /* ICH9M */
482 { PCI_VDEVICE(INTEL, 0x292f), board_ahci }, /* ICH9M */
483 { PCI_VDEVICE(INTEL, 0x294d), board_ahci }, /* ICH9 */
484 { PCI_VDEVICE(INTEL, 0x294e), board_ahci }, /* ICH9M */
Jason Gastond4155e62007-09-20 17:35:00 -0400485 { PCI_VDEVICE(INTEL, 0x502a), board_ahci }, /* Tolapai */
486 { PCI_VDEVICE(INTEL, 0x502b), board_ahci }, /* Tolapai */
Jason Gaston16ad1ad2008-01-28 17:34:14 -0800487 { PCI_VDEVICE(INTEL, 0x3a05), board_ahci }, /* ICH10 */
488 { PCI_VDEVICE(INTEL, 0x3a25), board_ahci }, /* ICH10 */
Seth Heasleyadcb5302008-08-11 17:03:09 -0700489 { PCI_VDEVICE(INTEL, 0x3b24), board_ahci }, /* PCH RAID */
490 { PCI_VDEVICE(INTEL, 0x3b2b), board_ahci }, /* PCH RAID */
Jeff Garzikfe7fa312006-06-22 23:05:36 -0400491
Tejun Heoe34bb372007-02-26 20:24:03 +0900492 /* JMicron 360/1/3/5/6, match class to avoid IDE function */
493 { PCI_VENDOR_ID_JMICRON, PCI_ANY_ID, PCI_ANY_ID, PCI_ANY_ID,
494 PCI_CLASS_STORAGE_SATA_AHCI, 0xffffff, board_ahci_ign_iferr },
Jeff Garzikfe7fa312006-06-22 23:05:36 -0400495
496 /* ATI */
Conke Huc65ec1c2007-04-11 18:23:14 +0800497 { PCI_VDEVICE(ATI, 0x4380), board_ahci_sb600 }, /* ATI SB600 */
Shane Huange39fc8c2008-02-22 05:00:31 -0800498 { PCI_VDEVICE(ATI, 0x4390), board_ahci_sb700 }, /* ATI SB700/800 */
499 { PCI_VDEVICE(ATI, 0x4391), board_ahci_sb700 }, /* ATI SB700/800 */
500 { PCI_VDEVICE(ATI, 0x4392), board_ahci_sb700 }, /* ATI SB700/800 */
501 { PCI_VDEVICE(ATI, 0x4393), board_ahci_sb700 }, /* ATI SB700/800 */
502 { PCI_VDEVICE(ATI, 0x4394), board_ahci_sb700 }, /* ATI SB700/800 */
503 { PCI_VDEVICE(ATI, 0x4395), board_ahci_sb700 }, /* ATI SB700/800 */
Jeff Garzikfe7fa312006-06-22 23:05:36 -0400504
505 /* VIA */
Jeff Garzik54bb3a942006-09-27 22:20:11 -0400506 { PCI_VDEVICE(VIA, 0x3349), board_ahci_vt8251 }, /* VIA VT8251 */
Tejun Heobf335542007-04-11 17:27:14 +0900507 { PCI_VDEVICE(VIA, 0x6287), board_ahci_vt8251 }, /* VIA VT8251 */
Jeff Garzikfe7fa312006-06-22 23:05:36 -0400508
509 /* NVIDIA */
Tejun Heoe297d992008-06-10 00:13:04 +0900510 { PCI_VDEVICE(NVIDIA, 0x044c), board_ahci_mcp65 }, /* MCP65 */
511 { PCI_VDEVICE(NVIDIA, 0x044d), board_ahci_mcp65 }, /* MCP65 */
512 { PCI_VDEVICE(NVIDIA, 0x044e), board_ahci_mcp65 }, /* MCP65 */
513 { PCI_VDEVICE(NVIDIA, 0x044f), board_ahci_mcp65 }, /* MCP65 */
514 { PCI_VDEVICE(NVIDIA, 0x045c), board_ahci_mcp65 }, /* MCP65 */
515 { PCI_VDEVICE(NVIDIA, 0x045d), board_ahci_mcp65 }, /* MCP65 */
516 { PCI_VDEVICE(NVIDIA, 0x045e), board_ahci_mcp65 }, /* MCP65 */
517 { PCI_VDEVICE(NVIDIA, 0x045f), board_ahci_mcp65 }, /* MCP65 */
Peer Chen6fbf5ba2006-12-20 14:18:00 -0500518 { PCI_VDEVICE(NVIDIA, 0x0550), board_ahci }, /* MCP67 */
519 { PCI_VDEVICE(NVIDIA, 0x0551), board_ahci }, /* MCP67 */
520 { PCI_VDEVICE(NVIDIA, 0x0552), board_ahci }, /* MCP67 */
521 { PCI_VDEVICE(NVIDIA, 0x0553), board_ahci }, /* MCP67 */
Peer Chen895663c2006-11-02 17:59:46 -0500522 { PCI_VDEVICE(NVIDIA, 0x0554), board_ahci }, /* MCP67 */
523 { PCI_VDEVICE(NVIDIA, 0x0555), board_ahci }, /* MCP67 */
524 { PCI_VDEVICE(NVIDIA, 0x0556), board_ahci }, /* MCP67 */
525 { PCI_VDEVICE(NVIDIA, 0x0557), board_ahci }, /* MCP67 */
526 { PCI_VDEVICE(NVIDIA, 0x0558), board_ahci }, /* MCP67 */
527 { PCI_VDEVICE(NVIDIA, 0x0559), board_ahci }, /* MCP67 */
528 { PCI_VDEVICE(NVIDIA, 0x055a), board_ahci }, /* MCP67 */
529 { PCI_VDEVICE(NVIDIA, 0x055b), board_ahci }, /* MCP67 */
Peer Chen0522b282007-06-07 18:05:12 +0800530 { PCI_VDEVICE(NVIDIA, 0x07f0), board_ahci }, /* MCP73 */
531 { PCI_VDEVICE(NVIDIA, 0x07f1), board_ahci }, /* MCP73 */
532 { PCI_VDEVICE(NVIDIA, 0x07f2), board_ahci }, /* MCP73 */
533 { PCI_VDEVICE(NVIDIA, 0x07f3), board_ahci }, /* MCP73 */
534 { PCI_VDEVICE(NVIDIA, 0x07f4), board_ahci }, /* MCP73 */
535 { PCI_VDEVICE(NVIDIA, 0x07f5), board_ahci }, /* MCP73 */
536 { PCI_VDEVICE(NVIDIA, 0x07f6), board_ahci }, /* MCP73 */
537 { PCI_VDEVICE(NVIDIA, 0x07f7), board_ahci }, /* MCP73 */
538 { PCI_VDEVICE(NVIDIA, 0x07f8), board_ahci }, /* MCP73 */
539 { PCI_VDEVICE(NVIDIA, 0x07f9), board_ahci }, /* MCP73 */
540 { PCI_VDEVICE(NVIDIA, 0x07fa), board_ahci }, /* MCP73 */
541 { PCI_VDEVICE(NVIDIA, 0x07fb), board_ahci }, /* MCP73 */
542 { PCI_VDEVICE(NVIDIA, 0x0ad0), board_ahci }, /* MCP77 */
543 { PCI_VDEVICE(NVIDIA, 0x0ad1), board_ahci }, /* MCP77 */
544 { PCI_VDEVICE(NVIDIA, 0x0ad2), board_ahci }, /* MCP77 */
545 { PCI_VDEVICE(NVIDIA, 0x0ad3), board_ahci }, /* MCP77 */
546 { PCI_VDEVICE(NVIDIA, 0x0ad4), board_ahci }, /* MCP77 */
547 { PCI_VDEVICE(NVIDIA, 0x0ad5), board_ahci }, /* MCP77 */
548 { PCI_VDEVICE(NVIDIA, 0x0ad6), board_ahci }, /* MCP77 */
549 { PCI_VDEVICE(NVIDIA, 0x0ad7), board_ahci }, /* MCP77 */
550 { PCI_VDEVICE(NVIDIA, 0x0ad8), board_ahci }, /* MCP77 */
551 { PCI_VDEVICE(NVIDIA, 0x0ad9), board_ahci }, /* MCP77 */
552 { PCI_VDEVICE(NVIDIA, 0x0ada), board_ahci }, /* MCP77 */
553 { PCI_VDEVICE(NVIDIA, 0x0adb), board_ahci }, /* MCP77 */
peerchen6ba86952007-12-03 22:20:37 +0800554 { PCI_VDEVICE(NVIDIA, 0x0ab4), board_ahci }, /* MCP79 */
555 { PCI_VDEVICE(NVIDIA, 0x0ab5), board_ahci }, /* MCP79 */
556 { PCI_VDEVICE(NVIDIA, 0x0ab6), board_ahci }, /* MCP79 */
557 { PCI_VDEVICE(NVIDIA, 0x0ab7), board_ahci }, /* MCP79 */
Peer Chen71008192007-09-24 10:16:25 +0800558 { PCI_VDEVICE(NVIDIA, 0x0ab8), board_ahci }, /* MCP79 */
559 { PCI_VDEVICE(NVIDIA, 0x0ab9), board_ahci }, /* MCP79 */
560 { PCI_VDEVICE(NVIDIA, 0x0aba), board_ahci }, /* MCP79 */
561 { PCI_VDEVICE(NVIDIA, 0x0abb), board_ahci }, /* MCP79 */
562 { PCI_VDEVICE(NVIDIA, 0x0abc), board_ahci }, /* MCP79 */
563 { PCI_VDEVICE(NVIDIA, 0x0abd), board_ahci }, /* MCP79 */
564 { PCI_VDEVICE(NVIDIA, 0x0abe), board_ahci }, /* MCP79 */
565 { PCI_VDEVICE(NVIDIA, 0x0abf), board_ahci }, /* MCP79 */
peerchen70d562c2008-03-06 21:22:41 +0800566 { PCI_VDEVICE(NVIDIA, 0x0bc8), board_ahci }, /* MCP7B */
567 { PCI_VDEVICE(NVIDIA, 0x0bc9), board_ahci }, /* MCP7B */
568 { PCI_VDEVICE(NVIDIA, 0x0bca), board_ahci }, /* MCP7B */
569 { PCI_VDEVICE(NVIDIA, 0x0bcb), board_ahci }, /* MCP7B */
570 { PCI_VDEVICE(NVIDIA, 0x0bcc), board_ahci }, /* MCP7B */
571 { PCI_VDEVICE(NVIDIA, 0x0bcd), board_ahci }, /* MCP7B */
572 { PCI_VDEVICE(NVIDIA, 0x0bce), board_ahci }, /* MCP7B */
573 { PCI_VDEVICE(NVIDIA, 0x0bcf), board_ahci }, /* MCP7B */
peerchen3072c372008-05-19 14:44:57 +0800574 { PCI_VDEVICE(NVIDIA, 0x0bc4), board_ahci }, /* MCP7B */
575 { PCI_VDEVICE(NVIDIA, 0x0bc5), board_ahci }, /* MCP7B */
576 { PCI_VDEVICE(NVIDIA, 0x0bc6), board_ahci }, /* MCP7B */
577 { PCI_VDEVICE(NVIDIA, 0x0bc7), board_ahci }, /* MCP7B */
Jeff Garzikfe7fa312006-06-22 23:05:36 -0400578
Jeff Garzik95916ed2006-07-29 04:10:14 -0400579 /* SiS */
Tejun Heo20e2de42008-08-01 12:51:43 +0900580 { PCI_VDEVICE(SI, 0x1184), board_ahci }, /* SiS 966 */
581 { PCI_VDEVICE(SI, 0x1185), board_ahci }, /* SiS 968 */
582 { PCI_VDEVICE(SI, 0x0186), board_ahci }, /* SiS 968 */
Jeff Garzik95916ed2006-07-29 04:10:14 -0400583
Jeff Garzikcd70c262007-07-08 02:29:42 -0400584 /* Marvell */
585 { PCI_VDEVICE(MARVELL, 0x6145), board_ahci_mv }, /* 6145 */
Jose Alberto Regueroc40e7cb2008-03-13 23:22:24 +0100586 { PCI_VDEVICE(MARVELL, 0x6121), board_ahci_mv }, /* 6121 */
Jeff Garzikcd70c262007-07-08 02:29:42 -0400587
Jeff Garzik415ae2b2006-11-01 05:10:42 -0500588 /* Generic, PCI class code for AHCI */
589 { PCI_ANY_ID, PCI_ANY_ID, PCI_ANY_ID, PCI_ANY_ID,
Conke Huc9f89472007-01-09 05:32:51 -0500590 PCI_CLASS_STORAGE_SATA_AHCI, 0xffffff, board_ahci },
Jeff Garzik415ae2b2006-11-01 05:10:42 -0500591
Linus Torvalds1da177e2005-04-16 15:20:36 -0700592 { } /* terminate list */
593};
594
595
596static struct pci_driver ahci_pci_driver = {
597 .name = DRV_NAME,
598 .id_table = ahci_pci_tbl,
599 .probe = ahci_init_one,
Tejun Heo24dc5f32007-01-20 16:00:28 +0900600 .remove = ata_pci_remove_one,
Tejun Heo438ac6d2007-03-02 17:31:26 +0900601#ifdef CONFIG_PM
Tejun Heoc1332872006-07-26 15:59:26 +0900602 .suspend = ahci_pci_device_suspend,
603 .resume = ahci_pci_device_resume,
Tejun Heo438ac6d2007-03-02 17:31:26 +0900604#endif
Linus Torvalds1da177e2005-04-16 15:20:36 -0700605};
606
Kristen Carlson Accardi18f7ba42008-06-03 10:33:55 -0700607static int ahci_em_messages = 1;
608module_param(ahci_em_messages, int, 0444);
609/* add other LED protocol types when they become supported */
610MODULE_PARM_DESC(ahci_em_messages,
611 "Set AHCI Enclosure Management Message type (0 = disabled, 1 = LED");
Linus Torvalds1da177e2005-04-16 15:20:36 -0700612
Alan Cox5b66c822008-09-03 14:48:34 +0100613#if defined(CONFIG_PATA_MARVELL) || defined(CONFIG_PATA_MARVELL_MODULE)
614static int marvell_enable;
615#else
616static int marvell_enable = 1;
617#endif
618module_param(marvell_enable, int, 0644);
619MODULE_PARM_DESC(marvell_enable, "Marvell SATA via AHCI (1 = enabled)");
620
621
Tejun Heo98fa4b62006-11-02 12:17:23 +0900622static inline int ahci_nr_ports(u32 cap)
623{
624 return (cap & 0x1f) + 1;
625}
626
Jeff Garzikdab632e2007-05-28 08:33:01 -0400627static inline void __iomem *__ahci_port_base(struct ata_host *host,
628 unsigned int port_no)
629{
630 void __iomem *mmio = host->iomap[AHCI_PCI_BAR];
631
632 return mmio + 0x100 + (port_no * 0x80);
633}
634
Tejun Heo4447d352007-04-17 23:44:08 +0900635static inline void __iomem *ahci_port_base(struct ata_port *ap)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700636{
Jeff Garzikdab632e2007-05-28 08:33:01 -0400637 return __ahci_port_base(ap->host, ap->port_no);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700638}
639
Tejun Heob710a1f2008-01-05 23:11:57 +0900640static void ahci_enable_ahci(void __iomem *mmio)
641{
Tejun Heo15fe9822008-04-23 20:52:58 +0900642 int i;
Tejun Heob710a1f2008-01-05 23:11:57 +0900643 u32 tmp;
644
645 /* turn on AHCI_EN */
646 tmp = readl(mmio + HOST_CTL);
Tejun Heo15fe9822008-04-23 20:52:58 +0900647 if (tmp & HOST_AHCI_EN)
648 return;
649
650 /* Some controllers need AHCI_EN to be written multiple times.
651 * Try a few times before giving up.
652 */
653 for (i = 0; i < 5; i++) {
Tejun Heob710a1f2008-01-05 23:11:57 +0900654 tmp |= HOST_AHCI_EN;
655 writel(tmp, mmio + HOST_CTL);
656 tmp = readl(mmio + HOST_CTL); /* flush && sanity check */
Tejun Heo15fe9822008-04-23 20:52:58 +0900657 if (tmp & HOST_AHCI_EN)
658 return;
659 msleep(10);
Tejun Heob710a1f2008-01-05 23:11:57 +0900660 }
Tejun Heo15fe9822008-04-23 20:52:58 +0900661
662 WARN_ON(1);
Tejun Heob710a1f2008-01-05 23:11:57 +0900663}
664
Tejun Heod447df12007-03-18 22:15:33 +0900665/**
666 * ahci_save_initial_config - Save and fixup initial config values
Tejun Heo4447d352007-04-17 23:44:08 +0900667 * @pdev: target PCI device
Tejun Heo4447d352007-04-17 23:44:08 +0900668 * @hpriv: host private area to store config values
Tejun Heod447df12007-03-18 22:15:33 +0900669 *
670 * Some registers containing configuration info might be setup by
671 * BIOS and might be cleared on reset. This function saves the
672 * initial values of those registers into @hpriv such that they
673 * can be restored after controller reset.
674 *
675 * If inconsistent, config values are fixed up by this function.
676 *
677 * LOCKING:
678 * None.
679 */
Tejun Heo4447d352007-04-17 23:44:08 +0900680static void ahci_save_initial_config(struct pci_dev *pdev,
Tejun Heo4447d352007-04-17 23:44:08 +0900681 struct ahci_host_priv *hpriv)
Tejun Heod447df12007-03-18 22:15:33 +0900682{
Tejun Heo4447d352007-04-17 23:44:08 +0900683 void __iomem *mmio = pcim_iomap_table(pdev)[AHCI_PCI_BAR];
Tejun Heod447df12007-03-18 22:15:33 +0900684 u32 cap, port_map;
Tejun Heo17199b12007-03-18 22:26:53 +0900685 int i;
Jose Alberto Regueroc40e7cb2008-03-13 23:22:24 +0100686 int mv;
Tejun Heod447df12007-03-18 22:15:33 +0900687
Tejun Heob710a1f2008-01-05 23:11:57 +0900688 /* make sure AHCI mode is enabled before accessing CAP */
689 ahci_enable_ahci(mmio);
690
Tejun Heod447df12007-03-18 22:15:33 +0900691 /* Values prefixed with saved_ are written back to host after
692 * reset. Values without are used for driver operation.
693 */
694 hpriv->saved_cap = cap = readl(mmio + HOST_CAP);
695 hpriv->saved_port_map = port_map = readl(mmio + HOST_PORTS_IMPL);
696
Tejun Heo274c1fd2007-07-16 14:29:40 +0900697 /* some chips have errata preventing 64bit use */
Tejun Heo417a1a62007-09-23 13:19:55 +0900698 if ((cap & HOST_CAP_64) && (hpriv->flags & AHCI_HFLAG_32BIT_ONLY)) {
Tejun Heoc7a42152007-05-18 16:23:19 +0200699 dev_printk(KERN_INFO, &pdev->dev,
700 "controller can't do 64bit DMA, forcing 32bit\n");
701 cap &= ~HOST_CAP_64;
702 }
703
Tejun Heo417a1a62007-09-23 13:19:55 +0900704 if ((cap & HOST_CAP_NCQ) && (hpriv->flags & AHCI_HFLAG_NO_NCQ)) {
Tejun Heo274c1fd2007-07-16 14:29:40 +0900705 dev_printk(KERN_INFO, &pdev->dev,
706 "controller can't do NCQ, turning off CAP_NCQ\n");
707 cap &= ~HOST_CAP_NCQ;
708 }
709
Tejun Heoe297d992008-06-10 00:13:04 +0900710 if (!(cap & HOST_CAP_NCQ) && (hpriv->flags & AHCI_HFLAG_YES_NCQ)) {
711 dev_printk(KERN_INFO, &pdev->dev,
712 "controller can do NCQ, turning on CAP_NCQ\n");
713 cap |= HOST_CAP_NCQ;
714 }
715
Roel Kluin258cd842008-03-09 21:42:40 +0100716 if ((cap & HOST_CAP_PMP) && (hpriv->flags & AHCI_HFLAG_NO_PMP)) {
Tejun Heo6949b912007-09-23 13:19:55 +0900717 dev_printk(KERN_INFO, &pdev->dev,
718 "controller can't do PMP, turning off CAP_PMP\n");
719 cap &= ~HOST_CAP_PMP;
720 }
721
Tejun Heod799e082008-06-17 12:46:30 +0900722 if (pdev->vendor == PCI_VENDOR_ID_JMICRON && pdev->device == 0x2361 &&
723 port_map != 1) {
724 dev_printk(KERN_INFO, &pdev->dev,
725 "JMB361 has only one port, port_map 0x%x -> 0x%x\n",
726 port_map, 1);
727 port_map = 1;
728 }
729
Jeff Garzikcd70c262007-07-08 02:29:42 -0400730 /*
731 * Temporary Marvell 6145 hack: PATA port presence
732 * is asserted through the standard AHCI port
733 * presence register, as bit 4 (counting from 0)
734 */
Tejun Heo417a1a62007-09-23 13:19:55 +0900735 if (hpriv->flags & AHCI_HFLAG_MV_PATA) {
Jose Alberto Regueroc40e7cb2008-03-13 23:22:24 +0100736 if (pdev->device == 0x6121)
737 mv = 0x3;
738 else
739 mv = 0xf;
Jeff Garzikcd70c262007-07-08 02:29:42 -0400740 dev_printk(KERN_ERR, &pdev->dev,
741 "MV_AHCI HACK: port_map %x -> %x\n",
Jose Alberto Regueroc40e7cb2008-03-13 23:22:24 +0100742 port_map,
743 port_map & mv);
Alan Cox5b66c822008-09-03 14:48:34 +0100744 dev_printk(KERN_ERR, &pdev->dev,
745 "Disabling your PATA port. Use the boot option 'ahci.marvell_enable=0' to avoid this.\n");
Jeff Garzikcd70c262007-07-08 02:29:42 -0400746
Jose Alberto Regueroc40e7cb2008-03-13 23:22:24 +0100747 port_map &= mv;
Jeff Garzikcd70c262007-07-08 02:29:42 -0400748 }
749
Tejun Heo17199b12007-03-18 22:26:53 +0900750 /* cross check port_map and cap.n_ports */
Tejun Heo7a234af2007-09-03 12:44:57 +0900751 if (port_map) {
Tejun Heo837f5f82008-02-06 15:13:51 +0900752 int map_ports = 0;
Tejun Heo17199b12007-03-18 22:26:53 +0900753
Tejun Heo837f5f82008-02-06 15:13:51 +0900754 for (i = 0; i < AHCI_MAX_PORTS; i++)
755 if (port_map & (1 << i))
756 map_ports++;
Tejun Heo17199b12007-03-18 22:26:53 +0900757
Tejun Heo837f5f82008-02-06 15:13:51 +0900758 /* If PI has more ports than n_ports, whine, clear
759 * port_map and let it be generated from n_ports.
Tejun Heo17199b12007-03-18 22:26:53 +0900760 */
Tejun Heo837f5f82008-02-06 15:13:51 +0900761 if (map_ports > ahci_nr_ports(cap)) {
Tejun Heo4447d352007-04-17 23:44:08 +0900762 dev_printk(KERN_WARNING, &pdev->dev,
Tejun Heo837f5f82008-02-06 15:13:51 +0900763 "implemented port map (0x%x) contains more "
764 "ports than nr_ports (%u), using nr_ports\n",
765 port_map, ahci_nr_ports(cap));
Tejun Heo7a234af2007-09-03 12:44:57 +0900766 port_map = 0;
767 }
768 }
769
770 /* fabricate port_map from cap.nr_ports */
771 if (!port_map) {
Tejun Heo17199b12007-03-18 22:26:53 +0900772 port_map = (1 << ahci_nr_ports(cap)) - 1;
Tejun Heo7a234af2007-09-03 12:44:57 +0900773 dev_printk(KERN_WARNING, &pdev->dev,
774 "forcing PORTS_IMPL to 0x%x\n", port_map);
775
776 /* write the fixed up value to the PI register */
777 hpriv->saved_port_map = port_map;
Tejun Heo17199b12007-03-18 22:26:53 +0900778 }
779
Tejun Heod447df12007-03-18 22:15:33 +0900780 /* record values to use during operation */
781 hpriv->cap = cap;
782 hpriv->port_map = port_map;
783}
784
785/**
786 * ahci_restore_initial_config - Restore initial config
Tejun Heo4447d352007-04-17 23:44:08 +0900787 * @host: target ATA host
Tejun Heod447df12007-03-18 22:15:33 +0900788 *
789 * Restore initial config stored by ahci_save_initial_config().
790 *
791 * LOCKING:
792 * None.
793 */
Tejun Heo4447d352007-04-17 23:44:08 +0900794static void ahci_restore_initial_config(struct ata_host *host)
Tejun Heod447df12007-03-18 22:15:33 +0900795{
Tejun Heo4447d352007-04-17 23:44:08 +0900796 struct ahci_host_priv *hpriv = host->private_data;
797 void __iomem *mmio = host->iomap[AHCI_PCI_BAR];
798
Tejun Heod447df12007-03-18 22:15:33 +0900799 writel(hpriv->saved_cap, mmio + HOST_CAP);
800 writel(hpriv->saved_port_map, mmio + HOST_PORTS_IMPL);
801 (void) readl(mmio + HOST_PORTS_IMPL); /* flush */
802}
803
Tejun Heo203ef6c2007-07-16 14:29:40 +0900804static unsigned ahci_scr_offset(struct ata_port *ap, unsigned int sc_reg)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700805{
Tejun Heo203ef6c2007-07-16 14:29:40 +0900806 static const int offset[] = {
807 [SCR_STATUS] = PORT_SCR_STAT,
808 [SCR_CONTROL] = PORT_SCR_CTL,
809 [SCR_ERROR] = PORT_SCR_ERR,
810 [SCR_ACTIVE] = PORT_SCR_ACT,
811 [SCR_NOTIFICATION] = PORT_SCR_NTF,
812 };
813 struct ahci_host_priv *hpriv = ap->host->private_data;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700814
Tejun Heo203ef6c2007-07-16 14:29:40 +0900815 if (sc_reg < ARRAY_SIZE(offset) &&
816 (sc_reg != SCR_NOTIFICATION || (hpriv->cap & HOST_CAP_SNTF)))
817 return offset[sc_reg];
Tejun Heoda3dbb12007-07-16 14:29:40 +0900818 return 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700819}
820
Tejun Heo203ef6c2007-07-16 14:29:40 +0900821static int ahci_scr_read(struct ata_port *ap, unsigned int sc_reg, u32 *val)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700822{
Tejun Heo203ef6c2007-07-16 14:29:40 +0900823 void __iomem *port_mmio = ahci_port_base(ap);
824 int offset = ahci_scr_offset(ap, sc_reg);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700825
Tejun Heo203ef6c2007-07-16 14:29:40 +0900826 if (offset) {
827 *val = readl(port_mmio + offset);
828 return 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700829 }
Tejun Heo203ef6c2007-07-16 14:29:40 +0900830 return -EINVAL;
831}
Linus Torvalds1da177e2005-04-16 15:20:36 -0700832
Tejun Heo203ef6c2007-07-16 14:29:40 +0900833static int ahci_scr_write(struct ata_port *ap, unsigned int sc_reg, u32 val)
834{
835 void __iomem *port_mmio = ahci_port_base(ap);
836 int offset = ahci_scr_offset(ap, sc_reg);
837
838 if (offset) {
839 writel(val, port_mmio + offset);
840 return 0;
841 }
842 return -EINVAL;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700843}
844
Tejun Heo4447d352007-04-17 23:44:08 +0900845static void ahci_start_engine(struct ata_port *ap)
Tejun Heo7c76d1e2005-12-19 22:36:34 +0900846{
Tejun Heo4447d352007-04-17 23:44:08 +0900847 void __iomem *port_mmio = ahci_port_base(ap);
Tejun Heo7c76d1e2005-12-19 22:36:34 +0900848 u32 tmp;
849
Tejun Heod8fcd112006-07-26 15:59:25 +0900850 /* start DMA */
Tejun Heo9f592052006-07-26 15:59:26 +0900851 tmp = readl(port_mmio + PORT_CMD);
Tejun Heo7c76d1e2005-12-19 22:36:34 +0900852 tmp |= PORT_CMD_START;
853 writel(tmp, port_mmio + PORT_CMD);
854 readl(port_mmio + PORT_CMD); /* flush */
855}
856
Tejun Heo4447d352007-04-17 23:44:08 +0900857static int ahci_stop_engine(struct ata_port *ap)
Tejun Heo254950c2006-07-26 15:59:25 +0900858{
Tejun Heo4447d352007-04-17 23:44:08 +0900859 void __iomem *port_mmio = ahci_port_base(ap);
Tejun Heo254950c2006-07-26 15:59:25 +0900860 u32 tmp;
861
862 tmp = readl(port_mmio + PORT_CMD);
863
Tejun Heod8fcd112006-07-26 15:59:25 +0900864 /* check if the HBA is idle */
Tejun Heo254950c2006-07-26 15:59:25 +0900865 if ((tmp & (PORT_CMD_START | PORT_CMD_LIST_ON)) == 0)
866 return 0;
867
Tejun Heod8fcd112006-07-26 15:59:25 +0900868 /* setting HBA to idle */
Tejun Heo254950c2006-07-26 15:59:25 +0900869 tmp &= ~PORT_CMD_START;
870 writel(tmp, port_mmio + PORT_CMD);
871
Tejun Heod8fcd112006-07-26 15:59:25 +0900872 /* wait for engine to stop. This could be as long as 500 msec */
Tejun Heo254950c2006-07-26 15:59:25 +0900873 tmp = ata_wait_register(port_mmio + PORT_CMD,
Jeff Garzik2dcb4072007-10-19 06:42:56 -0400874 PORT_CMD_LIST_ON, PORT_CMD_LIST_ON, 1, 500);
Tejun Heod8fcd112006-07-26 15:59:25 +0900875 if (tmp & PORT_CMD_LIST_ON)
Tejun Heo254950c2006-07-26 15:59:25 +0900876 return -EIO;
877
878 return 0;
879}
880
Tejun Heo4447d352007-04-17 23:44:08 +0900881static void ahci_start_fis_rx(struct ata_port *ap)
Tejun Heo0be0aa92006-07-26 15:59:26 +0900882{
Tejun Heo4447d352007-04-17 23:44:08 +0900883 void __iomem *port_mmio = ahci_port_base(ap);
884 struct ahci_host_priv *hpriv = ap->host->private_data;
885 struct ahci_port_priv *pp = ap->private_data;
Tejun Heo0be0aa92006-07-26 15:59:26 +0900886 u32 tmp;
887
888 /* set FIS registers */
Tejun Heo4447d352007-04-17 23:44:08 +0900889 if (hpriv->cap & HOST_CAP_64)
890 writel((pp->cmd_slot_dma >> 16) >> 16,
891 port_mmio + PORT_LST_ADDR_HI);
892 writel(pp->cmd_slot_dma & 0xffffffff, port_mmio + PORT_LST_ADDR);
Tejun Heo0be0aa92006-07-26 15:59:26 +0900893
Tejun Heo4447d352007-04-17 23:44:08 +0900894 if (hpriv->cap & HOST_CAP_64)
895 writel((pp->rx_fis_dma >> 16) >> 16,
896 port_mmio + PORT_FIS_ADDR_HI);
897 writel(pp->rx_fis_dma & 0xffffffff, port_mmio + PORT_FIS_ADDR);
Tejun Heo0be0aa92006-07-26 15:59:26 +0900898
899 /* enable FIS reception */
900 tmp = readl(port_mmio + PORT_CMD);
901 tmp |= PORT_CMD_FIS_RX;
902 writel(tmp, port_mmio + PORT_CMD);
903
904 /* flush */
905 readl(port_mmio + PORT_CMD);
906}
907
Tejun Heo4447d352007-04-17 23:44:08 +0900908static int ahci_stop_fis_rx(struct ata_port *ap)
Tejun Heo0be0aa92006-07-26 15:59:26 +0900909{
Tejun Heo4447d352007-04-17 23:44:08 +0900910 void __iomem *port_mmio = ahci_port_base(ap);
Tejun Heo0be0aa92006-07-26 15:59:26 +0900911 u32 tmp;
912
913 /* disable FIS reception */
914 tmp = readl(port_mmio + PORT_CMD);
915 tmp &= ~PORT_CMD_FIS_RX;
916 writel(tmp, port_mmio + PORT_CMD);
917
918 /* wait for completion, spec says 500ms, give it 1000 */
919 tmp = ata_wait_register(port_mmio + PORT_CMD, PORT_CMD_FIS_ON,
920 PORT_CMD_FIS_ON, 10, 1000);
921 if (tmp & PORT_CMD_FIS_ON)
922 return -EBUSY;
923
924 return 0;
925}
926
Tejun Heo4447d352007-04-17 23:44:08 +0900927static void ahci_power_up(struct ata_port *ap)
Tejun Heo0be0aa92006-07-26 15:59:26 +0900928{
Tejun Heo4447d352007-04-17 23:44:08 +0900929 struct ahci_host_priv *hpriv = ap->host->private_data;
930 void __iomem *port_mmio = ahci_port_base(ap);
Tejun Heo0be0aa92006-07-26 15:59:26 +0900931 u32 cmd;
932
933 cmd = readl(port_mmio + PORT_CMD) & ~PORT_CMD_ICC_MASK;
934
935 /* spin up device */
Tejun Heo4447d352007-04-17 23:44:08 +0900936 if (hpriv->cap & HOST_CAP_SSS) {
Tejun Heo0be0aa92006-07-26 15:59:26 +0900937 cmd |= PORT_CMD_SPIN_UP;
938 writel(cmd, port_mmio + PORT_CMD);
939 }
940
941 /* wake up link */
942 writel(cmd | PORT_CMD_ICC_ACTIVE, port_mmio + PORT_CMD);
943}
944
Kristen Carlson Accardi31556592007-10-25 01:33:26 -0400945static void ahci_disable_alpm(struct ata_port *ap)
946{
947 struct ahci_host_priv *hpriv = ap->host->private_data;
948 void __iomem *port_mmio = ahci_port_base(ap);
949 u32 cmd;
950 struct ahci_port_priv *pp = ap->private_data;
951
952 /* IPM bits should be disabled by libata-core */
953 /* get the existing command bits */
954 cmd = readl(port_mmio + PORT_CMD);
955
956 /* disable ALPM and ASP */
957 cmd &= ~PORT_CMD_ASP;
958 cmd &= ~PORT_CMD_ALPE;
959
960 /* force the interface back to active */
961 cmd |= PORT_CMD_ICC_ACTIVE;
962
963 /* write out new cmd value */
964 writel(cmd, port_mmio + PORT_CMD);
965 cmd = readl(port_mmio + PORT_CMD);
966
967 /* wait 10ms to be sure we've come out of any low power state */
968 msleep(10);
969
970 /* clear out any PhyRdy stuff from interrupt status */
971 writel(PORT_IRQ_PHYRDY, port_mmio + PORT_IRQ_STAT);
972
973 /* go ahead and clean out PhyRdy Change from Serror too */
974 ahci_scr_write(ap, SCR_ERROR, ((1 << 16) | (1 << 18)));
975
976 /*
977 * Clear flag to indicate that we should ignore all PhyRdy
978 * state changes
979 */
980 hpriv->flags &= ~AHCI_HFLAG_NO_HOTPLUG;
981
982 /*
983 * Enable interrupts on Phy Ready.
984 */
985 pp->intr_mask |= PORT_IRQ_PHYRDY;
986 writel(pp->intr_mask, port_mmio + PORT_IRQ_MASK);
987
988 /*
989 * don't change the link pm policy - we can be called
990 * just to turn of link pm temporarily
991 */
992}
993
994static int ahci_enable_alpm(struct ata_port *ap,
995 enum link_pm policy)
996{
997 struct ahci_host_priv *hpriv = ap->host->private_data;
998 void __iomem *port_mmio = ahci_port_base(ap);
999 u32 cmd;
1000 struct ahci_port_priv *pp = ap->private_data;
1001 u32 asp;
1002
1003 /* Make sure the host is capable of link power management */
1004 if (!(hpriv->cap & HOST_CAP_ALPM))
1005 return -EINVAL;
1006
1007 switch (policy) {
1008 case MAX_PERFORMANCE:
1009 case NOT_AVAILABLE:
1010 /*
1011 * if we came here with NOT_AVAILABLE,
1012 * it just means this is the first time we
1013 * have tried to enable - default to max performance,
1014 * and let the user go to lower power modes on request.
1015 */
1016 ahci_disable_alpm(ap);
1017 return 0;
1018 case MIN_POWER:
1019 /* configure HBA to enter SLUMBER */
1020 asp = PORT_CMD_ASP;
1021 break;
1022 case MEDIUM_POWER:
1023 /* configure HBA to enter PARTIAL */
1024 asp = 0;
1025 break;
1026 default:
1027 return -EINVAL;
1028 }
1029
1030 /*
1031 * Disable interrupts on Phy Ready. This keeps us from
1032 * getting woken up due to spurious phy ready interrupts
1033 * TBD - Hot plug should be done via polling now, is
1034 * that even supported?
1035 */
1036 pp->intr_mask &= ~PORT_IRQ_PHYRDY;
1037 writel(pp->intr_mask, port_mmio + PORT_IRQ_MASK);
1038
1039 /*
1040 * Set a flag to indicate that we should ignore all PhyRdy
1041 * state changes since these can happen now whenever we
1042 * change link state
1043 */
1044 hpriv->flags |= AHCI_HFLAG_NO_HOTPLUG;
1045
1046 /* get the existing command bits */
1047 cmd = readl(port_mmio + PORT_CMD);
1048
1049 /*
1050 * Set ASP based on Policy
1051 */
1052 cmd |= asp;
1053
1054 /*
1055 * Setting this bit will instruct the HBA to aggressively
1056 * enter a lower power link state when it's appropriate and
1057 * based on the value set above for ASP
1058 */
1059 cmd |= PORT_CMD_ALPE;
1060
1061 /* write out new cmd value */
1062 writel(cmd, port_mmio + PORT_CMD);
1063 cmd = readl(port_mmio + PORT_CMD);
1064
1065 /* IPM bits should be set by libata-core */
1066 return 0;
1067}
1068
Tejun Heo438ac6d2007-03-02 17:31:26 +09001069#ifdef CONFIG_PM
Tejun Heo4447d352007-04-17 23:44:08 +09001070static void ahci_power_down(struct ata_port *ap)
Tejun Heo0be0aa92006-07-26 15:59:26 +09001071{
Tejun Heo4447d352007-04-17 23:44:08 +09001072 struct ahci_host_priv *hpriv = ap->host->private_data;
1073 void __iomem *port_mmio = ahci_port_base(ap);
Tejun Heo0be0aa92006-07-26 15:59:26 +09001074 u32 cmd, scontrol;
1075
Tejun Heo4447d352007-04-17 23:44:08 +09001076 if (!(hpriv->cap & HOST_CAP_SSS))
Tejun Heo07c53da2007-01-21 02:10:11 +09001077 return;
1078
1079 /* put device into listen mode, first set PxSCTL.DET to 0 */
1080 scontrol = readl(port_mmio + PORT_SCR_CTL);
1081 scontrol &= ~0xf;
1082 writel(scontrol, port_mmio + PORT_SCR_CTL);
1083
1084 /* then set PxCMD.SUD to 0 */
Tejun Heo0be0aa92006-07-26 15:59:26 +09001085 cmd = readl(port_mmio + PORT_CMD) & ~PORT_CMD_ICC_MASK;
Tejun Heo07c53da2007-01-21 02:10:11 +09001086 cmd &= ~PORT_CMD_SPIN_UP;
1087 writel(cmd, port_mmio + PORT_CMD);
Tejun Heo0be0aa92006-07-26 15:59:26 +09001088}
Tejun Heo438ac6d2007-03-02 17:31:26 +09001089#endif
Tejun Heo0be0aa92006-07-26 15:59:26 +09001090
Jeff Garzikdf69c9c2007-05-26 20:46:51 -04001091static void ahci_start_port(struct ata_port *ap)
Tejun Heo0be0aa92006-07-26 15:59:26 +09001092{
Kristen Carlson Accardi18f7ba42008-06-03 10:33:55 -07001093 struct ahci_port_priv *pp = ap->private_data;
1094 struct ata_link *link;
1095 struct ahci_em_priv *emp;
1096
Tejun Heo0be0aa92006-07-26 15:59:26 +09001097 /* enable FIS reception */
Tejun Heo4447d352007-04-17 23:44:08 +09001098 ahci_start_fis_rx(ap);
Tejun Heo0be0aa92006-07-26 15:59:26 +09001099
1100 /* enable DMA */
Tejun Heo4447d352007-04-17 23:44:08 +09001101 ahci_start_engine(ap);
Kristen Carlson Accardi18f7ba42008-06-03 10:33:55 -07001102
1103 /* turn on LEDs */
1104 if (ap->flags & ATA_FLAG_EM) {
1105 ata_port_for_each_link(link, ap) {
1106 emp = &pp->em_priv[link->pmp];
1107 ahci_transmit_led_message(ap, emp->led_state, 4);
1108 }
1109 }
1110
1111 if (ap->flags & ATA_FLAG_SW_ACTIVITY)
1112 ata_port_for_each_link(link, ap)
1113 ahci_init_sw_activity(link);
1114
Tejun Heo0be0aa92006-07-26 15:59:26 +09001115}
1116
Tejun Heo4447d352007-04-17 23:44:08 +09001117static int ahci_deinit_port(struct ata_port *ap, const char **emsg)
Tejun Heo0be0aa92006-07-26 15:59:26 +09001118{
1119 int rc;
1120
1121 /* disable DMA */
Tejun Heo4447d352007-04-17 23:44:08 +09001122 rc = ahci_stop_engine(ap);
Tejun Heo0be0aa92006-07-26 15:59:26 +09001123 if (rc) {
1124 *emsg = "failed to stop engine";
1125 return rc;
1126 }
1127
1128 /* disable FIS reception */
Tejun Heo4447d352007-04-17 23:44:08 +09001129 rc = ahci_stop_fis_rx(ap);
Tejun Heo0be0aa92006-07-26 15:59:26 +09001130 if (rc) {
1131 *emsg = "failed stop FIS RX";
1132 return rc;
1133 }
1134
Tejun Heo0be0aa92006-07-26 15:59:26 +09001135 return 0;
1136}
1137
Tejun Heo4447d352007-04-17 23:44:08 +09001138static int ahci_reset_controller(struct ata_host *host)
Tejun Heod91542c2006-07-26 15:59:26 +09001139{
Tejun Heo4447d352007-04-17 23:44:08 +09001140 struct pci_dev *pdev = to_pci_dev(host->dev);
Tejun Heo49f29092007-11-19 16:03:44 +09001141 struct ahci_host_priv *hpriv = host->private_data;
Tejun Heo4447d352007-04-17 23:44:08 +09001142 void __iomem *mmio = host->iomap[AHCI_PCI_BAR];
Tejun Heod447df12007-03-18 22:15:33 +09001143 u32 tmp;
Tejun Heod91542c2006-07-26 15:59:26 +09001144
Jeff Garzik3cc3eb12007-09-26 00:02:41 -04001145 /* we must be in AHCI mode, before using anything
1146 * AHCI-specific, such as HOST_RESET.
1147 */
Tejun Heob710a1f2008-01-05 23:11:57 +09001148 ahci_enable_ahci(mmio);
Jeff Garzik3cc3eb12007-09-26 00:02:41 -04001149
1150 /* global controller reset */
Tejun Heoa22e6442008-03-10 10:25:25 +09001151 if (!ahci_skip_host_reset) {
1152 tmp = readl(mmio + HOST_CTL);
1153 if ((tmp & HOST_RESET) == 0) {
1154 writel(tmp | HOST_RESET, mmio + HOST_CTL);
1155 readl(mmio + HOST_CTL); /* flush */
1156 }
Tejun Heod91542c2006-07-26 15:59:26 +09001157
Zhang Rui24920c82008-07-04 13:32:17 +08001158 /*
1159 * to perform host reset, OS should set HOST_RESET
1160 * and poll until this bit is read to be "0".
1161 * reset must complete within 1 second, or
Tejun Heoa22e6442008-03-10 10:25:25 +09001162 * the hardware should be considered fried.
1163 */
Zhang Rui24920c82008-07-04 13:32:17 +08001164 tmp = ata_wait_register(mmio + HOST_CTL, HOST_RESET,
1165 HOST_RESET, 10, 1000);
Tejun Heod91542c2006-07-26 15:59:26 +09001166
Tejun Heoa22e6442008-03-10 10:25:25 +09001167 if (tmp & HOST_RESET) {
1168 dev_printk(KERN_ERR, host->dev,
1169 "controller reset failed (0x%x)\n", tmp);
1170 return -EIO;
1171 }
Tejun Heod91542c2006-07-26 15:59:26 +09001172
Tejun Heoa22e6442008-03-10 10:25:25 +09001173 /* turn on AHCI mode */
1174 ahci_enable_ahci(mmio);
Tejun Heo98fa4b62006-11-02 12:17:23 +09001175
Tejun Heoa22e6442008-03-10 10:25:25 +09001176 /* Some registers might be cleared on reset. Restore
1177 * initial values.
1178 */
1179 ahci_restore_initial_config(host);
1180 } else
1181 dev_printk(KERN_INFO, host->dev,
1182 "skipping global host reset\n");
Tejun Heod91542c2006-07-26 15:59:26 +09001183
1184 if (pdev->vendor == PCI_VENDOR_ID_INTEL) {
1185 u16 tmp16;
1186
1187 /* configure PCS */
1188 pci_read_config_word(pdev, 0x92, &tmp16);
Tejun Heo49f29092007-11-19 16:03:44 +09001189 if ((tmp16 & hpriv->port_map) != hpriv->port_map) {
1190 tmp16 |= hpriv->port_map;
1191 pci_write_config_word(pdev, 0x92, tmp16);
1192 }
Tejun Heod91542c2006-07-26 15:59:26 +09001193 }
1194
1195 return 0;
1196}
1197
Kristen Carlson Accardi18f7ba42008-06-03 10:33:55 -07001198static void ahci_sw_activity(struct ata_link *link)
1199{
1200 struct ata_port *ap = link->ap;
1201 struct ahci_port_priv *pp = ap->private_data;
1202 struct ahci_em_priv *emp = &pp->em_priv[link->pmp];
1203
1204 if (!(link->flags & ATA_LFLAG_SW_ACTIVITY))
1205 return;
1206
1207 emp->activity++;
1208 if (!timer_pending(&emp->timer))
1209 mod_timer(&emp->timer, jiffies + msecs_to_jiffies(10));
1210}
1211
1212static void ahci_sw_activity_blink(unsigned long arg)
1213{
1214 struct ata_link *link = (struct ata_link *)arg;
1215 struct ata_port *ap = link->ap;
1216 struct ahci_port_priv *pp = ap->private_data;
1217 struct ahci_em_priv *emp = &pp->em_priv[link->pmp];
1218 unsigned long led_message = emp->led_state;
1219 u32 activity_led_state;
1220
1221 led_message &= 0xffff0000;
1222 led_message |= ap->port_no | (link->pmp << 8);
1223
1224 /* check to see if we've had activity. If so,
1225 * toggle state of LED and reset timer. If not,
1226 * turn LED to desired idle state.
1227 */
1228 if (emp->saved_activity != emp->activity) {
1229 emp->saved_activity = emp->activity;
1230 /* get the current LED state */
1231 activity_led_state = led_message & 0x00010000;
1232
1233 if (activity_led_state)
1234 activity_led_state = 0;
1235 else
1236 activity_led_state = 1;
1237
1238 /* clear old state */
1239 led_message &= 0xfff8ffff;
1240
1241 /* toggle state */
1242 led_message |= (activity_led_state << 16);
1243 mod_timer(&emp->timer, jiffies + msecs_to_jiffies(100));
1244 } else {
1245 /* switch to idle */
1246 led_message &= 0xfff8ffff;
1247 if (emp->blink_policy == BLINK_OFF)
1248 led_message |= (1 << 16);
1249 }
1250 ahci_transmit_led_message(ap, led_message, 4);
1251}
1252
1253static void ahci_init_sw_activity(struct ata_link *link)
1254{
1255 struct ata_port *ap = link->ap;
1256 struct ahci_port_priv *pp = ap->private_data;
1257 struct ahci_em_priv *emp = &pp->em_priv[link->pmp];
1258
1259 /* init activity stats, setup timer */
1260 emp->saved_activity = emp->activity = 0;
1261 setup_timer(&emp->timer, ahci_sw_activity_blink, (unsigned long)link);
1262
1263 /* check our blink policy and set flag for link if it's enabled */
1264 if (emp->blink_policy)
1265 link->flags |= ATA_LFLAG_SW_ACTIVITY;
1266}
1267
1268static int ahci_reset_em(struct ata_host *host)
1269{
1270 void __iomem *mmio = host->iomap[AHCI_PCI_BAR];
1271 u32 em_ctl;
1272
1273 em_ctl = readl(mmio + HOST_EM_CTL);
1274 if ((em_ctl & EM_CTL_TM) || (em_ctl & EM_CTL_RST))
1275 return -EINVAL;
1276
1277 writel(em_ctl | EM_CTL_RST, mmio + HOST_EM_CTL);
1278 return 0;
1279}
1280
1281static ssize_t ahci_transmit_led_message(struct ata_port *ap, u32 state,
1282 ssize_t size)
1283{
1284 struct ahci_host_priv *hpriv = ap->host->private_data;
1285 struct ahci_port_priv *pp = ap->private_data;
1286 void __iomem *mmio = ap->host->iomap[AHCI_PCI_BAR];
1287 u32 em_ctl;
1288 u32 message[] = {0, 0};
Linus Torvalds93082f02008-07-25 10:56:36 -07001289 unsigned long flags;
Kristen Carlson Accardi18f7ba42008-06-03 10:33:55 -07001290 int pmp;
1291 struct ahci_em_priv *emp;
1292
1293 /* get the slot number from the message */
1294 pmp = (state & 0x0000ff00) >> 8;
1295 if (pmp < MAX_SLOTS)
1296 emp = &pp->em_priv[pmp];
1297 else
1298 return -EINVAL;
1299
1300 spin_lock_irqsave(ap->lock, flags);
1301
1302 /*
1303 * if we are still busy transmitting a previous message,
1304 * do not allow
1305 */
1306 em_ctl = readl(mmio + HOST_EM_CTL);
1307 if (em_ctl & EM_CTL_TM) {
1308 spin_unlock_irqrestore(ap->lock, flags);
1309 return -EINVAL;
1310 }
1311
1312 /*
1313 * create message header - this is all zero except for
1314 * the message size, which is 4 bytes.
1315 */
1316 message[0] |= (4 << 8);
1317
1318 /* ignore 0:4 of byte zero, fill in port info yourself */
1319 message[1] = ((state & 0xfffffff0) | ap->port_no);
1320
1321 /* write message to EM_LOC */
1322 writel(message[0], mmio + hpriv->em_loc);
1323 writel(message[1], mmio + hpriv->em_loc+4);
1324
1325 /* save off new led state for port/slot */
1326 emp->led_state = message[1];
1327
1328 /*
1329 * tell hardware to transmit the message
1330 */
1331 writel(em_ctl | EM_CTL_TM, mmio + HOST_EM_CTL);
1332
1333 spin_unlock_irqrestore(ap->lock, flags);
1334 return size;
1335}
1336
1337static ssize_t ahci_led_show(struct ata_port *ap, char *buf)
1338{
1339 struct ahci_port_priv *pp = ap->private_data;
1340 struct ata_link *link;
1341 struct ahci_em_priv *emp;
1342 int rc = 0;
1343
1344 ata_port_for_each_link(link, ap) {
1345 emp = &pp->em_priv[link->pmp];
1346 rc += sprintf(buf, "%lx\n", emp->led_state);
1347 }
1348 return rc;
1349}
1350
1351static ssize_t ahci_led_store(struct ata_port *ap, const char *buf,
1352 size_t size)
1353{
1354 int state;
1355 int pmp;
1356 struct ahci_port_priv *pp = ap->private_data;
1357 struct ahci_em_priv *emp;
1358
1359 state = simple_strtoul(buf, NULL, 0);
1360
1361 /* get the slot number from the message */
1362 pmp = (state & 0x0000ff00) >> 8;
1363 if (pmp < MAX_SLOTS)
1364 emp = &pp->em_priv[pmp];
1365 else
1366 return -EINVAL;
1367
1368 /* mask off the activity bits if we are in sw_activity
1369 * mode, user should turn off sw_activity before setting
1370 * activity led through em_message
1371 */
1372 if (emp->blink_policy)
1373 state &= 0xfff8ffff;
1374
1375 return ahci_transmit_led_message(ap, state, size);
1376}
1377
1378static ssize_t ahci_activity_store(struct ata_device *dev, enum sw_activity val)
1379{
1380 struct ata_link *link = dev->link;
1381 struct ata_port *ap = link->ap;
1382 struct ahci_port_priv *pp = ap->private_data;
1383 struct ahci_em_priv *emp = &pp->em_priv[link->pmp];
1384 u32 port_led_state = emp->led_state;
1385
1386 /* save the desired Activity LED behavior */
1387 if (val == OFF) {
1388 /* clear LFLAG */
1389 link->flags &= ~(ATA_LFLAG_SW_ACTIVITY);
1390
1391 /* set the LED to OFF */
1392 port_led_state &= 0xfff80000;
1393 port_led_state |= (ap->port_no | (link->pmp << 8));
1394 ahci_transmit_led_message(ap, port_led_state, 4);
1395 } else {
1396 link->flags |= ATA_LFLAG_SW_ACTIVITY;
1397 if (val == BLINK_OFF) {
1398 /* set LED to ON for idle */
1399 port_led_state &= 0xfff80000;
1400 port_led_state |= (ap->port_no | (link->pmp << 8));
1401 port_led_state |= 0x00010000; /* check this */
1402 ahci_transmit_led_message(ap, port_led_state, 4);
1403 }
1404 }
1405 emp->blink_policy = val;
1406 return 0;
1407}
1408
1409static ssize_t ahci_activity_show(struct ata_device *dev, char *buf)
1410{
1411 struct ata_link *link = dev->link;
1412 struct ata_port *ap = link->ap;
1413 struct ahci_port_priv *pp = ap->private_data;
1414 struct ahci_em_priv *emp = &pp->em_priv[link->pmp];
1415
1416 /* display the saved value of activity behavior for this
1417 * disk.
1418 */
1419 return sprintf(buf, "%d\n", emp->blink_policy);
1420}
1421
Jeff Garzik2bcd8662007-05-28 07:45:27 -04001422static void ahci_port_init(struct pci_dev *pdev, struct ata_port *ap,
1423 int port_no, void __iomem *mmio,
1424 void __iomem *port_mmio)
1425{
1426 const char *emsg = NULL;
1427 int rc;
1428 u32 tmp;
1429
1430 /* make sure port is not active */
1431 rc = ahci_deinit_port(ap, &emsg);
1432 if (rc)
1433 dev_printk(KERN_WARNING, &pdev->dev,
1434 "%s (%d)\n", emsg, rc);
1435
1436 /* clear SError */
1437 tmp = readl(port_mmio + PORT_SCR_ERR);
1438 VPRINTK("PORT_SCR_ERR 0x%x\n", tmp);
1439 writel(tmp, port_mmio + PORT_SCR_ERR);
1440
1441 /* clear port IRQ */
1442 tmp = readl(port_mmio + PORT_IRQ_STAT);
1443 VPRINTK("PORT_IRQ_STAT 0x%x\n", tmp);
1444 if (tmp)
1445 writel(tmp, port_mmio + PORT_IRQ_STAT);
1446
1447 writel(1 << port_no, mmio + HOST_IRQ_STAT);
1448}
1449
Tejun Heo4447d352007-04-17 23:44:08 +09001450static void ahci_init_controller(struct ata_host *host)
Tejun Heod91542c2006-07-26 15:59:26 +09001451{
Tejun Heo417a1a62007-09-23 13:19:55 +09001452 struct ahci_host_priv *hpriv = host->private_data;
Tejun Heo4447d352007-04-17 23:44:08 +09001453 struct pci_dev *pdev = to_pci_dev(host->dev);
1454 void __iomem *mmio = host->iomap[AHCI_PCI_BAR];
Jeff Garzik2bcd8662007-05-28 07:45:27 -04001455 int i;
Jeff Garzikcd70c262007-07-08 02:29:42 -04001456 void __iomem *port_mmio;
Tejun Heod91542c2006-07-26 15:59:26 +09001457 u32 tmp;
Jose Alberto Regueroc40e7cb2008-03-13 23:22:24 +01001458 int mv;
Tejun Heod91542c2006-07-26 15:59:26 +09001459
Tejun Heo417a1a62007-09-23 13:19:55 +09001460 if (hpriv->flags & AHCI_HFLAG_MV_PATA) {
Jose Alberto Regueroc40e7cb2008-03-13 23:22:24 +01001461 if (pdev->device == 0x6121)
1462 mv = 2;
1463 else
1464 mv = 4;
1465 port_mmio = __ahci_port_base(host, mv);
Jeff Garzikcd70c262007-07-08 02:29:42 -04001466
1467 writel(0, port_mmio + PORT_IRQ_MASK);
1468
1469 /* clear port IRQ */
1470 tmp = readl(port_mmio + PORT_IRQ_STAT);
1471 VPRINTK("PORT_IRQ_STAT 0x%x\n", tmp);
1472 if (tmp)
1473 writel(tmp, port_mmio + PORT_IRQ_STAT);
1474 }
1475
Tejun Heo4447d352007-04-17 23:44:08 +09001476 for (i = 0; i < host->n_ports; i++) {
1477 struct ata_port *ap = host->ports[i];
Tejun Heod91542c2006-07-26 15:59:26 +09001478
Jeff Garzikcd70c262007-07-08 02:29:42 -04001479 port_mmio = ahci_port_base(ap);
Tejun Heo4447d352007-04-17 23:44:08 +09001480 if (ata_port_is_dummy(ap))
Tejun Heod91542c2006-07-26 15:59:26 +09001481 continue;
Tejun Heod91542c2006-07-26 15:59:26 +09001482
Jeff Garzik2bcd8662007-05-28 07:45:27 -04001483 ahci_port_init(pdev, ap, i, mmio, port_mmio);
Tejun Heod91542c2006-07-26 15:59:26 +09001484 }
1485
1486 tmp = readl(mmio + HOST_CTL);
1487 VPRINTK("HOST_CTL 0x%x\n", tmp);
1488 writel(tmp | HOST_IRQ_EN, mmio + HOST_CTL);
1489 tmp = readl(mmio + HOST_CTL);
1490 VPRINTK("HOST_CTL 0x%x\n", tmp);
1491}
1492
Jeff Garzika8785392008-02-28 15:43:48 -05001493static void ahci_dev_config(struct ata_device *dev)
1494{
1495 struct ahci_host_priv *hpriv = dev->link->ap->host->private_data;
1496
Jeff Garzik4cde32f2008-03-24 22:40:40 -04001497 if (hpriv->flags & AHCI_HFLAG_SECT255) {
Jeff Garzika8785392008-02-28 15:43:48 -05001498 dev->max_sectors = 255;
Jeff Garzik4cde32f2008-03-24 22:40:40 -04001499 ata_dev_printk(dev, KERN_INFO,
1500 "SB600 AHCI: limiting to 255 sectors per cmd\n");
1501 }
Jeff Garzika8785392008-02-28 15:43:48 -05001502}
1503
Tejun Heo422b7592005-12-19 22:37:17 +09001504static unsigned int ahci_dev_classify(struct ata_port *ap)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001505{
Tejun Heo4447d352007-04-17 23:44:08 +09001506 void __iomem *port_mmio = ahci_port_base(ap);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001507 struct ata_taskfile tf;
Tejun Heo422b7592005-12-19 22:37:17 +09001508 u32 tmp;
1509
1510 tmp = readl(port_mmio + PORT_SIG);
1511 tf.lbah = (tmp >> 24) & 0xff;
1512 tf.lbam = (tmp >> 16) & 0xff;
1513 tf.lbal = (tmp >> 8) & 0xff;
1514 tf.nsect = (tmp) & 0xff;
1515
1516 return ata_dev_classify(&tf);
1517}
1518
Tejun Heo12fad3f2006-05-15 21:03:55 +09001519static void ahci_fill_cmd_slot(struct ahci_port_priv *pp, unsigned int tag,
1520 u32 opts)
Tejun Heocc9278e2006-02-10 17:25:47 +09001521{
Tejun Heo12fad3f2006-05-15 21:03:55 +09001522 dma_addr_t cmd_tbl_dma;
1523
1524 cmd_tbl_dma = pp->cmd_tbl_dma + tag * AHCI_CMD_TBL_SZ;
1525
1526 pp->cmd_slot[tag].opts = cpu_to_le32(opts);
1527 pp->cmd_slot[tag].status = 0;
1528 pp->cmd_slot[tag].tbl_addr = cpu_to_le32(cmd_tbl_dma & 0xffffffff);
1529 pp->cmd_slot[tag].tbl_addr_hi = cpu_to_le32((cmd_tbl_dma >> 16) >> 16);
Tejun Heocc9278e2006-02-10 17:25:47 +09001530}
1531
Tejun Heod2e75df2007-07-16 14:29:39 +09001532static int ahci_kick_engine(struct ata_port *ap, int force_restart)
Bastiaan Jacquesbf2af2a2006-04-17 14:17:59 +02001533{
Tejun Heo350756f2008-04-07 22:47:21 +09001534 void __iomem *port_mmio = ahci_port_base(ap);
Jeff Garzikcca39742006-08-24 03:19:22 -04001535 struct ahci_host_priv *hpriv = ap->host->private_data;
Tejun Heo520d06f2008-04-07 22:47:21 +09001536 u8 status = readl(port_mmio + PORT_TFDATA) & 0xFF;
Bastiaan Jacquesbf2af2a2006-04-17 14:17:59 +02001537 u32 tmp;
Tejun Heod2e75df2007-07-16 14:29:39 +09001538 int busy, rc;
Bastiaan Jacquesbf2af2a2006-04-17 14:17:59 +02001539
Tejun Heod2e75df2007-07-16 14:29:39 +09001540 /* do we need to kick the port? */
Tejun Heo520d06f2008-04-07 22:47:21 +09001541 busy = status & (ATA_BUSY | ATA_DRQ);
Tejun Heod2e75df2007-07-16 14:29:39 +09001542 if (!busy && !force_restart)
1543 return 0;
Bastiaan Jacquesbf2af2a2006-04-17 14:17:59 +02001544
Tejun Heod2e75df2007-07-16 14:29:39 +09001545 /* stop engine */
1546 rc = ahci_stop_engine(ap);
1547 if (rc)
1548 goto out_restart;
1549
1550 /* need to do CLO? */
1551 if (!busy) {
1552 rc = 0;
1553 goto out_restart;
1554 }
1555
1556 if (!(hpriv->cap & HOST_CAP_CLO)) {
1557 rc = -EOPNOTSUPP;
1558 goto out_restart;
1559 }
1560
1561 /* perform CLO */
Bastiaan Jacquesbf2af2a2006-04-17 14:17:59 +02001562 tmp = readl(port_mmio + PORT_CMD);
1563 tmp |= PORT_CMD_CLO;
1564 writel(tmp, port_mmio + PORT_CMD);
1565
Tejun Heod2e75df2007-07-16 14:29:39 +09001566 rc = 0;
Bastiaan Jacquesbf2af2a2006-04-17 14:17:59 +02001567 tmp = ata_wait_register(port_mmio + PORT_CMD,
1568 PORT_CMD_CLO, PORT_CMD_CLO, 1, 500);
1569 if (tmp & PORT_CMD_CLO)
Tejun Heod2e75df2007-07-16 14:29:39 +09001570 rc = -EIO;
Bastiaan Jacquesbf2af2a2006-04-17 14:17:59 +02001571
Tejun Heod2e75df2007-07-16 14:29:39 +09001572 /* restart engine */
1573 out_restart:
1574 ahci_start_engine(ap);
1575 return rc;
Bastiaan Jacquesbf2af2a2006-04-17 14:17:59 +02001576}
1577
Tejun Heo91c4a2e2007-07-16 14:29:39 +09001578static int ahci_exec_polled_cmd(struct ata_port *ap, int pmp,
1579 struct ata_taskfile *tf, int is_cmd, u16 flags,
1580 unsigned long timeout_msec)
1581{
1582 const u32 cmd_fis_len = 5; /* five dwords */
1583 struct ahci_port_priv *pp = ap->private_data;
1584 void __iomem *port_mmio = ahci_port_base(ap);
1585 u8 *fis = pp->cmd_tbl;
1586 u32 tmp;
1587
1588 /* prep the command */
1589 ata_tf_to_fis(tf, pmp, is_cmd, fis);
1590 ahci_fill_cmd_slot(pp, 0, cmd_fis_len | flags | (pmp << 12));
1591
1592 /* issue & wait */
1593 writel(1, port_mmio + PORT_CMD_ISSUE);
1594
1595 if (timeout_msec) {
1596 tmp = ata_wait_register(port_mmio + PORT_CMD_ISSUE, 0x1, 0x1,
1597 1, timeout_msec);
1598 if (tmp & 0x1) {
1599 ahci_kick_engine(ap, 1);
1600 return -EBUSY;
1601 }
1602 } else
1603 readl(port_mmio + PORT_CMD_ISSUE); /* flush */
1604
1605 return 0;
1606}
1607
Shane Huangbd172432008-06-10 15:52:04 +08001608static int ahci_do_softreset(struct ata_link *link, unsigned int *class,
1609 int pmp, unsigned long deadline,
1610 int (*check_ready)(struct ata_link *link))
Tejun Heo4658f792006-03-22 21:07:03 +09001611{
Tejun Heocc0680a2007-08-06 18:36:23 +09001612 struct ata_port *ap = link->ap;
Tejun Heo4658f792006-03-22 21:07:03 +09001613 const char *reason = NULL;
Tejun Heo2cbb79e2007-07-16 14:29:38 +09001614 unsigned long now, msecs;
Tejun Heo4658f792006-03-22 21:07:03 +09001615 struct ata_taskfile tf;
Tejun Heo4658f792006-03-22 21:07:03 +09001616 int rc;
1617
1618 DPRINTK("ENTER\n");
1619
1620 /* prepare for SRST (AHCI-1.1 10.4.1) */
Tejun Heod2e75df2007-07-16 14:29:39 +09001621 rc = ahci_kick_engine(ap, 1);
Tejun Heo994056d2007-12-06 15:02:48 +09001622 if (rc && rc != -EOPNOTSUPP)
Tejun Heocc0680a2007-08-06 18:36:23 +09001623 ata_link_printk(link, KERN_WARNING,
Tejun Heo994056d2007-12-06 15:02:48 +09001624 "failed to reset engine (errno=%d)\n", rc);
Tejun Heo4658f792006-03-22 21:07:03 +09001625
Tejun Heocc0680a2007-08-06 18:36:23 +09001626 ata_tf_init(link->device, &tf);
Tejun Heo4658f792006-03-22 21:07:03 +09001627
1628 /* issue the first D2H Register FIS */
Tejun Heo2cbb79e2007-07-16 14:29:38 +09001629 msecs = 0;
1630 now = jiffies;
1631 if (time_after(now, deadline))
1632 msecs = jiffies_to_msecs(deadline - now);
1633
Tejun Heo4658f792006-03-22 21:07:03 +09001634 tf.ctl |= ATA_SRST;
Tejun Heoa9cf5e82007-07-16 14:29:39 +09001635 if (ahci_exec_polled_cmd(ap, pmp, &tf, 0,
Tejun Heo91c4a2e2007-07-16 14:29:39 +09001636 AHCI_CMD_RESET | AHCI_CMD_CLR_BUSY, msecs)) {
Tejun Heo4658f792006-03-22 21:07:03 +09001637 rc = -EIO;
1638 reason = "1st FIS failed";
1639 goto fail;
1640 }
1641
1642 /* spec says at least 5us, but be generous and sleep for 1ms */
1643 msleep(1);
1644
1645 /* issue the second D2H Register FIS */
Tejun Heo4658f792006-03-22 21:07:03 +09001646 tf.ctl &= ~ATA_SRST;
Tejun Heoa9cf5e82007-07-16 14:29:39 +09001647 ahci_exec_polled_cmd(ap, pmp, &tf, 0, 0, 0);
Tejun Heo4658f792006-03-22 21:07:03 +09001648
Tejun Heo705e76b2008-04-07 22:47:19 +09001649 /* wait for link to become ready */
Shane Huangbd172432008-06-10 15:52:04 +08001650 rc = ata_wait_after_reset(link, deadline, check_ready);
Tejun Heo9b893912007-02-02 16:50:52 +09001651 /* link occupied, -ENODEV too is an error */
1652 if (rc) {
1653 reason = "device not ready";
1654 goto fail;
Tejun Heo4658f792006-03-22 21:07:03 +09001655 }
Tejun Heo9b893912007-02-02 16:50:52 +09001656 *class = ahci_dev_classify(ap);
Tejun Heo4658f792006-03-22 21:07:03 +09001657
1658 DPRINTK("EXIT, class=%u\n", *class);
1659 return 0;
1660
Tejun Heo4658f792006-03-22 21:07:03 +09001661 fail:
Tejun Heocc0680a2007-08-06 18:36:23 +09001662 ata_link_printk(link, KERN_ERR, "softreset failed (%s)\n", reason);
Tejun Heo4658f792006-03-22 21:07:03 +09001663 return rc;
1664}
1665
Shane Huangbd172432008-06-10 15:52:04 +08001666static int ahci_check_ready(struct ata_link *link)
1667{
1668 void __iomem *port_mmio = ahci_port_base(link->ap);
1669 u8 status = readl(port_mmio + PORT_TFDATA) & 0xFF;
1670
1671 return ata_check_ready(status);
1672}
1673
1674static int ahci_softreset(struct ata_link *link, unsigned int *class,
1675 unsigned long deadline)
1676{
1677 int pmp = sata_srst_pmp(link);
1678
1679 DPRINTK("ENTER\n");
1680
1681 return ahci_do_softreset(link, class, pmp, deadline, ahci_check_ready);
1682}
1683
1684static int ahci_sb600_check_ready(struct ata_link *link)
1685{
1686 void __iomem *port_mmio = ahci_port_base(link->ap);
1687 u8 status = readl(port_mmio + PORT_TFDATA) & 0xFF;
1688 u32 irq_status = readl(port_mmio + PORT_IRQ_STAT);
1689
1690 /*
1691 * There is no need to check TFDATA if BAD PMP is found due to HW bug,
1692 * which can save timeout delay.
1693 */
1694 if (irq_status & PORT_IRQ_BAD_PMP)
1695 return -EIO;
1696
1697 return ata_check_ready(status);
1698}
1699
1700static int ahci_sb600_softreset(struct ata_link *link, unsigned int *class,
1701 unsigned long deadline)
1702{
1703 struct ata_port *ap = link->ap;
1704 void __iomem *port_mmio = ahci_port_base(ap);
1705 int pmp = sata_srst_pmp(link);
1706 int rc;
1707 u32 irq_sts;
1708
1709 DPRINTK("ENTER\n");
1710
1711 rc = ahci_do_softreset(link, class, pmp, deadline,
1712 ahci_sb600_check_ready);
1713
1714 /*
1715 * Soft reset fails on some ATI chips with IPMS set when PMP
1716 * is enabled but SATA HDD/ODD is connected to SATA port,
1717 * do soft reset again to port 0.
1718 */
1719 if (rc == -EIO) {
1720 irq_sts = readl(port_mmio + PORT_IRQ_STAT);
1721 if (irq_sts & PORT_IRQ_BAD_PMP) {
1722 ata_link_printk(link, KERN_WARNING,
1723 "failed due to HW bug, retry pmp=0\n");
1724 rc = ahci_do_softreset(link, class, 0, deadline,
1725 ahci_check_ready);
1726 }
1727 }
1728
1729 return rc;
1730}
1731
Tejun Heocc0680a2007-08-06 18:36:23 +09001732static int ahci_hardreset(struct ata_link *link, unsigned int *class,
Tejun Heod4b2bab2007-02-02 16:50:52 +09001733 unsigned long deadline)
Tejun Heo422b7592005-12-19 22:37:17 +09001734{
Tejun Heo9dadd452008-04-07 22:47:19 +09001735 const unsigned long *timing = sata_ehc_deb_timing(&link->eh_context);
Tejun Heocc0680a2007-08-06 18:36:23 +09001736 struct ata_port *ap = link->ap;
Tejun Heo42969712006-05-31 18:28:18 +09001737 struct ahci_port_priv *pp = ap->private_data;
1738 u8 *d2h_fis = pp->rx_fis + RX_FIS_D2H_REG;
1739 struct ata_taskfile tf;
Tejun Heo9dadd452008-04-07 22:47:19 +09001740 bool online;
Tejun Heo4bd00f62006-02-11 16:26:02 +09001741 int rc;
1742
1743 DPRINTK("ENTER\n");
Linus Torvalds1da177e2005-04-16 15:20:36 -07001744
Tejun Heo4447d352007-04-17 23:44:08 +09001745 ahci_stop_engine(ap);
Tejun Heo42969712006-05-31 18:28:18 +09001746
1747 /* clear D2H reception area to properly wait for D2H FIS */
Tejun Heocc0680a2007-08-06 18:36:23 +09001748 ata_tf_init(link->device, &tf);
Tejun Heodfd7a3d2007-01-26 15:37:20 +09001749 tf.command = 0x80;
Tejun Heo99771262007-07-16 14:29:38 +09001750 ata_tf_to_fis(&tf, 0, 0, d2h_fis);
Tejun Heo42969712006-05-31 18:28:18 +09001751
Tejun Heo9dadd452008-04-07 22:47:19 +09001752 rc = sata_link_hardreset(link, timing, deadline, &online,
1753 ahci_check_ready);
Tejun Heo42969712006-05-31 18:28:18 +09001754
Tejun Heo4447d352007-04-17 23:44:08 +09001755 ahci_start_engine(ap);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001756
Tejun Heo9dadd452008-04-07 22:47:19 +09001757 if (online)
Tejun Heo4bd00f62006-02-11 16:26:02 +09001758 *class = ahci_dev_classify(ap);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001759
Tejun Heo4bd00f62006-02-11 16:26:02 +09001760 DPRINTK("EXIT, rc=%d, class=%u\n", rc, *class);
1761 return rc;
1762}
1763
Tejun Heocc0680a2007-08-06 18:36:23 +09001764static int ahci_vt8251_hardreset(struct ata_link *link, unsigned int *class,
Tejun Heod4b2bab2007-02-02 16:50:52 +09001765 unsigned long deadline)
Tejun Heoad616ff2006-11-01 18:00:24 +09001766{
Tejun Heocc0680a2007-08-06 18:36:23 +09001767 struct ata_port *ap = link->ap;
Tejun Heo9dadd452008-04-07 22:47:19 +09001768 bool online;
Tejun Heoad616ff2006-11-01 18:00:24 +09001769 int rc;
1770
1771 DPRINTK("ENTER\n");
1772
Tejun Heo4447d352007-04-17 23:44:08 +09001773 ahci_stop_engine(ap);
Tejun Heoad616ff2006-11-01 18:00:24 +09001774
Tejun Heocc0680a2007-08-06 18:36:23 +09001775 rc = sata_link_hardreset(link, sata_ehc_deb_timing(&link->eh_context),
Tejun Heo9dadd452008-04-07 22:47:19 +09001776 deadline, &online, NULL);
Tejun Heoad616ff2006-11-01 18:00:24 +09001777
Tejun Heo4447d352007-04-17 23:44:08 +09001778 ahci_start_engine(ap);
Tejun Heoad616ff2006-11-01 18:00:24 +09001779
1780 DPRINTK("EXIT, rc=%d, class=%u\n", rc, *class);
1781
1782 /* vt8251 doesn't clear BSY on signature FIS reception,
1783 * request follow-up softreset.
1784 */
Tejun Heo9dadd452008-04-07 22:47:19 +09001785 return online ? -EAGAIN : rc;
Tejun Heoad616ff2006-11-01 18:00:24 +09001786}
1787
Tejun Heoedc93052007-10-25 14:59:16 +09001788static int ahci_p5wdh_hardreset(struct ata_link *link, unsigned int *class,
1789 unsigned long deadline)
1790{
1791 struct ata_port *ap = link->ap;
1792 struct ahci_port_priv *pp = ap->private_data;
1793 u8 *d2h_fis = pp->rx_fis + RX_FIS_D2H_REG;
1794 struct ata_taskfile tf;
Tejun Heo9dadd452008-04-07 22:47:19 +09001795 bool online;
Tejun Heoedc93052007-10-25 14:59:16 +09001796 int rc;
1797
1798 ahci_stop_engine(ap);
1799
1800 /* clear D2H reception area to properly wait for D2H FIS */
1801 ata_tf_init(link->device, &tf);
1802 tf.command = 0x80;
1803 ata_tf_to_fis(&tf, 0, 0, d2h_fis);
1804
1805 rc = sata_link_hardreset(link, sata_ehc_deb_timing(&link->eh_context),
Tejun Heo9dadd452008-04-07 22:47:19 +09001806 deadline, &online, NULL);
Tejun Heoedc93052007-10-25 14:59:16 +09001807
1808 ahci_start_engine(ap);
1809
Tejun Heoedc93052007-10-25 14:59:16 +09001810 /* The pseudo configuration device on SIMG4726 attached to
1811 * ASUS P5W-DH Deluxe doesn't send signature FIS after
1812 * hardreset if no device is attached to the first downstream
1813 * port && the pseudo device locks up on SRST w/ PMP==0. To
1814 * work around this, wait for !BSY only briefly. If BSY isn't
1815 * cleared, perform CLO and proceed to IDENTIFY (achieved by
1816 * ATA_LFLAG_NO_SRST and ATA_LFLAG_ASSUME_ATA).
1817 *
1818 * Wait for two seconds. Devices attached to downstream port
1819 * which can't process the following IDENTIFY after this will
1820 * have to be reset again. For most cases, this should
1821 * suffice while making probing snappish enough.
1822 */
Tejun Heo9dadd452008-04-07 22:47:19 +09001823 if (online) {
1824 rc = ata_wait_after_reset(link, jiffies + 2 * HZ,
1825 ahci_check_ready);
1826 if (rc)
1827 ahci_kick_engine(ap, 0);
1828 }
Tejun Heo9dadd452008-04-07 22:47:19 +09001829 return rc;
Tejun Heoedc93052007-10-25 14:59:16 +09001830}
1831
Tejun Heocc0680a2007-08-06 18:36:23 +09001832static void ahci_postreset(struct ata_link *link, unsigned int *class)
Tejun Heo4bd00f62006-02-11 16:26:02 +09001833{
Tejun Heocc0680a2007-08-06 18:36:23 +09001834 struct ata_port *ap = link->ap;
Tejun Heo4447d352007-04-17 23:44:08 +09001835 void __iomem *port_mmio = ahci_port_base(ap);
Tejun Heo4bd00f62006-02-11 16:26:02 +09001836 u32 new_tmp, tmp;
1837
Tejun Heo203c75b2008-04-07 22:47:18 +09001838 ata_std_postreset(link, class);
Jeff Garzik02eaa662005-11-12 01:32:19 -05001839
1840 /* Make sure port's ATAPI bit is set appropriately */
1841 new_tmp = tmp = readl(port_mmio + PORT_CMD);
Tejun Heo4bd00f62006-02-11 16:26:02 +09001842 if (*class == ATA_DEV_ATAPI)
Jeff Garzik02eaa662005-11-12 01:32:19 -05001843 new_tmp |= PORT_CMD_ATAPI;
1844 else
1845 new_tmp &= ~PORT_CMD_ATAPI;
1846 if (new_tmp != tmp) {
1847 writel(new_tmp, port_mmio + PORT_CMD);
1848 readl(port_mmio + PORT_CMD); /* flush */
1849 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07001850}
1851
Tejun Heo12fad3f2006-05-15 21:03:55 +09001852static unsigned int ahci_fill_sg(struct ata_queued_cmd *qc, void *cmd_tbl)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001853{
Jeff Garzikcedc9a42005-10-05 07:13:30 -04001854 struct scatterlist *sg;
Tejun Heoff2aeb12007-12-05 16:43:11 +09001855 struct ahci_sg *ahci_sg = cmd_tbl + AHCI_CMD_TBL_HDR_SZ;
1856 unsigned int si;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001857
1858 VPRINTK("ENTER\n");
1859
1860 /*
1861 * Next, the S/G list.
1862 */
Tejun Heoff2aeb12007-12-05 16:43:11 +09001863 for_each_sg(qc->sg, sg, qc->n_elem, si) {
Jeff Garzikcedc9a42005-10-05 07:13:30 -04001864 dma_addr_t addr = sg_dma_address(sg);
1865 u32 sg_len = sg_dma_len(sg);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001866
Tejun Heoff2aeb12007-12-05 16:43:11 +09001867 ahci_sg[si].addr = cpu_to_le32(addr & 0xffffffff);
1868 ahci_sg[si].addr_hi = cpu_to_le32((addr >> 16) >> 16);
1869 ahci_sg[si].flags_size = cpu_to_le32(sg_len - 1);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001870 }
Jeff Garzik828d09d2005-11-12 01:27:07 -05001871
Tejun Heoff2aeb12007-12-05 16:43:11 +09001872 return si;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001873}
1874
1875static void ahci_qc_prep(struct ata_queued_cmd *qc)
1876{
Jeff Garzika0ea7322005-06-04 01:13:15 -04001877 struct ata_port *ap = qc->ap;
1878 struct ahci_port_priv *pp = ap->private_data;
Tejun Heo405e66b2007-11-27 19:28:53 +09001879 int is_atapi = ata_is_atapi(qc->tf.protocol);
Tejun Heo12fad3f2006-05-15 21:03:55 +09001880 void *cmd_tbl;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001881 u32 opts;
1882 const u32 cmd_fis_len = 5; /* five dwords */
Jeff Garzik828d09d2005-11-12 01:27:07 -05001883 unsigned int n_elem;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001884
1885 /*
Linus Torvalds1da177e2005-04-16 15:20:36 -07001886 * Fill in command table information. First, the header,
1887 * a SATA Register - Host to Device command FIS.
1888 */
Tejun Heo12fad3f2006-05-15 21:03:55 +09001889 cmd_tbl = pp->cmd_tbl + qc->tag * AHCI_CMD_TBL_SZ;
1890
Tejun Heo7d50b602007-09-23 13:19:54 +09001891 ata_tf_to_fis(&qc->tf, qc->dev->link->pmp, 1, cmd_tbl);
Tejun Heocc9278e2006-02-10 17:25:47 +09001892 if (is_atapi) {
Tejun Heo12fad3f2006-05-15 21:03:55 +09001893 memset(cmd_tbl + AHCI_CMD_TBL_CDB, 0, 32);
1894 memcpy(cmd_tbl + AHCI_CMD_TBL_CDB, qc->cdb, qc->dev->cdb_len);
Jeff Garzika0ea7322005-06-04 01:13:15 -04001895 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07001896
Tejun Heocc9278e2006-02-10 17:25:47 +09001897 n_elem = 0;
1898 if (qc->flags & ATA_QCFLAG_DMAMAP)
Tejun Heo12fad3f2006-05-15 21:03:55 +09001899 n_elem = ahci_fill_sg(qc, cmd_tbl);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001900
Tejun Heocc9278e2006-02-10 17:25:47 +09001901 /*
1902 * Fill in command slot information.
1903 */
Tejun Heo7d50b602007-09-23 13:19:54 +09001904 opts = cmd_fis_len | n_elem << 16 | (qc->dev->link->pmp << 12);
Tejun Heocc9278e2006-02-10 17:25:47 +09001905 if (qc->tf.flags & ATA_TFLAG_WRITE)
1906 opts |= AHCI_CMD_WRITE;
1907 if (is_atapi)
Tejun Heo4b10e552006-03-12 11:25:27 +09001908 opts |= AHCI_CMD_ATAPI | AHCI_CMD_PREFETCH;
Jeff Garzik828d09d2005-11-12 01:27:07 -05001909
Tejun Heo12fad3f2006-05-15 21:03:55 +09001910 ahci_fill_cmd_slot(pp, qc->tag, opts);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001911}
1912
Tejun Heo78cd52d2006-05-15 20:58:29 +09001913static void ahci_error_intr(struct ata_port *ap, u32 irq_stat)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001914{
Tejun Heo417a1a62007-09-23 13:19:55 +09001915 struct ahci_host_priv *hpriv = ap->host->private_data;
Tejun Heo78cd52d2006-05-15 20:58:29 +09001916 struct ahci_port_priv *pp = ap->private_data;
Tejun Heo7d50b602007-09-23 13:19:54 +09001917 struct ata_eh_info *host_ehi = &ap->link.eh_info;
1918 struct ata_link *link = NULL;
1919 struct ata_queued_cmd *active_qc;
1920 struct ata_eh_info *active_ehi;
Tejun Heo78cd52d2006-05-15 20:58:29 +09001921 u32 serror;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001922
Tejun Heo7d50b602007-09-23 13:19:54 +09001923 /* determine active link */
1924 ata_port_for_each_link(link, ap)
1925 if (ata_link_active(link))
1926 break;
1927 if (!link)
1928 link = &ap->link;
1929
1930 active_qc = ata_qc_from_tag(ap, link->active_tag);
1931 active_ehi = &link->eh_info;
1932
1933 /* record irq stat */
1934 ata_ehi_clear_desc(host_ehi);
1935 ata_ehi_push_desc(host_ehi, "irq_stat 0x%08x", irq_stat);
Jeff Garzik9f68a242005-11-15 14:03:47 -05001936
Tejun Heo78cd52d2006-05-15 20:58:29 +09001937 /* AHCI needs SError cleared; otherwise, it might lock up */
Tejun Heoda3dbb12007-07-16 14:29:40 +09001938 ahci_scr_read(ap, SCR_ERROR, &serror);
Tejun Heo78cd52d2006-05-15 20:58:29 +09001939 ahci_scr_write(ap, SCR_ERROR, serror);
Tejun Heo7d50b602007-09-23 13:19:54 +09001940 host_ehi->serror |= serror;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001941
Tejun Heo41669552006-11-29 11:33:14 +09001942 /* some controllers set IRQ_IF_ERR on device errors, ignore it */
Tejun Heo417a1a62007-09-23 13:19:55 +09001943 if (hpriv->flags & AHCI_HFLAG_IGN_IRQ_IF_ERR)
Tejun Heo41669552006-11-29 11:33:14 +09001944 irq_stat &= ~PORT_IRQ_IF_ERR;
1945
Conke Hu55a61602007-03-27 18:33:05 +08001946 if (irq_stat & PORT_IRQ_TF_ERR) {
Tejun Heo7d50b602007-09-23 13:19:54 +09001947 /* If qc is active, charge it; otherwise, the active
1948 * link. There's no active qc on NCQ errors. It will
1949 * be determined by EH by reading log page 10h.
1950 */
1951 if (active_qc)
1952 active_qc->err_mask |= AC_ERR_DEV;
1953 else
1954 active_ehi->err_mask |= AC_ERR_DEV;
1955
Tejun Heo417a1a62007-09-23 13:19:55 +09001956 if (hpriv->flags & AHCI_HFLAG_IGN_SERR_INTERNAL)
Tejun Heo7d50b602007-09-23 13:19:54 +09001957 host_ehi->serror &= ~SERR_INTERNAL;
Tejun Heo78cd52d2006-05-15 20:58:29 +09001958 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07001959
Tejun Heo78cd52d2006-05-15 20:58:29 +09001960 if (irq_stat & PORT_IRQ_UNK_FIS) {
1961 u32 *unk = (u32 *)(pp->rx_fis + RX_FIS_UNK);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001962
Tejun Heo7d50b602007-09-23 13:19:54 +09001963 active_ehi->err_mask |= AC_ERR_HSM;
Tejun Heocf480622008-01-24 00:05:14 +09001964 active_ehi->action |= ATA_EH_RESET;
Tejun Heo7d50b602007-09-23 13:19:54 +09001965 ata_ehi_push_desc(active_ehi,
1966 "unknown FIS %08x %08x %08x %08x" ,
Tejun Heo78cd52d2006-05-15 20:58:29 +09001967 unk[0], unk[1], unk[2], unk[3]);
1968 }
Jeff Garzikb8f61532005-08-25 22:01:20 -04001969
Tejun Heo071f44b2008-04-07 22:47:22 +09001970 if (sata_pmp_attached(ap) && (irq_stat & PORT_IRQ_BAD_PMP)) {
Tejun Heo7d50b602007-09-23 13:19:54 +09001971 active_ehi->err_mask |= AC_ERR_HSM;
Tejun Heocf480622008-01-24 00:05:14 +09001972 active_ehi->action |= ATA_EH_RESET;
Tejun Heo7d50b602007-09-23 13:19:54 +09001973 ata_ehi_push_desc(active_ehi, "incorrect PMP");
1974 }
Tejun Heo78cd52d2006-05-15 20:58:29 +09001975
Tejun Heo7d50b602007-09-23 13:19:54 +09001976 if (irq_stat & (PORT_IRQ_HBUS_ERR | PORT_IRQ_HBUS_DATA_ERR)) {
1977 host_ehi->err_mask |= AC_ERR_HOST_BUS;
Tejun Heocf480622008-01-24 00:05:14 +09001978 host_ehi->action |= ATA_EH_RESET;
Tejun Heo7d50b602007-09-23 13:19:54 +09001979 ata_ehi_push_desc(host_ehi, "host bus error");
1980 }
1981
1982 if (irq_stat & PORT_IRQ_IF_ERR) {
1983 host_ehi->err_mask |= AC_ERR_ATA_BUS;
Tejun Heocf480622008-01-24 00:05:14 +09001984 host_ehi->action |= ATA_EH_RESET;
Tejun Heo7d50b602007-09-23 13:19:54 +09001985 ata_ehi_push_desc(host_ehi, "interface fatal error");
1986 }
1987
1988 if (irq_stat & (PORT_IRQ_CONNECT | PORT_IRQ_PHYRDY)) {
1989 ata_ehi_hotplugged(host_ehi);
1990 ata_ehi_push_desc(host_ehi, "%s",
1991 irq_stat & PORT_IRQ_CONNECT ?
1992 "connection status changed" : "PHY RDY changed");
1993 }
1994
1995 /* okay, let's hand over to EH */
Linus Torvalds1da177e2005-04-16 15:20:36 -07001996
Tejun Heo78cd52d2006-05-15 20:58:29 +09001997 if (irq_stat & PORT_IRQ_FREEZE)
1998 ata_port_freeze(ap);
1999 else
2000 ata_port_abort(ap);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002001}
2002
Jeff Garzikdf69c9c2007-05-26 20:46:51 -04002003static void ahci_port_intr(struct ata_port *ap)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002004{
Tejun Heo350756f2008-04-07 22:47:21 +09002005 void __iomem *port_mmio = ahci_port_base(ap);
Tejun Heo9af5c9c2007-08-06 18:36:22 +09002006 struct ata_eh_info *ehi = &ap->link.eh_info;
Tejun Heo0291f952007-01-25 19:16:28 +09002007 struct ahci_port_priv *pp = ap->private_data;
Tejun Heo5f226c62007-10-09 15:02:23 +09002008 struct ahci_host_priv *hpriv = ap->host->private_data;
Tejun Heob06ce3e2007-10-09 15:06:48 +09002009 int resetting = !!(ap->pflags & ATA_PFLAG_RESETTING);
Tejun Heo12fad3f2006-05-15 21:03:55 +09002010 u32 status, qc_active;
Tejun Heo459ad682007-12-07 12:46:23 +09002011 int rc;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002012
2013 status = readl(port_mmio + PORT_IRQ_STAT);
2014 writel(status, port_mmio + PORT_IRQ_STAT);
2015
Tejun Heob06ce3e2007-10-09 15:06:48 +09002016 /* ignore BAD_PMP while resetting */
2017 if (unlikely(resetting))
2018 status &= ~PORT_IRQ_BAD_PMP;
2019
Kristen Carlson Accardi31556592007-10-25 01:33:26 -04002020 /* If we are getting PhyRdy, this is
2021 * just a power state change, we should
2022 * clear out this, plus the PhyRdy/Comm
2023 * Wake bits from Serror
2024 */
2025 if ((hpriv->flags & AHCI_HFLAG_NO_HOTPLUG) &&
2026 (status & PORT_IRQ_PHYRDY)) {
2027 status &= ~PORT_IRQ_PHYRDY;
2028 ahci_scr_write(ap, SCR_ERROR, ((1 << 16) | (1 << 18)));
2029 }
2030
Tejun Heo78cd52d2006-05-15 20:58:29 +09002031 if (unlikely(status & PORT_IRQ_ERROR)) {
2032 ahci_error_intr(ap, status);
2033 return;
2034 }
2035
Kristen Carlson Accardi2f294962007-08-15 04:11:25 -04002036 if (status & PORT_IRQ_SDB_FIS) {
Tejun Heo5f226c62007-10-09 15:02:23 +09002037 /* If SNotification is available, leave notification
2038 * handling to sata_async_notification(). If not,
2039 * emulate it by snooping SDB FIS RX area.
2040 *
2041 * Snooping FIS RX area is probably cheaper than
2042 * poking SNotification but some constrollers which
2043 * implement SNotification, ICH9 for example, don't
2044 * store AN SDB FIS into receive area.
Kristen Carlson Accardi2f294962007-08-15 04:11:25 -04002045 */
Tejun Heo5f226c62007-10-09 15:02:23 +09002046 if (hpriv->cap & HOST_CAP_SNTF)
Tejun Heo7d77b242007-09-23 13:14:13 +09002047 sata_async_notification(ap);
Tejun Heo5f226c62007-10-09 15:02:23 +09002048 else {
2049 /* If the 'N' bit in word 0 of the FIS is set,
2050 * we just received asynchronous notification.
2051 * Tell libata about it.
2052 */
2053 const __le32 *f = pp->rx_fis + RX_FIS_SDB;
2054 u32 f0 = le32_to_cpu(f[0]);
2055
2056 if (f0 & (1 << 15))
2057 sata_async_notification(ap);
2058 }
Kristen Carlson Accardi2f294962007-08-15 04:11:25 -04002059 }
2060
Tejun Heo7d50b602007-09-23 13:19:54 +09002061 /* pp->active_link is valid iff any command is in flight */
2062 if (ap->qc_active && pp->active_link->sactive)
Tejun Heo12fad3f2006-05-15 21:03:55 +09002063 qc_active = readl(port_mmio + PORT_SCR_ACT);
2064 else
2065 qc_active = readl(port_mmio + PORT_CMD_ISSUE);
2066
Tejun Heo79f97da2008-04-07 22:47:20 +09002067 rc = ata_qc_complete_multiple(ap, qc_active);
Tejun Heob06ce3e2007-10-09 15:06:48 +09002068
Tejun Heo459ad682007-12-07 12:46:23 +09002069 /* while resetting, invalid completions are expected */
2070 if (unlikely(rc < 0 && !resetting)) {
Tejun Heo12fad3f2006-05-15 21:03:55 +09002071 ehi->err_mask |= AC_ERR_HSM;
Tejun Heocf480622008-01-24 00:05:14 +09002072 ehi->action |= ATA_EH_RESET;
Tejun Heo12fad3f2006-05-15 21:03:55 +09002073 ata_port_freeze(ap);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002074 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07002075}
2076
David Howells7d12e782006-10-05 14:55:46 +01002077static irqreturn_t ahci_interrupt(int irq, void *dev_instance)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002078{
Jeff Garzikcca39742006-08-24 03:19:22 -04002079 struct ata_host *host = dev_instance;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002080 struct ahci_host_priv *hpriv;
2081 unsigned int i, handled = 0;
Jeff Garzikea6ba102005-08-30 05:18:18 -04002082 void __iomem *mmio;
Tejun Heod28f87a2008-07-05 13:10:50 +09002083 u32 irq_stat, irq_masked;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002084
2085 VPRINTK("ENTER\n");
2086
Jeff Garzikcca39742006-08-24 03:19:22 -04002087 hpriv = host->private_data;
Tejun Heo0d5ff562007-02-01 15:06:36 +09002088 mmio = host->iomap[AHCI_PCI_BAR];
Linus Torvalds1da177e2005-04-16 15:20:36 -07002089
2090 /* sigh. 0xffffffff is a valid return from h/w */
2091 irq_stat = readl(mmio + HOST_IRQ_STAT);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002092 if (!irq_stat)
2093 return IRQ_NONE;
2094
Tejun Heod28f87a2008-07-05 13:10:50 +09002095 irq_masked = irq_stat & hpriv->port_map;
2096
Jeff Garzik2dcb4072007-10-19 06:42:56 -04002097 spin_lock(&host->lock);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002098
Jeff Garzik2dcb4072007-10-19 06:42:56 -04002099 for (i = 0; i < host->n_ports; i++) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07002100 struct ata_port *ap;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002101
Tejun Heod28f87a2008-07-05 13:10:50 +09002102 if (!(irq_masked & (1 << i)))
Jeff Garzik67846b32005-10-05 02:58:32 -04002103 continue;
2104
Jeff Garzikcca39742006-08-24 03:19:22 -04002105 ap = host->ports[i];
Jeff Garzik67846b32005-10-05 02:58:32 -04002106 if (ap) {
Jeff Garzikdf69c9c2007-05-26 20:46:51 -04002107 ahci_port_intr(ap);
Jeff Garzik67846b32005-10-05 02:58:32 -04002108 VPRINTK("port %u\n", i);
2109 } else {
2110 VPRINTK("port %u (no irq)\n", i);
Tejun Heo6971ed12006-03-11 12:47:54 +09002111 if (ata_ratelimit())
Jeff Garzikcca39742006-08-24 03:19:22 -04002112 dev_printk(KERN_WARNING, host->dev,
Jeff Garzika9524a72005-10-30 14:39:11 -05002113 "interrupt on disabled port %u\n", i);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002114 }
Jeff Garzik67846b32005-10-05 02:58:32 -04002115
Linus Torvalds1da177e2005-04-16 15:20:36 -07002116 handled = 1;
2117 }
2118
Tejun Heod28f87a2008-07-05 13:10:50 +09002119 /* HOST_IRQ_STAT behaves as level triggered latch meaning that
2120 * it should be cleared after all the port events are cleared;
2121 * otherwise, it will raise a spurious interrupt after each
2122 * valid one. Please read section 10.6.2 of ahci 1.1 for more
2123 * information.
2124 *
2125 * Also, use the unmasked value to clear interrupt as spurious
2126 * pending event on a dummy port might cause screaming IRQ.
2127 */
Tejun Heoea0c62f2008-06-28 01:49:02 +09002128 writel(irq_stat, mmio + HOST_IRQ_STAT);
2129
Jeff Garzikcca39742006-08-24 03:19:22 -04002130 spin_unlock(&host->lock);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002131
2132 VPRINTK("EXIT\n");
2133
2134 return IRQ_RETVAL(handled);
2135}
2136
Tejun Heo9a3d9eb2006-01-23 13:09:36 +09002137static unsigned int ahci_qc_issue(struct ata_queued_cmd *qc)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002138{
2139 struct ata_port *ap = qc->ap;
Tejun Heo4447d352007-04-17 23:44:08 +09002140 void __iomem *port_mmio = ahci_port_base(ap);
Tejun Heo7d50b602007-09-23 13:19:54 +09002141 struct ahci_port_priv *pp = ap->private_data;
2142
2143 /* Keep track of the currently active link. It will be used
2144 * in completion path to determine whether NCQ phase is in
2145 * progress.
2146 */
2147 pp->active_link = qc->dev->link;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002148
Tejun Heo12fad3f2006-05-15 21:03:55 +09002149 if (qc->tf.protocol == ATA_PROT_NCQ)
2150 writel(1 << qc->tag, port_mmio + PORT_SCR_ACT);
2151 writel(1 << qc->tag, port_mmio + PORT_CMD_ISSUE);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002152
Kristen Carlson Accardi18f7ba42008-06-03 10:33:55 -07002153 ahci_sw_activity(qc->dev->link);
2154
Linus Torvalds1da177e2005-04-16 15:20:36 -07002155 return 0;
2156}
2157
Tejun Heo4c9bf4e2008-04-07 22:47:20 +09002158static bool ahci_qc_fill_rtf(struct ata_queued_cmd *qc)
2159{
2160 struct ahci_port_priv *pp = qc->ap->private_data;
2161 u8 *d2h_fis = pp->rx_fis + RX_FIS_D2H_REG;
2162
2163 ata_tf_from_fis(d2h_fis, &qc->result_tf);
2164 return true;
2165}
2166
Tejun Heo78cd52d2006-05-15 20:58:29 +09002167static void ahci_freeze(struct ata_port *ap)
2168{
Tejun Heo4447d352007-04-17 23:44:08 +09002169 void __iomem *port_mmio = ahci_port_base(ap);
Tejun Heo78cd52d2006-05-15 20:58:29 +09002170
2171 /* turn IRQ off */
2172 writel(0, port_mmio + PORT_IRQ_MASK);
2173}
2174
2175static void ahci_thaw(struct ata_port *ap)
2176{
Tejun Heo0d5ff562007-02-01 15:06:36 +09002177 void __iomem *mmio = ap->host->iomap[AHCI_PCI_BAR];
Tejun Heo4447d352007-04-17 23:44:08 +09002178 void __iomem *port_mmio = ahci_port_base(ap);
Tejun Heo78cd52d2006-05-15 20:58:29 +09002179 u32 tmp;
Kristen Carlson Accardia7384922007-08-09 14:23:41 -07002180 struct ahci_port_priv *pp = ap->private_data;
Tejun Heo78cd52d2006-05-15 20:58:29 +09002181
2182 /* clear IRQ */
2183 tmp = readl(port_mmio + PORT_IRQ_STAT);
2184 writel(tmp, port_mmio + PORT_IRQ_STAT);
Tejun Heoa7187282007-01-27 11:04:26 +09002185 writel(1 << ap->port_no, mmio + HOST_IRQ_STAT);
Tejun Heo78cd52d2006-05-15 20:58:29 +09002186
Tejun Heo1c954a42007-10-09 15:01:37 +09002187 /* turn IRQ back on */
2188 writel(pp->intr_mask, port_mmio + PORT_IRQ_MASK);
Tejun Heo78cd52d2006-05-15 20:58:29 +09002189}
2190
2191static void ahci_error_handler(struct ata_port *ap)
2192{
Tejun Heob51e9e52006-06-29 01:29:30 +09002193 if (!(ap->pflags & ATA_PFLAG_FROZEN)) {
Tejun Heo78cd52d2006-05-15 20:58:29 +09002194 /* restart engine */
Tejun Heo4447d352007-04-17 23:44:08 +09002195 ahci_stop_engine(ap);
2196 ahci_start_engine(ap);
Tejun Heo78cd52d2006-05-15 20:58:29 +09002197 }
2198
Tejun Heoa1efdab2008-03-25 12:22:50 +09002199 sata_pmp_error_handler(ap);
Tejun Heoedc93052007-10-25 14:59:16 +09002200}
2201
Tejun Heo78cd52d2006-05-15 20:58:29 +09002202static void ahci_post_internal_cmd(struct ata_queued_cmd *qc)
2203{
2204 struct ata_port *ap = qc->ap;
2205
Tejun Heod2e75df2007-07-16 14:29:39 +09002206 /* make DMA engine forget about the failed command */
2207 if (qc->flags & ATA_QCFLAG_FAILED)
2208 ahci_kick_engine(ap, 1);
Tejun Heo78cd52d2006-05-15 20:58:29 +09002209}
2210
Tejun Heo7d50b602007-09-23 13:19:54 +09002211static void ahci_pmp_attach(struct ata_port *ap)
2212{
2213 void __iomem *port_mmio = ahci_port_base(ap);
Tejun Heo1c954a42007-10-09 15:01:37 +09002214 struct ahci_port_priv *pp = ap->private_data;
Tejun Heo7d50b602007-09-23 13:19:54 +09002215 u32 cmd;
2216
2217 cmd = readl(port_mmio + PORT_CMD);
2218 cmd |= PORT_CMD_PMP;
2219 writel(cmd, port_mmio + PORT_CMD);
Tejun Heo1c954a42007-10-09 15:01:37 +09002220
2221 pp->intr_mask |= PORT_IRQ_BAD_PMP;
2222 writel(pp->intr_mask, port_mmio + PORT_IRQ_MASK);
Tejun Heo7d50b602007-09-23 13:19:54 +09002223}
2224
2225static void ahci_pmp_detach(struct ata_port *ap)
2226{
2227 void __iomem *port_mmio = ahci_port_base(ap);
Tejun Heo1c954a42007-10-09 15:01:37 +09002228 struct ahci_port_priv *pp = ap->private_data;
Tejun Heo7d50b602007-09-23 13:19:54 +09002229 u32 cmd;
2230
2231 cmd = readl(port_mmio + PORT_CMD);
2232 cmd &= ~PORT_CMD_PMP;
2233 writel(cmd, port_mmio + PORT_CMD);
Tejun Heo1c954a42007-10-09 15:01:37 +09002234
2235 pp->intr_mask &= ~PORT_IRQ_BAD_PMP;
2236 writel(pp->intr_mask, port_mmio + PORT_IRQ_MASK);
Tejun Heo7d50b602007-09-23 13:19:54 +09002237}
2238
Alexey Dobriyan028a2592007-07-17 23:48:48 +04002239static int ahci_port_resume(struct ata_port *ap)
2240{
2241 ahci_power_up(ap);
2242 ahci_start_port(ap);
2243
Tejun Heo071f44b2008-04-07 22:47:22 +09002244 if (sata_pmp_attached(ap))
Tejun Heo7d50b602007-09-23 13:19:54 +09002245 ahci_pmp_attach(ap);
2246 else
2247 ahci_pmp_detach(ap);
2248
Alexey Dobriyan028a2592007-07-17 23:48:48 +04002249 return 0;
2250}
2251
Tejun Heo438ac6d2007-03-02 17:31:26 +09002252#ifdef CONFIG_PM
Tejun Heoc1332872006-07-26 15:59:26 +09002253static int ahci_port_suspend(struct ata_port *ap, pm_message_t mesg)
2254{
Tejun Heoc1332872006-07-26 15:59:26 +09002255 const char *emsg = NULL;
2256 int rc;
2257
Tejun Heo4447d352007-04-17 23:44:08 +09002258 rc = ahci_deinit_port(ap, &emsg);
Tejun Heo8e16f942006-11-20 15:42:36 +09002259 if (rc == 0)
Tejun Heo4447d352007-04-17 23:44:08 +09002260 ahci_power_down(ap);
Tejun Heo8e16f942006-11-20 15:42:36 +09002261 else {
Tejun Heoc1332872006-07-26 15:59:26 +09002262 ata_port_printk(ap, KERN_ERR, "%s (%d)\n", emsg, rc);
Jeff Garzikdf69c9c2007-05-26 20:46:51 -04002263 ahci_start_port(ap);
Tejun Heoc1332872006-07-26 15:59:26 +09002264 }
2265
2266 return rc;
2267}
2268
Tejun Heoc1332872006-07-26 15:59:26 +09002269static int ahci_pci_device_suspend(struct pci_dev *pdev, pm_message_t mesg)
2270{
Jeff Garzikcca39742006-08-24 03:19:22 -04002271 struct ata_host *host = dev_get_drvdata(&pdev->dev);
Tejun Heo0d5ff562007-02-01 15:06:36 +09002272 void __iomem *mmio = host->iomap[AHCI_PCI_BAR];
Tejun Heoc1332872006-07-26 15:59:26 +09002273 u32 ctl;
2274
Rafael J. Wysocki3a2d5b72008-02-23 19:13:25 +01002275 if (mesg.event & PM_EVENT_SLEEP) {
Tejun Heoc1332872006-07-26 15:59:26 +09002276 /* AHCI spec rev1.1 section 8.3.3:
2277 * Software must disable interrupts prior to requesting a
2278 * transition of the HBA to D3 state.
2279 */
2280 ctl = readl(mmio + HOST_CTL);
2281 ctl &= ~HOST_IRQ_EN;
2282 writel(ctl, mmio + HOST_CTL);
2283 readl(mmio + HOST_CTL); /* flush */
2284 }
2285
2286 return ata_pci_device_suspend(pdev, mesg);
2287}
2288
2289static int ahci_pci_device_resume(struct pci_dev *pdev)
2290{
Jeff Garzikcca39742006-08-24 03:19:22 -04002291 struct ata_host *host = dev_get_drvdata(&pdev->dev);
Tejun Heoc1332872006-07-26 15:59:26 +09002292 int rc;
2293
Tejun Heo553c4aa2006-12-26 19:39:50 +09002294 rc = ata_pci_device_do_resume(pdev);
2295 if (rc)
2296 return rc;
Tejun Heoc1332872006-07-26 15:59:26 +09002297
2298 if (pdev->dev.power.power_state.event == PM_EVENT_SUSPEND) {
Tejun Heo4447d352007-04-17 23:44:08 +09002299 rc = ahci_reset_controller(host);
Tejun Heoc1332872006-07-26 15:59:26 +09002300 if (rc)
2301 return rc;
2302
Tejun Heo4447d352007-04-17 23:44:08 +09002303 ahci_init_controller(host);
Tejun Heoc1332872006-07-26 15:59:26 +09002304 }
2305
Jeff Garzikcca39742006-08-24 03:19:22 -04002306 ata_host_resume(host);
Tejun Heoc1332872006-07-26 15:59:26 +09002307
2308 return 0;
2309}
Tejun Heo438ac6d2007-03-02 17:31:26 +09002310#endif
Tejun Heoc1332872006-07-26 15:59:26 +09002311
Tejun Heo254950c2006-07-26 15:59:25 +09002312static int ahci_port_start(struct ata_port *ap)
2313{
Jeff Garzikcca39742006-08-24 03:19:22 -04002314 struct device *dev = ap->host->dev;
Tejun Heo254950c2006-07-26 15:59:25 +09002315 struct ahci_port_priv *pp;
Tejun Heo254950c2006-07-26 15:59:25 +09002316 void *mem;
2317 dma_addr_t mem_dma;
Tejun Heo254950c2006-07-26 15:59:25 +09002318
Tejun Heo24dc5f32007-01-20 16:00:28 +09002319 pp = devm_kzalloc(dev, sizeof(*pp), GFP_KERNEL);
Tejun Heo254950c2006-07-26 15:59:25 +09002320 if (!pp)
2321 return -ENOMEM;
Tejun Heo254950c2006-07-26 15:59:25 +09002322
Tejun Heo24dc5f32007-01-20 16:00:28 +09002323 mem = dmam_alloc_coherent(dev, AHCI_PORT_PRIV_DMA_SZ, &mem_dma,
2324 GFP_KERNEL);
2325 if (!mem)
Tejun Heo254950c2006-07-26 15:59:25 +09002326 return -ENOMEM;
Tejun Heo254950c2006-07-26 15:59:25 +09002327 memset(mem, 0, AHCI_PORT_PRIV_DMA_SZ);
2328
2329 /*
2330 * First item in chunk of DMA memory: 32-slot command table,
2331 * 32 bytes each in size
2332 */
2333 pp->cmd_slot = mem;
2334 pp->cmd_slot_dma = mem_dma;
2335
2336 mem += AHCI_CMD_SLOT_SZ;
2337 mem_dma += AHCI_CMD_SLOT_SZ;
2338
2339 /*
2340 * Second item: Received-FIS area
2341 */
2342 pp->rx_fis = mem;
2343 pp->rx_fis_dma = mem_dma;
2344
2345 mem += AHCI_RX_FIS_SZ;
2346 mem_dma += AHCI_RX_FIS_SZ;
2347
2348 /*
2349 * Third item: data area for storing a single command
2350 * and its scatter-gather table
2351 */
2352 pp->cmd_tbl = mem;
2353 pp->cmd_tbl_dma = mem_dma;
2354
Kristen Carlson Accardia7384922007-08-09 14:23:41 -07002355 /*
Jeff Garzik2dcb4072007-10-19 06:42:56 -04002356 * Save off initial list of interrupts to be enabled.
2357 * This could be changed later
2358 */
Kristen Carlson Accardia7384922007-08-09 14:23:41 -07002359 pp->intr_mask = DEF_PORT_IRQ;
2360
Tejun Heo254950c2006-07-26 15:59:25 +09002361 ap->private_data = pp;
2362
Jeff Garzikdf69c9c2007-05-26 20:46:51 -04002363 /* engage engines, captain */
2364 return ahci_port_resume(ap);
Tejun Heo254950c2006-07-26 15:59:25 +09002365}
2366
2367static void ahci_port_stop(struct ata_port *ap)
2368{
Tejun Heo0be0aa92006-07-26 15:59:26 +09002369 const char *emsg = NULL;
2370 int rc;
Tejun Heo254950c2006-07-26 15:59:25 +09002371
Tejun Heo0be0aa92006-07-26 15:59:26 +09002372 /* de-initialize port */
Tejun Heo4447d352007-04-17 23:44:08 +09002373 rc = ahci_deinit_port(ap, &emsg);
Tejun Heo0be0aa92006-07-26 15:59:26 +09002374 if (rc)
2375 ata_port_printk(ap, KERN_WARNING, "%s (%d)\n", emsg, rc);
Tejun Heo254950c2006-07-26 15:59:25 +09002376}
2377
Tejun Heo4447d352007-04-17 23:44:08 +09002378static int ahci_configure_dma_masks(struct pci_dev *pdev, int using_dac)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002379{
Linus Torvalds1da177e2005-04-16 15:20:36 -07002380 int rc;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002381
Linus Torvalds1da177e2005-04-16 15:20:36 -07002382 if (using_dac &&
2383 !pci_set_dma_mask(pdev, DMA_64BIT_MASK)) {
2384 rc = pci_set_consistent_dma_mask(pdev, DMA_64BIT_MASK);
2385 if (rc) {
2386 rc = pci_set_consistent_dma_mask(pdev, DMA_32BIT_MASK);
2387 if (rc) {
Jeff Garzika9524a72005-10-30 14:39:11 -05002388 dev_printk(KERN_ERR, &pdev->dev,
2389 "64-bit DMA enable failed\n");
Linus Torvalds1da177e2005-04-16 15:20:36 -07002390 return rc;
2391 }
2392 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07002393 } else {
2394 rc = pci_set_dma_mask(pdev, DMA_32BIT_MASK);
2395 if (rc) {
Jeff Garzika9524a72005-10-30 14:39:11 -05002396 dev_printk(KERN_ERR, &pdev->dev,
2397 "32-bit DMA enable failed\n");
Linus Torvalds1da177e2005-04-16 15:20:36 -07002398 return rc;
2399 }
2400 rc = pci_set_consistent_dma_mask(pdev, DMA_32BIT_MASK);
2401 if (rc) {
Jeff Garzika9524a72005-10-30 14:39:11 -05002402 dev_printk(KERN_ERR, &pdev->dev,
2403 "32-bit consistent DMA enable failed\n");
Linus Torvalds1da177e2005-04-16 15:20:36 -07002404 return rc;
2405 }
2406 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07002407 return 0;
2408}
2409
Tejun Heo4447d352007-04-17 23:44:08 +09002410static void ahci_print_info(struct ata_host *host)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002411{
Tejun Heo4447d352007-04-17 23:44:08 +09002412 struct ahci_host_priv *hpriv = host->private_data;
2413 struct pci_dev *pdev = to_pci_dev(host->dev);
2414 void __iomem *mmio = host->iomap[AHCI_PCI_BAR];
Linus Torvalds1da177e2005-04-16 15:20:36 -07002415 u32 vers, cap, impl, speed;
2416 const char *speed_s;
2417 u16 cc;
2418 const char *scc_s;
2419
2420 vers = readl(mmio + HOST_VERSION);
2421 cap = hpriv->cap;
2422 impl = hpriv->port_map;
2423
2424 speed = (cap >> 20) & 0xf;
2425 if (speed == 1)
2426 speed_s = "1.5";
2427 else if (speed == 2)
2428 speed_s = "3";
2429 else
2430 speed_s = "?";
2431
2432 pci_read_config_word(pdev, 0x0a, &cc);
Conke Huc9f89472007-01-09 05:32:51 -05002433 if (cc == PCI_CLASS_STORAGE_IDE)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002434 scc_s = "IDE";
Conke Huc9f89472007-01-09 05:32:51 -05002435 else if (cc == PCI_CLASS_STORAGE_SATA)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002436 scc_s = "SATA";
Conke Huc9f89472007-01-09 05:32:51 -05002437 else if (cc == PCI_CLASS_STORAGE_RAID)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002438 scc_s = "RAID";
2439 else
2440 scc_s = "unknown";
2441
Jeff Garzika9524a72005-10-30 14:39:11 -05002442 dev_printk(KERN_INFO, &pdev->dev,
2443 "AHCI %02x%02x.%02x%02x "
Linus Torvalds1da177e2005-04-16 15:20:36 -07002444 "%u slots %u ports %s Gbps 0x%x impl %s mode\n"
Jeff Garzik2dcb4072007-10-19 06:42:56 -04002445 ,
Linus Torvalds1da177e2005-04-16 15:20:36 -07002446
Jeff Garzik2dcb4072007-10-19 06:42:56 -04002447 (vers >> 24) & 0xff,
2448 (vers >> 16) & 0xff,
2449 (vers >> 8) & 0xff,
2450 vers & 0xff,
Linus Torvalds1da177e2005-04-16 15:20:36 -07002451
2452 ((cap >> 8) & 0x1f) + 1,
2453 (cap & 0x1f) + 1,
2454 speed_s,
2455 impl,
2456 scc_s);
2457
Jeff Garzika9524a72005-10-30 14:39:11 -05002458 dev_printk(KERN_INFO, &pdev->dev,
2459 "flags: "
Tejun Heo203ef6c2007-07-16 14:29:40 +09002460 "%s%s%s%s%s%s%s"
Kristen Carlson Accardi18f7ba42008-06-03 10:33:55 -07002461 "%s%s%s%s%s%s%s"
2462 "%s\n"
Jeff Garzik2dcb4072007-10-19 06:42:56 -04002463 ,
Linus Torvalds1da177e2005-04-16 15:20:36 -07002464
2465 cap & (1 << 31) ? "64bit " : "",
2466 cap & (1 << 30) ? "ncq " : "",
Tejun Heo203ef6c2007-07-16 14:29:40 +09002467 cap & (1 << 29) ? "sntf " : "",
Linus Torvalds1da177e2005-04-16 15:20:36 -07002468 cap & (1 << 28) ? "ilck " : "",
2469 cap & (1 << 27) ? "stag " : "",
2470 cap & (1 << 26) ? "pm " : "",
2471 cap & (1 << 25) ? "led " : "",
2472
2473 cap & (1 << 24) ? "clo " : "",
2474 cap & (1 << 19) ? "nz " : "",
2475 cap & (1 << 18) ? "only " : "",
2476 cap & (1 << 17) ? "pmp " : "",
2477 cap & (1 << 15) ? "pio " : "",
2478 cap & (1 << 14) ? "slum " : "",
Kristen Carlson Accardi18f7ba42008-06-03 10:33:55 -07002479 cap & (1 << 13) ? "part " : "",
2480 cap & (1 << 6) ? "ems ": ""
Linus Torvalds1da177e2005-04-16 15:20:36 -07002481 );
2482}
2483
Tejun Heoedc93052007-10-25 14:59:16 +09002484/* On ASUS P5W DH Deluxe, the second port of PCI device 00:1f.2 is
2485 * hardwired to on-board SIMG 4726. The chipset is ICH8 and doesn't
2486 * support PMP and the 4726 either directly exports the device
2487 * attached to the first downstream port or acts as a hardware storage
2488 * controller and emulate a single ATA device (can be RAID 0/1 or some
2489 * other configuration).
2490 *
2491 * When there's no device attached to the first downstream port of the
2492 * 4726, "Config Disk" appears, which is a pseudo ATA device to
2493 * configure the 4726. However, ATA emulation of the device is very
2494 * lame. It doesn't send signature D2H Reg FIS after the initial
2495 * hardreset, pukes on SRST w/ PMP==0 and has bunch of other issues.
2496 *
2497 * The following function works around the problem by always using
2498 * hardreset on the port and not depending on receiving signature FIS
2499 * afterward. If signature FIS isn't received soon, ATA class is
2500 * assumed without follow-up softreset.
2501 */
2502static void ahci_p5wdh_workaround(struct ata_host *host)
2503{
2504 static struct dmi_system_id sysids[] = {
2505 {
2506 .ident = "P5W DH Deluxe",
2507 .matches = {
2508 DMI_MATCH(DMI_SYS_VENDOR,
2509 "ASUSTEK COMPUTER INC"),
2510 DMI_MATCH(DMI_PRODUCT_NAME, "P5W DH Deluxe"),
2511 },
2512 },
2513 { }
2514 };
2515 struct pci_dev *pdev = to_pci_dev(host->dev);
2516
2517 if (pdev->bus->number == 0 && pdev->devfn == PCI_DEVFN(0x1f, 2) &&
2518 dmi_check_system(sysids)) {
2519 struct ata_port *ap = host->ports[1];
2520
2521 dev_printk(KERN_INFO, &pdev->dev, "enabling ASUS P5W DH "
2522 "Deluxe on-board SIMG4726 workaround\n");
2523
2524 ap->ops = &ahci_p5wdh_ops;
2525 ap->link.flags |= ATA_LFLAG_NO_SRST | ATA_LFLAG_ASSUME_ATA;
2526 }
2527}
2528
Tejun Heo24dc5f32007-01-20 16:00:28 +09002529static int ahci_init_one(struct pci_dev *pdev, const struct pci_device_id *ent)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002530{
2531 static int printed_version;
Tejun Heoe297d992008-06-10 00:13:04 +09002532 unsigned int board_id = ent->driver_data;
2533 struct ata_port_info pi = ahci_port_info[board_id];
Tejun Heo4447d352007-04-17 23:44:08 +09002534 const struct ata_port_info *ppi[] = { &pi, NULL };
Tejun Heo24dc5f32007-01-20 16:00:28 +09002535 struct device *dev = &pdev->dev;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002536 struct ahci_host_priv *hpriv;
Tejun Heo4447d352007-04-17 23:44:08 +09002537 struct ata_host *host;
Tejun Heo837f5f82008-02-06 15:13:51 +09002538 int n_ports, i, rc;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002539
2540 VPRINTK("ENTER\n");
2541
Tejun Heo12fad3f2006-05-15 21:03:55 +09002542 WARN_ON(ATA_MAX_QUEUE > AHCI_MAX_CMDS);
2543
Linus Torvalds1da177e2005-04-16 15:20:36 -07002544 if (!printed_version++)
Jeff Garzika9524a72005-10-30 14:39:11 -05002545 dev_printk(KERN_DEBUG, &pdev->dev, "version " DRV_VERSION "\n");
Linus Torvalds1da177e2005-04-16 15:20:36 -07002546
Alan Cox5b66c822008-09-03 14:48:34 +01002547 /* The AHCI driver can only drive the SATA ports, the PATA driver
2548 can drive them all so if both drivers are selected make sure
2549 AHCI stays out of the way */
2550 if (pdev->vendor == PCI_VENDOR_ID_MARVELL && !marvell_enable)
2551 return -ENODEV;
2552
Tejun Heo4447d352007-04-17 23:44:08 +09002553 /* acquire resources */
Tejun Heo24dc5f32007-01-20 16:00:28 +09002554 rc = pcim_enable_device(pdev);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002555 if (rc)
2556 return rc;
2557
Tejun Heodea55132008-03-11 19:52:31 +09002558 /* AHCI controllers often implement SFF compatible interface.
2559 * Grab all PCI BARs just in case.
2560 */
2561 rc = pcim_iomap_regions_request_all(pdev, 1 << AHCI_PCI_BAR, DRV_NAME);
Tejun Heo0d5ff562007-02-01 15:06:36 +09002562 if (rc == -EBUSY)
Tejun Heo24dc5f32007-01-20 16:00:28 +09002563 pcim_pin_device(pdev);
Tejun Heo0d5ff562007-02-01 15:06:36 +09002564 if (rc)
Tejun Heo24dc5f32007-01-20 16:00:28 +09002565 return rc;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002566
Tejun Heoc4f77922007-12-06 15:09:43 +09002567 if (pdev->vendor == PCI_VENDOR_ID_INTEL &&
2568 (pdev->device == 0x2652 || pdev->device == 0x2653)) {
2569 u8 map;
2570
2571 /* ICH6s share the same PCI ID for both piix and ahci
2572 * modes. Enabling ahci mode while MAP indicates
2573 * combined mode is a bad idea. Yield to ata_piix.
2574 */
2575 pci_read_config_byte(pdev, ICH_MAP, &map);
2576 if (map & 0x3) {
2577 dev_printk(KERN_INFO, &pdev->dev, "controller is in "
2578 "combined mode, can't enable AHCI mode\n");
2579 return -ENODEV;
2580 }
2581 }
2582
Tejun Heo24dc5f32007-01-20 16:00:28 +09002583 hpriv = devm_kzalloc(dev, sizeof(*hpriv), GFP_KERNEL);
2584 if (!hpriv)
2585 return -ENOMEM;
Tejun Heo417a1a62007-09-23 13:19:55 +09002586 hpriv->flags |= (unsigned long)pi.private_data;
2587
Tejun Heoe297d992008-06-10 00:13:04 +09002588 /* MCP65 revision A1 and A2 can't do MSI */
2589 if (board_id == board_ahci_mcp65 &&
2590 (pdev->revision == 0xa1 || pdev->revision == 0xa2))
2591 hpriv->flags |= AHCI_HFLAG_NO_MSI;
2592
Tejun Heo417a1a62007-09-23 13:19:55 +09002593 if ((hpriv->flags & AHCI_HFLAG_NO_MSI) || pci_enable_msi(pdev))
2594 pci_intx(pdev, 1);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002595
Tejun Heo4447d352007-04-17 23:44:08 +09002596 /* save initial config */
Tejun Heo417a1a62007-09-23 13:19:55 +09002597 ahci_save_initial_config(pdev, hpriv);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002598
Tejun Heo4447d352007-04-17 23:44:08 +09002599 /* prepare host */
Tejun Heo274c1fd2007-07-16 14:29:40 +09002600 if (hpriv->cap & HOST_CAP_NCQ)
Tejun Heo4447d352007-04-17 23:44:08 +09002601 pi.flags |= ATA_FLAG_NCQ;
2602
Tejun Heo7d50b602007-09-23 13:19:54 +09002603 if (hpriv->cap & HOST_CAP_PMP)
2604 pi.flags |= ATA_FLAG_PMP;
2605
Kristen Carlson Accardi18f7ba42008-06-03 10:33:55 -07002606 if (ahci_em_messages && (hpriv->cap & HOST_CAP_EMS)) {
2607 u8 messages;
2608 void __iomem *mmio = pcim_iomap_table(pdev)[AHCI_PCI_BAR];
2609 u32 em_loc = readl(mmio + HOST_EM_LOC);
2610 u32 em_ctl = readl(mmio + HOST_EM_CTL);
2611
2612 messages = (em_ctl & 0x000f0000) >> 16;
2613
2614 /* we only support LED message type right now */
2615 if ((messages & 0x01) && (ahci_em_messages == 1)) {
2616 /* store em_loc */
2617 hpriv->em_loc = ((em_loc >> 16) * 4);
2618 pi.flags |= ATA_FLAG_EM;
2619 if (!(em_ctl & EM_CTL_ALHD))
2620 pi.flags |= ATA_FLAG_SW_ACTIVITY;
2621 }
2622 }
2623
Tejun Heo837f5f82008-02-06 15:13:51 +09002624 /* CAP.NP sometimes indicate the index of the last enabled
2625 * port, at other times, that of the last possible port, so
2626 * determining the maximum port number requires looking at
2627 * both CAP.NP and port_map.
2628 */
2629 n_ports = max(ahci_nr_ports(hpriv->cap), fls(hpriv->port_map));
2630
2631 host = ata_host_alloc_pinfo(&pdev->dev, ppi, n_ports);
Tejun Heo4447d352007-04-17 23:44:08 +09002632 if (!host)
2633 return -ENOMEM;
2634 host->iomap = pcim_iomap_table(pdev);
2635 host->private_data = hpriv;
2636
Kristen Carlson Accardi18f7ba42008-06-03 10:33:55 -07002637 if (pi.flags & ATA_FLAG_EM)
2638 ahci_reset_em(host);
2639
Tejun Heo4447d352007-04-17 23:44:08 +09002640 for (i = 0; i < host->n_ports; i++) {
Jeff Garzikdab632e2007-05-28 08:33:01 -04002641 struct ata_port *ap = host->ports[i];
Tejun Heo4447d352007-04-17 23:44:08 +09002642
Tejun Heocbcdd872007-08-18 13:14:55 +09002643 ata_port_pbar_desc(ap, AHCI_PCI_BAR, -1, "abar");
2644 ata_port_pbar_desc(ap, AHCI_PCI_BAR,
2645 0x100 + ap->port_no * 0x80, "port");
2646
Kristen Carlson Accardi31556592007-10-25 01:33:26 -04002647 /* set initial link pm policy */
2648 ap->pm_policy = NOT_AVAILABLE;
2649
Kristen Carlson Accardi18f7ba42008-06-03 10:33:55 -07002650 /* set enclosure management message type */
2651 if (ap->flags & ATA_FLAG_EM)
2652 ap->em_message_type = ahci_em_messages;
2653
2654
Jeff Garzikdab632e2007-05-28 08:33:01 -04002655 /* disabled/not-implemented port */
Tejun Heo350756f2008-04-07 22:47:21 +09002656 if (!(hpriv->port_map & (1 << i)))
Jeff Garzikdab632e2007-05-28 08:33:01 -04002657 ap->ops = &ata_dummy_port_ops;
Tejun Heo4447d352007-04-17 23:44:08 +09002658 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07002659
Tejun Heoedc93052007-10-25 14:59:16 +09002660 /* apply workaround for ASUS P5W DH Deluxe mainboard */
2661 ahci_p5wdh_workaround(host);
2662
Linus Torvalds1da177e2005-04-16 15:20:36 -07002663 /* initialize adapter */
Tejun Heo4447d352007-04-17 23:44:08 +09002664 rc = ahci_configure_dma_masks(pdev, hpriv->cap & HOST_CAP_64);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002665 if (rc)
Tejun Heo24dc5f32007-01-20 16:00:28 +09002666 return rc;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002667
Tejun Heo4447d352007-04-17 23:44:08 +09002668 rc = ahci_reset_controller(host);
2669 if (rc)
2670 return rc;
Tejun Heo12fad3f2006-05-15 21:03:55 +09002671
Tejun Heo4447d352007-04-17 23:44:08 +09002672 ahci_init_controller(host);
2673 ahci_print_info(host);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002674
Tejun Heo4447d352007-04-17 23:44:08 +09002675 pci_set_master(pdev);
2676 return ata_host_activate(host, pdev->irq, ahci_interrupt, IRQF_SHARED,
2677 &ahci_sht);
Jeff Garzik907f4672005-05-12 15:03:42 -04002678}
Linus Torvalds1da177e2005-04-16 15:20:36 -07002679
2680static int __init ahci_init(void)
2681{
Pavel Roskinb7887192006-08-10 18:13:18 +09002682 return pci_register_driver(&ahci_pci_driver);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002683}
2684
Linus Torvalds1da177e2005-04-16 15:20:36 -07002685static void __exit ahci_exit(void)
2686{
2687 pci_unregister_driver(&ahci_pci_driver);
2688}
2689
2690
2691MODULE_AUTHOR("Jeff Garzik");
2692MODULE_DESCRIPTION("AHCI SATA low-level driver");
2693MODULE_LICENSE("GPL");
2694MODULE_DEVICE_TABLE(pci, ahci_pci_tbl);
Jeff Garzik68854332005-08-23 02:53:51 -04002695MODULE_VERSION(DRV_VERSION);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002696
2697module_init(ahci_init);
2698module_exit(ahci_exit);