sata_mv.c revision ea8b4db97aa41a66c05daa4055a1974692ccd52d
120f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ/*
220f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ * sata_mv.c - Marvell SATA support
320f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ *
48b260248d9e0e8b64bb72fd4dee03ad86984c344Jeff Garzik * Copyright 2005: EMC Corporation, all rights reserved.
5e2b1be56c5656902744c2b52e8304126a40bb609Jeff Garzik * Copyright 2005 Red Hat, Inc.  All rights reserved.
620f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ *
720f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ * Please ALWAYS copy linux-ide@vger.kernel.org on emails.
820f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ *
920f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ * This program is free software; you can redistribute it and/or modify
1020f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ * it under the terms of the GNU General Public License as published by
1120f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ * the Free Software Foundation; version 2 of the License.
1220f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ *
1320f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ * This program is distributed in the hope that it will be useful,
1420f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ * but WITHOUT ANY WARRANTY; without even the implied warranty of
1520f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
1620f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ * GNU General Public License for more details.
1720f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ *
1820f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ * You should have received a copy of the GNU General Public License
1920f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ * along with this program; if not, write to the Free Software
2020f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
2120f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ *
2220f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ */
2320f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ
244a05e2091709dbb22b86a1b3343cd3fa3c0d7a6bJeff Garzik/*
254a05e2091709dbb22b86a1b3343cd3fa3c0d7a6bJeff Garzik  sata_mv TODO list:
264a05e2091709dbb22b86a1b3343cd3fa3c0d7a6bJeff Garzik
274a05e2091709dbb22b86a1b3343cd3fa3c0d7a6bJeff Garzik  1) Needs a full errata audit for all chipsets.  I implemented most
284a05e2091709dbb22b86a1b3343cd3fa3c0d7a6bJeff Garzik  of the errata workarounds found in the Marvell vendor driver, but
294a05e2091709dbb22b86a1b3343cd3fa3c0d7a6bJeff Garzik  I distinctly remember a couple workarounds (one related to PCI-X)
304a05e2091709dbb22b86a1b3343cd3fa3c0d7a6bJeff Garzik  are still needed.
314a05e2091709dbb22b86a1b3343cd3fa3c0d7a6bJeff Garzik
324a05e2091709dbb22b86a1b3343cd3fa3c0d7a6bJeff Garzik  4) Add NCQ support (easy to intermediate, once new-EH support appears)
334a05e2091709dbb22b86a1b3343cd3fa3c0d7a6bJeff Garzik
344a05e2091709dbb22b86a1b3343cd3fa3c0d7a6bJeff Garzik  5) Investigate problems with PCI Message Signalled Interrupts (MSI).
354a05e2091709dbb22b86a1b3343cd3fa3c0d7a6bJeff Garzik
364a05e2091709dbb22b86a1b3343cd3fa3c0d7a6bJeff Garzik  6) Add port multiplier support (intermediate)
374a05e2091709dbb22b86a1b3343cd3fa3c0d7a6bJeff Garzik
384a05e2091709dbb22b86a1b3343cd3fa3c0d7a6bJeff Garzik  7) Test and verify 3.0 Gbps support
394a05e2091709dbb22b86a1b3343cd3fa3c0d7a6bJeff Garzik
404a05e2091709dbb22b86a1b3343cd3fa3c0d7a6bJeff Garzik  8) Develop a low-power-consumption strategy, and implement it.
414a05e2091709dbb22b86a1b3343cd3fa3c0d7a6bJeff Garzik
424a05e2091709dbb22b86a1b3343cd3fa3c0d7a6bJeff Garzik  9) [Experiment, low priority] See if ATAPI can be supported using
434a05e2091709dbb22b86a1b3343cd3fa3c0d7a6bJeff Garzik  "unknown FIS" or "vendor-specific FIS" support, or something creative
444a05e2091709dbb22b86a1b3343cd3fa3c0d7a6bJeff Garzik  like that.
454a05e2091709dbb22b86a1b3343cd3fa3c0d7a6bJeff Garzik
464a05e2091709dbb22b86a1b3343cd3fa3c0d7a6bJeff Garzik  10) [Experiment, low priority] Investigate interrupt coalescing.
474a05e2091709dbb22b86a1b3343cd3fa3c0d7a6bJeff Garzik  Quite often, especially with PCI Message Signalled Interrupts (MSI),
484a05e2091709dbb22b86a1b3343cd3fa3c0d7a6bJeff Garzik  the overhead reduced by interrupt mitigation is quite often not
494a05e2091709dbb22b86a1b3343cd3fa3c0d7a6bJeff Garzik  worth the latency cost.
504a05e2091709dbb22b86a1b3343cd3fa3c0d7a6bJeff Garzik
514a05e2091709dbb22b86a1b3343cd3fa3c0d7a6bJeff Garzik  11) [Experiment, Marvell value added] Is it possible to use target
524a05e2091709dbb22b86a1b3343cd3fa3c0d7a6bJeff Garzik  mode to cross-connect two Linux boxes with Marvell cards?  If so,
534a05e2091709dbb22b86a1b3343cd3fa3c0d7a6bJeff Garzik  creating LibATA target mode support would be very interesting.
544a05e2091709dbb22b86a1b3343cd3fa3c0d7a6bJeff Garzik
554a05e2091709dbb22b86a1b3343cd3fa3c0d7a6bJeff Garzik  Target mode, for those without docs, is the ability to directly
564a05e2091709dbb22b86a1b3343cd3fa3c0d7a6bJeff Garzik  connect two SATA controllers.
574a05e2091709dbb22b86a1b3343cd3fa3c0d7a6bJeff Garzik
584a05e2091709dbb22b86a1b3343cd3fa3c0d7a6bJeff Garzik  13) Verify that 7042 is fully supported.  I only have a 6042.
594a05e2091709dbb22b86a1b3343cd3fa3c0d7a6bJeff Garzik
604a05e2091709dbb22b86a1b3343cd3fa3c0d7a6bJeff Garzik*/
614a05e2091709dbb22b86a1b3343cd3fa3c0d7a6bJeff Garzik
624a05e2091709dbb22b86a1b3343cd3fa3c0d7a6bJeff Garzik
6320f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ#include <linux/kernel.h>
6420f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ#include <linux/module.h>
6520f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ#include <linux/pci.h>
6620f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ#include <linux/init.h>
6720f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ#include <linux/blkdev.h>
6820f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ#include <linux/delay.h>
6920f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ#include <linux/interrupt.h>
7020f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ#include <linux/dma-mapping.h>
71a9524a76f70f3343e4be27f95a7e92a8ba5f9009Jeff Garzik#include <linux/device.h>
7220f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ#include <scsi/scsi_host.h>
73193515d51ccb363165d6b09e9ba5c21089e34badJeff Garzik#include <scsi/scsi_cmnd.h>
7420f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ#include <linux/libata.h>
7520f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ
7620f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ#define DRV_NAME	"sata_mv"
778bc3fc470eb25af4d70c72485cbcb130cc657691Jeff Garzik#define DRV_VERSION	"0.81"
7820f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ
7920f733e7d75a16bffc34842b7682c9247dd5f954Brett Russenum {
8020f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ	/* BAR's are enumerated in terms of pci_resource_start() terms */
8120f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ	MV_PRIMARY_BAR		= 0,	/* offset 0x10: memory space */
8220f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ	MV_IO_BAR		= 2,	/* offset 0x18: IO space */
8320f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ	MV_MISC_BAR		= 3,	/* offset 0x1c: FLASH, NVRAM, SRAM */
8420f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ
8520f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ	MV_MAJOR_REG_AREA_SZ	= 0x10000,	/* 64KB */
8620f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ	MV_MINOR_REG_AREA_SZ	= 0x2000,	/* 8KB */
8720f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ
8820f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ	MV_PCI_REG_BASE		= 0,
8920f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ	MV_IRQ_COAL_REG_BASE	= 0x18000,	/* 6xxx part only */
90615ab95342f6245026d8974b9724f7ea57d9a184Mark Lord	MV_IRQ_COAL_CAUSE		= (MV_IRQ_COAL_REG_BASE + 0x08),
91615ab95342f6245026d8974b9724f7ea57d9a184Mark Lord	MV_IRQ_COAL_CAUSE_LO		= (MV_IRQ_COAL_REG_BASE + 0x88),
92615ab95342f6245026d8974b9724f7ea57d9a184Mark Lord	MV_IRQ_COAL_CAUSE_HI		= (MV_IRQ_COAL_REG_BASE + 0x8c),
93615ab95342f6245026d8974b9724f7ea57d9a184Mark Lord	MV_IRQ_COAL_THRESHOLD		= (MV_IRQ_COAL_REG_BASE + 0xcc),
94615ab95342f6245026d8974b9724f7ea57d9a184Mark Lord	MV_IRQ_COAL_TIME_THRESHOLD	= (MV_IRQ_COAL_REG_BASE + 0xd0),
95615ab95342f6245026d8974b9724f7ea57d9a184Mark Lord
9620f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ	MV_SATAHC0_REG_BASE	= 0x20000,
97522479fb98c6667f081e75f87e298e413c0b1db8Jeff Garzik	MV_FLASH_CTL		= 0x1046c,
98bca1c4eb9411533d613123618c0d127fae532595Jeff Garzik	MV_GPIO_PORT_CTL	= 0x104f0,
99bca1c4eb9411533d613123618c0d127fae532595Jeff Garzik	MV_RESET_CFG		= 0x180d8,
10020f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ
10120f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ	MV_PCI_REG_SZ		= MV_MAJOR_REG_AREA_SZ,
10220f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ	MV_SATAHC_REG_SZ	= MV_MAJOR_REG_AREA_SZ,
10320f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ	MV_SATAHC_ARBTR_REG_SZ	= MV_MINOR_REG_AREA_SZ,		/* arbiter */
10420f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ	MV_PORT_REG_SZ		= MV_MINOR_REG_AREA_SZ,
10520f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ
10631961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ	MV_MAX_Q_DEPTH		= 32,
10731961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ	MV_MAX_Q_DEPTH_MASK	= MV_MAX_Q_DEPTH - 1,
10831961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ
10931961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ	/* CRQB needs alignment on a 1KB boundary. Size == 1KB
11031961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ	 * CRPB needs alignment on a 256B boundary. Size == 256B
11131961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ	 * SG count of 176 leads to MV_PORT_PRIV_DMA_SZ == 4KB
11231961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ	 * ePRD (SG) entries need alignment on a 16B boundary. Size == 16B
11331961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ	 */
11431961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ	MV_CRQB_Q_SZ		= (32 * MV_MAX_Q_DEPTH),
11531961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ	MV_CRPB_Q_SZ		= (8 * MV_MAX_Q_DEPTH),
11631961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ	MV_MAX_SG_CT		= 176,
11731961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ	MV_SG_TBL_SZ		= (16 * MV_MAX_SG_CT),
11831961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ	MV_PORT_PRIV_DMA_SZ	= (MV_CRQB_Q_SZ + MV_CRPB_Q_SZ + MV_SG_TBL_SZ),
11931961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ
12020f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ	MV_PORTS_PER_HC		= 4,
12120f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ	/* == (port / MV_PORTS_PER_HC) to determine HC from 0-7 port */
12220f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ	MV_PORT_HC_SHIFT	= 2,
12331961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ	/* == (port % MV_PORTS_PER_HC) to determine hard port from 0-7 port */
12420f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ	MV_PORT_MASK		= 3,
12520f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ
12620f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ	/* Host Flags */
12720f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ	MV_FLAG_DUAL_HC		= (1 << 30),  /* two SATA Host Controllers */
12820f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ	MV_FLAG_IRQ_COALESCE	= (1 << 29),  /* IRQ coalescing capability */
129c5d3e45a2200a0905dc45b72714726b7aac3aaf1Jeff Garzik	MV_COMMON_FLAGS		= ATA_FLAG_SATA | ATA_FLAG_NO_LEGACY |
130bdd4dddee325a7dce3e84cf48201a06aa8508aa4Jeff Garzik				  ATA_FLAG_MMIO | ATA_FLAG_NO_ATAPI |
131bdd4dddee325a7dce3e84cf48201a06aa8508aa4Jeff Garzik				  ATA_FLAG_PIO_POLLING,
13247c2b677daeed9c79ecb7167c211ff36876ea611Jeff Garzik	MV_6XXX_FLAGS		= MV_FLAG_IRQ_COALESCE,
13320f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ
13431961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ	CRQB_FLAG_READ		= (1 << 0),
13531961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ	CRQB_TAG_SHIFT		= 1,
136c5d3e45a2200a0905dc45b72714726b7aac3aaf1Jeff Garzik	CRQB_IOID_SHIFT		= 6,	/* CRQB Gen-II/IIE IO Id shift */
137c5d3e45a2200a0905dc45b72714726b7aac3aaf1Jeff Garzik	CRQB_HOSTQ_SHIFT	= 17,	/* CRQB Gen-II/IIE HostQueTag shift */
13831961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ	CRQB_CMD_ADDR_SHIFT	= 8,
13931961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ	CRQB_CMD_CS		= (0x2 << 11),
14031961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ	CRQB_CMD_LAST		= (1 << 15),
14131961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ
14231961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ	CRPB_FLAG_STATUS_SHIFT	= 8,
143c5d3e45a2200a0905dc45b72714726b7aac3aaf1Jeff Garzik	CRPB_IOID_SHIFT_6	= 5,	/* CRPB Gen-II IO Id shift */
144c5d3e45a2200a0905dc45b72714726b7aac3aaf1Jeff Garzik	CRPB_IOID_SHIFT_7	= 7,	/* CRPB Gen-IIE IO Id shift */
14531961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ
14631961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ	EPRD_FLAG_END_OF_TBL	= (1 << 31),
14731961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ
14820f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ	/* PCI interface registers */
14920f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ
15031961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ	PCI_COMMAND_OFS		= 0xc00,
15131961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ
15220f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ	PCI_MAIN_CMD_STS_OFS	= 0xd30,
15320f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ	STOP_PCI_MASTER		= (1 << 2),
15420f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ	PCI_MASTER_EMPTY	= (1 << 3),
15520f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ	GLOB_SFT_RST		= (1 << 4),
15620f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ
157522479fb98c6667f081e75f87e298e413c0b1db8Jeff Garzik	MV_PCI_MODE		= 0xd00,
158522479fb98c6667f081e75f87e298e413c0b1db8Jeff Garzik	MV_PCI_EXP_ROM_BAR_CTL	= 0xd2c,
159522479fb98c6667f081e75f87e298e413c0b1db8Jeff Garzik	MV_PCI_DISC_TIMER	= 0xd04,
160522479fb98c6667f081e75f87e298e413c0b1db8Jeff Garzik	MV_PCI_MSI_TRIGGER	= 0xc38,
161522479fb98c6667f081e75f87e298e413c0b1db8Jeff Garzik	MV_PCI_SERR_MASK	= 0xc28,
162522479fb98c6667f081e75f87e298e413c0b1db8Jeff Garzik	MV_PCI_XBAR_TMOUT	= 0x1d04,
163522479fb98c6667f081e75f87e298e413c0b1db8Jeff Garzik	MV_PCI_ERR_LOW_ADDRESS	= 0x1d40,
164522479fb98c6667f081e75f87e298e413c0b1db8Jeff Garzik	MV_PCI_ERR_HIGH_ADDRESS	= 0x1d44,
165522479fb98c6667f081e75f87e298e413c0b1db8Jeff Garzik	MV_PCI_ERR_ATTRIBUTE	= 0x1d48,
166522479fb98c6667f081e75f87e298e413c0b1db8Jeff Garzik	MV_PCI_ERR_COMMAND	= 0x1d50,
167522479fb98c6667f081e75f87e298e413c0b1db8Jeff Garzik
168522479fb98c6667f081e75f87e298e413c0b1db8Jeff Garzik	PCI_IRQ_CAUSE_OFS		= 0x1d58,
169522479fb98c6667f081e75f87e298e413c0b1db8Jeff Garzik	PCI_IRQ_MASK_OFS		= 0x1d5c,
17020f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ	PCI_UNMASK_ALL_IRQS	= 0x7fffff,	/* bits 22-0 */
17120f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ
17220f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ	HC_MAIN_IRQ_CAUSE_OFS	= 0x1d60,
17320f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ	HC_MAIN_IRQ_MASK_OFS	= 0x1d64,
17420f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ	PORT0_ERR		= (1 << 0),	/* shift by port # */
17520f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ	PORT0_DONE		= (1 << 1),	/* shift by port # */
17620f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ	HC0_IRQ_PEND		= 0x1ff,	/* bits 0-8 = HC0's ports */
17720f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ	HC_SHIFT		= 9,		/* bits 9-17 = HC1's ports */
17820f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ	PCI_ERR			= (1 << 18),
17920f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ	TRAN_LO_DONE		= (1 << 19),	/* 6xxx: IRQ coalescing */
18020f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ	TRAN_HI_DONE		= (1 << 20),	/* 6xxx: IRQ coalescing */
181fb621e2fde735abab854586d52c96c5624bcb5b8Jeff Garzik	PORTS_0_3_COAL_DONE	= (1 << 8),
182fb621e2fde735abab854586d52c96c5624bcb5b8Jeff Garzik	PORTS_4_7_COAL_DONE	= (1 << 17),
18320f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ	PORTS_0_7_COAL_DONE	= (1 << 21),	/* 6xxx: IRQ coalescing */
18420f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ	GPIO_INT		= (1 << 22),
18520f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ	SELF_INT		= (1 << 23),
18620f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ	TWSI_INT		= (1 << 24),
18720f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ	HC_MAIN_RSVD		= (0x7f << 25),	/* bits 31-25 */
188fb621e2fde735abab854586d52c96c5624bcb5b8Jeff Garzik	HC_MAIN_RSVD_5		= (0x1fff << 19), /* bits 31-19 */
1898b260248d9e0e8b64bb72fd4dee03ad86984c344Jeff Garzik	HC_MAIN_MASKED_IRQS	= (TRAN_LO_DONE | TRAN_HI_DONE |
19020f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ				   PORTS_0_7_COAL_DONE | GPIO_INT | TWSI_INT |
19120f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ				   HC_MAIN_RSVD),
192fb621e2fde735abab854586d52c96c5624bcb5b8Jeff Garzik	HC_MAIN_MASKED_IRQS_5	= (PORTS_0_3_COAL_DONE | PORTS_4_7_COAL_DONE |
193fb621e2fde735abab854586d52c96c5624bcb5b8Jeff Garzik				   HC_MAIN_RSVD_5),
19420f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ
19520f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ	/* SATAHC registers */
19620f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ	HC_CFG_OFS		= 0,
19720f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ
19820f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ	HC_IRQ_CAUSE_OFS	= 0x14,
19931961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ	CRPB_DMA_DONE		= (1 << 0),	/* shift by port # */
20020f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ	HC_IRQ_COAL		= (1 << 4),	/* IRQ coalescing */
20120f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ	DEV_IRQ			= (1 << 8),	/* shift by port # */
20220f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ
20320f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ	/* Shadow block registers */
20431961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ	SHD_BLK_OFS		= 0x100,
20531961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ	SHD_CTL_AST_OFS		= 0x20,		/* ofs from SHD_BLK_OFS */
20620f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ
20720f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ	/* SATA registers */
20820f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ	SATA_STATUS_OFS		= 0x300,  /* ctrl, err regs follow status */
20920f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ	SATA_ACTIVE_OFS		= 0x350,
21047c2b677daeed9c79ecb7167c211ff36876ea611Jeff Garzik	PHY_MODE3		= 0x310,
211bca1c4eb9411533d613123618c0d127fae532595Jeff Garzik	PHY_MODE4		= 0x314,
212bca1c4eb9411533d613123618c0d127fae532595Jeff Garzik	PHY_MODE2		= 0x330,
213c9d39130123238ac18478a42e25cb7996eacfcc0Jeff Garzik	MV5_PHY_MODE		= 0x74,
214c9d39130123238ac18478a42e25cb7996eacfcc0Jeff Garzik	MV5_LT_MODE		= 0x30,
215c9d39130123238ac18478a42e25cb7996eacfcc0Jeff Garzik	MV5_PHY_CTL		= 0x0C,
216bca1c4eb9411533d613123618c0d127fae532595Jeff Garzik	SATA_INTERFACE_CTL	= 0x050,
217bca1c4eb9411533d613123618c0d127fae532595Jeff Garzik
218bca1c4eb9411533d613123618c0d127fae532595Jeff Garzik	MV_M2_PREAMP_MASK	= 0x7e0,
21920f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ
22020f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ	/* Port registers */
22120f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ	EDMA_CFG_OFS		= 0,
22231961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ	EDMA_CFG_Q_DEPTH	= 0,			/* queueing disabled */
22331961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ	EDMA_CFG_NCQ		= (1 << 5),
22431961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ	EDMA_CFG_NCQ_GO_ON_ERR	= (1 << 14),		/* continue on error */
22531961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ	EDMA_CFG_RD_BRST_EXT	= (1 << 11),		/* read burst 512B */
22631961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ	EDMA_CFG_WR_BUFF_LEN	= (1 << 13),		/* write buffer 512B */
22720f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ
22820f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ	EDMA_ERR_IRQ_CAUSE_OFS	= 0x8,
22920f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ	EDMA_ERR_IRQ_MASK_OFS	= 0xc,
23020f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ	EDMA_ERR_D_PAR		= (1 << 0),
23120f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ	EDMA_ERR_PRD_PAR	= (1 << 1),
23220f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ	EDMA_ERR_DEV		= (1 << 2),
23320f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ	EDMA_ERR_DEV_DCON	= (1 << 3),
23420f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ	EDMA_ERR_DEV_CON	= (1 << 4),
23520f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ	EDMA_ERR_SERR		= (1 << 5),
236c5d3e45a2200a0905dc45b72714726b7aac3aaf1Jeff Garzik	EDMA_ERR_SELF_DIS	= (1 << 7),	/* Gen II/IIE self-disable */
237c5d3e45a2200a0905dc45b72714726b7aac3aaf1Jeff Garzik	EDMA_ERR_SELF_DIS_5	= (1 << 8),	/* Gen I self-disable */
23820f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ	EDMA_ERR_BIST_ASYNC	= (1 << 8),
239c5d3e45a2200a0905dc45b72714726b7aac3aaf1Jeff Garzik	EDMA_ERR_TRANS_IRQ_7	= (1 << 8),	/* Gen IIE transprt layer irq */
24020f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ	EDMA_ERR_CRBQ_PAR	= (1 << 9),
24120f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ	EDMA_ERR_CRPB_PAR	= (1 << 10),
24220f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ	EDMA_ERR_INTRL_PAR	= (1 << 11),
24320f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ	EDMA_ERR_IORDY		= (1 << 12),
24420f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ	EDMA_ERR_LNK_CTRL_RX	= (0xf << 13),
24520f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ	EDMA_ERR_LNK_CTRL_RX_2	= (1 << 15),
24620f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ	EDMA_ERR_LNK_DATA_RX	= (0xf << 17),
24720f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ	EDMA_ERR_LNK_CTRL_TX	= (0x1f << 21),
24820f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ	EDMA_ERR_LNK_DATA_TX	= (0x1f << 26),
24920f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ	EDMA_ERR_TRANS_PROTO	= (1 << 31),
250c5d3e45a2200a0905dc45b72714726b7aac3aaf1Jeff Garzik	EDMA_ERR_OVERRUN_5	= (1 << 5),
251c5d3e45a2200a0905dc45b72714726b7aac3aaf1Jeff Garzik	EDMA_ERR_UNDERRUN_5	= (1 << 6),
252bdd4dddee325a7dce3e84cf48201a06aa8508aa4Jeff Garzik	EDMA_EH_FREEZE		= EDMA_ERR_D_PAR |
253bdd4dddee325a7dce3e84cf48201a06aa8508aa4Jeff Garzik				  EDMA_ERR_PRD_PAR |
254bdd4dddee325a7dce3e84cf48201a06aa8508aa4Jeff Garzik				  EDMA_ERR_DEV_DCON |
255bdd4dddee325a7dce3e84cf48201a06aa8508aa4Jeff Garzik				  EDMA_ERR_DEV_CON |
256bdd4dddee325a7dce3e84cf48201a06aa8508aa4Jeff Garzik				  EDMA_ERR_SERR |
257bdd4dddee325a7dce3e84cf48201a06aa8508aa4Jeff Garzik				  EDMA_ERR_SELF_DIS |
258bdd4dddee325a7dce3e84cf48201a06aa8508aa4Jeff Garzik				  EDMA_ERR_CRBQ_PAR |
259bdd4dddee325a7dce3e84cf48201a06aa8508aa4Jeff Garzik				  EDMA_ERR_CRPB_PAR |
260bdd4dddee325a7dce3e84cf48201a06aa8508aa4Jeff Garzik				  EDMA_ERR_INTRL_PAR |
261bdd4dddee325a7dce3e84cf48201a06aa8508aa4Jeff Garzik				  EDMA_ERR_IORDY |
262bdd4dddee325a7dce3e84cf48201a06aa8508aa4Jeff Garzik				  EDMA_ERR_LNK_CTRL_RX_2 |
263bdd4dddee325a7dce3e84cf48201a06aa8508aa4Jeff Garzik				  EDMA_ERR_LNK_DATA_RX |
264bdd4dddee325a7dce3e84cf48201a06aa8508aa4Jeff Garzik				  EDMA_ERR_LNK_DATA_TX |
265bdd4dddee325a7dce3e84cf48201a06aa8508aa4Jeff Garzik				  EDMA_ERR_TRANS_PROTO,
266bdd4dddee325a7dce3e84cf48201a06aa8508aa4Jeff Garzik	EDMA_EH_FREEZE_5	= EDMA_ERR_D_PAR |
267bdd4dddee325a7dce3e84cf48201a06aa8508aa4Jeff Garzik				  EDMA_ERR_PRD_PAR |
268bdd4dddee325a7dce3e84cf48201a06aa8508aa4Jeff Garzik				  EDMA_ERR_DEV_DCON |
269bdd4dddee325a7dce3e84cf48201a06aa8508aa4Jeff Garzik				  EDMA_ERR_DEV_CON |
270bdd4dddee325a7dce3e84cf48201a06aa8508aa4Jeff Garzik				  EDMA_ERR_OVERRUN_5 |
271bdd4dddee325a7dce3e84cf48201a06aa8508aa4Jeff Garzik				  EDMA_ERR_UNDERRUN_5 |
272bdd4dddee325a7dce3e84cf48201a06aa8508aa4Jeff Garzik				  EDMA_ERR_SELF_DIS_5 |
273bdd4dddee325a7dce3e84cf48201a06aa8508aa4Jeff Garzik				  EDMA_ERR_CRBQ_PAR |
274bdd4dddee325a7dce3e84cf48201a06aa8508aa4Jeff Garzik				  EDMA_ERR_CRPB_PAR |
275bdd4dddee325a7dce3e84cf48201a06aa8508aa4Jeff Garzik				  EDMA_ERR_INTRL_PAR |
276bdd4dddee325a7dce3e84cf48201a06aa8508aa4Jeff Garzik				  EDMA_ERR_IORDY,
27720f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ
27831961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ	EDMA_REQ_Q_BASE_HI_OFS	= 0x10,
27931961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ	EDMA_REQ_Q_IN_PTR_OFS	= 0x14,		/* also contains BASE_LO */
28031961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ
28131961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ	EDMA_REQ_Q_OUT_PTR_OFS	= 0x18,
28231961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ	EDMA_REQ_Q_PTR_SHIFT	= 5,
28331961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ
28431961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ	EDMA_RSP_Q_BASE_HI_OFS	= 0x1c,
28531961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ	EDMA_RSP_Q_IN_PTR_OFS	= 0x20,
28631961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ	EDMA_RSP_Q_OUT_PTR_OFS	= 0x24,		/* also contains BASE_LO */
28731961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ	EDMA_RSP_Q_PTR_SHIFT	= 3,
28831961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ
28920f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ	EDMA_CMD_OFS		= 0x28,
29020f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ	EDMA_EN			= (1 << 0),
29120f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ	EDMA_DS			= (1 << 1),
29220f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ	ATA_RST			= (1 << 2),
29320f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ
294c9d39130123238ac18478a42e25cb7996eacfcc0Jeff Garzik	EDMA_IORDY_TMOUT	= 0x34,
295bca1c4eb9411533d613123618c0d127fae532595Jeff Garzik	EDMA_ARB_CFG		= 0x38,
296bca1c4eb9411533d613123618c0d127fae532595Jeff Garzik
29731961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ	/* Host private flags (hp_flags) */
29831961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ	MV_HP_FLAG_MSI		= (1 << 0),
29947c2b677daeed9c79ecb7167c211ff36876ea611Jeff Garzik	MV_HP_ERRATA_50XXB0	= (1 << 1),
30047c2b677daeed9c79ecb7167c211ff36876ea611Jeff Garzik	MV_HP_ERRATA_50XXB2	= (1 << 2),
30147c2b677daeed9c79ecb7167c211ff36876ea611Jeff Garzik	MV_HP_ERRATA_60X1B2	= (1 << 3),
30247c2b677daeed9c79ecb7167c211ff36876ea611Jeff Garzik	MV_HP_ERRATA_60X1C0	= (1 << 4),
303e4e7b89280d1d666e2c09e5ad36cf071796c4c7eJeff Garzik	MV_HP_ERRATA_XX42A0	= (1 << 5),
304ee9ccdf70163ca6408f6965e0fbc65baeac7312cJeff Garzik	MV_HP_GEN_I		= (1 << 6),
305ee9ccdf70163ca6408f6965e0fbc65baeac7312cJeff Garzik	MV_HP_GEN_II		= (1 << 7),
306ee9ccdf70163ca6408f6965e0fbc65baeac7312cJeff Garzik	MV_HP_GEN_IIE		= (1 << 8),
30720f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ
30831961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ	/* Port private flags (pp_flags) */
30931961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ	MV_PP_FLAG_EDMA_EN	= (1 << 0),
31031961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ	MV_PP_FLAG_EDMA_DS_ACT	= (1 << 1),
311c5d3e45a2200a0905dc45b72714726b7aac3aaf1Jeff Garzik	MV_PP_FLAG_HAD_A_RESET	= (1 << 2),
31220f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ};
31320f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ
314ee9ccdf70163ca6408f6965e0fbc65baeac7312cJeff Garzik#define IS_GEN_I(hpriv) ((hpriv)->hp_flags & MV_HP_GEN_I)
315ee9ccdf70163ca6408f6965e0fbc65baeac7312cJeff Garzik#define IS_GEN_II(hpriv) ((hpriv)->hp_flags & MV_HP_GEN_II)
316e4e7b89280d1d666e2c09e5ad36cf071796c4c7eJeff Garzik#define IS_GEN_IIE(hpriv) ((hpriv)->hp_flags & MV_HP_GEN_IIE)
317bca1c4eb9411533d613123618c0d127fae532595Jeff Garzik
318095fec887eaa1c38d17c0c929a6733c744a9fa1fJeff Garzikenum {
319d88184fb2348a50f7c34f5d49a901c875b2e0114Jeff Garzik	MV_DMA_BOUNDARY		= 0xffffffffU,
320095fec887eaa1c38d17c0c929a6733c744a9fa1fJeff Garzik
321095fec887eaa1c38d17c0c929a6733c744a9fa1fJeff Garzik	EDMA_REQ_Q_BASE_LO_MASK	= 0xfffffc00U,
322095fec887eaa1c38d17c0c929a6733c744a9fa1fJeff Garzik
323095fec887eaa1c38d17c0c929a6733c744a9fa1fJeff Garzik	EDMA_RSP_Q_BASE_LO_MASK	= 0xffffff00U,
324095fec887eaa1c38d17c0c929a6733c744a9fa1fJeff Garzik};
325095fec887eaa1c38d17c0c929a6733c744a9fa1fJeff Garzik
326522479fb98c6667f081e75f87e298e413c0b1db8Jeff Garzikenum chip_type {
327522479fb98c6667f081e75f87e298e413c0b1db8Jeff Garzik	chip_504x,
328522479fb98c6667f081e75f87e298e413c0b1db8Jeff Garzik	chip_508x,
329522479fb98c6667f081e75f87e298e413c0b1db8Jeff Garzik	chip_5080,
330522479fb98c6667f081e75f87e298e413c0b1db8Jeff Garzik	chip_604x,
331522479fb98c6667f081e75f87e298e413c0b1db8Jeff Garzik	chip_608x,
332e4e7b89280d1d666e2c09e5ad36cf071796c4c7eJeff Garzik	chip_6042,
333e4e7b89280d1d666e2c09e5ad36cf071796c4c7eJeff Garzik	chip_7042,
334522479fb98c6667f081e75f87e298e413c0b1db8Jeff Garzik};
335522479fb98c6667f081e75f87e298e413c0b1db8Jeff Garzik
33631961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ/* Command ReQuest Block: 32B */
33731961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russstruct mv_crqb {
338e14698745dd0de1ddbf5cd0cca4313a90f8c1cc1Mark Lord	__le32			sg_addr;
339e14698745dd0de1ddbf5cd0cca4313a90f8c1cc1Mark Lord	__le32			sg_addr_hi;
340e14698745dd0de1ddbf5cd0cca4313a90f8c1cc1Mark Lord	__le16			ctrl_flags;
341e14698745dd0de1ddbf5cd0cca4313a90f8c1cc1Mark Lord	__le16			ata_cmd[11];
34231961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ};
34320f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ
344e4e7b89280d1d666e2c09e5ad36cf071796c4c7eJeff Garzikstruct mv_crqb_iie {
345e14698745dd0de1ddbf5cd0cca4313a90f8c1cc1Mark Lord	__le32			addr;
346e14698745dd0de1ddbf5cd0cca4313a90f8c1cc1Mark Lord	__le32			addr_hi;
347e14698745dd0de1ddbf5cd0cca4313a90f8c1cc1Mark Lord	__le32			flags;
348e14698745dd0de1ddbf5cd0cca4313a90f8c1cc1Mark Lord	__le32			len;
349e14698745dd0de1ddbf5cd0cca4313a90f8c1cc1Mark Lord	__le32			ata_cmd[4];
350e4e7b89280d1d666e2c09e5ad36cf071796c4c7eJeff Garzik};
351e4e7b89280d1d666e2c09e5ad36cf071796c4c7eJeff Garzik
35231961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ/* Command ResPonse Block: 8B */
35331961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russstruct mv_crpb {
354e14698745dd0de1ddbf5cd0cca4313a90f8c1cc1Mark Lord	__le16			id;
355e14698745dd0de1ddbf5cd0cca4313a90f8c1cc1Mark Lord	__le16			flags;
356e14698745dd0de1ddbf5cd0cca4313a90f8c1cc1Mark Lord	__le32			tmstmp;
35720f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ};
35820f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ
35931961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ/* EDMA Physical Region Descriptor (ePRD); A.K.A. SG */
36031961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russstruct mv_sg {
361e14698745dd0de1ddbf5cd0cca4313a90f8c1cc1Mark Lord	__le32			addr;
362e14698745dd0de1ddbf5cd0cca4313a90f8c1cc1Mark Lord	__le32			flags_size;
363e14698745dd0de1ddbf5cd0cca4313a90f8c1cc1Mark Lord	__le32			addr_hi;
364e14698745dd0de1ddbf5cd0cca4313a90f8c1cc1Mark Lord	__le32			reserved;
36531961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ};
36620f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ
36731961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russstruct mv_port_priv {
36831961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ	struct mv_crqb		*crqb;
36931961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ	dma_addr_t		crqb_dma;
37031961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ	struct mv_crpb		*crpb;
37131961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ	dma_addr_t		crpb_dma;
37231961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ	struct mv_sg		*sg_tbl;
37331961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ	dma_addr_t		sg_tbl_dma;
374bdd4dddee325a7dce3e84cf48201a06aa8508aa4Jeff Garzik
375bdd4dddee325a7dce3e84cf48201a06aa8508aa4Jeff Garzik	unsigned int		req_idx;
376bdd4dddee325a7dce3e84cf48201a06aa8508aa4Jeff Garzik	unsigned int		resp_idx;
377bdd4dddee325a7dce3e84cf48201a06aa8508aa4Jeff Garzik
37831961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ	u32			pp_flags;
37931961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ};
38031961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ
381bca1c4eb9411533d613123618c0d127fae532595Jeff Garzikstruct mv_port_signal {
382bca1c4eb9411533d613123618c0d127fae532595Jeff Garzik	u32			amps;
383bca1c4eb9411533d613123618c0d127fae532595Jeff Garzik	u32			pre;
384bca1c4eb9411533d613123618c0d127fae532595Jeff Garzik};
385bca1c4eb9411533d613123618c0d127fae532595Jeff Garzik
38647c2b677daeed9c79ecb7167c211ff36876ea611Jeff Garzikstruct mv_host_priv;
38747c2b677daeed9c79ecb7167c211ff36876ea611Jeff Garzikstruct mv_hw_ops {
3882a47ce06d534692f9bd2bf4e90a20fc9b1054c39Jeff Garzik	void (*phy_errata)(struct mv_host_priv *hpriv, void __iomem *mmio,
3892a47ce06d534692f9bd2bf4e90a20fc9b1054c39Jeff Garzik			   unsigned int port);
39047c2b677daeed9c79ecb7167c211ff36876ea611Jeff Garzik	void (*enable_leds)(struct mv_host_priv *hpriv, void __iomem *mmio);
39147c2b677daeed9c79ecb7167c211ff36876ea611Jeff Garzik	void (*read_preamp)(struct mv_host_priv *hpriv, int idx,
39247c2b677daeed9c79ecb7167c211ff36876ea611Jeff Garzik			   void __iomem *mmio);
393c9d39130123238ac18478a42e25cb7996eacfcc0Jeff Garzik	int (*reset_hc)(struct mv_host_priv *hpriv, void __iomem *mmio,
394c9d39130123238ac18478a42e25cb7996eacfcc0Jeff Garzik			unsigned int n_hc);
395522479fb98c6667f081e75f87e298e413c0b1db8Jeff Garzik	void (*reset_flash)(struct mv_host_priv *hpriv, void __iomem *mmio);
396522479fb98c6667f081e75f87e298e413c0b1db8Jeff Garzik	void (*reset_bus)(struct pci_dev *pdev, void __iomem *mmio);
39747c2b677daeed9c79ecb7167c211ff36876ea611Jeff Garzik};
39847c2b677daeed9c79ecb7167c211ff36876ea611Jeff Garzik
39931961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russstruct mv_host_priv {
40031961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ	u32			hp_flags;
401bca1c4eb9411533d613123618c0d127fae532595Jeff Garzik	struct mv_port_signal	signal[8];
40247c2b677daeed9c79ecb7167c211ff36876ea611Jeff Garzik	const struct mv_hw_ops	*ops;
40320f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ};
40420f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ
40520f733e7d75a16bffc34842b7682c9247dd5f954Brett Russstatic void mv_irq_clear(struct ata_port *ap);
40620f733e7d75a16bffc34842b7682c9247dd5f954Brett Russstatic u32 mv_scr_read(struct ata_port *ap, unsigned int sc_reg_in);
40720f733e7d75a16bffc34842b7682c9247dd5f954Brett Russstatic void mv_scr_write(struct ata_port *ap, unsigned int sc_reg_in, u32 val);
408c9d39130123238ac18478a42e25cb7996eacfcc0Jeff Garzikstatic u32 mv5_scr_read(struct ata_port *ap, unsigned int sc_reg_in);
409c9d39130123238ac18478a42e25cb7996eacfcc0Jeff Garzikstatic void mv5_scr_write(struct ata_port *ap, unsigned int sc_reg_in, u32 val);
41031961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russstatic int mv_port_start(struct ata_port *ap);
41131961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russstatic void mv_port_stop(struct ata_port *ap);
41231961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russstatic void mv_qc_prep(struct ata_queued_cmd *qc);
413e4e7b89280d1d666e2c09e5ad36cf071796c4c7eJeff Garzikstatic void mv_qc_prep_iie(struct ata_queued_cmd *qc);
4149a3d9eb0177eb10500d49cd283b35576082a522dTejun Heostatic unsigned int mv_qc_issue(struct ata_queued_cmd *qc);
415bdd4dddee325a7dce3e84cf48201a06aa8508aa4Jeff Garzikstatic void mv_error_handler(struct ata_port *ap);
416bdd4dddee325a7dce3e84cf48201a06aa8508aa4Jeff Garzikstatic void mv_post_int_cmd(struct ata_queued_cmd *qc);
417bdd4dddee325a7dce3e84cf48201a06aa8508aa4Jeff Garzikstatic void mv_eh_freeze(struct ata_port *ap);
418bdd4dddee325a7dce3e84cf48201a06aa8508aa4Jeff Garzikstatic void mv_eh_thaw(struct ata_port *ap);
41920f733e7d75a16bffc34842b7682c9247dd5f954Brett Russstatic int mv_init_one(struct pci_dev *pdev, const struct pci_device_id *ent);
42020f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ
4212a47ce06d534692f9bd2bf4e90a20fc9b1054c39Jeff Garzikstatic void mv5_phy_errata(struct mv_host_priv *hpriv, void __iomem *mmio,
4222a47ce06d534692f9bd2bf4e90a20fc9b1054c39Jeff Garzik			   unsigned int port);
42347c2b677daeed9c79ecb7167c211ff36876ea611Jeff Garzikstatic void mv5_enable_leds(struct mv_host_priv *hpriv, void __iomem *mmio);
42447c2b677daeed9c79ecb7167c211ff36876ea611Jeff Garzikstatic void mv5_read_preamp(struct mv_host_priv *hpriv, int idx,
42547c2b677daeed9c79ecb7167c211ff36876ea611Jeff Garzik			   void __iomem *mmio);
426c9d39130123238ac18478a42e25cb7996eacfcc0Jeff Garzikstatic int mv5_reset_hc(struct mv_host_priv *hpriv, void __iomem *mmio,
427c9d39130123238ac18478a42e25cb7996eacfcc0Jeff Garzik			unsigned int n_hc);
428522479fb98c6667f081e75f87e298e413c0b1db8Jeff Garzikstatic void mv5_reset_flash(struct mv_host_priv *hpriv, void __iomem *mmio);
429522479fb98c6667f081e75f87e298e413c0b1db8Jeff Garzikstatic void mv5_reset_bus(struct pci_dev *pdev, void __iomem *mmio);
43047c2b677daeed9c79ecb7167c211ff36876ea611Jeff Garzik
4312a47ce06d534692f9bd2bf4e90a20fc9b1054c39Jeff Garzikstatic void mv6_phy_errata(struct mv_host_priv *hpriv, void __iomem *mmio,
4322a47ce06d534692f9bd2bf4e90a20fc9b1054c39Jeff Garzik			   unsigned int port);
43347c2b677daeed9c79ecb7167c211ff36876ea611Jeff Garzikstatic void mv6_enable_leds(struct mv_host_priv *hpriv, void __iomem *mmio);
43447c2b677daeed9c79ecb7167c211ff36876ea611Jeff Garzikstatic void mv6_read_preamp(struct mv_host_priv *hpriv, int idx,
43547c2b677daeed9c79ecb7167c211ff36876ea611Jeff Garzik			   void __iomem *mmio);
436c9d39130123238ac18478a42e25cb7996eacfcc0Jeff Garzikstatic int mv6_reset_hc(struct mv_host_priv *hpriv, void __iomem *mmio,
437c9d39130123238ac18478a42e25cb7996eacfcc0Jeff Garzik			unsigned int n_hc);
438522479fb98c6667f081e75f87e298e413c0b1db8Jeff Garzikstatic void mv6_reset_flash(struct mv_host_priv *hpriv, void __iomem *mmio);
439522479fb98c6667f081e75f87e298e413c0b1db8Jeff Garzikstatic void mv_reset_pci_bus(struct pci_dev *pdev, void __iomem *mmio);
440c9d39130123238ac18478a42e25cb7996eacfcc0Jeff Garzikstatic void mv_channel_reset(struct mv_host_priv *hpriv, void __iomem *mmio,
441c9d39130123238ac18478a42e25cb7996eacfcc0Jeff Garzik			     unsigned int port_no);
44247c2b677daeed9c79ecb7167c211ff36876ea611Jeff Garzik
443c5d3e45a2200a0905dc45b72714726b7aac3aaf1Jeff Garzikstatic struct scsi_host_template mv5_sht = {
444c5d3e45a2200a0905dc45b72714726b7aac3aaf1Jeff Garzik	.module			= THIS_MODULE,
445c5d3e45a2200a0905dc45b72714726b7aac3aaf1Jeff Garzik	.name			= DRV_NAME,
446c5d3e45a2200a0905dc45b72714726b7aac3aaf1Jeff Garzik	.ioctl			= ata_scsi_ioctl,
447c5d3e45a2200a0905dc45b72714726b7aac3aaf1Jeff Garzik	.queuecommand		= ata_scsi_queuecmd,
448c5d3e45a2200a0905dc45b72714726b7aac3aaf1Jeff Garzik	.can_queue		= ATA_DEF_QUEUE,
449c5d3e45a2200a0905dc45b72714726b7aac3aaf1Jeff Garzik	.this_id		= ATA_SHT_THIS_ID,
450c5d3e45a2200a0905dc45b72714726b7aac3aaf1Jeff Garzik	.sg_tablesize		= MV_MAX_SG_CT,
451c5d3e45a2200a0905dc45b72714726b7aac3aaf1Jeff Garzik	.cmd_per_lun		= ATA_SHT_CMD_PER_LUN,
452c5d3e45a2200a0905dc45b72714726b7aac3aaf1Jeff Garzik	.emulated		= ATA_SHT_EMULATED,
453c5d3e45a2200a0905dc45b72714726b7aac3aaf1Jeff Garzik	.use_clustering		= 1,
454c5d3e45a2200a0905dc45b72714726b7aac3aaf1Jeff Garzik	.proc_name		= DRV_NAME,
455c5d3e45a2200a0905dc45b72714726b7aac3aaf1Jeff Garzik	.dma_boundary		= MV_DMA_BOUNDARY,
456c5d3e45a2200a0905dc45b72714726b7aac3aaf1Jeff Garzik	.slave_configure	= ata_scsi_slave_config,
457c5d3e45a2200a0905dc45b72714726b7aac3aaf1Jeff Garzik	.slave_destroy		= ata_scsi_slave_destroy,
458c5d3e45a2200a0905dc45b72714726b7aac3aaf1Jeff Garzik	.bios_param		= ata_std_bios_param,
459c5d3e45a2200a0905dc45b72714726b7aac3aaf1Jeff Garzik};
460c5d3e45a2200a0905dc45b72714726b7aac3aaf1Jeff Garzik
461c5d3e45a2200a0905dc45b72714726b7aac3aaf1Jeff Garzikstatic struct scsi_host_template mv6_sht = {
46220f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ	.module			= THIS_MODULE,
46320f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ	.name			= DRV_NAME,
46420f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ	.ioctl			= ata_scsi_ioctl,
46520f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ	.queuecommand		= ata_scsi_queuecmd,
466c5d3e45a2200a0905dc45b72714726b7aac3aaf1Jeff Garzik	.can_queue		= ATA_DEF_QUEUE,
46720f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ	.this_id		= ATA_SHT_THIS_ID,
468d88184fb2348a50f7c34f5d49a901c875b2e0114Jeff Garzik	.sg_tablesize		= MV_MAX_SG_CT,
46920f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ	.cmd_per_lun		= ATA_SHT_CMD_PER_LUN,
47020f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ	.emulated		= ATA_SHT_EMULATED,
471d88184fb2348a50f7c34f5d49a901c875b2e0114Jeff Garzik	.use_clustering		= 1,
47220f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ	.proc_name		= DRV_NAME,
47320f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ	.dma_boundary		= MV_DMA_BOUNDARY,
47420f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ	.slave_configure	= ata_scsi_slave_config,
475ccf68c3405fca11386004674377d951b9b18e756Tejun Heo	.slave_destroy		= ata_scsi_slave_destroy,
47620f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ	.bios_param		= ata_std_bios_param,
47720f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ};
47820f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ
479c9d39130123238ac18478a42e25cb7996eacfcc0Jeff Garzikstatic const struct ata_port_operations mv5_ops = {
480c9d39130123238ac18478a42e25cb7996eacfcc0Jeff Garzik	.port_disable		= ata_port_disable,
481c9d39130123238ac18478a42e25cb7996eacfcc0Jeff Garzik
482c9d39130123238ac18478a42e25cb7996eacfcc0Jeff Garzik	.tf_load		= ata_tf_load,
483c9d39130123238ac18478a42e25cb7996eacfcc0Jeff Garzik	.tf_read		= ata_tf_read,
484c9d39130123238ac18478a42e25cb7996eacfcc0Jeff Garzik	.check_status		= ata_check_status,
485c9d39130123238ac18478a42e25cb7996eacfcc0Jeff Garzik	.exec_command		= ata_exec_command,
486c9d39130123238ac18478a42e25cb7996eacfcc0Jeff Garzik	.dev_select		= ata_std_dev_select,
487c9d39130123238ac18478a42e25cb7996eacfcc0Jeff Garzik
488cffacd85bcf6fc652292001873119333555fe260Jeff Garzik	.cable_detect		= ata_cable_sata,
489c9d39130123238ac18478a42e25cb7996eacfcc0Jeff Garzik
490c9d39130123238ac18478a42e25cb7996eacfcc0Jeff Garzik	.qc_prep		= mv_qc_prep,
491c9d39130123238ac18478a42e25cb7996eacfcc0Jeff Garzik	.qc_issue		= mv_qc_issue,
4920d5ff566779f894ca9937231a181eb31e4adff0eTejun Heo	.data_xfer		= ata_data_xfer,
493c9d39130123238ac18478a42e25cb7996eacfcc0Jeff Garzik
494c9d39130123238ac18478a42e25cb7996eacfcc0Jeff Garzik	.irq_clear		= mv_irq_clear,
495246ce3b675843e0369643cceb4faeb6cf6d19a30Akira Iguchi	.irq_on			= ata_irq_on,
496246ce3b675843e0369643cceb4faeb6cf6d19a30Akira Iguchi	.irq_ack		= ata_irq_ack,
497c9d39130123238ac18478a42e25cb7996eacfcc0Jeff Garzik
498bdd4dddee325a7dce3e84cf48201a06aa8508aa4Jeff Garzik	.error_handler		= mv_error_handler,
499bdd4dddee325a7dce3e84cf48201a06aa8508aa4Jeff Garzik	.post_internal_cmd	= mv_post_int_cmd,
500bdd4dddee325a7dce3e84cf48201a06aa8508aa4Jeff Garzik	.freeze			= mv_eh_freeze,
501bdd4dddee325a7dce3e84cf48201a06aa8508aa4Jeff Garzik	.thaw			= mv_eh_thaw,
502bdd4dddee325a7dce3e84cf48201a06aa8508aa4Jeff Garzik
503c9d39130123238ac18478a42e25cb7996eacfcc0Jeff Garzik	.scr_read		= mv5_scr_read,
504c9d39130123238ac18478a42e25cb7996eacfcc0Jeff Garzik	.scr_write		= mv5_scr_write,
505c9d39130123238ac18478a42e25cb7996eacfcc0Jeff Garzik
506c9d39130123238ac18478a42e25cb7996eacfcc0Jeff Garzik	.port_start		= mv_port_start,
507c9d39130123238ac18478a42e25cb7996eacfcc0Jeff Garzik	.port_stop		= mv_port_stop,
508c9d39130123238ac18478a42e25cb7996eacfcc0Jeff Garzik};
509c9d39130123238ac18478a42e25cb7996eacfcc0Jeff Garzik
510c9d39130123238ac18478a42e25cb7996eacfcc0Jeff Garzikstatic const struct ata_port_operations mv6_ops = {
51120f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ	.port_disable		= ata_port_disable,
51220f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ
51320f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ	.tf_load		= ata_tf_load,
51420f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ	.tf_read		= ata_tf_read,
51520f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ	.check_status		= ata_check_status,
51620f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ	.exec_command		= ata_exec_command,
51720f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ	.dev_select		= ata_std_dev_select,
51820f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ
519cffacd85bcf6fc652292001873119333555fe260Jeff Garzik	.cable_detect		= ata_cable_sata,
52020f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ
52131961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ	.qc_prep		= mv_qc_prep,
52231961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ	.qc_issue		= mv_qc_issue,
5230d5ff566779f894ca9937231a181eb31e4adff0eTejun Heo	.data_xfer		= ata_data_xfer,
52420f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ
52520f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ	.irq_clear		= mv_irq_clear,
526246ce3b675843e0369643cceb4faeb6cf6d19a30Akira Iguchi	.irq_on			= ata_irq_on,
527246ce3b675843e0369643cceb4faeb6cf6d19a30Akira Iguchi	.irq_ack		= ata_irq_ack,
52820f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ
529bdd4dddee325a7dce3e84cf48201a06aa8508aa4Jeff Garzik	.error_handler		= mv_error_handler,
530bdd4dddee325a7dce3e84cf48201a06aa8508aa4Jeff Garzik	.post_internal_cmd	= mv_post_int_cmd,
531bdd4dddee325a7dce3e84cf48201a06aa8508aa4Jeff Garzik	.freeze			= mv_eh_freeze,
532bdd4dddee325a7dce3e84cf48201a06aa8508aa4Jeff Garzik	.thaw			= mv_eh_thaw,
533bdd4dddee325a7dce3e84cf48201a06aa8508aa4Jeff Garzik
53420f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ	.scr_read		= mv_scr_read,
53520f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ	.scr_write		= mv_scr_write,
53620f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ
53731961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ	.port_start		= mv_port_start,
53831961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ	.port_stop		= mv_port_stop,
53920f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ};
54020f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ
541e4e7b89280d1d666e2c09e5ad36cf071796c4c7eJeff Garzikstatic const struct ata_port_operations mv_iie_ops = {
542e4e7b89280d1d666e2c09e5ad36cf071796c4c7eJeff Garzik	.port_disable		= ata_port_disable,
543e4e7b89280d1d666e2c09e5ad36cf071796c4c7eJeff Garzik
544e4e7b89280d1d666e2c09e5ad36cf071796c4c7eJeff Garzik	.tf_load		= ata_tf_load,
545e4e7b89280d1d666e2c09e5ad36cf071796c4c7eJeff Garzik	.tf_read		= ata_tf_read,
546e4e7b89280d1d666e2c09e5ad36cf071796c4c7eJeff Garzik	.check_status		= ata_check_status,
547e4e7b89280d1d666e2c09e5ad36cf071796c4c7eJeff Garzik	.exec_command		= ata_exec_command,
548e4e7b89280d1d666e2c09e5ad36cf071796c4c7eJeff Garzik	.dev_select		= ata_std_dev_select,
549e4e7b89280d1d666e2c09e5ad36cf071796c4c7eJeff Garzik
550cffacd85bcf6fc652292001873119333555fe260Jeff Garzik	.cable_detect		= ata_cable_sata,
551e4e7b89280d1d666e2c09e5ad36cf071796c4c7eJeff Garzik
552e4e7b89280d1d666e2c09e5ad36cf071796c4c7eJeff Garzik	.qc_prep		= mv_qc_prep_iie,
553e4e7b89280d1d666e2c09e5ad36cf071796c4c7eJeff Garzik	.qc_issue		= mv_qc_issue,
5540d5ff566779f894ca9937231a181eb31e4adff0eTejun Heo	.data_xfer		= ata_data_xfer,
555e4e7b89280d1d666e2c09e5ad36cf071796c4c7eJeff Garzik
556e4e7b89280d1d666e2c09e5ad36cf071796c4c7eJeff Garzik	.irq_clear		= mv_irq_clear,
557246ce3b675843e0369643cceb4faeb6cf6d19a30Akira Iguchi	.irq_on			= ata_irq_on,
558246ce3b675843e0369643cceb4faeb6cf6d19a30Akira Iguchi	.irq_ack		= ata_irq_ack,
559e4e7b89280d1d666e2c09e5ad36cf071796c4c7eJeff Garzik
560bdd4dddee325a7dce3e84cf48201a06aa8508aa4Jeff Garzik	.error_handler		= mv_error_handler,
561bdd4dddee325a7dce3e84cf48201a06aa8508aa4Jeff Garzik	.post_internal_cmd	= mv_post_int_cmd,
562bdd4dddee325a7dce3e84cf48201a06aa8508aa4Jeff Garzik	.freeze			= mv_eh_freeze,
563bdd4dddee325a7dce3e84cf48201a06aa8508aa4Jeff Garzik	.thaw			= mv_eh_thaw,
564bdd4dddee325a7dce3e84cf48201a06aa8508aa4Jeff Garzik
565e4e7b89280d1d666e2c09e5ad36cf071796c4c7eJeff Garzik	.scr_read		= mv_scr_read,
566e4e7b89280d1d666e2c09e5ad36cf071796c4c7eJeff Garzik	.scr_write		= mv_scr_write,
567e4e7b89280d1d666e2c09e5ad36cf071796c4c7eJeff Garzik
568e4e7b89280d1d666e2c09e5ad36cf071796c4c7eJeff Garzik	.port_start		= mv_port_start,
569e4e7b89280d1d666e2c09e5ad36cf071796c4c7eJeff Garzik	.port_stop		= mv_port_stop,
570e4e7b89280d1d666e2c09e5ad36cf071796c4c7eJeff Garzik};
571e4e7b89280d1d666e2c09e5ad36cf071796c4c7eJeff Garzik
57298ac62defe529d04a192688f40d801a2d8fbcf98Arjan van de Venstatic const struct ata_port_info mv_port_info[] = {
57320f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ	{  /* chip_504x */
574cca3974e48607c3775dc73b544a5700b2e37c21aJeff Garzik		.flags		= MV_COMMON_FLAGS,
57531961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ		.pio_mask	= 0x1f,	/* pio0-4 */
576bf6263a853c9c143bf03f0a6fdcc68ab714fb5f5Jeff Garzik		.udma_mask	= ATA_UDMA6,
577c9d39130123238ac18478a42e25cb7996eacfcc0Jeff Garzik		.port_ops	= &mv5_ops,
57820f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ	},
57920f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ	{  /* chip_508x */
580c5d3e45a2200a0905dc45b72714726b7aac3aaf1Jeff Garzik		.flags		= MV_COMMON_FLAGS | MV_FLAG_DUAL_HC,
58131961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ		.pio_mask	= 0x1f,	/* pio0-4 */
582bf6263a853c9c143bf03f0a6fdcc68ab714fb5f5Jeff Garzik		.udma_mask	= ATA_UDMA6,
583c9d39130123238ac18478a42e25cb7996eacfcc0Jeff Garzik		.port_ops	= &mv5_ops,
58420f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ	},
58547c2b677daeed9c79ecb7167c211ff36876ea611Jeff Garzik	{  /* chip_5080 */
586c5d3e45a2200a0905dc45b72714726b7aac3aaf1Jeff Garzik		.flags		= MV_COMMON_FLAGS | MV_FLAG_DUAL_HC,
58747c2b677daeed9c79ecb7167c211ff36876ea611Jeff Garzik		.pio_mask	= 0x1f,	/* pio0-4 */
588bf6263a853c9c143bf03f0a6fdcc68ab714fb5f5Jeff Garzik		.udma_mask	= ATA_UDMA6,
589c9d39130123238ac18478a42e25cb7996eacfcc0Jeff Garzik		.port_ops	= &mv5_ops,
59047c2b677daeed9c79ecb7167c211ff36876ea611Jeff Garzik	},
59120f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ	{  /* chip_604x */
592c5d3e45a2200a0905dc45b72714726b7aac3aaf1Jeff Garzik		.flags		= MV_COMMON_FLAGS | MV_6XXX_FLAGS,
59331961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ		.pio_mask	= 0x1f,	/* pio0-4 */
594bf6263a853c9c143bf03f0a6fdcc68ab714fb5f5Jeff Garzik		.udma_mask	= ATA_UDMA6,
595c9d39130123238ac18478a42e25cb7996eacfcc0Jeff Garzik		.port_ops	= &mv6_ops,
59620f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ	},
59720f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ	{  /* chip_608x */
598c5d3e45a2200a0905dc45b72714726b7aac3aaf1Jeff Garzik		.flags		= MV_COMMON_FLAGS | MV_6XXX_FLAGS |
599c5d3e45a2200a0905dc45b72714726b7aac3aaf1Jeff Garzik				  MV_FLAG_DUAL_HC,
60031961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ		.pio_mask	= 0x1f,	/* pio0-4 */
601bf6263a853c9c143bf03f0a6fdcc68ab714fb5f5Jeff Garzik		.udma_mask	= ATA_UDMA6,
602c9d39130123238ac18478a42e25cb7996eacfcc0Jeff Garzik		.port_ops	= &mv6_ops,
60320f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ	},
604e4e7b89280d1d666e2c09e5ad36cf071796c4c7eJeff Garzik	{  /* chip_6042 */
605c5d3e45a2200a0905dc45b72714726b7aac3aaf1Jeff Garzik		.flags		= MV_COMMON_FLAGS | MV_6XXX_FLAGS,
606e4e7b89280d1d666e2c09e5ad36cf071796c4c7eJeff Garzik		.pio_mask	= 0x1f,	/* pio0-4 */
607bf6263a853c9c143bf03f0a6fdcc68ab714fb5f5Jeff Garzik		.udma_mask	= ATA_UDMA6,
608e4e7b89280d1d666e2c09e5ad36cf071796c4c7eJeff Garzik		.port_ops	= &mv_iie_ops,
609e4e7b89280d1d666e2c09e5ad36cf071796c4c7eJeff Garzik	},
610e4e7b89280d1d666e2c09e5ad36cf071796c4c7eJeff Garzik	{  /* chip_7042 */
611c5d3e45a2200a0905dc45b72714726b7aac3aaf1Jeff Garzik		.flags		= MV_COMMON_FLAGS | MV_6XXX_FLAGS,
612e4e7b89280d1d666e2c09e5ad36cf071796c4c7eJeff Garzik		.pio_mask	= 0x1f,	/* pio0-4 */
613bf6263a853c9c143bf03f0a6fdcc68ab714fb5f5Jeff Garzik		.udma_mask	= ATA_UDMA6,
614e4e7b89280d1d666e2c09e5ad36cf071796c4c7eJeff Garzik		.port_ops	= &mv_iie_ops,
615e4e7b89280d1d666e2c09e5ad36cf071796c4c7eJeff Garzik	},
61620f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ};
61720f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ
6183b7d697dfb7d03edb87e50b743a7ecff029618e9Jeff Garzikstatic const struct pci_device_id mv_pci_tbl[] = {
6192d2744fc8be620a2dc469cf48349e3e704119f1bJeff Garzik	{ PCI_VDEVICE(MARVELL, 0x5040), chip_504x },
6202d2744fc8be620a2dc469cf48349e3e704119f1bJeff Garzik	{ PCI_VDEVICE(MARVELL, 0x5041), chip_504x },
6212d2744fc8be620a2dc469cf48349e3e704119f1bJeff Garzik	{ PCI_VDEVICE(MARVELL, 0x5080), chip_5080 },
6222d2744fc8be620a2dc469cf48349e3e704119f1bJeff Garzik	{ PCI_VDEVICE(MARVELL, 0x5081), chip_508x },
6232d2744fc8be620a2dc469cf48349e3e704119f1bJeff Garzik
6242d2744fc8be620a2dc469cf48349e3e704119f1bJeff Garzik	{ PCI_VDEVICE(MARVELL, 0x6040), chip_604x },
6252d2744fc8be620a2dc469cf48349e3e704119f1bJeff Garzik	{ PCI_VDEVICE(MARVELL, 0x6041), chip_604x },
6262d2744fc8be620a2dc469cf48349e3e704119f1bJeff Garzik	{ PCI_VDEVICE(MARVELL, 0x6042), chip_6042 },
6272d2744fc8be620a2dc469cf48349e3e704119f1bJeff Garzik	{ PCI_VDEVICE(MARVELL, 0x6080), chip_608x },
6282d2744fc8be620a2dc469cf48349e3e704119f1bJeff Garzik	{ PCI_VDEVICE(MARVELL, 0x6081), chip_608x },
6292d2744fc8be620a2dc469cf48349e3e704119f1bJeff Garzik
6302d2744fc8be620a2dc469cf48349e3e704119f1bJeff Garzik	{ PCI_VDEVICE(ADAPTEC2, 0x0241), chip_604x },
6312d2744fc8be620a2dc469cf48349e3e704119f1bJeff Garzik
632d9f9c6bc91c14f53ffa782ffcd42259ecae1d38cFlorian Attenberger	/* Adaptec 1430SA */
633d9f9c6bc91c14f53ffa782ffcd42259ecae1d38cFlorian Attenberger	{ PCI_VDEVICE(ADAPTEC2, 0x0243), chip_7042 },
634d9f9c6bc91c14f53ffa782ffcd42259ecae1d38cFlorian Attenberger
635e93f09dc2d49d8e98818a93ad17f3ede91533738Olof Johansson	{ PCI_VDEVICE(TTI, 0x2310), chip_7042 },
636e93f09dc2d49d8e98818a93ad17f3ede91533738Olof Johansson
6376a3d586d8e8a50e4cfd7f8c36d82a53c5614e05bMorrison, Tom	/* add Marvell 7042 support */
6386a3d586d8e8a50e4cfd7f8c36d82a53c5614e05bMorrison, Tom	{ PCI_VDEVICE(MARVELL, 0x7042), chip_7042 },
6396a3d586d8e8a50e4cfd7f8c36d82a53c5614e05bMorrison, Tom
6402d2744fc8be620a2dc469cf48349e3e704119f1bJeff Garzik	{ }			/* terminate list */
64120f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ};
64220f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ
64320f733e7d75a16bffc34842b7682c9247dd5f954Brett Russstatic struct pci_driver mv_pci_driver = {
64420f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ	.name			= DRV_NAME,
64520f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ	.id_table		= mv_pci_tbl,
64620f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ	.probe			= mv_init_one,
64720f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ	.remove			= ata_pci_remove_one,
64820f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ};
64920f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ
65047c2b677daeed9c79ecb7167c211ff36876ea611Jeff Garzikstatic const struct mv_hw_ops mv5xxx_ops = {
65147c2b677daeed9c79ecb7167c211ff36876ea611Jeff Garzik	.phy_errata		= mv5_phy_errata,
65247c2b677daeed9c79ecb7167c211ff36876ea611Jeff Garzik	.enable_leds		= mv5_enable_leds,
65347c2b677daeed9c79ecb7167c211ff36876ea611Jeff Garzik	.read_preamp		= mv5_read_preamp,
65447c2b677daeed9c79ecb7167c211ff36876ea611Jeff Garzik	.reset_hc		= mv5_reset_hc,
655522479fb98c6667f081e75f87e298e413c0b1db8Jeff Garzik	.reset_flash		= mv5_reset_flash,
656522479fb98c6667f081e75f87e298e413c0b1db8Jeff Garzik	.reset_bus		= mv5_reset_bus,
65747c2b677daeed9c79ecb7167c211ff36876ea611Jeff Garzik};
65847c2b677daeed9c79ecb7167c211ff36876ea611Jeff Garzik
65947c2b677daeed9c79ecb7167c211ff36876ea611Jeff Garzikstatic const struct mv_hw_ops mv6xxx_ops = {
66047c2b677daeed9c79ecb7167c211ff36876ea611Jeff Garzik	.phy_errata		= mv6_phy_errata,
66147c2b677daeed9c79ecb7167c211ff36876ea611Jeff Garzik	.enable_leds		= mv6_enable_leds,
66247c2b677daeed9c79ecb7167c211ff36876ea611Jeff Garzik	.read_preamp		= mv6_read_preamp,
66347c2b677daeed9c79ecb7167c211ff36876ea611Jeff Garzik	.reset_hc		= mv6_reset_hc,
664522479fb98c6667f081e75f87e298e413c0b1db8Jeff Garzik	.reset_flash		= mv6_reset_flash,
665522479fb98c6667f081e75f87e298e413c0b1db8Jeff Garzik	.reset_bus		= mv_reset_pci_bus,
66647c2b677daeed9c79ecb7167c211ff36876ea611Jeff Garzik};
66747c2b677daeed9c79ecb7167c211ff36876ea611Jeff Garzik
66820f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ/*
669ddef9bb367b19383df627e388cb4c01c86ddba6cJeff Garzik * module options
670ddef9bb367b19383df627e388cb4c01c86ddba6cJeff Garzik */
671ddef9bb367b19383df627e388cb4c01c86ddba6cJeff Garzikstatic int msi;	      /* Use PCI msi; either zero (off, default) or non-zero */
672ddef9bb367b19383df627e388cb4c01c86ddba6cJeff Garzik
673ddef9bb367b19383df627e388cb4c01c86ddba6cJeff Garzik
674d88184fb2348a50f7c34f5d49a901c875b2e0114Jeff Garzik/* move to PCI layer or libata core? */
675d88184fb2348a50f7c34f5d49a901c875b2e0114Jeff Garzikstatic int pci_go_64(struct pci_dev *pdev)
676d88184fb2348a50f7c34f5d49a901c875b2e0114Jeff Garzik{
677d88184fb2348a50f7c34f5d49a901c875b2e0114Jeff Garzik	int rc;
678d88184fb2348a50f7c34f5d49a901c875b2e0114Jeff Garzik
679d88184fb2348a50f7c34f5d49a901c875b2e0114Jeff Garzik	if (!pci_set_dma_mask(pdev, DMA_64BIT_MASK)) {
680d88184fb2348a50f7c34f5d49a901c875b2e0114Jeff Garzik		rc = pci_set_consistent_dma_mask(pdev, DMA_64BIT_MASK);
681d88184fb2348a50f7c34f5d49a901c875b2e0114Jeff Garzik		if (rc) {
682d88184fb2348a50f7c34f5d49a901c875b2e0114Jeff Garzik			rc = pci_set_consistent_dma_mask(pdev, DMA_32BIT_MASK);
683d88184fb2348a50f7c34f5d49a901c875b2e0114Jeff Garzik			if (rc) {
684d88184fb2348a50f7c34f5d49a901c875b2e0114Jeff Garzik				dev_printk(KERN_ERR, &pdev->dev,
685d88184fb2348a50f7c34f5d49a901c875b2e0114Jeff Garzik					   "64-bit DMA enable failed\n");
686d88184fb2348a50f7c34f5d49a901c875b2e0114Jeff Garzik				return rc;
687d88184fb2348a50f7c34f5d49a901c875b2e0114Jeff Garzik			}
688d88184fb2348a50f7c34f5d49a901c875b2e0114Jeff Garzik		}
689d88184fb2348a50f7c34f5d49a901c875b2e0114Jeff Garzik	} else {
690d88184fb2348a50f7c34f5d49a901c875b2e0114Jeff Garzik		rc = pci_set_dma_mask(pdev, DMA_32BIT_MASK);
691d88184fb2348a50f7c34f5d49a901c875b2e0114Jeff Garzik		if (rc) {
692d88184fb2348a50f7c34f5d49a901c875b2e0114Jeff Garzik			dev_printk(KERN_ERR, &pdev->dev,
693d88184fb2348a50f7c34f5d49a901c875b2e0114Jeff Garzik				   "32-bit DMA enable failed\n");
694d88184fb2348a50f7c34f5d49a901c875b2e0114Jeff Garzik			return rc;
695d88184fb2348a50f7c34f5d49a901c875b2e0114Jeff Garzik		}
696d88184fb2348a50f7c34f5d49a901c875b2e0114Jeff Garzik		rc = pci_set_consistent_dma_mask(pdev, DMA_32BIT_MASK);
697d88184fb2348a50f7c34f5d49a901c875b2e0114Jeff Garzik		if (rc) {
698d88184fb2348a50f7c34f5d49a901c875b2e0114Jeff Garzik			dev_printk(KERN_ERR, &pdev->dev,
699d88184fb2348a50f7c34f5d49a901c875b2e0114Jeff Garzik				   "32-bit consistent DMA enable failed\n");
700d88184fb2348a50f7c34f5d49a901c875b2e0114Jeff Garzik			return rc;
701d88184fb2348a50f7c34f5d49a901c875b2e0114Jeff Garzik		}
702d88184fb2348a50f7c34f5d49a901c875b2e0114Jeff Garzik	}
703d88184fb2348a50f7c34f5d49a901c875b2e0114Jeff Garzik
704d88184fb2348a50f7c34f5d49a901c875b2e0114Jeff Garzik	return rc;
705d88184fb2348a50f7c34f5d49a901c875b2e0114Jeff Garzik}
706d88184fb2348a50f7c34f5d49a901c875b2e0114Jeff Garzik
707ddef9bb367b19383df627e388cb4c01c86ddba6cJeff Garzik/*
70820f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ * Functions
70920f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ */
71020f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ
71120f733e7d75a16bffc34842b7682c9247dd5f954Brett Russstatic inline void writelfl(unsigned long data, void __iomem *addr)
71220f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ{
71320f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ	writel(data, addr);
71420f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ	(void) readl(addr);	/* flush to avoid PCI posted write */
71520f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ}
71620f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ
71720f733e7d75a16bffc34842b7682c9247dd5f954Brett Russstatic inline void __iomem *mv_hc_base(void __iomem *base, unsigned int hc)
71820f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ{
71920f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ	return (base + MV_SATAHC0_REG_BASE + (hc * MV_SATAHC_REG_SZ));
72020f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ}
72120f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ
722c9d39130123238ac18478a42e25cb7996eacfcc0Jeff Garzikstatic inline unsigned int mv_hc_from_port(unsigned int port)
723c9d39130123238ac18478a42e25cb7996eacfcc0Jeff Garzik{
724c9d39130123238ac18478a42e25cb7996eacfcc0Jeff Garzik	return port >> MV_PORT_HC_SHIFT;
725c9d39130123238ac18478a42e25cb7996eacfcc0Jeff Garzik}
726c9d39130123238ac18478a42e25cb7996eacfcc0Jeff Garzik
727c9d39130123238ac18478a42e25cb7996eacfcc0Jeff Garzikstatic inline unsigned int mv_hardport_from_port(unsigned int port)
728c9d39130123238ac18478a42e25cb7996eacfcc0Jeff Garzik{
729c9d39130123238ac18478a42e25cb7996eacfcc0Jeff Garzik	return port & MV_PORT_MASK;
730c9d39130123238ac18478a42e25cb7996eacfcc0Jeff Garzik}
731c9d39130123238ac18478a42e25cb7996eacfcc0Jeff Garzik
732c9d39130123238ac18478a42e25cb7996eacfcc0Jeff Garzikstatic inline void __iomem *mv_hc_base_from_port(void __iomem *base,
733c9d39130123238ac18478a42e25cb7996eacfcc0Jeff Garzik						 unsigned int port)
734c9d39130123238ac18478a42e25cb7996eacfcc0Jeff Garzik{
735c9d39130123238ac18478a42e25cb7996eacfcc0Jeff Garzik	return mv_hc_base(base, mv_hc_from_port(port));
736c9d39130123238ac18478a42e25cb7996eacfcc0Jeff Garzik}
737c9d39130123238ac18478a42e25cb7996eacfcc0Jeff Garzik
73820f733e7d75a16bffc34842b7682c9247dd5f954Brett Russstatic inline void __iomem *mv_port_base(void __iomem *base, unsigned int port)
73920f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ{
740c9d39130123238ac18478a42e25cb7996eacfcc0Jeff Garzik	return  mv_hc_base_from_port(base, port) +
7418b260248d9e0e8b64bb72fd4dee03ad86984c344Jeff Garzik		MV_SATAHC_ARBTR_REG_SZ +
742c9d39130123238ac18478a42e25cb7996eacfcc0Jeff Garzik		(mv_hardport_from_port(port) * MV_PORT_REG_SZ);
74320f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ}
74420f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ
74520f733e7d75a16bffc34842b7682c9247dd5f954Brett Russstatic inline void __iomem *mv_ap_base(struct ata_port *ap)
74620f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ{
7470d5ff566779f894ca9937231a181eb31e4adff0eTejun Heo	return mv_port_base(ap->host->iomap[MV_PRIMARY_BAR], ap->port_no);
74820f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ}
74920f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ
750cca3974e48607c3775dc73b544a5700b2e37c21aJeff Garzikstatic inline int mv_get_hc_count(unsigned long port_flags)
75131961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ{
752cca3974e48607c3775dc73b544a5700b2e37c21aJeff Garzik	return ((port_flags & MV_FLAG_DUAL_HC) ? 2 : 1);
75331961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ}
75431961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ
75531961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russstatic void mv_irq_clear(struct ata_port *ap)
75620f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ{
75720f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ}
75820f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ
759c5d3e45a2200a0905dc45b72714726b7aac3aaf1Jeff Garzikstatic void mv_set_edma_ptrs(void __iomem *port_mmio,
760c5d3e45a2200a0905dc45b72714726b7aac3aaf1Jeff Garzik			     struct mv_host_priv *hpriv,
761c5d3e45a2200a0905dc45b72714726b7aac3aaf1Jeff Garzik			     struct mv_port_priv *pp)
762c5d3e45a2200a0905dc45b72714726b7aac3aaf1Jeff Garzik{
763bdd4dddee325a7dce3e84cf48201a06aa8508aa4Jeff Garzik	u32 index;
764bdd4dddee325a7dce3e84cf48201a06aa8508aa4Jeff Garzik
765c5d3e45a2200a0905dc45b72714726b7aac3aaf1Jeff Garzik	/*
766c5d3e45a2200a0905dc45b72714726b7aac3aaf1Jeff Garzik	 * initialize request queue
767c5d3e45a2200a0905dc45b72714726b7aac3aaf1Jeff Garzik	 */
768bdd4dddee325a7dce3e84cf48201a06aa8508aa4Jeff Garzik	index = (pp->req_idx & MV_MAX_Q_DEPTH_MASK) << EDMA_REQ_Q_PTR_SHIFT;
769bdd4dddee325a7dce3e84cf48201a06aa8508aa4Jeff Garzik
770c5d3e45a2200a0905dc45b72714726b7aac3aaf1Jeff Garzik	WARN_ON(pp->crqb_dma & 0x3ff);
771c5d3e45a2200a0905dc45b72714726b7aac3aaf1Jeff Garzik	writel((pp->crqb_dma >> 16) >> 16, port_mmio + EDMA_REQ_Q_BASE_HI_OFS);
772bdd4dddee325a7dce3e84cf48201a06aa8508aa4Jeff Garzik	writelfl((pp->crqb_dma & EDMA_REQ_Q_BASE_LO_MASK) | index,
773c5d3e45a2200a0905dc45b72714726b7aac3aaf1Jeff Garzik		 port_mmio + EDMA_REQ_Q_IN_PTR_OFS);
774c5d3e45a2200a0905dc45b72714726b7aac3aaf1Jeff Garzik
775c5d3e45a2200a0905dc45b72714726b7aac3aaf1Jeff Garzik	if (hpriv->hp_flags & MV_HP_ERRATA_XX42A0)
776bdd4dddee325a7dce3e84cf48201a06aa8508aa4Jeff Garzik		writelfl((pp->crqb_dma & 0xffffffff) | index,
777c5d3e45a2200a0905dc45b72714726b7aac3aaf1Jeff Garzik			 port_mmio + EDMA_REQ_Q_OUT_PTR_OFS);
778c5d3e45a2200a0905dc45b72714726b7aac3aaf1Jeff Garzik	else
779bdd4dddee325a7dce3e84cf48201a06aa8508aa4Jeff Garzik		writelfl(index, port_mmio + EDMA_REQ_Q_OUT_PTR_OFS);
780c5d3e45a2200a0905dc45b72714726b7aac3aaf1Jeff Garzik
781c5d3e45a2200a0905dc45b72714726b7aac3aaf1Jeff Garzik	/*
782c5d3e45a2200a0905dc45b72714726b7aac3aaf1Jeff Garzik	 * initialize response queue
783c5d3e45a2200a0905dc45b72714726b7aac3aaf1Jeff Garzik	 */
784bdd4dddee325a7dce3e84cf48201a06aa8508aa4Jeff Garzik	index = (pp->resp_idx & MV_MAX_Q_DEPTH_MASK) << EDMA_RSP_Q_PTR_SHIFT;
785bdd4dddee325a7dce3e84cf48201a06aa8508aa4Jeff Garzik
786c5d3e45a2200a0905dc45b72714726b7aac3aaf1Jeff Garzik	WARN_ON(pp->crpb_dma & 0xff);
787c5d3e45a2200a0905dc45b72714726b7aac3aaf1Jeff Garzik	writel((pp->crpb_dma >> 16) >> 16, port_mmio + EDMA_RSP_Q_BASE_HI_OFS);
788c5d3e45a2200a0905dc45b72714726b7aac3aaf1Jeff Garzik
789c5d3e45a2200a0905dc45b72714726b7aac3aaf1Jeff Garzik	if (hpriv->hp_flags & MV_HP_ERRATA_XX42A0)
790bdd4dddee325a7dce3e84cf48201a06aa8508aa4Jeff Garzik		writelfl((pp->crpb_dma & 0xffffffff) | index,
791c5d3e45a2200a0905dc45b72714726b7aac3aaf1Jeff Garzik			 port_mmio + EDMA_RSP_Q_IN_PTR_OFS);
792c5d3e45a2200a0905dc45b72714726b7aac3aaf1Jeff Garzik	else
793bdd4dddee325a7dce3e84cf48201a06aa8508aa4Jeff Garzik		writelfl(index, port_mmio + EDMA_RSP_Q_IN_PTR_OFS);
794c5d3e45a2200a0905dc45b72714726b7aac3aaf1Jeff Garzik
795bdd4dddee325a7dce3e84cf48201a06aa8508aa4Jeff Garzik	writelfl((pp->crpb_dma & EDMA_RSP_Q_BASE_LO_MASK) | index,
796c5d3e45a2200a0905dc45b72714726b7aac3aaf1Jeff Garzik		 port_mmio + EDMA_RSP_Q_OUT_PTR_OFS);
797c5d3e45a2200a0905dc45b72714726b7aac3aaf1Jeff Garzik}
798c5d3e45a2200a0905dc45b72714726b7aac3aaf1Jeff Garzik
79905b308e1df6d9d673daedb517969241f41278b52Brett Russ/**
80005b308e1df6d9d673daedb517969241f41278b52Brett Russ *      mv_start_dma - Enable eDMA engine
80105b308e1df6d9d673daedb517969241f41278b52Brett Russ *      @base: port base address
80205b308e1df6d9d673daedb517969241f41278b52Brett Russ *      @pp: port private data
80305b308e1df6d9d673daedb517969241f41278b52Brett Russ *
804beec7dbc6ff003bbc94de62b3323519c878fb2acTejun Heo *      Verify the local cache of the eDMA state is accurate with a
805beec7dbc6ff003bbc94de62b3323519c878fb2acTejun Heo *      WARN_ON.
80605b308e1df6d9d673daedb517969241f41278b52Brett Russ *
80705b308e1df6d9d673daedb517969241f41278b52Brett Russ *      LOCKING:
80805b308e1df6d9d673daedb517969241f41278b52Brett Russ *      Inherited from caller.
80905b308e1df6d9d673daedb517969241f41278b52Brett Russ */
810c5d3e45a2200a0905dc45b72714726b7aac3aaf1Jeff Garzikstatic void mv_start_dma(void __iomem *base, struct mv_host_priv *hpriv,
811c5d3e45a2200a0905dc45b72714726b7aac3aaf1Jeff Garzik			 struct mv_port_priv *pp)
81220f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ{
813c5d3e45a2200a0905dc45b72714726b7aac3aaf1Jeff Garzik	if (!(pp->pp_flags & MV_PP_FLAG_EDMA_EN)) {
814bdd4dddee325a7dce3e84cf48201a06aa8508aa4Jeff Garzik		/* clear EDMA event indicators, if any */
815bdd4dddee325a7dce3e84cf48201a06aa8508aa4Jeff Garzik		writelfl(0, base + EDMA_ERR_IRQ_CAUSE_OFS);
816bdd4dddee325a7dce3e84cf48201a06aa8508aa4Jeff Garzik
817bdd4dddee325a7dce3e84cf48201a06aa8508aa4Jeff Garzik		mv_set_edma_ptrs(base, hpriv, pp);
818bdd4dddee325a7dce3e84cf48201a06aa8508aa4Jeff Garzik
819afb0edd922c7ed6e73678730921dfcccebec17e8Brett Russ		writelfl(EDMA_EN, base + EDMA_CMD_OFS);
820afb0edd922c7ed6e73678730921dfcccebec17e8Brett Russ		pp->pp_flags |= MV_PP_FLAG_EDMA_EN;
821afb0edd922c7ed6e73678730921dfcccebec17e8Brett Russ	}
822beec7dbc6ff003bbc94de62b3323519c878fb2acTejun Heo	WARN_ON(!(EDMA_EN & readl(base + EDMA_CMD_OFS)));
82320f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ}
82420f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ
82505b308e1df6d9d673daedb517969241f41278b52Brett Russ/**
82605b308e1df6d9d673daedb517969241f41278b52Brett Russ *      mv_stop_dma - Disable eDMA engine
82705b308e1df6d9d673daedb517969241f41278b52Brett Russ *      @ap: ATA channel to manipulate
82805b308e1df6d9d673daedb517969241f41278b52Brett Russ *
829beec7dbc6ff003bbc94de62b3323519c878fb2acTejun Heo *      Verify the local cache of the eDMA state is accurate with a
830beec7dbc6ff003bbc94de62b3323519c878fb2acTejun Heo *      WARN_ON.
83105b308e1df6d9d673daedb517969241f41278b52Brett Russ *
83205b308e1df6d9d673daedb517969241f41278b52Brett Russ *      LOCKING:
83305b308e1df6d9d673daedb517969241f41278b52Brett Russ *      Inherited from caller.
83405b308e1df6d9d673daedb517969241f41278b52Brett Russ */
835c5d3e45a2200a0905dc45b72714726b7aac3aaf1Jeff Garzikstatic int mv_stop_dma(struct ata_port *ap)
83620f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ{
83731961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ	void __iomem *port_mmio = mv_ap_base(ap);
83831961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ	struct mv_port_priv *pp	= ap->private_data;
83931961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ	u32 reg;
840c5d3e45a2200a0905dc45b72714726b7aac3aaf1Jeff Garzik	int i, err = 0;
84131961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ
8424537deb5e90b717a725b3d74b58b4bb1d28443d0Jeff Garzik	if (pp->pp_flags & MV_PP_FLAG_EDMA_EN) {
843afb0edd922c7ed6e73678730921dfcccebec17e8Brett Russ		/* Disable EDMA if active.   The disable bit auto clears.
84431961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ		 */
84531961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ		writelfl(EDMA_DS, port_mmio + EDMA_CMD_OFS);
84631961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ		pp->pp_flags &= ~MV_PP_FLAG_EDMA_EN;
847afb0edd922c7ed6e73678730921dfcccebec17e8Brett Russ	} else {
848beec7dbc6ff003bbc94de62b3323519c878fb2acTejun Heo		WARN_ON(EDMA_EN & readl(port_mmio + EDMA_CMD_OFS));
849afb0edd922c7ed6e73678730921dfcccebec17e8Brett Russ  	}
8508b260248d9e0e8b64bb72fd4dee03ad86984c344Jeff Garzik
85131961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ	/* now properly wait for the eDMA to stop */
85231961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ	for (i = 1000; i > 0; i--) {
85331961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ		reg = readl(port_mmio + EDMA_CMD_OFS);
8544537deb5e90b717a725b3d74b58b4bb1d28443d0Jeff Garzik		if (!(reg & EDMA_EN))
85531961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ			break;
8564537deb5e90b717a725b3d74b58b4bb1d28443d0Jeff Garzik
85731961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ		udelay(100);
85831961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ	}
85931961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ
860c5d3e45a2200a0905dc45b72714726b7aac3aaf1Jeff Garzik	if (reg & EDMA_EN) {
861f15a1dafed22d5037e0feea7528e1eeb28a1a7a3Tejun Heo		ata_port_printk(ap, KERN_ERR, "Unable to stop eDMA\n");
862c5d3e45a2200a0905dc45b72714726b7aac3aaf1Jeff Garzik		err = -EIO;
86331961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ	}
864c5d3e45a2200a0905dc45b72714726b7aac3aaf1Jeff Garzik
865c5d3e45a2200a0905dc45b72714726b7aac3aaf1Jeff Garzik	return err;
86620f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ}
86720f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ
8688a70f8dc08dd40b7f8ac77280eaa99a8c6bc46f4Jeff Garzik#ifdef ATA_DEBUG
86931961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russstatic void mv_dump_mem(void __iomem *start, unsigned bytes)
87020f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ{
87131961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ	int b, w;
87231961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ	for (b = 0; b < bytes; ) {
87331961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ		DPRINTK("%p: ", start + b);
87431961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ		for (w = 0; b < bytes && w < 4; w++) {
87531961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ			printk("%08x ",readl(start + b));
87631961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ			b += sizeof(u32);
87731961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ		}
87831961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ		printk("\n");
87931961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ	}
88031961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ}
8818a70f8dc08dd40b7f8ac77280eaa99a8c6bc46f4Jeff Garzik#endif
8828a70f8dc08dd40b7f8ac77280eaa99a8c6bc46f4Jeff Garzik
88331961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russstatic void mv_dump_pci_cfg(struct pci_dev *pdev, unsigned bytes)
88431961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ{
88531961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ#ifdef ATA_DEBUG
88631961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ	int b, w;
88731961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ	u32 dw;
88831961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ	for (b = 0; b < bytes; ) {
88931961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ		DPRINTK("%02x: ", b);
89031961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ		for (w = 0; b < bytes && w < 4; w++) {
89131961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ			(void) pci_read_config_dword(pdev,b,&dw);
89231961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ			printk("%08x ",dw);
89331961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ			b += sizeof(u32);
89431961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ		}
89531961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ		printk("\n");
89631961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ	}
89731961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ#endif
89831961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ}
89931961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russstatic void mv_dump_all_regs(void __iomem *mmio_base, int port,
90031961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ			     struct pci_dev *pdev)
90131961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ{
90231961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ#ifdef ATA_DEBUG
9038b260248d9e0e8b64bb72fd4dee03ad86984c344Jeff Garzik	void __iomem *hc_base = mv_hc_base(mmio_base,
90431961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ					   port >> MV_PORT_HC_SHIFT);
90531961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ	void __iomem *port_base;
90631961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ	int start_port, num_ports, p, start_hc, num_hcs, hc;
90731961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ
90831961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ	if (0 > port) {
90931961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ		start_hc = start_port = 0;
91031961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ		num_ports = 8;		/* shld be benign for 4 port devs */
91131961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ		num_hcs = 2;
91231961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ	} else {
91331961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ		start_hc = port >> MV_PORT_HC_SHIFT;
91431961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ		start_port = port;
91531961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ		num_ports = num_hcs = 1;
91631961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ	}
9178b260248d9e0e8b64bb72fd4dee03ad86984c344Jeff Garzik	DPRINTK("All registers for port(s) %u-%u:\n", start_port,
91831961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ		num_ports > 1 ? num_ports - 1 : start_port);
91931961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ
92031961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ	if (NULL != pdev) {
92131961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ		DPRINTK("PCI config space regs:\n");
92231961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ		mv_dump_pci_cfg(pdev, 0x68);
92331961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ	}
92431961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ	DPRINTK("PCI regs:\n");
92531961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ	mv_dump_mem(mmio_base+0xc00, 0x3c);
92631961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ	mv_dump_mem(mmio_base+0xd00, 0x34);
92731961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ	mv_dump_mem(mmio_base+0xf00, 0x4);
92831961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ	mv_dump_mem(mmio_base+0x1d00, 0x6c);
92931961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ	for (hc = start_hc; hc < start_hc + num_hcs; hc++) {
930d220c37e0a3c9a47ae00e87e044d963b3ea040bcDan Aloni		hc_base = mv_hc_base(mmio_base, hc);
93131961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ		DPRINTK("HC regs (HC %i):\n", hc);
93231961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ		mv_dump_mem(hc_base, 0x1c);
93331961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ	}
93431961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ	for (p = start_port; p < start_port + num_ports; p++) {
93531961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ		port_base = mv_port_base(mmio_base, p);
93631961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ		DPRINTK("EDMA regs (port %i):\n",p);
93731961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ		mv_dump_mem(port_base, 0x54);
93831961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ		DPRINTK("SATA regs (port %i):\n",p);
93931961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ		mv_dump_mem(port_base+0x300, 0x60);
94031961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ	}
94131961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ#endif
94220f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ}
94320f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ
94420f733e7d75a16bffc34842b7682c9247dd5f954Brett Russstatic unsigned int mv_scr_offset(unsigned int sc_reg_in)
94520f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ{
94620f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ	unsigned int ofs;
94720f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ
94820f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ	switch (sc_reg_in) {
94920f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ	case SCR_STATUS:
95020f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ	case SCR_CONTROL:
95120f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ	case SCR_ERROR:
95220f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ		ofs = SATA_STATUS_OFS + (sc_reg_in * sizeof(u32));
95320f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ		break;
95420f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ	case SCR_ACTIVE:
95520f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ		ofs = SATA_ACTIVE_OFS;   /* active is not with the others */
95620f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ		break;
95720f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ	default:
95820f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ		ofs = 0xffffffffU;
95920f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ		break;
96020f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ	}
96120f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ	return ofs;
96220f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ}
96320f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ
96420f733e7d75a16bffc34842b7682c9247dd5f954Brett Russstatic u32 mv_scr_read(struct ata_port *ap, unsigned int sc_reg_in)
96520f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ{
96620f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ	unsigned int ofs = mv_scr_offset(sc_reg_in);
96720f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ
968351772658a4d1acc0221a6e30676bb0594e74812Jeff Garzik	if (0xffffffffU != ofs)
96920f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ		return readl(mv_ap_base(ap) + ofs);
970351772658a4d1acc0221a6e30676bb0594e74812Jeff Garzik	else
97120f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ		return (u32) ofs;
97220f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ}
97320f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ
97420f733e7d75a16bffc34842b7682c9247dd5f954Brett Russstatic void mv_scr_write(struct ata_port *ap, unsigned int sc_reg_in, u32 val)
97520f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ{
97620f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ	unsigned int ofs = mv_scr_offset(sc_reg_in);
97720f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ
978351772658a4d1acc0221a6e30676bb0594e74812Jeff Garzik	if (0xffffffffU != ofs)
97920f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ		writelfl(val, mv_ap_base(ap) + ofs);
98020f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ}
98120f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ
982c5d3e45a2200a0905dc45b72714726b7aac3aaf1Jeff Garzikstatic void mv_edma_cfg(struct ata_port *ap, struct mv_host_priv *hpriv,
983c5d3e45a2200a0905dc45b72714726b7aac3aaf1Jeff Garzik			void __iomem *port_mmio)
984e4e7b89280d1d666e2c09e5ad36cf071796c4c7eJeff Garzik{
985e4e7b89280d1d666e2c09e5ad36cf071796c4c7eJeff Garzik	u32 cfg = readl(port_mmio + EDMA_CFG_OFS);
986e4e7b89280d1d666e2c09e5ad36cf071796c4c7eJeff Garzik
987e4e7b89280d1d666e2c09e5ad36cf071796c4c7eJeff Garzik	/* set up non-NCQ EDMA configuration */
988c5d3e45a2200a0905dc45b72714726b7aac3aaf1Jeff Garzik	cfg &= ~(1 << 9);	/* disable eQue */
989e4e7b89280d1d666e2c09e5ad36cf071796c4c7eJeff Garzik
990e728eabea110da90e69c05855e3a11174edb77efJeff Garzik	if (IS_GEN_I(hpriv)) {
991e728eabea110da90e69c05855e3a11174edb77efJeff Garzik		cfg &= ~0x1f;		/* clear queue depth */
992e4e7b89280d1d666e2c09e5ad36cf071796c4c7eJeff Garzik		cfg |= (1 << 8);	/* enab config burst size mask */
993e728eabea110da90e69c05855e3a11174edb77efJeff Garzik	}
994e4e7b89280d1d666e2c09e5ad36cf071796c4c7eJeff Garzik
995e728eabea110da90e69c05855e3a11174edb77efJeff Garzik	else if (IS_GEN_II(hpriv)) {
996e728eabea110da90e69c05855e3a11174edb77efJeff Garzik		cfg &= ~0x1f;		/* clear queue depth */
997e4e7b89280d1d666e2c09e5ad36cf071796c4c7eJeff Garzik		cfg |= EDMA_CFG_RD_BRST_EXT | EDMA_CFG_WR_BUFF_LEN;
998e728eabea110da90e69c05855e3a11174edb77efJeff Garzik		cfg &= ~(EDMA_CFG_NCQ | EDMA_CFG_NCQ_GO_ON_ERR); /* clear NCQ */
999e728eabea110da90e69c05855e3a11174edb77efJeff Garzik	}
1000e4e7b89280d1d666e2c09e5ad36cf071796c4c7eJeff Garzik
1001e4e7b89280d1d666e2c09e5ad36cf071796c4c7eJeff Garzik	else if (IS_GEN_IIE(hpriv)) {
1002e728eabea110da90e69c05855e3a11174edb77efJeff Garzik		cfg |= (1 << 23);	/* do not mask PM field in rx'd FIS */
1003e728eabea110da90e69c05855e3a11174edb77efJeff Garzik		cfg |= (1 << 22);	/* enab 4-entry host queue cache */
1004e4e7b89280d1d666e2c09e5ad36cf071796c4c7eJeff Garzik		cfg &= ~(1 << 19);	/* dis 128-entry queue (for now?) */
1005e4e7b89280d1d666e2c09e5ad36cf071796c4c7eJeff Garzik		cfg |= (1 << 18);	/* enab early completion */
1006e728eabea110da90e69c05855e3a11174edb77efJeff Garzik		cfg |= (1 << 17);	/* enab cut-through (dis stor&forwrd) */
1007e728eabea110da90e69c05855e3a11174edb77efJeff Garzik		cfg &= ~(1 << 16);	/* dis FIS-based switching (for now) */
10084537deb5e90b717a725b3d74b58b4bb1d28443d0Jeff Garzik		cfg &= ~(EDMA_CFG_NCQ);	/* clear NCQ */
1009e4e7b89280d1d666e2c09e5ad36cf071796c4c7eJeff Garzik	}
1010e4e7b89280d1d666e2c09e5ad36cf071796c4c7eJeff Garzik
1011e4e7b89280d1d666e2c09e5ad36cf071796c4c7eJeff Garzik	writelfl(cfg, port_mmio + EDMA_CFG_OFS);
1012e4e7b89280d1d666e2c09e5ad36cf071796c4c7eJeff Garzik}
1013e4e7b89280d1d666e2c09e5ad36cf071796c4c7eJeff Garzik
101405b308e1df6d9d673daedb517969241f41278b52Brett Russ/**
101505b308e1df6d9d673daedb517969241f41278b52Brett Russ *      mv_port_start - Port specific init/start routine.
101605b308e1df6d9d673daedb517969241f41278b52Brett Russ *      @ap: ATA channel to manipulate
101705b308e1df6d9d673daedb517969241f41278b52Brett Russ *
101805b308e1df6d9d673daedb517969241f41278b52Brett Russ *      Allocate and point to DMA memory, init port private memory,
101905b308e1df6d9d673daedb517969241f41278b52Brett Russ *      zero indices.
102005b308e1df6d9d673daedb517969241f41278b52Brett Russ *
102105b308e1df6d9d673daedb517969241f41278b52Brett Russ *      LOCKING:
102205b308e1df6d9d673daedb517969241f41278b52Brett Russ *      Inherited from caller.
102305b308e1df6d9d673daedb517969241f41278b52Brett Russ */
102431961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russstatic int mv_port_start(struct ata_port *ap)
102531961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ{
1026cca3974e48607c3775dc73b544a5700b2e37c21aJeff Garzik	struct device *dev = ap->host->dev;
1027cca3974e48607c3775dc73b544a5700b2e37c21aJeff Garzik	struct mv_host_priv *hpriv = ap->host->private_data;
102831961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ	struct mv_port_priv *pp;
102931961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ	void __iomem *port_mmio = mv_ap_base(ap);
103031961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ	void *mem;
103131961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ	dma_addr_t mem_dma;
103224dc5f33ea4b504cfbd23fa159a4cacba8e4d800Tejun Heo	int rc;
103331961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ
103424dc5f33ea4b504cfbd23fa159a4cacba8e4d800Tejun Heo	pp = devm_kzalloc(dev, sizeof(*pp), GFP_KERNEL);
10356037d6bbdff65eb5a84fe35e140f4da4f7cc103aJeff Garzik	if (!pp)
103624dc5f33ea4b504cfbd23fa159a4cacba8e4d800Tejun Heo		return -ENOMEM;
103731961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ
103824dc5f33ea4b504cfbd23fa159a4cacba8e4d800Tejun Heo	mem = dmam_alloc_coherent(dev, MV_PORT_PRIV_DMA_SZ, &mem_dma,
103924dc5f33ea4b504cfbd23fa159a4cacba8e4d800Tejun Heo				  GFP_KERNEL);
10406037d6bbdff65eb5a84fe35e140f4da4f7cc103aJeff Garzik	if (!mem)
104124dc5f33ea4b504cfbd23fa159a4cacba8e4d800Tejun Heo		return -ENOMEM;
104231961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ	memset(mem, 0, MV_PORT_PRIV_DMA_SZ);
104331961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ
10446037d6bbdff65eb5a84fe35e140f4da4f7cc103aJeff Garzik	rc = ata_pad_alloc(ap, dev);
10456037d6bbdff65eb5a84fe35e140f4da4f7cc103aJeff Garzik	if (rc)
104624dc5f33ea4b504cfbd23fa159a4cacba8e4d800Tejun Heo		return rc;
10476037d6bbdff65eb5a84fe35e140f4da4f7cc103aJeff Garzik
10488b260248d9e0e8b64bb72fd4dee03ad86984c344Jeff Garzik	/* First item in chunk of DMA memory:
104931961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ	 * 32-slot command request table (CRQB), 32 bytes each in size
105031961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ	 */
105131961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ	pp->crqb = mem;
105231961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ	pp->crqb_dma = mem_dma;
105331961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ	mem += MV_CRQB_Q_SZ;
105431961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ	mem_dma += MV_CRQB_Q_SZ;
105531961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ
10568b260248d9e0e8b64bb72fd4dee03ad86984c344Jeff Garzik	/* Second item:
105731961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ	 * 32-slot command response table (CRPB), 8 bytes each in size
105831961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ	 */
105931961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ	pp->crpb = mem;
106031961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ	pp->crpb_dma = mem_dma;
106131961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ	mem += MV_CRPB_Q_SZ;
106231961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ	mem_dma += MV_CRPB_Q_SZ;
106331961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ
106431961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ	/* Third item:
106531961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ	 * Table of scatter-gather descriptors (ePRD), 16 bytes each
106631961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ	 */
106731961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ	pp->sg_tbl = mem;
106831961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ	pp->sg_tbl_dma = mem_dma;
106931961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ
1070c5d3e45a2200a0905dc45b72714726b7aac3aaf1Jeff Garzik	mv_edma_cfg(ap, hpriv, port_mmio);
1071e4e7b89280d1d666e2c09e5ad36cf071796c4c7eJeff Garzik
1072c5d3e45a2200a0905dc45b72714726b7aac3aaf1Jeff Garzik	mv_set_edma_ptrs(port_mmio, hpriv, pp);
107331961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ
107431961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ	/* Don't turn on EDMA here...do it before DMA commands only.  Else
107531961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ	 * we'll be unable to send non-data, PIO, etc due to restricted access
107631961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ	 * to shadow regs.
107731961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ	 */
107831961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ	ap->private_data = pp;
107931961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ	return 0;
108031961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ}
108131961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ
108205b308e1df6d9d673daedb517969241f41278b52Brett Russ/**
108305b308e1df6d9d673daedb517969241f41278b52Brett Russ *      mv_port_stop - Port specific cleanup/stop routine.
108405b308e1df6d9d673daedb517969241f41278b52Brett Russ *      @ap: ATA channel to manipulate
108505b308e1df6d9d673daedb517969241f41278b52Brett Russ *
108605b308e1df6d9d673daedb517969241f41278b52Brett Russ *      Stop DMA, cleanup port memory.
108705b308e1df6d9d673daedb517969241f41278b52Brett Russ *
108805b308e1df6d9d673daedb517969241f41278b52Brett Russ *      LOCKING:
1089cca3974e48607c3775dc73b544a5700b2e37c21aJeff Garzik *      This routine uses the host lock to protect the DMA stop.
109005b308e1df6d9d673daedb517969241f41278b52Brett Russ */
109131961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russstatic void mv_port_stop(struct ata_port *ap)
109231961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ{
1093afb0edd922c7ed6e73678730921dfcccebec17e8Brett Russ	unsigned long flags;
109431961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ
1095cca3974e48607c3775dc73b544a5700b2e37c21aJeff Garzik	spin_lock_irqsave(&ap->host->lock, flags);
109631961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ	mv_stop_dma(ap);
1097cca3974e48607c3775dc73b544a5700b2e37c21aJeff Garzik	spin_unlock_irqrestore(&ap->host->lock, flags);
109831961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ}
109931961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ
110005b308e1df6d9d673daedb517969241f41278b52Brett Russ/**
110105b308e1df6d9d673daedb517969241f41278b52Brett Russ *      mv_fill_sg - Fill out the Marvell ePRD (scatter gather) entries
110205b308e1df6d9d673daedb517969241f41278b52Brett Russ *      @qc: queued command whose SG list to source from
110305b308e1df6d9d673daedb517969241f41278b52Brett Russ *
110405b308e1df6d9d673daedb517969241f41278b52Brett Russ *      Populate the SG list and mark the last entry.
110505b308e1df6d9d673daedb517969241f41278b52Brett Russ *
110605b308e1df6d9d673daedb517969241f41278b52Brett Russ *      LOCKING:
110705b308e1df6d9d673daedb517969241f41278b52Brett Russ *      Inherited from caller.
110805b308e1df6d9d673daedb517969241f41278b52Brett Russ */
1109d88184fb2348a50f7c34f5d49a901c875b2e0114Jeff Garzikstatic unsigned int mv_fill_sg(struct ata_queued_cmd *qc)
111031961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ{
111131961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ	struct mv_port_priv *pp = qc->ap->private_data;
1112d88184fb2348a50f7c34f5d49a901c875b2e0114Jeff Garzik	unsigned int n_sg = 0;
1113972c26bdd6b58e7534473c4f7928584578cf43f4Jeff Garzik	struct scatterlist *sg;
1114d88184fb2348a50f7c34f5d49a901c875b2e0114Jeff Garzik	struct mv_sg *mv_sg;
111531961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ
1116d88184fb2348a50f7c34f5d49a901c875b2e0114Jeff Garzik	mv_sg = pp->sg_tbl;
1117972c26bdd6b58e7534473c4f7928584578cf43f4Jeff Garzik	ata_for_each_sg(sg, qc) {
1118d88184fb2348a50f7c34f5d49a901c875b2e0114Jeff Garzik		dma_addr_t addr = sg_dma_address(sg);
1119d88184fb2348a50f7c34f5d49a901c875b2e0114Jeff Garzik		u32 sg_len = sg_dma_len(sg);
112022374677d18c5eeefd3a283431d312b8c44fef02Jeff Garzik
1121d88184fb2348a50f7c34f5d49a901c875b2e0114Jeff Garzik		mv_sg->addr = cpu_to_le32(addr & 0xffffffff);
1122d88184fb2348a50f7c34f5d49a901c875b2e0114Jeff Garzik		mv_sg->addr_hi = cpu_to_le32((addr >> 16) >> 16);
1123d88184fb2348a50f7c34f5d49a901c875b2e0114Jeff Garzik		mv_sg->flags_size = cpu_to_le32(sg_len & 0xffff);
112422374677d18c5eeefd3a283431d312b8c44fef02Jeff Garzik
1125d88184fb2348a50f7c34f5d49a901c875b2e0114Jeff Garzik		if (ata_sg_is_last(sg, qc))
1126d88184fb2348a50f7c34f5d49a901c875b2e0114Jeff Garzik			mv_sg->flags_size |= cpu_to_le32(EPRD_FLAG_END_OF_TBL);
112722374677d18c5eeefd3a283431d312b8c44fef02Jeff Garzik
1128d88184fb2348a50f7c34f5d49a901c875b2e0114Jeff Garzik		mv_sg++;
1129d88184fb2348a50f7c34f5d49a901c875b2e0114Jeff Garzik		n_sg++;
113031961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ	}
1131d88184fb2348a50f7c34f5d49a901c875b2e0114Jeff Garzik
1132d88184fb2348a50f7c34f5d49a901c875b2e0114Jeff Garzik	return n_sg;
113331961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ}
113431961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ
1135e14698745dd0de1ddbf5cd0cca4313a90f8c1cc1Mark Lordstatic inline void mv_crqb_pack_cmd(__le16 *cmdw, u8 data, u8 addr, unsigned last)
113631961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ{
1137559eedad7f7764dacca33980127b4615011230e4Mark Lord	u16 tmp = data | (addr << CRQB_CMD_ADDR_SHIFT) | CRQB_CMD_CS |
113831961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ		(last ? CRQB_CMD_LAST : 0);
1139559eedad7f7764dacca33980127b4615011230e4Mark Lord	*cmdw = cpu_to_le16(tmp);
114031961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ}
114131961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ
114205b308e1df6d9d673daedb517969241f41278b52Brett Russ/**
114305b308e1df6d9d673daedb517969241f41278b52Brett Russ *      mv_qc_prep - Host specific command preparation.
114405b308e1df6d9d673daedb517969241f41278b52Brett Russ *      @qc: queued command to prepare
114505b308e1df6d9d673daedb517969241f41278b52Brett Russ *
114605b308e1df6d9d673daedb517969241f41278b52Brett Russ *      This routine simply redirects to the general purpose routine
114705b308e1df6d9d673daedb517969241f41278b52Brett Russ *      if command is not DMA.  Else, it handles prep of the CRQB
114805b308e1df6d9d673daedb517969241f41278b52Brett Russ *      (command request block), does some sanity checking, and calls
114905b308e1df6d9d673daedb517969241f41278b52Brett Russ *      the SG load routine.
115005b308e1df6d9d673daedb517969241f41278b52Brett Russ *
115105b308e1df6d9d673daedb517969241f41278b52Brett Russ *      LOCKING:
115205b308e1df6d9d673daedb517969241f41278b52Brett Russ *      Inherited from caller.
115305b308e1df6d9d673daedb517969241f41278b52Brett Russ */
115431961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russstatic void mv_qc_prep(struct ata_queued_cmd *qc)
115531961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ{
115631961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ	struct ata_port *ap = qc->ap;
115731961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ	struct mv_port_priv *pp = ap->private_data;
1158e14698745dd0de1ddbf5cd0cca4313a90f8c1cc1Mark Lord	__le16 *cw;
115931961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ	struct ata_taskfile *tf;
116031961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ	u16 flags = 0;
1161a6432436c5e14b416f27c8f87c5bf0bc36771f49Mark Lord	unsigned in_index;
116231961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ
1163c5d3e45a2200a0905dc45b72714726b7aac3aaf1Jeff Garzik 	if (qc->tf.protocol != ATA_PROT_DMA)
116431961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ		return;
116520f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ
116631961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ	/* Fill in command request block
116731961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ	 */
1168e4e7b89280d1d666e2c09e5ad36cf071796c4c7eJeff Garzik	if (!(qc->tf.flags & ATA_TFLAG_WRITE))
116931961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ		flags |= CRQB_FLAG_READ;
1170beec7dbc6ff003bbc94de62b3323519c878fb2acTejun Heo	WARN_ON(MV_MAX_Q_DEPTH <= qc->tag);
117131961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ	flags |= qc->tag << CRQB_TAG_SHIFT;
11724537deb5e90b717a725b3d74b58b4bb1d28443d0Jeff Garzik	flags |= qc->tag << CRQB_IOID_SHIFT;	/* 50xx appears to ignore this*/
117331961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ
1174bdd4dddee325a7dce3e84cf48201a06aa8508aa4Jeff Garzik	/* get current queue index from software */
1175bdd4dddee325a7dce3e84cf48201a06aa8508aa4Jeff Garzik	in_index = pp->req_idx & MV_MAX_Q_DEPTH_MASK;
1176a6432436c5e14b416f27c8f87c5bf0bc36771f49Mark Lord
1177a6432436c5e14b416f27c8f87c5bf0bc36771f49Mark Lord	pp->crqb[in_index].sg_addr =
117831961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ		cpu_to_le32(pp->sg_tbl_dma & 0xffffffff);
1179a6432436c5e14b416f27c8f87c5bf0bc36771f49Mark Lord	pp->crqb[in_index].sg_addr_hi =
118031961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ		cpu_to_le32((pp->sg_tbl_dma >> 16) >> 16);
1181a6432436c5e14b416f27c8f87c5bf0bc36771f49Mark Lord	pp->crqb[in_index].ctrl_flags = cpu_to_le16(flags);
118231961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ
1183a6432436c5e14b416f27c8f87c5bf0bc36771f49Mark Lord	cw = &pp->crqb[in_index].ata_cmd[0];
118431961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ	tf = &qc->tf;
118531961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ
118631961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ	/* Sadly, the CRQB cannot accomodate all registers--there are
118731961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ	 * only 11 bytes...so we must pick and choose required
118831961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ	 * registers based on the command.  So, we drop feature and
118931961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ	 * hob_feature for [RW] DMA commands, but they are needed for
119031961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ	 * NCQ.  NCQ will drop hob_nsect.
119120f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ	 */
119231961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ	switch (tf->command) {
119331961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ	case ATA_CMD_READ:
119431961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ	case ATA_CMD_READ_EXT:
119531961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ	case ATA_CMD_WRITE:
119631961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ	case ATA_CMD_WRITE_EXT:
1197c15d85c8f3f73b5f20aae7928e25b6996f16b328Jens Axboe	case ATA_CMD_WRITE_FUA_EXT:
119831961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ		mv_crqb_pack_cmd(cw++, tf->hob_nsect, ATA_REG_NSECT, 0);
119931961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ		break;
120031961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ#ifdef LIBATA_NCQ		/* FIXME: remove this line when NCQ added */
120131961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ	case ATA_CMD_FPDMA_READ:
120231961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ	case ATA_CMD_FPDMA_WRITE:
12038b260248d9e0e8b64bb72fd4dee03ad86984c344Jeff Garzik		mv_crqb_pack_cmd(cw++, tf->hob_feature, ATA_REG_FEATURE, 0);
120431961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ		mv_crqb_pack_cmd(cw++, tf->feature, ATA_REG_FEATURE, 0);
120531961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ		break;
120631961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ#endif				/* FIXME: remove this line when NCQ added */
120731961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ	default:
120831961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ		/* The only other commands EDMA supports in non-queued and
120931961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ		 * non-NCQ mode are: [RW] STREAM DMA and W DMA FUA EXT, none
121031961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ		 * of which are defined/used by Linux.  If we get here, this
121131961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ		 * driver needs work.
121231961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ		 *
121331961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ		 * FIXME: modify libata to give qc_prep a return value and
121431961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ		 * return error here.
121531961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ		 */
121631961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ		BUG_ON(tf->command);
121731961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ		break;
121831961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ	}
121931961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ	mv_crqb_pack_cmd(cw++, tf->nsect, ATA_REG_NSECT, 0);
122031961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ	mv_crqb_pack_cmd(cw++, tf->hob_lbal, ATA_REG_LBAL, 0);
122131961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ	mv_crqb_pack_cmd(cw++, tf->lbal, ATA_REG_LBAL, 0);
122231961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ	mv_crqb_pack_cmd(cw++, tf->hob_lbam, ATA_REG_LBAM, 0);
122331961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ	mv_crqb_pack_cmd(cw++, tf->lbam, ATA_REG_LBAM, 0);
122431961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ	mv_crqb_pack_cmd(cw++, tf->hob_lbah, ATA_REG_LBAH, 0);
122531961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ	mv_crqb_pack_cmd(cw++, tf->lbah, ATA_REG_LBAH, 0);
122631961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ	mv_crqb_pack_cmd(cw++, tf->device, ATA_REG_DEVICE, 0);
122731961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ	mv_crqb_pack_cmd(cw++, tf->command, ATA_REG_CMD, 1);	/* last */
122831961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ
1229e4e7b89280d1d666e2c09e5ad36cf071796c4c7eJeff Garzik	if (!(qc->flags & ATA_QCFLAG_DMAMAP))
1230e4e7b89280d1d666e2c09e5ad36cf071796c4c7eJeff Garzik		return;
1231e4e7b89280d1d666e2c09e5ad36cf071796c4c7eJeff Garzik	mv_fill_sg(qc);
1232e4e7b89280d1d666e2c09e5ad36cf071796c4c7eJeff Garzik}
1233e4e7b89280d1d666e2c09e5ad36cf071796c4c7eJeff Garzik
1234e4e7b89280d1d666e2c09e5ad36cf071796c4c7eJeff Garzik/**
1235e4e7b89280d1d666e2c09e5ad36cf071796c4c7eJeff Garzik *      mv_qc_prep_iie - Host specific command preparation.
1236e4e7b89280d1d666e2c09e5ad36cf071796c4c7eJeff Garzik *      @qc: queued command to prepare
1237e4e7b89280d1d666e2c09e5ad36cf071796c4c7eJeff Garzik *
1238e4e7b89280d1d666e2c09e5ad36cf071796c4c7eJeff Garzik *      This routine simply redirects to the general purpose routine
1239e4e7b89280d1d666e2c09e5ad36cf071796c4c7eJeff Garzik *      if command is not DMA.  Else, it handles prep of the CRQB
1240e4e7b89280d1d666e2c09e5ad36cf071796c4c7eJeff Garzik *      (command request block), does some sanity checking, and calls
1241e4e7b89280d1d666e2c09e5ad36cf071796c4c7eJeff Garzik *      the SG load routine.
1242e4e7b89280d1d666e2c09e5ad36cf071796c4c7eJeff Garzik *
1243e4e7b89280d1d666e2c09e5ad36cf071796c4c7eJeff Garzik *      LOCKING:
1244e4e7b89280d1d666e2c09e5ad36cf071796c4c7eJeff Garzik *      Inherited from caller.
1245e4e7b89280d1d666e2c09e5ad36cf071796c4c7eJeff Garzik */
1246e4e7b89280d1d666e2c09e5ad36cf071796c4c7eJeff Garzikstatic void mv_qc_prep_iie(struct ata_queued_cmd *qc)
1247e4e7b89280d1d666e2c09e5ad36cf071796c4c7eJeff Garzik{
1248e4e7b89280d1d666e2c09e5ad36cf071796c4c7eJeff Garzik	struct ata_port *ap = qc->ap;
1249e4e7b89280d1d666e2c09e5ad36cf071796c4c7eJeff Garzik	struct mv_port_priv *pp = ap->private_data;
1250e4e7b89280d1d666e2c09e5ad36cf071796c4c7eJeff Garzik	struct mv_crqb_iie *crqb;
1251e4e7b89280d1d666e2c09e5ad36cf071796c4c7eJeff Garzik	struct ata_taskfile *tf;
1252a6432436c5e14b416f27c8f87c5bf0bc36771f49Mark Lord	unsigned in_index;
1253e4e7b89280d1d666e2c09e5ad36cf071796c4c7eJeff Garzik	u32 flags = 0;
1254e4e7b89280d1d666e2c09e5ad36cf071796c4c7eJeff Garzik
1255c5d3e45a2200a0905dc45b72714726b7aac3aaf1Jeff Garzik 	if (qc->tf.protocol != ATA_PROT_DMA)
1256e4e7b89280d1d666e2c09e5ad36cf071796c4c7eJeff Garzik		return;
1257e4e7b89280d1d666e2c09e5ad36cf071796c4c7eJeff Garzik
1258e4e7b89280d1d666e2c09e5ad36cf071796c4c7eJeff Garzik	/* Fill in Gen IIE command request block
1259e4e7b89280d1d666e2c09e5ad36cf071796c4c7eJeff Garzik	 */
1260e4e7b89280d1d666e2c09e5ad36cf071796c4c7eJeff Garzik	if (!(qc->tf.flags & ATA_TFLAG_WRITE))
1261e4e7b89280d1d666e2c09e5ad36cf071796c4c7eJeff Garzik		flags |= CRQB_FLAG_READ;
1262e4e7b89280d1d666e2c09e5ad36cf071796c4c7eJeff Garzik
1263beec7dbc6ff003bbc94de62b3323519c878fb2acTejun Heo	WARN_ON(MV_MAX_Q_DEPTH <= qc->tag);
1264e4e7b89280d1d666e2c09e5ad36cf071796c4c7eJeff Garzik	flags |= qc->tag << CRQB_TAG_SHIFT;
1265bdd4dddee325a7dce3e84cf48201a06aa8508aa4Jeff Garzik	flags |= qc->tag << CRQB_IOID_SHIFT;	/* "I/O Id" is -really-
12664537deb5e90b717a725b3d74b58b4bb1d28443d0Jeff Garzik						   what we use as our tag */
1267e4e7b89280d1d666e2c09e5ad36cf071796c4c7eJeff Garzik
1268bdd4dddee325a7dce3e84cf48201a06aa8508aa4Jeff Garzik	/* get current queue index from software */
1269bdd4dddee325a7dce3e84cf48201a06aa8508aa4Jeff Garzik	in_index = pp->req_idx & MV_MAX_Q_DEPTH_MASK;
1270a6432436c5e14b416f27c8f87c5bf0bc36771f49Mark Lord
1271a6432436c5e14b416f27c8f87c5bf0bc36771f49Mark Lord	crqb = (struct mv_crqb_iie *) &pp->crqb[in_index];
1272e4e7b89280d1d666e2c09e5ad36cf071796c4c7eJeff Garzik	crqb->addr = cpu_to_le32(pp->sg_tbl_dma & 0xffffffff);
1273e4e7b89280d1d666e2c09e5ad36cf071796c4c7eJeff Garzik	crqb->addr_hi = cpu_to_le32((pp->sg_tbl_dma >> 16) >> 16);
1274e4e7b89280d1d666e2c09e5ad36cf071796c4c7eJeff Garzik	crqb->flags = cpu_to_le32(flags);
1275e4e7b89280d1d666e2c09e5ad36cf071796c4c7eJeff Garzik
1276e4e7b89280d1d666e2c09e5ad36cf071796c4c7eJeff Garzik	tf = &qc->tf;
1277e4e7b89280d1d666e2c09e5ad36cf071796c4c7eJeff Garzik	crqb->ata_cmd[0] = cpu_to_le32(
1278e4e7b89280d1d666e2c09e5ad36cf071796c4c7eJeff Garzik			(tf->command << 16) |
1279e4e7b89280d1d666e2c09e5ad36cf071796c4c7eJeff Garzik			(tf->feature << 24)
1280e4e7b89280d1d666e2c09e5ad36cf071796c4c7eJeff Garzik		);
1281e4e7b89280d1d666e2c09e5ad36cf071796c4c7eJeff Garzik	crqb->ata_cmd[1] = cpu_to_le32(
1282e4e7b89280d1d666e2c09e5ad36cf071796c4c7eJeff Garzik			(tf->lbal << 0) |
1283e4e7b89280d1d666e2c09e5ad36cf071796c4c7eJeff Garzik			(tf->lbam << 8) |
1284e4e7b89280d1d666e2c09e5ad36cf071796c4c7eJeff Garzik			(tf->lbah << 16) |
1285e4e7b89280d1d666e2c09e5ad36cf071796c4c7eJeff Garzik			(tf->device << 24)
1286e4e7b89280d1d666e2c09e5ad36cf071796c4c7eJeff Garzik		);
1287e4e7b89280d1d666e2c09e5ad36cf071796c4c7eJeff Garzik	crqb->ata_cmd[2] = cpu_to_le32(
1288e4e7b89280d1d666e2c09e5ad36cf071796c4c7eJeff Garzik			(tf->hob_lbal << 0) |
1289e4e7b89280d1d666e2c09e5ad36cf071796c4c7eJeff Garzik			(tf->hob_lbam << 8) |
1290e4e7b89280d1d666e2c09e5ad36cf071796c4c7eJeff Garzik			(tf->hob_lbah << 16) |
1291e4e7b89280d1d666e2c09e5ad36cf071796c4c7eJeff Garzik			(tf->hob_feature << 24)
1292e4e7b89280d1d666e2c09e5ad36cf071796c4c7eJeff Garzik		);
1293e4e7b89280d1d666e2c09e5ad36cf071796c4c7eJeff Garzik	crqb->ata_cmd[3] = cpu_to_le32(
1294e4e7b89280d1d666e2c09e5ad36cf071796c4c7eJeff Garzik			(tf->nsect << 0) |
1295e4e7b89280d1d666e2c09e5ad36cf071796c4c7eJeff Garzik			(tf->hob_nsect << 8)
1296e4e7b89280d1d666e2c09e5ad36cf071796c4c7eJeff Garzik		);
1297e4e7b89280d1d666e2c09e5ad36cf071796c4c7eJeff Garzik
1298e4e7b89280d1d666e2c09e5ad36cf071796c4c7eJeff Garzik	if (!(qc->flags & ATA_QCFLAG_DMAMAP))
129931961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ		return;
130031961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ	mv_fill_sg(qc);
130131961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ}
130231961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ
130305b308e1df6d9d673daedb517969241f41278b52Brett Russ/**
130405b308e1df6d9d673daedb517969241f41278b52Brett Russ *      mv_qc_issue - Initiate a command to the host
130505b308e1df6d9d673daedb517969241f41278b52Brett Russ *      @qc: queued command to start
130605b308e1df6d9d673daedb517969241f41278b52Brett Russ *
130705b308e1df6d9d673daedb517969241f41278b52Brett Russ *      This routine simply redirects to the general purpose routine
130805b308e1df6d9d673daedb517969241f41278b52Brett Russ *      if command is not DMA.  Else, it sanity checks our local
130905b308e1df6d9d673daedb517969241f41278b52Brett Russ *      caches of the request producer/consumer indices then enables
131005b308e1df6d9d673daedb517969241f41278b52Brett Russ *      DMA and bumps the request producer index.
131105b308e1df6d9d673daedb517969241f41278b52Brett Russ *
131205b308e1df6d9d673daedb517969241f41278b52Brett Russ *      LOCKING:
131305b308e1df6d9d673daedb517969241f41278b52Brett Russ *      Inherited from caller.
131405b308e1df6d9d673daedb517969241f41278b52Brett Russ */
13159a3d9eb0177eb10500d49cd283b35576082a522dTejun Heostatic unsigned int mv_qc_issue(struct ata_queued_cmd *qc)
131631961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ{
1317c5d3e45a2200a0905dc45b72714726b7aac3aaf1Jeff Garzik	struct ata_port *ap = qc->ap;
1318c5d3e45a2200a0905dc45b72714726b7aac3aaf1Jeff Garzik	void __iomem *port_mmio = mv_ap_base(ap);
1319c5d3e45a2200a0905dc45b72714726b7aac3aaf1Jeff Garzik	struct mv_port_priv *pp = ap->private_data;
1320c5d3e45a2200a0905dc45b72714726b7aac3aaf1Jeff Garzik	struct mv_host_priv *hpriv = ap->host->private_data;
1321bdd4dddee325a7dce3e84cf48201a06aa8508aa4Jeff Garzik	u32 in_index;
132231961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ
1323c5d3e45a2200a0905dc45b72714726b7aac3aaf1Jeff Garzik	if (qc->tf.protocol != ATA_PROT_DMA) {
132431961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ		/* We're about to send a non-EDMA capable command to the
132531961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ		 * port.  Turn off EDMA so there won't be problems accessing
132631961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ		 * shadow block, etc registers.
132731961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ		 */
1328c5d3e45a2200a0905dc45b72714726b7aac3aaf1Jeff Garzik		mv_stop_dma(ap);
132931961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ		return ata_qc_issue_prot(qc);
133031961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ	}
133131961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ
1332bdd4dddee325a7dce3e84cf48201a06aa8508aa4Jeff Garzik	mv_start_dma(port_mmio, hpriv, pp);
1333bdd4dddee325a7dce3e84cf48201a06aa8508aa4Jeff Garzik
1334bdd4dddee325a7dce3e84cf48201a06aa8508aa4Jeff Garzik	in_index = pp->req_idx & MV_MAX_Q_DEPTH_MASK;
133531961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ
133631961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ	/* until we do queuing, the queue should be empty at this point */
1337a6432436c5e14b416f27c8f87c5bf0bc36771f49Mark Lord	WARN_ON(in_index != ((readl(port_mmio + EDMA_REQ_Q_OUT_PTR_OFS)
1338a6432436c5e14b416f27c8f87c5bf0bc36771f49Mark Lord		>> EDMA_REQ_Q_PTR_SHIFT) & MV_MAX_Q_DEPTH_MASK));
133931961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ
1340bdd4dddee325a7dce3e84cf48201a06aa8508aa4Jeff Garzik	pp->req_idx++;
134131961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ
1342bdd4dddee325a7dce3e84cf48201a06aa8508aa4Jeff Garzik	in_index = (pp->req_idx & MV_MAX_Q_DEPTH_MASK) << EDMA_REQ_Q_PTR_SHIFT;
134331961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ
134431961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ	/* and write the request in pointer to kick the EDMA to life */
1345bdd4dddee325a7dce3e84cf48201a06aa8508aa4Jeff Garzik	writelfl((pp->crqb_dma & EDMA_REQ_Q_BASE_LO_MASK) | in_index,
1346bdd4dddee325a7dce3e84cf48201a06aa8508aa4Jeff Garzik		 port_mmio + EDMA_REQ_Q_IN_PTR_OFS);
134731961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ
134831961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ	return 0;
134931961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ}
135031961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ
135105b308e1df6d9d673daedb517969241f41278b52Brett Russ/**
135205b308e1df6d9d673daedb517969241f41278b52Brett Russ *      mv_err_intr - Handle error interrupts on the port
135305b308e1df6d9d673daedb517969241f41278b52Brett Russ *      @ap: ATA channel to manipulate
13549b358e305c1d783c8a4ebf00344e95deb9e38f3dMark Lord *      @reset_allowed: bool: 0 == don't trigger from reset here
135505b308e1df6d9d673daedb517969241f41278b52Brett Russ *
135605b308e1df6d9d673daedb517969241f41278b52Brett Russ *      In most cases, just clear the interrupt and move on.  However,
135705b308e1df6d9d673daedb517969241f41278b52Brett Russ *      some cases require an eDMA reset, which is done right before
135805b308e1df6d9d673daedb517969241f41278b52Brett Russ *      the COMRESET in mv_phy_reset().  The SERR case requires a
135905b308e1df6d9d673daedb517969241f41278b52Brett Russ *      clear of pending errors in the SATA SERROR register.  Finally,
136005b308e1df6d9d673daedb517969241f41278b52Brett Russ *      if the port disabled DMA, update our cached copy to match.
136105b308e1df6d9d673daedb517969241f41278b52Brett Russ *
136205b308e1df6d9d673daedb517969241f41278b52Brett Russ *      LOCKING:
136305b308e1df6d9d673daedb517969241f41278b52Brett Russ *      Inherited from caller.
136405b308e1df6d9d673daedb517969241f41278b52Brett Russ */
1365bdd4dddee325a7dce3e84cf48201a06aa8508aa4Jeff Garzikstatic void mv_err_intr(struct ata_port *ap, struct ata_queued_cmd *qc)
136631961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ{
136731961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ	void __iomem *port_mmio = mv_ap_base(ap);
1368bdd4dddee325a7dce3e84cf48201a06aa8508aa4Jeff Garzik	u32 edma_err_cause, eh_freeze_mask, serr = 0;
1369bdd4dddee325a7dce3e84cf48201a06aa8508aa4Jeff Garzik	struct mv_port_priv *pp = ap->private_data;
1370bdd4dddee325a7dce3e84cf48201a06aa8508aa4Jeff Garzik	struct mv_host_priv *hpriv = ap->host->private_data;
1371bdd4dddee325a7dce3e84cf48201a06aa8508aa4Jeff Garzik	unsigned int edma_enabled = (pp->pp_flags & MV_PP_FLAG_EDMA_EN);
1372bdd4dddee325a7dce3e84cf48201a06aa8508aa4Jeff Garzik	unsigned int action = 0, err_mask = 0;
1373bdd4dddee325a7dce3e84cf48201a06aa8508aa4Jeff Garzik	struct ata_eh_info *ehi = &ap->eh_info;
137420f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ
1375bdd4dddee325a7dce3e84cf48201a06aa8508aa4Jeff Garzik	ata_ehi_clear_desc(ehi);
137620f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ
1377bdd4dddee325a7dce3e84cf48201a06aa8508aa4Jeff Garzik	if (!edma_enabled) {
1378bdd4dddee325a7dce3e84cf48201a06aa8508aa4Jeff Garzik		/* just a guess: do we need to do this? should we
1379bdd4dddee325a7dce3e84cf48201a06aa8508aa4Jeff Garzik		 * expand this, and do it in all cases?
1380bdd4dddee325a7dce3e84cf48201a06aa8508aa4Jeff Garzik		 */
138181952c5497b40ae56835bd0d6537f8c6bdea07e7Tejun Heo		sata_scr_read(ap, SCR_ERROR, &serr);
138281952c5497b40ae56835bd0d6537f8c6bdea07e7Tejun Heo		sata_scr_write_flush(ap, SCR_ERROR, serr);
138320f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ	}
1384bdd4dddee325a7dce3e84cf48201a06aa8508aa4Jeff Garzik
1385bdd4dddee325a7dce3e84cf48201a06aa8508aa4Jeff Garzik	edma_err_cause = readl(port_mmio + EDMA_ERR_IRQ_CAUSE_OFS);
1386bdd4dddee325a7dce3e84cf48201a06aa8508aa4Jeff Garzik
1387bdd4dddee325a7dce3e84cf48201a06aa8508aa4Jeff Garzik	ata_ehi_push_desc(ehi, "edma_err 0x%08x", edma_err_cause);
1388bdd4dddee325a7dce3e84cf48201a06aa8508aa4Jeff Garzik
1389bdd4dddee325a7dce3e84cf48201a06aa8508aa4Jeff Garzik	/*
1390bdd4dddee325a7dce3e84cf48201a06aa8508aa4Jeff Garzik	 * all generations share these EDMA error cause bits
1391bdd4dddee325a7dce3e84cf48201a06aa8508aa4Jeff Garzik	 */
1392bdd4dddee325a7dce3e84cf48201a06aa8508aa4Jeff Garzik
1393bdd4dddee325a7dce3e84cf48201a06aa8508aa4Jeff Garzik	if (edma_err_cause & EDMA_ERR_DEV)
1394bdd4dddee325a7dce3e84cf48201a06aa8508aa4Jeff Garzik		err_mask |= AC_ERR_DEV;
1395bdd4dddee325a7dce3e84cf48201a06aa8508aa4Jeff Garzik	if (edma_err_cause & (EDMA_ERR_D_PAR | EDMA_ERR_PRD_PAR |
1396bdd4dddee325a7dce3e84cf48201a06aa8508aa4Jeff Garzik			EDMA_ERR_CRBQ_PAR | EDMA_ERR_CRPB_PAR |
1397bdd4dddee325a7dce3e84cf48201a06aa8508aa4Jeff Garzik			EDMA_ERR_INTRL_PAR)) {
1398bdd4dddee325a7dce3e84cf48201a06aa8508aa4Jeff Garzik		err_mask |= AC_ERR_ATA_BUS;
1399bdd4dddee325a7dce3e84cf48201a06aa8508aa4Jeff Garzik		action |= ATA_EH_HARDRESET;
1400bdd4dddee325a7dce3e84cf48201a06aa8508aa4Jeff Garzik		ata_ehi_push_desc(ehi, ", parity error");
1401bdd4dddee325a7dce3e84cf48201a06aa8508aa4Jeff Garzik	}
1402bdd4dddee325a7dce3e84cf48201a06aa8508aa4Jeff Garzik	if (edma_err_cause & (EDMA_ERR_DEV_DCON | EDMA_ERR_DEV_CON)) {
1403bdd4dddee325a7dce3e84cf48201a06aa8508aa4Jeff Garzik		ata_ehi_hotplugged(ehi);
1404bdd4dddee325a7dce3e84cf48201a06aa8508aa4Jeff Garzik		ata_ehi_push_desc(ehi, edma_err_cause & EDMA_ERR_DEV_DCON ?
1405bdd4dddee325a7dce3e84cf48201a06aa8508aa4Jeff Garzik			", dev disconnect" : ", dev connect");
1406bdd4dddee325a7dce3e84cf48201a06aa8508aa4Jeff Garzik	}
1407bdd4dddee325a7dce3e84cf48201a06aa8508aa4Jeff Garzik
1408ee9ccdf70163ca6408f6965e0fbc65baeac7312cJeff Garzik	if (IS_GEN_I(hpriv)) {
1409bdd4dddee325a7dce3e84cf48201a06aa8508aa4Jeff Garzik		eh_freeze_mask = EDMA_EH_FREEZE_5;
1410bdd4dddee325a7dce3e84cf48201a06aa8508aa4Jeff Garzik
1411bdd4dddee325a7dce3e84cf48201a06aa8508aa4Jeff Garzik		if (edma_err_cause & EDMA_ERR_SELF_DIS_5) {
1412bdd4dddee325a7dce3e84cf48201a06aa8508aa4Jeff Garzik			struct mv_port_priv *pp	= ap->private_data;
1413bdd4dddee325a7dce3e84cf48201a06aa8508aa4Jeff Garzik			pp->pp_flags &= ~MV_PP_FLAG_EDMA_EN;
1414bdd4dddee325a7dce3e84cf48201a06aa8508aa4Jeff Garzik			ata_ehi_push_desc(ehi, ", EDMA self-disable");
1415bdd4dddee325a7dce3e84cf48201a06aa8508aa4Jeff Garzik		}
1416bdd4dddee325a7dce3e84cf48201a06aa8508aa4Jeff Garzik	} else {
1417bdd4dddee325a7dce3e84cf48201a06aa8508aa4Jeff Garzik		eh_freeze_mask = EDMA_EH_FREEZE;
1418bdd4dddee325a7dce3e84cf48201a06aa8508aa4Jeff Garzik
1419bdd4dddee325a7dce3e84cf48201a06aa8508aa4Jeff Garzik		if (edma_err_cause & EDMA_ERR_SELF_DIS) {
1420bdd4dddee325a7dce3e84cf48201a06aa8508aa4Jeff Garzik			struct mv_port_priv *pp	= ap->private_data;
1421bdd4dddee325a7dce3e84cf48201a06aa8508aa4Jeff Garzik			pp->pp_flags &= ~MV_PP_FLAG_EDMA_EN;
1422bdd4dddee325a7dce3e84cf48201a06aa8508aa4Jeff Garzik			ata_ehi_push_desc(ehi, ", EDMA self-disable");
1423bdd4dddee325a7dce3e84cf48201a06aa8508aa4Jeff Garzik		}
1424bdd4dddee325a7dce3e84cf48201a06aa8508aa4Jeff Garzik
1425bdd4dddee325a7dce3e84cf48201a06aa8508aa4Jeff Garzik		if (edma_err_cause & EDMA_ERR_SERR) {
1426bdd4dddee325a7dce3e84cf48201a06aa8508aa4Jeff Garzik			sata_scr_read(ap, SCR_ERROR, &serr);
1427bdd4dddee325a7dce3e84cf48201a06aa8508aa4Jeff Garzik			sata_scr_write_flush(ap, SCR_ERROR, serr);
1428bdd4dddee325a7dce3e84cf48201a06aa8508aa4Jeff Garzik			err_mask = AC_ERR_ATA_BUS;
1429bdd4dddee325a7dce3e84cf48201a06aa8508aa4Jeff Garzik			action |= ATA_EH_HARDRESET;
1430bdd4dddee325a7dce3e84cf48201a06aa8508aa4Jeff Garzik		}
1431afb0edd922c7ed6e73678730921dfcccebec17e8Brett Russ	}
143220f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ
143320f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ	/* Clear EDMA now that SERR cleanup done */
143420f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ	writelfl(0, port_mmio + EDMA_ERR_IRQ_CAUSE_OFS);
143520f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ
1436bdd4dddee325a7dce3e84cf48201a06aa8508aa4Jeff Garzik	if (!err_mask) {
1437bdd4dddee325a7dce3e84cf48201a06aa8508aa4Jeff Garzik		err_mask = AC_ERR_OTHER;
1438bdd4dddee325a7dce3e84cf48201a06aa8508aa4Jeff Garzik		action |= ATA_EH_HARDRESET;
1439bdd4dddee325a7dce3e84cf48201a06aa8508aa4Jeff Garzik	}
1440bdd4dddee325a7dce3e84cf48201a06aa8508aa4Jeff Garzik
1441bdd4dddee325a7dce3e84cf48201a06aa8508aa4Jeff Garzik	ehi->serror |= serr;
1442bdd4dddee325a7dce3e84cf48201a06aa8508aa4Jeff Garzik	ehi->action |= action;
1443bdd4dddee325a7dce3e84cf48201a06aa8508aa4Jeff Garzik
1444bdd4dddee325a7dce3e84cf48201a06aa8508aa4Jeff Garzik	if (qc)
1445bdd4dddee325a7dce3e84cf48201a06aa8508aa4Jeff Garzik		qc->err_mask |= err_mask;
1446bdd4dddee325a7dce3e84cf48201a06aa8508aa4Jeff Garzik	else
1447bdd4dddee325a7dce3e84cf48201a06aa8508aa4Jeff Garzik		ehi->err_mask |= err_mask;
1448bdd4dddee325a7dce3e84cf48201a06aa8508aa4Jeff Garzik
1449bdd4dddee325a7dce3e84cf48201a06aa8508aa4Jeff Garzik	if (edma_err_cause & eh_freeze_mask)
1450bdd4dddee325a7dce3e84cf48201a06aa8508aa4Jeff Garzik		ata_port_freeze(ap);
1451bdd4dddee325a7dce3e84cf48201a06aa8508aa4Jeff Garzik	else
1452bdd4dddee325a7dce3e84cf48201a06aa8508aa4Jeff Garzik		ata_port_abort(ap);
1453bdd4dddee325a7dce3e84cf48201a06aa8508aa4Jeff Garzik}
1454bdd4dddee325a7dce3e84cf48201a06aa8508aa4Jeff Garzik
1455bdd4dddee325a7dce3e84cf48201a06aa8508aa4Jeff Garzikstatic void mv_intr_pio(struct ata_port *ap)
1456bdd4dddee325a7dce3e84cf48201a06aa8508aa4Jeff Garzik{
1457bdd4dddee325a7dce3e84cf48201a06aa8508aa4Jeff Garzik	struct ata_queued_cmd *qc;
1458bdd4dddee325a7dce3e84cf48201a06aa8508aa4Jeff Garzik	u8 ata_status;
1459bdd4dddee325a7dce3e84cf48201a06aa8508aa4Jeff Garzik
1460bdd4dddee325a7dce3e84cf48201a06aa8508aa4Jeff Garzik	/* ignore spurious intr if drive still BUSY */
1461bdd4dddee325a7dce3e84cf48201a06aa8508aa4Jeff Garzik	ata_status = readb(ap->ioaddr.status_addr);
1462bdd4dddee325a7dce3e84cf48201a06aa8508aa4Jeff Garzik	if (unlikely(ata_status & ATA_BUSY))
1463bdd4dddee325a7dce3e84cf48201a06aa8508aa4Jeff Garzik		return;
1464bdd4dddee325a7dce3e84cf48201a06aa8508aa4Jeff Garzik
1465bdd4dddee325a7dce3e84cf48201a06aa8508aa4Jeff Garzik	/* get active ATA command */
1466bdd4dddee325a7dce3e84cf48201a06aa8508aa4Jeff Garzik	qc = ata_qc_from_tag(ap, ap->active_tag);
1467bdd4dddee325a7dce3e84cf48201a06aa8508aa4Jeff Garzik	if (unlikely(!qc))			/* no active tag */
1468bdd4dddee325a7dce3e84cf48201a06aa8508aa4Jeff Garzik		return;
1469bdd4dddee325a7dce3e84cf48201a06aa8508aa4Jeff Garzik	if (qc->tf.flags & ATA_TFLAG_POLLING)	/* polling; we don't own qc */
1470bdd4dddee325a7dce3e84cf48201a06aa8508aa4Jeff Garzik		return;
1471bdd4dddee325a7dce3e84cf48201a06aa8508aa4Jeff Garzik
1472bdd4dddee325a7dce3e84cf48201a06aa8508aa4Jeff Garzik	/* and finally, complete the ATA command */
1473bdd4dddee325a7dce3e84cf48201a06aa8508aa4Jeff Garzik	qc->err_mask |= ac_err_mask(ata_status);
1474bdd4dddee325a7dce3e84cf48201a06aa8508aa4Jeff Garzik	ata_qc_complete(qc);
1475bdd4dddee325a7dce3e84cf48201a06aa8508aa4Jeff Garzik}
1476bdd4dddee325a7dce3e84cf48201a06aa8508aa4Jeff Garzik
1477bdd4dddee325a7dce3e84cf48201a06aa8508aa4Jeff Garzikstatic void mv_intr_edma(struct ata_port *ap)
1478bdd4dddee325a7dce3e84cf48201a06aa8508aa4Jeff Garzik{
1479bdd4dddee325a7dce3e84cf48201a06aa8508aa4Jeff Garzik	void __iomem *port_mmio = mv_ap_base(ap);
1480bdd4dddee325a7dce3e84cf48201a06aa8508aa4Jeff Garzik	struct mv_host_priv *hpriv = ap->host->private_data;
1481bdd4dddee325a7dce3e84cf48201a06aa8508aa4Jeff Garzik	struct mv_port_priv *pp = ap->private_data;
1482bdd4dddee325a7dce3e84cf48201a06aa8508aa4Jeff Garzik	struct ata_queued_cmd *qc;
1483bdd4dddee325a7dce3e84cf48201a06aa8508aa4Jeff Garzik	u32 out_index, in_index;
1484bdd4dddee325a7dce3e84cf48201a06aa8508aa4Jeff Garzik	bool work_done = false;
1485bdd4dddee325a7dce3e84cf48201a06aa8508aa4Jeff Garzik
1486bdd4dddee325a7dce3e84cf48201a06aa8508aa4Jeff Garzik	/* get h/w response queue pointer */
1487bdd4dddee325a7dce3e84cf48201a06aa8508aa4Jeff Garzik	in_index = (readl(port_mmio + EDMA_RSP_Q_IN_PTR_OFS)
1488bdd4dddee325a7dce3e84cf48201a06aa8508aa4Jeff Garzik			>> EDMA_RSP_Q_PTR_SHIFT) & MV_MAX_Q_DEPTH_MASK;
1489bdd4dddee325a7dce3e84cf48201a06aa8508aa4Jeff Garzik
1490bdd4dddee325a7dce3e84cf48201a06aa8508aa4Jeff Garzik	while (1) {
1491bdd4dddee325a7dce3e84cf48201a06aa8508aa4Jeff Garzik		u16 status;
1492bdd4dddee325a7dce3e84cf48201a06aa8508aa4Jeff Garzik
1493bdd4dddee325a7dce3e84cf48201a06aa8508aa4Jeff Garzik		/* get s/w response queue last-read pointer, and compare */
1494bdd4dddee325a7dce3e84cf48201a06aa8508aa4Jeff Garzik		out_index = pp->resp_idx & MV_MAX_Q_DEPTH_MASK;
1495bdd4dddee325a7dce3e84cf48201a06aa8508aa4Jeff Garzik		if (in_index == out_index)
1496bdd4dddee325a7dce3e84cf48201a06aa8508aa4Jeff Garzik			break;
1497bdd4dddee325a7dce3e84cf48201a06aa8508aa4Jeff Garzik
1498bdd4dddee325a7dce3e84cf48201a06aa8508aa4Jeff Garzik
1499bdd4dddee325a7dce3e84cf48201a06aa8508aa4Jeff Garzik		/* 50xx: get active ATA command */
1500bdd4dddee325a7dce3e84cf48201a06aa8508aa4Jeff Garzik		if (IS_GEN_I(hpriv))
1501bdd4dddee325a7dce3e84cf48201a06aa8508aa4Jeff Garzik			qc = ata_qc_from_tag(ap, ap->active_tag);
1502bdd4dddee325a7dce3e84cf48201a06aa8508aa4Jeff Garzik
1503bdd4dddee325a7dce3e84cf48201a06aa8508aa4Jeff Garzik		/* 60xx: get active ATA command via tag, to enable support
1504bdd4dddee325a7dce3e84cf48201a06aa8508aa4Jeff Garzik		 * for queueing.  this works transparently for queued and
1505bdd4dddee325a7dce3e84cf48201a06aa8508aa4Jeff Garzik		 * non-queued modes.
1506bdd4dddee325a7dce3e84cf48201a06aa8508aa4Jeff Garzik		 */
1507bdd4dddee325a7dce3e84cf48201a06aa8508aa4Jeff Garzik		else {
1508bdd4dddee325a7dce3e84cf48201a06aa8508aa4Jeff Garzik			unsigned int tag;
1509bdd4dddee325a7dce3e84cf48201a06aa8508aa4Jeff Garzik
1510bdd4dddee325a7dce3e84cf48201a06aa8508aa4Jeff Garzik			if (IS_GEN_II(hpriv))
1511bdd4dddee325a7dce3e84cf48201a06aa8508aa4Jeff Garzik				tag = (le16_to_cpu(pp->crpb[out_index].id)
1512bdd4dddee325a7dce3e84cf48201a06aa8508aa4Jeff Garzik					>> CRPB_IOID_SHIFT_6) & 0x3f;
1513bdd4dddee325a7dce3e84cf48201a06aa8508aa4Jeff Garzik			else
1514bdd4dddee325a7dce3e84cf48201a06aa8508aa4Jeff Garzik				tag = (le16_to_cpu(pp->crpb[out_index].id)
1515bdd4dddee325a7dce3e84cf48201a06aa8508aa4Jeff Garzik					>> CRPB_IOID_SHIFT_7) & 0x3f;
1516bdd4dddee325a7dce3e84cf48201a06aa8508aa4Jeff Garzik
1517bdd4dddee325a7dce3e84cf48201a06aa8508aa4Jeff Garzik			qc = ata_qc_from_tag(ap, tag);
1518bdd4dddee325a7dce3e84cf48201a06aa8508aa4Jeff Garzik		}
1519bdd4dddee325a7dce3e84cf48201a06aa8508aa4Jeff Garzik
1520bdd4dddee325a7dce3e84cf48201a06aa8508aa4Jeff Garzik		/* lower 8 bits of status are EDMA_ERR_IRQ_CAUSE_OFS
1521bdd4dddee325a7dce3e84cf48201a06aa8508aa4Jeff Garzik		 * bits (WARNING: might not necessarily be associated
1522bdd4dddee325a7dce3e84cf48201a06aa8508aa4Jeff Garzik		 * with this command), which -should- be clear
1523bdd4dddee325a7dce3e84cf48201a06aa8508aa4Jeff Garzik		 * if all is well
1524bdd4dddee325a7dce3e84cf48201a06aa8508aa4Jeff Garzik		 */
1525bdd4dddee325a7dce3e84cf48201a06aa8508aa4Jeff Garzik		status = le16_to_cpu(pp->crpb[out_index].flags);
1526bdd4dddee325a7dce3e84cf48201a06aa8508aa4Jeff Garzik		if (unlikely(status & 0xff)) {
1527bdd4dddee325a7dce3e84cf48201a06aa8508aa4Jeff Garzik			mv_err_intr(ap, qc);
1528bdd4dddee325a7dce3e84cf48201a06aa8508aa4Jeff Garzik			return;
1529bdd4dddee325a7dce3e84cf48201a06aa8508aa4Jeff Garzik		}
1530bdd4dddee325a7dce3e84cf48201a06aa8508aa4Jeff Garzik
1531bdd4dddee325a7dce3e84cf48201a06aa8508aa4Jeff Garzik		/* and finally, complete the ATA command */
1532bdd4dddee325a7dce3e84cf48201a06aa8508aa4Jeff Garzik		if (qc) {
1533bdd4dddee325a7dce3e84cf48201a06aa8508aa4Jeff Garzik			qc->err_mask |=
1534bdd4dddee325a7dce3e84cf48201a06aa8508aa4Jeff Garzik				ac_err_mask(status >> CRPB_FLAG_STATUS_SHIFT);
1535bdd4dddee325a7dce3e84cf48201a06aa8508aa4Jeff Garzik			ata_qc_complete(qc);
1536bdd4dddee325a7dce3e84cf48201a06aa8508aa4Jeff Garzik		}
1537bdd4dddee325a7dce3e84cf48201a06aa8508aa4Jeff Garzik
1538bdd4dddee325a7dce3e84cf48201a06aa8508aa4Jeff Garzik		/* advance software response queue pointer, to
1539bdd4dddee325a7dce3e84cf48201a06aa8508aa4Jeff Garzik		 * indicate (after the loop completes) to hardware
1540bdd4dddee325a7dce3e84cf48201a06aa8508aa4Jeff Garzik		 * that we have consumed a response queue entry.
1541bdd4dddee325a7dce3e84cf48201a06aa8508aa4Jeff Garzik		 */
1542bdd4dddee325a7dce3e84cf48201a06aa8508aa4Jeff Garzik		work_done = true;
1543bdd4dddee325a7dce3e84cf48201a06aa8508aa4Jeff Garzik		pp->resp_idx++;
1544bdd4dddee325a7dce3e84cf48201a06aa8508aa4Jeff Garzik	}
1545bdd4dddee325a7dce3e84cf48201a06aa8508aa4Jeff Garzik
1546bdd4dddee325a7dce3e84cf48201a06aa8508aa4Jeff Garzik	if (work_done)
1547bdd4dddee325a7dce3e84cf48201a06aa8508aa4Jeff Garzik		writelfl((pp->crpb_dma & EDMA_RSP_Q_BASE_LO_MASK) |
1548bdd4dddee325a7dce3e84cf48201a06aa8508aa4Jeff Garzik			 (out_index << EDMA_RSP_Q_PTR_SHIFT),
1549bdd4dddee325a7dce3e84cf48201a06aa8508aa4Jeff Garzik			 port_mmio + EDMA_RSP_Q_OUT_PTR_OFS);
155020f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ}
155120f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ
155205b308e1df6d9d673daedb517969241f41278b52Brett Russ/**
155305b308e1df6d9d673daedb517969241f41278b52Brett Russ *      mv_host_intr - Handle all interrupts on the given host controller
1554cca3974e48607c3775dc73b544a5700b2e37c21aJeff Garzik *      @host: host specific structure
155505b308e1df6d9d673daedb517969241f41278b52Brett Russ *      @relevant: port error bits relevant to this host controller
155605b308e1df6d9d673daedb517969241f41278b52Brett Russ *      @hc: which host controller we're to look at
155705b308e1df6d9d673daedb517969241f41278b52Brett Russ *
155805b308e1df6d9d673daedb517969241f41278b52Brett Russ *      Read then write clear the HC interrupt status then walk each
155905b308e1df6d9d673daedb517969241f41278b52Brett Russ *      port connected to the HC and see if it needs servicing.  Port
156005b308e1df6d9d673daedb517969241f41278b52Brett Russ *      success ints are reported in the HC interrupt status reg, the
156105b308e1df6d9d673daedb517969241f41278b52Brett Russ *      port error ints are reported in the higher level main
156205b308e1df6d9d673daedb517969241f41278b52Brett Russ *      interrupt status register and thus are passed in via the
156305b308e1df6d9d673daedb517969241f41278b52Brett Russ *      'relevant' argument.
156405b308e1df6d9d673daedb517969241f41278b52Brett Russ *
156505b308e1df6d9d673daedb517969241f41278b52Brett Russ *      LOCKING:
156605b308e1df6d9d673daedb517969241f41278b52Brett Russ *      Inherited from caller.
156705b308e1df6d9d673daedb517969241f41278b52Brett Russ */
1568cca3974e48607c3775dc73b544a5700b2e37c21aJeff Garzikstatic void mv_host_intr(struct ata_host *host, u32 relevant, unsigned int hc)
156920f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ{
15700d5ff566779f894ca9937231a181eb31e4adff0eTejun Heo	void __iomem *mmio = host->iomap[MV_PRIMARY_BAR];
157120f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ	void __iomem *hc_mmio = mv_hc_base(mmio, hc);
157220f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ	u32 hc_irq_cause;
1573c5d3e45a2200a0905dc45b72714726b7aac3aaf1Jeff Garzik	int port, port0;
157420f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ
1575351772658a4d1acc0221a6e30676bb0594e74812Jeff Garzik	if (hc == 0)
157620f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ		port0 = 0;
1577351772658a4d1acc0221a6e30676bb0594e74812Jeff Garzik	else
157820f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ		port0 = MV_PORTS_PER_HC;
157920f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ
158020f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ	/* we'll need the HC success int register in most cases */
158120f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ	hc_irq_cause = readl(hc_mmio + HC_IRQ_CAUSE_OFS);
1582bdd4dddee325a7dce3e84cf48201a06aa8508aa4Jeff Garzik	if (!hc_irq_cause)
1583bdd4dddee325a7dce3e84cf48201a06aa8508aa4Jeff Garzik		return;
1584bdd4dddee325a7dce3e84cf48201a06aa8508aa4Jeff Garzik
1585bdd4dddee325a7dce3e84cf48201a06aa8508aa4Jeff Garzik	writelfl(~hc_irq_cause, hc_mmio + HC_IRQ_CAUSE_OFS);
158620f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ
158720f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ	VPRINTK("ENTER, hc%u relevant=0x%08x HC IRQ cause=0x%08x\n",
158820f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ		hc,relevant,hc_irq_cause);
158920f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ
159020f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ	for (port = port0; port < port0 + MV_PORTS_PER_HC; port++) {
1591cca3974e48607c3775dc73b544a5700b2e37c21aJeff Garzik		struct ata_port *ap = host->ports[port];
159263af2a5c5990d95f1e7d8795f1425fb976ea2b4bMark Lord		struct mv_port_priv *pp = ap->private_data;
1593bdd4dddee325a7dce3e84cf48201a06aa8508aa4Jeff Garzik		int have_err_bits, hard_port, shift;
159455d8ca4f8094246da6e71889a4e04bfafaa78b10Jeff Garzik
1595bdd4dddee325a7dce3e84cf48201a06aa8508aa4Jeff Garzik		if ((!ap) || (ap->flags & ATA_FLAG_DISABLED))
1596a2c91a8819e315e9fd1aef3ff57badb6c1be3f80Jeff Garzik			continue;
1597a2c91a8819e315e9fd1aef3ff57badb6c1be3f80Jeff Garzik
159831961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ		shift = port << 1;		/* (port * 2) */
159920f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ		if (port >= MV_PORTS_PER_HC) {
160020f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ			shift++;	/* skip bit 8 in the HC Main IRQ reg */
160120f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ		}
1602bdd4dddee325a7dce3e84cf48201a06aa8508aa4Jeff Garzik		have_err_bits = ((PORT0_ERR << shift) & relevant);
1603bdd4dddee325a7dce3e84cf48201a06aa8508aa4Jeff Garzik
1604bdd4dddee325a7dce3e84cf48201a06aa8508aa4Jeff Garzik		if (unlikely(have_err_bits)) {
1605bdd4dddee325a7dce3e84cf48201a06aa8508aa4Jeff Garzik			struct ata_queued_cmd *qc;
16068b260248d9e0e8b64bb72fd4dee03ad86984c344Jeff Garzik
160720f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ			qc = ata_qc_from_tag(ap, ap->active_tag);
1608bdd4dddee325a7dce3e84cf48201a06aa8508aa4Jeff Garzik			if (qc && (qc->tf.flags & ATA_TFLAG_POLLING))
1609bdd4dddee325a7dce3e84cf48201a06aa8508aa4Jeff Garzik				continue;
1610bdd4dddee325a7dce3e84cf48201a06aa8508aa4Jeff Garzik
1611bdd4dddee325a7dce3e84cf48201a06aa8508aa4Jeff Garzik			mv_err_intr(ap, qc);
1612bdd4dddee325a7dce3e84cf48201a06aa8508aa4Jeff Garzik			continue;
1613bdd4dddee325a7dce3e84cf48201a06aa8508aa4Jeff Garzik		}
1614bdd4dddee325a7dce3e84cf48201a06aa8508aa4Jeff Garzik
1615bdd4dddee325a7dce3e84cf48201a06aa8508aa4Jeff Garzik		hard_port = mv_hardport_from_port(port); /* range 0..3 */
1616bdd4dddee325a7dce3e84cf48201a06aa8508aa4Jeff Garzik
1617bdd4dddee325a7dce3e84cf48201a06aa8508aa4Jeff Garzik		if (pp->pp_flags & MV_PP_FLAG_EDMA_EN) {
1618bdd4dddee325a7dce3e84cf48201a06aa8508aa4Jeff Garzik			if ((CRPB_DMA_DONE << hard_port) & hc_irq_cause)
1619bdd4dddee325a7dce3e84cf48201a06aa8508aa4Jeff Garzik				mv_intr_edma(ap);
1620bdd4dddee325a7dce3e84cf48201a06aa8508aa4Jeff Garzik		} else {
1621bdd4dddee325a7dce3e84cf48201a06aa8508aa4Jeff Garzik			if ((DEV_IRQ << hard_port) & hc_irq_cause)
1622bdd4dddee325a7dce3e84cf48201a06aa8508aa4Jeff Garzik				mv_intr_pio(ap);
162320f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ		}
162420f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ	}
162520f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ	VPRINTK("EXIT\n");
162620f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ}
162720f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ
1628bdd4dddee325a7dce3e84cf48201a06aa8508aa4Jeff Garzikstatic void mv_pci_error(struct ata_host *host, void __iomem *mmio)
1629bdd4dddee325a7dce3e84cf48201a06aa8508aa4Jeff Garzik{
1630bdd4dddee325a7dce3e84cf48201a06aa8508aa4Jeff Garzik	struct ata_port *ap;
1631bdd4dddee325a7dce3e84cf48201a06aa8508aa4Jeff Garzik	struct ata_queued_cmd *qc;
1632bdd4dddee325a7dce3e84cf48201a06aa8508aa4Jeff Garzik	struct ata_eh_info *ehi;
1633bdd4dddee325a7dce3e84cf48201a06aa8508aa4Jeff Garzik	unsigned int i, err_mask, printed = 0;
1634bdd4dddee325a7dce3e84cf48201a06aa8508aa4Jeff Garzik	u32 err_cause;
1635bdd4dddee325a7dce3e84cf48201a06aa8508aa4Jeff Garzik
1636bdd4dddee325a7dce3e84cf48201a06aa8508aa4Jeff Garzik	err_cause = readl(mmio + PCI_IRQ_CAUSE_OFS);
1637bdd4dddee325a7dce3e84cf48201a06aa8508aa4Jeff Garzik
1638bdd4dddee325a7dce3e84cf48201a06aa8508aa4Jeff Garzik	dev_printk(KERN_ERR, host->dev, "PCI ERROR; PCI IRQ cause=0x%08x\n",
1639bdd4dddee325a7dce3e84cf48201a06aa8508aa4Jeff Garzik		   err_cause);
1640bdd4dddee325a7dce3e84cf48201a06aa8508aa4Jeff Garzik
1641bdd4dddee325a7dce3e84cf48201a06aa8508aa4Jeff Garzik	DPRINTK("All regs @ PCI error\n");
1642bdd4dddee325a7dce3e84cf48201a06aa8508aa4Jeff Garzik	mv_dump_all_regs(mmio, -1, to_pci_dev(host->dev));
1643bdd4dddee325a7dce3e84cf48201a06aa8508aa4Jeff Garzik
1644bdd4dddee325a7dce3e84cf48201a06aa8508aa4Jeff Garzik	writelfl(0, mmio + PCI_IRQ_CAUSE_OFS);
1645bdd4dddee325a7dce3e84cf48201a06aa8508aa4Jeff Garzik
1646bdd4dddee325a7dce3e84cf48201a06aa8508aa4Jeff Garzik	for (i = 0; i < host->n_ports; i++) {
1647bdd4dddee325a7dce3e84cf48201a06aa8508aa4Jeff Garzik		ap = host->ports[i];
1648bdd4dddee325a7dce3e84cf48201a06aa8508aa4Jeff Garzik		if (!ata_port_offline(ap)) {
1649bdd4dddee325a7dce3e84cf48201a06aa8508aa4Jeff Garzik			ehi = &ap->eh_info;
1650bdd4dddee325a7dce3e84cf48201a06aa8508aa4Jeff Garzik			ata_ehi_clear_desc(ehi);
1651bdd4dddee325a7dce3e84cf48201a06aa8508aa4Jeff Garzik			if (!printed++)
1652bdd4dddee325a7dce3e84cf48201a06aa8508aa4Jeff Garzik				ata_ehi_push_desc(ehi,
1653bdd4dddee325a7dce3e84cf48201a06aa8508aa4Jeff Garzik					"PCI err cause 0x%08x", err_cause);
1654bdd4dddee325a7dce3e84cf48201a06aa8508aa4Jeff Garzik			err_mask = AC_ERR_HOST_BUS;
1655bdd4dddee325a7dce3e84cf48201a06aa8508aa4Jeff Garzik			ehi->action = ATA_EH_HARDRESET;
1656bdd4dddee325a7dce3e84cf48201a06aa8508aa4Jeff Garzik			qc = ata_qc_from_tag(ap, ap->active_tag);
1657bdd4dddee325a7dce3e84cf48201a06aa8508aa4Jeff Garzik			if (qc)
1658bdd4dddee325a7dce3e84cf48201a06aa8508aa4Jeff Garzik				qc->err_mask |= err_mask;
1659bdd4dddee325a7dce3e84cf48201a06aa8508aa4Jeff Garzik			else
1660bdd4dddee325a7dce3e84cf48201a06aa8508aa4Jeff Garzik				ehi->err_mask |= err_mask;
1661bdd4dddee325a7dce3e84cf48201a06aa8508aa4Jeff Garzik
1662bdd4dddee325a7dce3e84cf48201a06aa8508aa4Jeff Garzik			ata_port_freeze(ap);
1663bdd4dddee325a7dce3e84cf48201a06aa8508aa4Jeff Garzik		}
1664bdd4dddee325a7dce3e84cf48201a06aa8508aa4Jeff Garzik	}
1665bdd4dddee325a7dce3e84cf48201a06aa8508aa4Jeff Garzik}
1666bdd4dddee325a7dce3e84cf48201a06aa8508aa4Jeff Garzik
166705b308e1df6d9d673daedb517969241f41278b52Brett Russ/**
1668c5d3e45a2200a0905dc45b72714726b7aac3aaf1Jeff Garzik *      mv_interrupt - Main interrupt event handler
166905b308e1df6d9d673daedb517969241f41278b52Brett Russ *      @irq: unused
167005b308e1df6d9d673daedb517969241f41278b52Brett Russ *      @dev_instance: private data; in this case the host structure
167105b308e1df6d9d673daedb517969241f41278b52Brett Russ *
167205b308e1df6d9d673daedb517969241f41278b52Brett Russ *      Read the read only register to determine if any host
167305b308e1df6d9d673daedb517969241f41278b52Brett Russ *      controllers have pending interrupts.  If so, call lower level
167405b308e1df6d9d673daedb517969241f41278b52Brett Russ *      routine to handle.  Also check for PCI errors which are only
167505b308e1df6d9d673daedb517969241f41278b52Brett Russ *      reported here.
167605b308e1df6d9d673daedb517969241f41278b52Brett Russ *
16778b260248d9e0e8b64bb72fd4dee03ad86984c344Jeff Garzik *      LOCKING:
1678cca3974e48607c3775dc73b544a5700b2e37c21aJeff Garzik *      This routine holds the host lock while processing pending
167905b308e1df6d9d673daedb517969241f41278b52Brett Russ *      interrupts.
168005b308e1df6d9d673daedb517969241f41278b52Brett Russ */
16817d12e780e003f93433d49ce78cfedf4b4c52adc5David Howellsstatic irqreturn_t mv_interrupt(int irq, void *dev_instance)
168220f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ{
1683cca3974e48607c3775dc73b544a5700b2e37c21aJeff Garzik	struct ata_host *host = dev_instance;
168420f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ	unsigned int hc, handled = 0, n_hcs;
16850d5ff566779f894ca9937231a181eb31e4adff0eTejun Heo	void __iomem *mmio = host->iomap[MV_PRIMARY_BAR];
168620f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ	u32 irq_stat;
168720f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ
168820f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ	irq_stat = readl(mmio + HC_MAIN_IRQ_CAUSE_OFS);
168920f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ
169020f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ	/* check the cases where we either have nothing pending or have read
169120f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ	 * a bogus register value which can indicate HW removal or PCI fault
169220f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ	 */
1693351772658a4d1acc0221a6e30676bb0594e74812Jeff Garzik	if (!irq_stat || (0xffffffffU == irq_stat))
169420f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ		return IRQ_NONE;
169520f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ
1696cca3974e48607c3775dc73b544a5700b2e37c21aJeff Garzik	n_hcs = mv_get_hc_count(host->ports[0]->flags);
1697cca3974e48607c3775dc73b544a5700b2e37c21aJeff Garzik	spin_lock(&host->lock);
169820f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ
1699bdd4dddee325a7dce3e84cf48201a06aa8508aa4Jeff Garzik	if (unlikely(irq_stat & PCI_ERR)) {
1700bdd4dddee325a7dce3e84cf48201a06aa8508aa4Jeff Garzik		mv_pci_error(host, mmio);
1701bdd4dddee325a7dce3e84cf48201a06aa8508aa4Jeff Garzik		handled = 1;
1702bdd4dddee325a7dce3e84cf48201a06aa8508aa4Jeff Garzik		goto out_unlock;	/* skip all other HC irq handling */
1703bdd4dddee325a7dce3e84cf48201a06aa8508aa4Jeff Garzik	}
1704bdd4dddee325a7dce3e84cf48201a06aa8508aa4Jeff Garzik
170520f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ	for (hc = 0; hc < n_hcs; hc++) {
170620f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ		u32 relevant = irq_stat & (HC0_IRQ_PEND << (hc * HC_SHIFT));
170720f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ		if (relevant) {
1708cca3974e48607c3775dc73b544a5700b2e37c21aJeff Garzik			mv_host_intr(host, relevant, hc);
1709bdd4dddee325a7dce3e84cf48201a06aa8508aa4Jeff Garzik			handled = 1;
171020f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ		}
171120f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ	}
1712615ab95342f6245026d8974b9724f7ea57d9a184Mark Lord
1713bdd4dddee325a7dce3e84cf48201a06aa8508aa4Jeff Garzikout_unlock:
1714cca3974e48607c3775dc73b544a5700b2e37c21aJeff Garzik	spin_unlock(&host->lock);
171520f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ
171620f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ	return IRQ_RETVAL(handled);
171720f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ}
171820f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ
1719c9d39130123238ac18478a42e25cb7996eacfcc0Jeff Garzikstatic void __iomem *mv5_phy_base(void __iomem *mmio, unsigned int port)
1720c9d39130123238ac18478a42e25cb7996eacfcc0Jeff Garzik{
1721c9d39130123238ac18478a42e25cb7996eacfcc0Jeff Garzik	void __iomem *hc_mmio = mv_hc_base_from_port(mmio, port);
1722c9d39130123238ac18478a42e25cb7996eacfcc0Jeff Garzik	unsigned long ofs = (mv_hardport_from_port(port) + 1) * 0x100UL;
1723c9d39130123238ac18478a42e25cb7996eacfcc0Jeff Garzik
1724c9d39130123238ac18478a42e25cb7996eacfcc0Jeff Garzik	return hc_mmio + ofs;
1725c9d39130123238ac18478a42e25cb7996eacfcc0Jeff Garzik}
1726c9d39130123238ac18478a42e25cb7996eacfcc0Jeff Garzik
1727c9d39130123238ac18478a42e25cb7996eacfcc0Jeff Garzikstatic unsigned int mv5_scr_offset(unsigned int sc_reg_in)
1728c9d39130123238ac18478a42e25cb7996eacfcc0Jeff Garzik{
1729c9d39130123238ac18478a42e25cb7996eacfcc0Jeff Garzik	unsigned int ofs;
1730c9d39130123238ac18478a42e25cb7996eacfcc0Jeff Garzik
1731c9d39130123238ac18478a42e25cb7996eacfcc0Jeff Garzik	switch (sc_reg_in) {
1732c9d39130123238ac18478a42e25cb7996eacfcc0Jeff Garzik	case SCR_STATUS:
1733c9d39130123238ac18478a42e25cb7996eacfcc0Jeff Garzik	case SCR_ERROR:
1734c9d39130123238ac18478a42e25cb7996eacfcc0Jeff Garzik	case SCR_CONTROL:
1735c9d39130123238ac18478a42e25cb7996eacfcc0Jeff Garzik		ofs = sc_reg_in * sizeof(u32);
1736c9d39130123238ac18478a42e25cb7996eacfcc0Jeff Garzik		break;
1737c9d39130123238ac18478a42e25cb7996eacfcc0Jeff Garzik	default:
1738c9d39130123238ac18478a42e25cb7996eacfcc0Jeff Garzik		ofs = 0xffffffffU;
1739c9d39130123238ac18478a42e25cb7996eacfcc0Jeff Garzik		break;
1740c9d39130123238ac18478a42e25cb7996eacfcc0Jeff Garzik	}
1741c9d39130123238ac18478a42e25cb7996eacfcc0Jeff Garzik	return ofs;
1742c9d39130123238ac18478a42e25cb7996eacfcc0Jeff Garzik}
1743c9d39130123238ac18478a42e25cb7996eacfcc0Jeff Garzik
1744c9d39130123238ac18478a42e25cb7996eacfcc0Jeff Garzikstatic u32 mv5_scr_read(struct ata_port *ap, unsigned int sc_reg_in)
1745c9d39130123238ac18478a42e25cb7996eacfcc0Jeff Garzik{
17460d5ff566779f894ca9937231a181eb31e4adff0eTejun Heo	void __iomem *mmio = ap->host->iomap[MV_PRIMARY_BAR];
17470d5ff566779f894ca9937231a181eb31e4adff0eTejun Heo	void __iomem *addr = mv5_phy_base(mmio, ap->port_no);
1748c9d39130123238ac18478a42e25cb7996eacfcc0Jeff Garzik	unsigned int ofs = mv5_scr_offset(sc_reg_in);
1749c9d39130123238ac18478a42e25cb7996eacfcc0Jeff Garzik
1750c9d39130123238ac18478a42e25cb7996eacfcc0Jeff Garzik	if (ofs != 0xffffffffU)
17510d5ff566779f894ca9937231a181eb31e4adff0eTejun Heo		return readl(addr + ofs);
1752c9d39130123238ac18478a42e25cb7996eacfcc0Jeff Garzik	else
1753c9d39130123238ac18478a42e25cb7996eacfcc0Jeff Garzik		return (u32) ofs;
1754c9d39130123238ac18478a42e25cb7996eacfcc0Jeff Garzik}
1755c9d39130123238ac18478a42e25cb7996eacfcc0Jeff Garzik
1756c9d39130123238ac18478a42e25cb7996eacfcc0Jeff Garzikstatic void mv5_scr_write(struct ata_port *ap, unsigned int sc_reg_in, u32 val)
1757c9d39130123238ac18478a42e25cb7996eacfcc0Jeff Garzik{
17580d5ff566779f894ca9937231a181eb31e4adff0eTejun Heo	void __iomem *mmio = ap->host->iomap[MV_PRIMARY_BAR];
17590d5ff566779f894ca9937231a181eb31e4adff0eTejun Heo	void __iomem *addr = mv5_phy_base(mmio, ap->port_no);
1760c9d39130123238ac18478a42e25cb7996eacfcc0Jeff Garzik	unsigned int ofs = mv5_scr_offset(sc_reg_in);
1761c9d39130123238ac18478a42e25cb7996eacfcc0Jeff Garzik
1762c9d39130123238ac18478a42e25cb7996eacfcc0Jeff Garzik	if (ofs != 0xffffffffU)
17630d5ff566779f894ca9937231a181eb31e4adff0eTejun Heo		writelfl(val, addr + ofs);
1764c9d39130123238ac18478a42e25cb7996eacfcc0Jeff Garzik}
1765c9d39130123238ac18478a42e25cb7996eacfcc0Jeff Garzik
1766522479fb98c6667f081e75f87e298e413c0b1db8Jeff Garzikstatic void mv5_reset_bus(struct pci_dev *pdev, void __iomem *mmio)
1767522479fb98c6667f081e75f87e298e413c0b1db8Jeff Garzik{
1768522479fb98c6667f081e75f87e298e413c0b1db8Jeff Garzik	int early_5080;
1769522479fb98c6667f081e75f87e298e413c0b1db8Jeff Garzik
177044c10138fd4bbc4b6d6bff0873c24902f2a9da65Auke Kok	early_5080 = (pdev->device == 0x5080) && (pdev->revision == 0);
1771522479fb98c6667f081e75f87e298e413c0b1db8Jeff Garzik
1772522479fb98c6667f081e75f87e298e413c0b1db8Jeff Garzik	if (!early_5080) {
1773522479fb98c6667f081e75f87e298e413c0b1db8Jeff Garzik		u32 tmp = readl(mmio + MV_PCI_EXP_ROM_BAR_CTL);
1774522479fb98c6667f081e75f87e298e413c0b1db8Jeff Garzik		tmp |= (1 << 0);
1775522479fb98c6667f081e75f87e298e413c0b1db8Jeff Garzik		writel(tmp, mmio + MV_PCI_EXP_ROM_BAR_CTL);
1776522479fb98c6667f081e75f87e298e413c0b1db8Jeff Garzik	}
1777522479fb98c6667f081e75f87e298e413c0b1db8Jeff Garzik
1778522479fb98c6667f081e75f87e298e413c0b1db8Jeff Garzik	mv_reset_pci_bus(pdev, mmio);
1779522479fb98c6667f081e75f87e298e413c0b1db8Jeff Garzik}
1780522479fb98c6667f081e75f87e298e413c0b1db8Jeff Garzik
1781522479fb98c6667f081e75f87e298e413c0b1db8Jeff Garzikstatic void mv5_reset_flash(struct mv_host_priv *hpriv, void __iomem *mmio)
1782522479fb98c6667f081e75f87e298e413c0b1db8Jeff Garzik{
1783522479fb98c6667f081e75f87e298e413c0b1db8Jeff Garzik	writel(0x0fcfffff, mmio + MV_FLASH_CTL);
1784522479fb98c6667f081e75f87e298e413c0b1db8Jeff Garzik}
1785522479fb98c6667f081e75f87e298e413c0b1db8Jeff Garzik
178647c2b677daeed9c79ecb7167c211ff36876ea611Jeff Garzikstatic void mv5_read_preamp(struct mv_host_priv *hpriv, int idx,
1787ba3fe8fb6a469390a14379519915f3c39a973d99Jeff Garzik			   void __iomem *mmio)
1788ba3fe8fb6a469390a14379519915f3c39a973d99Jeff Garzik{
1789c9d39130123238ac18478a42e25cb7996eacfcc0Jeff Garzik	void __iomem *phy_mmio = mv5_phy_base(mmio, idx);
1790c9d39130123238ac18478a42e25cb7996eacfcc0Jeff Garzik	u32 tmp;
1791c9d39130123238ac18478a42e25cb7996eacfcc0Jeff Garzik
1792c9d39130123238ac18478a42e25cb7996eacfcc0Jeff Garzik	tmp = readl(phy_mmio + MV5_PHY_MODE);
1793c9d39130123238ac18478a42e25cb7996eacfcc0Jeff Garzik
1794c9d39130123238ac18478a42e25cb7996eacfcc0Jeff Garzik	hpriv->signal[idx].pre = tmp & 0x1800;	/* bits 12:11 */
1795c9d39130123238ac18478a42e25cb7996eacfcc0Jeff Garzik	hpriv->signal[idx].amps = tmp & 0xe0;	/* bits 7:5 */
1796ba3fe8fb6a469390a14379519915f3c39a973d99Jeff Garzik}
1797ba3fe8fb6a469390a14379519915f3c39a973d99Jeff Garzik
179847c2b677daeed9c79ecb7167c211ff36876ea611Jeff Garzikstatic void mv5_enable_leds(struct mv_host_priv *hpriv, void __iomem *mmio)
1799ba3fe8fb6a469390a14379519915f3c39a973d99Jeff Garzik{
1800522479fb98c6667f081e75f87e298e413c0b1db8Jeff Garzik	u32 tmp;
1801522479fb98c6667f081e75f87e298e413c0b1db8Jeff Garzik
1802522479fb98c6667f081e75f87e298e413c0b1db8Jeff Garzik	writel(0, mmio + MV_GPIO_PORT_CTL);
1803522479fb98c6667f081e75f87e298e413c0b1db8Jeff Garzik
1804522479fb98c6667f081e75f87e298e413c0b1db8Jeff Garzik	/* FIXME: handle MV_HP_ERRATA_50XXB2 errata */
1805522479fb98c6667f081e75f87e298e413c0b1db8Jeff Garzik
1806522479fb98c6667f081e75f87e298e413c0b1db8Jeff Garzik	tmp = readl(mmio + MV_PCI_EXP_ROM_BAR_CTL);
1807522479fb98c6667f081e75f87e298e413c0b1db8Jeff Garzik	tmp |= ~(1 << 0);
1808522479fb98c6667f081e75f87e298e413c0b1db8Jeff Garzik	writel(tmp, mmio + MV_PCI_EXP_ROM_BAR_CTL);
1809ba3fe8fb6a469390a14379519915f3c39a973d99Jeff Garzik}
1810ba3fe8fb6a469390a14379519915f3c39a973d99Jeff Garzik
18112a47ce06d534692f9bd2bf4e90a20fc9b1054c39Jeff Garzikstatic void mv5_phy_errata(struct mv_host_priv *hpriv, void __iomem *mmio,
18122a47ce06d534692f9bd2bf4e90a20fc9b1054c39Jeff Garzik			   unsigned int port)
1813bca1c4eb9411533d613123618c0d127fae532595Jeff Garzik{
1814c9d39130123238ac18478a42e25cb7996eacfcc0Jeff Garzik	void __iomem *phy_mmio = mv5_phy_base(mmio, port);
1815c9d39130123238ac18478a42e25cb7996eacfcc0Jeff Garzik	const u32 mask = (1<<12) | (1<<11) | (1<<7) | (1<<6) | (1<<5);
1816c9d39130123238ac18478a42e25cb7996eacfcc0Jeff Garzik	u32 tmp;
1817c9d39130123238ac18478a42e25cb7996eacfcc0Jeff Garzik	int fix_apm_sq = (hpriv->hp_flags & MV_HP_ERRATA_50XXB0);
1818c9d39130123238ac18478a42e25cb7996eacfcc0Jeff Garzik
1819c9d39130123238ac18478a42e25cb7996eacfcc0Jeff Garzik	if (fix_apm_sq) {
1820c9d39130123238ac18478a42e25cb7996eacfcc0Jeff Garzik		tmp = readl(phy_mmio + MV5_LT_MODE);
1821c9d39130123238ac18478a42e25cb7996eacfcc0Jeff Garzik		tmp |= (1 << 19);
1822c9d39130123238ac18478a42e25cb7996eacfcc0Jeff Garzik		writel(tmp, phy_mmio + MV5_LT_MODE);
1823c9d39130123238ac18478a42e25cb7996eacfcc0Jeff Garzik
1824c9d39130123238ac18478a42e25cb7996eacfcc0Jeff Garzik		tmp = readl(phy_mmio + MV5_PHY_CTL);
1825c9d39130123238ac18478a42e25cb7996eacfcc0Jeff Garzik		tmp &= ~0x3;
1826c9d39130123238ac18478a42e25cb7996eacfcc0Jeff Garzik		tmp |= 0x1;
1827c9d39130123238ac18478a42e25cb7996eacfcc0Jeff Garzik		writel(tmp, phy_mmio + MV5_PHY_CTL);
1828c9d39130123238ac18478a42e25cb7996eacfcc0Jeff Garzik	}
1829c9d39130123238ac18478a42e25cb7996eacfcc0Jeff Garzik
1830c9d39130123238ac18478a42e25cb7996eacfcc0Jeff Garzik	tmp = readl(phy_mmio + MV5_PHY_MODE);
1831c9d39130123238ac18478a42e25cb7996eacfcc0Jeff Garzik	tmp &= ~mask;
1832c9d39130123238ac18478a42e25cb7996eacfcc0Jeff Garzik	tmp |= hpriv->signal[port].pre;
1833c9d39130123238ac18478a42e25cb7996eacfcc0Jeff Garzik	tmp |= hpriv->signal[port].amps;
1834c9d39130123238ac18478a42e25cb7996eacfcc0Jeff Garzik	writel(tmp, phy_mmio + MV5_PHY_MODE);
1835bca1c4eb9411533d613123618c0d127fae532595Jeff Garzik}
1836bca1c4eb9411533d613123618c0d127fae532595Jeff Garzik
1837c9d39130123238ac18478a42e25cb7996eacfcc0Jeff Garzik
1838c9d39130123238ac18478a42e25cb7996eacfcc0Jeff Garzik#undef ZERO
1839c9d39130123238ac18478a42e25cb7996eacfcc0Jeff Garzik#define ZERO(reg) writel(0, port_mmio + (reg))
1840c9d39130123238ac18478a42e25cb7996eacfcc0Jeff Garzikstatic void mv5_reset_hc_port(struct mv_host_priv *hpriv, void __iomem *mmio,
1841c9d39130123238ac18478a42e25cb7996eacfcc0Jeff Garzik			     unsigned int port)
1842c9d39130123238ac18478a42e25cb7996eacfcc0Jeff Garzik{
1843c9d39130123238ac18478a42e25cb7996eacfcc0Jeff Garzik	void __iomem *port_mmio = mv_port_base(mmio, port);
1844c9d39130123238ac18478a42e25cb7996eacfcc0Jeff Garzik
1845c9d39130123238ac18478a42e25cb7996eacfcc0Jeff Garzik	writelfl(EDMA_DS, port_mmio + EDMA_CMD_OFS);
1846c9d39130123238ac18478a42e25cb7996eacfcc0Jeff Garzik
1847c9d39130123238ac18478a42e25cb7996eacfcc0Jeff Garzik	mv_channel_reset(hpriv, mmio, port);
1848c9d39130123238ac18478a42e25cb7996eacfcc0Jeff Garzik
1849c9d39130123238ac18478a42e25cb7996eacfcc0Jeff Garzik	ZERO(0x028);	/* command */
1850c9d39130123238ac18478a42e25cb7996eacfcc0Jeff Garzik	writel(0x11f, port_mmio + EDMA_CFG_OFS);
1851c9d39130123238ac18478a42e25cb7996eacfcc0Jeff Garzik	ZERO(0x004);	/* timer */
1852c9d39130123238ac18478a42e25cb7996eacfcc0Jeff Garzik	ZERO(0x008);	/* irq err cause */
1853c9d39130123238ac18478a42e25cb7996eacfcc0Jeff Garzik	ZERO(0x00c);	/* irq err mask */
1854c9d39130123238ac18478a42e25cb7996eacfcc0Jeff Garzik	ZERO(0x010);	/* rq bah */
1855c9d39130123238ac18478a42e25cb7996eacfcc0Jeff Garzik	ZERO(0x014);	/* rq inp */
1856c9d39130123238ac18478a42e25cb7996eacfcc0Jeff Garzik	ZERO(0x018);	/* rq outp */
1857c9d39130123238ac18478a42e25cb7996eacfcc0Jeff Garzik	ZERO(0x01c);	/* respq bah */
1858c9d39130123238ac18478a42e25cb7996eacfcc0Jeff Garzik	ZERO(0x024);	/* respq outp */
1859c9d39130123238ac18478a42e25cb7996eacfcc0Jeff Garzik	ZERO(0x020);	/* respq inp */
1860c9d39130123238ac18478a42e25cb7996eacfcc0Jeff Garzik	ZERO(0x02c);	/* test control */
1861c9d39130123238ac18478a42e25cb7996eacfcc0Jeff Garzik	writel(0xbc, port_mmio + EDMA_IORDY_TMOUT);
1862c9d39130123238ac18478a42e25cb7996eacfcc0Jeff Garzik}
1863c9d39130123238ac18478a42e25cb7996eacfcc0Jeff Garzik#undef ZERO
1864c9d39130123238ac18478a42e25cb7996eacfcc0Jeff Garzik
1865c9d39130123238ac18478a42e25cb7996eacfcc0Jeff Garzik#define ZERO(reg) writel(0, hc_mmio + (reg))
1866c9d39130123238ac18478a42e25cb7996eacfcc0Jeff Garzikstatic void mv5_reset_one_hc(struct mv_host_priv *hpriv, void __iomem *mmio,
1867c9d39130123238ac18478a42e25cb7996eacfcc0Jeff Garzik			unsigned int hc)
186847c2b677daeed9c79ecb7167c211ff36876ea611Jeff Garzik{
1869c9d39130123238ac18478a42e25cb7996eacfcc0Jeff Garzik	void __iomem *hc_mmio = mv_hc_base(mmio, hc);
1870c9d39130123238ac18478a42e25cb7996eacfcc0Jeff Garzik	u32 tmp;
1871c9d39130123238ac18478a42e25cb7996eacfcc0Jeff Garzik
1872c9d39130123238ac18478a42e25cb7996eacfcc0Jeff Garzik	ZERO(0x00c);
1873c9d39130123238ac18478a42e25cb7996eacfcc0Jeff Garzik	ZERO(0x010);
1874c9d39130123238ac18478a42e25cb7996eacfcc0Jeff Garzik	ZERO(0x014);
1875c9d39130123238ac18478a42e25cb7996eacfcc0Jeff Garzik	ZERO(0x018);
1876c9d39130123238ac18478a42e25cb7996eacfcc0Jeff Garzik
1877c9d39130123238ac18478a42e25cb7996eacfcc0Jeff Garzik	tmp = readl(hc_mmio + 0x20);
1878c9d39130123238ac18478a42e25cb7996eacfcc0Jeff Garzik	tmp &= 0x1c1c1c1c;
1879c9d39130123238ac18478a42e25cb7996eacfcc0Jeff Garzik	tmp |= 0x03030303;
1880c9d39130123238ac18478a42e25cb7996eacfcc0Jeff Garzik	writel(tmp, hc_mmio + 0x20);
1881c9d39130123238ac18478a42e25cb7996eacfcc0Jeff Garzik}
1882c9d39130123238ac18478a42e25cb7996eacfcc0Jeff Garzik#undef ZERO
1883c9d39130123238ac18478a42e25cb7996eacfcc0Jeff Garzik
1884c9d39130123238ac18478a42e25cb7996eacfcc0Jeff Garzikstatic int mv5_reset_hc(struct mv_host_priv *hpriv, void __iomem *mmio,
1885c9d39130123238ac18478a42e25cb7996eacfcc0Jeff Garzik			unsigned int n_hc)
1886c9d39130123238ac18478a42e25cb7996eacfcc0Jeff Garzik{
1887c9d39130123238ac18478a42e25cb7996eacfcc0Jeff Garzik	unsigned int hc, port;
1888c9d39130123238ac18478a42e25cb7996eacfcc0Jeff Garzik
1889c9d39130123238ac18478a42e25cb7996eacfcc0Jeff Garzik	for (hc = 0; hc < n_hc; hc++) {
1890c9d39130123238ac18478a42e25cb7996eacfcc0Jeff Garzik		for (port = 0; port < MV_PORTS_PER_HC; port++)
1891c9d39130123238ac18478a42e25cb7996eacfcc0Jeff Garzik			mv5_reset_hc_port(hpriv, mmio,
1892c9d39130123238ac18478a42e25cb7996eacfcc0Jeff Garzik					  (hc * MV_PORTS_PER_HC) + port);
1893c9d39130123238ac18478a42e25cb7996eacfcc0Jeff Garzik
1894c9d39130123238ac18478a42e25cb7996eacfcc0Jeff Garzik		mv5_reset_one_hc(hpriv, mmio, hc);
1895c9d39130123238ac18478a42e25cb7996eacfcc0Jeff Garzik	}
1896c9d39130123238ac18478a42e25cb7996eacfcc0Jeff Garzik
1897c9d39130123238ac18478a42e25cb7996eacfcc0Jeff Garzik	return 0;
189847c2b677daeed9c79ecb7167c211ff36876ea611Jeff Garzik}
189947c2b677daeed9c79ecb7167c211ff36876ea611Jeff Garzik
1900101ffae26c23ea928fce6d31a8b4901327d91a15Jeff Garzik#undef ZERO
1901101ffae26c23ea928fce6d31a8b4901327d91a15Jeff Garzik#define ZERO(reg) writel(0, mmio + (reg))
1902101ffae26c23ea928fce6d31a8b4901327d91a15Jeff Garzikstatic void mv_reset_pci_bus(struct pci_dev *pdev, void __iomem *mmio)
1903101ffae26c23ea928fce6d31a8b4901327d91a15Jeff Garzik{
1904101ffae26c23ea928fce6d31a8b4901327d91a15Jeff Garzik	u32 tmp;
1905101ffae26c23ea928fce6d31a8b4901327d91a15Jeff Garzik
1906101ffae26c23ea928fce6d31a8b4901327d91a15Jeff Garzik	tmp = readl(mmio + MV_PCI_MODE);
1907101ffae26c23ea928fce6d31a8b4901327d91a15Jeff Garzik	tmp &= 0xff00ffff;
1908101ffae26c23ea928fce6d31a8b4901327d91a15Jeff Garzik	writel(tmp, mmio + MV_PCI_MODE);
1909101ffae26c23ea928fce6d31a8b4901327d91a15Jeff Garzik
1910101ffae26c23ea928fce6d31a8b4901327d91a15Jeff Garzik	ZERO(MV_PCI_DISC_TIMER);
1911101ffae26c23ea928fce6d31a8b4901327d91a15Jeff Garzik	ZERO(MV_PCI_MSI_TRIGGER);
1912101ffae26c23ea928fce6d31a8b4901327d91a15Jeff Garzik	writel(0x000100ff, mmio + MV_PCI_XBAR_TMOUT);
1913101ffae26c23ea928fce6d31a8b4901327d91a15Jeff Garzik	ZERO(HC_MAIN_IRQ_MASK_OFS);
1914101ffae26c23ea928fce6d31a8b4901327d91a15Jeff Garzik	ZERO(MV_PCI_SERR_MASK);
1915101ffae26c23ea928fce6d31a8b4901327d91a15Jeff Garzik	ZERO(PCI_IRQ_CAUSE_OFS);
1916101ffae26c23ea928fce6d31a8b4901327d91a15Jeff Garzik	ZERO(PCI_IRQ_MASK_OFS);
1917101ffae26c23ea928fce6d31a8b4901327d91a15Jeff Garzik	ZERO(MV_PCI_ERR_LOW_ADDRESS);
1918101ffae26c23ea928fce6d31a8b4901327d91a15Jeff Garzik	ZERO(MV_PCI_ERR_HIGH_ADDRESS);
1919101ffae26c23ea928fce6d31a8b4901327d91a15Jeff Garzik	ZERO(MV_PCI_ERR_ATTRIBUTE);
1920101ffae26c23ea928fce6d31a8b4901327d91a15Jeff Garzik	ZERO(MV_PCI_ERR_COMMAND);
1921101ffae26c23ea928fce6d31a8b4901327d91a15Jeff Garzik}
1922101ffae26c23ea928fce6d31a8b4901327d91a15Jeff Garzik#undef ZERO
1923101ffae26c23ea928fce6d31a8b4901327d91a15Jeff Garzik
1924101ffae26c23ea928fce6d31a8b4901327d91a15Jeff Garzikstatic void mv6_reset_flash(struct mv_host_priv *hpriv, void __iomem *mmio)
1925101ffae26c23ea928fce6d31a8b4901327d91a15Jeff Garzik{
1926101ffae26c23ea928fce6d31a8b4901327d91a15Jeff Garzik	u32 tmp;
1927101ffae26c23ea928fce6d31a8b4901327d91a15Jeff Garzik
1928101ffae26c23ea928fce6d31a8b4901327d91a15Jeff Garzik	mv5_reset_flash(hpriv, mmio);
1929101ffae26c23ea928fce6d31a8b4901327d91a15Jeff Garzik
1930101ffae26c23ea928fce6d31a8b4901327d91a15Jeff Garzik	tmp = readl(mmio + MV_GPIO_PORT_CTL);
1931101ffae26c23ea928fce6d31a8b4901327d91a15Jeff Garzik	tmp &= 0x3;
1932101ffae26c23ea928fce6d31a8b4901327d91a15Jeff Garzik	tmp |= (1 << 5) | (1 << 6);
1933101ffae26c23ea928fce6d31a8b4901327d91a15Jeff Garzik	writel(tmp, mmio + MV_GPIO_PORT_CTL);
1934101ffae26c23ea928fce6d31a8b4901327d91a15Jeff Garzik}
1935101ffae26c23ea928fce6d31a8b4901327d91a15Jeff Garzik
1936101ffae26c23ea928fce6d31a8b4901327d91a15Jeff Garzik/**
1937101ffae26c23ea928fce6d31a8b4901327d91a15Jeff Garzik *      mv6_reset_hc - Perform the 6xxx global soft reset
1938101ffae26c23ea928fce6d31a8b4901327d91a15Jeff Garzik *      @mmio: base address of the HBA
1939101ffae26c23ea928fce6d31a8b4901327d91a15Jeff Garzik *
1940101ffae26c23ea928fce6d31a8b4901327d91a15Jeff Garzik *      This routine only applies to 6xxx parts.
1941101ffae26c23ea928fce6d31a8b4901327d91a15Jeff Garzik *
1942101ffae26c23ea928fce6d31a8b4901327d91a15Jeff Garzik *      LOCKING:
1943101ffae26c23ea928fce6d31a8b4901327d91a15Jeff Garzik *      Inherited from caller.
1944101ffae26c23ea928fce6d31a8b4901327d91a15Jeff Garzik */
1945c9d39130123238ac18478a42e25cb7996eacfcc0Jeff Garzikstatic int mv6_reset_hc(struct mv_host_priv *hpriv, void __iomem *mmio,
1946c9d39130123238ac18478a42e25cb7996eacfcc0Jeff Garzik			unsigned int n_hc)
1947101ffae26c23ea928fce6d31a8b4901327d91a15Jeff Garzik{
1948101ffae26c23ea928fce6d31a8b4901327d91a15Jeff Garzik	void __iomem *reg = mmio + PCI_MAIN_CMD_STS_OFS;
1949101ffae26c23ea928fce6d31a8b4901327d91a15Jeff Garzik	int i, rc = 0;
1950101ffae26c23ea928fce6d31a8b4901327d91a15Jeff Garzik	u32 t;
1951101ffae26c23ea928fce6d31a8b4901327d91a15Jeff Garzik
1952101ffae26c23ea928fce6d31a8b4901327d91a15Jeff Garzik	/* Following procedure defined in PCI "main command and status
1953101ffae26c23ea928fce6d31a8b4901327d91a15Jeff Garzik	 * register" table.
1954101ffae26c23ea928fce6d31a8b4901327d91a15Jeff Garzik	 */
1955101ffae26c23ea928fce6d31a8b4901327d91a15Jeff Garzik	t = readl(reg);
1956101ffae26c23ea928fce6d31a8b4901327d91a15Jeff Garzik	writel(t | STOP_PCI_MASTER, reg);
1957101ffae26c23ea928fce6d31a8b4901327d91a15Jeff Garzik
1958101ffae26c23ea928fce6d31a8b4901327d91a15Jeff Garzik	for (i = 0; i < 1000; i++) {
1959101ffae26c23ea928fce6d31a8b4901327d91a15Jeff Garzik		udelay(1);
1960101ffae26c23ea928fce6d31a8b4901327d91a15Jeff Garzik		t = readl(reg);
1961101ffae26c23ea928fce6d31a8b4901327d91a15Jeff Garzik		if (PCI_MASTER_EMPTY & t) {
1962101ffae26c23ea928fce6d31a8b4901327d91a15Jeff Garzik			break;
1963101ffae26c23ea928fce6d31a8b4901327d91a15Jeff Garzik		}
1964101ffae26c23ea928fce6d31a8b4901327d91a15Jeff Garzik	}
1965101ffae26c23ea928fce6d31a8b4901327d91a15Jeff Garzik	if (!(PCI_MASTER_EMPTY & t)) {
1966101ffae26c23ea928fce6d31a8b4901327d91a15Jeff Garzik		printk(KERN_ERR DRV_NAME ": PCI master won't flush\n");
1967101ffae26c23ea928fce6d31a8b4901327d91a15Jeff Garzik		rc = 1;
1968101ffae26c23ea928fce6d31a8b4901327d91a15Jeff Garzik		goto done;
1969101ffae26c23ea928fce6d31a8b4901327d91a15Jeff Garzik	}
1970101ffae26c23ea928fce6d31a8b4901327d91a15Jeff Garzik
1971101ffae26c23ea928fce6d31a8b4901327d91a15Jeff Garzik	/* set reset */
1972101ffae26c23ea928fce6d31a8b4901327d91a15Jeff Garzik	i = 5;
1973101ffae26c23ea928fce6d31a8b4901327d91a15Jeff Garzik	do {
1974101ffae26c23ea928fce6d31a8b4901327d91a15Jeff Garzik		writel(t | GLOB_SFT_RST, reg);
1975101ffae26c23ea928fce6d31a8b4901327d91a15Jeff Garzik		t = readl(reg);
1976101ffae26c23ea928fce6d31a8b4901327d91a15Jeff Garzik		udelay(1);
1977101ffae26c23ea928fce6d31a8b4901327d91a15Jeff Garzik	} while (!(GLOB_SFT_RST & t) && (i-- > 0));
1978101ffae26c23ea928fce6d31a8b4901327d91a15Jeff Garzik
1979101ffae26c23ea928fce6d31a8b4901327d91a15Jeff Garzik	if (!(GLOB_SFT_RST & t)) {
1980101ffae26c23ea928fce6d31a8b4901327d91a15Jeff Garzik		printk(KERN_ERR DRV_NAME ": can't set global reset\n");
1981101ffae26c23ea928fce6d31a8b4901327d91a15Jeff Garzik		rc = 1;
1982101ffae26c23ea928fce6d31a8b4901327d91a15Jeff Garzik		goto done;
1983101ffae26c23ea928fce6d31a8b4901327d91a15Jeff Garzik	}
1984101ffae26c23ea928fce6d31a8b4901327d91a15Jeff Garzik
1985101ffae26c23ea928fce6d31a8b4901327d91a15Jeff Garzik	/* clear reset and *reenable the PCI master* (not mentioned in spec) */
1986101ffae26c23ea928fce6d31a8b4901327d91a15Jeff Garzik	i = 5;
1987101ffae26c23ea928fce6d31a8b4901327d91a15Jeff Garzik	do {
1988101ffae26c23ea928fce6d31a8b4901327d91a15Jeff Garzik		writel(t & ~(GLOB_SFT_RST | STOP_PCI_MASTER), reg);
1989101ffae26c23ea928fce6d31a8b4901327d91a15Jeff Garzik		t = readl(reg);
1990101ffae26c23ea928fce6d31a8b4901327d91a15Jeff Garzik		udelay(1);
1991101ffae26c23ea928fce6d31a8b4901327d91a15Jeff Garzik	} while ((GLOB_SFT_RST & t) && (i-- > 0));
1992101ffae26c23ea928fce6d31a8b4901327d91a15Jeff Garzik
1993101ffae26c23ea928fce6d31a8b4901327d91a15Jeff Garzik	if (GLOB_SFT_RST & t) {
1994101ffae26c23ea928fce6d31a8b4901327d91a15Jeff Garzik		printk(KERN_ERR DRV_NAME ": can't clear global reset\n");
1995101ffae26c23ea928fce6d31a8b4901327d91a15Jeff Garzik		rc = 1;
1996101ffae26c23ea928fce6d31a8b4901327d91a15Jeff Garzik	}
1997101ffae26c23ea928fce6d31a8b4901327d91a15Jeff Garzikdone:
1998101ffae26c23ea928fce6d31a8b4901327d91a15Jeff Garzik	return rc;
1999101ffae26c23ea928fce6d31a8b4901327d91a15Jeff Garzik}
2000101ffae26c23ea928fce6d31a8b4901327d91a15Jeff Garzik
200147c2b677daeed9c79ecb7167c211ff36876ea611Jeff Garzikstatic void mv6_read_preamp(struct mv_host_priv *hpriv, int idx,
2002ba3fe8fb6a469390a14379519915f3c39a973d99Jeff Garzik			   void __iomem *mmio)
2003ba3fe8fb6a469390a14379519915f3c39a973d99Jeff Garzik{
2004ba3fe8fb6a469390a14379519915f3c39a973d99Jeff Garzik	void __iomem *port_mmio;
2005ba3fe8fb6a469390a14379519915f3c39a973d99Jeff Garzik	u32 tmp;
2006ba3fe8fb6a469390a14379519915f3c39a973d99Jeff Garzik
2007ba3fe8fb6a469390a14379519915f3c39a973d99Jeff Garzik	tmp = readl(mmio + MV_RESET_CFG);
2008ba3fe8fb6a469390a14379519915f3c39a973d99Jeff Garzik	if ((tmp & (1 << 0)) == 0) {
200947c2b677daeed9c79ecb7167c211ff36876ea611Jeff Garzik		hpriv->signal[idx].amps = 0x7 << 8;
2010ba3fe8fb6a469390a14379519915f3c39a973d99Jeff Garzik		hpriv->signal[idx].pre = 0x1 << 5;
2011ba3fe8fb6a469390a14379519915f3c39a973d99Jeff Garzik		return;
2012ba3fe8fb6a469390a14379519915f3c39a973d99Jeff Garzik	}
2013ba3fe8fb6a469390a14379519915f3c39a973d99Jeff Garzik
2014ba3fe8fb6a469390a14379519915f3c39a973d99Jeff Garzik	port_mmio = mv_port_base(mmio, idx);
2015ba3fe8fb6a469390a14379519915f3c39a973d99Jeff Garzik	tmp = readl(port_mmio + PHY_MODE2);
2016ba3fe8fb6a469390a14379519915f3c39a973d99Jeff Garzik
2017ba3fe8fb6a469390a14379519915f3c39a973d99Jeff Garzik	hpriv->signal[idx].amps = tmp & 0x700;	/* bits 10:8 */
2018ba3fe8fb6a469390a14379519915f3c39a973d99Jeff Garzik	hpriv->signal[idx].pre = tmp & 0xe0;	/* bits 7:5 */
2019ba3fe8fb6a469390a14379519915f3c39a973d99Jeff Garzik}
2020ba3fe8fb6a469390a14379519915f3c39a973d99Jeff Garzik
202147c2b677daeed9c79ecb7167c211ff36876ea611Jeff Garzikstatic void mv6_enable_leds(struct mv_host_priv *hpriv, void __iomem *mmio)
2022ba3fe8fb6a469390a14379519915f3c39a973d99Jeff Garzik{
202347c2b677daeed9c79ecb7167c211ff36876ea611Jeff Garzik	writel(0x00000060, mmio + MV_GPIO_PORT_CTL);
2024ba3fe8fb6a469390a14379519915f3c39a973d99Jeff Garzik}
2025ba3fe8fb6a469390a14379519915f3c39a973d99Jeff Garzik
2026c9d39130123238ac18478a42e25cb7996eacfcc0Jeff Garzikstatic void mv6_phy_errata(struct mv_host_priv *hpriv, void __iomem *mmio,
20272a47ce06d534692f9bd2bf4e90a20fc9b1054c39Jeff Garzik			   unsigned int port)
2028bca1c4eb9411533d613123618c0d127fae532595Jeff Garzik{
2029c9d39130123238ac18478a42e25cb7996eacfcc0Jeff Garzik	void __iomem *port_mmio = mv_port_base(mmio, port);
2030c9d39130123238ac18478a42e25cb7996eacfcc0Jeff Garzik
2031bca1c4eb9411533d613123618c0d127fae532595Jeff Garzik	u32 hp_flags = hpriv->hp_flags;
203247c2b677daeed9c79ecb7167c211ff36876ea611Jeff Garzik	int fix_phy_mode2 =
203347c2b677daeed9c79ecb7167c211ff36876ea611Jeff Garzik		hp_flags & (MV_HP_ERRATA_60X1B2 | MV_HP_ERRATA_60X1C0);
2034bca1c4eb9411533d613123618c0d127fae532595Jeff Garzik	int fix_phy_mode4 =
203547c2b677daeed9c79ecb7167c211ff36876ea611Jeff Garzik		hp_flags & (MV_HP_ERRATA_60X1B2 | MV_HP_ERRATA_60X1C0);
203647c2b677daeed9c79ecb7167c211ff36876ea611Jeff Garzik	u32 m2, tmp;
203747c2b677daeed9c79ecb7167c211ff36876ea611Jeff Garzik
203847c2b677daeed9c79ecb7167c211ff36876ea611Jeff Garzik	if (fix_phy_mode2) {
203947c2b677daeed9c79ecb7167c211ff36876ea611Jeff Garzik		m2 = readl(port_mmio + PHY_MODE2);
204047c2b677daeed9c79ecb7167c211ff36876ea611Jeff Garzik		m2 &= ~(1 << 16);
204147c2b677daeed9c79ecb7167c211ff36876ea611Jeff Garzik		m2 |= (1 << 31);
204247c2b677daeed9c79ecb7167c211ff36876ea611Jeff Garzik		writel(m2, port_mmio + PHY_MODE2);
204347c2b677daeed9c79ecb7167c211ff36876ea611Jeff Garzik
204447c2b677daeed9c79ecb7167c211ff36876ea611Jeff Garzik		udelay(200);
204547c2b677daeed9c79ecb7167c211ff36876ea611Jeff Garzik
204647c2b677daeed9c79ecb7167c211ff36876ea611Jeff Garzik		m2 = readl(port_mmio + PHY_MODE2);
204747c2b677daeed9c79ecb7167c211ff36876ea611Jeff Garzik		m2 &= ~((1 << 16) | (1 << 31));
204847c2b677daeed9c79ecb7167c211ff36876ea611Jeff Garzik		writel(m2, port_mmio + PHY_MODE2);
204947c2b677daeed9c79ecb7167c211ff36876ea611Jeff Garzik
205047c2b677daeed9c79ecb7167c211ff36876ea611Jeff Garzik		udelay(200);
205147c2b677daeed9c79ecb7167c211ff36876ea611Jeff Garzik	}
205247c2b677daeed9c79ecb7167c211ff36876ea611Jeff Garzik
205347c2b677daeed9c79ecb7167c211ff36876ea611Jeff Garzik	/* who knows what this magic does */
205447c2b677daeed9c79ecb7167c211ff36876ea611Jeff Garzik	tmp = readl(port_mmio + PHY_MODE3);
205547c2b677daeed9c79ecb7167c211ff36876ea611Jeff Garzik	tmp &= ~0x7F800000;
205647c2b677daeed9c79ecb7167c211ff36876ea611Jeff Garzik	tmp |= 0x2A800000;
205747c2b677daeed9c79ecb7167c211ff36876ea611Jeff Garzik	writel(tmp, port_mmio + PHY_MODE3);
2058bca1c4eb9411533d613123618c0d127fae532595Jeff Garzik
2059bca1c4eb9411533d613123618c0d127fae532595Jeff Garzik	if (fix_phy_mode4) {
206047c2b677daeed9c79ecb7167c211ff36876ea611Jeff Garzik		u32 m4;
2061bca1c4eb9411533d613123618c0d127fae532595Jeff Garzik
2062bca1c4eb9411533d613123618c0d127fae532595Jeff Garzik		m4 = readl(port_mmio + PHY_MODE4);
206347c2b677daeed9c79ecb7167c211ff36876ea611Jeff Garzik
206447c2b677daeed9c79ecb7167c211ff36876ea611Jeff Garzik		if (hp_flags & MV_HP_ERRATA_60X1B2)
206547c2b677daeed9c79ecb7167c211ff36876ea611Jeff Garzik			tmp = readl(port_mmio + 0x310);
2066bca1c4eb9411533d613123618c0d127fae532595Jeff Garzik
2067bca1c4eb9411533d613123618c0d127fae532595Jeff Garzik		m4 = (m4 & ~(1 << 1)) | (1 << 0);
2068bca1c4eb9411533d613123618c0d127fae532595Jeff Garzik
2069bca1c4eb9411533d613123618c0d127fae532595Jeff Garzik		writel(m4, port_mmio + PHY_MODE4);
207047c2b677daeed9c79ecb7167c211ff36876ea611Jeff Garzik
207147c2b677daeed9c79ecb7167c211ff36876ea611Jeff Garzik		if (hp_flags & MV_HP_ERRATA_60X1B2)
207247c2b677daeed9c79ecb7167c211ff36876ea611Jeff Garzik			writel(tmp, port_mmio + 0x310);
2073bca1c4eb9411533d613123618c0d127fae532595Jeff Garzik	}
2074bca1c4eb9411533d613123618c0d127fae532595Jeff Garzik
2075bca1c4eb9411533d613123618c0d127fae532595Jeff Garzik	/* Revert values of pre-emphasis and signal amps to the saved ones */
2076bca1c4eb9411533d613123618c0d127fae532595Jeff Garzik	m2 = readl(port_mmio + PHY_MODE2);
2077bca1c4eb9411533d613123618c0d127fae532595Jeff Garzik
2078bca1c4eb9411533d613123618c0d127fae532595Jeff Garzik	m2 &= ~MV_M2_PREAMP_MASK;
20792a47ce06d534692f9bd2bf4e90a20fc9b1054c39Jeff Garzik	m2 |= hpriv->signal[port].amps;
20802a47ce06d534692f9bd2bf4e90a20fc9b1054c39Jeff Garzik	m2 |= hpriv->signal[port].pre;
208147c2b677daeed9c79ecb7167c211ff36876ea611Jeff Garzik	m2 &= ~(1 << 16);
2082bca1c4eb9411533d613123618c0d127fae532595Jeff Garzik
2083e4e7b89280d1d666e2c09e5ad36cf071796c4c7eJeff Garzik	/* according to mvSata 3.6.1, some IIE values are fixed */
2084e4e7b89280d1d666e2c09e5ad36cf071796c4c7eJeff Garzik	if (IS_GEN_IIE(hpriv)) {
2085e4e7b89280d1d666e2c09e5ad36cf071796c4c7eJeff Garzik		m2 &= ~0xC30FF01F;
2086e4e7b89280d1d666e2c09e5ad36cf071796c4c7eJeff Garzik		m2 |= 0x0000900F;
2087e4e7b89280d1d666e2c09e5ad36cf071796c4c7eJeff Garzik	}
2088e4e7b89280d1d666e2c09e5ad36cf071796c4c7eJeff Garzik
2089bca1c4eb9411533d613123618c0d127fae532595Jeff Garzik	writel(m2, port_mmio + PHY_MODE2);
2090bca1c4eb9411533d613123618c0d127fae532595Jeff Garzik}
2091bca1c4eb9411533d613123618c0d127fae532595Jeff Garzik
2092c9d39130123238ac18478a42e25cb7996eacfcc0Jeff Garzikstatic void mv_channel_reset(struct mv_host_priv *hpriv, void __iomem *mmio,
2093c9d39130123238ac18478a42e25cb7996eacfcc0Jeff Garzik			     unsigned int port_no)
2094c9d39130123238ac18478a42e25cb7996eacfcc0Jeff Garzik{
2095c9d39130123238ac18478a42e25cb7996eacfcc0Jeff Garzik	void __iomem *port_mmio = mv_port_base(mmio, port_no);
2096c9d39130123238ac18478a42e25cb7996eacfcc0Jeff Garzik
2097c9d39130123238ac18478a42e25cb7996eacfcc0Jeff Garzik	writelfl(ATA_RST, port_mmio + EDMA_CMD_OFS);
2098c9d39130123238ac18478a42e25cb7996eacfcc0Jeff Garzik
2099ee9ccdf70163ca6408f6965e0fbc65baeac7312cJeff Garzik	if (IS_GEN_II(hpriv)) {
2100c9d39130123238ac18478a42e25cb7996eacfcc0Jeff Garzik		u32 ifctl = readl(port_mmio + SATA_INTERFACE_CTL);
2101eb46d684600ac145501805a294c94675e82eab2eMark Lord		ifctl |= (1 << 7);		/* enable gen2i speed */
2102eb46d684600ac145501805a294c94675e82eab2eMark Lord		ifctl = (ifctl & 0xfff) | 0x9b1000; /* from chip spec */
2103c9d39130123238ac18478a42e25cb7996eacfcc0Jeff Garzik		writelfl(ifctl, port_mmio + SATA_INTERFACE_CTL);
2104c9d39130123238ac18478a42e25cb7996eacfcc0Jeff Garzik	}
2105c9d39130123238ac18478a42e25cb7996eacfcc0Jeff Garzik
2106c9d39130123238ac18478a42e25cb7996eacfcc0Jeff Garzik	udelay(25);		/* allow reset propagation */
2107c9d39130123238ac18478a42e25cb7996eacfcc0Jeff Garzik
2108c9d39130123238ac18478a42e25cb7996eacfcc0Jeff Garzik	/* Spec never mentions clearing the bit.  Marvell's driver does
2109c9d39130123238ac18478a42e25cb7996eacfcc0Jeff Garzik	 * clear the bit, however.
2110c9d39130123238ac18478a42e25cb7996eacfcc0Jeff Garzik	 */
2111c9d39130123238ac18478a42e25cb7996eacfcc0Jeff Garzik	writelfl(0, port_mmio + EDMA_CMD_OFS);
2112c9d39130123238ac18478a42e25cb7996eacfcc0Jeff Garzik
2113c9d39130123238ac18478a42e25cb7996eacfcc0Jeff Garzik	hpriv->ops->phy_errata(hpriv, mmio, port_no);
2114c9d39130123238ac18478a42e25cb7996eacfcc0Jeff Garzik
2115ee9ccdf70163ca6408f6965e0fbc65baeac7312cJeff Garzik	if (IS_GEN_I(hpriv))
2116c9d39130123238ac18478a42e25cb7996eacfcc0Jeff Garzik		mdelay(1);
2117c9d39130123238ac18478a42e25cb7996eacfcc0Jeff Garzik}
2118c9d39130123238ac18478a42e25cb7996eacfcc0Jeff Garzik
211905b308e1df6d9d673daedb517969241f41278b52Brett Russ/**
2120bdd4dddee325a7dce3e84cf48201a06aa8508aa4Jeff Garzik *      mv_phy_reset - Perform eDMA reset followed by COMRESET
212105b308e1df6d9d673daedb517969241f41278b52Brett Russ *      @ap: ATA channel to manipulate
212205b308e1df6d9d673daedb517969241f41278b52Brett Russ *
212305b308e1df6d9d673daedb517969241f41278b52Brett Russ *      Part of this is taken from __sata_phy_reset and modified to
212405b308e1df6d9d673daedb517969241f41278b52Brett Russ *      not sleep since this routine gets called from interrupt level.
212505b308e1df6d9d673daedb517969241f41278b52Brett Russ *
212605b308e1df6d9d673daedb517969241f41278b52Brett Russ *      LOCKING:
212705b308e1df6d9d673daedb517969241f41278b52Brett Russ *      Inherited from caller.  This is coded to safe to call at
212805b308e1df6d9d673daedb517969241f41278b52Brett Russ *      interrupt level, i.e. it does not sleep.
212931961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ */
2130bdd4dddee325a7dce3e84cf48201a06aa8508aa4Jeff Garzikstatic void mv_phy_reset(struct ata_port *ap, unsigned int *class,
2131bdd4dddee325a7dce3e84cf48201a06aa8508aa4Jeff Garzik			 unsigned long deadline)
213220f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ{
2133095fec887eaa1c38d17c0c929a6733c744a9fa1fJeff Garzik	struct mv_port_priv *pp	= ap->private_data;
2134cca3974e48607c3775dc73b544a5700b2e37c21aJeff Garzik	struct mv_host_priv *hpriv = ap->host->private_data;
213520f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ	void __iomem *port_mmio = mv_ap_base(ap);
213622374677d18c5eeefd3a283431d312b8c44fef02Jeff Garzik	int retry = 5;
213722374677d18c5eeefd3a283431d312b8c44fef02Jeff Garzik	u32 sstatus;
213820f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ
213920f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ	VPRINTK("ENTER, port %u, mmio 0x%p\n", ap->port_no, port_mmio);
214020f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ
2141095fec887eaa1c38d17c0c929a6733c744a9fa1fJeff Garzik	DPRINTK("S-regs after ATA_RST: SStat 0x%08x SErr 0x%08x "
214231961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ		"SCtrl 0x%08x\n", mv_scr_read(ap, SCR_STATUS),
214331961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ		mv_scr_read(ap, SCR_ERROR), mv_scr_read(ap, SCR_CONTROL));
214420f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ
214522374677d18c5eeefd3a283431d312b8c44fef02Jeff Garzik	/* Issue COMRESET via SControl */
214622374677d18c5eeefd3a283431d312b8c44fef02Jeff Garzikcomreset_retry:
214781952c5497b40ae56835bd0d6537f8c6bdea07e7Tejun Heo	sata_scr_write_flush(ap, SCR_CONTROL, 0x301);
2148bdd4dddee325a7dce3e84cf48201a06aa8508aa4Jeff Garzik	msleep(1);
214922374677d18c5eeefd3a283431d312b8c44fef02Jeff Garzik
215081952c5497b40ae56835bd0d6537f8c6bdea07e7Tejun Heo	sata_scr_write_flush(ap, SCR_CONTROL, 0x300);
2151bdd4dddee325a7dce3e84cf48201a06aa8508aa4Jeff Garzik	msleep(20);
215222374677d18c5eeefd3a283431d312b8c44fef02Jeff Garzik
215331961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ	do {
215481952c5497b40ae56835bd0d6537f8c6bdea07e7Tejun Heo		sata_scr_read(ap, SCR_STATUS, &sstatus);
215562f1d0e6de138b91d55fbd7d579c837ed62e9e31Andres Salomon		if (((sstatus & 0x3) == 3) || ((sstatus & 0x3) == 0))
215631961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ			break;
215722374677d18c5eeefd3a283431d312b8c44fef02Jeff Garzik
2158bdd4dddee325a7dce3e84cf48201a06aa8508aa4Jeff Garzik		msleep(1);
2159c5d3e45a2200a0905dc45b72714726b7aac3aaf1Jeff Garzik	} while (time_before(jiffies, deadline));
216020f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ
216122374677d18c5eeefd3a283431d312b8c44fef02Jeff Garzik	/* work around errata */
2162ee9ccdf70163ca6408f6965e0fbc65baeac7312cJeff Garzik	if (IS_GEN_II(hpriv) &&
216322374677d18c5eeefd3a283431d312b8c44fef02Jeff Garzik	    (sstatus != 0x0) && (sstatus != 0x113) && (sstatus != 0x123) &&
216422374677d18c5eeefd3a283431d312b8c44fef02Jeff Garzik	    (retry-- > 0))
216522374677d18c5eeefd3a283431d312b8c44fef02Jeff Garzik		goto comreset_retry;
2166095fec887eaa1c38d17c0c929a6733c744a9fa1fJeff Garzik
2167095fec887eaa1c38d17c0c929a6733c744a9fa1fJeff Garzik	DPRINTK("S-regs after PHY wake: SStat 0x%08x SErr 0x%08x "
216831961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ		"SCtrl 0x%08x\n", mv_scr_read(ap, SCR_STATUS),
216931961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ		mv_scr_read(ap, SCR_ERROR), mv_scr_read(ap, SCR_CONTROL));
217031961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ
2171bdd4dddee325a7dce3e84cf48201a06aa8508aa4Jeff Garzik	if (ata_port_offline(ap)) {
2172bdd4dddee325a7dce3e84cf48201a06aa8508aa4Jeff Garzik		*class = ATA_DEV_NONE;
217320f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ		return;
217420f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ	}
217520f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ
217622374677d18c5eeefd3a283431d312b8c44fef02Jeff Garzik	/* even after SStatus reflects that device is ready,
217722374677d18c5eeefd3a283431d312b8c44fef02Jeff Garzik	 * it seems to take a while for link to be fully
217822374677d18c5eeefd3a283431d312b8c44fef02Jeff Garzik	 * established (and thus Status no longer 0x80/0x7F),
217922374677d18c5eeefd3a283431d312b8c44fef02Jeff Garzik	 * so we poll a bit for that, here.
218022374677d18c5eeefd3a283431d312b8c44fef02Jeff Garzik	 */
218122374677d18c5eeefd3a283431d312b8c44fef02Jeff Garzik	retry = 20;
218222374677d18c5eeefd3a283431d312b8c44fef02Jeff Garzik	while (1) {
218322374677d18c5eeefd3a283431d312b8c44fef02Jeff Garzik		u8 drv_stat = ata_check_status(ap);
218422374677d18c5eeefd3a283431d312b8c44fef02Jeff Garzik		if ((drv_stat != 0x80) && (drv_stat != 0x7f))
218522374677d18c5eeefd3a283431d312b8c44fef02Jeff Garzik			break;
2186bdd4dddee325a7dce3e84cf48201a06aa8508aa4Jeff Garzik		msleep(500);
218722374677d18c5eeefd3a283431d312b8c44fef02Jeff Garzik		if (retry-- <= 0)
218822374677d18c5eeefd3a283431d312b8c44fef02Jeff Garzik			break;
2189bdd4dddee325a7dce3e84cf48201a06aa8508aa4Jeff Garzik		if (time_after(jiffies, deadline))
2190bdd4dddee325a7dce3e84cf48201a06aa8508aa4Jeff Garzik			break;
219122374677d18c5eeefd3a283431d312b8c44fef02Jeff Garzik	}
219222374677d18c5eeefd3a283431d312b8c44fef02Jeff Garzik
2193bdd4dddee325a7dce3e84cf48201a06aa8508aa4Jeff Garzik	/* FIXME: if we passed the deadline, the following
2194bdd4dddee325a7dce3e84cf48201a06aa8508aa4Jeff Garzik	 * code probably produces an invalid result
2195bdd4dddee325a7dce3e84cf48201a06aa8508aa4Jeff Garzik	 */
219620f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ
2197bdd4dddee325a7dce3e84cf48201a06aa8508aa4Jeff Garzik	/* finally, read device signature from TF registers */
2198bdd4dddee325a7dce3e84cf48201a06aa8508aa4Jeff Garzik	*class = ata_dev_try_classify(ap, 0, NULL);
2199095fec887eaa1c38d17c0c929a6733c744a9fa1fJeff Garzik
2200095fec887eaa1c38d17c0c929a6733c744a9fa1fJeff Garzik	writelfl(0, port_mmio + EDMA_ERR_IRQ_CAUSE_OFS);
2201095fec887eaa1c38d17c0c929a6733c744a9fa1fJeff Garzik
2202bdd4dddee325a7dce3e84cf48201a06aa8508aa4Jeff Garzik	WARN_ON(pp->pp_flags & MV_PP_FLAG_EDMA_EN);
2203095fec887eaa1c38d17c0c929a6733c744a9fa1fJeff Garzik
2204bca1c4eb9411533d613123618c0d127fae532595Jeff Garzik	VPRINTK("EXIT\n");
220520f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ}
220620f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ
2207bdd4dddee325a7dce3e84cf48201a06aa8508aa4Jeff Garzikstatic int mv_prereset(struct ata_port *ap, unsigned long deadline)
220822374677d18c5eeefd3a283431d312b8c44fef02Jeff Garzik{
2209bdd4dddee325a7dce3e84cf48201a06aa8508aa4Jeff Garzik	struct mv_port_priv *pp	= ap->private_data;
2210bdd4dddee325a7dce3e84cf48201a06aa8508aa4Jeff Garzik	struct ata_eh_context *ehc = &ap->eh_context;
2211bdd4dddee325a7dce3e84cf48201a06aa8508aa4Jeff Garzik	int rc;
2212bdd4dddee325a7dce3e84cf48201a06aa8508aa4Jeff Garzik
2213bdd4dddee325a7dce3e84cf48201a06aa8508aa4Jeff Garzik	rc = mv_stop_dma(ap);
2214bdd4dddee325a7dce3e84cf48201a06aa8508aa4Jeff Garzik	if (rc)
2215bdd4dddee325a7dce3e84cf48201a06aa8508aa4Jeff Garzik		ehc->i.action |= ATA_EH_HARDRESET;
2216bdd4dddee325a7dce3e84cf48201a06aa8508aa4Jeff Garzik
2217bdd4dddee325a7dce3e84cf48201a06aa8508aa4Jeff Garzik	if (!(pp->pp_flags & MV_PP_FLAG_HAD_A_RESET)) {
2218bdd4dddee325a7dce3e84cf48201a06aa8508aa4Jeff Garzik		pp->pp_flags |= MV_PP_FLAG_HAD_A_RESET;
2219bdd4dddee325a7dce3e84cf48201a06aa8508aa4Jeff Garzik		ehc->i.action |= ATA_EH_HARDRESET;
2220bdd4dddee325a7dce3e84cf48201a06aa8508aa4Jeff Garzik	}
2221bdd4dddee325a7dce3e84cf48201a06aa8508aa4Jeff Garzik
2222bdd4dddee325a7dce3e84cf48201a06aa8508aa4Jeff Garzik	/* if we're about to do hardreset, nothing more to do */
2223bdd4dddee325a7dce3e84cf48201a06aa8508aa4Jeff Garzik	if (ehc->i.action & ATA_EH_HARDRESET)
2224bdd4dddee325a7dce3e84cf48201a06aa8508aa4Jeff Garzik		return 0;
2225bdd4dddee325a7dce3e84cf48201a06aa8508aa4Jeff Garzik
2226bdd4dddee325a7dce3e84cf48201a06aa8508aa4Jeff Garzik	if (ata_port_online(ap))
2227bdd4dddee325a7dce3e84cf48201a06aa8508aa4Jeff Garzik		rc = ata_wait_ready(ap, deadline);
2228bdd4dddee325a7dce3e84cf48201a06aa8508aa4Jeff Garzik	else
2229bdd4dddee325a7dce3e84cf48201a06aa8508aa4Jeff Garzik		rc = -ENODEV;
2230bdd4dddee325a7dce3e84cf48201a06aa8508aa4Jeff Garzik
2231bdd4dddee325a7dce3e84cf48201a06aa8508aa4Jeff Garzik	return rc;
223222374677d18c5eeefd3a283431d312b8c44fef02Jeff Garzik}
223322374677d18c5eeefd3a283431d312b8c44fef02Jeff Garzik
2234bdd4dddee325a7dce3e84cf48201a06aa8508aa4Jeff Garzikstatic int mv_hardreset(struct ata_port *ap, unsigned int *class,
2235bdd4dddee325a7dce3e84cf48201a06aa8508aa4Jeff Garzik			unsigned long deadline)
223631961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ{
2237bdd4dddee325a7dce3e84cf48201a06aa8508aa4Jeff Garzik	struct mv_host_priv *hpriv = ap->host->private_data;
22380d5ff566779f894ca9937231a181eb31e4adff0eTejun Heo	void __iomem *mmio = ap->host->iomap[MV_PRIMARY_BAR];
223931961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ
2240bdd4dddee325a7dce3e84cf48201a06aa8508aa4Jeff Garzik	mv_stop_dma(ap);
224131961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ
2242bdd4dddee325a7dce3e84cf48201a06aa8508aa4Jeff Garzik	mv_channel_reset(hpriv, mmio, ap->port_no);
224331961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ
2244bdd4dddee325a7dce3e84cf48201a06aa8508aa4Jeff Garzik	mv_phy_reset(ap, class, deadline);
2245bdd4dddee325a7dce3e84cf48201a06aa8508aa4Jeff Garzik
2246bdd4dddee325a7dce3e84cf48201a06aa8508aa4Jeff Garzik	return 0;
2247bdd4dddee325a7dce3e84cf48201a06aa8508aa4Jeff Garzik}
2248bdd4dddee325a7dce3e84cf48201a06aa8508aa4Jeff Garzik
2249bdd4dddee325a7dce3e84cf48201a06aa8508aa4Jeff Garzikstatic void mv_postreset(struct ata_port *ap, unsigned int *classes)
2250bdd4dddee325a7dce3e84cf48201a06aa8508aa4Jeff Garzik{
2251bdd4dddee325a7dce3e84cf48201a06aa8508aa4Jeff Garzik	u32 serr;
2252bdd4dddee325a7dce3e84cf48201a06aa8508aa4Jeff Garzik
2253bdd4dddee325a7dce3e84cf48201a06aa8508aa4Jeff Garzik	/* print link status */
2254bdd4dddee325a7dce3e84cf48201a06aa8508aa4Jeff Garzik	sata_print_link_status(ap);
225531961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ
2256bdd4dddee325a7dce3e84cf48201a06aa8508aa4Jeff Garzik	/* clear SError */
2257bdd4dddee325a7dce3e84cf48201a06aa8508aa4Jeff Garzik	sata_scr_read(ap, SCR_ERROR, &serr);
2258bdd4dddee325a7dce3e84cf48201a06aa8508aa4Jeff Garzik	sata_scr_write_flush(ap, SCR_ERROR, serr);
2259bdd4dddee325a7dce3e84cf48201a06aa8508aa4Jeff Garzik
2260bdd4dddee325a7dce3e84cf48201a06aa8508aa4Jeff Garzik	/* bail out if no device is present */
2261bdd4dddee325a7dce3e84cf48201a06aa8508aa4Jeff Garzik	if (classes[0] == ATA_DEV_NONE && classes[1] == ATA_DEV_NONE) {
2262bdd4dddee325a7dce3e84cf48201a06aa8508aa4Jeff Garzik		DPRINTK("EXIT, no device\n");
2263bdd4dddee325a7dce3e84cf48201a06aa8508aa4Jeff Garzik		return;
22649b358e305c1d783c8a4ebf00344e95deb9e38f3dMark Lord	}
2265bdd4dddee325a7dce3e84cf48201a06aa8508aa4Jeff Garzik
2266bdd4dddee325a7dce3e84cf48201a06aa8508aa4Jeff Garzik	/* set up device control */
2267bdd4dddee325a7dce3e84cf48201a06aa8508aa4Jeff Garzik	iowrite8(ap->ctl, ap->ioaddr.ctl_addr);
2268bdd4dddee325a7dce3e84cf48201a06aa8508aa4Jeff Garzik}
2269bdd4dddee325a7dce3e84cf48201a06aa8508aa4Jeff Garzik
2270bdd4dddee325a7dce3e84cf48201a06aa8508aa4Jeff Garzikstatic void mv_error_handler(struct ata_port *ap)
2271bdd4dddee325a7dce3e84cf48201a06aa8508aa4Jeff Garzik{
2272bdd4dddee325a7dce3e84cf48201a06aa8508aa4Jeff Garzik	ata_do_eh(ap, mv_prereset, ata_std_softreset,
2273bdd4dddee325a7dce3e84cf48201a06aa8508aa4Jeff Garzik		  mv_hardreset, mv_postreset);
2274bdd4dddee325a7dce3e84cf48201a06aa8508aa4Jeff Garzik}
2275bdd4dddee325a7dce3e84cf48201a06aa8508aa4Jeff Garzik
2276bdd4dddee325a7dce3e84cf48201a06aa8508aa4Jeff Garzikstatic void mv_post_int_cmd(struct ata_queued_cmd *qc)
2277bdd4dddee325a7dce3e84cf48201a06aa8508aa4Jeff Garzik{
2278bdd4dddee325a7dce3e84cf48201a06aa8508aa4Jeff Garzik	mv_stop_dma(qc->ap);
2279bdd4dddee325a7dce3e84cf48201a06aa8508aa4Jeff Garzik}
2280bdd4dddee325a7dce3e84cf48201a06aa8508aa4Jeff Garzik
2281bdd4dddee325a7dce3e84cf48201a06aa8508aa4Jeff Garzikstatic void mv_eh_freeze(struct ata_port *ap)
2282bdd4dddee325a7dce3e84cf48201a06aa8508aa4Jeff Garzik{
2283bdd4dddee325a7dce3e84cf48201a06aa8508aa4Jeff Garzik	void __iomem *mmio = ap->host->iomap[MV_PRIMARY_BAR];
2284bdd4dddee325a7dce3e84cf48201a06aa8508aa4Jeff Garzik	unsigned int hc = (ap->port_no > 3) ? 1 : 0;
2285bdd4dddee325a7dce3e84cf48201a06aa8508aa4Jeff Garzik	u32 tmp, mask;
2286bdd4dddee325a7dce3e84cf48201a06aa8508aa4Jeff Garzik	unsigned int shift;
2287bdd4dddee325a7dce3e84cf48201a06aa8508aa4Jeff Garzik
2288bdd4dddee325a7dce3e84cf48201a06aa8508aa4Jeff Garzik	/* FIXME: handle coalescing completion events properly */
2289bdd4dddee325a7dce3e84cf48201a06aa8508aa4Jeff Garzik
2290bdd4dddee325a7dce3e84cf48201a06aa8508aa4Jeff Garzik	shift = ap->port_no * 2;
2291bdd4dddee325a7dce3e84cf48201a06aa8508aa4Jeff Garzik	if (hc > 0)
2292bdd4dddee325a7dce3e84cf48201a06aa8508aa4Jeff Garzik		shift++;
2293bdd4dddee325a7dce3e84cf48201a06aa8508aa4Jeff Garzik
2294bdd4dddee325a7dce3e84cf48201a06aa8508aa4Jeff Garzik	mask = 0x3 << shift;
2295bdd4dddee325a7dce3e84cf48201a06aa8508aa4Jeff Garzik
2296bdd4dddee325a7dce3e84cf48201a06aa8508aa4Jeff Garzik	/* disable assertion of portN err, done events */
2297bdd4dddee325a7dce3e84cf48201a06aa8508aa4Jeff Garzik	tmp = readl(mmio + HC_MAIN_IRQ_MASK_OFS);
2298bdd4dddee325a7dce3e84cf48201a06aa8508aa4Jeff Garzik	writelfl(tmp & ~mask, mmio + HC_MAIN_IRQ_MASK_OFS);
2299bdd4dddee325a7dce3e84cf48201a06aa8508aa4Jeff Garzik}
2300bdd4dddee325a7dce3e84cf48201a06aa8508aa4Jeff Garzik
2301bdd4dddee325a7dce3e84cf48201a06aa8508aa4Jeff Garzikstatic void mv_eh_thaw(struct ata_port *ap)
2302bdd4dddee325a7dce3e84cf48201a06aa8508aa4Jeff Garzik{
2303bdd4dddee325a7dce3e84cf48201a06aa8508aa4Jeff Garzik	void __iomem *mmio = ap->host->iomap[MV_PRIMARY_BAR];
2304bdd4dddee325a7dce3e84cf48201a06aa8508aa4Jeff Garzik	unsigned int hc = (ap->port_no > 3) ? 1 : 0;
2305bdd4dddee325a7dce3e84cf48201a06aa8508aa4Jeff Garzik	void __iomem *hc_mmio = mv_hc_base(mmio, hc);
2306bdd4dddee325a7dce3e84cf48201a06aa8508aa4Jeff Garzik	void __iomem *port_mmio = mv_ap_base(ap);
2307bdd4dddee325a7dce3e84cf48201a06aa8508aa4Jeff Garzik	u32 tmp, mask, hc_irq_cause;
2308bdd4dddee325a7dce3e84cf48201a06aa8508aa4Jeff Garzik	unsigned int shift, hc_port_no = ap->port_no;
2309bdd4dddee325a7dce3e84cf48201a06aa8508aa4Jeff Garzik
2310bdd4dddee325a7dce3e84cf48201a06aa8508aa4Jeff Garzik	/* FIXME: handle coalescing completion events properly */
2311bdd4dddee325a7dce3e84cf48201a06aa8508aa4Jeff Garzik
2312bdd4dddee325a7dce3e84cf48201a06aa8508aa4Jeff Garzik	shift = ap->port_no * 2;
2313bdd4dddee325a7dce3e84cf48201a06aa8508aa4Jeff Garzik	if (hc > 0) {
2314bdd4dddee325a7dce3e84cf48201a06aa8508aa4Jeff Garzik		shift++;
2315bdd4dddee325a7dce3e84cf48201a06aa8508aa4Jeff Garzik		hc_port_no -= 4;
2316bdd4dddee325a7dce3e84cf48201a06aa8508aa4Jeff Garzik	}
2317bdd4dddee325a7dce3e84cf48201a06aa8508aa4Jeff Garzik
2318bdd4dddee325a7dce3e84cf48201a06aa8508aa4Jeff Garzik	mask = 0x3 << shift;
2319bdd4dddee325a7dce3e84cf48201a06aa8508aa4Jeff Garzik
2320bdd4dddee325a7dce3e84cf48201a06aa8508aa4Jeff Garzik	/* clear EDMA errors on this port */
2321bdd4dddee325a7dce3e84cf48201a06aa8508aa4Jeff Garzik	writel(0, port_mmio + EDMA_ERR_IRQ_CAUSE_OFS);
2322bdd4dddee325a7dce3e84cf48201a06aa8508aa4Jeff Garzik
2323bdd4dddee325a7dce3e84cf48201a06aa8508aa4Jeff Garzik	/* clear pending irq events */
2324bdd4dddee325a7dce3e84cf48201a06aa8508aa4Jeff Garzik	hc_irq_cause = readl(hc_mmio + HC_IRQ_CAUSE_OFS);
2325bdd4dddee325a7dce3e84cf48201a06aa8508aa4Jeff Garzik	hc_irq_cause &= ~(1 << hc_port_no);	/* clear CRPB-done */
2326bdd4dddee325a7dce3e84cf48201a06aa8508aa4Jeff Garzik	hc_irq_cause &= ~(1 << (hc_port_no + 8)); /* clear Device int */
2327bdd4dddee325a7dce3e84cf48201a06aa8508aa4Jeff Garzik	writel(hc_irq_cause, hc_mmio + HC_IRQ_CAUSE_OFS);
2328bdd4dddee325a7dce3e84cf48201a06aa8508aa4Jeff Garzik
2329bdd4dddee325a7dce3e84cf48201a06aa8508aa4Jeff Garzik	/* enable assertion of portN err, done events */
2330bdd4dddee325a7dce3e84cf48201a06aa8508aa4Jeff Garzik	tmp = readl(mmio + HC_MAIN_IRQ_MASK_OFS);
2331bdd4dddee325a7dce3e84cf48201a06aa8508aa4Jeff Garzik	writelfl(tmp | mask, mmio + HC_MAIN_IRQ_MASK_OFS);
233231961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ}
233331961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ
233405b308e1df6d9d673daedb517969241f41278b52Brett Russ/**
233505b308e1df6d9d673daedb517969241f41278b52Brett Russ *      mv_port_init - Perform some early initialization on a single port.
233605b308e1df6d9d673daedb517969241f41278b52Brett Russ *      @port: libata data structure storing shadow register addresses
233705b308e1df6d9d673daedb517969241f41278b52Brett Russ *      @port_mmio: base address of the port
233805b308e1df6d9d673daedb517969241f41278b52Brett Russ *
233905b308e1df6d9d673daedb517969241f41278b52Brett Russ *      Initialize shadow register mmio addresses, clear outstanding
234005b308e1df6d9d673daedb517969241f41278b52Brett Russ *      interrupts on the port, and unmask interrupts for the future
234105b308e1df6d9d673daedb517969241f41278b52Brett Russ *      start of the port.
234205b308e1df6d9d673daedb517969241f41278b52Brett Russ *
234305b308e1df6d9d673daedb517969241f41278b52Brett Russ *      LOCKING:
234405b308e1df6d9d673daedb517969241f41278b52Brett Russ *      Inherited from caller.
234505b308e1df6d9d673daedb517969241f41278b52Brett Russ */
234631961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russstatic void mv_port_init(struct ata_ioports *port,  void __iomem *port_mmio)
234720f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ{
23480d5ff566779f894ca9937231a181eb31e4adff0eTejun Heo	void __iomem *shd_base = port_mmio + SHD_BLK_OFS;
234931961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ	unsigned serr_ofs;
235031961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ
23518b260248d9e0e8b64bb72fd4dee03ad86984c344Jeff Garzik	/* PIO related setup
235231961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ	 */
235331961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ	port->data_addr = shd_base + (sizeof(u32) * ATA_REG_DATA);
23548b260248d9e0e8b64bb72fd4dee03ad86984c344Jeff Garzik	port->error_addr =
235531961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ		port->feature_addr = shd_base + (sizeof(u32) * ATA_REG_ERR);
235631961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ	port->nsect_addr = shd_base + (sizeof(u32) * ATA_REG_NSECT);
235731961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ	port->lbal_addr = shd_base + (sizeof(u32) * ATA_REG_LBAL);
235831961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ	port->lbam_addr = shd_base + (sizeof(u32) * ATA_REG_LBAM);
235931961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ	port->lbah_addr = shd_base + (sizeof(u32) * ATA_REG_LBAH);
236031961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ	port->device_addr = shd_base + (sizeof(u32) * ATA_REG_DEVICE);
23618b260248d9e0e8b64bb72fd4dee03ad86984c344Jeff Garzik	port->status_addr =
236231961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ		port->command_addr = shd_base + (sizeof(u32) * ATA_REG_STATUS);
236331961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ	/* special case: control/altstatus doesn't have ATA_REG_ address */
236431961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ	port->altstatus_addr = port->ctl_addr = shd_base + SHD_CTL_AST_OFS;
236531961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ
236631961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ	/* unused: */
23678d9db2d2fbae9e05022825c32f86e00c8e342860Randy Dunlap	port->cmd_addr = port->bmdma_addr = port->scr_addr = NULL;
236820f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ
236931961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ	/* Clear any currently outstanding port interrupt conditions */
237031961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ	serr_ofs = mv_scr_offset(SCR_ERROR);
237131961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ	writelfl(readl(port_mmio + serr_ofs), port_mmio + serr_ofs);
237231961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ	writelfl(0, port_mmio + EDMA_ERR_IRQ_CAUSE_OFS);
237331961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ
237420f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ	/* unmask all EDMA error interrupts */
237531961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ	writelfl(~0, port_mmio + EDMA_ERR_IRQ_MASK_OFS);
237620f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ
23778b260248d9e0e8b64bb72fd4dee03ad86984c344Jeff Garzik	VPRINTK("EDMA cfg=0x%08x EDMA IRQ err cause/mask=0x%08x/0x%08x\n",
237831961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ		readl(port_mmio + EDMA_CFG_OFS),
237931961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ		readl(port_mmio + EDMA_ERR_IRQ_CAUSE_OFS),
238031961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ		readl(port_mmio + EDMA_ERR_IRQ_MASK_OFS));
238120f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ}
238220f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ
23834447d35156169cf136e829eb6b5cac2d6370f2d9Tejun Heostatic int mv_chip_id(struct ata_host *host, unsigned int board_idx)
2384bca1c4eb9411533d613123618c0d127fae532595Jeff Garzik{
23854447d35156169cf136e829eb6b5cac2d6370f2d9Tejun Heo	struct pci_dev *pdev = to_pci_dev(host->dev);
23864447d35156169cf136e829eb6b5cac2d6370f2d9Tejun Heo	struct mv_host_priv *hpriv = host->private_data;
2387bca1c4eb9411533d613123618c0d127fae532595Jeff Garzik	u32 hp_flags = hpriv->hp_flags;
2388bca1c4eb9411533d613123618c0d127fae532595Jeff Garzik
2389bca1c4eb9411533d613123618c0d127fae532595Jeff Garzik	switch(board_idx) {
239047c2b677daeed9c79ecb7167c211ff36876ea611Jeff Garzik	case chip_5080:
239147c2b677daeed9c79ecb7167c211ff36876ea611Jeff Garzik		hpriv->ops = &mv5xxx_ops;
2392ee9ccdf70163ca6408f6965e0fbc65baeac7312cJeff Garzik		hp_flags |= MV_HP_GEN_I;
239347c2b677daeed9c79ecb7167c211ff36876ea611Jeff Garzik
239444c10138fd4bbc4b6d6bff0873c24902f2a9da65Auke Kok		switch (pdev->revision) {
239547c2b677daeed9c79ecb7167c211ff36876ea611Jeff Garzik		case 0x1:
239647c2b677daeed9c79ecb7167c211ff36876ea611Jeff Garzik			hp_flags |= MV_HP_ERRATA_50XXB0;
239747c2b677daeed9c79ecb7167c211ff36876ea611Jeff Garzik			break;
239847c2b677daeed9c79ecb7167c211ff36876ea611Jeff Garzik		case 0x3:
239947c2b677daeed9c79ecb7167c211ff36876ea611Jeff Garzik			hp_flags |= MV_HP_ERRATA_50XXB2;
240047c2b677daeed9c79ecb7167c211ff36876ea611Jeff Garzik			break;
240147c2b677daeed9c79ecb7167c211ff36876ea611Jeff Garzik		default:
240247c2b677daeed9c79ecb7167c211ff36876ea611Jeff Garzik			dev_printk(KERN_WARNING, &pdev->dev,
240347c2b677daeed9c79ecb7167c211ff36876ea611Jeff Garzik			   "Applying 50XXB2 workarounds to unknown rev\n");
240447c2b677daeed9c79ecb7167c211ff36876ea611Jeff Garzik			hp_flags |= MV_HP_ERRATA_50XXB2;
240547c2b677daeed9c79ecb7167c211ff36876ea611Jeff Garzik			break;
240647c2b677daeed9c79ecb7167c211ff36876ea611Jeff Garzik		}
240747c2b677daeed9c79ecb7167c211ff36876ea611Jeff Garzik		break;
240847c2b677daeed9c79ecb7167c211ff36876ea611Jeff Garzik
2409bca1c4eb9411533d613123618c0d127fae532595Jeff Garzik	case chip_504x:
2410bca1c4eb9411533d613123618c0d127fae532595Jeff Garzik	case chip_508x:
241147c2b677daeed9c79ecb7167c211ff36876ea611Jeff Garzik		hpriv->ops = &mv5xxx_ops;
2412ee9ccdf70163ca6408f6965e0fbc65baeac7312cJeff Garzik		hp_flags |= MV_HP_GEN_I;
2413bca1c4eb9411533d613123618c0d127fae532595Jeff Garzik
241444c10138fd4bbc4b6d6bff0873c24902f2a9da65Auke Kok		switch (pdev->revision) {
241547c2b677daeed9c79ecb7167c211ff36876ea611Jeff Garzik		case 0x0:
241647c2b677daeed9c79ecb7167c211ff36876ea611Jeff Garzik			hp_flags |= MV_HP_ERRATA_50XXB0;
241747c2b677daeed9c79ecb7167c211ff36876ea611Jeff Garzik			break;
241847c2b677daeed9c79ecb7167c211ff36876ea611Jeff Garzik		case 0x3:
241947c2b677daeed9c79ecb7167c211ff36876ea611Jeff Garzik			hp_flags |= MV_HP_ERRATA_50XXB2;
242047c2b677daeed9c79ecb7167c211ff36876ea611Jeff Garzik			break;
242147c2b677daeed9c79ecb7167c211ff36876ea611Jeff Garzik		default:
242247c2b677daeed9c79ecb7167c211ff36876ea611Jeff Garzik			dev_printk(KERN_WARNING, &pdev->dev,
242347c2b677daeed9c79ecb7167c211ff36876ea611Jeff Garzik			   "Applying B2 workarounds to unknown rev\n");
242447c2b677daeed9c79ecb7167c211ff36876ea611Jeff Garzik			hp_flags |= MV_HP_ERRATA_50XXB2;
242547c2b677daeed9c79ecb7167c211ff36876ea611Jeff Garzik			break;
2426bca1c4eb9411533d613123618c0d127fae532595Jeff Garzik		}
2427bca1c4eb9411533d613123618c0d127fae532595Jeff Garzik		break;
2428bca1c4eb9411533d613123618c0d127fae532595Jeff Garzik
2429bca1c4eb9411533d613123618c0d127fae532595Jeff Garzik	case chip_604x:
2430bca1c4eb9411533d613123618c0d127fae532595Jeff Garzik	case chip_608x:
243147c2b677daeed9c79ecb7167c211ff36876ea611Jeff Garzik		hpriv->ops = &mv6xxx_ops;
2432ee9ccdf70163ca6408f6965e0fbc65baeac7312cJeff Garzik		hp_flags |= MV_HP_GEN_II;
243347c2b677daeed9c79ecb7167c211ff36876ea611Jeff Garzik
243444c10138fd4bbc4b6d6bff0873c24902f2a9da65Auke Kok		switch (pdev->revision) {
243547c2b677daeed9c79ecb7167c211ff36876ea611Jeff Garzik		case 0x7:
243647c2b677daeed9c79ecb7167c211ff36876ea611Jeff Garzik			hp_flags |= MV_HP_ERRATA_60X1B2;
243747c2b677daeed9c79ecb7167c211ff36876ea611Jeff Garzik			break;
243847c2b677daeed9c79ecb7167c211ff36876ea611Jeff Garzik		case 0x9:
243947c2b677daeed9c79ecb7167c211ff36876ea611Jeff Garzik			hp_flags |= MV_HP_ERRATA_60X1C0;
2440bca1c4eb9411533d613123618c0d127fae532595Jeff Garzik			break;
2441bca1c4eb9411533d613123618c0d127fae532595Jeff Garzik		default:
2442bca1c4eb9411533d613123618c0d127fae532595Jeff Garzik			dev_printk(KERN_WARNING, &pdev->dev,
244347c2b677daeed9c79ecb7167c211ff36876ea611Jeff Garzik				   "Applying B2 workarounds to unknown rev\n");
244447c2b677daeed9c79ecb7167c211ff36876ea611Jeff Garzik			hp_flags |= MV_HP_ERRATA_60X1B2;
2445bca1c4eb9411533d613123618c0d127fae532595Jeff Garzik			break;
2446bca1c4eb9411533d613123618c0d127fae532595Jeff Garzik		}
2447bca1c4eb9411533d613123618c0d127fae532595Jeff Garzik		break;
2448bca1c4eb9411533d613123618c0d127fae532595Jeff Garzik
2449e4e7b89280d1d666e2c09e5ad36cf071796c4c7eJeff Garzik	case chip_7042:
2450e4e7b89280d1d666e2c09e5ad36cf071796c4c7eJeff Garzik	case chip_6042:
2451e4e7b89280d1d666e2c09e5ad36cf071796c4c7eJeff Garzik		hpriv->ops = &mv6xxx_ops;
2452e4e7b89280d1d666e2c09e5ad36cf071796c4c7eJeff Garzik		hp_flags |= MV_HP_GEN_IIE;
2453e4e7b89280d1d666e2c09e5ad36cf071796c4c7eJeff Garzik
245444c10138fd4bbc4b6d6bff0873c24902f2a9da65Auke Kok		switch (pdev->revision) {
2455e4e7b89280d1d666e2c09e5ad36cf071796c4c7eJeff Garzik		case 0x0:
2456e4e7b89280d1d666e2c09e5ad36cf071796c4c7eJeff Garzik			hp_flags |= MV_HP_ERRATA_XX42A0;
2457e4e7b89280d1d666e2c09e5ad36cf071796c4c7eJeff Garzik			break;
2458e4e7b89280d1d666e2c09e5ad36cf071796c4c7eJeff Garzik		case 0x1:
2459e4e7b89280d1d666e2c09e5ad36cf071796c4c7eJeff Garzik			hp_flags |= MV_HP_ERRATA_60X1C0;
2460e4e7b89280d1d666e2c09e5ad36cf071796c4c7eJeff Garzik			break;
2461e4e7b89280d1d666e2c09e5ad36cf071796c4c7eJeff Garzik		default:
2462e4e7b89280d1d666e2c09e5ad36cf071796c4c7eJeff Garzik			dev_printk(KERN_WARNING, &pdev->dev,
2463e4e7b89280d1d666e2c09e5ad36cf071796c4c7eJeff Garzik			   "Applying 60X1C0 workarounds to unknown rev\n");
2464e4e7b89280d1d666e2c09e5ad36cf071796c4c7eJeff Garzik			hp_flags |= MV_HP_ERRATA_60X1C0;
2465e4e7b89280d1d666e2c09e5ad36cf071796c4c7eJeff Garzik			break;
2466e4e7b89280d1d666e2c09e5ad36cf071796c4c7eJeff Garzik		}
2467e4e7b89280d1d666e2c09e5ad36cf071796c4c7eJeff Garzik		break;
2468e4e7b89280d1d666e2c09e5ad36cf071796c4c7eJeff Garzik
2469bca1c4eb9411533d613123618c0d127fae532595Jeff Garzik	default:
2470bca1c4eb9411533d613123618c0d127fae532595Jeff Garzik		printk(KERN_ERR DRV_NAME ": BUG: invalid board index %u\n", board_idx);
2471bca1c4eb9411533d613123618c0d127fae532595Jeff Garzik		return 1;
2472bca1c4eb9411533d613123618c0d127fae532595Jeff Garzik	}
2473bca1c4eb9411533d613123618c0d127fae532595Jeff Garzik
2474bca1c4eb9411533d613123618c0d127fae532595Jeff Garzik	hpriv->hp_flags = hp_flags;
2475bca1c4eb9411533d613123618c0d127fae532595Jeff Garzik
2476bca1c4eb9411533d613123618c0d127fae532595Jeff Garzik	return 0;
2477bca1c4eb9411533d613123618c0d127fae532595Jeff Garzik}
2478bca1c4eb9411533d613123618c0d127fae532595Jeff Garzik
247905b308e1df6d9d673daedb517969241f41278b52Brett Russ/**
248047c2b677daeed9c79ecb7167c211ff36876ea611Jeff Garzik *      mv_init_host - Perform some early initialization of the host.
24814447d35156169cf136e829eb6b5cac2d6370f2d9Tejun Heo *	@host: ATA host to initialize
24824447d35156169cf136e829eb6b5cac2d6370f2d9Tejun Heo *      @board_idx: controller index
248305b308e1df6d9d673daedb517969241f41278b52Brett Russ *
248405b308e1df6d9d673daedb517969241f41278b52Brett Russ *      If possible, do an early global reset of the host.  Then do
248505b308e1df6d9d673daedb517969241f41278b52Brett Russ *      our port init and clear/unmask all/relevant host interrupts.
248605b308e1df6d9d673daedb517969241f41278b52Brett Russ *
248705b308e1df6d9d673daedb517969241f41278b52Brett Russ *      LOCKING:
248805b308e1df6d9d673daedb517969241f41278b52Brett Russ *      Inherited from caller.
248905b308e1df6d9d673daedb517969241f41278b52Brett Russ */
24904447d35156169cf136e829eb6b5cac2d6370f2d9Tejun Heostatic int mv_init_host(struct ata_host *host, unsigned int board_idx)
249120f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ{
249220f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ	int rc = 0, n_hc, port, hc;
24934447d35156169cf136e829eb6b5cac2d6370f2d9Tejun Heo	struct pci_dev *pdev = to_pci_dev(host->dev);
24944447d35156169cf136e829eb6b5cac2d6370f2d9Tejun Heo	void __iomem *mmio = host->iomap[MV_PRIMARY_BAR];
24954447d35156169cf136e829eb6b5cac2d6370f2d9Tejun Heo	struct mv_host_priv *hpriv = host->private_data;
2496bca1c4eb9411533d613123618c0d127fae532595Jeff Garzik
249747c2b677daeed9c79ecb7167c211ff36876ea611Jeff Garzik	/* global interrupt mask */
249847c2b677daeed9c79ecb7167c211ff36876ea611Jeff Garzik	writel(0, mmio + HC_MAIN_IRQ_MASK_OFS);
249947c2b677daeed9c79ecb7167c211ff36876ea611Jeff Garzik
25004447d35156169cf136e829eb6b5cac2d6370f2d9Tejun Heo	rc = mv_chip_id(host, board_idx);
2501bca1c4eb9411533d613123618c0d127fae532595Jeff Garzik	if (rc)
2502bca1c4eb9411533d613123618c0d127fae532595Jeff Garzik		goto done;
2503bca1c4eb9411533d613123618c0d127fae532595Jeff Garzik
25044447d35156169cf136e829eb6b5cac2d6370f2d9Tejun Heo	n_hc = mv_get_hc_count(host->ports[0]->flags);
2505bca1c4eb9411533d613123618c0d127fae532595Jeff Garzik
25064447d35156169cf136e829eb6b5cac2d6370f2d9Tejun Heo	for (port = 0; port < host->n_ports; port++)
250747c2b677daeed9c79ecb7167c211ff36876ea611Jeff Garzik		hpriv->ops->read_preamp(hpriv, port, mmio);
250820f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ
2509c9d39130123238ac18478a42e25cb7996eacfcc0Jeff Garzik	rc = hpriv->ops->reset_hc(hpriv, mmio, n_hc);
251047c2b677daeed9c79ecb7167c211ff36876ea611Jeff Garzik	if (rc)
251120f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ		goto done;
251220f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ
2513522479fb98c6667f081e75f87e298e413c0b1db8Jeff Garzik	hpriv->ops->reset_flash(hpriv, mmio);
2514522479fb98c6667f081e75f87e298e413c0b1db8Jeff Garzik	hpriv->ops->reset_bus(pdev, mmio);
251547c2b677daeed9c79ecb7167c211ff36876ea611Jeff Garzik	hpriv->ops->enable_leds(hpriv, mmio);
251620f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ
25174447d35156169cf136e829eb6b5cac2d6370f2d9Tejun Heo	for (port = 0; port < host->n_ports; port++) {
2518ee9ccdf70163ca6408f6965e0fbc65baeac7312cJeff Garzik		if (IS_GEN_II(hpriv)) {
2519c9d39130123238ac18478a42e25cb7996eacfcc0Jeff Garzik			void __iomem *port_mmio = mv_port_base(mmio, port);
2520c9d39130123238ac18478a42e25cb7996eacfcc0Jeff Garzik
25212a47ce06d534692f9bd2bf4e90a20fc9b1054c39Jeff Garzik			u32 ifctl = readl(port_mmio + SATA_INTERFACE_CTL);
2522eb46d684600ac145501805a294c94675e82eab2eMark Lord			ifctl |= (1 << 7);		/* enable gen2i speed */
2523eb46d684600ac145501805a294c94675e82eab2eMark Lord			ifctl = (ifctl & 0xfff) | 0x9b1000; /* from chip spec */
25242a47ce06d534692f9bd2bf4e90a20fc9b1054c39Jeff Garzik			writelfl(ifctl, port_mmio + SATA_INTERFACE_CTL);
25252a47ce06d534692f9bd2bf4e90a20fc9b1054c39Jeff Garzik		}
25262a47ce06d534692f9bd2bf4e90a20fc9b1054c39Jeff Garzik
2527c9d39130123238ac18478a42e25cb7996eacfcc0Jeff Garzik		hpriv->ops->phy_errata(hpriv, mmio, port);
25282a47ce06d534692f9bd2bf4e90a20fc9b1054c39Jeff Garzik	}
25292a47ce06d534692f9bd2bf4e90a20fc9b1054c39Jeff Garzik
25304447d35156169cf136e829eb6b5cac2d6370f2d9Tejun Heo	for (port = 0; port < host->n_ports; port++) {
25312a47ce06d534692f9bd2bf4e90a20fc9b1054c39Jeff Garzik		void __iomem *port_mmio = mv_port_base(mmio, port);
25324447d35156169cf136e829eb6b5cac2d6370f2d9Tejun Heo		mv_port_init(&host->ports[port]->ioaddr, port_mmio);
253320f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ	}
253420f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ
253520f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ	for (hc = 0; hc < n_hc; hc++) {
253631961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ		void __iomem *hc_mmio = mv_hc_base(mmio, hc);
253731961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ
253831961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ		VPRINTK("HC%i: HC config=0x%08x HC IRQ cause "
253931961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ			"(before clear)=0x%08x\n", hc,
254031961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ			readl(hc_mmio + HC_CFG_OFS),
254131961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ			readl(hc_mmio + HC_IRQ_CAUSE_OFS));
254231961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ
254331961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ		/* Clear any currently outstanding hc interrupt conditions */
254431961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ		writelfl(0, hc_mmio + HC_IRQ_CAUSE_OFS);
254520f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ	}
254620f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ
254731961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ	/* Clear any currently outstanding host interrupt conditions */
254831961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ	writelfl(0, mmio + PCI_IRQ_CAUSE_OFS);
254931961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ
255031961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ	/* and unmask interrupt generation for host regs */
255131961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ	writelfl(PCI_UNMASK_ALL_IRQS, mmio + PCI_IRQ_MASK_OFS);
2552fb621e2fde735abab854586d52c96c5624bcb5b8Jeff Garzik
2553ee9ccdf70163ca6408f6965e0fbc65baeac7312cJeff Garzik	if (IS_GEN_I(hpriv))
2554fb621e2fde735abab854586d52c96c5624bcb5b8Jeff Garzik		writelfl(~HC_MAIN_MASKED_IRQS_5, mmio + HC_MAIN_IRQ_MASK_OFS);
2555fb621e2fde735abab854586d52c96c5624bcb5b8Jeff Garzik	else
2556fb621e2fde735abab854586d52c96c5624bcb5b8Jeff Garzik		writelfl(~HC_MAIN_MASKED_IRQS, mmio + HC_MAIN_IRQ_MASK_OFS);
255720f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ
255820f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ	VPRINTK("HC MAIN IRQ cause/mask=0x%08x/0x%08x "
25598b260248d9e0e8b64bb72fd4dee03ad86984c344Jeff Garzik		"PCI int cause/mask=0x%08x/0x%08x\n",
256020f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ		readl(mmio + HC_MAIN_IRQ_CAUSE_OFS),
256120f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ		readl(mmio + HC_MAIN_IRQ_MASK_OFS),
256220f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ		readl(mmio + PCI_IRQ_CAUSE_OFS),
256320f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ		readl(mmio + PCI_IRQ_MASK_OFS));
2564bca1c4eb9411533d613123618c0d127fae532595Jeff Garzik
256531961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russdone:
256620f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ	return rc;
256720f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ}
256820f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ
256905b308e1df6d9d673daedb517969241f41278b52Brett Russ/**
257005b308e1df6d9d673daedb517969241f41278b52Brett Russ *      mv_print_info - Dump key info to kernel log for perusal.
25714447d35156169cf136e829eb6b5cac2d6370f2d9Tejun Heo *      @host: ATA host to print info about
257205b308e1df6d9d673daedb517969241f41278b52Brett Russ *
257305b308e1df6d9d673daedb517969241f41278b52Brett Russ *      FIXME: complete this.
257405b308e1df6d9d673daedb517969241f41278b52Brett Russ *
257505b308e1df6d9d673daedb517969241f41278b52Brett Russ *      LOCKING:
257605b308e1df6d9d673daedb517969241f41278b52Brett Russ *      Inherited from caller.
257705b308e1df6d9d673daedb517969241f41278b52Brett Russ */
25784447d35156169cf136e829eb6b5cac2d6370f2d9Tejun Heostatic void mv_print_info(struct ata_host *host)
257931961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ{
25804447d35156169cf136e829eb6b5cac2d6370f2d9Tejun Heo	struct pci_dev *pdev = to_pci_dev(host->dev);
25814447d35156169cf136e829eb6b5cac2d6370f2d9Tejun Heo	struct mv_host_priv *hpriv = host->private_data;
258244c10138fd4bbc4b6d6bff0873c24902f2a9da65Auke Kok	u8 scc;
2583c1e4fe711a410a139095e6b3e3ce3f07f466063cJeff Garzik	const char *scc_s, *gen;
258431961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ
258531961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ	/* Use this to determine the HW stepping of the chip so we know
258631961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ	 * what errata to workaround
258731961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ	 */
258831961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ	pci_read_config_byte(pdev, PCI_CLASS_DEVICE, &scc);
258931961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ	if (scc == 0)
259031961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ		scc_s = "SCSI";
259131961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ	else if (scc == 0x01)
259231961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ		scc_s = "RAID";
259331961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ	else
2594c1e4fe711a410a139095e6b3e3ce3f07f466063cJeff Garzik		scc_s = "?";
2595c1e4fe711a410a139095e6b3e3ce3f07f466063cJeff Garzik
2596c1e4fe711a410a139095e6b3e3ce3f07f466063cJeff Garzik	if (IS_GEN_I(hpriv))
2597c1e4fe711a410a139095e6b3e3ce3f07f466063cJeff Garzik		gen = "I";
2598c1e4fe711a410a139095e6b3e3ce3f07f466063cJeff Garzik	else if (IS_GEN_II(hpriv))
2599c1e4fe711a410a139095e6b3e3ce3f07f466063cJeff Garzik		gen = "II";
2600c1e4fe711a410a139095e6b3e3ce3f07f466063cJeff Garzik	else if (IS_GEN_IIE(hpriv))
2601c1e4fe711a410a139095e6b3e3ce3f07f466063cJeff Garzik		gen = "IIE";
2602c1e4fe711a410a139095e6b3e3ce3f07f466063cJeff Garzik	else
2603c1e4fe711a410a139095e6b3e3ce3f07f466063cJeff Garzik		gen = "?";
260431961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ
2605a9524a76f70f3343e4be27f95a7e92a8ba5f9009Jeff Garzik	dev_printk(KERN_INFO, &pdev->dev,
2606c1e4fe711a410a139095e6b3e3ce3f07f466063cJeff Garzik	       "Gen-%s %u slots %u ports %s mode IRQ via %s\n",
2607c1e4fe711a410a139095e6b3e3ce3f07f466063cJeff Garzik	       gen, (unsigned)MV_MAX_Q_DEPTH, host->n_ports,
260831961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ	       scc_s, (MV_HP_FLAG_MSI & hpriv->hp_flags) ? "MSI" : "INTx");
260931961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ}
261031961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ
261105b308e1df6d9d673daedb517969241f41278b52Brett Russ/**
261205b308e1df6d9d673daedb517969241f41278b52Brett Russ *      mv_init_one - handle a positive probe of a Marvell host
261305b308e1df6d9d673daedb517969241f41278b52Brett Russ *      @pdev: PCI device found
261405b308e1df6d9d673daedb517969241f41278b52Brett Russ *      @ent: PCI device ID entry for the matched host
261505b308e1df6d9d673daedb517969241f41278b52Brett Russ *
261605b308e1df6d9d673daedb517969241f41278b52Brett Russ *      LOCKING:
261705b308e1df6d9d673daedb517969241f41278b52Brett Russ *      Inherited from caller.
261805b308e1df6d9d673daedb517969241f41278b52Brett Russ */
261920f733e7d75a16bffc34842b7682c9247dd5f954Brett Russstatic int mv_init_one(struct pci_dev *pdev, const struct pci_device_id *ent)
262020f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ{
262120f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ	static int printed_version = 0;
262220f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ	unsigned int board_idx = (unsigned int)ent->driver_data;
26234447d35156169cf136e829eb6b5cac2d6370f2d9Tejun Heo	const struct ata_port_info *ppi[] = { &mv_port_info[board_idx], NULL };
26244447d35156169cf136e829eb6b5cac2d6370f2d9Tejun Heo	struct ata_host *host;
26254447d35156169cf136e829eb6b5cac2d6370f2d9Tejun Heo	struct mv_host_priv *hpriv;
26264447d35156169cf136e829eb6b5cac2d6370f2d9Tejun Heo	int n_ports, rc;
262720f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ
2628a9524a76f70f3343e4be27f95a7e92a8ba5f9009Jeff Garzik	if (!printed_version++)
2629a9524a76f70f3343e4be27f95a7e92a8ba5f9009Jeff Garzik		dev_printk(KERN_INFO, &pdev->dev, "version " DRV_VERSION "\n");
263020f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ
26314447d35156169cf136e829eb6b5cac2d6370f2d9Tejun Heo	/* allocate host */
26324447d35156169cf136e829eb6b5cac2d6370f2d9Tejun Heo	n_ports = mv_get_hc_count(ppi[0]->flags) * MV_PORTS_PER_HC;
26334447d35156169cf136e829eb6b5cac2d6370f2d9Tejun Heo
26344447d35156169cf136e829eb6b5cac2d6370f2d9Tejun Heo	host = ata_host_alloc_pinfo(&pdev->dev, ppi, n_ports);
26354447d35156169cf136e829eb6b5cac2d6370f2d9Tejun Heo	hpriv = devm_kzalloc(&pdev->dev, sizeof(*hpriv), GFP_KERNEL);
26364447d35156169cf136e829eb6b5cac2d6370f2d9Tejun Heo	if (!host || !hpriv)
26374447d35156169cf136e829eb6b5cac2d6370f2d9Tejun Heo		return -ENOMEM;
26384447d35156169cf136e829eb6b5cac2d6370f2d9Tejun Heo	host->private_data = hpriv;
26394447d35156169cf136e829eb6b5cac2d6370f2d9Tejun Heo
26404447d35156169cf136e829eb6b5cac2d6370f2d9Tejun Heo	/* acquire resources */
264124dc5f33ea4b504cfbd23fa159a4cacba8e4d800Tejun Heo	rc = pcim_enable_device(pdev);
264224dc5f33ea4b504cfbd23fa159a4cacba8e4d800Tejun Heo	if (rc)
264320f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ		return rc;
264420f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ
26450d5ff566779f894ca9937231a181eb31e4adff0eTejun Heo	rc = pcim_iomap_regions(pdev, 1 << MV_PRIMARY_BAR, DRV_NAME);
26460d5ff566779f894ca9937231a181eb31e4adff0eTejun Heo	if (rc == -EBUSY)
264724dc5f33ea4b504cfbd23fa159a4cacba8e4d800Tejun Heo		pcim_pin_device(pdev);
26480d5ff566779f894ca9937231a181eb31e4adff0eTejun Heo	if (rc)
264924dc5f33ea4b504cfbd23fa159a4cacba8e4d800Tejun Heo		return rc;
26504447d35156169cf136e829eb6b5cac2d6370f2d9Tejun Heo	host->iomap = pcim_iomap_table(pdev);
265120f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ
2652d88184fb2348a50f7c34f5d49a901c875b2e0114Jeff Garzik	rc = pci_go_64(pdev);
2653d88184fb2348a50f7c34f5d49a901c875b2e0114Jeff Garzik	if (rc)
2654d88184fb2348a50f7c34f5d49a901c875b2e0114Jeff Garzik		return rc;
2655d88184fb2348a50f7c34f5d49a901c875b2e0114Jeff Garzik
265620f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ	/* initialize adapter */
26574447d35156169cf136e829eb6b5cac2d6370f2d9Tejun Heo	rc = mv_init_host(host, board_idx);
265824dc5f33ea4b504cfbd23fa159a4cacba8e4d800Tejun Heo	if (rc)
265924dc5f33ea4b504cfbd23fa159a4cacba8e4d800Tejun Heo		return rc;
266020f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ
266131961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ	/* Enable interrupts */
26626a59dcf8678cbc4106a8a6e158d7408a87691358Tejun Heo	if (msi && pci_enable_msi(pdev))
266331961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ		pci_intx(pdev, 1);
266420f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ
266531961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ	mv_dump_pci_cfg(pdev, 0x68);
26664447d35156169cf136e829eb6b5cac2d6370f2d9Tejun Heo	mv_print_info(host);
266720f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ
26684447d35156169cf136e829eb6b5cac2d6370f2d9Tejun Heo	pci_set_master(pdev);
2669ea8b4db97aa41a66c05daa4055a1974692ccd52dJeff Garzik	pci_try_set_mwi(pdev);
26704447d35156169cf136e829eb6b5cac2d6370f2d9Tejun Heo	return ata_host_activate(host, pdev->irq, mv_interrupt, IRQF_SHARED,
2671c5d3e45a2200a0905dc45b72714726b7aac3aaf1Jeff Garzik				 IS_GEN_I(hpriv) ? &mv5_sht : &mv6_sht);
267220f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ}
267320f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ
267420f733e7d75a16bffc34842b7682c9247dd5f954Brett Russstatic int __init mv_init(void)
267520f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ{
2676b7887196e38da54ff893897b80875d632d1a1114Pavel Roskin	return pci_register_driver(&mv_pci_driver);
267720f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ}
267820f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ
267920f733e7d75a16bffc34842b7682c9247dd5f954Brett Russstatic void __exit mv_exit(void)
268020f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ{
268120f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ	pci_unregister_driver(&mv_pci_driver);
268220f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ}
268320f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ
268420f733e7d75a16bffc34842b7682c9247dd5f954Brett RussMODULE_AUTHOR("Brett Russ");
268520f733e7d75a16bffc34842b7682c9247dd5f954Brett RussMODULE_DESCRIPTION("SCSI low-level driver for Marvell SATA controllers");
268620f733e7d75a16bffc34842b7682c9247dd5f954Brett RussMODULE_LICENSE("GPL");
268720f733e7d75a16bffc34842b7682c9247dd5f954Brett RussMODULE_DEVICE_TABLE(pci, mv_pci_tbl);
268820f733e7d75a16bffc34842b7682c9247dd5f954Brett RussMODULE_VERSION(DRV_VERSION);
268920f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ
2690ddef9bb367b19383df627e388cb4c01c86ddba6cJeff Garzikmodule_param(msi, int, 0444);
2691ddef9bb367b19383df627e388cb4c01c86ddba6cJeff GarzikMODULE_PARM_DESC(msi, "Enable use of PCI MSI (0=off, 1=on)");
2692ddef9bb367b19383df627e388cb4c01c86ddba6cJeff Garzik
269320f733e7d75a16bffc34842b7682c9247dd5f954Brett Russmodule_init(mv_init);
269420f733e7d75a16bffc34842b7682c9247dd5f954Brett Russmodule_exit(mv_exit);
2695