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