blob: 5dd969e1030255e09105464ee7df7678911fc585 [file] [log] [blame]
Brett Russ20f733e2005-09-01 18:26:17 -04001/*
2 * sata_mv.c - Marvell SATA support
3 *
Jeff Garzik8b260242005-11-12 12:32:50 -05004 * Copyright 2005: EMC Corporation, all rights reserved.
Jeff Garzike2b1be52005-11-18 14:04:23 -05005 * Copyright 2005 Red Hat, Inc. All rights reserved.
Brett Russ20f733e2005-09-01 18:26:17 -04006 *
7 * Please ALWAYS copy linux-ide@vger.kernel.org on emails.
8 *
9 * This program is free software; you can redistribute it and/or modify
10 * it under the terms of the GNU General Public License as published by
11 * the Free Software Foundation; version 2 of the License.
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; if not, write to the Free Software
20 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
21 *
22 */
23
Jeff Garzik4a05e202007-05-24 23:40:15 -040024/*
25 sata_mv TODO list:
26
27 1) Needs a full errata audit for all chipsets. I implemented most
28 of the errata workarounds found in the Marvell vendor driver, but
29 I distinctly remember a couple workarounds (one related to PCI-X)
30 are still needed.
31
Jeff Garzik4a05e202007-05-24 23:40:15 -040032 4) Add NCQ support (easy to intermediate, once new-EH support appears)
33
34 5) Investigate problems with PCI Message Signalled Interrupts (MSI).
35
36 6) Add port multiplier support (intermediate)
37
Jeff Garzik4a05e202007-05-24 23:40:15 -040038 8) Develop a low-power-consumption strategy, and implement it.
39
40 9) [Experiment, low priority] See if ATAPI can be supported using
41 "unknown FIS" or "vendor-specific FIS" support, or something creative
42 like that.
43
44 10) [Experiment, low priority] Investigate interrupt coalescing.
45 Quite often, especially with PCI Message Signalled Interrupts (MSI),
46 the overhead reduced by interrupt mitigation is quite often not
47 worth the latency cost.
48
49 11) [Experiment, Marvell value added] Is it possible to use target
50 mode to cross-connect two Linux boxes with Marvell cards? If so,
51 creating LibATA target mode support would be very interesting.
52
53 Target mode, for those without docs, is the ability to directly
54 connect two SATA controllers.
55
56 13) Verify that 7042 is fully supported. I only have a 6042.
57
58*/
59
60
Brett Russ20f733e2005-09-01 18:26:17 -040061#include <linux/kernel.h>
62#include <linux/module.h>
63#include <linux/pci.h>
64#include <linux/init.h>
65#include <linux/blkdev.h>
66#include <linux/delay.h>
67#include <linux/interrupt.h>
Brett Russ20f733e2005-09-01 18:26:17 -040068#include <linux/dma-mapping.h>
Jeff Garzika9524a72005-10-30 14:39:11 -050069#include <linux/device.h>
Brett Russ20f733e2005-09-01 18:26:17 -040070#include <scsi/scsi_host.h>
Jeff Garzik193515d2005-11-07 00:59:37 -050071#include <scsi/scsi_cmnd.h>
Jeff Garzik6c087722007-10-12 00:16:23 -040072#include <scsi/scsi_device.h>
Brett Russ20f733e2005-09-01 18:26:17 -040073#include <linux/libata.h>
Brett Russ20f733e2005-09-01 18:26:17 -040074
75#define DRV_NAME "sata_mv"
Jeff Garzik6c087722007-10-12 00:16:23 -040076#define DRV_VERSION "1.01"
Brett Russ20f733e2005-09-01 18:26:17 -040077
78enum {
79 /* BAR's are enumerated in terms of pci_resource_start() terms */
80 MV_PRIMARY_BAR = 0, /* offset 0x10: memory space */
81 MV_IO_BAR = 2, /* offset 0x18: IO space */
82 MV_MISC_BAR = 3, /* offset 0x1c: FLASH, NVRAM, SRAM */
83
84 MV_MAJOR_REG_AREA_SZ = 0x10000, /* 64KB */
85 MV_MINOR_REG_AREA_SZ = 0x2000, /* 8KB */
86
87 MV_PCI_REG_BASE = 0,
88 MV_IRQ_COAL_REG_BASE = 0x18000, /* 6xxx part only */
Mark Lord615ab952006-05-19 16:24:56 -040089 MV_IRQ_COAL_CAUSE = (MV_IRQ_COAL_REG_BASE + 0x08),
90 MV_IRQ_COAL_CAUSE_LO = (MV_IRQ_COAL_REG_BASE + 0x88),
91 MV_IRQ_COAL_CAUSE_HI = (MV_IRQ_COAL_REG_BASE + 0x8c),
92 MV_IRQ_COAL_THRESHOLD = (MV_IRQ_COAL_REG_BASE + 0xcc),
93 MV_IRQ_COAL_TIME_THRESHOLD = (MV_IRQ_COAL_REG_BASE + 0xd0),
94
Brett Russ20f733e2005-09-01 18:26:17 -040095 MV_SATAHC0_REG_BASE = 0x20000,
Jeff Garzik522479f2005-11-12 22:14:02 -050096 MV_FLASH_CTL = 0x1046c,
Jeff Garzikbca1c4e2005-11-12 12:48:15 -050097 MV_GPIO_PORT_CTL = 0x104f0,
98 MV_RESET_CFG = 0x180d8,
Brett Russ20f733e2005-09-01 18:26:17 -040099
100 MV_PCI_REG_SZ = MV_MAJOR_REG_AREA_SZ,
101 MV_SATAHC_REG_SZ = MV_MAJOR_REG_AREA_SZ,
102 MV_SATAHC_ARBTR_REG_SZ = MV_MINOR_REG_AREA_SZ, /* arbiter */
103 MV_PORT_REG_SZ = MV_MINOR_REG_AREA_SZ,
104
Brett Russ31961942005-09-30 01:36:00 -0400105 MV_MAX_Q_DEPTH = 32,
106 MV_MAX_Q_DEPTH_MASK = MV_MAX_Q_DEPTH - 1,
107
108 /* CRQB needs alignment on a 1KB boundary. Size == 1KB
109 * CRPB needs alignment on a 256B boundary. Size == 256B
110 * SG count of 176 leads to MV_PORT_PRIV_DMA_SZ == 4KB
111 * ePRD (SG) entries need alignment on a 16B boundary. Size == 16B
112 */
113 MV_CRQB_Q_SZ = (32 * MV_MAX_Q_DEPTH),
114 MV_CRPB_Q_SZ = (8 * MV_MAX_Q_DEPTH),
115 MV_MAX_SG_CT = 176,
116 MV_SG_TBL_SZ = (16 * MV_MAX_SG_CT),
117 MV_PORT_PRIV_DMA_SZ = (MV_CRQB_Q_SZ + MV_CRPB_Q_SZ + MV_SG_TBL_SZ),
118
Brett Russ20f733e2005-09-01 18:26:17 -0400119 MV_PORTS_PER_HC = 4,
120 /* == (port / MV_PORTS_PER_HC) to determine HC from 0-7 port */
121 MV_PORT_HC_SHIFT = 2,
Brett Russ31961942005-09-30 01:36:00 -0400122 /* == (port % MV_PORTS_PER_HC) to determine hard port from 0-7 port */
Brett Russ20f733e2005-09-01 18:26:17 -0400123 MV_PORT_MASK = 3,
124
125 /* Host Flags */
126 MV_FLAG_DUAL_HC = (1 << 30), /* two SATA Host Controllers */
127 MV_FLAG_IRQ_COALESCE = (1 << 29), /* IRQ coalescing capability */
Jeff Garzikc5d3e452007-07-11 18:30:50 -0400128 MV_COMMON_FLAGS = ATA_FLAG_SATA | ATA_FLAG_NO_LEGACY |
Jeff Garzikbdd4ddd2007-07-12 14:34:26 -0400129 ATA_FLAG_MMIO | ATA_FLAG_NO_ATAPI |
130 ATA_FLAG_PIO_POLLING,
Jeff Garzik47c2b672005-11-12 21:13:17 -0500131 MV_6XXX_FLAGS = MV_FLAG_IRQ_COALESCE,
Brett Russ20f733e2005-09-01 18:26:17 -0400132
Brett Russ31961942005-09-30 01:36:00 -0400133 CRQB_FLAG_READ = (1 << 0),
134 CRQB_TAG_SHIFT = 1,
Jeff Garzikc5d3e452007-07-11 18:30:50 -0400135 CRQB_IOID_SHIFT = 6, /* CRQB Gen-II/IIE IO Id shift */
136 CRQB_HOSTQ_SHIFT = 17, /* CRQB Gen-II/IIE HostQueTag shift */
Brett Russ31961942005-09-30 01:36:00 -0400137 CRQB_CMD_ADDR_SHIFT = 8,
138 CRQB_CMD_CS = (0x2 << 11),
139 CRQB_CMD_LAST = (1 << 15),
140
141 CRPB_FLAG_STATUS_SHIFT = 8,
Jeff Garzikc5d3e452007-07-11 18:30:50 -0400142 CRPB_IOID_SHIFT_6 = 5, /* CRPB Gen-II IO Id shift */
143 CRPB_IOID_SHIFT_7 = 7, /* CRPB Gen-IIE IO Id shift */
Brett Russ31961942005-09-30 01:36:00 -0400144
145 EPRD_FLAG_END_OF_TBL = (1 << 31),
146
Brett Russ20f733e2005-09-01 18:26:17 -0400147 /* PCI interface registers */
148
Brett Russ31961942005-09-30 01:36:00 -0400149 PCI_COMMAND_OFS = 0xc00,
150
Brett Russ20f733e2005-09-01 18:26:17 -0400151 PCI_MAIN_CMD_STS_OFS = 0xd30,
152 STOP_PCI_MASTER = (1 << 2),
153 PCI_MASTER_EMPTY = (1 << 3),
154 GLOB_SFT_RST = (1 << 4),
155
Jeff Garzik522479f2005-11-12 22:14:02 -0500156 MV_PCI_MODE = 0xd00,
157 MV_PCI_EXP_ROM_BAR_CTL = 0xd2c,
158 MV_PCI_DISC_TIMER = 0xd04,
159 MV_PCI_MSI_TRIGGER = 0xc38,
160 MV_PCI_SERR_MASK = 0xc28,
161 MV_PCI_XBAR_TMOUT = 0x1d04,
162 MV_PCI_ERR_LOW_ADDRESS = 0x1d40,
163 MV_PCI_ERR_HIGH_ADDRESS = 0x1d44,
164 MV_PCI_ERR_ATTRIBUTE = 0x1d48,
165 MV_PCI_ERR_COMMAND = 0x1d50,
166
Mark Lord02a121d2007-12-01 13:07:22 -0500167 PCI_IRQ_CAUSE_OFS = 0x1d58,
168 PCI_IRQ_MASK_OFS = 0x1d5c,
Brett Russ20f733e2005-09-01 18:26:17 -0400169 PCI_UNMASK_ALL_IRQS = 0x7fffff, /* bits 22-0 */
170
Mark Lord02a121d2007-12-01 13:07:22 -0500171 PCIE_IRQ_CAUSE_OFS = 0x1900,
172 PCIE_IRQ_MASK_OFS = 0x1910,
173 PCIE_UNMASK_ALL_IRQS = 0x70a, /* assorted bits */
174
Brett Russ20f733e2005-09-01 18:26:17 -0400175 HC_MAIN_IRQ_CAUSE_OFS = 0x1d60,
176 HC_MAIN_IRQ_MASK_OFS = 0x1d64,
177 PORT0_ERR = (1 << 0), /* shift by port # */
178 PORT0_DONE = (1 << 1), /* shift by port # */
179 HC0_IRQ_PEND = 0x1ff, /* bits 0-8 = HC0's ports */
180 HC_SHIFT = 9, /* bits 9-17 = HC1's ports */
181 PCI_ERR = (1 << 18),
182 TRAN_LO_DONE = (1 << 19), /* 6xxx: IRQ coalescing */
183 TRAN_HI_DONE = (1 << 20), /* 6xxx: IRQ coalescing */
Jeff Garzikfb621e22007-02-25 04:19:45 -0500184 PORTS_0_3_COAL_DONE = (1 << 8),
185 PORTS_4_7_COAL_DONE = (1 << 17),
Brett Russ20f733e2005-09-01 18:26:17 -0400186 PORTS_0_7_COAL_DONE = (1 << 21), /* 6xxx: IRQ coalescing */
187 GPIO_INT = (1 << 22),
188 SELF_INT = (1 << 23),
189 TWSI_INT = (1 << 24),
190 HC_MAIN_RSVD = (0x7f << 25), /* bits 31-25 */
Jeff Garzikfb621e22007-02-25 04:19:45 -0500191 HC_MAIN_RSVD_5 = (0x1fff << 19), /* bits 31-19 */
Jeff Garzik8b260242005-11-12 12:32:50 -0500192 HC_MAIN_MASKED_IRQS = (TRAN_LO_DONE | TRAN_HI_DONE |
Brett Russ20f733e2005-09-01 18:26:17 -0400193 PORTS_0_7_COAL_DONE | GPIO_INT | TWSI_INT |
194 HC_MAIN_RSVD),
Jeff Garzikfb621e22007-02-25 04:19:45 -0500195 HC_MAIN_MASKED_IRQS_5 = (PORTS_0_3_COAL_DONE | PORTS_4_7_COAL_DONE |
196 HC_MAIN_RSVD_5),
Brett Russ20f733e2005-09-01 18:26:17 -0400197
198 /* SATAHC registers */
199 HC_CFG_OFS = 0,
200
201 HC_IRQ_CAUSE_OFS = 0x14,
Brett Russ31961942005-09-30 01:36:00 -0400202 CRPB_DMA_DONE = (1 << 0), /* shift by port # */
Brett Russ20f733e2005-09-01 18:26:17 -0400203 HC_IRQ_COAL = (1 << 4), /* IRQ coalescing */
204 DEV_IRQ = (1 << 8), /* shift by port # */
205
206 /* Shadow block registers */
Brett Russ31961942005-09-30 01:36:00 -0400207 SHD_BLK_OFS = 0x100,
208 SHD_CTL_AST_OFS = 0x20, /* ofs from SHD_BLK_OFS */
Brett Russ20f733e2005-09-01 18:26:17 -0400209
210 /* SATA registers */
211 SATA_STATUS_OFS = 0x300, /* ctrl, err regs follow status */
212 SATA_ACTIVE_OFS = 0x350,
Jeff Garzik47c2b672005-11-12 21:13:17 -0500213 PHY_MODE3 = 0x310,
Jeff Garzikbca1c4e2005-11-12 12:48:15 -0500214 PHY_MODE4 = 0x314,
215 PHY_MODE2 = 0x330,
Jeff Garzikc9d39132005-11-13 17:47:51 -0500216 MV5_PHY_MODE = 0x74,
217 MV5_LT_MODE = 0x30,
218 MV5_PHY_CTL = 0x0C,
Jeff Garzikbca1c4e2005-11-12 12:48:15 -0500219 SATA_INTERFACE_CTL = 0x050,
220
221 MV_M2_PREAMP_MASK = 0x7e0,
Brett Russ20f733e2005-09-01 18:26:17 -0400222
223 /* Port registers */
224 EDMA_CFG_OFS = 0,
Brett Russ31961942005-09-30 01:36:00 -0400225 EDMA_CFG_Q_DEPTH = 0, /* queueing disabled */
226 EDMA_CFG_NCQ = (1 << 5),
227 EDMA_CFG_NCQ_GO_ON_ERR = (1 << 14), /* continue on error */
228 EDMA_CFG_RD_BRST_EXT = (1 << 11), /* read burst 512B */
229 EDMA_CFG_WR_BUFF_LEN = (1 << 13), /* write buffer 512B */
Brett Russ20f733e2005-09-01 18:26:17 -0400230
231 EDMA_ERR_IRQ_CAUSE_OFS = 0x8,
232 EDMA_ERR_IRQ_MASK_OFS = 0xc,
Jeff Garzik6c1153e2007-07-13 15:20:15 -0400233 EDMA_ERR_D_PAR = (1 << 0), /* UDMA data parity err */
234 EDMA_ERR_PRD_PAR = (1 << 1), /* UDMA PRD parity err */
235 EDMA_ERR_DEV = (1 << 2), /* device error */
236 EDMA_ERR_DEV_DCON = (1 << 3), /* device disconnect */
237 EDMA_ERR_DEV_CON = (1 << 4), /* device connected */
238 EDMA_ERR_SERR = (1 << 5), /* SError bits [WBDST] raised */
Jeff Garzikc5d3e452007-07-11 18:30:50 -0400239 EDMA_ERR_SELF_DIS = (1 << 7), /* Gen II/IIE self-disable */
240 EDMA_ERR_SELF_DIS_5 = (1 << 8), /* Gen I self-disable */
Jeff Garzik6c1153e2007-07-13 15:20:15 -0400241 EDMA_ERR_BIST_ASYNC = (1 << 8), /* BIST FIS or Async Notify */
Jeff Garzikc5d3e452007-07-11 18:30:50 -0400242 EDMA_ERR_TRANS_IRQ_7 = (1 << 8), /* Gen IIE transprt layer irq */
Jeff Garzik6c1153e2007-07-13 15:20:15 -0400243 EDMA_ERR_CRQB_PAR = (1 << 9), /* CRQB parity error */
244 EDMA_ERR_CRPB_PAR = (1 << 10), /* CRPB parity error */
245 EDMA_ERR_INTRL_PAR = (1 << 11), /* internal parity error */
246 EDMA_ERR_IORDY = (1 << 12), /* IORdy timeout */
247 EDMA_ERR_LNK_CTRL_RX = (0xf << 13), /* link ctrl rx error */
Brett Russ20f733e2005-09-01 18:26:17 -0400248 EDMA_ERR_LNK_CTRL_RX_2 = (1 << 15),
Jeff Garzik6c1153e2007-07-13 15:20:15 -0400249 EDMA_ERR_LNK_DATA_RX = (0xf << 17), /* link data rx error */
250 EDMA_ERR_LNK_CTRL_TX = (0x1f << 21), /* link ctrl tx error */
251 EDMA_ERR_LNK_DATA_TX = (0x1f << 26), /* link data tx error */
252 EDMA_ERR_TRANS_PROTO = (1 << 31), /* transport protocol error */
Jeff Garzikc5d3e452007-07-11 18:30:50 -0400253 EDMA_ERR_OVERRUN_5 = (1 << 5),
254 EDMA_ERR_UNDERRUN_5 = (1 << 6),
Jeff Garzikbdd4ddd2007-07-12 14:34:26 -0400255 EDMA_EH_FREEZE = EDMA_ERR_D_PAR |
256 EDMA_ERR_PRD_PAR |
257 EDMA_ERR_DEV_DCON |
258 EDMA_ERR_DEV_CON |
259 EDMA_ERR_SERR |
260 EDMA_ERR_SELF_DIS |
Jeff Garzik6c1153e2007-07-13 15:20:15 -0400261 EDMA_ERR_CRQB_PAR |
Jeff Garzikbdd4ddd2007-07-12 14:34:26 -0400262 EDMA_ERR_CRPB_PAR |
263 EDMA_ERR_INTRL_PAR |
264 EDMA_ERR_IORDY |
265 EDMA_ERR_LNK_CTRL_RX_2 |
266 EDMA_ERR_LNK_DATA_RX |
267 EDMA_ERR_LNK_DATA_TX |
268 EDMA_ERR_TRANS_PROTO,
269 EDMA_EH_FREEZE_5 = EDMA_ERR_D_PAR |
270 EDMA_ERR_PRD_PAR |
271 EDMA_ERR_DEV_DCON |
272 EDMA_ERR_DEV_CON |
273 EDMA_ERR_OVERRUN_5 |
274 EDMA_ERR_UNDERRUN_5 |
275 EDMA_ERR_SELF_DIS_5 |
Jeff Garzik6c1153e2007-07-13 15:20:15 -0400276 EDMA_ERR_CRQB_PAR |
Jeff Garzikbdd4ddd2007-07-12 14:34:26 -0400277 EDMA_ERR_CRPB_PAR |
278 EDMA_ERR_INTRL_PAR |
279 EDMA_ERR_IORDY,
Brett Russ20f733e2005-09-01 18:26:17 -0400280
Brett Russ31961942005-09-30 01:36:00 -0400281 EDMA_REQ_Q_BASE_HI_OFS = 0x10,
282 EDMA_REQ_Q_IN_PTR_OFS = 0x14, /* also contains BASE_LO */
Brett Russ31961942005-09-30 01:36:00 -0400283
284 EDMA_REQ_Q_OUT_PTR_OFS = 0x18,
285 EDMA_REQ_Q_PTR_SHIFT = 5,
286
287 EDMA_RSP_Q_BASE_HI_OFS = 0x1c,
288 EDMA_RSP_Q_IN_PTR_OFS = 0x20,
289 EDMA_RSP_Q_OUT_PTR_OFS = 0x24, /* also contains BASE_LO */
Brett Russ31961942005-09-30 01:36:00 -0400290 EDMA_RSP_Q_PTR_SHIFT = 3,
291
Jeff Garzik0ea9e172007-07-13 17:06:45 -0400292 EDMA_CMD_OFS = 0x28, /* EDMA command register */
293 EDMA_EN = (1 << 0), /* enable EDMA */
294 EDMA_DS = (1 << 1), /* disable EDMA; self-negated */
295 ATA_RST = (1 << 2), /* reset trans/link/phy */
Brett Russ20f733e2005-09-01 18:26:17 -0400296
Jeff Garzikc9d39132005-11-13 17:47:51 -0500297 EDMA_IORDY_TMOUT = 0x34,
Jeff Garzikbca1c4e2005-11-12 12:48:15 -0500298 EDMA_ARB_CFG = 0x38,
Jeff Garzikbca1c4e2005-11-12 12:48:15 -0500299
Brett Russ31961942005-09-30 01:36:00 -0400300 /* Host private flags (hp_flags) */
301 MV_HP_FLAG_MSI = (1 << 0),
Jeff Garzik47c2b672005-11-12 21:13:17 -0500302 MV_HP_ERRATA_50XXB0 = (1 << 1),
303 MV_HP_ERRATA_50XXB2 = (1 << 2),
304 MV_HP_ERRATA_60X1B2 = (1 << 3),
305 MV_HP_ERRATA_60X1C0 = (1 << 4),
Jeff Garzike4e7b892006-01-31 12:18:41 -0500306 MV_HP_ERRATA_XX42A0 = (1 << 5),
Jeff Garzik0ea9e172007-07-13 17:06:45 -0400307 MV_HP_GEN_I = (1 << 6), /* Generation I: 50xx */
308 MV_HP_GEN_II = (1 << 7), /* Generation II: 60xx */
309 MV_HP_GEN_IIE = (1 << 8), /* Generation IIE: 6042/7042 */
Mark Lord02a121d2007-12-01 13:07:22 -0500310 MV_HP_PCIE = (1 << 9), /* PCIe bus/regs: 7042 */
Brett Russ20f733e2005-09-01 18:26:17 -0400311
Brett Russ31961942005-09-30 01:36:00 -0400312 /* Port private flags (pp_flags) */
Jeff Garzik0ea9e172007-07-13 17:06:45 -0400313 MV_PP_FLAG_EDMA_EN = (1 << 0), /* is EDMA engine enabled? */
314 MV_PP_FLAG_HAD_A_RESET = (1 << 2), /* 1st hard reset complete? */
Brett Russ31961942005-09-30 01:36:00 -0400315};
316
Jeff Garzikee9ccdf2007-07-12 15:51:22 -0400317#define IS_GEN_I(hpriv) ((hpriv)->hp_flags & MV_HP_GEN_I)
318#define IS_GEN_II(hpriv) ((hpriv)->hp_flags & MV_HP_GEN_II)
Jeff Garzike4e7b892006-01-31 12:18:41 -0500319#define IS_GEN_IIE(hpriv) ((hpriv)->hp_flags & MV_HP_GEN_IIE)
Jeff Garzikbca1c4e2005-11-12 12:48:15 -0500320
Jeff Garzik095fec82005-11-12 09:50:49 -0500321enum {
Jeff Garzikbaf14aa2007-10-09 13:51:57 -0400322 /* DMA boundary 0xffff is required by the s/g splitting
323 * we need on /length/ in mv_fill-sg().
324 */
325 MV_DMA_BOUNDARY = 0xffffU,
Jeff Garzik095fec82005-11-12 09:50:49 -0500326
Jeff Garzik0ea9e172007-07-13 17:06:45 -0400327 /* mask of register bits containing lower 32 bits
328 * of EDMA request queue DMA address
329 */
Jeff Garzik095fec82005-11-12 09:50:49 -0500330 EDMA_REQ_Q_BASE_LO_MASK = 0xfffffc00U,
331
Jeff Garzik0ea9e172007-07-13 17:06:45 -0400332 /* ditto, for response queue */
Jeff Garzik095fec82005-11-12 09:50:49 -0500333 EDMA_RSP_Q_BASE_LO_MASK = 0xffffff00U,
334};
335
Jeff Garzik522479f2005-11-12 22:14:02 -0500336enum chip_type {
337 chip_504x,
338 chip_508x,
339 chip_5080,
340 chip_604x,
341 chip_608x,
Jeff Garzike4e7b892006-01-31 12:18:41 -0500342 chip_6042,
343 chip_7042,
Jeff Garzik522479f2005-11-12 22:14:02 -0500344};
345
Brett Russ31961942005-09-30 01:36:00 -0400346/* Command ReQuest Block: 32B */
347struct mv_crqb {
Mark Lorde1469872006-05-22 19:02:03 -0400348 __le32 sg_addr;
349 __le32 sg_addr_hi;
350 __le16 ctrl_flags;
351 __le16 ata_cmd[11];
Brett Russ31961942005-09-30 01:36:00 -0400352};
353
Jeff Garzike4e7b892006-01-31 12:18:41 -0500354struct mv_crqb_iie {
Mark Lorde1469872006-05-22 19:02:03 -0400355 __le32 addr;
356 __le32 addr_hi;
357 __le32 flags;
358 __le32 len;
359 __le32 ata_cmd[4];
Jeff Garzike4e7b892006-01-31 12:18:41 -0500360};
361
Brett Russ31961942005-09-30 01:36:00 -0400362/* Command ResPonse Block: 8B */
363struct mv_crpb {
Mark Lorde1469872006-05-22 19:02:03 -0400364 __le16 id;
365 __le16 flags;
366 __le32 tmstmp;
Brett Russ31961942005-09-30 01:36:00 -0400367};
368
369/* EDMA Physical Region Descriptor (ePRD); A.K.A. SG */
370struct mv_sg {
Mark Lorde1469872006-05-22 19:02:03 -0400371 __le32 addr;
372 __le32 flags_size;
373 __le32 addr_hi;
374 __le32 reserved;
Brett Russ20f733e2005-09-01 18:26:17 -0400375};
376
377struct mv_port_priv {
Brett Russ31961942005-09-30 01:36:00 -0400378 struct mv_crqb *crqb;
379 dma_addr_t crqb_dma;
380 struct mv_crpb *crpb;
381 dma_addr_t crpb_dma;
382 struct mv_sg *sg_tbl;
383 dma_addr_t sg_tbl_dma;
Jeff Garzikbdd4ddd2007-07-12 14:34:26 -0400384
385 unsigned int req_idx;
386 unsigned int resp_idx;
387
Brett Russ31961942005-09-30 01:36:00 -0400388 u32 pp_flags;
Brett Russ20f733e2005-09-01 18:26:17 -0400389};
390
Jeff Garzikbca1c4e2005-11-12 12:48:15 -0500391struct mv_port_signal {
392 u32 amps;
393 u32 pre;
394};
395
Mark Lord02a121d2007-12-01 13:07:22 -0500396struct mv_host_priv {
397 u32 hp_flags;
398 struct mv_port_signal signal[8];
399 const struct mv_hw_ops *ops;
400 u32 irq_cause_ofs;
401 u32 irq_mask_ofs;
402 u32 unmask_all_irqs;
403};
404
Jeff Garzik47c2b672005-11-12 21:13:17 -0500405struct mv_hw_ops {
Jeff Garzik2a47ce02005-11-12 23:05:14 -0500406 void (*phy_errata)(struct mv_host_priv *hpriv, void __iomem *mmio,
407 unsigned int port);
Jeff Garzik47c2b672005-11-12 21:13:17 -0500408 void (*enable_leds)(struct mv_host_priv *hpriv, void __iomem *mmio);
409 void (*read_preamp)(struct mv_host_priv *hpriv, int idx,
410 void __iomem *mmio);
Jeff Garzikc9d39132005-11-13 17:47:51 -0500411 int (*reset_hc)(struct mv_host_priv *hpriv, void __iomem *mmio,
412 unsigned int n_hc);
Jeff Garzik522479f2005-11-12 22:14:02 -0500413 void (*reset_flash)(struct mv_host_priv *hpriv, void __iomem *mmio);
414 void (*reset_bus)(struct pci_dev *pdev, void __iomem *mmio);
Jeff Garzik47c2b672005-11-12 21:13:17 -0500415};
416
Brett Russ20f733e2005-09-01 18:26:17 -0400417static void mv_irq_clear(struct ata_port *ap);
Tejun Heoda3dbb12007-07-16 14:29:40 +0900418static int mv_scr_read(struct ata_port *ap, unsigned int sc_reg_in, u32 *val);
419static int mv_scr_write(struct ata_port *ap, unsigned int sc_reg_in, u32 val);
420static int mv5_scr_read(struct ata_port *ap, unsigned int sc_reg_in, u32 *val);
421static int mv5_scr_write(struct ata_port *ap, unsigned int sc_reg_in, u32 val);
Brett Russ31961942005-09-30 01:36:00 -0400422static int mv_port_start(struct ata_port *ap);
423static void mv_port_stop(struct ata_port *ap);
424static void mv_qc_prep(struct ata_queued_cmd *qc);
Jeff Garzike4e7b892006-01-31 12:18:41 -0500425static void mv_qc_prep_iie(struct ata_queued_cmd *qc);
Tejun Heo9a3d9eb2006-01-23 13:09:36 +0900426static unsigned int mv_qc_issue(struct ata_queued_cmd *qc);
Jeff Garzikbdd4ddd2007-07-12 14:34:26 -0400427static void mv_error_handler(struct ata_port *ap);
428static void mv_post_int_cmd(struct ata_queued_cmd *qc);
429static void mv_eh_freeze(struct ata_port *ap);
430static void mv_eh_thaw(struct ata_port *ap);
Brett Russ20f733e2005-09-01 18:26:17 -0400431static int mv_init_one(struct pci_dev *pdev, const struct pci_device_id *ent);
432
Jeff Garzik2a47ce02005-11-12 23:05:14 -0500433static void mv5_phy_errata(struct mv_host_priv *hpriv, void __iomem *mmio,
434 unsigned int port);
Jeff Garzik47c2b672005-11-12 21:13:17 -0500435static void mv5_enable_leds(struct mv_host_priv *hpriv, void __iomem *mmio);
436static void mv5_read_preamp(struct mv_host_priv *hpriv, int idx,
437 void __iomem *mmio);
Jeff Garzikc9d39132005-11-13 17:47:51 -0500438static int mv5_reset_hc(struct mv_host_priv *hpriv, void __iomem *mmio,
439 unsigned int n_hc);
Jeff Garzik522479f2005-11-12 22:14:02 -0500440static void mv5_reset_flash(struct mv_host_priv *hpriv, void __iomem *mmio);
441static void mv5_reset_bus(struct pci_dev *pdev, void __iomem *mmio);
Jeff Garzik47c2b672005-11-12 21:13:17 -0500442
Jeff Garzik2a47ce02005-11-12 23:05:14 -0500443static void mv6_phy_errata(struct mv_host_priv *hpriv, void __iomem *mmio,
444 unsigned int port);
Jeff Garzik47c2b672005-11-12 21:13:17 -0500445static void mv6_enable_leds(struct mv_host_priv *hpriv, void __iomem *mmio);
446static void mv6_read_preamp(struct mv_host_priv *hpriv, int idx,
447 void __iomem *mmio);
Jeff Garzikc9d39132005-11-13 17:47:51 -0500448static int mv6_reset_hc(struct mv_host_priv *hpriv, void __iomem *mmio,
449 unsigned int n_hc);
Jeff Garzik522479f2005-11-12 22:14:02 -0500450static void mv6_reset_flash(struct mv_host_priv *hpriv, void __iomem *mmio);
451static void mv_reset_pci_bus(struct pci_dev *pdev, void __iomem *mmio);
Jeff Garzikc9d39132005-11-13 17:47:51 -0500452static void mv_channel_reset(struct mv_host_priv *hpriv, void __iomem *mmio,
453 unsigned int port_no);
Jeff Garzik47c2b672005-11-12 21:13:17 -0500454
Jeff Garzikc5d3e452007-07-11 18:30:50 -0400455static struct scsi_host_template mv5_sht = {
Brett Russ20f733e2005-09-01 18:26:17 -0400456 .module = THIS_MODULE,
457 .name = DRV_NAME,
458 .ioctl = ata_scsi_ioctl,
459 .queuecommand = ata_scsi_queuecmd,
Jeff Garzikc5d3e452007-07-11 18:30:50 -0400460 .can_queue = ATA_DEF_QUEUE,
461 .this_id = ATA_SHT_THIS_ID,
Jeff Garzikbaf14aa2007-10-09 13:51:57 -0400462 .sg_tablesize = MV_MAX_SG_CT / 2,
Jeff Garzikc5d3e452007-07-11 18:30:50 -0400463 .cmd_per_lun = ATA_SHT_CMD_PER_LUN,
464 .emulated = ATA_SHT_EMULATED,
465 .use_clustering = 1,
466 .proc_name = DRV_NAME,
467 .dma_boundary = MV_DMA_BOUNDARY,
Jeff Garzik3be6cbd2007-10-18 16:21:18 -0400468 .slave_configure = ata_scsi_slave_config,
Jeff Garzikc5d3e452007-07-11 18:30:50 -0400469 .slave_destroy = ata_scsi_slave_destroy,
470 .bios_param = ata_std_bios_param,
471};
472
473static struct scsi_host_template mv6_sht = {
474 .module = THIS_MODULE,
475 .name = DRV_NAME,
476 .ioctl = ata_scsi_ioctl,
477 .queuecommand = ata_scsi_queuecmd,
478 .can_queue = ATA_DEF_QUEUE,
Brett Russ20f733e2005-09-01 18:26:17 -0400479 .this_id = ATA_SHT_THIS_ID,
Jeff Garzikbaf14aa2007-10-09 13:51:57 -0400480 .sg_tablesize = MV_MAX_SG_CT / 2,
Brett Russ20f733e2005-09-01 18:26:17 -0400481 .cmd_per_lun = ATA_SHT_CMD_PER_LUN,
482 .emulated = ATA_SHT_EMULATED,
Jeff Garzikd88184f2007-02-26 01:26:06 -0500483 .use_clustering = 1,
Brett Russ20f733e2005-09-01 18:26:17 -0400484 .proc_name = DRV_NAME,
485 .dma_boundary = MV_DMA_BOUNDARY,
Jeff Garzik3be6cbd2007-10-18 16:21:18 -0400486 .slave_configure = ata_scsi_slave_config,
Tejun Heoccf68c32006-05-31 18:28:09 +0900487 .slave_destroy = ata_scsi_slave_destroy,
Brett Russ20f733e2005-09-01 18:26:17 -0400488 .bios_param = ata_std_bios_param,
Brett Russ20f733e2005-09-01 18:26:17 -0400489};
490
Jeff Garzikc9d39132005-11-13 17:47:51 -0500491static const struct ata_port_operations mv5_ops = {
Jeff Garzikc9d39132005-11-13 17:47:51 -0500492 .tf_load = ata_tf_load,
493 .tf_read = ata_tf_read,
494 .check_status = ata_check_status,
495 .exec_command = ata_exec_command,
496 .dev_select = ata_std_dev_select,
497
Jeff Garzikcffacd82007-03-09 09:46:47 -0500498 .cable_detect = ata_cable_sata,
Jeff Garzikc9d39132005-11-13 17:47:51 -0500499
500 .qc_prep = mv_qc_prep,
501 .qc_issue = mv_qc_issue,
Tejun Heo0d5ff562007-02-01 15:06:36 +0900502 .data_xfer = ata_data_xfer,
Jeff Garzikc9d39132005-11-13 17:47:51 -0500503
Jeff Garzikc9d39132005-11-13 17:47:51 -0500504 .irq_clear = mv_irq_clear,
Akira Iguchi246ce3b2007-01-26 16:27:58 +0900505 .irq_on = ata_irq_on,
Jeff Garzikc9d39132005-11-13 17:47:51 -0500506
Jeff Garzikbdd4ddd2007-07-12 14:34:26 -0400507 .error_handler = mv_error_handler,
508 .post_internal_cmd = mv_post_int_cmd,
509 .freeze = mv_eh_freeze,
510 .thaw = mv_eh_thaw,
511
Jeff Garzikc9d39132005-11-13 17:47:51 -0500512 .scr_read = mv5_scr_read,
513 .scr_write = mv5_scr_write,
514
515 .port_start = mv_port_start,
516 .port_stop = mv_port_stop,
Jeff Garzikc9d39132005-11-13 17:47:51 -0500517};
518
519static const struct ata_port_operations mv6_ops = {
Brett Russ20f733e2005-09-01 18:26:17 -0400520 .tf_load = ata_tf_load,
521 .tf_read = ata_tf_read,
522 .check_status = ata_check_status,
523 .exec_command = ata_exec_command,
524 .dev_select = ata_std_dev_select,
525
Jeff Garzikcffacd82007-03-09 09:46:47 -0500526 .cable_detect = ata_cable_sata,
Brett Russ20f733e2005-09-01 18:26:17 -0400527
Brett Russ31961942005-09-30 01:36:00 -0400528 .qc_prep = mv_qc_prep,
529 .qc_issue = mv_qc_issue,
Tejun Heo0d5ff562007-02-01 15:06:36 +0900530 .data_xfer = ata_data_xfer,
Brett Russ20f733e2005-09-01 18:26:17 -0400531
Brett Russ20f733e2005-09-01 18:26:17 -0400532 .irq_clear = mv_irq_clear,
Akira Iguchi246ce3b2007-01-26 16:27:58 +0900533 .irq_on = ata_irq_on,
Brett Russ20f733e2005-09-01 18:26:17 -0400534
Jeff Garzikbdd4ddd2007-07-12 14:34:26 -0400535 .error_handler = mv_error_handler,
536 .post_internal_cmd = mv_post_int_cmd,
537 .freeze = mv_eh_freeze,
538 .thaw = mv_eh_thaw,
539
Brett Russ20f733e2005-09-01 18:26:17 -0400540 .scr_read = mv_scr_read,
541 .scr_write = mv_scr_write,
542
Brett Russ31961942005-09-30 01:36:00 -0400543 .port_start = mv_port_start,
544 .port_stop = mv_port_stop,
Brett Russ20f733e2005-09-01 18:26:17 -0400545};
546
Jeff Garzike4e7b892006-01-31 12:18:41 -0500547static const struct ata_port_operations mv_iie_ops = {
Jeff Garzike4e7b892006-01-31 12:18:41 -0500548 .tf_load = ata_tf_load,
549 .tf_read = ata_tf_read,
550 .check_status = ata_check_status,
551 .exec_command = ata_exec_command,
552 .dev_select = ata_std_dev_select,
553
Jeff Garzikcffacd82007-03-09 09:46:47 -0500554 .cable_detect = ata_cable_sata,
Jeff Garzike4e7b892006-01-31 12:18:41 -0500555
556 .qc_prep = mv_qc_prep_iie,
557 .qc_issue = mv_qc_issue,
Tejun Heo0d5ff562007-02-01 15:06:36 +0900558 .data_xfer = ata_data_xfer,
Jeff Garzike4e7b892006-01-31 12:18:41 -0500559
Jeff Garzike4e7b892006-01-31 12:18:41 -0500560 .irq_clear = mv_irq_clear,
Akira Iguchi246ce3b2007-01-26 16:27:58 +0900561 .irq_on = ata_irq_on,
Jeff Garzike4e7b892006-01-31 12:18:41 -0500562
Jeff Garzikbdd4ddd2007-07-12 14:34:26 -0400563 .error_handler = mv_error_handler,
564 .post_internal_cmd = mv_post_int_cmd,
565 .freeze = mv_eh_freeze,
566 .thaw = mv_eh_thaw,
567
Jeff Garzike4e7b892006-01-31 12:18:41 -0500568 .scr_read = mv_scr_read,
569 .scr_write = mv_scr_write,
570
571 .port_start = mv_port_start,
572 .port_stop = mv_port_stop,
Jeff Garzike4e7b892006-01-31 12:18:41 -0500573};
574
Arjan van de Ven98ac62d2005-11-28 10:06:23 +0100575static const struct ata_port_info mv_port_info[] = {
Brett Russ20f733e2005-09-01 18:26:17 -0400576 { /* chip_504x */
Jeff Garzikcca39742006-08-24 03:19:22 -0400577 .flags = MV_COMMON_FLAGS,
Brett Russ31961942005-09-30 01:36:00 -0400578 .pio_mask = 0x1f, /* pio0-4 */
Jeff Garzikbf6263a2007-07-09 12:16:50 -0400579 .udma_mask = ATA_UDMA6,
Jeff Garzikc9d39132005-11-13 17:47:51 -0500580 .port_ops = &mv5_ops,
Brett Russ20f733e2005-09-01 18:26:17 -0400581 },
582 { /* chip_508x */
Jeff Garzikc5d3e452007-07-11 18:30:50 -0400583 .flags = MV_COMMON_FLAGS | MV_FLAG_DUAL_HC,
Brett Russ31961942005-09-30 01:36:00 -0400584 .pio_mask = 0x1f, /* pio0-4 */
Jeff Garzikbf6263a2007-07-09 12:16:50 -0400585 .udma_mask = ATA_UDMA6,
Jeff Garzikc9d39132005-11-13 17:47:51 -0500586 .port_ops = &mv5_ops,
Brett Russ20f733e2005-09-01 18:26:17 -0400587 },
Jeff Garzik47c2b672005-11-12 21:13:17 -0500588 { /* chip_5080 */
Jeff Garzikc5d3e452007-07-11 18:30:50 -0400589 .flags = MV_COMMON_FLAGS | MV_FLAG_DUAL_HC,
Jeff Garzik47c2b672005-11-12 21:13:17 -0500590 .pio_mask = 0x1f, /* pio0-4 */
Jeff Garzikbf6263a2007-07-09 12:16:50 -0400591 .udma_mask = ATA_UDMA6,
Jeff Garzikc9d39132005-11-13 17:47:51 -0500592 .port_ops = &mv5_ops,
Jeff Garzik47c2b672005-11-12 21:13:17 -0500593 },
Brett Russ20f733e2005-09-01 18:26:17 -0400594 { /* chip_604x */
Jeff Garzikc5d3e452007-07-11 18:30:50 -0400595 .flags = MV_COMMON_FLAGS | MV_6XXX_FLAGS,
Brett Russ31961942005-09-30 01:36:00 -0400596 .pio_mask = 0x1f, /* pio0-4 */
Jeff Garzikbf6263a2007-07-09 12:16:50 -0400597 .udma_mask = ATA_UDMA6,
Jeff Garzikc9d39132005-11-13 17:47:51 -0500598 .port_ops = &mv6_ops,
Brett Russ20f733e2005-09-01 18:26:17 -0400599 },
600 { /* chip_608x */
Jeff Garzikc5d3e452007-07-11 18:30:50 -0400601 .flags = MV_COMMON_FLAGS | MV_6XXX_FLAGS |
602 MV_FLAG_DUAL_HC,
Brett Russ31961942005-09-30 01:36:00 -0400603 .pio_mask = 0x1f, /* pio0-4 */
Jeff Garzikbf6263a2007-07-09 12:16:50 -0400604 .udma_mask = ATA_UDMA6,
Jeff Garzikc9d39132005-11-13 17:47:51 -0500605 .port_ops = &mv6_ops,
Brett Russ20f733e2005-09-01 18:26:17 -0400606 },
Jeff Garzike4e7b892006-01-31 12:18:41 -0500607 { /* chip_6042 */
Jeff Garzikc5d3e452007-07-11 18:30:50 -0400608 .flags = MV_COMMON_FLAGS | MV_6XXX_FLAGS,
Jeff Garzike4e7b892006-01-31 12:18:41 -0500609 .pio_mask = 0x1f, /* pio0-4 */
Jeff Garzikbf6263a2007-07-09 12:16:50 -0400610 .udma_mask = ATA_UDMA6,
Jeff Garzike4e7b892006-01-31 12:18:41 -0500611 .port_ops = &mv_iie_ops,
612 },
613 { /* chip_7042 */
Jeff Garzikc5d3e452007-07-11 18:30:50 -0400614 .flags = MV_COMMON_FLAGS | MV_6XXX_FLAGS,
Jeff Garzike4e7b892006-01-31 12:18:41 -0500615 .pio_mask = 0x1f, /* pio0-4 */
Jeff Garzikbf6263a2007-07-09 12:16:50 -0400616 .udma_mask = ATA_UDMA6,
Jeff Garzike4e7b892006-01-31 12:18:41 -0500617 .port_ops = &mv_iie_ops,
618 },
Brett Russ20f733e2005-09-01 18:26:17 -0400619};
620
Jeff Garzik3b7d6972005-11-10 11:04:11 -0500621static const struct pci_device_id mv_pci_tbl[] = {
Jeff Garzik2d2744f2006-09-28 20:21:59 -0400622 { PCI_VDEVICE(MARVELL, 0x5040), chip_504x },
623 { PCI_VDEVICE(MARVELL, 0x5041), chip_504x },
624 { PCI_VDEVICE(MARVELL, 0x5080), chip_5080 },
625 { PCI_VDEVICE(MARVELL, 0x5081), chip_508x },
Alan Coxcfbf7232007-07-09 14:38:41 +0100626 /* RocketRAID 1740/174x have different identifiers */
627 { PCI_VDEVICE(TTI, 0x1740), chip_508x },
628 { PCI_VDEVICE(TTI, 0x1742), chip_508x },
Brett Russ20f733e2005-09-01 18:26:17 -0400629
Jeff Garzik2d2744f2006-09-28 20:21:59 -0400630 { PCI_VDEVICE(MARVELL, 0x6040), chip_604x },
631 { PCI_VDEVICE(MARVELL, 0x6041), chip_604x },
632 { PCI_VDEVICE(MARVELL, 0x6042), chip_6042 },
633 { PCI_VDEVICE(MARVELL, 0x6080), chip_608x },
634 { PCI_VDEVICE(MARVELL, 0x6081), chip_608x },
Jeff Garzik29179532005-11-11 08:08:03 -0500635
Jeff Garzik2d2744f2006-09-28 20:21:59 -0400636 { PCI_VDEVICE(ADAPTEC2, 0x0241), chip_604x },
637
Florian Attenbergerd9f9c6b2007-07-02 17:09:29 +0200638 /* Adaptec 1430SA */
639 { PCI_VDEVICE(ADAPTEC2, 0x0243), chip_7042 },
640
Mark Lord02a121d2007-12-01 13:07:22 -0500641 /* Marvell 7042 support */
Morrison, Tom6a3d5862007-03-06 02:38:10 -0800642 { PCI_VDEVICE(MARVELL, 0x7042), chip_7042 },
643
Mark Lord02a121d2007-12-01 13:07:22 -0500644 /* Highpoint RocketRAID PCIe series */
645 { PCI_VDEVICE(TTI, 0x2300), chip_7042 },
646 { PCI_VDEVICE(TTI, 0x2310), chip_7042 },
647
Jeff Garzik2d2744f2006-09-28 20:21:59 -0400648 { } /* terminate list */
Brett Russ20f733e2005-09-01 18:26:17 -0400649};
650
651static struct pci_driver mv_pci_driver = {
652 .name = DRV_NAME,
653 .id_table = mv_pci_tbl,
654 .probe = mv_init_one,
655 .remove = ata_pci_remove_one,
656};
657
Jeff Garzik47c2b672005-11-12 21:13:17 -0500658static const struct mv_hw_ops mv5xxx_ops = {
659 .phy_errata = mv5_phy_errata,
660 .enable_leds = mv5_enable_leds,
661 .read_preamp = mv5_read_preamp,
662 .reset_hc = mv5_reset_hc,
Jeff Garzik522479f2005-11-12 22:14:02 -0500663 .reset_flash = mv5_reset_flash,
664 .reset_bus = mv5_reset_bus,
Jeff Garzik47c2b672005-11-12 21:13:17 -0500665};
666
667static const struct mv_hw_ops mv6xxx_ops = {
668 .phy_errata = mv6_phy_errata,
669 .enable_leds = mv6_enable_leds,
670 .read_preamp = mv6_read_preamp,
671 .reset_hc = mv6_reset_hc,
Jeff Garzik522479f2005-11-12 22:14:02 -0500672 .reset_flash = mv6_reset_flash,
673 .reset_bus = mv_reset_pci_bus,
Jeff Garzik47c2b672005-11-12 21:13:17 -0500674};
675
Brett Russ20f733e2005-09-01 18:26:17 -0400676/*
Jeff Garzikddef9bb2006-02-02 16:17:06 -0500677 * module options
678 */
679static int msi; /* Use PCI msi; either zero (off, default) or non-zero */
680
681
Jeff Garzikd88184f2007-02-26 01:26:06 -0500682/* move to PCI layer or libata core? */
683static int pci_go_64(struct pci_dev *pdev)
684{
685 int rc;
686
687 if (!pci_set_dma_mask(pdev, DMA_64BIT_MASK)) {
688 rc = pci_set_consistent_dma_mask(pdev, DMA_64BIT_MASK);
689 if (rc) {
690 rc = pci_set_consistent_dma_mask(pdev, DMA_32BIT_MASK);
691 if (rc) {
692 dev_printk(KERN_ERR, &pdev->dev,
693 "64-bit DMA enable failed\n");
694 return rc;
695 }
696 }
697 } else {
698 rc = pci_set_dma_mask(pdev, DMA_32BIT_MASK);
699 if (rc) {
700 dev_printk(KERN_ERR, &pdev->dev,
701 "32-bit DMA enable failed\n");
702 return rc;
703 }
704 rc = pci_set_consistent_dma_mask(pdev, DMA_32BIT_MASK);
705 if (rc) {
706 dev_printk(KERN_ERR, &pdev->dev,
707 "32-bit consistent DMA enable failed\n");
708 return rc;
709 }
710 }
711
712 return rc;
713}
714
Jeff Garzikddef9bb2006-02-02 16:17:06 -0500715/*
Brett Russ20f733e2005-09-01 18:26:17 -0400716 * Functions
717 */
718
719static inline void writelfl(unsigned long data, void __iomem *addr)
720{
721 writel(data, addr);
722 (void) readl(addr); /* flush to avoid PCI posted write */
723}
724
Brett Russ20f733e2005-09-01 18:26:17 -0400725static inline void __iomem *mv_hc_base(void __iomem *base, unsigned int hc)
726{
727 return (base + MV_SATAHC0_REG_BASE + (hc * MV_SATAHC_REG_SZ));
728}
729
Jeff Garzikc9d39132005-11-13 17:47:51 -0500730static inline unsigned int mv_hc_from_port(unsigned int port)
731{
732 return port >> MV_PORT_HC_SHIFT;
733}
734
735static inline unsigned int mv_hardport_from_port(unsigned int port)
736{
737 return port & MV_PORT_MASK;
738}
739
740static inline void __iomem *mv_hc_base_from_port(void __iomem *base,
741 unsigned int port)
742{
743 return mv_hc_base(base, mv_hc_from_port(port));
744}
745
Brett Russ20f733e2005-09-01 18:26:17 -0400746static inline void __iomem *mv_port_base(void __iomem *base, unsigned int port)
747{
Jeff Garzikc9d39132005-11-13 17:47:51 -0500748 return mv_hc_base_from_port(base, port) +
Jeff Garzik8b260242005-11-12 12:32:50 -0500749 MV_SATAHC_ARBTR_REG_SZ +
Jeff Garzikc9d39132005-11-13 17:47:51 -0500750 (mv_hardport_from_port(port) * MV_PORT_REG_SZ);
Brett Russ20f733e2005-09-01 18:26:17 -0400751}
752
753static inline void __iomem *mv_ap_base(struct ata_port *ap)
754{
Tejun Heo0d5ff562007-02-01 15:06:36 +0900755 return mv_port_base(ap->host->iomap[MV_PRIMARY_BAR], ap->port_no);
Brett Russ20f733e2005-09-01 18:26:17 -0400756}
757
Jeff Garzikcca39742006-08-24 03:19:22 -0400758static inline int mv_get_hc_count(unsigned long port_flags)
Brett Russ20f733e2005-09-01 18:26:17 -0400759{
Jeff Garzikcca39742006-08-24 03:19:22 -0400760 return ((port_flags & MV_FLAG_DUAL_HC) ? 2 : 1);
Brett Russ20f733e2005-09-01 18:26:17 -0400761}
762
763static void mv_irq_clear(struct ata_port *ap)
764{
765}
766
Jeff Garzikc5d3e452007-07-11 18:30:50 -0400767static void mv_set_edma_ptrs(void __iomem *port_mmio,
768 struct mv_host_priv *hpriv,
769 struct mv_port_priv *pp)
770{
Jeff Garzikbdd4ddd2007-07-12 14:34:26 -0400771 u32 index;
772
Jeff Garzikc5d3e452007-07-11 18:30:50 -0400773 /*
774 * initialize request queue
775 */
Jeff Garzikbdd4ddd2007-07-12 14:34:26 -0400776 index = (pp->req_idx & MV_MAX_Q_DEPTH_MASK) << EDMA_REQ_Q_PTR_SHIFT;
777
Jeff Garzikc5d3e452007-07-11 18:30:50 -0400778 WARN_ON(pp->crqb_dma & 0x3ff);
779 writel((pp->crqb_dma >> 16) >> 16, port_mmio + EDMA_REQ_Q_BASE_HI_OFS);
Jeff Garzikbdd4ddd2007-07-12 14:34:26 -0400780 writelfl((pp->crqb_dma & EDMA_REQ_Q_BASE_LO_MASK) | index,
Jeff Garzikc5d3e452007-07-11 18:30:50 -0400781 port_mmio + EDMA_REQ_Q_IN_PTR_OFS);
782
783 if (hpriv->hp_flags & MV_HP_ERRATA_XX42A0)
Jeff Garzikbdd4ddd2007-07-12 14:34:26 -0400784 writelfl((pp->crqb_dma & 0xffffffff) | index,
Jeff Garzikc5d3e452007-07-11 18:30:50 -0400785 port_mmio + EDMA_REQ_Q_OUT_PTR_OFS);
786 else
Jeff Garzikbdd4ddd2007-07-12 14:34:26 -0400787 writelfl(index, port_mmio + EDMA_REQ_Q_OUT_PTR_OFS);
Jeff Garzikc5d3e452007-07-11 18:30:50 -0400788
789 /*
790 * initialize response queue
791 */
Jeff Garzikbdd4ddd2007-07-12 14:34:26 -0400792 index = (pp->resp_idx & MV_MAX_Q_DEPTH_MASK) << EDMA_RSP_Q_PTR_SHIFT;
793
Jeff Garzikc5d3e452007-07-11 18:30:50 -0400794 WARN_ON(pp->crpb_dma & 0xff);
795 writel((pp->crpb_dma >> 16) >> 16, port_mmio + EDMA_RSP_Q_BASE_HI_OFS);
796
797 if (hpriv->hp_flags & MV_HP_ERRATA_XX42A0)
Jeff Garzikbdd4ddd2007-07-12 14:34:26 -0400798 writelfl((pp->crpb_dma & 0xffffffff) | index,
Jeff Garzikc5d3e452007-07-11 18:30:50 -0400799 port_mmio + EDMA_RSP_Q_IN_PTR_OFS);
800 else
Jeff Garzikbdd4ddd2007-07-12 14:34:26 -0400801 writelfl(index, port_mmio + EDMA_RSP_Q_IN_PTR_OFS);
Jeff Garzikc5d3e452007-07-11 18:30:50 -0400802
Jeff Garzikbdd4ddd2007-07-12 14:34:26 -0400803 writelfl((pp->crpb_dma & EDMA_RSP_Q_BASE_LO_MASK) | index,
Jeff Garzikc5d3e452007-07-11 18:30:50 -0400804 port_mmio + EDMA_RSP_Q_OUT_PTR_OFS);
Jeff Garzikc5d3e452007-07-11 18:30:50 -0400805}
806
Brett Russ05b308e2005-10-05 17:08:53 -0400807/**
808 * mv_start_dma - Enable eDMA engine
809 * @base: port base address
810 * @pp: port private data
811 *
Tejun Heobeec7db2006-02-11 19:11:13 +0900812 * Verify the local cache of the eDMA state is accurate with a
813 * WARN_ON.
Brett Russ05b308e2005-10-05 17:08:53 -0400814 *
815 * LOCKING:
816 * Inherited from caller.
817 */
Jeff Garzikc5d3e452007-07-11 18:30:50 -0400818static void mv_start_dma(void __iomem *base, struct mv_host_priv *hpriv,
819 struct mv_port_priv *pp)
Brett Russ31961942005-09-30 01:36:00 -0400820{
Jeff Garzikc5d3e452007-07-11 18:30:50 -0400821 if (!(pp->pp_flags & MV_PP_FLAG_EDMA_EN)) {
Jeff Garzikbdd4ddd2007-07-12 14:34:26 -0400822 /* clear EDMA event indicators, if any */
823 writelfl(0, base + EDMA_ERR_IRQ_CAUSE_OFS);
824
825 mv_set_edma_ptrs(base, hpriv, pp);
826
Brett Russafb0edd2005-10-05 17:08:42 -0400827 writelfl(EDMA_EN, base + EDMA_CMD_OFS);
828 pp->pp_flags |= MV_PP_FLAG_EDMA_EN;
829 }
Tejun Heobeec7db2006-02-11 19:11:13 +0900830 WARN_ON(!(EDMA_EN & readl(base + EDMA_CMD_OFS)));
Brett Russ31961942005-09-30 01:36:00 -0400831}
832
Brett Russ05b308e2005-10-05 17:08:53 -0400833/**
Jeff Garzik0ea9e172007-07-13 17:06:45 -0400834 * __mv_stop_dma - Disable eDMA engine
Brett Russ05b308e2005-10-05 17:08:53 -0400835 * @ap: ATA channel to manipulate
836 *
Tejun Heobeec7db2006-02-11 19:11:13 +0900837 * Verify the local cache of the eDMA state is accurate with a
838 * WARN_ON.
Brett Russ05b308e2005-10-05 17:08:53 -0400839 *
840 * LOCKING:
841 * Inherited from caller.
842 */
Jeff Garzik0ea9e172007-07-13 17:06:45 -0400843static int __mv_stop_dma(struct ata_port *ap)
Brett Russ31961942005-09-30 01:36:00 -0400844{
845 void __iomem *port_mmio = mv_ap_base(ap);
846 struct mv_port_priv *pp = ap->private_data;
Brett Russ31961942005-09-30 01:36:00 -0400847 u32 reg;
Jeff Garzikc5d3e452007-07-11 18:30:50 -0400848 int i, err = 0;
Brett Russ31961942005-09-30 01:36:00 -0400849
Jeff Garzik4537deb2007-07-12 14:30:19 -0400850 if (pp->pp_flags & MV_PP_FLAG_EDMA_EN) {
Brett Russafb0edd2005-10-05 17:08:42 -0400851 /* Disable EDMA if active. The disable bit auto clears.
Brett Russ31961942005-09-30 01:36:00 -0400852 */
Brett Russ31961942005-09-30 01:36:00 -0400853 writelfl(EDMA_DS, port_mmio + EDMA_CMD_OFS);
854 pp->pp_flags &= ~MV_PP_FLAG_EDMA_EN;
Brett Russafb0edd2005-10-05 17:08:42 -0400855 } else {
Tejun Heobeec7db2006-02-11 19:11:13 +0900856 WARN_ON(EDMA_EN & readl(port_mmio + EDMA_CMD_OFS));
Jeff Garzik2dcb4072007-10-19 06:42:56 -0400857 }
Jeff Garzik8b260242005-11-12 12:32:50 -0500858
Brett Russ31961942005-09-30 01:36:00 -0400859 /* now properly wait for the eDMA to stop */
860 for (i = 1000; i > 0; i--) {
861 reg = readl(port_mmio + EDMA_CMD_OFS);
Jeff Garzik4537deb2007-07-12 14:30:19 -0400862 if (!(reg & EDMA_EN))
Brett Russ31961942005-09-30 01:36:00 -0400863 break;
Jeff Garzik4537deb2007-07-12 14:30:19 -0400864
Brett Russ31961942005-09-30 01:36:00 -0400865 udelay(100);
866 }
867
Jeff Garzikc5d3e452007-07-11 18:30:50 -0400868 if (reg & EDMA_EN) {
Tejun Heof15a1da2006-05-15 20:57:56 +0900869 ata_port_printk(ap, KERN_ERR, "Unable to stop eDMA\n");
Jeff Garzikc5d3e452007-07-11 18:30:50 -0400870 err = -EIO;
Brett Russ31961942005-09-30 01:36:00 -0400871 }
Jeff Garzikc5d3e452007-07-11 18:30:50 -0400872
873 return err;
Brett Russ31961942005-09-30 01:36:00 -0400874}
875
Jeff Garzik0ea9e172007-07-13 17:06:45 -0400876static int mv_stop_dma(struct ata_port *ap)
877{
878 unsigned long flags;
879 int rc;
880
881 spin_lock_irqsave(&ap->host->lock, flags);
882 rc = __mv_stop_dma(ap);
883 spin_unlock_irqrestore(&ap->host->lock, flags);
884
885 return rc;
886}
887
Jeff Garzik8a70f8d2005-10-05 17:19:47 -0400888#ifdef ATA_DEBUG
Brett Russ31961942005-09-30 01:36:00 -0400889static void mv_dump_mem(void __iomem *start, unsigned bytes)
890{
Brett Russ31961942005-09-30 01:36:00 -0400891 int b, w;
892 for (b = 0; b < bytes; ) {
893 DPRINTK("%p: ", start + b);
894 for (w = 0; b < bytes && w < 4; w++) {
Jeff Garzik2dcb4072007-10-19 06:42:56 -0400895 printk("%08x ", readl(start + b));
Brett Russ31961942005-09-30 01:36:00 -0400896 b += sizeof(u32);
897 }
898 printk("\n");
899 }
Brett Russ31961942005-09-30 01:36:00 -0400900}
Jeff Garzik8a70f8d2005-10-05 17:19:47 -0400901#endif
902
Brett Russ31961942005-09-30 01:36:00 -0400903static void mv_dump_pci_cfg(struct pci_dev *pdev, unsigned bytes)
904{
905#ifdef ATA_DEBUG
906 int b, w;
907 u32 dw;
908 for (b = 0; b < bytes; ) {
909 DPRINTK("%02x: ", b);
910 for (w = 0; b < bytes && w < 4; w++) {
Jeff Garzik2dcb4072007-10-19 06:42:56 -0400911 (void) pci_read_config_dword(pdev, b, &dw);
912 printk("%08x ", dw);
Brett Russ31961942005-09-30 01:36:00 -0400913 b += sizeof(u32);
914 }
915 printk("\n");
916 }
917#endif
918}
919static void mv_dump_all_regs(void __iomem *mmio_base, int port,
920 struct pci_dev *pdev)
921{
922#ifdef ATA_DEBUG
Jeff Garzik8b260242005-11-12 12:32:50 -0500923 void __iomem *hc_base = mv_hc_base(mmio_base,
Brett Russ31961942005-09-30 01:36:00 -0400924 port >> MV_PORT_HC_SHIFT);
925 void __iomem *port_base;
926 int start_port, num_ports, p, start_hc, num_hcs, hc;
927
928 if (0 > port) {
929 start_hc = start_port = 0;
930 num_ports = 8; /* shld be benign for 4 port devs */
931 num_hcs = 2;
932 } else {
933 start_hc = port >> MV_PORT_HC_SHIFT;
934 start_port = port;
935 num_ports = num_hcs = 1;
936 }
Jeff Garzik8b260242005-11-12 12:32:50 -0500937 DPRINTK("All registers for port(s) %u-%u:\n", start_port,
Brett Russ31961942005-09-30 01:36:00 -0400938 num_ports > 1 ? num_ports - 1 : start_port);
939
940 if (NULL != pdev) {
941 DPRINTK("PCI config space regs:\n");
942 mv_dump_pci_cfg(pdev, 0x68);
943 }
944 DPRINTK("PCI regs:\n");
945 mv_dump_mem(mmio_base+0xc00, 0x3c);
946 mv_dump_mem(mmio_base+0xd00, 0x34);
947 mv_dump_mem(mmio_base+0xf00, 0x4);
948 mv_dump_mem(mmio_base+0x1d00, 0x6c);
949 for (hc = start_hc; hc < start_hc + num_hcs; hc++) {
Dan Alonid220c372006-04-10 23:20:22 -0700950 hc_base = mv_hc_base(mmio_base, hc);
Brett Russ31961942005-09-30 01:36:00 -0400951 DPRINTK("HC regs (HC %i):\n", hc);
952 mv_dump_mem(hc_base, 0x1c);
953 }
954 for (p = start_port; p < start_port + num_ports; p++) {
955 port_base = mv_port_base(mmio_base, p);
Jeff Garzik2dcb4072007-10-19 06:42:56 -0400956 DPRINTK("EDMA regs (port %i):\n", p);
Brett Russ31961942005-09-30 01:36:00 -0400957 mv_dump_mem(port_base, 0x54);
Jeff Garzik2dcb4072007-10-19 06:42:56 -0400958 DPRINTK("SATA regs (port %i):\n", p);
Brett Russ31961942005-09-30 01:36:00 -0400959 mv_dump_mem(port_base+0x300, 0x60);
960 }
961#endif
962}
963
Brett Russ20f733e2005-09-01 18:26:17 -0400964static unsigned int mv_scr_offset(unsigned int sc_reg_in)
965{
966 unsigned int ofs;
967
968 switch (sc_reg_in) {
969 case SCR_STATUS:
970 case SCR_CONTROL:
971 case SCR_ERROR:
972 ofs = SATA_STATUS_OFS + (sc_reg_in * sizeof(u32));
973 break;
974 case SCR_ACTIVE:
975 ofs = SATA_ACTIVE_OFS; /* active is not with the others */
976 break;
977 default:
978 ofs = 0xffffffffU;
979 break;
980 }
981 return ofs;
982}
983
Tejun Heoda3dbb12007-07-16 14:29:40 +0900984static int mv_scr_read(struct ata_port *ap, unsigned int sc_reg_in, u32 *val)
Brett Russ20f733e2005-09-01 18:26:17 -0400985{
986 unsigned int ofs = mv_scr_offset(sc_reg_in);
987
Tejun Heoda3dbb12007-07-16 14:29:40 +0900988 if (ofs != 0xffffffffU) {
989 *val = readl(mv_ap_base(ap) + ofs);
990 return 0;
991 } else
992 return -EINVAL;
Brett Russ20f733e2005-09-01 18:26:17 -0400993}
994
Tejun Heoda3dbb12007-07-16 14:29:40 +0900995static int mv_scr_write(struct ata_port *ap, unsigned int sc_reg_in, u32 val)
Brett Russ20f733e2005-09-01 18:26:17 -0400996{
997 unsigned int ofs = mv_scr_offset(sc_reg_in);
998
Tejun Heoda3dbb12007-07-16 14:29:40 +0900999 if (ofs != 0xffffffffU) {
Brett Russ20f733e2005-09-01 18:26:17 -04001000 writelfl(val, mv_ap_base(ap) + ofs);
Tejun Heoda3dbb12007-07-16 14:29:40 +09001001 return 0;
1002 } else
1003 return -EINVAL;
Brett Russ20f733e2005-09-01 18:26:17 -04001004}
1005
Jeff Garzikc5d3e452007-07-11 18:30:50 -04001006static void mv_edma_cfg(struct ata_port *ap, struct mv_host_priv *hpriv,
1007 void __iomem *port_mmio)
Jeff Garzike4e7b892006-01-31 12:18:41 -05001008{
1009 u32 cfg = readl(port_mmio + EDMA_CFG_OFS);
1010
1011 /* set up non-NCQ EDMA configuration */
Jeff Garzikc5d3e452007-07-11 18:30:50 -04001012 cfg &= ~(1 << 9); /* disable eQue */
Jeff Garzike4e7b892006-01-31 12:18:41 -05001013
Jeff Garzike728eab2007-02-25 02:53:41 -05001014 if (IS_GEN_I(hpriv)) {
1015 cfg &= ~0x1f; /* clear queue depth */
Jeff Garzike4e7b892006-01-31 12:18:41 -05001016 cfg |= (1 << 8); /* enab config burst size mask */
Jeff Garzike728eab2007-02-25 02:53:41 -05001017 }
Jeff Garzike4e7b892006-01-31 12:18:41 -05001018
Jeff Garzike728eab2007-02-25 02:53:41 -05001019 else if (IS_GEN_II(hpriv)) {
1020 cfg &= ~0x1f; /* clear queue depth */
Jeff Garzike4e7b892006-01-31 12:18:41 -05001021 cfg |= EDMA_CFG_RD_BRST_EXT | EDMA_CFG_WR_BUFF_LEN;
Jeff Garzike728eab2007-02-25 02:53:41 -05001022 cfg &= ~(EDMA_CFG_NCQ | EDMA_CFG_NCQ_GO_ON_ERR); /* clear NCQ */
1023 }
Jeff Garzike4e7b892006-01-31 12:18:41 -05001024
1025 else if (IS_GEN_IIE(hpriv)) {
Jeff Garzike728eab2007-02-25 02:53:41 -05001026 cfg |= (1 << 23); /* do not mask PM field in rx'd FIS */
1027 cfg |= (1 << 22); /* enab 4-entry host queue cache */
Jeff Garzike4e7b892006-01-31 12:18:41 -05001028 cfg &= ~(1 << 19); /* dis 128-entry queue (for now?) */
1029 cfg |= (1 << 18); /* enab early completion */
Jeff Garzike728eab2007-02-25 02:53:41 -05001030 cfg |= (1 << 17); /* enab cut-through (dis stor&forwrd) */
1031 cfg &= ~(1 << 16); /* dis FIS-based switching (for now) */
Jeff Garzik4537deb2007-07-12 14:30:19 -04001032 cfg &= ~(EDMA_CFG_NCQ); /* clear NCQ */
Jeff Garzike4e7b892006-01-31 12:18:41 -05001033 }
1034
1035 writelfl(cfg, port_mmio + EDMA_CFG_OFS);
1036}
1037
Brett Russ05b308e2005-10-05 17:08:53 -04001038/**
1039 * mv_port_start - Port specific init/start routine.
1040 * @ap: ATA channel to manipulate
1041 *
1042 * Allocate and point to DMA memory, init port private memory,
1043 * zero indices.
1044 *
1045 * LOCKING:
1046 * Inherited from caller.
1047 */
Brett Russ31961942005-09-30 01:36:00 -04001048static int mv_port_start(struct ata_port *ap)
1049{
Jeff Garzikcca39742006-08-24 03:19:22 -04001050 struct device *dev = ap->host->dev;
1051 struct mv_host_priv *hpriv = ap->host->private_data;
Brett Russ31961942005-09-30 01:36:00 -04001052 struct mv_port_priv *pp;
1053 void __iomem *port_mmio = mv_ap_base(ap);
1054 void *mem;
1055 dma_addr_t mem_dma;
Jeff Garzik0ea9e172007-07-13 17:06:45 -04001056 unsigned long flags;
Tejun Heo24dc5f32007-01-20 16:00:28 +09001057 int rc;
Brett Russ31961942005-09-30 01:36:00 -04001058
Tejun Heo24dc5f32007-01-20 16:00:28 +09001059 pp = devm_kzalloc(dev, sizeof(*pp), GFP_KERNEL);
Jeff Garzik6037d6b2005-11-04 22:08:00 -05001060 if (!pp)
Tejun Heo24dc5f32007-01-20 16:00:28 +09001061 return -ENOMEM;
Brett Russ31961942005-09-30 01:36:00 -04001062
Tejun Heo24dc5f32007-01-20 16:00:28 +09001063 mem = dmam_alloc_coherent(dev, MV_PORT_PRIV_DMA_SZ, &mem_dma,
1064 GFP_KERNEL);
Jeff Garzik6037d6b2005-11-04 22:08:00 -05001065 if (!mem)
Tejun Heo24dc5f32007-01-20 16:00:28 +09001066 return -ENOMEM;
Brett Russ31961942005-09-30 01:36:00 -04001067 memset(mem, 0, MV_PORT_PRIV_DMA_SZ);
1068
Jeff Garzik6037d6b2005-11-04 22:08:00 -05001069 rc = ata_pad_alloc(ap, dev);
1070 if (rc)
Tejun Heo24dc5f32007-01-20 16:00:28 +09001071 return rc;
Jeff Garzik6037d6b2005-11-04 22:08:00 -05001072
Jeff Garzik8b260242005-11-12 12:32:50 -05001073 /* First item in chunk of DMA memory:
Brett Russ31961942005-09-30 01:36:00 -04001074 * 32-slot command request table (CRQB), 32 bytes each in size
1075 */
1076 pp->crqb = mem;
1077 pp->crqb_dma = mem_dma;
1078 mem += MV_CRQB_Q_SZ;
1079 mem_dma += MV_CRQB_Q_SZ;
1080
Jeff Garzik8b260242005-11-12 12:32:50 -05001081 /* Second item:
Brett Russ31961942005-09-30 01:36:00 -04001082 * 32-slot command response table (CRPB), 8 bytes each in size
1083 */
1084 pp->crpb = mem;
1085 pp->crpb_dma = mem_dma;
1086 mem += MV_CRPB_Q_SZ;
1087 mem_dma += MV_CRPB_Q_SZ;
1088
1089 /* Third item:
1090 * Table of scatter-gather descriptors (ePRD), 16 bytes each
1091 */
1092 pp->sg_tbl = mem;
1093 pp->sg_tbl_dma = mem_dma;
1094
Jeff Garzik0ea9e172007-07-13 17:06:45 -04001095 spin_lock_irqsave(&ap->host->lock, flags);
1096
Jeff Garzikc5d3e452007-07-11 18:30:50 -04001097 mv_edma_cfg(ap, hpriv, port_mmio);
Brett Russ31961942005-09-30 01:36:00 -04001098
Jeff Garzikc5d3e452007-07-11 18:30:50 -04001099 mv_set_edma_ptrs(port_mmio, hpriv, pp);
Brett Russ31961942005-09-30 01:36:00 -04001100
Jeff Garzik0ea9e172007-07-13 17:06:45 -04001101 spin_unlock_irqrestore(&ap->host->lock, flags);
1102
Brett Russ31961942005-09-30 01:36:00 -04001103 /* Don't turn on EDMA here...do it before DMA commands only. Else
1104 * we'll be unable to send non-data, PIO, etc due to restricted access
1105 * to shadow regs.
1106 */
1107 ap->private_data = pp;
1108 return 0;
1109}
1110
Brett Russ05b308e2005-10-05 17:08:53 -04001111/**
1112 * mv_port_stop - Port specific cleanup/stop routine.
1113 * @ap: ATA channel to manipulate
1114 *
1115 * Stop DMA, cleanup port memory.
1116 *
1117 * LOCKING:
Jeff Garzikcca39742006-08-24 03:19:22 -04001118 * This routine uses the host lock to protect the DMA stop.
Brett Russ05b308e2005-10-05 17:08:53 -04001119 */
Brett Russ31961942005-09-30 01:36:00 -04001120static void mv_port_stop(struct ata_port *ap)
1121{
Brett Russ31961942005-09-30 01:36:00 -04001122 mv_stop_dma(ap);
Brett Russ31961942005-09-30 01:36:00 -04001123}
1124
Brett Russ05b308e2005-10-05 17:08:53 -04001125/**
1126 * mv_fill_sg - Fill out the Marvell ePRD (scatter gather) entries
1127 * @qc: queued command whose SG list to source from
1128 *
1129 * Populate the SG list and mark the last entry.
1130 *
1131 * LOCKING:
1132 * Inherited from caller.
1133 */
Jeff Garzik6c087722007-10-12 00:16:23 -04001134static void mv_fill_sg(struct ata_queued_cmd *qc)
Brett Russ31961942005-09-30 01:36:00 -04001135{
1136 struct mv_port_priv *pp = qc->ap->private_data;
Jeff Garzik972c26b2005-10-18 22:14:54 -04001137 struct scatterlist *sg;
Jeff Garzik3be6cbd2007-10-18 16:21:18 -04001138 struct mv_sg *mv_sg, *last_sg = NULL;
Tejun Heoff2aeb12007-12-05 16:43:11 +09001139 unsigned int si;
Brett Russ31961942005-09-30 01:36:00 -04001140
Jeff Garzikd88184f2007-02-26 01:26:06 -05001141 mv_sg = pp->sg_tbl;
Tejun Heoff2aeb12007-12-05 16:43:11 +09001142 for_each_sg(qc->sg, sg, qc->n_elem, si) {
Jeff Garzikd88184f2007-02-26 01:26:06 -05001143 dma_addr_t addr = sg_dma_address(sg);
1144 u32 sg_len = sg_dma_len(sg);
Brett Russ31961942005-09-30 01:36:00 -04001145
Olof Johansson4007b492007-10-02 20:45:27 -05001146 while (sg_len) {
1147 u32 offset = addr & 0xffff;
1148 u32 len = sg_len;
Brett Russ31961942005-09-30 01:36:00 -04001149
Olof Johansson4007b492007-10-02 20:45:27 -05001150 if ((offset + sg_len > 0x10000))
1151 len = 0x10000 - offset;
Jeff Garzik972c26b2005-10-18 22:14:54 -04001152
Olof Johansson4007b492007-10-02 20:45:27 -05001153 mv_sg->addr = cpu_to_le32(addr & 0xffffffff);
1154 mv_sg->addr_hi = cpu_to_le32((addr >> 16) >> 16);
Jeff Garzik6c087722007-10-12 00:16:23 -04001155 mv_sg->flags_size = cpu_to_le32(len & 0xffff);
Olof Johansson4007b492007-10-02 20:45:27 -05001156
1157 sg_len -= len;
1158 addr += len;
1159
Jeff Garzik3be6cbd2007-10-18 16:21:18 -04001160 last_sg = mv_sg;
Olof Johansson4007b492007-10-02 20:45:27 -05001161 mv_sg++;
Olof Johansson4007b492007-10-02 20:45:27 -05001162 }
Brett Russ31961942005-09-30 01:36:00 -04001163 }
Jeff Garzik3be6cbd2007-10-18 16:21:18 -04001164
1165 if (likely(last_sg))
1166 last_sg->flags_size |= cpu_to_le32(EPRD_FLAG_END_OF_TBL);
Brett Russ31961942005-09-30 01:36:00 -04001167}
1168
Jeff Garzik5796d1c2007-10-26 00:03:37 -04001169static void mv_crqb_pack_cmd(__le16 *cmdw, u8 data, u8 addr, unsigned last)
Brett Russ31961942005-09-30 01:36:00 -04001170{
Mark Lord559eeda2006-05-19 16:40:15 -04001171 u16 tmp = data | (addr << CRQB_CMD_ADDR_SHIFT) | CRQB_CMD_CS |
Brett Russ31961942005-09-30 01:36:00 -04001172 (last ? CRQB_CMD_LAST : 0);
Mark Lord559eeda2006-05-19 16:40:15 -04001173 *cmdw = cpu_to_le16(tmp);
Brett Russ31961942005-09-30 01:36:00 -04001174}
1175
Brett Russ05b308e2005-10-05 17:08:53 -04001176/**
1177 * mv_qc_prep - Host specific command preparation.
1178 * @qc: queued command to prepare
1179 *
1180 * This routine simply redirects to the general purpose routine
1181 * if command is not DMA. Else, it handles prep of the CRQB
1182 * (command request block), does some sanity checking, and calls
1183 * the SG load routine.
1184 *
1185 * LOCKING:
1186 * Inherited from caller.
1187 */
Brett Russ31961942005-09-30 01:36:00 -04001188static void mv_qc_prep(struct ata_queued_cmd *qc)
1189{
1190 struct ata_port *ap = qc->ap;
1191 struct mv_port_priv *pp = ap->private_data;
Mark Lorde1469872006-05-22 19:02:03 -04001192 __le16 *cw;
Brett Russ31961942005-09-30 01:36:00 -04001193 struct ata_taskfile *tf;
1194 u16 flags = 0;
Mark Lorda6432432006-05-19 16:36:36 -04001195 unsigned in_index;
Brett Russ31961942005-09-30 01:36:00 -04001196
Jeff Garzik2dcb4072007-10-19 06:42:56 -04001197 if (qc->tf.protocol != ATA_PROT_DMA)
Brett Russ31961942005-09-30 01:36:00 -04001198 return;
Brett Russ20f733e2005-09-01 18:26:17 -04001199
Brett Russ31961942005-09-30 01:36:00 -04001200 /* Fill in command request block
1201 */
Jeff Garzike4e7b892006-01-31 12:18:41 -05001202 if (!(qc->tf.flags & ATA_TFLAG_WRITE))
Brett Russ31961942005-09-30 01:36:00 -04001203 flags |= CRQB_FLAG_READ;
Tejun Heobeec7db2006-02-11 19:11:13 +09001204 WARN_ON(MV_MAX_Q_DEPTH <= qc->tag);
Brett Russ31961942005-09-30 01:36:00 -04001205 flags |= qc->tag << CRQB_TAG_SHIFT;
Jeff Garzik4537deb2007-07-12 14:30:19 -04001206 flags |= qc->tag << CRQB_IOID_SHIFT; /* 50xx appears to ignore this*/
Brett Russ31961942005-09-30 01:36:00 -04001207
Jeff Garzikbdd4ddd2007-07-12 14:34:26 -04001208 /* get current queue index from software */
1209 in_index = pp->req_idx & MV_MAX_Q_DEPTH_MASK;
Brett Russ31961942005-09-30 01:36:00 -04001210
Mark Lorda6432432006-05-19 16:36:36 -04001211 pp->crqb[in_index].sg_addr =
1212 cpu_to_le32(pp->sg_tbl_dma & 0xffffffff);
1213 pp->crqb[in_index].sg_addr_hi =
1214 cpu_to_le32((pp->sg_tbl_dma >> 16) >> 16);
1215 pp->crqb[in_index].ctrl_flags = cpu_to_le16(flags);
1216
1217 cw = &pp->crqb[in_index].ata_cmd[0];
Brett Russ31961942005-09-30 01:36:00 -04001218 tf = &qc->tf;
1219
1220 /* Sadly, the CRQB cannot accomodate all registers--there are
1221 * only 11 bytes...so we must pick and choose required
1222 * registers based on the command. So, we drop feature and
1223 * hob_feature for [RW] DMA commands, but they are needed for
1224 * NCQ. NCQ will drop hob_nsect.
1225 */
1226 switch (tf->command) {
1227 case ATA_CMD_READ:
1228 case ATA_CMD_READ_EXT:
1229 case ATA_CMD_WRITE:
1230 case ATA_CMD_WRITE_EXT:
Jens Axboec15d85c2006-02-15 15:59:25 +01001231 case ATA_CMD_WRITE_FUA_EXT:
Brett Russ31961942005-09-30 01:36:00 -04001232 mv_crqb_pack_cmd(cw++, tf->hob_nsect, ATA_REG_NSECT, 0);
1233 break;
1234#ifdef LIBATA_NCQ /* FIXME: remove this line when NCQ added */
1235 case ATA_CMD_FPDMA_READ:
1236 case ATA_CMD_FPDMA_WRITE:
Jeff Garzik8b260242005-11-12 12:32:50 -05001237 mv_crqb_pack_cmd(cw++, tf->hob_feature, ATA_REG_FEATURE, 0);
Brett Russ31961942005-09-30 01:36:00 -04001238 mv_crqb_pack_cmd(cw++, tf->feature, ATA_REG_FEATURE, 0);
1239 break;
1240#endif /* FIXME: remove this line when NCQ added */
1241 default:
1242 /* The only other commands EDMA supports in non-queued and
1243 * non-NCQ mode are: [RW] STREAM DMA and W DMA FUA EXT, none
1244 * of which are defined/used by Linux. If we get here, this
1245 * driver needs work.
1246 *
1247 * FIXME: modify libata to give qc_prep a return value and
1248 * return error here.
1249 */
1250 BUG_ON(tf->command);
1251 break;
1252 }
1253 mv_crqb_pack_cmd(cw++, tf->nsect, ATA_REG_NSECT, 0);
1254 mv_crqb_pack_cmd(cw++, tf->hob_lbal, ATA_REG_LBAL, 0);
1255 mv_crqb_pack_cmd(cw++, tf->lbal, ATA_REG_LBAL, 0);
1256 mv_crqb_pack_cmd(cw++, tf->hob_lbam, ATA_REG_LBAM, 0);
1257 mv_crqb_pack_cmd(cw++, tf->lbam, ATA_REG_LBAM, 0);
1258 mv_crqb_pack_cmd(cw++, tf->hob_lbah, ATA_REG_LBAH, 0);
1259 mv_crqb_pack_cmd(cw++, tf->lbah, ATA_REG_LBAH, 0);
1260 mv_crqb_pack_cmd(cw++, tf->device, ATA_REG_DEVICE, 0);
1261 mv_crqb_pack_cmd(cw++, tf->command, ATA_REG_CMD, 1); /* last */
1262
Jeff Garzike4e7b892006-01-31 12:18:41 -05001263 if (!(qc->flags & ATA_QCFLAG_DMAMAP))
Brett Russ31961942005-09-30 01:36:00 -04001264 return;
Jeff Garzike4e7b892006-01-31 12:18:41 -05001265 mv_fill_sg(qc);
1266}
1267
1268/**
1269 * mv_qc_prep_iie - Host specific command preparation.
1270 * @qc: queued command to prepare
1271 *
1272 * This routine simply redirects to the general purpose routine
1273 * if command is not DMA. Else, it handles prep of the CRQB
1274 * (command request block), does some sanity checking, and calls
1275 * the SG load routine.
1276 *
1277 * LOCKING:
1278 * Inherited from caller.
1279 */
1280static void mv_qc_prep_iie(struct ata_queued_cmd *qc)
1281{
1282 struct ata_port *ap = qc->ap;
1283 struct mv_port_priv *pp = ap->private_data;
1284 struct mv_crqb_iie *crqb;
1285 struct ata_taskfile *tf;
Mark Lorda6432432006-05-19 16:36:36 -04001286 unsigned in_index;
Jeff Garzike4e7b892006-01-31 12:18:41 -05001287 u32 flags = 0;
1288
Jeff Garzik2dcb4072007-10-19 06:42:56 -04001289 if (qc->tf.protocol != ATA_PROT_DMA)
Jeff Garzike4e7b892006-01-31 12:18:41 -05001290 return;
1291
Jeff Garzike4e7b892006-01-31 12:18:41 -05001292 /* Fill in Gen IIE command request block
1293 */
1294 if (!(qc->tf.flags & ATA_TFLAG_WRITE))
1295 flags |= CRQB_FLAG_READ;
1296
Tejun Heobeec7db2006-02-11 19:11:13 +09001297 WARN_ON(MV_MAX_Q_DEPTH <= qc->tag);
Jeff Garzike4e7b892006-01-31 12:18:41 -05001298 flags |= qc->tag << CRQB_TAG_SHIFT;
Jeff Garzikbdd4ddd2007-07-12 14:34:26 -04001299 flags |= qc->tag << CRQB_IOID_SHIFT; /* "I/O Id" is -really-
Jeff Garzik4537deb2007-07-12 14:30:19 -04001300 what we use as our tag */
Jeff Garzike4e7b892006-01-31 12:18:41 -05001301
Jeff Garzikbdd4ddd2007-07-12 14:34:26 -04001302 /* get current queue index from software */
1303 in_index = pp->req_idx & MV_MAX_Q_DEPTH_MASK;
Mark Lorda6432432006-05-19 16:36:36 -04001304
1305 crqb = (struct mv_crqb_iie *) &pp->crqb[in_index];
Jeff Garzike4e7b892006-01-31 12:18:41 -05001306 crqb->addr = cpu_to_le32(pp->sg_tbl_dma & 0xffffffff);
1307 crqb->addr_hi = cpu_to_le32((pp->sg_tbl_dma >> 16) >> 16);
1308 crqb->flags = cpu_to_le32(flags);
1309
1310 tf = &qc->tf;
1311 crqb->ata_cmd[0] = cpu_to_le32(
1312 (tf->command << 16) |
1313 (tf->feature << 24)
1314 );
1315 crqb->ata_cmd[1] = cpu_to_le32(
1316 (tf->lbal << 0) |
1317 (tf->lbam << 8) |
1318 (tf->lbah << 16) |
1319 (tf->device << 24)
1320 );
1321 crqb->ata_cmd[2] = cpu_to_le32(
1322 (tf->hob_lbal << 0) |
1323 (tf->hob_lbam << 8) |
1324 (tf->hob_lbah << 16) |
1325 (tf->hob_feature << 24)
1326 );
1327 crqb->ata_cmd[3] = cpu_to_le32(
1328 (tf->nsect << 0) |
1329 (tf->hob_nsect << 8)
1330 );
1331
1332 if (!(qc->flags & ATA_QCFLAG_DMAMAP))
1333 return;
Brett Russ31961942005-09-30 01:36:00 -04001334 mv_fill_sg(qc);
1335}
1336
Brett Russ05b308e2005-10-05 17:08:53 -04001337/**
1338 * mv_qc_issue - Initiate a command to the host
1339 * @qc: queued command to start
1340 *
1341 * This routine simply redirects to the general purpose routine
1342 * if command is not DMA. Else, it sanity checks our local
1343 * caches of the request producer/consumer indices then enables
1344 * DMA and bumps the request producer index.
1345 *
1346 * LOCKING:
1347 * Inherited from caller.
1348 */
Tejun Heo9a3d9eb2006-01-23 13:09:36 +09001349static unsigned int mv_qc_issue(struct ata_queued_cmd *qc)
Brett Russ31961942005-09-30 01:36:00 -04001350{
Jeff Garzikc5d3e452007-07-11 18:30:50 -04001351 struct ata_port *ap = qc->ap;
1352 void __iomem *port_mmio = mv_ap_base(ap);
1353 struct mv_port_priv *pp = ap->private_data;
1354 struct mv_host_priv *hpriv = ap->host->private_data;
Jeff Garzikbdd4ddd2007-07-12 14:34:26 -04001355 u32 in_index;
Brett Russ31961942005-09-30 01:36:00 -04001356
Jeff Garzikc5d3e452007-07-11 18:30:50 -04001357 if (qc->tf.protocol != ATA_PROT_DMA) {
Brett Russ31961942005-09-30 01:36:00 -04001358 /* We're about to send a non-EDMA capable command to the
1359 * port. Turn off EDMA so there won't be problems accessing
1360 * shadow block, etc registers.
1361 */
Jeff Garzik0ea9e172007-07-13 17:06:45 -04001362 __mv_stop_dma(ap);
Brett Russ31961942005-09-30 01:36:00 -04001363 return ata_qc_issue_prot(qc);
1364 }
1365
Jeff Garzikbdd4ddd2007-07-12 14:34:26 -04001366 mv_start_dma(port_mmio, hpriv, pp);
1367
1368 in_index = pp->req_idx & MV_MAX_Q_DEPTH_MASK;
Brett Russ31961942005-09-30 01:36:00 -04001369
Brett Russ31961942005-09-30 01:36:00 -04001370 /* until we do queuing, the queue should be empty at this point */
Mark Lorda6432432006-05-19 16:36:36 -04001371 WARN_ON(in_index != ((readl(port_mmio + EDMA_REQ_Q_OUT_PTR_OFS)
1372 >> EDMA_REQ_Q_PTR_SHIFT) & MV_MAX_Q_DEPTH_MASK));
Brett Russ31961942005-09-30 01:36:00 -04001373
Jeff Garzikbdd4ddd2007-07-12 14:34:26 -04001374 pp->req_idx++;
Brett Russ31961942005-09-30 01:36:00 -04001375
Jeff Garzikbdd4ddd2007-07-12 14:34:26 -04001376 in_index = (pp->req_idx & MV_MAX_Q_DEPTH_MASK) << EDMA_REQ_Q_PTR_SHIFT;
Brett Russ31961942005-09-30 01:36:00 -04001377
1378 /* and write the request in pointer to kick the EDMA to life */
Jeff Garzikbdd4ddd2007-07-12 14:34:26 -04001379 writelfl((pp->crqb_dma & EDMA_REQ_Q_BASE_LO_MASK) | in_index,
1380 port_mmio + EDMA_REQ_Q_IN_PTR_OFS);
Brett Russ31961942005-09-30 01:36:00 -04001381
1382 return 0;
1383}
1384
Brett Russ05b308e2005-10-05 17:08:53 -04001385/**
Brett Russ05b308e2005-10-05 17:08:53 -04001386 * mv_err_intr - Handle error interrupts on the port
1387 * @ap: ATA channel to manipulate
Mark Lord9b358e32006-05-19 16:21:03 -04001388 * @reset_allowed: bool: 0 == don't trigger from reset here
Brett Russ05b308e2005-10-05 17:08:53 -04001389 *
1390 * In most cases, just clear the interrupt and move on. However,
1391 * some cases require an eDMA reset, which is done right before
1392 * the COMRESET in mv_phy_reset(). The SERR case requires a
1393 * clear of pending errors in the SATA SERROR register. Finally,
1394 * if the port disabled DMA, update our cached copy to match.
1395 *
1396 * LOCKING:
1397 * Inherited from caller.
1398 */
Jeff Garzikbdd4ddd2007-07-12 14:34:26 -04001399static void mv_err_intr(struct ata_port *ap, struct ata_queued_cmd *qc)
Brett Russ20f733e2005-09-01 18:26:17 -04001400{
Brett Russ31961942005-09-30 01:36:00 -04001401 void __iomem *port_mmio = mv_ap_base(ap);
Jeff Garzikbdd4ddd2007-07-12 14:34:26 -04001402 u32 edma_err_cause, eh_freeze_mask, serr = 0;
1403 struct mv_port_priv *pp = ap->private_data;
1404 struct mv_host_priv *hpriv = ap->host->private_data;
1405 unsigned int edma_enabled = (pp->pp_flags & MV_PP_FLAG_EDMA_EN);
1406 unsigned int action = 0, err_mask = 0;
Tejun Heo9af5c9c2007-08-06 18:36:22 +09001407 struct ata_eh_info *ehi = &ap->link.eh_info;
Brett Russ20f733e2005-09-01 18:26:17 -04001408
Jeff Garzikbdd4ddd2007-07-12 14:34:26 -04001409 ata_ehi_clear_desc(ehi);
Brett Russ20f733e2005-09-01 18:26:17 -04001410
Jeff Garzikbdd4ddd2007-07-12 14:34:26 -04001411 if (!edma_enabled) {
1412 /* just a guess: do we need to do this? should we
1413 * expand this, and do it in all cases?
1414 */
Tejun Heo936fd732007-08-06 18:36:23 +09001415 sata_scr_read(&ap->link, SCR_ERROR, &serr);
1416 sata_scr_write_flush(&ap->link, SCR_ERROR, serr);
Brett Russ20f733e2005-09-01 18:26:17 -04001417 }
Jeff Garzikbdd4ddd2007-07-12 14:34:26 -04001418
1419 edma_err_cause = readl(port_mmio + EDMA_ERR_IRQ_CAUSE_OFS);
1420
1421 ata_ehi_push_desc(ehi, "edma_err 0x%08x", edma_err_cause);
1422
1423 /*
1424 * all generations share these EDMA error cause bits
1425 */
1426
1427 if (edma_err_cause & EDMA_ERR_DEV)
1428 err_mask |= AC_ERR_DEV;
1429 if (edma_err_cause & (EDMA_ERR_D_PAR | EDMA_ERR_PRD_PAR |
Jeff Garzik6c1153e2007-07-13 15:20:15 -04001430 EDMA_ERR_CRQB_PAR | EDMA_ERR_CRPB_PAR |
Jeff Garzikbdd4ddd2007-07-12 14:34:26 -04001431 EDMA_ERR_INTRL_PAR)) {
1432 err_mask |= AC_ERR_ATA_BUS;
1433 action |= ATA_EH_HARDRESET;
Tejun Heob64bbc32007-07-16 14:29:39 +09001434 ata_ehi_push_desc(ehi, "parity error");
Brett Russafb0edd2005-10-05 17:08:42 -04001435 }
Jeff Garzikbdd4ddd2007-07-12 14:34:26 -04001436 if (edma_err_cause & (EDMA_ERR_DEV_DCON | EDMA_ERR_DEV_CON)) {
1437 ata_ehi_hotplugged(ehi);
1438 ata_ehi_push_desc(ehi, edma_err_cause & EDMA_ERR_DEV_DCON ?
Tejun Heob64bbc32007-07-16 14:29:39 +09001439 "dev disconnect" : "dev connect");
Mark Lord3606a382008-01-26 18:28:23 -05001440 action |= ATA_EH_HARDRESET;
Jeff Garzikbdd4ddd2007-07-12 14:34:26 -04001441 }
1442
Jeff Garzikee9ccdf2007-07-12 15:51:22 -04001443 if (IS_GEN_I(hpriv)) {
Jeff Garzikbdd4ddd2007-07-12 14:34:26 -04001444 eh_freeze_mask = EDMA_EH_FREEZE_5;
1445
1446 if (edma_err_cause & EDMA_ERR_SELF_DIS_5) {
1447 struct mv_port_priv *pp = ap->private_data;
1448 pp->pp_flags &= ~MV_PP_FLAG_EDMA_EN;
Tejun Heob64bbc32007-07-16 14:29:39 +09001449 ata_ehi_push_desc(ehi, "EDMA self-disable");
Jeff Garzikbdd4ddd2007-07-12 14:34:26 -04001450 }
1451 } else {
1452 eh_freeze_mask = EDMA_EH_FREEZE;
1453
1454 if (edma_err_cause & EDMA_ERR_SELF_DIS) {
1455 struct mv_port_priv *pp = ap->private_data;
1456 pp->pp_flags &= ~MV_PP_FLAG_EDMA_EN;
Tejun Heob64bbc32007-07-16 14:29:39 +09001457 ata_ehi_push_desc(ehi, "EDMA self-disable");
Jeff Garzikbdd4ddd2007-07-12 14:34:26 -04001458 }
1459
1460 if (edma_err_cause & EDMA_ERR_SERR) {
Tejun Heo936fd732007-08-06 18:36:23 +09001461 sata_scr_read(&ap->link, SCR_ERROR, &serr);
1462 sata_scr_write_flush(&ap->link, SCR_ERROR, serr);
Jeff Garzikbdd4ddd2007-07-12 14:34:26 -04001463 err_mask = AC_ERR_ATA_BUS;
1464 action |= ATA_EH_HARDRESET;
1465 }
1466 }
Brett Russ20f733e2005-09-01 18:26:17 -04001467
1468 /* Clear EDMA now that SERR cleanup done */
Mark Lord3606a382008-01-26 18:28:23 -05001469 writelfl(~edma_err_cause, port_mmio + EDMA_ERR_IRQ_CAUSE_OFS);
Brett Russ20f733e2005-09-01 18:26:17 -04001470
Jeff Garzikbdd4ddd2007-07-12 14:34:26 -04001471 if (!err_mask) {
1472 err_mask = AC_ERR_OTHER;
1473 action |= ATA_EH_HARDRESET;
1474 }
1475
1476 ehi->serror |= serr;
1477 ehi->action |= action;
1478
1479 if (qc)
1480 qc->err_mask |= err_mask;
1481 else
1482 ehi->err_mask |= err_mask;
1483
1484 if (edma_err_cause & eh_freeze_mask)
1485 ata_port_freeze(ap);
1486 else
1487 ata_port_abort(ap);
1488}
1489
1490static void mv_intr_pio(struct ata_port *ap)
1491{
1492 struct ata_queued_cmd *qc;
1493 u8 ata_status;
1494
1495 /* ignore spurious intr if drive still BUSY */
1496 ata_status = readb(ap->ioaddr.status_addr);
1497 if (unlikely(ata_status & ATA_BUSY))
1498 return;
1499
1500 /* get active ATA command */
Tejun Heo9af5c9c2007-08-06 18:36:22 +09001501 qc = ata_qc_from_tag(ap, ap->link.active_tag);
Jeff Garzikbdd4ddd2007-07-12 14:34:26 -04001502 if (unlikely(!qc)) /* no active tag */
1503 return;
1504 if (qc->tf.flags & ATA_TFLAG_POLLING) /* polling; we don't own qc */
1505 return;
1506
1507 /* and finally, complete the ATA command */
1508 qc->err_mask |= ac_err_mask(ata_status);
1509 ata_qc_complete(qc);
1510}
1511
1512static void mv_intr_edma(struct ata_port *ap)
1513{
1514 void __iomem *port_mmio = mv_ap_base(ap);
1515 struct mv_host_priv *hpriv = ap->host->private_data;
1516 struct mv_port_priv *pp = ap->private_data;
1517 struct ata_queued_cmd *qc;
1518 u32 out_index, in_index;
1519 bool work_done = false;
1520
1521 /* get h/w response queue pointer */
1522 in_index = (readl(port_mmio + EDMA_RSP_Q_IN_PTR_OFS)
1523 >> EDMA_RSP_Q_PTR_SHIFT) & MV_MAX_Q_DEPTH_MASK;
1524
1525 while (1) {
1526 u16 status;
Jeff Garzik6c1153e2007-07-13 15:20:15 -04001527 unsigned int tag;
Jeff Garzikbdd4ddd2007-07-12 14:34:26 -04001528
1529 /* get s/w response queue last-read pointer, and compare */
1530 out_index = pp->resp_idx & MV_MAX_Q_DEPTH_MASK;
1531 if (in_index == out_index)
1532 break;
1533
Jeff Garzikbdd4ddd2007-07-12 14:34:26 -04001534 /* 50xx: get active ATA command */
Jeff Garzik0ea9e172007-07-13 17:06:45 -04001535 if (IS_GEN_I(hpriv))
Tejun Heo9af5c9c2007-08-06 18:36:22 +09001536 tag = ap->link.active_tag;
Jeff Garzikbdd4ddd2007-07-12 14:34:26 -04001537
Jeff Garzik6c1153e2007-07-13 15:20:15 -04001538 /* Gen II/IIE: get active ATA command via tag, to enable
1539 * support for queueing. this works transparently for
1540 * queued and non-queued modes.
Jeff Garzikbdd4ddd2007-07-12 14:34:26 -04001541 */
Jeff Garzik6c1153e2007-07-13 15:20:15 -04001542 else if (IS_GEN_II(hpriv))
1543 tag = (le16_to_cpu(pp->crpb[out_index].id)
1544 >> CRPB_IOID_SHIFT_6) & 0x3f;
Jeff Garzikbdd4ddd2007-07-12 14:34:26 -04001545
Jeff Garzik6c1153e2007-07-13 15:20:15 -04001546 else /* IS_GEN_IIE */
1547 tag = (le16_to_cpu(pp->crpb[out_index].id)
1548 >> CRPB_IOID_SHIFT_7) & 0x3f;
Jeff Garzikbdd4ddd2007-07-12 14:34:26 -04001549
Jeff Garzik6c1153e2007-07-13 15:20:15 -04001550 qc = ata_qc_from_tag(ap, tag);
Jeff Garzikbdd4ddd2007-07-12 14:34:26 -04001551
1552 /* lower 8 bits of status are EDMA_ERR_IRQ_CAUSE_OFS
1553 * bits (WARNING: might not necessarily be associated
1554 * with this command), which -should- be clear
1555 * if all is well
1556 */
1557 status = le16_to_cpu(pp->crpb[out_index].flags);
1558 if (unlikely(status & 0xff)) {
1559 mv_err_intr(ap, qc);
1560 return;
1561 }
1562
1563 /* and finally, complete the ATA command */
1564 if (qc) {
1565 qc->err_mask |=
1566 ac_err_mask(status >> CRPB_FLAG_STATUS_SHIFT);
1567 ata_qc_complete(qc);
1568 }
1569
Jeff Garzik0ea9e172007-07-13 17:06:45 -04001570 /* advance software response queue pointer, to
Jeff Garzikbdd4ddd2007-07-12 14:34:26 -04001571 * indicate (after the loop completes) to hardware
1572 * that we have consumed a response queue entry.
1573 */
1574 work_done = true;
1575 pp->resp_idx++;
1576 }
1577
1578 if (work_done)
1579 writelfl((pp->crpb_dma & EDMA_RSP_Q_BASE_LO_MASK) |
1580 (out_index << EDMA_RSP_Q_PTR_SHIFT),
1581 port_mmio + EDMA_RSP_Q_OUT_PTR_OFS);
Brett Russ20f733e2005-09-01 18:26:17 -04001582}
1583
Brett Russ05b308e2005-10-05 17:08:53 -04001584/**
1585 * mv_host_intr - Handle all interrupts on the given host controller
Jeff Garzikcca39742006-08-24 03:19:22 -04001586 * @host: host specific structure
Brett Russ05b308e2005-10-05 17:08:53 -04001587 * @relevant: port error bits relevant to this host controller
1588 * @hc: which host controller we're to look at
1589 *
1590 * Read then write clear the HC interrupt status then walk each
1591 * port connected to the HC and see if it needs servicing. Port
1592 * success ints are reported in the HC interrupt status reg, the
1593 * port error ints are reported in the higher level main
1594 * interrupt status register and thus are passed in via the
1595 * 'relevant' argument.
1596 *
1597 * LOCKING:
1598 * Inherited from caller.
1599 */
Jeff Garzikcca39742006-08-24 03:19:22 -04001600static void mv_host_intr(struct ata_host *host, u32 relevant, unsigned int hc)
Brett Russ20f733e2005-09-01 18:26:17 -04001601{
Tejun Heo0d5ff562007-02-01 15:06:36 +09001602 void __iomem *mmio = host->iomap[MV_PRIMARY_BAR];
Brett Russ20f733e2005-09-01 18:26:17 -04001603 void __iomem *hc_mmio = mv_hc_base(mmio, hc);
Brett Russ20f733e2005-09-01 18:26:17 -04001604 u32 hc_irq_cause;
Jeff Garzikc5d3e452007-07-11 18:30:50 -04001605 int port, port0;
Brett Russ20f733e2005-09-01 18:26:17 -04001606
Jeff Garzik35177262007-02-24 21:26:42 -05001607 if (hc == 0)
Brett Russ20f733e2005-09-01 18:26:17 -04001608 port0 = 0;
Jeff Garzik35177262007-02-24 21:26:42 -05001609 else
Brett Russ20f733e2005-09-01 18:26:17 -04001610 port0 = MV_PORTS_PER_HC;
Brett Russ20f733e2005-09-01 18:26:17 -04001611
1612 /* we'll need the HC success int register in most cases */
1613 hc_irq_cause = readl(hc_mmio + HC_IRQ_CAUSE_OFS);
Jeff Garzikbdd4ddd2007-07-12 14:34:26 -04001614 if (!hc_irq_cause)
1615 return;
1616
1617 writelfl(~hc_irq_cause, hc_mmio + HC_IRQ_CAUSE_OFS);
Brett Russ20f733e2005-09-01 18:26:17 -04001618
1619 VPRINTK("ENTER, hc%u relevant=0x%08x HC IRQ cause=0x%08x\n",
Jeff Garzik2dcb4072007-10-19 06:42:56 -04001620 hc, relevant, hc_irq_cause);
Brett Russ20f733e2005-09-01 18:26:17 -04001621
1622 for (port = port0; port < port0 + MV_PORTS_PER_HC; port++) {
Jeff Garzikcca39742006-08-24 03:19:22 -04001623 struct ata_port *ap = host->ports[port];
Mark Lord63af2a52006-03-29 09:50:31 -05001624 struct mv_port_priv *pp = ap->private_data;
Jeff Garzikbdd4ddd2007-07-12 14:34:26 -04001625 int have_err_bits, hard_port, shift;
Jeff Garzik55d8ca42006-03-29 19:43:31 -05001626
Jeff Garzikbdd4ddd2007-07-12 14:34:26 -04001627 if ((!ap) || (ap->flags & ATA_FLAG_DISABLED))
Jeff Garzika2c91a82005-11-17 05:44:44 -05001628 continue;
1629
Brett Russ31961942005-09-30 01:36:00 -04001630 shift = port << 1; /* (port * 2) */
Brett Russ20f733e2005-09-01 18:26:17 -04001631 if (port >= MV_PORTS_PER_HC) {
1632 shift++; /* skip bit 8 in the HC Main IRQ reg */
1633 }
Jeff Garzikbdd4ddd2007-07-12 14:34:26 -04001634 have_err_bits = ((PORT0_ERR << shift) & relevant);
1635
1636 if (unlikely(have_err_bits)) {
1637 struct ata_queued_cmd *qc;
1638
Tejun Heo9af5c9c2007-08-06 18:36:22 +09001639 qc = ata_qc_from_tag(ap, ap->link.active_tag);
Jeff Garzikbdd4ddd2007-07-12 14:34:26 -04001640 if (qc && (qc->tf.flags & ATA_TFLAG_POLLING))
1641 continue;
1642
1643 mv_err_intr(ap, qc);
1644 continue;
Brett Russ20f733e2005-09-01 18:26:17 -04001645 }
Jeff Garzik8b260242005-11-12 12:32:50 -05001646
Jeff Garzikbdd4ddd2007-07-12 14:34:26 -04001647 hard_port = mv_hardport_from_port(port); /* range 0..3 */
1648
1649 if (pp->pp_flags & MV_PP_FLAG_EDMA_EN) {
1650 if ((CRPB_DMA_DONE << hard_port) & hc_irq_cause)
1651 mv_intr_edma(ap);
1652 } else {
1653 if ((DEV_IRQ << hard_port) & hc_irq_cause)
1654 mv_intr_pio(ap);
Brett Russ20f733e2005-09-01 18:26:17 -04001655 }
1656 }
1657 VPRINTK("EXIT\n");
1658}
1659
Jeff Garzikbdd4ddd2007-07-12 14:34:26 -04001660static void mv_pci_error(struct ata_host *host, void __iomem *mmio)
1661{
Mark Lord02a121d2007-12-01 13:07:22 -05001662 struct mv_host_priv *hpriv = host->private_data;
Jeff Garzikbdd4ddd2007-07-12 14:34:26 -04001663 struct ata_port *ap;
1664 struct ata_queued_cmd *qc;
1665 struct ata_eh_info *ehi;
1666 unsigned int i, err_mask, printed = 0;
1667 u32 err_cause;
1668
Mark Lord02a121d2007-12-01 13:07:22 -05001669 err_cause = readl(mmio + hpriv->irq_cause_ofs);
Jeff Garzikbdd4ddd2007-07-12 14:34:26 -04001670
1671 dev_printk(KERN_ERR, host->dev, "PCI ERROR; PCI IRQ cause=0x%08x\n",
1672 err_cause);
1673
1674 DPRINTK("All regs @ PCI error\n");
1675 mv_dump_all_regs(mmio, -1, to_pci_dev(host->dev));
1676
Mark Lord02a121d2007-12-01 13:07:22 -05001677 writelfl(0, mmio + hpriv->irq_cause_ofs);
Jeff Garzikbdd4ddd2007-07-12 14:34:26 -04001678
1679 for (i = 0; i < host->n_ports; i++) {
1680 ap = host->ports[i];
Tejun Heo936fd732007-08-06 18:36:23 +09001681 if (!ata_link_offline(&ap->link)) {
Tejun Heo9af5c9c2007-08-06 18:36:22 +09001682 ehi = &ap->link.eh_info;
Jeff Garzikbdd4ddd2007-07-12 14:34:26 -04001683 ata_ehi_clear_desc(ehi);
1684 if (!printed++)
1685 ata_ehi_push_desc(ehi,
1686 "PCI err cause 0x%08x", err_cause);
1687 err_mask = AC_ERR_HOST_BUS;
1688 ehi->action = ATA_EH_HARDRESET;
Tejun Heo9af5c9c2007-08-06 18:36:22 +09001689 qc = ata_qc_from_tag(ap, ap->link.active_tag);
Jeff Garzikbdd4ddd2007-07-12 14:34:26 -04001690 if (qc)
1691 qc->err_mask |= err_mask;
1692 else
1693 ehi->err_mask |= err_mask;
1694
1695 ata_port_freeze(ap);
1696 }
1697 }
1698}
1699
Brett Russ05b308e2005-10-05 17:08:53 -04001700/**
Jeff Garzikc5d3e452007-07-11 18:30:50 -04001701 * mv_interrupt - Main interrupt event handler
Brett Russ05b308e2005-10-05 17:08:53 -04001702 * @irq: unused
1703 * @dev_instance: private data; in this case the host structure
Brett Russ05b308e2005-10-05 17:08:53 -04001704 *
1705 * Read the read only register to determine if any host
1706 * controllers have pending interrupts. If so, call lower level
1707 * routine to handle. Also check for PCI errors which are only
1708 * reported here.
1709 *
Jeff Garzik8b260242005-11-12 12:32:50 -05001710 * LOCKING:
Jeff Garzikcca39742006-08-24 03:19:22 -04001711 * This routine holds the host lock while processing pending
Brett Russ05b308e2005-10-05 17:08:53 -04001712 * interrupts.
1713 */
David Howells7d12e782006-10-05 14:55:46 +01001714static irqreturn_t mv_interrupt(int irq, void *dev_instance)
Brett Russ20f733e2005-09-01 18:26:17 -04001715{
Jeff Garzikcca39742006-08-24 03:19:22 -04001716 struct ata_host *host = dev_instance;
Brett Russ20f733e2005-09-01 18:26:17 -04001717 unsigned int hc, handled = 0, n_hcs;
Tejun Heo0d5ff562007-02-01 15:06:36 +09001718 void __iomem *mmio = host->iomap[MV_PRIMARY_BAR];
Brett Russ20f733e2005-09-01 18:26:17 -04001719 u32 irq_stat;
1720
Brett Russ20f733e2005-09-01 18:26:17 -04001721 irq_stat = readl(mmio + HC_MAIN_IRQ_CAUSE_OFS);
Brett Russ20f733e2005-09-01 18:26:17 -04001722
1723 /* check the cases where we either have nothing pending or have read
1724 * a bogus register value which can indicate HW removal or PCI fault
1725 */
Jeff Garzik35177262007-02-24 21:26:42 -05001726 if (!irq_stat || (0xffffffffU == irq_stat))
Brett Russ20f733e2005-09-01 18:26:17 -04001727 return IRQ_NONE;
Brett Russ20f733e2005-09-01 18:26:17 -04001728
Jeff Garzikcca39742006-08-24 03:19:22 -04001729 n_hcs = mv_get_hc_count(host->ports[0]->flags);
1730 spin_lock(&host->lock);
Brett Russ20f733e2005-09-01 18:26:17 -04001731
Jeff Garzikbdd4ddd2007-07-12 14:34:26 -04001732 if (unlikely(irq_stat & PCI_ERR)) {
1733 mv_pci_error(host, mmio);
1734 handled = 1;
1735 goto out_unlock; /* skip all other HC irq handling */
1736 }
1737
Brett Russ20f733e2005-09-01 18:26:17 -04001738 for (hc = 0; hc < n_hcs; hc++) {
1739 u32 relevant = irq_stat & (HC0_IRQ_PEND << (hc * HC_SHIFT));
1740 if (relevant) {
Jeff Garzikcca39742006-08-24 03:19:22 -04001741 mv_host_intr(host, relevant, hc);
Jeff Garzikbdd4ddd2007-07-12 14:34:26 -04001742 handled = 1;
Brett Russ20f733e2005-09-01 18:26:17 -04001743 }
1744 }
Mark Lord615ab952006-05-19 16:24:56 -04001745
Jeff Garzikbdd4ddd2007-07-12 14:34:26 -04001746out_unlock:
Jeff Garzikcca39742006-08-24 03:19:22 -04001747 spin_unlock(&host->lock);
Brett Russ20f733e2005-09-01 18:26:17 -04001748
1749 return IRQ_RETVAL(handled);
1750}
1751
Jeff Garzikc9d39132005-11-13 17:47:51 -05001752static void __iomem *mv5_phy_base(void __iomem *mmio, unsigned int port)
1753{
1754 void __iomem *hc_mmio = mv_hc_base_from_port(mmio, port);
1755 unsigned long ofs = (mv_hardport_from_port(port) + 1) * 0x100UL;
1756
1757 return hc_mmio + ofs;
1758}
1759
1760static unsigned int mv5_scr_offset(unsigned int sc_reg_in)
1761{
1762 unsigned int ofs;
1763
1764 switch (sc_reg_in) {
1765 case SCR_STATUS:
1766 case SCR_ERROR:
1767 case SCR_CONTROL:
1768 ofs = sc_reg_in * sizeof(u32);
1769 break;
1770 default:
1771 ofs = 0xffffffffU;
1772 break;
1773 }
1774 return ofs;
1775}
1776
Tejun Heoda3dbb12007-07-16 14:29:40 +09001777static int mv5_scr_read(struct ata_port *ap, unsigned int sc_reg_in, u32 *val)
Jeff Garzikc9d39132005-11-13 17:47:51 -05001778{
Tejun Heo0d5ff562007-02-01 15:06:36 +09001779 void __iomem *mmio = ap->host->iomap[MV_PRIMARY_BAR];
1780 void __iomem *addr = mv5_phy_base(mmio, ap->port_no);
Jeff Garzikc9d39132005-11-13 17:47:51 -05001781 unsigned int ofs = mv5_scr_offset(sc_reg_in);
1782
Tejun Heoda3dbb12007-07-16 14:29:40 +09001783 if (ofs != 0xffffffffU) {
1784 *val = readl(addr + ofs);
1785 return 0;
1786 } else
1787 return -EINVAL;
Jeff Garzikc9d39132005-11-13 17:47:51 -05001788}
1789
Tejun Heoda3dbb12007-07-16 14:29:40 +09001790static int mv5_scr_write(struct ata_port *ap, unsigned int sc_reg_in, u32 val)
Jeff Garzikc9d39132005-11-13 17:47:51 -05001791{
Tejun Heo0d5ff562007-02-01 15:06:36 +09001792 void __iomem *mmio = ap->host->iomap[MV_PRIMARY_BAR];
1793 void __iomem *addr = mv5_phy_base(mmio, ap->port_no);
Jeff Garzikc9d39132005-11-13 17:47:51 -05001794 unsigned int ofs = mv5_scr_offset(sc_reg_in);
1795
Tejun Heoda3dbb12007-07-16 14:29:40 +09001796 if (ofs != 0xffffffffU) {
Tejun Heo0d5ff562007-02-01 15:06:36 +09001797 writelfl(val, addr + ofs);
Tejun Heoda3dbb12007-07-16 14:29:40 +09001798 return 0;
1799 } else
1800 return -EINVAL;
Jeff Garzikc9d39132005-11-13 17:47:51 -05001801}
1802
Jeff Garzik522479f2005-11-12 22:14:02 -05001803static void mv5_reset_bus(struct pci_dev *pdev, void __iomem *mmio)
1804{
Jeff Garzik522479f2005-11-12 22:14:02 -05001805 int early_5080;
1806
Auke Kok44c10132007-06-08 15:46:36 -07001807 early_5080 = (pdev->device == 0x5080) && (pdev->revision == 0);
Jeff Garzik522479f2005-11-12 22:14:02 -05001808
1809 if (!early_5080) {
1810 u32 tmp = readl(mmio + MV_PCI_EXP_ROM_BAR_CTL);
1811 tmp |= (1 << 0);
1812 writel(tmp, mmio + MV_PCI_EXP_ROM_BAR_CTL);
1813 }
1814
1815 mv_reset_pci_bus(pdev, mmio);
1816}
1817
1818static void mv5_reset_flash(struct mv_host_priv *hpriv, void __iomem *mmio)
1819{
1820 writel(0x0fcfffff, mmio + MV_FLASH_CTL);
1821}
1822
Jeff Garzik47c2b672005-11-12 21:13:17 -05001823static void mv5_read_preamp(struct mv_host_priv *hpriv, int idx,
Jeff Garzikba3fe8f2005-11-12 19:08:48 -05001824 void __iomem *mmio)
1825{
Jeff Garzikc9d39132005-11-13 17:47:51 -05001826 void __iomem *phy_mmio = mv5_phy_base(mmio, idx);
1827 u32 tmp;
1828
1829 tmp = readl(phy_mmio + MV5_PHY_MODE);
1830
1831 hpriv->signal[idx].pre = tmp & 0x1800; /* bits 12:11 */
1832 hpriv->signal[idx].amps = tmp & 0xe0; /* bits 7:5 */
Jeff Garzikba3fe8f2005-11-12 19:08:48 -05001833}
1834
Jeff Garzik47c2b672005-11-12 21:13:17 -05001835static void mv5_enable_leds(struct mv_host_priv *hpriv, void __iomem *mmio)
Jeff Garzikba3fe8f2005-11-12 19:08:48 -05001836{
Jeff Garzik522479f2005-11-12 22:14:02 -05001837 u32 tmp;
1838
1839 writel(0, mmio + MV_GPIO_PORT_CTL);
1840
1841 /* FIXME: handle MV_HP_ERRATA_50XXB2 errata */
1842
1843 tmp = readl(mmio + MV_PCI_EXP_ROM_BAR_CTL);
1844 tmp |= ~(1 << 0);
1845 writel(tmp, mmio + MV_PCI_EXP_ROM_BAR_CTL);
Jeff Garzikba3fe8f2005-11-12 19:08:48 -05001846}
1847
Jeff Garzik2a47ce02005-11-12 23:05:14 -05001848static void mv5_phy_errata(struct mv_host_priv *hpriv, void __iomem *mmio,
1849 unsigned int port)
Jeff Garzikbca1c4e2005-11-12 12:48:15 -05001850{
Jeff Garzikc9d39132005-11-13 17:47:51 -05001851 void __iomem *phy_mmio = mv5_phy_base(mmio, port);
1852 const u32 mask = (1<<12) | (1<<11) | (1<<7) | (1<<6) | (1<<5);
1853 u32 tmp;
1854 int fix_apm_sq = (hpriv->hp_flags & MV_HP_ERRATA_50XXB0);
1855
1856 if (fix_apm_sq) {
1857 tmp = readl(phy_mmio + MV5_LT_MODE);
1858 tmp |= (1 << 19);
1859 writel(tmp, phy_mmio + MV5_LT_MODE);
1860
1861 tmp = readl(phy_mmio + MV5_PHY_CTL);
1862 tmp &= ~0x3;
1863 tmp |= 0x1;
1864 writel(tmp, phy_mmio + MV5_PHY_CTL);
1865 }
1866
1867 tmp = readl(phy_mmio + MV5_PHY_MODE);
1868 tmp &= ~mask;
1869 tmp |= hpriv->signal[port].pre;
1870 tmp |= hpriv->signal[port].amps;
1871 writel(tmp, phy_mmio + MV5_PHY_MODE);
Jeff Garzikbca1c4e2005-11-12 12:48:15 -05001872}
1873
Jeff Garzikc9d39132005-11-13 17:47:51 -05001874
1875#undef ZERO
1876#define ZERO(reg) writel(0, port_mmio + (reg))
1877static void mv5_reset_hc_port(struct mv_host_priv *hpriv, void __iomem *mmio,
1878 unsigned int port)
Jeff Garzik47c2b672005-11-12 21:13:17 -05001879{
Jeff Garzikc9d39132005-11-13 17:47:51 -05001880 void __iomem *port_mmio = mv_port_base(mmio, port);
1881
1882 writelfl(EDMA_DS, port_mmio + EDMA_CMD_OFS);
1883
1884 mv_channel_reset(hpriv, mmio, port);
1885
1886 ZERO(0x028); /* command */
1887 writel(0x11f, port_mmio + EDMA_CFG_OFS);
1888 ZERO(0x004); /* timer */
1889 ZERO(0x008); /* irq err cause */
1890 ZERO(0x00c); /* irq err mask */
1891 ZERO(0x010); /* rq bah */
1892 ZERO(0x014); /* rq inp */
1893 ZERO(0x018); /* rq outp */
1894 ZERO(0x01c); /* respq bah */
1895 ZERO(0x024); /* respq outp */
1896 ZERO(0x020); /* respq inp */
1897 ZERO(0x02c); /* test control */
1898 writel(0xbc, port_mmio + EDMA_IORDY_TMOUT);
1899}
1900#undef ZERO
1901
1902#define ZERO(reg) writel(0, hc_mmio + (reg))
1903static void mv5_reset_one_hc(struct mv_host_priv *hpriv, void __iomem *mmio,
1904 unsigned int hc)
1905{
1906 void __iomem *hc_mmio = mv_hc_base(mmio, hc);
1907 u32 tmp;
1908
1909 ZERO(0x00c);
1910 ZERO(0x010);
1911 ZERO(0x014);
1912 ZERO(0x018);
1913
1914 tmp = readl(hc_mmio + 0x20);
1915 tmp &= 0x1c1c1c1c;
1916 tmp |= 0x03030303;
1917 writel(tmp, hc_mmio + 0x20);
1918}
1919#undef ZERO
1920
1921static int mv5_reset_hc(struct mv_host_priv *hpriv, void __iomem *mmio,
1922 unsigned int n_hc)
1923{
1924 unsigned int hc, port;
1925
1926 for (hc = 0; hc < n_hc; hc++) {
1927 for (port = 0; port < MV_PORTS_PER_HC; port++)
1928 mv5_reset_hc_port(hpriv, mmio,
1929 (hc * MV_PORTS_PER_HC) + port);
1930
1931 mv5_reset_one_hc(hpriv, mmio, hc);
1932 }
1933
1934 return 0;
Jeff Garzik47c2b672005-11-12 21:13:17 -05001935}
1936
Jeff Garzik101ffae2005-11-12 22:17:49 -05001937#undef ZERO
1938#define ZERO(reg) writel(0, mmio + (reg))
1939static void mv_reset_pci_bus(struct pci_dev *pdev, void __iomem *mmio)
1940{
Mark Lord02a121d2007-12-01 13:07:22 -05001941 struct ata_host *host = dev_get_drvdata(&pdev->dev);
1942 struct mv_host_priv *hpriv = host->private_data;
Jeff Garzik101ffae2005-11-12 22:17:49 -05001943 u32 tmp;
1944
1945 tmp = readl(mmio + MV_PCI_MODE);
1946 tmp &= 0xff00ffff;
1947 writel(tmp, mmio + MV_PCI_MODE);
1948
1949 ZERO(MV_PCI_DISC_TIMER);
1950 ZERO(MV_PCI_MSI_TRIGGER);
1951 writel(0x000100ff, mmio + MV_PCI_XBAR_TMOUT);
1952 ZERO(HC_MAIN_IRQ_MASK_OFS);
1953 ZERO(MV_PCI_SERR_MASK);
Mark Lord02a121d2007-12-01 13:07:22 -05001954 ZERO(hpriv->irq_cause_ofs);
1955 ZERO(hpriv->irq_mask_ofs);
Jeff Garzik101ffae2005-11-12 22:17:49 -05001956 ZERO(MV_PCI_ERR_LOW_ADDRESS);
1957 ZERO(MV_PCI_ERR_HIGH_ADDRESS);
1958 ZERO(MV_PCI_ERR_ATTRIBUTE);
1959 ZERO(MV_PCI_ERR_COMMAND);
1960}
1961#undef ZERO
1962
1963static void mv6_reset_flash(struct mv_host_priv *hpriv, void __iomem *mmio)
1964{
1965 u32 tmp;
1966
1967 mv5_reset_flash(hpriv, mmio);
1968
1969 tmp = readl(mmio + MV_GPIO_PORT_CTL);
1970 tmp &= 0x3;
1971 tmp |= (1 << 5) | (1 << 6);
1972 writel(tmp, mmio + MV_GPIO_PORT_CTL);
1973}
1974
1975/**
1976 * mv6_reset_hc - Perform the 6xxx global soft reset
1977 * @mmio: base address of the HBA
1978 *
1979 * This routine only applies to 6xxx parts.
1980 *
1981 * LOCKING:
1982 * Inherited from caller.
1983 */
Jeff Garzikc9d39132005-11-13 17:47:51 -05001984static int mv6_reset_hc(struct mv_host_priv *hpriv, void __iomem *mmio,
1985 unsigned int n_hc)
Jeff Garzik101ffae2005-11-12 22:17:49 -05001986{
1987 void __iomem *reg = mmio + PCI_MAIN_CMD_STS_OFS;
1988 int i, rc = 0;
1989 u32 t;
1990
1991 /* Following procedure defined in PCI "main command and status
1992 * register" table.
1993 */
1994 t = readl(reg);
1995 writel(t | STOP_PCI_MASTER, reg);
1996
1997 for (i = 0; i < 1000; i++) {
1998 udelay(1);
1999 t = readl(reg);
Jeff Garzik2dcb4072007-10-19 06:42:56 -04002000 if (PCI_MASTER_EMPTY & t)
Jeff Garzik101ffae2005-11-12 22:17:49 -05002001 break;
Jeff Garzik101ffae2005-11-12 22:17:49 -05002002 }
2003 if (!(PCI_MASTER_EMPTY & t)) {
2004 printk(KERN_ERR DRV_NAME ": PCI master won't flush\n");
2005 rc = 1;
2006 goto done;
2007 }
2008
2009 /* set reset */
2010 i = 5;
2011 do {
2012 writel(t | GLOB_SFT_RST, reg);
2013 t = readl(reg);
2014 udelay(1);
2015 } while (!(GLOB_SFT_RST & t) && (i-- > 0));
2016
2017 if (!(GLOB_SFT_RST & t)) {
2018 printk(KERN_ERR DRV_NAME ": can't set global reset\n");
2019 rc = 1;
2020 goto done;
2021 }
2022
2023 /* clear reset and *reenable the PCI master* (not mentioned in spec) */
2024 i = 5;
2025 do {
2026 writel(t & ~(GLOB_SFT_RST | STOP_PCI_MASTER), reg);
2027 t = readl(reg);
2028 udelay(1);
2029 } while ((GLOB_SFT_RST & t) && (i-- > 0));
2030
2031 if (GLOB_SFT_RST & t) {
2032 printk(KERN_ERR DRV_NAME ": can't clear global reset\n");
2033 rc = 1;
2034 }
2035done:
2036 return rc;
2037}
2038
Jeff Garzik47c2b672005-11-12 21:13:17 -05002039static void mv6_read_preamp(struct mv_host_priv *hpriv, int idx,
Jeff Garzikba3fe8f2005-11-12 19:08:48 -05002040 void __iomem *mmio)
2041{
2042 void __iomem *port_mmio;
2043 u32 tmp;
2044
Jeff Garzikba3fe8f2005-11-12 19:08:48 -05002045 tmp = readl(mmio + MV_RESET_CFG);
2046 if ((tmp & (1 << 0)) == 0) {
Jeff Garzik47c2b672005-11-12 21:13:17 -05002047 hpriv->signal[idx].amps = 0x7 << 8;
Jeff Garzikba3fe8f2005-11-12 19:08:48 -05002048 hpriv->signal[idx].pre = 0x1 << 5;
2049 return;
2050 }
2051
2052 port_mmio = mv_port_base(mmio, idx);
2053 tmp = readl(port_mmio + PHY_MODE2);
2054
2055 hpriv->signal[idx].amps = tmp & 0x700; /* bits 10:8 */
2056 hpriv->signal[idx].pre = tmp & 0xe0; /* bits 7:5 */
2057}
2058
Jeff Garzik47c2b672005-11-12 21:13:17 -05002059static void mv6_enable_leds(struct mv_host_priv *hpriv, void __iomem *mmio)
Jeff Garzikba3fe8f2005-11-12 19:08:48 -05002060{
Jeff Garzik47c2b672005-11-12 21:13:17 -05002061 writel(0x00000060, mmio + MV_GPIO_PORT_CTL);
Jeff Garzikba3fe8f2005-11-12 19:08:48 -05002062}
2063
Jeff Garzikc9d39132005-11-13 17:47:51 -05002064static void mv6_phy_errata(struct mv_host_priv *hpriv, void __iomem *mmio,
Jeff Garzik2a47ce02005-11-12 23:05:14 -05002065 unsigned int port)
Jeff Garzikbca1c4e2005-11-12 12:48:15 -05002066{
Jeff Garzikc9d39132005-11-13 17:47:51 -05002067 void __iomem *port_mmio = mv_port_base(mmio, port);
2068
Jeff Garzikbca1c4e2005-11-12 12:48:15 -05002069 u32 hp_flags = hpriv->hp_flags;
Jeff Garzik47c2b672005-11-12 21:13:17 -05002070 int fix_phy_mode2 =
2071 hp_flags & (MV_HP_ERRATA_60X1B2 | MV_HP_ERRATA_60X1C0);
Jeff Garzikbca1c4e2005-11-12 12:48:15 -05002072 int fix_phy_mode4 =
Jeff Garzik47c2b672005-11-12 21:13:17 -05002073 hp_flags & (MV_HP_ERRATA_60X1B2 | MV_HP_ERRATA_60X1C0);
2074 u32 m2, tmp;
2075
2076 if (fix_phy_mode2) {
2077 m2 = readl(port_mmio + PHY_MODE2);
2078 m2 &= ~(1 << 16);
2079 m2 |= (1 << 31);
2080 writel(m2, port_mmio + PHY_MODE2);
2081
2082 udelay(200);
2083
2084 m2 = readl(port_mmio + PHY_MODE2);
2085 m2 &= ~((1 << 16) | (1 << 31));
2086 writel(m2, port_mmio + PHY_MODE2);
2087
2088 udelay(200);
2089 }
2090
2091 /* who knows what this magic does */
2092 tmp = readl(port_mmio + PHY_MODE3);
2093 tmp &= ~0x7F800000;
2094 tmp |= 0x2A800000;
2095 writel(tmp, port_mmio + PHY_MODE3);
Jeff Garzikbca1c4e2005-11-12 12:48:15 -05002096
2097 if (fix_phy_mode4) {
Jeff Garzik47c2b672005-11-12 21:13:17 -05002098 u32 m4;
Jeff Garzikbca1c4e2005-11-12 12:48:15 -05002099
2100 m4 = readl(port_mmio + PHY_MODE4);
Jeff Garzik47c2b672005-11-12 21:13:17 -05002101
2102 if (hp_flags & MV_HP_ERRATA_60X1B2)
2103 tmp = readl(port_mmio + 0x310);
Jeff Garzikbca1c4e2005-11-12 12:48:15 -05002104
2105 m4 = (m4 & ~(1 << 1)) | (1 << 0);
2106
2107 writel(m4, port_mmio + PHY_MODE4);
Jeff Garzik47c2b672005-11-12 21:13:17 -05002108
2109 if (hp_flags & MV_HP_ERRATA_60X1B2)
2110 writel(tmp, port_mmio + 0x310);
Jeff Garzikbca1c4e2005-11-12 12:48:15 -05002111 }
2112
2113 /* Revert values of pre-emphasis and signal amps to the saved ones */
2114 m2 = readl(port_mmio + PHY_MODE2);
2115
2116 m2 &= ~MV_M2_PREAMP_MASK;
Jeff Garzik2a47ce02005-11-12 23:05:14 -05002117 m2 |= hpriv->signal[port].amps;
2118 m2 |= hpriv->signal[port].pre;
Jeff Garzik47c2b672005-11-12 21:13:17 -05002119 m2 &= ~(1 << 16);
Jeff Garzikbca1c4e2005-11-12 12:48:15 -05002120
Jeff Garzike4e7b892006-01-31 12:18:41 -05002121 /* according to mvSata 3.6.1, some IIE values are fixed */
2122 if (IS_GEN_IIE(hpriv)) {
2123 m2 &= ~0xC30FF01F;
2124 m2 |= 0x0000900F;
2125 }
2126
Jeff Garzikbca1c4e2005-11-12 12:48:15 -05002127 writel(m2, port_mmio + PHY_MODE2);
2128}
2129
Jeff Garzikc9d39132005-11-13 17:47:51 -05002130static void mv_channel_reset(struct mv_host_priv *hpriv, void __iomem *mmio,
2131 unsigned int port_no)
Brett Russ20f733e2005-09-01 18:26:17 -04002132{
Jeff Garzikc9d39132005-11-13 17:47:51 -05002133 void __iomem *port_mmio = mv_port_base(mmio, port_no);
Brett Russ20f733e2005-09-01 18:26:17 -04002134
Brett Russ31961942005-09-30 01:36:00 -04002135 writelfl(ATA_RST, port_mmio + EDMA_CMD_OFS);
Jeff Garzikbca1c4e2005-11-12 12:48:15 -05002136
Jeff Garzikee9ccdf2007-07-12 15:51:22 -04002137 if (IS_GEN_II(hpriv)) {
Jeff Garzikbca1c4e2005-11-12 12:48:15 -05002138 u32 ifctl = readl(port_mmio + SATA_INTERFACE_CTL);
Mark Lordeb46d682006-05-19 16:29:21 -04002139 ifctl |= (1 << 7); /* enable gen2i speed */
2140 ifctl = (ifctl & 0xfff) | 0x9b1000; /* from chip spec */
Jeff Garzikbca1c4e2005-11-12 12:48:15 -05002141 writelfl(ifctl, port_mmio + SATA_INTERFACE_CTL);
2142 }
2143
Brett Russ20f733e2005-09-01 18:26:17 -04002144 udelay(25); /* allow reset propagation */
2145
2146 /* Spec never mentions clearing the bit. Marvell's driver does
2147 * clear the bit, however.
2148 */
Brett Russ31961942005-09-30 01:36:00 -04002149 writelfl(0, port_mmio + EDMA_CMD_OFS);
Brett Russ20f733e2005-09-01 18:26:17 -04002150
Jeff Garzikc9d39132005-11-13 17:47:51 -05002151 hpriv->ops->phy_errata(hpriv, mmio, port_no);
2152
Jeff Garzikee9ccdf2007-07-12 15:51:22 -04002153 if (IS_GEN_I(hpriv))
Jeff Garzikc9d39132005-11-13 17:47:51 -05002154 mdelay(1);
2155}
2156
Jeff Garzikc9d39132005-11-13 17:47:51 -05002157/**
Jeff Garzikbdd4ddd2007-07-12 14:34:26 -04002158 * mv_phy_reset - Perform eDMA reset followed by COMRESET
Jeff Garzikc9d39132005-11-13 17:47:51 -05002159 * @ap: ATA channel to manipulate
2160 *
2161 * Part of this is taken from __sata_phy_reset and modified to
2162 * not sleep since this routine gets called from interrupt level.
2163 *
2164 * LOCKING:
2165 * Inherited from caller. This is coded to safe to call at
2166 * interrupt level, i.e. it does not sleep.
2167 */
Jeff Garzikbdd4ddd2007-07-12 14:34:26 -04002168static void mv_phy_reset(struct ata_port *ap, unsigned int *class,
2169 unsigned long deadline)
Jeff Garzikc9d39132005-11-13 17:47:51 -05002170{
2171 struct mv_port_priv *pp = ap->private_data;
Jeff Garzikcca39742006-08-24 03:19:22 -04002172 struct mv_host_priv *hpriv = ap->host->private_data;
Jeff Garzikc9d39132005-11-13 17:47:51 -05002173 void __iomem *port_mmio = mv_ap_base(ap);
Jeff Garzik22374672005-11-17 10:59:48 -05002174 int retry = 5;
2175 u32 sstatus;
Jeff Garzikc9d39132005-11-13 17:47:51 -05002176
2177 VPRINTK("ENTER, port %u, mmio 0x%p\n", ap->port_no, port_mmio);
Jeff Garzikbca1c4e2005-11-12 12:48:15 -05002178
Tejun Heoda3dbb12007-07-16 14:29:40 +09002179#ifdef DEBUG
2180 {
2181 u32 sstatus, serror, scontrol;
2182
2183 mv_scr_read(ap, SCR_STATUS, &sstatus);
2184 mv_scr_read(ap, SCR_ERROR, &serror);
2185 mv_scr_read(ap, SCR_CONTROL, &scontrol);
2186 DPRINTK("S-regs after ATA_RST: SStat 0x%08x SErr 0x%08x "
Saeed Bishara2d79ab82007-11-27 17:26:08 +02002187 "SCtrl 0x%08x\n", sstatus, serror, scontrol);
Tejun Heoda3dbb12007-07-16 14:29:40 +09002188 }
2189#endif
Brett Russ20f733e2005-09-01 18:26:17 -04002190
Jeff Garzik22374672005-11-17 10:59:48 -05002191 /* Issue COMRESET via SControl */
2192comreset_retry:
Tejun Heo936fd732007-08-06 18:36:23 +09002193 sata_scr_write_flush(&ap->link, SCR_CONTROL, 0x301);
Jeff Garzikbdd4ddd2007-07-12 14:34:26 -04002194 msleep(1);
Jeff Garzik22374672005-11-17 10:59:48 -05002195
Tejun Heo936fd732007-08-06 18:36:23 +09002196 sata_scr_write_flush(&ap->link, SCR_CONTROL, 0x300);
Jeff Garzikbdd4ddd2007-07-12 14:34:26 -04002197 msleep(20);
Jeff Garzik22374672005-11-17 10:59:48 -05002198
Brett Russ31961942005-09-30 01:36:00 -04002199 do {
Tejun Heo936fd732007-08-06 18:36:23 +09002200 sata_scr_read(&ap->link, SCR_STATUS, &sstatus);
Andres Salomon62f1d0e2006-09-11 08:51:05 -04002201 if (((sstatus & 0x3) == 3) || ((sstatus & 0x3) == 0))
Brett Russ31961942005-09-30 01:36:00 -04002202 break;
Jeff Garzik22374672005-11-17 10:59:48 -05002203
Jeff Garzikbdd4ddd2007-07-12 14:34:26 -04002204 msleep(1);
Jeff Garzikc5d3e452007-07-11 18:30:50 -04002205 } while (time_before(jiffies, deadline));
Brett Russ20f733e2005-09-01 18:26:17 -04002206
Jeff Garzik22374672005-11-17 10:59:48 -05002207 /* work around errata */
Jeff Garzikee9ccdf2007-07-12 15:51:22 -04002208 if (IS_GEN_II(hpriv) &&
Jeff Garzik22374672005-11-17 10:59:48 -05002209 (sstatus != 0x0) && (sstatus != 0x113) && (sstatus != 0x123) &&
2210 (retry-- > 0))
2211 goto comreset_retry;
Jeff Garzik095fec82005-11-12 09:50:49 -05002212
Tejun Heoda3dbb12007-07-16 14:29:40 +09002213#ifdef DEBUG
2214 {
2215 u32 sstatus, serror, scontrol;
2216
2217 mv_scr_read(ap, SCR_STATUS, &sstatus);
2218 mv_scr_read(ap, SCR_ERROR, &serror);
2219 mv_scr_read(ap, SCR_CONTROL, &scontrol);
2220 DPRINTK("S-regs after PHY wake: SStat 0x%08x SErr 0x%08x "
2221 "SCtrl 0x%08x\n", sstatus, serror, scontrol);
2222 }
2223#endif
Brett Russ31961942005-09-30 01:36:00 -04002224
Tejun Heo936fd732007-08-06 18:36:23 +09002225 if (ata_link_offline(&ap->link)) {
Jeff Garzikbdd4ddd2007-07-12 14:34:26 -04002226 *class = ATA_DEV_NONE;
Brett Russ20f733e2005-09-01 18:26:17 -04002227 return;
2228 }
2229
Jeff Garzik22374672005-11-17 10:59:48 -05002230 /* even after SStatus reflects that device is ready,
2231 * it seems to take a while for link to be fully
2232 * established (and thus Status no longer 0x80/0x7F),
2233 * so we poll a bit for that, here.
2234 */
2235 retry = 20;
2236 while (1) {
2237 u8 drv_stat = ata_check_status(ap);
2238 if ((drv_stat != 0x80) && (drv_stat != 0x7f))
2239 break;
Jeff Garzikbdd4ddd2007-07-12 14:34:26 -04002240 msleep(500);
Jeff Garzik22374672005-11-17 10:59:48 -05002241 if (retry-- <= 0)
2242 break;
Jeff Garzikbdd4ddd2007-07-12 14:34:26 -04002243 if (time_after(jiffies, deadline))
2244 break;
Jeff Garzik22374672005-11-17 10:59:48 -05002245 }
2246
Jeff Garzikbdd4ddd2007-07-12 14:34:26 -04002247 /* FIXME: if we passed the deadline, the following
2248 * code probably produces an invalid result
2249 */
Brett Russ20f733e2005-09-01 18:26:17 -04002250
Jeff Garzikbdd4ddd2007-07-12 14:34:26 -04002251 /* finally, read device signature from TF registers */
Tejun Heo3f198592007-09-02 23:23:57 +09002252 *class = ata_dev_try_classify(ap->link.device, 1, NULL);
Jeff Garzik095fec82005-11-12 09:50:49 -05002253
2254 writelfl(0, port_mmio + EDMA_ERR_IRQ_CAUSE_OFS);
2255
Jeff Garzikbdd4ddd2007-07-12 14:34:26 -04002256 WARN_ON(pp->pp_flags & MV_PP_FLAG_EDMA_EN);
Jeff Garzik095fec82005-11-12 09:50:49 -05002257
Jeff Garzikbca1c4e2005-11-12 12:48:15 -05002258 VPRINTK("EXIT\n");
Brett Russ20f733e2005-09-01 18:26:17 -04002259}
2260
Tejun Heocc0680a2007-08-06 18:36:23 +09002261static int mv_prereset(struct ata_link *link, unsigned long deadline)
Jeff Garzik22374672005-11-17 10:59:48 -05002262{
Tejun Heocc0680a2007-08-06 18:36:23 +09002263 struct ata_port *ap = link->ap;
Jeff Garzikbdd4ddd2007-07-12 14:34:26 -04002264 struct mv_port_priv *pp = ap->private_data;
Tejun Heocc0680a2007-08-06 18:36:23 +09002265 struct ata_eh_context *ehc = &link->eh_context;
Jeff Garzikbdd4ddd2007-07-12 14:34:26 -04002266 int rc;
Jeff Garzik0ea9e172007-07-13 17:06:45 -04002267
Jeff Garzikbdd4ddd2007-07-12 14:34:26 -04002268 rc = mv_stop_dma(ap);
2269 if (rc)
2270 ehc->i.action |= ATA_EH_HARDRESET;
2271
2272 if (!(pp->pp_flags & MV_PP_FLAG_HAD_A_RESET)) {
2273 pp->pp_flags |= MV_PP_FLAG_HAD_A_RESET;
2274 ehc->i.action |= ATA_EH_HARDRESET;
2275 }
2276
2277 /* if we're about to do hardreset, nothing more to do */
2278 if (ehc->i.action & ATA_EH_HARDRESET)
2279 return 0;
2280
Tejun Heocc0680a2007-08-06 18:36:23 +09002281 if (ata_link_online(link))
Jeff Garzikbdd4ddd2007-07-12 14:34:26 -04002282 rc = ata_wait_ready(ap, deadline);
2283 else
2284 rc = -ENODEV;
2285
2286 return rc;
Jeff Garzik22374672005-11-17 10:59:48 -05002287}
2288
Tejun Heocc0680a2007-08-06 18:36:23 +09002289static int mv_hardreset(struct ata_link *link, unsigned int *class,
Jeff Garzikbdd4ddd2007-07-12 14:34:26 -04002290 unsigned long deadline)
2291{
Tejun Heocc0680a2007-08-06 18:36:23 +09002292 struct ata_port *ap = link->ap;
Jeff Garzikbdd4ddd2007-07-12 14:34:26 -04002293 struct mv_host_priv *hpriv = ap->host->private_data;
2294 void __iomem *mmio = ap->host->iomap[MV_PRIMARY_BAR];
2295
2296 mv_stop_dma(ap);
2297
2298 mv_channel_reset(hpriv, mmio, ap->port_no);
2299
2300 mv_phy_reset(ap, class, deadline);
2301
2302 return 0;
2303}
2304
Tejun Heocc0680a2007-08-06 18:36:23 +09002305static void mv_postreset(struct ata_link *link, unsigned int *classes)
Jeff Garzikbdd4ddd2007-07-12 14:34:26 -04002306{
Tejun Heocc0680a2007-08-06 18:36:23 +09002307 struct ata_port *ap = link->ap;
Jeff Garzikbdd4ddd2007-07-12 14:34:26 -04002308 u32 serr;
2309
2310 /* print link status */
Tejun Heocc0680a2007-08-06 18:36:23 +09002311 sata_print_link_status(link);
Jeff Garzikbdd4ddd2007-07-12 14:34:26 -04002312
2313 /* clear SError */
Tejun Heocc0680a2007-08-06 18:36:23 +09002314 sata_scr_read(link, SCR_ERROR, &serr);
2315 sata_scr_write_flush(link, SCR_ERROR, serr);
Jeff Garzikbdd4ddd2007-07-12 14:34:26 -04002316
2317 /* bail out if no device is present */
2318 if (classes[0] == ATA_DEV_NONE && classes[1] == ATA_DEV_NONE) {
2319 DPRINTK("EXIT, no device\n");
2320 return;
2321 }
2322
2323 /* set up device control */
2324 iowrite8(ap->ctl, ap->ioaddr.ctl_addr);
2325}
2326
2327static void mv_error_handler(struct ata_port *ap)
2328{
2329 ata_do_eh(ap, mv_prereset, ata_std_softreset,
2330 mv_hardreset, mv_postreset);
2331}
2332
2333static void mv_post_int_cmd(struct ata_queued_cmd *qc)
2334{
2335 mv_stop_dma(qc->ap);
2336}
2337
2338static void mv_eh_freeze(struct ata_port *ap)
Brett Russ20f733e2005-09-01 18:26:17 -04002339{
Tejun Heo0d5ff562007-02-01 15:06:36 +09002340 void __iomem *mmio = ap->host->iomap[MV_PRIMARY_BAR];
Jeff Garzikbdd4ddd2007-07-12 14:34:26 -04002341 unsigned int hc = (ap->port_no > 3) ? 1 : 0;
2342 u32 tmp, mask;
2343 unsigned int shift;
Brett Russ31961942005-09-30 01:36:00 -04002344
Jeff Garzikbdd4ddd2007-07-12 14:34:26 -04002345 /* FIXME: handle coalescing completion events properly */
Brett Russ31961942005-09-30 01:36:00 -04002346
Jeff Garzikbdd4ddd2007-07-12 14:34:26 -04002347 shift = ap->port_no * 2;
2348 if (hc > 0)
2349 shift++;
Brett Russ31961942005-09-30 01:36:00 -04002350
Jeff Garzikbdd4ddd2007-07-12 14:34:26 -04002351 mask = 0x3 << shift;
Brett Russ31961942005-09-30 01:36:00 -04002352
Jeff Garzikbdd4ddd2007-07-12 14:34:26 -04002353 /* disable assertion of portN err, done events */
2354 tmp = readl(mmio + HC_MAIN_IRQ_MASK_OFS);
2355 writelfl(tmp & ~mask, mmio + HC_MAIN_IRQ_MASK_OFS);
2356}
2357
2358static void mv_eh_thaw(struct ata_port *ap)
2359{
2360 void __iomem *mmio = ap->host->iomap[MV_PRIMARY_BAR];
2361 unsigned int hc = (ap->port_no > 3) ? 1 : 0;
2362 void __iomem *hc_mmio = mv_hc_base(mmio, hc);
2363 void __iomem *port_mmio = mv_ap_base(ap);
2364 u32 tmp, mask, hc_irq_cause;
2365 unsigned int shift, hc_port_no = ap->port_no;
2366
2367 /* FIXME: handle coalescing completion events properly */
2368
2369 shift = ap->port_no * 2;
2370 if (hc > 0) {
2371 shift++;
2372 hc_port_no -= 4;
Mark Lord9b358e32006-05-19 16:21:03 -04002373 }
Jeff Garzikbdd4ddd2007-07-12 14:34:26 -04002374
2375 mask = 0x3 << shift;
2376
2377 /* clear EDMA errors on this port */
2378 writel(0, port_mmio + EDMA_ERR_IRQ_CAUSE_OFS);
2379
2380 /* clear pending irq events */
2381 hc_irq_cause = readl(hc_mmio + HC_IRQ_CAUSE_OFS);
2382 hc_irq_cause &= ~(1 << hc_port_no); /* clear CRPB-done */
2383 hc_irq_cause &= ~(1 << (hc_port_no + 8)); /* clear Device int */
2384 writel(hc_irq_cause, hc_mmio + HC_IRQ_CAUSE_OFS);
2385
2386 /* enable assertion of portN err, done events */
2387 tmp = readl(mmio + HC_MAIN_IRQ_MASK_OFS);
2388 writelfl(tmp | mask, mmio + HC_MAIN_IRQ_MASK_OFS);
Brett Russ31961942005-09-30 01:36:00 -04002389}
2390
Brett Russ05b308e2005-10-05 17:08:53 -04002391/**
2392 * mv_port_init - Perform some early initialization on a single port.
2393 * @port: libata data structure storing shadow register addresses
2394 * @port_mmio: base address of the port
2395 *
2396 * Initialize shadow register mmio addresses, clear outstanding
2397 * interrupts on the port, and unmask interrupts for the future
2398 * start of the port.
2399 *
2400 * LOCKING:
2401 * Inherited from caller.
2402 */
Brett Russ31961942005-09-30 01:36:00 -04002403static void mv_port_init(struct ata_ioports *port, void __iomem *port_mmio)
2404{
Tejun Heo0d5ff562007-02-01 15:06:36 +09002405 void __iomem *shd_base = port_mmio + SHD_BLK_OFS;
Brett Russ31961942005-09-30 01:36:00 -04002406 unsigned serr_ofs;
2407
Jeff Garzik8b260242005-11-12 12:32:50 -05002408 /* PIO related setup
Brett Russ31961942005-09-30 01:36:00 -04002409 */
2410 port->data_addr = shd_base + (sizeof(u32) * ATA_REG_DATA);
Jeff Garzik8b260242005-11-12 12:32:50 -05002411 port->error_addr =
Brett Russ31961942005-09-30 01:36:00 -04002412 port->feature_addr = shd_base + (sizeof(u32) * ATA_REG_ERR);
2413 port->nsect_addr = shd_base + (sizeof(u32) * ATA_REG_NSECT);
2414 port->lbal_addr = shd_base + (sizeof(u32) * ATA_REG_LBAL);
2415 port->lbam_addr = shd_base + (sizeof(u32) * ATA_REG_LBAM);
2416 port->lbah_addr = shd_base + (sizeof(u32) * ATA_REG_LBAH);
2417 port->device_addr = shd_base + (sizeof(u32) * ATA_REG_DEVICE);
Jeff Garzik8b260242005-11-12 12:32:50 -05002418 port->status_addr =
Brett Russ31961942005-09-30 01:36:00 -04002419 port->command_addr = shd_base + (sizeof(u32) * ATA_REG_STATUS);
2420 /* special case: control/altstatus doesn't have ATA_REG_ address */
2421 port->altstatus_addr = port->ctl_addr = shd_base + SHD_CTL_AST_OFS;
2422
2423 /* unused: */
Randy Dunlap8d9db2d2007-02-16 01:40:06 -08002424 port->cmd_addr = port->bmdma_addr = port->scr_addr = NULL;
Brett Russ20f733e2005-09-01 18:26:17 -04002425
Brett Russ31961942005-09-30 01:36:00 -04002426 /* Clear any currently outstanding port interrupt conditions */
2427 serr_ofs = mv_scr_offset(SCR_ERROR);
2428 writelfl(readl(port_mmio + serr_ofs), port_mmio + serr_ofs);
2429 writelfl(0, port_mmio + EDMA_ERR_IRQ_CAUSE_OFS);
2430
Brett Russ20f733e2005-09-01 18:26:17 -04002431 /* unmask all EDMA error interrupts */
Brett Russ31961942005-09-30 01:36:00 -04002432 writelfl(~0, port_mmio + EDMA_ERR_IRQ_MASK_OFS);
Brett Russ20f733e2005-09-01 18:26:17 -04002433
Jeff Garzik8b260242005-11-12 12:32:50 -05002434 VPRINTK("EDMA cfg=0x%08x EDMA IRQ err cause/mask=0x%08x/0x%08x\n",
Brett Russ31961942005-09-30 01:36:00 -04002435 readl(port_mmio + EDMA_CFG_OFS),
2436 readl(port_mmio + EDMA_ERR_IRQ_CAUSE_OFS),
2437 readl(port_mmio + EDMA_ERR_IRQ_MASK_OFS));
Brett Russ20f733e2005-09-01 18:26:17 -04002438}
2439
Tejun Heo4447d352007-04-17 23:44:08 +09002440static int mv_chip_id(struct ata_host *host, unsigned int board_idx)
Jeff Garzikbca1c4e2005-11-12 12:48:15 -05002441{
Tejun Heo4447d352007-04-17 23:44:08 +09002442 struct pci_dev *pdev = to_pci_dev(host->dev);
2443 struct mv_host_priv *hpriv = host->private_data;
Jeff Garzikbca1c4e2005-11-12 12:48:15 -05002444 u32 hp_flags = hpriv->hp_flags;
2445
Jeff Garzik5796d1c2007-10-26 00:03:37 -04002446 switch (board_idx) {
Jeff Garzik47c2b672005-11-12 21:13:17 -05002447 case chip_5080:
2448 hpriv->ops = &mv5xxx_ops;
Jeff Garzikee9ccdf2007-07-12 15:51:22 -04002449 hp_flags |= MV_HP_GEN_I;
Jeff Garzikbca1c4e2005-11-12 12:48:15 -05002450
Auke Kok44c10132007-06-08 15:46:36 -07002451 switch (pdev->revision) {
Jeff Garzik47c2b672005-11-12 21:13:17 -05002452 case 0x1:
2453 hp_flags |= MV_HP_ERRATA_50XXB0;
2454 break;
2455 case 0x3:
2456 hp_flags |= MV_HP_ERRATA_50XXB2;
2457 break;
2458 default:
2459 dev_printk(KERN_WARNING, &pdev->dev,
2460 "Applying 50XXB2 workarounds to unknown rev\n");
2461 hp_flags |= MV_HP_ERRATA_50XXB2;
2462 break;
2463 }
2464 break;
2465
2466 case chip_504x:
2467 case chip_508x:
2468 hpriv->ops = &mv5xxx_ops;
Jeff Garzikee9ccdf2007-07-12 15:51:22 -04002469 hp_flags |= MV_HP_GEN_I;
Jeff Garzik47c2b672005-11-12 21:13:17 -05002470
Auke Kok44c10132007-06-08 15:46:36 -07002471 switch (pdev->revision) {
Jeff Garzik47c2b672005-11-12 21:13:17 -05002472 case 0x0:
2473 hp_flags |= MV_HP_ERRATA_50XXB0;
2474 break;
2475 case 0x3:
2476 hp_flags |= MV_HP_ERRATA_50XXB2;
2477 break;
2478 default:
2479 dev_printk(KERN_WARNING, &pdev->dev,
2480 "Applying B2 workarounds to unknown rev\n");
2481 hp_flags |= MV_HP_ERRATA_50XXB2;
2482 break;
Jeff Garzikbca1c4e2005-11-12 12:48:15 -05002483 }
2484 break;
2485
2486 case chip_604x:
2487 case chip_608x:
Jeff Garzik47c2b672005-11-12 21:13:17 -05002488 hpriv->ops = &mv6xxx_ops;
Jeff Garzikee9ccdf2007-07-12 15:51:22 -04002489 hp_flags |= MV_HP_GEN_II;
Jeff Garzik47c2b672005-11-12 21:13:17 -05002490
Auke Kok44c10132007-06-08 15:46:36 -07002491 switch (pdev->revision) {
Jeff Garzik47c2b672005-11-12 21:13:17 -05002492 case 0x7:
2493 hp_flags |= MV_HP_ERRATA_60X1B2;
2494 break;
2495 case 0x9:
2496 hp_flags |= MV_HP_ERRATA_60X1C0;
Jeff Garzikbca1c4e2005-11-12 12:48:15 -05002497 break;
2498 default:
2499 dev_printk(KERN_WARNING, &pdev->dev,
Jeff Garzik47c2b672005-11-12 21:13:17 -05002500 "Applying B2 workarounds to unknown rev\n");
2501 hp_flags |= MV_HP_ERRATA_60X1B2;
Jeff Garzikbca1c4e2005-11-12 12:48:15 -05002502 break;
2503 }
2504 break;
2505
Jeff Garzike4e7b892006-01-31 12:18:41 -05002506 case chip_7042:
Mark Lord02a121d2007-12-01 13:07:22 -05002507 hp_flags |= MV_HP_PCIE;
Mark Lord306b30f2007-12-04 14:07:52 -05002508 if (pdev->vendor == PCI_VENDOR_ID_TTI &&
2509 (pdev->device == 0x2300 || pdev->device == 0x2310))
2510 {
Mark Lord4e520032007-12-11 12:58:05 -05002511 /*
2512 * Highpoint RocketRAID PCIe 23xx series cards:
2513 *
2514 * Unconfigured drives are treated as "Legacy"
2515 * by the BIOS, and it overwrites sector 8 with
2516 * a "Lgcy" metadata block prior to Linux boot.
2517 *
2518 * Configured drives (RAID or JBOD) leave sector 8
2519 * alone, but instead overwrite a high numbered
2520 * sector for the RAID metadata. This sector can
2521 * be determined exactly, by truncating the physical
2522 * drive capacity to a nice even GB value.
2523 *
2524 * RAID metadata is at: (dev->n_sectors & ~0xfffff)
2525 *
2526 * Warn the user, lest they think we're just buggy.
2527 */
2528 printk(KERN_WARNING DRV_NAME ": Highpoint RocketRAID"
2529 " BIOS CORRUPTS DATA on all attached drives,"
2530 " regardless of if/how they are configured."
2531 " BEWARE!\n");
2532 printk(KERN_WARNING DRV_NAME ": For data safety, do not"
2533 " use sectors 8-9 on \"Legacy\" drives,"
2534 " and avoid the final two gigabytes on"
2535 " all RocketRAID BIOS initialized drives.\n");
Mark Lord306b30f2007-12-04 14:07:52 -05002536 }
Jeff Garzike4e7b892006-01-31 12:18:41 -05002537 case chip_6042:
2538 hpriv->ops = &mv6xxx_ops;
Jeff Garzike4e7b892006-01-31 12:18:41 -05002539 hp_flags |= MV_HP_GEN_IIE;
2540
Auke Kok44c10132007-06-08 15:46:36 -07002541 switch (pdev->revision) {
Jeff Garzike4e7b892006-01-31 12:18:41 -05002542 case 0x0:
2543 hp_flags |= MV_HP_ERRATA_XX42A0;
2544 break;
2545 case 0x1:
2546 hp_flags |= MV_HP_ERRATA_60X1C0;
2547 break;
2548 default:
2549 dev_printk(KERN_WARNING, &pdev->dev,
2550 "Applying 60X1C0 workarounds to unknown rev\n");
2551 hp_flags |= MV_HP_ERRATA_60X1C0;
2552 break;
2553 }
2554 break;
2555
Jeff Garzikbca1c4e2005-11-12 12:48:15 -05002556 default:
Jeff Garzik5796d1c2007-10-26 00:03:37 -04002557 dev_printk(KERN_ERR, &pdev->dev,
2558 "BUG: invalid board index %u\n", board_idx);
Jeff Garzikbca1c4e2005-11-12 12:48:15 -05002559 return 1;
2560 }
2561
2562 hpriv->hp_flags = hp_flags;
Mark Lord02a121d2007-12-01 13:07:22 -05002563 if (hp_flags & MV_HP_PCIE) {
2564 hpriv->irq_cause_ofs = PCIE_IRQ_CAUSE_OFS;
2565 hpriv->irq_mask_ofs = PCIE_IRQ_MASK_OFS;
2566 hpriv->unmask_all_irqs = PCIE_UNMASK_ALL_IRQS;
2567 } else {
2568 hpriv->irq_cause_ofs = PCI_IRQ_CAUSE_OFS;
2569 hpriv->irq_mask_ofs = PCI_IRQ_MASK_OFS;
2570 hpriv->unmask_all_irqs = PCI_UNMASK_ALL_IRQS;
2571 }
Jeff Garzikbca1c4e2005-11-12 12:48:15 -05002572
2573 return 0;
2574}
2575
Brett Russ05b308e2005-10-05 17:08:53 -04002576/**
Jeff Garzik47c2b672005-11-12 21:13:17 -05002577 * mv_init_host - Perform some early initialization of the host.
Tejun Heo4447d352007-04-17 23:44:08 +09002578 * @host: ATA host to initialize
2579 * @board_idx: controller index
Brett Russ05b308e2005-10-05 17:08:53 -04002580 *
2581 * If possible, do an early global reset of the host. Then do
2582 * our port init and clear/unmask all/relevant host interrupts.
2583 *
2584 * LOCKING:
2585 * Inherited from caller.
2586 */
Tejun Heo4447d352007-04-17 23:44:08 +09002587static int mv_init_host(struct ata_host *host, unsigned int board_idx)
Brett Russ20f733e2005-09-01 18:26:17 -04002588{
2589 int rc = 0, n_hc, port, hc;
Tejun Heo4447d352007-04-17 23:44:08 +09002590 struct pci_dev *pdev = to_pci_dev(host->dev);
2591 void __iomem *mmio = host->iomap[MV_PRIMARY_BAR];
2592 struct mv_host_priv *hpriv = host->private_data;
Jeff Garzikbca1c4e2005-11-12 12:48:15 -05002593
Jeff Garzik47c2b672005-11-12 21:13:17 -05002594 /* global interrupt mask */
2595 writel(0, mmio + HC_MAIN_IRQ_MASK_OFS);
2596
Tejun Heo4447d352007-04-17 23:44:08 +09002597 rc = mv_chip_id(host, board_idx);
Jeff Garzikbca1c4e2005-11-12 12:48:15 -05002598 if (rc)
2599 goto done;
2600
Tejun Heo4447d352007-04-17 23:44:08 +09002601 n_hc = mv_get_hc_count(host->ports[0]->flags);
Jeff Garzikbca1c4e2005-11-12 12:48:15 -05002602
Tejun Heo4447d352007-04-17 23:44:08 +09002603 for (port = 0; port < host->n_ports; port++)
Jeff Garzik47c2b672005-11-12 21:13:17 -05002604 hpriv->ops->read_preamp(hpriv, port, mmio);
Brett Russ20f733e2005-09-01 18:26:17 -04002605
Jeff Garzikc9d39132005-11-13 17:47:51 -05002606 rc = hpriv->ops->reset_hc(hpriv, mmio, n_hc);
Jeff Garzik47c2b672005-11-12 21:13:17 -05002607 if (rc)
Brett Russ20f733e2005-09-01 18:26:17 -04002608 goto done;
Brett Russ20f733e2005-09-01 18:26:17 -04002609
Jeff Garzik522479f2005-11-12 22:14:02 -05002610 hpriv->ops->reset_flash(hpriv, mmio);
2611 hpriv->ops->reset_bus(pdev, mmio);
Jeff Garzik47c2b672005-11-12 21:13:17 -05002612 hpriv->ops->enable_leds(hpriv, mmio);
Brett Russ20f733e2005-09-01 18:26:17 -04002613
Tejun Heo4447d352007-04-17 23:44:08 +09002614 for (port = 0; port < host->n_ports; port++) {
Jeff Garzikee9ccdf2007-07-12 15:51:22 -04002615 if (IS_GEN_II(hpriv)) {
Jeff Garzikc9d39132005-11-13 17:47:51 -05002616 void __iomem *port_mmio = mv_port_base(mmio, port);
2617
Jeff Garzik2a47ce02005-11-12 23:05:14 -05002618 u32 ifctl = readl(port_mmio + SATA_INTERFACE_CTL);
Mark Lordeb46d682006-05-19 16:29:21 -04002619 ifctl |= (1 << 7); /* enable gen2i speed */
2620 ifctl = (ifctl & 0xfff) | 0x9b1000; /* from chip spec */
Jeff Garzik2a47ce02005-11-12 23:05:14 -05002621 writelfl(ifctl, port_mmio + SATA_INTERFACE_CTL);
2622 }
2623
Jeff Garzikc9d39132005-11-13 17:47:51 -05002624 hpriv->ops->phy_errata(hpriv, mmio, port);
Jeff Garzik2a47ce02005-11-12 23:05:14 -05002625 }
2626
Tejun Heo4447d352007-04-17 23:44:08 +09002627 for (port = 0; port < host->n_ports; port++) {
Tejun Heocbcdd872007-08-18 13:14:55 +09002628 struct ata_port *ap = host->ports[port];
Jeff Garzik2a47ce02005-11-12 23:05:14 -05002629 void __iomem *port_mmio = mv_port_base(mmio, port);
Tejun Heocbcdd872007-08-18 13:14:55 +09002630 unsigned int offset = port_mmio - mmio;
2631
2632 mv_port_init(&ap->ioaddr, port_mmio);
2633
2634 ata_port_pbar_desc(ap, MV_PRIMARY_BAR, -1, "mmio");
2635 ata_port_pbar_desc(ap, MV_PRIMARY_BAR, offset, "port");
Brett Russ20f733e2005-09-01 18:26:17 -04002636 }
2637
2638 for (hc = 0; hc < n_hc; hc++) {
Brett Russ31961942005-09-30 01:36:00 -04002639 void __iomem *hc_mmio = mv_hc_base(mmio, hc);
2640
2641 VPRINTK("HC%i: HC config=0x%08x HC IRQ cause "
2642 "(before clear)=0x%08x\n", hc,
2643 readl(hc_mmio + HC_CFG_OFS),
2644 readl(hc_mmio + HC_IRQ_CAUSE_OFS));
2645
2646 /* Clear any currently outstanding hc interrupt conditions */
2647 writelfl(0, hc_mmio + HC_IRQ_CAUSE_OFS);
Brett Russ20f733e2005-09-01 18:26:17 -04002648 }
2649
Brett Russ31961942005-09-30 01:36:00 -04002650 /* Clear any currently outstanding host interrupt conditions */
Mark Lord02a121d2007-12-01 13:07:22 -05002651 writelfl(0, mmio + hpriv->irq_cause_ofs);
Brett Russ31961942005-09-30 01:36:00 -04002652
2653 /* and unmask interrupt generation for host regs */
Mark Lord02a121d2007-12-01 13:07:22 -05002654 writelfl(hpriv->unmask_all_irqs, mmio + hpriv->irq_mask_ofs);
Jeff Garzikfb621e22007-02-25 04:19:45 -05002655
Jeff Garzikee9ccdf2007-07-12 15:51:22 -04002656 if (IS_GEN_I(hpriv))
Jeff Garzikfb621e22007-02-25 04:19:45 -05002657 writelfl(~HC_MAIN_MASKED_IRQS_5, mmio + HC_MAIN_IRQ_MASK_OFS);
2658 else
2659 writelfl(~HC_MAIN_MASKED_IRQS, mmio + HC_MAIN_IRQ_MASK_OFS);
Brett Russ20f733e2005-09-01 18:26:17 -04002660
2661 VPRINTK("HC MAIN IRQ cause/mask=0x%08x/0x%08x "
Jeff Garzik8b260242005-11-12 12:32:50 -05002662 "PCI int cause/mask=0x%08x/0x%08x\n",
Brett Russ20f733e2005-09-01 18:26:17 -04002663 readl(mmio + HC_MAIN_IRQ_CAUSE_OFS),
2664 readl(mmio + HC_MAIN_IRQ_MASK_OFS),
Mark Lord02a121d2007-12-01 13:07:22 -05002665 readl(mmio + hpriv->irq_cause_ofs),
2666 readl(mmio + hpriv->irq_mask_ofs));
Jeff Garzikbca1c4e2005-11-12 12:48:15 -05002667
Brett Russ31961942005-09-30 01:36:00 -04002668done:
Brett Russ20f733e2005-09-01 18:26:17 -04002669 return rc;
2670}
2671
Brett Russ05b308e2005-10-05 17:08:53 -04002672/**
2673 * mv_print_info - Dump key info to kernel log for perusal.
Tejun Heo4447d352007-04-17 23:44:08 +09002674 * @host: ATA host to print info about
Brett Russ05b308e2005-10-05 17:08:53 -04002675 *
2676 * FIXME: complete this.
2677 *
2678 * LOCKING:
2679 * Inherited from caller.
2680 */
Tejun Heo4447d352007-04-17 23:44:08 +09002681static void mv_print_info(struct ata_host *host)
Brett Russ31961942005-09-30 01:36:00 -04002682{
Tejun Heo4447d352007-04-17 23:44:08 +09002683 struct pci_dev *pdev = to_pci_dev(host->dev);
2684 struct mv_host_priv *hpriv = host->private_data;
Auke Kok44c10132007-06-08 15:46:36 -07002685 u8 scc;
Jeff Garzikc1e4fe72007-07-09 12:29:31 -04002686 const char *scc_s, *gen;
Brett Russ31961942005-09-30 01:36:00 -04002687
2688 /* Use this to determine the HW stepping of the chip so we know
2689 * what errata to workaround
2690 */
Brett Russ31961942005-09-30 01:36:00 -04002691 pci_read_config_byte(pdev, PCI_CLASS_DEVICE, &scc);
2692 if (scc == 0)
2693 scc_s = "SCSI";
2694 else if (scc == 0x01)
2695 scc_s = "RAID";
2696 else
Jeff Garzikc1e4fe72007-07-09 12:29:31 -04002697 scc_s = "?";
2698
2699 if (IS_GEN_I(hpriv))
2700 gen = "I";
2701 else if (IS_GEN_II(hpriv))
2702 gen = "II";
2703 else if (IS_GEN_IIE(hpriv))
2704 gen = "IIE";
2705 else
2706 gen = "?";
Brett Russ31961942005-09-30 01:36:00 -04002707
Jeff Garzika9524a72005-10-30 14:39:11 -05002708 dev_printk(KERN_INFO, &pdev->dev,
Jeff Garzikc1e4fe72007-07-09 12:29:31 -04002709 "Gen-%s %u slots %u ports %s mode IRQ via %s\n",
2710 gen, (unsigned)MV_MAX_Q_DEPTH, host->n_ports,
Brett Russ31961942005-09-30 01:36:00 -04002711 scc_s, (MV_HP_FLAG_MSI & hpriv->hp_flags) ? "MSI" : "INTx");
2712}
2713
Brett Russ05b308e2005-10-05 17:08:53 -04002714/**
2715 * mv_init_one - handle a positive probe of a Marvell host
2716 * @pdev: PCI device found
2717 * @ent: PCI device ID entry for the matched host
2718 *
2719 * LOCKING:
2720 * Inherited from caller.
2721 */
Brett Russ20f733e2005-09-01 18:26:17 -04002722static int mv_init_one(struct pci_dev *pdev, const struct pci_device_id *ent)
2723{
Jeff Garzik2dcb4072007-10-19 06:42:56 -04002724 static int printed_version;
Brett Russ20f733e2005-09-01 18:26:17 -04002725 unsigned int board_idx = (unsigned int)ent->driver_data;
Tejun Heo4447d352007-04-17 23:44:08 +09002726 const struct ata_port_info *ppi[] = { &mv_port_info[board_idx], NULL };
2727 struct ata_host *host;
2728 struct mv_host_priv *hpriv;
2729 int n_ports, rc;
Brett Russ20f733e2005-09-01 18:26:17 -04002730
Jeff Garzika9524a72005-10-30 14:39:11 -05002731 if (!printed_version++)
2732 dev_printk(KERN_INFO, &pdev->dev, "version " DRV_VERSION "\n");
Brett Russ20f733e2005-09-01 18:26:17 -04002733
Tejun Heo4447d352007-04-17 23:44:08 +09002734 /* allocate host */
2735 n_ports = mv_get_hc_count(ppi[0]->flags) * MV_PORTS_PER_HC;
2736
2737 host = ata_host_alloc_pinfo(&pdev->dev, ppi, n_ports);
2738 hpriv = devm_kzalloc(&pdev->dev, sizeof(*hpriv), GFP_KERNEL);
2739 if (!host || !hpriv)
2740 return -ENOMEM;
2741 host->private_data = hpriv;
2742
2743 /* acquire resources */
Tejun Heo24dc5f32007-01-20 16:00:28 +09002744 rc = pcim_enable_device(pdev);
2745 if (rc)
Brett Russ20f733e2005-09-01 18:26:17 -04002746 return rc;
Brett Russ20f733e2005-09-01 18:26:17 -04002747
Tejun Heo0d5ff562007-02-01 15:06:36 +09002748 rc = pcim_iomap_regions(pdev, 1 << MV_PRIMARY_BAR, DRV_NAME);
2749 if (rc == -EBUSY)
Tejun Heo24dc5f32007-01-20 16:00:28 +09002750 pcim_pin_device(pdev);
Tejun Heo0d5ff562007-02-01 15:06:36 +09002751 if (rc)
Tejun Heo24dc5f32007-01-20 16:00:28 +09002752 return rc;
Tejun Heo4447d352007-04-17 23:44:08 +09002753 host->iomap = pcim_iomap_table(pdev);
Brett Russ20f733e2005-09-01 18:26:17 -04002754
Jeff Garzikd88184f2007-02-26 01:26:06 -05002755 rc = pci_go_64(pdev);
2756 if (rc)
2757 return rc;
2758
Brett Russ20f733e2005-09-01 18:26:17 -04002759 /* initialize adapter */
Tejun Heo4447d352007-04-17 23:44:08 +09002760 rc = mv_init_host(host, board_idx);
Tejun Heo24dc5f32007-01-20 16:00:28 +09002761 if (rc)
2762 return rc;
Brett Russ20f733e2005-09-01 18:26:17 -04002763
Brett Russ31961942005-09-30 01:36:00 -04002764 /* Enable interrupts */
Tejun Heo6a59dcf2007-02-24 15:12:31 +09002765 if (msi && pci_enable_msi(pdev))
Brett Russ31961942005-09-30 01:36:00 -04002766 pci_intx(pdev, 1);
Brett Russ20f733e2005-09-01 18:26:17 -04002767
Brett Russ31961942005-09-30 01:36:00 -04002768 mv_dump_pci_cfg(pdev, 0x68);
Tejun Heo4447d352007-04-17 23:44:08 +09002769 mv_print_info(host);
Brett Russ20f733e2005-09-01 18:26:17 -04002770
Tejun Heo4447d352007-04-17 23:44:08 +09002771 pci_set_master(pdev);
Jeff Garzikea8b4db2007-07-17 02:21:50 -04002772 pci_try_set_mwi(pdev);
Tejun Heo4447d352007-04-17 23:44:08 +09002773 return ata_host_activate(host, pdev->irq, mv_interrupt, IRQF_SHARED,
Jeff Garzikc5d3e452007-07-11 18:30:50 -04002774 IS_GEN_I(hpriv) ? &mv5_sht : &mv6_sht);
Brett Russ20f733e2005-09-01 18:26:17 -04002775}
2776
2777static int __init mv_init(void)
2778{
Pavel Roskinb7887192006-08-10 18:13:18 +09002779 return pci_register_driver(&mv_pci_driver);
Brett Russ20f733e2005-09-01 18:26:17 -04002780}
2781
2782static void __exit mv_exit(void)
2783{
2784 pci_unregister_driver(&mv_pci_driver);
2785}
2786
2787MODULE_AUTHOR("Brett Russ");
2788MODULE_DESCRIPTION("SCSI low-level driver for Marvell SATA controllers");
2789MODULE_LICENSE("GPL");
2790MODULE_DEVICE_TABLE(pci, mv_pci_tbl);
2791MODULE_VERSION(DRV_VERSION);
2792
Jeff Garzikddef9bb2006-02-02 16:17:06 -05002793module_param(msi, int, 0444);
2794MODULE_PARM_DESC(msi, "Enable use of PCI MSI (0=off, 1=on)");
2795
Brett Russ20f733e2005-09-01 18:26:17 -04002796module_init(mv_init);
2797module_exit(mv_exit);