sata_mv.c revision cca3974e48607c3775dc73b544a5700b2e37c21a
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
2420f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ#include <linux/kernel.h>
2520f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ#include <linux/module.h>
2620f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ#include <linux/pci.h>
2720f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ#include <linux/init.h>
2820f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ#include <linux/blkdev.h>
2920f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ#include <linux/delay.h>
3020f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ#include <linux/interrupt.h>
3120f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ#include <linux/sched.h>
3220f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ#include <linux/dma-mapping.h>
33a9524a76f70f3343e4be27f95a7e92a8ba5f9009Jeff Garzik#include <linux/device.h>
3420f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ#include <scsi/scsi_host.h>
35193515d51ccb363165d6b09e9ba5c21089e34badJeff Garzik#include <scsi/scsi_cmnd.h>
3620f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ#include <linux/libata.h>
3720f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ#include <asm/io.h>
3820f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ
3920f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ#define DRV_NAME	"sata_mv"
4063a25355cd5cd9a2d19a7c50eed4f0a8aa622f72Mark Lord#define DRV_VERSION	"0.7"
4120f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ
4220f733e7d75a16bffc34842b7682c9247dd5f954Brett Russenum {
4320f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ	/* BAR's are enumerated in terms of pci_resource_start() terms */
4420f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ	MV_PRIMARY_BAR		= 0,	/* offset 0x10: memory space */
4520f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ	MV_IO_BAR		= 2,	/* offset 0x18: IO space */
4620f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ	MV_MISC_BAR		= 3,	/* offset 0x1c: FLASH, NVRAM, SRAM */
4720f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ
4820f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ	MV_MAJOR_REG_AREA_SZ	= 0x10000,	/* 64KB */
4920f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ	MV_MINOR_REG_AREA_SZ	= 0x2000,	/* 8KB */
5020f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ
5120f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ	MV_PCI_REG_BASE		= 0,
5220f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ	MV_IRQ_COAL_REG_BASE	= 0x18000,	/* 6xxx part only */
53615ab95342f6245026d8974b9724f7ea57d9a184Mark Lord	MV_IRQ_COAL_CAUSE		= (MV_IRQ_COAL_REG_BASE + 0x08),
54615ab95342f6245026d8974b9724f7ea57d9a184Mark Lord	MV_IRQ_COAL_CAUSE_LO		= (MV_IRQ_COAL_REG_BASE + 0x88),
55615ab95342f6245026d8974b9724f7ea57d9a184Mark Lord	MV_IRQ_COAL_CAUSE_HI		= (MV_IRQ_COAL_REG_BASE + 0x8c),
56615ab95342f6245026d8974b9724f7ea57d9a184Mark Lord	MV_IRQ_COAL_THRESHOLD		= (MV_IRQ_COAL_REG_BASE + 0xcc),
57615ab95342f6245026d8974b9724f7ea57d9a184Mark Lord	MV_IRQ_COAL_TIME_THRESHOLD	= (MV_IRQ_COAL_REG_BASE + 0xd0),
58615ab95342f6245026d8974b9724f7ea57d9a184Mark Lord
5920f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ	MV_SATAHC0_REG_BASE	= 0x20000,
60522479fb98c6667f081e75f87e298e413c0b1db8Jeff Garzik	MV_FLASH_CTL		= 0x1046c,
61bca1c4eb9411533d613123618c0d127fae532595Jeff Garzik	MV_GPIO_PORT_CTL	= 0x104f0,
62bca1c4eb9411533d613123618c0d127fae532595Jeff Garzik	MV_RESET_CFG		= 0x180d8,
6320f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ
6420f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ	MV_PCI_REG_SZ		= MV_MAJOR_REG_AREA_SZ,
6520f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ	MV_SATAHC_REG_SZ	= MV_MAJOR_REG_AREA_SZ,
6620f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ	MV_SATAHC_ARBTR_REG_SZ	= MV_MINOR_REG_AREA_SZ,		/* arbiter */
6720f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ	MV_PORT_REG_SZ		= MV_MINOR_REG_AREA_SZ,
6820f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ
6931961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ	MV_USE_Q_DEPTH		= ATA_DEF_QUEUE,
7020f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ
7131961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ	MV_MAX_Q_DEPTH		= 32,
7231961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ	MV_MAX_Q_DEPTH_MASK	= MV_MAX_Q_DEPTH - 1,
7331961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ
7431961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ	/* CRQB needs alignment on a 1KB boundary. Size == 1KB
7531961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ	 * CRPB needs alignment on a 256B boundary. Size == 256B
7631961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ	 * SG count of 176 leads to MV_PORT_PRIV_DMA_SZ == 4KB
7731961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ	 * ePRD (SG) entries need alignment on a 16B boundary. Size == 16B
7831961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ	 */
7931961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ	MV_CRQB_Q_SZ		= (32 * MV_MAX_Q_DEPTH),
8031961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ	MV_CRPB_Q_SZ		= (8 * MV_MAX_Q_DEPTH),
8131961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ	MV_MAX_SG_CT		= 176,
8231961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ	MV_SG_TBL_SZ		= (16 * MV_MAX_SG_CT),
8331961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ	MV_PORT_PRIV_DMA_SZ	= (MV_CRQB_Q_SZ + MV_CRPB_Q_SZ + MV_SG_TBL_SZ),
8431961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ
8520f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ	MV_PORTS_PER_HC		= 4,
8620f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ	/* == (port / MV_PORTS_PER_HC) to determine HC from 0-7 port */
8720f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ	MV_PORT_HC_SHIFT	= 2,
8831961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ	/* == (port % MV_PORTS_PER_HC) to determine hard port from 0-7 port */
8920f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ	MV_PORT_MASK		= 3,
9020f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ
9120f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ	/* Host Flags */
9220f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ	MV_FLAG_DUAL_HC		= (1 << 30),  /* two SATA Host Controllers */
9320f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ	MV_FLAG_IRQ_COALESCE	= (1 << 29),  /* IRQ coalescing capability */
9431961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ	MV_COMMON_FLAGS		= (ATA_FLAG_SATA | ATA_FLAG_NO_LEGACY |
9550630195bbdfe1ca775d94cd68a5f18bc1b717e4Jeff Garzik				   ATA_FLAG_SATA_RESET | ATA_FLAG_MMIO |
961f3461a72619fcd70a0fcb563306c91f753b4620Albert Lee				   ATA_FLAG_NO_ATAPI | ATA_FLAG_PIO_POLLING),
9747c2b677daeed9c79ecb7167c211ff36876ea611Jeff Garzik	MV_6XXX_FLAGS		= MV_FLAG_IRQ_COALESCE,
9820f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ
9931961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ	CRQB_FLAG_READ		= (1 << 0),
10031961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ	CRQB_TAG_SHIFT		= 1,
10131961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ	CRQB_CMD_ADDR_SHIFT	= 8,
10231961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ	CRQB_CMD_CS		= (0x2 << 11),
10331961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ	CRQB_CMD_LAST		= (1 << 15),
10431961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ
10531961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ	CRPB_FLAG_STATUS_SHIFT	= 8,
10631961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ
10731961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ	EPRD_FLAG_END_OF_TBL	= (1 << 31),
10831961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ
10920f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ	/* PCI interface registers */
11020f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ
11131961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ	PCI_COMMAND_OFS		= 0xc00,
11231961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ
11320f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ	PCI_MAIN_CMD_STS_OFS	= 0xd30,
11420f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ	STOP_PCI_MASTER		= (1 << 2),
11520f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ	PCI_MASTER_EMPTY	= (1 << 3),
11620f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ	GLOB_SFT_RST		= (1 << 4),
11720f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ
118522479fb98c6667f081e75f87e298e413c0b1db8Jeff Garzik	MV_PCI_MODE		= 0xd00,
119522479fb98c6667f081e75f87e298e413c0b1db8Jeff Garzik	MV_PCI_EXP_ROM_BAR_CTL	= 0xd2c,
120522479fb98c6667f081e75f87e298e413c0b1db8Jeff Garzik	MV_PCI_DISC_TIMER	= 0xd04,
121522479fb98c6667f081e75f87e298e413c0b1db8Jeff Garzik	MV_PCI_MSI_TRIGGER	= 0xc38,
122522479fb98c6667f081e75f87e298e413c0b1db8Jeff Garzik	MV_PCI_SERR_MASK	= 0xc28,
123522479fb98c6667f081e75f87e298e413c0b1db8Jeff Garzik	MV_PCI_XBAR_TMOUT	= 0x1d04,
124522479fb98c6667f081e75f87e298e413c0b1db8Jeff Garzik	MV_PCI_ERR_LOW_ADDRESS	= 0x1d40,
125522479fb98c6667f081e75f87e298e413c0b1db8Jeff Garzik	MV_PCI_ERR_HIGH_ADDRESS	= 0x1d44,
126522479fb98c6667f081e75f87e298e413c0b1db8Jeff Garzik	MV_PCI_ERR_ATTRIBUTE	= 0x1d48,
127522479fb98c6667f081e75f87e298e413c0b1db8Jeff Garzik	MV_PCI_ERR_COMMAND	= 0x1d50,
128522479fb98c6667f081e75f87e298e413c0b1db8Jeff Garzik
129522479fb98c6667f081e75f87e298e413c0b1db8Jeff Garzik	PCI_IRQ_CAUSE_OFS		= 0x1d58,
130522479fb98c6667f081e75f87e298e413c0b1db8Jeff Garzik	PCI_IRQ_MASK_OFS		= 0x1d5c,
13120f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ	PCI_UNMASK_ALL_IRQS	= 0x7fffff,	/* bits 22-0 */
13220f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ
13320f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ	HC_MAIN_IRQ_CAUSE_OFS	= 0x1d60,
13420f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ	HC_MAIN_IRQ_MASK_OFS	= 0x1d64,
13520f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ	PORT0_ERR		= (1 << 0),	/* shift by port # */
13620f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ	PORT0_DONE		= (1 << 1),	/* shift by port # */
13720f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ	HC0_IRQ_PEND		= 0x1ff,	/* bits 0-8 = HC0's ports */
13820f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ	HC_SHIFT		= 9,		/* bits 9-17 = HC1's ports */
13920f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ	PCI_ERR			= (1 << 18),
14020f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ	TRAN_LO_DONE		= (1 << 19),	/* 6xxx: IRQ coalescing */
14120f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ	TRAN_HI_DONE		= (1 << 20),	/* 6xxx: IRQ coalescing */
14220f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ	PORTS_0_7_COAL_DONE	= (1 << 21),	/* 6xxx: IRQ coalescing */
14320f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ	GPIO_INT		= (1 << 22),
14420f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ	SELF_INT		= (1 << 23),
14520f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ	TWSI_INT		= (1 << 24),
14620f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ	HC_MAIN_RSVD		= (0x7f << 25),	/* bits 31-25 */
1478b260248d9e0e8b64bb72fd4dee03ad86984c344Jeff Garzik	HC_MAIN_MASKED_IRQS	= (TRAN_LO_DONE | TRAN_HI_DONE |
14820f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ				   PORTS_0_7_COAL_DONE | GPIO_INT | TWSI_INT |
14920f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ				   HC_MAIN_RSVD),
15020f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ
15120f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ	/* SATAHC registers */
15220f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ	HC_CFG_OFS		= 0,
15320f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ
15420f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ	HC_IRQ_CAUSE_OFS	= 0x14,
15531961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ	CRPB_DMA_DONE		= (1 << 0),	/* shift by port # */
15620f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ	HC_IRQ_COAL		= (1 << 4),	/* IRQ coalescing */
15720f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ	DEV_IRQ			= (1 << 8),	/* shift by port # */
15820f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ
15920f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ	/* Shadow block registers */
16031961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ	SHD_BLK_OFS		= 0x100,
16131961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ	SHD_CTL_AST_OFS		= 0x20,		/* ofs from SHD_BLK_OFS */
16220f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ
16320f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ	/* SATA registers */
16420f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ	SATA_STATUS_OFS		= 0x300,  /* ctrl, err regs follow status */
16520f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ	SATA_ACTIVE_OFS		= 0x350,
16647c2b677daeed9c79ecb7167c211ff36876ea611Jeff Garzik	PHY_MODE3		= 0x310,
167bca1c4eb9411533d613123618c0d127fae532595Jeff Garzik	PHY_MODE4		= 0x314,
168bca1c4eb9411533d613123618c0d127fae532595Jeff Garzik	PHY_MODE2		= 0x330,
169c9d39130123238ac18478a42e25cb7996eacfcc0Jeff Garzik	MV5_PHY_MODE		= 0x74,
170c9d39130123238ac18478a42e25cb7996eacfcc0Jeff Garzik	MV5_LT_MODE		= 0x30,
171c9d39130123238ac18478a42e25cb7996eacfcc0Jeff Garzik	MV5_PHY_CTL		= 0x0C,
172bca1c4eb9411533d613123618c0d127fae532595Jeff Garzik	SATA_INTERFACE_CTL	= 0x050,
173bca1c4eb9411533d613123618c0d127fae532595Jeff Garzik
174bca1c4eb9411533d613123618c0d127fae532595Jeff Garzik	MV_M2_PREAMP_MASK	= 0x7e0,
17520f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ
17620f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ	/* Port registers */
17720f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ	EDMA_CFG_OFS		= 0,
17831961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ	EDMA_CFG_Q_DEPTH	= 0,			/* queueing disabled */
17931961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ	EDMA_CFG_NCQ		= (1 << 5),
18031961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ	EDMA_CFG_NCQ_GO_ON_ERR	= (1 << 14),		/* continue on error */
18131961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ	EDMA_CFG_RD_BRST_EXT	= (1 << 11),		/* read burst 512B */
18231961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ	EDMA_CFG_WR_BUFF_LEN	= (1 << 13),		/* write buffer 512B */
18320f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ
18420f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ	EDMA_ERR_IRQ_CAUSE_OFS	= 0x8,
18520f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ	EDMA_ERR_IRQ_MASK_OFS	= 0xc,
18620f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ	EDMA_ERR_D_PAR		= (1 << 0),
18720f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ	EDMA_ERR_PRD_PAR	= (1 << 1),
18820f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ	EDMA_ERR_DEV		= (1 << 2),
18920f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ	EDMA_ERR_DEV_DCON	= (1 << 3),
19020f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ	EDMA_ERR_DEV_CON	= (1 << 4),
19120f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ	EDMA_ERR_SERR		= (1 << 5),
19220f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ	EDMA_ERR_SELF_DIS	= (1 << 7),
19320f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ	EDMA_ERR_BIST_ASYNC	= (1 << 8),
19420f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ	EDMA_ERR_CRBQ_PAR	= (1 << 9),
19520f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ	EDMA_ERR_CRPB_PAR	= (1 << 10),
19620f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ	EDMA_ERR_INTRL_PAR	= (1 << 11),
19720f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ	EDMA_ERR_IORDY		= (1 << 12),
19820f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ	EDMA_ERR_LNK_CTRL_RX	= (0xf << 13),
19920f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ	EDMA_ERR_LNK_CTRL_RX_2	= (1 << 15),
20020f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ	EDMA_ERR_LNK_DATA_RX	= (0xf << 17),
20120f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ	EDMA_ERR_LNK_CTRL_TX	= (0x1f << 21),
20220f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ	EDMA_ERR_LNK_DATA_TX	= (0x1f << 26),
20320f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ	EDMA_ERR_TRANS_PROTO	= (1 << 31),
2048b260248d9e0e8b64bb72fd4dee03ad86984c344Jeff Garzik	EDMA_ERR_FATAL		= (EDMA_ERR_D_PAR | EDMA_ERR_PRD_PAR |
20520f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ				   EDMA_ERR_DEV_DCON | EDMA_ERR_CRBQ_PAR |
20620f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ				   EDMA_ERR_CRPB_PAR | EDMA_ERR_INTRL_PAR |
2078b260248d9e0e8b64bb72fd4dee03ad86984c344Jeff Garzik				   EDMA_ERR_IORDY | EDMA_ERR_LNK_CTRL_RX_2 |
20820f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ				   EDMA_ERR_LNK_DATA_RX |
2098b260248d9e0e8b64bb72fd4dee03ad86984c344Jeff Garzik				   EDMA_ERR_LNK_DATA_TX |
21020f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ				   EDMA_ERR_TRANS_PROTO),
21120f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ
21231961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ	EDMA_REQ_Q_BASE_HI_OFS	= 0x10,
21331961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ	EDMA_REQ_Q_IN_PTR_OFS	= 0x14,		/* also contains BASE_LO */
21431961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ
21531961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ	EDMA_REQ_Q_OUT_PTR_OFS	= 0x18,
21631961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ	EDMA_REQ_Q_PTR_SHIFT	= 5,
21731961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ
21831961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ	EDMA_RSP_Q_BASE_HI_OFS	= 0x1c,
21931961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ	EDMA_RSP_Q_IN_PTR_OFS	= 0x20,
22031961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ	EDMA_RSP_Q_OUT_PTR_OFS	= 0x24,		/* also contains BASE_LO */
22131961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ	EDMA_RSP_Q_PTR_SHIFT	= 3,
22231961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ
22320f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ	EDMA_CMD_OFS		= 0x28,
22420f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ	EDMA_EN			= (1 << 0),
22520f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ	EDMA_DS			= (1 << 1),
22620f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ	ATA_RST			= (1 << 2),
22720f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ
228c9d39130123238ac18478a42e25cb7996eacfcc0Jeff Garzik	EDMA_IORDY_TMOUT	= 0x34,
229bca1c4eb9411533d613123618c0d127fae532595Jeff Garzik	EDMA_ARB_CFG		= 0x38,
230bca1c4eb9411533d613123618c0d127fae532595Jeff Garzik
23131961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ	/* Host private flags (hp_flags) */
23231961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ	MV_HP_FLAG_MSI		= (1 << 0),
23347c2b677daeed9c79ecb7167c211ff36876ea611Jeff Garzik	MV_HP_ERRATA_50XXB0	= (1 << 1),
23447c2b677daeed9c79ecb7167c211ff36876ea611Jeff Garzik	MV_HP_ERRATA_50XXB2	= (1 << 2),
23547c2b677daeed9c79ecb7167c211ff36876ea611Jeff Garzik	MV_HP_ERRATA_60X1B2	= (1 << 3),
23647c2b677daeed9c79ecb7167c211ff36876ea611Jeff Garzik	MV_HP_ERRATA_60X1C0	= (1 << 4),
237e4e7b89280d1d666e2c09e5ad36cf071796c4c7eJeff Garzik	MV_HP_ERRATA_XX42A0	= (1 << 5),
238e4e7b89280d1d666e2c09e5ad36cf071796c4c7eJeff Garzik	MV_HP_50XX		= (1 << 6),
239e4e7b89280d1d666e2c09e5ad36cf071796c4c7eJeff Garzik	MV_HP_GEN_IIE		= (1 << 7),
24020f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ
24131961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ	/* Port private flags (pp_flags) */
24231961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ	MV_PP_FLAG_EDMA_EN	= (1 << 0),
24331961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ	MV_PP_FLAG_EDMA_DS_ACT	= (1 << 1),
24420f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ};
24520f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ
246c9d39130123238ac18478a42e25cb7996eacfcc0Jeff Garzik#define IS_50XX(hpriv) ((hpriv)->hp_flags & MV_HP_50XX)
247bca1c4eb9411533d613123618c0d127fae532595Jeff Garzik#define IS_60XX(hpriv) (((hpriv)->hp_flags & MV_HP_50XX) == 0)
248e4e7b89280d1d666e2c09e5ad36cf071796c4c7eJeff Garzik#define IS_GEN_I(hpriv) IS_50XX(hpriv)
249e4e7b89280d1d666e2c09e5ad36cf071796c4c7eJeff Garzik#define IS_GEN_II(hpriv) IS_60XX(hpriv)
250e4e7b89280d1d666e2c09e5ad36cf071796c4c7eJeff Garzik#define IS_GEN_IIE(hpriv) ((hpriv)->hp_flags & MV_HP_GEN_IIE)
251bca1c4eb9411533d613123618c0d127fae532595Jeff Garzik
252095fec887eaa1c38d17c0c929a6733c744a9fa1fJeff Garzikenum {
253095fec887eaa1c38d17c0c929a6733c744a9fa1fJeff Garzik	/* Our DMA boundary is determined by an ePRD being unable to handle
254095fec887eaa1c38d17c0c929a6733c744a9fa1fJeff Garzik	 * anything larger than 64KB
255095fec887eaa1c38d17c0c929a6733c744a9fa1fJeff Garzik	 */
256095fec887eaa1c38d17c0c929a6733c744a9fa1fJeff Garzik	MV_DMA_BOUNDARY		= 0xffffU,
257095fec887eaa1c38d17c0c929a6733c744a9fa1fJeff Garzik
258095fec887eaa1c38d17c0c929a6733c744a9fa1fJeff Garzik	EDMA_REQ_Q_BASE_LO_MASK	= 0xfffffc00U,
259095fec887eaa1c38d17c0c929a6733c744a9fa1fJeff Garzik
260095fec887eaa1c38d17c0c929a6733c744a9fa1fJeff Garzik	EDMA_RSP_Q_BASE_LO_MASK	= 0xffffff00U,
261095fec887eaa1c38d17c0c929a6733c744a9fa1fJeff Garzik};
262095fec887eaa1c38d17c0c929a6733c744a9fa1fJeff Garzik
263522479fb98c6667f081e75f87e298e413c0b1db8Jeff Garzikenum chip_type {
264522479fb98c6667f081e75f87e298e413c0b1db8Jeff Garzik	chip_504x,
265522479fb98c6667f081e75f87e298e413c0b1db8Jeff Garzik	chip_508x,
266522479fb98c6667f081e75f87e298e413c0b1db8Jeff Garzik	chip_5080,
267522479fb98c6667f081e75f87e298e413c0b1db8Jeff Garzik	chip_604x,
268522479fb98c6667f081e75f87e298e413c0b1db8Jeff Garzik	chip_608x,
269e4e7b89280d1d666e2c09e5ad36cf071796c4c7eJeff Garzik	chip_6042,
270e4e7b89280d1d666e2c09e5ad36cf071796c4c7eJeff Garzik	chip_7042,
271522479fb98c6667f081e75f87e298e413c0b1db8Jeff Garzik};
272522479fb98c6667f081e75f87e298e413c0b1db8Jeff Garzik
27331961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ/* Command ReQuest Block: 32B */
27431961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russstruct mv_crqb {
275e14698745dd0de1ddbf5cd0cca4313a90f8c1cc1Mark Lord	__le32			sg_addr;
276e14698745dd0de1ddbf5cd0cca4313a90f8c1cc1Mark Lord	__le32			sg_addr_hi;
277e14698745dd0de1ddbf5cd0cca4313a90f8c1cc1Mark Lord	__le16			ctrl_flags;
278e14698745dd0de1ddbf5cd0cca4313a90f8c1cc1Mark Lord	__le16			ata_cmd[11];
27931961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ};
28020f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ
281e4e7b89280d1d666e2c09e5ad36cf071796c4c7eJeff Garzikstruct mv_crqb_iie {
282e14698745dd0de1ddbf5cd0cca4313a90f8c1cc1Mark Lord	__le32			addr;
283e14698745dd0de1ddbf5cd0cca4313a90f8c1cc1Mark Lord	__le32			addr_hi;
284e14698745dd0de1ddbf5cd0cca4313a90f8c1cc1Mark Lord	__le32			flags;
285e14698745dd0de1ddbf5cd0cca4313a90f8c1cc1Mark Lord	__le32			len;
286e14698745dd0de1ddbf5cd0cca4313a90f8c1cc1Mark Lord	__le32			ata_cmd[4];
287e4e7b89280d1d666e2c09e5ad36cf071796c4c7eJeff Garzik};
288e4e7b89280d1d666e2c09e5ad36cf071796c4c7eJeff Garzik
28931961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ/* Command ResPonse Block: 8B */
29031961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russstruct mv_crpb {
291e14698745dd0de1ddbf5cd0cca4313a90f8c1cc1Mark Lord	__le16			id;
292e14698745dd0de1ddbf5cd0cca4313a90f8c1cc1Mark Lord	__le16			flags;
293e14698745dd0de1ddbf5cd0cca4313a90f8c1cc1Mark Lord	__le32			tmstmp;
29420f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ};
29520f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ
29631961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ/* EDMA Physical Region Descriptor (ePRD); A.K.A. SG */
29731961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russstruct mv_sg {
298e14698745dd0de1ddbf5cd0cca4313a90f8c1cc1Mark Lord	__le32			addr;
299e14698745dd0de1ddbf5cd0cca4313a90f8c1cc1Mark Lord	__le32			flags_size;
300e14698745dd0de1ddbf5cd0cca4313a90f8c1cc1Mark Lord	__le32			addr_hi;
301e14698745dd0de1ddbf5cd0cca4313a90f8c1cc1Mark Lord	__le32			reserved;
30231961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ};
30320f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ
30431961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russstruct mv_port_priv {
30531961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ	struct mv_crqb		*crqb;
30631961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ	dma_addr_t		crqb_dma;
30731961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ	struct mv_crpb		*crpb;
30831961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ	dma_addr_t		crpb_dma;
30931961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ	struct mv_sg		*sg_tbl;
31031961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ	dma_addr_t		sg_tbl_dma;
31131961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ	u32			pp_flags;
31231961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ};
31331961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ
314bca1c4eb9411533d613123618c0d127fae532595Jeff Garzikstruct mv_port_signal {
315bca1c4eb9411533d613123618c0d127fae532595Jeff Garzik	u32			amps;
316bca1c4eb9411533d613123618c0d127fae532595Jeff Garzik	u32			pre;
317bca1c4eb9411533d613123618c0d127fae532595Jeff Garzik};
318bca1c4eb9411533d613123618c0d127fae532595Jeff Garzik
31947c2b677daeed9c79ecb7167c211ff36876ea611Jeff Garzikstruct mv_host_priv;
32047c2b677daeed9c79ecb7167c211ff36876ea611Jeff Garzikstruct mv_hw_ops {
3212a47ce06d534692f9bd2bf4e90a20fc9b1054c39Jeff Garzik	void (*phy_errata)(struct mv_host_priv *hpriv, void __iomem *mmio,
3222a47ce06d534692f9bd2bf4e90a20fc9b1054c39Jeff Garzik			   unsigned int port);
32347c2b677daeed9c79ecb7167c211ff36876ea611Jeff Garzik	void (*enable_leds)(struct mv_host_priv *hpriv, void __iomem *mmio);
32447c2b677daeed9c79ecb7167c211ff36876ea611Jeff Garzik	void (*read_preamp)(struct mv_host_priv *hpriv, int idx,
32547c2b677daeed9c79ecb7167c211ff36876ea611Jeff Garzik			   void __iomem *mmio);
326c9d39130123238ac18478a42e25cb7996eacfcc0Jeff Garzik	int (*reset_hc)(struct mv_host_priv *hpriv, void __iomem *mmio,
327c9d39130123238ac18478a42e25cb7996eacfcc0Jeff Garzik			unsigned int n_hc);
328522479fb98c6667f081e75f87e298e413c0b1db8Jeff Garzik	void (*reset_flash)(struct mv_host_priv *hpriv, void __iomem *mmio);
329522479fb98c6667f081e75f87e298e413c0b1db8Jeff Garzik	void (*reset_bus)(struct pci_dev *pdev, void __iomem *mmio);
33047c2b677daeed9c79ecb7167c211ff36876ea611Jeff Garzik};
33147c2b677daeed9c79ecb7167c211ff36876ea611Jeff Garzik
33231961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russstruct mv_host_priv {
33331961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ	u32			hp_flags;
334bca1c4eb9411533d613123618c0d127fae532595Jeff Garzik	struct mv_port_signal	signal[8];
33547c2b677daeed9c79ecb7167c211ff36876ea611Jeff Garzik	const struct mv_hw_ops	*ops;
33620f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ};
33720f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ
33820f733e7d75a16bffc34842b7682c9247dd5f954Brett Russstatic void mv_irq_clear(struct ata_port *ap);
33920f733e7d75a16bffc34842b7682c9247dd5f954Brett Russstatic u32 mv_scr_read(struct ata_port *ap, unsigned int sc_reg_in);
34020f733e7d75a16bffc34842b7682c9247dd5f954Brett Russstatic void mv_scr_write(struct ata_port *ap, unsigned int sc_reg_in, u32 val);
341c9d39130123238ac18478a42e25cb7996eacfcc0Jeff Garzikstatic u32 mv5_scr_read(struct ata_port *ap, unsigned int sc_reg_in);
342c9d39130123238ac18478a42e25cb7996eacfcc0Jeff Garzikstatic void mv5_scr_write(struct ata_port *ap, unsigned int sc_reg_in, u32 val);
34320f733e7d75a16bffc34842b7682c9247dd5f954Brett Russstatic void mv_phy_reset(struct ata_port *ap);
34422374677d18c5eeefd3a283431d312b8c44fef02Jeff Garzikstatic void __mv_phy_reset(struct ata_port *ap, int can_sleep);
345cca3974e48607c3775dc73b544a5700b2e37c21aJeff Garzikstatic void mv_host_stop(struct ata_host *host);
34631961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russstatic int mv_port_start(struct ata_port *ap);
34731961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russstatic void mv_port_stop(struct ata_port *ap);
34831961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russstatic void mv_qc_prep(struct ata_queued_cmd *qc);
349e4e7b89280d1d666e2c09e5ad36cf071796c4c7eJeff Garzikstatic void mv_qc_prep_iie(struct ata_queued_cmd *qc);
3509a3d9eb0177eb10500d49cd283b35576082a522dTejun Heostatic unsigned int mv_qc_issue(struct ata_queued_cmd *qc);
35120f733e7d75a16bffc34842b7682c9247dd5f954Brett Russstatic irqreturn_t mv_interrupt(int irq, void *dev_instance,
35220f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ				struct pt_regs *regs);
35331961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russstatic void mv_eng_timeout(struct ata_port *ap);
35420f733e7d75a16bffc34842b7682c9247dd5f954Brett Russstatic int mv_init_one(struct pci_dev *pdev, const struct pci_device_id *ent);
35520f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ
3562a47ce06d534692f9bd2bf4e90a20fc9b1054c39Jeff Garzikstatic void mv5_phy_errata(struct mv_host_priv *hpriv, void __iomem *mmio,
3572a47ce06d534692f9bd2bf4e90a20fc9b1054c39Jeff Garzik			   unsigned int port);
35847c2b677daeed9c79ecb7167c211ff36876ea611Jeff Garzikstatic void mv5_enable_leds(struct mv_host_priv *hpriv, void __iomem *mmio);
35947c2b677daeed9c79ecb7167c211ff36876ea611Jeff Garzikstatic void mv5_read_preamp(struct mv_host_priv *hpriv, int idx,
36047c2b677daeed9c79ecb7167c211ff36876ea611Jeff Garzik			   void __iomem *mmio);
361c9d39130123238ac18478a42e25cb7996eacfcc0Jeff Garzikstatic int mv5_reset_hc(struct mv_host_priv *hpriv, void __iomem *mmio,
362c9d39130123238ac18478a42e25cb7996eacfcc0Jeff Garzik			unsigned int n_hc);
363522479fb98c6667f081e75f87e298e413c0b1db8Jeff Garzikstatic void mv5_reset_flash(struct mv_host_priv *hpriv, void __iomem *mmio);
364522479fb98c6667f081e75f87e298e413c0b1db8Jeff Garzikstatic void mv5_reset_bus(struct pci_dev *pdev, void __iomem *mmio);
36547c2b677daeed9c79ecb7167c211ff36876ea611Jeff Garzik
3662a47ce06d534692f9bd2bf4e90a20fc9b1054c39Jeff Garzikstatic void mv6_phy_errata(struct mv_host_priv *hpriv, void __iomem *mmio,
3672a47ce06d534692f9bd2bf4e90a20fc9b1054c39Jeff Garzik			   unsigned int port);
36847c2b677daeed9c79ecb7167c211ff36876ea611Jeff Garzikstatic void mv6_enable_leds(struct mv_host_priv *hpriv, void __iomem *mmio);
36947c2b677daeed9c79ecb7167c211ff36876ea611Jeff Garzikstatic void mv6_read_preamp(struct mv_host_priv *hpriv, int idx,
37047c2b677daeed9c79ecb7167c211ff36876ea611Jeff Garzik			   void __iomem *mmio);
371c9d39130123238ac18478a42e25cb7996eacfcc0Jeff Garzikstatic int mv6_reset_hc(struct mv_host_priv *hpriv, void __iomem *mmio,
372c9d39130123238ac18478a42e25cb7996eacfcc0Jeff Garzik			unsigned int n_hc);
373522479fb98c6667f081e75f87e298e413c0b1db8Jeff Garzikstatic void mv6_reset_flash(struct mv_host_priv *hpriv, void __iomem *mmio);
374522479fb98c6667f081e75f87e298e413c0b1db8Jeff Garzikstatic void mv_reset_pci_bus(struct pci_dev *pdev, void __iomem *mmio);
375c9d39130123238ac18478a42e25cb7996eacfcc0Jeff Garzikstatic void mv_channel_reset(struct mv_host_priv *hpriv, void __iomem *mmio,
376c9d39130123238ac18478a42e25cb7996eacfcc0Jeff Garzik			     unsigned int port_no);
377c9d39130123238ac18478a42e25cb7996eacfcc0Jeff Garzikstatic void mv_stop_and_reset(struct ata_port *ap);
37847c2b677daeed9c79ecb7167c211ff36876ea611Jeff Garzik
379193515d51ccb363165d6b09e9ba5c21089e34badJeff Garzikstatic struct scsi_host_template mv_sht = {
38020f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ	.module			= THIS_MODULE,
38120f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ	.name			= DRV_NAME,
38220f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ	.ioctl			= ata_scsi_ioctl,
38320f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ	.queuecommand		= ata_scsi_queuecmd,
38431961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ	.can_queue		= MV_USE_Q_DEPTH,
38520f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ	.this_id		= ATA_SHT_THIS_ID,
38622374677d18c5eeefd3a283431d312b8c44fef02Jeff Garzik	.sg_tablesize		= MV_MAX_SG_CT / 2,
38720f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ	.cmd_per_lun		= ATA_SHT_CMD_PER_LUN,
38820f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ	.emulated		= ATA_SHT_EMULATED,
38931961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ	.use_clustering		= ATA_SHT_USE_CLUSTERING,
39020f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ	.proc_name		= DRV_NAME,
39120f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ	.dma_boundary		= MV_DMA_BOUNDARY,
39220f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ	.slave_configure	= ata_scsi_slave_config,
393ccf68c3405fca11386004674377d951b9b18e756Tejun Heo	.slave_destroy		= ata_scsi_slave_destroy,
39420f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ	.bios_param		= ata_std_bios_param,
39520f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ};
39620f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ
397c9d39130123238ac18478a42e25cb7996eacfcc0Jeff Garzikstatic const struct ata_port_operations mv5_ops = {
398c9d39130123238ac18478a42e25cb7996eacfcc0Jeff Garzik	.port_disable		= ata_port_disable,
399c9d39130123238ac18478a42e25cb7996eacfcc0Jeff Garzik
400c9d39130123238ac18478a42e25cb7996eacfcc0Jeff Garzik	.tf_load		= ata_tf_load,
401c9d39130123238ac18478a42e25cb7996eacfcc0Jeff Garzik	.tf_read		= ata_tf_read,
402c9d39130123238ac18478a42e25cb7996eacfcc0Jeff Garzik	.check_status		= ata_check_status,
403c9d39130123238ac18478a42e25cb7996eacfcc0Jeff Garzik	.exec_command		= ata_exec_command,
404c9d39130123238ac18478a42e25cb7996eacfcc0Jeff Garzik	.dev_select		= ata_std_dev_select,
405c9d39130123238ac18478a42e25cb7996eacfcc0Jeff Garzik
406c9d39130123238ac18478a42e25cb7996eacfcc0Jeff Garzik	.phy_reset		= mv_phy_reset,
407c9d39130123238ac18478a42e25cb7996eacfcc0Jeff Garzik
408c9d39130123238ac18478a42e25cb7996eacfcc0Jeff Garzik	.qc_prep		= mv_qc_prep,
409c9d39130123238ac18478a42e25cb7996eacfcc0Jeff Garzik	.qc_issue		= mv_qc_issue,
410a6b2c5d4754dc539a560fdf0d3fb78a14174394aAlan Cox	.data_xfer		= ata_mmio_data_xfer,
411c9d39130123238ac18478a42e25cb7996eacfcc0Jeff Garzik
412c9d39130123238ac18478a42e25cb7996eacfcc0Jeff Garzik	.eng_timeout		= mv_eng_timeout,
413c9d39130123238ac18478a42e25cb7996eacfcc0Jeff Garzik
414c9d39130123238ac18478a42e25cb7996eacfcc0Jeff Garzik	.irq_handler		= mv_interrupt,
415c9d39130123238ac18478a42e25cb7996eacfcc0Jeff Garzik	.irq_clear		= mv_irq_clear,
416c9d39130123238ac18478a42e25cb7996eacfcc0Jeff Garzik
417c9d39130123238ac18478a42e25cb7996eacfcc0Jeff Garzik	.scr_read		= mv5_scr_read,
418c9d39130123238ac18478a42e25cb7996eacfcc0Jeff Garzik	.scr_write		= mv5_scr_write,
419c9d39130123238ac18478a42e25cb7996eacfcc0Jeff Garzik
420c9d39130123238ac18478a42e25cb7996eacfcc0Jeff Garzik	.port_start		= mv_port_start,
421c9d39130123238ac18478a42e25cb7996eacfcc0Jeff Garzik	.port_stop		= mv_port_stop,
422c9d39130123238ac18478a42e25cb7996eacfcc0Jeff Garzik	.host_stop		= mv_host_stop,
423c9d39130123238ac18478a42e25cb7996eacfcc0Jeff Garzik};
424c9d39130123238ac18478a42e25cb7996eacfcc0Jeff Garzik
425c9d39130123238ac18478a42e25cb7996eacfcc0Jeff Garzikstatic const struct ata_port_operations mv6_ops = {
42620f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ	.port_disable		= ata_port_disable,
42720f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ
42820f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ	.tf_load		= ata_tf_load,
42920f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ	.tf_read		= ata_tf_read,
43020f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ	.check_status		= ata_check_status,
43120f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ	.exec_command		= ata_exec_command,
43220f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ	.dev_select		= ata_std_dev_select,
43320f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ
43420f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ	.phy_reset		= mv_phy_reset,
43520f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ
43631961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ	.qc_prep		= mv_qc_prep,
43731961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ	.qc_issue		= mv_qc_issue,
438a6b2c5d4754dc539a560fdf0d3fb78a14174394aAlan Cox	.data_xfer		= ata_mmio_data_xfer,
43920f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ
44031961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ	.eng_timeout		= mv_eng_timeout,
44120f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ
44220f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ	.irq_handler		= mv_interrupt,
44320f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ	.irq_clear		= mv_irq_clear,
44420f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ
44520f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ	.scr_read		= mv_scr_read,
44620f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ	.scr_write		= mv_scr_write,
44720f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ
44831961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ	.port_start		= mv_port_start,
44931961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ	.port_stop		= mv_port_stop,
45031961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ	.host_stop		= mv_host_stop,
45120f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ};
45220f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ
453e4e7b89280d1d666e2c09e5ad36cf071796c4c7eJeff Garzikstatic const struct ata_port_operations mv_iie_ops = {
454e4e7b89280d1d666e2c09e5ad36cf071796c4c7eJeff Garzik	.port_disable		= ata_port_disable,
455e4e7b89280d1d666e2c09e5ad36cf071796c4c7eJeff Garzik
456e4e7b89280d1d666e2c09e5ad36cf071796c4c7eJeff Garzik	.tf_load		= ata_tf_load,
457e4e7b89280d1d666e2c09e5ad36cf071796c4c7eJeff Garzik	.tf_read		= ata_tf_read,
458e4e7b89280d1d666e2c09e5ad36cf071796c4c7eJeff Garzik	.check_status		= ata_check_status,
459e4e7b89280d1d666e2c09e5ad36cf071796c4c7eJeff Garzik	.exec_command		= ata_exec_command,
460e4e7b89280d1d666e2c09e5ad36cf071796c4c7eJeff Garzik	.dev_select		= ata_std_dev_select,
461e4e7b89280d1d666e2c09e5ad36cf071796c4c7eJeff Garzik
462e4e7b89280d1d666e2c09e5ad36cf071796c4c7eJeff Garzik	.phy_reset		= mv_phy_reset,
463e4e7b89280d1d666e2c09e5ad36cf071796c4c7eJeff Garzik
464e4e7b89280d1d666e2c09e5ad36cf071796c4c7eJeff Garzik	.qc_prep		= mv_qc_prep_iie,
465e4e7b89280d1d666e2c09e5ad36cf071796c4c7eJeff Garzik	.qc_issue		= mv_qc_issue,
466e4e7b89280d1d666e2c09e5ad36cf071796c4c7eJeff Garzik
467e4e7b89280d1d666e2c09e5ad36cf071796c4c7eJeff Garzik	.eng_timeout		= mv_eng_timeout,
468e4e7b89280d1d666e2c09e5ad36cf071796c4c7eJeff Garzik
469e4e7b89280d1d666e2c09e5ad36cf071796c4c7eJeff Garzik	.irq_handler		= mv_interrupt,
470e4e7b89280d1d666e2c09e5ad36cf071796c4c7eJeff Garzik	.irq_clear		= mv_irq_clear,
471e4e7b89280d1d666e2c09e5ad36cf071796c4c7eJeff Garzik
472e4e7b89280d1d666e2c09e5ad36cf071796c4c7eJeff Garzik	.scr_read		= mv_scr_read,
473e4e7b89280d1d666e2c09e5ad36cf071796c4c7eJeff Garzik	.scr_write		= mv_scr_write,
474e4e7b89280d1d666e2c09e5ad36cf071796c4c7eJeff Garzik
475e4e7b89280d1d666e2c09e5ad36cf071796c4c7eJeff Garzik	.port_start		= mv_port_start,
476e4e7b89280d1d666e2c09e5ad36cf071796c4c7eJeff Garzik	.port_stop		= mv_port_stop,
477e4e7b89280d1d666e2c09e5ad36cf071796c4c7eJeff Garzik	.host_stop		= mv_host_stop,
478e4e7b89280d1d666e2c09e5ad36cf071796c4c7eJeff Garzik};
479e4e7b89280d1d666e2c09e5ad36cf071796c4c7eJeff Garzik
48098ac62defe529d04a192688f40d801a2d8fbcf98Arjan van de Venstatic const struct ata_port_info mv_port_info[] = {
48120f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ	{  /* chip_504x */
48220f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ		.sht		= &mv_sht,
483cca3974e48607c3775dc73b544a5700b2e37c21aJeff Garzik		.flags		= MV_COMMON_FLAGS,
48431961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ		.pio_mask	= 0x1f,	/* pio0-4 */
485c9d39130123238ac18478a42e25cb7996eacfcc0Jeff Garzik		.udma_mask	= 0x7f,	/* udma0-6 */
486c9d39130123238ac18478a42e25cb7996eacfcc0Jeff Garzik		.port_ops	= &mv5_ops,
48720f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ	},
48820f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ	{  /* chip_508x */
48920f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ		.sht		= &mv_sht,
490cca3974e48607c3775dc73b544a5700b2e37c21aJeff Garzik		.flags		= (MV_COMMON_FLAGS | MV_FLAG_DUAL_HC),
49131961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ		.pio_mask	= 0x1f,	/* pio0-4 */
492c9d39130123238ac18478a42e25cb7996eacfcc0Jeff Garzik		.udma_mask	= 0x7f,	/* udma0-6 */
493c9d39130123238ac18478a42e25cb7996eacfcc0Jeff Garzik		.port_ops	= &mv5_ops,
49420f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ	},
49547c2b677daeed9c79ecb7167c211ff36876ea611Jeff Garzik	{  /* chip_5080 */
49647c2b677daeed9c79ecb7167c211ff36876ea611Jeff Garzik		.sht		= &mv_sht,
497cca3974e48607c3775dc73b544a5700b2e37c21aJeff Garzik		.flags		= (MV_COMMON_FLAGS | MV_FLAG_DUAL_HC),
49847c2b677daeed9c79ecb7167c211ff36876ea611Jeff Garzik		.pio_mask	= 0x1f,	/* pio0-4 */
499c9d39130123238ac18478a42e25cb7996eacfcc0Jeff Garzik		.udma_mask	= 0x7f,	/* udma0-6 */
500c9d39130123238ac18478a42e25cb7996eacfcc0Jeff Garzik		.port_ops	= &mv5_ops,
50147c2b677daeed9c79ecb7167c211ff36876ea611Jeff Garzik	},
50220f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ	{  /* chip_604x */
50320f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ		.sht		= &mv_sht,
504cca3974e48607c3775dc73b544a5700b2e37c21aJeff Garzik		.flags		= (MV_COMMON_FLAGS | MV_6XXX_FLAGS),
50531961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ		.pio_mask	= 0x1f,	/* pio0-4 */
50631961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ		.udma_mask	= 0x7f,	/* udma0-6 */
507c9d39130123238ac18478a42e25cb7996eacfcc0Jeff Garzik		.port_ops	= &mv6_ops,
50820f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ	},
50920f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ	{  /* chip_608x */
51020f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ		.sht		= &mv_sht,
511cca3974e48607c3775dc73b544a5700b2e37c21aJeff Garzik		.flags		= (MV_COMMON_FLAGS | MV_6XXX_FLAGS |
51231961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ				   MV_FLAG_DUAL_HC),
51331961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ		.pio_mask	= 0x1f,	/* pio0-4 */
51431961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ		.udma_mask	= 0x7f,	/* udma0-6 */
515c9d39130123238ac18478a42e25cb7996eacfcc0Jeff Garzik		.port_ops	= &mv6_ops,
51620f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ	},
517e4e7b89280d1d666e2c09e5ad36cf071796c4c7eJeff Garzik	{  /* chip_6042 */
518e4e7b89280d1d666e2c09e5ad36cf071796c4c7eJeff Garzik		.sht		= &mv_sht,
519cca3974e48607c3775dc73b544a5700b2e37c21aJeff Garzik		.flags		= (MV_COMMON_FLAGS | MV_6XXX_FLAGS),
520e4e7b89280d1d666e2c09e5ad36cf071796c4c7eJeff Garzik		.pio_mask	= 0x1f,	/* pio0-4 */
521e4e7b89280d1d666e2c09e5ad36cf071796c4c7eJeff Garzik		.udma_mask	= 0x7f,	/* udma0-6 */
522e4e7b89280d1d666e2c09e5ad36cf071796c4c7eJeff Garzik		.port_ops	= &mv_iie_ops,
523e4e7b89280d1d666e2c09e5ad36cf071796c4c7eJeff Garzik	},
524e4e7b89280d1d666e2c09e5ad36cf071796c4c7eJeff Garzik	{  /* chip_7042 */
525e4e7b89280d1d666e2c09e5ad36cf071796c4c7eJeff Garzik		.sht		= &mv_sht,
526cca3974e48607c3775dc73b544a5700b2e37c21aJeff Garzik		.flags		= (MV_COMMON_FLAGS | MV_6XXX_FLAGS |
527e4e7b89280d1d666e2c09e5ad36cf071796c4c7eJeff Garzik				   MV_FLAG_DUAL_HC),
528e4e7b89280d1d666e2c09e5ad36cf071796c4c7eJeff Garzik		.pio_mask	= 0x1f,	/* pio0-4 */
529e4e7b89280d1d666e2c09e5ad36cf071796c4c7eJeff Garzik		.udma_mask	= 0x7f,	/* udma0-6 */
530e4e7b89280d1d666e2c09e5ad36cf071796c4c7eJeff Garzik		.port_ops	= &mv_iie_ops,
531e4e7b89280d1d666e2c09e5ad36cf071796c4c7eJeff Garzik	},
53220f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ};
53320f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ
5343b7d697dfb7d03edb87e50b743a7ecff029618e9Jeff Garzikstatic const struct pci_device_id mv_pci_tbl[] = {
53520f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ	{PCI_DEVICE(PCI_VENDOR_ID_MARVELL, 0x5040), 0, 0, chip_504x},
53620f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ	{PCI_DEVICE(PCI_VENDOR_ID_MARVELL, 0x5041), 0, 0, chip_504x},
53747c2b677daeed9c79ecb7167c211ff36876ea611Jeff Garzik	{PCI_DEVICE(PCI_VENDOR_ID_MARVELL, 0x5080), 0, 0, chip_5080},
53820f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ	{PCI_DEVICE(PCI_VENDOR_ID_MARVELL, 0x5081), 0, 0, chip_508x},
53920f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ
54020f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ	{PCI_DEVICE(PCI_VENDOR_ID_MARVELL, 0x6040), 0, 0, chip_604x},
54120f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ	{PCI_DEVICE(PCI_VENDOR_ID_MARVELL, 0x6041), 0, 0, chip_604x},
542e4e7b89280d1d666e2c09e5ad36cf071796c4c7eJeff Garzik	{PCI_DEVICE(PCI_VENDOR_ID_MARVELL, 0x6042), 0, 0, chip_6042},
54320f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ	{PCI_DEVICE(PCI_VENDOR_ID_MARVELL, 0x6080), 0, 0, chip_608x},
54420f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ	{PCI_DEVICE(PCI_VENDOR_ID_MARVELL, 0x6081), 0, 0, chip_608x},
54529179539dac74bf46b519b889602f23841be12e8Jeff Garzik
54629179539dac74bf46b519b889602f23841be12e8Jeff Garzik	{PCI_DEVICE(PCI_VENDOR_ID_ADAPTEC2, 0x0241), 0, 0, chip_604x},
54720f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ	{}			/* terminate list */
54820f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ};
54920f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ
55020f733e7d75a16bffc34842b7682c9247dd5f954Brett Russstatic struct pci_driver mv_pci_driver = {
55120f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ	.name			= DRV_NAME,
55220f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ	.id_table		= mv_pci_tbl,
55320f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ	.probe			= mv_init_one,
55420f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ	.remove			= ata_pci_remove_one,
55520f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ};
55620f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ
55747c2b677daeed9c79ecb7167c211ff36876ea611Jeff Garzikstatic const struct mv_hw_ops mv5xxx_ops = {
55847c2b677daeed9c79ecb7167c211ff36876ea611Jeff Garzik	.phy_errata		= mv5_phy_errata,
55947c2b677daeed9c79ecb7167c211ff36876ea611Jeff Garzik	.enable_leds		= mv5_enable_leds,
56047c2b677daeed9c79ecb7167c211ff36876ea611Jeff Garzik	.read_preamp		= mv5_read_preamp,
56147c2b677daeed9c79ecb7167c211ff36876ea611Jeff Garzik	.reset_hc		= mv5_reset_hc,
562522479fb98c6667f081e75f87e298e413c0b1db8Jeff Garzik	.reset_flash		= mv5_reset_flash,
563522479fb98c6667f081e75f87e298e413c0b1db8Jeff Garzik	.reset_bus		= mv5_reset_bus,
56447c2b677daeed9c79ecb7167c211ff36876ea611Jeff Garzik};
56547c2b677daeed9c79ecb7167c211ff36876ea611Jeff Garzik
56647c2b677daeed9c79ecb7167c211ff36876ea611Jeff Garzikstatic const struct mv_hw_ops mv6xxx_ops = {
56747c2b677daeed9c79ecb7167c211ff36876ea611Jeff Garzik	.phy_errata		= mv6_phy_errata,
56847c2b677daeed9c79ecb7167c211ff36876ea611Jeff Garzik	.enable_leds		= mv6_enable_leds,
56947c2b677daeed9c79ecb7167c211ff36876ea611Jeff Garzik	.read_preamp		= mv6_read_preamp,
57047c2b677daeed9c79ecb7167c211ff36876ea611Jeff Garzik	.reset_hc		= mv6_reset_hc,
571522479fb98c6667f081e75f87e298e413c0b1db8Jeff Garzik	.reset_flash		= mv6_reset_flash,
572522479fb98c6667f081e75f87e298e413c0b1db8Jeff Garzik	.reset_bus		= mv_reset_pci_bus,
57347c2b677daeed9c79ecb7167c211ff36876ea611Jeff Garzik};
57447c2b677daeed9c79ecb7167c211ff36876ea611Jeff Garzik
57520f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ/*
576ddef9bb367b19383df627e388cb4c01c86ddba6cJeff Garzik * module options
577ddef9bb367b19383df627e388cb4c01c86ddba6cJeff Garzik */
578ddef9bb367b19383df627e388cb4c01c86ddba6cJeff Garzikstatic int msi;	      /* Use PCI msi; either zero (off, default) or non-zero */
579ddef9bb367b19383df627e388cb4c01c86ddba6cJeff Garzik
580ddef9bb367b19383df627e388cb4c01c86ddba6cJeff Garzik
581ddef9bb367b19383df627e388cb4c01c86ddba6cJeff Garzik/*
58220f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ * Functions
58320f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ */
58420f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ
58520f733e7d75a16bffc34842b7682c9247dd5f954Brett Russstatic inline void writelfl(unsigned long data, void __iomem *addr)
58620f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ{
58720f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ	writel(data, addr);
58820f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ	(void) readl(addr);	/* flush to avoid PCI posted write */
58920f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ}
59020f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ
59120f733e7d75a16bffc34842b7682c9247dd5f954Brett Russstatic inline void __iomem *mv_hc_base(void __iomem *base, unsigned int hc)
59220f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ{
59320f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ	return (base + MV_SATAHC0_REG_BASE + (hc * MV_SATAHC_REG_SZ));
59420f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ}
59520f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ
596c9d39130123238ac18478a42e25cb7996eacfcc0Jeff Garzikstatic inline unsigned int mv_hc_from_port(unsigned int port)
597c9d39130123238ac18478a42e25cb7996eacfcc0Jeff Garzik{
598c9d39130123238ac18478a42e25cb7996eacfcc0Jeff Garzik	return port >> MV_PORT_HC_SHIFT;
599c9d39130123238ac18478a42e25cb7996eacfcc0Jeff Garzik}
600c9d39130123238ac18478a42e25cb7996eacfcc0Jeff Garzik
601c9d39130123238ac18478a42e25cb7996eacfcc0Jeff Garzikstatic inline unsigned int mv_hardport_from_port(unsigned int port)
602c9d39130123238ac18478a42e25cb7996eacfcc0Jeff Garzik{
603c9d39130123238ac18478a42e25cb7996eacfcc0Jeff Garzik	return port & MV_PORT_MASK;
604c9d39130123238ac18478a42e25cb7996eacfcc0Jeff Garzik}
605c9d39130123238ac18478a42e25cb7996eacfcc0Jeff Garzik
606c9d39130123238ac18478a42e25cb7996eacfcc0Jeff Garzikstatic inline void __iomem *mv_hc_base_from_port(void __iomem *base,
607c9d39130123238ac18478a42e25cb7996eacfcc0Jeff Garzik						 unsigned int port)
608c9d39130123238ac18478a42e25cb7996eacfcc0Jeff Garzik{
609c9d39130123238ac18478a42e25cb7996eacfcc0Jeff Garzik	return mv_hc_base(base, mv_hc_from_port(port));
610c9d39130123238ac18478a42e25cb7996eacfcc0Jeff Garzik}
611c9d39130123238ac18478a42e25cb7996eacfcc0Jeff Garzik
61220f733e7d75a16bffc34842b7682c9247dd5f954Brett Russstatic inline void __iomem *mv_port_base(void __iomem *base, unsigned int port)
61320f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ{
614c9d39130123238ac18478a42e25cb7996eacfcc0Jeff Garzik	return  mv_hc_base_from_port(base, port) +
6158b260248d9e0e8b64bb72fd4dee03ad86984c344Jeff Garzik		MV_SATAHC_ARBTR_REG_SZ +
616c9d39130123238ac18478a42e25cb7996eacfcc0Jeff Garzik		(mv_hardport_from_port(port) * MV_PORT_REG_SZ);
61720f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ}
61820f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ
61920f733e7d75a16bffc34842b7682c9247dd5f954Brett Russstatic inline void __iomem *mv_ap_base(struct ata_port *ap)
62020f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ{
621cca3974e48607c3775dc73b544a5700b2e37c21aJeff Garzik	return mv_port_base(ap->host->mmio_base, ap->port_no);
62220f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ}
62320f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ
624cca3974e48607c3775dc73b544a5700b2e37c21aJeff Garzikstatic inline int mv_get_hc_count(unsigned long port_flags)
62531961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ{
626cca3974e48607c3775dc73b544a5700b2e37c21aJeff Garzik	return ((port_flags & MV_FLAG_DUAL_HC) ? 2 : 1);
62731961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ}
62831961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ
62931961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russstatic void mv_irq_clear(struct ata_port *ap)
63020f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ{
63120f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ}
63220f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ
63305b308e1df6d9d673daedb517969241f41278b52Brett Russ/**
63405b308e1df6d9d673daedb517969241f41278b52Brett Russ *      mv_start_dma - Enable eDMA engine
63505b308e1df6d9d673daedb517969241f41278b52Brett Russ *      @base: port base address
63605b308e1df6d9d673daedb517969241f41278b52Brett Russ *      @pp: port private data
63705b308e1df6d9d673daedb517969241f41278b52Brett Russ *
638beec7dbc6ff003bbc94de62b3323519c878fb2acTejun Heo *      Verify the local cache of the eDMA state is accurate with a
639beec7dbc6ff003bbc94de62b3323519c878fb2acTejun Heo *      WARN_ON.
64005b308e1df6d9d673daedb517969241f41278b52Brett Russ *
64105b308e1df6d9d673daedb517969241f41278b52Brett Russ *      LOCKING:
64205b308e1df6d9d673daedb517969241f41278b52Brett Russ *      Inherited from caller.
64305b308e1df6d9d673daedb517969241f41278b52Brett Russ */
644afb0edd922c7ed6e73678730921dfcccebec17e8Brett Russstatic void mv_start_dma(void __iomem *base, struct mv_port_priv *pp)
64520f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ{
646afb0edd922c7ed6e73678730921dfcccebec17e8Brett Russ	if (!(MV_PP_FLAG_EDMA_EN & pp->pp_flags)) {
647afb0edd922c7ed6e73678730921dfcccebec17e8Brett Russ		writelfl(EDMA_EN, base + EDMA_CMD_OFS);
648afb0edd922c7ed6e73678730921dfcccebec17e8Brett Russ		pp->pp_flags |= MV_PP_FLAG_EDMA_EN;
649afb0edd922c7ed6e73678730921dfcccebec17e8Brett Russ	}
650beec7dbc6ff003bbc94de62b3323519c878fb2acTejun Heo	WARN_ON(!(EDMA_EN & readl(base + EDMA_CMD_OFS)));
65120f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ}
65220f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ
65305b308e1df6d9d673daedb517969241f41278b52Brett Russ/**
65405b308e1df6d9d673daedb517969241f41278b52Brett Russ *      mv_stop_dma - Disable eDMA engine
65505b308e1df6d9d673daedb517969241f41278b52Brett Russ *      @ap: ATA channel to manipulate
65605b308e1df6d9d673daedb517969241f41278b52Brett Russ *
657beec7dbc6ff003bbc94de62b3323519c878fb2acTejun Heo *      Verify the local cache of the eDMA state is accurate with a
658beec7dbc6ff003bbc94de62b3323519c878fb2acTejun Heo *      WARN_ON.
65905b308e1df6d9d673daedb517969241f41278b52Brett Russ *
66005b308e1df6d9d673daedb517969241f41278b52Brett Russ *      LOCKING:
66105b308e1df6d9d673daedb517969241f41278b52Brett Russ *      Inherited from caller.
66205b308e1df6d9d673daedb517969241f41278b52Brett Russ */
66331961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russstatic void mv_stop_dma(struct ata_port *ap)
66420f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ{
66531961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ	void __iomem *port_mmio = mv_ap_base(ap);
66631961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ	struct mv_port_priv *pp	= ap->private_data;
66731961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ	u32 reg;
66831961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ	int i;
66931961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ
670afb0edd922c7ed6e73678730921dfcccebec17e8Brett Russ	if (MV_PP_FLAG_EDMA_EN & pp->pp_flags) {
671afb0edd922c7ed6e73678730921dfcccebec17e8Brett Russ		/* Disable EDMA if active.   The disable bit auto clears.
67231961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ		 */
67331961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ		writelfl(EDMA_DS, port_mmio + EDMA_CMD_OFS);
67431961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ		pp->pp_flags &= ~MV_PP_FLAG_EDMA_EN;
675afb0edd922c7ed6e73678730921dfcccebec17e8Brett Russ	} else {
676beec7dbc6ff003bbc94de62b3323519c878fb2acTejun Heo		WARN_ON(EDMA_EN & readl(port_mmio + EDMA_CMD_OFS));
677afb0edd922c7ed6e73678730921dfcccebec17e8Brett Russ  	}
6788b260248d9e0e8b64bb72fd4dee03ad86984c344Jeff Garzik
67931961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ	/* now properly wait for the eDMA to stop */
68031961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ	for (i = 1000; i > 0; i--) {
68131961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ		reg = readl(port_mmio + EDMA_CMD_OFS);
68231961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ		if (!(EDMA_EN & reg)) {
68331961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ			break;
68431961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ		}
68531961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ		udelay(100);
68631961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ	}
68731961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ
68831961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ	if (EDMA_EN & reg) {
689f15a1dafed22d5037e0feea7528e1eeb28a1a7a3Tejun Heo		ata_port_printk(ap, KERN_ERR, "Unable to stop eDMA\n");
690afb0edd922c7ed6e73678730921dfcccebec17e8Brett Russ		/* FIXME: Consider doing a reset here to recover */
69131961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ	}
69220f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ}
69320f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ
6948a70f8dc08dd40b7f8ac77280eaa99a8c6bc46f4Jeff Garzik#ifdef ATA_DEBUG
69531961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russstatic void mv_dump_mem(void __iomem *start, unsigned bytes)
69620f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ{
69731961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ	int b, w;
69831961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ	for (b = 0; b < bytes; ) {
69931961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ		DPRINTK("%p: ", start + b);
70031961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ		for (w = 0; b < bytes && w < 4; w++) {
70131961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ			printk("%08x ",readl(start + b));
70231961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ			b += sizeof(u32);
70331961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ		}
70431961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ		printk("\n");
70531961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ	}
70631961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ}
7078a70f8dc08dd40b7f8ac77280eaa99a8c6bc46f4Jeff Garzik#endif
7088a70f8dc08dd40b7f8ac77280eaa99a8c6bc46f4Jeff Garzik
70931961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russstatic void mv_dump_pci_cfg(struct pci_dev *pdev, unsigned bytes)
71031961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ{
71131961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ#ifdef ATA_DEBUG
71231961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ	int b, w;
71331961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ	u32 dw;
71431961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ	for (b = 0; b < bytes; ) {
71531961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ		DPRINTK("%02x: ", b);
71631961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ		for (w = 0; b < bytes && w < 4; w++) {
71731961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ			(void) pci_read_config_dword(pdev,b,&dw);
71831961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ			printk("%08x ",dw);
71931961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ			b += sizeof(u32);
72031961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ		}
72131961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ		printk("\n");
72231961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ	}
72331961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ#endif
72431961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ}
72531961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russstatic void mv_dump_all_regs(void __iomem *mmio_base, int port,
72631961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ			     struct pci_dev *pdev)
72731961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ{
72831961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ#ifdef ATA_DEBUG
7298b260248d9e0e8b64bb72fd4dee03ad86984c344Jeff Garzik	void __iomem *hc_base = mv_hc_base(mmio_base,
73031961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ					   port >> MV_PORT_HC_SHIFT);
73131961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ	void __iomem *port_base;
73231961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ	int start_port, num_ports, p, start_hc, num_hcs, hc;
73331961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ
73431961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ	if (0 > port) {
73531961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ		start_hc = start_port = 0;
73631961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ		num_ports = 8;		/* shld be benign for 4 port devs */
73731961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ		num_hcs = 2;
73831961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ	} else {
73931961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ		start_hc = port >> MV_PORT_HC_SHIFT;
74031961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ		start_port = port;
74131961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ		num_ports = num_hcs = 1;
74231961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ	}
7438b260248d9e0e8b64bb72fd4dee03ad86984c344Jeff Garzik	DPRINTK("All registers for port(s) %u-%u:\n", start_port,
74431961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ		num_ports > 1 ? num_ports - 1 : start_port);
74531961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ
74631961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ	if (NULL != pdev) {
74731961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ		DPRINTK("PCI config space regs:\n");
74831961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ		mv_dump_pci_cfg(pdev, 0x68);
74931961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ	}
75031961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ	DPRINTK("PCI regs:\n");
75131961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ	mv_dump_mem(mmio_base+0xc00, 0x3c);
75231961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ	mv_dump_mem(mmio_base+0xd00, 0x34);
75331961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ	mv_dump_mem(mmio_base+0xf00, 0x4);
75431961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ	mv_dump_mem(mmio_base+0x1d00, 0x6c);
75531961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ	for (hc = start_hc; hc < start_hc + num_hcs; hc++) {
756d220c37e0a3c9a47ae00e87e044d963b3ea040bcDan Aloni		hc_base = mv_hc_base(mmio_base, hc);
75731961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ		DPRINTK("HC regs (HC %i):\n", hc);
75831961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ		mv_dump_mem(hc_base, 0x1c);
75931961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ	}
76031961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ	for (p = start_port; p < start_port + num_ports; p++) {
76131961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ		port_base = mv_port_base(mmio_base, p);
76231961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ		DPRINTK("EDMA regs (port %i):\n",p);
76331961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ		mv_dump_mem(port_base, 0x54);
76431961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ		DPRINTK("SATA regs (port %i):\n",p);
76531961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ		mv_dump_mem(port_base+0x300, 0x60);
76631961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ	}
76731961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ#endif
76820f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ}
76920f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ
77020f733e7d75a16bffc34842b7682c9247dd5f954Brett Russstatic unsigned int mv_scr_offset(unsigned int sc_reg_in)
77120f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ{
77220f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ	unsigned int ofs;
77320f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ
77420f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ	switch (sc_reg_in) {
77520f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ	case SCR_STATUS:
77620f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ	case SCR_CONTROL:
77720f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ	case SCR_ERROR:
77820f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ		ofs = SATA_STATUS_OFS + (sc_reg_in * sizeof(u32));
77920f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ		break;
78020f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ	case SCR_ACTIVE:
78120f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ		ofs = SATA_ACTIVE_OFS;   /* active is not with the others */
78220f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ		break;
78320f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ	default:
78420f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ		ofs = 0xffffffffU;
78520f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ		break;
78620f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ	}
78720f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ	return ofs;
78820f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ}
78920f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ
79020f733e7d75a16bffc34842b7682c9247dd5f954Brett Russstatic u32 mv_scr_read(struct ata_port *ap, unsigned int sc_reg_in)
79120f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ{
79220f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ	unsigned int ofs = mv_scr_offset(sc_reg_in);
79320f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ
79420f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ	if (0xffffffffU != ofs) {
79520f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ		return readl(mv_ap_base(ap) + ofs);
79620f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ	} else {
79720f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ		return (u32) ofs;
79820f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ	}
79920f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ}
80020f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ
80120f733e7d75a16bffc34842b7682c9247dd5f954Brett Russstatic void mv_scr_write(struct ata_port *ap, unsigned int sc_reg_in, u32 val)
80220f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ{
80320f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ	unsigned int ofs = mv_scr_offset(sc_reg_in);
80420f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ
80520f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ	if (0xffffffffU != ofs) {
80620f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ		writelfl(val, mv_ap_base(ap) + ofs);
80720f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ	}
80820f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ}
80920f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ
81005b308e1df6d9d673daedb517969241f41278b52Brett Russ/**
81105b308e1df6d9d673daedb517969241f41278b52Brett Russ *      mv_host_stop - Host specific cleanup/stop routine.
812cca3974e48607c3775dc73b544a5700b2e37c21aJeff Garzik *      @host: host data structure
81305b308e1df6d9d673daedb517969241f41278b52Brett Russ *
81405b308e1df6d9d673daedb517969241f41278b52Brett Russ *      Disable ints, cleanup host memory, call general purpose
81505b308e1df6d9d673daedb517969241f41278b52Brett Russ *      host_stop.
81605b308e1df6d9d673daedb517969241f41278b52Brett Russ *
81705b308e1df6d9d673daedb517969241f41278b52Brett Russ *      LOCKING:
81805b308e1df6d9d673daedb517969241f41278b52Brett Russ *      Inherited from caller.
81905b308e1df6d9d673daedb517969241f41278b52Brett Russ */
820cca3974e48607c3775dc73b544a5700b2e37c21aJeff Garzikstatic void mv_host_stop(struct ata_host *host)
82120f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ{
822cca3974e48607c3775dc73b544a5700b2e37c21aJeff Garzik	struct mv_host_priv *hpriv = host->private_data;
823cca3974e48607c3775dc73b544a5700b2e37c21aJeff Garzik	struct pci_dev *pdev = to_pci_dev(host->dev);
82431961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ
82531961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ	if (hpriv->hp_flags & MV_HP_FLAG_MSI) {
82631961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ		pci_disable_msi(pdev);
82731961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ	} else {
82831961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ		pci_intx(pdev, 0);
82931961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ	}
83031961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ	kfree(hpriv);
831cca3974e48607c3775dc73b544a5700b2e37c21aJeff Garzik	ata_host_stop(host);
83231961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ}
83331961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ
8346037d6bbdff65eb5a84fe35e140f4da4f7cc103aJeff Garzikstatic inline void mv_priv_free(struct mv_port_priv *pp, struct device *dev)
8356037d6bbdff65eb5a84fe35e140f4da4f7cc103aJeff Garzik{
8366037d6bbdff65eb5a84fe35e140f4da4f7cc103aJeff Garzik	dma_free_coherent(dev, MV_PORT_PRIV_DMA_SZ, pp->crpb, pp->crpb_dma);
8376037d6bbdff65eb5a84fe35e140f4da4f7cc103aJeff Garzik}
8386037d6bbdff65eb5a84fe35e140f4da4f7cc103aJeff Garzik
839e4e7b89280d1d666e2c09e5ad36cf071796c4c7eJeff Garzikstatic void mv_edma_cfg(struct mv_host_priv *hpriv, void __iomem *port_mmio)
840e4e7b89280d1d666e2c09e5ad36cf071796c4c7eJeff Garzik{
841e4e7b89280d1d666e2c09e5ad36cf071796c4c7eJeff Garzik	u32 cfg = readl(port_mmio + EDMA_CFG_OFS);
842e4e7b89280d1d666e2c09e5ad36cf071796c4c7eJeff Garzik
843e4e7b89280d1d666e2c09e5ad36cf071796c4c7eJeff Garzik	/* set up non-NCQ EDMA configuration */
844e4e7b89280d1d666e2c09e5ad36cf071796c4c7eJeff Garzik	cfg &= ~0x1f;		/* clear queue depth */
845e4e7b89280d1d666e2c09e5ad36cf071796c4c7eJeff Garzik	cfg &= ~EDMA_CFG_NCQ;	/* clear NCQ mode */
846e4e7b89280d1d666e2c09e5ad36cf071796c4c7eJeff Garzik	cfg &= ~(1 << 9);	/* disable equeue */
847e4e7b89280d1d666e2c09e5ad36cf071796c4c7eJeff Garzik
848e4e7b89280d1d666e2c09e5ad36cf071796c4c7eJeff Garzik	if (IS_GEN_I(hpriv))
849e4e7b89280d1d666e2c09e5ad36cf071796c4c7eJeff Garzik		cfg |= (1 << 8);	/* enab config burst size mask */
850e4e7b89280d1d666e2c09e5ad36cf071796c4c7eJeff Garzik
851e4e7b89280d1d666e2c09e5ad36cf071796c4c7eJeff Garzik	else if (IS_GEN_II(hpriv))
852e4e7b89280d1d666e2c09e5ad36cf071796c4c7eJeff Garzik		cfg |= EDMA_CFG_RD_BRST_EXT | EDMA_CFG_WR_BUFF_LEN;
853e4e7b89280d1d666e2c09e5ad36cf071796c4c7eJeff Garzik
854e4e7b89280d1d666e2c09e5ad36cf071796c4c7eJeff Garzik	else if (IS_GEN_IIE(hpriv)) {
855e4e7b89280d1d666e2c09e5ad36cf071796c4c7eJeff Garzik		cfg |= (1 << 23);	/* dis RX PM port mask */
856e4e7b89280d1d666e2c09e5ad36cf071796c4c7eJeff Garzik		cfg &= ~(1 << 16);	/* dis FIS-based switching (for now) */
857e4e7b89280d1d666e2c09e5ad36cf071796c4c7eJeff Garzik		cfg &= ~(1 << 19);	/* dis 128-entry queue (for now?) */
858e4e7b89280d1d666e2c09e5ad36cf071796c4c7eJeff Garzik		cfg |= (1 << 18);	/* enab early completion */
859e4e7b89280d1d666e2c09e5ad36cf071796c4c7eJeff Garzik		cfg |= (1 << 17);	/* enab host q cache */
860e4e7b89280d1d666e2c09e5ad36cf071796c4c7eJeff Garzik		cfg |= (1 << 22);	/* enab cutthrough */
861e4e7b89280d1d666e2c09e5ad36cf071796c4c7eJeff Garzik	}
862e4e7b89280d1d666e2c09e5ad36cf071796c4c7eJeff Garzik
863e4e7b89280d1d666e2c09e5ad36cf071796c4c7eJeff Garzik	writelfl(cfg, port_mmio + EDMA_CFG_OFS);
864e4e7b89280d1d666e2c09e5ad36cf071796c4c7eJeff Garzik}
865e4e7b89280d1d666e2c09e5ad36cf071796c4c7eJeff Garzik
86605b308e1df6d9d673daedb517969241f41278b52Brett Russ/**
86705b308e1df6d9d673daedb517969241f41278b52Brett Russ *      mv_port_start - Port specific init/start routine.
86805b308e1df6d9d673daedb517969241f41278b52Brett Russ *      @ap: ATA channel to manipulate
86905b308e1df6d9d673daedb517969241f41278b52Brett Russ *
87005b308e1df6d9d673daedb517969241f41278b52Brett Russ *      Allocate and point to DMA memory, init port private memory,
87105b308e1df6d9d673daedb517969241f41278b52Brett Russ *      zero indices.
87205b308e1df6d9d673daedb517969241f41278b52Brett Russ *
87305b308e1df6d9d673daedb517969241f41278b52Brett Russ *      LOCKING:
87405b308e1df6d9d673daedb517969241f41278b52Brett Russ *      Inherited from caller.
87505b308e1df6d9d673daedb517969241f41278b52Brett Russ */
87631961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russstatic int mv_port_start(struct ata_port *ap)
87731961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ{
878cca3974e48607c3775dc73b544a5700b2e37c21aJeff Garzik	struct device *dev = ap->host->dev;
879cca3974e48607c3775dc73b544a5700b2e37c21aJeff Garzik	struct mv_host_priv *hpriv = ap->host->private_data;
88031961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ	struct mv_port_priv *pp;
88131961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ	void __iomem *port_mmio = mv_ap_base(ap);
88231961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ	void *mem;
88331961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ	dma_addr_t mem_dma;
8846037d6bbdff65eb5a84fe35e140f4da4f7cc103aJeff Garzik	int rc = -ENOMEM;
88531961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ
88631961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ	pp = kmalloc(sizeof(*pp), GFP_KERNEL);
8876037d6bbdff65eb5a84fe35e140f4da4f7cc103aJeff Garzik	if (!pp)
8886037d6bbdff65eb5a84fe35e140f4da4f7cc103aJeff Garzik		goto err_out;
88931961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ	memset(pp, 0, sizeof(*pp));
89031961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ
8918b260248d9e0e8b64bb72fd4dee03ad86984c344Jeff Garzik	mem = dma_alloc_coherent(dev, MV_PORT_PRIV_DMA_SZ, &mem_dma,
89231961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ				 GFP_KERNEL);
8936037d6bbdff65eb5a84fe35e140f4da4f7cc103aJeff Garzik	if (!mem)
8946037d6bbdff65eb5a84fe35e140f4da4f7cc103aJeff Garzik		goto err_out_pp;
89531961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ	memset(mem, 0, MV_PORT_PRIV_DMA_SZ);
89631961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ
8976037d6bbdff65eb5a84fe35e140f4da4f7cc103aJeff Garzik	rc = ata_pad_alloc(ap, dev);
8986037d6bbdff65eb5a84fe35e140f4da4f7cc103aJeff Garzik	if (rc)
8996037d6bbdff65eb5a84fe35e140f4da4f7cc103aJeff Garzik		goto err_out_priv;
9006037d6bbdff65eb5a84fe35e140f4da4f7cc103aJeff Garzik
9018b260248d9e0e8b64bb72fd4dee03ad86984c344Jeff Garzik	/* First item in chunk of DMA memory:
90231961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ	 * 32-slot command request table (CRQB), 32 bytes each in size
90331961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ	 */
90431961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ	pp->crqb = mem;
90531961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ	pp->crqb_dma = mem_dma;
90631961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ	mem += MV_CRQB_Q_SZ;
90731961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ	mem_dma += MV_CRQB_Q_SZ;
90831961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ
9098b260248d9e0e8b64bb72fd4dee03ad86984c344Jeff Garzik	/* Second item:
91031961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ	 * 32-slot command response table (CRPB), 8 bytes each in size
91131961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ	 */
91231961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ	pp->crpb = mem;
91331961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ	pp->crpb_dma = mem_dma;
91431961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ	mem += MV_CRPB_Q_SZ;
91531961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ	mem_dma += MV_CRPB_Q_SZ;
91631961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ
91731961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ	/* Third item:
91831961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ	 * Table of scatter-gather descriptors (ePRD), 16 bytes each
91931961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ	 */
92031961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ	pp->sg_tbl = mem;
92131961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ	pp->sg_tbl_dma = mem_dma;
92231961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ
923e4e7b89280d1d666e2c09e5ad36cf071796c4c7eJeff Garzik	mv_edma_cfg(hpriv, port_mmio);
92431961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ
92531961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ	writel((pp->crqb_dma >> 16) >> 16, port_mmio + EDMA_REQ_Q_BASE_HI_OFS);
9268b260248d9e0e8b64bb72fd4dee03ad86984c344Jeff Garzik	writelfl(pp->crqb_dma & EDMA_REQ_Q_BASE_LO_MASK,
92731961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ		 port_mmio + EDMA_REQ_Q_IN_PTR_OFS);
92831961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ
929e4e7b89280d1d666e2c09e5ad36cf071796c4c7eJeff Garzik	if (hpriv->hp_flags & MV_HP_ERRATA_XX42A0)
930e4e7b89280d1d666e2c09e5ad36cf071796c4c7eJeff Garzik		writelfl(pp->crqb_dma & 0xffffffff,
931e4e7b89280d1d666e2c09e5ad36cf071796c4c7eJeff Garzik			 port_mmio + EDMA_REQ_Q_OUT_PTR_OFS);
932e4e7b89280d1d666e2c09e5ad36cf071796c4c7eJeff Garzik	else
933e4e7b89280d1d666e2c09e5ad36cf071796c4c7eJeff Garzik		writelfl(0, port_mmio + EDMA_REQ_Q_OUT_PTR_OFS);
93431961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ
93531961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ	writel((pp->crpb_dma >> 16) >> 16, port_mmio + EDMA_RSP_Q_BASE_HI_OFS);
936e4e7b89280d1d666e2c09e5ad36cf071796c4c7eJeff Garzik
937e4e7b89280d1d666e2c09e5ad36cf071796c4c7eJeff Garzik	if (hpriv->hp_flags & MV_HP_ERRATA_XX42A0)
938e4e7b89280d1d666e2c09e5ad36cf071796c4c7eJeff Garzik		writelfl(pp->crpb_dma & 0xffffffff,
939e4e7b89280d1d666e2c09e5ad36cf071796c4c7eJeff Garzik			 port_mmio + EDMA_RSP_Q_IN_PTR_OFS);
940e4e7b89280d1d666e2c09e5ad36cf071796c4c7eJeff Garzik	else
941e4e7b89280d1d666e2c09e5ad36cf071796c4c7eJeff Garzik		writelfl(0, port_mmio + EDMA_RSP_Q_IN_PTR_OFS);
942e4e7b89280d1d666e2c09e5ad36cf071796c4c7eJeff Garzik
9438b260248d9e0e8b64bb72fd4dee03ad86984c344Jeff Garzik	writelfl(pp->crpb_dma & EDMA_RSP_Q_BASE_LO_MASK,
94431961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ		 port_mmio + EDMA_RSP_Q_OUT_PTR_OFS);
94531961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ
94631961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ	/* Don't turn on EDMA here...do it before DMA commands only.  Else
94731961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ	 * we'll be unable to send non-data, PIO, etc due to restricted access
94831961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ	 * to shadow regs.
94931961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ	 */
95031961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ	ap->private_data = pp;
95131961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ	return 0;
9526037d6bbdff65eb5a84fe35e140f4da4f7cc103aJeff Garzik
9536037d6bbdff65eb5a84fe35e140f4da4f7cc103aJeff Garzikerr_out_priv:
9546037d6bbdff65eb5a84fe35e140f4da4f7cc103aJeff Garzik	mv_priv_free(pp, dev);
9556037d6bbdff65eb5a84fe35e140f4da4f7cc103aJeff Garzikerr_out_pp:
9566037d6bbdff65eb5a84fe35e140f4da4f7cc103aJeff Garzik	kfree(pp);
9576037d6bbdff65eb5a84fe35e140f4da4f7cc103aJeff Garzikerr_out:
9586037d6bbdff65eb5a84fe35e140f4da4f7cc103aJeff Garzik	return rc;
95931961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ}
96031961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ
96105b308e1df6d9d673daedb517969241f41278b52Brett Russ/**
96205b308e1df6d9d673daedb517969241f41278b52Brett Russ *      mv_port_stop - Port specific cleanup/stop routine.
96305b308e1df6d9d673daedb517969241f41278b52Brett Russ *      @ap: ATA channel to manipulate
96405b308e1df6d9d673daedb517969241f41278b52Brett Russ *
96505b308e1df6d9d673daedb517969241f41278b52Brett Russ *      Stop DMA, cleanup port memory.
96605b308e1df6d9d673daedb517969241f41278b52Brett Russ *
96705b308e1df6d9d673daedb517969241f41278b52Brett Russ *      LOCKING:
968cca3974e48607c3775dc73b544a5700b2e37c21aJeff Garzik *      This routine uses the host lock to protect the DMA stop.
96905b308e1df6d9d673daedb517969241f41278b52Brett Russ */
97031961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russstatic void mv_port_stop(struct ata_port *ap)
97131961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ{
972cca3974e48607c3775dc73b544a5700b2e37c21aJeff Garzik	struct device *dev = ap->host->dev;
97331961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ	struct mv_port_priv *pp = ap->private_data;
974afb0edd922c7ed6e73678730921dfcccebec17e8Brett Russ	unsigned long flags;
97531961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ
976cca3974e48607c3775dc73b544a5700b2e37c21aJeff Garzik	spin_lock_irqsave(&ap->host->lock, flags);
97731961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ	mv_stop_dma(ap);
978cca3974e48607c3775dc73b544a5700b2e37c21aJeff Garzik	spin_unlock_irqrestore(&ap->host->lock, flags);
97931961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ
98031961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ	ap->private_data = NULL;
9816037d6bbdff65eb5a84fe35e140f4da4f7cc103aJeff Garzik	ata_pad_free(ap, dev);
9826037d6bbdff65eb5a84fe35e140f4da4f7cc103aJeff Garzik	mv_priv_free(pp, dev);
98331961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ	kfree(pp);
98431961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ}
98531961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ
98605b308e1df6d9d673daedb517969241f41278b52Brett Russ/**
98705b308e1df6d9d673daedb517969241f41278b52Brett Russ *      mv_fill_sg - Fill out the Marvell ePRD (scatter gather) entries
98805b308e1df6d9d673daedb517969241f41278b52Brett Russ *      @qc: queued command whose SG list to source from
98905b308e1df6d9d673daedb517969241f41278b52Brett Russ *
99005b308e1df6d9d673daedb517969241f41278b52Brett Russ *      Populate the SG list and mark the last entry.
99105b308e1df6d9d673daedb517969241f41278b52Brett Russ *
99205b308e1df6d9d673daedb517969241f41278b52Brett Russ *      LOCKING:
99305b308e1df6d9d673daedb517969241f41278b52Brett Russ *      Inherited from caller.
99405b308e1df6d9d673daedb517969241f41278b52Brett Russ */
99531961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russstatic void mv_fill_sg(struct ata_queued_cmd *qc)
99631961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ{
99731961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ	struct mv_port_priv *pp = qc->ap->private_data;
998972c26bdd6b58e7534473c4f7928584578cf43f4Jeff Garzik	unsigned int i = 0;
999972c26bdd6b58e7534473c4f7928584578cf43f4Jeff Garzik	struct scatterlist *sg;
100031961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ
1001972c26bdd6b58e7534473c4f7928584578cf43f4Jeff Garzik	ata_for_each_sg(sg, qc) {
100231961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ		dma_addr_t addr;
100322374677d18c5eeefd3a283431d312b8c44fef02Jeff Garzik		u32 sg_len, len, offset;
100431961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ
1005972c26bdd6b58e7534473c4f7928584578cf43f4Jeff Garzik		addr = sg_dma_address(sg);
1006972c26bdd6b58e7534473c4f7928584578cf43f4Jeff Garzik		sg_len = sg_dma_len(sg);
100731961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ
100822374677d18c5eeefd3a283431d312b8c44fef02Jeff Garzik		while (sg_len) {
100922374677d18c5eeefd3a283431d312b8c44fef02Jeff Garzik			offset = addr & MV_DMA_BOUNDARY;
101022374677d18c5eeefd3a283431d312b8c44fef02Jeff Garzik			len = sg_len;
101122374677d18c5eeefd3a283431d312b8c44fef02Jeff Garzik			if ((offset + sg_len) > 0x10000)
101222374677d18c5eeefd3a283431d312b8c44fef02Jeff Garzik				len = 0x10000 - offset;
1013972c26bdd6b58e7534473c4f7928584578cf43f4Jeff Garzik
101422374677d18c5eeefd3a283431d312b8c44fef02Jeff Garzik			pp->sg_tbl[i].addr = cpu_to_le32(addr & 0xffffffff);
101522374677d18c5eeefd3a283431d312b8c44fef02Jeff Garzik			pp->sg_tbl[i].addr_hi = cpu_to_le32((addr >> 16) >> 16);
101663af2a5c5990d95f1e7d8795f1425fb976ea2b4bMark Lord			pp->sg_tbl[i].flags_size = cpu_to_le32(len & 0xffff);
101722374677d18c5eeefd3a283431d312b8c44fef02Jeff Garzik
101822374677d18c5eeefd3a283431d312b8c44fef02Jeff Garzik			sg_len -= len;
101922374677d18c5eeefd3a283431d312b8c44fef02Jeff Garzik			addr += len;
102022374677d18c5eeefd3a283431d312b8c44fef02Jeff Garzik
102122374677d18c5eeefd3a283431d312b8c44fef02Jeff Garzik			if (!sg_len && ata_sg_is_last(sg, qc))
102222374677d18c5eeefd3a283431d312b8c44fef02Jeff Garzik				pp->sg_tbl[i].flags_size |= cpu_to_le32(EPRD_FLAG_END_OF_TBL);
102322374677d18c5eeefd3a283431d312b8c44fef02Jeff Garzik
102422374677d18c5eeefd3a283431d312b8c44fef02Jeff Garzik			i++;
102522374677d18c5eeefd3a283431d312b8c44fef02Jeff Garzik		}
102631961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ	}
102731961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ}
102831961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ
1029a6432436c5e14b416f27c8f87c5bf0bc36771f49Mark Lordstatic inline unsigned mv_inc_q_index(unsigned index)
103031961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ{
1031a6432436c5e14b416f27c8f87c5bf0bc36771f49Mark Lord	return (index + 1) & MV_MAX_Q_DEPTH_MASK;
103231961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ}
103331961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ
1034e14698745dd0de1ddbf5cd0cca4313a90f8c1cc1Mark Lordstatic inline void mv_crqb_pack_cmd(__le16 *cmdw, u8 data, u8 addr, unsigned last)
103531961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ{
1036559eedad7f7764dacca33980127b4615011230e4Mark Lord	u16 tmp = data | (addr << CRQB_CMD_ADDR_SHIFT) | CRQB_CMD_CS |
103731961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ		(last ? CRQB_CMD_LAST : 0);
1038559eedad7f7764dacca33980127b4615011230e4Mark Lord	*cmdw = cpu_to_le16(tmp);
103931961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ}
104031961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ
104105b308e1df6d9d673daedb517969241f41278b52Brett Russ/**
104205b308e1df6d9d673daedb517969241f41278b52Brett Russ *      mv_qc_prep - Host specific command preparation.
104305b308e1df6d9d673daedb517969241f41278b52Brett Russ *      @qc: queued command to prepare
104405b308e1df6d9d673daedb517969241f41278b52Brett Russ *
104505b308e1df6d9d673daedb517969241f41278b52Brett Russ *      This routine simply redirects to the general purpose routine
104605b308e1df6d9d673daedb517969241f41278b52Brett Russ *      if command is not DMA.  Else, it handles prep of the CRQB
104705b308e1df6d9d673daedb517969241f41278b52Brett Russ *      (command request block), does some sanity checking, and calls
104805b308e1df6d9d673daedb517969241f41278b52Brett Russ *      the SG load routine.
104905b308e1df6d9d673daedb517969241f41278b52Brett Russ *
105005b308e1df6d9d673daedb517969241f41278b52Brett Russ *      LOCKING:
105105b308e1df6d9d673daedb517969241f41278b52Brett Russ *      Inherited from caller.
105205b308e1df6d9d673daedb517969241f41278b52Brett Russ */
105331961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russstatic void mv_qc_prep(struct ata_queued_cmd *qc)
105431961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ{
105531961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ	struct ata_port *ap = qc->ap;
105631961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ	struct mv_port_priv *pp = ap->private_data;
1057e14698745dd0de1ddbf5cd0cca4313a90f8c1cc1Mark Lord	__le16 *cw;
105831961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ	struct ata_taskfile *tf;
105931961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ	u16 flags = 0;
1060a6432436c5e14b416f27c8f87c5bf0bc36771f49Mark Lord	unsigned in_index;
106131961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ
1062e4e7b89280d1d666e2c09e5ad36cf071796c4c7eJeff Garzik 	if (ATA_PROT_DMA != qc->tf.protocol)
106331961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ		return;
106420f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ
106531961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ	/* Fill in command request block
106631961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ	 */
1067e4e7b89280d1d666e2c09e5ad36cf071796c4c7eJeff Garzik	if (!(qc->tf.flags & ATA_TFLAG_WRITE))
106831961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ		flags |= CRQB_FLAG_READ;
1069beec7dbc6ff003bbc94de62b3323519c878fb2acTejun Heo	WARN_ON(MV_MAX_Q_DEPTH <= qc->tag);
107031961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ	flags |= qc->tag << CRQB_TAG_SHIFT;
107131961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ
1072a6432436c5e14b416f27c8f87c5bf0bc36771f49Mark Lord	/* get current queue index from hardware */
1073a6432436c5e14b416f27c8f87c5bf0bc36771f49Mark Lord	in_index = (readl(mv_ap_base(ap) + EDMA_REQ_Q_IN_PTR_OFS)
1074a6432436c5e14b416f27c8f87c5bf0bc36771f49Mark Lord			>> EDMA_REQ_Q_PTR_SHIFT) & MV_MAX_Q_DEPTH_MASK;
1075a6432436c5e14b416f27c8f87c5bf0bc36771f49Mark Lord
1076a6432436c5e14b416f27c8f87c5bf0bc36771f49Mark Lord	pp->crqb[in_index].sg_addr =
107731961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ		cpu_to_le32(pp->sg_tbl_dma & 0xffffffff);
1078a6432436c5e14b416f27c8f87c5bf0bc36771f49Mark Lord	pp->crqb[in_index].sg_addr_hi =
107931961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ		cpu_to_le32((pp->sg_tbl_dma >> 16) >> 16);
1080a6432436c5e14b416f27c8f87c5bf0bc36771f49Mark Lord	pp->crqb[in_index].ctrl_flags = cpu_to_le16(flags);
108131961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ
1082a6432436c5e14b416f27c8f87c5bf0bc36771f49Mark Lord	cw = &pp->crqb[in_index].ata_cmd[0];
108331961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ	tf = &qc->tf;
108431961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ
108531961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ	/* Sadly, the CRQB cannot accomodate all registers--there are
108631961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ	 * only 11 bytes...so we must pick and choose required
108731961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ	 * registers based on the command.  So, we drop feature and
108831961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ	 * hob_feature for [RW] DMA commands, but they are needed for
108931961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ	 * NCQ.  NCQ will drop hob_nsect.
109020f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ	 */
109131961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ	switch (tf->command) {
109231961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ	case ATA_CMD_READ:
109331961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ	case ATA_CMD_READ_EXT:
109431961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ	case ATA_CMD_WRITE:
109531961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ	case ATA_CMD_WRITE_EXT:
1096c15d85c8f3f73b5f20aae7928e25b6996f16b328Jens Axboe	case ATA_CMD_WRITE_FUA_EXT:
109731961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ		mv_crqb_pack_cmd(cw++, tf->hob_nsect, ATA_REG_NSECT, 0);
109831961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ		break;
109931961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ#ifdef LIBATA_NCQ		/* FIXME: remove this line when NCQ added */
110031961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ	case ATA_CMD_FPDMA_READ:
110131961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ	case ATA_CMD_FPDMA_WRITE:
11028b260248d9e0e8b64bb72fd4dee03ad86984c344Jeff Garzik		mv_crqb_pack_cmd(cw++, tf->hob_feature, ATA_REG_FEATURE, 0);
110331961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ		mv_crqb_pack_cmd(cw++, tf->feature, ATA_REG_FEATURE, 0);
110431961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ		break;
110531961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ#endif				/* FIXME: remove this line when NCQ added */
110631961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ	default:
110731961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ		/* The only other commands EDMA supports in non-queued and
110831961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ		 * non-NCQ mode are: [RW] STREAM DMA and W DMA FUA EXT, none
110931961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ		 * of which are defined/used by Linux.  If we get here, this
111031961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ		 * driver needs work.
111131961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ		 *
111231961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ		 * FIXME: modify libata to give qc_prep a return value and
111331961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ		 * return error here.
111431961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ		 */
111531961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ		BUG_ON(tf->command);
111631961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ		break;
111731961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ	}
111831961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ	mv_crqb_pack_cmd(cw++, tf->nsect, ATA_REG_NSECT, 0);
111931961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ	mv_crqb_pack_cmd(cw++, tf->hob_lbal, ATA_REG_LBAL, 0);
112031961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ	mv_crqb_pack_cmd(cw++, tf->lbal, ATA_REG_LBAL, 0);
112131961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ	mv_crqb_pack_cmd(cw++, tf->hob_lbam, ATA_REG_LBAM, 0);
112231961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ	mv_crqb_pack_cmd(cw++, tf->lbam, ATA_REG_LBAM, 0);
112331961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ	mv_crqb_pack_cmd(cw++, tf->hob_lbah, ATA_REG_LBAH, 0);
112431961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ	mv_crqb_pack_cmd(cw++, tf->lbah, ATA_REG_LBAH, 0);
112531961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ	mv_crqb_pack_cmd(cw++, tf->device, ATA_REG_DEVICE, 0);
112631961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ	mv_crqb_pack_cmd(cw++, tf->command, ATA_REG_CMD, 1);	/* last */
112731961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ
1128e4e7b89280d1d666e2c09e5ad36cf071796c4c7eJeff Garzik	if (!(qc->flags & ATA_QCFLAG_DMAMAP))
1129e4e7b89280d1d666e2c09e5ad36cf071796c4c7eJeff Garzik		return;
1130e4e7b89280d1d666e2c09e5ad36cf071796c4c7eJeff Garzik	mv_fill_sg(qc);
1131e4e7b89280d1d666e2c09e5ad36cf071796c4c7eJeff Garzik}
1132e4e7b89280d1d666e2c09e5ad36cf071796c4c7eJeff Garzik
1133e4e7b89280d1d666e2c09e5ad36cf071796c4c7eJeff Garzik/**
1134e4e7b89280d1d666e2c09e5ad36cf071796c4c7eJeff Garzik *      mv_qc_prep_iie - Host specific command preparation.
1135e4e7b89280d1d666e2c09e5ad36cf071796c4c7eJeff Garzik *      @qc: queued command to prepare
1136e4e7b89280d1d666e2c09e5ad36cf071796c4c7eJeff Garzik *
1137e4e7b89280d1d666e2c09e5ad36cf071796c4c7eJeff Garzik *      This routine simply redirects to the general purpose routine
1138e4e7b89280d1d666e2c09e5ad36cf071796c4c7eJeff Garzik *      if command is not DMA.  Else, it handles prep of the CRQB
1139e4e7b89280d1d666e2c09e5ad36cf071796c4c7eJeff Garzik *      (command request block), does some sanity checking, and calls
1140e4e7b89280d1d666e2c09e5ad36cf071796c4c7eJeff Garzik *      the SG load routine.
1141e4e7b89280d1d666e2c09e5ad36cf071796c4c7eJeff Garzik *
1142e4e7b89280d1d666e2c09e5ad36cf071796c4c7eJeff Garzik *      LOCKING:
1143e4e7b89280d1d666e2c09e5ad36cf071796c4c7eJeff Garzik *      Inherited from caller.
1144e4e7b89280d1d666e2c09e5ad36cf071796c4c7eJeff Garzik */
1145e4e7b89280d1d666e2c09e5ad36cf071796c4c7eJeff Garzikstatic void mv_qc_prep_iie(struct ata_queued_cmd *qc)
1146e4e7b89280d1d666e2c09e5ad36cf071796c4c7eJeff Garzik{
1147e4e7b89280d1d666e2c09e5ad36cf071796c4c7eJeff Garzik	struct ata_port *ap = qc->ap;
1148e4e7b89280d1d666e2c09e5ad36cf071796c4c7eJeff Garzik	struct mv_port_priv *pp = ap->private_data;
1149e4e7b89280d1d666e2c09e5ad36cf071796c4c7eJeff Garzik	struct mv_crqb_iie *crqb;
1150e4e7b89280d1d666e2c09e5ad36cf071796c4c7eJeff Garzik	struct ata_taskfile *tf;
1151a6432436c5e14b416f27c8f87c5bf0bc36771f49Mark Lord	unsigned in_index;
1152e4e7b89280d1d666e2c09e5ad36cf071796c4c7eJeff Garzik	u32 flags = 0;
1153e4e7b89280d1d666e2c09e5ad36cf071796c4c7eJeff Garzik
1154e4e7b89280d1d666e2c09e5ad36cf071796c4c7eJeff Garzik 	if (ATA_PROT_DMA != qc->tf.protocol)
1155e4e7b89280d1d666e2c09e5ad36cf071796c4c7eJeff Garzik		return;
1156e4e7b89280d1d666e2c09e5ad36cf071796c4c7eJeff Garzik
1157e4e7b89280d1d666e2c09e5ad36cf071796c4c7eJeff Garzik	/* Fill in Gen IIE command request block
1158e4e7b89280d1d666e2c09e5ad36cf071796c4c7eJeff Garzik	 */
1159e4e7b89280d1d666e2c09e5ad36cf071796c4c7eJeff Garzik	if (!(qc->tf.flags & ATA_TFLAG_WRITE))
1160e4e7b89280d1d666e2c09e5ad36cf071796c4c7eJeff Garzik		flags |= CRQB_FLAG_READ;
1161e4e7b89280d1d666e2c09e5ad36cf071796c4c7eJeff Garzik
1162beec7dbc6ff003bbc94de62b3323519c878fb2acTejun Heo	WARN_ON(MV_MAX_Q_DEPTH <= qc->tag);
1163e4e7b89280d1d666e2c09e5ad36cf071796c4c7eJeff Garzik	flags |= qc->tag << CRQB_TAG_SHIFT;
1164e4e7b89280d1d666e2c09e5ad36cf071796c4c7eJeff Garzik
1165a6432436c5e14b416f27c8f87c5bf0bc36771f49Mark Lord	/* get current queue index from hardware */
1166a6432436c5e14b416f27c8f87c5bf0bc36771f49Mark Lord	in_index = (readl(mv_ap_base(ap) + EDMA_REQ_Q_IN_PTR_OFS)
1167a6432436c5e14b416f27c8f87c5bf0bc36771f49Mark Lord			>> EDMA_REQ_Q_PTR_SHIFT) & MV_MAX_Q_DEPTH_MASK;
1168a6432436c5e14b416f27c8f87c5bf0bc36771f49Mark Lord
1169a6432436c5e14b416f27c8f87c5bf0bc36771f49Mark Lord	crqb = (struct mv_crqb_iie *) &pp->crqb[in_index];
1170e4e7b89280d1d666e2c09e5ad36cf071796c4c7eJeff Garzik	crqb->addr = cpu_to_le32(pp->sg_tbl_dma & 0xffffffff);
1171e4e7b89280d1d666e2c09e5ad36cf071796c4c7eJeff Garzik	crqb->addr_hi = cpu_to_le32((pp->sg_tbl_dma >> 16) >> 16);
1172e4e7b89280d1d666e2c09e5ad36cf071796c4c7eJeff Garzik	crqb->flags = cpu_to_le32(flags);
1173e4e7b89280d1d666e2c09e5ad36cf071796c4c7eJeff Garzik
1174e4e7b89280d1d666e2c09e5ad36cf071796c4c7eJeff Garzik	tf = &qc->tf;
1175e4e7b89280d1d666e2c09e5ad36cf071796c4c7eJeff Garzik	crqb->ata_cmd[0] = cpu_to_le32(
1176e4e7b89280d1d666e2c09e5ad36cf071796c4c7eJeff Garzik			(tf->command << 16) |
1177e4e7b89280d1d666e2c09e5ad36cf071796c4c7eJeff Garzik			(tf->feature << 24)
1178e4e7b89280d1d666e2c09e5ad36cf071796c4c7eJeff Garzik		);
1179e4e7b89280d1d666e2c09e5ad36cf071796c4c7eJeff Garzik	crqb->ata_cmd[1] = cpu_to_le32(
1180e4e7b89280d1d666e2c09e5ad36cf071796c4c7eJeff Garzik			(tf->lbal << 0) |
1181e4e7b89280d1d666e2c09e5ad36cf071796c4c7eJeff Garzik			(tf->lbam << 8) |
1182e4e7b89280d1d666e2c09e5ad36cf071796c4c7eJeff Garzik			(tf->lbah << 16) |
1183e4e7b89280d1d666e2c09e5ad36cf071796c4c7eJeff Garzik			(tf->device << 24)
1184e4e7b89280d1d666e2c09e5ad36cf071796c4c7eJeff Garzik		);
1185e4e7b89280d1d666e2c09e5ad36cf071796c4c7eJeff Garzik	crqb->ata_cmd[2] = cpu_to_le32(
1186e4e7b89280d1d666e2c09e5ad36cf071796c4c7eJeff Garzik			(tf->hob_lbal << 0) |
1187e4e7b89280d1d666e2c09e5ad36cf071796c4c7eJeff Garzik			(tf->hob_lbam << 8) |
1188e4e7b89280d1d666e2c09e5ad36cf071796c4c7eJeff Garzik			(tf->hob_lbah << 16) |
1189e4e7b89280d1d666e2c09e5ad36cf071796c4c7eJeff Garzik			(tf->hob_feature << 24)
1190e4e7b89280d1d666e2c09e5ad36cf071796c4c7eJeff Garzik		);
1191e4e7b89280d1d666e2c09e5ad36cf071796c4c7eJeff Garzik	crqb->ata_cmd[3] = cpu_to_le32(
1192e4e7b89280d1d666e2c09e5ad36cf071796c4c7eJeff Garzik			(tf->nsect << 0) |
1193e4e7b89280d1d666e2c09e5ad36cf071796c4c7eJeff Garzik			(tf->hob_nsect << 8)
1194e4e7b89280d1d666e2c09e5ad36cf071796c4c7eJeff Garzik		);
1195e4e7b89280d1d666e2c09e5ad36cf071796c4c7eJeff Garzik
1196e4e7b89280d1d666e2c09e5ad36cf071796c4c7eJeff Garzik	if (!(qc->flags & ATA_QCFLAG_DMAMAP))
119731961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ		return;
119831961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ	mv_fill_sg(qc);
119931961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ}
120031961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ
120105b308e1df6d9d673daedb517969241f41278b52Brett Russ/**
120205b308e1df6d9d673daedb517969241f41278b52Brett Russ *      mv_qc_issue - Initiate a command to the host
120305b308e1df6d9d673daedb517969241f41278b52Brett Russ *      @qc: queued command to start
120405b308e1df6d9d673daedb517969241f41278b52Brett Russ *
120505b308e1df6d9d673daedb517969241f41278b52Brett Russ *      This routine simply redirects to the general purpose routine
120605b308e1df6d9d673daedb517969241f41278b52Brett Russ *      if command is not DMA.  Else, it sanity checks our local
120705b308e1df6d9d673daedb517969241f41278b52Brett Russ *      caches of the request producer/consumer indices then enables
120805b308e1df6d9d673daedb517969241f41278b52Brett Russ *      DMA and bumps the request producer index.
120905b308e1df6d9d673daedb517969241f41278b52Brett Russ *
121005b308e1df6d9d673daedb517969241f41278b52Brett Russ *      LOCKING:
121105b308e1df6d9d673daedb517969241f41278b52Brett Russ *      Inherited from caller.
121205b308e1df6d9d673daedb517969241f41278b52Brett Russ */
12139a3d9eb0177eb10500d49cd283b35576082a522dTejun Heostatic unsigned int mv_qc_issue(struct ata_queued_cmd *qc)
121431961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ{
121531961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ	void __iomem *port_mmio = mv_ap_base(qc->ap);
121631961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ	struct mv_port_priv *pp = qc->ap->private_data;
1217a6432436c5e14b416f27c8f87c5bf0bc36771f49Mark Lord	unsigned in_index;
121831961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ	u32 in_ptr;
121931961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ
122031961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ	if (ATA_PROT_DMA != qc->tf.protocol) {
122131961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ		/* We're about to send a non-EDMA capable command to the
122231961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ		 * port.  Turn off EDMA so there won't be problems accessing
122331961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ		 * shadow block, etc registers.
122431961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ		 */
122531961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ		mv_stop_dma(qc->ap);
122631961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ		return ata_qc_issue_prot(qc);
122731961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ	}
122831961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ
1229a6432436c5e14b416f27c8f87c5bf0bc36771f49Mark Lord	in_ptr   = readl(port_mmio + EDMA_REQ_Q_IN_PTR_OFS);
1230a6432436c5e14b416f27c8f87c5bf0bc36771f49Mark Lord	in_index = (in_ptr >> EDMA_REQ_Q_PTR_SHIFT) & MV_MAX_Q_DEPTH_MASK;
123131961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ
123231961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ	/* until we do queuing, the queue should be empty at this point */
1233a6432436c5e14b416f27c8f87c5bf0bc36771f49Mark Lord	WARN_ON(in_index != ((readl(port_mmio + EDMA_REQ_Q_OUT_PTR_OFS)
1234a6432436c5e14b416f27c8f87c5bf0bc36771f49Mark Lord		>> EDMA_REQ_Q_PTR_SHIFT) & MV_MAX_Q_DEPTH_MASK));
123531961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ
1236a6432436c5e14b416f27c8f87c5bf0bc36771f49Mark Lord	in_index = mv_inc_q_index(in_index);	/* now incr producer index */
123731961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ
1238afb0edd922c7ed6e73678730921dfcccebec17e8Brett Russ	mv_start_dma(port_mmio, pp);
123931961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ
124031961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ	/* and write the request in pointer to kick the EDMA to life */
124131961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ	in_ptr &= EDMA_REQ_Q_BASE_LO_MASK;
1242a6432436c5e14b416f27c8f87c5bf0bc36771f49Mark Lord	in_ptr |= in_index << EDMA_REQ_Q_PTR_SHIFT;
124331961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ	writelfl(in_ptr, port_mmio + EDMA_REQ_Q_IN_PTR_OFS);
124431961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ
124531961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ	return 0;
124631961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ}
124731961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ
124805b308e1df6d9d673daedb517969241f41278b52Brett Russ/**
124905b308e1df6d9d673daedb517969241f41278b52Brett Russ *      mv_get_crpb_status - get status from most recently completed cmd
125005b308e1df6d9d673daedb517969241f41278b52Brett Russ *      @ap: ATA channel to manipulate
125105b308e1df6d9d673daedb517969241f41278b52Brett Russ *
125205b308e1df6d9d673daedb517969241f41278b52Brett Russ *      This routine is for use when the port is in DMA mode, when it
125305b308e1df6d9d673daedb517969241f41278b52Brett Russ *      will be using the CRPB (command response block) method of
1254beec7dbc6ff003bbc94de62b3323519c878fb2acTejun Heo *      returning command completion information.  We check indices
125505b308e1df6d9d673daedb517969241f41278b52Brett Russ *      are good, grab status, and bump the response consumer index to
125605b308e1df6d9d673daedb517969241f41278b52Brett Russ *      prove that we're up to date.
125705b308e1df6d9d673daedb517969241f41278b52Brett Russ *
125805b308e1df6d9d673daedb517969241f41278b52Brett Russ *      LOCKING:
125905b308e1df6d9d673daedb517969241f41278b52Brett Russ *      Inherited from caller.
126005b308e1df6d9d673daedb517969241f41278b52Brett Russ */
126131961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russstatic u8 mv_get_crpb_status(struct ata_port *ap)
126231961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ{
126331961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ	void __iomem *port_mmio = mv_ap_base(ap);
126431961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ	struct mv_port_priv *pp = ap->private_data;
1265a6432436c5e14b416f27c8f87c5bf0bc36771f49Mark Lord	unsigned out_index;
126631961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ	u32 out_ptr;
1267806a6e7a9904d4a1dfd3fd79d373bf31d71d34cbMark Lord	u8 ata_status;
126831961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ
1269a6432436c5e14b416f27c8f87c5bf0bc36771f49Mark Lord	out_ptr   = readl(port_mmio + EDMA_RSP_Q_OUT_PTR_OFS);
1270a6432436c5e14b416f27c8f87c5bf0bc36771f49Mark Lord	out_index = (out_ptr >> EDMA_RSP_Q_PTR_SHIFT) & MV_MAX_Q_DEPTH_MASK;
127131961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ
1272a6432436c5e14b416f27c8f87c5bf0bc36771f49Mark Lord	ata_status = le16_to_cpu(pp->crpb[out_index].flags)
1273a6432436c5e14b416f27c8f87c5bf0bc36771f49Mark Lord					>> CRPB_FLAG_STATUS_SHIFT;
1274806a6e7a9904d4a1dfd3fd79d373bf31d71d34cbMark Lord
127531961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ	/* increment our consumer index... */
1276a6432436c5e14b416f27c8f87c5bf0bc36771f49Mark Lord	out_index = mv_inc_q_index(out_index);
12778b260248d9e0e8b64bb72fd4dee03ad86984c344Jeff Garzik
127831961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ	/* and, until we do NCQ, there should only be 1 CRPB waiting */
1279a6432436c5e14b416f27c8f87c5bf0bc36771f49Mark Lord	WARN_ON(out_index != ((readl(port_mmio + EDMA_RSP_Q_IN_PTR_OFS)
1280a6432436c5e14b416f27c8f87c5bf0bc36771f49Mark Lord		>> EDMA_RSP_Q_PTR_SHIFT) & MV_MAX_Q_DEPTH_MASK));
128131961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ
128231961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ	/* write out our inc'd consumer index so EDMA knows we're caught up */
128331961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ	out_ptr &= EDMA_RSP_Q_BASE_LO_MASK;
1284a6432436c5e14b416f27c8f87c5bf0bc36771f49Mark Lord	out_ptr |= out_index << EDMA_RSP_Q_PTR_SHIFT;
128531961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ	writelfl(out_ptr, port_mmio + EDMA_RSP_Q_OUT_PTR_OFS);
128631961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ
128731961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ	/* Return ATA status register for completed CRPB */
1288806a6e7a9904d4a1dfd3fd79d373bf31d71d34cbMark Lord	return ata_status;
128931961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ}
129031961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ
129105b308e1df6d9d673daedb517969241f41278b52Brett Russ/**
129205b308e1df6d9d673daedb517969241f41278b52Brett Russ *      mv_err_intr - Handle error interrupts on the port
129305b308e1df6d9d673daedb517969241f41278b52Brett Russ *      @ap: ATA channel to manipulate
12949b358e305c1d783c8a4ebf00344e95deb9e38f3dMark Lord *      @reset_allowed: bool: 0 == don't trigger from reset here
129505b308e1df6d9d673daedb517969241f41278b52Brett Russ *
129605b308e1df6d9d673daedb517969241f41278b52Brett Russ *      In most cases, just clear the interrupt and move on.  However,
129705b308e1df6d9d673daedb517969241f41278b52Brett Russ *      some cases require an eDMA reset, which is done right before
129805b308e1df6d9d673daedb517969241f41278b52Brett Russ *      the COMRESET in mv_phy_reset().  The SERR case requires a
129905b308e1df6d9d673daedb517969241f41278b52Brett Russ *      clear of pending errors in the SATA SERROR register.  Finally,
130005b308e1df6d9d673daedb517969241f41278b52Brett Russ *      if the port disabled DMA, update our cached copy to match.
130105b308e1df6d9d673daedb517969241f41278b52Brett Russ *
130205b308e1df6d9d673daedb517969241f41278b52Brett Russ *      LOCKING:
130305b308e1df6d9d673daedb517969241f41278b52Brett Russ *      Inherited from caller.
130405b308e1df6d9d673daedb517969241f41278b52Brett Russ */
13059b358e305c1d783c8a4ebf00344e95deb9e38f3dMark Lordstatic void mv_err_intr(struct ata_port *ap, int reset_allowed)
130631961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ{
130731961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ	void __iomem *port_mmio = mv_ap_base(ap);
130831961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ	u32 edma_err_cause, serr = 0;
130920f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ
131020f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ	edma_err_cause = readl(port_mmio + EDMA_ERR_IRQ_CAUSE_OFS);
131120f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ
131220f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ	if (EDMA_ERR_SERR & edma_err_cause) {
131381952c5497b40ae56835bd0d6537f8c6bdea07e7Tejun Heo		sata_scr_read(ap, SCR_ERROR, &serr);
131481952c5497b40ae56835bd0d6537f8c6bdea07e7Tejun Heo		sata_scr_write_flush(ap, SCR_ERROR, serr);
131520f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ	}
1316afb0edd922c7ed6e73678730921dfcccebec17e8Brett Russ	if (EDMA_ERR_SELF_DIS & edma_err_cause) {
1317afb0edd922c7ed6e73678730921dfcccebec17e8Brett Russ		struct mv_port_priv *pp	= ap->private_data;
1318afb0edd922c7ed6e73678730921dfcccebec17e8Brett Russ		pp->pp_flags &= ~MV_PP_FLAG_EDMA_EN;
1319afb0edd922c7ed6e73678730921dfcccebec17e8Brett Russ	}
1320afb0edd922c7ed6e73678730921dfcccebec17e8Brett Russ	DPRINTK(KERN_ERR "ata%u: port error; EDMA err cause: 0x%08x "
1321afb0edd922c7ed6e73678730921dfcccebec17e8Brett Russ		"SERR: 0x%08x\n", ap->id, edma_err_cause, serr);
132220f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ
132320f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ	/* Clear EDMA now that SERR cleanup done */
132420f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ	writelfl(0, port_mmio + EDMA_ERR_IRQ_CAUSE_OFS);
132520f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ
132620f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ	/* check for fatal here and recover if needed */
13279b358e305c1d783c8a4ebf00344e95deb9e38f3dMark Lord	if (reset_allowed && (EDMA_ERR_FATAL & edma_err_cause))
1328c9d39130123238ac18478a42e25cb7996eacfcc0Jeff Garzik		mv_stop_and_reset(ap);
132920f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ}
133020f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ
133105b308e1df6d9d673daedb517969241f41278b52Brett Russ/**
133205b308e1df6d9d673daedb517969241f41278b52Brett Russ *      mv_host_intr - Handle all interrupts on the given host controller
1333cca3974e48607c3775dc73b544a5700b2e37c21aJeff Garzik *      @host: host specific structure
133405b308e1df6d9d673daedb517969241f41278b52Brett Russ *      @relevant: port error bits relevant to this host controller
133505b308e1df6d9d673daedb517969241f41278b52Brett Russ *      @hc: which host controller we're to look at
133605b308e1df6d9d673daedb517969241f41278b52Brett Russ *
133705b308e1df6d9d673daedb517969241f41278b52Brett Russ *      Read then write clear the HC interrupt status then walk each
133805b308e1df6d9d673daedb517969241f41278b52Brett Russ *      port connected to the HC and see if it needs servicing.  Port
133905b308e1df6d9d673daedb517969241f41278b52Brett Russ *      success ints are reported in the HC interrupt status reg, the
134005b308e1df6d9d673daedb517969241f41278b52Brett Russ *      port error ints are reported in the higher level main
134105b308e1df6d9d673daedb517969241f41278b52Brett Russ *      interrupt status register and thus are passed in via the
134205b308e1df6d9d673daedb517969241f41278b52Brett Russ *      'relevant' argument.
134305b308e1df6d9d673daedb517969241f41278b52Brett Russ *
134405b308e1df6d9d673daedb517969241f41278b52Brett Russ *      LOCKING:
134505b308e1df6d9d673daedb517969241f41278b52Brett Russ *      Inherited from caller.
134605b308e1df6d9d673daedb517969241f41278b52Brett Russ */
1347cca3974e48607c3775dc73b544a5700b2e37c21aJeff Garzikstatic void mv_host_intr(struct ata_host *host, u32 relevant, unsigned int hc)
134820f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ{
1349cca3974e48607c3775dc73b544a5700b2e37c21aJeff Garzik	void __iomem *mmio = host->mmio_base;
135020f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ	void __iomem *hc_mmio = mv_hc_base(mmio, hc);
135120f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ	struct ata_queued_cmd *qc;
135220f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ	u32 hc_irq_cause;
135331961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ	int shift, port, port0, hard_port, handled;
1354a7dac447bb9cef27d4d29cdf63e2d7809c50b1f4Jeff Garzik	unsigned int err_mask;
135520f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ
135620f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ	if (hc == 0) {
135720f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ		port0 = 0;
135820f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ	} else {
135920f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ		port0 = MV_PORTS_PER_HC;
136020f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ	}
136120f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ
136220f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ	/* we'll need the HC success int register in most cases */
136320f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ	hc_irq_cause = readl(hc_mmio + HC_IRQ_CAUSE_OFS);
136420f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ	if (hc_irq_cause) {
136531961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ		writelfl(~hc_irq_cause, hc_mmio + HC_IRQ_CAUSE_OFS);
136620f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ	}
136720f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ
136820f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ	VPRINTK("ENTER, hc%u relevant=0x%08x HC IRQ cause=0x%08x\n",
136920f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ		hc,relevant,hc_irq_cause);
137020f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ
137120f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ	for (port = port0; port < port0 + MV_PORTS_PER_HC; port++) {
1372cd85f6e2f58282186ad720fc18482be228f0b972Jeff Garzik		u8 ata_status = 0;
1373cca3974e48607c3775dc73b544a5700b2e37c21aJeff Garzik		struct ata_port *ap = host->ports[port];
137463af2a5c5990d95f1e7d8795f1425fb976ea2b4bMark Lord		struct mv_port_priv *pp = ap->private_data;
137555d8ca4f8094246da6e71889a4e04bfafaa78b10Jeff Garzik
1376e857f141945f29c16f72ffcfdbce097f8be6c4e9Mark Lord		hard_port = mv_hardport_from_port(port); /* range 0..3 */
137731961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ		handled = 0;	/* ensure ata_status is set if handled++ */
137820f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ
137963af2a5c5990d95f1e7d8795f1425fb976ea2b4bMark Lord		/* Note that DEV_IRQ might happen spuriously during EDMA,
1380e857f141945f29c16f72ffcfdbce097f8be6c4e9Mark Lord		 * and should be ignored in such cases.
1381e857f141945f29c16f72ffcfdbce097f8be6c4e9Mark Lord		 * The cause of this is still under investigation.
13828190bdb9291758f3b8c436ec1154c9923ddb57eaJeff Garzik		 */
138363af2a5c5990d95f1e7d8795f1425fb976ea2b4bMark Lord		if (pp->pp_flags & MV_PP_FLAG_EDMA_EN) {
138463af2a5c5990d95f1e7d8795f1425fb976ea2b4bMark Lord			/* EDMA: check for response queue interrupt */
138563af2a5c5990d95f1e7d8795f1425fb976ea2b4bMark Lord			if ((CRPB_DMA_DONE << hard_port) & hc_irq_cause) {
138663af2a5c5990d95f1e7d8795f1425fb976ea2b4bMark Lord				ata_status = mv_get_crpb_status(ap);
138763af2a5c5990d95f1e7d8795f1425fb976ea2b4bMark Lord				handled = 1;
138863af2a5c5990d95f1e7d8795f1425fb976ea2b4bMark Lord			}
138963af2a5c5990d95f1e7d8795f1425fb976ea2b4bMark Lord		} else {
139063af2a5c5990d95f1e7d8795f1425fb976ea2b4bMark Lord			/* PIO: check for device (drive) interrupt */
139163af2a5c5990d95f1e7d8795f1425fb976ea2b4bMark Lord			if ((DEV_IRQ << hard_port) & hc_irq_cause) {
139263af2a5c5990d95f1e7d8795f1425fb976ea2b4bMark Lord				ata_status = readb((void __iomem *)
139320f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ					   ap->ioaddr.status_addr);
139463af2a5c5990d95f1e7d8795f1425fb976ea2b4bMark Lord				handled = 1;
1395e857f141945f29c16f72ffcfdbce097f8be6c4e9Mark Lord				/* ignore spurious intr if drive still BUSY */
1396e857f141945f29c16f72ffcfdbce097f8be6c4e9Mark Lord				if (ata_status & ATA_BUSY) {
1397e857f141945f29c16f72ffcfdbce097f8be6c4e9Mark Lord					ata_status = 0;
1398e857f141945f29c16f72ffcfdbce097f8be6c4e9Mark Lord					handled = 0;
1399e857f141945f29c16f72ffcfdbce097f8be6c4e9Mark Lord				}
140063af2a5c5990d95f1e7d8795f1425fb976ea2b4bMark Lord			}
140120f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ		}
140220f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ
1403029f5468b5b5f93a09bf90326fdcb9124079658dJeff Garzik		if (ap && (ap->flags & ATA_FLAG_DISABLED))
1404a2c91a8819e315e9fd1aef3ff57badb6c1be3f80Jeff Garzik			continue;
1405a2c91a8819e315e9fd1aef3ff57badb6c1be3f80Jeff Garzik
1406a7dac447bb9cef27d4d29cdf63e2d7809c50b1f4Jeff Garzik		err_mask = ac_err_mask(ata_status);
1407a7dac447bb9cef27d4d29cdf63e2d7809c50b1f4Jeff Garzik
140831961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ		shift = port << 1;		/* (port * 2) */
140920f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ		if (port >= MV_PORTS_PER_HC) {
141020f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ			shift++;	/* skip bit 8 in the HC Main IRQ reg */
141120f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ		}
141220f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ		if ((PORT0_ERR << shift) & relevant) {
14139b358e305c1d783c8a4ebf00344e95deb9e38f3dMark Lord			mv_err_intr(ap, 1);
1414a7dac447bb9cef27d4d29cdf63e2d7809c50b1f4Jeff Garzik			err_mask |= AC_ERR_OTHER;
141563af2a5c5990d95f1e7d8795f1425fb976ea2b4bMark Lord			handled = 1;
141620f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ		}
14178b260248d9e0e8b64bb72fd4dee03ad86984c344Jeff Garzik
141863af2a5c5990d95f1e7d8795f1425fb976ea2b4bMark Lord		if (handled) {
141920f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ			qc = ata_qc_from_tag(ap, ap->active_tag);
142063af2a5c5990d95f1e7d8795f1425fb976ea2b4bMark Lord			if (qc && (qc->flags & ATA_QCFLAG_ACTIVE)) {
142120f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ				VPRINTK("port %u IRQ found for qc, "
142220f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ					"ata_status 0x%x\n", port,ata_status);
142320f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ				/* mark qc status appropriately */
1424701db69d6647f61e4660c9102d7f2fd5dffc203dJeff Garzik				if (!(qc->tf.flags & ATA_TFLAG_POLLING)) {
1425a22e2eb0710798009b8e696ae911aef745089dd6Albert Lee					qc->err_mask |= err_mask;
1426a22e2eb0710798009b8e696ae911aef745089dd6Albert Lee					ata_qc_complete(qc);
1427a22e2eb0710798009b8e696ae911aef745089dd6Albert Lee				}
142820f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ			}
142920f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ		}
143020f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ	}
143120f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ	VPRINTK("EXIT\n");
143220f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ}
143320f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ
143405b308e1df6d9d673daedb517969241f41278b52Brett Russ/**
14358b260248d9e0e8b64bb72fd4dee03ad86984c344Jeff Garzik *      mv_interrupt -
143605b308e1df6d9d673daedb517969241f41278b52Brett Russ *      @irq: unused
143705b308e1df6d9d673daedb517969241f41278b52Brett Russ *      @dev_instance: private data; in this case the host structure
143805b308e1df6d9d673daedb517969241f41278b52Brett Russ *      @regs: unused
143905b308e1df6d9d673daedb517969241f41278b52Brett Russ *
144005b308e1df6d9d673daedb517969241f41278b52Brett Russ *      Read the read only register to determine if any host
144105b308e1df6d9d673daedb517969241f41278b52Brett Russ *      controllers have pending interrupts.  If so, call lower level
144205b308e1df6d9d673daedb517969241f41278b52Brett Russ *      routine to handle.  Also check for PCI errors which are only
144305b308e1df6d9d673daedb517969241f41278b52Brett Russ *      reported here.
144405b308e1df6d9d673daedb517969241f41278b52Brett Russ *
14458b260248d9e0e8b64bb72fd4dee03ad86984c344Jeff Garzik *      LOCKING:
1446cca3974e48607c3775dc73b544a5700b2e37c21aJeff Garzik *      This routine holds the host lock while processing pending
144705b308e1df6d9d673daedb517969241f41278b52Brett Russ *      interrupts.
144805b308e1df6d9d673daedb517969241f41278b52Brett Russ */
144920f733e7d75a16bffc34842b7682c9247dd5f954Brett Russstatic irqreturn_t mv_interrupt(int irq, void *dev_instance,
145020f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ				struct pt_regs *regs)
145120f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ{
1452cca3974e48607c3775dc73b544a5700b2e37c21aJeff Garzik	struct ata_host *host = dev_instance;
145320f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ	unsigned int hc, handled = 0, n_hcs;
1454cca3974e48607c3775dc73b544a5700b2e37c21aJeff Garzik	void __iomem *mmio = host->mmio_base;
1455615ab95342f6245026d8974b9724f7ea57d9a184Mark Lord	struct mv_host_priv *hpriv;
145620f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ	u32 irq_stat;
145720f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ
145820f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ	irq_stat = readl(mmio + HC_MAIN_IRQ_CAUSE_OFS);
145920f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ
146020f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ	/* check the cases where we either have nothing pending or have read
146120f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ	 * a bogus register value which can indicate HW removal or PCI fault
146220f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ	 */
146320f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ	if (!irq_stat || (0xffffffffU == irq_stat)) {
146420f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ		return IRQ_NONE;
146520f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ	}
146620f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ
1467cca3974e48607c3775dc73b544a5700b2e37c21aJeff Garzik	n_hcs = mv_get_hc_count(host->ports[0]->flags);
1468cca3974e48607c3775dc73b544a5700b2e37c21aJeff Garzik	spin_lock(&host->lock);
146920f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ
147020f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ	for (hc = 0; hc < n_hcs; hc++) {
147120f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ		u32 relevant = irq_stat & (HC0_IRQ_PEND << (hc * HC_SHIFT));
147220f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ		if (relevant) {
1473cca3974e48607c3775dc73b544a5700b2e37c21aJeff Garzik			mv_host_intr(host, relevant, hc);
147431961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ			handled++;
147520f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ		}
147620f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ	}
1477615ab95342f6245026d8974b9724f7ea57d9a184Mark Lord
1478cca3974e48607c3775dc73b544a5700b2e37c21aJeff Garzik	hpriv = host->private_data;
1479615ab95342f6245026d8974b9724f7ea57d9a184Mark Lord	if (IS_60XX(hpriv)) {
1480615ab95342f6245026d8974b9724f7ea57d9a184Mark Lord		/* deal with the interrupt coalescing bits */
1481615ab95342f6245026d8974b9724f7ea57d9a184Mark Lord		if (irq_stat & (TRAN_LO_DONE | TRAN_HI_DONE | PORTS_0_7_COAL_DONE)) {
1482615ab95342f6245026d8974b9724f7ea57d9a184Mark Lord			writelfl(0, mmio + MV_IRQ_COAL_CAUSE_LO);
1483615ab95342f6245026d8974b9724f7ea57d9a184Mark Lord			writelfl(0, mmio + MV_IRQ_COAL_CAUSE_HI);
1484615ab95342f6245026d8974b9724f7ea57d9a184Mark Lord			writelfl(0, mmio + MV_IRQ_COAL_CAUSE);
1485615ab95342f6245026d8974b9724f7ea57d9a184Mark Lord		}
1486615ab95342f6245026d8974b9724f7ea57d9a184Mark Lord	}
1487615ab95342f6245026d8974b9724f7ea57d9a184Mark Lord
148820f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ	if (PCI_ERR & irq_stat) {
148931961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ		printk(KERN_ERR DRV_NAME ": PCI ERROR; PCI IRQ cause=0x%08x\n",
149031961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ		       readl(mmio + PCI_IRQ_CAUSE_OFS));
149131961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ
1492afb0edd922c7ed6e73678730921dfcccebec17e8Brett Russ		DPRINTK("All regs @ PCI error\n");
1493cca3974e48607c3775dc73b544a5700b2e37c21aJeff Garzik		mv_dump_all_regs(mmio, -1, to_pci_dev(host->dev));
149420f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ
149531961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ		writelfl(0, mmio + PCI_IRQ_CAUSE_OFS);
149631961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ		handled++;
149731961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ	}
1498cca3974e48607c3775dc73b544a5700b2e37c21aJeff Garzik	spin_unlock(&host->lock);
149920f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ
150020f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ	return IRQ_RETVAL(handled);
150120f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ}
150220f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ
1503c9d39130123238ac18478a42e25cb7996eacfcc0Jeff Garzikstatic void __iomem *mv5_phy_base(void __iomem *mmio, unsigned int port)
1504c9d39130123238ac18478a42e25cb7996eacfcc0Jeff Garzik{
1505c9d39130123238ac18478a42e25cb7996eacfcc0Jeff Garzik	void __iomem *hc_mmio = mv_hc_base_from_port(mmio, port);
1506c9d39130123238ac18478a42e25cb7996eacfcc0Jeff Garzik	unsigned long ofs = (mv_hardport_from_port(port) + 1) * 0x100UL;
1507c9d39130123238ac18478a42e25cb7996eacfcc0Jeff Garzik
1508c9d39130123238ac18478a42e25cb7996eacfcc0Jeff Garzik	return hc_mmio + ofs;
1509c9d39130123238ac18478a42e25cb7996eacfcc0Jeff Garzik}
1510c9d39130123238ac18478a42e25cb7996eacfcc0Jeff Garzik
1511c9d39130123238ac18478a42e25cb7996eacfcc0Jeff Garzikstatic unsigned int mv5_scr_offset(unsigned int sc_reg_in)
1512c9d39130123238ac18478a42e25cb7996eacfcc0Jeff Garzik{
1513c9d39130123238ac18478a42e25cb7996eacfcc0Jeff Garzik	unsigned int ofs;
1514c9d39130123238ac18478a42e25cb7996eacfcc0Jeff Garzik
1515c9d39130123238ac18478a42e25cb7996eacfcc0Jeff Garzik	switch (sc_reg_in) {
1516c9d39130123238ac18478a42e25cb7996eacfcc0Jeff Garzik	case SCR_STATUS:
1517c9d39130123238ac18478a42e25cb7996eacfcc0Jeff Garzik	case SCR_ERROR:
1518c9d39130123238ac18478a42e25cb7996eacfcc0Jeff Garzik	case SCR_CONTROL:
1519c9d39130123238ac18478a42e25cb7996eacfcc0Jeff Garzik		ofs = sc_reg_in * sizeof(u32);
1520c9d39130123238ac18478a42e25cb7996eacfcc0Jeff Garzik		break;
1521c9d39130123238ac18478a42e25cb7996eacfcc0Jeff Garzik	default:
1522c9d39130123238ac18478a42e25cb7996eacfcc0Jeff Garzik		ofs = 0xffffffffU;
1523c9d39130123238ac18478a42e25cb7996eacfcc0Jeff Garzik		break;
1524c9d39130123238ac18478a42e25cb7996eacfcc0Jeff Garzik	}
1525c9d39130123238ac18478a42e25cb7996eacfcc0Jeff Garzik	return ofs;
1526c9d39130123238ac18478a42e25cb7996eacfcc0Jeff Garzik}
1527c9d39130123238ac18478a42e25cb7996eacfcc0Jeff Garzik
1528c9d39130123238ac18478a42e25cb7996eacfcc0Jeff Garzikstatic u32 mv5_scr_read(struct ata_port *ap, unsigned int sc_reg_in)
1529c9d39130123238ac18478a42e25cb7996eacfcc0Jeff Garzik{
1530cca3974e48607c3775dc73b544a5700b2e37c21aJeff Garzik	void __iomem *mmio = mv5_phy_base(ap->host->mmio_base, ap->port_no);
1531c9d39130123238ac18478a42e25cb7996eacfcc0Jeff Garzik	unsigned int ofs = mv5_scr_offset(sc_reg_in);
1532c9d39130123238ac18478a42e25cb7996eacfcc0Jeff Garzik
1533c9d39130123238ac18478a42e25cb7996eacfcc0Jeff Garzik	if (ofs != 0xffffffffU)
1534c9d39130123238ac18478a42e25cb7996eacfcc0Jeff Garzik		return readl(mmio + ofs);
1535c9d39130123238ac18478a42e25cb7996eacfcc0Jeff Garzik	else
1536c9d39130123238ac18478a42e25cb7996eacfcc0Jeff Garzik		return (u32) ofs;
1537c9d39130123238ac18478a42e25cb7996eacfcc0Jeff Garzik}
1538c9d39130123238ac18478a42e25cb7996eacfcc0Jeff Garzik
1539c9d39130123238ac18478a42e25cb7996eacfcc0Jeff Garzikstatic void mv5_scr_write(struct ata_port *ap, unsigned int sc_reg_in, u32 val)
1540c9d39130123238ac18478a42e25cb7996eacfcc0Jeff Garzik{
1541cca3974e48607c3775dc73b544a5700b2e37c21aJeff Garzik	void __iomem *mmio = mv5_phy_base(ap->host->mmio_base, ap->port_no);
1542c9d39130123238ac18478a42e25cb7996eacfcc0Jeff Garzik	unsigned int ofs = mv5_scr_offset(sc_reg_in);
1543c9d39130123238ac18478a42e25cb7996eacfcc0Jeff Garzik
1544c9d39130123238ac18478a42e25cb7996eacfcc0Jeff Garzik	if (ofs != 0xffffffffU)
1545c9d39130123238ac18478a42e25cb7996eacfcc0Jeff Garzik		writelfl(val, mmio + ofs);
1546c9d39130123238ac18478a42e25cb7996eacfcc0Jeff Garzik}
1547c9d39130123238ac18478a42e25cb7996eacfcc0Jeff Garzik
1548522479fb98c6667f081e75f87e298e413c0b1db8Jeff Garzikstatic void mv5_reset_bus(struct pci_dev *pdev, void __iomem *mmio)
1549522479fb98c6667f081e75f87e298e413c0b1db8Jeff Garzik{
1550522479fb98c6667f081e75f87e298e413c0b1db8Jeff Garzik	u8 rev_id;
1551522479fb98c6667f081e75f87e298e413c0b1db8Jeff Garzik	int early_5080;
1552522479fb98c6667f081e75f87e298e413c0b1db8Jeff Garzik
1553522479fb98c6667f081e75f87e298e413c0b1db8Jeff Garzik	pci_read_config_byte(pdev, PCI_REVISION_ID, &rev_id);
1554522479fb98c6667f081e75f87e298e413c0b1db8Jeff Garzik
1555522479fb98c6667f081e75f87e298e413c0b1db8Jeff Garzik	early_5080 = (pdev->device == 0x5080) && (rev_id == 0);
1556522479fb98c6667f081e75f87e298e413c0b1db8Jeff Garzik
1557522479fb98c6667f081e75f87e298e413c0b1db8Jeff Garzik	if (!early_5080) {
1558522479fb98c6667f081e75f87e298e413c0b1db8Jeff Garzik		u32 tmp = readl(mmio + MV_PCI_EXP_ROM_BAR_CTL);
1559522479fb98c6667f081e75f87e298e413c0b1db8Jeff Garzik		tmp |= (1 << 0);
1560522479fb98c6667f081e75f87e298e413c0b1db8Jeff Garzik		writel(tmp, mmio + MV_PCI_EXP_ROM_BAR_CTL);
1561522479fb98c6667f081e75f87e298e413c0b1db8Jeff Garzik	}
1562522479fb98c6667f081e75f87e298e413c0b1db8Jeff Garzik
1563522479fb98c6667f081e75f87e298e413c0b1db8Jeff Garzik	mv_reset_pci_bus(pdev, mmio);
1564522479fb98c6667f081e75f87e298e413c0b1db8Jeff Garzik}
1565522479fb98c6667f081e75f87e298e413c0b1db8Jeff Garzik
1566522479fb98c6667f081e75f87e298e413c0b1db8Jeff Garzikstatic void mv5_reset_flash(struct mv_host_priv *hpriv, void __iomem *mmio)
1567522479fb98c6667f081e75f87e298e413c0b1db8Jeff Garzik{
1568522479fb98c6667f081e75f87e298e413c0b1db8Jeff Garzik	writel(0x0fcfffff, mmio + MV_FLASH_CTL);
1569522479fb98c6667f081e75f87e298e413c0b1db8Jeff Garzik}
1570522479fb98c6667f081e75f87e298e413c0b1db8Jeff Garzik
157147c2b677daeed9c79ecb7167c211ff36876ea611Jeff Garzikstatic void mv5_read_preamp(struct mv_host_priv *hpriv, int idx,
1572ba3fe8fb6a469390a14379519915f3c39a973d99Jeff Garzik			   void __iomem *mmio)
1573ba3fe8fb6a469390a14379519915f3c39a973d99Jeff Garzik{
1574c9d39130123238ac18478a42e25cb7996eacfcc0Jeff Garzik	void __iomem *phy_mmio = mv5_phy_base(mmio, idx);
1575c9d39130123238ac18478a42e25cb7996eacfcc0Jeff Garzik	u32 tmp;
1576c9d39130123238ac18478a42e25cb7996eacfcc0Jeff Garzik
1577c9d39130123238ac18478a42e25cb7996eacfcc0Jeff Garzik	tmp = readl(phy_mmio + MV5_PHY_MODE);
1578c9d39130123238ac18478a42e25cb7996eacfcc0Jeff Garzik
1579c9d39130123238ac18478a42e25cb7996eacfcc0Jeff Garzik	hpriv->signal[idx].pre = tmp & 0x1800;	/* bits 12:11 */
1580c9d39130123238ac18478a42e25cb7996eacfcc0Jeff Garzik	hpriv->signal[idx].amps = tmp & 0xe0;	/* bits 7:5 */
1581ba3fe8fb6a469390a14379519915f3c39a973d99Jeff Garzik}
1582ba3fe8fb6a469390a14379519915f3c39a973d99Jeff Garzik
158347c2b677daeed9c79ecb7167c211ff36876ea611Jeff Garzikstatic void mv5_enable_leds(struct mv_host_priv *hpriv, void __iomem *mmio)
1584ba3fe8fb6a469390a14379519915f3c39a973d99Jeff Garzik{
1585522479fb98c6667f081e75f87e298e413c0b1db8Jeff Garzik	u32 tmp;
1586522479fb98c6667f081e75f87e298e413c0b1db8Jeff Garzik
1587522479fb98c6667f081e75f87e298e413c0b1db8Jeff Garzik	writel(0, mmio + MV_GPIO_PORT_CTL);
1588522479fb98c6667f081e75f87e298e413c0b1db8Jeff Garzik
1589522479fb98c6667f081e75f87e298e413c0b1db8Jeff Garzik	/* FIXME: handle MV_HP_ERRATA_50XXB2 errata */
1590522479fb98c6667f081e75f87e298e413c0b1db8Jeff Garzik
1591522479fb98c6667f081e75f87e298e413c0b1db8Jeff Garzik	tmp = readl(mmio + MV_PCI_EXP_ROM_BAR_CTL);
1592522479fb98c6667f081e75f87e298e413c0b1db8Jeff Garzik	tmp |= ~(1 << 0);
1593522479fb98c6667f081e75f87e298e413c0b1db8Jeff Garzik	writel(tmp, mmio + MV_PCI_EXP_ROM_BAR_CTL);
1594ba3fe8fb6a469390a14379519915f3c39a973d99Jeff Garzik}
1595ba3fe8fb6a469390a14379519915f3c39a973d99Jeff Garzik
15962a47ce06d534692f9bd2bf4e90a20fc9b1054c39Jeff Garzikstatic void mv5_phy_errata(struct mv_host_priv *hpriv, void __iomem *mmio,
15972a47ce06d534692f9bd2bf4e90a20fc9b1054c39Jeff Garzik			   unsigned int port)
1598bca1c4eb9411533d613123618c0d127fae532595Jeff Garzik{
1599c9d39130123238ac18478a42e25cb7996eacfcc0Jeff Garzik	void __iomem *phy_mmio = mv5_phy_base(mmio, port);
1600c9d39130123238ac18478a42e25cb7996eacfcc0Jeff Garzik	const u32 mask = (1<<12) | (1<<11) | (1<<7) | (1<<6) | (1<<5);
1601c9d39130123238ac18478a42e25cb7996eacfcc0Jeff Garzik	u32 tmp;
1602c9d39130123238ac18478a42e25cb7996eacfcc0Jeff Garzik	int fix_apm_sq = (hpriv->hp_flags & MV_HP_ERRATA_50XXB0);
1603c9d39130123238ac18478a42e25cb7996eacfcc0Jeff Garzik
1604c9d39130123238ac18478a42e25cb7996eacfcc0Jeff Garzik	if (fix_apm_sq) {
1605c9d39130123238ac18478a42e25cb7996eacfcc0Jeff Garzik		tmp = readl(phy_mmio + MV5_LT_MODE);
1606c9d39130123238ac18478a42e25cb7996eacfcc0Jeff Garzik		tmp |= (1 << 19);
1607c9d39130123238ac18478a42e25cb7996eacfcc0Jeff Garzik		writel(tmp, phy_mmio + MV5_LT_MODE);
1608c9d39130123238ac18478a42e25cb7996eacfcc0Jeff Garzik
1609c9d39130123238ac18478a42e25cb7996eacfcc0Jeff Garzik		tmp = readl(phy_mmio + MV5_PHY_CTL);
1610c9d39130123238ac18478a42e25cb7996eacfcc0Jeff Garzik		tmp &= ~0x3;
1611c9d39130123238ac18478a42e25cb7996eacfcc0Jeff Garzik		tmp |= 0x1;
1612c9d39130123238ac18478a42e25cb7996eacfcc0Jeff Garzik		writel(tmp, phy_mmio + MV5_PHY_CTL);
1613c9d39130123238ac18478a42e25cb7996eacfcc0Jeff Garzik	}
1614c9d39130123238ac18478a42e25cb7996eacfcc0Jeff Garzik
1615c9d39130123238ac18478a42e25cb7996eacfcc0Jeff Garzik	tmp = readl(phy_mmio + MV5_PHY_MODE);
1616c9d39130123238ac18478a42e25cb7996eacfcc0Jeff Garzik	tmp &= ~mask;
1617c9d39130123238ac18478a42e25cb7996eacfcc0Jeff Garzik	tmp |= hpriv->signal[port].pre;
1618c9d39130123238ac18478a42e25cb7996eacfcc0Jeff Garzik	tmp |= hpriv->signal[port].amps;
1619c9d39130123238ac18478a42e25cb7996eacfcc0Jeff Garzik	writel(tmp, phy_mmio + MV5_PHY_MODE);
1620bca1c4eb9411533d613123618c0d127fae532595Jeff Garzik}
1621bca1c4eb9411533d613123618c0d127fae532595Jeff Garzik
1622c9d39130123238ac18478a42e25cb7996eacfcc0Jeff Garzik
1623c9d39130123238ac18478a42e25cb7996eacfcc0Jeff Garzik#undef ZERO
1624c9d39130123238ac18478a42e25cb7996eacfcc0Jeff Garzik#define ZERO(reg) writel(0, port_mmio + (reg))
1625c9d39130123238ac18478a42e25cb7996eacfcc0Jeff Garzikstatic void mv5_reset_hc_port(struct mv_host_priv *hpriv, void __iomem *mmio,
1626c9d39130123238ac18478a42e25cb7996eacfcc0Jeff Garzik			     unsigned int port)
1627c9d39130123238ac18478a42e25cb7996eacfcc0Jeff Garzik{
1628c9d39130123238ac18478a42e25cb7996eacfcc0Jeff Garzik	void __iomem *port_mmio = mv_port_base(mmio, port);
1629c9d39130123238ac18478a42e25cb7996eacfcc0Jeff Garzik
1630c9d39130123238ac18478a42e25cb7996eacfcc0Jeff Garzik	writelfl(EDMA_DS, port_mmio + EDMA_CMD_OFS);
1631c9d39130123238ac18478a42e25cb7996eacfcc0Jeff Garzik
1632c9d39130123238ac18478a42e25cb7996eacfcc0Jeff Garzik	mv_channel_reset(hpriv, mmio, port);
1633c9d39130123238ac18478a42e25cb7996eacfcc0Jeff Garzik
1634c9d39130123238ac18478a42e25cb7996eacfcc0Jeff Garzik	ZERO(0x028);	/* command */
1635c9d39130123238ac18478a42e25cb7996eacfcc0Jeff Garzik	writel(0x11f, port_mmio + EDMA_CFG_OFS);
1636c9d39130123238ac18478a42e25cb7996eacfcc0Jeff Garzik	ZERO(0x004);	/* timer */
1637c9d39130123238ac18478a42e25cb7996eacfcc0Jeff Garzik	ZERO(0x008);	/* irq err cause */
1638c9d39130123238ac18478a42e25cb7996eacfcc0Jeff Garzik	ZERO(0x00c);	/* irq err mask */
1639c9d39130123238ac18478a42e25cb7996eacfcc0Jeff Garzik	ZERO(0x010);	/* rq bah */
1640c9d39130123238ac18478a42e25cb7996eacfcc0Jeff Garzik	ZERO(0x014);	/* rq inp */
1641c9d39130123238ac18478a42e25cb7996eacfcc0Jeff Garzik	ZERO(0x018);	/* rq outp */
1642c9d39130123238ac18478a42e25cb7996eacfcc0Jeff Garzik	ZERO(0x01c);	/* respq bah */
1643c9d39130123238ac18478a42e25cb7996eacfcc0Jeff Garzik	ZERO(0x024);	/* respq outp */
1644c9d39130123238ac18478a42e25cb7996eacfcc0Jeff Garzik	ZERO(0x020);	/* respq inp */
1645c9d39130123238ac18478a42e25cb7996eacfcc0Jeff Garzik	ZERO(0x02c);	/* test control */
1646c9d39130123238ac18478a42e25cb7996eacfcc0Jeff Garzik	writel(0xbc, port_mmio + EDMA_IORDY_TMOUT);
1647c9d39130123238ac18478a42e25cb7996eacfcc0Jeff Garzik}
1648c9d39130123238ac18478a42e25cb7996eacfcc0Jeff Garzik#undef ZERO
1649c9d39130123238ac18478a42e25cb7996eacfcc0Jeff Garzik
1650c9d39130123238ac18478a42e25cb7996eacfcc0Jeff Garzik#define ZERO(reg) writel(0, hc_mmio + (reg))
1651c9d39130123238ac18478a42e25cb7996eacfcc0Jeff Garzikstatic void mv5_reset_one_hc(struct mv_host_priv *hpriv, void __iomem *mmio,
1652c9d39130123238ac18478a42e25cb7996eacfcc0Jeff Garzik			unsigned int hc)
165347c2b677daeed9c79ecb7167c211ff36876ea611Jeff Garzik{
1654c9d39130123238ac18478a42e25cb7996eacfcc0Jeff Garzik	void __iomem *hc_mmio = mv_hc_base(mmio, hc);
1655c9d39130123238ac18478a42e25cb7996eacfcc0Jeff Garzik	u32 tmp;
1656c9d39130123238ac18478a42e25cb7996eacfcc0Jeff Garzik
1657c9d39130123238ac18478a42e25cb7996eacfcc0Jeff Garzik	ZERO(0x00c);
1658c9d39130123238ac18478a42e25cb7996eacfcc0Jeff Garzik	ZERO(0x010);
1659c9d39130123238ac18478a42e25cb7996eacfcc0Jeff Garzik	ZERO(0x014);
1660c9d39130123238ac18478a42e25cb7996eacfcc0Jeff Garzik	ZERO(0x018);
1661c9d39130123238ac18478a42e25cb7996eacfcc0Jeff Garzik
1662c9d39130123238ac18478a42e25cb7996eacfcc0Jeff Garzik	tmp = readl(hc_mmio + 0x20);
1663c9d39130123238ac18478a42e25cb7996eacfcc0Jeff Garzik	tmp &= 0x1c1c1c1c;
1664c9d39130123238ac18478a42e25cb7996eacfcc0Jeff Garzik	tmp |= 0x03030303;
1665c9d39130123238ac18478a42e25cb7996eacfcc0Jeff Garzik	writel(tmp, hc_mmio + 0x20);
1666c9d39130123238ac18478a42e25cb7996eacfcc0Jeff Garzik}
1667c9d39130123238ac18478a42e25cb7996eacfcc0Jeff Garzik#undef ZERO
1668c9d39130123238ac18478a42e25cb7996eacfcc0Jeff Garzik
1669c9d39130123238ac18478a42e25cb7996eacfcc0Jeff Garzikstatic int mv5_reset_hc(struct mv_host_priv *hpriv, void __iomem *mmio,
1670c9d39130123238ac18478a42e25cb7996eacfcc0Jeff Garzik			unsigned int n_hc)
1671c9d39130123238ac18478a42e25cb7996eacfcc0Jeff Garzik{
1672c9d39130123238ac18478a42e25cb7996eacfcc0Jeff Garzik	unsigned int hc, port;
1673c9d39130123238ac18478a42e25cb7996eacfcc0Jeff Garzik
1674c9d39130123238ac18478a42e25cb7996eacfcc0Jeff Garzik	for (hc = 0; hc < n_hc; hc++) {
1675c9d39130123238ac18478a42e25cb7996eacfcc0Jeff Garzik		for (port = 0; port < MV_PORTS_PER_HC; port++)
1676c9d39130123238ac18478a42e25cb7996eacfcc0Jeff Garzik			mv5_reset_hc_port(hpriv, mmio,
1677c9d39130123238ac18478a42e25cb7996eacfcc0Jeff Garzik					  (hc * MV_PORTS_PER_HC) + port);
1678c9d39130123238ac18478a42e25cb7996eacfcc0Jeff Garzik
1679c9d39130123238ac18478a42e25cb7996eacfcc0Jeff Garzik		mv5_reset_one_hc(hpriv, mmio, hc);
1680c9d39130123238ac18478a42e25cb7996eacfcc0Jeff Garzik	}
1681c9d39130123238ac18478a42e25cb7996eacfcc0Jeff Garzik
1682c9d39130123238ac18478a42e25cb7996eacfcc0Jeff Garzik	return 0;
168347c2b677daeed9c79ecb7167c211ff36876ea611Jeff Garzik}
168447c2b677daeed9c79ecb7167c211ff36876ea611Jeff Garzik
1685101ffae26c23ea928fce6d31a8b4901327d91a15Jeff Garzik#undef ZERO
1686101ffae26c23ea928fce6d31a8b4901327d91a15Jeff Garzik#define ZERO(reg) writel(0, mmio + (reg))
1687101ffae26c23ea928fce6d31a8b4901327d91a15Jeff Garzikstatic void mv_reset_pci_bus(struct pci_dev *pdev, void __iomem *mmio)
1688101ffae26c23ea928fce6d31a8b4901327d91a15Jeff Garzik{
1689101ffae26c23ea928fce6d31a8b4901327d91a15Jeff Garzik	u32 tmp;
1690101ffae26c23ea928fce6d31a8b4901327d91a15Jeff Garzik
1691101ffae26c23ea928fce6d31a8b4901327d91a15Jeff Garzik	tmp = readl(mmio + MV_PCI_MODE);
1692101ffae26c23ea928fce6d31a8b4901327d91a15Jeff Garzik	tmp &= 0xff00ffff;
1693101ffae26c23ea928fce6d31a8b4901327d91a15Jeff Garzik	writel(tmp, mmio + MV_PCI_MODE);
1694101ffae26c23ea928fce6d31a8b4901327d91a15Jeff Garzik
1695101ffae26c23ea928fce6d31a8b4901327d91a15Jeff Garzik	ZERO(MV_PCI_DISC_TIMER);
1696101ffae26c23ea928fce6d31a8b4901327d91a15Jeff Garzik	ZERO(MV_PCI_MSI_TRIGGER);
1697101ffae26c23ea928fce6d31a8b4901327d91a15Jeff Garzik	writel(0x000100ff, mmio + MV_PCI_XBAR_TMOUT);
1698101ffae26c23ea928fce6d31a8b4901327d91a15Jeff Garzik	ZERO(HC_MAIN_IRQ_MASK_OFS);
1699101ffae26c23ea928fce6d31a8b4901327d91a15Jeff Garzik	ZERO(MV_PCI_SERR_MASK);
1700101ffae26c23ea928fce6d31a8b4901327d91a15Jeff Garzik	ZERO(PCI_IRQ_CAUSE_OFS);
1701101ffae26c23ea928fce6d31a8b4901327d91a15Jeff Garzik	ZERO(PCI_IRQ_MASK_OFS);
1702101ffae26c23ea928fce6d31a8b4901327d91a15Jeff Garzik	ZERO(MV_PCI_ERR_LOW_ADDRESS);
1703101ffae26c23ea928fce6d31a8b4901327d91a15Jeff Garzik	ZERO(MV_PCI_ERR_HIGH_ADDRESS);
1704101ffae26c23ea928fce6d31a8b4901327d91a15Jeff Garzik	ZERO(MV_PCI_ERR_ATTRIBUTE);
1705101ffae26c23ea928fce6d31a8b4901327d91a15Jeff Garzik	ZERO(MV_PCI_ERR_COMMAND);
1706101ffae26c23ea928fce6d31a8b4901327d91a15Jeff Garzik}
1707101ffae26c23ea928fce6d31a8b4901327d91a15Jeff Garzik#undef ZERO
1708101ffae26c23ea928fce6d31a8b4901327d91a15Jeff Garzik
1709101ffae26c23ea928fce6d31a8b4901327d91a15Jeff Garzikstatic void mv6_reset_flash(struct mv_host_priv *hpriv, void __iomem *mmio)
1710101ffae26c23ea928fce6d31a8b4901327d91a15Jeff Garzik{
1711101ffae26c23ea928fce6d31a8b4901327d91a15Jeff Garzik	u32 tmp;
1712101ffae26c23ea928fce6d31a8b4901327d91a15Jeff Garzik
1713101ffae26c23ea928fce6d31a8b4901327d91a15Jeff Garzik	mv5_reset_flash(hpriv, mmio);
1714101ffae26c23ea928fce6d31a8b4901327d91a15Jeff Garzik
1715101ffae26c23ea928fce6d31a8b4901327d91a15Jeff Garzik	tmp = readl(mmio + MV_GPIO_PORT_CTL);
1716101ffae26c23ea928fce6d31a8b4901327d91a15Jeff Garzik	tmp &= 0x3;
1717101ffae26c23ea928fce6d31a8b4901327d91a15Jeff Garzik	tmp |= (1 << 5) | (1 << 6);
1718101ffae26c23ea928fce6d31a8b4901327d91a15Jeff Garzik	writel(tmp, mmio + MV_GPIO_PORT_CTL);
1719101ffae26c23ea928fce6d31a8b4901327d91a15Jeff Garzik}
1720101ffae26c23ea928fce6d31a8b4901327d91a15Jeff Garzik
1721101ffae26c23ea928fce6d31a8b4901327d91a15Jeff Garzik/**
1722101ffae26c23ea928fce6d31a8b4901327d91a15Jeff Garzik *      mv6_reset_hc - Perform the 6xxx global soft reset
1723101ffae26c23ea928fce6d31a8b4901327d91a15Jeff Garzik *      @mmio: base address of the HBA
1724101ffae26c23ea928fce6d31a8b4901327d91a15Jeff Garzik *
1725101ffae26c23ea928fce6d31a8b4901327d91a15Jeff Garzik *      This routine only applies to 6xxx parts.
1726101ffae26c23ea928fce6d31a8b4901327d91a15Jeff Garzik *
1727101ffae26c23ea928fce6d31a8b4901327d91a15Jeff Garzik *      LOCKING:
1728101ffae26c23ea928fce6d31a8b4901327d91a15Jeff Garzik *      Inherited from caller.
1729101ffae26c23ea928fce6d31a8b4901327d91a15Jeff Garzik */
1730c9d39130123238ac18478a42e25cb7996eacfcc0Jeff Garzikstatic int mv6_reset_hc(struct mv_host_priv *hpriv, void __iomem *mmio,
1731c9d39130123238ac18478a42e25cb7996eacfcc0Jeff Garzik			unsigned int n_hc)
1732101ffae26c23ea928fce6d31a8b4901327d91a15Jeff Garzik{
1733101ffae26c23ea928fce6d31a8b4901327d91a15Jeff Garzik	void __iomem *reg = mmio + PCI_MAIN_CMD_STS_OFS;
1734101ffae26c23ea928fce6d31a8b4901327d91a15Jeff Garzik	int i, rc = 0;
1735101ffae26c23ea928fce6d31a8b4901327d91a15Jeff Garzik	u32 t;
1736101ffae26c23ea928fce6d31a8b4901327d91a15Jeff Garzik
1737101ffae26c23ea928fce6d31a8b4901327d91a15Jeff Garzik	/* Following procedure defined in PCI "main command and status
1738101ffae26c23ea928fce6d31a8b4901327d91a15Jeff Garzik	 * register" table.
1739101ffae26c23ea928fce6d31a8b4901327d91a15Jeff Garzik	 */
1740101ffae26c23ea928fce6d31a8b4901327d91a15Jeff Garzik	t = readl(reg);
1741101ffae26c23ea928fce6d31a8b4901327d91a15Jeff Garzik	writel(t | STOP_PCI_MASTER, reg);
1742101ffae26c23ea928fce6d31a8b4901327d91a15Jeff Garzik
1743101ffae26c23ea928fce6d31a8b4901327d91a15Jeff Garzik	for (i = 0; i < 1000; i++) {
1744101ffae26c23ea928fce6d31a8b4901327d91a15Jeff Garzik		udelay(1);
1745101ffae26c23ea928fce6d31a8b4901327d91a15Jeff Garzik		t = readl(reg);
1746101ffae26c23ea928fce6d31a8b4901327d91a15Jeff Garzik		if (PCI_MASTER_EMPTY & t) {
1747101ffae26c23ea928fce6d31a8b4901327d91a15Jeff Garzik			break;
1748101ffae26c23ea928fce6d31a8b4901327d91a15Jeff Garzik		}
1749101ffae26c23ea928fce6d31a8b4901327d91a15Jeff Garzik	}
1750101ffae26c23ea928fce6d31a8b4901327d91a15Jeff Garzik	if (!(PCI_MASTER_EMPTY & t)) {
1751101ffae26c23ea928fce6d31a8b4901327d91a15Jeff Garzik		printk(KERN_ERR DRV_NAME ": PCI master won't flush\n");
1752101ffae26c23ea928fce6d31a8b4901327d91a15Jeff Garzik		rc = 1;
1753101ffae26c23ea928fce6d31a8b4901327d91a15Jeff Garzik		goto done;
1754101ffae26c23ea928fce6d31a8b4901327d91a15Jeff Garzik	}
1755101ffae26c23ea928fce6d31a8b4901327d91a15Jeff Garzik
1756101ffae26c23ea928fce6d31a8b4901327d91a15Jeff Garzik	/* set reset */
1757101ffae26c23ea928fce6d31a8b4901327d91a15Jeff Garzik	i = 5;
1758101ffae26c23ea928fce6d31a8b4901327d91a15Jeff Garzik	do {
1759101ffae26c23ea928fce6d31a8b4901327d91a15Jeff Garzik		writel(t | GLOB_SFT_RST, reg);
1760101ffae26c23ea928fce6d31a8b4901327d91a15Jeff Garzik		t = readl(reg);
1761101ffae26c23ea928fce6d31a8b4901327d91a15Jeff Garzik		udelay(1);
1762101ffae26c23ea928fce6d31a8b4901327d91a15Jeff Garzik	} while (!(GLOB_SFT_RST & t) && (i-- > 0));
1763101ffae26c23ea928fce6d31a8b4901327d91a15Jeff Garzik
1764101ffae26c23ea928fce6d31a8b4901327d91a15Jeff Garzik	if (!(GLOB_SFT_RST & t)) {
1765101ffae26c23ea928fce6d31a8b4901327d91a15Jeff Garzik		printk(KERN_ERR DRV_NAME ": can't set global reset\n");
1766101ffae26c23ea928fce6d31a8b4901327d91a15Jeff Garzik		rc = 1;
1767101ffae26c23ea928fce6d31a8b4901327d91a15Jeff Garzik		goto done;
1768101ffae26c23ea928fce6d31a8b4901327d91a15Jeff Garzik	}
1769101ffae26c23ea928fce6d31a8b4901327d91a15Jeff Garzik
1770101ffae26c23ea928fce6d31a8b4901327d91a15Jeff Garzik	/* clear reset and *reenable the PCI master* (not mentioned in spec) */
1771101ffae26c23ea928fce6d31a8b4901327d91a15Jeff Garzik	i = 5;
1772101ffae26c23ea928fce6d31a8b4901327d91a15Jeff Garzik	do {
1773101ffae26c23ea928fce6d31a8b4901327d91a15Jeff Garzik		writel(t & ~(GLOB_SFT_RST | STOP_PCI_MASTER), reg);
1774101ffae26c23ea928fce6d31a8b4901327d91a15Jeff Garzik		t = readl(reg);
1775101ffae26c23ea928fce6d31a8b4901327d91a15Jeff Garzik		udelay(1);
1776101ffae26c23ea928fce6d31a8b4901327d91a15Jeff Garzik	} while ((GLOB_SFT_RST & t) && (i-- > 0));
1777101ffae26c23ea928fce6d31a8b4901327d91a15Jeff Garzik
1778101ffae26c23ea928fce6d31a8b4901327d91a15Jeff Garzik	if (GLOB_SFT_RST & t) {
1779101ffae26c23ea928fce6d31a8b4901327d91a15Jeff Garzik		printk(KERN_ERR DRV_NAME ": can't clear global reset\n");
1780101ffae26c23ea928fce6d31a8b4901327d91a15Jeff Garzik		rc = 1;
1781101ffae26c23ea928fce6d31a8b4901327d91a15Jeff Garzik	}
1782101ffae26c23ea928fce6d31a8b4901327d91a15Jeff Garzikdone:
1783101ffae26c23ea928fce6d31a8b4901327d91a15Jeff Garzik	return rc;
1784101ffae26c23ea928fce6d31a8b4901327d91a15Jeff Garzik}
1785101ffae26c23ea928fce6d31a8b4901327d91a15Jeff Garzik
178647c2b677daeed9c79ecb7167c211ff36876ea611Jeff Garzikstatic void mv6_read_preamp(struct mv_host_priv *hpriv, int idx,
1787ba3fe8fb6a469390a14379519915f3c39a973d99Jeff Garzik			   void __iomem *mmio)
1788ba3fe8fb6a469390a14379519915f3c39a973d99Jeff Garzik{
1789ba3fe8fb6a469390a14379519915f3c39a973d99Jeff Garzik	void __iomem *port_mmio;
1790ba3fe8fb6a469390a14379519915f3c39a973d99Jeff Garzik	u32 tmp;
1791ba3fe8fb6a469390a14379519915f3c39a973d99Jeff Garzik
1792ba3fe8fb6a469390a14379519915f3c39a973d99Jeff Garzik	tmp = readl(mmio + MV_RESET_CFG);
1793ba3fe8fb6a469390a14379519915f3c39a973d99Jeff Garzik	if ((tmp & (1 << 0)) == 0) {
179447c2b677daeed9c79ecb7167c211ff36876ea611Jeff Garzik		hpriv->signal[idx].amps = 0x7 << 8;
1795ba3fe8fb6a469390a14379519915f3c39a973d99Jeff Garzik		hpriv->signal[idx].pre = 0x1 << 5;
1796ba3fe8fb6a469390a14379519915f3c39a973d99Jeff Garzik		return;
1797ba3fe8fb6a469390a14379519915f3c39a973d99Jeff Garzik	}
1798ba3fe8fb6a469390a14379519915f3c39a973d99Jeff Garzik
1799ba3fe8fb6a469390a14379519915f3c39a973d99Jeff Garzik	port_mmio = mv_port_base(mmio, idx);
1800ba3fe8fb6a469390a14379519915f3c39a973d99Jeff Garzik	tmp = readl(port_mmio + PHY_MODE2);
1801ba3fe8fb6a469390a14379519915f3c39a973d99Jeff Garzik
1802ba3fe8fb6a469390a14379519915f3c39a973d99Jeff Garzik	hpriv->signal[idx].amps = tmp & 0x700;	/* bits 10:8 */
1803ba3fe8fb6a469390a14379519915f3c39a973d99Jeff Garzik	hpriv->signal[idx].pre = tmp & 0xe0;	/* bits 7:5 */
1804ba3fe8fb6a469390a14379519915f3c39a973d99Jeff Garzik}
1805ba3fe8fb6a469390a14379519915f3c39a973d99Jeff Garzik
180647c2b677daeed9c79ecb7167c211ff36876ea611Jeff Garzikstatic void mv6_enable_leds(struct mv_host_priv *hpriv, void __iomem *mmio)
1807ba3fe8fb6a469390a14379519915f3c39a973d99Jeff Garzik{
180847c2b677daeed9c79ecb7167c211ff36876ea611Jeff Garzik	writel(0x00000060, mmio + MV_GPIO_PORT_CTL);
1809ba3fe8fb6a469390a14379519915f3c39a973d99Jeff Garzik}
1810ba3fe8fb6a469390a14379519915f3c39a973d99Jeff Garzik
1811c9d39130123238ac18478a42e25cb7996eacfcc0Jeff Garzikstatic void mv6_phy_errata(struct mv_host_priv *hpriv, void __iomem *mmio,
18122a47ce06d534692f9bd2bf4e90a20fc9b1054c39Jeff Garzik			   unsigned int port)
1813bca1c4eb9411533d613123618c0d127fae532595Jeff Garzik{
1814c9d39130123238ac18478a42e25cb7996eacfcc0Jeff Garzik	void __iomem *port_mmio = mv_port_base(mmio, port);
1815c9d39130123238ac18478a42e25cb7996eacfcc0Jeff Garzik
1816bca1c4eb9411533d613123618c0d127fae532595Jeff Garzik	u32 hp_flags = hpriv->hp_flags;
181747c2b677daeed9c79ecb7167c211ff36876ea611Jeff Garzik	int fix_phy_mode2 =
181847c2b677daeed9c79ecb7167c211ff36876ea611Jeff Garzik		hp_flags & (MV_HP_ERRATA_60X1B2 | MV_HP_ERRATA_60X1C0);
1819bca1c4eb9411533d613123618c0d127fae532595Jeff Garzik	int fix_phy_mode4 =
182047c2b677daeed9c79ecb7167c211ff36876ea611Jeff Garzik		hp_flags & (MV_HP_ERRATA_60X1B2 | MV_HP_ERRATA_60X1C0);
182147c2b677daeed9c79ecb7167c211ff36876ea611Jeff Garzik	u32 m2, tmp;
182247c2b677daeed9c79ecb7167c211ff36876ea611Jeff Garzik
182347c2b677daeed9c79ecb7167c211ff36876ea611Jeff Garzik	if (fix_phy_mode2) {
182447c2b677daeed9c79ecb7167c211ff36876ea611Jeff Garzik		m2 = readl(port_mmio + PHY_MODE2);
182547c2b677daeed9c79ecb7167c211ff36876ea611Jeff Garzik		m2 &= ~(1 << 16);
182647c2b677daeed9c79ecb7167c211ff36876ea611Jeff Garzik		m2 |= (1 << 31);
182747c2b677daeed9c79ecb7167c211ff36876ea611Jeff Garzik		writel(m2, port_mmio + PHY_MODE2);
182847c2b677daeed9c79ecb7167c211ff36876ea611Jeff Garzik
182947c2b677daeed9c79ecb7167c211ff36876ea611Jeff Garzik		udelay(200);
183047c2b677daeed9c79ecb7167c211ff36876ea611Jeff Garzik
183147c2b677daeed9c79ecb7167c211ff36876ea611Jeff Garzik		m2 = readl(port_mmio + PHY_MODE2);
183247c2b677daeed9c79ecb7167c211ff36876ea611Jeff Garzik		m2 &= ~((1 << 16) | (1 << 31));
183347c2b677daeed9c79ecb7167c211ff36876ea611Jeff Garzik		writel(m2, port_mmio + PHY_MODE2);
183447c2b677daeed9c79ecb7167c211ff36876ea611Jeff Garzik
183547c2b677daeed9c79ecb7167c211ff36876ea611Jeff Garzik		udelay(200);
183647c2b677daeed9c79ecb7167c211ff36876ea611Jeff Garzik	}
183747c2b677daeed9c79ecb7167c211ff36876ea611Jeff Garzik
183847c2b677daeed9c79ecb7167c211ff36876ea611Jeff Garzik	/* who knows what this magic does */
183947c2b677daeed9c79ecb7167c211ff36876ea611Jeff Garzik	tmp = readl(port_mmio + PHY_MODE3);
184047c2b677daeed9c79ecb7167c211ff36876ea611Jeff Garzik	tmp &= ~0x7F800000;
184147c2b677daeed9c79ecb7167c211ff36876ea611Jeff Garzik	tmp |= 0x2A800000;
184247c2b677daeed9c79ecb7167c211ff36876ea611Jeff Garzik	writel(tmp, port_mmio + PHY_MODE3);
1843bca1c4eb9411533d613123618c0d127fae532595Jeff Garzik
1844bca1c4eb9411533d613123618c0d127fae532595Jeff Garzik	if (fix_phy_mode4) {
184547c2b677daeed9c79ecb7167c211ff36876ea611Jeff Garzik		u32 m4;
1846bca1c4eb9411533d613123618c0d127fae532595Jeff Garzik
1847bca1c4eb9411533d613123618c0d127fae532595Jeff Garzik		m4 = readl(port_mmio + PHY_MODE4);
184847c2b677daeed9c79ecb7167c211ff36876ea611Jeff Garzik
184947c2b677daeed9c79ecb7167c211ff36876ea611Jeff Garzik		if (hp_flags & MV_HP_ERRATA_60X1B2)
185047c2b677daeed9c79ecb7167c211ff36876ea611Jeff Garzik			tmp = readl(port_mmio + 0x310);
1851bca1c4eb9411533d613123618c0d127fae532595Jeff Garzik
1852bca1c4eb9411533d613123618c0d127fae532595Jeff Garzik		m4 = (m4 & ~(1 << 1)) | (1 << 0);
1853bca1c4eb9411533d613123618c0d127fae532595Jeff Garzik
1854bca1c4eb9411533d613123618c0d127fae532595Jeff Garzik		writel(m4, port_mmio + PHY_MODE4);
185547c2b677daeed9c79ecb7167c211ff36876ea611Jeff Garzik
185647c2b677daeed9c79ecb7167c211ff36876ea611Jeff Garzik		if (hp_flags & MV_HP_ERRATA_60X1B2)
185747c2b677daeed9c79ecb7167c211ff36876ea611Jeff Garzik			writel(tmp, port_mmio + 0x310);
1858bca1c4eb9411533d613123618c0d127fae532595Jeff Garzik	}
1859bca1c4eb9411533d613123618c0d127fae532595Jeff Garzik
1860bca1c4eb9411533d613123618c0d127fae532595Jeff Garzik	/* Revert values of pre-emphasis and signal amps to the saved ones */
1861bca1c4eb9411533d613123618c0d127fae532595Jeff Garzik	m2 = readl(port_mmio + PHY_MODE2);
1862bca1c4eb9411533d613123618c0d127fae532595Jeff Garzik
1863bca1c4eb9411533d613123618c0d127fae532595Jeff Garzik	m2 &= ~MV_M2_PREAMP_MASK;
18642a47ce06d534692f9bd2bf4e90a20fc9b1054c39Jeff Garzik	m2 |= hpriv->signal[port].amps;
18652a47ce06d534692f9bd2bf4e90a20fc9b1054c39Jeff Garzik	m2 |= hpriv->signal[port].pre;
186647c2b677daeed9c79ecb7167c211ff36876ea611Jeff Garzik	m2 &= ~(1 << 16);
1867bca1c4eb9411533d613123618c0d127fae532595Jeff Garzik
1868e4e7b89280d1d666e2c09e5ad36cf071796c4c7eJeff Garzik	/* according to mvSata 3.6.1, some IIE values are fixed */
1869e4e7b89280d1d666e2c09e5ad36cf071796c4c7eJeff Garzik	if (IS_GEN_IIE(hpriv)) {
1870e4e7b89280d1d666e2c09e5ad36cf071796c4c7eJeff Garzik		m2 &= ~0xC30FF01F;
1871e4e7b89280d1d666e2c09e5ad36cf071796c4c7eJeff Garzik		m2 |= 0x0000900F;
1872e4e7b89280d1d666e2c09e5ad36cf071796c4c7eJeff Garzik	}
1873e4e7b89280d1d666e2c09e5ad36cf071796c4c7eJeff Garzik
1874bca1c4eb9411533d613123618c0d127fae532595Jeff Garzik	writel(m2, port_mmio + PHY_MODE2);
1875bca1c4eb9411533d613123618c0d127fae532595Jeff Garzik}
1876bca1c4eb9411533d613123618c0d127fae532595Jeff Garzik
1877c9d39130123238ac18478a42e25cb7996eacfcc0Jeff Garzikstatic void mv_channel_reset(struct mv_host_priv *hpriv, void __iomem *mmio,
1878c9d39130123238ac18478a42e25cb7996eacfcc0Jeff Garzik			     unsigned int port_no)
1879c9d39130123238ac18478a42e25cb7996eacfcc0Jeff Garzik{
1880c9d39130123238ac18478a42e25cb7996eacfcc0Jeff Garzik	void __iomem *port_mmio = mv_port_base(mmio, port_no);
1881c9d39130123238ac18478a42e25cb7996eacfcc0Jeff Garzik
1882c9d39130123238ac18478a42e25cb7996eacfcc0Jeff Garzik	writelfl(ATA_RST, port_mmio + EDMA_CMD_OFS);
1883c9d39130123238ac18478a42e25cb7996eacfcc0Jeff Garzik
1884c9d39130123238ac18478a42e25cb7996eacfcc0Jeff Garzik	if (IS_60XX(hpriv)) {
1885c9d39130123238ac18478a42e25cb7996eacfcc0Jeff Garzik		u32 ifctl = readl(port_mmio + SATA_INTERFACE_CTL);
1886eb46d684600ac145501805a294c94675e82eab2eMark Lord		ifctl |= (1 << 7);		/* enable gen2i speed */
1887eb46d684600ac145501805a294c94675e82eab2eMark Lord		ifctl = (ifctl & 0xfff) | 0x9b1000; /* from chip spec */
1888c9d39130123238ac18478a42e25cb7996eacfcc0Jeff Garzik		writelfl(ifctl, port_mmio + SATA_INTERFACE_CTL);
1889c9d39130123238ac18478a42e25cb7996eacfcc0Jeff Garzik	}
1890c9d39130123238ac18478a42e25cb7996eacfcc0Jeff Garzik
1891c9d39130123238ac18478a42e25cb7996eacfcc0Jeff Garzik	udelay(25);		/* allow reset propagation */
1892c9d39130123238ac18478a42e25cb7996eacfcc0Jeff Garzik
1893c9d39130123238ac18478a42e25cb7996eacfcc0Jeff Garzik	/* Spec never mentions clearing the bit.  Marvell's driver does
1894c9d39130123238ac18478a42e25cb7996eacfcc0Jeff Garzik	 * clear the bit, however.
1895c9d39130123238ac18478a42e25cb7996eacfcc0Jeff Garzik	 */
1896c9d39130123238ac18478a42e25cb7996eacfcc0Jeff Garzik	writelfl(0, port_mmio + EDMA_CMD_OFS);
1897c9d39130123238ac18478a42e25cb7996eacfcc0Jeff Garzik
1898c9d39130123238ac18478a42e25cb7996eacfcc0Jeff Garzik	hpriv->ops->phy_errata(hpriv, mmio, port_no);
1899c9d39130123238ac18478a42e25cb7996eacfcc0Jeff Garzik
1900c9d39130123238ac18478a42e25cb7996eacfcc0Jeff Garzik	if (IS_50XX(hpriv))
1901c9d39130123238ac18478a42e25cb7996eacfcc0Jeff Garzik		mdelay(1);
1902c9d39130123238ac18478a42e25cb7996eacfcc0Jeff Garzik}
1903c9d39130123238ac18478a42e25cb7996eacfcc0Jeff Garzik
1904c9d39130123238ac18478a42e25cb7996eacfcc0Jeff Garzikstatic void mv_stop_and_reset(struct ata_port *ap)
1905c9d39130123238ac18478a42e25cb7996eacfcc0Jeff Garzik{
1906cca3974e48607c3775dc73b544a5700b2e37c21aJeff Garzik	struct mv_host_priv *hpriv = ap->host->private_data;
1907cca3974e48607c3775dc73b544a5700b2e37c21aJeff Garzik	void __iomem *mmio = ap->host->mmio_base;
1908c9d39130123238ac18478a42e25cb7996eacfcc0Jeff Garzik
1909c9d39130123238ac18478a42e25cb7996eacfcc0Jeff Garzik	mv_stop_dma(ap);
1910c9d39130123238ac18478a42e25cb7996eacfcc0Jeff Garzik
1911c9d39130123238ac18478a42e25cb7996eacfcc0Jeff Garzik	mv_channel_reset(hpriv, mmio, ap->port_no);
1912c9d39130123238ac18478a42e25cb7996eacfcc0Jeff Garzik
191322374677d18c5eeefd3a283431d312b8c44fef02Jeff Garzik	__mv_phy_reset(ap, 0);
191422374677d18c5eeefd3a283431d312b8c44fef02Jeff Garzik}
191522374677d18c5eeefd3a283431d312b8c44fef02Jeff Garzik
191622374677d18c5eeefd3a283431d312b8c44fef02Jeff Garzikstatic inline void __msleep(unsigned int msec, int can_sleep)
191722374677d18c5eeefd3a283431d312b8c44fef02Jeff Garzik{
191822374677d18c5eeefd3a283431d312b8c44fef02Jeff Garzik	if (can_sleep)
191922374677d18c5eeefd3a283431d312b8c44fef02Jeff Garzik		msleep(msec);
192022374677d18c5eeefd3a283431d312b8c44fef02Jeff Garzik	else
192122374677d18c5eeefd3a283431d312b8c44fef02Jeff Garzik		mdelay(msec);
1922c9d39130123238ac18478a42e25cb7996eacfcc0Jeff Garzik}
1923c9d39130123238ac18478a42e25cb7996eacfcc0Jeff Garzik
192405b308e1df6d9d673daedb517969241f41278b52Brett Russ/**
192522374677d18c5eeefd3a283431d312b8c44fef02Jeff Garzik *      __mv_phy_reset - Perform eDMA reset followed by COMRESET
192605b308e1df6d9d673daedb517969241f41278b52Brett Russ *      @ap: ATA channel to manipulate
192705b308e1df6d9d673daedb517969241f41278b52Brett Russ *
192805b308e1df6d9d673daedb517969241f41278b52Brett Russ *      Part of this is taken from __sata_phy_reset and modified to
192905b308e1df6d9d673daedb517969241f41278b52Brett Russ *      not sleep since this routine gets called from interrupt level.
193005b308e1df6d9d673daedb517969241f41278b52Brett Russ *
193105b308e1df6d9d673daedb517969241f41278b52Brett Russ *      LOCKING:
193205b308e1df6d9d673daedb517969241f41278b52Brett Russ *      Inherited from caller.  This is coded to safe to call at
193305b308e1df6d9d673daedb517969241f41278b52Brett Russ *      interrupt level, i.e. it does not sleep.
193431961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ */
193522374677d18c5eeefd3a283431d312b8c44fef02Jeff Garzikstatic void __mv_phy_reset(struct ata_port *ap, int can_sleep)
193620f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ{
1937095fec887eaa1c38d17c0c929a6733c744a9fa1fJeff Garzik	struct mv_port_priv *pp	= ap->private_data;
1938cca3974e48607c3775dc73b544a5700b2e37c21aJeff Garzik	struct mv_host_priv *hpriv = ap->host->private_data;
193920f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ	void __iomem *port_mmio = mv_ap_base(ap);
194020f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ	struct ata_taskfile tf;
194120f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ	struct ata_device *dev = &ap->device[0];
194231961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ	unsigned long timeout;
194322374677d18c5eeefd3a283431d312b8c44fef02Jeff Garzik	int retry = 5;
194422374677d18c5eeefd3a283431d312b8c44fef02Jeff Garzik	u32 sstatus;
194520f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ
194620f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ	VPRINTK("ENTER, port %u, mmio 0x%p\n", ap->port_no, port_mmio);
194720f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ
1948095fec887eaa1c38d17c0c929a6733c744a9fa1fJeff Garzik	DPRINTK("S-regs after ATA_RST: SStat 0x%08x SErr 0x%08x "
194931961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ		"SCtrl 0x%08x\n", mv_scr_read(ap, SCR_STATUS),
195031961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ		mv_scr_read(ap, SCR_ERROR), mv_scr_read(ap, SCR_CONTROL));
195120f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ
195222374677d18c5eeefd3a283431d312b8c44fef02Jeff Garzik	/* Issue COMRESET via SControl */
195322374677d18c5eeefd3a283431d312b8c44fef02Jeff Garzikcomreset_retry:
195481952c5497b40ae56835bd0d6537f8c6bdea07e7Tejun Heo	sata_scr_write_flush(ap, SCR_CONTROL, 0x301);
195522374677d18c5eeefd3a283431d312b8c44fef02Jeff Garzik	__msleep(1, can_sleep);
195622374677d18c5eeefd3a283431d312b8c44fef02Jeff Garzik
195781952c5497b40ae56835bd0d6537f8c6bdea07e7Tejun Heo	sata_scr_write_flush(ap, SCR_CONTROL, 0x300);
195822374677d18c5eeefd3a283431d312b8c44fef02Jeff Garzik	__msleep(20, can_sleep);
195922374677d18c5eeefd3a283431d312b8c44fef02Jeff Garzik
196022374677d18c5eeefd3a283431d312b8c44fef02Jeff Garzik	timeout = jiffies + msecs_to_jiffies(200);
196131961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ	do {
196281952c5497b40ae56835bd0d6537f8c6bdea07e7Tejun Heo		sata_scr_read(ap, SCR_STATUS, &sstatus);
196381952c5497b40ae56835bd0d6537f8c6bdea07e7Tejun Heo		sstatus &= 0x3;
196422374677d18c5eeefd3a283431d312b8c44fef02Jeff Garzik		if ((sstatus == 3) || (sstatus == 0))
196531961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ			break;
196622374677d18c5eeefd3a283431d312b8c44fef02Jeff Garzik
196722374677d18c5eeefd3a283431d312b8c44fef02Jeff Garzik		__msleep(1, can_sleep);
196831961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ	} while (time_before(jiffies, timeout));
196920f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ
197022374677d18c5eeefd3a283431d312b8c44fef02Jeff Garzik	/* work around errata */
197122374677d18c5eeefd3a283431d312b8c44fef02Jeff Garzik	if (IS_60XX(hpriv) &&
197222374677d18c5eeefd3a283431d312b8c44fef02Jeff Garzik	    (sstatus != 0x0) && (sstatus != 0x113) && (sstatus != 0x123) &&
197322374677d18c5eeefd3a283431d312b8c44fef02Jeff Garzik	    (retry-- > 0))
197422374677d18c5eeefd3a283431d312b8c44fef02Jeff Garzik		goto comreset_retry;
1975095fec887eaa1c38d17c0c929a6733c744a9fa1fJeff Garzik
1976095fec887eaa1c38d17c0c929a6733c744a9fa1fJeff Garzik	DPRINTK("S-regs after PHY wake: SStat 0x%08x SErr 0x%08x "
197731961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ		"SCtrl 0x%08x\n", mv_scr_read(ap, SCR_STATUS),
197831961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ		mv_scr_read(ap, SCR_ERROR), mv_scr_read(ap, SCR_CONTROL));
197931961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ
198081952c5497b40ae56835bd0d6537f8c6bdea07e7Tejun Heo	if (ata_port_online(ap)) {
198131961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ		ata_port_probe(ap);
198231961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ	} else {
198381952c5497b40ae56835bd0d6537f8c6bdea07e7Tejun Heo		sata_scr_read(ap, SCR_STATUS, &sstatus);
1984f15a1dafed22d5037e0feea7528e1eeb28a1a7a3Tejun Heo		ata_port_printk(ap, KERN_INFO,
1985f15a1dafed22d5037e0feea7528e1eeb28a1a7a3Tejun Heo				"no device found (phy stat %08x)\n", sstatus);
198631961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ		ata_port_disable(ap);
198720f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ		return;
198820f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ	}
198931961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ	ap->cbl = ATA_CBL_SATA;
199020f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ
199122374677d18c5eeefd3a283431d312b8c44fef02Jeff Garzik	/* even after SStatus reflects that device is ready,
199222374677d18c5eeefd3a283431d312b8c44fef02Jeff Garzik	 * it seems to take a while for link to be fully
199322374677d18c5eeefd3a283431d312b8c44fef02Jeff Garzik	 * established (and thus Status no longer 0x80/0x7F),
199422374677d18c5eeefd3a283431d312b8c44fef02Jeff Garzik	 * so we poll a bit for that, here.
199522374677d18c5eeefd3a283431d312b8c44fef02Jeff Garzik	 */
199622374677d18c5eeefd3a283431d312b8c44fef02Jeff Garzik	retry = 20;
199722374677d18c5eeefd3a283431d312b8c44fef02Jeff Garzik	while (1) {
199822374677d18c5eeefd3a283431d312b8c44fef02Jeff Garzik		u8 drv_stat = ata_check_status(ap);
199922374677d18c5eeefd3a283431d312b8c44fef02Jeff Garzik		if ((drv_stat != 0x80) && (drv_stat != 0x7f))
200022374677d18c5eeefd3a283431d312b8c44fef02Jeff Garzik			break;
200122374677d18c5eeefd3a283431d312b8c44fef02Jeff Garzik		__msleep(500, can_sleep);
200222374677d18c5eeefd3a283431d312b8c44fef02Jeff Garzik		if (retry-- <= 0)
200322374677d18c5eeefd3a283431d312b8c44fef02Jeff Garzik			break;
200422374677d18c5eeefd3a283431d312b8c44fef02Jeff Garzik	}
200522374677d18c5eeefd3a283431d312b8c44fef02Jeff Garzik
200620f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ	tf.lbah = readb((void __iomem *) ap->ioaddr.lbah_addr);
200720f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ	tf.lbam = readb((void __iomem *) ap->ioaddr.lbam_addr);
200820f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ	tf.lbal = readb((void __iomem *) ap->ioaddr.lbal_addr);
200920f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ	tf.nsect = readb((void __iomem *) ap->ioaddr.nsect_addr);
201020f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ
201120f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ	dev->class = ata_dev_classify(&tf);
2012e1211e3fa7fd05ff0d4f597fd37e40de8acc6784Tejun Heo	if (!ata_dev_enabled(dev)) {
201320f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ		VPRINTK("Port disabled post-sig: No device present.\n");
201420f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ		ata_port_disable(ap);
201520f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ	}
2016095fec887eaa1c38d17c0c929a6733c744a9fa1fJeff Garzik
2017095fec887eaa1c38d17c0c929a6733c744a9fa1fJeff Garzik	writelfl(0, port_mmio + EDMA_ERR_IRQ_CAUSE_OFS);
2018095fec887eaa1c38d17c0c929a6733c744a9fa1fJeff Garzik
2019095fec887eaa1c38d17c0c929a6733c744a9fa1fJeff Garzik	pp->pp_flags &= ~MV_PP_FLAG_EDMA_EN;
2020095fec887eaa1c38d17c0c929a6733c744a9fa1fJeff Garzik
2021bca1c4eb9411533d613123618c0d127fae532595Jeff Garzik	VPRINTK("EXIT\n");
202220f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ}
202320f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ
202422374677d18c5eeefd3a283431d312b8c44fef02Jeff Garzikstatic void mv_phy_reset(struct ata_port *ap)
202522374677d18c5eeefd3a283431d312b8c44fef02Jeff Garzik{
202622374677d18c5eeefd3a283431d312b8c44fef02Jeff Garzik	__mv_phy_reset(ap, 1);
202722374677d18c5eeefd3a283431d312b8c44fef02Jeff Garzik}
202822374677d18c5eeefd3a283431d312b8c44fef02Jeff Garzik
202905b308e1df6d9d673daedb517969241f41278b52Brett Russ/**
203005b308e1df6d9d673daedb517969241f41278b52Brett Russ *      mv_eng_timeout - Routine called by libata when SCSI times out I/O
203105b308e1df6d9d673daedb517969241f41278b52Brett Russ *      @ap: ATA channel to manipulate
203205b308e1df6d9d673daedb517969241f41278b52Brett Russ *
203305b308e1df6d9d673daedb517969241f41278b52Brett Russ *      Intent is to clear all pending error conditions, reset the
203405b308e1df6d9d673daedb517969241f41278b52Brett Russ *      chip/bus, fail the command, and move on.
203505b308e1df6d9d673daedb517969241f41278b52Brett Russ *
203605b308e1df6d9d673daedb517969241f41278b52Brett Russ *      LOCKING:
2037cca3974e48607c3775dc73b544a5700b2e37c21aJeff Garzik *      This routine holds the host lock while failing the command.
203805b308e1df6d9d673daedb517969241f41278b52Brett Russ */
203931961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russstatic void mv_eng_timeout(struct ata_port *ap)
204031961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ{
204131961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ	struct ata_queued_cmd *qc;
20422f9719b61e1fcf7422a016ac4f2420a0cc6ba320Mark Lord	unsigned long flags;
204331961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ
2044f15a1dafed22d5037e0feea7528e1eeb28a1a7a3Tejun Heo	ata_port_printk(ap, KERN_ERR, "Entering mv_eng_timeout\n");
204531961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ	DPRINTK("All regs @ start of eng_timeout\n");
2046cca3974e48607c3775dc73b544a5700b2e37c21aJeff Garzik	mv_dump_all_regs(ap->host->mmio_base, ap->port_no,
2047cca3974e48607c3775dc73b544a5700b2e37c21aJeff Garzik			 to_pci_dev(ap->host->dev));
204831961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ
204931961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ	qc = ata_qc_from_tag(ap, ap->active_tag);
205031961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ        printk(KERN_ERR "mmio_base %p ap %p qc %p scsi_cmnd %p &cmnd %p\n",
2051cca3974e48607c3775dc73b544a5700b2e37c21aJeff Garzik	       ap->host->mmio_base, ap, qc, qc->scsicmd, &qc->scsicmd->cmnd);
205231961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ
2053cca3974e48607c3775dc73b544a5700b2e37c21aJeff Garzik	spin_lock_irqsave(&ap->host->lock, flags);
20549b358e305c1d783c8a4ebf00344e95deb9e38f3dMark Lord	mv_err_intr(ap, 0);
2055c9d39130123238ac18478a42e25cb7996eacfcc0Jeff Garzik	mv_stop_and_reset(ap);
2056cca3974e48607c3775dc73b544a5700b2e37c21aJeff Garzik	spin_unlock_irqrestore(&ap->host->lock, flags);
205731961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ
20589b358e305c1d783c8a4ebf00344e95deb9e38f3dMark Lord	WARN_ON(!(qc->flags & ATA_QCFLAG_ACTIVE));
20599b358e305c1d783c8a4ebf00344e95deb9e38f3dMark Lord	if (qc->flags & ATA_QCFLAG_ACTIVE) {
20609b358e305c1d783c8a4ebf00344e95deb9e38f3dMark Lord		qc->err_mask |= AC_ERR_TIMEOUT;
20619b358e305c1d783c8a4ebf00344e95deb9e38f3dMark Lord		ata_eh_qc_complete(qc);
20629b358e305c1d783c8a4ebf00344e95deb9e38f3dMark Lord	}
206331961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ}
206431961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ
206505b308e1df6d9d673daedb517969241f41278b52Brett Russ/**
206605b308e1df6d9d673daedb517969241f41278b52Brett Russ *      mv_port_init - Perform some early initialization on a single port.
206705b308e1df6d9d673daedb517969241f41278b52Brett Russ *      @port: libata data structure storing shadow register addresses
206805b308e1df6d9d673daedb517969241f41278b52Brett Russ *      @port_mmio: base address of the port
206905b308e1df6d9d673daedb517969241f41278b52Brett Russ *
207005b308e1df6d9d673daedb517969241f41278b52Brett Russ *      Initialize shadow register mmio addresses, clear outstanding
207105b308e1df6d9d673daedb517969241f41278b52Brett Russ *      interrupts on the port, and unmask interrupts for the future
207205b308e1df6d9d673daedb517969241f41278b52Brett Russ *      start of the port.
207305b308e1df6d9d673daedb517969241f41278b52Brett Russ *
207405b308e1df6d9d673daedb517969241f41278b52Brett Russ *      LOCKING:
207505b308e1df6d9d673daedb517969241f41278b52Brett Russ *      Inherited from caller.
207605b308e1df6d9d673daedb517969241f41278b52Brett Russ */
207731961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russstatic void mv_port_init(struct ata_ioports *port,  void __iomem *port_mmio)
207820f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ{
207931961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ	unsigned long shd_base = (unsigned long) port_mmio + SHD_BLK_OFS;
208031961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ	unsigned serr_ofs;
208131961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ
20828b260248d9e0e8b64bb72fd4dee03ad86984c344Jeff Garzik	/* PIO related setup
208331961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ	 */
208431961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ	port->data_addr = shd_base + (sizeof(u32) * ATA_REG_DATA);
20858b260248d9e0e8b64bb72fd4dee03ad86984c344Jeff Garzik	port->error_addr =
208631961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ		port->feature_addr = shd_base + (sizeof(u32) * ATA_REG_ERR);
208731961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ	port->nsect_addr = shd_base + (sizeof(u32) * ATA_REG_NSECT);
208831961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ	port->lbal_addr = shd_base + (sizeof(u32) * ATA_REG_LBAL);
208931961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ	port->lbam_addr = shd_base + (sizeof(u32) * ATA_REG_LBAM);
209031961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ	port->lbah_addr = shd_base + (sizeof(u32) * ATA_REG_LBAH);
209131961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ	port->device_addr = shd_base + (sizeof(u32) * ATA_REG_DEVICE);
20928b260248d9e0e8b64bb72fd4dee03ad86984c344Jeff Garzik	port->status_addr =
209331961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ		port->command_addr = shd_base + (sizeof(u32) * ATA_REG_STATUS);
209431961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ	/* special case: control/altstatus doesn't have ATA_REG_ address */
209531961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ	port->altstatus_addr = port->ctl_addr = shd_base + SHD_CTL_AST_OFS;
209631961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ
209731961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ	/* unused: */
209820f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ	port->cmd_addr = port->bmdma_addr = port->scr_addr = 0;
209920f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ
210031961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ	/* Clear any currently outstanding port interrupt conditions */
210131961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ	serr_ofs = mv_scr_offset(SCR_ERROR);
210231961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ	writelfl(readl(port_mmio + serr_ofs), port_mmio + serr_ofs);
210331961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ	writelfl(0, port_mmio + EDMA_ERR_IRQ_CAUSE_OFS);
210431961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ
210520f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ	/* unmask all EDMA error interrupts */
210631961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ	writelfl(~0, port_mmio + EDMA_ERR_IRQ_MASK_OFS);
210720f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ
21088b260248d9e0e8b64bb72fd4dee03ad86984c344Jeff Garzik	VPRINTK("EDMA cfg=0x%08x EDMA IRQ err cause/mask=0x%08x/0x%08x\n",
210931961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ		readl(port_mmio + EDMA_CFG_OFS),
211031961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ		readl(port_mmio + EDMA_ERR_IRQ_CAUSE_OFS),
211131961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ		readl(port_mmio + EDMA_ERR_IRQ_MASK_OFS));
211220f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ}
211320f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ
211447c2b677daeed9c79ecb7167c211ff36876ea611Jeff Garzikstatic int mv_chip_id(struct pci_dev *pdev, struct mv_host_priv *hpriv,
2115522479fb98c6667f081e75f87e298e413c0b1db8Jeff Garzik		      unsigned int board_idx)
2116bca1c4eb9411533d613123618c0d127fae532595Jeff Garzik{
2117bca1c4eb9411533d613123618c0d127fae532595Jeff Garzik	u8 rev_id;
2118bca1c4eb9411533d613123618c0d127fae532595Jeff Garzik	u32 hp_flags = hpriv->hp_flags;
2119bca1c4eb9411533d613123618c0d127fae532595Jeff Garzik
2120bca1c4eb9411533d613123618c0d127fae532595Jeff Garzik	pci_read_config_byte(pdev, PCI_REVISION_ID, &rev_id);
2121bca1c4eb9411533d613123618c0d127fae532595Jeff Garzik
2122bca1c4eb9411533d613123618c0d127fae532595Jeff Garzik	switch(board_idx) {
212347c2b677daeed9c79ecb7167c211ff36876ea611Jeff Garzik	case chip_5080:
212447c2b677daeed9c79ecb7167c211ff36876ea611Jeff Garzik		hpriv->ops = &mv5xxx_ops;
212547c2b677daeed9c79ecb7167c211ff36876ea611Jeff Garzik		hp_flags |= MV_HP_50XX;
212647c2b677daeed9c79ecb7167c211ff36876ea611Jeff Garzik
212747c2b677daeed9c79ecb7167c211ff36876ea611Jeff Garzik		switch (rev_id) {
212847c2b677daeed9c79ecb7167c211ff36876ea611Jeff Garzik		case 0x1:
212947c2b677daeed9c79ecb7167c211ff36876ea611Jeff Garzik			hp_flags |= MV_HP_ERRATA_50XXB0;
213047c2b677daeed9c79ecb7167c211ff36876ea611Jeff Garzik			break;
213147c2b677daeed9c79ecb7167c211ff36876ea611Jeff Garzik		case 0x3:
213247c2b677daeed9c79ecb7167c211ff36876ea611Jeff Garzik			hp_flags |= MV_HP_ERRATA_50XXB2;
213347c2b677daeed9c79ecb7167c211ff36876ea611Jeff Garzik			break;
213447c2b677daeed9c79ecb7167c211ff36876ea611Jeff Garzik		default:
213547c2b677daeed9c79ecb7167c211ff36876ea611Jeff Garzik			dev_printk(KERN_WARNING, &pdev->dev,
213647c2b677daeed9c79ecb7167c211ff36876ea611Jeff Garzik			   "Applying 50XXB2 workarounds to unknown rev\n");
213747c2b677daeed9c79ecb7167c211ff36876ea611Jeff Garzik			hp_flags |= MV_HP_ERRATA_50XXB2;
213847c2b677daeed9c79ecb7167c211ff36876ea611Jeff Garzik			break;
213947c2b677daeed9c79ecb7167c211ff36876ea611Jeff Garzik		}
214047c2b677daeed9c79ecb7167c211ff36876ea611Jeff Garzik		break;
214147c2b677daeed9c79ecb7167c211ff36876ea611Jeff Garzik
2142bca1c4eb9411533d613123618c0d127fae532595Jeff Garzik	case chip_504x:
2143bca1c4eb9411533d613123618c0d127fae532595Jeff Garzik	case chip_508x:
214447c2b677daeed9c79ecb7167c211ff36876ea611Jeff Garzik		hpriv->ops = &mv5xxx_ops;
2145bca1c4eb9411533d613123618c0d127fae532595Jeff Garzik		hp_flags |= MV_HP_50XX;
2146bca1c4eb9411533d613123618c0d127fae532595Jeff Garzik
214747c2b677daeed9c79ecb7167c211ff36876ea611Jeff Garzik		switch (rev_id) {
214847c2b677daeed9c79ecb7167c211ff36876ea611Jeff Garzik		case 0x0:
214947c2b677daeed9c79ecb7167c211ff36876ea611Jeff Garzik			hp_flags |= MV_HP_ERRATA_50XXB0;
215047c2b677daeed9c79ecb7167c211ff36876ea611Jeff Garzik			break;
215147c2b677daeed9c79ecb7167c211ff36876ea611Jeff Garzik		case 0x3:
215247c2b677daeed9c79ecb7167c211ff36876ea611Jeff Garzik			hp_flags |= MV_HP_ERRATA_50XXB2;
215347c2b677daeed9c79ecb7167c211ff36876ea611Jeff Garzik			break;
215447c2b677daeed9c79ecb7167c211ff36876ea611Jeff Garzik		default:
215547c2b677daeed9c79ecb7167c211ff36876ea611Jeff Garzik			dev_printk(KERN_WARNING, &pdev->dev,
215647c2b677daeed9c79ecb7167c211ff36876ea611Jeff Garzik			   "Applying B2 workarounds to unknown rev\n");
215747c2b677daeed9c79ecb7167c211ff36876ea611Jeff Garzik			hp_flags |= MV_HP_ERRATA_50XXB2;
215847c2b677daeed9c79ecb7167c211ff36876ea611Jeff Garzik			break;
2159bca1c4eb9411533d613123618c0d127fae532595Jeff Garzik		}
2160bca1c4eb9411533d613123618c0d127fae532595Jeff Garzik		break;
2161bca1c4eb9411533d613123618c0d127fae532595Jeff Garzik
2162bca1c4eb9411533d613123618c0d127fae532595Jeff Garzik	case chip_604x:
2163bca1c4eb9411533d613123618c0d127fae532595Jeff Garzik	case chip_608x:
216447c2b677daeed9c79ecb7167c211ff36876ea611Jeff Garzik		hpriv->ops = &mv6xxx_ops;
216547c2b677daeed9c79ecb7167c211ff36876ea611Jeff Garzik
2166bca1c4eb9411533d613123618c0d127fae532595Jeff Garzik		switch (rev_id) {
216747c2b677daeed9c79ecb7167c211ff36876ea611Jeff Garzik		case 0x7:
216847c2b677daeed9c79ecb7167c211ff36876ea611Jeff Garzik			hp_flags |= MV_HP_ERRATA_60X1B2;
216947c2b677daeed9c79ecb7167c211ff36876ea611Jeff Garzik			break;
217047c2b677daeed9c79ecb7167c211ff36876ea611Jeff Garzik		case 0x9:
217147c2b677daeed9c79ecb7167c211ff36876ea611Jeff Garzik			hp_flags |= MV_HP_ERRATA_60X1C0;
2172bca1c4eb9411533d613123618c0d127fae532595Jeff Garzik			break;
2173bca1c4eb9411533d613123618c0d127fae532595Jeff Garzik		default:
2174bca1c4eb9411533d613123618c0d127fae532595Jeff Garzik			dev_printk(KERN_WARNING, &pdev->dev,
217547c2b677daeed9c79ecb7167c211ff36876ea611Jeff Garzik				   "Applying B2 workarounds to unknown rev\n");
217647c2b677daeed9c79ecb7167c211ff36876ea611Jeff Garzik			hp_flags |= MV_HP_ERRATA_60X1B2;
2177bca1c4eb9411533d613123618c0d127fae532595Jeff Garzik			break;
2178bca1c4eb9411533d613123618c0d127fae532595Jeff Garzik		}
2179bca1c4eb9411533d613123618c0d127fae532595Jeff Garzik		break;
2180bca1c4eb9411533d613123618c0d127fae532595Jeff Garzik
2181e4e7b89280d1d666e2c09e5ad36cf071796c4c7eJeff Garzik	case chip_7042:
2182e4e7b89280d1d666e2c09e5ad36cf071796c4c7eJeff Garzik	case chip_6042:
2183e4e7b89280d1d666e2c09e5ad36cf071796c4c7eJeff Garzik		hpriv->ops = &mv6xxx_ops;
2184e4e7b89280d1d666e2c09e5ad36cf071796c4c7eJeff Garzik
2185e4e7b89280d1d666e2c09e5ad36cf071796c4c7eJeff Garzik		hp_flags |= MV_HP_GEN_IIE;
2186e4e7b89280d1d666e2c09e5ad36cf071796c4c7eJeff Garzik
2187e4e7b89280d1d666e2c09e5ad36cf071796c4c7eJeff Garzik		switch (rev_id) {
2188e4e7b89280d1d666e2c09e5ad36cf071796c4c7eJeff Garzik		case 0x0:
2189e4e7b89280d1d666e2c09e5ad36cf071796c4c7eJeff Garzik			hp_flags |= MV_HP_ERRATA_XX42A0;
2190e4e7b89280d1d666e2c09e5ad36cf071796c4c7eJeff Garzik			break;
2191e4e7b89280d1d666e2c09e5ad36cf071796c4c7eJeff Garzik		case 0x1:
2192e4e7b89280d1d666e2c09e5ad36cf071796c4c7eJeff Garzik			hp_flags |= MV_HP_ERRATA_60X1C0;
2193e4e7b89280d1d666e2c09e5ad36cf071796c4c7eJeff Garzik			break;
2194e4e7b89280d1d666e2c09e5ad36cf071796c4c7eJeff Garzik		default:
2195e4e7b89280d1d666e2c09e5ad36cf071796c4c7eJeff Garzik			dev_printk(KERN_WARNING, &pdev->dev,
2196e4e7b89280d1d666e2c09e5ad36cf071796c4c7eJeff Garzik			   "Applying 60X1C0 workarounds to unknown rev\n");
2197e4e7b89280d1d666e2c09e5ad36cf071796c4c7eJeff Garzik			hp_flags |= MV_HP_ERRATA_60X1C0;
2198e4e7b89280d1d666e2c09e5ad36cf071796c4c7eJeff Garzik			break;
2199e4e7b89280d1d666e2c09e5ad36cf071796c4c7eJeff Garzik		}
2200e4e7b89280d1d666e2c09e5ad36cf071796c4c7eJeff Garzik		break;
2201e4e7b89280d1d666e2c09e5ad36cf071796c4c7eJeff Garzik
2202bca1c4eb9411533d613123618c0d127fae532595Jeff Garzik	default:
2203bca1c4eb9411533d613123618c0d127fae532595Jeff Garzik		printk(KERN_ERR DRV_NAME ": BUG: invalid board index %u\n", board_idx);
2204bca1c4eb9411533d613123618c0d127fae532595Jeff Garzik		return 1;
2205bca1c4eb9411533d613123618c0d127fae532595Jeff Garzik	}
2206bca1c4eb9411533d613123618c0d127fae532595Jeff Garzik
2207bca1c4eb9411533d613123618c0d127fae532595Jeff Garzik	hpriv->hp_flags = hp_flags;
2208bca1c4eb9411533d613123618c0d127fae532595Jeff Garzik
2209bca1c4eb9411533d613123618c0d127fae532595Jeff Garzik	return 0;
2210bca1c4eb9411533d613123618c0d127fae532595Jeff Garzik}
2211bca1c4eb9411533d613123618c0d127fae532595Jeff Garzik
221205b308e1df6d9d673daedb517969241f41278b52Brett Russ/**
221347c2b677daeed9c79ecb7167c211ff36876ea611Jeff Garzik *      mv_init_host - Perform some early initialization of the host.
2214bca1c4eb9411533d613123618c0d127fae532595Jeff Garzik *	@pdev: host PCI device
221505b308e1df6d9d673daedb517969241f41278b52Brett Russ *      @probe_ent: early data struct representing the host
221605b308e1df6d9d673daedb517969241f41278b52Brett Russ *
221705b308e1df6d9d673daedb517969241f41278b52Brett Russ *      If possible, do an early global reset of the host.  Then do
221805b308e1df6d9d673daedb517969241f41278b52Brett Russ *      our port init and clear/unmask all/relevant host interrupts.
221905b308e1df6d9d673daedb517969241f41278b52Brett Russ *
222005b308e1df6d9d673daedb517969241f41278b52Brett Russ *      LOCKING:
222105b308e1df6d9d673daedb517969241f41278b52Brett Russ *      Inherited from caller.
222205b308e1df6d9d673daedb517969241f41278b52Brett Russ */
222347c2b677daeed9c79ecb7167c211ff36876ea611Jeff Garzikstatic int mv_init_host(struct pci_dev *pdev, struct ata_probe_ent *probe_ent,
2224bca1c4eb9411533d613123618c0d127fae532595Jeff Garzik			unsigned int board_idx)
222520f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ{
222620f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ	int rc = 0, n_hc, port, hc;
222720f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ	void __iomem *mmio = probe_ent->mmio_base;
2228bca1c4eb9411533d613123618c0d127fae532595Jeff Garzik	struct mv_host_priv *hpriv = probe_ent->private_data;
2229bca1c4eb9411533d613123618c0d127fae532595Jeff Garzik
223047c2b677daeed9c79ecb7167c211ff36876ea611Jeff Garzik	/* global interrupt mask */
223147c2b677daeed9c79ecb7167c211ff36876ea611Jeff Garzik	writel(0, mmio + HC_MAIN_IRQ_MASK_OFS);
223247c2b677daeed9c79ecb7167c211ff36876ea611Jeff Garzik
223347c2b677daeed9c79ecb7167c211ff36876ea611Jeff Garzik	rc = mv_chip_id(pdev, hpriv, board_idx);
2234bca1c4eb9411533d613123618c0d127fae532595Jeff Garzik	if (rc)
2235bca1c4eb9411533d613123618c0d127fae532595Jeff Garzik		goto done;
2236bca1c4eb9411533d613123618c0d127fae532595Jeff Garzik
2237cca3974e48607c3775dc73b544a5700b2e37c21aJeff Garzik	n_hc = mv_get_hc_count(probe_ent->port_flags);
2238bca1c4eb9411533d613123618c0d127fae532595Jeff Garzik	probe_ent->n_ports = MV_PORTS_PER_HC * n_hc;
2239bca1c4eb9411533d613123618c0d127fae532595Jeff Garzik
224047c2b677daeed9c79ecb7167c211ff36876ea611Jeff Garzik	for (port = 0; port < probe_ent->n_ports; port++)
224147c2b677daeed9c79ecb7167c211ff36876ea611Jeff Garzik		hpriv->ops->read_preamp(hpriv, port, mmio);
224220f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ
2243c9d39130123238ac18478a42e25cb7996eacfcc0Jeff Garzik	rc = hpriv->ops->reset_hc(hpriv, mmio, n_hc);
224447c2b677daeed9c79ecb7167c211ff36876ea611Jeff Garzik	if (rc)
224520f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ		goto done;
224620f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ
2247522479fb98c6667f081e75f87e298e413c0b1db8Jeff Garzik	hpriv->ops->reset_flash(hpriv, mmio);
2248522479fb98c6667f081e75f87e298e413c0b1db8Jeff Garzik	hpriv->ops->reset_bus(pdev, mmio);
224947c2b677daeed9c79ecb7167c211ff36876ea611Jeff Garzik	hpriv->ops->enable_leds(hpriv, mmio);
225020f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ
225120f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ	for (port = 0; port < probe_ent->n_ports; port++) {
22522a47ce06d534692f9bd2bf4e90a20fc9b1054c39Jeff Garzik		if (IS_60XX(hpriv)) {
2253c9d39130123238ac18478a42e25cb7996eacfcc0Jeff Garzik			void __iomem *port_mmio = mv_port_base(mmio, port);
2254c9d39130123238ac18478a42e25cb7996eacfcc0Jeff Garzik
22552a47ce06d534692f9bd2bf4e90a20fc9b1054c39Jeff Garzik			u32 ifctl = readl(port_mmio + SATA_INTERFACE_CTL);
2256eb46d684600ac145501805a294c94675e82eab2eMark Lord			ifctl |= (1 << 7);		/* enable gen2i speed */
2257eb46d684600ac145501805a294c94675e82eab2eMark Lord			ifctl = (ifctl & 0xfff) | 0x9b1000; /* from chip spec */
22582a47ce06d534692f9bd2bf4e90a20fc9b1054c39Jeff Garzik			writelfl(ifctl, port_mmio + SATA_INTERFACE_CTL);
22592a47ce06d534692f9bd2bf4e90a20fc9b1054c39Jeff Garzik		}
22602a47ce06d534692f9bd2bf4e90a20fc9b1054c39Jeff Garzik
2261c9d39130123238ac18478a42e25cb7996eacfcc0Jeff Garzik		hpriv->ops->phy_errata(hpriv, mmio, port);
22622a47ce06d534692f9bd2bf4e90a20fc9b1054c39Jeff Garzik	}
22632a47ce06d534692f9bd2bf4e90a20fc9b1054c39Jeff Garzik
22642a47ce06d534692f9bd2bf4e90a20fc9b1054c39Jeff Garzik	for (port = 0; port < probe_ent->n_ports; port++) {
22652a47ce06d534692f9bd2bf4e90a20fc9b1054c39Jeff Garzik		void __iomem *port_mmio = mv_port_base(mmio, port);
226631961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ		mv_port_init(&probe_ent->port[port], port_mmio);
226720f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ	}
226820f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ
226920f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ	for (hc = 0; hc < n_hc; hc++) {
227031961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ		void __iomem *hc_mmio = mv_hc_base(mmio, hc);
227131961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ
227231961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ		VPRINTK("HC%i: HC config=0x%08x HC IRQ cause "
227331961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ			"(before clear)=0x%08x\n", hc,
227431961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ			readl(hc_mmio + HC_CFG_OFS),
227531961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ			readl(hc_mmio + HC_IRQ_CAUSE_OFS));
227631961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ
227731961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ		/* Clear any currently outstanding hc interrupt conditions */
227831961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ		writelfl(0, hc_mmio + HC_IRQ_CAUSE_OFS);
227920f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ	}
228020f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ
228131961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ	/* Clear any currently outstanding host interrupt conditions */
228231961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ	writelfl(0, mmio + PCI_IRQ_CAUSE_OFS);
228331961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ
228431961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ	/* and unmask interrupt generation for host regs */
228531961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ	writelfl(PCI_UNMASK_ALL_IRQS, mmio + PCI_IRQ_MASK_OFS);
228631961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ	writelfl(~HC_MAIN_MASKED_IRQS, mmio + HC_MAIN_IRQ_MASK_OFS);
228720f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ
228820f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ	VPRINTK("HC MAIN IRQ cause/mask=0x%08x/0x%08x "
22898b260248d9e0e8b64bb72fd4dee03ad86984c344Jeff Garzik		"PCI int cause/mask=0x%08x/0x%08x\n",
229020f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ		readl(mmio + HC_MAIN_IRQ_CAUSE_OFS),
229120f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ		readl(mmio + HC_MAIN_IRQ_MASK_OFS),
229220f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ		readl(mmio + PCI_IRQ_CAUSE_OFS),
229320f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ		readl(mmio + PCI_IRQ_MASK_OFS));
2294bca1c4eb9411533d613123618c0d127fae532595Jeff Garzik
229531961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russdone:
229620f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ	return rc;
229720f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ}
229820f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ
229905b308e1df6d9d673daedb517969241f41278b52Brett Russ/**
230005b308e1df6d9d673daedb517969241f41278b52Brett Russ *      mv_print_info - Dump key info to kernel log for perusal.
230105b308e1df6d9d673daedb517969241f41278b52Brett Russ *      @probe_ent: early data struct representing the host
230205b308e1df6d9d673daedb517969241f41278b52Brett Russ *
230305b308e1df6d9d673daedb517969241f41278b52Brett Russ *      FIXME: complete this.
230405b308e1df6d9d673daedb517969241f41278b52Brett Russ *
230505b308e1df6d9d673daedb517969241f41278b52Brett Russ *      LOCKING:
230605b308e1df6d9d673daedb517969241f41278b52Brett Russ *      Inherited from caller.
230705b308e1df6d9d673daedb517969241f41278b52Brett Russ */
230831961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russstatic void mv_print_info(struct ata_probe_ent *probe_ent)
230931961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ{
231031961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ	struct pci_dev *pdev = to_pci_dev(probe_ent->dev);
231131961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ	struct mv_host_priv *hpriv = probe_ent->private_data;
231231961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ	u8 rev_id, scc;
231331961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ	const char *scc_s;
231431961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ
231531961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ	/* Use this to determine the HW stepping of the chip so we know
231631961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ	 * what errata to workaround
231731961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ	 */
231831961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ	pci_read_config_byte(pdev, PCI_REVISION_ID, &rev_id);
231931961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ
232031961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ	pci_read_config_byte(pdev, PCI_CLASS_DEVICE, &scc);
232131961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ	if (scc == 0)
232231961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ		scc_s = "SCSI";
232331961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ	else if (scc == 0x01)
232431961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ		scc_s = "RAID";
232531961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ	else
232631961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ		scc_s = "unknown";
232731961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ
2328a9524a76f70f3343e4be27f95a7e92a8ba5f9009Jeff Garzik	dev_printk(KERN_INFO, &pdev->dev,
2329a9524a76f70f3343e4be27f95a7e92a8ba5f9009Jeff Garzik	       "%u slots %u ports %s mode IRQ via %s\n",
23308b260248d9e0e8b64bb72fd4dee03ad86984c344Jeff Garzik	       (unsigned)MV_MAX_Q_DEPTH, probe_ent->n_ports,
233131961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ	       scc_s, (MV_HP_FLAG_MSI & hpriv->hp_flags) ? "MSI" : "INTx");
233231961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ}
233331961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ
233405b308e1df6d9d673daedb517969241f41278b52Brett Russ/**
233505b308e1df6d9d673daedb517969241f41278b52Brett Russ *      mv_init_one - handle a positive probe of a Marvell host
233605b308e1df6d9d673daedb517969241f41278b52Brett Russ *      @pdev: PCI device found
233705b308e1df6d9d673daedb517969241f41278b52Brett Russ *      @ent: PCI device ID entry for the matched host
233805b308e1df6d9d673daedb517969241f41278b52Brett Russ *
233905b308e1df6d9d673daedb517969241f41278b52Brett Russ *      LOCKING:
234005b308e1df6d9d673daedb517969241f41278b52Brett Russ *      Inherited from caller.
234105b308e1df6d9d673daedb517969241f41278b52Brett Russ */
234220f733e7d75a16bffc34842b7682c9247dd5f954Brett Russstatic int mv_init_one(struct pci_dev *pdev, const struct pci_device_id *ent)
234320f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ{
234420f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ	static int printed_version = 0;
234520f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ	struct ata_probe_ent *probe_ent = NULL;
234620f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ	struct mv_host_priv *hpriv;
234720f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ	unsigned int board_idx = (unsigned int)ent->driver_data;
234820f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ	void __iomem *mmio_base;
234931961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ	int pci_dev_busy = 0, rc;
235020f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ
2351a9524a76f70f3343e4be27f95a7e92a8ba5f9009Jeff Garzik	if (!printed_version++)
2352a9524a76f70f3343e4be27f95a7e92a8ba5f9009Jeff Garzik		dev_printk(KERN_INFO, &pdev->dev, "version " DRV_VERSION "\n");
235320f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ
235420f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ	rc = pci_enable_device(pdev);
235520f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ	if (rc) {
235620f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ		return rc;
235720f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ	}
2358eb46d684600ac145501805a294c94675e82eab2eMark Lord	pci_set_master(pdev);
235920f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ
236020f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ	rc = pci_request_regions(pdev, DRV_NAME);
236120f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ	if (rc) {
236220f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ		pci_dev_busy = 1;
236320f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ		goto err_out;
236420f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ	}
236520f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ
236620f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ	probe_ent = kmalloc(sizeof(*probe_ent), GFP_KERNEL);
236720f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ	if (probe_ent == NULL) {
236820f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ		rc = -ENOMEM;
236920f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ		goto err_out_regions;
237020f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ	}
237120f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ
237220f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ	memset(probe_ent, 0, sizeof(*probe_ent));
237320f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ	probe_ent->dev = pci_dev_to_dev(pdev);
237420f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ	INIT_LIST_HEAD(&probe_ent->node);
237520f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ
237631961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ	mmio_base = pci_iomap(pdev, MV_PRIMARY_BAR, 0);
237720f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ	if (mmio_base == NULL) {
237820f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ		rc = -ENOMEM;
237920f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ		goto err_out_free_ent;
238020f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ	}
238120f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ
238220f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ	hpriv = kmalloc(sizeof(*hpriv), GFP_KERNEL);
238320f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ	if (!hpriv) {
238420f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ		rc = -ENOMEM;
238520f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ		goto err_out_iounmap;
238620f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ	}
238720f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ	memset(hpriv, 0, sizeof(*hpriv));
238820f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ
238920f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ	probe_ent->sht = mv_port_info[board_idx].sht;
2390cca3974e48607c3775dc73b544a5700b2e37c21aJeff Garzik	probe_ent->port_flags = mv_port_info[board_idx].flags;
239120f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ	probe_ent->pio_mask = mv_port_info[board_idx].pio_mask;
239220f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ	probe_ent->udma_mask = mv_port_info[board_idx].udma_mask;
239320f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ	probe_ent->port_ops = mv_port_info[board_idx].port_ops;
239420f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ
239520f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ	probe_ent->irq = pdev->irq;
23961d6f359a2e06296418481239f8054a878f36e819Thomas Gleixner	probe_ent->irq_flags = IRQF_SHARED;
239720f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ	probe_ent->mmio_base = mmio_base;
239820f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ	probe_ent->private_data = hpriv;
239920f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ
240020f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ	/* initialize adapter */
240147c2b677daeed9c79ecb7167c211ff36876ea611Jeff Garzik	rc = mv_init_host(pdev, probe_ent, board_idx);
240220f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ	if (rc) {
240320f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ		goto err_out_hpriv;
240420f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ	}
240520f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ
240631961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ	/* Enable interrupts */
2407ddef9bb367b19383df627e388cb4c01c86ddba6cJeff Garzik	if (msi && pci_enable_msi(pdev) == 0) {
240831961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ		hpriv->hp_flags |= MV_HP_FLAG_MSI;
240931961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ	} else {
241031961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ		pci_intx(pdev, 1);
241120f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ	}
241220f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ
241331961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ	mv_dump_pci_cfg(pdev, 0x68);
241431961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ	mv_print_info(probe_ent);
241531961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ
241631961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ	if (ata_device_add(probe_ent) == 0) {
241731961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ		rc = -ENODEV;		/* No devices discovered */
241831961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ		goto err_out_dev_add;
241931961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ	}
242020f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ
242131961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ	kfree(probe_ent);
242220f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ	return 0;
242320f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ
242431961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russerr_out_dev_add:
242531961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ	if (MV_HP_FLAG_MSI & hpriv->hp_flags) {
242631961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ		pci_disable_msi(pdev);
242731961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ	} else {
242831961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ		pci_intx(pdev, 0);
242931961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ	}
243031961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russerr_out_hpriv:
243120f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ	kfree(hpriv);
243231961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russerr_out_iounmap:
243331961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ	pci_iounmap(pdev, mmio_base);
243431961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russerr_out_free_ent:
243520f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ	kfree(probe_ent);
243631961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russerr_out_regions:
243720f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ	pci_release_regions(pdev);
243831961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russerr_out:
243920f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ	if (!pci_dev_busy) {
244020f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ		pci_disable_device(pdev);
244120f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ	}
244220f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ
244320f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ	return rc;
244420f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ}
244520f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ
244620f733e7d75a16bffc34842b7682c9247dd5f954Brett Russstatic int __init mv_init(void)
244720f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ{
2448b7887196e38da54ff893897b80875d632d1a1114Pavel Roskin	return pci_register_driver(&mv_pci_driver);
244920f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ}
245020f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ
245120f733e7d75a16bffc34842b7682c9247dd5f954Brett Russstatic void __exit mv_exit(void)
245220f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ{
245320f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ	pci_unregister_driver(&mv_pci_driver);
245420f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ}
245520f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ
245620f733e7d75a16bffc34842b7682c9247dd5f954Brett RussMODULE_AUTHOR("Brett Russ");
245720f733e7d75a16bffc34842b7682c9247dd5f954Brett RussMODULE_DESCRIPTION("SCSI low-level driver for Marvell SATA controllers");
245820f733e7d75a16bffc34842b7682c9247dd5f954Brett RussMODULE_LICENSE("GPL");
245920f733e7d75a16bffc34842b7682c9247dd5f954Brett RussMODULE_DEVICE_TABLE(pci, mv_pci_tbl);
246020f733e7d75a16bffc34842b7682c9247dd5f954Brett RussMODULE_VERSION(DRV_VERSION);
246120f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ
2462ddef9bb367b19383df627e388cb4c01c86ddba6cJeff Garzikmodule_param(msi, int, 0444);
2463ddef9bb367b19383df627e388cb4c01c86ddba6cJeff GarzikMODULE_PARM_DESC(msi, "Enable use of PCI MSI (0=off, 1=on)");
2464ddef9bb367b19383df627e388cb4c01c86ddba6cJeff Garzik
246520f733e7d75a16bffc34842b7682c9247dd5f954Brett Russmodule_init(mv_init);
246620f733e7d75a16bffc34842b7682c9247dd5f954Brett Russmodule_exit(mv_exit);
2467