sata_mv.c revision 0d5ff566779f894ca9937231a181eb31e4adff0e
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
3820f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ#define DRV_NAME	"sata_mv"
3963a25355cd5cd9a2d19a7c50eed4f0a8aa622f72Mark Lord#define DRV_VERSION	"0.7"
4020f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ
4120f733e7d75a16bffc34842b7682c9247dd5f954Brett Russenum {
4220f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ	/* BAR's are enumerated in terms of pci_resource_start() terms */
4320f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ	MV_PRIMARY_BAR		= 0,	/* offset 0x10: memory space */
4420f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ	MV_IO_BAR		= 2,	/* offset 0x18: IO space */
4520f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ	MV_MISC_BAR		= 3,	/* offset 0x1c: FLASH, NVRAM, SRAM */
4620f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ
4720f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ	MV_MAJOR_REG_AREA_SZ	= 0x10000,	/* 64KB */
4820f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ	MV_MINOR_REG_AREA_SZ	= 0x2000,	/* 8KB */
4920f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ
5020f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ	MV_PCI_REG_BASE		= 0,
5120f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ	MV_IRQ_COAL_REG_BASE	= 0x18000,	/* 6xxx part only */
52615ab95342f6245026d8974b9724f7ea57d9a184Mark Lord	MV_IRQ_COAL_CAUSE		= (MV_IRQ_COAL_REG_BASE + 0x08),
53615ab95342f6245026d8974b9724f7ea57d9a184Mark Lord	MV_IRQ_COAL_CAUSE_LO		= (MV_IRQ_COAL_REG_BASE + 0x88),
54615ab95342f6245026d8974b9724f7ea57d9a184Mark Lord	MV_IRQ_COAL_CAUSE_HI		= (MV_IRQ_COAL_REG_BASE + 0x8c),
55615ab95342f6245026d8974b9724f7ea57d9a184Mark Lord	MV_IRQ_COAL_THRESHOLD		= (MV_IRQ_COAL_REG_BASE + 0xcc),
56615ab95342f6245026d8974b9724f7ea57d9a184Mark Lord	MV_IRQ_COAL_TIME_THRESHOLD	= (MV_IRQ_COAL_REG_BASE + 0xd0),
57615ab95342f6245026d8974b9724f7ea57d9a184Mark Lord
5820f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ	MV_SATAHC0_REG_BASE	= 0x20000,
59522479fb98c6667f081e75f87e298e413c0b1db8Jeff Garzik	MV_FLASH_CTL		= 0x1046c,
60bca1c4eb9411533d613123618c0d127fae532595Jeff Garzik	MV_GPIO_PORT_CTL	= 0x104f0,
61bca1c4eb9411533d613123618c0d127fae532595Jeff Garzik	MV_RESET_CFG		= 0x180d8,
6220f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ
6320f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ	MV_PCI_REG_SZ		= MV_MAJOR_REG_AREA_SZ,
6420f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ	MV_SATAHC_REG_SZ	= MV_MAJOR_REG_AREA_SZ,
6520f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ	MV_SATAHC_ARBTR_REG_SZ	= MV_MINOR_REG_AREA_SZ,		/* arbiter */
6620f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ	MV_PORT_REG_SZ		= MV_MINOR_REG_AREA_SZ,
6720f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ
6831961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ	MV_USE_Q_DEPTH		= ATA_DEF_QUEUE,
6920f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ
7031961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ	MV_MAX_Q_DEPTH		= 32,
7131961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ	MV_MAX_Q_DEPTH_MASK	= MV_MAX_Q_DEPTH - 1,
7231961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ
7331961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ	/* CRQB needs alignment on a 1KB boundary. Size == 1KB
7431961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ	 * CRPB needs alignment on a 256B boundary. Size == 256B
7531961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ	 * SG count of 176 leads to MV_PORT_PRIV_DMA_SZ == 4KB
7631961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ	 * ePRD (SG) entries need alignment on a 16B boundary. Size == 16B
7731961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ	 */
7831961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ	MV_CRQB_Q_SZ		= (32 * MV_MAX_Q_DEPTH),
7931961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ	MV_CRPB_Q_SZ		= (8 * MV_MAX_Q_DEPTH),
8031961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ	MV_MAX_SG_CT		= 176,
8131961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ	MV_SG_TBL_SZ		= (16 * MV_MAX_SG_CT),
8231961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ	MV_PORT_PRIV_DMA_SZ	= (MV_CRQB_Q_SZ + MV_CRPB_Q_SZ + MV_SG_TBL_SZ),
8331961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ
8420f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ	MV_PORTS_PER_HC		= 4,
8520f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ	/* == (port / MV_PORTS_PER_HC) to determine HC from 0-7 port */
8620f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ	MV_PORT_HC_SHIFT	= 2,
8731961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ	/* == (port % MV_PORTS_PER_HC) to determine hard port from 0-7 port */
8820f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ	MV_PORT_MASK		= 3,
8920f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ
9020f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ	/* Host Flags */
9120f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ	MV_FLAG_DUAL_HC		= (1 << 30),  /* two SATA Host Controllers */
9220f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ	MV_FLAG_IRQ_COALESCE	= (1 << 29),  /* IRQ coalescing capability */
9331961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ	MV_COMMON_FLAGS		= (ATA_FLAG_SATA | ATA_FLAG_NO_LEGACY |
9450630195bbdfe1ca775d94cd68a5f18bc1b717e4Jeff Garzik				   ATA_FLAG_SATA_RESET | ATA_FLAG_MMIO |
951f3461a72619fcd70a0fcb563306c91f753b4620Albert Lee				   ATA_FLAG_NO_ATAPI | ATA_FLAG_PIO_POLLING),
9647c2b677daeed9c79ecb7167c211ff36876ea611Jeff Garzik	MV_6XXX_FLAGS		= MV_FLAG_IRQ_COALESCE,
9720f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ
9831961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ	CRQB_FLAG_READ		= (1 << 0),
9931961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ	CRQB_TAG_SHIFT		= 1,
10031961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ	CRQB_CMD_ADDR_SHIFT	= 8,
10131961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ	CRQB_CMD_CS		= (0x2 << 11),
10231961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ	CRQB_CMD_LAST		= (1 << 15),
10331961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ
10431961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ	CRPB_FLAG_STATUS_SHIFT	= 8,
10531961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ
10631961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ	EPRD_FLAG_END_OF_TBL	= (1 << 31),
10731961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ
10820f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ	/* PCI interface registers */
10920f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ
11031961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ	PCI_COMMAND_OFS		= 0xc00,
11131961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ
11220f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ	PCI_MAIN_CMD_STS_OFS	= 0xd30,
11320f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ	STOP_PCI_MASTER		= (1 << 2),
11420f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ	PCI_MASTER_EMPTY	= (1 << 3),
11520f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ	GLOB_SFT_RST		= (1 << 4),
11620f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ
117522479fb98c6667f081e75f87e298e413c0b1db8Jeff Garzik	MV_PCI_MODE		= 0xd00,
118522479fb98c6667f081e75f87e298e413c0b1db8Jeff Garzik	MV_PCI_EXP_ROM_BAR_CTL	= 0xd2c,
119522479fb98c6667f081e75f87e298e413c0b1db8Jeff Garzik	MV_PCI_DISC_TIMER	= 0xd04,
120522479fb98c6667f081e75f87e298e413c0b1db8Jeff Garzik	MV_PCI_MSI_TRIGGER	= 0xc38,
121522479fb98c6667f081e75f87e298e413c0b1db8Jeff Garzik	MV_PCI_SERR_MASK	= 0xc28,
122522479fb98c6667f081e75f87e298e413c0b1db8Jeff Garzik	MV_PCI_XBAR_TMOUT	= 0x1d04,
123522479fb98c6667f081e75f87e298e413c0b1db8Jeff Garzik	MV_PCI_ERR_LOW_ADDRESS	= 0x1d40,
124522479fb98c6667f081e75f87e298e413c0b1db8Jeff Garzik	MV_PCI_ERR_HIGH_ADDRESS	= 0x1d44,
125522479fb98c6667f081e75f87e298e413c0b1db8Jeff Garzik	MV_PCI_ERR_ATTRIBUTE	= 0x1d48,
126522479fb98c6667f081e75f87e298e413c0b1db8Jeff Garzik	MV_PCI_ERR_COMMAND	= 0x1d50,
127522479fb98c6667f081e75f87e298e413c0b1db8Jeff Garzik
128522479fb98c6667f081e75f87e298e413c0b1db8Jeff Garzik	PCI_IRQ_CAUSE_OFS		= 0x1d58,
129522479fb98c6667f081e75f87e298e413c0b1db8Jeff Garzik	PCI_IRQ_MASK_OFS		= 0x1d5c,
13020f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ	PCI_UNMASK_ALL_IRQS	= 0x7fffff,	/* bits 22-0 */
13120f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ
13220f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ	HC_MAIN_IRQ_CAUSE_OFS	= 0x1d60,
13320f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ	HC_MAIN_IRQ_MASK_OFS	= 0x1d64,
13420f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ	PORT0_ERR		= (1 << 0),	/* shift by port # */
13520f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ	PORT0_DONE		= (1 << 1),	/* shift by port # */
13620f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ	HC0_IRQ_PEND		= 0x1ff,	/* bits 0-8 = HC0's ports */
13720f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ	HC_SHIFT		= 9,		/* bits 9-17 = HC1's ports */
13820f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ	PCI_ERR			= (1 << 18),
13920f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ	TRAN_LO_DONE		= (1 << 19),	/* 6xxx: IRQ coalescing */
14020f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ	TRAN_HI_DONE		= (1 << 20),	/* 6xxx: IRQ coalescing */
14120f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ	PORTS_0_7_COAL_DONE	= (1 << 21),	/* 6xxx: IRQ coalescing */
14220f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ	GPIO_INT		= (1 << 22),
14320f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ	SELF_INT		= (1 << 23),
14420f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ	TWSI_INT		= (1 << 24),
14520f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ	HC_MAIN_RSVD		= (0x7f << 25),	/* bits 31-25 */
1468b260248d9e0e8b64bb72fd4dee03ad86984c344Jeff Garzik	HC_MAIN_MASKED_IRQS	= (TRAN_LO_DONE | TRAN_HI_DONE |
14720f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ				   PORTS_0_7_COAL_DONE | GPIO_INT | TWSI_INT |
14820f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ				   HC_MAIN_RSVD),
14920f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ
15020f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ	/* SATAHC registers */
15120f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ	HC_CFG_OFS		= 0,
15220f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ
15320f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ	HC_IRQ_CAUSE_OFS	= 0x14,
15431961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ	CRPB_DMA_DONE		= (1 << 0),	/* shift by port # */
15520f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ	HC_IRQ_COAL		= (1 << 4),	/* IRQ coalescing */
15620f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ	DEV_IRQ			= (1 << 8),	/* shift by port # */
15720f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ
15820f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ	/* Shadow block registers */
15931961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ	SHD_BLK_OFS		= 0x100,
16031961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ	SHD_CTL_AST_OFS		= 0x20,		/* ofs from SHD_BLK_OFS */
16120f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ
16220f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ	/* SATA registers */
16320f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ	SATA_STATUS_OFS		= 0x300,  /* ctrl, err regs follow status */
16420f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ	SATA_ACTIVE_OFS		= 0x350,
16547c2b677daeed9c79ecb7167c211ff36876ea611Jeff Garzik	PHY_MODE3		= 0x310,
166bca1c4eb9411533d613123618c0d127fae532595Jeff Garzik	PHY_MODE4		= 0x314,
167bca1c4eb9411533d613123618c0d127fae532595Jeff Garzik	PHY_MODE2		= 0x330,
168c9d39130123238ac18478a42e25cb7996eacfcc0Jeff Garzik	MV5_PHY_MODE		= 0x74,
169c9d39130123238ac18478a42e25cb7996eacfcc0Jeff Garzik	MV5_LT_MODE		= 0x30,
170c9d39130123238ac18478a42e25cb7996eacfcc0Jeff Garzik	MV5_PHY_CTL		= 0x0C,
171bca1c4eb9411533d613123618c0d127fae532595Jeff Garzik	SATA_INTERFACE_CTL	= 0x050,
172bca1c4eb9411533d613123618c0d127fae532595Jeff Garzik
173bca1c4eb9411533d613123618c0d127fae532595Jeff Garzik	MV_M2_PREAMP_MASK	= 0x7e0,
17420f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ
17520f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ	/* Port registers */
17620f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ	EDMA_CFG_OFS		= 0,
17731961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ	EDMA_CFG_Q_DEPTH	= 0,			/* queueing disabled */
17831961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ	EDMA_CFG_NCQ		= (1 << 5),
17931961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ	EDMA_CFG_NCQ_GO_ON_ERR	= (1 << 14),		/* continue on error */
18031961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ	EDMA_CFG_RD_BRST_EXT	= (1 << 11),		/* read burst 512B */
18131961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ	EDMA_CFG_WR_BUFF_LEN	= (1 << 13),		/* write buffer 512B */
18220f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ
18320f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ	EDMA_ERR_IRQ_CAUSE_OFS	= 0x8,
18420f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ	EDMA_ERR_IRQ_MASK_OFS	= 0xc,
18520f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ	EDMA_ERR_D_PAR		= (1 << 0),
18620f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ	EDMA_ERR_PRD_PAR	= (1 << 1),
18720f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ	EDMA_ERR_DEV		= (1 << 2),
18820f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ	EDMA_ERR_DEV_DCON	= (1 << 3),
18920f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ	EDMA_ERR_DEV_CON	= (1 << 4),
19020f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ	EDMA_ERR_SERR		= (1 << 5),
19120f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ	EDMA_ERR_SELF_DIS	= (1 << 7),
19220f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ	EDMA_ERR_BIST_ASYNC	= (1 << 8),
19320f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ	EDMA_ERR_CRBQ_PAR	= (1 << 9),
19420f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ	EDMA_ERR_CRPB_PAR	= (1 << 10),
19520f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ	EDMA_ERR_INTRL_PAR	= (1 << 11),
19620f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ	EDMA_ERR_IORDY		= (1 << 12),
19720f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ	EDMA_ERR_LNK_CTRL_RX	= (0xf << 13),
19820f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ	EDMA_ERR_LNK_CTRL_RX_2	= (1 << 15),
19920f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ	EDMA_ERR_LNK_DATA_RX	= (0xf << 17),
20020f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ	EDMA_ERR_LNK_CTRL_TX	= (0x1f << 21),
20120f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ	EDMA_ERR_LNK_DATA_TX	= (0x1f << 26),
20220f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ	EDMA_ERR_TRANS_PROTO	= (1 << 31),
2038b260248d9e0e8b64bb72fd4dee03ad86984c344Jeff Garzik	EDMA_ERR_FATAL		= (EDMA_ERR_D_PAR | EDMA_ERR_PRD_PAR |
20420f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ				   EDMA_ERR_DEV_DCON | EDMA_ERR_CRBQ_PAR |
20520f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ				   EDMA_ERR_CRPB_PAR | EDMA_ERR_INTRL_PAR |
2068b260248d9e0e8b64bb72fd4dee03ad86984c344Jeff Garzik				   EDMA_ERR_IORDY | EDMA_ERR_LNK_CTRL_RX_2 |
20720f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ				   EDMA_ERR_LNK_DATA_RX |
2088b260248d9e0e8b64bb72fd4dee03ad86984c344Jeff Garzik				   EDMA_ERR_LNK_DATA_TX |
20920f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ				   EDMA_ERR_TRANS_PROTO),
21020f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ
21131961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ	EDMA_REQ_Q_BASE_HI_OFS	= 0x10,
21231961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ	EDMA_REQ_Q_IN_PTR_OFS	= 0x14,		/* also contains BASE_LO */
21331961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ
21431961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ	EDMA_REQ_Q_OUT_PTR_OFS	= 0x18,
21531961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ	EDMA_REQ_Q_PTR_SHIFT	= 5,
21631961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ
21731961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ	EDMA_RSP_Q_BASE_HI_OFS	= 0x1c,
21831961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ	EDMA_RSP_Q_IN_PTR_OFS	= 0x20,
21931961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ	EDMA_RSP_Q_OUT_PTR_OFS	= 0x24,		/* also contains BASE_LO */
22031961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ	EDMA_RSP_Q_PTR_SHIFT	= 3,
22131961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ
22220f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ	EDMA_CMD_OFS		= 0x28,
22320f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ	EDMA_EN			= (1 << 0),
22420f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ	EDMA_DS			= (1 << 1),
22520f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ	ATA_RST			= (1 << 2),
22620f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ
227c9d39130123238ac18478a42e25cb7996eacfcc0Jeff Garzik	EDMA_IORDY_TMOUT	= 0x34,
228bca1c4eb9411533d613123618c0d127fae532595Jeff Garzik	EDMA_ARB_CFG		= 0x38,
229bca1c4eb9411533d613123618c0d127fae532595Jeff Garzik
23031961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ	/* Host private flags (hp_flags) */
23131961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ	MV_HP_FLAG_MSI		= (1 << 0),
23247c2b677daeed9c79ecb7167c211ff36876ea611Jeff Garzik	MV_HP_ERRATA_50XXB0	= (1 << 1),
23347c2b677daeed9c79ecb7167c211ff36876ea611Jeff Garzik	MV_HP_ERRATA_50XXB2	= (1 << 2),
23447c2b677daeed9c79ecb7167c211ff36876ea611Jeff Garzik	MV_HP_ERRATA_60X1B2	= (1 << 3),
23547c2b677daeed9c79ecb7167c211ff36876ea611Jeff Garzik	MV_HP_ERRATA_60X1C0	= (1 << 4),
236e4e7b89280d1d666e2c09e5ad36cf071796c4c7eJeff Garzik	MV_HP_ERRATA_XX42A0	= (1 << 5),
237e4e7b89280d1d666e2c09e5ad36cf071796c4c7eJeff Garzik	MV_HP_50XX		= (1 << 6),
238e4e7b89280d1d666e2c09e5ad36cf071796c4c7eJeff Garzik	MV_HP_GEN_IIE		= (1 << 7),
23920f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ
24031961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ	/* Port private flags (pp_flags) */
24131961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ	MV_PP_FLAG_EDMA_EN	= (1 << 0),
24231961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ	MV_PP_FLAG_EDMA_DS_ACT	= (1 << 1),
24320f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ};
24420f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ
245c9d39130123238ac18478a42e25cb7996eacfcc0Jeff Garzik#define IS_50XX(hpriv) ((hpriv)->hp_flags & MV_HP_50XX)
246bca1c4eb9411533d613123618c0d127fae532595Jeff Garzik#define IS_60XX(hpriv) (((hpriv)->hp_flags & MV_HP_50XX) == 0)
247e4e7b89280d1d666e2c09e5ad36cf071796c4c7eJeff Garzik#define IS_GEN_I(hpriv) IS_50XX(hpriv)
248e4e7b89280d1d666e2c09e5ad36cf071796c4c7eJeff Garzik#define IS_GEN_II(hpriv) IS_60XX(hpriv)
249e4e7b89280d1d666e2c09e5ad36cf071796c4c7eJeff Garzik#define IS_GEN_IIE(hpriv) ((hpriv)->hp_flags & MV_HP_GEN_IIE)
250bca1c4eb9411533d613123618c0d127fae532595Jeff Garzik
251095fec887eaa1c38d17c0c929a6733c744a9fa1fJeff Garzikenum {
252095fec887eaa1c38d17c0c929a6733c744a9fa1fJeff Garzik	/* Our DMA boundary is determined by an ePRD being unable to handle
253095fec887eaa1c38d17c0c929a6733c744a9fa1fJeff Garzik	 * anything larger than 64KB
254095fec887eaa1c38d17c0c929a6733c744a9fa1fJeff Garzik	 */
255095fec887eaa1c38d17c0c929a6733c744a9fa1fJeff Garzik	MV_DMA_BOUNDARY		= 0xffffU,
256095fec887eaa1c38d17c0c929a6733c744a9fa1fJeff Garzik
257095fec887eaa1c38d17c0c929a6733c744a9fa1fJeff Garzik	EDMA_REQ_Q_BASE_LO_MASK	= 0xfffffc00U,
258095fec887eaa1c38d17c0c929a6733c744a9fa1fJeff Garzik
259095fec887eaa1c38d17c0c929a6733c744a9fa1fJeff Garzik	EDMA_RSP_Q_BASE_LO_MASK	= 0xffffff00U,
260095fec887eaa1c38d17c0c929a6733c744a9fa1fJeff Garzik};
261095fec887eaa1c38d17c0c929a6733c744a9fa1fJeff Garzik
262522479fb98c6667f081e75f87e298e413c0b1db8Jeff Garzikenum chip_type {
263522479fb98c6667f081e75f87e298e413c0b1db8Jeff Garzik	chip_504x,
264522479fb98c6667f081e75f87e298e413c0b1db8Jeff Garzik	chip_508x,
265522479fb98c6667f081e75f87e298e413c0b1db8Jeff Garzik	chip_5080,
266522479fb98c6667f081e75f87e298e413c0b1db8Jeff Garzik	chip_604x,
267522479fb98c6667f081e75f87e298e413c0b1db8Jeff Garzik	chip_608x,
268e4e7b89280d1d666e2c09e5ad36cf071796c4c7eJeff Garzik	chip_6042,
269e4e7b89280d1d666e2c09e5ad36cf071796c4c7eJeff Garzik	chip_7042,
270522479fb98c6667f081e75f87e298e413c0b1db8Jeff Garzik};
271522479fb98c6667f081e75f87e298e413c0b1db8Jeff Garzik
27231961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ/* Command ReQuest Block: 32B */
27331961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russstruct mv_crqb {
274e14698745dd0de1ddbf5cd0cca4313a90f8c1cc1Mark Lord	__le32			sg_addr;
275e14698745dd0de1ddbf5cd0cca4313a90f8c1cc1Mark Lord	__le32			sg_addr_hi;
276e14698745dd0de1ddbf5cd0cca4313a90f8c1cc1Mark Lord	__le16			ctrl_flags;
277e14698745dd0de1ddbf5cd0cca4313a90f8c1cc1Mark Lord	__le16			ata_cmd[11];
27831961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ};
27920f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ
280e4e7b89280d1d666e2c09e5ad36cf071796c4c7eJeff Garzikstruct mv_crqb_iie {
281e14698745dd0de1ddbf5cd0cca4313a90f8c1cc1Mark Lord	__le32			addr;
282e14698745dd0de1ddbf5cd0cca4313a90f8c1cc1Mark Lord	__le32			addr_hi;
283e14698745dd0de1ddbf5cd0cca4313a90f8c1cc1Mark Lord	__le32			flags;
284e14698745dd0de1ddbf5cd0cca4313a90f8c1cc1Mark Lord	__le32			len;
285e14698745dd0de1ddbf5cd0cca4313a90f8c1cc1Mark Lord	__le32			ata_cmd[4];
286e4e7b89280d1d666e2c09e5ad36cf071796c4c7eJeff Garzik};
287e4e7b89280d1d666e2c09e5ad36cf071796c4c7eJeff Garzik
28831961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ/* Command ResPonse Block: 8B */
28931961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russstruct mv_crpb {
290e14698745dd0de1ddbf5cd0cca4313a90f8c1cc1Mark Lord	__le16			id;
291e14698745dd0de1ddbf5cd0cca4313a90f8c1cc1Mark Lord	__le16			flags;
292e14698745dd0de1ddbf5cd0cca4313a90f8c1cc1Mark Lord	__le32			tmstmp;
29320f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ};
29420f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ
29531961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ/* EDMA Physical Region Descriptor (ePRD); A.K.A. SG */
29631961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russstruct mv_sg {
297e14698745dd0de1ddbf5cd0cca4313a90f8c1cc1Mark Lord	__le32			addr;
298e14698745dd0de1ddbf5cd0cca4313a90f8c1cc1Mark Lord	__le32			flags_size;
299e14698745dd0de1ddbf5cd0cca4313a90f8c1cc1Mark Lord	__le32			addr_hi;
300e14698745dd0de1ddbf5cd0cca4313a90f8c1cc1Mark Lord	__le32			reserved;
30131961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ};
30220f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ
30331961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russstruct mv_port_priv {
30431961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ	struct mv_crqb		*crqb;
30531961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ	dma_addr_t		crqb_dma;
30631961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ	struct mv_crpb		*crpb;
30731961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ	dma_addr_t		crpb_dma;
30831961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ	struct mv_sg		*sg_tbl;
30931961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ	dma_addr_t		sg_tbl_dma;
31031961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ	u32			pp_flags;
31131961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ};
31231961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ
313bca1c4eb9411533d613123618c0d127fae532595Jeff Garzikstruct mv_port_signal {
314bca1c4eb9411533d613123618c0d127fae532595Jeff Garzik	u32			amps;
315bca1c4eb9411533d613123618c0d127fae532595Jeff Garzik	u32			pre;
316bca1c4eb9411533d613123618c0d127fae532595Jeff Garzik};
317bca1c4eb9411533d613123618c0d127fae532595Jeff Garzik
31847c2b677daeed9c79ecb7167c211ff36876ea611Jeff Garzikstruct mv_host_priv;
31947c2b677daeed9c79ecb7167c211ff36876ea611Jeff Garzikstruct mv_hw_ops {
3202a47ce06d534692f9bd2bf4e90a20fc9b1054c39Jeff Garzik	void (*phy_errata)(struct mv_host_priv *hpriv, void __iomem *mmio,
3212a47ce06d534692f9bd2bf4e90a20fc9b1054c39Jeff Garzik			   unsigned int port);
32247c2b677daeed9c79ecb7167c211ff36876ea611Jeff Garzik	void (*enable_leds)(struct mv_host_priv *hpriv, void __iomem *mmio);
32347c2b677daeed9c79ecb7167c211ff36876ea611Jeff Garzik	void (*read_preamp)(struct mv_host_priv *hpriv, int idx,
32447c2b677daeed9c79ecb7167c211ff36876ea611Jeff Garzik			   void __iomem *mmio);
325c9d39130123238ac18478a42e25cb7996eacfcc0Jeff Garzik	int (*reset_hc)(struct mv_host_priv *hpriv, void __iomem *mmio,
326c9d39130123238ac18478a42e25cb7996eacfcc0Jeff Garzik			unsigned int n_hc);
327522479fb98c6667f081e75f87e298e413c0b1db8Jeff Garzik	void (*reset_flash)(struct mv_host_priv *hpriv, void __iomem *mmio);
328522479fb98c6667f081e75f87e298e413c0b1db8Jeff Garzik	void (*reset_bus)(struct pci_dev *pdev, void __iomem *mmio);
32947c2b677daeed9c79ecb7167c211ff36876ea611Jeff Garzik};
33047c2b677daeed9c79ecb7167c211ff36876ea611Jeff Garzik
33131961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russstruct mv_host_priv {
33231961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ	u32			hp_flags;
333bca1c4eb9411533d613123618c0d127fae532595Jeff Garzik	struct mv_port_signal	signal[8];
33447c2b677daeed9c79ecb7167c211ff36876ea611Jeff Garzik	const struct mv_hw_ops	*ops;
33520f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ};
33620f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ
33720f733e7d75a16bffc34842b7682c9247dd5f954Brett Russstatic void mv_irq_clear(struct ata_port *ap);
33820f733e7d75a16bffc34842b7682c9247dd5f954Brett Russstatic u32 mv_scr_read(struct ata_port *ap, unsigned int sc_reg_in);
33920f733e7d75a16bffc34842b7682c9247dd5f954Brett Russstatic void mv_scr_write(struct ata_port *ap, unsigned int sc_reg_in, u32 val);
340c9d39130123238ac18478a42e25cb7996eacfcc0Jeff Garzikstatic u32 mv5_scr_read(struct ata_port *ap, unsigned int sc_reg_in);
341c9d39130123238ac18478a42e25cb7996eacfcc0Jeff Garzikstatic void mv5_scr_write(struct ata_port *ap, unsigned int sc_reg_in, u32 val);
34220f733e7d75a16bffc34842b7682c9247dd5f954Brett Russstatic void mv_phy_reset(struct ata_port *ap);
34322374677d18c5eeefd3a283431d312b8c44fef02Jeff Garzikstatic void __mv_phy_reset(struct ata_port *ap, int can_sleep);
34431961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russstatic int mv_port_start(struct ata_port *ap);
34531961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russstatic void mv_port_stop(struct ata_port *ap);
34631961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russstatic void mv_qc_prep(struct ata_queued_cmd *qc);
347e4e7b89280d1d666e2c09e5ad36cf071796c4c7eJeff Garzikstatic void mv_qc_prep_iie(struct ata_queued_cmd *qc);
3489a3d9eb0177eb10500d49cd283b35576082a522dTejun Heostatic unsigned int mv_qc_issue(struct ata_queued_cmd *qc);
3497d12e780e003f93433d49ce78cfedf4b4c52adc5David Howellsstatic irqreturn_t mv_interrupt(int irq, void *dev_instance);
35031961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russstatic void mv_eng_timeout(struct ata_port *ap);
35120f733e7d75a16bffc34842b7682c9247dd5f954Brett Russstatic int mv_init_one(struct pci_dev *pdev, const struct pci_device_id *ent);
35220f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ
3532a47ce06d534692f9bd2bf4e90a20fc9b1054c39Jeff Garzikstatic void mv5_phy_errata(struct mv_host_priv *hpriv, void __iomem *mmio,
3542a47ce06d534692f9bd2bf4e90a20fc9b1054c39Jeff Garzik			   unsigned int port);
35547c2b677daeed9c79ecb7167c211ff36876ea611Jeff Garzikstatic void mv5_enable_leds(struct mv_host_priv *hpriv, void __iomem *mmio);
35647c2b677daeed9c79ecb7167c211ff36876ea611Jeff Garzikstatic void mv5_read_preamp(struct mv_host_priv *hpriv, int idx,
35747c2b677daeed9c79ecb7167c211ff36876ea611Jeff Garzik			   void __iomem *mmio);
358c9d39130123238ac18478a42e25cb7996eacfcc0Jeff Garzikstatic int mv5_reset_hc(struct mv_host_priv *hpriv, void __iomem *mmio,
359c9d39130123238ac18478a42e25cb7996eacfcc0Jeff Garzik			unsigned int n_hc);
360522479fb98c6667f081e75f87e298e413c0b1db8Jeff Garzikstatic void mv5_reset_flash(struct mv_host_priv *hpriv, void __iomem *mmio);
361522479fb98c6667f081e75f87e298e413c0b1db8Jeff Garzikstatic void mv5_reset_bus(struct pci_dev *pdev, void __iomem *mmio);
36247c2b677daeed9c79ecb7167c211ff36876ea611Jeff Garzik
3632a47ce06d534692f9bd2bf4e90a20fc9b1054c39Jeff Garzikstatic void mv6_phy_errata(struct mv_host_priv *hpriv, void __iomem *mmio,
3642a47ce06d534692f9bd2bf4e90a20fc9b1054c39Jeff Garzik			   unsigned int port);
36547c2b677daeed9c79ecb7167c211ff36876ea611Jeff Garzikstatic void mv6_enable_leds(struct mv_host_priv *hpriv, void __iomem *mmio);
36647c2b677daeed9c79ecb7167c211ff36876ea611Jeff Garzikstatic void mv6_read_preamp(struct mv_host_priv *hpriv, int idx,
36747c2b677daeed9c79ecb7167c211ff36876ea611Jeff Garzik			   void __iomem *mmio);
368c9d39130123238ac18478a42e25cb7996eacfcc0Jeff Garzikstatic int mv6_reset_hc(struct mv_host_priv *hpriv, void __iomem *mmio,
369c9d39130123238ac18478a42e25cb7996eacfcc0Jeff Garzik			unsigned int n_hc);
370522479fb98c6667f081e75f87e298e413c0b1db8Jeff Garzikstatic void mv6_reset_flash(struct mv_host_priv *hpriv, void __iomem *mmio);
371522479fb98c6667f081e75f87e298e413c0b1db8Jeff Garzikstatic void mv_reset_pci_bus(struct pci_dev *pdev, void __iomem *mmio);
372c9d39130123238ac18478a42e25cb7996eacfcc0Jeff Garzikstatic void mv_channel_reset(struct mv_host_priv *hpriv, void __iomem *mmio,
373c9d39130123238ac18478a42e25cb7996eacfcc0Jeff Garzik			     unsigned int port_no);
374c9d39130123238ac18478a42e25cb7996eacfcc0Jeff Garzikstatic void mv_stop_and_reset(struct ata_port *ap);
37547c2b677daeed9c79ecb7167c211ff36876ea611Jeff Garzik
376193515d51ccb363165d6b09e9ba5c21089e34badJeff Garzikstatic struct scsi_host_template mv_sht = {
37720f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ	.module			= THIS_MODULE,
37820f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ	.name			= DRV_NAME,
37920f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ	.ioctl			= ata_scsi_ioctl,
38020f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ	.queuecommand		= ata_scsi_queuecmd,
38131961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ	.can_queue		= MV_USE_Q_DEPTH,
38220f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ	.this_id		= ATA_SHT_THIS_ID,
38322374677d18c5eeefd3a283431d312b8c44fef02Jeff Garzik	.sg_tablesize		= MV_MAX_SG_CT / 2,
38420f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ	.cmd_per_lun		= ATA_SHT_CMD_PER_LUN,
38520f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ	.emulated		= ATA_SHT_EMULATED,
38631961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ	.use_clustering		= ATA_SHT_USE_CLUSTERING,
38720f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ	.proc_name		= DRV_NAME,
38820f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ	.dma_boundary		= MV_DMA_BOUNDARY,
38920f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ	.slave_configure	= ata_scsi_slave_config,
390ccf68c3405fca11386004674377d951b9b18e756Tejun Heo	.slave_destroy		= ata_scsi_slave_destroy,
39120f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ	.bios_param		= ata_std_bios_param,
39220f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ};
39320f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ
394c9d39130123238ac18478a42e25cb7996eacfcc0Jeff Garzikstatic const struct ata_port_operations mv5_ops = {
395c9d39130123238ac18478a42e25cb7996eacfcc0Jeff Garzik	.port_disable		= ata_port_disable,
396c9d39130123238ac18478a42e25cb7996eacfcc0Jeff Garzik
397c9d39130123238ac18478a42e25cb7996eacfcc0Jeff Garzik	.tf_load		= ata_tf_load,
398c9d39130123238ac18478a42e25cb7996eacfcc0Jeff Garzik	.tf_read		= ata_tf_read,
399c9d39130123238ac18478a42e25cb7996eacfcc0Jeff Garzik	.check_status		= ata_check_status,
400c9d39130123238ac18478a42e25cb7996eacfcc0Jeff Garzik	.exec_command		= ata_exec_command,
401c9d39130123238ac18478a42e25cb7996eacfcc0Jeff Garzik	.dev_select		= ata_std_dev_select,
402c9d39130123238ac18478a42e25cb7996eacfcc0Jeff Garzik
403c9d39130123238ac18478a42e25cb7996eacfcc0Jeff Garzik	.phy_reset		= mv_phy_reset,
404c9d39130123238ac18478a42e25cb7996eacfcc0Jeff Garzik
405c9d39130123238ac18478a42e25cb7996eacfcc0Jeff Garzik	.qc_prep		= mv_qc_prep,
406c9d39130123238ac18478a42e25cb7996eacfcc0Jeff Garzik	.qc_issue		= mv_qc_issue,
4070d5ff566779f894ca9937231a181eb31e4adff0eTejun Heo	.data_xfer		= ata_data_xfer,
408c9d39130123238ac18478a42e25cb7996eacfcc0Jeff Garzik
409c9d39130123238ac18478a42e25cb7996eacfcc0Jeff Garzik	.eng_timeout		= mv_eng_timeout,
410c9d39130123238ac18478a42e25cb7996eacfcc0Jeff Garzik
411c9d39130123238ac18478a42e25cb7996eacfcc0Jeff Garzik	.irq_handler		= mv_interrupt,
412c9d39130123238ac18478a42e25cb7996eacfcc0Jeff Garzik	.irq_clear		= mv_irq_clear,
413c9d39130123238ac18478a42e25cb7996eacfcc0Jeff Garzik
414c9d39130123238ac18478a42e25cb7996eacfcc0Jeff Garzik	.scr_read		= mv5_scr_read,
415c9d39130123238ac18478a42e25cb7996eacfcc0Jeff Garzik	.scr_write		= mv5_scr_write,
416c9d39130123238ac18478a42e25cb7996eacfcc0Jeff Garzik
417c9d39130123238ac18478a42e25cb7996eacfcc0Jeff Garzik	.port_start		= mv_port_start,
418c9d39130123238ac18478a42e25cb7996eacfcc0Jeff Garzik	.port_stop		= mv_port_stop,
419c9d39130123238ac18478a42e25cb7996eacfcc0Jeff Garzik};
420c9d39130123238ac18478a42e25cb7996eacfcc0Jeff Garzik
421c9d39130123238ac18478a42e25cb7996eacfcc0Jeff Garzikstatic const struct ata_port_operations mv6_ops = {
42220f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ	.port_disable		= ata_port_disable,
42320f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ
42420f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ	.tf_load		= ata_tf_load,
42520f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ	.tf_read		= ata_tf_read,
42620f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ	.check_status		= ata_check_status,
42720f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ	.exec_command		= ata_exec_command,
42820f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ	.dev_select		= ata_std_dev_select,
42920f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ
43020f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ	.phy_reset		= mv_phy_reset,
43120f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ
43231961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ	.qc_prep		= mv_qc_prep,
43331961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ	.qc_issue		= mv_qc_issue,
4340d5ff566779f894ca9937231a181eb31e4adff0eTejun Heo	.data_xfer		= ata_data_xfer,
43520f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ
43631961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ	.eng_timeout		= mv_eng_timeout,
43720f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ
43820f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ	.irq_handler		= mv_interrupt,
43920f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ	.irq_clear		= mv_irq_clear,
44020f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ
44120f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ	.scr_read		= mv_scr_read,
44220f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ	.scr_write		= mv_scr_write,
44320f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ
44431961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ	.port_start		= mv_port_start,
44531961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ	.port_stop		= mv_port_stop,
44620f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ};
44720f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ
448e4e7b89280d1d666e2c09e5ad36cf071796c4c7eJeff Garzikstatic const struct ata_port_operations mv_iie_ops = {
449e4e7b89280d1d666e2c09e5ad36cf071796c4c7eJeff Garzik	.port_disable		= ata_port_disable,
450e4e7b89280d1d666e2c09e5ad36cf071796c4c7eJeff Garzik
451e4e7b89280d1d666e2c09e5ad36cf071796c4c7eJeff Garzik	.tf_load		= ata_tf_load,
452e4e7b89280d1d666e2c09e5ad36cf071796c4c7eJeff Garzik	.tf_read		= ata_tf_read,
453e4e7b89280d1d666e2c09e5ad36cf071796c4c7eJeff Garzik	.check_status		= ata_check_status,
454e4e7b89280d1d666e2c09e5ad36cf071796c4c7eJeff Garzik	.exec_command		= ata_exec_command,
455e4e7b89280d1d666e2c09e5ad36cf071796c4c7eJeff Garzik	.dev_select		= ata_std_dev_select,
456e4e7b89280d1d666e2c09e5ad36cf071796c4c7eJeff Garzik
457e4e7b89280d1d666e2c09e5ad36cf071796c4c7eJeff Garzik	.phy_reset		= mv_phy_reset,
458e4e7b89280d1d666e2c09e5ad36cf071796c4c7eJeff Garzik
459e4e7b89280d1d666e2c09e5ad36cf071796c4c7eJeff Garzik	.qc_prep		= mv_qc_prep_iie,
460e4e7b89280d1d666e2c09e5ad36cf071796c4c7eJeff Garzik	.qc_issue		= mv_qc_issue,
4610d5ff566779f894ca9937231a181eb31e4adff0eTejun Heo	.data_xfer		= ata_data_xfer,
462e4e7b89280d1d666e2c09e5ad36cf071796c4c7eJeff Garzik
463e4e7b89280d1d666e2c09e5ad36cf071796c4c7eJeff Garzik	.eng_timeout		= mv_eng_timeout,
464e4e7b89280d1d666e2c09e5ad36cf071796c4c7eJeff Garzik
465e4e7b89280d1d666e2c09e5ad36cf071796c4c7eJeff Garzik	.irq_handler		= mv_interrupt,
466e4e7b89280d1d666e2c09e5ad36cf071796c4c7eJeff Garzik	.irq_clear		= mv_irq_clear,
467e4e7b89280d1d666e2c09e5ad36cf071796c4c7eJeff Garzik
468e4e7b89280d1d666e2c09e5ad36cf071796c4c7eJeff Garzik	.scr_read		= mv_scr_read,
469e4e7b89280d1d666e2c09e5ad36cf071796c4c7eJeff Garzik	.scr_write		= mv_scr_write,
470e4e7b89280d1d666e2c09e5ad36cf071796c4c7eJeff Garzik
471e4e7b89280d1d666e2c09e5ad36cf071796c4c7eJeff Garzik	.port_start		= mv_port_start,
472e4e7b89280d1d666e2c09e5ad36cf071796c4c7eJeff Garzik	.port_stop		= mv_port_stop,
473e4e7b89280d1d666e2c09e5ad36cf071796c4c7eJeff Garzik};
474e4e7b89280d1d666e2c09e5ad36cf071796c4c7eJeff Garzik
47598ac62defe529d04a192688f40d801a2d8fbcf98Arjan van de Venstatic const struct ata_port_info mv_port_info[] = {
47620f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ	{  /* chip_504x */
47720f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ		.sht		= &mv_sht,
478cca3974e48607c3775dc73b544a5700b2e37c21aJeff Garzik		.flags		= MV_COMMON_FLAGS,
47931961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ		.pio_mask	= 0x1f,	/* pio0-4 */
480c9d39130123238ac18478a42e25cb7996eacfcc0Jeff Garzik		.udma_mask	= 0x7f,	/* udma0-6 */
481c9d39130123238ac18478a42e25cb7996eacfcc0Jeff Garzik		.port_ops	= &mv5_ops,
48220f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ	},
48320f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ	{  /* chip_508x */
48420f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ		.sht		= &mv_sht,
485cca3974e48607c3775dc73b544a5700b2e37c21aJeff Garzik		.flags		= (MV_COMMON_FLAGS | MV_FLAG_DUAL_HC),
48631961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ		.pio_mask	= 0x1f,	/* pio0-4 */
487c9d39130123238ac18478a42e25cb7996eacfcc0Jeff Garzik		.udma_mask	= 0x7f,	/* udma0-6 */
488c9d39130123238ac18478a42e25cb7996eacfcc0Jeff Garzik		.port_ops	= &mv5_ops,
48920f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ	},
49047c2b677daeed9c79ecb7167c211ff36876ea611Jeff Garzik	{  /* chip_5080 */
49147c2b677daeed9c79ecb7167c211ff36876ea611Jeff Garzik		.sht		= &mv_sht,
492cca3974e48607c3775dc73b544a5700b2e37c21aJeff Garzik		.flags		= (MV_COMMON_FLAGS | MV_FLAG_DUAL_HC),
49347c2b677daeed9c79ecb7167c211ff36876ea611Jeff Garzik		.pio_mask	= 0x1f,	/* pio0-4 */
494c9d39130123238ac18478a42e25cb7996eacfcc0Jeff Garzik		.udma_mask	= 0x7f,	/* udma0-6 */
495c9d39130123238ac18478a42e25cb7996eacfcc0Jeff Garzik		.port_ops	= &mv5_ops,
49647c2b677daeed9c79ecb7167c211ff36876ea611Jeff Garzik	},
49720f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ	{  /* chip_604x */
49820f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ		.sht		= &mv_sht,
499cca3974e48607c3775dc73b544a5700b2e37c21aJeff Garzik		.flags		= (MV_COMMON_FLAGS | MV_6XXX_FLAGS),
50031961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ		.pio_mask	= 0x1f,	/* pio0-4 */
50131961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ		.udma_mask	= 0x7f,	/* udma0-6 */
502c9d39130123238ac18478a42e25cb7996eacfcc0Jeff Garzik		.port_ops	= &mv6_ops,
50320f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ	},
50420f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ	{  /* chip_608x */
50520f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ		.sht		= &mv_sht,
506cca3974e48607c3775dc73b544a5700b2e37c21aJeff Garzik		.flags		= (MV_COMMON_FLAGS | MV_6XXX_FLAGS |
50731961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ				   MV_FLAG_DUAL_HC),
50831961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ		.pio_mask	= 0x1f,	/* pio0-4 */
50931961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ		.udma_mask	= 0x7f,	/* udma0-6 */
510c9d39130123238ac18478a42e25cb7996eacfcc0Jeff Garzik		.port_ops	= &mv6_ops,
51120f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ	},
512e4e7b89280d1d666e2c09e5ad36cf071796c4c7eJeff Garzik	{  /* chip_6042 */
513e4e7b89280d1d666e2c09e5ad36cf071796c4c7eJeff Garzik		.sht		= &mv_sht,
514cca3974e48607c3775dc73b544a5700b2e37c21aJeff Garzik		.flags		= (MV_COMMON_FLAGS | MV_6XXX_FLAGS),
515e4e7b89280d1d666e2c09e5ad36cf071796c4c7eJeff Garzik		.pio_mask	= 0x1f,	/* pio0-4 */
516e4e7b89280d1d666e2c09e5ad36cf071796c4c7eJeff Garzik		.udma_mask	= 0x7f,	/* udma0-6 */
517e4e7b89280d1d666e2c09e5ad36cf071796c4c7eJeff Garzik		.port_ops	= &mv_iie_ops,
518e4e7b89280d1d666e2c09e5ad36cf071796c4c7eJeff Garzik	},
519e4e7b89280d1d666e2c09e5ad36cf071796c4c7eJeff Garzik	{  /* chip_7042 */
520e4e7b89280d1d666e2c09e5ad36cf071796c4c7eJeff Garzik		.sht		= &mv_sht,
521e93f09dc2d49d8e98818a93ad17f3ede91533738Olof Johansson		.flags		= (MV_COMMON_FLAGS | MV_6XXX_FLAGS),
522e4e7b89280d1d666e2c09e5ad36cf071796c4c7eJeff Garzik		.pio_mask	= 0x1f,	/* pio0-4 */
523e4e7b89280d1d666e2c09e5ad36cf071796c4c7eJeff Garzik		.udma_mask	= 0x7f,	/* udma0-6 */
524e4e7b89280d1d666e2c09e5ad36cf071796c4c7eJeff Garzik		.port_ops	= &mv_iie_ops,
525e4e7b89280d1d666e2c09e5ad36cf071796c4c7eJeff Garzik	},
52620f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ};
52720f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ
5283b7d697dfb7d03edb87e50b743a7ecff029618e9Jeff Garzikstatic const struct pci_device_id mv_pci_tbl[] = {
5292d2744fc8be620a2dc469cf48349e3e704119f1bJeff Garzik	{ PCI_VDEVICE(MARVELL, 0x5040), chip_504x },
5302d2744fc8be620a2dc469cf48349e3e704119f1bJeff Garzik	{ PCI_VDEVICE(MARVELL, 0x5041), chip_504x },
5312d2744fc8be620a2dc469cf48349e3e704119f1bJeff Garzik	{ PCI_VDEVICE(MARVELL, 0x5080), chip_5080 },
5322d2744fc8be620a2dc469cf48349e3e704119f1bJeff Garzik	{ PCI_VDEVICE(MARVELL, 0x5081), chip_508x },
5332d2744fc8be620a2dc469cf48349e3e704119f1bJeff Garzik
5342d2744fc8be620a2dc469cf48349e3e704119f1bJeff Garzik	{ PCI_VDEVICE(MARVELL, 0x6040), chip_604x },
5352d2744fc8be620a2dc469cf48349e3e704119f1bJeff Garzik	{ PCI_VDEVICE(MARVELL, 0x6041), chip_604x },
5362d2744fc8be620a2dc469cf48349e3e704119f1bJeff Garzik	{ PCI_VDEVICE(MARVELL, 0x6042), chip_6042 },
5372d2744fc8be620a2dc469cf48349e3e704119f1bJeff Garzik	{ PCI_VDEVICE(MARVELL, 0x6080), chip_608x },
5382d2744fc8be620a2dc469cf48349e3e704119f1bJeff Garzik	{ PCI_VDEVICE(MARVELL, 0x6081), chip_608x },
5392d2744fc8be620a2dc469cf48349e3e704119f1bJeff Garzik
5402d2744fc8be620a2dc469cf48349e3e704119f1bJeff Garzik	{ PCI_VDEVICE(ADAPTEC2, 0x0241), chip_604x },
5412d2744fc8be620a2dc469cf48349e3e704119f1bJeff Garzik
542e93f09dc2d49d8e98818a93ad17f3ede91533738Olof Johansson	{ PCI_VDEVICE(TTI, 0x2310), chip_7042 },
543e93f09dc2d49d8e98818a93ad17f3ede91533738Olof Johansson
5442d2744fc8be620a2dc469cf48349e3e704119f1bJeff Garzik	{ }			/* terminate list */
54520f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ};
54620f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ
54720f733e7d75a16bffc34842b7682c9247dd5f954Brett Russstatic struct pci_driver mv_pci_driver = {
54820f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ	.name			= DRV_NAME,
54920f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ	.id_table		= mv_pci_tbl,
55020f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ	.probe			= mv_init_one,
55120f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ	.remove			= ata_pci_remove_one,
55220f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ};
55320f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ
55447c2b677daeed9c79ecb7167c211ff36876ea611Jeff Garzikstatic const struct mv_hw_ops mv5xxx_ops = {
55547c2b677daeed9c79ecb7167c211ff36876ea611Jeff Garzik	.phy_errata		= mv5_phy_errata,
55647c2b677daeed9c79ecb7167c211ff36876ea611Jeff Garzik	.enable_leds		= mv5_enable_leds,
55747c2b677daeed9c79ecb7167c211ff36876ea611Jeff Garzik	.read_preamp		= mv5_read_preamp,
55847c2b677daeed9c79ecb7167c211ff36876ea611Jeff Garzik	.reset_hc		= mv5_reset_hc,
559522479fb98c6667f081e75f87e298e413c0b1db8Jeff Garzik	.reset_flash		= mv5_reset_flash,
560522479fb98c6667f081e75f87e298e413c0b1db8Jeff Garzik	.reset_bus		= mv5_reset_bus,
56147c2b677daeed9c79ecb7167c211ff36876ea611Jeff Garzik};
56247c2b677daeed9c79ecb7167c211ff36876ea611Jeff Garzik
56347c2b677daeed9c79ecb7167c211ff36876ea611Jeff Garzikstatic const struct mv_hw_ops mv6xxx_ops = {
56447c2b677daeed9c79ecb7167c211ff36876ea611Jeff Garzik	.phy_errata		= mv6_phy_errata,
56547c2b677daeed9c79ecb7167c211ff36876ea611Jeff Garzik	.enable_leds		= mv6_enable_leds,
56647c2b677daeed9c79ecb7167c211ff36876ea611Jeff Garzik	.read_preamp		= mv6_read_preamp,
56747c2b677daeed9c79ecb7167c211ff36876ea611Jeff Garzik	.reset_hc		= mv6_reset_hc,
568522479fb98c6667f081e75f87e298e413c0b1db8Jeff Garzik	.reset_flash		= mv6_reset_flash,
569522479fb98c6667f081e75f87e298e413c0b1db8Jeff Garzik	.reset_bus		= mv_reset_pci_bus,
57047c2b677daeed9c79ecb7167c211ff36876ea611Jeff Garzik};
57147c2b677daeed9c79ecb7167c211ff36876ea611Jeff Garzik
57220f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ/*
573ddef9bb367b19383df627e388cb4c01c86ddba6cJeff Garzik * module options
574ddef9bb367b19383df627e388cb4c01c86ddba6cJeff Garzik */
575ddef9bb367b19383df627e388cb4c01c86ddba6cJeff Garzikstatic int msi;	      /* Use PCI msi; either zero (off, default) or non-zero */
576ddef9bb367b19383df627e388cb4c01c86ddba6cJeff Garzik
577ddef9bb367b19383df627e388cb4c01c86ddba6cJeff Garzik
578ddef9bb367b19383df627e388cb4c01c86ddba6cJeff Garzik/*
57920f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ * Functions
58020f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ */
58120f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ
58220f733e7d75a16bffc34842b7682c9247dd5f954Brett Russstatic inline void writelfl(unsigned long data, void __iomem *addr)
58320f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ{
58420f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ	writel(data, addr);
58520f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ	(void) readl(addr);	/* flush to avoid PCI posted write */
58620f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ}
58720f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ
58820f733e7d75a16bffc34842b7682c9247dd5f954Brett Russstatic inline void __iomem *mv_hc_base(void __iomem *base, unsigned int hc)
58920f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ{
59020f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ	return (base + MV_SATAHC0_REG_BASE + (hc * MV_SATAHC_REG_SZ));
59120f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ}
59220f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ
593c9d39130123238ac18478a42e25cb7996eacfcc0Jeff Garzikstatic inline unsigned int mv_hc_from_port(unsigned int port)
594c9d39130123238ac18478a42e25cb7996eacfcc0Jeff Garzik{
595c9d39130123238ac18478a42e25cb7996eacfcc0Jeff Garzik	return port >> MV_PORT_HC_SHIFT;
596c9d39130123238ac18478a42e25cb7996eacfcc0Jeff Garzik}
597c9d39130123238ac18478a42e25cb7996eacfcc0Jeff Garzik
598c9d39130123238ac18478a42e25cb7996eacfcc0Jeff Garzikstatic inline unsigned int mv_hardport_from_port(unsigned int port)
599c9d39130123238ac18478a42e25cb7996eacfcc0Jeff Garzik{
600c9d39130123238ac18478a42e25cb7996eacfcc0Jeff Garzik	return port & MV_PORT_MASK;
601c9d39130123238ac18478a42e25cb7996eacfcc0Jeff Garzik}
602c9d39130123238ac18478a42e25cb7996eacfcc0Jeff Garzik
603c9d39130123238ac18478a42e25cb7996eacfcc0Jeff Garzikstatic inline void __iomem *mv_hc_base_from_port(void __iomem *base,
604c9d39130123238ac18478a42e25cb7996eacfcc0Jeff Garzik						 unsigned int port)
605c9d39130123238ac18478a42e25cb7996eacfcc0Jeff Garzik{
606c9d39130123238ac18478a42e25cb7996eacfcc0Jeff Garzik	return mv_hc_base(base, mv_hc_from_port(port));
607c9d39130123238ac18478a42e25cb7996eacfcc0Jeff Garzik}
608c9d39130123238ac18478a42e25cb7996eacfcc0Jeff Garzik
60920f733e7d75a16bffc34842b7682c9247dd5f954Brett Russstatic inline void __iomem *mv_port_base(void __iomem *base, unsigned int port)
61020f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ{
611c9d39130123238ac18478a42e25cb7996eacfcc0Jeff Garzik	return  mv_hc_base_from_port(base, port) +
6128b260248d9e0e8b64bb72fd4dee03ad86984c344Jeff Garzik		MV_SATAHC_ARBTR_REG_SZ +
613c9d39130123238ac18478a42e25cb7996eacfcc0Jeff Garzik		(mv_hardport_from_port(port) * MV_PORT_REG_SZ);
61420f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ}
61520f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ
61620f733e7d75a16bffc34842b7682c9247dd5f954Brett Russstatic inline void __iomem *mv_ap_base(struct ata_port *ap)
61720f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ{
6180d5ff566779f894ca9937231a181eb31e4adff0eTejun Heo	return mv_port_base(ap->host->iomap[MV_PRIMARY_BAR], ap->port_no);
61920f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ}
62020f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ
621cca3974e48607c3775dc73b544a5700b2e37c21aJeff Garzikstatic inline int mv_get_hc_count(unsigned long port_flags)
62231961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ{
623cca3974e48607c3775dc73b544a5700b2e37c21aJeff Garzik	return ((port_flags & MV_FLAG_DUAL_HC) ? 2 : 1);
62431961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ}
62531961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ
62631961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russstatic void mv_irq_clear(struct ata_port *ap)
62720f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ{
62820f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ}
62920f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ
63005b308e1df6d9d673daedb517969241f41278b52Brett Russ/**
63105b308e1df6d9d673daedb517969241f41278b52Brett Russ *      mv_start_dma - Enable eDMA engine
63205b308e1df6d9d673daedb517969241f41278b52Brett Russ *      @base: port base address
63305b308e1df6d9d673daedb517969241f41278b52Brett Russ *      @pp: port private data
63405b308e1df6d9d673daedb517969241f41278b52Brett Russ *
635beec7dbc6ff003bbc94de62b3323519c878fb2acTejun Heo *      Verify the local cache of the eDMA state is accurate with a
636beec7dbc6ff003bbc94de62b3323519c878fb2acTejun Heo *      WARN_ON.
63705b308e1df6d9d673daedb517969241f41278b52Brett Russ *
63805b308e1df6d9d673daedb517969241f41278b52Brett Russ *      LOCKING:
63905b308e1df6d9d673daedb517969241f41278b52Brett Russ *      Inherited from caller.
64005b308e1df6d9d673daedb517969241f41278b52Brett Russ */
641afb0edd922c7ed6e73678730921dfcccebec17e8Brett Russstatic void mv_start_dma(void __iomem *base, struct mv_port_priv *pp)
64220f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ{
643afb0edd922c7ed6e73678730921dfcccebec17e8Brett Russ	if (!(MV_PP_FLAG_EDMA_EN & pp->pp_flags)) {
644afb0edd922c7ed6e73678730921dfcccebec17e8Brett Russ		writelfl(EDMA_EN, base + EDMA_CMD_OFS);
645afb0edd922c7ed6e73678730921dfcccebec17e8Brett Russ		pp->pp_flags |= MV_PP_FLAG_EDMA_EN;
646afb0edd922c7ed6e73678730921dfcccebec17e8Brett Russ	}
647beec7dbc6ff003bbc94de62b3323519c878fb2acTejun Heo	WARN_ON(!(EDMA_EN & readl(base + EDMA_CMD_OFS)));
64820f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ}
64920f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ
65005b308e1df6d9d673daedb517969241f41278b52Brett Russ/**
65105b308e1df6d9d673daedb517969241f41278b52Brett Russ *      mv_stop_dma - Disable eDMA engine
65205b308e1df6d9d673daedb517969241f41278b52Brett Russ *      @ap: ATA channel to manipulate
65305b308e1df6d9d673daedb517969241f41278b52Brett Russ *
654beec7dbc6ff003bbc94de62b3323519c878fb2acTejun Heo *      Verify the local cache of the eDMA state is accurate with a
655beec7dbc6ff003bbc94de62b3323519c878fb2acTejun Heo *      WARN_ON.
65605b308e1df6d9d673daedb517969241f41278b52Brett Russ *
65705b308e1df6d9d673daedb517969241f41278b52Brett Russ *      LOCKING:
65805b308e1df6d9d673daedb517969241f41278b52Brett Russ *      Inherited from caller.
65905b308e1df6d9d673daedb517969241f41278b52Brett Russ */
66031961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russstatic void mv_stop_dma(struct ata_port *ap)
66120f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ{
66231961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ	void __iomem *port_mmio = mv_ap_base(ap);
66331961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ	struct mv_port_priv *pp	= ap->private_data;
66431961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ	u32 reg;
66531961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ	int i;
66631961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ
667afb0edd922c7ed6e73678730921dfcccebec17e8Brett Russ	if (MV_PP_FLAG_EDMA_EN & pp->pp_flags) {
668afb0edd922c7ed6e73678730921dfcccebec17e8Brett Russ		/* Disable EDMA if active.   The disable bit auto clears.
66931961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ		 */
67031961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ		writelfl(EDMA_DS, port_mmio + EDMA_CMD_OFS);
67131961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ		pp->pp_flags &= ~MV_PP_FLAG_EDMA_EN;
672afb0edd922c7ed6e73678730921dfcccebec17e8Brett Russ	} else {
673beec7dbc6ff003bbc94de62b3323519c878fb2acTejun Heo		WARN_ON(EDMA_EN & readl(port_mmio + EDMA_CMD_OFS));
674afb0edd922c7ed6e73678730921dfcccebec17e8Brett Russ  	}
6758b260248d9e0e8b64bb72fd4dee03ad86984c344Jeff Garzik
67631961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ	/* now properly wait for the eDMA to stop */
67731961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ	for (i = 1000; i > 0; i--) {
67831961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ		reg = readl(port_mmio + EDMA_CMD_OFS);
67931961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ		if (!(EDMA_EN & reg)) {
68031961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ			break;
68131961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ		}
68231961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ		udelay(100);
68331961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ	}
68431961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ
68531961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ	if (EDMA_EN & reg) {
686f15a1dafed22d5037e0feea7528e1eeb28a1a7a3Tejun Heo		ata_port_printk(ap, KERN_ERR, "Unable to stop eDMA\n");
687afb0edd922c7ed6e73678730921dfcccebec17e8Brett Russ		/* FIXME: Consider doing a reset here to recover */
68831961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ	}
68920f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ}
69020f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ
6918a70f8dc08dd40b7f8ac77280eaa99a8c6bc46f4Jeff Garzik#ifdef ATA_DEBUG
69231961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russstatic void mv_dump_mem(void __iomem *start, unsigned bytes)
69320f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ{
69431961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ	int b, w;
69531961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ	for (b = 0; b < bytes; ) {
69631961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ		DPRINTK("%p: ", start + b);
69731961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ		for (w = 0; b < bytes && w < 4; w++) {
69831961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ			printk("%08x ",readl(start + b));
69931961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ			b += sizeof(u32);
70031961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ		}
70131961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ		printk("\n");
70231961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ	}
70331961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ}
7048a70f8dc08dd40b7f8ac77280eaa99a8c6bc46f4Jeff Garzik#endif
7058a70f8dc08dd40b7f8ac77280eaa99a8c6bc46f4Jeff Garzik
70631961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russstatic void mv_dump_pci_cfg(struct pci_dev *pdev, unsigned bytes)
70731961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ{
70831961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ#ifdef ATA_DEBUG
70931961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ	int b, w;
71031961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ	u32 dw;
71131961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ	for (b = 0; b < bytes; ) {
71231961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ		DPRINTK("%02x: ", b);
71331961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ		for (w = 0; b < bytes && w < 4; w++) {
71431961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ			(void) pci_read_config_dword(pdev,b,&dw);
71531961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ			printk("%08x ",dw);
71631961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ			b += sizeof(u32);
71731961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ		}
71831961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ		printk("\n");
71931961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ	}
72031961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ#endif
72131961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ}
72231961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russstatic void mv_dump_all_regs(void __iomem *mmio_base, int port,
72331961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ			     struct pci_dev *pdev)
72431961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ{
72531961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ#ifdef ATA_DEBUG
7268b260248d9e0e8b64bb72fd4dee03ad86984c344Jeff Garzik	void __iomem *hc_base = mv_hc_base(mmio_base,
72731961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ					   port >> MV_PORT_HC_SHIFT);
72831961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ	void __iomem *port_base;
72931961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ	int start_port, num_ports, p, start_hc, num_hcs, hc;
73031961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ
73131961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ	if (0 > port) {
73231961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ		start_hc = start_port = 0;
73331961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ		num_ports = 8;		/* shld be benign for 4 port devs */
73431961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ		num_hcs = 2;
73531961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ	} else {
73631961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ		start_hc = port >> MV_PORT_HC_SHIFT;
73731961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ		start_port = port;
73831961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ		num_ports = num_hcs = 1;
73931961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ	}
7408b260248d9e0e8b64bb72fd4dee03ad86984c344Jeff Garzik	DPRINTK("All registers for port(s) %u-%u:\n", start_port,
74131961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ		num_ports > 1 ? num_ports - 1 : start_port);
74231961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ
74331961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ	if (NULL != pdev) {
74431961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ		DPRINTK("PCI config space regs:\n");
74531961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ		mv_dump_pci_cfg(pdev, 0x68);
74631961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ	}
74731961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ	DPRINTK("PCI regs:\n");
74831961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ	mv_dump_mem(mmio_base+0xc00, 0x3c);
74931961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ	mv_dump_mem(mmio_base+0xd00, 0x34);
75031961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ	mv_dump_mem(mmio_base+0xf00, 0x4);
75131961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ	mv_dump_mem(mmio_base+0x1d00, 0x6c);
75231961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ	for (hc = start_hc; hc < start_hc + num_hcs; hc++) {
753d220c37e0a3c9a47ae00e87e044d963b3ea040bcDan Aloni		hc_base = mv_hc_base(mmio_base, hc);
75431961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ		DPRINTK("HC regs (HC %i):\n", hc);
75531961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ		mv_dump_mem(hc_base, 0x1c);
75631961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ	}
75731961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ	for (p = start_port; p < start_port + num_ports; p++) {
75831961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ		port_base = mv_port_base(mmio_base, p);
75931961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ		DPRINTK("EDMA regs (port %i):\n",p);
76031961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ		mv_dump_mem(port_base, 0x54);
76131961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ		DPRINTK("SATA regs (port %i):\n",p);
76231961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ		mv_dump_mem(port_base+0x300, 0x60);
76331961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ	}
76431961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ#endif
76520f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ}
76620f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ
76720f733e7d75a16bffc34842b7682c9247dd5f954Brett Russstatic unsigned int mv_scr_offset(unsigned int sc_reg_in)
76820f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ{
76920f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ	unsigned int ofs;
77020f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ
77120f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ	switch (sc_reg_in) {
77220f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ	case SCR_STATUS:
77320f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ	case SCR_CONTROL:
77420f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ	case SCR_ERROR:
77520f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ		ofs = SATA_STATUS_OFS + (sc_reg_in * sizeof(u32));
77620f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ		break;
77720f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ	case SCR_ACTIVE:
77820f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ		ofs = SATA_ACTIVE_OFS;   /* active is not with the others */
77920f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ		break;
78020f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ	default:
78120f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ		ofs = 0xffffffffU;
78220f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ		break;
78320f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ	}
78420f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ	return ofs;
78520f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ}
78620f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ
78720f733e7d75a16bffc34842b7682c9247dd5f954Brett Russstatic u32 mv_scr_read(struct ata_port *ap, unsigned int sc_reg_in)
78820f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ{
78920f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ	unsigned int ofs = mv_scr_offset(sc_reg_in);
79020f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ
79120f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ	if (0xffffffffU != ofs) {
79220f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ		return readl(mv_ap_base(ap) + ofs);
79320f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ	} else {
79420f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ		return (u32) ofs;
79520f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ	}
79620f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ}
79720f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ
79820f733e7d75a16bffc34842b7682c9247dd5f954Brett Russstatic void mv_scr_write(struct ata_port *ap, unsigned int sc_reg_in, u32 val)
79920f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ{
80020f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ	unsigned int ofs = mv_scr_offset(sc_reg_in);
80120f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ
80220f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ	if (0xffffffffU != ofs) {
80320f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ		writelfl(val, mv_ap_base(ap) + ofs);
80420f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ	}
80520f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ}
80620f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ
807e4e7b89280d1d666e2c09e5ad36cf071796c4c7eJeff Garzikstatic void mv_edma_cfg(struct mv_host_priv *hpriv, void __iomem *port_mmio)
808e4e7b89280d1d666e2c09e5ad36cf071796c4c7eJeff Garzik{
809e4e7b89280d1d666e2c09e5ad36cf071796c4c7eJeff Garzik	u32 cfg = readl(port_mmio + EDMA_CFG_OFS);
810e4e7b89280d1d666e2c09e5ad36cf071796c4c7eJeff Garzik
811e4e7b89280d1d666e2c09e5ad36cf071796c4c7eJeff Garzik	/* set up non-NCQ EDMA configuration */
812e4e7b89280d1d666e2c09e5ad36cf071796c4c7eJeff Garzik	cfg &= ~0x1f;		/* clear queue depth */
813e4e7b89280d1d666e2c09e5ad36cf071796c4c7eJeff Garzik	cfg &= ~EDMA_CFG_NCQ;	/* clear NCQ mode */
814e4e7b89280d1d666e2c09e5ad36cf071796c4c7eJeff Garzik	cfg &= ~(1 << 9);	/* disable equeue */
815e4e7b89280d1d666e2c09e5ad36cf071796c4c7eJeff Garzik
816e4e7b89280d1d666e2c09e5ad36cf071796c4c7eJeff Garzik	if (IS_GEN_I(hpriv))
817e4e7b89280d1d666e2c09e5ad36cf071796c4c7eJeff Garzik		cfg |= (1 << 8);	/* enab config burst size mask */
818e4e7b89280d1d666e2c09e5ad36cf071796c4c7eJeff Garzik
819e4e7b89280d1d666e2c09e5ad36cf071796c4c7eJeff Garzik	else if (IS_GEN_II(hpriv))
820e4e7b89280d1d666e2c09e5ad36cf071796c4c7eJeff Garzik		cfg |= EDMA_CFG_RD_BRST_EXT | EDMA_CFG_WR_BUFF_LEN;
821e4e7b89280d1d666e2c09e5ad36cf071796c4c7eJeff Garzik
822e4e7b89280d1d666e2c09e5ad36cf071796c4c7eJeff Garzik	else if (IS_GEN_IIE(hpriv)) {
823e4e7b89280d1d666e2c09e5ad36cf071796c4c7eJeff Garzik		cfg |= (1 << 23);	/* dis RX PM port mask */
824e4e7b89280d1d666e2c09e5ad36cf071796c4c7eJeff Garzik		cfg &= ~(1 << 16);	/* dis FIS-based switching (for now) */
825e4e7b89280d1d666e2c09e5ad36cf071796c4c7eJeff Garzik		cfg &= ~(1 << 19);	/* dis 128-entry queue (for now?) */
826e4e7b89280d1d666e2c09e5ad36cf071796c4c7eJeff Garzik		cfg |= (1 << 18);	/* enab early completion */
827e4e7b89280d1d666e2c09e5ad36cf071796c4c7eJeff Garzik		cfg |= (1 << 17);	/* enab host q cache */
828e4e7b89280d1d666e2c09e5ad36cf071796c4c7eJeff Garzik		cfg |= (1 << 22);	/* enab cutthrough */
829e4e7b89280d1d666e2c09e5ad36cf071796c4c7eJeff Garzik	}
830e4e7b89280d1d666e2c09e5ad36cf071796c4c7eJeff Garzik
831e4e7b89280d1d666e2c09e5ad36cf071796c4c7eJeff Garzik	writelfl(cfg, port_mmio + EDMA_CFG_OFS);
832e4e7b89280d1d666e2c09e5ad36cf071796c4c7eJeff Garzik}
833e4e7b89280d1d666e2c09e5ad36cf071796c4c7eJeff Garzik
83405b308e1df6d9d673daedb517969241f41278b52Brett Russ/**
83505b308e1df6d9d673daedb517969241f41278b52Brett Russ *      mv_port_start - Port specific init/start routine.
83605b308e1df6d9d673daedb517969241f41278b52Brett Russ *      @ap: ATA channel to manipulate
83705b308e1df6d9d673daedb517969241f41278b52Brett Russ *
83805b308e1df6d9d673daedb517969241f41278b52Brett Russ *      Allocate and point to DMA memory, init port private memory,
83905b308e1df6d9d673daedb517969241f41278b52Brett Russ *      zero indices.
84005b308e1df6d9d673daedb517969241f41278b52Brett Russ *
84105b308e1df6d9d673daedb517969241f41278b52Brett Russ *      LOCKING:
84205b308e1df6d9d673daedb517969241f41278b52Brett Russ *      Inherited from caller.
84305b308e1df6d9d673daedb517969241f41278b52Brett Russ */
84431961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russstatic int mv_port_start(struct ata_port *ap)
84531961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ{
846cca3974e48607c3775dc73b544a5700b2e37c21aJeff Garzik	struct device *dev = ap->host->dev;
847cca3974e48607c3775dc73b544a5700b2e37c21aJeff Garzik	struct mv_host_priv *hpriv = ap->host->private_data;
84831961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ	struct mv_port_priv *pp;
84931961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ	void __iomem *port_mmio = mv_ap_base(ap);
85031961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ	void *mem;
85131961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ	dma_addr_t mem_dma;
85224dc5f33ea4b504cfbd23fa159a4cacba8e4d800Tejun Heo	int rc;
85331961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ
85424dc5f33ea4b504cfbd23fa159a4cacba8e4d800Tejun Heo	pp = devm_kzalloc(dev, sizeof(*pp), GFP_KERNEL);
8556037d6bbdff65eb5a84fe35e140f4da4f7cc103aJeff Garzik	if (!pp)
85624dc5f33ea4b504cfbd23fa159a4cacba8e4d800Tejun Heo		return -ENOMEM;
85731961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ
85824dc5f33ea4b504cfbd23fa159a4cacba8e4d800Tejun Heo	mem = dmam_alloc_coherent(dev, MV_PORT_PRIV_DMA_SZ, &mem_dma,
85924dc5f33ea4b504cfbd23fa159a4cacba8e4d800Tejun Heo				  GFP_KERNEL);
8606037d6bbdff65eb5a84fe35e140f4da4f7cc103aJeff Garzik	if (!mem)
86124dc5f33ea4b504cfbd23fa159a4cacba8e4d800Tejun Heo		return -ENOMEM;
86231961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ	memset(mem, 0, MV_PORT_PRIV_DMA_SZ);
86331961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ
8646037d6bbdff65eb5a84fe35e140f4da4f7cc103aJeff Garzik	rc = ata_pad_alloc(ap, dev);
8656037d6bbdff65eb5a84fe35e140f4da4f7cc103aJeff Garzik	if (rc)
86624dc5f33ea4b504cfbd23fa159a4cacba8e4d800Tejun Heo		return rc;
8676037d6bbdff65eb5a84fe35e140f4da4f7cc103aJeff Garzik
8688b260248d9e0e8b64bb72fd4dee03ad86984c344Jeff Garzik	/* First item in chunk of DMA memory:
86931961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ	 * 32-slot command request table (CRQB), 32 bytes each in size
87031961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ	 */
87131961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ	pp->crqb = mem;
87231961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ	pp->crqb_dma = mem_dma;
87331961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ	mem += MV_CRQB_Q_SZ;
87431961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ	mem_dma += MV_CRQB_Q_SZ;
87531961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ
8768b260248d9e0e8b64bb72fd4dee03ad86984c344Jeff Garzik	/* Second item:
87731961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ	 * 32-slot command response table (CRPB), 8 bytes each in size
87831961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ	 */
87931961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ	pp->crpb = mem;
88031961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ	pp->crpb_dma = mem_dma;
88131961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ	mem += MV_CRPB_Q_SZ;
88231961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ	mem_dma += MV_CRPB_Q_SZ;
88331961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ
88431961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ	/* Third item:
88531961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ	 * Table of scatter-gather descriptors (ePRD), 16 bytes each
88631961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ	 */
88731961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ	pp->sg_tbl = mem;
88831961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ	pp->sg_tbl_dma = mem_dma;
88931961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ
890e4e7b89280d1d666e2c09e5ad36cf071796c4c7eJeff Garzik	mv_edma_cfg(hpriv, port_mmio);
89131961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ
89231961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ	writel((pp->crqb_dma >> 16) >> 16, port_mmio + EDMA_REQ_Q_BASE_HI_OFS);
8938b260248d9e0e8b64bb72fd4dee03ad86984c344Jeff Garzik	writelfl(pp->crqb_dma & EDMA_REQ_Q_BASE_LO_MASK,
89431961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ		 port_mmio + EDMA_REQ_Q_IN_PTR_OFS);
89531961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ
896e4e7b89280d1d666e2c09e5ad36cf071796c4c7eJeff Garzik	if (hpriv->hp_flags & MV_HP_ERRATA_XX42A0)
897e4e7b89280d1d666e2c09e5ad36cf071796c4c7eJeff Garzik		writelfl(pp->crqb_dma & 0xffffffff,
898e4e7b89280d1d666e2c09e5ad36cf071796c4c7eJeff Garzik			 port_mmio + EDMA_REQ_Q_OUT_PTR_OFS);
899e4e7b89280d1d666e2c09e5ad36cf071796c4c7eJeff Garzik	else
900e4e7b89280d1d666e2c09e5ad36cf071796c4c7eJeff Garzik		writelfl(0, port_mmio + EDMA_REQ_Q_OUT_PTR_OFS);
90131961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ
90231961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ	writel((pp->crpb_dma >> 16) >> 16, port_mmio + EDMA_RSP_Q_BASE_HI_OFS);
903e4e7b89280d1d666e2c09e5ad36cf071796c4c7eJeff Garzik
904e4e7b89280d1d666e2c09e5ad36cf071796c4c7eJeff Garzik	if (hpriv->hp_flags & MV_HP_ERRATA_XX42A0)
905e4e7b89280d1d666e2c09e5ad36cf071796c4c7eJeff Garzik		writelfl(pp->crpb_dma & 0xffffffff,
906e4e7b89280d1d666e2c09e5ad36cf071796c4c7eJeff Garzik			 port_mmio + EDMA_RSP_Q_IN_PTR_OFS);
907e4e7b89280d1d666e2c09e5ad36cf071796c4c7eJeff Garzik	else
908e4e7b89280d1d666e2c09e5ad36cf071796c4c7eJeff Garzik		writelfl(0, port_mmio + EDMA_RSP_Q_IN_PTR_OFS);
909e4e7b89280d1d666e2c09e5ad36cf071796c4c7eJeff Garzik
9108b260248d9e0e8b64bb72fd4dee03ad86984c344Jeff Garzik	writelfl(pp->crpb_dma & EDMA_RSP_Q_BASE_LO_MASK,
91131961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ		 port_mmio + EDMA_RSP_Q_OUT_PTR_OFS);
91231961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ
91331961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ	/* Don't turn on EDMA here...do it before DMA commands only.  Else
91431961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ	 * we'll be unable to send non-data, PIO, etc due to restricted access
91531961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ	 * to shadow regs.
91631961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ	 */
91731961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ	ap->private_data = pp;
91831961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ	return 0;
91931961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ}
92031961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ
92105b308e1df6d9d673daedb517969241f41278b52Brett Russ/**
92205b308e1df6d9d673daedb517969241f41278b52Brett Russ *      mv_port_stop - Port specific cleanup/stop routine.
92305b308e1df6d9d673daedb517969241f41278b52Brett Russ *      @ap: ATA channel to manipulate
92405b308e1df6d9d673daedb517969241f41278b52Brett Russ *
92505b308e1df6d9d673daedb517969241f41278b52Brett Russ *      Stop DMA, cleanup port memory.
92605b308e1df6d9d673daedb517969241f41278b52Brett Russ *
92705b308e1df6d9d673daedb517969241f41278b52Brett Russ *      LOCKING:
928cca3974e48607c3775dc73b544a5700b2e37c21aJeff Garzik *      This routine uses the host lock to protect the DMA stop.
92905b308e1df6d9d673daedb517969241f41278b52Brett Russ */
93031961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russstatic void mv_port_stop(struct ata_port *ap)
93131961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ{
932afb0edd922c7ed6e73678730921dfcccebec17e8Brett Russ	unsigned long flags;
93331961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ
934cca3974e48607c3775dc73b544a5700b2e37c21aJeff Garzik	spin_lock_irqsave(&ap->host->lock, flags);
93531961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ	mv_stop_dma(ap);
936cca3974e48607c3775dc73b544a5700b2e37c21aJeff Garzik	spin_unlock_irqrestore(&ap->host->lock, flags);
93731961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ}
93831961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ
93905b308e1df6d9d673daedb517969241f41278b52Brett Russ/**
94005b308e1df6d9d673daedb517969241f41278b52Brett Russ *      mv_fill_sg - Fill out the Marvell ePRD (scatter gather) entries
94105b308e1df6d9d673daedb517969241f41278b52Brett Russ *      @qc: queued command whose SG list to source from
94205b308e1df6d9d673daedb517969241f41278b52Brett Russ *
94305b308e1df6d9d673daedb517969241f41278b52Brett Russ *      Populate the SG list and mark the last entry.
94405b308e1df6d9d673daedb517969241f41278b52Brett Russ *
94505b308e1df6d9d673daedb517969241f41278b52Brett Russ *      LOCKING:
94605b308e1df6d9d673daedb517969241f41278b52Brett Russ *      Inherited from caller.
94705b308e1df6d9d673daedb517969241f41278b52Brett Russ */
94831961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russstatic void mv_fill_sg(struct ata_queued_cmd *qc)
94931961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ{
95031961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ	struct mv_port_priv *pp = qc->ap->private_data;
951972c26bdd6b58e7534473c4f7928584578cf43f4Jeff Garzik	unsigned int i = 0;
952972c26bdd6b58e7534473c4f7928584578cf43f4Jeff Garzik	struct scatterlist *sg;
95331961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ
954972c26bdd6b58e7534473c4f7928584578cf43f4Jeff Garzik	ata_for_each_sg(sg, qc) {
95531961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ		dma_addr_t addr;
95622374677d18c5eeefd3a283431d312b8c44fef02Jeff Garzik		u32 sg_len, len, offset;
95731961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ
958972c26bdd6b58e7534473c4f7928584578cf43f4Jeff Garzik		addr = sg_dma_address(sg);
959972c26bdd6b58e7534473c4f7928584578cf43f4Jeff Garzik		sg_len = sg_dma_len(sg);
96031961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ
96122374677d18c5eeefd3a283431d312b8c44fef02Jeff Garzik		while (sg_len) {
96222374677d18c5eeefd3a283431d312b8c44fef02Jeff Garzik			offset = addr & MV_DMA_BOUNDARY;
96322374677d18c5eeefd3a283431d312b8c44fef02Jeff Garzik			len = sg_len;
96422374677d18c5eeefd3a283431d312b8c44fef02Jeff Garzik			if ((offset + sg_len) > 0x10000)
96522374677d18c5eeefd3a283431d312b8c44fef02Jeff Garzik				len = 0x10000 - offset;
966972c26bdd6b58e7534473c4f7928584578cf43f4Jeff Garzik
96722374677d18c5eeefd3a283431d312b8c44fef02Jeff Garzik			pp->sg_tbl[i].addr = cpu_to_le32(addr & 0xffffffff);
96822374677d18c5eeefd3a283431d312b8c44fef02Jeff Garzik			pp->sg_tbl[i].addr_hi = cpu_to_le32((addr >> 16) >> 16);
96963af2a5c5990d95f1e7d8795f1425fb976ea2b4bMark Lord			pp->sg_tbl[i].flags_size = cpu_to_le32(len & 0xffff);
97022374677d18c5eeefd3a283431d312b8c44fef02Jeff Garzik
97122374677d18c5eeefd3a283431d312b8c44fef02Jeff Garzik			sg_len -= len;
97222374677d18c5eeefd3a283431d312b8c44fef02Jeff Garzik			addr += len;
97322374677d18c5eeefd3a283431d312b8c44fef02Jeff Garzik
97422374677d18c5eeefd3a283431d312b8c44fef02Jeff Garzik			if (!sg_len && ata_sg_is_last(sg, qc))
97522374677d18c5eeefd3a283431d312b8c44fef02Jeff Garzik				pp->sg_tbl[i].flags_size |= cpu_to_le32(EPRD_FLAG_END_OF_TBL);
97622374677d18c5eeefd3a283431d312b8c44fef02Jeff Garzik
97722374677d18c5eeefd3a283431d312b8c44fef02Jeff Garzik			i++;
97822374677d18c5eeefd3a283431d312b8c44fef02Jeff Garzik		}
97931961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ	}
98031961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ}
98131961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ
982a6432436c5e14b416f27c8f87c5bf0bc36771f49Mark Lordstatic inline unsigned mv_inc_q_index(unsigned index)
98331961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ{
984a6432436c5e14b416f27c8f87c5bf0bc36771f49Mark Lord	return (index + 1) & MV_MAX_Q_DEPTH_MASK;
98531961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ}
98631961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ
987e14698745dd0de1ddbf5cd0cca4313a90f8c1cc1Mark Lordstatic inline void mv_crqb_pack_cmd(__le16 *cmdw, u8 data, u8 addr, unsigned last)
98831961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ{
989559eedad7f7764dacca33980127b4615011230e4Mark Lord	u16 tmp = data | (addr << CRQB_CMD_ADDR_SHIFT) | CRQB_CMD_CS |
99031961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ		(last ? CRQB_CMD_LAST : 0);
991559eedad7f7764dacca33980127b4615011230e4Mark Lord	*cmdw = cpu_to_le16(tmp);
99231961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ}
99331961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ
99405b308e1df6d9d673daedb517969241f41278b52Brett Russ/**
99505b308e1df6d9d673daedb517969241f41278b52Brett Russ *      mv_qc_prep - Host specific command preparation.
99605b308e1df6d9d673daedb517969241f41278b52Brett Russ *      @qc: queued command to prepare
99705b308e1df6d9d673daedb517969241f41278b52Brett Russ *
99805b308e1df6d9d673daedb517969241f41278b52Brett Russ *      This routine simply redirects to the general purpose routine
99905b308e1df6d9d673daedb517969241f41278b52Brett Russ *      if command is not DMA.  Else, it handles prep of the CRQB
100005b308e1df6d9d673daedb517969241f41278b52Brett Russ *      (command request block), does some sanity checking, and calls
100105b308e1df6d9d673daedb517969241f41278b52Brett Russ *      the SG load routine.
100205b308e1df6d9d673daedb517969241f41278b52Brett Russ *
100305b308e1df6d9d673daedb517969241f41278b52Brett Russ *      LOCKING:
100405b308e1df6d9d673daedb517969241f41278b52Brett Russ *      Inherited from caller.
100505b308e1df6d9d673daedb517969241f41278b52Brett Russ */
100631961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russstatic void mv_qc_prep(struct ata_queued_cmd *qc)
100731961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ{
100831961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ	struct ata_port *ap = qc->ap;
100931961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ	struct mv_port_priv *pp = ap->private_data;
1010e14698745dd0de1ddbf5cd0cca4313a90f8c1cc1Mark Lord	__le16 *cw;
101131961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ	struct ata_taskfile *tf;
101231961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ	u16 flags = 0;
1013a6432436c5e14b416f27c8f87c5bf0bc36771f49Mark Lord	unsigned in_index;
101431961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ
1015e4e7b89280d1d666e2c09e5ad36cf071796c4c7eJeff Garzik 	if (ATA_PROT_DMA != qc->tf.protocol)
101631961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ		return;
101720f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ
101831961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ	/* Fill in command request block
101931961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ	 */
1020e4e7b89280d1d666e2c09e5ad36cf071796c4c7eJeff Garzik	if (!(qc->tf.flags & ATA_TFLAG_WRITE))
102131961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ		flags |= CRQB_FLAG_READ;
1022beec7dbc6ff003bbc94de62b3323519c878fb2acTejun Heo	WARN_ON(MV_MAX_Q_DEPTH <= qc->tag);
102331961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ	flags |= qc->tag << CRQB_TAG_SHIFT;
102431961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ
1025a6432436c5e14b416f27c8f87c5bf0bc36771f49Mark Lord	/* get current queue index from hardware */
1026a6432436c5e14b416f27c8f87c5bf0bc36771f49Mark Lord	in_index = (readl(mv_ap_base(ap) + EDMA_REQ_Q_IN_PTR_OFS)
1027a6432436c5e14b416f27c8f87c5bf0bc36771f49Mark Lord			>> EDMA_REQ_Q_PTR_SHIFT) & MV_MAX_Q_DEPTH_MASK;
1028a6432436c5e14b416f27c8f87c5bf0bc36771f49Mark Lord
1029a6432436c5e14b416f27c8f87c5bf0bc36771f49Mark Lord	pp->crqb[in_index].sg_addr =
103031961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ		cpu_to_le32(pp->sg_tbl_dma & 0xffffffff);
1031a6432436c5e14b416f27c8f87c5bf0bc36771f49Mark Lord	pp->crqb[in_index].sg_addr_hi =
103231961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ		cpu_to_le32((pp->sg_tbl_dma >> 16) >> 16);
1033a6432436c5e14b416f27c8f87c5bf0bc36771f49Mark Lord	pp->crqb[in_index].ctrl_flags = cpu_to_le16(flags);
103431961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ
1035a6432436c5e14b416f27c8f87c5bf0bc36771f49Mark Lord	cw = &pp->crqb[in_index].ata_cmd[0];
103631961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ	tf = &qc->tf;
103731961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ
103831961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ	/* Sadly, the CRQB cannot accomodate all registers--there are
103931961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ	 * only 11 bytes...so we must pick and choose required
104031961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ	 * registers based on the command.  So, we drop feature and
104131961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ	 * hob_feature for [RW] DMA commands, but they are needed for
104231961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ	 * NCQ.  NCQ will drop hob_nsect.
104320f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ	 */
104431961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ	switch (tf->command) {
104531961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ	case ATA_CMD_READ:
104631961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ	case ATA_CMD_READ_EXT:
104731961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ	case ATA_CMD_WRITE:
104831961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ	case ATA_CMD_WRITE_EXT:
1049c15d85c8f3f73b5f20aae7928e25b6996f16b328Jens Axboe	case ATA_CMD_WRITE_FUA_EXT:
105031961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ		mv_crqb_pack_cmd(cw++, tf->hob_nsect, ATA_REG_NSECT, 0);
105131961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ		break;
105231961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ#ifdef LIBATA_NCQ		/* FIXME: remove this line when NCQ added */
105331961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ	case ATA_CMD_FPDMA_READ:
105431961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ	case ATA_CMD_FPDMA_WRITE:
10558b260248d9e0e8b64bb72fd4dee03ad86984c344Jeff Garzik		mv_crqb_pack_cmd(cw++, tf->hob_feature, ATA_REG_FEATURE, 0);
105631961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ		mv_crqb_pack_cmd(cw++, tf->feature, ATA_REG_FEATURE, 0);
105731961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ		break;
105831961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ#endif				/* FIXME: remove this line when NCQ added */
105931961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ	default:
106031961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ		/* The only other commands EDMA supports in non-queued and
106131961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ		 * non-NCQ mode are: [RW] STREAM DMA and W DMA FUA EXT, none
106231961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ		 * of which are defined/used by Linux.  If we get here, this
106331961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ		 * driver needs work.
106431961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ		 *
106531961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ		 * FIXME: modify libata to give qc_prep a return value and
106631961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ		 * return error here.
106731961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ		 */
106831961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ		BUG_ON(tf->command);
106931961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ		break;
107031961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ	}
107131961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ	mv_crqb_pack_cmd(cw++, tf->nsect, ATA_REG_NSECT, 0);
107231961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ	mv_crqb_pack_cmd(cw++, tf->hob_lbal, ATA_REG_LBAL, 0);
107331961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ	mv_crqb_pack_cmd(cw++, tf->lbal, ATA_REG_LBAL, 0);
107431961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ	mv_crqb_pack_cmd(cw++, tf->hob_lbam, ATA_REG_LBAM, 0);
107531961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ	mv_crqb_pack_cmd(cw++, tf->lbam, ATA_REG_LBAM, 0);
107631961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ	mv_crqb_pack_cmd(cw++, tf->hob_lbah, ATA_REG_LBAH, 0);
107731961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ	mv_crqb_pack_cmd(cw++, tf->lbah, ATA_REG_LBAH, 0);
107831961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ	mv_crqb_pack_cmd(cw++, tf->device, ATA_REG_DEVICE, 0);
107931961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ	mv_crqb_pack_cmd(cw++, tf->command, ATA_REG_CMD, 1);	/* last */
108031961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ
1081e4e7b89280d1d666e2c09e5ad36cf071796c4c7eJeff Garzik	if (!(qc->flags & ATA_QCFLAG_DMAMAP))
1082e4e7b89280d1d666e2c09e5ad36cf071796c4c7eJeff Garzik		return;
1083e4e7b89280d1d666e2c09e5ad36cf071796c4c7eJeff Garzik	mv_fill_sg(qc);
1084e4e7b89280d1d666e2c09e5ad36cf071796c4c7eJeff Garzik}
1085e4e7b89280d1d666e2c09e5ad36cf071796c4c7eJeff Garzik
1086e4e7b89280d1d666e2c09e5ad36cf071796c4c7eJeff Garzik/**
1087e4e7b89280d1d666e2c09e5ad36cf071796c4c7eJeff Garzik *      mv_qc_prep_iie - Host specific command preparation.
1088e4e7b89280d1d666e2c09e5ad36cf071796c4c7eJeff Garzik *      @qc: queued command to prepare
1089e4e7b89280d1d666e2c09e5ad36cf071796c4c7eJeff Garzik *
1090e4e7b89280d1d666e2c09e5ad36cf071796c4c7eJeff Garzik *      This routine simply redirects to the general purpose routine
1091e4e7b89280d1d666e2c09e5ad36cf071796c4c7eJeff Garzik *      if command is not DMA.  Else, it handles prep of the CRQB
1092e4e7b89280d1d666e2c09e5ad36cf071796c4c7eJeff Garzik *      (command request block), does some sanity checking, and calls
1093e4e7b89280d1d666e2c09e5ad36cf071796c4c7eJeff Garzik *      the SG load routine.
1094e4e7b89280d1d666e2c09e5ad36cf071796c4c7eJeff Garzik *
1095e4e7b89280d1d666e2c09e5ad36cf071796c4c7eJeff Garzik *      LOCKING:
1096e4e7b89280d1d666e2c09e5ad36cf071796c4c7eJeff Garzik *      Inherited from caller.
1097e4e7b89280d1d666e2c09e5ad36cf071796c4c7eJeff Garzik */
1098e4e7b89280d1d666e2c09e5ad36cf071796c4c7eJeff Garzikstatic void mv_qc_prep_iie(struct ata_queued_cmd *qc)
1099e4e7b89280d1d666e2c09e5ad36cf071796c4c7eJeff Garzik{
1100e4e7b89280d1d666e2c09e5ad36cf071796c4c7eJeff Garzik	struct ata_port *ap = qc->ap;
1101e4e7b89280d1d666e2c09e5ad36cf071796c4c7eJeff Garzik	struct mv_port_priv *pp = ap->private_data;
1102e4e7b89280d1d666e2c09e5ad36cf071796c4c7eJeff Garzik	struct mv_crqb_iie *crqb;
1103e4e7b89280d1d666e2c09e5ad36cf071796c4c7eJeff Garzik	struct ata_taskfile *tf;
1104a6432436c5e14b416f27c8f87c5bf0bc36771f49Mark Lord	unsigned in_index;
1105e4e7b89280d1d666e2c09e5ad36cf071796c4c7eJeff Garzik	u32 flags = 0;
1106e4e7b89280d1d666e2c09e5ad36cf071796c4c7eJeff Garzik
1107e4e7b89280d1d666e2c09e5ad36cf071796c4c7eJeff Garzik 	if (ATA_PROT_DMA != qc->tf.protocol)
1108e4e7b89280d1d666e2c09e5ad36cf071796c4c7eJeff Garzik		return;
1109e4e7b89280d1d666e2c09e5ad36cf071796c4c7eJeff Garzik
1110e4e7b89280d1d666e2c09e5ad36cf071796c4c7eJeff Garzik	/* Fill in Gen IIE command request block
1111e4e7b89280d1d666e2c09e5ad36cf071796c4c7eJeff Garzik	 */
1112e4e7b89280d1d666e2c09e5ad36cf071796c4c7eJeff Garzik	if (!(qc->tf.flags & ATA_TFLAG_WRITE))
1113e4e7b89280d1d666e2c09e5ad36cf071796c4c7eJeff Garzik		flags |= CRQB_FLAG_READ;
1114e4e7b89280d1d666e2c09e5ad36cf071796c4c7eJeff Garzik
1115beec7dbc6ff003bbc94de62b3323519c878fb2acTejun Heo	WARN_ON(MV_MAX_Q_DEPTH <= qc->tag);
1116e4e7b89280d1d666e2c09e5ad36cf071796c4c7eJeff Garzik	flags |= qc->tag << CRQB_TAG_SHIFT;
1117e4e7b89280d1d666e2c09e5ad36cf071796c4c7eJeff Garzik
1118a6432436c5e14b416f27c8f87c5bf0bc36771f49Mark Lord	/* get current queue index from hardware */
1119a6432436c5e14b416f27c8f87c5bf0bc36771f49Mark Lord	in_index = (readl(mv_ap_base(ap) + EDMA_REQ_Q_IN_PTR_OFS)
1120a6432436c5e14b416f27c8f87c5bf0bc36771f49Mark Lord			>> EDMA_REQ_Q_PTR_SHIFT) & MV_MAX_Q_DEPTH_MASK;
1121a6432436c5e14b416f27c8f87c5bf0bc36771f49Mark Lord
1122a6432436c5e14b416f27c8f87c5bf0bc36771f49Mark Lord	crqb = (struct mv_crqb_iie *) &pp->crqb[in_index];
1123e4e7b89280d1d666e2c09e5ad36cf071796c4c7eJeff Garzik	crqb->addr = cpu_to_le32(pp->sg_tbl_dma & 0xffffffff);
1124e4e7b89280d1d666e2c09e5ad36cf071796c4c7eJeff Garzik	crqb->addr_hi = cpu_to_le32((pp->sg_tbl_dma >> 16) >> 16);
1125e4e7b89280d1d666e2c09e5ad36cf071796c4c7eJeff Garzik	crqb->flags = cpu_to_le32(flags);
1126e4e7b89280d1d666e2c09e5ad36cf071796c4c7eJeff Garzik
1127e4e7b89280d1d666e2c09e5ad36cf071796c4c7eJeff Garzik	tf = &qc->tf;
1128e4e7b89280d1d666e2c09e5ad36cf071796c4c7eJeff Garzik	crqb->ata_cmd[0] = cpu_to_le32(
1129e4e7b89280d1d666e2c09e5ad36cf071796c4c7eJeff Garzik			(tf->command << 16) |
1130e4e7b89280d1d666e2c09e5ad36cf071796c4c7eJeff Garzik			(tf->feature << 24)
1131e4e7b89280d1d666e2c09e5ad36cf071796c4c7eJeff Garzik		);
1132e4e7b89280d1d666e2c09e5ad36cf071796c4c7eJeff Garzik	crqb->ata_cmd[1] = cpu_to_le32(
1133e4e7b89280d1d666e2c09e5ad36cf071796c4c7eJeff Garzik			(tf->lbal << 0) |
1134e4e7b89280d1d666e2c09e5ad36cf071796c4c7eJeff Garzik			(tf->lbam << 8) |
1135e4e7b89280d1d666e2c09e5ad36cf071796c4c7eJeff Garzik			(tf->lbah << 16) |
1136e4e7b89280d1d666e2c09e5ad36cf071796c4c7eJeff Garzik			(tf->device << 24)
1137e4e7b89280d1d666e2c09e5ad36cf071796c4c7eJeff Garzik		);
1138e4e7b89280d1d666e2c09e5ad36cf071796c4c7eJeff Garzik	crqb->ata_cmd[2] = cpu_to_le32(
1139e4e7b89280d1d666e2c09e5ad36cf071796c4c7eJeff Garzik			(tf->hob_lbal << 0) |
1140e4e7b89280d1d666e2c09e5ad36cf071796c4c7eJeff Garzik			(tf->hob_lbam << 8) |
1141e4e7b89280d1d666e2c09e5ad36cf071796c4c7eJeff Garzik			(tf->hob_lbah << 16) |
1142e4e7b89280d1d666e2c09e5ad36cf071796c4c7eJeff Garzik			(tf->hob_feature << 24)
1143e4e7b89280d1d666e2c09e5ad36cf071796c4c7eJeff Garzik		);
1144e4e7b89280d1d666e2c09e5ad36cf071796c4c7eJeff Garzik	crqb->ata_cmd[3] = cpu_to_le32(
1145e4e7b89280d1d666e2c09e5ad36cf071796c4c7eJeff Garzik			(tf->nsect << 0) |
1146e4e7b89280d1d666e2c09e5ad36cf071796c4c7eJeff Garzik			(tf->hob_nsect << 8)
1147e4e7b89280d1d666e2c09e5ad36cf071796c4c7eJeff Garzik		);
1148e4e7b89280d1d666e2c09e5ad36cf071796c4c7eJeff Garzik
1149e4e7b89280d1d666e2c09e5ad36cf071796c4c7eJeff Garzik	if (!(qc->flags & ATA_QCFLAG_DMAMAP))
115031961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ		return;
115131961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ	mv_fill_sg(qc);
115231961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ}
115331961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ
115405b308e1df6d9d673daedb517969241f41278b52Brett Russ/**
115505b308e1df6d9d673daedb517969241f41278b52Brett Russ *      mv_qc_issue - Initiate a command to the host
115605b308e1df6d9d673daedb517969241f41278b52Brett Russ *      @qc: queued command to start
115705b308e1df6d9d673daedb517969241f41278b52Brett Russ *
115805b308e1df6d9d673daedb517969241f41278b52Brett Russ *      This routine simply redirects to the general purpose routine
115905b308e1df6d9d673daedb517969241f41278b52Brett Russ *      if command is not DMA.  Else, it sanity checks our local
116005b308e1df6d9d673daedb517969241f41278b52Brett Russ *      caches of the request producer/consumer indices then enables
116105b308e1df6d9d673daedb517969241f41278b52Brett Russ *      DMA and bumps the request producer index.
116205b308e1df6d9d673daedb517969241f41278b52Brett Russ *
116305b308e1df6d9d673daedb517969241f41278b52Brett Russ *      LOCKING:
116405b308e1df6d9d673daedb517969241f41278b52Brett Russ *      Inherited from caller.
116505b308e1df6d9d673daedb517969241f41278b52Brett Russ */
11669a3d9eb0177eb10500d49cd283b35576082a522dTejun Heostatic unsigned int mv_qc_issue(struct ata_queued_cmd *qc)
116731961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ{
116831961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ	void __iomem *port_mmio = mv_ap_base(qc->ap);
116931961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ	struct mv_port_priv *pp = qc->ap->private_data;
1170a6432436c5e14b416f27c8f87c5bf0bc36771f49Mark Lord	unsigned in_index;
117131961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ	u32 in_ptr;
117231961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ
117331961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ	if (ATA_PROT_DMA != qc->tf.protocol) {
117431961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ		/* We're about to send a non-EDMA capable command to the
117531961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ		 * port.  Turn off EDMA so there won't be problems accessing
117631961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ		 * shadow block, etc registers.
117731961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ		 */
117831961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ		mv_stop_dma(qc->ap);
117931961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ		return ata_qc_issue_prot(qc);
118031961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ	}
118131961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ
1182a6432436c5e14b416f27c8f87c5bf0bc36771f49Mark Lord	in_ptr   = readl(port_mmio + EDMA_REQ_Q_IN_PTR_OFS);
1183a6432436c5e14b416f27c8f87c5bf0bc36771f49Mark Lord	in_index = (in_ptr >> EDMA_REQ_Q_PTR_SHIFT) & MV_MAX_Q_DEPTH_MASK;
118431961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ
118531961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ	/* until we do queuing, the queue should be empty at this point */
1186a6432436c5e14b416f27c8f87c5bf0bc36771f49Mark Lord	WARN_ON(in_index != ((readl(port_mmio + EDMA_REQ_Q_OUT_PTR_OFS)
1187a6432436c5e14b416f27c8f87c5bf0bc36771f49Mark Lord		>> EDMA_REQ_Q_PTR_SHIFT) & MV_MAX_Q_DEPTH_MASK));
118831961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ
1189a6432436c5e14b416f27c8f87c5bf0bc36771f49Mark Lord	in_index = mv_inc_q_index(in_index);	/* now incr producer index */
119031961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ
1191afb0edd922c7ed6e73678730921dfcccebec17e8Brett Russ	mv_start_dma(port_mmio, pp);
119231961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ
119331961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ	/* and write the request in pointer to kick the EDMA to life */
119431961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ	in_ptr &= EDMA_REQ_Q_BASE_LO_MASK;
1195a6432436c5e14b416f27c8f87c5bf0bc36771f49Mark Lord	in_ptr |= in_index << EDMA_REQ_Q_PTR_SHIFT;
119631961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ	writelfl(in_ptr, port_mmio + EDMA_REQ_Q_IN_PTR_OFS);
119731961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ
119831961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ	return 0;
119931961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ}
120031961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ
120105b308e1df6d9d673daedb517969241f41278b52Brett Russ/**
120205b308e1df6d9d673daedb517969241f41278b52Brett Russ *      mv_get_crpb_status - get status from most recently completed cmd
120305b308e1df6d9d673daedb517969241f41278b52Brett Russ *      @ap: ATA channel to manipulate
120405b308e1df6d9d673daedb517969241f41278b52Brett Russ *
120505b308e1df6d9d673daedb517969241f41278b52Brett Russ *      This routine is for use when the port is in DMA mode, when it
120605b308e1df6d9d673daedb517969241f41278b52Brett Russ *      will be using the CRPB (command response block) method of
1207beec7dbc6ff003bbc94de62b3323519c878fb2acTejun Heo *      returning command completion information.  We check indices
120805b308e1df6d9d673daedb517969241f41278b52Brett Russ *      are good, grab status, and bump the response consumer index to
120905b308e1df6d9d673daedb517969241f41278b52Brett Russ *      prove that we're up to date.
121005b308e1df6d9d673daedb517969241f41278b52Brett Russ *
121105b308e1df6d9d673daedb517969241f41278b52Brett Russ *      LOCKING:
121205b308e1df6d9d673daedb517969241f41278b52Brett Russ *      Inherited from caller.
121305b308e1df6d9d673daedb517969241f41278b52Brett Russ */
121431961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russstatic u8 mv_get_crpb_status(struct ata_port *ap)
121531961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ{
121631961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ	void __iomem *port_mmio = mv_ap_base(ap);
121731961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ	struct mv_port_priv *pp = ap->private_data;
1218a6432436c5e14b416f27c8f87c5bf0bc36771f49Mark Lord	unsigned out_index;
121931961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ	u32 out_ptr;
1220806a6e7a9904d4a1dfd3fd79d373bf31d71d34cbMark Lord	u8 ata_status;
122131961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ
1222a6432436c5e14b416f27c8f87c5bf0bc36771f49Mark Lord	out_ptr   = readl(port_mmio + EDMA_RSP_Q_OUT_PTR_OFS);
1223a6432436c5e14b416f27c8f87c5bf0bc36771f49Mark Lord	out_index = (out_ptr >> EDMA_RSP_Q_PTR_SHIFT) & MV_MAX_Q_DEPTH_MASK;
122431961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ
1225a6432436c5e14b416f27c8f87c5bf0bc36771f49Mark Lord	ata_status = le16_to_cpu(pp->crpb[out_index].flags)
1226a6432436c5e14b416f27c8f87c5bf0bc36771f49Mark Lord					>> CRPB_FLAG_STATUS_SHIFT;
1227806a6e7a9904d4a1dfd3fd79d373bf31d71d34cbMark Lord
122831961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ	/* increment our consumer index... */
1229a6432436c5e14b416f27c8f87c5bf0bc36771f49Mark Lord	out_index = mv_inc_q_index(out_index);
12308b260248d9e0e8b64bb72fd4dee03ad86984c344Jeff Garzik
123131961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ	/* and, until we do NCQ, there should only be 1 CRPB waiting */
1232a6432436c5e14b416f27c8f87c5bf0bc36771f49Mark Lord	WARN_ON(out_index != ((readl(port_mmio + EDMA_RSP_Q_IN_PTR_OFS)
1233a6432436c5e14b416f27c8f87c5bf0bc36771f49Mark Lord		>> EDMA_RSP_Q_PTR_SHIFT) & MV_MAX_Q_DEPTH_MASK));
123431961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ
123531961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ	/* write out our inc'd consumer index so EDMA knows we're caught up */
123631961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ	out_ptr &= EDMA_RSP_Q_BASE_LO_MASK;
1237a6432436c5e14b416f27c8f87c5bf0bc36771f49Mark Lord	out_ptr |= out_index << EDMA_RSP_Q_PTR_SHIFT;
123831961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ	writelfl(out_ptr, port_mmio + EDMA_RSP_Q_OUT_PTR_OFS);
123931961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ
124031961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ	/* Return ATA status register for completed CRPB */
1241806a6e7a9904d4a1dfd3fd79d373bf31d71d34cbMark Lord	return ata_status;
124231961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ}
124331961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ
124405b308e1df6d9d673daedb517969241f41278b52Brett Russ/**
124505b308e1df6d9d673daedb517969241f41278b52Brett Russ *      mv_err_intr - Handle error interrupts on the port
124605b308e1df6d9d673daedb517969241f41278b52Brett Russ *      @ap: ATA channel to manipulate
12479b358e305c1d783c8a4ebf00344e95deb9e38f3dMark Lord *      @reset_allowed: bool: 0 == don't trigger from reset here
124805b308e1df6d9d673daedb517969241f41278b52Brett Russ *
124905b308e1df6d9d673daedb517969241f41278b52Brett Russ *      In most cases, just clear the interrupt and move on.  However,
125005b308e1df6d9d673daedb517969241f41278b52Brett Russ *      some cases require an eDMA reset, which is done right before
125105b308e1df6d9d673daedb517969241f41278b52Brett Russ *      the COMRESET in mv_phy_reset().  The SERR case requires a
125205b308e1df6d9d673daedb517969241f41278b52Brett Russ *      clear of pending errors in the SATA SERROR register.  Finally,
125305b308e1df6d9d673daedb517969241f41278b52Brett Russ *      if the port disabled DMA, update our cached copy to match.
125405b308e1df6d9d673daedb517969241f41278b52Brett Russ *
125505b308e1df6d9d673daedb517969241f41278b52Brett Russ *      LOCKING:
125605b308e1df6d9d673daedb517969241f41278b52Brett Russ *      Inherited from caller.
125705b308e1df6d9d673daedb517969241f41278b52Brett Russ */
12589b358e305c1d783c8a4ebf00344e95deb9e38f3dMark Lordstatic void mv_err_intr(struct ata_port *ap, int reset_allowed)
125931961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ{
126031961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ	void __iomem *port_mmio = mv_ap_base(ap);
126131961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ	u32 edma_err_cause, serr = 0;
126220f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ
126320f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ	edma_err_cause = readl(port_mmio + EDMA_ERR_IRQ_CAUSE_OFS);
126420f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ
126520f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ	if (EDMA_ERR_SERR & edma_err_cause) {
126681952c5497b40ae56835bd0d6537f8c6bdea07e7Tejun Heo		sata_scr_read(ap, SCR_ERROR, &serr);
126781952c5497b40ae56835bd0d6537f8c6bdea07e7Tejun Heo		sata_scr_write_flush(ap, SCR_ERROR, serr);
126820f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ	}
1269afb0edd922c7ed6e73678730921dfcccebec17e8Brett Russ	if (EDMA_ERR_SELF_DIS & edma_err_cause) {
1270afb0edd922c7ed6e73678730921dfcccebec17e8Brett Russ		struct mv_port_priv *pp	= ap->private_data;
1271afb0edd922c7ed6e73678730921dfcccebec17e8Brett Russ		pp->pp_flags &= ~MV_PP_FLAG_EDMA_EN;
1272afb0edd922c7ed6e73678730921dfcccebec17e8Brett Russ	}
1273afb0edd922c7ed6e73678730921dfcccebec17e8Brett Russ	DPRINTK(KERN_ERR "ata%u: port error; EDMA err cause: 0x%08x "
1274afb0edd922c7ed6e73678730921dfcccebec17e8Brett Russ		"SERR: 0x%08x\n", ap->id, edma_err_cause, serr);
127520f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ
127620f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ	/* Clear EDMA now that SERR cleanup done */
127720f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ	writelfl(0, port_mmio + EDMA_ERR_IRQ_CAUSE_OFS);
127820f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ
127920f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ	/* check for fatal here and recover if needed */
12809b358e305c1d783c8a4ebf00344e95deb9e38f3dMark Lord	if (reset_allowed && (EDMA_ERR_FATAL & edma_err_cause))
1281c9d39130123238ac18478a42e25cb7996eacfcc0Jeff Garzik		mv_stop_and_reset(ap);
128220f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ}
128320f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ
128405b308e1df6d9d673daedb517969241f41278b52Brett Russ/**
128505b308e1df6d9d673daedb517969241f41278b52Brett Russ *      mv_host_intr - Handle all interrupts on the given host controller
1286cca3974e48607c3775dc73b544a5700b2e37c21aJeff Garzik *      @host: host specific structure
128705b308e1df6d9d673daedb517969241f41278b52Brett Russ *      @relevant: port error bits relevant to this host controller
128805b308e1df6d9d673daedb517969241f41278b52Brett Russ *      @hc: which host controller we're to look at
128905b308e1df6d9d673daedb517969241f41278b52Brett Russ *
129005b308e1df6d9d673daedb517969241f41278b52Brett Russ *      Read then write clear the HC interrupt status then walk each
129105b308e1df6d9d673daedb517969241f41278b52Brett Russ *      port connected to the HC and see if it needs servicing.  Port
129205b308e1df6d9d673daedb517969241f41278b52Brett Russ *      success ints are reported in the HC interrupt status reg, the
129305b308e1df6d9d673daedb517969241f41278b52Brett Russ *      port error ints are reported in the higher level main
129405b308e1df6d9d673daedb517969241f41278b52Brett Russ *      interrupt status register and thus are passed in via the
129505b308e1df6d9d673daedb517969241f41278b52Brett Russ *      'relevant' argument.
129605b308e1df6d9d673daedb517969241f41278b52Brett Russ *
129705b308e1df6d9d673daedb517969241f41278b52Brett Russ *      LOCKING:
129805b308e1df6d9d673daedb517969241f41278b52Brett Russ *      Inherited from caller.
129905b308e1df6d9d673daedb517969241f41278b52Brett Russ */
1300cca3974e48607c3775dc73b544a5700b2e37c21aJeff Garzikstatic void mv_host_intr(struct ata_host *host, u32 relevant, unsigned int hc)
130120f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ{
13020d5ff566779f894ca9937231a181eb31e4adff0eTejun Heo	void __iomem *mmio = host->iomap[MV_PRIMARY_BAR];
130320f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ	void __iomem *hc_mmio = mv_hc_base(mmio, hc);
130420f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ	struct ata_queued_cmd *qc;
130520f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ	u32 hc_irq_cause;
130631961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ	int shift, port, port0, hard_port, handled;
1307a7dac447bb9cef27d4d29cdf63e2d7809c50b1f4Jeff Garzik	unsigned int err_mask;
130820f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ
130920f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ	if (hc == 0) {
131020f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ		port0 = 0;
131120f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ	} else {
131220f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ		port0 = MV_PORTS_PER_HC;
131320f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ	}
131420f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ
131520f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ	/* we'll need the HC success int register in most cases */
131620f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ	hc_irq_cause = readl(hc_mmio + HC_IRQ_CAUSE_OFS);
131720f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ	if (hc_irq_cause) {
131831961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ		writelfl(~hc_irq_cause, hc_mmio + HC_IRQ_CAUSE_OFS);
131920f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ	}
132020f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ
132120f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ	VPRINTK("ENTER, hc%u relevant=0x%08x HC IRQ cause=0x%08x\n",
132220f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ		hc,relevant,hc_irq_cause);
132320f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ
132420f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ	for (port = port0; port < port0 + MV_PORTS_PER_HC; port++) {
1325cd85f6e2f58282186ad720fc18482be228f0b972Jeff Garzik		u8 ata_status = 0;
1326cca3974e48607c3775dc73b544a5700b2e37c21aJeff Garzik		struct ata_port *ap = host->ports[port];
132763af2a5c5990d95f1e7d8795f1425fb976ea2b4bMark Lord		struct mv_port_priv *pp = ap->private_data;
132855d8ca4f8094246da6e71889a4e04bfafaa78b10Jeff Garzik
1329e857f141945f29c16f72ffcfdbce097f8be6c4e9Mark Lord		hard_port = mv_hardport_from_port(port); /* range 0..3 */
133031961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ		handled = 0;	/* ensure ata_status is set if handled++ */
133120f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ
133263af2a5c5990d95f1e7d8795f1425fb976ea2b4bMark Lord		/* Note that DEV_IRQ might happen spuriously during EDMA,
1333e857f141945f29c16f72ffcfdbce097f8be6c4e9Mark Lord		 * and should be ignored in such cases.
1334e857f141945f29c16f72ffcfdbce097f8be6c4e9Mark Lord		 * The cause of this is still under investigation.
13358190bdb9291758f3b8c436ec1154c9923ddb57eaJeff Garzik		 */
133663af2a5c5990d95f1e7d8795f1425fb976ea2b4bMark Lord		if (pp->pp_flags & MV_PP_FLAG_EDMA_EN) {
133763af2a5c5990d95f1e7d8795f1425fb976ea2b4bMark Lord			/* EDMA: check for response queue interrupt */
133863af2a5c5990d95f1e7d8795f1425fb976ea2b4bMark Lord			if ((CRPB_DMA_DONE << hard_port) & hc_irq_cause) {
133963af2a5c5990d95f1e7d8795f1425fb976ea2b4bMark Lord				ata_status = mv_get_crpb_status(ap);
134063af2a5c5990d95f1e7d8795f1425fb976ea2b4bMark Lord				handled = 1;
134163af2a5c5990d95f1e7d8795f1425fb976ea2b4bMark Lord			}
134263af2a5c5990d95f1e7d8795f1425fb976ea2b4bMark Lord		} else {
134363af2a5c5990d95f1e7d8795f1425fb976ea2b4bMark Lord			/* PIO: check for device (drive) interrupt */
134463af2a5c5990d95f1e7d8795f1425fb976ea2b4bMark Lord			if ((DEV_IRQ << hard_port) & hc_irq_cause) {
13450d5ff566779f894ca9937231a181eb31e4adff0eTejun Heo				ata_status = readb(ap->ioaddr.status_addr);
134663af2a5c5990d95f1e7d8795f1425fb976ea2b4bMark Lord				handled = 1;
1347e857f141945f29c16f72ffcfdbce097f8be6c4e9Mark Lord				/* ignore spurious intr if drive still BUSY */
1348e857f141945f29c16f72ffcfdbce097f8be6c4e9Mark Lord				if (ata_status & ATA_BUSY) {
1349e857f141945f29c16f72ffcfdbce097f8be6c4e9Mark Lord					ata_status = 0;
1350e857f141945f29c16f72ffcfdbce097f8be6c4e9Mark Lord					handled = 0;
1351e857f141945f29c16f72ffcfdbce097f8be6c4e9Mark Lord				}
135263af2a5c5990d95f1e7d8795f1425fb976ea2b4bMark Lord			}
135320f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ		}
135420f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ
1355029f5468b5b5f93a09bf90326fdcb9124079658dJeff Garzik		if (ap && (ap->flags & ATA_FLAG_DISABLED))
1356a2c91a8819e315e9fd1aef3ff57badb6c1be3f80Jeff Garzik			continue;
1357a2c91a8819e315e9fd1aef3ff57badb6c1be3f80Jeff Garzik
1358a7dac447bb9cef27d4d29cdf63e2d7809c50b1f4Jeff Garzik		err_mask = ac_err_mask(ata_status);
1359a7dac447bb9cef27d4d29cdf63e2d7809c50b1f4Jeff Garzik
136031961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ		shift = port << 1;		/* (port * 2) */
136120f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ		if (port >= MV_PORTS_PER_HC) {
136220f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ			shift++;	/* skip bit 8 in the HC Main IRQ reg */
136320f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ		}
136420f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ		if ((PORT0_ERR << shift) & relevant) {
13659b358e305c1d783c8a4ebf00344e95deb9e38f3dMark Lord			mv_err_intr(ap, 1);
1366a7dac447bb9cef27d4d29cdf63e2d7809c50b1f4Jeff Garzik			err_mask |= AC_ERR_OTHER;
136763af2a5c5990d95f1e7d8795f1425fb976ea2b4bMark Lord			handled = 1;
136820f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ		}
13698b260248d9e0e8b64bb72fd4dee03ad86984c344Jeff Garzik
137063af2a5c5990d95f1e7d8795f1425fb976ea2b4bMark Lord		if (handled) {
137120f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ			qc = ata_qc_from_tag(ap, ap->active_tag);
137263af2a5c5990d95f1e7d8795f1425fb976ea2b4bMark Lord			if (qc && (qc->flags & ATA_QCFLAG_ACTIVE)) {
137320f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ				VPRINTK("port %u IRQ found for qc, "
137420f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ					"ata_status 0x%x\n", port,ata_status);
137520f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ				/* mark qc status appropriately */
1376701db69d6647f61e4660c9102d7f2fd5dffc203dJeff Garzik				if (!(qc->tf.flags & ATA_TFLAG_POLLING)) {
1377a22e2eb0710798009b8e696ae911aef745089dd6Albert Lee					qc->err_mask |= err_mask;
1378a22e2eb0710798009b8e696ae911aef745089dd6Albert Lee					ata_qc_complete(qc);
1379a22e2eb0710798009b8e696ae911aef745089dd6Albert Lee				}
138020f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ			}
138120f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ		}
138220f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ	}
138320f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ	VPRINTK("EXIT\n");
138420f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ}
138520f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ
138605b308e1df6d9d673daedb517969241f41278b52Brett Russ/**
13878b260248d9e0e8b64bb72fd4dee03ad86984c344Jeff Garzik *      mv_interrupt -
138805b308e1df6d9d673daedb517969241f41278b52Brett Russ *      @irq: unused
138905b308e1df6d9d673daedb517969241f41278b52Brett Russ *      @dev_instance: private data; in this case the host structure
139005b308e1df6d9d673daedb517969241f41278b52Brett Russ *      @regs: unused
139105b308e1df6d9d673daedb517969241f41278b52Brett Russ *
139205b308e1df6d9d673daedb517969241f41278b52Brett Russ *      Read the read only register to determine if any host
139305b308e1df6d9d673daedb517969241f41278b52Brett Russ *      controllers have pending interrupts.  If so, call lower level
139405b308e1df6d9d673daedb517969241f41278b52Brett Russ *      routine to handle.  Also check for PCI errors which are only
139505b308e1df6d9d673daedb517969241f41278b52Brett Russ *      reported here.
139605b308e1df6d9d673daedb517969241f41278b52Brett Russ *
13978b260248d9e0e8b64bb72fd4dee03ad86984c344Jeff Garzik *      LOCKING:
1398cca3974e48607c3775dc73b544a5700b2e37c21aJeff Garzik *      This routine holds the host lock while processing pending
139905b308e1df6d9d673daedb517969241f41278b52Brett Russ *      interrupts.
140005b308e1df6d9d673daedb517969241f41278b52Brett Russ */
14017d12e780e003f93433d49ce78cfedf4b4c52adc5David Howellsstatic irqreturn_t mv_interrupt(int irq, void *dev_instance)
140220f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ{
1403cca3974e48607c3775dc73b544a5700b2e37c21aJeff Garzik	struct ata_host *host = dev_instance;
140420f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ	unsigned int hc, handled = 0, n_hcs;
14050d5ff566779f894ca9937231a181eb31e4adff0eTejun Heo	void __iomem *mmio = host->iomap[MV_PRIMARY_BAR];
1406615ab95342f6245026d8974b9724f7ea57d9a184Mark Lord	struct mv_host_priv *hpriv;
140720f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ	u32 irq_stat;
140820f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ
140920f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ	irq_stat = readl(mmio + HC_MAIN_IRQ_CAUSE_OFS);
141020f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ
141120f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ	/* check the cases where we either have nothing pending or have read
141220f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ	 * a bogus register value which can indicate HW removal or PCI fault
141320f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ	 */
141420f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ	if (!irq_stat || (0xffffffffU == irq_stat)) {
141520f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ		return IRQ_NONE;
141620f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ	}
141720f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ
1418cca3974e48607c3775dc73b544a5700b2e37c21aJeff Garzik	n_hcs = mv_get_hc_count(host->ports[0]->flags);
1419cca3974e48607c3775dc73b544a5700b2e37c21aJeff Garzik	spin_lock(&host->lock);
142020f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ
142120f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ	for (hc = 0; hc < n_hcs; hc++) {
142220f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ		u32 relevant = irq_stat & (HC0_IRQ_PEND << (hc * HC_SHIFT));
142320f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ		if (relevant) {
1424cca3974e48607c3775dc73b544a5700b2e37c21aJeff Garzik			mv_host_intr(host, relevant, hc);
142531961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ			handled++;
142620f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ		}
142720f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ	}
1428615ab95342f6245026d8974b9724f7ea57d9a184Mark Lord
1429cca3974e48607c3775dc73b544a5700b2e37c21aJeff Garzik	hpriv = host->private_data;
1430615ab95342f6245026d8974b9724f7ea57d9a184Mark Lord	if (IS_60XX(hpriv)) {
1431615ab95342f6245026d8974b9724f7ea57d9a184Mark Lord		/* deal with the interrupt coalescing bits */
1432615ab95342f6245026d8974b9724f7ea57d9a184Mark Lord		if (irq_stat & (TRAN_LO_DONE | TRAN_HI_DONE | PORTS_0_7_COAL_DONE)) {
1433615ab95342f6245026d8974b9724f7ea57d9a184Mark Lord			writelfl(0, mmio + MV_IRQ_COAL_CAUSE_LO);
1434615ab95342f6245026d8974b9724f7ea57d9a184Mark Lord			writelfl(0, mmio + MV_IRQ_COAL_CAUSE_HI);
1435615ab95342f6245026d8974b9724f7ea57d9a184Mark Lord			writelfl(0, mmio + MV_IRQ_COAL_CAUSE);
1436615ab95342f6245026d8974b9724f7ea57d9a184Mark Lord		}
1437615ab95342f6245026d8974b9724f7ea57d9a184Mark Lord	}
1438615ab95342f6245026d8974b9724f7ea57d9a184Mark Lord
143920f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ	if (PCI_ERR & irq_stat) {
144031961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ		printk(KERN_ERR DRV_NAME ": PCI ERROR; PCI IRQ cause=0x%08x\n",
144131961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ		       readl(mmio + PCI_IRQ_CAUSE_OFS));
144231961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ
1443afb0edd922c7ed6e73678730921dfcccebec17e8Brett Russ		DPRINTK("All regs @ PCI error\n");
1444cca3974e48607c3775dc73b544a5700b2e37c21aJeff Garzik		mv_dump_all_regs(mmio, -1, to_pci_dev(host->dev));
144520f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ
144631961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ		writelfl(0, mmio + PCI_IRQ_CAUSE_OFS);
144731961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ		handled++;
144831961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ	}
1449cca3974e48607c3775dc73b544a5700b2e37c21aJeff Garzik	spin_unlock(&host->lock);
145020f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ
145120f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ	return IRQ_RETVAL(handled);
145220f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ}
145320f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ
1454c9d39130123238ac18478a42e25cb7996eacfcc0Jeff Garzikstatic void __iomem *mv5_phy_base(void __iomem *mmio, unsigned int port)
1455c9d39130123238ac18478a42e25cb7996eacfcc0Jeff Garzik{
1456c9d39130123238ac18478a42e25cb7996eacfcc0Jeff Garzik	void __iomem *hc_mmio = mv_hc_base_from_port(mmio, port);
1457c9d39130123238ac18478a42e25cb7996eacfcc0Jeff Garzik	unsigned long ofs = (mv_hardport_from_port(port) + 1) * 0x100UL;
1458c9d39130123238ac18478a42e25cb7996eacfcc0Jeff Garzik
1459c9d39130123238ac18478a42e25cb7996eacfcc0Jeff Garzik	return hc_mmio + ofs;
1460c9d39130123238ac18478a42e25cb7996eacfcc0Jeff Garzik}
1461c9d39130123238ac18478a42e25cb7996eacfcc0Jeff Garzik
1462c9d39130123238ac18478a42e25cb7996eacfcc0Jeff Garzikstatic unsigned int mv5_scr_offset(unsigned int sc_reg_in)
1463c9d39130123238ac18478a42e25cb7996eacfcc0Jeff Garzik{
1464c9d39130123238ac18478a42e25cb7996eacfcc0Jeff Garzik	unsigned int ofs;
1465c9d39130123238ac18478a42e25cb7996eacfcc0Jeff Garzik
1466c9d39130123238ac18478a42e25cb7996eacfcc0Jeff Garzik	switch (sc_reg_in) {
1467c9d39130123238ac18478a42e25cb7996eacfcc0Jeff Garzik	case SCR_STATUS:
1468c9d39130123238ac18478a42e25cb7996eacfcc0Jeff Garzik	case SCR_ERROR:
1469c9d39130123238ac18478a42e25cb7996eacfcc0Jeff Garzik	case SCR_CONTROL:
1470c9d39130123238ac18478a42e25cb7996eacfcc0Jeff Garzik		ofs = sc_reg_in * sizeof(u32);
1471c9d39130123238ac18478a42e25cb7996eacfcc0Jeff Garzik		break;
1472c9d39130123238ac18478a42e25cb7996eacfcc0Jeff Garzik	default:
1473c9d39130123238ac18478a42e25cb7996eacfcc0Jeff Garzik		ofs = 0xffffffffU;
1474c9d39130123238ac18478a42e25cb7996eacfcc0Jeff Garzik		break;
1475c9d39130123238ac18478a42e25cb7996eacfcc0Jeff Garzik	}
1476c9d39130123238ac18478a42e25cb7996eacfcc0Jeff Garzik	return ofs;
1477c9d39130123238ac18478a42e25cb7996eacfcc0Jeff Garzik}
1478c9d39130123238ac18478a42e25cb7996eacfcc0Jeff Garzik
1479c9d39130123238ac18478a42e25cb7996eacfcc0Jeff Garzikstatic u32 mv5_scr_read(struct ata_port *ap, unsigned int sc_reg_in)
1480c9d39130123238ac18478a42e25cb7996eacfcc0Jeff Garzik{
14810d5ff566779f894ca9937231a181eb31e4adff0eTejun Heo	void __iomem *mmio = ap->host->iomap[MV_PRIMARY_BAR];
14820d5ff566779f894ca9937231a181eb31e4adff0eTejun Heo	void __iomem *addr = mv5_phy_base(mmio, ap->port_no);
1483c9d39130123238ac18478a42e25cb7996eacfcc0Jeff Garzik	unsigned int ofs = mv5_scr_offset(sc_reg_in);
1484c9d39130123238ac18478a42e25cb7996eacfcc0Jeff Garzik
1485c9d39130123238ac18478a42e25cb7996eacfcc0Jeff Garzik	if (ofs != 0xffffffffU)
14860d5ff566779f894ca9937231a181eb31e4adff0eTejun Heo		return readl(addr + ofs);
1487c9d39130123238ac18478a42e25cb7996eacfcc0Jeff Garzik	else
1488c9d39130123238ac18478a42e25cb7996eacfcc0Jeff Garzik		return (u32) ofs;
1489c9d39130123238ac18478a42e25cb7996eacfcc0Jeff Garzik}
1490c9d39130123238ac18478a42e25cb7996eacfcc0Jeff Garzik
1491c9d39130123238ac18478a42e25cb7996eacfcc0Jeff Garzikstatic void mv5_scr_write(struct ata_port *ap, unsigned int sc_reg_in, u32 val)
1492c9d39130123238ac18478a42e25cb7996eacfcc0Jeff Garzik{
14930d5ff566779f894ca9937231a181eb31e4adff0eTejun Heo	void __iomem *mmio = ap->host->iomap[MV_PRIMARY_BAR];
14940d5ff566779f894ca9937231a181eb31e4adff0eTejun Heo	void __iomem *addr = mv5_phy_base(mmio, ap->port_no);
1495c9d39130123238ac18478a42e25cb7996eacfcc0Jeff Garzik	unsigned int ofs = mv5_scr_offset(sc_reg_in);
1496c9d39130123238ac18478a42e25cb7996eacfcc0Jeff Garzik
1497c9d39130123238ac18478a42e25cb7996eacfcc0Jeff Garzik	if (ofs != 0xffffffffU)
14980d5ff566779f894ca9937231a181eb31e4adff0eTejun Heo		writelfl(val, addr + ofs);
1499c9d39130123238ac18478a42e25cb7996eacfcc0Jeff Garzik}
1500c9d39130123238ac18478a42e25cb7996eacfcc0Jeff Garzik
1501522479fb98c6667f081e75f87e298e413c0b1db8Jeff Garzikstatic void mv5_reset_bus(struct pci_dev *pdev, void __iomem *mmio)
1502522479fb98c6667f081e75f87e298e413c0b1db8Jeff Garzik{
1503522479fb98c6667f081e75f87e298e413c0b1db8Jeff Garzik	u8 rev_id;
1504522479fb98c6667f081e75f87e298e413c0b1db8Jeff Garzik	int early_5080;
1505522479fb98c6667f081e75f87e298e413c0b1db8Jeff Garzik
1506522479fb98c6667f081e75f87e298e413c0b1db8Jeff Garzik	pci_read_config_byte(pdev, PCI_REVISION_ID, &rev_id);
1507522479fb98c6667f081e75f87e298e413c0b1db8Jeff Garzik
1508522479fb98c6667f081e75f87e298e413c0b1db8Jeff Garzik	early_5080 = (pdev->device == 0x5080) && (rev_id == 0);
1509522479fb98c6667f081e75f87e298e413c0b1db8Jeff Garzik
1510522479fb98c6667f081e75f87e298e413c0b1db8Jeff Garzik	if (!early_5080) {
1511522479fb98c6667f081e75f87e298e413c0b1db8Jeff Garzik		u32 tmp = readl(mmio + MV_PCI_EXP_ROM_BAR_CTL);
1512522479fb98c6667f081e75f87e298e413c0b1db8Jeff Garzik		tmp |= (1 << 0);
1513522479fb98c6667f081e75f87e298e413c0b1db8Jeff Garzik		writel(tmp, mmio + MV_PCI_EXP_ROM_BAR_CTL);
1514522479fb98c6667f081e75f87e298e413c0b1db8Jeff Garzik	}
1515522479fb98c6667f081e75f87e298e413c0b1db8Jeff Garzik
1516522479fb98c6667f081e75f87e298e413c0b1db8Jeff Garzik	mv_reset_pci_bus(pdev, mmio);
1517522479fb98c6667f081e75f87e298e413c0b1db8Jeff Garzik}
1518522479fb98c6667f081e75f87e298e413c0b1db8Jeff Garzik
1519522479fb98c6667f081e75f87e298e413c0b1db8Jeff Garzikstatic void mv5_reset_flash(struct mv_host_priv *hpriv, void __iomem *mmio)
1520522479fb98c6667f081e75f87e298e413c0b1db8Jeff Garzik{
1521522479fb98c6667f081e75f87e298e413c0b1db8Jeff Garzik	writel(0x0fcfffff, mmio + MV_FLASH_CTL);
1522522479fb98c6667f081e75f87e298e413c0b1db8Jeff Garzik}
1523522479fb98c6667f081e75f87e298e413c0b1db8Jeff Garzik
152447c2b677daeed9c79ecb7167c211ff36876ea611Jeff Garzikstatic void mv5_read_preamp(struct mv_host_priv *hpriv, int idx,
1525ba3fe8fb6a469390a14379519915f3c39a973d99Jeff Garzik			   void __iomem *mmio)
1526ba3fe8fb6a469390a14379519915f3c39a973d99Jeff Garzik{
1527c9d39130123238ac18478a42e25cb7996eacfcc0Jeff Garzik	void __iomem *phy_mmio = mv5_phy_base(mmio, idx);
1528c9d39130123238ac18478a42e25cb7996eacfcc0Jeff Garzik	u32 tmp;
1529c9d39130123238ac18478a42e25cb7996eacfcc0Jeff Garzik
1530c9d39130123238ac18478a42e25cb7996eacfcc0Jeff Garzik	tmp = readl(phy_mmio + MV5_PHY_MODE);
1531c9d39130123238ac18478a42e25cb7996eacfcc0Jeff Garzik
1532c9d39130123238ac18478a42e25cb7996eacfcc0Jeff Garzik	hpriv->signal[idx].pre = tmp & 0x1800;	/* bits 12:11 */
1533c9d39130123238ac18478a42e25cb7996eacfcc0Jeff Garzik	hpriv->signal[idx].amps = tmp & 0xe0;	/* bits 7:5 */
1534ba3fe8fb6a469390a14379519915f3c39a973d99Jeff Garzik}
1535ba3fe8fb6a469390a14379519915f3c39a973d99Jeff Garzik
153647c2b677daeed9c79ecb7167c211ff36876ea611Jeff Garzikstatic void mv5_enable_leds(struct mv_host_priv *hpriv, void __iomem *mmio)
1537ba3fe8fb6a469390a14379519915f3c39a973d99Jeff Garzik{
1538522479fb98c6667f081e75f87e298e413c0b1db8Jeff Garzik	u32 tmp;
1539522479fb98c6667f081e75f87e298e413c0b1db8Jeff Garzik
1540522479fb98c6667f081e75f87e298e413c0b1db8Jeff Garzik	writel(0, mmio + MV_GPIO_PORT_CTL);
1541522479fb98c6667f081e75f87e298e413c0b1db8Jeff Garzik
1542522479fb98c6667f081e75f87e298e413c0b1db8Jeff Garzik	/* FIXME: handle MV_HP_ERRATA_50XXB2 errata */
1543522479fb98c6667f081e75f87e298e413c0b1db8Jeff Garzik
1544522479fb98c6667f081e75f87e298e413c0b1db8Jeff Garzik	tmp = readl(mmio + MV_PCI_EXP_ROM_BAR_CTL);
1545522479fb98c6667f081e75f87e298e413c0b1db8Jeff Garzik	tmp |= ~(1 << 0);
1546522479fb98c6667f081e75f87e298e413c0b1db8Jeff Garzik	writel(tmp, mmio + MV_PCI_EXP_ROM_BAR_CTL);
1547ba3fe8fb6a469390a14379519915f3c39a973d99Jeff Garzik}
1548ba3fe8fb6a469390a14379519915f3c39a973d99Jeff Garzik
15492a47ce06d534692f9bd2bf4e90a20fc9b1054c39Jeff Garzikstatic void mv5_phy_errata(struct mv_host_priv *hpriv, void __iomem *mmio,
15502a47ce06d534692f9bd2bf4e90a20fc9b1054c39Jeff Garzik			   unsigned int port)
1551bca1c4eb9411533d613123618c0d127fae532595Jeff Garzik{
1552c9d39130123238ac18478a42e25cb7996eacfcc0Jeff Garzik	void __iomem *phy_mmio = mv5_phy_base(mmio, port);
1553c9d39130123238ac18478a42e25cb7996eacfcc0Jeff Garzik	const u32 mask = (1<<12) | (1<<11) | (1<<7) | (1<<6) | (1<<5);
1554c9d39130123238ac18478a42e25cb7996eacfcc0Jeff Garzik	u32 tmp;
1555c9d39130123238ac18478a42e25cb7996eacfcc0Jeff Garzik	int fix_apm_sq = (hpriv->hp_flags & MV_HP_ERRATA_50XXB0);
1556c9d39130123238ac18478a42e25cb7996eacfcc0Jeff Garzik
1557c9d39130123238ac18478a42e25cb7996eacfcc0Jeff Garzik	if (fix_apm_sq) {
1558c9d39130123238ac18478a42e25cb7996eacfcc0Jeff Garzik		tmp = readl(phy_mmio + MV5_LT_MODE);
1559c9d39130123238ac18478a42e25cb7996eacfcc0Jeff Garzik		tmp |= (1 << 19);
1560c9d39130123238ac18478a42e25cb7996eacfcc0Jeff Garzik		writel(tmp, phy_mmio + MV5_LT_MODE);
1561c9d39130123238ac18478a42e25cb7996eacfcc0Jeff Garzik
1562c9d39130123238ac18478a42e25cb7996eacfcc0Jeff Garzik		tmp = readl(phy_mmio + MV5_PHY_CTL);
1563c9d39130123238ac18478a42e25cb7996eacfcc0Jeff Garzik		tmp &= ~0x3;
1564c9d39130123238ac18478a42e25cb7996eacfcc0Jeff Garzik		tmp |= 0x1;
1565c9d39130123238ac18478a42e25cb7996eacfcc0Jeff Garzik		writel(tmp, phy_mmio + MV5_PHY_CTL);
1566c9d39130123238ac18478a42e25cb7996eacfcc0Jeff Garzik	}
1567c9d39130123238ac18478a42e25cb7996eacfcc0Jeff Garzik
1568c9d39130123238ac18478a42e25cb7996eacfcc0Jeff Garzik	tmp = readl(phy_mmio + MV5_PHY_MODE);
1569c9d39130123238ac18478a42e25cb7996eacfcc0Jeff Garzik	tmp &= ~mask;
1570c9d39130123238ac18478a42e25cb7996eacfcc0Jeff Garzik	tmp |= hpriv->signal[port].pre;
1571c9d39130123238ac18478a42e25cb7996eacfcc0Jeff Garzik	tmp |= hpriv->signal[port].amps;
1572c9d39130123238ac18478a42e25cb7996eacfcc0Jeff Garzik	writel(tmp, phy_mmio + MV5_PHY_MODE);
1573bca1c4eb9411533d613123618c0d127fae532595Jeff Garzik}
1574bca1c4eb9411533d613123618c0d127fae532595Jeff Garzik
1575c9d39130123238ac18478a42e25cb7996eacfcc0Jeff Garzik
1576c9d39130123238ac18478a42e25cb7996eacfcc0Jeff Garzik#undef ZERO
1577c9d39130123238ac18478a42e25cb7996eacfcc0Jeff Garzik#define ZERO(reg) writel(0, port_mmio + (reg))
1578c9d39130123238ac18478a42e25cb7996eacfcc0Jeff Garzikstatic void mv5_reset_hc_port(struct mv_host_priv *hpriv, void __iomem *mmio,
1579c9d39130123238ac18478a42e25cb7996eacfcc0Jeff Garzik			     unsigned int port)
1580c9d39130123238ac18478a42e25cb7996eacfcc0Jeff Garzik{
1581c9d39130123238ac18478a42e25cb7996eacfcc0Jeff Garzik	void __iomem *port_mmio = mv_port_base(mmio, port);
1582c9d39130123238ac18478a42e25cb7996eacfcc0Jeff Garzik
1583c9d39130123238ac18478a42e25cb7996eacfcc0Jeff Garzik	writelfl(EDMA_DS, port_mmio + EDMA_CMD_OFS);
1584c9d39130123238ac18478a42e25cb7996eacfcc0Jeff Garzik
1585c9d39130123238ac18478a42e25cb7996eacfcc0Jeff Garzik	mv_channel_reset(hpriv, mmio, port);
1586c9d39130123238ac18478a42e25cb7996eacfcc0Jeff Garzik
1587c9d39130123238ac18478a42e25cb7996eacfcc0Jeff Garzik	ZERO(0x028);	/* command */
1588c9d39130123238ac18478a42e25cb7996eacfcc0Jeff Garzik	writel(0x11f, port_mmio + EDMA_CFG_OFS);
1589c9d39130123238ac18478a42e25cb7996eacfcc0Jeff Garzik	ZERO(0x004);	/* timer */
1590c9d39130123238ac18478a42e25cb7996eacfcc0Jeff Garzik	ZERO(0x008);	/* irq err cause */
1591c9d39130123238ac18478a42e25cb7996eacfcc0Jeff Garzik	ZERO(0x00c);	/* irq err mask */
1592c9d39130123238ac18478a42e25cb7996eacfcc0Jeff Garzik	ZERO(0x010);	/* rq bah */
1593c9d39130123238ac18478a42e25cb7996eacfcc0Jeff Garzik	ZERO(0x014);	/* rq inp */
1594c9d39130123238ac18478a42e25cb7996eacfcc0Jeff Garzik	ZERO(0x018);	/* rq outp */
1595c9d39130123238ac18478a42e25cb7996eacfcc0Jeff Garzik	ZERO(0x01c);	/* respq bah */
1596c9d39130123238ac18478a42e25cb7996eacfcc0Jeff Garzik	ZERO(0x024);	/* respq outp */
1597c9d39130123238ac18478a42e25cb7996eacfcc0Jeff Garzik	ZERO(0x020);	/* respq inp */
1598c9d39130123238ac18478a42e25cb7996eacfcc0Jeff Garzik	ZERO(0x02c);	/* test control */
1599c9d39130123238ac18478a42e25cb7996eacfcc0Jeff Garzik	writel(0xbc, port_mmio + EDMA_IORDY_TMOUT);
1600c9d39130123238ac18478a42e25cb7996eacfcc0Jeff Garzik}
1601c9d39130123238ac18478a42e25cb7996eacfcc0Jeff Garzik#undef ZERO
1602c9d39130123238ac18478a42e25cb7996eacfcc0Jeff Garzik
1603c9d39130123238ac18478a42e25cb7996eacfcc0Jeff Garzik#define ZERO(reg) writel(0, hc_mmio + (reg))
1604c9d39130123238ac18478a42e25cb7996eacfcc0Jeff Garzikstatic void mv5_reset_one_hc(struct mv_host_priv *hpriv, void __iomem *mmio,
1605c9d39130123238ac18478a42e25cb7996eacfcc0Jeff Garzik			unsigned int hc)
160647c2b677daeed9c79ecb7167c211ff36876ea611Jeff Garzik{
1607c9d39130123238ac18478a42e25cb7996eacfcc0Jeff Garzik	void __iomem *hc_mmio = mv_hc_base(mmio, hc);
1608c9d39130123238ac18478a42e25cb7996eacfcc0Jeff Garzik	u32 tmp;
1609c9d39130123238ac18478a42e25cb7996eacfcc0Jeff Garzik
1610c9d39130123238ac18478a42e25cb7996eacfcc0Jeff Garzik	ZERO(0x00c);
1611c9d39130123238ac18478a42e25cb7996eacfcc0Jeff Garzik	ZERO(0x010);
1612c9d39130123238ac18478a42e25cb7996eacfcc0Jeff Garzik	ZERO(0x014);
1613c9d39130123238ac18478a42e25cb7996eacfcc0Jeff Garzik	ZERO(0x018);
1614c9d39130123238ac18478a42e25cb7996eacfcc0Jeff Garzik
1615c9d39130123238ac18478a42e25cb7996eacfcc0Jeff Garzik	tmp = readl(hc_mmio + 0x20);
1616c9d39130123238ac18478a42e25cb7996eacfcc0Jeff Garzik	tmp &= 0x1c1c1c1c;
1617c9d39130123238ac18478a42e25cb7996eacfcc0Jeff Garzik	tmp |= 0x03030303;
1618c9d39130123238ac18478a42e25cb7996eacfcc0Jeff Garzik	writel(tmp, hc_mmio + 0x20);
1619c9d39130123238ac18478a42e25cb7996eacfcc0Jeff Garzik}
1620c9d39130123238ac18478a42e25cb7996eacfcc0Jeff Garzik#undef ZERO
1621c9d39130123238ac18478a42e25cb7996eacfcc0Jeff Garzik
1622c9d39130123238ac18478a42e25cb7996eacfcc0Jeff Garzikstatic int mv5_reset_hc(struct mv_host_priv *hpriv, void __iomem *mmio,
1623c9d39130123238ac18478a42e25cb7996eacfcc0Jeff Garzik			unsigned int n_hc)
1624c9d39130123238ac18478a42e25cb7996eacfcc0Jeff Garzik{
1625c9d39130123238ac18478a42e25cb7996eacfcc0Jeff Garzik	unsigned int hc, port;
1626c9d39130123238ac18478a42e25cb7996eacfcc0Jeff Garzik
1627c9d39130123238ac18478a42e25cb7996eacfcc0Jeff Garzik	for (hc = 0; hc < n_hc; hc++) {
1628c9d39130123238ac18478a42e25cb7996eacfcc0Jeff Garzik		for (port = 0; port < MV_PORTS_PER_HC; port++)
1629c9d39130123238ac18478a42e25cb7996eacfcc0Jeff Garzik			mv5_reset_hc_port(hpriv, mmio,
1630c9d39130123238ac18478a42e25cb7996eacfcc0Jeff Garzik					  (hc * MV_PORTS_PER_HC) + port);
1631c9d39130123238ac18478a42e25cb7996eacfcc0Jeff Garzik
1632c9d39130123238ac18478a42e25cb7996eacfcc0Jeff Garzik		mv5_reset_one_hc(hpriv, mmio, hc);
1633c9d39130123238ac18478a42e25cb7996eacfcc0Jeff Garzik	}
1634c9d39130123238ac18478a42e25cb7996eacfcc0Jeff Garzik
1635c9d39130123238ac18478a42e25cb7996eacfcc0Jeff Garzik	return 0;
163647c2b677daeed9c79ecb7167c211ff36876ea611Jeff Garzik}
163747c2b677daeed9c79ecb7167c211ff36876ea611Jeff Garzik
1638101ffae26c23ea928fce6d31a8b4901327d91a15Jeff Garzik#undef ZERO
1639101ffae26c23ea928fce6d31a8b4901327d91a15Jeff Garzik#define ZERO(reg) writel(0, mmio + (reg))
1640101ffae26c23ea928fce6d31a8b4901327d91a15Jeff Garzikstatic void mv_reset_pci_bus(struct pci_dev *pdev, void __iomem *mmio)
1641101ffae26c23ea928fce6d31a8b4901327d91a15Jeff Garzik{
1642101ffae26c23ea928fce6d31a8b4901327d91a15Jeff Garzik	u32 tmp;
1643101ffae26c23ea928fce6d31a8b4901327d91a15Jeff Garzik
1644101ffae26c23ea928fce6d31a8b4901327d91a15Jeff Garzik	tmp = readl(mmio + MV_PCI_MODE);
1645101ffae26c23ea928fce6d31a8b4901327d91a15Jeff Garzik	tmp &= 0xff00ffff;
1646101ffae26c23ea928fce6d31a8b4901327d91a15Jeff Garzik	writel(tmp, mmio + MV_PCI_MODE);
1647101ffae26c23ea928fce6d31a8b4901327d91a15Jeff Garzik
1648101ffae26c23ea928fce6d31a8b4901327d91a15Jeff Garzik	ZERO(MV_PCI_DISC_TIMER);
1649101ffae26c23ea928fce6d31a8b4901327d91a15Jeff Garzik	ZERO(MV_PCI_MSI_TRIGGER);
1650101ffae26c23ea928fce6d31a8b4901327d91a15Jeff Garzik	writel(0x000100ff, mmio + MV_PCI_XBAR_TMOUT);
1651101ffae26c23ea928fce6d31a8b4901327d91a15Jeff Garzik	ZERO(HC_MAIN_IRQ_MASK_OFS);
1652101ffae26c23ea928fce6d31a8b4901327d91a15Jeff Garzik	ZERO(MV_PCI_SERR_MASK);
1653101ffae26c23ea928fce6d31a8b4901327d91a15Jeff Garzik	ZERO(PCI_IRQ_CAUSE_OFS);
1654101ffae26c23ea928fce6d31a8b4901327d91a15Jeff Garzik	ZERO(PCI_IRQ_MASK_OFS);
1655101ffae26c23ea928fce6d31a8b4901327d91a15Jeff Garzik	ZERO(MV_PCI_ERR_LOW_ADDRESS);
1656101ffae26c23ea928fce6d31a8b4901327d91a15Jeff Garzik	ZERO(MV_PCI_ERR_HIGH_ADDRESS);
1657101ffae26c23ea928fce6d31a8b4901327d91a15Jeff Garzik	ZERO(MV_PCI_ERR_ATTRIBUTE);
1658101ffae26c23ea928fce6d31a8b4901327d91a15Jeff Garzik	ZERO(MV_PCI_ERR_COMMAND);
1659101ffae26c23ea928fce6d31a8b4901327d91a15Jeff Garzik}
1660101ffae26c23ea928fce6d31a8b4901327d91a15Jeff Garzik#undef ZERO
1661101ffae26c23ea928fce6d31a8b4901327d91a15Jeff Garzik
1662101ffae26c23ea928fce6d31a8b4901327d91a15Jeff Garzikstatic void mv6_reset_flash(struct mv_host_priv *hpriv, void __iomem *mmio)
1663101ffae26c23ea928fce6d31a8b4901327d91a15Jeff Garzik{
1664101ffae26c23ea928fce6d31a8b4901327d91a15Jeff Garzik	u32 tmp;
1665101ffae26c23ea928fce6d31a8b4901327d91a15Jeff Garzik
1666101ffae26c23ea928fce6d31a8b4901327d91a15Jeff Garzik	mv5_reset_flash(hpriv, mmio);
1667101ffae26c23ea928fce6d31a8b4901327d91a15Jeff Garzik
1668101ffae26c23ea928fce6d31a8b4901327d91a15Jeff Garzik	tmp = readl(mmio + MV_GPIO_PORT_CTL);
1669101ffae26c23ea928fce6d31a8b4901327d91a15Jeff Garzik	tmp &= 0x3;
1670101ffae26c23ea928fce6d31a8b4901327d91a15Jeff Garzik	tmp |= (1 << 5) | (1 << 6);
1671101ffae26c23ea928fce6d31a8b4901327d91a15Jeff Garzik	writel(tmp, mmio + MV_GPIO_PORT_CTL);
1672101ffae26c23ea928fce6d31a8b4901327d91a15Jeff Garzik}
1673101ffae26c23ea928fce6d31a8b4901327d91a15Jeff Garzik
1674101ffae26c23ea928fce6d31a8b4901327d91a15Jeff Garzik/**
1675101ffae26c23ea928fce6d31a8b4901327d91a15Jeff Garzik *      mv6_reset_hc - Perform the 6xxx global soft reset
1676101ffae26c23ea928fce6d31a8b4901327d91a15Jeff Garzik *      @mmio: base address of the HBA
1677101ffae26c23ea928fce6d31a8b4901327d91a15Jeff Garzik *
1678101ffae26c23ea928fce6d31a8b4901327d91a15Jeff Garzik *      This routine only applies to 6xxx parts.
1679101ffae26c23ea928fce6d31a8b4901327d91a15Jeff Garzik *
1680101ffae26c23ea928fce6d31a8b4901327d91a15Jeff Garzik *      LOCKING:
1681101ffae26c23ea928fce6d31a8b4901327d91a15Jeff Garzik *      Inherited from caller.
1682101ffae26c23ea928fce6d31a8b4901327d91a15Jeff Garzik */
1683c9d39130123238ac18478a42e25cb7996eacfcc0Jeff Garzikstatic int mv6_reset_hc(struct mv_host_priv *hpriv, void __iomem *mmio,
1684c9d39130123238ac18478a42e25cb7996eacfcc0Jeff Garzik			unsigned int n_hc)
1685101ffae26c23ea928fce6d31a8b4901327d91a15Jeff Garzik{
1686101ffae26c23ea928fce6d31a8b4901327d91a15Jeff Garzik	void __iomem *reg = mmio + PCI_MAIN_CMD_STS_OFS;
1687101ffae26c23ea928fce6d31a8b4901327d91a15Jeff Garzik	int i, rc = 0;
1688101ffae26c23ea928fce6d31a8b4901327d91a15Jeff Garzik	u32 t;
1689101ffae26c23ea928fce6d31a8b4901327d91a15Jeff Garzik
1690101ffae26c23ea928fce6d31a8b4901327d91a15Jeff Garzik	/* Following procedure defined in PCI "main command and status
1691101ffae26c23ea928fce6d31a8b4901327d91a15Jeff Garzik	 * register" table.
1692101ffae26c23ea928fce6d31a8b4901327d91a15Jeff Garzik	 */
1693101ffae26c23ea928fce6d31a8b4901327d91a15Jeff Garzik	t = readl(reg);
1694101ffae26c23ea928fce6d31a8b4901327d91a15Jeff Garzik	writel(t | STOP_PCI_MASTER, reg);
1695101ffae26c23ea928fce6d31a8b4901327d91a15Jeff Garzik
1696101ffae26c23ea928fce6d31a8b4901327d91a15Jeff Garzik	for (i = 0; i < 1000; i++) {
1697101ffae26c23ea928fce6d31a8b4901327d91a15Jeff Garzik		udelay(1);
1698101ffae26c23ea928fce6d31a8b4901327d91a15Jeff Garzik		t = readl(reg);
1699101ffae26c23ea928fce6d31a8b4901327d91a15Jeff Garzik		if (PCI_MASTER_EMPTY & t) {
1700101ffae26c23ea928fce6d31a8b4901327d91a15Jeff Garzik			break;
1701101ffae26c23ea928fce6d31a8b4901327d91a15Jeff Garzik		}
1702101ffae26c23ea928fce6d31a8b4901327d91a15Jeff Garzik	}
1703101ffae26c23ea928fce6d31a8b4901327d91a15Jeff Garzik	if (!(PCI_MASTER_EMPTY & t)) {
1704101ffae26c23ea928fce6d31a8b4901327d91a15Jeff Garzik		printk(KERN_ERR DRV_NAME ": PCI master won't flush\n");
1705101ffae26c23ea928fce6d31a8b4901327d91a15Jeff Garzik		rc = 1;
1706101ffae26c23ea928fce6d31a8b4901327d91a15Jeff Garzik		goto done;
1707101ffae26c23ea928fce6d31a8b4901327d91a15Jeff Garzik	}
1708101ffae26c23ea928fce6d31a8b4901327d91a15Jeff Garzik
1709101ffae26c23ea928fce6d31a8b4901327d91a15Jeff Garzik	/* set reset */
1710101ffae26c23ea928fce6d31a8b4901327d91a15Jeff Garzik	i = 5;
1711101ffae26c23ea928fce6d31a8b4901327d91a15Jeff Garzik	do {
1712101ffae26c23ea928fce6d31a8b4901327d91a15Jeff Garzik		writel(t | GLOB_SFT_RST, reg);
1713101ffae26c23ea928fce6d31a8b4901327d91a15Jeff Garzik		t = readl(reg);
1714101ffae26c23ea928fce6d31a8b4901327d91a15Jeff Garzik		udelay(1);
1715101ffae26c23ea928fce6d31a8b4901327d91a15Jeff Garzik	} while (!(GLOB_SFT_RST & t) && (i-- > 0));
1716101ffae26c23ea928fce6d31a8b4901327d91a15Jeff Garzik
1717101ffae26c23ea928fce6d31a8b4901327d91a15Jeff Garzik	if (!(GLOB_SFT_RST & t)) {
1718101ffae26c23ea928fce6d31a8b4901327d91a15Jeff Garzik		printk(KERN_ERR DRV_NAME ": can't set global reset\n");
1719101ffae26c23ea928fce6d31a8b4901327d91a15Jeff Garzik		rc = 1;
1720101ffae26c23ea928fce6d31a8b4901327d91a15Jeff Garzik		goto done;
1721101ffae26c23ea928fce6d31a8b4901327d91a15Jeff Garzik	}
1722101ffae26c23ea928fce6d31a8b4901327d91a15Jeff Garzik
1723101ffae26c23ea928fce6d31a8b4901327d91a15Jeff Garzik	/* clear reset and *reenable the PCI master* (not mentioned in spec) */
1724101ffae26c23ea928fce6d31a8b4901327d91a15Jeff Garzik	i = 5;
1725101ffae26c23ea928fce6d31a8b4901327d91a15Jeff Garzik	do {
1726101ffae26c23ea928fce6d31a8b4901327d91a15Jeff Garzik		writel(t & ~(GLOB_SFT_RST | STOP_PCI_MASTER), reg);
1727101ffae26c23ea928fce6d31a8b4901327d91a15Jeff Garzik		t = readl(reg);
1728101ffae26c23ea928fce6d31a8b4901327d91a15Jeff Garzik		udelay(1);
1729101ffae26c23ea928fce6d31a8b4901327d91a15Jeff Garzik	} while ((GLOB_SFT_RST & t) && (i-- > 0));
1730101ffae26c23ea928fce6d31a8b4901327d91a15Jeff Garzik
1731101ffae26c23ea928fce6d31a8b4901327d91a15Jeff Garzik	if (GLOB_SFT_RST & t) {
1732101ffae26c23ea928fce6d31a8b4901327d91a15Jeff Garzik		printk(KERN_ERR DRV_NAME ": can't clear global reset\n");
1733101ffae26c23ea928fce6d31a8b4901327d91a15Jeff Garzik		rc = 1;
1734101ffae26c23ea928fce6d31a8b4901327d91a15Jeff Garzik	}
1735101ffae26c23ea928fce6d31a8b4901327d91a15Jeff Garzikdone:
1736101ffae26c23ea928fce6d31a8b4901327d91a15Jeff Garzik	return rc;
1737101ffae26c23ea928fce6d31a8b4901327d91a15Jeff Garzik}
1738101ffae26c23ea928fce6d31a8b4901327d91a15Jeff Garzik
173947c2b677daeed9c79ecb7167c211ff36876ea611Jeff Garzikstatic void mv6_read_preamp(struct mv_host_priv *hpriv, int idx,
1740ba3fe8fb6a469390a14379519915f3c39a973d99Jeff Garzik			   void __iomem *mmio)
1741ba3fe8fb6a469390a14379519915f3c39a973d99Jeff Garzik{
1742ba3fe8fb6a469390a14379519915f3c39a973d99Jeff Garzik	void __iomem *port_mmio;
1743ba3fe8fb6a469390a14379519915f3c39a973d99Jeff Garzik	u32 tmp;
1744ba3fe8fb6a469390a14379519915f3c39a973d99Jeff Garzik
1745ba3fe8fb6a469390a14379519915f3c39a973d99Jeff Garzik	tmp = readl(mmio + MV_RESET_CFG);
1746ba3fe8fb6a469390a14379519915f3c39a973d99Jeff Garzik	if ((tmp & (1 << 0)) == 0) {
174747c2b677daeed9c79ecb7167c211ff36876ea611Jeff Garzik		hpriv->signal[idx].amps = 0x7 << 8;
1748ba3fe8fb6a469390a14379519915f3c39a973d99Jeff Garzik		hpriv->signal[idx].pre = 0x1 << 5;
1749ba3fe8fb6a469390a14379519915f3c39a973d99Jeff Garzik		return;
1750ba3fe8fb6a469390a14379519915f3c39a973d99Jeff Garzik	}
1751ba3fe8fb6a469390a14379519915f3c39a973d99Jeff Garzik
1752ba3fe8fb6a469390a14379519915f3c39a973d99Jeff Garzik	port_mmio = mv_port_base(mmio, idx);
1753ba3fe8fb6a469390a14379519915f3c39a973d99Jeff Garzik	tmp = readl(port_mmio + PHY_MODE2);
1754ba3fe8fb6a469390a14379519915f3c39a973d99Jeff Garzik
1755ba3fe8fb6a469390a14379519915f3c39a973d99Jeff Garzik	hpriv->signal[idx].amps = tmp & 0x700;	/* bits 10:8 */
1756ba3fe8fb6a469390a14379519915f3c39a973d99Jeff Garzik	hpriv->signal[idx].pre = tmp & 0xe0;	/* bits 7:5 */
1757ba3fe8fb6a469390a14379519915f3c39a973d99Jeff Garzik}
1758ba3fe8fb6a469390a14379519915f3c39a973d99Jeff Garzik
175947c2b677daeed9c79ecb7167c211ff36876ea611Jeff Garzikstatic void mv6_enable_leds(struct mv_host_priv *hpriv, void __iomem *mmio)
1760ba3fe8fb6a469390a14379519915f3c39a973d99Jeff Garzik{
176147c2b677daeed9c79ecb7167c211ff36876ea611Jeff Garzik	writel(0x00000060, mmio + MV_GPIO_PORT_CTL);
1762ba3fe8fb6a469390a14379519915f3c39a973d99Jeff Garzik}
1763ba3fe8fb6a469390a14379519915f3c39a973d99Jeff Garzik
1764c9d39130123238ac18478a42e25cb7996eacfcc0Jeff Garzikstatic void mv6_phy_errata(struct mv_host_priv *hpriv, void __iomem *mmio,
17652a47ce06d534692f9bd2bf4e90a20fc9b1054c39Jeff Garzik			   unsigned int port)
1766bca1c4eb9411533d613123618c0d127fae532595Jeff Garzik{
1767c9d39130123238ac18478a42e25cb7996eacfcc0Jeff Garzik	void __iomem *port_mmio = mv_port_base(mmio, port);
1768c9d39130123238ac18478a42e25cb7996eacfcc0Jeff Garzik
1769bca1c4eb9411533d613123618c0d127fae532595Jeff Garzik	u32 hp_flags = hpriv->hp_flags;
177047c2b677daeed9c79ecb7167c211ff36876ea611Jeff Garzik	int fix_phy_mode2 =
177147c2b677daeed9c79ecb7167c211ff36876ea611Jeff Garzik		hp_flags & (MV_HP_ERRATA_60X1B2 | MV_HP_ERRATA_60X1C0);
1772bca1c4eb9411533d613123618c0d127fae532595Jeff Garzik	int fix_phy_mode4 =
177347c2b677daeed9c79ecb7167c211ff36876ea611Jeff Garzik		hp_flags & (MV_HP_ERRATA_60X1B2 | MV_HP_ERRATA_60X1C0);
177447c2b677daeed9c79ecb7167c211ff36876ea611Jeff Garzik	u32 m2, tmp;
177547c2b677daeed9c79ecb7167c211ff36876ea611Jeff Garzik
177647c2b677daeed9c79ecb7167c211ff36876ea611Jeff Garzik	if (fix_phy_mode2) {
177747c2b677daeed9c79ecb7167c211ff36876ea611Jeff Garzik		m2 = readl(port_mmio + PHY_MODE2);
177847c2b677daeed9c79ecb7167c211ff36876ea611Jeff Garzik		m2 &= ~(1 << 16);
177947c2b677daeed9c79ecb7167c211ff36876ea611Jeff Garzik		m2 |= (1 << 31);
178047c2b677daeed9c79ecb7167c211ff36876ea611Jeff Garzik		writel(m2, port_mmio + PHY_MODE2);
178147c2b677daeed9c79ecb7167c211ff36876ea611Jeff Garzik
178247c2b677daeed9c79ecb7167c211ff36876ea611Jeff Garzik		udelay(200);
178347c2b677daeed9c79ecb7167c211ff36876ea611Jeff Garzik
178447c2b677daeed9c79ecb7167c211ff36876ea611Jeff Garzik		m2 = readl(port_mmio + PHY_MODE2);
178547c2b677daeed9c79ecb7167c211ff36876ea611Jeff Garzik		m2 &= ~((1 << 16) | (1 << 31));
178647c2b677daeed9c79ecb7167c211ff36876ea611Jeff Garzik		writel(m2, port_mmio + PHY_MODE2);
178747c2b677daeed9c79ecb7167c211ff36876ea611Jeff Garzik
178847c2b677daeed9c79ecb7167c211ff36876ea611Jeff Garzik		udelay(200);
178947c2b677daeed9c79ecb7167c211ff36876ea611Jeff Garzik	}
179047c2b677daeed9c79ecb7167c211ff36876ea611Jeff Garzik
179147c2b677daeed9c79ecb7167c211ff36876ea611Jeff Garzik	/* who knows what this magic does */
179247c2b677daeed9c79ecb7167c211ff36876ea611Jeff Garzik	tmp = readl(port_mmio + PHY_MODE3);
179347c2b677daeed9c79ecb7167c211ff36876ea611Jeff Garzik	tmp &= ~0x7F800000;
179447c2b677daeed9c79ecb7167c211ff36876ea611Jeff Garzik	tmp |= 0x2A800000;
179547c2b677daeed9c79ecb7167c211ff36876ea611Jeff Garzik	writel(tmp, port_mmio + PHY_MODE3);
1796bca1c4eb9411533d613123618c0d127fae532595Jeff Garzik
1797bca1c4eb9411533d613123618c0d127fae532595Jeff Garzik	if (fix_phy_mode4) {
179847c2b677daeed9c79ecb7167c211ff36876ea611Jeff Garzik		u32 m4;
1799bca1c4eb9411533d613123618c0d127fae532595Jeff Garzik
1800bca1c4eb9411533d613123618c0d127fae532595Jeff Garzik		m4 = readl(port_mmio + PHY_MODE4);
180147c2b677daeed9c79ecb7167c211ff36876ea611Jeff Garzik
180247c2b677daeed9c79ecb7167c211ff36876ea611Jeff Garzik		if (hp_flags & MV_HP_ERRATA_60X1B2)
180347c2b677daeed9c79ecb7167c211ff36876ea611Jeff Garzik			tmp = readl(port_mmio + 0x310);
1804bca1c4eb9411533d613123618c0d127fae532595Jeff Garzik
1805bca1c4eb9411533d613123618c0d127fae532595Jeff Garzik		m4 = (m4 & ~(1 << 1)) | (1 << 0);
1806bca1c4eb9411533d613123618c0d127fae532595Jeff Garzik
1807bca1c4eb9411533d613123618c0d127fae532595Jeff Garzik		writel(m4, port_mmio + PHY_MODE4);
180847c2b677daeed9c79ecb7167c211ff36876ea611Jeff Garzik
180947c2b677daeed9c79ecb7167c211ff36876ea611Jeff Garzik		if (hp_flags & MV_HP_ERRATA_60X1B2)
181047c2b677daeed9c79ecb7167c211ff36876ea611Jeff Garzik			writel(tmp, port_mmio + 0x310);
1811bca1c4eb9411533d613123618c0d127fae532595Jeff Garzik	}
1812bca1c4eb9411533d613123618c0d127fae532595Jeff Garzik
1813bca1c4eb9411533d613123618c0d127fae532595Jeff Garzik	/* Revert values of pre-emphasis and signal amps to the saved ones */
1814bca1c4eb9411533d613123618c0d127fae532595Jeff Garzik	m2 = readl(port_mmio + PHY_MODE2);
1815bca1c4eb9411533d613123618c0d127fae532595Jeff Garzik
1816bca1c4eb9411533d613123618c0d127fae532595Jeff Garzik	m2 &= ~MV_M2_PREAMP_MASK;
18172a47ce06d534692f9bd2bf4e90a20fc9b1054c39Jeff Garzik	m2 |= hpriv->signal[port].amps;
18182a47ce06d534692f9bd2bf4e90a20fc9b1054c39Jeff Garzik	m2 |= hpriv->signal[port].pre;
181947c2b677daeed9c79ecb7167c211ff36876ea611Jeff Garzik	m2 &= ~(1 << 16);
1820bca1c4eb9411533d613123618c0d127fae532595Jeff Garzik
1821e4e7b89280d1d666e2c09e5ad36cf071796c4c7eJeff Garzik	/* according to mvSata 3.6.1, some IIE values are fixed */
1822e4e7b89280d1d666e2c09e5ad36cf071796c4c7eJeff Garzik	if (IS_GEN_IIE(hpriv)) {
1823e4e7b89280d1d666e2c09e5ad36cf071796c4c7eJeff Garzik		m2 &= ~0xC30FF01F;
1824e4e7b89280d1d666e2c09e5ad36cf071796c4c7eJeff Garzik		m2 |= 0x0000900F;
1825e4e7b89280d1d666e2c09e5ad36cf071796c4c7eJeff Garzik	}
1826e4e7b89280d1d666e2c09e5ad36cf071796c4c7eJeff Garzik
1827bca1c4eb9411533d613123618c0d127fae532595Jeff Garzik	writel(m2, port_mmio + PHY_MODE2);
1828bca1c4eb9411533d613123618c0d127fae532595Jeff Garzik}
1829bca1c4eb9411533d613123618c0d127fae532595Jeff Garzik
1830c9d39130123238ac18478a42e25cb7996eacfcc0Jeff Garzikstatic void mv_channel_reset(struct mv_host_priv *hpriv, void __iomem *mmio,
1831c9d39130123238ac18478a42e25cb7996eacfcc0Jeff Garzik			     unsigned int port_no)
1832c9d39130123238ac18478a42e25cb7996eacfcc0Jeff Garzik{
1833c9d39130123238ac18478a42e25cb7996eacfcc0Jeff Garzik	void __iomem *port_mmio = mv_port_base(mmio, port_no);
1834c9d39130123238ac18478a42e25cb7996eacfcc0Jeff Garzik
1835c9d39130123238ac18478a42e25cb7996eacfcc0Jeff Garzik	writelfl(ATA_RST, port_mmio + EDMA_CMD_OFS);
1836c9d39130123238ac18478a42e25cb7996eacfcc0Jeff Garzik
1837c9d39130123238ac18478a42e25cb7996eacfcc0Jeff Garzik	if (IS_60XX(hpriv)) {
1838c9d39130123238ac18478a42e25cb7996eacfcc0Jeff Garzik		u32 ifctl = readl(port_mmio + SATA_INTERFACE_CTL);
1839eb46d684600ac145501805a294c94675e82eab2eMark Lord		ifctl |= (1 << 7);		/* enable gen2i speed */
1840eb46d684600ac145501805a294c94675e82eab2eMark Lord		ifctl = (ifctl & 0xfff) | 0x9b1000; /* from chip spec */
1841c9d39130123238ac18478a42e25cb7996eacfcc0Jeff Garzik		writelfl(ifctl, port_mmio + SATA_INTERFACE_CTL);
1842c9d39130123238ac18478a42e25cb7996eacfcc0Jeff Garzik	}
1843c9d39130123238ac18478a42e25cb7996eacfcc0Jeff Garzik
1844c9d39130123238ac18478a42e25cb7996eacfcc0Jeff Garzik	udelay(25);		/* allow reset propagation */
1845c9d39130123238ac18478a42e25cb7996eacfcc0Jeff Garzik
1846c9d39130123238ac18478a42e25cb7996eacfcc0Jeff Garzik	/* Spec never mentions clearing the bit.  Marvell's driver does
1847c9d39130123238ac18478a42e25cb7996eacfcc0Jeff Garzik	 * clear the bit, however.
1848c9d39130123238ac18478a42e25cb7996eacfcc0Jeff Garzik	 */
1849c9d39130123238ac18478a42e25cb7996eacfcc0Jeff Garzik	writelfl(0, port_mmio + EDMA_CMD_OFS);
1850c9d39130123238ac18478a42e25cb7996eacfcc0Jeff Garzik
1851c9d39130123238ac18478a42e25cb7996eacfcc0Jeff Garzik	hpriv->ops->phy_errata(hpriv, mmio, port_no);
1852c9d39130123238ac18478a42e25cb7996eacfcc0Jeff Garzik
1853c9d39130123238ac18478a42e25cb7996eacfcc0Jeff Garzik	if (IS_50XX(hpriv))
1854c9d39130123238ac18478a42e25cb7996eacfcc0Jeff Garzik		mdelay(1);
1855c9d39130123238ac18478a42e25cb7996eacfcc0Jeff Garzik}
1856c9d39130123238ac18478a42e25cb7996eacfcc0Jeff Garzik
1857c9d39130123238ac18478a42e25cb7996eacfcc0Jeff Garzikstatic void mv_stop_and_reset(struct ata_port *ap)
1858c9d39130123238ac18478a42e25cb7996eacfcc0Jeff Garzik{
1859cca3974e48607c3775dc73b544a5700b2e37c21aJeff Garzik	struct mv_host_priv *hpriv = ap->host->private_data;
18600d5ff566779f894ca9937231a181eb31e4adff0eTejun Heo	void __iomem *mmio = ap->host->iomap[MV_PRIMARY_BAR];
1861c9d39130123238ac18478a42e25cb7996eacfcc0Jeff Garzik
1862c9d39130123238ac18478a42e25cb7996eacfcc0Jeff Garzik	mv_stop_dma(ap);
1863c9d39130123238ac18478a42e25cb7996eacfcc0Jeff Garzik
1864c9d39130123238ac18478a42e25cb7996eacfcc0Jeff Garzik	mv_channel_reset(hpriv, mmio, ap->port_no);
1865c9d39130123238ac18478a42e25cb7996eacfcc0Jeff Garzik
186622374677d18c5eeefd3a283431d312b8c44fef02Jeff Garzik	__mv_phy_reset(ap, 0);
186722374677d18c5eeefd3a283431d312b8c44fef02Jeff Garzik}
186822374677d18c5eeefd3a283431d312b8c44fef02Jeff Garzik
186922374677d18c5eeefd3a283431d312b8c44fef02Jeff Garzikstatic inline void __msleep(unsigned int msec, int can_sleep)
187022374677d18c5eeefd3a283431d312b8c44fef02Jeff Garzik{
187122374677d18c5eeefd3a283431d312b8c44fef02Jeff Garzik	if (can_sleep)
187222374677d18c5eeefd3a283431d312b8c44fef02Jeff Garzik		msleep(msec);
187322374677d18c5eeefd3a283431d312b8c44fef02Jeff Garzik	else
187422374677d18c5eeefd3a283431d312b8c44fef02Jeff Garzik		mdelay(msec);
1875c9d39130123238ac18478a42e25cb7996eacfcc0Jeff Garzik}
1876c9d39130123238ac18478a42e25cb7996eacfcc0Jeff Garzik
187705b308e1df6d9d673daedb517969241f41278b52Brett Russ/**
187822374677d18c5eeefd3a283431d312b8c44fef02Jeff Garzik *      __mv_phy_reset - Perform eDMA reset followed by COMRESET
187905b308e1df6d9d673daedb517969241f41278b52Brett Russ *      @ap: ATA channel to manipulate
188005b308e1df6d9d673daedb517969241f41278b52Brett Russ *
188105b308e1df6d9d673daedb517969241f41278b52Brett Russ *      Part of this is taken from __sata_phy_reset and modified to
188205b308e1df6d9d673daedb517969241f41278b52Brett Russ *      not sleep since this routine gets called from interrupt level.
188305b308e1df6d9d673daedb517969241f41278b52Brett Russ *
188405b308e1df6d9d673daedb517969241f41278b52Brett Russ *      LOCKING:
188505b308e1df6d9d673daedb517969241f41278b52Brett Russ *      Inherited from caller.  This is coded to safe to call at
188605b308e1df6d9d673daedb517969241f41278b52Brett Russ *      interrupt level, i.e. it does not sleep.
188731961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ */
188822374677d18c5eeefd3a283431d312b8c44fef02Jeff Garzikstatic void __mv_phy_reset(struct ata_port *ap, int can_sleep)
188920f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ{
1890095fec887eaa1c38d17c0c929a6733c744a9fa1fJeff Garzik	struct mv_port_priv *pp	= ap->private_data;
1891cca3974e48607c3775dc73b544a5700b2e37c21aJeff Garzik	struct mv_host_priv *hpriv = ap->host->private_data;
189220f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ	void __iomem *port_mmio = mv_ap_base(ap);
189320f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ	struct ata_taskfile tf;
189420f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ	struct ata_device *dev = &ap->device[0];
189531961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ	unsigned long timeout;
189622374677d18c5eeefd3a283431d312b8c44fef02Jeff Garzik	int retry = 5;
189722374677d18c5eeefd3a283431d312b8c44fef02Jeff Garzik	u32 sstatus;
189820f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ
189920f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ	VPRINTK("ENTER, port %u, mmio 0x%p\n", ap->port_no, port_mmio);
190020f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ
1901095fec887eaa1c38d17c0c929a6733c744a9fa1fJeff Garzik	DPRINTK("S-regs after ATA_RST: SStat 0x%08x SErr 0x%08x "
190231961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ		"SCtrl 0x%08x\n", mv_scr_read(ap, SCR_STATUS),
190331961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ		mv_scr_read(ap, SCR_ERROR), mv_scr_read(ap, SCR_CONTROL));
190420f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ
190522374677d18c5eeefd3a283431d312b8c44fef02Jeff Garzik	/* Issue COMRESET via SControl */
190622374677d18c5eeefd3a283431d312b8c44fef02Jeff Garzikcomreset_retry:
190781952c5497b40ae56835bd0d6537f8c6bdea07e7Tejun Heo	sata_scr_write_flush(ap, SCR_CONTROL, 0x301);
190822374677d18c5eeefd3a283431d312b8c44fef02Jeff Garzik	__msleep(1, can_sleep);
190922374677d18c5eeefd3a283431d312b8c44fef02Jeff Garzik
191081952c5497b40ae56835bd0d6537f8c6bdea07e7Tejun Heo	sata_scr_write_flush(ap, SCR_CONTROL, 0x300);
191122374677d18c5eeefd3a283431d312b8c44fef02Jeff Garzik	__msleep(20, can_sleep);
191222374677d18c5eeefd3a283431d312b8c44fef02Jeff Garzik
191322374677d18c5eeefd3a283431d312b8c44fef02Jeff Garzik	timeout = jiffies + msecs_to_jiffies(200);
191431961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ	do {
191581952c5497b40ae56835bd0d6537f8c6bdea07e7Tejun Heo		sata_scr_read(ap, SCR_STATUS, &sstatus);
191662f1d0e6de138b91d55fbd7d579c837ed62e9e31Andres Salomon		if (((sstatus & 0x3) == 3) || ((sstatus & 0x3) == 0))
191731961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ			break;
191822374677d18c5eeefd3a283431d312b8c44fef02Jeff Garzik
191922374677d18c5eeefd3a283431d312b8c44fef02Jeff Garzik		__msleep(1, can_sleep);
192031961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ	} while (time_before(jiffies, timeout));
192120f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ
192222374677d18c5eeefd3a283431d312b8c44fef02Jeff Garzik	/* work around errata */
192322374677d18c5eeefd3a283431d312b8c44fef02Jeff Garzik	if (IS_60XX(hpriv) &&
192422374677d18c5eeefd3a283431d312b8c44fef02Jeff Garzik	    (sstatus != 0x0) && (sstatus != 0x113) && (sstatus != 0x123) &&
192522374677d18c5eeefd3a283431d312b8c44fef02Jeff Garzik	    (retry-- > 0))
192622374677d18c5eeefd3a283431d312b8c44fef02Jeff Garzik		goto comreset_retry;
1927095fec887eaa1c38d17c0c929a6733c744a9fa1fJeff Garzik
1928095fec887eaa1c38d17c0c929a6733c744a9fa1fJeff Garzik	DPRINTK("S-regs after PHY wake: SStat 0x%08x SErr 0x%08x "
192931961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ		"SCtrl 0x%08x\n", mv_scr_read(ap, SCR_STATUS),
193031961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ		mv_scr_read(ap, SCR_ERROR), mv_scr_read(ap, SCR_CONTROL));
193131961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ
193281952c5497b40ae56835bd0d6537f8c6bdea07e7Tejun Heo	if (ata_port_online(ap)) {
193331961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ		ata_port_probe(ap);
193431961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ	} else {
193581952c5497b40ae56835bd0d6537f8c6bdea07e7Tejun Heo		sata_scr_read(ap, SCR_STATUS, &sstatus);
1936f15a1dafed22d5037e0feea7528e1eeb28a1a7a3Tejun Heo		ata_port_printk(ap, KERN_INFO,
1937f15a1dafed22d5037e0feea7528e1eeb28a1a7a3Tejun Heo				"no device found (phy stat %08x)\n", sstatus);
193831961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ		ata_port_disable(ap);
193920f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ		return;
194020f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ	}
194131961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ	ap->cbl = ATA_CBL_SATA;
194220f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ
194322374677d18c5eeefd3a283431d312b8c44fef02Jeff Garzik	/* even after SStatus reflects that device is ready,
194422374677d18c5eeefd3a283431d312b8c44fef02Jeff Garzik	 * it seems to take a while for link to be fully
194522374677d18c5eeefd3a283431d312b8c44fef02Jeff Garzik	 * established (and thus Status no longer 0x80/0x7F),
194622374677d18c5eeefd3a283431d312b8c44fef02Jeff Garzik	 * so we poll a bit for that, here.
194722374677d18c5eeefd3a283431d312b8c44fef02Jeff Garzik	 */
194822374677d18c5eeefd3a283431d312b8c44fef02Jeff Garzik	retry = 20;
194922374677d18c5eeefd3a283431d312b8c44fef02Jeff Garzik	while (1) {
195022374677d18c5eeefd3a283431d312b8c44fef02Jeff Garzik		u8 drv_stat = ata_check_status(ap);
195122374677d18c5eeefd3a283431d312b8c44fef02Jeff Garzik		if ((drv_stat != 0x80) && (drv_stat != 0x7f))
195222374677d18c5eeefd3a283431d312b8c44fef02Jeff Garzik			break;
195322374677d18c5eeefd3a283431d312b8c44fef02Jeff Garzik		__msleep(500, can_sleep);
195422374677d18c5eeefd3a283431d312b8c44fef02Jeff Garzik		if (retry-- <= 0)
195522374677d18c5eeefd3a283431d312b8c44fef02Jeff Garzik			break;
195622374677d18c5eeefd3a283431d312b8c44fef02Jeff Garzik	}
195722374677d18c5eeefd3a283431d312b8c44fef02Jeff Garzik
19580d5ff566779f894ca9937231a181eb31e4adff0eTejun Heo	tf.lbah = readb(ap->ioaddr.lbah_addr);
19590d5ff566779f894ca9937231a181eb31e4adff0eTejun Heo	tf.lbam = readb(ap->ioaddr.lbam_addr);
19600d5ff566779f894ca9937231a181eb31e4adff0eTejun Heo	tf.lbal = readb(ap->ioaddr.lbal_addr);
19610d5ff566779f894ca9937231a181eb31e4adff0eTejun Heo	tf.nsect = readb(ap->ioaddr.nsect_addr);
196220f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ
196320f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ	dev->class = ata_dev_classify(&tf);
1964e1211e3fa7fd05ff0d4f597fd37e40de8acc6784Tejun Heo	if (!ata_dev_enabled(dev)) {
196520f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ		VPRINTK("Port disabled post-sig: No device present.\n");
196620f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ		ata_port_disable(ap);
196720f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ	}
1968095fec887eaa1c38d17c0c929a6733c744a9fa1fJeff Garzik
1969095fec887eaa1c38d17c0c929a6733c744a9fa1fJeff Garzik	writelfl(0, port_mmio + EDMA_ERR_IRQ_CAUSE_OFS);
1970095fec887eaa1c38d17c0c929a6733c744a9fa1fJeff Garzik
1971095fec887eaa1c38d17c0c929a6733c744a9fa1fJeff Garzik	pp->pp_flags &= ~MV_PP_FLAG_EDMA_EN;
1972095fec887eaa1c38d17c0c929a6733c744a9fa1fJeff Garzik
1973bca1c4eb9411533d613123618c0d127fae532595Jeff Garzik	VPRINTK("EXIT\n");
197420f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ}
197520f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ
197622374677d18c5eeefd3a283431d312b8c44fef02Jeff Garzikstatic void mv_phy_reset(struct ata_port *ap)
197722374677d18c5eeefd3a283431d312b8c44fef02Jeff Garzik{
197822374677d18c5eeefd3a283431d312b8c44fef02Jeff Garzik	__mv_phy_reset(ap, 1);
197922374677d18c5eeefd3a283431d312b8c44fef02Jeff Garzik}
198022374677d18c5eeefd3a283431d312b8c44fef02Jeff Garzik
198105b308e1df6d9d673daedb517969241f41278b52Brett Russ/**
198205b308e1df6d9d673daedb517969241f41278b52Brett Russ *      mv_eng_timeout - Routine called by libata when SCSI times out I/O
198305b308e1df6d9d673daedb517969241f41278b52Brett Russ *      @ap: ATA channel to manipulate
198405b308e1df6d9d673daedb517969241f41278b52Brett Russ *
198505b308e1df6d9d673daedb517969241f41278b52Brett Russ *      Intent is to clear all pending error conditions, reset the
198605b308e1df6d9d673daedb517969241f41278b52Brett Russ *      chip/bus, fail the command, and move on.
198705b308e1df6d9d673daedb517969241f41278b52Brett Russ *
198805b308e1df6d9d673daedb517969241f41278b52Brett Russ *      LOCKING:
1989cca3974e48607c3775dc73b544a5700b2e37c21aJeff Garzik *      This routine holds the host lock while failing the command.
199005b308e1df6d9d673daedb517969241f41278b52Brett Russ */
199131961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russstatic void mv_eng_timeout(struct ata_port *ap)
199231961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ{
19930d5ff566779f894ca9937231a181eb31e4adff0eTejun Heo	void __iomem *mmio = ap->host->iomap[MV_PRIMARY_BAR];
199431961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ	struct ata_queued_cmd *qc;
19952f9719b61e1fcf7422a016ac4f2420a0cc6ba320Mark Lord	unsigned long flags;
199631961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ
1997f15a1dafed22d5037e0feea7528e1eeb28a1a7a3Tejun Heo	ata_port_printk(ap, KERN_ERR, "Entering mv_eng_timeout\n");
199831961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ	DPRINTK("All regs @ start of eng_timeout\n");
19990d5ff566779f894ca9937231a181eb31e4adff0eTejun Heo	mv_dump_all_regs(mmio, ap->port_no, to_pci_dev(ap->host->dev));
200031961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ
200131961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ	qc = ata_qc_from_tag(ap, ap->active_tag);
200231961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ        printk(KERN_ERR "mmio_base %p ap %p qc %p scsi_cmnd %p &cmnd %p\n",
20030d5ff566779f894ca9937231a181eb31e4adff0eTejun Heo	       mmio, ap, qc, qc->scsicmd, &qc->scsicmd->cmnd);
200431961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ
2005cca3974e48607c3775dc73b544a5700b2e37c21aJeff Garzik	spin_lock_irqsave(&ap->host->lock, flags);
20069b358e305c1d783c8a4ebf00344e95deb9e38f3dMark Lord	mv_err_intr(ap, 0);
2007c9d39130123238ac18478a42e25cb7996eacfcc0Jeff Garzik	mv_stop_and_reset(ap);
2008cca3974e48607c3775dc73b544a5700b2e37c21aJeff Garzik	spin_unlock_irqrestore(&ap->host->lock, flags);
200931961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ
20109b358e305c1d783c8a4ebf00344e95deb9e38f3dMark Lord	WARN_ON(!(qc->flags & ATA_QCFLAG_ACTIVE));
20119b358e305c1d783c8a4ebf00344e95deb9e38f3dMark Lord	if (qc->flags & ATA_QCFLAG_ACTIVE) {
20129b358e305c1d783c8a4ebf00344e95deb9e38f3dMark Lord		qc->err_mask |= AC_ERR_TIMEOUT;
20139b358e305c1d783c8a4ebf00344e95deb9e38f3dMark Lord		ata_eh_qc_complete(qc);
20149b358e305c1d783c8a4ebf00344e95deb9e38f3dMark Lord	}
201531961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ}
201631961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ
201705b308e1df6d9d673daedb517969241f41278b52Brett Russ/**
201805b308e1df6d9d673daedb517969241f41278b52Brett Russ *      mv_port_init - Perform some early initialization on a single port.
201905b308e1df6d9d673daedb517969241f41278b52Brett Russ *      @port: libata data structure storing shadow register addresses
202005b308e1df6d9d673daedb517969241f41278b52Brett Russ *      @port_mmio: base address of the port
202105b308e1df6d9d673daedb517969241f41278b52Brett Russ *
202205b308e1df6d9d673daedb517969241f41278b52Brett Russ *      Initialize shadow register mmio addresses, clear outstanding
202305b308e1df6d9d673daedb517969241f41278b52Brett Russ *      interrupts on the port, and unmask interrupts for the future
202405b308e1df6d9d673daedb517969241f41278b52Brett Russ *      start of the port.
202505b308e1df6d9d673daedb517969241f41278b52Brett Russ *
202605b308e1df6d9d673daedb517969241f41278b52Brett Russ *      LOCKING:
202705b308e1df6d9d673daedb517969241f41278b52Brett Russ *      Inherited from caller.
202805b308e1df6d9d673daedb517969241f41278b52Brett Russ */
202931961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russstatic void mv_port_init(struct ata_ioports *port,  void __iomem *port_mmio)
203020f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ{
20310d5ff566779f894ca9937231a181eb31e4adff0eTejun Heo	void __iomem *shd_base = port_mmio + SHD_BLK_OFS;
203231961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ	unsigned serr_ofs;
203331961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ
20348b260248d9e0e8b64bb72fd4dee03ad86984c344Jeff Garzik	/* PIO related setup
203531961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ	 */
203631961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ	port->data_addr = shd_base + (sizeof(u32) * ATA_REG_DATA);
20378b260248d9e0e8b64bb72fd4dee03ad86984c344Jeff Garzik	port->error_addr =
203831961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ		port->feature_addr = shd_base + (sizeof(u32) * ATA_REG_ERR);
203931961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ	port->nsect_addr = shd_base + (sizeof(u32) * ATA_REG_NSECT);
204031961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ	port->lbal_addr = shd_base + (sizeof(u32) * ATA_REG_LBAL);
204131961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ	port->lbam_addr = shd_base + (sizeof(u32) * ATA_REG_LBAM);
204231961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ	port->lbah_addr = shd_base + (sizeof(u32) * ATA_REG_LBAH);
204331961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ	port->device_addr = shd_base + (sizeof(u32) * ATA_REG_DEVICE);
20448b260248d9e0e8b64bb72fd4dee03ad86984c344Jeff Garzik	port->status_addr =
204531961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ		port->command_addr = shd_base + (sizeof(u32) * ATA_REG_STATUS);
204631961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ	/* special case: control/altstatus doesn't have ATA_REG_ address */
204731961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ	port->altstatus_addr = port->ctl_addr = shd_base + SHD_CTL_AST_OFS;
204831961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ
204931961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ	/* unused: */
205020f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ	port->cmd_addr = port->bmdma_addr = port->scr_addr = 0;
205120f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ
205231961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ	/* Clear any currently outstanding port interrupt conditions */
205331961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ	serr_ofs = mv_scr_offset(SCR_ERROR);
205431961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ	writelfl(readl(port_mmio + serr_ofs), port_mmio + serr_ofs);
205531961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ	writelfl(0, port_mmio + EDMA_ERR_IRQ_CAUSE_OFS);
205631961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ
205720f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ	/* unmask all EDMA error interrupts */
205831961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ	writelfl(~0, port_mmio + EDMA_ERR_IRQ_MASK_OFS);
205920f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ
20608b260248d9e0e8b64bb72fd4dee03ad86984c344Jeff Garzik	VPRINTK("EDMA cfg=0x%08x EDMA IRQ err cause/mask=0x%08x/0x%08x\n",
206131961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ		readl(port_mmio + EDMA_CFG_OFS),
206231961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ		readl(port_mmio + EDMA_ERR_IRQ_CAUSE_OFS),
206331961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ		readl(port_mmio + EDMA_ERR_IRQ_MASK_OFS));
206420f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ}
206520f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ
206647c2b677daeed9c79ecb7167c211ff36876ea611Jeff Garzikstatic int mv_chip_id(struct pci_dev *pdev, struct mv_host_priv *hpriv,
2067522479fb98c6667f081e75f87e298e413c0b1db8Jeff Garzik		      unsigned int board_idx)
2068bca1c4eb9411533d613123618c0d127fae532595Jeff Garzik{
2069bca1c4eb9411533d613123618c0d127fae532595Jeff Garzik	u8 rev_id;
2070bca1c4eb9411533d613123618c0d127fae532595Jeff Garzik	u32 hp_flags = hpriv->hp_flags;
2071bca1c4eb9411533d613123618c0d127fae532595Jeff Garzik
2072bca1c4eb9411533d613123618c0d127fae532595Jeff Garzik	pci_read_config_byte(pdev, PCI_REVISION_ID, &rev_id);
2073bca1c4eb9411533d613123618c0d127fae532595Jeff Garzik
2074bca1c4eb9411533d613123618c0d127fae532595Jeff Garzik	switch(board_idx) {
207547c2b677daeed9c79ecb7167c211ff36876ea611Jeff Garzik	case chip_5080:
207647c2b677daeed9c79ecb7167c211ff36876ea611Jeff Garzik		hpriv->ops = &mv5xxx_ops;
207747c2b677daeed9c79ecb7167c211ff36876ea611Jeff Garzik		hp_flags |= MV_HP_50XX;
207847c2b677daeed9c79ecb7167c211ff36876ea611Jeff Garzik
207947c2b677daeed9c79ecb7167c211ff36876ea611Jeff Garzik		switch (rev_id) {
208047c2b677daeed9c79ecb7167c211ff36876ea611Jeff Garzik		case 0x1:
208147c2b677daeed9c79ecb7167c211ff36876ea611Jeff Garzik			hp_flags |= MV_HP_ERRATA_50XXB0;
208247c2b677daeed9c79ecb7167c211ff36876ea611Jeff Garzik			break;
208347c2b677daeed9c79ecb7167c211ff36876ea611Jeff Garzik		case 0x3:
208447c2b677daeed9c79ecb7167c211ff36876ea611Jeff Garzik			hp_flags |= MV_HP_ERRATA_50XXB2;
208547c2b677daeed9c79ecb7167c211ff36876ea611Jeff Garzik			break;
208647c2b677daeed9c79ecb7167c211ff36876ea611Jeff Garzik		default:
208747c2b677daeed9c79ecb7167c211ff36876ea611Jeff Garzik			dev_printk(KERN_WARNING, &pdev->dev,
208847c2b677daeed9c79ecb7167c211ff36876ea611Jeff Garzik			   "Applying 50XXB2 workarounds to unknown rev\n");
208947c2b677daeed9c79ecb7167c211ff36876ea611Jeff Garzik			hp_flags |= MV_HP_ERRATA_50XXB2;
209047c2b677daeed9c79ecb7167c211ff36876ea611Jeff Garzik			break;
209147c2b677daeed9c79ecb7167c211ff36876ea611Jeff Garzik		}
209247c2b677daeed9c79ecb7167c211ff36876ea611Jeff Garzik		break;
209347c2b677daeed9c79ecb7167c211ff36876ea611Jeff Garzik
2094bca1c4eb9411533d613123618c0d127fae532595Jeff Garzik	case chip_504x:
2095bca1c4eb9411533d613123618c0d127fae532595Jeff Garzik	case chip_508x:
209647c2b677daeed9c79ecb7167c211ff36876ea611Jeff Garzik		hpriv->ops = &mv5xxx_ops;
2097bca1c4eb9411533d613123618c0d127fae532595Jeff Garzik		hp_flags |= MV_HP_50XX;
2098bca1c4eb9411533d613123618c0d127fae532595Jeff Garzik
209947c2b677daeed9c79ecb7167c211ff36876ea611Jeff Garzik		switch (rev_id) {
210047c2b677daeed9c79ecb7167c211ff36876ea611Jeff Garzik		case 0x0:
210147c2b677daeed9c79ecb7167c211ff36876ea611Jeff Garzik			hp_flags |= MV_HP_ERRATA_50XXB0;
210247c2b677daeed9c79ecb7167c211ff36876ea611Jeff Garzik			break;
210347c2b677daeed9c79ecb7167c211ff36876ea611Jeff Garzik		case 0x3:
210447c2b677daeed9c79ecb7167c211ff36876ea611Jeff Garzik			hp_flags |= MV_HP_ERRATA_50XXB2;
210547c2b677daeed9c79ecb7167c211ff36876ea611Jeff Garzik			break;
210647c2b677daeed9c79ecb7167c211ff36876ea611Jeff Garzik		default:
210747c2b677daeed9c79ecb7167c211ff36876ea611Jeff Garzik			dev_printk(KERN_WARNING, &pdev->dev,
210847c2b677daeed9c79ecb7167c211ff36876ea611Jeff Garzik			   "Applying B2 workarounds to unknown rev\n");
210947c2b677daeed9c79ecb7167c211ff36876ea611Jeff Garzik			hp_flags |= MV_HP_ERRATA_50XXB2;
211047c2b677daeed9c79ecb7167c211ff36876ea611Jeff Garzik			break;
2111bca1c4eb9411533d613123618c0d127fae532595Jeff Garzik		}
2112bca1c4eb9411533d613123618c0d127fae532595Jeff Garzik		break;
2113bca1c4eb9411533d613123618c0d127fae532595Jeff Garzik
2114bca1c4eb9411533d613123618c0d127fae532595Jeff Garzik	case chip_604x:
2115bca1c4eb9411533d613123618c0d127fae532595Jeff Garzik	case chip_608x:
211647c2b677daeed9c79ecb7167c211ff36876ea611Jeff Garzik		hpriv->ops = &mv6xxx_ops;
211747c2b677daeed9c79ecb7167c211ff36876ea611Jeff Garzik
2118bca1c4eb9411533d613123618c0d127fae532595Jeff Garzik		switch (rev_id) {
211947c2b677daeed9c79ecb7167c211ff36876ea611Jeff Garzik		case 0x7:
212047c2b677daeed9c79ecb7167c211ff36876ea611Jeff Garzik			hp_flags |= MV_HP_ERRATA_60X1B2;
212147c2b677daeed9c79ecb7167c211ff36876ea611Jeff Garzik			break;
212247c2b677daeed9c79ecb7167c211ff36876ea611Jeff Garzik		case 0x9:
212347c2b677daeed9c79ecb7167c211ff36876ea611Jeff Garzik			hp_flags |= MV_HP_ERRATA_60X1C0;
2124bca1c4eb9411533d613123618c0d127fae532595Jeff Garzik			break;
2125bca1c4eb9411533d613123618c0d127fae532595Jeff Garzik		default:
2126bca1c4eb9411533d613123618c0d127fae532595Jeff Garzik			dev_printk(KERN_WARNING, &pdev->dev,
212747c2b677daeed9c79ecb7167c211ff36876ea611Jeff Garzik				   "Applying B2 workarounds to unknown rev\n");
212847c2b677daeed9c79ecb7167c211ff36876ea611Jeff Garzik			hp_flags |= MV_HP_ERRATA_60X1B2;
2129bca1c4eb9411533d613123618c0d127fae532595Jeff Garzik			break;
2130bca1c4eb9411533d613123618c0d127fae532595Jeff Garzik		}
2131bca1c4eb9411533d613123618c0d127fae532595Jeff Garzik		break;
2132bca1c4eb9411533d613123618c0d127fae532595Jeff Garzik
2133e4e7b89280d1d666e2c09e5ad36cf071796c4c7eJeff Garzik	case chip_7042:
2134e4e7b89280d1d666e2c09e5ad36cf071796c4c7eJeff Garzik	case chip_6042:
2135e4e7b89280d1d666e2c09e5ad36cf071796c4c7eJeff Garzik		hpriv->ops = &mv6xxx_ops;
2136e4e7b89280d1d666e2c09e5ad36cf071796c4c7eJeff Garzik
2137e4e7b89280d1d666e2c09e5ad36cf071796c4c7eJeff Garzik		hp_flags |= MV_HP_GEN_IIE;
2138e4e7b89280d1d666e2c09e5ad36cf071796c4c7eJeff Garzik
2139e4e7b89280d1d666e2c09e5ad36cf071796c4c7eJeff Garzik		switch (rev_id) {
2140e4e7b89280d1d666e2c09e5ad36cf071796c4c7eJeff Garzik		case 0x0:
2141e4e7b89280d1d666e2c09e5ad36cf071796c4c7eJeff Garzik			hp_flags |= MV_HP_ERRATA_XX42A0;
2142e4e7b89280d1d666e2c09e5ad36cf071796c4c7eJeff Garzik			break;
2143e4e7b89280d1d666e2c09e5ad36cf071796c4c7eJeff Garzik		case 0x1:
2144e4e7b89280d1d666e2c09e5ad36cf071796c4c7eJeff Garzik			hp_flags |= MV_HP_ERRATA_60X1C0;
2145e4e7b89280d1d666e2c09e5ad36cf071796c4c7eJeff Garzik			break;
2146e4e7b89280d1d666e2c09e5ad36cf071796c4c7eJeff Garzik		default:
2147e4e7b89280d1d666e2c09e5ad36cf071796c4c7eJeff Garzik			dev_printk(KERN_WARNING, &pdev->dev,
2148e4e7b89280d1d666e2c09e5ad36cf071796c4c7eJeff Garzik			   "Applying 60X1C0 workarounds to unknown rev\n");
2149e4e7b89280d1d666e2c09e5ad36cf071796c4c7eJeff Garzik			hp_flags |= MV_HP_ERRATA_60X1C0;
2150e4e7b89280d1d666e2c09e5ad36cf071796c4c7eJeff Garzik			break;
2151e4e7b89280d1d666e2c09e5ad36cf071796c4c7eJeff Garzik		}
2152e4e7b89280d1d666e2c09e5ad36cf071796c4c7eJeff Garzik		break;
2153e4e7b89280d1d666e2c09e5ad36cf071796c4c7eJeff Garzik
2154bca1c4eb9411533d613123618c0d127fae532595Jeff Garzik	default:
2155bca1c4eb9411533d613123618c0d127fae532595Jeff Garzik		printk(KERN_ERR DRV_NAME ": BUG: invalid board index %u\n", board_idx);
2156bca1c4eb9411533d613123618c0d127fae532595Jeff Garzik		return 1;
2157bca1c4eb9411533d613123618c0d127fae532595Jeff Garzik	}
2158bca1c4eb9411533d613123618c0d127fae532595Jeff Garzik
2159bca1c4eb9411533d613123618c0d127fae532595Jeff Garzik	hpriv->hp_flags = hp_flags;
2160bca1c4eb9411533d613123618c0d127fae532595Jeff Garzik
2161bca1c4eb9411533d613123618c0d127fae532595Jeff Garzik	return 0;
2162bca1c4eb9411533d613123618c0d127fae532595Jeff Garzik}
2163bca1c4eb9411533d613123618c0d127fae532595Jeff Garzik
216405b308e1df6d9d673daedb517969241f41278b52Brett Russ/**
216547c2b677daeed9c79ecb7167c211ff36876ea611Jeff Garzik *      mv_init_host - Perform some early initialization of the host.
2166bca1c4eb9411533d613123618c0d127fae532595Jeff Garzik *	@pdev: host PCI device
216705b308e1df6d9d673daedb517969241f41278b52Brett Russ *      @probe_ent: early data struct representing the host
216805b308e1df6d9d673daedb517969241f41278b52Brett Russ *
216905b308e1df6d9d673daedb517969241f41278b52Brett Russ *      If possible, do an early global reset of the host.  Then do
217005b308e1df6d9d673daedb517969241f41278b52Brett Russ *      our port init and clear/unmask all/relevant host interrupts.
217105b308e1df6d9d673daedb517969241f41278b52Brett Russ *
217205b308e1df6d9d673daedb517969241f41278b52Brett Russ *      LOCKING:
217305b308e1df6d9d673daedb517969241f41278b52Brett Russ *      Inherited from caller.
217405b308e1df6d9d673daedb517969241f41278b52Brett Russ */
217547c2b677daeed9c79ecb7167c211ff36876ea611Jeff Garzikstatic int mv_init_host(struct pci_dev *pdev, struct ata_probe_ent *probe_ent,
2176bca1c4eb9411533d613123618c0d127fae532595Jeff Garzik			unsigned int board_idx)
217720f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ{
217820f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ	int rc = 0, n_hc, port, hc;
21790d5ff566779f894ca9937231a181eb31e4adff0eTejun Heo	void __iomem *mmio = probe_ent->iomap[MV_PRIMARY_BAR];
2180bca1c4eb9411533d613123618c0d127fae532595Jeff Garzik	struct mv_host_priv *hpriv = probe_ent->private_data;
2181bca1c4eb9411533d613123618c0d127fae532595Jeff Garzik
218247c2b677daeed9c79ecb7167c211ff36876ea611Jeff Garzik	/* global interrupt mask */
218347c2b677daeed9c79ecb7167c211ff36876ea611Jeff Garzik	writel(0, mmio + HC_MAIN_IRQ_MASK_OFS);
218447c2b677daeed9c79ecb7167c211ff36876ea611Jeff Garzik
218547c2b677daeed9c79ecb7167c211ff36876ea611Jeff Garzik	rc = mv_chip_id(pdev, hpriv, board_idx);
2186bca1c4eb9411533d613123618c0d127fae532595Jeff Garzik	if (rc)
2187bca1c4eb9411533d613123618c0d127fae532595Jeff Garzik		goto done;
2188bca1c4eb9411533d613123618c0d127fae532595Jeff Garzik
2189cca3974e48607c3775dc73b544a5700b2e37c21aJeff Garzik	n_hc = mv_get_hc_count(probe_ent->port_flags);
2190bca1c4eb9411533d613123618c0d127fae532595Jeff Garzik	probe_ent->n_ports = MV_PORTS_PER_HC * n_hc;
2191bca1c4eb9411533d613123618c0d127fae532595Jeff Garzik
219247c2b677daeed9c79ecb7167c211ff36876ea611Jeff Garzik	for (port = 0; port < probe_ent->n_ports; port++)
219347c2b677daeed9c79ecb7167c211ff36876ea611Jeff Garzik		hpriv->ops->read_preamp(hpriv, port, mmio);
219420f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ
2195c9d39130123238ac18478a42e25cb7996eacfcc0Jeff Garzik	rc = hpriv->ops->reset_hc(hpriv, mmio, n_hc);
219647c2b677daeed9c79ecb7167c211ff36876ea611Jeff Garzik	if (rc)
219720f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ		goto done;
219820f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ
2199522479fb98c6667f081e75f87e298e413c0b1db8Jeff Garzik	hpriv->ops->reset_flash(hpriv, mmio);
2200522479fb98c6667f081e75f87e298e413c0b1db8Jeff Garzik	hpriv->ops->reset_bus(pdev, mmio);
220147c2b677daeed9c79ecb7167c211ff36876ea611Jeff Garzik	hpriv->ops->enable_leds(hpriv, mmio);
220220f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ
220320f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ	for (port = 0; port < probe_ent->n_ports; port++) {
22042a47ce06d534692f9bd2bf4e90a20fc9b1054c39Jeff Garzik		if (IS_60XX(hpriv)) {
2205c9d39130123238ac18478a42e25cb7996eacfcc0Jeff Garzik			void __iomem *port_mmio = mv_port_base(mmio, port);
2206c9d39130123238ac18478a42e25cb7996eacfcc0Jeff Garzik
22072a47ce06d534692f9bd2bf4e90a20fc9b1054c39Jeff Garzik			u32 ifctl = readl(port_mmio + SATA_INTERFACE_CTL);
2208eb46d684600ac145501805a294c94675e82eab2eMark Lord			ifctl |= (1 << 7);		/* enable gen2i speed */
2209eb46d684600ac145501805a294c94675e82eab2eMark Lord			ifctl = (ifctl & 0xfff) | 0x9b1000; /* from chip spec */
22102a47ce06d534692f9bd2bf4e90a20fc9b1054c39Jeff Garzik			writelfl(ifctl, port_mmio + SATA_INTERFACE_CTL);
22112a47ce06d534692f9bd2bf4e90a20fc9b1054c39Jeff Garzik		}
22122a47ce06d534692f9bd2bf4e90a20fc9b1054c39Jeff Garzik
2213c9d39130123238ac18478a42e25cb7996eacfcc0Jeff Garzik		hpriv->ops->phy_errata(hpriv, mmio, port);
22142a47ce06d534692f9bd2bf4e90a20fc9b1054c39Jeff Garzik	}
22152a47ce06d534692f9bd2bf4e90a20fc9b1054c39Jeff Garzik
22162a47ce06d534692f9bd2bf4e90a20fc9b1054c39Jeff Garzik	for (port = 0; port < probe_ent->n_ports; port++) {
22172a47ce06d534692f9bd2bf4e90a20fc9b1054c39Jeff Garzik		void __iomem *port_mmio = mv_port_base(mmio, port);
221831961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ		mv_port_init(&probe_ent->port[port], port_mmio);
221920f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ	}
222020f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ
222120f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ	for (hc = 0; hc < n_hc; hc++) {
222231961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ		void __iomem *hc_mmio = mv_hc_base(mmio, hc);
222331961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ
222431961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ		VPRINTK("HC%i: HC config=0x%08x HC IRQ cause "
222531961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ			"(before clear)=0x%08x\n", hc,
222631961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ			readl(hc_mmio + HC_CFG_OFS),
222731961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ			readl(hc_mmio + HC_IRQ_CAUSE_OFS));
222831961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ
222931961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ		/* Clear any currently outstanding hc interrupt conditions */
223031961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ		writelfl(0, hc_mmio + HC_IRQ_CAUSE_OFS);
223120f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ	}
223220f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ
223331961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ	/* Clear any currently outstanding host interrupt conditions */
223431961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ	writelfl(0, mmio + PCI_IRQ_CAUSE_OFS);
223531961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ
223631961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ	/* and unmask interrupt generation for host regs */
223731961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ	writelfl(PCI_UNMASK_ALL_IRQS, mmio + PCI_IRQ_MASK_OFS);
223831961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ	writelfl(~HC_MAIN_MASKED_IRQS, mmio + HC_MAIN_IRQ_MASK_OFS);
223920f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ
224020f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ	VPRINTK("HC MAIN IRQ cause/mask=0x%08x/0x%08x "
22418b260248d9e0e8b64bb72fd4dee03ad86984c344Jeff Garzik		"PCI int cause/mask=0x%08x/0x%08x\n",
224220f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ		readl(mmio + HC_MAIN_IRQ_CAUSE_OFS),
224320f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ		readl(mmio + HC_MAIN_IRQ_MASK_OFS),
224420f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ		readl(mmio + PCI_IRQ_CAUSE_OFS),
224520f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ		readl(mmio + PCI_IRQ_MASK_OFS));
2246bca1c4eb9411533d613123618c0d127fae532595Jeff Garzik
224731961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russdone:
224820f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ	return rc;
224920f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ}
225020f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ
225105b308e1df6d9d673daedb517969241f41278b52Brett Russ/**
225205b308e1df6d9d673daedb517969241f41278b52Brett Russ *      mv_print_info - Dump key info to kernel log for perusal.
225305b308e1df6d9d673daedb517969241f41278b52Brett Russ *      @probe_ent: early data struct representing the host
225405b308e1df6d9d673daedb517969241f41278b52Brett Russ *
225505b308e1df6d9d673daedb517969241f41278b52Brett Russ *      FIXME: complete this.
225605b308e1df6d9d673daedb517969241f41278b52Brett Russ *
225705b308e1df6d9d673daedb517969241f41278b52Brett Russ *      LOCKING:
225805b308e1df6d9d673daedb517969241f41278b52Brett Russ *      Inherited from caller.
225905b308e1df6d9d673daedb517969241f41278b52Brett Russ */
226031961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russstatic void mv_print_info(struct ata_probe_ent *probe_ent)
226131961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ{
226231961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ	struct pci_dev *pdev = to_pci_dev(probe_ent->dev);
226331961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ	struct mv_host_priv *hpriv = probe_ent->private_data;
226431961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ	u8 rev_id, scc;
226531961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ	const char *scc_s;
226631961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ
226731961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ	/* Use this to determine the HW stepping of the chip so we know
226831961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ	 * what errata to workaround
226931961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ	 */
227031961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ	pci_read_config_byte(pdev, PCI_REVISION_ID, &rev_id);
227131961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ
227231961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ	pci_read_config_byte(pdev, PCI_CLASS_DEVICE, &scc);
227331961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ	if (scc == 0)
227431961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ		scc_s = "SCSI";
227531961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ	else if (scc == 0x01)
227631961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ		scc_s = "RAID";
227731961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ	else
227831961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ		scc_s = "unknown";
227931961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ
2280a9524a76f70f3343e4be27f95a7e92a8ba5f9009Jeff Garzik	dev_printk(KERN_INFO, &pdev->dev,
2281a9524a76f70f3343e4be27f95a7e92a8ba5f9009Jeff Garzik	       "%u slots %u ports %s mode IRQ via %s\n",
22828b260248d9e0e8b64bb72fd4dee03ad86984c344Jeff Garzik	       (unsigned)MV_MAX_Q_DEPTH, probe_ent->n_ports,
228331961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ	       scc_s, (MV_HP_FLAG_MSI & hpriv->hp_flags) ? "MSI" : "INTx");
228431961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ}
228531961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ
228605b308e1df6d9d673daedb517969241f41278b52Brett Russ/**
228705b308e1df6d9d673daedb517969241f41278b52Brett Russ *      mv_init_one - handle a positive probe of a Marvell host
228805b308e1df6d9d673daedb517969241f41278b52Brett Russ *      @pdev: PCI device found
228905b308e1df6d9d673daedb517969241f41278b52Brett Russ *      @ent: PCI device ID entry for the matched host
229005b308e1df6d9d673daedb517969241f41278b52Brett Russ *
229105b308e1df6d9d673daedb517969241f41278b52Brett Russ *      LOCKING:
229205b308e1df6d9d673daedb517969241f41278b52Brett Russ *      Inherited from caller.
229305b308e1df6d9d673daedb517969241f41278b52Brett Russ */
229420f733e7d75a16bffc34842b7682c9247dd5f954Brett Russstatic int mv_init_one(struct pci_dev *pdev, const struct pci_device_id *ent)
229520f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ{
229620f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ	static int printed_version = 0;
229724dc5f33ea4b504cfbd23fa159a4cacba8e4d800Tejun Heo	struct device *dev = &pdev->dev;
229824dc5f33ea4b504cfbd23fa159a4cacba8e4d800Tejun Heo	struct ata_probe_ent *probe_ent;
229920f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ	struct mv_host_priv *hpriv;
230020f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ	unsigned int board_idx = (unsigned int)ent->driver_data;
230124dc5f33ea4b504cfbd23fa159a4cacba8e4d800Tejun Heo	int rc;
230220f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ
2303a9524a76f70f3343e4be27f95a7e92a8ba5f9009Jeff Garzik	if (!printed_version++)
2304a9524a76f70f3343e4be27f95a7e92a8ba5f9009Jeff Garzik		dev_printk(KERN_INFO, &pdev->dev, "version " DRV_VERSION "\n");
230520f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ
230624dc5f33ea4b504cfbd23fa159a4cacba8e4d800Tejun Heo	rc = pcim_enable_device(pdev);
230724dc5f33ea4b504cfbd23fa159a4cacba8e4d800Tejun Heo	if (rc)
230820f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ		return rc;
2309eb46d684600ac145501805a294c94675e82eab2eMark Lord	pci_set_master(pdev);
231020f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ
23110d5ff566779f894ca9937231a181eb31e4adff0eTejun Heo	rc = pcim_iomap_regions(pdev, 1 << MV_PRIMARY_BAR, DRV_NAME);
23120d5ff566779f894ca9937231a181eb31e4adff0eTejun Heo	if (rc == -EBUSY)
231324dc5f33ea4b504cfbd23fa159a4cacba8e4d800Tejun Heo		pcim_pin_device(pdev);
23140d5ff566779f894ca9937231a181eb31e4adff0eTejun Heo	if (rc)
231524dc5f33ea4b504cfbd23fa159a4cacba8e4d800Tejun Heo		return rc;
231620f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ
231724dc5f33ea4b504cfbd23fa159a4cacba8e4d800Tejun Heo	probe_ent = devm_kzalloc(dev, sizeof(*probe_ent), GFP_KERNEL);
231824dc5f33ea4b504cfbd23fa159a4cacba8e4d800Tejun Heo	if (probe_ent == NULL)
231924dc5f33ea4b504cfbd23fa159a4cacba8e4d800Tejun Heo		return -ENOMEM;
232020f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ
232120f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ	probe_ent->dev = pci_dev_to_dev(pdev);
232220f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ	INIT_LIST_HEAD(&probe_ent->node);
232320f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ
232424dc5f33ea4b504cfbd23fa159a4cacba8e4d800Tejun Heo	hpriv = devm_kzalloc(dev, sizeof(*hpriv), GFP_KERNEL);
232524dc5f33ea4b504cfbd23fa159a4cacba8e4d800Tejun Heo	if (!hpriv)
232624dc5f33ea4b504cfbd23fa159a4cacba8e4d800Tejun Heo		return -ENOMEM;
232720f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ
232820f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ	probe_ent->sht = mv_port_info[board_idx].sht;
2329cca3974e48607c3775dc73b544a5700b2e37c21aJeff Garzik	probe_ent->port_flags = mv_port_info[board_idx].flags;
233020f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ	probe_ent->pio_mask = mv_port_info[board_idx].pio_mask;
233120f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ	probe_ent->udma_mask = mv_port_info[board_idx].udma_mask;
233220f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ	probe_ent->port_ops = mv_port_info[board_idx].port_ops;
233320f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ
233420f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ	probe_ent->irq = pdev->irq;
23351d6f359a2e06296418481239f8054a878f36e819Thomas Gleixner	probe_ent->irq_flags = IRQF_SHARED;
23360d5ff566779f894ca9937231a181eb31e4adff0eTejun Heo	probe_ent->iomap = pcim_iomap_table(pdev);
233720f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ	probe_ent->private_data = hpriv;
233820f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ
233920f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ	/* initialize adapter */
234047c2b677daeed9c79ecb7167c211ff36876ea611Jeff Garzik	rc = mv_init_host(pdev, probe_ent, board_idx);
234124dc5f33ea4b504cfbd23fa159a4cacba8e4d800Tejun Heo	if (rc)
234224dc5f33ea4b504cfbd23fa159a4cacba8e4d800Tejun Heo		return rc;
234320f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ
234431961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ	/* Enable interrupts */
234524dc5f33ea4b504cfbd23fa159a4cacba8e4d800Tejun Heo	if (msi && !pci_enable_msi(pdev))
234631961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ		pci_intx(pdev, 1);
234720f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ
234831961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ	mv_dump_pci_cfg(pdev, 0x68);
234931961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ	mv_print_info(probe_ent);
235031961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ
235124dc5f33ea4b504cfbd23fa159a4cacba8e4d800Tejun Heo	if (ata_device_add(probe_ent) == 0)
235224dc5f33ea4b504cfbd23fa159a4cacba8e4d800Tejun Heo		return -ENODEV;
235320f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ
235424dc5f33ea4b504cfbd23fa159a4cacba8e4d800Tejun Heo	devm_kfree(dev, probe_ent);
235520f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ	return 0;
235620f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ}
235720f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ
235820f733e7d75a16bffc34842b7682c9247dd5f954Brett Russstatic int __init mv_init(void)
235920f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ{
2360b7887196e38da54ff893897b80875d632d1a1114Pavel Roskin	return pci_register_driver(&mv_pci_driver);
236120f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ}
236220f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ
236320f733e7d75a16bffc34842b7682c9247dd5f954Brett Russstatic void __exit mv_exit(void)
236420f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ{
236520f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ	pci_unregister_driver(&mv_pci_driver);
236620f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ}
236720f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ
236820f733e7d75a16bffc34842b7682c9247dd5f954Brett RussMODULE_AUTHOR("Brett Russ");
236920f733e7d75a16bffc34842b7682c9247dd5f954Brett RussMODULE_DESCRIPTION("SCSI low-level driver for Marvell SATA controllers");
237020f733e7d75a16bffc34842b7682c9247dd5f954Brett RussMODULE_LICENSE("GPL");
237120f733e7d75a16bffc34842b7682c9247dd5f954Brett RussMODULE_DEVICE_TABLE(pci, mv_pci_tbl);
237220f733e7d75a16bffc34842b7682c9247dd5f954Brett RussMODULE_VERSION(DRV_VERSION);
237320f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ
2374ddef9bb367b19383df627e388cb4c01c86ddba6cJeff Garzikmodule_param(msi, int, 0444);
2375ddef9bb367b19383df627e388cb4c01c86ddba6cJeff GarzikMODULE_PARM_DESC(msi, "Enable use of PCI MSI (0=off, 1=on)");
2376ddef9bb367b19383df627e388cb4c01c86ddba6cJeff Garzik
237720f733e7d75a16bffc34842b7682c9247dd5f954Brett Russmodule_init(mv_init);
237820f733e7d75a16bffc34842b7682c9247dd5f954Brett Russmodule_exit(mv_exit);
2379