sata_mv.c revision f630d562829fcd8160a118f98c1e5b9cdb4e703e
120f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ/*
220f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ * sata_mv.c - Marvell SATA support
320f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ *
48b260248d9e0e8b64bb72fd4dee03ad86984c344Jeff Garzik * Copyright 2005: EMC Corporation, all rights reserved.
5e2b1be56c5656902744c2b52e8304126a40bb609Jeff Garzik * Copyright 2005 Red Hat, Inc.  All rights reserved.
620f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ *
720f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ * Please ALWAYS copy linux-ide@vger.kernel.org on emails.
820f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ *
920f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ * This program is free software; you can redistribute it and/or modify
1020f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ * it under the terms of the GNU General Public License as published by
1120f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ * the Free Software Foundation; version 2 of the License.
1220f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ *
1320f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ * This program is distributed in the hope that it will be useful,
1420f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ * but WITHOUT ANY WARRANTY; without even the implied warranty of
1520f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
1620f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ * GNU General Public License for more details.
1720f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ *
1820f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ * You should have received a copy of the GNU General Public License
1920f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ * along with this program; if not, write to the Free Software
2020f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
2120f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ *
2220f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ */
2320f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ
244a05e2091709dbb22b86a1b3343cd3fa3c0d7a6bJeff Garzik/*
254a05e2091709dbb22b86a1b3343cd3fa3c0d7a6bJeff Garzik  sata_mv TODO list:
264a05e2091709dbb22b86a1b3343cd3fa3c0d7a6bJeff Garzik
274a05e2091709dbb22b86a1b3343cd3fa3c0d7a6bJeff Garzik  1) Needs a full errata audit for all chipsets.  I implemented most
284a05e2091709dbb22b86a1b3343cd3fa3c0d7a6bJeff Garzik  of the errata workarounds found in the Marvell vendor driver, but
294a05e2091709dbb22b86a1b3343cd3fa3c0d7a6bJeff Garzik  I distinctly remember a couple workarounds (one related to PCI-X)
304a05e2091709dbb22b86a1b3343cd3fa3c0d7a6bJeff Garzik  are still needed.
314a05e2091709dbb22b86a1b3343cd3fa3c0d7a6bJeff Garzik
324a05e2091709dbb22b86a1b3343cd3fa3c0d7a6bJeff Garzik  4) Add NCQ support (easy to intermediate, once new-EH support appears)
334a05e2091709dbb22b86a1b3343cd3fa3c0d7a6bJeff Garzik
344a05e2091709dbb22b86a1b3343cd3fa3c0d7a6bJeff Garzik  5) Investigate problems with PCI Message Signalled Interrupts (MSI).
354a05e2091709dbb22b86a1b3343cd3fa3c0d7a6bJeff Garzik
364a05e2091709dbb22b86a1b3343cd3fa3c0d7a6bJeff Garzik  6) Add port multiplier support (intermediate)
374a05e2091709dbb22b86a1b3343cd3fa3c0d7a6bJeff Garzik
384a05e2091709dbb22b86a1b3343cd3fa3c0d7a6bJeff Garzik  8) Develop a low-power-consumption strategy, and implement it.
394a05e2091709dbb22b86a1b3343cd3fa3c0d7a6bJeff Garzik
404a05e2091709dbb22b86a1b3343cd3fa3c0d7a6bJeff Garzik  9) [Experiment, low priority] See if ATAPI can be supported using
414a05e2091709dbb22b86a1b3343cd3fa3c0d7a6bJeff Garzik  "unknown FIS" or "vendor-specific FIS" support, or something creative
424a05e2091709dbb22b86a1b3343cd3fa3c0d7a6bJeff Garzik  like that.
434a05e2091709dbb22b86a1b3343cd3fa3c0d7a6bJeff Garzik
444a05e2091709dbb22b86a1b3343cd3fa3c0d7a6bJeff Garzik  10) [Experiment, low priority] Investigate interrupt coalescing.
454a05e2091709dbb22b86a1b3343cd3fa3c0d7a6bJeff Garzik  Quite often, especially with PCI Message Signalled Interrupts (MSI),
464a05e2091709dbb22b86a1b3343cd3fa3c0d7a6bJeff Garzik  the overhead reduced by interrupt mitigation is quite often not
474a05e2091709dbb22b86a1b3343cd3fa3c0d7a6bJeff Garzik  worth the latency cost.
484a05e2091709dbb22b86a1b3343cd3fa3c0d7a6bJeff Garzik
494a05e2091709dbb22b86a1b3343cd3fa3c0d7a6bJeff Garzik  11) [Experiment, Marvell value added] Is it possible to use target
504a05e2091709dbb22b86a1b3343cd3fa3c0d7a6bJeff Garzik  mode to cross-connect two Linux boxes with Marvell cards?  If so,
514a05e2091709dbb22b86a1b3343cd3fa3c0d7a6bJeff Garzik  creating LibATA target mode support would be very interesting.
524a05e2091709dbb22b86a1b3343cd3fa3c0d7a6bJeff Garzik
534a05e2091709dbb22b86a1b3343cd3fa3c0d7a6bJeff Garzik  Target mode, for those without docs, is the ability to directly
544a05e2091709dbb22b86a1b3343cd3fa3c0d7a6bJeff Garzik  connect two SATA controllers.
554a05e2091709dbb22b86a1b3343cd3fa3c0d7a6bJeff Garzik
564a05e2091709dbb22b86a1b3343cd3fa3c0d7a6bJeff Garzik  13) Verify that 7042 is fully supported.  I only have a 6042.
574a05e2091709dbb22b86a1b3343cd3fa3c0d7a6bJeff Garzik
584a05e2091709dbb22b86a1b3343cd3fa3c0d7a6bJeff Garzik*/
594a05e2091709dbb22b86a1b3343cd3fa3c0d7a6bJeff Garzik
604a05e2091709dbb22b86a1b3343cd3fa3c0d7a6bJeff Garzik
6120f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ#include <linux/kernel.h>
6220f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ#include <linux/module.h>
6320f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ#include <linux/pci.h>
6420f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ#include <linux/init.h>
6520f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ#include <linux/blkdev.h>
6620f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ#include <linux/delay.h>
6720f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ#include <linux/interrupt.h>
6820f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ#include <linux/dma-mapping.h>
69a9524a76f70f3343e4be27f95a7e92a8ba5f9009Jeff Garzik#include <linux/device.h>
7020f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ#include <scsi/scsi_host.h>
71193515d51ccb363165d6b09e9ba5c21089e34badJeff Garzik#include <scsi/scsi_cmnd.h>
726c08772e49622e90d39903e7ff0be1a0f463ac86Jeff Garzik#include <scsi/scsi_device.h>
7320f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ#include <linux/libata.h>
7420f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ
7520f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ#define DRV_NAME	"sata_mv"
766c08772e49622e90d39903e7ff0be1a0f463ac86Jeff Garzik#define DRV_VERSION	"1.01"
7720f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ
7820f733e7d75a16bffc34842b7682c9247dd5f954Brett Russenum {
7920f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ	/* BAR's are enumerated in terms of pci_resource_start() terms */
8020f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ	MV_PRIMARY_BAR		= 0,	/* offset 0x10: memory space */
8120f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ	MV_IO_BAR		= 2,	/* offset 0x18: IO space */
8220f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ	MV_MISC_BAR		= 3,	/* offset 0x1c: FLASH, NVRAM, SRAM */
8320f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ
8420f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ	MV_MAJOR_REG_AREA_SZ	= 0x10000,	/* 64KB */
8520f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ	MV_MINOR_REG_AREA_SZ	= 0x2000,	/* 8KB */
8620f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ
8720f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ	MV_PCI_REG_BASE		= 0,
8820f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ	MV_IRQ_COAL_REG_BASE	= 0x18000,	/* 6xxx part only */
89615ab95342f6245026d8974b9724f7ea57d9a184Mark Lord	MV_IRQ_COAL_CAUSE		= (MV_IRQ_COAL_REG_BASE + 0x08),
90615ab95342f6245026d8974b9724f7ea57d9a184Mark Lord	MV_IRQ_COAL_CAUSE_LO		= (MV_IRQ_COAL_REG_BASE + 0x88),
91615ab95342f6245026d8974b9724f7ea57d9a184Mark Lord	MV_IRQ_COAL_CAUSE_HI		= (MV_IRQ_COAL_REG_BASE + 0x8c),
92615ab95342f6245026d8974b9724f7ea57d9a184Mark Lord	MV_IRQ_COAL_THRESHOLD		= (MV_IRQ_COAL_REG_BASE + 0xcc),
93615ab95342f6245026d8974b9724f7ea57d9a184Mark Lord	MV_IRQ_COAL_TIME_THRESHOLD	= (MV_IRQ_COAL_REG_BASE + 0xd0),
94615ab95342f6245026d8974b9724f7ea57d9a184Mark Lord
9520f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ	MV_SATAHC0_REG_BASE	= 0x20000,
96522479fb98c6667f081e75f87e298e413c0b1db8Jeff Garzik	MV_FLASH_CTL		= 0x1046c,
97bca1c4eb9411533d613123618c0d127fae532595Jeff Garzik	MV_GPIO_PORT_CTL	= 0x104f0,
98bca1c4eb9411533d613123618c0d127fae532595Jeff Garzik	MV_RESET_CFG		= 0x180d8,
9920f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ
10020f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ	MV_PCI_REG_SZ		= MV_MAJOR_REG_AREA_SZ,
10120f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ	MV_SATAHC_REG_SZ	= MV_MAJOR_REG_AREA_SZ,
10220f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ	MV_SATAHC_ARBTR_REG_SZ	= MV_MINOR_REG_AREA_SZ,		/* arbiter */
10320f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ	MV_PORT_REG_SZ		= MV_MINOR_REG_AREA_SZ,
10420f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ
10531961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ	MV_MAX_Q_DEPTH		= 32,
10631961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ	MV_MAX_Q_DEPTH_MASK	= MV_MAX_Q_DEPTH - 1,
10731961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ
10831961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ	/* CRQB needs alignment on a 1KB boundary. Size == 1KB
10931961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ	 * CRPB needs alignment on a 256B boundary. Size == 256B
11031961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ	 * SG count of 176 leads to MV_PORT_PRIV_DMA_SZ == 4KB
11131961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ	 * ePRD (SG) entries need alignment on a 16B boundary. Size == 16B
11231961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ	 */
11331961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ	MV_CRQB_Q_SZ		= (32 * MV_MAX_Q_DEPTH),
11431961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ	MV_CRPB_Q_SZ		= (8 * MV_MAX_Q_DEPTH),
11531961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ	MV_MAX_SG_CT		= 176,
11631961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ	MV_SG_TBL_SZ		= (16 * MV_MAX_SG_CT),
11731961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ	MV_PORT_PRIV_DMA_SZ	= (MV_CRQB_Q_SZ + MV_CRPB_Q_SZ + MV_SG_TBL_SZ),
11831961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ
11920f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ	MV_PORTS_PER_HC		= 4,
12020f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ	/* == (port / MV_PORTS_PER_HC) to determine HC from 0-7 port */
12120f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ	MV_PORT_HC_SHIFT	= 2,
12231961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ	/* == (port % MV_PORTS_PER_HC) to determine hard port from 0-7 port */
12320f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ	MV_PORT_MASK		= 3,
12420f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ
12520f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ	/* Host Flags */
12620f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ	MV_FLAG_DUAL_HC		= (1 << 30),  /* two SATA Host Controllers */
12720f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ	MV_FLAG_IRQ_COALESCE	= (1 << 29),  /* IRQ coalescing capability */
128c5d3e45a2200a0905dc45b72714726b7aac3aaf1Jeff Garzik	MV_COMMON_FLAGS		= ATA_FLAG_SATA | ATA_FLAG_NO_LEGACY |
129bdd4dddee325a7dce3e84cf48201a06aa8508aa4Jeff Garzik				  ATA_FLAG_MMIO | ATA_FLAG_NO_ATAPI |
130bdd4dddee325a7dce3e84cf48201a06aa8508aa4Jeff Garzik				  ATA_FLAG_PIO_POLLING,
13147c2b677daeed9c79ecb7167c211ff36876ea611Jeff Garzik	MV_6XXX_FLAGS		= MV_FLAG_IRQ_COALESCE,
13220f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ
13331961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ	CRQB_FLAG_READ		= (1 << 0),
13431961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ	CRQB_TAG_SHIFT		= 1,
135c5d3e45a2200a0905dc45b72714726b7aac3aaf1Jeff Garzik	CRQB_IOID_SHIFT		= 6,	/* CRQB Gen-II/IIE IO Id shift */
136c5d3e45a2200a0905dc45b72714726b7aac3aaf1Jeff Garzik	CRQB_HOSTQ_SHIFT	= 17,	/* CRQB Gen-II/IIE HostQueTag shift */
13731961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ	CRQB_CMD_ADDR_SHIFT	= 8,
13831961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ	CRQB_CMD_CS		= (0x2 << 11),
13931961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ	CRQB_CMD_LAST		= (1 << 15),
14031961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ
14131961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ	CRPB_FLAG_STATUS_SHIFT	= 8,
142c5d3e45a2200a0905dc45b72714726b7aac3aaf1Jeff Garzik	CRPB_IOID_SHIFT_6	= 5,	/* CRPB Gen-II IO Id shift */
143c5d3e45a2200a0905dc45b72714726b7aac3aaf1Jeff Garzik	CRPB_IOID_SHIFT_7	= 7,	/* CRPB Gen-IIE IO Id shift */
14431961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ
14531961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ	EPRD_FLAG_END_OF_TBL	= (1 << 31),
14631961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ
14720f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ	/* PCI interface registers */
14820f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ
14931961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ	PCI_COMMAND_OFS		= 0xc00,
15031961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ
15120f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ	PCI_MAIN_CMD_STS_OFS	= 0xd30,
15220f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ	STOP_PCI_MASTER		= (1 << 2),
15320f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ	PCI_MASTER_EMPTY	= (1 << 3),
15420f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ	GLOB_SFT_RST		= (1 << 4),
15520f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ
156522479fb98c6667f081e75f87e298e413c0b1db8Jeff Garzik	MV_PCI_MODE		= 0xd00,
157522479fb98c6667f081e75f87e298e413c0b1db8Jeff Garzik	MV_PCI_EXP_ROM_BAR_CTL	= 0xd2c,
158522479fb98c6667f081e75f87e298e413c0b1db8Jeff Garzik	MV_PCI_DISC_TIMER	= 0xd04,
159522479fb98c6667f081e75f87e298e413c0b1db8Jeff Garzik	MV_PCI_MSI_TRIGGER	= 0xc38,
160522479fb98c6667f081e75f87e298e413c0b1db8Jeff Garzik	MV_PCI_SERR_MASK	= 0xc28,
161522479fb98c6667f081e75f87e298e413c0b1db8Jeff Garzik	MV_PCI_XBAR_TMOUT	= 0x1d04,
162522479fb98c6667f081e75f87e298e413c0b1db8Jeff Garzik	MV_PCI_ERR_LOW_ADDRESS	= 0x1d40,
163522479fb98c6667f081e75f87e298e413c0b1db8Jeff Garzik	MV_PCI_ERR_HIGH_ADDRESS	= 0x1d44,
164522479fb98c6667f081e75f87e298e413c0b1db8Jeff Garzik	MV_PCI_ERR_ATTRIBUTE	= 0x1d48,
165522479fb98c6667f081e75f87e298e413c0b1db8Jeff Garzik	MV_PCI_ERR_COMMAND	= 0x1d50,
166522479fb98c6667f081e75f87e298e413c0b1db8Jeff Garzik
16702a121da5a53d415b6596bc19cc6999d295d32a4Mark Lord	PCI_IRQ_CAUSE_OFS	= 0x1d58,
16802a121da5a53d415b6596bc19cc6999d295d32a4Mark Lord	PCI_IRQ_MASK_OFS	= 0x1d5c,
16920f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ	PCI_UNMASK_ALL_IRQS	= 0x7fffff,	/* bits 22-0 */
17020f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ
17102a121da5a53d415b6596bc19cc6999d295d32a4Mark Lord	PCIE_IRQ_CAUSE_OFS	= 0x1900,
17202a121da5a53d415b6596bc19cc6999d295d32a4Mark Lord	PCIE_IRQ_MASK_OFS	= 0x1910,
173646a4da514f2555298481cb00dc5b3eb02b21b72Mark Lord	PCIE_UNMASK_ALL_IRQS	= 0x40a,	/* assorted bits */
17402a121da5a53d415b6596bc19cc6999d295d32a4Mark Lord
17520f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ	HC_MAIN_IRQ_CAUSE_OFS	= 0x1d60,
17620f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ	HC_MAIN_IRQ_MASK_OFS	= 0x1d64,
17720f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ	PORT0_ERR		= (1 << 0),	/* shift by port # */
17820f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ	PORT0_DONE		= (1 << 1),	/* shift by port # */
17920f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ	HC0_IRQ_PEND		= 0x1ff,	/* bits 0-8 = HC0's ports */
18020f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ	HC_SHIFT		= 9,		/* bits 9-17 = HC1's ports */
18120f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ	PCI_ERR			= (1 << 18),
18220f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ	TRAN_LO_DONE		= (1 << 19),	/* 6xxx: IRQ coalescing */
18320f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ	TRAN_HI_DONE		= (1 << 20),	/* 6xxx: IRQ coalescing */
184fb621e2fde735abab854586d52c96c5624bcb5b8Jeff Garzik	PORTS_0_3_COAL_DONE	= (1 << 8),
185fb621e2fde735abab854586d52c96c5624bcb5b8Jeff Garzik	PORTS_4_7_COAL_DONE	= (1 << 17),
18620f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ	PORTS_0_7_COAL_DONE	= (1 << 21),	/* 6xxx: IRQ coalescing */
18720f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ	GPIO_INT		= (1 << 22),
18820f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ	SELF_INT		= (1 << 23),
18920f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ	TWSI_INT		= (1 << 24),
19020f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ	HC_MAIN_RSVD		= (0x7f << 25),	/* bits 31-25 */
191fb621e2fde735abab854586d52c96c5624bcb5b8Jeff Garzik	HC_MAIN_RSVD_5		= (0x1fff << 19), /* bits 31-19 */
1928b260248d9e0e8b64bb72fd4dee03ad86984c344Jeff Garzik	HC_MAIN_MASKED_IRQS	= (TRAN_LO_DONE | TRAN_HI_DONE |
19320f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ				   PORTS_0_7_COAL_DONE | GPIO_INT | TWSI_INT |
19420f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ				   HC_MAIN_RSVD),
195fb621e2fde735abab854586d52c96c5624bcb5b8Jeff Garzik	HC_MAIN_MASKED_IRQS_5	= (PORTS_0_3_COAL_DONE | PORTS_4_7_COAL_DONE |
196fb621e2fde735abab854586d52c96c5624bcb5b8Jeff Garzik				   HC_MAIN_RSVD_5),
19720f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ
19820f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ	/* SATAHC registers */
19920f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ	HC_CFG_OFS		= 0,
20020f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ
20120f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ	HC_IRQ_CAUSE_OFS	= 0x14,
20231961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ	CRPB_DMA_DONE		= (1 << 0),	/* shift by port # */
20320f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ	HC_IRQ_COAL		= (1 << 4),	/* IRQ coalescing */
20420f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ	DEV_IRQ			= (1 << 8),	/* shift by port # */
20520f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ
20620f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ	/* Shadow block registers */
20731961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ	SHD_BLK_OFS		= 0x100,
20831961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ	SHD_CTL_AST_OFS		= 0x20,		/* ofs from SHD_BLK_OFS */
20920f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ
21020f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ	/* SATA registers */
21120f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ	SATA_STATUS_OFS		= 0x300,  /* ctrl, err regs follow status */
21220f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ	SATA_ACTIVE_OFS		= 0x350,
21347c2b677daeed9c79ecb7167c211ff36876ea611Jeff Garzik	PHY_MODE3		= 0x310,
214bca1c4eb9411533d613123618c0d127fae532595Jeff Garzik	PHY_MODE4		= 0x314,
215bca1c4eb9411533d613123618c0d127fae532595Jeff Garzik	PHY_MODE2		= 0x330,
216c9d39130123238ac18478a42e25cb7996eacfcc0Jeff Garzik	MV5_PHY_MODE		= 0x74,
217c9d39130123238ac18478a42e25cb7996eacfcc0Jeff Garzik	MV5_LT_MODE		= 0x30,
218c9d39130123238ac18478a42e25cb7996eacfcc0Jeff Garzik	MV5_PHY_CTL		= 0x0C,
219bca1c4eb9411533d613123618c0d127fae532595Jeff Garzik	SATA_INTERFACE_CTL	= 0x050,
220bca1c4eb9411533d613123618c0d127fae532595Jeff Garzik
221bca1c4eb9411533d613123618c0d127fae532595Jeff Garzik	MV_M2_PREAMP_MASK	= 0x7e0,
22220f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ
22320f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ	/* Port registers */
22420f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ	EDMA_CFG_OFS		= 0,
22531961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ	EDMA_CFG_Q_DEPTH	= 0,			/* queueing disabled */
22631961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ	EDMA_CFG_NCQ		= (1 << 5),
22731961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ	EDMA_CFG_NCQ_GO_ON_ERR	= (1 << 14),		/* continue on error */
22831961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ	EDMA_CFG_RD_BRST_EXT	= (1 << 11),		/* read burst 512B */
22931961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ	EDMA_CFG_WR_BUFF_LEN	= (1 << 13),		/* write buffer 512B */
23020f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ
23120f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ	EDMA_ERR_IRQ_CAUSE_OFS	= 0x8,
23220f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ	EDMA_ERR_IRQ_MASK_OFS	= 0xc,
2336c1153e00af8de755ec278d873a97c9ce2a72d10Jeff Garzik	EDMA_ERR_D_PAR		= (1 << 0),	/* UDMA data parity err */
2346c1153e00af8de755ec278d873a97c9ce2a72d10Jeff Garzik	EDMA_ERR_PRD_PAR	= (1 << 1),	/* UDMA PRD parity err */
2356c1153e00af8de755ec278d873a97c9ce2a72d10Jeff Garzik	EDMA_ERR_DEV		= (1 << 2),	/* device error */
2366c1153e00af8de755ec278d873a97c9ce2a72d10Jeff Garzik	EDMA_ERR_DEV_DCON	= (1 << 3),	/* device disconnect */
2376c1153e00af8de755ec278d873a97c9ce2a72d10Jeff Garzik	EDMA_ERR_DEV_CON	= (1 << 4),	/* device connected */
2386c1153e00af8de755ec278d873a97c9ce2a72d10Jeff Garzik	EDMA_ERR_SERR		= (1 << 5),	/* SError bits [WBDST] raised */
239c5d3e45a2200a0905dc45b72714726b7aac3aaf1Jeff Garzik	EDMA_ERR_SELF_DIS	= (1 << 7),	/* Gen II/IIE self-disable */
240c5d3e45a2200a0905dc45b72714726b7aac3aaf1Jeff Garzik	EDMA_ERR_SELF_DIS_5	= (1 << 8),	/* Gen I self-disable */
2416c1153e00af8de755ec278d873a97c9ce2a72d10Jeff Garzik	EDMA_ERR_BIST_ASYNC	= (1 << 8),	/* BIST FIS or Async Notify */
242c5d3e45a2200a0905dc45b72714726b7aac3aaf1Jeff Garzik	EDMA_ERR_TRANS_IRQ_7	= (1 << 8),	/* Gen IIE transprt layer irq */
2436c1153e00af8de755ec278d873a97c9ce2a72d10Jeff Garzik	EDMA_ERR_CRQB_PAR	= (1 << 9),	/* CRQB parity error */
2446c1153e00af8de755ec278d873a97c9ce2a72d10Jeff Garzik	EDMA_ERR_CRPB_PAR	= (1 << 10),	/* CRPB parity error */
2456c1153e00af8de755ec278d873a97c9ce2a72d10Jeff Garzik	EDMA_ERR_INTRL_PAR	= (1 << 11),	/* internal parity error */
2466c1153e00af8de755ec278d873a97c9ce2a72d10Jeff Garzik	EDMA_ERR_IORDY		= (1 << 12),	/* IORdy timeout */
247646a4da514f2555298481cb00dc5b3eb02b21b72Mark Lord
2486c1153e00af8de755ec278d873a97c9ce2a72d10Jeff Garzik	EDMA_ERR_LNK_CTRL_RX	= (0xf << 13),	/* link ctrl rx error */
249646a4da514f2555298481cb00dc5b3eb02b21b72Mark Lord	EDMA_ERR_LNK_CTRL_RX_0	= (1 << 13),	/* transient: CRC err */
250646a4da514f2555298481cb00dc5b3eb02b21b72Mark Lord	EDMA_ERR_LNK_CTRL_RX_1	= (1 << 14),	/* transient: FIFO err */
251646a4da514f2555298481cb00dc5b3eb02b21b72Mark Lord	EDMA_ERR_LNK_CTRL_RX_2	= (1 << 15),	/* fatal: caught SYNC */
252646a4da514f2555298481cb00dc5b3eb02b21b72Mark Lord	EDMA_ERR_LNK_CTRL_RX_3	= (1 << 16),	/* transient: FIS rx err */
253646a4da514f2555298481cb00dc5b3eb02b21b72Mark Lord
2546c1153e00af8de755ec278d873a97c9ce2a72d10Jeff Garzik	EDMA_ERR_LNK_DATA_RX	= (0xf << 17),	/* link data rx error */
255646a4da514f2555298481cb00dc5b3eb02b21b72Mark Lord
2566c1153e00af8de755ec278d873a97c9ce2a72d10Jeff Garzik	EDMA_ERR_LNK_CTRL_TX	= (0x1f << 21),	/* link ctrl tx error */
257646a4da514f2555298481cb00dc5b3eb02b21b72Mark Lord	EDMA_ERR_LNK_CTRL_TX_0	= (1 << 21),	/* transient: CRC err */
258646a4da514f2555298481cb00dc5b3eb02b21b72Mark Lord	EDMA_ERR_LNK_CTRL_TX_1	= (1 << 22),	/* transient: FIFO err */
259646a4da514f2555298481cb00dc5b3eb02b21b72Mark Lord	EDMA_ERR_LNK_CTRL_TX_2	= (1 << 23),	/* transient: caught SYNC */
260646a4da514f2555298481cb00dc5b3eb02b21b72Mark Lord	EDMA_ERR_LNK_CTRL_TX_3	= (1 << 24),	/* transient: caught DMAT */
261646a4da514f2555298481cb00dc5b3eb02b21b72Mark Lord	EDMA_ERR_LNK_CTRL_TX_4	= (1 << 25),	/* transient: FIS collision */
262646a4da514f2555298481cb00dc5b3eb02b21b72Mark Lord
2636c1153e00af8de755ec278d873a97c9ce2a72d10Jeff Garzik	EDMA_ERR_LNK_DATA_TX	= (0x1f << 26),	/* link data tx error */
264646a4da514f2555298481cb00dc5b3eb02b21b72Mark Lord
2656c1153e00af8de755ec278d873a97c9ce2a72d10Jeff Garzik	EDMA_ERR_TRANS_PROTO	= (1 << 31),	/* transport protocol error */
266c5d3e45a2200a0905dc45b72714726b7aac3aaf1Jeff Garzik	EDMA_ERR_OVERRUN_5	= (1 << 5),
267c5d3e45a2200a0905dc45b72714726b7aac3aaf1Jeff Garzik	EDMA_ERR_UNDERRUN_5	= (1 << 6),
268646a4da514f2555298481cb00dc5b3eb02b21b72Mark Lord
269646a4da514f2555298481cb00dc5b3eb02b21b72Mark Lord	EDMA_ERR_IRQ_TRANSIENT  = EDMA_ERR_LNK_CTRL_RX_0 |
270646a4da514f2555298481cb00dc5b3eb02b21b72Mark Lord				  EDMA_ERR_LNK_CTRL_RX_1 |
271646a4da514f2555298481cb00dc5b3eb02b21b72Mark Lord				  EDMA_ERR_LNK_CTRL_RX_3 |
272646a4da514f2555298481cb00dc5b3eb02b21b72Mark Lord				  EDMA_ERR_LNK_CTRL_TX,
273646a4da514f2555298481cb00dc5b3eb02b21b72Mark Lord
274bdd4dddee325a7dce3e84cf48201a06aa8508aa4Jeff Garzik	EDMA_EH_FREEZE		= EDMA_ERR_D_PAR |
275bdd4dddee325a7dce3e84cf48201a06aa8508aa4Jeff Garzik				  EDMA_ERR_PRD_PAR |
276bdd4dddee325a7dce3e84cf48201a06aa8508aa4Jeff Garzik				  EDMA_ERR_DEV_DCON |
277bdd4dddee325a7dce3e84cf48201a06aa8508aa4Jeff Garzik				  EDMA_ERR_DEV_CON |
278bdd4dddee325a7dce3e84cf48201a06aa8508aa4Jeff Garzik				  EDMA_ERR_SERR |
279bdd4dddee325a7dce3e84cf48201a06aa8508aa4Jeff Garzik				  EDMA_ERR_SELF_DIS |
2806c1153e00af8de755ec278d873a97c9ce2a72d10Jeff Garzik				  EDMA_ERR_CRQB_PAR |
281bdd4dddee325a7dce3e84cf48201a06aa8508aa4Jeff Garzik				  EDMA_ERR_CRPB_PAR |
282bdd4dddee325a7dce3e84cf48201a06aa8508aa4Jeff Garzik				  EDMA_ERR_INTRL_PAR |
283bdd4dddee325a7dce3e84cf48201a06aa8508aa4Jeff Garzik				  EDMA_ERR_IORDY |
284bdd4dddee325a7dce3e84cf48201a06aa8508aa4Jeff Garzik				  EDMA_ERR_LNK_CTRL_RX_2 |
285bdd4dddee325a7dce3e84cf48201a06aa8508aa4Jeff Garzik				  EDMA_ERR_LNK_DATA_RX |
286bdd4dddee325a7dce3e84cf48201a06aa8508aa4Jeff Garzik				  EDMA_ERR_LNK_DATA_TX |
287bdd4dddee325a7dce3e84cf48201a06aa8508aa4Jeff Garzik				  EDMA_ERR_TRANS_PROTO,
288bdd4dddee325a7dce3e84cf48201a06aa8508aa4Jeff Garzik	EDMA_EH_FREEZE_5	= EDMA_ERR_D_PAR |
289bdd4dddee325a7dce3e84cf48201a06aa8508aa4Jeff Garzik				  EDMA_ERR_PRD_PAR |
290bdd4dddee325a7dce3e84cf48201a06aa8508aa4Jeff Garzik				  EDMA_ERR_DEV_DCON |
291bdd4dddee325a7dce3e84cf48201a06aa8508aa4Jeff Garzik				  EDMA_ERR_DEV_CON |
292bdd4dddee325a7dce3e84cf48201a06aa8508aa4Jeff Garzik				  EDMA_ERR_OVERRUN_5 |
293bdd4dddee325a7dce3e84cf48201a06aa8508aa4Jeff Garzik				  EDMA_ERR_UNDERRUN_5 |
294bdd4dddee325a7dce3e84cf48201a06aa8508aa4Jeff Garzik				  EDMA_ERR_SELF_DIS_5 |
2956c1153e00af8de755ec278d873a97c9ce2a72d10Jeff Garzik				  EDMA_ERR_CRQB_PAR |
296bdd4dddee325a7dce3e84cf48201a06aa8508aa4Jeff Garzik				  EDMA_ERR_CRPB_PAR |
297bdd4dddee325a7dce3e84cf48201a06aa8508aa4Jeff Garzik				  EDMA_ERR_INTRL_PAR |
298bdd4dddee325a7dce3e84cf48201a06aa8508aa4Jeff Garzik				  EDMA_ERR_IORDY,
29920f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ
30031961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ	EDMA_REQ_Q_BASE_HI_OFS	= 0x10,
30131961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ	EDMA_REQ_Q_IN_PTR_OFS	= 0x14,		/* also contains BASE_LO */
30231961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ
30331961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ	EDMA_REQ_Q_OUT_PTR_OFS	= 0x18,
30431961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ	EDMA_REQ_Q_PTR_SHIFT	= 5,
30531961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ
30631961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ	EDMA_RSP_Q_BASE_HI_OFS	= 0x1c,
30731961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ	EDMA_RSP_Q_IN_PTR_OFS	= 0x20,
30831961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ	EDMA_RSP_Q_OUT_PTR_OFS	= 0x24,		/* also contains BASE_LO */
30931961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ	EDMA_RSP_Q_PTR_SHIFT	= 3,
31031961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ
3110ea9e179f436f153fc19fdaef7abbc1e0da20762Jeff Garzik	EDMA_CMD_OFS		= 0x28,		/* EDMA command register */
3120ea9e179f436f153fc19fdaef7abbc1e0da20762Jeff Garzik	EDMA_EN			= (1 << 0),	/* enable EDMA */
3130ea9e179f436f153fc19fdaef7abbc1e0da20762Jeff Garzik	EDMA_DS			= (1 << 1),	/* disable EDMA; self-negated */
3140ea9e179f436f153fc19fdaef7abbc1e0da20762Jeff Garzik	ATA_RST			= (1 << 2),	/* reset trans/link/phy */
31520f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ
316c9d39130123238ac18478a42e25cb7996eacfcc0Jeff Garzik	EDMA_IORDY_TMOUT	= 0x34,
317bca1c4eb9411533d613123618c0d127fae532595Jeff Garzik	EDMA_ARB_CFG		= 0x38,
318bca1c4eb9411533d613123618c0d127fae532595Jeff Garzik
31931961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ	/* Host private flags (hp_flags) */
32031961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ	MV_HP_FLAG_MSI		= (1 << 0),
32147c2b677daeed9c79ecb7167c211ff36876ea611Jeff Garzik	MV_HP_ERRATA_50XXB0	= (1 << 1),
32247c2b677daeed9c79ecb7167c211ff36876ea611Jeff Garzik	MV_HP_ERRATA_50XXB2	= (1 << 2),
32347c2b677daeed9c79ecb7167c211ff36876ea611Jeff Garzik	MV_HP_ERRATA_60X1B2	= (1 << 3),
32447c2b677daeed9c79ecb7167c211ff36876ea611Jeff Garzik	MV_HP_ERRATA_60X1C0	= (1 << 4),
325e4e7b89280d1d666e2c09e5ad36cf071796c4c7eJeff Garzik	MV_HP_ERRATA_XX42A0	= (1 << 5),
3260ea9e179f436f153fc19fdaef7abbc1e0da20762Jeff Garzik	MV_HP_GEN_I		= (1 << 6),	/* Generation I: 50xx */
3270ea9e179f436f153fc19fdaef7abbc1e0da20762Jeff Garzik	MV_HP_GEN_II		= (1 << 7),	/* Generation II: 60xx */
3280ea9e179f436f153fc19fdaef7abbc1e0da20762Jeff Garzik	MV_HP_GEN_IIE		= (1 << 8),	/* Generation IIE: 6042/7042 */
32902a121da5a53d415b6596bc19cc6999d295d32a4Mark Lord	MV_HP_PCIE		= (1 << 9),	/* PCIe bus/regs: 7042 */
33020f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ
33131961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ	/* Port private flags (pp_flags) */
3320ea9e179f436f153fc19fdaef7abbc1e0da20762Jeff Garzik	MV_PP_FLAG_EDMA_EN	= (1 << 0),	/* is EDMA engine enabled? */
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;
40131961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ	struct mv_sg		*sg_tbl;
40231961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ	dma_addr_t		sg_tbl_dma;
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;
42202a121da5a53d415b6596bc19cc6999d295d32a4Mark Lord};
42302a121da5a53d415b6596bc19cc6999d295d32a4Mark Lord
42447c2b677daeed9c79ecb7167c211ff36876ea611Jeff Garzikstruct mv_hw_ops {
4252a47ce06d534692f9bd2bf4e90a20fc9b1054c39Jeff Garzik	void (*phy_errata)(struct mv_host_priv *hpriv, void __iomem *mmio,
4262a47ce06d534692f9bd2bf4e90a20fc9b1054c39Jeff Garzik			   unsigned int port);
42747c2b677daeed9c79ecb7167c211ff36876ea611Jeff Garzik	void (*enable_leds)(struct mv_host_priv *hpriv, void __iomem *mmio);
42847c2b677daeed9c79ecb7167c211ff36876ea611Jeff Garzik	void (*read_preamp)(struct mv_host_priv *hpriv, int idx,
42947c2b677daeed9c79ecb7167c211ff36876ea611Jeff Garzik			   void __iomem *mmio);
430c9d39130123238ac18478a42e25cb7996eacfcc0Jeff Garzik	int (*reset_hc)(struct mv_host_priv *hpriv, void __iomem *mmio,
431c9d39130123238ac18478a42e25cb7996eacfcc0Jeff Garzik			unsigned int n_hc);
432522479fb98c6667f081e75f87e298e413c0b1db8Jeff Garzik	void (*reset_flash)(struct mv_host_priv *hpriv, void __iomem *mmio);
433522479fb98c6667f081e75f87e298e413c0b1db8Jeff Garzik	void (*reset_bus)(struct pci_dev *pdev, void __iomem *mmio);
43447c2b677daeed9c79ecb7167c211ff36876ea611Jeff Garzik};
43547c2b677daeed9c79ecb7167c211ff36876ea611Jeff Garzik
43620f733e7d75a16bffc34842b7682c9247dd5f954Brett Russstatic void mv_irq_clear(struct ata_port *ap);
437da3dbb17a0e9a9ec7f5aed95f1fddadb790edc9dTejun Heostatic int mv_scr_read(struct ata_port *ap, unsigned int sc_reg_in, u32 *val);
438da3dbb17a0e9a9ec7f5aed95f1fddadb790edc9dTejun Heostatic int mv_scr_write(struct ata_port *ap, unsigned int sc_reg_in, u32 val);
439da3dbb17a0e9a9ec7f5aed95f1fddadb790edc9dTejun Heostatic int mv5_scr_read(struct ata_port *ap, unsigned int sc_reg_in, u32 *val);
440da3dbb17a0e9a9ec7f5aed95f1fddadb790edc9dTejun Heostatic int mv5_scr_write(struct ata_port *ap, unsigned int sc_reg_in, u32 val);
44131961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russstatic int mv_port_start(struct ata_port *ap);
44231961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russstatic void mv_port_stop(struct ata_port *ap);
44331961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russstatic void mv_qc_prep(struct ata_queued_cmd *qc);
444e4e7b89280d1d666e2c09e5ad36cf071796c4c7eJeff Garzikstatic void mv_qc_prep_iie(struct ata_queued_cmd *qc);
4459a3d9eb0177eb10500d49cd283b35576082a522dTejun Heostatic unsigned int mv_qc_issue(struct ata_queued_cmd *qc);
446bdd4dddee325a7dce3e84cf48201a06aa8508aa4Jeff Garzikstatic void mv_error_handler(struct ata_port *ap);
447bdd4dddee325a7dce3e84cf48201a06aa8508aa4Jeff Garzikstatic void mv_post_int_cmd(struct ata_queued_cmd *qc);
448bdd4dddee325a7dce3e84cf48201a06aa8508aa4Jeff Garzikstatic void mv_eh_freeze(struct ata_port *ap);
449bdd4dddee325a7dce3e84cf48201a06aa8508aa4Jeff Garzikstatic void mv_eh_thaw(struct ata_port *ap);
45020f733e7d75a16bffc34842b7682c9247dd5f954Brett Russstatic int mv_init_one(struct pci_dev *pdev, const struct pci_device_id *ent);
45120f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ
4522a47ce06d534692f9bd2bf4e90a20fc9b1054c39Jeff Garzikstatic void mv5_phy_errata(struct mv_host_priv *hpriv, void __iomem *mmio,
4532a47ce06d534692f9bd2bf4e90a20fc9b1054c39Jeff Garzik			   unsigned int port);
45447c2b677daeed9c79ecb7167c211ff36876ea611Jeff Garzikstatic void mv5_enable_leds(struct mv_host_priv *hpriv, void __iomem *mmio);
45547c2b677daeed9c79ecb7167c211ff36876ea611Jeff Garzikstatic void mv5_read_preamp(struct mv_host_priv *hpriv, int idx,
45647c2b677daeed9c79ecb7167c211ff36876ea611Jeff Garzik			   void __iomem *mmio);
457c9d39130123238ac18478a42e25cb7996eacfcc0Jeff Garzikstatic int mv5_reset_hc(struct mv_host_priv *hpriv, void __iomem *mmio,
458c9d39130123238ac18478a42e25cb7996eacfcc0Jeff Garzik			unsigned int n_hc);
459522479fb98c6667f081e75f87e298e413c0b1db8Jeff Garzikstatic void mv5_reset_flash(struct mv_host_priv *hpriv, void __iomem *mmio);
460522479fb98c6667f081e75f87e298e413c0b1db8Jeff Garzikstatic void mv5_reset_bus(struct pci_dev *pdev, void __iomem *mmio);
46147c2b677daeed9c79ecb7167c211ff36876ea611Jeff Garzik
4622a47ce06d534692f9bd2bf4e90a20fc9b1054c39Jeff Garzikstatic void mv6_phy_errata(struct mv_host_priv *hpriv, void __iomem *mmio,
4632a47ce06d534692f9bd2bf4e90a20fc9b1054c39Jeff Garzik			   unsigned int port);
46447c2b677daeed9c79ecb7167c211ff36876ea611Jeff Garzikstatic void mv6_enable_leds(struct mv_host_priv *hpriv, void __iomem *mmio);
46547c2b677daeed9c79ecb7167c211ff36876ea611Jeff Garzikstatic void mv6_read_preamp(struct mv_host_priv *hpriv, int idx,
46647c2b677daeed9c79ecb7167c211ff36876ea611Jeff Garzik			   void __iomem *mmio);
467c9d39130123238ac18478a42e25cb7996eacfcc0Jeff Garzikstatic int mv6_reset_hc(struct mv_host_priv *hpriv, void __iomem *mmio,
468c9d39130123238ac18478a42e25cb7996eacfcc0Jeff Garzik			unsigned int n_hc);
469522479fb98c6667f081e75f87e298e413c0b1db8Jeff Garzikstatic void mv6_reset_flash(struct mv_host_priv *hpriv, void __iomem *mmio);
470522479fb98c6667f081e75f87e298e413c0b1db8Jeff Garzikstatic void mv_reset_pci_bus(struct pci_dev *pdev, void __iomem *mmio);
471c9d39130123238ac18478a42e25cb7996eacfcc0Jeff Garzikstatic void mv_channel_reset(struct mv_host_priv *hpriv, void __iomem *mmio,
472c9d39130123238ac18478a42e25cb7996eacfcc0Jeff Garzik			     unsigned int port_no);
47347c2b677daeed9c79ecb7167c211ff36876ea611Jeff Garzik
474c5d3e45a2200a0905dc45b72714726b7aac3aaf1Jeff Garzikstatic struct scsi_host_template mv5_sht = {
475c5d3e45a2200a0905dc45b72714726b7aac3aaf1Jeff Garzik	.module			= THIS_MODULE,
476c5d3e45a2200a0905dc45b72714726b7aac3aaf1Jeff Garzik	.name			= DRV_NAME,
477c5d3e45a2200a0905dc45b72714726b7aac3aaf1Jeff Garzik	.ioctl			= ata_scsi_ioctl,
478c5d3e45a2200a0905dc45b72714726b7aac3aaf1Jeff Garzik	.queuecommand		= ata_scsi_queuecmd,
479c5d3e45a2200a0905dc45b72714726b7aac3aaf1Jeff Garzik	.can_queue		= ATA_DEF_QUEUE,
480c5d3e45a2200a0905dc45b72714726b7aac3aaf1Jeff Garzik	.this_id		= ATA_SHT_THIS_ID,
481baf14aa14efcfdb5a74d5cf804691086c6bec743Jeff Garzik	.sg_tablesize		= MV_MAX_SG_CT / 2,
482c5d3e45a2200a0905dc45b72714726b7aac3aaf1Jeff Garzik	.cmd_per_lun		= ATA_SHT_CMD_PER_LUN,
483c5d3e45a2200a0905dc45b72714726b7aac3aaf1Jeff Garzik	.emulated		= ATA_SHT_EMULATED,
484c5d3e45a2200a0905dc45b72714726b7aac3aaf1Jeff Garzik	.use_clustering		= 1,
485c5d3e45a2200a0905dc45b72714726b7aac3aaf1Jeff Garzik	.proc_name		= DRV_NAME,
486c5d3e45a2200a0905dc45b72714726b7aac3aaf1Jeff Garzik	.dma_boundary		= MV_DMA_BOUNDARY,
4873be6cbd73f74b4a3da82cc7d6e1688a4ae595fc7Jeff Garzik	.slave_configure	= ata_scsi_slave_config,
488c5d3e45a2200a0905dc45b72714726b7aac3aaf1Jeff Garzik	.slave_destroy		= ata_scsi_slave_destroy,
489c5d3e45a2200a0905dc45b72714726b7aac3aaf1Jeff Garzik	.bios_param		= ata_std_bios_param,
490c5d3e45a2200a0905dc45b72714726b7aac3aaf1Jeff Garzik};
491c5d3e45a2200a0905dc45b72714726b7aac3aaf1Jeff Garzik
492c5d3e45a2200a0905dc45b72714726b7aac3aaf1Jeff Garzikstatic struct scsi_host_template mv6_sht = {
49320f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ	.module			= THIS_MODULE,
49420f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ	.name			= DRV_NAME,
49520f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ	.ioctl			= ata_scsi_ioctl,
49620f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ	.queuecommand		= ata_scsi_queuecmd,
497c5d3e45a2200a0905dc45b72714726b7aac3aaf1Jeff Garzik	.can_queue		= ATA_DEF_QUEUE,
49820f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ	.this_id		= ATA_SHT_THIS_ID,
499baf14aa14efcfdb5a74d5cf804691086c6bec743Jeff Garzik	.sg_tablesize		= MV_MAX_SG_CT / 2,
50020f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ	.cmd_per_lun		= ATA_SHT_CMD_PER_LUN,
50120f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ	.emulated		= ATA_SHT_EMULATED,
502d88184fb2348a50f7c34f5d49a901c875b2e0114Jeff Garzik	.use_clustering		= 1,
50320f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ	.proc_name		= DRV_NAME,
50420f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ	.dma_boundary		= MV_DMA_BOUNDARY,
5053be6cbd73f74b4a3da82cc7d6e1688a4ae595fc7Jeff Garzik	.slave_configure	= ata_scsi_slave_config,
506ccf68c3405fca11386004674377d951b9b18e756Tejun Heo	.slave_destroy		= ata_scsi_slave_destroy,
50720f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ	.bios_param		= ata_std_bios_param,
50820f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ};
50920f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ
510c9d39130123238ac18478a42e25cb7996eacfcc0Jeff Garzikstatic const struct ata_port_operations mv5_ops = {
511c9d39130123238ac18478a42e25cb7996eacfcc0Jeff Garzik	.tf_load		= ata_tf_load,
512c9d39130123238ac18478a42e25cb7996eacfcc0Jeff Garzik	.tf_read		= ata_tf_read,
513c9d39130123238ac18478a42e25cb7996eacfcc0Jeff Garzik	.check_status		= ata_check_status,
514c9d39130123238ac18478a42e25cb7996eacfcc0Jeff Garzik	.exec_command		= ata_exec_command,
515c9d39130123238ac18478a42e25cb7996eacfcc0Jeff Garzik	.dev_select		= ata_std_dev_select,
516c9d39130123238ac18478a42e25cb7996eacfcc0Jeff Garzik
517cffacd85bcf6fc652292001873119333555fe260Jeff Garzik	.cable_detect		= ata_cable_sata,
518c9d39130123238ac18478a42e25cb7996eacfcc0Jeff Garzik
519c9d39130123238ac18478a42e25cb7996eacfcc0Jeff Garzik	.qc_prep		= mv_qc_prep,
520c9d39130123238ac18478a42e25cb7996eacfcc0Jeff Garzik	.qc_issue		= mv_qc_issue,
5210d5ff566779f894ca9937231a181eb31e4adff0eTejun Heo	.data_xfer		= ata_data_xfer,
522c9d39130123238ac18478a42e25cb7996eacfcc0Jeff Garzik
523c9d39130123238ac18478a42e25cb7996eacfcc0Jeff Garzik	.irq_clear		= mv_irq_clear,
524246ce3b675843e0369643cceb4faeb6cf6d19a30Akira Iguchi	.irq_on			= ata_irq_on,
525c9d39130123238ac18478a42e25cb7996eacfcc0Jeff Garzik
526bdd4dddee325a7dce3e84cf48201a06aa8508aa4Jeff Garzik	.error_handler		= mv_error_handler,
527bdd4dddee325a7dce3e84cf48201a06aa8508aa4Jeff Garzik	.post_internal_cmd	= mv_post_int_cmd,
528bdd4dddee325a7dce3e84cf48201a06aa8508aa4Jeff Garzik	.freeze			= mv_eh_freeze,
529bdd4dddee325a7dce3e84cf48201a06aa8508aa4Jeff Garzik	.thaw			= mv_eh_thaw,
530bdd4dddee325a7dce3e84cf48201a06aa8508aa4Jeff Garzik
531c9d39130123238ac18478a42e25cb7996eacfcc0Jeff Garzik	.scr_read		= mv5_scr_read,
532c9d39130123238ac18478a42e25cb7996eacfcc0Jeff Garzik	.scr_write		= mv5_scr_write,
533c9d39130123238ac18478a42e25cb7996eacfcc0Jeff Garzik
534c9d39130123238ac18478a42e25cb7996eacfcc0Jeff Garzik	.port_start		= mv_port_start,
535c9d39130123238ac18478a42e25cb7996eacfcc0Jeff Garzik	.port_stop		= mv_port_stop,
536c9d39130123238ac18478a42e25cb7996eacfcc0Jeff Garzik};
537c9d39130123238ac18478a42e25cb7996eacfcc0Jeff Garzik
538c9d39130123238ac18478a42e25cb7996eacfcc0Jeff Garzikstatic const struct ata_port_operations mv6_ops = {
53920f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ	.tf_load		= ata_tf_load,
54020f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ	.tf_read		= ata_tf_read,
54120f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ	.check_status		= ata_check_status,
54220f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ	.exec_command		= ata_exec_command,
54320f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ	.dev_select		= ata_std_dev_select,
54420f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ
545cffacd85bcf6fc652292001873119333555fe260Jeff Garzik	.cable_detect		= ata_cable_sata,
54620f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ
54731961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ	.qc_prep		= mv_qc_prep,
54831961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ	.qc_issue		= mv_qc_issue,
5490d5ff566779f894ca9937231a181eb31e4adff0eTejun Heo	.data_xfer		= ata_data_xfer,
55020f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ
55120f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ	.irq_clear		= mv_irq_clear,
552246ce3b675843e0369643cceb4faeb6cf6d19a30Akira Iguchi	.irq_on			= ata_irq_on,
55320f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ
554bdd4dddee325a7dce3e84cf48201a06aa8508aa4Jeff Garzik	.error_handler		= mv_error_handler,
555bdd4dddee325a7dce3e84cf48201a06aa8508aa4Jeff Garzik	.post_internal_cmd	= mv_post_int_cmd,
556bdd4dddee325a7dce3e84cf48201a06aa8508aa4Jeff Garzik	.freeze			= mv_eh_freeze,
557bdd4dddee325a7dce3e84cf48201a06aa8508aa4Jeff Garzik	.thaw			= mv_eh_thaw,
558bdd4dddee325a7dce3e84cf48201a06aa8508aa4Jeff Garzik
55920f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ	.scr_read		= mv_scr_read,
56020f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ	.scr_write		= mv_scr_write,
56120f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ
56231961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ	.port_start		= mv_port_start,
56331961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ	.port_stop		= mv_port_stop,
56420f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ};
56520f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ
566e4e7b89280d1d666e2c09e5ad36cf071796c4c7eJeff Garzikstatic const struct ata_port_operations mv_iie_ops = {
567e4e7b89280d1d666e2c09e5ad36cf071796c4c7eJeff Garzik	.tf_load		= ata_tf_load,
568e4e7b89280d1d666e2c09e5ad36cf071796c4c7eJeff Garzik	.tf_read		= ata_tf_read,
569e4e7b89280d1d666e2c09e5ad36cf071796c4c7eJeff Garzik	.check_status		= ata_check_status,
570e4e7b89280d1d666e2c09e5ad36cf071796c4c7eJeff Garzik	.exec_command		= ata_exec_command,
571e4e7b89280d1d666e2c09e5ad36cf071796c4c7eJeff Garzik	.dev_select		= ata_std_dev_select,
572e4e7b89280d1d666e2c09e5ad36cf071796c4c7eJeff Garzik
573cffacd85bcf6fc652292001873119333555fe260Jeff Garzik	.cable_detect		= ata_cable_sata,
574e4e7b89280d1d666e2c09e5ad36cf071796c4c7eJeff Garzik
575e4e7b89280d1d666e2c09e5ad36cf071796c4c7eJeff Garzik	.qc_prep		= mv_qc_prep_iie,
576e4e7b89280d1d666e2c09e5ad36cf071796c4c7eJeff Garzik	.qc_issue		= mv_qc_issue,
5770d5ff566779f894ca9937231a181eb31e4adff0eTejun Heo	.data_xfer		= ata_data_xfer,
578e4e7b89280d1d666e2c09e5ad36cf071796c4c7eJeff Garzik
579e4e7b89280d1d666e2c09e5ad36cf071796c4c7eJeff Garzik	.irq_clear		= mv_irq_clear,
580246ce3b675843e0369643cceb4faeb6cf6d19a30Akira Iguchi	.irq_on			= ata_irq_on,
581e4e7b89280d1d666e2c09e5ad36cf071796c4c7eJeff Garzik
582bdd4dddee325a7dce3e84cf48201a06aa8508aa4Jeff Garzik	.error_handler		= mv_error_handler,
583bdd4dddee325a7dce3e84cf48201a06aa8508aa4Jeff Garzik	.post_internal_cmd	= mv_post_int_cmd,
584bdd4dddee325a7dce3e84cf48201a06aa8508aa4Jeff Garzik	.freeze			= mv_eh_freeze,
585bdd4dddee325a7dce3e84cf48201a06aa8508aa4Jeff Garzik	.thaw			= mv_eh_thaw,
586bdd4dddee325a7dce3e84cf48201a06aa8508aa4Jeff Garzik
587e4e7b89280d1d666e2c09e5ad36cf071796c4c7eJeff Garzik	.scr_read		= mv_scr_read,
588e4e7b89280d1d666e2c09e5ad36cf071796c4c7eJeff Garzik	.scr_write		= mv_scr_write,
589e4e7b89280d1d666e2c09e5ad36cf071796c4c7eJeff Garzik
590e4e7b89280d1d666e2c09e5ad36cf071796c4c7eJeff Garzik	.port_start		= mv_port_start,
591e4e7b89280d1d666e2c09e5ad36cf071796c4c7eJeff Garzik	.port_stop		= mv_port_stop,
592e4e7b89280d1d666e2c09e5ad36cf071796c4c7eJeff Garzik};
593e4e7b89280d1d666e2c09e5ad36cf071796c4c7eJeff Garzik
59498ac62defe529d04a192688f40d801a2d8fbcf98Arjan van de Venstatic const struct ata_port_info mv_port_info[] = {
59520f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ	{  /* chip_504x */
596cca3974e48607c3775dc73b544a5700b2e37c21aJeff Garzik		.flags		= MV_COMMON_FLAGS,
59731961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ		.pio_mask	= 0x1f,	/* pio0-4 */
598bf6263a853c9c143bf03f0a6fdcc68ab714fb5f5Jeff Garzik		.udma_mask	= ATA_UDMA6,
599c9d39130123238ac18478a42e25cb7996eacfcc0Jeff Garzik		.port_ops	= &mv5_ops,
60020f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ	},
60120f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ	{  /* chip_508x */
602c5d3e45a2200a0905dc45b72714726b7aac3aaf1Jeff Garzik		.flags		= MV_COMMON_FLAGS | MV_FLAG_DUAL_HC,
60331961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ		.pio_mask	= 0x1f,	/* pio0-4 */
604bf6263a853c9c143bf03f0a6fdcc68ab714fb5f5Jeff Garzik		.udma_mask	= ATA_UDMA6,
605c9d39130123238ac18478a42e25cb7996eacfcc0Jeff Garzik		.port_ops	= &mv5_ops,
60620f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ	},
60747c2b677daeed9c79ecb7167c211ff36876ea611Jeff Garzik	{  /* chip_5080 */
608c5d3e45a2200a0905dc45b72714726b7aac3aaf1Jeff Garzik		.flags		= MV_COMMON_FLAGS | MV_FLAG_DUAL_HC,
60947c2b677daeed9c79ecb7167c211ff36876ea611Jeff Garzik		.pio_mask	= 0x1f,	/* pio0-4 */
610bf6263a853c9c143bf03f0a6fdcc68ab714fb5f5Jeff Garzik		.udma_mask	= ATA_UDMA6,
611c9d39130123238ac18478a42e25cb7996eacfcc0Jeff Garzik		.port_ops	= &mv5_ops,
61247c2b677daeed9c79ecb7167c211ff36876ea611Jeff Garzik	},
61320f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ	{  /* chip_604x */
614c5d3e45a2200a0905dc45b72714726b7aac3aaf1Jeff Garzik		.flags		= MV_COMMON_FLAGS | MV_6XXX_FLAGS,
61531961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ		.pio_mask	= 0x1f,	/* pio0-4 */
616bf6263a853c9c143bf03f0a6fdcc68ab714fb5f5Jeff Garzik		.udma_mask	= ATA_UDMA6,
617c9d39130123238ac18478a42e25cb7996eacfcc0Jeff Garzik		.port_ops	= &mv6_ops,
61820f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ	},
61920f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ	{  /* chip_608x */
620c5d3e45a2200a0905dc45b72714726b7aac3aaf1Jeff Garzik		.flags		= MV_COMMON_FLAGS | MV_6XXX_FLAGS |
621c5d3e45a2200a0905dc45b72714726b7aac3aaf1Jeff Garzik				  MV_FLAG_DUAL_HC,
62231961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ		.pio_mask	= 0x1f,	/* pio0-4 */
623bf6263a853c9c143bf03f0a6fdcc68ab714fb5f5Jeff Garzik		.udma_mask	= ATA_UDMA6,
624c9d39130123238ac18478a42e25cb7996eacfcc0Jeff Garzik		.port_ops	= &mv6_ops,
62520f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ	},
626e4e7b89280d1d666e2c09e5ad36cf071796c4c7eJeff Garzik	{  /* chip_6042 */
627c5d3e45a2200a0905dc45b72714726b7aac3aaf1Jeff Garzik		.flags		= MV_COMMON_FLAGS | MV_6XXX_FLAGS,
628e4e7b89280d1d666e2c09e5ad36cf071796c4c7eJeff Garzik		.pio_mask	= 0x1f,	/* pio0-4 */
629bf6263a853c9c143bf03f0a6fdcc68ab714fb5f5Jeff Garzik		.udma_mask	= ATA_UDMA6,
630e4e7b89280d1d666e2c09e5ad36cf071796c4c7eJeff Garzik		.port_ops	= &mv_iie_ops,
631e4e7b89280d1d666e2c09e5ad36cf071796c4c7eJeff Garzik	},
632e4e7b89280d1d666e2c09e5ad36cf071796c4c7eJeff Garzik	{  /* chip_7042 */
633c5d3e45a2200a0905dc45b72714726b7aac3aaf1Jeff Garzik		.flags		= MV_COMMON_FLAGS | MV_6XXX_FLAGS,
634e4e7b89280d1d666e2c09e5ad36cf071796c4c7eJeff Garzik		.pio_mask	= 0x1f,	/* pio0-4 */
635bf6263a853c9c143bf03f0a6fdcc68ab714fb5f5Jeff Garzik		.udma_mask	= ATA_UDMA6,
636e4e7b89280d1d666e2c09e5ad36cf071796c4c7eJeff Garzik		.port_ops	= &mv_iie_ops,
637e4e7b89280d1d666e2c09e5ad36cf071796c4c7eJeff Garzik	},
63820f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ};
63920f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ
6403b7d697dfb7d03edb87e50b743a7ecff029618e9Jeff Garzikstatic const struct pci_device_id mv_pci_tbl[] = {
6412d2744fc8be620a2dc469cf48349e3e704119f1bJeff Garzik	{ PCI_VDEVICE(MARVELL, 0x5040), chip_504x },
6422d2744fc8be620a2dc469cf48349e3e704119f1bJeff Garzik	{ PCI_VDEVICE(MARVELL, 0x5041), chip_504x },
6432d2744fc8be620a2dc469cf48349e3e704119f1bJeff Garzik	{ PCI_VDEVICE(MARVELL, 0x5080), chip_5080 },
6442d2744fc8be620a2dc469cf48349e3e704119f1bJeff Garzik	{ PCI_VDEVICE(MARVELL, 0x5081), chip_508x },
645cfbf723eb7928879292ee71fa0d118fc4e37b8c9Alan Cox	/* RocketRAID 1740/174x have different identifiers */
646cfbf723eb7928879292ee71fa0d118fc4e37b8c9Alan Cox	{ PCI_VDEVICE(TTI, 0x1740), chip_508x },
647cfbf723eb7928879292ee71fa0d118fc4e37b8c9Alan Cox	{ PCI_VDEVICE(TTI, 0x1742), chip_508x },
6482d2744fc8be620a2dc469cf48349e3e704119f1bJeff Garzik
6492d2744fc8be620a2dc469cf48349e3e704119f1bJeff Garzik	{ PCI_VDEVICE(MARVELL, 0x6040), chip_604x },
6502d2744fc8be620a2dc469cf48349e3e704119f1bJeff Garzik	{ PCI_VDEVICE(MARVELL, 0x6041), chip_604x },
6512d2744fc8be620a2dc469cf48349e3e704119f1bJeff Garzik	{ PCI_VDEVICE(MARVELL, 0x6042), chip_6042 },
6522d2744fc8be620a2dc469cf48349e3e704119f1bJeff Garzik	{ PCI_VDEVICE(MARVELL, 0x6080), chip_608x },
6532d2744fc8be620a2dc469cf48349e3e704119f1bJeff Garzik	{ PCI_VDEVICE(MARVELL, 0x6081), chip_608x },
6542d2744fc8be620a2dc469cf48349e3e704119f1bJeff Garzik
6552d2744fc8be620a2dc469cf48349e3e704119f1bJeff Garzik	{ PCI_VDEVICE(ADAPTEC2, 0x0241), chip_604x },
6562d2744fc8be620a2dc469cf48349e3e704119f1bJeff Garzik
657d9f9c6bc91c14f53ffa782ffcd42259ecae1d38cFlorian Attenberger	/* Adaptec 1430SA */
658d9f9c6bc91c14f53ffa782ffcd42259ecae1d38cFlorian Attenberger	{ PCI_VDEVICE(ADAPTEC2, 0x0243), chip_7042 },
659d9f9c6bc91c14f53ffa782ffcd42259ecae1d38cFlorian Attenberger
66002a121da5a53d415b6596bc19cc6999d295d32a4Mark Lord	/* Marvell 7042 support */
6616a3d586d8e8a50e4cfd7f8c36d82a53c5614e05bMorrison, Tom	{ PCI_VDEVICE(MARVELL, 0x7042), chip_7042 },
6626a3d586d8e8a50e4cfd7f8c36d82a53c5614e05bMorrison, Tom
66302a121da5a53d415b6596bc19cc6999d295d32a4Mark Lord	/* Highpoint RocketRAID PCIe series */
66402a121da5a53d415b6596bc19cc6999d295d32a4Mark Lord	{ PCI_VDEVICE(TTI, 0x2300), chip_7042 },
66502a121da5a53d415b6596bc19cc6999d295d32a4Mark Lord	{ PCI_VDEVICE(TTI, 0x2310), chip_7042 },
66602a121da5a53d415b6596bc19cc6999d295d32a4Mark Lord
6672d2744fc8be620a2dc469cf48349e3e704119f1bJeff Garzik	{ }			/* terminate list */
66820f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ};
66920f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ
67020f733e7d75a16bffc34842b7682c9247dd5f954Brett Russstatic struct pci_driver mv_pci_driver = {
67120f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ	.name			= DRV_NAME,
67220f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ	.id_table		= mv_pci_tbl,
67320f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ	.probe			= mv_init_one,
67420f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ	.remove			= ata_pci_remove_one,
67520f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ};
67620f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ
67747c2b677daeed9c79ecb7167c211ff36876ea611Jeff Garzikstatic const struct mv_hw_ops mv5xxx_ops = {
67847c2b677daeed9c79ecb7167c211ff36876ea611Jeff Garzik	.phy_errata		= mv5_phy_errata,
67947c2b677daeed9c79ecb7167c211ff36876ea611Jeff Garzik	.enable_leds		= mv5_enable_leds,
68047c2b677daeed9c79ecb7167c211ff36876ea611Jeff Garzik	.read_preamp		= mv5_read_preamp,
68147c2b677daeed9c79ecb7167c211ff36876ea611Jeff Garzik	.reset_hc		= mv5_reset_hc,
682522479fb98c6667f081e75f87e298e413c0b1db8Jeff Garzik	.reset_flash		= mv5_reset_flash,
683522479fb98c6667f081e75f87e298e413c0b1db8Jeff Garzik	.reset_bus		= mv5_reset_bus,
68447c2b677daeed9c79ecb7167c211ff36876ea611Jeff Garzik};
68547c2b677daeed9c79ecb7167c211ff36876ea611Jeff Garzik
68647c2b677daeed9c79ecb7167c211ff36876ea611Jeff Garzikstatic const struct mv_hw_ops mv6xxx_ops = {
68747c2b677daeed9c79ecb7167c211ff36876ea611Jeff Garzik	.phy_errata		= mv6_phy_errata,
68847c2b677daeed9c79ecb7167c211ff36876ea611Jeff Garzik	.enable_leds		= mv6_enable_leds,
68947c2b677daeed9c79ecb7167c211ff36876ea611Jeff Garzik	.read_preamp		= mv6_read_preamp,
69047c2b677daeed9c79ecb7167c211ff36876ea611Jeff Garzik	.reset_hc		= mv6_reset_hc,
691522479fb98c6667f081e75f87e298e413c0b1db8Jeff Garzik	.reset_flash		= mv6_reset_flash,
692522479fb98c6667f081e75f87e298e413c0b1db8Jeff Garzik	.reset_bus		= mv_reset_pci_bus,
69347c2b677daeed9c79ecb7167c211ff36876ea611Jeff Garzik};
69447c2b677daeed9c79ecb7167c211ff36876ea611Jeff Garzik
69520f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ/*
696ddef9bb367b19383df627e388cb4c01c86ddba6cJeff Garzik * module options
697ddef9bb367b19383df627e388cb4c01c86ddba6cJeff Garzik */
698ddef9bb367b19383df627e388cb4c01c86ddba6cJeff Garzikstatic int msi;	      /* Use PCI msi; either zero (off, default) or non-zero */
699ddef9bb367b19383df627e388cb4c01c86ddba6cJeff Garzik
700ddef9bb367b19383df627e388cb4c01c86ddba6cJeff Garzik
701d88184fb2348a50f7c34f5d49a901c875b2e0114Jeff Garzik/* move to PCI layer or libata core? */
702d88184fb2348a50f7c34f5d49a901c875b2e0114Jeff Garzikstatic int pci_go_64(struct pci_dev *pdev)
703d88184fb2348a50f7c34f5d49a901c875b2e0114Jeff Garzik{
704d88184fb2348a50f7c34f5d49a901c875b2e0114Jeff Garzik	int rc;
705d88184fb2348a50f7c34f5d49a901c875b2e0114Jeff Garzik
706d88184fb2348a50f7c34f5d49a901c875b2e0114Jeff Garzik	if (!pci_set_dma_mask(pdev, DMA_64BIT_MASK)) {
707d88184fb2348a50f7c34f5d49a901c875b2e0114Jeff Garzik		rc = pci_set_consistent_dma_mask(pdev, DMA_64BIT_MASK);
708d88184fb2348a50f7c34f5d49a901c875b2e0114Jeff Garzik		if (rc) {
709d88184fb2348a50f7c34f5d49a901c875b2e0114Jeff Garzik			rc = pci_set_consistent_dma_mask(pdev, DMA_32BIT_MASK);
710d88184fb2348a50f7c34f5d49a901c875b2e0114Jeff Garzik			if (rc) {
711d88184fb2348a50f7c34f5d49a901c875b2e0114Jeff Garzik				dev_printk(KERN_ERR, &pdev->dev,
712d88184fb2348a50f7c34f5d49a901c875b2e0114Jeff Garzik					   "64-bit DMA enable failed\n");
713d88184fb2348a50f7c34f5d49a901c875b2e0114Jeff Garzik				return rc;
714d88184fb2348a50f7c34f5d49a901c875b2e0114Jeff Garzik			}
715d88184fb2348a50f7c34f5d49a901c875b2e0114Jeff Garzik		}
716d88184fb2348a50f7c34f5d49a901c875b2e0114Jeff Garzik	} else {
717d88184fb2348a50f7c34f5d49a901c875b2e0114Jeff Garzik		rc = pci_set_dma_mask(pdev, DMA_32BIT_MASK);
718d88184fb2348a50f7c34f5d49a901c875b2e0114Jeff Garzik		if (rc) {
719d88184fb2348a50f7c34f5d49a901c875b2e0114Jeff Garzik			dev_printk(KERN_ERR, &pdev->dev,
720d88184fb2348a50f7c34f5d49a901c875b2e0114Jeff Garzik				   "32-bit DMA enable failed\n");
721d88184fb2348a50f7c34f5d49a901c875b2e0114Jeff Garzik			return rc;
722d88184fb2348a50f7c34f5d49a901c875b2e0114Jeff Garzik		}
723d88184fb2348a50f7c34f5d49a901c875b2e0114Jeff Garzik		rc = pci_set_consistent_dma_mask(pdev, DMA_32BIT_MASK);
724d88184fb2348a50f7c34f5d49a901c875b2e0114Jeff Garzik		if (rc) {
725d88184fb2348a50f7c34f5d49a901c875b2e0114Jeff Garzik			dev_printk(KERN_ERR, &pdev->dev,
726d88184fb2348a50f7c34f5d49a901c875b2e0114Jeff Garzik				   "32-bit consistent DMA enable failed\n");
727d88184fb2348a50f7c34f5d49a901c875b2e0114Jeff Garzik			return rc;
728d88184fb2348a50f7c34f5d49a901c875b2e0114Jeff Garzik		}
729d88184fb2348a50f7c34f5d49a901c875b2e0114Jeff Garzik	}
730d88184fb2348a50f7c34f5d49a901c875b2e0114Jeff Garzik
731d88184fb2348a50f7c34f5d49a901c875b2e0114Jeff Garzik	return rc;
732d88184fb2348a50f7c34f5d49a901c875b2e0114Jeff Garzik}
733d88184fb2348a50f7c34f5d49a901c875b2e0114Jeff Garzik
734ddef9bb367b19383df627e388cb4c01c86ddba6cJeff Garzik/*
73520f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ * Functions
73620f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ */
73720f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ
73820f733e7d75a16bffc34842b7682c9247dd5f954Brett Russstatic inline void writelfl(unsigned long data, void __iomem *addr)
73920f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ{
74020f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ	writel(data, addr);
74120f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ	(void) readl(addr);	/* flush to avoid PCI posted write */
74220f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ}
74320f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ
74420f733e7d75a16bffc34842b7682c9247dd5f954Brett Russstatic inline void __iomem *mv_hc_base(void __iomem *base, unsigned int hc)
74520f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ{
74620f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ	return (base + MV_SATAHC0_REG_BASE + (hc * MV_SATAHC_REG_SZ));
74720f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ}
74820f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ
749c9d39130123238ac18478a42e25cb7996eacfcc0Jeff Garzikstatic inline unsigned int mv_hc_from_port(unsigned int port)
750c9d39130123238ac18478a42e25cb7996eacfcc0Jeff Garzik{
751c9d39130123238ac18478a42e25cb7996eacfcc0Jeff Garzik	return port >> MV_PORT_HC_SHIFT;
752c9d39130123238ac18478a42e25cb7996eacfcc0Jeff Garzik}
753c9d39130123238ac18478a42e25cb7996eacfcc0Jeff Garzik
754c9d39130123238ac18478a42e25cb7996eacfcc0Jeff Garzikstatic inline unsigned int mv_hardport_from_port(unsigned int port)
755c9d39130123238ac18478a42e25cb7996eacfcc0Jeff Garzik{
756c9d39130123238ac18478a42e25cb7996eacfcc0Jeff Garzik	return port & MV_PORT_MASK;
757c9d39130123238ac18478a42e25cb7996eacfcc0Jeff Garzik}
758c9d39130123238ac18478a42e25cb7996eacfcc0Jeff Garzik
759c9d39130123238ac18478a42e25cb7996eacfcc0Jeff Garzikstatic inline void __iomem *mv_hc_base_from_port(void __iomem *base,
760c9d39130123238ac18478a42e25cb7996eacfcc0Jeff Garzik						 unsigned int port)
761c9d39130123238ac18478a42e25cb7996eacfcc0Jeff Garzik{
762c9d39130123238ac18478a42e25cb7996eacfcc0Jeff Garzik	return mv_hc_base(base, mv_hc_from_port(port));
763c9d39130123238ac18478a42e25cb7996eacfcc0Jeff Garzik}
764c9d39130123238ac18478a42e25cb7996eacfcc0Jeff Garzik
76520f733e7d75a16bffc34842b7682c9247dd5f954Brett Russstatic inline void __iomem *mv_port_base(void __iomem *base, unsigned int port)
76620f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ{
767c9d39130123238ac18478a42e25cb7996eacfcc0Jeff Garzik	return  mv_hc_base_from_port(base, port) +
7688b260248d9e0e8b64bb72fd4dee03ad86984c344Jeff Garzik		MV_SATAHC_ARBTR_REG_SZ +
769c9d39130123238ac18478a42e25cb7996eacfcc0Jeff Garzik		(mv_hardport_from_port(port) * MV_PORT_REG_SZ);
77020f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ}
77120f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ
77220f733e7d75a16bffc34842b7682c9247dd5f954Brett Russstatic inline void __iomem *mv_ap_base(struct ata_port *ap)
77320f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ{
7740d5ff566779f894ca9937231a181eb31e4adff0eTejun Heo	return mv_port_base(ap->host->iomap[MV_PRIMARY_BAR], ap->port_no);
77520f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ}
77620f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ
777cca3974e48607c3775dc73b544a5700b2e37c21aJeff Garzikstatic inline int mv_get_hc_count(unsigned long port_flags)
77831961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ{
779cca3974e48607c3775dc73b544a5700b2e37c21aJeff Garzik	return ((port_flags & MV_FLAG_DUAL_HC) ? 2 : 1);
78031961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ}
78131961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ
78231961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russstatic void mv_irq_clear(struct ata_port *ap)
78320f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ{
78420f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ}
78520f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ
786c5d3e45a2200a0905dc45b72714726b7aac3aaf1Jeff Garzikstatic void mv_set_edma_ptrs(void __iomem *port_mmio,
787c5d3e45a2200a0905dc45b72714726b7aac3aaf1Jeff Garzik			     struct mv_host_priv *hpriv,
788c5d3e45a2200a0905dc45b72714726b7aac3aaf1Jeff Garzik			     struct mv_port_priv *pp)
789c5d3e45a2200a0905dc45b72714726b7aac3aaf1Jeff Garzik{
790bdd4dddee325a7dce3e84cf48201a06aa8508aa4Jeff Garzik	u32 index;
791bdd4dddee325a7dce3e84cf48201a06aa8508aa4Jeff Garzik
792c5d3e45a2200a0905dc45b72714726b7aac3aaf1Jeff Garzik	/*
793c5d3e45a2200a0905dc45b72714726b7aac3aaf1Jeff Garzik	 * initialize request queue
794c5d3e45a2200a0905dc45b72714726b7aac3aaf1Jeff Garzik	 */
795bdd4dddee325a7dce3e84cf48201a06aa8508aa4Jeff Garzik	index = (pp->req_idx & MV_MAX_Q_DEPTH_MASK) << EDMA_REQ_Q_PTR_SHIFT;
796bdd4dddee325a7dce3e84cf48201a06aa8508aa4Jeff Garzik
797c5d3e45a2200a0905dc45b72714726b7aac3aaf1Jeff Garzik	WARN_ON(pp->crqb_dma & 0x3ff);
798c5d3e45a2200a0905dc45b72714726b7aac3aaf1Jeff Garzik	writel((pp->crqb_dma >> 16) >> 16, port_mmio + EDMA_REQ_Q_BASE_HI_OFS);
799bdd4dddee325a7dce3e84cf48201a06aa8508aa4Jeff Garzik	writelfl((pp->crqb_dma & EDMA_REQ_Q_BASE_LO_MASK) | index,
800c5d3e45a2200a0905dc45b72714726b7aac3aaf1Jeff Garzik		 port_mmio + EDMA_REQ_Q_IN_PTR_OFS);
801c5d3e45a2200a0905dc45b72714726b7aac3aaf1Jeff Garzik
802c5d3e45a2200a0905dc45b72714726b7aac3aaf1Jeff Garzik	if (hpriv->hp_flags & MV_HP_ERRATA_XX42A0)
803bdd4dddee325a7dce3e84cf48201a06aa8508aa4Jeff Garzik		writelfl((pp->crqb_dma & 0xffffffff) | index,
804c5d3e45a2200a0905dc45b72714726b7aac3aaf1Jeff Garzik			 port_mmio + EDMA_REQ_Q_OUT_PTR_OFS);
805c5d3e45a2200a0905dc45b72714726b7aac3aaf1Jeff Garzik	else
806bdd4dddee325a7dce3e84cf48201a06aa8508aa4Jeff Garzik		writelfl(index, port_mmio + EDMA_REQ_Q_OUT_PTR_OFS);
807c5d3e45a2200a0905dc45b72714726b7aac3aaf1Jeff Garzik
808c5d3e45a2200a0905dc45b72714726b7aac3aaf1Jeff Garzik	/*
809c5d3e45a2200a0905dc45b72714726b7aac3aaf1Jeff Garzik	 * initialize response queue
810c5d3e45a2200a0905dc45b72714726b7aac3aaf1Jeff Garzik	 */
811bdd4dddee325a7dce3e84cf48201a06aa8508aa4Jeff Garzik	index = (pp->resp_idx & MV_MAX_Q_DEPTH_MASK) << EDMA_RSP_Q_PTR_SHIFT;
812bdd4dddee325a7dce3e84cf48201a06aa8508aa4Jeff Garzik
813c5d3e45a2200a0905dc45b72714726b7aac3aaf1Jeff Garzik	WARN_ON(pp->crpb_dma & 0xff);
814c5d3e45a2200a0905dc45b72714726b7aac3aaf1Jeff Garzik	writel((pp->crpb_dma >> 16) >> 16, port_mmio + EDMA_RSP_Q_BASE_HI_OFS);
815c5d3e45a2200a0905dc45b72714726b7aac3aaf1Jeff Garzik
816c5d3e45a2200a0905dc45b72714726b7aac3aaf1Jeff Garzik	if (hpriv->hp_flags & MV_HP_ERRATA_XX42A0)
817bdd4dddee325a7dce3e84cf48201a06aa8508aa4Jeff Garzik		writelfl((pp->crpb_dma & 0xffffffff) | index,
818c5d3e45a2200a0905dc45b72714726b7aac3aaf1Jeff Garzik			 port_mmio + EDMA_RSP_Q_IN_PTR_OFS);
819c5d3e45a2200a0905dc45b72714726b7aac3aaf1Jeff Garzik	else
820bdd4dddee325a7dce3e84cf48201a06aa8508aa4Jeff Garzik		writelfl(index, port_mmio + EDMA_RSP_Q_IN_PTR_OFS);
821c5d3e45a2200a0905dc45b72714726b7aac3aaf1Jeff Garzik
822bdd4dddee325a7dce3e84cf48201a06aa8508aa4Jeff Garzik	writelfl((pp->crpb_dma & EDMA_RSP_Q_BASE_LO_MASK) | index,
823c5d3e45a2200a0905dc45b72714726b7aac3aaf1Jeff Garzik		 port_mmio + EDMA_RSP_Q_OUT_PTR_OFS);
824c5d3e45a2200a0905dc45b72714726b7aac3aaf1Jeff Garzik}
825c5d3e45a2200a0905dc45b72714726b7aac3aaf1Jeff Garzik
82605b308e1df6d9d673daedb517969241f41278b52Brett Russ/**
82705b308e1df6d9d673daedb517969241f41278b52Brett Russ *      mv_start_dma - Enable eDMA engine
82805b308e1df6d9d673daedb517969241f41278b52Brett Russ *      @base: port base address
82905b308e1df6d9d673daedb517969241f41278b52Brett Russ *      @pp: port private data
83005b308e1df6d9d673daedb517969241f41278b52Brett Russ *
831beec7dbc6ff003bbc94de62b3323519c878fb2acTejun Heo *      Verify the local cache of the eDMA state is accurate with a
832beec7dbc6ff003bbc94de62b3323519c878fb2acTejun Heo *      WARN_ON.
83305b308e1df6d9d673daedb517969241f41278b52Brett Russ *
83405b308e1df6d9d673daedb517969241f41278b52Brett Russ *      LOCKING:
83505b308e1df6d9d673daedb517969241f41278b52Brett Russ *      Inherited from caller.
83605b308e1df6d9d673daedb517969241f41278b52Brett Russ */
837f630d562829fcd8160a118f98c1e5b9cdb4e703eMark Lordstatic void mv_start_dma(void __iomem *port_mmio, struct mv_host_priv *hpriv,
838c5d3e45a2200a0905dc45b72714726b7aac3aaf1Jeff Garzik			 struct mv_port_priv *pp)
83920f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ{
840c5d3e45a2200a0905dc45b72714726b7aac3aaf1Jeff Garzik	if (!(pp->pp_flags & MV_PP_FLAG_EDMA_EN)) {
841bdd4dddee325a7dce3e84cf48201a06aa8508aa4Jeff Garzik		/* clear EDMA event indicators, if any */
842f630d562829fcd8160a118f98c1e5b9cdb4e703eMark Lord		writelfl(0, port_mmio + EDMA_ERR_IRQ_CAUSE_OFS);
843bdd4dddee325a7dce3e84cf48201a06aa8508aa4Jeff Garzik
844f630d562829fcd8160a118f98c1e5b9cdb4e703eMark Lord		mv_set_edma_ptrs(port_mmio, hpriv, pp);
845bdd4dddee325a7dce3e84cf48201a06aa8508aa4Jeff Garzik
846f630d562829fcd8160a118f98c1e5b9cdb4e703eMark Lord		writelfl(EDMA_EN, port_mmio + EDMA_CMD_OFS);
847afb0edd922c7ed6e73678730921dfcccebec17e8Brett Russ		pp->pp_flags |= MV_PP_FLAG_EDMA_EN;
848afb0edd922c7ed6e73678730921dfcccebec17e8Brett Russ	}
849f630d562829fcd8160a118f98c1e5b9cdb4e703eMark Lord	WARN_ON(!(EDMA_EN & readl(port_mmio + EDMA_CMD_OFS)));
85020f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ}
85120f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ
85205b308e1df6d9d673daedb517969241f41278b52Brett Russ/**
8530ea9e179f436f153fc19fdaef7abbc1e0da20762Jeff Garzik *      __mv_stop_dma - Disable eDMA engine
85405b308e1df6d9d673daedb517969241f41278b52Brett Russ *      @ap: ATA channel to manipulate
85505b308e1df6d9d673daedb517969241f41278b52Brett Russ *
856beec7dbc6ff003bbc94de62b3323519c878fb2acTejun Heo *      Verify the local cache of the eDMA state is accurate with a
857beec7dbc6ff003bbc94de62b3323519c878fb2acTejun Heo *      WARN_ON.
85805b308e1df6d9d673daedb517969241f41278b52Brett Russ *
85905b308e1df6d9d673daedb517969241f41278b52Brett Russ *      LOCKING:
86005b308e1df6d9d673daedb517969241f41278b52Brett Russ *      Inherited from caller.
86105b308e1df6d9d673daedb517969241f41278b52Brett Russ */
8620ea9e179f436f153fc19fdaef7abbc1e0da20762Jeff Garzikstatic int __mv_stop_dma(struct ata_port *ap)
86320f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ{
86431961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ	void __iomem *port_mmio = mv_ap_base(ap);
86531961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ	struct mv_port_priv *pp	= ap->private_data;
86631961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ	u32 reg;
867c5d3e45a2200a0905dc45b72714726b7aac3aaf1Jeff Garzik	int i, err = 0;
86831961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ
8694537deb5e90b717a725b3d74b58b4bb1d28443d0Jeff Garzik	if (pp->pp_flags & MV_PP_FLAG_EDMA_EN) {
870afb0edd922c7ed6e73678730921dfcccebec17e8Brett Russ		/* Disable EDMA if active.   The disable bit auto clears.
87131961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ		 */
87231961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ		writelfl(EDMA_DS, port_mmio + EDMA_CMD_OFS);
87331961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ		pp->pp_flags &= ~MV_PP_FLAG_EDMA_EN;
874afb0edd922c7ed6e73678730921dfcccebec17e8Brett Russ	} else {
875beec7dbc6ff003bbc94de62b3323519c878fb2acTejun Heo		WARN_ON(EDMA_EN & readl(port_mmio + EDMA_CMD_OFS));
8762dcb407e61458ded17503d6bd12b8c064965368bJeff Garzik	}
8778b260248d9e0e8b64bb72fd4dee03ad86984c344Jeff Garzik
87831961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ	/* now properly wait for the eDMA to stop */
87931961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ	for (i = 1000; i > 0; i--) {
88031961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ		reg = readl(port_mmio + EDMA_CMD_OFS);
8814537deb5e90b717a725b3d74b58b4bb1d28443d0Jeff Garzik		if (!(reg & EDMA_EN))
88231961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ			break;
8834537deb5e90b717a725b3d74b58b4bb1d28443d0Jeff Garzik
88431961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ		udelay(100);
88531961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ	}
88631961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ
887c5d3e45a2200a0905dc45b72714726b7aac3aaf1Jeff Garzik	if (reg & EDMA_EN) {
888f15a1dafed22d5037e0feea7528e1eeb28a1a7a3Tejun Heo		ata_port_printk(ap, KERN_ERR, "Unable to stop eDMA\n");
889c5d3e45a2200a0905dc45b72714726b7aac3aaf1Jeff Garzik		err = -EIO;
89031961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ	}
891c5d3e45a2200a0905dc45b72714726b7aac3aaf1Jeff Garzik
892c5d3e45a2200a0905dc45b72714726b7aac3aaf1Jeff Garzik	return err;
89320f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ}
89420f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ
8950ea9e179f436f153fc19fdaef7abbc1e0da20762Jeff Garzikstatic int mv_stop_dma(struct ata_port *ap)
8960ea9e179f436f153fc19fdaef7abbc1e0da20762Jeff Garzik{
8970ea9e179f436f153fc19fdaef7abbc1e0da20762Jeff Garzik	unsigned long flags;
8980ea9e179f436f153fc19fdaef7abbc1e0da20762Jeff Garzik	int rc;
8990ea9e179f436f153fc19fdaef7abbc1e0da20762Jeff Garzik
9000ea9e179f436f153fc19fdaef7abbc1e0da20762Jeff Garzik	spin_lock_irqsave(&ap->host->lock, flags);
9010ea9e179f436f153fc19fdaef7abbc1e0da20762Jeff Garzik	rc = __mv_stop_dma(ap);
9020ea9e179f436f153fc19fdaef7abbc1e0da20762Jeff Garzik	spin_unlock_irqrestore(&ap->host->lock, flags);
9030ea9e179f436f153fc19fdaef7abbc1e0da20762Jeff Garzik
9040ea9e179f436f153fc19fdaef7abbc1e0da20762Jeff Garzik	return rc;
9050ea9e179f436f153fc19fdaef7abbc1e0da20762Jeff Garzik}
9060ea9e179f436f153fc19fdaef7abbc1e0da20762Jeff Garzik
9078a70f8dc08dd40b7f8ac77280eaa99a8c6bc46f4Jeff Garzik#ifdef ATA_DEBUG
90831961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russstatic void mv_dump_mem(void __iomem *start, unsigned bytes)
90920f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ{
91031961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ	int b, w;
91131961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ	for (b = 0; b < bytes; ) {
91231961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ		DPRINTK("%p: ", start + b);
91331961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ		for (w = 0; b < bytes && w < 4; w++) {
9142dcb407e61458ded17503d6bd12b8c064965368bJeff Garzik			printk("%08x ", readl(start + b));
91531961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ			b += sizeof(u32);
91631961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ		}
91731961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ		printk("\n");
91831961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ	}
91931961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ}
9208a70f8dc08dd40b7f8ac77280eaa99a8c6bc46f4Jeff Garzik#endif
9218a70f8dc08dd40b7f8ac77280eaa99a8c6bc46f4Jeff Garzik
92231961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russstatic void mv_dump_pci_cfg(struct pci_dev *pdev, unsigned bytes)
92331961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ{
92431961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ#ifdef ATA_DEBUG
92531961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ	int b, w;
92631961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ	u32 dw;
92731961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ	for (b = 0; b < bytes; ) {
92831961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ		DPRINTK("%02x: ", b);
92931961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ		for (w = 0; b < bytes && w < 4; w++) {
9302dcb407e61458ded17503d6bd12b8c064965368bJeff Garzik			(void) pci_read_config_dword(pdev, b, &dw);
9312dcb407e61458ded17503d6bd12b8c064965368bJeff Garzik			printk("%08x ", dw);
93231961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ			b += sizeof(u32);
93331961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ		}
93431961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ		printk("\n");
93531961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ	}
93631961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ#endif
93731961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ}
93831961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russstatic void mv_dump_all_regs(void __iomem *mmio_base, int port,
93931961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ			     struct pci_dev *pdev)
94031961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ{
94131961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ#ifdef ATA_DEBUG
9428b260248d9e0e8b64bb72fd4dee03ad86984c344Jeff Garzik	void __iomem *hc_base = mv_hc_base(mmio_base,
94331961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ					   port >> MV_PORT_HC_SHIFT);
94431961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ	void __iomem *port_base;
94531961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ	int start_port, num_ports, p, start_hc, num_hcs, hc;
94631961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ
94731961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ	if (0 > port) {
94831961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ		start_hc = start_port = 0;
94931961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ		num_ports = 8;		/* shld be benign for 4 port devs */
95031961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ		num_hcs = 2;
95131961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ	} else {
95231961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ		start_hc = port >> MV_PORT_HC_SHIFT;
95331961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ		start_port = port;
95431961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ		num_ports = num_hcs = 1;
95531961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ	}
9568b260248d9e0e8b64bb72fd4dee03ad86984c344Jeff Garzik	DPRINTK("All registers for port(s) %u-%u:\n", start_port,
95731961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ		num_ports > 1 ? num_ports - 1 : start_port);
95831961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ
95931961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ	if (NULL != pdev) {
96031961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ		DPRINTK("PCI config space regs:\n");
96131961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ		mv_dump_pci_cfg(pdev, 0x68);
96231961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ	}
96331961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ	DPRINTK("PCI regs:\n");
96431961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ	mv_dump_mem(mmio_base+0xc00, 0x3c);
96531961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ	mv_dump_mem(mmio_base+0xd00, 0x34);
96631961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ	mv_dump_mem(mmio_base+0xf00, 0x4);
96731961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ	mv_dump_mem(mmio_base+0x1d00, 0x6c);
96831961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ	for (hc = start_hc; hc < start_hc + num_hcs; hc++) {
969d220c37e0a3c9a47ae00e87e044d963b3ea040bcDan Aloni		hc_base = mv_hc_base(mmio_base, hc);
97031961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ		DPRINTK("HC regs (HC %i):\n", hc);
97131961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ		mv_dump_mem(hc_base, 0x1c);
97231961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ	}
97331961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ	for (p = start_port; p < start_port + num_ports; p++) {
97431961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ		port_base = mv_port_base(mmio_base, p);
9752dcb407e61458ded17503d6bd12b8c064965368bJeff Garzik		DPRINTK("EDMA regs (port %i):\n", p);
97631961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ		mv_dump_mem(port_base, 0x54);
9772dcb407e61458ded17503d6bd12b8c064965368bJeff Garzik		DPRINTK("SATA regs (port %i):\n", p);
97831961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ		mv_dump_mem(port_base+0x300, 0x60);
97931961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ	}
98031961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ#endif
98120f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ}
98220f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ
98320f733e7d75a16bffc34842b7682c9247dd5f954Brett Russstatic unsigned int mv_scr_offset(unsigned int sc_reg_in)
98420f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ{
98520f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ	unsigned int ofs;
98620f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ
98720f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ	switch (sc_reg_in) {
98820f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ	case SCR_STATUS:
98920f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ	case SCR_CONTROL:
99020f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ	case SCR_ERROR:
99120f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ		ofs = SATA_STATUS_OFS + (sc_reg_in * sizeof(u32));
99220f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ		break;
99320f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ	case SCR_ACTIVE:
99420f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ		ofs = SATA_ACTIVE_OFS;   /* active is not with the others */
99520f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ		break;
99620f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ	default:
99720f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ		ofs = 0xffffffffU;
99820f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ		break;
99920f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ	}
100020f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ	return ofs;
100120f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ}
100220f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ
1003da3dbb17a0e9a9ec7f5aed95f1fddadb790edc9dTejun Heostatic int mv_scr_read(struct ata_port *ap, unsigned int sc_reg_in, u32 *val)
100420f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ{
100520f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ	unsigned int ofs = mv_scr_offset(sc_reg_in);
100620f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ
1007da3dbb17a0e9a9ec7f5aed95f1fddadb790edc9dTejun Heo	if (ofs != 0xffffffffU) {
1008da3dbb17a0e9a9ec7f5aed95f1fddadb790edc9dTejun Heo		*val = readl(mv_ap_base(ap) + ofs);
1009da3dbb17a0e9a9ec7f5aed95f1fddadb790edc9dTejun Heo		return 0;
1010da3dbb17a0e9a9ec7f5aed95f1fddadb790edc9dTejun Heo	} else
1011da3dbb17a0e9a9ec7f5aed95f1fddadb790edc9dTejun Heo		return -EINVAL;
101220f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ}
101320f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ
1014da3dbb17a0e9a9ec7f5aed95f1fddadb790edc9dTejun Heostatic int mv_scr_write(struct ata_port *ap, unsigned int sc_reg_in, u32 val)
101520f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ{
101620f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ	unsigned int ofs = mv_scr_offset(sc_reg_in);
101720f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ
1018da3dbb17a0e9a9ec7f5aed95f1fddadb790edc9dTejun Heo	if (ofs != 0xffffffffU) {
101920f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ		writelfl(val, mv_ap_base(ap) + ofs);
1020da3dbb17a0e9a9ec7f5aed95f1fddadb790edc9dTejun Heo		return 0;
1021da3dbb17a0e9a9ec7f5aed95f1fddadb790edc9dTejun Heo	} else
1022da3dbb17a0e9a9ec7f5aed95f1fddadb790edc9dTejun Heo		return -EINVAL;
102320f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ}
102420f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ
1025c5d3e45a2200a0905dc45b72714726b7aac3aaf1Jeff Garzikstatic void mv_edma_cfg(struct ata_port *ap, struct mv_host_priv *hpriv,
1026c5d3e45a2200a0905dc45b72714726b7aac3aaf1Jeff Garzik			void __iomem *port_mmio)
1027e4e7b89280d1d666e2c09e5ad36cf071796c4c7eJeff Garzik{
1028e4e7b89280d1d666e2c09e5ad36cf071796c4c7eJeff Garzik	u32 cfg = readl(port_mmio + EDMA_CFG_OFS);
1029e4e7b89280d1d666e2c09e5ad36cf071796c4c7eJeff Garzik
1030e4e7b89280d1d666e2c09e5ad36cf071796c4c7eJeff Garzik	/* set up non-NCQ EDMA configuration */
1031c5d3e45a2200a0905dc45b72714726b7aac3aaf1Jeff Garzik	cfg &= ~(1 << 9);	/* disable eQue */
1032e4e7b89280d1d666e2c09e5ad36cf071796c4c7eJeff Garzik
1033e728eabea110da90e69c05855e3a11174edb77efJeff Garzik	if (IS_GEN_I(hpriv)) {
1034e728eabea110da90e69c05855e3a11174edb77efJeff Garzik		cfg &= ~0x1f;		/* clear queue depth */
1035e4e7b89280d1d666e2c09e5ad36cf071796c4c7eJeff Garzik		cfg |= (1 << 8);	/* enab config burst size mask */
1036e728eabea110da90e69c05855e3a11174edb77efJeff Garzik	}
1037e4e7b89280d1d666e2c09e5ad36cf071796c4c7eJeff Garzik
1038e728eabea110da90e69c05855e3a11174edb77efJeff Garzik	else if (IS_GEN_II(hpriv)) {
1039e728eabea110da90e69c05855e3a11174edb77efJeff Garzik		cfg &= ~0x1f;		/* clear queue depth */
1040e4e7b89280d1d666e2c09e5ad36cf071796c4c7eJeff Garzik		cfg |= EDMA_CFG_RD_BRST_EXT | EDMA_CFG_WR_BUFF_LEN;
1041e728eabea110da90e69c05855e3a11174edb77efJeff Garzik		cfg &= ~(EDMA_CFG_NCQ | EDMA_CFG_NCQ_GO_ON_ERR); /* clear NCQ */
1042e728eabea110da90e69c05855e3a11174edb77efJeff Garzik	}
1043e4e7b89280d1d666e2c09e5ad36cf071796c4c7eJeff Garzik
1044e4e7b89280d1d666e2c09e5ad36cf071796c4c7eJeff Garzik	else if (IS_GEN_IIE(hpriv)) {
1045e728eabea110da90e69c05855e3a11174edb77efJeff Garzik		cfg |= (1 << 23);	/* do not mask PM field in rx'd FIS */
1046e728eabea110da90e69c05855e3a11174edb77efJeff Garzik		cfg |= (1 << 22);	/* enab 4-entry host queue cache */
1047e4e7b89280d1d666e2c09e5ad36cf071796c4c7eJeff Garzik		cfg &= ~(1 << 19);	/* dis 128-entry queue (for now?) */
1048e4e7b89280d1d666e2c09e5ad36cf071796c4c7eJeff Garzik		cfg |= (1 << 18);	/* enab early completion */
1049e728eabea110da90e69c05855e3a11174edb77efJeff Garzik		cfg |= (1 << 17);	/* enab cut-through (dis stor&forwrd) */
1050e728eabea110da90e69c05855e3a11174edb77efJeff Garzik		cfg &= ~(1 << 16);	/* dis FIS-based switching (for now) */
10514537deb5e90b717a725b3d74b58b4bb1d28443d0Jeff Garzik		cfg &= ~(EDMA_CFG_NCQ);	/* clear NCQ */
1052e4e7b89280d1d666e2c09e5ad36cf071796c4c7eJeff Garzik	}
1053e4e7b89280d1d666e2c09e5ad36cf071796c4c7eJeff Garzik
1054e4e7b89280d1d666e2c09e5ad36cf071796c4c7eJeff Garzik	writelfl(cfg, port_mmio + EDMA_CFG_OFS);
1055e4e7b89280d1d666e2c09e5ad36cf071796c4c7eJeff Garzik}
1056e4e7b89280d1d666e2c09e5ad36cf071796c4c7eJeff Garzik
105705b308e1df6d9d673daedb517969241f41278b52Brett Russ/**
105805b308e1df6d9d673daedb517969241f41278b52Brett Russ *      mv_port_start - Port specific init/start routine.
105905b308e1df6d9d673daedb517969241f41278b52Brett Russ *      @ap: ATA channel to manipulate
106005b308e1df6d9d673daedb517969241f41278b52Brett Russ *
106105b308e1df6d9d673daedb517969241f41278b52Brett Russ *      Allocate and point to DMA memory, init port private memory,
106205b308e1df6d9d673daedb517969241f41278b52Brett Russ *      zero indices.
106305b308e1df6d9d673daedb517969241f41278b52Brett Russ *
106405b308e1df6d9d673daedb517969241f41278b52Brett Russ *      LOCKING:
106505b308e1df6d9d673daedb517969241f41278b52Brett Russ *      Inherited from caller.
106605b308e1df6d9d673daedb517969241f41278b52Brett Russ */
106731961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russstatic int mv_port_start(struct ata_port *ap)
106831961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ{
1069cca3974e48607c3775dc73b544a5700b2e37c21aJeff Garzik	struct device *dev = ap->host->dev;
1070cca3974e48607c3775dc73b544a5700b2e37c21aJeff Garzik	struct mv_host_priv *hpriv = ap->host->private_data;
107131961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ	struct mv_port_priv *pp;
107231961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ	void __iomem *port_mmio = mv_ap_base(ap);
107331961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ	void *mem;
107431961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ	dma_addr_t mem_dma;
10750ea9e179f436f153fc19fdaef7abbc1e0da20762Jeff Garzik	unsigned long flags;
107624dc5f33ea4b504cfbd23fa159a4cacba8e4d800Tejun Heo	int rc;
107731961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ
107824dc5f33ea4b504cfbd23fa159a4cacba8e4d800Tejun Heo	pp = devm_kzalloc(dev, sizeof(*pp), GFP_KERNEL);
10796037d6bbdff65eb5a84fe35e140f4da4f7cc103aJeff Garzik	if (!pp)
108024dc5f33ea4b504cfbd23fa159a4cacba8e4d800Tejun Heo		return -ENOMEM;
108131961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ
108224dc5f33ea4b504cfbd23fa159a4cacba8e4d800Tejun Heo	mem = dmam_alloc_coherent(dev, MV_PORT_PRIV_DMA_SZ, &mem_dma,
108324dc5f33ea4b504cfbd23fa159a4cacba8e4d800Tejun Heo				  GFP_KERNEL);
10846037d6bbdff65eb5a84fe35e140f4da4f7cc103aJeff Garzik	if (!mem)
108524dc5f33ea4b504cfbd23fa159a4cacba8e4d800Tejun Heo		return -ENOMEM;
108631961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ	memset(mem, 0, MV_PORT_PRIV_DMA_SZ);
108731961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ
10886037d6bbdff65eb5a84fe35e140f4da4f7cc103aJeff Garzik	rc = ata_pad_alloc(ap, dev);
10896037d6bbdff65eb5a84fe35e140f4da4f7cc103aJeff Garzik	if (rc)
109024dc5f33ea4b504cfbd23fa159a4cacba8e4d800Tejun Heo		return rc;
10916037d6bbdff65eb5a84fe35e140f4da4f7cc103aJeff Garzik
10928b260248d9e0e8b64bb72fd4dee03ad86984c344Jeff Garzik	/* First item in chunk of DMA memory:
109331961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ	 * 32-slot command request table (CRQB), 32 bytes each in size
109431961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ	 */
109531961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ	pp->crqb = mem;
109631961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ	pp->crqb_dma = mem_dma;
109731961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ	mem += MV_CRQB_Q_SZ;
109831961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ	mem_dma += MV_CRQB_Q_SZ;
109931961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ
11008b260248d9e0e8b64bb72fd4dee03ad86984c344Jeff Garzik	/* Second item:
110131961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ	 * 32-slot command response table (CRPB), 8 bytes each in size
110231961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ	 */
110331961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ	pp->crpb = mem;
110431961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ	pp->crpb_dma = mem_dma;
110531961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ	mem += MV_CRPB_Q_SZ;
110631961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ	mem_dma += MV_CRPB_Q_SZ;
110731961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ
110831961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ	/* Third item:
110931961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ	 * Table of scatter-gather descriptors (ePRD), 16 bytes each
111031961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ	 */
111131961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ	pp->sg_tbl = mem;
111231961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ	pp->sg_tbl_dma = mem_dma;
111331961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ
11140ea9e179f436f153fc19fdaef7abbc1e0da20762Jeff Garzik	spin_lock_irqsave(&ap->host->lock, flags);
11150ea9e179f436f153fc19fdaef7abbc1e0da20762Jeff Garzik
1116c5d3e45a2200a0905dc45b72714726b7aac3aaf1Jeff Garzik	mv_edma_cfg(ap, hpriv, port_mmio);
1117e4e7b89280d1d666e2c09e5ad36cf071796c4c7eJeff Garzik
1118c5d3e45a2200a0905dc45b72714726b7aac3aaf1Jeff Garzik	mv_set_edma_ptrs(port_mmio, hpriv, pp);
111931961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ
11200ea9e179f436f153fc19fdaef7abbc1e0da20762Jeff Garzik	spin_unlock_irqrestore(&ap->host->lock, flags);
11210ea9e179f436f153fc19fdaef7abbc1e0da20762Jeff Garzik
112231961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ	/* Don't turn on EDMA here...do it before DMA commands only.  Else
112331961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ	 * we'll be unable to send non-data, PIO, etc due to restricted access
112431961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ	 * to shadow regs.
112531961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ	 */
112631961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ	ap->private_data = pp;
112731961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ	return 0;
112831961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ}
112931961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ
113005b308e1df6d9d673daedb517969241f41278b52Brett Russ/**
113105b308e1df6d9d673daedb517969241f41278b52Brett Russ *      mv_port_stop - Port specific cleanup/stop routine.
113205b308e1df6d9d673daedb517969241f41278b52Brett Russ *      @ap: ATA channel to manipulate
113305b308e1df6d9d673daedb517969241f41278b52Brett Russ *
113405b308e1df6d9d673daedb517969241f41278b52Brett Russ *      Stop DMA, cleanup port memory.
113505b308e1df6d9d673daedb517969241f41278b52Brett Russ *
113605b308e1df6d9d673daedb517969241f41278b52Brett Russ *      LOCKING:
1137cca3974e48607c3775dc73b544a5700b2e37c21aJeff Garzik *      This routine uses the host lock to protect the DMA stop.
113805b308e1df6d9d673daedb517969241f41278b52Brett Russ */
113931961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russstatic void mv_port_stop(struct ata_port *ap)
114031961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ{
114131961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ	mv_stop_dma(ap);
114231961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ}
114331961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ
114405b308e1df6d9d673daedb517969241f41278b52Brett Russ/**
114505b308e1df6d9d673daedb517969241f41278b52Brett Russ *      mv_fill_sg - Fill out the Marvell ePRD (scatter gather) entries
114605b308e1df6d9d673daedb517969241f41278b52Brett Russ *      @qc: queued command whose SG list to source from
114705b308e1df6d9d673daedb517969241f41278b52Brett Russ *
114805b308e1df6d9d673daedb517969241f41278b52Brett Russ *      Populate the SG list and mark the last entry.
114905b308e1df6d9d673daedb517969241f41278b52Brett Russ *
115005b308e1df6d9d673daedb517969241f41278b52Brett Russ *      LOCKING:
115105b308e1df6d9d673daedb517969241f41278b52Brett Russ *      Inherited from caller.
115205b308e1df6d9d673daedb517969241f41278b52Brett Russ */
11536c08772e49622e90d39903e7ff0be1a0f463ac86Jeff Garzikstatic void mv_fill_sg(struct ata_queued_cmd *qc)
115431961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ{
115531961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ	struct mv_port_priv *pp = qc->ap->private_data;
1156972c26bdd6b58e7534473c4f7928584578cf43f4Jeff Garzik	struct scatterlist *sg;
11573be6cbd73f74b4a3da82cc7d6e1688a4ae595fc7Jeff Garzik	struct mv_sg *mv_sg, *last_sg = NULL;
1158ff2aeb1eb64c8a4770a6304f9addbae9f9828646Tejun Heo	unsigned int si;
115931961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ
1160d88184fb2348a50f7c34f5d49a901c875b2e0114Jeff Garzik	mv_sg = pp->sg_tbl;
1161ff2aeb1eb64c8a4770a6304f9addbae9f9828646Tejun Heo	for_each_sg(qc->sg, sg, qc->n_elem, si) {
1162d88184fb2348a50f7c34f5d49a901c875b2e0114Jeff Garzik		dma_addr_t addr = sg_dma_address(sg);
1163d88184fb2348a50f7c34f5d49a901c875b2e0114Jeff Garzik		u32 sg_len = sg_dma_len(sg);
116422374677d18c5eeefd3a283431d312b8c44fef02Jeff Garzik
11654007b493ee6e4a52c2b618ab8361847fba5bf116Olof Johansson		while (sg_len) {
11664007b493ee6e4a52c2b618ab8361847fba5bf116Olof Johansson			u32 offset = addr & 0xffff;
11674007b493ee6e4a52c2b618ab8361847fba5bf116Olof Johansson			u32 len = sg_len;
116822374677d18c5eeefd3a283431d312b8c44fef02Jeff Garzik
11694007b493ee6e4a52c2b618ab8361847fba5bf116Olof Johansson			if ((offset + sg_len > 0x10000))
11704007b493ee6e4a52c2b618ab8361847fba5bf116Olof Johansson				len = 0x10000 - offset;
11714007b493ee6e4a52c2b618ab8361847fba5bf116Olof Johansson
11724007b493ee6e4a52c2b618ab8361847fba5bf116Olof Johansson			mv_sg->addr = cpu_to_le32(addr & 0xffffffff);
11734007b493ee6e4a52c2b618ab8361847fba5bf116Olof Johansson			mv_sg->addr_hi = cpu_to_le32((addr >> 16) >> 16);
11746c08772e49622e90d39903e7ff0be1a0f463ac86Jeff Garzik			mv_sg->flags_size = cpu_to_le32(len & 0xffff);
11754007b493ee6e4a52c2b618ab8361847fba5bf116Olof Johansson
11764007b493ee6e4a52c2b618ab8361847fba5bf116Olof Johansson			sg_len -= len;
11774007b493ee6e4a52c2b618ab8361847fba5bf116Olof Johansson			addr += len;
11784007b493ee6e4a52c2b618ab8361847fba5bf116Olof Johansson
11793be6cbd73f74b4a3da82cc7d6e1688a4ae595fc7Jeff Garzik			last_sg = mv_sg;
11804007b493ee6e4a52c2b618ab8361847fba5bf116Olof Johansson			mv_sg++;
11814007b493ee6e4a52c2b618ab8361847fba5bf116Olof Johansson		}
118231961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ	}
11833be6cbd73f74b4a3da82cc7d6e1688a4ae595fc7Jeff Garzik
11843be6cbd73f74b4a3da82cc7d6e1688a4ae595fc7Jeff Garzik	if (likely(last_sg))
11853be6cbd73f74b4a3da82cc7d6e1688a4ae595fc7Jeff Garzik		last_sg->flags_size |= cpu_to_le32(EPRD_FLAG_END_OF_TBL);
118631961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ}
118731961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ
11885796d1c4c89efff823259fda35b08ea66ebf8b23Jeff Garzikstatic void mv_crqb_pack_cmd(__le16 *cmdw, u8 data, u8 addr, unsigned last)
118931961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ{
1190559eedad7f7764dacca33980127b4615011230e4Mark Lord	u16 tmp = data | (addr << CRQB_CMD_ADDR_SHIFT) | CRQB_CMD_CS |
119131961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ		(last ? CRQB_CMD_LAST : 0);
1192559eedad7f7764dacca33980127b4615011230e4Mark Lord	*cmdw = cpu_to_le16(tmp);
119331961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ}
119431961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ
119505b308e1df6d9d673daedb517969241f41278b52Brett Russ/**
119605b308e1df6d9d673daedb517969241f41278b52Brett Russ *      mv_qc_prep - Host specific command preparation.
119705b308e1df6d9d673daedb517969241f41278b52Brett Russ *      @qc: queued command to prepare
119805b308e1df6d9d673daedb517969241f41278b52Brett Russ *
119905b308e1df6d9d673daedb517969241f41278b52Brett Russ *      This routine simply redirects to the general purpose routine
120005b308e1df6d9d673daedb517969241f41278b52Brett Russ *      if command is not DMA.  Else, it handles prep of the CRQB
120105b308e1df6d9d673daedb517969241f41278b52Brett Russ *      (command request block), does some sanity checking, and calls
120205b308e1df6d9d673daedb517969241f41278b52Brett Russ *      the SG load routine.
120305b308e1df6d9d673daedb517969241f41278b52Brett Russ *
120405b308e1df6d9d673daedb517969241f41278b52Brett Russ *      LOCKING:
120505b308e1df6d9d673daedb517969241f41278b52Brett Russ *      Inherited from caller.
120605b308e1df6d9d673daedb517969241f41278b52Brett Russ */
120731961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russstatic void mv_qc_prep(struct ata_queued_cmd *qc)
120831961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ{
120931961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ	struct ata_port *ap = qc->ap;
121031961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ	struct mv_port_priv *pp = ap->private_data;
1211e14698745dd0de1ddbf5cd0cca4313a90f8c1cc1Mark Lord	__le16 *cw;
121231961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ	struct ata_taskfile *tf;
121331961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ	u16 flags = 0;
1214a6432436c5e14b416f27c8f87c5bf0bc36771f49Mark Lord	unsigned in_index;
121531961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ
12162dcb407e61458ded17503d6bd12b8c064965368bJeff Garzik	if (qc->tf.protocol != ATA_PROT_DMA)
121731961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ		return;
121820f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ
121931961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ	/* Fill in command request block
122031961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ	 */
1221e4e7b89280d1d666e2c09e5ad36cf071796c4c7eJeff Garzik	if (!(qc->tf.flags & ATA_TFLAG_WRITE))
122231961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ		flags |= CRQB_FLAG_READ;
1223beec7dbc6ff003bbc94de62b3323519c878fb2acTejun Heo	WARN_ON(MV_MAX_Q_DEPTH <= qc->tag);
122431961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ	flags |= qc->tag << CRQB_TAG_SHIFT;
12254537deb5e90b717a725b3d74b58b4bb1d28443d0Jeff Garzik	flags |= qc->tag << CRQB_IOID_SHIFT;	/* 50xx appears to ignore this*/
122631961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ
1227bdd4dddee325a7dce3e84cf48201a06aa8508aa4Jeff Garzik	/* get current queue index from software */
1228bdd4dddee325a7dce3e84cf48201a06aa8508aa4Jeff Garzik	in_index = pp->req_idx & MV_MAX_Q_DEPTH_MASK;
1229a6432436c5e14b416f27c8f87c5bf0bc36771f49Mark Lord
1230a6432436c5e14b416f27c8f87c5bf0bc36771f49Mark Lord	pp->crqb[in_index].sg_addr =
123131961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ		cpu_to_le32(pp->sg_tbl_dma & 0xffffffff);
1232a6432436c5e14b416f27c8f87c5bf0bc36771f49Mark Lord	pp->crqb[in_index].sg_addr_hi =
123331961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ		cpu_to_le32((pp->sg_tbl_dma >> 16) >> 16);
1234a6432436c5e14b416f27c8f87c5bf0bc36771f49Mark Lord	pp->crqb[in_index].ctrl_flags = cpu_to_le16(flags);
123531961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ
1236a6432436c5e14b416f27c8f87c5bf0bc36771f49Mark Lord	cw = &pp->crqb[in_index].ata_cmd[0];
123731961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ	tf = &qc->tf;
123831961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ
123931961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ	/* Sadly, the CRQB cannot accomodate all registers--there are
124031961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ	 * only 11 bytes...so we must pick and choose required
124131961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ	 * registers based on the command.  So, we drop feature and
124231961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ	 * hob_feature for [RW] DMA commands, but they are needed for
124331961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ	 * NCQ.  NCQ will drop hob_nsect.
124420f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ	 */
124531961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ	switch (tf->command) {
124631961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ	case ATA_CMD_READ:
124731961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ	case ATA_CMD_READ_EXT:
124831961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ	case ATA_CMD_WRITE:
124931961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ	case ATA_CMD_WRITE_EXT:
1250c15d85c8f3f73b5f20aae7928e25b6996f16b328Jens Axboe	case ATA_CMD_WRITE_FUA_EXT:
125131961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ		mv_crqb_pack_cmd(cw++, tf->hob_nsect, ATA_REG_NSECT, 0);
125231961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ		break;
125331961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ#ifdef LIBATA_NCQ		/* FIXME: remove this line when NCQ added */
125431961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ	case ATA_CMD_FPDMA_READ:
125531961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ	case ATA_CMD_FPDMA_WRITE:
12568b260248d9e0e8b64bb72fd4dee03ad86984c344Jeff Garzik		mv_crqb_pack_cmd(cw++, tf->hob_feature, ATA_REG_FEATURE, 0);
125731961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ		mv_crqb_pack_cmd(cw++, tf->feature, ATA_REG_FEATURE, 0);
125831961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ		break;
125931961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ#endif				/* FIXME: remove this line when NCQ added */
126031961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ	default:
126131961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ		/* The only other commands EDMA supports in non-queued and
126231961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ		 * non-NCQ mode are: [RW] STREAM DMA and W DMA FUA EXT, none
126331961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ		 * of which are defined/used by Linux.  If we get here, this
126431961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ		 * driver needs work.
126531961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ		 *
126631961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ		 * FIXME: modify libata to give qc_prep a return value and
126731961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ		 * return error here.
126831961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ		 */
126931961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ		BUG_ON(tf->command);
127031961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ		break;
127131961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ	}
127231961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ	mv_crqb_pack_cmd(cw++, tf->nsect, ATA_REG_NSECT, 0);
127331961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ	mv_crqb_pack_cmd(cw++, tf->hob_lbal, ATA_REG_LBAL, 0);
127431961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ	mv_crqb_pack_cmd(cw++, tf->lbal, ATA_REG_LBAL, 0);
127531961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ	mv_crqb_pack_cmd(cw++, tf->hob_lbam, ATA_REG_LBAM, 0);
127631961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ	mv_crqb_pack_cmd(cw++, tf->lbam, ATA_REG_LBAM, 0);
127731961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ	mv_crqb_pack_cmd(cw++, tf->hob_lbah, ATA_REG_LBAH, 0);
127831961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ	mv_crqb_pack_cmd(cw++, tf->lbah, ATA_REG_LBAH, 0);
127931961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ	mv_crqb_pack_cmd(cw++, tf->device, ATA_REG_DEVICE, 0);
128031961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ	mv_crqb_pack_cmd(cw++, tf->command, ATA_REG_CMD, 1);	/* last */
128131961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ
1282e4e7b89280d1d666e2c09e5ad36cf071796c4c7eJeff Garzik	if (!(qc->flags & ATA_QCFLAG_DMAMAP))
1283e4e7b89280d1d666e2c09e5ad36cf071796c4c7eJeff Garzik		return;
1284e4e7b89280d1d666e2c09e5ad36cf071796c4c7eJeff Garzik	mv_fill_sg(qc);
1285e4e7b89280d1d666e2c09e5ad36cf071796c4c7eJeff Garzik}
1286e4e7b89280d1d666e2c09e5ad36cf071796c4c7eJeff Garzik
1287e4e7b89280d1d666e2c09e5ad36cf071796c4c7eJeff Garzik/**
1288e4e7b89280d1d666e2c09e5ad36cf071796c4c7eJeff Garzik *      mv_qc_prep_iie - Host specific command preparation.
1289e4e7b89280d1d666e2c09e5ad36cf071796c4c7eJeff Garzik *      @qc: queued command to prepare
1290e4e7b89280d1d666e2c09e5ad36cf071796c4c7eJeff Garzik *
1291e4e7b89280d1d666e2c09e5ad36cf071796c4c7eJeff Garzik *      This routine simply redirects to the general purpose routine
1292e4e7b89280d1d666e2c09e5ad36cf071796c4c7eJeff Garzik *      if command is not DMA.  Else, it handles prep of the CRQB
1293e4e7b89280d1d666e2c09e5ad36cf071796c4c7eJeff Garzik *      (command request block), does some sanity checking, and calls
1294e4e7b89280d1d666e2c09e5ad36cf071796c4c7eJeff Garzik *      the SG load routine.
1295e4e7b89280d1d666e2c09e5ad36cf071796c4c7eJeff Garzik *
1296e4e7b89280d1d666e2c09e5ad36cf071796c4c7eJeff Garzik *      LOCKING:
1297e4e7b89280d1d666e2c09e5ad36cf071796c4c7eJeff Garzik *      Inherited from caller.
1298e4e7b89280d1d666e2c09e5ad36cf071796c4c7eJeff Garzik */
1299e4e7b89280d1d666e2c09e5ad36cf071796c4c7eJeff Garzikstatic void mv_qc_prep_iie(struct ata_queued_cmd *qc)
1300e4e7b89280d1d666e2c09e5ad36cf071796c4c7eJeff Garzik{
1301e4e7b89280d1d666e2c09e5ad36cf071796c4c7eJeff Garzik	struct ata_port *ap = qc->ap;
1302e4e7b89280d1d666e2c09e5ad36cf071796c4c7eJeff Garzik	struct mv_port_priv *pp = ap->private_data;
1303e4e7b89280d1d666e2c09e5ad36cf071796c4c7eJeff Garzik	struct mv_crqb_iie *crqb;
1304e4e7b89280d1d666e2c09e5ad36cf071796c4c7eJeff Garzik	struct ata_taskfile *tf;
1305a6432436c5e14b416f27c8f87c5bf0bc36771f49Mark Lord	unsigned in_index;
1306e4e7b89280d1d666e2c09e5ad36cf071796c4c7eJeff Garzik	u32 flags = 0;
1307e4e7b89280d1d666e2c09e5ad36cf071796c4c7eJeff Garzik
13082dcb407e61458ded17503d6bd12b8c064965368bJeff Garzik	if (qc->tf.protocol != ATA_PROT_DMA)
1309e4e7b89280d1d666e2c09e5ad36cf071796c4c7eJeff Garzik		return;
1310e4e7b89280d1d666e2c09e5ad36cf071796c4c7eJeff Garzik
1311e4e7b89280d1d666e2c09e5ad36cf071796c4c7eJeff Garzik	/* Fill in Gen IIE command request block
1312e4e7b89280d1d666e2c09e5ad36cf071796c4c7eJeff Garzik	 */
1313e4e7b89280d1d666e2c09e5ad36cf071796c4c7eJeff Garzik	if (!(qc->tf.flags & ATA_TFLAG_WRITE))
1314e4e7b89280d1d666e2c09e5ad36cf071796c4c7eJeff Garzik		flags |= CRQB_FLAG_READ;
1315e4e7b89280d1d666e2c09e5ad36cf071796c4c7eJeff Garzik
1316beec7dbc6ff003bbc94de62b3323519c878fb2acTejun Heo	WARN_ON(MV_MAX_Q_DEPTH <= qc->tag);
1317e4e7b89280d1d666e2c09e5ad36cf071796c4c7eJeff Garzik	flags |= qc->tag << CRQB_TAG_SHIFT;
1318bdd4dddee325a7dce3e84cf48201a06aa8508aa4Jeff Garzik	flags |= qc->tag << CRQB_IOID_SHIFT;	/* "I/O Id" is -really-
13194537deb5e90b717a725b3d74b58b4bb1d28443d0Jeff Garzik						   what we use as our tag */
1320e4e7b89280d1d666e2c09e5ad36cf071796c4c7eJeff Garzik
1321bdd4dddee325a7dce3e84cf48201a06aa8508aa4Jeff Garzik	/* get current queue index from software */
1322bdd4dddee325a7dce3e84cf48201a06aa8508aa4Jeff Garzik	in_index = pp->req_idx & MV_MAX_Q_DEPTH_MASK;
1323a6432436c5e14b416f27c8f87c5bf0bc36771f49Mark Lord
1324a6432436c5e14b416f27c8f87c5bf0bc36771f49Mark Lord	crqb = (struct mv_crqb_iie *) &pp->crqb[in_index];
1325e4e7b89280d1d666e2c09e5ad36cf071796c4c7eJeff Garzik	crqb->addr = cpu_to_le32(pp->sg_tbl_dma & 0xffffffff);
1326e4e7b89280d1d666e2c09e5ad36cf071796c4c7eJeff Garzik	crqb->addr_hi = cpu_to_le32((pp->sg_tbl_dma >> 16) >> 16);
1327e4e7b89280d1d666e2c09e5ad36cf071796c4c7eJeff Garzik	crqb->flags = cpu_to_le32(flags);
1328e4e7b89280d1d666e2c09e5ad36cf071796c4c7eJeff Garzik
1329e4e7b89280d1d666e2c09e5ad36cf071796c4c7eJeff Garzik	tf = &qc->tf;
1330e4e7b89280d1d666e2c09e5ad36cf071796c4c7eJeff Garzik	crqb->ata_cmd[0] = cpu_to_le32(
1331e4e7b89280d1d666e2c09e5ad36cf071796c4c7eJeff Garzik			(tf->command << 16) |
1332e4e7b89280d1d666e2c09e5ad36cf071796c4c7eJeff Garzik			(tf->feature << 24)
1333e4e7b89280d1d666e2c09e5ad36cf071796c4c7eJeff Garzik		);
1334e4e7b89280d1d666e2c09e5ad36cf071796c4c7eJeff Garzik	crqb->ata_cmd[1] = cpu_to_le32(
1335e4e7b89280d1d666e2c09e5ad36cf071796c4c7eJeff Garzik			(tf->lbal << 0) |
1336e4e7b89280d1d666e2c09e5ad36cf071796c4c7eJeff Garzik			(tf->lbam << 8) |
1337e4e7b89280d1d666e2c09e5ad36cf071796c4c7eJeff Garzik			(tf->lbah << 16) |
1338e4e7b89280d1d666e2c09e5ad36cf071796c4c7eJeff Garzik			(tf->device << 24)
1339e4e7b89280d1d666e2c09e5ad36cf071796c4c7eJeff Garzik		);
1340e4e7b89280d1d666e2c09e5ad36cf071796c4c7eJeff Garzik	crqb->ata_cmd[2] = cpu_to_le32(
1341e4e7b89280d1d666e2c09e5ad36cf071796c4c7eJeff Garzik			(tf->hob_lbal << 0) |
1342e4e7b89280d1d666e2c09e5ad36cf071796c4c7eJeff Garzik			(tf->hob_lbam << 8) |
1343e4e7b89280d1d666e2c09e5ad36cf071796c4c7eJeff Garzik			(tf->hob_lbah << 16) |
1344e4e7b89280d1d666e2c09e5ad36cf071796c4c7eJeff Garzik			(tf->hob_feature << 24)
1345e4e7b89280d1d666e2c09e5ad36cf071796c4c7eJeff Garzik		);
1346e4e7b89280d1d666e2c09e5ad36cf071796c4c7eJeff Garzik	crqb->ata_cmd[3] = cpu_to_le32(
1347e4e7b89280d1d666e2c09e5ad36cf071796c4c7eJeff Garzik			(tf->nsect << 0) |
1348e4e7b89280d1d666e2c09e5ad36cf071796c4c7eJeff Garzik			(tf->hob_nsect << 8)
1349e4e7b89280d1d666e2c09e5ad36cf071796c4c7eJeff Garzik		);
1350e4e7b89280d1d666e2c09e5ad36cf071796c4c7eJeff Garzik
1351e4e7b89280d1d666e2c09e5ad36cf071796c4c7eJeff Garzik	if (!(qc->flags & ATA_QCFLAG_DMAMAP))
135231961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ		return;
135331961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ	mv_fill_sg(qc);
135431961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ}
135531961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ
135605b308e1df6d9d673daedb517969241f41278b52Brett Russ/**
135705b308e1df6d9d673daedb517969241f41278b52Brett Russ *      mv_qc_issue - Initiate a command to the host
135805b308e1df6d9d673daedb517969241f41278b52Brett Russ *      @qc: queued command to start
135905b308e1df6d9d673daedb517969241f41278b52Brett Russ *
136005b308e1df6d9d673daedb517969241f41278b52Brett Russ *      This routine simply redirects to the general purpose routine
136105b308e1df6d9d673daedb517969241f41278b52Brett Russ *      if command is not DMA.  Else, it sanity checks our local
136205b308e1df6d9d673daedb517969241f41278b52Brett Russ *      caches of the request producer/consumer indices then enables
136305b308e1df6d9d673daedb517969241f41278b52Brett Russ *      DMA and bumps the request producer index.
136405b308e1df6d9d673daedb517969241f41278b52Brett Russ *
136505b308e1df6d9d673daedb517969241f41278b52Brett Russ *      LOCKING:
136605b308e1df6d9d673daedb517969241f41278b52Brett Russ *      Inherited from caller.
136705b308e1df6d9d673daedb517969241f41278b52Brett Russ */
13689a3d9eb0177eb10500d49cd283b35576082a522dTejun Heostatic unsigned int mv_qc_issue(struct ata_queued_cmd *qc)
136931961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ{
1370c5d3e45a2200a0905dc45b72714726b7aac3aaf1Jeff Garzik	struct ata_port *ap = qc->ap;
1371c5d3e45a2200a0905dc45b72714726b7aac3aaf1Jeff Garzik	void __iomem *port_mmio = mv_ap_base(ap);
1372c5d3e45a2200a0905dc45b72714726b7aac3aaf1Jeff Garzik	struct mv_port_priv *pp = ap->private_data;
1373c5d3e45a2200a0905dc45b72714726b7aac3aaf1Jeff Garzik	struct mv_host_priv *hpriv = ap->host->private_data;
1374bdd4dddee325a7dce3e84cf48201a06aa8508aa4Jeff Garzik	u32 in_index;
137531961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ
1376c5d3e45a2200a0905dc45b72714726b7aac3aaf1Jeff Garzik	if (qc->tf.protocol != ATA_PROT_DMA) {
137731961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ		/* We're about to send a non-EDMA capable command to the
137831961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ		 * port.  Turn off EDMA so there won't be problems accessing
137931961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ		 * shadow block, etc registers.
138031961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ		 */
13810ea9e179f436f153fc19fdaef7abbc1e0da20762Jeff Garzik		__mv_stop_dma(ap);
138231961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ		return ata_qc_issue_prot(qc);
138331961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ	}
138431961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ
1385bdd4dddee325a7dce3e84cf48201a06aa8508aa4Jeff Garzik	mv_start_dma(port_mmio, hpriv, pp);
1386bdd4dddee325a7dce3e84cf48201a06aa8508aa4Jeff Garzik
1387bdd4dddee325a7dce3e84cf48201a06aa8508aa4Jeff Garzik	in_index = pp->req_idx & MV_MAX_Q_DEPTH_MASK;
138831961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ
138931961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ	/* until we do queuing, the queue should be empty at this point */
1390a6432436c5e14b416f27c8f87c5bf0bc36771f49Mark Lord	WARN_ON(in_index != ((readl(port_mmio + EDMA_REQ_Q_OUT_PTR_OFS)
1391a6432436c5e14b416f27c8f87c5bf0bc36771f49Mark Lord		>> EDMA_REQ_Q_PTR_SHIFT) & MV_MAX_Q_DEPTH_MASK));
139231961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ
1393bdd4dddee325a7dce3e84cf48201a06aa8508aa4Jeff Garzik	pp->req_idx++;
139431961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ
1395bdd4dddee325a7dce3e84cf48201a06aa8508aa4Jeff Garzik	in_index = (pp->req_idx & MV_MAX_Q_DEPTH_MASK) << EDMA_REQ_Q_PTR_SHIFT;
139631961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ
139731961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ	/* and write the request in pointer to kick the EDMA to life */
1398bdd4dddee325a7dce3e84cf48201a06aa8508aa4Jeff Garzik	writelfl((pp->crqb_dma & EDMA_REQ_Q_BASE_LO_MASK) | in_index,
1399bdd4dddee325a7dce3e84cf48201a06aa8508aa4Jeff Garzik		 port_mmio + EDMA_REQ_Q_IN_PTR_OFS);
140031961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ
140131961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ	return 0;
140231961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ}
140331961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ
140405b308e1df6d9d673daedb517969241f41278b52Brett Russ/**
140505b308e1df6d9d673daedb517969241f41278b52Brett Russ *      mv_err_intr - Handle error interrupts on the port
140605b308e1df6d9d673daedb517969241f41278b52Brett Russ *      @ap: ATA channel to manipulate
14079b358e305c1d783c8a4ebf00344e95deb9e38f3dMark Lord *      @reset_allowed: bool: 0 == don't trigger from reset here
140805b308e1df6d9d673daedb517969241f41278b52Brett Russ *
140905b308e1df6d9d673daedb517969241f41278b52Brett Russ *      In most cases, just clear the interrupt and move on.  However,
141005b308e1df6d9d673daedb517969241f41278b52Brett Russ *      some cases require an eDMA reset, which is done right before
141105b308e1df6d9d673daedb517969241f41278b52Brett Russ *      the COMRESET in mv_phy_reset().  The SERR case requires a
141205b308e1df6d9d673daedb517969241f41278b52Brett Russ *      clear of pending errors in the SATA SERROR register.  Finally,
141305b308e1df6d9d673daedb517969241f41278b52Brett Russ *      if the port disabled DMA, update our cached copy to match.
141405b308e1df6d9d673daedb517969241f41278b52Brett Russ *
141505b308e1df6d9d673daedb517969241f41278b52Brett Russ *      LOCKING:
141605b308e1df6d9d673daedb517969241f41278b52Brett Russ *      Inherited from caller.
141705b308e1df6d9d673daedb517969241f41278b52Brett Russ */
1418bdd4dddee325a7dce3e84cf48201a06aa8508aa4Jeff Garzikstatic void mv_err_intr(struct ata_port *ap, struct ata_queued_cmd *qc)
141931961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ{
142031961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ	void __iomem *port_mmio = mv_ap_base(ap);
1421bdd4dddee325a7dce3e84cf48201a06aa8508aa4Jeff Garzik	u32 edma_err_cause, eh_freeze_mask, serr = 0;
1422bdd4dddee325a7dce3e84cf48201a06aa8508aa4Jeff Garzik	struct mv_port_priv *pp = ap->private_data;
1423bdd4dddee325a7dce3e84cf48201a06aa8508aa4Jeff Garzik	struct mv_host_priv *hpriv = ap->host->private_data;
1424bdd4dddee325a7dce3e84cf48201a06aa8508aa4Jeff Garzik	unsigned int edma_enabled = (pp->pp_flags & MV_PP_FLAG_EDMA_EN);
1425bdd4dddee325a7dce3e84cf48201a06aa8508aa4Jeff Garzik	unsigned int action = 0, err_mask = 0;
14269af5c9c97dc9d599281778864c72b385f0c63341Tejun Heo	struct ata_eh_info *ehi = &ap->link.eh_info;
142720f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ
1428bdd4dddee325a7dce3e84cf48201a06aa8508aa4Jeff Garzik	ata_ehi_clear_desc(ehi);
142920f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ
1430bdd4dddee325a7dce3e84cf48201a06aa8508aa4Jeff Garzik	if (!edma_enabled) {
1431bdd4dddee325a7dce3e84cf48201a06aa8508aa4Jeff Garzik		/* just a guess: do we need to do this? should we
1432bdd4dddee325a7dce3e84cf48201a06aa8508aa4Jeff Garzik		 * expand this, and do it in all cases?
1433bdd4dddee325a7dce3e84cf48201a06aa8508aa4Jeff Garzik		 */
1434936fd7328657884d5a69a55666c74a55aa83ca27Tejun Heo		sata_scr_read(&ap->link, SCR_ERROR, &serr);
1435936fd7328657884d5a69a55666c74a55aa83ca27Tejun Heo		sata_scr_write_flush(&ap->link, SCR_ERROR, serr);
143620f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ	}
1437bdd4dddee325a7dce3e84cf48201a06aa8508aa4Jeff Garzik
1438bdd4dddee325a7dce3e84cf48201a06aa8508aa4Jeff Garzik	edma_err_cause = readl(port_mmio + EDMA_ERR_IRQ_CAUSE_OFS);
1439bdd4dddee325a7dce3e84cf48201a06aa8508aa4Jeff Garzik
1440bdd4dddee325a7dce3e84cf48201a06aa8508aa4Jeff Garzik	ata_ehi_push_desc(ehi, "edma_err 0x%08x", edma_err_cause);
1441bdd4dddee325a7dce3e84cf48201a06aa8508aa4Jeff Garzik
1442bdd4dddee325a7dce3e84cf48201a06aa8508aa4Jeff Garzik	/*
1443bdd4dddee325a7dce3e84cf48201a06aa8508aa4Jeff Garzik	 * all generations share these EDMA error cause bits
1444bdd4dddee325a7dce3e84cf48201a06aa8508aa4Jeff Garzik	 */
1445bdd4dddee325a7dce3e84cf48201a06aa8508aa4Jeff Garzik
1446bdd4dddee325a7dce3e84cf48201a06aa8508aa4Jeff Garzik	if (edma_err_cause & EDMA_ERR_DEV)
1447bdd4dddee325a7dce3e84cf48201a06aa8508aa4Jeff Garzik		err_mask |= AC_ERR_DEV;
1448bdd4dddee325a7dce3e84cf48201a06aa8508aa4Jeff Garzik	if (edma_err_cause & (EDMA_ERR_D_PAR | EDMA_ERR_PRD_PAR |
14496c1153e00af8de755ec278d873a97c9ce2a72d10Jeff Garzik			EDMA_ERR_CRQB_PAR | EDMA_ERR_CRPB_PAR |
1450bdd4dddee325a7dce3e84cf48201a06aa8508aa4Jeff Garzik			EDMA_ERR_INTRL_PAR)) {
1451bdd4dddee325a7dce3e84cf48201a06aa8508aa4Jeff Garzik		err_mask |= AC_ERR_ATA_BUS;
1452bdd4dddee325a7dce3e84cf48201a06aa8508aa4Jeff Garzik		action |= ATA_EH_HARDRESET;
1453b64bbc39f2122a2276578e40144af69ef01decd4Tejun Heo		ata_ehi_push_desc(ehi, "parity error");
1454bdd4dddee325a7dce3e84cf48201a06aa8508aa4Jeff Garzik	}
1455bdd4dddee325a7dce3e84cf48201a06aa8508aa4Jeff Garzik	if (edma_err_cause & (EDMA_ERR_DEV_DCON | EDMA_ERR_DEV_CON)) {
1456bdd4dddee325a7dce3e84cf48201a06aa8508aa4Jeff Garzik		ata_ehi_hotplugged(ehi);
1457bdd4dddee325a7dce3e84cf48201a06aa8508aa4Jeff Garzik		ata_ehi_push_desc(ehi, edma_err_cause & EDMA_ERR_DEV_DCON ?
1458b64bbc39f2122a2276578e40144af69ef01decd4Tejun Heo			"dev disconnect" : "dev connect");
14593606a380692cf958355a40fc1aa336800c17baf1Mark Lord		action |= ATA_EH_HARDRESET;
1460bdd4dddee325a7dce3e84cf48201a06aa8508aa4Jeff Garzik	}
1461bdd4dddee325a7dce3e84cf48201a06aa8508aa4Jeff Garzik
1462ee9ccdf70163ca6408f6965e0fbc65baeac7312cJeff Garzik	if (IS_GEN_I(hpriv)) {
1463bdd4dddee325a7dce3e84cf48201a06aa8508aa4Jeff Garzik		eh_freeze_mask = EDMA_EH_FREEZE_5;
1464bdd4dddee325a7dce3e84cf48201a06aa8508aa4Jeff Garzik
1465bdd4dddee325a7dce3e84cf48201a06aa8508aa4Jeff Garzik		if (edma_err_cause & EDMA_ERR_SELF_DIS_5) {
1466bdd4dddee325a7dce3e84cf48201a06aa8508aa4Jeff Garzik			struct mv_port_priv *pp	= ap->private_data;
1467bdd4dddee325a7dce3e84cf48201a06aa8508aa4Jeff Garzik			pp->pp_flags &= ~MV_PP_FLAG_EDMA_EN;
1468b64bbc39f2122a2276578e40144af69ef01decd4Tejun Heo			ata_ehi_push_desc(ehi, "EDMA self-disable");
1469bdd4dddee325a7dce3e84cf48201a06aa8508aa4Jeff Garzik		}
1470bdd4dddee325a7dce3e84cf48201a06aa8508aa4Jeff Garzik	} else {
1471bdd4dddee325a7dce3e84cf48201a06aa8508aa4Jeff Garzik		eh_freeze_mask = EDMA_EH_FREEZE;
1472bdd4dddee325a7dce3e84cf48201a06aa8508aa4Jeff Garzik
1473bdd4dddee325a7dce3e84cf48201a06aa8508aa4Jeff Garzik		if (edma_err_cause & EDMA_ERR_SELF_DIS) {
1474bdd4dddee325a7dce3e84cf48201a06aa8508aa4Jeff Garzik			struct mv_port_priv *pp	= ap->private_data;
1475bdd4dddee325a7dce3e84cf48201a06aa8508aa4Jeff Garzik			pp->pp_flags &= ~MV_PP_FLAG_EDMA_EN;
1476b64bbc39f2122a2276578e40144af69ef01decd4Tejun Heo			ata_ehi_push_desc(ehi, "EDMA self-disable");
1477bdd4dddee325a7dce3e84cf48201a06aa8508aa4Jeff Garzik		}
1478bdd4dddee325a7dce3e84cf48201a06aa8508aa4Jeff Garzik
1479bdd4dddee325a7dce3e84cf48201a06aa8508aa4Jeff Garzik		if (edma_err_cause & EDMA_ERR_SERR) {
1480936fd7328657884d5a69a55666c74a55aa83ca27Tejun Heo			sata_scr_read(&ap->link, SCR_ERROR, &serr);
1481936fd7328657884d5a69a55666c74a55aa83ca27Tejun Heo			sata_scr_write_flush(&ap->link, SCR_ERROR, serr);
1482bdd4dddee325a7dce3e84cf48201a06aa8508aa4Jeff Garzik			err_mask = AC_ERR_ATA_BUS;
1483bdd4dddee325a7dce3e84cf48201a06aa8508aa4Jeff Garzik			action |= ATA_EH_HARDRESET;
1484bdd4dddee325a7dce3e84cf48201a06aa8508aa4Jeff Garzik		}
1485afb0edd922c7ed6e73678730921dfcccebec17e8Brett Russ	}
148620f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ
148720f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ	/* Clear EDMA now that SERR cleanup done */
14883606a380692cf958355a40fc1aa336800c17baf1Mark Lord	writelfl(~edma_err_cause, port_mmio + EDMA_ERR_IRQ_CAUSE_OFS);
148920f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ
1490bdd4dddee325a7dce3e84cf48201a06aa8508aa4Jeff Garzik	if (!err_mask) {
1491bdd4dddee325a7dce3e84cf48201a06aa8508aa4Jeff Garzik		err_mask = AC_ERR_OTHER;
1492bdd4dddee325a7dce3e84cf48201a06aa8508aa4Jeff Garzik		action |= ATA_EH_HARDRESET;
1493bdd4dddee325a7dce3e84cf48201a06aa8508aa4Jeff Garzik	}
1494bdd4dddee325a7dce3e84cf48201a06aa8508aa4Jeff Garzik
1495bdd4dddee325a7dce3e84cf48201a06aa8508aa4Jeff Garzik	ehi->serror |= serr;
1496bdd4dddee325a7dce3e84cf48201a06aa8508aa4Jeff Garzik	ehi->action |= action;
1497bdd4dddee325a7dce3e84cf48201a06aa8508aa4Jeff Garzik
1498bdd4dddee325a7dce3e84cf48201a06aa8508aa4Jeff Garzik	if (qc)
1499bdd4dddee325a7dce3e84cf48201a06aa8508aa4Jeff Garzik		qc->err_mask |= err_mask;
1500bdd4dddee325a7dce3e84cf48201a06aa8508aa4Jeff Garzik	else
1501bdd4dddee325a7dce3e84cf48201a06aa8508aa4Jeff Garzik		ehi->err_mask |= err_mask;
1502bdd4dddee325a7dce3e84cf48201a06aa8508aa4Jeff Garzik
1503bdd4dddee325a7dce3e84cf48201a06aa8508aa4Jeff Garzik	if (edma_err_cause & eh_freeze_mask)
1504bdd4dddee325a7dce3e84cf48201a06aa8508aa4Jeff Garzik		ata_port_freeze(ap);
1505bdd4dddee325a7dce3e84cf48201a06aa8508aa4Jeff Garzik	else
1506bdd4dddee325a7dce3e84cf48201a06aa8508aa4Jeff Garzik		ata_port_abort(ap);
1507bdd4dddee325a7dce3e84cf48201a06aa8508aa4Jeff Garzik}
1508bdd4dddee325a7dce3e84cf48201a06aa8508aa4Jeff Garzik
1509bdd4dddee325a7dce3e84cf48201a06aa8508aa4Jeff Garzikstatic void mv_intr_pio(struct ata_port *ap)
1510bdd4dddee325a7dce3e84cf48201a06aa8508aa4Jeff Garzik{
1511bdd4dddee325a7dce3e84cf48201a06aa8508aa4Jeff Garzik	struct ata_queued_cmd *qc;
1512bdd4dddee325a7dce3e84cf48201a06aa8508aa4Jeff Garzik	u8 ata_status;
1513bdd4dddee325a7dce3e84cf48201a06aa8508aa4Jeff Garzik
1514bdd4dddee325a7dce3e84cf48201a06aa8508aa4Jeff Garzik	/* ignore spurious intr if drive still BUSY */
1515bdd4dddee325a7dce3e84cf48201a06aa8508aa4Jeff Garzik	ata_status = readb(ap->ioaddr.status_addr);
1516bdd4dddee325a7dce3e84cf48201a06aa8508aa4Jeff Garzik	if (unlikely(ata_status & ATA_BUSY))
1517bdd4dddee325a7dce3e84cf48201a06aa8508aa4Jeff Garzik		return;
1518bdd4dddee325a7dce3e84cf48201a06aa8508aa4Jeff Garzik
1519bdd4dddee325a7dce3e84cf48201a06aa8508aa4Jeff Garzik	/* get active ATA command */
15209af5c9c97dc9d599281778864c72b385f0c63341Tejun Heo	qc = ata_qc_from_tag(ap, ap->link.active_tag);
1521bdd4dddee325a7dce3e84cf48201a06aa8508aa4Jeff Garzik	if (unlikely(!qc))			/* no active tag */
1522bdd4dddee325a7dce3e84cf48201a06aa8508aa4Jeff Garzik		return;
1523bdd4dddee325a7dce3e84cf48201a06aa8508aa4Jeff Garzik	if (qc->tf.flags & ATA_TFLAG_POLLING)	/* polling; we don't own qc */
1524bdd4dddee325a7dce3e84cf48201a06aa8508aa4Jeff Garzik		return;
1525bdd4dddee325a7dce3e84cf48201a06aa8508aa4Jeff Garzik
1526bdd4dddee325a7dce3e84cf48201a06aa8508aa4Jeff Garzik	/* and finally, complete the ATA command */
1527bdd4dddee325a7dce3e84cf48201a06aa8508aa4Jeff Garzik	qc->err_mask |= ac_err_mask(ata_status);
1528bdd4dddee325a7dce3e84cf48201a06aa8508aa4Jeff Garzik	ata_qc_complete(qc);
1529bdd4dddee325a7dce3e84cf48201a06aa8508aa4Jeff Garzik}
1530bdd4dddee325a7dce3e84cf48201a06aa8508aa4Jeff Garzik
1531bdd4dddee325a7dce3e84cf48201a06aa8508aa4Jeff Garzikstatic void mv_intr_edma(struct ata_port *ap)
1532bdd4dddee325a7dce3e84cf48201a06aa8508aa4Jeff Garzik{
1533bdd4dddee325a7dce3e84cf48201a06aa8508aa4Jeff Garzik	void __iomem *port_mmio = mv_ap_base(ap);
1534bdd4dddee325a7dce3e84cf48201a06aa8508aa4Jeff Garzik	struct mv_host_priv *hpriv = ap->host->private_data;
1535bdd4dddee325a7dce3e84cf48201a06aa8508aa4Jeff Garzik	struct mv_port_priv *pp = ap->private_data;
1536bdd4dddee325a7dce3e84cf48201a06aa8508aa4Jeff Garzik	struct ata_queued_cmd *qc;
1537bdd4dddee325a7dce3e84cf48201a06aa8508aa4Jeff Garzik	u32 out_index, in_index;
1538bdd4dddee325a7dce3e84cf48201a06aa8508aa4Jeff Garzik	bool work_done = false;
1539bdd4dddee325a7dce3e84cf48201a06aa8508aa4Jeff Garzik
1540bdd4dddee325a7dce3e84cf48201a06aa8508aa4Jeff Garzik	/* get h/w response queue pointer */
1541bdd4dddee325a7dce3e84cf48201a06aa8508aa4Jeff Garzik	in_index = (readl(port_mmio + EDMA_RSP_Q_IN_PTR_OFS)
1542bdd4dddee325a7dce3e84cf48201a06aa8508aa4Jeff Garzik			>> EDMA_RSP_Q_PTR_SHIFT) & MV_MAX_Q_DEPTH_MASK;
1543bdd4dddee325a7dce3e84cf48201a06aa8508aa4Jeff Garzik
1544bdd4dddee325a7dce3e84cf48201a06aa8508aa4Jeff Garzik	while (1) {
1545bdd4dddee325a7dce3e84cf48201a06aa8508aa4Jeff Garzik		u16 status;
15466c1153e00af8de755ec278d873a97c9ce2a72d10Jeff Garzik		unsigned int tag;
1547bdd4dddee325a7dce3e84cf48201a06aa8508aa4Jeff Garzik
1548bdd4dddee325a7dce3e84cf48201a06aa8508aa4Jeff Garzik		/* get s/w response queue last-read pointer, and compare */
1549bdd4dddee325a7dce3e84cf48201a06aa8508aa4Jeff Garzik		out_index = pp->resp_idx & MV_MAX_Q_DEPTH_MASK;
1550bdd4dddee325a7dce3e84cf48201a06aa8508aa4Jeff Garzik		if (in_index == out_index)
1551bdd4dddee325a7dce3e84cf48201a06aa8508aa4Jeff Garzik			break;
1552bdd4dddee325a7dce3e84cf48201a06aa8508aa4Jeff Garzik
1553bdd4dddee325a7dce3e84cf48201a06aa8508aa4Jeff Garzik		/* 50xx: get active ATA command */
15540ea9e179f436f153fc19fdaef7abbc1e0da20762Jeff Garzik		if (IS_GEN_I(hpriv))
15559af5c9c97dc9d599281778864c72b385f0c63341Tejun Heo			tag = ap->link.active_tag;
1556bdd4dddee325a7dce3e84cf48201a06aa8508aa4Jeff Garzik
15576c1153e00af8de755ec278d873a97c9ce2a72d10Jeff Garzik		/* Gen II/IIE: get active ATA command via tag, to enable
15586c1153e00af8de755ec278d873a97c9ce2a72d10Jeff Garzik		 * support for queueing.  this works transparently for
15596c1153e00af8de755ec278d873a97c9ce2a72d10Jeff Garzik		 * queued and non-queued modes.
1560bdd4dddee325a7dce3e84cf48201a06aa8508aa4Jeff Garzik		 */
15616c1153e00af8de755ec278d873a97c9ce2a72d10Jeff Garzik		else if (IS_GEN_II(hpriv))
15626c1153e00af8de755ec278d873a97c9ce2a72d10Jeff Garzik			tag = (le16_to_cpu(pp->crpb[out_index].id)
15636c1153e00af8de755ec278d873a97c9ce2a72d10Jeff Garzik				>> CRPB_IOID_SHIFT_6) & 0x3f;
1564bdd4dddee325a7dce3e84cf48201a06aa8508aa4Jeff Garzik
15656c1153e00af8de755ec278d873a97c9ce2a72d10Jeff Garzik		else /* IS_GEN_IIE */
15666c1153e00af8de755ec278d873a97c9ce2a72d10Jeff Garzik			tag = (le16_to_cpu(pp->crpb[out_index].id)
15676c1153e00af8de755ec278d873a97c9ce2a72d10Jeff Garzik				>> CRPB_IOID_SHIFT_7) & 0x3f;
1568bdd4dddee325a7dce3e84cf48201a06aa8508aa4Jeff Garzik
15696c1153e00af8de755ec278d873a97c9ce2a72d10Jeff Garzik		qc = ata_qc_from_tag(ap, tag);
1570bdd4dddee325a7dce3e84cf48201a06aa8508aa4Jeff Garzik
1571bdd4dddee325a7dce3e84cf48201a06aa8508aa4Jeff Garzik		/* lower 8 bits of status are EDMA_ERR_IRQ_CAUSE_OFS
1572bdd4dddee325a7dce3e84cf48201a06aa8508aa4Jeff Garzik		 * bits (WARNING: might not necessarily be associated
1573bdd4dddee325a7dce3e84cf48201a06aa8508aa4Jeff Garzik		 * with this command), which -should- be clear
1574bdd4dddee325a7dce3e84cf48201a06aa8508aa4Jeff Garzik		 * if all is well
1575bdd4dddee325a7dce3e84cf48201a06aa8508aa4Jeff Garzik		 */
1576bdd4dddee325a7dce3e84cf48201a06aa8508aa4Jeff Garzik		status = le16_to_cpu(pp->crpb[out_index].flags);
1577bdd4dddee325a7dce3e84cf48201a06aa8508aa4Jeff Garzik		if (unlikely(status & 0xff)) {
1578bdd4dddee325a7dce3e84cf48201a06aa8508aa4Jeff Garzik			mv_err_intr(ap, qc);
1579bdd4dddee325a7dce3e84cf48201a06aa8508aa4Jeff Garzik			return;
1580bdd4dddee325a7dce3e84cf48201a06aa8508aa4Jeff Garzik		}
1581bdd4dddee325a7dce3e84cf48201a06aa8508aa4Jeff Garzik
1582bdd4dddee325a7dce3e84cf48201a06aa8508aa4Jeff Garzik		/* and finally, complete the ATA command */
1583bdd4dddee325a7dce3e84cf48201a06aa8508aa4Jeff Garzik		if (qc) {
1584bdd4dddee325a7dce3e84cf48201a06aa8508aa4Jeff Garzik			qc->err_mask |=
1585bdd4dddee325a7dce3e84cf48201a06aa8508aa4Jeff Garzik				ac_err_mask(status >> CRPB_FLAG_STATUS_SHIFT);
1586bdd4dddee325a7dce3e84cf48201a06aa8508aa4Jeff Garzik			ata_qc_complete(qc);
1587bdd4dddee325a7dce3e84cf48201a06aa8508aa4Jeff Garzik		}
1588bdd4dddee325a7dce3e84cf48201a06aa8508aa4Jeff Garzik
15890ea9e179f436f153fc19fdaef7abbc1e0da20762Jeff Garzik		/* advance software response queue pointer, to
1590bdd4dddee325a7dce3e84cf48201a06aa8508aa4Jeff Garzik		 * indicate (after the loop completes) to hardware
1591bdd4dddee325a7dce3e84cf48201a06aa8508aa4Jeff Garzik		 * that we have consumed a response queue entry.
1592bdd4dddee325a7dce3e84cf48201a06aa8508aa4Jeff Garzik		 */
1593bdd4dddee325a7dce3e84cf48201a06aa8508aa4Jeff Garzik		work_done = true;
1594bdd4dddee325a7dce3e84cf48201a06aa8508aa4Jeff Garzik		pp->resp_idx++;
1595bdd4dddee325a7dce3e84cf48201a06aa8508aa4Jeff Garzik	}
1596bdd4dddee325a7dce3e84cf48201a06aa8508aa4Jeff Garzik
1597bdd4dddee325a7dce3e84cf48201a06aa8508aa4Jeff Garzik	if (work_done)
1598bdd4dddee325a7dce3e84cf48201a06aa8508aa4Jeff Garzik		writelfl((pp->crpb_dma & EDMA_RSP_Q_BASE_LO_MASK) |
1599bdd4dddee325a7dce3e84cf48201a06aa8508aa4Jeff Garzik			 (out_index << EDMA_RSP_Q_PTR_SHIFT),
1600bdd4dddee325a7dce3e84cf48201a06aa8508aa4Jeff Garzik			 port_mmio + EDMA_RSP_Q_OUT_PTR_OFS);
160120f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ}
160220f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ
160305b308e1df6d9d673daedb517969241f41278b52Brett Russ/**
160405b308e1df6d9d673daedb517969241f41278b52Brett Russ *      mv_host_intr - Handle all interrupts on the given host controller
1605cca3974e48607c3775dc73b544a5700b2e37c21aJeff Garzik *      @host: host specific structure
160605b308e1df6d9d673daedb517969241f41278b52Brett Russ *      @relevant: port error bits relevant to this host controller
160705b308e1df6d9d673daedb517969241f41278b52Brett Russ *      @hc: which host controller we're to look at
160805b308e1df6d9d673daedb517969241f41278b52Brett Russ *
160905b308e1df6d9d673daedb517969241f41278b52Brett Russ *      Read then write clear the HC interrupt status then walk each
161005b308e1df6d9d673daedb517969241f41278b52Brett Russ *      port connected to the HC and see if it needs servicing.  Port
161105b308e1df6d9d673daedb517969241f41278b52Brett Russ *      success ints are reported in the HC interrupt status reg, the
161205b308e1df6d9d673daedb517969241f41278b52Brett Russ *      port error ints are reported in the higher level main
161305b308e1df6d9d673daedb517969241f41278b52Brett Russ *      interrupt status register and thus are passed in via the
161405b308e1df6d9d673daedb517969241f41278b52Brett Russ *      'relevant' argument.
161505b308e1df6d9d673daedb517969241f41278b52Brett Russ *
161605b308e1df6d9d673daedb517969241f41278b52Brett Russ *      LOCKING:
161705b308e1df6d9d673daedb517969241f41278b52Brett Russ *      Inherited from caller.
161805b308e1df6d9d673daedb517969241f41278b52Brett Russ */
1619cca3974e48607c3775dc73b544a5700b2e37c21aJeff Garzikstatic void mv_host_intr(struct ata_host *host, u32 relevant, unsigned int hc)
162020f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ{
16210d5ff566779f894ca9937231a181eb31e4adff0eTejun Heo	void __iomem *mmio = host->iomap[MV_PRIMARY_BAR];
162220f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ	void __iomem *hc_mmio = mv_hc_base(mmio, hc);
162320f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ	u32 hc_irq_cause;
1624c5d3e45a2200a0905dc45b72714726b7aac3aaf1Jeff Garzik	int port, port0;
162520f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ
1626351772658a4d1acc0221a6e30676bb0594e74812Jeff Garzik	if (hc == 0)
162720f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ		port0 = 0;
1628351772658a4d1acc0221a6e30676bb0594e74812Jeff Garzik	else
162920f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ		port0 = MV_PORTS_PER_HC;
163020f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ
163120f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ	/* we'll need the HC success int register in most cases */
163220f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ	hc_irq_cause = readl(hc_mmio + HC_IRQ_CAUSE_OFS);
1633bdd4dddee325a7dce3e84cf48201a06aa8508aa4Jeff Garzik	if (!hc_irq_cause)
1634bdd4dddee325a7dce3e84cf48201a06aa8508aa4Jeff Garzik		return;
1635bdd4dddee325a7dce3e84cf48201a06aa8508aa4Jeff Garzik
1636bdd4dddee325a7dce3e84cf48201a06aa8508aa4Jeff Garzik	writelfl(~hc_irq_cause, hc_mmio + HC_IRQ_CAUSE_OFS);
163720f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ
163820f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ	VPRINTK("ENTER, hc%u relevant=0x%08x HC IRQ cause=0x%08x\n",
16392dcb407e61458ded17503d6bd12b8c064965368bJeff Garzik		hc, relevant, hc_irq_cause);
164020f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ
164120f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ	for (port = port0; port < port0 + MV_PORTS_PER_HC; port++) {
1642cca3974e48607c3775dc73b544a5700b2e37c21aJeff Garzik		struct ata_port *ap = host->ports[port];
164363af2a5c5990d95f1e7d8795f1425fb976ea2b4bMark Lord		struct mv_port_priv *pp = ap->private_data;
1644bdd4dddee325a7dce3e84cf48201a06aa8508aa4Jeff Garzik		int have_err_bits, hard_port, shift;
164555d8ca4f8094246da6e71889a4e04bfafaa78b10Jeff Garzik
1646bdd4dddee325a7dce3e84cf48201a06aa8508aa4Jeff Garzik		if ((!ap) || (ap->flags & ATA_FLAG_DISABLED))
1647a2c91a8819e315e9fd1aef3ff57badb6c1be3f80Jeff Garzik			continue;
1648a2c91a8819e315e9fd1aef3ff57badb6c1be3f80Jeff Garzik
164931961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ		shift = port << 1;		/* (port * 2) */
165020f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ		if (port >= MV_PORTS_PER_HC) {
165120f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ			shift++;	/* skip bit 8 in the HC Main IRQ reg */
165220f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ		}
1653bdd4dddee325a7dce3e84cf48201a06aa8508aa4Jeff Garzik		have_err_bits = ((PORT0_ERR << shift) & relevant);
1654bdd4dddee325a7dce3e84cf48201a06aa8508aa4Jeff Garzik
1655bdd4dddee325a7dce3e84cf48201a06aa8508aa4Jeff Garzik		if (unlikely(have_err_bits)) {
1656bdd4dddee325a7dce3e84cf48201a06aa8508aa4Jeff Garzik			struct ata_queued_cmd *qc;
16578b260248d9e0e8b64bb72fd4dee03ad86984c344Jeff Garzik
16589af5c9c97dc9d599281778864c72b385f0c63341Tejun Heo			qc = ata_qc_from_tag(ap, ap->link.active_tag);
1659bdd4dddee325a7dce3e84cf48201a06aa8508aa4Jeff Garzik			if (qc && (qc->tf.flags & ATA_TFLAG_POLLING))
1660bdd4dddee325a7dce3e84cf48201a06aa8508aa4Jeff Garzik				continue;
1661bdd4dddee325a7dce3e84cf48201a06aa8508aa4Jeff Garzik
1662bdd4dddee325a7dce3e84cf48201a06aa8508aa4Jeff Garzik			mv_err_intr(ap, qc);
1663bdd4dddee325a7dce3e84cf48201a06aa8508aa4Jeff Garzik			continue;
1664bdd4dddee325a7dce3e84cf48201a06aa8508aa4Jeff Garzik		}
1665bdd4dddee325a7dce3e84cf48201a06aa8508aa4Jeff Garzik
1666bdd4dddee325a7dce3e84cf48201a06aa8508aa4Jeff Garzik		hard_port = mv_hardport_from_port(port); /* range 0..3 */
1667bdd4dddee325a7dce3e84cf48201a06aa8508aa4Jeff Garzik
1668bdd4dddee325a7dce3e84cf48201a06aa8508aa4Jeff Garzik		if (pp->pp_flags & MV_PP_FLAG_EDMA_EN) {
1669bdd4dddee325a7dce3e84cf48201a06aa8508aa4Jeff Garzik			if ((CRPB_DMA_DONE << hard_port) & hc_irq_cause)
1670bdd4dddee325a7dce3e84cf48201a06aa8508aa4Jeff Garzik				mv_intr_edma(ap);
1671bdd4dddee325a7dce3e84cf48201a06aa8508aa4Jeff Garzik		} else {
1672bdd4dddee325a7dce3e84cf48201a06aa8508aa4Jeff Garzik			if ((DEV_IRQ << hard_port) & hc_irq_cause)
1673bdd4dddee325a7dce3e84cf48201a06aa8508aa4Jeff Garzik				mv_intr_pio(ap);
167420f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ		}
167520f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ	}
167620f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ	VPRINTK("EXIT\n");
167720f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ}
167820f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ
1679bdd4dddee325a7dce3e84cf48201a06aa8508aa4Jeff Garzikstatic void mv_pci_error(struct ata_host *host, void __iomem *mmio)
1680bdd4dddee325a7dce3e84cf48201a06aa8508aa4Jeff Garzik{
168102a121da5a53d415b6596bc19cc6999d295d32a4Mark Lord	struct mv_host_priv *hpriv = host->private_data;
1682bdd4dddee325a7dce3e84cf48201a06aa8508aa4Jeff Garzik	struct ata_port *ap;
1683bdd4dddee325a7dce3e84cf48201a06aa8508aa4Jeff Garzik	struct ata_queued_cmd *qc;
1684bdd4dddee325a7dce3e84cf48201a06aa8508aa4Jeff Garzik	struct ata_eh_info *ehi;
1685bdd4dddee325a7dce3e84cf48201a06aa8508aa4Jeff Garzik	unsigned int i, err_mask, printed = 0;
1686bdd4dddee325a7dce3e84cf48201a06aa8508aa4Jeff Garzik	u32 err_cause;
1687bdd4dddee325a7dce3e84cf48201a06aa8508aa4Jeff Garzik
168802a121da5a53d415b6596bc19cc6999d295d32a4Mark Lord	err_cause = readl(mmio + hpriv->irq_cause_ofs);
1689bdd4dddee325a7dce3e84cf48201a06aa8508aa4Jeff Garzik
1690bdd4dddee325a7dce3e84cf48201a06aa8508aa4Jeff Garzik	dev_printk(KERN_ERR, host->dev, "PCI ERROR; PCI IRQ cause=0x%08x\n",
1691bdd4dddee325a7dce3e84cf48201a06aa8508aa4Jeff Garzik		   err_cause);
1692bdd4dddee325a7dce3e84cf48201a06aa8508aa4Jeff Garzik
1693bdd4dddee325a7dce3e84cf48201a06aa8508aa4Jeff Garzik	DPRINTK("All regs @ PCI error\n");
1694bdd4dddee325a7dce3e84cf48201a06aa8508aa4Jeff Garzik	mv_dump_all_regs(mmio, -1, to_pci_dev(host->dev));
1695bdd4dddee325a7dce3e84cf48201a06aa8508aa4Jeff Garzik
169602a121da5a53d415b6596bc19cc6999d295d32a4Mark Lord	writelfl(0, mmio + hpriv->irq_cause_ofs);
1697bdd4dddee325a7dce3e84cf48201a06aa8508aa4Jeff Garzik
1698bdd4dddee325a7dce3e84cf48201a06aa8508aa4Jeff Garzik	for (i = 0; i < host->n_ports; i++) {
1699bdd4dddee325a7dce3e84cf48201a06aa8508aa4Jeff Garzik		ap = host->ports[i];
1700936fd7328657884d5a69a55666c74a55aa83ca27Tejun Heo		if (!ata_link_offline(&ap->link)) {
17019af5c9c97dc9d599281778864c72b385f0c63341Tejun Heo			ehi = &ap->link.eh_info;
1702bdd4dddee325a7dce3e84cf48201a06aa8508aa4Jeff Garzik			ata_ehi_clear_desc(ehi);
1703bdd4dddee325a7dce3e84cf48201a06aa8508aa4Jeff Garzik			if (!printed++)
1704bdd4dddee325a7dce3e84cf48201a06aa8508aa4Jeff Garzik				ata_ehi_push_desc(ehi,
1705bdd4dddee325a7dce3e84cf48201a06aa8508aa4Jeff Garzik					"PCI err cause 0x%08x", err_cause);
1706bdd4dddee325a7dce3e84cf48201a06aa8508aa4Jeff Garzik			err_mask = AC_ERR_HOST_BUS;
1707bdd4dddee325a7dce3e84cf48201a06aa8508aa4Jeff Garzik			ehi->action = ATA_EH_HARDRESET;
17089af5c9c97dc9d599281778864c72b385f0c63341Tejun Heo			qc = ata_qc_from_tag(ap, ap->link.active_tag);
1709bdd4dddee325a7dce3e84cf48201a06aa8508aa4Jeff Garzik			if (qc)
1710bdd4dddee325a7dce3e84cf48201a06aa8508aa4Jeff Garzik				qc->err_mask |= err_mask;
1711bdd4dddee325a7dce3e84cf48201a06aa8508aa4Jeff Garzik			else
1712bdd4dddee325a7dce3e84cf48201a06aa8508aa4Jeff Garzik				ehi->err_mask |= err_mask;
1713bdd4dddee325a7dce3e84cf48201a06aa8508aa4Jeff Garzik
1714bdd4dddee325a7dce3e84cf48201a06aa8508aa4Jeff Garzik			ata_port_freeze(ap);
1715bdd4dddee325a7dce3e84cf48201a06aa8508aa4Jeff Garzik		}
1716bdd4dddee325a7dce3e84cf48201a06aa8508aa4Jeff Garzik	}
1717bdd4dddee325a7dce3e84cf48201a06aa8508aa4Jeff Garzik}
1718bdd4dddee325a7dce3e84cf48201a06aa8508aa4Jeff Garzik
171905b308e1df6d9d673daedb517969241f41278b52Brett Russ/**
1720c5d3e45a2200a0905dc45b72714726b7aac3aaf1Jeff Garzik *      mv_interrupt - Main interrupt event handler
172105b308e1df6d9d673daedb517969241f41278b52Brett Russ *      @irq: unused
172205b308e1df6d9d673daedb517969241f41278b52Brett Russ *      @dev_instance: private data; in this case the host structure
172305b308e1df6d9d673daedb517969241f41278b52Brett Russ *
172405b308e1df6d9d673daedb517969241f41278b52Brett Russ *      Read the read only register to determine if any host
172505b308e1df6d9d673daedb517969241f41278b52Brett Russ *      controllers have pending interrupts.  If so, call lower level
172605b308e1df6d9d673daedb517969241f41278b52Brett Russ *      routine to handle.  Also check for PCI errors which are only
172705b308e1df6d9d673daedb517969241f41278b52Brett Russ *      reported here.
172805b308e1df6d9d673daedb517969241f41278b52Brett Russ *
17298b260248d9e0e8b64bb72fd4dee03ad86984c344Jeff Garzik *      LOCKING:
1730cca3974e48607c3775dc73b544a5700b2e37c21aJeff Garzik *      This routine holds the host lock while processing pending
173105b308e1df6d9d673daedb517969241f41278b52Brett Russ *      interrupts.
173205b308e1df6d9d673daedb517969241f41278b52Brett Russ */
17337d12e780e003f93433d49ce78cfedf4b4c52adc5David Howellsstatic irqreturn_t mv_interrupt(int irq, void *dev_instance)
173420f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ{
1735cca3974e48607c3775dc73b544a5700b2e37c21aJeff Garzik	struct ata_host *host = dev_instance;
173620f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ	unsigned int hc, handled = 0, n_hcs;
17370d5ff566779f894ca9937231a181eb31e4adff0eTejun Heo	void __iomem *mmio = host->iomap[MV_PRIMARY_BAR];
1738646a4da514f2555298481cb00dc5b3eb02b21b72Mark Lord	u32 irq_stat, irq_mask;
173920f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ
1740646a4da514f2555298481cb00dc5b3eb02b21b72Mark Lord	spin_lock(&host->lock);
174120f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ	irq_stat = readl(mmio + HC_MAIN_IRQ_CAUSE_OFS);
1742646a4da514f2555298481cb00dc5b3eb02b21b72Mark Lord	irq_mask = readl(mmio + HC_MAIN_IRQ_MASK_OFS);
174320f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ
174420f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ	/* check the cases where we either have nothing pending or have read
174520f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ	 * a bogus register value which can indicate HW removal or PCI fault
174620f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ	 */
1747646a4da514f2555298481cb00dc5b3eb02b21b72Mark Lord	if (!(irq_stat & irq_mask) || (0xffffffffU == irq_stat))
1748646a4da514f2555298481cb00dc5b3eb02b21b72Mark Lord		goto out_unlock;
174920f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ
1750cca3974e48607c3775dc73b544a5700b2e37c21aJeff Garzik	n_hcs = mv_get_hc_count(host->ports[0]->flags);
175120f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ
1752bdd4dddee325a7dce3e84cf48201a06aa8508aa4Jeff Garzik	if (unlikely(irq_stat & PCI_ERR)) {
1753bdd4dddee325a7dce3e84cf48201a06aa8508aa4Jeff Garzik		mv_pci_error(host, mmio);
1754bdd4dddee325a7dce3e84cf48201a06aa8508aa4Jeff Garzik		handled = 1;
1755bdd4dddee325a7dce3e84cf48201a06aa8508aa4Jeff Garzik		goto out_unlock;	/* skip all other HC irq handling */
1756bdd4dddee325a7dce3e84cf48201a06aa8508aa4Jeff Garzik	}
1757bdd4dddee325a7dce3e84cf48201a06aa8508aa4Jeff Garzik
175820f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ	for (hc = 0; hc < n_hcs; hc++) {
175920f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ		u32 relevant = irq_stat & (HC0_IRQ_PEND << (hc * HC_SHIFT));
176020f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ		if (relevant) {
1761cca3974e48607c3775dc73b544a5700b2e37c21aJeff Garzik			mv_host_intr(host, relevant, hc);
1762bdd4dddee325a7dce3e84cf48201a06aa8508aa4Jeff Garzik			handled = 1;
176320f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ		}
176420f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ	}
1765615ab95342f6245026d8974b9724f7ea57d9a184Mark Lord
1766bdd4dddee325a7dce3e84cf48201a06aa8508aa4Jeff Garzikout_unlock:
1767cca3974e48607c3775dc73b544a5700b2e37c21aJeff Garzik	spin_unlock(&host->lock);
176820f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ
176920f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ	return IRQ_RETVAL(handled);
177020f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ}
177120f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ
1772c9d39130123238ac18478a42e25cb7996eacfcc0Jeff Garzikstatic void __iomem *mv5_phy_base(void __iomem *mmio, unsigned int port)
1773c9d39130123238ac18478a42e25cb7996eacfcc0Jeff Garzik{
1774c9d39130123238ac18478a42e25cb7996eacfcc0Jeff Garzik	void __iomem *hc_mmio = mv_hc_base_from_port(mmio, port);
1775c9d39130123238ac18478a42e25cb7996eacfcc0Jeff Garzik	unsigned long ofs = (mv_hardport_from_port(port) + 1) * 0x100UL;
1776c9d39130123238ac18478a42e25cb7996eacfcc0Jeff Garzik
1777c9d39130123238ac18478a42e25cb7996eacfcc0Jeff Garzik	return hc_mmio + ofs;
1778c9d39130123238ac18478a42e25cb7996eacfcc0Jeff Garzik}
1779c9d39130123238ac18478a42e25cb7996eacfcc0Jeff Garzik
1780c9d39130123238ac18478a42e25cb7996eacfcc0Jeff Garzikstatic unsigned int mv5_scr_offset(unsigned int sc_reg_in)
1781c9d39130123238ac18478a42e25cb7996eacfcc0Jeff Garzik{
1782c9d39130123238ac18478a42e25cb7996eacfcc0Jeff Garzik	unsigned int ofs;
1783c9d39130123238ac18478a42e25cb7996eacfcc0Jeff Garzik
1784c9d39130123238ac18478a42e25cb7996eacfcc0Jeff Garzik	switch (sc_reg_in) {
1785c9d39130123238ac18478a42e25cb7996eacfcc0Jeff Garzik	case SCR_STATUS:
1786c9d39130123238ac18478a42e25cb7996eacfcc0Jeff Garzik	case SCR_ERROR:
1787c9d39130123238ac18478a42e25cb7996eacfcc0Jeff Garzik	case SCR_CONTROL:
1788c9d39130123238ac18478a42e25cb7996eacfcc0Jeff Garzik		ofs = sc_reg_in * sizeof(u32);
1789c9d39130123238ac18478a42e25cb7996eacfcc0Jeff Garzik		break;
1790c9d39130123238ac18478a42e25cb7996eacfcc0Jeff Garzik	default:
1791c9d39130123238ac18478a42e25cb7996eacfcc0Jeff Garzik		ofs = 0xffffffffU;
1792c9d39130123238ac18478a42e25cb7996eacfcc0Jeff Garzik		break;
1793c9d39130123238ac18478a42e25cb7996eacfcc0Jeff Garzik	}
1794c9d39130123238ac18478a42e25cb7996eacfcc0Jeff Garzik	return ofs;
1795c9d39130123238ac18478a42e25cb7996eacfcc0Jeff Garzik}
1796c9d39130123238ac18478a42e25cb7996eacfcc0Jeff Garzik
1797da3dbb17a0e9a9ec7f5aed95f1fddadb790edc9dTejun Heostatic int mv5_scr_read(struct ata_port *ap, unsigned int sc_reg_in, u32 *val)
1798c9d39130123238ac18478a42e25cb7996eacfcc0Jeff Garzik{
17990d5ff566779f894ca9937231a181eb31e4adff0eTejun Heo	void __iomem *mmio = ap->host->iomap[MV_PRIMARY_BAR];
18000d5ff566779f894ca9937231a181eb31e4adff0eTejun Heo	void __iomem *addr = mv5_phy_base(mmio, ap->port_no);
1801c9d39130123238ac18478a42e25cb7996eacfcc0Jeff Garzik	unsigned int ofs = mv5_scr_offset(sc_reg_in);
1802c9d39130123238ac18478a42e25cb7996eacfcc0Jeff Garzik
1803da3dbb17a0e9a9ec7f5aed95f1fddadb790edc9dTejun Heo	if (ofs != 0xffffffffU) {
1804da3dbb17a0e9a9ec7f5aed95f1fddadb790edc9dTejun Heo		*val = readl(addr + ofs);
1805da3dbb17a0e9a9ec7f5aed95f1fddadb790edc9dTejun Heo		return 0;
1806da3dbb17a0e9a9ec7f5aed95f1fddadb790edc9dTejun Heo	} else
1807da3dbb17a0e9a9ec7f5aed95f1fddadb790edc9dTejun Heo		return -EINVAL;
1808c9d39130123238ac18478a42e25cb7996eacfcc0Jeff Garzik}
1809c9d39130123238ac18478a42e25cb7996eacfcc0Jeff Garzik
1810da3dbb17a0e9a9ec7f5aed95f1fddadb790edc9dTejun Heostatic int mv5_scr_write(struct ata_port *ap, unsigned int sc_reg_in, u32 val)
1811c9d39130123238ac18478a42e25cb7996eacfcc0Jeff Garzik{
18120d5ff566779f894ca9937231a181eb31e4adff0eTejun Heo	void __iomem *mmio = ap->host->iomap[MV_PRIMARY_BAR];
18130d5ff566779f894ca9937231a181eb31e4adff0eTejun Heo	void __iomem *addr = mv5_phy_base(mmio, ap->port_no);
1814c9d39130123238ac18478a42e25cb7996eacfcc0Jeff Garzik	unsigned int ofs = mv5_scr_offset(sc_reg_in);
1815c9d39130123238ac18478a42e25cb7996eacfcc0Jeff Garzik
1816da3dbb17a0e9a9ec7f5aed95f1fddadb790edc9dTejun Heo	if (ofs != 0xffffffffU) {
18170d5ff566779f894ca9937231a181eb31e4adff0eTejun Heo		writelfl(val, addr + ofs);
1818da3dbb17a0e9a9ec7f5aed95f1fddadb790edc9dTejun Heo		return 0;
1819da3dbb17a0e9a9ec7f5aed95f1fddadb790edc9dTejun Heo	} else
1820da3dbb17a0e9a9ec7f5aed95f1fddadb790edc9dTejun Heo		return -EINVAL;
1821c9d39130123238ac18478a42e25cb7996eacfcc0Jeff Garzik}
1822c9d39130123238ac18478a42e25cb7996eacfcc0Jeff Garzik
1823522479fb98c6667f081e75f87e298e413c0b1db8Jeff Garzikstatic void mv5_reset_bus(struct pci_dev *pdev, void __iomem *mmio)
1824522479fb98c6667f081e75f87e298e413c0b1db8Jeff Garzik{
1825522479fb98c6667f081e75f87e298e413c0b1db8Jeff Garzik	int early_5080;
1826522479fb98c6667f081e75f87e298e413c0b1db8Jeff Garzik
182744c10138fd4bbc4b6d6bff0873c24902f2a9da65Auke Kok	early_5080 = (pdev->device == 0x5080) && (pdev->revision == 0);
1828522479fb98c6667f081e75f87e298e413c0b1db8Jeff Garzik
1829522479fb98c6667f081e75f87e298e413c0b1db8Jeff Garzik	if (!early_5080) {
1830522479fb98c6667f081e75f87e298e413c0b1db8Jeff Garzik		u32 tmp = readl(mmio + MV_PCI_EXP_ROM_BAR_CTL);
1831522479fb98c6667f081e75f87e298e413c0b1db8Jeff Garzik		tmp |= (1 << 0);
1832522479fb98c6667f081e75f87e298e413c0b1db8Jeff Garzik		writel(tmp, mmio + MV_PCI_EXP_ROM_BAR_CTL);
1833522479fb98c6667f081e75f87e298e413c0b1db8Jeff Garzik	}
1834522479fb98c6667f081e75f87e298e413c0b1db8Jeff Garzik
1835522479fb98c6667f081e75f87e298e413c0b1db8Jeff Garzik	mv_reset_pci_bus(pdev, mmio);
1836522479fb98c6667f081e75f87e298e413c0b1db8Jeff Garzik}
1837522479fb98c6667f081e75f87e298e413c0b1db8Jeff Garzik
1838522479fb98c6667f081e75f87e298e413c0b1db8Jeff Garzikstatic void mv5_reset_flash(struct mv_host_priv *hpriv, void __iomem *mmio)
1839522479fb98c6667f081e75f87e298e413c0b1db8Jeff Garzik{
1840522479fb98c6667f081e75f87e298e413c0b1db8Jeff Garzik	writel(0x0fcfffff, mmio + MV_FLASH_CTL);
1841522479fb98c6667f081e75f87e298e413c0b1db8Jeff Garzik}
1842522479fb98c6667f081e75f87e298e413c0b1db8Jeff Garzik
184347c2b677daeed9c79ecb7167c211ff36876ea611Jeff Garzikstatic void mv5_read_preamp(struct mv_host_priv *hpriv, int idx,
1844ba3fe8fb6a469390a14379519915f3c39a973d99Jeff Garzik			   void __iomem *mmio)
1845ba3fe8fb6a469390a14379519915f3c39a973d99Jeff Garzik{
1846c9d39130123238ac18478a42e25cb7996eacfcc0Jeff Garzik	void __iomem *phy_mmio = mv5_phy_base(mmio, idx);
1847c9d39130123238ac18478a42e25cb7996eacfcc0Jeff Garzik	u32 tmp;
1848c9d39130123238ac18478a42e25cb7996eacfcc0Jeff Garzik
1849c9d39130123238ac18478a42e25cb7996eacfcc0Jeff Garzik	tmp = readl(phy_mmio + MV5_PHY_MODE);
1850c9d39130123238ac18478a42e25cb7996eacfcc0Jeff Garzik
1851c9d39130123238ac18478a42e25cb7996eacfcc0Jeff Garzik	hpriv->signal[idx].pre = tmp & 0x1800;	/* bits 12:11 */
1852c9d39130123238ac18478a42e25cb7996eacfcc0Jeff Garzik	hpriv->signal[idx].amps = tmp & 0xe0;	/* bits 7:5 */
1853ba3fe8fb6a469390a14379519915f3c39a973d99Jeff Garzik}
1854ba3fe8fb6a469390a14379519915f3c39a973d99Jeff Garzik
185547c2b677daeed9c79ecb7167c211ff36876ea611Jeff Garzikstatic void mv5_enable_leds(struct mv_host_priv *hpriv, void __iomem *mmio)
1856ba3fe8fb6a469390a14379519915f3c39a973d99Jeff Garzik{
1857522479fb98c6667f081e75f87e298e413c0b1db8Jeff Garzik	u32 tmp;
1858522479fb98c6667f081e75f87e298e413c0b1db8Jeff Garzik
1859522479fb98c6667f081e75f87e298e413c0b1db8Jeff Garzik	writel(0, mmio + MV_GPIO_PORT_CTL);
1860522479fb98c6667f081e75f87e298e413c0b1db8Jeff Garzik
1861522479fb98c6667f081e75f87e298e413c0b1db8Jeff Garzik	/* FIXME: handle MV_HP_ERRATA_50XXB2 errata */
1862522479fb98c6667f081e75f87e298e413c0b1db8Jeff Garzik
1863522479fb98c6667f081e75f87e298e413c0b1db8Jeff Garzik	tmp = readl(mmio + MV_PCI_EXP_ROM_BAR_CTL);
1864522479fb98c6667f081e75f87e298e413c0b1db8Jeff Garzik	tmp |= ~(1 << 0);
1865522479fb98c6667f081e75f87e298e413c0b1db8Jeff Garzik	writel(tmp, mmio + MV_PCI_EXP_ROM_BAR_CTL);
1866ba3fe8fb6a469390a14379519915f3c39a973d99Jeff Garzik}
1867ba3fe8fb6a469390a14379519915f3c39a973d99Jeff Garzik
18682a47ce06d534692f9bd2bf4e90a20fc9b1054c39Jeff Garzikstatic void mv5_phy_errata(struct mv_host_priv *hpriv, void __iomem *mmio,
18692a47ce06d534692f9bd2bf4e90a20fc9b1054c39Jeff Garzik			   unsigned int port)
1870bca1c4eb9411533d613123618c0d127fae532595Jeff Garzik{
1871c9d39130123238ac18478a42e25cb7996eacfcc0Jeff Garzik	void __iomem *phy_mmio = mv5_phy_base(mmio, port);
1872c9d39130123238ac18478a42e25cb7996eacfcc0Jeff Garzik	const u32 mask = (1<<12) | (1<<11) | (1<<7) | (1<<6) | (1<<5);
1873c9d39130123238ac18478a42e25cb7996eacfcc0Jeff Garzik	u32 tmp;
1874c9d39130123238ac18478a42e25cb7996eacfcc0Jeff Garzik	int fix_apm_sq = (hpriv->hp_flags & MV_HP_ERRATA_50XXB0);
1875c9d39130123238ac18478a42e25cb7996eacfcc0Jeff Garzik
1876c9d39130123238ac18478a42e25cb7996eacfcc0Jeff Garzik	if (fix_apm_sq) {
1877c9d39130123238ac18478a42e25cb7996eacfcc0Jeff Garzik		tmp = readl(phy_mmio + MV5_LT_MODE);
1878c9d39130123238ac18478a42e25cb7996eacfcc0Jeff Garzik		tmp |= (1 << 19);
1879c9d39130123238ac18478a42e25cb7996eacfcc0Jeff Garzik		writel(tmp, phy_mmio + MV5_LT_MODE);
1880c9d39130123238ac18478a42e25cb7996eacfcc0Jeff Garzik
1881c9d39130123238ac18478a42e25cb7996eacfcc0Jeff Garzik		tmp = readl(phy_mmio + MV5_PHY_CTL);
1882c9d39130123238ac18478a42e25cb7996eacfcc0Jeff Garzik		tmp &= ~0x3;
1883c9d39130123238ac18478a42e25cb7996eacfcc0Jeff Garzik		tmp |= 0x1;
1884c9d39130123238ac18478a42e25cb7996eacfcc0Jeff Garzik		writel(tmp, phy_mmio + MV5_PHY_CTL);
1885c9d39130123238ac18478a42e25cb7996eacfcc0Jeff Garzik	}
1886c9d39130123238ac18478a42e25cb7996eacfcc0Jeff Garzik
1887c9d39130123238ac18478a42e25cb7996eacfcc0Jeff Garzik	tmp = readl(phy_mmio + MV5_PHY_MODE);
1888c9d39130123238ac18478a42e25cb7996eacfcc0Jeff Garzik	tmp &= ~mask;
1889c9d39130123238ac18478a42e25cb7996eacfcc0Jeff Garzik	tmp |= hpriv->signal[port].pre;
1890c9d39130123238ac18478a42e25cb7996eacfcc0Jeff Garzik	tmp |= hpriv->signal[port].amps;
1891c9d39130123238ac18478a42e25cb7996eacfcc0Jeff Garzik	writel(tmp, phy_mmio + MV5_PHY_MODE);
1892bca1c4eb9411533d613123618c0d127fae532595Jeff Garzik}
1893bca1c4eb9411533d613123618c0d127fae532595Jeff Garzik
1894c9d39130123238ac18478a42e25cb7996eacfcc0Jeff Garzik
1895c9d39130123238ac18478a42e25cb7996eacfcc0Jeff Garzik#undef ZERO
1896c9d39130123238ac18478a42e25cb7996eacfcc0Jeff Garzik#define ZERO(reg) writel(0, port_mmio + (reg))
1897c9d39130123238ac18478a42e25cb7996eacfcc0Jeff Garzikstatic void mv5_reset_hc_port(struct mv_host_priv *hpriv, void __iomem *mmio,
1898c9d39130123238ac18478a42e25cb7996eacfcc0Jeff Garzik			     unsigned int port)
1899c9d39130123238ac18478a42e25cb7996eacfcc0Jeff Garzik{
1900c9d39130123238ac18478a42e25cb7996eacfcc0Jeff Garzik	void __iomem *port_mmio = mv_port_base(mmio, port);
1901c9d39130123238ac18478a42e25cb7996eacfcc0Jeff Garzik
1902c9d39130123238ac18478a42e25cb7996eacfcc0Jeff Garzik	writelfl(EDMA_DS, port_mmio + EDMA_CMD_OFS);
1903c9d39130123238ac18478a42e25cb7996eacfcc0Jeff Garzik
1904c9d39130123238ac18478a42e25cb7996eacfcc0Jeff Garzik	mv_channel_reset(hpriv, mmio, port);
1905c9d39130123238ac18478a42e25cb7996eacfcc0Jeff Garzik
1906c9d39130123238ac18478a42e25cb7996eacfcc0Jeff Garzik	ZERO(0x028);	/* command */
1907c9d39130123238ac18478a42e25cb7996eacfcc0Jeff Garzik	writel(0x11f, port_mmio + EDMA_CFG_OFS);
1908c9d39130123238ac18478a42e25cb7996eacfcc0Jeff Garzik	ZERO(0x004);	/* timer */
1909c9d39130123238ac18478a42e25cb7996eacfcc0Jeff Garzik	ZERO(0x008);	/* irq err cause */
1910c9d39130123238ac18478a42e25cb7996eacfcc0Jeff Garzik	ZERO(0x00c);	/* irq err mask */
1911c9d39130123238ac18478a42e25cb7996eacfcc0Jeff Garzik	ZERO(0x010);	/* rq bah */
1912c9d39130123238ac18478a42e25cb7996eacfcc0Jeff Garzik	ZERO(0x014);	/* rq inp */
1913c9d39130123238ac18478a42e25cb7996eacfcc0Jeff Garzik	ZERO(0x018);	/* rq outp */
1914c9d39130123238ac18478a42e25cb7996eacfcc0Jeff Garzik	ZERO(0x01c);	/* respq bah */
1915c9d39130123238ac18478a42e25cb7996eacfcc0Jeff Garzik	ZERO(0x024);	/* respq outp */
1916c9d39130123238ac18478a42e25cb7996eacfcc0Jeff Garzik	ZERO(0x020);	/* respq inp */
1917c9d39130123238ac18478a42e25cb7996eacfcc0Jeff Garzik	ZERO(0x02c);	/* test control */
1918c9d39130123238ac18478a42e25cb7996eacfcc0Jeff Garzik	writel(0xbc, port_mmio + EDMA_IORDY_TMOUT);
1919c9d39130123238ac18478a42e25cb7996eacfcc0Jeff Garzik}
1920c9d39130123238ac18478a42e25cb7996eacfcc0Jeff Garzik#undef ZERO
1921c9d39130123238ac18478a42e25cb7996eacfcc0Jeff Garzik
1922c9d39130123238ac18478a42e25cb7996eacfcc0Jeff Garzik#define ZERO(reg) writel(0, hc_mmio + (reg))
1923c9d39130123238ac18478a42e25cb7996eacfcc0Jeff Garzikstatic void mv5_reset_one_hc(struct mv_host_priv *hpriv, void __iomem *mmio,
1924c9d39130123238ac18478a42e25cb7996eacfcc0Jeff Garzik			unsigned int hc)
192547c2b677daeed9c79ecb7167c211ff36876ea611Jeff Garzik{
1926c9d39130123238ac18478a42e25cb7996eacfcc0Jeff Garzik	void __iomem *hc_mmio = mv_hc_base(mmio, hc);
1927c9d39130123238ac18478a42e25cb7996eacfcc0Jeff Garzik	u32 tmp;
1928c9d39130123238ac18478a42e25cb7996eacfcc0Jeff Garzik
1929c9d39130123238ac18478a42e25cb7996eacfcc0Jeff Garzik	ZERO(0x00c);
1930c9d39130123238ac18478a42e25cb7996eacfcc0Jeff Garzik	ZERO(0x010);
1931c9d39130123238ac18478a42e25cb7996eacfcc0Jeff Garzik	ZERO(0x014);
1932c9d39130123238ac18478a42e25cb7996eacfcc0Jeff Garzik	ZERO(0x018);
1933c9d39130123238ac18478a42e25cb7996eacfcc0Jeff Garzik
1934c9d39130123238ac18478a42e25cb7996eacfcc0Jeff Garzik	tmp = readl(hc_mmio + 0x20);
1935c9d39130123238ac18478a42e25cb7996eacfcc0Jeff Garzik	tmp &= 0x1c1c1c1c;
1936c9d39130123238ac18478a42e25cb7996eacfcc0Jeff Garzik	tmp |= 0x03030303;
1937c9d39130123238ac18478a42e25cb7996eacfcc0Jeff Garzik	writel(tmp, hc_mmio + 0x20);
1938c9d39130123238ac18478a42e25cb7996eacfcc0Jeff Garzik}
1939c9d39130123238ac18478a42e25cb7996eacfcc0Jeff Garzik#undef ZERO
1940c9d39130123238ac18478a42e25cb7996eacfcc0Jeff Garzik
1941c9d39130123238ac18478a42e25cb7996eacfcc0Jeff Garzikstatic int mv5_reset_hc(struct mv_host_priv *hpriv, void __iomem *mmio,
1942c9d39130123238ac18478a42e25cb7996eacfcc0Jeff Garzik			unsigned int n_hc)
1943c9d39130123238ac18478a42e25cb7996eacfcc0Jeff Garzik{
1944c9d39130123238ac18478a42e25cb7996eacfcc0Jeff Garzik	unsigned int hc, port;
1945c9d39130123238ac18478a42e25cb7996eacfcc0Jeff Garzik
1946c9d39130123238ac18478a42e25cb7996eacfcc0Jeff Garzik	for (hc = 0; hc < n_hc; hc++) {
1947c9d39130123238ac18478a42e25cb7996eacfcc0Jeff Garzik		for (port = 0; port < MV_PORTS_PER_HC; port++)
1948c9d39130123238ac18478a42e25cb7996eacfcc0Jeff Garzik			mv5_reset_hc_port(hpriv, mmio,
1949c9d39130123238ac18478a42e25cb7996eacfcc0Jeff Garzik					  (hc * MV_PORTS_PER_HC) + port);
1950c9d39130123238ac18478a42e25cb7996eacfcc0Jeff Garzik
1951c9d39130123238ac18478a42e25cb7996eacfcc0Jeff Garzik		mv5_reset_one_hc(hpriv, mmio, hc);
1952c9d39130123238ac18478a42e25cb7996eacfcc0Jeff Garzik	}
1953c9d39130123238ac18478a42e25cb7996eacfcc0Jeff Garzik
1954c9d39130123238ac18478a42e25cb7996eacfcc0Jeff Garzik	return 0;
195547c2b677daeed9c79ecb7167c211ff36876ea611Jeff Garzik}
195647c2b677daeed9c79ecb7167c211ff36876ea611Jeff Garzik
1957101ffae26c23ea928fce6d31a8b4901327d91a15Jeff Garzik#undef ZERO
1958101ffae26c23ea928fce6d31a8b4901327d91a15Jeff Garzik#define ZERO(reg) writel(0, mmio + (reg))
1959101ffae26c23ea928fce6d31a8b4901327d91a15Jeff Garzikstatic void mv_reset_pci_bus(struct pci_dev *pdev, void __iomem *mmio)
1960101ffae26c23ea928fce6d31a8b4901327d91a15Jeff Garzik{
196102a121da5a53d415b6596bc19cc6999d295d32a4Mark Lord	struct ata_host     *host = dev_get_drvdata(&pdev->dev);
196202a121da5a53d415b6596bc19cc6999d295d32a4Mark Lord	struct mv_host_priv *hpriv = host->private_data;
1963101ffae26c23ea928fce6d31a8b4901327d91a15Jeff Garzik	u32 tmp;
1964101ffae26c23ea928fce6d31a8b4901327d91a15Jeff Garzik
1965101ffae26c23ea928fce6d31a8b4901327d91a15Jeff Garzik	tmp = readl(mmio + MV_PCI_MODE);
1966101ffae26c23ea928fce6d31a8b4901327d91a15Jeff Garzik	tmp &= 0xff00ffff;
1967101ffae26c23ea928fce6d31a8b4901327d91a15Jeff Garzik	writel(tmp, mmio + MV_PCI_MODE);
1968101ffae26c23ea928fce6d31a8b4901327d91a15Jeff Garzik
1969101ffae26c23ea928fce6d31a8b4901327d91a15Jeff Garzik	ZERO(MV_PCI_DISC_TIMER);
1970101ffae26c23ea928fce6d31a8b4901327d91a15Jeff Garzik	ZERO(MV_PCI_MSI_TRIGGER);
1971101ffae26c23ea928fce6d31a8b4901327d91a15Jeff Garzik	writel(0x000100ff, mmio + MV_PCI_XBAR_TMOUT);
1972101ffae26c23ea928fce6d31a8b4901327d91a15Jeff Garzik	ZERO(HC_MAIN_IRQ_MASK_OFS);
1973101ffae26c23ea928fce6d31a8b4901327d91a15Jeff Garzik	ZERO(MV_PCI_SERR_MASK);
197402a121da5a53d415b6596bc19cc6999d295d32a4Mark Lord	ZERO(hpriv->irq_cause_ofs);
197502a121da5a53d415b6596bc19cc6999d295d32a4Mark Lord	ZERO(hpriv->irq_mask_ofs);
1976101ffae26c23ea928fce6d31a8b4901327d91a15Jeff Garzik	ZERO(MV_PCI_ERR_LOW_ADDRESS);
1977101ffae26c23ea928fce6d31a8b4901327d91a15Jeff Garzik	ZERO(MV_PCI_ERR_HIGH_ADDRESS);
1978101ffae26c23ea928fce6d31a8b4901327d91a15Jeff Garzik	ZERO(MV_PCI_ERR_ATTRIBUTE);
1979101ffae26c23ea928fce6d31a8b4901327d91a15Jeff Garzik	ZERO(MV_PCI_ERR_COMMAND);
1980101ffae26c23ea928fce6d31a8b4901327d91a15Jeff Garzik}
1981101ffae26c23ea928fce6d31a8b4901327d91a15Jeff Garzik#undef ZERO
1982101ffae26c23ea928fce6d31a8b4901327d91a15Jeff Garzik
1983101ffae26c23ea928fce6d31a8b4901327d91a15Jeff Garzikstatic void mv6_reset_flash(struct mv_host_priv *hpriv, void __iomem *mmio)
1984101ffae26c23ea928fce6d31a8b4901327d91a15Jeff Garzik{
1985101ffae26c23ea928fce6d31a8b4901327d91a15Jeff Garzik	u32 tmp;
1986101ffae26c23ea928fce6d31a8b4901327d91a15Jeff Garzik
1987101ffae26c23ea928fce6d31a8b4901327d91a15Jeff Garzik	mv5_reset_flash(hpriv, mmio);
1988101ffae26c23ea928fce6d31a8b4901327d91a15Jeff Garzik
1989101ffae26c23ea928fce6d31a8b4901327d91a15Jeff Garzik	tmp = readl(mmio + MV_GPIO_PORT_CTL);
1990101ffae26c23ea928fce6d31a8b4901327d91a15Jeff Garzik	tmp &= 0x3;
1991101ffae26c23ea928fce6d31a8b4901327d91a15Jeff Garzik	tmp |= (1 << 5) | (1 << 6);
1992101ffae26c23ea928fce6d31a8b4901327d91a15Jeff Garzik	writel(tmp, mmio + MV_GPIO_PORT_CTL);
1993101ffae26c23ea928fce6d31a8b4901327d91a15Jeff Garzik}
1994101ffae26c23ea928fce6d31a8b4901327d91a15Jeff Garzik
1995101ffae26c23ea928fce6d31a8b4901327d91a15Jeff Garzik/**
1996101ffae26c23ea928fce6d31a8b4901327d91a15Jeff Garzik *      mv6_reset_hc - Perform the 6xxx global soft reset
1997101ffae26c23ea928fce6d31a8b4901327d91a15Jeff Garzik *      @mmio: base address of the HBA
1998101ffae26c23ea928fce6d31a8b4901327d91a15Jeff Garzik *
1999101ffae26c23ea928fce6d31a8b4901327d91a15Jeff Garzik *      This routine only applies to 6xxx parts.
2000101ffae26c23ea928fce6d31a8b4901327d91a15Jeff Garzik *
2001101ffae26c23ea928fce6d31a8b4901327d91a15Jeff Garzik *      LOCKING:
2002101ffae26c23ea928fce6d31a8b4901327d91a15Jeff Garzik *      Inherited from caller.
2003101ffae26c23ea928fce6d31a8b4901327d91a15Jeff Garzik */
2004c9d39130123238ac18478a42e25cb7996eacfcc0Jeff Garzikstatic int mv6_reset_hc(struct mv_host_priv *hpriv, void __iomem *mmio,
2005c9d39130123238ac18478a42e25cb7996eacfcc0Jeff Garzik			unsigned int n_hc)
2006101ffae26c23ea928fce6d31a8b4901327d91a15Jeff Garzik{
2007101ffae26c23ea928fce6d31a8b4901327d91a15Jeff Garzik	void __iomem *reg = mmio + PCI_MAIN_CMD_STS_OFS;
2008101ffae26c23ea928fce6d31a8b4901327d91a15Jeff Garzik	int i, rc = 0;
2009101ffae26c23ea928fce6d31a8b4901327d91a15Jeff Garzik	u32 t;
2010101ffae26c23ea928fce6d31a8b4901327d91a15Jeff Garzik
2011101ffae26c23ea928fce6d31a8b4901327d91a15Jeff Garzik	/* Following procedure defined in PCI "main command and status
2012101ffae26c23ea928fce6d31a8b4901327d91a15Jeff Garzik	 * register" table.
2013101ffae26c23ea928fce6d31a8b4901327d91a15Jeff Garzik	 */
2014101ffae26c23ea928fce6d31a8b4901327d91a15Jeff Garzik	t = readl(reg);
2015101ffae26c23ea928fce6d31a8b4901327d91a15Jeff Garzik	writel(t | STOP_PCI_MASTER, reg);
2016101ffae26c23ea928fce6d31a8b4901327d91a15Jeff Garzik
2017101ffae26c23ea928fce6d31a8b4901327d91a15Jeff Garzik	for (i = 0; i < 1000; i++) {
2018101ffae26c23ea928fce6d31a8b4901327d91a15Jeff Garzik		udelay(1);
2019101ffae26c23ea928fce6d31a8b4901327d91a15Jeff Garzik		t = readl(reg);
20202dcb407e61458ded17503d6bd12b8c064965368bJeff Garzik		if (PCI_MASTER_EMPTY & t)
2021101ffae26c23ea928fce6d31a8b4901327d91a15Jeff Garzik			break;
2022101ffae26c23ea928fce6d31a8b4901327d91a15Jeff Garzik	}
2023101ffae26c23ea928fce6d31a8b4901327d91a15Jeff Garzik	if (!(PCI_MASTER_EMPTY & t)) {
2024101ffae26c23ea928fce6d31a8b4901327d91a15Jeff Garzik		printk(KERN_ERR DRV_NAME ": PCI master won't flush\n");
2025101ffae26c23ea928fce6d31a8b4901327d91a15Jeff Garzik		rc = 1;
2026101ffae26c23ea928fce6d31a8b4901327d91a15Jeff Garzik		goto done;
2027101ffae26c23ea928fce6d31a8b4901327d91a15Jeff Garzik	}
2028101ffae26c23ea928fce6d31a8b4901327d91a15Jeff Garzik
2029101ffae26c23ea928fce6d31a8b4901327d91a15Jeff Garzik	/* set reset */
2030101ffae26c23ea928fce6d31a8b4901327d91a15Jeff Garzik	i = 5;
2031101ffae26c23ea928fce6d31a8b4901327d91a15Jeff Garzik	do {
2032101ffae26c23ea928fce6d31a8b4901327d91a15Jeff Garzik		writel(t | GLOB_SFT_RST, reg);
2033101ffae26c23ea928fce6d31a8b4901327d91a15Jeff Garzik		t = readl(reg);
2034101ffae26c23ea928fce6d31a8b4901327d91a15Jeff Garzik		udelay(1);
2035101ffae26c23ea928fce6d31a8b4901327d91a15Jeff Garzik	} while (!(GLOB_SFT_RST & t) && (i-- > 0));
2036101ffae26c23ea928fce6d31a8b4901327d91a15Jeff Garzik
2037101ffae26c23ea928fce6d31a8b4901327d91a15Jeff Garzik	if (!(GLOB_SFT_RST & t)) {
2038101ffae26c23ea928fce6d31a8b4901327d91a15Jeff Garzik		printk(KERN_ERR DRV_NAME ": can't set global reset\n");
2039101ffae26c23ea928fce6d31a8b4901327d91a15Jeff Garzik		rc = 1;
2040101ffae26c23ea928fce6d31a8b4901327d91a15Jeff Garzik		goto done;
2041101ffae26c23ea928fce6d31a8b4901327d91a15Jeff Garzik	}
2042101ffae26c23ea928fce6d31a8b4901327d91a15Jeff Garzik
2043101ffae26c23ea928fce6d31a8b4901327d91a15Jeff Garzik	/* clear reset and *reenable the PCI master* (not mentioned in spec) */
2044101ffae26c23ea928fce6d31a8b4901327d91a15Jeff Garzik	i = 5;
2045101ffae26c23ea928fce6d31a8b4901327d91a15Jeff Garzik	do {
2046101ffae26c23ea928fce6d31a8b4901327d91a15Jeff Garzik		writel(t & ~(GLOB_SFT_RST | STOP_PCI_MASTER), reg);
2047101ffae26c23ea928fce6d31a8b4901327d91a15Jeff Garzik		t = readl(reg);
2048101ffae26c23ea928fce6d31a8b4901327d91a15Jeff Garzik		udelay(1);
2049101ffae26c23ea928fce6d31a8b4901327d91a15Jeff Garzik	} while ((GLOB_SFT_RST & t) && (i-- > 0));
2050101ffae26c23ea928fce6d31a8b4901327d91a15Jeff Garzik
2051101ffae26c23ea928fce6d31a8b4901327d91a15Jeff Garzik	if (GLOB_SFT_RST & t) {
2052101ffae26c23ea928fce6d31a8b4901327d91a15Jeff Garzik		printk(KERN_ERR DRV_NAME ": can't clear global reset\n");
2053101ffae26c23ea928fce6d31a8b4901327d91a15Jeff Garzik		rc = 1;
2054101ffae26c23ea928fce6d31a8b4901327d91a15Jeff Garzik	}
2055101ffae26c23ea928fce6d31a8b4901327d91a15Jeff Garzikdone:
2056101ffae26c23ea928fce6d31a8b4901327d91a15Jeff Garzik	return rc;
2057101ffae26c23ea928fce6d31a8b4901327d91a15Jeff Garzik}
2058101ffae26c23ea928fce6d31a8b4901327d91a15Jeff Garzik
205947c2b677daeed9c79ecb7167c211ff36876ea611Jeff Garzikstatic void mv6_read_preamp(struct mv_host_priv *hpriv, int idx,
2060ba3fe8fb6a469390a14379519915f3c39a973d99Jeff Garzik			   void __iomem *mmio)
2061ba3fe8fb6a469390a14379519915f3c39a973d99Jeff Garzik{
2062ba3fe8fb6a469390a14379519915f3c39a973d99Jeff Garzik	void __iomem *port_mmio;
2063ba3fe8fb6a469390a14379519915f3c39a973d99Jeff Garzik	u32 tmp;
2064ba3fe8fb6a469390a14379519915f3c39a973d99Jeff Garzik
2065ba3fe8fb6a469390a14379519915f3c39a973d99Jeff Garzik	tmp = readl(mmio + MV_RESET_CFG);
2066ba3fe8fb6a469390a14379519915f3c39a973d99Jeff Garzik	if ((tmp & (1 << 0)) == 0) {
206747c2b677daeed9c79ecb7167c211ff36876ea611Jeff Garzik		hpriv->signal[idx].amps = 0x7 << 8;
2068ba3fe8fb6a469390a14379519915f3c39a973d99Jeff Garzik		hpriv->signal[idx].pre = 0x1 << 5;
2069ba3fe8fb6a469390a14379519915f3c39a973d99Jeff Garzik		return;
2070ba3fe8fb6a469390a14379519915f3c39a973d99Jeff Garzik	}
2071ba3fe8fb6a469390a14379519915f3c39a973d99Jeff Garzik
2072ba3fe8fb6a469390a14379519915f3c39a973d99Jeff Garzik	port_mmio = mv_port_base(mmio, idx);
2073ba3fe8fb6a469390a14379519915f3c39a973d99Jeff Garzik	tmp = readl(port_mmio + PHY_MODE2);
2074ba3fe8fb6a469390a14379519915f3c39a973d99Jeff Garzik
2075ba3fe8fb6a469390a14379519915f3c39a973d99Jeff Garzik	hpriv->signal[idx].amps = tmp & 0x700;	/* bits 10:8 */
2076ba3fe8fb6a469390a14379519915f3c39a973d99Jeff Garzik	hpriv->signal[idx].pre = tmp & 0xe0;	/* bits 7:5 */
2077ba3fe8fb6a469390a14379519915f3c39a973d99Jeff Garzik}
2078ba3fe8fb6a469390a14379519915f3c39a973d99Jeff Garzik
207947c2b677daeed9c79ecb7167c211ff36876ea611Jeff Garzikstatic void mv6_enable_leds(struct mv_host_priv *hpriv, void __iomem *mmio)
2080ba3fe8fb6a469390a14379519915f3c39a973d99Jeff Garzik{
208147c2b677daeed9c79ecb7167c211ff36876ea611Jeff Garzik	writel(0x00000060, mmio + MV_GPIO_PORT_CTL);
2082ba3fe8fb6a469390a14379519915f3c39a973d99Jeff Garzik}
2083ba3fe8fb6a469390a14379519915f3c39a973d99Jeff Garzik
2084c9d39130123238ac18478a42e25cb7996eacfcc0Jeff Garzikstatic void mv6_phy_errata(struct mv_host_priv *hpriv, void __iomem *mmio,
20852a47ce06d534692f9bd2bf4e90a20fc9b1054c39Jeff Garzik			   unsigned int port)
2086bca1c4eb9411533d613123618c0d127fae532595Jeff Garzik{
2087c9d39130123238ac18478a42e25cb7996eacfcc0Jeff Garzik	void __iomem *port_mmio = mv_port_base(mmio, port);
2088c9d39130123238ac18478a42e25cb7996eacfcc0Jeff Garzik
2089bca1c4eb9411533d613123618c0d127fae532595Jeff Garzik	u32 hp_flags = hpriv->hp_flags;
209047c2b677daeed9c79ecb7167c211ff36876ea611Jeff Garzik	int fix_phy_mode2 =
209147c2b677daeed9c79ecb7167c211ff36876ea611Jeff Garzik		hp_flags & (MV_HP_ERRATA_60X1B2 | MV_HP_ERRATA_60X1C0);
2092bca1c4eb9411533d613123618c0d127fae532595Jeff Garzik	int fix_phy_mode4 =
209347c2b677daeed9c79ecb7167c211ff36876ea611Jeff Garzik		hp_flags & (MV_HP_ERRATA_60X1B2 | MV_HP_ERRATA_60X1C0);
209447c2b677daeed9c79ecb7167c211ff36876ea611Jeff Garzik	u32 m2, tmp;
209547c2b677daeed9c79ecb7167c211ff36876ea611Jeff Garzik
209647c2b677daeed9c79ecb7167c211ff36876ea611Jeff Garzik	if (fix_phy_mode2) {
209747c2b677daeed9c79ecb7167c211ff36876ea611Jeff Garzik		m2 = readl(port_mmio + PHY_MODE2);
209847c2b677daeed9c79ecb7167c211ff36876ea611Jeff Garzik		m2 &= ~(1 << 16);
209947c2b677daeed9c79ecb7167c211ff36876ea611Jeff Garzik		m2 |= (1 << 31);
210047c2b677daeed9c79ecb7167c211ff36876ea611Jeff Garzik		writel(m2, port_mmio + PHY_MODE2);
210147c2b677daeed9c79ecb7167c211ff36876ea611Jeff Garzik
210247c2b677daeed9c79ecb7167c211ff36876ea611Jeff Garzik		udelay(200);
210347c2b677daeed9c79ecb7167c211ff36876ea611Jeff Garzik
210447c2b677daeed9c79ecb7167c211ff36876ea611Jeff Garzik		m2 = readl(port_mmio + PHY_MODE2);
210547c2b677daeed9c79ecb7167c211ff36876ea611Jeff Garzik		m2 &= ~((1 << 16) | (1 << 31));
210647c2b677daeed9c79ecb7167c211ff36876ea611Jeff Garzik		writel(m2, port_mmio + PHY_MODE2);
210747c2b677daeed9c79ecb7167c211ff36876ea611Jeff Garzik
210847c2b677daeed9c79ecb7167c211ff36876ea611Jeff Garzik		udelay(200);
210947c2b677daeed9c79ecb7167c211ff36876ea611Jeff Garzik	}
211047c2b677daeed9c79ecb7167c211ff36876ea611Jeff Garzik
211147c2b677daeed9c79ecb7167c211ff36876ea611Jeff Garzik	/* who knows what this magic does */
211247c2b677daeed9c79ecb7167c211ff36876ea611Jeff Garzik	tmp = readl(port_mmio + PHY_MODE3);
211347c2b677daeed9c79ecb7167c211ff36876ea611Jeff Garzik	tmp &= ~0x7F800000;
211447c2b677daeed9c79ecb7167c211ff36876ea611Jeff Garzik	tmp |= 0x2A800000;
211547c2b677daeed9c79ecb7167c211ff36876ea611Jeff Garzik	writel(tmp, port_mmio + PHY_MODE3);
2116bca1c4eb9411533d613123618c0d127fae532595Jeff Garzik
2117bca1c4eb9411533d613123618c0d127fae532595Jeff Garzik	if (fix_phy_mode4) {
211847c2b677daeed9c79ecb7167c211ff36876ea611Jeff Garzik		u32 m4;
2119bca1c4eb9411533d613123618c0d127fae532595Jeff Garzik
2120bca1c4eb9411533d613123618c0d127fae532595Jeff Garzik		m4 = readl(port_mmio + PHY_MODE4);
212147c2b677daeed9c79ecb7167c211ff36876ea611Jeff Garzik
212247c2b677daeed9c79ecb7167c211ff36876ea611Jeff Garzik		if (hp_flags & MV_HP_ERRATA_60X1B2)
212347c2b677daeed9c79ecb7167c211ff36876ea611Jeff Garzik			tmp = readl(port_mmio + 0x310);
2124bca1c4eb9411533d613123618c0d127fae532595Jeff Garzik
2125bca1c4eb9411533d613123618c0d127fae532595Jeff Garzik		m4 = (m4 & ~(1 << 1)) | (1 << 0);
2126bca1c4eb9411533d613123618c0d127fae532595Jeff Garzik
2127bca1c4eb9411533d613123618c0d127fae532595Jeff Garzik		writel(m4, port_mmio + PHY_MODE4);
212847c2b677daeed9c79ecb7167c211ff36876ea611Jeff Garzik
212947c2b677daeed9c79ecb7167c211ff36876ea611Jeff Garzik		if (hp_flags & MV_HP_ERRATA_60X1B2)
213047c2b677daeed9c79ecb7167c211ff36876ea611Jeff Garzik			writel(tmp, port_mmio + 0x310);
2131bca1c4eb9411533d613123618c0d127fae532595Jeff Garzik	}
2132bca1c4eb9411533d613123618c0d127fae532595Jeff Garzik
2133bca1c4eb9411533d613123618c0d127fae532595Jeff Garzik	/* Revert values of pre-emphasis and signal amps to the saved ones */
2134bca1c4eb9411533d613123618c0d127fae532595Jeff Garzik	m2 = readl(port_mmio + PHY_MODE2);
2135bca1c4eb9411533d613123618c0d127fae532595Jeff Garzik
2136bca1c4eb9411533d613123618c0d127fae532595Jeff Garzik	m2 &= ~MV_M2_PREAMP_MASK;
21372a47ce06d534692f9bd2bf4e90a20fc9b1054c39Jeff Garzik	m2 |= hpriv->signal[port].amps;
21382a47ce06d534692f9bd2bf4e90a20fc9b1054c39Jeff Garzik	m2 |= hpriv->signal[port].pre;
213947c2b677daeed9c79ecb7167c211ff36876ea611Jeff Garzik	m2 &= ~(1 << 16);
2140bca1c4eb9411533d613123618c0d127fae532595Jeff Garzik
2141e4e7b89280d1d666e2c09e5ad36cf071796c4c7eJeff Garzik	/* according to mvSata 3.6.1, some IIE values are fixed */
2142e4e7b89280d1d666e2c09e5ad36cf071796c4c7eJeff Garzik	if (IS_GEN_IIE(hpriv)) {
2143e4e7b89280d1d666e2c09e5ad36cf071796c4c7eJeff Garzik		m2 &= ~0xC30FF01F;
2144e4e7b89280d1d666e2c09e5ad36cf071796c4c7eJeff Garzik		m2 |= 0x0000900F;
2145e4e7b89280d1d666e2c09e5ad36cf071796c4c7eJeff Garzik	}
2146e4e7b89280d1d666e2c09e5ad36cf071796c4c7eJeff Garzik
2147bca1c4eb9411533d613123618c0d127fae532595Jeff Garzik	writel(m2, port_mmio + PHY_MODE2);
2148bca1c4eb9411533d613123618c0d127fae532595Jeff Garzik}
2149bca1c4eb9411533d613123618c0d127fae532595Jeff Garzik
2150c9d39130123238ac18478a42e25cb7996eacfcc0Jeff Garzikstatic void mv_channel_reset(struct mv_host_priv *hpriv, void __iomem *mmio,
2151c9d39130123238ac18478a42e25cb7996eacfcc0Jeff Garzik			     unsigned int port_no)
2152c9d39130123238ac18478a42e25cb7996eacfcc0Jeff Garzik{
2153c9d39130123238ac18478a42e25cb7996eacfcc0Jeff Garzik	void __iomem *port_mmio = mv_port_base(mmio, port_no);
2154c9d39130123238ac18478a42e25cb7996eacfcc0Jeff Garzik
2155c9d39130123238ac18478a42e25cb7996eacfcc0Jeff Garzik	writelfl(ATA_RST, port_mmio + EDMA_CMD_OFS);
2156c9d39130123238ac18478a42e25cb7996eacfcc0Jeff Garzik
2157ee9ccdf70163ca6408f6965e0fbc65baeac7312cJeff Garzik	if (IS_GEN_II(hpriv)) {
2158c9d39130123238ac18478a42e25cb7996eacfcc0Jeff Garzik		u32 ifctl = readl(port_mmio + SATA_INTERFACE_CTL);
2159eb46d684600ac145501805a294c94675e82eab2eMark Lord		ifctl |= (1 << 7);		/* enable gen2i speed */
2160eb46d684600ac145501805a294c94675e82eab2eMark Lord		ifctl = (ifctl & 0xfff) | 0x9b1000; /* from chip spec */
2161c9d39130123238ac18478a42e25cb7996eacfcc0Jeff Garzik		writelfl(ifctl, port_mmio + SATA_INTERFACE_CTL);
2162c9d39130123238ac18478a42e25cb7996eacfcc0Jeff Garzik	}
2163c9d39130123238ac18478a42e25cb7996eacfcc0Jeff Garzik
2164c9d39130123238ac18478a42e25cb7996eacfcc0Jeff Garzik	udelay(25);		/* allow reset propagation */
2165c9d39130123238ac18478a42e25cb7996eacfcc0Jeff Garzik
2166c9d39130123238ac18478a42e25cb7996eacfcc0Jeff Garzik	/* Spec never mentions clearing the bit.  Marvell's driver does
2167c9d39130123238ac18478a42e25cb7996eacfcc0Jeff Garzik	 * clear the bit, however.
2168c9d39130123238ac18478a42e25cb7996eacfcc0Jeff Garzik	 */
2169c9d39130123238ac18478a42e25cb7996eacfcc0Jeff Garzik	writelfl(0, port_mmio + EDMA_CMD_OFS);
2170c9d39130123238ac18478a42e25cb7996eacfcc0Jeff Garzik
2171c9d39130123238ac18478a42e25cb7996eacfcc0Jeff Garzik	hpriv->ops->phy_errata(hpriv, mmio, port_no);
2172c9d39130123238ac18478a42e25cb7996eacfcc0Jeff Garzik
2173ee9ccdf70163ca6408f6965e0fbc65baeac7312cJeff Garzik	if (IS_GEN_I(hpriv))
2174c9d39130123238ac18478a42e25cb7996eacfcc0Jeff Garzik		mdelay(1);
2175c9d39130123238ac18478a42e25cb7996eacfcc0Jeff Garzik}
2176c9d39130123238ac18478a42e25cb7996eacfcc0Jeff Garzik
217705b308e1df6d9d673daedb517969241f41278b52Brett Russ/**
2178bdd4dddee325a7dce3e84cf48201a06aa8508aa4Jeff Garzik *      mv_phy_reset - Perform eDMA reset followed by COMRESET
217905b308e1df6d9d673daedb517969241f41278b52Brett Russ *      @ap: ATA channel to manipulate
218005b308e1df6d9d673daedb517969241f41278b52Brett Russ *
218105b308e1df6d9d673daedb517969241f41278b52Brett Russ *      Part of this is taken from __sata_phy_reset and modified to
218205b308e1df6d9d673daedb517969241f41278b52Brett Russ *      not sleep since this routine gets called from interrupt level.
218305b308e1df6d9d673daedb517969241f41278b52Brett Russ *
218405b308e1df6d9d673daedb517969241f41278b52Brett Russ *      LOCKING:
218505b308e1df6d9d673daedb517969241f41278b52Brett Russ *      Inherited from caller.  This is coded to safe to call at
218605b308e1df6d9d673daedb517969241f41278b52Brett Russ *      interrupt level, i.e. it does not sleep.
218731961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ */
2188bdd4dddee325a7dce3e84cf48201a06aa8508aa4Jeff Garzikstatic void mv_phy_reset(struct ata_port *ap, unsigned int *class,
2189bdd4dddee325a7dce3e84cf48201a06aa8508aa4Jeff Garzik			 unsigned long deadline)
219020f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ{
2191095fec887eaa1c38d17c0c929a6733c744a9fa1fJeff Garzik	struct mv_port_priv *pp	= ap->private_data;
2192cca3974e48607c3775dc73b544a5700b2e37c21aJeff Garzik	struct mv_host_priv *hpriv = ap->host->private_data;
219320f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ	void __iomem *port_mmio = mv_ap_base(ap);
219422374677d18c5eeefd3a283431d312b8c44fef02Jeff Garzik	int retry = 5;
219522374677d18c5eeefd3a283431d312b8c44fef02Jeff Garzik	u32 sstatus;
219620f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ
219720f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ	VPRINTK("ENTER, port %u, mmio 0x%p\n", ap->port_no, port_mmio);
219820f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ
2199da3dbb17a0e9a9ec7f5aed95f1fddadb790edc9dTejun Heo#ifdef DEBUG
2200da3dbb17a0e9a9ec7f5aed95f1fddadb790edc9dTejun Heo	{
2201da3dbb17a0e9a9ec7f5aed95f1fddadb790edc9dTejun Heo		u32 sstatus, serror, scontrol;
2202da3dbb17a0e9a9ec7f5aed95f1fddadb790edc9dTejun Heo
2203da3dbb17a0e9a9ec7f5aed95f1fddadb790edc9dTejun Heo		mv_scr_read(ap, SCR_STATUS, &sstatus);
2204da3dbb17a0e9a9ec7f5aed95f1fddadb790edc9dTejun Heo		mv_scr_read(ap, SCR_ERROR, &serror);
2205da3dbb17a0e9a9ec7f5aed95f1fddadb790edc9dTejun Heo		mv_scr_read(ap, SCR_CONTROL, &scontrol);
2206da3dbb17a0e9a9ec7f5aed95f1fddadb790edc9dTejun Heo		DPRINTK("S-regs after ATA_RST: SStat 0x%08x SErr 0x%08x "
22072d79ab8fd7a7bf3a45d0e948ae27b3dd95ce95eaSaeed Bishara			"SCtrl 0x%08x\n", sstatus, serror, scontrol);
2208da3dbb17a0e9a9ec7f5aed95f1fddadb790edc9dTejun Heo	}
2209da3dbb17a0e9a9ec7f5aed95f1fddadb790edc9dTejun Heo#endif
221020f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ
221122374677d18c5eeefd3a283431d312b8c44fef02Jeff Garzik	/* Issue COMRESET via SControl */
221222374677d18c5eeefd3a283431d312b8c44fef02Jeff Garzikcomreset_retry:
2213936fd7328657884d5a69a55666c74a55aa83ca27Tejun Heo	sata_scr_write_flush(&ap->link, SCR_CONTROL, 0x301);
2214bdd4dddee325a7dce3e84cf48201a06aa8508aa4Jeff Garzik	msleep(1);
221522374677d18c5eeefd3a283431d312b8c44fef02Jeff Garzik
2216936fd7328657884d5a69a55666c74a55aa83ca27Tejun Heo	sata_scr_write_flush(&ap->link, SCR_CONTROL, 0x300);
2217bdd4dddee325a7dce3e84cf48201a06aa8508aa4Jeff Garzik	msleep(20);
221822374677d18c5eeefd3a283431d312b8c44fef02Jeff Garzik
221931961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ	do {
2220936fd7328657884d5a69a55666c74a55aa83ca27Tejun Heo		sata_scr_read(&ap->link, SCR_STATUS, &sstatus);
222162f1d0e6de138b91d55fbd7d579c837ed62e9e31Andres Salomon		if (((sstatus & 0x3) == 3) || ((sstatus & 0x3) == 0))
222231961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ			break;
222322374677d18c5eeefd3a283431d312b8c44fef02Jeff Garzik
2224bdd4dddee325a7dce3e84cf48201a06aa8508aa4Jeff Garzik		msleep(1);
2225c5d3e45a2200a0905dc45b72714726b7aac3aaf1Jeff Garzik	} while (time_before(jiffies, deadline));
222620f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ
222722374677d18c5eeefd3a283431d312b8c44fef02Jeff Garzik	/* work around errata */
2228ee9ccdf70163ca6408f6965e0fbc65baeac7312cJeff Garzik	if (IS_GEN_II(hpriv) &&
222922374677d18c5eeefd3a283431d312b8c44fef02Jeff Garzik	    (sstatus != 0x0) && (sstatus != 0x113) && (sstatus != 0x123) &&
223022374677d18c5eeefd3a283431d312b8c44fef02Jeff Garzik	    (retry-- > 0))
223122374677d18c5eeefd3a283431d312b8c44fef02Jeff Garzik		goto comreset_retry;
2232095fec887eaa1c38d17c0c929a6733c744a9fa1fJeff Garzik
2233da3dbb17a0e9a9ec7f5aed95f1fddadb790edc9dTejun Heo#ifdef DEBUG
2234da3dbb17a0e9a9ec7f5aed95f1fddadb790edc9dTejun Heo	{
2235da3dbb17a0e9a9ec7f5aed95f1fddadb790edc9dTejun Heo		u32 sstatus, serror, scontrol;
2236da3dbb17a0e9a9ec7f5aed95f1fddadb790edc9dTejun Heo
2237da3dbb17a0e9a9ec7f5aed95f1fddadb790edc9dTejun Heo		mv_scr_read(ap, SCR_STATUS, &sstatus);
2238da3dbb17a0e9a9ec7f5aed95f1fddadb790edc9dTejun Heo		mv_scr_read(ap, SCR_ERROR, &serror);
2239da3dbb17a0e9a9ec7f5aed95f1fddadb790edc9dTejun Heo		mv_scr_read(ap, SCR_CONTROL, &scontrol);
2240da3dbb17a0e9a9ec7f5aed95f1fddadb790edc9dTejun Heo		DPRINTK("S-regs after PHY wake: SStat 0x%08x SErr 0x%08x "
2241da3dbb17a0e9a9ec7f5aed95f1fddadb790edc9dTejun Heo			"SCtrl 0x%08x\n", sstatus, serror, scontrol);
2242da3dbb17a0e9a9ec7f5aed95f1fddadb790edc9dTejun Heo	}
2243da3dbb17a0e9a9ec7f5aed95f1fddadb790edc9dTejun Heo#endif
224431961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ
2245936fd7328657884d5a69a55666c74a55aa83ca27Tejun Heo	if (ata_link_offline(&ap->link)) {
2246bdd4dddee325a7dce3e84cf48201a06aa8508aa4Jeff Garzik		*class = ATA_DEV_NONE;
224720f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ		return;
224820f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ	}
224920f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ
225022374677d18c5eeefd3a283431d312b8c44fef02Jeff Garzik	/* even after SStatus reflects that device is ready,
225122374677d18c5eeefd3a283431d312b8c44fef02Jeff Garzik	 * it seems to take a while for link to be fully
225222374677d18c5eeefd3a283431d312b8c44fef02Jeff Garzik	 * established (and thus Status no longer 0x80/0x7F),
225322374677d18c5eeefd3a283431d312b8c44fef02Jeff Garzik	 * so we poll a bit for that, here.
225422374677d18c5eeefd3a283431d312b8c44fef02Jeff Garzik	 */
225522374677d18c5eeefd3a283431d312b8c44fef02Jeff Garzik	retry = 20;
225622374677d18c5eeefd3a283431d312b8c44fef02Jeff Garzik	while (1) {
225722374677d18c5eeefd3a283431d312b8c44fef02Jeff Garzik		u8 drv_stat = ata_check_status(ap);
225822374677d18c5eeefd3a283431d312b8c44fef02Jeff Garzik		if ((drv_stat != 0x80) && (drv_stat != 0x7f))
225922374677d18c5eeefd3a283431d312b8c44fef02Jeff Garzik			break;
2260bdd4dddee325a7dce3e84cf48201a06aa8508aa4Jeff Garzik		msleep(500);
226122374677d18c5eeefd3a283431d312b8c44fef02Jeff Garzik		if (retry-- <= 0)
226222374677d18c5eeefd3a283431d312b8c44fef02Jeff Garzik			break;
2263bdd4dddee325a7dce3e84cf48201a06aa8508aa4Jeff Garzik		if (time_after(jiffies, deadline))
2264bdd4dddee325a7dce3e84cf48201a06aa8508aa4Jeff Garzik			break;
226522374677d18c5eeefd3a283431d312b8c44fef02Jeff Garzik	}
226622374677d18c5eeefd3a283431d312b8c44fef02Jeff Garzik
2267bdd4dddee325a7dce3e84cf48201a06aa8508aa4Jeff Garzik	/* FIXME: if we passed the deadline, the following
2268bdd4dddee325a7dce3e84cf48201a06aa8508aa4Jeff Garzik	 * code probably produces an invalid result
2269bdd4dddee325a7dce3e84cf48201a06aa8508aa4Jeff Garzik	 */
227020f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ
2271bdd4dddee325a7dce3e84cf48201a06aa8508aa4Jeff Garzik	/* finally, read device signature from TF registers */
22723f19859ee95a38c066a0420eb8a30c76ecd67a42Tejun Heo	*class = ata_dev_try_classify(ap->link.device, 1, NULL);
2273095fec887eaa1c38d17c0c929a6733c744a9fa1fJeff Garzik
2274095fec887eaa1c38d17c0c929a6733c744a9fa1fJeff Garzik	writelfl(0, port_mmio + EDMA_ERR_IRQ_CAUSE_OFS);
2275095fec887eaa1c38d17c0c929a6733c744a9fa1fJeff Garzik
2276bdd4dddee325a7dce3e84cf48201a06aa8508aa4Jeff Garzik	WARN_ON(pp->pp_flags & MV_PP_FLAG_EDMA_EN);
2277095fec887eaa1c38d17c0c929a6733c744a9fa1fJeff Garzik
2278bca1c4eb9411533d613123618c0d127fae532595Jeff Garzik	VPRINTK("EXIT\n");
227920f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ}
228020f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ
2281cc0680a580b5be81a1ca321b58f8e9b80b5c1052Tejun Heostatic int mv_prereset(struct ata_link *link, unsigned long deadline)
228222374677d18c5eeefd3a283431d312b8c44fef02Jeff Garzik{
2283cc0680a580b5be81a1ca321b58f8e9b80b5c1052Tejun Heo	struct ata_port *ap = link->ap;
2284bdd4dddee325a7dce3e84cf48201a06aa8508aa4Jeff Garzik	struct mv_port_priv *pp	= ap->private_data;
2285cc0680a580b5be81a1ca321b58f8e9b80b5c1052Tejun Heo	struct ata_eh_context *ehc = &link->eh_context;
2286bdd4dddee325a7dce3e84cf48201a06aa8508aa4Jeff Garzik	int rc;
22870ea9e179f436f153fc19fdaef7abbc1e0da20762Jeff Garzik
2288bdd4dddee325a7dce3e84cf48201a06aa8508aa4Jeff Garzik	rc = mv_stop_dma(ap);
2289bdd4dddee325a7dce3e84cf48201a06aa8508aa4Jeff Garzik	if (rc)
2290bdd4dddee325a7dce3e84cf48201a06aa8508aa4Jeff Garzik		ehc->i.action |= ATA_EH_HARDRESET;
2291bdd4dddee325a7dce3e84cf48201a06aa8508aa4Jeff Garzik
2292bdd4dddee325a7dce3e84cf48201a06aa8508aa4Jeff Garzik	if (!(pp->pp_flags & MV_PP_FLAG_HAD_A_RESET)) {
2293bdd4dddee325a7dce3e84cf48201a06aa8508aa4Jeff Garzik		pp->pp_flags |= MV_PP_FLAG_HAD_A_RESET;
2294bdd4dddee325a7dce3e84cf48201a06aa8508aa4Jeff Garzik		ehc->i.action |= ATA_EH_HARDRESET;
2295bdd4dddee325a7dce3e84cf48201a06aa8508aa4Jeff Garzik	}
2296bdd4dddee325a7dce3e84cf48201a06aa8508aa4Jeff Garzik
2297bdd4dddee325a7dce3e84cf48201a06aa8508aa4Jeff Garzik	/* if we're about to do hardreset, nothing more to do */
2298bdd4dddee325a7dce3e84cf48201a06aa8508aa4Jeff Garzik	if (ehc->i.action & ATA_EH_HARDRESET)
2299bdd4dddee325a7dce3e84cf48201a06aa8508aa4Jeff Garzik		return 0;
2300bdd4dddee325a7dce3e84cf48201a06aa8508aa4Jeff Garzik
2301cc0680a580b5be81a1ca321b58f8e9b80b5c1052Tejun Heo	if (ata_link_online(link))
2302bdd4dddee325a7dce3e84cf48201a06aa8508aa4Jeff Garzik		rc = ata_wait_ready(ap, deadline);
2303bdd4dddee325a7dce3e84cf48201a06aa8508aa4Jeff Garzik	else
2304bdd4dddee325a7dce3e84cf48201a06aa8508aa4Jeff Garzik		rc = -ENODEV;
2305bdd4dddee325a7dce3e84cf48201a06aa8508aa4Jeff Garzik
2306bdd4dddee325a7dce3e84cf48201a06aa8508aa4Jeff Garzik	return rc;
230722374677d18c5eeefd3a283431d312b8c44fef02Jeff Garzik}
230822374677d18c5eeefd3a283431d312b8c44fef02Jeff Garzik
2309cc0680a580b5be81a1ca321b58f8e9b80b5c1052Tejun Heostatic int mv_hardreset(struct ata_link *link, unsigned int *class,
2310bdd4dddee325a7dce3e84cf48201a06aa8508aa4Jeff Garzik			unsigned long deadline)
231131961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ{
2312cc0680a580b5be81a1ca321b58f8e9b80b5c1052Tejun Heo	struct ata_port *ap = link->ap;
2313bdd4dddee325a7dce3e84cf48201a06aa8508aa4Jeff Garzik	struct mv_host_priv *hpriv = ap->host->private_data;
23140d5ff566779f894ca9937231a181eb31e4adff0eTejun Heo	void __iomem *mmio = ap->host->iomap[MV_PRIMARY_BAR];
231531961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ
2316bdd4dddee325a7dce3e84cf48201a06aa8508aa4Jeff Garzik	mv_stop_dma(ap);
231731961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ
2318bdd4dddee325a7dce3e84cf48201a06aa8508aa4Jeff Garzik	mv_channel_reset(hpriv, mmio, ap->port_no);
231931961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ
2320bdd4dddee325a7dce3e84cf48201a06aa8508aa4Jeff Garzik	mv_phy_reset(ap, class, deadline);
2321bdd4dddee325a7dce3e84cf48201a06aa8508aa4Jeff Garzik
2322bdd4dddee325a7dce3e84cf48201a06aa8508aa4Jeff Garzik	return 0;
2323bdd4dddee325a7dce3e84cf48201a06aa8508aa4Jeff Garzik}
2324bdd4dddee325a7dce3e84cf48201a06aa8508aa4Jeff Garzik
2325cc0680a580b5be81a1ca321b58f8e9b80b5c1052Tejun Heostatic void mv_postreset(struct ata_link *link, unsigned int *classes)
2326bdd4dddee325a7dce3e84cf48201a06aa8508aa4Jeff Garzik{
2327cc0680a580b5be81a1ca321b58f8e9b80b5c1052Tejun Heo	struct ata_port *ap = link->ap;
2328bdd4dddee325a7dce3e84cf48201a06aa8508aa4Jeff Garzik	u32 serr;
2329bdd4dddee325a7dce3e84cf48201a06aa8508aa4Jeff Garzik
2330bdd4dddee325a7dce3e84cf48201a06aa8508aa4Jeff Garzik	/* print link status */
2331cc0680a580b5be81a1ca321b58f8e9b80b5c1052Tejun Heo	sata_print_link_status(link);
233231961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ
2333bdd4dddee325a7dce3e84cf48201a06aa8508aa4Jeff Garzik	/* clear SError */
2334cc0680a580b5be81a1ca321b58f8e9b80b5c1052Tejun Heo	sata_scr_read(link, SCR_ERROR, &serr);
2335cc0680a580b5be81a1ca321b58f8e9b80b5c1052Tejun Heo	sata_scr_write_flush(link, SCR_ERROR, serr);
2336bdd4dddee325a7dce3e84cf48201a06aa8508aa4Jeff Garzik
2337bdd4dddee325a7dce3e84cf48201a06aa8508aa4Jeff Garzik	/* bail out if no device is present */
2338bdd4dddee325a7dce3e84cf48201a06aa8508aa4Jeff Garzik	if (classes[0] == ATA_DEV_NONE && classes[1] == ATA_DEV_NONE) {
2339bdd4dddee325a7dce3e84cf48201a06aa8508aa4Jeff Garzik		DPRINTK("EXIT, no device\n");
2340bdd4dddee325a7dce3e84cf48201a06aa8508aa4Jeff Garzik		return;
23419b358e305c1d783c8a4ebf00344e95deb9e38f3dMark Lord	}
2342bdd4dddee325a7dce3e84cf48201a06aa8508aa4Jeff Garzik
2343bdd4dddee325a7dce3e84cf48201a06aa8508aa4Jeff Garzik	/* set up device control */
2344bdd4dddee325a7dce3e84cf48201a06aa8508aa4Jeff Garzik	iowrite8(ap->ctl, ap->ioaddr.ctl_addr);
2345bdd4dddee325a7dce3e84cf48201a06aa8508aa4Jeff Garzik}
2346bdd4dddee325a7dce3e84cf48201a06aa8508aa4Jeff Garzik
2347bdd4dddee325a7dce3e84cf48201a06aa8508aa4Jeff Garzikstatic void mv_error_handler(struct ata_port *ap)
2348bdd4dddee325a7dce3e84cf48201a06aa8508aa4Jeff Garzik{
2349bdd4dddee325a7dce3e84cf48201a06aa8508aa4Jeff Garzik	ata_do_eh(ap, mv_prereset, ata_std_softreset,
2350bdd4dddee325a7dce3e84cf48201a06aa8508aa4Jeff Garzik		  mv_hardreset, mv_postreset);
2351bdd4dddee325a7dce3e84cf48201a06aa8508aa4Jeff Garzik}
2352bdd4dddee325a7dce3e84cf48201a06aa8508aa4Jeff Garzik
2353bdd4dddee325a7dce3e84cf48201a06aa8508aa4Jeff Garzikstatic void mv_post_int_cmd(struct ata_queued_cmd *qc)
2354bdd4dddee325a7dce3e84cf48201a06aa8508aa4Jeff Garzik{
2355bdd4dddee325a7dce3e84cf48201a06aa8508aa4Jeff Garzik	mv_stop_dma(qc->ap);
2356bdd4dddee325a7dce3e84cf48201a06aa8508aa4Jeff Garzik}
2357bdd4dddee325a7dce3e84cf48201a06aa8508aa4Jeff Garzik
2358bdd4dddee325a7dce3e84cf48201a06aa8508aa4Jeff Garzikstatic void mv_eh_freeze(struct ata_port *ap)
2359bdd4dddee325a7dce3e84cf48201a06aa8508aa4Jeff Garzik{
2360bdd4dddee325a7dce3e84cf48201a06aa8508aa4Jeff Garzik	void __iomem *mmio = ap->host->iomap[MV_PRIMARY_BAR];
2361bdd4dddee325a7dce3e84cf48201a06aa8508aa4Jeff Garzik	unsigned int hc = (ap->port_no > 3) ? 1 : 0;
2362bdd4dddee325a7dce3e84cf48201a06aa8508aa4Jeff Garzik	u32 tmp, mask;
2363bdd4dddee325a7dce3e84cf48201a06aa8508aa4Jeff Garzik	unsigned int shift;
2364bdd4dddee325a7dce3e84cf48201a06aa8508aa4Jeff Garzik
2365bdd4dddee325a7dce3e84cf48201a06aa8508aa4Jeff Garzik	/* FIXME: handle coalescing completion events properly */
2366bdd4dddee325a7dce3e84cf48201a06aa8508aa4Jeff Garzik
2367bdd4dddee325a7dce3e84cf48201a06aa8508aa4Jeff Garzik	shift = ap->port_no * 2;
2368bdd4dddee325a7dce3e84cf48201a06aa8508aa4Jeff Garzik	if (hc > 0)
2369bdd4dddee325a7dce3e84cf48201a06aa8508aa4Jeff Garzik		shift++;
2370bdd4dddee325a7dce3e84cf48201a06aa8508aa4Jeff Garzik
2371bdd4dddee325a7dce3e84cf48201a06aa8508aa4Jeff Garzik	mask = 0x3 << shift;
2372bdd4dddee325a7dce3e84cf48201a06aa8508aa4Jeff Garzik
2373bdd4dddee325a7dce3e84cf48201a06aa8508aa4Jeff Garzik	/* disable assertion of portN err, done events */
2374bdd4dddee325a7dce3e84cf48201a06aa8508aa4Jeff Garzik	tmp = readl(mmio + HC_MAIN_IRQ_MASK_OFS);
2375bdd4dddee325a7dce3e84cf48201a06aa8508aa4Jeff Garzik	writelfl(tmp & ~mask, mmio + HC_MAIN_IRQ_MASK_OFS);
2376bdd4dddee325a7dce3e84cf48201a06aa8508aa4Jeff Garzik}
2377bdd4dddee325a7dce3e84cf48201a06aa8508aa4Jeff Garzik
2378bdd4dddee325a7dce3e84cf48201a06aa8508aa4Jeff Garzikstatic void mv_eh_thaw(struct ata_port *ap)
2379bdd4dddee325a7dce3e84cf48201a06aa8508aa4Jeff Garzik{
2380bdd4dddee325a7dce3e84cf48201a06aa8508aa4Jeff Garzik	void __iomem *mmio = ap->host->iomap[MV_PRIMARY_BAR];
2381bdd4dddee325a7dce3e84cf48201a06aa8508aa4Jeff Garzik	unsigned int hc = (ap->port_no > 3) ? 1 : 0;
2382bdd4dddee325a7dce3e84cf48201a06aa8508aa4Jeff Garzik	void __iomem *hc_mmio = mv_hc_base(mmio, hc);
2383bdd4dddee325a7dce3e84cf48201a06aa8508aa4Jeff Garzik	void __iomem *port_mmio = mv_ap_base(ap);
2384bdd4dddee325a7dce3e84cf48201a06aa8508aa4Jeff Garzik	u32 tmp, mask, hc_irq_cause;
2385bdd4dddee325a7dce3e84cf48201a06aa8508aa4Jeff Garzik	unsigned int shift, hc_port_no = ap->port_no;
2386bdd4dddee325a7dce3e84cf48201a06aa8508aa4Jeff Garzik
2387bdd4dddee325a7dce3e84cf48201a06aa8508aa4Jeff Garzik	/* FIXME: handle coalescing completion events properly */
2388bdd4dddee325a7dce3e84cf48201a06aa8508aa4Jeff Garzik
2389bdd4dddee325a7dce3e84cf48201a06aa8508aa4Jeff Garzik	shift = ap->port_no * 2;
2390bdd4dddee325a7dce3e84cf48201a06aa8508aa4Jeff Garzik	if (hc > 0) {
2391bdd4dddee325a7dce3e84cf48201a06aa8508aa4Jeff Garzik		shift++;
2392bdd4dddee325a7dce3e84cf48201a06aa8508aa4Jeff Garzik		hc_port_no -= 4;
2393bdd4dddee325a7dce3e84cf48201a06aa8508aa4Jeff Garzik	}
2394bdd4dddee325a7dce3e84cf48201a06aa8508aa4Jeff Garzik
2395bdd4dddee325a7dce3e84cf48201a06aa8508aa4Jeff Garzik	mask = 0x3 << shift;
2396bdd4dddee325a7dce3e84cf48201a06aa8508aa4Jeff Garzik
2397bdd4dddee325a7dce3e84cf48201a06aa8508aa4Jeff Garzik	/* clear EDMA errors on this port */
2398bdd4dddee325a7dce3e84cf48201a06aa8508aa4Jeff Garzik	writel(0, port_mmio + EDMA_ERR_IRQ_CAUSE_OFS);
2399bdd4dddee325a7dce3e84cf48201a06aa8508aa4Jeff Garzik
2400bdd4dddee325a7dce3e84cf48201a06aa8508aa4Jeff Garzik	/* clear pending irq events */
2401bdd4dddee325a7dce3e84cf48201a06aa8508aa4Jeff Garzik	hc_irq_cause = readl(hc_mmio + HC_IRQ_CAUSE_OFS);
2402bdd4dddee325a7dce3e84cf48201a06aa8508aa4Jeff Garzik	hc_irq_cause &= ~(1 << hc_port_no);	/* clear CRPB-done */
2403bdd4dddee325a7dce3e84cf48201a06aa8508aa4Jeff Garzik	hc_irq_cause &= ~(1 << (hc_port_no + 8)); /* clear Device int */
2404bdd4dddee325a7dce3e84cf48201a06aa8508aa4Jeff Garzik	writel(hc_irq_cause, hc_mmio + HC_IRQ_CAUSE_OFS);
2405bdd4dddee325a7dce3e84cf48201a06aa8508aa4Jeff Garzik
2406bdd4dddee325a7dce3e84cf48201a06aa8508aa4Jeff Garzik	/* enable assertion of portN err, done events */
2407bdd4dddee325a7dce3e84cf48201a06aa8508aa4Jeff Garzik	tmp = readl(mmio + HC_MAIN_IRQ_MASK_OFS);
2408bdd4dddee325a7dce3e84cf48201a06aa8508aa4Jeff Garzik	writelfl(tmp | mask, mmio + HC_MAIN_IRQ_MASK_OFS);
240931961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ}
241031961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ
241105b308e1df6d9d673daedb517969241f41278b52Brett Russ/**
241205b308e1df6d9d673daedb517969241f41278b52Brett Russ *      mv_port_init - Perform some early initialization on a single port.
241305b308e1df6d9d673daedb517969241f41278b52Brett Russ *      @port: libata data structure storing shadow register addresses
241405b308e1df6d9d673daedb517969241f41278b52Brett Russ *      @port_mmio: base address of the port
241505b308e1df6d9d673daedb517969241f41278b52Brett Russ *
241605b308e1df6d9d673daedb517969241f41278b52Brett Russ *      Initialize shadow register mmio addresses, clear outstanding
241705b308e1df6d9d673daedb517969241f41278b52Brett Russ *      interrupts on the port, and unmask interrupts for the future
241805b308e1df6d9d673daedb517969241f41278b52Brett Russ *      start of the port.
241905b308e1df6d9d673daedb517969241f41278b52Brett Russ *
242005b308e1df6d9d673daedb517969241f41278b52Brett Russ *      LOCKING:
242105b308e1df6d9d673daedb517969241f41278b52Brett Russ *      Inherited from caller.
242205b308e1df6d9d673daedb517969241f41278b52Brett Russ */
242331961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russstatic void mv_port_init(struct ata_ioports *port,  void __iomem *port_mmio)
242420f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ{
24250d5ff566779f894ca9937231a181eb31e4adff0eTejun Heo	void __iomem *shd_base = port_mmio + SHD_BLK_OFS;
242631961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ	unsigned serr_ofs;
242731961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ
24288b260248d9e0e8b64bb72fd4dee03ad86984c344Jeff Garzik	/* PIO related setup
242931961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ	 */
243031961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ	port->data_addr = shd_base + (sizeof(u32) * ATA_REG_DATA);
24318b260248d9e0e8b64bb72fd4dee03ad86984c344Jeff Garzik	port->error_addr =
243231961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ		port->feature_addr = shd_base + (sizeof(u32) * ATA_REG_ERR);
243331961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ	port->nsect_addr = shd_base + (sizeof(u32) * ATA_REG_NSECT);
243431961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ	port->lbal_addr = shd_base + (sizeof(u32) * ATA_REG_LBAL);
243531961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ	port->lbam_addr = shd_base + (sizeof(u32) * ATA_REG_LBAM);
243631961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ	port->lbah_addr = shd_base + (sizeof(u32) * ATA_REG_LBAH);
243731961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ	port->device_addr = shd_base + (sizeof(u32) * ATA_REG_DEVICE);
24388b260248d9e0e8b64bb72fd4dee03ad86984c344Jeff Garzik	port->status_addr =
243931961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ		port->command_addr = shd_base + (sizeof(u32) * ATA_REG_STATUS);
244031961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ	/* special case: control/altstatus doesn't have ATA_REG_ address */
244131961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ	port->altstatus_addr = port->ctl_addr = shd_base + SHD_CTL_AST_OFS;
244231961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ
244331961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ	/* unused: */
24448d9db2d2fbae9e05022825c32f86e00c8e342860Randy Dunlap	port->cmd_addr = port->bmdma_addr = port->scr_addr = NULL;
244520f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ
244631961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ	/* Clear any currently outstanding port interrupt conditions */
244731961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ	serr_ofs = mv_scr_offset(SCR_ERROR);
244831961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ	writelfl(readl(port_mmio + serr_ofs), port_mmio + serr_ofs);
244931961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ	writelfl(0, port_mmio + EDMA_ERR_IRQ_CAUSE_OFS);
245031961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ
2451646a4da514f2555298481cb00dc5b3eb02b21b72Mark Lord	/* unmask all non-transient EDMA error interrupts */
2452646a4da514f2555298481cb00dc5b3eb02b21b72Mark Lord	writelfl(~EDMA_ERR_IRQ_TRANSIENT, port_mmio + EDMA_ERR_IRQ_MASK_OFS);
245320f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ
24548b260248d9e0e8b64bb72fd4dee03ad86984c344Jeff Garzik	VPRINTK("EDMA cfg=0x%08x EDMA IRQ err cause/mask=0x%08x/0x%08x\n",
245531961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ		readl(port_mmio + EDMA_CFG_OFS),
245631961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ		readl(port_mmio + EDMA_ERR_IRQ_CAUSE_OFS),
245731961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ		readl(port_mmio + EDMA_ERR_IRQ_MASK_OFS));
245820f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ}
245920f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ
24604447d35156169cf136e829eb6b5cac2d6370f2d9Tejun Heostatic int mv_chip_id(struct ata_host *host, unsigned int board_idx)
2461bca1c4eb9411533d613123618c0d127fae532595Jeff Garzik{
24624447d35156169cf136e829eb6b5cac2d6370f2d9Tejun Heo	struct pci_dev *pdev = to_pci_dev(host->dev);
24634447d35156169cf136e829eb6b5cac2d6370f2d9Tejun Heo	struct mv_host_priv *hpriv = host->private_data;
2464bca1c4eb9411533d613123618c0d127fae532595Jeff Garzik	u32 hp_flags = hpriv->hp_flags;
2465bca1c4eb9411533d613123618c0d127fae532595Jeff Garzik
24665796d1c4c89efff823259fda35b08ea66ebf8b23Jeff Garzik	switch (board_idx) {
246747c2b677daeed9c79ecb7167c211ff36876ea611Jeff Garzik	case chip_5080:
246847c2b677daeed9c79ecb7167c211ff36876ea611Jeff Garzik		hpriv->ops = &mv5xxx_ops;
2469ee9ccdf70163ca6408f6965e0fbc65baeac7312cJeff Garzik		hp_flags |= MV_HP_GEN_I;
247047c2b677daeed9c79ecb7167c211ff36876ea611Jeff Garzik
247144c10138fd4bbc4b6d6bff0873c24902f2a9da65Auke Kok		switch (pdev->revision) {
247247c2b677daeed9c79ecb7167c211ff36876ea611Jeff Garzik		case 0x1:
247347c2b677daeed9c79ecb7167c211ff36876ea611Jeff Garzik			hp_flags |= MV_HP_ERRATA_50XXB0;
247447c2b677daeed9c79ecb7167c211ff36876ea611Jeff Garzik			break;
247547c2b677daeed9c79ecb7167c211ff36876ea611Jeff Garzik		case 0x3:
247647c2b677daeed9c79ecb7167c211ff36876ea611Jeff Garzik			hp_flags |= MV_HP_ERRATA_50XXB2;
247747c2b677daeed9c79ecb7167c211ff36876ea611Jeff Garzik			break;
247847c2b677daeed9c79ecb7167c211ff36876ea611Jeff Garzik		default:
247947c2b677daeed9c79ecb7167c211ff36876ea611Jeff Garzik			dev_printk(KERN_WARNING, &pdev->dev,
248047c2b677daeed9c79ecb7167c211ff36876ea611Jeff Garzik			   "Applying 50XXB2 workarounds to unknown rev\n");
248147c2b677daeed9c79ecb7167c211ff36876ea611Jeff Garzik			hp_flags |= MV_HP_ERRATA_50XXB2;
248247c2b677daeed9c79ecb7167c211ff36876ea611Jeff Garzik			break;
248347c2b677daeed9c79ecb7167c211ff36876ea611Jeff Garzik		}
248447c2b677daeed9c79ecb7167c211ff36876ea611Jeff Garzik		break;
248547c2b677daeed9c79ecb7167c211ff36876ea611Jeff Garzik
2486bca1c4eb9411533d613123618c0d127fae532595Jeff Garzik	case chip_504x:
2487bca1c4eb9411533d613123618c0d127fae532595Jeff Garzik	case chip_508x:
248847c2b677daeed9c79ecb7167c211ff36876ea611Jeff Garzik		hpriv->ops = &mv5xxx_ops;
2489ee9ccdf70163ca6408f6965e0fbc65baeac7312cJeff Garzik		hp_flags |= MV_HP_GEN_I;
2490bca1c4eb9411533d613123618c0d127fae532595Jeff Garzik
249144c10138fd4bbc4b6d6bff0873c24902f2a9da65Auke Kok		switch (pdev->revision) {
249247c2b677daeed9c79ecb7167c211ff36876ea611Jeff Garzik		case 0x0:
249347c2b677daeed9c79ecb7167c211ff36876ea611Jeff Garzik			hp_flags |= MV_HP_ERRATA_50XXB0;
249447c2b677daeed9c79ecb7167c211ff36876ea611Jeff Garzik			break;
249547c2b677daeed9c79ecb7167c211ff36876ea611Jeff Garzik		case 0x3:
249647c2b677daeed9c79ecb7167c211ff36876ea611Jeff Garzik			hp_flags |= MV_HP_ERRATA_50XXB2;
249747c2b677daeed9c79ecb7167c211ff36876ea611Jeff Garzik			break;
249847c2b677daeed9c79ecb7167c211ff36876ea611Jeff Garzik		default:
249947c2b677daeed9c79ecb7167c211ff36876ea611Jeff Garzik			dev_printk(KERN_WARNING, &pdev->dev,
250047c2b677daeed9c79ecb7167c211ff36876ea611Jeff Garzik			   "Applying B2 workarounds to unknown rev\n");
250147c2b677daeed9c79ecb7167c211ff36876ea611Jeff Garzik			hp_flags |= MV_HP_ERRATA_50XXB2;
250247c2b677daeed9c79ecb7167c211ff36876ea611Jeff Garzik			break;
2503bca1c4eb9411533d613123618c0d127fae532595Jeff Garzik		}
2504bca1c4eb9411533d613123618c0d127fae532595Jeff Garzik		break;
2505bca1c4eb9411533d613123618c0d127fae532595Jeff Garzik
2506bca1c4eb9411533d613123618c0d127fae532595Jeff Garzik	case chip_604x:
2507bca1c4eb9411533d613123618c0d127fae532595Jeff Garzik	case chip_608x:
250847c2b677daeed9c79ecb7167c211ff36876ea611Jeff Garzik		hpriv->ops = &mv6xxx_ops;
2509ee9ccdf70163ca6408f6965e0fbc65baeac7312cJeff Garzik		hp_flags |= MV_HP_GEN_II;
251047c2b677daeed9c79ecb7167c211ff36876ea611Jeff Garzik
251144c10138fd4bbc4b6d6bff0873c24902f2a9da65Auke Kok		switch (pdev->revision) {
251247c2b677daeed9c79ecb7167c211ff36876ea611Jeff Garzik		case 0x7:
251347c2b677daeed9c79ecb7167c211ff36876ea611Jeff Garzik			hp_flags |= MV_HP_ERRATA_60X1B2;
251447c2b677daeed9c79ecb7167c211ff36876ea611Jeff Garzik			break;
251547c2b677daeed9c79ecb7167c211ff36876ea611Jeff Garzik		case 0x9:
251647c2b677daeed9c79ecb7167c211ff36876ea611Jeff Garzik			hp_flags |= MV_HP_ERRATA_60X1C0;
2517bca1c4eb9411533d613123618c0d127fae532595Jeff Garzik			break;
2518bca1c4eb9411533d613123618c0d127fae532595Jeff Garzik		default:
2519bca1c4eb9411533d613123618c0d127fae532595Jeff Garzik			dev_printk(KERN_WARNING, &pdev->dev,
252047c2b677daeed9c79ecb7167c211ff36876ea611Jeff Garzik				   "Applying B2 workarounds to unknown rev\n");
252147c2b677daeed9c79ecb7167c211ff36876ea611Jeff Garzik			hp_flags |= MV_HP_ERRATA_60X1B2;
2522bca1c4eb9411533d613123618c0d127fae532595Jeff Garzik			break;
2523bca1c4eb9411533d613123618c0d127fae532595Jeff Garzik		}
2524bca1c4eb9411533d613123618c0d127fae532595Jeff Garzik		break;
2525bca1c4eb9411533d613123618c0d127fae532595Jeff Garzik
2526e4e7b89280d1d666e2c09e5ad36cf071796c4c7eJeff Garzik	case chip_7042:
252702a121da5a53d415b6596bc19cc6999d295d32a4Mark Lord		hp_flags |= MV_HP_PCIE;
2528306b30f74d37f289033c696285e07ce0158a5d7bMark Lord		if (pdev->vendor == PCI_VENDOR_ID_TTI &&
2529306b30f74d37f289033c696285e07ce0158a5d7bMark Lord		    (pdev->device == 0x2300 || pdev->device == 0x2310))
2530306b30f74d37f289033c696285e07ce0158a5d7bMark Lord		{
25314e5200334e03e5620aa19d538300c13db270a063Mark Lord			/*
25324e5200334e03e5620aa19d538300c13db270a063Mark Lord			 * Highpoint RocketRAID PCIe 23xx series cards:
25334e5200334e03e5620aa19d538300c13db270a063Mark Lord			 *
25344e5200334e03e5620aa19d538300c13db270a063Mark Lord			 * Unconfigured drives are treated as "Legacy"
25354e5200334e03e5620aa19d538300c13db270a063Mark Lord			 * by the BIOS, and it overwrites sector 8 with
25364e5200334e03e5620aa19d538300c13db270a063Mark Lord			 * a "Lgcy" metadata block prior to Linux boot.
25374e5200334e03e5620aa19d538300c13db270a063Mark Lord			 *
25384e5200334e03e5620aa19d538300c13db270a063Mark Lord			 * Configured drives (RAID or JBOD) leave sector 8
25394e5200334e03e5620aa19d538300c13db270a063Mark Lord			 * alone, but instead overwrite a high numbered
25404e5200334e03e5620aa19d538300c13db270a063Mark Lord			 * sector for the RAID metadata.  This sector can
25414e5200334e03e5620aa19d538300c13db270a063Mark Lord			 * be determined exactly, by truncating the physical
25424e5200334e03e5620aa19d538300c13db270a063Mark Lord			 * drive capacity to a nice even GB value.
25434e5200334e03e5620aa19d538300c13db270a063Mark Lord			 *
25444e5200334e03e5620aa19d538300c13db270a063Mark Lord			 * RAID metadata is at: (dev->n_sectors & ~0xfffff)
25454e5200334e03e5620aa19d538300c13db270a063Mark Lord			 *
25464e5200334e03e5620aa19d538300c13db270a063Mark Lord			 * Warn the user, lest they think we're just buggy.
25474e5200334e03e5620aa19d538300c13db270a063Mark Lord			 */
25484e5200334e03e5620aa19d538300c13db270a063Mark Lord			printk(KERN_WARNING DRV_NAME ": Highpoint RocketRAID"
25494e5200334e03e5620aa19d538300c13db270a063Mark Lord				" BIOS CORRUPTS DATA on all attached drives,"
25504e5200334e03e5620aa19d538300c13db270a063Mark Lord				" regardless of if/how they are configured."
25514e5200334e03e5620aa19d538300c13db270a063Mark Lord				" BEWARE!\n");
25524e5200334e03e5620aa19d538300c13db270a063Mark Lord			printk(KERN_WARNING DRV_NAME ": For data safety, do not"
25534e5200334e03e5620aa19d538300c13db270a063Mark Lord				" use sectors 8-9 on \"Legacy\" drives,"
25544e5200334e03e5620aa19d538300c13db270a063Mark Lord				" and avoid the final two gigabytes on"
25554e5200334e03e5620aa19d538300c13db270a063Mark Lord				" all RocketRAID BIOS initialized drives.\n");
2556306b30f74d37f289033c696285e07ce0158a5d7bMark Lord		}
2557e4e7b89280d1d666e2c09e5ad36cf071796c4c7eJeff Garzik	case chip_6042:
2558e4e7b89280d1d666e2c09e5ad36cf071796c4c7eJeff Garzik		hpriv->ops = &mv6xxx_ops;
2559e4e7b89280d1d666e2c09e5ad36cf071796c4c7eJeff Garzik		hp_flags |= MV_HP_GEN_IIE;
2560e4e7b89280d1d666e2c09e5ad36cf071796c4c7eJeff Garzik
256144c10138fd4bbc4b6d6bff0873c24902f2a9da65Auke Kok		switch (pdev->revision) {
2562e4e7b89280d1d666e2c09e5ad36cf071796c4c7eJeff Garzik		case 0x0:
2563e4e7b89280d1d666e2c09e5ad36cf071796c4c7eJeff Garzik			hp_flags |= MV_HP_ERRATA_XX42A0;
2564e4e7b89280d1d666e2c09e5ad36cf071796c4c7eJeff Garzik			break;
2565e4e7b89280d1d666e2c09e5ad36cf071796c4c7eJeff Garzik		case 0x1:
2566e4e7b89280d1d666e2c09e5ad36cf071796c4c7eJeff Garzik			hp_flags |= MV_HP_ERRATA_60X1C0;
2567e4e7b89280d1d666e2c09e5ad36cf071796c4c7eJeff Garzik			break;
2568e4e7b89280d1d666e2c09e5ad36cf071796c4c7eJeff Garzik		default:
2569e4e7b89280d1d666e2c09e5ad36cf071796c4c7eJeff Garzik			dev_printk(KERN_WARNING, &pdev->dev,
2570e4e7b89280d1d666e2c09e5ad36cf071796c4c7eJeff Garzik			   "Applying 60X1C0 workarounds to unknown rev\n");
2571e4e7b89280d1d666e2c09e5ad36cf071796c4c7eJeff Garzik			hp_flags |= MV_HP_ERRATA_60X1C0;
2572e4e7b89280d1d666e2c09e5ad36cf071796c4c7eJeff Garzik			break;
2573e4e7b89280d1d666e2c09e5ad36cf071796c4c7eJeff Garzik		}
2574e4e7b89280d1d666e2c09e5ad36cf071796c4c7eJeff Garzik		break;
2575e4e7b89280d1d666e2c09e5ad36cf071796c4c7eJeff Garzik
2576bca1c4eb9411533d613123618c0d127fae532595Jeff Garzik	default:
25775796d1c4c89efff823259fda35b08ea66ebf8b23Jeff Garzik		dev_printk(KERN_ERR, &pdev->dev,
25785796d1c4c89efff823259fda35b08ea66ebf8b23Jeff Garzik			   "BUG: invalid board index %u\n", board_idx);
2579bca1c4eb9411533d613123618c0d127fae532595Jeff Garzik		return 1;
2580bca1c4eb9411533d613123618c0d127fae532595Jeff Garzik	}
2581bca1c4eb9411533d613123618c0d127fae532595Jeff Garzik
2582bca1c4eb9411533d613123618c0d127fae532595Jeff Garzik	hpriv->hp_flags = hp_flags;
258302a121da5a53d415b6596bc19cc6999d295d32a4Mark Lord	if (hp_flags & MV_HP_PCIE) {
258402a121da5a53d415b6596bc19cc6999d295d32a4Mark Lord		hpriv->irq_cause_ofs	= PCIE_IRQ_CAUSE_OFS;
258502a121da5a53d415b6596bc19cc6999d295d32a4Mark Lord		hpriv->irq_mask_ofs	= PCIE_IRQ_MASK_OFS;
258602a121da5a53d415b6596bc19cc6999d295d32a4Mark Lord		hpriv->unmask_all_irqs	= PCIE_UNMASK_ALL_IRQS;
258702a121da5a53d415b6596bc19cc6999d295d32a4Mark Lord	} else {
258802a121da5a53d415b6596bc19cc6999d295d32a4Mark Lord		hpriv->irq_cause_ofs	= PCI_IRQ_CAUSE_OFS;
258902a121da5a53d415b6596bc19cc6999d295d32a4Mark Lord		hpriv->irq_mask_ofs	= PCI_IRQ_MASK_OFS;
259002a121da5a53d415b6596bc19cc6999d295d32a4Mark Lord		hpriv->unmask_all_irqs	= PCI_UNMASK_ALL_IRQS;
259102a121da5a53d415b6596bc19cc6999d295d32a4Mark Lord	}
2592bca1c4eb9411533d613123618c0d127fae532595Jeff Garzik
2593bca1c4eb9411533d613123618c0d127fae532595Jeff Garzik	return 0;
2594bca1c4eb9411533d613123618c0d127fae532595Jeff Garzik}
2595bca1c4eb9411533d613123618c0d127fae532595Jeff Garzik
259605b308e1df6d9d673daedb517969241f41278b52Brett Russ/**
259747c2b677daeed9c79ecb7167c211ff36876ea611Jeff Garzik *      mv_init_host - Perform some early initialization of the host.
25984447d35156169cf136e829eb6b5cac2d6370f2d9Tejun Heo *	@host: ATA host to initialize
25994447d35156169cf136e829eb6b5cac2d6370f2d9Tejun Heo *      @board_idx: controller index
260005b308e1df6d9d673daedb517969241f41278b52Brett Russ *
260105b308e1df6d9d673daedb517969241f41278b52Brett Russ *      If possible, do an early global reset of the host.  Then do
260205b308e1df6d9d673daedb517969241f41278b52Brett Russ *      our port init and clear/unmask all/relevant host interrupts.
260305b308e1df6d9d673daedb517969241f41278b52Brett Russ *
260405b308e1df6d9d673daedb517969241f41278b52Brett Russ *      LOCKING:
260505b308e1df6d9d673daedb517969241f41278b52Brett Russ *      Inherited from caller.
260605b308e1df6d9d673daedb517969241f41278b52Brett Russ */
26074447d35156169cf136e829eb6b5cac2d6370f2d9Tejun Heostatic int mv_init_host(struct ata_host *host, unsigned int board_idx)
260820f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ{
260920f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ	int rc = 0, n_hc, port, hc;
26104447d35156169cf136e829eb6b5cac2d6370f2d9Tejun Heo	struct pci_dev *pdev = to_pci_dev(host->dev);
26114447d35156169cf136e829eb6b5cac2d6370f2d9Tejun Heo	void __iomem *mmio = host->iomap[MV_PRIMARY_BAR];
26124447d35156169cf136e829eb6b5cac2d6370f2d9Tejun Heo	struct mv_host_priv *hpriv = host->private_data;
2613bca1c4eb9411533d613123618c0d127fae532595Jeff Garzik
261447c2b677daeed9c79ecb7167c211ff36876ea611Jeff Garzik	/* global interrupt mask */
261547c2b677daeed9c79ecb7167c211ff36876ea611Jeff Garzik	writel(0, mmio + HC_MAIN_IRQ_MASK_OFS);
261647c2b677daeed9c79ecb7167c211ff36876ea611Jeff Garzik
26174447d35156169cf136e829eb6b5cac2d6370f2d9Tejun Heo	rc = mv_chip_id(host, board_idx);
2618bca1c4eb9411533d613123618c0d127fae532595Jeff Garzik	if (rc)
2619bca1c4eb9411533d613123618c0d127fae532595Jeff Garzik		goto done;
2620bca1c4eb9411533d613123618c0d127fae532595Jeff Garzik
26214447d35156169cf136e829eb6b5cac2d6370f2d9Tejun Heo	n_hc = mv_get_hc_count(host->ports[0]->flags);
2622bca1c4eb9411533d613123618c0d127fae532595Jeff Garzik
26234447d35156169cf136e829eb6b5cac2d6370f2d9Tejun Heo	for (port = 0; port < host->n_ports; port++)
262447c2b677daeed9c79ecb7167c211ff36876ea611Jeff Garzik		hpriv->ops->read_preamp(hpriv, port, mmio);
262520f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ
2626c9d39130123238ac18478a42e25cb7996eacfcc0Jeff Garzik	rc = hpriv->ops->reset_hc(hpriv, mmio, n_hc);
262747c2b677daeed9c79ecb7167c211ff36876ea611Jeff Garzik	if (rc)
262820f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ		goto done;
262920f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ
2630522479fb98c6667f081e75f87e298e413c0b1db8Jeff Garzik	hpriv->ops->reset_flash(hpriv, mmio);
2631522479fb98c6667f081e75f87e298e413c0b1db8Jeff Garzik	hpriv->ops->reset_bus(pdev, mmio);
263247c2b677daeed9c79ecb7167c211ff36876ea611Jeff Garzik	hpriv->ops->enable_leds(hpriv, mmio);
263320f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ
26344447d35156169cf136e829eb6b5cac2d6370f2d9Tejun Heo	for (port = 0; port < host->n_ports; port++) {
2635ee9ccdf70163ca6408f6965e0fbc65baeac7312cJeff Garzik		if (IS_GEN_II(hpriv)) {
2636c9d39130123238ac18478a42e25cb7996eacfcc0Jeff Garzik			void __iomem *port_mmio = mv_port_base(mmio, port);
2637c9d39130123238ac18478a42e25cb7996eacfcc0Jeff Garzik
26382a47ce06d534692f9bd2bf4e90a20fc9b1054c39Jeff Garzik			u32 ifctl = readl(port_mmio + SATA_INTERFACE_CTL);
2639eb46d684600ac145501805a294c94675e82eab2eMark Lord			ifctl |= (1 << 7);		/* enable gen2i speed */
2640eb46d684600ac145501805a294c94675e82eab2eMark Lord			ifctl = (ifctl & 0xfff) | 0x9b1000; /* from chip spec */
26412a47ce06d534692f9bd2bf4e90a20fc9b1054c39Jeff Garzik			writelfl(ifctl, port_mmio + SATA_INTERFACE_CTL);
26422a47ce06d534692f9bd2bf4e90a20fc9b1054c39Jeff Garzik		}
26432a47ce06d534692f9bd2bf4e90a20fc9b1054c39Jeff Garzik
2644c9d39130123238ac18478a42e25cb7996eacfcc0Jeff Garzik		hpriv->ops->phy_errata(hpriv, mmio, port);
26452a47ce06d534692f9bd2bf4e90a20fc9b1054c39Jeff Garzik	}
26462a47ce06d534692f9bd2bf4e90a20fc9b1054c39Jeff Garzik
26474447d35156169cf136e829eb6b5cac2d6370f2d9Tejun Heo	for (port = 0; port < host->n_ports; port++) {
2648cbcdd87593a1d85c5c4b259945a3a09eee12814dTejun Heo		struct ata_port *ap = host->ports[port];
26492a47ce06d534692f9bd2bf4e90a20fc9b1054c39Jeff Garzik		void __iomem *port_mmio = mv_port_base(mmio, port);
2650cbcdd87593a1d85c5c4b259945a3a09eee12814dTejun Heo		unsigned int offset = port_mmio - mmio;
2651cbcdd87593a1d85c5c4b259945a3a09eee12814dTejun Heo
2652cbcdd87593a1d85c5c4b259945a3a09eee12814dTejun Heo		mv_port_init(&ap->ioaddr, port_mmio);
2653cbcdd87593a1d85c5c4b259945a3a09eee12814dTejun Heo
2654cbcdd87593a1d85c5c4b259945a3a09eee12814dTejun Heo		ata_port_pbar_desc(ap, MV_PRIMARY_BAR, -1, "mmio");
2655cbcdd87593a1d85c5c4b259945a3a09eee12814dTejun Heo		ata_port_pbar_desc(ap, MV_PRIMARY_BAR, offset, "port");
265620f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ	}
265720f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ
265820f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ	for (hc = 0; hc < n_hc; hc++) {
265931961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ		void __iomem *hc_mmio = mv_hc_base(mmio, hc);
266031961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ
266131961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ		VPRINTK("HC%i: HC config=0x%08x HC IRQ cause "
266231961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ			"(before clear)=0x%08x\n", hc,
266331961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ			readl(hc_mmio + HC_CFG_OFS),
266431961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ			readl(hc_mmio + HC_IRQ_CAUSE_OFS));
266531961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ
266631961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ		/* Clear any currently outstanding hc interrupt conditions */
266731961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ		writelfl(0, hc_mmio + HC_IRQ_CAUSE_OFS);
266820f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ	}
266920f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ
267031961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ	/* Clear any currently outstanding host interrupt conditions */
267102a121da5a53d415b6596bc19cc6999d295d32a4Mark Lord	writelfl(0, mmio + hpriv->irq_cause_ofs);
267231961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ
267331961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ	/* and unmask interrupt generation for host regs */
267402a121da5a53d415b6596bc19cc6999d295d32a4Mark Lord	writelfl(hpriv->unmask_all_irqs, mmio + hpriv->irq_mask_ofs);
2675fb621e2fde735abab854586d52c96c5624bcb5b8Jeff Garzik
2676ee9ccdf70163ca6408f6965e0fbc65baeac7312cJeff Garzik	if (IS_GEN_I(hpriv))
2677fb621e2fde735abab854586d52c96c5624bcb5b8Jeff Garzik		writelfl(~HC_MAIN_MASKED_IRQS_5, mmio + HC_MAIN_IRQ_MASK_OFS);
2678fb621e2fde735abab854586d52c96c5624bcb5b8Jeff Garzik	else
2679fb621e2fde735abab854586d52c96c5624bcb5b8Jeff Garzik		writelfl(~HC_MAIN_MASKED_IRQS, mmio + HC_MAIN_IRQ_MASK_OFS);
268020f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ
268120f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ	VPRINTK("HC MAIN IRQ cause/mask=0x%08x/0x%08x "
26828b260248d9e0e8b64bb72fd4dee03ad86984c344Jeff Garzik		"PCI int cause/mask=0x%08x/0x%08x\n",
268320f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ		readl(mmio + HC_MAIN_IRQ_CAUSE_OFS),
268420f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ		readl(mmio + HC_MAIN_IRQ_MASK_OFS),
268502a121da5a53d415b6596bc19cc6999d295d32a4Mark Lord		readl(mmio + hpriv->irq_cause_ofs),
268602a121da5a53d415b6596bc19cc6999d295d32a4Mark Lord		readl(mmio + hpriv->irq_mask_ofs));
2687bca1c4eb9411533d613123618c0d127fae532595Jeff Garzik
268831961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russdone:
268920f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ	return rc;
269020f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ}
269120f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ
269205b308e1df6d9d673daedb517969241f41278b52Brett Russ/**
269305b308e1df6d9d673daedb517969241f41278b52Brett Russ *      mv_print_info - Dump key info to kernel log for perusal.
26944447d35156169cf136e829eb6b5cac2d6370f2d9Tejun Heo *      @host: ATA host to print info about
269505b308e1df6d9d673daedb517969241f41278b52Brett Russ *
269605b308e1df6d9d673daedb517969241f41278b52Brett Russ *      FIXME: complete this.
269705b308e1df6d9d673daedb517969241f41278b52Brett Russ *
269805b308e1df6d9d673daedb517969241f41278b52Brett Russ *      LOCKING:
269905b308e1df6d9d673daedb517969241f41278b52Brett Russ *      Inherited from caller.
270005b308e1df6d9d673daedb517969241f41278b52Brett Russ */
27014447d35156169cf136e829eb6b5cac2d6370f2d9Tejun Heostatic void mv_print_info(struct ata_host *host)
270231961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ{
27034447d35156169cf136e829eb6b5cac2d6370f2d9Tejun Heo	struct pci_dev *pdev = to_pci_dev(host->dev);
27044447d35156169cf136e829eb6b5cac2d6370f2d9Tejun Heo	struct mv_host_priv *hpriv = host->private_data;
270544c10138fd4bbc4b6d6bff0873c24902f2a9da65Auke Kok	u8 scc;
2706c1e4fe711a410a139095e6b3e3ce3f07f466063cJeff Garzik	const char *scc_s, *gen;
270731961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ
270831961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ	/* Use this to determine the HW stepping of the chip so we know
270931961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ	 * what errata to workaround
271031961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ	 */
271131961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ	pci_read_config_byte(pdev, PCI_CLASS_DEVICE, &scc);
271231961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ	if (scc == 0)
271331961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ		scc_s = "SCSI";
271431961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ	else if (scc == 0x01)
271531961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ		scc_s = "RAID";
271631961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ	else
2717c1e4fe711a410a139095e6b3e3ce3f07f466063cJeff Garzik		scc_s = "?";
2718c1e4fe711a410a139095e6b3e3ce3f07f466063cJeff Garzik
2719c1e4fe711a410a139095e6b3e3ce3f07f466063cJeff Garzik	if (IS_GEN_I(hpriv))
2720c1e4fe711a410a139095e6b3e3ce3f07f466063cJeff Garzik		gen = "I";
2721c1e4fe711a410a139095e6b3e3ce3f07f466063cJeff Garzik	else if (IS_GEN_II(hpriv))
2722c1e4fe711a410a139095e6b3e3ce3f07f466063cJeff Garzik		gen = "II";
2723c1e4fe711a410a139095e6b3e3ce3f07f466063cJeff Garzik	else if (IS_GEN_IIE(hpriv))
2724c1e4fe711a410a139095e6b3e3ce3f07f466063cJeff Garzik		gen = "IIE";
2725c1e4fe711a410a139095e6b3e3ce3f07f466063cJeff Garzik	else
2726c1e4fe711a410a139095e6b3e3ce3f07f466063cJeff Garzik		gen = "?";
272731961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ
2728a9524a76f70f3343e4be27f95a7e92a8ba5f9009Jeff Garzik	dev_printk(KERN_INFO, &pdev->dev,
2729c1e4fe711a410a139095e6b3e3ce3f07f466063cJeff Garzik	       "Gen-%s %u slots %u ports %s mode IRQ via %s\n",
2730c1e4fe711a410a139095e6b3e3ce3f07f466063cJeff Garzik	       gen, (unsigned)MV_MAX_Q_DEPTH, host->n_ports,
273131961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ	       scc_s, (MV_HP_FLAG_MSI & hpriv->hp_flags) ? "MSI" : "INTx");
273231961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ}
273331961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ
273405b308e1df6d9d673daedb517969241f41278b52Brett Russ/**
273505b308e1df6d9d673daedb517969241f41278b52Brett Russ *      mv_init_one - handle a positive probe of a Marvell host
273605b308e1df6d9d673daedb517969241f41278b52Brett Russ *      @pdev: PCI device found
273705b308e1df6d9d673daedb517969241f41278b52Brett Russ *      @ent: PCI device ID entry for the matched host
273805b308e1df6d9d673daedb517969241f41278b52Brett Russ *
273905b308e1df6d9d673daedb517969241f41278b52Brett Russ *      LOCKING:
274005b308e1df6d9d673daedb517969241f41278b52Brett Russ *      Inherited from caller.
274105b308e1df6d9d673daedb517969241f41278b52Brett Russ */
274220f733e7d75a16bffc34842b7682c9247dd5f954Brett Russstatic int mv_init_one(struct pci_dev *pdev, const struct pci_device_id *ent)
274320f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ{
27442dcb407e61458ded17503d6bd12b8c064965368bJeff Garzik	static int printed_version;
274520f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ	unsigned int board_idx = (unsigned int)ent->driver_data;
27464447d35156169cf136e829eb6b5cac2d6370f2d9Tejun Heo	const struct ata_port_info *ppi[] = { &mv_port_info[board_idx], NULL };
27474447d35156169cf136e829eb6b5cac2d6370f2d9Tejun Heo	struct ata_host *host;
27484447d35156169cf136e829eb6b5cac2d6370f2d9Tejun Heo	struct mv_host_priv *hpriv;
27494447d35156169cf136e829eb6b5cac2d6370f2d9Tejun Heo	int n_ports, rc;
275020f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ
2751a9524a76f70f3343e4be27f95a7e92a8ba5f9009Jeff Garzik	if (!printed_version++)
2752a9524a76f70f3343e4be27f95a7e92a8ba5f9009Jeff Garzik		dev_printk(KERN_INFO, &pdev->dev, "version " DRV_VERSION "\n");
275320f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ
27544447d35156169cf136e829eb6b5cac2d6370f2d9Tejun Heo	/* allocate host */
27554447d35156169cf136e829eb6b5cac2d6370f2d9Tejun Heo	n_ports = mv_get_hc_count(ppi[0]->flags) * MV_PORTS_PER_HC;
27564447d35156169cf136e829eb6b5cac2d6370f2d9Tejun Heo
27574447d35156169cf136e829eb6b5cac2d6370f2d9Tejun Heo	host = ata_host_alloc_pinfo(&pdev->dev, ppi, n_ports);
27584447d35156169cf136e829eb6b5cac2d6370f2d9Tejun Heo	hpriv = devm_kzalloc(&pdev->dev, sizeof(*hpriv), GFP_KERNEL);
27594447d35156169cf136e829eb6b5cac2d6370f2d9Tejun Heo	if (!host || !hpriv)
27604447d35156169cf136e829eb6b5cac2d6370f2d9Tejun Heo		return -ENOMEM;
27614447d35156169cf136e829eb6b5cac2d6370f2d9Tejun Heo	host->private_data = hpriv;
27624447d35156169cf136e829eb6b5cac2d6370f2d9Tejun Heo
27634447d35156169cf136e829eb6b5cac2d6370f2d9Tejun Heo	/* acquire resources */
276424dc5f33ea4b504cfbd23fa159a4cacba8e4d800Tejun Heo	rc = pcim_enable_device(pdev);
276524dc5f33ea4b504cfbd23fa159a4cacba8e4d800Tejun Heo	if (rc)
276620f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ		return rc;
276720f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ
27680d5ff566779f894ca9937231a181eb31e4adff0eTejun Heo	rc = pcim_iomap_regions(pdev, 1 << MV_PRIMARY_BAR, DRV_NAME);
27690d5ff566779f894ca9937231a181eb31e4adff0eTejun Heo	if (rc == -EBUSY)
277024dc5f33ea4b504cfbd23fa159a4cacba8e4d800Tejun Heo		pcim_pin_device(pdev);
27710d5ff566779f894ca9937231a181eb31e4adff0eTejun Heo	if (rc)
277224dc5f33ea4b504cfbd23fa159a4cacba8e4d800Tejun Heo		return rc;
27734447d35156169cf136e829eb6b5cac2d6370f2d9Tejun Heo	host->iomap = pcim_iomap_table(pdev);
277420f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ
2775d88184fb2348a50f7c34f5d49a901c875b2e0114Jeff Garzik	rc = pci_go_64(pdev);
2776d88184fb2348a50f7c34f5d49a901c875b2e0114Jeff Garzik	if (rc)
2777d88184fb2348a50f7c34f5d49a901c875b2e0114Jeff Garzik		return rc;
2778d88184fb2348a50f7c34f5d49a901c875b2e0114Jeff Garzik
277920f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ	/* initialize adapter */
27804447d35156169cf136e829eb6b5cac2d6370f2d9Tejun Heo	rc = mv_init_host(host, board_idx);
278124dc5f33ea4b504cfbd23fa159a4cacba8e4d800Tejun Heo	if (rc)
278224dc5f33ea4b504cfbd23fa159a4cacba8e4d800Tejun Heo		return rc;
278320f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ
278431961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ	/* Enable interrupts */
27856a59dcf8678cbc4106a8a6e158d7408a87691358Tejun Heo	if (msi && pci_enable_msi(pdev))
278631961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ		pci_intx(pdev, 1);
278720f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ
278831961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ	mv_dump_pci_cfg(pdev, 0x68);
27894447d35156169cf136e829eb6b5cac2d6370f2d9Tejun Heo	mv_print_info(host);
279020f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ
27914447d35156169cf136e829eb6b5cac2d6370f2d9Tejun Heo	pci_set_master(pdev);
2792ea8b4db97aa41a66c05daa4055a1974692ccd52dJeff Garzik	pci_try_set_mwi(pdev);
27934447d35156169cf136e829eb6b5cac2d6370f2d9Tejun Heo	return ata_host_activate(host, pdev->irq, mv_interrupt, IRQF_SHARED,
2794c5d3e45a2200a0905dc45b72714726b7aac3aaf1Jeff Garzik				 IS_GEN_I(hpriv) ? &mv5_sht : &mv6_sht);
279520f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ}
279620f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ
279720f733e7d75a16bffc34842b7682c9247dd5f954Brett Russstatic int __init mv_init(void)
279820f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ{
2799b7887196e38da54ff893897b80875d632d1a1114Pavel Roskin	return pci_register_driver(&mv_pci_driver);
280020f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ}
280120f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ
280220f733e7d75a16bffc34842b7682c9247dd5f954Brett Russstatic void __exit mv_exit(void)
280320f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ{
280420f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ	pci_unregister_driver(&mv_pci_driver);
280520f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ}
280620f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ
280720f733e7d75a16bffc34842b7682c9247dd5f954Brett RussMODULE_AUTHOR("Brett Russ");
280820f733e7d75a16bffc34842b7682c9247dd5f954Brett RussMODULE_DESCRIPTION("SCSI low-level driver for Marvell SATA controllers");
280920f733e7d75a16bffc34842b7682c9247dd5f954Brett RussMODULE_LICENSE("GPL");
281020f733e7d75a16bffc34842b7682c9247dd5f954Brett RussMODULE_DEVICE_TABLE(pci, mv_pci_tbl);
281120f733e7d75a16bffc34842b7682c9247dd5f954Brett RussMODULE_VERSION(DRV_VERSION);
281220f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ
2813ddef9bb367b19383df627e388cb4c01c86ddba6cJeff Garzikmodule_param(msi, int, 0444);
2814ddef9bb367b19383df627e388cb4c01c86ddba6cJeff GarzikMODULE_PARM_DESC(msi, "Enable use of PCI MSI (0=off, 1=on)");
2815ddef9bb367b19383df627e388cb4c01c86ddba6cJeff Garzik
281620f733e7d75a16bffc34842b7682c9247dd5f954Brett Russmodule_init(mv_init);
281720f733e7d75a16bffc34842b7682c9247dd5f954Brett Russmodule_exit(mv_exit);
2818