sata_mv.c revision f351b2d638c3cb0b95adde3549b7bfaf3f991dfa
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
321fd2e1c242acb4a589d59c77853897bdbb599186Mark Lord  2) Improve/fix IRQ and error handling sequences.
331fd2e1c242acb4a589d59c77853897bdbb599186Mark Lord
341fd2e1c242acb4a589d59c77853897bdbb599186Mark Lord  3) ATAPI support (Marvell claims the 60xx/70xx chips can do it).
351fd2e1c242acb4a589d59c77853897bdbb599186Mark Lord
361fd2e1c242acb4a589d59c77853897bdbb599186Mark Lord  4) Think about TCQ support here, and for libata in general
371fd2e1c242acb4a589d59c77853897bdbb599186Mark Lord  with controllers that suppport it via host-queuing hardware
381fd2e1c242acb4a589d59c77853897bdbb599186Mark Lord  (a software-only implementation could be a nightmare).
394a05e2091709dbb22b86a1b3343cd3fa3c0d7a6bJeff Garzik
404a05e2091709dbb22b86a1b3343cd3fa3c0d7a6bJeff Garzik  5) Investigate problems with PCI Message Signalled Interrupts (MSI).
414a05e2091709dbb22b86a1b3343cd3fa3c0d7a6bJeff Garzik
424a05e2091709dbb22b86a1b3343cd3fa3c0d7a6bJeff Garzik  6) Add port multiplier support (intermediate)
434a05e2091709dbb22b86a1b3343cd3fa3c0d7a6bJeff Garzik
444a05e2091709dbb22b86a1b3343cd3fa3c0d7a6bJeff Garzik  8) Develop a low-power-consumption strategy, and implement it.
454a05e2091709dbb22b86a1b3343cd3fa3c0d7a6bJeff Garzik
464a05e2091709dbb22b86a1b3343cd3fa3c0d7a6bJeff Garzik  9) [Experiment, low priority] See if ATAPI can be supported using
474a05e2091709dbb22b86a1b3343cd3fa3c0d7a6bJeff Garzik  "unknown FIS" or "vendor-specific FIS" support, or something creative
484a05e2091709dbb22b86a1b3343cd3fa3c0d7a6bJeff Garzik  like that.
494a05e2091709dbb22b86a1b3343cd3fa3c0d7a6bJeff Garzik
504a05e2091709dbb22b86a1b3343cd3fa3c0d7a6bJeff Garzik  10) [Experiment, low priority] Investigate interrupt coalescing.
514a05e2091709dbb22b86a1b3343cd3fa3c0d7a6bJeff Garzik  Quite often, especially with PCI Message Signalled Interrupts (MSI),
524a05e2091709dbb22b86a1b3343cd3fa3c0d7a6bJeff Garzik  the overhead reduced by interrupt mitigation is quite often not
534a05e2091709dbb22b86a1b3343cd3fa3c0d7a6bJeff Garzik  worth the latency cost.
544a05e2091709dbb22b86a1b3343cd3fa3c0d7a6bJeff Garzik
554a05e2091709dbb22b86a1b3343cd3fa3c0d7a6bJeff Garzik  11) [Experiment, Marvell value added] Is it possible to use target
564a05e2091709dbb22b86a1b3343cd3fa3c0d7a6bJeff Garzik  mode to cross-connect two Linux boxes with Marvell cards?  If so,
574a05e2091709dbb22b86a1b3343cd3fa3c0d7a6bJeff Garzik  creating LibATA target mode support would be very interesting.
584a05e2091709dbb22b86a1b3343cd3fa3c0d7a6bJeff Garzik
594a05e2091709dbb22b86a1b3343cd3fa3c0d7a6bJeff Garzik  Target mode, for those without docs, is the ability to directly
604a05e2091709dbb22b86a1b3343cd3fa3c0d7a6bJeff Garzik  connect two SATA controllers.
614a05e2091709dbb22b86a1b3343cd3fa3c0d7a6bJeff Garzik
624a05e2091709dbb22b86a1b3343cd3fa3c0d7a6bJeff Garzik*/
634a05e2091709dbb22b86a1b3343cd3fa3c0d7a6bJeff Garzik
644a05e2091709dbb22b86a1b3343cd3fa3c0d7a6bJeff Garzik
6520f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ#include <linux/kernel.h>
6620f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ#include <linux/module.h>
6720f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ#include <linux/pci.h>
6820f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ#include <linux/init.h>
6920f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ#include <linux/blkdev.h>
7020f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ#include <linux/delay.h>
7120f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ#include <linux/interrupt.h>
7220f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ#include <linux/dma-mapping.h>
73a9524a76f70f3343e4be27f95a7e92a8ba5f9009Jeff Garzik#include <linux/device.h>
74f351b2d638c3cb0b95adde3549b7bfaf3f991dfaSaeed Bishara#include <linux/platform_device.h>
75f351b2d638c3cb0b95adde3549b7bfaf3f991dfaSaeed Bishara#include <linux/ata_platform.h>
7620f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ#include <scsi/scsi_host.h>
77193515d51ccb363165d6b09e9ba5c21089e34badJeff Garzik#include <scsi/scsi_cmnd.h>
786c08772e49622e90d39903e7ff0be1a0f463ac86Jeff Garzik#include <scsi/scsi_device.h>
7920f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ#include <linux/libata.h>
8020f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ
8120f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ#define DRV_NAME	"sata_mv"
821fd2e1c242acb4a589d59c77853897bdbb599186Mark Lord#define DRV_VERSION	"1.20"
8320f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ
8420f733e7d75a16bffc34842b7682c9247dd5f954Brett Russenum {
8520f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ	/* BAR's are enumerated in terms of pci_resource_start() terms */
8620f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ	MV_PRIMARY_BAR		= 0,	/* offset 0x10: memory space */
8720f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ	MV_IO_BAR		= 2,	/* offset 0x18: IO space */
8820f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ	MV_MISC_BAR		= 3,	/* offset 0x1c: FLASH, NVRAM, SRAM */
8920f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ
9020f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ	MV_MAJOR_REG_AREA_SZ	= 0x10000,	/* 64KB */
9120f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ	MV_MINOR_REG_AREA_SZ	= 0x2000,	/* 8KB */
9220f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ
9320f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ	MV_PCI_REG_BASE		= 0,
9420f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ	MV_IRQ_COAL_REG_BASE	= 0x18000,	/* 6xxx part only */
95615ab95342f6245026d8974b9724f7ea57d9a184Mark Lord	MV_IRQ_COAL_CAUSE		= (MV_IRQ_COAL_REG_BASE + 0x08),
96615ab95342f6245026d8974b9724f7ea57d9a184Mark Lord	MV_IRQ_COAL_CAUSE_LO		= (MV_IRQ_COAL_REG_BASE + 0x88),
97615ab95342f6245026d8974b9724f7ea57d9a184Mark Lord	MV_IRQ_COAL_CAUSE_HI		= (MV_IRQ_COAL_REG_BASE + 0x8c),
98615ab95342f6245026d8974b9724f7ea57d9a184Mark Lord	MV_IRQ_COAL_THRESHOLD		= (MV_IRQ_COAL_REG_BASE + 0xcc),
99615ab95342f6245026d8974b9724f7ea57d9a184Mark Lord	MV_IRQ_COAL_TIME_THRESHOLD	= (MV_IRQ_COAL_REG_BASE + 0xd0),
100615ab95342f6245026d8974b9724f7ea57d9a184Mark Lord
10120f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ	MV_SATAHC0_REG_BASE	= 0x20000,
102522479fb98c6667f081e75f87e298e413c0b1db8Jeff Garzik	MV_FLASH_CTL		= 0x1046c,
103bca1c4eb9411533d613123618c0d127fae532595Jeff Garzik	MV_GPIO_PORT_CTL	= 0x104f0,
104bca1c4eb9411533d613123618c0d127fae532595Jeff Garzik	MV_RESET_CFG		= 0x180d8,
10520f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ
10620f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ	MV_PCI_REG_SZ		= MV_MAJOR_REG_AREA_SZ,
10720f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ	MV_SATAHC_REG_SZ	= MV_MAJOR_REG_AREA_SZ,
10820f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ	MV_SATAHC_ARBTR_REG_SZ	= MV_MINOR_REG_AREA_SZ,		/* arbiter */
10920f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ	MV_PORT_REG_SZ		= MV_MINOR_REG_AREA_SZ,
11020f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ
11131961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ	MV_MAX_Q_DEPTH		= 32,
11231961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ	MV_MAX_Q_DEPTH_MASK	= MV_MAX_Q_DEPTH - 1,
11331961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ
11431961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ	/* CRQB needs alignment on a 1KB boundary. Size == 1KB
11531961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ	 * CRPB needs alignment on a 256B boundary. Size == 256B
11631961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ	 * ePRD (SG) entries need alignment on a 16B boundary. Size == 16B
11731961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ	 */
11831961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ	MV_CRQB_Q_SZ		= (32 * MV_MAX_Q_DEPTH),
11931961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ	MV_CRPB_Q_SZ		= (8 * MV_MAX_Q_DEPTH),
120da2fa9baf06f33a8fa7aa3f56c9f2b4070ceca0eMark Lord	MV_MAX_SG_CT		= 256,
12131961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ	MV_SG_TBL_SZ		= (16 * MV_MAX_SG_CT),
12231961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ
12320f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ	MV_PORTS_PER_HC		= 4,
12420f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ	/* == (port / MV_PORTS_PER_HC) to determine HC from 0-7 port */
12520f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ	MV_PORT_HC_SHIFT	= 2,
12631961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ	/* == (port % MV_PORTS_PER_HC) to determine hard port from 0-7 port */
12720f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ	MV_PORT_MASK		= 3,
12820f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ
12920f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ	/* Host Flags */
13020f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ	MV_FLAG_DUAL_HC		= (1 << 30),  /* two SATA Host Controllers */
13120f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ	MV_FLAG_IRQ_COALESCE	= (1 << 29),  /* IRQ coalescing capability */
1327bb3c5290ca0ec9e65947c907495c2b56e895e46Saeed Bishara	/* SoC integrated controllers, no PCI interface */
1337bb3c5290ca0ec9e65947c907495c2b56e895e46Saeed Bishara	MV_FLAG_SOC = (1 << 28),
1347bb3c5290ca0ec9e65947c907495c2b56e895e46Saeed Bishara
135c5d3e45a2200a0905dc45b72714726b7aac3aaf1Jeff Garzik	MV_COMMON_FLAGS		= ATA_FLAG_SATA | ATA_FLAG_NO_LEGACY |
136bdd4dddee325a7dce3e84cf48201a06aa8508aa4Jeff Garzik				  ATA_FLAG_MMIO | ATA_FLAG_NO_ATAPI |
137bdd4dddee325a7dce3e84cf48201a06aa8508aa4Jeff Garzik				  ATA_FLAG_PIO_POLLING,
13847c2b677daeed9c79ecb7167c211ff36876ea611Jeff Garzik	MV_6XXX_FLAGS		= MV_FLAG_IRQ_COALESCE,
13920f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ
14031961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ	CRQB_FLAG_READ		= (1 << 0),
14131961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ	CRQB_TAG_SHIFT		= 1,
142c5d3e45a2200a0905dc45b72714726b7aac3aaf1Jeff Garzik	CRQB_IOID_SHIFT		= 6,	/* CRQB Gen-II/IIE IO Id shift */
143c5d3e45a2200a0905dc45b72714726b7aac3aaf1Jeff Garzik	CRQB_HOSTQ_SHIFT	= 17,	/* CRQB Gen-II/IIE HostQueTag shift */
14431961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ	CRQB_CMD_ADDR_SHIFT	= 8,
14531961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ	CRQB_CMD_CS		= (0x2 << 11),
14631961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ	CRQB_CMD_LAST		= (1 << 15),
14731961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ
14831961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ	CRPB_FLAG_STATUS_SHIFT	= 8,
149c5d3e45a2200a0905dc45b72714726b7aac3aaf1Jeff Garzik	CRPB_IOID_SHIFT_6	= 5,	/* CRPB Gen-II IO Id shift */
150c5d3e45a2200a0905dc45b72714726b7aac3aaf1Jeff Garzik	CRPB_IOID_SHIFT_7	= 7,	/* CRPB Gen-IIE IO Id shift */
15131961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ
15231961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ	EPRD_FLAG_END_OF_TBL	= (1 << 31),
15331961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ
15420f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ	/* PCI interface registers */
15520f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ
15631961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ	PCI_COMMAND_OFS		= 0xc00,
15731961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ
15820f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ	PCI_MAIN_CMD_STS_OFS	= 0xd30,
15920f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ	STOP_PCI_MASTER		= (1 << 2),
16020f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ	PCI_MASTER_EMPTY	= (1 << 3),
16120f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ	GLOB_SFT_RST		= (1 << 4),
16220f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ
163522479fb98c6667f081e75f87e298e413c0b1db8Jeff Garzik	MV_PCI_MODE		= 0xd00,
164522479fb98c6667f081e75f87e298e413c0b1db8Jeff Garzik	MV_PCI_EXP_ROM_BAR_CTL	= 0xd2c,
165522479fb98c6667f081e75f87e298e413c0b1db8Jeff Garzik	MV_PCI_DISC_TIMER	= 0xd04,
166522479fb98c6667f081e75f87e298e413c0b1db8Jeff Garzik	MV_PCI_MSI_TRIGGER	= 0xc38,
167522479fb98c6667f081e75f87e298e413c0b1db8Jeff Garzik	MV_PCI_SERR_MASK	= 0xc28,
168522479fb98c6667f081e75f87e298e413c0b1db8Jeff Garzik	MV_PCI_XBAR_TMOUT	= 0x1d04,
169522479fb98c6667f081e75f87e298e413c0b1db8Jeff Garzik	MV_PCI_ERR_LOW_ADDRESS	= 0x1d40,
170522479fb98c6667f081e75f87e298e413c0b1db8Jeff Garzik	MV_PCI_ERR_HIGH_ADDRESS	= 0x1d44,
171522479fb98c6667f081e75f87e298e413c0b1db8Jeff Garzik	MV_PCI_ERR_ATTRIBUTE	= 0x1d48,
172522479fb98c6667f081e75f87e298e413c0b1db8Jeff Garzik	MV_PCI_ERR_COMMAND	= 0x1d50,
173522479fb98c6667f081e75f87e298e413c0b1db8Jeff Garzik
17402a121da5a53d415b6596bc19cc6999d295d32a4Mark Lord	PCI_IRQ_CAUSE_OFS	= 0x1d58,
17502a121da5a53d415b6596bc19cc6999d295d32a4Mark Lord	PCI_IRQ_MASK_OFS	= 0x1d5c,
17620f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ	PCI_UNMASK_ALL_IRQS	= 0x7fffff,	/* bits 22-0 */
17720f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ
17802a121da5a53d415b6596bc19cc6999d295d32a4Mark Lord	PCIE_IRQ_CAUSE_OFS	= 0x1900,
17902a121da5a53d415b6596bc19cc6999d295d32a4Mark Lord	PCIE_IRQ_MASK_OFS	= 0x1910,
180646a4da514f2555298481cb00dc5b3eb02b21b72Mark Lord	PCIE_UNMASK_ALL_IRQS	= 0x40a,	/* assorted bits */
18102a121da5a53d415b6596bc19cc6999d295d32a4Mark Lord
18220f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ	HC_MAIN_IRQ_CAUSE_OFS	= 0x1d60,
18320f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ	HC_MAIN_IRQ_MASK_OFS	= 0x1d64,
184f351b2d638c3cb0b95adde3549b7bfaf3f991dfaSaeed Bishara	HC_SOC_MAIN_IRQ_CAUSE_OFS = 0x20020,
185f351b2d638c3cb0b95adde3549b7bfaf3f991dfaSaeed Bishara	HC_SOC_MAIN_IRQ_MASK_OFS = 0x20024,
18620f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ	PORT0_ERR		= (1 << 0),	/* shift by port # */
18720f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ	PORT0_DONE		= (1 << 1),	/* shift by port # */
18820f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ	HC0_IRQ_PEND		= 0x1ff,	/* bits 0-8 = HC0's ports */
18920f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ	HC_SHIFT		= 9,		/* bits 9-17 = HC1's ports */
19020f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ	PCI_ERR			= (1 << 18),
19120f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ	TRAN_LO_DONE		= (1 << 19),	/* 6xxx: IRQ coalescing */
19220f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ	TRAN_HI_DONE		= (1 << 20),	/* 6xxx: IRQ coalescing */
193fb621e2fde735abab854586d52c96c5624bcb5b8Jeff Garzik	PORTS_0_3_COAL_DONE	= (1 << 8),
194fb621e2fde735abab854586d52c96c5624bcb5b8Jeff Garzik	PORTS_4_7_COAL_DONE	= (1 << 17),
19520f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ	PORTS_0_7_COAL_DONE	= (1 << 21),	/* 6xxx: IRQ coalescing */
19620f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ	GPIO_INT		= (1 << 22),
19720f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ	SELF_INT		= (1 << 23),
19820f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ	TWSI_INT		= (1 << 24),
19920f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ	HC_MAIN_RSVD		= (0x7f << 25),	/* bits 31-25 */
200fb621e2fde735abab854586d52c96c5624bcb5b8Jeff Garzik	HC_MAIN_RSVD_5		= (0x1fff << 19), /* bits 31-19 */
201f351b2d638c3cb0b95adde3549b7bfaf3f991dfaSaeed Bishara	HC_MAIN_RSVD_SOC 	= (0x3fffffb << 6),     /* bits 31-9, 7-6 */
2028b260248d9e0e8b64bb72fd4dee03ad86984c344Jeff Garzik	HC_MAIN_MASKED_IRQS	= (TRAN_LO_DONE | TRAN_HI_DONE |
20320f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ				   PORTS_0_7_COAL_DONE | GPIO_INT | TWSI_INT |
20420f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ				   HC_MAIN_RSVD),
205fb621e2fde735abab854586d52c96c5624bcb5b8Jeff Garzik	HC_MAIN_MASKED_IRQS_5	= (PORTS_0_3_COAL_DONE | PORTS_4_7_COAL_DONE |
206fb621e2fde735abab854586d52c96c5624bcb5b8Jeff Garzik				   HC_MAIN_RSVD_5),
207f351b2d638c3cb0b95adde3549b7bfaf3f991dfaSaeed Bishara	HC_MAIN_MASKED_IRQS_SOC = (PORTS_0_3_COAL_DONE | HC_MAIN_RSVD_SOC),
20820f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ
20920f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ	/* SATAHC registers */
21020f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ	HC_CFG_OFS		= 0,
21120f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ
21220f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ	HC_IRQ_CAUSE_OFS	= 0x14,
21331961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ	CRPB_DMA_DONE		= (1 << 0),	/* shift by port # */
21420f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ	HC_IRQ_COAL		= (1 << 4),	/* IRQ coalescing */
21520f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ	DEV_IRQ			= (1 << 8),	/* shift by port # */
21620f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ
21720f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ	/* Shadow block registers */
21831961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ	SHD_BLK_OFS		= 0x100,
21931961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ	SHD_CTL_AST_OFS		= 0x20,		/* ofs from SHD_BLK_OFS */
22020f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ
22120f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ	/* SATA registers */
22220f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ	SATA_STATUS_OFS		= 0x300,  /* ctrl, err regs follow status */
22320f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ	SATA_ACTIVE_OFS		= 0x350,
2240c58912e192fc3a4835d772aafa40b72552b819fMark Lord	SATA_FIS_IRQ_CAUSE_OFS	= 0x364,
22547c2b677daeed9c79ecb7167c211ff36876ea611Jeff Garzik	PHY_MODE3		= 0x310,
226bca1c4eb9411533d613123618c0d127fae532595Jeff Garzik	PHY_MODE4		= 0x314,
227bca1c4eb9411533d613123618c0d127fae532595Jeff Garzik	PHY_MODE2		= 0x330,
228c9d39130123238ac18478a42e25cb7996eacfcc0Jeff Garzik	MV5_PHY_MODE		= 0x74,
229c9d39130123238ac18478a42e25cb7996eacfcc0Jeff Garzik	MV5_LT_MODE		= 0x30,
230c9d39130123238ac18478a42e25cb7996eacfcc0Jeff Garzik	MV5_PHY_CTL		= 0x0C,
231bca1c4eb9411533d613123618c0d127fae532595Jeff Garzik	SATA_INTERFACE_CTL	= 0x050,
232bca1c4eb9411533d613123618c0d127fae532595Jeff Garzik
233bca1c4eb9411533d613123618c0d127fae532595Jeff Garzik	MV_M2_PREAMP_MASK	= 0x7e0,
23420f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ
23520f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ	/* Port registers */
23620f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ	EDMA_CFG_OFS		= 0,
2370c58912e192fc3a4835d772aafa40b72552b819fMark Lord	EDMA_CFG_Q_DEPTH	= 0x1f,		/* max device queue depth */
2380c58912e192fc3a4835d772aafa40b72552b819fMark Lord	EDMA_CFG_NCQ		= (1 << 5),	/* for R/W FPDMA queued */
2390c58912e192fc3a4835d772aafa40b72552b819fMark Lord	EDMA_CFG_NCQ_GO_ON_ERR	= (1 << 14),	/* continue on error */
2400c58912e192fc3a4835d772aafa40b72552b819fMark Lord	EDMA_CFG_RD_BRST_EXT	= (1 << 11),	/* read burst 512B */
2410c58912e192fc3a4835d772aafa40b72552b819fMark Lord	EDMA_CFG_WR_BUFF_LEN	= (1 << 13),	/* write buffer 512B */
24220f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ
24320f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ	EDMA_ERR_IRQ_CAUSE_OFS	= 0x8,
24420f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ	EDMA_ERR_IRQ_MASK_OFS	= 0xc,
2456c1153e00af8de755ec278d873a97c9ce2a72d10Jeff Garzik	EDMA_ERR_D_PAR		= (1 << 0),	/* UDMA data parity err */
2466c1153e00af8de755ec278d873a97c9ce2a72d10Jeff Garzik	EDMA_ERR_PRD_PAR	= (1 << 1),	/* UDMA PRD parity err */
2476c1153e00af8de755ec278d873a97c9ce2a72d10Jeff Garzik	EDMA_ERR_DEV		= (1 << 2),	/* device error */
2486c1153e00af8de755ec278d873a97c9ce2a72d10Jeff Garzik	EDMA_ERR_DEV_DCON	= (1 << 3),	/* device disconnect */
2496c1153e00af8de755ec278d873a97c9ce2a72d10Jeff Garzik	EDMA_ERR_DEV_CON	= (1 << 4),	/* device connected */
2506c1153e00af8de755ec278d873a97c9ce2a72d10Jeff Garzik	EDMA_ERR_SERR		= (1 << 5),	/* SError bits [WBDST] raised */
251c5d3e45a2200a0905dc45b72714726b7aac3aaf1Jeff Garzik	EDMA_ERR_SELF_DIS	= (1 << 7),	/* Gen II/IIE self-disable */
252c5d3e45a2200a0905dc45b72714726b7aac3aaf1Jeff Garzik	EDMA_ERR_SELF_DIS_5	= (1 << 8),	/* Gen I self-disable */
2536c1153e00af8de755ec278d873a97c9ce2a72d10Jeff Garzik	EDMA_ERR_BIST_ASYNC	= (1 << 8),	/* BIST FIS or Async Notify */
254c5d3e45a2200a0905dc45b72714726b7aac3aaf1Jeff Garzik	EDMA_ERR_TRANS_IRQ_7	= (1 << 8),	/* Gen IIE transprt layer irq */
2556c1153e00af8de755ec278d873a97c9ce2a72d10Jeff Garzik	EDMA_ERR_CRQB_PAR	= (1 << 9),	/* CRQB parity error */
2566c1153e00af8de755ec278d873a97c9ce2a72d10Jeff Garzik	EDMA_ERR_CRPB_PAR	= (1 << 10),	/* CRPB parity error */
2576c1153e00af8de755ec278d873a97c9ce2a72d10Jeff Garzik	EDMA_ERR_INTRL_PAR	= (1 << 11),	/* internal parity error */
2586c1153e00af8de755ec278d873a97c9ce2a72d10Jeff Garzik	EDMA_ERR_IORDY		= (1 << 12),	/* IORdy timeout */
259646a4da514f2555298481cb00dc5b3eb02b21b72Mark Lord
2606c1153e00af8de755ec278d873a97c9ce2a72d10Jeff Garzik	EDMA_ERR_LNK_CTRL_RX	= (0xf << 13),	/* link ctrl rx error */
261646a4da514f2555298481cb00dc5b3eb02b21b72Mark Lord	EDMA_ERR_LNK_CTRL_RX_0	= (1 << 13),	/* transient: CRC err */
262646a4da514f2555298481cb00dc5b3eb02b21b72Mark Lord	EDMA_ERR_LNK_CTRL_RX_1	= (1 << 14),	/* transient: FIFO err */
263646a4da514f2555298481cb00dc5b3eb02b21b72Mark Lord	EDMA_ERR_LNK_CTRL_RX_2	= (1 << 15),	/* fatal: caught SYNC */
264646a4da514f2555298481cb00dc5b3eb02b21b72Mark Lord	EDMA_ERR_LNK_CTRL_RX_3	= (1 << 16),	/* transient: FIS rx err */
265646a4da514f2555298481cb00dc5b3eb02b21b72Mark Lord
2666c1153e00af8de755ec278d873a97c9ce2a72d10Jeff Garzik	EDMA_ERR_LNK_DATA_RX	= (0xf << 17),	/* link data rx error */
267646a4da514f2555298481cb00dc5b3eb02b21b72Mark Lord
2686c1153e00af8de755ec278d873a97c9ce2a72d10Jeff Garzik	EDMA_ERR_LNK_CTRL_TX	= (0x1f << 21),	/* link ctrl tx error */
269646a4da514f2555298481cb00dc5b3eb02b21b72Mark Lord	EDMA_ERR_LNK_CTRL_TX_0	= (1 << 21),	/* transient: CRC err */
270646a4da514f2555298481cb00dc5b3eb02b21b72Mark Lord	EDMA_ERR_LNK_CTRL_TX_1	= (1 << 22),	/* transient: FIFO err */
271646a4da514f2555298481cb00dc5b3eb02b21b72Mark Lord	EDMA_ERR_LNK_CTRL_TX_2	= (1 << 23),	/* transient: caught SYNC */
272646a4da514f2555298481cb00dc5b3eb02b21b72Mark Lord	EDMA_ERR_LNK_CTRL_TX_3	= (1 << 24),	/* transient: caught DMAT */
273646a4da514f2555298481cb00dc5b3eb02b21b72Mark Lord	EDMA_ERR_LNK_CTRL_TX_4	= (1 << 25),	/* transient: FIS collision */
274646a4da514f2555298481cb00dc5b3eb02b21b72Mark Lord
2756c1153e00af8de755ec278d873a97c9ce2a72d10Jeff Garzik	EDMA_ERR_LNK_DATA_TX	= (0x1f << 26),	/* link data tx error */
276646a4da514f2555298481cb00dc5b3eb02b21b72Mark Lord
2776c1153e00af8de755ec278d873a97c9ce2a72d10Jeff Garzik	EDMA_ERR_TRANS_PROTO	= (1 << 31),	/* transport protocol error */
278c5d3e45a2200a0905dc45b72714726b7aac3aaf1Jeff Garzik	EDMA_ERR_OVERRUN_5	= (1 << 5),
279c5d3e45a2200a0905dc45b72714726b7aac3aaf1Jeff Garzik	EDMA_ERR_UNDERRUN_5	= (1 << 6),
280646a4da514f2555298481cb00dc5b3eb02b21b72Mark Lord
281646a4da514f2555298481cb00dc5b3eb02b21b72Mark Lord	EDMA_ERR_IRQ_TRANSIENT  = EDMA_ERR_LNK_CTRL_RX_0 |
282646a4da514f2555298481cb00dc5b3eb02b21b72Mark Lord				  EDMA_ERR_LNK_CTRL_RX_1 |
283646a4da514f2555298481cb00dc5b3eb02b21b72Mark Lord				  EDMA_ERR_LNK_CTRL_RX_3 |
284646a4da514f2555298481cb00dc5b3eb02b21b72Mark Lord				  EDMA_ERR_LNK_CTRL_TX,
285646a4da514f2555298481cb00dc5b3eb02b21b72Mark Lord
286bdd4dddee325a7dce3e84cf48201a06aa8508aa4Jeff Garzik	EDMA_EH_FREEZE		= EDMA_ERR_D_PAR |
287bdd4dddee325a7dce3e84cf48201a06aa8508aa4Jeff Garzik				  EDMA_ERR_PRD_PAR |
288bdd4dddee325a7dce3e84cf48201a06aa8508aa4Jeff Garzik				  EDMA_ERR_DEV_DCON |
289bdd4dddee325a7dce3e84cf48201a06aa8508aa4Jeff Garzik				  EDMA_ERR_DEV_CON |
290bdd4dddee325a7dce3e84cf48201a06aa8508aa4Jeff Garzik				  EDMA_ERR_SERR |
291bdd4dddee325a7dce3e84cf48201a06aa8508aa4Jeff Garzik				  EDMA_ERR_SELF_DIS |
2926c1153e00af8de755ec278d873a97c9ce2a72d10Jeff Garzik				  EDMA_ERR_CRQB_PAR |
293bdd4dddee325a7dce3e84cf48201a06aa8508aa4Jeff Garzik				  EDMA_ERR_CRPB_PAR |
294bdd4dddee325a7dce3e84cf48201a06aa8508aa4Jeff Garzik				  EDMA_ERR_INTRL_PAR |
295bdd4dddee325a7dce3e84cf48201a06aa8508aa4Jeff Garzik				  EDMA_ERR_IORDY |
296bdd4dddee325a7dce3e84cf48201a06aa8508aa4Jeff Garzik				  EDMA_ERR_LNK_CTRL_RX_2 |
297bdd4dddee325a7dce3e84cf48201a06aa8508aa4Jeff Garzik				  EDMA_ERR_LNK_DATA_RX |
298bdd4dddee325a7dce3e84cf48201a06aa8508aa4Jeff Garzik				  EDMA_ERR_LNK_DATA_TX |
299bdd4dddee325a7dce3e84cf48201a06aa8508aa4Jeff Garzik				  EDMA_ERR_TRANS_PROTO,
300bdd4dddee325a7dce3e84cf48201a06aa8508aa4Jeff Garzik	EDMA_EH_FREEZE_5	= EDMA_ERR_D_PAR |
301bdd4dddee325a7dce3e84cf48201a06aa8508aa4Jeff Garzik				  EDMA_ERR_PRD_PAR |
302bdd4dddee325a7dce3e84cf48201a06aa8508aa4Jeff Garzik				  EDMA_ERR_DEV_DCON |
303bdd4dddee325a7dce3e84cf48201a06aa8508aa4Jeff Garzik				  EDMA_ERR_DEV_CON |
304bdd4dddee325a7dce3e84cf48201a06aa8508aa4Jeff Garzik				  EDMA_ERR_OVERRUN_5 |
305bdd4dddee325a7dce3e84cf48201a06aa8508aa4Jeff Garzik				  EDMA_ERR_UNDERRUN_5 |
306bdd4dddee325a7dce3e84cf48201a06aa8508aa4Jeff Garzik				  EDMA_ERR_SELF_DIS_5 |
3076c1153e00af8de755ec278d873a97c9ce2a72d10Jeff Garzik				  EDMA_ERR_CRQB_PAR |
308bdd4dddee325a7dce3e84cf48201a06aa8508aa4Jeff Garzik				  EDMA_ERR_CRPB_PAR |
309bdd4dddee325a7dce3e84cf48201a06aa8508aa4Jeff Garzik				  EDMA_ERR_INTRL_PAR |
310bdd4dddee325a7dce3e84cf48201a06aa8508aa4Jeff Garzik				  EDMA_ERR_IORDY,
31120f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ
31231961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ	EDMA_REQ_Q_BASE_HI_OFS	= 0x10,
31331961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ	EDMA_REQ_Q_IN_PTR_OFS	= 0x14,		/* also contains BASE_LO */
31431961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ
31531961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ	EDMA_REQ_Q_OUT_PTR_OFS	= 0x18,
31631961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ	EDMA_REQ_Q_PTR_SHIFT	= 5,
31731961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ
31831961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ	EDMA_RSP_Q_BASE_HI_OFS	= 0x1c,
31931961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ	EDMA_RSP_Q_IN_PTR_OFS	= 0x20,
32031961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ	EDMA_RSP_Q_OUT_PTR_OFS	= 0x24,		/* also contains BASE_LO */
32131961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ	EDMA_RSP_Q_PTR_SHIFT	= 3,
32231961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ
3230ea9e179f436f153fc19fdaef7abbc1e0da20762Jeff Garzik	EDMA_CMD_OFS		= 0x28,		/* EDMA command register */
3240ea9e179f436f153fc19fdaef7abbc1e0da20762Jeff Garzik	EDMA_EN			= (1 << 0),	/* enable EDMA */
3250ea9e179f436f153fc19fdaef7abbc1e0da20762Jeff Garzik	EDMA_DS			= (1 << 1),	/* disable EDMA; self-negated */
3260ea9e179f436f153fc19fdaef7abbc1e0da20762Jeff Garzik	ATA_RST			= (1 << 2),	/* reset trans/link/phy */
32720f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ
328c9d39130123238ac18478a42e25cb7996eacfcc0Jeff Garzik	EDMA_IORDY_TMOUT	= 0x34,
329bca1c4eb9411533d613123618c0d127fae532595Jeff Garzik	EDMA_ARB_CFG		= 0x38,
330bca1c4eb9411533d613123618c0d127fae532595Jeff Garzik
33131961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ	/* Host private flags (hp_flags) */
33231961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ	MV_HP_FLAG_MSI		= (1 << 0),
33347c2b677daeed9c79ecb7167c211ff36876ea611Jeff Garzik	MV_HP_ERRATA_50XXB0	= (1 << 1),
33447c2b677daeed9c79ecb7167c211ff36876ea611Jeff Garzik	MV_HP_ERRATA_50XXB2	= (1 << 2),
33547c2b677daeed9c79ecb7167c211ff36876ea611Jeff Garzik	MV_HP_ERRATA_60X1B2	= (1 << 3),
33647c2b677daeed9c79ecb7167c211ff36876ea611Jeff Garzik	MV_HP_ERRATA_60X1C0	= (1 << 4),
337e4e7b89280d1d666e2c09e5ad36cf071796c4c7eJeff Garzik	MV_HP_ERRATA_XX42A0	= (1 << 5),
3380ea9e179f436f153fc19fdaef7abbc1e0da20762Jeff Garzik	MV_HP_GEN_I		= (1 << 6),	/* Generation I: 50xx */
3390ea9e179f436f153fc19fdaef7abbc1e0da20762Jeff Garzik	MV_HP_GEN_II		= (1 << 7),	/* Generation II: 60xx */
3400ea9e179f436f153fc19fdaef7abbc1e0da20762Jeff Garzik	MV_HP_GEN_IIE		= (1 << 8),	/* Generation IIE: 6042/7042 */
34102a121da5a53d415b6596bc19cc6999d295d32a4Mark Lord	MV_HP_PCIE		= (1 << 9),	/* PCIe bus/regs: 7042 */
34220f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ
34331961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ	/* Port private flags (pp_flags) */
3440ea9e179f436f153fc19fdaef7abbc1e0da20762Jeff Garzik	MV_PP_FLAG_EDMA_EN	= (1 << 0),	/* is EDMA engine enabled? */
345721091685f853ba4e6c49f26f989db0b1a811250Mark Lord	MV_PP_FLAG_NCQ_EN	= (1 << 1),	/* is EDMA set up for NCQ? */
3460ea9e179f436f153fc19fdaef7abbc1e0da20762Jeff Garzik	MV_PP_FLAG_HAD_A_RESET	= (1 << 2),	/* 1st hard reset complete? */
34720f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ};
34820f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ
349ee9ccdf70163ca6408f6965e0fbc65baeac7312cJeff Garzik#define IS_GEN_I(hpriv) ((hpriv)->hp_flags & MV_HP_GEN_I)
350ee9ccdf70163ca6408f6965e0fbc65baeac7312cJeff Garzik#define IS_GEN_II(hpriv) ((hpriv)->hp_flags & MV_HP_GEN_II)
351e4e7b89280d1d666e2c09e5ad36cf071796c4c7eJeff Garzik#define IS_GEN_IIE(hpriv) ((hpriv)->hp_flags & MV_HP_GEN_IIE)
3527bb3c5290ca0ec9e65947c907495c2b56e895e46Saeed Bishara#define HAS_PCI(host) (!((host)->ports[0]->flags & MV_FLAG_SOC))
353bca1c4eb9411533d613123618c0d127fae532595Jeff Garzik
354095fec887eaa1c38d17c0c929a6733c744a9fa1fJeff Garzikenum {
355baf14aa14efcfdb5a74d5cf804691086c6bec743Jeff Garzik	/* DMA boundary 0xffff is required by the s/g splitting
356baf14aa14efcfdb5a74d5cf804691086c6bec743Jeff Garzik	 * we need on /length/ in mv_fill-sg().
357baf14aa14efcfdb5a74d5cf804691086c6bec743Jeff Garzik	 */
358baf14aa14efcfdb5a74d5cf804691086c6bec743Jeff Garzik	MV_DMA_BOUNDARY		= 0xffffU,
359095fec887eaa1c38d17c0c929a6733c744a9fa1fJeff Garzik
3600ea9e179f436f153fc19fdaef7abbc1e0da20762Jeff Garzik	/* mask of register bits containing lower 32 bits
3610ea9e179f436f153fc19fdaef7abbc1e0da20762Jeff Garzik	 * of EDMA request queue DMA address
3620ea9e179f436f153fc19fdaef7abbc1e0da20762Jeff Garzik	 */
363095fec887eaa1c38d17c0c929a6733c744a9fa1fJeff Garzik	EDMA_REQ_Q_BASE_LO_MASK	= 0xfffffc00U,
364095fec887eaa1c38d17c0c929a6733c744a9fa1fJeff Garzik
3650ea9e179f436f153fc19fdaef7abbc1e0da20762Jeff Garzik	/* ditto, for response queue */
366095fec887eaa1c38d17c0c929a6733c744a9fa1fJeff Garzik	EDMA_RSP_Q_BASE_LO_MASK	= 0xffffff00U,
367095fec887eaa1c38d17c0c929a6733c744a9fa1fJeff Garzik};
368095fec887eaa1c38d17c0c929a6733c744a9fa1fJeff Garzik
369522479fb98c6667f081e75f87e298e413c0b1db8Jeff Garzikenum chip_type {
370522479fb98c6667f081e75f87e298e413c0b1db8Jeff Garzik	chip_504x,
371522479fb98c6667f081e75f87e298e413c0b1db8Jeff Garzik	chip_508x,
372522479fb98c6667f081e75f87e298e413c0b1db8Jeff Garzik	chip_5080,
373522479fb98c6667f081e75f87e298e413c0b1db8Jeff Garzik	chip_604x,
374522479fb98c6667f081e75f87e298e413c0b1db8Jeff Garzik	chip_608x,
375e4e7b89280d1d666e2c09e5ad36cf071796c4c7eJeff Garzik	chip_6042,
376e4e7b89280d1d666e2c09e5ad36cf071796c4c7eJeff Garzik	chip_7042,
377f351b2d638c3cb0b95adde3549b7bfaf3f991dfaSaeed Bishara	chip_soc,
378522479fb98c6667f081e75f87e298e413c0b1db8Jeff Garzik};
379522479fb98c6667f081e75f87e298e413c0b1db8Jeff Garzik
38031961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ/* Command ReQuest Block: 32B */
38131961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russstruct mv_crqb {
382e14698745dd0de1ddbf5cd0cca4313a90f8c1cc1Mark Lord	__le32			sg_addr;
383e14698745dd0de1ddbf5cd0cca4313a90f8c1cc1Mark Lord	__le32			sg_addr_hi;
384e14698745dd0de1ddbf5cd0cca4313a90f8c1cc1Mark Lord	__le16			ctrl_flags;
385e14698745dd0de1ddbf5cd0cca4313a90f8c1cc1Mark Lord	__le16			ata_cmd[11];
38631961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ};
38720f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ
388e4e7b89280d1d666e2c09e5ad36cf071796c4c7eJeff Garzikstruct mv_crqb_iie {
389e14698745dd0de1ddbf5cd0cca4313a90f8c1cc1Mark Lord	__le32			addr;
390e14698745dd0de1ddbf5cd0cca4313a90f8c1cc1Mark Lord	__le32			addr_hi;
391e14698745dd0de1ddbf5cd0cca4313a90f8c1cc1Mark Lord	__le32			flags;
392e14698745dd0de1ddbf5cd0cca4313a90f8c1cc1Mark Lord	__le32			len;
393e14698745dd0de1ddbf5cd0cca4313a90f8c1cc1Mark Lord	__le32			ata_cmd[4];
394e4e7b89280d1d666e2c09e5ad36cf071796c4c7eJeff Garzik};
395e4e7b89280d1d666e2c09e5ad36cf071796c4c7eJeff Garzik
39631961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ/* Command ResPonse Block: 8B */
39731961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russstruct mv_crpb {
398e14698745dd0de1ddbf5cd0cca4313a90f8c1cc1Mark Lord	__le16			id;
399e14698745dd0de1ddbf5cd0cca4313a90f8c1cc1Mark Lord	__le16			flags;
400e14698745dd0de1ddbf5cd0cca4313a90f8c1cc1Mark Lord	__le32			tmstmp;
40120f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ};
40220f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ
40331961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ/* EDMA Physical Region Descriptor (ePRD); A.K.A. SG */
40431961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russstruct mv_sg {
405e14698745dd0de1ddbf5cd0cca4313a90f8c1cc1Mark Lord	__le32			addr;
406e14698745dd0de1ddbf5cd0cca4313a90f8c1cc1Mark Lord	__le32			flags_size;
407e14698745dd0de1ddbf5cd0cca4313a90f8c1cc1Mark Lord	__le32			addr_hi;
408e14698745dd0de1ddbf5cd0cca4313a90f8c1cc1Mark Lord	__le32			reserved;
40931961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ};
41020f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ
41131961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russstruct mv_port_priv {
41231961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ	struct mv_crqb		*crqb;
41331961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ	dma_addr_t		crqb_dma;
41431961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ	struct mv_crpb		*crpb;
41531961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ	dma_addr_t		crpb_dma;
416eb73d558d1c1c931de0b3a86af962c77d74ef688Mark Lord	struct mv_sg		*sg_tbl[MV_MAX_Q_DEPTH];
417eb73d558d1c1c931de0b3a86af962c77d74ef688Mark Lord	dma_addr_t		sg_tbl_dma[MV_MAX_Q_DEPTH];
418bdd4dddee325a7dce3e84cf48201a06aa8508aa4Jeff Garzik
419bdd4dddee325a7dce3e84cf48201a06aa8508aa4Jeff Garzik	unsigned int		req_idx;
420bdd4dddee325a7dce3e84cf48201a06aa8508aa4Jeff Garzik	unsigned int		resp_idx;
421bdd4dddee325a7dce3e84cf48201a06aa8508aa4Jeff Garzik
42231961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ	u32			pp_flags;
42331961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ};
42431961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ
425bca1c4eb9411533d613123618c0d127fae532595Jeff Garzikstruct mv_port_signal {
426bca1c4eb9411533d613123618c0d127fae532595Jeff Garzik	u32			amps;
427bca1c4eb9411533d613123618c0d127fae532595Jeff Garzik	u32			pre;
428bca1c4eb9411533d613123618c0d127fae532595Jeff Garzik};
429bca1c4eb9411533d613123618c0d127fae532595Jeff Garzik
43002a121da5a53d415b6596bc19cc6999d295d32a4Mark Lordstruct mv_host_priv {
43102a121da5a53d415b6596bc19cc6999d295d32a4Mark Lord	u32			hp_flags;
43202a121da5a53d415b6596bc19cc6999d295d32a4Mark Lord	struct mv_port_signal	signal[8];
43302a121da5a53d415b6596bc19cc6999d295d32a4Mark Lord	const struct mv_hw_ops	*ops;
434f351b2d638c3cb0b95adde3549b7bfaf3f991dfaSaeed Bishara	int			n_ports;
435f351b2d638c3cb0b95adde3549b7bfaf3f991dfaSaeed Bishara	void __iomem		*base;
436f351b2d638c3cb0b95adde3549b7bfaf3f991dfaSaeed Bishara	void __iomem		*main_cause_reg_addr;
437f351b2d638c3cb0b95adde3549b7bfaf3f991dfaSaeed Bishara	void __iomem		*main_mask_reg_addr;
43802a121da5a53d415b6596bc19cc6999d295d32a4Mark Lord	u32			irq_cause_ofs;
43902a121da5a53d415b6596bc19cc6999d295d32a4Mark Lord	u32			irq_mask_ofs;
44002a121da5a53d415b6596bc19cc6999d295d32a4Mark Lord	u32			unmask_all_irqs;
441da2fa9baf06f33a8fa7aa3f56c9f2b4070ceca0eMark Lord	/*
442da2fa9baf06f33a8fa7aa3f56c9f2b4070ceca0eMark Lord	 * These consistent DMA memory pools give us guaranteed
443da2fa9baf06f33a8fa7aa3f56c9f2b4070ceca0eMark Lord	 * alignment for hardware-accessed data structures,
444da2fa9baf06f33a8fa7aa3f56c9f2b4070ceca0eMark Lord	 * and less memory waste in accomplishing the alignment.
445da2fa9baf06f33a8fa7aa3f56c9f2b4070ceca0eMark Lord	 */
446da2fa9baf06f33a8fa7aa3f56c9f2b4070ceca0eMark Lord	struct dma_pool		*crqb_pool;
447da2fa9baf06f33a8fa7aa3f56c9f2b4070ceca0eMark Lord	struct dma_pool		*crpb_pool;
448da2fa9baf06f33a8fa7aa3f56c9f2b4070ceca0eMark Lord	struct dma_pool		*sg_tbl_pool;
44902a121da5a53d415b6596bc19cc6999d295d32a4Mark Lord};
45002a121da5a53d415b6596bc19cc6999d295d32a4Mark Lord
45147c2b677daeed9c79ecb7167c211ff36876ea611Jeff Garzikstruct mv_hw_ops {
4522a47ce06d534692f9bd2bf4e90a20fc9b1054c39Jeff Garzik	void (*phy_errata)(struct mv_host_priv *hpriv, void __iomem *mmio,
4532a47ce06d534692f9bd2bf4e90a20fc9b1054c39Jeff Garzik			   unsigned int port);
45447c2b677daeed9c79ecb7167c211ff36876ea611Jeff Garzik	void (*enable_leds)(struct mv_host_priv *hpriv, void __iomem *mmio);
45547c2b677daeed9c79ecb7167c211ff36876ea611Jeff Garzik	void (*read_preamp)(struct mv_host_priv *hpriv, int idx,
45647c2b677daeed9c79ecb7167c211ff36876ea611Jeff Garzik			   void __iomem *mmio);
457c9d39130123238ac18478a42e25cb7996eacfcc0Jeff Garzik	int (*reset_hc)(struct mv_host_priv *hpriv, void __iomem *mmio,
458c9d39130123238ac18478a42e25cb7996eacfcc0Jeff Garzik			unsigned int n_hc);
459522479fb98c6667f081e75f87e298e413c0b1db8Jeff Garzik	void (*reset_flash)(struct mv_host_priv *hpriv, void __iomem *mmio);
4607bb3c5290ca0ec9e65947c907495c2b56e895e46Saeed Bishara	void (*reset_bus)(struct ata_host *host, void __iomem *mmio);
46147c2b677daeed9c79ecb7167c211ff36876ea611Jeff Garzik};
46247c2b677daeed9c79ecb7167c211ff36876ea611Jeff Garzik
46320f733e7d75a16bffc34842b7682c9247dd5f954Brett Russstatic void mv_irq_clear(struct ata_port *ap);
464da3dbb17a0e9a9ec7f5aed95f1fddadb790edc9dTejun Heostatic int mv_scr_read(struct ata_port *ap, unsigned int sc_reg_in, u32 *val);
465da3dbb17a0e9a9ec7f5aed95f1fddadb790edc9dTejun Heostatic int mv_scr_write(struct ata_port *ap, unsigned int sc_reg_in, u32 val);
466da3dbb17a0e9a9ec7f5aed95f1fddadb790edc9dTejun Heostatic int mv5_scr_read(struct ata_port *ap, unsigned int sc_reg_in, u32 *val);
467da3dbb17a0e9a9ec7f5aed95f1fddadb790edc9dTejun Heostatic int mv5_scr_write(struct ata_port *ap, unsigned int sc_reg_in, u32 val);
46831961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russstatic int mv_port_start(struct ata_port *ap);
46931961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russstatic void mv_port_stop(struct ata_port *ap);
47031961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russstatic void mv_qc_prep(struct ata_queued_cmd *qc);
471e4e7b89280d1d666e2c09e5ad36cf071796c4c7eJeff Garzikstatic void mv_qc_prep_iie(struct ata_queued_cmd *qc);
4729a3d9eb0177eb10500d49cd283b35576082a522dTejun Heostatic unsigned int mv_qc_issue(struct ata_queued_cmd *qc);
473bdd4dddee325a7dce3e84cf48201a06aa8508aa4Jeff Garzikstatic void mv_error_handler(struct ata_port *ap);
474bdd4dddee325a7dce3e84cf48201a06aa8508aa4Jeff Garzikstatic void mv_eh_freeze(struct ata_port *ap);
475bdd4dddee325a7dce3e84cf48201a06aa8508aa4Jeff Garzikstatic void mv_eh_thaw(struct ata_port *ap);
476f273827e2aadcf2f74a7bdc9ad715a1b20ea7ddaMark Lordstatic void mv6_dev_config(struct ata_device *dev);
47720f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ
4782a47ce06d534692f9bd2bf4e90a20fc9b1054c39Jeff Garzikstatic void mv5_phy_errata(struct mv_host_priv *hpriv, void __iomem *mmio,
4792a47ce06d534692f9bd2bf4e90a20fc9b1054c39Jeff Garzik			   unsigned int port);
48047c2b677daeed9c79ecb7167c211ff36876ea611Jeff Garzikstatic void mv5_enable_leds(struct mv_host_priv *hpriv, void __iomem *mmio);
48147c2b677daeed9c79ecb7167c211ff36876ea611Jeff Garzikstatic void mv5_read_preamp(struct mv_host_priv *hpriv, int idx,
48247c2b677daeed9c79ecb7167c211ff36876ea611Jeff Garzik			   void __iomem *mmio);
483c9d39130123238ac18478a42e25cb7996eacfcc0Jeff Garzikstatic int mv5_reset_hc(struct mv_host_priv *hpriv, void __iomem *mmio,
484c9d39130123238ac18478a42e25cb7996eacfcc0Jeff Garzik			unsigned int n_hc);
485522479fb98c6667f081e75f87e298e413c0b1db8Jeff Garzikstatic void mv5_reset_flash(struct mv_host_priv *hpriv, void __iomem *mmio);
4867bb3c5290ca0ec9e65947c907495c2b56e895e46Saeed Bisharastatic void mv5_reset_bus(struct ata_host *host, void __iomem *mmio);
48747c2b677daeed9c79ecb7167c211ff36876ea611Jeff Garzik
4882a47ce06d534692f9bd2bf4e90a20fc9b1054c39Jeff Garzikstatic void mv6_phy_errata(struct mv_host_priv *hpriv, void __iomem *mmio,
4892a47ce06d534692f9bd2bf4e90a20fc9b1054c39Jeff Garzik			   unsigned int port);
49047c2b677daeed9c79ecb7167c211ff36876ea611Jeff Garzikstatic void mv6_enable_leds(struct mv_host_priv *hpriv, void __iomem *mmio);
49147c2b677daeed9c79ecb7167c211ff36876ea611Jeff Garzikstatic void mv6_read_preamp(struct mv_host_priv *hpriv, int idx,
49247c2b677daeed9c79ecb7167c211ff36876ea611Jeff Garzik			   void __iomem *mmio);
493c9d39130123238ac18478a42e25cb7996eacfcc0Jeff Garzikstatic int mv6_reset_hc(struct mv_host_priv *hpriv, void __iomem *mmio,
494c9d39130123238ac18478a42e25cb7996eacfcc0Jeff Garzik			unsigned int n_hc);
495522479fb98c6667f081e75f87e298e413c0b1db8Jeff Garzikstatic void mv6_reset_flash(struct mv_host_priv *hpriv, void __iomem *mmio);
496f351b2d638c3cb0b95adde3549b7bfaf3f991dfaSaeed Bisharastatic void mv_soc_enable_leds(struct mv_host_priv *hpriv,
497f351b2d638c3cb0b95adde3549b7bfaf3f991dfaSaeed Bishara				      void __iomem *mmio);
498f351b2d638c3cb0b95adde3549b7bfaf3f991dfaSaeed Bisharastatic void mv_soc_read_preamp(struct mv_host_priv *hpriv, int idx,
499f351b2d638c3cb0b95adde3549b7bfaf3f991dfaSaeed Bishara				      void __iomem *mmio);
500f351b2d638c3cb0b95adde3549b7bfaf3f991dfaSaeed Bisharastatic int mv_soc_reset_hc(struct mv_host_priv *hpriv,
501f351b2d638c3cb0b95adde3549b7bfaf3f991dfaSaeed Bishara				  void __iomem *mmio, unsigned int n_hc);
502f351b2d638c3cb0b95adde3549b7bfaf3f991dfaSaeed Bisharastatic void mv_soc_reset_flash(struct mv_host_priv *hpriv,
503f351b2d638c3cb0b95adde3549b7bfaf3f991dfaSaeed Bishara				      void __iomem *mmio);
504f351b2d638c3cb0b95adde3549b7bfaf3f991dfaSaeed Bisharastatic void mv_soc_reset_bus(struct ata_host *host, void __iomem *mmio);
5057bb3c5290ca0ec9e65947c907495c2b56e895e46Saeed Bisharastatic void mv_reset_pci_bus(struct ata_host *host, void __iomem *mmio);
506c9d39130123238ac18478a42e25cb7996eacfcc0Jeff Garzikstatic void mv_channel_reset(struct mv_host_priv *hpriv, void __iomem *mmio,
507c9d39130123238ac18478a42e25cb7996eacfcc0Jeff Garzik			     unsigned int port_no);
508721091685f853ba4e6c49f26f989db0b1a811250Mark Lordstatic void mv_edma_cfg(struct mv_port_priv *pp, struct mv_host_priv *hpriv,
509721091685f853ba4e6c49f26f989db0b1a811250Mark Lord			void __iomem *port_mmio, int want_ncq);
510721091685f853ba4e6c49f26f989db0b1a811250Mark Lordstatic int __mv_stop_dma(struct ata_port *ap);
51147c2b677daeed9c79ecb7167c211ff36876ea611Jeff Garzik
512eb73d558d1c1c931de0b3a86af962c77d74ef688Mark Lord/* .sg_tablesize is (MV_MAX_SG_CT / 2) in the structures below
513eb73d558d1c1c931de0b3a86af962c77d74ef688Mark Lord * because we have to allow room for worst case splitting of
514eb73d558d1c1c931de0b3a86af962c77d74ef688Mark Lord * PRDs for 64K boundaries in mv_fill_sg().
515eb73d558d1c1c931de0b3a86af962c77d74ef688Mark Lord */
516c5d3e45a2200a0905dc45b72714726b7aac3aaf1Jeff Garzikstatic struct scsi_host_template mv5_sht = {
517c5d3e45a2200a0905dc45b72714726b7aac3aaf1Jeff Garzik	.module			= THIS_MODULE,
518c5d3e45a2200a0905dc45b72714726b7aac3aaf1Jeff Garzik	.name			= DRV_NAME,
519c5d3e45a2200a0905dc45b72714726b7aac3aaf1Jeff Garzik	.ioctl			= ata_scsi_ioctl,
520c5d3e45a2200a0905dc45b72714726b7aac3aaf1Jeff Garzik	.queuecommand		= ata_scsi_queuecmd,
521c5d3e45a2200a0905dc45b72714726b7aac3aaf1Jeff Garzik	.can_queue		= ATA_DEF_QUEUE,
522c5d3e45a2200a0905dc45b72714726b7aac3aaf1Jeff Garzik	.this_id		= ATA_SHT_THIS_ID,
523baf14aa14efcfdb5a74d5cf804691086c6bec743Jeff Garzik	.sg_tablesize		= MV_MAX_SG_CT / 2,
524c5d3e45a2200a0905dc45b72714726b7aac3aaf1Jeff Garzik	.cmd_per_lun		= ATA_SHT_CMD_PER_LUN,
525c5d3e45a2200a0905dc45b72714726b7aac3aaf1Jeff Garzik	.emulated		= ATA_SHT_EMULATED,
526c5d3e45a2200a0905dc45b72714726b7aac3aaf1Jeff Garzik	.use_clustering		= 1,
527c5d3e45a2200a0905dc45b72714726b7aac3aaf1Jeff Garzik	.proc_name		= DRV_NAME,
528c5d3e45a2200a0905dc45b72714726b7aac3aaf1Jeff Garzik	.dma_boundary		= MV_DMA_BOUNDARY,
5293be6cbd73f74b4a3da82cc7d6e1688a4ae595fc7Jeff Garzik	.slave_configure	= ata_scsi_slave_config,
530c5d3e45a2200a0905dc45b72714726b7aac3aaf1Jeff Garzik	.slave_destroy		= ata_scsi_slave_destroy,
531c5d3e45a2200a0905dc45b72714726b7aac3aaf1Jeff Garzik	.bios_param		= ata_std_bios_param,
532c5d3e45a2200a0905dc45b72714726b7aac3aaf1Jeff Garzik};
533c5d3e45a2200a0905dc45b72714726b7aac3aaf1Jeff Garzik
534c5d3e45a2200a0905dc45b72714726b7aac3aaf1Jeff Garzikstatic struct scsi_host_template mv6_sht = {
53520f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ	.module			= THIS_MODULE,
53620f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ	.name			= DRV_NAME,
53720f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ	.ioctl			= ata_scsi_ioctl,
53820f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ	.queuecommand		= ata_scsi_queuecmd,
539138bfdd03f2c08cc62b6af3900fb7be1c696315bMark Lord	.change_queue_depth	= ata_scsi_change_queue_depth,
540138bfdd03f2c08cc62b6af3900fb7be1c696315bMark Lord	.can_queue		= MV_MAX_Q_DEPTH - 1,
54120f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ	.this_id		= ATA_SHT_THIS_ID,
542baf14aa14efcfdb5a74d5cf804691086c6bec743Jeff Garzik	.sg_tablesize		= MV_MAX_SG_CT / 2,
54320f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ	.cmd_per_lun		= ATA_SHT_CMD_PER_LUN,
54420f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ	.emulated		= ATA_SHT_EMULATED,
545d88184fb2348a50f7c34f5d49a901c875b2e0114Jeff Garzik	.use_clustering		= 1,
54620f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ	.proc_name		= DRV_NAME,
54720f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ	.dma_boundary		= MV_DMA_BOUNDARY,
5483be6cbd73f74b4a3da82cc7d6e1688a4ae595fc7Jeff Garzik	.slave_configure	= ata_scsi_slave_config,
549ccf68c3405fca11386004674377d951b9b18e756Tejun Heo	.slave_destroy		= ata_scsi_slave_destroy,
55020f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ	.bios_param		= ata_std_bios_param,
55120f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ};
55220f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ
553c9d39130123238ac18478a42e25cb7996eacfcc0Jeff Garzikstatic const struct ata_port_operations mv5_ops = {
554c9d39130123238ac18478a42e25cb7996eacfcc0Jeff Garzik	.tf_load		= ata_tf_load,
555c9d39130123238ac18478a42e25cb7996eacfcc0Jeff Garzik	.tf_read		= ata_tf_read,
556c9d39130123238ac18478a42e25cb7996eacfcc0Jeff Garzik	.check_status		= ata_check_status,
557c9d39130123238ac18478a42e25cb7996eacfcc0Jeff Garzik	.exec_command		= ata_exec_command,
558c9d39130123238ac18478a42e25cb7996eacfcc0Jeff Garzik	.dev_select		= ata_std_dev_select,
559c9d39130123238ac18478a42e25cb7996eacfcc0Jeff Garzik
560cffacd85bcf6fc652292001873119333555fe260Jeff Garzik	.cable_detect		= ata_cable_sata,
561c9d39130123238ac18478a42e25cb7996eacfcc0Jeff Garzik
562c9d39130123238ac18478a42e25cb7996eacfcc0Jeff Garzik	.qc_prep		= mv_qc_prep,
563c9d39130123238ac18478a42e25cb7996eacfcc0Jeff Garzik	.qc_issue		= mv_qc_issue,
5640d5ff566779f894ca9937231a181eb31e4adff0eTejun Heo	.data_xfer		= ata_data_xfer,
565c9d39130123238ac18478a42e25cb7996eacfcc0Jeff Garzik
566c9d39130123238ac18478a42e25cb7996eacfcc0Jeff Garzik	.irq_clear		= mv_irq_clear,
567246ce3b675843e0369643cceb4faeb6cf6d19a30Akira Iguchi	.irq_on			= ata_irq_on,
568c9d39130123238ac18478a42e25cb7996eacfcc0Jeff Garzik
569bdd4dddee325a7dce3e84cf48201a06aa8508aa4Jeff Garzik	.error_handler		= mv_error_handler,
570bdd4dddee325a7dce3e84cf48201a06aa8508aa4Jeff Garzik	.freeze			= mv_eh_freeze,
571bdd4dddee325a7dce3e84cf48201a06aa8508aa4Jeff Garzik	.thaw			= mv_eh_thaw,
572bdd4dddee325a7dce3e84cf48201a06aa8508aa4Jeff Garzik
573c9d39130123238ac18478a42e25cb7996eacfcc0Jeff Garzik	.scr_read		= mv5_scr_read,
574c9d39130123238ac18478a42e25cb7996eacfcc0Jeff Garzik	.scr_write		= mv5_scr_write,
575c9d39130123238ac18478a42e25cb7996eacfcc0Jeff Garzik
576c9d39130123238ac18478a42e25cb7996eacfcc0Jeff Garzik	.port_start		= mv_port_start,
577c9d39130123238ac18478a42e25cb7996eacfcc0Jeff Garzik	.port_stop		= mv_port_stop,
578c9d39130123238ac18478a42e25cb7996eacfcc0Jeff Garzik};
579c9d39130123238ac18478a42e25cb7996eacfcc0Jeff Garzik
580c9d39130123238ac18478a42e25cb7996eacfcc0Jeff Garzikstatic const struct ata_port_operations mv6_ops = {
581f273827e2aadcf2f74a7bdc9ad715a1b20ea7ddaMark Lord	.dev_config             = mv6_dev_config,
58220f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ	.tf_load		= ata_tf_load,
58320f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ	.tf_read		= ata_tf_read,
58420f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ	.check_status		= ata_check_status,
58520f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ	.exec_command		= ata_exec_command,
58620f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ	.dev_select		= ata_std_dev_select,
58720f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ
588cffacd85bcf6fc652292001873119333555fe260Jeff Garzik	.cable_detect		= ata_cable_sata,
58920f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ
59031961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ	.qc_prep		= mv_qc_prep,
59131961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ	.qc_issue		= mv_qc_issue,
5920d5ff566779f894ca9937231a181eb31e4adff0eTejun Heo	.data_xfer		= ata_data_xfer,
59320f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ
59420f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ	.irq_clear		= mv_irq_clear,
595246ce3b675843e0369643cceb4faeb6cf6d19a30Akira Iguchi	.irq_on			= ata_irq_on,
59620f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ
597bdd4dddee325a7dce3e84cf48201a06aa8508aa4Jeff Garzik	.error_handler		= mv_error_handler,
598bdd4dddee325a7dce3e84cf48201a06aa8508aa4Jeff Garzik	.freeze			= mv_eh_freeze,
599bdd4dddee325a7dce3e84cf48201a06aa8508aa4Jeff Garzik	.thaw			= mv_eh_thaw,
600138bfdd03f2c08cc62b6af3900fb7be1c696315bMark Lord	.qc_defer		= ata_std_qc_defer,
601bdd4dddee325a7dce3e84cf48201a06aa8508aa4Jeff Garzik
60220f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ	.scr_read		= mv_scr_read,
60320f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ	.scr_write		= mv_scr_write,
60420f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ
60531961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ	.port_start		= mv_port_start,
60631961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ	.port_stop		= mv_port_stop,
60720f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ};
60820f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ
609e4e7b89280d1d666e2c09e5ad36cf071796c4c7eJeff Garzikstatic const struct ata_port_operations mv_iie_ops = {
610e4e7b89280d1d666e2c09e5ad36cf071796c4c7eJeff Garzik	.tf_load		= ata_tf_load,
611e4e7b89280d1d666e2c09e5ad36cf071796c4c7eJeff Garzik	.tf_read		= ata_tf_read,
612e4e7b89280d1d666e2c09e5ad36cf071796c4c7eJeff Garzik	.check_status		= ata_check_status,
613e4e7b89280d1d666e2c09e5ad36cf071796c4c7eJeff Garzik	.exec_command		= ata_exec_command,
614e4e7b89280d1d666e2c09e5ad36cf071796c4c7eJeff Garzik	.dev_select		= ata_std_dev_select,
615e4e7b89280d1d666e2c09e5ad36cf071796c4c7eJeff Garzik
616cffacd85bcf6fc652292001873119333555fe260Jeff Garzik	.cable_detect		= ata_cable_sata,
617e4e7b89280d1d666e2c09e5ad36cf071796c4c7eJeff Garzik
618e4e7b89280d1d666e2c09e5ad36cf071796c4c7eJeff Garzik	.qc_prep		= mv_qc_prep_iie,
619e4e7b89280d1d666e2c09e5ad36cf071796c4c7eJeff Garzik	.qc_issue		= mv_qc_issue,
6200d5ff566779f894ca9937231a181eb31e4adff0eTejun Heo	.data_xfer		= ata_data_xfer,
621e4e7b89280d1d666e2c09e5ad36cf071796c4c7eJeff Garzik
622e4e7b89280d1d666e2c09e5ad36cf071796c4c7eJeff Garzik	.irq_clear		= mv_irq_clear,
623246ce3b675843e0369643cceb4faeb6cf6d19a30Akira Iguchi	.irq_on			= ata_irq_on,
624e4e7b89280d1d666e2c09e5ad36cf071796c4c7eJeff Garzik
625bdd4dddee325a7dce3e84cf48201a06aa8508aa4Jeff Garzik	.error_handler		= mv_error_handler,
626bdd4dddee325a7dce3e84cf48201a06aa8508aa4Jeff Garzik	.freeze			= mv_eh_freeze,
627bdd4dddee325a7dce3e84cf48201a06aa8508aa4Jeff Garzik	.thaw			= mv_eh_thaw,
628138bfdd03f2c08cc62b6af3900fb7be1c696315bMark Lord	.qc_defer		= ata_std_qc_defer,
629bdd4dddee325a7dce3e84cf48201a06aa8508aa4Jeff Garzik
630e4e7b89280d1d666e2c09e5ad36cf071796c4c7eJeff Garzik	.scr_read		= mv_scr_read,
631e4e7b89280d1d666e2c09e5ad36cf071796c4c7eJeff Garzik	.scr_write		= mv_scr_write,
632e4e7b89280d1d666e2c09e5ad36cf071796c4c7eJeff Garzik
633e4e7b89280d1d666e2c09e5ad36cf071796c4c7eJeff Garzik	.port_start		= mv_port_start,
634e4e7b89280d1d666e2c09e5ad36cf071796c4c7eJeff Garzik	.port_stop		= mv_port_stop,
635e4e7b89280d1d666e2c09e5ad36cf071796c4c7eJeff Garzik};
636e4e7b89280d1d666e2c09e5ad36cf071796c4c7eJeff Garzik
63798ac62defe529d04a192688f40d801a2d8fbcf98Arjan van de Venstatic const struct ata_port_info mv_port_info[] = {
63820f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ	{  /* chip_504x */
639cca3974e48607c3775dc73b544a5700b2e37c21aJeff Garzik		.flags		= MV_COMMON_FLAGS,
64031961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ		.pio_mask	= 0x1f,	/* pio0-4 */
641bf6263a853c9c143bf03f0a6fdcc68ab714fb5f5Jeff Garzik		.udma_mask	= ATA_UDMA6,
642c9d39130123238ac18478a42e25cb7996eacfcc0Jeff Garzik		.port_ops	= &mv5_ops,
64320f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ	},
64420f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ	{  /* chip_508x */
645c5d3e45a2200a0905dc45b72714726b7aac3aaf1Jeff Garzik		.flags		= MV_COMMON_FLAGS | MV_FLAG_DUAL_HC,
64631961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ		.pio_mask	= 0x1f,	/* pio0-4 */
647bf6263a853c9c143bf03f0a6fdcc68ab714fb5f5Jeff Garzik		.udma_mask	= ATA_UDMA6,
648c9d39130123238ac18478a42e25cb7996eacfcc0Jeff Garzik		.port_ops	= &mv5_ops,
64920f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ	},
65047c2b677daeed9c79ecb7167c211ff36876ea611Jeff Garzik	{  /* chip_5080 */
651c5d3e45a2200a0905dc45b72714726b7aac3aaf1Jeff Garzik		.flags		= MV_COMMON_FLAGS | MV_FLAG_DUAL_HC,
65247c2b677daeed9c79ecb7167c211ff36876ea611Jeff Garzik		.pio_mask	= 0x1f,	/* pio0-4 */
653bf6263a853c9c143bf03f0a6fdcc68ab714fb5f5Jeff Garzik		.udma_mask	= ATA_UDMA6,
654c9d39130123238ac18478a42e25cb7996eacfcc0Jeff Garzik		.port_ops	= &mv5_ops,
65547c2b677daeed9c79ecb7167c211ff36876ea611Jeff Garzik	},
65620f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ	{  /* chip_604x */
657138bfdd03f2c08cc62b6af3900fb7be1c696315bMark Lord		.flags		= MV_COMMON_FLAGS | MV_6XXX_FLAGS |
658138bfdd03f2c08cc62b6af3900fb7be1c696315bMark Lord				  ATA_FLAG_NCQ,
65931961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ		.pio_mask	= 0x1f,	/* pio0-4 */
660bf6263a853c9c143bf03f0a6fdcc68ab714fb5f5Jeff Garzik		.udma_mask	= ATA_UDMA6,
661c9d39130123238ac18478a42e25cb7996eacfcc0Jeff Garzik		.port_ops	= &mv6_ops,
66220f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ	},
66320f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ	{  /* chip_608x */
664c5d3e45a2200a0905dc45b72714726b7aac3aaf1Jeff Garzik		.flags		= MV_COMMON_FLAGS | MV_6XXX_FLAGS |
665138bfdd03f2c08cc62b6af3900fb7be1c696315bMark Lord				  ATA_FLAG_NCQ | MV_FLAG_DUAL_HC,
66631961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ		.pio_mask	= 0x1f,	/* pio0-4 */
667bf6263a853c9c143bf03f0a6fdcc68ab714fb5f5Jeff Garzik		.udma_mask	= ATA_UDMA6,
668c9d39130123238ac18478a42e25cb7996eacfcc0Jeff Garzik		.port_ops	= &mv6_ops,
66920f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ	},
670e4e7b89280d1d666e2c09e5ad36cf071796c4c7eJeff Garzik	{  /* chip_6042 */
671138bfdd03f2c08cc62b6af3900fb7be1c696315bMark Lord		.flags		= MV_COMMON_FLAGS | MV_6XXX_FLAGS |
672138bfdd03f2c08cc62b6af3900fb7be1c696315bMark Lord				  ATA_FLAG_NCQ,
673e4e7b89280d1d666e2c09e5ad36cf071796c4c7eJeff Garzik		.pio_mask	= 0x1f,	/* pio0-4 */
674bf6263a853c9c143bf03f0a6fdcc68ab714fb5f5Jeff Garzik		.udma_mask	= ATA_UDMA6,
675e4e7b89280d1d666e2c09e5ad36cf071796c4c7eJeff Garzik		.port_ops	= &mv_iie_ops,
676e4e7b89280d1d666e2c09e5ad36cf071796c4c7eJeff Garzik	},
677e4e7b89280d1d666e2c09e5ad36cf071796c4c7eJeff Garzik	{  /* chip_7042 */
678138bfdd03f2c08cc62b6af3900fb7be1c696315bMark Lord		.flags		= MV_COMMON_FLAGS | MV_6XXX_FLAGS |
679138bfdd03f2c08cc62b6af3900fb7be1c696315bMark Lord				  ATA_FLAG_NCQ,
680e4e7b89280d1d666e2c09e5ad36cf071796c4c7eJeff Garzik		.pio_mask	= 0x1f,	/* pio0-4 */
681bf6263a853c9c143bf03f0a6fdcc68ab714fb5f5Jeff Garzik		.udma_mask	= ATA_UDMA6,
682e4e7b89280d1d666e2c09e5ad36cf071796c4c7eJeff Garzik		.port_ops	= &mv_iie_ops,
683e4e7b89280d1d666e2c09e5ad36cf071796c4c7eJeff Garzik	},
684f351b2d638c3cb0b95adde3549b7bfaf3f991dfaSaeed Bishara	{  /* chip_soc */
685f351b2d638c3cb0b95adde3549b7bfaf3f991dfaSaeed Bishara		.flags = MV_COMMON_FLAGS | MV_FLAG_SOC,
686f351b2d638c3cb0b95adde3549b7bfaf3f991dfaSaeed Bishara		.pio_mask = 0x1f,      /* pio0-4 */
687f351b2d638c3cb0b95adde3549b7bfaf3f991dfaSaeed Bishara		.udma_mask = ATA_UDMA6,
688f351b2d638c3cb0b95adde3549b7bfaf3f991dfaSaeed Bishara		.port_ops = &mv_iie_ops,
689f351b2d638c3cb0b95adde3549b7bfaf3f991dfaSaeed Bishara	},
69020f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ};
69120f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ
6923b7d697dfb7d03edb87e50b743a7ecff029618e9Jeff Garzikstatic const struct pci_device_id mv_pci_tbl[] = {
6932d2744fc8be620a2dc469cf48349e3e704119f1bJeff Garzik	{ PCI_VDEVICE(MARVELL, 0x5040), chip_504x },
6942d2744fc8be620a2dc469cf48349e3e704119f1bJeff Garzik	{ PCI_VDEVICE(MARVELL, 0x5041), chip_504x },
6952d2744fc8be620a2dc469cf48349e3e704119f1bJeff Garzik	{ PCI_VDEVICE(MARVELL, 0x5080), chip_5080 },
6962d2744fc8be620a2dc469cf48349e3e704119f1bJeff Garzik	{ PCI_VDEVICE(MARVELL, 0x5081), chip_508x },
697cfbf723eb7928879292ee71fa0d118fc4e37b8c9Alan Cox	/* RocketRAID 1740/174x have different identifiers */
698cfbf723eb7928879292ee71fa0d118fc4e37b8c9Alan Cox	{ PCI_VDEVICE(TTI, 0x1740), chip_508x },
699cfbf723eb7928879292ee71fa0d118fc4e37b8c9Alan Cox	{ PCI_VDEVICE(TTI, 0x1742), chip_508x },
7002d2744fc8be620a2dc469cf48349e3e704119f1bJeff Garzik
7012d2744fc8be620a2dc469cf48349e3e704119f1bJeff Garzik	{ PCI_VDEVICE(MARVELL, 0x6040), chip_604x },
7022d2744fc8be620a2dc469cf48349e3e704119f1bJeff Garzik	{ PCI_VDEVICE(MARVELL, 0x6041), chip_604x },
7032d2744fc8be620a2dc469cf48349e3e704119f1bJeff Garzik	{ PCI_VDEVICE(MARVELL, 0x6042), chip_6042 },
7042d2744fc8be620a2dc469cf48349e3e704119f1bJeff Garzik	{ PCI_VDEVICE(MARVELL, 0x6080), chip_608x },
7052d2744fc8be620a2dc469cf48349e3e704119f1bJeff Garzik	{ PCI_VDEVICE(MARVELL, 0x6081), chip_608x },
7062d2744fc8be620a2dc469cf48349e3e704119f1bJeff Garzik
7072d2744fc8be620a2dc469cf48349e3e704119f1bJeff Garzik	{ PCI_VDEVICE(ADAPTEC2, 0x0241), chip_604x },
7082d2744fc8be620a2dc469cf48349e3e704119f1bJeff Garzik
709d9f9c6bc91c14f53ffa782ffcd42259ecae1d38cFlorian Attenberger	/* Adaptec 1430SA */
710d9f9c6bc91c14f53ffa782ffcd42259ecae1d38cFlorian Attenberger	{ PCI_VDEVICE(ADAPTEC2, 0x0243), chip_7042 },
711d9f9c6bc91c14f53ffa782ffcd42259ecae1d38cFlorian Attenberger
71202a121da5a53d415b6596bc19cc6999d295d32a4Mark Lord	/* Marvell 7042 support */
7136a3d586d8e8a50e4cfd7f8c36d82a53c5614e05bMorrison, Tom	{ PCI_VDEVICE(MARVELL, 0x7042), chip_7042 },
7146a3d586d8e8a50e4cfd7f8c36d82a53c5614e05bMorrison, Tom
71502a121da5a53d415b6596bc19cc6999d295d32a4Mark Lord	/* Highpoint RocketRAID PCIe series */
71602a121da5a53d415b6596bc19cc6999d295d32a4Mark Lord	{ PCI_VDEVICE(TTI, 0x2300), chip_7042 },
71702a121da5a53d415b6596bc19cc6999d295d32a4Mark Lord	{ PCI_VDEVICE(TTI, 0x2310), chip_7042 },
71802a121da5a53d415b6596bc19cc6999d295d32a4Mark Lord
7192d2744fc8be620a2dc469cf48349e3e704119f1bJeff Garzik	{ }			/* terminate list */
72020f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ};
72120f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ
72247c2b677daeed9c79ecb7167c211ff36876ea611Jeff Garzikstatic const struct mv_hw_ops mv5xxx_ops = {
72347c2b677daeed9c79ecb7167c211ff36876ea611Jeff Garzik	.phy_errata		= mv5_phy_errata,
72447c2b677daeed9c79ecb7167c211ff36876ea611Jeff Garzik	.enable_leds		= mv5_enable_leds,
72547c2b677daeed9c79ecb7167c211ff36876ea611Jeff Garzik	.read_preamp		= mv5_read_preamp,
72647c2b677daeed9c79ecb7167c211ff36876ea611Jeff Garzik	.reset_hc		= mv5_reset_hc,
727522479fb98c6667f081e75f87e298e413c0b1db8Jeff Garzik	.reset_flash		= mv5_reset_flash,
728522479fb98c6667f081e75f87e298e413c0b1db8Jeff Garzik	.reset_bus		= mv5_reset_bus,
72947c2b677daeed9c79ecb7167c211ff36876ea611Jeff Garzik};
73047c2b677daeed9c79ecb7167c211ff36876ea611Jeff Garzik
73147c2b677daeed9c79ecb7167c211ff36876ea611Jeff Garzikstatic const struct mv_hw_ops mv6xxx_ops = {
73247c2b677daeed9c79ecb7167c211ff36876ea611Jeff Garzik	.phy_errata		= mv6_phy_errata,
73347c2b677daeed9c79ecb7167c211ff36876ea611Jeff Garzik	.enable_leds		= mv6_enable_leds,
73447c2b677daeed9c79ecb7167c211ff36876ea611Jeff Garzik	.read_preamp		= mv6_read_preamp,
73547c2b677daeed9c79ecb7167c211ff36876ea611Jeff Garzik	.reset_hc		= mv6_reset_hc,
736522479fb98c6667f081e75f87e298e413c0b1db8Jeff Garzik	.reset_flash		= mv6_reset_flash,
737522479fb98c6667f081e75f87e298e413c0b1db8Jeff Garzik	.reset_bus		= mv_reset_pci_bus,
73847c2b677daeed9c79ecb7167c211ff36876ea611Jeff Garzik};
73947c2b677daeed9c79ecb7167c211ff36876ea611Jeff Garzik
740f351b2d638c3cb0b95adde3549b7bfaf3f991dfaSaeed Bisharastatic const struct mv_hw_ops mv_soc_ops = {
741f351b2d638c3cb0b95adde3549b7bfaf3f991dfaSaeed Bishara	.phy_errata		= mv6_phy_errata,
742f351b2d638c3cb0b95adde3549b7bfaf3f991dfaSaeed Bishara	.enable_leds		= mv_soc_enable_leds,
743f351b2d638c3cb0b95adde3549b7bfaf3f991dfaSaeed Bishara	.read_preamp		= mv_soc_read_preamp,
744f351b2d638c3cb0b95adde3549b7bfaf3f991dfaSaeed Bishara	.reset_hc		= mv_soc_reset_hc,
745f351b2d638c3cb0b95adde3549b7bfaf3f991dfaSaeed Bishara	.reset_flash		= mv_soc_reset_flash,
746f351b2d638c3cb0b95adde3549b7bfaf3f991dfaSaeed Bishara	.reset_bus		= mv_soc_reset_bus,
747f351b2d638c3cb0b95adde3549b7bfaf3f991dfaSaeed Bishara};
748f351b2d638c3cb0b95adde3549b7bfaf3f991dfaSaeed Bishara
74920f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ/*
75020f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ * Functions
75120f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ */
75220f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ
75320f733e7d75a16bffc34842b7682c9247dd5f954Brett Russstatic inline void writelfl(unsigned long data, void __iomem *addr)
75420f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ{
75520f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ	writel(data, addr);
75620f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ	(void) readl(addr);	/* flush to avoid PCI posted write */
75720f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ}
75820f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ
75920f733e7d75a16bffc34842b7682c9247dd5f954Brett Russstatic inline void __iomem *mv_hc_base(void __iomem *base, unsigned int hc)
76020f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ{
76120f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ	return (base + MV_SATAHC0_REG_BASE + (hc * MV_SATAHC_REG_SZ));
76220f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ}
76320f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ
764c9d39130123238ac18478a42e25cb7996eacfcc0Jeff Garzikstatic inline unsigned int mv_hc_from_port(unsigned int port)
765c9d39130123238ac18478a42e25cb7996eacfcc0Jeff Garzik{
766c9d39130123238ac18478a42e25cb7996eacfcc0Jeff Garzik	return port >> MV_PORT_HC_SHIFT;
767c9d39130123238ac18478a42e25cb7996eacfcc0Jeff Garzik}
768c9d39130123238ac18478a42e25cb7996eacfcc0Jeff Garzik
769c9d39130123238ac18478a42e25cb7996eacfcc0Jeff Garzikstatic inline unsigned int mv_hardport_from_port(unsigned int port)
770c9d39130123238ac18478a42e25cb7996eacfcc0Jeff Garzik{
771c9d39130123238ac18478a42e25cb7996eacfcc0Jeff Garzik	return port & MV_PORT_MASK;
772c9d39130123238ac18478a42e25cb7996eacfcc0Jeff Garzik}
773c9d39130123238ac18478a42e25cb7996eacfcc0Jeff Garzik
774c9d39130123238ac18478a42e25cb7996eacfcc0Jeff Garzikstatic inline void __iomem *mv_hc_base_from_port(void __iomem *base,
775c9d39130123238ac18478a42e25cb7996eacfcc0Jeff Garzik						 unsigned int port)
776c9d39130123238ac18478a42e25cb7996eacfcc0Jeff Garzik{
777c9d39130123238ac18478a42e25cb7996eacfcc0Jeff Garzik	return mv_hc_base(base, mv_hc_from_port(port));
778c9d39130123238ac18478a42e25cb7996eacfcc0Jeff Garzik}
779c9d39130123238ac18478a42e25cb7996eacfcc0Jeff Garzik
78020f733e7d75a16bffc34842b7682c9247dd5f954Brett Russstatic inline void __iomem *mv_port_base(void __iomem *base, unsigned int port)
78120f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ{
782c9d39130123238ac18478a42e25cb7996eacfcc0Jeff Garzik	return  mv_hc_base_from_port(base, port) +
7838b260248d9e0e8b64bb72fd4dee03ad86984c344Jeff Garzik		MV_SATAHC_ARBTR_REG_SZ +
784c9d39130123238ac18478a42e25cb7996eacfcc0Jeff Garzik		(mv_hardport_from_port(port) * MV_PORT_REG_SZ);
78520f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ}
78620f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ
787f351b2d638c3cb0b95adde3549b7bfaf3f991dfaSaeed Bisharastatic inline void __iomem *mv_host_base(struct ata_host *host)
788f351b2d638c3cb0b95adde3549b7bfaf3f991dfaSaeed Bishara{
789f351b2d638c3cb0b95adde3549b7bfaf3f991dfaSaeed Bishara	struct mv_host_priv *hpriv = host->private_data;
790f351b2d638c3cb0b95adde3549b7bfaf3f991dfaSaeed Bishara	return hpriv->base;
791f351b2d638c3cb0b95adde3549b7bfaf3f991dfaSaeed Bishara}
792f351b2d638c3cb0b95adde3549b7bfaf3f991dfaSaeed Bishara
79320f733e7d75a16bffc34842b7682c9247dd5f954Brett Russstatic inline void __iomem *mv_ap_base(struct ata_port *ap)
79420f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ{
795f351b2d638c3cb0b95adde3549b7bfaf3f991dfaSaeed Bishara	return mv_port_base(mv_host_base(ap->host), ap->port_no);
79620f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ}
79720f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ
798cca3974e48607c3775dc73b544a5700b2e37c21aJeff Garzikstatic inline int mv_get_hc_count(unsigned long port_flags)
79931961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ{
800cca3974e48607c3775dc73b544a5700b2e37c21aJeff Garzik	return ((port_flags & MV_FLAG_DUAL_HC) ? 2 : 1);
80131961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ}
80231961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ
80331961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russstatic void mv_irq_clear(struct ata_port *ap)
80420f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ{
80520f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ}
80620f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ
807c5d3e45a2200a0905dc45b72714726b7aac3aaf1Jeff Garzikstatic void mv_set_edma_ptrs(void __iomem *port_mmio,
808c5d3e45a2200a0905dc45b72714726b7aac3aaf1Jeff Garzik			     struct mv_host_priv *hpriv,
809c5d3e45a2200a0905dc45b72714726b7aac3aaf1Jeff Garzik			     struct mv_port_priv *pp)
810c5d3e45a2200a0905dc45b72714726b7aac3aaf1Jeff Garzik{
811bdd4dddee325a7dce3e84cf48201a06aa8508aa4Jeff Garzik	u32 index;
812bdd4dddee325a7dce3e84cf48201a06aa8508aa4Jeff Garzik
813c5d3e45a2200a0905dc45b72714726b7aac3aaf1Jeff Garzik	/*
814c5d3e45a2200a0905dc45b72714726b7aac3aaf1Jeff Garzik	 * initialize request queue
815c5d3e45a2200a0905dc45b72714726b7aac3aaf1Jeff Garzik	 */
816bdd4dddee325a7dce3e84cf48201a06aa8508aa4Jeff Garzik	index = (pp->req_idx & MV_MAX_Q_DEPTH_MASK) << EDMA_REQ_Q_PTR_SHIFT;
817bdd4dddee325a7dce3e84cf48201a06aa8508aa4Jeff Garzik
818c5d3e45a2200a0905dc45b72714726b7aac3aaf1Jeff Garzik	WARN_ON(pp->crqb_dma & 0x3ff);
819c5d3e45a2200a0905dc45b72714726b7aac3aaf1Jeff Garzik	writel((pp->crqb_dma >> 16) >> 16, port_mmio + EDMA_REQ_Q_BASE_HI_OFS);
820bdd4dddee325a7dce3e84cf48201a06aa8508aa4Jeff Garzik	writelfl((pp->crqb_dma & EDMA_REQ_Q_BASE_LO_MASK) | index,
821c5d3e45a2200a0905dc45b72714726b7aac3aaf1Jeff Garzik		 port_mmio + EDMA_REQ_Q_IN_PTR_OFS);
822c5d3e45a2200a0905dc45b72714726b7aac3aaf1Jeff Garzik
823c5d3e45a2200a0905dc45b72714726b7aac3aaf1Jeff Garzik	if (hpriv->hp_flags & MV_HP_ERRATA_XX42A0)
824bdd4dddee325a7dce3e84cf48201a06aa8508aa4Jeff Garzik		writelfl((pp->crqb_dma & 0xffffffff) | index,
825c5d3e45a2200a0905dc45b72714726b7aac3aaf1Jeff Garzik			 port_mmio + EDMA_REQ_Q_OUT_PTR_OFS);
826c5d3e45a2200a0905dc45b72714726b7aac3aaf1Jeff Garzik	else
827bdd4dddee325a7dce3e84cf48201a06aa8508aa4Jeff Garzik		writelfl(index, port_mmio + EDMA_REQ_Q_OUT_PTR_OFS);
828c5d3e45a2200a0905dc45b72714726b7aac3aaf1Jeff Garzik
829c5d3e45a2200a0905dc45b72714726b7aac3aaf1Jeff Garzik	/*
830c5d3e45a2200a0905dc45b72714726b7aac3aaf1Jeff Garzik	 * initialize response queue
831c5d3e45a2200a0905dc45b72714726b7aac3aaf1Jeff Garzik	 */
832bdd4dddee325a7dce3e84cf48201a06aa8508aa4Jeff Garzik	index = (pp->resp_idx & MV_MAX_Q_DEPTH_MASK) << EDMA_RSP_Q_PTR_SHIFT;
833bdd4dddee325a7dce3e84cf48201a06aa8508aa4Jeff Garzik
834c5d3e45a2200a0905dc45b72714726b7aac3aaf1Jeff Garzik	WARN_ON(pp->crpb_dma & 0xff);
835c5d3e45a2200a0905dc45b72714726b7aac3aaf1Jeff Garzik	writel((pp->crpb_dma >> 16) >> 16, port_mmio + EDMA_RSP_Q_BASE_HI_OFS);
836c5d3e45a2200a0905dc45b72714726b7aac3aaf1Jeff Garzik
837c5d3e45a2200a0905dc45b72714726b7aac3aaf1Jeff Garzik	if (hpriv->hp_flags & MV_HP_ERRATA_XX42A0)
838bdd4dddee325a7dce3e84cf48201a06aa8508aa4Jeff Garzik		writelfl((pp->crpb_dma & 0xffffffff) | index,
839c5d3e45a2200a0905dc45b72714726b7aac3aaf1Jeff Garzik			 port_mmio + EDMA_RSP_Q_IN_PTR_OFS);
840c5d3e45a2200a0905dc45b72714726b7aac3aaf1Jeff Garzik	else
841bdd4dddee325a7dce3e84cf48201a06aa8508aa4Jeff Garzik		writelfl(index, port_mmio + EDMA_RSP_Q_IN_PTR_OFS);
842c5d3e45a2200a0905dc45b72714726b7aac3aaf1Jeff Garzik
843bdd4dddee325a7dce3e84cf48201a06aa8508aa4Jeff Garzik	writelfl((pp->crpb_dma & EDMA_RSP_Q_BASE_LO_MASK) | index,
844c5d3e45a2200a0905dc45b72714726b7aac3aaf1Jeff Garzik		 port_mmio + EDMA_RSP_Q_OUT_PTR_OFS);
845c5d3e45a2200a0905dc45b72714726b7aac3aaf1Jeff Garzik}
846c5d3e45a2200a0905dc45b72714726b7aac3aaf1Jeff Garzik
84705b308e1df6d9d673daedb517969241f41278b52Brett Russ/**
84805b308e1df6d9d673daedb517969241f41278b52Brett Russ *      mv_start_dma - Enable eDMA engine
84905b308e1df6d9d673daedb517969241f41278b52Brett Russ *      @base: port base address
85005b308e1df6d9d673daedb517969241f41278b52Brett Russ *      @pp: port private data
85105b308e1df6d9d673daedb517969241f41278b52Brett Russ *
852beec7dbc6ff003bbc94de62b3323519c878fb2acTejun Heo *      Verify the local cache of the eDMA state is accurate with a
853beec7dbc6ff003bbc94de62b3323519c878fb2acTejun Heo *      WARN_ON.
85405b308e1df6d9d673daedb517969241f41278b52Brett Russ *
85505b308e1df6d9d673daedb517969241f41278b52Brett Russ *      LOCKING:
85605b308e1df6d9d673daedb517969241f41278b52Brett Russ *      Inherited from caller.
85705b308e1df6d9d673daedb517969241f41278b52Brett Russ */
8580c58912e192fc3a4835d772aafa40b72552b819fMark Lordstatic void mv_start_dma(struct ata_port *ap, void __iomem *port_mmio,
859721091685f853ba4e6c49f26f989db0b1a811250Mark Lord			 struct mv_port_priv *pp, u8 protocol)
86020f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ{
861721091685f853ba4e6c49f26f989db0b1a811250Mark Lord	int want_ncq = (protocol == ATA_PROT_NCQ);
862721091685f853ba4e6c49f26f989db0b1a811250Mark Lord
863721091685f853ba4e6c49f26f989db0b1a811250Mark Lord	if (pp->pp_flags & MV_PP_FLAG_EDMA_EN) {
864721091685f853ba4e6c49f26f989db0b1a811250Mark Lord		int using_ncq = ((pp->pp_flags & MV_PP_FLAG_NCQ_EN) != 0);
865721091685f853ba4e6c49f26f989db0b1a811250Mark Lord		if (want_ncq != using_ncq)
866721091685f853ba4e6c49f26f989db0b1a811250Mark Lord			__mv_stop_dma(ap);
867721091685f853ba4e6c49f26f989db0b1a811250Mark Lord	}
868c5d3e45a2200a0905dc45b72714726b7aac3aaf1Jeff Garzik	if (!(pp->pp_flags & MV_PP_FLAG_EDMA_EN)) {
8690c58912e192fc3a4835d772aafa40b72552b819fMark Lord		struct mv_host_priv *hpriv = ap->host->private_data;
8700c58912e192fc3a4835d772aafa40b72552b819fMark Lord		int hard_port = mv_hardport_from_port(ap->port_no);
8710c58912e192fc3a4835d772aafa40b72552b819fMark Lord		void __iomem *hc_mmio = mv_hc_base_from_port(
8720c58912e192fc3a4835d772aafa40b72552b819fMark Lord				ap->host->iomap[MV_PRIMARY_BAR], hard_port);
8730c58912e192fc3a4835d772aafa40b72552b819fMark Lord		u32 hc_irq_cause, ipending;
8740c58912e192fc3a4835d772aafa40b72552b819fMark Lord
875bdd4dddee325a7dce3e84cf48201a06aa8508aa4Jeff Garzik		/* clear EDMA event indicators, if any */
876f630d562829fcd8160a118f98c1e5b9cdb4e703eMark Lord		writelfl(0, port_mmio + EDMA_ERR_IRQ_CAUSE_OFS);
877bdd4dddee325a7dce3e84cf48201a06aa8508aa4Jeff Garzik
8780c58912e192fc3a4835d772aafa40b72552b819fMark Lord		/* clear EDMA interrupt indicator, if any */
8790c58912e192fc3a4835d772aafa40b72552b819fMark Lord		hc_irq_cause = readl(hc_mmio + HC_IRQ_CAUSE_OFS);
8800c58912e192fc3a4835d772aafa40b72552b819fMark Lord		ipending = (DEV_IRQ << hard_port) |
8810c58912e192fc3a4835d772aafa40b72552b819fMark Lord				(CRPB_DMA_DONE << hard_port);
8820c58912e192fc3a4835d772aafa40b72552b819fMark Lord		if (hc_irq_cause & ipending) {
8830c58912e192fc3a4835d772aafa40b72552b819fMark Lord			writelfl(hc_irq_cause & ~ipending,
8840c58912e192fc3a4835d772aafa40b72552b819fMark Lord				 hc_mmio + HC_IRQ_CAUSE_OFS);
8850c58912e192fc3a4835d772aafa40b72552b819fMark Lord		}
8860c58912e192fc3a4835d772aafa40b72552b819fMark Lord
887721091685f853ba4e6c49f26f989db0b1a811250Mark Lord		mv_edma_cfg(pp, hpriv, port_mmio, want_ncq);
8880c58912e192fc3a4835d772aafa40b72552b819fMark Lord
8890c58912e192fc3a4835d772aafa40b72552b819fMark Lord		/* clear FIS IRQ Cause */
8900c58912e192fc3a4835d772aafa40b72552b819fMark Lord		writelfl(0, port_mmio + SATA_FIS_IRQ_CAUSE_OFS);
8910c58912e192fc3a4835d772aafa40b72552b819fMark Lord
892f630d562829fcd8160a118f98c1e5b9cdb4e703eMark Lord		mv_set_edma_ptrs(port_mmio, hpriv, pp);
893bdd4dddee325a7dce3e84cf48201a06aa8508aa4Jeff Garzik
894f630d562829fcd8160a118f98c1e5b9cdb4e703eMark Lord		writelfl(EDMA_EN, port_mmio + EDMA_CMD_OFS);
895afb0edd922c7ed6e73678730921dfcccebec17e8Brett Russ		pp->pp_flags |= MV_PP_FLAG_EDMA_EN;
896afb0edd922c7ed6e73678730921dfcccebec17e8Brett Russ	}
897f630d562829fcd8160a118f98c1e5b9cdb4e703eMark Lord	WARN_ON(!(EDMA_EN & readl(port_mmio + EDMA_CMD_OFS)));
89820f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ}
89920f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ
90005b308e1df6d9d673daedb517969241f41278b52Brett Russ/**
9010ea9e179f436f153fc19fdaef7abbc1e0da20762Jeff Garzik *      __mv_stop_dma - Disable eDMA engine
90205b308e1df6d9d673daedb517969241f41278b52Brett Russ *      @ap: ATA channel to manipulate
90305b308e1df6d9d673daedb517969241f41278b52Brett Russ *
904beec7dbc6ff003bbc94de62b3323519c878fb2acTejun Heo *      Verify the local cache of the eDMA state is accurate with a
905beec7dbc6ff003bbc94de62b3323519c878fb2acTejun Heo *      WARN_ON.
90605b308e1df6d9d673daedb517969241f41278b52Brett Russ *
90705b308e1df6d9d673daedb517969241f41278b52Brett Russ *      LOCKING:
90805b308e1df6d9d673daedb517969241f41278b52Brett Russ *      Inherited from caller.
90905b308e1df6d9d673daedb517969241f41278b52Brett Russ */
9100ea9e179f436f153fc19fdaef7abbc1e0da20762Jeff Garzikstatic int __mv_stop_dma(struct ata_port *ap)
91120f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ{
91231961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ	void __iomem *port_mmio = mv_ap_base(ap);
91331961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ	struct mv_port_priv *pp	= ap->private_data;
91431961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ	u32 reg;
915c5d3e45a2200a0905dc45b72714726b7aac3aaf1Jeff Garzik	int i, err = 0;
91631961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ
9174537deb5e90b717a725b3d74b58b4bb1d28443d0Jeff Garzik	if (pp->pp_flags & MV_PP_FLAG_EDMA_EN) {
918afb0edd922c7ed6e73678730921dfcccebec17e8Brett Russ		/* Disable EDMA if active.   The disable bit auto clears.
91931961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ		 */
92031961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ		writelfl(EDMA_DS, port_mmio + EDMA_CMD_OFS);
92131961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ		pp->pp_flags &= ~MV_PP_FLAG_EDMA_EN;
922afb0edd922c7ed6e73678730921dfcccebec17e8Brett Russ	} else {
923beec7dbc6ff003bbc94de62b3323519c878fb2acTejun Heo		WARN_ON(EDMA_EN & readl(port_mmio + EDMA_CMD_OFS));
9242dcb407e61458ded17503d6bd12b8c064965368bJeff Garzik	}
9258b260248d9e0e8b64bb72fd4dee03ad86984c344Jeff Garzik
92631961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ	/* now properly wait for the eDMA to stop */
92731961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ	for (i = 1000; i > 0; i--) {
92831961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ		reg = readl(port_mmio + EDMA_CMD_OFS);
9294537deb5e90b717a725b3d74b58b4bb1d28443d0Jeff Garzik		if (!(reg & EDMA_EN))
93031961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ			break;
9314537deb5e90b717a725b3d74b58b4bb1d28443d0Jeff Garzik
93231961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ		udelay(100);
93331961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ	}
93431961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ
935c5d3e45a2200a0905dc45b72714726b7aac3aaf1Jeff Garzik	if (reg & EDMA_EN) {
936f15a1dafed22d5037e0feea7528e1eeb28a1a7a3Tejun Heo		ata_port_printk(ap, KERN_ERR, "Unable to stop eDMA\n");
937c5d3e45a2200a0905dc45b72714726b7aac3aaf1Jeff Garzik		err = -EIO;
93831961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ	}
939c5d3e45a2200a0905dc45b72714726b7aac3aaf1Jeff Garzik
940c5d3e45a2200a0905dc45b72714726b7aac3aaf1Jeff Garzik	return err;
94120f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ}
94220f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ
9430ea9e179f436f153fc19fdaef7abbc1e0da20762Jeff Garzikstatic int mv_stop_dma(struct ata_port *ap)
9440ea9e179f436f153fc19fdaef7abbc1e0da20762Jeff Garzik{
9450ea9e179f436f153fc19fdaef7abbc1e0da20762Jeff Garzik	unsigned long flags;
9460ea9e179f436f153fc19fdaef7abbc1e0da20762Jeff Garzik	int rc;
9470ea9e179f436f153fc19fdaef7abbc1e0da20762Jeff Garzik
9480ea9e179f436f153fc19fdaef7abbc1e0da20762Jeff Garzik	spin_lock_irqsave(&ap->host->lock, flags);
9490ea9e179f436f153fc19fdaef7abbc1e0da20762Jeff Garzik	rc = __mv_stop_dma(ap);
9500ea9e179f436f153fc19fdaef7abbc1e0da20762Jeff Garzik	spin_unlock_irqrestore(&ap->host->lock, flags);
9510ea9e179f436f153fc19fdaef7abbc1e0da20762Jeff Garzik
9520ea9e179f436f153fc19fdaef7abbc1e0da20762Jeff Garzik	return rc;
9530ea9e179f436f153fc19fdaef7abbc1e0da20762Jeff Garzik}
9540ea9e179f436f153fc19fdaef7abbc1e0da20762Jeff Garzik
9558a70f8dc08dd40b7f8ac77280eaa99a8c6bc46f4Jeff Garzik#ifdef ATA_DEBUG
95631961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russstatic void mv_dump_mem(void __iomem *start, unsigned bytes)
95720f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ{
95831961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ	int b, w;
95931961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ	for (b = 0; b < bytes; ) {
96031961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ		DPRINTK("%p: ", start + b);
96131961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ		for (w = 0; b < bytes && w < 4; w++) {
9622dcb407e61458ded17503d6bd12b8c064965368bJeff Garzik			printk("%08x ", readl(start + b));
96331961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ			b += sizeof(u32);
96431961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ		}
96531961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ		printk("\n");
96631961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ	}
96731961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ}
9688a70f8dc08dd40b7f8ac77280eaa99a8c6bc46f4Jeff Garzik#endif
9698a70f8dc08dd40b7f8ac77280eaa99a8c6bc46f4Jeff Garzik
97031961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russstatic void mv_dump_pci_cfg(struct pci_dev *pdev, unsigned bytes)
97131961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ{
97231961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ#ifdef ATA_DEBUG
97331961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ	int b, w;
97431961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ	u32 dw;
97531961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ	for (b = 0; b < bytes; ) {
97631961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ		DPRINTK("%02x: ", b);
97731961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ		for (w = 0; b < bytes && w < 4; w++) {
9782dcb407e61458ded17503d6bd12b8c064965368bJeff Garzik			(void) pci_read_config_dword(pdev, b, &dw);
9792dcb407e61458ded17503d6bd12b8c064965368bJeff Garzik			printk("%08x ", dw);
98031961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ			b += sizeof(u32);
98131961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ		}
98231961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ		printk("\n");
98331961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ	}
98431961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ#endif
98531961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ}
98631961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russstatic void mv_dump_all_regs(void __iomem *mmio_base, int port,
98731961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ			     struct pci_dev *pdev)
98831961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ{
98931961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ#ifdef ATA_DEBUG
9908b260248d9e0e8b64bb72fd4dee03ad86984c344Jeff Garzik	void __iomem *hc_base = mv_hc_base(mmio_base,
99131961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ					   port >> MV_PORT_HC_SHIFT);
99231961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ	void __iomem *port_base;
99331961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ	int start_port, num_ports, p, start_hc, num_hcs, hc;
99431961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ
99531961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ	if (0 > port) {
99631961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ		start_hc = start_port = 0;
99731961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ		num_ports = 8;		/* shld be benign for 4 port devs */
99831961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ		num_hcs = 2;
99931961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ	} else {
100031961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ		start_hc = port >> MV_PORT_HC_SHIFT;
100131961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ		start_port = port;
100231961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ		num_ports = num_hcs = 1;
100331961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ	}
10048b260248d9e0e8b64bb72fd4dee03ad86984c344Jeff Garzik	DPRINTK("All registers for port(s) %u-%u:\n", start_port,
100531961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ		num_ports > 1 ? num_ports - 1 : start_port);
100631961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ
100731961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ	if (NULL != pdev) {
100831961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ		DPRINTK("PCI config space regs:\n");
100931961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ		mv_dump_pci_cfg(pdev, 0x68);
101031961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ	}
101131961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ	DPRINTK("PCI regs:\n");
101231961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ	mv_dump_mem(mmio_base+0xc00, 0x3c);
101331961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ	mv_dump_mem(mmio_base+0xd00, 0x34);
101431961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ	mv_dump_mem(mmio_base+0xf00, 0x4);
101531961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ	mv_dump_mem(mmio_base+0x1d00, 0x6c);
101631961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ	for (hc = start_hc; hc < start_hc + num_hcs; hc++) {
1017d220c37e0a3c9a47ae00e87e044d963b3ea040bcDan Aloni		hc_base = mv_hc_base(mmio_base, hc);
101831961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ		DPRINTK("HC regs (HC %i):\n", hc);
101931961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ		mv_dump_mem(hc_base, 0x1c);
102031961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ	}
102131961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ	for (p = start_port; p < start_port + num_ports; p++) {
102231961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ		port_base = mv_port_base(mmio_base, p);
10232dcb407e61458ded17503d6bd12b8c064965368bJeff Garzik		DPRINTK("EDMA regs (port %i):\n", p);
102431961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ		mv_dump_mem(port_base, 0x54);
10252dcb407e61458ded17503d6bd12b8c064965368bJeff Garzik		DPRINTK("SATA regs (port %i):\n", p);
102631961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ		mv_dump_mem(port_base+0x300, 0x60);
102731961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ	}
102831961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ#endif
102920f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ}
103020f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ
103120f733e7d75a16bffc34842b7682c9247dd5f954Brett Russstatic unsigned int mv_scr_offset(unsigned int sc_reg_in)
103220f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ{
103320f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ	unsigned int ofs;
103420f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ
103520f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ	switch (sc_reg_in) {
103620f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ	case SCR_STATUS:
103720f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ	case SCR_CONTROL:
103820f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ	case SCR_ERROR:
103920f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ		ofs = SATA_STATUS_OFS + (sc_reg_in * sizeof(u32));
104020f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ		break;
104120f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ	case SCR_ACTIVE:
104220f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ		ofs = SATA_ACTIVE_OFS;   /* active is not with the others */
104320f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ		break;
104420f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ	default:
104520f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ		ofs = 0xffffffffU;
104620f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ		break;
104720f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ	}
104820f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ	return ofs;
104920f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ}
105020f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ
1051da3dbb17a0e9a9ec7f5aed95f1fddadb790edc9dTejun Heostatic int mv_scr_read(struct ata_port *ap, unsigned int sc_reg_in, u32 *val)
105220f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ{
105320f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ	unsigned int ofs = mv_scr_offset(sc_reg_in);
105420f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ
1055da3dbb17a0e9a9ec7f5aed95f1fddadb790edc9dTejun Heo	if (ofs != 0xffffffffU) {
1056da3dbb17a0e9a9ec7f5aed95f1fddadb790edc9dTejun Heo		*val = readl(mv_ap_base(ap) + ofs);
1057da3dbb17a0e9a9ec7f5aed95f1fddadb790edc9dTejun Heo		return 0;
1058da3dbb17a0e9a9ec7f5aed95f1fddadb790edc9dTejun Heo	} else
1059da3dbb17a0e9a9ec7f5aed95f1fddadb790edc9dTejun Heo		return -EINVAL;
106020f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ}
106120f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ
1062da3dbb17a0e9a9ec7f5aed95f1fddadb790edc9dTejun Heostatic int mv_scr_write(struct ata_port *ap, unsigned int sc_reg_in, u32 val)
106320f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ{
106420f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ	unsigned int ofs = mv_scr_offset(sc_reg_in);
106520f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ
1066da3dbb17a0e9a9ec7f5aed95f1fddadb790edc9dTejun Heo	if (ofs != 0xffffffffU) {
106720f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ		writelfl(val, mv_ap_base(ap) + ofs);
1068da3dbb17a0e9a9ec7f5aed95f1fddadb790edc9dTejun Heo		return 0;
1069da3dbb17a0e9a9ec7f5aed95f1fddadb790edc9dTejun Heo	} else
1070da3dbb17a0e9a9ec7f5aed95f1fddadb790edc9dTejun Heo		return -EINVAL;
107120f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ}
107220f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ
1073f273827e2aadcf2f74a7bdc9ad715a1b20ea7ddaMark Lordstatic void mv6_dev_config(struct ata_device *adev)
1074f273827e2aadcf2f74a7bdc9ad715a1b20ea7ddaMark Lord{
1075f273827e2aadcf2f74a7bdc9ad715a1b20ea7ddaMark Lord	/*
1076f273827e2aadcf2f74a7bdc9ad715a1b20ea7ddaMark Lord	 * We don't have hob_nsect when doing NCQ commands on Gen-II.
1077f273827e2aadcf2f74a7bdc9ad715a1b20ea7ddaMark Lord	 * See mv_qc_prep() for more info.
1078f273827e2aadcf2f74a7bdc9ad715a1b20ea7ddaMark Lord	 */
1079f273827e2aadcf2f74a7bdc9ad715a1b20ea7ddaMark Lord	if (adev->flags & ATA_DFLAG_NCQ)
1080f273827e2aadcf2f74a7bdc9ad715a1b20ea7ddaMark Lord		if (adev->max_sectors > ATA_MAX_SECTORS)
1081f273827e2aadcf2f74a7bdc9ad715a1b20ea7ddaMark Lord			adev->max_sectors = ATA_MAX_SECTORS;
1082f273827e2aadcf2f74a7bdc9ad715a1b20ea7ddaMark Lord}
1083f273827e2aadcf2f74a7bdc9ad715a1b20ea7ddaMark Lord
1084721091685f853ba4e6c49f26f989db0b1a811250Mark Lordstatic void mv_edma_cfg(struct mv_port_priv *pp, struct mv_host_priv *hpriv,
1085721091685f853ba4e6c49f26f989db0b1a811250Mark Lord			void __iomem *port_mmio, int want_ncq)
1086e4e7b89280d1d666e2c09e5ad36cf071796c4c7eJeff Garzik{
10870c58912e192fc3a4835d772aafa40b72552b819fMark Lord	u32 cfg;
1088e4e7b89280d1d666e2c09e5ad36cf071796c4c7eJeff Garzik
1089e4e7b89280d1d666e2c09e5ad36cf071796c4c7eJeff Garzik	/* set up non-NCQ EDMA configuration */
10900c58912e192fc3a4835d772aafa40b72552b819fMark Lord	cfg = EDMA_CFG_Q_DEPTH;		/* always 0x1f for *all* chips */
1091e4e7b89280d1d666e2c09e5ad36cf071796c4c7eJeff Garzik
10920c58912e192fc3a4835d772aafa40b72552b819fMark Lord	if (IS_GEN_I(hpriv))
1093e4e7b89280d1d666e2c09e5ad36cf071796c4c7eJeff Garzik		cfg |= (1 << 8);	/* enab config burst size mask */
1094e4e7b89280d1d666e2c09e5ad36cf071796c4c7eJeff Garzik
10950c58912e192fc3a4835d772aafa40b72552b819fMark Lord	else if (IS_GEN_II(hpriv))
1096e4e7b89280d1d666e2c09e5ad36cf071796c4c7eJeff Garzik		cfg |= EDMA_CFG_RD_BRST_EXT | EDMA_CFG_WR_BUFF_LEN;
1097e4e7b89280d1d666e2c09e5ad36cf071796c4c7eJeff Garzik
1098e4e7b89280d1d666e2c09e5ad36cf071796c4c7eJeff Garzik	else if (IS_GEN_IIE(hpriv)) {
1099e728eabea110da90e69c05855e3a11174edb77efJeff Garzik		cfg |= (1 << 23);	/* do not mask PM field in rx'd FIS */
1100e728eabea110da90e69c05855e3a11174edb77efJeff Garzik		cfg |= (1 << 22);	/* enab 4-entry host queue cache */
1101e4e7b89280d1d666e2c09e5ad36cf071796c4c7eJeff Garzik		cfg |= (1 << 18);	/* enab early completion */
1102e728eabea110da90e69c05855e3a11174edb77efJeff Garzik		cfg |= (1 << 17);	/* enab cut-through (dis stor&forwrd) */
1103e4e7b89280d1d666e2c09e5ad36cf071796c4c7eJeff Garzik	}
1104e4e7b89280d1d666e2c09e5ad36cf071796c4c7eJeff Garzik
1105721091685f853ba4e6c49f26f989db0b1a811250Mark Lord	if (want_ncq) {
1106721091685f853ba4e6c49f26f989db0b1a811250Mark Lord		cfg |= EDMA_CFG_NCQ;
1107721091685f853ba4e6c49f26f989db0b1a811250Mark Lord		pp->pp_flags |=  MV_PP_FLAG_NCQ_EN;
1108721091685f853ba4e6c49f26f989db0b1a811250Mark Lord	} else
1109721091685f853ba4e6c49f26f989db0b1a811250Mark Lord		pp->pp_flags &= ~MV_PP_FLAG_NCQ_EN;
1110721091685f853ba4e6c49f26f989db0b1a811250Mark Lord
1111e4e7b89280d1d666e2c09e5ad36cf071796c4c7eJeff Garzik	writelfl(cfg, port_mmio + EDMA_CFG_OFS);
1112e4e7b89280d1d666e2c09e5ad36cf071796c4c7eJeff Garzik}
1113e4e7b89280d1d666e2c09e5ad36cf071796c4c7eJeff Garzik
1114da2fa9baf06f33a8fa7aa3f56c9f2b4070ceca0eMark Lordstatic void mv_port_free_dma_mem(struct ata_port *ap)
1115da2fa9baf06f33a8fa7aa3f56c9f2b4070ceca0eMark Lord{
1116da2fa9baf06f33a8fa7aa3f56c9f2b4070ceca0eMark Lord	struct mv_host_priv *hpriv = ap->host->private_data;
1117da2fa9baf06f33a8fa7aa3f56c9f2b4070ceca0eMark Lord	struct mv_port_priv *pp = ap->private_data;
1118eb73d558d1c1c931de0b3a86af962c77d74ef688Mark Lord	int tag;
1119da2fa9baf06f33a8fa7aa3f56c9f2b4070ceca0eMark Lord
1120da2fa9baf06f33a8fa7aa3f56c9f2b4070ceca0eMark Lord	if (pp->crqb) {
1121da2fa9baf06f33a8fa7aa3f56c9f2b4070ceca0eMark Lord		dma_pool_free(hpriv->crqb_pool, pp->crqb, pp->crqb_dma);
1122da2fa9baf06f33a8fa7aa3f56c9f2b4070ceca0eMark Lord		pp->crqb = NULL;
1123da2fa9baf06f33a8fa7aa3f56c9f2b4070ceca0eMark Lord	}
1124da2fa9baf06f33a8fa7aa3f56c9f2b4070ceca0eMark Lord	if (pp->crpb) {
1125da2fa9baf06f33a8fa7aa3f56c9f2b4070ceca0eMark Lord		dma_pool_free(hpriv->crpb_pool, pp->crpb, pp->crpb_dma);
1126da2fa9baf06f33a8fa7aa3f56c9f2b4070ceca0eMark Lord		pp->crpb = NULL;
1127da2fa9baf06f33a8fa7aa3f56c9f2b4070ceca0eMark Lord	}
1128eb73d558d1c1c931de0b3a86af962c77d74ef688Mark Lord	/*
1129eb73d558d1c1c931de0b3a86af962c77d74ef688Mark Lord	 * For GEN_I, there's no NCQ, so we have only a single sg_tbl.
1130eb73d558d1c1c931de0b3a86af962c77d74ef688Mark Lord	 * For later hardware, we have one unique sg_tbl per NCQ tag.
1131eb73d558d1c1c931de0b3a86af962c77d74ef688Mark Lord	 */
1132eb73d558d1c1c931de0b3a86af962c77d74ef688Mark Lord	for (tag = 0; tag < MV_MAX_Q_DEPTH; ++tag) {
1133eb73d558d1c1c931de0b3a86af962c77d74ef688Mark Lord		if (pp->sg_tbl[tag]) {
1134eb73d558d1c1c931de0b3a86af962c77d74ef688Mark Lord			if (tag == 0 || !IS_GEN_I(hpriv))
1135eb73d558d1c1c931de0b3a86af962c77d74ef688Mark Lord				dma_pool_free(hpriv->sg_tbl_pool,
1136eb73d558d1c1c931de0b3a86af962c77d74ef688Mark Lord					      pp->sg_tbl[tag],
1137eb73d558d1c1c931de0b3a86af962c77d74ef688Mark Lord					      pp->sg_tbl_dma[tag]);
1138eb73d558d1c1c931de0b3a86af962c77d74ef688Mark Lord			pp->sg_tbl[tag] = NULL;
1139eb73d558d1c1c931de0b3a86af962c77d74ef688Mark Lord		}
1140da2fa9baf06f33a8fa7aa3f56c9f2b4070ceca0eMark Lord	}
1141da2fa9baf06f33a8fa7aa3f56c9f2b4070ceca0eMark Lord}
1142da2fa9baf06f33a8fa7aa3f56c9f2b4070ceca0eMark Lord
114305b308e1df6d9d673daedb517969241f41278b52Brett Russ/**
114405b308e1df6d9d673daedb517969241f41278b52Brett Russ *      mv_port_start - Port specific init/start routine.
114505b308e1df6d9d673daedb517969241f41278b52Brett Russ *      @ap: ATA channel to manipulate
114605b308e1df6d9d673daedb517969241f41278b52Brett Russ *
114705b308e1df6d9d673daedb517969241f41278b52Brett Russ *      Allocate and point to DMA memory, init port private memory,
114805b308e1df6d9d673daedb517969241f41278b52Brett Russ *      zero indices.
114905b308e1df6d9d673daedb517969241f41278b52Brett Russ *
115005b308e1df6d9d673daedb517969241f41278b52Brett Russ *      LOCKING:
115105b308e1df6d9d673daedb517969241f41278b52Brett Russ *      Inherited from caller.
115205b308e1df6d9d673daedb517969241f41278b52Brett Russ */
115331961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russstatic int mv_port_start(struct ata_port *ap)
115431961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ{
1155cca3974e48607c3775dc73b544a5700b2e37c21aJeff Garzik	struct device *dev = ap->host->dev;
1156cca3974e48607c3775dc73b544a5700b2e37c21aJeff Garzik	struct mv_host_priv *hpriv = ap->host->private_data;
115731961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ	struct mv_port_priv *pp;
115831961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ	void __iomem *port_mmio = mv_ap_base(ap);
11590ea9e179f436f153fc19fdaef7abbc1e0da20762Jeff Garzik	unsigned long flags;
1160eb73d558d1c1c931de0b3a86af962c77d74ef688Mark Lord	int tag, rc;
116131961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ
116224dc5f33ea4b504cfbd23fa159a4cacba8e4d800Tejun Heo	pp = devm_kzalloc(dev, sizeof(*pp), GFP_KERNEL);
11636037d6bbdff65eb5a84fe35e140f4da4f7cc103aJeff Garzik	if (!pp)
116424dc5f33ea4b504cfbd23fa159a4cacba8e4d800Tejun Heo		return -ENOMEM;
1165da2fa9baf06f33a8fa7aa3f56c9f2b4070ceca0eMark Lord	ap->private_data = pp;
116631961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ
11676037d6bbdff65eb5a84fe35e140f4da4f7cc103aJeff Garzik	rc = ata_pad_alloc(ap, dev);
11686037d6bbdff65eb5a84fe35e140f4da4f7cc103aJeff Garzik	if (rc)
116924dc5f33ea4b504cfbd23fa159a4cacba8e4d800Tejun Heo		return rc;
11706037d6bbdff65eb5a84fe35e140f4da4f7cc103aJeff Garzik
1171da2fa9baf06f33a8fa7aa3f56c9f2b4070ceca0eMark Lord	pp->crqb = dma_pool_alloc(hpriv->crqb_pool, GFP_KERNEL, &pp->crqb_dma);
1172da2fa9baf06f33a8fa7aa3f56c9f2b4070ceca0eMark Lord	if (!pp->crqb)
1173da2fa9baf06f33a8fa7aa3f56c9f2b4070ceca0eMark Lord		return -ENOMEM;
1174da2fa9baf06f33a8fa7aa3f56c9f2b4070ceca0eMark Lord	memset(pp->crqb, 0, MV_CRQB_Q_SZ);
117531961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ
1176da2fa9baf06f33a8fa7aa3f56c9f2b4070ceca0eMark Lord	pp->crpb = dma_pool_alloc(hpriv->crpb_pool, GFP_KERNEL, &pp->crpb_dma);
1177da2fa9baf06f33a8fa7aa3f56c9f2b4070ceca0eMark Lord	if (!pp->crpb)
1178da2fa9baf06f33a8fa7aa3f56c9f2b4070ceca0eMark Lord		goto out_port_free_dma_mem;
1179da2fa9baf06f33a8fa7aa3f56c9f2b4070ceca0eMark Lord	memset(pp->crpb, 0, MV_CRPB_Q_SZ);
118031961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ
1181eb73d558d1c1c931de0b3a86af962c77d74ef688Mark Lord	/*
1182eb73d558d1c1c931de0b3a86af962c77d74ef688Mark Lord	 * For GEN_I, there's no NCQ, so we only allocate a single sg_tbl.
1183eb73d558d1c1c931de0b3a86af962c77d74ef688Mark Lord	 * For later hardware, we need one unique sg_tbl per NCQ tag.
1184eb73d558d1c1c931de0b3a86af962c77d74ef688Mark Lord	 */
1185eb73d558d1c1c931de0b3a86af962c77d74ef688Mark Lord	for (tag = 0; tag < MV_MAX_Q_DEPTH; ++tag) {
1186eb73d558d1c1c931de0b3a86af962c77d74ef688Mark Lord		if (tag == 0 || !IS_GEN_I(hpriv)) {
1187eb73d558d1c1c931de0b3a86af962c77d74ef688Mark Lord			pp->sg_tbl[tag] = dma_pool_alloc(hpriv->sg_tbl_pool,
1188eb73d558d1c1c931de0b3a86af962c77d74ef688Mark Lord					      GFP_KERNEL, &pp->sg_tbl_dma[tag]);
1189eb73d558d1c1c931de0b3a86af962c77d74ef688Mark Lord			if (!pp->sg_tbl[tag])
1190eb73d558d1c1c931de0b3a86af962c77d74ef688Mark Lord				goto out_port_free_dma_mem;
1191eb73d558d1c1c931de0b3a86af962c77d74ef688Mark Lord		} else {
1192eb73d558d1c1c931de0b3a86af962c77d74ef688Mark Lord			pp->sg_tbl[tag]     = pp->sg_tbl[0];
1193eb73d558d1c1c931de0b3a86af962c77d74ef688Mark Lord			pp->sg_tbl_dma[tag] = pp->sg_tbl_dma[0];
1194eb73d558d1c1c931de0b3a86af962c77d74ef688Mark Lord		}
1195eb73d558d1c1c931de0b3a86af962c77d74ef688Mark Lord	}
119631961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ
11970ea9e179f436f153fc19fdaef7abbc1e0da20762Jeff Garzik	spin_lock_irqsave(&ap->host->lock, flags);
11980ea9e179f436f153fc19fdaef7abbc1e0da20762Jeff Garzik
1199721091685f853ba4e6c49f26f989db0b1a811250Mark Lord	mv_edma_cfg(pp, hpriv, port_mmio, 0);
1200c5d3e45a2200a0905dc45b72714726b7aac3aaf1Jeff Garzik	mv_set_edma_ptrs(port_mmio, hpriv, pp);
120131961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ
12020ea9e179f436f153fc19fdaef7abbc1e0da20762Jeff Garzik	spin_unlock_irqrestore(&ap->host->lock, flags);
12030ea9e179f436f153fc19fdaef7abbc1e0da20762Jeff Garzik
120431961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ	/* Don't turn on EDMA here...do it before DMA commands only.  Else
120531961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ	 * we'll be unable to send non-data, PIO, etc due to restricted access
120631961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ	 * to shadow regs.
120731961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ	 */
120831961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ	return 0;
1209da2fa9baf06f33a8fa7aa3f56c9f2b4070ceca0eMark Lord
1210da2fa9baf06f33a8fa7aa3f56c9f2b4070ceca0eMark Lordout_port_free_dma_mem:
1211da2fa9baf06f33a8fa7aa3f56c9f2b4070ceca0eMark Lord	mv_port_free_dma_mem(ap);
1212da2fa9baf06f33a8fa7aa3f56c9f2b4070ceca0eMark Lord	return -ENOMEM;
121331961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ}
121431961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ
121505b308e1df6d9d673daedb517969241f41278b52Brett Russ/**
121605b308e1df6d9d673daedb517969241f41278b52Brett Russ *      mv_port_stop - Port specific cleanup/stop routine.
121705b308e1df6d9d673daedb517969241f41278b52Brett Russ *      @ap: ATA channel to manipulate
121805b308e1df6d9d673daedb517969241f41278b52Brett Russ *
121905b308e1df6d9d673daedb517969241f41278b52Brett Russ *      Stop DMA, cleanup port memory.
122005b308e1df6d9d673daedb517969241f41278b52Brett Russ *
122105b308e1df6d9d673daedb517969241f41278b52Brett Russ *      LOCKING:
1222cca3974e48607c3775dc73b544a5700b2e37c21aJeff Garzik *      This routine uses the host lock to protect the DMA stop.
122305b308e1df6d9d673daedb517969241f41278b52Brett Russ */
122431961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russstatic void mv_port_stop(struct ata_port *ap)
122531961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ{
122631961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ	mv_stop_dma(ap);
1227da2fa9baf06f33a8fa7aa3f56c9f2b4070ceca0eMark Lord	mv_port_free_dma_mem(ap);
122831961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ}
122931961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ
123005b308e1df6d9d673daedb517969241f41278b52Brett Russ/**
123105b308e1df6d9d673daedb517969241f41278b52Brett Russ *      mv_fill_sg - Fill out the Marvell ePRD (scatter gather) entries
123205b308e1df6d9d673daedb517969241f41278b52Brett Russ *      @qc: queued command whose SG list to source from
123305b308e1df6d9d673daedb517969241f41278b52Brett Russ *
123405b308e1df6d9d673daedb517969241f41278b52Brett Russ *      Populate the SG list and mark the last entry.
123505b308e1df6d9d673daedb517969241f41278b52Brett Russ *
123605b308e1df6d9d673daedb517969241f41278b52Brett Russ *      LOCKING:
123705b308e1df6d9d673daedb517969241f41278b52Brett Russ *      Inherited from caller.
123805b308e1df6d9d673daedb517969241f41278b52Brett Russ */
12396c08772e49622e90d39903e7ff0be1a0f463ac86Jeff Garzikstatic void mv_fill_sg(struct ata_queued_cmd *qc)
124031961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ{
124131961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ	struct mv_port_priv *pp = qc->ap->private_data;
1242972c26bdd6b58e7534473c4f7928584578cf43f4Jeff Garzik	struct scatterlist *sg;
12433be6cbd73f74b4a3da82cc7d6e1688a4ae595fc7Jeff Garzik	struct mv_sg *mv_sg, *last_sg = NULL;
1244ff2aeb1eb64c8a4770a6304f9addbae9f9828646Tejun Heo	unsigned int si;
124531961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ
1246eb73d558d1c1c931de0b3a86af962c77d74ef688Mark Lord	mv_sg = pp->sg_tbl[qc->tag];
1247ff2aeb1eb64c8a4770a6304f9addbae9f9828646Tejun Heo	for_each_sg(qc->sg, sg, qc->n_elem, si) {
1248d88184fb2348a50f7c34f5d49a901c875b2e0114Jeff Garzik		dma_addr_t addr = sg_dma_address(sg);
1249d88184fb2348a50f7c34f5d49a901c875b2e0114Jeff Garzik		u32 sg_len = sg_dma_len(sg);
125022374677d18c5eeefd3a283431d312b8c44fef02Jeff Garzik
12514007b493ee6e4a52c2b618ab8361847fba5bf116Olof Johansson		while (sg_len) {
12524007b493ee6e4a52c2b618ab8361847fba5bf116Olof Johansson			u32 offset = addr & 0xffff;
12534007b493ee6e4a52c2b618ab8361847fba5bf116Olof Johansson			u32 len = sg_len;
125422374677d18c5eeefd3a283431d312b8c44fef02Jeff Garzik
12554007b493ee6e4a52c2b618ab8361847fba5bf116Olof Johansson			if ((offset + sg_len > 0x10000))
12564007b493ee6e4a52c2b618ab8361847fba5bf116Olof Johansson				len = 0x10000 - offset;
12574007b493ee6e4a52c2b618ab8361847fba5bf116Olof Johansson
12584007b493ee6e4a52c2b618ab8361847fba5bf116Olof Johansson			mv_sg->addr = cpu_to_le32(addr & 0xffffffff);
12594007b493ee6e4a52c2b618ab8361847fba5bf116Olof Johansson			mv_sg->addr_hi = cpu_to_le32((addr >> 16) >> 16);
12606c08772e49622e90d39903e7ff0be1a0f463ac86Jeff Garzik			mv_sg->flags_size = cpu_to_le32(len & 0xffff);
12614007b493ee6e4a52c2b618ab8361847fba5bf116Olof Johansson
12624007b493ee6e4a52c2b618ab8361847fba5bf116Olof Johansson			sg_len -= len;
12634007b493ee6e4a52c2b618ab8361847fba5bf116Olof Johansson			addr += len;
12644007b493ee6e4a52c2b618ab8361847fba5bf116Olof Johansson
12653be6cbd73f74b4a3da82cc7d6e1688a4ae595fc7Jeff Garzik			last_sg = mv_sg;
12664007b493ee6e4a52c2b618ab8361847fba5bf116Olof Johansson			mv_sg++;
12674007b493ee6e4a52c2b618ab8361847fba5bf116Olof Johansson		}
126831961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ	}
12693be6cbd73f74b4a3da82cc7d6e1688a4ae595fc7Jeff Garzik
12703be6cbd73f74b4a3da82cc7d6e1688a4ae595fc7Jeff Garzik	if (likely(last_sg))
12713be6cbd73f74b4a3da82cc7d6e1688a4ae595fc7Jeff Garzik		last_sg->flags_size |= cpu_to_le32(EPRD_FLAG_END_OF_TBL);
127231961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ}
127331961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ
12745796d1c4c89efff823259fda35b08ea66ebf8b23Jeff Garzikstatic void mv_crqb_pack_cmd(__le16 *cmdw, u8 data, u8 addr, unsigned last)
127531961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ{
1276559eedad7f7764dacca33980127b4615011230e4Mark Lord	u16 tmp = data | (addr << CRQB_CMD_ADDR_SHIFT) | CRQB_CMD_CS |
127731961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ		(last ? CRQB_CMD_LAST : 0);
1278559eedad7f7764dacca33980127b4615011230e4Mark Lord	*cmdw = cpu_to_le16(tmp);
127931961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ}
128031961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ
128105b308e1df6d9d673daedb517969241f41278b52Brett Russ/**
128205b308e1df6d9d673daedb517969241f41278b52Brett Russ *      mv_qc_prep - Host specific command preparation.
128305b308e1df6d9d673daedb517969241f41278b52Brett Russ *      @qc: queued command to prepare
128405b308e1df6d9d673daedb517969241f41278b52Brett Russ *
128505b308e1df6d9d673daedb517969241f41278b52Brett Russ *      This routine simply redirects to the general purpose routine
128605b308e1df6d9d673daedb517969241f41278b52Brett Russ *      if command is not DMA.  Else, it handles prep of the CRQB
128705b308e1df6d9d673daedb517969241f41278b52Brett Russ *      (command request block), does some sanity checking, and calls
128805b308e1df6d9d673daedb517969241f41278b52Brett Russ *      the SG load routine.
128905b308e1df6d9d673daedb517969241f41278b52Brett Russ *
129005b308e1df6d9d673daedb517969241f41278b52Brett Russ *      LOCKING:
129105b308e1df6d9d673daedb517969241f41278b52Brett Russ *      Inherited from caller.
129205b308e1df6d9d673daedb517969241f41278b52Brett Russ */
129331961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russstatic void mv_qc_prep(struct ata_queued_cmd *qc)
129431961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ{
129531961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ	struct ata_port *ap = qc->ap;
129631961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ	struct mv_port_priv *pp = ap->private_data;
1297e14698745dd0de1ddbf5cd0cca4313a90f8c1cc1Mark Lord	__le16 *cw;
129831961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ	struct ata_taskfile *tf;
129931961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ	u16 flags = 0;
1300a6432436c5e14b416f27c8f87c5bf0bc36771f49Mark Lord	unsigned in_index;
130131961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ
1302138bfdd03f2c08cc62b6af3900fb7be1c696315bMark Lord	if ((qc->tf.protocol != ATA_PROT_DMA) &&
1303138bfdd03f2c08cc62b6af3900fb7be1c696315bMark Lord	    (qc->tf.protocol != ATA_PROT_NCQ))
130431961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ		return;
130520f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ
130631961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ	/* Fill in command request block
130731961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ	 */
1308e4e7b89280d1d666e2c09e5ad36cf071796c4c7eJeff Garzik	if (!(qc->tf.flags & ATA_TFLAG_WRITE))
130931961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ		flags |= CRQB_FLAG_READ;
1310beec7dbc6ff003bbc94de62b3323519c878fb2acTejun Heo	WARN_ON(MV_MAX_Q_DEPTH <= qc->tag);
131131961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ	flags |= qc->tag << CRQB_TAG_SHIFT;
131231961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ
1313bdd4dddee325a7dce3e84cf48201a06aa8508aa4Jeff Garzik	/* get current queue index from software */
1314bdd4dddee325a7dce3e84cf48201a06aa8508aa4Jeff Garzik	in_index = pp->req_idx & MV_MAX_Q_DEPTH_MASK;
1315a6432436c5e14b416f27c8f87c5bf0bc36771f49Mark Lord
1316a6432436c5e14b416f27c8f87c5bf0bc36771f49Mark Lord	pp->crqb[in_index].sg_addr =
1317eb73d558d1c1c931de0b3a86af962c77d74ef688Mark Lord		cpu_to_le32(pp->sg_tbl_dma[qc->tag] & 0xffffffff);
1318a6432436c5e14b416f27c8f87c5bf0bc36771f49Mark Lord	pp->crqb[in_index].sg_addr_hi =
1319eb73d558d1c1c931de0b3a86af962c77d74ef688Mark Lord		cpu_to_le32((pp->sg_tbl_dma[qc->tag] >> 16) >> 16);
1320a6432436c5e14b416f27c8f87c5bf0bc36771f49Mark Lord	pp->crqb[in_index].ctrl_flags = cpu_to_le16(flags);
132131961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ
1322a6432436c5e14b416f27c8f87c5bf0bc36771f49Mark Lord	cw = &pp->crqb[in_index].ata_cmd[0];
132331961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ	tf = &qc->tf;
132431961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ
132531961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ	/* Sadly, the CRQB cannot accomodate all registers--there are
132631961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ	 * only 11 bytes...so we must pick and choose required
132731961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ	 * registers based on the command.  So, we drop feature and
132831961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ	 * hob_feature for [RW] DMA commands, but they are needed for
132931961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ	 * NCQ.  NCQ will drop hob_nsect.
133020f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ	 */
133131961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ	switch (tf->command) {
133231961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ	case ATA_CMD_READ:
133331961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ	case ATA_CMD_READ_EXT:
133431961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ	case ATA_CMD_WRITE:
133531961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ	case ATA_CMD_WRITE_EXT:
1336c15d85c8f3f73b5f20aae7928e25b6996f16b328Jens Axboe	case ATA_CMD_WRITE_FUA_EXT:
133731961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ		mv_crqb_pack_cmd(cw++, tf->hob_nsect, ATA_REG_NSECT, 0);
133831961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ		break;
133931961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ	case ATA_CMD_FPDMA_READ:
134031961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ	case ATA_CMD_FPDMA_WRITE:
13418b260248d9e0e8b64bb72fd4dee03ad86984c344Jeff Garzik		mv_crqb_pack_cmd(cw++, tf->hob_feature, ATA_REG_FEATURE, 0);
134231961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ		mv_crqb_pack_cmd(cw++, tf->feature, ATA_REG_FEATURE, 0);
134331961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ		break;
134431961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ	default:
134531961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ		/* The only other commands EDMA supports in non-queued and
134631961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ		 * non-NCQ mode are: [RW] STREAM DMA and W DMA FUA EXT, none
134731961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ		 * of which are defined/used by Linux.  If we get here, this
134831961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ		 * driver needs work.
134931961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ		 *
135031961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ		 * FIXME: modify libata to give qc_prep a return value and
135131961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ		 * return error here.
135231961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ		 */
135331961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ		BUG_ON(tf->command);
135431961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ		break;
135531961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ	}
135631961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ	mv_crqb_pack_cmd(cw++, tf->nsect, ATA_REG_NSECT, 0);
135731961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ	mv_crqb_pack_cmd(cw++, tf->hob_lbal, ATA_REG_LBAL, 0);
135831961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ	mv_crqb_pack_cmd(cw++, tf->lbal, ATA_REG_LBAL, 0);
135931961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ	mv_crqb_pack_cmd(cw++, tf->hob_lbam, ATA_REG_LBAM, 0);
136031961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ	mv_crqb_pack_cmd(cw++, tf->lbam, ATA_REG_LBAM, 0);
136131961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ	mv_crqb_pack_cmd(cw++, tf->hob_lbah, ATA_REG_LBAH, 0);
136231961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ	mv_crqb_pack_cmd(cw++, tf->lbah, ATA_REG_LBAH, 0);
136331961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ	mv_crqb_pack_cmd(cw++, tf->device, ATA_REG_DEVICE, 0);
136431961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ	mv_crqb_pack_cmd(cw++, tf->command, ATA_REG_CMD, 1);	/* last */
136531961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ
1366e4e7b89280d1d666e2c09e5ad36cf071796c4c7eJeff Garzik	if (!(qc->flags & ATA_QCFLAG_DMAMAP))
1367e4e7b89280d1d666e2c09e5ad36cf071796c4c7eJeff Garzik		return;
1368e4e7b89280d1d666e2c09e5ad36cf071796c4c7eJeff Garzik	mv_fill_sg(qc);
1369e4e7b89280d1d666e2c09e5ad36cf071796c4c7eJeff Garzik}
1370e4e7b89280d1d666e2c09e5ad36cf071796c4c7eJeff Garzik
1371e4e7b89280d1d666e2c09e5ad36cf071796c4c7eJeff Garzik/**
1372e4e7b89280d1d666e2c09e5ad36cf071796c4c7eJeff Garzik *      mv_qc_prep_iie - Host specific command preparation.
1373e4e7b89280d1d666e2c09e5ad36cf071796c4c7eJeff Garzik *      @qc: queued command to prepare
1374e4e7b89280d1d666e2c09e5ad36cf071796c4c7eJeff Garzik *
1375e4e7b89280d1d666e2c09e5ad36cf071796c4c7eJeff Garzik *      This routine simply redirects to the general purpose routine
1376e4e7b89280d1d666e2c09e5ad36cf071796c4c7eJeff Garzik *      if command is not DMA.  Else, it handles prep of the CRQB
1377e4e7b89280d1d666e2c09e5ad36cf071796c4c7eJeff Garzik *      (command request block), does some sanity checking, and calls
1378e4e7b89280d1d666e2c09e5ad36cf071796c4c7eJeff Garzik *      the SG load routine.
1379e4e7b89280d1d666e2c09e5ad36cf071796c4c7eJeff Garzik *
1380e4e7b89280d1d666e2c09e5ad36cf071796c4c7eJeff Garzik *      LOCKING:
1381e4e7b89280d1d666e2c09e5ad36cf071796c4c7eJeff Garzik *      Inherited from caller.
1382e4e7b89280d1d666e2c09e5ad36cf071796c4c7eJeff Garzik */
1383e4e7b89280d1d666e2c09e5ad36cf071796c4c7eJeff Garzikstatic void mv_qc_prep_iie(struct ata_queued_cmd *qc)
1384e4e7b89280d1d666e2c09e5ad36cf071796c4c7eJeff Garzik{
1385e4e7b89280d1d666e2c09e5ad36cf071796c4c7eJeff Garzik	struct ata_port *ap = qc->ap;
1386e4e7b89280d1d666e2c09e5ad36cf071796c4c7eJeff Garzik	struct mv_port_priv *pp = ap->private_data;
1387e4e7b89280d1d666e2c09e5ad36cf071796c4c7eJeff Garzik	struct mv_crqb_iie *crqb;
1388e4e7b89280d1d666e2c09e5ad36cf071796c4c7eJeff Garzik	struct ata_taskfile *tf;
1389a6432436c5e14b416f27c8f87c5bf0bc36771f49Mark Lord	unsigned in_index;
1390e4e7b89280d1d666e2c09e5ad36cf071796c4c7eJeff Garzik	u32 flags = 0;
1391e4e7b89280d1d666e2c09e5ad36cf071796c4c7eJeff Garzik
1392138bfdd03f2c08cc62b6af3900fb7be1c696315bMark Lord	if ((qc->tf.protocol != ATA_PROT_DMA) &&
1393138bfdd03f2c08cc62b6af3900fb7be1c696315bMark Lord	    (qc->tf.protocol != ATA_PROT_NCQ))
1394e4e7b89280d1d666e2c09e5ad36cf071796c4c7eJeff Garzik		return;
1395e4e7b89280d1d666e2c09e5ad36cf071796c4c7eJeff Garzik
1396e4e7b89280d1d666e2c09e5ad36cf071796c4c7eJeff Garzik	/* Fill in Gen IIE command request block
1397e4e7b89280d1d666e2c09e5ad36cf071796c4c7eJeff Garzik	 */
1398e4e7b89280d1d666e2c09e5ad36cf071796c4c7eJeff Garzik	if (!(qc->tf.flags & ATA_TFLAG_WRITE))
1399e4e7b89280d1d666e2c09e5ad36cf071796c4c7eJeff Garzik		flags |= CRQB_FLAG_READ;
1400e4e7b89280d1d666e2c09e5ad36cf071796c4c7eJeff Garzik
1401beec7dbc6ff003bbc94de62b3323519c878fb2acTejun Heo	WARN_ON(MV_MAX_Q_DEPTH <= qc->tag);
1402e4e7b89280d1d666e2c09e5ad36cf071796c4c7eJeff Garzik	flags |= qc->tag << CRQB_TAG_SHIFT;
14038c0aeb4a483334613336ef895f34cecc0ecbbfa6Mark Lord	flags |= qc->tag << CRQB_HOSTQ_SHIFT;
1404e4e7b89280d1d666e2c09e5ad36cf071796c4c7eJeff Garzik
1405bdd4dddee325a7dce3e84cf48201a06aa8508aa4Jeff Garzik	/* get current queue index from software */
1406bdd4dddee325a7dce3e84cf48201a06aa8508aa4Jeff Garzik	in_index = pp->req_idx & MV_MAX_Q_DEPTH_MASK;
1407a6432436c5e14b416f27c8f87c5bf0bc36771f49Mark Lord
1408a6432436c5e14b416f27c8f87c5bf0bc36771f49Mark Lord	crqb = (struct mv_crqb_iie *) &pp->crqb[in_index];
1409eb73d558d1c1c931de0b3a86af962c77d74ef688Mark Lord	crqb->addr = cpu_to_le32(pp->sg_tbl_dma[qc->tag] & 0xffffffff);
1410eb73d558d1c1c931de0b3a86af962c77d74ef688Mark Lord	crqb->addr_hi = cpu_to_le32((pp->sg_tbl_dma[qc->tag] >> 16) >> 16);
1411e4e7b89280d1d666e2c09e5ad36cf071796c4c7eJeff Garzik	crqb->flags = cpu_to_le32(flags);
1412e4e7b89280d1d666e2c09e5ad36cf071796c4c7eJeff Garzik
1413e4e7b89280d1d666e2c09e5ad36cf071796c4c7eJeff Garzik	tf = &qc->tf;
1414e4e7b89280d1d666e2c09e5ad36cf071796c4c7eJeff Garzik	crqb->ata_cmd[0] = cpu_to_le32(
1415e4e7b89280d1d666e2c09e5ad36cf071796c4c7eJeff Garzik			(tf->command << 16) |
1416e4e7b89280d1d666e2c09e5ad36cf071796c4c7eJeff Garzik			(tf->feature << 24)
1417e4e7b89280d1d666e2c09e5ad36cf071796c4c7eJeff Garzik		);
1418e4e7b89280d1d666e2c09e5ad36cf071796c4c7eJeff Garzik	crqb->ata_cmd[1] = cpu_to_le32(
1419e4e7b89280d1d666e2c09e5ad36cf071796c4c7eJeff Garzik			(tf->lbal << 0) |
1420e4e7b89280d1d666e2c09e5ad36cf071796c4c7eJeff Garzik			(tf->lbam << 8) |
1421e4e7b89280d1d666e2c09e5ad36cf071796c4c7eJeff Garzik			(tf->lbah << 16) |
1422e4e7b89280d1d666e2c09e5ad36cf071796c4c7eJeff Garzik			(tf->device << 24)
1423e4e7b89280d1d666e2c09e5ad36cf071796c4c7eJeff Garzik		);
1424e4e7b89280d1d666e2c09e5ad36cf071796c4c7eJeff Garzik	crqb->ata_cmd[2] = cpu_to_le32(
1425e4e7b89280d1d666e2c09e5ad36cf071796c4c7eJeff Garzik			(tf->hob_lbal << 0) |
1426e4e7b89280d1d666e2c09e5ad36cf071796c4c7eJeff Garzik			(tf->hob_lbam << 8) |
1427e4e7b89280d1d666e2c09e5ad36cf071796c4c7eJeff Garzik			(tf->hob_lbah << 16) |
1428e4e7b89280d1d666e2c09e5ad36cf071796c4c7eJeff Garzik			(tf->hob_feature << 24)
1429e4e7b89280d1d666e2c09e5ad36cf071796c4c7eJeff Garzik		);
1430e4e7b89280d1d666e2c09e5ad36cf071796c4c7eJeff Garzik	crqb->ata_cmd[3] = cpu_to_le32(
1431e4e7b89280d1d666e2c09e5ad36cf071796c4c7eJeff Garzik			(tf->nsect << 0) |
1432e4e7b89280d1d666e2c09e5ad36cf071796c4c7eJeff Garzik			(tf->hob_nsect << 8)
1433e4e7b89280d1d666e2c09e5ad36cf071796c4c7eJeff Garzik		);
1434e4e7b89280d1d666e2c09e5ad36cf071796c4c7eJeff Garzik
1435e4e7b89280d1d666e2c09e5ad36cf071796c4c7eJeff Garzik	if (!(qc->flags & ATA_QCFLAG_DMAMAP))
143631961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ		return;
143731961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ	mv_fill_sg(qc);
143831961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ}
143931961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ
144005b308e1df6d9d673daedb517969241f41278b52Brett Russ/**
144105b308e1df6d9d673daedb517969241f41278b52Brett Russ *      mv_qc_issue - Initiate a command to the host
144205b308e1df6d9d673daedb517969241f41278b52Brett Russ *      @qc: queued command to start
144305b308e1df6d9d673daedb517969241f41278b52Brett Russ *
144405b308e1df6d9d673daedb517969241f41278b52Brett Russ *      This routine simply redirects to the general purpose routine
144505b308e1df6d9d673daedb517969241f41278b52Brett Russ *      if command is not DMA.  Else, it sanity checks our local
144605b308e1df6d9d673daedb517969241f41278b52Brett Russ *      caches of the request producer/consumer indices then enables
144705b308e1df6d9d673daedb517969241f41278b52Brett Russ *      DMA and bumps the request producer index.
144805b308e1df6d9d673daedb517969241f41278b52Brett Russ *
144905b308e1df6d9d673daedb517969241f41278b52Brett Russ *      LOCKING:
145005b308e1df6d9d673daedb517969241f41278b52Brett Russ *      Inherited from caller.
145105b308e1df6d9d673daedb517969241f41278b52Brett Russ */
14529a3d9eb0177eb10500d49cd283b35576082a522dTejun Heostatic unsigned int mv_qc_issue(struct ata_queued_cmd *qc)
145331961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ{
1454c5d3e45a2200a0905dc45b72714726b7aac3aaf1Jeff Garzik	struct ata_port *ap = qc->ap;
1455c5d3e45a2200a0905dc45b72714726b7aac3aaf1Jeff Garzik	void __iomem *port_mmio = mv_ap_base(ap);
1456c5d3e45a2200a0905dc45b72714726b7aac3aaf1Jeff Garzik	struct mv_port_priv *pp = ap->private_data;
1457bdd4dddee325a7dce3e84cf48201a06aa8508aa4Jeff Garzik	u32 in_index;
145831961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ
1459138bfdd03f2c08cc62b6af3900fb7be1c696315bMark Lord	if ((qc->tf.protocol != ATA_PROT_DMA) &&
1460138bfdd03f2c08cc62b6af3900fb7be1c696315bMark Lord	    (qc->tf.protocol != ATA_PROT_NCQ)) {
146131961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ		/* We're about to send a non-EDMA capable command to the
146231961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ		 * port.  Turn off EDMA so there won't be problems accessing
146331961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ		 * shadow block, etc registers.
146431961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ		 */
14650ea9e179f436f153fc19fdaef7abbc1e0da20762Jeff Garzik		__mv_stop_dma(ap);
146631961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ		return ata_qc_issue_prot(qc);
146731961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ	}
146831961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ
1469721091685f853ba4e6c49f26f989db0b1a811250Mark Lord	mv_start_dma(ap, port_mmio, pp, qc->tf.protocol);
1470bdd4dddee325a7dce3e84cf48201a06aa8508aa4Jeff Garzik
1471bdd4dddee325a7dce3e84cf48201a06aa8508aa4Jeff Garzik	pp->req_idx++;
147231961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ
1473bdd4dddee325a7dce3e84cf48201a06aa8508aa4Jeff Garzik	in_index = (pp->req_idx & MV_MAX_Q_DEPTH_MASK) << EDMA_REQ_Q_PTR_SHIFT;
147431961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ
147531961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ	/* and write the request in pointer to kick the EDMA to life */
1476bdd4dddee325a7dce3e84cf48201a06aa8508aa4Jeff Garzik	writelfl((pp->crqb_dma & EDMA_REQ_Q_BASE_LO_MASK) | in_index,
1477bdd4dddee325a7dce3e84cf48201a06aa8508aa4Jeff Garzik		 port_mmio + EDMA_REQ_Q_IN_PTR_OFS);
147831961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ
147931961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ	return 0;
148031961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ}
148131961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ
148205b308e1df6d9d673daedb517969241f41278b52Brett Russ/**
148305b308e1df6d9d673daedb517969241f41278b52Brett Russ *      mv_err_intr - Handle error interrupts on the port
148405b308e1df6d9d673daedb517969241f41278b52Brett Russ *      @ap: ATA channel to manipulate
14859b358e305c1d783c8a4ebf00344e95deb9e38f3dMark Lord *      @reset_allowed: bool: 0 == don't trigger from reset here
148605b308e1df6d9d673daedb517969241f41278b52Brett Russ *
148705b308e1df6d9d673daedb517969241f41278b52Brett Russ *      In most cases, just clear the interrupt and move on.  However,
148805b308e1df6d9d673daedb517969241f41278b52Brett Russ *      some cases require an eDMA reset, which is done right before
148905b308e1df6d9d673daedb517969241f41278b52Brett Russ *      the COMRESET in mv_phy_reset().  The SERR case requires a
149005b308e1df6d9d673daedb517969241f41278b52Brett Russ *      clear of pending errors in the SATA SERROR register.  Finally,
149105b308e1df6d9d673daedb517969241f41278b52Brett Russ *      if the port disabled DMA, update our cached copy to match.
149205b308e1df6d9d673daedb517969241f41278b52Brett Russ *
149305b308e1df6d9d673daedb517969241f41278b52Brett Russ *      LOCKING:
149405b308e1df6d9d673daedb517969241f41278b52Brett Russ *      Inherited from caller.
149505b308e1df6d9d673daedb517969241f41278b52Brett Russ */
1496bdd4dddee325a7dce3e84cf48201a06aa8508aa4Jeff Garzikstatic void mv_err_intr(struct ata_port *ap, struct ata_queued_cmd *qc)
149731961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ{
149831961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ	void __iomem *port_mmio = mv_ap_base(ap);
1499bdd4dddee325a7dce3e84cf48201a06aa8508aa4Jeff Garzik	u32 edma_err_cause, eh_freeze_mask, serr = 0;
1500bdd4dddee325a7dce3e84cf48201a06aa8508aa4Jeff Garzik	struct mv_port_priv *pp = ap->private_data;
1501bdd4dddee325a7dce3e84cf48201a06aa8508aa4Jeff Garzik	struct mv_host_priv *hpriv = ap->host->private_data;
1502bdd4dddee325a7dce3e84cf48201a06aa8508aa4Jeff Garzik	unsigned int edma_enabled = (pp->pp_flags & MV_PP_FLAG_EDMA_EN);
1503bdd4dddee325a7dce3e84cf48201a06aa8508aa4Jeff Garzik	unsigned int action = 0, err_mask = 0;
15049af5c9c97dc9d599281778864c72b385f0c63341Tejun Heo	struct ata_eh_info *ehi = &ap->link.eh_info;
150520f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ
1506bdd4dddee325a7dce3e84cf48201a06aa8508aa4Jeff Garzik	ata_ehi_clear_desc(ehi);
150720f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ
1508bdd4dddee325a7dce3e84cf48201a06aa8508aa4Jeff Garzik	if (!edma_enabled) {
1509bdd4dddee325a7dce3e84cf48201a06aa8508aa4Jeff Garzik		/* just a guess: do we need to do this? should we
1510bdd4dddee325a7dce3e84cf48201a06aa8508aa4Jeff Garzik		 * expand this, and do it in all cases?
1511bdd4dddee325a7dce3e84cf48201a06aa8508aa4Jeff Garzik		 */
1512936fd7328657884d5a69a55666c74a55aa83ca27Tejun Heo		sata_scr_read(&ap->link, SCR_ERROR, &serr);
1513936fd7328657884d5a69a55666c74a55aa83ca27Tejun Heo		sata_scr_write_flush(&ap->link, SCR_ERROR, serr);
151420f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ	}
1515bdd4dddee325a7dce3e84cf48201a06aa8508aa4Jeff Garzik
1516bdd4dddee325a7dce3e84cf48201a06aa8508aa4Jeff Garzik	edma_err_cause = readl(port_mmio + EDMA_ERR_IRQ_CAUSE_OFS);
1517bdd4dddee325a7dce3e84cf48201a06aa8508aa4Jeff Garzik
1518bdd4dddee325a7dce3e84cf48201a06aa8508aa4Jeff Garzik	ata_ehi_push_desc(ehi, "edma_err 0x%08x", edma_err_cause);
1519bdd4dddee325a7dce3e84cf48201a06aa8508aa4Jeff Garzik
1520bdd4dddee325a7dce3e84cf48201a06aa8508aa4Jeff Garzik	/*
1521bdd4dddee325a7dce3e84cf48201a06aa8508aa4Jeff Garzik	 * all generations share these EDMA error cause bits
1522bdd4dddee325a7dce3e84cf48201a06aa8508aa4Jeff Garzik	 */
1523bdd4dddee325a7dce3e84cf48201a06aa8508aa4Jeff Garzik
1524bdd4dddee325a7dce3e84cf48201a06aa8508aa4Jeff Garzik	if (edma_err_cause & EDMA_ERR_DEV)
1525bdd4dddee325a7dce3e84cf48201a06aa8508aa4Jeff Garzik		err_mask |= AC_ERR_DEV;
1526bdd4dddee325a7dce3e84cf48201a06aa8508aa4Jeff Garzik	if (edma_err_cause & (EDMA_ERR_D_PAR | EDMA_ERR_PRD_PAR |
15276c1153e00af8de755ec278d873a97c9ce2a72d10Jeff Garzik			EDMA_ERR_CRQB_PAR | EDMA_ERR_CRPB_PAR |
1528bdd4dddee325a7dce3e84cf48201a06aa8508aa4Jeff Garzik			EDMA_ERR_INTRL_PAR)) {
1529bdd4dddee325a7dce3e84cf48201a06aa8508aa4Jeff Garzik		err_mask |= AC_ERR_ATA_BUS;
1530bdd4dddee325a7dce3e84cf48201a06aa8508aa4Jeff Garzik		action |= ATA_EH_HARDRESET;
1531b64bbc39f2122a2276578e40144af69ef01decd4Tejun Heo		ata_ehi_push_desc(ehi, "parity error");
1532bdd4dddee325a7dce3e84cf48201a06aa8508aa4Jeff Garzik	}
1533bdd4dddee325a7dce3e84cf48201a06aa8508aa4Jeff Garzik	if (edma_err_cause & (EDMA_ERR_DEV_DCON | EDMA_ERR_DEV_CON)) {
1534bdd4dddee325a7dce3e84cf48201a06aa8508aa4Jeff Garzik		ata_ehi_hotplugged(ehi);
1535bdd4dddee325a7dce3e84cf48201a06aa8508aa4Jeff Garzik		ata_ehi_push_desc(ehi, edma_err_cause & EDMA_ERR_DEV_DCON ?
1536b64bbc39f2122a2276578e40144af69ef01decd4Tejun Heo			"dev disconnect" : "dev connect");
15373606a380692cf958355a40fc1aa336800c17baf1Mark Lord		action |= ATA_EH_HARDRESET;
1538bdd4dddee325a7dce3e84cf48201a06aa8508aa4Jeff Garzik	}
1539bdd4dddee325a7dce3e84cf48201a06aa8508aa4Jeff Garzik
1540ee9ccdf70163ca6408f6965e0fbc65baeac7312cJeff Garzik	if (IS_GEN_I(hpriv)) {
1541bdd4dddee325a7dce3e84cf48201a06aa8508aa4Jeff Garzik		eh_freeze_mask = EDMA_EH_FREEZE_5;
1542bdd4dddee325a7dce3e84cf48201a06aa8508aa4Jeff Garzik
1543bdd4dddee325a7dce3e84cf48201a06aa8508aa4Jeff Garzik		if (edma_err_cause & EDMA_ERR_SELF_DIS_5) {
1544bdd4dddee325a7dce3e84cf48201a06aa8508aa4Jeff Garzik			struct mv_port_priv *pp	= ap->private_data;
1545bdd4dddee325a7dce3e84cf48201a06aa8508aa4Jeff Garzik			pp->pp_flags &= ~MV_PP_FLAG_EDMA_EN;
1546b64bbc39f2122a2276578e40144af69ef01decd4Tejun Heo			ata_ehi_push_desc(ehi, "EDMA self-disable");
1547bdd4dddee325a7dce3e84cf48201a06aa8508aa4Jeff Garzik		}
1548bdd4dddee325a7dce3e84cf48201a06aa8508aa4Jeff Garzik	} else {
1549bdd4dddee325a7dce3e84cf48201a06aa8508aa4Jeff Garzik		eh_freeze_mask = EDMA_EH_FREEZE;
1550bdd4dddee325a7dce3e84cf48201a06aa8508aa4Jeff Garzik
1551bdd4dddee325a7dce3e84cf48201a06aa8508aa4Jeff Garzik		if (edma_err_cause & EDMA_ERR_SELF_DIS) {
1552bdd4dddee325a7dce3e84cf48201a06aa8508aa4Jeff Garzik			struct mv_port_priv *pp	= ap->private_data;
1553bdd4dddee325a7dce3e84cf48201a06aa8508aa4Jeff Garzik			pp->pp_flags &= ~MV_PP_FLAG_EDMA_EN;
1554b64bbc39f2122a2276578e40144af69ef01decd4Tejun Heo			ata_ehi_push_desc(ehi, "EDMA self-disable");
1555bdd4dddee325a7dce3e84cf48201a06aa8508aa4Jeff Garzik		}
1556bdd4dddee325a7dce3e84cf48201a06aa8508aa4Jeff Garzik
1557bdd4dddee325a7dce3e84cf48201a06aa8508aa4Jeff Garzik		if (edma_err_cause & EDMA_ERR_SERR) {
1558936fd7328657884d5a69a55666c74a55aa83ca27Tejun Heo			sata_scr_read(&ap->link, SCR_ERROR, &serr);
1559936fd7328657884d5a69a55666c74a55aa83ca27Tejun Heo			sata_scr_write_flush(&ap->link, SCR_ERROR, serr);
1560bdd4dddee325a7dce3e84cf48201a06aa8508aa4Jeff Garzik			err_mask = AC_ERR_ATA_BUS;
1561bdd4dddee325a7dce3e84cf48201a06aa8508aa4Jeff Garzik			action |= ATA_EH_HARDRESET;
1562bdd4dddee325a7dce3e84cf48201a06aa8508aa4Jeff Garzik		}
1563afb0edd922c7ed6e73678730921dfcccebec17e8Brett Russ	}
156420f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ
156520f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ	/* Clear EDMA now that SERR cleanup done */
15663606a380692cf958355a40fc1aa336800c17baf1Mark Lord	writelfl(~edma_err_cause, port_mmio + EDMA_ERR_IRQ_CAUSE_OFS);
156720f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ
1568bdd4dddee325a7dce3e84cf48201a06aa8508aa4Jeff Garzik	if (!err_mask) {
1569bdd4dddee325a7dce3e84cf48201a06aa8508aa4Jeff Garzik		err_mask = AC_ERR_OTHER;
1570bdd4dddee325a7dce3e84cf48201a06aa8508aa4Jeff Garzik		action |= ATA_EH_HARDRESET;
1571bdd4dddee325a7dce3e84cf48201a06aa8508aa4Jeff Garzik	}
1572bdd4dddee325a7dce3e84cf48201a06aa8508aa4Jeff Garzik
1573bdd4dddee325a7dce3e84cf48201a06aa8508aa4Jeff Garzik	ehi->serror |= serr;
1574bdd4dddee325a7dce3e84cf48201a06aa8508aa4Jeff Garzik	ehi->action |= action;
1575bdd4dddee325a7dce3e84cf48201a06aa8508aa4Jeff Garzik
1576bdd4dddee325a7dce3e84cf48201a06aa8508aa4Jeff Garzik	if (qc)
1577bdd4dddee325a7dce3e84cf48201a06aa8508aa4Jeff Garzik		qc->err_mask |= err_mask;
1578bdd4dddee325a7dce3e84cf48201a06aa8508aa4Jeff Garzik	else
1579bdd4dddee325a7dce3e84cf48201a06aa8508aa4Jeff Garzik		ehi->err_mask |= err_mask;
1580bdd4dddee325a7dce3e84cf48201a06aa8508aa4Jeff Garzik
1581bdd4dddee325a7dce3e84cf48201a06aa8508aa4Jeff Garzik	if (edma_err_cause & eh_freeze_mask)
1582bdd4dddee325a7dce3e84cf48201a06aa8508aa4Jeff Garzik		ata_port_freeze(ap);
1583bdd4dddee325a7dce3e84cf48201a06aa8508aa4Jeff Garzik	else
1584bdd4dddee325a7dce3e84cf48201a06aa8508aa4Jeff Garzik		ata_port_abort(ap);
1585bdd4dddee325a7dce3e84cf48201a06aa8508aa4Jeff Garzik}
1586bdd4dddee325a7dce3e84cf48201a06aa8508aa4Jeff Garzik
1587bdd4dddee325a7dce3e84cf48201a06aa8508aa4Jeff Garzikstatic void mv_intr_pio(struct ata_port *ap)
1588bdd4dddee325a7dce3e84cf48201a06aa8508aa4Jeff Garzik{
1589bdd4dddee325a7dce3e84cf48201a06aa8508aa4Jeff Garzik	struct ata_queued_cmd *qc;
1590bdd4dddee325a7dce3e84cf48201a06aa8508aa4Jeff Garzik	u8 ata_status;
1591bdd4dddee325a7dce3e84cf48201a06aa8508aa4Jeff Garzik
1592bdd4dddee325a7dce3e84cf48201a06aa8508aa4Jeff Garzik	/* ignore spurious intr if drive still BUSY */
1593bdd4dddee325a7dce3e84cf48201a06aa8508aa4Jeff Garzik	ata_status = readb(ap->ioaddr.status_addr);
1594bdd4dddee325a7dce3e84cf48201a06aa8508aa4Jeff Garzik	if (unlikely(ata_status & ATA_BUSY))
1595bdd4dddee325a7dce3e84cf48201a06aa8508aa4Jeff Garzik		return;
1596bdd4dddee325a7dce3e84cf48201a06aa8508aa4Jeff Garzik
1597bdd4dddee325a7dce3e84cf48201a06aa8508aa4Jeff Garzik	/* get active ATA command */
15989af5c9c97dc9d599281778864c72b385f0c63341Tejun Heo	qc = ata_qc_from_tag(ap, ap->link.active_tag);
1599bdd4dddee325a7dce3e84cf48201a06aa8508aa4Jeff Garzik	if (unlikely(!qc))			/* no active tag */
1600bdd4dddee325a7dce3e84cf48201a06aa8508aa4Jeff Garzik		return;
1601bdd4dddee325a7dce3e84cf48201a06aa8508aa4Jeff Garzik	if (qc->tf.flags & ATA_TFLAG_POLLING)	/* polling; we don't own qc */
1602bdd4dddee325a7dce3e84cf48201a06aa8508aa4Jeff Garzik		return;
1603bdd4dddee325a7dce3e84cf48201a06aa8508aa4Jeff Garzik
1604bdd4dddee325a7dce3e84cf48201a06aa8508aa4Jeff Garzik	/* and finally, complete the ATA command */
1605bdd4dddee325a7dce3e84cf48201a06aa8508aa4Jeff Garzik	qc->err_mask |= ac_err_mask(ata_status);
1606bdd4dddee325a7dce3e84cf48201a06aa8508aa4Jeff Garzik	ata_qc_complete(qc);
1607bdd4dddee325a7dce3e84cf48201a06aa8508aa4Jeff Garzik}
1608bdd4dddee325a7dce3e84cf48201a06aa8508aa4Jeff Garzik
1609bdd4dddee325a7dce3e84cf48201a06aa8508aa4Jeff Garzikstatic void mv_intr_edma(struct ata_port *ap)
1610bdd4dddee325a7dce3e84cf48201a06aa8508aa4Jeff Garzik{
1611bdd4dddee325a7dce3e84cf48201a06aa8508aa4Jeff Garzik	void __iomem *port_mmio = mv_ap_base(ap);
1612bdd4dddee325a7dce3e84cf48201a06aa8508aa4Jeff Garzik	struct mv_host_priv *hpriv = ap->host->private_data;
1613bdd4dddee325a7dce3e84cf48201a06aa8508aa4Jeff Garzik	struct mv_port_priv *pp = ap->private_data;
1614bdd4dddee325a7dce3e84cf48201a06aa8508aa4Jeff Garzik	struct ata_queued_cmd *qc;
1615bdd4dddee325a7dce3e84cf48201a06aa8508aa4Jeff Garzik	u32 out_index, in_index;
1616bdd4dddee325a7dce3e84cf48201a06aa8508aa4Jeff Garzik	bool work_done = false;
1617bdd4dddee325a7dce3e84cf48201a06aa8508aa4Jeff Garzik
1618bdd4dddee325a7dce3e84cf48201a06aa8508aa4Jeff Garzik	/* get h/w response queue pointer */
1619bdd4dddee325a7dce3e84cf48201a06aa8508aa4Jeff Garzik	in_index = (readl(port_mmio + EDMA_RSP_Q_IN_PTR_OFS)
1620bdd4dddee325a7dce3e84cf48201a06aa8508aa4Jeff Garzik			>> EDMA_RSP_Q_PTR_SHIFT) & MV_MAX_Q_DEPTH_MASK;
1621bdd4dddee325a7dce3e84cf48201a06aa8508aa4Jeff Garzik
1622bdd4dddee325a7dce3e84cf48201a06aa8508aa4Jeff Garzik	while (1) {
1623bdd4dddee325a7dce3e84cf48201a06aa8508aa4Jeff Garzik		u16 status;
16246c1153e00af8de755ec278d873a97c9ce2a72d10Jeff Garzik		unsigned int tag;
1625bdd4dddee325a7dce3e84cf48201a06aa8508aa4Jeff Garzik
1626bdd4dddee325a7dce3e84cf48201a06aa8508aa4Jeff Garzik		/* get s/w response queue last-read pointer, and compare */
1627bdd4dddee325a7dce3e84cf48201a06aa8508aa4Jeff Garzik		out_index = pp->resp_idx & MV_MAX_Q_DEPTH_MASK;
1628bdd4dddee325a7dce3e84cf48201a06aa8508aa4Jeff Garzik		if (in_index == out_index)
1629bdd4dddee325a7dce3e84cf48201a06aa8508aa4Jeff Garzik			break;
1630bdd4dddee325a7dce3e84cf48201a06aa8508aa4Jeff Garzik
1631bdd4dddee325a7dce3e84cf48201a06aa8508aa4Jeff Garzik		/* 50xx: get active ATA command */
16320ea9e179f436f153fc19fdaef7abbc1e0da20762Jeff Garzik		if (IS_GEN_I(hpriv))
16339af5c9c97dc9d599281778864c72b385f0c63341Tejun Heo			tag = ap->link.active_tag;
1634bdd4dddee325a7dce3e84cf48201a06aa8508aa4Jeff Garzik
16356c1153e00af8de755ec278d873a97c9ce2a72d10Jeff Garzik		/* Gen II/IIE: get active ATA command via tag, to enable
16366c1153e00af8de755ec278d873a97c9ce2a72d10Jeff Garzik		 * support for queueing.  this works transparently for
16376c1153e00af8de755ec278d873a97c9ce2a72d10Jeff Garzik		 * queued and non-queued modes.
1638bdd4dddee325a7dce3e84cf48201a06aa8508aa4Jeff Garzik		 */
16398c0aeb4a483334613336ef895f34cecc0ecbbfa6Mark Lord		else
16408c0aeb4a483334613336ef895f34cecc0ecbbfa6Mark Lord			tag = le16_to_cpu(pp->crpb[out_index].id) & 0x1f;
1641bdd4dddee325a7dce3e84cf48201a06aa8508aa4Jeff Garzik
16426c1153e00af8de755ec278d873a97c9ce2a72d10Jeff Garzik		qc = ata_qc_from_tag(ap, tag);
1643bdd4dddee325a7dce3e84cf48201a06aa8508aa4Jeff Garzik
1644cb92441973ebd71d556fc7cdd9e597582327dd71Mark Lord		/* For non-NCQ mode, the lower 8 bits of status
1645cb92441973ebd71d556fc7cdd9e597582327dd71Mark Lord		 * are from EDMA_ERR_IRQ_CAUSE_OFS,
1646cb92441973ebd71d556fc7cdd9e597582327dd71Mark Lord		 * which should be zero if all went well.
1647bdd4dddee325a7dce3e84cf48201a06aa8508aa4Jeff Garzik		 */
1648bdd4dddee325a7dce3e84cf48201a06aa8508aa4Jeff Garzik		status = le16_to_cpu(pp->crpb[out_index].flags);
1649cb92441973ebd71d556fc7cdd9e597582327dd71Mark Lord		if ((status & 0xff) && !(pp->pp_flags & MV_PP_FLAG_NCQ_EN)) {
1650bdd4dddee325a7dce3e84cf48201a06aa8508aa4Jeff Garzik			mv_err_intr(ap, qc);
1651bdd4dddee325a7dce3e84cf48201a06aa8508aa4Jeff Garzik			return;
1652bdd4dddee325a7dce3e84cf48201a06aa8508aa4Jeff Garzik		}
1653bdd4dddee325a7dce3e84cf48201a06aa8508aa4Jeff Garzik
1654bdd4dddee325a7dce3e84cf48201a06aa8508aa4Jeff Garzik		/* and finally, complete the ATA command */
1655bdd4dddee325a7dce3e84cf48201a06aa8508aa4Jeff Garzik		if (qc) {
1656bdd4dddee325a7dce3e84cf48201a06aa8508aa4Jeff Garzik			qc->err_mask |=
1657bdd4dddee325a7dce3e84cf48201a06aa8508aa4Jeff Garzik				ac_err_mask(status >> CRPB_FLAG_STATUS_SHIFT);
1658bdd4dddee325a7dce3e84cf48201a06aa8508aa4Jeff Garzik			ata_qc_complete(qc);
1659bdd4dddee325a7dce3e84cf48201a06aa8508aa4Jeff Garzik		}
1660bdd4dddee325a7dce3e84cf48201a06aa8508aa4Jeff Garzik
16610ea9e179f436f153fc19fdaef7abbc1e0da20762Jeff Garzik		/* advance software response queue pointer, to
1662bdd4dddee325a7dce3e84cf48201a06aa8508aa4Jeff Garzik		 * indicate (after the loop completes) to hardware
1663bdd4dddee325a7dce3e84cf48201a06aa8508aa4Jeff Garzik		 * that we have consumed a response queue entry.
1664bdd4dddee325a7dce3e84cf48201a06aa8508aa4Jeff Garzik		 */
1665bdd4dddee325a7dce3e84cf48201a06aa8508aa4Jeff Garzik		work_done = true;
1666bdd4dddee325a7dce3e84cf48201a06aa8508aa4Jeff Garzik		pp->resp_idx++;
1667bdd4dddee325a7dce3e84cf48201a06aa8508aa4Jeff Garzik	}
1668bdd4dddee325a7dce3e84cf48201a06aa8508aa4Jeff Garzik
1669bdd4dddee325a7dce3e84cf48201a06aa8508aa4Jeff Garzik	if (work_done)
1670bdd4dddee325a7dce3e84cf48201a06aa8508aa4Jeff Garzik		writelfl((pp->crpb_dma & EDMA_RSP_Q_BASE_LO_MASK) |
1671bdd4dddee325a7dce3e84cf48201a06aa8508aa4Jeff Garzik			 (out_index << EDMA_RSP_Q_PTR_SHIFT),
1672bdd4dddee325a7dce3e84cf48201a06aa8508aa4Jeff Garzik			 port_mmio + EDMA_RSP_Q_OUT_PTR_OFS);
167320f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ}
167420f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ
167505b308e1df6d9d673daedb517969241f41278b52Brett Russ/**
167605b308e1df6d9d673daedb517969241f41278b52Brett Russ *      mv_host_intr - Handle all interrupts on the given host controller
1677cca3974e48607c3775dc73b544a5700b2e37c21aJeff Garzik *      @host: host specific structure
167805b308e1df6d9d673daedb517969241f41278b52Brett Russ *      @relevant: port error bits relevant to this host controller
167905b308e1df6d9d673daedb517969241f41278b52Brett Russ *      @hc: which host controller we're to look at
168005b308e1df6d9d673daedb517969241f41278b52Brett Russ *
168105b308e1df6d9d673daedb517969241f41278b52Brett Russ *      Read then write clear the HC interrupt status then walk each
168205b308e1df6d9d673daedb517969241f41278b52Brett Russ *      port connected to the HC and see if it needs servicing.  Port
168305b308e1df6d9d673daedb517969241f41278b52Brett Russ *      success ints are reported in the HC interrupt status reg, the
168405b308e1df6d9d673daedb517969241f41278b52Brett Russ *      port error ints are reported in the higher level main
168505b308e1df6d9d673daedb517969241f41278b52Brett Russ *      interrupt status register and thus are passed in via the
168605b308e1df6d9d673daedb517969241f41278b52Brett Russ *      'relevant' argument.
168705b308e1df6d9d673daedb517969241f41278b52Brett Russ *
168805b308e1df6d9d673daedb517969241f41278b52Brett Russ *      LOCKING:
168905b308e1df6d9d673daedb517969241f41278b52Brett Russ *      Inherited from caller.
169005b308e1df6d9d673daedb517969241f41278b52Brett Russ */
1691cca3974e48607c3775dc73b544a5700b2e37c21aJeff Garzikstatic void mv_host_intr(struct ata_host *host, u32 relevant, unsigned int hc)
169220f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ{
1693f351b2d638c3cb0b95adde3549b7bfaf3f991dfaSaeed Bishara	struct mv_host_priv *hpriv = host->private_data;
1694f351b2d638c3cb0b95adde3549b7bfaf3f991dfaSaeed Bishara	void __iomem *mmio = hpriv->base;
169520f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ	void __iomem *hc_mmio = mv_hc_base(mmio, hc);
169620f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ	u32 hc_irq_cause;
1697f351b2d638c3cb0b95adde3549b7bfaf3f991dfaSaeed Bishara	int port, port0, last_port;
169820f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ
1699351772658a4d1acc0221a6e30676bb0594e74812Jeff Garzik	if (hc == 0)
170020f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ		port0 = 0;
1701351772658a4d1acc0221a6e30676bb0594e74812Jeff Garzik	else
170220f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ		port0 = MV_PORTS_PER_HC;
170320f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ
1704f351b2d638c3cb0b95adde3549b7bfaf3f991dfaSaeed Bishara	if (HAS_PCI(host))
1705f351b2d638c3cb0b95adde3549b7bfaf3f991dfaSaeed Bishara		last_port = port0 + MV_PORTS_PER_HC;
1706f351b2d638c3cb0b95adde3549b7bfaf3f991dfaSaeed Bishara	else
1707f351b2d638c3cb0b95adde3549b7bfaf3f991dfaSaeed Bishara		last_port = port0 + hpriv->n_ports;
170820f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ	/* we'll need the HC success int register in most cases */
170920f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ	hc_irq_cause = readl(hc_mmio + HC_IRQ_CAUSE_OFS);
1710bdd4dddee325a7dce3e84cf48201a06aa8508aa4Jeff Garzik	if (!hc_irq_cause)
1711bdd4dddee325a7dce3e84cf48201a06aa8508aa4Jeff Garzik		return;
1712bdd4dddee325a7dce3e84cf48201a06aa8508aa4Jeff Garzik
1713bdd4dddee325a7dce3e84cf48201a06aa8508aa4Jeff Garzik	writelfl(~hc_irq_cause, hc_mmio + HC_IRQ_CAUSE_OFS);
171420f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ
171520f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ	VPRINTK("ENTER, hc%u relevant=0x%08x HC IRQ cause=0x%08x\n",
17162dcb407e61458ded17503d6bd12b8c064965368bJeff Garzik		hc, relevant, hc_irq_cause);
171720f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ
1718f351b2d638c3cb0b95adde3549b7bfaf3f991dfaSaeed Bishara	for (port = port0; port < port0 + last_port; port++) {
1719cca3974e48607c3775dc73b544a5700b2e37c21aJeff Garzik		struct ata_port *ap = host->ports[port];
172063af2a5c5990d95f1e7d8795f1425fb976ea2b4bMark Lord		struct mv_port_priv *pp = ap->private_data;
1721bdd4dddee325a7dce3e84cf48201a06aa8508aa4Jeff Garzik		int have_err_bits, hard_port, shift;
172255d8ca4f8094246da6e71889a4e04bfafaa78b10Jeff Garzik
1723bdd4dddee325a7dce3e84cf48201a06aa8508aa4Jeff Garzik		if ((!ap) || (ap->flags & ATA_FLAG_DISABLED))
1724a2c91a8819e315e9fd1aef3ff57badb6c1be3f80Jeff Garzik			continue;
1725a2c91a8819e315e9fd1aef3ff57badb6c1be3f80Jeff Garzik
172631961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ		shift = port << 1;		/* (port * 2) */
172720f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ		if (port >= MV_PORTS_PER_HC) {
172820f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ			shift++;	/* skip bit 8 in the HC Main IRQ reg */
172920f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ		}
1730bdd4dddee325a7dce3e84cf48201a06aa8508aa4Jeff Garzik		have_err_bits = ((PORT0_ERR << shift) & relevant);
1731bdd4dddee325a7dce3e84cf48201a06aa8508aa4Jeff Garzik
1732bdd4dddee325a7dce3e84cf48201a06aa8508aa4Jeff Garzik		if (unlikely(have_err_bits)) {
1733bdd4dddee325a7dce3e84cf48201a06aa8508aa4Jeff Garzik			struct ata_queued_cmd *qc;
17348b260248d9e0e8b64bb72fd4dee03ad86984c344Jeff Garzik
17359af5c9c97dc9d599281778864c72b385f0c63341Tejun Heo			qc = ata_qc_from_tag(ap, ap->link.active_tag);
1736bdd4dddee325a7dce3e84cf48201a06aa8508aa4Jeff Garzik			if (qc && (qc->tf.flags & ATA_TFLAG_POLLING))
1737bdd4dddee325a7dce3e84cf48201a06aa8508aa4Jeff Garzik				continue;
1738bdd4dddee325a7dce3e84cf48201a06aa8508aa4Jeff Garzik
1739bdd4dddee325a7dce3e84cf48201a06aa8508aa4Jeff Garzik			mv_err_intr(ap, qc);
1740bdd4dddee325a7dce3e84cf48201a06aa8508aa4Jeff Garzik			continue;
1741bdd4dddee325a7dce3e84cf48201a06aa8508aa4Jeff Garzik		}
1742bdd4dddee325a7dce3e84cf48201a06aa8508aa4Jeff Garzik
1743bdd4dddee325a7dce3e84cf48201a06aa8508aa4Jeff Garzik		hard_port = mv_hardport_from_port(port); /* range 0..3 */
1744bdd4dddee325a7dce3e84cf48201a06aa8508aa4Jeff Garzik
1745bdd4dddee325a7dce3e84cf48201a06aa8508aa4Jeff Garzik		if (pp->pp_flags & MV_PP_FLAG_EDMA_EN) {
1746bdd4dddee325a7dce3e84cf48201a06aa8508aa4Jeff Garzik			if ((CRPB_DMA_DONE << hard_port) & hc_irq_cause)
1747bdd4dddee325a7dce3e84cf48201a06aa8508aa4Jeff Garzik				mv_intr_edma(ap);
1748bdd4dddee325a7dce3e84cf48201a06aa8508aa4Jeff Garzik		} else {
1749bdd4dddee325a7dce3e84cf48201a06aa8508aa4Jeff Garzik			if ((DEV_IRQ << hard_port) & hc_irq_cause)
1750bdd4dddee325a7dce3e84cf48201a06aa8508aa4Jeff Garzik				mv_intr_pio(ap);
175120f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ		}
175220f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ	}
175320f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ	VPRINTK("EXIT\n");
175420f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ}
175520f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ
1756bdd4dddee325a7dce3e84cf48201a06aa8508aa4Jeff Garzikstatic void mv_pci_error(struct ata_host *host, void __iomem *mmio)
1757bdd4dddee325a7dce3e84cf48201a06aa8508aa4Jeff Garzik{
175802a121da5a53d415b6596bc19cc6999d295d32a4Mark Lord	struct mv_host_priv *hpriv = host->private_data;
1759bdd4dddee325a7dce3e84cf48201a06aa8508aa4Jeff Garzik	struct ata_port *ap;
1760bdd4dddee325a7dce3e84cf48201a06aa8508aa4Jeff Garzik	struct ata_queued_cmd *qc;
1761bdd4dddee325a7dce3e84cf48201a06aa8508aa4Jeff Garzik	struct ata_eh_info *ehi;
1762bdd4dddee325a7dce3e84cf48201a06aa8508aa4Jeff Garzik	unsigned int i, err_mask, printed = 0;
1763bdd4dddee325a7dce3e84cf48201a06aa8508aa4Jeff Garzik	u32 err_cause;
1764bdd4dddee325a7dce3e84cf48201a06aa8508aa4Jeff Garzik
176502a121da5a53d415b6596bc19cc6999d295d32a4Mark Lord	err_cause = readl(mmio + hpriv->irq_cause_ofs);
1766bdd4dddee325a7dce3e84cf48201a06aa8508aa4Jeff Garzik
1767bdd4dddee325a7dce3e84cf48201a06aa8508aa4Jeff Garzik	dev_printk(KERN_ERR, host->dev, "PCI ERROR; PCI IRQ cause=0x%08x\n",
1768bdd4dddee325a7dce3e84cf48201a06aa8508aa4Jeff Garzik		   err_cause);
1769bdd4dddee325a7dce3e84cf48201a06aa8508aa4Jeff Garzik
1770bdd4dddee325a7dce3e84cf48201a06aa8508aa4Jeff Garzik	DPRINTK("All regs @ PCI error\n");
1771bdd4dddee325a7dce3e84cf48201a06aa8508aa4Jeff Garzik	mv_dump_all_regs(mmio, -1, to_pci_dev(host->dev));
1772bdd4dddee325a7dce3e84cf48201a06aa8508aa4Jeff Garzik
177302a121da5a53d415b6596bc19cc6999d295d32a4Mark Lord	writelfl(0, mmio + hpriv->irq_cause_ofs);
1774bdd4dddee325a7dce3e84cf48201a06aa8508aa4Jeff Garzik
1775bdd4dddee325a7dce3e84cf48201a06aa8508aa4Jeff Garzik	for (i = 0; i < host->n_ports; i++) {
1776bdd4dddee325a7dce3e84cf48201a06aa8508aa4Jeff Garzik		ap = host->ports[i];
1777936fd7328657884d5a69a55666c74a55aa83ca27Tejun Heo		if (!ata_link_offline(&ap->link)) {
17789af5c9c97dc9d599281778864c72b385f0c63341Tejun Heo			ehi = &ap->link.eh_info;
1779bdd4dddee325a7dce3e84cf48201a06aa8508aa4Jeff Garzik			ata_ehi_clear_desc(ehi);
1780bdd4dddee325a7dce3e84cf48201a06aa8508aa4Jeff Garzik			if (!printed++)
1781bdd4dddee325a7dce3e84cf48201a06aa8508aa4Jeff Garzik				ata_ehi_push_desc(ehi,
1782bdd4dddee325a7dce3e84cf48201a06aa8508aa4Jeff Garzik					"PCI err cause 0x%08x", err_cause);
1783bdd4dddee325a7dce3e84cf48201a06aa8508aa4Jeff Garzik			err_mask = AC_ERR_HOST_BUS;
1784bdd4dddee325a7dce3e84cf48201a06aa8508aa4Jeff Garzik			ehi->action = ATA_EH_HARDRESET;
17859af5c9c97dc9d599281778864c72b385f0c63341Tejun Heo			qc = ata_qc_from_tag(ap, ap->link.active_tag);
1786bdd4dddee325a7dce3e84cf48201a06aa8508aa4Jeff Garzik			if (qc)
1787bdd4dddee325a7dce3e84cf48201a06aa8508aa4Jeff Garzik				qc->err_mask |= err_mask;
1788bdd4dddee325a7dce3e84cf48201a06aa8508aa4Jeff Garzik			else
1789bdd4dddee325a7dce3e84cf48201a06aa8508aa4Jeff Garzik				ehi->err_mask |= err_mask;
1790bdd4dddee325a7dce3e84cf48201a06aa8508aa4Jeff Garzik
1791bdd4dddee325a7dce3e84cf48201a06aa8508aa4Jeff Garzik			ata_port_freeze(ap);
1792bdd4dddee325a7dce3e84cf48201a06aa8508aa4Jeff Garzik		}
1793bdd4dddee325a7dce3e84cf48201a06aa8508aa4Jeff Garzik	}
1794bdd4dddee325a7dce3e84cf48201a06aa8508aa4Jeff Garzik}
1795bdd4dddee325a7dce3e84cf48201a06aa8508aa4Jeff Garzik
179605b308e1df6d9d673daedb517969241f41278b52Brett Russ/**
1797c5d3e45a2200a0905dc45b72714726b7aac3aaf1Jeff Garzik *      mv_interrupt - Main interrupt event handler
179805b308e1df6d9d673daedb517969241f41278b52Brett Russ *      @irq: unused
179905b308e1df6d9d673daedb517969241f41278b52Brett Russ *      @dev_instance: private data; in this case the host structure
180005b308e1df6d9d673daedb517969241f41278b52Brett Russ *
180105b308e1df6d9d673daedb517969241f41278b52Brett Russ *      Read the read only register to determine if any host
180205b308e1df6d9d673daedb517969241f41278b52Brett Russ *      controllers have pending interrupts.  If so, call lower level
180305b308e1df6d9d673daedb517969241f41278b52Brett Russ *      routine to handle.  Also check for PCI errors which are only
180405b308e1df6d9d673daedb517969241f41278b52Brett Russ *      reported here.
180505b308e1df6d9d673daedb517969241f41278b52Brett Russ *
18068b260248d9e0e8b64bb72fd4dee03ad86984c344Jeff Garzik *      LOCKING:
1807cca3974e48607c3775dc73b544a5700b2e37c21aJeff Garzik *      This routine holds the host lock while processing pending
180805b308e1df6d9d673daedb517969241f41278b52Brett Russ *      interrupts.
180905b308e1df6d9d673daedb517969241f41278b52Brett Russ */
18107d12e780e003f93433d49ce78cfedf4b4c52adc5David Howellsstatic irqreturn_t mv_interrupt(int irq, void *dev_instance)
181120f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ{
1812cca3974e48607c3775dc73b544a5700b2e37c21aJeff Garzik	struct ata_host *host = dev_instance;
1813f351b2d638c3cb0b95adde3549b7bfaf3f991dfaSaeed Bishara	struct mv_host_priv *hpriv = host->private_data;
181420f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ	unsigned int hc, handled = 0, n_hcs;
1815f351b2d638c3cb0b95adde3549b7bfaf3f991dfaSaeed Bishara	void __iomem *mmio = hpriv->base;
1816646a4da514f2555298481cb00dc5b3eb02b21b72Mark Lord	u32 irq_stat, irq_mask;
181720f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ
1818646a4da514f2555298481cb00dc5b3eb02b21b72Mark Lord	spin_lock(&host->lock);
1819f351b2d638c3cb0b95adde3549b7bfaf3f991dfaSaeed Bishara
1820f351b2d638c3cb0b95adde3549b7bfaf3f991dfaSaeed Bishara	irq_stat = readl(hpriv->main_cause_reg_addr);
1821f351b2d638c3cb0b95adde3549b7bfaf3f991dfaSaeed Bishara	irq_mask = readl(hpriv->main_mask_reg_addr);
182220f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ
182320f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ	/* check the cases where we either have nothing pending or have read
182420f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ	 * a bogus register value which can indicate HW removal or PCI fault
182520f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ	 */
1826646a4da514f2555298481cb00dc5b3eb02b21b72Mark Lord	if (!(irq_stat & irq_mask) || (0xffffffffU == irq_stat))
1827646a4da514f2555298481cb00dc5b3eb02b21b72Mark Lord		goto out_unlock;
182820f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ
1829cca3974e48607c3775dc73b544a5700b2e37c21aJeff Garzik	n_hcs = mv_get_hc_count(host->ports[0]->flags);
183020f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ
18317bb3c5290ca0ec9e65947c907495c2b56e895e46Saeed Bishara	if (unlikely((irq_stat & PCI_ERR) && HAS_PCI(host))) {
1832bdd4dddee325a7dce3e84cf48201a06aa8508aa4Jeff Garzik		mv_pci_error(host, mmio);
1833bdd4dddee325a7dce3e84cf48201a06aa8508aa4Jeff Garzik		handled = 1;
1834bdd4dddee325a7dce3e84cf48201a06aa8508aa4Jeff Garzik		goto out_unlock;	/* skip all other HC irq handling */
1835bdd4dddee325a7dce3e84cf48201a06aa8508aa4Jeff Garzik	}
1836bdd4dddee325a7dce3e84cf48201a06aa8508aa4Jeff Garzik
183720f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ	for (hc = 0; hc < n_hcs; hc++) {
183820f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ		u32 relevant = irq_stat & (HC0_IRQ_PEND << (hc * HC_SHIFT));
183920f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ		if (relevant) {
1840cca3974e48607c3775dc73b544a5700b2e37c21aJeff Garzik			mv_host_intr(host, relevant, hc);
1841bdd4dddee325a7dce3e84cf48201a06aa8508aa4Jeff Garzik			handled = 1;
184220f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ		}
184320f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ	}
1844615ab95342f6245026d8974b9724f7ea57d9a184Mark Lord
1845bdd4dddee325a7dce3e84cf48201a06aa8508aa4Jeff Garzikout_unlock:
1846cca3974e48607c3775dc73b544a5700b2e37c21aJeff Garzik	spin_unlock(&host->lock);
184720f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ
184820f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ	return IRQ_RETVAL(handled);
184920f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ}
185020f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ
1851c9d39130123238ac18478a42e25cb7996eacfcc0Jeff Garzikstatic void __iomem *mv5_phy_base(void __iomem *mmio, unsigned int port)
1852c9d39130123238ac18478a42e25cb7996eacfcc0Jeff Garzik{
1853c9d39130123238ac18478a42e25cb7996eacfcc0Jeff Garzik	void __iomem *hc_mmio = mv_hc_base_from_port(mmio, port);
1854c9d39130123238ac18478a42e25cb7996eacfcc0Jeff Garzik	unsigned long ofs = (mv_hardport_from_port(port) + 1) * 0x100UL;
1855c9d39130123238ac18478a42e25cb7996eacfcc0Jeff Garzik
1856c9d39130123238ac18478a42e25cb7996eacfcc0Jeff Garzik	return hc_mmio + ofs;
1857c9d39130123238ac18478a42e25cb7996eacfcc0Jeff Garzik}
1858c9d39130123238ac18478a42e25cb7996eacfcc0Jeff Garzik
1859c9d39130123238ac18478a42e25cb7996eacfcc0Jeff Garzikstatic unsigned int mv5_scr_offset(unsigned int sc_reg_in)
1860c9d39130123238ac18478a42e25cb7996eacfcc0Jeff Garzik{
1861c9d39130123238ac18478a42e25cb7996eacfcc0Jeff Garzik	unsigned int ofs;
1862c9d39130123238ac18478a42e25cb7996eacfcc0Jeff Garzik
1863c9d39130123238ac18478a42e25cb7996eacfcc0Jeff Garzik	switch (sc_reg_in) {
1864c9d39130123238ac18478a42e25cb7996eacfcc0Jeff Garzik	case SCR_STATUS:
1865c9d39130123238ac18478a42e25cb7996eacfcc0Jeff Garzik	case SCR_ERROR:
1866c9d39130123238ac18478a42e25cb7996eacfcc0Jeff Garzik	case SCR_CONTROL:
1867c9d39130123238ac18478a42e25cb7996eacfcc0Jeff Garzik		ofs = sc_reg_in * sizeof(u32);
1868c9d39130123238ac18478a42e25cb7996eacfcc0Jeff Garzik		break;
1869c9d39130123238ac18478a42e25cb7996eacfcc0Jeff Garzik	default:
1870c9d39130123238ac18478a42e25cb7996eacfcc0Jeff Garzik		ofs = 0xffffffffU;
1871c9d39130123238ac18478a42e25cb7996eacfcc0Jeff Garzik		break;
1872c9d39130123238ac18478a42e25cb7996eacfcc0Jeff Garzik	}
1873c9d39130123238ac18478a42e25cb7996eacfcc0Jeff Garzik	return ofs;
1874c9d39130123238ac18478a42e25cb7996eacfcc0Jeff Garzik}
1875c9d39130123238ac18478a42e25cb7996eacfcc0Jeff Garzik
1876da3dbb17a0e9a9ec7f5aed95f1fddadb790edc9dTejun Heostatic int mv5_scr_read(struct ata_port *ap, unsigned int sc_reg_in, u32 *val)
1877c9d39130123238ac18478a42e25cb7996eacfcc0Jeff Garzik{
1878f351b2d638c3cb0b95adde3549b7bfaf3f991dfaSaeed Bishara	struct mv_host_priv *hpriv = ap->host->private_data;
1879f351b2d638c3cb0b95adde3549b7bfaf3f991dfaSaeed Bishara	void __iomem *mmio = hpriv->base;
18800d5ff566779f894ca9937231a181eb31e4adff0eTejun Heo	void __iomem *addr = mv5_phy_base(mmio, ap->port_no);
1881c9d39130123238ac18478a42e25cb7996eacfcc0Jeff Garzik	unsigned int ofs = mv5_scr_offset(sc_reg_in);
1882c9d39130123238ac18478a42e25cb7996eacfcc0Jeff Garzik
1883da3dbb17a0e9a9ec7f5aed95f1fddadb790edc9dTejun Heo	if (ofs != 0xffffffffU) {
1884da3dbb17a0e9a9ec7f5aed95f1fddadb790edc9dTejun Heo		*val = readl(addr + ofs);
1885da3dbb17a0e9a9ec7f5aed95f1fddadb790edc9dTejun Heo		return 0;
1886da3dbb17a0e9a9ec7f5aed95f1fddadb790edc9dTejun Heo	} else
1887da3dbb17a0e9a9ec7f5aed95f1fddadb790edc9dTejun Heo		return -EINVAL;
1888c9d39130123238ac18478a42e25cb7996eacfcc0Jeff Garzik}
1889c9d39130123238ac18478a42e25cb7996eacfcc0Jeff Garzik
1890da3dbb17a0e9a9ec7f5aed95f1fddadb790edc9dTejun Heostatic int mv5_scr_write(struct ata_port *ap, unsigned int sc_reg_in, u32 val)
1891c9d39130123238ac18478a42e25cb7996eacfcc0Jeff Garzik{
1892f351b2d638c3cb0b95adde3549b7bfaf3f991dfaSaeed Bishara	struct mv_host_priv *hpriv = ap->host->private_data;
1893f351b2d638c3cb0b95adde3549b7bfaf3f991dfaSaeed Bishara	void __iomem *mmio = hpriv->base;
18940d5ff566779f894ca9937231a181eb31e4adff0eTejun Heo	void __iomem *addr = mv5_phy_base(mmio, ap->port_no);
1895c9d39130123238ac18478a42e25cb7996eacfcc0Jeff Garzik	unsigned int ofs = mv5_scr_offset(sc_reg_in);
1896c9d39130123238ac18478a42e25cb7996eacfcc0Jeff Garzik
1897da3dbb17a0e9a9ec7f5aed95f1fddadb790edc9dTejun Heo	if (ofs != 0xffffffffU) {
18980d5ff566779f894ca9937231a181eb31e4adff0eTejun Heo		writelfl(val, addr + ofs);
1899da3dbb17a0e9a9ec7f5aed95f1fddadb790edc9dTejun Heo		return 0;
1900da3dbb17a0e9a9ec7f5aed95f1fddadb790edc9dTejun Heo	} else
1901da3dbb17a0e9a9ec7f5aed95f1fddadb790edc9dTejun Heo		return -EINVAL;
1902c9d39130123238ac18478a42e25cb7996eacfcc0Jeff Garzik}
1903c9d39130123238ac18478a42e25cb7996eacfcc0Jeff Garzik
19047bb3c5290ca0ec9e65947c907495c2b56e895e46Saeed Bisharastatic void mv5_reset_bus(struct ata_host *host, void __iomem *mmio)
1905522479fb98c6667f081e75f87e298e413c0b1db8Jeff Garzik{
19067bb3c5290ca0ec9e65947c907495c2b56e895e46Saeed Bishara	struct pci_dev *pdev = to_pci_dev(host->dev);
1907522479fb98c6667f081e75f87e298e413c0b1db8Jeff Garzik	int early_5080;
1908522479fb98c6667f081e75f87e298e413c0b1db8Jeff Garzik
190944c10138fd4bbc4b6d6bff0873c24902f2a9da65Auke Kok	early_5080 = (pdev->device == 0x5080) && (pdev->revision == 0);
1910522479fb98c6667f081e75f87e298e413c0b1db8Jeff Garzik
1911522479fb98c6667f081e75f87e298e413c0b1db8Jeff Garzik	if (!early_5080) {
1912522479fb98c6667f081e75f87e298e413c0b1db8Jeff Garzik		u32 tmp = readl(mmio + MV_PCI_EXP_ROM_BAR_CTL);
1913522479fb98c6667f081e75f87e298e413c0b1db8Jeff Garzik		tmp |= (1 << 0);
1914522479fb98c6667f081e75f87e298e413c0b1db8Jeff Garzik		writel(tmp, mmio + MV_PCI_EXP_ROM_BAR_CTL);
1915522479fb98c6667f081e75f87e298e413c0b1db8Jeff Garzik	}
1916522479fb98c6667f081e75f87e298e413c0b1db8Jeff Garzik
19177bb3c5290ca0ec9e65947c907495c2b56e895e46Saeed Bishara	mv_reset_pci_bus(host, mmio);
1918522479fb98c6667f081e75f87e298e413c0b1db8Jeff Garzik}
1919522479fb98c6667f081e75f87e298e413c0b1db8Jeff Garzik
1920522479fb98c6667f081e75f87e298e413c0b1db8Jeff Garzikstatic void mv5_reset_flash(struct mv_host_priv *hpriv, void __iomem *mmio)
1921522479fb98c6667f081e75f87e298e413c0b1db8Jeff Garzik{
1922522479fb98c6667f081e75f87e298e413c0b1db8Jeff Garzik	writel(0x0fcfffff, mmio + MV_FLASH_CTL);
1923522479fb98c6667f081e75f87e298e413c0b1db8Jeff Garzik}
1924522479fb98c6667f081e75f87e298e413c0b1db8Jeff Garzik
192547c2b677daeed9c79ecb7167c211ff36876ea611Jeff Garzikstatic void mv5_read_preamp(struct mv_host_priv *hpriv, int idx,
1926ba3fe8fb6a469390a14379519915f3c39a973d99Jeff Garzik			   void __iomem *mmio)
1927ba3fe8fb6a469390a14379519915f3c39a973d99Jeff Garzik{
1928c9d39130123238ac18478a42e25cb7996eacfcc0Jeff Garzik	void __iomem *phy_mmio = mv5_phy_base(mmio, idx);
1929c9d39130123238ac18478a42e25cb7996eacfcc0Jeff Garzik	u32 tmp;
1930c9d39130123238ac18478a42e25cb7996eacfcc0Jeff Garzik
1931c9d39130123238ac18478a42e25cb7996eacfcc0Jeff Garzik	tmp = readl(phy_mmio + MV5_PHY_MODE);
1932c9d39130123238ac18478a42e25cb7996eacfcc0Jeff Garzik
1933c9d39130123238ac18478a42e25cb7996eacfcc0Jeff Garzik	hpriv->signal[idx].pre = tmp & 0x1800;	/* bits 12:11 */
1934c9d39130123238ac18478a42e25cb7996eacfcc0Jeff Garzik	hpriv->signal[idx].amps = tmp & 0xe0;	/* bits 7:5 */
1935ba3fe8fb6a469390a14379519915f3c39a973d99Jeff Garzik}
1936ba3fe8fb6a469390a14379519915f3c39a973d99Jeff Garzik
193747c2b677daeed9c79ecb7167c211ff36876ea611Jeff Garzikstatic void mv5_enable_leds(struct mv_host_priv *hpriv, void __iomem *mmio)
1938ba3fe8fb6a469390a14379519915f3c39a973d99Jeff Garzik{
1939522479fb98c6667f081e75f87e298e413c0b1db8Jeff Garzik	u32 tmp;
1940522479fb98c6667f081e75f87e298e413c0b1db8Jeff Garzik
1941522479fb98c6667f081e75f87e298e413c0b1db8Jeff Garzik	writel(0, mmio + MV_GPIO_PORT_CTL);
1942522479fb98c6667f081e75f87e298e413c0b1db8Jeff Garzik
1943522479fb98c6667f081e75f87e298e413c0b1db8Jeff Garzik	/* FIXME: handle MV_HP_ERRATA_50XXB2 errata */
1944522479fb98c6667f081e75f87e298e413c0b1db8Jeff Garzik
1945522479fb98c6667f081e75f87e298e413c0b1db8Jeff Garzik	tmp = readl(mmio + MV_PCI_EXP_ROM_BAR_CTL);
1946522479fb98c6667f081e75f87e298e413c0b1db8Jeff Garzik	tmp |= ~(1 << 0);
1947522479fb98c6667f081e75f87e298e413c0b1db8Jeff Garzik	writel(tmp, mmio + MV_PCI_EXP_ROM_BAR_CTL);
1948ba3fe8fb6a469390a14379519915f3c39a973d99Jeff Garzik}
1949ba3fe8fb6a469390a14379519915f3c39a973d99Jeff Garzik
19502a47ce06d534692f9bd2bf4e90a20fc9b1054c39Jeff Garzikstatic void mv5_phy_errata(struct mv_host_priv *hpriv, void __iomem *mmio,
19512a47ce06d534692f9bd2bf4e90a20fc9b1054c39Jeff Garzik			   unsigned int port)
1952bca1c4eb9411533d613123618c0d127fae532595Jeff Garzik{
1953c9d39130123238ac18478a42e25cb7996eacfcc0Jeff Garzik	void __iomem *phy_mmio = mv5_phy_base(mmio, port);
1954c9d39130123238ac18478a42e25cb7996eacfcc0Jeff Garzik	const u32 mask = (1<<12) | (1<<11) | (1<<7) | (1<<6) | (1<<5);
1955c9d39130123238ac18478a42e25cb7996eacfcc0Jeff Garzik	u32 tmp;
1956c9d39130123238ac18478a42e25cb7996eacfcc0Jeff Garzik	int fix_apm_sq = (hpriv->hp_flags & MV_HP_ERRATA_50XXB0);
1957c9d39130123238ac18478a42e25cb7996eacfcc0Jeff Garzik
1958c9d39130123238ac18478a42e25cb7996eacfcc0Jeff Garzik	if (fix_apm_sq) {
1959c9d39130123238ac18478a42e25cb7996eacfcc0Jeff Garzik		tmp = readl(phy_mmio + MV5_LT_MODE);
1960c9d39130123238ac18478a42e25cb7996eacfcc0Jeff Garzik		tmp |= (1 << 19);
1961c9d39130123238ac18478a42e25cb7996eacfcc0Jeff Garzik		writel(tmp, phy_mmio + MV5_LT_MODE);
1962c9d39130123238ac18478a42e25cb7996eacfcc0Jeff Garzik
1963c9d39130123238ac18478a42e25cb7996eacfcc0Jeff Garzik		tmp = readl(phy_mmio + MV5_PHY_CTL);
1964c9d39130123238ac18478a42e25cb7996eacfcc0Jeff Garzik		tmp &= ~0x3;
1965c9d39130123238ac18478a42e25cb7996eacfcc0Jeff Garzik		tmp |= 0x1;
1966c9d39130123238ac18478a42e25cb7996eacfcc0Jeff Garzik		writel(tmp, phy_mmio + MV5_PHY_CTL);
1967c9d39130123238ac18478a42e25cb7996eacfcc0Jeff Garzik	}
1968c9d39130123238ac18478a42e25cb7996eacfcc0Jeff Garzik
1969c9d39130123238ac18478a42e25cb7996eacfcc0Jeff Garzik	tmp = readl(phy_mmio + MV5_PHY_MODE);
1970c9d39130123238ac18478a42e25cb7996eacfcc0Jeff Garzik	tmp &= ~mask;
1971c9d39130123238ac18478a42e25cb7996eacfcc0Jeff Garzik	tmp |= hpriv->signal[port].pre;
1972c9d39130123238ac18478a42e25cb7996eacfcc0Jeff Garzik	tmp |= hpriv->signal[port].amps;
1973c9d39130123238ac18478a42e25cb7996eacfcc0Jeff Garzik	writel(tmp, phy_mmio + MV5_PHY_MODE);
1974bca1c4eb9411533d613123618c0d127fae532595Jeff Garzik}
1975bca1c4eb9411533d613123618c0d127fae532595Jeff Garzik
1976c9d39130123238ac18478a42e25cb7996eacfcc0Jeff Garzik
1977c9d39130123238ac18478a42e25cb7996eacfcc0Jeff Garzik#undef ZERO
1978c9d39130123238ac18478a42e25cb7996eacfcc0Jeff Garzik#define ZERO(reg) writel(0, port_mmio + (reg))
1979c9d39130123238ac18478a42e25cb7996eacfcc0Jeff Garzikstatic void mv5_reset_hc_port(struct mv_host_priv *hpriv, void __iomem *mmio,
1980c9d39130123238ac18478a42e25cb7996eacfcc0Jeff Garzik			     unsigned int port)
1981c9d39130123238ac18478a42e25cb7996eacfcc0Jeff Garzik{
1982c9d39130123238ac18478a42e25cb7996eacfcc0Jeff Garzik	void __iomem *port_mmio = mv_port_base(mmio, port);
1983c9d39130123238ac18478a42e25cb7996eacfcc0Jeff Garzik
1984c9d39130123238ac18478a42e25cb7996eacfcc0Jeff Garzik	writelfl(EDMA_DS, port_mmio + EDMA_CMD_OFS);
1985c9d39130123238ac18478a42e25cb7996eacfcc0Jeff Garzik
1986c9d39130123238ac18478a42e25cb7996eacfcc0Jeff Garzik	mv_channel_reset(hpriv, mmio, port);
1987c9d39130123238ac18478a42e25cb7996eacfcc0Jeff Garzik
1988c9d39130123238ac18478a42e25cb7996eacfcc0Jeff Garzik	ZERO(0x028);	/* command */
1989c9d39130123238ac18478a42e25cb7996eacfcc0Jeff Garzik	writel(0x11f, port_mmio + EDMA_CFG_OFS);
1990c9d39130123238ac18478a42e25cb7996eacfcc0Jeff Garzik	ZERO(0x004);	/* timer */
1991c9d39130123238ac18478a42e25cb7996eacfcc0Jeff Garzik	ZERO(0x008);	/* irq err cause */
1992c9d39130123238ac18478a42e25cb7996eacfcc0Jeff Garzik	ZERO(0x00c);	/* irq err mask */
1993c9d39130123238ac18478a42e25cb7996eacfcc0Jeff Garzik	ZERO(0x010);	/* rq bah */
1994c9d39130123238ac18478a42e25cb7996eacfcc0Jeff Garzik	ZERO(0x014);	/* rq inp */
1995c9d39130123238ac18478a42e25cb7996eacfcc0Jeff Garzik	ZERO(0x018);	/* rq outp */
1996c9d39130123238ac18478a42e25cb7996eacfcc0Jeff Garzik	ZERO(0x01c);	/* respq bah */
1997c9d39130123238ac18478a42e25cb7996eacfcc0Jeff Garzik	ZERO(0x024);	/* respq outp */
1998c9d39130123238ac18478a42e25cb7996eacfcc0Jeff Garzik	ZERO(0x020);	/* respq inp */
1999c9d39130123238ac18478a42e25cb7996eacfcc0Jeff Garzik	ZERO(0x02c);	/* test control */
2000c9d39130123238ac18478a42e25cb7996eacfcc0Jeff Garzik	writel(0xbc, port_mmio + EDMA_IORDY_TMOUT);
2001c9d39130123238ac18478a42e25cb7996eacfcc0Jeff Garzik}
2002c9d39130123238ac18478a42e25cb7996eacfcc0Jeff Garzik#undef ZERO
2003c9d39130123238ac18478a42e25cb7996eacfcc0Jeff Garzik
2004c9d39130123238ac18478a42e25cb7996eacfcc0Jeff Garzik#define ZERO(reg) writel(0, hc_mmio + (reg))
2005c9d39130123238ac18478a42e25cb7996eacfcc0Jeff Garzikstatic void mv5_reset_one_hc(struct mv_host_priv *hpriv, void __iomem *mmio,
2006c9d39130123238ac18478a42e25cb7996eacfcc0Jeff Garzik			unsigned int hc)
200747c2b677daeed9c79ecb7167c211ff36876ea611Jeff Garzik{
2008c9d39130123238ac18478a42e25cb7996eacfcc0Jeff Garzik	void __iomem *hc_mmio = mv_hc_base(mmio, hc);
2009c9d39130123238ac18478a42e25cb7996eacfcc0Jeff Garzik	u32 tmp;
2010c9d39130123238ac18478a42e25cb7996eacfcc0Jeff Garzik
2011c9d39130123238ac18478a42e25cb7996eacfcc0Jeff Garzik	ZERO(0x00c);
2012c9d39130123238ac18478a42e25cb7996eacfcc0Jeff Garzik	ZERO(0x010);
2013c9d39130123238ac18478a42e25cb7996eacfcc0Jeff Garzik	ZERO(0x014);
2014c9d39130123238ac18478a42e25cb7996eacfcc0Jeff Garzik	ZERO(0x018);
2015c9d39130123238ac18478a42e25cb7996eacfcc0Jeff Garzik
2016c9d39130123238ac18478a42e25cb7996eacfcc0Jeff Garzik	tmp = readl(hc_mmio + 0x20);
2017c9d39130123238ac18478a42e25cb7996eacfcc0Jeff Garzik	tmp &= 0x1c1c1c1c;
2018c9d39130123238ac18478a42e25cb7996eacfcc0Jeff Garzik	tmp |= 0x03030303;
2019c9d39130123238ac18478a42e25cb7996eacfcc0Jeff Garzik	writel(tmp, hc_mmio + 0x20);
2020c9d39130123238ac18478a42e25cb7996eacfcc0Jeff Garzik}
2021c9d39130123238ac18478a42e25cb7996eacfcc0Jeff Garzik#undef ZERO
2022c9d39130123238ac18478a42e25cb7996eacfcc0Jeff Garzik
2023c9d39130123238ac18478a42e25cb7996eacfcc0Jeff Garzikstatic int mv5_reset_hc(struct mv_host_priv *hpriv, void __iomem *mmio,
2024c9d39130123238ac18478a42e25cb7996eacfcc0Jeff Garzik			unsigned int n_hc)
2025c9d39130123238ac18478a42e25cb7996eacfcc0Jeff Garzik{
2026c9d39130123238ac18478a42e25cb7996eacfcc0Jeff Garzik	unsigned int hc, port;
2027c9d39130123238ac18478a42e25cb7996eacfcc0Jeff Garzik
2028c9d39130123238ac18478a42e25cb7996eacfcc0Jeff Garzik	for (hc = 0; hc < n_hc; hc++) {
2029c9d39130123238ac18478a42e25cb7996eacfcc0Jeff Garzik		for (port = 0; port < MV_PORTS_PER_HC; port++)
2030c9d39130123238ac18478a42e25cb7996eacfcc0Jeff Garzik			mv5_reset_hc_port(hpriv, mmio,
2031c9d39130123238ac18478a42e25cb7996eacfcc0Jeff Garzik					  (hc * MV_PORTS_PER_HC) + port);
2032c9d39130123238ac18478a42e25cb7996eacfcc0Jeff Garzik
2033c9d39130123238ac18478a42e25cb7996eacfcc0Jeff Garzik		mv5_reset_one_hc(hpriv, mmio, hc);
2034c9d39130123238ac18478a42e25cb7996eacfcc0Jeff Garzik	}
2035c9d39130123238ac18478a42e25cb7996eacfcc0Jeff Garzik
2036c9d39130123238ac18478a42e25cb7996eacfcc0Jeff Garzik	return 0;
203747c2b677daeed9c79ecb7167c211ff36876ea611Jeff Garzik}
203847c2b677daeed9c79ecb7167c211ff36876ea611Jeff Garzik
2039101ffae26c23ea928fce6d31a8b4901327d91a15Jeff Garzik#undef ZERO
2040101ffae26c23ea928fce6d31a8b4901327d91a15Jeff Garzik#define ZERO(reg) writel(0, mmio + (reg))
20417bb3c5290ca0ec9e65947c907495c2b56e895e46Saeed Bisharastatic void mv_reset_pci_bus(struct ata_host *host, void __iomem *mmio)
2042101ffae26c23ea928fce6d31a8b4901327d91a15Jeff Garzik{
204302a121da5a53d415b6596bc19cc6999d295d32a4Mark Lord	struct mv_host_priv *hpriv = host->private_data;
2044101ffae26c23ea928fce6d31a8b4901327d91a15Jeff Garzik	u32 tmp;
2045101ffae26c23ea928fce6d31a8b4901327d91a15Jeff Garzik
2046101ffae26c23ea928fce6d31a8b4901327d91a15Jeff Garzik	tmp = readl(mmio + MV_PCI_MODE);
2047101ffae26c23ea928fce6d31a8b4901327d91a15Jeff Garzik	tmp &= 0xff00ffff;
2048101ffae26c23ea928fce6d31a8b4901327d91a15Jeff Garzik	writel(tmp, mmio + MV_PCI_MODE);
2049101ffae26c23ea928fce6d31a8b4901327d91a15Jeff Garzik
2050101ffae26c23ea928fce6d31a8b4901327d91a15Jeff Garzik	ZERO(MV_PCI_DISC_TIMER);
2051101ffae26c23ea928fce6d31a8b4901327d91a15Jeff Garzik	ZERO(MV_PCI_MSI_TRIGGER);
2052101ffae26c23ea928fce6d31a8b4901327d91a15Jeff Garzik	writel(0x000100ff, mmio + MV_PCI_XBAR_TMOUT);
2053101ffae26c23ea928fce6d31a8b4901327d91a15Jeff Garzik	ZERO(HC_MAIN_IRQ_MASK_OFS);
2054101ffae26c23ea928fce6d31a8b4901327d91a15Jeff Garzik	ZERO(MV_PCI_SERR_MASK);
205502a121da5a53d415b6596bc19cc6999d295d32a4Mark Lord	ZERO(hpriv->irq_cause_ofs);
205602a121da5a53d415b6596bc19cc6999d295d32a4Mark Lord	ZERO(hpriv->irq_mask_ofs);
2057101ffae26c23ea928fce6d31a8b4901327d91a15Jeff Garzik	ZERO(MV_PCI_ERR_LOW_ADDRESS);
2058101ffae26c23ea928fce6d31a8b4901327d91a15Jeff Garzik	ZERO(MV_PCI_ERR_HIGH_ADDRESS);
2059101ffae26c23ea928fce6d31a8b4901327d91a15Jeff Garzik	ZERO(MV_PCI_ERR_ATTRIBUTE);
2060101ffae26c23ea928fce6d31a8b4901327d91a15Jeff Garzik	ZERO(MV_PCI_ERR_COMMAND);
2061101ffae26c23ea928fce6d31a8b4901327d91a15Jeff Garzik}
2062101ffae26c23ea928fce6d31a8b4901327d91a15Jeff Garzik#undef ZERO
2063101ffae26c23ea928fce6d31a8b4901327d91a15Jeff Garzik
2064101ffae26c23ea928fce6d31a8b4901327d91a15Jeff Garzikstatic void mv6_reset_flash(struct mv_host_priv *hpriv, void __iomem *mmio)
2065101ffae26c23ea928fce6d31a8b4901327d91a15Jeff Garzik{
2066101ffae26c23ea928fce6d31a8b4901327d91a15Jeff Garzik	u32 tmp;
2067101ffae26c23ea928fce6d31a8b4901327d91a15Jeff Garzik
2068101ffae26c23ea928fce6d31a8b4901327d91a15Jeff Garzik	mv5_reset_flash(hpriv, mmio);
2069101ffae26c23ea928fce6d31a8b4901327d91a15Jeff Garzik
2070101ffae26c23ea928fce6d31a8b4901327d91a15Jeff Garzik	tmp = readl(mmio + MV_GPIO_PORT_CTL);
2071101ffae26c23ea928fce6d31a8b4901327d91a15Jeff Garzik	tmp &= 0x3;
2072101ffae26c23ea928fce6d31a8b4901327d91a15Jeff Garzik	tmp |= (1 << 5) | (1 << 6);
2073101ffae26c23ea928fce6d31a8b4901327d91a15Jeff Garzik	writel(tmp, mmio + MV_GPIO_PORT_CTL);
2074101ffae26c23ea928fce6d31a8b4901327d91a15Jeff Garzik}
2075101ffae26c23ea928fce6d31a8b4901327d91a15Jeff Garzik
2076101ffae26c23ea928fce6d31a8b4901327d91a15Jeff Garzik/**
2077101ffae26c23ea928fce6d31a8b4901327d91a15Jeff Garzik *      mv6_reset_hc - Perform the 6xxx global soft reset
2078101ffae26c23ea928fce6d31a8b4901327d91a15Jeff Garzik *      @mmio: base address of the HBA
2079101ffae26c23ea928fce6d31a8b4901327d91a15Jeff Garzik *
2080101ffae26c23ea928fce6d31a8b4901327d91a15Jeff Garzik *      This routine only applies to 6xxx parts.
2081101ffae26c23ea928fce6d31a8b4901327d91a15Jeff Garzik *
2082101ffae26c23ea928fce6d31a8b4901327d91a15Jeff Garzik *      LOCKING:
2083101ffae26c23ea928fce6d31a8b4901327d91a15Jeff Garzik *      Inherited from caller.
2084101ffae26c23ea928fce6d31a8b4901327d91a15Jeff Garzik */
2085c9d39130123238ac18478a42e25cb7996eacfcc0Jeff Garzikstatic int mv6_reset_hc(struct mv_host_priv *hpriv, void __iomem *mmio,
2086c9d39130123238ac18478a42e25cb7996eacfcc0Jeff Garzik			unsigned int n_hc)
2087101ffae26c23ea928fce6d31a8b4901327d91a15Jeff Garzik{
2088101ffae26c23ea928fce6d31a8b4901327d91a15Jeff Garzik	void __iomem *reg = mmio + PCI_MAIN_CMD_STS_OFS;
2089101ffae26c23ea928fce6d31a8b4901327d91a15Jeff Garzik	int i, rc = 0;
2090101ffae26c23ea928fce6d31a8b4901327d91a15Jeff Garzik	u32 t;
2091101ffae26c23ea928fce6d31a8b4901327d91a15Jeff Garzik
2092101ffae26c23ea928fce6d31a8b4901327d91a15Jeff Garzik	/* Following procedure defined in PCI "main command and status
2093101ffae26c23ea928fce6d31a8b4901327d91a15Jeff Garzik	 * register" table.
2094101ffae26c23ea928fce6d31a8b4901327d91a15Jeff Garzik	 */
2095101ffae26c23ea928fce6d31a8b4901327d91a15Jeff Garzik	t = readl(reg);
2096101ffae26c23ea928fce6d31a8b4901327d91a15Jeff Garzik	writel(t | STOP_PCI_MASTER, reg);
2097101ffae26c23ea928fce6d31a8b4901327d91a15Jeff Garzik
2098101ffae26c23ea928fce6d31a8b4901327d91a15Jeff Garzik	for (i = 0; i < 1000; i++) {
2099101ffae26c23ea928fce6d31a8b4901327d91a15Jeff Garzik		udelay(1);
2100101ffae26c23ea928fce6d31a8b4901327d91a15Jeff Garzik		t = readl(reg);
21012dcb407e61458ded17503d6bd12b8c064965368bJeff Garzik		if (PCI_MASTER_EMPTY & t)
2102101ffae26c23ea928fce6d31a8b4901327d91a15Jeff Garzik			break;
2103101ffae26c23ea928fce6d31a8b4901327d91a15Jeff Garzik	}
2104101ffae26c23ea928fce6d31a8b4901327d91a15Jeff Garzik	if (!(PCI_MASTER_EMPTY & t)) {
2105101ffae26c23ea928fce6d31a8b4901327d91a15Jeff Garzik		printk(KERN_ERR DRV_NAME ": PCI master won't flush\n");
2106101ffae26c23ea928fce6d31a8b4901327d91a15Jeff Garzik		rc = 1;
2107101ffae26c23ea928fce6d31a8b4901327d91a15Jeff Garzik		goto done;
2108101ffae26c23ea928fce6d31a8b4901327d91a15Jeff Garzik	}
2109101ffae26c23ea928fce6d31a8b4901327d91a15Jeff Garzik
2110101ffae26c23ea928fce6d31a8b4901327d91a15Jeff Garzik	/* set reset */
2111101ffae26c23ea928fce6d31a8b4901327d91a15Jeff Garzik	i = 5;
2112101ffae26c23ea928fce6d31a8b4901327d91a15Jeff Garzik	do {
2113101ffae26c23ea928fce6d31a8b4901327d91a15Jeff Garzik		writel(t | GLOB_SFT_RST, reg);
2114101ffae26c23ea928fce6d31a8b4901327d91a15Jeff Garzik		t = readl(reg);
2115101ffae26c23ea928fce6d31a8b4901327d91a15Jeff Garzik		udelay(1);
2116101ffae26c23ea928fce6d31a8b4901327d91a15Jeff Garzik	} while (!(GLOB_SFT_RST & t) && (i-- > 0));
2117101ffae26c23ea928fce6d31a8b4901327d91a15Jeff Garzik
2118101ffae26c23ea928fce6d31a8b4901327d91a15Jeff Garzik	if (!(GLOB_SFT_RST & t)) {
2119101ffae26c23ea928fce6d31a8b4901327d91a15Jeff Garzik		printk(KERN_ERR DRV_NAME ": can't set global reset\n");
2120101ffae26c23ea928fce6d31a8b4901327d91a15Jeff Garzik		rc = 1;
2121101ffae26c23ea928fce6d31a8b4901327d91a15Jeff Garzik		goto done;
2122101ffae26c23ea928fce6d31a8b4901327d91a15Jeff Garzik	}
2123101ffae26c23ea928fce6d31a8b4901327d91a15Jeff Garzik
2124101ffae26c23ea928fce6d31a8b4901327d91a15Jeff Garzik	/* clear reset and *reenable the PCI master* (not mentioned in spec) */
2125101ffae26c23ea928fce6d31a8b4901327d91a15Jeff Garzik	i = 5;
2126101ffae26c23ea928fce6d31a8b4901327d91a15Jeff Garzik	do {
2127101ffae26c23ea928fce6d31a8b4901327d91a15Jeff Garzik		writel(t & ~(GLOB_SFT_RST | STOP_PCI_MASTER), reg);
2128101ffae26c23ea928fce6d31a8b4901327d91a15Jeff Garzik		t = readl(reg);
2129101ffae26c23ea928fce6d31a8b4901327d91a15Jeff Garzik		udelay(1);
2130101ffae26c23ea928fce6d31a8b4901327d91a15Jeff Garzik	} while ((GLOB_SFT_RST & t) && (i-- > 0));
2131101ffae26c23ea928fce6d31a8b4901327d91a15Jeff Garzik
2132101ffae26c23ea928fce6d31a8b4901327d91a15Jeff Garzik	if (GLOB_SFT_RST & t) {
2133101ffae26c23ea928fce6d31a8b4901327d91a15Jeff Garzik		printk(KERN_ERR DRV_NAME ": can't clear global reset\n");
2134101ffae26c23ea928fce6d31a8b4901327d91a15Jeff Garzik		rc = 1;
2135101ffae26c23ea928fce6d31a8b4901327d91a15Jeff Garzik	}
2136101ffae26c23ea928fce6d31a8b4901327d91a15Jeff Garzikdone:
2137101ffae26c23ea928fce6d31a8b4901327d91a15Jeff Garzik	return rc;
2138101ffae26c23ea928fce6d31a8b4901327d91a15Jeff Garzik}
2139101ffae26c23ea928fce6d31a8b4901327d91a15Jeff Garzik
214047c2b677daeed9c79ecb7167c211ff36876ea611Jeff Garzikstatic void mv6_read_preamp(struct mv_host_priv *hpriv, int idx,
2141ba3fe8fb6a469390a14379519915f3c39a973d99Jeff Garzik			   void __iomem *mmio)
2142ba3fe8fb6a469390a14379519915f3c39a973d99Jeff Garzik{
2143ba3fe8fb6a469390a14379519915f3c39a973d99Jeff Garzik	void __iomem *port_mmio;
2144ba3fe8fb6a469390a14379519915f3c39a973d99Jeff Garzik	u32 tmp;
2145ba3fe8fb6a469390a14379519915f3c39a973d99Jeff Garzik
2146ba3fe8fb6a469390a14379519915f3c39a973d99Jeff Garzik	tmp = readl(mmio + MV_RESET_CFG);
2147ba3fe8fb6a469390a14379519915f3c39a973d99Jeff Garzik	if ((tmp & (1 << 0)) == 0) {
214847c2b677daeed9c79ecb7167c211ff36876ea611Jeff Garzik		hpriv->signal[idx].amps = 0x7 << 8;
2149ba3fe8fb6a469390a14379519915f3c39a973d99Jeff Garzik		hpriv->signal[idx].pre = 0x1 << 5;
2150ba3fe8fb6a469390a14379519915f3c39a973d99Jeff Garzik		return;
2151ba3fe8fb6a469390a14379519915f3c39a973d99Jeff Garzik	}
2152ba3fe8fb6a469390a14379519915f3c39a973d99Jeff Garzik
2153ba3fe8fb6a469390a14379519915f3c39a973d99Jeff Garzik	port_mmio = mv_port_base(mmio, idx);
2154ba3fe8fb6a469390a14379519915f3c39a973d99Jeff Garzik	tmp = readl(port_mmio + PHY_MODE2);
2155ba3fe8fb6a469390a14379519915f3c39a973d99Jeff Garzik
2156ba3fe8fb6a469390a14379519915f3c39a973d99Jeff Garzik	hpriv->signal[idx].amps = tmp & 0x700;	/* bits 10:8 */
2157ba3fe8fb6a469390a14379519915f3c39a973d99Jeff Garzik	hpriv->signal[idx].pre = tmp & 0xe0;	/* bits 7:5 */
2158ba3fe8fb6a469390a14379519915f3c39a973d99Jeff Garzik}
2159ba3fe8fb6a469390a14379519915f3c39a973d99Jeff Garzik
216047c2b677daeed9c79ecb7167c211ff36876ea611Jeff Garzikstatic void mv6_enable_leds(struct mv_host_priv *hpriv, void __iomem *mmio)
2161ba3fe8fb6a469390a14379519915f3c39a973d99Jeff Garzik{
216247c2b677daeed9c79ecb7167c211ff36876ea611Jeff Garzik	writel(0x00000060, mmio + MV_GPIO_PORT_CTL);
2163ba3fe8fb6a469390a14379519915f3c39a973d99Jeff Garzik}
2164ba3fe8fb6a469390a14379519915f3c39a973d99Jeff Garzik
2165c9d39130123238ac18478a42e25cb7996eacfcc0Jeff Garzikstatic void mv6_phy_errata(struct mv_host_priv *hpriv, void __iomem *mmio,
21662a47ce06d534692f9bd2bf4e90a20fc9b1054c39Jeff Garzik			   unsigned int port)
2167bca1c4eb9411533d613123618c0d127fae532595Jeff Garzik{
2168c9d39130123238ac18478a42e25cb7996eacfcc0Jeff Garzik	void __iomem *port_mmio = mv_port_base(mmio, port);
2169c9d39130123238ac18478a42e25cb7996eacfcc0Jeff Garzik
2170bca1c4eb9411533d613123618c0d127fae532595Jeff Garzik	u32 hp_flags = hpriv->hp_flags;
217147c2b677daeed9c79ecb7167c211ff36876ea611Jeff Garzik	int fix_phy_mode2 =
217247c2b677daeed9c79ecb7167c211ff36876ea611Jeff Garzik		hp_flags & (MV_HP_ERRATA_60X1B2 | MV_HP_ERRATA_60X1C0);
2173bca1c4eb9411533d613123618c0d127fae532595Jeff Garzik	int fix_phy_mode4 =
217447c2b677daeed9c79ecb7167c211ff36876ea611Jeff Garzik		hp_flags & (MV_HP_ERRATA_60X1B2 | MV_HP_ERRATA_60X1C0);
217547c2b677daeed9c79ecb7167c211ff36876ea611Jeff Garzik	u32 m2, tmp;
217647c2b677daeed9c79ecb7167c211ff36876ea611Jeff Garzik
217747c2b677daeed9c79ecb7167c211ff36876ea611Jeff Garzik	if (fix_phy_mode2) {
217847c2b677daeed9c79ecb7167c211ff36876ea611Jeff Garzik		m2 = readl(port_mmio + PHY_MODE2);
217947c2b677daeed9c79ecb7167c211ff36876ea611Jeff Garzik		m2 &= ~(1 << 16);
218047c2b677daeed9c79ecb7167c211ff36876ea611Jeff Garzik		m2 |= (1 << 31);
218147c2b677daeed9c79ecb7167c211ff36876ea611Jeff Garzik		writel(m2, port_mmio + PHY_MODE2);
218247c2b677daeed9c79ecb7167c211ff36876ea611Jeff Garzik
218347c2b677daeed9c79ecb7167c211ff36876ea611Jeff Garzik		udelay(200);
218447c2b677daeed9c79ecb7167c211ff36876ea611Jeff Garzik
218547c2b677daeed9c79ecb7167c211ff36876ea611Jeff Garzik		m2 = readl(port_mmio + PHY_MODE2);
218647c2b677daeed9c79ecb7167c211ff36876ea611Jeff Garzik		m2 &= ~((1 << 16) | (1 << 31));
218747c2b677daeed9c79ecb7167c211ff36876ea611Jeff Garzik		writel(m2, port_mmio + PHY_MODE2);
218847c2b677daeed9c79ecb7167c211ff36876ea611Jeff Garzik
218947c2b677daeed9c79ecb7167c211ff36876ea611Jeff Garzik		udelay(200);
219047c2b677daeed9c79ecb7167c211ff36876ea611Jeff Garzik	}
219147c2b677daeed9c79ecb7167c211ff36876ea611Jeff Garzik
219247c2b677daeed9c79ecb7167c211ff36876ea611Jeff Garzik	/* who knows what this magic does */
219347c2b677daeed9c79ecb7167c211ff36876ea611Jeff Garzik	tmp = readl(port_mmio + PHY_MODE3);
219447c2b677daeed9c79ecb7167c211ff36876ea611Jeff Garzik	tmp &= ~0x7F800000;
219547c2b677daeed9c79ecb7167c211ff36876ea611Jeff Garzik	tmp |= 0x2A800000;
219647c2b677daeed9c79ecb7167c211ff36876ea611Jeff Garzik	writel(tmp, port_mmio + PHY_MODE3);
2197bca1c4eb9411533d613123618c0d127fae532595Jeff Garzik
2198bca1c4eb9411533d613123618c0d127fae532595Jeff Garzik	if (fix_phy_mode4) {
219947c2b677daeed9c79ecb7167c211ff36876ea611Jeff Garzik		u32 m4;
2200bca1c4eb9411533d613123618c0d127fae532595Jeff Garzik
2201bca1c4eb9411533d613123618c0d127fae532595Jeff Garzik		m4 = readl(port_mmio + PHY_MODE4);
220247c2b677daeed9c79ecb7167c211ff36876ea611Jeff Garzik
220347c2b677daeed9c79ecb7167c211ff36876ea611Jeff Garzik		if (hp_flags & MV_HP_ERRATA_60X1B2)
220447c2b677daeed9c79ecb7167c211ff36876ea611Jeff Garzik			tmp = readl(port_mmio + 0x310);
2205bca1c4eb9411533d613123618c0d127fae532595Jeff Garzik
2206bca1c4eb9411533d613123618c0d127fae532595Jeff Garzik		m4 = (m4 & ~(1 << 1)) | (1 << 0);
2207bca1c4eb9411533d613123618c0d127fae532595Jeff Garzik
2208bca1c4eb9411533d613123618c0d127fae532595Jeff Garzik		writel(m4, port_mmio + PHY_MODE4);
220947c2b677daeed9c79ecb7167c211ff36876ea611Jeff Garzik
221047c2b677daeed9c79ecb7167c211ff36876ea611Jeff Garzik		if (hp_flags & MV_HP_ERRATA_60X1B2)
221147c2b677daeed9c79ecb7167c211ff36876ea611Jeff Garzik			writel(tmp, port_mmio + 0x310);
2212bca1c4eb9411533d613123618c0d127fae532595Jeff Garzik	}
2213bca1c4eb9411533d613123618c0d127fae532595Jeff Garzik
2214bca1c4eb9411533d613123618c0d127fae532595Jeff Garzik	/* Revert values of pre-emphasis and signal amps to the saved ones */
2215bca1c4eb9411533d613123618c0d127fae532595Jeff Garzik	m2 = readl(port_mmio + PHY_MODE2);
2216bca1c4eb9411533d613123618c0d127fae532595Jeff Garzik
2217bca1c4eb9411533d613123618c0d127fae532595Jeff Garzik	m2 &= ~MV_M2_PREAMP_MASK;
22182a47ce06d534692f9bd2bf4e90a20fc9b1054c39Jeff Garzik	m2 |= hpriv->signal[port].amps;
22192a47ce06d534692f9bd2bf4e90a20fc9b1054c39Jeff Garzik	m2 |= hpriv->signal[port].pre;
222047c2b677daeed9c79ecb7167c211ff36876ea611Jeff Garzik	m2 &= ~(1 << 16);
2221bca1c4eb9411533d613123618c0d127fae532595Jeff Garzik
2222e4e7b89280d1d666e2c09e5ad36cf071796c4c7eJeff Garzik	/* according to mvSata 3.6.1, some IIE values are fixed */
2223e4e7b89280d1d666e2c09e5ad36cf071796c4c7eJeff Garzik	if (IS_GEN_IIE(hpriv)) {
2224e4e7b89280d1d666e2c09e5ad36cf071796c4c7eJeff Garzik		m2 &= ~0xC30FF01F;
2225e4e7b89280d1d666e2c09e5ad36cf071796c4c7eJeff Garzik		m2 |= 0x0000900F;
2226e4e7b89280d1d666e2c09e5ad36cf071796c4c7eJeff Garzik	}
2227e4e7b89280d1d666e2c09e5ad36cf071796c4c7eJeff Garzik
2228bca1c4eb9411533d613123618c0d127fae532595Jeff Garzik	writel(m2, port_mmio + PHY_MODE2);
2229bca1c4eb9411533d613123618c0d127fae532595Jeff Garzik}
2230bca1c4eb9411533d613123618c0d127fae532595Jeff Garzik
2231f351b2d638c3cb0b95adde3549b7bfaf3f991dfaSaeed Bishara/* TODO: use the generic LED interface to configure the SATA Presence */
2232f351b2d638c3cb0b95adde3549b7bfaf3f991dfaSaeed Bishara/* & Acitivy LEDs on the board */
2233f351b2d638c3cb0b95adde3549b7bfaf3f991dfaSaeed Bisharastatic void mv_soc_enable_leds(struct mv_host_priv *hpriv,
2234f351b2d638c3cb0b95adde3549b7bfaf3f991dfaSaeed Bishara				      void __iomem *mmio)
2235f351b2d638c3cb0b95adde3549b7bfaf3f991dfaSaeed Bishara{
2236f351b2d638c3cb0b95adde3549b7bfaf3f991dfaSaeed Bishara	return;
2237f351b2d638c3cb0b95adde3549b7bfaf3f991dfaSaeed Bishara}
2238f351b2d638c3cb0b95adde3549b7bfaf3f991dfaSaeed Bishara
2239f351b2d638c3cb0b95adde3549b7bfaf3f991dfaSaeed Bisharastatic void mv_soc_read_preamp(struct mv_host_priv *hpriv, int idx,
2240f351b2d638c3cb0b95adde3549b7bfaf3f991dfaSaeed Bishara			   void __iomem *mmio)
2241f351b2d638c3cb0b95adde3549b7bfaf3f991dfaSaeed Bishara{
2242f351b2d638c3cb0b95adde3549b7bfaf3f991dfaSaeed Bishara	void __iomem *port_mmio;
2243f351b2d638c3cb0b95adde3549b7bfaf3f991dfaSaeed Bishara	u32 tmp;
2244f351b2d638c3cb0b95adde3549b7bfaf3f991dfaSaeed Bishara
2245f351b2d638c3cb0b95adde3549b7bfaf3f991dfaSaeed Bishara	port_mmio = mv_port_base(mmio, idx);
2246f351b2d638c3cb0b95adde3549b7bfaf3f991dfaSaeed Bishara	tmp = readl(port_mmio + PHY_MODE2);
2247f351b2d638c3cb0b95adde3549b7bfaf3f991dfaSaeed Bishara
2248f351b2d638c3cb0b95adde3549b7bfaf3f991dfaSaeed Bishara	hpriv->signal[idx].amps = tmp & 0x700;	/* bits 10:8 */
2249f351b2d638c3cb0b95adde3549b7bfaf3f991dfaSaeed Bishara	hpriv->signal[idx].pre = tmp & 0xe0;	/* bits 7:5 */
2250f351b2d638c3cb0b95adde3549b7bfaf3f991dfaSaeed Bishara}
2251f351b2d638c3cb0b95adde3549b7bfaf3f991dfaSaeed Bishara
2252f351b2d638c3cb0b95adde3549b7bfaf3f991dfaSaeed Bishara#undef ZERO
2253f351b2d638c3cb0b95adde3549b7bfaf3f991dfaSaeed Bishara#define ZERO(reg) writel(0, port_mmio + (reg))
2254f351b2d638c3cb0b95adde3549b7bfaf3f991dfaSaeed Bisharastatic void mv_soc_reset_hc_port(struct mv_host_priv *hpriv,
2255f351b2d638c3cb0b95adde3549b7bfaf3f991dfaSaeed Bishara					void __iomem *mmio, unsigned int port)
2256f351b2d638c3cb0b95adde3549b7bfaf3f991dfaSaeed Bishara{
2257f351b2d638c3cb0b95adde3549b7bfaf3f991dfaSaeed Bishara	void __iomem *port_mmio = mv_port_base(mmio, port);
2258f351b2d638c3cb0b95adde3549b7bfaf3f991dfaSaeed Bishara
2259f351b2d638c3cb0b95adde3549b7bfaf3f991dfaSaeed Bishara	writelfl(EDMA_DS, port_mmio + EDMA_CMD_OFS);
2260f351b2d638c3cb0b95adde3549b7bfaf3f991dfaSaeed Bishara
2261f351b2d638c3cb0b95adde3549b7bfaf3f991dfaSaeed Bishara	mv_channel_reset(hpriv, mmio, port);
2262f351b2d638c3cb0b95adde3549b7bfaf3f991dfaSaeed Bishara
2263f351b2d638c3cb0b95adde3549b7bfaf3f991dfaSaeed Bishara	ZERO(0x028);		/* command */
2264f351b2d638c3cb0b95adde3549b7bfaf3f991dfaSaeed Bishara	writel(0x101f, port_mmio + EDMA_CFG_OFS);
2265f351b2d638c3cb0b95adde3549b7bfaf3f991dfaSaeed Bishara	ZERO(0x004);		/* timer */
2266f351b2d638c3cb0b95adde3549b7bfaf3f991dfaSaeed Bishara	ZERO(0x008);		/* irq err cause */
2267f351b2d638c3cb0b95adde3549b7bfaf3f991dfaSaeed Bishara	ZERO(0x00c);		/* irq err mask */
2268f351b2d638c3cb0b95adde3549b7bfaf3f991dfaSaeed Bishara	ZERO(0x010);		/* rq bah */
2269f351b2d638c3cb0b95adde3549b7bfaf3f991dfaSaeed Bishara	ZERO(0x014);		/* rq inp */
2270f351b2d638c3cb0b95adde3549b7bfaf3f991dfaSaeed Bishara	ZERO(0x018);		/* rq outp */
2271f351b2d638c3cb0b95adde3549b7bfaf3f991dfaSaeed Bishara	ZERO(0x01c);		/* respq bah */
2272f351b2d638c3cb0b95adde3549b7bfaf3f991dfaSaeed Bishara	ZERO(0x024);		/* respq outp */
2273f351b2d638c3cb0b95adde3549b7bfaf3f991dfaSaeed Bishara	ZERO(0x020);		/* respq inp */
2274f351b2d638c3cb0b95adde3549b7bfaf3f991dfaSaeed Bishara	ZERO(0x02c);		/* test control */
2275f351b2d638c3cb0b95adde3549b7bfaf3f991dfaSaeed Bishara	writel(0xbc, port_mmio + EDMA_IORDY_TMOUT);
2276f351b2d638c3cb0b95adde3549b7bfaf3f991dfaSaeed Bishara}
2277f351b2d638c3cb0b95adde3549b7bfaf3f991dfaSaeed Bishara
2278f351b2d638c3cb0b95adde3549b7bfaf3f991dfaSaeed Bishara#undef ZERO
2279f351b2d638c3cb0b95adde3549b7bfaf3f991dfaSaeed Bishara
2280f351b2d638c3cb0b95adde3549b7bfaf3f991dfaSaeed Bishara#define ZERO(reg) writel(0, hc_mmio + (reg))
2281f351b2d638c3cb0b95adde3549b7bfaf3f991dfaSaeed Bisharastatic void mv_soc_reset_one_hc(struct mv_host_priv *hpriv,
2282f351b2d638c3cb0b95adde3549b7bfaf3f991dfaSaeed Bishara				       void __iomem *mmio)
2283f351b2d638c3cb0b95adde3549b7bfaf3f991dfaSaeed Bishara{
2284f351b2d638c3cb0b95adde3549b7bfaf3f991dfaSaeed Bishara	void __iomem *hc_mmio = mv_hc_base(mmio, 0);
2285f351b2d638c3cb0b95adde3549b7bfaf3f991dfaSaeed Bishara
2286f351b2d638c3cb0b95adde3549b7bfaf3f991dfaSaeed Bishara	ZERO(0x00c);
2287f351b2d638c3cb0b95adde3549b7bfaf3f991dfaSaeed Bishara	ZERO(0x010);
2288f351b2d638c3cb0b95adde3549b7bfaf3f991dfaSaeed Bishara	ZERO(0x014);
2289f351b2d638c3cb0b95adde3549b7bfaf3f991dfaSaeed Bishara
2290f351b2d638c3cb0b95adde3549b7bfaf3f991dfaSaeed Bishara}
2291f351b2d638c3cb0b95adde3549b7bfaf3f991dfaSaeed Bishara
2292f351b2d638c3cb0b95adde3549b7bfaf3f991dfaSaeed Bishara#undef ZERO
2293f351b2d638c3cb0b95adde3549b7bfaf3f991dfaSaeed Bishara
2294f351b2d638c3cb0b95adde3549b7bfaf3f991dfaSaeed Bisharastatic int mv_soc_reset_hc(struct mv_host_priv *hpriv,
2295f351b2d638c3cb0b95adde3549b7bfaf3f991dfaSaeed Bishara				  void __iomem *mmio, unsigned int n_hc)
2296f351b2d638c3cb0b95adde3549b7bfaf3f991dfaSaeed Bishara{
2297f351b2d638c3cb0b95adde3549b7bfaf3f991dfaSaeed Bishara	unsigned int port;
2298f351b2d638c3cb0b95adde3549b7bfaf3f991dfaSaeed Bishara
2299f351b2d638c3cb0b95adde3549b7bfaf3f991dfaSaeed Bishara	for (port = 0; port < hpriv->n_ports; port++)
2300f351b2d638c3cb0b95adde3549b7bfaf3f991dfaSaeed Bishara		mv_soc_reset_hc_port(hpriv, mmio, port);
2301f351b2d638c3cb0b95adde3549b7bfaf3f991dfaSaeed Bishara
2302f351b2d638c3cb0b95adde3549b7bfaf3f991dfaSaeed Bishara	mv_soc_reset_one_hc(hpriv, mmio);
2303f351b2d638c3cb0b95adde3549b7bfaf3f991dfaSaeed Bishara
2304f351b2d638c3cb0b95adde3549b7bfaf3f991dfaSaeed Bishara	return 0;
2305f351b2d638c3cb0b95adde3549b7bfaf3f991dfaSaeed Bishara}
2306f351b2d638c3cb0b95adde3549b7bfaf3f991dfaSaeed Bishara
2307f351b2d638c3cb0b95adde3549b7bfaf3f991dfaSaeed Bisharastatic void mv_soc_reset_flash(struct mv_host_priv *hpriv,
2308f351b2d638c3cb0b95adde3549b7bfaf3f991dfaSaeed Bishara				      void __iomem *mmio)
2309f351b2d638c3cb0b95adde3549b7bfaf3f991dfaSaeed Bishara{
2310f351b2d638c3cb0b95adde3549b7bfaf3f991dfaSaeed Bishara	return;
2311f351b2d638c3cb0b95adde3549b7bfaf3f991dfaSaeed Bishara}
2312f351b2d638c3cb0b95adde3549b7bfaf3f991dfaSaeed Bishara
2313f351b2d638c3cb0b95adde3549b7bfaf3f991dfaSaeed Bisharastatic void mv_soc_reset_bus(struct ata_host *host, void __iomem *mmio)
2314f351b2d638c3cb0b95adde3549b7bfaf3f991dfaSaeed Bishara{
2315f351b2d638c3cb0b95adde3549b7bfaf3f991dfaSaeed Bishara	return;
2316f351b2d638c3cb0b95adde3549b7bfaf3f991dfaSaeed Bishara}
2317f351b2d638c3cb0b95adde3549b7bfaf3f991dfaSaeed Bishara
2318c9d39130123238ac18478a42e25cb7996eacfcc0Jeff Garzikstatic void mv_channel_reset(struct mv_host_priv *hpriv, void __iomem *mmio,
2319c9d39130123238ac18478a42e25cb7996eacfcc0Jeff Garzik			     unsigned int port_no)
2320c9d39130123238ac18478a42e25cb7996eacfcc0Jeff Garzik{
2321c9d39130123238ac18478a42e25cb7996eacfcc0Jeff Garzik	void __iomem *port_mmio = mv_port_base(mmio, port_no);
2322c9d39130123238ac18478a42e25cb7996eacfcc0Jeff Garzik
2323c9d39130123238ac18478a42e25cb7996eacfcc0Jeff Garzik	writelfl(ATA_RST, port_mmio + EDMA_CMD_OFS);
2324c9d39130123238ac18478a42e25cb7996eacfcc0Jeff Garzik
2325ee9ccdf70163ca6408f6965e0fbc65baeac7312cJeff Garzik	if (IS_GEN_II(hpriv)) {
2326c9d39130123238ac18478a42e25cb7996eacfcc0Jeff Garzik		u32 ifctl = readl(port_mmio + SATA_INTERFACE_CTL);
2327eb46d684600ac145501805a294c94675e82eab2eMark Lord		ifctl |= (1 << 7);		/* enable gen2i speed */
2328eb46d684600ac145501805a294c94675e82eab2eMark Lord		ifctl = (ifctl & 0xfff) | 0x9b1000; /* from chip spec */
2329c9d39130123238ac18478a42e25cb7996eacfcc0Jeff Garzik		writelfl(ifctl, port_mmio + SATA_INTERFACE_CTL);
2330c9d39130123238ac18478a42e25cb7996eacfcc0Jeff Garzik	}
2331c9d39130123238ac18478a42e25cb7996eacfcc0Jeff Garzik
2332c9d39130123238ac18478a42e25cb7996eacfcc0Jeff Garzik	udelay(25);		/* allow reset propagation */
2333c9d39130123238ac18478a42e25cb7996eacfcc0Jeff Garzik
2334c9d39130123238ac18478a42e25cb7996eacfcc0Jeff Garzik	/* Spec never mentions clearing the bit.  Marvell's driver does
2335c9d39130123238ac18478a42e25cb7996eacfcc0Jeff Garzik	 * clear the bit, however.
2336c9d39130123238ac18478a42e25cb7996eacfcc0Jeff Garzik	 */
2337c9d39130123238ac18478a42e25cb7996eacfcc0Jeff Garzik	writelfl(0, port_mmio + EDMA_CMD_OFS);
2338c9d39130123238ac18478a42e25cb7996eacfcc0Jeff Garzik
2339c9d39130123238ac18478a42e25cb7996eacfcc0Jeff Garzik	hpriv->ops->phy_errata(hpriv, mmio, port_no);
2340c9d39130123238ac18478a42e25cb7996eacfcc0Jeff Garzik
2341ee9ccdf70163ca6408f6965e0fbc65baeac7312cJeff Garzik	if (IS_GEN_I(hpriv))
2342c9d39130123238ac18478a42e25cb7996eacfcc0Jeff Garzik		mdelay(1);
2343c9d39130123238ac18478a42e25cb7996eacfcc0Jeff Garzik}
2344c9d39130123238ac18478a42e25cb7996eacfcc0Jeff Garzik
234505b308e1df6d9d673daedb517969241f41278b52Brett Russ/**
2346bdd4dddee325a7dce3e84cf48201a06aa8508aa4Jeff Garzik *      mv_phy_reset - Perform eDMA reset followed by COMRESET
234705b308e1df6d9d673daedb517969241f41278b52Brett Russ *      @ap: ATA channel to manipulate
234805b308e1df6d9d673daedb517969241f41278b52Brett Russ *
234905b308e1df6d9d673daedb517969241f41278b52Brett Russ *      Part of this is taken from __sata_phy_reset and modified to
235005b308e1df6d9d673daedb517969241f41278b52Brett Russ *      not sleep since this routine gets called from interrupt level.
235105b308e1df6d9d673daedb517969241f41278b52Brett Russ *
235205b308e1df6d9d673daedb517969241f41278b52Brett Russ *      LOCKING:
235305b308e1df6d9d673daedb517969241f41278b52Brett Russ *      Inherited from caller.  This is coded to safe to call at
235405b308e1df6d9d673daedb517969241f41278b52Brett Russ *      interrupt level, i.e. it does not sleep.
235531961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ */
2356bdd4dddee325a7dce3e84cf48201a06aa8508aa4Jeff Garzikstatic void mv_phy_reset(struct ata_port *ap, unsigned int *class,
2357bdd4dddee325a7dce3e84cf48201a06aa8508aa4Jeff Garzik			 unsigned long deadline)
235820f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ{
2359095fec887eaa1c38d17c0c929a6733c744a9fa1fJeff Garzik	struct mv_port_priv *pp	= ap->private_data;
2360cca3974e48607c3775dc73b544a5700b2e37c21aJeff Garzik	struct mv_host_priv *hpriv = ap->host->private_data;
236120f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ	void __iomem *port_mmio = mv_ap_base(ap);
236222374677d18c5eeefd3a283431d312b8c44fef02Jeff Garzik	int retry = 5;
236322374677d18c5eeefd3a283431d312b8c44fef02Jeff Garzik	u32 sstatus;
236420f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ
236520f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ	VPRINTK("ENTER, port %u, mmio 0x%p\n", ap->port_no, port_mmio);
236620f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ
2367da3dbb17a0e9a9ec7f5aed95f1fddadb790edc9dTejun Heo#ifdef DEBUG
2368da3dbb17a0e9a9ec7f5aed95f1fddadb790edc9dTejun Heo	{
2369da3dbb17a0e9a9ec7f5aed95f1fddadb790edc9dTejun Heo		u32 sstatus, serror, scontrol;
2370da3dbb17a0e9a9ec7f5aed95f1fddadb790edc9dTejun Heo
2371da3dbb17a0e9a9ec7f5aed95f1fddadb790edc9dTejun Heo		mv_scr_read(ap, SCR_STATUS, &sstatus);
2372da3dbb17a0e9a9ec7f5aed95f1fddadb790edc9dTejun Heo		mv_scr_read(ap, SCR_ERROR, &serror);
2373da3dbb17a0e9a9ec7f5aed95f1fddadb790edc9dTejun Heo		mv_scr_read(ap, SCR_CONTROL, &scontrol);
2374da3dbb17a0e9a9ec7f5aed95f1fddadb790edc9dTejun Heo		DPRINTK("S-regs after ATA_RST: SStat 0x%08x SErr 0x%08x "
23752d79ab8fd7a7bf3a45d0e948ae27b3dd95ce95eaSaeed Bishara			"SCtrl 0x%08x\n", sstatus, serror, scontrol);
2376da3dbb17a0e9a9ec7f5aed95f1fddadb790edc9dTejun Heo	}
2377da3dbb17a0e9a9ec7f5aed95f1fddadb790edc9dTejun Heo#endif
237820f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ
237922374677d18c5eeefd3a283431d312b8c44fef02Jeff Garzik	/* Issue COMRESET via SControl */
238022374677d18c5eeefd3a283431d312b8c44fef02Jeff Garzikcomreset_retry:
2381936fd7328657884d5a69a55666c74a55aa83ca27Tejun Heo	sata_scr_write_flush(&ap->link, SCR_CONTROL, 0x301);
2382bdd4dddee325a7dce3e84cf48201a06aa8508aa4Jeff Garzik	msleep(1);
238322374677d18c5eeefd3a283431d312b8c44fef02Jeff Garzik
2384936fd7328657884d5a69a55666c74a55aa83ca27Tejun Heo	sata_scr_write_flush(&ap->link, SCR_CONTROL, 0x300);
2385bdd4dddee325a7dce3e84cf48201a06aa8508aa4Jeff Garzik	msleep(20);
238622374677d18c5eeefd3a283431d312b8c44fef02Jeff Garzik
238731961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ	do {
2388936fd7328657884d5a69a55666c74a55aa83ca27Tejun Heo		sata_scr_read(&ap->link, SCR_STATUS, &sstatus);
238962f1d0e6de138b91d55fbd7d579c837ed62e9e31Andres Salomon		if (((sstatus & 0x3) == 3) || ((sstatus & 0x3) == 0))
239031961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ			break;
239122374677d18c5eeefd3a283431d312b8c44fef02Jeff Garzik
2392bdd4dddee325a7dce3e84cf48201a06aa8508aa4Jeff Garzik		msleep(1);
2393c5d3e45a2200a0905dc45b72714726b7aac3aaf1Jeff Garzik	} while (time_before(jiffies, deadline));
239420f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ
239522374677d18c5eeefd3a283431d312b8c44fef02Jeff Garzik	/* work around errata */
2396ee9ccdf70163ca6408f6965e0fbc65baeac7312cJeff Garzik	if (IS_GEN_II(hpriv) &&
239722374677d18c5eeefd3a283431d312b8c44fef02Jeff Garzik	    (sstatus != 0x0) && (sstatus != 0x113) && (sstatus != 0x123) &&
239822374677d18c5eeefd3a283431d312b8c44fef02Jeff Garzik	    (retry-- > 0))
239922374677d18c5eeefd3a283431d312b8c44fef02Jeff Garzik		goto comreset_retry;
2400095fec887eaa1c38d17c0c929a6733c744a9fa1fJeff Garzik
2401da3dbb17a0e9a9ec7f5aed95f1fddadb790edc9dTejun Heo#ifdef DEBUG
2402da3dbb17a0e9a9ec7f5aed95f1fddadb790edc9dTejun Heo	{
2403da3dbb17a0e9a9ec7f5aed95f1fddadb790edc9dTejun Heo		u32 sstatus, serror, scontrol;
2404da3dbb17a0e9a9ec7f5aed95f1fddadb790edc9dTejun Heo
2405da3dbb17a0e9a9ec7f5aed95f1fddadb790edc9dTejun Heo		mv_scr_read(ap, SCR_STATUS, &sstatus);
2406da3dbb17a0e9a9ec7f5aed95f1fddadb790edc9dTejun Heo		mv_scr_read(ap, SCR_ERROR, &serror);
2407da3dbb17a0e9a9ec7f5aed95f1fddadb790edc9dTejun Heo		mv_scr_read(ap, SCR_CONTROL, &scontrol);
2408da3dbb17a0e9a9ec7f5aed95f1fddadb790edc9dTejun Heo		DPRINTK("S-regs after PHY wake: SStat 0x%08x SErr 0x%08x "
2409da3dbb17a0e9a9ec7f5aed95f1fddadb790edc9dTejun Heo			"SCtrl 0x%08x\n", sstatus, serror, scontrol);
2410da3dbb17a0e9a9ec7f5aed95f1fddadb790edc9dTejun Heo	}
2411da3dbb17a0e9a9ec7f5aed95f1fddadb790edc9dTejun Heo#endif
241231961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ
2413936fd7328657884d5a69a55666c74a55aa83ca27Tejun Heo	if (ata_link_offline(&ap->link)) {
2414bdd4dddee325a7dce3e84cf48201a06aa8508aa4Jeff Garzik		*class = ATA_DEV_NONE;
241520f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ		return;
241620f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ	}
241720f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ
241822374677d18c5eeefd3a283431d312b8c44fef02Jeff Garzik	/* even after SStatus reflects that device is ready,
241922374677d18c5eeefd3a283431d312b8c44fef02Jeff Garzik	 * it seems to take a while for link to be fully
242022374677d18c5eeefd3a283431d312b8c44fef02Jeff Garzik	 * established (and thus Status no longer 0x80/0x7F),
242122374677d18c5eeefd3a283431d312b8c44fef02Jeff Garzik	 * so we poll a bit for that, here.
242222374677d18c5eeefd3a283431d312b8c44fef02Jeff Garzik	 */
242322374677d18c5eeefd3a283431d312b8c44fef02Jeff Garzik	retry = 20;
242422374677d18c5eeefd3a283431d312b8c44fef02Jeff Garzik	while (1) {
242522374677d18c5eeefd3a283431d312b8c44fef02Jeff Garzik		u8 drv_stat = ata_check_status(ap);
242622374677d18c5eeefd3a283431d312b8c44fef02Jeff Garzik		if ((drv_stat != 0x80) && (drv_stat != 0x7f))
242722374677d18c5eeefd3a283431d312b8c44fef02Jeff Garzik			break;
2428bdd4dddee325a7dce3e84cf48201a06aa8508aa4Jeff Garzik		msleep(500);
242922374677d18c5eeefd3a283431d312b8c44fef02Jeff Garzik		if (retry-- <= 0)
243022374677d18c5eeefd3a283431d312b8c44fef02Jeff Garzik			break;
2431bdd4dddee325a7dce3e84cf48201a06aa8508aa4Jeff Garzik		if (time_after(jiffies, deadline))
2432bdd4dddee325a7dce3e84cf48201a06aa8508aa4Jeff Garzik			break;
243322374677d18c5eeefd3a283431d312b8c44fef02Jeff Garzik	}
243422374677d18c5eeefd3a283431d312b8c44fef02Jeff Garzik
2435bdd4dddee325a7dce3e84cf48201a06aa8508aa4Jeff Garzik	/* FIXME: if we passed the deadline, the following
2436bdd4dddee325a7dce3e84cf48201a06aa8508aa4Jeff Garzik	 * code probably produces an invalid result
2437bdd4dddee325a7dce3e84cf48201a06aa8508aa4Jeff Garzik	 */
243820f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ
2439bdd4dddee325a7dce3e84cf48201a06aa8508aa4Jeff Garzik	/* finally, read device signature from TF registers */
24403f19859ee95a38c066a0420eb8a30c76ecd67a42Tejun Heo	*class = ata_dev_try_classify(ap->link.device, 1, NULL);
2441095fec887eaa1c38d17c0c929a6733c744a9fa1fJeff Garzik
2442095fec887eaa1c38d17c0c929a6733c744a9fa1fJeff Garzik	writelfl(0, port_mmio + EDMA_ERR_IRQ_CAUSE_OFS);
2443095fec887eaa1c38d17c0c929a6733c744a9fa1fJeff Garzik
2444bdd4dddee325a7dce3e84cf48201a06aa8508aa4Jeff Garzik	WARN_ON(pp->pp_flags & MV_PP_FLAG_EDMA_EN);
2445095fec887eaa1c38d17c0c929a6733c744a9fa1fJeff Garzik
2446bca1c4eb9411533d613123618c0d127fae532595Jeff Garzik	VPRINTK("EXIT\n");
244720f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ}
244820f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ
2449cc0680a580b5be81a1ca321b58f8e9b80b5c1052Tejun Heostatic int mv_prereset(struct ata_link *link, unsigned long deadline)
245022374677d18c5eeefd3a283431d312b8c44fef02Jeff Garzik{
2451cc0680a580b5be81a1ca321b58f8e9b80b5c1052Tejun Heo	struct ata_port *ap = link->ap;
2452bdd4dddee325a7dce3e84cf48201a06aa8508aa4Jeff Garzik	struct mv_port_priv *pp	= ap->private_data;
2453cc0680a580b5be81a1ca321b58f8e9b80b5c1052Tejun Heo	struct ata_eh_context *ehc = &link->eh_context;
2454bdd4dddee325a7dce3e84cf48201a06aa8508aa4Jeff Garzik	int rc;
24550ea9e179f436f153fc19fdaef7abbc1e0da20762Jeff Garzik
2456bdd4dddee325a7dce3e84cf48201a06aa8508aa4Jeff Garzik	rc = mv_stop_dma(ap);
2457bdd4dddee325a7dce3e84cf48201a06aa8508aa4Jeff Garzik	if (rc)
2458bdd4dddee325a7dce3e84cf48201a06aa8508aa4Jeff Garzik		ehc->i.action |= ATA_EH_HARDRESET;
2459bdd4dddee325a7dce3e84cf48201a06aa8508aa4Jeff Garzik
2460bdd4dddee325a7dce3e84cf48201a06aa8508aa4Jeff Garzik	if (!(pp->pp_flags & MV_PP_FLAG_HAD_A_RESET)) {
2461bdd4dddee325a7dce3e84cf48201a06aa8508aa4Jeff Garzik		pp->pp_flags |= MV_PP_FLAG_HAD_A_RESET;
2462bdd4dddee325a7dce3e84cf48201a06aa8508aa4Jeff Garzik		ehc->i.action |= ATA_EH_HARDRESET;
2463bdd4dddee325a7dce3e84cf48201a06aa8508aa4Jeff Garzik	}
2464bdd4dddee325a7dce3e84cf48201a06aa8508aa4Jeff Garzik
2465bdd4dddee325a7dce3e84cf48201a06aa8508aa4Jeff Garzik	/* if we're about to do hardreset, nothing more to do */
2466bdd4dddee325a7dce3e84cf48201a06aa8508aa4Jeff Garzik	if (ehc->i.action & ATA_EH_HARDRESET)
2467bdd4dddee325a7dce3e84cf48201a06aa8508aa4Jeff Garzik		return 0;
2468bdd4dddee325a7dce3e84cf48201a06aa8508aa4Jeff Garzik
2469cc0680a580b5be81a1ca321b58f8e9b80b5c1052Tejun Heo	if (ata_link_online(link))
2470bdd4dddee325a7dce3e84cf48201a06aa8508aa4Jeff Garzik		rc = ata_wait_ready(ap, deadline);
2471bdd4dddee325a7dce3e84cf48201a06aa8508aa4Jeff Garzik	else
2472bdd4dddee325a7dce3e84cf48201a06aa8508aa4Jeff Garzik		rc = -ENODEV;
2473bdd4dddee325a7dce3e84cf48201a06aa8508aa4Jeff Garzik
2474bdd4dddee325a7dce3e84cf48201a06aa8508aa4Jeff Garzik	return rc;
247522374677d18c5eeefd3a283431d312b8c44fef02Jeff Garzik}
247622374677d18c5eeefd3a283431d312b8c44fef02Jeff Garzik
2477cc0680a580b5be81a1ca321b58f8e9b80b5c1052Tejun Heostatic int mv_hardreset(struct ata_link *link, unsigned int *class,
2478bdd4dddee325a7dce3e84cf48201a06aa8508aa4Jeff Garzik			unsigned long deadline)
247931961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ{
2480cc0680a580b5be81a1ca321b58f8e9b80b5c1052Tejun Heo	struct ata_port *ap = link->ap;
2481bdd4dddee325a7dce3e84cf48201a06aa8508aa4Jeff Garzik	struct mv_host_priv *hpriv = ap->host->private_data;
2482f351b2d638c3cb0b95adde3549b7bfaf3f991dfaSaeed Bishara	void __iomem *mmio = hpriv->base;
248331961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ
2484bdd4dddee325a7dce3e84cf48201a06aa8508aa4Jeff Garzik	mv_stop_dma(ap);
248531961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ
2486bdd4dddee325a7dce3e84cf48201a06aa8508aa4Jeff Garzik	mv_channel_reset(hpriv, mmio, ap->port_no);
248731961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ
2488bdd4dddee325a7dce3e84cf48201a06aa8508aa4Jeff Garzik	mv_phy_reset(ap, class, deadline);
2489bdd4dddee325a7dce3e84cf48201a06aa8508aa4Jeff Garzik
2490bdd4dddee325a7dce3e84cf48201a06aa8508aa4Jeff Garzik	return 0;
2491bdd4dddee325a7dce3e84cf48201a06aa8508aa4Jeff Garzik}
2492bdd4dddee325a7dce3e84cf48201a06aa8508aa4Jeff Garzik
2493cc0680a580b5be81a1ca321b58f8e9b80b5c1052Tejun Heostatic void mv_postreset(struct ata_link *link, unsigned int *classes)
2494bdd4dddee325a7dce3e84cf48201a06aa8508aa4Jeff Garzik{
2495cc0680a580b5be81a1ca321b58f8e9b80b5c1052Tejun Heo	struct ata_port *ap = link->ap;
2496bdd4dddee325a7dce3e84cf48201a06aa8508aa4Jeff Garzik	u32 serr;
2497bdd4dddee325a7dce3e84cf48201a06aa8508aa4Jeff Garzik
2498bdd4dddee325a7dce3e84cf48201a06aa8508aa4Jeff Garzik	/* print link status */
2499cc0680a580b5be81a1ca321b58f8e9b80b5c1052Tejun Heo	sata_print_link_status(link);
250031961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ
2501bdd4dddee325a7dce3e84cf48201a06aa8508aa4Jeff Garzik	/* clear SError */
2502cc0680a580b5be81a1ca321b58f8e9b80b5c1052Tejun Heo	sata_scr_read(link, SCR_ERROR, &serr);
2503cc0680a580b5be81a1ca321b58f8e9b80b5c1052Tejun Heo	sata_scr_write_flush(link, SCR_ERROR, serr);
2504bdd4dddee325a7dce3e84cf48201a06aa8508aa4Jeff Garzik
2505bdd4dddee325a7dce3e84cf48201a06aa8508aa4Jeff Garzik	/* bail out if no device is present */
2506bdd4dddee325a7dce3e84cf48201a06aa8508aa4Jeff Garzik	if (classes[0] == ATA_DEV_NONE && classes[1] == ATA_DEV_NONE) {
2507bdd4dddee325a7dce3e84cf48201a06aa8508aa4Jeff Garzik		DPRINTK("EXIT, no device\n");
2508bdd4dddee325a7dce3e84cf48201a06aa8508aa4Jeff Garzik		return;
25099b358e305c1d783c8a4ebf00344e95deb9e38f3dMark Lord	}
2510bdd4dddee325a7dce3e84cf48201a06aa8508aa4Jeff Garzik
2511bdd4dddee325a7dce3e84cf48201a06aa8508aa4Jeff Garzik	/* set up device control */
2512bdd4dddee325a7dce3e84cf48201a06aa8508aa4Jeff Garzik	iowrite8(ap->ctl, ap->ioaddr.ctl_addr);
2513bdd4dddee325a7dce3e84cf48201a06aa8508aa4Jeff Garzik}
2514bdd4dddee325a7dce3e84cf48201a06aa8508aa4Jeff Garzik
2515bdd4dddee325a7dce3e84cf48201a06aa8508aa4Jeff Garzikstatic void mv_error_handler(struct ata_port *ap)
2516bdd4dddee325a7dce3e84cf48201a06aa8508aa4Jeff Garzik{
2517bdd4dddee325a7dce3e84cf48201a06aa8508aa4Jeff Garzik	ata_do_eh(ap, mv_prereset, ata_std_softreset,
2518bdd4dddee325a7dce3e84cf48201a06aa8508aa4Jeff Garzik		  mv_hardreset, mv_postreset);
2519bdd4dddee325a7dce3e84cf48201a06aa8508aa4Jeff Garzik}
2520bdd4dddee325a7dce3e84cf48201a06aa8508aa4Jeff Garzik
2521bdd4dddee325a7dce3e84cf48201a06aa8508aa4Jeff Garzikstatic void mv_eh_freeze(struct ata_port *ap)
2522bdd4dddee325a7dce3e84cf48201a06aa8508aa4Jeff Garzik{
2523f351b2d638c3cb0b95adde3549b7bfaf3f991dfaSaeed Bishara	struct mv_host_priv *hpriv = ap->host->private_data;
2524bdd4dddee325a7dce3e84cf48201a06aa8508aa4Jeff Garzik	unsigned int hc = (ap->port_no > 3) ? 1 : 0;
2525bdd4dddee325a7dce3e84cf48201a06aa8508aa4Jeff Garzik	u32 tmp, mask;
2526bdd4dddee325a7dce3e84cf48201a06aa8508aa4Jeff Garzik	unsigned int shift;
2527bdd4dddee325a7dce3e84cf48201a06aa8508aa4Jeff Garzik
2528bdd4dddee325a7dce3e84cf48201a06aa8508aa4Jeff Garzik	/* FIXME: handle coalescing completion events properly */
2529bdd4dddee325a7dce3e84cf48201a06aa8508aa4Jeff Garzik
2530bdd4dddee325a7dce3e84cf48201a06aa8508aa4Jeff Garzik	shift = ap->port_no * 2;
2531bdd4dddee325a7dce3e84cf48201a06aa8508aa4Jeff Garzik	if (hc > 0)
2532bdd4dddee325a7dce3e84cf48201a06aa8508aa4Jeff Garzik		shift++;
2533bdd4dddee325a7dce3e84cf48201a06aa8508aa4Jeff Garzik
2534bdd4dddee325a7dce3e84cf48201a06aa8508aa4Jeff Garzik	mask = 0x3 << shift;
2535bdd4dddee325a7dce3e84cf48201a06aa8508aa4Jeff Garzik
2536bdd4dddee325a7dce3e84cf48201a06aa8508aa4Jeff Garzik	/* disable assertion of portN err, done events */
2537f351b2d638c3cb0b95adde3549b7bfaf3f991dfaSaeed Bishara	tmp = readl(hpriv->main_mask_reg_addr);
2538f351b2d638c3cb0b95adde3549b7bfaf3f991dfaSaeed Bishara	writelfl(tmp & ~mask, hpriv->main_mask_reg_addr);
2539bdd4dddee325a7dce3e84cf48201a06aa8508aa4Jeff Garzik}
2540bdd4dddee325a7dce3e84cf48201a06aa8508aa4Jeff Garzik
2541bdd4dddee325a7dce3e84cf48201a06aa8508aa4Jeff Garzikstatic void mv_eh_thaw(struct ata_port *ap)
2542bdd4dddee325a7dce3e84cf48201a06aa8508aa4Jeff Garzik{
2543f351b2d638c3cb0b95adde3549b7bfaf3f991dfaSaeed Bishara	struct mv_host_priv *hpriv = ap->host->private_data;
2544f351b2d638c3cb0b95adde3549b7bfaf3f991dfaSaeed Bishara	void __iomem *mmio = hpriv->base;
2545bdd4dddee325a7dce3e84cf48201a06aa8508aa4Jeff Garzik	unsigned int hc = (ap->port_no > 3) ? 1 : 0;
2546bdd4dddee325a7dce3e84cf48201a06aa8508aa4Jeff Garzik	void __iomem *hc_mmio = mv_hc_base(mmio, hc);
2547bdd4dddee325a7dce3e84cf48201a06aa8508aa4Jeff Garzik	void __iomem *port_mmio = mv_ap_base(ap);
2548bdd4dddee325a7dce3e84cf48201a06aa8508aa4Jeff Garzik	u32 tmp, mask, hc_irq_cause;
2549bdd4dddee325a7dce3e84cf48201a06aa8508aa4Jeff Garzik	unsigned int shift, hc_port_no = ap->port_no;
2550bdd4dddee325a7dce3e84cf48201a06aa8508aa4Jeff Garzik
2551bdd4dddee325a7dce3e84cf48201a06aa8508aa4Jeff Garzik	/* FIXME: handle coalescing completion events properly */
2552bdd4dddee325a7dce3e84cf48201a06aa8508aa4Jeff Garzik
2553bdd4dddee325a7dce3e84cf48201a06aa8508aa4Jeff Garzik	shift = ap->port_no * 2;
2554bdd4dddee325a7dce3e84cf48201a06aa8508aa4Jeff Garzik	if (hc > 0) {
2555bdd4dddee325a7dce3e84cf48201a06aa8508aa4Jeff Garzik		shift++;
2556bdd4dddee325a7dce3e84cf48201a06aa8508aa4Jeff Garzik		hc_port_no -= 4;
2557bdd4dddee325a7dce3e84cf48201a06aa8508aa4Jeff Garzik	}
2558bdd4dddee325a7dce3e84cf48201a06aa8508aa4Jeff Garzik
2559bdd4dddee325a7dce3e84cf48201a06aa8508aa4Jeff Garzik	mask = 0x3 << shift;
2560bdd4dddee325a7dce3e84cf48201a06aa8508aa4Jeff Garzik
2561bdd4dddee325a7dce3e84cf48201a06aa8508aa4Jeff Garzik	/* clear EDMA errors on this port */
2562bdd4dddee325a7dce3e84cf48201a06aa8508aa4Jeff Garzik	writel(0, port_mmio + EDMA_ERR_IRQ_CAUSE_OFS);
2563bdd4dddee325a7dce3e84cf48201a06aa8508aa4Jeff Garzik
2564bdd4dddee325a7dce3e84cf48201a06aa8508aa4Jeff Garzik	/* clear pending irq events */
2565bdd4dddee325a7dce3e84cf48201a06aa8508aa4Jeff Garzik	hc_irq_cause = readl(hc_mmio + HC_IRQ_CAUSE_OFS);
2566bdd4dddee325a7dce3e84cf48201a06aa8508aa4Jeff Garzik	hc_irq_cause &= ~(1 << hc_port_no);	/* clear CRPB-done */
2567bdd4dddee325a7dce3e84cf48201a06aa8508aa4Jeff Garzik	hc_irq_cause &= ~(1 << (hc_port_no + 8)); /* clear Device int */
2568bdd4dddee325a7dce3e84cf48201a06aa8508aa4Jeff Garzik	writel(hc_irq_cause, hc_mmio + HC_IRQ_CAUSE_OFS);
2569bdd4dddee325a7dce3e84cf48201a06aa8508aa4Jeff Garzik
2570bdd4dddee325a7dce3e84cf48201a06aa8508aa4Jeff Garzik	/* enable assertion of portN err, done events */
2571f351b2d638c3cb0b95adde3549b7bfaf3f991dfaSaeed Bishara	tmp = readl(hpriv->main_mask_reg_addr);
2572f351b2d638c3cb0b95adde3549b7bfaf3f991dfaSaeed Bishara	writelfl(tmp | mask, hpriv->main_mask_reg_addr);
257331961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ}
257431961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ
257505b308e1df6d9d673daedb517969241f41278b52Brett Russ/**
257605b308e1df6d9d673daedb517969241f41278b52Brett Russ *      mv_port_init - Perform some early initialization on a single port.
257705b308e1df6d9d673daedb517969241f41278b52Brett Russ *      @port: libata data structure storing shadow register addresses
257805b308e1df6d9d673daedb517969241f41278b52Brett Russ *      @port_mmio: base address of the port
257905b308e1df6d9d673daedb517969241f41278b52Brett Russ *
258005b308e1df6d9d673daedb517969241f41278b52Brett Russ *      Initialize shadow register mmio addresses, clear outstanding
258105b308e1df6d9d673daedb517969241f41278b52Brett Russ *      interrupts on the port, and unmask interrupts for the future
258205b308e1df6d9d673daedb517969241f41278b52Brett Russ *      start of the port.
258305b308e1df6d9d673daedb517969241f41278b52Brett Russ *
258405b308e1df6d9d673daedb517969241f41278b52Brett Russ *      LOCKING:
258505b308e1df6d9d673daedb517969241f41278b52Brett Russ *      Inherited from caller.
258605b308e1df6d9d673daedb517969241f41278b52Brett Russ */
258731961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russstatic void mv_port_init(struct ata_ioports *port,  void __iomem *port_mmio)
258820f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ{
25890d5ff566779f894ca9937231a181eb31e4adff0eTejun Heo	void __iomem *shd_base = port_mmio + SHD_BLK_OFS;
259031961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ	unsigned serr_ofs;
259131961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ
25928b260248d9e0e8b64bb72fd4dee03ad86984c344Jeff Garzik	/* PIO related setup
259331961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ	 */
259431961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ	port->data_addr = shd_base + (sizeof(u32) * ATA_REG_DATA);
25958b260248d9e0e8b64bb72fd4dee03ad86984c344Jeff Garzik	port->error_addr =
259631961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ		port->feature_addr = shd_base + (sizeof(u32) * ATA_REG_ERR);
259731961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ	port->nsect_addr = shd_base + (sizeof(u32) * ATA_REG_NSECT);
259831961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ	port->lbal_addr = shd_base + (sizeof(u32) * ATA_REG_LBAL);
259931961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ	port->lbam_addr = shd_base + (sizeof(u32) * ATA_REG_LBAM);
260031961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ	port->lbah_addr = shd_base + (sizeof(u32) * ATA_REG_LBAH);
260131961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ	port->device_addr = shd_base + (sizeof(u32) * ATA_REG_DEVICE);
26028b260248d9e0e8b64bb72fd4dee03ad86984c344Jeff Garzik	port->status_addr =
260331961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ		port->command_addr = shd_base + (sizeof(u32) * ATA_REG_STATUS);
260431961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ	/* special case: control/altstatus doesn't have ATA_REG_ address */
260531961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ	port->altstatus_addr = port->ctl_addr = shd_base + SHD_CTL_AST_OFS;
260631961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ
260731961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ	/* unused: */
26088d9db2d2fbae9e05022825c32f86e00c8e342860Randy Dunlap	port->cmd_addr = port->bmdma_addr = port->scr_addr = NULL;
260920f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ
261031961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ	/* Clear any currently outstanding port interrupt conditions */
261131961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ	serr_ofs = mv_scr_offset(SCR_ERROR);
261231961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ	writelfl(readl(port_mmio + serr_ofs), port_mmio + serr_ofs);
261331961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ	writelfl(0, port_mmio + EDMA_ERR_IRQ_CAUSE_OFS);
261431961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ
2615646a4da514f2555298481cb00dc5b3eb02b21b72Mark Lord	/* unmask all non-transient EDMA error interrupts */
2616646a4da514f2555298481cb00dc5b3eb02b21b72Mark Lord	writelfl(~EDMA_ERR_IRQ_TRANSIENT, port_mmio + EDMA_ERR_IRQ_MASK_OFS);
261720f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ
26188b260248d9e0e8b64bb72fd4dee03ad86984c344Jeff Garzik	VPRINTK("EDMA cfg=0x%08x EDMA IRQ err cause/mask=0x%08x/0x%08x\n",
261931961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ		readl(port_mmio + EDMA_CFG_OFS),
262031961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ		readl(port_mmio + EDMA_ERR_IRQ_CAUSE_OFS),
262131961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ		readl(port_mmio + EDMA_ERR_IRQ_MASK_OFS));
262220f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ}
262320f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ
26244447d35156169cf136e829eb6b5cac2d6370f2d9Tejun Heostatic int mv_chip_id(struct ata_host *host, unsigned int board_idx)
2625bca1c4eb9411533d613123618c0d127fae532595Jeff Garzik{
26264447d35156169cf136e829eb6b5cac2d6370f2d9Tejun Heo	struct pci_dev *pdev = to_pci_dev(host->dev);
26274447d35156169cf136e829eb6b5cac2d6370f2d9Tejun Heo	struct mv_host_priv *hpriv = host->private_data;
2628bca1c4eb9411533d613123618c0d127fae532595Jeff Garzik	u32 hp_flags = hpriv->hp_flags;
2629bca1c4eb9411533d613123618c0d127fae532595Jeff Garzik
26305796d1c4c89efff823259fda35b08ea66ebf8b23Jeff Garzik	switch (board_idx) {
263147c2b677daeed9c79ecb7167c211ff36876ea611Jeff Garzik	case chip_5080:
263247c2b677daeed9c79ecb7167c211ff36876ea611Jeff Garzik		hpriv->ops = &mv5xxx_ops;
2633ee9ccdf70163ca6408f6965e0fbc65baeac7312cJeff Garzik		hp_flags |= MV_HP_GEN_I;
263447c2b677daeed9c79ecb7167c211ff36876ea611Jeff Garzik
263544c10138fd4bbc4b6d6bff0873c24902f2a9da65Auke Kok		switch (pdev->revision) {
263647c2b677daeed9c79ecb7167c211ff36876ea611Jeff Garzik		case 0x1:
263747c2b677daeed9c79ecb7167c211ff36876ea611Jeff Garzik			hp_flags |= MV_HP_ERRATA_50XXB0;
263847c2b677daeed9c79ecb7167c211ff36876ea611Jeff Garzik			break;
263947c2b677daeed9c79ecb7167c211ff36876ea611Jeff Garzik		case 0x3:
264047c2b677daeed9c79ecb7167c211ff36876ea611Jeff Garzik			hp_flags |= MV_HP_ERRATA_50XXB2;
264147c2b677daeed9c79ecb7167c211ff36876ea611Jeff Garzik			break;
264247c2b677daeed9c79ecb7167c211ff36876ea611Jeff Garzik		default:
264347c2b677daeed9c79ecb7167c211ff36876ea611Jeff Garzik			dev_printk(KERN_WARNING, &pdev->dev,
264447c2b677daeed9c79ecb7167c211ff36876ea611Jeff Garzik			   "Applying 50XXB2 workarounds to unknown rev\n");
264547c2b677daeed9c79ecb7167c211ff36876ea611Jeff Garzik			hp_flags |= MV_HP_ERRATA_50XXB2;
264647c2b677daeed9c79ecb7167c211ff36876ea611Jeff Garzik			break;
264747c2b677daeed9c79ecb7167c211ff36876ea611Jeff Garzik		}
264847c2b677daeed9c79ecb7167c211ff36876ea611Jeff Garzik		break;
264947c2b677daeed9c79ecb7167c211ff36876ea611Jeff Garzik
2650bca1c4eb9411533d613123618c0d127fae532595Jeff Garzik	case chip_504x:
2651bca1c4eb9411533d613123618c0d127fae532595Jeff Garzik	case chip_508x:
265247c2b677daeed9c79ecb7167c211ff36876ea611Jeff Garzik		hpriv->ops = &mv5xxx_ops;
2653ee9ccdf70163ca6408f6965e0fbc65baeac7312cJeff Garzik		hp_flags |= MV_HP_GEN_I;
2654bca1c4eb9411533d613123618c0d127fae532595Jeff Garzik
265544c10138fd4bbc4b6d6bff0873c24902f2a9da65Auke Kok		switch (pdev->revision) {
265647c2b677daeed9c79ecb7167c211ff36876ea611Jeff Garzik		case 0x0:
265747c2b677daeed9c79ecb7167c211ff36876ea611Jeff Garzik			hp_flags |= MV_HP_ERRATA_50XXB0;
265847c2b677daeed9c79ecb7167c211ff36876ea611Jeff Garzik			break;
265947c2b677daeed9c79ecb7167c211ff36876ea611Jeff Garzik		case 0x3:
266047c2b677daeed9c79ecb7167c211ff36876ea611Jeff Garzik			hp_flags |= MV_HP_ERRATA_50XXB2;
266147c2b677daeed9c79ecb7167c211ff36876ea611Jeff Garzik			break;
266247c2b677daeed9c79ecb7167c211ff36876ea611Jeff Garzik		default:
266347c2b677daeed9c79ecb7167c211ff36876ea611Jeff Garzik			dev_printk(KERN_WARNING, &pdev->dev,
266447c2b677daeed9c79ecb7167c211ff36876ea611Jeff Garzik			   "Applying B2 workarounds to unknown rev\n");
266547c2b677daeed9c79ecb7167c211ff36876ea611Jeff Garzik			hp_flags |= MV_HP_ERRATA_50XXB2;
266647c2b677daeed9c79ecb7167c211ff36876ea611Jeff Garzik			break;
2667bca1c4eb9411533d613123618c0d127fae532595Jeff Garzik		}
2668bca1c4eb9411533d613123618c0d127fae532595Jeff Garzik		break;
2669bca1c4eb9411533d613123618c0d127fae532595Jeff Garzik
2670bca1c4eb9411533d613123618c0d127fae532595Jeff Garzik	case chip_604x:
2671bca1c4eb9411533d613123618c0d127fae532595Jeff Garzik	case chip_608x:
267247c2b677daeed9c79ecb7167c211ff36876ea611Jeff Garzik		hpriv->ops = &mv6xxx_ops;
2673ee9ccdf70163ca6408f6965e0fbc65baeac7312cJeff Garzik		hp_flags |= MV_HP_GEN_II;
267447c2b677daeed9c79ecb7167c211ff36876ea611Jeff Garzik
267544c10138fd4bbc4b6d6bff0873c24902f2a9da65Auke Kok		switch (pdev->revision) {
267647c2b677daeed9c79ecb7167c211ff36876ea611Jeff Garzik		case 0x7:
267747c2b677daeed9c79ecb7167c211ff36876ea611Jeff Garzik			hp_flags |= MV_HP_ERRATA_60X1B2;
267847c2b677daeed9c79ecb7167c211ff36876ea611Jeff Garzik			break;
267947c2b677daeed9c79ecb7167c211ff36876ea611Jeff Garzik		case 0x9:
268047c2b677daeed9c79ecb7167c211ff36876ea611Jeff Garzik			hp_flags |= MV_HP_ERRATA_60X1C0;
2681bca1c4eb9411533d613123618c0d127fae532595Jeff Garzik			break;
2682bca1c4eb9411533d613123618c0d127fae532595Jeff Garzik		default:
2683bca1c4eb9411533d613123618c0d127fae532595Jeff Garzik			dev_printk(KERN_WARNING, &pdev->dev,
268447c2b677daeed9c79ecb7167c211ff36876ea611Jeff Garzik				   "Applying B2 workarounds to unknown rev\n");
268547c2b677daeed9c79ecb7167c211ff36876ea611Jeff Garzik			hp_flags |= MV_HP_ERRATA_60X1B2;
2686bca1c4eb9411533d613123618c0d127fae532595Jeff Garzik			break;
2687bca1c4eb9411533d613123618c0d127fae532595Jeff Garzik		}
2688bca1c4eb9411533d613123618c0d127fae532595Jeff Garzik		break;
2689bca1c4eb9411533d613123618c0d127fae532595Jeff Garzik
2690e4e7b89280d1d666e2c09e5ad36cf071796c4c7eJeff Garzik	case chip_7042:
269102a121da5a53d415b6596bc19cc6999d295d32a4Mark Lord		hp_flags |= MV_HP_PCIE;
2692306b30f74d37f289033c696285e07ce0158a5d7bMark Lord		if (pdev->vendor == PCI_VENDOR_ID_TTI &&
2693306b30f74d37f289033c696285e07ce0158a5d7bMark Lord		    (pdev->device == 0x2300 || pdev->device == 0x2310))
2694306b30f74d37f289033c696285e07ce0158a5d7bMark Lord		{
26954e5200334e03e5620aa19d538300c13db270a063Mark Lord			/*
26964e5200334e03e5620aa19d538300c13db270a063Mark Lord			 * Highpoint RocketRAID PCIe 23xx series cards:
26974e5200334e03e5620aa19d538300c13db270a063Mark Lord			 *
26984e5200334e03e5620aa19d538300c13db270a063Mark Lord			 * Unconfigured drives are treated as "Legacy"
26994e5200334e03e5620aa19d538300c13db270a063Mark Lord			 * by the BIOS, and it overwrites sector 8 with
27004e5200334e03e5620aa19d538300c13db270a063Mark Lord			 * a "Lgcy" metadata block prior to Linux boot.
27014e5200334e03e5620aa19d538300c13db270a063Mark Lord			 *
27024e5200334e03e5620aa19d538300c13db270a063Mark Lord			 * Configured drives (RAID or JBOD) leave sector 8
27034e5200334e03e5620aa19d538300c13db270a063Mark Lord			 * alone, but instead overwrite a high numbered
27044e5200334e03e5620aa19d538300c13db270a063Mark Lord			 * sector for the RAID metadata.  This sector can
27054e5200334e03e5620aa19d538300c13db270a063Mark Lord			 * be determined exactly, by truncating the physical
27064e5200334e03e5620aa19d538300c13db270a063Mark Lord			 * drive capacity to a nice even GB value.
27074e5200334e03e5620aa19d538300c13db270a063Mark Lord			 *
27084e5200334e03e5620aa19d538300c13db270a063Mark Lord			 * RAID metadata is at: (dev->n_sectors & ~0xfffff)
27094e5200334e03e5620aa19d538300c13db270a063Mark Lord			 *
27104e5200334e03e5620aa19d538300c13db270a063Mark Lord			 * Warn the user, lest they think we're just buggy.
27114e5200334e03e5620aa19d538300c13db270a063Mark Lord			 */
27124e5200334e03e5620aa19d538300c13db270a063Mark Lord			printk(KERN_WARNING DRV_NAME ": Highpoint RocketRAID"
27134e5200334e03e5620aa19d538300c13db270a063Mark Lord				" BIOS CORRUPTS DATA on all attached drives,"
27144e5200334e03e5620aa19d538300c13db270a063Mark Lord				" regardless of if/how they are configured."
27154e5200334e03e5620aa19d538300c13db270a063Mark Lord				" BEWARE!\n");
27164e5200334e03e5620aa19d538300c13db270a063Mark Lord			printk(KERN_WARNING DRV_NAME ": For data safety, do not"
27174e5200334e03e5620aa19d538300c13db270a063Mark Lord				" use sectors 8-9 on \"Legacy\" drives,"
27184e5200334e03e5620aa19d538300c13db270a063Mark Lord				" and avoid the final two gigabytes on"
27194e5200334e03e5620aa19d538300c13db270a063Mark Lord				" all RocketRAID BIOS initialized drives.\n");
2720306b30f74d37f289033c696285e07ce0158a5d7bMark Lord		}
2721e4e7b89280d1d666e2c09e5ad36cf071796c4c7eJeff Garzik	case chip_6042:
2722e4e7b89280d1d666e2c09e5ad36cf071796c4c7eJeff Garzik		hpriv->ops = &mv6xxx_ops;
2723e4e7b89280d1d666e2c09e5ad36cf071796c4c7eJeff Garzik		hp_flags |= MV_HP_GEN_IIE;
2724e4e7b89280d1d666e2c09e5ad36cf071796c4c7eJeff Garzik
272544c10138fd4bbc4b6d6bff0873c24902f2a9da65Auke Kok		switch (pdev->revision) {
2726e4e7b89280d1d666e2c09e5ad36cf071796c4c7eJeff Garzik		case 0x0:
2727e4e7b89280d1d666e2c09e5ad36cf071796c4c7eJeff Garzik			hp_flags |= MV_HP_ERRATA_XX42A0;
2728e4e7b89280d1d666e2c09e5ad36cf071796c4c7eJeff Garzik			break;
2729e4e7b89280d1d666e2c09e5ad36cf071796c4c7eJeff Garzik		case 0x1:
2730e4e7b89280d1d666e2c09e5ad36cf071796c4c7eJeff Garzik			hp_flags |= MV_HP_ERRATA_60X1C0;
2731e4e7b89280d1d666e2c09e5ad36cf071796c4c7eJeff Garzik			break;
2732e4e7b89280d1d666e2c09e5ad36cf071796c4c7eJeff Garzik		default:
2733e4e7b89280d1d666e2c09e5ad36cf071796c4c7eJeff Garzik			dev_printk(KERN_WARNING, &pdev->dev,
2734e4e7b89280d1d666e2c09e5ad36cf071796c4c7eJeff Garzik			   "Applying 60X1C0 workarounds to unknown rev\n");
2735e4e7b89280d1d666e2c09e5ad36cf071796c4c7eJeff Garzik			hp_flags |= MV_HP_ERRATA_60X1C0;
2736e4e7b89280d1d666e2c09e5ad36cf071796c4c7eJeff Garzik			break;
2737e4e7b89280d1d666e2c09e5ad36cf071796c4c7eJeff Garzik		}
2738e4e7b89280d1d666e2c09e5ad36cf071796c4c7eJeff Garzik		break;
2739f351b2d638c3cb0b95adde3549b7bfaf3f991dfaSaeed Bishara	case chip_soc:
2740f351b2d638c3cb0b95adde3549b7bfaf3f991dfaSaeed Bishara		hpriv->ops = &mv_soc_ops;
2741f351b2d638c3cb0b95adde3549b7bfaf3f991dfaSaeed Bishara		hp_flags |= MV_HP_ERRATA_60X1C0;
2742f351b2d638c3cb0b95adde3549b7bfaf3f991dfaSaeed Bishara		break;
2743e4e7b89280d1d666e2c09e5ad36cf071796c4c7eJeff Garzik
2744bca1c4eb9411533d613123618c0d127fae532595Jeff Garzik	default:
2745f351b2d638c3cb0b95adde3549b7bfaf3f991dfaSaeed Bishara		dev_printk(KERN_ERR, host->dev,
27465796d1c4c89efff823259fda35b08ea66ebf8b23Jeff Garzik			   "BUG: invalid board index %u\n", board_idx);
2747bca1c4eb9411533d613123618c0d127fae532595Jeff Garzik		return 1;
2748bca1c4eb9411533d613123618c0d127fae532595Jeff Garzik	}
2749bca1c4eb9411533d613123618c0d127fae532595Jeff Garzik
2750bca1c4eb9411533d613123618c0d127fae532595Jeff Garzik	hpriv->hp_flags = hp_flags;
275102a121da5a53d415b6596bc19cc6999d295d32a4Mark Lord	if (hp_flags & MV_HP_PCIE) {
275202a121da5a53d415b6596bc19cc6999d295d32a4Mark Lord		hpriv->irq_cause_ofs	= PCIE_IRQ_CAUSE_OFS;
275302a121da5a53d415b6596bc19cc6999d295d32a4Mark Lord		hpriv->irq_mask_ofs	= PCIE_IRQ_MASK_OFS;
275402a121da5a53d415b6596bc19cc6999d295d32a4Mark Lord		hpriv->unmask_all_irqs	= PCIE_UNMASK_ALL_IRQS;
275502a121da5a53d415b6596bc19cc6999d295d32a4Mark Lord	} else {
275602a121da5a53d415b6596bc19cc6999d295d32a4Mark Lord		hpriv->irq_cause_ofs	= PCI_IRQ_CAUSE_OFS;
275702a121da5a53d415b6596bc19cc6999d295d32a4Mark Lord		hpriv->irq_mask_ofs	= PCI_IRQ_MASK_OFS;
275802a121da5a53d415b6596bc19cc6999d295d32a4Mark Lord		hpriv->unmask_all_irqs	= PCI_UNMASK_ALL_IRQS;
275902a121da5a53d415b6596bc19cc6999d295d32a4Mark Lord	}
2760bca1c4eb9411533d613123618c0d127fae532595Jeff Garzik
2761bca1c4eb9411533d613123618c0d127fae532595Jeff Garzik	return 0;
2762bca1c4eb9411533d613123618c0d127fae532595Jeff Garzik}
2763bca1c4eb9411533d613123618c0d127fae532595Jeff Garzik
276405b308e1df6d9d673daedb517969241f41278b52Brett Russ/**
276547c2b677daeed9c79ecb7167c211ff36876ea611Jeff Garzik *      mv_init_host - Perform some early initialization of the host.
27664447d35156169cf136e829eb6b5cac2d6370f2d9Tejun Heo *	@host: ATA host to initialize
27674447d35156169cf136e829eb6b5cac2d6370f2d9Tejun Heo *      @board_idx: controller index
276805b308e1df6d9d673daedb517969241f41278b52Brett Russ *
276905b308e1df6d9d673daedb517969241f41278b52Brett Russ *      If possible, do an early global reset of the host.  Then do
277005b308e1df6d9d673daedb517969241f41278b52Brett Russ *      our port init and clear/unmask all/relevant host interrupts.
277105b308e1df6d9d673daedb517969241f41278b52Brett Russ *
277205b308e1df6d9d673daedb517969241f41278b52Brett Russ *      LOCKING:
277305b308e1df6d9d673daedb517969241f41278b52Brett Russ *      Inherited from caller.
277405b308e1df6d9d673daedb517969241f41278b52Brett Russ */
27754447d35156169cf136e829eb6b5cac2d6370f2d9Tejun Heostatic int mv_init_host(struct ata_host *host, unsigned int board_idx)
277620f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ{
277720f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ	int rc = 0, n_hc, port, hc;
27784447d35156169cf136e829eb6b5cac2d6370f2d9Tejun Heo	struct mv_host_priv *hpriv = host->private_data;
2779f351b2d638c3cb0b95adde3549b7bfaf3f991dfaSaeed Bishara	void __iomem *mmio = hpriv->base;
278047c2b677daeed9c79ecb7167c211ff36876ea611Jeff Garzik
27814447d35156169cf136e829eb6b5cac2d6370f2d9Tejun Heo	rc = mv_chip_id(host, board_idx);
2782bca1c4eb9411533d613123618c0d127fae532595Jeff Garzik	if (rc)
2783f351b2d638c3cb0b95adde3549b7bfaf3f991dfaSaeed Bishara	goto done;
2784f351b2d638c3cb0b95adde3549b7bfaf3f991dfaSaeed Bishara
2785f351b2d638c3cb0b95adde3549b7bfaf3f991dfaSaeed Bishara	if (HAS_PCI(host)) {
2786f351b2d638c3cb0b95adde3549b7bfaf3f991dfaSaeed Bishara		hpriv->main_cause_reg_addr = hpriv->base +
2787f351b2d638c3cb0b95adde3549b7bfaf3f991dfaSaeed Bishara		  HC_MAIN_IRQ_CAUSE_OFS;
2788f351b2d638c3cb0b95adde3549b7bfaf3f991dfaSaeed Bishara		hpriv->main_mask_reg_addr = hpriv->base + HC_MAIN_IRQ_MASK_OFS;
2789f351b2d638c3cb0b95adde3549b7bfaf3f991dfaSaeed Bishara	} else {
2790f351b2d638c3cb0b95adde3549b7bfaf3f991dfaSaeed Bishara		hpriv->main_cause_reg_addr = hpriv->base +
2791f351b2d638c3cb0b95adde3549b7bfaf3f991dfaSaeed Bishara		  HC_SOC_MAIN_IRQ_CAUSE_OFS;
2792f351b2d638c3cb0b95adde3549b7bfaf3f991dfaSaeed Bishara		hpriv->main_mask_reg_addr = hpriv->base +
2793f351b2d638c3cb0b95adde3549b7bfaf3f991dfaSaeed Bishara		  HC_SOC_MAIN_IRQ_MASK_OFS;
2794f351b2d638c3cb0b95adde3549b7bfaf3f991dfaSaeed Bishara	}
2795f351b2d638c3cb0b95adde3549b7bfaf3f991dfaSaeed Bishara	/* global interrupt mask */
2796f351b2d638c3cb0b95adde3549b7bfaf3f991dfaSaeed Bishara	writel(0, hpriv->main_mask_reg_addr);
2797bca1c4eb9411533d613123618c0d127fae532595Jeff Garzik
27984447d35156169cf136e829eb6b5cac2d6370f2d9Tejun Heo	n_hc = mv_get_hc_count(host->ports[0]->flags);
2799bca1c4eb9411533d613123618c0d127fae532595Jeff Garzik
28004447d35156169cf136e829eb6b5cac2d6370f2d9Tejun Heo	for (port = 0; port < host->n_ports; port++)
280147c2b677daeed9c79ecb7167c211ff36876ea611Jeff Garzik		hpriv->ops->read_preamp(hpriv, port, mmio);
280220f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ
2803c9d39130123238ac18478a42e25cb7996eacfcc0Jeff Garzik	rc = hpriv->ops->reset_hc(hpriv, mmio, n_hc);
280447c2b677daeed9c79ecb7167c211ff36876ea611Jeff Garzik	if (rc)
280520f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ		goto done;
280620f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ
2807522479fb98c6667f081e75f87e298e413c0b1db8Jeff Garzik	hpriv->ops->reset_flash(hpriv, mmio);
28087bb3c5290ca0ec9e65947c907495c2b56e895e46Saeed Bishara	hpriv->ops->reset_bus(host, mmio);
280947c2b677daeed9c79ecb7167c211ff36876ea611Jeff Garzik	hpriv->ops->enable_leds(hpriv, mmio);
281020f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ
28114447d35156169cf136e829eb6b5cac2d6370f2d9Tejun Heo	for (port = 0; port < host->n_ports; port++) {
2812ee9ccdf70163ca6408f6965e0fbc65baeac7312cJeff Garzik		if (IS_GEN_II(hpriv)) {
2813c9d39130123238ac18478a42e25cb7996eacfcc0Jeff Garzik			void __iomem *port_mmio = mv_port_base(mmio, port);
2814c9d39130123238ac18478a42e25cb7996eacfcc0Jeff Garzik
28152a47ce06d534692f9bd2bf4e90a20fc9b1054c39Jeff Garzik			u32 ifctl = readl(port_mmio + SATA_INTERFACE_CTL);
2816eb46d684600ac145501805a294c94675e82eab2eMark Lord			ifctl |= (1 << 7);		/* enable gen2i speed */
2817eb46d684600ac145501805a294c94675e82eab2eMark Lord			ifctl = (ifctl & 0xfff) | 0x9b1000; /* from chip spec */
28182a47ce06d534692f9bd2bf4e90a20fc9b1054c39Jeff Garzik			writelfl(ifctl, port_mmio + SATA_INTERFACE_CTL);
28192a47ce06d534692f9bd2bf4e90a20fc9b1054c39Jeff Garzik		}
28202a47ce06d534692f9bd2bf4e90a20fc9b1054c39Jeff Garzik
2821c9d39130123238ac18478a42e25cb7996eacfcc0Jeff Garzik		hpriv->ops->phy_errata(hpriv, mmio, port);
28222a47ce06d534692f9bd2bf4e90a20fc9b1054c39Jeff Garzik	}
28232a47ce06d534692f9bd2bf4e90a20fc9b1054c39Jeff Garzik
28244447d35156169cf136e829eb6b5cac2d6370f2d9Tejun Heo	for (port = 0; port < host->n_ports; port++) {
2825cbcdd87593a1d85c5c4b259945a3a09eee12814dTejun Heo		struct ata_port *ap = host->ports[port];
28262a47ce06d534692f9bd2bf4e90a20fc9b1054c39Jeff Garzik		void __iomem *port_mmio = mv_port_base(mmio, port);
2827cbcdd87593a1d85c5c4b259945a3a09eee12814dTejun Heo
2828cbcdd87593a1d85c5c4b259945a3a09eee12814dTejun Heo		mv_port_init(&ap->ioaddr, port_mmio);
2829cbcdd87593a1d85c5c4b259945a3a09eee12814dTejun Heo
28307bb3c5290ca0ec9e65947c907495c2b56e895e46Saeed Bishara#ifdef CONFIG_PCI
2831f351b2d638c3cb0b95adde3549b7bfaf3f991dfaSaeed Bishara		if (HAS_PCI(host)) {
2832f351b2d638c3cb0b95adde3549b7bfaf3f991dfaSaeed Bishara			unsigned int offset = port_mmio - mmio;
2833f351b2d638c3cb0b95adde3549b7bfaf3f991dfaSaeed Bishara			ata_port_pbar_desc(ap, MV_PRIMARY_BAR, -1, "mmio");
2834f351b2d638c3cb0b95adde3549b7bfaf3f991dfaSaeed Bishara			ata_port_pbar_desc(ap, MV_PRIMARY_BAR, offset, "port");
2835f351b2d638c3cb0b95adde3549b7bfaf3f991dfaSaeed Bishara		}
28367bb3c5290ca0ec9e65947c907495c2b56e895e46Saeed Bishara#endif
283720f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ	}
283820f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ
283920f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ	for (hc = 0; hc < n_hc; hc++) {
284031961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ		void __iomem *hc_mmio = mv_hc_base(mmio, hc);
284131961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ
284231961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ		VPRINTK("HC%i: HC config=0x%08x HC IRQ cause "
284331961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ			"(before clear)=0x%08x\n", hc,
284431961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ			readl(hc_mmio + HC_CFG_OFS),
284531961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ			readl(hc_mmio + HC_IRQ_CAUSE_OFS));
284631961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ
284731961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ		/* Clear any currently outstanding hc interrupt conditions */
284831961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ		writelfl(0, hc_mmio + HC_IRQ_CAUSE_OFS);
284920f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ	}
285020f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ
2851f351b2d638c3cb0b95adde3549b7bfaf3f991dfaSaeed Bishara	if (HAS_PCI(host)) {
2852f351b2d638c3cb0b95adde3549b7bfaf3f991dfaSaeed Bishara		/* Clear any currently outstanding host interrupt conditions */
2853f351b2d638c3cb0b95adde3549b7bfaf3f991dfaSaeed Bishara		writelfl(0, mmio + hpriv->irq_cause_ofs);
285431961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ
2855f351b2d638c3cb0b95adde3549b7bfaf3f991dfaSaeed Bishara		/* and unmask interrupt generation for host regs */
2856f351b2d638c3cb0b95adde3549b7bfaf3f991dfaSaeed Bishara		writelfl(hpriv->unmask_all_irqs, mmio + hpriv->irq_mask_ofs);
2857f351b2d638c3cb0b95adde3549b7bfaf3f991dfaSaeed Bishara		if (IS_GEN_I(hpriv))
2858f351b2d638c3cb0b95adde3549b7bfaf3f991dfaSaeed Bishara			writelfl(~HC_MAIN_MASKED_IRQS_5,
2859f351b2d638c3cb0b95adde3549b7bfaf3f991dfaSaeed Bishara				 hpriv->main_mask_reg_addr);
2860f351b2d638c3cb0b95adde3549b7bfaf3f991dfaSaeed Bishara		else
2861f351b2d638c3cb0b95adde3549b7bfaf3f991dfaSaeed Bishara			writelfl(~HC_MAIN_MASKED_IRQS,
2862f351b2d638c3cb0b95adde3549b7bfaf3f991dfaSaeed Bishara				 hpriv->main_mask_reg_addr);
2863f351b2d638c3cb0b95adde3549b7bfaf3f991dfaSaeed Bishara
2864f351b2d638c3cb0b95adde3549b7bfaf3f991dfaSaeed Bishara		VPRINTK("HC MAIN IRQ cause/mask=0x%08x/0x%08x "
2865f351b2d638c3cb0b95adde3549b7bfaf3f991dfaSaeed Bishara			"PCI int cause/mask=0x%08x/0x%08x\n",
2866f351b2d638c3cb0b95adde3549b7bfaf3f991dfaSaeed Bishara			readl(hpriv->main_cause_reg_addr),
2867f351b2d638c3cb0b95adde3549b7bfaf3f991dfaSaeed Bishara			readl(hpriv->main_mask_reg_addr),
2868f351b2d638c3cb0b95adde3549b7bfaf3f991dfaSaeed Bishara			readl(mmio + hpriv->irq_cause_ofs),
2869f351b2d638c3cb0b95adde3549b7bfaf3f991dfaSaeed Bishara			readl(mmio + hpriv->irq_mask_ofs));
2870f351b2d638c3cb0b95adde3549b7bfaf3f991dfaSaeed Bishara	} else {
2871f351b2d638c3cb0b95adde3549b7bfaf3f991dfaSaeed Bishara		writelfl(~HC_MAIN_MASKED_IRQS_SOC,
2872f351b2d638c3cb0b95adde3549b7bfaf3f991dfaSaeed Bishara			 hpriv->main_mask_reg_addr);
2873f351b2d638c3cb0b95adde3549b7bfaf3f991dfaSaeed Bishara		VPRINTK("HC MAIN IRQ cause/mask=0x%08x/0x%08x\n",
2874f351b2d638c3cb0b95adde3549b7bfaf3f991dfaSaeed Bishara			readl(hpriv->main_cause_reg_addr),
2875f351b2d638c3cb0b95adde3549b7bfaf3f991dfaSaeed Bishara			readl(hpriv->main_mask_reg_addr));
2876f351b2d638c3cb0b95adde3549b7bfaf3f991dfaSaeed Bishara	}
2877f351b2d638c3cb0b95adde3549b7bfaf3f991dfaSaeed Bisharadone:
2878f351b2d638c3cb0b95adde3549b7bfaf3f991dfaSaeed Bishara	return rc;
2879f351b2d638c3cb0b95adde3549b7bfaf3f991dfaSaeed Bishara}
2880fb621e2fde735abab854586d52c96c5624bcb5b8Jeff Garzik
2881f351b2d638c3cb0b95adde3549b7bfaf3f991dfaSaeed Bishara/**
2882f351b2d638c3cb0b95adde3549b7bfaf3f991dfaSaeed Bishara *      mv_platform_probe - handle a positive probe of an soc Marvell
2883f351b2d638c3cb0b95adde3549b7bfaf3f991dfaSaeed Bishara *      host
2884f351b2d638c3cb0b95adde3549b7bfaf3f991dfaSaeed Bishara *      @pdev: platform device found
2885f351b2d638c3cb0b95adde3549b7bfaf3f991dfaSaeed Bishara *
2886f351b2d638c3cb0b95adde3549b7bfaf3f991dfaSaeed Bishara *      LOCKING:
2887f351b2d638c3cb0b95adde3549b7bfaf3f991dfaSaeed Bishara *      Inherited from caller.
2888f351b2d638c3cb0b95adde3549b7bfaf3f991dfaSaeed Bishara */
2889f351b2d638c3cb0b95adde3549b7bfaf3f991dfaSaeed Bisharastatic int mv_platform_probe(struct platform_device *pdev)
2890f351b2d638c3cb0b95adde3549b7bfaf3f991dfaSaeed Bishara{
2891f351b2d638c3cb0b95adde3549b7bfaf3f991dfaSaeed Bishara	static int printed_version;
2892f351b2d638c3cb0b95adde3549b7bfaf3f991dfaSaeed Bishara	const struct mv_sata_platform_data *mv_platform_data;
2893f351b2d638c3cb0b95adde3549b7bfaf3f991dfaSaeed Bishara	const struct ata_port_info *ppi[] =
2894f351b2d638c3cb0b95adde3549b7bfaf3f991dfaSaeed Bishara	    { &mv_port_info[chip_soc], NULL };
2895f351b2d638c3cb0b95adde3549b7bfaf3f991dfaSaeed Bishara	struct ata_host *host;
2896f351b2d638c3cb0b95adde3549b7bfaf3f991dfaSaeed Bishara	struct mv_host_priv *hpriv;
2897f351b2d638c3cb0b95adde3549b7bfaf3f991dfaSaeed Bishara	struct resource *res;
2898f351b2d638c3cb0b95adde3549b7bfaf3f991dfaSaeed Bishara	int n_ports, rc;
289920f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ
2900f351b2d638c3cb0b95adde3549b7bfaf3f991dfaSaeed Bishara	if (!printed_version++)
2901f351b2d638c3cb0b95adde3549b7bfaf3f991dfaSaeed Bishara		dev_printk(KERN_INFO, &pdev->dev, "version " DRV_VERSION "\n");
2902bca1c4eb9411533d613123618c0d127fae532595Jeff Garzik
2903f351b2d638c3cb0b95adde3549b7bfaf3f991dfaSaeed Bishara	/*
2904f351b2d638c3cb0b95adde3549b7bfaf3f991dfaSaeed Bishara	 * Simple resource validation ..
2905f351b2d638c3cb0b95adde3549b7bfaf3f991dfaSaeed Bishara	 */
2906f351b2d638c3cb0b95adde3549b7bfaf3f991dfaSaeed Bishara	if (unlikely(pdev->num_resources != 2)) {
2907f351b2d638c3cb0b95adde3549b7bfaf3f991dfaSaeed Bishara		dev_err(&pdev->dev, "invalid number of resources\n");
2908f351b2d638c3cb0b95adde3549b7bfaf3f991dfaSaeed Bishara		return -EINVAL;
2909f351b2d638c3cb0b95adde3549b7bfaf3f991dfaSaeed Bishara	}
2910f351b2d638c3cb0b95adde3549b7bfaf3f991dfaSaeed Bishara
2911f351b2d638c3cb0b95adde3549b7bfaf3f991dfaSaeed Bishara	/*
2912f351b2d638c3cb0b95adde3549b7bfaf3f991dfaSaeed Bishara	 * Get the register base first
2913f351b2d638c3cb0b95adde3549b7bfaf3f991dfaSaeed Bishara	 */
2914f351b2d638c3cb0b95adde3549b7bfaf3f991dfaSaeed Bishara	res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
2915f351b2d638c3cb0b95adde3549b7bfaf3f991dfaSaeed Bishara	if (res == NULL)
2916f351b2d638c3cb0b95adde3549b7bfaf3f991dfaSaeed Bishara		return -EINVAL;
2917f351b2d638c3cb0b95adde3549b7bfaf3f991dfaSaeed Bishara
2918f351b2d638c3cb0b95adde3549b7bfaf3f991dfaSaeed Bishara	/* allocate host */
2919f351b2d638c3cb0b95adde3549b7bfaf3f991dfaSaeed Bishara	mv_platform_data = pdev->dev.platform_data;
2920f351b2d638c3cb0b95adde3549b7bfaf3f991dfaSaeed Bishara	n_ports = mv_platform_data->n_ports;
2921f351b2d638c3cb0b95adde3549b7bfaf3f991dfaSaeed Bishara
2922f351b2d638c3cb0b95adde3549b7bfaf3f991dfaSaeed Bishara	host = ata_host_alloc_pinfo(&pdev->dev, ppi, n_ports);
2923f351b2d638c3cb0b95adde3549b7bfaf3f991dfaSaeed Bishara	hpriv = devm_kzalloc(&pdev->dev, sizeof(*hpriv), GFP_KERNEL);
2924f351b2d638c3cb0b95adde3549b7bfaf3f991dfaSaeed Bishara
2925f351b2d638c3cb0b95adde3549b7bfaf3f991dfaSaeed Bishara	if (!host || !hpriv)
2926f351b2d638c3cb0b95adde3549b7bfaf3f991dfaSaeed Bishara		return -ENOMEM;
2927f351b2d638c3cb0b95adde3549b7bfaf3f991dfaSaeed Bishara	host->private_data = hpriv;
2928f351b2d638c3cb0b95adde3549b7bfaf3f991dfaSaeed Bishara	hpriv->n_ports = n_ports;
2929f351b2d638c3cb0b95adde3549b7bfaf3f991dfaSaeed Bishara
2930f351b2d638c3cb0b95adde3549b7bfaf3f991dfaSaeed Bishara	host->iomap = NULL;
2931f351b2d638c3cb0b95adde3549b7bfaf3f991dfaSaeed Bishara	hpriv->base = ioremap(res->start, res->end - res->start + 1);
2932f351b2d638c3cb0b95adde3549b7bfaf3f991dfaSaeed Bishara	hpriv->base -= MV_SATAHC0_REG_BASE;
2933f351b2d638c3cb0b95adde3549b7bfaf3f991dfaSaeed Bishara
2934f351b2d638c3cb0b95adde3549b7bfaf3f991dfaSaeed Bishara	/* initialize adapter */
2935f351b2d638c3cb0b95adde3549b7bfaf3f991dfaSaeed Bishara	rc = mv_init_host(host, chip_soc);
2936f351b2d638c3cb0b95adde3549b7bfaf3f991dfaSaeed Bishara	if (rc)
2937f351b2d638c3cb0b95adde3549b7bfaf3f991dfaSaeed Bishara		return rc;
2938f351b2d638c3cb0b95adde3549b7bfaf3f991dfaSaeed Bishara
2939f351b2d638c3cb0b95adde3549b7bfaf3f991dfaSaeed Bishara	dev_printk(KERN_INFO, &pdev->dev,
2940f351b2d638c3cb0b95adde3549b7bfaf3f991dfaSaeed Bishara		   "slots %u ports %d\n", (unsigned)MV_MAX_Q_DEPTH,
2941f351b2d638c3cb0b95adde3549b7bfaf3f991dfaSaeed Bishara		   host->n_ports);
2942f351b2d638c3cb0b95adde3549b7bfaf3f991dfaSaeed Bishara
2943f351b2d638c3cb0b95adde3549b7bfaf3f991dfaSaeed Bishara	return ata_host_activate(host, platform_get_irq(pdev, 0), mv_interrupt,
2944f351b2d638c3cb0b95adde3549b7bfaf3f991dfaSaeed Bishara				 IRQF_SHARED, &mv6_sht);
2945f351b2d638c3cb0b95adde3549b7bfaf3f991dfaSaeed Bishara}
2946f351b2d638c3cb0b95adde3549b7bfaf3f991dfaSaeed Bishara
2947f351b2d638c3cb0b95adde3549b7bfaf3f991dfaSaeed Bishara/*
2948f351b2d638c3cb0b95adde3549b7bfaf3f991dfaSaeed Bishara *
2949f351b2d638c3cb0b95adde3549b7bfaf3f991dfaSaeed Bishara *      mv_platform_remove    -       unplug a platform interface
2950f351b2d638c3cb0b95adde3549b7bfaf3f991dfaSaeed Bishara *      @pdev: platform device
2951f351b2d638c3cb0b95adde3549b7bfaf3f991dfaSaeed Bishara *
2952f351b2d638c3cb0b95adde3549b7bfaf3f991dfaSaeed Bishara *      A platform bus SATA device has been unplugged. Perform the needed
2953f351b2d638c3cb0b95adde3549b7bfaf3f991dfaSaeed Bishara *      cleanup. Also called on module unload for any active devices.
2954f351b2d638c3cb0b95adde3549b7bfaf3f991dfaSaeed Bishara */
2955f351b2d638c3cb0b95adde3549b7bfaf3f991dfaSaeed Bisharastatic int __devexit mv_platform_remove(struct platform_device *pdev)
2956f351b2d638c3cb0b95adde3549b7bfaf3f991dfaSaeed Bishara{
2957f351b2d638c3cb0b95adde3549b7bfaf3f991dfaSaeed Bishara	struct device *dev = &pdev->dev;
2958f351b2d638c3cb0b95adde3549b7bfaf3f991dfaSaeed Bishara	struct ata_host *host = dev_get_drvdata(dev);
2959f351b2d638c3cb0b95adde3549b7bfaf3f991dfaSaeed Bishara	struct mv_host_priv *hpriv = host->private_data;
2960f351b2d638c3cb0b95adde3549b7bfaf3f991dfaSaeed Bishara	void __iomem *base = hpriv->base;
2961f351b2d638c3cb0b95adde3549b7bfaf3f991dfaSaeed Bishara
2962f351b2d638c3cb0b95adde3549b7bfaf3f991dfaSaeed Bishara	ata_host_detach(host);
2963f351b2d638c3cb0b95adde3549b7bfaf3f991dfaSaeed Bishara	iounmap(base);
2964f351b2d638c3cb0b95adde3549b7bfaf3f991dfaSaeed Bishara	return 0;
296520f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ}
296620f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ
2967f351b2d638c3cb0b95adde3549b7bfaf3f991dfaSaeed Bisharastatic struct platform_driver mv_platform_driver = {
2968f351b2d638c3cb0b95adde3549b7bfaf3f991dfaSaeed Bishara	.probe			= mv_platform_probe,
2969f351b2d638c3cb0b95adde3549b7bfaf3f991dfaSaeed Bishara	.remove			= __devexit_p(mv_platform_remove),
2970f351b2d638c3cb0b95adde3549b7bfaf3f991dfaSaeed Bishara	.driver			= {
2971f351b2d638c3cb0b95adde3549b7bfaf3f991dfaSaeed Bishara				   .name = DRV_NAME,
2972f351b2d638c3cb0b95adde3549b7bfaf3f991dfaSaeed Bishara				   .owner = THIS_MODULE,
2973f351b2d638c3cb0b95adde3549b7bfaf3f991dfaSaeed Bishara				  },
2974f351b2d638c3cb0b95adde3549b7bfaf3f991dfaSaeed Bishara};
2975f351b2d638c3cb0b95adde3549b7bfaf3f991dfaSaeed Bishara
2976f351b2d638c3cb0b95adde3549b7bfaf3f991dfaSaeed Bishara
29777bb3c5290ca0ec9e65947c907495c2b56e895e46Saeed Bishara#ifdef CONFIG_PCI
2978f351b2d638c3cb0b95adde3549b7bfaf3f991dfaSaeed Bisharastatic int mv_pci_init_one(struct pci_dev *pdev,
2979f351b2d638c3cb0b95adde3549b7bfaf3f991dfaSaeed Bishara			   const struct pci_device_id *ent);
2980f351b2d638c3cb0b95adde3549b7bfaf3f991dfaSaeed Bishara
29817bb3c5290ca0ec9e65947c907495c2b56e895e46Saeed Bishara
29827bb3c5290ca0ec9e65947c907495c2b56e895e46Saeed Bisharastatic struct pci_driver mv_pci_driver = {
29837bb3c5290ca0ec9e65947c907495c2b56e895e46Saeed Bishara	.name			= DRV_NAME,
29847bb3c5290ca0ec9e65947c907495c2b56e895e46Saeed Bishara	.id_table		= mv_pci_tbl,
2985f351b2d638c3cb0b95adde3549b7bfaf3f991dfaSaeed Bishara	.probe			= mv_pci_init_one,
29867bb3c5290ca0ec9e65947c907495c2b56e895e46Saeed Bishara	.remove			= ata_pci_remove_one,
29877bb3c5290ca0ec9e65947c907495c2b56e895e46Saeed Bishara};
29887bb3c5290ca0ec9e65947c907495c2b56e895e46Saeed Bishara
29897bb3c5290ca0ec9e65947c907495c2b56e895e46Saeed Bishara/*
29907bb3c5290ca0ec9e65947c907495c2b56e895e46Saeed Bishara * module options
29917bb3c5290ca0ec9e65947c907495c2b56e895e46Saeed Bishara */
29927bb3c5290ca0ec9e65947c907495c2b56e895e46Saeed Bisharastatic int msi;	      /* Use PCI msi; either zero (off, default) or non-zero */
29937bb3c5290ca0ec9e65947c907495c2b56e895e46Saeed Bishara
29947bb3c5290ca0ec9e65947c907495c2b56e895e46Saeed Bishara
29957bb3c5290ca0ec9e65947c907495c2b56e895e46Saeed Bishara/* move to PCI layer or libata core? */
29967bb3c5290ca0ec9e65947c907495c2b56e895e46Saeed Bisharastatic int pci_go_64(struct pci_dev *pdev)
29977bb3c5290ca0ec9e65947c907495c2b56e895e46Saeed Bishara{
29987bb3c5290ca0ec9e65947c907495c2b56e895e46Saeed Bishara	int rc;
29997bb3c5290ca0ec9e65947c907495c2b56e895e46Saeed Bishara
30007bb3c5290ca0ec9e65947c907495c2b56e895e46Saeed Bishara	if (!pci_set_dma_mask(pdev, DMA_64BIT_MASK)) {
30017bb3c5290ca0ec9e65947c907495c2b56e895e46Saeed Bishara		rc = pci_set_consistent_dma_mask(pdev, DMA_64BIT_MASK);
30027bb3c5290ca0ec9e65947c907495c2b56e895e46Saeed Bishara		if (rc) {
30037bb3c5290ca0ec9e65947c907495c2b56e895e46Saeed Bishara			rc = pci_set_consistent_dma_mask(pdev, DMA_32BIT_MASK);
30047bb3c5290ca0ec9e65947c907495c2b56e895e46Saeed Bishara			if (rc) {
30057bb3c5290ca0ec9e65947c907495c2b56e895e46Saeed Bishara				dev_printk(KERN_ERR, &pdev->dev,
30067bb3c5290ca0ec9e65947c907495c2b56e895e46Saeed Bishara					   "64-bit DMA enable failed\n");
30077bb3c5290ca0ec9e65947c907495c2b56e895e46Saeed Bishara				return rc;
30087bb3c5290ca0ec9e65947c907495c2b56e895e46Saeed Bishara			}
30097bb3c5290ca0ec9e65947c907495c2b56e895e46Saeed Bishara		}
30107bb3c5290ca0ec9e65947c907495c2b56e895e46Saeed Bishara	} else {
30117bb3c5290ca0ec9e65947c907495c2b56e895e46Saeed Bishara		rc = pci_set_dma_mask(pdev, DMA_32BIT_MASK);
30127bb3c5290ca0ec9e65947c907495c2b56e895e46Saeed Bishara		if (rc) {
30137bb3c5290ca0ec9e65947c907495c2b56e895e46Saeed Bishara			dev_printk(KERN_ERR, &pdev->dev,
30147bb3c5290ca0ec9e65947c907495c2b56e895e46Saeed Bishara				   "32-bit DMA enable failed\n");
30157bb3c5290ca0ec9e65947c907495c2b56e895e46Saeed Bishara			return rc;
30167bb3c5290ca0ec9e65947c907495c2b56e895e46Saeed Bishara		}
30177bb3c5290ca0ec9e65947c907495c2b56e895e46Saeed Bishara		rc = pci_set_consistent_dma_mask(pdev, DMA_32BIT_MASK);
30187bb3c5290ca0ec9e65947c907495c2b56e895e46Saeed Bishara		if (rc) {
30197bb3c5290ca0ec9e65947c907495c2b56e895e46Saeed Bishara			dev_printk(KERN_ERR, &pdev->dev,
30207bb3c5290ca0ec9e65947c907495c2b56e895e46Saeed Bishara				   "32-bit consistent DMA enable failed\n");
30217bb3c5290ca0ec9e65947c907495c2b56e895e46Saeed Bishara			return rc;
30227bb3c5290ca0ec9e65947c907495c2b56e895e46Saeed Bishara		}
30237bb3c5290ca0ec9e65947c907495c2b56e895e46Saeed Bishara	}
30247bb3c5290ca0ec9e65947c907495c2b56e895e46Saeed Bishara
30257bb3c5290ca0ec9e65947c907495c2b56e895e46Saeed Bishara	return rc;
30267bb3c5290ca0ec9e65947c907495c2b56e895e46Saeed Bishara}
30277bb3c5290ca0ec9e65947c907495c2b56e895e46Saeed Bishara
302805b308e1df6d9d673daedb517969241f41278b52Brett Russ/**
302905b308e1df6d9d673daedb517969241f41278b52Brett Russ *      mv_print_info - Dump key info to kernel log for perusal.
30304447d35156169cf136e829eb6b5cac2d6370f2d9Tejun Heo *      @host: ATA host to print info about
303105b308e1df6d9d673daedb517969241f41278b52Brett Russ *
303205b308e1df6d9d673daedb517969241f41278b52Brett Russ *      FIXME: complete this.
303305b308e1df6d9d673daedb517969241f41278b52Brett Russ *
303405b308e1df6d9d673daedb517969241f41278b52Brett Russ *      LOCKING:
303505b308e1df6d9d673daedb517969241f41278b52Brett Russ *      Inherited from caller.
303605b308e1df6d9d673daedb517969241f41278b52Brett Russ */
30374447d35156169cf136e829eb6b5cac2d6370f2d9Tejun Heostatic void mv_print_info(struct ata_host *host)
303831961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ{
30394447d35156169cf136e829eb6b5cac2d6370f2d9Tejun Heo	struct pci_dev *pdev = to_pci_dev(host->dev);
30404447d35156169cf136e829eb6b5cac2d6370f2d9Tejun Heo	struct mv_host_priv *hpriv = host->private_data;
304144c10138fd4bbc4b6d6bff0873c24902f2a9da65Auke Kok	u8 scc;
3042c1e4fe711a410a139095e6b3e3ce3f07f466063cJeff Garzik	const char *scc_s, *gen;
304331961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ
304431961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ	/* Use this to determine the HW stepping of the chip so we know
304531961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ	 * what errata to workaround
304631961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ	 */
304731961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ	pci_read_config_byte(pdev, PCI_CLASS_DEVICE, &scc);
304831961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ	if (scc == 0)
304931961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ		scc_s = "SCSI";
305031961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ	else if (scc == 0x01)
305131961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ		scc_s = "RAID";
305231961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ	else
3053c1e4fe711a410a139095e6b3e3ce3f07f466063cJeff Garzik		scc_s = "?";
3054c1e4fe711a410a139095e6b3e3ce3f07f466063cJeff Garzik
3055c1e4fe711a410a139095e6b3e3ce3f07f466063cJeff Garzik	if (IS_GEN_I(hpriv))
3056c1e4fe711a410a139095e6b3e3ce3f07f466063cJeff Garzik		gen = "I";
3057c1e4fe711a410a139095e6b3e3ce3f07f466063cJeff Garzik	else if (IS_GEN_II(hpriv))
3058c1e4fe711a410a139095e6b3e3ce3f07f466063cJeff Garzik		gen = "II";
3059c1e4fe711a410a139095e6b3e3ce3f07f466063cJeff Garzik	else if (IS_GEN_IIE(hpriv))
3060c1e4fe711a410a139095e6b3e3ce3f07f466063cJeff Garzik		gen = "IIE";
3061c1e4fe711a410a139095e6b3e3ce3f07f466063cJeff Garzik	else
3062c1e4fe711a410a139095e6b3e3ce3f07f466063cJeff Garzik		gen = "?";
306331961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ
3064a9524a76f70f3343e4be27f95a7e92a8ba5f9009Jeff Garzik	dev_printk(KERN_INFO, &pdev->dev,
3065c1e4fe711a410a139095e6b3e3ce3f07f466063cJeff Garzik	       "Gen-%s %u slots %u ports %s mode IRQ via %s\n",
3066c1e4fe711a410a139095e6b3e3ce3f07f466063cJeff Garzik	       gen, (unsigned)MV_MAX_Q_DEPTH, host->n_ports,
306731961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ	       scc_s, (MV_HP_FLAG_MSI & hpriv->hp_flags) ? "MSI" : "INTx");
306831961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ}
306931961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ
3070da2fa9baf06f33a8fa7aa3f56c9f2b4070ceca0eMark Lordstatic int mv_create_dma_pools(struct mv_host_priv *hpriv, struct device *dev)
3071da2fa9baf06f33a8fa7aa3f56c9f2b4070ceca0eMark Lord{
3072da2fa9baf06f33a8fa7aa3f56c9f2b4070ceca0eMark Lord	hpriv->crqb_pool   = dmam_pool_create("crqb_q", dev, MV_CRQB_Q_SZ,
3073da2fa9baf06f33a8fa7aa3f56c9f2b4070ceca0eMark Lord							     MV_CRQB_Q_SZ, 0);
3074da2fa9baf06f33a8fa7aa3f56c9f2b4070ceca0eMark Lord	if (!hpriv->crqb_pool)
3075da2fa9baf06f33a8fa7aa3f56c9f2b4070ceca0eMark Lord		return -ENOMEM;
3076da2fa9baf06f33a8fa7aa3f56c9f2b4070ceca0eMark Lord
3077da2fa9baf06f33a8fa7aa3f56c9f2b4070ceca0eMark Lord	hpriv->crpb_pool   = dmam_pool_create("crpb_q", dev, MV_CRPB_Q_SZ,
3078da2fa9baf06f33a8fa7aa3f56c9f2b4070ceca0eMark Lord							     MV_CRPB_Q_SZ, 0);
3079da2fa9baf06f33a8fa7aa3f56c9f2b4070ceca0eMark Lord	if (!hpriv->crpb_pool)
3080da2fa9baf06f33a8fa7aa3f56c9f2b4070ceca0eMark Lord		return -ENOMEM;
3081da2fa9baf06f33a8fa7aa3f56c9f2b4070ceca0eMark Lord
3082da2fa9baf06f33a8fa7aa3f56c9f2b4070ceca0eMark Lord	hpriv->sg_tbl_pool = dmam_pool_create("sg_tbl", dev, MV_SG_TBL_SZ,
3083da2fa9baf06f33a8fa7aa3f56c9f2b4070ceca0eMark Lord							     MV_SG_TBL_SZ, 0);
3084da2fa9baf06f33a8fa7aa3f56c9f2b4070ceca0eMark Lord	if (!hpriv->sg_tbl_pool)
3085da2fa9baf06f33a8fa7aa3f56c9f2b4070ceca0eMark Lord		return -ENOMEM;
3086da2fa9baf06f33a8fa7aa3f56c9f2b4070ceca0eMark Lord
3087da2fa9baf06f33a8fa7aa3f56c9f2b4070ceca0eMark Lord	return 0;
3088da2fa9baf06f33a8fa7aa3f56c9f2b4070ceca0eMark Lord}
3089da2fa9baf06f33a8fa7aa3f56c9f2b4070ceca0eMark Lord
309005b308e1df6d9d673daedb517969241f41278b52Brett Russ/**
3091f351b2d638c3cb0b95adde3549b7bfaf3f991dfaSaeed Bishara *      mv_pci_init_one - handle a positive probe of a PCI Marvell host
309205b308e1df6d9d673daedb517969241f41278b52Brett Russ *      @pdev: PCI device found
309305b308e1df6d9d673daedb517969241f41278b52Brett Russ *      @ent: PCI device ID entry for the matched host
309405b308e1df6d9d673daedb517969241f41278b52Brett Russ *
309505b308e1df6d9d673daedb517969241f41278b52Brett Russ *      LOCKING:
309605b308e1df6d9d673daedb517969241f41278b52Brett Russ *      Inherited from caller.
309705b308e1df6d9d673daedb517969241f41278b52Brett Russ */
3098f351b2d638c3cb0b95adde3549b7bfaf3f991dfaSaeed Bisharastatic int mv_pci_init_one(struct pci_dev *pdev,
3099f351b2d638c3cb0b95adde3549b7bfaf3f991dfaSaeed Bishara			   const struct pci_device_id *ent)
310020f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ{
31012dcb407e61458ded17503d6bd12b8c064965368bJeff Garzik	static int printed_version;
310220f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ	unsigned int board_idx = (unsigned int)ent->driver_data;
31034447d35156169cf136e829eb6b5cac2d6370f2d9Tejun Heo	const struct ata_port_info *ppi[] = { &mv_port_info[board_idx], NULL };
31044447d35156169cf136e829eb6b5cac2d6370f2d9Tejun Heo	struct ata_host *host;
31054447d35156169cf136e829eb6b5cac2d6370f2d9Tejun Heo	struct mv_host_priv *hpriv;
31064447d35156169cf136e829eb6b5cac2d6370f2d9Tejun Heo	int n_ports, rc;
310720f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ
3108a9524a76f70f3343e4be27f95a7e92a8ba5f9009Jeff Garzik	if (!printed_version++)
3109a9524a76f70f3343e4be27f95a7e92a8ba5f9009Jeff Garzik		dev_printk(KERN_INFO, &pdev->dev, "version " DRV_VERSION "\n");
311020f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ
31114447d35156169cf136e829eb6b5cac2d6370f2d9Tejun Heo	/* allocate host */
31124447d35156169cf136e829eb6b5cac2d6370f2d9Tejun Heo	n_ports = mv_get_hc_count(ppi[0]->flags) * MV_PORTS_PER_HC;
31134447d35156169cf136e829eb6b5cac2d6370f2d9Tejun Heo
31144447d35156169cf136e829eb6b5cac2d6370f2d9Tejun Heo	host = ata_host_alloc_pinfo(&pdev->dev, ppi, n_ports);
31154447d35156169cf136e829eb6b5cac2d6370f2d9Tejun Heo	hpriv = devm_kzalloc(&pdev->dev, sizeof(*hpriv), GFP_KERNEL);
31164447d35156169cf136e829eb6b5cac2d6370f2d9Tejun Heo	if (!host || !hpriv)
31174447d35156169cf136e829eb6b5cac2d6370f2d9Tejun Heo		return -ENOMEM;
31184447d35156169cf136e829eb6b5cac2d6370f2d9Tejun Heo	host->private_data = hpriv;
3119f351b2d638c3cb0b95adde3549b7bfaf3f991dfaSaeed Bishara	hpriv->n_ports = n_ports;
31204447d35156169cf136e829eb6b5cac2d6370f2d9Tejun Heo
31214447d35156169cf136e829eb6b5cac2d6370f2d9Tejun Heo	/* acquire resources */
312224dc5f33ea4b504cfbd23fa159a4cacba8e4d800Tejun Heo	rc = pcim_enable_device(pdev);
312324dc5f33ea4b504cfbd23fa159a4cacba8e4d800Tejun Heo	if (rc)
312420f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ		return rc;
312520f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ
31260d5ff566779f894ca9937231a181eb31e4adff0eTejun Heo	rc = pcim_iomap_regions(pdev, 1 << MV_PRIMARY_BAR, DRV_NAME);
31270d5ff566779f894ca9937231a181eb31e4adff0eTejun Heo	if (rc == -EBUSY)
312824dc5f33ea4b504cfbd23fa159a4cacba8e4d800Tejun Heo		pcim_pin_device(pdev);
31290d5ff566779f894ca9937231a181eb31e4adff0eTejun Heo	if (rc)
313024dc5f33ea4b504cfbd23fa159a4cacba8e4d800Tejun Heo		return rc;
31314447d35156169cf136e829eb6b5cac2d6370f2d9Tejun Heo	host->iomap = pcim_iomap_table(pdev);
3132f351b2d638c3cb0b95adde3549b7bfaf3f991dfaSaeed Bishara	hpriv->base = host->iomap[MV_PRIMARY_BAR];
313320f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ
3134d88184fb2348a50f7c34f5d49a901c875b2e0114Jeff Garzik	rc = pci_go_64(pdev);
3135d88184fb2348a50f7c34f5d49a901c875b2e0114Jeff Garzik	if (rc)
3136d88184fb2348a50f7c34f5d49a901c875b2e0114Jeff Garzik		return rc;
3137d88184fb2348a50f7c34f5d49a901c875b2e0114Jeff Garzik
3138da2fa9baf06f33a8fa7aa3f56c9f2b4070ceca0eMark Lord	rc = mv_create_dma_pools(hpriv, &pdev->dev);
3139da2fa9baf06f33a8fa7aa3f56c9f2b4070ceca0eMark Lord	if (rc)
3140da2fa9baf06f33a8fa7aa3f56c9f2b4070ceca0eMark Lord		return rc;
3141da2fa9baf06f33a8fa7aa3f56c9f2b4070ceca0eMark Lord
314220f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ	/* initialize adapter */
31434447d35156169cf136e829eb6b5cac2d6370f2d9Tejun Heo	rc = mv_init_host(host, board_idx);
314424dc5f33ea4b504cfbd23fa159a4cacba8e4d800Tejun Heo	if (rc)
314524dc5f33ea4b504cfbd23fa159a4cacba8e4d800Tejun Heo		return rc;
314620f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ
314731961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ	/* Enable interrupts */
31486a59dcf8678cbc4106a8a6e158d7408a87691358Tejun Heo	if (msi && pci_enable_msi(pdev))
314931961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ		pci_intx(pdev, 1);
315020f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ
315131961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ	mv_dump_pci_cfg(pdev, 0x68);
31524447d35156169cf136e829eb6b5cac2d6370f2d9Tejun Heo	mv_print_info(host);
315320f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ
31544447d35156169cf136e829eb6b5cac2d6370f2d9Tejun Heo	pci_set_master(pdev);
3155ea8b4db97aa41a66c05daa4055a1974692ccd52dJeff Garzik	pci_try_set_mwi(pdev);
31564447d35156169cf136e829eb6b5cac2d6370f2d9Tejun Heo	return ata_host_activate(host, pdev->irq, mv_interrupt, IRQF_SHARED,
3157c5d3e45a2200a0905dc45b72714726b7aac3aaf1Jeff Garzik				 IS_GEN_I(hpriv) ? &mv5_sht : &mv6_sht);
315820f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ}
31597bb3c5290ca0ec9e65947c907495c2b56e895e46Saeed Bishara#endif
316020f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ
3161f351b2d638c3cb0b95adde3549b7bfaf3f991dfaSaeed Bisharastatic int mv_platform_probe(struct platform_device *pdev);
3162f351b2d638c3cb0b95adde3549b7bfaf3f991dfaSaeed Bisharastatic int __devexit mv_platform_remove(struct platform_device *pdev);
3163f351b2d638c3cb0b95adde3549b7bfaf3f991dfaSaeed Bishara
316420f733e7d75a16bffc34842b7682c9247dd5f954Brett Russstatic int __init mv_init(void)
316520f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ{
31667bb3c5290ca0ec9e65947c907495c2b56e895e46Saeed Bishara	int rc = -ENODEV;
31677bb3c5290ca0ec9e65947c907495c2b56e895e46Saeed Bishara#ifdef CONFIG_PCI
31687bb3c5290ca0ec9e65947c907495c2b56e895e46Saeed Bishara	rc = pci_register_driver(&mv_pci_driver);
3169f351b2d638c3cb0b95adde3549b7bfaf3f991dfaSaeed Bishara	if (rc < 0)
3170f351b2d638c3cb0b95adde3549b7bfaf3f991dfaSaeed Bishara		return rc;
3171f351b2d638c3cb0b95adde3549b7bfaf3f991dfaSaeed Bishara#endif
3172f351b2d638c3cb0b95adde3549b7bfaf3f991dfaSaeed Bishara	rc = platform_driver_register(&mv_platform_driver);
3173f351b2d638c3cb0b95adde3549b7bfaf3f991dfaSaeed Bishara
3174f351b2d638c3cb0b95adde3549b7bfaf3f991dfaSaeed Bishara#ifdef CONFIG_PCI
3175f351b2d638c3cb0b95adde3549b7bfaf3f991dfaSaeed Bishara	if (rc < 0)
3176f351b2d638c3cb0b95adde3549b7bfaf3f991dfaSaeed Bishara		pci_unregister_driver(&mv_pci_driver);
31777bb3c5290ca0ec9e65947c907495c2b56e895e46Saeed Bishara#endif
31787bb3c5290ca0ec9e65947c907495c2b56e895e46Saeed Bishara	return rc;
317920f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ}
318020f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ
318120f733e7d75a16bffc34842b7682c9247dd5f954Brett Russstatic void __exit mv_exit(void)
318220f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ{
31837bb3c5290ca0ec9e65947c907495c2b56e895e46Saeed Bishara#ifdef CONFIG_PCI
318420f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ	pci_unregister_driver(&mv_pci_driver);
31857bb3c5290ca0ec9e65947c907495c2b56e895e46Saeed Bishara#endif
3186f351b2d638c3cb0b95adde3549b7bfaf3f991dfaSaeed Bishara	platform_driver_unregister(&mv_platform_driver);
318720f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ}
318820f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ
318920f733e7d75a16bffc34842b7682c9247dd5f954Brett RussMODULE_AUTHOR("Brett Russ");
319020f733e7d75a16bffc34842b7682c9247dd5f954Brett RussMODULE_DESCRIPTION("SCSI low-level driver for Marvell SATA controllers");
319120f733e7d75a16bffc34842b7682c9247dd5f954Brett RussMODULE_LICENSE("GPL");
319220f733e7d75a16bffc34842b7682c9247dd5f954Brett RussMODULE_DEVICE_TABLE(pci, mv_pci_tbl);
319320f733e7d75a16bffc34842b7682c9247dd5f954Brett RussMODULE_VERSION(DRV_VERSION);
319420f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ
31957bb3c5290ca0ec9e65947c907495c2b56e895e46Saeed Bishara#ifdef CONFIG_PCI
3196ddef9bb367b19383df627e388cb4c01c86ddba6cJeff Garzikmodule_param(msi, int, 0444);
3197ddef9bb367b19383df627e388cb4c01c86ddba6cJeff GarzikMODULE_PARM_DESC(msi, "Enable use of PCI MSI (0=off, 1=on)");
31987bb3c5290ca0ec9e65947c907495c2b56e895e46Saeed Bishara#endif
3199ddef9bb367b19383df627e388cb4c01c86ddba6cJeff Garzik
320020f733e7d75a16bffc34842b7682c9247dd5f954Brett Russmodule_init(mv_init);
320120f733e7d75a16bffc34842b7682c9247dd5f954Brett Russmodule_exit(mv_exit);
3202