blob: 93bf5855a9b5a244ab882b344aee550ba5e1e2c6 [file] [log] [blame]
Linus Torvalds1da177e2005-04-16 15:20:36 -07001/*
2 * sata_nv.c - NVIDIA nForce SATA
3 *
4 * Copyright 2004 NVIDIA Corp. All rights reserved.
5 * Copyright 2004 Andrew Chew
6 *
Linus Torvalds1da177e2005-04-16 15:20:36 -07007 *
Jeff Garzikaa7e16d2005-08-29 15:12:56 -04008 * This program is free software; you can redistribute it and/or modify
9 * it under the terms of the GNU General Public License as published by
10 * the Free Software Foundation; either version 2, or (at your option)
11 * any later version.
12 *
13 * This program is distributed in the hope that it will be useful,
14 * but WITHOUT ANY WARRANTY; without even the implied warranty of
15 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16 * GNU General Public License for more details.
17 *
18 * You should have received a copy of the GNU General Public License
19 * along with this program; see the file COPYING. If not, write to
20 * the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA.
Linus Torvalds1da177e2005-04-16 15:20:36 -070021 *
Jeff Garzikaf36d7f2005-08-28 20:18:39 -040022 *
23 * libata documentation is available via 'make {ps|pdf}docs',
24 * as Documentation/DocBook/libata.*
25 *
26 * No hardware documentation available outside of NVIDIA.
27 * This driver programs the NVIDIA SATA controller in a similar
28 * fashion as with other PCI IDE BMDMA controllers, with a few
29 * NV-specific details such as register offsets, SATA phy location,
30 * hotplug info, etc.
31 *
Robert Hancockfbbb2622006-10-27 19:08:41 -070032 * CK804/MCP04 controllers support an alternate programming interface
33 * similar to the ADMA specification (with some modifications).
34 * This allows the use of NCQ. Non-DMA-mapped ATA commands are still
35 * sent through the legacy interface.
36 *
Linus Torvalds1da177e2005-04-16 15:20:36 -070037 */
38
Linus Torvalds1da177e2005-04-16 15:20:36 -070039#include <linux/kernel.h>
40#include <linux/module.h>
41#include <linux/pci.h>
42#include <linux/init.h>
43#include <linux/blkdev.h>
44#include <linux/delay.h>
45#include <linux/interrupt.h>
Jeff Garzika9524a72005-10-30 14:39:11 -050046#include <linux/device.h>
Linus Torvalds1da177e2005-04-16 15:20:36 -070047#include <scsi/scsi_host.h>
Robert Hancockfbbb2622006-10-27 19:08:41 -070048#include <scsi/scsi_device.h>
Linus Torvalds1da177e2005-04-16 15:20:36 -070049#include <linux/libata.h>
50
51#define DRV_NAME "sata_nv"
Jeff Garzik2a3103c2007-08-31 04:54:06 -040052#define DRV_VERSION "3.5"
Robert Hancockfbbb2622006-10-27 19:08:41 -070053
54#define NV_ADMA_DMA_BOUNDARY 0xffffffffUL
Linus Torvalds1da177e2005-04-16 15:20:36 -070055
Jeff Garzik10ad05d2006-03-22 23:50:50 -050056enum {
Tejun Heo0d5ff562007-02-01 15:06:36 +090057 NV_MMIO_BAR = 5,
58
Jeff Garzik10ad05d2006-03-22 23:50:50 -050059 NV_PORTS = 2,
60 NV_PIO_MASK = 0x1f,
61 NV_MWDMA_MASK = 0x07,
62 NV_UDMA_MASK = 0x7f,
63 NV_PORT0_SCR_REG_OFFSET = 0x00,
64 NV_PORT1_SCR_REG_OFFSET = 0x40,
Linus Torvalds1da177e2005-04-16 15:20:36 -070065
Tejun Heo27e4b272006-06-17 15:49:55 +090066 /* INT_STATUS/ENABLE */
Jeff Garzik10ad05d2006-03-22 23:50:50 -050067 NV_INT_STATUS = 0x10,
Jeff Garzik10ad05d2006-03-22 23:50:50 -050068 NV_INT_ENABLE = 0x11,
Tejun Heo27e4b272006-06-17 15:49:55 +090069 NV_INT_STATUS_CK804 = 0x440,
Jeff Garzik10ad05d2006-03-22 23:50:50 -050070 NV_INT_ENABLE_CK804 = 0x441,
Linus Torvalds1da177e2005-04-16 15:20:36 -070071
Tejun Heo27e4b272006-06-17 15:49:55 +090072 /* INT_STATUS/ENABLE bits */
73 NV_INT_DEV = 0x01,
74 NV_INT_PM = 0x02,
75 NV_INT_ADDED = 0x04,
76 NV_INT_REMOVED = 0x08,
77
78 NV_INT_PORT_SHIFT = 4, /* each port occupies 4 bits */
79
Tejun Heo39f87582006-06-17 15:49:56 +090080 NV_INT_ALL = 0x0f,
Tejun Heo5a44eff2006-06-17 15:49:56 +090081 NV_INT_MASK = NV_INT_DEV |
82 NV_INT_ADDED | NV_INT_REMOVED,
Tejun Heo39f87582006-06-17 15:49:56 +090083
Tejun Heo27e4b272006-06-17 15:49:55 +090084 /* INT_CONFIG */
Jeff Garzik10ad05d2006-03-22 23:50:50 -050085 NV_INT_CONFIG = 0x12,
86 NV_INT_CONFIG_METHD = 0x01, // 0 = INT, 1 = SMI
Linus Torvalds1da177e2005-04-16 15:20:36 -070087
Jeff Garzik10ad05d2006-03-22 23:50:50 -050088 // For PCI config register 20
89 NV_MCP_SATA_CFG_20 = 0x50,
90 NV_MCP_SATA_CFG_20_SATA_SPACE_EN = 0x04,
Robert Hancockfbbb2622006-10-27 19:08:41 -070091 NV_MCP_SATA_CFG_20_PORT0_EN = (1 << 17),
92 NV_MCP_SATA_CFG_20_PORT1_EN = (1 << 16),
93 NV_MCP_SATA_CFG_20_PORT0_PWB_EN = (1 << 14),
94 NV_MCP_SATA_CFG_20_PORT1_PWB_EN = (1 << 12),
95
96 NV_ADMA_MAX_CPBS = 32,
97 NV_ADMA_CPB_SZ = 128,
98 NV_ADMA_APRD_SZ = 16,
99 NV_ADMA_SGTBL_LEN = (1024 - NV_ADMA_CPB_SZ) /
100 NV_ADMA_APRD_SZ,
101 NV_ADMA_SGTBL_TOTAL_LEN = NV_ADMA_SGTBL_LEN + 5,
102 NV_ADMA_SGTBL_SZ = NV_ADMA_SGTBL_LEN * NV_ADMA_APRD_SZ,
103 NV_ADMA_PORT_PRIV_DMA_SZ = NV_ADMA_MAX_CPBS *
104 (NV_ADMA_CPB_SZ + NV_ADMA_SGTBL_SZ),
105
106 /* BAR5 offset to ADMA general registers */
107 NV_ADMA_GEN = 0x400,
108 NV_ADMA_GEN_CTL = 0x00,
109 NV_ADMA_NOTIFIER_CLEAR = 0x30,
110
111 /* BAR5 offset to ADMA ports */
112 NV_ADMA_PORT = 0x480,
113
114 /* size of ADMA port register space */
115 NV_ADMA_PORT_SIZE = 0x100,
116
117 /* ADMA port registers */
118 NV_ADMA_CTL = 0x40,
119 NV_ADMA_CPB_COUNT = 0x42,
120 NV_ADMA_NEXT_CPB_IDX = 0x43,
121 NV_ADMA_STAT = 0x44,
122 NV_ADMA_CPB_BASE_LOW = 0x48,
123 NV_ADMA_CPB_BASE_HIGH = 0x4C,
124 NV_ADMA_APPEND = 0x50,
125 NV_ADMA_NOTIFIER = 0x68,
126 NV_ADMA_NOTIFIER_ERROR = 0x6C,
127
128 /* NV_ADMA_CTL register bits */
129 NV_ADMA_CTL_HOTPLUG_IEN = (1 << 0),
130 NV_ADMA_CTL_CHANNEL_RESET = (1 << 5),
131 NV_ADMA_CTL_GO = (1 << 7),
132 NV_ADMA_CTL_AIEN = (1 << 8),
133 NV_ADMA_CTL_READ_NON_COHERENT = (1 << 11),
134 NV_ADMA_CTL_WRITE_NON_COHERENT = (1 << 12),
135
136 /* CPB response flag bits */
137 NV_CPB_RESP_DONE = (1 << 0),
138 NV_CPB_RESP_ATA_ERR = (1 << 3),
139 NV_CPB_RESP_CMD_ERR = (1 << 4),
140 NV_CPB_RESP_CPB_ERR = (1 << 7),
141
142 /* CPB control flag bits */
143 NV_CPB_CTL_CPB_VALID = (1 << 0),
144 NV_CPB_CTL_QUEUE = (1 << 1),
145 NV_CPB_CTL_APRD_VALID = (1 << 2),
146 NV_CPB_CTL_IEN = (1 << 3),
147 NV_CPB_CTL_FPDMA = (1 << 4),
148
149 /* APRD flags */
150 NV_APRD_WRITE = (1 << 1),
151 NV_APRD_END = (1 << 2),
152 NV_APRD_CONT = (1 << 3),
153
154 /* NV_ADMA_STAT flags */
155 NV_ADMA_STAT_TIMEOUT = (1 << 0),
156 NV_ADMA_STAT_HOTUNPLUG = (1 << 1),
157 NV_ADMA_STAT_HOTPLUG = (1 << 2),
158 NV_ADMA_STAT_CPBERR = (1 << 4),
159 NV_ADMA_STAT_SERROR = (1 << 5),
160 NV_ADMA_STAT_CMD_COMPLETE = (1 << 6),
161 NV_ADMA_STAT_IDLE = (1 << 8),
162 NV_ADMA_STAT_LEGACY = (1 << 9),
163 NV_ADMA_STAT_STOPPED = (1 << 10),
164 NV_ADMA_STAT_DONE = (1 << 12),
165 NV_ADMA_STAT_ERR = NV_ADMA_STAT_CPBERR |
Jeff Garzik2dcb4072007-10-19 06:42:56 -0400166 NV_ADMA_STAT_TIMEOUT,
Robert Hancockfbbb2622006-10-27 19:08:41 -0700167
168 /* port flags */
169 NV_ADMA_PORT_REGISTER_MODE = (1 << 0),
Robert Hancock2dec7552006-11-26 14:20:19 -0600170 NV_ADMA_ATAPI_SETUP_COMPLETE = (1 << 1),
Robert Hancockfbbb2622006-10-27 19:08:41 -0700171
Kuan Luof140f0f2007-10-15 15:16:53 -0400172 /* MCP55 reg offset */
173 NV_CTL_MCP55 = 0x400,
174 NV_INT_STATUS_MCP55 = 0x440,
175 NV_INT_ENABLE_MCP55 = 0x444,
176 NV_NCQ_REG_MCP55 = 0x448,
177
178 /* MCP55 */
179 NV_INT_ALL_MCP55 = 0xffff,
180 NV_INT_PORT_SHIFT_MCP55 = 16, /* each port occupies 16 bits */
181 NV_INT_MASK_MCP55 = NV_INT_ALL_MCP55 & 0xfffd,
182
183 /* SWNCQ ENABLE BITS*/
184 NV_CTL_PRI_SWNCQ = 0x02,
185 NV_CTL_SEC_SWNCQ = 0x04,
186
187 /* SW NCQ status bits*/
188 NV_SWNCQ_IRQ_DEV = (1 << 0),
189 NV_SWNCQ_IRQ_PM = (1 << 1),
190 NV_SWNCQ_IRQ_ADDED = (1 << 2),
191 NV_SWNCQ_IRQ_REMOVED = (1 << 3),
192
193 NV_SWNCQ_IRQ_BACKOUT = (1 << 4),
194 NV_SWNCQ_IRQ_SDBFIS = (1 << 5),
195 NV_SWNCQ_IRQ_DHREGFIS = (1 << 6),
196 NV_SWNCQ_IRQ_DMASETUP = (1 << 7),
197
198 NV_SWNCQ_IRQ_HOTPLUG = NV_SWNCQ_IRQ_ADDED |
199 NV_SWNCQ_IRQ_REMOVED,
200
Jeff Garzik10ad05d2006-03-22 23:50:50 -0500201};
Linus Torvalds1da177e2005-04-16 15:20:36 -0700202
Robert Hancockfbbb2622006-10-27 19:08:41 -0700203/* ADMA Physical Region Descriptor - one SG segment */
204struct nv_adma_prd {
205 __le64 addr;
206 __le32 len;
207 u8 flags;
208 u8 packet_len;
209 __le16 reserved;
210};
211
212enum nv_adma_regbits {
213 CMDEND = (1 << 15), /* end of command list */
214 WNB = (1 << 14), /* wait-not-BSY */
215 IGN = (1 << 13), /* ignore this entry */
216 CS1n = (1 << (4 + 8)), /* std. PATA signals follow... */
217 DA2 = (1 << (2 + 8)),
218 DA1 = (1 << (1 + 8)),
219 DA0 = (1 << (0 + 8)),
220};
221
222/* ADMA Command Parameter Block
223 The first 5 SG segments are stored inside the Command Parameter Block itself.
224 If there are more than 5 segments the remainder are stored in a separate
225 memory area indicated by next_aprd. */
226struct nv_adma_cpb {
227 u8 resp_flags; /* 0 */
228 u8 reserved1; /* 1 */
229 u8 ctl_flags; /* 2 */
230 /* len is length of taskfile in 64 bit words */
Jeff Garzik2dcb4072007-10-19 06:42:56 -0400231 u8 len; /* 3 */
Robert Hancockfbbb2622006-10-27 19:08:41 -0700232 u8 tag; /* 4 */
233 u8 next_cpb_idx; /* 5 */
234 __le16 reserved2; /* 6-7 */
235 __le16 tf[12]; /* 8-31 */
236 struct nv_adma_prd aprd[5]; /* 32-111 */
237 __le64 next_aprd; /* 112-119 */
238 __le64 reserved3; /* 120-127 */
239};
240
241
242struct nv_adma_port_priv {
243 struct nv_adma_cpb *cpb;
244 dma_addr_t cpb_dma;
245 struct nv_adma_prd *aprd;
246 dma_addr_t aprd_dma;
Jeff Garzik2dcb4072007-10-19 06:42:56 -0400247 void __iomem *ctl_block;
248 void __iomem *gen_block;
249 void __iomem *notifier_clear_block;
Robert Hancock8959d302008-02-04 19:39:02 -0600250 u64 adma_dma_mask;
Robert Hancockfbbb2622006-10-27 19:08:41 -0700251 u8 flags;
Robert Hancock5e5c74a2007-02-19 18:42:30 -0600252 int last_issue_ncq;
Robert Hancockfbbb2622006-10-27 19:08:41 -0700253};
254
Robert Hancockcdf56bc2007-01-03 18:13:57 -0600255struct nv_host_priv {
256 unsigned long type;
257};
258
Kuan Luof140f0f2007-10-15 15:16:53 -0400259struct defer_queue {
260 u32 defer_bits;
261 unsigned int head;
262 unsigned int tail;
263 unsigned int tag[ATA_MAX_QUEUE];
264};
265
266enum ncq_saw_flag_list {
267 ncq_saw_d2h = (1U << 0),
268 ncq_saw_dmas = (1U << 1),
269 ncq_saw_sdb = (1U << 2),
270 ncq_saw_backout = (1U << 3),
271};
272
273struct nv_swncq_port_priv {
274 struct ata_prd *prd; /* our SG list */
275 dma_addr_t prd_dma; /* and its DMA mapping */
276 void __iomem *sactive_block;
277 void __iomem *irq_block;
278 void __iomem *tag_block;
279 u32 qc_active;
280
281 unsigned int last_issue_tag;
282
283 /* fifo circular queue to store deferral command */
284 struct defer_queue defer_queue;
285
286 /* for NCQ interrupt analysis */
287 u32 dhfis_bits;
288 u32 dmafis_bits;
289 u32 sdbfis_bits;
290
291 unsigned int ncq_flags;
292};
293
294
Jeff Garzik5796d1c2007-10-26 00:03:37 -0400295#define NV_ADMA_CHECK_INTR(GCTL, PORT) ((GCTL) & (1 << (19 + (12 * (PORT)))))
Robert Hancockfbbb2622006-10-27 19:08:41 -0700296
Jeff Garzik2dcb4072007-10-19 06:42:56 -0400297static int nv_init_one(struct pci_dev *pdev, const struct pci_device_id *ent);
Tejun Heo438ac6d2007-03-02 17:31:26 +0900298#ifdef CONFIG_PM
Robert Hancockcdf56bc2007-01-03 18:13:57 -0600299static int nv_pci_device_resume(struct pci_dev *pdev);
Tejun Heo438ac6d2007-03-02 17:31:26 +0900300#endif
Jeff Garzikcca39742006-08-24 03:19:22 -0400301static void nv_ck804_host_stop(struct ata_host *host);
David Howells7d12e782006-10-05 14:55:46 +0100302static irqreturn_t nv_generic_interrupt(int irq, void *dev_instance);
303static irqreturn_t nv_nf2_interrupt(int irq, void *dev_instance);
304static irqreturn_t nv_ck804_interrupt(int irq, void *dev_instance);
Tejun Heo82ef04f2008-07-31 17:02:40 +0900305static int nv_scr_read(struct ata_link *link, unsigned int sc_reg, u32 *val);
306static int nv_scr_write(struct ata_link *link, unsigned int sc_reg, u32 val);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700307
Tejun Heoe8caa3c2009-01-25 11:25:22 +0900308static int nv_noclassify_hardreset(struct ata_link *link, unsigned int *class,
309 unsigned long deadline);
Tejun Heo39f87582006-06-17 15:49:56 +0900310static void nv_nf2_freeze(struct ata_port *ap);
311static void nv_nf2_thaw(struct ata_port *ap);
312static void nv_ck804_freeze(struct ata_port *ap);
313static void nv_ck804_thaw(struct ata_port *ap);
Robert Hancockfbbb2622006-10-27 19:08:41 -0700314static int nv_adma_slave_config(struct scsi_device *sdev);
Robert Hancock2dec7552006-11-26 14:20:19 -0600315static int nv_adma_check_atapi_dma(struct ata_queued_cmd *qc);
Robert Hancockfbbb2622006-10-27 19:08:41 -0700316static void nv_adma_qc_prep(struct ata_queued_cmd *qc);
317static unsigned int nv_adma_qc_issue(struct ata_queued_cmd *qc);
318static irqreturn_t nv_adma_interrupt(int irq, void *dev_instance);
319static void nv_adma_irq_clear(struct ata_port *ap);
320static int nv_adma_port_start(struct ata_port *ap);
321static void nv_adma_port_stop(struct ata_port *ap);
Tejun Heo438ac6d2007-03-02 17:31:26 +0900322#ifdef CONFIG_PM
Robert Hancockcdf56bc2007-01-03 18:13:57 -0600323static int nv_adma_port_suspend(struct ata_port *ap, pm_message_t mesg);
324static int nv_adma_port_resume(struct ata_port *ap);
Tejun Heo438ac6d2007-03-02 17:31:26 +0900325#endif
Robert Hancock53014e22007-05-05 15:36:36 -0600326static void nv_adma_freeze(struct ata_port *ap);
327static void nv_adma_thaw(struct ata_port *ap);
Robert Hancockfbbb2622006-10-27 19:08:41 -0700328static void nv_adma_error_handler(struct ata_port *ap);
329static void nv_adma_host_stop(struct ata_host *host);
Robert Hancockf5ecac22007-02-20 21:49:10 -0600330static void nv_adma_post_internal_cmd(struct ata_queued_cmd *qc);
Robert Hancockf2fb3442007-03-26 21:43:36 -0800331static void nv_adma_tf_read(struct ata_port *ap, struct ata_taskfile *tf);
Tejun Heo39f87582006-06-17 15:49:56 +0900332
Kuan Luof140f0f2007-10-15 15:16:53 -0400333static void nv_mcp55_thaw(struct ata_port *ap);
334static void nv_mcp55_freeze(struct ata_port *ap);
335static void nv_swncq_error_handler(struct ata_port *ap);
336static int nv_swncq_slave_config(struct scsi_device *sdev);
337static int nv_swncq_port_start(struct ata_port *ap);
338static void nv_swncq_qc_prep(struct ata_queued_cmd *qc);
339static void nv_swncq_fill_sg(struct ata_queued_cmd *qc);
340static unsigned int nv_swncq_qc_issue(struct ata_queued_cmd *qc);
341static void nv_swncq_irq_clear(struct ata_port *ap, u16 fis);
342static irqreturn_t nv_swncq_interrupt(int irq, void *dev_instance);
343#ifdef CONFIG_PM
344static int nv_swncq_port_suspend(struct ata_port *ap, pm_message_t mesg);
345static int nv_swncq_port_resume(struct ata_port *ap);
346#endif
347
Linus Torvalds1da177e2005-04-16 15:20:36 -0700348enum nv_host_type
349{
350 GENERIC,
351 NFORCE2,
Tejun Heo27e4b272006-06-17 15:49:55 +0900352 NFORCE3 = NFORCE2, /* NF2 == NF3 as far as sata_nv is concerned */
Robert Hancockfbbb2622006-10-27 19:08:41 -0700353 CK804,
Kuan Luof140f0f2007-10-15 15:16:53 -0400354 ADMA,
355 SWNCQ,
Linus Torvalds1da177e2005-04-16 15:20:36 -0700356};
357
Jeff Garzik3b7d6972005-11-10 11:04:11 -0500358static const struct pci_device_id nv_pci_tbl[] = {
Jeff Garzik54bb3a942006-09-27 22:20:11 -0400359 { PCI_VDEVICE(NVIDIA, PCI_DEVICE_ID_NVIDIA_NFORCE2S_SATA), NFORCE2 },
360 { PCI_VDEVICE(NVIDIA, PCI_DEVICE_ID_NVIDIA_NFORCE3S_SATA), NFORCE3 },
361 { PCI_VDEVICE(NVIDIA, PCI_DEVICE_ID_NVIDIA_NFORCE3S_SATA2), NFORCE3 },
362 { PCI_VDEVICE(NVIDIA, PCI_DEVICE_ID_NVIDIA_NFORCE_CK804_SATA), CK804 },
363 { PCI_VDEVICE(NVIDIA, PCI_DEVICE_ID_NVIDIA_NFORCE_CK804_SATA2), CK804 },
364 { PCI_VDEVICE(NVIDIA, PCI_DEVICE_ID_NVIDIA_NFORCE_MCP04_SATA), CK804 },
365 { PCI_VDEVICE(NVIDIA, PCI_DEVICE_ID_NVIDIA_NFORCE_MCP04_SATA2), CK804 },
Kuan Luof140f0f2007-10-15 15:16:53 -0400366 { PCI_VDEVICE(NVIDIA, PCI_DEVICE_ID_NVIDIA_NFORCE_MCP51_SATA), SWNCQ },
367 { PCI_VDEVICE(NVIDIA, PCI_DEVICE_ID_NVIDIA_NFORCE_MCP51_SATA2), SWNCQ },
368 { PCI_VDEVICE(NVIDIA, PCI_DEVICE_ID_NVIDIA_NFORCE_MCP55_SATA), SWNCQ },
369 { PCI_VDEVICE(NVIDIA, PCI_DEVICE_ID_NVIDIA_NFORCE_MCP55_SATA2), SWNCQ },
Kuan Luoe2e031e2007-10-25 02:14:17 -0400370 { PCI_VDEVICE(NVIDIA, PCI_DEVICE_ID_NVIDIA_NFORCE_MCP61_SATA), GENERIC },
371 { PCI_VDEVICE(NVIDIA, PCI_DEVICE_ID_NVIDIA_NFORCE_MCP61_SATA2), GENERIC },
372 { PCI_VDEVICE(NVIDIA, PCI_DEVICE_ID_NVIDIA_NFORCE_MCP61_SATA3), GENERIC },
Jeff Garzik2d2744f2006-09-28 20:21:59 -0400373
374 { } /* terminate list */
Linus Torvalds1da177e2005-04-16 15:20:36 -0700375};
376
Linus Torvalds1da177e2005-04-16 15:20:36 -0700377static struct pci_driver nv_pci_driver = {
378 .name = DRV_NAME,
379 .id_table = nv_pci_tbl,
380 .probe = nv_init_one,
Tejun Heo438ac6d2007-03-02 17:31:26 +0900381#ifdef CONFIG_PM
Robert Hancockcdf56bc2007-01-03 18:13:57 -0600382 .suspend = ata_pci_device_suspend,
383 .resume = nv_pci_device_resume,
Tejun Heo438ac6d2007-03-02 17:31:26 +0900384#endif
Tejun Heo1daf9ce2007-05-17 13:13:57 +0200385 .remove = ata_pci_remove_one,
Linus Torvalds1da177e2005-04-16 15:20:36 -0700386};
387
Jeff Garzik193515d2005-11-07 00:59:37 -0500388static struct scsi_host_template nv_sht = {
Tejun Heo68d1d072008-03-25 12:22:49 +0900389 ATA_BMDMA_SHT(DRV_NAME),
Linus Torvalds1da177e2005-04-16 15:20:36 -0700390};
391
Robert Hancockfbbb2622006-10-27 19:08:41 -0700392static struct scsi_host_template nv_adma_sht = {
Tejun Heo68d1d072008-03-25 12:22:49 +0900393 ATA_NCQ_SHT(DRV_NAME),
Robert Hancockfbbb2622006-10-27 19:08:41 -0700394 .can_queue = NV_ADMA_MAX_CPBS,
Robert Hancockfbbb2622006-10-27 19:08:41 -0700395 .sg_tablesize = NV_ADMA_SGTBL_TOTAL_LEN,
Robert Hancockfbbb2622006-10-27 19:08:41 -0700396 .dma_boundary = NV_ADMA_DMA_BOUNDARY,
397 .slave_configure = nv_adma_slave_config,
Robert Hancockfbbb2622006-10-27 19:08:41 -0700398};
399
Kuan Luof140f0f2007-10-15 15:16:53 -0400400static struct scsi_host_template nv_swncq_sht = {
Tejun Heo68d1d072008-03-25 12:22:49 +0900401 ATA_NCQ_SHT(DRV_NAME),
Kuan Luof140f0f2007-10-15 15:16:53 -0400402 .can_queue = ATA_MAX_QUEUE,
Kuan Luof140f0f2007-10-15 15:16:53 -0400403 .sg_tablesize = LIBATA_MAX_PRD,
Kuan Luof140f0f2007-10-15 15:16:53 -0400404 .dma_boundary = ATA_DMA_BOUNDARY,
405 .slave_configure = nv_swncq_slave_config,
Kuan Luof140f0f2007-10-15 15:16:53 -0400406};
407
Tejun Heo4c1eb902008-09-28 07:39:01 +0900408static struct ata_port_operations nv_common_ops = {
Tejun Heo029cfd62008-03-25 12:22:49 +0900409 .inherits = &ata_bmdma_port_ops,
Linus Torvalds1da177e2005-04-16 15:20:36 -0700410 .scr_read = nv_scr_read,
411 .scr_write = nv_scr_write,
Linus Torvalds1da177e2005-04-16 15:20:36 -0700412};
413
Tejun Heo4c1eb902008-09-28 07:39:01 +0900414/* OSDL bz11195 reports that link doesn't come online after hardreset
415 * on generic nv's and there have been several other similar reports
416 * on linux-ide. Disable hardreset for generic nv's.
417 */
418static struct ata_port_operations nv_generic_ops = {
419 .inherits = &nv_common_ops,
420 .hardreset = ATA_OP_NULL,
421};
422
Tejun Heo3c324282008-11-03 12:37:49 +0900423/* OSDL bz3352 reports that nf2/3 controllers can't determine device
424 * signature reliably. Also, the following thread reports detection
425 * failure on cold boot with the standard debouncing timing.
426 *
427 * http://thread.gmane.org/gmane.linux.ide/34098
428 *
429 * Debounce with hotplug timing and request follow-up SRST.
430 */
Tejun Heo029cfd62008-03-25 12:22:49 +0900431static struct ata_port_operations nv_nf2_ops = {
Tejun Heo4c1eb902008-09-28 07:39:01 +0900432 .inherits = &nv_common_ops,
Tejun Heo39f87582006-06-17 15:49:56 +0900433 .freeze = nv_nf2_freeze,
434 .thaw = nv_nf2_thaw,
Tejun Heoe8caa3c2009-01-25 11:25:22 +0900435 .hardreset = nv_noclassify_hardreset,
Tejun Heoada364e2006-06-17 15:49:56 +0900436};
437
Tejun Heo3c324282008-11-03 12:37:49 +0900438/* CK804 finally gets hardreset right */
Tejun Heo029cfd62008-03-25 12:22:49 +0900439static struct ata_port_operations nv_ck804_ops = {
Tejun Heo4c1eb902008-09-28 07:39:01 +0900440 .inherits = &nv_common_ops,
Tejun Heo39f87582006-06-17 15:49:56 +0900441 .freeze = nv_ck804_freeze,
442 .thaw = nv_ck804_thaw,
Tejun Heoada364e2006-06-17 15:49:56 +0900443 .host_stop = nv_ck804_host_stop,
444};
445
Tejun Heo029cfd62008-03-25 12:22:49 +0900446static struct ata_port_operations nv_adma_ops = {
Tejun Heo3c324282008-11-03 12:37:49 +0900447 .inherits = &nv_ck804_ops,
Tejun Heo029cfd62008-03-25 12:22:49 +0900448
Robert Hancock2dec7552006-11-26 14:20:19 -0600449 .check_atapi_dma = nv_adma_check_atapi_dma,
Tejun Heo5682ed32008-04-07 22:47:16 +0900450 .sff_tf_read = nv_adma_tf_read,
Tejun Heo31cc23b2007-09-23 13:14:12 +0900451 .qc_defer = ata_std_qc_defer,
Robert Hancockfbbb2622006-10-27 19:08:41 -0700452 .qc_prep = nv_adma_qc_prep,
453 .qc_issue = nv_adma_qc_issue,
Tejun Heo5682ed32008-04-07 22:47:16 +0900454 .sff_irq_clear = nv_adma_irq_clear,
Tejun Heo029cfd62008-03-25 12:22:49 +0900455
Robert Hancock53014e22007-05-05 15:36:36 -0600456 .freeze = nv_adma_freeze,
457 .thaw = nv_adma_thaw,
Robert Hancockfbbb2622006-10-27 19:08:41 -0700458 .error_handler = nv_adma_error_handler,
Robert Hancockf5ecac22007-02-20 21:49:10 -0600459 .post_internal_cmd = nv_adma_post_internal_cmd,
Tejun Heo029cfd62008-03-25 12:22:49 +0900460
Robert Hancockfbbb2622006-10-27 19:08:41 -0700461 .port_start = nv_adma_port_start,
462 .port_stop = nv_adma_port_stop,
Tejun Heo438ac6d2007-03-02 17:31:26 +0900463#ifdef CONFIG_PM
Robert Hancockcdf56bc2007-01-03 18:13:57 -0600464 .port_suspend = nv_adma_port_suspend,
465 .port_resume = nv_adma_port_resume,
Tejun Heo438ac6d2007-03-02 17:31:26 +0900466#endif
Robert Hancockfbbb2622006-10-27 19:08:41 -0700467 .host_stop = nv_adma_host_stop,
468};
469
Tejun Heo029cfd62008-03-25 12:22:49 +0900470static struct ata_port_operations nv_swncq_ops = {
Tejun Heo3c324282008-11-03 12:37:49 +0900471 .inherits = &nv_generic_ops,
Tejun Heo029cfd62008-03-25 12:22:49 +0900472
Kuan Luof140f0f2007-10-15 15:16:53 -0400473 .qc_defer = ata_std_qc_defer,
474 .qc_prep = nv_swncq_qc_prep,
475 .qc_issue = nv_swncq_qc_issue,
Tejun Heo029cfd62008-03-25 12:22:49 +0900476
Kuan Luof140f0f2007-10-15 15:16:53 -0400477 .freeze = nv_mcp55_freeze,
478 .thaw = nv_mcp55_thaw,
479 .error_handler = nv_swncq_error_handler,
Tejun Heo029cfd62008-03-25 12:22:49 +0900480
Kuan Luof140f0f2007-10-15 15:16:53 -0400481#ifdef CONFIG_PM
482 .port_suspend = nv_swncq_port_suspend,
483 .port_resume = nv_swncq_port_resume,
484#endif
485 .port_start = nv_swncq_port_start,
486};
487
Tejun Heo95947192008-03-25 12:22:49 +0900488struct nv_pi_priv {
489 irq_handler_t irq_handler;
490 struct scsi_host_template *sht;
491};
492
493#define NV_PI_PRIV(_irq_handler, _sht) \
494 &(struct nv_pi_priv){ .irq_handler = _irq_handler, .sht = _sht }
495
Tejun Heo1626aeb2007-05-04 12:43:58 +0200496static const struct ata_port_info nv_port_info[] = {
Tejun Heoada364e2006-06-17 15:49:56 +0900497 /* generic */
498 {
Tejun Heo0c887582007-08-06 18:36:23 +0900499 .flags = ATA_FLAG_SATA | ATA_FLAG_NO_LEGACY,
Tejun Heoada364e2006-06-17 15:49:56 +0900500 .pio_mask = NV_PIO_MASK,
501 .mwdma_mask = NV_MWDMA_MASK,
502 .udma_mask = NV_UDMA_MASK,
503 .port_ops = &nv_generic_ops,
Tejun Heo95947192008-03-25 12:22:49 +0900504 .private_data = NV_PI_PRIV(nv_generic_interrupt, &nv_sht),
Tejun Heoada364e2006-06-17 15:49:56 +0900505 },
506 /* nforce2/3 */
507 {
Tejun Heo0c887582007-08-06 18:36:23 +0900508 .flags = ATA_FLAG_SATA | ATA_FLAG_NO_LEGACY,
Tejun Heoada364e2006-06-17 15:49:56 +0900509 .pio_mask = NV_PIO_MASK,
510 .mwdma_mask = NV_MWDMA_MASK,
511 .udma_mask = NV_UDMA_MASK,
512 .port_ops = &nv_nf2_ops,
Tejun Heo95947192008-03-25 12:22:49 +0900513 .private_data = NV_PI_PRIV(nv_nf2_interrupt, &nv_sht),
Tejun Heoada364e2006-06-17 15:49:56 +0900514 },
515 /* ck804 */
516 {
Tejun Heo0c887582007-08-06 18:36:23 +0900517 .flags = ATA_FLAG_SATA | ATA_FLAG_NO_LEGACY,
Tejun Heoada364e2006-06-17 15:49:56 +0900518 .pio_mask = NV_PIO_MASK,
519 .mwdma_mask = NV_MWDMA_MASK,
520 .udma_mask = NV_UDMA_MASK,
521 .port_ops = &nv_ck804_ops,
Tejun Heo95947192008-03-25 12:22:49 +0900522 .private_data = NV_PI_PRIV(nv_ck804_interrupt, &nv_sht),
Tejun Heoada364e2006-06-17 15:49:56 +0900523 },
Robert Hancockfbbb2622006-10-27 19:08:41 -0700524 /* ADMA */
525 {
Robert Hancockfbbb2622006-10-27 19:08:41 -0700526 .flags = ATA_FLAG_SATA | ATA_FLAG_NO_LEGACY |
527 ATA_FLAG_MMIO | ATA_FLAG_NCQ,
528 .pio_mask = NV_PIO_MASK,
529 .mwdma_mask = NV_MWDMA_MASK,
530 .udma_mask = NV_UDMA_MASK,
531 .port_ops = &nv_adma_ops,
Tejun Heo95947192008-03-25 12:22:49 +0900532 .private_data = NV_PI_PRIV(nv_adma_interrupt, &nv_adma_sht),
Robert Hancockfbbb2622006-10-27 19:08:41 -0700533 },
Kuan Luof140f0f2007-10-15 15:16:53 -0400534 /* SWNCQ */
535 {
Kuan Luof140f0f2007-10-15 15:16:53 -0400536 .flags = ATA_FLAG_SATA | ATA_FLAG_NO_LEGACY |
537 ATA_FLAG_NCQ,
Kuan Luof140f0f2007-10-15 15:16:53 -0400538 .pio_mask = NV_PIO_MASK,
539 .mwdma_mask = NV_MWDMA_MASK,
540 .udma_mask = NV_UDMA_MASK,
541 .port_ops = &nv_swncq_ops,
Tejun Heo95947192008-03-25 12:22:49 +0900542 .private_data = NV_PI_PRIV(nv_swncq_interrupt, &nv_swncq_sht),
Kuan Luof140f0f2007-10-15 15:16:53 -0400543 },
Linus Torvalds1da177e2005-04-16 15:20:36 -0700544};
545
546MODULE_AUTHOR("NVIDIA");
547MODULE_DESCRIPTION("low-level driver for NVIDIA nForce SATA controller");
548MODULE_LICENSE("GPL");
549MODULE_DEVICE_TABLE(pci, nv_pci_tbl);
550MODULE_VERSION(DRV_VERSION);
551
Jeff Garzik06993d22008-04-04 03:34:45 -0400552static int adma_enabled;
Zoltan Boszormenyid21279f2008-03-28 14:33:46 -0700553static int swncq_enabled = 1;
Robert Hancockfbbb2622006-10-27 19:08:41 -0700554
Robert Hancock2dec7552006-11-26 14:20:19 -0600555static void nv_adma_register_mode(struct ata_port *ap)
556{
Robert Hancock2dec7552006-11-26 14:20:19 -0600557 struct nv_adma_port_priv *pp = ap->private_data;
Robert Hancockcdf56bc2007-01-03 18:13:57 -0600558 void __iomem *mmio = pp->ctl_block;
Robert Hancocka2cfe812007-02-05 16:26:03 -0800559 u16 tmp, status;
560 int count = 0;
Robert Hancock2dec7552006-11-26 14:20:19 -0600561
562 if (pp->flags & NV_ADMA_PORT_REGISTER_MODE)
563 return;
564
Robert Hancocka2cfe812007-02-05 16:26:03 -0800565 status = readw(mmio + NV_ADMA_STAT);
Jeff Garzik2dcb4072007-10-19 06:42:56 -0400566 while (!(status & NV_ADMA_STAT_IDLE) && count < 20) {
Robert Hancocka2cfe812007-02-05 16:26:03 -0800567 ndelay(50);
568 status = readw(mmio + NV_ADMA_STAT);
569 count++;
570 }
Jeff Garzik2dcb4072007-10-19 06:42:56 -0400571 if (count == 20)
Robert Hancocka2cfe812007-02-05 16:26:03 -0800572 ata_port_printk(ap, KERN_WARNING,
573 "timeout waiting for ADMA IDLE, stat=0x%hx\n",
574 status);
575
Robert Hancock2dec7552006-11-26 14:20:19 -0600576 tmp = readw(mmio + NV_ADMA_CTL);
577 writew(tmp & ~NV_ADMA_CTL_GO, mmio + NV_ADMA_CTL);
578
Robert Hancocka2cfe812007-02-05 16:26:03 -0800579 count = 0;
580 status = readw(mmio + NV_ADMA_STAT);
Jeff Garzik2dcb4072007-10-19 06:42:56 -0400581 while (!(status & NV_ADMA_STAT_LEGACY) && count < 20) {
Robert Hancocka2cfe812007-02-05 16:26:03 -0800582 ndelay(50);
583 status = readw(mmio + NV_ADMA_STAT);
584 count++;
585 }
Jeff Garzik2dcb4072007-10-19 06:42:56 -0400586 if (count == 20)
Robert Hancocka2cfe812007-02-05 16:26:03 -0800587 ata_port_printk(ap, KERN_WARNING,
588 "timeout waiting for ADMA LEGACY, stat=0x%hx\n",
589 status);
590
Robert Hancock2dec7552006-11-26 14:20:19 -0600591 pp->flags |= NV_ADMA_PORT_REGISTER_MODE;
592}
593
594static void nv_adma_mode(struct ata_port *ap)
595{
Robert Hancock2dec7552006-11-26 14:20:19 -0600596 struct nv_adma_port_priv *pp = ap->private_data;
Robert Hancockcdf56bc2007-01-03 18:13:57 -0600597 void __iomem *mmio = pp->ctl_block;
Robert Hancocka2cfe812007-02-05 16:26:03 -0800598 u16 tmp, status;
599 int count = 0;
Robert Hancock2dec7552006-11-26 14:20:19 -0600600
601 if (!(pp->flags & NV_ADMA_PORT_REGISTER_MODE))
602 return;
Jeff Garzikf20b16f2006-12-11 11:14:06 -0500603
Robert Hancock2dec7552006-11-26 14:20:19 -0600604 WARN_ON(pp->flags & NV_ADMA_ATAPI_SETUP_COMPLETE);
605
606 tmp = readw(mmio + NV_ADMA_CTL);
607 writew(tmp | NV_ADMA_CTL_GO, mmio + NV_ADMA_CTL);
608
Robert Hancocka2cfe812007-02-05 16:26:03 -0800609 status = readw(mmio + NV_ADMA_STAT);
Jeff Garzik2dcb4072007-10-19 06:42:56 -0400610 while (((status & NV_ADMA_STAT_LEGACY) ||
Robert Hancocka2cfe812007-02-05 16:26:03 -0800611 !(status & NV_ADMA_STAT_IDLE)) && count < 20) {
612 ndelay(50);
613 status = readw(mmio + NV_ADMA_STAT);
614 count++;
615 }
Jeff Garzik2dcb4072007-10-19 06:42:56 -0400616 if (count == 20)
Robert Hancocka2cfe812007-02-05 16:26:03 -0800617 ata_port_printk(ap, KERN_WARNING,
618 "timeout waiting for ADMA LEGACY clear and IDLE, stat=0x%hx\n",
619 status);
620
Robert Hancock2dec7552006-11-26 14:20:19 -0600621 pp->flags &= ~NV_ADMA_PORT_REGISTER_MODE;
622}
623
Robert Hancockfbbb2622006-10-27 19:08:41 -0700624static int nv_adma_slave_config(struct scsi_device *sdev)
625{
626 struct ata_port *ap = ata_shost_to_port(sdev->host);
Robert Hancock2dec7552006-11-26 14:20:19 -0600627 struct nv_adma_port_priv *pp = ap->private_data;
Robert Hancock8959d302008-02-04 19:39:02 -0600628 struct nv_adma_port_priv *port0, *port1;
629 struct scsi_device *sdev0, *sdev1;
Robert Hancock2dec7552006-11-26 14:20:19 -0600630 struct pci_dev *pdev = to_pci_dev(ap->host->dev);
Robert Hancock8959d302008-02-04 19:39:02 -0600631 unsigned long segment_boundary, flags;
Robert Hancockfbbb2622006-10-27 19:08:41 -0700632 unsigned short sg_tablesize;
633 int rc;
Robert Hancock2dec7552006-11-26 14:20:19 -0600634 int adma_enable;
635 u32 current_reg, new_reg, config_mask;
Robert Hancockfbbb2622006-10-27 19:08:41 -0700636
637 rc = ata_scsi_slave_config(sdev);
638
639 if (sdev->id >= ATA_MAX_DEVICES || sdev->channel || sdev->lun)
640 /* Not a proper libata device, ignore */
641 return rc;
642
Robert Hancock8959d302008-02-04 19:39:02 -0600643 spin_lock_irqsave(ap->lock, flags);
644
Tejun Heo9af5c9c2007-08-06 18:36:22 +0900645 if (ap->link.device[sdev->id].class == ATA_DEV_ATAPI) {
Robert Hancockfbbb2622006-10-27 19:08:41 -0700646 /*
647 * NVIDIA reports that ADMA mode does not support ATAPI commands.
648 * Therefore ATAPI commands are sent through the legacy interface.
649 * However, the legacy interface only supports 32-bit DMA.
650 * Restrict DMA parameters as required by the legacy interface
651 * when an ATAPI device is connected.
652 */
Robert Hancockfbbb2622006-10-27 19:08:41 -0700653 segment_boundary = ATA_DMA_BOUNDARY;
654 /* Subtract 1 since an extra entry may be needed for padding, see
655 libata-scsi.c */
656 sg_tablesize = LIBATA_MAX_PRD - 1;
Jeff Garzikf20b16f2006-12-11 11:14:06 -0500657
Robert Hancock2dec7552006-11-26 14:20:19 -0600658 /* Since the legacy DMA engine is in use, we need to disable ADMA
659 on the port. */
660 adma_enable = 0;
661 nv_adma_register_mode(ap);
Jeff Garzik2dcb4072007-10-19 06:42:56 -0400662 } else {
Robert Hancockfbbb2622006-10-27 19:08:41 -0700663 segment_boundary = NV_ADMA_DMA_BOUNDARY;
664 sg_tablesize = NV_ADMA_SGTBL_TOTAL_LEN;
Robert Hancock2dec7552006-11-26 14:20:19 -0600665 adma_enable = 1;
Robert Hancockfbbb2622006-10-27 19:08:41 -0700666 }
Jeff Garzikf20b16f2006-12-11 11:14:06 -0500667
Robert Hancock2dec7552006-11-26 14:20:19 -0600668 pci_read_config_dword(pdev, NV_MCP_SATA_CFG_20, &current_reg);
Robert Hancockfbbb2622006-10-27 19:08:41 -0700669
Jeff Garzik2dcb4072007-10-19 06:42:56 -0400670 if (ap->port_no == 1)
Robert Hancock2dec7552006-11-26 14:20:19 -0600671 config_mask = NV_MCP_SATA_CFG_20_PORT1_EN |
672 NV_MCP_SATA_CFG_20_PORT1_PWB_EN;
673 else
674 config_mask = NV_MCP_SATA_CFG_20_PORT0_EN |
675 NV_MCP_SATA_CFG_20_PORT0_PWB_EN;
Jeff Garzikf20b16f2006-12-11 11:14:06 -0500676
Jeff Garzik2dcb4072007-10-19 06:42:56 -0400677 if (adma_enable) {
Robert Hancock2dec7552006-11-26 14:20:19 -0600678 new_reg = current_reg | config_mask;
679 pp->flags &= ~NV_ADMA_ATAPI_SETUP_COMPLETE;
Jeff Garzik2dcb4072007-10-19 06:42:56 -0400680 } else {
Robert Hancock2dec7552006-11-26 14:20:19 -0600681 new_reg = current_reg & ~config_mask;
682 pp->flags |= NV_ADMA_ATAPI_SETUP_COMPLETE;
683 }
Jeff Garzikf20b16f2006-12-11 11:14:06 -0500684
Jeff Garzik2dcb4072007-10-19 06:42:56 -0400685 if (current_reg != new_reg)
Robert Hancock2dec7552006-11-26 14:20:19 -0600686 pci_write_config_dword(pdev, NV_MCP_SATA_CFG_20, new_reg);
Jeff Garzikf20b16f2006-12-11 11:14:06 -0500687
Robert Hancock8959d302008-02-04 19:39:02 -0600688 port0 = ap->host->ports[0]->private_data;
689 port1 = ap->host->ports[1]->private_data;
690 sdev0 = ap->host->ports[0]->link.device[0].sdev;
691 sdev1 = ap->host->ports[1]->link.device[0].sdev;
692 if ((port0->flags & NV_ADMA_ATAPI_SETUP_COMPLETE) ||
693 (port1->flags & NV_ADMA_ATAPI_SETUP_COMPLETE)) {
694 /** We have to set the DMA mask to 32-bit if either port is in
695 ATAPI mode, since they are on the same PCI device which is
696 used for DMA mapping. If we set the mask we also need to set
697 the bounce limit on both ports to ensure that the block
698 layer doesn't feed addresses that cause DMA mapping to
699 choke. If either SCSI device is not allocated yet, it's OK
700 since that port will discover its correct setting when it
701 does get allocated.
702 Note: Setting 32-bit mask should not fail. */
703 if (sdev0)
704 blk_queue_bounce_limit(sdev0->request_queue,
705 ATA_DMA_MASK);
706 if (sdev1)
707 blk_queue_bounce_limit(sdev1->request_queue,
708 ATA_DMA_MASK);
709
710 pci_set_dma_mask(pdev, ATA_DMA_MASK);
711 } else {
712 /** This shouldn't fail as it was set to this value before */
713 pci_set_dma_mask(pdev, pp->adma_dma_mask);
714 if (sdev0)
715 blk_queue_bounce_limit(sdev0->request_queue,
716 pp->adma_dma_mask);
717 if (sdev1)
718 blk_queue_bounce_limit(sdev1->request_queue,
719 pp->adma_dma_mask);
720 }
721
Robert Hancockfbbb2622006-10-27 19:08:41 -0700722 blk_queue_segment_boundary(sdev->request_queue, segment_boundary);
723 blk_queue_max_hw_segments(sdev->request_queue, sg_tablesize);
724 ata_port_printk(ap, KERN_INFO,
Robert Hancock8959d302008-02-04 19:39:02 -0600725 "DMA mask 0x%llX, segment boundary 0x%lX, hw segs %hu\n",
726 (unsigned long long)*ap->host->dev->dma_mask,
727 segment_boundary, sg_tablesize);
728
729 spin_unlock_irqrestore(ap->lock, flags);
730
Robert Hancockfbbb2622006-10-27 19:08:41 -0700731 return rc;
732}
733
Robert Hancock2dec7552006-11-26 14:20:19 -0600734static int nv_adma_check_atapi_dma(struct ata_queued_cmd *qc)
735{
736 struct nv_adma_port_priv *pp = qc->ap->private_data;
737 return !(pp->flags & NV_ADMA_ATAPI_SETUP_COMPLETE);
738}
739
Robert Hancockf2fb3442007-03-26 21:43:36 -0800740static void nv_adma_tf_read(struct ata_port *ap, struct ata_taskfile *tf)
741{
Robert Hancock3f3debd2007-11-25 16:59:36 -0600742 /* Other than when internal or pass-through commands are executed,
743 the only time this function will be called in ADMA mode will be
744 if a command fails. In the failure case we don't care about going
745 into register mode with ADMA commands pending, as the commands will
746 all shortly be aborted anyway. We assume that NCQ commands are not
747 issued via passthrough, which is the only way that switching into
748 ADMA mode could abort outstanding commands. */
Robert Hancockf2fb3442007-03-26 21:43:36 -0800749 nv_adma_register_mode(ap);
750
Tejun Heo9363c382008-04-07 22:47:16 +0900751 ata_sff_tf_read(ap, tf);
Robert Hancockf2fb3442007-03-26 21:43:36 -0800752}
753
Robert Hancock2dec7552006-11-26 14:20:19 -0600754static unsigned int nv_adma_tf_to_cpb(struct ata_taskfile *tf, __le16 *cpb)
Robert Hancockfbbb2622006-10-27 19:08:41 -0700755{
756 unsigned int idx = 0;
757
Jeff Garzik2dcb4072007-10-19 06:42:56 -0400758 if (tf->flags & ATA_TFLAG_ISADDR) {
Robert Hancockac3d6b82007-02-19 19:02:46 -0600759 if (tf->flags & ATA_TFLAG_LBA48) {
760 cpb[idx++] = cpu_to_le16((ATA_REG_ERR << 8) | tf->hob_feature | WNB);
761 cpb[idx++] = cpu_to_le16((ATA_REG_NSECT << 8) | tf->hob_nsect);
762 cpb[idx++] = cpu_to_le16((ATA_REG_LBAL << 8) | tf->hob_lbal);
763 cpb[idx++] = cpu_to_le16((ATA_REG_LBAM << 8) | tf->hob_lbam);
764 cpb[idx++] = cpu_to_le16((ATA_REG_LBAH << 8) | tf->hob_lbah);
765 cpb[idx++] = cpu_to_le16((ATA_REG_ERR << 8) | tf->feature);
766 } else
767 cpb[idx++] = cpu_to_le16((ATA_REG_ERR << 8) | tf->feature | WNB);
Jeff Garzika84471f2007-02-26 05:51:33 -0500768
Robert Hancockac3d6b82007-02-19 19:02:46 -0600769 cpb[idx++] = cpu_to_le16((ATA_REG_NSECT << 8) | tf->nsect);
770 cpb[idx++] = cpu_to_le16((ATA_REG_LBAL << 8) | tf->lbal);
771 cpb[idx++] = cpu_to_le16((ATA_REG_LBAM << 8) | tf->lbam);
772 cpb[idx++] = cpu_to_le16((ATA_REG_LBAH << 8) | tf->lbah);
Robert Hancockfbbb2622006-10-27 19:08:41 -0700773 }
Jeff Garzika84471f2007-02-26 05:51:33 -0500774
Jeff Garzik2dcb4072007-10-19 06:42:56 -0400775 if (tf->flags & ATA_TFLAG_DEVICE)
Robert Hancockac3d6b82007-02-19 19:02:46 -0600776 cpb[idx++] = cpu_to_le16((ATA_REG_DEVICE << 8) | tf->device);
Robert Hancockfbbb2622006-10-27 19:08:41 -0700777
778 cpb[idx++] = cpu_to_le16((ATA_REG_CMD << 8) | tf->command | CMDEND);
Jeff Garzika84471f2007-02-26 05:51:33 -0500779
Jeff Garzik2dcb4072007-10-19 06:42:56 -0400780 while (idx < 12)
Robert Hancockac3d6b82007-02-19 19:02:46 -0600781 cpb[idx++] = cpu_to_le16(IGN);
Robert Hancockfbbb2622006-10-27 19:08:41 -0700782
783 return idx;
784}
785
Robert Hancock5bd28a42007-02-05 16:26:01 -0800786static int nv_adma_check_cpb(struct ata_port *ap, int cpb_num, int force_err)
Robert Hancockfbbb2622006-10-27 19:08:41 -0700787{
788 struct nv_adma_port_priv *pp = ap->private_data;
Robert Hancock2dec7552006-11-26 14:20:19 -0600789 u8 flags = pp->cpb[cpb_num].resp_flags;
Robert Hancockfbbb2622006-10-27 19:08:41 -0700790
791 VPRINTK("CPB %d, flags=0x%x\n", cpb_num, flags);
792
Robert Hancock5bd28a42007-02-05 16:26:01 -0800793 if (unlikely((force_err ||
794 flags & (NV_CPB_RESP_ATA_ERR |
795 NV_CPB_RESP_CMD_ERR |
796 NV_CPB_RESP_CPB_ERR)))) {
Tejun Heo9af5c9c2007-08-06 18:36:22 +0900797 struct ata_eh_info *ehi = &ap->link.eh_info;
Robert Hancock5bd28a42007-02-05 16:26:01 -0800798 int freeze = 0;
799
800 ata_ehi_clear_desc(ehi);
Jeff Garzik2dcb4072007-10-19 06:42:56 -0400801 __ata_ehi_push_desc(ehi, "CPB resp_flags 0x%x: ", flags);
Robert Hancock5bd28a42007-02-05 16:26:01 -0800802 if (flags & NV_CPB_RESP_ATA_ERR) {
Tejun Heob64bbc32007-07-16 14:29:39 +0900803 ata_ehi_push_desc(ehi, "ATA error");
Robert Hancock5bd28a42007-02-05 16:26:01 -0800804 ehi->err_mask |= AC_ERR_DEV;
805 } else if (flags & NV_CPB_RESP_CMD_ERR) {
Tejun Heob64bbc32007-07-16 14:29:39 +0900806 ata_ehi_push_desc(ehi, "CMD error");
Robert Hancock5bd28a42007-02-05 16:26:01 -0800807 ehi->err_mask |= AC_ERR_DEV;
808 } else if (flags & NV_CPB_RESP_CPB_ERR) {
Tejun Heob64bbc32007-07-16 14:29:39 +0900809 ata_ehi_push_desc(ehi, "CPB error");
Robert Hancock5bd28a42007-02-05 16:26:01 -0800810 ehi->err_mask |= AC_ERR_SYSTEM;
811 freeze = 1;
812 } else {
813 /* notifier error, but no error in CPB flags? */
Tejun Heob64bbc32007-07-16 14:29:39 +0900814 ata_ehi_push_desc(ehi, "unknown");
Robert Hancock5bd28a42007-02-05 16:26:01 -0800815 ehi->err_mask |= AC_ERR_OTHER;
816 freeze = 1;
817 }
818 /* Kill all commands. EH will determine what actually failed. */
819 if (freeze)
820 ata_port_freeze(ap);
821 else
822 ata_port_abort(ap);
823 return 1;
824 }
825
Robert Hancockf2fb3442007-03-26 21:43:36 -0800826 if (likely(flags & NV_CPB_RESP_DONE)) {
Robert Hancockfbbb2622006-10-27 19:08:41 -0700827 struct ata_queued_cmd *qc = ata_qc_from_tag(ap, cpb_num);
Robert Hancock5bd28a42007-02-05 16:26:01 -0800828 VPRINTK("CPB flags done, flags=0x%x\n", flags);
829 if (likely(qc)) {
Jeff Garzik2dcb4072007-10-19 06:42:56 -0400830 DPRINTK("Completing qc from tag %d\n", cpb_num);
Robert Hancockfbbb2622006-10-27 19:08:41 -0700831 ata_qc_complete(qc);
Robert Hancock2a54cf72007-02-21 23:53:03 -0600832 } else {
Tejun Heo9af5c9c2007-08-06 18:36:22 +0900833 struct ata_eh_info *ehi = &ap->link.eh_info;
Robert Hancock2a54cf72007-02-21 23:53:03 -0600834 /* Notifier bits set without a command may indicate the drive
835 is misbehaving. Raise host state machine violation on this
836 condition. */
Jeff Garzik5796d1c2007-10-26 00:03:37 -0400837 ata_port_printk(ap, KERN_ERR,
838 "notifier for tag %d with no cmd?\n",
839 cpb_num);
Robert Hancock2a54cf72007-02-21 23:53:03 -0600840 ehi->err_mask |= AC_ERR_HSM;
Tejun Heocf480622008-01-24 00:05:14 +0900841 ehi->action |= ATA_EH_RESET;
Robert Hancock2a54cf72007-02-21 23:53:03 -0600842 ata_port_freeze(ap);
843 return 1;
Robert Hancockfbbb2622006-10-27 19:08:41 -0700844 }
845 }
Robert Hancock5bd28a42007-02-05 16:26:01 -0800846 return 0;
Robert Hancockfbbb2622006-10-27 19:08:41 -0700847}
848
Robert Hancock2dec7552006-11-26 14:20:19 -0600849static int nv_host_intr(struct ata_port *ap, u8 irq_stat)
850{
Tejun Heo9af5c9c2007-08-06 18:36:22 +0900851 struct ata_queued_cmd *qc = ata_qc_from_tag(ap, ap->link.active_tag);
Robert Hancock2dec7552006-11-26 14:20:19 -0600852
853 /* freeze if hotplugged */
854 if (unlikely(irq_stat & (NV_INT_ADDED | NV_INT_REMOVED))) {
855 ata_port_freeze(ap);
856 return 1;
857 }
858
859 /* bail out if not our interrupt */
860 if (!(irq_stat & NV_INT_DEV))
861 return 0;
862
863 /* DEV interrupt w/ no active qc? */
864 if (unlikely(!qc || (qc->tf.flags & ATA_TFLAG_POLLING))) {
Tejun Heo9363c382008-04-07 22:47:16 +0900865 ata_sff_check_status(ap);
Robert Hancock2dec7552006-11-26 14:20:19 -0600866 return 1;
867 }
868
869 /* handle interrupt */
Tejun Heo9363c382008-04-07 22:47:16 +0900870 return ata_sff_host_intr(ap, qc);
Robert Hancock2dec7552006-11-26 14:20:19 -0600871}
872
Robert Hancockfbbb2622006-10-27 19:08:41 -0700873static irqreturn_t nv_adma_interrupt(int irq, void *dev_instance)
874{
875 struct ata_host *host = dev_instance;
876 int i, handled = 0;
Robert Hancock2dec7552006-11-26 14:20:19 -0600877 u32 notifier_clears[2];
Robert Hancockfbbb2622006-10-27 19:08:41 -0700878
879 spin_lock(&host->lock);
880
881 for (i = 0; i < host->n_ports; i++) {
882 struct ata_port *ap = host->ports[i];
Robert Hancock2dec7552006-11-26 14:20:19 -0600883 notifier_clears[i] = 0;
Robert Hancockfbbb2622006-10-27 19:08:41 -0700884
885 if (ap && !(ap->flags & ATA_FLAG_DISABLED)) {
886 struct nv_adma_port_priv *pp = ap->private_data;
Robert Hancockcdf56bc2007-01-03 18:13:57 -0600887 void __iomem *mmio = pp->ctl_block;
Robert Hancockfbbb2622006-10-27 19:08:41 -0700888 u16 status;
889 u32 gen_ctl;
Robert Hancockfbbb2622006-10-27 19:08:41 -0700890 u32 notifier, notifier_error;
Jeff Garzika617c092007-05-21 20:14:23 -0400891
Robert Hancock53014e22007-05-05 15:36:36 -0600892 /* if ADMA is disabled, use standard ata interrupt handler */
893 if (pp->flags & NV_ADMA_ATAPI_SETUP_COMPLETE) {
894 u8 irq_stat = readb(host->iomap[NV_MMIO_BAR] + NV_INT_STATUS_CK804)
895 >> (NV_INT_PORT_SHIFT * i);
896 handled += nv_host_intr(ap, irq_stat);
897 continue;
898 }
Robert Hancockfbbb2622006-10-27 19:08:41 -0700899
Robert Hancock53014e22007-05-05 15:36:36 -0600900 /* if in ATA register mode, check for standard interrupts */
Robert Hancockfbbb2622006-10-27 19:08:41 -0700901 if (pp->flags & NV_ADMA_PORT_REGISTER_MODE) {
Tejun Heo0d5ff562007-02-01 15:06:36 +0900902 u8 irq_stat = readb(host->iomap[NV_MMIO_BAR] + NV_INT_STATUS_CK804)
Robert Hancock2dec7552006-11-26 14:20:19 -0600903 >> (NV_INT_PORT_SHIFT * i);
Jeff Garzik2dcb4072007-10-19 06:42:56 -0400904 if (ata_tag_valid(ap->link.active_tag))
Robert Hancockf740d162007-01-23 20:09:02 -0600905 /** NV_INT_DEV indication seems unreliable at times
906 at least in ADMA mode. Force it on always when a
907 command is active, to prevent losing interrupts. */
908 irq_stat |= NV_INT_DEV;
Robert Hancock2dec7552006-11-26 14:20:19 -0600909 handled += nv_host_intr(ap, irq_stat);
Robert Hancockfbbb2622006-10-27 19:08:41 -0700910 }
911
912 notifier = readl(mmio + NV_ADMA_NOTIFIER);
913 notifier_error = readl(mmio + NV_ADMA_NOTIFIER_ERROR);
Robert Hancock2dec7552006-11-26 14:20:19 -0600914 notifier_clears[i] = notifier | notifier_error;
Robert Hancockfbbb2622006-10-27 19:08:41 -0700915
Robert Hancockcdf56bc2007-01-03 18:13:57 -0600916 gen_ctl = readl(pp->gen_block + NV_ADMA_GEN_CTL);
Robert Hancockfbbb2622006-10-27 19:08:41 -0700917
Jeff Garzik2dcb4072007-10-19 06:42:56 -0400918 if (!NV_ADMA_CHECK_INTR(gen_ctl, ap->port_no) && !notifier &&
Robert Hancockfbbb2622006-10-27 19:08:41 -0700919 !notifier_error)
920 /* Nothing to do */
921 continue;
922
923 status = readw(mmio + NV_ADMA_STAT);
924
925 /* Clear status. Ensure the controller sees the clearing before we start
926 looking at any of the CPB statuses, so that any CPB completions after
927 this point in the handler will raise another interrupt. */
928 writew(status, mmio + NV_ADMA_STAT);
929 readw(mmio + NV_ADMA_STAT); /* flush posted write */
930 rmb();
931
Robert Hancock5bd28a42007-02-05 16:26:01 -0800932 handled++; /* irq handled if we got here */
933
934 /* freeze if hotplugged or controller error */
935 if (unlikely(status & (NV_ADMA_STAT_HOTPLUG |
936 NV_ADMA_STAT_HOTUNPLUG |
Robert Hancock5278b502007-02-11 18:36:56 -0600937 NV_ADMA_STAT_TIMEOUT |
938 NV_ADMA_STAT_SERROR))) {
Tejun Heo9af5c9c2007-08-06 18:36:22 +0900939 struct ata_eh_info *ehi = &ap->link.eh_info;
Robert Hancock5bd28a42007-02-05 16:26:01 -0800940
941 ata_ehi_clear_desc(ehi);
Jeff Garzik2dcb4072007-10-19 06:42:56 -0400942 __ata_ehi_push_desc(ehi, "ADMA status 0x%08x: ", status);
Robert Hancock5bd28a42007-02-05 16:26:01 -0800943 if (status & NV_ADMA_STAT_TIMEOUT) {
944 ehi->err_mask |= AC_ERR_SYSTEM;
Tejun Heob64bbc32007-07-16 14:29:39 +0900945 ata_ehi_push_desc(ehi, "timeout");
Robert Hancock5bd28a42007-02-05 16:26:01 -0800946 } else if (status & NV_ADMA_STAT_HOTPLUG) {
947 ata_ehi_hotplugged(ehi);
Tejun Heob64bbc32007-07-16 14:29:39 +0900948 ata_ehi_push_desc(ehi, "hotplug");
Robert Hancock5bd28a42007-02-05 16:26:01 -0800949 } else if (status & NV_ADMA_STAT_HOTUNPLUG) {
950 ata_ehi_hotplugged(ehi);
Tejun Heob64bbc32007-07-16 14:29:39 +0900951 ata_ehi_push_desc(ehi, "hot unplug");
Robert Hancock5278b502007-02-11 18:36:56 -0600952 } else if (status & NV_ADMA_STAT_SERROR) {
953 /* let libata analyze SError and figure out the cause */
Tejun Heob64bbc32007-07-16 14:29:39 +0900954 ata_ehi_push_desc(ehi, "SError");
955 } else
956 ata_ehi_push_desc(ehi, "unknown");
Robert Hancockfbbb2622006-10-27 19:08:41 -0700957 ata_port_freeze(ap);
Robert Hancockfbbb2622006-10-27 19:08:41 -0700958 continue;
959 }
960
Robert Hancock5bd28a42007-02-05 16:26:01 -0800961 if (status & (NV_ADMA_STAT_DONE |
Robert Hancocka1fe7822008-01-29 19:53:19 -0600962 NV_ADMA_STAT_CPBERR |
963 NV_ADMA_STAT_CMD_COMPLETE)) {
964 u32 check_commands = notifier_clears[i];
Robert Hancock721449b2007-02-19 19:03:08 -0600965 int pos, error = 0;
Robert Hancock8ba5e4c2007-03-08 18:02:18 -0600966
Robert Hancocka1fe7822008-01-29 19:53:19 -0600967 if (status & NV_ADMA_STAT_CPBERR) {
968 /* Check all active commands */
969 if (ata_tag_valid(ap->link.active_tag))
970 check_commands = 1 <<
971 ap->link.active_tag;
972 else
973 check_commands = ap->
974 link.sactive;
975 }
Robert Hancock8ba5e4c2007-03-08 18:02:18 -0600976
Robert Hancockfbbb2622006-10-27 19:08:41 -0700977 /** Check CPBs for completed commands */
Robert Hancock721449b2007-02-19 19:03:08 -0600978 while ((pos = ffs(check_commands)) && !error) {
979 pos--;
980 error = nv_adma_check_cpb(ap, pos,
Jeff Garzik5796d1c2007-10-26 00:03:37 -0400981 notifier_error & (1 << pos));
982 check_commands &= ~(1 << pos);
Robert Hancockfbbb2622006-10-27 19:08:41 -0700983 }
984 }
Robert Hancockfbbb2622006-10-27 19:08:41 -0700985 }
986 }
Jeff Garzikf20b16f2006-12-11 11:14:06 -0500987
Jeff Garzikb4479162007-10-25 20:47:30 -0400988 if (notifier_clears[0] || notifier_clears[1]) {
Robert Hancock2dec7552006-11-26 14:20:19 -0600989 /* Note: Both notifier clear registers must be written
990 if either is set, even if one is zero, according to NVIDIA. */
Robert Hancockcdf56bc2007-01-03 18:13:57 -0600991 struct nv_adma_port_priv *pp = host->ports[0]->private_data;
992 writel(notifier_clears[0], pp->notifier_clear_block);
993 pp = host->ports[1]->private_data;
994 writel(notifier_clears[1], pp->notifier_clear_block);
Robert Hancock2dec7552006-11-26 14:20:19 -0600995 }
Robert Hancockfbbb2622006-10-27 19:08:41 -0700996
997 spin_unlock(&host->lock);
998
999 return IRQ_RETVAL(handled);
1000}
1001
Robert Hancock53014e22007-05-05 15:36:36 -06001002static void nv_adma_freeze(struct ata_port *ap)
1003{
1004 struct nv_adma_port_priv *pp = ap->private_data;
1005 void __iomem *mmio = pp->ctl_block;
1006 u16 tmp;
1007
1008 nv_ck804_freeze(ap);
1009
1010 if (pp->flags & NV_ADMA_ATAPI_SETUP_COMPLETE)
1011 return;
1012
1013 /* clear any outstanding CK804 notifications */
Jeff Garzik2dcb4072007-10-19 06:42:56 -04001014 writeb(NV_INT_ALL << (ap->port_no * NV_INT_PORT_SHIFT),
Robert Hancock53014e22007-05-05 15:36:36 -06001015 ap->host->iomap[NV_MMIO_BAR] + NV_INT_STATUS_CK804);
1016
1017 /* Disable interrupt */
1018 tmp = readw(mmio + NV_ADMA_CTL);
Jeff Garzik2dcb4072007-10-19 06:42:56 -04001019 writew(tmp & ~(NV_ADMA_CTL_AIEN | NV_ADMA_CTL_HOTPLUG_IEN),
Robert Hancock53014e22007-05-05 15:36:36 -06001020 mmio + NV_ADMA_CTL);
Jeff Garzik5796d1c2007-10-26 00:03:37 -04001021 readw(mmio + NV_ADMA_CTL); /* flush posted write */
Robert Hancock53014e22007-05-05 15:36:36 -06001022}
1023
1024static void nv_adma_thaw(struct ata_port *ap)
1025{
1026 struct nv_adma_port_priv *pp = ap->private_data;
1027 void __iomem *mmio = pp->ctl_block;
1028 u16 tmp;
1029
1030 nv_ck804_thaw(ap);
1031
1032 if (pp->flags & NV_ADMA_ATAPI_SETUP_COMPLETE)
1033 return;
1034
1035 /* Enable interrupt */
1036 tmp = readw(mmio + NV_ADMA_CTL);
Jeff Garzik2dcb4072007-10-19 06:42:56 -04001037 writew(tmp | (NV_ADMA_CTL_AIEN | NV_ADMA_CTL_HOTPLUG_IEN),
Robert Hancock53014e22007-05-05 15:36:36 -06001038 mmio + NV_ADMA_CTL);
Jeff Garzik5796d1c2007-10-26 00:03:37 -04001039 readw(mmio + NV_ADMA_CTL); /* flush posted write */
Robert Hancock53014e22007-05-05 15:36:36 -06001040}
1041
Robert Hancockfbbb2622006-10-27 19:08:41 -07001042static void nv_adma_irq_clear(struct ata_port *ap)
1043{
Robert Hancockcdf56bc2007-01-03 18:13:57 -06001044 struct nv_adma_port_priv *pp = ap->private_data;
1045 void __iomem *mmio = pp->ctl_block;
Robert Hancock53014e22007-05-05 15:36:36 -06001046 u32 notifier_clears[2];
1047
1048 if (pp->flags & NV_ADMA_ATAPI_SETUP_COMPLETE) {
Tejun Heo9363c382008-04-07 22:47:16 +09001049 ata_sff_irq_clear(ap);
Robert Hancock53014e22007-05-05 15:36:36 -06001050 return;
1051 }
1052
1053 /* clear any outstanding CK804 notifications */
Jeff Garzik2dcb4072007-10-19 06:42:56 -04001054 writeb(NV_INT_ALL << (ap->port_no * NV_INT_PORT_SHIFT),
Robert Hancock53014e22007-05-05 15:36:36 -06001055 ap->host->iomap[NV_MMIO_BAR] + NV_INT_STATUS_CK804);
Robert Hancockfbbb2622006-10-27 19:08:41 -07001056
1057 /* clear ADMA status */
Robert Hancock53014e22007-05-05 15:36:36 -06001058 writew(0xffff, mmio + NV_ADMA_STAT);
Jeff Garzika617c092007-05-21 20:14:23 -04001059
Robert Hancock53014e22007-05-05 15:36:36 -06001060 /* clear notifiers - note both ports need to be written with
1061 something even though we are only clearing on one */
1062 if (ap->port_no == 0) {
1063 notifier_clears[0] = 0xFFFFFFFF;
1064 notifier_clears[1] = 0;
1065 } else {
1066 notifier_clears[0] = 0;
1067 notifier_clears[1] = 0xFFFFFFFF;
1068 }
1069 pp = ap->host->ports[0]->private_data;
1070 writel(notifier_clears[0], pp->notifier_clear_block);
1071 pp = ap->host->ports[1]->private_data;
1072 writel(notifier_clears[1], pp->notifier_clear_block);
Robert Hancockfbbb2622006-10-27 19:08:41 -07001073}
1074
Robert Hancockf5ecac22007-02-20 21:49:10 -06001075static void nv_adma_post_internal_cmd(struct ata_queued_cmd *qc)
Robert Hancockfbbb2622006-10-27 19:08:41 -07001076{
Robert Hancockf5ecac22007-02-20 21:49:10 -06001077 struct nv_adma_port_priv *pp = qc->ap->private_data;
Robert Hancockfbbb2622006-10-27 19:08:41 -07001078
Jeff Garzikb4479162007-10-25 20:47:30 -04001079 if (pp->flags & NV_ADMA_PORT_REGISTER_MODE)
Tejun Heo9363c382008-04-07 22:47:16 +09001080 ata_sff_post_internal_cmd(qc);
Robert Hancockfbbb2622006-10-27 19:08:41 -07001081}
1082
1083static int nv_adma_port_start(struct ata_port *ap)
1084{
1085 struct device *dev = ap->host->dev;
1086 struct nv_adma_port_priv *pp;
1087 int rc;
1088 void *mem;
1089 dma_addr_t mem_dma;
Robert Hancockcdf56bc2007-01-03 18:13:57 -06001090 void __iomem *mmio;
Robert Hancock8959d302008-02-04 19:39:02 -06001091 struct pci_dev *pdev = to_pci_dev(dev);
Robert Hancockfbbb2622006-10-27 19:08:41 -07001092 u16 tmp;
1093
1094 VPRINTK("ENTER\n");
1095
Robert Hancock8959d302008-02-04 19:39:02 -06001096 /* Ensure DMA mask is set to 32-bit before allocating legacy PRD and
1097 pad buffers */
1098 rc = pci_set_dma_mask(pdev, DMA_BIT_MASK(32));
1099 if (rc)
1100 return rc;
1101 rc = pci_set_consistent_dma_mask(pdev, DMA_BIT_MASK(32));
1102 if (rc)
1103 return rc;
1104
Robert Hancockfbbb2622006-10-27 19:08:41 -07001105 rc = ata_port_start(ap);
1106 if (rc)
1107 return rc;
1108
Tejun Heo24dc5f32007-01-20 16:00:28 +09001109 pp = devm_kzalloc(dev, sizeof(*pp), GFP_KERNEL);
1110 if (!pp)
1111 return -ENOMEM;
Robert Hancockfbbb2622006-10-27 19:08:41 -07001112
Tejun Heo0d5ff562007-02-01 15:06:36 +09001113 mmio = ap->host->iomap[NV_MMIO_BAR] + NV_ADMA_PORT +
Robert Hancockcdf56bc2007-01-03 18:13:57 -06001114 ap->port_no * NV_ADMA_PORT_SIZE;
1115 pp->ctl_block = mmio;
Tejun Heo0d5ff562007-02-01 15:06:36 +09001116 pp->gen_block = ap->host->iomap[NV_MMIO_BAR] + NV_ADMA_GEN;
Robert Hancockcdf56bc2007-01-03 18:13:57 -06001117 pp->notifier_clear_block = pp->gen_block +
1118 NV_ADMA_NOTIFIER_CLEAR + (4 * ap->port_no);
1119
Robert Hancock8959d302008-02-04 19:39:02 -06001120 /* Now that the legacy PRD and padding buffer are allocated we can
1121 safely raise the DMA mask to allocate the CPB/APRD table.
1122 These are allowed to fail since we store the value that ends up
1123 being used to set as the bounce limit in slave_config later if
1124 needed. */
1125 pci_set_dma_mask(pdev, DMA_BIT_MASK(64));
1126 pci_set_consistent_dma_mask(pdev, DMA_BIT_MASK(64));
1127 pp->adma_dma_mask = *dev->dma_mask;
1128
Tejun Heo24dc5f32007-01-20 16:00:28 +09001129 mem = dmam_alloc_coherent(dev, NV_ADMA_PORT_PRIV_DMA_SZ,
1130 &mem_dma, GFP_KERNEL);
1131 if (!mem)
1132 return -ENOMEM;
Robert Hancockfbbb2622006-10-27 19:08:41 -07001133 memset(mem, 0, NV_ADMA_PORT_PRIV_DMA_SZ);
1134
1135 /*
1136 * First item in chunk of DMA memory:
1137 * 128-byte command parameter block (CPB)
1138 * one for each command tag
1139 */
1140 pp->cpb = mem;
1141 pp->cpb_dma = mem_dma;
1142
1143 writel(mem_dma & 0xFFFFFFFF, mmio + NV_ADMA_CPB_BASE_LOW);
Jeff Garzik5796d1c2007-10-26 00:03:37 -04001144 writel((mem_dma >> 16) >> 16, mmio + NV_ADMA_CPB_BASE_HIGH);
Robert Hancockfbbb2622006-10-27 19:08:41 -07001145
1146 mem += NV_ADMA_MAX_CPBS * NV_ADMA_CPB_SZ;
1147 mem_dma += NV_ADMA_MAX_CPBS * NV_ADMA_CPB_SZ;
1148
1149 /*
1150 * Second item: block of ADMA_SGTBL_LEN s/g entries
1151 */
1152 pp->aprd = mem;
1153 pp->aprd_dma = mem_dma;
1154
1155 ap->private_data = pp;
1156
1157 /* clear any outstanding interrupt conditions */
1158 writew(0xffff, mmio + NV_ADMA_STAT);
1159
1160 /* initialize port variables */
1161 pp->flags = NV_ADMA_PORT_REGISTER_MODE;
1162
1163 /* clear CPB fetch count */
1164 writew(0, mmio + NV_ADMA_CPB_COUNT);
1165
Robert Hancockcdf56bc2007-01-03 18:13:57 -06001166 /* clear GO for register mode, enable interrupt */
Robert Hancockfbbb2622006-10-27 19:08:41 -07001167 tmp = readw(mmio + NV_ADMA_CTL);
Jeff Garzik5796d1c2007-10-26 00:03:37 -04001168 writew((tmp & ~NV_ADMA_CTL_GO) | NV_ADMA_CTL_AIEN |
1169 NV_ADMA_CTL_HOTPLUG_IEN, mmio + NV_ADMA_CTL);
Robert Hancockfbbb2622006-10-27 19:08:41 -07001170
1171 tmp = readw(mmio + NV_ADMA_CTL);
1172 writew(tmp | NV_ADMA_CTL_CHANNEL_RESET, mmio + NV_ADMA_CTL);
Jeff Garzik5796d1c2007-10-26 00:03:37 -04001173 readw(mmio + NV_ADMA_CTL); /* flush posted write */
Robert Hancockfbbb2622006-10-27 19:08:41 -07001174 udelay(1);
1175 writew(tmp & ~NV_ADMA_CTL_CHANNEL_RESET, mmio + NV_ADMA_CTL);
Jeff Garzik5796d1c2007-10-26 00:03:37 -04001176 readw(mmio + NV_ADMA_CTL); /* flush posted write */
Robert Hancockfbbb2622006-10-27 19:08:41 -07001177
1178 return 0;
Robert Hancockfbbb2622006-10-27 19:08:41 -07001179}
1180
1181static void nv_adma_port_stop(struct ata_port *ap)
1182{
Robert Hancockfbbb2622006-10-27 19:08:41 -07001183 struct nv_adma_port_priv *pp = ap->private_data;
Robert Hancockcdf56bc2007-01-03 18:13:57 -06001184 void __iomem *mmio = pp->ctl_block;
Robert Hancockfbbb2622006-10-27 19:08:41 -07001185
1186 VPRINTK("ENTER\n");
Robert Hancockfbbb2622006-10-27 19:08:41 -07001187 writew(0, mmio + NV_ADMA_CTL);
Robert Hancockfbbb2622006-10-27 19:08:41 -07001188}
1189
Tejun Heo438ac6d2007-03-02 17:31:26 +09001190#ifdef CONFIG_PM
Robert Hancockcdf56bc2007-01-03 18:13:57 -06001191static int nv_adma_port_suspend(struct ata_port *ap, pm_message_t mesg)
1192{
1193 struct nv_adma_port_priv *pp = ap->private_data;
1194 void __iomem *mmio = pp->ctl_block;
1195
1196 /* Go to register mode - clears GO */
1197 nv_adma_register_mode(ap);
1198
1199 /* clear CPB fetch count */
1200 writew(0, mmio + NV_ADMA_CPB_COUNT);
1201
1202 /* disable interrupt, shut down port */
1203 writew(0, mmio + NV_ADMA_CTL);
1204
1205 return 0;
1206}
1207
1208static int nv_adma_port_resume(struct ata_port *ap)
1209{
1210 struct nv_adma_port_priv *pp = ap->private_data;
1211 void __iomem *mmio = pp->ctl_block;
1212 u16 tmp;
1213
1214 /* set CPB block location */
1215 writel(pp->cpb_dma & 0xFFFFFFFF, mmio + NV_ADMA_CPB_BASE_LOW);
Jeff Garzik5796d1c2007-10-26 00:03:37 -04001216 writel((pp->cpb_dma >> 16) >> 16, mmio + NV_ADMA_CPB_BASE_HIGH);
Robert Hancockcdf56bc2007-01-03 18:13:57 -06001217
1218 /* clear any outstanding interrupt conditions */
1219 writew(0xffff, mmio + NV_ADMA_STAT);
1220
1221 /* initialize port variables */
1222 pp->flags |= NV_ADMA_PORT_REGISTER_MODE;
1223
1224 /* clear CPB fetch count */
1225 writew(0, mmio + NV_ADMA_CPB_COUNT);
1226
1227 /* clear GO for register mode, enable interrupt */
1228 tmp = readw(mmio + NV_ADMA_CTL);
Jeff Garzik5796d1c2007-10-26 00:03:37 -04001229 writew((tmp & ~NV_ADMA_CTL_GO) | NV_ADMA_CTL_AIEN |
1230 NV_ADMA_CTL_HOTPLUG_IEN, mmio + NV_ADMA_CTL);
Robert Hancockcdf56bc2007-01-03 18:13:57 -06001231
1232 tmp = readw(mmio + NV_ADMA_CTL);
1233 writew(tmp | NV_ADMA_CTL_CHANNEL_RESET, mmio + NV_ADMA_CTL);
Jeff Garzik5796d1c2007-10-26 00:03:37 -04001234 readw(mmio + NV_ADMA_CTL); /* flush posted write */
Robert Hancockcdf56bc2007-01-03 18:13:57 -06001235 udelay(1);
1236 writew(tmp & ~NV_ADMA_CTL_CHANNEL_RESET, mmio + NV_ADMA_CTL);
Jeff Garzik5796d1c2007-10-26 00:03:37 -04001237 readw(mmio + NV_ADMA_CTL); /* flush posted write */
Robert Hancockcdf56bc2007-01-03 18:13:57 -06001238
1239 return 0;
1240}
Tejun Heo438ac6d2007-03-02 17:31:26 +09001241#endif
Robert Hancockfbbb2622006-10-27 19:08:41 -07001242
Tejun Heo9a829cc2007-04-17 23:44:08 +09001243static void nv_adma_setup_port(struct ata_port *ap)
Robert Hancockfbbb2622006-10-27 19:08:41 -07001244{
Tejun Heo9a829cc2007-04-17 23:44:08 +09001245 void __iomem *mmio = ap->host->iomap[NV_MMIO_BAR];
1246 struct ata_ioports *ioport = &ap->ioaddr;
Robert Hancockfbbb2622006-10-27 19:08:41 -07001247
1248 VPRINTK("ENTER\n");
1249
Tejun Heo9a829cc2007-04-17 23:44:08 +09001250 mmio += NV_ADMA_PORT + ap->port_no * NV_ADMA_PORT_SIZE;
Robert Hancockfbbb2622006-10-27 19:08:41 -07001251
Tejun Heo0d5ff562007-02-01 15:06:36 +09001252 ioport->cmd_addr = mmio;
1253 ioport->data_addr = mmio + (ATA_REG_DATA * 4);
Robert Hancockfbbb2622006-10-27 19:08:41 -07001254 ioport->error_addr =
Tejun Heo0d5ff562007-02-01 15:06:36 +09001255 ioport->feature_addr = mmio + (ATA_REG_ERR * 4);
1256 ioport->nsect_addr = mmio + (ATA_REG_NSECT * 4);
1257 ioport->lbal_addr = mmio + (ATA_REG_LBAL * 4);
1258 ioport->lbam_addr = mmio + (ATA_REG_LBAM * 4);
1259 ioport->lbah_addr = mmio + (ATA_REG_LBAH * 4);
1260 ioport->device_addr = mmio + (ATA_REG_DEVICE * 4);
Robert Hancockfbbb2622006-10-27 19:08:41 -07001261 ioport->status_addr =
Tejun Heo0d5ff562007-02-01 15:06:36 +09001262 ioport->command_addr = mmio + (ATA_REG_STATUS * 4);
Robert Hancockfbbb2622006-10-27 19:08:41 -07001263 ioport->altstatus_addr =
Tejun Heo0d5ff562007-02-01 15:06:36 +09001264 ioport->ctl_addr = mmio + 0x20;
Robert Hancockfbbb2622006-10-27 19:08:41 -07001265}
1266
Tejun Heo9a829cc2007-04-17 23:44:08 +09001267static int nv_adma_host_init(struct ata_host *host)
Robert Hancockfbbb2622006-10-27 19:08:41 -07001268{
Tejun Heo9a829cc2007-04-17 23:44:08 +09001269 struct pci_dev *pdev = to_pci_dev(host->dev);
Robert Hancockfbbb2622006-10-27 19:08:41 -07001270 unsigned int i;
1271 u32 tmp32;
1272
1273 VPRINTK("ENTER\n");
1274
1275 /* enable ADMA on the ports */
1276 pci_read_config_dword(pdev, NV_MCP_SATA_CFG_20, &tmp32);
1277 tmp32 |= NV_MCP_SATA_CFG_20_PORT0_EN |
1278 NV_MCP_SATA_CFG_20_PORT0_PWB_EN |
1279 NV_MCP_SATA_CFG_20_PORT1_EN |
1280 NV_MCP_SATA_CFG_20_PORT1_PWB_EN;
1281
1282 pci_write_config_dword(pdev, NV_MCP_SATA_CFG_20, tmp32);
1283
Tejun Heo9a829cc2007-04-17 23:44:08 +09001284 for (i = 0; i < host->n_ports; i++)
1285 nv_adma_setup_port(host->ports[i]);
Robert Hancockfbbb2622006-10-27 19:08:41 -07001286
Robert Hancockfbbb2622006-10-27 19:08:41 -07001287 return 0;
1288}
1289
1290static void nv_adma_fill_aprd(struct ata_queued_cmd *qc,
1291 struct scatterlist *sg,
1292 int idx,
1293 struct nv_adma_prd *aprd)
1294{
Robert Hancock41949ed2007-02-19 19:02:27 -06001295 u8 flags = 0;
Robert Hancockfbbb2622006-10-27 19:08:41 -07001296 if (qc->tf.flags & ATA_TFLAG_WRITE)
1297 flags |= NV_APRD_WRITE;
1298 if (idx == qc->n_elem - 1)
1299 flags |= NV_APRD_END;
1300 else if (idx != 4)
1301 flags |= NV_APRD_CONT;
1302
1303 aprd->addr = cpu_to_le64(((u64)sg_dma_address(sg)));
1304 aprd->len = cpu_to_le32(((u32)sg_dma_len(sg))); /* len in bytes */
Robert Hancock2dec7552006-11-26 14:20:19 -06001305 aprd->flags = flags;
Robert Hancock41949ed2007-02-19 19:02:27 -06001306 aprd->packet_len = 0;
Robert Hancockfbbb2622006-10-27 19:08:41 -07001307}
1308
1309static void nv_adma_fill_sg(struct ata_queued_cmd *qc, struct nv_adma_cpb *cpb)
1310{
1311 struct nv_adma_port_priv *pp = qc->ap->private_data;
Robert Hancockfbbb2622006-10-27 19:08:41 -07001312 struct nv_adma_prd *aprd;
1313 struct scatterlist *sg;
Tejun Heoff2aeb12007-12-05 16:43:11 +09001314 unsigned int si;
Robert Hancockfbbb2622006-10-27 19:08:41 -07001315
1316 VPRINTK("ENTER\n");
1317
Tejun Heoff2aeb12007-12-05 16:43:11 +09001318 for_each_sg(qc->sg, sg, qc->n_elem, si) {
1319 aprd = (si < 5) ? &cpb->aprd[si] :
1320 &pp->aprd[NV_ADMA_SGTBL_LEN * qc->tag + (si-5)];
1321 nv_adma_fill_aprd(qc, sg, si, aprd);
Robert Hancockfbbb2622006-10-27 19:08:41 -07001322 }
Tejun Heoff2aeb12007-12-05 16:43:11 +09001323 if (si > 5)
Robert Hancockfbbb2622006-10-27 19:08:41 -07001324 cpb->next_aprd = cpu_to_le64(((u64)(pp->aprd_dma + NV_ADMA_SGTBL_SZ * qc->tag)));
Robert Hancock41949ed2007-02-19 19:02:27 -06001325 else
1326 cpb->next_aprd = cpu_to_le64(0);
Robert Hancockfbbb2622006-10-27 19:08:41 -07001327}
1328
Robert Hancock382a6652007-02-05 16:26:02 -08001329static int nv_adma_use_reg_mode(struct ata_queued_cmd *qc)
1330{
1331 struct nv_adma_port_priv *pp = qc->ap->private_data;
1332
1333 /* ADMA engine can only be used for non-ATAPI DMA commands,
Robert Hancock3f3debd2007-11-25 16:59:36 -06001334 or interrupt-driven no-data commands. */
Jeff Garzikb4479162007-10-25 20:47:30 -04001335 if ((pp->flags & NV_ADMA_ATAPI_SETUP_COMPLETE) ||
Robert Hancock3f3debd2007-11-25 16:59:36 -06001336 (qc->tf.flags & ATA_TFLAG_POLLING))
Robert Hancock382a6652007-02-05 16:26:02 -08001337 return 1;
1338
Jeff Garzikb4479162007-10-25 20:47:30 -04001339 if ((qc->flags & ATA_QCFLAG_DMAMAP) ||
Robert Hancock382a6652007-02-05 16:26:02 -08001340 (qc->tf.protocol == ATA_PROT_NODATA))
1341 return 0;
1342
1343 return 1;
1344}
1345
Robert Hancockfbbb2622006-10-27 19:08:41 -07001346static void nv_adma_qc_prep(struct ata_queued_cmd *qc)
1347{
1348 struct nv_adma_port_priv *pp = qc->ap->private_data;
1349 struct nv_adma_cpb *cpb = &pp->cpb[qc->tag];
1350 u8 ctl_flags = NV_CPB_CTL_CPB_VALID |
Robert Hancockfbbb2622006-10-27 19:08:41 -07001351 NV_CPB_CTL_IEN;
1352
Robert Hancock382a6652007-02-05 16:26:02 -08001353 if (nv_adma_use_reg_mode(qc)) {
Robert Hancock3f3debd2007-11-25 16:59:36 -06001354 BUG_ON(!(pp->flags & NV_ADMA_ATAPI_SETUP_COMPLETE) &&
1355 (qc->flags & ATA_QCFLAG_DMAMAP));
Robert Hancock2dec7552006-11-26 14:20:19 -06001356 nv_adma_register_mode(qc->ap);
Tejun Heo9363c382008-04-07 22:47:16 +09001357 ata_sff_qc_prep(qc);
Robert Hancockfbbb2622006-10-27 19:08:41 -07001358 return;
1359 }
1360
Robert Hancock41949ed2007-02-19 19:02:27 -06001361 cpb->resp_flags = NV_CPB_RESP_DONE;
1362 wmb();
1363 cpb->ctl_flags = 0;
1364 wmb();
Robert Hancockfbbb2622006-10-27 19:08:41 -07001365
1366 cpb->len = 3;
1367 cpb->tag = qc->tag;
1368 cpb->next_cpb_idx = 0;
1369
1370 /* turn on NCQ flags for NCQ commands */
1371 if (qc->tf.protocol == ATA_PROT_NCQ)
1372 ctl_flags |= NV_CPB_CTL_QUEUE | NV_CPB_CTL_FPDMA;
1373
Robert Hancockcdf56bc2007-01-03 18:13:57 -06001374 VPRINTK("qc->flags = 0x%lx\n", qc->flags);
1375
Robert Hancockfbbb2622006-10-27 19:08:41 -07001376 nv_adma_tf_to_cpb(&qc->tf, cpb->tf);
1377
Jeff Garzikb4479162007-10-25 20:47:30 -04001378 if (qc->flags & ATA_QCFLAG_DMAMAP) {
Robert Hancock382a6652007-02-05 16:26:02 -08001379 nv_adma_fill_sg(qc, cpb);
1380 ctl_flags |= NV_CPB_CTL_APRD_VALID;
1381 } else
1382 memset(&cpb->aprd[0], 0, sizeof(struct nv_adma_prd) * 5);
Robert Hancockfbbb2622006-10-27 19:08:41 -07001383
Jeff Garzik5796d1c2007-10-26 00:03:37 -04001384 /* Be paranoid and don't let the device see NV_CPB_CTL_CPB_VALID
1385 until we are finished filling in all of the contents */
Robert Hancockfbbb2622006-10-27 19:08:41 -07001386 wmb();
1387 cpb->ctl_flags = ctl_flags;
Robert Hancock41949ed2007-02-19 19:02:27 -06001388 wmb();
1389 cpb->resp_flags = 0;
Robert Hancockfbbb2622006-10-27 19:08:41 -07001390}
1391
1392static unsigned int nv_adma_qc_issue(struct ata_queued_cmd *qc)
1393{
Robert Hancock2dec7552006-11-26 14:20:19 -06001394 struct nv_adma_port_priv *pp = qc->ap->private_data;
Robert Hancockcdf56bc2007-01-03 18:13:57 -06001395 void __iomem *mmio = pp->ctl_block;
Robert Hancock5e5c74a2007-02-19 18:42:30 -06001396 int curr_ncq = (qc->tf.protocol == ATA_PROT_NCQ);
Robert Hancockfbbb2622006-10-27 19:08:41 -07001397
1398 VPRINTK("ENTER\n");
1399
Robert Hancock3f3debd2007-11-25 16:59:36 -06001400 /* We can't handle result taskfile with NCQ commands, since
1401 retrieving the taskfile switches us out of ADMA mode and would abort
1402 existing commands. */
1403 if (unlikely(qc->tf.protocol == ATA_PROT_NCQ &&
1404 (qc->flags & ATA_QCFLAG_RESULT_TF))) {
1405 ata_dev_printk(qc->dev, KERN_ERR,
1406 "NCQ w/ RESULT_TF not allowed\n");
1407 return AC_ERR_SYSTEM;
1408 }
1409
Robert Hancock382a6652007-02-05 16:26:02 -08001410 if (nv_adma_use_reg_mode(qc)) {
Robert Hancockfbbb2622006-10-27 19:08:41 -07001411 /* use ATA register mode */
Robert Hancock382a6652007-02-05 16:26:02 -08001412 VPRINTK("using ATA register mode: 0x%lx\n", qc->flags);
Robert Hancock3f3debd2007-11-25 16:59:36 -06001413 BUG_ON(!(pp->flags & NV_ADMA_ATAPI_SETUP_COMPLETE) &&
1414 (qc->flags & ATA_QCFLAG_DMAMAP));
Robert Hancockfbbb2622006-10-27 19:08:41 -07001415 nv_adma_register_mode(qc->ap);
Tejun Heo9363c382008-04-07 22:47:16 +09001416 return ata_sff_qc_issue(qc);
Robert Hancockfbbb2622006-10-27 19:08:41 -07001417 } else
1418 nv_adma_mode(qc->ap);
1419
1420 /* write append register, command tag in lower 8 bits
1421 and (number of cpbs to append -1) in top 8 bits */
1422 wmb();
Robert Hancock5e5c74a2007-02-19 18:42:30 -06001423
Jeff Garzikb4479162007-10-25 20:47:30 -04001424 if (curr_ncq != pp->last_issue_ncq) {
Jeff Garzik5796d1c2007-10-26 00:03:37 -04001425 /* Seems to need some delay before switching between NCQ and
1426 non-NCQ commands, else we get command timeouts and such. */
Robert Hancock5e5c74a2007-02-19 18:42:30 -06001427 udelay(20);
1428 pp->last_issue_ncq = curr_ncq;
1429 }
1430
Robert Hancockfbbb2622006-10-27 19:08:41 -07001431 writew(qc->tag, mmio + NV_ADMA_APPEND);
1432
Jeff Garzik5796d1c2007-10-26 00:03:37 -04001433 DPRINTK("Issued tag %u\n", qc->tag);
Robert Hancockfbbb2622006-10-27 19:08:41 -07001434
1435 return 0;
1436}
1437
David Howells7d12e782006-10-05 14:55:46 +01001438static irqreturn_t nv_generic_interrupt(int irq, void *dev_instance)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001439{
Jeff Garzikcca39742006-08-24 03:19:22 -04001440 struct ata_host *host = dev_instance;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001441 unsigned int i;
1442 unsigned int handled = 0;
1443 unsigned long flags;
1444
Jeff Garzikcca39742006-08-24 03:19:22 -04001445 spin_lock_irqsave(&host->lock, flags);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001446
Jeff Garzikcca39742006-08-24 03:19:22 -04001447 for (i = 0; i < host->n_ports; i++) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07001448 struct ata_port *ap;
1449
Jeff Garzikcca39742006-08-24 03:19:22 -04001450 ap = host->ports[i];
Tejun Heoc1389502005-08-22 14:59:24 +09001451 if (ap &&
Jeff Garzik029f5462006-04-02 10:30:40 -04001452 !(ap->flags & ATA_FLAG_DISABLED)) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07001453 struct ata_queued_cmd *qc;
1454
Tejun Heo9af5c9c2007-08-06 18:36:22 +09001455 qc = ata_qc_from_tag(ap, ap->link.active_tag);
Albert Leee50362e2005-09-27 17:39:50 +08001456 if (qc && (!(qc->tf.flags & ATA_TFLAG_POLLING)))
Tejun Heo9363c382008-04-07 22:47:16 +09001457 handled += ata_sff_host_intr(ap, qc);
Andrew Chewb8870302006-01-04 19:13:04 -08001458 else
1459 // No request pending? Clear interrupt status
1460 // anyway, in case there's one pending.
Tejun Heo5682ed32008-04-07 22:47:16 +09001461 ap->ops->sff_check_status(ap);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001462 }
1463
1464 }
1465
Jeff Garzikcca39742006-08-24 03:19:22 -04001466 spin_unlock_irqrestore(&host->lock, flags);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001467
1468 return IRQ_RETVAL(handled);
1469}
1470
Jeff Garzikcca39742006-08-24 03:19:22 -04001471static irqreturn_t nv_do_interrupt(struct ata_host *host, u8 irq_stat)
Tejun Heoada364e2006-06-17 15:49:56 +09001472{
1473 int i, handled = 0;
1474
Jeff Garzikcca39742006-08-24 03:19:22 -04001475 for (i = 0; i < host->n_ports; i++) {
1476 struct ata_port *ap = host->ports[i];
Tejun Heoada364e2006-06-17 15:49:56 +09001477
1478 if (ap && !(ap->flags & ATA_FLAG_DISABLED))
1479 handled += nv_host_intr(ap, irq_stat);
1480
1481 irq_stat >>= NV_INT_PORT_SHIFT;
1482 }
1483
1484 return IRQ_RETVAL(handled);
1485}
1486
David Howells7d12e782006-10-05 14:55:46 +01001487static irqreturn_t nv_nf2_interrupt(int irq, void *dev_instance)
Tejun Heoada364e2006-06-17 15:49:56 +09001488{
Jeff Garzikcca39742006-08-24 03:19:22 -04001489 struct ata_host *host = dev_instance;
Tejun Heoada364e2006-06-17 15:49:56 +09001490 u8 irq_stat;
1491 irqreturn_t ret;
1492
Jeff Garzikcca39742006-08-24 03:19:22 -04001493 spin_lock(&host->lock);
Tejun Heo0d5ff562007-02-01 15:06:36 +09001494 irq_stat = ioread8(host->ports[0]->ioaddr.scr_addr + NV_INT_STATUS);
Jeff Garzikcca39742006-08-24 03:19:22 -04001495 ret = nv_do_interrupt(host, irq_stat);
1496 spin_unlock(&host->lock);
Tejun Heoada364e2006-06-17 15:49:56 +09001497
1498 return ret;
1499}
1500
David Howells7d12e782006-10-05 14:55:46 +01001501static irqreturn_t nv_ck804_interrupt(int irq, void *dev_instance)
Tejun Heoada364e2006-06-17 15:49:56 +09001502{
Jeff Garzikcca39742006-08-24 03:19:22 -04001503 struct ata_host *host = dev_instance;
Tejun Heoada364e2006-06-17 15:49:56 +09001504 u8 irq_stat;
1505 irqreturn_t ret;
1506
Jeff Garzikcca39742006-08-24 03:19:22 -04001507 spin_lock(&host->lock);
Tejun Heo0d5ff562007-02-01 15:06:36 +09001508 irq_stat = readb(host->iomap[NV_MMIO_BAR] + NV_INT_STATUS_CK804);
Jeff Garzikcca39742006-08-24 03:19:22 -04001509 ret = nv_do_interrupt(host, irq_stat);
1510 spin_unlock(&host->lock);
Tejun Heoada364e2006-06-17 15:49:56 +09001511
1512 return ret;
1513}
1514
Tejun Heo82ef04f2008-07-31 17:02:40 +09001515static int nv_scr_read(struct ata_link *link, unsigned int sc_reg, u32 *val)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001516{
Linus Torvalds1da177e2005-04-16 15:20:36 -07001517 if (sc_reg > SCR_CONTROL)
Tejun Heoda3dbb12007-07-16 14:29:40 +09001518 return -EINVAL;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001519
Tejun Heo82ef04f2008-07-31 17:02:40 +09001520 *val = ioread32(link->ap->ioaddr.scr_addr + (sc_reg * 4));
Tejun Heoda3dbb12007-07-16 14:29:40 +09001521 return 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001522}
1523
Tejun Heo82ef04f2008-07-31 17:02:40 +09001524static int nv_scr_write(struct ata_link *link, unsigned int sc_reg, u32 val)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001525{
Linus Torvalds1da177e2005-04-16 15:20:36 -07001526 if (sc_reg > SCR_CONTROL)
Tejun Heoda3dbb12007-07-16 14:29:40 +09001527 return -EINVAL;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001528
Tejun Heo82ef04f2008-07-31 17:02:40 +09001529 iowrite32(val, link->ap->ioaddr.scr_addr + (sc_reg * 4));
Tejun Heoda3dbb12007-07-16 14:29:40 +09001530 return 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001531}
1532
Tejun Heoe8caa3c2009-01-25 11:25:22 +09001533static int nv_noclassify_hardreset(struct ata_link *link, unsigned int *class,
1534 unsigned long deadline)
1535{
1536 bool online;
1537 int rc;
1538
1539 rc = sata_link_hardreset(link, sata_deb_timing_hotplug, deadline,
1540 &online, NULL);
1541 return online ? -EAGAIN : rc;
1542}
1543
Tejun Heo39f87582006-06-17 15:49:56 +09001544static void nv_nf2_freeze(struct ata_port *ap)
1545{
Tejun Heo0d5ff562007-02-01 15:06:36 +09001546 void __iomem *scr_addr = ap->host->ports[0]->ioaddr.scr_addr;
Tejun Heo39f87582006-06-17 15:49:56 +09001547 int shift = ap->port_no * NV_INT_PORT_SHIFT;
1548 u8 mask;
1549
Tejun Heo0d5ff562007-02-01 15:06:36 +09001550 mask = ioread8(scr_addr + NV_INT_ENABLE);
Tejun Heo39f87582006-06-17 15:49:56 +09001551 mask &= ~(NV_INT_ALL << shift);
Tejun Heo0d5ff562007-02-01 15:06:36 +09001552 iowrite8(mask, scr_addr + NV_INT_ENABLE);
Tejun Heo39f87582006-06-17 15:49:56 +09001553}
1554
1555static void nv_nf2_thaw(struct ata_port *ap)
1556{
Tejun Heo0d5ff562007-02-01 15:06:36 +09001557 void __iomem *scr_addr = ap->host->ports[0]->ioaddr.scr_addr;
Tejun Heo39f87582006-06-17 15:49:56 +09001558 int shift = ap->port_no * NV_INT_PORT_SHIFT;
1559 u8 mask;
1560
Tejun Heo0d5ff562007-02-01 15:06:36 +09001561 iowrite8(NV_INT_ALL << shift, scr_addr + NV_INT_STATUS);
Tejun Heo39f87582006-06-17 15:49:56 +09001562
Tejun Heo0d5ff562007-02-01 15:06:36 +09001563 mask = ioread8(scr_addr + NV_INT_ENABLE);
Tejun Heo39f87582006-06-17 15:49:56 +09001564 mask |= (NV_INT_MASK << shift);
Tejun Heo0d5ff562007-02-01 15:06:36 +09001565 iowrite8(mask, scr_addr + NV_INT_ENABLE);
Tejun Heo39f87582006-06-17 15:49:56 +09001566}
1567
1568static void nv_ck804_freeze(struct ata_port *ap)
1569{
Tejun Heo0d5ff562007-02-01 15:06:36 +09001570 void __iomem *mmio_base = ap->host->iomap[NV_MMIO_BAR];
Tejun Heo39f87582006-06-17 15:49:56 +09001571 int shift = ap->port_no * NV_INT_PORT_SHIFT;
1572 u8 mask;
1573
1574 mask = readb(mmio_base + NV_INT_ENABLE_CK804);
1575 mask &= ~(NV_INT_ALL << shift);
1576 writeb(mask, mmio_base + NV_INT_ENABLE_CK804);
1577}
1578
1579static void nv_ck804_thaw(struct ata_port *ap)
1580{
Tejun Heo0d5ff562007-02-01 15:06:36 +09001581 void __iomem *mmio_base = ap->host->iomap[NV_MMIO_BAR];
Tejun Heo39f87582006-06-17 15:49:56 +09001582 int shift = ap->port_no * NV_INT_PORT_SHIFT;
1583 u8 mask;
1584
1585 writeb(NV_INT_ALL << shift, mmio_base + NV_INT_STATUS_CK804);
1586
1587 mask = readb(mmio_base + NV_INT_ENABLE_CK804);
1588 mask |= (NV_INT_MASK << shift);
1589 writeb(mask, mmio_base + NV_INT_ENABLE_CK804);
1590}
1591
Kuan Luof140f0f2007-10-15 15:16:53 -04001592static void nv_mcp55_freeze(struct ata_port *ap)
1593{
1594 void __iomem *mmio_base = ap->host->iomap[NV_MMIO_BAR];
1595 int shift = ap->port_no * NV_INT_PORT_SHIFT_MCP55;
1596 u32 mask;
1597
1598 writel(NV_INT_ALL_MCP55 << shift, mmio_base + NV_INT_STATUS_MCP55);
1599
1600 mask = readl(mmio_base + NV_INT_ENABLE_MCP55);
1601 mask &= ~(NV_INT_ALL_MCP55 << shift);
1602 writel(mask, mmio_base + NV_INT_ENABLE_MCP55);
Tejun Heo9363c382008-04-07 22:47:16 +09001603 ata_sff_freeze(ap);
Kuan Luof140f0f2007-10-15 15:16:53 -04001604}
1605
1606static void nv_mcp55_thaw(struct ata_port *ap)
1607{
1608 void __iomem *mmio_base = ap->host->iomap[NV_MMIO_BAR];
1609 int shift = ap->port_no * NV_INT_PORT_SHIFT_MCP55;
1610 u32 mask;
1611
1612 writel(NV_INT_ALL_MCP55 << shift, mmio_base + NV_INT_STATUS_MCP55);
1613
1614 mask = readl(mmio_base + NV_INT_ENABLE_MCP55);
1615 mask |= (NV_INT_MASK_MCP55 << shift);
1616 writel(mask, mmio_base + NV_INT_ENABLE_MCP55);
Tejun Heo9363c382008-04-07 22:47:16 +09001617 ata_sff_thaw(ap);
Kuan Luof140f0f2007-10-15 15:16:53 -04001618}
1619
Robert Hancockfbbb2622006-10-27 19:08:41 -07001620static void nv_adma_error_handler(struct ata_port *ap)
1621{
1622 struct nv_adma_port_priv *pp = ap->private_data;
Jeff Garzikb4479162007-10-25 20:47:30 -04001623 if (!(pp->flags & NV_ADMA_PORT_REGISTER_MODE)) {
Robert Hancockcdf56bc2007-01-03 18:13:57 -06001624 void __iomem *mmio = pp->ctl_block;
Robert Hancockfbbb2622006-10-27 19:08:41 -07001625 int i;
1626 u16 tmp;
Jeff Garzika84471f2007-02-26 05:51:33 -05001627
Jeff Garzikb4479162007-10-25 20:47:30 -04001628 if (ata_tag_valid(ap->link.active_tag) || ap->link.sactive) {
Robert Hancock2cb27852007-02-11 18:34:44 -06001629 u32 notifier = readl(mmio + NV_ADMA_NOTIFIER);
1630 u32 notifier_error = readl(mmio + NV_ADMA_NOTIFIER_ERROR);
1631 u32 gen_ctl = readl(pp->gen_block + NV_ADMA_GEN_CTL);
1632 u32 status = readw(mmio + NV_ADMA_STAT);
Robert Hancock08af7412007-02-19 19:01:59 -06001633 u8 cpb_count = readb(mmio + NV_ADMA_CPB_COUNT);
1634 u8 next_cpb_idx = readb(mmio + NV_ADMA_NEXT_CPB_IDX);
Robert Hancock2cb27852007-02-11 18:34:44 -06001635
Jeff Garzik5796d1c2007-10-26 00:03:37 -04001636 ata_port_printk(ap, KERN_ERR,
1637 "EH in ADMA mode, notifier 0x%X "
Robert Hancock08af7412007-02-19 19:01:59 -06001638 "notifier_error 0x%X gen_ctl 0x%X status 0x%X "
1639 "next cpb count 0x%X next cpb idx 0x%x\n",
1640 notifier, notifier_error, gen_ctl, status,
1641 cpb_count, next_cpb_idx);
Robert Hancock2cb27852007-02-11 18:34:44 -06001642
Jeff Garzikb4479162007-10-25 20:47:30 -04001643 for (i = 0; i < NV_ADMA_MAX_CPBS; i++) {
Robert Hancock2cb27852007-02-11 18:34:44 -06001644 struct nv_adma_cpb *cpb = &pp->cpb[i];
Jeff Garzikb4479162007-10-25 20:47:30 -04001645 if ((ata_tag_valid(ap->link.active_tag) && i == ap->link.active_tag) ||
Jeff Garzik5796d1c2007-10-26 00:03:37 -04001646 ap->link.sactive & (1 << i))
Robert Hancock2cb27852007-02-11 18:34:44 -06001647 ata_port_printk(ap, KERN_ERR,
1648 "CPB %d: ctl_flags 0x%x, resp_flags 0x%x\n",
1649 i, cpb->ctl_flags, cpb->resp_flags);
1650 }
1651 }
Robert Hancockfbbb2622006-10-27 19:08:41 -07001652
Robert Hancockfbbb2622006-10-27 19:08:41 -07001653 /* Push us back into port register mode for error handling. */
1654 nv_adma_register_mode(ap);
1655
Jeff Garzik5796d1c2007-10-26 00:03:37 -04001656 /* Mark all of the CPBs as invalid to prevent them from
1657 being executed */
Jeff Garzikb4479162007-10-25 20:47:30 -04001658 for (i = 0; i < NV_ADMA_MAX_CPBS; i++)
Robert Hancockfbbb2622006-10-27 19:08:41 -07001659 pp->cpb[i].ctl_flags &= ~NV_CPB_CTL_CPB_VALID;
1660
1661 /* clear CPB fetch count */
1662 writew(0, mmio + NV_ADMA_CPB_COUNT);
1663
1664 /* Reset channel */
1665 tmp = readw(mmio + NV_ADMA_CTL);
1666 writew(tmp | NV_ADMA_CTL_CHANNEL_RESET, mmio + NV_ADMA_CTL);
Jeff Garzikb4479162007-10-25 20:47:30 -04001667 readw(mmio + NV_ADMA_CTL); /* flush posted write */
Robert Hancockfbbb2622006-10-27 19:08:41 -07001668 udelay(1);
1669 writew(tmp & ~NV_ADMA_CTL_CHANNEL_RESET, mmio + NV_ADMA_CTL);
Jeff Garzikb4479162007-10-25 20:47:30 -04001670 readw(mmio + NV_ADMA_CTL); /* flush posted write */
Robert Hancockfbbb2622006-10-27 19:08:41 -07001671 }
1672
Tejun Heo9363c382008-04-07 22:47:16 +09001673 ata_sff_error_handler(ap);
Robert Hancockfbbb2622006-10-27 19:08:41 -07001674}
1675
Kuan Luof140f0f2007-10-15 15:16:53 -04001676static void nv_swncq_qc_to_dq(struct ata_port *ap, struct ata_queued_cmd *qc)
1677{
1678 struct nv_swncq_port_priv *pp = ap->private_data;
1679 struct defer_queue *dq = &pp->defer_queue;
1680
1681 /* queue is full */
1682 WARN_ON(dq->tail - dq->head == ATA_MAX_QUEUE);
1683 dq->defer_bits |= (1 << qc->tag);
1684 dq->tag[dq->tail++ & (ATA_MAX_QUEUE - 1)] = qc->tag;
1685}
1686
1687static struct ata_queued_cmd *nv_swncq_qc_from_dq(struct ata_port *ap)
1688{
1689 struct nv_swncq_port_priv *pp = ap->private_data;
1690 struct defer_queue *dq = &pp->defer_queue;
1691 unsigned int tag;
1692
1693 if (dq->head == dq->tail) /* null queue */
1694 return NULL;
1695
1696 tag = dq->tag[dq->head & (ATA_MAX_QUEUE - 1)];
1697 dq->tag[dq->head++ & (ATA_MAX_QUEUE - 1)] = ATA_TAG_POISON;
1698 WARN_ON(!(dq->defer_bits & (1 << tag)));
1699 dq->defer_bits &= ~(1 << tag);
1700
1701 return ata_qc_from_tag(ap, tag);
1702}
1703
1704static void nv_swncq_fis_reinit(struct ata_port *ap)
1705{
1706 struct nv_swncq_port_priv *pp = ap->private_data;
1707
1708 pp->dhfis_bits = 0;
1709 pp->dmafis_bits = 0;
1710 pp->sdbfis_bits = 0;
1711 pp->ncq_flags = 0;
1712}
1713
1714static void nv_swncq_pp_reinit(struct ata_port *ap)
1715{
1716 struct nv_swncq_port_priv *pp = ap->private_data;
1717 struct defer_queue *dq = &pp->defer_queue;
1718
1719 dq->head = 0;
1720 dq->tail = 0;
1721 dq->defer_bits = 0;
1722 pp->qc_active = 0;
1723 pp->last_issue_tag = ATA_TAG_POISON;
1724 nv_swncq_fis_reinit(ap);
1725}
1726
1727static void nv_swncq_irq_clear(struct ata_port *ap, u16 fis)
1728{
1729 struct nv_swncq_port_priv *pp = ap->private_data;
1730
1731 writew(fis, pp->irq_block);
1732}
1733
1734static void __ata_bmdma_stop(struct ata_port *ap)
1735{
1736 struct ata_queued_cmd qc;
1737
1738 qc.ap = ap;
1739 ata_bmdma_stop(&qc);
1740}
1741
1742static void nv_swncq_ncq_stop(struct ata_port *ap)
1743{
1744 struct nv_swncq_port_priv *pp = ap->private_data;
1745 unsigned int i;
1746 u32 sactive;
1747 u32 done_mask;
1748
1749 ata_port_printk(ap, KERN_ERR,
1750 "EH in SWNCQ mode,QC:qc_active 0x%X sactive 0x%X\n",
1751 ap->qc_active, ap->link.sactive);
1752 ata_port_printk(ap, KERN_ERR,
1753 "SWNCQ:qc_active 0x%X defer_bits 0x%X last_issue_tag 0x%x\n "
1754 "dhfis 0x%X dmafis 0x%X sdbfis 0x%X\n",
1755 pp->qc_active, pp->defer_queue.defer_bits, pp->last_issue_tag,
1756 pp->dhfis_bits, pp->dmafis_bits, pp->sdbfis_bits);
1757
1758 ata_port_printk(ap, KERN_ERR, "ATA_REG 0x%X ERR_REG 0x%X\n",
Tejun Heo5682ed32008-04-07 22:47:16 +09001759 ap->ops->sff_check_status(ap),
Kuan Luof140f0f2007-10-15 15:16:53 -04001760 ioread8(ap->ioaddr.error_addr));
1761
1762 sactive = readl(pp->sactive_block);
1763 done_mask = pp->qc_active ^ sactive;
1764
1765 ata_port_printk(ap, KERN_ERR, "tag : dhfis dmafis sdbfis sacitve\n");
1766 for (i = 0; i < ATA_MAX_QUEUE; i++) {
1767 u8 err = 0;
1768 if (pp->qc_active & (1 << i))
1769 err = 0;
1770 else if (done_mask & (1 << i))
1771 err = 1;
1772 else
1773 continue;
1774
1775 ata_port_printk(ap, KERN_ERR,
1776 "tag 0x%x: %01x %01x %01x %01x %s\n", i,
1777 (pp->dhfis_bits >> i) & 0x1,
1778 (pp->dmafis_bits >> i) & 0x1,
1779 (pp->sdbfis_bits >> i) & 0x1,
1780 (sactive >> i) & 0x1,
1781 (err ? "error! tag doesn't exit" : " "));
1782 }
1783
1784 nv_swncq_pp_reinit(ap);
Tejun Heo5682ed32008-04-07 22:47:16 +09001785 ap->ops->sff_irq_clear(ap);
Kuan Luof140f0f2007-10-15 15:16:53 -04001786 __ata_bmdma_stop(ap);
1787 nv_swncq_irq_clear(ap, 0xffff);
1788}
1789
1790static void nv_swncq_error_handler(struct ata_port *ap)
1791{
1792 struct ata_eh_context *ehc = &ap->link.eh_context;
1793
1794 if (ap->link.sactive) {
1795 nv_swncq_ncq_stop(ap);
Tejun Heocf480622008-01-24 00:05:14 +09001796 ehc->i.action |= ATA_EH_RESET;
Kuan Luof140f0f2007-10-15 15:16:53 -04001797 }
1798
Tejun Heo9363c382008-04-07 22:47:16 +09001799 ata_sff_error_handler(ap);
Kuan Luof140f0f2007-10-15 15:16:53 -04001800}
1801
1802#ifdef CONFIG_PM
1803static int nv_swncq_port_suspend(struct ata_port *ap, pm_message_t mesg)
1804{
1805 void __iomem *mmio = ap->host->iomap[NV_MMIO_BAR];
1806 u32 tmp;
1807
1808 /* clear irq */
1809 writel(~0, mmio + NV_INT_STATUS_MCP55);
1810
1811 /* disable irq */
1812 writel(0, mmio + NV_INT_ENABLE_MCP55);
1813
1814 /* disable swncq */
1815 tmp = readl(mmio + NV_CTL_MCP55);
1816 tmp &= ~(NV_CTL_PRI_SWNCQ | NV_CTL_SEC_SWNCQ);
1817 writel(tmp, mmio + NV_CTL_MCP55);
1818
1819 return 0;
1820}
1821
1822static int nv_swncq_port_resume(struct ata_port *ap)
1823{
1824 void __iomem *mmio = ap->host->iomap[NV_MMIO_BAR];
1825 u32 tmp;
1826
1827 /* clear irq */
1828 writel(~0, mmio + NV_INT_STATUS_MCP55);
1829
1830 /* enable irq */
1831 writel(0x00fd00fd, mmio + NV_INT_ENABLE_MCP55);
1832
1833 /* enable swncq */
1834 tmp = readl(mmio + NV_CTL_MCP55);
1835 writel(tmp | NV_CTL_PRI_SWNCQ | NV_CTL_SEC_SWNCQ, mmio + NV_CTL_MCP55);
1836
1837 return 0;
1838}
1839#endif
1840
1841static void nv_swncq_host_init(struct ata_host *host)
1842{
1843 u32 tmp;
1844 void __iomem *mmio = host->iomap[NV_MMIO_BAR];
1845 struct pci_dev *pdev = to_pci_dev(host->dev);
1846 u8 regval;
1847
1848 /* disable ECO 398 */
1849 pci_read_config_byte(pdev, 0x7f, &regval);
1850 regval &= ~(1 << 7);
1851 pci_write_config_byte(pdev, 0x7f, regval);
1852
1853 /* enable swncq */
1854 tmp = readl(mmio + NV_CTL_MCP55);
1855 VPRINTK("HOST_CTL:0x%X\n", tmp);
1856 writel(tmp | NV_CTL_PRI_SWNCQ | NV_CTL_SEC_SWNCQ, mmio + NV_CTL_MCP55);
1857
1858 /* enable irq intr */
1859 tmp = readl(mmio + NV_INT_ENABLE_MCP55);
1860 VPRINTK("HOST_ENABLE:0x%X\n", tmp);
1861 writel(tmp | 0x00fd00fd, mmio + NV_INT_ENABLE_MCP55);
1862
1863 /* clear port irq */
1864 writel(~0x0, mmio + NV_INT_STATUS_MCP55);
1865}
1866
1867static int nv_swncq_slave_config(struct scsi_device *sdev)
1868{
1869 struct ata_port *ap = ata_shost_to_port(sdev->host);
1870 struct pci_dev *pdev = to_pci_dev(ap->host->dev);
1871 struct ata_device *dev;
1872 int rc;
1873 u8 rev;
1874 u8 check_maxtor = 0;
1875 unsigned char model_num[ATA_ID_PROD_LEN + 1];
1876
1877 rc = ata_scsi_slave_config(sdev);
1878 if (sdev->id >= ATA_MAX_DEVICES || sdev->channel || sdev->lun)
1879 /* Not a proper libata device, ignore */
1880 return rc;
1881
1882 dev = &ap->link.device[sdev->id];
1883 if (!(ap->flags & ATA_FLAG_NCQ) || dev->class == ATA_DEV_ATAPI)
1884 return rc;
1885
1886 /* if MCP51 and Maxtor, then disable ncq */
1887 if (pdev->device == PCI_DEVICE_ID_NVIDIA_NFORCE_MCP51_SATA ||
1888 pdev->device == PCI_DEVICE_ID_NVIDIA_NFORCE_MCP51_SATA2)
1889 check_maxtor = 1;
1890
1891 /* if MCP55 and rev <= a2 and Maxtor, then disable ncq */
1892 if (pdev->device == PCI_DEVICE_ID_NVIDIA_NFORCE_MCP55_SATA ||
1893 pdev->device == PCI_DEVICE_ID_NVIDIA_NFORCE_MCP55_SATA2) {
1894 pci_read_config_byte(pdev, 0x8, &rev);
1895 if (rev <= 0xa2)
1896 check_maxtor = 1;
1897 }
1898
1899 if (!check_maxtor)
1900 return rc;
1901
1902 ata_id_c_string(dev->id, model_num, ATA_ID_PROD, sizeof(model_num));
1903
1904 if (strncmp(model_num, "Maxtor", 6) == 0) {
1905 ata_scsi_change_queue_depth(sdev, 1);
1906 ata_dev_printk(dev, KERN_NOTICE,
1907 "Disabling SWNCQ mode (depth %x)\n", sdev->queue_depth);
1908 }
1909
1910 return rc;
1911}
1912
1913static int nv_swncq_port_start(struct ata_port *ap)
1914{
1915 struct device *dev = ap->host->dev;
1916 void __iomem *mmio = ap->host->iomap[NV_MMIO_BAR];
1917 struct nv_swncq_port_priv *pp;
1918 int rc;
1919
1920 rc = ata_port_start(ap);
1921 if (rc)
1922 return rc;
1923
1924 pp = devm_kzalloc(dev, sizeof(*pp), GFP_KERNEL);
1925 if (!pp)
1926 return -ENOMEM;
1927
1928 pp->prd = dmam_alloc_coherent(dev, ATA_PRD_TBL_SZ * ATA_MAX_QUEUE,
1929 &pp->prd_dma, GFP_KERNEL);
1930 if (!pp->prd)
1931 return -ENOMEM;
1932 memset(pp->prd, 0, ATA_PRD_TBL_SZ * ATA_MAX_QUEUE);
1933
1934 ap->private_data = pp;
1935 pp->sactive_block = ap->ioaddr.scr_addr + 4 * SCR_ACTIVE;
1936 pp->irq_block = mmio + NV_INT_STATUS_MCP55 + ap->port_no * 2;
1937 pp->tag_block = mmio + NV_NCQ_REG_MCP55 + ap->port_no * 2;
1938
1939 return 0;
1940}
1941
1942static void nv_swncq_qc_prep(struct ata_queued_cmd *qc)
1943{
1944 if (qc->tf.protocol != ATA_PROT_NCQ) {
Tejun Heo9363c382008-04-07 22:47:16 +09001945 ata_sff_qc_prep(qc);
Kuan Luof140f0f2007-10-15 15:16:53 -04001946 return;
1947 }
1948
1949 if (!(qc->flags & ATA_QCFLAG_DMAMAP))
1950 return;
1951
1952 nv_swncq_fill_sg(qc);
1953}
1954
1955static void nv_swncq_fill_sg(struct ata_queued_cmd *qc)
1956{
1957 struct ata_port *ap = qc->ap;
1958 struct scatterlist *sg;
Kuan Luof140f0f2007-10-15 15:16:53 -04001959 struct nv_swncq_port_priv *pp = ap->private_data;
1960 struct ata_prd *prd;
Tejun Heoff2aeb12007-12-05 16:43:11 +09001961 unsigned int si, idx;
Kuan Luof140f0f2007-10-15 15:16:53 -04001962
1963 prd = pp->prd + ATA_MAX_PRD * qc->tag;
1964
1965 idx = 0;
Tejun Heoff2aeb12007-12-05 16:43:11 +09001966 for_each_sg(qc->sg, sg, qc->n_elem, si) {
Kuan Luof140f0f2007-10-15 15:16:53 -04001967 u32 addr, offset;
1968 u32 sg_len, len;
1969
1970 addr = (u32)sg_dma_address(sg);
1971 sg_len = sg_dma_len(sg);
1972
1973 while (sg_len) {
1974 offset = addr & 0xffff;
1975 len = sg_len;
1976 if ((offset + sg_len) > 0x10000)
1977 len = 0x10000 - offset;
1978
1979 prd[idx].addr = cpu_to_le32(addr);
1980 prd[idx].flags_len = cpu_to_le32(len & 0xffff);
1981
1982 idx++;
1983 sg_len -= len;
1984 addr += len;
1985 }
1986 }
1987
Tejun Heoff2aeb12007-12-05 16:43:11 +09001988 prd[idx - 1].flags_len |= cpu_to_le32(ATA_PRD_EOT);
Kuan Luof140f0f2007-10-15 15:16:53 -04001989}
1990
1991static unsigned int nv_swncq_issue_atacmd(struct ata_port *ap,
1992 struct ata_queued_cmd *qc)
1993{
1994 struct nv_swncq_port_priv *pp = ap->private_data;
1995
1996 if (qc == NULL)
1997 return 0;
1998
1999 DPRINTK("Enter\n");
2000
2001 writel((1 << qc->tag), pp->sactive_block);
2002 pp->last_issue_tag = qc->tag;
2003 pp->dhfis_bits &= ~(1 << qc->tag);
2004 pp->dmafis_bits &= ~(1 << qc->tag);
2005 pp->qc_active |= (0x1 << qc->tag);
2006
Tejun Heo5682ed32008-04-07 22:47:16 +09002007 ap->ops->sff_tf_load(ap, &qc->tf); /* load tf registers */
2008 ap->ops->sff_exec_command(ap, &qc->tf);
Kuan Luof140f0f2007-10-15 15:16:53 -04002009
2010 DPRINTK("Issued tag %u\n", qc->tag);
2011
2012 return 0;
2013}
2014
2015static unsigned int nv_swncq_qc_issue(struct ata_queued_cmd *qc)
2016{
2017 struct ata_port *ap = qc->ap;
2018 struct nv_swncq_port_priv *pp = ap->private_data;
2019
2020 if (qc->tf.protocol != ATA_PROT_NCQ)
Tejun Heo9363c382008-04-07 22:47:16 +09002021 return ata_sff_qc_issue(qc);
Kuan Luof140f0f2007-10-15 15:16:53 -04002022
2023 DPRINTK("Enter\n");
2024
2025 if (!pp->qc_active)
2026 nv_swncq_issue_atacmd(ap, qc);
2027 else
2028 nv_swncq_qc_to_dq(ap, qc); /* add qc to defer queue */
2029
2030 return 0;
2031}
2032
2033static void nv_swncq_hotplug(struct ata_port *ap, u32 fis)
2034{
2035 u32 serror;
2036 struct ata_eh_info *ehi = &ap->link.eh_info;
2037
2038 ata_ehi_clear_desc(ehi);
2039
2040 /* AHCI needs SError cleared; otherwise, it might lock up */
2041 sata_scr_read(&ap->link, SCR_ERROR, &serror);
2042 sata_scr_write(&ap->link, SCR_ERROR, serror);
2043
2044 /* analyze @irq_stat */
2045 if (fis & NV_SWNCQ_IRQ_ADDED)
2046 ata_ehi_push_desc(ehi, "hot plug");
2047 else if (fis & NV_SWNCQ_IRQ_REMOVED)
2048 ata_ehi_push_desc(ehi, "hot unplug");
2049
2050 ata_ehi_hotplugged(ehi);
2051
2052 /* okay, let's hand over to EH */
2053 ehi->serror |= serror;
2054
2055 ata_port_freeze(ap);
2056}
2057
2058static int nv_swncq_sdbfis(struct ata_port *ap)
2059{
2060 struct ata_queued_cmd *qc;
2061 struct nv_swncq_port_priv *pp = ap->private_data;
2062 struct ata_eh_info *ehi = &ap->link.eh_info;
2063 u32 sactive;
2064 int nr_done = 0;
2065 u32 done_mask;
2066 int i;
2067 u8 host_stat;
2068 u8 lack_dhfis = 0;
2069
2070 host_stat = ap->ops->bmdma_status(ap);
2071 if (unlikely(host_stat & ATA_DMA_ERR)) {
2072 /* error when transfering data to/from memory */
2073 ata_ehi_clear_desc(ehi);
2074 ata_ehi_push_desc(ehi, "BMDMA stat 0x%x", host_stat);
2075 ehi->err_mask |= AC_ERR_HOST_BUS;
Tejun Heocf480622008-01-24 00:05:14 +09002076 ehi->action |= ATA_EH_RESET;
Kuan Luof140f0f2007-10-15 15:16:53 -04002077 return -EINVAL;
2078 }
2079
Tejun Heo5682ed32008-04-07 22:47:16 +09002080 ap->ops->sff_irq_clear(ap);
Kuan Luof140f0f2007-10-15 15:16:53 -04002081 __ata_bmdma_stop(ap);
2082
2083 sactive = readl(pp->sactive_block);
2084 done_mask = pp->qc_active ^ sactive;
2085
2086 if (unlikely(done_mask & sactive)) {
2087 ata_ehi_clear_desc(ehi);
2088 ata_ehi_push_desc(ehi, "illegal SWNCQ:qc_active transition"
2089 "(%08x->%08x)", pp->qc_active, sactive);
2090 ehi->err_mask |= AC_ERR_HSM;
Tejun Heocf480622008-01-24 00:05:14 +09002091 ehi->action |= ATA_EH_RESET;
Kuan Luof140f0f2007-10-15 15:16:53 -04002092 return -EINVAL;
2093 }
2094 for (i = 0; i < ATA_MAX_QUEUE; i++) {
2095 if (!(done_mask & (1 << i)))
2096 continue;
2097
2098 qc = ata_qc_from_tag(ap, i);
2099 if (qc) {
2100 ata_qc_complete(qc);
2101 pp->qc_active &= ~(1 << i);
2102 pp->dhfis_bits &= ~(1 << i);
2103 pp->dmafis_bits &= ~(1 << i);
2104 pp->sdbfis_bits |= (1 << i);
2105 nr_done++;
2106 }
2107 }
2108
2109 if (!ap->qc_active) {
2110 DPRINTK("over\n");
2111 nv_swncq_pp_reinit(ap);
2112 return nr_done;
2113 }
2114
2115 if (pp->qc_active & pp->dhfis_bits)
2116 return nr_done;
2117
2118 if ((pp->ncq_flags & ncq_saw_backout) ||
2119 (pp->qc_active ^ pp->dhfis_bits))
2120 /* if the controller cann't get a device to host register FIS,
2121 * The driver needs to reissue the new command.
2122 */
2123 lack_dhfis = 1;
2124
2125 DPRINTK("id 0x%x QC: qc_active 0x%x,"
2126 "SWNCQ:qc_active 0x%X defer_bits %X "
2127 "dhfis 0x%X dmafis 0x%X last_issue_tag %x\n",
2128 ap->print_id, ap->qc_active, pp->qc_active,
2129 pp->defer_queue.defer_bits, pp->dhfis_bits,
2130 pp->dmafis_bits, pp->last_issue_tag);
2131
2132 nv_swncq_fis_reinit(ap);
2133
2134 if (lack_dhfis) {
2135 qc = ata_qc_from_tag(ap, pp->last_issue_tag);
2136 nv_swncq_issue_atacmd(ap, qc);
2137 return nr_done;
2138 }
2139
2140 if (pp->defer_queue.defer_bits) {
2141 /* send deferral queue command */
2142 qc = nv_swncq_qc_from_dq(ap);
2143 WARN_ON(qc == NULL);
2144 nv_swncq_issue_atacmd(ap, qc);
2145 }
2146
2147 return nr_done;
2148}
2149
2150static inline u32 nv_swncq_tag(struct ata_port *ap)
2151{
2152 struct nv_swncq_port_priv *pp = ap->private_data;
2153 u32 tag;
2154
2155 tag = readb(pp->tag_block) >> 2;
2156 return (tag & 0x1f);
2157}
2158
2159static int nv_swncq_dmafis(struct ata_port *ap)
2160{
2161 struct ata_queued_cmd *qc;
2162 unsigned int rw;
2163 u8 dmactl;
2164 u32 tag;
2165 struct nv_swncq_port_priv *pp = ap->private_data;
2166
2167 __ata_bmdma_stop(ap);
2168 tag = nv_swncq_tag(ap);
2169
2170 DPRINTK("dma setup tag 0x%x\n", tag);
2171 qc = ata_qc_from_tag(ap, tag);
2172
2173 if (unlikely(!qc))
2174 return 0;
2175
2176 rw = qc->tf.flags & ATA_TFLAG_WRITE;
2177
2178 /* load PRD table addr. */
2179 iowrite32(pp->prd_dma + ATA_PRD_TBL_SZ * qc->tag,
2180 ap->ioaddr.bmdma_addr + ATA_DMA_TABLE_OFS);
2181
2182 /* specify data direction, triple-check start bit is clear */
2183 dmactl = ioread8(ap->ioaddr.bmdma_addr + ATA_DMA_CMD);
2184 dmactl &= ~ATA_DMA_WR;
2185 if (!rw)
2186 dmactl |= ATA_DMA_WR;
2187
2188 iowrite8(dmactl | ATA_DMA_START, ap->ioaddr.bmdma_addr + ATA_DMA_CMD);
2189
2190 return 1;
2191}
2192
2193static void nv_swncq_host_interrupt(struct ata_port *ap, u16 fis)
2194{
2195 struct nv_swncq_port_priv *pp = ap->private_data;
2196 struct ata_queued_cmd *qc;
2197 struct ata_eh_info *ehi = &ap->link.eh_info;
2198 u32 serror;
2199 u8 ata_stat;
2200 int rc = 0;
2201
Tejun Heo5682ed32008-04-07 22:47:16 +09002202 ata_stat = ap->ops->sff_check_status(ap);
Kuan Luof140f0f2007-10-15 15:16:53 -04002203 nv_swncq_irq_clear(ap, fis);
2204 if (!fis)
2205 return;
2206
2207 if (ap->pflags & ATA_PFLAG_FROZEN)
2208 return;
2209
2210 if (fis & NV_SWNCQ_IRQ_HOTPLUG) {
2211 nv_swncq_hotplug(ap, fis);
2212 return;
2213 }
2214
2215 if (!pp->qc_active)
2216 return;
2217
Tejun Heo82ef04f2008-07-31 17:02:40 +09002218 if (ap->ops->scr_read(&ap->link, SCR_ERROR, &serror))
Kuan Luof140f0f2007-10-15 15:16:53 -04002219 return;
Tejun Heo82ef04f2008-07-31 17:02:40 +09002220 ap->ops->scr_write(&ap->link, SCR_ERROR, serror);
Kuan Luof140f0f2007-10-15 15:16:53 -04002221
2222 if (ata_stat & ATA_ERR) {
2223 ata_ehi_clear_desc(ehi);
2224 ata_ehi_push_desc(ehi, "Ata error. fis:0x%X", fis);
2225 ehi->err_mask |= AC_ERR_DEV;
2226 ehi->serror |= serror;
Tejun Heocf480622008-01-24 00:05:14 +09002227 ehi->action |= ATA_EH_RESET;
Kuan Luof140f0f2007-10-15 15:16:53 -04002228 ata_port_freeze(ap);
2229 return;
2230 }
2231
2232 if (fis & NV_SWNCQ_IRQ_BACKOUT) {
2233 /* If the IRQ is backout, driver must issue
2234 * the new command again some time later.
2235 */
2236 pp->ncq_flags |= ncq_saw_backout;
2237 }
2238
2239 if (fis & NV_SWNCQ_IRQ_SDBFIS) {
2240 pp->ncq_flags |= ncq_saw_sdb;
2241 DPRINTK("id 0x%x SWNCQ: qc_active 0x%X "
2242 "dhfis 0x%X dmafis 0x%X sactive 0x%X\n",
2243 ap->print_id, pp->qc_active, pp->dhfis_bits,
2244 pp->dmafis_bits, readl(pp->sactive_block));
2245 rc = nv_swncq_sdbfis(ap);
2246 if (rc < 0)
2247 goto irq_error;
2248 }
2249
2250 if (fis & NV_SWNCQ_IRQ_DHREGFIS) {
2251 /* The interrupt indicates the new command
2252 * was transmitted correctly to the drive.
2253 */
2254 pp->dhfis_bits |= (0x1 << pp->last_issue_tag);
2255 pp->ncq_flags |= ncq_saw_d2h;
2256 if (pp->ncq_flags & (ncq_saw_sdb | ncq_saw_backout)) {
2257 ata_ehi_push_desc(ehi, "illegal fis transaction");
2258 ehi->err_mask |= AC_ERR_HSM;
Tejun Heocf480622008-01-24 00:05:14 +09002259 ehi->action |= ATA_EH_RESET;
Kuan Luof140f0f2007-10-15 15:16:53 -04002260 goto irq_error;
2261 }
2262
2263 if (!(fis & NV_SWNCQ_IRQ_DMASETUP) &&
2264 !(pp->ncq_flags & ncq_saw_dmas)) {
Tejun Heo5682ed32008-04-07 22:47:16 +09002265 ata_stat = ap->ops->sff_check_status(ap);
Kuan Luof140f0f2007-10-15 15:16:53 -04002266 if (ata_stat & ATA_BUSY)
2267 goto irq_exit;
2268
2269 if (pp->defer_queue.defer_bits) {
2270 DPRINTK("send next command\n");
2271 qc = nv_swncq_qc_from_dq(ap);
2272 nv_swncq_issue_atacmd(ap, qc);
2273 }
2274 }
2275 }
2276
2277 if (fis & NV_SWNCQ_IRQ_DMASETUP) {
2278 /* program the dma controller with appropriate PRD buffers
2279 * and start the DMA transfer for requested command.
2280 */
2281 pp->dmafis_bits |= (0x1 << nv_swncq_tag(ap));
2282 pp->ncq_flags |= ncq_saw_dmas;
2283 rc = nv_swncq_dmafis(ap);
2284 }
2285
2286irq_exit:
2287 return;
2288irq_error:
2289 ata_ehi_push_desc(ehi, "fis:0x%x", fis);
2290 ata_port_freeze(ap);
2291 return;
2292}
2293
2294static irqreturn_t nv_swncq_interrupt(int irq, void *dev_instance)
2295{
2296 struct ata_host *host = dev_instance;
2297 unsigned int i;
2298 unsigned int handled = 0;
2299 unsigned long flags;
2300 u32 irq_stat;
2301
2302 spin_lock_irqsave(&host->lock, flags);
2303
2304 irq_stat = readl(host->iomap[NV_MMIO_BAR] + NV_INT_STATUS_MCP55);
2305
2306 for (i = 0; i < host->n_ports; i++) {
2307 struct ata_port *ap = host->ports[i];
2308
2309 if (ap && !(ap->flags & ATA_FLAG_DISABLED)) {
2310 if (ap->link.sactive) {
2311 nv_swncq_host_interrupt(ap, (u16)irq_stat);
2312 handled = 1;
2313 } else {
2314 if (irq_stat) /* reserve Hotplug */
2315 nv_swncq_irq_clear(ap, 0xfff0);
2316
2317 handled += nv_host_intr(ap, (u8)irq_stat);
2318 }
2319 }
2320 irq_stat >>= NV_INT_PORT_SHIFT_MCP55;
2321 }
2322
2323 spin_unlock_irqrestore(&host->lock, flags);
2324
2325 return IRQ_RETVAL(handled);
2326}
2327
Jeff Garzik5796d1c2007-10-26 00:03:37 -04002328static int nv_init_one(struct pci_dev *pdev, const struct pci_device_id *ent)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002329{
Jeff Garzik5796d1c2007-10-26 00:03:37 -04002330 static int printed_version;
Tejun Heo1626aeb2007-05-04 12:43:58 +02002331 const struct ata_port_info *ppi[] = { NULL, NULL };
Tejun Heo95947192008-03-25 12:22:49 +09002332 struct nv_pi_priv *ipriv;
Tejun Heo9a829cc2007-04-17 23:44:08 +09002333 struct ata_host *host;
Robert Hancockcdf56bc2007-01-03 18:13:57 -06002334 struct nv_host_priv *hpriv;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002335 int rc;
2336 u32 bar;
Tejun Heo0d5ff562007-02-01 15:06:36 +09002337 void __iomem *base;
Robert Hancockfbbb2622006-10-27 19:08:41 -07002338 unsigned long type = ent->driver_data;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002339
2340 // Make sure this is a SATA controller by counting the number of bars
2341 // (NVIDIA SATA controllers will always have six bars). Otherwise,
2342 // it's an IDE controller and we ignore it.
Jeff Garzik5796d1c2007-10-26 00:03:37 -04002343 for (bar = 0; bar < 6; bar++)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002344 if (pci_resource_start(pdev, bar) == 0)
2345 return -ENODEV;
2346
Robert Hancockcdf56bc2007-01-03 18:13:57 -06002347 if (!printed_version++)
Jeff Garzika9524a72005-10-30 14:39:11 -05002348 dev_printk(KERN_DEBUG, &pdev->dev, "version " DRV_VERSION "\n");
Linus Torvalds1da177e2005-04-16 15:20:36 -07002349
Tejun Heo24dc5f32007-01-20 16:00:28 +09002350 rc = pcim_enable_device(pdev);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002351 if (rc)
Tejun Heo24dc5f32007-01-20 16:00:28 +09002352 return rc;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002353
Tejun Heo9a829cc2007-04-17 23:44:08 +09002354 /* determine type and allocate host */
Kuan Luof140f0f2007-10-15 15:16:53 -04002355 if (type == CK804 && adma_enabled) {
Robert Hancockfbbb2622006-10-27 19:08:41 -07002356 dev_printk(KERN_NOTICE, &pdev->dev, "Using ADMA mode\n");
2357 type = ADMA;
Robert Hancockfbbb2622006-10-27 19:08:41 -07002358 }
2359
Jeff Garzik360737a2007-10-29 06:49:24 -04002360 if (type == SWNCQ) {
2361 if (swncq_enabled)
2362 dev_printk(KERN_NOTICE, &pdev->dev,
2363 "Using SWNCQ mode\n");
2364 else
2365 type = GENERIC;
2366 }
2367
Tejun Heo1626aeb2007-05-04 12:43:58 +02002368 ppi[0] = &nv_port_info[type];
Tejun Heo95947192008-03-25 12:22:49 +09002369 ipriv = ppi[0]->private_data;
Tejun Heo9363c382008-04-07 22:47:16 +09002370 rc = ata_pci_sff_prepare_host(pdev, ppi, &host);
Tejun Heo9a829cc2007-04-17 23:44:08 +09002371 if (rc)
2372 return rc;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002373
Tejun Heo24dc5f32007-01-20 16:00:28 +09002374 hpriv = devm_kzalloc(&pdev->dev, sizeof(*hpriv), GFP_KERNEL);
Robert Hancockcdf56bc2007-01-03 18:13:57 -06002375 if (!hpriv)
Tejun Heo24dc5f32007-01-20 16:00:28 +09002376 return -ENOMEM;
Robert Hancockcdf56bc2007-01-03 18:13:57 -06002377 hpriv->type = type;
Tejun Heo9a829cc2007-04-17 23:44:08 +09002378 host->private_data = hpriv;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002379
Tejun Heo9a829cc2007-04-17 23:44:08 +09002380 /* request and iomap NV_MMIO_BAR */
2381 rc = pcim_iomap_regions(pdev, 1 << NV_MMIO_BAR, DRV_NAME);
2382 if (rc)
2383 return rc;
2384
2385 /* configure SCR access */
2386 base = host->iomap[NV_MMIO_BAR];
2387 host->ports[0]->ioaddr.scr_addr = base + NV_PORT0_SCR_REG_OFFSET;
2388 host->ports[1]->ioaddr.scr_addr = base + NV_PORT1_SCR_REG_OFFSET;
Jeff Garzik02cbd922006-03-22 23:59:46 -05002389
Tejun Heoada364e2006-06-17 15:49:56 +09002390 /* enable SATA space for CK804 */
Robert Hancockfbbb2622006-10-27 19:08:41 -07002391 if (type >= CK804) {
Tejun Heoada364e2006-06-17 15:49:56 +09002392 u8 regval;
2393
2394 pci_read_config_byte(pdev, NV_MCP_SATA_CFG_20, &regval);
2395 regval |= NV_MCP_SATA_CFG_20_SATA_SPACE_EN;
2396 pci_write_config_byte(pdev, NV_MCP_SATA_CFG_20, regval);
2397 }
2398
Tejun Heo9a829cc2007-04-17 23:44:08 +09002399 /* init ADMA */
Robert Hancockfbbb2622006-10-27 19:08:41 -07002400 if (type == ADMA) {
Tejun Heo9a829cc2007-04-17 23:44:08 +09002401 rc = nv_adma_host_init(host);
Robert Hancockfbbb2622006-10-27 19:08:41 -07002402 if (rc)
Tejun Heo24dc5f32007-01-20 16:00:28 +09002403 return rc;
Jeff Garzik360737a2007-10-29 06:49:24 -04002404 } else if (type == SWNCQ)
Kuan Luof140f0f2007-10-15 15:16:53 -04002405 nv_swncq_host_init(host);
Robert Hancockfbbb2622006-10-27 19:08:41 -07002406
Tejun Heo9a829cc2007-04-17 23:44:08 +09002407 pci_set_master(pdev);
Tejun Heo95947192008-03-25 12:22:49 +09002408 return ata_host_activate(host, pdev->irq, ipriv->irq_handler,
2409 IRQF_SHARED, ipriv->sht);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002410}
2411
Tejun Heo438ac6d2007-03-02 17:31:26 +09002412#ifdef CONFIG_PM
Robert Hancockcdf56bc2007-01-03 18:13:57 -06002413static int nv_pci_device_resume(struct pci_dev *pdev)
2414{
2415 struct ata_host *host = dev_get_drvdata(&pdev->dev);
2416 struct nv_host_priv *hpriv = host->private_data;
Robert Hancockce053fa2007-02-05 16:26:04 -08002417 int rc;
Robert Hancockcdf56bc2007-01-03 18:13:57 -06002418
Robert Hancockce053fa2007-02-05 16:26:04 -08002419 rc = ata_pci_device_do_resume(pdev);
Jeff Garzikb4479162007-10-25 20:47:30 -04002420 if (rc)
Robert Hancockce053fa2007-02-05 16:26:04 -08002421 return rc;
Robert Hancockcdf56bc2007-01-03 18:13:57 -06002422
2423 if (pdev->dev.power.power_state.event == PM_EVENT_SUSPEND) {
Jeff Garzikb4479162007-10-25 20:47:30 -04002424 if (hpriv->type >= CK804) {
Robert Hancockcdf56bc2007-01-03 18:13:57 -06002425 u8 regval;
2426
2427 pci_read_config_byte(pdev, NV_MCP_SATA_CFG_20, &regval);
2428 regval |= NV_MCP_SATA_CFG_20_SATA_SPACE_EN;
2429 pci_write_config_byte(pdev, NV_MCP_SATA_CFG_20, regval);
2430 }
Jeff Garzikb4479162007-10-25 20:47:30 -04002431 if (hpriv->type == ADMA) {
Robert Hancockcdf56bc2007-01-03 18:13:57 -06002432 u32 tmp32;
2433 struct nv_adma_port_priv *pp;
2434 /* enable/disable ADMA on the ports appropriately */
2435 pci_read_config_dword(pdev, NV_MCP_SATA_CFG_20, &tmp32);
2436
2437 pp = host->ports[0]->private_data;
Jeff Garzikb4479162007-10-25 20:47:30 -04002438 if (pp->flags & NV_ADMA_ATAPI_SETUP_COMPLETE)
Robert Hancockcdf56bc2007-01-03 18:13:57 -06002439 tmp32 &= ~(NV_MCP_SATA_CFG_20_PORT0_EN |
Jeff Garzik5796d1c2007-10-26 00:03:37 -04002440 NV_MCP_SATA_CFG_20_PORT0_PWB_EN);
Robert Hancockcdf56bc2007-01-03 18:13:57 -06002441 else
2442 tmp32 |= (NV_MCP_SATA_CFG_20_PORT0_EN |
Jeff Garzik5796d1c2007-10-26 00:03:37 -04002443 NV_MCP_SATA_CFG_20_PORT0_PWB_EN);
Robert Hancockcdf56bc2007-01-03 18:13:57 -06002444 pp = host->ports[1]->private_data;
Jeff Garzikb4479162007-10-25 20:47:30 -04002445 if (pp->flags & NV_ADMA_ATAPI_SETUP_COMPLETE)
Robert Hancockcdf56bc2007-01-03 18:13:57 -06002446 tmp32 &= ~(NV_MCP_SATA_CFG_20_PORT1_EN |
Jeff Garzik5796d1c2007-10-26 00:03:37 -04002447 NV_MCP_SATA_CFG_20_PORT1_PWB_EN);
Robert Hancockcdf56bc2007-01-03 18:13:57 -06002448 else
2449 tmp32 |= (NV_MCP_SATA_CFG_20_PORT1_EN |
Jeff Garzik5796d1c2007-10-26 00:03:37 -04002450 NV_MCP_SATA_CFG_20_PORT1_PWB_EN);
Robert Hancockcdf56bc2007-01-03 18:13:57 -06002451
2452 pci_write_config_dword(pdev, NV_MCP_SATA_CFG_20, tmp32);
2453 }
2454 }
2455
2456 ata_host_resume(host);
2457
2458 return 0;
2459}
Tejun Heo438ac6d2007-03-02 17:31:26 +09002460#endif
Robert Hancockcdf56bc2007-01-03 18:13:57 -06002461
Jeff Garzikcca39742006-08-24 03:19:22 -04002462static void nv_ck804_host_stop(struct ata_host *host)
Tejun Heoada364e2006-06-17 15:49:56 +09002463{
Jeff Garzikcca39742006-08-24 03:19:22 -04002464 struct pci_dev *pdev = to_pci_dev(host->dev);
Tejun Heoada364e2006-06-17 15:49:56 +09002465 u8 regval;
2466
2467 /* disable SATA space for CK804 */
2468 pci_read_config_byte(pdev, NV_MCP_SATA_CFG_20, &regval);
2469 regval &= ~NV_MCP_SATA_CFG_20_SATA_SPACE_EN;
2470 pci_write_config_byte(pdev, NV_MCP_SATA_CFG_20, regval);
Tejun Heoada364e2006-06-17 15:49:56 +09002471}
2472
Robert Hancockfbbb2622006-10-27 19:08:41 -07002473static void nv_adma_host_stop(struct ata_host *host)
2474{
2475 struct pci_dev *pdev = to_pci_dev(host->dev);
Robert Hancockfbbb2622006-10-27 19:08:41 -07002476 u32 tmp32;
2477
Robert Hancockfbbb2622006-10-27 19:08:41 -07002478 /* disable ADMA on the ports */
2479 pci_read_config_dword(pdev, NV_MCP_SATA_CFG_20, &tmp32);
2480 tmp32 &= ~(NV_MCP_SATA_CFG_20_PORT0_EN |
2481 NV_MCP_SATA_CFG_20_PORT0_PWB_EN |
2482 NV_MCP_SATA_CFG_20_PORT1_EN |
2483 NV_MCP_SATA_CFG_20_PORT1_PWB_EN);
2484
2485 pci_write_config_dword(pdev, NV_MCP_SATA_CFG_20, tmp32);
2486
2487 nv_ck804_host_stop(host);
2488}
2489
Linus Torvalds1da177e2005-04-16 15:20:36 -07002490static int __init nv_init(void)
2491{
Pavel Roskinb7887192006-08-10 18:13:18 +09002492 return pci_register_driver(&nv_pci_driver);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002493}
2494
2495static void __exit nv_exit(void)
2496{
2497 pci_unregister_driver(&nv_pci_driver);
2498}
2499
2500module_init(nv_init);
2501module_exit(nv_exit);
Robert Hancockfbbb2622006-10-27 19:08:41 -07002502module_param_named(adma, adma_enabled, bool, 0444);
2503MODULE_PARM_DESC(adma, "Enable use of ADMA (Default: true)");
Kuan Luof140f0f2007-10-15 15:16:53 -04002504module_param_named(swncq, swncq_enabled, bool, 0444);
Zoltan Boszormenyid21279f2008-03-28 14:33:46 -07002505MODULE_PARM_DESC(swncq, "Enable use of SWNCQ (Default: true)");
Kuan Luof140f0f2007-10-15 15:16:53 -04002506