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