blob: 3c71d31334315a0a5c20c5920efb4f66d6f70dfe [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 Heo82ef04f2008-07-31 17:02:40 +0900270static int ahci_scr_read(struct ata_link *link, unsigned int sc_reg, u32 *val);
271static int ahci_scr_write(struct ata_link *link, 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,
Elias Oltmanns45fabbb2008-09-21 11:54:08 +0200319 &dev_attr_unload_heads,
Kristen Carlson Accardi31556592007-10-25 01:33:26 -0400320 NULL
321};
322
Jeff Garzik193515d2005-11-07 00:59:37 -0500323static struct scsi_host_template ahci_sht = {
Tejun Heo68d1d072008-03-25 12:22:49 +0900324 ATA_NCQ_SHT(DRV_NAME),
Tejun Heo12fad3f2006-05-15 21:03:55 +0900325 .can_queue = AHCI_MAX_CMDS - 1,
Linus Torvalds1da177e2005-04-16 15:20:36 -0700326 .sg_tablesize = AHCI_MAX_SG,
Linus Torvalds1da177e2005-04-16 15:20:36 -0700327 .dma_boundary = AHCI_DMA_BOUNDARY,
Kristen Carlson Accardi31556592007-10-25 01:33:26 -0400328 .shost_attrs = ahci_shost_attrs,
Kristen Carlson Accardi18f7ba42008-06-03 10:33:55 -0700329 .sdev_attrs = ahci_sdev_attrs,
Linus Torvalds1da177e2005-04-16 15:20:36 -0700330};
331
Tejun Heo029cfd62008-03-25 12:22:49 +0900332static struct ata_port_operations ahci_ops = {
333 .inherits = &sata_pmp_port_ops,
334
Tejun Heo7d50b602007-09-23 13:19:54 +0900335 .qc_defer = sata_pmp_qc_defer_cmd_switch,
Linus Torvalds1da177e2005-04-16 15:20:36 -0700336 .qc_prep = ahci_qc_prep,
337 .qc_issue = ahci_qc_issue,
Tejun Heo4c9bf4e2008-04-07 22:47:20 +0900338 .qc_fill_rtf = ahci_qc_fill_rtf,
Linus Torvalds1da177e2005-04-16 15:20:36 -0700339
Tejun Heo78cd52d2006-05-15 20:58:29 +0900340 .freeze = ahci_freeze,
341 .thaw = ahci_thaw,
Tejun Heoa1efdab2008-03-25 12:22:50 +0900342 .softreset = ahci_softreset,
343 .hardreset = ahci_hardreset,
344 .postreset = ahci_postreset,
Tejun Heo071f44b2008-04-07 22:47:22 +0900345 .pmp_softreset = ahci_softreset,
Tejun Heo78cd52d2006-05-15 20:58:29 +0900346 .error_handler = ahci_error_handler,
347 .post_internal_cmd = ahci_post_internal_cmd,
Tejun Heo029cfd62008-03-25 12:22:49 +0900348 .dev_config = ahci_dev_config,
Tejun Heo78cd52d2006-05-15 20:58:29 +0900349
Tejun Heo029cfd62008-03-25 12:22:49 +0900350 .scr_read = ahci_scr_read,
351 .scr_write = ahci_scr_write,
Tejun Heo7d50b602007-09-23 13:19:54 +0900352 .pmp_attach = ahci_pmp_attach,
353 .pmp_detach = ahci_pmp_detach,
Tejun Heo7d50b602007-09-23 13:19:54 +0900354
Tejun Heo029cfd62008-03-25 12:22:49 +0900355 .enable_pm = ahci_enable_alpm,
356 .disable_pm = ahci_disable_alpm,
Kristen Carlson Accardi18f7ba42008-06-03 10:33:55 -0700357 .em_show = ahci_led_show,
358 .em_store = ahci_led_store,
359 .sw_activity_show = ahci_activity_show,
360 .sw_activity_store = ahci_activity_store,
Tejun Heo438ac6d2007-03-02 17:31:26 +0900361#ifdef CONFIG_PM
Tejun Heoc1332872006-07-26 15:59:26 +0900362 .port_suspend = ahci_port_suspend,
363 .port_resume = ahci_port_resume,
Tejun Heo438ac6d2007-03-02 17:31:26 +0900364#endif
Linus Torvalds1da177e2005-04-16 15:20:36 -0700365 .port_start = ahci_port_start,
366 .port_stop = ahci_port_stop,
Linus Torvalds1da177e2005-04-16 15:20:36 -0700367};
368
Tejun Heo029cfd62008-03-25 12:22:49 +0900369static struct ata_port_operations ahci_vt8251_ops = {
370 .inherits = &ahci_ops,
Tejun Heoa1efdab2008-03-25 12:22:50 +0900371 .hardreset = ahci_vt8251_hardreset,
Tejun Heoad616ff2006-11-01 18:00:24 +0900372};
373
Tejun Heo029cfd62008-03-25 12:22:49 +0900374static struct ata_port_operations ahci_p5wdh_ops = {
375 .inherits = &ahci_ops,
Tejun Heoa1efdab2008-03-25 12:22:50 +0900376 .hardreset = ahci_p5wdh_hardreset,
Tejun Heoedc93052007-10-25 14:59:16 +0900377};
378
Shane Huangbd172432008-06-10 15:52:04 +0800379static struct ata_port_operations ahci_sb600_ops = {
380 .inherits = &ahci_ops,
381 .softreset = ahci_sb600_softreset,
382 .pmp_softreset = ahci_sb600_softreset,
383};
384
Tejun Heo417a1a62007-09-23 13:19:55 +0900385#define AHCI_HFLAGS(flags) .private_data = (void *)(flags)
386
Arjan van de Ven98ac62d2005-11-28 10:06:23 +0100387static const struct ata_port_info ahci_port_info[] = {
Linus Torvalds1da177e2005-04-16 15:20:36 -0700388 /* board_ahci */
389 {
Tejun Heo1188c0d2007-04-23 02:41:05 +0900390 .flags = AHCI_FLAG_COMMON,
Brett Russ7da79312005-09-01 21:53:34 -0400391 .pio_mask = 0x1f, /* pio0-4 */
Jeff Garzik469248a2007-07-08 01:13:16 -0400392 .udma_mask = ATA_UDMA6,
Linus Torvalds1da177e2005-04-16 15:20:36 -0700393 .port_ops = &ahci_ops,
394 },
Bastiaan Jacquesbf2af2a2006-04-17 14:17:59 +0200395 /* board_ahci_vt8251 */
396 {
Tejun Heo6949b912007-09-23 13:19:55 +0900397 AHCI_HFLAGS (AHCI_HFLAG_NO_NCQ | AHCI_HFLAG_NO_PMP),
Tejun Heo417a1a62007-09-23 13:19:55 +0900398 .flags = AHCI_FLAG_COMMON,
Bastiaan Jacquesbf2af2a2006-04-17 14:17:59 +0200399 .pio_mask = 0x1f, /* pio0-4 */
Jeff Garzik469248a2007-07-08 01:13:16 -0400400 .udma_mask = ATA_UDMA6,
Tejun Heoad616ff2006-11-01 18:00:24 +0900401 .port_ops = &ahci_vt8251_ops,
Bastiaan Jacquesbf2af2a2006-04-17 14:17:59 +0200402 },
Tejun Heo41669552006-11-29 11:33:14 +0900403 /* board_ahci_ign_iferr */
404 {
Tejun Heo417a1a62007-09-23 13:19:55 +0900405 AHCI_HFLAGS (AHCI_HFLAG_IGN_IRQ_IF_ERR),
406 .flags = AHCI_FLAG_COMMON,
Tejun Heo41669552006-11-29 11:33:14 +0900407 .pio_mask = 0x1f, /* pio0-4 */
Jeff Garzik469248a2007-07-08 01:13:16 -0400408 .udma_mask = ATA_UDMA6,
Tejun Heo41669552006-11-29 11:33:14 +0900409 .port_ops = &ahci_ops,
410 },
Conke Hu55a61602007-03-27 18:33:05 +0800411 /* board_ahci_sb600 */
412 {
Tejun Heo417a1a62007-09-23 13:19:55 +0900413 AHCI_HFLAGS (AHCI_HFLAG_IGN_SERR_INTERNAL |
Tejun Heo22b5e7a2008-04-29 16:09:22 +0900414 AHCI_HFLAG_32BIT_ONLY | AHCI_HFLAG_NO_MSI |
Shane Huangbd172432008-06-10 15:52:04 +0800415 AHCI_HFLAG_SECT255),
Tejun Heo417a1a62007-09-23 13:19:55 +0900416 .flags = AHCI_FLAG_COMMON,
Conke Hu55a61602007-03-27 18:33:05 +0800417 .pio_mask = 0x1f, /* pio0-4 */
Jeff Garzik469248a2007-07-08 01:13:16 -0400418 .udma_mask = ATA_UDMA6,
Shane Huangbd172432008-06-10 15:52:04 +0800419 .port_ops = &ahci_sb600_ops,
Conke Hu55a61602007-03-27 18:33:05 +0800420 },
Jeff Garzikcd70c262007-07-08 02:29:42 -0400421 /* board_ahci_mv */
422 {
Tejun Heo417a1a62007-09-23 13:19:55 +0900423 AHCI_HFLAGS (AHCI_HFLAG_NO_NCQ | AHCI_HFLAG_NO_MSI |
Tejun Heo17248462008-08-29 16:03:59 +0200424 AHCI_HFLAG_MV_PATA | AHCI_HFLAG_NO_PMP),
Jeff Garzikcd70c262007-07-08 02:29:42 -0400425 .flags = ATA_FLAG_SATA | ATA_FLAG_NO_LEGACY |
Tejun Heo417a1a62007-09-23 13:19:55 +0900426 ATA_FLAG_MMIO | ATA_FLAG_PIO_DMA,
Jeff Garzikcd70c262007-07-08 02:29:42 -0400427 .pio_mask = 0x1f, /* pio0-4 */
428 .udma_mask = ATA_UDMA6,
429 .port_ops = &ahci_ops,
430 },
Shane Huange39fc8c2008-02-22 05:00:31 -0800431 /* board_ahci_sb700 */
432 {
Shane Huangbd172432008-06-10 15:52:04 +0800433 AHCI_HFLAGS (AHCI_HFLAG_IGN_SERR_INTERNAL),
Shane Huange39fc8c2008-02-22 05:00:31 -0800434 .flags = AHCI_FLAG_COMMON,
Shane Huange39fc8c2008-02-22 05:00:31 -0800435 .pio_mask = 0x1f, /* pio0-4 */
436 .udma_mask = ATA_UDMA6,
Shane Huangbd172432008-06-10 15:52:04 +0800437 .port_ops = &ahci_sb600_ops,
Shane Huange39fc8c2008-02-22 05:00:31 -0800438 },
Tejun Heoe297d992008-06-10 00:13:04 +0900439 /* board_ahci_mcp65 */
440 {
441 AHCI_HFLAGS (AHCI_HFLAG_YES_NCQ),
442 .flags = AHCI_FLAG_COMMON,
443 .pio_mask = 0x1f, /* pio0-4 */
444 .udma_mask = ATA_UDMA6,
445 .port_ops = &ahci_ops,
446 },
Tejun Heo9a3b1032008-06-18 20:56:58 -0400447 /* board_ahci_nopmp */
448 {
449 AHCI_HFLAGS (AHCI_HFLAG_NO_PMP),
450 .flags = AHCI_FLAG_COMMON,
451 .pio_mask = 0x1f, /* pio0-4 */
452 .udma_mask = ATA_UDMA6,
453 .port_ops = &ahci_ops,
454 },
Linus Torvalds1da177e2005-04-16 15:20:36 -0700455};
456
Jeff Garzik3b7d6972005-11-10 11:04:11 -0500457static const struct pci_device_id ahci_pci_tbl[] = {
Jeff Garzikfe7fa312006-06-22 23:05:36 -0400458 /* Intel */
Jeff Garzik54bb3a942006-09-27 22:20:11 -0400459 { PCI_VDEVICE(INTEL, 0x2652), board_ahci }, /* ICH6 */
460 { PCI_VDEVICE(INTEL, 0x2653), board_ahci }, /* ICH6M */
461 { PCI_VDEVICE(INTEL, 0x27c1), board_ahci }, /* ICH7 */
462 { PCI_VDEVICE(INTEL, 0x27c5), board_ahci }, /* ICH7M */
463 { PCI_VDEVICE(INTEL, 0x27c3), board_ahci }, /* ICH7R */
Tejun Heo82490c02007-01-23 15:13:39 +0900464 { PCI_VDEVICE(AL, 0x5288), board_ahci_ign_iferr }, /* ULi M5288 */
Jeff Garzik54bb3a942006-09-27 22:20:11 -0400465 { PCI_VDEVICE(INTEL, 0x2681), board_ahci }, /* ESB2 */
466 { PCI_VDEVICE(INTEL, 0x2682), board_ahci }, /* ESB2 */
467 { PCI_VDEVICE(INTEL, 0x2683), board_ahci }, /* ESB2 */
468 { PCI_VDEVICE(INTEL, 0x27c6), board_ahci }, /* ICH7-M DH */
Tejun Heo7a234af2007-09-03 12:44:57 +0900469 { PCI_VDEVICE(INTEL, 0x2821), board_ahci }, /* ICH8 */
470 { PCI_VDEVICE(INTEL, 0x2822), board_ahci }, /* ICH8 */
471 { PCI_VDEVICE(INTEL, 0x2824), board_ahci }, /* ICH8 */
472 { PCI_VDEVICE(INTEL, 0x2829), board_ahci }, /* ICH8M */
473 { PCI_VDEVICE(INTEL, 0x282a), board_ahci }, /* ICH8M */
474 { PCI_VDEVICE(INTEL, 0x2922), board_ahci }, /* ICH9 */
475 { PCI_VDEVICE(INTEL, 0x2923), board_ahci }, /* ICH9 */
476 { PCI_VDEVICE(INTEL, 0x2924), board_ahci }, /* ICH9 */
477 { PCI_VDEVICE(INTEL, 0x2925), board_ahci }, /* ICH9 */
478 { PCI_VDEVICE(INTEL, 0x2927), board_ahci }, /* ICH9 */
479 { PCI_VDEVICE(INTEL, 0x2929), board_ahci }, /* ICH9M */
480 { PCI_VDEVICE(INTEL, 0x292a), board_ahci }, /* ICH9M */
481 { PCI_VDEVICE(INTEL, 0x292b), board_ahci }, /* ICH9M */
482 { PCI_VDEVICE(INTEL, 0x292c), board_ahci }, /* ICH9M */
483 { PCI_VDEVICE(INTEL, 0x292f), board_ahci }, /* ICH9M */
484 { PCI_VDEVICE(INTEL, 0x294d), board_ahci }, /* ICH9 */
485 { PCI_VDEVICE(INTEL, 0x294e), board_ahci }, /* ICH9M */
Jason Gastond4155e62007-09-20 17:35:00 -0400486 { PCI_VDEVICE(INTEL, 0x502a), board_ahci }, /* Tolapai */
487 { PCI_VDEVICE(INTEL, 0x502b), board_ahci }, /* Tolapai */
Jason Gaston16ad1ad2008-01-28 17:34:14 -0800488 { PCI_VDEVICE(INTEL, 0x3a05), board_ahci }, /* ICH10 */
489 { PCI_VDEVICE(INTEL, 0x3a25), board_ahci }, /* ICH10 */
Seth Heasleyadcb5302008-08-11 17:03:09 -0700490 { PCI_VDEVICE(INTEL, 0x3b24), board_ahci }, /* PCH RAID */
Seth Heasley8e48b6b2008-08-27 16:47:22 -0700491 { PCI_VDEVICE(INTEL, 0x3b25), board_ahci }, /* PCH RAID */
Seth Heasleyadcb5302008-08-11 17:03:09 -0700492 { PCI_VDEVICE(INTEL, 0x3b2b), board_ahci }, /* PCH RAID */
Seth Heasley8e48b6b2008-08-27 16:47:22 -0700493 { PCI_VDEVICE(INTEL, 0x3b2c), board_ahci }, /* PCH RAID */
Jeff Garzikfe7fa312006-06-22 23:05:36 -0400494
Tejun Heoe34bb372007-02-26 20:24:03 +0900495 /* JMicron 360/1/3/5/6, match class to avoid IDE function */
496 { PCI_VENDOR_ID_JMICRON, PCI_ANY_ID, PCI_ANY_ID, PCI_ANY_ID,
497 PCI_CLASS_STORAGE_SATA_AHCI, 0xffffff, board_ahci_ign_iferr },
Jeff Garzikfe7fa312006-06-22 23:05:36 -0400498
499 /* ATI */
Conke Huc65ec1c2007-04-11 18:23:14 +0800500 { PCI_VDEVICE(ATI, 0x4380), board_ahci_sb600 }, /* ATI SB600 */
Shane Huange39fc8c2008-02-22 05:00:31 -0800501 { PCI_VDEVICE(ATI, 0x4390), board_ahci_sb700 }, /* ATI SB700/800 */
502 { PCI_VDEVICE(ATI, 0x4391), board_ahci_sb700 }, /* ATI SB700/800 */
503 { PCI_VDEVICE(ATI, 0x4392), board_ahci_sb700 }, /* ATI SB700/800 */
504 { PCI_VDEVICE(ATI, 0x4393), board_ahci_sb700 }, /* ATI SB700/800 */
505 { PCI_VDEVICE(ATI, 0x4394), board_ahci_sb700 }, /* ATI SB700/800 */
506 { PCI_VDEVICE(ATI, 0x4395), board_ahci_sb700 }, /* ATI SB700/800 */
Jeff Garzikfe7fa312006-06-22 23:05:36 -0400507
508 /* VIA */
Jeff Garzik54bb3a942006-09-27 22:20:11 -0400509 { PCI_VDEVICE(VIA, 0x3349), board_ahci_vt8251 }, /* VIA VT8251 */
Tejun Heobf335542007-04-11 17:27:14 +0900510 { PCI_VDEVICE(VIA, 0x6287), board_ahci_vt8251 }, /* VIA VT8251 */
Jeff Garzikfe7fa312006-06-22 23:05:36 -0400511
512 /* NVIDIA */
Tejun Heoe297d992008-06-10 00:13:04 +0900513 { PCI_VDEVICE(NVIDIA, 0x044c), board_ahci_mcp65 }, /* MCP65 */
514 { PCI_VDEVICE(NVIDIA, 0x044d), board_ahci_mcp65 }, /* MCP65 */
515 { PCI_VDEVICE(NVIDIA, 0x044e), board_ahci_mcp65 }, /* MCP65 */
516 { PCI_VDEVICE(NVIDIA, 0x044f), board_ahci_mcp65 }, /* MCP65 */
517 { PCI_VDEVICE(NVIDIA, 0x045c), board_ahci_mcp65 }, /* MCP65 */
518 { PCI_VDEVICE(NVIDIA, 0x045d), board_ahci_mcp65 }, /* MCP65 */
519 { PCI_VDEVICE(NVIDIA, 0x045e), board_ahci_mcp65 }, /* MCP65 */
520 { PCI_VDEVICE(NVIDIA, 0x045f), board_ahci_mcp65 }, /* MCP65 */
Peer Chen6fbf5ba2006-12-20 14:18:00 -0500521 { PCI_VDEVICE(NVIDIA, 0x0550), board_ahci }, /* MCP67 */
522 { PCI_VDEVICE(NVIDIA, 0x0551), board_ahci }, /* MCP67 */
523 { PCI_VDEVICE(NVIDIA, 0x0552), board_ahci }, /* MCP67 */
524 { PCI_VDEVICE(NVIDIA, 0x0553), board_ahci }, /* MCP67 */
Peer Chen895663c2006-11-02 17:59:46 -0500525 { PCI_VDEVICE(NVIDIA, 0x0554), board_ahci }, /* MCP67 */
526 { PCI_VDEVICE(NVIDIA, 0x0555), board_ahci }, /* MCP67 */
527 { PCI_VDEVICE(NVIDIA, 0x0556), board_ahci }, /* MCP67 */
528 { PCI_VDEVICE(NVIDIA, 0x0557), board_ahci }, /* MCP67 */
529 { PCI_VDEVICE(NVIDIA, 0x0558), board_ahci }, /* MCP67 */
530 { PCI_VDEVICE(NVIDIA, 0x0559), board_ahci }, /* MCP67 */
531 { PCI_VDEVICE(NVIDIA, 0x055a), board_ahci }, /* MCP67 */
532 { PCI_VDEVICE(NVIDIA, 0x055b), board_ahci }, /* MCP67 */
Peer Chen0522b282007-06-07 18:05:12 +0800533 { PCI_VDEVICE(NVIDIA, 0x07f0), board_ahci }, /* MCP73 */
534 { PCI_VDEVICE(NVIDIA, 0x07f1), board_ahci }, /* MCP73 */
535 { PCI_VDEVICE(NVIDIA, 0x07f2), board_ahci }, /* MCP73 */
536 { PCI_VDEVICE(NVIDIA, 0x07f3), board_ahci }, /* MCP73 */
537 { PCI_VDEVICE(NVIDIA, 0x07f4), board_ahci }, /* MCP73 */
538 { PCI_VDEVICE(NVIDIA, 0x07f5), board_ahci }, /* MCP73 */
539 { PCI_VDEVICE(NVIDIA, 0x07f6), board_ahci }, /* MCP73 */
540 { PCI_VDEVICE(NVIDIA, 0x07f7), board_ahci }, /* MCP73 */
541 { PCI_VDEVICE(NVIDIA, 0x07f8), board_ahci }, /* MCP73 */
542 { PCI_VDEVICE(NVIDIA, 0x07f9), board_ahci }, /* MCP73 */
543 { PCI_VDEVICE(NVIDIA, 0x07fa), board_ahci }, /* MCP73 */
544 { PCI_VDEVICE(NVIDIA, 0x07fb), board_ahci }, /* MCP73 */
545 { PCI_VDEVICE(NVIDIA, 0x0ad0), board_ahci }, /* MCP77 */
546 { PCI_VDEVICE(NVIDIA, 0x0ad1), board_ahci }, /* MCP77 */
547 { PCI_VDEVICE(NVIDIA, 0x0ad2), board_ahci }, /* MCP77 */
548 { PCI_VDEVICE(NVIDIA, 0x0ad3), board_ahci }, /* MCP77 */
549 { PCI_VDEVICE(NVIDIA, 0x0ad4), board_ahci }, /* MCP77 */
550 { PCI_VDEVICE(NVIDIA, 0x0ad5), board_ahci }, /* MCP77 */
551 { PCI_VDEVICE(NVIDIA, 0x0ad6), board_ahci }, /* MCP77 */
552 { PCI_VDEVICE(NVIDIA, 0x0ad7), board_ahci }, /* MCP77 */
553 { PCI_VDEVICE(NVIDIA, 0x0ad8), board_ahci }, /* MCP77 */
554 { PCI_VDEVICE(NVIDIA, 0x0ad9), board_ahci }, /* MCP77 */
555 { PCI_VDEVICE(NVIDIA, 0x0ada), board_ahci }, /* MCP77 */
556 { PCI_VDEVICE(NVIDIA, 0x0adb), board_ahci }, /* MCP77 */
peerchen6ba86952007-12-03 22:20:37 +0800557 { PCI_VDEVICE(NVIDIA, 0x0ab4), board_ahci }, /* MCP79 */
558 { PCI_VDEVICE(NVIDIA, 0x0ab5), board_ahci }, /* MCP79 */
559 { PCI_VDEVICE(NVIDIA, 0x0ab6), board_ahci }, /* MCP79 */
560 { PCI_VDEVICE(NVIDIA, 0x0ab7), board_ahci }, /* MCP79 */
Peer Chen71008192007-09-24 10:16:25 +0800561 { PCI_VDEVICE(NVIDIA, 0x0ab8), board_ahci }, /* MCP79 */
562 { PCI_VDEVICE(NVIDIA, 0x0ab9), board_ahci }, /* MCP79 */
563 { PCI_VDEVICE(NVIDIA, 0x0aba), board_ahci }, /* MCP79 */
564 { PCI_VDEVICE(NVIDIA, 0x0abb), board_ahci }, /* MCP79 */
565 { PCI_VDEVICE(NVIDIA, 0x0abc), board_ahci }, /* MCP79 */
566 { PCI_VDEVICE(NVIDIA, 0x0abd), board_ahci }, /* MCP79 */
567 { PCI_VDEVICE(NVIDIA, 0x0abe), board_ahci }, /* MCP79 */
568 { PCI_VDEVICE(NVIDIA, 0x0abf), board_ahci }, /* MCP79 */
peerchen70d562c2008-03-06 21:22:41 +0800569 { PCI_VDEVICE(NVIDIA, 0x0bc8), board_ahci }, /* MCP7B */
570 { PCI_VDEVICE(NVIDIA, 0x0bc9), board_ahci }, /* MCP7B */
571 { PCI_VDEVICE(NVIDIA, 0x0bca), board_ahci }, /* MCP7B */
572 { PCI_VDEVICE(NVIDIA, 0x0bcb), board_ahci }, /* MCP7B */
573 { PCI_VDEVICE(NVIDIA, 0x0bcc), board_ahci }, /* MCP7B */
574 { PCI_VDEVICE(NVIDIA, 0x0bcd), board_ahci }, /* MCP7B */
575 { PCI_VDEVICE(NVIDIA, 0x0bce), board_ahci }, /* MCP7B */
576 { PCI_VDEVICE(NVIDIA, 0x0bcf), board_ahci }, /* MCP7B */
peerchen3072c372008-05-19 14:44:57 +0800577 { PCI_VDEVICE(NVIDIA, 0x0bc4), board_ahci }, /* MCP7B */
578 { PCI_VDEVICE(NVIDIA, 0x0bc5), board_ahci }, /* MCP7B */
579 { PCI_VDEVICE(NVIDIA, 0x0bc6), board_ahci }, /* MCP7B */
580 { PCI_VDEVICE(NVIDIA, 0x0bc7), board_ahci }, /* MCP7B */
Jeff Garzikfe7fa312006-06-22 23:05:36 -0400581
Jeff Garzik95916ed2006-07-29 04:10:14 -0400582 /* SiS */
Tejun Heo20e2de42008-08-01 12:51:43 +0900583 { PCI_VDEVICE(SI, 0x1184), board_ahci }, /* SiS 966 */
584 { PCI_VDEVICE(SI, 0x1185), board_ahci }, /* SiS 968 */
585 { PCI_VDEVICE(SI, 0x0186), board_ahci }, /* SiS 968 */
Jeff Garzik95916ed2006-07-29 04:10:14 -0400586
Jeff Garzikcd70c262007-07-08 02:29:42 -0400587 /* Marvell */
588 { PCI_VDEVICE(MARVELL, 0x6145), board_ahci_mv }, /* 6145 */
Jose Alberto Regueroc40e7cb2008-03-13 23:22:24 +0100589 { PCI_VDEVICE(MARVELL, 0x6121), board_ahci_mv }, /* 6121 */
Jeff Garzikcd70c262007-07-08 02:29:42 -0400590
Mark Nelsonc77a0362008-10-23 14:08:16 +1100591 /* Promise */
592 { PCI_VDEVICE(PROMISE, 0x3f20), board_ahci }, /* PDC42819 */
593
Jeff Garzik415ae2b2006-11-01 05:10:42 -0500594 /* Generic, PCI class code for AHCI */
595 { PCI_ANY_ID, PCI_ANY_ID, PCI_ANY_ID, PCI_ANY_ID,
Conke Huc9f89472007-01-09 05:32:51 -0500596 PCI_CLASS_STORAGE_SATA_AHCI, 0xffffff, board_ahci },
Jeff Garzik415ae2b2006-11-01 05:10:42 -0500597
Linus Torvalds1da177e2005-04-16 15:20:36 -0700598 { } /* terminate list */
599};
600
601
602static struct pci_driver ahci_pci_driver = {
603 .name = DRV_NAME,
604 .id_table = ahci_pci_tbl,
605 .probe = ahci_init_one,
Tejun Heo24dc5f32007-01-20 16:00:28 +0900606 .remove = ata_pci_remove_one,
Tejun Heo438ac6d2007-03-02 17:31:26 +0900607#ifdef CONFIG_PM
Tejun Heoc1332872006-07-26 15:59:26 +0900608 .suspend = ahci_pci_device_suspend,
609 .resume = ahci_pci_device_resume,
Tejun Heo438ac6d2007-03-02 17:31:26 +0900610#endif
Linus Torvalds1da177e2005-04-16 15:20:36 -0700611};
612
Kristen Carlson Accardi18f7ba42008-06-03 10:33:55 -0700613static int ahci_em_messages = 1;
614module_param(ahci_em_messages, int, 0444);
615/* add other LED protocol types when they become supported */
616MODULE_PARM_DESC(ahci_em_messages,
617 "Set AHCI Enclosure Management Message type (0 = disabled, 1 = LED");
Linus Torvalds1da177e2005-04-16 15:20:36 -0700618
Alan Cox5b66c822008-09-03 14:48:34 +0100619#if defined(CONFIG_PATA_MARVELL) || defined(CONFIG_PATA_MARVELL_MODULE)
620static int marvell_enable;
621#else
622static int marvell_enable = 1;
623#endif
624module_param(marvell_enable, int, 0644);
625MODULE_PARM_DESC(marvell_enable, "Marvell SATA via AHCI (1 = enabled)");
626
627
Tejun Heo98fa4b62006-11-02 12:17:23 +0900628static inline int ahci_nr_ports(u32 cap)
629{
630 return (cap & 0x1f) + 1;
631}
632
Jeff Garzikdab632e2007-05-28 08:33:01 -0400633static inline void __iomem *__ahci_port_base(struct ata_host *host,
634 unsigned int port_no)
635{
636 void __iomem *mmio = host->iomap[AHCI_PCI_BAR];
637
638 return mmio + 0x100 + (port_no * 0x80);
639}
640
Tejun Heo4447d352007-04-17 23:44:08 +0900641static inline void __iomem *ahci_port_base(struct ata_port *ap)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700642{
Jeff Garzikdab632e2007-05-28 08:33:01 -0400643 return __ahci_port_base(ap->host, ap->port_no);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700644}
645
Tejun Heob710a1f2008-01-05 23:11:57 +0900646static void ahci_enable_ahci(void __iomem *mmio)
647{
Tejun Heo15fe9822008-04-23 20:52:58 +0900648 int i;
Tejun Heob710a1f2008-01-05 23:11:57 +0900649 u32 tmp;
650
651 /* turn on AHCI_EN */
652 tmp = readl(mmio + HOST_CTL);
Tejun Heo15fe9822008-04-23 20:52:58 +0900653 if (tmp & HOST_AHCI_EN)
654 return;
655
656 /* Some controllers need AHCI_EN to be written multiple times.
657 * Try a few times before giving up.
658 */
659 for (i = 0; i < 5; i++) {
Tejun Heob710a1f2008-01-05 23:11:57 +0900660 tmp |= HOST_AHCI_EN;
661 writel(tmp, mmio + HOST_CTL);
662 tmp = readl(mmio + HOST_CTL); /* flush && sanity check */
Tejun Heo15fe9822008-04-23 20:52:58 +0900663 if (tmp & HOST_AHCI_EN)
664 return;
665 msleep(10);
Tejun Heob710a1f2008-01-05 23:11:57 +0900666 }
Tejun Heo15fe9822008-04-23 20:52:58 +0900667
668 WARN_ON(1);
Tejun Heob710a1f2008-01-05 23:11:57 +0900669}
670
Tejun Heod447df12007-03-18 22:15:33 +0900671/**
672 * ahci_save_initial_config - Save and fixup initial config values
Tejun Heo4447d352007-04-17 23:44:08 +0900673 * @pdev: target PCI device
Tejun Heo4447d352007-04-17 23:44:08 +0900674 * @hpriv: host private area to store config values
Tejun Heod447df12007-03-18 22:15:33 +0900675 *
676 * Some registers containing configuration info might be setup by
677 * BIOS and might be cleared on reset. This function saves the
678 * initial values of those registers into @hpriv such that they
679 * can be restored after controller reset.
680 *
681 * If inconsistent, config values are fixed up by this function.
682 *
683 * LOCKING:
684 * None.
685 */
Tejun Heo4447d352007-04-17 23:44:08 +0900686static void ahci_save_initial_config(struct pci_dev *pdev,
Tejun Heo4447d352007-04-17 23:44:08 +0900687 struct ahci_host_priv *hpriv)
Tejun Heod447df12007-03-18 22:15:33 +0900688{
Tejun Heo4447d352007-04-17 23:44:08 +0900689 void __iomem *mmio = pcim_iomap_table(pdev)[AHCI_PCI_BAR];
Tejun Heod447df12007-03-18 22:15:33 +0900690 u32 cap, port_map;
Tejun Heo17199b12007-03-18 22:26:53 +0900691 int i;
Jose Alberto Regueroc40e7cb2008-03-13 23:22:24 +0100692 int mv;
Tejun Heod447df12007-03-18 22:15:33 +0900693
Tejun Heob710a1f2008-01-05 23:11:57 +0900694 /* make sure AHCI mode is enabled before accessing CAP */
695 ahci_enable_ahci(mmio);
696
Tejun Heod447df12007-03-18 22:15:33 +0900697 /* Values prefixed with saved_ are written back to host after
698 * reset. Values without are used for driver operation.
699 */
700 hpriv->saved_cap = cap = readl(mmio + HOST_CAP);
701 hpriv->saved_port_map = port_map = readl(mmio + HOST_PORTS_IMPL);
702
Tejun Heo274c1fd2007-07-16 14:29:40 +0900703 /* some chips have errata preventing 64bit use */
Tejun Heo417a1a62007-09-23 13:19:55 +0900704 if ((cap & HOST_CAP_64) && (hpriv->flags & AHCI_HFLAG_32BIT_ONLY)) {
Tejun Heoc7a42152007-05-18 16:23:19 +0200705 dev_printk(KERN_INFO, &pdev->dev,
706 "controller can't do 64bit DMA, forcing 32bit\n");
707 cap &= ~HOST_CAP_64;
708 }
709
Tejun Heo417a1a62007-09-23 13:19:55 +0900710 if ((cap & HOST_CAP_NCQ) && (hpriv->flags & AHCI_HFLAG_NO_NCQ)) {
Tejun Heo274c1fd2007-07-16 14:29:40 +0900711 dev_printk(KERN_INFO, &pdev->dev,
712 "controller can't do NCQ, turning off CAP_NCQ\n");
713 cap &= ~HOST_CAP_NCQ;
714 }
715
Tejun Heoe297d992008-06-10 00:13:04 +0900716 if (!(cap & HOST_CAP_NCQ) && (hpriv->flags & AHCI_HFLAG_YES_NCQ)) {
717 dev_printk(KERN_INFO, &pdev->dev,
718 "controller can do NCQ, turning on CAP_NCQ\n");
719 cap |= HOST_CAP_NCQ;
720 }
721
Roel Kluin258cd842008-03-09 21:42:40 +0100722 if ((cap & HOST_CAP_PMP) && (hpriv->flags & AHCI_HFLAG_NO_PMP)) {
Tejun Heo6949b912007-09-23 13:19:55 +0900723 dev_printk(KERN_INFO, &pdev->dev,
724 "controller can't do PMP, turning off CAP_PMP\n");
725 cap &= ~HOST_CAP_PMP;
726 }
727
Tejun Heod799e082008-06-17 12:46:30 +0900728 if (pdev->vendor == PCI_VENDOR_ID_JMICRON && pdev->device == 0x2361 &&
729 port_map != 1) {
730 dev_printk(KERN_INFO, &pdev->dev,
731 "JMB361 has only one port, port_map 0x%x -> 0x%x\n",
732 port_map, 1);
733 port_map = 1;
734 }
735
Jeff Garzikcd70c262007-07-08 02:29:42 -0400736 /*
737 * Temporary Marvell 6145 hack: PATA port presence
738 * is asserted through the standard AHCI port
739 * presence register, as bit 4 (counting from 0)
740 */
Tejun Heo417a1a62007-09-23 13:19:55 +0900741 if (hpriv->flags & AHCI_HFLAG_MV_PATA) {
Jose Alberto Regueroc40e7cb2008-03-13 23:22:24 +0100742 if (pdev->device == 0x6121)
743 mv = 0x3;
744 else
745 mv = 0xf;
Jeff Garzikcd70c262007-07-08 02:29:42 -0400746 dev_printk(KERN_ERR, &pdev->dev,
747 "MV_AHCI HACK: port_map %x -> %x\n",
Jose Alberto Regueroc40e7cb2008-03-13 23:22:24 +0100748 port_map,
749 port_map & mv);
Alan Cox5b66c822008-09-03 14:48:34 +0100750 dev_printk(KERN_ERR, &pdev->dev,
751 "Disabling your PATA port. Use the boot option 'ahci.marvell_enable=0' to avoid this.\n");
Jeff Garzikcd70c262007-07-08 02:29:42 -0400752
Jose Alberto Regueroc40e7cb2008-03-13 23:22:24 +0100753 port_map &= mv;
Jeff Garzikcd70c262007-07-08 02:29:42 -0400754 }
755
Tejun Heo17199b12007-03-18 22:26:53 +0900756 /* cross check port_map and cap.n_ports */
Tejun Heo7a234af2007-09-03 12:44:57 +0900757 if (port_map) {
Tejun Heo837f5f82008-02-06 15:13:51 +0900758 int map_ports = 0;
Tejun Heo17199b12007-03-18 22:26:53 +0900759
Tejun Heo837f5f82008-02-06 15:13:51 +0900760 for (i = 0; i < AHCI_MAX_PORTS; i++)
761 if (port_map & (1 << i))
762 map_ports++;
Tejun Heo17199b12007-03-18 22:26:53 +0900763
Tejun Heo837f5f82008-02-06 15:13:51 +0900764 /* If PI has more ports than n_ports, whine, clear
765 * port_map and let it be generated from n_ports.
Tejun Heo17199b12007-03-18 22:26:53 +0900766 */
Tejun Heo837f5f82008-02-06 15:13:51 +0900767 if (map_ports > ahci_nr_ports(cap)) {
Tejun Heo4447d352007-04-17 23:44:08 +0900768 dev_printk(KERN_WARNING, &pdev->dev,
Tejun Heo837f5f82008-02-06 15:13:51 +0900769 "implemented port map (0x%x) contains more "
770 "ports than nr_ports (%u), using nr_ports\n",
771 port_map, ahci_nr_ports(cap));
Tejun Heo7a234af2007-09-03 12:44:57 +0900772 port_map = 0;
773 }
774 }
775
776 /* fabricate port_map from cap.nr_ports */
777 if (!port_map) {
Tejun Heo17199b12007-03-18 22:26:53 +0900778 port_map = (1 << ahci_nr_ports(cap)) - 1;
Tejun Heo7a234af2007-09-03 12:44:57 +0900779 dev_printk(KERN_WARNING, &pdev->dev,
780 "forcing PORTS_IMPL to 0x%x\n", port_map);
781
782 /* write the fixed up value to the PI register */
783 hpriv->saved_port_map = port_map;
Tejun Heo17199b12007-03-18 22:26:53 +0900784 }
785
Tejun Heod447df12007-03-18 22:15:33 +0900786 /* record values to use during operation */
787 hpriv->cap = cap;
788 hpriv->port_map = port_map;
789}
790
791/**
792 * ahci_restore_initial_config - Restore initial config
Tejun Heo4447d352007-04-17 23:44:08 +0900793 * @host: target ATA host
Tejun Heod447df12007-03-18 22:15:33 +0900794 *
795 * Restore initial config stored by ahci_save_initial_config().
796 *
797 * LOCKING:
798 * None.
799 */
Tejun Heo4447d352007-04-17 23:44:08 +0900800static void ahci_restore_initial_config(struct ata_host *host)
Tejun Heod447df12007-03-18 22:15:33 +0900801{
Tejun Heo4447d352007-04-17 23:44:08 +0900802 struct ahci_host_priv *hpriv = host->private_data;
803 void __iomem *mmio = host->iomap[AHCI_PCI_BAR];
804
Tejun Heod447df12007-03-18 22:15:33 +0900805 writel(hpriv->saved_cap, mmio + HOST_CAP);
806 writel(hpriv->saved_port_map, mmio + HOST_PORTS_IMPL);
807 (void) readl(mmio + HOST_PORTS_IMPL); /* flush */
808}
809
Tejun Heo203ef6c2007-07-16 14:29:40 +0900810static unsigned ahci_scr_offset(struct ata_port *ap, unsigned int sc_reg)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700811{
Tejun Heo203ef6c2007-07-16 14:29:40 +0900812 static const int offset[] = {
813 [SCR_STATUS] = PORT_SCR_STAT,
814 [SCR_CONTROL] = PORT_SCR_CTL,
815 [SCR_ERROR] = PORT_SCR_ERR,
816 [SCR_ACTIVE] = PORT_SCR_ACT,
817 [SCR_NOTIFICATION] = PORT_SCR_NTF,
818 };
819 struct ahci_host_priv *hpriv = ap->host->private_data;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700820
Tejun Heo203ef6c2007-07-16 14:29:40 +0900821 if (sc_reg < ARRAY_SIZE(offset) &&
822 (sc_reg != SCR_NOTIFICATION || (hpriv->cap & HOST_CAP_SNTF)))
823 return offset[sc_reg];
Tejun Heoda3dbb12007-07-16 14:29:40 +0900824 return 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700825}
826
Tejun Heo82ef04f2008-07-31 17:02:40 +0900827static int ahci_scr_read(struct ata_link *link, unsigned int sc_reg, u32 *val)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700828{
Tejun Heo82ef04f2008-07-31 17:02:40 +0900829 void __iomem *port_mmio = ahci_port_base(link->ap);
830 int offset = ahci_scr_offset(link->ap, sc_reg);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700831
Tejun Heo203ef6c2007-07-16 14:29:40 +0900832 if (offset) {
833 *val = readl(port_mmio + offset);
834 return 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700835 }
Tejun Heo203ef6c2007-07-16 14:29:40 +0900836 return -EINVAL;
837}
Linus Torvalds1da177e2005-04-16 15:20:36 -0700838
Tejun Heo82ef04f2008-07-31 17:02:40 +0900839static int ahci_scr_write(struct ata_link *link, unsigned int sc_reg, u32 val)
Tejun Heo203ef6c2007-07-16 14:29:40 +0900840{
Tejun Heo82ef04f2008-07-31 17:02:40 +0900841 void __iomem *port_mmio = ahci_port_base(link->ap);
842 int offset = ahci_scr_offset(link->ap, sc_reg);
Tejun Heo203ef6c2007-07-16 14:29:40 +0900843
844 if (offset) {
845 writel(val, port_mmio + offset);
846 return 0;
847 }
848 return -EINVAL;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700849}
850
Tejun Heo4447d352007-04-17 23:44:08 +0900851static void ahci_start_engine(struct ata_port *ap)
Tejun Heo7c76d1e2005-12-19 22:36:34 +0900852{
Tejun Heo4447d352007-04-17 23:44:08 +0900853 void __iomem *port_mmio = ahci_port_base(ap);
Tejun Heo7c76d1e2005-12-19 22:36:34 +0900854 u32 tmp;
855
Tejun Heod8fcd112006-07-26 15:59:25 +0900856 /* start DMA */
Tejun Heo9f592052006-07-26 15:59:26 +0900857 tmp = readl(port_mmio + PORT_CMD);
Tejun Heo7c76d1e2005-12-19 22:36:34 +0900858 tmp |= PORT_CMD_START;
859 writel(tmp, port_mmio + PORT_CMD);
860 readl(port_mmio + PORT_CMD); /* flush */
861}
862
Tejun Heo4447d352007-04-17 23:44:08 +0900863static int ahci_stop_engine(struct ata_port *ap)
Tejun Heo254950c2006-07-26 15:59:25 +0900864{
Tejun Heo4447d352007-04-17 23:44:08 +0900865 void __iomem *port_mmio = ahci_port_base(ap);
Tejun Heo254950c2006-07-26 15:59:25 +0900866 u32 tmp;
867
868 tmp = readl(port_mmio + PORT_CMD);
869
Tejun Heod8fcd112006-07-26 15:59:25 +0900870 /* check if the HBA is idle */
Tejun Heo254950c2006-07-26 15:59:25 +0900871 if ((tmp & (PORT_CMD_START | PORT_CMD_LIST_ON)) == 0)
872 return 0;
873
Tejun Heod8fcd112006-07-26 15:59:25 +0900874 /* setting HBA to idle */
Tejun Heo254950c2006-07-26 15:59:25 +0900875 tmp &= ~PORT_CMD_START;
876 writel(tmp, port_mmio + PORT_CMD);
877
Tejun Heod8fcd112006-07-26 15:59:25 +0900878 /* wait for engine to stop. This could be as long as 500 msec */
Tejun Heo254950c2006-07-26 15:59:25 +0900879 tmp = ata_wait_register(port_mmio + PORT_CMD,
Jeff Garzik2dcb4072007-10-19 06:42:56 -0400880 PORT_CMD_LIST_ON, PORT_CMD_LIST_ON, 1, 500);
Tejun Heod8fcd112006-07-26 15:59:25 +0900881 if (tmp & PORT_CMD_LIST_ON)
Tejun Heo254950c2006-07-26 15:59:25 +0900882 return -EIO;
883
884 return 0;
885}
886
Tejun Heo4447d352007-04-17 23:44:08 +0900887static void ahci_start_fis_rx(struct ata_port *ap)
Tejun Heo0be0aa92006-07-26 15:59:26 +0900888{
Tejun Heo4447d352007-04-17 23:44:08 +0900889 void __iomem *port_mmio = ahci_port_base(ap);
890 struct ahci_host_priv *hpriv = ap->host->private_data;
891 struct ahci_port_priv *pp = ap->private_data;
Tejun Heo0be0aa92006-07-26 15:59:26 +0900892 u32 tmp;
893
894 /* set FIS registers */
Tejun Heo4447d352007-04-17 23:44:08 +0900895 if (hpriv->cap & HOST_CAP_64)
896 writel((pp->cmd_slot_dma >> 16) >> 16,
897 port_mmio + PORT_LST_ADDR_HI);
898 writel(pp->cmd_slot_dma & 0xffffffff, port_mmio + PORT_LST_ADDR);
Tejun Heo0be0aa92006-07-26 15:59:26 +0900899
Tejun Heo4447d352007-04-17 23:44:08 +0900900 if (hpriv->cap & HOST_CAP_64)
901 writel((pp->rx_fis_dma >> 16) >> 16,
902 port_mmio + PORT_FIS_ADDR_HI);
903 writel(pp->rx_fis_dma & 0xffffffff, port_mmio + PORT_FIS_ADDR);
Tejun Heo0be0aa92006-07-26 15:59:26 +0900904
905 /* enable FIS reception */
906 tmp = readl(port_mmio + PORT_CMD);
907 tmp |= PORT_CMD_FIS_RX;
908 writel(tmp, port_mmio + PORT_CMD);
909
910 /* flush */
911 readl(port_mmio + PORT_CMD);
912}
913
Tejun Heo4447d352007-04-17 23:44:08 +0900914static int ahci_stop_fis_rx(struct ata_port *ap)
Tejun Heo0be0aa92006-07-26 15:59:26 +0900915{
Tejun Heo4447d352007-04-17 23:44:08 +0900916 void __iomem *port_mmio = ahci_port_base(ap);
Tejun Heo0be0aa92006-07-26 15:59:26 +0900917 u32 tmp;
918
919 /* disable FIS reception */
920 tmp = readl(port_mmio + PORT_CMD);
921 tmp &= ~PORT_CMD_FIS_RX;
922 writel(tmp, port_mmio + PORT_CMD);
923
924 /* wait for completion, spec says 500ms, give it 1000 */
925 tmp = ata_wait_register(port_mmio + PORT_CMD, PORT_CMD_FIS_ON,
926 PORT_CMD_FIS_ON, 10, 1000);
927 if (tmp & PORT_CMD_FIS_ON)
928 return -EBUSY;
929
930 return 0;
931}
932
Tejun Heo4447d352007-04-17 23:44:08 +0900933static void ahci_power_up(struct ata_port *ap)
Tejun Heo0be0aa92006-07-26 15:59:26 +0900934{
Tejun Heo4447d352007-04-17 23:44:08 +0900935 struct ahci_host_priv *hpriv = ap->host->private_data;
936 void __iomem *port_mmio = ahci_port_base(ap);
Tejun Heo0be0aa92006-07-26 15:59:26 +0900937 u32 cmd;
938
939 cmd = readl(port_mmio + PORT_CMD) & ~PORT_CMD_ICC_MASK;
940
941 /* spin up device */
Tejun Heo4447d352007-04-17 23:44:08 +0900942 if (hpriv->cap & HOST_CAP_SSS) {
Tejun Heo0be0aa92006-07-26 15:59:26 +0900943 cmd |= PORT_CMD_SPIN_UP;
944 writel(cmd, port_mmio + PORT_CMD);
945 }
946
947 /* wake up link */
948 writel(cmd | PORT_CMD_ICC_ACTIVE, port_mmio + PORT_CMD);
949}
950
Kristen Carlson Accardi31556592007-10-25 01:33:26 -0400951static void ahci_disable_alpm(struct ata_port *ap)
952{
953 struct ahci_host_priv *hpriv = ap->host->private_data;
954 void __iomem *port_mmio = ahci_port_base(ap);
955 u32 cmd;
956 struct ahci_port_priv *pp = ap->private_data;
957
958 /* IPM bits should be disabled by libata-core */
959 /* get the existing command bits */
960 cmd = readl(port_mmio + PORT_CMD);
961
962 /* disable ALPM and ASP */
963 cmd &= ~PORT_CMD_ASP;
964 cmd &= ~PORT_CMD_ALPE;
965
966 /* force the interface back to active */
967 cmd |= PORT_CMD_ICC_ACTIVE;
968
969 /* write out new cmd value */
970 writel(cmd, port_mmio + PORT_CMD);
971 cmd = readl(port_mmio + PORT_CMD);
972
973 /* wait 10ms to be sure we've come out of any low power state */
974 msleep(10);
975
976 /* clear out any PhyRdy stuff from interrupt status */
977 writel(PORT_IRQ_PHYRDY, port_mmio + PORT_IRQ_STAT);
978
979 /* go ahead and clean out PhyRdy Change from Serror too */
Tejun Heo82ef04f2008-07-31 17:02:40 +0900980 ahci_scr_write(&ap->link, SCR_ERROR, ((1 << 16) | (1 << 18)));
Kristen Carlson Accardi31556592007-10-25 01:33:26 -0400981
982 /*
983 * Clear flag to indicate that we should ignore all PhyRdy
984 * state changes
985 */
986 hpriv->flags &= ~AHCI_HFLAG_NO_HOTPLUG;
987
988 /*
989 * Enable interrupts on Phy Ready.
990 */
991 pp->intr_mask |= PORT_IRQ_PHYRDY;
992 writel(pp->intr_mask, port_mmio + PORT_IRQ_MASK);
993
994 /*
995 * don't change the link pm policy - we can be called
996 * just to turn of link pm temporarily
997 */
998}
999
1000static int ahci_enable_alpm(struct ata_port *ap,
1001 enum link_pm policy)
1002{
1003 struct ahci_host_priv *hpriv = ap->host->private_data;
1004 void __iomem *port_mmio = ahci_port_base(ap);
1005 u32 cmd;
1006 struct ahci_port_priv *pp = ap->private_data;
1007 u32 asp;
1008
1009 /* Make sure the host is capable of link power management */
1010 if (!(hpriv->cap & HOST_CAP_ALPM))
1011 return -EINVAL;
1012
1013 switch (policy) {
1014 case MAX_PERFORMANCE:
1015 case NOT_AVAILABLE:
1016 /*
1017 * if we came here with NOT_AVAILABLE,
1018 * it just means this is the first time we
1019 * have tried to enable - default to max performance,
1020 * and let the user go to lower power modes on request.
1021 */
1022 ahci_disable_alpm(ap);
1023 return 0;
1024 case MIN_POWER:
1025 /* configure HBA to enter SLUMBER */
1026 asp = PORT_CMD_ASP;
1027 break;
1028 case MEDIUM_POWER:
1029 /* configure HBA to enter PARTIAL */
1030 asp = 0;
1031 break;
1032 default:
1033 return -EINVAL;
1034 }
1035
1036 /*
1037 * Disable interrupts on Phy Ready. This keeps us from
1038 * getting woken up due to spurious phy ready interrupts
1039 * TBD - Hot plug should be done via polling now, is
1040 * that even supported?
1041 */
1042 pp->intr_mask &= ~PORT_IRQ_PHYRDY;
1043 writel(pp->intr_mask, port_mmio + PORT_IRQ_MASK);
1044
1045 /*
1046 * Set a flag to indicate that we should ignore all PhyRdy
1047 * state changes since these can happen now whenever we
1048 * change link state
1049 */
1050 hpriv->flags |= AHCI_HFLAG_NO_HOTPLUG;
1051
1052 /* get the existing command bits */
1053 cmd = readl(port_mmio + PORT_CMD);
1054
1055 /*
1056 * Set ASP based on Policy
1057 */
1058 cmd |= asp;
1059
1060 /*
1061 * Setting this bit will instruct the HBA to aggressively
1062 * enter a lower power link state when it's appropriate and
1063 * based on the value set above for ASP
1064 */
1065 cmd |= PORT_CMD_ALPE;
1066
1067 /* write out new cmd value */
1068 writel(cmd, port_mmio + PORT_CMD);
1069 cmd = readl(port_mmio + PORT_CMD);
1070
1071 /* IPM bits should be set by libata-core */
1072 return 0;
1073}
1074
Tejun Heo438ac6d2007-03-02 17:31:26 +09001075#ifdef CONFIG_PM
Tejun Heo4447d352007-04-17 23:44:08 +09001076static void ahci_power_down(struct ata_port *ap)
Tejun Heo0be0aa92006-07-26 15:59:26 +09001077{
Tejun Heo4447d352007-04-17 23:44:08 +09001078 struct ahci_host_priv *hpriv = ap->host->private_data;
1079 void __iomem *port_mmio = ahci_port_base(ap);
Tejun Heo0be0aa92006-07-26 15:59:26 +09001080 u32 cmd, scontrol;
1081
Tejun Heo4447d352007-04-17 23:44:08 +09001082 if (!(hpriv->cap & HOST_CAP_SSS))
Tejun Heo07c53da2007-01-21 02:10:11 +09001083 return;
1084
1085 /* put device into listen mode, first set PxSCTL.DET to 0 */
1086 scontrol = readl(port_mmio + PORT_SCR_CTL);
1087 scontrol &= ~0xf;
1088 writel(scontrol, port_mmio + PORT_SCR_CTL);
1089
1090 /* then set PxCMD.SUD to 0 */
Tejun Heo0be0aa92006-07-26 15:59:26 +09001091 cmd = readl(port_mmio + PORT_CMD) & ~PORT_CMD_ICC_MASK;
Tejun Heo07c53da2007-01-21 02:10:11 +09001092 cmd &= ~PORT_CMD_SPIN_UP;
1093 writel(cmd, port_mmio + PORT_CMD);
Tejun Heo0be0aa92006-07-26 15:59:26 +09001094}
Tejun Heo438ac6d2007-03-02 17:31:26 +09001095#endif
Tejun Heo0be0aa92006-07-26 15:59:26 +09001096
Jeff Garzikdf69c9c2007-05-26 20:46:51 -04001097static void ahci_start_port(struct ata_port *ap)
Tejun Heo0be0aa92006-07-26 15:59:26 +09001098{
Kristen Carlson Accardi18f7ba42008-06-03 10:33:55 -07001099 struct ahci_port_priv *pp = ap->private_data;
1100 struct ata_link *link;
1101 struct ahci_em_priv *emp;
1102
Tejun Heo0be0aa92006-07-26 15:59:26 +09001103 /* enable FIS reception */
Tejun Heo4447d352007-04-17 23:44:08 +09001104 ahci_start_fis_rx(ap);
Tejun Heo0be0aa92006-07-26 15:59:26 +09001105
1106 /* enable DMA */
Tejun Heo4447d352007-04-17 23:44:08 +09001107 ahci_start_engine(ap);
Kristen Carlson Accardi18f7ba42008-06-03 10:33:55 -07001108
1109 /* turn on LEDs */
1110 if (ap->flags & ATA_FLAG_EM) {
1111 ata_port_for_each_link(link, ap) {
1112 emp = &pp->em_priv[link->pmp];
1113 ahci_transmit_led_message(ap, emp->led_state, 4);
1114 }
1115 }
1116
1117 if (ap->flags & ATA_FLAG_SW_ACTIVITY)
1118 ata_port_for_each_link(link, ap)
1119 ahci_init_sw_activity(link);
1120
Tejun Heo0be0aa92006-07-26 15:59:26 +09001121}
1122
Tejun Heo4447d352007-04-17 23:44:08 +09001123static int ahci_deinit_port(struct ata_port *ap, const char **emsg)
Tejun Heo0be0aa92006-07-26 15:59:26 +09001124{
1125 int rc;
1126
1127 /* disable DMA */
Tejun Heo4447d352007-04-17 23:44:08 +09001128 rc = ahci_stop_engine(ap);
Tejun Heo0be0aa92006-07-26 15:59:26 +09001129 if (rc) {
1130 *emsg = "failed to stop engine";
1131 return rc;
1132 }
1133
1134 /* disable FIS reception */
Tejun Heo4447d352007-04-17 23:44:08 +09001135 rc = ahci_stop_fis_rx(ap);
Tejun Heo0be0aa92006-07-26 15:59:26 +09001136 if (rc) {
1137 *emsg = "failed stop FIS RX";
1138 return rc;
1139 }
1140
Tejun Heo0be0aa92006-07-26 15:59:26 +09001141 return 0;
1142}
1143
Tejun Heo4447d352007-04-17 23:44:08 +09001144static int ahci_reset_controller(struct ata_host *host)
Tejun Heod91542c2006-07-26 15:59:26 +09001145{
Tejun Heo4447d352007-04-17 23:44:08 +09001146 struct pci_dev *pdev = to_pci_dev(host->dev);
Tejun Heo49f29092007-11-19 16:03:44 +09001147 struct ahci_host_priv *hpriv = host->private_data;
Tejun Heo4447d352007-04-17 23:44:08 +09001148 void __iomem *mmio = host->iomap[AHCI_PCI_BAR];
Tejun Heod447df12007-03-18 22:15:33 +09001149 u32 tmp;
Tejun Heod91542c2006-07-26 15:59:26 +09001150
Jeff Garzik3cc3eb12007-09-26 00:02:41 -04001151 /* we must be in AHCI mode, before using anything
1152 * AHCI-specific, such as HOST_RESET.
1153 */
Tejun Heob710a1f2008-01-05 23:11:57 +09001154 ahci_enable_ahci(mmio);
Jeff Garzik3cc3eb12007-09-26 00:02:41 -04001155
1156 /* global controller reset */
Tejun Heoa22e6442008-03-10 10:25:25 +09001157 if (!ahci_skip_host_reset) {
1158 tmp = readl(mmio + HOST_CTL);
1159 if ((tmp & HOST_RESET) == 0) {
1160 writel(tmp | HOST_RESET, mmio + HOST_CTL);
1161 readl(mmio + HOST_CTL); /* flush */
1162 }
Tejun Heod91542c2006-07-26 15:59:26 +09001163
Zhang Rui24920c82008-07-04 13:32:17 +08001164 /*
1165 * to perform host reset, OS should set HOST_RESET
1166 * and poll until this bit is read to be "0".
1167 * reset must complete within 1 second, or
Tejun Heoa22e6442008-03-10 10:25:25 +09001168 * the hardware should be considered fried.
1169 */
Zhang Rui24920c82008-07-04 13:32:17 +08001170 tmp = ata_wait_register(mmio + HOST_CTL, HOST_RESET,
1171 HOST_RESET, 10, 1000);
Tejun Heod91542c2006-07-26 15:59:26 +09001172
Tejun Heoa22e6442008-03-10 10:25:25 +09001173 if (tmp & HOST_RESET) {
1174 dev_printk(KERN_ERR, host->dev,
1175 "controller reset failed (0x%x)\n", tmp);
1176 return -EIO;
1177 }
Tejun Heod91542c2006-07-26 15:59:26 +09001178
Tejun Heoa22e6442008-03-10 10:25:25 +09001179 /* turn on AHCI mode */
1180 ahci_enable_ahci(mmio);
Tejun Heo98fa4b62006-11-02 12:17:23 +09001181
Tejun Heoa22e6442008-03-10 10:25:25 +09001182 /* Some registers might be cleared on reset. Restore
1183 * initial values.
1184 */
1185 ahci_restore_initial_config(host);
1186 } else
1187 dev_printk(KERN_INFO, host->dev,
1188 "skipping global host reset\n");
Tejun Heod91542c2006-07-26 15:59:26 +09001189
1190 if (pdev->vendor == PCI_VENDOR_ID_INTEL) {
1191 u16 tmp16;
1192
1193 /* configure PCS */
1194 pci_read_config_word(pdev, 0x92, &tmp16);
Tejun Heo49f29092007-11-19 16:03:44 +09001195 if ((tmp16 & hpriv->port_map) != hpriv->port_map) {
1196 tmp16 |= hpriv->port_map;
1197 pci_write_config_word(pdev, 0x92, tmp16);
1198 }
Tejun Heod91542c2006-07-26 15:59:26 +09001199 }
1200
1201 return 0;
1202}
1203
Kristen Carlson Accardi18f7ba42008-06-03 10:33:55 -07001204static void ahci_sw_activity(struct ata_link *link)
1205{
1206 struct ata_port *ap = link->ap;
1207 struct ahci_port_priv *pp = ap->private_data;
1208 struct ahci_em_priv *emp = &pp->em_priv[link->pmp];
1209
1210 if (!(link->flags & ATA_LFLAG_SW_ACTIVITY))
1211 return;
1212
1213 emp->activity++;
1214 if (!timer_pending(&emp->timer))
1215 mod_timer(&emp->timer, jiffies + msecs_to_jiffies(10));
1216}
1217
1218static void ahci_sw_activity_blink(unsigned long arg)
1219{
1220 struct ata_link *link = (struct ata_link *)arg;
1221 struct ata_port *ap = link->ap;
1222 struct ahci_port_priv *pp = ap->private_data;
1223 struct ahci_em_priv *emp = &pp->em_priv[link->pmp];
1224 unsigned long led_message = emp->led_state;
1225 u32 activity_led_state;
David Milburneb409632008-10-16 09:26:19 -05001226 unsigned long flags;
Kristen Carlson Accardi18f7ba42008-06-03 10:33:55 -07001227
1228 led_message &= 0xffff0000;
1229 led_message |= ap->port_no | (link->pmp << 8);
1230
1231 /* check to see if we've had activity. If so,
1232 * toggle state of LED and reset timer. If not,
1233 * turn LED to desired idle state.
1234 */
David Milburneb409632008-10-16 09:26:19 -05001235 spin_lock_irqsave(ap->lock, flags);
Kristen Carlson Accardi18f7ba42008-06-03 10:33:55 -07001236 if (emp->saved_activity != emp->activity) {
1237 emp->saved_activity = emp->activity;
1238 /* get the current LED state */
1239 activity_led_state = led_message & 0x00010000;
1240
1241 if (activity_led_state)
1242 activity_led_state = 0;
1243 else
1244 activity_led_state = 1;
1245
1246 /* clear old state */
1247 led_message &= 0xfff8ffff;
1248
1249 /* toggle state */
1250 led_message |= (activity_led_state << 16);
1251 mod_timer(&emp->timer, jiffies + msecs_to_jiffies(100));
1252 } else {
1253 /* switch to idle */
1254 led_message &= 0xfff8ffff;
1255 if (emp->blink_policy == BLINK_OFF)
1256 led_message |= (1 << 16);
1257 }
David Milburneb409632008-10-16 09:26:19 -05001258 spin_unlock_irqrestore(ap->lock, flags);
Kristen Carlson Accardi18f7ba42008-06-03 10:33:55 -07001259 ahci_transmit_led_message(ap, led_message, 4);
1260}
1261
1262static void ahci_init_sw_activity(struct ata_link *link)
1263{
1264 struct ata_port *ap = link->ap;
1265 struct ahci_port_priv *pp = ap->private_data;
1266 struct ahci_em_priv *emp = &pp->em_priv[link->pmp];
1267
1268 /* init activity stats, setup timer */
1269 emp->saved_activity = emp->activity = 0;
1270 setup_timer(&emp->timer, ahci_sw_activity_blink, (unsigned long)link);
1271
1272 /* check our blink policy and set flag for link if it's enabled */
1273 if (emp->blink_policy)
1274 link->flags |= ATA_LFLAG_SW_ACTIVITY;
1275}
1276
1277static int ahci_reset_em(struct ata_host *host)
1278{
1279 void __iomem *mmio = host->iomap[AHCI_PCI_BAR];
1280 u32 em_ctl;
1281
1282 em_ctl = readl(mmio + HOST_EM_CTL);
1283 if ((em_ctl & EM_CTL_TM) || (em_ctl & EM_CTL_RST))
1284 return -EINVAL;
1285
1286 writel(em_ctl | EM_CTL_RST, mmio + HOST_EM_CTL);
1287 return 0;
1288}
1289
1290static ssize_t ahci_transmit_led_message(struct ata_port *ap, u32 state,
1291 ssize_t size)
1292{
1293 struct ahci_host_priv *hpriv = ap->host->private_data;
1294 struct ahci_port_priv *pp = ap->private_data;
1295 void __iomem *mmio = ap->host->iomap[AHCI_PCI_BAR];
1296 u32 em_ctl;
1297 u32 message[] = {0, 0};
Linus Torvalds93082f02008-07-25 10:56:36 -07001298 unsigned long flags;
Kristen Carlson Accardi18f7ba42008-06-03 10:33:55 -07001299 int pmp;
1300 struct ahci_em_priv *emp;
1301
1302 /* get the slot number from the message */
1303 pmp = (state & 0x0000ff00) >> 8;
1304 if (pmp < MAX_SLOTS)
1305 emp = &pp->em_priv[pmp];
1306 else
1307 return -EINVAL;
1308
1309 spin_lock_irqsave(ap->lock, flags);
1310
1311 /*
1312 * if we are still busy transmitting a previous message,
1313 * do not allow
1314 */
1315 em_ctl = readl(mmio + HOST_EM_CTL);
1316 if (em_ctl & EM_CTL_TM) {
1317 spin_unlock_irqrestore(ap->lock, flags);
1318 return -EINVAL;
1319 }
1320
1321 /*
1322 * create message header - this is all zero except for
1323 * the message size, which is 4 bytes.
1324 */
1325 message[0] |= (4 << 8);
1326
1327 /* ignore 0:4 of byte zero, fill in port info yourself */
1328 message[1] = ((state & 0xfffffff0) | ap->port_no);
1329
1330 /* write message to EM_LOC */
1331 writel(message[0], mmio + hpriv->em_loc);
1332 writel(message[1], mmio + hpriv->em_loc+4);
1333
1334 /* save off new led state for port/slot */
1335 emp->led_state = message[1];
1336
1337 /*
1338 * tell hardware to transmit the message
1339 */
1340 writel(em_ctl | EM_CTL_TM, mmio + HOST_EM_CTL);
1341
1342 spin_unlock_irqrestore(ap->lock, flags);
1343 return size;
1344}
1345
1346static ssize_t ahci_led_show(struct ata_port *ap, char *buf)
1347{
1348 struct ahci_port_priv *pp = ap->private_data;
1349 struct ata_link *link;
1350 struct ahci_em_priv *emp;
1351 int rc = 0;
1352
1353 ata_port_for_each_link(link, ap) {
1354 emp = &pp->em_priv[link->pmp];
1355 rc += sprintf(buf, "%lx\n", emp->led_state);
1356 }
1357 return rc;
1358}
1359
1360static ssize_t ahci_led_store(struct ata_port *ap, const char *buf,
1361 size_t size)
1362{
1363 int state;
1364 int pmp;
1365 struct ahci_port_priv *pp = ap->private_data;
1366 struct ahci_em_priv *emp;
1367
1368 state = simple_strtoul(buf, NULL, 0);
1369
1370 /* get the slot number from the message */
1371 pmp = (state & 0x0000ff00) >> 8;
1372 if (pmp < MAX_SLOTS)
1373 emp = &pp->em_priv[pmp];
1374 else
1375 return -EINVAL;
1376
1377 /* mask off the activity bits if we are in sw_activity
1378 * mode, user should turn off sw_activity before setting
1379 * activity led through em_message
1380 */
1381 if (emp->blink_policy)
1382 state &= 0xfff8ffff;
1383
1384 return ahci_transmit_led_message(ap, state, size);
1385}
1386
1387static ssize_t ahci_activity_store(struct ata_device *dev, enum sw_activity val)
1388{
1389 struct ata_link *link = dev->link;
1390 struct ata_port *ap = link->ap;
1391 struct ahci_port_priv *pp = ap->private_data;
1392 struct ahci_em_priv *emp = &pp->em_priv[link->pmp];
1393 u32 port_led_state = emp->led_state;
1394
1395 /* save the desired Activity LED behavior */
1396 if (val == OFF) {
1397 /* clear LFLAG */
1398 link->flags &= ~(ATA_LFLAG_SW_ACTIVITY);
1399
1400 /* set the LED to OFF */
1401 port_led_state &= 0xfff80000;
1402 port_led_state |= (ap->port_no | (link->pmp << 8));
1403 ahci_transmit_led_message(ap, port_led_state, 4);
1404 } else {
1405 link->flags |= ATA_LFLAG_SW_ACTIVITY;
1406 if (val == BLINK_OFF) {
1407 /* set LED to ON for idle */
1408 port_led_state &= 0xfff80000;
1409 port_led_state |= (ap->port_no | (link->pmp << 8));
1410 port_led_state |= 0x00010000; /* check this */
1411 ahci_transmit_led_message(ap, port_led_state, 4);
1412 }
1413 }
1414 emp->blink_policy = val;
1415 return 0;
1416}
1417
1418static ssize_t ahci_activity_show(struct ata_device *dev, char *buf)
1419{
1420 struct ata_link *link = dev->link;
1421 struct ata_port *ap = link->ap;
1422 struct ahci_port_priv *pp = ap->private_data;
1423 struct ahci_em_priv *emp = &pp->em_priv[link->pmp];
1424
1425 /* display the saved value of activity behavior for this
1426 * disk.
1427 */
1428 return sprintf(buf, "%d\n", emp->blink_policy);
1429}
1430
Jeff Garzik2bcd8662007-05-28 07:45:27 -04001431static void ahci_port_init(struct pci_dev *pdev, struct ata_port *ap,
1432 int port_no, void __iomem *mmio,
1433 void __iomem *port_mmio)
1434{
1435 const char *emsg = NULL;
1436 int rc;
1437 u32 tmp;
1438
1439 /* make sure port is not active */
1440 rc = ahci_deinit_port(ap, &emsg);
1441 if (rc)
1442 dev_printk(KERN_WARNING, &pdev->dev,
1443 "%s (%d)\n", emsg, rc);
1444
1445 /* clear SError */
1446 tmp = readl(port_mmio + PORT_SCR_ERR);
1447 VPRINTK("PORT_SCR_ERR 0x%x\n", tmp);
1448 writel(tmp, port_mmio + PORT_SCR_ERR);
1449
1450 /* clear port IRQ */
1451 tmp = readl(port_mmio + PORT_IRQ_STAT);
1452 VPRINTK("PORT_IRQ_STAT 0x%x\n", tmp);
1453 if (tmp)
1454 writel(tmp, port_mmio + PORT_IRQ_STAT);
1455
1456 writel(1 << port_no, mmio + HOST_IRQ_STAT);
1457}
1458
Tejun Heo4447d352007-04-17 23:44:08 +09001459static void ahci_init_controller(struct ata_host *host)
Tejun Heod91542c2006-07-26 15:59:26 +09001460{
Tejun Heo417a1a62007-09-23 13:19:55 +09001461 struct ahci_host_priv *hpriv = host->private_data;
Tejun Heo4447d352007-04-17 23:44:08 +09001462 struct pci_dev *pdev = to_pci_dev(host->dev);
1463 void __iomem *mmio = host->iomap[AHCI_PCI_BAR];
Jeff Garzik2bcd8662007-05-28 07:45:27 -04001464 int i;
Jeff Garzikcd70c262007-07-08 02:29:42 -04001465 void __iomem *port_mmio;
Tejun Heod91542c2006-07-26 15:59:26 +09001466 u32 tmp;
Jose Alberto Regueroc40e7cb2008-03-13 23:22:24 +01001467 int mv;
Tejun Heod91542c2006-07-26 15:59:26 +09001468
Tejun Heo417a1a62007-09-23 13:19:55 +09001469 if (hpriv->flags & AHCI_HFLAG_MV_PATA) {
Jose Alberto Regueroc40e7cb2008-03-13 23:22:24 +01001470 if (pdev->device == 0x6121)
1471 mv = 2;
1472 else
1473 mv = 4;
1474 port_mmio = __ahci_port_base(host, mv);
Jeff Garzikcd70c262007-07-08 02:29:42 -04001475
1476 writel(0, port_mmio + PORT_IRQ_MASK);
1477
1478 /* clear port IRQ */
1479 tmp = readl(port_mmio + PORT_IRQ_STAT);
1480 VPRINTK("PORT_IRQ_STAT 0x%x\n", tmp);
1481 if (tmp)
1482 writel(tmp, port_mmio + PORT_IRQ_STAT);
1483 }
1484
Tejun Heo4447d352007-04-17 23:44:08 +09001485 for (i = 0; i < host->n_ports; i++) {
1486 struct ata_port *ap = host->ports[i];
Tejun Heod91542c2006-07-26 15:59:26 +09001487
Jeff Garzikcd70c262007-07-08 02:29:42 -04001488 port_mmio = ahci_port_base(ap);
Tejun Heo4447d352007-04-17 23:44:08 +09001489 if (ata_port_is_dummy(ap))
Tejun Heod91542c2006-07-26 15:59:26 +09001490 continue;
Tejun Heod91542c2006-07-26 15:59:26 +09001491
Jeff Garzik2bcd8662007-05-28 07:45:27 -04001492 ahci_port_init(pdev, ap, i, mmio, port_mmio);
Tejun Heod91542c2006-07-26 15:59:26 +09001493 }
1494
1495 tmp = readl(mmio + HOST_CTL);
1496 VPRINTK("HOST_CTL 0x%x\n", tmp);
1497 writel(tmp | HOST_IRQ_EN, mmio + HOST_CTL);
1498 tmp = readl(mmio + HOST_CTL);
1499 VPRINTK("HOST_CTL 0x%x\n", tmp);
1500}
1501
Jeff Garzika8785392008-02-28 15:43:48 -05001502static void ahci_dev_config(struct ata_device *dev)
1503{
1504 struct ahci_host_priv *hpriv = dev->link->ap->host->private_data;
1505
Jeff Garzik4cde32f2008-03-24 22:40:40 -04001506 if (hpriv->flags & AHCI_HFLAG_SECT255) {
Jeff Garzika8785392008-02-28 15:43:48 -05001507 dev->max_sectors = 255;
Jeff Garzik4cde32f2008-03-24 22:40:40 -04001508 ata_dev_printk(dev, KERN_INFO,
1509 "SB600 AHCI: limiting to 255 sectors per cmd\n");
1510 }
Jeff Garzika8785392008-02-28 15:43:48 -05001511}
1512
Tejun Heo422b7592005-12-19 22:37:17 +09001513static unsigned int ahci_dev_classify(struct ata_port *ap)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001514{
Tejun Heo4447d352007-04-17 23:44:08 +09001515 void __iomem *port_mmio = ahci_port_base(ap);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001516 struct ata_taskfile tf;
Tejun Heo422b7592005-12-19 22:37:17 +09001517 u32 tmp;
1518
1519 tmp = readl(port_mmio + PORT_SIG);
1520 tf.lbah = (tmp >> 24) & 0xff;
1521 tf.lbam = (tmp >> 16) & 0xff;
1522 tf.lbal = (tmp >> 8) & 0xff;
1523 tf.nsect = (tmp) & 0xff;
1524
1525 return ata_dev_classify(&tf);
1526}
1527
Tejun Heo12fad3f2006-05-15 21:03:55 +09001528static void ahci_fill_cmd_slot(struct ahci_port_priv *pp, unsigned int tag,
1529 u32 opts)
Tejun Heocc9278e2006-02-10 17:25:47 +09001530{
Tejun Heo12fad3f2006-05-15 21:03:55 +09001531 dma_addr_t cmd_tbl_dma;
1532
1533 cmd_tbl_dma = pp->cmd_tbl_dma + tag * AHCI_CMD_TBL_SZ;
1534
1535 pp->cmd_slot[tag].opts = cpu_to_le32(opts);
1536 pp->cmd_slot[tag].status = 0;
1537 pp->cmd_slot[tag].tbl_addr = cpu_to_le32(cmd_tbl_dma & 0xffffffff);
1538 pp->cmd_slot[tag].tbl_addr_hi = cpu_to_le32((cmd_tbl_dma >> 16) >> 16);
Tejun Heocc9278e2006-02-10 17:25:47 +09001539}
1540
Tejun Heod2e75df2007-07-16 14:29:39 +09001541static int ahci_kick_engine(struct ata_port *ap, int force_restart)
Bastiaan Jacquesbf2af2a2006-04-17 14:17:59 +02001542{
Tejun Heo350756f2008-04-07 22:47:21 +09001543 void __iomem *port_mmio = ahci_port_base(ap);
Jeff Garzikcca39742006-08-24 03:19:22 -04001544 struct ahci_host_priv *hpriv = ap->host->private_data;
Tejun Heo520d06f2008-04-07 22:47:21 +09001545 u8 status = readl(port_mmio + PORT_TFDATA) & 0xFF;
Bastiaan Jacquesbf2af2a2006-04-17 14:17:59 +02001546 u32 tmp;
Tejun Heod2e75df2007-07-16 14:29:39 +09001547 int busy, rc;
Bastiaan Jacquesbf2af2a2006-04-17 14:17:59 +02001548
Tejun Heod2e75df2007-07-16 14:29:39 +09001549 /* do we need to kick the port? */
Tejun Heo520d06f2008-04-07 22:47:21 +09001550 busy = status & (ATA_BUSY | ATA_DRQ);
Tejun Heod2e75df2007-07-16 14:29:39 +09001551 if (!busy && !force_restart)
1552 return 0;
Bastiaan Jacquesbf2af2a2006-04-17 14:17:59 +02001553
Tejun Heod2e75df2007-07-16 14:29:39 +09001554 /* stop engine */
1555 rc = ahci_stop_engine(ap);
1556 if (rc)
1557 goto out_restart;
1558
1559 /* need to do CLO? */
1560 if (!busy) {
1561 rc = 0;
1562 goto out_restart;
1563 }
1564
1565 if (!(hpriv->cap & HOST_CAP_CLO)) {
1566 rc = -EOPNOTSUPP;
1567 goto out_restart;
1568 }
1569
1570 /* perform CLO */
Bastiaan Jacquesbf2af2a2006-04-17 14:17:59 +02001571 tmp = readl(port_mmio + PORT_CMD);
1572 tmp |= PORT_CMD_CLO;
1573 writel(tmp, port_mmio + PORT_CMD);
1574
Tejun Heod2e75df2007-07-16 14:29:39 +09001575 rc = 0;
Bastiaan Jacquesbf2af2a2006-04-17 14:17:59 +02001576 tmp = ata_wait_register(port_mmio + PORT_CMD,
1577 PORT_CMD_CLO, PORT_CMD_CLO, 1, 500);
1578 if (tmp & PORT_CMD_CLO)
Tejun Heod2e75df2007-07-16 14:29:39 +09001579 rc = -EIO;
Bastiaan Jacquesbf2af2a2006-04-17 14:17:59 +02001580
Tejun Heod2e75df2007-07-16 14:29:39 +09001581 /* restart engine */
1582 out_restart:
1583 ahci_start_engine(ap);
1584 return rc;
Bastiaan Jacquesbf2af2a2006-04-17 14:17:59 +02001585}
1586
Tejun Heo91c4a2e2007-07-16 14:29:39 +09001587static int ahci_exec_polled_cmd(struct ata_port *ap, int pmp,
1588 struct ata_taskfile *tf, int is_cmd, u16 flags,
1589 unsigned long timeout_msec)
1590{
1591 const u32 cmd_fis_len = 5; /* five dwords */
1592 struct ahci_port_priv *pp = ap->private_data;
1593 void __iomem *port_mmio = ahci_port_base(ap);
1594 u8 *fis = pp->cmd_tbl;
1595 u32 tmp;
1596
1597 /* prep the command */
1598 ata_tf_to_fis(tf, pmp, is_cmd, fis);
1599 ahci_fill_cmd_slot(pp, 0, cmd_fis_len | flags | (pmp << 12));
1600
1601 /* issue & wait */
1602 writel(1, port_mmio + PORT_CMD_ISSUE);
1603
1604 if (timeout_msec) {
1605 tmp = ata_wait_register(port_mmio + PORT_CMD_ISSUE, 0x1, 0x1,
1606 1, timeout_msec);
1607 if (tmp & 0x1) {
1608 ahci_kick_engine(ap, 1);
1609 return -EBUSY;
1610 }
1611 } else
1612 readl(port_mmio + PORT_CMD_ISSUE); /* flush */
1613
1614 return 0;
1615}
1616
Shane Huangbd172432008-06-10 15:52:04 +08001617static int ahci_do_softreset(struct ata_link *link, unsigned int *class,
1618 int pmp, unsigned long deadline,
1619 int (*check_ready)(struct ata_link *link))
Tejun Heo4658f792006-03-22 21:07:03 +09001620{
Tejun Heocc0680a2007-08-06 18:36:23 +09001621 struct ata_port *ap = link->ap;
Tejun Heo4658f792006-03-22 21:07:03 +09001622 const char *reason = NULL;
Tejun Heo2cbb79e2007-07-16 14:29:38 +09001623 unsigned long now, msecs;
Tejun Heo4658f792006-03-22 21:07:03 +09001624 struct ata_taskfile tf;
Tejun Heo4658f792006-03-22 21:07:03 +09001625 int rc;
1626
1627 DPRINTK("ENTER\n");
1628
1629 /* prepare for SRST (AHCI-1.1 10.4.1) */
Tejun Heod2e75df2007-07-16 14:29:39 +09001630 rc = ahci_kick_engine(ap, 1);
Tejun Heo994056d2007-12-06 15:02:48 +09001631 if (rc && rc != -EOPNOTSUPP)
Tejun Heocc0680a2007-08-06 18:36:23 +09001632 ata_link_printk(link, KERN_WARNING,
Tejun Heo994056d2007-12-06 15:02:48 +09001633 "failed to reset engine (errno=%d)\n", rc);
Tejun Heo4658f792006-03-22 21:07:03 +09001634
Tejun Heocc0680a2007-08-06 18:36:23 +09001635 ata_tf_init(link->device, &tf);
Tejun Heo4658f792006-03-22 21:07:03 +09001636
1637 /* issue the first D2H Register FIS */
Tejun Heo2cbb79e2007-07-16 14:29:38 +09001638 msecs = 0;
1639 now = jiffies;
1640 if (time_after(now, deadline))
1641 msecs = jiffies_to_msecs(deadline - now);
1642
Tejun Heo4658f792006-03-22 21:07:03 +09001643 tf.ctl |= ATA_SRST;
Tejun Heoa9cf5e82007-07-16 14:29:39 +09001644 if (ahci_exec_polled_cmd(ap, pmp, &tf, 0,
Tejun Heo91c4a2e2007-07-16 14:29:39 +09001645 AHCI_CMD_RESET | AHCI_CMD_CLR_BUSY, msecs)) {
Tejun Heo4658f792006-03-22 21:07:03 +09001646 rc = -EIO;
1647 reason = "1st FIS failed";
1648 goto fail;
1649 }
1650
1651 /* spec says at least 5us, but be generous and sleep for 1ms */
1652 msleep(1);
1653
1654 /* issue the second D2H Register FIS */
Tejun Heo4658f792006-03-22 21:07:03 +09001655 tf.ctl &= ~ATA_SRST;
Tejun Heoa9cf5e82007-07-16 14:29:39 +09001656 ahci_exec_polled_cmd(ap, pmp, &tf, 0, 0, 0);
Tejun Heo4658f792006-03-22 21:07:03 +09001657
Tejun Heo705e76b2008-04-07 22:47:19 +09001658 /* wait for link to become ready */
Shane Huangbd172432008-06-10 15:52:04 +08001659 rc = ata_wait_after_reset(link, deadline, check_ready);
Tejun Heo9b893912007-02-02 16:50:52 +09001660 /* link occupied, -ENODEV too is an error */
1661 if (rc) {
1662 reason = "device not ready";
1663 goto fail;
Tejun Heo4658f792006-03-22 21:07:03 +09001664 }
Tejun Heo9b893912007-02-02 16:50:52 +09001665 *class = ahci_dev_classify(ap);
Tejun Heo4658f792006-03-22 21:07:03 +09001666
1667 DPRINTK("EXIT, class=%u\n", *class);
1668 return 0;
1669
Tejun Heo4658f792006-03-22 21:07:03 +09001670 fail:
Tejun Heocc0680a2007-08-06 18:36:23 +09001671 ata_link_printk(link, KERN_ERR, "softreset failed (%s)\n", reason);
Tejun Heo4658f792006-03-22 21:07:03 +09001672 return rc;
1673}
1674
Shane Huangbd172432008-06-10 15:52:04 +08001675static int ahci_check_ready(struct ata_link *link)
1676{
1677 void __iomem *port_mmio = ahci_port_base(link->ap);
1678 u8 status = readl(port_mmio + PORT_TFDATA) & 0xFF;
1679
1680 return ata_check_ready(status);
1681}
1682
1683static int ahci_softreset(struct ata_link *link, unsigned int *class,
1684 unsigned long deadline)
1685{
1686 int pmp = sata_srst_pmp(link);
1687
1688 DPRINTK("ENTER\n");
1689
1690 return ahci_do_softreset(link, class, pmp, deadline, ahci_check_ready);
1691}
1692
1693static int ahci_sb600_check_ready(struct ata_link *link)
1694{
1695 void __iomem *port_mmio = ahci_port_base(link->ap);
1696 u8 status = readl(port_mmio + PORT_TFDATA) & 0xFF;
1697 u32 irq_status = readl(port_mmio + PORT_IRQ_STAT);
1698
1699 /*
1700 * There is no need to check TFDATA if BAD PMP is found due to HW bug,
1701 * which can save timeout delay.
1702 */
1703 if (irq_status & PORT_IRQ_BAD_PMP)
1704 return -EIO;
1705
1706 return ata_check_ready(status);
1707}
1708
1709static int ahci_sb600_softreset(struct ata_link *link, unsigned int *class,
1710 unsigned long deadline)
1711{
1712 struct ata_port *ap = link->ap;
1713 void __iomem *port_mmio = ahci_port_base(ap);
1714 int pmp = sata_srst_pmp(link);
1715 int rc;
1716 u32 irq_sts;
1717
1718 DPRINTK("ENTER\n");
1719
1720 rc = ahci_do_softreset(link, class, pmp, deadline,
1721 ahci_sb600_check_ready);
1722
1723 /*
1724 * Soft reset fails on some ATI chips with IPMS set when PMP
1725 * is enabled but SATA HDD/ODD is connected to SATA port,
1726 * do soft reset again to port 0.
1727 */
1728 if (rc == -EIO) {
1729 irq_sts = readl(port_mmio + PORT_IRQ_STAT);
1730 if (irq_sts & PORT_IRQ_BAD_PMP) {
1731 ata_link_printk(link, KERN_WARNING,
1732 "failed due to HW bug, retry pmp=0\n");
1733 rc = ahci_do_softreset(link, class, 0, deadline,
1734 ahci_check_ready);
1735 }
1736 }
1737
1738 return rc;
1739}
1740
Tejun Heocc0680a2007-08-06 18:36:23 +09001741static int ahci_hardreset(struct ata_link *link, unsigned int *class,
Tejun Heod4b2bab2007-02-02 16:50:52 +09001742 unsigned long deadline)
Tejun Heo422b7592005-12-19 22:37:17 +09001743{
Tejun Heo9dadd452008-04-07 22:47:19 +09001744 const unsigned long *timing = sata_ehc_deb_timing(&link->eh_context);
Tejun Heocc0680a2007-08-06 18:36:23 +09001745 struct ata_port *ap = link->ap;
Tejun Heo42969712006-05-31 18:28:18 +09001746 struct ahci_port_priv *pp = ap->private_data;
1747 u8 *d2h_fis = pp->rx_fis + RX_FIS_D2H_REG;
1748 struct ata_taskfile tf;
Tejun Heo9dadd452008-04-07 22:47:19 +09001749 bool online;
Tejun Heo4bd00f62006-02-11 16:26:02 +09001750 int rc;
1751
1752 DPRINTK("ENTER\n");
Linus Torvalds1da177e2005-04-16 15:20:36 -07001753
Tejun Heo4447d352007-04-17 23:44:08 +09001754 ahci_stop_engine(ap);
Tejun Heo42969712006-05-31 18:28:18 +09001755
1756 /* clear D2H reception area to properly wait for D2H FIS */
Tejun Heocc0680a2007-08-06 18:36:23 +09001757 ata_tf_init(link->device, &tf);
Tejun Heodfd7a3d2007-01-26 15:37:20 +09001758 tf.command = 0x80;
Tejun Heo99771262007-07-16 14:29:38 +09001759 ata_tf_to_fis(&tf, 0, 0, d2h_fis);
Tejun Heo42969712006-05-31 18:28:18 +09001760
Tejun Heo9dadd452008-04-07 22:47:19 +09001761 rc = sata_link_hardreset(link, timing, deadline, &online,
1762 ahci_check_ready);
Tejun Heo42969712006-05-31 18:28:18 +09001763
Tejun Heo4447d352007-04-17 23:44:08 +09001764 ahci_start_engine(ap);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001765
Tejun Heo9dadd452008-04-07 22:47:19 +09001766 if (online)
Tejun Heo4bd00f62006-02-11 16:26:02 +09001767 *class = ahci_dev_classify(ap);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001768
Tejun Heo4bd00f62006-02-11 16:26:02 +09001769 DPRINTK("EXIT, rc=%d, class=%u\n", rc, *class);
1770 return rc;
1771}
1772
Tejun Heocc0680a2007-08-06 18:36:23 +09001773static int ahci_vt8251_hardreset(struct ata_link *link, unsigned int *class,
Tejun Heod4b2bab2007-02-02 16:50:52 +09001774 unsigned long deadline)
Tejun Heoad616ff2006-11-01 18:00:24 +09001775{
Tejun Heocc0680a2007-08-06 18:36:23 +09001776 struct ata_port *ap = link->ap;
Tejun Heo9dadd452008-04-07 22:47:19 +09001777 bool online;
Tejun Heoad616ff2006-11-01 18:00:24 +09001778 int rc;
1779
1780 DPRINTK("ENTER\n");
1781
Tejun Heo4447d352007-04-17 23:44:08 +09001782 ahci_stop_engine(ap);
Tejun Heoad616ff2006-11-01 18:00:24 +09001783
Tejun Heocc0680a2007-08-06 18:36:23 +09001784 rc = sata_link_hardreset(link, sata_ehc_deb_timing(&link->eh_context),
Tejun Heo9dadd452008-04-07 22:47:19 +09001785 deadline, &online, NULL);
Tejun Heoad616ff2006-11-01 18:00:24 +09001786
Tejun Heo4447d352007-04-17 23:44:08 +09001787 ahci_start_engine(ap);
Tejun Heoad616ff2006-11-01 18:00:24 +09001788
1789 DPRINTK("EXIT, rc=%d, class=%u\n", rc, *class);
1790
1791 /* vt8251 doesn't clear BSY on signature FIS reception,
1792 * request follow-up softreset.
1793 */
Tejun Heo9dadd452008-04-07 22:47:19 +09001794 return online ? -EAGAIN : rc;
Tejun Heoad616ff2006-11-01 18:00:24 +09001795}
1796
Tejun Heoedc93052007-10-25 14:59:16 +09001797static int ahci_p5wdh_hardreset(struct ata_link *link, unsigned int *class,
1798 unsigned long deadline)
1799{
1800 struct ata_port *ap = link->ap;
1801 struct ahci_port_priv *pp = ap->private_data;
1802 u8 *d2h_fis = pp->rx_fis + RX_FIS_D2H_REG;
1803 struct ata_taskfile tf;
Tejun Heo9dadd452008-04-07 22:47:19 +09001804 bool online;
Tejun Heoedc93052007-10-25 14:59:16 +09001805 int rc;
1806
1807 ahci_stop_engine(ap);
1808
1809 /* clear D2H reception area to properly wait for D2H FIS */
1810 ata_tf_init(link->device, &tf);
1811 tf.command = 0x80;
1812 ata_tf_to_fis(&tf, 0, 0, d2h_fis);
1813
1814 rc = sata_link_hardreset(link, sata_ehc_deb_timing(&link->eh_context),
Tejun Heo9dadd452008-04-07 22:47:19 +09001815 deadline, &online, NULL);
Tejun Heoedc93052007-10-25 14:59:16 +09001816
1817 ahci_start_engine(ap);
1818
Tejun Heoedc93052007-10-25 14:59:16 +09001819 /* The pseudo configuration device on SIMG4726 attached to
1820 * ASUS P5W-DH Deluxe doesn't send signature FIS after
1821 * hardreset if no device is attached to the first downstream
1822 * port && the pseudo device locks up on SRST w/ PMP==0. To
1823 * work around this, wait for !BSY only briefly. If BSY isn't
1824 * cleared, perform CLO and proceed to IDENTIFY (achieved by
1825 * ATA_LFLAG_NO_SRST and ATA_LFLAG_ASSUME_ATA).
1826 *
1827 * Wait for two seconds. Devices attached to downstream port
1828 * which can't process the following IDENTIFY after this will
1829 * have to be reset again. For most cases, this should
1830 * suffice while making probing snappish enough.
1831 */
Tejun Heo9dadd452008-04-07 22:47:19 +09001832 if (online) {
1833 rc = ata_wait_after_reset(link, jiffies + 2 * HZ,
1834 ahci_check_ready);
1835 if (rc)
1836 ahci_kick_engine(ap, 0);
1837 }
Tejun Heo9dadd452008-04-07 22:47:19 +09001838 return rc;
Tejun Heoedc93052007-10-25 14:59:16 +09001839}
1840
Tejun Heocc0680a2007-08-06 18:36:23 +09001841static void ahci_postreset(struct ata_link *link, unsigned int *class)
Tejun Heo4bd00f62006-02-11 16:26:02 +09001842{
Tejun Heocc0680a2007-08-06 18:36:23 +09001843 struct ata_port *ap = link->ap;
Tejun Heo4447d352007-04-17 23:44:08 +09001844 void __iomem *port_mmio = ahci_port_base(ap);
Tejun Heo4bd00f62006-02-11 16:26:02 +09001845 u32 new_tmp, tmp;
1846
Tejun Heo203c75b2008-04-07 22:47:18 +09001847 ata_std_postreset(link, class);
Jeff Garzik02eaa662005-11-12 01:32:19 -05001848
1849 /* Make sure port's ATAPI bit is set appropriately */
1850 new_tmp = tmp = readl(port_mmio + PORT_CMD);
Tejun Heo4bd00f62006-02-11 16:26:02 +09001851 if (*class == ATA_DEV_ATAPI)
Jeff Garzik02eaa662005-11-12 01:32:19 -05001852 new_tmp |= PORT_CMD_ATAPI;
1853 else
1854 new_tmp &= ~PORT_CMD_ATAPI;
1855 if (new_tmp != tmp) {
1856 writel(new_tmp, port_mmio + PORT_CMD);
1857 readl(port_mmio + PORT_CMD); /* flush */
1858 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07001859}
1860
Tejun Heo12fad3f2006-05-15 21:03:55 +09001861static unsigned int ahci_fill_sg(struct ata_queued_cmd *qc, void *cmd_tbl)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001862{
Jeff Garzikcedc9a42005-10-05 07:13:30 -04001863 struct scatterlist *sg;
Tejun Heoff2aeb12007-12-05 16:43:11 +09001864 struct ahci_sg *ahci_sg = cmd_tbl + AHCI_CMD_TBL_HDR_SZ;
1865 unsigned int si;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001866
1867 VPRINTK("ENTER\n");
1868
1869 /*
1870 * Next, the S/G list.
1871 */
Tejun Heoff2aeb12007-12-05 16:43:11 +09001872 for_each_sg(qc->sg, sg, qc->n_elem, si) {
Jeff Garzikcedc9a42005-10-05 07:13:30 -04001873 dma_addr_t addr = sg_dma_address(sg);
1874 u32 sg_len = sg_dma_len(sg);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001875
Tejun Heoff2aeb12007-12-05 16:43:11 +09001876 ahci_sg[si].addr = cpu_to_le32(addr & 0xffffffff);
1877 ahci_sg[si].addr_hi = cpu_to_le32((addr >> 16) >> 16);
1878 ahci_sg[si].flags_size = cpu_to_le32(sg_len - 1);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001879 }
Jeff Garzik828d09d2005-11-12 01:27:07 -05001880
Tejun Heoff2aeb12007-12-05 16:43:11 +09001881 return si;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001882}
1883
1884static void ahci_qc_prep(struct ata_queued_cmd *qc)
1885{
Jeff Garzika0ea7322005-06-04 01:13:15 -04001886 struct ata_port *ap = qc->ap;
1887 struct ahci_port_priv *pp = ap->private_data;
Tejun Heo405e66b2007-11-27 19:28:53 +09001888 int is_atapi = ata_is_atapi(qc->tf.protocol);
Tejun Heo12fad3f2006-05-15 21:03:55 +09001889 void *cmd_tbl;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001890 u32 opts;
1891 const u32 cmd_fis_len = 5; /* five dwords */
Jeff Garzik828d09d2005-11-12 01:27:07 -05001892 unsigned int n_elem;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001893
1894 /*
Linus Torvalds1da177e2005-04-16 15:20:36 -07001895 * Fill in command table information. First, the header,
1896 * a SATA Register - Host to Device command FIS.
1897 */
Tejun Heo12fad3f2006-05-15 21:03:55 +09001898 cmd_tbl = pp->cmd_tbl + qc->tag * AHCI_CMD_TBL_SZ;
1899
Tejun Heo7d50b602007-09-23 13:19:54 +09001900 ata_tf_to_fis(&qc->tf, qc->dev->link->pmp, 1, cmd_tbl);
Tejun Heocc9278e2006-02-10 17:25:47 +09001901 if (is_atapi) {
Tejun Heo12fad3f2006-05-15 21:03:55 +09001902 memset(cmd_tbl + AHCI_CMD_TBL_CDB, 0, 32);
1903 memcpy(cmd_tbl + AHCI_CMD_TBL_CDB, qc->cdb, qc->dev->cdb_len);
Jeff Garzika0ea7322005-06-04 01:13:15 -04001904 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07001905
Tejun Heocc9278e2006-02-10 17:25:47 +09001906 n_elem = 0;
1907 if (qc->flags & ATA_QCFLAG_DMAMAP)
Tejun Heo12fad3f2006-05-15 21:03:55 +09001908 n_elem = ahci_fill_sg(qc, cmd_tbl);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001909
Tejun Heocc9278e2006-02-10 17:25:47 +09001910 /*
1911 * Fill in command slot information.
1912 */
Tejun Heo7d50b602007-09-23 13:19:54 +09001913 opts = cmd_fis_len | n_elem << 16 | (qc->dev->link->pmp << 12);
Tejun Heocc9278e2006-02-10 17:25:47 +09001914 if (qc->tf.flags & ATA_TFLAG_WRITE)
1915 opts |= AHCI_CMD_WRITE;
1916 if (is_atapi)
Tejun Heo4b10e552006-03-12 11:25:27 +09001917 opts |= AHCI_CMD_ATAPI | AHCI_CMD_PREFETCH;
Jeff Garzik828d09d2005-11-12 01:27:07 -05001918
Tejun Heo12fad3f2006-05-15 21:03:55 +09001919 ahci_fill_cmd_slot(pp, qc->tag, opts);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001920}
1921
Tejun Heo78cd52d2006-05-15 20:58:29 +09001922static void ahci_error_intr(struct ata_port *ap, u32 irq_stat)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001923{
Tejun Heo417a1a62007-09-23 13:19:55 +09001924 struct ahci_host_priv *hpriv = ap->host->private_data;
Tejun Heo78cd52d2006-05-15 20:58:29 +09001925 struct ahci_port_priv *pp = ap->private_data;
Tejun Heo7d50b602007-09-23 13:19:54 +09001926 struct ata_eh_info *host_ehi = &ap->link.eh_info;
1927 struct ata_link *link = NULL;
1928 struct ata_queued_cmd *active_qc;
1929 struct ata_eh_info *active_ehi;
Tejun Heo78cd52d2006-05-15 20:58:29 +09001930 u32 serror;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001931
Tejun Heo7d50b602007-09-23 13:19:54 +09001932 /* determine active link */
1933 ata_port_for_each_link(link, ap)
1934 if (ata_link_active(link))
1935 break;
1936 if (!link)
1937 link = &ap->link;
1938
1939 active_qc = ata_qc_from_tag(ap, link->active_tag);
1940 active_ehi = &link->eh_info;
1941
1942 /* record irq stat */
1943 ata_ehi_clear_desc(host_ehi);
1944 ata_ehi_push_desc(host_ehi, "irq_stat 0x%08x", irq_stat);
Jeff Garzik9f68a242005-11-15 14:03:47 -05001945
Tejun Heo78cd52d2006-05-15 20:58:29 +09001946 /* AHCI needs SError cleared; otherwise, it might lock up */
Tejun Heo82ef04f2008-07-31 17:02:40 +09001947 ahci_scr_read(&ap->link, SCR_ERROR, &serror);
1948 ahci_scr_write(&ap->link, SCR_ERROR, serror);
Tejun Heo7d50b602007-09-23 13:19:54 +09001949 host_ehi->serror |= serror;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001950
Tejun Heo41669552006-11-29 11:33:14 +09001951 /* some controllers set IRQ_IF_ERR on device errors, ignore it */
Tejun Heo417a1a62007-09-23 13:19:55 +09001952 if (hpriv->flags & AHCI_HFLAG_IGN_IRQ_IF_ERR)
Tejun Heo41669552006-11-29 11:33:14 +09001953 irq_stat &= ~PORT_IRQ_IF_ERR;
1954
Conke Hu55a61602007-03-27 18:33:05 +08001955 if (irq_stat & PORT_IRQ_TF_ERR) {
Tejun Heo7d50b602007-09-23 13:19:54 +09001956 /* If qc is active, charge it; otherwise, the active
1957 * link. There's no active qc on NCQ errors. It will
1958 * be determined by EH by reading log page 10h.
1959 */
1960 if (active_qc)
1961 active_qc->err_mask |= AC_ERR_DEV;
1962 else
1963 active_ehi->err_mask |= AC_ERR_DEV;
1964
Tejun Heo417a1a62007-09-23 13:19:55 +09001965 if (hpriv->flags & AHCI_HFLAG_IGN_SERR_INTERNAL)
Tejun Heo7d50b602007-09-23 13:19:54 +09001966 host_ehi->serror &= ~SERR_INTERNAL;
Tejun Heo78cd52d2006-05-15 20:58:29 +09001967 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07001968
Tejun Heo78cd52d2006-05-15 20:58:29 +09001969 if (irq_stat & PORT_IRQ_UNK_FIS) {
1970 u32 *unk = (u32 *)(pp->rx_fis + RX_FIS_UNK);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001971
Tejun Heo7d50b602007-09-23 13:19:54 +09001972 active_ehi->err_mask |= AC_ERR_HSM;
Tejun Heocf480622008-01-24 00:05:14 +09001973 active_ehi->action |= ATA_EH_RESET;
Tejun Heo7d50b602007-09-23 13:19:54 +09001974 ata_ehi_push_desc(active_ehi,
1975 "unknown FIS %08x %08x %08x %08x" ,
Tejun Heo78cd52d2006-05-15 20:58:29 +09001976 unk[0], unk[1], unk[2], unk[3]);
1977 }
Jeff Garzikb8f61532005-08-25 22:01:20 -04001978
Tejun Heo071f44b2008-04-07 22:47:22 +09001979 if (sata_pmp_attached(ap) && (irq_stat & PORT_IRQ_BAD_PMP)) {
Tejun Heo7d50b602007-09-23 13:19:54 +09001980 active_ehi->err_mask |= AC_ERR_HSM;
Tejun Heocf480622008-01-24 00:05:14 +09001981 active_ehi->action |= ATA_EH_RESET;
Tejun Heo7d50b602007-09-23 13:19:54 +09001982 ata_ehi_push_desc(active_ehi, "incorrect PMP");
1983 }
Tejun Heo78cd52d2006-05-15 20:58:29 +09001984
Tejun Heo7d50b602007-09-23 13:19:54 +09001985 if (irq_stat & (PORT_IRQ_HBUS_ERR | PORT_IRQ_HBUS_DATA_ERR)) {
1986 host_ehi->err_mask |= AC_ERR_HOST_BUS;
Tejun Heocf480622008-01-24 00:05:14 +09001987 host_ehi->action |= ATA_EH_RESET;
Tejun Heo7d50b602007-09-23 13:19:54 +09001988 ata_ehi_push_desc(host_ehi, "host bus error");
1989 }
1990
1991 if (irq_stat & PORT_IRQ_IF_ERR) {
1992 host_ehi->err_mask |= AC_ERR_ATA_BUS;
Tejun Heocf480622008-01-24 00:05:14 +09001993 host_ehi->action |= ATA_EH_RESET;
Tejun Heo7d50b602007-09-23 13:19:54 +09001994 ata_ehi_push_desc(host_ehi, "interface fatal error");
1995 }
1996
1997 if (irq_stat & (PORT_IRQ_CONNECT | PORT_IRQ_PHYRDY)) {
1998 ata_ehi_hotplugged(host_ehi);
1999 ata_ehi_push_desc(host_ehi, "%s",
2000 irq_stat & PORT_IRQ_CONNECT ?
2001 "connection status changed" : "PHY RDY changed");
2002 }
2003
2004 /* okay, let's hand over to EH */
Linus Torvalds1da177e2005-04-16 15:20:36 -07002005
Tejun Heo78cd52d2006-05-15 20:58:29 +09002006 if (irq_stat & PORT_IRQ_FREEZE)
2007 ata_port_freeze(ap);
2008 else
2009 ata_port_abort(ap);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002010}
2011
Jeff Garzikdf69c9c2007-05-26 20:46:51 -04002012static void ahci_port_intr(struct ata_port *ap)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002013{
Tejun Heo350756f2008-04-07 22:47:21 +09002014 void __iomem *port_mmio = ahci_port_base(ap);
Tejun Heo9af5c9c2007-08-06 18:36:22 +09002015 struct ata_eh_info *ehi = &ap->link.eh_info;
Tejun Heo0291f952007-01-25 19:16:28 +09002016 struct ahci_port_priv *pp = ap->private_data;
Tejun Heo5f226c62007-10-09 15:02:23 +09002017 struct ahci_host_priv *hpriv = ap->host->private_data;
Tejun Heob06ce3e2007-10-09 15:06:48 +09002018 int resetting = !!(ap->pflags & ATA_PFLAG_RESETTING);
Tejun Heo12fad3f2006-05-15 21:03:55 +09002019 u32 status, qc_active;
Tejun Heo459ad682007-12-07 12:46:23 +09002020 int rc;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002021
2022 status = readl(port_mmio + PORT_IRQ_STAT);
2023 writel(status, port_mmio + PORT_IRQ_STAT);
2024
Tejun Heob06ce3e2007-10-09 15:06:48 +09002025 /* ignore BAD_PMP while resetting */
2026 if (unlikely(resetting))
2027 status &= ~PORT_IRQ_BAD_PMP;
2028
Kristen Carlson Accardi31556592007-10-25 01:33:26 -04002029 /* If we are getting PhyRdy, this is
2030 * just a power state change, we should
2031 * clear out this, plus the PhyRdy/Comm
2032 * Wake bits from Serror
2033 */
2034 if ((hpriv->flags & AHCI_HFLAG_NO_HOTPLUG) &&
2035 (status & PORT_IRQ_PHYRDY)) {
2036 status &= ~PORT_IRQ_PHYRDY;
Tejun Heo82ef04f2008-07-31 17:02:40 +09002037 ahci_scr_write(&ap->link, SCR_ERROR, ((1 << 16) | (1 << 18)));
Kristen Carlson Accardi31556592007-10-25 01:33:26 -04002038 }
2039
Tejun Heo78cd52d2006-05-15 20:58:29 +09002040 if (unlikely(status & PORT_IRQ_ERROR)) {
2041 ahci_error_intr(ap, status);
2042 return;
2043 }
2044
Kristen Carlson Accardi2f294962007-08-15 04:11:25 -04002045 if (status & PORT_IRQ_SDB_FIS) {
Tejun Heo5f226c62007-10-09 15:02:23 +09002046 /* If SNotification is available, leave notification
2047 * handling to sata_async_notification(). If not,
2048 * emulate it by snooping SDB FIS RX area.
2049 *
2050 * Snooping FIS RX area is probably cheaper than
2051 * poking SNotification but some constrollers which
2052 * implement SNotification, ICH9 for example, don't
2053 * store AN SDB FIS into receive area.
Kristen Carlson Accardi2f294962007-08-15 04:11:25 -04002054 */
Tejun Heo5f226c62007-10-09 15:02:23 +09002055 if (hpriv->cap & HOST_CAP_SNTF)
Tejun Heo7d77b242007-09-23 13:14:13 +09002056 sata_async_notification(ap);
Tejun Heo5f226c62007-10-09 15:02:23 +09002057 else {
2058 /* If the 'N' bit in word 0 of the FIS is set,
2059 * we just received asynchronous notification.
2060 * Tell libata about it.
2061 */
2062 const __le32 *f = pp->rx_fis + RX_FIS_SDB;
2063 u32 f0 = le32_to_cpu(f[0]);
2064
2065 if (f0 & (1 << 15))
2066 sata_async_notification(ap);
2067 }
Kristen Carlson Accardi2f294962007-08-15 04:11:25 -04002068 }
2069
Tejun Heo7d50b602007-09-23 13:19:54 +09002070 /* pp->active_link is valid iff any command is in flight */
2071 if (ap->qc_active && pp->active_link->sactive)
Tejun Heo12fad3f2006-05-15 21:03:55 +09002072 qc_active = readl(port_mmio + PORT_SCR_ACT);
2073 else
2074 qc_active = readl(port_mmio + PORT_CMD_ISSUE);
2075
Tejun Heo79f97da2008-04-07 22:47:20 +09002076 rc = ata_qc_complete_multiple(ap, qc_active);
Tejun Heob06ce3e2007-10-09 15:06:48 +09002077
Tejun Heo459ad682007-12-07 12:46:23 +09002078 /* while resetting, invalid completions are expected */
2079 if (unlikely(rc < 0 && !resetting)) {
Tejun Heo12fad3f2006-05-15 21:03:55 +09002080 ehi->err_mask |= AC_ERR_HSM;
Tejun Heocf480622008-01-24 00:05:14 +09002081 ehi->action |= ATA_EH_RESET;
Tejun Heo12fad3f2006-05-15 21:03:55 +09002082 ata_port_freeze(ap);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002083 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07002084}
2085
David Howells7d12e782006-10-05 14:55:46 +01002086static irqreturn_t ahci_interrupt(int irq, void *dev_instance)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002087{
Jeff Garzikcca39742006-08-24 03:19:22 -04002088 struct ata_host *host = dev_instance;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002089 struct ahci_host_priv *hpriv;
2090 unsigned int i, handled = 0;
Jeff Garzikea6ba102005-08-30 05:18:18 -04002091 void __iomem *mmio;
Tejun Heod28f87a2008-07-05 13:10:50 +09002092 u32 irq_stat, irq_masked;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002093
2094 VPRINTK("ENTER\n");
2095
Jeff Garzikcca39742006-08-24 03:19:22 -04002096 hpriv = host->private_data;
Tejun Heo0d5ff562007-02-01 15:06:36 +09002097 mmio = host->iomap[AHCI_PCI_BAR];
Linus Torvalds1da177e2005-04-16 15:20:36 -07002098
2099 /* sigh. 0xffffffff is a valid return from h/w */
2100 irq_stat = readl(mmio + HOST_IRQ_STAT);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002101 if (!irq_stat)
2102 return IRQ_NONE;
2103
Tejun Heod28f87a2008-07-05 13:10:50 +09002104 irq_masked = irq_stat & hpriv->port_map;
2105
Jeff Garzik2dcb4072007-10-19 06:42:56 -04002106 spin_lock(&host->lock);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002107
Jeff Garzik2dcb4072007-10-19 06:42:56 -04002108 for (i = 0; i < host->n_ports; i++) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07002109 struct ata_port *ap;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002110
Tejun Heod28f87a2008-07-05 13:10:50 +09002111 if (!(irq_masked & (1 << i)))
Jeff Garzik67846b32005-10-05 02:58:32 -04002112 continue;
2113
Jeff Garzikcca39742006-08-24 03:19:22 -04002114 ap = host->ports[i];
Jeff Garzik67846b32005-10-05 02:58:32 -04002115 if (ap) {
Jeff Garzikdf69c9c2007-05-26 20:46:51 -04002116 ahci_port_intr(ap);
Jeff Garzik67846b32005-10-05 02:58:32 -04002117 VPRINTK("port %u\n", i);
2118 } else {
2119 VPRINTK("port %u (no irq)\n", i);
Tejun Heo6971ed12006-03-11 12:47:54 +09002120 if (ata_ratelimit())
Jeff Garzikcca39742006-08-24 03:19:22 -04002121 dev_printk(KERN_WARNING, host->dev,
Jeff Garzika9524a72005-10-30 14:39:11 -05002122 "interrupt on disabled port %u\n", i);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002123 }
Jeff Garzik67846b32005-10-05 02:58:32 -04002124
Linus Torvalds1da177e2005-04-16 15:20:36 -07002125 handled = 1;
2126 }
2127
Tejun Heod28f87a2008-07-05 13:10:50 +09002128 /* HOST_IRQ_STAT behaves as level triggered latch meaning that
2129 * it should be cleared after all the port events are cleared;
2130 * otherwise, it will raise a spurious interrupt after each
2131 * valid one. Please read section 10.6.2 of ahci 1.1 for more
2132 * information.
2133 *
2134 * Also, use the unmasked value to clear interrupt as spurious
2135 * pending event on a dummy port might cause screaming IRQ.
2136 */
Tejun Heoea0c62f2008-06-28 01:49:02 +09002137 writel(irq_stat, mmio + HOST_IRQ_STAT);
2138
Jeff Garzikcca39742006-08-24 03:19:22 -04002139 spin_unlock(&host->lock);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002140
2141 VPRINTK("EXIT\n");
2142
2143 return IRQ_RETVAL(handled);
2144}
2145
Tejun Heo9a3d9eb2006-01-23 13:09:36 +09002146static unsigned int ahci_qc_issue(struct ata_queued_cmd *qc)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002147{
2148 struct ata_port *ap = qc->ap;
Tejun Heo4447d352007-04-17 23:44:08 +09002149 void __iomem *port_mmio = ahci_port_base(ap);
Tejun Heo7d50b602007-09-23 13:19:54 +09002150 struct ahci_port_priv *pp = ap->private_data;
2151
2152 /* Keep track of the currently active link. It will be used
2153 * in completion path to determine whether NCQ phase is in
2154 * progress.
2155 */
2156 pp->active_link = qc->dev->link;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002157
Tejun Heo12fad3f2006-05-15 21:03:55 +09002158 if (qc->tf.protocol == ATA_PROT_NCQ)
2159 writel(1 << qc->tag, port_mmio + PORT_SCR_ACT);
2160 writel(1 << qc->tag, port_mmio + PORT_CMD_ISSUE);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002161
Kristen Carlson Accardi18f7ba42008-06-03 10:33:55 -07002162 ahci_sw_activity(qc->dev->link);
2163
Linus Torvalds1da177e2005-04-16 15:20:36 -07002164 return 0;
2165}
2166
Tejun Heo4c9bf4e2008-04-07 22:47:20 +09002167static bool ahci_qc_fill_rtf(struct ata_queued_cmd *qc)
2168{
2169 struct ahci_port_priv *pp = qc->ap->private_data;
2170 u8 *d2h_fis = pp->rx_fis + RX_FIS_D2H_REG;
2171
2172 ata_tf_from_fis(d2h_fis, &qc->result_tf);
2173 return true;
2174}
2175
Tejun Heo78cd52d2006-05-15 20:58:29 +09002176static void ahci_freeze(struct ata_port *ap)
2177{
Tejun Heo4447d352007-04-17 23:44:08 +09002178 void __iomem *port_mmio = ahci_port_base(ap);
Tejun Heo78cd52d2006-05-15 20:58:29 +09002179
2180 /* turn IRQ off */
2181 writel(0, port_mmio + PORT_IRQ_MASK);
2182}
2183
2184static void ahci_thaw(struct ata_port *ap)
2185{
Tejun Heo0d5ff562007-02-01 15:06:36 +09002186 void __iomem *mmio = ap->host->iomap[AHCI_PCI_BAR];
Tejun Heo4447d352007-04-17 23:44:08 +09002187 void __iomem *port_mmio = ahci_port_base(ap);
Tejun Heo78cd52d2006-05-15 20:58:29 +09002188 u32 tmp;
Kristen Carlson Accardia7384922007-08-09 14:23:41 -07002189 struct ahci_port_priv *pp = ap->private_data;
Tejun Heo78cd52d2006-05-15 20:58:29 +09002190
2191 /* clear IRQ */
2192 tmp = readl(port_mmio + PORT_IRQ_STAT);
2193 writel(tmp, port_mmio + PORT_IRQ_STAT);
Tejun Heoa7187282007-01-27 11:04:26 +09002194 writel(1 << ap->port_no, mmio + HOST_IRQ_STAT);
Tejun Heo78cd52d2006-05-15 20:58:29 +09002195
Tejun Heo1c954a42007-10-09 15:01:37 +09002196 /* turn IRQ back on */
2197 writel(pp->intr_mask, port_mmio + PORT_IRQ_MASK);
Tejun Heo78cd52d2006-05-15 20:58:29 +09002198}
2199
2200static void ahci_error_handler(struct ata_port *ap)
2201{
Tejun Heob51e9e52006-06-29 01:29:30 +09002202 if (!(ap->pflags & ATA_PFLAG_FROZEN)) {
Tejun Heo78cd52d2006-05-15 20:58:29 +09002203 /* restart engine */
Tejun Heo4447d352007-04-17 23:44:08 +09002204 ahci_stop_engine(ap);
2205 ahci_start_engine(ap);
Tejun Heo78cd52d2006-05-15 20:58:29 +09002206 }
2207
Tejun Heoa1efdab2008-03-25 12:22:50 +09002208 sata_pmp_error_handler(ap);
Tejun Heoedc93052007-10-25 14:59:16 +09002209}
2210
Tejun Heo78cd52d2006-05-15 20:58:29 +09002211static void ahci_post_internal_cmd(struct ata_queued_cmd *qc)
2212{
2213 struct ata_port *ap = qc->ap;
2214
Tejun Heod2e75df2007-07-16 14:29:39 +09002215 /* make DMA engine forget about the failed command */
2216 if (qc->flags & ATA_QCFLAG_FAILED)
2217 ahci_kick_engine(ap, 1);
Tejun Heo78cd52d2006-05-15 20:58:29 +09002218}
2219
Tejun Heo7d50b602007-09-23 13:19:54 +09002220static void ahci_pmp_attach(struct ata_port *ap)
2221{
2222 void __iomem *port_mmio = ahci_port_base(ap);
Tejun Heo1c954a42007-10-09 15:01:37 +09002223 struct ahci_port_priv *pp = ap->private_data;
Tejun Heo7d50b602007-09-23 13:19:54 +09002224 u32 cmd;
2225
2226 cmd = readl(port_mmio + PORT_CMD);
2227 cmd |= PORT_CMD_PMP;
2228 writel(cmd, port_mmio + PORT_CMD);
Tejun Heo1c954a42007-10-09 15:01:37 +09002229
2230 pp->intr_mask |= PORT_IRQ_BAD_PMP;
2231 writel(pp->intr_mask, port_mmio + PORT_IRQ_MASK);
Tejun Heo7d50b602007-09-23 13:19:54 +09002232}
2233
2234static void ahci_pmp_detach(struct ata_port *ap)
2235{
2236 void __iomem *port_mmio = ahci_port_base(ap);
Tejun Heo1c954a42007-10-09 15:01:37 +09002237 struct ahci_port_priv *pp = ap->private_data;
Tejun Heo7d50b602007-09-23 13:19:54 +09002238 u32 cmd;
2239
2240 cmd = readl(port_mmio + PORT_CMD);
2241 cmd &= ~PORT_CMD_PMP;
2242 writel(cmd, port_mmio + PORT_CMD);
Tejun Heo1c954a42007-10-09 15:01:37 +09002243
2244 pp->intr_mask &= ~PORT_IRQ_BAD_PMP;
2245 writel(pp->intr_mask, port_mmio + PORT_IRQ_MASK);
Tejun Heo7d50b602007-09-23 13:19:54 +09002246}
2247
Alexey Dobriyan028a2592007-07-17 23:48:48 +04002248static int ahci_port_resume(struct ata_port *ap)
2249{
2250 ahci_power_up(ap);
2251 ahci_start_port(ap);
2252
Tejun Heo071f44b2008-04-07 22:47:22 +09002253 if (sata_pmp_attached(ap))
Tejun Heo7d50b602007-09-23 13:19:54 +09002254 ahci_pmp_attach(ap);
2255 else
2256 ahci_pmp_detach(ap);
2257
Alexey Dobriyan028a2592007-07-17 23:48:48 +04002258 return 0;
2259}
2260
Tejun Heo438ac6d2007-03-02 17:31:26 +09002261#ifdef CONFIG_PM
Tejun Heoc1332872006-07-26 15:59:26 +09002262static int ahci_port_suspend(struct ata_port *ap, pm_message_t mesg)
2263{
Tejun Heoc1332872006-07-26 15:59:26 +09002264 const char *emsg = NULL;
2265 int rc;
2266
Tejun Heo4447d352007-04-17 23:44:08 +09002267 rc = ahci_deinit_port(ap, &emsg);
Tejun Heo8e16f942006-11-20 15:42:36 +09002268 if (rc == 0)
Tejun Heo4447d352007-04-17 23:44:08 +09002269 ahci_power_down(ap);
Tejun Heo8e16f942006-11-20 15:42:36 +09002270 else {
Tejun Heoc1332872006-07-26 15:59:26 +09002271 ata_port_printk(ap, KERN_ERR, "%s (%d)\n", emsg, rc);
Jeff Garzikdf69c9c2007-05-26 20:46:51 -04002272 ahci_start_port(ap);
Tejun Heoc1332872006-07-26 15:59:26 +09002273 }
2274
2275 return rc;
2276}
2277
Tejun Heoc1332872006-07-26 15:59:26 +09002278static int ahci_pci_device_suspend(struct pci_dev *pdev, pm_message_t mesg)
2279{
Jeff Garzikcca39742006-08-24 03:19:22 -04002280 struct ata_host *host = dev_get_drvdata(&pdev->dev);
Tejun Heo0d5ff562007-02-01 15:06:36 +09002281 void __iomem *mmio = host->iomap[AHCI_PCI_BAR];
Tejun Heoc1332872006-07-26 15:59:26 +09002282 u32 ctl;
2283
Rafael J. Wysocki3a2d5b72008-02-23 19:13:25 +01002284 if (mesg.event & PM_EVENT_SLEEP) {
Tejun Heoc1332872006-07-26 15:59:26 +09002285 /* AHCI spec rev1.1 section 8.3.3:
2286 * Software must disable interrupts prior to requesting a
2287 * transition of the HBA to D3 state.
2288 */
2289 ctl = readl(mmio + HOST_CTL);
2290 ctl &= ~HOST_IRQ_EN;
2291 writel(ctl, mmio + HOST_CTL);
2292 readl(mmio + HOST_CTL); /* flush */
2293 }
2294
2295 return ata_pci_device_suspend(pdev, mesg);
2296}
2297
2298static int ahci_pci_device_resume(struct pci_dev *pdev)
2299{
Jeff Garzikcca39742006-08-24 03:19:22 -04002300 struct ata_host *host = dev_get_drvdata(&pdev->dev);
Tejun Heoc1332872006-07-26 15:59:26 +09002301 int rc;
2302
Tejun Heo553c4aa2006-12-26 19:39:50 +09002303 rc = ata_pci_device_do_resume(pdev);
2304 if (rc)
2305 return rc;
Tejun Heoc1332872006-07-26 15:59:26 +09002306
2307 if (pdev->dev.power.power_state.event == PM_EVENT_SUSPEND) {
Tejun Heo4447d352007-04-17 23:44:08 +09002308 rc = ahci_reset_controller(host);
Tejun Heoc1332872006-07-26 15:59:26 +09002309 if (rc)
2310 return rc;
2311
Tejun Heo4447d352007-04-17 23:44:08 +09002312 ahci_init_controller(host);
Tejun Heoc1332872006-07-26 15:59:26 +09002313 }
2314
Jeff Garzikcca39742006-08-24 03:19:22 -04002315 ata_host_resume(host);
Tejun Heoc1332872006-07-26 15:59:26 +09002316
2317 return 0;
2318}
Tejun Heo438ac6d2007-03-02 17:31:26 +09002319#endif
Tejun Heoc1332872006-07-26 15:59:26 +09002320
Tejun Heo254950c2006-07-26 15:59:25 +09002321static int ahci_port_start(struct ata_port *ap)
2322{
Jeff Garzikcca39742006-08-24 03:19:22 -04002323 struct device *dev = ap->host->dev;
Tejun Heo254950c2006-07-26 15:59:25 +09002324 struct ahci_port_priv *pp;
Tejun Heo254950c2006-07-26 15:59:25 +09002325 void *mem;
2326 dma_addr_t mem_dma;
Tejun Heo254950c2006-07-26 15:59:25 +09002327
Tejun Heo24dc5f32007-01-20 16:00:28 +09002328 pp = devm_kzalloc(dev, sizeof(*pp), GFP_KERNEL);
Tejun Heo254950c2006-07-26 15:59:25 +09002329 if (!pp)
2330 return -ENOMEM;
Tejun Heo254950c2006-07-26 15:59:25 +09002331
Tejun Heo24dc5f32007-01-20 16:00:28 +09002332 mem = dmam_alloc_coherent(dev, AHCI_PORT_PRIV_DMA_SZ, &mem_dma,
2333 GFP_KERNEL);
2334 if (!mem)
Tejun Heo254950c2006-07-26 15:59:25 +09002335 return -ENOMEM;
Tejun Heo254950c2006-07-26 15:59:25 +09002336 memset(mem, 0, AHCI_PORT_PRIV_DMA_SZ);
2337
2338 /*
2339 * First item in chunk of DMA memory: 32-slot command table,
2340 * 32 bytes each in size
2341 */
2342 pp->cmd_slot = mem;
2343 pp->cmd_slot_dma = mem_dma;
2344
2345 mem += AHCI_CMD_SLOT_SZ;
2346 mem_dma += AHCI_CMD_SLOT_SZ;
2347
2348 /*
2349 * Second item: Received-FIS area
2350 */
2351 pp->rx_fis = mem;
2352 pp->rx_fis_dma = mem_dma;
2353
2354 mem += AHCI_RX_FIS_SZ;
2355 mem_dma += AHCI_RX_FIS_SZ;
2356
2357 /*
2358 * Third item: data area for storing a single command
2359 * and its scatter-gather table
2360 */
2361 pp->cmd_tbl = mem;
2362 pp->cmd_tbl_dma = mem_dma;
2363
Kristen Carlson Accardia7384922007-08-09 14:23:41 -07002364 /*
Jeff Garzik2dcb4072007-10-19 06:42:56 -04002365 * Save off initial list of interrupts to be enabled.
2366 * This could be changed later
2367 */
Kristen Carlson Accardia7384922007-08-09 14:23:41 -07002368 pp->intr_mask = DEF_PORT_IRQ;
2369
Tejun Heo254950c2006-07-26 15:59:25 +09002370 ap->private_data = pp;
2371
Jeff Garzikdf69c9c2007-05-26 20:46:51 -04002372 /* engage engines, captain */
2373 return ahci_port_resume(ap);
Tejun Heo254950c2006-07-26 15:59:25 +09002374}
2375
2376static void ahci_port_stop(struct ata_port *ap)
2377{
Tejun Heo0be0aa92006-07-26 15:59:26 +09002378 const char *emsg = NULL;
2379 int rc;
Tejun Heo254950c2006-07-26 15:59:25 +09002380
Tejun Heo0be0aa92006-07-26 15:59:26 +09002381 /* de-initialize port */
Tejun Heo4447d352007-04-17 23:44:08 +09002382 rc = ahci_deinit_port(ap, &emsg);
Tejun Heo0be0aa92006-07-26 15:59:26 +09002383 if (rc)
2384 ata_port_printk(ap, KERN_WARNING, "%s (%d)\n", emsg, rc);
Tejun Heo254950c2006-07-26 15:59:25 +09002385}
2386
Tejun Heo4447d352007-04-17 23:44:08 +09002387static int ahci_configure_dma_masks(struct pci_dev *pdev, int using_dac)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002388{
Linus Torvalds1da177e2005-04-16 15:20:36 -07002389 int rc;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002390
Linus Torvalds1da177e2005-04-16 15:20:36 -07002391 if (using_dac &&
2392 !pci_set_dma_mask(pdev, DMA_64BIT_MASK)) {
2393 rc = pci_set_consistent_dma_mask(pdev, DMA_64BIT_MASK);
2394 if (rc) {
2395 rc = pci_set_consistent_dma_mask(pdev, DMA_32BIT_MASK);
2396 if (rc) {
Jeff Garzika9524a72005-10-30 14:39:11 -05002397 dev_printk(KERN_ERR, &pdev->dev,
2398 "64-bit DMA enable failed\n");
Linus Torvalds1da177e2005-04-16 15:20:36 -07002399 return rc;
2400 }
2401 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07002402 } else {
2403 rc = pci_set_dma_mask(pdev, DMA_32BIT_MASK);
2404 if (rc) {
Jeff Garzika9524a72005-10-30 14:39:11 -05002405 dev_printk(KERN_ERR, &pdev->dev,
2406 "32-bit DMA enable failed\n");
Linus Torvalds1da177e2005-04-16 15:20:36 -07002407 return rc;
2408 }
2409 rc = pci_set_consistent_dma_mask(pdev, DMA_32BIT_MASK);
2410 if (rc) {
Jeff Garzika9524a72005-10-30 14:39:11 -05002411 dev_printk(KERN_ERR, &pdev->dev,
2412 "32-bit consistent DMA enable failed\n");
Linus Torvalds1da177e2005-04-16 15:20:36 -07002413 return rc;
2414 }
2415 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07002416 return 0;
2417}
2418
Tejun Heo4447d352007-04-17 23:44:08 +09002419static void ahci_print_info(struct ata_host *host)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002420{
Tejun Heo4447d352007-04-17 23:44:08 +09002421 struct ahci_host_priv *hpriv = host->private_data;
2422 struct pci_dev *pdev = to_pci_dev(host->dev);
2423 void __iomem *mmio = host->iomap[AHCI_PCI_BAR];
Linus Torvalds1da177e2005-04-16 15:20:36 -07002424 u32 vers, cap, impl, speed;
2425 const char *speed_s;
2426 u16 cc;
2427 const char *scc_s;
2428
2429 vers = readl(mmio + HOST_VERSION);
2430 cap = hpriv->cap;
2431 impl = hpriv->port_map;
2432
2433 speed = (cap >> 20) & 0xf;
2434 if (speed == 1)
2435 speed_s = "1.5";
2436 else if (speed == 2)
2437 speed_s = "3";
2438 else
2439 speed_s = "?";
2440
2441 pci_read_config_word(pdev, 0x0a, &cc);
Conke Huc9f89472007-01-09 05:32:51 -05002442 if (cc == PCI_CLASS_STORAGE_IDE)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002443 scc_s = "IDE";
Conke Huc9f89472007-01-09 05:32:51 -05002444 else if (cc == PCI_CLASS_STORAGE_SATA)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002445 scc_s = "SATA";
Conke Huc9f89472007-01-09 05:32:51 -05002446 else if (cc == PCI_CLASS_STORAGE_RAID)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002447 scc_s = "RAID";
2448 else
2449 scc_s = "unknown";
2450
Jeff Garzika9524a72005-10-30 14:39:11 -05002451 dev_printk(KERN_INFO, &pdev->dev,
2452 "AHCI %02x%02x.%02x%02x "
Linus Torvalds1da177e2005-04-16 15:20:36 -07002453 "%u slots %u ports %s Gbps 0x%x impl %s mode\n"
Jeff Garzik2dcb4072007-10-19 06:42:56 -04002454 ,
Linus Torvalds1da177e2005-04-16 15:20:36 -07002455
Jeff Garzik2dcb4072007-10-19 06:42:56 -04002456 (vers >> 24) & 0xff,
2457 (vers >> 16) & 0xff,
2458 (vers >> 8) & 0xff,
2459 vers & 0xff,
Linus Torvalds1da177e2005-04-16 15:20:36 -07002460
2461 ((cap >> 8) & 0x1f) + 1,
2462 (cap & 0x1f) + 1,
2463 speed_s,
2464 impl,
2465 scc_s);
2466
Jeff Garzika9524a72005-10-30 14:39:11 -05002467 dev_printk(KERN_INFO, &pdev->dev,
2468 "flags: "
Tejun Heo203ef6c2007-07-16 14:29:40 +09002469 "%s%s%s%s%s%s%s"
Kristen Carlson Accardi18f7ba42008-06-03 10:33:55 -07002470 "%s%s%s%s%s%s%s"
2471 "%s\n"
Jeff Garzik2dcb4072007-10-19 06:42:56 -04002472 ,
Linus Torvalds1da177e2005-04-16 15:20:36 -07002473
2474 cap & (1 << 31) ? "64bit " : "",
2475 cap & (1 << 30) ? "ncq " : "",
Tejun Heo203ef6c2007-07-16 14:29:40 +09002476 cap & (1 << 29) ? "sntf " : "",
Linus Torvalds1da177e2005-04-16 15:20:36 -07002477 cap & (1 << 28) ? "ilck " : "",
2478 cap & (1 << 27) ? "stag " : "",
2479 cap & (1 << 26) ? "pm " : "",
2480 cap & (1 << 25) ? "led " : "",
2481
2482 cap & (1 << 24) ? "clo " : "",
2483 cap & (1 << 19) ? "nz " : "",
2484 cap & (1 << 18) ? "only " : "",
2485 cap & (1 << 17) ? "pmp " : "",
2486 cap & (1 << 15) ? "pio " : "",
2487 cap & (1 << 14) ? "slum " : "",
Kristen Carlson Accardi18f7ba42008-06-03 10:33:55 -07002488 cap & (1 << 13) ? "part " : "",
2489 cap & (1 << 6) ? "ems ": ""
Linus Torvalds1da177e2005-04-16 15:20:36 -07002490 );
2491}
2492
Tejun Heoedc93052007-10-25 14:59:16 +09002493/* On ASUS P5W DH Deluxe, the second port of PCI device 00:1f.2 is
2494 * hardwired to on-board SIMG 4726. The chipset is ICH8 and doesn't
2495 * support PMP and the 4726 either directly exports the device
2496 * attached to the first downstream port or acts as a hardware storage
2497 * controller and emulate a single ATA device (can be RAID 0/1 or some
2498 * other configuration).
2499 *
2500 * When there's no device attached to the first downstream port of the
2501 * 4726, "Config Disk" appears, which is a pseudo ATA device to
2502 * configure the 4726. However, ATA emulation of the device is very
2503 * lame. It doesn't send signature D2H Reg FIS after the initial
2504 * hardreset, pukes on SRST w/ PMP==0 and has bunch of other issues.
2505 *
2506 * The following function works around the problem by always using
2507 * hardreset on the port and not depending on receiving signature FIS
2508 * afterward. If signature FIS isn't received soon, ATA class is
2509 * assumed without follow-up softreset.
2510 */
2511static void ahci_p5wdh_workaround(struct ata_host *host)
2512{
2513 static struct dmi_system_id sysids[] = {
2514 {
2515 .ident = "P5W DH Deluxe",
2516 .matches = {
2517 DMI_MATCH(DMI_SYS_VENDOR,
2518 "ASUSTEK COMPUTER INC"),
2519 DMI_MATCH(DMI_PRODUCT_NAME, "P5W DH Deluxe"),
2520 },
2521 },
2522 { }
2523 };
2524 struct pci_dev *pdev = to_pci_dev(host->dev);
2525
2526 if (pdev->bus->number == 0 && pdev->devfn == PCI_DEVFN(0x1f, 2) &&
2527 dmi_check_system(sysids)) {
2528 struct ata_port *ap = host->ports[1];
2529
2530 dev_printk(KERN_INFO, &pdev->dev, "enabling ASUS P5W DH "
2531 "Deluxe on-board SIMG4726 workaround\n");
2532
2533 ap->ops = &ahci_p5wdh_ops;
2534 ap->link.flags |= ATA_LFLAG_NO_SRST | ATA_LFLAG_ASSUME_ATA;
2535 }
2536}
2537
Tejun Heo24dc5f32007-01-20 16:00:28 +09002538static int ahci_init_one(struct pci_dev *pdev, const struct pci_device_id *ent)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002539{
2540 static int printed_version;
Tejun Heoe297d992008-06-10 00:13:04 +09002541 unsigned int board_id = ent->driver_data;
2542 struct ata_port_info pi = ahci_port_info[board_id];
Tejun Heo4447d352007-04-17 23:44:08 +09002543 const struct ata_port_info *ppi[] = { &pi, NULL };
Tejun Heo24dc5f32007-01-20 16:00:28 +09002544 struct device *dev = &pdev->dev;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002545 struct ahci_host_priv *hpriv;
Tejun Heo4447d352007-04-17 23:44:08 +09002546 struct ata_host *host;
Tejun Heo837f5f82008-02-06 15:13:51 +09002547 int n_ports, i, rc;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002548
2549 VPRINTK("ENTER\n");
2550
Tejun Heo12fad3f2006-05-15 21:03:55 +09002551 WARN_ON(ATA_MAX_QUEUE > AHCI_MAX_CMDS);
2552
Linus Torvalds1da177e2005-04-16 15:20:36 -07002553 if (!printed_version++)
Jeff Garzika9524a72005-10-30 14:39:11 -05002554 dev_printk(KERN_DEBUG, &pdev->dev, "version " DRV_VERSION "\n");
Linus Torvalds1da177e2005-04-16 15:20:36 -07002555
Alan Cox5b66c822008-09-03 14:48:34 +01002556 /* The AHCI driver can only drive the SATA ports, the PATA driver
2557 can drive them all so if both drivers are selected make sure
2558 AHCI stays out of the way */
2559 if (pdev->vendor == PCI_VENDOR_ID_MARVELL && !marvell_enable)
2560 return -ENODEV;
2561
Tejun Heo4447d352007-04-17 23:44:08 +09002562 /* acquire resources */
Tejun Heo24dc5f32007-01-20 16:00:28 +09002563 rc = pcim_enable_device(pdev);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002564 if (rc)
2565 return rc;
2566
Tejun Heodea55132008-03-11 19:52:31 +09002567 /* AHCI controllers often implement SFF compatible interface.
2568 * Grab all PCI BARs just in case.
2569 */
2570 rc = pcim_iomap_regions_request_all(pdev, 1 << AHCI_PCI_BAR, DRV_NAME);
Tejun Heo0d5ff562007-02-01 15:06:36 +09002571 if (rc == -EBUSY)
Tejun Heo24dc5f32007-01-20 16:00:28 +09002572 pcim_pin_device(pdev);
Tejun Heo0d5ff562007-02-01 15:06:36 +09002573 if (rc)
Tejun Heo24dc5f32007-01-20 16:00:28 +09002574 return rc;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002575
Tejun Heoc4f77922007-12-06 15:09:43 +09002576 if (pdev->vendor == PCI_VENDOR_ID_INTEL &&
2577 (pdev->device == 0x2652 || pdev->device == 0x2653)) {
2578 u8 map;
2579
2580 /* ICH6s share the same PCI ID for both piix and ahci
2581 * modes. Enabling ahci mode while MAP indicates
2582 * combined mode is a bad idea. Yield to ata_piix.
2583 */
2584 pci_read_config_byte(pdev, ICH_MAP, &map);
2585 if (map & 0x3) {
2586 dev_printk(KERN_INFO, &pdev->dev, "controller is in "
2587 "combined mode, can't enable AHCI mode\n");
2588 return -ENODEV;
2589 }
2590 }
2591
Tejun Heo24dc5f32007-01-20 16:00:28 +09002592 hpriv = devm_kzalloc(dev, sizeof(*hpriv), GFP_KERNEL);
2593 if (!hpriv)
2594 return -ENOMEM;
Tejun Heo417a1a62007-09-23 13:19:55 +09002595 hpriv->flags |= (unsigned long)pi.private_data;
2596
Tejun Heoe297d992008-06-10 00:13:04 +09002597 /* MCP65 revision A1 and A2 can't do MSI */
2598 if (board_id == board_ahci_mcp65 &&
2599 (pdev->revision == 0xa1 || pdev->revision == 0xa2))
2600 hpriv->flags |= AHCI_HFLAG_NO_MSI;
2601
Tejun Heo417a1a62007-09-23 13:19:55 +09002602 if ((hpriv->flags & AHCI_HFLAG_NO_MSI) || pci_enable_msi(pdev))
2603 pci_intx(pdev, 1);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002604
Tejun Heo4447d352007-04-17 23:44:08 +09002605 /* save initial config */
Tejun Heo417a1a62007-09-23 13:19:55 +09002606 ahci_save_initial_config(pdev, hpriv);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002607
Tejun Heo4447d352007-04-17 23:44:08 +09002608 /* prepare host */
Tejun Heo274c1fd2007-07-16 14:29:40 +09002609 if (hpriv->cap & HOST_CAP_NCQ)
Tejun Heo4447d352007-04-17 23:44:08 +09002610 pi.flags |= ATA_FLAG_NCQ;
2611
Tejun Heo7d50b602007-09-23 13:19:54 +09002612 if (hpriv->cap & HOST_CAP_PMP)
2613 pi.flags |= ATA_FLAG_PMP;
2614
Kristen Carlson Accardi18f7ba42008-06-03 10:33:55 -07002615 if (ahci_em_messages && (hpriv->cap & HOST_CAP_EMS)) {
2616 u8 messages;
2617 void __iomem *mmio = pcim_iomap_table(pdev)[AHCI_PCI_BAR];
2618 u32 em_loc = readl(mmio + HOST_EM_LOC);
2619 u32 em_ctl = readl(mmio + HOST_EM_CTL);
2620
2621 messages = (em_ctl & 0x000f0000) >> 16;
2622
2623 /* we only support LED message type right now */
2624 if ((messages & 0x01) && (ahci_em_messages == 1)) {
2625 /* store em_loc */
2626 hpriv->em_loc = ((em_loc >> 16) * 4);
2627 pi.flags |= ATA_FLAG_EM;
2628 if (!(em_ctl & EM_CTL_ALHD))
2629 pi.flags |= ATA_FLAG_SW_ACTIVITY;
2630 }
2631 }
2632
Tejun Heo837f5f82008-02-06 15:13:51 +09002633 /* CAP.NP sometimes indicate the index of the last enabled
2634 * port, at other times, that of the last possible port, so
2635 * determining the maximum port number requires looking at
2636 * both CAP.NP and port_map.
2637 */
2638 n_ports = max(ahci_nr_ports(hpriv->cap), fls(hpriv->port_map));
2639
2640 host = ata_host_alloc_pinfo(&pdev->dev, ppi, n_ports);
Tejun Heo4447d352007-04-17 23:44:08 +09002641 if (!host)
2642 return -ENOMEM;
2643 host->iomap = pcim_iomap_table(pdev);
2644 host->private_data = hpriv;
2645
Kristen Carlson Accardi18f7ba42008-06-03 10:33:55 -07002646 if (pi.flags & ATA_FLAG_EM)
2647 ahci_reset_em(host);
2648
Tejun Heo4447d352007-04-17 23:44:08 +09002649 for (i = 0; i < host->n_ports; i++) {
Jeff Garzikdab632e2007-05-28 08:33:01 -04002650 struct ata_port *ap = host->ports[i];
Tejun Heo4447d352007-04-17 23:44:08 +09002651
Tejun Heocbcdd872007-08-18 13:14:55 +09002652 ata_port_pbar_desc(ap, AHCI_PCI_BAR, -1, "abar");
2653 ata_port_pbar_desc(ap, AHCI_PCI_BAR,
2654 0x100 + ap->port_no * 0x80, "port");
2655
Kristen Carlson Accardi31556592007-10-25 01:33:26 -04002656 /* set initial link pm policy */
2657 ap->pm_policy = NOT_AVAILABLE;
2658
Kristen Carlson Accardi18f7ba42008-06-03 10:33:55 -07002659 /* set enclosure management message type */
2660 if (ap->flags & ATA_FLAG_EM)
2661 ap->em_message_type = ahci_em_messages;
2662
2663
Jeff Garzikdab632e2007-05-28 08:33:01 -04002664 /* disabled/not-implemented port */
Tejun Heo350756f2008-04-07 22:47:21 +09002665 if (!(hpriv->port_map & (1 << i)))
Jeff Garzikdab632e2007-05-28 08:33:01 -04002666 ap->ops = &ata_dummy_port_ops;
Tejun Heo4447d352007-04-17 23:44:08 +09002667 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07002668
Tejun Heoedc93052007-10-25 14:59:16 +09002669 /* apply workaround for ASUS P5W DH Deluxe mainboard */
2670 ahci_p5wdh_workaround(host);
2671
Linus Torvalds1da177e2005-04-16 15:20:36 -07002672 /* initialize adapter */
Tejun Heo4447d352007-04-17 23:44:08 +09002673 rc = ahci_configure_dma_masks(pdev, hpriv->cap & HOST_CAP_64);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002674 if (rc)
Tejun Heo24dc5f32007-01-20 16:00:28 +09002675 return rc;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002676
Tejun Heo4447d352007-04-17 23:44:08 +09002677 rc = ahci_reset_controller(host);
2678 if (rc)
2679 return rc;
Tejun Heo12fad3f2006-05-15 21:03:55 +09002680
Tejun Heo4447d352007-04-17 23:44:08 +09002681 ahci_init_controller(host);
2682 ahci_print_info(host);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002683
Tejun Heo4447d352007-04-17 23:44:08 +09002684 pci_set_master(pdev);
2685 return ata_host_activate(host, pdev->irq, ahci_interrupt, IRQF_SHARED,
2686 &ahci_sht);
Jeff Garzik907f4672005-05-12 15:03:42 -04002687}
Linus Torvalds1da177e2005-04-16 15:20:36 -07002688
2689static int __init ahci_init(void)
2690{
Pavel Roskinb7887192006-08-10 18:13:18 +09002691 return pci_register_driver(&ahci_pci_driver);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002692}
2693
Linus Torvalds1da177e2005-04-16 15:20:36 -07002694static void __exit ahci_exit(void)
2695{
2696 pci_unregister_driver(&ahci_pci_driver);
2697}
2698
2699
2700MODULE_AUTHOR("Jeff Garzik");
2701MODULE_DESCRIPTION("AHCI SATA low-level driver");
2702MODULE_LICENSE("GPL");
2703MODULE_DEVICE_TABLE(pci, ahci_pci_tbl);
Jeff Garzik68854332005-08-23 02:53:51 -04002704MODULE_VERSION(DRV_VERSION);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002705
2706module_init(ahci_init);
2707module_exit(ahci_exit);