sata_mv.c revision eb73d558d1c1c931de0b3a86af962c77d74ef688
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	 * ePRD (SG) entries need alignment on a 16B boundary. Size == 16B
11131961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ	 */
11231961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ	MV_CRQB_Q_SZ		= (32 * MV_MAX_Q_DEPTH),
11331961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ	MV_CRPB_Q_SZ		= (8 * MV_MAX_Q_DEPTH),
114da2fa9baf06f33a8fa7aa3f56c9f2b4070ceca0eMark Lord	MV_MAX_SG_CT		= 256,
11531961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ	MV_SG_TBL_SZ		= (16 * MV_MAX_SG_CT),
11631961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ
11720f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ	MV_PORTS_PER_HC		= 4,
11820f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ	/* == (port / MV_PORTS_PER_HC) to determine HC from 0-7 port */
11920f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ	MV_PORT_HC_SHIFT	= 2,
12031961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ	/* == (port % MV_PORTS_PER_HC) to determine hard port from 0-7 port */
12120f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ	MV_PORT_MASK		= 3,
12220f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ
12320f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ	/* Host Flags */
12420f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ	MV_FLAG_DUAL_HC		= (1 << 30),  /* two SATA Host Controllers */
12520f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ	MV_FLAG_IRQ_COALESCE	= (1 << 29),  /* IRQ coalescing capability */
126c5d3e45a2200a0905dc45b72714726b7aac3aaf1Jeff Garzik	MV_COMMON_FLAGS		= ATA_FLAG_SATA | ATA_FLAG_NO_LEGACY |
127bdd4dddee325a7dce3e84cf48201a06aa8508aa4Jeff Garzik				  ATA_FLAG_MMIO | ATA_FLAG_NO_ATAPI |
128bdd4dddee325a7dce3e84cf48201a06aa8508aa4Jeff Garzik				  ATA_FLAG_PIO_POLLING,
12947c2b677daeed9c79ecb7167c211ff36876ea611Jeff Garzik	MV_6XXX_FLAGS		= MV_FLAG_IRQ_COALESCE,
13020f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ
13131961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ	CRQB_FLAG_READ		= (1 << 0),
13231961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ	CRQB_TAG_SHIFT		= 1,
133c5d3e45a2200a0905dc45b72714726b7aac3aaf1Jeff Garzik	CRQB_IOID_SHIFT		= 6,	/* CRQB Gen-II/IIE IO Id shift */
134c5d3e45a2200a0905dc45b72714726b7aac3aaf1Jeff Garzik	CRQB_HOSTQ_SHIFT	= 17,	/* CRQB Gen-II/IIE HostQueTag shift */
13531961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ	CRQB_CMD_ADDR_SHIFT	= 8,
13631961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ	CRQB_CMD_CS		= (0x2 << 11),
13731961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ	CRQB_CMD_LAST		= (1 << 15),
13831961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ
13931961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ	CRPB_FLAG_STATUS_SHIFT	= 8,
140c5d3e45a2200a0905dc45b72714726b7aac3aaf1Jeff Garzik	CRPB_IOID_SHIFT_6	= 5,	/* CRPB Gen-II IO Id shift */
141c5d3e45a2200a0905dc45b72714726b7aac3aaf1Jeff Garzik	CRPB_IOID_SHIFT_7	= 7,	/* CRPB Gen-IIE IO Id shift */
14231961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ
14331961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ	EPRD_FLAG_END_OF_TBL	= (1 << 31),
14431961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ
14520f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ	/* PCI interface registers */
14620f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ
14731961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ	PCI_COMMAND_OFS		= 0xc00,
14831961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ
14920f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ	PCI_MAIN_CMD_STS_OFS	= 0xd30,
15020f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ	STOP_PCI_MASTER		= (1 << 2),
15120f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ	PCI_MASTER_EMPTY	= (1 << 3),
15220f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ	GLOB_SFT_RST		= (1 << 4),
15320f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ
154522479fb98c6667f081e75f87e298e413c0b1db8Jeff Garzik	MV_PCI_MODE		= 0xd00,
155522479fb98c6667f081e75f87e298e413c0b1db8Jeff Garzik	MV_PCI_EXP_ROM_BAR_CTL	= 0xd2c,
156522479fb98c6667f081e75f87e298e413c0b1db8Jeff Garzik	MV_PCI_DISC_TIMER	= 0xd04,
157522479fb98c6667f081e75f87e298e413c0b1db8Jeff Garzik	MV_PCI_MSI_TRIGGER	= 0xc38,
158522479fb98c6667f081e75f87e298e413c0b1db8Jeff Garzik	MV_PCI_SERR_MASK	= 0xc28,
159522479fb98c6667f081e75f87e298e413c0b1db8Jeff Garzik	MV_PCI_XBAR_TMOUT	= 0x1d04,
160522479fb98c6667f081e75f87e298e413c0b1db8Jeff Garzik	MV_PCI_ERR_LOW_ADDRESS	= 0x1d40,
161522479fb98c6667f081e75f87e298e413c0b1db8Jeff Garzik	MV_PCI_ERR_HIGH_ADDRESS	= 0x1d44,
162522479fb98c6667f081e75f87e298e413c0b1db8Jeff Garzik	MV_PCI_ERR_ATTRIBUTE	= 0x1d48,
163522479fb98c6667f081e75f87e298e413c0b1db8Jeff Garzik	MV_PCI_ERR_COMMAND	= 0x1d50,
164522479fb98c6667f081e75f87e298e413c0b1db8Jeff Garzik
16502a121da5a53d415b6596bc19cc6999d295d32a4Mark Lord	PCI_IRQ_CAUSE_OFS	= 0x1d58,
16602a121da5a53d415b6596bc19cc6999d295d32a4Mark Lord	PCI_IRQ_MASK_OFS	= 0x1d5c,
16720f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ	PCI_UNMASK_ALL_IRQS	= 0x7fffff,	/* bits 22-0 */
16820f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ
16902a121da5a53d415b6596bc19cc6999d295d32a4Mark Lord	PCIE_IRQ_CAUSE_OFS	= 0x1900,
17002a121da5a53d415b6596bc19cc6999d295d32a4Mark Lord	PCIE_IRQ_MASK_OFS	= 0x1910,
171646a4da514f2555298481cb00dc5b3eb02b21b72Mark Lord	PCIE_UNMASK_ALL_IRQS	= 0x40a,	/* assorted bits */
17202a121da5a53d415b6596bc19cc6999d295d32a4Mark Lord
17320f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ	HC_MAIN_IRQ_CAUSE_OFS	= 0x1d60,
17420f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ	HC_MAIN_IRQ_MASK_OFS	= 0x1d64,
17520f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ	PORT0_ERR		= (1 << 0),	/* shift by port # */
17620f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ	PORT0_DONE		= (1 << 1),	/* shift by port # */
17720f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ	HC0_IRQ_PEND		= 0x1ff,	/* bits 0-8 = HC0's ports */
17820f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ	HC_SHIFT		= 9,		/* bits 9-17 = HC1's ports */
17920f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ	PCI_ERR			= (1 << 18),
18020f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ	TRAN_LO_DONE		= (1 << 19),	/* 6xxx: IRQ coalescing */
18120f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ	TRAN_HI_DONE		= (1 << 20),	/* 6xxx: IRQ coalescing */
182fb621e2fde735abab854586d52c96c5624bcb5b8Jeff Garzik	PORTS_0_3_COAL_DONE	= (1 << 8),
183fb621e2fde735abab854586d52c96c5624bcb5b8Jeff Garzik	PORTS_4_7_COAL_DONE	= (1 << 17),
18420f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ	PORTS_0_7_COAL_DONE	= (1 << 21),	/* 6xxx: IRQ coalescing */
18520f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ	GPIO_INT		= (1 << 22),
18620f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ	SELF_INT		= (1 << 23),
18720f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ	TWSI_INT		= (1 << 24),
18820f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ	HC_MAIN_RSVD		= (0x7f << 25),	/* bits 31-25 */
189fb621e2fde735abab854586d52c96c5624bcb5b8Jeff Garzik	HC_MAIN_RSVD_5		= (0x1fff << 19), /* bits 31-19 */
1908b260248d9e0e8b64bb72fd4dee03ad86984c344Jeff Garzik	HC_MAIN_MASKED_IRQS	= (TRAN_LO_DONE | TRAN_HI_DONE |
19120f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ				   PORTS_0_7_COAL_DONE | GPIO_INT | TWSI_INT |
19220f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ				   HC_MAIN_RSVD),
193fb621e2fde735abab854586d52c96c5624bcb5b8Jeff Garzik	HC_MAIN_MASKED_IRQS_5	= (PORTS_0_3_COAL_DONE | PORTS_4_7_COAL_DONE |
194fb621e2fde735abab854586d52c96c5624bcb5b8Jeff Garzik				   HC_MAIN_RSVD_5),
19520f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ
19620f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ	/* SATAHC registers */
19720f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ	HC_CFG_OFS		= 0,
19820f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ
19920f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ	HC_IRQ_CAUSE_OFS	= 0x14,
20031961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ	CRPB_DMA_DONE		= (1 << 0),	/* shift by port # */
20120f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ	HC_IRQ_COAL		= (1 << 4),	/* IRQ coalescing */
20220f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ	DEV_IRQ			= (1 << 8),	/* shift by port # */
20320f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ
20420f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ	/* Shadow block registers */
20531961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ	SHD_BLK_OFS		= 0x100,
20631961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ	SHD_CTL_AST_OFS		= 0x20,		/* ofs from SHD_BLK_OFS */
20720f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ
20820f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ	/* SATA registers */
20920f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ	SATA_STATUS_OFS		= 0x300,  /* ctrl, err regs follow status */
21020f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ	SATA_ACTIVE_OFS		= 0x350,
2110c58912e192fc3a4835d772aafa40b72552b819fMark Lord	SATA_FIS_IRQ_CAUSE_OFS	= 0x364,
21247c2b677daeed9c79ecb7167c211ff36876ea611Jeff Garzik	PHY_MODE3		= 0x310,
213bca1c4eb9411533d613123618c0d127fae532595Jeff Garzik	PHY_MODE4		= 0x314,
214bca1c4eb9411533d613123618c0d127fae532595Jeff Garzik	PHY_MODE2		= 0x330,
215c9d39130123238ac18478a42e25cb7996eacfcc0Jeff Garzik	MV5_PHY_MODE		= 0x74,
216c9d39130123238ac18478a42e25cb7996eacfcc0Jeff Garzik	MV5_LT_MODE		= 0x30,
217c9d39130123238ac18478a42e25cb7996eacfcc0Jeff Garzik	MV5_PHY_CTL		= 0x0C,
218bca1c4eb9411533d613123618c0d127fae532595Jeff Garzik	SATA_INTERFACE_CTL	= 0x050,
219bca1c4eb9411533d613123618c0d127fae532595Jeff Garzik
220bca1c4eb9411533d613123618c0d127fae532595Jeff Garzik	MV_M2_PREAMP_MASK	= 0x7e0,
22120f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ
22220f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ	/* Port registers */
22320f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ	EDMA_CFG_OFS		= 0,
2240c58912e192fc3a4835d772aafa40b72552b819fMark Lord	EDMA_CFG_Q_DEPTH	= 0x1f,		/* max device queue depth */
2250c58912e192fc3a4835d772aafa40b72552b819fMark Lord	EDMA_CFG_NCQ		= (1 << 5),	/* for R/W FPDMA queued */
2260c58912e192fc3a4835d772aafa40b72552b819fMark Lord	EDMA_CFG_NCQ_GO_ON_ERR	= (1 << 14),	/* continue on error */
2270c58912e192fc3a4835d772aafa40b72552b819fMark Lord	EDMA_CFG_RD_BRST_EXT	= (1 << 11),	/* read burst 512B */
2280c58912e192fc3a4835d772aafa40b72552b819fMark Lord	EDMA_CFG_WR_BUFF_LEN	= (1 << 13),	/* write buffer 512B */
22920f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ
23020f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ	EDMA_ERR_IRQ_CAUSE_OFS	= 0x8,
23120f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ	EDMA_ERR_IRQ_MASK_OFS	= 0xc,
2326c1153e00af8de755ec278d873a97c9ce2a72d10Jeff Garzik	EDMA_ERR_D_PAR		= (1 << 0),	/* UDMA data parity err */
2336c1153e00af8de755ec278d873a97c9ce2a72d10Jeff Garzik	EDMA_ERR_PRD_PAR	= (1 << 1),	/* UDMA PRD parity err */
2346c1153e00af8de755ec278d873a97c9ce2a72d10Jeff Garzik	EDMA_ERR_DEV		= (1 << 2),	/* device error */
2356c1153e00af8de755ec278d873a97c9ce2a72d10Jeff Garzik	EDMA_ERR_DEV_DCON	= (1 << 3),	/* device disconnect */
2366c1153e00af8de755ec278d873a97c9ce2a72d10Jeff Garzik	EDMA_ERR_DEV_CON	= (1 << 4),	/* device connected */
2376c1153e00af8de755ec278d873a97c9ce2a72d10Jeff Garzik	EDMA_ERR_SERR		= (1 << 5),	/* SError bits [WBDST] raised */
238c5d3e45a2200a0905dc45b72714726b7aac3aaf1Jeff Garzik	EDMA_ERR_SELF_DIS	= (1 << 7),	/* Gen II/IIE self-disable */
239c5d3e45a2200a0905dc45b72714726b7aac3aaf1Jeff Garzik	EDMA_ERR_SELF_DIS_5	= (1 << 8),	/* Gen I self-disable */
2406c1153e00af8de755ec278d873a97c9ce2a72d10Jeff Garzik	EDMA_ERR_BIST_ASYNC	= (1 << 8),	/* BIST FIS or Async Notify */
241c5d3e45a2200a0905dc45b72714726b7aac3aaf1Jeff Garzik	EDMA_ERR_TRANS_IRQ_7	= (1 << 8),	/* Gen IIE transprt layer irq */
2426c1153e00af8de755ec278d873a97c9ce2a72d10Jeff Garzik	EDMA_ERR_CRQB_PAR	= (1 << 9),	/* CRQB parity error */
2436c1153e00af8de755ec278d873a97c9ce2a72d10Jeff Garzik	EDMA_ERR_CRPB_PAR	= (1 << 10),	/* CRPB parity error */
2446c1153e00af8de755ec278d873a97c9ce2a72d10Jeff Garzik	EDMA_ERR_INTRL_PAR	= (1 << 11),	/* internal parity error */
2456c1153e00af8de755ec278d873a97c9ce2a72d10Jeff Garzik	EDMA_ERR_IORDY		= (1 << 12),	/* IORdy timeout */
246646a4da514f2555298481cb00dc5b3eb02b21b72Mark Lord
2476c1153e00af8de755ec278d873a97c9ce2a72d10Jeff Garzik	EDMA_ERR_LNK_CTRL_RX	= (0xf << 13),	/* link ctrl rx error */
248646a4da514f2555298481cb00dc5b3eb02b21b72Mark Lord	EDMA_ERR_LNK_CTRL_RX_0	= (1 << 13),	/* transient: CRC err */
249646a4da514f2555298481cb00dc5b3eb02b21b72Mark Lord	EDMA_ERR_LNK_CTRL_RX_1	= (1 << 14),	/* transient: FIFO err */
250646a4da514f2555298481cb00dc5b3eb02b21b72Mark Lord	EDMA_ERR_LNK_CTRL_RX_2	= (1 << 15),	/* fatal: caught SYNC */
251646a4da514f2555298481cb00dc5b3eb02b21b72Mark Lord	EDMA_ERR_LNK_CTRL_RX_3	= (1 << 16),	/* transient: FIS rx err */
252646a4da514f2555298481cb00dc5b3eb02b21b72Mark Lord
2536c1153e00af8de755ec278d873a97c9ce2a72d10Jeff Garzik	EDMA_ERR_LNK_DATA_RX	= (0xf << 17),	/* link data rx error */
254646a4da514f2555298481cb00dc5b3eb02b21b72Mark Lord
2556c1153e00af8de755ec278d873a97c9ce2a72d10Jeff Garzik	EDMA_ERR_LNK_CTRL_TX	= (0x1f << 21),	/* link ctrl tx error */
256646a4da514f2555298481cb00dc5b3eb02b21b72Mark Lord	EDMA_ERR_LNK_CTRL_TX_0	= (1 << 21),	/* transient: CRC err */
257646a4da514f2555298481cb00dc5b3eb02b21b72Mark Lord	EDMA_ERR_LNK_CTRL_TX_1	= (1 << 22),	/* transient: FIFO err */
258646a4da514f2555298481cb00dc5b3eb02b21b72Mark Lord	EDMA_ERR_LNK_CTRL_TX_2	= (1 << 23),	/* transient: caught SYNC */
259646a4da514f2555298481cb00dc5b3eb02b21b72Mark Lord	EDMA_ERR_LNK_CTRL_TX_3	= (1 << 24),	/* transient: caught DMAT */
260646a4da514f2555298481cb00dc5b3eb02b21b72Mark Lord	EDMA_ERR_LNK_CTRL_TX_4	= (1 << 25),	/* transient: FIS collision */
261646a4da514f2555298481cb00dc5b3eb02b21b72Mark Lord
2626c1153e00af8de755ec278d873a97c9ce2a72d10Jeff Garzik	EDMA_ERR_LNK_DATA_TX	= (0x1f << 26),	/* link data tx error */
263646a4da514f2555298481cb00dc5b3eb02b21b72Mark Lord
2646c1153e00af8de755ec278d873a97c9ce2a72d10Jeff Garzik	EDMA_ERR_TRANS_PROTO	= (1 << 31),	/* transport protocol error */
265c5d3e45a2200a0905dc45b72714726b7aac3aaf1Jeff Garzik	EDMA_ERR_OVERRUN_5	= (1 << 5),
266c5d3e45a2200a0905dc45b72714726b7aac3aaf1Jeff Garzik	EDMA_ERR_UNDERRUN_5	= (1 << 6),
267646a4da514f2555298481cb00dc5b3eb02b21b72Mark Lord
268646a4da514f2555298481cb00dc5b3eb02b21b72Mark Lord	EDMA_ERR_IRQ_TRANSIENT  = EDMA_ERR_LNK_CTRL_RX_0 |
269646a4da514f2555298481cb00dc5b3eb02b21b72Mark Lord				  EDMA_ERR_LNK_CTRL_RX_1 |
270646a4da514f2555298481cb00dc5b3eb02b21b72Mark Lord				  EDMA_ERR_LNK_CTRL_RX_3 |
271646a4da514f2555298481cb00dc5b3eb02b21b72Mark Lord				  EDMA_ERR_LNK_CTRL_TX,
272646a4da514f2555298481cb00dc5b3eb02b21b72Mark Lord
273bdd4dddee325a7dce3e84cf48201a06aa8508aa4Jeff Garzik	EDMA_EH_FREEZE		= EDMA_ERR_D_PAR |
274bdd4dddee325a7dce3e84cf48201a06aa8508aa4Jeff Garzik				  EDMA_ERR_PRD_PAR |
275bdd4dddee325a7dce3e84cf48201a06aa8508aa4Jeff Garzik				  EDMA_ERR_DEV_DCON |
276bdd4dddee325a7dce3e84cf48201a06aa8508aa4Jeff Garzik				  EDMA_ERR_DEV_CON |
277bdd4dddee325a7dce3e84cf48201a06aa8508aa4Jeff Garzik				  EDMA_ERR_SERR |
278bdd4dddee325a7dce3e84cf48201a06aa8508aa4Jeff Garzik				  EDMA_ERR_SELF_DIS |
2796c1153e00af8de755ec278d873a97c9ce2a72d10Jeff Garzik				  EDMA_ERR_CRQB_PAR |
280bdd4dddee325a7dce3e84cf48201a06aa8508aa4Jeff Garzik				  EDMA_ERR_CRPB_PAR |
281bdd4dddee325a7dce3e84cf48201a06aa8508aa4Jeff Garzik				  EDMA_ERR_INTRL_PAR |
282bdd4dddee325a7dce3e84cf48201a06aa8508aa4Jeff Garzik				  EDMA_ERR_IORDY |
283bdd4dddee325a7dce3e84cf48201a06aa8508aa4Jeff Garzik				  EDMA_ERR_LNK_CTRL_RX_2 |
284bdd4dddee325a7dce3e84cf48201a06aa8508aa4Jeff Garzik				  EDMA_ERR_LNK_DATA_RX |
285bdd4dddee325a7dce3e84cf48201a06aa8508aa4Jeff Garzik				  EDMA_ERR_LNK_DATA_TX |
286bdd4dddee325a7dce3e84cf48201a06aa8508aa4Jeff Garzik				  EDMA_ERR_TRANS_PROTO,
287bdd4dddee325a7dce3e84cf48201a06aa8508aa4Jeff Garzik	EDMA_EH_FREEZE_5	= EDMA_ERR_D_PAR |
288bdd4dddee325a7dce3e84cf48201a06aa8508aa4Jeff Garzik				  EDMA_ERR_PRD_PAR |
289bdd4dddee325a7dce3e84cf48201a06aa8508aa4Jeff Garzik				  EDMA_ERR_DEV_DCON |
290bdd4dddee325a7dce3e84cf48201a06aa8508aa4Jeff Garzik				  EDMA_ERR_DEV_CON |
291bdd4dddee325a7dce3e84cf48201a06aa8508aa4Jeff Garzik				  EDMA_ERR_OVERRUN_5 |
292bdd4dddee325a7dce3e84cf48201a06aa8508aa4Jeff Garzik				  EDMA_ERR_UNDERRUN_5 |
293bdd4dddee325a7dce3e84cf48201a06aa8508aa4Jeff Garzik				  EDMA_ERR_SELF_DIS_5 |
2946c1153e00af8de755ec278d873a97c9ce2a72d10Jeff Garzik				  EDMA_ERR_CRQB_PAR |
295bdd4dddee325a7dce3e84cf48201a06aa8508aa4Jeff Garzik				  EDMA_ERR_CRPB_PAR |
296bdd4dddee325a7dce3e84cf48201a06aa8508aa4Jeff Garzik				  EDMA_ERR_INTRL_PAR |
297bdd4dddee325a7dce3e84cf48201a06aa8508aa4Jeff Garzik				  EDMA_ERR_IORDY,
29820f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ
29931961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ	EDMA_REQ_Q_BASE_HI_OFS	= 0x10,
30031961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ	EDMA_REQ_Q_IN_PTR_OFS	= 0x14,		/* also contains BASE_LO */
30131961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ
30231961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ	EDMA_REQ_Q_OUT_PTR_OFS	= 0x18,
30331961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ	EDMA_REQ_Q_PTR_SHIFT	= 5,
30431961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ
30531961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ	EDMA_RSP_Q_BASE_HI_OFS	= 0x1c,
30631961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ	EDMA_RSP_Q_IN_PTR_OFS	= 0x20,
30731961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ	EDMA_RSP_Q_OUT_PTR_OFS	= 0x24,		/* also contains BASE_LO */
30831961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ	EDMA_RSP_Q_PTR_SHIFT	= 3,
30931961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ
3100ea9e179f436f153fc19fdaef7abbc1e0da20762Jeff Garzik	EDMA_CMD_OFS		= 0x28,		/* EDMA command register */
3110ea9e179f436f153fc19fdaef7abbc1e0da20762Jeff Garzik	EDMA_EN			= (1 << 0),	/* enable EDMA */
3120ea9e179f436f153fc19fdaef7abbc1e0da20762Jeff Garzik	EDMA_DS			= (1 << 1),	/* disable EDMA; self-negated */
3130ea9e179f436f153fc19fdaef7abbc1e0da20762Jeff Garzik	ATA_RST			= (1 << 2),	/* reset trans/link/phy */
31420f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ
315c9d39130123238ac18478a42e25cb7996eacfcc0Jeff Garzik	EDMA_IORDY_TMOUT	= 0x34,
316bca1c4eb9411533d613123618c0d127fae532595Jeff Garzik	EDMA_ARB_CFG		= 0x38,
317bca1c4eb9411533d613123618c0d127fae532595Jeff Garzik
31831961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ	/* Host private flags (hp_flags) */
31931961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ	MV_HP_FLAG_MSI		= (1 << 0),
32047c2b677daeed9c79ecb7167c211ff36876ea611Jeff Garzik	MV_HP_ERRATA_50XXB0	= (1 << 1),
32147c2b677daeed9c79ecb7167c211ff36876ea611Jeff Garzik	MV_HP_ERRATA_50XXB2	= (1 << 2),
32247c2b677daeed9c79ecb7167c211ff36876ea611Jeff Garzik	MV_HP_ERRATA_60X1B2	= (1 << 3),
32347c2b677daeed9c79ecb7167c211ff36876ea611Jeff Garzik	MV_HP_ERRATA_60X1C0	= (1 << 4),
324e4e7b89280d1d666e2c09e5ad36cf071796c4c7eJeff Garzik	MV_HP_ERRATA_XX42A0	= (1 << 5),
3250ea9e179f436f153fc19fdaef7abbc1e0da20762Jeff Garzik	MV_HP_GEN_I		= (1 << 6),	/* Generation I: 50xx */
3260ea9e179f436f153fc19fdaef7abbc1e0da20762Jeff Garzik	MV_HP_GEN_II		= (1 << 7),	/* Generation II: 60xx */
3270ea9e179f436f153fc19fdaef7abbc1e0da20762Jeff Garzik	MV_HP_GEN_IIE		= (1 << 8),	/* Generation IIE: 6042/7042 */
32802a121da5a53d415b6596bc19cc6999d295d32a4Mark Lord	MV_HP_PCIE		= (1 << 9),	/* PCIe bus/regs: 7042 */
32920f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ
33031961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ	/* Port private flags (pp_flags) */
3310ea9e179f436f153fc19fdaef7abbc1e0da20762Jeff Garzik	MV_PP_FLAG_EDMA_EN	= (1 << 0),	/* is EDMA engine enabled? */
332721091685f853ba4e6c49f26f989db0b1a811250Mark Lord	MV_PP_FLAG_NCQ_EN	= (1 << 1),	/* is EDMA set up for NCQ? */
3330ea9e179f436f153fc19fdaef7abbc1e0da20762Jeff Garzik	MV_PP_FLAG_HAD_A_RESET	= (1 << 2),	/* 1st hard reset complete? */
33420f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ};
33520f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ
336ee9ccdf70163ca6408f6965e0fbc65baeac7312cJeff Garzik#define IS_GEN_I(hpriv) ((hpriv)->hp_flags & MV_HP_GEN_I)
337ee9ccdf70163ca6408f6965e0fbc65baeac7312cJeff Garzik#define IS_GEN_II(hpriv) ((hpriv)->hp_flags & MV_HP_GEN_II)
338e4e7b89280d1d666e2c09e5ad36cf071796c4c7eJeff Garzik#define IS_GEN_IIE(hpriv) ((hpriv)->hp_flags & MV_HP_GEN_IIE)
339bca1c4eb9411533d613123618c0d127fae532595Jeff Garzik
340095fec887eaa1c38d17c0c929a6733c744a9fa1fJeff Garzikenum {
341baf14aa14efcfdb5a74d5cf804691086c6bec743Jeff Garzik	/* DMA boundary 0xffff is required by the s/g splitting
342baf14aa14efcfdb5a74d5cf804691086c6bec743Jeff Garzik	 * we need on /length/ in mv_fill-sg().
343baf14aa14efcfdb5a74d5cf804691086c6bec743Jeff Garzik	 */
344baf14aa14efcfdb5a74d5cf804691086c6bec743Jeff Garzik	MV_DMA_BOUNDARY		= 0xffffU,
345095fec887eaa1c38d17c0c929a6733c744a9fa1fJeff Garzik
3460ea9e179f436f153fc19fdaef7abbc1e0da20762Jeff Garzik	/* mask of register bits containing lower 32 bits
3470ea9e179f436f153fc19fdaef7abbc1e0da20762Jeff Garzik	 * of EDMA request queue DMA address
3480ea9e179f436f153fc19fdaef7abbc1e0da20762Jeff Garzik	 */
349095fec887eaa1c38d17c0c929a6733c744a9fa1fJeff Garzik	EDMA_REQ_Q_BASE_LO_MASK	= 0xfffffc00U,
350095fec887eaa1c38d17c0c929a6733c744a9fa1fJeff Garzik
3510ea9e179f436f153fc19fdaef7abbc1e0da20762Jeff Garzik	/* ditto, for response queue */
352095fec887eaa1c38d17c0c929a6733c744a9fa1fJeff Garzik	EDMA_RSP_Q_BASE_LO_MASK	= 0xffffff00U,
353095fec887eaa1c38d17c0c929a6733c744a9fa1fJeff Garzik};
354095fec887eaa1c38d17c0c929a6733c744a9fa1fJeff Garzik
355522479fb98c6667f081e75f87e298e413c0b1db8Jeff Garzikenum chip_type {
356522479fb98c6667f081e75f87e298e413c0b1db8Jeff Garzik	chip_504x,
357522479fb98c6667f081e75f87e298e413c0b1db8Jeff Garzik	chip_508x,
358522479fb98c6667f081e75f87e298e413c0b1db8Jeff Garzik	chip_5080,
359522479fb98c6667f081e75f87e298e413c0b1db8Jeff Garzik	chip_604x,
360522479fb98c6667f081e75f87e298e413c0b1db8Jeff Garzik	chip_608x,
361e4e7b89280d1d666e2c09e5ad36cf071796c4c7eJeff Garzik	chip_6042,
362e4e7b89280d1d666e2c09e5ad36cf071796c4c7eJeff Garzik	chip_7042,
363522479fb98c6667f081e75f87e298e413c0b1db8Jeff Garzik};
364522479fb98c6667f081e75f87e298e413c0b1db8Jeff Garzik
36531961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ/* Command ReQuest Block: 32B */
36631961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russstruct mv_crqb {
367e14698745dd0de1ddbf5cd0cca4313a90f8c1cc1Mark Lord	__le32			sg_addr;
368e14698745dd0de1ddbf5cd0cca4313a90f8c1cc1Mark Lord	__le32			sg_addr_hi;
369e14698745dd0de1ddbf5cd0cca4313a90f8c1cc1Mark Lord	__le16			ctrl_flags;
370e14698745dd0de1ddbf5cd0cca4313a90f8c1cc1Mark Lord	__le16			ata_cmd[11];
37131961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ};
37220f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ
373e4e7b89280d1d666e2c09e5ad36cf071796c4c7eJeff Garzikstruct mv_crqb_iie {
374e14698745dd0de1ddbf5cd0cca4313a90f8c1cc1Mark Lord	__le32			addr;
375e14698745dd0de1ddbf5cd0cca4313a90f8c1cc1Mark Lord	__le32			addr_hi;
376e14698745dd0de1ddbf5cd0cca4313a90f8c1cc1Mark Lord	__le32			flags;
377e14698745dd0de1ddbf5cd0cca4313a90f8c1cc1Mark Lord	__le32			len;
378e14698745dd0de1ddbf5cd0cca4313a90f8c1cc1Mark Lord	__le32			ata_cmd[4];
379e4e7b89280d1d666e2c09e5ad36cf071796c4c7eJeff Garzik};
380e4e7b89280d1d666e2c09e5ad36cf071796c4c7eJeff Garzik
38131961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ/* Command ResPonse Block: 8B */
38231961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russstruct mv_crpb {
383e14698745dd0de1ddbf5cd0cca4313a90f8c1cc1Mark Lord	__le16			id;
384e14698745dd0de1ddbf5cd0cca4313a90f8c1cc1Mark Lord	__le16			flags;
385e14698745dd0de1ddbf5cd0cca4313a90f8c1cc1Mark Lord	__le32			tmstmp;
38620f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ};
38720f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ
38831961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ/* EDMA Physical Region Descriptor (ePRD); A.K.A. SG */
38931961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russstruct mv_sg {
390e14698745dd0de1ddbf5cd0cca4313a90f8c1cc1Mark Lord	__le32			addr;
391e14698745dd0de1ddbf5cd0cca4313a90f8c1cc1Mark Lord	__le32			flags_size;
392e14698745dd0de1ddbf5cd0cca4313a90f8c1cc1Mark Lord	__le32			addr_hi;
393e14698745dd0de1ddbf5cd0cca4313a90f8c1cc1Mark Lord	__le32			reserved;
39431961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ};
39520f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ
39631961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russstruct mv_port_priv {
39731961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ	struct mv_crqb		*crqb;
39831961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ	dma_addr_t		crqb_dma;
39931961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ	struct mv_crpb		*crpb;
40031961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ	dma_addr_t		crpb_dma;
401eb73d558d1c1c931de0b3a86af962c77d74ef688Mark Lord	struct mv_sg		*sg_tbl[MV_MAX_Q_DEPTH];
402eb73d558d1c1c931de0b3a86af962c77d74ef688Mark Lord	dma_addr_t		sg_tbl_dma[MV_MAX_Q_DEPTH];
403bdd4dddee325a7dce3e84cf48201a06aa8508aa4Jeff Garzik
404bdd4dddee325a7dce3e84cf48201a06aa8508aa4Jeff Garzik	unsigned int		req_idx;
405bdd4dddee325a7dce3e84cf48201a06aa8508aa4Jeff Garzik	unsigned int		resp_idx;
406bdd4dddee325a7dce3e84cf48201a06aa8508aa4Jeff Garzik
40731961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ	u32			pp_flags;
40831961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ};
40931961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ
410bca1c4eb9411533d613123618c0d127fae532595Jeff Garzikstruct mv_port_signal {
411bca1c4eb9411533d613123618c0d127fae532595Jeff Garzik	u32			amps;
412bca1c4eb9411533d613123618c0d127fae532595Jeff Garzik	u32			pre;
413bca1c4eb9411533d613123618c0d127fae532595Jeff Garzik};
414bca1c4eb9411533d613123618c0d127fae532595Jeff Garzik
41502a121da5a53d415b6596bc19cc6999d295d32a4Mark Lordstruct mv_host_priv {
41602a121da5a53d415b6596bc19cc6999d295d32a4Mark Lord	u32			hp_flags;
41702a121da5a53d415b6596bc19cc6999d295d32a4Mark Lord	struct mv_port_signal	signal[8];
41802a121da5a53d415b6596bc19cc6999d295d32a4Mark Lord	const struct mv_hw_ops	*ops;
41902a121da5a53d415b6596bc19cc6999d295d32a4Mark Lord	u32			irq_cause_ofs;
42002a121da5a53d415b6596bc19cc6999d295d32a4Mark Lord	u32			irq_mask_ofs;
42102a121da5a53d415b6596bc19cc6999d295d32a4Mark Lord	u32			unmask_all_irqs;
422da2fa9baf06f33a8fa7aa3f56c9f2b4070ceca0eMark Lord	/*
423da2fa9baf06f33a8fa7aa3f56c9f2b4070ceca0eMark Lord	 * These consistent DMA memory pools give us guaranteed
424da2fa9baf06f33a8fa7aa3f56c9f2b4070ceca0eMark Lord	 * alignment for hardware-accessed data structures,
425da2fa9baf06f33a8fa7aa3f56c9f2b4070ceca0eMark Lord	 * and less memory waste in accomplishing the alignment.
426da2fa9baf06f33a8fa7aa3f56c9f2b4070ceca0eMark Lord	 */
427da2fa9baf06f33a8fa7aa3f56c9f2b4070ceca0eMark Lord	struct dma_pool		*crqb_pool;
428da2fa9baf06f33a8fa7aa3f56c9f2b4070ceca0eMark Lord	struct dma_pool		*crpb_pool;
429da2fa9baf06f33a8fa7aa3f56c9f2b4070ceca0eMark Lord	struct dma_pool		*sg_tbl_pool;
43002a121da5a53d415b6596bc19cc6999d295d32a4Mark Lord};
43102a121da5a53d415b6596bc19cc6999d295d32a4Mark Lord
43247c2b677daeed9c79ecb7167c211ff36876ea611Jeff Garzikstruct mv_hw_ops {
4332a47ce06d534692f9bd2bf4e90a20fc9b1054c39Jeff Garzik	void (*phy_errata)(struct mv_host_priv *hpriv, void __iomem *mmio,
4342a47ce06d534692f9bd2bf4e90a20fc9b1054c39Jeff Garzik			   unsigned int port);
43547c2b677daeed9c79ecb7167c211ff36876ea611Jeff Garzik	void (*enable_leds)(struct mv_host_priv *hpriv, void __iomem *mmio);
43647c2b677daeed9c79ecb7167c211ff36876ea611Jeff Garzik	void (*read_preamp)(struct mv_host_priv *hpriv, int idx,
43747c2b677daeed9c79ecb7167c211ff36876ea611Jeff Garzik			   void __iomem *mmio);
438c9d39130123238ac18478a42e25cb7996eacfcc0Jeff Garzik	int (*reset_hc)(struct mv_host_priv *hpriv, void __iomem *mmio,
439c9d39130123238ac18478a42e25cb7996eacfcc0Jeff Garzik			unsigned int n_hc);
440522479fb98c6667f081e75f87e298e413c0b1db8Jeff Garzik	void (*reset_flash)(struct mv_host_priv *hpriv, void __iomem *mmio);
441522479fb98c6667f081e75f87e298e413c0b1db8Jeff Garzik	void (*reset_bus)(struct pci_dev *pdev, void __iomem *mmio);
44247c2b677daeed9c79ecb7167c211ff36876ea611Jeff Garzik};
44347c2b677daeed9c79ecb7167c211ff36876ea611Jeff Garzik
44420f733e7d75a16bffc34842b7682c9247dd5f954Brett Russstatic void mv_irq_clear(struct ata_port *ap);
445da3dbb17a0e9a9ec7f5aed95f1fddadb790edc9dTejun Heostatic int mv_scr_read(struct ata_port *ap, unsigned int sc_reg_in, u32 *val);
446da3dbb17a0e9a9ec7f5aed95f1fddadb790edc9dTejun Heostatic int mv_scr_write(struct ata_port *ap, unsigned int sc_reg_in, u32 val);
447da3dbb17a0e9a9ec7f5aed95f1fddadb790edc9dTejun Heostatic int mv5_scr_read(struct ata_port *ap, unsigned int sc_reg_in, u32 *val);
448da3dbb17a0e9a9ec7f5aed95f1fddadb790edc9dTejun Heostatic int mv5_scr_write(struct ata_port *ap, unsigned int sc_reg_in, u32 val);
44931961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russstatic int mv_port_start(struct ata_port *ap);
45031961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russstatic void mv_port_stop(struct ata_port *ap);
45131961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russstatic void mv_qc_prep(struct ata_queued_cmd *qc);
452e4e7b89280d1d666e2c09e5ad36cf071796c4c7eJeff Garzikstatic void mv_qc_prep_iie(struct ata_queued_cmd *qc);
4539a3d9eb0177eb10500d49cd283b35576082a522dTejun Heostatic unsigned int mv_qc_issue(struct ata_queued_cmd *qc);
454bdd4dddee325a7dce3e84cf48201a06aa8508aa4Jeff Garzikstatic void mv_error_handler(struct ata_port *ap);
455bdd4dddee325a7dce3e84cf48201a06aa8508aa4Jeff Garzikstatic void mv_post_int_cmd(struct ata_queued_cmd *qc);
456bdd4dddee325a7dce3e84cf48201a06aa8508aa4Jeff Garzikstatic void mv_eh_freeze(struct ata_port *ap);
457bdd4dddee325a7dce3e84cf48201a06aa8508aa4Jeff Garzikstatic void mv_eh_thaw(struct ata_port *ap);
458f273827e2aadcf2f74a7bdc9ad715a1b20ea7ddaMark Lordstatic void mv6_dev_config(struct ata_device *dev);
45920f733e7d75a16bffc34842b7682c9247dd5f954Brett Russstatic int mv_init_one(struct pci_dev *pdev, const struct pci_device_id *ent);
46020f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ
4612a47ce06d534692f9bd2bf4e90a20fc9b1054c39Jeff Garzikstatic void mv5_phy_errata(struct mv_host_priv *hpriv, void __iomem *mmio,
4622a47ce06d534692f9bd2bf4e90a20fc9b1054c39Jeff Garzik			   unsigned int port);
46347c2b677daeed9c79ecb7167c211ff36876ea611Jeff Garzikstatic void mv5_enable_leds(struct mv_host_priv *hpriv, void __iomem *mmio);
46447c2b677daeed9c79ecb7167c211ff36876ea611Jeff Garzikstatic void mv5_read_preamp(struct mv_host_priv *hpriv, int idx,
46547c2b677daeed9c79ecb7167c211ff36876ea611Jeff Garzik			   void __iomem *mmio);
466c9d39130123238ac18478a42e25cb7996eacfcc0Jeff Garzikstatic int mv5_reset_hc(struct mv_host_priv *hpriv, void __iomem *mmio,
467c9d39130123238ac18478a42e25cb7996eacfcc0Jeff Garzik			unsigned int n_hc);
468522479fb98c6667f081e75f87e298e413c0b1db8Jeff Garzikstatic void mv5_reset_flash(struct mv_host_priv *hpriv, void __iomem *mmio);
469522479fb98c6667f081e75f87e298e413c0b1db8Jeff Garzikstatic void mv5_reset_bus(struct pci_dev *pdev, void __iomem *mmio);
47047c2b677daeed9c79ecb7167c211ff36876ea611Jeff Garzik
4712a47ce06d534692f9bd2bf4e90a20fc9b1054c39Jeff Garzikstatic void mv6_phy_errata(struct mv_host_priv *hpriv, void __iomem *mmio,
4722a47ce06d534692f9bd2bf4e90a20fc9b1054c39Jeff Garzik			   unsigned int port);
47347c2b677daeed9c79ecb7167c211ff36876ea611Jeff Garzikstatic void mv6_enable_leds(struct mv_host_priv *hpriv, void __iomem *mmio);
47447c2b677daeed9c79ecb7167c211ff36876ea611Jeff Garzikstatic void mv6_read_preamp(struct mv_host_priv *hpriv, int idx,
47547c2b677daeed9c79ecb7167c211ff36876ea611Jeff Garzik			   void __iomem *mmio);
476c9d39130123238ac18478a42e25cb7996eacfcc0Jeff Garzikstatic int mv6_reset_hc(struct mv_host_priv *hpriv, void __iomem *mmio,
477c9d39130123238ac18478a42e25cb7996eacfcc0Jeff Garzik			unsigned int n_hc);
478522479fb98c6667f081e75f87e298e413c0b1db8Jeff Garzikstatic void mv6_reset_flash(struct mv_host_priv *hpriv, void __iomem *mmio);
479522479fb98c6667f081e75f87e298e413c0b1db8Jeff Garzikstatic void mv_reset_pci_bus(struct pci_dev *pdev, void __iomem *mmio);
480c9d39130123238ac18478a42e25cb7996eacfcc0Jeff Garzikstatic void mv_channel_reset(struct mv_host_priv *hpriv, void __iomem *mmio,
481c9d39130123238ac18478a42e25cb7996eacfcc0Jeff Garzik			     unsigned int port_no);
482721091685f853ba4e6c49f26f989db0b1a811250Mark Lordstatic void mv_edma_cfg(struct mv_port_priv *pp, struct mv_host_priv *hpriv,
483721091685f853ba4e6c49f26f989db0b1a811250Mark Lord			void __iomem *port_mmio, int want_ncq);
484721091685f853ba4e6c49f26f989db0b1a811250Mark Lordstatic int __mv_stop_dma(struct ata_port *ap);
48547c2b677daeed9c79ecb7167c211ff36876ea611Jeff Garzik
486eb73d558d1c1c931de0b3a86af962c77d74ef688Mark Lord/* .sg_tablesize is (MV_MAX_SG_CT / 2) in the structures below
487eb73d558d1c1c931de0b3a86af962c77d74ef688Mark Lord * because we have to allow room for worst case splitting of
488eb73d558d1c1c931de0b3a86af962c77d74ef688Mark Lord * PRDs for 64K boundaries in mv_fill_sg().
489eb73d558d1c1c931de0b3a86af962c77d74ef688Mark Lord */
490c5d3e45a2200a0905dc45b72714726b7aac3aaf1Jeff Garzikstatic struct scsi_host_template mv5_sht = {
491c5d3e45a2200a0905dc45b72714726b7aac3aaf1Jeff Garzik	.module			= THIS_MODULE,
492c5d3e45a2200a0905dc45b72714726b7aac3aaf1Jeff Garzik	.name			= DRV_NAME,
493c5d3e45a2200a0905dc45b72714726b7aac3aaf1Jeff Garzik	.ioctl			= ata_scsi_ioctl,
494c5d3e45a2200a0905dc45b72714726b7aac3aaf1Jeff Garzik	.queuecommand		= ata_scsi_queuecmd,
495c5d3e45a2200a0905dc45b72714726b7aac3aaf1Jeff Garzik	.can_queue		= ATA_DEF_QUEUE,
496c5d3e45a2200a0905dc45b72714726b7aac3aaf1Jeff Garzik	.this_id		= ATA_SHT_THIS_ID,
497baf14aa14efcfdb5a74d5cf804691086c6bec743Jeff Garzik	.sg_tablesize		= MV_MAX_SG_CT / 2,
498c5d3e45a2200a0905dc45b72714726b7aac3aaf1Jeff Garzik	.cmd_per_lun		= ATA_SHT_CMD_PER_LUN,
499c5d3e45a2200a0905dc45b72714726b7aac3aaf1Jeff Garzik	.emulated		= ATA_SHT_EMULATED,
500c5d3e45a2200a0905dc45b72714726b7aac3aaf1Jeff Garzik	.use_clustering		= 1,
501c5d3e45a2200a0905dc45b72714726b7aac3aaf1Jeff Garzik	.proc_name		= DRV_NAME,
502c5d3e45a2200a0905dc45b72714726b7aac3aaf1Jeff Garzik	.dma_boundary		= MV_DMA_BOUNDARY,
5033be6cbd73f74b4a3da82cc7d6e1688a4ae595fc7Jeff Garzik	.slave_configure	= ata_scsi_slave_config,
504c5d3e45a2200a0905dc45b72714726b7aac3aaf1Jeff Garzik	.slave_destroy		= ata_scsi_slave_destroy,
505c5d3e45a2200a0905dc45b72714726b7aac3aaf1Jeff Garzik	.bios_param		= ata_std_bios_param,
506c5d3e45a2200a0905dc45b72714726b7aac3aaf1Jeff Garzik};
507c5d3e45a2200a0905dc45b72714726b7aac3aaf1Jeff Garzik
508c5d3e45a2200a0905dc45b72714726b7aac3aaf1Jeff Garzikstatic struct scsi_host_template mv6_sht = {
50920f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ	.module			= THIS_MODULE,
51020f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ	.name			= DRV_NAME,
51120f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ	.ioctl			= ata_scsi_ioctl,
51220f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ	.queuecommand		= ata_scsi_queuecmd,
513c5d3e45a2200a0905dc45b72714726b7aac3aaf1Jeff Garzik	.can_queue		= ATA_DEF_QUEUE,
51420f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ	.this_id		= ATA_SHT_THIS_ID,
515baf14aa14efcfdb5a74d5cf804691086c6bec743Jeff Garzik	.sg_tablesize		= MV_MAX_SG_CT / 2,
51620f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ	.cmd_per_lun		= ATA_SHT_CMD_PER_LUN,
51720f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ	.emulated		= ATA_SHT_EMULATED,
518d88184fb2348a50f7c34f5d49a901c875b2e0114Jeff Garzik	.use_clustering		= 1,
51920f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ	.proc_name		= DRV_NAME,
52020f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ	.dma_boundary		= MV_DMA_BOUNDARY,
5213be6cbd73f74b4a3da82cc7d6e1688a4ae595fc7Jeff Garzik	.slave_configure	= ata_scsi_slave_config,
522ccf68c3405fca11386004674377d951b9b18e756Tejun Heo	.slave_destroy		= ata_scsi_slave_destroy,
52320f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ	.bios_param		= ata_std_bios_param,
52420f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ};
52520f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ
526c9d39130123238ac18478a42e25cb7996eacfcc0Jeff Garzikstatic const struct ata_port_operations mv5_ops = {
527c9d39130123238ac18478a42e25cb7996eacfcc0Jeff Garzik	.tf_load		= ata_tf_load,
528c9d39130123238ac18478a42e25cb7996eacfcc0Jeff Garzik	.tf_read		= ata_tf_read,
529c9d39130123238ac18478a42e25cb7996eacfcc0Jeff Garzik	.check_status		= ata_check_status,
530c9d39130123238ac18478a42e25cb7996eacfcc0Jeff Garzik	.exec_command		= ata_exec_command,
531c9d39130123238ac18478a42e25cb7996eacfcc0Jeff Garzik	.dev_select		= ata_std_dev_select,
532c9d39130123238ac18478a42e25cb7996eacfcc0Jeff Garzik
533cffacd85bcf6fc652292001873119333555fe260Jeff Garzik	.cable_detect		= ata_cable_sata,
534c9d39130123238ac18478a42e25cb7996eacfcc0Jeff Garzik
535c9d39130123238ac18478a42e25cb7996eacfcc0Jeff Garzik	.qc_prep		= mv_qc_prep,
536c9d39130123238ac18478a42e25cb7996eacfcc0Jeff Garzik	.qc_issue		= mv_qc_issue,
5370d5ff566779f894ca9937231a181eb31e4adff0eTejun Heo	.data_xfer		= ata_data_xfer,
538c9d39130123238ac18478a42e25cb7996eacfcc0Jeff Garzik
539c9d39130123238ac18478a42e25cb7996eacfcc0Jeff Garzik	.irq_clear		= mv_irq_clear,
540246ce3b675843e0369643cceb4faeb6cf6d19a30Akira Iguchi	.irq_on			= ata_irq_on,
541c9d39130123238ac18478a42e25cb7996eacfcc0Jeff Garzik
542bdd4dddee325a7dce3e84cf48201a06aa8508aa4Jeff Garzik	.error_handler		= mv_error_handler,
543bdd4dddee325a7dce3e84cf48201a06aa8508aa4Jeff Garzik	.post_internal_cmd	= mv_post_int_cmd,
544bdd4dddee325a7dce3e84cf48201a06aa8508aa4Jeff Garzik	.freeze			= mv_eh_freeze,
545bdd4dddee325a7dce3e84cf48201a06aa8508aa4Jeff Garzik	.thaw			= mv_eh_thaw,
546bdd4dddee325a7dce3e84cf48201a06aa8508aa4Jeff Garzik
547c9d39130123238ac18478a42e25cb7996eacfcc0Jeff Garzik	.scr_read		= mv5_scr_read,
548c9d39130123238ac18478a42e25cb7996eacfcc0Jeff Garzik	.scr_write		= mv5_scr_write,
549c9d39130123238ac18478a42e25cb7996eacfcc0Jeff Garzik
550c9d39130123238ac18478a42e25cb7996eacfcc0Jeff Garzik	.port_start		= mv_port_start,
551c9d39130123238ac18478a42e25cb7996eacfcc0Jeff Garzik	.port_stop		= mv_port_stop,
552c9d39130123238ac18478a42e25cb7996eacfcc0Jeff Garzik};
553c9d39130123238ac18478a42e25cb7996eacfcc0Jeff Garzik
554c9d39130123238ac18478a42e25cb7996eacfcc0Jeff Garzikstatic const struct ata_port_operations mv6_ops = {
555f273827e2aadcf2f74a7bdc9ad715a1b20ea7ddaMark Lord	.dev_config             = mv6_dev_config,
55620f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ	.tf_load		= ata_tf_load,
55720f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ	.tf_read		= ata_tf_read,
55820f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ	.check_status		= ata_check_status,
55920f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ	.exec_command		= ata_exec_command,
56020f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ	.dev_select		= ata_std_dev_select,
56120f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ
562cffacd85bcf6fc652292001873119333555fe260Jeff Garzik	.cable_detect		= ata_cable_sata,
56320f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ
56431961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ	.qc_prep		= mv_qc_prep,
56531961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ	.qc_issue		= mv_qc_issue,
5660d5ff566779f894ca9937231a181eb31e4adff0eTejun Heo	.data_xfer		= ata_data_xfer,
56720f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ
56820f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ	.irq_clear		= mv_irq_clear,
569246ce3b675843e0369643cceb4faeb6cf6d19a30Akira Iguchi	.irq_on			= ata_irq_on,
57020f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ
571bdd4dddee325a7dce3e84cf48201a06aa8508aa4Jeff Garzik	.error_handler		= mv_error_handler,
572bdd4dddee325a7dce3e84cf48201a06aa8508aa4Jeff Garzik	.post_internal_cmd	= mv_post_int_cmd,
573bdd4dddee325a7dce3e84cf48201a06aa8508aa4Jeff Garzik	.freeze			= mv_eh_freeze,
574bdd4dddee325a7dce3e84cf48201a06aa8508aa4Jeff Garzik	.thaw			= mv_eh_thaw,
575bdd4dddee325a7dce3e84cf48201a06aa8508aa4Jeff Garzik
57620f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ	.scr_read		= mv_scr_read,
57720f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ	.scr_write		= mv_scr_write,
57820f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ
57931961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ	.port_start		= mv_port_start,
58031961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ	.port_stop		= mv_port_stop,
58120f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ};
58220f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ
583e4e7b89280d1d666e2c09e5ad36cf071796c4c7eJeff Garzikstatic const struct ata_port_operations mv_iie_ops = {
584e4e7b89280d1d666e2c09e5ad36cf071796c4c7eJeff Garzik	.tf_load		= ata_tf_load,
585e4e7b89280d1d666e2c09e5ad36cf071796c4c7eJeff Garzik	.tf_read		= ata_tf_read,
586e4e7b89280d1d666e2c09e5ad36cf071796c4c7eJeff Garzik	.check_status		= ata_check_status,
587e4e7b89280d1d666e2c09e5ad36cf071796c4c7eJeff Garzik	.exec_command		= ata_exec_command,
588e4e7b89280d1d666e2c09e5ad36cf071796c4c7eJeff Garzik	.dev_select		= ata_std_dev_select,
589e4e7b89280d1d666e2c09e5ad36cf071796c4c7eJeff Garzik
590cffacd85bcf6fc652292001873119333555fe260Jeff Garzik	.cable_detect		= ata_cable_sata,
591e4e7b89280d1d666e2c09e5ad36cf071796c4c7eJeff Garzik
592e4e7b89280d1d666e2c09e5ad36cf071796c4c7eJeff Garzik	.qc_prep		= mv_qc_prep_iie,
593e4e7b89280d1d666e2c09e5ad36cf071796c4c7eJeff Garzik	.qc_issue		= mv_qc_issue,
5940d5ff566779f894ca9937231a181eb31e4adff0eTejun Heo	.data_xfer		= ata_data_xfer,
595e4e7b89280d1d666e2c09e5ad36cf071796c4c7eJeff Garzik
596e4e7b89280d1d666e2c09e5ad36cf071796c4c7eJeff Garzik	.irq_clear		= mv_irq_clear,
597246ce3b675843e0369643cceb4faeb6cf6d19a30Akira Iguchi	.irq_on			= ata_irq_on,
598e4e7b89280d1d666e2c09e5ad36cf071796c4c7eJeff Garzik
599bdd4dddee325a7dce3e84cf48201a06aa8508aa4Jeff Garzik	.error_handler		= mv_error_handler,
600bdd4dddee325a7dce3e84cf48201a06aa8508aa4Jeff Garzik	.post_internal_cmd	= mv_post_int_cmd,
601bdd4dddee325a7dce3e84cf48201a06aa8508aa4Jeff Garzik	.freeze			= mv_eh_freeze,
602bdd4dddee325a7dce3e84cf48201a06aa8508aa4Jeff Garzik	.thaw			= mv_eh_thaw,
603bdd4dddee325a7dce3e84cf48201a06aa8508aa4Jeff Garzik
604e4e7b89280d1d666e2c09e5ad36cf071796c4c7eJeff Garzik	.scr_read		= mv_scr_read,
605e4e7b89280d1d666e2c09e5ad36cf071796c4c7eJeff Garzik	.scr_write		= mv_scr_write,
606e4e7b89280d1d666e2c09e5ad36cf071796c4c7eJeff Garzik
607e4e7b89280d1d666e2c09e5ad36cf071796c4c7eJeff Garzik	.port_start		= mv_port_start,
608e4e7b89280d1d666e2c09e5ad36cf071796c4c7eJeff Garzik	.port_stop		= mv_port_stop,
609e4e7b89280d1d666e2c09e5ad36cf071796c4c7eJeff Garzik};
610e4e7b89280d1d666e2c09e5ad36cf071796c4c7eJeff Garzik
61198ac62defe529d04a192688f40d801a2d8fbcf98Arjan van de Venstatic const struct ata_port_info mv_port_info[] = {
61220f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ	{  /* chip_504x */
613cca3974e48607c3775dc73b544a5700b2e37c21aJeff Garzik		.flags		= MV_COMMON_FLAGS,
61431961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ		.pio_mask	= 0x1f,	/* pio0-4 */
615bf6263a853c9c143bf03f0a6fdcc68ab714fb5f5Jeff Garzik		.udma_mask	= ATA_UDMA6,
616c9d39130123238ac18478a42e25cb7996eacfcc0Jeff Garzik		.port_ops	= &mv5_ops,
61720f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ	},
61820f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ	{  /* chip_508x */
619c5d3e45a2200a0905dc45b72714726b7aac3aaf1Jeff Garzik		.flags		= MV_COMMON_FLAGS | MV_FLAG_DUAL_HC,
62031961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ		.pio_mask	= 0x1f,	/* pio0-4 */
621bf6263a853c9c143bf03f0a6fdcc68ab714fb5f5Jeff Garzik		.udma_mask	= ATA_UDMA6,
622c9d39130123238ac18478a42e25cb7996eacfcc0Jeff Garzik		.port_ops	= &mv5_ops,
62320f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ	},
62447c2b677daeed9c79ecb7167c211ff36876ea611Jeff Garzik	{  /* chip_5080 */
625c5d3e45a2200a0905dc45b72714726b7aac3aaf1Jeff Garzik		.flags		= MV_COMMON_FLAGS | MV_FLAG_DUAL_HC,
62647c2b677daeed9c79ecb7167c211ff36876ea611Jeff Garzik		.pio_mask	= 0x1f,	/* pio0-4 */
627bf6263a853c9c143bf03f0a6fdcc68ab714fb5f5Jeff Garzik		.udma_mask	= ATA_UDMA6,
628c9d39130123238ac18478a42e25cb7996eacfcc0Jeff Garzik		.port_ops	= &mv5_ops,
62947c2b677daeed9c79ecb7167c211ff36876ea611Jeff Garzik	},
63020f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ	{  /* chip_604x */
631c5d3e45a2200a0905dc45b72714726b7aac3aaf1Jeff Garzik		.flags		= MV_COMMON_FLAGS | MV_6XXX_FLAGS,
63231961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ		.pio_mask	= 0x1f,	/* pio0-4 */
633bf6263a853c9c143bf03f0a6fdcc68ab714fb5f5Jeff Garzik		.udma_mask	= ATA_UDMA6,
634c9d39130123238ac18478a42e25cb7996eacfcc0Jeff Garzik		.port_ops	= &mv6_ops,
63520f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ	},
63620f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ	{  /* chip_608x */
637c5d3e45a2200a0905dc45b72714726b7aac3aaf1Jeff Garzik		.flags		= MV_COMMON_FLAGS | MV_6XXX_FLAGS |
638c5d3e45a2200a0905dc45b72714726b7aac3aaf1Jeff Garzik				  MV_FLAG_DUAL_HC,
63931961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ		.pio_mask	= 0x1f,	/* pio0-4 */
640bf6263a853c9c143bf03f0a6fdcc68ab714fb5f5Jeff Garzik		.udma_mask	= ATA_UDMA6,
641c9d39130123238ac18478a42e25cb7996eacfcc0Jeff Garzik		.port_ops	= &mv6_ops,
64220f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ	},
643e4e7b89280d1d666e2c09e5ad36cf071796c4c7eJeff Garzik	{  /* chip_6042 */
644c5d3e45a2200a0905dc45b72714726b7aac3aaf1Jeff Garzik		.flags		= MV_COMMON_FLAGS | MV_6XXX_FLAGS,
645e4e7b89280d1d666e2c09e5ad36cf071796c4c7eJeff Garzik		.pio_mask	= 0x1f,	/* pio0-4 */
646bf6263a853c9c143bf03f0a6fdcc68ab714fb5f5Jeff Garzik		.udma_mask	= ATA_UDMA6,
647e4e7b89280d1d666e2c09e5ad36cf071796c4c7eJeff Garzik		.port_ops	= &mv_iie_ops,
648e4e7b89280d1d666e2c09e5ad36cf071796c4c7eJeff Garzik	},
649e4e7b89280d1d666e2c09e5ad36cf071796c4c7eJeff Garzik	{  /* chip_7042 */
650c5d3e45a2200a0905dc45b72714726b7aac3aaf1Jeff Garzik		.flags		= MV_COMMON_FLAGS | MV_6XXX_FLAGS,
651e4e7b89280d1d666e2c09e5ad36cf071796c4c7eJeff Garzik		.pio_mask	= 0x1f,	/* pio0-4 */
652bf6263a853c9c143bf03f0a6fdcc68ab714fb5f5Jeff Garzik		.udma_mask	= ATA_UDMA6,
653e4e7b89280d1d666e2c09e5ad36cf071796c4c7eJeff Garzik		.port_ops	= &mv_iie_ops,
654e4e7b89280d1d666e2c09e5ad36cf071796c4c7eJeff Garzik	},
65520f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ};
65620f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ
6573b7d697dfb7d03edb87e50b743a7ecff029618e9Jeff Garzikstatic const struct pci_device_id mv_pci_tbl[] = {
6582d2744fc8be620a2dc469cf48349e3e704119f1bJeff Garzik	{ PCI_VDEVICE(MARVELL, 0x5040), chip_504x },
6592d2744fc8be620a2dc469cf48349e3e704119f1bJeff Garzik	{ PCI_VDEVICE(MARVELL, 0x5041), chip_504x },
6602d2744fc8be620a2dc469cf48349e3e704119f1bJeff Garzik	{ PCI_VDEVICE(MARVELL, 0x5080), chip_5080 },
6612d2744fc8be620a2dc469cf48349e3e704119f1bJeff Garzik	{ PCI_VDEVICE(MARVELL, 0x5081), chip_508x },
662cfbf723eb7928879292ee71fa0d118fc4e37b8c9Alan Cox	/* RocketRAID 1740/174x have different identifiers */
663cfbf723eb7928879292ee71fa0d118fc4e37b8c9Alan Cox	{ PCI_VDEVICE(TTI, 0x1740), chip_508x },
664cfbf723eb7928879292ee71fa0d118fc4e37b8c9Alan Cox	{ PCI_VDEVICE(TTI, 0x1742), chip_508x },
6652d2744fc8be620a2dc469cf48349e3e704119f1bJeff Garzik
6662d2744fc8be620a2dc469cf48349e3e704119f1bJeff Garzik	{ PCI_VDEVICE(MARVELL, 0x6040), chip_604x },
6672d2744fc8be620a2dc469cf48349e3e704119f1bJeff Garzik	{ PCI_VDEVICE(MARVELL, 0x6041), chip_604x },
6682d2744fc8be620a2dc469cf48349e3e704119f1bJeff Garzik	{ PCI_VDEVICE(MARVELL, 0x6042), chip_6042 },
6692d2744fc8be620a2dc469cf48349e3e704119f1bJeff Garzik	{ PCI_VDEVICE(MARVELL, 0x6080), chip_608x },
6702d2744fc8be620a2dc469cf48349e3e704119f1bJeff Garzik	{ PCI_VDEVICE(MARVELL, 0x6081), chip_608x },
6712d2744fc8be620a2dc469cf48349e3e704119f1bJeff Garzik
6722d2744fc8be620a2dc469cf48349e3e704119f1bJeff Garzik	{ PCI_VDEVICE(ADAPTEC2, 0x0241), chip_604x },
6732d2744fc8be620a2dc469cf48349e3e704119f1bJeff Garzik
674d9f9c6bc91c14f53ffa782ffcd42259ecae1d38cFlorian Attenberger	/* Adaptec 1430SA */
675d9f9c6bc91c14f53ffa782ffcd42259ecae1d38cFlorian Attenberger	{ PCI_VDEVICE(ADAPTEC2, 0x0243), chip_7042 },
676d9f9c6bc91c14f53ffa782ffcd42259ecae1d38cFlorian Attenberger
67702a121da5a53d415b6596bc19cc6999d295d32a4Mark Lord	/* Marvell 7042 support */
6786a3d586d8e8a50e4cfd7f8c36d82a53c5614e05bMorrison, Tom	{ PCI_VDEVICE(MARVELL, 0x7042), chip_7042 },
6796a3d586d8e8a50e4cfd7f8c36d82a53c5614e05bMorrison, Tom
68002a121da5a53d415b6596bc19cc6999d295d32a4Mark Lord	/* Highpoint RocketRAID PCIe series */
68102a121da5a53d415b6596bc19cc6999d295d32a4Mark Lord	{ PCI_VDEVICE(TTI, 0x2300), chip_7042 },
68202a121da5a53d415b6596bc19cc6999d295d32a4Mark Lord	{ PCI_VDEVICE(TTI, 0x2310), chip_7042 },
68302a121da5a53d415b6596bc19cc6999d295d32a4Mark Lord
6842d2744fc8be620a2dc469cf48349e3e704119f1bJeff Garzik	{ }			/* terminate list */
68520f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ};
68620f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ
68720f733e7d75a16bffc34842b7682c9247dd5f954Brett Russstatic struct pci_driver mv_pci_driver = {
68820f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ	.name			= DRV_NAME,
68920f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ	.id_table		= mv_pci_tbl,
69020f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ	.probe			= mv_init_one,
69120f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ	.remove			= ata_pci_remove_one,
69220f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ};
69320f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ
69447c2b677daeed9c79ecb7167c211ff36876ea611Jeff Garzikstatic const struct mv_hw_ops mv5xxx_ops = {
69547c2b677daeed9c79ecb7167c211ff36876ea611Jeff Garzik	.phy_errata		= mv5_phy_errata,
69647c2b677daeed9c79ecb7167c211ff36876ea611Jeff Garzik	.enable_leds		= mv5_enable_leds,
69747c2b677daeed9c79ecb7167c211ff36876ea611Jeff Garzik	.read_preamp		= mv5_read_preamp,
69847c2b677daeed9c79ecb7167c211ff36876ea611Jeff Garzik	.reset_hc		= mv5_reset_hc,
699522479fb98c6667f081e75f87e298e413c0b1db8Jeff Garzik	.reset_flash		= mv5_reset_flash,
700522479fb98c6667f081e75f87e298e413c0b1db8Jeff Garzik	.reset_bus		= mv5_reset_bus,
70147c2b677daeed9c79ecb7167c211ff36876ea611Jeff Garzik};
70247c2b677daeed9c79ecb7167c211ff36876ea611Jeff Garzik
70347c2b677daeed9c79ecb7167c211ff36876ea611Jeff Garzikstatic const struct mv_hw_ops mv6xxx_ops = {
70447c2b677daeed9c79ecb7167c211ff36876ea611Jeff Garzik	.phy_errata		= mv6_phy_errata,
70547c2b677daeed9c79ecb7167c211ff36876ea611Jeff Garzik	.enable_leds		= mv6_enable_leds,
70647c2b677daeed9c79ecb7167c211ff36876ea611Jeff Garzik	.read_preamp		= mv6_read_preamp,
70747c2b677daeed9c79ecb7167c211ff36876ea611Jeff Garzik	.reset_hc		= mv6_reset_hc,
708522479fb98c6667f081e75f87e298e413c0b1db8Jeff Garzik	.reset_flash		= mv6_reset_flash,
709522479fb98c6667f081e75f87e298e413c0b1db8Jeff Garzik	.reset_bus		= mv_reset_pci_bus,
71047c2b677daeed9c79ecb7167c211ff36876ea611Jeff Garzik};
71147c2b677daeed9c79ecb7167c211ff36876ea611Jeff Garzik
71220f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ/*
713ddef9bb367b19383df627e388cb4c01c86ddba6cJeff Garzik * module options
714ddef9bb367b19383df627e388cb4c01c86ddba6cJeff Garzik */
715ddef9bb367b19383df627e388cb4c01c86ddba6cJeff Garzikstatic int msi;	      /* Use PCI msi; either zero (off, default) or non-zero */
716ddef9bb367b19383df627e388cb4c01c86ddba6cJeff Garzik
717ddef9bb367b19383df627e388cb4c01c86ddba6cJeff Garzik
718d88184fb2348a50f7c34f5d49a901c875b2e0114Jeff Garzik/* move to PCI layer or libata core? */
719d88184fb2348a50f7c34f5d49a901c875b2e0114Jeff Garzikstatic int pci_go_64(struct pci_dev *pdev)
720d88184fb2348a50f7c34f5d49a901c875b2e0114Jeff Garzik{
721d88184fb2348a50f7c34f5d49a901c875b2e0114Jeff Garzik	int rc;
722d88184fb2348a50f7c34f5d49a901c875b2e0114Jeff Garzik
723d88184fb2348a50f7c34f5d49a901c875b2e0114Jeff Garzik	if (!pci_set_dma_mask(pdev, DMA_64BIT_MASK)) {
724d88184fb2348a50f7c34f5d49a901c875b2e0114Jeff Garzik		rc = pci_set_consistent_dma_mask(pdev, DMA_64BIT_MASK);
725d88184fb2348a50f7c34f5d49a901c875b2e0114Jeff Garzik		if (rc) {
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					   "64-bit DMA enable failed\n");
730d88184fb2348a50f7c34f5d49a901c875b2e0114Jeff Garzik				return rc;
731d88184fb2348a50f7c34f5d49a901c875b2e0114Jeff Garzik			}
732d88184fb2348a50f7c34f5d49a901c875b2e0114Jeff Garzik		}
733d88184fb2348a50f7c34f5d49a901c875b2e0114Jeff Garzik	} else {
734d88184fb2348a50f7c34f5d49a901c875b2e0114Jeff Garzik		rc = pci_set_dma_mask(pdev, DMA_32BIT_MASK);
735d88184fb2348a50f7c34f5d49a901c875b2e0114Jeff Garzik		if (rc) {
736d88184fb2348a50f7c34f5d49a901c875b2e0114Jeff Garzik			dev_printk(KERN_ERR, &pdev->dev,
737d88184fb2348a50f7c34f5d49a901c875b2e0114Jeff Garzik				   "32-bit DMA enable failed\n");
738d88184fb2348a50f7c34f5d49a901c875b2e0114Jeff Garzik			return rc;
739d88184fb2348a50f7c34f5d49a901c875b2e0114Jeff Garzik		}
740d88184fb2348a50f7c34f5d49a901c875b2e0114Jeff Garzik		rc = pci_set_consistent_dma_mask(pdev, DMA_32BIT_MASK);
741d88184fb2348a50f7c34f5d49a901c875b2e0114Jeff Garzik		if (rc) {
742d88184fb2348a50f7c34f5d49a901c875b2e0114Jeff Garzik			dev_printk(KERN_ERR, &pdev->dev,
743d88184fb2348a50f7c34f5d49a901c875b2e0114Jeff Garzik				   "32-bit consistent DMA enable failed\n");
744d88184fb2348a50f7c34f5d49a901c875b2e0114Jeff Garzik			return rc;
745d88184fb2348a50f7c34f5d49a901c875b2e0114Jeff Garzik		}
746d88184fb2348a50f7c34f5d49a901c875b2e0114Jeff Garzik	}
747d88184fb2348a50f7c34f5d49a901c875b2e0114Jeff Garzik
748d88184fb2348a50f7c34f5d49a901c875b2e0114Jeff Garzik	return rc;
749d88184fb2348a50f7c34f5d49a901c875b2e0114Jeff Garzik}
750d88184fb2348a50f7c34f5d49a901c875b2e0114Jeff Garzik
751ddef9bb367b19383df627e388cb4c01c86ddba6cJeff Garzik/*
75220f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ * Functions
75320f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ */
75420f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ
75520f733e7d75a16bffc34842b7682c9247dd5f954Brett Russstatic inline void writelfl(unsigned long data, void __iomem *addr)
75620f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ{
75720f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ	writel(data, addr);
75820f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ	(void) readl(addr);	/* flush to avoid PCI posted write */
75920f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ}
76020f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ
76120f733e7d75a16bffc34842b7682c9247dd5f954Brett Russstatic inline void __iomem *mv_hc_base(void __iomem *base, unsigned int hc)
76220f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ{
76320f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ	return (base + MV_SATAHC0_REG_BASE + (hc * MV_SATAHC_REG_SZ));
76420f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ}
76520f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ
766c9d39130123238ac18478a42e25cb7996eacfcc0Jeff Garzikstatic inline unsigned int mv_hc_from_port(unsigned int port)
767c9d39130123238ac18478a42e25cb7996eacfcc0Jeff Garzik{
768c9d39130123238ac18478a42e25cb7996eacfcc0Jeff Garzik	return port >> MV_PORT_HC_SHIFT;
769c9d39130123238ac18478a42e25cb7996eacfcc0Jeff Garzik}
770c9d39130123238ac18478a42e25cb7996eacfcc0Jeff Garzik
771c9d39130123238ac18478a42e25cb7996eacfcc0Jeff Garzikstatic inline unsigned int mv_hardport_from_port(unsigned int port)
772c9d39130123238ac18478a42e25cb7996eacfcc0Jeff Garzik{
773c9d39130123238ac18478a42e25cb7996eacfcc0Jeff Garzik	return port & MV_PORT_MASK;
774c9d39130123238ac18478a42e25cb7996eacfcc0Jeff Garzik}
775c9d39130123238ac18478a42e25cb7996eacfcc0Jeff Garzik
776c9d39130123238ac18478a42e25cb7996eacfcc0Jeff Garzikstatic inline void __iomem *mv_hc_base_from_port(void __iomem *base,
777c9d39130123238ac18478a42e25cb7996eacfcc0Jeff Garzik						 unsigned int port)
778c9d39130123238ac18478a42e25cb7996eacfcc0Jeff Garzik{
779c9d39130123238ac18478a42e25cb7996eacfcc0Jeff Garzik	return mv_hc_base(base, mv_hc_from_port(port));
780c9d39130123238ac18478a42e25cb7996eacfcc0Jeff Garzik}
781c9d39130123238ac18478a42e25cb7996eacfcc0Jeff Garzik
78220f733e7d75a16bffc34842b7682c9247dd5f954Brett Russstatic inline void __iomem *mv_port_base(void __iomem *base, unsigned int port)
78320f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ{
784c9d39130123238ac18478a42e25cb7996eacfcc0Jeff Garzik	return  mv_hc_base_from_port(base, port) +
7858b260248d9e0e8b64bb72fd4dee03ad86984c344Jeff Garzik		MV_SATAHC_ARBTR_REG_SZ +
786c9d39130123238ac18478a42e25cb7996eacfcc0Jeff Garzik		(mv_hardport_from_port(port) * MV_PORT_REG_SZ);
78720f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ}
78820f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ
78920f733e7d75a16bffc34842b7682c9247dd5f954Brett Russstatic inline void __iomem *mv_ap_base(struct ata_port *ap)
79020f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ{
7910d5ff566779f894ca9937231a181eb31e4adff0eTejun Heo	return mv_port_base(ap->host->iomap[MV_PRIMARY_BAR], ap->port_no);
79220f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ}
79320f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ
794cca3974e48607c3775dc73b544a5700b2e37c21aJeff Garzikstatic inline int mv_get_hc_count(unsigned long port_flags)
79531961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ{
796cca3974e48607c3775dc73b544a5700b2e37c21aJeff Garzik	return ((port_flags & MV_FLAG_DUAL_HC) ? 2 : 1);
79731961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ}
79831961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ
79931961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russstatic void mv_irq_clear(struct ata_port *ap)
80020f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ{
80120f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ}
80220f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ
803c5d3e45a2200a0905dc45b72714726b7aac3aaf1Jeff Garzikstatic void mv_set_edma_ptrs(void __iomem *port_mmio,
804c5d3e45a2200a0905dc45b72714726b7aac3aaf1Jeff Garzik			     struct mv_host_priv *hpriv,
805c5d3e45a2200a0905dc45b72714726b7aac3aaf1Jeff Garzik			     struct mv_port_priv *pp)
806c5d3e45a2200a0905dc45b72714726b7aac3aaf1Jeff Garzik{
807bdd4dddee325a7dce3e84cf48201a06aa8508aa4Jeff Garzik	u32 index;
808bdd4dddee325a7dce3e84cf48201a06aa8508aa4Jeff Garzik
809c5d3e45a2200a0905dc45b72714726b7aac3aaf1Jeff Garzik	/*
810c5d3e45a2200a0905dc45b72714726b7aac3aaf1Jeff Garzik	 * initialize request queue
811c5d3e45a2200a0905dc45b72714726b7aac3aaf1Jeff Garzik	 */
812bdd4dddee325a7dce3e84cf48201a06aa8508aa4Jeff Garzik	index = (pp->req_idx & MV_MAX_Q_DEPTH_MASK) << EDMA_REQ_Q_PTR_SHIFT;
813bdd4dddee325a7dce3e84cf48201a06aa8508aa4Jeff Garzik
814c5d3e45a2200a0905dc45b72714726b7aac3aaf1Jeff Garzik	WARN_ON(pp->crqb_dma & 0x3ff);
815c5d3e45a2200a0905dc45b72714726b7aac3aaf1Jeff Garzik	writel((pp->crqb_dma >> 16) >> 16, port_mmio + EDMA_REQ_Q_BASE_HI_OFS);
816bdd4dddee325a7dce3e84cf48201a06aa8508aa4Jeff Garzik	writelfl((pp->crqb_dma & EDMA_REQ_Q_BASE_LO_MASK) | index,
817c5d3e45a2200a0905dc45b72714726b7aac3aaf1Jeff Garzik		 port_mmio + EDMA_REQ_Q_IN_PTR_OFS);
818c5d3e45a2200a0905dc45b72714726b7aac3aaf1Jeff Garzik
819c5d3e45a2200a0905dc45b72714726b7aac3aaf1Jeff Garzik	if (hpriv->hp_flags & MV_HP_ERRATA_XX42A0)
820bdd4dddee325a7dce3e84cf48201a06aa8508aa4Jeff Garzik		writelfl((pp->crqb_dma & 0xffffffff) | index,
821c5d3e45a2200a0905dc45b72714726b7aac3aaf1Jeff Garzik			 port_mmio + EDMA_REQ_Q_OUT_PTR_OFS);
822c5d3e45a2200a0905dc45b72714726b7aac3aaf1Jeff Garzik	else
823bdd4dddee325a7dce3e84cf48201a06aa8508aa4Jeff Garzik		writelfl(index, port_mmio + EDMA_REQ_Q_OUT_PTR_OFS);
824c5d3e45a2200a0905dc45b72714726b7aac3aaf1Jeff Garzik
825c5d3e45a2200a0905dc45b72714726b7aac3aaf1Jeff Garzik	/*
826c5d3e45a2200a0905dc45b72714726b7aac3aaf1Jeff Garzik	 * initialize response queue
827c5d3e45a2200a0905dc45b72714726b7aac3aaf1Jeff Garzik	 */
828bdd4dddee325a7dce3e84cf48201a06aa8508aa4Jeff Garzik	index = (pp->resp_idx & MV_MAX_Q_DEPTH_MASK) << EDMA_RSP_Q_PTR_SHIFT;
829bdd4dddee325a7dce3e84cf48201a06aa8508aa4Jeff Garzik
830c5d3e45a2200a0905dc45b72714726b7aac3aaf1Jeff Garzik	WARN_ON(pp->crpb_dma & 0xff);
831c5d3e45a2200a0905dc45b72714726b7aac3aaf1Jeff Garzik	writel((pp->crpb_dma >> 16) >> 16, port_mmio + EDMA_RSP_Q_BASE_HI_OFS);
832c5d3e45a2200a0905dc45b72714726b7aac3aaf1Jeff Garzik
833c5d3e45a2200a0905dc45b72714726b7aac3aaf1Jeff Garzik	if (hpriv->hp_flags & MV_HP_ERRATA_XX42A0)
834bdd4dddee325a7dce3e84cf48201a06aa8508aa4Jeff Garzik		writelfl((pp->crpb_dma & 0xffffffff) | index,
835c5d3e45a2200a0905dc45b72714726b7aac3aaf1Jeff Garzik			 port_mmio + EDMA_RSP_Q_IN_PTR_OFS);
836c5d3e45a2200a0905dc45b72714726b7aac3aaf1Jeff Garzik	else
837bdd4dddee325a7dce3e84cf48201a06aa8508aa4Jeff Garzik		writelfl(index, port_mmio + EDMA_RSP_Q_IN_PTR_OFS);
838c5d3e45a2200a0905dc45b72714726b7aac3aaf1Jeff Garzik
839bdd4dddee325a7dce3e84cf48201a06aa8508aa4Jeff Garzik	writelfl((pp->crpb_dma & EDMA_RSP_Q_BASE_LO_MASK) | index,
840c5d3e45a2200a0905dc45b72714726b7aac3aaf1Jeff Garzik		 port_mmio + EDMA_RSP_Q_OUT_PTR_OFS);
841c5d3e45a2200a0905dc45b72714726b7aac3aaf1Jeff Garzik}
842c5d3e45a2200a0905dc45b72714726b7aac3aaf1Jeff Garzik
84305b308e1df6d9d673daedb517969241f41278b52Brett Russ/**
84405b308e1df6d9d673daedb517969241f41278b52Brett Russ *      mv_start_dma - Enable eDMA engine
84505b308e1df6d9d673daedb517969241f41278b52Brett Russ *      @base: port base address
84605b308e1df6d9d673daedb517969241f41278b52Brett Russ *      @pp: port private data
84705b308e1df6d9d673daedb517969241f41278b52Brett Russ *
848beec7dbc6ff003bbc94de62b3323519c878fb2acTejun Heo *      Verify the local cache of the eDMA state is accurate with a
849beec7dbc6ff003bbc94de62b3323519c878fb2acTejun Heo *      WARN_ON.
85005b308e1df6d9d673daedb517969241f41278b52Brett Russ *
85105b308e1df6d9d673daedb517969241f41278b52Brett Russ *      LOCKING:
85205b308e1df6d9d673daedb517969241f41278b52Brett Russ *      Inherited from caller.
85305b308e1df6d9d673daedb517969241f41278b52Brett Russ */
8540c58912e192fc3a4835d772aafa40b72552b819fMark Lordstatic void mv_start_dma(struct ata_port *ap, void __iomem *port_mmio,
855721091685f853ba4e6c49f26f989db0b1a811250Mark Lord			 struct mv_port_priv *pp, u8 protocol)
85620f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ{
857721091685f853ba4e6c49f26f989db0b1a811250Mark Lord	int want_ncq = (protocol == ATA_PROT_NCQ);
858721091685f853ba4e6c49f26f989db0b1a811250Mark Lord
859721091685f853ba4e6c49f26f989db0b1a811250Mark Lord	if (pp->pp_flags & MV_PP_FLAG_EDMA_EN) {
860721091685f853ba4e6c49f26f989db0b1a811250Mark Lord		int using_ncq = ((pp->pp_flags & MV_PP_FLAG_NCQ_EN) != 0);
861721091685f853ba4e6c49f26f989db0b1a811250Mark Lord		if (want_ncq != using_ncq)
862721091685f853ba4e6c49f26f989db0b1a811250Mark Lord			__mv_stop_dma(ap);
863721091685f853ba4e6c49f26f989db0b1a811250Mark Lord	}
864c5d3e45a2200a0905dc45b72714726b7aac3aaf1Jeff Garzik	if (!(pp->pp_flags & MV_PP_FLAG_EDMA_EN)) {
8650c58912e192fc3a4835d772aafa40b72552b819fMark Lord		struct mv_host_priv *hpriv = ap->host->private_data;
8660c58912e192fc3a4835d772aafa40b72552b819fMark Lord		int hard_port = mv_hardport_from_port(ap->port_no);
8670c58912e192fc3a4835d772aafa40b72552b819fMark Lord		void __iomem *hc_mmio = mv_hc_base_from_port(
8680c58912e192fc3a4835d772aafa40b72552b819fMark Lord				ap->host->iomap[MV_PRIMARY_BAR], hard_port);
8690c58912e192fc3a4835d772aafa40b72552b819fMark Lord		u32 hc_irq_cause, ipending;
8700c58912e192fc3a4835d772aafa40b72552b819fMark Lord
871bdd4dddee325a7dce3e84cf48201a06aa8508aa4Jeff Garzik		/* clear EDMA event indicators, if any */
872f630d562829fcd8160a118f98c1e5b9cdb4e703eMark Lord		writelfl(0, port_mmio + EDMA_ERR_IRQ_CAUSE_OFS);
873bdd4dddee325a7dce3e84cf48201a06aa8508aa4Jeff Garzik
8740c58912e192fc3a4835d772aafa40b72552b819fMark Lord		/* clear EDMA interrupt indicator, if any */
8750c58912e192fc3a4835d772aafa40b72552b819fMark Lord		hc_irq_cause = readl(hc_mmio + HC_IRQ_CAUSE_OFS);
8760c58912e192fc3a4835d772aafa40b72552b819fMark Lord		ipending = (DEV_IRQ << hard_port) |
8770c58912e192fc3a4835d772aafa40b72552b819fMark Lord				(CRPB_DMA_DONE << hard_port);
8780c58912e192fc3a4835d772aafa40b72552b819fMark Lord		if (hc_irq_cause & ipending) {
8790c58912e192fc3a4835d772aafa40b72552b819fMark Lord			writelfl(hc_irq_cause & ~ipending,
8800c58912e192fc3a4835d772aafa40b72552b819fMark Lord				 hc_mmio + HC_IRQ_CAUSE_OFS);
8810c58912e192fc3a4835d772aafa40b72552b819fMark Lord		}
8820c58912e192fc3a4835d772aafa40b72552b819fMark Lord
883721091685f853ba4e6c49f26f989db0b1a811250Mark Lord		mv_edma_cfg(pp, hpriv, port_mmio, want_ncq);
8840c58912e192fc3a4835d772aafa40b72552b819fMark Lord
8850c58912e192fc3a4835d772aafa40b72552b819fMark Lord		/* clear FIS IRQ Cause */
8860c58912e192fc3a4835d772aafa40b72552b819fMark Lord		writelfl(0, port_mmio + SATA_FIS_IRQ_CAUSE_OFS);
8870c58912e192fc3a4835d772aafa40b72552b819fMark Lord
888f630d562829fcd8160a118f98c1e5b9cdb4e703eMark Lord		mv_set_edma_ptrs(port_mmio, hpriv, pp);
889bdd4dddee325a7dce3e84cf48201a06aa8508aa4Jeff Garzik
890f630d562829fcd8160a118f98c1e5b9cdb4e703eMark Lord		writelfl(EDMA_EN, port_mmio + EDMA_CMD_OFS);
891afb0edd922c7ed6e73678730921dfcccebec17e8Brett Russ		pp->pp_flags |= MV_PP_FLAG_EDMA_EN;
892afb0edd922c7ed6e73678730921dfcccebec17e8Brett Russ	}
893f630d562829fcd8160a118f98c1e5b9cdb4e703eMark Lord	WARN_ON(!(EDMA_EN & readl(port_mmio + EDMA_CMD_OFS)));
89420f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ}
89520f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ
89605b308e1df6d9d673daedb517969241f41278b52Brett Russ/**
8970ea9e179f436f153fc19fdaef7abbc1e0da20762Jeff Garzik *      __mv_stop_dma - Disable eDMA engine
89805b308e1df6d9d673daedb517969241f41278b52Brett Russ *      @ap: ATA channel to manipulate
89905b308e1df6d9d673daedb517969241f41278b52Brett Russ *
900beec7dbc6ff003bbc94de62b3323519c878fb2acTejun Heo *      Verify the local cache of the eDMA state is accurate with a
901beec7dbc6ff003bbc94de62b3323519c878fb2acTejun Heo *      WARN_ON.
90205b308e1df6d9d673daedb517969241f41278b52Brett Russ *
90305b308e1df6d9d673daedb517969241f41278b52Brett Russ *      LOCKING:
90405b308e1df6d9d673daedb517969241f41278b52Brett Russ *      Inherited from caller.
90505b308e1df6d9d673daedb517969241f41278b52Brett Russ */
9060ea9e179f436f153fc19fdaef7abbc1e0da20762Jeff Garzikstatic int __mv_stop_dma(struct ata_port *ap)
90720f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ{
90831961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ	void __iomem *port_mmio = mv_ap_base(ap);
90931961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ	struct mv_port_priv *pp	= ap->private_data;
91031961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ	u32 reg;
911c5d3e45a2200a0905dc45b72714726b7aac3aaf1Jeff Garzik	int i, err = 0;
91231961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ
9134537deb5e90b717a725b3d74b58b4bb1d28443d0Jeff Garzik	if (pp->pp_flags & MV_PP_FLAG_EDMA_EN) {
914afb0edd922c7ed6e73678730921dfcccebec17e8Brett Russ		/* Disable EDMA if active.   The disable bit auto clears.
91531961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ		 */
91631961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ		writelfl(EDMA_DS, port_mmio + EDMA_CMD_OFS);
91731961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ		pp->pp_flags &= ~MV_PP_FLAG_EDMA_EN;
918afb0edd922c7ed6e73678730921dfcccebec17e8Brett Russ	} else {
919beec7dbc6ff003bbc94de62b3323519c878fb2acTejun Heo		WARN_ON(EDMA_EN & readl(port_mmio + EDMA_CMD_OFS));
9202dcb407e61458ded17503d6bd12b8c064965368bJeff Garzik	}
9218b260248d9e0e8b64bb72fd4dee03ad86984c344Jeff Garzik
92231961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ	/* now properly wait for the eDMA to stop */
92331961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ	for (i = 1000; i > 0; i--) {
92431961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ		reg = readl(port_mmio + EDMA_CMD_OFS);
9254537deb5e90b717a725b3d74b58b4bb1d28443d0Jeff Garzik		if (!(reg & EDMA_EN))
92631961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ			break;
9274537deb5e90b717a725b3d74b58b4bb1d28443d0Jeff Garzik
92831961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ		udelay(100);
92931961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ	}
93031961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ
931c5d3e45a2200a0905dc45b72714726b7aac3aaf1Jeff Garzik	if (reg & EDMA_EN) {
932f15a1dafed22d5037e0feea7528e1eeb28a1a7a3Tejun Heo		ata_port_printk(ap, KERN_ERR, "Unable to stop eDMA\n");
933c5d3e45a2200a0905dc45b72714726b7aac3aaf1Jeff Garzik		err = -EIO;
93431961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ	}
935c5d3e45a2200a0905dc45b72714726b7aac3aaf1Jeff Garzik
936c5d3e45a2200a0905dc45b72714726b7aac3aaf1Jeff Garzik	return err;
93720f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ}
93820f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ
9390ea9e179f436f153fc19fdaef7abbc1e0da20762Jeff Garzikstatic int mv_stop_dma(struct ata_port *ap)
9400ea9e179f436f153fc19fdaef7abbc1e0da20762Jeff Garzik{
9410ea9e179f436f153fc19fdaef7abbc1e0da20762Jeff Garzik	unsigned long flags;
9420ea9e179f436f153fc19fdaef7abbc1e0da20762Jeff Garzik	int rc;
9430ea9e179f436f153fc19fdaef7abbc1e0da20762Jeff Garzik
9440ea9e179f436f153fc19fdaef7abbc1e0da20762Jeff Garzik	spin_lock_irqsave(&ap->host->lock, flags);
9450ea9e179f436f153fc19fdaef7abbc1e0da20762Jeff Garzik	rc = __mv_stop_dma(ap);
9460ea9e179f436f153fc19fdaef7abbc1e0da20762Jeff Garzik	spin_unlock_irqrestore(&ap->host->lock, flags);
9470ea9e179f436f153fc19fdaef7abbc1e0da20762Jeff Garzik
9480ea9e179f436f153fc19fdaef7abbc1e0da20762Jeff Garzik	return rc;
9490ea9e179f436f153fc19fdaef7abbc1e0da20762Jeff Garzik}
9500ea9e179f436f153fc19fdaef7abbc1e0da20762Jeff Garzik
9518a70f8dc08dd40b7f8ac77280eaa99a8c6bc46f4Jeff Garzik#ifdef ATA_DEBUG
95231961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russstatic void mv_dump_mem(void __iomem *start, unsigned bytes)
95320f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ{
95431961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ	int b, w;
95531961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ	for (b = 0; b < bytes; ) {
95631961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ		DPRINTK("%p: ", start + b);
95731961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ		for (w = 0; b < bytes && w < 4; w++) {
9582dcb407e61458ded17503d6bd12b8c064965368bJeff Garzik			printk("%08x ", readl(start + b));
95931961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ			b += sizeof(u32);
96031961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ		}
96131961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ		printk("\n");
96231961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ	}
96331961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ}
9648a70f8dc08dd40b7f8ac77280eaa99a8c6bc46f4Jeff Garzik#endif
9658a70f8dc08dd40b7f8ac77280eaa99a8c6bc46f4Jeff Garzik
96631961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russstatic void mv_dump_pci_cfg(struct pci_dev *pdev, unsigned bytes)
96731961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ{
96831961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ#ifdef ATA_DEBUG
96931961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ	int b, w;
97031961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ	u32 dw;
97131961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ	for (b = 0; b < bytes; ) {
97231961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ		DPRINTK("%02x: ", b);
97331961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ		for (w = 0; b < bytes && w < 4; w++) {
9742dcb407e61458ded17503d6bd12b8c064965368bJeff Garzik			(void) pci_read_config_dword(pdev, b, &dw);
9752dcb407e61458ded17503d6bd12b8c064965368bJeff Garzik			printk("%08x ", dw);
97631961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ			b += sizeof(u32);
97731961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ		}
97831961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ		printk("\n");
97931961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ	}
98031961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ#endif
98131961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ}
98231961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russstatic void mv_dump_all_regs(void __iomem *mmio_base, int port,
98331961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ			     struct pci_dev *pdev)
98431961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ{
98531961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ#ifdef ATA_DEBUG
9868b260248d9e0e8b64bb72fd4dee03ad86984c344Jeff Garzik	void __iomem *hc_base = mv_hc_base(mmio_base,
98731961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ					   port >> MV_PORT_HC_SHIFT);
98831961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ	void __iomem *port_base;
98931961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ	int start_port, num_ports, p, start_hc, num_hcs, hc;
99031961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ
99131961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ	if (0 > port) {
99231961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ		start_hc = start_port = 0;
99331961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ		num_ports = 8;		/* shld be benign for 4 port devs */
99431961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ		num_hcs = 2;
99531961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ	} else {
99631961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ		start_hc = port >> MV_PORT_HC_SHIFT;
99731961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ		start_port = port;
99831961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ		num_ports = num_hcs = 1;
99931961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ	}
10008b260248d9e0e8b64bb72fd4dee03ad86984c344Jeff Garzik	DPRINTK("All registers for port(s) %u-%u:\n", start_port,
100131961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ		num_ports > 1 ? num_ports - 1 : start_port);
100231961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ
100331961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ	if (NULL != pdev) {
100431961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ		DPRINTK("PCI config space regs:\n");
100531961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ		mv_dump_pci_cfg(pdev, 0x68);
100631961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ	}
100731961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ	DPRINTK("PCI regs:\n");
100831961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ	mv_dump_mem(mmio_base+0xc00, 0x3c);
100931961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ	mv_dump_mem(mmio_base+0xd00, 0x34);
101031961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ	mv_dump_mem(mmio_base+0xf00, 0x4);
101131961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ	mv_dump_mem(mmio_base+0x1d00, 0x6c);
101231961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ	for (hc = start_hc; hc < start_hc + num_hcs; hc++) {
1013d220c37e0a3c9a47ae00e87e044d963b3ea040bcDan Aloni		hc_base = mv_hc_base(mmio_base, hc);
101431961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ		DPRINTK("HC regs (HC %i):\n", hc);
101531961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ		mv_dump_mem(hc_base, 0x1c);
101631961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ	}
101731961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ	for (p = start_port; p < start_port + num_ports; p++) {
101831961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ		port_base = mv_port_base(mmio_base, p);
10192dcb407e61458ded17503d6bd12b8c064965368bJeff Garzik		DPRINTK("EDMA regs (port %i):\n", p);
102031961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ		mv_dump_mem(port_base, 0x54);
10212dcb407e61458ded17503d6bd12b8c064965368bJeff Garzik		DPRINTK("SATA regs (port %i):\n", p);
102231961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ		mv_dump_mem(port_base+0x300, 0x60);
102331961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ	}
102431961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ#endif
102520f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ}
102620f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ
102720f733e7d75a16bffc34842b7682c9247dd5f954Brett Russstatic unsigned int mv_scr_offset(unsigned int sc_reg_in)
102820f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ{
102920f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ	unsigned int ofs;
103020f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ
103120f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ	switch (sc_reg_in) {
103220f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ	case SCR_STATUS:
103320f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ	case SCR_CONTROL:
103420f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ	case SCR_ERROR:
103520f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ		ofs = SATA_STATUS_OFS + (sc_reg_in * sizeof(u32));
103620f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ		break;
103720f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ	case SCR_ACTIVE:
103820f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ		ofs = SATA_ACTIVE_OFS;   /* active is not with the others */
103920f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ		break;
104020f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ	default:
104120f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ		ofs = 0xffffffffU;
104220f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ		break;
104320f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ	}
104420f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ	return ofs;
104520f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ}
104620f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ
1047da3dbb17a0e9a9ec7f5aed95f1fddadb790edc9dTejun Heostatic int mv_scr_read(struct ata_port *ap, unsigned int sc_reg_in, u32 *val)
104820f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ{
104920f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ	unsigned int ofs = mv_scr_offset(sc_reg_in);
105020f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ
1051da3dbb17a0e9a9ec7f5aed95f1fddadb790edc9dTejun Heo	if (ofs != 0xffffffffU) {
1052da3dbb17a0e9a9ec7f5aed95f1fddadb790edc9dTejun Heo		*val = readl(mv_ap_base(ap) + ofs);
1053da3dbb17a0e9a9ec7f5aed95f1fddadb790edc9dTejun Heo		return 0;
1054da3dbb17a0e9a9ec7f5aed95f1fddadb790edc9dTejun Heo	} else
1055da3dbb17a0e9a9ec7f5aed95f1fddadb790edc9dTejun Heo		return -EINVAL;
105620f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ}
105720f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ
1058da3dbb17a0e9a9ec7f5aed95f1fddadb790edc9dTejun Heostatic int mv_scr_write(struct ata_port *ap, unsigned int sc_reg_in, u32 val)
105920f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ{
106020f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ	unsigned int ofs = mv_scr_offset(sc_reg_in);
106120f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ
1062da3dbb17a0e9a9ec7f5aed95f1fddadb790edc9dTejun Heo	if (ofs != 0xffffffffU) {
106320f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ		writelfl(val, mv_ap_base(ap) + ofs);
1064da3dbb17a0e9a9ec7f5aed95f1fddadb790edc9dTejun Heo		return 0;
1065da3dbb17a0e9a9ec7f5aed95f1fddadb790edc9dTejun Heo	} else
1066da3dbb17a0e9a9ec7f5aed95f1fddadb790edc9dTejun Heo		return -EINVAL;
106720f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ}
106820f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ
1069f273827e2aadcf2f74a7bdc9ad715a1b20ea7ddaMark Lordstatic void mv6_dev_config(struct ata_device *adev)
1070f273827e2aadcf2f74a7bdc9ad715a1b20ea7ddaMark Lord{
1071f273827e2aadcf2f74a7bdc9ad715a1b20ea7ddaMark Lord	/*
1072f273827e2aadcf2f74a7bdc9ad715a1b20ea7ddaMark Lord	 * We don't have hob_nsect when doing NCQ commands on Gen-II.
1073f273827e2aadcf2f74a7bdc9ad715a1b20ea7ddaMark Lord	 * See mv_qc_prep() for more info.
1074f273827e2aadcf2f74a7bdc9ad715a1b20ea7ddaMark Lord	 */
1075f273827e2aadcf2f74a7bdc9ad715a1b20ea7ddaMark Lord	if (adev->flags & ATA_DFLAG_NCQ)
1076f273827e2aadcf2f74a7bdc9ad715a1b20ea7ddaMark Lord		if (adev->max_sectors > ATA_MAX_SECTORS)
1077f273827e2aadcf2f74a7bdc9ad715a1b20ea7ddaMark Lord			adev->max_sectors = ATA_MAX_SECTORS;
1078f273827e2aadcf2f74a7bdc9ad715a1b20ea7ddaMark Lord}
1079f273827e2aadcf2f74a7bdc9ad715a1b20ea7ddaMark Lord
1080721091685f853ba4e6c49f26f989db0b1a811250Mark Lordstatic void mv_edma_cfg(struct mv_port_priv *pp, struct mv_host_priv *hpriv,
1081721091685f853ba4e6c49f26f989db0b1a811250Mark Lord			void __iomem *port_mmio, int want_ncq)
1082e4e7b89280d1d666e2c09e5ad36cf071796c4c7eJeff Garzik{
10830c58912e192fc3a4835d772aafa40b72552b819fMark Lord	u32 cfg;
1084e4e7b89280d1d666e2c09e5ad36cf071796c4c7eJeff Garzik
1085e4e7b89280d1d666e2c09e5ad36cf071796c4c7eJeff Garzik	/* set up non-NCQ EDMA configuration */
10860c58912e192fc3a4835d772aafa40b72552b819fMark Lord	cfg = EDMA_CFG_Q_DEPTH;		/* always 0x1f for *all* chips */
1087e4e7b89280d1d666e2c09e5ad36cf071796c4c7eJeff Garzik
10880c58912e192fc3a4835d772aafa40b72552b819fMark Lord	if (IS_GEN_I(hpriv))
1089e4e7b89280d1d666e2c09e5ad36cf071796c4c7eJeff Garzik		cfg |= (1 << 8);	/* enab config burst size mask */
1090e4e7b89280d1d666e2c09e5ad36cf071796c4c7eJeff Garzik
10910c58912e192fc3a4835d772aafa40b72552b819fMark Lord	else if (IS_GEN_II(hpriv))
1092e4e7b89280d1d666e2c09e5ad36cf071796c4c7eJeff Garzik		cfg |= EDMA_CFG_RD_BRST_EXT | EDMA_CFG_WR_BUFF_LEN;
1093e4e7b89280d1d666e2c09e5ad36cf071796c4c7eJeff Garzik
1094e4e7b89280d1d666e2c09e5ad36cf071796c4c7eJeff Garzik	else if (IS_GEN_IIE(hpriv)) {
1095e728eabea110da90e69c05855e3a11174edb77efJeff Garzik		cfg |= (1 << 23);	/* do not mask PM field in rx'd FIS */
1096e728eabea110da90e69c05855e3a11174edb77efJeff Garzik		cfg |= (1 << 22);	/* enab 4-entry host queue cache */
1097e4e7b89280d1d666e2c09e5ad36cf071796c4c7eJeff Garzik		cfg |= (1 << 18);	/* enab early completion */
1098e728eabea110da90e69c05855e3a11174edb77efJeff Garzik		cfg |= (1 << 17);	/* enab cut-through (dis stor&forwrd) */
1099e4e7b89280d1d666e2c09e5ad36cf071796c4c7eJeff Garzik	}
1100e4e7b89280d1d666e2c09e5ad36cf071796c4c7eJeff Garzik
1101721091685f853ba4e6c49f26f989db0b1a811250Mark Lord	if (want_ncq) {
1102721091685f853ba4e6c49f26f989db0b1a811250Mark Lord		cfg |= EDMA_CFG_NCQ;
1103721091685f853ba4e6c49f26f989db0b1a811250Mark Lord		pp->pp_flags |=  MV_PP_FLAG_NCQ_EN;
1104721091685f853ba4e6c49f26f989db0b1a811250Mark Lord	} else
1105721091685f853ba4e6c49f26f989db0b1a811250Mark Lord		pp->pp_flags &= ~MV_PP_FLAG_NCQ_EN;
1106721091685f853ba4e6c49f26f989db0b1a811250Mark Lord
1107e4e7b89280d1d666e2c09e5ad36cf071796c4c7eJeff Garzik	writelfl(cfg, port_mmio + EDMA_CFG_OFS);
1108e4e7b89280d1d666e2c09e5ad36cf071796c4c7eJeff Garzik}
1109e4e7b89280d1d666e2c09e5ad36cf071796c4c7eJeff Garzik
1110da2fa9baf06f33a8fa7aa3f56c9f2b4070ceca0eMark Lordstatic void mv_port_free_dma_mem(struct ata_port *ap)
1111da2fa9baf06f33a8fa7aa3f56c9f2b4070ceca0eMark Lord{
1112da2fa9baf06f33a8fa7aa3f56c9f2b4070ceca0eMark Lord	struct mv_host_priv *hpriv = ap->host->private_data;
1113da2fa9baf06f33a8fa7aa3f56c9f2b4070ceca0eMark Lord	struct mv_port_priv *pp = ap->private_data;
1114eb73d558d1c1c931de0b3a86af962c77d74ef688Mark Lord	int tag;
1115da2fa9baf06f33a8fa7aa3f56c9f2b4070ceca0eMark Lord
1116da2fa9baf06f33a8fa7aa3f56c9f2b4070ceca0eMark Lord	if (pp->crqb) {
1117da2fa9baf06f33a8fa7aa3f56c9f2b4070ceca0eMark Lord		dma_pool_free(hpriv->crqb_pool, pp->crqb, pp->crqb_dma);
1118da2fa9baf06f33a8fa7aa3f56c9f2b4070ceca0eMark Lord		pp->crqb = NULL;
1119da2fa9baf06f33a8fa7aa3f56c9f2b4070ceca0eMark Lord	}
1120da2fa9baf06f33a8fa7aa3f56c9f2b4070ceca0eMark Lord	if (pp->crpb) {
1121da2fa9baf06f33a8fa7aa3f56c9f2b4070ceca0eMark Lord		dma_pool_free(hpriv->crpb_pool, pp->crpb, pp->crpb_dma);
1122da2fa9baf06f33a8fa7aa3f56c9f2b4070ceca0eMark Lord		pp->crpb = NULL;
1123da2fa9baf06f33a8fa7aa3f56c9f2b4070ceca0eMark Lord	}
1124eb73d558d1c1c931de0b3a86af962c77d74ef688Mark Lord	/*
1125eb73d558d1c1c931de0b3a86af962c77d74ef688Mark Lord	 * For GEN_I, there's no NCQ, so we have only a single sg_tbl.
1126eb73d558d1c1c931de0b3a86af962c77d74ef688Mark Lord	 * For later hardware, we have one unique sg_tbl per NCQ tag.
1127eb73d558d1c1c931de0b3a86af962c77d74ef688Mark Lord	 */
1128eb73d558d1c1c931de0b3a86af962c77d74ef688Mark Lord	for (tag = 0; tag < MV_MAX_Q_DEPTH; ++tag) {
1129eb73d558d1c1c931de0b3a86af962c77d74ef688Mark Lord		if (pp->sg_tbl[tag]) {
1130eb73d558d1c1c931de0b3a86af962c77d74ef688Mark Lord			if (tag == 0 || !IS_GEN_I(hpriv))
1131eb73d558d1c1c931de0b3a86af962c77d74ef688Mark Lord				dma_pool_free(hpriv->sg_tbl_pool,
1132eb73d558d1c1c931de0b3a86af962c77d74ef688Mark Lord					      pp->sg_tbl[tag],
1133eb73d558d1c1c931de0b3a86af962c77d74ef688Mark Lord					      pp->sg_tbl_dma[tag]);
1134eb73d558d1c1c931de0b3a86af962c77d74ef688Mark Lord			pp->sg_tbl[tag] = NULL;
1135eb73d558d1c1c931de0b3a86af962c77d74ef688Mark Lord		}
1136da2fa9baf06f33a8fa7aa3f56c9f2b4070ceca0eMark Lord	}
1137da2fa9baf06f33a8fa7aa3f56c9f2b4070ceca0eMark Lord}
1138da2fa9baf06f33a8fa7aa3f56c9f2b4070ceca0eMark Lord
113905b308e1df6d9d673daedb517969241f41278b52Brett Russ/**
114005b308e1df6d9d673daedb517969241f41278b52Brett Russ *      mv_port_start - Port specific init/start routine.
114105b308e1df6d9d673daedb517969241f41278b52Brett Russ *      @ap: ATA channel to manipulate
114205b308e1df6d9d673daedb517969241f41278b52Brett Russ *
114305b308e1df6d9d673daedb517969241f41278b52Brett Russ *      Allocate and point to DMA memory, init port private memory,
114405b308e1df6d9d673daedb517969241f41278b52Brett Russ *      zero indices.
114505b308e1df6d9d673daedb517969241f41278b52Brett Russ *
114605b308e1df6d9d673daedb517969241f41278b52Brett Russ *      LOCKING:
114705b308e1df6d9d673daedb517969241f41278b52Brett Russ *      Inherited from caller.
114805b308e1df6d9d673daedb517969241f41278b52Brett Russ */
114931961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russstatic int mv_port_start(struct ata_port *ap)
115031961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ{
1151cca3974e48607c3775dc73b544a5700b2e37c21aJeff Garzik	struct device *dev = ap->host->dev;
1152cca3974e48607c3775dc73b544a5700b2e37c21aJeff Garzik	struct mv_host_priv *hpriv = ap->host->private_data;
115331961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ	struct mv_port_priv *pp;
115431961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ	void __iomem *port_mmio = mv_ap_base(ap);
11550ea9e179f436f153fc19fdaef7abbc1e0da20762Jeff Garzik	unsigned long flags;
1156eb73d558d1c1c931de0b3a86af962c77d74ef688Mark Lord	int tag, rc;
115731961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ
115824dc5f33ea4b504cfbd23fa159a4cacba8e4d800Tejun Heo	pp = devm_kzalloc(dev, sizeof(*pp), GFP_KERNEL);
11596037d6bbdff65eb5a84fe35e140f4da4f7cc103aJeff Garzik	if (!pp)
116024dc5f33ea4b504cfbd23fa159a4cacba8e4d800Tejun Heo		return -ENOMEM;
1161da2fa9baf06f33a8fa7aa3f56c9f2b4070ceca0eMark Lord	ap->private_data = pp;
116231961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ
11636037d6bbdff65eb5a84fe35e140f4da4f7cc103aJeff Garzik	rc = ata_pad_alloc(ap, dev);
11646037d6bbdff65eb5a84fe35e140f4da4f7cc103aJeff Garzik	if (rc)
116524dc5f33ea4b504cfbd23fa159a4cacba8e4d800Tejun Heo		return rc;
11666037d6bbdff65eb5a84fe35e140f4da4f7cc103aJeff Garzik
1167da2fa9baf06f33a8fa7aa3f56c9f2b4070ceca0eMark Lord	pp->crqb = dma_pool_alloc(hpriv->crqb_pool, GFP_KERNEL, &pp->crqb_dma);
1168da2fa9baf06f33a8fa7aa3f56c9f2b4070ceca0eMark Lord	if (!pp->crqb)
1169da2fa9baf06f33a8fa7aa3f56c9f2b4070ceca0eMark Lord		return -ENOMEM;
1170da2fa9baf06f33a8fa7aa3f56c9f2b4070ceca0eMark Lord	memset(pp->crqb, 0, MV_CRQB_Q_SZ);
117131961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ
1172da2fa9baf06f33a8fa7aa3f56c9f2b4070ceca0eMark Lord	pp->crpb = dma_pool_alloc(hpriv->crpb_pool, GFP_KERNEL, &pp->crpb_dma);
1173da2fa9baf06f33a8fa7aa3f56c9f2b4070ceca0eMark Lord	if (!pp->crpb)
1174da2fa9baf06f33a8fa7aa3f56c9f2b4070ceca0eMark Lord		goto out_port_free_dma_mem;
1175da2fa9baf06f33a8fa7aa3f56c9f2b4070ceca0eMark Lord	memset(pp->crpb, 0, MV_CRPB_Q_SZ);
117631961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ
1177eb73d558d1c1c931de0b3a86af962c77d74ef688Mark Lord	/*
1178eb73d558d1c1c931de0b3a86af962c77d74ef688Mark Lord	 * For GEN_I, there's no NCQ, so we only allocate a single sg_tbl.
1179eb73d558d1c1c931de0b3a86af962c77d74ef688Mark Lord	 * For later hardware, we need one unique sg_tbl per NCQ tag.
1180eb73d558d1c1c931de0b3a86af962c77d74ef688Mark Lord	 */
1181eb73d558d1c1c931de0b3a86af962c77d74ef688Mark Lord	for (tag = 0; tag < MV_MAX_Q_DEPTH; ++tag) {
1182eb73d558d1c1c931de0b3a86af962c77d74ef688Mark Lord		if (tag == 0 || !IS_GEN_I(hpriv)) {
1183eb73d558d1c1c931de0b3a86af962c77d74ef688Mark Lord			pp->sg_tbl[tag] = dma_pool_alloc(hpriv->sg_tbl_pool,
1184eb73d558d1c1c931de0b3a86af962c77d74ef688Mark Lord					      GFP_KERNEL, &pp->sg_tbl_dma[tag]);
1185eb73d558d1c1c931de0b3a86af962c77d74ef688Mark Lord			if (!pp->sg_tbl[tag])
1186eb73d558d1c1c931de0b3a86af962c77d74ef688Mark Lord				goto out_port_free_dma_mem;
1187eb73d558d1c1c931de0b3a86af962c77d74ef688Mark Lord		} else {
1188eb73d558d1c1c931de0b3a86af962c77d74ef688Mark Lord			pp->sg_tbl[tag]     = pp->sg_tbl[0];
1189eb73d558d1c1c931de0b3a86af962c77d74ef688Mark Lord			pp->sg_tbl_dma[tag] = pp->sg_tbl_dma[0];
1190eb73d558d1c1c931de0b3a86af962c77d74ef688Mark Lord		}
1191eb73d558d1c1c931de0b3a86af962c77d74ef688Mark Lord	}
119231961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ
11930ea9e179f436f153fc19fdaef7abbc1e0da20762Jeff Garzik	spin_lock_irqsave(&ap->host->lock, flags);
11940ea9e179f436f153fc19fdaef7abbc1e0da20762Jeff Garzik
1195721091685f853ba4e6c49f26f989db0b1a811250Mark Lord	mv_edma_cfg(pp, hpriv, port_mmio, 0);
1196c5d3e45a2200a0905dc45b72714726b7aac3aaf1Jeff Garzik	mv_set_edma_ptrs(port_mmio, hpriv, pp);
119731961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ
11980ea9e179f436f153fc19fdaef7abbc1e0da20762Jeff Garzik	spin_unlock_irqrestore(&ap->host->lock, flags);
11990ea9e179f436f153fc19fdaef7abbc1e0da20762Jeff Garzik
120031961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ	/* Don't turn on EDMA here...do it before DMA commands only.  Else
120131961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ	 * we'll be unable to send non-data, PIO, etc due to restricted access
120231961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ	 * to shadow regs.
120331961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ	 */
120431961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ	return 0;
1205da2fa9baf06f33a8fa7aa3f56c9f2b4070ceca0eMark Lord
1206da2fa9baf06f33a8fa7aa3f56c9f2b4070ceca0eMark Lordout_port_free_dma_mem:
1207da2fa9baf06f33a8fa7aa3f56c9f2b4070ceca0eMark Lord	mv_port_free_dma_mem(ap);
1208da2fa9baf06f33a8fa7aa3f56c9f2b4070ceca0eMark Lord	return -ENOMEM;
120931961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ}
121031961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ
121105b308e1df6d9d673daedb517969241f41278b52Brett Russ/**
121205b308e1df6d9d673daedb517969241f41278b52Brett Russ *      mv_port_stop - Port specific cleanup/stop routine.
121305b308e1df6d9d673daedb517969241f41278b52Brett Russ *      @ap: ATA channel to manipulate
121405b308e1df6d9d673daedb517969241f41278b52Brett Russ *
121505b308e1df6d9d673daedb517969241f41278b52Brett Russ *      Stop DMA, cleanup port memory.
121605b308e1df6d9d673daedb517969241f41278b52Brett Russ *
121705b308e1df6d9d673daedb517969241f41278b52Brett Russ *      LOCKING:
1218cca3974e48607c3775dc73b544a5700b2e37c21aJeff Garzik *      This routine uses the host lock to protect the DMA stop.
121905b308e1df6d9d673daedb517969241f41278b52Brett Russ */
122031961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russstatic void mv_port_stop(struct ata_port *ap)
122131961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ{
122231961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ	mv_stop_dma(ap);
1223da2fa9baf06f33a8fa7aa3f56c9f2b4070ceca0eMark Lord	mv_port_free_dma_mem(ap);
122431961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ}
122531961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ
122605b308e1df6d9d673daedb517969241f41278b52Brett Russ/**
122705b308e1df6d9d673daedb517969241f41278b52Brett Russ *      mv_fill_sg - Fill out the Marvell ePRD (scatter gather) entries
122805b308e1df6d9d673daedb517969241f41278b52Brett Russ *      @qc: queued command whose SG list to source from
122905b308e1df6d9d673daedb517969241f41278b52Brett Russ *
123005b308e1df6d9d673daedb517969241f41278b52Brett Russ *      Populate the SG list and mark the last entry.
123105b308e1df6d9d673daedb517969241f41278b52Brett Russ *
123205b308e1df6d9d673daedb517969241f41278b52Brett Russ *      LOCKING:
123305b308e1df6d9d673daedb517969241f41278b52Brett Russ *      Inherited from caller.
123405b308e1df6d9d673daedb517969241f41278b52Brett Russ */
12356c08772e49622e90d39903e7ff0be1a0f463ac86Jeff Garzikstatic void mv_fill_sg(struct ata_queued_cmd *qc)
123631961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ{
123731961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ	struct mv_port_priv *pp = qc->ap->private_data;
1238972c26bdd6b58e7534473c4f7928584578cf43f4Jeff Garzik	struct scatterlist *sg;
12393be6cbd73f74b4a3da82cc7d6e1688a4ae595fc7Jeff Garzik	struct mv_sg *mv_sg, *last_sg = NULL;
1240ff2aeb1eb64c8a4770a6304f9addbae9f9828646Tejun Heo	unsigned int si;
124131961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ
1242eb73d558d1c1c931de0b3a86af962c77d74ef688Mark Lord	mv_sg = pp->sg_tbl[qc->tag];
1243ff2aeb1eb64c8a4770a6304f9addbae9f9828646Tejun Heo	for_each_sg(qc->sg, sg, qc->n_elem, si) {
1244d88184fb2348a50f7c34f5d49a901c875b2e0114Jeff Garzik		dma_addr_t addr = sg_dma_address(sg);
1245d88184fb2348a50f7c34f5d49a901c875b2e0114Jeff Garzik		u32 sg_len = sg_dma_len(sg);
124622374677d18c5eeefd3a283431d312b8c44fef02Jeff Garzik
12474007b493ee6e4a52c2b618ab8361847fba5bf116Olof Johansson		while (sg_len) {
12484007b493ee6e4a52c2b618ab8361847fba5bf116Olof Johansson			u32 offset = addr & 0xffff;
12494007b493ee6e4a52c2b618ab8361847fba5bf116Olof Johansson			u32 len = sg_len;
125022374677d18c5eeefd3a283431d312b8c44fef02Jeff Garzik
12514007b493ee6e4a52c2b618ab8361847fba5bf116Olof Johansson			if ((offset + sg_len > 0x10000))
12524007b493ee6e4a52c2b618ab8361847fba5bf116Olof Johansson				len = 0x10000 - offset;
12534007b493ee6e4a52c2b618ab8361847fba5bf116Olof Johansson
12544007b493ee6e4a52c2b618ab8361847fba5bf116Olof Johansson			mv_sg->addr = cpu_to_le32(addr & 0xffffffff);
12554007b493ee6e4a52c2b618ab8361847fba5bf116Olof Johansson			mv_sg->addr_hi = cpu_to_le32((addr >> 16) >> 16);
12566c08772e49622e90d39903e7ff0be1a0f463ac86Jeff Garzik			mv_sg->flags_size = cpu_to_le32(len & 0xffff);
12574007b493ee6e4a52c2b618ab8361847fba5bf116Olof Johansson
12584007b493ee6e4a52c2b618ab8361847fba5bf116Olof Johansson			sg_len -= len;
12594007b493ee6e4a52c2b618ab8361847fba5bf116Olof Johansson			addr += len;
12604007b493ee6e4a52c2b618ab8361847fba5bf116Olof Johansson
12613be6cbd73f74b4a3da82cc7d6e1688a4ae595fc7Jeff Garzik			last_sg = mv_sg;
12624007b493ee6e4a52c2b618ab8361847fba5bf116Olof Johansson			mv_sg++;
12634007b493ee6e4a52c2b618ab8361847fba5bf116Olof Johansson		}
126431961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ	}
12653be6cbd73f74b4a3da82cc7d6e1688a4ae595fc7Jeff Garzik
12663be6cbd73f74b4a3da82cc7d6e1688a4ae595fc7Jeff Garzik	if (likely(last_sg))
12673be6cbd73f74b4a3da82cc7d6e1688a4ae595fc7Jeff Garzik		last_sg->flags_size |= cpu_to_le32(EPRD_FLAG_END_OF_TBL);
126831961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ}
126931961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ
12705796d1c4c89efff823259fda35b08ea66ebf8b23Jeff Garzikstatic void mv_crqb_pack_cmd(__le16 *cmdw, u8 data, u8 addr, unsigned last)
127131961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ{
1272559eedad7f7764dacca33980127b4615011230e4Mark Lord	u16 tmp = data | (addr << CRQB_CMD_ADDR_SHIFT) | CRQB_CMD_CS |
127331961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ		(last ? CRQB_CMD_LAST : 0);
1274559eedad7f7764dacca33980127b4615011230e4Mark Lord	*cmdw = cpu_to_le16(tmp);
127531961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ}
127631961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ
127705b308e1df6d9d673daedb517969241f41278b52Brett Russ/**
127805b308e1df6d9d673daedb517969241f41278b52Brett Russ *      mv_qc_prep - Host specific command preparation.
127905b308e1df6d9d673daedb517969241f41278b52Brett Russ *      @qc: queued command to prepare
128005b308e1df6d9d673daedb517969241f41278b52Brett Russ *
128105b308e1df6d9d673daedb517969241f41278b52Brett Russ *      This routine simply redirects to the general purpose routine
128205b308e1df6d9d673daedb517969241f41278b52Brett Russ *      if command is not DMA.  Else, it handles prep of the CRQB
128305b308e1df6d9d673daedb517969241f41278b52Brett Russ *      (command request block), does some sanity checking, and calls
128405b308e1df6d9d673daedb517969241f41278b52Brett Russ *      the SG load routine.
128505b308e1df6d9d673daedb517969241f41278b52Brett Russ *
128605b308e1df6d9d673daedb517969241f41278b52Brett Russ *      LOCKING:
128705b308e1df6d9d673daedb517969241f41278b52Brett Russ *      Inherited from caller.
128805b308e1df6d9d673daedb517969241f41278b52Brett Russ */
128931961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russstatic void mv_qc_prep(struct ata_queued_cmd *qc)
129031961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ{
129131961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ	struct ata_port *ap = qc->ap;
129231961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ	struct mv_port_priv *pp = ap->private_data;
1293e14698745dd0de1ddbf5cd0cca4313a90f8c1cc1Mark Lord	__le16 *cw;
129431961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ	struct ata_taskfile *tf;
129531961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ	u16 flags = 0;
1296a6432436c5e14b416f27c8f87c5bf0bc36771f49Mark Lord	unsigned in_index;
129731961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ
12982dcb407e61458ded17503d6bd12b8c064965368bJeff Garzik	if (qc->tf.protocol != ATA_PROT_DMA)
129931961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ		return;
130020f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ
130131961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ	/* Fill in command request block
130231961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ	 */
1303e4e7b89280d1d666e2c09e5ad36cf071796c4c7eJeff Garzik	if (!(qc->tf.flags & ATA_TFLAG_WRITE))
130431961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ		flags |= CRQB_FLAG_READ;
1305beec7dbc6ff003bbc94de62b3323519c878fb2acTejun Heo	WARN_ON(MV_MAX_Q_DEPTH <= qc->tag);
130631961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ	flags |= qc->tag << CRQB_TAG_SHIFT;
130731961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ
1308bdd4dddee325a7dce3e84cf48201a06aa8508aa4Jeff Garzik	/* get current queue index from software */
1309bdd4dddee325a7dce3e84cf48201a06aa8508aa4Jeff Garzik	in_index = pp->req_idx & MV_MAX_Q_DEPTH_MASK;
1310a6432436c5e14b416f27c8f87c5bf0bc36771f49Mark Lord
1311a6432436c5e14b416f27c8f87c5bf0bc36771f49Mark Lord	pp->crqb[in_index].sg_addr =
1312eb73d558d1c1c931de0b3a86af962c77d74ef688Mark Lord		cpu_to_le32(pp->sg_tbl_dma[qc->tag] & 0xffffffff);
1313a6432436c5e14b416f27c8f87c5bf0bc36771f49Mark Lord	pp->crqb[in_index].sg_addr_hi =
1314eb73d558d1c1c931de0b3a86af962c77d74ef688Mark Lord		cpu_to_le32((pp->sg_tbl_dma[qc->tag] >> 16) >> 16);
1315a6432436c5e14b416f27c8f87c5bf0bc36771f49Mark Lord	pp->crqb[in_index].ctrl_flags = cpu_to_le16(flags);
131631961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ
1317a6432436c5e14b416f27c8f87c5bf0bc36771f49Mark Lord	cw = &pp->crqb[in_index].ata_cmd[0];
131831961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ	tf = &qc->tf;
131931961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ
132031961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ	/* Sadly, the CRQB cannot accomodate all registers--there are
132131961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ	 * only 11 bytes...so we must pick and choose required
132231961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ	 * registers based on the command.  So, we drop feature and
132331961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ	 * hob_feature for [RW] DMA commands, but they are needed for
132431961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ	 * NCQ.  NCQ will drop hob_nsect.
132520f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ	 */
132631961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ	switch (tf->command) {
132731961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ	case ATA_CMD_READ:
132831961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ	case ATA_CMD_READ_EXT:
132931961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ	case ATA_CMD_WRITE:
133031961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ	case ATA_CMD_WRITE_EXT:
1331c15d85c8f3f73b5f20aae7928e25b6996f16b328Jens Axboe	case ATA_CMD_WRITE_FUA_EXT:
133231961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ		mv_crqb_pack_cmd(cw++, tf->hob_nsect, ATA_REG_NSECT, 0);
133331961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ		break;
133431961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ#ifdef LIBATA_NCQ		/* FIXME: remove this line when NCQ added */
133531961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ	case ATA_CMD_FPDMA_READ:
133631961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ	case ATA_CMD_FPDMA_WRITE:
13378b260248d9e0e8b64bb72fd4dee03ad86984c344Jeff Garzik		mv_crqb_pack_cmd(cw++, tf->hob_feature, ATA_REG_FEATURE, 0);
133831961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ		mv_crqb_pack_cmd(cw++, tf->feature, ATA_REG_FEATURE, 0);
133931961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ		break;
134031961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ#endif				/* FIXME: remove this line when NCQ added */
134131961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ	default:
134231961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ		/* The only other commands EDMA supports in non-queued and
134331961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ		 * non-NCQ mode are: [RW] STREAM DMA and W DMA FUA EXT, none
134431961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ		 * of which are defined/used by Linux.  If we get here, this
134531961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ		 * driver needs work.
134631961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ		 *
134731961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ		 * FIXME: modify libata to give qc_prep a return value and
134831961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ		 * return error here.
134931961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ		 */
135031961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ		BUG_ON(tf->command);
135131961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ		break;
135231961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ	}
135331961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ	mv_crqb_pack_cmd(cw++, tf->nsect, ATA_REG_NSECT, 0);
135431961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ	mv_crqb_pack_cmd(cw++, tf->hob_lbal, ATA_REG_LBAL, 0);
135531961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ	mv_crqb_pack_cmd(cw++, tf->lbal, ATA_REG_LBAL, 0);
135631961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ	mv_crqb_pack_cmd(cw++, tf->hob_lbam, ATA_REG_LBAM, 0);
135731961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ	mv_crqb_pack_cmd(cw++, tf->lbam, ATA_REG_LBAM, 0);
135831961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ	mv_crqb_pack_cmd(cw++, tf->hob_lbah, ATA_REG_LBAH, 0);
135931961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ	mv_crqb_pack_cmd(cw++, tf->lbah, ATA_REG_LBAH, 0);
136031961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ	mv_crqb_pack_cmd(cw++, tf->device, ATA_REG_DEVICE, 0);
136131961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ	mv_crqb_pack_cmd(cw++, tf->command, ATA_REG_CMD, 1);	/* last */
136231961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ
1363e4e7b89280d1d666e2c09e5ad36cf071796c4c7eJeff Garzik	if (!(qc->flags & ATA_QCFLAG_DMAMAP))
1364e4e7b89280d1d666e2c09e5ad36cf071796c4c7eJeff Garzik		return;
1365e4e7b89280d1d666e2c09e5ad36cf071796c4c7eJeff Garzik	mv_fill_sg(qc);
1366e4e7b89280d1d666e2c09e5ad36cf071796c4c7eJeff Garzik}
1367e4e7b89280d1d666e2c09e5ad36cf071796c4c7eJeff Garzik
1368e4e7b89280d1d666e2c09e5ad36cf071796c4c7eJeff Garzik/**
1369e4e7b89280d1d666e2c09e5ad36cf071796c4c7eJeff Garzik *      mv_qc_prep_iie - Host specific command preparation.
1370e4e7b89280d1d666e2c09e5ad36cf071796c4c7eJeff Garzik *      @qc: queued command to prepare
1371e4e7b89280d1d666e2c09e5ad36cf071796c4c7eJeff Garzik *
1372e4e7b89280d1d666e2c09e5ad36cf071796c4c7eJeff Garzik *      This routine simply redirects to the general purpose routine
1373e4e7b89280d1d666e2c09e5ad36cf071796c4c7eJeff Garzik *      if command is not DMA.  Else, it handles prep of the CRQB
1374e4e7b89280d1d666e2c09e5ad36cf071796c4c7eJeff Garzik *      (command request block), does some sanity checking, and calls
1375e4e7b89280d1d666e2c09e5ad36cf071796c4c7eJeff Garzik *      the SG load routine.
1376e4e7b89280d1d666e2c09e5ad36cf071796c4c7eJeff Garzik *
1377e4e7b89280d1d666e2c09e5ad36cf071796c4c7eJeff Garzik *      LOCKING:
1378e4e7b89280d1d666e2c09e5ad36cf071796c4c7eJeff Garzik *      Inherited from caller.
1379e4e7b89280d1d666e2c09e5ad36cf071796c4c7eJeff Garzik */
1380e4e7b89280d1d666e2c09e5ad36cf071796c4c7eJeff Garzikstatic void mv_qc_prep_iie(struct ata_queued_cmd *qc)
1381e4e7b89280d1d666e2c09e5ad36cf071796c4c7eJeff Garzik{
1382e4e7b89280d1d666e2c09e5ad36cf071796c4c7eJeff Garzik	struct ata_port *ap = qc->ap;
1383e4e7b89280d1d666e2c09e5ad36cf071796c4c7eJeff Garzik	struct mv_port_priv *pp = ap->private_data;
1384e4e7b89280d1d666e2c09e5ad36cf071796c4c7eJeff Garzik	struct mv_crqb_iie *crqb;
1385e4e7b89280d1d666e2c09e5ad36cf071796c4c7eJeff Garzik	struct ata_taskfile *tf;
1386a6432436c5e14b416f27c8f87c5bf0bc36771f49Mark Lord	unsigned in_index;
1387e4e7b89280d1d666e2c09e5ad36cf071796c4c7eJeff Garzik	u32 flags = 0;
1388e4e7b89280d1d666e2c09e5ad36cf071796c4c7eJeff Garzik
13892dcb407e61458ded17503d6bd12b8c064965368bJeff Garzik	if (qc->tf.protocol != ATA_PROT_DMA)
1390e4e7b89280d1d666e2c09e5ad36cf071796c4c7eJeff Garzik		return;
1391e4e7b89280d1d666e2c09e5ad36cf071796c4c7eJeff Garzik
1392e4e7b89280d1d666e2c09e5ad36cf071796c4c7eJeff Garzik	/* Fill in Gen IIE command request block
1393e4e7b89280d1d666e2c09e5ad36cf071796c4c7eJeff Garzik	 */
1394e4e7b89280d1d666e2c09e5ad36cf071796c4c7eJeff Garzik	if (!(qc->tf.flags & ATA_TFLAG_WRITE))
1395e4e7b89280d1d666e2c09e5ad36cf071796c4c7eJeff Garzik		flags |= CRQB_FLAG_READ;
1396e4e7b89280d1d666e2c09e5ad36cf071796c4c7eJeff Garzik
1397beec7dbc6ff003bbc94de62b3323519c878fb2acTejun Heo	WARN_ON(MV_MAX_Q_DEPTH <= qc->tag);
1398e4e7b89280d1d666e2c09e5ad36cf071796c4c7eJeff Garzik	flags |= qc->tag << CRQB_TAG_SHIFT;
13998c0aeb4a483334613336ef895f34cecc0ecbbfa6Mark Lord	flags |= qc->tag << CRQB_HOSTQ_SHIFT;
1400e4e7b89280d1d666e2c09e5ad36cf071796c4c7eJeff Garzik
1401bdd4dddee325a7dce3e84cf48201a06aa8508aa4Jeff Garzik	/* get current queue index from software */
1402bdd4dddee325a7dce3e84cf48201a06aa8508aa4Jeff Garzik	in_index = pp->req_idx & MV_MAX_Q_DEPTH_MASK;
1403a6432436c5e14b416f27c8f87c5bf0bc36771f49Mark Lord
1404a6432436c5e14b416f27c8f87c5bf0bc36771f49Mark Lord	crqb = (struct mv_crqb_iie *) &pp->crqb[in_index];
1405eb73d558d1c1c931de0b3a86af962c77d74ef688Mark Lord	crqb->addr = cpu_to_le32(pp->sg_tbl_dma[qc->tag] & 0xffffffff);
1406eb73d558d1c1c931de0b3a86af962c77d74ef688Mark Lord	crqb->addr_hi = cpu_to_le32((pp->sg_tbl_dma[qc->tag] >> 16) >> 16);
1407e4e7b89280d1d666e2c09e5ad36cf071796c4c7eJeff Garzik	crqb->flags = cpu_to_le32(flags);
1408e4e7b89280d1d666e2c09e5ad36cf071796c4c7eJeff Garzik
1409e4e7b89280d1d666e2c09e5ad36cf071796c4c7eJeff Garzik	tf = &qc->tf;
1410e4e7b89280d1d666e2c09e5ad36cf071796c4c7eJeff Garzik	crqb->ata_cmd[0] = cpu_to_le32(
1411e4e7b89280d1d666e2c09e5ad36cf071796c4c7eJeff Garzik			(tf->command << 16) |
1412e4e7b89280d1d666e2c09e5ad36cf071796c4c7eJeff Garzik			(tf->feature << 24)
1413e4e7b89280d1d666e2c09e5ad36cf071796c4c7eJeff Garzik		);
1414e4e7b89280d1d666e2c09e5ad36cf071796c4c7eJeff Garzik	crqb->ata_cmd[1] = cpu_to_le32(
1415e4e7b89280d1d666e2c09e5ad36cf071796c4c7eJeff Garzik			(tf->lbal << 0) |
1416e4e7b89280d1d666e2c09e5ad36cf071796c4c7eJeff Garzik			(tf->lbam << 8) |
1417e4e7b89280d1d666e2c09e5ad36cf071796c4c7eJeff Garzik			(tf->lbah << 16) |
1418e4e7b89280d1d666e2c09e5ad36cf071796c4c7eJeff Garzik			(tf->device << 24)
1419e4e7b89280d1d666e2c09e5ad36cf071796c4c7eJeff Garzik		);
1420e4e7b89280d1d666e2c09e5ad36cf071796c4c7eJeff Garzik	crqb->ata_cmd[2] = cpu_to_le32(
1421e4e7b89280d1d666e2c09e5ad36cf071796c4c7eJeff Garzik			(tf->hob_lbal << 0) |
1422e4e7b89280d1d666e2c09e5ad36cf071796c4c7eJeff Garzik			(tf->hob_lbam << 8) |
1423e4e7b89280d1d666e2c09e5ad36cf071796c4c7eJeff Garzik			(tf->hob_lbah << 16) |
1424e4e7b89280d1d666e2c09e5ad36cf071796c4c7eJeff Garzik			(tf->hob_feature << 24)
1425e4e7b89280d1d666e2c09e5ad36cf071796c4c7eJeff Garzik		);
1426e4e7b89280d1d666e2c09e5ad36cf071796c4c7eJeff Garzik	crqb->ata_cmd[3] = cpu_to_le32(
1427e4e7b89280d1d666e2c09e5ad36cf071796c4c7eJeff Garzik			(tf->nsect << 0) |
1428e4e7b89280d1d666e2c09e5ad36cf071796c4c7eJeff Garzik			(tf->hob_nsect << 8)
1429e4e7b89280d1d666e2c09e5ad36cf071796c4c7eJeff Garzik		);
1430e4e7b89280d1d666e2c09e5ad36cf071796c4c7eJeff Garzik
1431e4e7b89280d1d666e2c09e5ad36cf071796c4c7eJeff Garzik	if (!(qc->flags & ATA_QCFLAG_DMAMAP))
143231961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ		return;
143331961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ	mv_fill_sg(qc);
143431961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ}
143531961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ
143605b308e1df6d9d673daedb517969241f41278b52Brett Russ/**
143705b308e1df6d9d673daedb517969241f41278b52Brett Russ *      mv_qc_issue - Initiate a command to the host
143805b308e1df6d9d673daedb517969241f41278b52Brett Russ *      @qc: queued command to start
143905b308e1df6d9d673daedb517969241f41278b52Brett Russ *
144005b308e1df6d9d673daedb517969241f41278b52Brett Russ *      This routine simply redirects to the general purpose routine
144105b308e1df6d9d673daedb517969241f41278b52Brett Russ *      if command is not DMA.  Else, it sanity checks our local
144205b308e1df6d9d673daedb517969241f41278b52Brett Russ *      caches of the request producer/consumer indices then enables
144305b308e1df6d9d673daedb517969241f41278b52Brett Russ *      DMA and bumps the request producer index.
144405b308e1df6d9d673daedb517969241f41278b52Brett Russ *
144505b308e1df6d9d673daedb517969241f41278b52Brett Russ *      LOCKING:
144605b308e1df6d9d673daedb517969241f41278b52Brett Russ *      Inherited from caller.
144705b308e1df6d9d673daedb517969241f41278b52Brett Russ */
14489a3d9eb0177eb10500d49cd283b35576082a522dTejun Heostatic unsigned int mv_qc_issue(struct ata_queued_cmd *qc)
144931961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ{
1450c5d3e45a2200a0905dc45b72714726b7aac3aaf1Jeff Garzik	struct ata_port *ap = qc->ap;
1451c5d3e45a2200a0905dc45b72714726b7aac3aaf1Jeff Garzik	void __iomem *port_mmio = mv_ap_base(ap);
1452c5d3e45a2200a0905dc45b72714726b7aac3aaf1Jeff Garzik	struct mv_port_priv *pp = ap->private_data;
1453bdd4dddee325a7dce3e84cf48201a06aa8508aa4Jeff Garzik	u32 in_index;
145431961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ
1455c5d3e45a2200a0905dc45b72714726b7aac3aaf1Jeff Garzik	if (qc->tf.protocol != ATA_PROT_DMA) {
145631961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ		/* We're about to send a non-EDMA capable command to the
145731961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ		 * port.  Turn off EDMA so there won't be problems accessing
145831961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ		 * shadow block, etc registers.
145931961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ		 */
14600ea9e179f436f153fc19fdaef7abbc1e0da20762Jeff Garzik		__mv_stop_dma(ap);
146131961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ		return ata_qc_issue_prot(qc);
146231961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ	}
146331961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ
1464721091685f853ba4e6c49f26f989db0b1a811250Mark Lord	mv_start_dma(ap, port_mmio, pp, qc->tf.protocol);
1465bdd4dddee325a7dce3e84cf48201a06aa8508aa4Jeff Garzik
1466bdd4dddee325a7dce3e84cf48201a06aa8508aa4Jeff Garzik	in_index = pp->req_idx & MV_MAX_Q_DEPTH_MASK;
146731961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ
146831961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ	/* until we do queuing, the queue should be empty at this point */
1469a6432436c5e14b416f27c8f87c5bf0bc36771f49Mark Lord	WARN_ON(in_index != ((readl(port_mmio + EDMA_REQ_Q_OUT_PTR_OFS)
1470a6432436c5e14b416f27c8f87c5bf0bc36771f49Mark Lord		>> EDMA_REQ_Q_PTR_SHIFT) & MV_MAX_Q_DEPTH_MASK));
147131961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ
1472bdd4dddee325a7dce3e84cf48201a06aa8508aa4Jeff Garzik	pp->req_idx++;
147331961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ
1474bdd4dddee325a7dce3e84cf48201a06aa8508aa4Jeff Garzik	in_index = (pp->req_idx & MV_MAX_Q_DEPTH_MASK) << EDMA_REQ_Q_PTR_SHIFT;
147531961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ
147631961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ	/* and write the request in pointer to kick the EDMA to life */
1477bdd4dddee325a7dce3e84cf48201a06aa8508aa4Jeff Garzik	writelfl((pp->crqb_dma & EDMA_REQ_Q_BASE_LO_MASK) | in_index,
1478bdd4dddee325a7dce3e84cf48201a06aa8508aa4Jeff Garzik		 port_mmio + EDMA_REQ_Q_IN_PTR_OFS);
147931961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ
148031961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ	return 0;
148131961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ}
148231961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ
148305b308e1df6d9d673daedb517969241f41278b52Brett Russ/**
148405b308e1df6d9d673daedb517969241f41278b52Brett Russ *      mv_err_intr - Handle error interrupts on the port
148505b308e1df6d9d673daedb517969241f41278b52Brett Russ *      @ap: ATA channel to manipulate
14869b358e305c1d783c8a4ebf00344e95deb9e38f3dMark Lord *      @reset_allowed: bool: 0 == don't trigger from reset here
148705b308e1df6d9d673daedb517969241f41278b52Brett Russ *
148805b308e1df6d9d673daedb517969241f41278b52Brett Russ *      In most cases, just clear the interrupt and move on.  However,
148905b308e1df6d9d673daedb517969241f41278b52Brett Russ *      some cases require an eDMA reset, which is done right before
149005b308e1df6d9d673daedb517969241f41278b52Brett Russ *      the COMRESET in mv_phy_reset().  The SERR case requires a
149105b308e1df6d9d673daedb517969241f41278b52Brett Russ *      clear of pending errors in the SATA SERROR register.  Finally,
149205b308e1df6d9d673daedb517969241f41278b52Brett Russ *      if the port disabled DMA, update our cached copy to match.
149305b308e1df6d9d673daedb517969241f41278b52Brett Russ *
149405b308e1df6d9d673daedb517969241f41278b52Brett Russ *      LOCKING:
149505b308e1df6d9d673daedb517969241f41278b52Brett Russ *      Inherited from caller.
149605b308e1df6d9d673daedb517969241f41278b52Brett Russ */
1497bdd4dddee325a7dce3e84cf48201a06aa8508aa4Jeff Garzikstatic void mv_err_intr(struct ata_port *ap, struct ata_queued_cmd *qc)
149831961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ{
149931961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ	void __iomem *port_mmio = mv_ap_base(ap);
1500bdd4dddee325a7dce3e84cf48201a06aa8508aa4Jeff Garzik	u32 edma_err_cause, eh_freeze_mask, serr = 0;
1501bdd4dddee325a7dce3e84cf48201a06aa8508aa4Jeff Garzik	struct mv_port_priv *pp = ap->private_data;
1502bdd4dddee325a7dce3e84cf48201a06aa8508aa4Jeff Garzik	struct mv_host_priv *hpriv = ap->host->private_data;
1503bdd4dddee325a7dce3e84cf48201a06aa8508aa4Jeff Garzik	unsigned int edma_enabled = (pp->pp_flags & MV_PP_FLAG_EDMA_EN);
1504bdd4dddee325a7dce3e84cf48201a06aa8508aa4Jeff Garzik	unsigned int action = 0, err_mask = 0;
15059af5c9c97dc9d599281778864c72b385f0c63341Tejun Heo	struct ata_eh_info *ehi = &ap->link.eh_info;
150620f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ
1507bdd4dddee325a7dce3e84cf48201a06aa8508aa4Jeff Garzik	ata_ehi_clear_desc(ehi);
150820f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ
1509bdd4dddee325a7dce3e84cf48201a06aa8508aa4Jeff Garzik	if (!edma_enabled) {
1510bdd4dddee325a7dce3e84cf48201a06aa8508aa4Jeff Garzik		/* just a guess: do we need to do this? should we
1511bdd4dddee325a7dce3e84cf48201a06aa8508aa4Jeff Garzik		 * expand this, and do it in all cases?
1512bdd4dddee325a7dce3e84cf48201a06aa8508aa4Jeff Garzik		 */
1513936fd7328657884d5a69a55666c74a55aa83ca27Tejun Heo		sata_scr_read(&ap->link, SCR_ERROR, &serr);
1514936fd7328657884d5a69a55666c74a55aa83ca27Tejun Heo		sata_scr_write_flush(&ap->link, SCR_ERROR, serr);
151520f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ	}
1516bdd4dddee325a7dce3e84cf48201a06aa8508aa4Jeff Garzik
1517bdd4dddee325a7dce3e84cf48201a06aa8508aa4Jeff Garzik	edma_err_cause = readl(port_mmio + EDMA_ERR_IRQ_CAUSE_OFS);
1518bdd4dddee325a7dce3e84cf48201a06aa8508aa4Jeff Garzik
1519bdd4dddee325a7dce3e84cf48201a06aa8508aa4Jeff Garzik	ata_ehi_push_desc(ehi, "edma_err 0x%08x", edma_err_cause);
1520bdd4dddee325a7dce3e84cf48201a06aa8508aa4Jeff Garzik
1521bdd4dddee325a7dce3e84cf48201a06aa8508aa4Jeff Garzik	/*
1522bdd4dddee325a7dce3e84cf48201a06aa8508aa4Jeff Garzik	 * all generations share these EDMA error cause bits
1523bdd4dddee325a7dce3e84cf48201a06aa8508aa4Jeff Garzik	 */
1524bdd4dddee325a7dce3e84cf48201a06aa8508aa4Jeff Garzik
1525bdd4dddee325a7dce3e84cf48201a06aa8508aa4Jeff Garzik	if (edma_err_cause & EDMA_ERR_DEV)
1526bdd4dddee325a7dce3e84cf48201a06aa8508aa4Jeff Garzik		err_mask |= AC_ERR_DEV;
1527bdd4dddee325a7dce3e84cf48201a06aa8508aa4Jeff Garzik	if (edma_err_cause & (EDMA_ERR_D_PAR | EDMA_ERR_PRD_PAR |
15286c1153e00af8de755ec278d873a97c9ce2a72d10Jeff Garzik			EDMA_ERR_CRQB_PAR | EDMA_ERR_CRPB_PAR |
1529bdd4dddee325a7dce3e84cf48201a06aa8508aa4Jeff Garzik			EDMA_ERR_INTRL_PAR)) {
1530bdd4dddee325a7dce3e84cf48201a06aa8508aa4Jeff Garzik		err_mask |= AC_ERR_ATA_BUS;
1531bdd4dddee325a7dce3e84cf48201a06aa8508aa4Jeff Garzik		action |= ATA_EH_HARDRESET;
1532b64bbc39f2122a2276578e40144af69ef01decd4Tejun Heo		ata_ehi_push_desc(ehi, "parity error");
1533bdd4dddee325a7dce3e84cf48201a06aa8508aa4Jeff Garzik	}
1534bdd4dddee325a7dce3e84cf48201a06aa8508aa4Jeff Garzik	if (edma_err_cause & (EDMA_ERR_DEV_DCON | EDMA_ERR_DEV_CON)) {
1535bdd4dddee325a7dce3e84cf48201a06aa8508aa4Jeff Garzik		ata_ehi_hotplugged(ehi);
1536bdd4dddee325a7dce3e84cf48201a06aa8508aa4Jeff Garzik		ata_ehi_push_desc(ehi, edma_err_cause & EDMA_ERR_DEV_DCON ?
1537b64bbc39f2122a2276578e40144af69ef01decd4Tejun Heo			"dev disconnect" : "dev connect");
15383606a380692cf958355a40fc1aa336800c17baf1Mark Lord		action |= ATA_EH_HARDRESET;
1539bdd4dddee325a7dce3e84cf48201a06aa8508aa4Jeff Garzik	}
1540bdd4dddee325a7dce3e84cf48201a06aa8508aa4Jeff Garzik
1541ee9ccdf70163ca6408f6965e0fbc65baeac7312cJeff Garzik	if (IS_GEN_I(hpriv)) {
1542bdd4dddee325a7dce3e84cf48201a06aa8508aa4Jeff Garzik		eh_freeze_mask = EDMA_EH_FREEZE_5;
1543bdd4dddee325a7dce3e84cf48201a06aa8508aa4Jeff Garzik
1544bdd4dddee325a7dce3e84cf48201a06aa8508aa4Jeff Garzik		if (edma_err_cause & EDMA_ERR_SELF_DIS_5) {
1545bdd4dddee325a7dce3e84cf48201a06aa8508aa4Jeff Garzik			struct mv_port_priv *pp	= ap->private_data;
1546bdd4dddee325a7dce3e84cf48201a06aa8508aa4Jeff Garzik			pp->pp_flags &= ~MV_PP_FLAG_EDMA_EN;
1547b64bbc39f2122a2276578e40144af69ef01decd4Tejun Heo			ata_ehi_push_desc(ehi, "EDMA self-disable");
1548bdd4dddee325a7dce3e84cf48201a06aa8508aa4Jeff Garzik		}
1549bdd4dddee325a7dce3e84cf48201a06aa8508aa4Jeff Garzik	} else {
1550bdd4dddee325a7dce3e84cf48201a06aa8508aa4Jeff Garzik		eh_freeze_mask = EDMA_EH_FREEZE;
1551bdd4dddee325a7dce3e84cf48201a06aa8508aa4Jeff Garzik
1552bdd4dddee325a7dce3e84cf48201a06aa8508aa4Jeff Garzik		if (edma_err_cause & EDMA_ERR_SELF_DIS) {
1553bdd4dddee325a7dce3e84cf48201a06aa8508aa4Jeff Garzik			struct mv_port_priv *pp	= ap->private_data;
1554bdd4dddee325a7dce3e84cf48201a06aa8508aa4Jeff Garzik			pp->pp_flags &= ~MV_PP_FLAG_EDMA_EN;
1555b64bbc39f2122a2276578e40144af69ef01decd4Tejun Heo			ata_ehi_push_desc(ehi, "EDMA self-disable");
1556bdd4dddee325a7dce3e84cf48201a06aa8508aa4Jeff Garzik		}
1557bdd4dddee325a7dce3e84cf48201a06aa8508aa4Jeff Garzik
1558bdd4dddee325a7dce3e84cf48201a06aa8508aa4Jeff Garzik		if (edma_err_cause & EDMA_ERR_SERR) {
1559936fd7328657884d5a69a55666c74a55aa83ca27Tejun Heo			sata_scr_read(&ap->link, SCR_ERROR, &serr);
1560936fd7328657884d5a69a55666c74a55aa83ca27Tejun Heo			sata_scr_write_flush(&ap->link, SCR_ERROR, serr);
1561bdd4dddee325a7dce3e84cf48201a06aa8508aa4Jeff Garzik			err_mask = AC_ERR_ATA_BUS;
1562bdd4dddee325a7dce3e84cf48201a06aa8508aa4Jeff Garzik			action |= ATA_EH_HARDRESET;
1563bdd4dddee325a7dce3e84cf48201a06aa8508aa4Jeff Garzik		}
1564afb0edd922c7ed6e73678730921dfcccebec17e8Brett Russ	}
156520f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ
156620f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ	/* Clear EDMA now that SERR cleanup done */
15673606a380692cf958355a40fc1aa336800c17baf1Mark Lord	writelfl(~edma_err_cause, port_mmio + EDMA_ERR_IRQ_CAUSE_OFS);
156820f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ
1569bdd4dddee325a7dce3e84cf48201a06aa8508aa4Jeff Garzik	if (!err_mask) {
1570bdd4dddee325a7dce3e84cf48201a06aa8508aa4Jeff Garzik		err_mask = AC_ERR_OTHER;
1571bdd4dddee325a7dce3e84cf48201a06aa8508aa4Jeff Garzik		action |= ATA_EH_HARDRESET;
1572bdd4dddee325a7dce3e84cf48201a06aa8508aa4Jeff Garzik	}
1573bdd4dddee325a7dce3e84cf48201a06aa8508aa4Jeff Garzik
1574bdd4dddee325a7dce3e84cf48201a06aa8508aa4Jeff Garzik	ehi->serror |= serr;
1575bdd4dddee325a7dce3e84cf48201a06aa8508aa4Jeff Garzik	ehi->action |= action;
1576bdd4dddee325a7dce3e84cf48201a06aa8508aa4Jeff Garzik
1577bdd4dddee325a7dce3e84cf48201a06aa8508aa4Jeff Garzik	if (qc)
1578bdd4dddee325a7dce3e84cf48201a06aa8508aa4Jeff Garzik		qc->err_mask |= err_mask;
1579bdd4dddee325a7dce3e84cf48201a06aa8508aa4Jeff Garzik	else
1580bdd4dddee325a7dce3e84cf48201a06aa8508aa4Jeff Garzik		ehi->err_mask |= err_mask;
1581bdd4dddee325a7dce3e84cf48201a06aa8508aa4Jeff Garzik
1582bdd4dddee325a7dce3e84cf48201a06aa8508aa4Jeff Garzik	if (edma_err_cause & eh_freeze_mask)
1583bdd4dddee325a7dce3e84cf48201a06aa8508aa4Jeff Garzik		ata_port_freeze(ap);
1584bdd4dddee325a7dce3e84cf48201a06aa8508aa4Jeff Garzik	else
1585bdd4dddee325a7dce3e84cf48201a06aa8508aa4Jeff Garzik		ata_port_abort(ap);
1586bdd4dddee325a7dce3e84cf48201a06aa8508aa4Jeff Garzik}
1587bdd4dddee325a7dce3e84cf48201a06aa8508aa4Jeff Garzik
1588bdd4dddee325a7dce3e84cf48201a06aa8508aa4Jeff Garzikstatic void mv_intr_pio(struct ata_port *ap)
1589bdd4dddee325a7dce3e84cf48201a06aa8508aa4Jeff Garzik{
1590bdd4dddee325a7dce3e84cf48201a06aa8508aa4Jeff Garzik	struct ata_queued_cmd *qc;
1591bdd4dddee325a7dce3e84cf48201a06aa8508aa4Jeff Garzik	u8 ata_status;
1592bdd4dddee325a7dce3e84cf48201a06aa8508aa4Jeff Garzik
1593bdd4dddee325a7dce3e84cf48201a06aa8508aa4Jeff Garzik	/* ignore spurious intr if drive still BUSY */
1594bdd4dddee325a7dce3e84cf48201a06aa8508aa4Jeff Garzik	ata_status = readb(ap->ioaddr.status_addr);
1595bdd4dddee325a7dce3e84cf48201a06aa8508aa4Jeff Garzik	if (unlikely(ata_status & ATA_BUSY))
1596bdd4dddee325a7dce3e84cf48201a06aa8508aa4Jeff Garzik		return;
1597bdd4dddee325a7dce3e84cf48201a06aa8508aa4Jeff Garzik
1598bdd4dddee325a7dce3e84cf48201a06aa8508aa4Jeff Garzik	/* get active ATA command */
15999af5c9c97dc9d599281778864c72b385f0c63341Tejun Heo	qc = ata_qc_from_tag(ap, ap->link.active_tag);
1600bdd4dddee325a7dce3e84cf48201a06aa8508aa4Jeff Garzik	if (unlikely(!qc))			/* no active tag */
1601bdd4dddee325a7dce3e84cf48201a06aa8508aa4Jeff Garzik		return;
1602bdd4dddee325a7dce3e84cf48201a06aa8508aa4Jeff Garzik	if (qc->tf.flags & ATA_TFLAG_POLLING)	/* polling; we don't own qc */
1603bdd4dddee325a7dce3e84cf48201a06aa8508aa4Jeff Garzik		return;
1604bdd4dddee325a7dce3e84cf48201a06aa8508aa4Jeff Garzik
1605bdd4dddee325a7dce3e84cf48201a06aa8508aa4Jeff Garzik	/* and finally, complete the ATA command */
1606bdd4dddee325a7dce3e84cf48201a06aa8508aa4Jeff Garzik	qc->err_mask |= ac_err_mask(ata_status);
1607bdd4dddee325a7dce3e84cf48201a06aa8508aa4Jeff Garzik	ata_qc_complete(qc);
1608bdd4dddee325a7dce3e84cf48201a06aa8508aa4Jeff Garzik}
1609bdd4dddee325a7dce3e84cf48201a06aa8508aa4Jeff Garzik
1610bdd4dddee325a7dce3e84cf48201a06aa8508aa4Jeff Garzikstatic void mv_intr_edma(struct ata_port *ap)
1611bdd4dddee325a7dce3e84cf48201a06aa8508aa4Jeff Garzik{
1612bdd4dddee325a7dce3e84cf48201a06aa8508aa4Jeff Garzik	void __iomem *port_mmio = mv_ap_base(ap);
1613bdd4dddee325a7dce3e84cf48201a06aa8508aa4Jeff Garzik	struct mv_host_priv *hpriv = ap->host->private_data;
1614bdd4dddee325a7dce3e84cf48201a06aa8508aa4Jeff Garzik	struct mv_port_priv *pp = ap->private_data;
1615bdd4dddee325a7dce3e84cf48201a06aa8508aa4Jeff Garzik	struct ata_queued_cmd *qc;
1616bdd4dddee325a7dce3e84cf48201a06aa8508aa4Jeff Garzik	u32 out_index, in_index;
1617bdd4dddee325a7dce3e84cf48201a06aa8508aa4Jeff Garzik	bool work_done = false;
1618bdd4dddee325a7dce3e84cf48201a06aa8508aa4Jeff Garzik
1619bdd4dddee325a7dce3e84cf48201a06aa8508aa4Jeff Garzik	/* get h/w response queue pointer */
1620bdd4dddee325a7dce3e84cf48201a06aa8508aa4Jeff Garzik	in_index = (readl(port_mmio + EDMA_RSP_Q_IN_PTR_OFS)
1621bdd4dddee325a7dce3e84cf48201a06aa8508aa4Jeff Garzik			>> EDMA_RSP_Q_PTR_SHIFT) & MV_MAX_Q_DEPTH_MASK;
1622bdd4dddee325a7dce3e84cf48201a06aa8508aa4Jeff Garzik
1623bdd4dddee325a7dce3e84cf48201a06aa8508aa4Jeff Garzik	while (1) {
1624bdd4dddee325a7dce3e84cf48201a06aa8508aa4Jeff Garzik		u16 status;
16256c1153e00af8de755ec278d873a97c9ce2a72d10Jeff Garzik		unsigned int tag;
1626bdd4dddee325a7dce3e84cf48201a06aa8508aa4Jeff Garzik
1627bdd4dddee325a7dce3e84cf48201a06aa8508aa4Jeff Garzik		/* get s/w response queue last-read pointer, and compare */
1628bdd4dddee325a7dce3e84cf48201a06aa8508aa4Jeff Garzik		out_index = pp->resp_idx & MV_MAX_Q_DEPTH_MASK;
1629bdd4dddee325a7dce3e84cf48201a06aa8508aa4Jeff Garzik		if (in_index == out_index)
1630bdd4dddee325a7dce3e84cf48201a06aa8508aa4Jeff Garzik			break;
1631bdd4dddee325a7dce3e84cf48201a06aa8508aa4Jeff Garzik
1632bdd4dddee325a7dce3e84cf48201a06aa8508aa4Jeff Garzik		/* 50xx: get active ATA command */
16330ea9e179f436f153fc19fdaef7abbc1e0da20762Jeff Garzik		if (IS_GEN_I(hpriv))
16349af5c9c97dc9d599281778864c72b385f0c63341Tejun Heo			tag = ap->link.active_tag;
1635bdd4dddee325a7dce3e84cf48201a06aa8508aa4Jeff Garzik
16366c1153e00af8de755ec278d873a97c9ce2a72d10Jeff Garzik		/* Gen II/IIE: get active ATA command via tag, to enable
16376c1153e00af8de755ec278d873a97c9ce2a72d10Jeff Garzik		 * support for queueing.  this works transparently for
16386c1153e00af8de755ec278d873a97c9ce2a72d10Jeff Garzik		 * queued and non-queued modes.
1639bdd4dddee325a7dce3e84cf48201a06aa8508aa4Jeff Garzik		 */
16408c0aeb4a483334613336ef895f34cecc0ecbbfa6Mark Lord		else
16418c0aeb4a483334613336ef895f34cecc0ecbbfa6Mark Lord			tag = le16_to_cpu(pp->crpb[out_index].id) & 0x1f;
1642bdd4dddee325a7dce3e84cf48201a06aa8508aa4Jeff Garzik
16436c1153e00af8de755ec278d873a97c9ce2a72d10Jeff Garzik		qc = ata_qc_from_tag(ap, tag);
1644bdd4dddee325a7dce3e84cf48201a06aa8508aa4Jeff Garzik
1645cb92441973ebd71d556fc7cdd9e597582327dd71Mark Lord		/* For non-NCQ mode, the lower 8 bits of status
1646cb92441973ebd71d556fc7cdd9e597582327dd71Mark Lord		 * are from EDMA_ERR_IRQ_CAUSE_OFS,
1647cb92441973ebd71d556fc7cdd9e597582327dd71Mark Lord		 * which should be zero if all went well.
1648bdd4dddee325a7dce3e84cf48201a06aa8508aa4Jeff Garzik		 */
1649bdd4dddee325a7dce3e84cf48201a06aa8508aa4Jeff Garzik		status = le16_to_cpu(pp->crpb[out_index].flags);
1650cb92441973ebd71d556fc7cdd9e597582327dd71Mark Lord		if ((status & 0xff) && !(pp->pp_flags & MV_PP_FLAG_NCQ_EN)) {
1651bdd4dddee325a7dce3e84cf48201a06aa8508aa4Jeff Garzik			mv_err_intr(ap, qc);
1652bdd4dddee325a7dce3e84cf48201a06aa8508aa4Jeff Garzik			return;
1653bdd4dddee325a7dce3e84cf48201a06aa8508aa4Jeff Garzik		}
1654bdd4dddee325a7dce3e84cf48201a06aa8508aa4Jeff Garzik
1655bdd4dddee325a7dce3e84cf48201a06aa8508aa4Jeff Garzik		/* and finally, complete the ATA command */
1656bdd4dddee325a7dce3e84cf48201a06aa8508aa4Jeff Garzik		if (qc) {
1657bdd4dddee325a7dce3e84cf48201a06aa8508aa4Jeff Garzik			qc->err_mask |=
1658bdd4dddee325a7dce3e84cf48201a06aa8508aa4Jeff Garzik				ac_err_mask(status >> CRPB_FLAG_STATUS_SHIFT);
1659bdd4dddee325a7dce3e84cf48201a06aa8508aa4Jeff Garzik			ata_qc_complete(qc);
1660bdd4dddee325a7dce3e84cf48201a06aa8508aa4Jeff Garzik		}
1661bdd4dddee325a7dce3e84cf48201a06aa8508aa4Jeff Garzik
16620ea9e179f436f153fc19fdaef7abbc1e0da20762Jeff Garzik		/* advance software response queue pointer, to
1663bdd4dddee325a7dce3e84cf48201a06aa8508aa4Jeff Garzik		 * indicate (after the loop completes) to hardware
1664bdd4dddee325a7dce3e84cf48201a06aa8508aa4Jeff Garzik		 * that we have consumed a response queue entry.
1665bdd4dddee325a7dce3e84cf48201a06aa8508aa4Jeff Garzik		 */
1666bdd4dddee325a7dce3e84cf48201a06aa8508aa4Jeff Garzik		work_done = true;
1667bdd4dddee325a7dce3e84cf48201a06aa8508aa4Jeff Garzik		pp->resp_idx++;
1668bdd4dddee325a7dce3e84cf48201a06aa8508aa4Jeff Garzik	}
1669bdd4dddee325a7dce3e84cf48201a06aa8508aa4Jeff Garzik
1670bdd4dddee325a7dce3e84cf48201a06aa8508aa4Jeff Garzik	if (work_done)
1671bdd4dddee325a7dce3e84cf48201a06aa8508aa4Jeff Garzik		writelfl((pp->crpb_dma & EDMA_RSP_Q_BASE_LO_MASK) |
1672bdd4dddee325a7dce3e84cf48201a06aa8508aa4Jeff Garzik			 (out_index << EDMA_RSP_Q_PTR_SHIFT),
1673bdd4dddee325a7dce3e84cf48201a06aa8508aa4Jeff Garzik			 port_mmio + EDMA_RSP_Q_OUT_PTR_OFS);
167420f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ}
167520f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ
167605b308e1df6d9d673daedb517969241f41278b52Brett Russ/**
167705b308e1df6d9d673daedb517969241f41278b52Brett Russ *      mv_host_intr - Handle all interrupts on the given host controller
1678cca3974e48607c3775dc73b544a5700b2e37c21aJeff Garzik *      @host: host specific structure
167905b308e1df6d9d673daedb517969241f41278b52Brett Russ *      @relevant: port error bits relevant to this host controller
168005b308e1df6d9d673daedb517969241f41278b52Brett Russ *      @hc: which host controller we're to look at
168105b308e1df6d9d673daedb517969241f41278b52Brett Russ *
168205b308e1df6d9d673daedb517969241f41278b52Brett Russ *      Read then write clear the HC interrupt status then walk each
168305b308e1df6d9d673daedb517969241f41278b52Brett Russ *      port connected to the HC and see if it needs servicing.  Port
168405b308e1df6d9d673daedb517969241f41278b52Brett Russ *      success ints are reported in the HC interrupt status reg, the
168505b308e1df6d9d673daedb517969241f41278b52Brett Russ *      port error ints are reported in the higher level main
168605b308e1df6d9d673daedb517969241f41278b52Brett Russ *      interrupt status register and thus are passed in via the
168705b308e1df6d9d673daedb517969241f41278b52Brett Russ *      'relevant' argument.
168805b308e1df6d9d673daedb517969241f41278b52Brett Russ *
168905b308e1df6d9d673daedb517969241f41278b52Brett Russ *      LOCKING:
169005b308e1df6d9d673daedb517969241f41278b52Brett Russ *      Inherited from caller.
169105b308e1df6d9d673daedb517969241f41278b52Brett Russ */
1692cca3974e48607c3775dc73b544a5700b2e37c21aJeff Garzikstatic void mv_host_intr(struct ata_host *host, u32 relevant, unsigned int hc)
169320f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ{
16940d5ff566779f894ca9937231a181eb31e4adff0eTejun Heo	void __iomem *mmio = host->iomap[MV_PRIMARY_BAR];
169520f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ	void __iomem *hc_mmio = mv_hc_base(mmio, hc);
169620f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ	u32 hc_irq_cause;
1697c5d3e45a2200a0905dc45b72714726b7aac3aaf1Jeff Garzik	int port, port0;
169820f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ
1699351772658a4d1acc0221a6e30676bb0594e74812Jeff Garzik	if (hc == 0)
170020f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ		port0 = 0;
1701351772658a4d1acc0221a6e30676bb0594e74812Jeff Garzik	else
170220f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ		port0 = MV_PORTS_PER_HC;
170320f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ
170420f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ	/* we'll need the HC success int register in most cases */
170520f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ	hc_irq_cause = readl(hc_mmio + HC_IRQ_CAUSE_OFS);
1706bdd4dddee325a7dce3e84cf48201a06aa8508aa4Jeff Garzik	if (!hc_irq_cause)
1707bdd4dddee325a7dce3e84cf48201a06aa8508aa4Jeff Garzik		return;
1708bdd4dddee325a7dce3e84cf48201a06aa8508aa4Jeff Garzik
1709bdd4dddee325a7dce3e84cf48201a06aa8508aa4Jeff Garzik	writelfl(~hc_irq_cause, hc_mmio + HC_IRQ_CAUSE_OFS);
171020f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ
171120f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ	VPRINTK("ENTER, hc%u relevant=0x%08x HC IRQ cause=0x%08x\n",
17122dcb407e61458ded17503d6bd12b8c064965368bJeff Garzik		hc, relevant, hc_irq_cause);
171320f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ
171420f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ	for (port = port0; port < port0 + MV_PORTS_PER_HC; port++) {
1715cca3974e48607c3775dc73b544a5700b2e37c21aJeff Garzik		struct ata_port *ap = host->ports[port];
171663af2a5c5990d95f1e7d8795f1425fb976ea2b4bMark Lord		struct mv_port_priv *pp = ap->private_data;
1717bdd4dddee325a7dce3e84cf48201a06aa8508aa4Jeff Garzik		int have_err_bits, hard_port, shift;
171855d8ca4f8094246da6e71889a4e04bfafaa78b10Jeff Garzik
1719bdd4dddee325a7dce3e84cf48201a06aa8508aa4Jeff Garzik		if ((!ap) || (ap->flags & ATA_FLAG_DISABLED))
1720a2c91a8819e315e9fd1aef3ff57badb6c1be3f80Jeff Garzik			continue;
1721a2c91a8819e315e9fd1aef3ff57badb6c1be3f80Jeff Garzik
172231961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ		shift = port << 1;		/* (port * 2) */
172320f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ		if (port >= MV_PORTS_PER_HC) {
172420f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ			shift++;	/* skip bit 8 in the HC Main IRQ reg */
172520f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ		}
1726bdd4dddee325a7dce3e84cf48201a06aa8508aa4Jeff Garzik		have_err_bits = ((PORT0_ERR << shift) & relevant);
1727bdd4dddee325a7dce3e84cf48201a06aa8508aa4Jeff Garzik
1728bdd4dddee325a7dce3e84cf48201a06aa8508aa4Jeff Garzik		if (unlikely(have_err_bits)) {
1729bdd4dddee325a7dce3e84cf48201a06aa8508aa4Jeff Garzik			struct ata_queued_cmd *qc;
17308b260248d9e0e8b64bb72fd4dee03ad86984c344Jeff Garzik
17319af5c9c97dc9d599281778864c72b385f0c63341Tejun Heo			qc = ata_qc_from_tag(ap, ap->link.active_tag);
1732bdd4dddee325a7dce3e84cf48201a06aa8508aa4Jeff Garzik			if (qc && (qc->tf.flags & ATA_TFLAG_POLLING))
1733bdd4dddee325a7dce3e84cf48201a06aa8508aa4Jeff Garzik				continue;
1734bdd4dddee325a7dce3e84cf48201a06aa8508aa4Jeff Garzik
1735bdd4dddee325a7dce3e84cf48201a06aa8508aa4Jeff Garzik			mv_err_intr(ap, qc);
1736bdd4dddee325a7dce3e84cf48201a06aa8508aa4Jeff Garzik			continue;
1737bdd4dddee325a7dce3e84cf48201a06aa8508aa4Jeff Garzik		}
1738bdd4dddee325a7dce3e84cf48201a06aa8508aa4Jeff Garzik
1739bdd4dddee325a7dce3e84cf48201a06aa8508aa4Jeff Garzik		hard_port = mv_hardport_from_port(port); /* range 0..3 */
1740bdd4dddee325a7dce3e84cf48201a06aa8508aa4Jeff Garzik
1741bdd4dddee325a7dce3e84cf48201a06aa8508aa4Jeff Garzik		if (pp->pp_flags & MV_PP_FLAG_EDMA_EN) {
1742bdd4dddee325a7dce3e84cf48201a06aa8508aa4Jeff Garzik			if ((CRPB_DMA_DONE << hard_port) & hc_irq_cause)
1743bdd4dddee325a7dce3e84cf48201a06aa8508aa4Jeff Garzik				mv_intr_edma(ap);
1744bdd4dddee325a7dce3e84cf48201a06aa8508aa4Jeff Garzik		} else {
1745bdd4dddee325a7dce3e84cf48201a06aa8508aa4Jeff Garzik			if ((DEV_IRQ << hard_port) & hc_irq_cause)
1746bdd4dddee325a7dce3e84cf48201a06aa8508aa4Jeff Garzik				mv_intr_pio(ap);
174720f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ		}
174820f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ	}
174920f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ	VPRINTK("EXIT\n");
175020f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ}
175120f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ
1752bdd4dddee325a7dce3e84cf48201a06aa8508aa4Jeff Garzikstatic void mv_pci_error(struct ata_host *host, void __iomem *mmio)
1753bdd4dddee325a7dce3e84cf48201a06aa8508aa4Jeff Garzik{
175402a121da5a53d415b6596bc19cc6999d295d32a4Mark Lord	struct mv_host_priv *hpriv = host->private_data;
1755bdd4dddee325a7dce3e84cf48201a06aa8508aa4Jeff Garzik	struct ata_port *ap;
1756bdd4dddee325a7dce3e84cf48201a06aa8508aa4Jeff Garzik	struct ata_queued_cmd *qc;
1757bdd4dddee325a7dce3e84cf48201a06aa8508aa4Jeff Garzik	struct ata_eh_info *ehi;
1758bdd4dddee325a7dce3e84cf48201a06aa8508aa4Jeff Garzik	unsigned int i, err_mask, printed = 0;
1759bdd4dddee325a7dce3e84cf48201a06aa8508aa4Jeff Garzik	u32 err_cause;
1760bdd4dddee325a7dce3e84cf48201a06aa8508aa4Jeff Garzik
176102a121da5a53d415b6596bc19cc6999d295d32a4Mark Lord	err_cause = readl(mmio + hpriv->irq_cause_ofs);
1762bdd4dddee325a7dce3e84cf48201a06aa8508aa4Jeff Garzik
1763bdd4dddee325a7dce3e84cf48201a06aa8508aa4Jeff Garzik	dev_printk(KERN_ERR, host->dev, "PCI ERROR; PCI IRQ cause=0x%08x\n",
1764bdd4dddee325a7dce3e84cf48201a06aa8508aa4Jeff Garzik		   err_cause);
1765bdd4dddee325a7dce3e84cf48201a06aa8508aa4Jeff Garzik
1766bdd4dddee325a7dce3e84cf48201a06aa8508aa4Jeff Garzik	DPRINTK("All regs @ PCI error\n");
1767bdd4dddee325a7dce3e84cf48201a06aa8508aa4Jeff Garzik	mv_dump_all_regs(mmio, -1, to_pci_dev(host->dev));
1768bdd4dddee325a7dce3e84cf48201a06aa8508aa4Jeff Garzik
176902a121da5a53d415b6596bc19cc6999d295d32a4Mark Lord	writelfl(0, mmio + hpriv->irq_cause_ofs);
1770bdd4dddee325a7dce3e84cf48201a06aa8508aa4Jeff Garzik
1771bdd4dddee325a7dce3e84cf48201a06aa8508aa4Jeff Garzik	for (i = 0; i < host->n_ports; i++) {
1772bdd4dddee325a7dce3e84cf48201a06aa8508aa4Jeff Garzik		ap = host->ports[i];
1773936fd7328657884d5a69a55666c74a55aa83ca27Tejun Heo		if (!ata_link_offline(&ap->link)) {
17749af5c9c97dc9d599281778864c72b385f0c63341Tejun Heo			ehi = &ap->link.eh_info;
1775bdd4dddee325a7dce3e84cf48201a06aa8508aa4Jeff Garzik			ata_ehi_clear_desc(ehi);
1776bdd4dddee325a7dce3e84cf48201a06aa8508aa4Jeff Garzik			if (!printed++)
1777bdd4dddee325a7dce3e84cf48201a06aa8508aa4Jeff Garzik				ata_ehi_push_desc(ehi,
1778bdd4dddee325a7dce3e84cf48201a06aa8508aa4Jeff Garzik					"PCI err cause 0x%08x", err_cause);
1779bdd4dddee325a7dce3e84cf48201a06aa8508aa4Jeff Garzik			err_mask = AC_ERR_HOST_BUS;
1780bdd4dddee325a7dce3e84cf48201a06aa8508aa4Jeff Garzik			ehi->action = ATA_EH_HARDRESET;
17819af5c9c97dc9d599281778864c72b385f0c63341Tejun Heo			qc = ata_qc_from_tag(ap, ap->link.active_tag);
1782bdd4dddee325a7dce3e84cf48201a06aa8508aa4Jeff Garzik			if (qc)
1783bdd4dddee325a7dce3e84cf48201a06aa8508aa4Jeff Garzik				qc->err_mask |= err_mask;
1784bdd4dddee325a7dce3e84cf48201a06aa8508aa4Jeff Garzik			else
1785bdd4dddee325a7dce3e84cf48201a06aa8508aa4Jeff Garzik				ehi->err_mask |= err_mask;
1786bdd4dddee325a7dce3e84cf48201a06aa8508aa4Jeff Garzik
1787bdd4dddee325a7dce3e84cf48201a06aa8508aa4Jeff Garzik			ata_port_freeze(ap);
1788bdd4dddee325a7dce3e84cf48201a06aa8508aa4Jeff Garzik		}
1789bdd4dddee325a7dce3e84cf48201a06aa8508aa4Jeff Garzik	}
1790bdd4dddee325a7dce3e84cf48201a06aa8508aa4Jeff Garzik}
1791bdd4dddee325a7dce3e84cf48201a06aa8508aa4Jeff Garzik
179205b308e1df6d9d673daedb517969241f41278b52Brett Russ/**
1793c5d3e45a2200a0905dc45b72714726b7aac3aaf1Jeff Garzik *      mv_interrupt - Main interrupt event handler
179405b308e1df6d9d673daedb517969241f41278b52Brett Russ *      @irq: unused
179505b308e1df6d9d673daedb517969241f41278b52Brett Russ *      @dev_instance: private data; in this case the host structure
179605b308e1df6d9d673daedb517969241f41278b52Brett Russ *
179705b308e1df6d9d673daedb517969241f41278b52Brett Russ *      Read the read only register to determine if any host
179805b308e1df6d9d673daedb517969241f41278b52Brett Russ *      controllers have pending interrupts.  If so, call lower level
179905b308e1df6d9d673daedb517969241f41278b52Brett Russ *      routine to handle.  Also check for PCI errors which are only
180005b308e1df6d9d673daedb517969241f41278b52Brett Russ *      reported here.
180105b308e1df6d9d673daedb517969241f41278b52Brett Russ *
18028b260248d9e0e8b64bb72fd4dee03ad86984c344Jeff Garzik *      LOCKING:
1803cca3974e48607c3775dc73b544a5700b2e37c21aJeff Garzik *      This routine holds the host lock while processing pending
180405b308e1df6d9d673daedb517969241f41278b52Brett Russ *      interrupts.
180505b308e1df6d9d673daedb517969241f41278b52Brett Russ */
18067d12e780e003f93433d49ce78cfedf4b4c52adc5David Howellsstatic irqreturn_t mv_interrupt(int irq, void *dev_instance)
180720f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ{
1808cca3974e48607c3775dc73b544a5700b2e37c21aJeff Garzik	struct ata_host *host = dev_instance;
180920f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ	unsigned int hc, handled = 0, n_hcs;
18100d5ff566779f894ca9937231a181eb31e4adff0eTejun Heo	void __iomem *mmio = host->iomap[MV_PRIMARY_BAR];
1811646a4da514f2555298481cb00dc5b3eb02b21b72Mark Lord	u32 irq_stat, irq_mask;
181220f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ
1813646a4da514f2555298481cb00dc5b3eb02b21b72Mark Lord	spin_lock(&host->lock);
181420f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ	irq_stat = readl(mmio + HC_MAIN_IRQ_CAUSE_OFS);
1815646a4da514f2555298481cb00dc5b3eb02b21b72Mark Lord	irq_mask = readl(mmio + HC_MAIN_IRQ_MASK_OFS);
181620f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ
181720f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ	/* check the cases where we either have nothing pending or have read
181820f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ	 * a bogus register value which can indicate HW removal or PCI fault
181920f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ	 */
1820646a4da514f2555298481cb00dc5b3eb02b21b72Mark Lord	if (!(irq_stat & irq_mask) || (0xffffffffU == irq_stat))
1821646a4da514f2555298481cb00dc5b3eb02b21b72Mark Lord		goto out_unlock;
182220f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ
1823cca3974e48607c3775dc73b544a5700b2e37c21aJeff Garzik	n_hcs = mv_get_hc_count(host->ports[0]->flags);
182420f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ
1825bdd4dddee325a7dce3e84cf48201a06aa8508aa4Jeff Garzik	if (unlikely(irq_stat & PCI_ERR)) {
1826bdd4dddee325a7dce3e84cf48201a06aa8508aa4Jeff Garzik		mv_pci_error(host, mmio);
1827bdd4dddee325a7dce3e84cf48201a06aa8508aa4Jeff Garzik		handled = 1;
1828bdd4dddee325a7dce3e84cf48201a06aa8508aa4Jeff Garzik		goto out_unlock;	/* skip all other HC irq handling */
1829bdd4dddee325a7dce3e84cf48201a06aa8508aa4Jeff Garzik	}
1830bdd4dddee325a7dce3e84cf48201a06aa8508aa4Jeff Garzik
183120f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ	for (hc = 0; hc < n_hcs; hc++) {
183220f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ		u32 relevant = irq_stat & (HC0_IRQ_PEND << (hc * HC_SHIFT));
183320f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ		if (relevant) {
1834cca3974e48607c3775dc73b544a5700b2e37c21aJeff Garzik			mv_host_intr(host, relevant, hc);
1835bdd4dddee325a7dce3e84cf48201a06aa8508aa4Jeff Garzik			handled = 1;
183620f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ		}
183720f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ	}
1838615ab95342f6245026d8974b9724f7ea57d9a184Mark Lord
1839bdd4dddee325a7dce3e84cf48201a06aa8508aa4Jeff Garzikout_unlock:
1840cca3974e48607c3775dc73b544a5700b2e37c21aJeff Garzik	spin_unlock(&host->lock);
184120f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ
184220f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ	return IRQ_RETVAL(handled);
184320f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ}
184420f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ
1845c9d39130123238ac18478a42e25cb7996eacfcc0Jeff Garzikstatic void __iomem *mv5_phy_base(void __iomem *mmio, unsigned int port)
1846c9d39130123238ac18478a42e25cb7996eacfcc0Jeff Garzik{
1847c9d39130123238ac18478a42e25cb7996eacfcc0Jeff Garzik	void __iomem *hc_mmio = mv_hc_base_from_port(mmio, port);
1848c9d39130123238ac18478a42e25cb7996eacfcc0Jeff Garzik	unsigned long ofs = (mv_hardport_from_port(port) + 1) * 0x100UL;
1849c9d39130123238ac18478a42e25cb7996eacfcc0Jeff Garzik
1850c9d39130123238ac18478a42e25cb7996eacfcc0Jeff Garzik	return hc_mmio + ofs;
1851c9d39130123238ac18478a42e25cb7996eacfcc0Jeff Garzik}
1852c9d39130123238ac18478a42e25cb7996eacfcc0Jeff Garzik
1853c9d39130123238ac18478a42e25cb7996eacfcc0Jeff Garzikstatic unsigned int mv5_scr_offset(unsigned int sc_reg_in)
1854c9d39130123238ac18478a42e25cb7996eacfcc0Jeff Garzik{
1855c9d39130123238ac18478a42e25cb7996eacfcc0Jeff Garzik	unsigned int ofs;
1856c9d39130123238ac18478a42e25cb7996eacfcc0Jeff Garzik
1857c9d39130123238ac18478a42e25cb7996eacfcc0Jeff Garzik	switch (sc_reg_in) {
1858c9d39130123238ac18478a42e25cb7996eacfcc0Jeff Garzik	case SCR_STATUS:
1859c9d39130123238ac18478a42e25cb7996eacfcc0Jeff Garzik	case SCR_ERROR:
1860c9d39130123238ac18478a42e25cb7996eacfcc0Jeff Garzik	case SCR_CONTROL:
1861c9d39130123238ac18478a42e25cb7996eacfcc0Jeff Garzik		ofs = sc_reg_in * sizeof(u32);
1862c9d39130123238ac18478a42e25cb7996eacfcc0Jeff Garzik		break;
1863c9d39130123238ac18478a42e25cb7996eacfcc0Jeff Garzik	default:
1864c9d39130123238ac18478a42e25cb7996eacfcc0Jeff Garzik		ofs = 0xffffffffU;
1865c9d39130123238ac18478a42e25cb7996eacfcc0Jeff Garzik		break;
1866c9d39130123238ac18478a42e25cb7996eacfcc0Jeff Garzik	}
1867c9d39130123238ac18478a42e25cb7996eacfcc0Jeff Garzik	return ofs;
1868c9d39130123238ac18478a42e25cb7996eacfcc0Jeff Garzik}
1869c9d39130123238ac18478a42e25cb7996eacfcc0Jeff Garzik
1870da3dbb17a0e9a9ec7f5aed95f1fddadb790edc9dTejun Heostatic int mv5_scr_read(struct ata_port *ap, unsigned int sc_reg_in, u32 *val)
1871c9d39130123238ac18478a42e25cb7996eacfcc0Jeff Garzik{
18720d5ff566779f894ca9937231a181eb31e4adff0eTejun Heo	void __iomem *mmio = ap->host->iomap[MV_PRIMARY_BAR];
18730d5ff566779f894ca9937231a181eb31e4adff0eTejun Heo	void __iomem *addr = mv5_phy_base(mmio, ap->port_no);
1874c9d39130123238ac18478a42e25cb7996eacfcc0Jeff Garzik	unsigned int ofs = mv5_scr_offset(sc_reg_in);
1875c9d39130123238ac18478a42e25cb7996eacfcc0Jeff Garzik
1876da3dbb17a0e9a9ec7f5aed95f1fddadb790edc9dTejun Heo	if (ofs != 0xffffffffU) {
1877da3dbb17a0e9a9ec7f5aed95f1fddadb790edc9dTejun Heo		*val = readl(addr + ofs);
1878da3dbb17a0e9a9ec7f5aed95f1fddadb790edc9dTejun Heo		return 0;
1879da3dbb17a0e9a9ec7f5aed95f1fddadb790edc9dTejun Heo	} else
1880da3dbb17a0e9a9ec7f5aed95f1fddadb790edc9dTejun Heo		return -EINVAL;
1881c9d39130123238ac18478a42e25cb7996eacfcc0Jeff Garzik}
1882c9d39130123238ac18478a42e25cb7996eacfcc0Jeff Garzik
1883da3dbb17a0e9a9ec7f5aed95f1fddadb790edc9dTejun Heostatic int mv5_scr_write(struct ata_port *ap, unsigned int sc_reg_in, u32 val)
1884c9d39130123238ac18478a42e25cb7996eacfcc0Jeff Garzik{
18850d5ff566779f894ca9937231a181eb31e4adff0eTejun Heo	void __iomem *mmio = ap->host->iomap[MV_PRIMARY_BAR];
18860d5ff566779f894ca9937231a181eb31e4adff0eTejun Heo	void __iomem *addr = mv5_phy_base(mmio, ap->port_no);
1887c9d39130123238ac18478a42e25cb7996eacfcc0Jeff Garzik	unsigned int ofs = mv5_scr_offset(sc_reg_in);
1888c9d39130123238ac18478a42e25cb7996eacfcc0Jeff Garzik
1889da3dbb17a0e9a9ec7f5aed95f1fddadb790edc9dTejun Heo	if (ofs != 0xffffffffU) {
18900d5ff566779f894ca9937231a181eb31e4adff0eTejun Heo		writelfl(val, addr + ofs);
1891da3dbb17a0e9a9ec7f5aed95f1fddadb790edc9dTejun Heo		return 0;
1892da3dbb17a0e9a9ec7f5aed95f1fddadb790edc9dTejun Heo	} else
1893da3dbb17a0e9a9ec7f5aed95f1fddadb790edc9dTejun Heo		return -EINVAL;
1894c9d39130123238ac18478a42e25cb7996eacfcc0Jeff Garzik}
1895c9d39130123238ac18478a42e25cb7996eacfcc0Jeff Garzik
1896522479fb98c6667f081e75f87e298e413c0b1db8Jeff Garzikstatic void mv5_reset_bus(struct pci_dev *pdev, void __iomem *mmio)
1897522479fb98c6667f081e75f87e298e413c0b1db8Jeff Garzik{
1898522479fb98c6667f081e75f87e298e413c0b1db8Jeff Garzik	int early_5080;
1899522479fb98c6667f081e75f87e298e413c0b1db8Jeff Garzik
190044c10138fd4bbc4b6d6bff0873c24902f2a9da65Auke Kok	early_5080 = (pdev->device == 0x5080) && (pdev->revision == 0);
1901522479fb98c6667f081e75f87e298e413c0b1db8Jeff Garzik
1902522479fb98c6667f081e75f87e298e413c0b1db8Jeff Garzik	if (!early_5080) {
1903522479fb98c6667f081e75f87e298e413c0b1db8Jeff Garzik		u32 tmp = readl(mmio + MV_PCI_EXP_ROM_BAR_CTL);
1904522479fb98c6667f081e75f87e298e413c0b1db8Jeff Garzik		tmp |= (1 << 0);
1905522479fb98c6667f081e75f87e298e413c0b1db8Jeff Garzik		writel(tmp, mmio + MV_PCI_EXP_ROM_BAR_CTL);
1906522479fb98c6667f081e75f87e298e413c0b1db8Jeff Garzik	}
1907522479fb98c6667f081e75f87e298e413c0b1db8Jeff Garzik
1908522479fb98c6667f081e75f87e298e413c0b1db8Jeff Garzik	mv_reset_pci_bus(pdev, mmio);
1909522479fb98c6667f081e75f87e298e413c0b1db8Jeff Garzik}
1910522479fb98c6667f081e75f87e298e413c0b1db8Jeff Garzik
1911522479fb98c6667f081e75f87e298e413c0b1db8Jeff Garzikstatic void mv5_reset_flash(struct mv_host_priv *hpriv, void __iomem *mmio)
1912522479fb98c6667f081e75f87e298e413c0b1db8Jeff Garzik{
1913522479fb98c6667f081e75f87e298e413c0b1db8Jeff Garzik	writel(0x0fcfffff, mmio + MV_FLASH_CTL);
1914522479fb98c6667f081e75f87e298e413c0b1db8Jeff Garzik}
1915522479fb98c6667f081e75f87e298e413c0b1db8Jeff Garzik
191647c2b677daeed9c79ecb7167c211ff36876ea611Jeff Garzikstatic void mv5_read_preamp(struct mv_host_priv *hpriv, int idx,
1917ba3fe8fb6a469390a14379519915f3c39a973d99Jeff Garzik			   void __iomem *mmio)
1918ba3fe8fb6a469390a14379519915f3c39a973d99Jeff Garzik{
1919c9d39130123238ac18478a42e25cb7996eacfcc0Jeff Garzik	void __iomem *phy_mmio = mv5_phy_base(mmio, idx);
1920c9d39130123238ac18478a42e25cb7996eacfcc0Jeff Garzik	u32 tmp;
1921c9d39130123238ac18478a42e25cb7996eacfcc0Jeff Garzik
1922c9d39130123238ac18478a42e25cb7996eacfcc0Jeff Garzik	tmp = readl(phy_mmio + MV5_PHY_MODE);
1923c9d39130123238ac18478a42e25cb7996eacfcc0Jeff Garzik
1924c9d39130123238ac18478a42e25cb7996eacfcc0Jeff Garzik	hpriv->signal[idx].pre = tmp & 0x1800;	/* bits 12:11 */
1925c9d39130123238ac18478a42e25cb7996eacfcc0Jeff Garzik	hpriv->signal[idx].amps = tmp & 0xe0;	/* bits 7:5 */
1926ba3fe8fb6a469390a14379519915f3c39a973d99Jeff Garzik}
1927ba3fe8fb6a469390a14379519915f3c39a973d99Jeff Garzik
192847c2b677daeed9c79ecb7167c211ff36876ea611Jeff Garzikstatic void mv5_enable_leds(struct mv_host_priv *hpriv, void __iomem *mmio)
1929ba3fe8fb6a469390a14379519915f3c39a973d99Jeff Garzik{
1930522479fb98c6667f081e75f87e298e413c0b1db8Jeff Garzik	u32 tmp;
1931522479fb98c6667f081e75f87e298e413c0b1db8Jeff Garzik
1932522479fb98c6667f081e75f87e298e413c0b1db8Jeff Garzik	writel(0, mmio + MV_GPIO_PORT_CTL);
1933522479fb98c6667f081e75f87e298e413c0b1db8Jeff Garzik
1934522479fb98c6667f081e75f87e298e413c0b1db8Jeff Garzik	/* FIXME: handle MV_HP_ERRATA_50XXB2 errata */
1935522479fb98c6667f081e75f87e298e413c0b1db8Jeff Garzik
1936522479fb98c6667f081e75f87e298e413c0b1db8Jeff Garzik	tmp = readl(mmio + MV_PCI_EXP_ROM_BAR_CTL);
1937522479fb98c6667f081e75f87e298e413c0b1db8Jeff Garzik	tmp |= ~(1 << 0);
1938522479fb98c6667f081e75f87e298e413c0b1db8Jeff Garzik	writel(tmp, mmio + MV_PCI_EXP_ROM_BAR_CTL);
1939ba3fe8fb6a469390a14379519915f3c39a973d99Jeff Garzik}
1940ba3fe8fb6a469390a14379519915f3c39a973d99Jeff Garzik
19412a47ce06d534692f9bd2bf4e90a20fc9b1054c39Jeff Garzikstatic void mv5_phy_errata(struct mv_host_priv *hpriv, void __iomem *mmio,
19422a47ce06d534692f9bd2bf4e90a20fc9b1054c39Jeff Garzik			   unsigned int port)
1943bca1c4eb9411533d613123618c0d127fae532595Jeff Garzik{
1944c9d39130123238ac18478a42e25cb7996eacfcc0Jeff Garzik	void __iomem *phy_mmio = mv5_phy_base(mmio, port);
1945c9d39130123238ac18478a42e25cb7996eacfcc0Jeff Garzik	const u32 mask = (1<<12) | (1<<11) | (1<<7) | (1<<6) | (1<<5);
1946c9d39130123238ac18478a42e25cb7996eacfcc0Jeff Garzik	u32 tmp;
1947c9d39130123238ac18478a42e25cb7996eacfcc0Jeff Garzik	int fix_apm_sq = (hpriv->hp_flags & MV_HP_ERRATA_50XXB0);
1948c9d39130123238ac18478a42e25cb7996eacfcc0Jeff Garzik
1949c9d39130123238ac18478a42e25cb7996eacfcc0Jeff Garzik	if (fix_apm_sq) {
1950c9d39130123238ac18478a42e25cb7996eacfcc0Jeff Garzik		tmp = readl(phy_mmio + MV5_LT_MODE);
1951c9d39130123238ac18478a42e25cb7996eacfcc0Jeff Garzik		tmp |= (1 << 19);
1952c9d39130123238ac18478a42e25cb7996eacfcc0Jeff Garzik		writel(tmp, phy_mmio + MV5_LT_MODE);
1953c9d39130123238ac18478a42e25cb7996eacfcc0Jeff Garzik
1954c9d39130123238ac18478a42e25cb7996eacfcc0Jeff Garzik		tmp = readl(phy_mmio + MV5_PHY_CTL);
1955c9d39130123238ac18478a42e25cb7996eacfcc0Jeff Garzik		tmp &= ~0x3;
1956c9d39130123238ac18478a42e25cb7996eacfcc0Jeff Garzik		tmp |= 0x1;
1957c9d39130123238ac18478a42e25cb7996eacfcc0Jeff Garzik		writel(tmp, phy_mmio + MV5_PHY_CTL);
1958c9d39130123238ac18478a42e25cb7996eacfcc0Jeff Garzik	}
1959c9d39130123238ac18478a42e25cb7996eacfcc0Jeff Garzik
1960c9d39130123238ac18478a42e25cb7996eacfcc0Jeff Garzik	tmp = readl(phy_mmio + MV5_PHY_MODE);
1961c9d39130123238ac18478a42e25cb7996eacfcc0Jeff Garzik	tmp &= ~mask;
1962c9d39130123238ac18478a42e25cb7996eacfcc0Jeff Garzik	tmp |= hpriv->signal[port].pre;
1963c9d39130123238ac18478a42e25cb7996eacfcc0Jeff Garzik	tmp |= hpriv->signal[port].amps;
1964c9d39130123238ac18478a42e25cb7996eacfcc0Jeff Garzik	writel(tmp, phy_mmio + MV5_PHY_MODE);
1965bca1c4eb9411533d613123618c0d127fae532595Jeff Garzik}
1966bca1c4eb9411533d613123618c0d127fae532595Jeff Garzik
1967c9d39130123238ac18478a42e25cb7996eacfcc0Jeff Garzik
1968c9d39130123238ac18478a42e25cb7996eacfcc0Jeff Garzik#undef ZERO
1969c9d39130123238ac18478a42e25cb7996eacfcc0Jeff Garzik#define ZERO(reg) writel(0, port_mmio + (reg))
1970c9d39130123238ac18478a42e25cb7996eacfcc0Jeff Garzikstatic void mv5_reset_hc_port(struct mv_host_priv *hpriv, void __iomem *mmio,
1971c9d39130123238ac18478a42e25cb7996eacfcc0Jeff Garzik			     unsigned int port)
1972c9d39130123238ac18478a42e25cb7996eacfcc0Jeff Garzik{
1973c9d39130123238ac18478a42e25cb7996eacfcc0Jeff Garzik	void __iomem *port_mmio = mv_port_base(mmio, port);
1974c9d39130123238ac18478a42e25cb7996eacfcc0Jeff Garzik
1975c9d39130123238ac18478a42e25cb7996eacfcc0Jeff Garzik	writelfl(EDMA_DS, port_mmio + EDMA_CMD_OFS);
1976c9d39130123238ac18478a42e25cb7996eacfcc0Jeff Garzik
1977c9d39130123238ac18478a42e25cb7996eacfcc0Jeff Garzik	mv_channel_reset(hpriv, mmio, port);
1978c9d39130123238ac18478a42e25cb7996eacfcc0Jeff Garzik
1979c9d39130123238ac18478a42e25cb7996eacfcc0Jeff Garzik	ZERO(0x028);	/* command */
1980c9d39130123238ac18478a42e25cb7996eacfcc0Jeff Garzik	writel(0x11f, port_mmio + EDMA_CFG_OFS);
1981c9d39130123238ac18478a42e25cb7996eacfcc0Jeff Garzik	ZERO(0x004);	/* timer */
1982c9d39130123238ac18478a42e25cb7996eacfcc0Jeff Garzik	ZERO(0x008);	/* irq err cause */
1983c9d39130123238ac18478a42e25cb7996eacfcc0Jeff Garzik	ZERO(0x00c);	/* irq err mask */
1984c9d39130123238ac18478a42e25cb7996eacfcc0Jeff Garzik	ZERO(0x010);	/* rq bah */
1985c9d39130123238ac18478a42e25cb7996eacfcc0Jeff Garzik	ZERO(0x014);	/* rq inp */
1986c9d39130123238ac18478a42e25cb7996eacfcc0Jeff Garzik	ZERO(0x018);	/* rq outp */
1987c9d39130123238ac18478a42e25cb7996eacfcc0Jeff Garzik	ZERO(0x01c);	/* respq bah */
1988c9d39130123238ac18478a42e25cb7996eacfcc0Jeff Garzik	ZERO(0x024);	/* respq outp */
1989c9d39130123238ac18478a42e25cb7996eacfcc0Jeff Garzik	ZERO(0x020);	/* respq inp */
1990c9d39130123238ac18478a42e25cb7996eacfcc0Jeff Garzik	ZERO(0x02c);	/* test control */
1991c9d39130123238ac18478a42e25cb7996eacfcc0Jeff Garzik	writel(0xbc, port_mmio + EDMA_IORDY_TMOUT);
1992c9d39130123238ac18478a42e25cb7996eacfcc0Jeff Garzik}
1993c9d39130123238ac18478a42e25cb7996eacfcc0Jeff Garzik#undef ZERO
1994c9d39130123238ac18478a42e25cb7996eacfcc0Jeff Garzik
1995c9d39130123238ac18478a42e25cb7996eacfcc0Jeff Garzik#define ZERO(reg) writel(0, hc_mmio + (reg))
1996c9d39130123238ac18478a42e25cb7996eacfcc0Jeff Garzikstatic void mv5_reset_one_hc(struct mv_host_priv *hpriv, void __iomem *mmio,
1997c9d39130123238ac18478a42e25cb7996eacfcc0Jeff Garzik			unsigned int hc)
199847c2b677daeed9c79ecb7167c211ff36876ea611Jeff Garzik{
1999c9d39130123238ac18478a42e25cb7996eacfcc0Jeff Garzik	void __iomem *hc_mmio = mv_hc_base(mmio, hc);
2000c9d39130123238ac18478a42e25cb7996eacfcc0Jeff Garzik	u32 tmp;
2001c9d39130123238ac18478a42e25cb7996eacfcc0Jeff Garzik
2002c9d39130123238ac18478a42e25cb7996eacfcc0Jeff Garzik	ZERO(0x00c);
2003c9d39130123238ac18478a42e25cb7996eacfcc0Jeff Garzik	ZERO(0x010);
2004c9d39130123238ac18478a42e25cb7996eacfcc0Jeff Garzik	ZERO(0x014);
2005c9d39130123238ac18478a42e25cb7996eacfcc0Jeff Garzik	ZERO(0x018);
2006c9d39130123238ac18478a42e25cb7996eacfcc0Jeff Garzik
2007c9d39130123238ac18478a42e25cb7996eacfcc0Jeff Garzik	tmp = readl(hc_mmio + 0x20);
2008c9d39130123238ac18478a42e25cb7996eacfcc0Jeff Garzik	tmp &= 0x1c1c1c1c;
2009c9d39130123238ac18478a42e25cb7996eacfcc0Jeff Garzik	tmp |= 0x03030303;
2010c9d39130123238ac18478a42e25cb7996eacfcc0Jeff Garzik	writel(tmp, hc_mmio + 0x20);
2011c9d39130123238ac18478a42e25cb7996eacfcc0Jeff Garzik}
2012c9d39130123238ac18478a42e25cb7996eacfcc0Jeff Garzik#undef ZERO
2013c9d39130123238ac18478a42e25cb7996eacfcc0Jeff Garzik
2014c9d39130123238ac18478a42e25cb7996eacfcc0Jeff Garzikstatic int mv5_reset_hc(struct mv_host_priv *hpriv, void __iomem *mmio,
2015c9d39130123238ac18478a42e25cb7996eacfcc0Jeff Garzik			unsigned int n_hc)
2016c9d39130123238ac18478a42e25cb7996eacfcc0Jeff Garzik{
2017c9d39130123238ac18478a42e25cb7996eacfcc0Jeff Garzik	unsigned int hc, port;
2018c9d39130123238ac18478a42e25cb7996eacfcc0Jeff Garzik
2019c9d39130123238ac18478a42e25cb7996eacfcc0Jeff Garzik	for (hc = 0; hc < n_hc; hc++) {
2020c9d39130123238ac18478a42e25cb7996eacfcc0Jeff Garzik		for (port = 0; port < MV_PORTS_PER_HC; port++)
2021c9d39130123238ac18478a42e25cb7996eacfcc0Jeff Garzik			mv5_reset_hc_port(hpriv, mmio,
2022c9d39130123238ac18478a42e25cb7996eacfcc0Jeff Garzik					  (hc * MV_PORTS_PER_HC) + port);
2023c9d39130123238ac18478a42e25cb7996eacfcc0Jeff Garzik
2024c9d39130123238ac18478a42e25cb7996eacfcc0Jeff Garzik		mv5_reset_one_hc(hpriv, mmio, hc);
2025c9d39130123238ac18478a42e25cb7996eacfcc0Jeff Garzik	}
2026c9d39130123238ac18478a42e25cb7996eacfcc0Jeff Garzik
2027c9d39130123238ac18478a42e25cb7996eacfcc0Jeff Garzik	return 0;
202847c2b677daeed9c79ecb7167c211ff36876ea611Jeff Garzik}
202947c2b677daeed9c79ecb7167c211ff36876ea611Jeff Garzik
2030101ffae26c23ea928fce6d31a8b4901327d91a15Jeff Garzik#undef ZERO
2031101ffae26c23ea928fce6d31a8b4901327d91a15Jeff Garzik#define ZERO(reg) writel(0, mmio + (reg))
2032101ffae26c23ea928fce6d31a8b4901327d91a15Jeff Garzikstatic void mv_reset_pci_bus(struct pci_dev *pdev, void __iomem *mmio)
2033101ffae26c23ea928fce6d31a8b4901327d91a15Jeff Garzik{
203402a121da5a53d415b6596bc19cc6999d295d32a4Mark Lord	struct ata_host     *host = dev_get_drvdata(&pdev->dev);
203502a121da5a53d415b6596bc19cc6999d295d32a4Mark Lord	struct mv_host_priv *hpriv = host->private_data;
2036101ffae26c23ea928fce6d31a8b4901327d91a15Jeff Garzik	u32 tmp;
2037101ffae26c23ea928fce6d31a8b4901327d91a15Jeff Garzik
2038101ffae26c23ea928fce6d31a8b4901327d91a15Jeff Garzik	tmp = readl(mmio + MV_PCI_MODE);
2039101ffae26c23ea928fce6d31a8b4901327d91a15Jeff Garzik	tmp &= 0xff00ffff;
2040101ffae26c23ea928fce6d31a8b4901327d91a15Jeff Garzik	writel(tmp, mmio + MV_PCI_MODE);
2041101ffae26c23ea928fce6d31a8b4901327d91a15Jeff Garzik
2042101ffae26c23ea928fce6d31a8b4901327d91a15Jeff Garzik	ZERO(MV_PCI_DISC_TIMER);
2043101ffae26c23ea928fce6d31a8b4901327d91a15Jeff Garzik	ZERO(MV_PCI_MSI_TRIGGER);
2044101ffae26c23ea928fce6d31a8b4901327d91a15Jeff Garzik	writel(0x000100ff, mmio + MV_PCI_XBAR_TMOUT);
2045101ffae26c23ea928fce6d31a8b4901327d91a15Jeff Garzik	ZERO(HC_MAIN_IRQ_MASK_OFS);
2046101ffae26c23ea928fce6d31a8b4901327d91a15Jeff Garzik	ZERO(MV_PCI_SERR_MASK);
204702a121da5a53d415b6596bc19cc6999d295d32a4Mark Lord	ZERO(hpriv->irq_cause_ofs);
204802a121da5a53d415b6596bc19cc6999d295d32a4Mark Lord	ZERO(hpriv->irq_mask_ofs);
2049101ffae26c23ea928fce6d31a8b4901327d91a15Jeff Garzik	ZERO(MV_PCI_ERR_LOW_ADDRESS);
2050101ffae26c23ea928fce6d31a8b4901327d91a15Jeff Garzik	ZERO(MV_PCI_ERR_HIGH_ADDRESS);
2051101ffae26c23ea928fce6d31a8b4901327d91a15Jeff Garzik	ZERO(MV_PCI_ERR_ATTRIBUTE);
2052101ffae26c23ea928fce6d31a8b4901327d91a15Jeff Garzik	ZERO(MV_PCI_ERR_COMMAND);
2053101ffae26c23ea928fce6d31a8b4901327d91a15Jeff Garzik}
2054101ffae26c23ea928fce6d31a8b4901327d91a15Jeff Garzik#undef ZERO
2055101ffae26c23ea928fce6d31a8b4901327d91a15Jeff Garzik
2056101ffae26c23ea928fce6d31a8b4901327d91a15Jeff Garzikstatic void mv6_reset_flash(struct mv_host_priv *hpriv, void __iomem *mmio)
2057101ffae26c23ea928fce6d31a8b4901327d91a15Jeff Garzik{
2058101ffae26c23ea928fce6d31a8b4901327d91a15Jeff Garzik	u32 tmp;
2059101ffae26c23ea928fce6d31a8b4901327d91a15Jeff Garzik
2060101ffae26c23ea928fce6d31a8b4901327d91a15Jeff Garzik	mv5_reset_flash(hpriv, mmio);
2061101ffae26c23ea928fce6d31a8b4901327d91a15Jeff Garzik
2062101ffae26c23ea928fce6d31a8b4901327d91a15Jeff Garzik	tmp = readl(mmio + MV_GPIO_PORT_CTL);
2063101ffae26c23ea928fce6d31a8b4901327d91a15Jeff Garzik	tmp &= 0x3;
2064101ffae26c23ea928fce6d31a8b4901327d91a15Jeff Garzik	tmp |= (1 << 5) | (1 << 6);
2065101ffae26c23ea928fce6d31a8b4901327d91a15Jeff Garzik	writel(tmp, mmio + MV_GPIO_PORT_CTL);
2066101ffae26c23ea928fce6d31a8b4901327d91a15Jeff Garzik}
2067101ffae26c23ea928fce6d31a8b4901327d91a15Jeff Garzik
2068101ffae26c23ea928fce6d31a8b4901327d91a15Jeff Garzik/**
2069101ffae26c23ea928fce6d31a8b4901327d91a15Jeff Garzik *      mv6_reset_hc - Perform the 6xxx global soft reset
2070101ffae26c23ea928fce6d31a8b4901327d91a15Jeff Garzik *      @mmio: base address of the HBA
2071101ffae26c23ea928fce6d31a8b4901327d91a15Jeff Garzik *
2072101ffae26c23ea928fce6d31a8b4901327d91a15Jeff Garzik *      This routine only applies to 6xxx parts.
2073101ffae26c23ea928fce6d31a8b4901327d91a15Jeff Garzik *
2074101ffae26c23ea928fce6d31a8b4901327d91a15Jeff Garzik *      LOCKING:
2075101ffae26c23ea928fce6d31a8b4901327d91a15Jeff Garzik *      Inherited from caller.
2076101ffae26c23ea928fce6d31a8b4901327d91a15Jeff Garzik */
2077c9d39130123238ac18478a42e25cb7996eacfcc0Jeff Garzikstatic int mv6_reset_hc(struct mv_host_priv *hpriv, void __iomem *mmio,
2078c9d39130123238ac18478a42e25cb7996eacfcc0Jeff Garzik			unsigned int n_hc)
2079101ffae26c23ea928fce6d31a8b4901327d91a15Jeff Garzik{
2080101ffae26c23ea928fce6d31a8b4901327d91a15Jeff Garzik	void __iomem *reg = mmio + PCI_MAIN_CMD_STS_OFS;
2081101ffae26c23ea928fce6d31a8b4901327d91a15Jeff Garzik	int i, rc = 0;
2082101ffae26c23ea928fce6d31a8b4901327d91a15Jeff Garzik	u32 t;
2083101ffae26c23ea928fce6d31a8b4901327d91a15Jeff Garzik
2084101ffae26c23ea928fce6d31a8b4901327d91a15Jeff Garzik	/* Following procedure defined in PCI "main command and status
2085101ffae26c23ea928fce6d31a8b4901327d91a15Jeff Garzik	 * register" table.
2086101ffae26c23ea928fce6d31a8b4901327d91a15Jeff Garzik	 */
2087101ffae26c23ea928fce6d31a8b4901327d91a15Jeff Garzik	t = readl(reg);
2088101ffae26c23ea928fce6d31a8b4901327d91a15Jeff Garzik	writel(t | STOP_PCI_MASTER, reg);
2089101ffae26c23ea928fce6d31a8b4901327d91a15Jeff Garzik
2090101ffae26c23ea928fce6d31a8b4901327d91a15Jeff Garzik	for (i = 0; i < 1000; i++) {
2091101ffae26c23ea928fce6d31a8b4901327d91a15Jeff Garzik		udelay(1);
2092101ffae26c23ea928fce6d31a8b4901327d91a15Jeff Garzik		t = readl(reg);
20932dcb407e61458ded17503d6bd12b8c064965368bJeff Garzik		if (PCI_MASTER_EMPTY & t)
2094101ffae26c23ea928fce6d31a8b4901327d91a15Jeff Garzik			break;
2095101ffae26c23ea928fce6d31a8b4901327d91a15Jeff Garzik	}
2096101ffae26c23ea928fce6d31a8b4901327d91a15Jeff Garzik	if (!(PCI_MASTER_EMPTY & t)) {
2097101ffae26c23ea928fce6d31a8b4901327d91a15Jeff Garzik		printk(KERN_ERR DRV_NAME ": PCI master won't flush\n");
2098101ffae26c23ea928fce6d31a8b4901327d91a15Jeff Garzik		rc = 1;
2099101ffae26c23ea928fce6d31a8b4901327d91a15Jeff Garzik		goto done;
2100101ffae26c23ea928fce6d31a8b4901327d91a15Jeff Garzik	}
2101101ffae26c23ea928fce6d31a8b4901327d91a15Jeff Garzik
2102101ffae26c23ea928fce6d31a8b4901327d91a15Jeff Garzik	/* set reset */
2103101ffae26c23ea928fce6d31a8b4901327d91a15Jeff Garzik	i = 5;
2104101ffae26c23ea928fce6d31a8b4901327d91a15Jeff Garzik	do {
2105101ffae26c23ea928fce6d31a8b4901327d91a15Jeff Garzik		writel(t | GLOB_SFT_RST, reg);
2106101ffae26c23ea928fce6d31a8b4901327d91a15Jeff Garzik		t = readl(reg);
2107101ffae26c23ea928fce6d31a8b4901327d91a15Jeff Garzik		udelay(1);
2108101ffae26c23ea928fce6d31a8b4901327d91a15Jeff Garzik	} while (!(GLOB_SFT_RST & t) && (i-- > 0));
2109101ffae26c23ea928fce6d31a8b4901327d91a15Jeff Garzik
2110101ffae26c23ea928fce6d31a8b4901327d91a15Jeff Garzik	if (!(GLOB_SFT_RST & t)) {
2111101ffae26c23ea928fce6d31a8b4901327d91a15Jeff Garzik		printk(KERN_ERR DRV_NAME ": can't set global reset\n");
2112101ffae26c23ea928fce6d31a8b4901327d91a15Jeff Garzik		rc = 1;
2113101ffae26c23ea928fce6d31a8b4901327d91a15Jeff Garzik		goto done;
2114101ffae26c23ea928fce6d31a8b4901327d91a15Jeff Garzik	}
2115101ffae26c23ea928fce6d31a8b4901327d91a15Jeff Garzik
2116101ffae26c23ea928fce6d31a8b4901327d91a15Jeff Garzik	/* clear reset and *reenable the PCI master* (not mentioned in spec) */
2117101ffae26c23ea928fce6d31a8b4901327d91a15Jeff Garzik	i = 5;
2118101ffae26c23ea928fce6d31a8b4901327d91a15Jeff Garzik	do {
2119101ffae26c23ea928fce6d31a8b4901327d91a15Jeff Garzik		writel(t & ~(GLOB_SFT_RST | STOP_PCI_MASTER), reg);
2120101ffae26c23ea928fce6d31a8b4901327d91a15Jeff Garzik		t = readl(reg);
2121101ffae26c23ea928fce6d31a8b4901327d91a15Jeff Garzik		udelay(1);
2122101ffae26c23ea928fce6d31a8b4901327d91a15Jeff Garzik	} while ((GLOB_SFT_RST & t) && (i-- > 0));
2123101ffae26c23ea928fce6d31a8b4901327d91a15Jeff Garzik
2124101ffae26c23ea928fce6d31a8b4901327d91a15Jeff Garzik	if (GLOB_SFT_RST & t) {
2125101ffae26c23ea928fce6d31a8b4901327d91a15Jeff Garzik		printk(KERN_ERR DRV_NAME ": can't clear global reset\n");
2126101ffae26c23ea928fce6d31a8b4901327d91a15Jeff Garzik		rc = 1;
2127101ffae26c23ea928fce6d31a8b4901327d91a15Jeff Garzik	}
2128101ffae26c23ea928fce6d31a8b4901327d91a15Jeff Garzikdone:
2129101ffae26c23ea928fce6d31a8b4901327d91a15Jeff Garzik	return rc;
2130101ffae26c23ea928fce6d31a8b4901327d91a15Jeff Garzik}
2131101ffae26c23ea928fce6d31a8b4901327d91a15Jeff Garzik
213247c2b677daeed9c79ecb7167c211ff36876ea611Jeff Garzikstatic void mv6_read_preamp(struct mv_host_priv *hpriv, int idx,
2133ba3fe8fb6a469390a14379519915f3c39a973d99Jeff Garzik			   void __iomem *mmio)
2134ba3fe8fb6a469390a14379519915f3c39a973d99Jeff Garzik{
2135ba3fe8fb6a469390a14379519915f3c39a973d99Jeff Garzik	void __iomem *port_mmio;
2136ba3fe8fb6a469390a14379519915f3c39a973d99Jeff Garzik	u32 tmp;
2137ba3fe8fb6a469390a14379519915f3c39a973d99Jeff Garzik
2138ba3fe8fb6a469390a14379519915f3c39a973d99Jeff Garzik	tmp = readl(mmio + MV_RESET_CFG);
2139ba3fe8fb6a469390a14379519915f3c39a973d99Jeff Garzik	if ((tmp & (1 << 0)) == 0) {
214047c2b677daeed9c79ecb7167c211ff36876ea611Jeff Garzik		hpriv->signal[idx].amps = 0x7 << 8;
2141ba3fe8fb6a469390a14379519915f3c39a973d99Jeff Garzik		hpriv->signal[idx].pre = 0x1 << 5;
2142ba3fe8fb6a469390a14379519915f3c39a973d99Jeff Garzik		return;
2143ba3fe8fb6a469390a14379519915f3c39a973d99Jeff Garzik	}
2144ba3fe8fb6a469390a14379519915f3c39a973d99Jeff Garzik
2145ba3fe8fb6a469390a14379519915f3c39a973d99Jeff Garzik	port_mmio = mv_port_base(mmio, idx);
2146ba3fe8fb6a469390a14379519915f3c39a973d99Jeff Garzik	tmp = readl(port_mmio + PHY_MODE2);
2147ba3fe8fb6a469390a14379519915f3c39a973d99Jeff Garzik
2148ba3fe8fb6a469390a14379519915f3c39a973d99Jeff Garzik	hpriv->signal[idx].amps = tmp & 0x700;	/* bits 10:8 */
2149ba3fe8fb6a469390a14379519915f3c39a973d99Jeff Garzik	hpriv->signal[idx].pre = tmp & 0xe0;	/* bits 7:5 */
2150ba3fe8fb6a469390a14379519915f3c39a973d99Jeff Garzik}
2151ba3fe8fb6a469390a14379519915f3c39a973d99Jeff Garzik
215247c2b677daeed9c79ecb7167c211ff36876ea611Jeff Garzikstatic void mv6_enable_leds(struct mv_host_priv *hpriv, void __iomem *mmio)
2153ba3fe8fb6a469390a14379519915f3c39a973d99Jeff Garzik{
215447c2b677daeed9c79ecb7167c211ff36876ea611Jeff Garzik	writel(0x00000060, mmio + MV_GPIO_PORT_CTL);
2155ba3fe8fb6a469390a14379519915f3c39a973d99Jeff Garzik}
2156ba3fe8fb6a469390a14379519915f3c39a973d99Jeff Garzik
2157c9d39130123238ac18478a42e25cb7996eacfcc0Jeff Garzikstatic void mv6_phy_errata(struct mv_host_priv *hpriv, void __iomem *mmio,
21582a47ce06d534692f9bd2bf4e90a20fc9b1054c39Jeff Garzik			   unsigned int port)
2159bca1c4eb9411533d613123618c0d127fae532595Jeff Garzik{
2160c9d39130123238ac18478a42e25cb7996eacfcc0Jeff Garzik	void __iomem *port_mmio = mv_port_base(mmio, port);
2161c9d39130123238ac18478a42e25cb7996eacfcc0Jeff Garzik
2162bca1c4eb9411533d613123618c0d127fae532595Jeff Garzik	u32 hp_flags = hpriv->hp_flags;
216347c2b677daeed9c79ecb7167c211ff36876ea611Jeff Garzik	int fix_phy_mode2 =
216447c2b677daeed9c79ecb7167c211ff36876ea611Jeff Garzik		hp_flags & (MV_HP_ERRATA_60X1B2 | MV_HP_ERRATA_60X1C0);
2165bca1c4eb9411533d613123618c0d127fae532595Jeff Garzik	int fix_phy_mode4 =
216647c2b677daeed9c79ecb7167c211ff36876ea611Jeff Garzik		hp_flags & (MV_HP_ERRATA_60X1B2 | MV_HP_ERRATA_60X1C0);
216747c2b677daeed9c79ecb7167c211ff36876ea611Jeff Garzik	u32 m2, tmp;
216847c2b677daeed9c79ecb7167c211ff36876ea611Jeff Garzik
216947c2b677daeed9c79ecb7167c211ff36876ea611Jeff Garzik	if (fix_phy_mode2) {
217047c2b677daeed9c79ecb7167c211ff36876ea611Jeff Garzik		m2 = readl(port_mmio + PHY_MODE2);
217147c2b677daeed9c79ecb7167c211ff36876ea611Jeff Garzik		m2 &= ~(1 << 16);
217247c2b677daeed9c79ecb7167c211ff36876ea611Jeff Garzik		m2 |= (1 << 31);
217347c2b677daeed9c79ecb7167c211ff36876ea611Jeff Garzik		writel(m2, port_mmio + PHY_MODE2);
217447c2b677daeed9c79ecb7167c211ff36876ea611Jeff Garzik
217547c2b677daeed9c79ecb7167c211ff36876ea611Jeff Garzik		udelay(200);
217647c2b677daeed9c79ecb7167c211ff36876ea611Jeff Garzik
217747c2b677daeed9c79ecb7167c211ff36876ea611Jeff Garzik		m2 = readl(port_mmio + PHY_MODE2);
217847c2b677daeed9c79ecb7167c211ff36876ea611Jeff Garzik		m2 &= ~((1 << 16) | (1 << 31));
217947c2b677daeed9c79ecb7167c211ff36876ea611Jeff Garzik		writel(m2, port_mmio + PHY_MODE2);
218047c2b677daeed9c79ecb7167c211ff36876ea611Jeff Garzik
218147c2b677daeed9c79ecb7167c211ff36876ea611Jeff Garzik		udelay(200);
218247c2b677daeed9c79ecb7167c211ff36876ea611Jeff Garzik	}
218347c2b677daeed9c79ecb7167c211ff36876ea611Jeff Garzik
218447c2b677daeed9c79ecb7167c211ff36876ea611Jeff Garzik	/* who knows what this magic does */
218547c2b677daeed9c79ecb7167c211ff36876ea611Jeff Garzik	tmp = readl(port_mmio + PHY_MODE3);
218647c2b677daeed9c79ecb7167c211ff36876ea611Jeff Garzik	tmp &= ~0x7F800000;
218747c2b677daeed9c79ecb7167c211ff36876ea611Jeff Garzik	tmp |= 0x2A800000;
218847c2b677daeed9c79ecb7167c211ff36876ea611Jeff Garzik	writel(tmp, port_mmio + PHY_MODE3);
2189bca1c4eb9411533d613123618c0d127fae532595Jeff Garzik
2190bca1c4eb9411533d613123618c0d127fae532595Jeff Garzik	if (fix_phy_mode4) {
219147c2b677daeed9c79ecb7167c211ff36876ea611Jeff Garzik		u32 m4;
2192bca1c4eb9411533d613123618c0d127fae532595Jeff Garzik
2193bca1c4eb9411533d613123618c0d127fae532595Jeff Garzik		m4 = readl(port_mmio + PHY_MODE4);
219447c2b677daeed9c79ecb7167c211ff36876ea611Jeff Garzik
219547c2b677daeed9c79ecb7167c211ff36876ea611Jeff Garzik		if (hp_flags & MV_HP_ERRATA_60X1B2)
219647c2b677daeed9c79ecb7167c211ff36876ea611Jeff Garzik			tmp = readl(port_mmio + 0x310);
2197bca1c4eb9411533d613123618c0d127fae532595Jeff Garzik
2198bca1c4eb9411533d613123618c0d127fae532595Jeff Garzik		m4 = (m4 & ~(1 << 1)) | (1 << 0);
2199bca1c4eb9411533d613123618c0d127fae532595Jeff Garzik
2200bca1c4eb9411533d613123618c0d127fae532595Jeff Garzik		writel(m4, port_mmio + PHY_MODE4);
220147c2b677daeed9c79ecb7167c211ff36876ea611Jeff Garzik
220247c2b677daeed9c79ecb7167c211ff36876ea611Jeff Garzik		if (hp_flags & MV_HP_ERRATA_60X1B2)
220347c2b677daeed9c79ecb7167c211ff36876ea611Jeff Garzik			writel(tmp, port_mmio + 0x310);
2204bca1c4eb9411533d613123618c0d127fae532595Jeff Garzik	}
2205bca1c4eb9411533d613123618c0d127fae532595Jeff Garzik
2206bca1c4eb9411533d613123618c0d127fae532595Jeff Garzik	/* Revert values of pre-emphasis and signal amps to the saved ones */
2207bca1c4eb9411533d613123618c0d127fae532595Jeff Garzik	m2 = readl(port_mmio + PHY_MODE2);
2208bca1c4eb9411533d613123618c0d127fae532595Jeff Garzik
2209bca1c4eb9411533d613123618c0d127fae532595Jeff Garzik	m2 &= ~MV_M2_PREAMP_MASK;
22102a47ce06d534692f9bd2bf4e90a20fc9b1054c39Jeff Garzik	m2 |= hpriv->signal[port].amps;
22112a47ce06d534692f9bd2bf4e90a20fc9b1054c39Jeff Garzik	m2 |= hpriv->signal[port].pre;
221247c2b677daeed9c79ecb7167c211ff36876ea611Jeff Garzik	m2 &= ~(1 << 16);
2213bca1c4eb9411533d613123618c0d127fae532595Jeff Garzik
2214e4e7b89280d1d666e2c09e5ad36cf071796c4c7eJeff Garzik	/* according to mvSata 3.6.1, some IIE values are fixed */
2215e4e7b89280d1d666e2c09e5ad36cf071796c4c7eJeff Garzik	if (IS_GEN_IIE(hpriv)) {
2216e4e7b89280d1d666e2c09e5ad36cf071796c4c7eJeff Garzik		m2 &= ~0xC30FF01F;
2217e4e7b89280d1d666e2c09e5ad36cf071796c4c7eJeff Garzik		m2 |= 0x0000900F;
2218e4e7b89280d1d666e2c09e5ad36cf071796c4c7eJeff Garzik	}
2219e4e7b89280d1d666e2c09e5ad36cf071796c4c7eJeff Garzik
2220bca1c4eb9411533d613123618c0d127fae532595Jeff Garzik	writel(m2, port_mmio + PHY_MODE2);
2221bca1c4eb9411533d613123618c0d127fae532595Jeff Garzik}
2222bca1c4eb9411533d613123618c0d127fae532595Jeff Garzik
2223c9d39130123238ac18478a42e25cb7996eacfcc0Jeff Garzikstatic void mv_channel_reset(struct mv_host_priv *hpriv, void __iomem *mmio,
2224c9d39130123238ac18478a42e25cb7996eacfcc0Jeff Garzik			     unsigned int port_no)
2225c9d39130123238ac18478a42e25cb7996eacfcc0Jeff Garzik{
2226c9d39130123238ac18478a42e25cb7996eacfcc0Jeff Garzik	void __iomem *port_mmio = mv_port_base(mmio, port_no);
2227c9d39130123238ac18478a42e25cb7996eacfcc0Jeff Garzik
2228c9d39130123238ac18478a42e25cb7996eacfcc0Jeff Garzik	writelfl(ATA_RST, port_mmio + EDMA_CMD_OFS);
2229c9d39130123238ac18478a42e25cb7996eacfcc0Jeff Garzik
2230ee9ccdf70163ca6408f6965e0fbc65baeac7312cJeff Garzik	if (IS_GEN_II(hpriv)) {
2231c9d39130123238ac18478a42e25cb7996eacfcc0Jeff Garzik		u32 ifctl = readl(port_mmio + SATA_INTERFACE_CTL);
2232eb46d684600ac145501805a294c94675e82eab2eMark Lord		ifctl |= (1 << 7);		/* enable gen2i speed */
2233eb46d684600ac145501805a294c94675e82eab2eMark Lord		ifctl = (ifctl & 0xfff) | 0x9b1000; /* from chip spec */
2234c9d39130123238ac18478a42e25cb7996eacfcc0Jeff Garzik		writelfl(ifctl, port_mmio + SATA_INTERFACE_CTL);
2235c9d39130123238ac18478a42e25cb7996eacfcc0Jeff Garzik	}
2236c9d39130123238ac18478a42e25cb7996eacfcc0Jeff Garzik
2237c9d39130123238ac18478a42e25cb7996eacfcc0Jeff Garzik	udelay(25);		/* allow reset propagation */
2238c9d39130123238ac18478a42e25cb7996eacfcc0Jeff Garzik
2239c9d39130123238ac18478a42e25cb7996eacfcc0Jeff Garzik	/* Spec never mentions clearing the bit.  Marvell's driver does
2240c9d39130123238ac18478a42e25cb7996eacfcc0Jeff Garzik	 * clear the bit, however.
2241c9d39130123238ac18478a42e25cb7996eacfcc0Jeff Garzik	 */
2242c9d39130123238ac18478a42e25cb7996eacfcc0Jeff Garzik	writelfl(0, port_mmio + EDMA_CMD_OFS);
2243c9d39130123238ac18478a42e25cb7996eacfcc0Jeff Garzik
2244c9d39130123238ac18478a42e25cb7996eacfcc0Jeff Garzik	hpriv->ops->phy_errata(hpriv, mmio, port_no);
2245c9d39130123238ac18478a42e25cb7996eacfcc0Jeff Garzik
2246ee9ccdf70163ca6408f6965e0fbc65baeac7312cJeff Garzik	if (IS_GEN_I(hpriv))
2247c9d39130123238ac18478a42e25cb7996eacfcc0Jeff Garzik		mdelay(1);
2248c9d39130123238ac18478a42e25cb7996eacfcc0Jeff Garzik}
2249c9d39130123238ac18478a42e25cb7996eacfcc0Jeff Garzik
225005b308e1df6d9d673daedb517969241f41278b52Brett Russ/**
2251bdd4dddee325a7dce3e84cf48201a06aa8508aa4Jeff Garzik *      mv_phy_reset - Perform eDMA reset followed by COMRESET
225205b308e1df6d9d673daedb517969241f41278b52Brett Russ *      @ap: ATA channel to manipulate
225305b308e1df6d9d673daedb517969241f41278b52Brett Russ *
225405b308e1df6d9d673daedb517969241f41278b52Brett Russ *      Part of this is taken from __sata_phy_reset and modified to
225505b308e1df6d9d673daedb517969241f41278b52Brett Russ *      not sleep since this routine gets called from interrupt level.
225605b308e1df6d9d673daedb517969241f41278b52Brett Russ *
225705b308e1df6d9d673daedb517969241f41278b52Brett Russ *      LOCKING:
225805b308e1df6d9d673daedb517969241f41278b52Brett Russ *      Inherited from caller.  This is coded to safe to call at
225905b308e1df6d9d673daedb517969241f41278b52Brett Russ *      interrupt level, i.e. it does not sleep.
226031961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ */
2261bdd4dddee325a7dce3e84cf48201a06aa8508aa4Jeff Garzikstatic void mv_phy_reset(struct ata_port *ap, unsigned int *class,
2262bdd4dddee325a7dce3e84cf48201a06aa8508aa4Jeff Garzik			 unsigned long deadline)
226320f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ{
2264095fec887eaa1c38d17c0c929a6733c744a9fa1fJeff Garzik	struct mv_port_priv *pp	= ap->private_data;
2265cca3974e48607c3775dc73b544a5700b2e37c21aJeff Garzik	struct mv_host_priv *hpriv = ap->host->private_data;
226620f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ	void __iomem *port_mmio = mv_ap_base(ap);
226722374677d18c5eeefd3a283431d312b8c44fef02Jeff Garzik	int retry = 5;
226822374677d18c5eeefd3a283431d312b8c44fef02Jeff Garzik	u32 sstatus;
226920f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ
227020f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ	VPRINTK("ENTER, port %u, mmio 0x%p\n", ap->port_no, port_mmio);
227120f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ
2272da3dbb17a0e9a9ec7f5aed95f1fddadb790edc9dTejun Heo#ifdef DEBUG
2273da3dbb17a0e9a9ec7f5aed95f1fddadb790edc9dTejun Heo	{
2274da3dbb17a0e9a9ec7f5aed95f1fddadb790edc9dTejun Heo		u32 sstatus, serror, scontrol;
2275da3dbb17a0e9a9ec7f5aed95f1fddadb790edc9dTejun Heo
2276da3dbb17a0e9a9ec7f5aed95f1fddadb790edc9dTejun Heo		mv_scr_read(ap, SCR_STATUS, &sstatus);
2277da3dbb17a0e9a9ec7f5aed95f1fddadb790edc9dTejun Heo		mv_scr_read(ap, SCR_ERROR, &serror);
2278da3dbb17a0e9a9ec7f5aed95f1fddadb790edc9dTejun Heo		mv_scr_read(ap, SCR_CONTROL, &scontrol);
2279da3dbb17a0e9a9ec7f5aed95f1fddadb790edc9dTejun Heo		DPRINTK("S-regs after ATA_RST: SStat 0x%08x SErr 0x%08x "
22802d79ab8fd7a7bf3a45d0e948ae27b3dd95ce95eaSaeed Bishara			"SCtrl 0x%08x\n", sstatus, serror, scontrol);
2281da3dbb17a0e9a9ec7f5aed95f1fddadb790edc9dTejun Heo	}
2282da3dbb17a0e9a9ec7f5aed95f1fddadb790edc9dTejun Heo#endif
228320f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ
228422374677d18c5eeefd3a283431d312b8c44fef02Jeff Garzik	/* Issue COMRESET via SControl */
228522374677d18c5eeefd3a283431d312b8c44fef02Jeff Garzikcomreset_retry:
2286936fd7328657884d5a69a55666c74a55aa83ca27Tejun Heo	sata_scr_write_flush(&ap->link, SCR_CONTROL, 0x301);
2287bdd4dddee325a7dce3e84cf48201a06aa8508aa4Jeff Garzik	msleep(1);
228822374677d18c5eeefd3a283431d312b8c44fef02Jeff Garzik
2289936fd7328657884d5a69a55666c74a55aa83ca27Tejun Heo	sata_scr_write_flush(&ap->link, SCR_CONTROL, 0x300);
2290bdd4dddee325a7dce3e84cf48201a06aa8508aa4Jeff Garzik	msleep(20);
229122374677d18c5eeefd3a283431d312b8c44fef02Jeff Garzik
229231961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ	do {
2293936fd7328657884d5a69a55666c74a55aa83ca27Tejun Heo		sata_scr_read(&ap->link, SCR_STATUS, &sstatus);
229462f1d0e6de138b91d55fbd7d579c837ed62e9e31Andres Salomon		if (((sstatus & 0x3) == 3) || ((sstatus & 0x3) == 0))
229531961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ			break;
229622374677d18c5eeefd3a283431d312b8c44fef02Jeff Garzik
2297bdd4dddee325a7dce3e84cf48201a06aa8508aa4Jeff Garzik		msleep(1);
2298c5d3e45a2200a0905dc45b72714726b7aac3aaf1Jeff Garzik	} while (time_before(jiffies, deadline));
229920f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ
230022374677d18c5eeefd3a283431d312b8c44fef02Jeff Garzik	/* work around errata */
2301ee9ccdf70163ca6408f6965e0fbc65baeac7312cJeff Garzik	if (IS_GEN_II(hpriv) &&
230222374677d18c5eeefd3a283431d312b8c44fef02Jeff Garzik	    (sstatus != 0x0) && (sstatus != 0x113) && (sstatus != 0x123) &&
230322374677d18c5eeefd3a283431d312b8c44fef02Jeff Garzik	    (retry-- > 0))
230422374677d18c5eeefd3a283431d312b8c44fef02Jeff Garzik		goto comreset_retry;
2305095fec887eaa1c38d17c0c929a6733c744a9fa1fJeff Garzik
2306da3dbb17a0e9a9ec7f5aed95f1fddadb790edc9dTejun Heo#ifdef DEBUG
2307da3dbb17a0e9a9ec7f5aed95f1fddadb790edc9dTejun Heo	{
2308da3dbb17a0e9a9ec7f5aed95f1fddadb790edc9dTejun Heo		u32 sstatus, serror, scontrol;
2309da3dbb17a0e9a9ec7f5aed95f1fddadb790edc9dTejun Heo
2310da3dbb17a0e9a9ec7f5aed95f1fddadb790edc9dTejun Heo		mv_scr_read(ap, SCR_STATUS, &sstatus);
2311da3dbb17a0e9a9ec7f5aed95f1fddadb790edc9dTejun Heo		mv_scr_read(ap, SCR_ERROR, &serror);
2312da3dbb17a0e9a9ec7f5aed95f1fddadb790edc9dTejun Heo		mv_scr_read(ap, SCR_CONTROL, &scontrol);
2313da3dbb17a0e9a9ec7f5aed95f1fddadb790edc9dTejun Heo		DPRINTK("S-regs after PHY wake: SStat 0x%08x SErr 0x%08x "
2314da3dbb17a0e9a9ec7f5aed95f1fddadb790edc9dTejun Heo			"SCtrl 0x%08x\n", sstatus, serror, scontrol);
2315da3dbb17a0e9a9ec7f5aed95f1fddadb790edc9dTejun Heo	}
2316da3dbb17a0e9a9ec7f5aed95f1fddadb790edc9dTejun Heo#endif
231731961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ
2318936fd7328657884d5a69a55666c74a55aa83ca27Tejun Heo	if (ata_link_offline(&ap->link)) {
2319bdd4dddee325a7dce3e84cf48201a06aa8508aa4Jeff Garzik		*class = ATA_DEV_NONE;
232020f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ		return;
232120f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ	}
232220f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ
232322374677d18c5eeefd3a283431d312b8c44fef02Jeff Garzik	/* even after SStatus reflects that device is ready,
232422374677d18c5eeefd3a283431d312b8c44fef02Jeff Garzik	 * it seems to take a while for link to be fully
232522374677d18c5eeefd3a283431d312b8c44fef02Jeff Garzik	 * established (and thus Status no longer 0x80/0x7F),
232622374677d18c5eeefd3a283431d312b8c44fef02Jeff Garzik	 * so we poll a bit for that, here.
232722374677d18c5eeefd3a283431d312b8c44fef02Jeff Garzik	 */
232822374677d18c5eeefd3a283431d312b8c44fef02Jeff Garzik	retry = 20;
232922374677d18c5eeefd3a283431d312b8c44fef02Jeff Garzik	while (1) {
233022374677d18c5eeefd3a283431d312b8c44fef02Jeff Garzik		u8 drv_stat = ata_check_status(ap);
233122374677d18c5eeefd3a283431d312b8c44fef02Jeff Garzik		if ((drv_stat != 0x80) && (drv_stat != 0x7f))
233222374677d18c5eeefd3a283431d312b8c44fef02Jeff Garzik			break;
2333bdd4dddee325a7dce3e84cf48201a06aa8508aa4Jeff Garzik		msleep(500);
233422374677d18c5eeefd3a283431d312b8c44fef02Jeff Garzik		if (retry-- <= 0)
233522374677d18c5eeefd3a283431d312b8c44fef02Jeff Garzik			break;
2336bdd4dddee325a7dce3e84cf48201a06aa8508aa4Jeff Garzik		if (time_after(jiffies, deadline))
2337bdd4dddee325a7dce3e84cf48201a06aa8508aa4Jeff Garzik			break;
233822374677d18c5eeefd3a283431d312b8c44fef02Jeff Garzik	}
233922374677d18c5eeefd3a283431d312b8c44fef02Jeff Garzik
2340bdd4dddee325a7dce3e84cf48201a06aa8508aa4Jeff Garzik	/* FIXME: if we passed the deadline, the following
2341bdd4dddee325a7dce3e84cf48201a06aa8508aa4Jeff Garzik	 * code probably produces an invalid result
2342bdd4dddee325a7dce3e84cf48201a06aa8508aa4Jeff Garzik	 */
234320f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ
2344bdd4dddee325a7dce3e84cf48201a06aa8508aa4Jeff Garzik	/* finally, read device signature from TF registers */
23453f19859ee95a38c066a0420eb8a30c76ecd67a42Tejun Heo	*class = ata_dev_try_classify(ap->link.device, 1, NULL);
2346095fec887eaa1c38d17c0c929a6733c744a9fa1fJeff Garzik
2347095fec887eaa1c38d17c0c929a6733c744a9fa1fJeff Garzik	writelfl(0, port_mmio + EDMA_ERR_IRQ_CAUSE_OFS);
2348095fec887eaa1c38d17c0c929a6733c744a9fa1fJeff Garzik
2349bdd4dddee325a7dce3e84cf48201a06aa8508aa4Jeff Garzik	WARN_ON(pp->pp_flags & MV_PP_FLAG_EDMA_EN);
2350095fec887eaa1c38d17c0c929a6733c744a9fa1fJeff Garzik
2351bca1c4eb9411533d613123618c0d127fae532595Jeff Garzik	VPRINTK("EXIT\n");
235220f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ}
235320f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ
2354cc0680a580b5be81a1ca321b58f8e9b80b5c1052Tejun Heostatic int mv_prereset(struct ata_link *link, unsigned long deadline)
235522374677d18c5eeefd3a283431d312b8c44fef02Jeff Garzik{
2356cc0680a580b5be81a1ca321b58f8e9b80b5c1052Tejun Heo	struct ata_port *ap = link->ap;
2357bdd4dddee325a7dce3e84cf48201a06aa8508aa4Jeff Garzik	struct mv_port_priv *pp	= ap->private_data;
2358cc0680a580b5be81a1ca321b58f8e9b80b5c1052Tejun Heo	struct ata_eh_context *ehc = &link->eh_context;
2359bdd4dddee325a7dce3e84cf48201a06aa8508aa4Jeff Garzik	int rc;
23600ea9e179f436f153fc19fdaef7abbc1e0da20762Jeff Garzik
2361bdd4dddee325a7dce3e84cf48201a06aa8508aa4Jeff Garzik	rc = mv_stop_dma(ap);
2362bdd4dddee325a7dce3e84cf48201a06aa8508aa4Jeff Garzik	if (rc)
2363bdd4dddee325a7dce3e84cf48201a06aa8508aa4Jeff Garzik		ehc->i.action |= ATA_EH_HARDRESET;
2364bdd4dddee325a7dce3e84cf48201a06aa8508aa4Jeff Garzik
2365bdd4dddee325a7dce3e84cf48201a06aa8508aa4Jeff Garzik	if (!(pp->pp_flags & MV_PP_FLAG_HAD_A_RESET)) {
2366bdd4dddee325a7dce3e84cf48201a06aa8508aa4Jeff Garzik		pp->pp_flags |= MV_PP_FLAG_HAD_A_RESET;
2367bdd4dddee325a7dce3e84cf48201a06aa8508aa4Jeff Garzik		ehc->i.action |= ATA_EH_HARDRESET;
2368bdd4dddee325a7dce3e84cf48201a06aa8508aa4Jeff Garzik	}
2369bdd4dddee325a7dce3e84cf48201a06aa8508aa4Jeff Garzik
2370bdd4dddee325a7dce3e84cf48201a06aa8508aa4Jeff Garzik	/* if we're about to do hardreset, nothing more to do */
2371bdd4dddee325a7dce3e84cf48201a06aa8508aa4Jeff Garzik	if (ehc->i.action & ATA_EH_HARDRESET)
2372bdd4dddee325a7dce3e84cf48201a06aa8508aa4Jeff Garzik		return 0;
2373bdd4dddee325a7dce3e84cf48201a06aa8508aa4Jeff Garzik
2374cc0680a580b5be81a1ca321b58f8e9b80b5c1052Tejun Heo	if (ata_link_online(link))
2375bdd4dddee325a7dce3e84cf48201a06aa8508aa4Jeff Garzik		rc = ata_wait_ready(ap, deadline);
2376bdd4dddee325a7dce3e84cf48201a06aa8508aa4Jeff Garzik	else
2377bdd4dddee325a7dce3e84cf48201a06aa8508aa4Jeff Garzik		rc = -ENODEV;
2378bdd4dddee325a7dce3e84cf48201a06aa8508aa4Jeff Garzik
2379bdd4dddee325a7dce3e84cf48201a06aa8508aa4Jeff Garzik	return rc;
238022374677d18c5eeefd3a283431d312b8c44fef02Jeff Garzik}
238122374677d18c5eeefd3a283431d312b8c44fef02Jeff Garzik
2382cc0680a580b5be81a1ca321b58f8e9b80b5c1052Tejun Heostatic int mv_hardreset(struct ata_link *link, unsigned int *class,
2383bdd4dddee325a7dce3e84cf48201a06aa8508aa4Jeff Garzik			unsigned long deadline)
238431961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ{
2385cc0680a580b5be81a1ca321b58f8e9b80b5c1052Tejun Heo	struct ata_port *ap = link->ap;
2386bdd4dddee325a7dce3e84cf48201a06aa8508aa4Jeff Garzik	struct mv_host_priv *hpriv = ap->host->private_data;
23870d5ff566779f894ca9937231a181eb31e4adff0eTejun Heo	void __iomem *mmio = ap->host->iomap[MV_PRIMARY_BAR];
238831961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ
2389bdd4dddee325a7dce3e84cf48201a06aa8508aa4Jeff Garzik	mv_stop_dma(ap);
239031961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ
2391bdd4dddee325a7dce3e84cf48201a06aa8508aa4Jeff Garzik	mv_channel_reset(hpriv, mmio, ap->port_no);
239231961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ
2393bdd4dddee325a7dce3e84cf48201a06aa8508aa4Jeff Garzik	mv_phy_reset(ap, class, deadline);
2394bdd4dddee325a7dce3e84cf48201a06aa8508aa4Jeff Garzik
2395bdd4dddee325a7dce3e84cf48201a06aa8508aa4Jeff Garzik	return 0;
2396bdd4dddee325a7dce3e84cf48201a06aa8508aa4Jeff Garzik}
2397bdd4dddee325a7dce3e84cf48201a06aa8508aa4Jeff Garzik
2398cc0680a580b5be81a1ca321b58f8e9b80b5c1052Tejun Heostatic void mv_postreset(struct ata_link *link, unsigned int *classes)
2399bdd4dddee325a7dce3e84cf48201a06aa8508aa4Jeff Garzik{
2400cc0680a580b5be81a1ca321b58f8e9b80b5c1052Tejun Heo	struct ata_port *ap = link->ap;
2401bdd4dddee325a7dce3e84cf48201a06aa8508aa4Jeff Garzik	u32 serr;
2402bdd4dddee325a7dce3e84cf48201a06aa8508aa4Jeff Garzik
2403bdd4dddee325a7dce3e84cf48201a06aa8508aa4Jeff Garzik	/* print link status */
2404cc0680a580b5be81a1ca321b58f8e9b80b5c1052Tejun Heo	sata_print_link_status(link);
240531961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ
2406bdd4dddee325a7dce3e84cf48201a06aa8508aa4Jeff Garzik	/* clear SError */
2407cc0680a580b5be81a1ca321b58f8e9b80b5c1052Tejun Heo	sata_scr_read(link, SCR_ERROR, &serr);
2408cc0680a580b5be81a1ca321b58f8e9b80b5c1052Tejun Heo	sata_scr_write_flush(link, SCR_ERROR, serr);
2409bdd4dddee325a7dce3e84cf48201a06aa8508aa4Jeff Garzik
2410bdd4dddee325a7dce3e84cf48201a06aa8508aa4Jeff Garzik	/* bail out if no device is present */
2411bdd4dddee325a7dce3e84cf48201a06aa8508aa4Jeff Garzik	if (classes[0] == ATA_DEV_NONE && classes[1] == ATA_DEV_NONE) {
2412bdd4dddee325a7dce3e84cf48201a06aa8508aa4Jeff Garzik		DPRINTK("EXIT, no device\n");
2413bdd4dddee325a7dce3e84cf48201a06aa8508aa4Jeff Garzik		return;
24149b358e305c1d783c8a4ebf00344e95deb9e38f3dMark Lord	}
2415bdd4dddee325a7dce3e84cf48201a06aa8508aa4Jeff Garzik
2416bdd4dddee325a7dce3e84cf48201a06aa8508aa4Jeff Garzik	/* set up device control */
2417bdd4dddee325a7dce3e84cf48201a06aa8508aa4Jeff Garzik	iowrite8(ap->ctl, ap->ioaddr.ctl_addr);
2418bdd4dddee325a7dce3e84cf48201a06aa8508aa4Jeff Garzik}
2419bdd4dddee325a7dce3e84cf48201a06aa8508aa4Jeff Garzik
2420bdd4dddee325a7dce3e84cf48201a06aa8508aa4Jeff Garzikstatic void mv_error_handler(struct ata_port *ap)
2421bdd4dddee325a7dce3e84cf48201a06aa8508aa4Jeff Garzik{
2422bdd4dddee325a7dce3e84cf48201a06aa8508aa4Jeff Garzik	ata_do_eh(ap, mv_prereset, ata_std_softreset,
2423bdd4dddee325a7dce3e84cf48201a06aa8508aa4Jeff Garzik		  mv_hardreset, mv_postreset);
2424bdd4dddee325a7dce3e84cf48201a06aa8508aa4Jeff Garzik}
2425bdd4dddee325a7dce3e84cf48201a06aa8508aa4Jeff Garzik
2426bdd4dddee325a7dce3e84cf48201a06aa8508aa4Jeff Garzikstatic void mv_post_int_cmd(struct ata_queued_cmd *qc)
2427bdd4dddee325a7dce3e84cf48201a06aa8508aa4Jeff Garzik{
2428bdd4dddee325a7dce3e84cf48201a06aa8508aa4Jeff Garzik	mv_stop_dma(qc->ap);
2429bdd4dddee325a7dce3e84cf48201a06aa8508aa4Jeff Garzik}
2430bdd4dddee325a7dce3e84cf48201a06aa8508aa4Jeff Garzik
2431bdd4dddee325a7dce3e84cf48201a06aa8508aa4Jeff Garzikstatic void mv_eh_freeze(struct ata_port *ap)
2432bdd4dddee325a7dce3e84cf48201a06aa8508aa4Jeff Garzik{
2433bdd4dddee325a7dce3e84cf48201a06aa8508aa4Jeff Garzik	void __iomem *mmio = ap->host->iomap[MV_PRIMARY_BAR];
2434bdd4dddee325a7dce3e84cf48201a06aa8508aa4Jeff Garzik	unsigned int hc = (ap->port_no > 3) ? 1 : 0;
2435bdd4dddee325a7dce3e84cf48201a06aa8508aa4Jeff Garzik	u32 tmp, mask;
2436bdd4dddee325a7dce3e84cf48201a06aa8508aa4Jeff Garzik	unsigned int shift;
2437bdd4dddee325a7dce3e84cf48201a06aa8508aa4Jeff Garzik
2438bdd4dddee325a7dce3e84cf48201a06aa8508aa4Jeff Garzik	/* FIXME: handle coalescing completion events properly */
2439bdd4dddee325a7dce3e84cf48201a06aa8508aa4Jeff Garzik
2440bdd4dddee325a7dce3e84cf48201a06aa8508aa4Jeff Garzik	shift = ap->port_no * 2;
2441bdd4dddee325a7dce3e84cf48201a06aa8508aa4Jeff Garzik	if (hc > 0)
2442bdd4dddee325a7dce3e84cf48201a06aa8508aa4Jeff Garzik		shift++;
2443bdd4dddee325a7dce3e84cf48201a06aa8508aa4Jeff Garzik
2444bdd4dddee325a7dce3e84cf48201a06aa8508aa4Jeff Garzik	mask = 0x3 << shift;
2445bdd4dddee325a7dce3e84cf48201a06aa8508aa4Jeff Garzik
2446bdd4dddee325a7dce3e84cf48201a06aa8508aa4Jeff Garzik	/* disable assertion of portN err, done events */
2447bdd4dddee325a7dce3e84cf48201a06aa8508aa4Jeff Garzik	tmp = readl(mmio + HC_MAIN_IRQ_MASK_OFS);
2448bdd4dddee325a7dce3e84cf48201a06aa8508aa4Jeff Garzik	writelfl(tmp & ~mask, mmio + HC_MAIN_IRQ_MASK_OFS);
2449bdd4dddee325a7dce3e84cf48201a06aa8508aa4Jeff Garzik}
2450bdd4dddee325a7dce3e84cf48201a06aa8508aa4Jeff Garzik
2451bdd4dddee325a7dce3e84cf48201a06aa8508aa4Jeff Garzikstatic void mv_eh_thaw(struct ata_port *ap)
2452bdd4dddee325a7dce3e84cf48201a06aa8508aa4Jeff Garzik{
2453bdd4dddee325a7dce3e84cf48201a06aa8508aa4Jeff Garzik	void __iomem *mmio = ap->host->iomap[MV_PRIMARY_BAR];
2454bdd4dddee325a7dce3e84cf48201a06aa8508aa4Jeff Garzik	unsigned int hc = (ap->port_no > 3) ? 1 : 0;
2455bdd4dddee325a7dce3e84cf48201a06aa8508aa4Jeff Garzik	void __iomem *hc_mmio = mv_hc_base(mmio, hc);
2456bdd4dddee325a7dce3e84cf48201a06aa8508aa4Jeff Garzik	void __iomem *port_mmio = mv_ap_base(ap);
2457bdd4dddee325a7dce3e84cf48201a06aa8508aa4Jeff Garzik	u32 tmp, mask, hc_irq_cause;
2458bdd4dddee325a7dce3e84cf48201a06aa8508aa4Jeff Garzik	unsigned int shift, hc_port_no = ap->port_no;
2459bdd4dddee325a7dce3e84cf48201a06aa8508aa4Jeff Garzik
2460bdd4dddee325a7dce3e84cf48201a06aa8508aa4Jeff Garzik	/* FIXME: handle coalescing completion events properly */
2461bdd4dddee325a7dce3e84cf48201a06aa8508aa4Jeff Garzik
2462bdd4dddee325a7dce3e84cf48201a06aa8508aa4Jeff Garzik	shift = ap->port_no * 2;
2463bdd4dddee325a7dce3e84cf48201a06aa8508aa4Jeff Garzik	if (hc > 0) {
2464bdd4dddee325a7dce3e84cf48201a06aa8508aa4Jeff Garzik		shift++;
2465bdd4dddee325a7dce3e84cf48201a06aa8508aa4Jeff Garzik		hc_port_no -= 4;
2466bdd4dddee325a7dce3e84cf48201a06aa8508aa4Jeff Garzik	}
2467bdd4dddee325a7dce3e84cf48201a06aa8508aa4Jeff Garzik
2468bdd4dddee325a7dce3e84cf48201a06aa8508aa4Jeff Garzik	mask = 0x3 << shift;
2469bdd4dddee325a7dce3e84cf48201a06aa8508aa4Jeff Garzik
2470bdd4dddee325a7dce3e84cf48201a06aa8508aa4Jeff Garzik	/* clear EDMA errors on this port */
2471bdd4dddee325a7dce3e84cf48201a06aa8508aa4Jeff Garzik	writel(0, port_mmio + EDMA_ERR_IRQ_CAUSE_OFS);
2472bdd4dddee325a7dce3e84cf48201a06aa8508aa4Jeff Garzik
2473bdd4dddee325a7dce3e84cf48201a06aa8508aa4Jeff Garzik	/* clear pending irq events */
2474bdd4dddee325a7dce3e84cf48201a06aa8508aa4Jeff Garzik	hc_irq_cause = readl(hc_mmio + HC_IRQ_CAUSE_OFS);
2475bdd4dddee325a7dce3e84cf48201a06aa8508aa4Jeff Garzik	hc_irq_cause &= ~(1 << hc_port_no);	/* clear CRPB-done */
2476bdd4dddee325a7dce3e84cf48201a06aa8508aa4Jeff Garzik	hc_irq_cause &= ~(1 << (hc_port_no + 8)); /* clear Device int */
2477bdd4dddee325a7dce3e84cf48201a06aa8508aa4Jeff Garzik	writel(hc_irq_cause, hc_mmio + HC_IRQ_CAUSE_OFS);
2478bdd4dddee325a7dce3e84cf48201a06aa8508aa4Jeff Garzik
2479bdd4dddee325a7dce3e84cf48201a06aa8508aa4Jeff Garzik	/* enable assertion of portN err, done events */
2480bdd4dddee325a7dce3e84cf48201a06aa8508aa4Jeff Garzik	tmp = readl(mmio + HC_MAIN_IRQ_MASK_OFS);
2481bdd4dddee325a7dce3e84cf48201a06aa8508aa4Jeff Garzik	writelfl(tmp | mask, mmio + HC_MAIN_IRQ_MASK_OFS);
248231961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ}
248331961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ
248405b308e1df6d9d673daedb517969241f41278b52Brett Russ/**
248505b308e1df6d9d673daedb517969241f41278b52Brett Russ *      mv_port_init - Perform some early initialization on a single port.
248605b308e1df6d9d673daedb517969241f41278b52Brett Russ *      @port: libata data structure storing shadow register addresses
248705b308e1df6d9d673daedb517969241f41278b52Brett Russ *      @port_mmio: base address of the port
248805b308e1df6d9d673daedb517969241f41278b52Brett Russ *
248905b308e1df6d9d673daedb517969241f41278b52Brett Russ *      Initialize shadow register mmio addresses, clear outstanding
249005b308e1df6d9d673daedb517969241f41278b52Brett Russ *      interrupts on the port, and unmask interrupts for the future
249105b308e1df6d9d673daedb517969241f41278b52Brett Russ *      start of the port.
249205b308e1df6d9d673daedb517969241f41278b52Brett Russ *
249305b308e1df6d9d673daedb517969241f41278b52Brett Russ *      LOCKING:
249405b308e1df6d9d673daedb517969241f41278b52Brett Russ *      Inherited from caller.
249505b308e1df6d9d673daedb517969241f41278b52Brett Russ */
249631961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russstatic void mv_port_init(struct ata_ioports *port,  void __iomem *port_mmio)
249720f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ{
24980d5ff566779f894ca9937231a181eb31e4adff0eTejun Heo	void __iomem *shd_base = port_mmio + SHD_BLK_OFS;
249931961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ	unsigned serr_ofs;
250031961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ
25018b260248d9e0e8b64bb72fd4dee03ad86984c344Jeff Garzik	/* PIO related setup
250231961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ	 */
250331961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ	port->data_addr = shd_base + (sizeof(u32) * ATA_REG_DATA);
25048b260248d9e0e8b64bb72fd4dee03ad86984c344Jeff Garzik	port->error_addr =
250531961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ		port->feature_addr = shd_base + (sizeof(u32) * ATA_REG_ERR);
250631961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ	port->nsect_addr = shd_base + (sizeof(u32) * ATA_REG_NSECT);
250731961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ	port->lbal_addr = shd_base + (sizeof(u32) * ATA_REG_LBAL);
250831961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ	port->lbam_addr = shd_base + (sizeof(u32) * ATA_REG_LBAM);
250931961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ	port->lbah_addr = shd_base + (sizeof(u32) * ATA_REG_LBAH);
251031961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ	port->device_addr = shd_base + (sizeof(u32) * ATA_REG_DEVICE);
25118b260248d9e0e8b64bb72fd4dee03ad86984c344Jeff Garzik	port->status_addr =
251231961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ		port->command_addr = shd_base + (sizeof(u32) * ATA_REG_STATUS);
251331961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ	/* special case: control/altstatus doesn't have ATA_REG_ address */
251431961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ	port->altstatus_addr = port->ctl_addr = shd_base + SHD_CTL_AST_OFS;
251531961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ
251631961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ	/* unused: */
25178d9db2d2fbae9e05022825c32f86e00c8e342860Randy Dunlap	port->cmd_addr = port->bmdma_addr = port->scr_addr = NULL;
251820f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ
251931961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ	/* Clear any currently outstanding port interrupt conditions */
252031961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ	serr_ofs = mv_scr_offset(SCR_ERROR);
252131961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ	writelfl(readl(port_mmio + serr_ofs), port_mmio + serr_ofs);
252231961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ	writelfl(0, port_mmio + EDMA_ERR_IRQ_CAUSE_OFS);
252331961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ
2524646a4da514f2555298481cb00dc5b3eb02b21b72Mark Lord	/* unmask all non-transient EDMA error interrupts */
2525646a4da514f2555298481cb00dc5b3eb02b21b72Mark Lord	writelfl(~EDMA_ERR_IRQ_TRANSIENT, port_mmio + EDMA_ERR_IRQ_MASK_OFS);
252620f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ
25278b260248d9e0e8b64bb72fd4dee03ad86984c344Jeff Garzik	VPRINTK("EDMA cfg=0x%08x EDMA IRQ err cause/mask=0x%08x/0x%08x\n",
252831961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ		readl(port_mmio + EDMA_CFG_OFS),
252931961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ		readl(port_mmio + EDMA_ERR_IRQ_CAUSE_OFS),
253031961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ		readl(port_mmio + EDMA_ERR_IRQ_MASK_OFS));
253120f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ}
253220f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ
25334447d35156169cf136e829eb6b5cac2d6370f2d9Tejun Heostatic int mv_chip_id(struct ata_host *host, unsigned int board_idx)
2534bca1c4eb9411533d613123618c0d127fae532595Jeff Garzik{
25354447d35156169cf136e829eb6b5cac2d6370f2d9Tejun Heo	struct pci_dev *pdev = to_pci_dev(host->dev);
25364447d35156169cf136e829eb6b5cac2d6370f2d9Tejun Heo	struct mv_host_priv *hpriv = host->private_data;
2537bca1c4eb9411533d613123618c0d127fae532595Jeff Garzik	u32 hp_flags = hpriv->hp_flags;
2538bca1c4eb9411533d613123618c0d127fae532595Jeff Garzik
25395796d1c4c89efff823259fda35b08ea66ebf8b23Jeff Garzik	switch (board_idx) {
254047c2b677daeed9c79ecb7167c211ff36876ea611Jeff Garzik	case chip_5080:
254147c2b677daeed9c79ecb7167c211ff36876ea611Jeff Garzik		hpriv->ops = &mv5xxx_ops;
2542ee9ccdf70163ca6408f6965e0fbc65baeac7312cJeff Garzik		hp_flags |= MV_HP_GEN_I;
254347c2b677daeed9c79ecb7167c211ff36876ea611Jeff Garzik
254444c10138fd4bbc4b6d6bff0873c24902f2a9da65Auke Kok		switch (pdev->revision) {
254547c2b677daeed9c79ecb7167c211ff36876ea611Jeff Garzik		case 0x1:
254647c2b677daeed9c79ecb7167c211ff36876ea611Jeff Garzik			hp_flags |= MV_HP_ERRATA_50XXB0;
254747c2b677daeed9c79ecb7167c211ff36876ea611Jeff Garzik			break;
254847c2b677daeed9c79ecb7167c211ff36876ea611Jeff Garzik		case 0x3:
254947c2b677daeed9c79ecb7167c211ff36876ea611Jeff Garzik			hp_flags |= MV_HP_ERRATA_50XXB2;
255047c2b677daeed9c79ecb7167c211ff36876ea611Jeff Garzik			break;
255147c2b677daeed9c79ecb7167c211ff36876ea611Jeff Garzik		default:
255247c2b677daeed9c79ecb7167c211ff36876ea611Jeff Garzik			dev_printk(KERN_WARNING, &pdev->dev,
255347c2b677daeed9c79ecb7167c211ff36876ea611Jeff Garzik			   "Applying 50XXB2 workarounds to unknown rev\n");
255447c2b677daeed9c79ecb7167c211ff36876ea611Jeff Garzik			hp_flags |= MV_HP_ERRATA_50XXB2;
255547c2b677daeed9c79ecb7167c211ff36876ea611Jeff Garzik			break;
255647c2b677daeed9c79ecb7167c211ff36876ea611Jeff Garzik		}
255747c2b677daeed9c79ecb7167c211ff36876ea611Jeff Garzik		break;
255847c2b677daeed9c79ecb7167c211ff36876ea611Jeff Garzik
2559bca1c4eb9411533d613123618c0d127fae532595Jeff Garzik	case chip_504x:
2560bca1c4eb9411533d613123618c0d127fae532595Jeff Garzik	case chip_508x:
256147c2b677daeed9c79ecb7167c211ff36876ea611Jeff Garzik		hpriv->ops = &mv5xxx_ops;
2562ee9ccdf70163ca6408f6965e0fbc65baeac7312cJeff Garzik		hp_flags |= MV_HP_GEN_I;
2563bca1c4eb9411533d613123618c0d127fae532595Jeff Garzik
256444c10138fd4bbc4b6d6bff0873c24902f2a9da65Auke Kok		switch (pdev->revision) {
256547c2b677daeed9c79ecb7167c211ff36876ea611Jeff Garzik		case 0x0:
256647c2b677daeed9c79ecb7167c211ff36876ea611Jeff Garzik			hp_flags |= MV_HP_ERRATA_50XXB0;
256747c2b677daeed9c79ecb7167c211ff36876ea611Jeff Garzik			break;
256847c2b677daeed9c79ecb7167c211ff36876ea611Jeff Garzik		case 0x3:
256947c2b677daeed9c79ecb7167c211ff36876ea611Jeff Garzik			hp_flags |= MV_HP_ERRATA_50XXB2;
257047c2b677daeed9c79ecb7167c211ff36876ea611Jeff Garzik			break;
257147c2b677daeed9c79ecb7167c211ff36876ea611Jeff Garzik		default:
257247c2b677daeed9c79ecb7167c211ff36876ea611Jeff Garzik			dev_printk(KERN_WARNING, &pdev->dev,
257347c2b677daeed9c79ecb7167c211ff36876ea611Jeff Garzik			   "Applying B2 workarounds to unknown rev\n");
257447c2b677daeed9c79ecb7167c211ff36876ea611Jeff Garzik			hp_flags |= MV_HP_ERRATA_50XXB2;
257547c2b677daeed9c79ecb7167c211ff36876ea611Jeff Garzik			break;
2576bca1c4eb9411533d613123618c0d127fae532595Jeff Garzik		}
2577bca1c4eb9411533d613123618c0d127fae532595Jeff Garzik		break;
2578bca1c4eb9411533d613123618c0d127fae532595Jeff Garzik
2579bca1c4eb9411533d613123618c0d127fae532595Jeff Garzik	case chip_604x:
2580bca1c4eb9411533d613123618c0d127fae532595Jeff Garzik	case chip_608x:
258147c2b677daeed9c79ecb7167c211ff36876ea611Jeff Garzik		hpriv->ops = &mv6xxx_ops;
2582ee9ccdf70163ca6408f6965e0fbc65baeac7312cJeff Garzik		hp_flags |= MV_HP_GEN_II;
258347c2b677daeed9c79ecb7167c211ff36876ea611Jeff Garzik
258444c10138fd4bbc4b6d6bff0873c24902f2a9da65Auke Kok		switch (pdev->revision) {
258547c2b677daeed9c79ecb7167c211ff36876ea611Jeff Garzik		case 0x7:
258647c2b677daeed9c79ecb7167c211ff36876ea611Jeff Garzik			hp_flags |= MV_HP_ERRATA_60X1B2;
258747c2b677daeed9c79ecb7167c211ff36876ea611Jeff Garzik			break;
258847c2b677daeed9c79ecb7167c211ff36876ea611Jeff Garzik		case 0x9:
258947c2b677daeed9c79ecb7167c211ff36876ea611Jeff Garzik			hp_flags |= MV_HP_ERRATA_60X1C0;
2590bca1c4eb9411533d613123618c0d127fae532595Jeff Garzik			break;
2591bca1c4eb9411533d613123618c0d127fae532595Jeff Garzik		default:
2592bca1c4eb9411533d613123618c0d127fae532595Jeff Garzik			dev_printk(KERN_WARNING, &pdev->dev,
259347c2b677daeed9c79ecb7167c211ff36876ea611Jeff Garzik				   "Applying B2 workarounds to unknown rev\n");
259447c2b677daeed9c79ecb7167c211ff36876ea611Jeff Garzik			hp_flags |= MV_HP_ERRATA_60X1B2;
2595bca1c4eb9411533d613123618c0d127fae532595Jeff Garzik			break;
2596bca1c4eb9411533d613123618c0d127fae532595Jeff Garzik		}
2597bca1c4eb9411533d613123618c0d127fae532595Jeff Garzik		break;
2598bca1c4eb9411533d613123618c0d127fae532595Jeff Garzik
2599e4e7b89280d1d666e2c09e5ad36cf071796c4c7eJeff Garzik	case chip_7042:
260002a121da5a53d415b6596bc19cc6999d295d32a4Mark Lord		hp_flags |= MV_HP_PCIE;
2601306b30f74d37f289033c696285e07ce0158a5d7bMark Lord		if (pdev->vendor == PCI_VENDOR_ID_TTI &&
2602306b30f74d37f289033c696285e07ce0158a5d7bMark Lord		    (pdev->device == 0x2300 || pdev->device == 0x2310))
2603306b30f74d37f289033c696285e07ce0158a5d7bMark Lord		{
26044e5200334e03e5620aa19d538300c13db270a063Mark Lord			/*
26054e5200334e03e5620aa19d538300c13db270a063Mark Lord			 * Highpoint RocketRAID PCIe 23xx series cards:
26064e5200334e03e5620aa19d538300c13db270a063Mark Lord			 *
26074e5200334e03e5620aa19d538300c13db270a063Mark Lord			 * Unconfigured drives are treated as "Legacy"
26084e5200334e03e5620aa19d538300c13db270a063Mark Lord			 * by the BIOS, and it overwrites sector 8 with
26094e5200334e03e5620aa19d538300c13db270a063Mark Lord			 * a "Lgcy" metadata block prior to Linux boot.
26104e5200334e03e5620aa19d538300c13db270a063Mark Lord			 *
26114e5200334e03e5620aa19d538300c13db270a063Mark Lord			 * Configured drives (RAID or JBOD) leave sector 8
26124e5200334e03e5620aa19d538300c13db270a063Mark Lord			 * alone, but instead overwrite a high numbered
26134e5200334e03e5620aa19d538300c13db270a063Mark Lord			 * sector for the RAID metadata.  This sector can
26144e5200334e03e5620aa19d538300c13db270a063Mark Lord			 * be determined exactly, by truncating the physical
26154e5200334e03e5620aa19d538300c13db270a063Mark Lord			 * drive capacity to a nice even GB value.
26164e5200334e03e5620aa19d538300c13db270a063Mark Lord			 *
26174e5200334e03e5620aa19d538300c13db270a063Mark Lord			 * RAID metadata is at: (dev->n_sectors & ~0xfffff)
26184e5200334e03e5620aa19d538300c13db270a063Mark Lord			 *
26194e5200334e03e5620aa19d538300c13db270a063Mark Lord			 * Warn the user, lest they think we're just buggy.
26204e5200334e03e5620aa19d538300c13db270a063Mark Lord			 */
26214e5200334e03e5620aa19d538300c13db270a063Mark Lord			printk(KERN_WARNING DRV_NAME ": Highpoint RocketRAID"
26224e5200334e03e5620aa19d538300c13db270a063Mark Lord				" BIOS CORRUPTS DATA on all attached drives,"
26234e5200334e03e5620aa19d538300c13db270a063Mark Lord				" regardless of if/how they are configured."
26244e5200334e03e5620aa19d538300c13db270a063Mark Lord				" BEWARE!\n");
26254e5200334e03e5620aa19d538300c13db270a063Mark Lord			printk(KERN_WARNING DRV_NAME ": For data safety, do not"
26264e5200334e03e5620aa19d538300c13db270a063Mark Lord				" use sectors 8-9 on \"Legacy\" drives,"
26274e5200334e03e5620aa19d538300c13db270a063Mark Lord				" and avoid the final two gigabytes on"
26284e5200334e03e5620aa19d538300c13db270a063Mark Lord				" all RocketRAID BIOS initialized drives.\n");
2629306b30f74d37f289033c696285e07ce0158a5d7bMark Lord		}
2630e4e7b89280d1d666e2c09e5ad36cf071796c4c7eJeff Garzik	case chip_6042:
2631e4e7b89280d1d666e2c09e5ad36cf071796c4c7eJeff Garzik		hpriv->ops = &mv6xxx_ops;
2632e4e7b89280d1d666e2c09e5ad36cf071796c4c7eJeff Garzik		hp_flags |= MV_HP_GEN_IIE;
2633e4e7b89280d1d666e2c09e5ad36cf071796c4c7eJeff Garzik
263444c10138fd4bbc4b6d6bff0873c24902f2a9da65Auke Kok		switch (pdev->revision) {
2635e4e7b89280d1d666e2c09e5ad36cf071796c4c7eJeff Garzik		case 0x0:
2636e4e7b89280d1d666e2c09e5ad36cf071796c4c7eJeff Garzik			hp_flags |= MV_HP_ERRATA_XX42A0;
2637e4e7b89280d1d666e2c09e5ad36cf071796c4c7eJeff Garzik			break;
2638e4e7b89280d1d666e2c09e5ad36cf071796c4c7eJeff Garzik		case 0x1:
2639e4e7b89280d1d666e2c09e5ad36cf071796c4c7eJeff Garzik			hp_flags |= MV_HP_ERRATA_60X1C0;
2640e4e7b89280d1d666e2c09e5ad36cf071796c4c7eJeff Garzik			break;
2641e4e7b89280d1d666e2c09e5ad36cf071796c4c7eJeff Garzik		default:
2642e4e7b89280d1d666e2c09e5ad36cf071796c4c7eJeff Garzik			dev_printk(KERN_WARNING, &pdev->dev,
2643e4e7b89280d1d666e2c09e5ad36cf071796c4c7eJeff Garzik			   "Applying 60X1C0 workarounds to unknown rev\n");
2644e4e7b89280d1d666e2c09e5ad36cf071796c4c7eJeff Garzik			hp_flags |= MV_HP_ERRATA_60X1C0;
2645e4e7b89280d1d666e2c09e5ad36cf071796c4c7eJeff Garzik			break;
2646e4e7b89280d1d666e2c09e5ad36cf071796c4c7eJeff Garzik		}
2647e4e7b89280d1d666e2c09e5ad36cf071796c4c7eJeff Garzik		break;
2648e4e7b89280d1d666e2c09e5ad36cf071796c4c7eJeff Garzik
2649bca1c4eb9411533d613123618c0d127fae532595Jeff Garzik	default:
26505796d1c4c89efff823259fda35b08ea66ebf8b23Jeff Garzik		dev_printk(KERN_ERR, &pdev->dev,
26515796d1c4c89efff823259fda35b08ea66ebf8b23Jeff Garzik			   "BUG: invalid board index %u\n", board_idx);
2652bca1c4eb9411533d613123618c0d127fae532595Jeff Garzik		return 1;
2653bca1c4eb9411533d613123618c0d127fae532595Jeff Garzik	}
2654bca1c4eb9411533d613123618c0d127fae532595Jeff Garzik
2655bca1c4eb9411533d613123618c0d127fae532595Jeff Garzik	hpriv->hp_flags = hp_flags;
265602a121da5a53d415b6596bc19cc6999d295d32a4Mark Lord	if (hp_flags & MV_HP_PCIE) {
265702a121da5a53d415b6596bc19cc6999d295d32a4Mark Lord		hpriv->irq_cause_ofs	= PCIE_IRQ_CAUSE_OFS;
265802a121da5a53d415b6596bc19cc6999d295d32a4Mark Lord		hpriv->irq_mask_ofs	= PCIE_IRQ_MASK_OFS;
265902a121da5a53d415b6596bc19cc6999d295d32a4Mark Lord		hpriv->unmask_all_irqs	= PCIE_UNMASK_ALL_IRQS;
266002a121da5a53d415b6596bc19cc6999d295d32a4Mark Lord	} else {
266102a121da5a53d415b6596bc19cc6999d295d32a4Mark Lord		hpriv->irq_cause_ofs	= PCI_IRQ_CAUSE_OFS;
266202a121da5a53d415b6596bc19cc6999d295d32a4Mark Lord		hpriv->irq_mask_ofs	= PCI_IRQ_MASK_OFS;
266302a121da5a53d415b6596bc19cc6999d295d32a4Mark Lord		hpriv->unmask_all_irqs	= PCI_UNMASK_ALL_IRQS;
266402a121da5a53d415b6596bc19cc6999d295d32a4Mark Lord	}
2665bca1c4eb9411533d613123618c0d127fae532595Jeff Garzik
2666bca1c4eb9411533d613123618c0d127fae532595Jeff Garzik	return 0;
2667bca1c4eb9411533d613123618c0d127fae532595Jeff Garzik}
2668bca1c4eb9411533d613123618c0d127fae532595Jeff Garzik
266905b308e1df6d9d673daedb517969241f41278b52Brett Russ/**
267047c2b677daeed9c79ecb7167c211ff36876ea611Jeff Garzik *      mv_init_host - Perform some early initialization of the host.
26714447d35156169cf136e829eb6b5cac2d6370f2d9Tejun Heo *	@host: ATA host to initialize
26724447d35156169cf136e829eb6b5cac2d6370f2d9Tejun Heo *      @board_idx: controller index
267305b308e1df6d9d673daedb517969241f41278b52Brett Russ *
267405b308e1df6d9d673daedb517969241f41278b52Brett Russ *      If possible, do an early global reset of the host.  Then do
267505b308e1df6d9d673daedb517969241f41278b52Brett Russ *      our port init and clear/unmask all/relevant host interrupts.
267605b308e1df6d9d673daedb517969241f41278b52Brett Russ *
267705b308e1df6d9d673daedb517969241f41278b52Brett Russ *      LOCKING:
267805b308e1df6d9d673daedb517969241f41278b52Brett Russ *      Inherited from caller.
267905b308e1df6d9d673daedb517969241f41278b52Brett Russ */
26804447d35156169cf136e829eb6b5cac2d6370f2d9Tejun Heostatic int mv_init_host(struct ata_host *host, unsigned int board_idx)
268120f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ{
268220f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ	int rc = 0, n_hc, port, hc;
26834447d35156169cf136e829eb6b5cac2d6370f2d9Tejun Heo	struct pci_dev *pdev = to_pci_dev(host->dev);
26844447d35156169cf136e829eb6b5cac2d6370f2d9Tejun Heo	void __iomem *mmio = host->iomap[MV_PRIMARY_BAR];
26854447d35156169cf136e829eb6b5cac2d6370f2d9Tejun Heo	struct mv_host_priv *hpriv = host->private_data;
2686bca1c4eb9411533d613123618c0d127fae532595Jeff Garzik
268747c2b677daeed9c79ecb7167c211ff36876ea611Jeff Garzik	/* global interrupt mask */
268847c2b677daeed9c79ecb7167c211ff36876ea611Jeff Garzik	writel(0, mmio + HC_MAIN_IRQ_MASK_OFS);
268947c2b677daeed9c79ecb7167c211ff36876ea611Jeff Garzik
26904447d35156169cf136e829eb6b5cac2d6370f2d9Tejun Heo	rc = mv_chip_id(host, board_idx);
2691bca1c4eb9411533d613123618c0d127fae532595Jeff Garzik	if (rc)
2692bca1c4eb9411533d613123618c0d127fae532595Jeff Garzik		goto done;
2693bca1c4eb9411533d613123618c0d127fae532595Jeff Garzik
26944447d35156169cf136e829eb6b5cac2d6370f2d9Tejun Heo	n_hc = mv_get_hc_count(host->ports[0]->flags);
2695bca1c4eb9411533d613123618c0d127fae532595Jeff Garzik
26964447d35156169cf136e829eb6b5cac2d6370f2d9Tejun Heo	for (port = 0; port < host->n_ports; port++)
269747c2b677daeed9c79ecb7167c211ff36876ea611Jeff Garzik		hpriv->ops->read_preamp(hpriv, port, mmio);
269820f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ
2699c9d39130123238ac18478a42e25cb7996eacfcc0Jeff Garzik	rc = hpriv->ops->reset_hc(hpriv, mmio, n_hc);
270047c2b677daeed9c79ecb7167c211ff36876ea611Jeff Garzik	if (rc)
270120f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ		goto done;
270220f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ
2703522479fb98c6667f081e75f87e298e413c0b1db8Jeff Garzik	hpriv->ops->reset_flash(hpriv, mmio);
2704522479fb98c6667f081e75f87e298e413c0b1db8Jeff Garzik	hpriv->ops->reset_bus(pdev, mmio);
270547c2b677daeed9c79ecb7167c211ff36876ea611Jeff Garzik	hpriv->ops->enable_leds(hpriv, mmio);
270620f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ
27074447d35156169cf136e829eb6b5cac2d6370f2d9Tejun Heo	for (port = 0; port < host->n_ports; port++) {
2708ee9ccdf70163ca6408f6965e0fbc65baeac7312cJeff Garzik		if (IS_GEN_II(hpriv)) {
2709c9d39130123238ac18478a42e25cb7996eacfcc0Jeff Garzik			void __iomem *port_mmio = mv_port_base(mmio, port);
2710c9d39130123238ac18478a42e25cb7996eacfcc0Jeff Garzik
27112a47ce06d534692f9bd2bf4e90a20fc9b1054c39Jeff Garzik			u32 ifctl = readl(port_mmio + SATA_INTERFACE_CTL);
2712eb46d684600ac145501805a294c94675e82eab2eMark Lord			ifctl |= (1 << 7);		/* enable gen2i speed */
2713eb46d684600ac145501805a294c94675e82eab2eMark Lord			ifctl = (ifctl & 0xfff) | 0x9b1000; /* from chip spec */
27142a47ce06d534692f9bd2bf4e90a20fc9b1054c39Jeff Garzik			writelfl(ifctl, port_mmio + SATA_INTERFACE_CTL);
27152a47ce06d534692f9bd2bf4e90a20fc9b1054c39Jeff Garzik		}
27162a47ce06d534692f9bd2bf4e90a20fc9b1054c39Jeff Garzik
2717c9d39130123238ac18478a42e25cb7996eacfcc0Jeff Garzik		hpriv->ops->phy_errata(hpriv, mmio, port);
27182a47ce06d534692f9bd2bf4e90a20fc9b1054c39Jeff Garzik	}
27192a47ce06d534692f9bd2bf4e90a20fc9b1054c39Jeff Garzik
27204447d35156169cf136e829eb6b5cac2d6370f2d9Tejun Heo	for (port = 0; port < host->n_ports; port++) {
2721cbcdd87593a1d85c5c4b259945a3a09eee12814dTejun Heo		struct ata_port *ap = host->ports[port];
27222a47ce06d534692f9bd2bf4e90a20fc9b1054c39Jeff Garzik		void __iomem *port_mmio = mv_port_base(mmio, port);
2723cbcdd87593a1d85c5c4b259945a3a09eee12814dTejun Heo		unsigned int offset = port_mmio - mmio;
2724cbcdd87593a1d85c5c4b259945a3a09eee12814dTejun Heo
2725cbcdd87593a1d85c5c4b259945a3a09eee12814dTejun Heo		mv_port_init(&ap->ioaddr, port_mmio);
2726cbcdd87593a1d85c5c4b259945a3a09eee12814dTejun Heo
2727cbcdd87593a1d85c5c4b259945a3a09eee12814dTejun Heo		ata_port_pbar_desc(ap, MV_PRIMARY_BAR, -1, "mmio");
2728cbcdd87593a1d85c5c4b259945a3a09eee12814dTejun Heo		ata_port_pbar_desc(ap, MV_PRIMARY_BAR, offset, "port");
272920f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ	}
273020f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ
273120f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ	for (hc = 0; hc < n_hc; hc++) {
273231961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ		void __iomem *hc_mmio = mv_hc_base(mmio, hc);
273331961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ
273431961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ		VPRINTK("HC%i: HC config=0x%08x HC IRQ cause "
273531961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ			"(before clear)=0x%08x\n", hc,
273631961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ			readl(hc_mmio + HC_CFG_OFS),
273731961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ			readl(hc_mmio + HC_IRQ_CAUSE_OFS));
273831961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ
273931961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ		/* Clear any currently outstanding hc interrupt conditions */
274031961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ		writelfl(0, hc_mmio + HC_IRQ_CAUSE_OFS);
274120f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ	}
274220f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ
274331961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ	/* Clear any currently outstanding host interrupt conditions */
274402a121da5a53d415b6596bc19cc6999d295d32a4Mark Lord	writelfl(0, mmio + hpriv->irq_cause_ofs);
274531961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ
274631961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ	/* and unmask interrupt generation for host regs */
274702a121da5a53d415b6596bc19cc6999d295d32a4Mark Lord	writelfl(hpriv->unmask_all_irqs, mmio + hpriv->irq_mask_ofs);
2748fb621e2fde735abab854586d52c96c5624bcb5b8Jeff Garzik
2749ee9ccdf70163ca6408f6965e0fbc65baeac7312cJeff Garzik	if (IS_GEN_I(hpriv))
2750fb621e2fde735abab854586d52c96c5624bcb5b8Jeff Garzik		writelfl(~HC_MAIN_MASKED_IRQS_5, mmio + HC_MAIN_IRQ_MASK_OFS);
2751fb621e2fde735abab854586d52c96c5624bcb5b8Jeff Garzik	else
2752fb621e2fde735abab854586d52c96c5624bcb5b8Jeff Garzik		writelfl(~HC_MAIN_MASKED_IRQS, mmio + HC_MAIN_IRQ_MASK_OFS);
275320f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ
275420f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ	VPRINTK("HC MAIN IRQ cause/mask=0x%08x/0x%08x "
27558b260248d9e0e8b64bb72fd4dee03ad86984c344Jeff Garzik		"PCI int cause/mask=0x%08x/0x%08x\n",
275620f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ		readl(mmio + HC_MAIN_IRQ_CAUSE_OFS),
275720f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ		readl(mmio + HC_MAIN_IRQ_MASK_OFS),
275802a121da5a53d415b6596bc19cc6999d295d32a4Mark Lord		readl(mmio + hpriv->irq_cause_ofs),
275902a121da5a53d415b6596bc19cc6999d295d32a4Mark Lord		readl(mmio + hpriv->irq_mask_ofs));
2760bca1c4eb9411533d613123618c0d127fae532595Jeff Garzik
276131961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russdone:
276220f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ	return rc;
276320f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ}
276420f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ
276505b308e1df6d9d673daedb517969241f41278b52Brett Russ/**
276605b308e1df6d9d673daedb517969241f41278b52Brett Russ *      mv_print_info - Dump key info to kernel log for perusal.
27674447d35156169cf136e829eb6b5cac2d6370f2d9Tejun Heo *      @host: ATA host to print info about
276805b308e1df6d9d673daedb517969241f41278b52Brett Russ *
276905b308e1df6d9d673daedb517969241f41278b52Brett Russ *      FIXME: complete this.
277005b308e1df6d9d673daedb517969241f41278b52Brett Russ *
277105b308e1df6d9d673daedb517969241f41278b52Brett Russ *      LOCKING:
277205b308e1df6d9d673daedb517969241f41278b52Brett Russ *      Inherited from caller.
277305b308e1df6d9d673daedb517969241f41278b52Brett Russ */
27744447d35156169cf136e829eb6b5cac2d6370f2d9Tejun Heostatic void mv_print_info(struct ata_host *host)
277531961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ{
27764447d35156169cf136e829eb6b5cac2d6370f2d9Tejun Heo	struct pci_dev *pdev = to_pci_dev(host->dev);
27774447d35156169cf136e829eb6b5cac2d6370f2d9Tejun Heo	struct mv_host_priv *hpriv = host->private_data;
277844c10138fd4bbc4b6d6bff0873c24902f2a9da65Auke Kok	u8 scc;
2779c1e4fe711a410a139095e6b3e3ce3f07f466063cJeff Garzik	const char *scc_s, *gen;
278031961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ
278131961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ	/* Use this to determine the HW stepping of the chip so we know
278231961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ	 * what errata to workaround
278331961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ	 */
278431961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ	pci_read_config_byte(pdev, PCI_CLASS_DEVICE, &scc);
278531961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ	if (scc == 0)
278631961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ		scc_s = "SCSI";
278731961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ	else if (scc == 0x01)
278831961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ		scc_s = "RAID";
278931961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ	else
2790c1e4fe711a410a139095e6b3e3ce3f07f466063cJeff Garzik		scc_s = "?";
2791c1e4fe711a410a139095e6b3e3ce3f07f466063cJeff Garzik
2792c1e4fe711a410a139095e6b3e3ce3f07f466063cJeff Garzik	if (IS_GEN_I(hpriv))
2793c1e4fe711a410a139095e6b3e3ce3f07f466063cJeff Garzik		gen = "I";
2794c1e4fe711a410a139095e6b3e3ce3f07f466063cJeff Garzik	else if (IS_GEN_II(hpriv))
2795c1e4fe711a410a139095e6b3e3ce3f07f466063cJeff Garzik		gen = "II";
2796c1e4fe711a410a139095e6b3e3ce3f07f466063cJeff Garzik	else if (IS_GEN_IIE(hpriv))
2797c1e4fe711a410a139095e6b3e3ce3f07f466063cJeff Garzik		gen = "IIE";
2798c1e4fe711a410a139095e6b3e3ce3f07f466063cJeff Garzik	else
2799c1e4fe711a410a139095e6b3e3ce3f07f466063cJeff Garzik		gen = "?";
280031961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ
2801a9524a76f70f3343e4be27f95a7e92a8ba5f9009Jeff Garzik	dev_printk(KERN_INFO, &pdev->dev,
2802c1e4fe711a410a139095e6b3e3ce3f07f466063cJeff Garzik	       "Gen-%s %u slots %u ports %s mode IRQ via %s\n",
2803c1e4fe711a410a139095e6b3e3ce3f07f466063cJeff Garzik	       gen, (unsigned)MV_MAX_Q_DEPTH, host->n_ports,
280431961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ	       scc_s, (MV_HP_FLAG_MSI & hpriv->hp_flags) ? "MSI" : "INTx");
280531961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ}
280631961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ
2807da2fa9baf06f33a8fa7aa3f56c9f2b4070ceca0eMark Lordstatic int mv_create_dma_pools(struct mv_host_priv *hpriv, struct device *dev)
2808da2fa9baf06f33a8fa7aa3f56c9f2b4070ceca0eMark Lord{
2809da2fa9baf06f33a8fa7aa3f56c9f2b4070ceca0eMark Lord	hpriv->crqb_pool   = dmam_pool_create("crqb_q", dev, MV_CRQB_Q_SZ,
2810da2fa9baf06f33a8fa7aa3f56c9f2b4070ceca0eMark Lord							     MV_CRQB_Q_SZ, 0);
2811da2fa9baf06f33a8fa7aa3f56c9f2b4070ceca0eMark Lord	if (!hpriv->crqb_pool)
2812da2fa9baf06f33a8fa7aa3f56c9f2b4070ceca0eMark Lord		return -ENOMEM;
2813da2fa9baf06f33a8fa7aa3f56c9f2b4070ceca0eMark Lord
2814da2fa9baf06f33a8fa7aa3f56c9f2b4070ceca0eMark Lord	hpriv->crpb_pool   = dmam_pool_create("crpb_q", dev, MV_CRPB_Q_SZ,
2815da2fa9baf06f33a8fa7aa3f56c9f2b4070ceca0eMark Lord							     MV_CRPB_Q_SZ, 0);
2816da2fa9baf06f33a8fa7aa3f56c9f2b4070ceca0eMark Lord	if (!hpriv->crpb_pool)
2817da2fa9baf06f33a8fa7aa3f56c9f2b4070ceca0eMark Lord		return -ENOMEM;
2818da2fa9baf06f33a8fa7aa3f56c9f2b4070ceca0eMark Lord
2819da2fa9baf06f33a8fa7aa3f56c9f2b4070ceca0eMark Lord	hpriv->sg_tbl_pool = dmam_pool_create("sg_tbl", dev, MV_SG_TBL_SZ,
2820da2fa9baf06f33a8fa7aa3f56c9f2b4070ceca0eMark Lord							     MV_SG_TBL_SZ, 0);
2821da2fa9baf06f33a8fa7aa3f56c9f2b4070ceca0eMark Lord	if (!hpriv->sg_tbl_pool)
2822da2fa9baf06f33a8fa7aa3f56c9f2b4070ceca0eMark Lord		return -ENOMEM;
2823da2fa9baf06f33a8fa7aa3f56c9f2b4070ceca0eMark Lord
2824da2fa9baf06f33a8fa7aa3f56c9f2b4070ceca0eMark Lord	return 0;
2825da2fa9baf06f33a8fa7aa3f56c9f2b4070ceca0eMark Lord}
2826da2fa9baf06f33a8fa7aa3f56c9f2b4070ceca0eMark Lord
282705b308e1df6d9d673daedb517969241f41278b52Brett Russ/**
282805b308e1df6d9d673daedb517969241f41278b52Brett Russ *      mv_init_one - handle a positive probe of a Marvell host
282905b308e1df6d9d673daedb517969241f41278b52Brett Russ *      @pdev: PCI device found
283005b308e1df6d9d673daedb517969241f41278b52Brett Russ *      @ent: PCI device ID entry for the matched host
283105b308e1df6d9d673daedb517969241f41278b52Brett Russ *
283205b308e1df6d9d673daedb517969241f41278b52Brett Russ *      LOCKING:
283305b308e1df6d9d673daedb517969241f41278b52Brett Russ *      Inherited from caller.
283405b308e1df6d9d673daedb517969241f41278b52Brett Russ */
283520f733e7d75a16bffc34842b7682c9247dd5f954Brett Russstatic int mv_init_one(struct pci_dev *pdev, const struct pci_device_id *ent)
283620f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ{
28372dcb407e61458ded17503d6bd12b8c064965368bJeff Garzik	static int printed_version;
283820f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ	unsigned int board_idx = (unsigned int)ent->driver_data;
28394447d35156169cf136e829eb6b5cac2d6370f2d9Tejun Heo	const struct ata_port_info *ppi[] = { &mv_port_info[board_idx], NULL };
28404447d35156169cf136e829eb6b5cac2d6370f2d9Tejun Heo	struct ata_host *host;
28414447d35156169cf136e829eb6b5cac2d6370f2d9Tejun Heo	struct mv_host_priv *hpriv;
28424447d35156169cf136e829eb6b5cac2d6370f2d9Tejun Heo	int n_ports, rc;
284320f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ
2844a9524a76f70f3343e4be27f95a7e92a8ba5f9009Jeff Garzik	if (!printed_version++)
2845a9524a76f70f3343e4be27f95a7e92a8ba5f9009Jeff Garzik		dev_printk(KERN_INFO, &pdev->dev, "version " DRV_VERSION "\n");
284620f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ
28474447d35156169cf136e829eb6b5cac2d6370f2d9Tejun Heo	/* allocate host */
28484447d35156169cf136e829eb6b5cac2d6370f2d9Tejun Heo	n_ports = mv_get_hc_count(ppi[0]->flags) * MV_PORTS_PER_HC;
28494447d35156169cf136e829eb6b5cac2d6370f2d9Tejun Heo
28504447d35156169cf136e829eb6b5cac2d6370f2d9Tejun Heo	host = ata_host_alloc_pinfo(&pdev->dev, ppi, n_ports);
28514447d35156169cf136e829eb6b5cac2d6370f2d9Tejun Heo	hpriv = devm_kzalloc(&pdev->dev, sizeof(*hpriv), GFP_KERNEL);
28524447d35156169cf136e829eb6b5cac2d6370f2d9Tejun Heo	if (!host || !hpriv)
28534447d35156169cf136e829eb6b5cac2d6370f2d9Tejun Heo		return -ENOMEM;
28544447d35156169cf136e829eb6b5cac2d6370f2d9Tejun Heo	host->private_data = hpriv;
28554447d35156169cf136e829eb6b5cac2d6370f2d9Tejun Heo
28564447d35156169cf136e829eb6b5cac2d6370f2d9Tejun Heo	/* acquire resources */
285724dc5f33ea4b504cfbd23fa159a4cacba8e4d800Tejun Heo	rc = pcim_enable_device(pdev);
285824dc5f33ea4b504cfbd23fa159a4cacba8e4d800Tejun Heo	if (rc)
285920f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ		return rc;
286020f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ
28610d5ff566779f894ca9937231a181eb31e4adff0eTejun Heo	rc = pcim_iomap_regions(pdev, 1 << MV_PRIMARY_BAR, DRV_NAME);
28620d5ff566779f894ca9937231a181eb31e4adff0eTejun Heo	if (rc == -EBUSY)
286324dc5f33ea4b504cfbd23fa159a4cacba8e4d800Tejun Heo		pcim_pin_device(pdev);
28640d5ff566779f894ca9937231a181eb31e4adff0eTejun Heo	if (rc)
286524dc5f33ea4b504cfbd23fa159a4cacba8e4d800Tejun Heo		return rc;
28664447d35156169cf136e829eb6b5cac2d6370f2d9Tejun Heo	host->iomap = pcim_iomap_table(pdev);
286720f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ
2868d88184fb2348a50f7c34f5d49a901c875b2e0114Jeff Garzik	rc = pci_go_64(pdev);
2869d88184fb2348a50f7c34f5d49a901c875b2e0114Jeff Garzik	if (rc)
2870d88184fb2348a50f7c34f5d49a901c875b2e0114Jeff Garzik		return rc;
2871d88184fb2348a50f7c34f5d49a901c875b2e0114Jeff Garzik
2872da2fa9baf06f33a8fa7aa3f56c9f2b4070ceca0eMark Lord	rc = mv_create_dma_pools(hpriv, &pdev->dev);
2873da2fa9baf06f33a8fa7aa3f56c9f2b4070ceca0eMark Lord	if (rc)
2874da2fa9baf06f33a8fa7aa3f56c9f2b4070ceca0eMark Lord		return rc;
2875da2fa9baf06f33a8fa7aa3f56c9f2b4070ceca0eMark Lord
287620f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ	/* initialize adapter */
28774447d35156169cf136e829eb6b5cac2d6370f2d9Tejun Heo	rc = mv_init_host(host, board_idx);
287824dc5f33ea4b504cfbd23fa159a4cacba8e4d800Tejun Heo	if (rc)
287924dc5f33ea4b504cfbd23fa159a4cacba8e4d800Tejun Heo		return rc;
288020f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ
288131961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ	/* Enable interrupts */
28826a59dcf8678cbc4106a8a6e158d7408a87691358Tejun Heo	if (msi && pci_enable_msi(pdev))
288331961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ		pci_intx(pdev, 1);
288420f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ
288531961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ	mv_dump_pci_cfg(pdev, 0x68);
28864447d35156169cf136e829eb6b5cac2d6370f2d9Tejun Heo	mv_print_info(host);
288720f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ
28884447d35156169cf136e829eb6b5cac2d6370f2d9Tejun Heo	pci_set_master(pdev);
2889ea8b4db97aa41a66c05daa4055a1974692ccd52dJeff Garzik	pci_try_set_mwi(pdev);
28904447d35156169cf136e829eb6b5cac2d6370f2d9Tejun Heo	return ata_host_activate(host, pdev->irq, mv_interrupt, IRQF_SHARED,
2891c5d3e45a2200a0905dc45b72714726b7aac3aaf1Jeff Garzik				 IS_GEN_I(hpriv) ? &mv5_sht : &mv6_sht);
289220f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ}
289320f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ
289420f733e7d75a16bffc34842b7682c9247dd5f954Brett Russstatic int __init mv_init(void)
289520f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ{
2896b7887196e38da54ff893897b80875d632d1a1114Pavel Roskin	return pci_register_driver(&mv_pci_driver);
289720f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ}
289820f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ
289920f733e7d75a16bffc34842b7682c9247dd5f954Brett Russstatic void __exit mv_exit(void)
290020f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ{
290120f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ	pci_unregister_driver(&mv_pci_driver);
290220f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ}
290320f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ
290420f733e7d75a16bffc34842b7682c9247dd5f954Brett RussMODULE_AUTHOR("Brett Russ");
290520f733e7d75a16bffc34842b7682c9247dd5f954Brett RussMODULE_DESCRIPTION("SCSI low-level driver for Marvell SATA controllers");
290620f733e7d75a16bffc34842b7682c9247dd5f954Brett RussMODULE_LICENSE("GPL");
290720f733e7d75a16bffc34842b7682c9247dd5f954Brett RussMODULE_DEVICE_TABLE(pci, mv_pci_tbl);
290820f733e7d75a16bffc34842b7682c9247dd5f954Brett RussMODULE_VERSION(DRV_VERSION);
290920f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ
2910ddef9bb367b19383df627e388cb4c01c86ddba6cJeff Garzikmodule_param(msi, int, 0444);
2911ddef9bb367b19383df627e388cb4c01c86ddba6cJeff GarzikMODULE_PARM_DESC(msi, "Enable use of PCI MSI (0=off, 1=on)");
2912ddef9bb367b19383df627e388cb4c01c86ddba6cJeff Garzik
291320f733e7d75a16bffc34842b7682c9247dd5f954Brett Russmodule_init(mv_init);
291420f733e7d75a16bffc34842b7682c9247dd5f954Brett Russmodule_exit(mv_exit);
2915