sata_mv.c revision 0c58912e192fc3a4835d772aafa40b72552b819f
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  8) Develop a low-power-consumption strategy, and implement it.
394a05e2091709dbb22b86a1b3343cd3fa3c0d7a6bJeff Garzik
404a05e2091709dbb22b86a1b3343cd3fa3c0d7a6bJeff Garzik  9) [Experiment, low priority] See if ATAPI can be supported using
414a05e2091709dbb22b86a1b3343cd3fa3c0d7a6bJeff Garzik  "unknown FIS" or "vendor-specific FIS" support, or something creative
424a05e2091709dbb22b86a1b3343cd3fa3c0d7a6bJeff Garzik  like that.
434a05e2091709dbb22b86a1b3343cd3fa3c0d7a6bJeff Garzik
444a05e2091709dbb22b86a1b3343cd3fa3c0d7a6bJeff Garzik  10) [Experiment, low priority] Investigate interrupt coalescing.
454a05e2091709dbb22b86a1b3343cd3fa3c0d7a6bJeff Garzik  Quite often, especially with PCI Message Signalled Interrupts (MSI),
464a05e2091709dbb22b86a1b3343cd3fa3c0d7a6bJeff Garzik  the overhead reduced by interrupt mitigation is quite often not
474a05e2091709dbb22b86a1b3343cd3fa3c0d7a6bJeff Garzik  worth the latency cost.
484a05e2091709dbb22b86a1b3343cd3fa3c0d7a6bJeff Garzik
494a05e2091709dbb22b86a1b3343cd3fa3c0d7a6bJeff Garzik  11) [Experiment, Marvell value added] Is it possible to use target
504a05e2091709dbb22b86a1b3343cd3fa3c0d7a6bJeff Garzik  mode to cross-connect two Linux boxes with Marvell cards?  If so,
514a05e2091709dbb22b86a1b3343cd3fa3c0d7a6bJeff Garzik  creating LibATA target mode support would be very interesting.
524a05e2091709dbb22b86a1b3343cd3fa3c0d7a6bJeff Garzik
534a05e2091709dbb22b86a1b3343cd3fa3c0d7a6bJeff Garzik  Target mode, for those without docs, is the ability to directly
544a05e2091709dbb22b86a1b3343cd3fa3c0d7a6bJeff Garzik  connect two SATA controllers.
554a05e2091709dbb22b86a1b3343cd3fa3c0d7a6bJeff Garzik
564a05e2091709dbb22b86a1b3343cd3fa3c0d7a6bJeff Garzik  13) Verify that 7042 is fully supported.  I only have a 6042.
574a05e2091709dbb22b86a1b3343cd3fa3c0d7a6bJeff Garzik
584a05e2091709dbb22b86a1b3343cd3fa3c0d7a6bJeff Garzik*/
594a05e2091709dbb22b86a1b3343cd3fa3c0d7a6bJeff Garzik
604a05e2091709dbb22b86a1b3343cd3fa3c0d7a6bJeff Garzik
6120f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ#include <linux/kernel.h>
6220f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ#include <linux/module.h>
6320f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ#include <linux/pci.h>
6420f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ#include <linux/init.h>
6520f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ#include <linux/blkdev.h>
6620f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ#include <linux/delay.h>
6720f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ#include <linux/interrupt.h>
6820f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ#include <linux/dma-mapping.h>
69a9524a76f70f3343e4be27f95a7e92a8ba5f9009Jeff Garzik#include <linux/device.h>
7020f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ#include <scsi/scsi_host.h>
71193515d51ccb363165d6b09e9ba5c21089e34badJeff Garzik#include <scsi/scsi_cmnd.h>
726c08772e49622e90d39903e7ff0be1a0f463ac86Jeff Garzik#include <scsi/scsi_device.h>
7320f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ#include <linux/libata.h>
7420f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ
7520f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ#define DRV_NAME	"sata_mv"
766c08772e49622e90d39903e7ff0be1a0f463ac86Jeff Garzik#define DRV_VERSION	"1.01"
7720f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ
7820f733e7d75a16bffc34842b7682c9247dd5f954Brett Russenum {
7920f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ	/* BAR's are enumerated in terms of pci_resource_start() terms */
8020f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ	MV_PRIMARY_BAR		= 0,	/* offset 0x10: memory space */
8120f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ	MV_IO_BAR		= 2,	/* offset 0x18: IO space */
8220f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ	MV_MISC_BAR		= 3,	/* offset 0x1c: FLASH, NVRAM, SRAM */
8320f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ
8420f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ	MV_MAJOR_REG_AREA_SZ	= 0x10000,	/* 64KB */
8520f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ	MV_MINOR_REG_AREA_SZ	= 0x2000,	/* 8KB */
8620f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ
8720f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ	MV_PCI_REG_BASE		= 0,
8820f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ	MV_IRQ_COAL_REG_BASE	= 0x18000,	/* 6xxx part only */
89615ab95342f6245026d8974b9724f7ea57d9a184Mark Lord	MV_IRQ_COAL_CAUSE		= (MV_IRQ_COAL_REG_BASE + 0x08),
90615ab95342f6245026d8974b9724f7ea57d9a184Mark Lord	MV_IRQ_COAL_CAUSE_LO		= (MV_IRQ_COAL_REG_BASE + 0x88),
91615ab95342f6245026d8974b9724f7ea57d9a184Mark Lord	MV_IRQ_COAL_CAUSE_HI		= (MV_IRQ_COAL_REG_BASE + 0x8c),
92615ab95342f6245026d8974b9724f7ea57d9a184Mark Lord	MV_IRQ_COAL_THRESHOLD		= (MV_IRQ_COAL_REG_BASE + 0xcc),
93615ab95342f6245026d8974b9724f7ea57d9a184Mark Lord	MV_IRQ_COAL_TIME_THRESHOLD	= (MV_IRQ_COAL_REG_BASE + 0xd0),
94615ab95342f6245026d8974b9724f7ea57d9a184Mark Lord
9520f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ	MV_SATAHC0_REG_BASE	= 0x20000,
96522479fb98c6667f081e75f87e298e413c0b1db8Jeff Garzik	MV_FLASH_CTL		= 0x1046c,
97bca1c4eb9411533d613123618c0d127fae532595Jeff Garzik	MV_GPIO_PORT_CTL	= 0x104f0,
98bca1c4eb9411533d613123618c0d127fae532595Jeff Garzik	MV_RESET_CFG		= 0x180d8,
9920f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ
10020f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ	MV_PCI_REG_SZ		= MV_MAJOR_REG_AREA_SZ,
10120f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ	MV_SATAHC_REG_SZ	= MV_MAJOR_REG_AREA_SZ,
10220f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ	MV_SATAHC_ARBTR_REG_SZ	= MV_MINOR_REG_AREA_SZ,		/* arbiter */
10320f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ	MV_PORT_REG_SZ		= MV_MINOR_REG_AREA_SZ,
10420f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ
10531961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ	MV_MAX_Q_DEPTH		= 32,
10631961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ	MV_MAX_Q_DEPTH_MASK	= MV_MAX_Q_DEPTH - 1,
10731961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ
10831961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ	/* CRQB needs alignment on a 1KB boundary. Size == 1KB
10931961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ	 * CRPB needs alignment on a 256B boundary. Size == 256B
11031961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ	 * SG count of 176 leads to MV_PORT_PRIV_DMA_SZ == 4KB
11131961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ	 * ePRD (SG) entries need alignment on a 16B boundary. Size == 16B
11231961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ	 */
11331961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ	MV_CRQB_Q_SZ		= (32 * MV_MAX_Q_DEPTH),
11431961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ	MV_CRPB_Q_SZ		= (8 * MV_MAX_Q_DEPTH),
11531961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ	MV_MAX_SG_CT		= 176,
11631961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ	MV_SG_TBL_SZ		= (16 * MV_MAX_SG_CT),
11731961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ	MV_PORT_PRIV_DMA_SZ	= (MV_CRQB_Q_SZ + MV_CRPB_Q_SZ + MV_SG_TBL_SZ),
11831961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ
11920f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ	MV_PORTS_PER_HC		= 4,
12020f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ	/* == (port / MV_PORTS_PER_HC) to determine HC from 0-7 port */
12120f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ	MV_PORT_HC_SHIFT	= 2,
12231961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ	/* == (port % MV_PORTS_PER_HC) to determine hard port from 0-7 port */
12320f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ	MV_PORT_MASK		= 3,
12420f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ
12520f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ	/* Host Flags */
12620f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ	MV_FLAG_DUAL_HC		= (1 << 30),  /* two SATA Host Controllers */
12720f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ	MV_FLAG_IRQ_COALESCE	= (1 << 29),  /* IRQ coalescing capability */
128c5d3e45a2200a0905dc45b72714726b7aac3aaf1Jeff Garzik	MV_COMMON_FLAGS		= ATA_FLAG_SATA | ATA_FLAG_NO_LEGACY |
129bdd4dddee325a7dce3e84cf48201a06aa8508aa4Jeff Garzik				  ATA_FLAG_MMIO | ATA_FLAG_NO_ATAPI |
130bdd4dddee325a7dce3e84cf48201a06aa8508aa4Jeff Garzik				  ATA_FLAG_PIO_POLLING,
13147c2b677daeed9c79ecb7167c211ff36876ea611Jeff Garzik	MV_6XXX_FLAGS		= MV_FLAG_IRQ_COALESCE,
13220f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ
13331961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ	CRQB_FLAG_READ		= (1 << 0),
13431961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ	CRQB_TAG_SHIFT		= 1,
135c5d3e45a2200a0905dc45b72714726b7aac3aaf1Jeff Garzik	CRQB_IOID_SHIFT		= 6,	/* CRQB Gen-II/IIE IO Id shift */
136c5d3e45a2200a0905dc45b72714726b7aac3aaf1Jeff Garzik	CRQB_HOSTQ_SHIFT	= 17,	/* CRQB Gen-II/IIE HostQueTag shift */
13731961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ	CRQB_CMD_ADDR_SHIFT	= 8,
13831961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ	CRQB_CMD_CS		= (0x2 << 11),
13931961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ	CRQB_CMD_LAST		= (1 << 15),
14031961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ
14131961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ	CRPB_FLAG_STATUS_SHIFT	= 8,
142c5d3e45a2200a0905dc45b72714726b7aac3aaf1Jeff Garzik	CRPB_IOID_SHIFT_6	= 5,	/* CRPB Gen-II IO Id shift */
143c5d3e45a2200a0905dc45b72714726b7aac3aaf1Jeff Garzik	CRPB_IOID_SHIFT_7	= 7,	/* CRPB Gen-IIE IO Id shift */
14431961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ
14531961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ	EPRD_FLAG_END_OF_TBL	= (1 << 31),
14631961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ
14720f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ	/* PCI interface registers */
14820f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ
14931961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ	PCI_COMMAND_OFS		= 0xc00,
15031961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ
15120f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ	PCI_MAIN_CMD_STS_OFS	= 0xd30,
15220f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ	STOP_PCI_MASTER		= (1 << 2),
15320f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ	PCI_MASTER_EMPTY	= (1 << 3),
15420f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ	GLOB_SFT_RST		= (1 << 4),
15520f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ
156522479fb98c6667f081e75f87e298e413c0b1db8Jeff Garzik	MV_PCI_MODE		= 0xd00,
157522479fb98c6667f081e75f87e298e413c0b1db8Jeff Garzik	MV_PCI_EXP_ROM_BAR_CTL	= 0xd2c,
158522479fb98c6667f081e75f87e298e413c0b1db8Jeff Garzik	MV_PCI_DISC_TIMER	= 0xd04,
159522479fb98c6667f081e75f87e298e413c0b1db8Jeff Garzik	MV_PCI_MSI_TRIGGER	= 0xc38,
160522479fb98c6667f081e75f87e298e413c0b1db8Jeff Garzik	MV_PCI_SERR_MASK	= 0xc28,
161522479fb98c6667f081e75f87e298e413c0b1db8Jeff Garzik	MV_PCI_XBAR_TMOUT	= 0x1d04,
162522479fb98c6667f081e75f87e298e413c0b1db8Jeff Garzik	MV_PCI_ERR_LOW_ADDRESS	= 0x1d40,
163522479fb98c6667f081e75f87e298e413c0b1db8Jeff Garzik	MV_PCI_ERR_HIGH_ADDRESS	= 0x1d44,
164522479fb98c6667f081e75f87e298e413c0b1db8Jeff Garzik	MV_PCI_ERR_ATTRIBUTE	= 0x1d48,
165522479fb98c6667f081e75f87e298e413c0b1db8Jeff Garzik	MV_PCI_ERR_COMMAND	= 0x1d50,
166522479fb98c6667f081e75f87e298e413c0b1db8Jeff Garzik
16702a121da5a53d415b6596bc19cc6999d295d32a4Mark Lord	PCI_IRQ_CAUSE_OFS	= 0x1d58,
16802a121da5a53d415b6596bc19cc6999d295d32a4Mark Lord	PCI_IRQ_MASK_OFS	= 0x1d5c,
16920f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ	PCI_UNMASK_ALL_IRQS	= 0x7fffff,	/* bits 22-0 */
17020f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ
17102a121da5a53d415b6596bc19cc6999d295d32a4Mark Lord	PCIE_IRQ_CAUSE_OFS	= 0x1900,
17202a121da5a53d415b6596bc19cc6999d295d32a4Mark Lord	PCIE_IRQ_MASK_OFS	= 0x1910,
173646a4da514f2555298481cb00dc5b3eb02b21b72Mark Lord	PCIE_UNMASK_ALL_IRQS	= 0x40a,	/* assorted bits */
17402a121da5a53d415b6596bc19cc6999d295d32a4Mark Lord
17520f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ	HC_MAIN_IRQ_CAUSE_OFS	= 0x1d60,
17620f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ	HC_MAIN_IRQ_MASK_OFS	= 0x1d64,
17720f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ	PORT0_ERR		= (1 << 0),	/* shift by port # */
17820f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ	PORT0_DONE		= (1 << 1),	/* shift by port # */
17920f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ	HC0_IRQ_PEND		= 0x1ff,	/* bits 0-8 = HC0's ports */
18020f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ	HC_SHIFT		= 9,		/* bits 9-17 = HC1's ports */
18120f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ	PCI_ERR			= (1 << 18),
18220f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ	TRAN_LO_DONE		= (1 << 19),	/* 6xxx: IRQ coalescing */
18320f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ	TRAN_HI_DONE		= (1 << 20),	/* 6xxx: IRQ coalescing */
184fb621e2fde735abab854586d52c96c5624bcb5b8Jeff Garzik	PORTS_0_3_COAL_DONE	= (1 << 8),
185fb621e2fde735abab854586d52c96c5624bcb5b8Jeff Garzik	PORTS_4_7_COAL_DONE	= (1 << 17),
18620f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ	PORTS_0_7_COAL_DONE	= (1 << 21),	/* 6xxx: IRQ coalescing */
18720f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ	GPIO_INT		= (1 << 22),
18820f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ	SELF_INT		= (1 << 23),
18920f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ	TWSI_INT		= (1 << 24),
19020f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ	HC_MAIN_RSVD		= (0x7f << 25),	/* bits 31-25 */
191fb621e2fde735abab854586d52c96c5624bcb5b8Jeff Garzik	HC_MAIN_RSVD_5		= (0x1fff << 19), /* bits 31-19 */
1928b260248d9e0e8b64bb72fd4dee03ad86984c344Jeff Garzik	HC_MAIN_MASKED_IRQS	= (TRAN_LO_DONE | TRAN_HI_DONE |
19320f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ				   PORTS_0_7_COAL_DONE | GPIO_INT | TWSI_INT |
19420f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ				   HC_MAIN_RSVD),
195fb621e2fde735abab854586d52c96c5624bcb5b8Jeff Garzik	HC_MAIN_MASKED_IRQS_5	= (PORTS_0_3_COAL_DONE | PORTS_4_7_COAL_DONE |
196fb621e2fde735abab854586d52c96c5624bcb5b8Jeff Garzik				   HC_MAIN_RSVD_5),
19720f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ
19820f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ	/* SATAHC registers */
19920f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ	HC_CFG_OFS		= 0,
20020f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ
20120f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ	HC_IRQ_CAUSE_OFS	= 0x14,
20231961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ	CRPB_DMA_DONE		= (1 << 0),	/* shift by port # */
20320f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ	HC_IRQ_COAL		= (1 << 4),	/* IRQ coalescing */
20420f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ	DEV_IRQ			= (1 << 8),	/* shift by port # */
20520f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ
20620f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ	/* Shadow block registers */
20731961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ	SHD_BLK_OFS		= 0x100,
20831961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ	SHD_CTL_AST_OFS		= 0x20,		/* ofs from SHD_BLK_OFS */
20920f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ
21020f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ	/* SATA registers */
21120f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ	SATA_STATUS_OFS		= 0x300,  /* ctrl, err regs follow status */
21220f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ	SATA_ACTIVE_OFS		= 0x350,
2130c58912e192fc3a4835d772aafa40b72552b819fMark Lord	SATA_FIS_IRQ_CAUSE_OFS	= 0x364,
21447c2b677daeed9c79ecb7167c211ff36876ea611Jeff Garzik	PHY_MODE3		= 0x310,
215bca1c4eb9411533d613123618c0d127fae532595Jeff Garzik	PHY_MODE4		= 0x314,
216bca1c4eb9411533d613123618c0d127fae532595Jeff Garzik	PHY_MODE2		= 0x330,
217c9d39130123238ac18478a42e25cb7996eacfcc0Jeff Garzik	MV5_PHY_MODE		= 0x74,
218c9d39130123238ac18478a42e25cb7996eacfcc0Jeff Garzik	MV5_LT_MODE		= 0x30,
219c9d39130123238ac18478a42e25cb7996eacfcc0Jeff Garzik	MV5_PHY_CTL		= 0x0C,
220bca1c4eb9411533d613123618c0d127fae532595Jeff Garzik	SATA_INTERFACE_CTL	= 0x050,
221bca1c4eb9411533d613123618c0d127fae532595Jeff Garzik
222bca1c4eb9411533d613123618c0d127fae532595Jeff Garzik	MV_M2_PREAMP_MASK	= 0x7e0,
22320f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ
22420f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ	/* Port registers */
22520f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ	EDMA_CFG_OFS		= 0,
2260c58912e192fc3a4835d772aafa40b72552b819fMark Lord	EDMA_CFG_Q_DEPTH	= 0x1f,		/* max device queue depth */
2270c58912e192fc3a4835d772aafa40b72552b819fMark Lord	EDMA_CFG_NCQ		= (1 << 5),	/* for R/W FPDMA queued */
2280c58912e192fc3a4835d772aafa40b72552b819fMark Lord	EDMA_CFG_NCQ_GO_ON_ERR	= (1 << 14),	/* continue on error */
2290c58912e192fc3a4835d772aafa40b72552b819fMark Lord	EDMA_CFG_RD_BRST_EXT	= (1 << 11),	/* read burst 512B */
2300c58912e192fc3a4835d772aafa40b72552b819fMark Lord	EDMA_CFG_WR_BUFF_LEN	= (1 << 13),	/* write buffer 512B */
23120f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ
23220f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ	EDMA_ERR_IRQ_CAUSE_OFS	= 0x8,
23320f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ	EDMA_ERR_IRQ_MASK_OFS	= 0xc,
2346c1153e00af8de755ec278d873a97c9ce2a72d10Jeff Garzik	EDMA_ERR_D_PAR		= (1 << 0),	/* UDMA data parity err */
2356c1153e00af8de755ec278d873a97c9ce2a72d10Jeff Garzik	EDMA_ERR_PRD_PAR	= (1 << 1),	/* UDMA PRD parity err */
2366c1153e00af8de755ec278d873a97c9ce2a72d10Jeff Garzik	EDMA_ERR_DEV		= (1 << 2),	/* device error */
2376c1153e00af8de755ec278d873a97c9ce2a72d10Jeff Garzik	EDMA_ERR_DEV_DCON	= (1 << 3),	/* device disconnect */
2386c1153e00af8de755ec278d873a97c9ce2a72d10Jeff Garzik	EDMA_ERR_DEV_CON	= (1 << 4),	/* device connected */
2396c1153e00af8de755ec278d873a97c9ce2a72d10Jeff Garzik	EDMA_ERR_SERR		= (1 << 5),	/* SError bits [WBDST] raised */
240c5d3e45a2200a0905dc45b72714726b7aac3aaf1Jeff Garzik	EDMA_ERR_SELF_DIS	= (1 << 7),	/* Gen II/IIE self-disable */
241c5d3e45a2200a0905dc45b72714726b7aac3aaf1Jeff Garzik	EDMA_ERR_SELF_DIS_5	= (1 << 8),	/* Gen I self-disable */
2426c1153e00af8de755ec278d873a97c9ce2a72d10Jeff Garzik	EDMA_ERR_BIST_ASYNC	= (1 << 8),	/* BIST FIS or Async Notify */
243c5d3e45a2200a0905dc45b72714726b7aac3aaf1Jeff Garzik	EDMA_ERR_TRANS_IRQ_7	= (1 << 8),	/* Gen IIE transprt layer irq */
2446c1153e00af8de755ec278d873a97c9ce2a72d10Jeff Garzik	EDMA_ERR_CRQB_PAR	= (1 << 9),	/* CRQB parity error */
2456c1153e00af8de755ec278d873a97c9ce2a72d10Jeff Garzik	EDMA_ERR_CRPB_PAR	= (1 << 10),	/* CRPB parity error */
2466c1153e00af8de755ec278d873a97c9ce2a72d10Jeff Garzik	EDMA_ERR_INTRL_PAR	= (1 << 11),	/* internal parity error */
2476c1153e00af8de755ec278d873a97c9ce2a72d10Jeff Garzik	EDMA_ERR_IORDY		= (1 << 12),	/* IORdy timeout */
248646a4da514f2555298481cb00dc5b3eb02b21b72Mark Lord
2496c1153e00af8de755ec278d873a97c9ce2a72d10Jeff Garzik	EDMA_ERR_LNK_CTRL_RX	= (0xf << 13),	/* link ctrl rx error */
250646a4da514f2555298481cb00dc5b3eb02b21b72Mark Lord	EDMA_ERR_LNK_CTRL_RX_0	= (1 << 13),	/* transient: CRC err */
251646a4da514f2555298481cb00dc5b3eb02b21b72Mark Lord	EDMA_ERR_LNK_CTRL_RX_1	= (1 << 14),	/* transient: FIFO err */
252646a4da514f2555298481cb00dc5b3eb02b21b72Mark Lord	EDMA_ERR_LNK_CTRL_RX_2	= (1 << 15),	/* fatal: caught SYNC */
253646a4da514f2555298481cb00dc5b3eb02b21b72Mark Lord	EDMA_ERR_LNK_CTRL_RX_3	= (1 << 16),	/* transient: FIS rx err */
254646a4da514f2555298481cb00dc5b3eb02b21b72Mark Lord
2556c1153e00af8de755ec278d873a97c9ce2a72d10Jeff Garzik	EDMA_ERR_LNK_DATA_RX	= (0xf << 17),	/* link data rx error */
256646a4da514f2555298481cb00dc5b3eb02b21b72Mark Lord
2576c1153e00af8de755ec278d873a97c9ce2a72d10Jeff Garzik	EDMA_ERR_LNK_CTRL_TX	= (0x1f << 21),	/* link ctrl tx error */
258646a4da514f2555298481cb00dc5b3eb02b21b72Mark Lord	EDMA_ERR_LNK_CTRL_TX_0	= (1 << 21),	/* transient: CRC err */
259646a4da514f2555298481cb00dc5b3eb02b21b72Mark Lord	EDMA_ERR_LNK_CTRL_TX_1	= (1 << 22),	/* transient: FIFO err */
260646a4da514f2555298481cb00dc5b3eb02b21b72Mark Lord	EDMA_ERR_LNK_CTRL_TX_2	= (1 << 23),	/* transient: caught SYNC */
261646a4da514f2555298481cb00dc5b3eb02b21b72Mark Lord	EDMA_ERR_LNK_CTRL_TX_3	= (1 << 24),	/* transient: caught DMAT */
262646a4da514f2555298481cb00dc5b3eb02b21b72Mark Lord	EDMA_ERR_LNK_CTRL_TX_4	= (1 << 25),	/* transient: FIS collision */
263646a4da514f2555298481cb00dc5b3eb02b21b72Mark Lord
2646c1153e00af8de755ec278d873a97c9ce2a72d10Jeff Garzik	EDMA_ERR_LNK_DATA_TX	= (0x1f << 26),	/* link data tx error */
265646a4da514f2555298481cb00dc5b3eb02b21b72Mark Lord
2666c1153e00af8de755ec278d873a97c9ce2a72d10Jeff Garzik	EDMA_ERR_TRANS_PROTO	= (1 << 31),	/* transport protocol error */
267c5d3e45a2200a0905dc45b72714726b7aac3aaf1Jeff Garzik	EDMA_ERR_OVERRUN_5	= (1 << 5),
268c5d3e45a2200a0905dc45b72714726b7aac3aaf1Jeff Garzik	EDMA_ERR_UNDERRUN_5	= (1 << 6),
269646a4da514f2555298481cb00dc5b3eb02b21b72Mark Lord
270646a4da514f2555298481cb00dc5b3eb02b21b72Mark Lord	EDMA_ERR_IRQ_TRANSIENT  = EDMA_ERR_LNK_CTRL_RX_0 |
271646a4da514f2555298481cb00dc5b3eb02b21b72Mark Lord				  EDMA_ERR_LNK_CTRL_RX_1 |
272646a4da514f2555298481cb00dc5b3eb02b21b72Mark Lord				  EDMA_ERR_LNK_CTRL_RX_3 |
273646a4da514f2555298481cb00dc5b3eb02b21b72Mark Lord				  EDMA_ERR_LNK_CTRL_TX,
274646a4da514f2555298481cb00dc5b3eb02b21b72Mark Lord
275bdd4dddee325a7dce3e84cf48201a06aa8508aa4Jeff Garzik	EDMA_EH_FREEZE		= EDMA_ERR_D_PAR |
276bdd4dddee325a7dce3e84cf48201a06aa8508aa4Jeff Garzik				  EDMA_ERR_PRD_PAR |
277bdd4dddee325a7dce3e84cf48201a06aa8508aa4Jeff Garzik				  EDMA_ERR_DEV_DCON |
278bdd4dddee325a7dce3e84cf48201a06aa8508aa4Jeff Garzik				  EDMA_ERR_DEV_CON |
279bdd4dddee325a7dce3e84cf48201a06aa8508aa4Jeff Garzik				  EDMA_ERR_SERR |
280bdd4dddee325a7dce3e84cf48201a06aa8508aa4Jeff Garzik				  EDMA_ERR_SELF_DIS |
2816c1153e00af8de755ec278d873a97c9ce2a72d10Jeff Garzik				  EDMA_ERR_CRQB_PAR |
282bdd4dddee325a7dce3e84cf48201a06aa8508aa4Jeff Garzik				  EDMA_ERR_CRPB_PAR |
283bdd4dddee325a7dce3e84cf48201a06aa8508aa4Jeff Garzik				  EDMA_ERR_INTRL_PAR |
284bdd4dddee325a7dce3e84cf48201a06aa8508aa4Jeff Garzik				  EDMA_ERR_IORDY |
285bdd4dddee325a7dce3e84cf48201a06aa8508aa4Jeff Garzik				  EDMA_ERR_LNK_CTRL_RX_2 |
286bdd4dddee325a7dce3e84cf48201a06aa8508aa4Jeff Garzik				  EDMA_ERR_LNK_DATA_RX |
287bdd4dddee325a7dce3e84cf48201a06aa8508aa4Jeff Garzik				  EDMA_ERR_LNK_DATA_TX |
288bdd4dddee325a7dce3e84cf48201a06aa8508aa4Jeff Garzik				  EDMA_ERR_TRANS_PROTO,
289bdd4dddee325a7dce3e84cf48201a06aa8508aa4Jeff Garzik	EDMA_EH_FREEZE_5	= EDMA_ERR_D_PAR |
290bdd4dddee325a7dce3e84cf48201a06aa8508aa4Jeff Garzik				  EDMA_ERR_PRD_PAR |
291bdd4dddee325a7dce3e84cf48201a06aa8508aa4Jeff Garzik				  EDMA_ERR_DEV_DCON |
292bdd4dddee325a7dce3e84cf48201a06aa8508aa4Jeff Garzik				  EDMA_ERR_DEV_CON |
293bdd4dddee325a7dce3e84cf48201a06aa8508aa4Jeff Garzik				  EDMA_ERR_OVERRUN_5 |
294bdd4dddee325a7dce3e84cf48201a06aa8508aa4Jeff Garzik				  EDMA_ERR_UNDERRUN_5 |
295bdd4dddee325a7dce3e84cf48201a06aa8508aa4Jeff Garzik				  EDMA_ERR_SELF_DIS_5 |
2966c1153e00af8de755ec278d873a97c9ce2a72d10Jeff Garzik				  EDMA_ERR_CRQB_PAR |
297bdd4dddee325a7dce3e84cf48201a06aa8508aa4Jeff Garzik				  EDMA_ERR_CRPB_PAR |
298bdd4dddee325a7dce3e84cf48201a06aa8508aa4Jeff Garzik				  EDMA_ERR_INTRL_PAR |
299bdd4dddee325a7dce3e84cf48201a06aa8508aa4Jeff Garzik				  EDMA_ERR_IORDY,
30020f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ
30131961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ	EDMA_REQ_Q_BASE_HI_OFS	= 0x10,
30231961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ	EDMA_REQ_Q_IN_PTR_OFS	= 0x14,		/* also contains BASE_LO */
30331961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ
30431961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ	EDMA_REQ_Q_OUT_PTR_OFS	= 0x18,
30531961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ	EDMA_REQ_Q_PTR_SHIFT	= 5,
30631961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ
30731961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ	EDMA_RSP_Q_BASE_HI_OFS	= 0x1c,
30831961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ	EDMA_RSP_Q_IN_PTR_OFS	= 0x20,
30931961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ	EDMA_RSP_Q_OUT_PTR_OFS	= 0x24,		/* also contains BASE_LO */
31031961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ	EDMA_RSP_Q_PTR_SHIFT	= 3,
31131961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ
3120ea9e179f436f153fc19fdaef7abbc1e0da20762Jeff Garzik	EDMA_CMD_OFS		= 0x28,		/* EDMA command register */
3130ea9e179f436f153fc19fdaef7abbc1e0da20762Jeff Garzik	EDMA_EN			= (1 << 0),	/* enable EDMA */
3140ea9e179f436f153fc19fdaef7abbc1e0da20762Jeff Garzik	EDMA_DS			= (1 << 1),	/* disable EDMA; self-negated */
3150ea9e179f436f153fc19fdaef7abbc1e0da20762Jeff Garzik	ATA_RST			= (1 << 2),	/* reset trans/link/phy */
31620f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ
317c9d39130123238ac18478a42e25cb7996eacfcc0Jeff Garzik	EDMA_IORDY_TMOUT	= 0x34,
318bca1c4eb9411533d613123618c0d127fae532595Jeff Garzik	EDMA_ARB_CFG		= 0x38,
319bca1c4eb9411533d613123618c0d127fae532595Jeff Garzik
32031961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ	/* Host private flags (hp_flags) */
32131961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ	MV_HP_FLAG_MSI		= (1 << 0),
32247c2b677daeed9c79ecb7167c211ff36876ea611Jeff Garzik	MV_HP_ERRATA_50XXB0	= (1 << 1),
32347c2b677daeed9c79ecb7167c211ff36876ea611Jeff Garzik	MV_HP_ERRATA_50XXB2	= (1 << 2),
32447c2b677daeed9c79ecb7167c211ff36876ea611Jeff Garzik	MV_HP_ERRATA_60X1B2	= (1 << 3),
32547c2b677daeed9c79ecb7167c211ff36876ea611Jeff Garzik	MV_HP_ERRATA_60X1C0	= (1 << 4),
326e4e7b89280d1d666e2c09e5ad36cf071796c4c7eJeff Garzik	MV_HP_ERRATA_XX42A0	= (1 << 5),
3270ea9e179f436f153fc19fdaef7abbc1e0da20762Jeff Garzik	MV_HP_GEN_I		= (1 << 6),	/* Generation I: 50xx */
3280ea9e179f436f153fc19fdaef7abbc1e0da20762Jeff Garzik	MV_HP_GEN_II		= (1 << 7),	/* Generation II: 60xx */
3290ea9e179f436f153fc19fdaef7abbc1e0da20762Jeff Garzik	MV_HP_GEN_IIE		= (1 << 8),	/* Generation IIE: 6042/7042 */
33002a121da5a53d415b6596bc19cc6999d295d32a4Mark Lord	MV_HP_PCIE		= (1 << 9),	/* PCIe bus/regs: 7042 */
33120f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ
33231961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ	/* Port private flags (pp_flags) */
3330ea9e179f436f153fc19fdaef7abbc1e0da20762Jeff Garzik	MV_PP_FLAG_EDMA_EN	= (1 << 0),	/* is EDMA engine enabled? */
3340ea9e179f436f153fc19fdaef7abbc1e0da20762Jeff Garzik	MV_PP_FLAG_HAD_A_RESET	= (1 << 2),	/* 1st hard reset complete? */
33520f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ};
33620f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ
337ee9ccdf70163ca6408f6965e0fbc65baeac7312cJeff Garzik#define IS_GEN_I(hpriv) ((hpriv)->hp_flags & MV_HP_GEN_I)
338ee9ccdf70163ca6408f6965e0fbc65baeac7312cJeff Garzik#define IS_GEN_II(hpriv) ((hpriv)->hp_flags & MV_HP_GEN_II)
339e4e7b89280d1d666e2c09e5ad36cf071796c4c7eJeff Garzik#define IS_GEN_IIE(hpriv) ((hpriv)->hp_flags & MV_HP_GEN_IIE)
340bca1c4eb9411533d613123618c0d127fae532595Jeff Garzik
341095fec887eaa1c38d17c0c929a6733c744a9fa1fJeff Garzikenum {
342baf14aa14efcfdb5a74d5cf804691086c6bec743Jeff Garzik	/* DMA boundary 0xffff is required by the s/g splitting
343baf14aa14efcfdb5a74d5cf804691086c6bec743Jeff Garzik	 * we need on /length/ in mv_fill-sg().
344baf14aa14efcfdb5a74d5cf804691086c6bec743Jeff Garzik	 */
345baf14aa14efcfdb5a74d5cf804691086c6bec743Jeff Garzik	MV_DMA_BOUNDARY		= 0xffffU,
346095fec887eaa1c38d17c0c929a6733c744a9fa1fJeff Garzik
3470ea9e179f436f153fc19fdaef7abbc1e0da20762Jeff Garzik	/* mask of register bits containing lower 32 bits
3480ea9e179f436f153fc19fdaef7abbc1e0da20762Jeff Garzik	 * of EDMA request queue DMA address
3490ea9e179f436f153fc19fdaef7abbc1e0da20762Jeff Garzik	 */
350095fec887eaa1c38d17c0c929a6733c744a9fa1fJeff Garzik	EDMA_REQ_Q_BASE_LO_MASK	= 0xfffffc00U,
351095fec887eaa1c38d17c0c929a6733c744a9fa1fJeff Garzik
3520ea9e179f436f153fc19fdaef7abbc1e0da20762Jeff Garzik	/* ditto, for response queue */
353095fec887eaa1c38d17c0c929a6733c744a9fa1fJeff Garzik	EDMA_RSP_Q_BASE_LO_MASK	= 0xffffff00U,
354095fec887eaa1c38d17c0c929a6733c744a9fa1fJeff Garzik};
355095fec887eaa1c38d17c0c929a6733c744a9fa1fJeff Garzik
356522479fb98c6667f081e75f87e298e413c0b1db8Jeff Garzikenum chip_type {
357522479fb98c6667f081e75f87e298e413c0b1db8Jeff Garzik	chip_504x,
358522479fb98c6667f081e75f87e298e413c0b1db8Jeff Garzik	chip_508x,
359522479fb98c6667f081e75f87e298e413c0b1db8Jeff Garzik	chip_5080,
360522479fb98c6667f081e75f87e298e413c0b1db8Jeff Garzik	chip_604x,
361522479fb98c6667f081e75f87e298e413c0b1db8Jeff Garzik	chip_608x,
362e4e7b89280d1d666e2c09e5ad36cf071796c4c7eJeff Garzik	chip_6042,
363e4e7b89280d1d666e2c09e5ad36cf071796c4c7eJeff Garzik	chip_7042,
364522479fb98c6667f081e75f87e298e413c0b1db8Jeff Garzik};
365522479fb98c6667f081e75f87e298e413c0b1db8Jeff Garzik
36631961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ/* Command ReQuest Block: 32B */
36731961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russstruct mv_crqb {
368e14698745dd0de1ddbf5cd0cca4313a90f8c1cc1Mark Lord	__le32			sg_addr;
369e14698745dd0de1ddbf5cd0cca4313a90f8c1cc1Mark Lord	__le32			sg_addr_hi;
370e14698745dd0de1ddbf5cd0cca4313a90f8c1cc1Mark Lord	__le16			ctrl_flags;
371e14698745dd0de1ddbf5cd0cca4313a90f8c1cc1Mark Lord	__le16			ata_cmd[11];
37231961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ};
37320f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ
374e4e7b89280d1d666e2c09e5ad36cf071796c4c7eJeff Garzikstruct mv_crqb_iie {
375e14698745dd0de1ddbf5cd0cca4313a90f8c1cc1Mark Lord	__le32			addr;
376e14698745dd0de1ddbf5cd0cca4313a90f8c1cc1Mark Lord	__le32			addr_hi;
377e14698745dd0de1ddbf5cd0cca4313a90f8c1cc1Mark Lord	__le32			flags;
378e14698745dd0de1ddbf5cd0cca4313a90f8c1cc1Mark Lord	__le32			len;
379e14698745dd0de1ddbf5cd0cca4313a90f8c1cc1Mark Lord	__le32			ata_cmd[4];
380e4e7b89280d1d666e2c09e5ad36cf071796c4c7eJeff Garzik};
381e4e7b89280d1d666e2c09e5ad36cf071796c4c7eJeff Garzik
38231961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ/* Command ResPonse Block: 8B */
38331961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russstruct mv_crpb {
384e14698745dd0de1ddbf5cd0cca4313a90f8c1cc1Mark Lord	__le16			id;
385e14698745dd0de1ddbf5cd0cca4313a90f8c1cc1Mark Lord	__le16			flags;
386e14698745dd0de1ddbf5cd0cca4313a90f8c1cc1Mark Lord	__le32			tmstmp;
38720f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ};
38820f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ
38931961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ/* EDMA Physical Region Descriptor (ePRD); A.K.A. SG */
39031961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russstruct mv_sg {
391e14698745dd0de1ddbf5cd0cca4313a90f8c1cc1Mark Lord	__le32			addr;
392e14698745dd0de1ddbf5cd0cca4313a90f8c1cc1Mark Lord	__le32			flags_size;
393e14698745dd0de1ddbf5cd0cca4313a90f8c1cc1Mark Lord	__le32			addr_hi;
394e14698745dd0de1ddbf5cd0cca4313a90f8c1cc1Mark Lord	__le32			reserved;
39531961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ};
39620f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ
39731961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russstruct mv_port_priv {
39831961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ	struct mv_crqb		*crqb;
39931961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ	dma_addr_t		crqb_dma;
40031961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ	struct mv_crpb		*crpb;
40131961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ	dma_addr_t		crpb_dma;
40231961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ	struct mv_sg		*sg_tbl;
40331961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ	dma_addr_t		sg_tbl_dma;
404bdd4dddee325a7dce3e84cf48201a06aa8508aa4Jeff Garzik
405bdd4dddee325a7dce3e84cf48201a06aa8508aa4Jeff Garzik	unsigned int		req_idx;
406bdd4dddee325a7dce3e84cf48201a06aa8508aa4Jeff Garzik	unsigned int		resp_idx;
407bdd4dddee325a7dce3e84cf48201a06aa8508aa4Jeff Garzik
40831961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ	u32			pp_flags;
40931961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ};
41031961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ
411bca1c4eb9411533d613123618c0d127fae532595Jeff Garzikstruct mv_port_signal {
412bca1c4eb9411533d613123618c0d127fae532595Jeff Garzik	u32			amps;
413bca1c4eb9411533d613123618c0d127fae532595Jeff Garzik	u32			pre;
414bca1c4eb9411533d613123618c0d127fae532595Jeff Garzik};
415bca1c4eb9411533d613123618c0d127fae532595Jeff Garzik
41602a121da5a53d415b6596bc19cc6999d295d32a4Mark Lordstruct mv_host_priv {
41702a121da5a53d415b6596bc19cc6999d295d32a4Mark Lord	u32			hp_flags;
41802a121da5a53d415b6596bc19cc6999d295d32a4Mark Lord	struct mv_port_signal	signal[8];
41902a121da5a53d415b6596bc19cc6999d295d32a4Mark Lord	const struct mv_hw_ops	*ops;
42002a121da5a53d415b6596bc19cc6999d295d32a4Mark Lord	u32			irq_cause_ofs;
42102a121da5a53d415b6596bc19cc6999d295d32a4Mark Lord	u32			irq_mask_ofs;
42202a121da5a53d415b6596bc19cc6999d295d32a4Mark Lord	u32			unmask_all_irqs;
42302a121da5a53d415b6596bc19cc6999d295d32a4Mark Lord};
42402a121da5a53d415b6596bc19cc6999d295d32a4Mark Lord
42547c2b677daeed9c79ecb7167c211ff36876ea611Jeff Garzikstruct mv_hw_ops {
4262a47ce06d534692f9bd2bf4e90a20fc9b1054c39Jeff Garzik	void (*phy_errata)(struct mv_host_priv *hpriv, void __iomem *mmio,
4272a47ce06d534692f9bd2bf4e90a20fc9b1054c39Jeff Garzik			   unsigned int port);
42847c2b677daeed9c79ecb7167c211ff36876ea611Jeff Garzik	void (*enable_leds)(struct mv_host_priv *hpriv, void __iomem *mmio);
42947c2b677daeed9c79ecb7167c211ff36876ea611Jeff Garzik	void (*read_preamp)(struct mv_host_priv *hpriv, int idx,
43047c2b677daeed9c79ecb7167c211ff36876ea611Jeff Garzik			   void __iomem *mmio);
431c9d39130123238ac18478a42e25cb7996eacfcc0Jeff Garzik	int (*reset_hc)(struct mv_host_priv *hpriv, void __iomem *mmio,
432c9d39130123238ac18478a42e25cb7996eacfcc0Jeff Garzik			unsigned int n_hc);
433522479fb98c6667f081e75f87e298e413c0b1db8Jeff Garzik	void (*reset_flash)(struct mv_host_priv *hpriv, void __iomem *mmio);
434522479fb98c6667f081e75f87e298e413c0b1db8Jeff Garzik	void (*reset_bus)(struct pci_dev *pdev, void __iomem *mmio);
43547c2b677daeed9c79ecb7167c211ff36876ea611Jeff Garzik};
43647c2b677daeed9c79ecb7167c211ff36876ea611Jeff Garzik
43720f733e7d75a16bffc34842b7682c9247dd5f954Brett Russstatic void mv_irq_clear(struct ata_port *ap);
438da3dbb17a0e9a9ec7f5aed95f1fddadb790edc9dTejun Heostatic int mv_scr_read(struct ata_port *ap, unsigned int sc_reg_in, u32 *val);
439da3dbb17a0e9a9ec7f5aed95f1fddadb790edc9dTejun Heostatic int mv_scr_write(struct ata_port *ap, unsigned int sc_reg_in, u32 val);
440da3dbb17a0e9a9ec7f5aed95f1fddadb790edc9dTejun Heostatic int mv5_scr_read(struct ata_port *ap, unsigned int sc_reg_in, u32 *val);
441da3dbb17a0e9a9ec7f5aed95f1fddadb790edc9dTejun Heostatic int mv5_scr_write(struct ata_port *ap, unsigned int sc_reg_in, u32 val);
44231961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russstatic int mv_port_start(struct ata_port *ap);
44331961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russstatic void mv_port_stop(struct ata_port *ap);
44431961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russstatic void mv_qc_prep(struct ata_queued_cmd *qc);
445e4e7b89280d1d666e2c09e5ad36cf071796c4c7eJeff Garzikstatic void mv_qc_prep_iie(struct ata_queued_cmd *qc);
4469a3d9eb0177eb10500d49cd283b35576082a522dTejun Heostatic unsigned int mv_qc_issue(struct ata_queued_cmd *qc);
447bdd4dddee325a7dce3e84cf48201a06aa8508aa4Jeff Garzikstatic void mv_error_handler(struct ata_port *ap);
448bdd4dddee325a7dce3e84cf48201a06aa8508aa4Jeff Garzikstatic void mv_post_int_cmd(struct ata_queued_cmd *qc);
449bdd4dddee325a7dce3e84cf48201a06aa8508aa4Jeff Garzikstatic void mv_eh_freeze(struct ata_port *ap);
450bdd4dddee325a7dce3e84cf48201a06aa8508aa4Jeff Garzikstatic void mv_eh_thaw(struct ata_port *ap);
45120f733e7d75a16bffc34842b7682c9247dd5f954Brett Russstatic int mv_init_one(struct pci_dev *pdev, const struct pci_device_id *ent);
45220f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ
4532a47ce06d534692f9bd2bf4e90a20fc9b1054c39Jeff Garzikstatic void mv5_phy_errata(struct mv_host_priv *hpriv, void __iomem *mmio,
4542a47ce06d534692f9bd2bf4e90a20fc9b1054c39Jeff Garzik			   unsigned int port);
45547c2b677daeed9c79ecb7167c211ff36876ea611Jeff Garzikstatic void mv5_enable_leds(struct mv_host_priv *hpriv, void __iomem *mmio);
45647c2b677daeed9c79ecb7167c211ff36876ea611Jeff Garzikstatic void mv5_read_preamp(struct mv_host_priv *hpriv, int idx,
45747c2b677daeed9c79ecb7167c211ff36876ea611Jeff Garzik			   void __iomem *mmio);
458c9d39130123238ac18478a42e25cb7996eacfcc0Jeff Garzikstatic int mv5_reset_hc(struct mv_host_priv *hpriv, void __iomem *mmio,
459c9d39130123238ac18478a42e25cb7996eacfcc0Jeff Garzik			unsigned int n_hc);
460522479fb98c6667f081e75f87e298e413c0b1db8Jeff Garzikstatic void mv5_reset_flash(struct mv_host_priv *hpriv, void __iomem *mmio);
461522479fb98c6667f081e75f87e298e413c0b1db8Jeff Garzikstatic void mv5_reset_bus(struct pci_dev *pdev, void __iomem *mmio);
46247c2b677daeed9c79ecb7167c211ff36876ea611Jeff Garzik
4632a47ce06d534692f9bd2bf4e90a20fc9b1054c39Jeff Garzikstatic void mv6_phy_errata(struct mv_host_priv *hpriv, void __iomem *mmio,
4642a47ce06d534692f9bd2bf4e90a20fc9b1054c39Jeff Garzik			   unsigned int port);
46547c2b677daeed9c79ecb7167c211ff36876ea611Jeff Garzikstatic void mv6_enable_leds(struct mv_host_priv *hpriv, void __iomem *mmio);
46647c2b677daeed9c79ecb7167c211ff36876ea611Jeff Garzikstatic void mv6_read_preamp(struct mv_host_priv *hpriv, int idx,
46747c2b677daeed9c79ecb7167c211ff36876ea611Jeff Garzik			   void __iomem *mmio);
468c9d39130123238ac18478a42e25cb7996eacfcc0Jeff Garzikstatic int mv6_reset_hc(struct mv_host_priv *hpriv, void __iomem *mmio,
469c9d39130123238ac18478a42e25cb7996eacfcc0Jeff Garzik			unsigned int n_hc);
470522479fb98c6667f081e75f87e298e413c0b1db8Jeff Garzikstatic void mv6_reset_flash(struct mv_host_priv *hpriv, void __iomem *mmio);
471522479fb98c6667f081e75f87e298e413c0b1db8Jeff Garzikstatic void mv_reset_pci_bus(struct pci_dev *pdev, void __iomem *mmio);
472c9d39130123238ac18478a42e25cb7996eacfcc0Jeff Garzikstatic void mv_channel_reset(struct mv_host_priv *hpriv, void __iomem *mmio,
473c9d39130123238ac18478a42e25cb7996eacfcc0Jeff Garzik			     unsigned int port_no);
4740c58912e192fc3a4835d772aafa40b72552b819fMark Lordstatic void mv_edma_cfg(struct ata_port *ap, struct mv_host_priv *hpriv,
4750c58912e192fc3a4835d772aafa40b72552b819fMark Lord			void __iomem *port_mmio);
47647c2b677daeed9c79ecb7167c211ff36876ea611Jeff Garzik
477c5d3e45a2200a0905dc45b72714726b7aac3aaf1Jeff Garzikstatic struct scsi_host_template mv5_sht = {
478c5d3e45a2200a0905dc45b72714726b7aac3aaf1Jeff Garzik	.module			= THIS_MODULE,
479c5d3e45a2200a0905dc45b72714726b7aac3aaf1Jeff Garzik	.name			= DRV_NAME,
480c5d3e45a2200a0905dc45b72714726b7aac3aaf1Jeff Garzik	.ioctl			= ata_scsi_ioctl,
481c5d3e45a2200a0905dc45b72714726b7aac3aaf1Jeff Garzik	.queuecommand		= ata_scsi_queuecmd,
482c5d3e45a2200a0905dc45b72714726b7aac3aaf1Jeff Garzik	.can_queue		= ATA_DEF_QUEUE,
483c5d3e45a2200a0905dc45b72714726b7aac3aaf1Jeff Garzik	.this_id		= ATA_SHT_THIS_ID,
484baf14aa14efcfdb5a74d5cf804691086c6bec743Jeff Garzik	.sg_tablesize		= MV_MAX_SG_CT / 2,
485c5d3e45a2200a0905dc45b72714726b7aac3aaf1Jeff Garzik	.cmd_per_lun		= ATA_SHT_CMD_PER_LUN,
486c5d3e45a2200a0905dc45b72714726b7aac3aaf1Jeff Garzik	.emulated		= ATA_SHT_EMULATED,
487c5d3e45a2200a0905dc45b72714726b7aac3aaf1Jeff Garzik	.use_clustering		= 1,
488c5d3e45a2200a0905dc45b72714726b7aac3aaf1Jeff Garzik	.proc_name		= DRV_NAME,
489c5d3e45a2200a0905dc45b72714726b7aac3aaf1Jeff Garzik	.dma_boundary		= MV_DMA_BOUNDARY,
4903be6cbd73f74b4a3da82cc7d6e1688a4ae595fc7Jeff Garzik	.slave_configure	= ata_scsi_slave_config,
491c5d3e45a2200a0905dc45b72714726b7aac3aaf1Jeff Garzik	.slave_destroy		= ata_scsi_slave_destroy,
492c5d3e45a2200a0905dc45b72714726b7aac3aaf1Jeff Garzik	.bios_param		= ata_std_bios_param,
493c5d3e45a2200a0905dc45b72714726b7aac3aaf1Jeff Garzik};
494c5d3e45a2200a0905dc45b72714726b7aac3aaf1Jeff Garzik
495c5d3e45a2200a0905dc45b72714726b7aac3aaf1Jeff Garzikstatic struct scsi_host_template mv6_sht = {
49620f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ	.module			= THIS_MODULE,
49720f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ	.name			= DRV_NAME,
49820f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ	.ioctl			= ata_scsi_ioctl,
49920f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ	.queuecommand		= ata_scsi_queuecmd,
500c5d3e45a2200a0905dc45b72714726b7aac3aaf1Jeff Garzik	.can_queue		= ATA_DEF_QUEUE,
50120f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ	.this_id		= ATA_SHT_THIS_ID,
502baf14aa14efcfdb5a74d5cf804691086c6bec743Jeff Garzik	.sg_tablesize		= MV_MAX_SG_CT / 2,
50320f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ	.cmd_per_lun		= ATA_SHT_CMD_PER_LUN,
50420f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ	.emulated		= ATA_SHT_EMULATED,
505d88184fb2348a50f7c34f5d49a901c875b2e0114Jeff Garzik	.use_clustering		= 1,
50620f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ	.proc_name		= DRV_NAME,
50720f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ	.dma_boundary		= MV_DMA_BOUNDARY,
5083be6cbd73f74b4a3da82cc7d6e1688a4ae595fc7Jeff Garzik	.slave_configure	= ata_scsi_slave_config,
509ccf68c3405fca11386004674377d951b9b18e756Tejun Heo	.slave_destroy		= ata_scsi_slave_destroy,
51020f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ	.bios_param		= ata_std_bios_param,
51120f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ};
51220f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ
513c9d39130123238ac18478a42e25cb7996eacfcc0Jeff Garzikstatic const struct ata_port_operations mv5_ops = {
514c9d39130123238ac18478a42e25cb7996eacfcc0Jeff Garzik	.tf_load		= ata_tf_load,
515c9d39130123238ac18478a42e25cb7996eacfcc0Jeff Garzik	.tf_read		= ata_tf_read,
516c9d39130123238ac18478a42e25cb7996eacfcc0Jeff Garzik	.check_status		= ata_check_status,
517c9d39130123238ac18478a42e25cb7996eacfcc0Jeff Garzik	.exec_command		= ata_exec_command,
518c9d39130123238ac18478a42e25cb7996eacfcc0Jeff Garzik	.dev_select		= ata_std_dev_select,
519c9d39130123238ac18478a42e25cb7996eacfcc0Jeff Garzik
520cffacd85bcf6fc652292001873119333555fe260Jeff Garzik	.cable_detect		= ata_cable_sata,
521c9d39130123238ac18478a42e25cb7996eacfcc0Jeff Garzik
522c9d39130123238ac18478a42e25cb7996eacfcc0Jeff Garzik	.qc_prep		= mv_qc_prep,
523c9d39130123238ac18478a42e25cb7996eacfcc0Jeff Garzik	.qc_issue		= mv_qc_issue,
5240d5ff566779f894ca9937231a181eb31e4adff0eTejun Heo	.data_xfer		= ata_data_xfer,
525c9d39130123238ac18478a42e25cb7996eacfcc0Jeff Garzik
526c9d39130123238ac18478a42e25cb7996eacfcc0Jeff Garzik	.irq_clear		= mv_irq_clear,
527246ce3b675843e0369643cceb4faeb6cf6d19a30Akira Iguchi	.irq_on			= ata_irq_on,
528c9d39130123238ac18478a42e25cb7996eacfcc0Jeff Garzik
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
534c9d39130123238ac18478a42e25cb7996eacfcc0Jeff Garzik	.scr_read		= mv5_scr_read,
535c9d39130123238ac18478a42e25cb7996eacfcc0Jeff Garzik	.scr_write		= mv5_scr_write,
536c9d39130123238ac18478a42e25cb7996eacfcc0Jeff Garzik
537c9d39130123238ac18478a42e25cb7996eacfcc0Jeff Garzik	.port_start		= mv_port_start,
538c9d39130123238ac18478a42e25cb7996eacfcc0Jeff Garzik	.port_stop		= mv_port_stop,
539c9d39130123238ac18478a42e25cb7996eacfcc0Jeff Garzik};
540c9d39130123238ac18478a42e25cb7996eacfcc0Jeff Garzik
541c9d39130123238ac18478a42e25cb7996eacfcc0Jeff Garzikstatic const struct ata_port_operations mv6_ops = {
54220f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ	.tf_load		= ata_tf_load,
54320f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ	.tf_read		= ata_tf_read,
54420f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ	.check_status		= ata_check_status,
54520f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ	.exec_command		= ata_exec_command,
54620f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ	.dev_select		= ata_std_dev_select,
54720f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ
548cffacd85bcf6fc652292001873119333555fe260Jeff Garzik	.cable_detect		= ata_cable_sata,
54920f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ
55031961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ	.qc_prep		= mv_qc_prep,
55131961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ	.qc_issue		= mv_qc_issue,
5520d5ff566779f894ca9937231a181eb31e4adff0eTejun Heo	.data_xfer		= ata_data_xfer,
55320f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ
55420f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ	.irq_clear		= mv_irq_clear,
555246ce3b675843e0369643cceb4faeb6cf6d19a30Akira Iguchi	.irq_on			= ata_irq_on,
55620f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ
557bdd4dddee325a7dce3e84cf48201a06aa8508aa4Jeff Garzik	.error_handler		= mv_error_handler,
558bdd4dddee325a7dce3e84cf48201a06aa8508aa4Jeff Garzik	.post_internal_cmd	= mv_post_int_cmd,
559bdd4dddee325a7dce3e84cf48201a06aa8508aa4Jeff Garzik	.freeze			= mv_eh_freeze,
560bdd4dddee325a7dce3e84cf48201a06aa8508aa4Jeff Garzik	.thaw			= mv_eh_thaw,
561bdd4dddee325a7dce3e84cf48201a06aa8508aa4Jeff Garzik
56220f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ	.scr_read		= mv_scr_read,
56320f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ	.scr_write		= mv_scr_write,
56420f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ
56531961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ	.port_start		= mv_port_start,
56631961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ	.port_stop		= mv_port_stop,
56720f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ};
56820f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ
569e4e7b89280d1d666e2c09e5ad36cf071796c4c7eJeff Garzikstatic const struct ata_port_operations mv_iie_ops = {
570e4e7b89280d1d666e2c09e5ad36cf071796c4c7eJeff Garzik	.tf_load		= ata_tf_load,
571e4e7b89280d1d666e2c09e5ad36cf071796c4c7eJeff Garzik	.tf_read		= ata_tf_read,
572e4e7b89280d1d666e2c09e5ad36cf071796c4c7eJeff Garzik	.check_status		= ata_check_status,
573e4e7b89280d1d666e2c09e5ad36cf071796c4c7eJeff Garzik	.exec_command		= ata_exec_command,
574e4e7b89280d1d666e2c09e5ad36cf071796c4c7eJeff Garzik	.dev_select		= ata_std_dev_select,
575e4e7b89280d1d666e2c09e5ad36cf071796c4c7eJeff Garzik
576cffacd85bcf6fc652292001873119333555fe260Jeff Garzik	.cable_detect		= ata_cable_sata,
577e4e7b89280d1d666e2c09e5ad36cf071796c4c7eJeff Garzik
578e4e7b89280d1d666e2c09e5ad36cf071796c4c7eJeff Garzik	.qc_prep		= mv_qc_prep_iie,
579e4e7b89280d1d666e2c09e5ad36cf071796c4c7eJeff Garzik	.qc_issue		= mv_qc_issue,
5800d5ff566779f894ca9937231a181eb31e4adff0eTejun Heo	.data_xfer		= ata_data_xfer,
581e4e7b89280d1d666e2c09e5ad36cf071796c4c7eJeff Garzik
582e4e7b89280d1d666e2c09e5ad36cf071796c4c7eJeff Garzik	.irq_clear		= mv_irq_clear,
583246ce3b675843e0369643cceb4faeb6cf6d19a30Akira Iguchi	.irq_on			= ata_irq_on,
584e4e7b89280d1d666e2c09e5ad36cf071796c4c7eJeff Garzik
585bdd4dddee325a7dce3e84cf48201a06aa8508aa4Jeff Garzik	.error_handler		= mv_error_handler,
586bdd4dddee325a7dce3e84cf48201a06aa8508aa4Jeff Garzik	.post_internal_cmd	= mv_post_int_cmd,
587bdd4dddee325a7dce3e84cf48201a06aa8508aa4Jeff Garzik	.freeze			= mv_eh_freeze,
588bdd4dddee325a7dce3e84cf48201a06aa8508aa4Jeff Garzik	.thaw			= mv_eh_thaw,
589bdd4dddee325a7dce3e84cf48201a06aa8508aa4Jeff Garzik
590e4e7b89280d1d666e2c09e5ad36cf071796c4c7eJeff Garzik	.scr_read		= mv_scr_read,
591e4e7b89280d1d666e2c09e5ad36cf071796c4c7eJeff Garzik	.scr_write		= mv_scr_write,
592e4e7b89280d1d666e2c09e5ad36cf071796c4c7eJeff Garzik
593e4e7b89280d1d666e2c09e5ad36cf071796c4c7eJeff Garzik	.port_start		= mv_port_start,
594e4e7b89280d1d666e2c09e5ad36cf071796c4c7eJeff Garzik	.port_stop		= mv_port_stop,
595e4e7b89280d1d666e2c09e5ad36cf071796c4c7eJeff Garzik};
596e4e7b89280d1d666e2c09e5ad36cf071796c4c7eJeff Garzik
59798ac62defe529d04a192688f40d801a2d8fbcf98Arjan van de Venstatic const struct ata_port_info mv_port_info[] = {
59820f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ	{  /* chip_504x */
599cca3974e48607c3775dc73b544a5700b2e37c21aJeff Garzik		.flags		= MV_COMMON_FLAGS,
60031961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ		.pio_mask	= 0x1f,	/* pio0-4 */
601bf6263a853c9c143bf03f0a6fdcc68ab714fb5f5Jeff Garzik		.udma_mask	= ATA_UDMA6,
602c9d39130123238ac18478a42e25cb7996eacfcc0Jeff Garzik		.port_ops	= &mv5_ops,
60320f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ	},
60420f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ	{  /* chip_508x */
605c5d3e45a2200a0905dc45b72714726b7aac3aaf1Jeff Garzik		.flags		= MV_COMMON_FLAGS | MV_FLAG_DUAL_HC,
60631961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ		.pio_mask	= 0x1f,	/* pio0-4 */
607bf6263a853c9c143bf03f0a6fdcc68ab714fb5f5Jeff Garzik		.udma_mask	= ATA_UDMA6,
608c9d39130123238ac18478a42e25cb7996eacfcc0Jeff Garzik		.port_ops	= &mv5_ops,
60920f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ	},
61047c2b677daeed9c79ecb7167c211ff36876ea611Jeff Garzik	{  /* chip_5080 */
611c5d3e45a2200a0905dc45b72714726b7aac3aaf1Jeff Garzik		.flags		= MV_COMMON_FLAGS | MV_FLAG_DUAL_HC,
61247c2b677daeed9c79ecb7167c211ff36876ea611Jeff Garzik		.pio_mask	= 0x1f,	/* pio0-4 */
613bf6263a853c9c143bf03f0a6fdcc68ab714fb5f5Jeff Garzik		.udma_mask	= ATA_UDMA6,
614c9d39130123238ac18478a42e25cb7996eacfcc0Jeff Garzik		.port_ops	= &mv5_ops,
61547c2b677daeed9c79ecb7167c211ff36876ea611Jeff Garzik	},
61620f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ	{  /* chip_604x */
617c5d3e45a2200a0905dc45b72714726b7aac3aaf1Jeff Garzik		.flags		= MV_COMMON_FLAGS | MV_6XXX_FLAGS,
61831961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ		.pio_mask	= 0x1f,	/* pio0-4 */
619bf6263a853c9c143bf03f0a6fdcc68ab714fb5f5Jeff Garzik		.udma_mask	= ATA_UDMA6,
620c9d39130123238ac18478a42e25cb7996eacfcc0Jeff Garzik		.port_ops	= &mv6_ops,
62120f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ	},
62220f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ	{  /* chip_608x */
623c5d3e45a2200a0905dc45b72714726b7aac3aaf1Jeff Garzik		.flags		= MV_COMMON_FLAGS | MV_6XXX_FLAGS |
624c5d3e45a2200a0905dc45b72714726b7aac3aaf1Jeff Garzik				  MV_FLAG_DUAL_HC,
62531961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ		.pio_mask	= 0x1f,	/* pio0-4 */
626bf6263a853c9c143bf03f0a6fdcc68ab714fb5f5Jeff Garzik		.udma_mask	= ATA_UDMA6,
627c9d39130123238ac18478a42e25cb7996eacfcc0Jeff Garzik		.port_ops	= &mv6_ops,
62820f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ	},
629e4e7b89280d1d666e2c09e5ad36cf071796c4c7eJeff Garzik	{  /* chip_6042 */
630c5d3e45a2200a0905dc45b72714726b7aac3aaf1Jeff Garzik		.flags		= MV_COMMON_FLAGS | MV_6XXX_FLAGS,
631e4e7b89280d1d666e2c09e5ad36cf071796c4c7eJeff Garzik		.pio_mask	= 0x1f,	/* pio0-4 */
632bf6263a853c9c143bf03f0a6fdcc68ab714fb5f5Jeff Garzik		.udma_mask	= ATA_UDMA6,
633e4e7b89280d1d666e2c09e5ad36cf071796c4c7eJeff Garzik		.port_ops	= &mv_iie_ops,
634e4e7b89280d1d666e2c09e5ad36cf071796c4c7eJeff Garzik	},
635e4e7b89280d1d666e2c09e5ad36cf071796c4c7eJeff Garzik	{  /* chip_7042 */
636c5d3e45a2200a0905dc45b72714726b7aac3aaf1Jeff Garzik		.flags		= MV_COMMON_FLAGS | MV_6XXX_FLAGS,
637e4e7b89280d1d666e2c09e5ad36cf071796c4c7eJeff Garzik		.pio_mask	= 0x1f,	/* pio0-4 */
638bf6263a853c9c143bf03f0a6fdcc68ab714fb5f5Jeff Garzik		.udma_mask	= ATA_UDMA6,
639e4e7b89280d1d666e2c09e5ad36cf071796c4c7eJeff Garzik		.port_ops	= &mv_iie_ops,
640e4e7b89280d1d666e2c09e5ad36cf071796c4c7eJeff Garzik	},
64120f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ};
64220f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ
6433b7d697dfb7d03edb87e50b743a7ecff029618e9Jeff Garzikstatic const struct pci_device_id mv_pci_tbl[] = {
6442d2744fc8be620a2dc469cf48349e3e704119f1bJeff Garzik	{ PCI_VDEVICE(MARVELL, 0x5040), chip_504x },
6452d2744fc8be620a2dc469cf48349e3e704119f1bJeff Garzik	{ PCI_VDEVICE(MARVELL, 0x5041), chip_504x },
6462d2744fc8be620a2dc469cf48349e3e704119f1bJeff Garzik	{ PCI_VDEVICE(MARVELL, 0x5080), chip_5080 },
6472d2744fc8be620a2dc469cf48349e3e704119f1bJeff Garzik	{ PCI_VDEVICE(MARVELL, 0x5081), chip_508x },
648cfbf723eb7928879292ee71fa0d118fc4e37b8c9Alan Cox	/* RocketRAID 1740/174x have different identifiers */
649cfbf723eb7928879292ee71fa0d118fc4e37b8c9Alan Cox	{ PCI_VDEVICE(TTI, 0x1740), chip_508x },
650cfbf723eb7928879292ee71fa0d118fc4e37b8c9Alan Cox	{ PCI_VDEVICE(TTI, 0x1742), chip_508x },
6512d2744fc8be620a2dc469cf48349e3e704119f1bJeff Garzik
6522d2744fc8be620a2dc469cf48349e3e704119f1bJeff Garzik	{ PCI_VDEVICE(MARVELL, 0x6040), chip_604x },
6532d2744fc8be620a2dc469cf48349e3e704119f1bJeff Garzik	{ PCI_VDEVICE(MARVELL, 0x6041), chip_604x },
6542d2744fc8be620a2dc469cf48349e3e704119f1bJeff Garzik	{ PCI_VDEVICE(MARVELL, 0x6042), chip_6042 },
6552d2744fc8be620a2dc469cf48349e3e704119f1bJeff Garzik	{ PCI_VDEVICE(MARVELL, 0x6080), chip_608x },
6562d2744fc8be620a2dc469cf48349e3e704119f1bJeff Garzik	{ PCI_VDEVICE(MARVELL, 0x6081), chip_608x },
6572d2744fc8be620a2dc469cf48349e3e704119f1bJeff Garzik
6582d2744fc8be620a2dc469cf48349e3e704119f1bJeff Garzik	{ PCI_VDEVICE(ADAPTEC2, 0x0241), chip_604x },
6592d2744fc8be620a2dc469cf48349e3e704119f1bJeff Garzik
660d9f9c6bc91c14f53ffa782ffcd42259ecae1d38cFlorian Attenberger	/* Adaptec 1430SA */
661d9f9c6bc91c14f53ffa782ffcd42259ecae1d38cFlorian Attenberger	{ PCI_VDEVICE(ADAPTEC2, 0x0243), chip_7042 },
662d9f9c6bc91c14f53ffa782ffcd42259ecae1d38cFlorian Attenberger
66302a121da5a53d415b6596bc19cc6999d295d32a4Mark Lord	/* Marvell 7042 support */
6646a3d586d8e8a50e4cfd7f8c36d82a53c5614e05bMorrison, Tom	{ PCI_VDEVICE(MARVELL, 0x7042), chip_7042 },
6656a3d586d8e8a50e4cfd7f8c36d82a53c5614e05bMorrison, Tom
66602a121da5a53d415b6596bc19cc6999d295d32a4Mark Lord	/* Highpoint RocketRAID PCIe series */
66702a121da5a53d415b6596bc19cc6999d295d32a4Mark Lord	{ PCI_VDEVICE(TTI, 0x2300), chip_7042 },
66802a121da5a53d415b6596bc19cc6999d295d32a4Mark Lord	{ PCI_VDEVICE(TTI, 0x2310), chip_7042 },
66902a121da5a53d415b6596bc19cc6999d295d32a4Mark Lord
6702d2744fc8be620a2dc469cf48349e3e704119f1bJeff Garzik	{ }			/* terminate list */
67120f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ};
67220f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ
67320f733e7d75a16bffc34842b7682c9247dd5f954Brett Russstatic struct pci_driver mv_pci_driver = {
67420f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ	.name			= DRV_NAME,
67520f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ	.id_table		= mv_pci_tbl,
67620f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ	.probe			= mv_init_one,
67720f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ	.remove			= ata_pci_remove_one,
67820f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ};
67920f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ
68047c2b677daeed9c79ecb7167c211ff36876ea611Jeff Garzikstatic const struct mv_hw_ops mv5xxx_ops = {
68147c2b677daeed9c79ecb7167c211ff36876ea611Jeff Garzik	.phy_errata		= mv5_phy_errata,
68247c2b677daeed9c79ecb7167c211ff36876ea611Jeff Garzik	.enable_leds		= mv5_enable_leds,
68347c2b677daeed9c79ecb7167c211ff36876ea611Jeff Garzik	.read_preamp		= mv5_read_preamp,
68447c2b677daeed9c79ecb7167c211ff36876ea611Jeff Garzik	.reset_hc		= mv5_reset_hc,
685522479fb98c6667f081e75f87e298e413c0b1db8Jeff Garzik	.reset_flash		= mv5_reset_flash,
686522479fb98c6667f081e75f87e298e413c0b1db8Jeff Garzik	.reset_bus		= mv5_reset_bus,
68747c2b677daeed9c79ecb7167c211ff36876ea611Jeff Garzik};
68847c2b677daeed9c79ecb7167c211ff36876ea611Jeff Garzik
68947c2b677daeed9c79ecb7167c211ff36876ea611Jeff Garzikstatic const struct mv_hw_ops mv6xxx_ops = {
69047c2b677daeed9c79ecb7167c211ff36876ea611Jeff Garzik	.phy_errata		= mv6_phy_errata,
69147c2b677daeed9c79ecb7167c211ff36876ea611Jeff Garzik	.enable_leds		= mv6_enable_leds,
69247c2b677daeed9c79ecb7167c211ff36876ea611Jeff Garzik	.read_preamp		= mv6_read_preamp,
69347c2b677daeed9c79ecb7167c211ff36876ea611Jeff Garzik	.reset_hc		= mv6_reset_hc,
694522479fb98c6667f081e75f87e298e413c0b1db8Jeff Garzik	.reset_flash		= mv6_reset_flash,
695522479fb98c6667f081e75f87e298e413c0b1db8Jeff Garzik	.reset_bus		= mv_reset_pci_bus,
69647c2b677daeed9c79ecb7167c211ff36876ea611Jeff Garzik};
69747c2b677daeed9c79ecb7167c211ff36876ea611Jeff Garzik
69820f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ/*
699ddef9bb367b19383df627e388cb4c01c86ddba6cJeff Garzik * module options
700ddef9bb367b19383df627e388cb4c01c86ddba6cJeff Garzik */
701ddef9bb367b19383df627e388cb4c01c86ddba6cJeff Garzikstatic int msi;	      /* Use PCI msi; either zero (off, default) or non-zero */
702ddef9bb367b19383df627e388cb4c01c86ddba6cJeff Garzik
703ddef9bb367b19383df627e388cb4c01c86ddba6cJeff Garzik
704d88184fb2348a50f7c34f5d49a901c875b2e0114Jeff Garzik/* move to PCI layer or libata core? */
705d88184fb2348a50f7c34f5d49a901c875b2e0114Jeff Garzikstatic int pci_go_64(struct pci_dev *pdev)
706d88184fb2348a50f7c34f5d49a901c875b2e0114Jeff Garzik{
707d88184fb2348a50f7c34f5d49a901c875b2e0114Jeff Garzik	int rc;
708d88184fb2348a50f7c34f5d49a901c875b2e0114Jeff Garzik
709d88184fb2348a50f7c34f5d49a901c875b2e0114Jeff Garzik	if (!pci_set_dma_mask(pdev, DMA_64BIT_MASK)) {
710d88184fb2348a50f7c34f5d49a901c875b2e0114Jeff Garzik		rc = pci_set_consistent_dma_mask(pdev, DMA_64BIT_MASK);
711d88184fb2348a50f7c34f5d49a901c875b2e0114Jeff Garzik		if (rc) {
712d88184fb2348a50f7c34f5d49a901c875b2e0114Jeff Garzik			rc = pci_set_consistent_dma_mask(pdev, DMA_32BIT_MASK);
713d88184fb2348a50f7c34f5d49a901c875b2e0114Jeff Garzik			if (rc) {
714d88184fb2348a50f7c34f5d49a901c875b2e0114Jeff Garzik				dev_printk(KERN_ERR, &pdev->dev,
715d88184fb2348a50f7c34f5d49a901c875b2e0114Jeff Garzik					   "64-bit DMA enable failed\n");
716d88184fb2348a50f7c34f5d49a901c875b2e0114Jeff Garzik				return rc;
717d88184fb2348a50f7c34f5d49a901c875b2e0114Jeff Garzik			}
718d88184fb2348a50f7c34f5d49a901c875b2e0114Jeff Garzik		}
719d88184fb2348a50f7c34f5d49a901c875b2e0114Jeff Garzik	} else {
720d88184fb2348a50f7c34f5d49a901c875b2e0114Jeff Garzik		rc = pci_set_dma_mask(pdev, DMA_32BIT_MASK);
721d88184fb2348a50f7c34f5d49a901c875b2e0114Jeff Garzik		if (rc) {
722d88184fb2348a50f7c34f5d49a901c875b2e0114Jeff Garzik			dev_printk(KERN_ERR, &pdev->dev,
723d88184fb2348a50f7c34f5d49a901c875b2e0114Jeff Garzik				   "32-bit DMA enable failed\n");
724d88184fb2348a50f7c34f5d49a901c875b2e0114Jeff Garzik			return rc;
725d88184fb2348a50f7c34f5d49a901c875b2e0114Jeff Garzik		}
726d88184fb2348a50f7c34f5d49a901c875b2e0114Jeff Garzik		rc = pci_set_consistent_dma_mask(pdev, DMA_32BIT_MASK);
727d88184fb2348a50f7c34f5d49a901c875b2e0114Jeff Garzik		if (rc) {
728d88184fb2348a50f7c34f5d49a901c875b2e0114Jeff Garzik			dev_printk(KERN_ERR, &pdev->dev,
729d88184fb2348a50f7c34f5d49a901c875b2e0114Jeff Garzik				   "32-bit consistent DMA enable failed\n");
730d88184fb2348a50f7c34f5d49a901c875b2e0114Jeff Garzik			return rc;
731d88184fb2348a50f7c34f5d49a901c875b2e0114Jeff Garzik		}
732d88184fb2348a50f7c34f5d49a901c875b2e0114Jeff Garzik	}
733d88184fb2348a50f7c34f5d49a901c875b2e0114Jeff Garzik
734d88184fb2348a50f7c34f5d49a901c875b2e0114Jeff Garzik	return rc;
735d88184fb2348a50f7c34f5d49a901c875b2e0114Jeff Garzik}
736d88184fb2348a50f7c34f5d49a901c875b2e0114Jeff Garzik
737ddef9bb367b19383df627e388cb4c01c86ddba6cJeff Garzik/*
73820f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ * Functions
73920f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ */
74020f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ
74120f733e7d75a16bffc34842b7682c9247dd5f954Brett Russstatic inline void writelfl(unsigned long data, void __iomem *addr)
74220f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ{
74320f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ	writel(data, addr);
74420f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ	(void) readl(addr);	/* flush to avoid PCI posted write */
74520f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ}
74620f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ
74720f733e7d75a16bffc34842b7682c9247dd5f954Brett Russstatic inline void __iomem *mv_hc_base(void __iomem *base, unsigned int hc)
74820f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ{
74920f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ	return (base + MV_SATAHC0_REG_BASE + (hc * MV_SATAHC_REG_SZ));
75020f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ}
75120f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ
752c9d39130123238ac18478a42e25cb7996eacfcc0Jeff Garzikstatic inline unsigned int mv_hc_from_port(unsigned int port)
753c9d39130123238ac18478a42e25cb7996eacfcc0Jeff Garzik{
754c9d39130123238ac18478a42e25cb7996eacfcc0Jeff Garzik	return port >> MV_PORT_HC_SHIFT;
755c9d39130123238ac18478a42e25cb7996eacfcc0Jeff Garzik}
756c9d39130123238ac18478a42e25cb7996eacfcc0Jeff Garzik
757c9d39130123238ac18478a42e25cb7996eacfcc0Jeff Garzikstatic inline unsigned int mv_hardport_from_port(unsigned int port)
758c9d39130123238ac18478a42e25cb7996eacfcc0Jeff Garzik{
759c9d39130123238ac18478a42e25cb7996eacfcc0Jeff Garzik	return port & MV_PORT_MASK;
760c9d39130123238ac18478a42e25cb7996eacfcc0Jeff Garzik}
761c9d39130123238ac18478a42e25cb7996eacfcc0Jeff Garzik
762c9d39130123238ac18478a42e25cb7996eacfcc0Jeff Garzikstatic inline void __iomem *mv_hc_base_from_port(void __iomem *base,
763c9d39130123238ac18478a42e25cb7996eacfcc0Jeff Garzik						 unsigned int port)
764c9d39130123238ac18478a42e25cb7996eacfcc0Jeff Garzik{
765c9d39130123238ac18478a42e25cb7996eacfcc0Jeff Garzik	return mv_hc_base(base, mv_hc_from_port(port));
766c9d39130123238ac18478a42e25cb7996eacfcc0Jeff Garzik}
767c9d39130123238ac18478a42e25cb7996eacfcc0Jeff Garzik
76820f733e7d75a16bffc34842b7682c9247dd5f954Brett Russstatic inline void __iomem *mv_port_base(void __iomem *base, unsigned int port)
76920f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ{
770c9d39130123238ac18478a42e25cb7996eacfcc0Jeff Garzik	return  mv_hc_base_from_port(base, port) +
7718b260248d9e0e8b64bb72fd4dee03ad86984c344Jeff Garzik		MV_SATAHC_ARBTR_REG_SZ +
772c9d39130123238ac18478a42e25cb7996eacfcc0Jeff Garzik		(mv_hardport_from_port(port) * MV_PORT_REG_SZ);
77320f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ}
77420f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ
77520f733e7d75a16bffc34842b7682c9247dd5f954Brett Russstatic inline void __iomem *mv_ap_base(struct ata_port *ap)
77620f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ{
7770d5ff566779f894ca9937231a181eb31e4adff0eTejun Heo	return mv_port_base(ap->host->iomap[MV_PRIMARY_BAR], ap->port_no);
77820f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ}
77920f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ
780cca3974e48607c3775dc73b544a5700b2e37c21aJeff Garzikstatic inline int mv_get_hc_count(unsigned long port_flags)
78131961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ{
782cca3974e48607c3775dc73b544a5700b2e37c21aJeff Garzik	return ((port_flags & MV_FLAG_DUAL_HC) ? 2 : 1);
78331961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ}
78431961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ
78531961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russstatic void mv_irq_clear(struct ata_port *ap)
78620f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ{
78720f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ}
78820f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ
789c5d3e45a2200a0905dc45b72714726b7aac3aaf1Jeff Garzikstatic void mv_set_edma_ptrs(void __iomem *port_mmio,
790c5d3e45a2200a0905dc45b72714726b7aac3aaf1Jeff Garzik			     struct mv_host_priv *hpriv,
791c5d3e45a2200a0905dc45b72714726b7aac3aaf1Jeff Garzik			     struct mv_port_priv *pp)
792c5d3e45a2200a0905dc45b72714726b7aac3aaf1Jeff Garzik{
793bdd4dddee325a7dce3e84cf48201a06aa8508aa4Jeff Garzik	u32 index;
794bdd4dddee325a7dce3e84cf48201a06aa8508aa4Jeff Garzik
795c5d3e45a2200a0905dc45b72714726b7aac3aaf1Jeff Garzik	/*
796c5d3e45a2200a0905dc45b72714726b7aac3aaf1Jeff Garzik	 * initialize request queue
797c5d3e45a2200a0905dc45b72714726b7aac3aaf1Jeff Garzik	 */
798bdd4dddee325a7dce3e84cf48201a06aa8508aa4Jeff Garzik	index = (pp->req_idx & MV_MAX_Q_DEPTH_MASK) << EDMA_REQ_Q_PTR_SHIFT;
799bdd4dddee325a7dce3e84cf48201a06aa8508aa4Jeff Garzik
800c5d3e45a2200a0905dc45b72714726b7aac3aaf1Jeff Garzik	WARN_ON(pp->crqb_dma & 0x3ff);
801c5d3e45a2200a0905dc45b72714726b7aac3aaf1Jeff Garzik	writel((pp->crqb_dma >> 16) >> 16, port_mmio + EDMA_REQ_Q_BASE_HI_OFS);
802bdd4dddee325a7dce3e84cf48201a06aa8508aa4Jeff Garzik	writelfl((pp->crqb_dma & EDMA_REQ_Q_BASE_LO_MASK) | index,
803c5d3e45a2200a0905dc45b72714726b7aac3aaf1Jeff Garzik		 port_mmio + EDMA_REQ_Q_IN_PTR_OFS);
804c5d3e45a2200a0905dc45b72714726b7aac3aaf1Jeff Garzik
805c5d3e45a2200a0905dc45b72714726b7aac3aaf1Jeff Garzik	if (hpriv->hp_flags & MV_HP_ERRATA_XX42A0)
806bdd4dddee325a7dce3e84cf48201a06aa8508aa4Jeff Garzik		writelfl((pp->crqb_dma & 0xffffffff) | index,
807c5d3e45a2200a0905dc45b72714726b7aac3aaf1Jeff Garzik			 port_mmio + EDMA_REQ_Q_OUT_PTR_OFS);
808c5d3e45a2200a0905dc45b72714726b7aac3aaf1Jeff Garzik	else
809bdd4dddee325a7dce3e84cf48201a06aa8508aa4Jeff Garzik		writelfl(index, port_mmio + EDMA_REQ_Q_OUT_PTR_OFS);
810c5d3e45a2200a0905dc45b72714726b7aac3aaf1Jeff Garzik
811c5d3e45a2200a0905dc45b72714726b7aac3aaf1Jeff Garzik	/*
812c5d3e45a2200a0905dc45b72714726b7aac3aaf1Jeff Garzik	 * initialize response queue
813c5d3e45a2200a0905dc45b72714726b7aac3aaf1Jeff Garzik	 */
814bdd4dddee325a7dce3e84cf48201a06aa8508aa4Jeff Garzik	index = (pp->resp_idx & MV_MAX_Q_DEPTH_MASK) << EDMA_RSP_Q_PTR_SHIFT;
815bdd4dddee325a7dce3e84cf48201a06aa8508aa4Jeff Garzik
816c5d3e45a2200a0905dc45b72714726b7aac3aaf1Jeff Garzik	WARN_ON(pp->crpb_dma & 0xff);
817c5d3e45a2200a0905dc45b72714726b7aac3aaf1Jeff Garzik	writel((pp->crpb_dma >> 16) >> 16, port_mmio + EDMA_RSP_Q_BASE_HI_OFS);
818c5d3e45a2200a0905dc45b72714726b7aac3aaf1Jeff Garzik
819c5d3e45a2200a0905dc45b72714726b7aac3aaf1Jeff Garzik	if (hpriv->hp_flags & MV_HP_ERRATA_XX42A0)
820bdd4dddee325a7dce3e84cf48201a06aa8508aa4Jeff Garzik		writelfl((pp->crpb_dma & 0xffffffff) | index,
821c5d3e45a2200a0905dc45b72714726b7aac3aaf1Jeff Garzik			 port_mmio + EDMA_RSP_Q_IN_PTR_OFS);
822c5d3e45a2200a0905dc45b72714726b7aac3aaf1Jeff Garzik	else
823bdd4dddee325a7dce3e84cf48201a06aa8508aa4Jeff Garzik		writelfl(index, port_mmio + EDMA_RSP_Q_IN_PTR_OFS);
824c5d3e45a2200a0905dc45b72714726b7aac3aaf1Jeff Garzik
825bdd4dddee325a7dce3e84cf48201a06aa8508aa4Jeff Garzik	writelfl((pp->crpb_dma & EDMA_RSP_Q_BASE_LO_MASK) | index,
826c5d3e45a2200a0905dc45b72714726b7aac3aaf1Jeff Garzik		 port_mmio + EDMA_RSP_Q_OUT_PTR_OFS);
827c5d3e45a2200a0905dc45b72714726b7aac3aaf1Jeff Garzik}
828c5d3e45a2200a0905dc45b72714726b7aac3aaf1Jeff Garzik
82905b308e1df6d9d673daedb517969241f41278b52Brett Russ/**
83005b308e1df6d9d673daedb517969241f41278b52Brett Russ *      mv_start_dma - Enable eDMA engine
83105b308e1df6d9d673daedb517969241f41278b52Brett Russ *      @base: port base address
83205b308e1df6d9d673daedb517969241f41278b52Brett Russ *      @pp: port private data
83305b308e1df6d9d673daedb517969241f41278b52Brett Russ *
834beec7dbc6ff003bbc94de62b3323519c878fb2acTejun Heo *      Verify the local cache of the eDMA state is accurate with a
835beec7dbc6ff003bbc94de62b3323519c878fb2acTejun Heo *      WARN_ON.
83605b308e1df6d9d673daedb517969241f41278b52Brett Russ *
83705b308e1df6d9d673daedb517969241f41278b52Brett Russ *      LOCKING:
83805b308e1df6d9d673daedb517969241f41278b52Brett Russ *      Inherited from caller.
83905b308e1df6d9d673daedb517969241f41278b52Brett Russ */
8400c58912e192fc3a4835d772aafa40b72552b819fMark Lordstatic void mv_start_dma(struct ata_port *ap, void __iomem *port_mmio,
841c5d3e45a2200a0905dc45b72714726b7aac3aaf1Jeff Garzik			 struct mv_port_priv *pp)
84220f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ{
843c5d3e45a2200a0905dc45b72714726b7aac3aaf1Jeff Garzik	if (!(pp->pp_flags & MV_PP_FLAG_EDMA_EN)) {
8440c58912e192fc3a4835d772aafa40b72552b819fMark Lord		struct mv_host_priv *hpriv = ap->host->private_data;
8450c58912e192fc3a4835d772aafa40b72552b819fMark Lord		int hard_port = mv_hardport_from_port(ap->port_no);
8460c58912e192fc3a4835d772aafa40b72552b819fMark Lord		void __iomem *hc_mmio = mv_hc_base_from_port(
8470c58912e192fc3a4835d772aafa40b72552b819fMark Lord				ap->host->iomap[MV_PRIMARY_BAR], hard_port);
8480c58912e192fc3a4835d772aafa40b72552b819fMark Lord		u32 hc_irq_cause, ipending;
8490c58912e192fc3a4835d772aafa40b72552b819fMark Lord
850bdd4dddee325a7dce3e84cf48201a06aa8508aa4Jeff Garzik		/* clear EDMA event indicators, if any */
851f630d562829fcd8160a118f98c1e5b9cdb4e703eMark Lord		writelfl(0, port_mmio + EDMA_ERR_IRQ_CAUSE_OFS);
852bdd4dddee325a7dce3e84cf48201a06aa8508aa4Jeff Garzik
8530c58912e192fc3a4835d772aafa40b72552b819fMark Lord		/* clear EDMA interrupt indicator, if any */
8540c58912e192fc3a4835d772aafa40b72552b819fMark Lord		hc_irq_cause = readl(hc_mmio + HC_IRQ_CAUSE_OFS);
8550c58912e192fc3a4835d772aafa40b72552b819fMark Lord		ipending = (DEV_IRQ << hard_port) |
8560c58912e192fc3a4835d772aafa40b72552b819fMark Lord				(CRPB_DMA_DONE << hard_port);
8570c58912e192fc3a4835d772aafa40b72552b819fMark Lord		if (hc_irq_cause & ipending) {
8580c58912e192fc3a4835d772aafa40b72552b819fMark Lord			writelfl(hc_irq_cause & ~ipending,
8590c58912e192fc3a4835d772aafa40b72552b819fMark Lord				 hc_mmio + HC_IRQ_CAUSE_OFS);
8600c58912e192fc3a4835d772aafa40b72552b819fMark Lord		}
8610c58912e192fc3a4835d772aafa40b72552b819fMark Lord
8620c58912e192fc3a4835d772aafa40b72552b819fMark Lord		mv_edma_cfg(ap, hpriv, port_mmio);
8630c58912e192fc3a4835d772aafa40b72552b819fMark Lord
8640c58912e192fc3a4835d772aafa40b72552b819fMark Lord		/* clear FIS IRQ Cause */
8650c58912e192fc3a4835d772aafa40b72552b819fMark Lord		writelfl(0, port_mmio + SATA_FIS_IRQ_CAUSE_OFS);
8660c58912e192fc3a4835d772aafa40b72552b819fMark Lord
867f630d562829fcd8160a118f98c1e5b9cdb4e703eMark Lord		mv_set_edma_ptrs(port_mmio, hpriv, pp);
868bdd4dddee325a7dce3e84cf48201a06aa8508aa4Jeff Garzik
869f630d562829fcd8160a118f98c1e5b9cdb4e703eMark Lord		writelfl(EDMA_EN, port_mmio + EDMA_CMD_OFS);
870afb0edd922c7ed6e73678730921dfcccebec17e8Brett Russ		pp->pp_flags |= MV_PP_FLAG_EDMA_EN;
871afb0edd922c7ed6e73678730921dfcccebec17e8Brett Russ	}
872f630d562829fcd8160a118f98c1e5b9cdb4e703eMark Lord	WARN_ON(!(EDMA_EN & readl(port_mmio + EDMA_CMD_OFS)));
87320f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ}
87420f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ
87505b308e1df6d9d673daedb517969241f41278b52Brett Russ/**
8760ea9e179f436f153fc19fdaef7abbc1e0da20762Jeff Garzik *      __mv_stop_dma - Disable eDMA engine
87705b308e1df6d9d673daedb517969241f41278b52Brett Russ *      @ap: ATA channel to manipulate
87805b308e1df6d9d673daedb517969241f41278b52Brett Russ *
879beec7dbc6ff003bbc94de62b3323519c878fb2acTejun Heo *      Verify the local cache of the eDMA state is accurate with a
880beec7dbc6ff003bbc94de62b3323519c878fb2acTejun Heo *      WARN_ON.
88105b308e1df6d9d673daedb517969241f41278b52Brett Russ *
88205b308e1df6d9d673daedb517969241f41278b52Brett Russ *      LOCKING:
88305b308e1df6d9d673daedb517969241f41278b52Brett Russ *      Inherited from caller.
88405b308e1df6d9d673daedb517969241f41278b52Brett Russ */
8850ea9e179f436f153fc19fdaef7abbc1e0da20762Jeff Garzikstatic int __mv_stop_dma(struct ata_port *ap)
88620f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ{
88731961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ	void __iomem *port_mmio = mv_ap_base(ap);
88831961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ	struct mv_port_priv *pp	= ap->private_data;
88931961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ	u32 reg;
890c5d3e45a2200a0905dc45b72714726b7aac3aaf1Jeff Garzik	int i, err = 0;
89131961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ
8924537deb5e90b717a725b3d74b58b4bb1d28443d0Jeff Garzik	if (pp->pp_flags & MV_PP_FLAG_EDMA_EN) {
893afb0edd922c7ed6e73678730921dfcccebec17e8Brett Russ		/* Disable EDMA if active.   The disable bit auto clears.
89431961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ		 */
89531961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ		writelfl(EDMA_DS, port_mmio + EDMA_CMD_OFS);
89631961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ		pp->pp_flags &= ~MV_PP_FLAG_EDMA_EN;
897afb0edd922c7ed6e73678730921dfcccebec17e8Brett Russ	} else {
898beec7dbc6ff003bbc94de62b3323519c878fb2acTejun Heo		WARN_ON(EDMA_EN & readl(port_mmio + EDMA_CMD_OFS));
8992dcb407e61458ded17503d6bd12b8c064965368bJeff Garzik	}
9008b260248d9e0e8b64bb72fd4dee03ad86984c344Jeff Garzik
90131961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ	/* now properly wait for the eDMA to stop */
90231961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ	for (i = 1000; i > 0; i--) {
90331961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ		reg = readl(port_mmio + EDMA_CMD_OFS);
9044537deb5e90b717a725b3d74b58b4bb1d28443d0Jeff Garzik		if (!(reg & EDMA_EN))
90531961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ			break;
9064537deb5e90b717a725b3d74b58b4bb1d28443d0Jeff Garzik
90731961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ		udelay(100);
90831961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ	}
90931961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ
910c5d3e45a2200a0905dc45b72714726b7aac3aaf1Jeff Garzik	if (reg & EDMA_EN) {
911f15a1dafed22d5037e0feea7528e1eeb28a1a7a3Tejun Heo		ata_port_printk(ap, KERN_ERR, "Unable to stop eDMA\n");
912c5d3e45a2200a0905dc45b72714726b7aac3aaf1Jeff Garzik		err = -EIO;
91331961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ	}
914c5d3e45a2200a0905dc45b72714726b7aac3aaf1Jeff Garzik
915c5d3e45a2200a0905dc45b72714726b7aac3aaf1Jeff Garzik	return err;
91620f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ}
91720f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ
9180ea9e179f436f153fc19fdaef7abbc1e0da20762Jeff Garzikstatic int mv_stop_dma(struct ata_port *ap)
9190ea9e179f436f153fc19fdaef7abbc1e0da20762Jeff Garzik{
9200ea9e179f436f153fc19fdaef7abbc1e0da20762Jeff Garzik	unsigned long flags;
9210ea9e179f436f153fc19fdaef7abbc1e0da20762Jeff Garzik	int rc;
9220ea9e179f436f153fc19fdaef7abbc1e0da20762Jeff Garzik
9230ea9e179f436f153fc19fdaef7abbc1e0da20762Jeff Garzik	spin_lock_irqsave(&ap->host->lock, flags);
9240ea9e179f436f153fc19fdaef7abbc1e0da20762Jeff Garzik	rc = __mv_stop_dma(ap);
9250ea9e179f436f153fc19fdaef7abbc1e0da20762Jeff Garzik	spin_unlock_irqrestore(&ap->host->lock, flags);
9260ea9e179f436f153fc19fdaef7abbc1e0da20762Jeff Garzik
9270ea9e179f436f153fc19fdaef7abbc1e0da20762Jeff Garzik	return rc;
9280ea9e179f436f153fc19fdaef7abbc1e0da20762Jeff Garzik}
9290ea9e179f436f153fc19fdaef7abbc1e0da20762Jeff Garzik
9308a70f8dc08dd40b7f8ac77280eaa99a8c6bc46f4Jeff Garzik#ifdef ATA_DEBUG
93131961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russstatic void mv_dump_mem(void __iomem *start, unsigned bytes)
93220f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ{
93331961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ	int b, w;
93431961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ	for (b = 0; b < bytes; ) {
93531961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ		DPRINTK("%p: ", start + b);
93631961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ		for (w = 0; b < bytes && w < 4; w++) {
9372dcb407e61458ded17503d6bd12b8c064965368bJeff Garzik			printk("%08x ", readl(start + b));
93831961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ			b += sizeof(u32);
93931961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ		}
94031961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ		printk("\n");
94131961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ	}
94231961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ}
9438a70f8dc08dd40b7f8ac77280eaa99a8c6bc46f4Jeff Garzik#endif
9448a70f8dc08dd40b7f8ac77280eaa99a8c6bc46f4Jeff Garzik
94531961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russstatic void mv_dump_pci_cfg(struct pci_dev *pdev, unsigned bytes)
94631961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ{
94731961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ#ifdef ATA_DEBUG
94831961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ	int b, w;
94931961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ	u32 dw;
95031961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ	for (b = 0; b < bytes; ) {
95131961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ		DPRINTK("%02x: ", b);
95231961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ		for (w = 0; b < bytes && w < 4; w++) {
9532dcb407e61458ded17503d6bd12b8c064965368bJeff Garzik			(void) pci_read_config_dword(pdev, b, &dw);
9542dcb407e61458ded17503d6bd12b8c064965368bJeff Garzik			printk("%08x ", dw);
95531961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ			b += sizeof(u32);
95631961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ		}
95731961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ		printk("\n");
95831961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ	}
95931961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ#endif
96031961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ}
96131961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russstatic void mv_dump_all_regs(void __iomem *mmio_base, int port,
96231961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ			     struct pci_dev *pdev)
96331961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ{
96431961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ#ifdef ATA_DEBUG
9658b260248d9e0e8b64bb72fd4dee03ad86984c344Jeff Garzik	void __iomem *hc_base = mv_hc_base(mmio_base,
96631961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ					   port >> MV_PORT_HC_SHIFT);
96731961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ	void __iomem *port_base;
96831961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ	int start_port, num_ports, p, start_hc, num_hcs, hc;
96931961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ
97031961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ	if (0 > port) {
97131961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ		start_hc = start_port = 0;
97231961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ		num_ports = 8;		/* shld be benign for 4 port devs */
97331961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ		num_hcs = 2;
97431961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ	} else {
97531961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ		start_hc = port >> MV_PORT_HC_SHIFT;
97631961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ		start_port = port;
97731961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ		num_ports = num_hcs = 1;
97831961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ	}
9798b260248d9e0e8b64bb72fd4dee03ad86984c344Jeff Garzik	DPRINTK("All registers for port(s) %u-%u:\n", start_port,
98031961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ		num_ports > 1 ? num_ports - 1 : start_port);
98131961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ
98231961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ	if (NULL != pdev) {
98331961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ		DPRINTK("PCI config space regs:\n");
98431961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ		mv_dump_pci_cfg(pdev, 0x68);
98531961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ	}
98631961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ	DPRINTK("PCI regs:\n");
98731961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ	mv_dump_mem(mmio_base+0xc00, 0x3c);
98831961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ	mv_dump_mem(mmio_base+0xd00, 0x34);
98931961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ	mv_dump_mem(mmio_base+0xf00, 0x4);
99031961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ	mv_dump_mem(mmio_base+0x1d00, 0x6c);
99131961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ	for (hc = start_hc; hc < start_hc + num_hcs; hc++) {
992d220c37e0a3c9a47ae00e87e044d963b3ea040bcDan Aloni		hc_base = mv_hc_base(mmio_base, hc);
99331961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ		DPRINTK("HC regs (HC %i):\n", hc);
99431961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ		mv_dump_mem(hc_base, 0x1c);
99531961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ	}
99631961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ	for (p = start_port; p < start_port + num_ports; p++) {
99731961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ		port_base = mv_port_base(mmio_base, p);
9982dcb407e61458ded17503d6bd12b8c064965368bJeff Garzik		DPRINTK("EDMA regs (port %i):\n", p);
99931961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ		mv_dump_mem(port_base, 0x54);
10002dcb407e61458ded17503d6bd12b8c064965368bJeff Garzik		DPRINTK("SATA regs (port %i):\n", p);
100131961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ		mv_dump_mem(port_base+0x300, 0x60);
100231961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ	}
100331961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ#endif
100420f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ}
100520f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ
100620f733e7d75a16bffc34842b7682c9247dd5f954Brett Russstatic unsigned int mv_scr_offset(unsigned int sc_reg_in)
100720f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ{
100820f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ	unsigned int ofs;
100920f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ
101020f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ	switch (sc_reg_in) {
101120f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ	case SCR_STATUS:
101220f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ	case SCR_CONTROL:
101320f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ	case SCR_ERROR:
101420f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ		ofs = SATA_STATUS_OFS + (sc_reg_in * sizeof(u32));
101520f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ		break;
101620f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ	case SCR_ACTIVE:
101720f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ		ofs = SATA_ACTIVE_OFS;   /* active is not with the others */
101820f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ		break;
101920f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ	default:
102020f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ		ofs = 0xffffffffU;
102120f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ		break;
102220f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ	}
102320f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ	return ofs;
102420f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ}
102520f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ
1026da3dbb17a0e9a9ec7f5aed95f1fddadb790edc9dTejun Heostatic int mv_scr_read(struct ata_port *ap, unsigned int sc_reg_in, u32 *val)
102720f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ{
102820f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ	unsigned int ofs = mv_scr_offset(sc_reg_in);
102920f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ
1030da3dbb17a0e9a9ec7f5aed95f1fddadb790edc9dTejun Heo	if (ofs != 0xffffffffU) {
1031da3dbb17a0e9a9ec7f5aed95f1fddadb790edc9dTejun Heo		*val = readl(mv_ap_base(ap) + ofs);
1032da3dbb17a0e9a9ec7f5aed95f1fddadb790edc9dTejun Heo		return 0;
1033da3dbb17a0e9a9ec7f5aed95f1fddadb790edc9dTejun Heo	} else
1034da3dbb17a0e9a9ec7f5aed95f1fddadb790edc9dTejun Heo		return -EINVAL;
103520f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ}
103620f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ
1037da3dbb17a0e9a9ec7f5aed95f1fddadb790edc9dTejun Heostatic int mv_scr_write(struct ata_port *ap, unsigned int sc_reg_in, u32 val)
103820f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ{
103920f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ	unsigned int ofs = mv_scr_offset(sc_reg_in);
104020f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ
1041da3dbb17a0e9a9ec7f5aed95f1fddadb790edc9dTejun Heo	if (ofs != 0xffffffffU) {
104220f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ		writelfl(val, mv_ap_base(ap) + ofs);
1043da3dbb17a0e9a9ec7f5aed95f1fddadb790edc9dTejun Heo		return 0;
1044da3dbb17a0e9a9ec7f5aed95f1fddadb790edc9dTejun Heo	} else
1045da3dbb17a0e9a9ec7f5aed95f1fddadb790edc9dTejun Heo		return -EINVAL;
104620f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ}
104720f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ
1048c5d3e45a2200a0905dc45b72714726b7aac3aaf1Jeff Garzikstatic void mv_edma_cfg(struct ata_port *ap, struct mv_host_priv *hpriv,
1049c5d3e45a2200a0905dc45b72714726b7aac3aaf1Jeff Garzik			void __iomem *port_mmio)
1050e4e7b89280d1d666e2c09e5ad36cf071796c4c7eJeff Garzik{
10510c58912e192fc3a4835d772aafa40b72552b819fMark Lord	u32 cfg;
1052e4e7b89280d1d666e2c09e5ad36cf071796c4c7eJeff Garzik
1053e4e7b89280d1d666e2c09e5ad36cf071796c4c7eJeff Garzik	/* set up non-NCQ EDMA configuration */
10540c58912e192fc3a4835d772aafa40b72552b819fMark Lord	cfg = EDMA_CFG_Q_DEPTH;		/* always 0x1f for *all* chips */
1055e4e7b89280d1d666e2c09e5ad36cf071796c4c7eJeff Garzik
10560c58912e192fc3a4835d772aafa40b72552b819fMark Lord	if (IS_GEN_I(hpriv))
1057e4e7b89280d1d666e2c09e5ad36cf071796c4c7eJeff Garzik		cfg |= (1 << 8);	/* enab config burst size mask */
1058e4e7b89280d1d666e2c09e5ad36cf071796c4c7eJeff Garzik
10590c58912e192fc3a4835d772aafa40b72552b819fMark Lord	else if (IS_GEN_II(hpriv))
1060e4e7b89280d1d666e2c09e5ad36cf071796c4c7eJeff Garzik		cfg |= EDMA_CFG_RD_BRST_EXT | EDMA_CFG_WR_BUFF_LEN;
1061e4e7b89280d1d666e2c09e5ad36cf071796c4c7eJeff Garzik
1062e4e7b89280d1d666e2c09e5ad36cf071796c4c7eJeff Garzik	else if (IS_GEN_IIE(hpriv)) {
1063e728eabea110da90e69c05855e3a11174edb77efJeff Garzik		cfg |= (1 << 23);	/* do not mask PM field in rx'd FIS */
1064e728eabea110da90e69c05855e3a11174edb77efJeff Garzik		cfg |= (1 << 22);	/* enab 4-entry host queue cache */
1065e4e7b89280d1d666e2c09e5ad36cf071796c4c7eJeff Garzik		cfg |= (1 << 18);	/* enab early completion */
1066e728eabea110da90e69c05855e3a11174edb77efJeff Garzik		cfg |= (1 << 17);	/* enab cut-through (dis stor&forwrd) */
1067e4e7b89280d1d666e2c09e5ad36cf071796c4c7eJeff Garzik	}
1068e4e7b89280d1d666e2c09e5ad36cf071796c4c7eJeff Garzik
1069e4e7b89280d1d666e2c09e5ad36cf071796c4c7eJeff Garzik	writelfl(cfg, port_mmio + EDMA_CFG_OFS);
1070e4e7b89280d1d666e2c09e5ad36cf071796c4c7eJeff Garzik}
1071e4e7b89280d1d666e2c09e5ad36cf071796c4c7eJeff Garzik
107205b308e1df6d9d673daedb517969241f41278b52Brett Russ/**
107305b308e1df6d9d673daedb517969241f41278b52Brett Russ *      mv_port_start - Port specific init/start routine.
107405b308e1df6d9d673daedb517969241f41278b52Brett Russ *      @ap: ATA channel to manipulate
107505b308e1df6d9d673daedb517969241f41278b52Brett Russ *
107605b308e1df6d9d673daedb517969241f41278b52Brett Russ *      Allocate and point to DMA memory, init port private memory,
107705b308e1df6d9d673daedb517969241f41278b52Brett Russ *      zero indices.
107805b308e1df6d9d673daedb517969241f41278b52Brett Russ *
107905b308e1df6d9d673daedb517969241f41278b52Brett Russ *      LOCKING:
108005b308e1df6d9d673daedb517969241f41278b52Brett Russ *      Inherited from caller.
108105b308e1df6d9d673daedb517969241f41278b52Brett Russ */
108231961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russstatic int mv_port_start(struct ata_port *ap)
108331961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ{
1084cca3974e48607c3775dc73b544a5700b2e37c21aJeff Garzik	struct device *dev = ap->host->dev;
1085cca3974e48607c3775dc73b544a5700b2e37c21aJeff Garzik	struct mv_host_priv *hpriv = ap->host->private_data;
108631961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ	struct mv_port_priv *pp;
108731961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ	void __iomem *port_mmio = mv_ap_base(ap);
108831961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ	void *mem;
108931961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ	dma_addr_t mem_dma;
10900ea9e179f436f153fc19fdaef7abbc1e0da20762Jeff Garzik	unsigned long flags;
109124dc5f33ea4b504cfbd23fa159a4cacba8e4d800Tejun Heo	int rc;
109231961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ
109324dc5f33ea4b504cfbd23fa159a4cacba8e4d800Tejun Heo	pp = devm_kzalloc(dev, sizeof(*pp), GFP_KERNEL);
10946037d6bbdff65eb5a84fe35e140f4da4f7cc103aJeff Garzik	if (!pp)
109524dc5f33ea4b504cfbd23fa159a4cacba8e4d800Tejun Heo		return -ENOMEM;
109631961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ
109724dc5f33ea4b504cfbd23fa159a4cacba8e4d800Tejun Heo	mem = dmam_alloc_coherent(dev, MV_PORT_PRIV_DMA_SZ, &mem_dma,
109824dc5f33ea4b504cfbd23fa159a4cacba8e4d800Tejun Heo				  GFP_KERNEL);
10996037d6bbdff65eb5a84fe35e140f4da4f7cc103aJeff Garzik	if (!mem)
110024dc5f33ea4b504cfbd23fa159a4cacba8e4d800Tejun Heo		return -ENOMEM;
110131961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ	memset(mem, 0, MV_PORT_PRIV_DMA_SZ);
110231961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ
11036037d6bbdff65eb5a84fe35e140f4da4f7cc103aJeff Garzik	rc = ata_pad_alloc(ap, dev);
11046037d6bbdff65eb5a84fe35e140f4da4f7cc103aJeff Garzik	if (rc)
110524dc5f33ea4b504cfbd23fa159a4cacba8e4d800Tejun Heo		return rc;
11066037d6bbdff65eb5a84fe35e140f4da4f7cc103aJeff Garzik
11078b260248d9e0e8b64bb72fd4dee03ad86984c344Jeff Garzik	/* First item in chunk of DMA memory:
110831961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ	 * 32-slot command request table (CRQB), 32 bytes each in size
110931961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ	 */
111031961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ	pp->crqb = mem;
111131961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ	pp->crqb_dma = mem_dma;
111231961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ	mem += MV_CRQB_Q_SZ;
111331961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ	mem_dma += MV_CRQB_Q_SZ;
111431961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ
11158b260248d9e0e8b64bb72fd4dee03ad86984c344Jeff Garzik	/* Second item:
111631961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ	 * 32-slot command response table (CRPB), 8 bytes each in size
111731961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ	 */
111831961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ	pp->crpb = mem;
111931961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ	pp->crpb_dma = mem_dma;
112031961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ	mem += MV_CRPB_Q_SZ;
112131961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ	mem_dma += MV_CRPB_Q_SZ;
112231961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ
112331961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ	/* Third item:
112431961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ	 * Table of scatter-gather descriptors (ePRD), 16 bytes each
112531961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ	 */
112631961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ	pp->sg_tbl = mem;
112731961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ	pp->sg_tbl_dma = mem_dma;
112831961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ
11290ea9e179f436f153fc19fdaef7abbc1e0da20762Jeff Garzik	spin_lock_irqsave(&ap->host->lock, flags);
11300ea9e179f436f153fc19fdaef7abbc1e0da20762Jeff Garzik
1131c5d3e45a2200a0905dc45b72714726b7aac3aaf1Jeff Garzik	mv_edma_cfg(ap, hpriv, port_mmio);
1132e4e7b89280d1d666e2c09e5ad36cf071796c4c7eJeff Garzik
1133c5d3e45a2200a0905dc45b72714726b7aac3aaf1Jeff Garzik	mv_set_edma_ptrs(port_mmio, hpriv, pp);
113431961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ
11350ea9e179f436f153fc19fdaef7abbc1e0da20762Jeff Garzik	spin_unlock_irqrestore(&ap->host->lock, flags);
11360ea9e179f436f153fc19fdaef7abbc1e0da20762Jeff Garzik
113731961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ	/* Don't turn on EDMA here...do it before DMA commands only.  Else
113831961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ	 * we'll be unable to send non-data, PIO, etc due to restricted access
113931961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ	 * to shadow regs.
114031961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ	 */
114131961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ	ap->private_data = pp;
114231961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ	return 0;
114331961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ}
114431961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ
114505b308e1df6d9d673daedb517969241f41278b52Brett Russ/**
114605b308e1df6d9d673daedb517969241f41278b52Brett Russ *      mv_port_stop - Port specific cleanup/stop routine.
114705b308e1df6d9d673daedb517969241f41278b52Brett Russ *      @ap: ATA channel to manipulate
114805b308e1df6d9d673daedb517969241f41278b52Brett Russ *
114905b308e1df6d9d673daedb517969241f41278b52Brett Russ *      Stop DMA, cleanup port memory.
115005b308e1df6d9d673daedb517969241f41278b52Brett Russ *
115105b308e1df6d9d673daedb517969241f41278b52Brett Russ *      LOCKING:
1152cca3974e48607c3775dc73b544a5700b2e37c21aJeff Garzik *      This routine uses the host lock to protect the DMA stop.
115305b308e1df6d9d673daedb517969241f41278b52Brett Russ */
115431961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russstatic void mv_port_stop(struct ata_port *ap)
115531961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ{
115631961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ	mv_stop_dma(ap);
115731961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ}
115831961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ
115905b308e1df6d9d673daedb517969241f41278b52Brett Russ/**
116005b308e1df6d9d673daedb517969241f41278b52Brett Russ *      mv_fill_sg - Fill out the Marvell ePRD (scatter gather) entries
116105b308e1df6d9d673daedb517969241f41278b52Brett Russ *      @qc: queued command whose SG list to source from
116205b308e1df6d9d673daedb517969241f41278b52Brett Russ *
116305b308e1df6d9d673daedb517969241f41278b52Brett Russ *      Populate the SG list and mark the last entry.
116405b308e1df6d9d673daedb517969241f41278b52Brett Russ *
116505b308e1df6d9d673daedb517969241f41278b52Brett Russ *      LOCKING:
116605b308e1df6d9d673daedb517969241f41278b52Brett Russ *      Inherited from caller.
116705b308e1df6d9d673daedb517969241f41278b52Brett Russ */
11686c08772e49622e90d39903e7ff0be1a0f463ac86Jeff Garzikstatic void mv_fill_sg(struct ata_queued_cmd *qc)
116931961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ{
117031961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ	struct mv_port_priv *pp = qc->ap->private_data;
1171972c26bdd6b58e7534473c4f7928584578cf43f4Jeff Garzik	struct scatterlist *sg;
11723be6cbd73f74b4a3da82cc7d6e1688a4ae595fc7Jeff Garzik	struct mv_sg *mv_sg, *last_sg = NULL;
1173ff2aeb1eb64c8a4770a6304f9addbae9f9828646Tejun Heo	unsigned int si;
117431961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ
1175d88184fb2348a50f7c34f5d49a901c875b2e0114Jeff Garzik	mv_sg = pp->sg_tbl;
1176ff2aeb1eb64c8a4770a6304f9addbae9f9828646Tejun Heo	for_each_sg(qc->sg, sg, qc->n_elem, si) {
1177d88184fb2348a50f7c34f5d49a901c875b2e0114Jeff Garzik		dma_addr_t addr = sg_dma_address(sg);
1178d88184fb2348a50f7c34f5d49a901c875b2e0114Jeff Garzik		u32 sg_len = sg_dma_len(sg);
117922374677d18c5eeefd3a283431d312b8c44fef02Jeff Garzik
11804007b493ee6e4a52c2b618ab8361847fba5bf116Olof Johansson		while (sg_len) {
11814007b493ee6e4a52c2b618ab8361847fba5bf116Olof Johansson			u32 offset = addr & 0xffff;
11824007b493ee6e4a52c2b618ab8361847fba5bf116Olof Johansson			u32 len = sg_len;
118322374677d18c5eeefd3a283431d312b8c44fef02Jeff Garzik
11844007b493ee6e4a52c2b618ab8361847fba5bf116Olof Johansson			if ((offset + sg_len > 0x10000))
11854007b493ee6e4a52c2b618ab8361847fba5bf116Olof Johansson				len = 0x10000 - offset;
11864007b493ee6e4a52c2b618ab8361847fba5bf116Olof Johansson
11874007b493ee6e4a52c2b618ab8361847fba5bf116Olof Johansson			mv_sg->addr = cpu_to_le32(addr & 0xffffffff);
11884007b493ee6e4a52c2b618ab8361847fba5bf116Olof Johansson			mv_sg->addr_hi = cpu_to_le32((addr >> 16) >> 16);
11896c08772e49622e90d39903e7ff0be1a0f463ac86Jeff Garzik			mv_sg->flags_size = cpu_to_le32(len & 0xffff);
11904007b493ee6e4a52c2b618ab8361847fba5bf116Olof Johansson
11914007b493ee6e4a52c2b618ab8361847fba5bf116Olof Johansson			sg_len -= len;
11924007b493ee6e4a52c2b618ab8361847fba5bf116Olof Johansson			addr += len;
11934007b493ee6e4a52c2b618ab8361847fba5bf116Olof Johansson
11943be6cbd73f74b4a3da82cc7d6e1688a4ae595fc7Jeff Garzik			last_sg = mv_sg;
11954007b493ee6e4a52c2b618ab8361847fba5bf116Olof Johansson			mv_sg++;
11964007b493ee6e4a52c2b618ab8361847fba5bf116Olof Johansson		}
119731961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ	}
11983be6cbd73f74b4a3da82cc7d6e1688a4ae595fc7Jeff Garzik
11993be6cbd73f74b4a3da82cc7d6e1688a4ae595fc7Jeff Garzik	if (likely(last_sg))
12003be6cbd73f74b4a3da82cc7d6e1688a4ae595fc7Jeff Garzik		last_sg->flags_size |= cpu_to_le32(EPRD_FLAG_END_OF_TBL);
120131961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ}
120231961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ
12035796d1c4c89efff823259fda35b08ea66ebf8b23Jeff Garzikstatic void mv_crqb_pack_cmd(__le16 *cmdw, u8 data, u8 addr, unsigned last)
120431961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ{
1205559eedad7f7764dacca33980127b4615011230e4Mark Lord	u16 tmp = data | (addr << CRQB_CMD_ADDR_SHIFT) | CRQB_CMD_CS |
120631961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ		(last ? CRQB_CMD_LAST : 0);
1207559eedad7f7764dacca33980127b4615011230e4Mark Lord	*cmdw = cpu_to_le16(tmp);
120831961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ}
120931961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ
121005b308e1df6d9d673daedb517969241f41278b52Brett Russ/**
121105b308e1df6d9d673daedb517969241f41278b52Brett Russ *      mv_qc_prep - Host specific command preparation.
121205b308e1df6d9d673daedb517969241f41278b52Brett Russ *      @qc: queued command to prepare
121305b308e1df6d9d673daedb517969241f41278b52Brett Russ *
121405b308e1df6d9d673daedb517969241f41278b52Brett Russ *      This routine simply redirects to the general purpose routine
121505b308e1df6d9d673daedb517969241f41278b52Brett Russ *      if command is not DMA.  Else, it handles prep of the CRQB
121605b308e1df6d9d673daedb517969241f41278b52Brett Russ *      (command request block), does some sanity checking, and calls
121705b308e1df6d9d673daedb517969241f41278b52Brett Russ *      the SG load routine.
121805b308e1df6d9d673daedb517969241f41278b52Brett Russ *
121905b308e1df6d9d673daedb517969241f41278b52Brett Russ *      LOCKING:
122005b308e1df6d9d673daedb517969241f41278b52Brett Russ *      Inherited from caller.
122105b308e1df6d9d673daedb517969241f41278b52Brett Russ */
122231961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russstatic void mv_qc_prep(struct ata_queued_cmd *qc)
122331961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ{
122431961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ	struct ata_port *ap = qc->ap;
122531961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ	struct mv_port_priv *pp = ap->private_data;
1226e14698745dd0de1ddbf5cd0cca4313a90f8c1cc1Mark Lord	__le16 *cw;
122731961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ	struct ata_taskfile *tf;
122831961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ	u16 flags = 0;
1229a6432436c5e14b416f27c8f87c5bf0bc36771f49Mark Lord	unsigned in_index;
123031961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ
12312dcb407e61458ded17503d6bd12b8c064965368bJeff Garzik	if (qc->tf.protocol != ATA_PROT_DMA)
123231961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ		return;
123320f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ
123431961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ	/* Fill in command request block
123531961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ	 */
1236e4e7b89280d1d666e2c09e5ad36cf071796c4c7eJeff Garzik	if (!(qc->tf.flags & ATA_TFLAG_WRITE))
123731961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ		flags |= CRQB_FLAG_READ;
1238beec7dbc6ff003bbc94de62b3323519c878fb2acTejun Heo	WARN_ON(MV_MAX_Q_DEPTH <= qc->tag);
123931961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ	flags |= qc->tag << CRQB_TAG_SHIFT;
12404537deb5e90b717a725b3d74b58b4bb1d28443d0Jeff Garzik	flags |= qc->tag << CRQB_IOID_SHIFT;	/* 50xx appears to ignore this*/
124131961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ
1242bdd4dddee325a7dce3e84cf48201a06aa8508aa4Jeff Garzik	/* get current queue index from software */
1243bdd4dddee325a7dce3e84cf48201a06aa8508aa4Jeff Garzik	in_index = pp->req_idx & MV_MAX_Q_DEPTH_MASK;
1244a6432436c5e14b416f27c8f87c5bf0bc36771f49Mark Lord
1245a6432436c5e14b416f27c8f87c5bf0bc36771f49Mark Lord	pp->crqb[in_index].sg_addr =
124631961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ		cpu_to_le32(pp->sg_tbl_dma & 0xffffffff);
1247a6432436c5e14b416f27c8f87c5bf0bc36771f49Mark Lord	pp->crqb[in_index].sg_addr_hi =
124831961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ		cpu_to_le32((pp->sg_tbl_dma >> 16) >> 16);
1249a6432436c5e14b416f27c8f87c5bf0bc36771f49Mark Lord	pp->crqb[in_index].ctrl_flags = cpu_to_le16(flags);
125031961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ
1251a6432436c5e14b416f27c8f87c5bf0bc36771f49Mark Lord	cw = &pp->crqb[in_index].ata_cmd[0];
125231961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ	tf = &qc->tf;
125331961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ
125431961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ	/* Sadly, the CRQB cannot accomodate all registers--there are
125531961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ	 * only 11 bytes...so we must pick and choose required
125631961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ	 * registers based on the command.  So, we drop feature and
125731961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ	 * hob_feature for [RW] DMA commands, but they are needed for
125831961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ	 * NCQ.  NCQ will drop hob_nsect.
125920f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ	 */
126031961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ	switch (tf->command) {
126131961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ	case ATA_CMD_READ:
126231961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ	case ATA_CMD_READ_EXT:
126331961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ	case ATA_CMD_WRITE:
126431961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ	case ATA_CMD_WRITE_EXT:
1265c15d85c8f3f73b5f20aae7928e25b6996f16b328Jens Axboe	case ATA_CMD_WRITE_FUA_EXT:
126631961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ		mv_crqb_pack_cmd(cw++, tf->hob_nsect, ATA_REG_NSECT, 0);
126731961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ		break;
126831961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ#ifdef LIBATA_NCQ		/* FIXME: remove this line when NCQ added */
126931961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ	case ATA_CMD_FPDMA_READ:
127031961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ	case ATA_CMD_FPDMA_WRITE:
12718b260248d9e0e8b64bb72fd4dee03ad86984c344Jeff Garzik		mv_crqb_pack_cmd(cw++, tf->hob_feature, ATA_REG_FEATURE, 0);
127231961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ		mv_crqb_pack_cmd(cw++, tf->feature, ATA_REG_FEATURE, 0);
127331961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ		break;
127431961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ#endif				/* FIXME: remove this line when NCQ added */
127531961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ	default:
127631961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ		/* The only other commands EDMA supports in non-queued and
127731961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ		 * non-NCQ mode are: [RW] STREAM DMA and W DMA FUA EXT, none
127831961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ		 * of which are defined/used by Linux.  If we get here, this
127931961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ		 * driver needs work.
128031961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ		 *
128131961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ		 * FIXME: modify libata to give qc_prep a return value and
128231961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ		 * return error here.
128331961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ		 */
128431961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ		BUG_ON(tf->command);
128531961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ		break;
128631961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ	}
128731961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ	mv_crqb_pack_cmd(cw++, tf->nsect, ATA_REG_NSECT, 0);
128831961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ	mv_crqb_pack_cmd(cw++, tf->hob_lbal, ATA_REG_LBAL, 0);
128931961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ	mv_crqb_pack_cmd(cw++, tf->lbal, ATA_REG_LBAL, 0);
129031961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ	mv_crqb_pack_cmd(cw++, tf->hob_lbam, ATA_REG_LBAM, 0);
129131961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ	mv_crqb_pack_cmd(cw++, tf->lbam, ATA_REG_LBAM, 0);
129231961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ	mv_crqb_pack_cmd(cw++, tf->hob_lbah, ATA_REG_LBAH, 0);
129331961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ	mv_crqb_pack_cmd(cw++, tf->lbah, ATA_REG_LBAH, 0);
129431961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ	mv_crqb_pack_cmd(cw++, tf->device, ATA_REG_DEVICE, 0);
129531961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ	mv_crqb_pack_cmd(cw++, tf->command, ATA_REG_CMD, 1);	/* last */
129631961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ
1297e4e7b89280d1d666e2c09e5ad36cf071796c4c7eJeff Garzik	if (!(qc->flags & ATA_QCFLAG_DMAMAP))
1298e4e7b89280d1d666e2c09e5ad36cf071796c4c7eJeff Garzik		return;
1299e4e7b89280d1d666e2c09e5ad36cf071796c4c7eJeff Garzik	mv_fill_sg(qc);
1300e4e7b89280d1d666e2c09e5ad36cf071796c4c7eJeff Garzik}
1301e4e7b89280d1d666e2c09e5ad36cf071796c4c7eJeff Garzik
1302e4e7b89280d1d666e2c09e5ad36cf071796c4c7eJeff Garzik/**
1303e4e7b89280d1d666e2c09e5ad36cf071796c4c7eJeff Garzik *      mv_qc_prep_iie - Host specific command preparation.
1304e4e7b89280d1d666e2c09e5ad36cf071796c4c7eJeff Garzik *      @qc: queued command to prepare
1305e4e7b89280d1d666e2c09e5ad36cf071796c4c7eJeff Garzik *
1306e4e7b89280d1d666e2c09e5ad36cf071796c4c7eJeff Garzik *      This routine simply redirects to the general purpose routine
1307e4e7b89280d1d666e2c09e5ad36cf071796c4c7eJeff Garzik *      if command is not DMA.  Else, it handles prep of the CRQB
1308e4e7b89280d1d666e2c09e5ad36cf071796c4c7eJeff Garzik *      (command request block), does some sanity checking, and calls
1309e4e7b89280d1d666e2c09e5ad36cf071796c4c7eJeff Garzik *      the SG load routine.
1310e4e7b89280d1d666e2c09e5ad36cf071796c4c7eJeff Garzik *
1311e4e7b89280d1d666e2c09e5ad36cf071796c4c7eJeff Garzik *      LOCKING:
1312e4e7b89280d1d666e2c09e5ad36cf071796c4c7eJeff Garzik *      Inherited from caller.
1313e4e7b89280d1d666e2c09e5ad36cf071796c4c7eJeff Garzik */
1314e4e7b89280d1d666e2c09e5ad36cf071796c4c7eJeff Garzikstatic void mv_qc_prep_iie(struct ata_queued_cmd *qc)
1315e4e7b89280d1d666e2c09e5ad36cf071796c4c7eJeff Garzik{
1316e4e7b89280d1d666e2c09e5ad36cf071796c4c7eJeff Garzik	struct ata_port *ap = qc->ap;
1317e4e7b89280d1d666e2c09e5ad36cf071796c4c7eJeff Garzik	struct mv_port_priv *pp = ap->private_data;
1318e4e7b89280d1d666e2c09e5ad36cf071796c4c7eJeff Garzik	struct mv_crqb_iie *crqb;
1319e4e7b89280d1d666e2c09e5ad36cf071796c4c7eJeff Garzik	struct ata_taskfile *tf;
1320a6432436c5e14b416f27c8f87c5bf0bc36771f49Mark Lord	unsigned in_index;
1321e4e7b89280d1d666e2c09e5ad36cf071796c4c7eJeff Garzik	u32 flags = 0;
1322e4e7b89280d1d666e2c09e5ad36cf071796c4c7eJeff Garzik
13232dcb407e61458ded17503d6bd12b8c064965368bJeff Garzik	if (qc->tf.protocol != ATA_PROT_DMA)
1324e4e7b89280d1d666e2c09e5ad36cf071796c4c7eJeff Garzik		return;
1325e4e7b89280d1d666e2c09e5ad36cf071796c4c7eJeff Garzik
1326e4e7b89280d1d666e2c09e5ad36cf071796c4c7eJeff Garzik	/* Fill in Gen IIE command request block
1327e4e7b89280d1d666e2c09e5ad36cf071796c4c7eJeff Garzik	 */
1328e4e7b89280d1d666e2c09e5ad36cf071796c4c7eJeff Garzik	if (!(qc->tf.flags & ATA_TFLAG_WRITE))
1329e4e7b89280d1d666e2c09e5ad36cf071796c4c7eJeff Garzik		flags |= CRQB_FLAG_READ;
1330e4e7b89280d1d666e2c09e5ad36cf071796c4c7eJeff Garzik
1331beec7dbc6ff003bbc94de62b3323519c878fb2acTejun Heo	WARN_ON(MV_MAX_Q_DEPTH <= qc->tag);
1332e4e7b89280d1d666e2c09e5ad36cf071796c4c7eJeff Garzik	flags |= qc->tag << CRQB_TAG_SHIFT;
1333bdd4dddee325a7dce3e84cf48201a06aa8508aa4Jeff Garzik	flags |= qc->tag << CRQB_IOID_SHIFT;	/* "I/O Id" is -really-
13344537deb5e90b717a725b3d74b58b4bb1d28443d0Jeff Garzik						   what we use as our tag */
1335e4e7b89280d1d666e2c09e5ad36cf071796c4c7eJeff Garzik
1336bdd4dddee325a7dce3e84cf48201a06aa8508aa4Jeff Garzik	/* get current queue index from software */
1337bdd4dddee325a7dce3e84cf48201a06aa8508aa4Jeff Garzik	in_index = pp->req_idx & MV_MAX_Q_DEPTH_MASK;
1338a6432436c5e14b416f27c8f87c5bf0bc36771f49Mark Lord
1339a6432436c5e14b416f27c8f87c5bf0bc36771f49Mark Lord	crqb = (struct mv_crqb_iie *) &pp->crqb[in_index];
1340e4e7b89280d1d666e2c09e5ad36cf071796c4c7eJeff Garzik	crqb->addr = cpu_to_le32(pp->sg_tbl_dma & 0xffffffff);
1341e4e7b89280d1d666e2c09e5ad36cf071796c4c7eJeff Garzik	crqb->addr_hi = cpu_to_le32((pp->sg_tbl_dma >> 16) >> 16);
1342e4e7b89280d1d666e2c09e5ad36cf071796c4c7eJeff Garzik	crqb->flags = cpu_to_le32(flags);
1343e4e7b89280d1d666e2c09e5ad36cf071796c4c7eJeff Garzik
1344e4e7b89280d1d666e2c09e5ad36cf071796c4c7eJeff Garzik	tf = &qc->tf;
1345e4e7b89280d1d666e2c09e5ad36cf071796c4c7eJeff Garzik	crqb->ata_cmd[0] = cpu_to_le32(
1346e4e7b89280d1d666e2c09e5ad36cf071796c4c7eJeff Garzik			(tf->command << 16) |
1347e4e7b89280d1d666e2c09e5ad36cf071796c4c7eJeff Garzik			(tf->feature << 24)
1348e4e7b89280d1d666e2c09e5ad36cf071796c4c7eJeff Garzik		);
1349e4e7b89280d1d666e2c09e5ad36cf071796c4c7eJeff Garzik	crqb->ata_cmd[1] = cpu_to_le32(
1350e4e7b89280d1d666e2c09e5ad36cf071796c4c7eJeff Garzik			(tf->lbal << 0) |
1351e4e7b89280d1d666e2c09e5ad36cf071796c4c7eJeff Garzik			(tf->lbam << 8) |
1352e4e7b89280d1d666e2c09e5ad36cf071796c4c7eJeff Garzik			(tf->lbah << 16) |
1353e4e7b89280d1d666e2c09e5ad36cf071796c4c7eJeff Garzik			(tf->device << 24)
1354e4e7b89280d1d666e2c09e5ad36cf071796c4c7eJeff Garzik		);
1355e4e7b89280d1d666e2c09e5ad36cf071796c4c7eJeff Garzik	crqb->ata_cmd[2] = cpu_to_le32(
1356e4e7b89280d1d666e2c09e5ad36cf071796c4c7eJeff Garzik			(tf->hob_lbal << 0) |
1357e4e7b89280d1d666e2c09e5ad36cf071796c4c7eJeff Garzik			(tf->hob_lbam << 8) |
1358e4e7b89280d1d666e2c09e5ad36cf071796c4c7eJeff Garzik			(tf->hob_lbah << 16) |
1359e4e7b89280d1d666e2c09e5ad36cf071796c4c7eJeff Garzik			(tf->hob_feature << 24)
1360e4e7b89280d1d666e2c09e5ad36cf071796c4c7eJeff Garzik		);
1361e4e7b89280d1d666e2c09e5ad36cf071796c4c7eJeff Garzik	crqb->ata_cmd[3] = cpu_to_le32(
1362e4e7b89280d1d666e2c09e5ad36cf071796c4c7eJeff Garzik			(tf->nsect << 0) |
1363e4e7b89280d1d666e2c09e5ad36cf071796c4c7eJeff Garzik			(tf->hob_nsect << 8)
1364e4e7b89280d1d666e2c09e5ad36cf071796c4c7eJeff Garzik		);
1365e4e7b89280d1d666e2c09e5ad36cf071796c4c7eJeff Garzik
1366e4e7b89280d1d666e2c09e5ad36cf071796c4c7eJeff Garzik	if (!(qc->flags & ATA_QCFLAG_DMAMAP))
136731961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ		return;
136831961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ	mv_fill_sg(qc);
136931961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ}
137031961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ
137105b308e1df6d9d673daedb517969241f41278b52Brett Russ/**
137205b308e1df6d9d673daedb517969241f41278b52Brett Russ *      mv_qc_issue - Initiate a command to the host
137305b308e1df6d9d673daedb517969241f41278b52Brett Russ *      @qc: queued command to start
137405b308e1df6d9d673daedb517969241f41278b52Brett Russ *
137505b308e1df6d9d673daedb517969241f41278b52Brett Russ *      This routine simply redirects to the general purpose routine
137605b308e1df6d9d673daedb517969241f41278b52Brett Russ *      if command is not DMA.  Else, it sanity checks our local
137705b308e1df6d9d673daedb517969241f41278b52Brett Russ *      caches of the request producer/consumer indices then enables
137805b308e1df6d9d673daedb517969241f41278b52Brett Russ *      DMA and bumps the request producer index.
137905b308e1df6d9d673daedb517969241f41278b52Brett Russ *
138005b308e1df6d9d673daedb517969241f41278b52Brett Russ *      LOCKING:
138105b308e1df6d9d673daedb517969241f41278b52Brett Russ *      Inherited from caller.
138205b308e1df6d9d673daedb517969241f41278b52Brett Russ */
13839a3d9eb0177eb10500d49cd283b35576082a522dTejun Heostatic unsigned int mv_qc_issue(struct ata_queued_cmd *qc)
138431961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ{
1385c5d3e45a2200a0905dc45b72714726b7aac3aaf1Jeff Garzik	struct ata_port *ap = qc->ap;
1386c5d3e45a2200a0905dc45b72714726b7aac3aaf1Jeff Garzik	void __iomem *port_mmio = mv_ap_base(ap);
1387c5d3e45a2200a0905dc45b72714726b7aac3aaf1Jeff Garzik	struct mv_port_priv *pp = ap->private_data;
1388bdd4dddee325a7dce3e84cf48201a06aa8508aa4Jeff Garzik	u32 in_index;
138931961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ
1390c5d3e45a2200a0905dc45b72714726b7aac3aaf1Jeff Garzik	if (qc->tf.protocol != ATA_PROT_DMA) {
139131961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ		/* We're about to send a non-EDMA capable command to the
139231961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ		 * port.  Turn off EDMA so there won't be problems accessing
139331961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ		 * shadow block, etc registers.
139431961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ		 */
13950ea9e179f436f153fc19fdaef7abbc1e0da20762Jeff Garzik		__mv_stop_dma(ap);
139631961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ		return ata_qc_issue_prot(qc);
139731961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ	}
139831961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ
13990c58912e192fc3a4835d772aafa40b72552b819fMark Lord	mv_start_dma(ap, port_mmio, pp);
1400bdd4dddee325a7dce3e84cf48201a06aa8508aa4Jeff Garzik
1401bdd4dddee325a7dce3e84cf48201a06aa8508aa4Jeff Garzik	in_index = pp->req_idx & MV_MAX_Q_DEPTH_MASK;
140231961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ
140331961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ	/* until we do queuing, the queue should be empty at this point */
1404a6432436c5e14b416f27c8f87c5bf0bc36771f49Mark Lord	WARN_ON(in_index != ((readl(port_mmio + EDMA_REQ_Q_OUT_PTR_OFS)
1405a6432436c5e14b416f27c8f87c5bf0bc36771f49Mark Lord		>> EDMA_REQ_Q_PTR_SHIFT) & MV_MAX_Q_DEPTH_MASK));
140631961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ
1407bdd4dddee325a7dce3e84cf48201a06aa8508aa4Jeff Garzik	pp->req_idx++;
140831961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ
1409bdd4dddee325a7dce3e84cf48201a06aa8508aa4Jeff Garzik	in_index = (pp->req_idx & MV_MAX_Q_DEPTH_MASK) << EDMA_REQ_Q_PTR_SHIFT;
141031961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ
141131961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ	/* and write the request in pointer to kick the EDMA to life */
1412bdd4dddee325a7dce3e84cf48201a06aa8508aa4Jeff Garzik	writelfl((pp->crqb_dma & EDMA_REQ_Q_BASE_LO_MASK) | in_index,
1413bdd4dddee325a7dce3e84cf48201a06aa8508aa4Jeff Garzik		 port_mmio + EDMA_REQ_Q_IN_PTR_OFS);
141431961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ
141531961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ	return 0;
141631961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ}
141731961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ
141805b308e1df6d9d673daedb517969241f41278b52Brett Russ/**
141905b308e1df6d9d673daedb517969241f41278b52Brett Russ *      mv_err_intr - Handle error interrupts on the port
142005b308e1df6d9d673daedb517969241f41278b52Brett Russ *      @ap: ATA channel to manipulate
14219b358e305c1d783c8a4ebf00344e95deb9e38f3dMark Lord *      @reset_allowed: bool: 0 == don't trigger from reset here
142205b308e1df6d9d673daedb517969241f41278b52Brett Russ *
142305b308e1df6d9d673daedb517969241f41278b52Brett Russ *      In most cases, just clear the interrupt and move on.  However,
142405b308e1df6d9d673daedb517969241f41278b52Brett Russ *      some cases require an eDMA reset, which is done right before
142505b308e1df6d9d673daedb517969241f41278b52Brett Russ *      the COMRESET in mv_phy_reset().  The SERR case requires a
142605b308e1df6d9d673daedb517969241f41278b52Brett Russ *      clear of pending errors in the SATA SERROR register.  Finally,
142705b308e1df6d9d673daedb517969241f41278b52Brett Russ *      if the port disabled DMA, update our cached copy to match.
142805b308e1df6d9d673daedb517969241f41278b52Brett Russ *
142905b308e1df6d9d673daedb517969241f41278b52Brett Russ *      LOCKING:
143005b308e1df6d9d673daedb517969241f41278b52Brett Russ *      Inherited from caller.
143105b308e1df6d9d673daedb517969241f41278b52Brett Russ */
1432bdd4dddee325a7dce3e84cf48201a06aa8508aa4Jeff Garzikstatic void mv_err_intr(struct ata_port *ap, struct ata_queued_cmd *qc)
143331961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ{
143431961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ	void __iomem *port_mmio = mv_ap_base(ap);
1435bdd4dddee325a7dce3e84cf48201a06aa8508aa4Jeff Garzik	u32 edma_err_cause, eh_freeze_mask, serr = 0;
1436bdd4dddee325a7dce3e84cf48201a06aa8508aa4Jeff Garzik	struct mv_port_priv *pp = ap->private_data;
1437bdd4dddee325a7dce3e84cf48201a06aa8508aa4Jeff Garzik	struct mv_host_priv *hpriv = ap->host->private_data;
1438bdd4dddee325a7dce3e84cf48201a06aa8508aa4Jeff Garzik	unsigned int edma_enabled = (pp->pp_flags & MV_PP_FLAG_EDMA_EN);
1439bdd4dddee325a7dce3e84cf48201a06aa8508aa4Jeff Garzik	unsigned int action = 0, err_mask = 0;
14409af5c9c97dc9d599281778864c72b385f0c63341Tejun Heo	struct ata_eh_info *ehi = &ap->link.eh_info;
144120f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ
1442bdd4dddee325a7dce3e84cf48201a06aa8508aa4Jeff Garzik	ata_ehi_clear_desc(ehi);
144320f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ
1444bdd4dddee325a7dce3e84cf48201a06aa8508aa4Jeff Garzik	if (!edma_enabled) {
1445bdd4dddee325a7dce3e84cf48201a06aa8508aa4Jeff Garzik		/* just a guess: do we need to do this? should we
1446bdd4dddee325a7dce3e84cf48201a06aa8508aa4Jeff Garzik		 * expand this, and do it in all cases?
1447bdd4dddee325a7dce3e84cf48201a06aa8508aa4Jeff Garzik		 */
1448936fd7328657884d5a69a55666c74a55aa83ca27Tejun Heo		sata_scr_read(&ap->link, SCR_ERROR, &serr);
1449936fd7328657884d5a69a55666c74a55aa83ca27Tejun Heo		sata_scr_write_flush(&ap->link, SCR_ERROR, serr);
145020f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ	}
1451bdd4dddee325a7dce3e84cf48201a06aa8508aa4Jeff Garzik
1452bdd4dddee325a7dce3e84cf48201a06aa8508aa4Jeff Garzik	edma_err_cause = readl(port_mmio + EDMA_ERR_IRQ_CAUSE_OFS);
1453bdd4dddee325a7dce3e84cf48201a06aa8508aa4Jeff Garzik
1454bdd4dddee325a7dce3e84cf48201a06aa8508aa4Jeff Garzik	ata_ehi_push_desc(ehi, "edma_err 0x%08x", edma_err_cause);
1455bdd4dddee325a7dce3e84cf48201a06aa8508aa4Jeff Garzik
1456bdd4dddee325a7dce3e84cf48201a06aa8508aa4Jeff Garzik	/*
1457bdd4dddee325a7dce3e84cf48201a06aa8508aa4Jeff Garzik	 * all generations share these EDMA error cause bits
1458bdd4dddee325a7dce3e84cf48201a06aa8508aa4Jeff Garzik	 */
1459bdd4dddee325a7dce3e84cf48201a06aa8508aa4Jeff Garzik
1460bdd4dddee325a7dce3e84cf48201a06aa8508aa4Jeff Garzik	if (edma_err_cause & EDMA_ERR_DEV)
1461bdd4dddee325a7dce3e84cf48201a06aa8508aa4Jeff Garzik		err_mask |= AC_ERR_DEV;
1462bdd4dddee325a7dce3e84cf48201a06aa8508aa4Jeff Garzik	if (edma_err_cause & (EDMA_ERR_D_PAR | EDMA_ERR_PRD_PAR |
14636c1153e00af8de755ec278d873a97c9ce2a72d10Jeff Garzik			EDMA_ERR_CRQB_PAR | EDMA_ERR_CRPB_PAR |
1464bdd4dddee325a7dce3e84cf48201a06aa8508aa4Jeff Garzik			EDMA_ERR_INTRL_PAR)) {
1465bdd4dddee325a7dce3e84cf48201a06aa8508aa4Jeff Garzik		err_mask |= AC_ERR_ATA_BUS;
1466bdd4dddee325a7dce3e84cf48201a06aa8508aa4Jeff Garzik		action |= ATA_EH_HARDRESET;
1467b64bbc39f2122a2276578e40144af69ef01decd4Tejun Heo		ata_ehi_push_desc(ehi, "parity error");
1468bdd4dddee325a7dce3e84cf48201a06aa8508aa4Jeff Garzik	}
1469bdd4dddee325a7dce3e84cf48201a06aa8508aa4Jeff Garzik	if (edma_err_cause & (EDMA_ERR_DEV_DCON | EDMA_ERR_DEV_CON)) {
1470bdd4dddee325a7dce3e84cf48201a06aa8508aa4Jeff Garzik		ata_ehi_hotplugged(ehi);
1471bdd4dddee325a7dce3e84cf48201a06aa8508aa4Jeff Garzik		ata_ehi_push_desc(ehi, edma_err_cause & EDMA_ERR_DEV_DCON ?
1472b64bbc39f2122a2276578e40144af69ef01decd4Tejun Heo			"dev disconnect" : "dev connect");
14733606a380692cf958355a40fc1aa336800c17baf1Mark Lord		action |= ATA_EH_HARDRESET;
1474bdd4dddee325a7dce3e84cf48201a06aa8508aa4Jeff Garzik	}
1475bdd4dddee325a7dce3e84cf48201a06aa8508aa4Jeff Garzik
1476ee9ccdf70163ca6408f6965e0fbc65baeac7312cJeff Garzik	if (IS_GEN_I(hpriv)) {
1477bdd4dddee325a7dce3e84cf48201a06aa8508aa4Jeff Garzik		eh_freeze_mask = EDMA_EH_FREEZE_5;
1478bdd4dddee325a7dce3e84cf48201a06aa8508aa4Jeff Garzik
1479bdd4dddee325a7dce3e84cf48201a06aa8508aa4Jeff Garzik		if (edma_err_cause & EDMA_ERR_SELF_DIS_5) {
1480bdd4dddee325a7dce3e84cf48201a06aa8508aa4Jeff Garzik			struct mv_port_priv *pp	= ap->private_data;
1481bdd4dddee325a7dce3e84cf48201a06aa8508aa4Jeff Garzik			pp->pp_flags &= ~MV_PP_FLAG_EDMA_EN;
1482b64bbc39f2122a2276578e40144af69ef01decd4Tejun Heo			ata_ehi_push_desc(ehi, "EDMA self-disable");
1483bdd4dddee325a7dce3e84cf48201a06aa8508aa4Jeff Garzik		}
1484bdd4dddee325a7dce3e84cf48201a06aa8508aa4Jeff Garzik	} else {
1485bdd4dddee325a7dce3e84cf48201a06aa8508aa4Jeff Garzik		eh_freeze_mask = EDMA_EH_FREEZE;
1486bdd4dddee325a7dce3e84cf48201a06aa8508aa4Jeff Garzik
1487bdd4dddee325a7dce3e84cf48201a06aa8508aa4Jeff Garzik		if (edma_err_cause & EDMA_ERR_SELF_DIS) {
1488bdd4dddee325a7dce3e84cf48201a06aa8508aa4Jeff Garzik			struct mv_port_priv *pp	= ap->private_data;
1489bdd4dddee325a7dce3e84cf48201a06aa8508aa4Jeff Garzik			pp->pp_flags &= ~MV_PP_FLAG_EDMA_EN;
1490b64bbc39f2122a2276578e40144af69ef01decd4Tejun Heo			ata_ehi_push_desc(ehi, "EDMA self-disable");
1491bdd4dddee325a7dce3e84cf48201a06aa8508aa4Jeff Garzik		}
1492bdd4dddee325a7dce3e84cf48201a06aa8508aa4Jeff Garzik
1493bdd4dddee325a7dce3e84cf48201a06aa8508aa4Jeff Garzik		if (edma_err_cause & EDMA_ERR_SERR) {
1494936fd7328657884d5a69a55666c74a55aa83ca27Tejun Heo			sata_scr_read(&ap->link, SCR_ERROR, &serr);
1495936fd7328657884d5a69a55666c74a55aa83ca27Tejun Heo			sata_scr_write_flush(&ap->link, SCR_ERROR, serr);
1496bdd4dddee325a7dce3e84cf48201a06aa8508aa4Jeff Garzik			err_mask = AC_ERR_ATA_BUS;
1497bdd4dddee325a7dce3e84cf48201a06aa8508aa4Jeff Garzik			action |= ATA_EH_HARDRESET;
1498bdd4dddee325a7dce3e84cf48201a06aa8508aa4Jeff Garzik		}
1499afb0edd922c7ed6e73678730921dfcccebec17e8Brett Russ	}
150020f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ
150120f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ	/* Clear EDMA now that SERR cleanup done */
15023606a380692cf958355a40fc1aa336800c17baf1Mark Lord	writelfl(~edma_err_cause, port_mmio + EDMA_ERR_IRQ_CAUSE_OFS);
150320f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ
1504bdd4dddee325a7dce3e84cf48201a06aa8508aa4Jeff Garzik	if (!err_mask) {
1505bdd4dddee325a7dce3e84cf48201a06aa8508aa4Jeff Garzik		err_mask = AC_ERR_OTHER;
1506bdd4dddee325a7dce3e84cf48201a06aa8508aa4Jeff Garzik		action |= ATA_EH_HARDRESET;
1507bdd4dddee325a7dce3e84cf48201a06aa8508aa4Jeff Garzik	}
1508bdd4dddee325a7dce3e84cf48201a06aa8508aa4Jeff Garzik
1509bdd4dddee325a7dce3e84cf48201a06aa8508aa4Jeff Garzik	ehi->serror |= serr;
1510bdd4dddee325a7dce3e84cf48201a06aa8508aa4Jeff Garzik	ehi->action |= action;
1511bdd4dddee325a7dce3e84cf48201a06aa8508aa4Jeff Garzik
1512bdd4dddee325a7dce3e84cf48201a06aa8508aa4Jeff Garzik	if (qc)
1513bdd4dddee325a7dce3e84cf48201a06aa8508aa4Jeff Garzik		qc->err_mask |= err_mask;
1514bdd4dddee325a7dce3e84cf48201a06aa8508aa4Jeff Garzik	else
1515bdd4dddee325a7dce3e84cf48201a06aa8508aa4Jeff Garzik		ehi->err_mask |= err_mask;
1516bdd4dddee325a7dce3e84cf48201a06aa8508aa4Jeff Garzik
1517bdd4dddee325a7dce3e84cf48201a06aa8508aa4Jeff Garzik	if (edma_err_cause & eh_freeze_mask)
1518bdd4dddee325a7dce3e84cf48201a06aa8508aa4Jeff Garzik		ata_port_freeze(ap);
1519bdd4dddee325a7dce3e84cf48201a06aa8508aa4Jeff Garzik	else
1520bdd4dddee325a7dce3e84cf48201a06aa8508aa4Jeff Garzik		ata_port_abort(ap);
1521bdd4dddee325a7dce3e84cf48201a06aa8508aa4Jeff Garzik}
1522bdd4dddee325a7dce3e84cf48201a06aa8508aa4Jeff Garzik
1523bdd4dddee325a7dce3e84cf48201a06aa8508aa4Jeff Garzikstatic void mv_intr_pio(struct ata_port *ap)
1524bdd4dddee325a7dce3e84cf48201a06aa8508aa4Jeff Garzik{
1525bdd4dddee325a7dce3e84cf48201a06aa8508aa4Jeff Garzik	struct ata_queued_cmd *qc;
1526bdd4dddee325a7dce3e84cf48201a06aa8508aa4Jeff Garzik	u8 ata_status;
1527bdd4dddee325a7dce3e84cf48201a06aa8508aa4Jeff Garzik
1528bdd4dddee325a7dce3e84cf48201a06aa8508aa4Jeff Garzik	/* ignore spurious intr if drive still BUSY */
1529bdd4dddee325a7dce3e84cf48201a06aa8508aa4Jeff Garzik	ata_status = readb(ap->ioaddr.status_addr);
1530bdd4dddee325a7dce3e84cf48201a06aa8508aa4Jeff Garzik	if (unlikely(ata_status & ATA_BUSY))
1531bdd4dddee325a7dce3e84cf48201a06aa8508aa4Jeff Garzik		return;
1532bdd4dddee325a7dce3e84cf48201a06aa8508aa4Jeff Garzik
1533bdd4dddee325a7dce3e84cf48201a06aa8508aa4Jeff Garzik	/* get active ATA command */
15349af5c9c97dc9d599281778864c72b385f0c63341Tejun Heo	qc = ata_qc_from_tag(ap, ap->link.active_tag);
1535bdd4dddee325a7dce3e84cf48201a06aa8508aa4Jeff Garzik	if (unlikely(!qc))			/* no active tag */
1536bdd4dddee325a7dce3e84cf48201a06aa8508aa4Jeff Garzik		return;
1537bdd4dddee325a7dce3e84cf48201a06aa8508aa4Jeff Garzik	if (qc->tf.flags & ATA_TFLAG_POLLING)	/* polling; we don't own qc */
1538bdd4dddee325a7dce3e84cf48201a06aa8508aa4Jeff Garzik		return;
1539bdd4dddee325a7dce3e84cf48201a06aa8508aa4Jeff Garzik
1540bdd4dddee325a7dce3e84cf48201a06aa8508aa4Jeff Garzik	/* and finally, complete the ATA command */
1541bdd4dddee325a7dce3e84cf48201a06aa8508aa4Jeff Garzik	qc->err_mask |= ac_err_mask(ata_status);
1542bdd4dddee325a7dce3e84cf48201a06aa8508aa4Jeff Garzik	ata_qc_complete(qc);
1543bdd4dddee325a7dce3e84cf48201a06aa8508aa4Jeff Garzik}
1544bdd4dddee325a7dce3e84cf48201a06aa8508aa4Jeff Garzik
1545bdd4dddee325a7dce3e84cf48201a06aa8508aa4Jeff Garzikstatic void mv_intr_edma(struct ata_port *ap)
1546bdd4dddee325a7dce3e84cf48201a06aa8508aa4Jeff Garzik{
1547bdd4dddee325a7dce3e84cf48201a06aa8508aa4Jeff Garzik	void __iomem *port_mmio = mv_ap_base(ap);
1548bdd4dddee325a7dce3e84cf48201a06aa8508aa4Jeff Garzik	struct mv_host_priv *hpriv = ap->host->private_data;
1549bdd4dddee325a7dce3e84cf48201a06aa8508aa4Jeff Garzik	struct mv_port_priv *pp = ap->private_data;
1550bdd4dddee325a7dce3e84cf48201a06aa8508aa4Jeff Garzik	struct ata_queued_cmd *qc;
1551bdd4dddee325a7dce3e84cf48201a06aa8508aa4Jeff Garzik	u32 out_index, in_index;
1552bdd4dddee325a7dce3e84cf48201a06aa8508aa4Jeff Garzik	bool work_done = false;
1553bdd4dddee325a7dce3e84cf48201a06aa8508aa4Jeff Garzik
1554bdd4dddee325a7dce3e84cf48201a06aa8508aa4Jeff Garzik	/* get h/w response queue pointer */
1555bdd4dddee325a7dce3e84cf48201a06aa8508aa4Jeff Garzik	in_index = (readl(port_mmio + EDMA_RSP_Q_IN_PTR_OFS)
1556bdd4dddee325a7dce3e84cf48201a06aa8508aa4Jeff Garzik			>> EDMA_RSP_Q_PTR_SHIFT) & MV_MAX_Q_DEPTH_MASK;
1557bdd4dddee325a7dce3e84cf48201a06aa8508aa4Jeff Garzik
1558bdd4dddee325a7dce3e84cf48201a06aa8508aa4Jeff Garzik	while (1) {
1559bdd4dddee325a7dce3e84cf48201a06aa8508aa4Jeff Garzik		u16 status;
15606c1153e00af8de755ec278d873a97c9ce2a72d10Jeff Garzik		unsigned int tag;
1561bdd4dddee325a7dce3e84cf48201a06aa8508aa4Jeff Garzik
1562bdd4dddee325a7dce3e84cf48201a06aa8508aa4Jeff Garzik		/* get s/w response queue last-read pointer, and compare */
1563bdd4dddee325a7dce3e84cf48201a06aa8508aa4Jeff Garzik		out_index = pp->resp_idx & MV_MAX_Q_DEPTH_MASK;
1564bdd4dddee325a7dce3e84cf48201a06aa8508aa4Jeff Garzik		if (in_index == out_index)
1565bdd4dddee325a7dce3e84cf48201a06aa8508aa4Jeff Garzik			break;
1566bdd4dddee325a7dce3e84cf48201a06aa8508aa4Jeff Garzik
1567bdd4dddee325a7dce3e84cf48201a06aa8508aa4Jeff Garzik		/* 50xx: get active ATA command */
15680ea9e179f436f153fc19fdaef7abbc1e0da20762Jeff Garzik		if (IS_GEN_I(hpriv))
15699af5c9c97dc9d599281778864c72b385f0c63341Tejun Heo			tag = ap->link.active_tag;
1570bdd4dddee325a7dce3e84cf48201a06aa8508aa4Jeff Garzik
15716c1153e00af8de755ec278d873a97c9ce2a72d10Jeff Garzik		/* Gen II/IIE: get active ATA command via tag, to enable
15726c1153e00af8de755ec278d873a97c9ce2a72d10Jeff Garzik		 * support for queueing.  this works transparently for
15736c1153e00af8de755ec278d873a97c9ce2a72d10Jeff Garzik		 * queued and non-queued modes.
1574bdd4dddee325a7dce3e84cf48201a06aa8508aa4Jeff Garzik		 */
15756c1153e00af8de755ec278d873a97c9ce2a72d10Jeff Garzik		else if (IS_GEN_II(hpriv))
15766c1153e00af8de755ec278d873a97c9ce2a72d10Jeff Garzik			tag = (le16_to_cpu(pp->crpb[out_index].id)
15776c1153e00af8de755ec278d873a97c9ce2a72d10Jeff Garzik				>> CRPB_IOID_SHIFT_6) & 0x3f;
1578bdd4dddee325a7dce3e84cf48201a06aa8508aa4Jeff Garzik
15796c1153e00af8de755ec278d873a97c9ce2a72d10Jeff Garzik		else /* IS_GEN_IIE */
15806c1153e00af8de755ec278d873a97c9ce2a72d10Jeff Garzik			tag = (le16_to_cpu(pp->crpb[out_index].id)
15816c1153e00af8de755ec278d873a97c9ce2a72d10Jeff Garzik				>> CRPB_IOID_SHIFT_7) & 0x3f;
1582bdd4dddee325a7dce3e84cf48201a06aa8508aa4Jeff Garzik
15836c1153e00af8de755ec278d873a97c9ce2a72d10Jeff Garzik		qc = ata_qc_from_tag(ap, tag);
1584bdd4dddee325a7dce3e84cf48201a06aa8508aa4Jeff Garzik
1585bdd4dddee325a7dce3e84cf48201a06aa8508aa4Jeff Garzik		/* lower 8 bits of status are EDMA_ERR_IRQ_CAUSE_OFS
1586bdd4dddee325a7dce3e84cf48201a06aa8508aa4Jeff Garzik		 * bits (WARNING: might not necessarily be associated
1587bdd4dddee325a7dce3e84cf48201a06aa8508aa4Jeff Garzik		 * with this command), which -should- be clear
1588bdd4dddee325a7dce3e84cf48201a06aa8508aa4Jeff Garzik		 * if all is well
1589bdd4dddee325a7dce3e84cf48201a06aa8508aa4Jeff Garzik		 */
1590bdd4dddee325a7dce3e84cf48201a06aa8508aa4Jeff Garzik		status = le16_to_cpu(pp->crpb[out_index].flags);
1591bdd4dddee325a7dce3e84cf48201a06aa8508aa4Jeff Garzik		if (unlikely(status & 0xff)) {
1592bdd4dddee325a7dce3e84cf48201a06aa8508aa4Jeff Garzik			mv_err_intr(ap, qc);
1593bdd4dddee325a7dce3e84cf48201a06aa8508aa4Jeff Garzik			return;
1594bdd4dddee325a7dce3e84cf48201a06aa8508aa4Jeff Garzik		}
1595bdd4dddee325a7dce3e84cf48201a06aa8508aa4Jeff Garzik
1596bdd4dddee325a7dce3e84cf48201a06aa8508aa4Jeff Garzik		/* and finally, complete the ATA command */
1597bdd4dddee325a7dce3e84cf48201a06aa8508aa4Jeff Garzik		if (qc) {
1598bdd4dddee325a7dce3e84cf48201a06aa8508aa4Jeff Garzik			qc->err_mask |=
1599bdd4dddee325a7dce3e84cf48201a06aa8508aa4Jeff Garzik				ac_err_mask(status >> CRPB_FLAG_STATUS_SHIFT);
1600bdd4dddee325a7dce3e84cf48201a06aa8508aa4Jeff Garzik			ata_qc_complete(qc);
1601bdd4dddee325a7dce3e84cf48201a06aa8508aa4Jeff Garzik		}
1602bdd4dddee325a7dce3e84cf48201a06aa8508aa4Jeff Garzik
16030ea9e179f436f153fc19fdaef7abbc1e0da20762Jeff Garzik		/* advance software response queue pointer, to
1604bdd4dddee325a7dce3e84cf48201a06aa8508aa4Jeff Garzik		 * indicate (after the loop completes) to hardware
1605bdd4dddee325a7dce3e84cf48201a06aa8508aa4Jeff Garzik		 * that we have consumed a response queue entry.
1606bdd4dddee325a7dce3e84cf48201a06aa8508aa4Jeff Garzik		 */
1607bdd4dddee325a7dce3e84cf48201a06aa8508aa4Jeff Garzik		work_done = true;
1608bdd4dddee325a7dce3e84cf48201a06aa8508aa4Jeff Garzik		pp->resp_idx++;
1609bdd4dddee325a7dce3e84cf48201a06aa8508aa4Jeff Garzik	}
1610bdd4dddee325a7dce3e84cf48201a06aa8508aa4Jeff Garzik
1611bdd4dddee325a7dce3e84cf48201a06aa8508aa4Jeff Garzik	if (work_done)
1612bdd4dddee325a7dce3e84cf48201a06aa8508aa4Jeff Garzik		writelfl((pp->crpb_dma & EDMA_RSP_Q_BASE_LO_MASK) |
1613bdd4dddee325a7dce3e84cf48201a06aa8508aa4Jeff Garzik			 (out_index << EDMA_RSP_Q_PTR_SHIFT),
1614bdd4dddee325a7dce3e84cf48201a06aa8508aa4Jeff Garzik			 port_mmio + EDMA_RSP_Q_OUT_PTR_OFS);
161520f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ}
161620f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ
161705b308e1df6d9d673daedb517969241f41278b52Brett Russ/**
161805b308e1df6d9d673daedb517969241f41278b52Brett Russ *      mv_host_intr - Handle all interrupts on the given host controller
1619cca3974e48607c3775dc73b544a5700b2e37c21aJeff Garzik *      @host: host specific structure
162005b308e1df6d9d673daedb517969241f41278b52Brett Russ *      @relevant: port error bits relevant to this host controller
162105b308e1df6d9d673daedb517969241f41278b52Brett Russ *      @hc: which host controller we're to look at
162205b308e1df6d9d673daedb517969241f41278b52Brett Russ *
162305b308e1df6d9d673daedb517969241f41278b52Brett Russ *      Read then write clear the HC interrupt status then walk each
162405b308e1df6d9d673daedb517969241f41278b52Brett Russ *      port connected to the HC and see if it needs servicing.  Port
162505b308e1df6d9d673daedb517969241f41278b52Brett Russ *      success ints are reported in the HC interrupt status reg, the
162605b308e1df6d9d673daedb517969241f41278b52Brett Russ *      port error ints are reported in the higher level main
162705b308e1df6d9d673daedb517969241f41278b52Brett Russ *      interrupt status register and thus are passed in via the
162805b308e1df6d9d673daedb517969241f41278b52Brett Russ *      'relevant' argument.
162905b308e1df6d9d673daedb517969241f41278b52Brett Russ *
163005b308e1df6d9d673daedb517969241f41278b52Brett Russ *      LOCKING:
163105b308e1df6d9d673daedb517969241f41278b52Brett Russ *      Inherited from caller.
163205b308e1df6d9d673daedb517969241f41278b52Brett Russ */
1633cca3974e48607c3775dc73b544a5700b2e37c21aJeff Garzikstatic void mv_host_intr(struct ata_host *host, u32 relevant, unsigned int hc)
163420f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ{
16350d5ff566779f894ca9937231a181eb31e4adff0eTejun Heo	void __iomem *mmio = host->iomap[MV_PRIMARY_BAR];
163620f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ	void __iomem *hc_mmio = mv_hc_base(mmio, hc);
163720f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ	u32 hc_irq_cause;
1638c5d3e45a2200a0905dc45b72714726b7aac3aaf1Jeff Garzik	int port, port0;
163920f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ
1640351772658a4d1acc0221a6e30676bb0594e74812Jeff Garzik	if (hc == 0)
164120f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ		port0 = 0;
1642351772658a4d1acc0221a6e30676bb0594e74812Jeff Garzik	else
164320f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ		port0 = MV_PORTS_PER_HC;
164420f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ
164520f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ	/* we'll need the HC success int register in most cases */
164620f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ	hc_irq_cause = readl(hc_mmio + HC_IRQ_CAUSE_OFS);
1647bdd4dddee325a7dce3e84cf48201a06aa8508aa4Jeff Garzik	if (!hc_irq_cause)
1648bdd4dddee325a7dce3e84cf48201a06aa8508aa4Jeff Garzik		return;
1649bdd4dddee325a7dce3e84cf48201a06aa8508aa4Jeff Garzik
1650bdd4dddee325a7dce3e84cf48201a06aa8508aa4Jeff Garzik	writelfl(~hc_irq_cause, hc_mmio + HC_IRQ_CAUSE_OFS);
165120f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ
165220f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ	VPRINTK("ENTER, hc%u relevant=0x%08x HC IRQ cause=0x%08x\n",
16532dcb407e61458ded17503d6bd12b8c064965368bJeff Garzik		hc, relevant, hc_irq_cause);
165420f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ
165520f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ	for (port = port0; port < port0 + MV_PORTS_PER_HC; port++) {
1656cca3974e48607c3775dc73b544a5700b2e37c21aJeff Garzik		struct ata_port *ap = host->ports[port];
165763af2a5c5990d95f1e7d8795f1425fb976ea2b4bMark Lord		struct mv_port_priv *pp = ap->private_data;
1658bdd4dddee325a7dce3e84cf48201a06aa8508aa4Jeff Garzik		int have_err_bits, hard_port, shift;
165955d8ca4f8094246da6e71889a4e04bfafaa78b10Jeff Garzik
1660bdd4dddee325a7dce3e84cf48201a06aa8508aa4Jeff Garzik		if ((!ap) || (ap->flags & ATA_FLAG_DISABLED))
1661a2c91a8819e315e9fd1aef3ff57badb6c1be3f80Jeff Garzik			continue;
1662a2c91a8819e315e9fd1aef3ff57badb6c1be3f80Jeff Garzik
166331961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ		shift = port << 1;		/* (port * 2) */
166420f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ		if (port >= MV_PORTS_PER_HC) {
166520f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ			shift++;	/* skip bit 8 in the HC Main IRQ reg */
166620f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ		}
1667bdd4dddee325a7dce3e84cf48201a06aa8508aa4Jeff Garzik		have_err_bits = ((PORT0_ERR << shift) & relevant);
1668bdd4dddee325a7dce3e84cf48201a06aa8508aa4Jeff Garzik
1669bdd4dddee325a7dce3e84cf48201a06aa8508aa4Jeff Garzik		if (unlikely(have_err_bits)) {
1670bdd4dddee325a7dce3e84cf48201a06aa8508aa4Jeff Garzik			struct ata_queued_cmd *qc;
16718b260248d9e0e8b64bb72fd4dee03ad86984c344Jeff Garzik
16729af5c9c97dc9d599281778864c72b385f0c63341Tejun Heo			qc = ata_qc_from_tag(ap, ap->link.active_tag);
1673bdd4dddee325a7dce3e84cf48201a06aa8508aa4Jeff Garzik			if (qc && (qc->tf.flags & ATA_TFLAG_POLLING))
1674bdd4dddee325a7dce3e84cf48201a06aa8508aa4Jeff Garzik				continue;
1675bdd4dddee325a7dce3e84cf48201a06aa8508aa4Jeff Garzik
1676bdd4dddee325a7dce3e84cf48201a06aa8508aa4Jeff Garzik			mv_err_intr(ap, qc);
1677bdd4dddee325a7dce3e84cf48201a06aa8508aa4Jeff Garzik			continue;
1678bdd4dddee325a7dce3e84cf48201a06aa8508aa4Jeff Garzik		}
1679bdd4dddee325a7dce3e84cf48201a06aa8508aa4Jeff Garzik
1680bdd4dddee325a7dce3e84cf48201a06aa8508aa4Jeff Garzik		hard_port = mv_hardport_from_port(port); /* range 0..3 */
1681bdd4dddee325a7dce3e84cf48201a06aa8508aa4Jeff Garzik
1682bdd4dddee325a7dce3e84cf48201a06aa8508aa4Jeff Garzik		if (pp->pp_flags & MV_PP_FLAG_EDMA_EN) {
1683bdd4dddee325a7dce3e84cf48201a06aa8508aa4Jeff Garzik			if ((CRPB_DMA_DONE << hard_port) & hc_irq_cause)
1684bdd4dddee325a7dce3e84cf48201a06aa8508aa4Jeff Garzik				mv_intr_edma(ap);
1685bdd4dddee325a7dce3e84cf48201a06aa8508aa4Jeff Garzik		} else {
1686bdd4dddee325a7dce3e84cf48201a06aa8508aa4Jeff Garzik			if ((DEV_IRQ << hard_port) & hc_irq_cause)
1687bdd4dddee325a7dce3e84cf48201a06aa8508aa4Jeff Garzik				mv_intr_pio(ap);
168820f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ		}
168920f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ	}
169020f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ	VPRINTK("EXIT\n");
169120f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ}
169220f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ
1693bdd4dddee325a7dce3e84cf48201a06aa8508aa4Jeff Garzikstatic void mv_pci_error(struct ata_host *host, void __iomem *mmio)
1694bdd4dddee325a7dce3e84cf48201a06aa8508aa4Jeff Garzik{
169502a121da5a53d415b6596bc19cc6999d295d32a4Mark Lord	struct mv_host_priv *hpriv = host->private_data;
1696bdd4dddee325a7dce3e84cf48201a06aa8508aa4Jeff Garzik	struct ata_port *ap;
1697bdd4dddee325a7dce3e84cf48201a06aa8508aa4Jeff Garzik	struct ata_queued_cmd *qc;
1698bdd4dddee325a7dce3e84cf48201a06aa8508aa4Jeff Garzik	struct ata_eh_info *ehi;
1699bdd4dddee325a7dce3e84cf48201a06aa8508aa4Jeff Garzik	unsigned int i, err_mask, printed = 0;
1700bdd4dddee325a7dce3e84cf48201a06aa8508aa4Jeff Garzik	u32 err_cause;
1701bdd4dddee325a7dce3e84cf48201a06aa8508aa4Jeff Garzik
170202a121da5a53d415b6596bc19cc6999d295d32a4Mark Lord	err_cause = readl(mmio + hpriv->irq_cause_ofs);
1703bdd4dddee325a7dce3e84cf48201a06aa8508aa4Jeff Garzik
1704bdd4dddee325a7dce3e84cf48201a06aa8508aa4Jeff Garzik	dev_printk(KERN_ERR, host->dev, "PCI ERROR; PCI IRQ cause=0x%08x\n",
1705bdd4dddee325a7dce3e84cf48201a06aa8508aa4Jeff Garzik		   err_cause);
1706bdd4dddee325a7dce3e84cf48201a06aa8508aa4Jeff Garzik
1707bdd4dddee325a7dce3e84cf48201a06aa8508aa4Jeff Garzik	DPRINTK("All regs @ PCI error\n");
1708bdd4dddee325a7dce3e84cf48201a06aa8508aa4Jeff Garzik	mv_dump_all_regs(mmio, -1, to_pci_dev(host->dev));
1709bdd4dddee325a7dce3e84cf48201a06aa8508aa4Jeff Garzik
171002a121da5a53d415b6596bc19cc6999d295d32a4Mark Lord	writelfl(0, mmio + hpriv->irq_cause_ofs);
1711bdd4dddee325a7dce3e84cf48201a06aa8508aa4Jeff Garzik
1712bdd4dddee325a7dce3e84cf48201a06aa8508aa4Jeff Garzik	for (i = 0; i < host->n_ports; i++) {
1713bdd4dddee325a7dce3e84cf48201a06aa8508aa4Jeff Garzik		ap = host->ports[i];
1714936fd7328657884d5a69a55666c74a55aa83ca27Tejun Heo		if (!ata_link_offline(&ap->link)) {
17159af5c9c97dc9d599281778864c72b385f0c63341Tejun Heo			ehi = &ap->link.eh_info;
1716bdd4dddee325a7dce3e84cf48201a06aa8508aa4Jeff Garzik			ata_ehi_clear_desc(ehi);
1717bdd4dddee325a7dce3e84cf48201a06aa8508aa4Jeff Garzik			if (!printed++)
1718bdd4dddee325a7dce3e84cf48201a06aa8508aa4Jeff Garzik				ata_ehi_push_desc(ehi,
1719bdd4dddee325a7dce3e84cf48201a06aa8508aa4Jeff Garzik					"PCI err cause 0x%08x", err_cause);
1720bdd4dddee325a7dce3e84cf48201a06aa8508aa4Jeff Garzik			err_mask = AC_ERR_HOST_BUS;
1721bdd4dddee325a7dce3e84cf48201a06aa8508aa4Jeff Garzik			ehi->action = ATA_EH_HARDRESET;
17229af5c9c97dc9d599281778864c72b385f0c63341Tejun Heo			qc = ata_qc_from_tag(ap, ap->link.active_tag);
1723bdd4dddee325a7dce3e84cf48201a06aa8508aa4Jeff Garzik			if (qc)
1724bdd4dddee325a7dce3e84cf48201a06aa8508aa4Jeff Garzik				qc->err_mask |= err_mask;
1725bdd4dddee325a7dce3e84cf48201a06aa8508aa4Jeff Garzik			else
1726bdd4dddee325a7dce3e84cf48201a06aa8508aa4Jeff Garzik				ehi->err_mask |= err_mask;
1727bdd4dddee325a7dce3e84cf48201a06aa8508aa4Jeff Garzik
1728bdd4dddee325a7dce3e84cf48201a06aa8508aa4Jeff Garzik			ata_port_freeze(ap);
1729bdd4dddee325a7dce3e84cf48201a06aa8508aa4Jeff Garzik		}
1730bdd4dddee325a7dce3e84cf48201a06aa8508aa4Jeff Garzik	}
1731bdd4dddee325a7dce3e84cf48201a06aa8508aa4Jeff Garzik}
1732bdd4dddee325a7dce3e84cf48201a06aa8508aa4Jeff Garzik
173305b308e1df6d9d673daedb517969241f41278b52Brett Russ/**
1734c5d3e45a2200a0905dc45b72714726b7aac3aaf1Jeff Garzik *      mv_interrupt - Main interrupt event handler
173505b308e1df6d9d673daedb517969241f41278b52Brett Russ *      @irq: unused
173605b308e1df6d9d673daedb517969241f41278b52Brett Russ *      @dev_instance: private data; in this case the host structure
173705b308e1df6d9d673daedb517969241f41278b52Brett Russ *
173805b308e1df6d9d673daedb517969241f41278b52Brett Russ *      Read the read only register to determine if any host
173905b308e1df6d9d673daedb517969241f41278b52Brett Russ *      controllers have pending interrupts.  If so, call lower level
174005b308e1df6d9d673daedb517969241f41278b52Brett Russ *      routine to handle.  Also check for PCI errors which are only
174105b308e1df6d9d673daedb517969241f41278b52Brett Russ *      reported here.
174205b308e1df6d9d673daedb517969241f41278b52Brett Russ *
17438b260248d9e0e8b64bb72fd4dee03ad86984c344Jeff Garzik *      LOCKING:
1744cca3974e48607c3775dc73b544a5700b2e37c21aJeff Garzik *      This routine holds the host lock while processing pending
174505b308e1df6d9d673daedb517969241f41278b52Brett Russ *      interrupts.
174605b308e1df6d9d673daedb517969241f41278b52Brett Russ */
17477d12e780e003f93433d49ce78cfedf4b4c52adc5David Howellsstatic irqreturn_t mv_interrupt(int irq, void *dev_instance)
174820f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ{
1749cca3974e48607c3775dc73b544a5700b2e37c21aJeff Garzik	struct ata_host *host = dev_instance;
175020f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ	unsigned int hc, handled = 0, n_hcs;
17510d5ff566779f894ca9937231a181eb31e4adff0eTejun Heo	void __iomem *mmio = host->iomap[MV_PRIMARY_BAR];
1752646a4da514f2555298481cb00dc5b3eb02b21b72Mark Lord	u32 irq_stat, irq_mask;
175320f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ
1754646a4da514f2555298481cb00dc5b3eb02b21b72Mark Lord	spin_lock(&host->lock);
175520f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ	irq_stat = readl(mmio + HC_MAIN_IRQ_CAUSE_OFS);
1756646a4da514f2555298481cb00dc5b3eb02b21b72Mark Lord	irq_mask = readl(mmio + HC_MAIN_IRQ_MASK_OFS);
175720f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ
175820f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ	/* check the cases where we either have nothing pending or have read
175920f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ	 * a bogus register value which can indicate HW removal or PCI fault
176020f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ	 */
1761646a4da514f2555298481cb00dc5b3eb02b21b72Mark Lord	if (!(irq_stat & irq_mask) || (0xffffffffU == irq_stat))
1762646a4da514f2555298481cb00dc5b3eb02b21b72Mark Lord		goto out_unlock;
176320f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ
1764cca3974e48607c3775dc73b544a5700b2e37c21aJeff Garzik	n_hcs = mv_get_hc_count(host->ports[0]->flags);
176520f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ
1766bdd4dddee325a7dce3e84cf48201a06aa8508aa4Jeff Garzik	if (unlikely(irq_stat & PCI_ERR)) {
1767bdd4dddee325a7dce3e84cf48201a06aa8508aa4Jeff Garzik		mv_pci_error(host, mmio);
1768bdd4dddee325a7dce3e84cf48201a06aa8508aa4Jeff Garzik		handled = 1;
1769bdd4dddee325a7dce3e84cf48201a06aa8508aa4Jeff Garzik		goto out_unlock;	/* skip all other HC irq handling */
1770bdd4dddee325a7dce3e84cf48201a06aa8508aa4Jeff Garzik	}
1771bdd4dddee325a7dce3e84cf48201a06aa8508aa4Jeff Garzik
177220f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ	for (hc = 0; hc < n_hcs; hc++) {
177320f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ		u32 relevant = irq_stat & (HC0_IRQ_PEND << (hc * HC_SHIFT));
177420f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ		if (relevant) {
1775cca3974e48607c3775dc73b544a5700b2e37c21aJeff Garzik			mv_host_intr(host, relevant, hc);
1776bdd4dddee325a7dce3e84cf48201a06aa8508aa4Jeff Garzik			handled = 1;
177720f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ		}
177820f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ	}
1779615ab95342f6245026d8974b9724f7ea57d9a184Mark Lord
1780bdd4dddee325a7dce3e84cf48201a06aa8508aa4Jeff Garzikout_unlock:
1781cca3974e48607c3775dc73b544a5700b2e37c21aJeff Garzik	spin_unlock(&host->lock);
178220f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ
178320f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ	return IRQ_RETVAL(handled);
178420f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ}
178520f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ
1786c9d39130123238ac18478a42e25cb7996eacfcc0Jeff Garzikstatic void __iomem *mv5_phy_base(void __iomem *mmio, unsigned int port)
1787c9d39130123238ac18478a42e25cb7996eacfcc0Jeff Garzik{
1788c9d39130123238ac18478a42e25cb7996eacfcc0Jeff Garzik	void __iomem *hc_mmio = mv_hc_base_from_port(mmio, port);
1789c9d39130123238ac18478a42e25cb7996eacfcc0Jeff Garzik	unsigned long ofs = (mv_hardport_from_port(port) + 1) * 0x100UL;
1790c9d39130123238ac18478a42e25cb7996eacfcc0Jeff Garzik
1791c9d39130123238ac18478a42e25cb7996eacfcc0Jeff Garzik	return hc_mmio + ofs;
1792c9d39130123238ac18478a42e25cb7996eacfcc0Jeff Garzik}
1793c9d39130123238ac18478a42e25cb7996eacfcc0Jeff Garzik
1794c9d39130123238ac18478a42e25cb7996eacfcc0Jeff Garzikstatic unsigned int mv5_scr_offset(unsigned int sc_reg_in)
1795c9d39130123238ac18478a42e25cb7996eacfcc0Jeff Garzik{
1796c9d39130123238ac18478a42e25cb7996eacfcc0Jeff Garzik	unsigned int ofs;
1797c9d39130123238ac18478a42e25cb7996eacfcc0Jeff Garzik
1798c9d39130123238ac18478a42e25cb7996eacfcc0Jeff Garzik	switch (sc_reg_in) {
1799c9d39130123238ac18478a42e25cb7996eacfcc0Jeff Garzik	case SCR_STATUS:
1800c9d39130123238ac18478a42e25cb7996eacfcc0Jeff Garzik	case SCR_ERROR:
1801c9d39130123238ac18478a42e25cb7996eacfcc0Jeff Garzik	case SCR_CONTROL:
1802c9d39130123238ac18478a42e25cb7996eacfcc0Jeff Garzik		ofs = sc_reg_in * sizeof(u32);
1803c9d39130123238ac18478a42e25cb7996eacfcc0Jeff Garzik		break;
1804c9d39130123238ac18478a42e25cb7996eacfcc0Jeff Garzik	default:
1805c9d39130123238ac18478a42e25cb7996eacfcc0Jeff Garzik		ofs = 0xffffffffU;
1806c9d39130123238ac18478a42e25cb7996eacfcc0Jeff Garzik		break;
1807c9d39130123238ac18478a42e25cb7996eacfcc0Jeff Garzik	}
1808c9d39130123238ac18478a42e25cb7996eacfcc0Jeff Garzik	return ofs;
1809c9d39130123238ac18478a42e25cb7996eacfcc0Jeff Garzik}
1810c9d39130123238ac18478a42e25cb7996eacfcc0Jeff Garzik
1811da3dbb17a0e9a9ec7f5aed95f1fddadb790edc9dTejun Heostatic int mv5_scr_read(struct ata_port *ap, unsigned int sc_reg_in, u32 *val)
1812c9d39130123238ac18478a42e25cb7996eacfcc0Jeff Garzik{
18130d5ff566779f894ca9937231a181eb31e4adff0eTejun Heo	void __iomem *mmio = ap->host->iomap[MV_PRIMARY_BAR];
18140d5ff566779f894ca9937231a181eb31e4adff0eTejun Heo	void __iomem *addr = mv5_phy_base(mmio, ap->port_no);
1815c9d39130123238ac18478a42e25cb7996eacfcc0Jeff Garzik	unsigned int ofs = mv5_scr_offset(sc_reg_in);
1816c9d39130123238ac18478a42e25cb7996eacfcc0Jeff Garzik
1817da3dbb17a0e9a9ec7f5aed95f1fddadb790edc9dTejun Heo	if (ofs != 0xffffffffU) {
1818da3dbb17a0e9a9ec7f5aed95f1fddadb790edc9dTejun Heo		*val = readl(addr + ofs);
1819da3dbb17a0e9a9ec7f5aed95f1fddadb790edc9dTejun Heo		return 0;
1820da3dbb17a0e9a9ec7f5aed95f1fddadb790edc9dTejun Heo	} else
1821da3dbb17a0e9a9ec7f5aed95f1fddadb790edc9dTejun Heo		return -EINVAL;
1822c9d39130123238ac18478a42e25cb7996eacfcc0Jeff Garzik}
1823c9d39130123238ac18478a42e25cb7996eacfcc0Jeff Garzik
1824da3dbb17a0e9a9ec7f5aed95f1fddadb790edc9dTejun Heostatic int mv5_scr_write(struct ata_port *ap, unsigned int sc_reg_in, u32 val)
1825c9d39130123238ac18478a42e25cb7996eacfcc0Jeff Garzik{
18260d5ff566779f894ca9937231a181eb31e4adff0eTejun Heo	void __iomem *mmio = ap->host->iomap[MV_PRIMARY_BAR];
18270d5ff566779f894ca9937231a181eb31e4adff0eTejun Heo	void __iomem *addr = mv5_phy_base(mmio, ap->port_no);
1828c9d39130123238ac18478a42e25cb7996eacfcc0Jeff Garzik	unsigned int ofs = mv5_scr_offset(sc_reg_in);
1829c9d39130123238ac18478a42e25cb7996eacfcc0Jeff Garzik
1830da3dbb17a0e9a9ec7f5aed95f1fddadb790edc9dTejun Heo	if (ofs != 0xffffffffU) {
18310d5ff566779f894ca9937231a181eb31e4adff0eTejun Heo		writelfl(val, addr + ofs);
1832da3dbb17a0e9a9ec7f5aed95f1fddadb790edc9dTejun Heo		return 0;
1833da3dbb17a0e9a9ec7f5aed95f1fddadb790edc9dTejun Heo	} else
1834da3dbb17a0e9a9ec7f5aed95f1fddadb790edc9dTejun Heo		return -EINVAL;
1835c9d39130123238ac18478a42e25cb7996eacfcc0Jeff Garzik}
1836c9d39130123238ac18478a42e25cb7996eacfcc0Jeff Garzik
1837522479fb98c6667f081e75f87e298e413c0b1db8Jeff Garzikstatic void mv5_reset_bus(struct pci_dev *pdev, void __iomem *mmio)
1838522479fb98c6667f081e75f87e298e413c0b1db8Jeff Garzik{
1839522479fb98c6667f081e75f87e298e413c0b1db8Jeff Garzik	int early_5080;
1840522479fb98c6667f081e75f87e298e413c0b1db8Jeff Garzik
184144c10138fd4bbc4b6d6bff0873c24902f2a9da65Auke Kok	early_5080 = (pdev->device == 0x5080) && (pdev->revision == 0);
1842522479fb98c6667f081e75f87e298e413c0b1db8Jeff Garzik
1843522479fb98c6667f081e75f87e298e413c0b1db8Jeff Garzik	if (!early_5080) {
1844522479fb98c6667f081e75f87e298e413c0b1db8Jeff Garzik		u32 tmp = readl(mmio + MV_PCI_EXP_ROM_BAR_CTL);
1845522479fb98c6667f081e75f87e298e413c0b1db8Jeff Garzik		tmp |= (1 << 0);
1846522479fb98c6667f081e75f87e298e413c0b1db8Jeff Garzik		writel(tmp, mmio + MV_PCI_EXP_ROM_BAR_CTL);
1847522479fb98c6667f081e75f87e298e413c0b1db8Jeff Garzik	}
1848522479fb98c6667f081e75f87e298e413c0b1db8Jeff Garzik
1849522479fb98c6667f081e75f87e298e413c0b1db8Jeff Garzik	mv_reset_pci_bus(pdev, mmio);
1850522479fb98c6667f081e75f87e298e413c0b1db8Jeff Garzik}
1851522479fb98c6667f081e75f87e298e413c0b1db8Jeff Garzik
1852522479fb98c6667f081e75f87e298e413c0b1db8Jeff Garzikstatic void mv5_reset_flash(struct mv_host_priv *hpriv, void __iomem *mmio)
1853522479fb98c6667f081e75f87e298e413c0b1db8Jeff Garzik{
1854522479fb98c6667f081e75f87e298e413c0b1db8Jeff Garzik	writel(0x0fcfffff, mmio + MV_FLASH_CTL);
1855522479fb98c6667f081e75f87e298e413c0b1db8Jeff Garzik}
1856522479fb98c6667f081e75f87e298e413c0b1db8Jeff Garzik
185747c2b677daeed9c79ecb7167c211ff36876ea611Jeff Garzikstatic void mv5_read_preamp(struct mv_host_priv *hpriv, int idx,
1858ba3fe8fb6a469390a14379519915f3c39a973d99Jeff Garzik			   void __iomem *mmio)
1859ba3fe8fb6a469390a14379519915f3c39a973d99Jeff Garzik{
1860c9d39130123238ac18478a42e25cb7996eacfcc0Jeff Garzik	void __iomem *phy_mmio = mv5_phy_base(mmio, idx);
1861c9d39130123238ac18478a42e25cb7996eacfcc0Jeff Garzik	u32 tmp;
1862c9d39130123238ac18478a42e25cb7996eacfcc0Jeff Garzik
1863c9d39130123238ac18478a42e25cb7996eacfcc0Jeff Garzik	tmp = readl(phy_mmio + MV5_PHY_MODE);
1864c9d39130123238ac18478a42e25cb7996eacfcc0Jeff Garzik
1865c9d39130123238ac18478a42e25cb7996eacfcc0Jeff Garzik	hpriv->signal[idx].pre = tmp & 0x1800;	/* bits 12:11 */
1866c9d39130123238ac18478a42e25cb7996eacfcc0Jeff Garzik	hpriv->signal[idx].amps = tmp & 0xe0;	/* bits 7:5 */
1867ba3fe8fb6a469390a14379519915f3c39a973d99Jeff Garzik}
1868ba3fe8fb6a469390a14379519915f3c39a973d99Jeff Garzik
186947c2b677daeed9c79ecb7167c211ff36876ea611Jeff Garzikstatic void mv5_enable_leds(struct mv_host_priv *hpriv, void __iomem *mmio)
1870ba3fe8fb6a469390a14379519915f3c39a973d99Jeff Garzik{
1871522479fb98c6667f081e75f87e298e413c0b1db8Jeff Garzik	u32 tmp;
1872522479fb98c6667f081e75f87e298e413c0b1db8Jeff Garzik
1873522479fb98c6667f081e75f87e298e413c0b1db8Jeff Garzik	writel(0, mmio + MV_GPIO_PORT_CTL);
1874522479fb98c6667f081e75f87e298e413c0b1db8Jeff Garzik
1875522479fb98c6667f081e75f87e298e413c0b1db8Jeff Garzik	/* FIXME: handle MV_HP_ERRATA_50XXB2 errata */
1876522479fb98c6667f081e75f87e298e413c0b1db8Jeff Garzik
1877522479fb98c6667f081e75f87e298e413c0b1db8Jeff Garzik	tmp = readl(mmio + MV_PCI_EXP_ROM_BAR_CTL);
1878522479fb98c6667f081e75f87e298e413c0b1db8Jeff Garzik	tmp |= ~(1 << 0);
1879522479fb98c6667f081e75f87e298e413c0b1db8Jeff Garzik	writel(tmp, mmio + MV_PCI_EXP_ROM_BAR_CTL);
1880ba3fe8fb6a469390a14379519915f3c39a973d99Jeff Garzik}
1881ba3fe8fb6a469390a14379519915f3c39a973d99Jeff Garzik
18822a47ce06d534692f9bd2bf4e90a20fc9b1054c39Jeff Garzikstatic void mv5_phy_errata(struct mv_host_priv *hpriv, void __iomem *mmio,
18832a47ce06d534692f9bd2bf4e90a20fc9b1054c39Jeff Garzik			   unsigned int port)
1884bca1c4eb9411533d613123618c0d127fae532595Jeff Garzik{
1885c9d39130123238ac18478a42e25cb7996eacfcc0Jeff Garzik	void __iomem *phy_mmio = mv5_phy_base(mmio, port);
1886c9d39130123238ac18478a42e25cb7996eacfcc0Jeff Garzik	const u32 mask = (1<<12) | (1<<11) | (1<<7) | (1<<6) | (1<<5);
1887c9d39130123238ac18478a42e25cb7996eacfcc0Jeff Garzik	u32 tmp;
1888c9d39130123238ac18478a42e25cb7996eacfcc0Jeff Garzik	int fix_apm_sq = (hpriv->hp_flags & MV_HP_ERRATA_50XXB0);
1889c9d39130123238ac18478a42e25cb7996eacfcc0Jeff Garzik
1890c9d39130123238ac18478a42e25cb7996eacfcc0Jeff Garzik	if (fix_apm_sq) {
1891c9d39130123238ac18478a42e25cb7996eacfcc0Jeff Garzik		tmp = readl(phy_mmio + MV5_LT_MODE);
1892c9d39130123238ac18478a42e25cb7996eacfcc0Jeff Garzik		tmp |= (1 << 19);
1893c9d39130123238ac18478a42e25cb7996eacfcc0Jeff Garzik		writel(tmp, phy_mmio + MV5_LT_MODE);
1894c9d39130123238ac18478a42e25cb7996eacfcc0Jeff Garzik
1895c9d39130123238ac18478a42e25cb7996eacfcc0Jeff Garzik		tmp = readl(phy_mmio + MV5_PHY_CTL);
1896c9d39130123238ac18478a42e25cb7996eacfcc0Jeff Garzik		tmp &= ~0x3;
1897c9d39130123238ac18478a42e25cb7996eacfcc0Jeff Garzik		tmp |= 0x1;
1898c9d39130123238ac18478a42e25cb7996eacfcc0Jeff Garzik		writel(tmp, phy_mmio + MV5_PHY_CTL);
1899c9d39130123238ac18478a42e25cb7996eacfcc0Jeff Garzik	}
1900c9d39130123238ac18478a42e25cb7996eacfcc0Jeff Garzik
1901c9d39130123238ac18478a42e25cb7996eacfcc0Jeff Garzik	tmp = readl(phy_mmio + MV5_PHY_MODE);
1902c9d39130123238ac18478a42e25cb7996eacfcc0Jeff Garzik	tmp &= ~mask;
1903c9d39130123238ac18478a42e25cb7996eacfcc0Jeff Garzik	tmp |= hpriv->signal[port].pre;
1904c9d39130123238ac18478a42e25cb7996eacfcc0Jeff Garzik	tmp |= hpriv->signal[port].amps;
1905c9d39130123238ac18478a42e25cb7996eacfcc0Jeff Garzik	writel(tmp, phy_mmio + MV5_PHY_MODE);
1906bca1c4eb9411533d613123618c0d127fae532595Jeff Garzik}
1907bca1c4eb9411533d613123618c0d127fae532595Jeff Garzik
1908c9d39130123238ac18478a42e25cb7996eacfcc0Jeff Garzik
1909c9d39130123238ac18478a42e25cb7996eacfcc0Jeff Garzik#undef ZERO
1910c9d39130123238ac18478a42e25cb7996eacfcc0Jeff Garzik#define ZERO(reg) writel(0, port_mmio + (reg))
1911c9d39130123238ac18478a42e25cb7996eacfcc0Jeff Garzikstatic void mv5_reset_hc_port(struct mv_host_priv *hpriv, void __iomem *mmio,
1912c9d39130123238ac18478a42e25cb7996eacfcc0Jeff Garzik			     unsigned int port)
1913c9d39130123238ac18478a42e25cb7996eacfcc0Jeff Garzik{
1914c9d39130123238ac18478a42e25cb7996eacfcc0Jeff Garzik	void __iomem *port_mmio = mv_port_base(mmio, port);
1915c9d39130123238ac18478a42e25cb7996eacfcc0Jeff Garzik
1916c9d39130123238ac18478a42e25cb7996eacfcc0Jeff Garzik	writelfl(EDMA_DS, port_mmio + EDMA_CMD_OFS);
1917c9d39130123238ac18478a42e25cb7996eacfcc0Jeff Garzik
1918c9d39130123238ac18478a42e25cb7996eacfcc0Jeff Garzik	mv_channel_reset(hpriv, mmio, port);
1919c9d39130123238ac18478a42e25cb7996eacfcc0Jeff Garzik
1920c9d39130123238ac18478a42e25cb7996eacfcc0Jeff Garzik	ZERO(0x028);	/* command */
1921c9d39130123238ac18478a42e25cb7996eacfcc0Jeff Garzik	writel(0x11f, port_mmio + EDMA_CFG_OFS);
1922c9d39130123238ac18478a42e25cb7996eacfcc0Jeff Garzik	ZERO(0x004);	/* timer */
1923c9d39130123238ac18478a42e25cb7996eacfcc0Jeff Garzik	ZERO(0x008);	/* irq err cause */
1924c9d39130123238ac18478a42e25cb7996eacfcc0Jeff Garzik	ZERO(0x00c);	/* irq err mask */
1925c9d39130123238ac18478a42e25cb7996eacfcc0Jeff Garzik	ZERO(0x010);	/* rq bah */
1926c9d39130123238ac18478a42e25cb7996eacfcc0Jeff Garzik	ZERO(0x014);	/* rq inp */
1927c9d39130123238ac18478a42e25cb7996eacfcc0Jeff Garzik	ZERO(0x018);	/* rq outp */
1928c9d39130123238ac18478a42e25cb7996eacfcc0Jeff Garzik	ZERO(0x01c);	/* respq bah */
1929c9d39130123238ac18478a42e25cb7996eacfcc0Jeff Garzik	ZERO(0x024);	/* respq outp */
1930c9d39130123238ac18478a42e25cb7996eacfcc0Jeff Garzik	ZERO(0x020);	/* respq inp */
1931c9d39130123238ac18478a42e25cb7996eacfcc0Jeff Garzik	ZERO(0x02c);	/* test control */
1932c9d39130123238ac18478a42e25cb7996eacfcc0Jeff Garzik	writel(0xbc, port_mmio + EDMA_IORDY_TMOUT);
1933c9d39130123238ac18478a42e25cb7996eacfcc0Jeff Garzik}
1934c9d39130123238ac18478a42e25cb7996eacfcc0Jeff Garzik#undef ZERO
1935c9d39130123238ac18478a42e25cb7996eacfcc0Jeff Garzik
1936c9d39130123238ac18478a42e25cb7996eacfcc0Jeff Garzik#define ZERO(reg) writel(0, hc_mmio + (reg))
1937c9d39130123238ac18478a42e25cb7996eacfcc0Jeff Garzikstatic void mv5_reset_one_hc(struct mv_host_priv *hpriv, void __iomem *mmio,
1938c9d39130123238ac18478a42e25cb7996eacfcc0Jeff Garzik			unsigned int hc)
193947c2b677daeed9c79ecb7167c211ff36876ea611Jeff Garzik{
1940c9d39130123238ac18478a42e25cb7996eacfcc0Jeff Garzik	void __iomem *hc_mmio = mv_hc_base(mmio, hc);
1941c9d39130123238ac18478a42e25cb7996eacfcc0Jeff Garzik	u32 tmp;
1942c9d39130123238ac18478a42e25cb7996eacfcc0Jeff Garzik
1943c9d39130123238ac18478a42e25cb7996eacfcc0Jeff Garzik	ZERO(0x00c);
1944c9d39130123238ac18478a42e25cb7996eacfcc0Jeff Garzik	ZERO(0x010);
1945c9d39130123238ac18478a42e25cb7996eacfcc0Jeff Garzik	ZERO(0x014);
1946c9d39130123238ac18478a42e25cb7996eacfcc0Jeff Garzik	ZERO(0x018);
1947c9d39130123238ac18478a42e25cb7996eacfcc0Jeff Garzik
1948c9d39130123238ac18478a42e25cb7996eacfcc0Jeff Garzik	tmp = readl(hc_mmio + 0x20);
1949c9d39130123238ac18478a42e25cb7996eacfcc0Jeff Garzik	tmp &= 0x1c1c1c1c;
1950c9d39130123238ac18478a42e25cb7996eacfcc0Jeff Garzik	tmp |= 0x03030303;
1951c9d39130123238ac18478a42e25cb7996eacfcc0Jeff Garzik	writel(tmp, hc_mmio + 0x20);
1952c9d39130123238ac18478a42e25cb7996eacfcc0Jeff Garzik}
1953c9d39130123238ac18478a42e25cb7996eacfcc0Jeff Garzik#undef ZERO
1954c9d39130123238ac18478a42e25cb7996eacfcc0Jeff Garzik
1955c9d39130123238ac18478a42e25cb7996eacfcc0Jeff Garzikstatic int mv5_reset_hc(struct mv_host_priv *hpriv, void __iomem *mmio,
1956c9d39130123238ac18478a42e25cb7996eacfcc0Jeff Garzik			unsigned int n_hc)
1957c9d39130123238ac18478a42e25cb7996eacfcc0Jeff Garzik{
1958c9d39130123238ac18478a42e25cb7996eacfcc0Jeff Garzik	unsigned int hc, port;
1959c9d39130123238ac18478a42e25cb7996eacfcc0Jeff Garzik
1960c9d39130123238ac18478a42e25cb7996eacfcc0Jeff Garzik	for (hc = 0; hc < n_hc; hc++) {
1961c9d39130123238ac18478a42e25cb7996eacfcc0Jeff Garzik		for (port = 0; port < MV_PORTS_PER_HC; port++)
1962c9d39130123238ac18478a42e25cb7996eacfcc0Jeff Garzik			mv5_reset_hc_port(hpriv, mmio,
1963c9d39130123238ac18478a42e25cb7996eacfcc0Jeff Garzik					  (hc * MV_PORTS_PER_HC) + port);
1964c9d39130123238ac18478a42e25cb7996eacfcc0Jeff Garzik
1965c9d39130123238ac18478a42e25cb7996eacfcc0Jeff Garzik		mv5_reset_one_hc(hpriv, mmio, hc);
1966c9d39130123238ac18478a42e25cb7996eacfcc0Jeff Garzik	}
1967c9d39130123238ac18478a42e25cb7996eacfcc0Jeff Garzik
1968c9d39130123238ac18478a42e25cb7996eacfcc0Jeff Garzik	return 0;
196947c2b677daeed9c79ecb7167c211ff36876ea611Jeff Garzik}
197047c2b677daeed9c79ecb7167c211ff36876ea611Jeff Garzik
1971101ffae26c23ea928fce6d31a8b4901327d91a15Jeff Garzik#undef ZERO
1972101ffae26c23ea928fce6d31a8b4901327d91a15Jeff Garzik#define ZERO(reg) writel(0, mmio + (reg))
1973101ffae26c23ea928fce6d31a8b4901327d91a15Jeff Garzikstatic void mv_reset_pci_bus(struct pci_dev *pdev, void __iomem *mmio)
1974101ffae26c23ea928fce6d31a8b4901327d91a15Jeff Garzik{
197502a121da5a53d415b6596bc19cc6999d295d32a4Mark Lord	struct ata_host     *host = dev_get_drvdata(&pdev->dev);
197602a121da5a53d415b6596bc19cc6999d295d32a4Mark Lord	struct mv_host_priv *hpriv = host->private_data;
1977101ffae26c23ea928fce6d31a8b4901327d91a15Jeff Garzik	u32 tmp;
1978101ffae26c23ea928fce6d31a8b4901327d91a15Jeff Garzik
1979101ffae26c23ea928fce6d31a8b4901327d91a15Jeff Garzik	tmp = readl(mmio + MV_PCI_MODE);
1980101ffae26c23ea928fce6d31a8b4901327d91a15Jeff Garzik	tmp &= 0xff00ffff;
1981101ffae26c23ea928fce6d31a8b4901327d91a15Jeff Garzik	writel(tmp, mmio + MV_PCI_MODE);
1982101ffae26c23ea928fce6d31a8b4901327d91a15Jeff Garzik
1983101ffae26c23ea928fce6d31a8b4901327d91a15Jeff Garzik	ZERO(MV_PCI_DISC_TIMER);
1984101ffae26c23ea928fce6d31a8b4901327d91a15Jeff Garzik	ZERO(MV_PCI_MSI_TRIGGER);
1985101ffae26c23ea928fce6d31a8b4901327d91a15Jeff Garzik	writel(0x000100ff, mmio + MV_PCI_XBAR_TMOUT);
1986101ffae26c23ea928fce6d31a8b4901327d91a15Jeff Garzik	ZERO(HC_MAIN_IRQ_MASK_OFS);
1987101ffae26c23ea928fce6d31a8b4901327d91a15Jeff Garzik	ZERO(MV_PCI_SERR_MASK);
198802a121da5a53d415b6596bc19cc6999d295d32a4Mark Lord	ZERO(hpriv->irq_cause_ofs);
198902a121da5a53d415b6596bc19cc6999d295d32a4Mark Lord	ZERO(hpriv->irq_mask_ofs);
1990101ffae26c23ea928fce6d31a8b4901327d91a15Jeff Garzik	ZERO(MV_PCI_ERR_LOW_ADDRESS);
1991101ffae26c23ea928fce6d31a8b4901327d91a15Jeff Garzik	ZERO(MV_PCI_ERR_HIGH_ADDRESS);
1992101ffae26c23ea928fce6d31a8b4901327d91a15Jeff Garzik	ZERO(MV_PCI_ERR_ATTRIBUTE);
1993101ffae26c23ea928fce6d31a8b4901327d91a15Jeff Garzik	ZERO(MV_PCI_ERR_COMMAND);
1994101ffae26c23ea928fce6d31a8b4901327d91a15Jeff Garzik}
1995101ffae26c23ea928fce6d31a8b4901327d91a15Jeff Garzik#undef ZERO
1996101ffae26c23ea928fce6d31a8b4901327d91a15Jeff Garzik
1997101ffae26c23ea928fce6d31a8b4901327d91a15Jeff Garzikstatic void mv6_reset_flash(struct mv_host_priv *hpriv, void __iomem *mmio)
1998101ffae26c23ea928fce6d31a8b4901327d91a15Jeff Garzik{
1999101ffae26c23ea928fce6d31a8b4901327d91a15Jeff Garzik	u32 tmp;
2000101ffae26c23ea928fce6d31a8b4901327d91a15Jeff Garzik
2001101ffae26c23ea928fce6d31a8b4901327d91a15Jeff Garzik	mv5_reset_flash(hpriv, mmio);
2002101ffae26c23ea928fce6d31a8b4901327d91a15Jeff Garzik
2003101ffae26c23ea928fce6d31a8b4901327d91a15Jeff Garzik	tmp = readl(mmio + MV_GPIO_PORT_CTL);
2004101ffae26c23ea928fce6d31a8b4901327d91a15Jeff Garzik	tmp &= 0x3;
2005101ffae26c23ea928fce6d31a8b4901327d91a15Jeff Garzik	tmp |= (1 << 5) | (1 << 6);
2006101ffae26c23ea928fce6d31a8b4901327d91a15Jeff Garzik	writel(tmp, mmio + MV_GPIO_PORT_CTL);
2007101ffae26c23ea928fce6d31a8b4901327d91a15Jeff Garzik}
2008101ffae26c23ea928fce6d31a8b4901327d91a15Jeff Garzik
2009101ffae26c23ea928fce6d31a8b4901327d91a15Jeff Garzik/**
2010101ffae26c23ea928fce6d31a8b4901327d91a15Jeff Garzik *      mv6_reset_hc - Perform the 6xxx global soft reset
2011101ffae26c23ea928fce6d31a8b4901327d91a15Jeff Garzik *      @mmio: base address of the HBA
2012101ffae26c23ea928fce6d31a8b4901327d91a15Jeff Garzik *
2013101ffae26c23ea928fce6d31a8b4901327d91a15Jeff Garzik *      This routine only applies to 6xxx parts.
2014101ffae26c23ea928fce6d31a8b4901327d91a15Jeff Garzik *
2015101ffae26c23ea928fce6d31a8b4901327d91a15Jeff Garzik *      LOCKING:
2016101ffae26c23ea928fce6d31a8b4901327d91a15Jeff Garzik *      Inherited from caller.
2017101ffae26c23ea928fce6d31a8b4901327d91a15Jeff Garzik */
2018c9d39130123238ac18478a42e25cb7996eacfcc0Jeff Garzikstatic int mv6_reset_hc(struct mv_host_priv *hpriv, void __iomem *mmio,
2019c9d39130123238ac18478a42e25cb7996eacfcc0Jeff Garzik			unsigned int n_hc)
2020101ffae26c23ea928fce6d31a8b4901327d91a15Jeff Garzik{
2021101ffae26c23ea928fce6d31a8b4901327d91a15Jeff Garzik	void __iomem *reg = mmio + PCI_MAIN_CMD_STS_OFS;
2022101ffae26c23ea928fce6d31a8b4901327d91a15Jeff Garzik	int i, rc = 0;
2023101ffae26c23ea928fce6d31a8b4901327d91a15Jeff Garzik	u32 t;
2024101ffae26c23ea928fce6d31a8b4901327d91a15Jeff Garzik
2025101ffae26c23ea928fce6d31a8b4901327d91a15Jeff Garzik	/* Following procedure defined in PCI "main command and status
2026101ffae26c23ea928fce6d31a8b4901327d91a15Jeff Garzik	 * register" table.
2027101ffae26c23ea928fce6d31a8b4901327d91a15Jeff Garzik	 */
2028101ffae26c23ea928fce6d31a8b4901327d91a15Jeff Garzik	t = readl(reg);
2029101ffae26c23ea928fce6d31a8b4901327d91a15Jeff Garzik	writel(t | STOP_PCI_MASTER, reg);
2030101ffae26c23ea928fce6d31a8b4901327d91a15Jeff Garzik
2031101ffae26c23ea928fce6d31a8b4901327d91a15Jeff Garzik	for (i = 0; i < 1000; i++) {
2032101ffae26c23ea928fce6d31a8b4901327d91a15Jeff Garzik		udelay(1);
2033101ffae26c23ea928fce6d31a8b4901327d91a15Jeff Garzik		t = readl(reg);
20342dcb407e61458ded17503d6bd12b8c064965368bJeff Garzik		if (PCI_MASTER_EMPTY & t)
2035101ffae26c23ea928fce6d31a8b4901327d91a15Jeff Garzik			break;
2036101ffae26c23ea928fce6d31a8b4901327d91a15Jeff Garzik	}
2037101ffae26c23ea928fce6d31a8b4901327d91a15Jeff Garzik	if (!(PCI_MASTER_EMPTY & t)) {
2038101ffae26c23ea928fce6d31a8b4901327d91a15Jeff Garzik		printk(KERN_ERR DRV_NAME ": PCI master won't flush\n");
2039101ffae26c23ea928fce6d31a8b4901327d91a15Jeff Garzik		rc = 1;
2040101ffae26c23ea928fce6d31a8b4901327d91a15Jeff Garzik		goto done;
2041101ffae26c23ea928fce6d31a8b4901327d91a15Jeff Garzik	}
2042101ffae26c23ea928fce6d31a8b4901327d91a15Jeff Garzik
2043101ffae26c23ea928fce6d31a8b4901327d91a15Jeff Garzik	/* set reset */
2044101ffae26c23ea928fce6d31a8b4901327d91a15Jeff Garzik	i = 5;
2045101ffae26c23ea928fce6d31a8b4901327d91a15Jeff Garzik	do {
2046101ffae26c23ea928fce6d31a8b4901327d91a15Jeff Garzik		writel(t | GLOB_SFT_RST, reg);
2047101ffae26c23ea928fce6d31a8b4901327d91a15Jeff Garzik		t = readl(reg);
2048101ffae26c23ea928fce6d31a8b4901327d91a15Jeff Garzik		udelay(1);
2049101ffae26c23ea928fce6d31a8b4901327d91a15Jeff Garzik	} while (!(GLOB_SFT_RST & t) && (i-- > 0));
2050101ffae26c23ea928fce6d31a8b4901327d91a15Jeff Garzik
2051101ffae26c23ea928fce6d31a8b4901327d91a15Jeff Garzik	if (!(GLOB_SFT_RST & t)) {
2052101ffae26c23ea928fce6d31a8b4901327d91a15Jeff Garzik		printk(KERN_ERR DRV_NAME ": can't set global reset\n");
2053101ffae26c23ea928fce6d31a8b4901327d91a15Jeff Garzik		rc = 1;
2054101ffae26c23ea928fce6d31a8b4901327d91a15Jeff Garzik		goto done;
2055101ffae26c23ea928fce6d31a8b4901327d91a15Jeff Garzik	}
2056101ffae26c23ea928fce6d31a8b4901327d91a15Jeff Garzik
2057101ffae26c23ea928fce6d31a8b4901327d91a15Jeff Garzik	/* clear reset and *reenable the PCI master* (not mentioned in spec) */
2058101ffae26c23ea928fce6d31a8b4901327d91a15Jeff Garzik	i = 5;
2059101ffae26c23ea928fce6d31a8b4901327d91a15Jeff Garzik	do {
2060101ffae26c23ea928fce6d31a8b4901327d91a15Jeff Garzik		writel(t & ~(GLOB_SFT_RST | STOP_PCI_MASTER), reg);
2061101ffae26c23ea928fce6d31a8b4901327d91a15Jeff Garzik		t = readl(reg);
2062101ffae26c23ea928fce6d31a8b4901327d91a15Jeff Garzik		udelay(1);
2063101ffae26c23ea928fce6d31a8b4901327d91a15Jeff Garzik	} while ((GLOB_SFT_RST & t) && (i-- > 0));
2064101ffae26c23ea928fce6d31a8b4901327d91a15Jeff Garzik
2065101ffae26c23ea928fce6d31a8b4901327d91a15Jeff Garzik	if (GLOB_SFT_RST & t) {
2066101ffae26c23ea928fce6d31a8b4901327d91a15Jeff Garzik		printk(KERN_ERR DRV_NAME ": can't clear global reset\n");
2067101ffae26c23ea928fce6d31a8b4901327d91a15Jeff Garzik		rc = 1;
2068101ffae26c23ea928fce6d31a8b4901327d91a15Jeff Garzik	}
2069101ffae26c23ea928fce6d31a8b4901327d91a15Jeff Garzikdone:
2070101ffae26c23ea928fce6d31a8b4901327d91a15Jeff Garzik	return rc;
2071101ffae26c23ea928fce6d31a8b4901327d91a15Jeff Garzik}
2072101ffae26c23ea928fce6d31a8b4901327d91a15Jeff Garzik
207347c2b677daeed9c79ecb7167c211ff36876ea611Jeff Garzikstatic void mv6_read_preamp(struct mv_host_priv *hpriv, int idx,
2074ba3fe8fb6a469390a14379519915f3c39a973d99Jeff Garzik			   void __iomem *mmio)
2075ba3fe8fb6a469390a14379519915f3c39a973d99Jeff Garzik{
2076ba3fe8fb6a469390a14379519915f3c39a973d99Jeff Garzik	void __iomem *port_mmio;
2077ba3fe8fb6a469390a14379519915f3c39a973d99Jeff Garzik	u32 tmp;
2078ba3fe8fb6a469390a14379519915f3c39a973d99Jeff Garzik
2079ba3fe8fb6a469390a14379519915f3c39a973d99Jeff Garzik	tmp = readl(mmio + MV_RESET_CFG);
2080ba3fe8fb6a469390a14379519915f3c39a973d99Jeff Garzik	if ((tmp & (1 << 0)) == 0) {
208147c2b677daeed9c79ecb7167c211ff36876ea611Jeff Garzik		hpriv->signal[idx].amps = 0x7 << 8;
2082ba3fe8fb6a469390a14379519915f3c39a973d99Jeff Garzik		hpriv->signal[idx].pre = 0x1 << 5;
2083ba3fe8fb6a469390a14379519915f3c39a973d99Jeff Garzik		return;
2084ba3fe8fb6a469390a14379519915f3c39a973d99Jeff Garzik	}
2085ba3fe8fb6a469390a14379519915f3c39a973d99Jeff Garzik
2086ba3fe8fb6a469390a14379519915f3c39a973d99Jeff Garzik	port_mmio = mv_port_base(mmio, idx);
2087ba3fe8fb6a469390a14379519915f3c39a973d99Jeff Garzik	tmp = readl(port_mmio + PHY_MODE2);
2088ba3fe8fb6a469390a14379519915f3c39a973d99Jeff Garzik
2089ba3fe8fb6a469390a14379519915f3c39a973d99Jeff Garzik	hpriv->signal[idx].amps = tmp & 0x700;	/* bits 10:8 */
2090ba3fe8fb6a469390a14379519915f3c39a973d99Jeff Garzik	hpriv->signal[idx].pre = tmp & 0xe0;	/* bits 7:5 */
2091ba3fe8fb6a469390a14379519915f3c39a973d99Jeff Garzik}
2092ba3fe8fb6a469390a14379519915f3c39a973d99Jeff Garzik
209347c2b677daeed9c79ecb7167c211ff36876ea611Jeff Garzikstatic void mv6_enable_leds(struct mv_host_priv *hpriv, void __iomem *mmio)
2094ba3fe8fb6a469390a14379519915f3c39a973d99Jeff Garzik{
209547c2b677daeed9c79ecb7167c211ff36876ea611Jeff Garzik	writel(0x00000060, mmio + MV_GPIO_PORT_CTL);
2096ba3fe8fb6a469390a14379519915f3c39a973d99Jeff Garzik}
2097ba3fe8fb6a469390a14379519915f3c39a973d99Jeff Garzik
2098c9d39130123238ac18478a42e25cb7996eacfcc0Jeff Garzikstatic void mv6_phy_errata(struct mv_host_priv *hpriv, void __iomem *mmio,
20992a47ce06d534692f9bd2bf4e90a20fc9b1054c39Jeff Garzik			   unsigned int port)
2100bca1c4eb9411533d613123618c0d127fae532595Jeff Garzik{
2101c9d39130123238ac18478a42e25cb7996eacfcc0Jeff Garzik	void __iomem *port_mmio = mv_port_base(mmio, port);
2102c9d39130123238ac18478a42e25cb7996eacfcc0Jeff Garzik
2103bca1c4eb9411533d613123618c0d127fae532595Jeff Garzik	u32 hp_flags = hpriv->hp_flags;
210447c2b677daeed9c79ecb7167c211ff36876ea611Jeff Garzik	int fix_phy_mode2 =
210547c2b677daeed9c79ecb7167c211ff36876ea611Jeff Garzik		hp_flags & (MV_HP_ERRATA_60X1B2 | MV_HP_ERRATA_60X1C0);
2106bca1c4eb9411533d613123618c0d127fae532595Jeff Garzik	int fix_phy_mode4 =
210747c2b677daeed9c79ecb7167c211ff36876ea611Jeff Garzik		hp_flags & (MV_HP_ERRATA_60X1B2 | MV_HP_ERRATA_60X1C0);
210847c2b677daeed9c79ecb7167c211ff36876ea611Jeff Garzik	u32 m2, tmp;
210947c2b677daeed9c79ecb7167c211ff36876ea611Jeff Garzik
211047c2b677daeed9c79ecb7167c211ff36876ea611Jeff Garzik	if (fix_phy_mode2) {
211147c2b677daeed9c79ecb7167c211ff36876ea611Jeff Garzik		m2 = readl(port_mmio + PHY_MODE2);
211247c2b677daeed9c79ecb7167c211ff36876ea611Jeff Garzik		m2 &= ~(1 << 16);
211347c2b677daeed9c79ecb7167c211ff36876ea611Jeff Garzik		m2 |= (1 << 31);
211447c2b677daeed9c79ecb7167c211ff36876ea611Jeff Garzik		writel(m2, port_mmio + PHY_MODE2);
211547c2b677daeed9c79ecb7167c211ff36876ea611Jeff Garzik
211647c2b677daeed9c79ecb7167c211ff36876ea611Jeff Garzik		udelay(200);
211747c2b677daeed9c79ecb7167c211ff36876ea611Jeff Garzik
211847c2b677daeed9c79ecb7167c211ff36876ea611Jeff Garzik		m2 = readl(port_mmio + PHY_MODE2);
211947c2b677daeed9c79ecb7167c211ff36876ea611Jeff Garzik		m2 &= ~((1 << 16) | (1 << 31));
212047c2b677daeed9c79ecb7167c211ff36876ea611Jeff Garzik		writel(m2, port_mmio + PHY_MODE2);
212147c2b677daeed9c79ecb7167c211ff36876ea611Jeff Garzik
212247c2b677daeed9c79ecb7167c211ff36876ea611Jeff Garzik		udelay(200);
212347c2b677daeed9c79ecb7167c211ff36876ea611Jeff Garzik	}
212447c2b677daeed9c79ecb7167c211ff36876ea611Jeff Garzik
212547c2b677daeed9c79ecb7167c211ff36876ea611Jeff Garzik	/* who knows what this magic does */
212647c2b677daeed9c79ecb7167c211ff36876ea611Jeff Garzik	tmp = readl(port_mmio + PHY_MODE3);
212747c2b677daeed9c79ecb7167c211ff36876ea611Jeff Garzik	tmp &= ~0x7F800000;
212847c2b677daeed9c79ecb7167c211ff36876ea611Jeff Garzik	tmp |= 0x2A800000;
212947c2b677daeed9c79ecb7167c211ff36876ea611Jeff Garzik	writel(tmp, port_mmio + PHY_MODE3);
2130bca1c4eb9411533d613123618c0d127fae532595Jeff Garzik
2131bca1c4eb9411533d613123618c0d127fae532595Jeff Garzik	if (fix_phy_mode4) {
213247c2b677daeed9c79ecb7167c211ff36876ea611Jeff Garzik		u32 m4;
2133bca1c4eb9411533d613123618c0d127fae532595Jeff Garzik
2134bca1c4eb9411533d613123618c0d127fae532595Jeff Garzik		m4 = readl(port_mmio + PHY_MODE4);
213547c2b677daeed9c79ecb7167c211ff36876ea611Jeff Garzik
213647c2b677daeed9c79ecb7167c211ff36876ea611Jeff Garzik		if (hp_flags & MV_HP_ERRATA_60X1B2)
213747c2b677daeed9c79ecb7167c211ff36876ea611Jeff Garzik			tmp = readl(port_mmio + 0x310);
2138bca1c4eb9411533d613123618c0d127fae532595Jeff Garzik
2139bca1c4eb9411533d613123618c0d127fae532595Jeff Garzik		m4 = (m4 & ~(1 << 1)) | (1 << 0);
2140bca1c4eb9411533d613123618c0d127fae532595Jeff Garzik
2141bca1c4eb9411533d613123618c0d127fae532595Jeff Garzik		writel(m4, port_mmio + PHY_MODE4);
214247c2b677daeed9c79ecb7167c211ff36876ea611Jeff Garzik
214347c2b677daeed9c79ecb7167c211ff36876ea611Jeff Garzik		if (hp_flags & MV_HP_ERRATA_60X1B2)
214447c2b677daeed9c79ecb7167c211ff36876ea611Jeff Garzik			writel(tmp, port_mmio + 0x310);
2145bca1c4eb9411533d613123618c0d127fae532595Jeff Garzik	}
2146bca1c4eb9411533d613123618c0d127fae532595Jeff Garzik
2147bca1c4eb9411533d613123618c0d127fae532595Jeff Garzik	/* Revert values of pre-emphasis and signal amps to the saved ones */
2148bca1c4eb9411533d613123618c0d127fae532595Jeff Garzik	m2 = readl(port_mmio + PHY_MODE2);
2149bca1c4eb9411533d613123618c0d127fae532595Jeff Garzik
2150bca1c4eb9411533d613123618c0d127fae532595Jeff Garzik	m2 &= ~MV_M2_PREAMP_MASK;
21512a47ce06d534692f9bd2bf4e90a20fc9b1054c39Jeff Garzik	m2 |= hpriv->signal[port].amps;
21522a47ce06d534692f9bd2bf4e90a20fc9b1054c39Jeff Garzik	m2 |= hpriv->signal[port].pre;
215347c2b677daeed9c79ecb7167c211ff36876ea611Jeff Garzik	m2 &= ~(1 << 16);
2154bca1c4eb9411533d613123618c0d127fae532595Jeff Garzik
2155e4e7b89280d1d666e2c09e5ad36cf071796c4c7eJeff Garzik	/* according to mvSata 3.6.1, some IIE values are fixed */
2156e4e7b89280d1d666e2c09e5ad36cf071796c4c7eJeff Garzik	if (IS_GEN_IIE(hpriv)) {
2157e4e7b89280d1d666e2c09e5ad36cf071796c4c7eJeff Garzik		m2 &= ~0xC30FF01F;
2158e4e7b89280d1d666e2c09e5ad36cf071796c4c7eJeff Garzik		m2 |= 0x0000900F;
2159e4e7b89280d1d666e2c09e5ad36cf071796c4c7eJeff Garzik	}
2160e4e7b89280d1d666e2c09e5ad36cf071796c4c7eJeff Garzik
2161bca1c4eb9411533d613123618c0d127fae532595Jeff Garzik	writel(m2, port_mmio + PHY_MODE2);
2162bca1c4eb9411533d613123618c0d127fae532595Jeff Garzik}
2163bca1c4eb9411533d613123618c0d127fae532595Jeff Garzik
2164c9d39130123238ac18478a42e25cb7996eacfcc0Jeff Garzikstatic void mv_channel_reset(struct mv_host_priv *hpriv, void __iomem *mmio,
2165c9d39130123238ac18478a42e25cb7996eacfcc0Jeff Garzik			     unsigned int port_no)
2166c9d39130123238ac18478a42e25cb7996eacfcc0Jeff Garzik{
2167c9d39130123238ac18478a42e25cb7996eacfcc0Jeff Garzik	void __iomem *port_mmio = mv_port_base(mmio, port_no);
2168c9d39130123238ac18478a42e25cb7996eacfcc0Jeff Garzik
2169c9d39130123238ac18478a42e25cb7996eacfcc0Jeff Garzik	writelfl(ATA_RST, port_mmio + EDMA_CMD_OFS);
2170c9d39130123238ac18478a42e25cb7996eacfcc0Jeff Garzik
2171ee9ccdf70163ca6408f6965e0fbc65baeac7312cJeff Garzik	if (IS_GEN_II(hpriv)) {
2172c9d39130123238ac18478a42e25cb7996eacfcc0Jeff Garzik		u32 ifctl = readl(port_mmio + SATA_INTERFACE_CTL);
2173eb46d684600ac145501805a294c94675e82eab2eMark Lord		ifctl |= (1 << 7);		/* enable gen2i speed */
2174eb46d684600ac145501805a294c94675e82eab2eMark Lord		ifctl = (ifctl & 0xfff) | 0x9b1000; /* from chip spec */
2175c9d39130123238ac18478a42e25cb7996eacfcc0Jeff Garzik		writelfl(ifctl, port_mmio + SATA_INTERFACE_CTL);
2176c9d39130123238ac18478a42e25cb7996eacfcc0Jeff Garzik	}
2177c9d39130123238ac18478a42e25cb7996eacfcc0Jeff Garzik
2178c9d39130123238ac18478a42e25cb7996eacfcc0Jeff Garzik	udelay(25);		/* allow reset propagation */
2179c9d39130123238ac18478a42e25cb7996eacfcc0Jeff Garzik
2180c9d39130123238ac18478a42e25cb7996eacfcc0Jeff Garzik	/* Spec never mentions clearing the bit.  Marvell's driver does
2181c9d39130123238ac18478a42e25cb7996eacfcc0Jeff Garzik	 * clear the bit, however.
2182c9d39130123238ac18478a42e25cb7996eacfcc0Jeff Garzik	 */
2183c9d39130123238ac18478a42e25cb7996eacfcc0Jeff Garzik	writelfl(0, port_mmio + EDMA_CMD_OFS);
2184c9d39130123238ac18478a42e25cb7996eacfcc0Jeff Garzik
2185c9d39130123238ac18478a42e25cb7996eacfcc0Jeff Garzik	hpriv->ops->phy_errata(hpriv, mmio, port_no);
2186c9d39130123238ac18478a42e25cb7996eacfcc0Jeff Garzik
2187ee9ccdf70163ca6408f6965e0fbc65baeac7312cJeff Garzik	if (IS_GEN_I(hpriv))
2188c9d39130123238ac18478a42e25cb7996eacfcc0Jeff Garzik		mdelay(1);
2189c9d39130123238ac18478a42e25cb7996eacfcc0Jeff Garzik}
2190c9d39130123238ac18478a42e25cb7996eacfcc0Jeff Garzik
219105b308e1df6d9d673daedb517969241f41278b52Brett Russ/**
2192bdd4dddee325a7dce3e84cf48201a06aa8508aa4Jeff Garzik *      mv_phy_reset - Perform eDMA reset followed by COMRESET
219305b308e1df6d9d673daedb517969241f41278b52Brett Russ *      @ap: ATA channel to manipulate
219405b308e1df6d9d673daedb517969241f41278b52Brett Russ *
219505b308e1df6d9d673daedb517969241f41278b52Brett Russ *      Part of this is taken from __sata_phy_reset and modified to
219605b308e1df6d9d673daedb517969241f41278b52Brett Russ *      not sleep since this routine gets called from interrupt level.
219705b308e1df6d9d673daedb517969241f41278b52Brett Russ *
219805b308e1df6d9d673daedb517969241f41278b52Brett Russ *      LOCKING:
219905b308e1df6d9d673daedb517969241f41278b52Brett Russ *      Inherited from caller.  This is coded to safe to call at
220005b308e1df6d9d673daedb517969241f41278b52Brett Russ *      interrupt level, i.e. it does not sleep.
220131961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ */
2202bdd4dddee325a7dce3e84cf48201a06aa8508aa4Jeff Garzikstatic void mv_phy_reset(struct ata_port *ap, unsigned int *class,
2203bdd4dddee325a7dce3e84cf48201a06aa8508aa4Jeff Garzik			 unsigned long deadline)
220420f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ{
2205095fec887eaa1c38d17c0c929a6733c744a9fa1fJeff Garzik	struct mv_port_priv *pp	= ap->private_data;
2206cca3974e48607c3775dc73b544a5700b2e37c21aJeff Garzik	struct mv_host_priv *hpriv = ap->host->private_data;
220720f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ	void __iomem *port_mmio = mv_ap_base(ap);
220822374677d18c5eeefd3a283431d312b8c44fef02Jeff Garzik	int retry = 5;
220922374677d18c5eeefd3a283431d312b8c44fef02Jeff Garzik	u32 sstatus;
221020f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ
221120f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ	VPRINTK("ENTER, port %u, mmio 0x%p\n", ap->port_no, port_mmio);
221220f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ
2213da3dbb17a0e9a9ec7f5aed95f1fddadb790edc9dTejun Heo#ifdef DEBUG
2214da3dbb17a0e9a9ec7f5aed95f1fddadb790edc9dTejun Heo	{
2215da3dbb17a0e9a9ec7f5aed95f1fddadb790edc9dTejun Heo		u32 sstatus, serror, scontrol;
2216da3dbb17a0e9a9ec7f5aed95f1fddadb790edc9dTejun Heo
2217da3dbb17a0e9a9ec7f5aed95f1fddadb790edc9dTejun Heo		mv_scr_read(ap, SCR_STATUS, &sstatus);
2218da3dbb17a0e9a9ec7f5aed95f1fddadb790edc9dTejun Heo		mv_scr_read(ap, SCR_ERROR, &serror);
2219da3dbb17a0e9a9ec7f5aed95f1fddadb790edc9dTejun Heo		mv_scr_read(ap, SCR_CONTROL, &scontrol);
2220da3dbb17a0e9a9ec7f5aed95f1fddadb790edc9dTejun Heo		DPRINTK("S-regs after ATA_RST: SStat 0x%08x SErr 0x%08x "
22212d79ab8fd7a7bf3a45d0e948ae27b3dd95ce95eaSaeed Bishara			"SCtrl 0x%08x\n", sstatus, serror, scontrol);
2222da3dbb17a0e9a9ec7f5aed95f1fddadb790edc9dTejun Heo	}
2223da3dbb17a0e9a9ec7f5aed95f1fddadb790edc9dTejun Heo#endif
222420f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ
222522374677d18c5eeefd3a283431d312b8c44fef02Jeff Garzik	/* Issue COMRESET via SControl */
222622374677d18c5eeefd3a283431d312b8c44fef02Jeff Garzikcomreset_retry:
2227936fd7328657884d5a69a55666c74a55aa83ca27Tejun Heo	sata_scr_write_flush(&ap->link, SCR_CONTROL, 0x301);
2228bdd4dddee325a7dce3e84cf48201a06aa8508aa4Jeff Garzik	msleep(1);
222922374677d18c5eeefd3a283431d312b8c44fef02Jeff Garzik
2230936fd7328657884d5a69a55666c74a55aa83ca27Tejun Heo	sata_scr_write_flush(&ap->link, SCR_CONTROL, 0x300);
2231bdd4dddee325a7dce3e84cf48201a06aa8508aa4Jeff Garzik	msleep(20);
223222374677d18c5eeefd3a283431d312b8c44fef02Jeff Garzik
223331961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ	do {
2234936fd7328657884d5a69a55666c74a55aa83ca27Tejun Heo		sata_scr_read(&ap->link, SCR_STATUS, &sstatus);
223562f1d0e6de138b91d55fbd7d579c837ed62e9e31Andres Salomon		if (((sstatus & 0x3) == 3) || ((sstatus & 0x3) == 0))
223631961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ			break;
223722374677d18c5eeefd3a283431d312b8c44fef02Jeff Garzik
2238bdd4dddee325a7dce3e84cf48201a06aa8508aa4Jeff Garzik		msleep(1);
2239c5d3e45a2200a0905dc45b72714726b7aac3aaf1Jeff Garzik	} while (time_before(jiffies, deadline));
224020f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ
224122374677d18c5eeefd3a283431d312b8c44fef02Jeff Garzik	/* work around errata */
2242ee9ccdf70163ca6408f6965e0fbc65baeac7312cJeff Garzik	if (IS_GEN_II(hpriv) &&
224322374677d18c5eeefd3a283431d312b8c44fef02Jeff Garzik	    (sstatus != 0x0) && (sstatus != 0x113) && (sstatus != 0x123) &&
224422374677d18c5eeefd3a283431d312b8c44fef02Jeff Garzik	    (retry-- > 0))
224522374677d18c5eeefd3a283431d312b8c44fef02Jeff Garzik		goto comreset_retry;
2246095fec887eaa1c38d17c0c929a6733c744a9fa1fJeff Garzik
2247da3dbb17a0e9a9ec7f5aed95f1fddadb790edc9dTejun Heo#ifdef DEBUG
2248da3dbb17a0e9a9ec7f5aed95f1fddadb790edc9dTejun Heo	{
2249da3dbb17a0e9a9ec7f5aed95f1fddadb790edc9dTejun Heo		u32 sstatus, serror, scontrol;
2250da3dbb17a0e9a9ec7f5aed95f1fddadb790edc9dTejun Heo
2251da3dbb17a0e9a9ec7f5aed95f1fddadb790edc9dTejun Heo		mv_scr_read(ap, SCR_STATUS, &sstatus);
2252da3dbb17a0e9a9ec7f5aed95f1fddadb790edc9dTejun Heo		mv_scr_read(ap, SCR_ERROR, &serror);
2253da3dbb17a0e9a9ec7f5aed95f1fddadb790edc9dTejun Heo		mv_scr_read(ap, SCR_CONTROL, &scontrol);
2254da3dbb17a0e9a9ec7f5aed95f1fddadb790edc9dTejun Heo		DPRINTK("S-regs after PHY wake: SStat 0x%08x SErr 0x%08x "
2255da3dbb17a0e9a9ec7f5aed95f1fddadb790edc9dTejun Heo			"SCtrl 0x%08x\n", sstatus, serror, scontrol);
2256da3dbb17a0e9a9ec7f5aed95f1fddadb790edc9dTejun Heo	}
2257da3dbb17a0e9a9ec7f5aed95f1fddadb790edc9dTejun Heo#endif
225831961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ
2259936fd7328657884d5a69a55666c74a55aa83ca27Tejun Heo	if (ata_link_offline(&ap->link)) {
2260bdd4dddee325a7dce3e84cf48201a06aa8508aa4Jeff Garzik		*class = ATA_DEV_NONE;
226120f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ		return;
226220f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ	}
226320f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ
226422374677d18c5eeefd3a283431d312b8c44fef02Jeff Garzik	/* even after SStatus reflects that device is ready,
226522374677d18c5eeefd3a283431d312b8c44fef02Jeff Garzik	 * it seems to take a while for link to be fully
226622374677d18c5eeefd3a283431d312b8c44fef02Jeff Garzik	 * established (and thus Status no longer 0x80/0x7F),
226722374677d18c5eeefd3a283431d312b8c44fef02Jeff Garzik	 * so we poll a bit for that, here.
226822374677d18c5eeefd3a283431d312b8c44fef02Jeff Garzik	 */
226922374677d18c5eeefd3a283431d312b8c44fef02Jeff Garzik	retry = 20;
227022374677d18c5eeefd3a283431d312b8c44fef02Jeff Garzik	while (1) {
227122374677d18c5eeefd3a283431d312b8c44fef02Jeff Garzik		u8 drv_stat = ata_check_status(ap);
227222374677d18c5eeefd3a283431d312b8c44fef02Jeff Garzik		if ((drv_stat != 0x80) && (drv_stat != 0x7f))
227322374677d18c5eeefd3a283431d312b8c44fef02Jeff Garzik			break;
2274bdd4dddee325a7dce3e84cf48201a06aa8508aa4Jeff Garzik		msleep(500);
227522374677d18c5eeefd3a283431d312b8c44fef02Jeff Garzik		if (retry-- <= 0)
227622374677d18c5eeefd3a283431d312b8c44fef02Jeff Garzik			break;
2277bdd4dddee325a7dce3e84cf48201a06aa8508aa4Jeff Garzik		if (time_after(jiffies, deadline))
2278bdd4dddee325a7dce3e84cf48201a06aa8508aa4Jeff Garzik			break;
227922374677d18c5eeefd3a283431d312b8c44fef02Jeff Garzik	}
228022374677d18c5eeefd3a283431d312b8c44fef02Jeff Garzik
2281bdd4dddee325a7dce3e84cf48201a06aa8508aa4Jeff Garzik	/* FIXME: if we passed the deadline, the following
2282bdd4dddee325a7dce3e84cf48201a06aa8508aa4Jeff Garzik	 * code probably produces an invalid result
2283bdd4dddee325a7dce3e84cf48201a06aa8508aa4Jeff Garzik	 */
228420f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ
2285bdd4dddee325a7dce3e84cf48201a06aa8508aa4Jeff Garzik	/* finally, read device signature from TF registers */
22863f19859ee95a38c066a0420eb8a30c76ecd67a42Tejun Heo	*class = ata_dev_try_classify(ap->link.device, 1, NULL);
2287095fec887eaa1c38d17c0c929a6733c744a9fa1fJeff Garzik
2288095fec887eaa1c38d17c0c929a6733c744a9fa1fJeff Garzik	writelfl(0, port_mmio + EDMA_ERR_IRQ_CAUSE_OFS);
2289095fec887eaa1c38d17c0c929a6733c744a9fa1fJeff Garzik
2290bdd4dddee325a7dce3e84cf48201a06aa8508aa4Jeff Garzik	WARN_ON(pp->pp_flags & MV_PP_FLAG_EDMA_EN);
2291095fec887eaa1c38d17c0c929a6733c744a9fa1fJeff Garzik
2292bca1c4eb9411533d613123618c0d127fae532595Jeff Garzik	VPRINTK("EXIT\n");
229320f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ}
229420f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ
2295cc0680a580b5be81a1ca321b58f8e9b80b5c1052Tejun Heostatic int mv_prereset(struct ata_link *link, unsigned long deadline)
229622374677d18c5eeefd3a283431d312b8c44fef02Jeff Garzik{
2297cc0680a580b5be81a1ca321b58f8e9b80b5c1052Tejun Heo	struct ata_port *ap = link->ap;
2298bdd4dddee325a7dce3e84cf48201a06aa8508aa4Jeff Garzik	struct mv_port_priv *pp	= ap->private_data;
2299cc0680a580b5be81a1ca321b58f8e9b80b5c1052Tejun Heo	struct ata_eh_context *ehc = &link->eh_context;
2300bdd4dddee325a7dce3e84cf48201a06aa8508aa4Jeff Garzik	int rc;
23010ea9e179f436f153fc19fdaef7abbc1e0da20762Jeff Garzik
2302bdd4dddee325a7dce3e84cf48201a06aa8508aa4Jeff Garzik	rc = mv_stop_dma(ap);
2303bdd4dddee325a7dce3e84cf48201a06aa8508aa4Jeff Garzik	if (rc)
2304bdd4dddee325a7dce3e84cf48201a06aa8508aa4Jeff Garzik		ehc->i.action |= ATA_EH_HARDRESET;
2305bdd4dddee325a7dce3e84cf48201a06aa8508aa4Jeff Garzik
2306bdd4dddee325a7dce3e84cf48201a06aa8508aa4Jeff Garzik	if (!(pp->pp_flags & MV_PP_FLAG_HAD_A_RESET)) {
2307bdd4dddee325a7dce3e84cf48201a06aa8508aa4Jeff Garzik		pp->pp_flags |= MV_PP_FLAG_HAD_A_RESET;
2308bdd4dddee325a7dce3e84cf48201a06aa8508aa4Jeff Garzik		ehc->i.action |= ATA_EH_HARDRESET;
2309bdd4dddee325a7dce3e84cf48201a06aa8508aa4Jeff Garzik	}
2310bdd4dddee325a7dce3e84cf48201a06aa8508aa4Jeff Garzik
2311bdd4dddee325a7dce3e84cf48201a06aa8508aa4Jeff Garzik	/* if we're about to do hardreset, nothing more to do */
2312bdd4dddee325a7dce3e84cf48201a06aa8508aa4Jeff Garzik	if (ehc->i.action & ATA_EH_HARDRESET)
2313bdd4dddee325a7dce3e84cf48201a06aa8508aa4Jeff Garzik		return 0;
2314bdd4dddee325a7dce3e84cf48201a06aa8508aa4Jeff Garzik
2315cc0680a580b5be81a1ca321b58f8e9b80b5c1052Tejun Heo	if (ata_link_online(link))
2316bdd4dddee325a7dce3e84cf48201a06aa8508aa4Jeff Garzik		rc = ata_wait_ready(ap, deadline);
2317bdd4dddee325a7dce3e84cf48201a06aa8508aa4Jeff Garzik	else
2318bdd4dddee325a7dce3e84cf48201a06aa8508aa4Jeff Garzik		rc = -ENODEV;
2319bdd4dddee325a7dce3e84cf48201a06aa8508aa4Jeff Garzik
2320bdd4dddee325a7dce3e84cf48201a06aa8508aa4Jeff Garzik	return rc;
232122374677d18c5eeefd3a283431d312b8c44fef02Jeff Garzik}
232222374677d18c5eeefd3a283431d312b8c44fef02Jeff Garzik
2323cc0680a580b5be81a1ca321b58f8e9b80b5c1052Tejun Heostatic int mv_hardreset(struct ata_link *link, unsigned int *class,
2324bdd4dddee325a7dce3e84cf48201a06aa8508aa4Jeff Garzik			unsigned long deadline)
232531961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ{
2326cc0680a580b5be81a1ca321b58f8e9b80b5c1052Tejun Heo	struct ata_port *ap = link->ap;
2327bdd4dddee325a7dce3e84cf48201a06aa8508aa4Jeff Garzik	struct mv_host_priv *hpriv = ap->host->private_data;
23280d5ff566779f894ca9937231a181eb31e4adff0eTejun Heo	void __iomem *mmio = ap->host->iomap[MV_PRIMARY_BAR];
232931961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ
2330bdd4dddee325a7dce3e84cf48201a06aa8508aa4Jeff Garzik	mv_stop_dma(ap);
233131961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ
2332bdd4dddee325a7dce3e84cf48201a06aa8508aa4Jeff Garzik	mv_channel_reset(hpriv, mmio, ap->port_no);
233331961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ
2334bdd4dddee325a7dce3e84cf48201a06aa8508aa4Jeff Garzik	mv_phy_reset(ap, class, deadline);
2335bdd4dddee325a7dce3e84cf48201a06aa8508aa4Jeff Garzik
2336bdd4dddee325a7dce3e84cf48201a06aa8508aa4Jeff Garzik	return 0;
2337bdd4dddee325a7dce3e84cf48201a06aa8508aa4Jeff Garzik}
2338bdd4dddee325a7dce3e84cf48201a06aa8508aa4Jeff Garzik
2339cc0680a580b5be81a1ca321b58f8e9b80b5c1052Tejun Heostatic void mv_postreset(struct ata_link *link, unsigned int *classes)
2340bdd4dddee325a7dce3e84cf48201a06aa8508aa4Jeff Garzik{
2341cc0680a580b5be81a1ca321b58f8e9b80b5c1052Tejun Heo	struct ata_port *ap = link->ap;
2342bdd4dddee325a7dce3e84cf48201a06aa8508aa4Jeff Garzik	u32 serr;
2343bdd4dddee325a7dce3e84cf48201a06aa8508aa4Jeff Garzik
2344bdd4dddee325a7dce3e84cf48201a06aa8508aa4Jeff Garzik	/* print link status */
2345cc0680a580b5be81a1ca321b58f8e9b80b5c1052Tejun Heo	sata_print_link_status(link);
234631961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ
2347bdd4dddee325a7dce3e84cf48201a06aa8508aa4Jeff Garzik	/* clear SError */
2348cc0680a580b5be81a1ca321b58f8e9b80b5c1052Tejun Heo	sata_scr_read(link, SCR_ERROR, &serr);
2349cc0680a580b5be81a1ca321b58f8e9b80b5c1052Tejun Heo	sata_scr_write_flush(link, SCR_ERROR, serr);
2350bdd4dddee325a7dce3e84cf48201a06aa8508aa4Jeff Garzik
2351bdd4dddee325a7dce3e84cf48201a06aa8508aa4Jeff Garzik	/* bail out if no device is present */
2352bdd4dddee325a7dce3e84cf48201a06aa8508aa4Jeff Garzik	if (classes[0] == ATA_DEV_NONE && classes[1] == ATA_DEV_NONE) {
2353bdd4dddee325a7dce3e84cf48201a06aa8508aa4Jeff Garzik		DPRINTK("EXIT, no device\n");
2354bdd4dddee325a7dce3e84cf48201a06aa8508aa4Jeff Garzik		return;
23559b358e305c1d783c8a4ebf00344e95deb9e38f3dMark Lord	}
2356bdd4dddee325a7dce3e84cf48201a06aa8508aa4Jeff Garzik
2357bdd4dddee325a7dce3e84cf48201a06aa8508aa4Jeff Garzik	/* set up device control */
2358bdd4dddee325a7dce3e84cf48201a06aa8508aa4Jeff Garzik	iowrite8(ap->ctl, ap->ioaddr.ctl_addr);
2359bdd4dddee325a7dce3e84cf48201a06aa8508aa4Jeff Garzik}
2360bdd4dddee325a7dce3e84cf48201a06aa8508aa4Jeff Garzik
2361bdd4dddee325a7dce3e84cf48201a06aa8508aa4Jeff Garzikstatic void mv_error_handler(struct ata_port *ap)
2362bdd4dddee325a7dce3e84cf48201a06aa8508aa4Jeff Garzik{
2363bdd4dddee325a7dce3e84cf48201a06aa8508aa4Jeff Garzik	ata_do_eh(ap, mv_prereset, ata_std_softreset,
2364bdd4dddee325a7dce3e84cf48201a06aa8508aa4Jeff Garzik		  mv_hardreset, mv_postreset);
2365bdd4dddee325a7dce3e84cf48201a06aa8508aa4Jeff Garzik}
2366bdd4dddee325a7dce3e84cf48201a06aa8508aa4Jeff Garzik
2367bdd4dddee325a7dce3e84cf48201a06aa8508aa4Jeff Garzikstatic void mv_post_int_cmd(struct ata_queued_cmd *qc)
2368bdd4dddee325a7dce3e84cf48201a06aa8508aa4Jeff Garzik{
2369bdd4dddee325a7dce3e84cf48201a06aa8508aa4Jeff Garzik	mv_stop_dma(qc->ap);
2370bdd4dddee325a7dce3e84cf48201a06aa8508aa4Jeff Garzik}
2371bdd4dddee325a7dce3e84cf48201a06aa8508aa4Jeff Garzik
2372bdd4dddee325a7dce3e84cf48201a06aa8508aa4Jeff Garzikstatic void mv_eh_freeze(struct ata_port *ap)
2373bdd4dddee325a7dce3e84cf48201a06aa8508aa4Jeff Garzik{
2374bdd4dddee325a7dce3e84cf48201a06aa8508aa4Jeff Garzik	void __iomem *mmio = ap->host->iomap[MV_PRIMARY_BAR];
2375bdd4dddee325a7dce3e84cf48201a06aa8508aa4Jeff Garzik	unsigned int hc = (ap->port_no > 3) ? 1 : 0;
2376bdd4dddee325a7dce3e84cf48201a06aa8508aa4Jeff Garzik	u32 tmp, mask;
2377bdd4dddee325a7dce3e84cf48201a06aa8508aa4Jeff Garzik	unsigned int shift;
2378bdd4dddee325a7dce3e84cf48201a06aa8508aa4Jeff Garzik
2379bdd4dddee325a7dce3e84cf48201a06aa8508aa4Jeff Garzik	/* FIXME: handle coalescing completion events properly */
2380bdd4dddee325a7dce3e84cf48201a06aa8508aa4Jeff Garzik
2381bdd4dddee325a7dce3e84cf48201a06aa8508aa4Jeff Garzik	shift = ap->port_no * 2;
2382bdd4dddee325a7dce3e84cf48201a06aa8508aa4Jeff Garzik	if (hc > 0)
2383bdd4dddee325a7dce3e84cf48201a06aa8508aa4Jeff Garzik		shift++;
2384bdd4dddee325a7dce3e84cf48201a06aa8508aa4Jeff Garzik
2385bdd4dddee325a7dce3e84cf48201a06aa8508aa4Jeff Garzik	mask = 0x3 << shift;
2386bdd4dddee325a7dce3e84cf48201a06aa8508aa4Jeff Garzik
2387bdd4dddee325a7dce3e84cf48201a06aa8508aa4Jeff Garzik	/* disable assertion of portN err, done events */
2388bdd4dddee325a7dce3e84cf48201a06aa8508aa4Jeff Garzik	tmp = readl(mmio + HC_MAIN_IRQ_MASK_OFS);
2389bdd4dddee325a7dce3e84cf48201a06aa8508aa4Jeff Garzik	writelfl(tmp & ~mask, mmio + HC_MAIN_IRQ_MASK_OFS);
2390bdd4dddee325a7dce3e84cf48201a06aa8508aa4Jeff Garzik}
2391bdd4dddee325a7dce3e84cf48201a06aa8508aa4Jeff Garzik
2392bdd4dddee325a7dce3e84cf48201a06aa8508aa4Jeff Garzikstatic void mv_eh_thaw(struct ata_port *ap)
2393bdd4dddee325a7dce3e84cf48201a06aa8508aa4Jeff Garzik{
2394bdd4dddee325a7dce3e84cf48201a06aa8508aa4Jeff Garzik	void __iomem *mmio = ap->host->iomap[MV_PRIMARY_BAR];
2395bdd4dddee325a7dce3e84cf48201a06aa8508aa4Jeff Garzik	unsigned int hc = (ap->port_no > 3) ? 1 : 0;
2396bdd4dddee325a7dce3e84cf48201a06aa8508aa4Jeff Garzik	void __iomem *hc_mmio = mv_hc_base(mmio, hc);
2397bdd4dddee325a7dce3e84cf48201a06aa8508aa4Jeff Garzik	void __iomem *port_mmio = mv_ap_base(ap);
2398bdd4dddee325a7dce3e84cf48201a06aa8508aa4Jeff Garzik	u32 tmp, mask, hc_irq_cause;
2399bdd4dddee325a7dce3e84cf48201a06aa8508aa4Jeff Garzik	unsigned int shift, hc_port_no = ap->port_no;
2400bdd4dddee325a7dce3e84cf48201a06aa8508aa4Jeff Garzik
2401bdd4dddee325a7dce3e84cf48201a06aa8508aa4Jeff Garzik	/* FIXME: handle coalescing completion events properly */
2402bdd4dddee325a7dce3e84cf48201a06aa8508aa4Jeff Garzik
2403bdd4dddee325a7dce3e84cf48201a06aa8508aa4Jeff Garzik	shift = ap->port_no * 2;
2404bdd4dddee325a7dce3e84cf48201a06aa8508aa4Jeff Garzik	if (hc > 0) {
2405bdd4dddee325a7dce3e84cf48201a06aa8508aa4Jeff Garzik		shift++;
2406bdd4dddee325a7dce3e84cf48201a06aa8508aa4Jeff Garzik		hc_port_no -= 4;
2407bdd4dddee325a7dce3e84cf48201a06aa8508aa4Jeff Garzik	}
2408bdd4dddee325a7dce3e84cf48201a06aa8508aa4Jeff Garzik
2409bdd4dddee325a7dce3e84cf48201a06aa8508aa4Jeff Garzik	mask = 0x3 << shift;
2410bdd4dddee325a7dce3e84cf48201a06aa8508aa4Jeff Garzik
2411bdd4dddee325a7dce3e84cf48201a06aa8508aa4Jeff Garzik	/* clear EDMA errors on this port */
2412bdd4dddee325a7dce3e84cf48201a06aa8508aa4Jeff Garzik	writel(0, port_mmio + EDMA_ERR_IRQ_CAUSE_OFS);
2413bdd4dddee325a7dce3e84cf48201a06aa8508aa4Jeff Garzik
2414bdd4dddee325a7dce3e84cf48201a06aa8508aa4Jeff Garzik	/* clear pending irq events */
2415bdd4dddee325a7dce3e84cf48201a06aa8508aa4Jeff Garzik	hc_irq_cause = readl(hc_mmio + HC_IRQ_CAUSE_OFS);
2416bdd4dddee325a7dce3e84cf48201a06aa8508aa4Jeff Garzik	hc_irq_cause &= ~(1 << hc_port_no);	/* clear CRPB-done */
2417bdd4dddee325a7dce3e84cf48201a06aa8508aa4Jeff Garzik	hc_irq_cause &= ~(1 << (hc_port_no + 8)); /* clear Device int */
2418bdd4dddee325a7dce3e84cf48201a06aa8508aa4Jeff Garzik	writel(hc_irq_cause, hc_mmio + HC_IRQ_CAUSE_OFS);
2419bdd4dddee325a7dce3e84cf48201a06aa8508aa4Jeff Garzik
2420bdd4dddee325a7dce3e84cf48201a06aa8508aa4Jeff Garzik	/* enable assertion of portN err, done events */
2421bdd4dddee325a7dce3e84cf48201a06aa8508aa4Jeff Garzik	tmp = readl(mmio + HC_MAIN_IRQ_MASK_OFS);
2422bdd4dddee325a7dce3e84cf48201a06aa8508aa4Jeff Garzik	writelfl(tmp | mask, mmio + HC_MAIN_IRQ_MASK_OFS);
242331961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ}
242431961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ
242505b308e1df6d9d673daedb517969241f41278b52Brett Russ/**
242605b308e1df6d9d673daedb517969241f41278b52Brett Russ *      mv_port_init - Perform some early initialization on a single port.
242705b308e1df6d9d673daedb517969241f41278b52Brett Russ *      @port: libata data structure storing shadow register addresses
242805b308e1df6d9d673daedb517969241f41278b52Brett Russ *      @port_mmio: base address of the port
242905b308e1df6d9d673daedb517969241f41278b52Brett Russ *
243005b308e1df6d9d673daedb517969241f41278b52Brett Russ *      Initialize shadow register mmio addresses, clear outstanding
243105b308e1df6d9d673daedb517969241f41278b52Brett Russ *      interrupts on the port, and unmask interrupts for the future
243205b308e1df6d9d673daedb517969241f41278b52Brett Russ *      start of the port.
243305b308e1df6d9d673daedb517969241f41278b52Brett Russ *
243405b308e1df6d9d673daedb517969241f41278b52Brett Russ *      LOCKING:
243505b308e1df6d9d673daedb517969241f41278b52Brett Russ *      Inherited from caller.
243605b308e1df6d9d673daedb517969241f41278b52Brett Russ */
243731961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russstatic void mv_port_init(struct ata_ioports *port,  void __iomem *port_mmio)
243820f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ{
24390d5ff566779f894ca9937231a181eb31e4adff0eTejun Heo	void __iomem *shd_base = port_mmio + SHD_BLK_OFS;
244031961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ	unsigned serr_ofs;
244131961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ
24428b260248d9e0e8b64bb72fd4dee03ad86984c344Jeff Garzik	/* PIO related setup
244331961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ	 */
244431961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ	port->data_addr = shd_base + (sizeof(u32) * ATA_REG_DATA);
24458b260248d9e0e8b64bb72fd4dee03ad86984c344Jeff Garzik	port->error_addr =
244631961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ		port->feature_addr = shd_base + (sizeof(u32) * ATA_REG_ERR);
244731961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ	port->nsect_addr = shd_base + (sizeof(u32) * ATA_REG_NSECT);
244831961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ	port->lbal_addr = shd_base + (sizeof(u32) * ATA_REG_LBAL);
244931961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ	port->lbam_addr = shd_base + (sizeof(u32) * ATA_REG_LBAM);
245031961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ	port->lbah_addr = shd_base + (sizeof(u32) * ATA_REG_LBAH);
245131961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ	port->device_addr = shd_base + (sizeof(u32) * ATA_REG_DEVICE);
24528b260248d9e0e8b64bb72fd4dee03ad86984c344Jeff Garzik	port->status_addr =
245331961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ		port->command_addr = shd_base + (sizeof(u32) * ATA_REG_STATUS);
245431961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ	/* special case: control/altstatus doesn't have ATA_REG_ address */
245531961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ	port->altstatus_addr = port->ctl_addr = shd_base + SHD_CTL_AST_OFS;
245631961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ
245731961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ	/* unused: */
24588d9db2d2fbae9e05022825c32f86e00c8e342860Randy Dunlap	port->cmd_addr = port->bmdma_addr = port->scr_addr = NULL;
245920f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ
246031961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ	/* Clear any currently outstanding port interrupt conditions */
246131961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ	serr_ofs = mv_scr_offset(SCR_ERROR);
246231961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ	writelfl(readl(port_mmio + serr_ofs), port_mmio + serr_ofs);
246331961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ	writelfl(0, port_mmio + EDMA_ERR_IRQ_CAUSE_OFS);
246431961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ
2465646a4da514f2555298481cb00dc5b3eb02b21b72Mark Lord	/* unmask all non-transient EDMA error interrupts */
2466646a4da514f2555298481cb00dc5b3eb02b21b72Mark Lord	writelfl(~EDMA_ERR_IRQ_TRANSIENT, port_mmio + EDMA_ERR_IRQ_MASK_OFS);
246720f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ
24688b260248d9e0e8b64bb72fd4dee03ad86984c344Jeff Garzik	VPRINTK("EDMA cfg=0x%08x EDMA IRQ err cause/mask=0x%08x/0x%08x\n",
246931961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ		readl(port_mmio + EDMA_CFG_OFS),
247031961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ		readl(port_mmio + EDMA_ERR_IRQ_CAUSE_OFS),
247131961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ		readl(port_mmio + EDMA_ERR_IRQ_MASK_OFS));
247220f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ}
247320f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ
24744447d35156169cf136e829eb6b5cac2d6370f2d9Tejun Heostatic int mv_chip_id(struct ata_host *host, unsigned int board_idx)
2475bca1c4eb9411533d613123618c0d127fae532595Jeff Garzik{
24764447d35156169cf136e829eb6b5cac2d6370f2d9Tejun Heo	struct pci_dev *pdev = to_pci_dev(host->dev);
24774447d35156169cf136e829eb6b5cac2d6370f2d9Tejun Heo	struct mv_host_priv *hpriv = host->private_data;
2478bca1c4eb9411533d613123618c0d127fae532595Jeff Garzik	u32 hp_flags = hpriv->hp_flags;
2479bca1c4eb9411533d613123618c0d127fae532595Jeff Garzik
24805796d1c4c89efff823259fda35b08ea66ebf8b23Jeff Garzik	switch (board_idx) {
248147c2b677daeed9c79ecb7167c211ff36876ea611Jeff Garzik	case chip_5080:
248247c2b677daeed9c79ecb7167c211ff36876ea611Jeff Garzik		hpriv->ops = &mv5xxx_ops;
2483ee9ccdf70163ca6408f6965e0fbc65baeac7312cJeff Garzik		hp_flags |= MV_HP_GEN_I;
248447c2b677daeed9c79ecb7167c211ff36876ea611Jeff Garzik
248544c10138fd4bbc4b6d6bff0873c24902f2a9da65Auke Kok		switch (pdev->revision) {
248647c2b677daeed9c79ecb7167c211ff36876ea611Jeff Garzik		case 0x1:
248747c2b677daeed9c79ecb7167c211ff36876ea611Jeff Garzik			hp_flags |= MV_HP_ERRATA_50XXB0;
248847c2b677daeed9c79ecb7167c211ff36876ea611Jeff Garzik			break;
248947c2b677daeed9c79ecb7167c211ff36876ea611Jeff Garzik		case 0x3:
249047c2b677daeed9c79ecb7167c211ff36876ea611Jeff Garzik			hp_flags |= MV_HP_ERRATA_50XXB2;
249147c2b677daeed9c79ecb7167c211ff36876ea611Jeff Garzik			break;
249247c2b677daeed9c79ecb7167c211ff36876ea611Jeff Garzik		default:
249347c2b677daeed9c79ecb7167c211ff36876ea611Jeff Garzik			dev_printk(KERN_WARNING, &pdev->dev,
249447c2b677daeed9c79ecb7167c211ff36876ea611Jeff Garzik			   "Applying 50XXB2 workarounds to unknown rev\n");
249547c2b677daeed9c79ecb7167c211ff36876ea611Jeff Garzik			hp_flags |= MV_HP_ERRATA_50XXB2;
249647c2b677daeed9c79ecb7167c211ff36876ea611Jeff Garzik			break;
249747c2b677daeed9c79ecb7167c211ff36876ea611Jeff Garzik		}
249847c2b677daeed9c79ecb7167c211ff36876ea611Jeff Garzik		break;
249947c2b677daeed9c79ecb7167c211ff36876ea611Jeff Garzik
2500bca1c4eb9411533d613123618c0d127fae532595Jeff Garzik	case chip_504x:
2501bca1c4eb9411533d613123618c0d127fae532595Jeff Garzik	case chip_508x:
250247c2b677daeed9c79ecb7167c211ff36876ea611Jeff Garzik		hpriv->ops = &mv5xxx_ops;
2503ee9ccdf70163ca6408f6965e0fbc65baeac7312cJeff Garzik		hp_flags |= MV_HP_GEN_I;
2504bca1c4eb9411533d613123618c0d127fae532595Jeff Garzik
250544c10138fd4bbc4b6d6bff0873c24902f2a9da65Auke Kok		switch (pdev->revision) {
250647c2b677daeed9c79ecb7167c211ff36876ea611Jeff Garzik		case 0x0:
250747c2b677daeed9c79ecb7167c211ff36876ea611Jeff Garzik			hp_flags |= MV_HP_ERRATA_50XXB0;
250847c2b677daeed9c79ecb7167c211ff36876ea611Jeff Garzik			break;
250947c2b677daeed9c79ecb7167c211ff36876ea611Jeff Garzik		case 0x3:
251047c2b677daeed9c79ecb7167c211ff36876ea611Jeff Garzik			hp_flags |= MV_HP_ERRATA_50XXB2;
251147c2b677daeed9c79ecb7167c211ff36876ea611Jeff Garzik			break;
251247c2b677daeed9c79ecb7167c211ff36876ea611Jeff Garzik		default:
251347c2b677daeed9c79ecb7167c211ff36876ea611Jeff Garzik			dev_printk(KERN_WARNING, &pdev->dev,
251447c2b677daeed9c79ecb7167c211ff36876ea611Jeff Garzik			   "Applying B2 workarounds to unknown rev\n");
251547c2b677daeed9c79ecb7167c211ff36876ea611Jeff Garzik			hp_flags |= MV_HP_ERRATA_50XXB2;
251647c2b677daeed9c79ecb7167c211ff36876ea611Jeff Garzik			break;
2517bca1c4eb9411533d613123618c0d127fae532595Jeff Garzik		}
2518bca1c4eb9411533d613123618c0d127fae532595Jeff Garzik		break;
2519bca1c4eb9411533d613123618c0d127fae532595Jeff Garzik
2520bca1c4eb9411533d613123618c0d127fae532595Jeff Garzik	case chip_604x:
2521bca1c4eb9411533d613123618c0d127fae532595Jeff Garzik	case chip_608x:
252247c2b677daeed9c79ecb7167c211ff36876ea611Jeff Garzik		hpriv->ops = &mv6xxx_ops;
2523ee9ccdf70163ca6408f6965e0fbc65baeac7312cJeff Garzik		hp_flags |= MV_HP_GEN_II;
252447c2b677daeed9c79ecb7167c211ff36876ea611Jeff Garzik
252544c10138fd4bbc4b6d6bff0873c24902f2a9da65Auke Kok		switch (pdev->revision) {
252647c2b677daeed9c79ecb7167c211ff36876ea611Jeff Garzik		case 0x7:
252747c2b677daeed9c79ecb7167c211ff36876ea611Jeff Garzik			hp_flags |= MV_HP_ERRATA_60X1B2;
252847c2b677daeed9c79ecb7167c211ff36876ea611Jeff Garzik			break;
252947c2b677daeed9c79ecb7167c211ff36876ea611Jeff Garzik		case 0x9:
253047c2b677daeed9c79ecb7167c211ff36876ea611Jeff Garzik			hp_flags |= MV_HP_ERRATA_60X1C0;
2531bca1c4eb9411533d613123618c0d127fae532595Jeff Garzik			break;
2532bca1c4eb9411533d613123618c0d127fae532595Jeff Garzik		default:
2533bca1c4eb9411533d613123618c0d127fae532595Jeff Garzik			dev_printk(KERN_WARNING, &pdev->dev,
253447c2b677daeed9c79ecb7167c211ff36876ea611Jeff Garzik				   "Applying B2 workarounds to unknown rev\n");
253547c2b677daeed9c79ecb7167c211ff36876ea611Jeff Garzik			hp_flags |= MV_HP_ERRATA_60X1B2;
2536bca1c4eb9411533d613123618c0d127fae532595Jeff Garzik			break;
2537bca1c4eb9411533d613123618c0d127fae532595Jeff Garzik		}
2538bca1c4eb9411533d613123618c0d127fae532595Jeff Garzik		break;
2539bca1c4eb9411533d613123618c0d127fae532595Jeff Garzik
2540e4e7b89280d1d666e2c09e5ad36cf071796c4c7eJeff Garzik	case chip_7042:
254102a121da5a53d415b6596bc19cc6999d295d32a4Mark Lord		hp_flags |= MV_HP_PCIE;
2542306b30f74d37f289033c696285e07ce0158a5d7bMark Lord		if (pdev->vendor == PCI_VENDOR_ID_TTI &&
2543306b30f74d37f289033c696285e07ce0158a5d7bMark Lord		    (pdev->device == 0x2300 || pdev->device == 0x2310))
2544306b30f74d37f289033c696285e07ce0158a5d7bMark Lord		{
25454e5200334e03e5620aa19d538300c13db270a063Mark Lord			/*
25464e5200334e03e5620aa19d538300c13db270a063Mark Lord			 * Highpoint RocketRAID PCIe 23xx series cards:
25474e5200334e03e5620aa19d538300c13db270a063Mark Lord			 *
25484e5200334e03e5620aa19d538300c13db270a063Mark Lord			 * Unconfigured drives are treated as "Legacy"
25494e5200334e03e5620aa19d538300c13db270a063Mark Lord			 * by the BIOS, and it overwrites sector 8 with
25504e5200334e03e5620aa19d538300c13db270a063Mark Lord			 * a "Lgcy" metadata block prior to Linux boot.
25514e5200334e03e5620aa19d538300c13db270a063Mark Lord			 *
25524e5200334e03e5620aa19d538300c13db270a063Mark Lord			 * Configured drives (RAID or JBOD) leave sector 8
25534e5200334e03e5620aa19d538300c13db270a063Mark Lord			 * alone, but instead overwrite a high numbered
25544e5200334e03e5620aa19d538300c13db270a063Mark Lord			 * sector for the RAID metadata.  This sector can
25554e5200334e03e5620aa19d538300c13db270a063Mark Lord			 * be determined exactly, by truncating the physical
25564e5200334e03e5620aa19d538300c13db270a063Mark Lord			 * drive capacity to a nice even GB value.
25574e5200334e03e5620aa19d538300c13db270a063Mark Lord			 *
25584e5200334e03e5620aa19d538300c13db270a063Mark Lord			 * RAID metadata is at: (dev->n_sectors & ~0xfffff)
25594e5200334e03e5620aa19d538300c13db270a063Mark Lord			 *
25604e5200334e03e5620aa19d538300c13db270a063Mark Lord			 * Warn the user, lest they think we're just buggy.
25614e5200334e03e5620aa19d538300c13db270a063Mark Lord			 */
25624e5200334e03e5620aa19d538300c13db270a063Mark Lord			printk(KERN_WARNING DRV_NAME ": Highpoint RocketRAID"
25634e5200334e03e5620aa19d538300c13db270a063Mark Lord				" BIOS CORRUPTS DATA on all attached drives,"
25644e5200334e03e5620aa19d538300c13db270a063Mark Lord				" regardless of if/how they are configured."
25654e5200334e03e5620aa19d538300c13db270a063Mark Lord				" BEWARE!\n");
25664e5200334e03e5620aa19d538300c13db270a063Mark Lord			printk(KERN_WARNING DRV_NAME ": For data safety, do not"
25674e5200334e03e5620aa19d538300c13db270a063Mark Lord				" use sectors 8-9 on \"Legacy\" drives,"
25684e5200334e03e5620aa19d538300c13db270a063Mark Lord				" and avoid the final two gigabytes on"
25694e5200334e03e5620aa19d538300c13db270a063Mark Lord				" all RocketRAID BIOS initialized drives.\n");
2570306b30f74d37f289033c696285e07ce0158a5d7bMark Lord		}
2571e4e7b89280d1d666e2c09e5ad36cf071796c4c7eJeff Garzik	case chip_6042:
2572e4e7b89280d1d666e2c09e5ad36cf071796c4c7eJeff Garzik		hpriv->ops = &mv6xxx_ops;
2573e4e7b89280d1d666e2c09e5ad36cf071796c4c7eJeff Garzik		hp_flags |= MV_HP_GEN_IIE;
2574e4e7b89280d1d666e2c09e5ad36cf071796c4c7eJeff Garzik
257544c10138fd4bbc4b6d6bff0873c24902f2a9da65Auke Kok		switch (pdev->revision) {
2576e4e7b89280d1d666e2c09e5ad36cf071796c4c7eJeff Garzik		case 0x0:
2577e4e7b89280d1d666e2c09e5ad36cf071796c4c7eJeff Garzik			hp_flags |= MV_HP_ERRATA_XX42A0;
2578e4e7b89280d1d666e2c09e5ad36cf071796c4c7eJeff Garzik			break;
2579e4e7b89280d1d666e2c09e5ad36cf071796c4c7eJeff Garzik		case 0x1:
2580e4e7b89280d1d666e2c09e5ad36cf071796c4c7eJeff Garzik			hp_flags |= MV_HP_ERRATA_60X1C0;
2581e4e7b89280d1d666e2c09e5ad36cf071796c4c7eJeff Garzik			break;
2582e4e7b89280d1d666e2c09e5ad36cf071796c4c7eJeff Garzik		default:
2583e4e7b89280d1d666e2c09e5ad36cf071796c4c7eJeff Garzik			dev_printk(KERN_WARNING, &pdev->dev,
2584e4e7b89280d1d666e2c09e5ad36cf071796c4c7eJeff Garzik			   "Applying 60X1C0 workarounds to unknown rev\n");
2585e4e7b89280d1d666e2c09e5ad36cf071796c4c7eJeff Garzik			hp_flags |= MV_HP_ERRATA_60X1C0;
2586e4e7b89280d1d666e2c09e5ad36cf071796c4c7eJeff Garzik			break;
2587e4e7b89280d1d666e2c09e5ad36cf071796c4c7eJeff Garzik		}
2588e4e7b89280d1d666e2c09e5ad36cf071796c4c7eJeff Garzik		break;
2589e4e7b89280d1d666e2c09e5ad36cf071796c4c7eJeff Garzik
2590bca1c4eb9411533d613123618c0d127fae532595Jeff Garzik	default:
25915796d1c4c89efff823259fda35b08ea66ebf8b23Jeff Garzik		dev_printk(KERN_ERR, &pdev->dev,
25925796d1c4c89efff823259fda35b08ea66ebf8b23Jeff Garzik			   "BUG: invalid board index %u\n", board_idx);
2593bca1c4eb9411533d613123618c0d127fae532595Jeff Garzik		return 1;
2594bca1c4eb9411533d613123618c0d127fae532595Jeff Garzik	}
2595bca1c4eb9411533d613123618c0d127fae532595Jeff Garzik
2596bca1c4eb9411533d613123618c0d127fae532595Jeff Garzik	hpriv->hp_flags = hp_flags;
259702a121da5a53d415b6596bc19cc6999d295d32a4Mark Lord	if (hp_flags & MV_HP_PCIE) {
259802a121da5a53d415b6596bc19cc6999d295d32a4Mark Lord		hpriv->irq_cause_ofs	= PCIE_IRQ_CAUSE_OFS;
259902a121da5a53d415b6596bc19cc6999d295d32a4Mark Lord		hpriv->irq_mask_ofs	= PCIE_IRQ_MASK_OFS;
260002a121da5a53d415b6596bc19cc6999d295d32a4Mark Lord		hpriv->unmask_all_irqs	= PCIE_UNMASK_ALL_IRQS;
260102a121da5a53d415b6596bc19cc6999d295d32a4Mark Lord	} else {
260202a121da5a53d415b6596bc19cc6999d295d32a4Mark Lord		hpriv->irq_cause_ofs	= PCI_IRQ_CAUSE_OFS;
260302a121da5a53d415b6596bc19cc6999d295d32a4Mark Lord		hpriv->irq_mask_ofs	= PCI_IRQ_MASK_OFS;
260402a121da5a53d415b6596bc19cc6999d295d32a4Mark Lord		hpriv->unmask_all_irqs	= PCI_UNMASK_ALL_IRQS;
260502a121da5a53d415b6596bc19cc6999d295d32a4Mark Lord	}
2606bca1c4eb9411533d613123618c0d127fae532595Jeff Garzik
2607bca1c4eb9411533d613123618c0d127fae532595Jeff Garzik	return 0;
2608bca1c4eb9411533d613123618c0d127fae532595Jeff Garzik}
2609bca1c4eb9411533d613123618c0d127fae532595Jeff Garzik
261005b308e1df6d9d673daedb517969241f41278b52Brett Russ/**
261147c2b677daeed9c79ecb7167c211ff36876ea611Jeff Garzik *      mv_init_host - Perform some early initialization of the host.
26124447d35156169cf136e829eb6b5cac2d6370f2d9Tejun Heo *	@host: ATA host to initialize
26134447d35156169cf136e829eb6b5cac2d6370f2d9Tejun Heo *      @board_idx: controller index
261405b308e1df6d9d673daedb517969241f41278b52Brett Russ *
261505b308e1df6d9d673daedb517969241f41278b52Brett Russ *      If possible, do an early global reset of the host.  Then do
261605b308e1df6d9d673daedb517969241f41278b52Brett Russ *      our port init and clear/unmask all/relevant host interrupts.
261705b308e1df6d9d673daedb517969241f41278b52Brett Russ *
261805b308e1df6d9d673daedb517969241f41278b52Brett Russ *      LOCKING:
261905b308e1df6d9d673daedb517969241f41278b52Brett Russ *      Inherited from caller.
262005b308e1df6d9d673daedb517969241f41278b52Brett Russ */
26214447d35156169cf136e829eb6b5cac2d6370f2d9Tejun Heostatic int mv_init_host(struct ata_host *host, unsigned int board_idx)
262220f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ{
262320f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ	int rc = 0, n_hc, port, hc;
26244447d35156169cf136e829eb6b5cac2d6370f2d9Tejun Heo	struct pci_dev *pdev = to_pci_dev(host->dev);
26254447d35156169cf136e829eb6b5cac2d6370f2d9Tejun Heo	void __iomem *mmio = host->iomap[MV_PRIMARY_BAR];
26264447d35156169cf136e829eb6b5cac2d6370f2d9Tejun Heo	struct mv_host_priv *hpriv = host->private_data;
2627bca1c4eb9411533d613123618c0d127fae532595Jeff Garzik
262847c2b677daeed9c79ecb7167c211ff36876ea611Jeff Garzik	/* global interrupt mask */
262947c2b677daeed9c79ecb7167c211ff36876ea611Jeff Garzik	writel(0, mmio + HC_MAIN_IRQ_MASK_OFS);
263047c2b677daeed9c79ecb7167c211ff36876ea611Jeff Garzik
26314447d35156169cf136e829eb6b5cac2d6370f2d9Tejun Heo	rc = mv_chip_id(host, board_idx);
2632bca1c4eb9411533d613123618c0d127fae532595Jeff Garzik	if (rc)
2633bca1c4eb9411533d613123618c0d127fae532595Jeff Garzik		goto done;
2634bca1c4eb9411533d613123618c0d127fae532595Jeff Garzik
26354447d35156169cf136e829eb6b5cac2d6370f2d9Tejun Heo	n_hc = mv_get_hc_count(host->ports[0]->flags);
2636bca1c4eb9411533d613123618c0d127fae532595Jeff Garzik
26374447d35156169cf136e829eb6b5cac2d6370f2d9Tejun Heo	for (port = 0; port < host->n_ports; port++)
263847c2b677daeed9c79ecb7167c211ff36876ea611Jeff Garzik		hpriv->ops->read_preamp(hpriv, port, mmio);
263920f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ
2640c9d39130123238ac18478a42e25cb7996eacfcc0Jeff Garzik	rc = hpriv->ops->reset_hc(hpriv, mmio, n_hc);
264147c2b677daeed9c79ecb7167c211ff36876ea611Jeff Garzik	if (rc)
264220f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ		goto done;
264320f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ
2644522479fb98c6667f081e75f87e298e413c0b1db8Jeff Garzik	hpriv->ops->reset_flash(hpriv, mmio);
2645522479fb98c6667f081e75f87e298e413c0b1db8Jeff Garzik	hpriv->ops->reset_bus(pdev, mmio);
264647c2b677daeed9c79ecb7167c211ff36876ea611Jeff Garzik	hpriv->ops->enable_leds(hpriv, mmio);
264720f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ
26484447d35156169cf136e829eb6b5cac2d6370f2d9Tejun Heo	for (port = 0; port < host->n_ports; port++) {
2649ee9ccdf70163ca6408f6965e0fbc65baeac7312cJeff Garzik		if (IS_GEN_II(hpriv)) {
2650c9d39130123238ac18478a42e25cb7996eacfcc0Jeff Garzik			void __iomem *port_mmio = mv_port_base(mmio, port);
2651c9d39130123238ac18478a42e25cb7996eacfcc0Jeff Garzik
26522a47ce06d534692f9bd2bf4e90a20fc9b1054c39Jeff Garzik			u32 ifctl = readl(port_mmio + SATA_INTERFACE_CTL);
2653eb46d684600ac145501805a294c94675e82eab2eMark Lord			ifctl |= (1 << 7);		/* enable gen2i speed */
2654eb46d684600ac145501805a294c94675e82eab2eMark Lord			ifctl = (ifctl & 0xfff) | 0x9b1000; /* from chip spec */
26552a47ce06d534692f9bd2bf4e90a20fc9b1054c39Jeff Garzik			writelfl(ifctl, port_mmio + SATA_INTERFACE_CTL);
26562a47ce06d534692f9bd2bf4e90a20fc9b1054c39Jeff Garzik		}
26572a47ce06d534692f9bd2bf4e90a20fc9b1054c39Jeff Garzik
2658c9d39130123238ac18478a42e25cb7996eacfcc0Jeff Garzik		hpriv->ops->phy_errata(hpriv, mmio, port);
26592a47ce06d534692f9bd2bf4e90a20fc9b1054c39Jeff Garzik	}
26602a47ce06d534692f9bd2bf4e90a20fc9b1054c39Jeff Garzik
26614447d35156169cf136e829eb6b5cac2d6370f2d9Tejun Heo	for (port = 0; port < host->n_ports; port++) {
2662cbcdd87593a1d85c5c4b259945a3a09eee12814dTejun Heo		struct ata_port *ap = host->ports[port];
26632a47ce06d534692f9bd2bf4e90a20fc9b1054c39Jeff Garzik		void __iomem *port_mmio = mv_port_base(mmio, port);
2664cbcdd87593a1d85c5c4b259945a3a09eee12814dTejun Heo		unsigned int offset = port_mmio - mmio;
2665cbcdd87593a1d85c5c4b259945a3a09eee12814dTejun Heo
2666cbcdd87593a1d85c5c4b259945a3a09eee12814dTejun Heo		mv_port_init(&ap->ioaddr, port_mmio);
2667cbcdd87593a1d85c5c4b259945a3a09eee12814dTejun Heo
2668cbcdd87593a1d85c5c4b259945a3a09eee12814dTejun Heo		ata_port_pbar_desc(ap, MV_PRIMARY_BAR, -1, "mmio");
2669cbcdd87593a1d85c5c4b259945a3a09eee12814dTejun Heo		ata_port_pbar_desc(ap, MV_PRIMARY_BAR, offset, "port");
267020f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ	}
267120f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ
267220f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ	for (hc = 0; hc < n_hc; hc++) {
267331961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ		void __iomem *hc_mmio = mv_hc_base(mmio, hc);
267431961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ
267531961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ		VPRINTK("HC%i: HC config=0x%08x HC IRQ cause "
267631961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ			"(before clear)=0x%08x\n", hc,
267731961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ			readl(hc_mmio + HC_CFG_OFS),
267831961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ			readl(hc_mmio + HC_IRQ_CAUSE_OFS));
267931961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ
268031961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ		/* Clear any currently outstanding hc interrupt conditions */
268131961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ		writelfl(0, hc_mmio + HC_IRQ_CAUSE_OFS);
268220f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ	}
268320f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ
268431961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ	/* Clear any currently outstanding host interrupt conditions */
268502a121da5a53d415b6596bc19cc6999d295d32a4Mark Lord	writelfl(0, mmio + hpriv->irq_cause_ofs);
268631961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ
268731961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ	/* and unmask interrupt generation for host regs */
268802a121da5a53d415b6596bc19cc6999d295d32a4Mark Lord	writelfl(hpriv->unmask_all_irqs, mmio + hpriv->irq_mask_ofs);
2689fb621e2fde735abab854586d52c96c5624bcb5b8Jeff Garzik
2690ee9ccdf70163ca6408f6965e0fbc65baeac7312cJeff Garzik	if (IS_GEN_I(hpriv))
2691fb621e2fde735abab854586d52c96c5624bcb5b8Jeff Garzik		writelfl(~HC_MAIN_MASKED_IRQS_5, mmio + HC_MAIN_IRQ_MASK_OFS);
2692fb621e2fde735abab854586d52c96c5624bcb5b8Jeff Garzik	else
2693fb621e2fde735abab854586d52c96c5624bcb5b8Jeff Garzik		writelfl(~HC_MAIN_MASKED_IRQS, mmio + HC_MAIN_IRQ_MASK_OFS);
269420f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ
269520f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ	VPRINTK("HC MAIN IRQ cause/mask=0x%08x/0x%08x "
26968b260248d9e0e8b64bb72fd4dee03ad86984c344Jeff Garzik		"PCI int cause/mask=0x%08x/0x%08x\n",
269720f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ		readl(mmio + HC_MAIN_IRQ_CAUSE_OFS),
269820f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ		readl(mmio + HC_MAIN_IRQ_MASK_OFS),
269902a121da5a53d415b6596bc19cc6999d295d32a4Mark Lord		readl(mmio + hpriv->irq_cause_ofs),
270002a121da5a53d415b6596bc19cc6999d295d32a4Mark Lord		readl(mmio + hpriv->irq_mask_ofs));
2701bca1c4eb9411533d613123618c0d127fae532595Jeff Garzik
270231961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russdone:
270320f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ	return rc;
270420f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ}
270520f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ
270605b308e1df6d9d673daedb517969241f41278b52Brett Russ/**
270705b308e1df6d9d673daedb517969241f41278b52Brett Russ *      mv_print_info - Dump key info to kernel log for perusal.
27084447d35156169cf136e829eb6b5cac2d6370f2d9Tejun Heo *      @host: ATA host to print info about
270905b308e1df6d9d673daedb517969241f41278b52Brett Russ *
271005b308e1df6d9d673daedb517969241f41278b52Brett Russ *      FIXME: complete this.
271105b308e1df6d9d673daedb517969241f41278b52Brett Russ *
271205b308e1df6d9d673daedb517969241f41278b52Brett Russ *      LOCKING:
271305b308e1df6d9d673daedb517969241f41278b52Brett Russ *      Inherited from caller.
271405b308e1df6d9d673daedb517969241f41278b52Brett Russ */
27154447d35156169cf136e829eb6b5cac2d6370f2d9Tejun Heostatic void mv_print_info(struct ata_host *host)
271631961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ{
27174447d35156169cf136e829eb6b5cac2d6370f2d9Tejun Heo	struct pci_dev *pdev = to_pci_dev(host->dev);
27184447d35156169cf136e829eb6b5cac2d6370f2d9Tejun Heo	struct mv_host_priv *hpriv = host->private_data;
271944c10138fd4bbc4b6d6bff0873c24902f2a9da65Auke Kok	u8 scc;
2720c1e4fe711a410a139095e6b3e3ce3f07f466063cJeff Garzik	const char *scc_s, *gen;
272131961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ
272231961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ	/* Use this to determine the HW stepping of the chip so we know
272331961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ	 * what errata to workaround
272431961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ	 */
272531961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ	pci_read_config_byte(pdev, PCI_CLASS_DEVICE, &scc);
272631961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ	if (scc == 0)
272731961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ		scc_s = "SCSI";
272831961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ	else if (scc == 0x01)
272931961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ		scc_s = "RAID";
273031961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ	else
2731c1e4fe711a410a139095e6b3e3ce3f07f466063cJeff Garzik		scc_s = "?";
2732c1e4fe711a410a139095e6b3e3ce3f07f466063cJeff Garzik
2733c1e4fe711a410a139095e6b3e3ce3f07f466063cJeff Garzik	if (IS_GEN_I(hpriv))
2734c1e4fe711a410a139095e6b3e3ce3f07f466063cJeff Garzik		gen = "I";
2735c1e4fe711a410a139095e6b3e3ce3f07f466063cJeff Garzik	else if (IS_GEN_II(hpriv))
2736c1e4fe711a410a139095e6b3e3ce3f07f466063cJeff Garzik		gen = "II";
2737c1e4fe711a410a139095e6b3e3ce3f07f466063cJeff Garzik	else if (IS_GEN_IIE(hpriv))
2738c1e4fe711a410a139095e6b3e3ce3f07f466063cJeff Garzik		gen = "IIE";
2739c1e4fe711a410a139095e6b3e3ce3f07f466063cJeff Garzik	else
2740c1e4fe711a410a139095e6b3e3ce3f07f466063cJeff Garzik		gen = "?";
274131961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ
2742a9524a76f70f3343e4be27f95a7e92a8ba5f9009Jeff Garzik	dev_printk(KERN_INFO, &pdev->dev,
2743c1e4fe711a410a139095e6b3e3ce3f07f466063cJeff Garzik	       "Gen-%s %u slots %u ports %s mode IRQ via %s\n",
2744c1e4fe711a410a139095e6b3e3ce3f07f466063cJeff Garzik	       gen, (unsigned)MV_MAX_Q_DEPTH, host->n_ports,
274531961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ	       scc_s, (MV_HP_FLAG_MSI & hpriv->hp_flags) ? "MSI" : "INTx");
274631961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ}
274731961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ
274805b308e1df6d9d673daedb517969241f41278b52Brett Russ/**
274905b308e1df6d9d673daedb517969241f41278b52Brett Russ *      mv_init_one - handle a positive probe of a Marvell host
275005b308e1df6d9d673daedb517969241f41278b52Brett Russ *      @pdev: PCI device found
275105b308e1df6d9d673daedb517969241f41278b52Brett Russ *      @ent: PCI device ID entry for the matched host
275205b308e1df6d9d673daedb517969241f41278b52Brett Russ *
275305b308e1df6d9d673daedb517969241f41278b52Brett Russ *      LOCKING:
275405b308e1df6d9d673daedb517969241f41278b52Brett Russ *      Inherited from caller.
275505b308e1df6d9d673daedb517969241f41278b52Brett Russ */
275620f733e7d75a16bffc34842b7682c9247dd5f954Brett Russstatic int mv_init_one(struct pci_dev *pdev, const struct pci_device_id *ent)
275720f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ{
27582dcb407e61458ded17503d6bd12b8c064965368bJeff Garzik	static int printed_version;
275920f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ	unsigned int board_idx = (unsigned int)ent->driver_data;
27604447d35156169cf136e829eb6b5cac2d6370f2d9Tejun Heo	const struct ata_port_info *ppi[] = { &mv_port_info[board_idx], NULL };
27614447d35156169cf136e829eb6b5cac2d6370f2d9Tejun Heo	struct ata_host *host;
27624447d35156169cf136e829eb6b5cac2d6370f2d9Tejun Heo	struct mv_host_priv *hpriv;
27634447d35156169cf136e829eb6b5cac2d6370f2d9Tejun Heo	int n_ports, rc;
276420f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ
2765a9524a76f70f3343e4be27f95a7e92a8ba5f9009Jeff Garzik	if (!printed_version++)
2766a9524a76f70f3343e4be27f95a7e92a8ba5f9009Jeff Garzik		dev_printk(KERN_INFO, &pdev->dev, "version " DRV_VERSION "\n");
276720f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ
27684447d35156169cf136e829eb6b5cac2d6370f2d9Tejun Heo	/* allocate host */
27694447d35156169cf136e829eb6b5cac2d6370f2d9Tejun Heo	n_ports = mv_get_hc_count(ppi[0]->flags) * MV_PORTS_PER_HC;
27704447d35156169cf136e829eb6b5cac2d6370f2d9Tejun Heo
27714447d35156169cf136e829eb6b5cac2d6370f2d9Tejun Heo	host = ata_host_alloc_pinfo(&pdev->dev, ppi, n_ports);
27724447d35156169cf136e829eb6b5cac2d6370f2d9Tejun Heo	hpriv = devm_kzalloc(&pdev->dev, sizeof(*hpriv), GFP_KERNEL);
27734447d35156169cf136e829eb6b5cac2d6370f2d9Tejun Heo	if (!host || !hpriv)
27744447d35156169cf136e829eb6b5cac2d6370f2d9Tejun Heo		return -ENOMEM;
27754447d35156169cf136e829eb6b5cac2d6370f2d9Tejun Heo	host->private_data = hpriv;
27764447d35156169cf136e829eb6b5cac2d6370f2d9Tejun Heo
27774447d35156169cf136e829eb6b5cac2d6370f2d9Tejun Heo	/* acquire resources */
277824dc5f33ea4b504cfbd23fa159a4cacba8e4d800Tejun Heo	rc = pcim_enable_device(pdev);
277924dc5f33ea4b504cfbd23fa159a4cacba8e4d800Tejun Heo	if (rc)
278020f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ		return rc;
278120f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ
27820d5ff566779f894ca9937231a181eb31e4adff0eTejun Heo	rc = pcim_iomap_regions(pdev, 1 << MV_PRIMARY_BAR, DRV_NAME);
27830d5ff566779f894ca9937231a181eb31e4adff0eTejun Heo	if (rc == -EBUSY)
278424dc5f33ea4b504cfbd23fa159a4cacba8e4d800Tejun Heo		pcim_pin_device(pdev);
27850d5ff566779f894ca9937231a181eb31e4adff0eTejun Heo	if (rc)
278624dc5f33ea4b504cfbd23fa159a4cacba8e4d800Tejun Heo		return rc;
27874447d35156169cf136e829eb6b5cac2d6370f2d9Tejun Heo	host->iomap = pcim_iomap_table(pdev);
278820f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ
2789d88184fb2348a50f7c34f5d49a901c875b2e0114Jeff Garzik	rc = pci_go_64(pdev);
2790d88184fb2348a50f7c34f5d49a901c875b2e0114Jeff Garzik	if (rc)
2791d88184fb2348a50f7c34f5d49a901c875b2e0114Jeff Garzik		return rc;
2792d88184fb2348a50f7c34f5d49a901c875b2e0114Jeff Garzik
279320f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ	/* initialize adapter */
27944447d35156169cf136e829eb6b5cac2d6370f2d9Tejun Heo	rc = mv_init_host(host, board_idx);
279524dc5f33ea4b504cfbd23fa159a4cacba8e4d800Tejun Heo	if (rc)
279624dc5f33ea4b504cfbd23fa159a4cacba8e4d800Tejun Heo		return rc;
279720f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ
279831961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ	/* Enable interrupts */
27996a59dcf8678cbc4106a8a6e158d7408a87691358Tejun Heo	if (msi && pci_enable_msi(pdev))
280031961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ		pci_intx(pdev, 1);
280120f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ
280231961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ	mv_dump_pci_cfg(pdev, 0x68);
28034447d35156169cf136e829eb6b5cac2d6370f2d9Tejun Heo	mv_print_info(host);
280420f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ
28054447d35156169cf136e829eb6b5cac2d6370f2d9Tejun Heo	pci_set_master(pdev);
2806ea8b4db97aa41a66c05daa4055a1974692ccd52dJeff Garzik	pci_try_set_mwi(pdev);
28074447d35156169cf136e829eb6b5cac2d6370f2d9Tejun Heo	return ata_host_activate(host, pdev->irq, mv_interrupt, IRQF_SHARED,
2808c5d3e45a2200a0905dc45b72714726b7aac3aaf1Jeff Garzik				 IS_GEN_I(hpriv) ? &mv5_sht : &mv6_sht);
280920f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ}
281020f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ
281120f733e7d75a16bffc34842b7682c9247dd5f954Brett Russstatic int __init mv_init(void)
281220f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ{
2813b7887196e38da54ff893897b80875d632d1a1114Pavel Roskin	return pci_register_driver(&mv_pci_driver);
281420f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ}
281520f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ
281620f733e7d75a16bffc34842b7682c9247dd5f954Brett Russstatic void __exit mv_exit(void)
281720f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ{
281820f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ	pci_unregister_driver(&mv_pci_driver);
281920f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ}
282020f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ
282120f733e7d75a16bffc34842b7682c9247dd5f954Brett RussMODULE_AUTHOR("Brett Russ");
282220f733e7d75a16bffc34842b7682c9247dd5f954Brett RussMODULE_DESCRIPTION("SCSI low-level driver for Marvell SATA controllers");
282320f733e7d75a16bffc34842b7682c9247dd5f954Brett RussMODULE_LICENSE("GPL");
282420f733e7d75a16bffc34842b7682c9247dd5f954Brett RussMODULE_DEVICE_TABLE(pci, mv_pci_tbl);
282520f733e7d75a16bffc34842b7682c9247dd5f954Brett RussMODULE_VERSION(DRV_VERSION);
282620f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ
2827ddef9bb367b19383df627e388cb4c01c86ddba6cJeff Garzikmodule_param(msi, int, 0444);
2828ddef9bb367b19383df627e388cb4c01c86ddba6cJeff GarzikMODULE_PARM_DESC(msi, "Enable use of PCI MSI (0=off, 1=on)");
2829ddef9bb367b19383df627e388cb4c01c86ddba6cJeff Garzik
283020f733e7d75a16bffc34842b7682c9247dd5f954Brett Russmodule_init(mv_init);
283120f733e7d75a16bffc34842b7682c9247dd5f954Brett Russmodule_exit(mv_exit);
2832