sata_mv.c revision 44c10138fd4bbc4b6d6bff0873c24902f2a9da65
120f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ/*
220f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ * sata_mv.c - Marvell SATA support
320f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ *
48b260248d9e0e8b64bb72fd4dee03ad86984c344Jeff Garzik * Copyright 2005: EMC Corporation, all rights reserved.
5e2b1be56c5656902744c2b52e8304126a40bb609Jeff Garzik * Copyright 2005 Red Hat, Inc.  All rights reserved.
620f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ *
720f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ * Please ALWAYS copy linux-ide@vger.kernel.org on emails.
820f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ *
920f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ * This program is free software; you can redistribute it and/or modify
1020f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ * it under the terms of the GNU General Public License as published by
1120f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ * the Free Software Foundation; version 2 of the License.
1220f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ *
1320f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ * This program is distributed in the hope that it will be useful,
1420f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ * but WITHOUT ANY WARRANTY; without even the implied warranty of
1520f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
1620f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ * GNU General Public License for more details.
1720f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ *
1820f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ * You should have received a copy of the GNU General Public License
1920f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ * along with this program; if not, write to the Free Software
2020f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
2120f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ *
2220f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ */
2320f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ
244a05e2091709dbb22b86a1b3343cd3fa3c0d7a6bJeff Garzik/*
254a05e2091709dbb22b86a1b3343cd3fa3c0d7a6bJeff Garzik  sata_mv TODO list:
264a05e2091709dbb22b86a1b3343cd3fa3c0d7a6bJeff Garzik
274a05e2091709dbb22b86a1b3343cd3fa3c0d7a6bJeff Garzik  1) Needs a full errata audit for all chipsets.  I implemented most
284a05e2091709dbb22b86a1b3343cd3fa3c0d7a6bJeff Garzik  of the errata workarounds found in the Marvell vendor driver, but
294a05e2091709dbb22b86a1b3343cd3fa3c0d7a6bJeff Garzik  I distinctly remember a couple workarounds (one related to PCI-X)
304a05e2091709dbb22b86a1b3343cd3fa3c0d7a6bJeff Garzik  are still needed.
314a05e2091709dbb22b86a1b3343cd3fa3c0d7a6bJeff Garzik
324a05e2091709dbb22b86a1b3343cd3fa3c0d7a6bJeff Garzik  2) Convert to LibATA new EH.  Required for hotplug, NCQ, and sane
334a05e2091709dbb22b86a1b3343cd3fa3c0d7a6bJeff Garzik  probing/error handling in general.  MUST HAVE.
344a05e2091709dbb22b86a1b3343cd3fa3c0d7a6bJeff Garzik
354a05e2091709dbb22b86a1b3343cd3fa3c0d7a6bJeff Garzik  3) Add hotplug support (easy, once new-EH support appears)
364a05e2091709dbb22b86a1b3343cd3fa3c0d7a6bJeff Garzik
374a05e2091709dbb22b86a1b3343cd3fa3c0d7a6bJeff Garzik  4) Add NCQ support (easy to intermediate, once new-EH support appears)
384a05e2091709dbb22b86a1b3343cd3fa3c0d7a6bJeff Garzik
394a05e2091709dbb22b86a1b3343cd3fa3c0d7a6bJeff Garzik  5) Investigate problems with PCI Message Signalled Interrupts (MSI).
404a05e2091709dbb22b86a1b3343cd3fa3c0d7a6bJeff Garzik
414a05e2091709dbb22b86a1b3343cd3fa3c0d7a6bJeff Garzik  6) Add port multiplier support (intermediate)
424a05e2091709dbb22b86a1b3343cd3fa3c0d7a6bJeff Garzik
434a05e2091709dbb22b86a1b3343cd3fa3c0d7a6bJeff Garzik  7) Test and verify 3.0 Gbps support
444a05e2091709dbb22b86a1b3343cd3fa3c0d7a6bJeff Garzik
454a05e2091709dbb22b86a1b3343cd3fa3c0d7a6bJeff Garzik  8) Develop a low-power-consumption strategy, and implement it.
464a05e2091709dbb22b86a1b3343cd3fa3c0d7a6bJeff Garzik
474a05e2091709dbb22b86a1b3343cd3fa3c0d7a6bJeff Garzik  9) [Experiment, low priority] See if ATAPI can be supported using
484a05e2091709dbb22b86a1b3343cd3fa3c0d7a6bJeff Garzik  "unknown FIS" or "vendor-specific FIS" support, or something creative
494a05e2091709dbb22b86a1b3343cd3fa3c0d7a6bJeff Garzik  like that.
504a05e2091709dbb22b86a1b3343cd3fa3c0d7a6bJeff Garzik
514a05e2091709dbb22b86a1b3343cd3fa3c0d7a6bJeff Garzik  10) [Experiment, low priority] Investigate interrupt coalescing.
524a05e2091709dbb22b86a1b3343cd3fa3c0d7a6bJeff Garzik  Quite often, especially with PCI Message Signalled Interrupts (MSI),
534a05e2091709dbb22b86a1b3343cd3fa3c0d7a6bJeff Garzik  the overhead reduced by interrupt mitigation is quite often not
544a05e2091709dbb22b86a1b3343cd3fa3c0d7a6bJeff Garzik  worth the latency cost.
554a05e2091709dbb22b86a1b3343cd3fa3c0d7a6bJeff Garzik
564a05e2091709dbb22b86a1b3343cd3fa3c0d7a6bJeff Garzik  11) [Experiment, Marvell value added] Is it possible to use target
574a05e2091709dbb22b86a1b3343cd3fa3c0d7a6bJeff Garzik  mode to cross-connect two Linux boxes with Marvell cards?  If so,
584a05e2091709dbb22b86a1b3343cd3fa3c0d7a6bJeff Garzik  creating LibATA target mode support would be very interesting.
594a05e2091709dbb22b86a1b3343cd3fa3c0d7a6bJeff Garzik
604a05e2091709dbb22b86a1b3343cd3fa3c0d7a6bJeff Garzik  Target mode, for those without docs, is the ability to directly
614a05e2091709dbb22b86a1b3343cd3fa3c0d7a6bJeff Garzik  connect two SATA controllers.
624a05e2091709dbb22b86a1b3343cd3fa3c0d7a6bJeff Garzik
634a05e2091709dbb22b86a1b3343cd3fa3c0d7a6bJeff Garzik  13) Verify that 7042 is fully supported.  I only have a 6042.
644a05e2091709dbb22b86a1b3343cd3fa3c0d7a6bJeff Garzik
654a05e2091709dbb22b86a1b3343cd3fa3c0d7a6bJeff Garzik*/
664a05e2091709dbb22b86a1b3343cd3fa3c0d7a6bJeff Garzik
674a05e2091709dbb22b86a1b3343cd3fa3c0d7a6bJeff Garzik
6820f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ#include <linux/kernel.h>
6920f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ#include <linux/module.h>
7020f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ#include <linux/pci.h>
7120f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ#include <linux/init.h>
7220f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ#include <linux/blkdev.h>
7320f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ#include <linux/delay.h>
7420f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ#include <linux/interrupt.h>
7520f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ#include <linux/dma-mapping.h>
76a9524a76f70f3343e4be27f95a7e92a8ba5f9009Jeff Garzik#include <linux/device.h>
7720f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ#include <scsi/scsi_host.h>
78193515d51ccb363165d6b09e9ba5c21089e34badJeff Garzik#include <scsi/scsi_cmnd.h>
7920f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ#include <linux/libata.h>
8020f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ
8120f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ#define DRV_NAME	"sata_mv"
828bc3fc470eb25af4d70c72485cbcb130cc657691Jeff Garzik#define DRV_VERSION	"0.81"
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_USE_Q_DEPTH		= ATA_DEF_QUEUE,
11220f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ
11331961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ	MV_MAX_Q_DEPTH		= 32,
11431961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ	MV_MAX_Q_DEPTH_MASK	= MV_MAX_Q_DEPTH - 1,
11531961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ
11631961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ	/* CRQB needs alignment on a 1KB boundary. Size == 1KB
11731961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ	 * CRPB needs alignment on a 256B boundary. Size == 256B
11831961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ	 * SG count of 176 leads to MV_PORT_PRIV_DMA_SZ == 4KB
11931961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ	 * ePRD (SG) entries need alignment on a 16B boundary. Size == 16B
12031961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ	 */
12131961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ	MV_CRQB_Q_SZ		= (32 * MV_MAX_Q_DEPTH),
12231961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ	MV_CRPB_Q_SZ		= (8 * MV_MAX_Q_DEPTH),
12331961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ	MV_MAX_SG_CT		= 176,
12431961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ	MV_SG_TBL_SZ		= (16 * MV_MAX_SG_CT),
12531961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ	MV_PORT_PRIV_DMA_SZ	= (MV_CRQB_Q_SZ + MV_CRPB_Q_SZ + MV_SG_TBL_SZ),
12631961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ
12720f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ	MV_PORTS_PER_HC		= 4,
12820f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ	/* == (port / MV_PORTS_PER_HC) to determine HC from 0-7 port */
12920f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ	MV_PORT_HC_SHIFT	= 2,
13031961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ	/* == (port % MV_PORTS_PER_HC) to determine hard port from 0-7 port */
13120f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ	MV_PORT_MASK		= 3,
13220f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ
13320f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ	/* Host Flags */
13420f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ	MV_FLAG_DUAL_HC		= (1 << 30),  /* two SATA Host Controllers */
13520f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ	MV_FLAG_IRQ_COALESCE	= (1 << 29),  /* IRQ coalescing capability */
13631961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ	MV_COMMON_FLAGS		= (ATA_FLAG_SATA | ATA_FLAG_NO_LEGACY |
13750630195bbdfe1ca775d94cd68a5f18bc1b717e4Jeff Garzik				   ATA_FLAG_SATA_RESET | ATA_FLAG_MMIO |
1381f3461a72619fcd70a0fcb563306c91f753b4620Albert Lee				   ATA_FLAG_NO_ATAPI | ATA_FLAG_PIO_POLLING),
13947c2b677daeed9c79ecb7167c211ff36876ea611Jeff Garzik	MV_6XXX_FLAGS		= MV_FLAG_IRQ_COALESCE,
14020f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ
14131961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ	CRQB_FLAG_READ		= (1 << 0),
14231961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ	CRQB_TAG_SHIFT		= 1,
14331961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ	CRQB_CMD_ADDR_SHIFT	= 8,
14431961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ	CRQB_CMD_CS		= (0x2 << 11),
14531961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ	CRQB_CMD_LAST		= (1 << 15),
14631961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ
14731961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ	CRPB_FLAG_STATUS_SHIFT	= 8,
14831961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ
14931961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ	EPRD_FLAG_END_OF_TBL	= (1 << 31),
15031961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ
15120f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ	/* PCI interface registers */
15220f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ
15331961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ	PCI_COMMAND_OFS		= 0xc00,
15431961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ
15520f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ	PCI_MAIN_CMD_STS_OFS	= 0xd30,
15620f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ	STOP_PCI_MASTER		= (1 << 2),
15720f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ	PCI_MASTER_EMPTY	= (1 << 3),
15820f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ	GLOB_SFT_RST		= (1 << 4),
15920f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ
160522479fb98c6667f081e75f87e298e413c0b1db8Jeff Garzik	MV_PCI_MODE		= 0xd00,
161522479fb98c6667f081e75f87e298e413c0b1db8Jeff Garzik	MV_PCI_EXP_ROM_BAR_CTL	= 0xd2c,
162522479fb98c6667f081e75f87e298e413c0b1db8Jeff Garzik	MV_PCI_DISC_TIMER	= 0xd04,
163522479fb98c6667f081e75f87e298e413c0b1db8Jeff Garzik	MV_PCI_MSI_TRIGGER	= 0xc38,
164522479fb98c6667f081e75f87e298e413c0b1db8Jeff Garzik	MV_PCI_SERR_MASK	= 0xc28,
165522479fb98c6667f081e75f87e298e413c0b1db8Jeff Garzik	MV_PCI_XBAR_TMOUT	= 0x1d04,
166522479fb98c6667f081e75f87e298e413c0b1db8Jeff Garzik	MV_PCI_ERR_LOW_ADDRESS	= 0x1d40,
167522479fb98c6667f081e75f87e298e413c0b1db8Jeff Garzik	MV_PCI_ERR_HIGH_ADDRESS	= 0x1d44,
168522479fb98c6667f081e75f87e298e413c0b1db8Jeff Garzik	MV_PCI_ERR_ATTRIBUTE	= 0x1d48,
169522479fb98c6667f081e75f87e298e413c0b1db8Jeff Garzik	MV_PCI_ERR_COMMAND	= 0x1d50,
170522479fb98c6667f081e75f87e298e413c0b1db8Jeff Garzik
171522479fb98c6667f081e75f87e298e413c0b1db8Jeff Garzik	PCI_IRQ_CAUSE_OFS		= 0x1d58,
172522479fb98c6667f081e75f87e298e413c0b1db8Jeff Garzik	PCI_IRQ_MASK_OFS		= 0x1d5c,
17320f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ	PCI_UNMASK_ALL_IRQS	= 0x7fffff,	/* bits 22-0 */
17420f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ
17520f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ	HC_MAIN_IRQ_CAUSE_OFS	= 0x1d60,
17620f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ	HC_MAIN_IRQ_MASK_OFS	= 0x1d64,
17720f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ	PORT0_ERR		= (1 << 0),	/* shift by port # */
17820f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ	PORT0_DONE		= (1 << 1),	/* shift by port # */
17920f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ	HC0_IRQ_PEND		= 0x1ff,	/* bits 0-8 = HC0's ports */
18020f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ	HC_SHIFT		= 9,		/* bits 9-17 = HC1's ports */
18120f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ	PCI_ERR			= (1 << 18),
18220f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ	TRAN_LO_DONE		= (1 << 19),	/* 6xxx: IRQ coalescing */
18320f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ	TRAN_HI_DONE		= (1 << 20),	/* 6xxx: IRQ coalescing */
184fb621e2fde735abab854586d52c96c5624bcb5b8Jeff Garzik	PORTS_0_3_COAL_DONE	= (1 << 8),
185fb621e2fde735abab854586d52c96c5624bcb5b8Jeff Garzik	PORTS_4_7_COAL_DONE	= (1 << 17),
18620f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ	PORTS_0_7_COAL_DONE	= (1 << 21),	/* 6xxx: IRQ coalescing */
18720f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ	GPIO_INT		= (1 << 22),
18820f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ	SELF_INT		= (1 << 23),
18920f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ	TWSI_INT		= (1 << 24),
19020f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ	HC_MAIN_RSVD		= (0x7f << 25),	/* bits 31-25 */
191fb621e2fde735abab854586d52c96c5624bcb5b8Jeff Garzik	HC_MAIN_RSVD_5		= (0x1fff << 19), /* bits 31-19 */
1928b260248d9e0e8b64bb72fd4dee03ad86984c344Jeff Garzik	HC_MAIN_MASKED_IRQS	= (TRAN_LO_DONE | TRAN_HI_DONE |
19320f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ				   PORTS_0_7_COAL_DONE | GPIO_INT | TWSI_INT |
19420f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ				   HC_MAIN_RSVD),
195fb621e2fde735abab854586d52c96c5624bcb5b8Jeff Garzik	HC_MAIN_MASKED_IRQS_5	= (PORTS_0_3_COAL_DONE | PORTS_4_7_COAL_DONE |
196fb621e2fde735abab854586d52c96c5624bcb5b8Jeff Garzik				   HC_MAIN_RSVD_5),
19720f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ
19820f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ	/* SATAHC registers */
19920f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ	HC_CFG_OFS		= 0,
20020f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ
20120f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ	HC_IRQ_CAUSE_OFS	= 0x14,
20231961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ	CRPB_DMA_DONE		= (1 << 0),	/* shift by port # */
20320f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ	HC_IRQ_COAL		= (1 << 4),	/* IRQ coalescing */
20420f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ	DEV_IRQ			= (1 << 8),	/* shift by port # */
20520f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ
20620f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ	/* Shadow block registers */
20731961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ	SHD_BLK_OFS		= 0x100,
20831961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ	SHD_CTL_AST_OFS		= 0x20,		/* ofs from SHD_BLK_OFS */
20920f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ
21020f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ	/* SATA registers */
21120f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ	SATA_STATUS_OFS		= 0x300,  /* ctrl, err regs follow status */
21220f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ	SATA_ACTIVE_OFS		= 0x350,
21347c2b677daeed9c79ecb7167c211ff36876ea611Jeff Garzik	PHY_MODE3		= 0x310,
214bca1c4eb9411533d613123618c0d127fae532595Jeff Garzik	PHY_MODE4		= 0x314,
215bca1c4eb9411533d613123618c0d127fae532595Jeff Garzik	PHY_MODE2		= 0x330,
216c9d39130123238ac18478a42e25cb7996eacfcc0Jeff Garzik	MV5_PHY_MODE		= 0x74,
217c9d39130123238ac18478a42e25cb7996eacfcc0Jeff Garzik	MV5_LT_MODE		= 0x30,
218c9d39130123238ac18478a42e25cb7996eacfcc0Jeff Garzik	MV5_PHY_CTL		= 0x0C,
219bca1c4eb9411533d613123618c0d127fae532595Jeff Garzik	SATA_INTERFACE_CTL	= 0x050,
220bca1c4eb9411533d613123618c0d127fae532595Jeff Garzik
221bca1c4eb9411533d613123618c0d127fae532595Jeff Garzik	MV_M2_PREAMP_MASK	= 0x7e0,
22220f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ
22320f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ	/* Port registers */
22420f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ	EDMA_CFG_OFS		= 0,
22531961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ	EDMA_CFG_Q_DEPTH	= 0,			/* queueing disabled */
22631961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ	EDMA_CFG_NCQ		= (1 << 5),
22731961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ	EDMA_CFG_NCQ_GO_ON_ERR	= (1 << 14),		/* continue on error */
22831961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ	EDMA_CFG_RD_BRST_EXT	= (1 << 11),		/* read burst 512B */
22931961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ	EDMA_CFG_WR_BUFF_LEN	= (1 << 13),		/* write buffer 512B */
23020f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ
23120f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ	EDMA_ERR_IRQ_CAUSE_OFS	= 0x8,
23220f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ	EDMA_ERR_IRQ_MASK_OFS	= 0xc,
23320f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ	EDMA_ERR_D_PAR		= (1 << 0),
23420f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ	EDMA_ERR_PRD_PAR	= (1 << 1),
23520f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ	EDMA_ERR_DEV		= (1 << 2),
23620f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ	EDMA_ERR_DEV_DCON	= (1 << 3),
23720f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ	EDMA_ERR_DEV_CON	= (1 << 4),
23820f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ	EDMA_ERR_SERR		= (1 << 5),
23920f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ	EDMA_ERR_SELF_DIS	= (1 << 7),
24020f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ	EDMA_ERR_BIST_ASYNC	= (1 << 8),
24120f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ	EDMA_ERR_CRBQ_PAR	= (1 << 9),
24220f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ	EDMA_ERR_CRPB_PAR	= (1 << 10),
24320f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ	EDMA_ERR_INTRL_PAR	= (1 << 11),
24420f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ	EDMA_ERR_IORDY		= (1 << 12),
24520f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ	EDMA_ERR_LNK_CTRL_RX	= (0xf << 13),
24620f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ	EDMA_ERR_LNK_CTRL_RX_2	= (1 << 15),
24720f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ	EDMA_ERR_LNK_DATA_RX	= (0xf << 17),
24820f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ	EDMA_ERR_LNK_CTRL_TX	= (0x1f << 21),
24920f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ	EDMA_ERR_LNK_DATA_TX	= (0x1f << 26),
25020f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ	EDMA_ERR_TRANS_PROTO	= (1 << 31),
2518b260248d9e0e8b64bb72fd4dee03ad86984c344Jeff Garzik	EDMA_ERR_FATAL		= (EDMA_ERR_D_PAR | EDMA_ERR_PRD_PAR |
25220f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ				   EDMA_ERR_DEV_DCON | EDMA_ERR_CRBQ_PAR |
25320f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ				   EDMA_ERR_CRPB_PAR | EDMA_ERR_INTRL_PAR |
2548b260248d9e0e8b64bb72fd4dee03ad86984c344Jeff Garzik				   EDMA_ERR_IORDY | EDMA_ERR_LNK_CTRL_RX_2 |
25520f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ				   EDMA_ERR_LNK_DATA_RX |
2568b260248d9e0e8b64bb72fd4dee03ad86984c344Jeff Garzik				   EDMA_ERR_LNK_DATA_TX |
25720f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ				   EDMA_ERR_TRANS_PROTO),
25820f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ
25931961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ	EDMA_REQ_Q_BASE_HI_OFS	= 0x10,
26031961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ	EDMA_REQ_Q_IN_PTR_OFS	= 0x14,		/* also contains BASE_LO */
26131961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ
26231961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ	EDMA_REQ_Q_OUT_PTR_OFS	= 0x18,
26331961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ	EDMA_REQ_Q_PTR_SHIFT	= 5,
26431961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ
26531961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ	EDMA_RSP_Q_BASE_HI_OFS	= 0x1c,
26631961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ	EDMA_RSP_Q_IN_PTR_OFS	= 0x20,
26731961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ	EDMA_RSP_Q_OUT_PTR_OFS	= 0x24,		/* also contains BASE_LO */
26831961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ	EDMA_RSP_Q_PTR_SHIFT	= 3,
26931961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ
27020f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ	EDMA_CMD_OFS		= 0x28,
27120f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ	EDMA_EN			= (1 << 0),
27220f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ	EDMA_DS			= (1 << 1),
27320f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ	ATA_RST			= (1 << 2),
27420f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ
275c9d39130123238ac18478a42e25cb7996eacfcc0Jeff Garzik	EDMA_IORDY_TMOUT	= 0x34,
276bca1c4eb9411533d613123618c0d127fae532595Jeff Garzik	EDMA_ARB_CFG		= 0x38,
277bca1c4eb9411533d613123618c0d127fae532595Jeff Garzik
27831961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ	/* Host private flags (hp_flags) */
27931961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ	MV_HP_FLAG_MSI		= (1 << 0),
28047c2b677daeed9c79ecb7167c211ff36876ea611Jeff Garzik	MV_HP_ERRATA_50XXB0	= (1 << 1),
28147c2b677daeed9c79ecb7167c211ff36876ea611Jeff Garzik	MV_HP_ERRATA_50XXB2	= (1 << 2),
28247c2b677daeed9c79ecb7167c211ff36876ea611Jeff Garzik	MV_HP_ERRATA_60X1B2	= (1 << 3),
28347c2b677daeed9c79ecb7167c211ff36876ea611Jeff Garzik	MV_HP_ERRATA_60X1C0	= (1 << 4),
284e4e7b89280d1d666e2c09e5ad36cf071796c4c7eJeff Garzik	MV_HP_ERRATA_XX42A0	= (1 << 5),
285e4e7b89280d1d666e2c09e5ad36cf071796c4c7eJeff Garzik	MV_HP_50XX		= (1 << 6),
286e4e7b89280d1d666e2c09e5ad36cf071796c4c7eJeff Garzik	MV_HP_GEN_IIE		= (1 << 7),
28720f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ
28831961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ	/* Port private flags (pp_flags) */
28931961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ	MV_PP_FLAG_EDMA_EN	= (1 << 0),
29031961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ	MV_PP_FLAG_EDMA_DS_ACT	= (1 << 1),
29120f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ};
29220f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ
293c9d39130123238ac18478a42e25cb7996eacfcc0Jeff Garzik#define IS_50XX(hpriv) ((hpriv)->hp_flags & MV_HP_50XX)
294bca1c4eb9411533d613123618c0d127fae532595Jeff Garzik#define IS_60XX(hpriv) (((hpriv)->hp_flags & MV_HP_50XX) == 0)
295e4e7b89280d1d666e2c09e5ad36cf071796c4c7eJeff Garzik#define IS_GEN_I(hpriv) IS_50XX(hpriv)
296e4e7b89280d1d666e2c09e5ad36cf071796c4c7eJeff Garzik#define IS_GEN_II(hpriv) IS_60XX(hpriv)
297e4e7b89280d1d666e2c09e5ad36cf071796c4c7eJeff Garzik#define IS_GEN_IIE(hpriv) ((hpriv)->hp_flags & MV_HP_GEN_IIE)
298bca1c4eb9411533d613123618c0d127fae532595Jeff Garzik
299095fec887eaa1c38d17c0c929a6733c744a9fa1fJeff Garzikenum {
300d88184fb2348a50f7c34f5d49a901c875b2e0114Jeff Garzik	MV_DMA_BOUNDARY		= 0xffffffffU,
301095fec887eaa1c38d17c0c929a6733c744a9fa1fJeff Garzik
302095fec887eaa1c38d17c0c929a6733c744a9fa1fJeff Garzik	EDMA_REQ_Q_BASE_LO_MASK	= 0xfffffc00U,
303095fec887eaa1c38d17c0c929a6733c744a9fa1fJeff Garzik
304095fec887eaa1c38d17c0c929a6733c744a9fa1fJeff Garzik	EDMA_RSP_Q_BASE_LO_MASK	= 0xffffff00U,
305095fec887eaa1c38d17c0c929a6733c744a9fa1fJeff Garzik};
306095fec887eaa1c38d17c0c929a6733c744a9fa1fJeff Garzik
307522479fb98c6667f081e75f87e298e413c0b1db8Jeff Garzikenum chip_type {
308522479fb98c6667f081e75f87e298e413c0b1db8Jeff Garzik	chip_504x,
309522479fb98c6667f081e75f87e298e413c0b1db8Jeff Garzik	chip_508x,
310522479fb98c6667f081e75f87e298e413c0b1db8Jeff Garzik	chip_5080,
311522479fb98c6667f081e75f87e298e413c0b1db8Jeff Garzik	chip_604x,
312522479fb98c6667f081e75f87e298e413c0b1db8Jeff Garzik	chip_608x,
313e4e7b89280d1d666e2c09e5ad36cf071796c4c7eJeff Garzik	chip_6042,
314e4e7b89280d1d666e2c09e5ad36cf071796c4c7eJeff Garzik	chip_7042,
315522479fb98c6667f081e75f87e298e413c0b1db8Jeff Garzik};
316522479fb98c6667f081e75f87e298e413c0b1db8Jeff Garzik
31731961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ/* Command ReQuest Block: 32B */
31831961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russstruct mv_crqb {
319e14698745dd0de1ddbf5cd0cca4313a90f8c1cc1Mark Lord	__le32			sg_addr;
320e14698745dd0de1ddbf5cd0cca4313a90f8c1cc1Mark Lord	__le32			sg_addr_hi;
321e14698745dd0de1ddbf5cd0cca4313a90f8c1cc1Mark Lord	__le16			ctrl_flags;
322e14698745dd0de1ddbf5cd0cca4313a90f8c1cc1Mark Lord	__le16			ata_cmd[11];
32331961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ};
32420f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ
325e4e7b89280d1d666e2c09e5ad36cf071796c4c7eJeff Garzikstruct mv_crqb_iie {
326e14698745dd0de1ddbf5cd0cca4313a90f8c1cc1Mark Lord	__le32			addr;
327e14698745dd0de1ddbf5cd0cca4313a90f8c1cc1Mark Lord	__le32			addr_hi;
328e14698745dd0de1ddbf5cd0cca4313a90f8c1cc1Mark Lord	__le32			flags;
329e14698745dd0de1ddbf5cd0cca4313a90f8c1cc1Mark Lord	__le32			len;
330e14698745dd0de1ddbf5cd0cca4313a90f8c1cc1Mark Lord	__le32			ata_cmd[4];
331e4e7b89280d1d666e2c09e5ad36cf071796c4c7eJeff Garzik};
332e4e7b89280d1d666e2c09e5ad36cf071796c4c7eJeff Garzik
33331961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ/* Command ResPonse Block: 8B */
33431961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russstruct mv_crpb {
335e14698745dd0de1ddbf5cd0cca4313a90f8c1cc1Mark Lord	__le16			id;
336e14698745dd0de1ddbf5cd0cca4313a90f8c1cc1Mark Lord	__le16			flags;
337e14698745dd0de1ddbf5cd0cca4313a90f8c1cc1Mark Lord	__le32			tmstmp;
33820f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ};
33920f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ
34031961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ/* EDMA Physical Region Descriptor (ePRD); A.K.A. SG */
34131961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russstruct mv_sg {
342e14698745dd0de1ddbf5cd0cca4313a90f8c1cc1Mark Lord	__le32			addr;
343e14698745dd0de1ddbf5cd0cca4313a90f8c1cc1Mark Lord	__le32			flags_size;
344e14698745dd0de1ddbf5cd0cca4313a90f8c1cc1Mark Lord	__le32			addr_hi;
345e14698745dd0de1ddbf5cd0cca4313a90f8c1cc1Mark Lord	__le32			reserved;
34631961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ};
34720f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ
34831961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russstruct mv_port_priv {
34931961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ	struct mv_crqb		*crqb;
35031961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ	dma_addr_t		crqb_dma;
35131961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ	struct mv_crpb		*crpb;
35231961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ	dma_addr_t		crpb_dma;
35331961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ	struct mv_sg		*sg_tbl;
35431961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ	dma_addr_t		sg_tbl_dma;
35531961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ	u32			pp_flags;
35631961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ};
35731961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ
358bca1c4eb9411533d613123618c0d127fae532595Jeff Garzikstruct mv_port_signal {
359bca1c4eb9411533d613123618c0d127fae532595Jeff Garzik	u32			amps;
360bca1c4eb9411533d613123618c0d127fae532595Jeff Garzik	u32			pre;
361bca1c4eb9411533d613123618c0d127fae532595Jeff Garzik};
362bca1c4eb9411533d613123618c0d127fae532595Jeff Garzik
36347c2b677daeed9c79ecb7167c211ff36876ea611Jeff Garzikstruct mv_host_priv;
36447c2b677daeed9c79ecb7167c211ff36876ea611Jeff Garzikstruct mv_hw_ops {
3652a47ce06d534692f9bd2bf4e90a20fc9b1054c39Jeff Garzik	void (*phy_errata)(struct mv_host_priv *hpriv, void __iomem *mmio,
3662a47ce06d534692f9bd2bf4e90a20fc9b1054c39Jeff Garzik			   unsigned int port);
36747c2b677daeed9c79ecb7167c211ff36876ea611Jeff Garzik	void (*enable_leds)(struct mv_host_priv *hpriv, void __iomem *mmio);
36847c2b677daeed9c79ecb7167c211ff36876ea611Jeff Garzik	void (*read_preamp)(struct mv_host_priv *hpriv, int idx,
36947c2b677daeed9c79ecb7167c211ff36876ea611Jeff Garzik			   void __iomem *mmio);
370c9d39130123238ac18478a42e25cb7996eacfcc0Jeff Garzik	int (*reset_hc)(struct mv_host_priv *hpriv, void __iomem *mmio,
371c9d39130123238ac18478a42e25cb7996eacfcc0Jeff Garzik			unsigned int n_hc);
372522479fb98c6667f081e75f87e298e413c0b1db8Jeff Garzik	void (*reset_flash)(struct mv_host_priv *hpriv, void __iomem *mmio);
373522479fb98c6667f081e75f87e298e413c0b1db8Jeff Garzik	void (*reset_bus)(struct pci_dev *pdev, void __iomem *mmio);
37447c2b677daeed9c79ecb7167c211ff36876ea611Jeff Garzik};
37547c2b677daeed9c79ecb7167c211ff36876ea611Jeff Garzik
37631961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russstruct mv_host_priv {
37731961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ	u32			hp_flags;
378bca1c4eb9411533d613123618c0d127fae532595Jeff Garzik	struct mv_port_signal	signal[8];
37947c2b677daeed9c79ecb7167c211ff36876ea611Jeff Garzik	const struct mv_hw_ops	*ops;
38020f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ};
38120f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ
38220f733e7d75a16bffc34842b7682c9247dd5f954Brett Russstatic void mv_irq_clear(struct ata_port *ap);
38320f733e7d75a16bffc34842b7682c9247dd5f954Brett Russstatic u32 mv_scr_read(struct ata_port *ap, unsigned int sc_reg_in);
38420f733e7d75a16bffc34842b7682c9247dd5f954Brett Russstatic void mv_scr_write(struct ata_port *ap, unsigned int sc_reg_in, u32 val);
385c9d39130123238ac18478a42e25cb7996eacfcc0Jeff Garzikstatic u32 mv5_scr_read(struct ata_port *ap, unsigned int sc_reg_in);
386c9d39130123238ac18478a42e25cb7996eacfcc0Jeff Garzikstatic void mv5_scr_write(struct ata_port *ap, unsigned int sc_reg_in, u32 val);
38720f733e7d75a16bffc34842b7682c9247dd5f954Brett Russstatic void mv_phy_reset(struct ata_port *ap);
38822374677d18c5eeefd3a283431d312b8c44fef02Jeff Garzikstatic void __mv_phy_reset(struct ata_port *ap, int can_sleep);
38931961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russstatic int mv_port_start(struct ata_port *ap);
39031961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russstatic void mv_port_stop(struct ata_port *ap);
39131961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russstatic void mv_qc_prep(struct ata_queued_cmd *qc);
392e4e7b89280d1d666e2c09e5ad36cf071796c4c7eJeff Garzikstatic void mv_qc_prep_iie(struct ata_queued_cmd *qc);
3939a3d9eb0177eb10500d49cd283b35576082a522dTejun Heostatic unsigned int mv_qc_issue(struct ata_queued_cmd *qc);
39431961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russstatic void mv_eng_timeout(struct ata_port *ap);
39520f733e7d75a16bffc34842b7682c9247dd5f954Brett Russstatic int mv_init_one(struct pci_dev *pdev, const struct pci_device_id *ent);
39620f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ
3972a47ce06d534692f9bd2bf4e90a20fc9b1054c39Jeff Garzikstatic void mv5_phy_errata(struct mv_host_priv *hpriv, void __iomem *mmio,
3982a47ce06d534692f9bd2bf4e90a20fc9b1054c39Jeff Garzik			   unsigned int port);
39947c2b677daeed9c79ecb7167c211ff36876ea611Jeff Garzikstatic void mv5_enable_leds(struct mv_host_priv *hpriv, void __iomem *mmio);
40047c2b677daeed9c79ecb7167c211ff36876ea611Jeff Garzikstatic void mv5_read_preamp(struct mv_host_priv *hpriv, int idx,
40147c2b677daeed9c79ecb7167c211ff36876ea611Jeff Garzik			   void __iomem *mmio);
402c9d39130123238ac18478a42e25cb7996eacfcc0Jeff Garzikstatic int mv5_reset_hc(struct mv_host_priv *hpriv, void __iomem *mmio,
403c9d39130123238ac18478a42e25cb7996eacfcc0Jeff Garzik			unsigned int n_hc);
404522479fb98c6667f081e75f87e298e413c0b1db8Jeff Garzikstatic void mv5_reset_flash(struct mv_host_priv *hpriv, void __iomem *mmio);
405522479fb98c6667f081e75f87e298e413c0b1db8Jeff Garzikstatic void mv5_reset_bus(struct pci_dev *pdev, void __iomem *mmio);
40647c2b677daeed9c79ecb7167c211ff36876ea611Jeff Garzik
4072a47ce06d534692f9bd2bf4e90a20fc9b1054c39Jeff Garzikstatic void mv6_phy_errata(struct mv_host_priv *hpriv, void __iomem *mmio,
4082a47ce06d534692f9bd2bf4e90a20fc9b1054c39Jeff Garzik			   unsigned int port);
40947c2b677daeed9c79ecb7167c211ff36876ea611Jeff Garzikstatic void mv6_enable_leds(struct mv_host_priv *hpriv, void __iomem *mmio);
41047c2b677daeed9c79ecb7167c211ff36876ea611Jeff Garzikstatic void mv6_read_preamp(struct mv_host_priv *hpriv, int idx,
41147c2b677daeed9c79ecb7167c211ff36876ea611Jeff Garzik			   void __iomem *mmio);
412c9d39130123238ac18478a42e25cb7996eacfcc0Jeff Garzikstatic int mv6_reset_hc(struct mv_host_priv *hpriv, void __iomem *mmio,
413c9d39130123238ac18478a42e25cb7996eacfcc0Jeff Garzik			unsigned int n_hc);
414522479fb98c6667f081e75f87e298e413c0b1db8Jeff Garzikstatic void mv6_reset_flash(struct mv_host_priv *hpriv, void __iomem *mmio);
415522479fb98c6667f081e75f87e298e413c0b1db8Jeff Garzikstatic void mv_reset_pci_bus(struct pci_dev *pdev, void __iomem *mmio);
416c9d39130123238ac18478a42e25cb7996eacfcc0Jeff Garzikstatic void mv_channel_reset(struct mv_host_priv *hpriv, void __iomem *mmio,
417c9d39130123238ac18478a42e25cb7996eacfcc0Jeff Garzik			     unsigned int port_no);
418c9d39130123238ac18478a42e25cb7996eacfcc0Jeff Garzikstatic void mv_stop_and_reset(struct ata_port *ap);
41947c2b677daeed9c79ecb7167c211ff36876ea611Jeff Garzik
420193515d51ccb363165d6b09e9ba5c21089e34badJeff Garzikstatic struct scsi_host_template mv_sht = {
42120f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ	.module			= THIS_MODULE,
42220f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ	.name			= DRV_NAME,
42320f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ	.ioctl			= ata_scsi_ioctl,
42420f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ	.queuecommand		= ata_scsi_queuecmd,
42531961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ	.can_queue		= MV_USE_Q_DEPTH,
42620f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ	.this_id		= ATA_SHT_THIS_ID,
427d88184fb2348a50f7c34f5d49a901c875b2e0114Jeff Garzik	.sg_tablesize		= MV_MAX_SG_CT,
42820f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ	.cmd_per_lun		= ATA_SHT_CMD_PER_LUN,
42920f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ	.emulated		= ATA_SHT_EMULATED,
430d88184fb2348a50f7c34f5d49a901c875b2e0114Jeff Garzik	.use_clustering		= 1,
43120f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ	.proc_name		= DRV_NAME,
43220f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ	.dma_boundary		= MV_DMA_BOUNDARY,
43320f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ	.slave_configure	= ata_scsi_slave_config,
434ccf68c3405fca11386004674377d951b9b18e756Tejun Heo	.slave_destroy		= ata_scsi_slave_destroy,
43520f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ	.bios_param		= ata_std_bios_param,
43620f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ};
43720f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ
438c9d39130123238ac18478a42e25cb7996eacfcc0Jeff Garzikstatic const struct ata_port_operations mv5_ops = {
439c9d39130123238ac18478a42e25cb7996eacfcc0Jeff Garzik	.port_disable		= ata_port_disable,
440c9d39130123238ac18478a42e25cb7996eacfcc0Jeff Garzik
441c9d39130123238ac18478a42e25cb7996eacfcc0Jeff Garzik	.tf_load		= ata_tf_load,
442c9d39130123238ac18478a42e25cb7996eacfcc0Jeff Garzik	.tf_read		= ata_tf_read,
443c9d39130123238ac18478a42e25cb7996eacfcc0Jeff Garzik	.check_status		= ata_check_status,
444c9d39130123238ac18478a42e25cb7996eacfcc0Jeff Garzik	.exec_command		= ata_exec_command,
445c9d39130123238ac18478a42e25cb7996eacfcc0Jeff Garzik	.dev_select		= ata_std_dev_select,
446c9d39130123238ac18478a42e25cb7996eacfcc0Jeff Garzik
447c9d39130123238ac18478a42e25cb7996eacfcc0Jeff Garzik	.phy_reset		= mv_phy_reset,
448cffacd85bcf6fc652292001873119333555fe260Jeff Garzik	.cable_detect		= ata_cable_sata,
449c9d39130123238ac18478a42e25cb7996eacfcc0Jeff Garzik
450c9d39130123238ac18478a42e25cb7996eacfcc0Jeff Garzik	.qc_prep		= mv_qc_prep,
451c9d39130123238ac18478a42e25cb7996eacfcc0Jeff Garzik	.qc_issue		= mv_qc_issue,
4520d5ff566779f894ca9937231a181eb31e4adff0eTejun Heo	.data_xfer		= ata_data_xfer,
453c9d39130123238ac18478a42e25cb7996eacfcc0Jeff Garzik
454c9d39130123238ac18478a42e25cb7996eacfcc0Jeff Garzik	.eng_timeout		= mv_eng_timeout,
455c9d39130123238ac18478a42e25cb7996eacfcc0Jeff Garzik
456c9d39130123238ac18478a42e25cb7996eacfcc0Jeff Garzik	.irq_clear		= mv_irq_clear,
457246ce3b675843e0369643cceb4faeb6cf6d19a30Akira Iguchi	.irq_on			= ata_irq_on,
458246ce3b675843e0369643cceb4faeb6cf6d19a30Akira Iguchi	.irq_ack		= ata_irq_ack,
459c9d39130123238ac18478a42e25cb7996eacfcc0Jeff Garzik
460c9d39130123238ac18478a42e25cb7996eacfcc0Jeff Garzik	.scr_read		= mv5_scr_read,
461c9d39130123238ac18478a42e25cb7996eacfcc0Jeff Garzik	.scr_write		= mv5_scr_write,
462c9d39130123238ac18478a42e25cb7996eacfcc0Jeff Garzik
463c9d39130123238ac18478a42e25cb7996eacfcc0Jeff Garzik	.port_start		= mv_port_start,
464c9d39130123238ac18478a42e25cb7996eacfcc0Jeff Garzik	.port_stop		= mv_port_stop,
465c9d39130123238ac18478a42e25cb7996eacfcc0Jeff Garzik};
466c9d39130123238ac18478a42e25cb7996eacfcc0Jeff Garzik
467c9d39130123238ac18478a42e25cb7996eacfcc0Jeff Garzikstatic const struct ata_port_operations mv6_ops = {
46820f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ	.port_disable		= ata_port_disable,
46920f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ
47020f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ	.tf_load		= ata_tf_load,
47120f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ	.tf_read		= ata_tf_read,
47220f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ	.check_status		= ata_check_status,
47320f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ	.exec_command		= ata_exec_command,
47420f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ	.dev_select		= ata_std_dev_select,
47520f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ
47620f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ	.phy_reset		= mv_phy_reset,
477cffacd85bcf6fc652292001873119333555fe260Jeff Garzik	.cable_detect		= ata_cable_sata,
47820f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ
47931961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ	.qc_prep		= mv_qc_prep,
48031961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ	.qc_issue		= mv_qc_issue,
4810d5ff566779f894ca9937231a181eb31e4adff0eTejun Heo	.data_xfer		= ata_data_xfer,
48220f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ
48331961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ	.eng_timeout		= mv_eng_timeout,
48420f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ
48520f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ	.irq_clear		= mv_irq_clear,
486246ce3b675843e0369643cceb4faeb6cf6d19a30Akira Iguchi	.irq_on			= ata_irq_on,
487246ce3b675843e0369643cceb4faeb6cf6d19a30Akira Iguchi	.irq_ack		= ata_irq_ack,
48820f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ
48920f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ	.scr_read		= mv_scr_read,
49020f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ	.scr_write		= mv_scr_write,
49120f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ
49231961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ	.port_start		= mv_port_start,
49331961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ	.port_stop		= mv_port_stop,
49420f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ};
49520f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ
496e4e7b89280d1d666e2c09e5ad36cf071796c4c7eJeff Garzikstatic const struct ata_port_operations mv_iie_ops = {
497e4e7b89280d1d666e2c09e5ad36cf071796c4c7eJeff Garzik	.port_disable		= ata_port_disable,
498e4e7b89280d1d666e2c09e5ad36cf071796c4c7eJeff Garzik
499e4e7b89280d1d666e2c09e5ad36cf071796c4c7eJeff Garzik	.tf_load		= ata_tf_load,
500e4e7b89280d1d666e2c09e5ad36cf071796c4c7eJeff Garzik	.tf_read		= ata_tf_read,
501e4e7b89280d1d666e2c09e5ad36cf071796c4c7eJeff Garzik	.check_status		= ata_check_status,
502e4e7b89280d1d666e2c09e5ad36cf071796c4c7eJeff Garzik	.exec_command		= ata_exec_command,
503e4e7b89280d1d666e2c09e5ad36cf071796c4c7eJeff Garzik	.dev_select		= ata_std_dev_select,
504e4e7b89280d1d666e2c09e5ad36cf071796c4c7eJeff Garzik
505e4e7b89280d1d666e2c09e5ad36cf071796c4c7eJeff Garzik	.phy_reset		= mv_phy_reset,
506cffacd85bcf6fc652292001873119333555fe260Jeff Garzik	.cable_detect		= ata_cable_sata,
507e4e7b89280d1d666e2c09e5ad36cf071796c4c7eJeff Garzik
508e4e7b89280d1d666e2c09e5ad36cf071796c4c7eJeff Garzik	.qc_prep		= mv_qc_prep_iie,
509e4e7b89280d1d666e2c09e5ad36cf071796c4c7eJeff Garzik	.qc_issue		= mv_qc_issue,
5100d5ff566779f894ca9937231a181eb31e4adff0eTejun Heo	.data_xfer		= ata_data_xfer,
511e4e7b89280d1d666e2c09e5ad36cf071796c4c7eJeff Garzik
512e4e7b89280d1d666e2c09e5ad36cf071796c4c7eJeff Garzik	.eng_timeout		= mv_eng_timeout,
513e4e7b89280d1d666e2c09e5ad36cf071796c4c7eJeff Garzik
514e4e7b89280d1d666e2c09e5ad36cf071796c4c7eJeff Garzik	.irq_clear		= mv_irq_clear,
515246ce3b675843e0369643cceb4faeb6cf6d19a30Akira Iguchi	.irq_on			= ata_irq_on,
516246ce3b675843e0369643cceb4faeb6cf6d19a30Akira Iguchi	.irq_ack		= ata_irq_ack,
517e4e7b89280d1d666e2c09e5ad36cf071796c4c7eJeff Garzik
518e4e7b89280d1d666e2c09e5ad36cf071796c4c7eJeff Garzik	.scr_read		= mv_scr_read,
519e4e7b89280d1d666e2c09e5ad36cf071796c4c7eJeff Garzik	.scr_write		= mv_scr_write,
520e4e7b89280d1d666e2c09e5ad36cf071796c4c7eJeff Garzik
521e4e7b89280d1d666e2c09e5ad36cf071796c4c7eJeff Garzik	.port_start		= mv_port_start,
522e4e7b89280d1d666e2c09e5ad36cf071796c4c7eJeff Garzik	.port_stop		= mv_port_stop,
523e4e7b89280d1d666e2c09e5ad36cf071796c4c7eJeff Garzik};
524e4e7b89280d1d666e2c09e5ad36cf071796c4c7eJeff Garzik
52598ac62defe529d04a192688f40d801a2d8fbcf98Arjan van de Venstatic const struct ata_port_info mv_port_info[] = {
52620f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ	{  /* chip_504x */
527cca3974e48607c3775dc73b544a5700b2e37c21aJeff Garzik		.flags		= MV_COMMON_FLAGS,
52831961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ		.pio_mask	= 0x1f,	/* pio0-4 */
529bf6263a853c9c143bf03f0a6fdcc68ab714fb5f5Jeff Garzik		.udma_mask	= ATA_UDMA6,
530c9d39130123238ac18478a42e25cb7996eacfcc0Jeff Garzik		.port_ops	= &mv5_ops,
53120f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ	},
53220f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ	{  /* chip_508x */
533cca3974e48607c3775dc73b544a5700b2e37c21aJeff Garzik		.flags		= (MV_COMMON_FLAGS | MV_FLAG_DUAL_HC),
53431961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ		.pio_mask	= 0x1f,	/* pio0-4 */
535bf6263a853c9c143bf03f0a6fdcc68ab714fb5f5Jeff Garzik		.udma_mask	= ATA_UDMA6,
536c9d39130123238ac18478a42e25cb7996eacfcc0Jeff Garzik		.port_ops	= &mv5_ops,
53720f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ	},
53847c2b677daeed9c79ecb7167c211ff36876ea611Jeff Garzik	{  /* chip_5080 */
539cca3974e48607c3775dc73b544a5700b2e37c21aJeff Garzik		.flags		= (MV_COMMON_FLAGS | MV_FLAG_DUAL_HC),
54047c2b677daeed9c79ecb7167c211ff36876ea611Jeff Garzik		.pio_mask	= 0x1f,	/* pio0-4 */
541bf6263a853c9c143bf03f0a6fdcc68ab714fb5f5Jeff Garzik		.udma_mask	= ATA_UDMA6,
542c9d39130123238ac18478a42e25cb7996eacfcc0Jeff Garzik		.port_ops	= &mv5_ops,
54347c2b677daeed9c79ecb7167c211ff36876ea611Jeff Garzik	},
54420f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ	{  /* chip_604x */
545cca3974e48607c3775dc73b544a5700b2e37c21aJeff Garzik		.flags		= (MV_COMMON_FLAGS | MV_6XXX_FLAGS),
54631961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ		.pio_mask	= 0x1f,	/* pio0-4 */
547bf6263a853c9c143bf03f0a6fdcc68ab714fb5f5Jeff Garzik		.udma_mask	= ATA_UDMA6,
548c9d39130123238ac18478a42e25cb7996eacfcc0Jeff Garzik		.port_ops	= &mv6_ops,
54920f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ	},
55020f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ	{  /* chip_608x */
551cca3974e48607c3775dc73b544a5700b2e37c21aJeff Garzik		.flags		= (MV_COMMON_FLAGS | MV_6XXX_FLAGS |
55231961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ				   MV_FLAG_DUAL_HC),
55331961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ		.pio_mask	= 0x1f,	/* pio0-4 */
554bf6263a853c9c143bf03f0a6fdcc68ab714fb5f5Jeff Garzik		.udma_mask	= ATA_UDMA6,
555c9d39130123238ac18478a42e25cb7996eacfcc0Jeff Garzik		.port_ops	= &mv6_ops,
55620f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ	},
557e4e7b89280d1d666e2c09e5ad36cf071796c4c7eJeff Garzik	{  /* chip_6042 */
558cca3974e48607c3775dc73b544a5700b2e37c21aJeff Garzik		.flags		= (MV_COMMON_FLAGS | MV_6XXX_FLAGS),
559e4e7b89280d1d666e2c09e5ad36cf071796c4c7eJeff Garzik		.pio_mask	= 0x1f,	/* pio0-4 */
560bf6263a853c9c143bf03f0a6fdcc68ab714fb5f5Jeff Garzik		.udma_mask	= ATA_UDMA6,
561e4e7b89280d1d666e2c09e5ad36cf071796c4c7eJeff Garzik		.port_ops	= &mv_iie_ops,
562e4e7b89280d1d666e2c09e5ad36cf071796c4c7eJeff Garzik	},
563e4e7b89280d1d666e2c09e5ad36cf071796c4c7eJeff Garzik	{  /* chip_7042 */
564e93f09dc2d49d8e98818a93ad17f3ede91533738Olof Johansson		.flags		= (MV_COMMON_FLAGS | MV_6XXX_FLAGS),
565e4e7b89280d1d666e2c09e5ad36cf071796c4c7eJeff Garzik		.pio_mask	= 0x1f,	/* pio0-4 */
566bf6263a853c9c143bf03f0a6fdcc68ab714fb5f5Jeff Garzik		.udma_mask	= ATA_UDMA6,
567e4e7b89280d1d666e2c09e5ad36cf071796c4c7eJeff Garzik		.port_ops	= &mv_iie_ops,
568e4e7b89280d1d666e2c09e5ad36cf071796c4c7eJeff Garzik	},
56920f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ};
57020f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ
5713b7d697dfb7d03edb87e50b743a7ecff029618e9Jeff Garzikstatic const struct pci_device_id mv_pci_tbl[] = {
5722d2744fc8be620a2dc469cf48349e3e704119f1bJeff Garzik	{ PCI_VDEVICE(MARVELL, 0x5040), chip_504x },
5732d2744fc8be620a2dc469cf48349e3e704119f1bJeff Garzik	{ PCI_VDEVICE(MARVELL, 0x5041), chip_504x },
5742d2744fc8be620a2dc469cf48349e3e704119f1bJeff Garzik	{ PCI_VDEVICE(MARVELL, 0x5080), chip_5080 },
5752d2744fc8be620a2dc469cf48349e3e704119f1bJeff Garzik	{ PCI_VDEVICE(MARVELL, 0x5081), chip_508x },
5762d2744fc8be620a2dc469cf48349e3e704119f1bJeff Garzik
5772d2744fc8be620a2dc469cf48349e3e704119f1bJeff Garzik	{ PCI_VDEVICE(MARVELL, 0x6040), chip_604x },
5782d2744fc8be620a2dc469cf48349e3e704119f1bJeff Garzik	{ PCI_VDEVICE(MARVELL, 0x6041), chip_604x },
5792d2744fc8be620a2dc469cf48349e3e704119f1bJeff Garzik	{ PCI_VDEVICE(MARVELL, 0x6042), chip_6042 },
5802d2744fc8be620a2dc469cf48349e3e704119f1bJeff Garzik	{ PCI_VDEVICE(MARVELL, 0x6080), chip_608x },
5812d2744fc8be620a2dc469cf48349e3e704119f1bJeff Garzik	{ PCI_VDEVICE(MARVELL, 0x6081), chip_608x },
5822d2744fc8be620a2dc469cf48349e3e704119f1bJeff Garzik
5832d2744fc8be620a2dc469cf48349e3e704119f1bJeff Garzik	{ PCI_VDEVICE(ADAPTEC2, 0x0241), chip_604x },
5842d2744fc8be620a2dc469cf48349e3e704119f1bJeff Garzik
585d9f9c6bc91c14f53ffa782ffcd42259ecae1d38cFlorian Attenberger	/* Adaptec 1430SA */
586d9f9c6bc91c14f53ffa782ffcd42259ecae1d38cFlorian Attenberger	{ PCI_VDEVICE(ADAPTEC2, 0x0243), chip_7042 },
587d9f9c6bc91c14f53ffa782ffcd42259ecae1d38cFlorian Attenberger
588e93f09dc2d49d8e98818a93ad17f3ede91533738Olof Johansson	{ PCI_VDEVICE(TTI, 0x2310), chip_7042 },
589e93f09dc2d49d8e98818a93ad17f3ede91533738Olof Johansson
5906a3d586d8e8a50e4cfd7f8c36d82a53c5614e05bMorrison, Tom	/* add Marvell 7042 support */
5916a3d586d8e8a50e4cfd7f8c36d82a53c5614e05bMorrison, Tom	{ PCI_VDEVICE(MARVELL, 0x7042), chip_7042 },
5926a3d586d8e8a50e4cfd7f8c36d82a53c5614e05bMorrison, Tom
5932d2744fc8be620a2dc469cf48349e3e704119f1bJeff Garzik	{ }			/* terminate list */
59420f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ};
59520f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ
59620f733e7d75a16bffc34842b7682c9247dd5f954Brett Russstatic struct pci_driver mv_pci_driver = {
59720f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ	.name			= DRV_NAME,
59820f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ	.id_table		= mv_pci_tbl,
59920f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ	.probe			= mv_init_one,
60020f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ	.remove			= ata_pci_remove_one,
60120f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ};
60220f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ
60347c2b677daeed9c79ecb7167c211ff36876ea611Jeff Garzikstatic const struct mv_hw_ops mv5xxx_ops = {
60447c2b677daeed9c79ecb7167c211ff36876ea611Jeff Garzik	.phy_errata		= mv5_phy_errata,
60547c2b677daeed9c79ecb7167c211ff36876ea611Jeff Garzik	.enable_leds		= mv5_enable_leds,
60647c2b677daeed9c79ecb7167c211ff36876ea611Jeff Garzik	.read_preamp		= mv5_read_preamp,
60747c2b677daeed9c79ecb7167c211ff36876ea611Jeff Garzik	.reset_hc		= mv5_reset_hc,
608522479fb98c6667f081e75f87e298e413c0b1db8Jeff Garzik	.reset_flash		= mv5_reset_flash,
609522479fb98c6667f081e75f87e298e413c0b1db8Jeff Garzik	.reset_bus		= mv5_reset_bus,
61047c2b677daeed9c79ecb7167c211ff36876ea611Jeff Garzik};
61147c2b677daeed9c79ecb7167c211ff36876ea611Jeff Garzik
61247c2b677daeed9c79ecb7167c211ff36876ea611Jeff Garzikstatic const struct mv_hw_ops mv6xxx_ops = {
61347c2b677daeed9c79ecb7167c211ff36876ea611Jeff Garzik	.phy_errata		= mv6_phy_errata,
61447c2b677daeed9c79ecb7167c211ff36876ea611Jeff Garzik	.enable_leds		= mv6_enable_leds,
61547c2b677daeed9c79ecb7167c211ff36876ea611Jeff Garzik	.read_preamp		= mv6_read_preamp,
61647c2b677daeed9c79ecb7167c211ff36876ea611Jeff Garzik	.reset_hc		= mv6_reset_hc,
617522479fb98c6667f081e75f87e298e413c0b1db8Jeff Garzik	.reset_flash		= mv6_reset_flash,
618522479fb98c6667f081e75f87e298e413c0b1db8Jeff Garzik	.reset_bus		= mv_reset_pci_bus,
61947c2b677daeed9c79ecb7167c211ff36876ea611Jeff Garzik};
62047c2b677daeed9c79ecb7167c211ff36876ea611Jeff Garzik
62120f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ/*
622ddef9bb367b19383df627e388cb4c01c86ddba6cJeff Garzik * module options
623ddef9bb367b19383df627e388cb4c01c86ddba6cJeff Garzik */
624ddef9bb367b19383df627e388cb4c01c86ddba6cJeff Garzikstatic int msi;	      /* Use PCI msi; either zero (off, default) or non-zero */
625ddef9bb367b19383df627e388cb4c01c86ddba6cJeff Garzik
626ddef9bb367b19383df627e388cb4c01c86ddba6cJeff Garzik
627d88184fb2348a50f7c34f5d49a901c875b2e0114Jeff Garzik/* move to PCI layer or libata core? */
628d88184fb2348a50f7c34f5d49a901c875b2e0114Jeff Garzikstatic int pci_go_64(struct pci_dev *pdev)
629d88184fb2348a50f7c34f5d49a901c875b2e0114Jeff Garzik{
630d88184fb2348a50f7c34f5d49a901c875b2e0114Jeff Garzik	int rc;
631d88184fb2348a50f7c34f5d49a901c875b2e0114Jeff Garzik
632d88184fb2348a50f7c34f5d49a901c875b2e0114Jeff Garzik	if (!pci_set_dma_mask(pdev, DMA_64BIT_MASK)) {
633d88184fb2348a50f7c34f5d49a901c875b2e0114Jeff Garzik		rc = pci_set_consistent_dma_mask(pdev, DMA_64BIT_MASK);
634d88184fb2348a50f7c34f5d49a901c875b2e0114Jeff Garzik		if (rc) {
635d88184fb2348a50f7c34f5d49a901c875b2e0114Jeff Garzik			rc = pci_set_consistent_dma_mask(pdev, DMA_32BIT_MASK);
636d88184fb2348a50f7c34f5d49a901c875b2e0114Jeff Garzik			if (rc) {
637d88184fb2348a50f7c34f5d49a901c875b2e0114Jeff Garzik				dev_printk(KERN_ERR, &pdev->dev,
638d88184fb2348a50f7c34f5d49a901c875b2e0114Jeff Garzik					   "64-bit DMA enable failed\n");
639d88184fb2348a50f7c34f5d49a901c875b2e0114Jeff Garzik				return rc;
640d88184fb2348a50f7c34f5d49a901c875b2e0114Jeff Garzik			}
641d88184fb2348a50f7c34f5d49a901c875b2e0114Jeff Garzik		}
642d88184fb2348a50f7c34f5d49a901c875b2e0114Jeff Garzik	} else {
643d88184fb2348a50f7c34f5d49a901c875b2e0114Jeff Garzik		rc = pci_set_dma_mask(pdev, DMA_32BIT_MASK);
644d88184fb2348a50f7c34f5d49a901c875b2e0114Jeff Garzik		if (rc) {
645d88184fb2348a50f7c34f5d49a901c875b2e0114Jeff Garzik			dev_printk(KERN_ERR, &pdev->dev,
646d88184fb2348a50f7c34f5d49a901c875b2e0114Jeff Garzik				   "32-bit DMA enable failed\n");
647d88184fb2348a50f7c34f5d49a901c875b2e0114Jeff Garzik			return rc;
648d88184fb2348a50f7c34f5d49a901c875b2e0114Jeff Garzik		}
649d88184fb2348a50f7c34f5d49a901c875b2e0114Jeff Garzik		rc = pci_set_consistent_dma_mask(pdev, DMA_32BIT_MASK);
650d88184fb2348a50f7c34f5d49a901c875b2e0114Jeff Garzik		if (rc) {
651d88184fb2348a50f7c34f5d49a901c875b2e0114Jeff Garzik			dev_printk(KERN_ERR, &pdev->dev,
652d88184fb2348a50f7c34f5d49a901c875b2e0114Jeff Garzik				   "32-bit consistent DMA enable failed\n");
653d88184fb2348a50f7c34f5d49a901c875b2e0114Jeff Garzik			return rc;
654d88184fb2348a50f7c34f5d49a901c875b2e0114Jeff Garzik		}
655d88184fb2348a50f7c34f5d49a901c875b2e0114Jeff Garzik	}
656d88184fb2348a50f7c34f5d49a901c875b2e0114Jeff Garzik
657d88184fb2348a50f7c34f5d49a901c875b2e0114Jeff Garzik	return rc;
658d88184fb2348a50f7c34f5d49a901c875b2e0114Jeff Garzik}
659d88184fb2348a50f7c34f5d49a901c875b2e0114Jeff Garzik
660ddef9bb367b19383df627e388cb4c01c86ddba6cJeff Garzik/*
66120f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ * Functions
66220f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ */
66320f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ
66420f733e7d75a16bffc34842b7682c9247dd5f954Brett Russstatic inline void writelfl(unsigned long data, void __iomem *addr)
66520f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ{
66620f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ	writel(data, addr);
66720f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ	(void) readl(addr);	/* flush to avoid PCI posted write */
66820f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ}
66920f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ
67020f733e7d75a16bffc34842b7682c9247dd5f954Brett Russstatic inline void __iomem *mv_hc_base(void __iomem *base, unsigned int hc)
67120f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ{
67220f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ	return (base + MV_SATAHC0_REG_BASE + (hc * MV_SATAHC_REG_SZ));
67320f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ}
67420f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ
675c9d39130123238ac18478a42e25cb7996eacfcc0Jeff Garzikstatic inline unsigned int mv_hc_from_port(unsigned int port)
676c9d39130123238ac18478a42e25cb7996eacfcc0Jeff Garzik{
677c9d39130123238ac18478a42e25cb7996eacfcc0Jeff Garzik	return port >> MV_PORT_HC_SHIFT;
678c9d39130123238ac18478a42e25cb7996eacfcc0Jeff Garzik}
679c9d39130123238ac18478a42e25cb7996eacfcc0Jeff Garzik
680c9d39130123238ac18478a42e25cb7996eacfcc0Jeff Garzikstatic inline unsigned int mv_hardport_from_port(unsigned int port)
681c9d39130123238ac18478a42e25cb7996eacfcc0Jeff Garzik{
682c9d39130123238ac18478a42e25cb7996eacfcc0Jeff Garzik	return port & MV_PORT_MASK;
683c9d39130123238ac18478a42e25cb7996eacfcc0Jeff Garzik}
684c9d39130123238ac18478a42e25cb7996eacfcc0Jeff Garzik
685c9d39130123238ac18478a42e25cb7996eacfcc0Jeff Garzikstatic inline void __iomem *mv_hc_base_from_port(void __iomem *base,
686c9d39130123238ac18478a42e25cb7996eacfcc0Jeff Garzik						 unsigned int port)
687c9d39130123238ac18478a42e25cb7996eacfcc0Jeff Garzik{
688c9d39130123238ac18478a42e25cb7996eacfcc0Jeff Garzik	return mv_hc_base(base, mv_hc_from_port(port));
689c9d39130123238ac18478a42e25cb7996eacfcc0Jeff Garzik}
690c9d39130123238ac18478a42e25cb7996eacfcc0Jeff Garzik
69120f733e7d75a16bffc34842b7682c9247dd5f954Brett Russstatic inline void __iomem *mv_port_base(void __iomem *base, unsigned int port)
69220f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ{
693c9d39130123238ac18478a42e25cb7996eacfcc0Jeff Garzik	return  mv_hc_base_from_port(base, port) +
6948b260248d9e0e8b64bb72fd4dee03ad86984c344Jeff Garzik		MV_SATAHC_ARBTR_REG_SZ +
695c9d39130123238ac18478a42e25cb7996eacfcc0Jeff Garzik		(mv_hardport_from_port(port) * MV_PORT_REG_SZ);
69620f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ}
69720f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ
69820f733e7d75a16bffc34842b7682c9247dd5f954Brett Russstatic inline void __iomem *mv_ap_base(struct ata_port *ap)
69920f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ{
7000d5ff566779f894ca9937231a181eb31e4adff0eTejun Heo	return mv_port_base(ap->host->iomap[MV_PRIMARY_BAR], ap->port_no);
70120f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ}
70220f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ
703cca3974e48607c3775dc73b544a5700b2e37c21aJeff Garzikstatic inline int mv_get_hc_count(unsigned long port_flags)
70431961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ{
705cca3974e48607c3775dc73b544a5700b2e37c21aJeff Garzik	return ((port_flags & MV_FLAG_DUAL_HC) ? 2 : 1);
70631961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ}
70731961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ
70831961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russstatic void mv_irq_clear(struct ata_port *ap)
70920f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ{
71020f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ}
71120f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ
71205b308e1df6d9d673daedb517969241f41278b52Brett Russ/**
71305b308e1df6d9d673daedb517969241f41278b52Brett Russ *      mv_start_dma - Enable eDMA engine
71405b308e1df6d9d673daedb517969241f41278b52Brett Russ *      @base: port base address
71505b308e1df6d9d673daedb517969241f41278b52Brett Russ *      @pp: port private data
71605b308e1df6d9d673daedb517969241f41278b52Brett Russ *
717beec7dbc6ff003bbc94de62b3323519c878fb2acTejun Heo *      Verify the local cache of the eDMA state is accurate with a
718beec7dbc6ff003bbc94de62b3323519c878fb2acTejun Heo *      WARN_ON.
71905b308e1df6d9d673daedb517969241f41278b52Brett Russ *
72005b308e1df6d9d673daedb517969241f41278b52Brett Russ *      LOCKING:
72105b308e1df6d9d673daedb517969241f41278b52Brett Russ *      Inherited from caller.
72205b308e1df6d9d673daedb517969241f41278b52Brett Russ */
723afb0edd922c7ed6e73678730921dfcccebec17e8Brett Russstatic void mv_start_dma(void __iomem *base, struct mv_port_priv *pp)
72420f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ{
725afb0edd922c7ed6e73678730921dfcccebec17e8Brett Russ	if (!(MV_PP_FLAG_EDMA_EN & pp->pp_flags)) {
726afb0edd922c7ed6e73678730921dfcccebec17e8Brett Russ		writelfl(EDMA_EN, base + EDMA_CMD_OFS);
727afb0edd922c7ed6e73678730921dfcccebec17e8Brett Russ		pp->pp_flags |= MV_PP_FLAG_EDMA_EN;
728afb0edd922c7ed6e73678730921dfcccebec17e8Brett Russ	}
729beec7dbc6ff003bbc94de62b3323519c878fb2acTejun Heo	WARN_ON(!(EDMA_EN & readl(base + EDMA_CMD_OFS)));
73020f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ}
73120f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ
73205b308e1df6d9d673daedb517969241f41278b52Brett Russ/**
73305b308e1df6d9d673daedb517969241f41278b52Brett Russ *      mv_stop_dma - Disable eDMA engine
73405b308e1df6d9d673daedb517969241f41278b52Brett Russ *      @ap: ATA channel to manipulate
73505b308e1df6d9d673daedb517969241f41278b52Brett Russ *
736beec7dbc6ff003bbc94de62b3323519c878fb2acTejun Heo *      Verify the local cache of the eDMA state is accurate with a
737beec7dbc6ff003bbc94de62b3323519c878fb2acTejun Heo *      WARN_ON.
73805b308e1df6d9d673daedb517969241f41278b52Brett Russ *
73905b308e1df6d9d673daedb517969241f41278b52Brett Russ *      LOCKING:
74005b308e1df6d9d673daedb517969241f41278b52Brett Russ *      Inherited from caller.
74105b308e1df6d9d673daedb517969241f41278b52Brett Russ */
74231961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russstatic void mv_stop_dma(struct ata_port *ap)
74320f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ{
74431961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ	void __iomem *port_mmio = mv_ap_base(ap);
74531961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ	struct mv_port_priv *pp	= ap->private_data;
74631961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ	u32 reg;
74731961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ	int i;
74831961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ
749afb0edd922c7ed6e73678730921dfcccebec17e8Brett Russ	if (MV_PP_FLAG_EDMA_EN & pp->pp_flags) {
750afb0edd922c7ed6e73678730921dfcccebec17e8Brett Russ		/* Disable EDMA if active.   The disable bit auto clears.
75131961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ		 */
75231961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ		writelfl(EDMA_DS, port_mmio + EDMA_CMD_OFS);
75331961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ		pp->pp_flags &= ~MV_PP_FLAG_EDMA_EN;
754afb0edd922c7ed6e73678730921dfcccebec17e8Brett Russ	} else {
755beec7dbc6ff003bbc94de62b3323519c878fb2acTejun Heo		WARN_ON(EDMA_EN & readl(port_mmio + EDMA_CMD_OFS));
756afb0edd922c7ed6e73678730921dfcccebec17e8Brett Russ  	}
7578b260248d9e0e8b64bb72fd4dee03ad86984c344Jeff Garzik
75831961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ	/* now properly wait for the eDMA to stop */
75931961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ	for (i = 1000; i > 0; i--) {
76031961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ		reg = readl(port_mmio + EDMA_CMD_OFS);
76131961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ		if (!(EDMA_EN & reg)) {
76231961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ			break;
76331961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ		}
76431961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ		udelay(100);
76531961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ	}
76631961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ
76731961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ	if (EDMA_EN & reg) {
768f15a1dafed22d5037e0feea7528e1eeb28a1a7a3Tejun Heo		ata_port_printk(ap, KERN_ERR, "Unable to stop eDMA\n");
769afb0edd922c7ed6e73678730921dfcccebec17e8Brett Russ		/* FIXME: Consider doing a reset here to recover */
77031961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ	}
77120f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ}
77220f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ
7738a70f8dc08dd40b7f8ac77280eaa99a8c6bc46f4Jeff Garzik#ifdef ATA_DEBUG
77431961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russstatic void mv_dump_mem(void __iomem *start, unsigned bytes)
77520f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ{
77631961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ	int b, w;
77731961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ	for (b = 0; b < bytes; ) {
77831961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ		DPRINTK("%p: ", start + b);
77931961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ		for (w = 0; b < bytes && w < 4; w++) {
78031961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ			printk("%08x ",readl(start + b));
78131961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ			b += sizeof(u32);
78231961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ		}
78331961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ		printk("\n");
78431961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ	}
78531961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ}
7868a70f8dc08dd40b7f8ac77280eaa99a8c6bc46f4Jeff Garzik#endif
7878a70f8dc08dd40b7f8ac77280eaa99a8c6bc46f4Jeff Garzik
78831961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russstatic void mv_dump_pci_cfg(struct pci_dev *pdev, unsigned bytes)
78931961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ{
79031961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ#ifdef ATA_DEBUG
79131961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ	int b, w;
79231961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ	u32 dw;
79331961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ	for (b = 0; b < bytes; ) {
79431961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ		DPRINTK("%02x: ", b);
79531961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ		for (w = 0; b < bytes && w < 4; w++) {
79631961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ			(void) pci_read_config_dword(pdev,b,&dw);
79731961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ			printk("%08x ",dw);
79831961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ			b += sizeof(u32);
79931961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ		}
80031961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ		printk("\n");
80131961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ	}
80231961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ#endif
80331961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ}
80431961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russstatic void mv_dump_all_regs(void __iomem *mmio_base, int port,
80531961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ			     struct pci_dev *pdev)
80631961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ{
80731961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ#ifdef ATA_DEBUG
8088b260248d9e0e8b64bb72fd4dee03ad86984c344Jeff Garzik	void __iomem *hc_base = mv_hc_base(mmio_base,
80931961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ					   port >> MV_PORT_HC_SHIFT);
81031961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ	void __iomem *port_base;
81131961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ	int start_port, num_ports, p, start_hc, num_hcs, hc;
81231961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ
81331961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ	if (0 > port) {
81431961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ		start_hc = start_port = 0;
81531961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ		num_ports = 8;		/* shld be benign for 4 port devs */
81631961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ		num_hcs = 2;
81731961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ	} else {
81831961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ		start_hc = port >> MV_PORT_HC_SHIFT;
81931961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ		start_port = port;
82031961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ		num_ports = num_hcs = 1;
82131961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ	}
8228b260248d9e0e8b64bb72fd4dee03ad86984c344Jeff Garzik	DPRINTK("All registers for port(s) %u-%u:\n", start_port,
82331961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ		num_ports > 1 ? num_ports - 1 : start_port);
82431961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ
82531961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ	if (NULL != pdev) {
82631961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ		DPRINTK("PCI config space regs:\n");
82731961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ		mv_dump_pci_cfg(pdev, 0x68);
82831961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ	}
82931961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ	DPRINTK("PCI regs:\n");
83031961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ	mv_dump_mem(mmio_base+0xc00, 0x3c);
83131961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ	mv_dump_mem(mmio_base+0xd00, 0x34);
83231961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ	mv_dump_mem(mmio_base+0xf00, 0x4);
83331961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ	mv_dump_mem(mmio_base+0x1d00, 0x6c);
83431961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ	for (hc = start_hc; hc < start_hc + num_hcs; hc++) {
835d220c37e0a3c9a47ae00e87e044d963b3ea040bcDan Aloni		hc_base = mv_hc_base(mmio_base, hc);
83631961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ		DPRINTK("HC regs (HC %i):\n", hc);
83731961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ		mv_dump_mem(hc_base, 0x1c);
83831961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ	}
83931961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ	for (p = start_port; p < start_port + num_ports; p++) {
84031961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ		port_base = mv_port_base(mmio_base, p);
84131961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ		DPRINTK("EDMA regs (port %i):\n",p);
84231961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ		mv_dump_mem(port_base, 0x54);
84331961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ		DPRINTK("SATA regs (port %i):\n",p);
84431961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ		mv_dump_mem(port_base+0x300, 0x60);
84531961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ	}
84631961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ#endif
84720f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ}
84820f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ
84920f733e7d75a16bffc34842b7682c9247dd5f954Brett Russstatic unsigned int mv_scr_offset(unsigned int sc_reg_in)
85020f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ{
85120f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ	unsigned int ofs;
85220f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ
85320f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ	switch (sc_reg_in) {
85420f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ	case SCR_STATUS:
85520f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ	case SCR_CONTROL:
85620f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ	case SCR_ERROR:
85720f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ		ofs = SATA_STATUS_OFS + (sc_reg_in * sizeof(u32));
85820f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ		break;
85920f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ	case SCR_ACTIVE:
86020f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ		ofs = SATA_ACTIVE_OFS;   /* active is not with the others */
86120f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ		break;
86220f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ	default:
86320f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ		ofs = 0xffffffffU;
86420f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ		break;
86520f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ	}
86620f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ	return ofs;
86720f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ}
86820f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ
86920f733e7d75a16bffc34842b7682c9247dd5f954Brett Russstatic u32 mv_scr_read(struct ata_port *ap, unsigned int sc_reg_in)
87020f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ{
87120f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ	unsigned int ofs = mv_scr_offset(sc_reg_in);
87220f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ
873351772658a4d1acc0221a6e30676bb0594e74812Jeff Garzik	if (0xffffffffU != ofs)
87420f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ		return readl(mv_ap_base(ap) + ofs);
875351772658a4d1acc0221a6e30676bb0594e74812Jeff Garzik	else
87620f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ		return (u32) ofs;
87720f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ}
87820f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ
87920f733e7d75a16bffc34842b7682c9247dd5f954Brett Russstatic void mv_scr_write(struct ata_port *ap, unsigned int sc_reg_in, u32 val)
88020f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ{
88120f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ	unsigned int ofs = mv_scr_offset(sc_reg_in);
88220f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ
883351772658a4d1acc0221a6e30676bb0594e74812Jeff Garzik	if (0xffffffffU != ofs)
88420f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ		writelfl(val, mv_ap_base(ap) + ofs);
88520f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ}
88620f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ
887e4e7b89280d1d666e2c09e5ad36cf071796c4c7eJeff Garzikstatic void mv_edma_cfg(struct mv_host_priv *hpriv, void __iomem *port_mmio)
888e4e7b89280d1d666e2c09e5ad36cf071796c4c7eJeff Garzik{
889e4e7b89280d1d666e2c09e5ad36cf071796c4c7eJeff Garzik	u32 cfg = readl(port_mmio + EDMA_CFG_OFS);
890e4e7b89280d1d666e2c09e5ad36cf071796c4c7eJeff Garzik
891e4e7b89280d1d666e2c09e5ad36cf071796c4c7eJeff Garzik	/* set up non-NCQ EDMA configuration */
892e4e7b89280d1d666e2c09e5ad36cf071796c4c7eJeff Garzik	cfg &= ~(1 << 9);	/* disable equeue */
893e4e7b89280d1d666e2c09e5ad36cf071796c4c7eJeff Garzik
894e728eabea110da90e69c05855e3a11174edb77efJeff Garzik	if (IS_GEN_I(hpriv)) {
895e728eabea110da90e69c05855e3a11174edb77efJeff Garzik		cfg &= ~0x1f;		/* clear queue depth */
896e4e7b89280d1d666e2c09e5ad36cf071796c4c7eJeff Garzik		cfg |= (1 << 8);	/* enab config burst size mask */
897e728eabea110da90e69c05855e3a11174edb77efJeff Garzik	}
898e4e7b89280d1d666e2c09e5ad36cf071796c4c7eJeff Garzik
899e728eabea110da90e69c05855e3a11174edb77efJeff Garzik	else if (IS_GEN_II(hpriv)) {
900e728eabea110da90e69c05855e3a11174edb77efJeff Garzik		cfg &= ~0x1f;		/* clear queue depth */
901e4e7b89280d1d666e2c09e5ad36cf071796c4c7eJeff Garzik		cfg |= EDMA_CFG_RD_BRST_EXT | EDMA_CFG_WR_BUFF_LEN;
902e728eabea110da90e69c05855e3a11174edb77efJeff Garzik		cfg &= ~(EDMA_CFG_NCQ | EDMA_CFG_NCQ_GO_ON_ERR); /* clear NCQ */
903e728eabea110da90e69c05855e3a11174edb77efJeff Garzik	}
904e4e7b89280d1d666e2c09e5ad36cf071796c4c7eJeff Garzik
905e4e7b89280d1d666e2c09e5ad36cf071796c4c7eJeff Garzik	else if (IS_GEN_IIE(hpriv)) {
906e728eabea110da90e69c05855e3a11174edb77efJeff Garzik		cfg |= (1 << 23);	/* do not mask PM field in rx'd FIS */
907e728eabea110da90e69c05855e3a11174edb77efJeff Garzik		cfg |= (1 << 22);	/* enab 4-entry host queue cache */
908e4e7b89280d1d666e2c09e5ad36cf071796c4c7eJeff Garzik		cfg &= ~(1 << 19);	/* dis 128-entry queue (for now?) */
909e4e7b89280d1d666e2c09e5ad36cf071796c4c7eJeff Garzik		cfg |= (1 << 18);	/* enab early completion */
910e728eabea110da90e69c05855e3a11174edb77efJeff Garzik		cfg |= (1 << 17);	/* enab cut-through (dis stor&forwrd) */
911e728eabea110da90e69c05855e3a11174edb77efJeff Garzik		cfg &= ~(1 << 16);	/* dis FIS-based switching (for now) */
912e728eabea110da90e69c05855e3a11174edb77efJeff Garzik		cfg &= ~(EDMA_CFG_NCQ | EDMA_CFG_NCQ_GO_ON_ERR); /* clear NCQ */
913e4e7b89280d1d666e2c09e5ad36cf071796c4c7eJeff Garzik	}
914e4e7b89280d1d666e2c09e5ad36cf071796c4c7eJeff Garzik
915e4e7b89280d1d666e2c09e5ad36cf071796c4c7eJeff Garzik	writelfl(cfg, port_mmio + EDMA_CFG_OFS);
916e4e7b89280d1d666e2c09e5ad36cf071796c4c7eJeff Garzik}
917e4e7b89280d1d666e2c09e5ad36cf071796c4c7eJeff Garzik
91805b308e1df6d9d673daedb517969241f41278b52Brett Russ/**
91905b308e1df6d9d673daedb517969241f41278b52Brett Russ *      mv_port_start - Port specific init/start routine.
92005b308e1df6d9d673daedb517969241f41278b52Brett Russ *      @ap: ATA channel to manipulate
92105b308e1df6d9d673daedb517969241f41278b52Brett Russ *
92205b308e1df6d9d673daedb517969241f41278b52Brett Russ *      Allocate and point to DMA memory, init port private memory,
92305b308e1df6d9d673daedb517969241f41278b52Brett Russ *      zero indices.
92405b308e1df6d9d673daedb517969241f41278b52Brett Russ *
92505b308e1df6d9d673daedb517969241f41278b52Brett Russ *      LOCKING:
92605b308e1df6d9d673daedb517969241f41278b52Brett Russ *      Inherited from caller.
92705b308e1df6d9d673daedb517969241f41278b52Brett Russ */
92831961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russstatic int mv_port_start(struct ata_port *ap)
92931961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ{
930cca3974e48607c3775dc73b544a5700b2e37c21aJeff Garzik	struct device *dev = ap->host->dev;
931cca3974e48607c3775dc73b544a5700b2e37c21aJeff Garzik	struct mv_host_priv *hpriv = ap->host->private_data;
93231961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ	struct mv_port_priv *pp;
93331961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ	void __iomem *port_mmio = mv_ap_base(ap);
93431961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ	void *mem;
93531961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ	dma_addr_t mem_dma;
93624dc5f33ea4b504cfbd23fa159a4cacba8e4d800Tejun Heo	int rc;
93731961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ
93824dc5f33ea4b504cfbd23fa159a4cacba8e4d800Tejun Heo	pp = devm_kzalloc(dev, sizeof(*pp), GFP_KERNEL);
9396037d6bbdff65eb5a84fe35e140f4da4f7cc103aJeff Garzik	if (!pp)
94024dc5f33ea4b504cfbd23fa159a4cacba8e4d800Tejun Heo		return -ENOMEM;
94131961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ
94224dc5f33ea4b504cfbd23fa159a4cacba8e4d800Tejun Heo	mem = dmam_alloc_coherent(dev, MV_PORT_PRIV_DMA_SZ, &mem_dma,
94324dc5f33ea4b504cfbd23fa159a4cacba8e4d800Tejun Heo				  GFP_KERNEL);
9446037d6bbdff65eb5a84fe35e140f4da4f7cc103aJeff Garzik	if (!mem)
94524dc5f33ea4b504cfbd23fa159a4cacba8e4d800Tejun Heo		return -ENOMEM;
94631961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ	memset(mem, 0, MV_PORT_PRIV_DMA_SZ);
94731961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ
9486037d6bbdff65eb5a84fe35e140f4da4f7cc103aJeff Garzik	rc = ata_pad_alloc(ap, dev);
9496037d6bbdff65eb5a84fe35e140f4da4f7cc103aJeff Garzik	if (rc)
95024dc5f33ea4b504cfbd23fa159a4cacba8e4d800Tejun Heo		return rc;
9516037d6bbdff65eb5a84fe35e140f4da4f7cc103aJeff Garzik
9528b260248d9e0e8b64bb72fd4dee03ad86984c344Jeff Garzik	/* First item in chunk of DMA memory:
95331961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ	 * 32-slot command request table (CRQB), 32 bytes each in size
95431961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ	 */
95531961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ	pp->crqb = mem;
95631961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ	pp->crqb_dma = mem_dma;
95731961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ	mem += MV_CRQB_Q_SZ;
95831961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ	mem_dma += MV_CRQB_Q_SZ;
95931961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ
9608b260248d9e0e8b64bb72fd4dee03ad86984c344Jeff Garzik	/* Second item:
96131961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ	 * 32-slot command response table (CRPB), 8 bytes each in size
96231961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ	 */
96331961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ	pp->crpb = mem;
96431961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ	pp->crpb_dma = mem_dma;
96531961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ	mem += MV_CRPB_Q_SZ;
96631961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ	mem_dma += MV_CRPB_Q_SZ;
96731961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ
96831961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ	/* Third item:
96931961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ	 * Table of scatter-gather descriptors (ePRD), 16 bytes each
97031961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ	 */
97131961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ	pp->sg_tbl = mem;
97231961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ	pp->sg_tbl_dma = mem_dma;
97331961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ
974e4e7b89280d1d666e2c09e5ad36cf071796c4c7eJeff Garzik	mv_edma_cfg(hpriv, port_mmio);
97531961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ
97631961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ	writel((pp->crqb_dma >> 16) >> 16, port_mmio + EDMA_REQ_Q_BASE_HI_OFS);
9778b260248d9e0e8b64bb72fd4dee03ad86984c344Jeff Garzik	writelfl(pp->crqb_dma & EDMA_REQ_Q_BASE_LO_MASK,
97831961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ		 port_mmio + EDMA_REQ_Q_IN_PTR_OFS);
97931961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ
980e4e7b89280d1d666e2c09e5ad36cf071796c4c7eJeff Garzik	if (hpriv->hp_flags & MV_HP_ERRATA_XX42A0)
981e4e7b89280d1d666e2c09e5ad36cf071796c4c7eJeff Garzik		writelfl(pp->crqb_dma & 0xffffffff,
982e4e7b89280d1d666e2c09e5ad36cf071796c4c7eJeff Garzik			 port_mmio + EDMA_REQ_Q_OUT_PTR_OFS);
983e4e7b89280d1d666e2c09e5ad36cf071796c4c7eJeff Garzik	else
984e4e7b89280d1d666e2c09e5ad36cf071796c4c7eJeff Garzik		writelfl(0, port_mmio + EDMA_REQ_Q_OUT_PTR_OFS);
98531961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ
98631961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ	writel((pp->crpb_dma >> 16) >> 16, port_mmio + EDMA_RSP_Q_BASE_HI_OFS);
987e4e7b89280d1d666e2c09e5ad36cf071796c4c7eJeff Garzik
988e4e7b89280d1d666e2c09e5ad36cf071796c4c7eJeff Garzik	if (hpriv->hp_flags & MV_HP_ERRATA_XX42A0)
989e4e7b89280d1d666e2c09e5ad36cf071796c4c7eJeff Garzik		writelfl(pp->crpb_dma & 0xffffffff,
990e4e7b89280d1d666e2c09e5ad36cf071796c4c7eJeff Garzik			 port_mmio + EDMA_RSP_Q_IN_PTR_OFS);
991e4e7b89280d1d666e2c09e5ad36cf071796c4c7eJeff Garzik	else
992e4e7b89280d1d666e2c09e5ad36cf071796c4c7eJeff Garzik		writelfl(0, port_mmio + EDMA_RSP_Q_IN_PTR_OFS);
993e4e7b89280d1d666e2c09e5ad36cf071796c4c7eJeff Garzik
9948b260248d9e0e8b64bb72fd4dee03ad86984c344Jeff Garzik	writelfl(pp->crpb_dma & EDMA_RSP_Q_BASE_LO_MASK,
99531961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ		 port_mmio + EDMA_RSP_Q_OUT_PTR_OFS);
99631961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ
99731961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ	/* Don't turn on EDMA here...do it before DMA commands only.  Else
99831961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ	 * we'll be unable to send non-data, PIO, etc due to restricted access
99931961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ	 * to shadow regs.
100031961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ	 */
100131961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ	ap->private_data = pp;
100231961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ	return 0;
100331961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ}
100431961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ
100505b308e1df6d9d673daedb517969241f41278b52Brett Russ/**
100605b308e1df6d9d673daedb517969241f41278b52Brett Russ *      mv_port_stop - Port specific cleanup/stop routine.
100705b308e1df6d9d673daedb517969241f41278b52Brett Russ *      @ap: ATA channel to manipulate
100805b308e1df6d9d673daedb517969241f41278b52Brett Russ *
100905b308e1df6d9d673daedb517969241f41278b52Brett Russ *      Stop DMA, cleanup port memory.
101005b308e1df6d9d673daedb517969241f41278b52Brett Russ *
101105b308e1df6d9d673daedb517969241f41278b52Brett Russ *      LOCKING:
1012cca3974e48607c3775dc73b544a5700b2e37c21aJeff Garzik *      This routine uses the host lock to protect the DMA stop.
101305b308e1df6d9d673daedb517969241f41278b52Brett Russ */
101431961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russstatic void mv_port_stop(struct ata_port *ap)
101531961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ{
1016afb0edd922c7ed6e73678730921dfcccebec17e8Brett Russ	unsigned long flags;
101731961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ
1018cca3974e48607c3775dc73b544a5700b2e37c21aJeff Garzik	spin_lock_irqsave(&ap->host->lock, flags);
101931961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ	mv_stop_dma(ap);
1020cca3974e48607c3775dc73b544a5700b2e37c21aJeff Garzik	spin_unlock_irqrestore(&ap->host->lock, flags);
102131961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ}
102231961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ
102305b308e1df6d9d673daedb517969241f41278b52Brett Russ/**
102405b308e1df6d9d673daedb517969241f41278b52Brett Russ *      mv_fill_sg - Fill out the Marvell ePRD (scatter gather) entries
102505b308e1df6d9d673daedb517969241f41278b52Brett Russ *      @qc: queued command whose SG list to source from
102605b308e1df6d9d673daedb517969241f41278b52Brett Russ *
102705b308e1df6d9d673daedb517969241f41278b52Brett Russ *      Populate the SG list and mark the last entry.
102805b308e1df6d9d673daedb517969241f41278b52Brett Russ *
102905b308e1df6d9d673daedb517969241f41278b52Brett Russ *      LOCKING:
103005b308e1df6d9d673daedb517969241f41278b52Brett Russ *      Inherited from caller.
103105b308e1df6d9d673daedb517969241f41278b52Brett Russ */
1032d88184fb2348a50f7c34f5d49a901c875b2e0114Jeff Garzikstatic unsigned int mv_fill_sg(struct ata_queued_cmd *qc)
103331961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ{
103431961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ	struct mv_port_priv *pp = qc->ap->private_data;
1035d88184fb2348a50f7c34f5d49a901c875b2e0114Jeff Garzik	unsigned int n_sg = 0;
1036972c26bdd6b58e7534473c4f7928584578cf43f4Jeff Garzik	struct scatterlist *sg;
1037d88184fb2348a50f7c34f5d49a901c875b2e0114Jeff Garzik	struct mv_sg *mv_sg;
103831961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ
1039d88184fb2348a50f7c34f5d49a901c875b2e0114Jeff Garzik	mv_sg = pp->sg_tbl;
1040972c26bdd6b58e7534473c4f7928584578cf43f4Jeff Garzik	ata_for_each_sg(sg, qc) {
1041d88184fb2348a50f7c34f5d49a901c875b2e0114Jeff Garzik		dma_addr_t addr = sg_dma_address(sg);
1042d88184fb2348a50f7c34f5d49a901c875b2e0114Jeff Garzik		u32 sg_len = sg_dma_len(sg);
104322374677d18c5eeefd3a283431d312b8c44fef02Jeff Garzik
1044d88184fb2348a50f7c34f5d49a901c875b2e0114Jeff Garzik		mv_sg->addr = cpu_to_le32(addr & 0xffffffff);
1045d88184fb2348a50f7c34f5d49a901c875b2e0114Jeff Garzik		mv_sg->addr_hi = cpu_to_le32((addr >> 16) >> 16);
1046d88184fb2348a50f7c34f5d49a901c875b2e0114Jeff Garzik		mv_sg->flags_size = cpu_to_le32(sg_len & 0xffff);
104722374677d18c5eeefd3a283431d312b8c44fef02Jeff Garzik
1048d88184fb2348a50f7c34f5d49a901c875b2e0114Jeff Garzik		if (ata_sg_is_last(sg, qc))
1049d88184fb2348a50f7c34f5d49a901c875b2e0114Jeff Garzik			mv_sg->flags_size |= cpu_to_le32(EPRD_FLAG_END_OF_TBL);
105022374677d18c5eeefd3a283431d312b8c44fef02Jeff Garzik
1051d88184fb2348a50f7c34f5d49a901c875b2e0114Jeff Garzik		mv_sg++;
1052d88184fb2348a50f7c34f5d49a901c875b2e0114Jeff Garzik		n_sg++;
105331961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ	}
1054d88184fb2348a50f7c34f5d49a901c875b2e0114Jeff Garzik
1055d88184fb2348a50f7c34f5d49a901c875b2e0114Jeff Garzik	return n_sg;
105631961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ}
105731961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ
1058a6432436c5e14b416f27c8f87c5bf0bc36771f49Mark Lordstatic inline unsigned mv_inc_q_index(unsigned index)
105931961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ{
1060a6432436c5e14b416f27c8f87c5bf0bc36771f49Mark Lord	return (index + 1) & MV_MAX_Q_DEPTH_MASK;
106131961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ}
106231961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ
1063e14698745dd0de1ddbf5cd0cca4313a90f8c1cc1Mark Lordstatic inline void mv_crqb_pack_cmd(__le16 *cmdw, u8 data, u8 addr, unsigned last)
106431961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ{
1065559eedad7f7764dacca33980127b4615011230e4Mark Lord	u16 tmp = data | (addr << CRQB_CMD_ADDR_SHIFT) | CRQB_CMD_CS |
106631961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ		(last ? CRQB_CMD_LAST : 0);
1067559eedad7f7764dacca33980127b4615011230e4Mark Lord	*cmdw = cpu_to_le16(tmp);
106831961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ}
106931961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ
107005b308e1df6d9d673daedb517969241f41278b52Brett Russ/**
107105b308e1df6d9d673daedb517969241f41278b52Brett Russ *      mv_qc_prep - Host specific command preparation.
107205b308e1df6d9d673daedb517969241f41278b52Brett Russ *      @qc: queued command to prepare
107305b308e1df6d9d673daedb517969241f41278b52Brett Russ *
107405b308e1df6d9d673daedb517969241f41278b52Brett Russ *      This routine simply redirects to the general purpose routine
107505b308e1df6d9d673daedb517969241f41278b52Brett Russ *      if command is not DMA.  Else, it handles prep of the CRQB
107605b308e1df6d9d673daedb517969241f41278b52Brett Russ *      (command request block), does some sanity checking, and calls
107705b308e1df6d9d673daedb517969241f41278b52Brett Russ *      the SG load routine.
107805b308e1df6d9d673daedb517969241f41278b52Brett Russ *
107905b308e1df6d9d673daedb517969241f41278b52Brett Russ *      LOCKING:
108005b308e1df6d9d673daedb517969241f41278b52Brett Russ *      Inherited from caller.
108105b308e1df6d9d673daedb517969241f41278b52Brett Russ */
108231961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russstatic void mv_qc_prep(struct ata_queued_cmd *qc)
108331961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ{
108431961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ	struct ata_port *ap = qc->ap;
108531961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ	struct mv_port_priv *pp = ap->private_data;
1086e14698745dd0de1ddbf5cd0cca4313a90f8c1cc1Mark Lord	__le16 *cw;
108731961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ	struct ata_taskfile *tf;
108831961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ	u16 flags = 0;
1089a6432436c5e14b416f27c8f87c5bf0bc36771f49Mark Lord	unsigned in_index;
109031961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ
1091e4e7b89280d1d666e2c09e5ad36cf071796c4c7eJeff Garzik 	if (ATA_PROT_DMA != qc->tf.protocol)
109231961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ		return;
109320f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ
109431961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ	/* Fill in command request block
109531961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ	 */
1096e4e7b89280d1d666e2c09e5ad36cf071796c4c7eJeff Garzik	if (!(qc->tf.flags & ATA_TFLAG_WRITE))
109731961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ		flags |= CRQB_FLAG_READ;
1098beec7dbc6ff003bbc94de62b3323519c878fb2acTejun Heo	WARN_ON(MV_MAX_Q_DEPTH <= qc->tag);
109931961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ	flags |= qc->tag << CRQB_TAG_SHIFT;
110031961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ
1101a6432436c5e14b416f27c8f87c5bf0bc36771f49Mark Lord	/* get current queue index from hardware */
1102a6432436c5e14b416f27c8f87c5bf0bc36771f49Mark Lord	in_index = (readl(mv_ap_base(ap) + EDMA_REQ_Q_IN_PTR_OFS)
1103a6432436c5e14b416f27c8f87c5bf0bc36771f49Mark Lord			>> EDMA_REQ_Q_PTR_SHIFT) & MV_MAX_Q_DEPTH_MASK;
1104a6432436c5e14b416f27c8f87c5bf0bc36771f49Mark Lord
1105a6432436c5e14b416f27c8f87c5bf0bc36771f49Mark Lord	pp->crqb[in_index].sg_addr =
110631961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ		cpu_to_le32(pp->sg_tbl_dma & 0xffffffff);
1107a6432436c5e14b416f27c8f87c5bf0bc36771f49Mark Lord	pp->crqb[in_index].sg_addr_hi =
110831961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ		cpu_to_le32((pp->sg_tbl_dma >> 16) >> 16);
1109a6432436c5e14b416f27c8f87c5bf0bc36771f49Mark Lord	pp->crqb[in_index].ctrl_flags = cpu_to_le16(flags);
111031961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ
1111a6432436c5e14b416f27c8f87c5bf0bc36771f49Mark Lord	cw = &pp->crqb[in_index].ata_cmd[0];
111231961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ	tf = &qc->tf;
111331961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ
111431961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ	/* Sadly, the CRQB cannot accomodate all registers--there are
111531961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ	 * only 11 bytes...so we must pick and choose required
111631961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ	 * registers based on the command.  So, we drop feature and
111731961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ	 * hob_feature for [RW] DMA commands, but they are needed for
111831961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ	 * NCQ.  NCQ will drop hob_nsect.
111920f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ	 */
112031961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ	switch (tf->command) {
112131961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ	case ATA_CMD_READ:
112231961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ	case ATA_CMD_READ_EXT:
112331961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ	case ATA_CMD_WRITE:
112431961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ	case ATA_CMD_WRITE_EXT:
1125c15d85c8f3f73b5f20aae7928e25b6996f16b328Jens Axboe	case ATA_CMD_WRITE_FUA_EXT:
112631961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ		mv_crqb_pack_cmd(cw++, tf->hob_nsect, ATA_REG_NSECT, 0);
112731961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ		break;
112831961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ#ifdef LIBATA_NCQ		/* FIXME: remove this line when NCQ added */
112931961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ	case ATA_CMD_FPDMA_READ:
113031961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ	case ATA_CMD_FPDMA_WRITE:
11318b260248d9e0e8b64bb72fd4dee03ad86984c344Jeff Garzik		mv_crqb_pack_cmd(cw++, tf->hob_feature, ATA_REG_FEATURE, 0);
113231961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ		mv_crqb_pack_cmd(cw++, tf->feature, ATA_REG_FEATURE, 0);
113331961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ		break;
113431961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ#endif				/* FIXME: remove this line when NCQ added */
113531961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ	default:
113631961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ		/* The only other commands EDMA supports in non-queued and
113731961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ		 * non-NCQ mode are: [RW] STREAM DMA and W DMA FUA EXT, none
113831961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ		 * of which are defined/used by Linux.  If we get here, this
113931961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ		 * driver needs work.
114031961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ		 *
114131961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ		 * FIXME: modify libata to give qc_prep a return value and
114231961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ		 * return error here.
114331961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ		 */
114431961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ		BUG_ON(tf->command);
114531961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ		break;
114631961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ	}
114731961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ	mv_crqb_pack_cmd(cw++, tf->nsect, ATA_REG_NSECT, 0);
114831961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ	mv_crqb_pack_cmd(cw++, tf->hob_lbal, ATA_REG_LBAL, 0);
114931961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ	mv_crqb_pack_cmd(cw++, tf->lbal, ATA_REG_LBAL, 0);
115031961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ	mv_crqb_pack_cmd(cw++, tf->hob_lbam, ATA_REG_LBAM, 0);
115131961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ	mv_crqb_pack_cmd(cw++, tf->lbam, ATA_REG_LBAM, 0);
115231961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ	mv_crqb_pack_cmd(cw++, tf->hob_lbah, ATA_REG_LBAH, 0);
115331961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ	mv_crqb_pack_cmd(cw++, tf->lbah, ATA_REG_LBAH, 0);
115431961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ	mv_crqb_pack_cmd(cw++, tf->device, ATA_REG_DEVICE, 0);
115531961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ	mv_crqb_pack_cmd(cw++, tf->command, ATA_REG_CMD, 1);	/* last */
115631961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ
1157e4e7b89280d1d666e2c09e5ad36cf071796c4c7eJeff Garzik	if (!(qc->flags & ATA_QCFLAG_DMAMAP))
1158e4e7b89280d1d666e2c09e5ad36cf071796c4c7eJeff Garzik		return;
1159e4e7b89280d1d666e2c09e5ad36cf071796c4c7eJeff Garzik	mv_fill_sg(qc);
1160e4e7b89280d1d666e2c09e5ad36cf071796c4c7eJeff Garzik}
1161e4e7b89280d1d666e2c09e5ad36cf071796c4c7eJeff Garzik
1162e4e7b89280d1d666e2c09e5ad36cf071796c4c7eJeff Garzik/**
1163e4e7b89280d1d666e2c09e5ad36cf071796c4c7eJeff Garzik *      mv_qc_prep_iie - Host specific command preparation.
1164e4e7b89280d1d666e2c09e5ad36cf071796c4c7eJeff Garzik *      @qc: queued command to prepare
1165e4e7b89280d1d666e2c09e5ad36cf071796c4c7eJeff Garzik *
1166e4e7b89280d1d666e2c09e5ad36cf071796c4c7eJeff Garzik *      This routine simply redirects to the general purpose routine
1167e4e7b89280d1d666e2c09e5ad36cf071796c4c7eJeff Garzik *      if command is not DMA.  Else, it handles prep of the CRQB
1168e4e7b89280d1d666e2c09e5ad36cf071796c4c7eJeff Garzik *      (command request block), does some sanity checking, and calls
1169e4e7b89280d1d666e2c09e5ad36cf071796c4c7eJeff Garzik *      the SG load routine.
1170e4e7b89280d1d666e2c09e5ad36cf071796c4c7eJeff Garzik *
1171e4e7b89280d1d666e2c09e5ad36cf071796c4c7eJeff Garzik *      LOCKING:
1172e4e7b89280d1d666e2c09e5ad36cf071796c4c7eJeff Garzik *      Inherited from caller.
1173e4e7b89280d1d666e2c09e5ad36cf071796c4c7eJeff Garzik */
1174e4e7b89280d1d666e2c09e5ad36cf071796c4c7eJeff Garzikstatic void mv_qc_prep_iie(struct ata_queued_cmd *qc)
1175e4e7b89280d1d666e2c09e5ad36cf071796c4c7eJeff Garzik{
1176e4e7b89280d1d666e2c09e5ad36cf071796c4c7eJeff Garzik	struct ata_port *ap = qc->ap;
1177e4e7b89280d1d666e2c09e5ad36cf071796c4c7eJeff Garzik	struct mv_port_priv *pp = ap->private_data;
1178e4e7b89280d1d666e2c09e5ad36cf071796c4c7eJeff Garzik	struct mv_crqb_iie *crqb;
1179e4e7b89280d1d666e2c09e5ad36cf071796c4c7eJeff Garzik	struct ata_taskfile *tf;
1180a6432436c5e14b416f27c8f87c5bf0bc36771f49Mark Lord	unsigned in_index;
1181e4e7b89280d1d666e2c09e5ad36cf071796c4c7eJeff Garzik	u32 flags = 0;
1182e4e7b89280d1d666e2c09e5ad36cf071796c4c7eJeff Garzik
1183e4e7b89280d1d666e2c09e5ad36cf071796c4c7eJeff Garzik 	if (ATA_PROT_DMA != qc->tf.protocol)
1184e4e7b89280d1d666e2c09e5ad36cf071796c4c7eJeff Garzik		return;
1185e4e7b89280d1d666e2c09e5ad36cf071796c4c7eJeff Garzik
1186e4e7b89280d1d666e2c09e5ad36cf071796c4c7eJeff Garzik	/* Fill in Gen IIE command request block
1187e4e7b89280d1d666e2c09e5ad36cf071796c4c7eJeff Garzik	 */
1188e4e7b89280d1d666e2c09e5ad36cf071796c4c7eJeff Garzik	if (!(qc->tf.flags & ATA_TFLAG_WRITE))
1189e4e7b89280d1d666e2c09e5ad36cf071796c4c7eJeff Garzik		flags |= CRQB_FLAG_READ;
1190e4e7b89280d1d666e2c09e5ad36cf071796c4c7eJeff Garzik
1191beec7dbc6ff003bbc94de62b3323519c878fb2acTejun Heo	WARN_ON(MV_MAX_Q_DEPTH <= qc->tag);
1192e4e7b89280d1d666e2c09e5ad36cf071796c4c7eJeff Garzik	flags |= qc->tag << CRQB_TAG_SHIFT;
1193e4e7b89280d1d666e2c09e5ad36cf071796c4c7eJeff Garzik
1194a6432436c5e14b416f27c8f87c5bf0bc36771f49Mark Lord	/* get current queue index from hardware */
1195a6432436c5e14b416f27c8f87c5bf0bc36771f49Mark Lord	in_index = (readl(mv_ap_base(ap) + EDMA_REQ_Q_IN_PTR_OFS)
1196a6432436c5e14b416f27c8f87c5bf0bc36771f49Mark Lord			>> EDMA_REQ_Q_PTR_SHIFT) & MV_MAX_Q_DEPTH_MASK;
1197a6432436c5e14b416f27c8f87c5bf0bc36771f49Mark Lord
1198a6432436c5e14b416f27c8f87c5bf0bc36771f49Mark Lord	crqb = (struct mv_crqb_iie *) &pp->crqb[in_index];
1199e4e7b89280d1d666e2c09e5ad36cf071796c4c7eJeff Garzik	crqb->addr = cpu_to_le32(pp->sg_tbl_dma & 0xffffffff);
1200e4e7b89280d1d666e2c09e5ad36cf071796c4c7eJeff Garzik	crqb->addr_hi = cpu_to_le32((pp->sg_tbl_dma >> 16) >> 16);
1201e4e7b89280d1d666e2c09e5ad36cf071796c4c7eJeff Garzik	crqb->flags = cpu_to_le32(flags);
1202e4e7b89280d1d666e2c09e5ad36cf071796c4c7eJeff Garzik
1203e4e7b89280d1d666e2c09e5ad36cf071796c4c7eJeff Garzik	tf = &qc->tf;
1204e4e7b89280d1d666e2c09e5ad36cf071796c4c7eJeff Garzik	crqb->ata_cmd[0] = cpu_to_le32(
1205e4e7b89280d1d666e2c09e5ad36cf071796c4c7eJeff Garzik			(tf->command << 16) |
1206e4e7b89280d1d666e2c09e5ad36cf071796c4c7eJeff Garzik			(tf->feature << 24)
1207e4e7b89280d1d666e2c09e5ad36cf071796c4c7eJeff Garzik		);
1208e4e7b89280d1d666e2c09e5ad36cf071796c4c7eJeff Garzik	crqb->ata_cmd[1] = cpu_to_le32(
1209e4e7b89280d1d666e2c09e5ad36cf071796c4c7eJeff Garzik			(tf->lbal << 0) |
1210e4e7b89280d1d666e2c09e5ad36cf071796c4c7eJeff Garzik			(tf->lbam << 8) |
1211e4e7b89280d1d666e2c09e5ad36cf071796c4c7eJeff Garzik			(tf->lbah << 16) |
1212e4e7b89280d1d666e2c09e5ad36cf071796c4c7eJeff Garzik			(tf->device << 24)
1213e4e7b89280d1d666e2c09e5ad36cf071796c4c7eJeff Garzik		);
1214e4e7b89280d1d666e2c09e5ad36cf071796c4c7eJeff Garzik	crqb->ata_cmd[2] = cpu_to_le32(
1215e4e7b89280d1d666e2c09e5ad36cf071796c4c7eJeff Garzik			(tf->hob_lbal << 0) |
1216e4e7b89280d1d666e2c09e5ad36cf071796c4c7eJeff Garzik			(tf->hob_lbam << 8) |
1217e4e7b89280d1d666e2c09e5ad36cf071796c4c7eJeff Garzik			(tf->hob_lbah << 16) |
1218e4e7b89280d1d666e2c09e5ad36cf071796c4c7eJeff Garzik			(tf->hob_feature << 24)
1219e4e7b89280d1d666e2c09e5ad36cf071796c4c7eJeff Garzik		);
1220e4e7b89280d1d666e2c09e5ad36cf071796c4c7eJeff Garzik	crqb->ata_cmd[3] = cpu_to_le32(
1221e4e7b89280d1d666e2c09e5ad36cf071796c4c7eJeff Garzik			(tf->nsect << 0) |
1222e4e7b89280d1d666e2c09e5ad36cf071796c4c7eJeff Garzik			(tf->hob_nsect << 8)
1223e4e7b89280d1d666e2c09e5ad36cf071796c4c7eJeff Garzik		);
1224e4e7b89280d1d666e2c09e5ad36cf071796c4c7eJeff Garzik
1225e4e7b89280d1d666e2c09e5ad36cf071796c4c7eJeff Garzik	if (!(qc->flags & ATA_QCFLAG_DMAMAP))
122631961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ		return;
122731961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ	mv_fill_sg(qc);
122831961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ}
122931961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ
123005b308e1df6d9d673daedb517969241f41278b52Brett Russ/**
123105b308e1df6d9d673daedb517969241f41278b52Brett Russ *      mv_qc_issue - Initiate a command to the host
123205b308e1df6d9d673daedb517969241f41278b52Brett Russ *      @qc: queued command to start
123305b308e1df6d9d673daedb517969241f41278b52Brett Russ *
123405b308e1df6d9d673daedb517969241f41278b52Brett Russ *      This routine simply redirects to the general purpose routine
123505b308e1df6d9d673daedb517969241f41278b52Brett Russ *      if command is not DMA.  Else, it sanity checks our local
123605b308e1df6d9d673daedb517969241f41278b52Brett Russ *      caches of the request producer/consumer indices then enables
123705b308e1df6d9d673daedb517969241f41278b52Brett Russ *      DMA and bumps the request producer index.
123805b308e1df6d9d673daedb517969241f41278b52Brett Russ *
123905b308e1df6d9d673daedb517969241f41278b52Brett Russ *      LOCKING:
124005b308e1df6d9d673daedb517969241f41278b52Brett Russ *      Inherited from caller.
124105b308e1df6d9d673daedb517969241f41278b52Brett Russ */
12429a3d9eb0177eb10500d49cd283b35576082a522dTejun Heostatic unsigned int mv_qc_issue(struct ata_queued_cmd *qc)
124331961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ{
124431961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ	void __iomem *port_mmio = mv_ap_base(qc->ap);
124531961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ	struct mv_port_priv *pp = qc->ap->private_data;
1246a6432436c5e14b416f27c8f87c5bf0bc36771f49Mark Lord	unsigned in_index;
124731961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ	u32 in_ptr;
124831961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ
124931961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ	if (ATA_PROT_DMA != qc->tf.protocol) {
125031961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ		/* We're about to send a non-EDMA capable command to the
125131961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ		 * port.  Turn off EDMA so there won't be problems accessing
125231961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ		 * shadow block, etc registers.
125331961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ		 */
125431961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ		mv_stop_dma(qc->ap);
125531961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ		return ata_qc_issue_prot(qc);
125631961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ	}
125731961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ
1258a6432436c5e14b416f27c8f87c5bf0bc36771f49Mark Lord	in_ptr   = readl(port_mmio + EDMA_REQ_Q_IN_PTR_OFS);
1259a6432436c5e14b416f27c8f87c5bf0bc36771f49Mark Lord	in_index = (in_ptr >> EDMA_REQ_Q_PTR_SHIFT) & MV_MAX_Q_DEPTH_MASK;
126031961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ
126131961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ	/* until we do queuing, the queue should be empty at this point */
1262a6432436c5e14b416f27c8f87c5bf0bc36771f49Mark Lord	WARN_ON(in_index != ((readl(port_mmio + EDMA_REQ_Q_OUT_PTR_OFS)
1263a6432436c5e14b416f27c8f87c5bf0bc36771f49Mark Lord		>> EDMA_REQ_Q_PTR_SHIFT) & MV_MAX_Q_DEPTH_MASK));
126431961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ
1265a6432436c5e14b416f27c8f87c5bf0bc36771f49Mark Lord	in_index = mv_inc_q_index(in_index);	/* now incr producer index */
126631961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ
1267afb0edd922c7ed6e73678730921dfcccebec17e8Brett Russ	mv_start_dma(port_mmio, pp);
126831961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ
126931961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ	/* and write the request in pointer to kick the EDMA to life */
127031961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ	in_ptr &= EDMA_REQ_Q_BASE_LO_MASK;
1271a6432436c5e14b416f27c8f87c5bf0bc36771f49Mark Lord	in_ptr |= in_index << EDMA_REQ_Q_PTR_SHIFT;
127231961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ	writelfl(in_ptr, port_mmio + EDMA_REQ_Q_IN_PTR_OFS);
127331961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ
127431961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ	return 0;
127531961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ}
127631961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ
127705b308e1df6d9d673daedb517969241f41278b52Brett Russ/**
127805b308e1df6d9d673daedb517969241f41278b52Brett Russ *      mv_get_crpb_status - get status from most recently completed cmd
127905b308e1df6d9d673daedb517969241f41278b52Brett Russ *      @ap: ATA channel to manipulate
128005b308e1df6d9d673daedb517969241f41278b52Brett Russ *
128105b308e1df6d9d673daedb517969241f41278b52Brett Russ *      This routine is for use when the port is in DMA mode, when it
128205b308e1df6d9d673daedb517969241f41278b52Brett Russ *      will be using the CRPB (command response block) method of
1283beec7dbc6ff003bbc94de62b3323519c878fb2acTejun Heo *      returning command completion information.  We check indices
128405b308e1df6d9d673daedb517969241f41278b52Brett Russ *      are good, grab status, and bump the response consumer index to
128505b308e1df6d9d673daedb517969241f41278b52Brett Russ *      prove that we're up to date.
128605b308e1df6d9d673daedb517969241f41278b52Brett Russ *
128705b308e1df6d9d673daedb517969241f41278b52Brett Russ *      LOCKING:
128805b308e1df6d9d673daedb517969241f41278b52Brett Russ *      Inherited from caller.
128905b308e1df6d9d673daedb517969241f41278b52Brett Russ */
129031961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russstatic u8 mv_get_crpb_status(struct ata_port *ap)
129131961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ{
129231961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ	void __iomem *port_mmio = mv_ap_base(ap);
129331961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ	struct mv_port_priv *pp = ap->private_data;
1294a6432436c5e14b416f27c8f87c5bf0bc36771f49Mark Lord	unsigned out_index;
129531961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ	u32 out_ptr;
1296806a6e7a9904d4a1dfd3fd79d373bf31d71d34cbMark Lord	u8 ata_status;
129731961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ
1298a6432436c5e14b416f27c8f87c5bf0bc36771f49Mark Lord	out_ptr   = readl(port_mmio + EDMA_RSP_Q_OUT_PTR_OFS);
1299a6432436c5e14b416f27c8f87c5bf0bc36771f49Mark Lord	out_index = (out_ptr >> EDMA_RSP_Q_PTR_SHIFT) & MV_MAX_Q_DEPTH_MASK;
130031961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ
1301a6432436c5e14b416f27c8f87c5bf0bc36771f49Mark Lord	ata_status = le16_to_cpu(pp->crpb[out_index].flags)
1302a6432436c5e14b416f27c8f87c5bf0bc36771f49Mark Lord					>> CRPB_FLAG_STATUS_SHIFT;
1303806a6e7a9904d4a1dfd3fd79d373bf31d71d34cbMark Lord
130431961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ	/* increment our consumer index... */
1305a6432436c5e14b416f27c8f87c5bf0bc36771f49Mark Lord	out_index = mv_inc_q_index(out_index);
13068b260248d9e0e8b64bb72fd4dee03ad86984c344Jeff Garzik
130731961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ	/* and, until we do NCQ, there should only be 1 CRPB waiting */
1308a6432436c5e14b416f27c8f87c5bf0bc36771f49Mark Lord	WARN_ON(out_index != ((readl(port_mmio + EDMA_RSP_Q_IN_PTR_OFS)
1309a6432436c5e14b416f27c8f87c5bf0bc36771f49Mark Lord		>> EDMA_RSP_Q_PTR_SHIFT) & MV_MAX_Q_DEPTH_MASK));
131031961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ
131131961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ	/* write out our inc'd consumer index so EDMA knows we're caught up */
131231961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ	out_ptr &= EDMA_RSP_Q_BASE_LO_MASK;
1313a6432436c5e14b416f27c8f87c5bf0bc36771f49Mark Lord	out_ptr |= out_index << EDMA_RSP_Q_PTR_SHIFT;
131431961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ	writelfl(out_ptr, port_mmio + EDMA_RSP_Q_OUT_PTR_OFS);
131531961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ
131631961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ	/* Return ATA status register for completed CRPB */
1317806a6e7a9904d4a1dfd3fd79d373bf31d71d34cbMark Lord	return ata_status;
131831961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ}
131931961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ
132005b308e1df6d9d673daedb517969241f41278b52Brett Russ/**
132105b308e1df6d9d673daedb517969241f41278b52Brett Russ *      mv_err_intr - Handle error interrupts on the port
132205b308e1df6d9d673daedb517969241f41278b52Brett Russ *      @ap: ATA channel to manipulate
13239b358e305c1d783c8a4ebf00344e95deb9e38f3dMark Lord *      @reset_allowed: bool: 0 == don't trigger from reset here
132405b308e1df6d9d673daedb517969241f41278b52Brett Russ *
132505b308e1df6d9d673daedb517969241f41278b52Brett Russ *      In most cases, just clear the interrupt and move on.  However,
132605b308e1df6d9d673daedb517969241f41278b52Brett Russ *      some cases require an eDMA reset, which is done right before
132705b308e1df6d9d673daedb517969241f41278b52Brett Russ *      the COMRESET in mv_phy_reset().  The SERR case requires a
132805b308e1df6d9d673daedb517969241f41278b52Brett Russ *      clear of pending errors in the SATA SERROR register.  Finally,
132905b308e1df6d9d673daedb517969241f41278b52Brett Russ *      if the port disabled DMA, update our cached copy to match.
133005b308e1df6d9d673daedb517969241f41278b52Brett Russ *
133105b308e1df6d9d673daedb517969241f41278b52Brett Russ *      LOCKING:
133205b308e1df6d9d673daedb517969241f41278b52Brett Russ *      Inherited from caller.
133305b308e1df6d9d673daedb517969241f41278b52Brett Russ */
13349b358e305c1d783c8a4ebf00344e95deb9e38f3dMark Lordstatic void mv_err_intr(struct ata_port *ap, int reset_allowed)
133531961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ{
133631961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ	void __iomem *port_mmio = mv_ap_base(ap);
133731961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ	u32 edma_err_cause, serr = 0;
133820f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ
133920f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ	edma_err_cause = readl(port_mmio + EDMA_ERR_IRQ_CAUSE_OFS);
134020f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ
134120f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ	if (EDMA_ERR_SERR & edma_err_cause) {
134281952c5497b40ae56835bd0d6537f8c6bdea07e7Tejun Heo		sata_scr_read(ap, SCR_ERROR, &serr);
134381952c5497b40ae56835bd0d6537f8c6bdea07e7Tejun Heo		sata_scr_write_flush(ap, SCR_ERROR, serr);
134420f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ	}
1345afb0edd922c7ed6e73678730921dfcccebec17e8Brett Russ	if (EDMA_ERR_SELF_DIS & edma_err_cause) {
1346afb0edd922c7ed6e73678730921dfcccebec17e8Brett Russ		struct mv_port_priv *pp	= ap->private_data;
1347afb0edd922c7ed6e73678730921dfcccebec17e8Brett Russ		pp->pp_flags &= ~MV_PP_FLAG_EDMA_EN;
1348afb0edd922c7ed6e73678730921dfcccebec17e8Brett Russ	}
1349afb0edd922c7ed6e73678730921dfcccebec17e8Brett Russ	DPRINTK(KERN_ERR "ata%u: port error; EDMA err cause: 0x%08x "
135044877b4e22f391d39c6589412106a3668e81a05bTejun Heo		"SERR: 0x%08x\n", ap->print_id, edma_err_cause, serr);
135120f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ
135220f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ	/* Clear EDMA now that SERR cleanup done */
135320f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ	writelfl(0, port_mmio + EDMA_ERR_IRQ_CAUSE_OFS);
135420f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ
135520f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ	/* check for fatal here and recover if needed */
13569b358e305c1d783c8a4ebf00344e95deb9e38f3dMark Lord	if (reset_allowed && (EDMA_ERR_FATAL & edma_err_cause))
1357c9d39130123238ac18478a42e25cb7996eacfcc0Jeff Garzik		mv_stop_and_reset(ap);
135820f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ}
135920f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ
136005b308e1df6d9d673daedb517969241f41278b52Brett Russ/**
136105b308e1df6d9d673daedb517969241f41278b52Brett Russ *      mv_host_intr - Handle all interrupts on the given host controller
1362cca3974e48607c3775dc73b544a5700b2e37c21aJeff Garzik *      @host: host specific structure
136305b308e1df6d9d673daedb517969241f41278b52Brett Russ *      @relevant: port error bits relevant to this host controller
136405b308e1df6d9d673daedb517969241f41278b52Brett Russ *      @hc: which host controller we're to look at
136505b308e1df6d9d673daedb517969241f41278b52Brett Russ *
136605b308e1df6d9d673daedb517969241f41278b52Brett Russ *      Read then write clear the HC interrupt status then walk each
136705b308e1df6d9d673daedb517969241f41278b52Brett Russ *      port connected to the HC and see if it needs servicing.  Port
136805b308e1df6d9d673daedb517969241f41278b52Brett Russ *      success ints are reported in the HC interrupt status reg, the
136905b308e1df6d9d673daedb517969241f41278b52Brett Russ *      port error ints are reported in the higher level main
137005b308e1df6d9d673daedb517969241f41278b52Brett Russ *      interrupt status register and thus are passed in via the
137105b308e1df6d9d673daedb517969241f41278b52Brett Russ *      'relevant' argument.
137205b308e1df6d9d673daedb517969241f41278b52Brett Russ *
137305b308e1df6d9d673daedb517969241f41278b52Brett Russ *      LOCKING:
137405b308e1df6d9d673daedb517969241f41278b52Brett Russ *      Inherited from caller.
137505b308e1df6d9d673daedb517969241f41278b52Brett Russ */
1376cca3974e48607c3775dc73b544a5700b2e37c21aJeff Garzikstatic void mv_host_intr(struct ata_host *host, u32 relevant, unsigned int hc)
137720f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ{
13780d5ff566779f894ca9937231a181eb31e4adff0eTejun Heo	void __iomem *mmio = host->iomap[MV_PRIMARY_BAR];
137920f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ	void __iomem *hc_mmio = mv_hc_base(mmio, hc);
138020f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ	struct ata_queued_cmd *qc;
138120f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ	u32 hc_irq_cause;
138231961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ	int shift, port, port0, hard_port, handled;
1383a7dac447bb9cef27d4d29cdf63e2d7809c50b1f4Jeff Garzik	unsigned int err_mask;
138420f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ
1385351772658a4d1acc0221a6e30676bb0594e74812Jeff Garzik	if (hc == 0)
138620f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ		port0 = 0;
1387351772658a4d1acc0221a6e30676bb0594e74812Jeff Garzik	else
138820f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ		port0 = MV_PORTS_PER_HC;
138920f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ
139020f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ	/* we'll need the HC success int register in most cases */
139120f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ	hc_irq_cause = readl(hc_mmio + HC_IRQ_CAUSE_OFS);
1392351772658a4d1acc0221a6e30676bb0594e74812Jeff Garzik	if (hc_irq_cause)
139331961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ		writelfl(~hc_irq_cause, hc_mmio + HC_IRQ_CAUSE_OFS);
139420f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ
139520f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ	VPRINTK("ENTER, hc%u relevant=0x%08x HC IRQ cause=0x%08x\n",
139620f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ		hc,relevant,hc_irq_cause);
139720f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ
139820f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ	for (port = port0; port < port0 + MV_PORTS_PER_HC; port++) {
1399cd85f6e2f58282186ad720fc18482be228f0b972Jeff Garzik		u8 ata_status = 0;
1400cca3974e48607c3775dc73b544a5700b2e37c21aJeff Garzik		struct ata_port *ap = host->ports[port];
140163af2a5c5990d95f1e7d8795f1425fb976ea2b4bMark Lord		struct mv_port_priv *pp = ap->private_data;
140255d8ca4f8094246da6e71889a4e04bfafaa78b10Jeff Garzik
1403e857f141945f29c16f72ffcfdbce097f8be6c4e9Mark Lord		hard_port = mv_hardport_from_port(port); /* range 0..3 */
140431961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ		handled = 0;	/* ensure ata_status is set if handled++ */
140520f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ
140663af2a5c5990d95f1e7d8795f1425fb976ea2b4bMark Lord		/* Note that DEV_IRQ might happen spuriously during EDMA,
1407e857f141945f29c16f72ffcfdbce097f8be6c4e9Mark Lord		 * and should be ignored in such cases.
1408e857f141945f29c16f72ffcfdbce097f8be6c4e9Mark Lord		 * The cause of this is still under investigation.
14098190bdb9291758f3b8c436ec1154c9923ddb57eaJeff Garzik		 */
141063af2a5c5990d95f1e7d8795f1425fb976ea2b4bMark Lord		if (pp->pp_flags & MV_PP_FLAG_EDMA_EN) {
141163af2a5c5990d95f1e7d8795f1425fb976ea2b4bMark Lord			/* EDMA: check for response queue interrupt */
141263af2a5c5990d95f1e7d8795f1425fb976ea2b4bMark Lord			if ((CRPB_DMA_DONE << hard_port) & hc_irq_cause) {
141363af2a5c5990d95f1e7d8795f1425fb976ea2b4bMark Lord				ata_status = mv_get_crpb_status(ap);
141463af2a5c5990d95f1e7d8795f1425fb976ea2b4bMark Lord				handled = 1;
141563af2a5c5990d95f1e7d8795f1425fb976ea2b4bMark Lord			}
141663af2a5c5990d95f1e7d8795f1425fb976ea2b4bMark Lord		} else {
141763af2a5c5990d95f1e7d8795f1425fb976ea2b4bMark Lord			/* PIO: check for device (drive) interrupt */
141863af2a5c5990d95f1e7d8795f1425fb976ea2b4bMark Lord			if ((DEV_IRQ << hard_port) & hc_irq_cause) {
14190d5ff566779f894ca9937231a181eb31e4adff0eTejun Heo				ata_status = readb(ap->ioaddr.status_addr);
142063af2a5c5990d95f1e7d8795f1425fb976ea2b4bMark Lord				handled = 1;
1421e857f141945f29c16f72ffcfdbce097f8be6c4e9Mark Lord				/* ignore spurious intr if drive still BUSY */
1422e857f141945f29c16f72ffcfdbce097f8be6c4e9Mark Lord				if (ata_status & ATA_BUSY) {
1423e857f141945f29c16f72ffcfdbce097f8be6c4e9Mark Lord					ata_status = 0;
1424e857f141945f29c16f72ffcfdbce097f8be6c4e9Mark Lord					handled = 0;
1425e857f141945f29c16f72ffcfdbce097f8be6c4e9Mark Lord				}
142663af2a5c5990d95f1e7d8795f1425fb976ea2b4bMark Lord			}
142720f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ		}
142820f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ
1429029f5468b5b5f93a09bf90326fdcb9124079658dJeff Garzik		if (ap && (ap->flags & ATA_FLAG_DISABLED))
1430a2c91a8819e315e9fd1aef3ff57badb6c1be3f80Jeff Garzik			continue;
1431a2c91a8819e315e9fd1aef3ff57badb6c1be3f80Jeff Garzik
1432a7dac447bb9cef27d4d29cdf63e2d7809c50b1f4Jeff Garzik		err_mask = ac_err_mask(ata_status);
1433a7dac447bb9cef27d4d29cdf63e2d7809c50b1f4Jeff Garzik
143431961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ		shift = port << 1;		/* (port * 2) */
143520f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ		if (port >= MV_PORTS_PER_HC) {
143620f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ			shift++;	/* skip bit 8 in the HC Main IRQ reg */
143720f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ		}
143820f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ		if ((PORT0_ERR << shift) & relevant) {
14399b358e305c1d783c8a4ebf00344e95deb9e38f3dMark Lord			mv_err_intr(ap, 1);
1440a7dac447bb9cef27d4d29cdf63e2d7809c50b1f4Jeff Garzik			err_mask |= AC_ERR_OTHER;
144163af2a5c5990d95f1e7d8795f1425fb976ea2b4bMark Lord			handled = 1;
144220f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ		}
14438b260248d9e0e8b64bb72fd4dee03ad86984c344Jeff Garzik
144463af2a5c5990d95f1e7d8795f1425fb976ea2b4bMark Lord		if (handled) {
144520f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ			qc = ata_qc_from_tag(ap, ap->active_tag);
144663af2a5c5990d95f1e7d8795f1425fb976ea2b4bMark Lord			if (qc && (qc->flags & ATA_QCFLAG_ACTIVE)) {
144720f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ				VPRINTK("port %u IRQ found for qc, "
144820f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ					"ata_status 0x%x\n", port,ata_status);
144920f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ				/* mark qc status appropriately */
1450701db69d6647f61e4660c9102d7f2fd5dffc203dJeff Garzik				if (!(qc->tf.flags & ATA_TFLAG_POLLING)) {
1451a22e2eb0710798009b8e696ae911aef745089dd6Albert Lee					qc->err_mask |= err_mask;
1452a22e2eb0710798009b8e696ae911aef745089dd6Albert Lee					ata_qc_complete(qc);
1453a22e2eb0710798009b8e696ae911aef745089dd6Albert Lee				}
145420f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ			}
145520f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ		}
145620f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ	}
145720f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ	VPRINTK("EXIT\n");
145820f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ}
145920f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ
146005b308e1df6d9d673daedb517969241f41278b52Brett Russ/**
14618b260248d9e0e8b64bb72fd4dee03ad86984c344Jeff Garzik *      mv_interrupt -
146205b308e1df6d9d673daedb517969241f41278b52Brett Russ *      @irq: unused
146305b308e1df6d9d673daedb517969241f41278b52Brett Russ *      @dev_instance: private data; in this case the host structure
146405b308e1df6d9d673daedb517969241f41278b52Brett Russ *      @regs: unused
146505b308e1df6d9d673daedb517969241f41278b52Brett Russ *
146605b308e1df6d9d673daedb517969241f41278b52Brett Russ *      Read the read only register to determine if any host
146705b308e1df6d9d673daedb517969241f41278b52Brett Russ *      controllers have pending interrupts.  If so, call lower level
146805b308e1df6d9d673daedb517969241f41278b52Brett Russ *      routine to handle.  Also check for PCI errors which are only
146905b308e1df6d9d673daedb517969241f41278b52Brett Russ *      reported here.
147005b308e1df6d9d673daedb517969241f41278b52Brett Russ *
14718b260248d9e0e8b64bb72fd4dee03ad86984c344Jeff Garzik *      LOCKING:
1472cca3974e48607c3775dc73b544a5700b2e37c21aJeff Garzik *      This routine holds the host lock while processing pending
147305b308e1df6d9d673daedb517969241f41278b52Brett Russ *      interrupts.
147405b308e1df6d9d673daedb517969241f41278b52Brett Russ */
14757d12e780e003f93433d49ce78cfedf4b4c52adc5David Howellsstatic irqreturn_t mv_interrupt(int irq, void *dev_instance)
147620f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ{
1477cca3974e48607c3775dc73b544a5700b2e37c21aJeff Garzik	struct ata_host *host = dev_instance;
147820f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ	unsigned int hc, handled = 0, n_hcs;
14790d5ff566779f894ca9937231a181eb31e4adff0eTejun Heo	void __iomem *mmio = host->iomap[MV_PRIMARY_BAR];
1480615ab95342f6245026d8974b9724f7ea57d9a184Mark Lord	struct mv_host_priv *hpriv;
148120f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ	u32 irq_stat;
148220f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ
148320f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ	irq_stat = readl(mmio + HC_MAIN_IRQ_CAUSE_OFS);
148420f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ
148520f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ	/* check the cases where we either have nothing pending or have read
148620f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ	 * a bogus register value which can indicate HW removal or PCI fault
148720f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ	 */
1488351772658a4d1acc0221a6e30676bb0594e74812Jeff Garzik	if (!irq_stat || (0xffffffffU == irq_stat))
148920f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ		return IRQ_NONE;
149020f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ
1491cca3974e48607c3775dc73b544a5700b2e37c21aJeff Garzik	n_hcs = mv_get_hc_count(host->ports[0]->flags);
1492cca3974e48607c3775dc73b544a5700b2e37c21aJeff Garzik	spin_lock(&host->lock);
149320f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ
149420f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ	for (hc = 0; hc < n_hcs; hc++) {
149520f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ		u32 relevant = irq_stat & (HC0_IRQ_PEND << (hc * HC_SHIFT));
149620f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ		if (relevant) {
1497cca3974e48607c3775dc73b544a5700b2e37c21aJeff Garzik			mv_host_intr(host, relevant, hc);
149831961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ			handled++;
149920f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ		}
150020f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ	}
1501615ab95342f6245026d8974b9724f7ea57d9a184Mark Lord
1502cca3974e48607c3775dc73b544a5700b2e37c21aJeff Garzik	hpriv = host->private_data;
1503615ab95342f6245026d8974b9724f7ea57d9a184Mark Lord	if (IS_60XX(hpriv)) {
1504615ab95342f6245026d8974b9724f7ea57d9a184Mark Lord		/* deal with the interrupt coalescing bits */
1505615ab95342f6245026d8974b9724f7ea57d9a184Mark Lord		if (irq_stat & (TRAN_LO_DONE | TRAN_HI_DONE | PORTS_0_7_COAL_DONE)) {
1506615ab95342f6245026d8974b9724f7ea57d9a184Mark Lord			writelfl(0, mmio + MV_IRQ_COAL_CAUSE_LO);
1507615ab95342f6245026d8974b9724f7ea57d9a184Mark Lord			writelfl(0, mmio + MV_IRQ_COAL_CAUSE_HI);
1508615ab95342f6245026d8974b9724f7ea57d9a184Mark Lord			writelfl(0, mmio + MV_IRQ_COAL_CAUSE);
1509615ab95342f6245026d8974b9724f7ea57d9a184Mark Lord		}
1510615ab95342f6245026d8974b9724f7ea57d9a184Mark Lord	}
1511615ab95342f6245026d8974b9724f7ea57d9a184Mark Lord
151220f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ	if (PCI_ERR & irq_stat) {
151331961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ		printk(KERN_ERR DRV_NAME ": PCI ERROR; PCI IRQ cause=0x%08x\n",
151431961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ		       readl(mmio + PCI_IRQ_CAUSE_OFS));
151531961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ
1516afb0edd922c7ed6e73678730921dfcccebec17e8Brett Russ		DPRINTK("All regs @ PCI error\n");
1517cca3974e48607c3775dc73b544a5700b2e37c21aJeff Garzik		mv_dump_all_regs(mmio, -1, to_pci_dev(host->dev));
151820f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ
151931961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ		writelfl(0, mmio + PCI_IRQ_CAUSE_OFS);
152031961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ		handled++;
152131961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ	}
1522cca3974e48607c3775dc73b544a5700b2e37c21aJeff Garzik	spin_unlock(&host->lock);
152320f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ
152420f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ	return IRQ_RETVAL(handled);
152520f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ}
152620f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ
1527c9d39130123238ac18478a42e25cb7996eacfcc0Jeff Garzikstatic void __iomem *mv5_phy_base(void __iomem *mmio, unsigned int port)
1528c9d39130123238ac18478a42e25cb7996eacfcc0Jeff Garzik{
1529c9d39130123238ac18478a42e25cb7996eacfcc0Jeff Garzik	void __iomem *hc_mmio = mv_hc_base_from_port(mmio, port);
1530c9d39130123238ac18478a42e25cb7996eacfcc0Jeff Garzik	unsigned long ofs = (mv_hardport_from_port(port) + 1) * 0x100UL;
1531c9d39130123238ac18478a42e25cb7996eacfcc0Jeff Garzik
1532c9d39130123238ac18478a42e25cb7996eacfcc0Jeff Garzik	return hc_mmio + ofs;
1533c9d39130123238ac18478a42e25cb7996eacfcc0Jeff Garzik}
1534c9d39130123238ac18478a42e25cb7996eacfcc0Jeff Garzik
1535c9d39130123238ac18478a42e25cb7996eacfcc0Jeff Garzikstatic unsigned int mv5_scr_offset(unsigned int sc_reg_in)
1536c9d39130123238ac18478a42e25cb7996eacfcc0Jeff Garzik{
1537c9d39130123238ac18478a42e25cb7996eacfcc0Jeff Garzik	unsigned int ofs;
1538c9d39130123238ac18478a42e25cb7996eacfcc0Jeff Garzik
1539c9d39130123238ac18478a42e25cb7996eacfcc0Jeff Garzik	switch (sc_reg_in) {
1540c9d39130123238ac18478a42e25cb7996eacfcc0Jeff Garzik	case SCR_STATUS:
1541c9d39130123238ac18478a42e25cb7996eacfcc0Jeff Garzik	case SCR_ERROR:
1542c9d39130123238ac18478a42e25cb7996eacfcc0Jeff Garzik	case SCR_CONTROL:
1543c9d39130123238ac18478a42e25cb7996eacfcc0Jeff Garzik		ofs = sc_reg_in * sizeof(u32);
1544c9d39130123238ac18478a42e25cb7996eacfcc0Jeff Garzik		break;
1545c9d39130123238ac18478a42e25cb7996eacfcc0Jeff Garzik	default:
1546c9d39130123238ac18478a42e25cb7996eacfcc0Jeff Garzik		ofs = 0xffffffffU;
1547c9d39130123238ac18478a42e25cb7996eacfcc0Jeff Garzik		break;
1548c9d39130123238ac18478a42e25cb7996eacfcc0Jeff Garzik	}
1549c9d39130123238ac18478a42e25cb7996eacfcc0Jeff Garzik	return ofs;
1550c9d39130123238ac18478a42e25cb7996eacfcc0Jeff Garzik}
1551c9d39130123238ac18478a42e25cb7996eacfcc0Jeff Garzik
1552c9d39130123238ac18478a42e25cb7996eacfcc0Jeff Garzikstatic u32 mv5_scr_read(struct ata_port *ap, unsigned int sc_reg_in)
1553c9d39130123238ac18478a42e25cb7996eacfcc0Jeff Garzik{
15540d5ff566779f894ca9937231a181eb31e4adff0eTejun Heo	void __iomem *mmio = ap->host->iomap[MV_PRIMARY_BAR];
15550d5ff566779f894ca9937231a181eb31e4adff0eTejun Heo	void __iomem *addr = mv5_phy_base(mmio, ap->port_no);
1556c9d39130123238ac18478a42e25cb7996eacfcc0Jeff Garzik	unsigned int ofs = mv5_scr_offset(sc_reg_in);
1557c9d39130123238ac18478a42e25cb7996eacfcc0Jeff Garzik
1558c9d39130123238ac18478a42e25cb7996eacfcc0Jeff Garzik	if (ofs != 0xffffffffU)
15590d5ff566779f894ca9937231a181eb31e4adff0eTejun Heo		return readl(addr + ofs);
1560c9d39130123238ac18478a42e25cb7996eacfcc0Jeff Garzik	else
1561c9d39130123238ac18478a42e25cb7996eacfcc0Jeff Garzik		return (u32) ofs;
1562c9d39130123238ac18478a42e25cb7996eacfcc0Jeff Garzik}
1563c9d39130123238ac18478a42e25cb7996eacfcc0Jeff Garzik
1564c9d39130123238ac18478a42e25cb7996eacfcc0Jeff Garzikstatic void mv5_scr_write(struct ata_port *ap, unsigned int sc_reg_in, u32 val)
1565c9d39130123238ac18478a42e25cb7996eacfcc0Jeff Garzik{
15660d5ff566779f894ca9937231a181eb31e4adff0eTejun Heo	void __iomem *mmio = ap->host->iomap[MV_PRIMARY_BAR];
15670d5ff566779f894ca9937231a181eb31e4adff0eTejun Heo	void __iomem *addr = mv5_phy_base(mmio, ap->port_no);
1568c9d39130123238ac18478a42e25cb7996eacfcc0Jeff Garzik	unsigned int ofs = mv5_scr_offset(sc_reg_in);
1569c9d39130123238ac18478a42e25cb7996eacfcc0Jeff Garzik
1570c9d39130123238ac18478a42e25cb7996eacfcc0Jeff Garzik	if (ofs != 0xffffffffU)
15710d5ff566779f894ca9937231a181eb31e4adff0eTejun Heo		writelfl(val, addr + ofs);
1572c9d39130123238ac18478a42e25cb7996eacfcc0Jeff Garzik}
1573c9d39130123238ac18478a42e25cb7996eacfcc0Jeff Garzik
1574522479fb98c6667f081e75f87e298e413c0b1db8Jeff Garzikstatic void mv5_reset_bus(struct pci_dev *pdev, void __iomem *mmio)
1575522479fb98c6667f081e75f87e298e413c0b1db8Jeff Garzik{
1576522479fb98c6667f081e75f87e298e413c0b1db8Jeff Garzik	int early_5080;
1577522479fb98c6667f081e75f87e298e413c0b1db8Jeff Garzik
157844c10138fd4bbc4b6d6bff0873c24902f2a9da65Auke Kok	early_5080 = (pdev->device == 0x5080) && (pdev->revision == 0);
1579522479fb98c6667f081e75f87e298e413c0b1db8Jeff Garzik
1580522479fb98c6667f081e75f87e298e413c0b1db8Jeff Garzik	if (!early_5080) {
1581522479fb98c6667f081e75f87e298e413c0b1db8Jeff Garzik		u32 tmp = readl(mmio + MV_PCI_EXP_ROM_BAR_CTL);
1582522479fb98c6667f081e75f87e298e413c0b1db8Jeff Garzik		tmp |= (1 << 0);
1583522479fb98c6667f081e75f87e298e413c0b1db8Jeff Garzik		writel(tmp, mmio + MV_PCI_EXP_ROM_BAR_CTL);
1584522479fb98c6667f081e75f87e298e413c0b1db8Jeff Garzik	}
1585522479fb98c6667f081e75f87e298e413c0b1db8Jeff Garzik
1586522479fb98c6667f081e75f87e298e413c0b1db8Jeff Garzik	mv_reset_pci_bus(pdev, mmio);
1587522479fb98c6667f081e75f87e298e413c0b1db8Jeff Garzik}
1588522479fb98c6667f081e75f87e298e413c0b1db8Jeff Garzik
1589522479fb98c6667f081e75f87e298e413c0b1db8Jeff Garzikstatic void mv5_reset_flash(struct mv_host_priv *hpriv, void __iomem *mmio)
1590522479fb98c6667f081e75f87e298e413c0b1db8Jeff Garzik{
1591522479fb98c6667f081e75f87e298e413c0b1db8Jeff Garzik	writel(0x0fcfffff, mmio + MV_FLASH_CTL);
1592522479fb98c6667f081e75f87e298e413c0b1db8Jeff Garzik}
1593522479fb98c6667f081e75f87e298e413c0b1db8Jeff Garzik
159447c2b677daeed9c79ecb7167c211ff36876ea611Jeff Garzikstatic void mv5_read_preamp(struct mv_host_priv *hpriv, int idx,
1595ba3fe8fb6a469390a14379519915f3c39a973d99Jeff Garzik			   void __iomem *mmio)
1596ba3fe8fb6a469390a14379519915f3c39a973d99Jeff Garzik{
1597c9d39130123238ac18478a42e25cb7996eacfcc0Jeff Garzik	void __iomem *phy_mmio = mv5_phy_base(mmio, idx);
1598c9d39130123238ac18478a42e25cb7996eacfcc0Jeff Garzik	u32 tmp;
1599c9d39130123238ac18478a42e25cb7996eacfcc0Jeff Garzik
1600c9d39130123238ac18478a42e25cb7996eacfcc0Jeff Garzik	tmp = readl(phy_mmio + MV5_PHY_MODE);
1601c9d39130123238ac18478a42e25cb7996eacfcc0Jeff Garzik
1602c9d39130123238ac18478a42e25cb7996eacfcc0Jeff Garzik	hpriv->signal[idx].pre = tmp & 0x1800;	/* bits 12:11 */
1603c9d39130123238ac18478a42e25cb7996eacfcc0Jeff Garzik	hpriv->signal[idx].amps = tmp & 0xe0;	/* bits 7:5 */
1604ba3fe8fb6a469390a14379519915f3c39a973d99Jeff Garzik}
1605ba3fe8fb6a469390a14379519915f3c39a973d99Jeff Garzik
160647c2b677daeed9c79ecb7167c211ff36876ea611Jeff Garzikstatic void mv5_enable_leds(struct mv_host_priv *hpriv, void __iomem *mmio)
1607ba3fe8fb6a469390a14379519915f3c39a973d99Jeff Garzik{
1608522479fb98c6667f081e75f87e298e413c0b1db8Jeff Garzik	u32 tmp;
1609522479fb98c6667f081e75f87e298e413c0b1db8Jeff Garzik
1610522479fb98c6667f081e75f87e298e413c0b1db8Jeff Garzik	writel(0, mmio + MV_GPIO_PORT_CTL);
1611522479fb98c6667f081e75f87e298e413c0b1db8Jeff Garzik
1612522479fb98c6667f081e75f87e298e413c0b1db8Jeff Garzik	/* FIXME: handle MV_HP_ERRATA_50XXB2 errata */
1613522479fb98c6667f081e75f87e298e413c0b1db8Jeff Garzik
1614522479fb98c6667f081e75f87e298e413c0b1db8Jeff Garzik	tmp = readl(mmio + MV_PCI_EXP_ROM_BAR_CTL);
1615522479fb98c6667f081e75f87e298e413c0b1db8Jeff Garzik	tmp |= ~(1 << 0);
1616522479fb98c6667f081e75f87e298e413c0b1db8Jeff Garzik	writel(tmp, mmio + MV_PCI_EXP_ROM_BAR_CTL);
1617ba3fe8fb6a469390a14379519915f3c39a973d99Jeff Garzik}
1618ba3fe8fb6a469390a14379519915f3c39a973d99Jeff Garzik
16192a47ce06d534692f9bd2bf4e90a20fc9b1054c39Jeff Garzikstatic void mv5_phy_errata(struct mv_host_priv *hpriv, void __iomem *mmio,
16202a47ce06d534692f9bd2bf4e90a20fc9b1054c39Jeff Garzik			   unsigned int port)
1621bca1c4eb9411533d613123618c0d127fae532595Jeff Garzik{
1622c9d39130123238ac18478a42e25cb7996eacfcc0Jeff Garzik	void __iomem *phy_mmio = mv5_phy_base(mmio, port);
1623c9d39130123238ac18478a42e25cb7996eacfcc0Jeff Garzik	const u32 mask = (1<<12) | (1<<11) | (1<<7) | (1<<6) | (1<<5);
1624c9d39130123238ac18478a42e25cb7996eacfcc0Jeff Garzik	u32 tmp;
1625c9d39130123238ac18478a42e25cb7996eacfcc0Jeff Garzik	int fix_apm_sq = (hpriv->hp_flags & MV_HP_ERRATA_50XXB0);
1626c9d39130123238ac18478a42e25cb7996eacfcc0Jeff Garzik
1627c9d39130123238ac18478a42e25cb7996eacfcc0Jeff Garzik	if (fix_apm_sq) {
1628c9d39130123238ac18478a42e25cb7996eacfcc0Jeff Garzik		tmp = readl(phy_mmio + MV5_LT_MODE);
1629c9d39130123238ac18478a42e25cb7996eacfcc0Jeff Garzik		tmp |= (1 << 19);
1630c9d39130123238ac18478a42e25cb7996eacfcc0Jeff Garzik		writel(tmp, phy_mmio + MV5_LT_MODE);
1631c9d39130123238ac18478a42e25cb7996eacfcc0Jeff Garzik
1632c9d39130123238ac18478a42e25cb7996eacfcc0Jeff Garzik		tmp = readl(phy_mmio + MV5_PHY_CTL);
1633c9d39130123238ac18478a42e25cb7996eacfcc0Jeff Garzik		tmp &= ~0x3;
1634c9d39130123238ac18478a42e25cb7996eacfcc0Jeff Garzik		tmp |= 0x1;
1635c9d39130123238ac18478a42e25cb7996eacfcc0Jeff Garzik		writel(tmp, phy_mmio + MV5_PHY_CTL);
1636c9d39130123238ac18478a42e25cb7996eacfcc0Jeff Garzik	}
1637c9d39130123238ac18478a42e25cb7996eacfcc0Jeff Garzik
1638c9d39130123238ac18478a42e25cb7996eacfcc0Jeff Garzik	tmp = readl(phy_mmio + MV5_PHY_MODE);
1639c9d39130123238ac18478a42e25cb7996eacfcc0Jeff Garzik	tmp &= ~mask;
1640c9d39130123238ac18478a42e25cb7996eacfcc0Jeff Garzik	tmp |= hpriv->signal[port].pre;
1641c9d39130123238ac18478a42e25cb7996eacfcc0Jeff Garzik	tmp |= hpriv->signal[port].amps;
1642c9d39130123238ac18478a42e25cb7996eacfcc0Jeff Garzik	writel(tmp, phy_mmio + MV5_PHY_MODE);
1643bca1c4eb9411533d613123618c0d127fae532595Jeff Garzik}
1644bca1c4eb9411533d613123618c0d127fae532595Jeff Garzik
1645c9d39130123238ac18478a42e25cb7996eacfcc0Jeff Garzik
1646c9d39130123238ac18478a42e25cb7996eacfcc0Jeff Garzik#undef ZERO
1647c9d39130123238ac18478a42e25cb7996eacfcc0Jeff Garzik#define ZERO(reg) writel(0, port_mmio + (reg))
1648c9d39130123238ac18478a42e25cb7996eacfcc0Jeff Garzikstatic void mv5_reset_hc_port(struct mv_host_priv *hpriv, void __iomem *mmio,
1649c9d39130123238ac18478a42e25cb7996eacfcc0Jeff Garzik			     unsigned int port)
1650c9d39130123238ac18478a42e25cb7996eacfcc0Jeff Garzik{
1651c9d39130123238ac18478a42e25cb7996eacfcc0Jeff Garzik	void __iomem *port_mmio = mv_port_base(mmio, port);
1652c9d39130123238ac18478a42e25cb7996eacfcc0Jeff Garzik
1653c9d39130123238ac18478a42e25cb7996eacfcc0Jeff Garzik	writelfl(EDMA_DS, port_mmio + EDMA_CMD_OFS);
1654c9d39130123238ac18478a42e25cb7996eacfcc0Jeff Garzik
1655c9d39130123238ac18478a42e25cb7996eacfcc0Jeff Garzik	mv_channel_reset(hpriv, mmio, port);
1656c9d39130123238ac18478a42e25cb7996eacfcc0Jeff Garzik
1657c9d39130123238ac18478a42e25cb7996eacfcc0Jeff Garzik	ZERO(0x028);	/* command */
1658c9d39130123238ac18478a42e25cb7996eacfcc0Jeff Garzik	writel(0x11f, port_mmio + EDMA_CFG_OFS);
1659c9d39130123238ac18478a42e25cb7996eacfcc0Jeff Garzik	ZERO(0x004);	/* timer */
1660c9d39130123238ac18478a42e25cb7996eacfcc0Jeff Garzik	ZERO(0x008);	/* irq err cause */
1661c9d39130123238ac18478a42e25cb7996eacfcc0Jeff Garzik	ZERO(0x00c);	/* irq err mask */
1662c9d39130123238ac18478a42e25cb7996eacfcc0Jeff Garzik	ZERO(0x010);	/* rq bah */
1663c9d39130123238ac18478a42e25cb7996eacfcc0Jeff Garzik	ZERO(0x014);	/* rq inp */
1664c9d39130123238ac18478a42e25cb7996eacfcc0Jeff Garzik	ZERO(0x018);	/* rq outp */
1665c9d39130123238ac18478a42e25cb7996eacfcc0Jeff Garzik	ZERO(0x01c);	/* respq bah */
1666c9d39130123238ac18478a42e25cb7996eacfcc0Jeff Garzik	ZERO(0x024);	/* respq outp */
1667c9d39130123238ac18478a42e25cb7996eacfcc0Jeff Garzik	ZERO(0x020);	/* respq inp */
1668c9d39130123238ac18478a42e25cb7996eacfcc0Jeff Garzik	ZERO(0x02c);	/* test control */
1669c9d39130123238ac18478a42e25cb7996eacfcc0Jeff Garzik	writel(0xbc, port_mmio + EDMA_IORDY_TMOUT);
1670c9d39130123238ac18478a42e25cb7996eacfcc0Jeff Garzik}
1671c9d39130123238ac18478a42e25cb7996eacfcc0Jeff Garzik#undef ZERO
1672c9d39130123238ac18478a42e25cb7996eacfcc0Jeff Garzik
1673c9d39130123238ac18478a42e25cb7996eacfcc0Jeff Garzik#define ZERO(reg) writel(0, hc_mmio + (reg))
1674c9d39130123238ac18478a42e25cb7996eacfcc0Jeff Garzikstatic void mv5_reset_one_hc(struct mv_host_priv *hpriv, void __iomem *mmio,
1675c9d39130123238ac18478a42e25cb7996eacfcc0Jeff Garzik			unsigned int hc)
167647c2b677daeed9c79ecb7167c211ff36876ea611Jeff Garzik{
1677c9d39130123238ac18478a42e25cb7996eacfcc0Jeff Garzik	void __iomem *hc_mmio = mv_hc_base(mmio, hc);
1678c9d39130123238ac18478a42e25cb7996eacfcc0Jeff Garzik	u32 tmp;
1679c9d39130123238ac18478a42e25cb7996eacfcc0Jeff Garzik
1680c9d39130123238ac18478a42e25cb7996eacfcc0Jeff Garzik	ZERO(0x00c);
1681c9d39130123238ac18478a42e25cb7996eacfcc0Jeff Garzik	ZERO(0x010);
1682c9d39130123238ac18478a42e25cb7996eacfcc0Jeff Garzik	ZERO(0x014);
1683c9d39130123238ac18478a42e25cb7996eacfcc0Jeff Garzik	ZERO(0x018);
1684c9d39130123238ac18478a42e25cb7996eacfcc0Jeff Garzik
1685c9d39130123238ac18478a42e25cb7996eacfcc0Jeff Garzik	tmp = readl(hc_mmio + 0x20);
1686c9d39130123238ac18478a42e25cb7996eacfcc0Jeff Garzik	tmp &= 0x1c1c1c1c;
1687c9d39130123238ac18478a42e25cb7996eacfcc0Jeff Garzik	tmp |= 0x03030303;
1688c9d39130123238ac18478a42e25cb7996eacfcc0Jeff Garzik	writel(tmp, hc_mmio + 0x20);
1689c9d39130123238ac18478a42e25cb7996eacfcc0Jeff Garzik}
1690c9d39130123238ac18478a42e25cb7996eacfcc0Jeff Garzik#undef ZERO
1691c9d39130123238ac18478a42e25cb7996eacfcc0Jeff Garzik
1692c9d39130123238ac18478a42e25cb7996eacfcc0Jeff Garzikstatic int mv5_reset_hc(struct mv_host_priv *hpriv, void __iomem *mmio,
1693c9d39130123238ac18478a42e25cb7996eacfcc0Jeff Garzik			unsigned int n_hc)
1694c9d39130123238ac18478a42e25cb7996eacfcc0Jeff Garzik{
1695c9d39130123238ac18478a42e25cb7996eacfcc0Jeff Garzik	unsigned int hc, port;
1696c9d39130123238ac18478a42e25cb7996eacfcc0Jeff Garzik
1697c9d39130123238ac18478a42e25cb7996eacfcc0Jeff Garzik	for (hc = 0; hc < n_hc; hc++) {
1698c9d39130123238ac18478a42e25cb7996eacfcc0Jeff Garzik		for (port = 0; port < MV_PORTS_PER_HC; port++)
1699c9d39130123238ac18478a42e25cb7996eacfcc0Jeff Garzik			mv5_reset_hc_port(hpriv, mmio,
1700c9d39130123238ac18478a42e25cb7996eacfcc0Jeff Garzik					  (hc * MV_PORTS_PER_HC) + port);
1701c9d39130123238ac18478a42e25cb7996eacfcc0Jeff Garzik
1702c9d39130123238ac18478a42e25cb7996eacfcc0Jeff Garzik		mv5_reset_one_hc(hpriv, mmio, hc);
1703c9d39130123238ac18478a42e25cb7996eacfcc0Jeff Garzik	}
1704c9d39130123238ac18478a42e25cb7996eacfcc0Jeff Garzik
1705c9d39130123238ac18478a42e25cb7996eacfcc0Jeff Garzik	return 0;
170647c2b677daeed9c79ecb7167c211ff36876ea611Jeff Garzik}
170747c2b677daeed9c79ecb7167c211ff36876ea611Jeff Garzik
1708101ffae26c23ea928fce6d31a8b4901327d91a15Jeff Garzik#undef ZERO
1709101ffae26c23ea928fce6d31a8b4901327d91a15Jeff Garzik#define ZERO(reg) writel(0, mmio + (reg))
1710101ffae26c23ea928fce6d31a8b4901327d91a15Jeff Garzikstatic void mv_reset_pci_bus(struct pci_dev *pdev, void __iomem *mmio)
1711101ffae26c23ea928fce6d31a8b4901327d91a15Jeff Garzik{
1712101ffae26c23ea928fce6d31a8b4901327d91a15Jeff Garzik	u32 tmp;
1713101ffae26c23ea928fce6d31a8b4901327d91a15Jeff Garzik
1714101ffae26c23ea928fce6d31a8b4901327d91a15Jeff Garzik	tmp = readl(mmio + MV_PCI_MODE);
1715101ffae26c23ea928fce6d31a8b4901327d91a15Jeff Garzik	tmp &= 0xff00ffff;
1716101ffae26c23ea928fce6d31a8b4901327d91a15Jeff Garzik	writel(tmp, mmio + MV_PCI_MODE);
1717101ffae26c23ea928fce6d31a8b4901327d91a15Jeff Garzik
1718101ffae26c23ea928fce6d31a8b4901327d91a15Jeff Garzik	ZERO(MV_PCI_DISC_TIMER);
1719101ffae26c23ea928fce6d31a8b4901327d91a15Jeff Garzik	ZERO(MV_PCI_MSI_TRIGGER);
1720101ffae26c23ea928fce6d31a8b4901327d91a15Jeff Garzik	writel(0x000100ff, mmio + MV_PCI_XBAR_TMOUT);
1721101ffae26c23ea928fce6d31a8b4901327d91a15Jeff Garzik	ZERO(HC_MAIN_IRQ_MASK_OFS);
1722101ffae26c23ea928fce6d31a8b4901327d91a15Jeff Garzik	ZERO(MV_PCI_SERR_MASK);
1723101ffae26c23ea928fce6d31a8b4901327d91a15Jeff Garzik	ZERO(PCI_IRQ_CAUSE_OFS);
1724101ffae26c23ea928fce6d31a8b4901327d91a15Jeff Garzik	ZERO(PCI_IRQ_MASK_OFS);
1725101ffae26c23ea928fce6d31a8b4901327d91a15Jeff Garzik	ZERO(MV_PCI_ERR_LOW_ADDRESS);
1726101ffae26c23ea928fce6d31a8b4901327d91a15Jeff Garzik	ZERO(MV_PCI_ERR_HIGH_ADDRESS);
1727101ffae26c23ea928fce6d31a8b4901327d91a15Jeff Garzik	ZERO(MV_PCI_ERR_ATTRIBUTE);
1728101ffae26c23ea928fce6d31a8b4901327d91a15Jeff Garzik	ZERO(MV_PCI_ERR_COMMAND);
1729101ffae26c23ea928fce6d31a8b4901327d91a15Jeff Garzik}
1730101ffae26c23ea928fce6d31a8b4901327d91a15Jeff Garzik#undef ZERO
1731101ffae26c23ea928fce6d31a8b4901327d91a15Jeff Garzik
1732101ffae26c23ea928fce6d31a8b4901327d91a15Jeff Garzikstatic void mv6_reset_flash(struct mv_host_priv *hpriv, void __iomem *mmio)
1733101ffae26c23ea928fce6d31a8b4901327d91a15Jeff Garzik{
1734101ffae26c23ea928fce6d31a8b4901327d91a15Jeff Garzik	u32 tmp;
1735101ffae26c23ea928fce6d31a8b4901327d91a15Jeff Garzik
1736101ffae26c23ea928fce6d31a8b4901327d91a15Jeff Garzik	mv5_reset_flash(hpriv, mmio);
1737101ffae26c23ea928fce6d31a8b4901327d91a15Jeff Garzik
1738101ffae26c23ea928fce6d31a8b4901327d91a15Jeff Garzik	tmp = readl(mmio + MV_GPIO_PORT_CTL);
1739101ffae26c23ea928fce6d31a8b4901327d91a15Jeff Garzik	tmp &= 0x3;
1740101ffae26c23ea928fce6d31a8b4901327d91a15Jeff Garzik	tmp |= (1 << 5) | (1 << 6);
1741101ffae26c23ea928fce6d31a8b4901327d91a15Jeff Garzik	writel(tmp, mmio + MV_GPIO_PORT_CTL);
1742101ffae26c23ea928fce6d31a8b4901327d91a15Jeff Garzik}
1743101ffae26c23ea928fce6d31a8b4901327d91a15Jeff Garzik
1744101ffae26c23ea928fce6d31a8b4901327d91a15Jeff Garzik/**
1745101ffae26c23ea928fce6d31a8b4901327d91a15Jeff Garzik *      mv6_reset_hc - Perform the 6xxx global soft reset
1746101ffae26c23ea928fce6d31a8b4901327d91a15Jeff Garzik *      @mmio: base address of the HBA
1747101ffae26c23ea928fce6d31a8b4901327d91a15Jeff Garzik *
1748101ffae26c23ea928fce6d31a8b4901327d91a15Jeff Garzik *      This routine only applies to 6xxx parts.
1749101ffae26c23ea928fce6d31a8b4901327d91a15Jeff Garzik *
1750101ffae26c23ea928fce6d31a8b4901327d91a15Jeff Garzik *      LOCKING:
1751101ffae26c23ea928fce6d31a8b4901327d91a15Jeff Garzik *      Inherited from caller.
1752101ffae26c23ea928fce6d31a8b4901327d91a15Jeff Garzik */
1753c9d39130123238ac18478a42e25cb7996eacfcc0Jeff Garzikstatic int mv6_reset_hc(struct mv_host_priv *hpriv, void __iomem *mmio,
1754c9d39130123238ac18478a42e25cb7996eacfcc0Jeff Garzik			unsigned int n_hc)
1755101ffae26c23ea928fce6d31a8b4901327d91a15Jeff Garzik{
1756101ffae26c23ea928fce6d31a8b4901327d91a15Jeff Garzik	void __iomem *reg = mmio + PCI_MAIN_CMD_STS_OFS;
1757101ffae26c23ea928fce6d31a8b4901327d91a15Jeff Garzik	int i, rc = 0;
1758101ffae26c23ea928fce6d31a8b4901327d91a15Jeff Garzik	u32 t;
1759101ffae26c23ea928fce6d31a8b4901327d91a15Jeff Garzik
1760101ffae26c23ea928fce6d31a8b4901327d91a15Jeff Garzik	/* Following procedure defined in PCI "main command and status
1761101ffae26c23ea928fce6d31a8b4901327d91a15Jeff Garzik	 * register" table.
1762101ffae26c23ea928fce6d31a8b4901327d91a15Jeff Garzik	 */
1763101ffae26c23ea928fce6d31a8b4901327d91a15Jeff Garzik	t = readl(reg);
1764101ffae26c23ea928fce6d31a8b4901327d91a15Jeff Garzik	writel(t | STOP_PCI_MASTER, reg);
1765101ffae26c23ea928fce6d31a8b4901327d91a15Jeff Garzik
1766101ffae26c23ea928fce6d31a8b4901327d91a15Jeff Garzik	for (i = 0; i < 1000; i++) {
1767101ffae26c23ea928fce6d31a8b4901327d91a15Jeff Garzik		udelay(1);
1768101ffae26c23ea928fce6d31a8b4901327d91a15Jeff Garzik		t = readl(reg);
1769101ffae26c23ea928fce6d31a8b4901327d91a15Jeff Garzik		if (PCI_MASTER_EMPTY & t) {
1770101ffae26c23ea928fce6d31a8b4901327d91a15Jeff Garzik			break;
1771101ffae26c23ea928fce6d31a8b4901327d91a15Jeff Garzik		}
1772101ffae26c23ea928fce6d31a8b4901327d91a15Jeff Garzik	}
1773101ffae26c23ea928fce6d31a8b4901327d91a15Jeff Garzik	if (!(PCI_MASTER_EMPTY & t)) {
1774101ffae26c23ea928fce6d31a8b4901327d91a15Jeff Garzik		printk(KERN_ERR DRV_NAME ": PCI master won't flush\n");
1775101ffae26c23ea928fce6d31a8b4901327d91a15Jeff Garzik		rc = 1;
1776101ffae26c23ea928fce6d31a8b4901327d91a15Jeff Garzik		goto done;
1777101ffae26c23ea928fce6d31a8b4901327d91a15Jeff Garzik	}
1778101ffae26c23ea928fce6d31a8b4901327d91a15Jeff Garzik
1779101ffae26c23ea928fce6d31a8b4901327d91a15Jeff Garzik	/* set reset */
1780101ffae26c23ea928fce6d31a8b4901327d91a15Jeff Garzik	i = 5;
1781101ffae26c23ea928fce6d31a8b4901327d91a15Jeff Garzik	do {
1782101ffae26c23ea928fce6d31a8b4901327d91a15Jeff Garzik		writel(t | GLOB_SFT_RST, reg);
1783101ffae26c23ea928fce6d31a8b4901327d91a15Jeff Garzik		t = readl(reg);
1784101ffae26c23ea928fce6d31a8b4901327d91a15Jeff Garzik		udelay(1);
1785101ffae26c23ea928fce6d31a8b4901327d91a15Jeff Garzik	} while (!(GLOB_SFT_RST & t) && (i-- > 0));
1786101ffae26c23ea928fce6d31a8b4901327d91a15Jeff Garzik
1787101ffae26c23ea928fce6d31a8b4901327d91a15Jeff Garzik	if (!(GLOB_SFT_RST & t)) {
1788101ffae26c23ea928fce6d31a8b4901327d91a15Jeff Garzik		printk(KERN_ERR DRV_NAME ": can't set global reset\n");
1789101ffae26c23ea928fce6d31a8b4901327d91a15Jeff Garzik		rc = 1;
1790101ffae26c23ea928fce6d31a8b4901327d91a15Jeff Garzik		goto done;
1791101ffae26c23ea928fce6d31a8b4901327d91a15Jeff Garzik	}
1792101ffae26c23ea928fce6d31a8b4901327d91a15Jeff Garzik
1793101ffae26c23ea928fce6d31a8b4901327d91a15Jeff Garzik	/* clear reset and *reenable the PCI master* (not mentioned in spec) */
1794101ffae26c23ea928fce6d31a8b4901327d91a15Jeff Garzik	i = 5;
1795101ffae26c23ea928fce6d31a8b4901327d91a15Jeff Garzik	do {
1796101ffae26c23ea928fce6d31a8b4901327d91a15Jeff Garzik		writel(t & ~(GLOB_SFT_RST | STOP_PCI_MASTER), reg);
1797101ffae26c23ea928fce6d31a8b4901327d91a15Jeff Garzik		t = readl(reg);
1798101ffae26c23ea928fce6d31a8b4901327d91a15Jeff Garzik		udelay(1);
1799101ffae26c23ea928fce6d31a8b4901327d91a15Jeff Garzik	} while ((GLOB_SFT_RST & t) && (i-- > 0));
1800101ffae26c23ea928fce6d31a8b4901327d91a15Jeff Garzik
1801101ffae26c23ea928fce6d31a8b4901327d91a15Jeff Garzik	if (GLOB_SFT_RST & t) {
1802101ffae26c23ea928fce6d31a8b4901327d91a15Jeff Garzik		printk(KERN_ERR DRV_NAME ": can't clear global reset\n");
1803101ffae26c23ea928fce6d31a8b4901327d91a15Jeff Garzik		rc = 1;
1804101ffae26c23ea928fce6d31a8b4901327d91a15Jeff Garzik	}
1805101ffae26c23ea928fce6d31a8b4901327d91a15Jeff Garzikdone:
1806101ffae26c23ea928fce6d31a8b4901327d91a15Jeff Garzik	return rc;
1807101ffae26c23ea928fce6d31a8b4901327d91a15Jeff Garzik}
1808101ffae26c23ea928fce6d31a8b4901327d91a15Jeff Garzik
180947c2b677daeed9c79ecb7167c211ff36876ea611Jeff Garzikstatic void mv6_read_preamp(struct mv_host_priv *hpriv, int idx,
1810ba3fe8fb6a469390a14379519915f3c39a973d99Jeff Garzik			   void __iomem *mmio)
1811ba3fe8fb6a469390a14379519915f3c39a973d99Jeff Garzik{
1812ba3fe8fb6a469390a14379519915f3c39a973d99Jeff Garzik	void __iomem *port_mmio;
1813ba3fe8fb6a469390a14379519915f3c39a973d99Jeff Garzik	u32 tmp;
1814ba3fe8fb6a469390a14379519915f3c39a973d99Jeff Garzik
1815ba3fe8fb6a469390a14379519915f3c39a973d99Jeff Garzik	tmp = readl(mmio + MV_RESET_CFG);
1816ba3fe8fb6a469390a14379519915f3c39a973d99Jeff Garzik	if ((tmp & (1 << 0)) == 0) {
181747c2b677daeed9c79ecb7167c211ff36876ea611Jeff Garzik		hpriv->signal[idx].amps = 0x7 << 8;
1818ba3fe8fb6a469390a14379519915f3c39a973d99Jeff Garzik		hpriv->signal[idx].pre = 0x1 << 5;
1819ba3fe8fb6a469390a14379519915f3c39a973d99Jeff Garzik		return;
1820ba3fe8fb6a469390a14379519915f3c39a973d99Jeff Garzik	}
1821ba3fe8fb6a469390a14379519915f3c39a973d99Jeff Garzik
1822ba3fe8fb6a469390a14379519915f3c39a973d99Jeff Garzik	port_mmio = mv_port_base(mmio, idx);
1823ba3fe8fb6a469390a14379519915f3c39a973d99Jeff Garzik	tmp = readl(port_mmio + PHY_MODE2);
1824ba3fe8fb6a469390a14379519915f3c39a973d99Jeff Garzik
1825ba3fe8fb6a469390a14379519915f3c39a973d99Jeff Garzik	hpriv->signal[idx].amps = tmp & 0x700;	/* bits 10:8 */
1826ba3fe8fb6a469390a14379519915f3c39a973d99Jeff Garzik	hpriv->signal[idx].pre = tmp & 0xe0;	/* bits 7:5 */
1827ba3fe8fb6a469390a14379519915f3c39a973d99Jeff Garzik}
1828ba3fe8fb6a469390a14379519915f3c39a973d99Jeff Garzik
182947c2b677daeed9c79ecb7167c211ff36876ea611Jeff Garzikstatic void mv6_enable_leds(struct mv_host_priv *hpriv, void __iomem *mmio)
1830ba3fe8fb6a469390a14379519915f3c39a973d99Jeff Garzik{
183147c2b677daeed9c79ecb7167c211ff36876ea611Jeff Garzik	writel(0x00000060, mmio + MV_GPIO_PORT_CTL);
1832ba3fe8fb6a469390a14379519915f3c39a973d99Jeff Garzik}
1833ba3fe8fb6a469390a14379519915f3c39a973d99Jeff Garzik
1834c9d39130123238ac18478a42e25cb7996eacfcc0Jeff Garzikstatic void mv6_phy_errata(struct mv_host_priv *hpriv, void __iomem *mmio,
18352a47ce06d534692f9bd2bf4e90a20fc9b1054c39Jeff Garzik			   unsigned int port)
1836bca1c4eb9411533d613123618c0d127fae532595Jeff Garzik{
1837c9d39130123238ac18478a42e25cb7996eacfcc0Jeff Garzik	void __iomem *port_mmio = mv_port_base(mmio, port);
1838c9d39130123238ac18478a42e25cb7996eacfcc0Jeff Garzik
1839bca1c4eb9411533d613123618c0d127fae532595Jeff Garzik	u32 hp_flags = hpriv->hp_flags;
184047c2b677daeed9c79ecb7167c211ff36876ea611Jeff Garzik	int fix_phy_mode2 =
184147c2b677daeed9c79ecb7167c211ff36876ea611Jeff Garzik		hp_flags & (MV_HP_ERRATA_60X1B2 | MV_HP_ERRATA_60X1C0);
1842bca1c4eb9411533d613123618c0d127fae532595Jeff Garzik	int fix_phy_mode4 =
184347c2b677daeed9c79ecb7167c211ff36876ea611Jeff Garzik		hp_flags & (MV_HP_ERRATA_60X1B2 | MV_HP_ERRATA_60X1C0);
184447c2b677daeed9c79ecb7167c211ff36876ea611Jeff Garzik	u32 m2, tmp;
184547c2b677daeed9c79ecb7167c211ff36876ea611Jeff Garzik
184647c2b677daeed9c79ecb7167c211ff36876ea611Jeff Garzik	if (fix_phy_mode2) {
184747c2b677daeed9c79ecb7167c211ff36876ea611Jeff Garzik		m2 = readl(port_mmio + PHY_MODE2);
184847c2b677daeed9c79ecb7167c211ff36876ea611Jeff Garzik		m2 &= ~(1 << 16);
184947c2b677daeed9c79ecb7167c211ff36876ea611Jeff Garzik		m2 |= (1 << 31);
185047c2b677daeed9c79ecb7167c211ff36876ea611Jeff Garzik		writel(m2, port_mmio + PHY_MODE2);
185147c2b677daeed9c79ecb7167c211ff36876ea611Jeff Garzik
185247c2b677daeed9c79ecb7167c211ff36876ea611Jeff Garzik		udelay(200);
185347c2b677daeed9c79ecb7167c211ff36876ea611Jeff Garzik
185447c2b677daeed9c79ecb7167c211ff36876ea611Jeff Garzik		m2 = readl(port_mmio + PHY_MODE2);
185547c2b677daeed9c79ecb7167c211ff36876ea611Jeff Garzik		m2 &= ~((1 << 16) | (1 << 31));
185647c2b677daeed9c79ecb7167c211ff36876ea611Jeff Garzik		writel(m2, port_mmio + PHY_MODE2);
185747c2b677daeed9c79ecb7167c211ff36876ea611Jeff Garzik
185847c2b677daeed9c79ecb7167c211ff36876ea611Jeff Garzik		udelay(200);
185947c2b677daeed9c79ecb7167c211ff36876ea611Jeff Garzik	}
186047c2b677daeed9c79ecb7167c211ff36876ea611Jeff Garzik
186147c2b677daeed9c79ecb7167c211ff36876ea611Jeff Garzik	/* who knows what this magic does */
186247c2b677daeed9c79ecb7167c211ff36876ea611Jeff Garzik	tmp = readl(port_mmio + PHY_MODE3);
186347c2b677daeed9c79ecb7167c211ff36876ea611Jeff Garzik	tmp &= ~0x7F800000;
186447c2b677daeed9c79ecb7167c211ff36876ea611Jeff Garzik	tmp |= 0x2A800000;
186547c2b677daeed9c79ecb7167c211ff36876ea611Jeff Garzik	writel(tmp, port_mmio + PHY_MODE3);
1866bca1c4eb9411533d613123618c0d127fae532595Jeff Garzik
1867bca1c4eb9411533d613123618c0d127fae532595Jeff Garzik	if (fix_phy_mode4) {
186847c2b677daeed9c79ecb7167c211ff36876ea611Jeff Garzik		u32 m4;
1869bca1c4eb9411533d613123618c0d127fae532595Jeff Garzik
1870bca1c4eb9411533d613123618c0d127fae532595Jeff Garzik		m4 = readl(port_mmio + PHY_MODE4);
187147c2b677daeed9c79ecb7167c211ff36876ea611Jeff Garzik
187247c2b677daeed9c79ecb7167c211ff36876ea611Jeff Garzik		if (hp_flags & MV_HP_ERRATA_60X1B2)
187347c2b677daeed9c79ecb7167c211ff36876ea611Jeff Garzik			tmp = readl(port_mmio + 0x310);
1874bca1c4eb9411533d613123618c0d127fae532595Jeff Garzik
1875bca1c4eb9411533d613123618c0d127fae532595Jeff Garzik		m4 = (m4 & ~(1 << 1)) | (1 << 0);
1876bca1c4eb9411533d613123618c0d127fae532595Jeff Garzik
1877bca1c4eb9411533d613123618c0d127fae532595Jeff Garzik		writel(m4, port_mmio + PHY_MODE4);
187847c2b677daeed9c79ecb7167c211ff36876ea611Jeff Garzik
187947c2b677daeed9c79ecb7167c211ff36876ea611Jeff Garzik		if (hp_flags & MV_HP_ERRATA_60X1B2)
188047c2b677daeed9c79ecb7167c211ff36876ea611Jeff Garzik			writel(tmp, port_mmio + 0x310);
1881bca1c4eb9411533d613123618c0d127fae532595Jeff Garzik	}
1882bca1c4eb9411533d613123618c0d127fae532595Jeff Garzik
1883bca1c4eb9411533d613123618c0d127fae532595Jeff Garzik	/* Revert values of pre-emphasis and signal amps to the saved ones */
1884bca1c4eb9411533d613123618c0d127fae532595Jeff Garzik	m2 = readl(port_mmio + PHY_MODE2);
1885bca1c4eb9411533d613123618c0d127fae532595Jeff Garzik
1886bca1c4eb9411533d613123618c0d127fae532595Jeff Garzik	m2 &= ~MV_M2_PREAMP_MASK;
18872a47ce06d534692f9bd2bf4e90a20fc9b1054c39Jeff Garzik	m2 |= hpriv->signal[port].amps;
18882a47ce06d534692f9bd2bf4e90a20fc9b1054c39Jeff Garzik	m2 |= hpriv->signal[port].pre;
188947c2b677daeed9c79ecb7167c211ff36876ea611Jeff Garzik	m2 &= ~(1 << 16);
1890bca1c4eb9411533d613123618c0d127fae532595Jeff Garzik
1891e4e7b89280d1d666e2c09e5ad36cf071796c4c7eJeff Garzik	/* according to mvSata 3.6.1, some IIE values are fixed */
1892e4e7b89280d1d666e2c09e5ad36cf071796c4c7eJeff Garzik	if (IS_GEN_IIE(hpriv)) {
1893e4e7b89280d1d666e2c09e5ad36cf071796c4c7eJeff Garzik		m2 &= ~0xC30FF01F;
1894e4e7b89280d1d666e2c09e5ad36cf071796c4c7eJeff Garzik		m2 |= 0x0000900F;
1895e4e7b89280d1d666e2c09e5ad36cf071796c4c7eJeff Garzik	}
1896e4e7b89280d1d666e2c09e5ad36cf071796c4c7eJeff Garzik
1897bca1c4eb9411533d613123618c0d127fae532595Jeff Garzik	writel(m2, port_mmio + PHY_MODE2);
1898bca1c4eb9411533d613123618c0d127fae532595Jeff Garzik}
1899bca1c4eb9411533d613123618c0d127fae532595Jeff Garzik
1900c9d39130123238ac18478a42e25cb7996eacfcc0Jeff Garzikstatic void mv_channel_reset(struct mv_host_priv *hpriv, void __iomem *mmio,
1901c9d39130123238ac18478a42e25cb7996eacfcc0Jeff Garzik			     unsigned int port_no)
1902c9d39130123238ac18478a42e25cb7996eacfcc0Jeff Garzik{
1903c9d39130123238ac18478a42e25cb7996eacfcc0Jeff Garzik	void __iomem *port_mmio = mv_port_base(mmio, port_no);
1904c9d39130123238ac18478a42e25cb7996eacfcc0Jeff Garzik
1905c9d39130123238ac18478a42e25cb7996eacfcc0Jeff Garzik	writelfl(ATA_RST, port_mmio + EDMA_CMD_OFS);
1906c9d39130123238ac18478a42e25cb7996eacfcc0Jeff Garzik
1907c9d39130123238ac18478a42e25cb7996eacfcc0Jeff Garzik	if (IS_60XX(hpriv)) {
1908c9d39130123238ac18478a42e25cb7996eacfcc0Jeff Garzik		u32 ifctl = readl(port_mmio + SATA_INTERFACE_CTL);
1909eb46d684600ac145501805a294c94675e82eab2eMark Lord		ifctl |= (1 << 7);		/* enable gen2i speed */
1910eb46d684600ac145501805a294c94675e82eab2eMark Lord		ifctl = (ifctl & 0xfff) | 0x9b1000; /* from chip spec */
1911c9d39130123238ac18478a42e25cb7996eacfcc0Jeff Garzik		writelfl(ifctl, port_mmio + SATA_INTERFACE_CTL);
1912c9d39130123238ac18478a42e25cb7996eacfcc0Jeff Garzik	}
1913c9d39130123238ac18478a42e25cb7996eacfcc0Jeff Garzik
1914c9d39130123238ac18478a42e25cb7996eacfcc0Jeff Garzik	udelay(25);		/* allow reset propagation */
1915c9d39130123238ac18478a42e25cb7996eacfcc0Jeff Garzik
1916c9d39130123238ac18478a42e25cb7996eacfcc0Jeff Garzik	/* Spec never mentions clearing the bit.  Marvell's driver does
1917c9d39130123238ac18478a42e25cb7996eacfcc0Jeff Garzik	 * clear the bit, however.
1918c9d39130123238ac18478a42e25cb7996eacfcc0Jeff Garzik	 */
1919c9d39130123238ac18478a42e25cb7996eacfcc0Jeff Garzik	writelfl(0, port_mmio + EDMA_CMD_OFS);
1920c9d39130123238ac18478a42e25cb7996eacfcc0Jeff Garzik
1921c9d39130123238ac18478a42e25cb7996eacfcc0Jeff Garzik	hpriv->ops->phy_errata(hpriv, mmio, port_no);
1922c9d39130123238ac18478a42e25cb7996eacfcc0Jeff Garzik
1923c9d39130123238ac18478a42e25cb7996eacfcc0Jeff Garzik	if (IS_50XX(hpriv))
1924c9d39130123238ac18478a42e25cb7996eacfcc0Jeff Garzik		mdelay(1);
1925c9d39130123238ac18478a42e25cb7996eacfcc0Jeff Garzik}
1926c9d39130123238ac18478a42e25cb7996eacfcc0Jeff Garzik
1927c9d39130123238ac18478a42e25cb7996eacfcc0Jeff Garzikstatic void mv_stop_and_reset(struct ata_port *ap)
1928c9d39130123238ac18478a42e25cb7996eacfcc0Jeff Garzik{
1929cca3974e48607c3775dc73b544a5700b2e37c21aJeff Garzik	struct mv_host_priv *hpriv = ap->host->private_data;
19300d5ff566779f894ca9937231a181eb31e4adff0eTejun Heo	void __iomem *mmio = ap->host->iomap[MV_PRIMARY_BAR];
1931c9d39130123238ac18478a42e25cb7996eacfcc0Jeff Garzik
1932c9d39130123238ac18478a42e25cb7996eacfcc0Jeff Garzik	mv_stop_dma(ap);
1933c9d39130123238ac18478a42e25cb7996eacfcc0Jeff Garzik
1934c9d39130123238ac18478a42e25cb7996eacfcc0Jeff Garzik	mv_channel_reset(hpriv, mmio, ap->port_no);
1935c9d39130123238ac18478a42e25cb7996eacfcc0Jeff Garzik
193622374677d18c5eeefd3a283431d312b8c44fef02Jeff Garzik	__mv_phy_reset(ap, 0);
193722374677d18c5eeefd3a283431d312b8c44fef02Jeff Garzik}
193822374677d18c5eeefd3a283431d312b8c44fef02Jeff Garzik
193922374677d18c5eeefd3a283431d312b8c44fef02Jeff Garzikstatic inline void __msleep(unsigned int msec, int can_sleep)
194022374677d18c5eeefd3a283431d312b8c44fef02Jeff Garzik{
194122374677d18c5eeefd3a283431d312b8c44fef02Jeff Garzik	if (can_sleep)
194222374677d18c5eeefd3a283431d312b8c44fef02Jeff Garzik		msleep(msec);
194322374677d18c5eeefd3a283431d312b8c44fef02Jeff Garzik	else
194422374677d18c5eeefd3a283431d312b8c44fef02Jeff Garzik		mdelay(msec);
1945c9d39130123238ac18478a42e25cb7996eacfcc0Jeff Garzik}
1946c9d39130123238ac18478a42e25cb7996eacfcc0Jeff Garzik
194705b308e1df6d9d673daedb517969241f41278b52Brett Russ/**
194822374677d18c5eeefd3a283431d312b8c44fef02Jeff Garzik *      __mv_phy_reset - Perform eDMA reset followed by COMRESET
194905b308e1df6d9d673daedb517969241f41278b52Brett Russ *      @ap: ATA channel to manipulate
195005b308e1df6d9d673daedb517969241f41278b52Brett Russ *
195105b308e1df6d9d673daedb517969241f41278b52Brett Russ *      Part of this is taken from __sata_phy_reset and modified to
195205b308e1df6d9d673daedb517969241f41278b52Brett Russ *      not sleep since this routine gets called from interrupt level.
195305b308e1df6d9d673daedb517969241f41278b52Brett Russ *
195405b308e1df6d9d673daedb517969241f41278b52Brett Russ *      LOCKING:
195505b308e1df6d9d673daedb517969241f41278b52Brett Russ *      Inherited from caller.  This is coded to safe to call at
195605b308e1df6d9d673daedb517969241f41278b52Brett Russ *      interrupt level, i.e. it does not sleep.
195731961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ */
195822374677d18c5eeefd3a283431d312b8c44fef02Jeff Garzikstatic void __mv_phy_reset(struct ata_port *ap, int can_sleep)
195920f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ{
1960095fec887eaa1c38d17c0c929a6733c744a9fa1fJeff Garzik	struct mv_port_priv *pp	= ap->private_data;
1961cca3974e48607c3775dc73b544a5700b2e37c21aJeff Garzik	struct mv_host_priv *hpriv = ap->host->private_data;
196220f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ	void __iomem *port_mmio = mv_ap_base(ap);
196320f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ	struct ata_taskfile tf;
196420f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ	struct ata_device *dev = &ap->device[0];
196531961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ	unsigned long timeout;
196622374677d18c5eeefd3a283431d312b8c44fef02Jeff Garzik	int retry = 5;
196722374677d18c5eeefd3a283431d312b8c44fef02Jeff Garzik	u32 sstatus;
196820f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ
196920f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ	VPRINTK("ENTER, port %u, mmio 0x%p\n", ap->port_no, port_mmio);
197020f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ
1971095fec887eaa1c38d17c0c929a6733c744a9fa1fJeff Garzik	DPRINTK("S-regs after ATA_RST: SStat 0x%08x SErr 0x%08x "
197231961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ		"SCtrl 0x%08x\n", mv_scr_read(ap, SCR_STATUS),
197331961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ		mv_scr_read(ap, SCR_ERROR), mv_scr_read(ap, SCR_CONTROL));
197420f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ
197522374677d18c5eeefd3a283431d312b8c44fef02Jeff Garzik	/* Issue COMRESET via SControl */
197622374677d18c5eeefd3a283431d312b8c44fef02Jeff Garzikcomreset_retry:
197781952c5497b40ae56835bd0d6537f8c6bdea07e7Tejun Heo	sata_scr_write_flush(ap, SCR_CONTROL, 0x301);
197822374677d18c5eeefd3a283431d312b8c44fef02Jeff Garzik	__msleep(1, can_sleep);
197922374677d18c5eeefd3a283431d312b8c44fef02Jeff Garzik
198081952c5497b40ae56835bd0d6537f8c6bdea07e7Tejun Heo	sata_scr_write_flush(ap, SCR_CONTROL, 0x300);
198122374677d18c5eeefd3a283431d312b8c44fef02Jeff Garzik	__msleep(20, can_sleep);
198222374677d18c5eeefd3a283431d312b8c44fef02Jeff Garzik
198322374677d18c5eeefd3a283431d312b8c44fef02Jeff Garzik	timeout = jiffies + msecs_to_jiffies(200);
198431961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ	do {
198581952c5497b40ae56835bd0d6537f8c6bdea07e7Tejun Heo		sata_scr_read(ap, SCR_STATUS, &sstatus);
198662f1d0e6de138b91d55fbd7d579c837ed62e9e31Andres Salomon		if (((sstatus & 0x3) == 3) || ((sstatus & 0x3) == 0))
198731961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ			break;
198822374677d18c5eeefd3a283431d312b8c44fef02Jeff Garzik
198922374677d18c5eeefd3a283431d312b8c44fef02Jeff Garzik		__msleep(1, can_sleep);
199031961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ	} while (time_before(jiffies, timeout));
199120f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ
199222374677d18c5eeefd3a283431d312b8c44fef02Jeff Garzik	/* work around errata */
199322374677d18c5eeefd3a283431d312b8c44fef02Jeff Garzik	if (IS_60XX(hpriv) &&
199422374677d18c5eeefd3a283431d312b8c44fef02Jeff Garzik	    (sstatus != 0x0) && (sstatus != 0x113) && (sstatus != 0x123) &&
199522374677d18c5eeefd3a283431d312b8c44fef02Jeff Garzik	    (retry-- > 0))
199622374677d18c5eeefd3a283431d312b8c44fef02Jeff Garzik		goto comreset_retry;
1997095fec887eaa1c38d17c0c929a6733c744a9fa1fJeff Garzik
1998095fec887eaa1c38d17c0c929a6733c744a9fa1fJeff Garzik	DPRINTK("S-regs after PHY wake: SStat 0x%08x SErr 0x%08x "
199931961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ		"SCtrl 0x%08x\n", mv_scr_read(ap, SCR_STATUS),
200031961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ		mv_scr_read(ap, SCR_ERROR), mv_scr_read(ap, SCR_CONTROL));
200131961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ
200281952c5497b40ae56835bd0d6537f8c6bdea07e7Tejun Heo	if (ata_port_online(ap)) {
200331961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ		ata_port_probe(ap);
200431961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ	} else {
200581952c5497b40ae56835bd0d6537f8c6bdea07e7Tejun Heo		sata_scr_read(ap, SCR_STATUS, &sstatus);
2006f15a1dafed22d5037e0feea7528e1eeb28a1a7a3Tejun Heo		ata_port_printk(ap, KERN_INFO,
2007f15a1dafed22d5037e0feea7528e1eeb28a1a7a3Tejun Heo				"no device found (phy stat %08x)\n", sstatus);
200831961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ		ata_port_disable(ap);
200920f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ		return;
201020f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ	}
201120f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ
201222374677d18c5eeefd3a283431d312b8c44fef02Jeff Garzik	/* even after SStatus reflects that device is ready,
201322374677d18c5eeefd3a283431d312b8c44fef02Jeff Garzik	 * it seems to take a while for link to be fully
201422374677d18c5eeefd3a283431d312b8c44fef02Jeff Garzik	 * established (and thus Status no longer 0x80/0x7F),
201522374677d18c5eeefd3a283431d312b8c44fef02Jeff Garzik	 * so we poll a bit for that, here.
201622374677d18c5eeefd3a283431d312b8c44fef02Jeff Garzik	 */
201722374677d18c5eeefd3a283431d312b8c44fef02Jeff Garzik	retry = 20;
201822374677d18c5eeefd3a283431d312b8c44fef02Jeff Garzik	while (1) {
201922374677d18c5eeefd3a283431d312b8c44fef02Jeff Garzik		u8 drv_stat = ata_check_status(ap);
202022374677d18c5eeefd3a283431d312b8c44fef02Jeff Garzik		if ((drv_stat != 0x80) && (drv_stat != 0x7f))
202122374677d18c5eeefd3a283431d312b8c44fef02Jeff Garzik			break;
202222374677d18c5eeefd3a283431d312b8c44fef02Jeff Garzik		__msleep(500, can_sleep);
202322374677d18c5eeefd3a283431d312b8c44fef02Jeff Garzik		if (retry-- <= 0)
202422374677d18c5eeefd3a283431d312b8c44fef02Jeff Garzik			break;
202522374677d18c5eeefd3a283431d312b8c44fef02Jeff Garzik	}
202622374677d18c5eeefd3a283431d312b8c44fef02Jeff Garzik
20270d5ff566779f894ca9937231a181eb31e4adff0eTejun Heo	tf.lbah = readb(ap->ioaddr.lbah_addr);
20280d5ff566779f894ca9937231a181eb31e4adff0eTejun Heo	tf.lbam = readb(ap->ioaddr.lbam_addr);
20290d5ff566779f894ca9937231a181eb31e4adff0eTejun Heo	tf.lbal = readb(ap->ioaddr.lbal_addr);
20300d5ff566779f894ca9937231a181eb31e4adff0eTejun Heo	tf.nsect = readb(ap->ioaddr.nsect_addr);
203120f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ
203220f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ	dev->class = ata_dev_classify(&tf);
2033e1211e3fa7fd05ff0d4f597fd37e40de8acc6784Tejun Heo	if (!ata_dev_enabled(dev)) {
203420f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ		VPRINTK("Port disabled post-sig: No device present.\n");
203520f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ		ata_port_disable(ap);
203620f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ	}
2037095fec887eaa1c38d17c0c929a6733c744a9fa1fJeff Garzik
2038095fec887eaa1c38d17c0c929a6733c744a9fa1fJeff Garzik	writelfl(0, port_mmio + EDMA_ERR_IRQ_CAUSE_OFS);
2039095fec887eaa1c38d17c0c929a6733c744a9fa1fJeff Garzik
2040095fec887eaa1c38d17c0c929a6733c744a9fa1fJeff Garzik	pp->pp_flags &= ~MV_PP_FLAG_EDMA_EN;
2041095fec887eaa1c38d17c0c929a6733c744a9fa1fJeff Garzik
2042bca1c4eb9411533d613123618c0d127fae532595Jeff Garzik	VPRINTK("EXIT\n");
204320f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ}
204420f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ
204522374677d18c5eeefd3a283431d312b8c44fef02Jeff Garzikstatic void mv_phy_reset(struct ata_port *ap)
204622374677d18c5eeefd3a283431d312b8c44fef02Jeff Garzik{
204722374677d18c5eeefd3a283431d312b8c44fef02Jeff Garzik	__mv_phy_reset(ap, 1);
204822374677d18c5eeefd3a283431d312b8c44fef02Jeff Garzik}
204922374677d18c5eeefd3a283431d312b8c44fef02Jeff Garzik
205005b308e1df6d9d673daedb517969241f41278b52Brett Russ/**
205105b308e1df6d9d673daedb517969241f41278b52Brett Russ *      mv_eng_timeout - Routine called by libata when SCSI times out I/O
205205b308e1df6d9d673daedb517969241f41278b52Brett Russ *      @ap: ATA channel to manipulate
205305b308e1df6d9d673daedb517969241f41278b52Brett Russ *
205405b308e1df6d9d673daedb517969241f41278b52Brett Russ *      Intent is to clear all pending error conditions, reset the
205505b308e1df6d9d673daedb517969241f41278b52Brett Russ *      chip/bus, fail the command, and move on.
205605b308e1df6d9d673daedb517969241f41278b52Brett Russ *
205705b308e1df6d9d673daedb517969241f41278b52Brett Russ *      LOCKING:
2058cca3974e48607c3775dc73b544a5700b2e37c21aJeff Garzik *      This routine holds the host lock while failing the command.
205905b308e1df6d9d673daedb517969241f41278b52Brett Russ */
206031961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russstatic void mv_eng_timeout(struct ata_port *ap)
206131961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ{
20620d5ff566779f894ca9937231a181eb31e4adff0eTejun Heo	void __iomem *mmio = ap->host->iomap[MV_PRIMARY_BAR];
206331961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ	struct ata_queued_cmd *qc;
20642f9719b61e1fcf7422a016ac4f2420a0cc6ba320Mark Lord	unsigned long flags;
206531961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ
2066f15a1dafed22d5037e0feea7528e1eeb28a1a7a3Tejun Heo	ata_port_printk(ap, KERN_ERR, "Entering mv_eng_timeout\n");
206731961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ	DPRINTK("All regs @ start of eng_timeout\n");
20680d5ff566779f894ca9937231a181eb31e4adff0eTejun Heo	mv_dump_all_regs(mmio, ap->port_no, to_pci_dev(ap->host->dev));
206931961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ
207031961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ	qc = ata_qc_from_tag(ap, ap->active_tag);
207131961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ        printk(KERN_ERR "mmio_base %p ap %p qc %p scsi_cmnd %p &cmnd %p\n",
20720d5ff566779f894ca9937231a181eb31e4adff0eTejun Heo	       mmio, ap, qc, qc->scsicmd, &qc->scsicmd->cmnd);
207331961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ
2074cca3974e48607c3775dc73b544a5700b2e37c21aJeff Garzik	spin_lock_irqsave(&ap->host->lock, flags);
20759b358e305c1d783c8a4ebf00344e95deb9e38f3dMark Lord	mv_err_intr(ap, 0);
2076c9d39130123238ac18478a42e25cb7996eacfcc0Jeff Garzik	mv_stop_and_reset(ap);
2077cca3974e48607c3775dc73b544a5700b2e37c21aJeff Garzik	spin_unlock_irqrestore(&ap->host->lock, flags);
207831961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ
20799b358e305c1d783c8a4ebf00344e95deb9e38f3dMark Lord	WARN_ON(!(qc->flags & ATA_QCFLAG_ACTIVE));
20809b358e305c1d783c8a4ebf00344e95deb9e38f3dMark Lord	if (qc->flags & ATA_QCFLAG_ACTIVE) {
20819b358e305c1d783c8a4ebf00344e95deb9e38f3dMark Lord		qc->err_mask |= AC_ERR_TIMEOUT;
20829b358e305c1d783c8a4ebf00344e95deb9e38f3dMark Lord		ata_eh_qc_complete(qc);
20839b358e305c1d783c8a4ebf00344e95deb9e38f3dMark Lord	}
208431961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ}
208531961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ
208605b308e1df6d9d673daedb517969241f41278b52Brett Russ/**
208705b308e1df6d9d673daedb517969241f41278b52Brett Russ *      mv_port_init - Perform some early initialization on a single port.
208805b308e1df6d9d673daedb517969241f41278b52Brett Russ *      @port: libata data structure storing shadow register addresses
208905b308e1df6d9d673daedb517969241f41278b52Brett Russ *      @port_mmio: base address of the port
209005b308e1df6d9d673daedb517969241f41278b52Brett Russ *
209105b308e1df6d9d673daedb517969241f41278b52Brett Russ *      Initialize shadow register mmio addresses, clear outstanding
209205b308e1df6d9d673daedb517969241f41278b52Brett Russ *      interrupts on the port, and unmask interrupts for the future
209305b308e1df6d9d673daedb517969241f41278b52Brett Russ *      start of the port.
209405b308e1df6d9d673daedb517969241f41278b52Brett Russ *
209505b308e1df6d9d673daedb517969241f41278b52Brett Russ *      LOCKING:
209605b308e1df6d9d673daedb517969241f41278b52Brett Russ *      Inherited from caller.
209705b308e1df6d9d673daedb517969241f41278b52Brett Russ */
209831961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russstatic void mv_port_init(struct ata_ioports *port,  void __iomem *port_mmio)
209920f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ{
21000d5ff566779f894ca9937231a181eb31e4adff0eTejun Heo	void __iomem *shd_base = port_mmio + SHD_BLK_OFS;
210131961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ	unsigned serr_ofs;
210231961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ
21038b260248d9e0e8b64bb72fd4dee03ad86984c344Jeff Garzik	/* PIO related setup
210431961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ	 */
210531961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ	port->data_addr = shd_base + (sizeof(u32) * ATA_REG_DATA);
21068b260248d9e0e8b64bb72fd4dee03ad86984c344Jeff Garzik	port->error_addr =
210731961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ		port->feature_addr = shd_base + (sizeof(u32) * ATA_REG_ERR);
210831961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ	port->nsect_addr = shd_base + (sizeof(u32) * ATA_REG_NSECT);
210931961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ	port->lbal_addr = shd_base + (sizeof(u32) * ATA_REG_LBAL);
211031961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ	port->lbam_addr = shd_base + (sizeof(u32) * ATA_REG_LBAM);
211131961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ	port->lbah_addr = shd_base + (sizeof(u32) * ATA_REG_LBAH);
211231961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ	port->device_addr = shd_base + (sizeof(u32) * ATA_REG_DEVICE);
21138b260248d9e0e8b64bb72fd4dee03ad86984c344Jeff Garzik	port->status_addr =
211431961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ		port->command_addr = shd_base + (sizeof(u32) * ATA_REG_STATUS);
211531961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ	/* special case: control/altstatus doesn't have ATA_REG_ address */
211631961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ	port->altstatus_addr = port->ctl_addr = shd_base + SHD_CTL_AST_OFS;
211731961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ
211831961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ	/* unused: */
21198d9db2d2fbae9e05022825c32f86e00c8e342860Randy Dunlap	port->cmd_addr = port->bmdma_addr = port->scr_addr = NULL;
212020f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ
212131961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ	/* Clear any currently outstanding port interrupt conditions */
212231961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ	serr_ofs = mv_scr_offset(SCR_ERROR);
212331961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ	writelfl(readl(port_mmio + serr_ofs), port_mmio + serr_ofs);
212431961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ	writelfl(0, port_mmio + EDMA_ERR_IRQ_CAUSE_OFS);
212531961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ
212620f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ	/* unmask all EDMA error interrupts */
212731961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ	writelfl(~0, port_mmio + EDMA_ERR_IRQ_MASK_OFS);
212820f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ
21298b260248d9e0e8b64bb72fd4dee03ad86984c344Jeff Garzik	VPRINTK("EDMA cfg=0x%08x EDMA IRQ err cause/mask=0x%08x/0x%08x\n",
213031961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ		readl(port_mmio + EDMA_CFG_OFS),
213131961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ		readl(port_mmio + EDMA_ERR_IRQ_CAUSE_OFS),
213231961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ		readl(port_mmio + EDMA_ERR_IRQ_MASK_OFS));
213320f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ}
213420f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ
21354447d35156169cf136e829eb6b5cac2d6370f2d9Tejun Heostatic int mv_chip_id(struct ata_host *host, unsigned int board_idx)
2136bca1c4eb9411533d613123618c0d127fae532595Jeff Garzik{
21374447d35156169cf136e829eb6b5cac2d6370f2d9Tejun Heo	struct pci_dev *pdev = to_pci_dev(host->dev);
21384447d35156169cf136e829eb6b5cac2d6370f2d9Tejun Heo	struct mv_host_priv *hpriv = host->private_data;
2139bca1c4eb9411533d613123618c0d127fae532595Jeff Garzik	u32 hp_flags = hpriv->hp_flags;
2140bca1c4eb9411533d613123618c0d127fae532595Jeff Garzik
2141bca1c4eb9411533d613123618c0d127fae532595Jeff Garzik	switch(board_idx) {
214247c2b677daeed9c79ecb7167c211ff36876ea611Jeff Garzik	case chip_5080:
214347c2b677daeed9c79ecb7167c211ff36876ea611Jeff Garzik		hpriv->ops = &mv5xxx_ops;
214447c2b677daeed9c79ecb7167c211ff36876ea611Jeff Garzik		hp_flags |= MV_HP_50XX;
214547c2b677daeed9c79ecb7167c211ff36876ea611Jeff Garzik
214644c10138fd4bbc4b6d6bff0873c24902f2a9da65Auke Kok		switch (pdev->revision) {
214747c2b677daeed9c79ecb7167c211ff36876ea611Jeff Garzik		case 0x1:
214847c2b677daeed9c79ecb7167c211ff36876ea611Jeff Garzik			hp_flags |= MV_HP_ERRATA_50XXB0;
214947c2b677daeed9c79ecb7167c211ff36876ea611Jeff Garzik			break;
215047c2b677daeed9c79ecb7167c211ff36876ea611Jeff Garzik		case 0x3:
215147c2b677daeed9c79ecb7167c211ff36876ea611Jeff Garzik			hp_flags |= MV_HP_ERRATA_50XXB2;
215247c2b677daeed9c79ecb7167c211ff36876ea611Jeff Garzik			break;
215347c2b677daeed9c79ecb7167c211ff36876ea611Jeff Garzik		default:
215447c2b677daeed9c79ecb7167c211ff36876ea611Jeff Garzik			dev_printk(KERN_WARNING, &pdev->dev,
215547c2b677daeed9c79ecb7167c211ff36876ea611Jeff Garzik			   "Applying 50XXB2 workarounds to unknown rev\n");
215647c2b677daeed9c79ecb7167c211ff36876ea611Jeff Garzik			hp_flags |= MV_HP_ERRATA_50XXB2;
215747c2b677daeed9c79ecb7167c211ff36876ea611Jeff Garzik			break;
215847c2b677daeed9c79ecb7167c211ff36876ea611Jeff Garzik		}
215947c2b677daeed9c79ecb7167c211ff36876ea611Jeff Garzik		break;
216047c2b677daeed9c79ecb7167c211ff36876ea611Jeff Garzik
2161bca1c4eb9411533d613123618c0d127fae532595Jeff Garzik	case chip_504x:
2162bca1c4eb9411533d613123618c0d127fae532595Jeff Garzik	case chip_508x:
216347c2b677daeed9c79ecb7167c211ff36876ea611Jeff Garzik		hpriv->ops = &mv5xxx_ops;
2164bca1c4eb9411533d613123618c0d127fae532595Jeff Garzik		hp_flags |= MV_HP_50XX;
2165bca1c4eb9411533d613123618c0d127fae532595Jeff Garzik
216644c10138fd4bbc4b6d6bff0873c24902f2a9da65Auke Kok		switch (pdev->revision) {
216747c2b677daeed9c79ecb7167c211ff36876ea611Jeff Garzik		case 0x0:
216847c2b677daeed9c79ecb7167c211ff36876ea611Jeff Garzik			hp_flags |= MV_HP_ERRATA_50XXB0;
216947c2b677daeed9c79ecb7167c211ff36876ea611Jeff Garzik			break;
217047c2b677daeed9c79ecb7167c211ff36876ea611Jeff Garzik		case 0x3:
217147c2b677daeed9c79ecb7167c211ff36876ea611Jeff Garzik			hp_flags |= MV_HP_ERRATA_50XXB2;
217247c2b677daeed9c79ecb7167c211ff36876ea611Jeff Garzik			break;
217347c2b677daeed9c79ecb7167c211ff36876ea611Jeff Garzik		default:
217447c2b677daeed9c79ecb7167c211ff36876ea611Jeff Garzik			dev_printk(KERN_WARNING, &pdev->dev,
217547c2b677daeed9c79ecb7167c211ff36876ea611Jeff Garzik			   "Applying B2 workarounds to unknown rev\n");
217647c2b677daeed9c79ecb7167c211ff36876ea611Jeff Garzik			hp_flags |= MV_HP_ERRATA_50XXB2;
217747c2b677daeed9c79ecb7167c211ff36876ea611Jeff Garzik			break;
2178bca1c4eb9411533d613123618c0d127fae532595Jeff Garzik		}
2179bca1c4eb9411533d613123618c0d127fae532595Jeff Garzik		break;
2180bca1c4eb9411533d613123618c0d127fae532595Jeff Garzik
2181bca1c4eb9411533d613123618c0d127fae532595Jeff Garzik	case chip_604x:
2182bca1c4eb9411533d613123618c0d127fae532595Jeff Garzik	case chip_608x:
218347c2b677daeed9c79ecb7167c211ff36876ea611Jeff Garzik		hpriv->ops = &mv6xxx_ops;
218447c2b677daeed9c79ecb7167c211ff36876ea611Jeff Garzik
218544c10138fd4bbc4b6d6bff0873c24902f2a9da65Auke Kok		switch (pdev->revision) {
218647c2b677daeed9c79ecb7167c211ff36876ea611Jeff Garzik		case 0x7:
218747c2b677daeed9c79ecb7167c211ff36876ea611Jeff Garzik			hp_flags |= MV_HP_ERRATA_60X1B2;
218847c2b677daeed9c79ecb7167c211ff36876ea611Jeff Garzik			break;
218947c2b677daeed9c79ecb7167c211ff36876ea611Jeff Garzik		case 0x9:
219047c2b677daeed9c79ecb7167c211ff36876ea611Jeff Garzik			hp_flags |= MV_HP_ERRATA_60X1C0;
2191bca1c4eb9411533d613123618c0d127fae532595Jeff Garzik			break;
2192bca1c4eb9411533d613123618c0d127fae532595Jeff Garzik		default:
2193bca1c4eb9411533d613123618c0d127fae532595Jeff Garzik			dev_printk(KERN_WARNING, &pdev->dev,
219447c2b677daeed9c79ecb7167c211ff36876ea611Jeff Garzik				   "Applying B2 workarounds to unknown rev\n");
219547c2b677daeed9c79ecb7167c211ff36876ea611Jeff Garzik			hp_flags |= MV_HP_ERRATA_60X1B2;
2196bca1c4eb9411533d613123618c0d127fae532595Jeff Garzik			break;
2197bca1c4eb9411533d613123618c0d127fae532595Jeff Garzik		}
2198bca1c4eb9411533d613123618c0d127fae532595Jeff Garzik		break;
2199bca1c4eb9411533d613123618c0d127fae532595Jeff Garzik
2200e4e7b89280d1d666e2c09e5ad36cf071796c4c7eJeff Garzik	case chip_7042:
2201e4e7b89280d1d666e2c09e5ad36cf071796c4c7eJeff Garzik	case chip_6042:
2202e4e7b89280d1d666e2c09e5ad36cf071796c4c7eJeff Garzik		hpriv->ops = &mv6xxx_ops;
2203e4e7b89280d1d666e2c09e5ad36cf071796c4c7eJeff Garzik
2204e4e7b89280d1d666e2c09e5ad36cf071796c4c7eJeff Garzik		hp_flags |= MV_HP_GEN_IIE;
2205e4e7b89280d1d666e2c09e5ad36cf071796c4c7eJeff Garzik
220644c10138fd4bbc4b6d6bff0873c24902f2a9da65Auke Kok		switch (pdev->revision) {
2207e4e7b89280d1d666e2c09e5ad36cf071796c4c7eJeff Garzik		case 0x0:
2208e4e7b89280d1d666e2c09e5ad36cf071796c4c7eJeff Garzik			hp_flags |= MV_HP_ERRATA_XX42A0;
2209e4e7b89280d1d666e2c09e5ad36cf071796c4c7eJeff Garzik			break;
2210e4e7b89280d1d666e2c09e5ad36cf071796c4c7eJeff Garzik		case 0x1:
2211e4e7b89280d1d666e2c09e5ad36cf071796c4c7eJeff Garzik			hp_flags |= MV_HP_ERRATA_60X1C0;
2212e4e7b89280d1d666e2c09e5ad36cf071796c4c7eJeff Garzik			break;
2213e4e7b89280d1d666e2c09e5ad36cf071796c4c7eJeff Garzik		default:
2214e4e7b89280d1d666e2c09e5ad36cf071796c4c7eJeff Garzik			dev_printk(KERN_WARNING, &pdev->dev,
2215e4e7b89280d1d666e2c09e5ad36cf071796c4c7eJeff Garzik			   "Applying 60X1C0 workarounds to unknown rev\n");
2216e4e7b89280d1d666e2c09e5ad36cf071796c4c7eJeff Garzik			hp_flags |= MV_HP_ERRATA_60X1C0;
2217e4e7b89280d1d666e2c09e5ad36cf071796c4c7eJeff Garzik			break;
2218e4e7b89280d1d666e2c09e5ad36cf071796c4c7eJeff Garzik		}
2219e4e7b89280d1d666e2c09e5ad36cf071796c4c7eJeff Garzik		break;
2220e4e7b89280d1d666e2c09e5ad36cf071796c4c7eJeff Garzik
2221bca1c4eb9411533d613123618c0d127fae532595Jeff Garzik	default:
2222bca1c4eb9411533d613123618c0d127fae532595Jeff Garzik		printk(KERN_ERR DRV_NAME ": BUG: invalid board index %u\n", board_idx);
2223bca1c4eb9411533d613123618c0d127fae532595Jeff Garzik		return 1;
2224bca1c4eb9411533d613123618c0d127fae532595Jeff Garzik	}
2225bca1c4eb9411533d613123618c0d127fae532595Jeff Garzik
2226bca1c4eb9411533d613123618c0d127fae532595Jeff Garzik	hpriv->hp_flags = hp_flags;
2227bca1c4eb9411533d613123618c0d127fae532595Jeff Garzik
2228bca1c4eb9411533d613123618c0d127fae532595Jeff Garzik	return 0;
2229bca1c4eb9411533d613123618c0d127fae532595Jeff Garzik}
2230bca1c4eb9411533d613123618c0d127fae532595Jeff Garzik
223105b308e1df6d9d673daedb517969241f41278b52Brett Russ/**
223247c2b677daeed9c79ecb7167c211ff36876ea611Jeff Garzik *      mv_init_host - Perform some early initialization of the host.
22334447d35156169cf136e829eb6b5cac2d6370f2d9Tejun Heo *	@host: ATA host to initialize
22344447d35156169cf136e829eb6b5cac2d6370f2d9Tejun Heo *      @board_idx: controller index
223505b308e1df6d9d673daedb517969241f41278b52Brett Russ *
223605b308e1df6d9d673daedb517969241f41278b52Brett Russ *      If possible, do an early global reset of the host.  Then do
223705b308e1df6d9d673daedb517969241f41278b52Brett Russ *      our port init and clear/unmask all/relevant host interrupts.
223805b308e1df6d9d673daedb517969241f41278b52Brett Russ *
223905b308e1df6d9d673daedb517969241f41278b52Brett Russ *      LOCKING:
224005b308e1df6d9d673daedb517969241f41278b52Brett Russ *      Inherited from caller.
224105b308e1df6d9d673daedb517969241f41278b52Brett Russ */
22424447d35156169cf136e829eb6b5cac2d6370f2d9Tejun Heostatic int mv_init_host(struct ata_host *host, unsigned int board_idx)
224320f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ{
224420f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ	int rc = 0, n_hc, port, hc;
22454447d35156169cf136e829eb6b5cac2d6370f2d9Tejun Heo	struct pci_dev *pdev = to_pci_dev(host->dev);
22464447d35156169cf136e829eb6b5cac2d6370f2d9Tejun Heo	void __iomem *mmio = host->iomap[MV_PRIMARY_BAR];
22474447d35156169cf136e829eb6b5cac2d6370f2d9Tejun Heo	struct mv_host_priv *hpriv = host->private_data;
2248bca1c4eb9411533d613123618c0d127fae532595Jeff Garzik
224947c2b677daeed9c79ecb7167c211ff36876ea611Jeff Garzik	/* global interrupt mask */
225047c2b677daeed9c79ecb7167c211ff36876ea611Jeff Garzik	writel(0, mmio + HC_MAIN_IRQ_MASK_OFS);
225147c2b677daeed9c79ecb7167c211ff36876ea611Jeff Garzik
22524447d35156169cf136e829eb6b5cac2d6370f2d9Tejun Heo	rc = mv_chip_id(host, board_idx);
2253bca1c4eb9411533d613123618c0d127fae532595Jeff Garzik	if (rc)
2254bca1c4eb9411533d613123618c0d127fae532595Jeff Garzik		goto done;
2255bca1c4eb9411533d613123618c0d127fae532595Jeff Garzik
22564447d35156169cf136e829eb6b5cac2d6370f2d9Tejun Heo	n_hc = mv_get_hc_count(host->ports[0]->flags);
2257bca1c4eb9411533d613123618c0d127fae532595Jeff Garzik
22584447d35156169cf136e829eb6b5cac2d6370f2d9Tejun Heo	for (port = 0; port < host->n_ports; port++)
225947c2b677daeed9c79ecb7167c211ff36876ea611Jeff Garzik		hpriv->ops->read_preamp(hpriv, port, mmio);
226020f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ
2261c9d39130123238ac18478a42e25cb7996eacfcc0Jeff Garzik	rc = hpriv->ops->reset_hc(hpriv, mmio, n_hc);
226247c2b677daeed9c79ecb7167c211ff36876ea611Jeff Garzik	if (rc)
226320f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ		goto done;
226420f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ
2265522479fb98c6667f081e75f87e298e413c0b1db8Jeff Garzik	hpriv->ops->reset_flash(hpriv, mmio);
2266522479fb98c6667f081e75f87e298e413c0b1db8Jeff Garzik	hpriv->ops->reset_bus(pdev, mmio);
226747c2b677daeed9c79ecb7167c211ff36876ea611Jeff Garzik	hpriv->ops->enable_leds(hpriv, mmio);
226820f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ
22694447d35156169cf136e829eb6b5cac2d6370f2d9Tejun Heo	for (port = 0; port < host->n_ports; port++) {
22702a47ce06d534692f9bd2bf4e90a20fc9b1054c39Jeff Garzik		if (IS_60XX(hpriv)) {
2271c9d39130123238ac18478a42e25cb7996eacfcc0Jeff Garzik			void __iomem *port_mmio = mv_port_base(mmio, port);
2272c9d39130123238ac18478a42e25cb7996eacfcc0Jeff Garzik
22732a47ce06d534692f9bd2bf4e90a20fc9b1054c39Jeff Garzik			u32 ifctl = readl(port_mmio + SATA_INTERFACE_CTL);
2274eb46d684600ac145501805a294c94675e82eab2eMark Lord			ifctl |= (1 << 7);		/* enable gen2i speed */
2275eb46d684600ac145501805a294c94675e82eab2eMark Lord			ifctl = (ifctl & 0xfff) | 0x9b1000; /* from chip spec */
22762a47ce06d534692f9bd2bf4e90a20fc9b1054c39Jeff Garzik			writelfl(ifctl, port_mmio + SATA_INTERFACE_CTL);
22772a47ce06d534692f9bd2bf4e90a20fc9b1054c39Jeff Garzik		}
22782a47ce06d534692f9bd2bf4e90a20fc9b1054c39Jeff Garzik
2279c9d39130123238ac18478a42e25cb7996eacfcc0Jeff Garzik		hpriv->ops->phy_errata(hpriv, mmio, port);
22802a47ce06d534692f9bd2bf4e90a20fc9b1054c39Jeff Garzik	}
22812a47ce06d534692f9bd2bf4e90a20fc9b1054c39Jeff Garzik
22824447d35156169cf136e829eb6b5cac2d6370f2d9Tejun Heo	for (port = 0; port < host->n_ports; port++) {
22832a47ce06d534692f9bd2bf4e90a20fc9b1054c39Jeff Garzik		void __iomem *port_mmio = mv_port_base(mmio, port);
22844447d35156169cf136e829eb6b5cac2d6370f2d9Tejun Heo		mv_port_init(&host->ports[port]->ioaddr, port_mmio);
228520f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ	}
228620f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ
228720f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ	for (hc = 0; hc < n_hc; hc++) {
228831961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ		void __iomem *hc_mmio = mv_hc_base(mmio, hc);
228931961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ
229031961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ		VPRINTK("HC%i: HC config=0x%08x HC IRQ cause "
229131961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ			"(before clear)=0x%08x\n", hc,
229231961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ			readl(hc_mmio + HC_CFG_OFS),
229331961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ			readl(hc_mmio + HC_IRQ_CAUSE_OFS));
229431961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ
229531961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ		/* Clear any currently outstanding hc interrupt conditions */
229631961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ		writelfl(0, hc_mmio + HC_IRQ_CAUSE_OFS);
229720f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ	}
229820f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ
229931961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ	/* Clear any currently outstanding host interrupt conditions */
230031961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ	writelfl(0, mmio + PCI_IRQ_CAUSE_OFS);
230131961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ
230231961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ	/* and unmask interrupt generation for host regs */
230331961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ	writelfl(PCI_UNMASK_ALL_IRQS, mmio + PCI_IRQ_MASK_OFS);
2304fb621e2fde735abab854586d52c96c5624bcb5b8Jeff Garzik
2305fb621e2fde735abab854586d52c96c5624bcb5b8Jeff Garzik	if (IS_50XX(hpriv))
2306fb621e2fde735abab854586d52c96c5624bcb5b8Jeff Garzik		writelfl(~HC_MAIN_MASKED_IRQS_5, mmio + HC_MAIN_IRQ_MASK_OFS);
2307fb621e2fde735abab854586d52c96c5624bcb5b8Jeff Garzik	else
2308fb621e2fde735abab854586d52c96c5624bcb5b8Jeff Garzik		writelfl(~HC_MAIN_MASKED_IRQS, mmio + HC_MAIN_IRQ_MASK_OFS);
230920f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ
231020f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ	VPRINTK("HC MAIN IRQ cause/mask=0x%08x/0x%08x "
23118b260248d9e0e8b64bb72fd4dee03ad86984c344Jeff Garzik		"PCI int cause/mask=0x%08x/0x%08x\n",
231220f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ		readl(mmio + HC_MAIN_IRQ_CAUSE_OFS),
231320f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ		readl(mmio + HC_MAIN_IRQ_MASK_OFS),
231420f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ		readl(mmio + PCI_IRQ_CAUSE_OFS),
231520f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ		readl(mmio + PCI_IRQ_MASK_OFS));
2316bca1c4eb9411533d613123618c0d127fae532595Jeff Garzik
231731961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russdone:
231820f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ	return rc;
231920f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ}
232020f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ
232105b308e1df6d9d673daedb517969241f41278b52Brett Russ/**
232205b308e1df6d9d673daedb517969241f41278b52Brett Russ *      mv_print_info - Dump key info to kernel log for perusal.
23234447d35156169cf136e829eb6b5cac2d6370f2d9Tejun Heo *      @host: ATA host to print info about
232405b308e1df6d9d673daedb517969241f41278b52Brett Russ *
232505b308e1df6d9d673daedb517969241f41278b52Brett Russ *      FIXME: complete this.
232605b308e1df6d9d673daedb517969241f41278b52Brett Russ *
232705b308e1df6d9d673daedb517969241f41278b52Brett Russ *      LOCKING:
232805b308e1df6d9d673daedb517969241f41278b52Brett Russ *      Inherited from caller.
232905b308e1df6d9d673daedb517969241f41278b52Brett Russ */
23304447d35156169cf136e829eb6b5cac2d6370f2d9Tejun Heostatic void mv_print_info(struct ata_host *host)
233131961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ{
23324447d35156169cf136e829eb6b5cac2d6370f2d9Tejun Heo	struct pci_dev *pdev = to_pci_dev(host->dev);
23334447d35156169cf136e829eb6b5cac2d6370f2d9Tejun Heo	struct mv_host_priv *hpriv = host->private_data;
233444c10138fd4bbc4b6d6bff0873c24902f2a9da65Auke Kok	u8 scc;
2335c1e4fe711a410a139095e6b3e3ce3f07f466063cJeff Garzik	const char *scc_s, *gen;
233631961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ
233731961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ	/* Use this to determine the HW stepping of the chip so we know
233831961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ	 * what errata to workaround
233931961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ	 */
234031961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ	pci_read_config_byte(pdev, PCI_CLASS_DEVICE, &scc);
234131961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ	if (scc == 0)
234231961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ		scc_s = "SCSI";
234331961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ	else if (scc == 0x01)
234431961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ		scc_s = "RAID";
234531961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ	else
2346c1e4fe711a410a139095e6b3e3ce3f07f466063cJeff Garzik		scc_s = "?";
2347c1e4fe711a410a139095e6b3e3ce3f07f466063cJeff Garzik
2348c1e4fe711a410a139095e6b3e3ce3f07f466063cJeff Garzik	if (IS_GEN_I(hpriv))
2349c1e4fe711a410a139095e6b3e3ce3f07f466063cJeff Garzik		gen = "I";
2350c1e4fe711a410a139095e6b3e3ce3f07f466063cJeff Garzik	else if (IS_GEN_II(hpriv))
2351c1e4fe711a410a139095e6b3e3ce3f07f466063cJeff Garzik		gen = "II";
2352c1e4fe711a410a139095e6b3e3ce3f07f466063cJeff Garzik	else if (IS_GEN_IIE(hpriv))
2353c1e4fe711a410a139095e6b3e3ce3f07f466063cJeff Garzik		gen = "IIE";
2354c1e4fe711a410a139095e6b3e3ce3f07f466063cJeff Garzik	else
2355c1e4fe711a410a139095e6b3e3ce3f07f466063cJeff Garzik		gen = "?";
235631961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ
2357a9524a76f70f3343e4be27f95a7e92a8ba5f9009Jeff Garzik	dev_printk(KERN_INFO, &pdev->dev,
2358c1e4fe711a410a139095e6b3e3ce3f07f466063cJeff Garzik	       "Gen-%s %u slots %u ports %s mode IRQ via %s\n",
2359c1e4fe711a410a139095e6b3e3ce3f07f466063cJeff Garzik	       gen, (unsigned)MV_MAX_Q_DEPTH, host->n_ports,
236031961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ	       scc_s, (MV_HP_FLAG_MSI & hpriv->hp_flags) ? "MSI" : "INTx");
236131961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ}
236231961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ
236305b308e1df6d9d673daedb517969241f41278b52Brett Russ/**
236405b308e1df6d9d673daedb517969241f41278b52Brett Russ *      mv_init_one - handle a positive probe of a Marvell host
236505b308e1df6d9d673daedb517969241f41278b52Brett Russ *      @pdev: PCI device found
236605b308e1df6d9d673daedb517969241f41278b52Brett Russ *      @ent: PCI device ID entry for the matched host
236705b308e1df6d9d673daedb517969241f41278b52Brett Russ *
236805b308e1df6d9d673daedb517969241f41278b52Brett Russ *      LOCKING:
236905b308e1df6d9d673daedb517969241f41278b52Brett Russ *      Inherited from caller.
237005b308e1df6d9d673daedb517969241f41278b52Brett Russ */
237120f733e7d75a16bffc34842b7682c9247dd5f954Brett Russstatic int mv_init_one(struct pci_dev *pdev, const struct pci_device_id *ent)
237220f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ{
237320f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ	static int printed_version = 0;
237420f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ	unsigned int board_idx = (unsigned int)ent->driver_data;
23754447d35156169cf136e829eb6b5cac2d6370f2d9Tejun Heo	const struct ata_port_info *ppi[] = { &mv_port_info[board_idx], NULL };
23764447d35156169cf136e829eb6b5cac2d6370f2d9Tejun Heo	struct ata_host *host;
23774447d35156169cf136e829eb6b5cac2d6370f2d9Tejun Heo	struct mv_host_priv *hpriv;
23784447d35156169cf136e829eb6b5cac2d6370f2d9Tejun Heo	int n_ports, rc;
237920f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ
2380a9524a76f70f3343e4be27f95a7e92a8ba5f9009Jeff Garzik	if (!printed_version++)
2381a9524a76f70f3343e4be27f95a7e92a8ba5f9009Jeff Garzik		dev_printk(KERN_INFO, &pdev->dev, "version " DRV_VERSION "\n");
238220f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ
23834447d35156169cf136e829eb6b5cac2d6370f2d9Tejun Heo	/* allocate host */
23844447d35156169cf136e829eb6b5cac2d6370f2d9Tejun Heo	n_ports = mv_get_hc_count(ppi[0]->flags) * MV_PORTS_PER_HC;
23854447d35156169cf136e829eb6b5cac2d6370f2d9Tejun Heo
23864447d35156169cf136e829eb6b5cac2d6370f2d9Tejun Heo	host = ata_host_alloc_pinfo(&pdev->dev, ppi, n_ports);
23874447d35156169cf136e829eb6b5cac2d6370f2d9Tejun Heo	hpriv = devm_kzalloc(&pdev->dev, sizeof(*hpriv), GFP_KERNEL);
23884447d35156169cf136e829eb6b5cac2d6370f2d9Tejun Heo	if (!host || !hpriv)
23894447d35156169cf136e829eb6b5cac2d6370f2d9Tejun Heo		return -ENOMEM;
23904447d35156169cf136e829eb6b5cac2d6370f2d9Tejun Heo	host->private_data = hpriv;
23914447d35156169cf136e829eb6b5cac2d6370f2d9Tejun Heo
23924447d35156169cf136e829eb6b5cac2d6370f2d9Tejun Heo	/* acquire resources */
239324dc5f33ea4b504cfbd23fa159a4cacba8e4d800Tejun Heo	rc = pcim_enable_device(pdev);
239424dc5f33ea4b504cfbd23fa159a4cacba8e4d800Tejun Heo	if (rc)
239520f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ		return rc;
239620f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ
23970d5ff566779f894ca9937231a181eb31e4adff0eTejun Heo	rc = pcim_iomap_regions(pdev, 1 << MV_PRIMARY_BAR, DRV_NAME);
23980d5ff566779f894ca9937231a181eb31e4adff0eTejun Heo	if (rc == -EBUSY)
239924dc5f33ea4b504cfbd23fa159a4cacba8e4d800Tejun Heo		pcim_pin_device(pdev);
24000d5ff566779f894ca9937231a181eb31e4adff0eTejun Heo	if (rc)
240124dc5f33ea4b504cfbd23fa159a4cacba8e4d800Tejun Heo		return rc;
24024447d35156169cf136e829eb6b5cac2d6370f2d9Tejun Heo	host->iomap = pcim_iomap_table(pdev);
240320f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ
2404d88184fb2348a50f7c34f5d49a901c875b2e0114Jeff Garzik	rc = pci_go_64(pdev);
2405d88184fb2348a50f7c34f5d49a901c875b2e0114Jeff Garzik	if (rc)
2406d88184fb2348a50f7c34f5d49a901c875b2e0114Jeff Garzik		return rc;
2407d88184fb2348a50f7c34f5d49a901c875b2e0114Jeff Garzik
240820f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ	/* initialize adapter */
24094447d35156169cf136e829eb6b5cac2d6370f2d9Tejun Heo	rc = mv_init_host(host, board_idx);
241024dc5f33ea4b504cfbd23fa159a4cacba8e4d800Tejun Heo	if (rc)
241124dc5f33ea4b504cfbd23fa159a4cacba8e4d800Tejun Heo		return rc;
241220f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ
241331961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ	/* Enable interrupts */
24146a59dcf8678cbc4106a8a6e158d7408a87691358Tejun Heo	if (msi && pci_enable_msi(pdev))
241531961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ		pci_intx(pdev, 1);
241620f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ
241731961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ	mv_dump_pci_cfg(pdev, 0x68);
24184447d35156169cf136e829eb6b5cac2d6370f2d9Tejun Heo	mv_print_info(host);
241920f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ
24204447d35156169cf136e829eb6b5cac2d6370f2d9Tejun Heo	pci_set_master(pdev);
24214447d35156169cf136e829eb6b5cac2d6370f2d9Tejun Heo	return ata_host_activate(host, pdev->irq, mv_interrupt, IRQF_SHARED,
24224447d35156169cf136e829eb6b5cac2d6370f2d9Tejun Heo				 &mv_sht);
242320f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ}
242420f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ
242520f733e7d75a16bffc34842b7682c9247dd5f954Brett Russstatic int __init mv_init(void)
242620f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ{
2427b7887196e38da54ff893897b80875d632d1a1114Pavel Roskin	return pci_register_driver(&mv_pci_driver);
242820f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ}
242920f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ
243020f733e7d75a16bffc34842b7682c9247dd5f954Brett Russstatic void __exit mv_exit(void)
243120f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ{
243220f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ	pci_unregister_driver(&mv_pci_driver);
243320f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ}
243420f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ
243520f733e7d75a16bffc34842b7682c9247dd5f954Brett RussMODULE_AUTHOR("Brett Russ");
243620f733e7d75a16bffc34842b7682c9247dd5f954Brett RussMODULE_DESCRIPTION("SCSI low-level driver for Marvell SATA controllers");
243720f733e7d75a16bffc34842b7682c9247dd5f954Brett RussMODULE_LICENSE("GPL");
243820f733e7d75a16bffc34842b7682c9247dd5f954Brett RussMODULE_DEVICE_TABLE(pci, mv_pci_tbl);
243920f733e7d75a16bffc34842b7682c9247dd5f954Brett RussMODULE_VERSION(DRV_VERSION);
244020f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ
2441ddef9bb367b19383df627e388cb4c01c86ddba6cJeff Garzikmodule_param(msi, int, 0444);
2442ddef9bb367b19383df627e388cb4c01c86ddba6cJeff GarzikMODULE_PARM_DESC(msi, "Enable use of PCI MSI (0=off, 1=on)");
2443ddef9bb367b19383df627e388cb4c01c86ddba6cJeff Garzik
244420f733e7d75a16bffc34842b7682c9247dd5f954Brett Russmodule_init(mv_init);
244520f733e7d75a16bffc34842b7682c9247dd5f954Brett Russmodule_exit(mv_exit);
2446