1c6fd2807SJeff Garzik /* 2c6fd2807SJeff Garzik * sata_mv.c - Marvell SATA support 3c6fd2807SJeff Garzik * 4c6fd2807SJeff Garzik * Copyright 2005: EMC Corporation, all rights reserved. 5c6fd2807SJeff Garzik * Copyright 2005 Red Hat, Inc. All rights reserved. 6c6fd2807SJeff Garzik * 7c6fd2807SJeff Garzik * Please ALWAYS copy linux-ide@vger.kernel.org on emails. 8c6fd2807SJeff Garzik * 9c6fd2807SJeff Garzik * This program is free software; you can redistribute it and/or modify 10c6fd2807SJeff Garzik * it under the terms of the GNU General Public License as published by 11c6fd2807SJeff Garzik * the Free Software Foundation; version 2 of the License. 12c6fd2807SJeff Garzik * 13c6fd2807SJeff Garzik * This program is distributed in the hope that it will be useful, 14c6fd2807SJeff Garzik * but WITHOUT ANY WARRANTY; without even the implied warranty of 15c6fd2807SJeff Garzik * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 16c6fd2807SJeff Garzik * GNU General Public License for more details. 17c6fd2807SJeff Garzik * 18c6fd2807SJeff Garzik * You should have received a copy of the GNU General Public License 19c6fd2807SJeff Garzik * along with this program; if not, write to the Free Software 20c6fd2807SJeff Garzik * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA 21c6fd2807SJeff Garzik * 22c6fd2807SJeff Garzik */ 23c6fd2807SJeff Garzik 244a05e209SJeff Garzik /* 254a05e209SJeff Garzik sata_mv TODO list: 264a05e209SJeff Garzik 274a05e209SJeff Garzik 1) Needs a full errata audit for all chipsets. I implemented most 284a05e209SJeff Garzik of the errata workarounds found in the Marvell vendor driver, but 294a05e209SJeff Garzik I distinctly remember a couple workarounds (one related to PCI-X) 304a05e209SJeff Garzik are still needed. 314a05e209SJeff Garzik 324a05e209SJeff Garzik 2) Convert to LibATA new EH. Required for hotplug, NCQ, and sane 334a05e209SJeff Garzik probing/error handling in general. MUST HAVE. 344a05e209SJeff Garzik 354a05e209SJeff Garzik 3) Add hotplug support (easy, once new-EH support appears) 364a05e209SJeff Garzik 374a05e209SJeff Garzik 4) Add NCQ support (easy to intermediate, once new-EH support appears) 384a05e209SJeff Garzik 394a05e209SJeff Garzik 5) Investigate problems with PCI Message Signalled Interrupts (MSI). 404a05e209SJeff Garzik 414a05e209SJeff Garzik 6) Add port multiplier support (intermediate) 424a05e209SJeff Garzik 434a05e209SJeff Garzik 7) Test and verify 3.0 Gbps support 444a05e209SJeff Garzik 454a05e209SJeff Garzik 8) Develop a low-power-consumption strategy, and implement it. 464a05e209SJeff Garzik 474a05e209SJeff Garzik 9) [Experiment, low priority] See if ATAPI can be supported using 484a05e209SJeff Garzik "unknown FIS" or "vendor-specific FIS" support, or something creative 494a05e209SJeff Garzik like that. 504a05e209SJeff Garzik 514a05e209SJeff Garzik 10) [Experiment, low priority] Investigate interrupt coalescing. 524a05e209SJeff Garzik Quite often, especially with PCI Message Signalled Interrupts (MSI), 534a05e209SJeff Garzik the overhead reduced by interrupt mitigation is quite often not 544a05e209SJeff Garzik worth the latency cost. 554a05e209SJeff Garzik 564a05e209SJeff Garzik 11) [Experiment, Marvell value added] Is it possible to use target 574a05e209SJeff Garzik mode to cross-connect two Linux boxes with Marvell cards? If so, 584a05e209SJeff Garzik creating LibATA target mode support would be very interesting. 594a05e209SJeff Garzik 604a05e209SJeff Garzik Target mode, for those without docs, is the ability to directly 614a05e209SJeff Garzik connect two SATA controllers. 624a05e209SJeff Garzik 634a05e209SJeff Garzik 13) Verify that 7042 is fully supported. I only have a 6042. 644a05e209SJeff Garzik 654a05e209SJeff Garzik */ 664a05e209SJeff Garzik 674a05e209SJeff Garzik 68c6fd2807SJeff Garzik #include <linux/kernel.h> 69c6fd2807SJeff Garzik #include <linux/module.h> 70c6fd2807SJeff Garzik #include <linux/pci.h> 71c6fd2807SJeff Garzik #include <linux/init.h> 72c6fd2807SJeff Garzik #include <linux/blkdev.h> 73c6fd2807SJeff Garzik #include <linux/delay.h> 74c6fd2807SJeff Garzik #include <linux/interrupt.h> 75c6fd2807SJeff Garzik #include <linux/dma-mapping.h> 76c6fd2807SJeff Garzik #include <linux/device.h> 77c6fd2807SJeff Garzik #include <scsi/scsi_host.h> 78c6fd2807SJeff Garzik #include <scsi/scsi_cmnd.h> 79c6fd2807SJeff Garzik #include <linux/libata.h> 80c6fd2807SJeff Garzik 81c6fd2807SJeff Garzik #define DRV_NAME "sata_mv" 828bc3fc47SJeff Garzik #define DRV_VERSION "0.81" 83c6fd2807SJeff Garzik 84c6fd2807SJeff Garzik enum { 85c6fd2807SJeff Garzik /* BAR's are enumerated in terms of pci_resource_start() terms */ 86c6fd2807SJeff Garzik MV_PRIMARY_BAR = 0, /* offset 0x10: memory space */ 87c6fd2807SJeff Garzik MV_IO_BAR = 2, /* offset 0x18: IO space */ 88c6fd2807SJeff Garzik MV_MISC_BAR = 3, /* offset 0x1c: FLASH, NVRAM, SRAM */ 89c6fd2807SJeff Garzik 90c6fd2807SJeff Garzik MV_MAJOR_REG_AREA_SZ = 0x10000, /* 64KB */ 91c6fd2807SJeff Garzik MV_MINOR_REG_AREA_SZ = 0x2000, /* 8KB */ 92c6fd2807SJeff Garzik 93c6fd2807SJeff Garzik MV_PCI_REG_BASE = 0, 94c6fd2807SJeff Garzik MV_IRQ_COAL_REG_BASE = 0x18000, /* 6xxx part only */ 95c6fd2807SJeff Garzik MV_IRQ_COAL_CAUSE = (MV_IRQ_COAL_REG_BASE + 0x08), 96c6fd2807SJeff Garzik MV_IRQ_COAL_CAUSE_LO = (MV_IRQ_COAL_REG_BASE + 0x88), 97c6fd2807SJeff Garzik MV_IRQ_COAL_CAUSE_HI = (MV_IRQ_COAL_REG_BASE + 0x8c), 98c6fd2807SJeff Garzik MV_IRQ_COAL_THRESHOLD = (MV_IRQ_COAL_REG_BASE + 0xcc), 99c6fd2807SJeff Garzik MV_IRQ_COAL_TIME_THRESHOLD = (MV_IRQ_COAL_REG_BASE + 0xd0), 100c6fd2807SJeff Garzik 101c6fd2807SJeff Garzik MV_SATAHC0_REG_BASE = 0x20000, 102c6fd2807SJeff Garzik MV_FLASH_CTL = 0x1046c, 103c6fd2807SJeff Garzik MV_GPIO_PORT_CTL = 0x104f0, 104c6fd2807SJeff Garzik MV_RESET_CFG = 0x180d8, 105c6fd2807SJeff Garzik 106c6fd2807SJeff Garzik MV_PCI_REG_SZ = MV_MAJOR_REG_AREA_SZ, 107c6fd2807SJeff Garzik MV_SATAHC_REG_SZ = MV_MAJOR_REG_AREA_SZ, 108c6fd2807SJeff Garzik MV_SATAHC_ARBTR_REG_SZ = MV_MINOR_REG_AREA_SZ, /* arbiter */ 109c6fd2807SJeff Garzik MV_PORT_REG_SZ = MV_MINOR_REG_AREA_SZ, 110c6fd2807SJeff Garzik 111c6fd2807SJeff Garzik MV_MAX_Q_DEPTH = 32, 112c6fd2807SJeff Garzik MV_MAX_Q_DEPTH_MASK = MV_MAX_Q_DEPTH - 1, 113c6fd2807SJeff Garzik 114c6fd2807SJeff Garzik /* CRQB needs alignment on a 1KB boundary. Size == 1KB 115c6fd2807SJeff Garzik * CRPB needs alignment on a 256B boundary. Size == 256B 116c6fd2807SJeff Garzik * SG count of 176 leads to MV_PORT_PRIV_DMA_SZ == 4KB 117c6fd2807SJeff Garzik * ePRD (SG) entries need alignment on a 16B boundary. Size == 16B 118c6fd2807SJeff Garzik */ 119c6fd2807SJeff Garzik MV_CRQB_Q_SZ = (32 * MV_MAX_Q_DEPTH), 120c6fd2807SJeff Garzik MV_CRPB_Q_SZ = (8 * MV_MAX_Q_DEPTH), 121c6fd2807SJeff Garzik MV_MAX_SG_CT = 176, 122c6fd2807SJeff Garzik MV_SG_TBL_SZ = (16 * MV_MAX_SG_CT), 123c6fd2807SJeff Garzik MV_PORT_PRIV_DMA_SZ = (MV_CRQB_Q_SZ + MV_CRPB_Q_SZ + MV_SG_TBL_SZ), 124c6fd2807SJeff Garzik 125c6fd2807SJeff Garzik MV_PORTS_PER_HC = 4, 126c6fd2807SJeff Garzik /* == (port / MV_PORTS_PER_HC) to determine HC from 0-7 port */ 127c6fd2807SJeff Garzik MV_PORT_HC_SHIFT = 2, 128c6fd2807SJeff Garzik /* == (port % MV_PORTS_PER_HC) to determine hard port from 0-7 port */ 129c6fd2807SJeff Garzik MV_PORT_MASK = 3, 130c6fd2807SJeff Garzik 131c6fd2807SJeff Garzik /* Host Flags */ 132c6fd2807SJeff Garzik MV_FLAG_DUAL_HC = (1 << 30), /* two SATA Host Controllers */ 133c6fd2807SJeff Garzik MV_FLAG_IRQ_COALESCE = (1 << 29), /* IRQ coalescing capability */ 134*c5d3e45aSJeff Garzik MV_COMMON_FLAGS = ATA_FLAG_SATA | ATA_FLAG_NO_LEGACY | 135c6fd2807SJeff Garzik ATA_FLAG_SATA_RESET | ATA_FLAG_MMIO | 136*c5d3e45aSJeff Garzik ATA_FLAG_NO_ATAPI | ATA_FLAG_PIO_POLLING, 137c6fd2807SJeff Garzik MV_6XXX_FLAGS = MV_FLAG_IRQ_COALESCE, 138c6fd2807SJeff Garzik 139c6fd2807SJeff Garzik CRQB_FLAG_READ = (1 << 0), 140c6fd2807SJeff Garzik CRQB_TAG_SHIFT = 1, 141*c5d3e45aSJeff Garzik CRQB_IOID_SHIFT = 6, /* CRQB Gen-II/IIE IO Id shift */ 142*c5d3e45aSJeff Garzik CRQB_HOSTQ_SHIFT = 17, /* CRQB Gen-II/IIE HostQueTag shift */ 143c6fd2807SJeff Garzik CRQB_CMD_ADDR_SHIFT = 8, 144c6fd2807SJeff Garzik CRQB_CMD_CS = (0x2 << 11), 145c6fd2807SJeff Garzik CRQB_CMD_LAST = (1 << 15), 146c6fd2807SJeff Garzik 147c6fd2807SJeff Garzik CRPB_FLAG_STATUS_SHIFT = 8, 148*c5d3e45aSJeff Garzik CRPB_IOID_SHIFT_6 = 5, /* CRPB Gen-II IO Id shift */ 149*c5d3e45aSJeff Garzik CRPB_IOID_SHIFT_7 = 7, /* CRPB Gen-IIE IO Id shift */ 150c6fd2807SJeff Garzik 151c6fd2807SJeff Garzik EPRD_FLAG_END_OF_TBL = (1 << 31), 152c6fd2807SJeff Garzik 153c6fd2807SJeff Garzik /* PCI interface registers */ 154c6fd2807SJeff Garzik 155c6fd2807SJeff Garzik PCI_COMMAND_OFS = 0xc00, 156c6fd2807SJeff Garzik 157c6fd2807SJeff Garzik PCI_MAIN_CMD_STS_OFS = 0xd30, 158c6fd2807SJeff Garzik STOP_PCI_MASTER = (1 << 2), 159c6fd2807SJeff Garzik PCI_MASTER_EMPTY = (1 << 3), 160c6fd2807SJeff Garzik GLOB_SFT_RST = (1 << 4), 161c6fd2807SJeff Garzik 162c6fd2807SJeff Garzik MV_PCI_MODE = 0xd00, 163c6fd2807SJeff Garzik MV_PCI_EXP_ROM_BAR_CTL = 0xd2c, 164c6fd2807SJeff Garzik MV_PCI_DISC_TIMER = 0xd04, 165c6fd2807SJeff Garzik MV_PCI_MSI_TRIGGER = 0xc38, 166c6fd2807SJeff Garzik MV_PCI_SERR_MASK = 0xc28, 167c6fd2807SJeff Garzik MV_PCI_XBAR_TMOUT = 0x1d04, 168c6fd2807SJeff Garzik MV_PCI_ERR_LOW_ADDRESS = 0x1d40, 169c6fd2807SJeff Garzik MV_PCI_ERR_HIGH_ADDRESS = 0x1d44, 170c6fd2807SJeff Garzik MV_PCI_ERR_ATTRIBUTE = 0x1d48, 171c6fd2807SJeff Garzik MV_PCI_ERR_COMMAND = 0x1d50, 172c6fd2807SJeff Garzik 173c6fd2807SJeff Garzik PCI_IRQ_CAUSE_OFS = 0x1d58, 174c6fd2807SJeff Garzik PCI_IRQ_MASK_OFS = 0x1d5c, 175c6fd2807SJeff Garzik PCI_UNMASK_ALL_IRQS = 0x7fffff, /* bits 22-0 */ 176c6fd2807SJeff Garzik 177c6fd2807SJeff Garzik HC_MAIN_IRQ_CAUSE_OFS = 0x1d60, 178c6fd2807SJeff Garzik HC_MAIN_IRQ_MASK_OFS = 0x1d64, 179c6fd2807SJeff Garzik PORT0_ERR = (1 << 0), /* shift by port # */ 180c6fd2807SJeff Garzik PORT0_DONE = (1 << 1), /* shift by port # */ 181c6fd2807SJeff Garzik HC0_IRQ_PEND = 0x1ff, /* bits 0-8 = HC0's ports */ 182c6fd2807SJeff Garzik HC_SHIFT = 9, /* bits 9-17 = HC1's ports */ 183c6fd2807SJeff Garzik PCI_ERR = (1 << 18), 184c6fd2807SJeff Garzik TRAN_LO_DONE = (1 << 19), /* 6xxx: IRQ coalescing */ 185c6fd2807SJeff Garzik TRAN_HI_DONE = (1 << 20), /* 6xxx: IRQ coalescing */ 186fb621e2fSJeff Garzik PORTS_0_3_COAL_DONE = (1 << 8), 187fb621e2fSJeff Garzik PORTS_4_7_COAL_DONE = (1 << 17), 188c6fd2807SJeff Garzik PORTS_0_7_COAL_DONE = (1 << 21), /* 6xxx: IRQ coalescing */ 189c6fd2807SJeff Garzik GPIO_INT = (1 << 22), 190c6fd2807SJeff Garzik SELF_INT = (1 << 23), 191c6fd2807SJeff Garzik TWSI_INT = (1 << 24), 192c6fd2807SJeff Garzik HC_MAIN_RSVD = (0x7f << 25), /* bits 31-25 */ 193fb621e2fSJeff Garzik HC_MAIN_RSVD_5 = (0x1fff << 19), /* bits 31-19 */ 194c6fd2807SJeff Garzik HC_MAIN_MASKED_IRQS = (TRAN_LO_DONE | TRAN_HI_DONE | 195c6fd2807SJeff Garzik PORTS_0_7_COAL_DONE | GPIO_INT | TWSI_INT | 196c6fd2807SJeff Garzik HC_MAIN_RSVD), 197fb621e2fSJeff Garzik HC_MAIN_MASKED_IRQS_5 = (PORTS_0_3_COAL_DONE | PORTS_4_7_COAL_DONE | 198fb621e2fSJeff Garzik HC_MAIN_RSVD_5), 199c6fd2807SJeff Garzik 200c6fd2807SJeff Garzik /* SATAHC registers */ 201c6fd2807SJeff Garzik HC_CFG_OFS = 0, 202c6fd2807SJeff Garzik 203c6fd2807SJeff Garzik HC_IRQ_CAUSE_OFS = 0x14, 204c6fd2807SJeff Garzik CRPB_DMA_DONE = (1 << 0), /* shift by port # */ 205c6fd2807SJeff Garzik HC_IRQ_COAL = (1 << 4), /* IRQ coalescing */ 206c6fd2807SJeff Garzik DEV_IRQ = (1 << 8), /* shift by port # */ 207c6fd2807SJeff Garzik 208c6fd2807SJeff Garzik /* Shadow block registers */ 209c6fd2807SJeff Garzik SHD_BLK_OFS = 0x100, 210c6fd2807SJeff Garzik SHD_CTL_AST_OFS = 0x20, /* ofs from SHD_BLK_OFS */ 211c6fd2807SJeff Garzik 212c6fd2807SJeff Garzik /* SATA registers */ 213c6fd2807SJeff Garzik SATA_STATUS_OFS = 0x300, /* ctrl, err regs follow status */ 214c6fd2807SJeff Garzik SATA_ACTIVE_OFS = 0x350, 215c6fd2807SJeff Garzik PHY_MODE3 = 0x310, 216c6fd2807SJeff Garzik PHY_MODE4 = 0x314, 217c6fd2807SJeff Garzik PHY_MODE2 = 0x330, 218c6fd2807SJeff Garzik MV5_PHY_MODE = 0x74, 219c6fd2807SJeff Garzik MV5_LT_MODE = 0x30, 220c6fd2807SJeff Garzik MV5_PHY_CTL = 0x0C, 221c6fd2807SJeff Garzik SATA_INTERFACE_CTL = 0x050, 222c6fd2807SJeff Garzik 223c6fd2807SJeff Garzik MV_M2_PREAMP_MASK = 0x7e0, 224c6fd2807SJeff Garzik 225c6fd2807SJeff Garzik /* Port registers */ 226c6fd2807SJeff Garzik EDMA_CFG_OFS = 0, 227c6fd2807SJeff Garzik EDMA_CFG_Q_DEPTH = 0, /* queueing disabled */ 228c6fd2807SJeff Garzik EDMA_CFG_NCQ = (1 << 5), 229c6fd2807SJeff Garzik EDMA_CFG_NCQ_GO_ON_ERR = (1 << 14), /* continue on error */ 230c6fd2807SJeff Garzik EDMA_CFG_RD_BRST_EXT = (1 << 11), /* read burst 512B */ 231c6fd2807SJeff Garzik EDMA_CFG_WR_BUFF_LEN = (1 << 13), /* write buffer 512B */ 232c6fd2807SJeff Garzik 233c6fd2807SJeff Garzik EDMA_ERR_IRQ_CAUSE_OFS = 0x8, 234c6fd2807SJeff Garzik EDMA_ERR_IRQ_MASK_OFS = 0xc, 235c6fd2807SJeff Garzik EDMA_ERR_D_PAR = (1 << 0), 236c6fd2807SJeff Garzik EDMA_ERR_PRD_PAR = (1 << 1), 237c6fd2807SJeff Garzik EDMA_ERR_DEV = (1 << 2), 238c6fd2807SJeff Garzik EDMA_ERR_DEV_DCON = (1 << 3), 239c6fd2807SJeff Garzik EDMA_ERR_DEV_CON = (1 << 4), 240c6fd2807SJeff Garzik EDMA_ERR_SERR = (1 << 5), 241*c5d3e45aSJeff Garzik EDMA_ERR_SELF_DIS = (1 << 7), /* Gen II/IIE self-disable */ 242*c5d3e45aSJeff Garzik EDMA_ERR_SELF_DIS_5 = (1 << 8), /* Gen I self-disable */ 243c6fd2807SJeff Garzik EDMA_ERR_BIST_ASYNC = (1 << 8), 244*c5d3e45aSJeff Garzik EDMA_ERR_TRANS_IRQ_7 = (1 << 8), /* Gen IIE transprt layer irq */ 245c6fd2807SJeff Garzik EDMA_ERR_CRBQ_PAR = (1 << 9), 246c6fd2807SJeff Garzik EDMA_ERR_CRPB_PAR = (1 << 10), 247c6fd2807SJeff Garzik EDMA_ERR_INTRL_PAR = (1 << 11), 248c6fd2807SJeff Garzik EDMA_ERR_IORDY = (1 << 12), 249c6fd2807SJeff Garzik EDMA_ERR_LNK_CTRL_RX = (0xf << 13), 250c6fd2807SJeff Garzik EDMA_ERR_LNK_CTRL_RX_2 = (1 << 15), 251c6fd2807SJeff Garzik EDMA_ERR_LNK_DATA_RX = (0xf << 17), 252c6fd2807SJeff Garzik EDMA_ERR_LNK_CTRL_TX = (0x1f << 21), 253c6fd2807SJeff Garzik EDMA_ERR_LNK_DATA_TX = (0x1f << 26), 254c6fd2807SJeff Garzik EDMA_ERR_TRANS_PROTO = (1 << 31), 255*c5d3e45aSJeff Garzik EDMA_ERR_OVERRUN_5 = (1 << 5), 256*c5d3e45aSJeff Garzik EDMA_ERR_UNDERRUN_5 = (1 << 6), 257c6fd2807SJeff Garzik EDMA_ERR_FATAL = (EDMA_ERR_D_PAR | EDMA_ERR_PRD_PAR | 258c6fd2807SJeff Garzik EDMA_ERR_DEV_DCON | EDMA_ERR_CRBQ_PAR | 259c6fd2807SJeff Garzik EDMA_ERR_CRPB_PAR | EDMA_ERR_INTRL_PAR | 260c6fd2807SJeff Garzik EDMA_ERR_IORDY | EDMA_ERR_LNK_CTRL_RX_2 | 261c6fd2807SJeff Garzik EDMA_ERR_LNK_DATA_RX | 262c6fd2807SJeff Garzik EDMA_ERR_LNK_DATA_TX | 263c6fd2807SJeff Garzik EDMA_ERR_TRANS_PROTO), 264c6fd2807SJeff Garzik 265c6fd2807SJeff Garzik EDMA_REQ_Q_BASE_HI_OFS = 0x10, 266c6fd2807SJeff Garzik EDMA_REQ_Q_IN_PTR_OFS = 0x14, /* also contains BASE_LO */ 267c6fd2807SJeff Garzik 268c6fd2807SJeff Garzik EDMA_REQ_Q_OUT_PTR_OFS = 0x18, 269c6fd2807SJeff Garzik EDMA_REQ_Q_PTR_SHIFT = 5, 270c6fd2807SJeff Garzik 271c6fd2807SJeff Garzik EDMA_RSP_Q_BASE_HI_OFS = 0x1c, 272c6fd2807SJeff Garzik EDMA_RSP_Q_IN_PTR_OFS = 0x20, 273c6fd2807SJeff Garzik EDMA_RSP_Q_OUT_PTR_OFS = 0x24, /* also contains BASE_LO */ 274c6fd2807SJeff Garzik EDMA_RSP_Q_PTR_SHIFT = 3, 275c6fd2807SJeff Garzik 276c6fd2807SJeff Garzik EDMA_CMD_OFS = 0x28, 277c6fd2807SJeff Garzik EDMA_EN = (1 << 0), 278c6fd2807SJeff Garzik EDMA_DS = (1 << 1), 279c6fd2807SJeff Garzik ATA_RST = (1 << 2), 280c6fd2807SJeff Garzik 281c6fd2807SJeff Garzik EDMA_IORDY_TMOUT = 0x34, 282c6fd2807SJeff Garzik EDMA_ARB_CFG = 0x38, 283c6fd2807SJeff Garzik 284c6fd2807SJeff Garzik /* Host private flags (hp_flags) */ 285c6fd2807SJeff Garzik MV_HP_FLAG_MSI = (1 << 0), 286c6fd2807SJeff Garzik MV_HP_ERRATA_50XXB0 = (1 << 1), 287c6fd2807SJeff Garzik MV_HP_ERRATA_50XXB2 = (1 << 2), 288c6fd2807SJeff Garzik MV_HP_ERRATA_60X1B2 = (1 << 3), 289c6fd2807SJeff Garzik MV_HP_ERRATA_60X1C0 = (1 << 4), 290c6fd2807SJeff Garzik MV_HP_ERRATA_XX42A0 = (1 << 5), 291c6fd2807SJeff Garzik MV_HP_50XX = (1 << 6), 292c6fd2807SJeff Garzik MV_HP_GEN_IIE = (1 << 7), 293c6fd2807SJeff Garzik 294c6fd2807SJeff Garzik /* Port private flags (pp_flags) */ 295c6fd2807SJeff Garzik MV_PP_FLAG_EDMA_EN = (1 << 0), 296c6fd2807SJeff Garzik MV_PP_FLAG_EDMA_DS_ACT = (1 << 1), 297*c5d3e45aSJeff Garzik MV_PP_FLAG_HAD_A_RESET = (1 << 2), 298c6fd2807SJeff Garzik }; 299c6fd2807SJeff Garzik 300c6fd2807SJeff Garzik #define IS_50XX(hpriv) ((hpriv)->hp_flags & MV_HP_50XX) 301c6fd2807SJeff Garzik #define IS_60XX(hpriv) (((hpriv)->hp_flags & MV_HP_50XX) == 0) 302c6fd2807SJeff Garzik #define IS_GEN_I(hpriv) IS_50XX(hpriv) 303c6fd2807SJeff Garzik #define IS_GEN_II(hpriv) IS_60XX(hpriv) 304c6fd2807SJeff Garzik #define IS_GEN_IIE(hpriv) ((hpriv)->hp_flags & MV_HP_GEN_IIE) 305c6fd2807SJeff Garzik 306c6fd2807SJeff Garzik enum { 307d88184fbSJeff Garzik MV_DMA_BOUNDARY = 0xffffffffU, 308c6fd2807SJeff Garzik 309c6fd2807SJeff Garzik EDMA_REQ_Q_BASE_LO_MASK = 0xfffffc00U, 310c6fd2807SJeff Garzik 311c6fd2807SJeff Garzik EDMA_RSP_Q_BASE_LO_MASK = 0xffffff00U, 312c6fd2807SJeff Garzik }; 313c6fd2807SJeff Garzik 314c6fd2807SJeff Garzik enum chip_type { 315c6fd2807SJeff Garzik chip_504x, 316c6fd2807SJeff Garzik chip_508x, 317c6fd2807SJeff Garzik chip_5080, 318c6fd2807SJeff Garzik chip_604x, 319c6fd2807SJeff Garzik chip_608x, 320c6fd2807SJeff Garzik chip_6042, 321c6fd2807SJeff Garzik chip_7042, 322c6fd2807SJeff Garzik }; 323c6fd2807SJeff Garzik 324c6fd2807SJeff Garzik /* Command ReQuest Block: 32B */ 325c6fd2807SJeff Garzik struct mv_crqb { 326c6fd2807SJeff Garzik __le32 sg_addr; 327c6fd2807SJeff Garzik __le32 sg_addr_hi; 328c6fd2807SJeff Garzik __le16 ctrl_flags; 329c6fd2807SJeff Garzik __le16 ata_cmd[11]; 330c6fd2807SJeff Garzik }; 331c6fd2807SJeff Garzik 332c6fd2807SJeff Garzik struct mv_crqb_iie { 333c6fd2807SJeff Garzik __le32 addr; 334c6fd2807SJeff Garzik __le32 addr_hi; 335c6fd2807SJeff Garzik __le32 flags; 336c6fd2807SJeff Garzik __le32 len; 337c6fd2807SJeff Garzik __le32 ata_cmd[4]; 338c6fd2807SJeff Garzik }; 339c6fd2807SJeff Garzik 340c6fd2807SJeff Garzik /* Command ResPonse Block: 8B */ 341c6fd2807SJeff Garzik struct mv_crpb { 342c6fd2807SJeff Garzik __le16 id; 343c6fd2807SJeff Garzik __le16 flags; 344c6fd2807SJeff Garzik __le32 tmstmp; 345c6fd2807SJeff Garzik }; 346c6fd2807SJeff Garzik 347c6fd2807SJeff Garzik /* EDMA Physical Region Descriptor (ePRD); A.K.A. SG */ 348c6fd2807SJeff Garzik struct mv_sg { 349c6fd2807SJeff Garzik __le32 addr; 350c6fd2807SJeff Garzik __le32 flags_size; 351c6fd2807SJeff Garzik __le32 addr_hi; 352c6fd2807SJeff Garzik __le32 reserved; 353c6fd2807SJeff Garzik }; 354c6fd2807SJeff Garzik 355c6fd2807SJeff Garzik struct mv_port_priv { 356c6fd2807SJeff Garzik struct mv_crqb *crqb; 357c6fd2807SJeff Garzik dma_addr_t crqb_dma; 358c6fd2807SJeff Garzik struct mv_crpb *crpb; 359c6fd2807SJeff Garzik dma_addr_t crpb_dma; 360c6fd2807SJeff Garzik struct mv_sg *sg_tbl; 361c6fd2807SJeff Garzik dma_addr_t sg_tbl_dma; 362c6fd2807SJeff Garzik u32 pp_flags; 363c6fd2807SJeff Garzik }; 364c6fd2807SJeff Garzik 365c6fd2807SJeff Garzik struct mv_port_signal { 366c6fd2807SJeff Garzik u32 amps; 367c6fd2807SJeff Garzik u32 pre; 368c6fd2807SJeff Garzik }; 369c6fd2807SJeff Garzik 370c6fd2807SJeff Garzik struct mv_host_priv; 371c6fd2807SJeff Garzik struct mv_hw_ops { 372c6fd2807SJeff Garzik void (*phy_errata)(struct mv_host_priv *hpriv, void __iomem *mmio, 373c6fd2807SJeff Garzik unsigned int port); 374c6fd2807SJeff Garzik void (*enable_leds)(struct mv_host_priv *hpriv, void __iomem *mmio); 375c6fd2807SJeff Garzik void (*read_preamp)(struct mv_host_priv *hpriv, int idx, 376c6fd2807SJeff Garzik void __iomem *mmio); 377c6fd2807SJeff Garzik int (*reset_hc)(struct mv_host_priv *hpriv, void __iomem *mmio, 378c6fd2807SJeff Garzik unsigned int n_hc); 379c6fd2807SJeff Garzik void (*reset_flash)(struct mv_host_priv *hpriv, void __iomem *mmio); 380c6fd2807SJeff Garzik void (*reset_bus)(struct pci_dev *pdev, void __iomem *mmio); 381c6fd2807SJeff Garzik }; 382c6fd2807SJeff Garzik 383c6fd2807SJeff Garzik struct mv_host_priv { 384c6fd2807SJeff Garzik u32 hp_flags; 385c6fd2807SJeff Garzik struct mv_port_signal signal[8]; 386c6fd2807SJeff Garzik const struct mv_hw_ops *ops; 387c6fd2807SJeff Garzik }; 388c6fd2807SJeff Garzik 389c6fd2807SJeff Garzik static void mv_irq_clear(struct ata_port *ap); 390c6fd2807SJeff Garzik static u32 mv_scr_read(struct ata_port *ap, unsigned int sc_reg_in); 391c6fd2807SJeff Garzik static void mv_scr_write(struct ata_port *ap, unsigned int sc_reg_in, u32 val); 392c6fd2807SJeff Garzik static u32 mv5_scr_read(struct ata_port *ap, unsigned int sc_reg_in); 393c6fd2807SJeff Garzik static void mv5_scr_write(struct ata_port *ap, unsigned int sc_reg_in, u32 val); 394c6fd2807SJeff Garzik static void mv_phy_reset(struct ata_port *ap); 395c6fd2807SJeff Garzik static void __mv_phy_reset(struct ata_port *ap, int can_sleep); 396c6fd2807SJeff Garzik static int mv_port_start(struct ata_port *ap); 397c6fd2807SJeff Garzik static void mv_port_stop(struct ata_port *ap); 398c6fd2807SJeff Garzik static void mv_qc_prep(struct ata_queued_cmd *qc); 399c6fd2807SJeff Garzik static void mv_qc_prep_iie(struct ata_queued_cmd *qc); 400c6fd2807SJeff Garzik static unsigned int mv_qc_issue(struct ata_queued_cmd *qc); 401c6fd2807SJeff Garzik static void mv_eng_timeout(struct ata_port *ap); 402c6fd2807SJeff Garzik static int mv_init_one(struct pci_dev *pdev, const struct pci_device_id *ent); 403c6fd2807SJeff Garzik 404c6fd2807SJeff Garzik static void mv5_phy_errata(struct mv_host_priv *hpriv, void __iomem *mmio, 405c6fd2807SJeff Garzik unsigned int port); 406c6fd2807SJeff Garzik static void mv5_enable_leds(struct mv_host_priv *hpriv, void __iomem *mmio); 407c6fd2807SJeff Garzik static void mv5_read_preamp(struct mv_host_priv *hpriv, int idx, 408c6fd2807SJeff Garzik void __iomem *mmio); 409c6fd2807SJeff Garzik static int mv5_reset_hc(struct mv_host_priv *hpriv, void __iomem *mmio, 410c6fd2807SJeff Garzik unsigned int n_hc); 411c6fd2807SJeff Garzik static void mv5_reset_flash(struct mv_host_priv *hpriv, void __iomem *mmio); 412c6fd2807SJeff Garzik static void mv5_reset_bus(struct pci_dev *pdev, void __iomem *mmio); 413c6fd2807SJeff Garzik 414c6fd2807SJeff Garzik static void mv6_phy_errata(struct mv_host_priv *hpriv, void __iomem *mmio, 415c6fd2807SJeff Garzik unsigned int port); 416c6fd2807SJeff Garzik static void mv6_enable_leds(struct mv_host_priv *hpriv, void __iomem *mmio); 417c6fd2807SJeff Garzik static void mv6_read_preamp(struct mv_host_priv *hpriv, int idx, 418c6fd2807SJeff Garzik void __iomem *mmio); 419c6fd2807SJeff Garzik static int mv6_reset_hc(struct mv_host_priv *hpriv, void __iomem *mmio, 420c6fd2807SJeff Garzik unsigned int n_hc); 421c6fd2807SJeff Garzik static void mv6_reset_flash(struct mv_host_priv *hpriv, void __iomem *mmio); 422c6fd2807SJeff Garzik static void mv_reset_pci_bus(struct pci_dev *pdev, void __iomem *mmio); 423c6fd2807SJeff Garzik static void mv_channel_reset(struct mv_host_priv *hpriv, void __iomem *mmio, 424c6fd2807SJeff Garzik unsigned int port_no); 425c6fd2807SJeff Garzik static void mv_stop_and_reset(struct ata_port *ap); 426c6fd2807SJeff Garzik 427*c5d3e45aSJeff Garzik static struct scsi_host_template mv5_sht = { 428c6fd2807SJeff Garzik .module = THIS_MODULE, 429c6fd2807SJeff Garzik .name = DRV_NAME, 430c6fd2807SJeff Garzik .ioctl = ata_scsi_ioctl, 431c6fd2807SJeff Garzik .queuecommand = ata_scsi_queuecmd, 432*c5d3e45aSJeff Garzik .can_queue = ATA_DEF_QUEUE, 433*c5d3e45aSJeff Garzik .this_id = ATA_SHT_THIS_ID, 434*c5d3e45aSJeff Garzik .sg_tablesize = MV_MAX_SG_CT, 435*c5d3e45aSJeff Garzik .cmd_per_lun = ATA_SHT_CMD_PER_LUN, 436*c5d3e45aSJeff Garzik .emulated = ATA_SHT_EMULATED, 437*c5d3e45aSJeff Garzik .use_clustering = 1, 438*c5d3e45aSJeff Garzik .proc_name = DRV_NAME, 439*c5d3e45aSJeff Garzik .dma_boundary = MV_DMA_BOUNDARY, 440*c5d3e45aSJeff Garzik .slave_configure = ata_scsi_slave_config, 441*c5d3e45aSJeff Garzik .slave_destroy = ata_scsi_slave_destroy, 442*c5d3e45aSJeff Garzik .bios_param = ata_std_bios_param, 443*c5d3e45aSJeff Garzik }; 444*c5d3e45aSJeff Garzik 445*c5d3e45aSJeff Garzik static struct scsi_host_template mv6_sht = { 446*c5d3e45aSJeff Garzik .module = THIS_MODULE, 447*c5d3e45aSJeff Garzik .name = DRV_NAME, 448*c5d3e45aSJeff Garzik .ioctl = ata_scsi_ioctl, 449*c5d3e45aSJeff Garzik .queuecommand = ata_scsi_queuecmd, 450*c5d3e45aSJeff Garzik .can_queue = ATA_DEF_QUEUE, 451c6fd2807SJeff Garzik .this_id = ATA_SHT_THIS_ID, 452d88184fbSJeff Garzik .sg_tablesize = MV_MAX_SG_CT, 453c6fd2807SJeff Garzik .cmd_per_lun = ATA_SHT_CMD_PER_LUN, 454c6fd2807SJeff Garzik .emulated = ATA_SHT_EMULATED, 455d88184fbSJeff Garzik .use_clustering = 1, 456c6fd2807SJeff Garzik .proc_name = DRV_NAME, 457c6fd2807SJeff Garzik .dma_boundary = MV_DMA_BOUNDARY, 458c6fd2807SJeff Garzik .slave_configure = ata_scsi_slave_config, 459c6fd2807SJeff Garzik .slave_destroy = ata_scsi_slave_destroy, 460c6fd2807SJeff Garzik .bios_param = ata_std_bios_param, 461c6fd2807SJeff Garzik }; 462c6fd2807SJeff Garzik 463c6fd2807SJeff Garzik static const struct ata_port_operations mv5_ops = { 464c6fd2807SJeff Garzik .port_disable = ata_port_disable, 465c6fd2807SJeff Garzik 466c6fd2807SJeff Garzik .tf_load = ata_tf_load, 467c6fd2807SJeff Garzik .tf_read = ata_tf_read, 468c6fd2807SJeff Garzik .check_status = ata_check_status, 469c6fd2807SJeff Garzik .exec_command = ata_exec_command, 470c6fd2807SJeff Garzik .dev_select = ata_std_dev_select, 471c6fd2807SJeff Garzik 472c6fd2807SJeff Garzik .phy_reset = mv_phy_reset, 473cffacd85SJeff Garzik .cable_detect = ata_cable_sata, 474c6fd2807SJeff Garzik 475c6fd2807SJeff Garzik .qc_prep = mv_qc_prep, 476c6fd2807SJeff Garzik .qc_issue = mv_qc_issue, 4770d5ff566STejun Heo .data_xfer = ata_data_xfer, 478c6fd2807SJeff Garzik 479c6fd2807SJeff Garzik .eng_timeout = mv_eng_timeout, 480c6fd2807SJeff Garzik 481c6fd2807SJeff Garzik .irq_clear = mv_irq_clear, 482246ce3b6SAkira Iguchi .irq_on = ata_irq_on, 483246ce3b6SAkira Iguchi .irq_ack = ata_irq_ack, 484c6fd2807SJeff Garzik 485c6fd2807SJeff Garzik .scr_read = mv5_scr_read, 486c6fd2807SJeff Garzik .scr_write = mv5_scr_write, 487c6fd2807SJeff Garzik 488c6fd2807SJeff Garzik .port_start = mv_port_start, 489c6fd2807SJeff Garzik .port_stop = mv_port_stop, 490c6fd2807SJeff Garzik }; 491c6fd2807SJeff Garzik 492c6fd2807SJeff Garzik static const struct ata_port_operations mv6_ops = { 493c6fd2807SJeff Garzik .port_disable = ata_port_disable, 494c6fd2807SJeff Garzik 495c6fd2807SJeff Garzik .tf_load = ata_tf_load, 496c6fd2807SJeff Garzik .tf_read = ata_tf_read, 497c6fd2807SJeff Garzik .check_status = ata_check_status, 498c6fd2807SJeff Garzik .exec_command = ata_exec_command, 499c6fd2807SJeff Garzik .dev_select = ata_std_dev_select, 500c6fd2807SJeff Garzik 501c6fd2807SJeff Garzik .phy_reset = mv_phy_reset, 502cffacd85SJeff Garzik .cable_detect = ata_cable_sata, 503c6fd2807SJeff Garzik 504c6fd2807SJeff Garzik .qc_prep = mv_qc_prep, 505c6fd2807SJeff Garzik .qc_issue = mv_qc_issue, 5060d5ff566STejun Heo .data_xfer = ata_data_xfer, 507c6fd2807SJeff Garzik 508c6fd2807SJeff Garzik .eng_timeout = mv_eng_timeout, 509c6fd2807SJeff Garzik 510c6fd2807SJeff Garzik .irq_clear = mv_irq_clear, 511246ce3b6SAkira Iguchi .irq_on = ata_irq_on, 512246ce3b6SAkira Iguchi .irq_ack = ata_irq_ack, 513c6fd2807SJeff Garzik 514c6fd2807SJeff Garzik .scr_read = mv_scr_read, 515c6fd2807SJeff Garzik .scr_write = mv_scr_write, 516c6fd2807SJeff Garzik 517c6fd2807SJeff Garzik .port_start = mv_port_start, 518c6fd2807SJeff Garzik .port_stop = mv_port_stop, 519c6fd2807SJeff Garzik }; 520c6fd2807SJeff Garzik 521c6fd2807SJeff Garzik static const struct ata_port_operations mv_iie_ops = { 522c6fd2807SJeff Garzik .port_disable = ata_port_disable, 523c6fd2807SJeff Garzik 524c6fd2807SJeff Garzik .tf_load = ata_tf_load, 525c6fd2807SJeff Garzik .tf_read = ata_tf_read, 526c6fd2807SJeff Garzik .check_status = ata_check_status, 527c6fd2807SJeff Garzik .exec_command = ata_exec_command, 528c6fd2807SJeff Garzik .dev_select = ata_std_dev_select, 529c6fd2807SJeff Garzik 530c6fd2807SJeff Garzik .phy_reset = mv_phy_reset, 531cffacd85SJeff Garzik .cable_detect = ata_cable_sata, 532c6fd2807SJeff Garzik 533c6fd2807SJeff Garzik .qc_prep = mv_qc_prep_iie, 534c6fd2807SJeff Garzik .qc_issue = mv_qc_issue, 5350d5ff566STejun Heo .data_xfer = ata_data_xfer, 536c6fd2807SJeff Garzik 537c6fd2807SJeff Garzik .eng_timeout = mv_eng_timeout, 538c6fd2807SJeff Garzik 539c6fd2807SJeff Garzik .irq_clear = mv_irq_clear, 540246ce3b6SAkira Iguchi .irq_on = ata_irq_on, 541246ce3b6SAkira Iguchi .irq_ack = ata_irq_ack, 542c6fd2807SJeff Garzik 543c6fd2807SJeff Garzik .scr_read = mv_scr_read, 544c6fd2807SJeff Garzik .scr_write = mv_scr_write, 545c6fd2807SJeff Garzik 546c6fd2807SJeff Garzik .port_start = mv_port_start, 547c6fd2807SJeff Garzik .port_stop = mv_port_stop, 548c6fd2807SJeff Garzik }; 549c6fd2807SJeff Garzik 550c6fd2807SJeff Garzik static const struct ata_port_info mv_port_info[] = { 551c6fd2807SJeff Garzik { /* chip_504x */ 552cca3974eSJeff Garzik .flags = MV_COMMON_FLAGS, 553c6fd2807SJeff Garzik .pio_mask = 0x1f, /* pio0-4 */ 554bf6263a8SJeff Garzik .udma_mask = ATA_UDMA6, 555c6fd2807SJeff Garzik .port_ops = &mv5_ops, 556c6fd2807SJeff Garzik }, 557c6fd2807SJeff Garzik { /* chip_508x */ 558*c5d3e45aSJeff Garzik .flags = MV_COMMON_FLAGS | MV_FLAG_DUAL_HC, 559c6fd2807SJeff Garzik .pio_mask = 0x1f, /* pio0-4 */ 560bf6263a8SJeff Garzik .udma_mask = ATA_UDMA6, 561c6fd2807SJeff Garzik .port_ops = &mv5_ops, 562c6fd2807SJeff Garzik }, 563c6fd2807SJeff Garzik { /* chip_5080 */ 564*c5d3e45aSJeff Garzik .flags = MV_COMMON_FLAGS | MV_FLAG_DUAL_HC, 565c6fd2807SJeff Garzik .pio_mask = 0x1f, /* pio0-4 */ 566bf6263a8SJeff Garzik .udma_mask = ATA_UDMA6, 567c6fd2807SJeff Garzik .port_ops = &mv5_ops, 568c6fd2807SJeff Garzik }, 569c6fd2807SJeff Garzik { /* chip_604x */ 570*c5d3e45aSJeff Garzik .flags = MV_COMMON_FLAGS | MV_6XXX_FLAGS, 571c6fd2807SJeff Garzik .pio_mask = 0x1f, /* pio0-4 */ 572bf6263a8SJeff Garzik .udma_mask = ATA_UDMA6, 573c6fd2807SJeff Garzik .port_ops = &mv6_ops, 574c6fd2807SJeff Garzik }, 575c6fd2807SJeff Garzik { /* chip_608x */ 576*c5d3e45aSJeff Garzik .flags = MV_COMMON_FLAGS | MV_6XXX_FLAGS | 577*c5d3e45aSJeff Garzik MV_FLAG_DUAL_HC, 578c6fd2807SJeff Garzik .pio_mask = 0x1f, /* pio0-4 */ 579bf6263a8SJeff Garzik .udma_mask = ATA_UDMA6, 580c6fd2807SJeff Garzik .port_ops = &mv6_ops, 581c6fd2807SJeff Garzik }, 582c6fd2807SJeff Garzik { /* chip_6042 */ 583*c5d3e45aSJeff Garzik .flags = MV_COMMON_FLAGS | MV_6XXX_FLAGS, 584c6fd2807SJeff Garzik .pio_mask = 0x1f, /* pio0-4 */ 585bf6263a8SJeff Garzik .udma_mask = ATA_UDMA6, 586c6fd2807SJeff Garzik .port_ops = &mv_iie_ops, 587c6fd2807SJeff Garzik }, 588c6fd2807SJeff Garzik { /* chip_7042 */ 589*c5d3e45aSJeff Garzik .flags = MV_COMMON_FLAGS | MV_6XXX_FLAGS, 590c6fd2807SJeff Garzik .pio_mask = 0x1f, /* pio0-4 */ 591bf6263a8SJeff Garzik .udma_mask = ATA_UDMA6, 592c6fd2807SJeff Garzik .port_ops = &mv_iie_ops, 593c6fd2807SJeff Garzik }, 594c6fd2807SJeff Garzik }; 595c6fd2807SJeff Garzik 596c6fd2807SJeff Garzik static const struct pci_device_id mv_pci_tbl[] = { 5972d2744fcSJeff Garzik { PCI_VDEVICE(MARVELL, 0x5040), chip_504x }, 5982d2744fcSJeff Garzik { PCI_VDEVICE(MARVELL, 0x5041), chip_504x }, 5992d2744fcSJeff Garzik { PCI_VDEVICE(MARVELL, 0x5080), chip_5080 }, 6002d2744fcSJeff Garzik { PCI_VDEVICE(MARVELL, 0x5081), chip_508x }, 601c6fd2807SJeff Garzik 6022d2744fcSJeff Garzik { PCI_VDEVICE(MARVELL, 0x6040), chip_604x }, 6032d2744fcSJeff Garzik { PCI_VDEVICE(MARVELL, 0x6041), chip_604x }, 6042d2744fcSJeff Garzik { PCI_VDEVICE(MARVELL, 0x6042), chip_6042 }, 6052d2744fcSJeff Garzik { PCI_VDEVICE(MARVELL, 0x6080), chip_608x }, 6062d2744fcSJeff Garzik { PCI_VDEVICE(MARVELL, 0x6081), chip_608x }, 607c6fd2807SJeff Garzik 6082d2744fcSJeff Garzik { PCI_VDEVICE(ADAPTEC2, 0x0241), chip_604x }, 6092d2744fcSJeff Garzik 610d9f9c6bcSFlorian Attenberger /* Adaptec 1430SA */ 611d9f9c6bcSFlorian Attenberger { PCI_VDEVICE(ADAPTEC2, 0x0243), chip_7042 }, 612d9f9c6bcSFlorian Attenberger 613e93f09dcSOlof Johansson { PCI_VDEVICE(TTI, 0x2310), chip_7042 }, 614e93f09dcSOlof Johansson 6156a3d586dSMorrison, Tom /* add Marvell 7042 support */ 6166a3d586dSMorrison, Tom { PCI_VDEVICE(MARVELL, 0x7042), chip_7042 }, 6176a3d586dSMorrison, Tom 618c6fd2807SJeff Garzik { } /* terminate list */ 619c6fd2807SJeff Garzik }; 620c6fd2807SJeff Garzik 621c6fd2807SJeff Garzik static struct pci_driver mv_pci_driver = { 622c6fd2807SJeff Garzik .name = DRV_NAME, 623c6fd2807SJeff Garzik .id_table = mv_pci_tbl, 624c6fd2807SJeff Garzik .probe = mv_init_one, 625c6fd2807SJeff Garzik .remove = ata_pci_remove_one, 626c6fd2807SJeff Garzik }; 627c6fd2807SJeff Garzik 628c6fd2807SJeff Garzik static const struct mv_hw_ops mv5xxx_ops = { 629c6fd2807SJeff Garzik .phy_errata = mv5_phy_errata, 630c6fd2807SJeff Garzik .enable_leds = mv5_enable_leds, 631c6fd2807SJeff Garzik .read_preamp = mv5_read_preamp, 632c6fd2807SJeff Garzik .reset_hc = mv5_reset_hc, 633c6fd2807SJeff Garzik .reset_flash = mv5_reset_flash, 634c6fd2807SJeff Garzik .reset_bus = mv5_reset_bus, 635c6fd2807SJeff Garzik }; 636c6fd2807SJeff Garzik 637c6fd2807SJeff Garzik static const struct mv_hw_ops mv6xxx_ops = { 638c6fd2807SJeff Garzik .phy_errata = mv6_phy_errata, 639c6fd2807SJeff Garzik .enable_leds = mv6_enable_leds, 640c6fd2807SJeff Garzik .read_preamp = mv6_read_preamp, 641c6fd2807SJeff Garzik .reset_hc = mv6_reset_hc, 642c6fd2807SJeff Garzik .reset_flash = mv6_reset_flash, 643c6fd2807SJeff Garzik .reset_bus = mv_reset_pci_bus, 644c6fd2807SJeff Garzik }; 645c6fd2807SJeff Garzik 646c6fd2807SJeff Garzik /* 647c6fd2807SJeff Garzik * module options 648c6fd2807SJeff Garzik */ 649c6fd2807SJeff Garzik static int msi; /* Use PCI msi; either zero (off, default) or non-zero */ 650c6fd2807SJeff Garzik 651c6fd2807SJeff Garzik 652d88184fbSJeff Garzik /* move to PCI layer or libata core? */ 653d88184fbSJeff Garzik static int pci_go_64(struct pci_dev *pdev) 654d88184fbSJeff Garzik { 655d88184fbSJeff Garzik int rc; 656d88184fbSJeff Garzik 657d88184fbSJeff Garzik if (!pci_set_dma_mask(pdev, DMA_64BIT_MASK)) { 658d88184fbSJeff Garzik rc = pci_set_consistent_dma_mask(pdev, DMA_64BIT_MASK); 659d88184fbSJeff Garzik if (rc) { 660d88184fbSJeff Garzik rc = pci_set_consistent_dma_mask(pdev, DMA_32BIT_MASK); 661d88184fbSJeff Garzik if (rc) { 662d88184fbSJeff Garzik dev_printk(KERN_ERR, &pdev->dev, 663d88184fbSJeff Garzik "64-bit DMA enable failed\n"); 664d88184fbSJeff Garzik return rc; 665d88184fbSJeff Garzik } 666d88184fbSJeff Garzik } 667d88184fbSJeff Garzik } else { 668d88184fbSJeff Garzik rc = pci_set_dma_mask(pdev, DMA_32BIT_MASK); 669d88184fbSJeff Garzik if (rc) { 670d88184fbSJeff Garzik dev_printk(KERN_ERR, &pdev->dev, 671d88184fbSJeff Garzik "32-bit DMA enable failed\n"); 672d88184fbSJeff Garzik return rc; 673d88184fbSJeff Garzik } 674d88184fbSJeff Garzik rc = pci_set_consistent_dma_mask(pdev, DMA_32BIT_MASK); 675d88184fbSJeff Garzik if (rc) { 676d88184fbSJeff Garzik dev_printk(KERN_ERR, &pdev->dev, 677d88184fbSJeff Garzik "32-bit consistent DMA enable failed\n"); 678d88184fbSJeff Garzik return rc; 679d88184fbSJeff Garzik } 680d88184fbSJeff Garzik } 681d88184fbSJeff Garzik 682d88184fbSJeff Garzik return rc; 683d88184fbSJeff Garzik } 684d88184fbSJeff Garzik 685c6fd2807SJeff Garzik /* 686c6fd2807SJeff Garzik * Functions 687c6fd2807SJeff Garzik */ 688c6fd2807SJeff Garzik 689c6fd2807SJeff Garzik static inline void writelfl(unsigned long data, void __iomem *addr) 690c6fd2807SJeff Garzik { 691c6fd2807SJeff Garzik writel(data, addr); 692c6fd2807SJeff Garzik (void) readl(addr); /* flush to avoid PCI posted write */ 693c6fd2807SJeff Garzik } 694c6fd2807SJeff Garzik 695c6fd2807SJeff Garzik static inline void __iomem *mv_hc_base(void __iomem *base, unsigned int hc) 696c6fd2807SJeff Garzik { 697c6fd2807SJeff Garzik return (base + MV_SATAHC0_REG_BASE + (hc * MV_SATAHC_REG_SZ)); 698c6fd2807SJeff Garzik } 699c6fd2807SJeff Garzik 700c6fd2807SJeff Garzik static inline unsigned int mv_hc_from_port(unsigned int port) 701c6fd2807SJeff Garzik { 702c6fd2807SJeff Garzik return port >> MV_PORT_HC_SHIFT; 703c6fd2807SJeff Garzik } 704c6fd2807SJeff Garzik 705c6fd2807SJeff Garzik static inline unsigned int mv_hardport_from_port(unsigned int port) 706c6fd2807SJeff Garzik { 707c6fd2807SJeff Garzik return port & MV_PORT_MASK; 708c6fd2807SJeff Garzik } 709c6fd2807SJeff Garzik 710c6fd2807SJeff Garzik static inline void __iomem *mv_hc_base_from_port(void __iomem *base, 711c6fd2807SJeff Garzik unsigned int port) 712c6fd2807SJeff Garzik { 713c6fd2807SJeff Garzik return mv_hc_base(base, mv_hc_from_port(port)); 714c6fd2807SJeff Garzik } 715c6fd2807SJeff Garzik 716c6fd2807SJeff Garzik static inline void __iomem *mv_port_base(void __iomem *base, unsigned int port) 717c6fd2807SJeff Garzik { 718c6fd2807SJeff Garzik return mv_hc_base_from_port(base, port) + 719c6fd2807SJeff Garzik MV_SATAHC_ARBTR_REG_SZ + 720c6fd2807SJeff Garzik (mv_hardport_from_port(port) * MV_PORT_REG_SZ); 721c6fd2807SJeff Garzik } 722c6fd2807SJeff Garzik 723c6fd2807SJeff Garzik static inline void __iomem *mv_ap_base(struct ata_port *ap) 724c6fd2807SJeff Garzik { 7250d5ff566STejun Heo return mv_port_base(ap->host->iomap[MV_PRIMARY_BAR], ap->port_no); 726c6fd2807SJeff Garzik } 727c6fd2807SJeff Garzik 728cca3974eSJeff Garzik static inline int mv_get_hc_count(unsigned long port_flags) 729c6fd2807SJeff Garzik { 730cca3974eSJeff Garzik return ((port_flags & MV_FLAG_DUAL_HC) ? 2 : 1); 731c6fd2807SJeff Garzik } 732c6fd2807SJeff Garzik 733c6fd2807SJeff Garzik static void mv_irq_clear(struct ata_port *ap) 734c6fd2807SJeff Garzik { 735c6fd2807SJeff Garzik } 736c6fd2807SJeff Garzik 737*c5d3e45aSJeff Garzik static void mv_set_edma_ptrs(void __iomem *port_mmio, 738*c5d3e45aSJeff Garzik struct mv_host_priv *hpriv, 739*c5d3e45aSJeff Garzik struct mv_port_priv *pp) 740*c5d3e45aSJeff Garzik { 741*c5d3e45aSJeff Garzik /* 742*c5d3e45aSJeff Garzik * initialize request queue 743*c5d3e45aSJeff Garzik */ 744*c5d3e45aSJeff Garzik WARN_ON(pp->crqb_dma & 0x3ff); 745*c5d3e45aSJeff Garzik writel((pp->crqb_dma >> 16) >> 16, port_mmio + EDMA_REQ_Q_BASE_HI_OFS); 746*c5d3e45aSJeff Garzik writelfl(pp->crqb_dma & EDMA_REQ_Q_BASE_LO_MASK, 747*c5d3e45aSJeff Garzik port_mmio + EDMA_REQ_Q_IN_PTR_OFS); 748*c5d3e45aSJeff Garzik 749*c5d3e45aSJeff Garzik if (hpriv->hp_flags & MV_HP_ERRATA_XX42A0) 750*c5d3e45aSJeff Garzik writelfl(pp->crqb_dma & 0xffffffff, 751*c5d3e45aSJeff Garzik port_mmio + EDMA_REQ_Q_OUT_PTR_OFS); 752*c5d3e45aSJeff Garzik else 753*c5d3e45aSJeff Garzik writelfl(0, port_mmio + EDMA_REQ_Q_OUT_PTR_OFS); 754*c5d3e45aSJeff Garzik 755*c5d3e45aSJeff Garzik /* 756*c5d3e45aSJeff Garzik * initialize response queue 757*c5d3e45aSJeff Garzik */ 758*c5d3e45aSJeff Garzik WARN_ON(pp->crpb_dma & 0xff); 759*c5d3e45aSJeff Garzik writel((pp->crpb_dma >> 16) >> 16, port_mmio + EDMA_RSP_Q_BASE_HI_OFS); 760*c5d3e45aSJeff Garzik 761*c5d3e45aSJeff Garzik if (hpriv->hp_flags & MV_HP_ERRATA_XX42A0) 762*c5d3e45aSJeff Garzik writelfl(pp->crpb_dma & 0xffffffff, 763*c5d3e45aSJeff Garzik port_mmio + EDMA_RSP_Q_IN_PTR_OFS); 764*c5d3e45aSJeff Garzik else 765*c5d3e45aSJeff Garzik writelfl(0, port_mmio + EDMA_RSP_Q_IN_PTR_OFS); 766*c5d3e45aSJeff Garzik 767*c5d3e45aSJeff Garzik writelfl(pp->crpb_dma & EDMA_RSP_Q_BASE_LO_MASK, 768*c5d3e45aSJeff Garzik port_mmio + EDMA_RSP_Q_OUT_PTR_OFS); 769*c5d3e45aSJeff Garzik 770*c5d3e45aSJeff Garzik } 771*c5d3e45aSJeff Garzik 772c6fd2807SJeff Garzik /** 773c6fd2807SJeff Garzik * mv_start_dma - Enable eDMA engine 774c6fd2807SJeff Garzik * @base: port base address 775c6fd2807SJeff Garzik * @pp: port private data 776c6fd2807SJeff Garzik * 777c6fd2807SJeff Garzik * Verify the local cache of the eDMA state is accurate with a 778c6fd2807SJeff Garzik * WARN_ON. 779c6fd2807SJeff Garzik * 780c6fd2807SJeff Garzik * LOCKING: 781c6fd2807SJeff Garzik * Inherited from caller. 782c6fd2807SJeff Garzik */ 783*c5d3e45aSJeff Garzik static void mv_start_dma(void __iomem *base, struct mv_host_priv *hpriv, 784*c5d3e45aSJeff Garzik struct mv_port_priv *pp) 785c6fd2807SJeff Garzik { 786*c5d3e45aSJeff Garzik if (!(pp->pp_flags & MV_PP_FLAG_EDMA_EN)) { 787c6fd2807SJeff Garzik writelfl(EDMA_EN, base + EDMA_CMD_OFS); 788c6fd2807SJeff Garzik pp->pp_flags |= MV_PP_FLAG_EDMA_EN; 789c6fd2807SJeff Garzik } 790c6fd2807SJeff Garzik WARN_ON(!(EDMA_EN & readl(base + EDMA_CMD_OFS))); 791c6fd2807SJeff Garzik } 792c6fd2807SJeff Garzik 793c6fd2807SJeff Garzik /** 794c6fd2807SJeff Garzik * mv_stop_dma - Disable eDMA engine 795c6fd2807SJeff Garzik * @ap: ATA channel to manipulate 796c6fd2807SJeff Garzik * 797c6fd2807SJeff Garzik * Verify the local cache of the eDMA state is accurate with a 798c6fd2807SJeff Garzik * WARN_ON. 799c6fd2807SJeff Garzik * 800c6fd2807SJeff Garzik * LOCKING: 801c6fd2807SJeff Garzik * Inherited from caller. 802c6fd2807SJeff Garzik */ 803*c5d3e45aSJeff Garzik static int mv_stop_dma(struct ata_port *ap) 804c6fd2807SJeff Garzik { 805c6fd2807SJeff Garzik void __iomem *port_mmio = mv_ap_base(ap); 806c6fd2807SJeff Garzik struct mv_port_priv *pp = ap->private_data; 807c6fd2807SJeff Garzik u32 reg; 808*c5d3e45aSJeff Garzik int i, err = 0; 809c6fd2807SJeff Garzik 810c6fd2807SJeff Garzik if (MV_PP_FLAG_EDMA_EN & pp->pp_flags) { 811c6fd2807SJeff Garzik /* Disable EDMA if active. The disable bit auto clears. 812c6fd2807SJeff Garzik */ 813c6fd2807SJeff Garzik writelfl(EDMA_DS, port_mmio + EDMA_CMD_OFS); 814c6fd2807SJeff Garzik pp->pp_flags &= ~MV_PP_FLAG_EDMA_EN; 815c6fd2807SJeff Garzik } else { 816c6fd2807SJeff Garzik WARN_ON(EDMA_EN & readl(port_mmio + EDMA_CMD_OFS)); 817c6fd2807SJeff Garzik } 818c6fd2807SJeff Garzik 819c6fd2807SJeff Garzik /* now properly wait for the eDMA to stop */ 820c6fd2807SJeff Garzik for (i = 1000; i > 0; i--) { 821c6fd2807SJeff Garzik reg = readl(port_mmio + EDMA_CMD_OFS); 822c6fd2807SJeff Garzik if (!(EDMA_EN & reg)) { 823c6fd2807SJeff Garzik break; 824c6fd2807SJeff Garzik } 825c6fd2807SJeff Garzik udelay(100); 826c6fd2807SJeff Garzik } 827c6fd2807SJeff Garzik 828*c5d3e45aSJeff Garzik if (reg & EDMA_EN) { 829c6fd2807SJeff Garzik ata_port_printk(ap, KERN_ERR, "Unable to stop eDMA\n"); 830c6fd2807SJeff Garzik /* FIXME: Consider doing a reset here to recover */ 831*c5d3e45aSJeff Garzik err = -EIO; 832c6fd2807SJeff Garzik } 833*c5d3e45aSJeff Garzik 834*c5d3e45aSJeff Garzik return err; 835c6fd2807SJeff Garzik } 836c6fd2807SJeff Garzik 837c6fd2807SJeff Garzik #ifdef ATA_DEBUG 838c6fd2807SJeff Garzik static void mv_dump_mem(void __iomem *start, unsigned bytes) 839c6fd2807SJeff Garzik { 840c6fd2807SJeff Garzik int b, w; 841c6fd2807SJeff Garzik for (b = 0; b < bytes; ) { 842c6fd2807SJeff Garzik DPRINTK("%p: ", start + b); 843c6fd2807SJeff Garzik for (w = 0; b < bytes && w < 4; w++) { 844c6fd2807SJeff Garzik printk("%08x ",readl(start + b)); 845c6fd2807SJeff Garzik b += sizeof(u32); 846c6fd2807SJeff Garzik } 847c6fd2807SJeff Garzik printk("\n"); 848c6fd2807SJeff Garzik } 849c6fd2807SJeff Garzik } 850c6fd2807SJeff Garzik #endif 851c6fd2807SJeff Garzik 852c6fd2807SJeff Garzik static void mv_dump_pci_cfg(struct pci_dev *pdev, unsigned bytes) 853c6fd2807SJeff Garzik { 854c6fd2807SJeff Garzik #ifdef ATA_DEBUG 855c6fd2807SJeff Garzik int b, w; 856c6fd2807SJeff Garzik u32 dw; 857c6fd2807SJeff Garzik for (b = 0; b < bytes; ) { 858c6fd2807SJeff Garzik DPRINTK("%02x: ", b); 859c6fd2807SJeff Garzik for (w = 0; b < bytes && w < 4; w++) { 860c6fd2807SJeff Garzik (void) pci_read_config_dword(pdev,b,&dw); 861c6fd2807SJeff Garzik printk("%08x ",dw); 862c6fd2807SJeff Garzik b += sizeof(u32); 863c6fd2807SJeff Garzik } 864c6fd2807SJeff Garzik printk("\n"); 865c6fd2807SJeff Garzik } 866c6fd2807SJeff Garzik #endif 867c6fd2807SJeff Garzik } 868c6fd2807SJeff Garzik static void mv_dump_all_regs(void __iomem *mmio_base, int port, 869c6fd2807SJeff Garzik struct pci_dev *pdev) 870c6fd2807SJeff Garzik { 871c6fd2807SJeff Garzik #ifdef ATA_DEBUG 872c6fd2807SJeff Garzik void __iomem *hc_base = mv_hc_base(mmio_base, 873c6fd2807SJeff Garzik port >> MV_PORT_HC_SHIFT); 874c6fd2807SJeff Garzik void __iomem *port_base; 875c6fd2807SJeff Garzik int start_port, num_ports, p, start_hc, num_hcs, hc; 876c6fd2807SJeff Garzik 877c6fd2807SJeff Garzik if (0 > port) { 878c6fd2807SJeff Garzik start_hc = start_port = 0; 879c6fd2807SJeff Garzik num_ports = 8; /* shld be benign for 4 port devs */ 880c6fd2807SJeff Garzik num_hcs = 2; 881c6fd2807SJeff Garzik } else { 882c6fd2807SJeff Garzik start_hc = port >> MV_PORT_HC_SHIFT; 883c6fd2807SJeff Garzik start_port = port; 884c6fd2807SJeff Garzik num_ports = num_hcs = 1; 885c6fd2807SJeff Garzik } 886c6fd2807SJeff Garzik DPRINTK("All registers for port(s) %u-%u:\n", start_port, 887c6fd2807SJeff Garzik num_ports > 1 ? num_ports - 1 : start_port); 888c6fd2807SJeff Garzik 889c6fd2807SJeff Garzik if (NULL != pdev) { 890c6fd2807SJeff Garzik DPRINTK("PCI config space regs:\n"); 891c6fd2807SJeff Garzik mv_dump_pci_cfg(pdev, 0x68); 892c6fd2807SJeff Garzik } 893c6fd2807SJeff Garzik DPRINTK("PCI regs:\n"); 894c6fd2807SJeff Garzik mv_dump_mem(mmio_base+0xc00, 0x3c); 895c6fd2807SJeff Garzik mv_dump_mem(mmio_base+0xd00, 0x34); 896c6fd2807SJeff Garzik mv_dump_mem(mmio_base+0xf00, 0x4); 897c6fd2807SJeff Garzik mv_dump_mem(mmio_base+0x1d00, 0x6c); 898c6fd2807SJeff Garzik for (hc = start_hc; hc < start_hc + num_hcs; hc++) { 899c6fd2807SJeff Garzik hc_base = mv_hc_base(mmio_base, hc); 900c6fd2807SJeff Garzik DPRINTK("HC regs (HC %i):\n", hc); 901c6fd2807SJeff Garzik mv_dump_mem(hc_base, 0x1c); 902c6fd2807SJeff Garzik } 903c6fd2807SJeff Garzik for (p = start_port; p < start_port + num_ports; p++) { 904c6fd2807SJeff Garzik port_base = mv_port_base(mmio_base, p); 905c6fd2807SJeff Garzik DPRINTK("EDMA regs (port %i):\n",p); 906c6fd2807SJeff Garzik mv_dump_mem(port_base, 0x54); 907c6fd2807SJeff Garzik DPRINTK("SATA regs (port %i):\n",p); 908c6fd2807SJeff Garzik mv_dump_mem(port_base+0x300, 0x60); 909c6fd2807SJeff Garzik } 910c6fd2807SJeff Garzik #endif 911c6fd2807SJeff Garzik } 912c6fd2807SJeff Garzik 913c6fd2807SJeff Garzik static unsigned int mv_scr_offset(unsigned int sc_reg_in) 914c6fd2807SJeff Garzik { 915c6fd2807SJeff Garzik unsigned int ofs; 916c6fd2807SJeff Garzik 917c6fd2807SJeff Garzik switch (sc_reg_in) { 918c6fd2807SJeff Garzik case SCR_STATUS: 919c6fd2807SJeff Garzik case SCR_CONTROL: 920c6fd2807SJeff Garzik case SCR_ERROR: 921c6fd2807SJeff Garzik ofs = SATA_STATUS_OFS + (sc_reg_in * sizeof(u32)); 922c6fd2807SJeff Garzik break; 923c6fd2807SJeff Garzik case SCR_ACTIVE: 924c6fd2807SJeff Garzik ofs = SATA_ACTIVE_OFS; /* active is not with the others */ 925c6fd2807SJeff Garzik break; 926c6fd2807SJeff Garzik default: 927c6fd2807SJeff Garzik ofs = 0xffffffffU; 928c6fd2807SJeff Garzik break; 929c6fd2807SJeff Garzik } 930c6fd2807SJeff Garzik return ofs; 931c6fd2807SJeff Garzik } 932c6fd2807SJeff Garzik 933c6fd2807SJeff Garzik static u32 mv_scr_read(struct ata_port *ap, unsigned int sc_reg_in) 934c6fd2807SJeff Garzik { 935c6fd2807SJeff Garzik unsigned int ofs = mv_scr_offset(sc_reg_in); 936c6fd2807SJeff Garzik 93735177265SJeff Garzik if (0xffffffffU != ofs) 938c6fd2807SJeff Garzik return readl(mv_ap_base(ap) + ofs); 93935177265SJeff Garzik else 940c6fd2807SJeff Garzik return (u32) ofs; 941c6fd2807SJeff Garzik } 942c6fd2807SJeff Garzik 943c6fd2807SJeff Garzik static void mv_scr_write(struct ata_port *ap, unsigned int sc_reg_in, u32 val) 944c6fd2807SJeff Garzik { 945c6fd2807SJeff Garzik unsigned int ofs = mv_scr_offset(sc_reg_in); 946c6fd2807SJeff Garzik 94735177265SJeff Garzik if (0xffffffffU != ofs) 948c6fd2807SJeff Garzik writelfl(val, mv_ap_base(ap) + ofs); 949c6fd2807SJeff Garzik } 950c6fd2807SJeff Garzik 951*c5d3e45aSJeff Garzik static void mv_edma_cfg(struct ata_port *ap, struct mv_host_priv *hpriv, 952*c5d3e45aSJeff Garzik void __iomem *port_mmio) 953c6fd2807SJeff Garzik { 954c6fd2807SJeff Garzik u32 cfg = readl(port_mmio + EDMA_CFG_OFS); 955c6fd2807SJeff Garzik 956c6fd2807SJeff Garzik /* set up non-NCQ EDMA configuration */ 957*c5d3e45aSJeff Garzik cfg &= ~(1 << 9); /* disable eQue */ 958c6fd2807SJeff Garzik 959e728eabeSJeff Garzik if (IS_GEN_I(hpriv)) { 960e728eabeSJeff Garzik cfg &= ~0x1f; /* clear queue depth */ 961c6fd2807SJeff Garzik cfg |= (1 << 8); /* enab config burst size mask */ 962e728eabeSJeff Garzik } 963c6fd2807SJeff Garzik 964e728eabeSJeff Garzik else if (IS_GEN_II(hpriv)) { 965e728eabeSJeff Garzik cfg &= ~0x1f; /* clear queue depth */ 966c6fd2807SJeff Garzik cfg |= EDMA_CFG_RD_BRST_EXT | EDMA_CFG_WR_BUFF_LEN; 967e728eabeSJeff Garzik cfg &= ~(EDMA_CFG_NCQ | EDMA_CFG_NCQ_GO_ON_ERR); /* clear NCQ */ 968e728eabeSJeff Garzik } 969c6fd2807SJeff Garzik 970c6fd2807SJeff Garzik else if (IS_GEN_IIE(hpriv)) { 971e728eabeSJeff Garzik cfg |= (1 << 23); /* do not mask PM field in rx'd FIS */ 972e728eabeSJeff Garzik cfg |= (1 << 22); /* enab 4-entry host queue cache */ 973c6fd2807SJeff Garzik cfg &= ~(1 << 19); /* dis 128-entry queue (for now?) */ 974c6fd2807SJeff Garzik cfg |= (1 << 18); /* enab early completion */ 975e728eabeSJeff Garzik cfg |= (1 << 17); /* enab cut-through (dis stor&forwrd) */ 976e728eabeSJeff Garzik cfg &= ~(1 << 16); /* dis FIS-based switching (for now) */ 977e728eabeSJeff Garzik cfg &= ~(EDMA_CFG_NCQ | EDMA_CFG_NCQ_GO_ON_ERR); /* clear NCQ */ 978c6fd2807SJeff Garzik } 979c6fd2807SJeff Garzik 980c6fd2807SJeff Garzik writelfl(cfg, port_mmio + EDMA_CFG_OFS); 981c6fd2807SJeff Garzik } 982c6fd2807SJeff Garzik 983c6fd2807SJeff Garzik /** 984c6fd2807SJeff Garzik * mv_port_start - Port specific init/start routine. 985c6fd2807SJeff Garzik * @ap: ATA channel to manipulate 986c6fd2807SJeff Garzik * 987c6fd2807SJeff Garzik * Allocate and point to DMA memory, init port private memory, 988c6fd2807SJeff Garzik * zero indices. 989c6fd2807SJeff Garzik * 990c6fd2807SJeff Garzik * LOCKING: 991c6fd2807SJeff Garzik * Inherited from caller. 992c6fd2807SJeff Garzik */ 993c6fd2807SJeff Garzik static int mv_port_start(struct ata_port *ap) 994c6fd2807SJeff Garzik { 995cca3974eSJeff Garzik struct device *dev = ap->host->dev; 996cca3974eSJeff Garzik struct mv_host_priv *hpriv = ap->host->private_data; 997c6fd2807SJeff Garzik struct mv_port_priv *pp; 998c6fd2807SJeff Garzik void __iomem *port_mmio = mv_ap_base(ap); 999c6fd2807SJeff Garzik void *mem; 1000c6fd2807SJeff Garzik dma_addr_t mem_dma; 100124dc5f33STejun Heo int rc; 1002c6fd2807SJeff Garzik 100324dc5f33STejun Heo pp = devm_kzalloc(dev, sizeof(*pp), GFP_KERNEL); 1004c6fd2807SJeff Garzik if (!pp) 100524dc5f33STejun Heo return -ENOMEM; 1006c6fd2807SJeff Garzik 100724dc5f33STejun Heo mem = dmam_alloc_coherent(dev, MV_PORT_PRIV_DMA_SZ, &mem_dma, 1008c6fd2807SJeff Garzik GFP_KERNEL); 1009c6fd2807SJeff Garzik if (!mem) 101024dc5f33STejun Heo return -ENOMEM; 1011c6fd2807SJeff Garzik memset(mem, 0, MV_PORT_PRIV_DMA_SZ); 1012c6fd2807SJeff Garzik 1013c6fd2807SJeff Garzik rc = ata_pad_alloc(ap, dev); 1014c6fd2807SJeff Garzik if (rc) 101524dc5f33STejun Heo return rc; 1016c6fd2807SJeff Garzik 1017c6fd2807SJeff Garzik /* First item in chunk of DMA memory: 1018c6fd2807SJeff Garzik * 32-slot command request table (CRQB), 32 bytes each in size 1019c6fd2807SJeff Garzik */ 1020c6fd2807SJeff Garzik pp->crqb = mem; 1021c6fd2807SJeff Garzik pp->crqb_dma = mem_dma; 1022c6fd2807SJeff Garzik mem += MV_CRQB_Q_SZ; 1023c6fd2807SJeff Garzik mem_dma += MV_CRQB_Q_SZ; 1024c6fd2807SJeff Garzik 1025c6fd2807SJeff Garzik /* Second item: 1026c6fd2807SJeff Garzik * 32-slot command response table (CRPB), 8 bytes each in size 1027c6fd2807SJeff Garzik */ 1028c6fd2807SJeff Garzik pp->crpb = mem; 1029c6fd2807SJeff Garzik pp->crpb_dma = mem_dma; 1030c6fd2807SJeff Garzik mem += MV_CRPB_Q_SZ; 1031c6fd2807SJeff Garzik mem_dma += MV_CRPB_Q_SZ; 1032c6fd2807SJeff Garzik 1033c6fd2807SJeff Garzik /* Third item: 1034c6fd2807SJeff Garzik * Table of scatter-gather descriptors (ePRD), 16 bytes each 1035c6fd2807SJeff Garzik */ 1036c6fd2807SJeff Garzik pp->sg_tbl = mem; 1037c6fd2807SJeff Garzik pp->sg_tbl_dma = mem_dma; 1038c6fd2807SJeff Garzik 1039*c5d3e45aSJeff Garzik mv_edma_cfg(ap, hpriv, port_mmio); 1040c6fd2807SJeff Garzik 1041*c5d3e45aSJeff Garzik mv_set_edma_ptrs(port_mmio, hpriv, pp); 1042c6fd2807SJeff Garzik 1043c6fd2807SJeff Garzik /* Don't turn on EDMA here...do it before DMA commands only. Else 1044c6fd2807SJeff Garzik * we'll be unable to send non-data, PIO, etc due to restricted access 1045c6fd2807SJeff Garzik * to shadow regs. 1046c6fd2807SJeff Garzik */ 1047c6fd2807SJeff Garzik ap->private_data = pp; 1048c6fd2807SJeff Garzik return 0; 1049c6fd2807SJeff Garzik } 1050c6fd2807SJeff Garzik 1051c6fd2807SJeff Garzik /** 1052c6fd2807SJeff Garzik * mv_port_stop - Port specific cleanup/stop routine. 1053c6fd2807SJeff Garzik * @ap: ATA channel to manipulate 1054c6fd2807SJeff Garzik * 1055c6fd2807SJeff Garzik * Stop DMA, cleanup port memory. 1056c6fd2807SJeff Garzik * 1057c6fd2807SJeff Garzik * LOCKING: 1058cca3974eSJeff Garzik * This routine uses the host lock to protect the DMA stop. 1059c6fd2807SJeff Garzik */ 1060c6fd2807SJeff Garzik static void mv_port_stop(struct ata_port *ap) 1061c6fd2807SJeff Garzik { 1062c6fd2807SJeff Garzik unsigned long flags; 1063c6fd2807SJeff Garzik 1064cca3974eSJeff Garzik spin_lock_irqsave(&ap->host->lock, flags); 1065c6fd2807SJeff Garzik mv_stop_dma(ap); 1066cca3974eSJeff Garzik spin_unlock_irqrestore(&ap->host->lock, flags); 1067c6fd2807SJeff Garzik } 1068c6fd2807SJeff Garzik 1069c6fd2807SJeff Garzik /** 1070c6fd2807SJeff Garzik * mv_fill_sg - Fill out the Marvell ePRD (scatter gather) entries 1071c6fd2807SJeff Garzik * @qc: queued command whose SG list to source from 1072c6fd2807SJeff Garzik * 1073c6fd2807SJeff Garzik * Populate the SG list and mark the last entry. 1074c6fd2807SJeff Garzik * 1075c6fd2807SJeff Garzik * LOCKING: 1076c6fd2807SJeff Garzik * Inherited from caller. 1077c6fd2807SJeff Garzik */ 1078d88184fbSJeff Garzik static unsigned int mv_fill_sg(struct ata_queued_cmd *qc) 1079c6fd2807SJeff Garzik { 1080c6fd2807SJeff Garzik struct mv_port_priv *pp = qc->ap->private_data; 1081d88184fbSJeff Garzik unsigned int n_sg = 0; 1082c6fd2807SJeff Garzik struct scatterlist *sg; 1083d88184fbSJeff Garzik struct mv_sg *mv_sg; 1084c6fd2807SJeff Garzik 1085d88184fbSJeff Garzik mv_sg = pp->sg_tbl; 1086c6fd2807SJeff Garzik ata_for_each_sg(sg, qc) { 1087d88184fbSJeff Garzik dma_addr_t addr = sg_dma_address(sg); 1088d88184fbSJeff Garzik u32 sg_len = sg_dma_len(sg); 1089c6fd2807SJeff Garzik 1090d88184fbSJeff Garzik mv_sg->addr = cpu_to_le32(addr & 0xffffffff); 1091d88184fbSJeff Garzik mv_sg->addr_hi = cpu_to_le32((addr >> 16) >> 16); 1092d88184fbSJeff Garzik mv_sg->flags_size = cpu_to_le32(sg_len & 0xffff); 1093c6fd2807SJeff Garzik 1094d88184fbSJeff Garzik if (ata_sg_is_last(sg, qc)) 1095d88184fbSJeff Garzik mv_sg->flags_size |= cpu_to_le32(EPRD_FLAG_END_OF_TBL); 1096c6fd2807SJeff Garzik 1097d88184fbSJeff Garzik mv_sg++; 1098d88184fbSJeff Garzik n_sg++; 1099c6fd2807SJeff Garzik } 1100d88184fbSJeff Garzik 1101d88184fbSJeff Garzik return n_sg; 1102c6fd2807SJeff Garzik } 1103c6fd2807SJeff Garzik 1104c6fd2807SJeff Garzik static inline unsigned mv_inc_q_index(unsigned index) 1105c6fd2807SJeff Garzik { 1106c6fd2807SJeff Garzik return (index + 1) & MV_MAX_Q_DEPTH_MASK; 1107c6fd2807SJeff Garzik } 1108c6fd2807SJeff Garzik 1109c6fd2807SJeff Garzik static inline void mv_crqb_pack_cmd(__le16 *cmdw, u8 data, u8 addr, unsigned last) 1110c6fd2807SJeff Garzik { 1111c6fd2807SJeff Garzik u16 tmp = data | (addr << CRQB_CMD_ADDR_SHIFT) | CRQB_CMD_CS | 1112c6fd2807SJeff Garzik (last ? CRQB_CMD_LAST : 0); 1113c6fd2807SJeff Garzik *cmdw = cpu_to_le16(tmp); 1114c6fd2807SJeff Garzik } 1115c6fd2807SJeff Garzik 1116c6fd2807SJeff Garzik /** 1117c6fd2807SJeff Garzik * mv_qc_prep - Host specific command preparation. 1118c6fd2807SJeff Garzik * @qc: queued command to prepare 1119c6fd2807SJeff Garzik * 1120c6fd2807SJeff Garzik * This routine simply redirects to the general purpose routine 1121c6fd2807SJeff Garzik * if command is not DMA. Else, it handles prep of the CRQB 1122c6fd2807SJeff Garzik * (command request block), does some sanity checking, and calls 1123c6fd2807SJeff Garzik * the SG load routine. 1124c6fd2807SJeff Garzik * 1125c6fd2807SJeff Garzik * LOCKING: 1126c6fd2807SJeff Garzik * Inherited from caller. 1127c6fd2807SJeff Garzik */ 1128c6fd2807SJeff Garzik static void mv_qc_prep(struct ata_queued_cmd *qc) 1129c6fd2807SJeff Garzik { 1130c6fd2807SJeff Garzik struct ata_port *ap = qc->ap; 1131c6fd2807SJeff Garzik struct mv_port_priv *pp = ap->private_data; 1132c6fd2807SJeff Garzik __le16 *cw; 1133c6fd2807SJeff Garzik struct ata_taskfile *tf; 1134c6fd2807SJeff Garzik u16 flags = 0; 1135c6fd2807SJeff Garzik unsigned in_index; 1136c6fd2807SJeff Garzik 1137*c5d3e45aSJeff Garzik if (qc->tf.protocol != ATA_PROT_DMA) 1138c6fd2807SJeff Garzik return; 1139c6fd2807SJeff Garzik 1140c6fd2807SJeff Garzik /* Fill in command request block 1141c6fd2807SJeff Garzik */ 1142c6fd2807SJeff Garzik if (!(qc->tf.flags & ATA_TFLAG_WRITE)) 1143c6fd2807SJeff Garzik flags |= CRQB_FLAG_READ; 1144c6fd2807SJeff Garzik WARN_ON(MV_MAX_Q_DEPTH <= qc->tag); 1145c6fd2807SJeff Garzik flags |= qc->tag << CRQB_TAG_SHIFT; 1146c6fd2807SJeff Garzik 1147c6fd2807SJeff Garzik /* get current queue index from hardware */ 1148c6fd2807SJeff Garzik in_index = (readl(mv_ap_base(ap) + EDMA_REQ_Q_IN_PTR_OFS) 1149c6fd2807SJeff Garzik >> EDMA_REQ_Q_PTR_SHIFT) & MV_MAX_Q_DEPTH_MASK; 1150c6fd2807SJeff Garzik 1151c6fd2807SJeff Garzik pp->crqb[in_index].sg_addr = 1152c6fd2807SJeff Garzik cpu_to_le32(pp->sg_tbl_dma & 0xffffffff); 1153c6fd2807SJeff Garzik pp->crqb[in_index].sg_addr_hi = 1154c6fd2807SJeff Garzik cpu_to_le32((pp->sg_tbl_dma >> 16) >> 16); 1155c6fd2807SJeff Garzik pp->crqb[in_index].ctrl_flags = cpu_to_le16(flags); 1156c6fd2807SJeff Garzik 1157c6fd2807SJeff Garzik cw = &pp->crqb[in_index].ata_cmd[0]; 1158c6fd2807SJeff Garzik tf = &qc->tf; 1159c6fd2807SJeff Garzik 1160c6fd2807SJeff Garzik /* Sadly, the CRQB cannot accomodate all registers--there are 1161c6fd2807SJeff Garzik * only 11 bytes...so we must pick and choose required 1162c6fd2807SJeff Garzik * registers based on the command. So, we drop feature and 1163c6fd2807SJeff Garzik * hob_feature for [RW] DMA commands, but they are needed for 1164c6fd2807SJeff Garzik * NCQ. NCQ will drop hob_nsect. 1165c6fd2807SJeff Garzik */ 1166c6fd2807SJeff Garzik switch (tf->command) { 1167c6fd2807SJeff Garzik case ATA_CMD_READ: 1168c6fd2807SJeff Garzik case ATA_CMD_READ_EXT: 1169c6fd2807SJeff Garzik case ATA_CMD_WRITE: 1170c6fd2807SJeff Garzik case ATA_CMD_WRITE_EXT: 1171c6fd2807SJeff Garzik case ATA_CMD_WRITE_FUA_EXT: 1172c6fd2807SJeff Garzik mv_crqb_pack_cmd(cw++, tf->hob_nsect, ATA_REG_NSECT, 0); 1173c6fd2807SJeff Garzik break; 1174c6fd2807SJeff Garzik #ifdef LIBATA_NCQ /* FIXME: remove this line when NCQ added */ 1175c6fd2807SJeff Garzik case ATA_CMD_FPDMA_READ: 1176c6fd2807SJeff Garzik case ATA_CMD_FPDMA_WRITE: 1177c6fd2807SJeff Garzik mv_crqb_pack_cmd(cw++, tf->hob_feature, ATA_REG_FEATURE, 0); 1178c6fd2807SJeff Garzik mv_crqb_pack_cmd(cw++, tf->feature, ATA_REG_FEATURE, 0); 1179c6fd2807SJeff Garzik break; 1180c6fd2807SJeff Garzik #endif /* FIXME: remove this line when NCQ added */ 1181c6fd2807SJeff Garzik default: 1182c6fd2807SJeff Garzik /* The only other commands EDMA supports in non-queued and 1183c6fd2807SJeff Garzik * non-NCQ mode are: [RW] STREAM DMA and W DMA FUA EXT, none 1184c6fd2807SJeff Garzik * of which are defined/used by Linux. If we get here, this 1185c6fd2807SJeff Garzik * driver needs work. 1186c6fd2807SJeff Garzik * 1187c6fd2807SJeff Garzik * FIXME: modify libata to give qc_prep a return value and 1188c6fd2807SJeff Garzik * return error here. 1189c6fd2807SJeff Garzik */ 1190c6fd2807SJeff Garzik BUG_ON(tf->command); 1191c6fd2807SJeff Garzik break; 1192c6fd2807SJeff Garzik } 1193c6fd2807SJeff Garzik mv_crqb_pack_cmd(cw++, tf->nsect, ATA_REG_NSECT, 0); 1194c6fd2807SJeff Garzik mv_crqb_pack_cmd(cw++, tf->hob_lbal, ATA_REG_LBAL, 0); 1195c6fd2807SJeff Garzik mv_crqb_pack_cmd(cw++, tf->lbal, ATA_REG_LBAL, 0); 1196c6fd2807SJeff Garzik mv_crqb_pack_cmd(cw++, tf->hob_lbam, ATA_REG_LBAM, 0); 1197c6fd2807SJeff Garzik mv_crqb_pack_cmd(cw++, tf->lbam, ATA_REG_LBAM, 0); 1198c6fd2807SJeff Garzik mv_crqb_pack_cmd(cw++, tf->hob_lbah, ATA_REG_LBAH, 0); 1199c6fd2807SJeff Garzik mv_crqb_pack_cmd(cw++, tf->lbah, ATA_REG_LBAH, 0); 1200c6fd2807SJeff Garzik mv_crqb_pack_cmd(cw++, tf->device, ATA_REG_DEVICE, 0); 1201c6fd2807SJeff Garzik mv_crqb_pack_cmd(cw++, tf->command, ATA_REG_CMD, 1); /* last */ 1202c6fd2807SJeff Garzik 1203c6fd2807SJeff Garzik if (!(qc->flags & ATA_QCFLAG_DMAMAP)) 1204c6fd2807SJeff Garzik return; 1205c6fd2807SJeff Garzik mv_fill_sg(qc); 1206c6fd2807SJeff Garzik } 1207c6fd2807SJeff Garzik 1208c6fd2807SJeff Garzik /** 1209c6fd2807SJeff Garzik * mv_qc_prep_iie - Host specific command preparation. 1210c6fd2807SJeff Garzik * @qc: queued command to prepare 1211c6fd2807SJeff Garzik * 1212c6fd2807SJeff Garzik * This routine simply redirects to the general purpose routine 1213c6fd2807SJeff Garzik * if command is not DMA. Else, it handles prep of the CRQB 1214c6fd2807SJeff Garzik * (command request block), does some sanity checking, and calls 1215c6fd2807SJeff Garzik * the SG load routine. 1216c6fd2807SJeff Garzik * 1217c6fd2807SJeff Garzik * LOCKING: 1218c6fd2807SJeff Garzik * Inherited from caller. 1219c6fd2807SJeff Garzik */ 1220c6fd2807SJeff Garzik static void mv_qc_prep_iie(struct ata_queued_cmd *qc) 1221c6fd2807SJeff Garzik { 1222c6fd2807SJeff Garzik struct ata_port *ap = qc->ap; 1223c6fd2807SJeff Garzik struct mv_port_priv *pp = ap->private_data; 1224c6fd2807SJeff Garzik struct mv_crqb_iie *crqb; 1225c6fd2807SJeff Garzik struct ata_taskfile *tf; 1226c6fd2807SJeff Garzik unsigned in_index; 1227c6fd2807SJeff Garzik u32 flags = 0; 1228c6fd2807SJeff Garzik 1229*c5d3e45aSJeff Garzik if (qc->tf.protocol != ATA_PROT_DMA) 1230c6fd2807SJeff Garzik return; 1231c6fd2807SJeff Garzik 1232c6fd2807SJeff Garzik /* Fill in Gen IIE command request block 1233c6fd2807SJeff Garzik */ 1234c6fd2807SJeff Garzik if (!(qc->tf.flags & ATA_TFLAG_WRITE)) 1235c6fd2807SJeff Garzik flags |= CRQB_FLAG_READ; 1236c6fd2807SJeff Garzik 1237c6fd2807SJeff Garzik WARN_ON(MV_MAX_Q_DEPTH <= qc->tag); 1238c6fd2807SJeff Garzik flags |= qc->tag << CRQB_TAG_SHIFT; 1239c6fd2807SJeff Garzik 1240c6fd2807SJeff Garzik /* get current queue index from hardware */ 1241c6fd2807SJeff Garzik in_index = (readl(mv_ap_base(ap) + EDMA_REQ_Q_IN_PTR_OFS) 1242c6fd2807SJeff Garzik >> EDMA_REQ_Q_PTR_SHIFT) & MV_MAX_Q_DEPTH_MASK; 1243c6fd2807SJeff Garzik 1244c6fd2807SJeff Garzik crqb = (struct mv_crqb_iie *) &pp->crqb[in_index]; 1245c6fd2807SJeff Garzik crqb->addr = cpu_to_le32(pp->sg_tbl_dma & 0xffffffff); 1246c6fd2807SJeff Garzik crqb->addr_hi = cpu_to_le32((pp->sg_tbl_dma >> 16) >> 16); 1247c6fd2807SJeff Garzik crqb->flags = cpu_to_le32(flags); 1248c6fd2807SJeff Garzik 1249c6fd2807SJeff Garzik tf = &qc->tf; 1250c6fd2807SJeff Garzik crqb->ata_cmd[0] = cpu_to_le32( 1251c6fd2807SJeff Garzik (tf->command << 16) | 1252c6fd2807SJeff Garzik (tf->feature << 24) 1253c6fd2807SJeff Garzik ); 1254c6fd2807SJeff Garzik crqb->ata_cmd[1] = cpu_to_le32( 1255c6fd2807SJeff Garzik (tf->lbal << 0) | 1256c6fd2807SJeff Garzik (tf->lbam << 8) | 1257c6fd2807SJeff Garzik (tf->lbah << 16) | 1258c6fd2807SJeff Garzik (tf->device << 24) 1259c6fd2807SJeff Garzik ); 1260c6fd2807SJeff Garzik crqb->ata_cmd[2] = cpu_to_le32( 1261c6fd2807SJeff Garzik (tf->hob_lbal << 0) | 1262c6fd2807SJeff Garzik (tf->hob_lbam << 8) | 1263c6fd2807SJeff Garzik (tf->hob_lbah << 16) | 1264c6fd2807SJeff Garzik (tf->hob_feature << 24) 1265c6fd2807SJeff Garzik ); 1266c6fd2807SJeff Garzik crqb->ata_cmd[3] = cpu_to_le32( 1267c6fd2807SJeff Garzik (tf->nsect << 0) | 1268c6fd2807SJeff Garzik (tf->hob_nsect << 8) 1269c6fd2807SJeff Garzik ); 1270c6fd2807SJeff Garzik 1271c6fd2807SJeff Garzik if (!(qc->flags & ATA_QCFLAG_DMAMAP)) 1272c6fd2807SJeff Garzik return; 1273c6fd2807SJeff Garzik mv_fill_sg(qc); 1274c6fd2807SJeff Garzik } 1275c6fd2807SJeff Garzik 1276c6fd2807SJeff Garzik /** 1277c6fd2807SJeff Garzik * mv_qc_issue - Initiate a command to the host 1278c6fd2807SJeff Garzik * @qc: queued command to start 1279c6fd2807SJeff Garzik * 1280c6fd2807SJeff Garzik * This routine simply redirects to the general purpose routine 1281c6fd2807SJeff Garzik * if command is not DMA. Else, it sanity checks our local 1282c6fd2807SJeff Garzik * caches of the request producer/consumer indices then enables 1283c6fd2807SJeff Garzik * DMA and bumps the request producer index. 1284c6fd2807SJeff Garzik * 1285c6fd2807SJeff Garzik * LOCKING: 1286c6fd2807SJeff Garzik * Inherited from caller. 1287c6fd2807SJeff Garzik */ 1288c6fd2807SJeff Garzik static unsigned int mv_qc_issue(struct ata_queued_cmd *qc) 1289c6fd2807SJeff Garzik { 1290*c5d3e45aSJeff Garzik struct ata_port *ap = qc->ap; 1291*c5d3e45aSJeff Garzik void __iomem *port_mmio = mv_ap_base(ap); 1292*c5d3e45aSJeff Garzik struct mv_port_priv *pp = ap->private_data; 1293*c5d3e45aSJeff Garzik struct mv_host_priv *hpriv = ap->host->private_data; 1294c6fd2807SJeff Garzik unsigned in_index; 1295c6fd2807SJeff Garzik u32 in_ptr; 1296c6fd2807SJeff Garzik 1297*c5d3e45aSJeff Garzik if (qc->tf.protocol != ATA_PROT_DMA) { 1298c6fd2807SJeff Garzik /* We're about to send a non-EDMA capable command to the 1299c6fd2807SJeff Garzik * port. Turn off EDMA so there won't be problems accessing 1300c6fd2807SJeff Garzik * shadow block, etc registers. 1301c6fd2807SJeff Garzik */ 1302*c5d3e45aSJeff Garzik mv_stop_dma(ap); 1303c6fd2807SJeff Garzik return ata_qc_issue_prot(qc); 1304c6fd2807SJeff Garzik } 1305c6fd2807SJeff Garzik 1306c6fd2807SJeff Garzik in_ptr = readl(port_mmio + EDMA_REQ_Q_IN_PTR_OFS); 1307c6fd2807SJeff Garzik in_index = (in_ptr >> EDMA_REQ_Q_PTR_SHIFT) & MV_MAX_Q_DEPTH_MASK; 1308c6fd2807SJeff Garzik 1309c6fd2807SJeff Garzik /* until we do queuing, the queue should be empty at this point */ 1310c6fd2807SJeff Garzik WARN_ON(in_index != ((readl(port_mmio + EDMA_REQ_Q_OUT_PTR_OFS) 1311c6fd2807SJeff Garzik >> EDMA_REQ_Q_PTR_SHIFT) & MV_MAX_Q_DEPTH_MASK)); 1312c6fd2807SJeff Garzik 1313c6fd2807SJeff Garzik in_index = mv_inc_q_index(in_index); /* now incr producer index */ 1314c6fd2807SJeff Garzik 1315*c5d3e45aSJeff Garzik mv_start_dma(port_mmio, hpriv, pp); 1316c6fd2807SJeff Garzik 1317c6fd2807SJeff Garzik /* and write the request in pointer to kick the EDMA to life */ 1318c6fd2807SJeff Garzik in_ptr &= EDMA_REQ_Q_BASE_LO_MASK; 1319c6fd2807SJeff Garzik in_ptr |= in_index << EDMA_REQ_Q_PTR_SHIFT; 1320c6fd2807SJeff Garzik writelfl(in_ptr, port_mmio + EDMA_REQ_Q_IN_PTR_OFS); 1321c6fd2807SJeff Garzik 1322c6fd2807SJeff Garzik return 0; 1323c6fd2807SJeff Garzik } 1324c6fd2807SJeff Garzik 1325c6fd2807SJeff Garzik /** 1326c6fd2807SJeff Garzik * mv_get_crpb_status - get status from most recently completed cmd 1327c6fd2807SJeff Garzik * @ap: ATA channel to manipulate 1328c6fd2807SJeff Garzik * 1329c6fd2807SJeff Garzik * This routine is for use when the port is in DMA mode, when it 1330c6fd2807SJeff Garzik * will be using the CRPB (command response block) method of 1331c6fd2807SJeff Garzik * returning command completion information. We check indices 1332c6fd2807SJeff Garzik * are good, grab status, and bump the response consumer index to 1333c6fd2807SJeff Garzik * prove that we're up to date. 1334c6fd2807SJeff Garzik * 1335c6fd2807SJeff Garzik * LOCKING: 1336c6fd2807SJeff Garzik * Inherited from caller. 1337c6fd2807SJeff Garzik */ 1338c6fd2807SJeff Garzik static u8 mv_get_crpb_status(struct ata_port *ap) 1339c6fd2807SJeff Garzik { 1340c6fd2807SJeff Garzik void __iomem *port_mmio = mv_ap_base(ap); 1341c6fd2807SJeff Garzik struct mv_port_priv *pp = ap->private_data; 1342c6fd2807SJeff Garzik unsigned out_index; 1343c6fd2807SJeff Garzik u32 out_ptr; 1344c6fd2807SJeff Garzik u8 ata_status; 1345c6fd2807SJeff Garzik 1346c6fd2807SJeff Garzik out_ptr = readl(port_mmio + EDMA_RSP_Q_OUT_PTR_OFS); 1347c6fd2807SJeff Garzik out_index = (out_ptr >> EDMA_RSP_Q_PTR_SHIFT) & MV_MAX_Q_DEPTH_MASK; 1348c6fd2807SJeff Garzik 1349c6fd2807SJeff Garzik ata_status = le16_to_cpu(pp->crpb[out_index].flags) 1350c6fd2807SJeff Garzik >> CRPB_FLAG_STATUS_SHIFT; 1351c6fd2807SJeff Garzik 1352c6fd2807SJeff Garzik /* increment our consumer index... */ 1353c6fd2807SJeff Garzik out_index = mv_inc_q_index(out_index); 1354c6fd2807SJeff Garzik 1355c6fd2807SJeff Garzik /* and, until we do NCQ, there should only be 1 CRPB waiting */ 1356c6fd2807SJeff Garzik WARN_ON(out_index != ((readl(port_mmio + EDMA_RSP_Q_IN_PTR_OFS) 1357c6fd2807SJeff Garzik >> EDMA_RSP_Q_PTR_SHIFT) & MV_MAX_Q_DEPTH_MASK)); 1358c6fd2807SJeff Garzik 1359c6fd2807SJeff Garzik /* write out our inc'd consumer index so EDMA knows we're caught up */ 1360c6fd2807SJeff Garzik out_ptr &= EDMA_RSP_Q_BASE_LO_MASK; 1361c6fd2807SJeff Garzik out_ptr |= out_index << EDMA_RSP_Q_PTR_SHIFT; 1362c6fd2807SJeff Garzik writelfl(out_ptr, port_mmio + EDMA_RSP_Q_OUT_PTR_OFS); 1363c6fd2807SJeff Garzik 1364c6fd2807SJeff Garzik /* Return ATA status register for completed CRPB */ 1365c6fd2807SJeff Garzik return ata_status; 1366c6fd2807SJeff Garzik } 1367c6fd2807SJeff Garzik 1368c6fd2807SJeff Garzik /** 1369c6fd2807SJeff Garzik * mv_err_intr - Handle error interrupts on the port 1370c6fd2807SJeff Garzik * @ap: ATA channel to manipulate 1371c6fd2807SJeff Garzik * @reset_allowed: bool: 0 == don't trigger from reset here 1372c6fd2807SJeff Garzik * 1373c6fd2807SJeff Garzik * In most cases, just clear the interrupt and move on. However, 1374c6fd2807SJeff Garzik * some cases require an eDMA reset, which is done right before 1375c6fd2807SJeff Garzik * the COMRESET in mv_phy_reset(). The SERR case requires a 1376c6fd2807SJeff Garzik * clear of pending errors in the SATA SERROR register. Finally, 1377c6fd2807SJeff Garzik * if the port disabled DMA, update our cached copy to match. 1378c6fd2807SJeff Garzik * 1379c6fd2807SJeff Garzik * LOCKING: 1380c6fd2807SJeff Garzik * Inherited from caller. 1381c6fd2807SJeff Garzik */ 1382c6fd2807SJeff Garzik static void mv_err_intr(struct ata_port *ap, int reset_allowed) 1383c6fd2807SJeff Garzik { 1384c6fd2807SJeff Garzik void __iomem *port_mmio = mv_ap_base(ap); 1385c6fd2807SJeff Garzik u32 edma_err_cause, serr = 0; 1386c6fd2807SJeff Garzik 1387c6fd2807SJeff Garzik edma_err_cause = readl(port_mmio + EDMA_ERR_IRQ_CAUSE_OFS); 1388c6fd2807SJeff Garzik 1389c6fd2807SJeff Garzik if (EDMA_ERR_SERR & edma_err_cause) { 1390c6fd2807SJeff Garzik sata_scr_read(ap, SCR_ERROR, &serr); 1391c6fd2807SJeff Garzik sata_scr_write_flush(ap, SCR_ERROR, serr); 1392c6fd2807SJeff Garzik } 1393c6fd2807SJeff Garzik if (EDMA_ERR_SELF_DIS & edma_err_cause) { 1394c6fd2807SJeff Garzik struct mv_port_priv *pp = ap->private_data; 1395c6fd2807SJeff Garzik pp->pp_flags &= ~MV_PP_FLAG_EDMA_EN; 1396c6fd2807SJeff Garzik } 1397c6fd2807SJeff Garzik DPRINTK(KERN_ERR "ata%u: port error; EDMA err cause: 0x%08x " 139844877b4eSTejun Heo "SERR: 0x%08x\n", ap->print_id, edma_err_cause, serr); 1399c6fd2807SJeff Garzik 1400c6fd2807SJeff Garzik /* Clear EDMA now that SERR cleanup done */ 1401c6fd2807SJeff Garzik writelfl(0, port_mmio + EDMA_ERR_IRQ_CAUSE_OFS); 1402c6fd2807SJeff Garzik 1403c6fd2807SJeff Garzik /* check for fatal here and recover if needed */ 1404c6fd2807SJeff Garzik if (reset_allowed && (EDMA_ERR_FATAL & edma_err_cause)) 1405c6fd2807SJeff Garzik mv_stop_and_reset(ap); 1406c6fd2807SJeff Garzik } 1407c6fd2807SJeff Garzik 1408c6fd2807SJeff Garzik /** 1409c6fd2807SJeff Garzik * mv_host_intr - Handle all interrupts on the given host controller 1410cca3974eSJeff Garzik * @host: host specific structure 1411c6fd2807SJeff Garzik * @relevant: port error bits relevant to this host controller 1412c6fd2807SJeff Garzik * @hc: which host controller we're to look at 1413c6fd2807SJeff Garzik * 1414c6fd2807SJeff Garzik * Read then write clear the HC interrupt status then walk each 1415c6fd2807SJeff Garzik * port connected to the HC and see if it needs servicing. Port 1416c6fd2807SJeff Garzik * success ints are reported in the HC interrupt status reg, the 1417c6fd2807SJeff Garzik * port error ints are reported in the higher level main 1418c6fd2807SJeff Garzik * interrupt status register and thus are passed in via the 1419c6fd2807SJeff Garzik * 'relevant' argument. 1420c6fd2807SJeff Garzik * 1421c6fd2807SJeff Garzik * LOCKING: 1422c6fd2807SJeff Garzik * Inherited from caller. 1423c6fd2807SJeff Garzik */ 1424cca3974eSJeff Garzik static void mv_host_intr(struct ata_host *host, u32 relevant, unsigned int hc) 1425c6fd2807SJeff Garzik { 14260d5ff566STejun Heo void __iomem *mmio = host->iomap[MV_PRIMARY_BAR]; 1427c6fd2807SJeff Garzik void __iomem *hc_mmio = mv_hc_base(mmio, hc); 1428c6fd2807SJeff Garzik struct ata_queued_cmd *qc; 1429c6fd2807SJeff Garzik u32 hc_irq_cause; 1430*c5d3e45aSJeff Garzik int port, port0; 1431*c5d3e45aSJeff Garzik int shift, hard_port, handled; 1432c6fd2807SJeff Garzik unsigned int err_mask; 1433c6fd2807SJeff Garzik 143435177265SJeff Garzik if (hc == 0) 1435c6fd2807SJeff Garzik port0 = 0; 143635177265SJeff Garzik else 1437c6fd2807SJeff Garzik port0 = MV_PORTS_PER_HC; 1438c6fd2807SJeff Garzik 1439c6fd2807SJeff Garzik /* we'll need the HC success int register in most cases */ 1440c6fd2807SJeff Garzik hc_irq_cause = readl(hc_mmio + HC_IRQ_CAUSE_OFS); 144135177265SJeff Garzik if (hc_irq_cause) 1442c6fd2807SJeff Garzik writelfl(~hc_irq_cause, hc_mmio + HC_IRQ_CAUSE_OFS); 1443c6fd2807SJeff Garzik 1444c6fd2807SJeff Garzik VPRINTK("ENTER, hc%u relevant=0x%08x HC IRQ cause=0x%08x\n", 1445c6fd2807SJeff Garzik hc,relevant,hc_irq_cause); 1446c6fd2807SJeff Garzik 1447c6fd2807SJeff Garzik for (port = port0; port < port0 + MV_PORTS_PER_HC; port++) { 1448c6fd2807SJeff Garzik u8 ata_status = 0; 1449cca3974eSJeff Garzik struct ata_port *ap = host->ports[port]; 1450c6fd2807SJeff Garzik struct mv_port_priv *pp = ap->private_data; 1451c6fd2807SJeff Garzik 1452c6fd2807SJeff Garzik hard_port = mv_hardport_from_port(port); /* range 0..3 */ 1453c6fd2807SJeff Garzik handled = 0; /* ensure ata_status is set if handled++ */ 1454c6fd2807SJeff Garzik 1455c6fd2807SJeff Garzik /* Note that DEV_IRQ might happen spuriously during EDMA, 1456c6fd2807SJeff Garzik * and should be ignored in such cases. 1457c6fd2807SJeff Garzik * The cause of this is still under investigation. 1458c6fd2807SJeff Garzik */ 1459c6fd2807SJeff Garzik if (pp->pp_flags & MV_PP_FLAG_EDMA_EN) { 1460c6fd2807SJeff Garzik /* EDMA: check for response queue interrupt */ 1461c6fd2807SJeff Garzik if ((CRPB_DMA_DONE << hard_port) & hc_irq_cause) { 1462c6fd2807SJeff Garzik ata_status = mv_get_crpb_status(ap); 1463c6fd2807SJeff Garzik handled = 1; 1464c6fd2807SJeff Garzik } 1465c6fd2807SJeff Garzik } else { 1466c6fd2807SJeff Garzik /* PIO: check for device (drive) interrupt */ 1467c6fd2807SJeff Garzik if ((DEV_IRQ << hard_port) & hc_irq_cause) { 14680d5ff566STejun Heo ata_status = readb(ap->ioaddr.status_addr); 1469c6fd2807SJeff Garzik handled = 1; 1470c6fd2807SJeff Garzik /* ignore spurious intr if drive still BUSY */ 1471c6fd2807SJeff Garzik if (ata_status & ATA_BUSY) { 1472c6fd2807SJeff Garzik ata_status = 0; 1473c6fd2807SJeff Garzik handled = 0; 1474c6fd2807SJeff Garzik } 1475c6fd2807SJeff Garzik } 1476c6fd2807SJeff Garzik } 1477c6fd2807SJeff Garzik 1478c6fd2807SJeff Garzik if (ap && (ap->flags & ATA_FLAG_DISABLED)) 1479c6fd2807SJeff Garzik continue; 1480c6fd2807SJeff Garzik 1481c6fd2807SJeff Garzik err_mask = ac_err_mask(ata_status); 1482c6fd2807SJeff Garzik 1483c6fd2807SJeff Garzik shift = port << 1; /* (port * 2) */ 1484c6fd2807SJeff Garzik if (port >= MV_PORTS_PER_HC) { 1485c6fd2807SJeff Garzik shift++; /* skip bit 8 in the HC Main IRQ reg */ 1486c6fd2807SJeff Garzik } 1487c6fd2807SJeff Garzik if ((PORT0_ERR << shift) & relevant) { 1488c6fd2807SJeff Garzik mv_err_intr(ap, 1); 1489c6fd2807SJeff Garzik err_mask |= AC_ERR_OTHER; 1490c6fd2807SJeff Garzik handled = 1; 1491c6fd2807SJeff Garzik } 1492c6fd2807SJeff Garzik 1493c6fd2807SJeff Garzik if (handled) { 1494c6fd2807SJeff Garzik qc = ata_qc_from_tag(ap, ap->active_tag); 1495c6fd2807SJeff Garzik if (qc && (qc->flags & ATA_QCFLAG_ACTIVE)) { 1496c6fd2807SJeff Garzik VPRINTK("port %u IRQ found for qc, " 1497c6fd2807SJeff Garzik "ata_status 0x%x\n", port,ata_status); 1498c6fd2807SJeff Garzik /* mark qc status appropriately */ 1499c6fd2807SJeff Garzik if (!(qc->tf.flags & ATA_TFLAG_POLLING)) { 1500c6fd2807SJeff Garzik qc->err_mask |= err_mask; 1501c6fd2807SJeff Garzik ata_qc_complete(qc); 1502c6fd2807SJeff Garzik } 1503c6fd2807SJeff Garzik } 1504c6fd2807SJeff Garzik } 1505c6fd2807SJeff Garzik } 1506c6fd2807SJeff Garzik VPRINTK("EXIT\n"); 1507c6fd2807SJeff Garzik } 1508c6fd2807SJeff Garzik 1509c6fd2807SJeff Garzik /** 1510*c5d3e45aSJeff Garzik * mv_interrupt - Main interrupt event handler 1511c6fd2807SJeff Garzik * @irq: unused 1512c6fd2807SJeff Garzik * @dev_instance: private data; in this case the host structure 1513c6fd2807SJeff Garzik * 1514c6fd2807SJeff Garzik * Read the read only register to determine if any host 1515c6fd2807SJeff Garzik * controllers have pending interrupts. If so, call lower level 1516c6fd2807SJeff Garzik * routine to handle. Also check for PCI errors which are only 1517c6fd2807SJeff Garzik * reported here. 1518c6fd2807SJeff Garzik * 1519c6fd2807SJeff Garzik * LOCKING: 1520cca3974eSJeff Garzik * This routine holds the host lock while processing pending 1521c6fd2807SJeff Garzik * interrupts. 1522c6fd2807SJeff Garzik */ 15237d12e780SDavid Howells static irqreturn_t mv_interrupt(int irq, void *dev_instance) 1524c6fd2807SJeff Garzik { 1525cca3974eSJeff Garzik struct ata_host *host = dev_instance; 1526c6fd2807SJeff Garzik unsigned int hc, handled = 0, n_hcs; 15270d5ff566STejun Heo void __iomem *mmio = host->iomap[MV_PRIMARY_BAR]; 1528c6fd2807SJeff Garzik struct mv_host_priv *hpriv; 1529c6fd2807SJeff Garzik u32 irq_stat; 1530c6fd2807SJeff Garzik 1531c6fd2807SJeff Garzik irq_stat = readl(mmio + HC_MAIN_IRQ_CAUSE_OFS); 1532c6fd2807SJeff Garzik 1533c6fd2807SJeff Garzik /* check the cases where we either have nothing pending or have read 1534c6fd2807SJeff Garzik * a bogus register value which can indicate HW removal or PCI fault 1535c6fd2807SJeff Garzik */ 153635177265SJeff Garzik if (!irq_stat || (0xffffffffU == irq_stat)) 1537c6fd2807SJeff Garzik return IRQ_NONE; 1538c6fd2807SJeff Garzik 1539cca3974eSJeff Garzik n_hcs = mv_get_hc_count(host->ports[0]->flags); 1540cca3974eSJeff Garzik spin_lock(&host->lock); 1541c6fd2807SJeff Garzik 1542c6fd2807SJeff Garzik for (hc = 0; hc < n_hcs; hc++) { 1543c6fd2807SJeff Garzik u32 relevant = irq_stat & (HC0_IRQ_PEND << (hc * HC_SHIFT)); 1544c6fd2807SJeff Garzik if (relevant) { 1545cca3974eSJeff Garzik mv_host_intr(host, relevant, hc); 1546c6fd2807SJeff Garzik handled++; 1547c6fd2807SJeff Garzik } 1548c6fd2807SJeff Garzik } 1549c6fd2807SJeff Garzik 1550cca3974eSJeff Garzik hpriv = host->private_data; 1551c6fd2807SJeff Garzik if (IS_60XX(hpriv)) { 1552c6fd2807SJeff Garzik /* deal with the interrupt coalescing bits */ 1553c6fd2807SJeff Garzik if (irq_stat & (TRAN_LO_DONE | TRAN_HI_DONE | PORTS_0_7_COAL_DONE)) { 1554c6fd2807SJeff Garzik writelfl(0, mmio + MV_IRQ_COAL_CAUSE_LO); 1555c6fd2807SJeff Garzik writelfl(0, mmio + MV_IRQ_COAL_CAUSE_HI); 1556c6fd2807SJeff Garzik writelfl(0, mmio + MV_IRQ_COAL_CAUSE); 1557c6fd2807SJeff Garzik } 1558c6fd2807SJeff Garzik } 1559c6fd2807SJeff Garzik 1560c6fd2807SJeff Garzik if (PCI_ERR & irq_stat) { 1561c6fd2807SJeff Garzik printk(KERN_ERR DRV_NAME ": PCI ERROR; PCI IRQ cause=0x%08x\n", 1562c6fd2807SJeff Garzik readl(mmio + PCI_IRQ_CAUSE_OFS)); 1563c6fd2807SJeff Garzik 1564c6fd2807SJeff Garzik DPRINTK("All regs @ PCI error\n"); 1565cca3974eSJeff Garzik mv_dump_all_regs(mmio, -1, to_pci_dev(host->dev)); 1566c6fd2807SJeff Garzik 1567c6fd2807SJeff Garzik writelfl(0, mmio + PCI_IRQ_CAUSE_OFS); 1568c6fd2807SJeff Garzik handled++; 1569c6fd2807SJeff Garzik } 1570cca3974eSJeff Garzik spin_unlock(&host->lock); 1571c6fd2807SJeff Garzik 1572c6fd2807SJeff Garzik return IRQ_RETVAL(handled); 1573c6fd2807SJeff Garzik } 1574c6fd2807SJeff Garzik 1575c6fd2807SJeff Garzik static void __iomem *mv5_phy_base(void __iomem *mmio, unsigned int port) 1576c6fd2807SJeff Garzik { 1577c6fd2807SJeff Garzik void __iomem *hc_mmio = mv_hc_base_from_port(mmio, port); 1578c6fd2807SJeff Garzik unsigned long ofs = (mv_hardport_from_port(port) + 1) * 0x100UL; 1579c6fd2807SJeff Garzik 1580c6fd2807SJeff Garzik return hc_mmio + ofs; 1581c6fd2807SJeff Garzik } 1582c6fd2807SJeff Garzik 1583c6fd2807SJeff Garzik static unsigned int mv5_scr_offset(unsigned int sc_reg_in) 1584c6fd2807SJeff Garzik { 1585c6fd2807SJeff Garzik unsigned int ofs; 1586c6fd2807SJeff Garzik 1587c6fd2807SJeff Garzik switch (sc_reg_in) { 1588c6fd2807SJeff Garzik case SCR_STATUS: 1589c6fd2807SJeff Garzik case SCR_ERROR: 1590c6fd2807SJeff Garzik case SCR_CONTROL: 1591c6fd2807SJeff Garzik ofs = sc_reg_in * sizeof(u32); 1592c6fd2807SJeff Garzik break; 1593c6fd2807SJeff Garzik default: 1594c6fd2807SJeff Garzik ofs = 0xffffffffU; 1595c6fd2807SJeff Garzik break; 1596c6fd2807SJeff Garzik } 1597c6fd2807SJeff Garzik return ofs; 1598c6fd2807SJeff Garzik } 1599c6fd2807SJeff Garzik 1600c6fd2807SJeff Garzik static u32 mv5_scr_read(struct ata_port *ap, unsigned int sc_reg_in) 1601c6fd2807SJeff Garzik { 16020d5ff566STejun Heo void __iomem *mmio = ap->host->iomap[MV_PRIMARY_BAR]; 16030d5ff566STejun Heo void __iomem *addr = mv5_phy_base(mmio, ap->port_no); 1604c6fd2807SJeff Garzik unsigned int ofs = mv5_scr_offset(sc_reg_in); 1605c6fd2807SJeff Garzik 1606c6fd2807SJeff Garzik if (ofs != 0xffffffffU) 16070d5ff566STejun Heo return readl(addr + ofs); 1608c6fd2807SJeff Garzik else 1609c6fd2807SJeff Garzik return (u32) ofs; 1610c6fd2807SJeff Garzik } 1611c6fd2807SJeff Garzik 1612c6fd2807SJeff Garzik static void mv5_scr_write(struct ata_port *ap, unsigned int sc_reg_in, u32 val) 1613c6fd2807SJeff Garzik { 16140d5ff566STejun Heo void __iomem *mmio = ap->host->iomap[MV_PRIMARY_BAR]; 16150d5ff566STejun Heo void __iomem *addr = mv5_phy_base(mmio, ap->port_no); 1616c6fd2807SJeff Garzik unsigned int ofs = mv5_scr_offset(sc_reg_in); 1617c6fd2807SJeff Garzik 1618c6fd2807SJeff Garzik if (ofs != 0xffffffffU) 16190d5ff566STejun Heo writelfl(val, addr + ofs); 1620c6fd2807SJeff Garzik } 1621c6fd2807SJeff Garzik 1622c6fd2807SJeff Garzik static void mv5_reset_bus(struct pci_dev *pdev, void __iomem *mmio) 1623c6fd2807SJeff Garzik { 1624c6fd2807SJeff Garzik u8 rev_id; 1625c6fd2807SJeff Garzik int early_5080; 1626c6fd2807SJeff Garzik 1627c6fd2807SJeff Garzik pci_read_config_byte(pdev, PCI_REVISION_ID, &rev_id); 1628c6fd2807SJeff Garzik 1629c6fd2807SJeff Garzik early_5080 = (pdev->device == 0x5080) && (rev_id == 0); 1630c6fd2807SJeff Garzik 1631c6fd2807SJeff Garzik if (!early_5080) { 1632c6fd2807SJeff Garzik u32 tmp = readl(mmio + MV_PCI_EXP_ROM_BAR_CTL); 1633c6fd2807SJeff Garzik tmp |= (1 << 0); 1634c6fd2807SJeff Garzik writel(tmp, mmio + MV_PCI_EXP_ROM_BAR_CTL); 1635c6fd2807SJeff Garzik } 1636c6fd2807SJeff Garzik 1637c6fd2807SJeff Garzik mv_reset_pci_bus(pdev, mmio); 1638c6fd2807SJeff Garzik } 1639c6fd2807SJeff Garzik 1640c6fd2807SJeff Garzik static void mv5_reset_flash(struct mv_host_priv *hpriv, void __iomem *mmio) 1641c6fd2807SJeff Garzik { 1642c6fd2807SJeff Garzik writel(0x0fcfffff, mmio + MV_FLASH_CTL); 1643c6fd2807SJeff Garzik } 1644c6fd2807SJeff Garzik 1645c6fd2807SJeff Garzik static void mv5_read_preamp(struct mv_host_priv *hpriv, int idx, 1646c6fd2807SJeff Garzik void __iomem *mmio) 1647c6fd2807SJeff Garzik { 1648c6fd2807SJeff Garzik void __iomem *phy_mmio = mv5_phy_base(mmio, idx); 1649c6fd2807SJeff Garzik u32 tmp; 1650c6fd2807SJeff Garzik 1651c6fd2807SJeff Garzik tmp = readl(phy_mmio + MV5_PHY_MODE); 1652c6fd2807SJeff Garzik 1653c6fd2807SJeff Garzik hpriv->signal[idx].pre = tmp & 0x1800; /* bits 12:11 */ 1654c6fd2807SJeff Garzik hpriv->signal[idx].amps = tmp & 0xe0; /* bits 7:5 */ 1655c6fd2807SJeff Garzik } 1656c6fd2807SJeff Garzik 1657c6fd2807SJeff Garzik static void mv5_enable_leds(struct mv_host_priv *hpriv, void __iomem *mmio) 1658c6fd2807SJeff Garzik { 1659c6fd2807SJeff Garzik u32 tmp; 1660c6fd2807SJeff Garzik 1661c6fd2807SJeff Garzik writel(0, mmio + MV_GPIO_PORT_CTL); 1662c6fd2807SJeff Garzik 1663c6fd2807SJeff Garzik /* FIXME: handle MV_HP_ERRATA_50XXB2 errata */ 1664c6fd2807SJeff Garzik 1665c6fd2807SJeff Garzik tmp = readl(mmio + MV_PCI_EXP_ROM_BAR_CTL); 1666c6fd2807SJeff Garzik tmp |= ~(1 << 0); 1667c6fd2807SJeff Garzik writel(tmp, mmio + MV_PCI_EXP_ROM_BAR_CTL); 1668c6fd2807SJeff Garzik } 1669c6fd2807SJeff Garzik 1670c6fd2807SJeff Garzik static void mv5_phy_errata(struct mv_host_priv *hpriv, void __iomem *mmio, 1671c6fd2807SJeff Garzik unsigned int port) 1672c6fd2807SJeff Garzik { 1673c6fd2807SJeff Garzik void __iomem *phy_mmio = mv5_phy_base(mmio, port); 1674c6fd2807SJeff Garzik const u32 mask = (1<<12) | (1<<11) | (1<<7) | (1<<6) | (1<<5); 1675c6fd2807SJeff Garzik u32 tmp; 1676c6fd2807SJeff Garzik int fix_apm_sq = (hpriv->hp_flags & MV_HP_ERRATA_50XXB0); 1677c6fd2807SJeff Garzik 1678c6fd2807SJeff Garzik if (fix_apm_sq) { 1679c6fd2807SJeff Garzik tmp = readl(phy_mmio + MV5_LT_MODE); 1680c6fd2807SJeff Garzik tmp |= (1 << 19); 1681c6fd2807SJeff Garzik writel(tmp, phy_mmio + MV5_LT_MODE); 1682c6fd2807SJeff Garzik 1683c6fd2807SJeff Garzik tmp = readl(phy_mmio + MV5_PHY_CTL); 1684c6fd2807SJeff Garzik tmp &= ~0x3; 1685c6fd2807SJeff Garzik tmp |= 0x1; 1686c6fd2807SJeff Garzik writel(tmp, phy_mmio + MV5_PHY_CTL); 1687c6fd2807SJeff Garzik } 1688c6fd2807SJeff Garzik 1689c6fd2807SJeff Garzik tmp = readl(phy_mmio + MV5_PHY_MODE); 1690c6fd2807SJeff Garzik tmp &= ~mask; 1691c6fd2807SJeff Garzik tmp |= hpriv->signal[port].pre; 1692c6fd2807SJeff Garzik tmp |= hpriv->signal[port].amps; 1693c6fd2807SJeff Garzik writel(tmp, phy_mmio + MV5_PHY_MODE); 1694c6fd2807SJeff Garzik } 1695c6fd2807SJeff Garzik 1696c6fd2807SJeff Garzik 1697c6fd2807SJeff Garzik #undef ZERO 1698c6fd2807SJeff Garzik #define ZERO(reg) writel(0, port_mmio + (reg)) 1699c6fd2807SJeff Garzik static void mv5_reset_hc_port(struct mv_host_priv *hpriv, void __iomem *mmio, 1700c6fd2807SJeff Garzik unsigned int port) 1701c6fd2807SJeff Garzik { 1702c6fd2807SJeff Garzik void __iomem *port_mmio = mv_port_base(mmio, port); 1703c6fd2807SJeff Garzik 1704c6fd2807SJeff Garzik writelfl(EDMA_DS, port_mmio + EDMA_CMD_OFS); 1705c6fd2807SJeff Garzik 1706c6fd2807SJeff Garzik mv_channel_reset(hpriv, mmio, port); 1707c6fd2807SJeff Garzik 1708c6fd2807SJeff Garzik ZERO(0x028); /* command */ 1709c6fd2807SJeff Garzik writel(0x11f, port_mmio + EDMA_CFG_OFS); 1710c6fd2807SJeff Garzik ZERO(0x004); /* timer */ 1711c6fd2807SJeff Garzik ZERO(0x008); /* irq err cause */ 1712c6fd2807SJeff Garzik ZERO(0x00c); /* irq err mask */ 1713c6fd2807SJeff Garzik ZERO(0x010); /* rq bah */ 1714c6fd2807SJeff Garzik ZERO(0x014); /* rq inp */ 1715c6fd2807SJeff Garzik ZERO(0x018); /* rq outp */ 1716c6fd2807SJeff Garzik ZERO(0x01c); /* respq bah */ 1717c6fd2807SJeff Garzik ZERO(0x024); /* respq outp */ 1718c6fd2807SJeff Garzik ZERO(0x020); /* respq inp */ 1719c6fd2807SJeff Garzik ZERO(0x02c); /* test control */ 1720c6fd2807SJeff Garzik writel(0xbc, port_mmio + EDMA_IORDY_TMOUT); 1721c6fd2807SJeff Garzik } 1722c6fd2807SJeff Garzik #undef ZERO 1723c6fd2807SJeff Garzik 1724c6fd2807SJeff Garzik #define ZERO(reg) writel(0, hc_mmio + (reg)) 1725c6fd2807SJeff Garzik static void mv5_reset_one_hc(struct mv_host_priv *hpriv, void __iomem *mmio, 1726c6fd2807SJeff Garzik unsigned int hc) 1727c6fd2807SJeff Garzik { 1728c6fd2807SJeff Garzik void __iomem *hc_mmio = mv_hc_base(mmio, hc); 1729c6fd2807SJeff Garzik u32 tmp; 1730c6fd2807SJeff Garzik 1731c6fd2807SJeff Garzik ZERO(0x00c); 1732c6fd2807SJeff Garzik ZERO(0x010); 1733c6fd2807SJeff Garzik ZERO(0x014); 1734c6fd2807SJeff Garzik ZERO(0x018); 1735c6fd2807SJeff Garzik 1736c6fd2807SJeff Garzik tmp = readl(hc_mmio + 0x20); 1737c6fd2807SJeff Garzik tmp &= 0x1c1c1c1c; 1738c6fd2807SJeff Garzik tmp |= 0x03030303; 1739c6fd2807SJeff Garzik writel(tmp, hc_mmio + 0x20); 1740c6fd2807SJeff Garzik } 1741c6fd2807SJeff Garzik #undef ZERO 1742c6fd2807SJeff Garzik 1743c6fd2807SJeff Garzik static int mv5_reset_hc(struct mv_host_priv *hpriv, void __iomem *mmio, 1744c6fd2807SJeff Garzik unsigned int n_hc) 1745c6fd2807SJeff Garzik { 1746c6fd2807SJeff Garzik unsigned int hc, port; 1747c6fd2807SJeff Garzik 1748c6fd2807SJeff Garzik for (hc = 0; hc < n_hc; hc++) { 1749c6fd2807SJeff Garzik for (port = 0; port < MV_PORTS_PER_HC; port++) 1750c6fd2807SJeff Garzik mv5_reset_hc_port(hpriv, mmio, 1751c6fd2807SJeff Garzik (hc * MV_PORTS_PER_HC) + port); 1752c6fd2807SJeff Garzik 1753c6fd2807SJeff Garzik mv5_reset_one_hc(hpriv, mmio, hc); 1754c6fd2807SJeff Garzik } 1755c6fd2807SJeff Garzik 1756c6fd2807SJeff Garzik return 0; 1757c6fd2807SJeff Garzik } 1758c6fd2807SJeff Garzik 1759c6fd2807SJeff Garzik #undef ZERO 1760c6fd2807SJeff Garzik #define ZERO(reg) writel(0, mmio + (reg)) 1761c6fd2807SJeff Garzik static void mv_reset_pci_bus(struct pci_dev *pdev, void __iomem *mmio) 1762c6fd2807SJeff Garzik { 1763c6fd2807SJeff Garzik u32 tmp; 1764c6fd2807SJeff Garzik 1765c6fd2807SJeff Garzik tmp = readl(mmio + MV_PCI_MODE); 1766c6fd2807SJeff Garzik tmp &= 0xff00ffff; 1767c6fd2807SJeff Garzik writel(tmp, mmio + MV_PCI_MODE); 1768c6fd2807SJeff Garzik 1769c6fd2807SJeff Garzik ZERO(MV_PCI_DISC_TIMER); 1770c6fd2807SJeff Garzik ZERO(MV_PCI_MSI_TRIGGER); 1771c6fd2807SJeff Garzik writel(0x000100ff, mmio + MV_PCI_XBAR_TMOUT); 1772c6fd2807SJeff Garzik ZERO(HC_MAIN_IRQ_MASK_OFS); 1773c6fd2807SJeff Garzik ZERO(MV_PCI_SERR_MASK); 1774c6fd2807SJeff Garzik ZERO(PCI_IRQ_CAUSE_OFS); 1775c6fd2807SJeff Garzik ZERO(PCI_IRQ_MASK_OFS); 1776c6fd2807SJeff Garzik ZERO(MV_PCI_ERR_LOW_ADDRESS); 1777c6fd2807SJeff Garzik ZERO(MV_PCI_ERR_HIGH_ADDRESS); 1778c6fd2807SJeff Garzik ZERO(MV_PCI_ERR_ATTRIBUTE); 1779c6fd2807SJeff Garzik ZERO(MV_PCI_ERR_COMMAND); 1780c6fd2807SJeff Garzik } 1781c6fd2807SJeff Garzik #undef ZERO 1782c6fd2807SJeff Garzik 1783c6fd2807SJeff Garzik static void mv6_reset_flash(struct mv_host_priv *hpriv, void __iomem *mmio) 1784c6fd2807SJeff Garzik { 1785c6fd2807SJeff Garzik u32 tmp; 1786c6fd2807SJeff Garzik 1787c6fd2807SJeff Garzik mv5_reset_flash(hpriv, mmio); 1788c6fd2807SJeff Garzik 1789c6fd2807SJeff Garzik tmp = readl(mmio + MV_GPIO_PORT_CTL); 1790c6fd2807SJeff Garzik tmp &= 0x3; 1791c6fd2807SJeff Garzik tmp |= (1 << 5) | (1 << 6); 1792c6fd2807SJeff Garzik writel(tmp, mmio + MV_GPIO_PORT_CTL); 1793c6fd2807SJeff Garzik } 1794c6fd2807SJeff Garzik 1795c6fd2807SJeff Garzik /** 1796c6fd2807SJeff Garzik * mv6_reset_hc - Perform the 6xxx global soft reset 1797c6fd2807SJeff Garzik * @mmio: base address of the HBA 1798c6fd2807SJeff Garzik * 1799c6fd2807SJeff Garzik * This routine only applies to 6xxx parts. 1800c6fd2807SJeff Garzik * 1801c6fd2807SJeff Garzik * LOCKING: 1802c6fd2807SJeff Garzik * Inherited from caller. 1803c6fd2807SJeff Garzik */ 1804c6fd2807SJeff Garzik static int mv6_reset_hc(struct mv_host_priv *hpriv, void __iomem *mmio, 1805c6fd2807SJeff Garzik unsigned int n_hc) 1806c6fd2807SJeff Garzik { 1807c6fd2807SJeff Garzik void __iomem *reg = mmio + PCI_MAIN_CMD_STS_OFS; 1808c6fd2807SJeff Garzik int i, rc = 0; 1809c6fd2807SJeff Garzik u32 t; 1810c6fd2807SJeff Garzik 1811c6fd2807SJeff Garzik /* Following procedure defined in PCI "main command and status 1812c6fd2807SJeff Garzik * register" table. 1813c6fd2807SJeff Garzik */ 1814c6fd2807SJeff Garzik t = readl(reg); 1815c6fd2807SJeff Garzik writel(t | STOP_PCI_MASTER, reg); 1816c6fd2807SJeff Garzik 1817c6fd2807SJeff Garzik for (i = 0; i < 1000; i++) { 1818c6fd2807SJeff Garzik udelay(1); 1819c6fd2807SJeff Garzik t = readl(reg); 1820c6fd2807SJeff Garzik if (PCI_MASTER_EMPTY & t) { 1821c6fd2807SJeff Garzik break; 1822c6fd2807SJeff Garzik } 1823c6fd2807SJeff Garzik } 1824c6fd2807SJeff Garzik if (!(PCI_MASTER_EMPTY & t)) { 1825c6fd2807SJeff Garzik printk(KERN_ERR DRV_NAME ": PCI master won't flush\n"); 1826c6fd2807SJeff Garzik rc = 1; 1827c6fd2807SJeff Garzik goto done; 1828c6fd2807SJeff Garzik } 1829c6fd2807SJeff Garzik 1830c6fd2807SJeff Garzik /* set reset */ 1831c6fd2807SJeff Garzik i = 5; 1832c6fd2807SJeff Garzik do { 1833c6fd2807SJeff Garzik writel(t | GLOB_SFT_RST, reg); 1834c6fd2807SJeff Garzik t = readl(reg); 1835c6fd2807SJeff Garzik udelay(1); 1836c6fd2807SJeff Garzik } while (!(GLOB_SFT_RST & t) && (i-- > 0)); 1837c6fd2807SJeff Garzik 1838c6fd2807SJeff Garzik if (!(GLOB_SFT_RST & t)) { 1839c6fd2807SJeff Garzik printk(KERN_ERR DRV_NAME ": can't set global reset\n"); 1840c6fd2807SJeff Garzik rc = 1; 1841c6fd2807SJeff Garzik goto done; 1842c6fd2807SJeff Garzik } 1843c6fd2807SJeff Garzik 1844c6fd2807SJeff Garzik /* clear reset and *reenable the PCI master* (not mentioned in spec) */ 1845c6fd2807SJeff Garzik i = 5; 1846c6fd2807SJeff Garzik do { 1847c6fd2807SJeff Garzik writel(t & ~(GLOB_SFT_RST | STOP_PCI_MASTER), reg); 1848c6fd2807SJeff Garzik t = readl(reg); 1849c6fd2807SJeff Garzik udelay(1); 1850c6fd2807SJeff Garzik } while ((GLOB_SFT_RST & t) && (i-- > 0)); 1851c6fd2807SJeff Garzik 1852c6fd2807SJeff Garzik if (GLOB_SFT_RST & t) { 1853c6fd2807SJeff Garzik printk(KERN_ERR DRV_NAME ": can't clear global reset\n"); 1854c6fd2807SJeff Garzik rc = 1; 1855c6fd2807SJeff Garzik } 1856c6fd2807SJeff Garzik done: 1857c6fd2807SJeff Garzik return rc; 1858c6fd2807SJeff Garzik } 1859c6fd2807SJeff Garzik 1860c6fd2807SJeff Garzik static void mv6_read_preamp(struct mv_host_priv *hpriv, int idx, 1861c6fd2807SJeff Garzik void __iomem *mmio) 1862c6fd2807SJeff Garzik { 1863c6fd2807SJeff Garzik void __iomem *port_mmio; 1864c6fd2807SJeff Garzik u32 tmp; 1865c6fd2807SJeff Garzik 1866c6fd2807SJeff Garzik tmp = readl(mmio + MV_RESET_CFG); 1867c6fd2807SJeff Garzik if ((tmp & (1 << 0)) == 0) { 1868c6fd2807SJeff Garzik hpriv->signal[idx].amps = 0x7 << 8; 1869c6fd2807SJeff Garzik hpriv->signal[idx].pre = 0x1 << 5; 1870c6fd2807SJeff Garzik return; 1871c6fd2807SJeff Garzik } 1872c6fd2807SJeff Garzik 1873c6fd2807SJeff Garzik port_mmio = mv_port_base(mmio, idx); 1874c6fd2807SJeff Garzik tmp = readl(port_mmio + PHY_MODE2); 1875c6fd2807SJeff Garzik 1876c6fd2807SJeff Garzik hpriv->signal[idx].amps = tmp & 0x700; /* bits 10:8 */ 1877c6fd2807SJeff Garzik hpriv->signal[idx].pre = tmp & 0xe0; /* bits 7:5 */ 1878c6fd2807SJeff Garzik } 1879c6fd2807SJeff Garzik 1880c6fd2807SJeff Garzik static void mv6_enable_leds(struct mv_host_priv *hpriv, void __iomem *mmio) 1881c6fd2807SJeff Garzik { 1882c6fd2807SJeff Garzik writel(0x00000060, mmio + MV_GPIO_PORT_CTL); 1883c6fd2807SJeff Garzik } 1884c6fd2807SJeff Garzik 1885c6fd2807SJeff Garzik static void mv6_phy_errata(struct mv_host_priv *hpriv, void __iomem *mmio, 1886c6fd2807SJeff Garzik unsigned int port) 1887c6fd2807SJeff Garzik { 1888c6fd2807SJeff Garzik void __iomem *port_mmio = mv_port_base(mmio, port); 1889c6fd2807SJeff Garzik 1890c6fd2807SJeff Garzik u32 hp_flags = hpriv->hp_flags; 1891c6fd2807SJeff Garzik int fix_phy_mode2 = 1892c6fd2807SJeff Garzik hp_flags & (MV_HP_ERRATA_60X1B2 | MV_HP_ERRATA_60X1C0); 1893c6fd2807SJeff Garzik int fix_phy_mode4 = 1894c6fd2807SJeff Garzik hp_flags & (MV_HP_ERRATA_60X1B2 | MV_HP_ERRATA_60X1C0); 1895c6fd2807SJeff Garzik u32 m2, tmp; 1896c6fd2807SJeff Garzik 1897c6fd2807SJeff Garzik if (fix_phy_mode2) { 1898c6fd2807SJeff Garzik m2 = readl(port_mmio + PHY_MODE2); 1899c6fd2807SJeff Garzik m2 &= ~(1 << 16); 1900c6fd2807SJeff Garzik m2 |= (1 << 31); 1901c6fd2807SJeff Garzik writel(m2, port_mmio + PHY_MODE2); 1902c6fd2807SJeff Garzik 1903c6fd2807SJeff Garzik udelay(200); 1904c6fd2807SJeff Garzik 1905c6fd2807SJeff Garzik m2 = readl(port_mmio + PHY_MODE2); 1906c6fd2807SJeff Garzik m2 &= ~((1 << 16) | (1 << 31)); 1907c6fd2807SJeff Garzik writel(m2, port_mmio + PHY_MODE2); 1908c6fd2807SJeff Garzik 1909c6fd2807SJeff Garzik udelay(200); 1910c6fd2807SJeff Garzik } 1911c6fd2807SJeff Garzik 1912c6fd2807SJeff Garzik /* who knows what this magic does */ 1913c6fd2807SJeff Garzik tmp = readl(port_mmio + PHY_MODE3); 1914c6fd2807SJeff Garzik tmp &= ~0x7F800000; 1915c6fd2807SJeff Garzik tmp |= 0x2A800000; 1916c6fd2807SJeff Garzik writel(tmp, port_mmio + PHY_MODE3); 1917c6fd2807SJeff Garzik 1918c6fd2807SJeff Garzik if (fix_phy_mode4) { 1919c6fd2807SJeff Garzik u32 m4; 1920c6fd2807SJeff Garzik 1921c6fd2807SJeff Garzik m4 = readl(port_mmio + PHY_MODE4); 1922c6fd2807SJeff Garzik 1923c6fd2807SJeff Garzik if (hp_flags & MV_HP_ERRATA_60X1B2) 1924c6fd2807SJeff Garzik tmp = readl(port_mmio + 0x310); 1925c6fd2807SJeff Garzik 1926c6fd2807SJeff Garzik m4 = (m4 & ~(1 << 1)) | (1 << 0); 1927c6fd2807SJeff Garzik 1928c6fd2807SJeff Garzik writel(m4, port_mmio + PHY_MODE4); 1929c6fd2807SJeff Garzik 1930c6fd2807SJeff Garzik if (hp_flags & MV_HP_ERRATA_60X1B2) 1931c6fd2807SJeff Garzik writel(tmp, port_mmio + 0x310); 1932c6fd2807SJeff Garzik } 1933c6fd2807SJeff Garzik 1934c6fd2807SJeff Garzik /* Revert values of pre-emphasis and signal amps to the saved ones */ 1935c6fd2807SJeff Garzik m2 = readl(port_mmio + PHY_MODE2); 1936c6fd2807SJeff Garzik 1937c6fd2807SJeff Garzik m2 &= ~MV_M2_PREAMP_MASK; 1938c6fd2807SJeff Garzik m2 |= hpriv->signal[port].amps; 1939c6fd2807SJeff Garzik m2 |= hpriv->signal[port].pre; 1940c6fd2807SJeff Garzik m2 &= ~(1 << 16); 1941c6fd2807SJeff Garzik 1942c6fd2807SJeff Garzik /* according to mvSata 3.6.1, some IIE values are fixed */ 1943c6fd2807SJeff Garzik if (IS_GEN_IIE(hpriv)) { 1944c6fd2807SJeff Garzik m2 &= ~0xC30FF01F; 1945c6fd2807SJeff Garzik m2 |= 0x0000900F; 1946c6fd2807SJeff Garzik } 1947c6fd2807SJeff Garzik 1948c6fd2807SJeff Garzik writel(m2, port_mmio + PHY_MODE2); 1949c6fd2807SJeff Garzik } 1950c6fd2807SJeff Garzik 1951c6fd2807SJeff Garzik static void mv_channel_reset(struct mv_host_priv *hpriv, void __iomem *mmio, 1952c6fd2807SJeff Garzik unsigned int port_no) 1953c6fd2807SJeff Garzik { 1954c6fd2807SJeff Garzik void __iomem *port_mmio = mv_port_base(mmio, port_no); 1955c6fd2807SJeff Garzik 1956c6fd2807SJeff Garzik writelfl(ATA_RST, port_mmio + EDMA_CMD_OFS); 1957c6fd2807SJeff Garzik 1958c6fd2807SJeff Garzik if (IS_60XX(hpriv)) { 1959c6fd2807SJeff Garzik u32 ifctl = readl(port_mmio + SATA_INTERFACE_CTL); 1960c6fd2807SJeff Garzik ifctl |= (1 << 7); /* enable gen2i speed */ 1961c6fd2807SJeff Garzik ifctl = (ifctl & 0xfff) | 0x9b1000; /* from chip spec */ 1962c6fd2807SJeff Garzik writelfl(ifctl, port_mmio + SATA_INTERFACE_CTL); 1963c6fd2807SJeff Garzik } 1964c6fd2807SJeff Garzik 1965c6fd2807SJeff Garzik udelay(25); /* allow reset propagation */ 1966c6fd2807SJeff Garzik 1967c6fd2807SJeff Garzik /* Spec never mentions clearing the bit. Marvell's driver does 1968c6fd2807SJeff Garzik * clear the bit, however. 1969c6fd2807SJeff Garzik */ 1970c6fd2807SJeff Garzik writelfl(0, port_mmio + EDMA_CMD_OFS); 1971c6fd2807SJeff Garzik 1972c6fd2807SJeff Garzik hpriv->ops->phy_errata(hpriv, mmio, port_no); 1973c6fd2807SJeff Garzik 1974c6fd2807SJeff Garzik if (IS_50XX(hpriv)) 1975c6fd2807SJeff Garzik mdelay(1); 1976c6fd2807SJeff Garzik } 1977c6fd2807SJeff Garzik 1978c6fd2807SJeff Garzik static void mv_stop_and_reset(struct ata_port *ap) 1979c6fd2807SJeff Garzik { 1980cca3974eSJeff Garzik struct mv_host_priv *hpriv = ap->host->private_data; 19810d5ff566STejun Heo void __iomem *mmio = ap->host->iomap[MV_PRIMARY_BAR]; 1982c6fd2807SJeff Garzik 1983c6fd2807SJeff Garzik mv_stop_dma(ap); 1984c6fd2807SJeff Garzik 1985c6fd2807SJeff Garzik mv_channel_reset(hpriv, mmio, ap->port_no); 1986c6fd2807SJeff Garzik 1987c6fd2807SJeff Garzik __mv_phy_reset(ap, 0); 1988c6fd2807SJeff Garzik } 1989c6fd2807SJeff Garzik 1990c6fd2807SJeff Garzik static inline void __msleep(unsigned int msec, int can_sleep) 1991c6fd2807SJeff Garzik { 1992c6fd2807SJeff Garzik if (can_sleep) 1993c6fd2807SJeff Garzik msleep(msec); 1994c6fd2807SJeff Garzik else 1995c6fd2807SJeff Garzik mdelay(msec); 1996c6fd2807SJeff Garzik } 1997c6fd2807SJeff Garzik 1998c6fd2807SJeff Garzik /** 1999c6fd2807SJeff Garzik * __mv_phy_reset - Perform eDMA reset followed by COMRESET 2000c6fd2807SJeff Garzik * @ap: ATA channel to manipulate 2001c6fd2807SJeff Garzik * 2002c6fd2807SJeff Garzik * Part of this is taken from __sata_phy_reset and modified to 2003c6fd2807SJeff Garzik * not sleep since this routine gets called from interrupt level. 2004c6fd2807SJeff Garzik * 2005c6fd2807SJeff Garzik * LOCKING: 2006c6fd2807SJeff Garzik * Inherited from caller. This is coded to safe to call at 2007c6fd2807SJeff Garzik * interrupt level, i.e. it does not sleep. 2008c6fd2807SJeff Garzik */ 2009c6fd2807SJeff Garzik static void __mv_phy_reset(struct ata_port *ap, int can_sleep) 2010c6fd2807SJeff Garzik { 2011c6fd2807SJeff Garzik struct mv_port_priv *pp = ap->private_data; 2012cca3974eSJeff Garzik struct mv_host_priv *hpriv = ap->host->private_data; 2013c6fd2807SJeff Garzik void __iomem *port_mmio = mv_ap_base(ap); 2014c6fd2807SJeff Garzik struct ata_taskfile tf; 2015c6fd2807SJeff Garzik struct ata_device *dev = &ap->device[0]; 2016*c5d3e45aSJeff Garzik unsigned long deadline; 2017c6fd2807SJeff Garzik int retry = 5; 2018c6fd2807SJeff Garzik u32 sstatus; 2019c6fd2807SJeff Garzik 2020c6fd2807SJeff Garzik VPRINTK("ENTER, port %u, mmio 0x%p\n", ap->port_no, port_mmio); 2021c6fd2807SJeff Garzik 2022c6fd2807SJeff Garzik DPRINTK("S-regs after ATA_RST: SStat 0x%08x SErr 0x%08x " 2023c6fd2807SJeff Garzik "SCtrl 0x%08x\n", mv_scr_read(ap, SCR_STATUS), 2024c6fd2807SJeff Garzik mv_scr_read(ap, SCR_ERROR), mv_scr_read(ap, SCR_CONTROL)); 2025c6fd2807SJeff Garzik 2026c6fd2807SJeff Garzik /* Issue COMRESET via SControl */ 2027c6fd2807SJeff Garzik comreset_retry: 2028c6fd2807SJeff Garzik sata_scr_write_flush(ap, SCR_CONTROL, 0x301); 2029c6fd2807SJeff Garzik __msleep(1, can_sleep); 2030c6fd2807SJeff Garzik 2031c6fd2807SJeff Garzik sata_scr_write_flush(ap, SCR_CONTROL, 0x300); 2032c6fd2807SJeff Garzik __msleep(20, can_sleep); 2033c6fd2807SJeff Garzik 2034*c5d3e45aSJeff Garzik deadline = jiffies + msecs_to_jiffies(200); 2035c6fd2807SJeff Garzik do { 2036c6fd2807SJeff Garzik sata_scr_read(ap, SCR_STATUS, &sstatus); 2037dd1dc802SJeff Garzik if (((sstatus & 0x3) == 3) || ((sstatus & 0x3) == 0)) 2038c6fd2807SJeff Garzik break; 2039c6fd2807SJeff Garzik 2040c6fd2807SJeff Garzik __msleep(1, can_sleep); 2041*c5d3e45aSJeff Garzik } while (time_before(jiffies, deadline)); 2042c6fd2807SJeff Garzik 2043c6fd2807SJeff Garzik /* work around errata */ 2044c6fd2807SJeff Garzik if (IS_60XX(hpriv) && 2045c6fd2807SJeff Garzik (sstatus != 0x0) && (sstatus != 0x113) && (sstatus != 0x123) && 2046c6fd2807SJeff Garzik (retry-- > 0)) 2047c6fd2807SJeff Garzik goto comreset_retry; 2048c6fd2807SJeff Garzik 2049c6fd2807SJeff Garzik DPRINTK("S-regs after PHY wake: SStat 0x%08x SErr 0x%08x " 2050c6fd2807SJeff Garzik "SCtrl 0x%08x\n", mv_scr_read(ap, SCR_STATUS), 2051c6fd2807SJeff Garzik mv_scr_read(ap, SCR_ERROR), mv_scr_read(ap, SCR_CONTROL)); 2052c6fd2807SJeff Garzik 2053c6fd2807SJeff Garzik if (ata_port_online(ap)) { 2054c6fd2807SJeff Garzik ata_port_probe(ap); 2055c6fd2807SJeff Garzik } else { 2056c6fd2807SJeff Garzik sata_scr_read(ap, SCR_STATUS, &sstatus); 2057c6fd2807SJeff Garzik ata_port_printk(ap, KERN_INFO, 2058c6fd2807SJeff Garzik "no device found (phy stat %08x)\n", sstatus); 2059c6fd2807SJeff Garzik ata_port_disable(ap); 2060c6fd2807SJeff Garzik return; 2061c6fd2807SJeff Garzik } 2062c6fd2807SJeff Garzik 2063c6fd2807SJeff Garzik /* even after SStatus reflects that device is ready, 2064c6fd2807SJeff Garzik * it seems to take a while for link to be fully 2065c6fd2807SJeff Garzik * established (and thus Status no longer 0x80/0x7F), 2066c6fd2807SJeff Garzik * so we poll a bit for that, here. 2067c6fd2807SJeff Garzik */ 2068c6fd2807SJeff Garzik retry = 20; 2069c6fd2807SJeff Garzik while (1) { 2070c6fd2807SJeff Garzik u8 drv_stat = ata_check_status(ap); 2071c6fd2807SJeff Garzik if ((drv_stat != 0x80) && (drv_stat != 0x7f)) 2072c6fd2807SJeff Garzik break; 2073c6fd2807SJeff Garzik __msleep(500, can_sleep); 2074c6fd2807SJeff Garzik if (retry-- <= 0) 2075c6fd2807SJeff Garzik break; 2076c6fd2807SJeff Garzik } 2077c6fd2807SJeff Garzik 20780d5ff566STejun Heo tf.lbah = readb(ap->ioaddr.lbah_addr); 20790d5ff566STejun Heo tf.lbam = readb(ap->ioaddr.lbam_addr); 20800d5ff566STejun Heo tf.lbal = readb(ap->ioaddr.lbal_addr); 20810d5ff566STejun Heo tf.nsect = readb(ap->ioaddr.nsect_addr); 2082c6fd2807SJeff Garzik 2083c6fd2807SJeff Garzik dev->class = ata_dev_classify(&tf); 2084c6fd2807SJeff Garzik if (!ata_dev_enabled(dev)) { 2085c6fd2807SJeff Garzik VPRINTK("Port disabled post-sig: No device present.\n"); 2086c6fd2807SJeff Garzik ata_port_disable(ap); 2087c6fd2807SJeff Garzik } 2088c6fd2807SJeff Garzik 2089c6fd2807SJeff Garzik writelfl(0, port_mmio + EDMA_ERR_IRQ_CAUSE_OFS); 2090c6fd2807SJeff Garzik 2091c6fd2807SJeff Garzik pp->pp_flags &= ~MV_PP_FLAG_EDMA_EN; 2092c6fd2807SJeff Garzik 2093c6fd2807SJeff Garzik VPRINTK("EXIT\n"); 2094c6fd2807SJeff Garzik } 2095c6fd2807SJeff Garzik 2096c6fd2807SJeff Garzik static void mv_phy_reset(struct ata_port *ap) 2097c6fd2807SJeff Garzik { 2098c6fd2807SJeff Garzik __mv_phy_reset(ap, 1); 2099c6fd2807SJeff Garzik } 2100c6fd2807SJeff Garzik 2101c6fd2807SJeff Garzik /** 2102c6fd2807SJeff Garzik * mv_eng_timeout - Routine called by libata when SCSI times out I/O 2103c6fd2807SJeff Garzik * @ap: ATA channel to manipulate 2104c6fd2807SJeff Garzik * 2105c6fd2807SJeff Garzik * Intent is to clear all pending error conditions, reset the 2106c6fd2807SJeff Garzik * chip/bus, fail the command, and move on. 2107c6fd2807SJeff Garzik * 2108c6fd2807SJeff Garzik * LOCKING: 2109cca3974eSJeff Garzik * This routine holds the host lock while failing the command. 2110c6fd2807SJeff Garzik */ 2111c6fd2807SJeff Garzik static void mv_eng_timeout(struct ata_port *ap) 2112c6fd2807SJeff Garzik { 21130d5ff566STejun Heo void __iomem *mmio = ap->host->iomap[MV_PRIMARY_BAR]; 2114c6fd2807SJeff Garzik struct ata_queued_cmd *qc; 2115c6fd2807SJeff Garzik unsigned long flags; 2116c6fd2807SJeff Garzik 2117c6fd2807SJeff Garzik ata_port_printk(ap, KERN_ERR, "Entering mv_eng_timeout\n"); 2118c6fd2807SJeff Garzik DPRINTK("All regs @ start of eng_timeout\n"); 21190d5ff566STejun Heo mv_dump_all_regs(mmio, ap->port_no, to_pci_dev(ap->host->dev)); 2120c6fd2807SJeff Garzik 2121c6fd2807SJeff Garzik qc = ata_qc_from_tag(ap, ap->active_tag); 2122c6fd2807SJeff Garzik printk(KERN_ERR "mmio_base %p ap %p qc %p scsi_cmnd %p &cmnd %p\n", 21230d5ff566STejun Heo mmio, ap, qc, qc->scsicmd, &qc->scsicmd->cmnd); 2124c6fd2807SJeff Garzik 2125cca3974eSJeff Garzik spin_lock_irqsave(&ap->host->lock, flags); 2126c6fd2807SJeff Garzik mv_err_intr(ap, 0); 2127c6fd2807SJeff Garzik mv_stop_and_reset(ap); 2128cca3974eSJeff Garzik spin_unlock_irqrestore(&ap->host->lock, flags); 2129c6fd2807SJeff Garzik 2130c6fd2807SJeff Garzik WARN_ON(!(qc->flags & ATA_QCFLAG_ACTIVE)); 2131c6fd2807SJeff Garzik if (qc->flags & ATA_QCFLAG_ACTIVE) { 2132c6fd2807SJeff Garzik qc->err_mask |= AC_ERR_TIMEOUT; 2133c6fd2807SJeff Garzik ata_eh_qc_complete(qc); 2134c6fd2807SJeff Garzik } 2135c6fd2807SJeff Garzik } 2136c6fd2807SJeff Garzik 2137c6fd2807SJeff Garzik /** 2138c6fd2807SJeff Garzik * mv_port_init - Perform some early initialization on a single port. 2139c6fd2807SJeff Garzik * @port: libata data structure storing shadow register addresses 2140c6fd2807SJeff Garzik * @port_mmio: base address of the port 2141c6fd2807SJeff Garzik * 2142c6fd2807SJeff Garzik * Initialize shadow register mmio addresses, clear outstanding 2143c6fd2807SJeff Garzik * interrupts on the port, and unmask interrupts for the future 2144c6fd2807SJeff Garzik * start of the port. 2145c6fd2807SJeff Garzik * 2146c6fd2807SJeff Garzik * LOCKING: 2147c6fd2807SJeff Garzik * Inherited from caller. 2148c6fd2807SJeff Garzik */ 2149c6fd2807SJeff Garzik static void mv_port_init(struct ata_ioports *port, void __iomem *port_mmio) 2150c6fd2807SJeff Garzik { 21510d5ff566STejun Heo void __iomem *shd_base = port_mmio + SHD_BLK_OFS; 2152c6fd2807SJeff Garzik unsigned serr_ofs; 2153c6fd2807SJeff Garzik 2154c6fd2807SJeff Garzik /* PIO related setup 2155c6fd2807SJeff Garzik */ 2156c6fd2807SJeff Garzik port->data_addr = shd_base + (sizeof(u32) * ATA_REG_DATA); 2157c6fd2807SJeff Garzik port->error_addr = 2158c6fd2807SJeff Garzik port->feature_addr = shd_base + (sizeof(u32) * ATA_REG_ERR); 2159c6fd2807SJeff Garzik port->nsect_addr = shd_base + (sizeof(u32) * ATA_REG_NSECT); 2160c6fd2807SJeff Garzik port->lbal_addr = shd_base + (sizeof(u32) * ATA_REG_LBAL); 2161c6fd2807SJeff Garzik port->lbam_addr = shd_base + (sizeof(u32) * ATA_REG_LBAM); 2162c6fd2807SJeff Garzik port->lbah_addr = shd_base + (sizeof(u32) * ATA_REG_LBAH); 2163c6fd2807SJeff Garzik port->device_addr = shd_base + (sizeof(u32) * ATA_REG_DEVICE); 2164c6fd2807SJeff Garzik port->status_addr = 2165c6fd2807SJeff Garzik port->command_addr = shd_base + (sizeof(u32) * ATA_REG_STATUS); 2166c6fd2807SJeff Garzik /* special case: control/altstatus doesn't have ATA_REG_ address */ 2167c6fd2807SJeff Garzik port->altstatus_addr = port->ctl_addr = shd_base + SHD_CTL_AST_OFS; 2168c6fd2807SJeff Garzik 2169c6fd2807SJeff Garzik /* unused: */ 21708d9db2d2SRandy Dunlap port->cmd_addr = port->bmdma_addr = port->scr_addr = NULL; 2171c6fd2807SJeff Garzik 2172c6fd2807SJeff Garzik /* Clear any currently outstanding port interrupt conditions */ 2173c6fd2807SJeff Garzik serr_ofs = mv_scr_offset(SCR_ERROR); 2174c6fd2807SJeff Garzik writelfl(readl(port_mmio + serr_ofs), port_mmio + serr_ofs); 2175c6fd2807SJeff Garzik writelfl(0, port_mmio + EDMA_ERR_IRQ_CAUSE_OFS); 2176c6fd2807SJeff Garzik 2177c6fd2807SJeff Garzik /* unmask all EDMA error interrupts */ 2178c6fd2807SJeff Garzik writelfl(~0, port_mmio + EDMA_ERR_IRQ_MASK_OFS); 2179c6fd2807SJeff Garzik 2180c6fd2807SJeff Garzik VPRINTK("EDMA cfg=0x%08x EDMA IRQ err cause/mask=0x%08x/0x%08x\n", 2181c6fd2807SJeff Garzik readl(port_mmio + EDMA_CFG_OFS), 2182c6fd2807SJeff Garzik readl(port_mmio + EDMA_ERR_IRQ_CAUSE_OFS), 2183c6fd2807SJeff Garzik readl(port_mmio + EDMA_ERR_IRQ_MASK_OFS)); 2184c6fd2807SJeff Garzik } 2185c6fd2807SJeff Garzik 21864447d351STejun Heo static int mv_chip_id(struct ata_host *host, unsigned int board_idx) 2187c6fd2807SJeff Garzik { 21884447d351STejun Heo struct pci_dev *pdev = to_pci_dev(host->dev); 21894447d351STejun Heo struct mv_host_priv *hpriv = host->private_data; 2190c6fd2807SJeff Garzik u8 rev_id; 2191c6fd2807SJeff Garzik u32 hp_flags = hpriv->hp_flags; 2192c6fd2807SJeff Garzik 2193c6fd2807SJeff Garzik pci_read_config_byte(pdev, PCI_REVISION_ID, &rev_id); 2194c6fd2807SJeff Garzik 2195c6fd2807SJeff Garzik switch(board_idx) { 2196c6fd2807SJeff Garzik case chip_5080: 2197c6fd2807SJeff Garzik hpriv->ops = &mv5xxx_ops; 2198c6fd2807SJeff Garzik hp_flags |= MV_HP_50XX; 2199c6fd2807SJeff Garzik 2200c6fd2807SJeff Garzik switch (rev_id) { 2201c6fd2807SJeff Garzik case 0x1: 2202c6fd2807SJeff Garzik hp_flags |= MV_HP_ERRATA_50XXB0; 2203c6fd2807SJeff Garzik break; 2204c6fd2807SJeff Garzik case 0x3: 2205c6fd2807SJeff Garzik hp_flags |= MV_HP_ERRATA_50XXB2; 2206c6fd2807SJeff Garzik break; 2207c6fd2807SJeff Garzik default: 2208c6fd2807SJeff Garzik dev_printk(KERN_WARNING, &pdev->dev, 2209c6fd2807SJeff Garzik "Applying 50XXB2 workarounds to unknown rev\n"); 2210c6fd2807SJeff Garzik hp_flags |= MV_HP_ERRATA_50XXB2; 2211c6fd2807SJeff Garzik break; 2212c6fd2807SJeff Garzik } 2213c6fd2807SJeff Garzik break; 2214c6fd2807SJeff Garzik 2215c6fd2807SJeff Garzik case chip_504x: 2216c6fd2807SJeff Garzik case chip_508x: 2217c6fd2807SJeff Garzik hpriv->ops = &mv5xxx_ops; 2218c6fd2807SJeff Garzik hp_flags |= MV_HP_50XX; 2219c6fd2807SJeff Garzik 2220c6fd2807SJeff Garzik switch (rev_id) { 2221c6fd2807SJeff Garzik case 0x0: 2222c6fd2807SJeff Garzik hp_flags |= MV_HP_ERRATA_50XXB0; 2223c6fd2807SJeff Garzik break; 2224c6fd2807SJeff Garzik case 0x3: 2225c6fd2807SJeff Garzik hp_flags |= MV_HP_ERRATA_50XXB2; 2226c6fd2807SJeff Garzik break; 2227c6fd2807SJeff Garzik default: 2228c6fd2807SJeff Garzik dev_printk(KERN_WARNING, &pdev->dev, 2229c6fd2807SJeff Garzik "Applying B2 workarounds to unknown rev\n"); 2230c6fd2807SJeff Garzik hp_flags |= MV_HP_ERRATA_50XXB2; 2231c6fd2807SJeff Garzik break; 2232c6fd2807SJeff Garzik } 2233c6fd2807SJeff Garzik break; 2234c6fd2807SJeff Garzik 2235c6fd2807SJeff Garzik case chip_604x: 2236c6fd2807SJeff Garzik case chip_608x: 2237c6fd2807SJeff Garzik hpriv->ops = &mv6xxx_ops; 2238c6fd2807SJeff Garzik 2239c6fd2807SJeff Garzik switch (rev_id) { 2240c6fd2807SJeff Garzik case 0x7: 2241c6fd2807SJeff Garzik hp_flags |= MV_HP_ERRATA_60X1B2; 2242c6fd2807SJeff Garzik break; 2243c6fd2807SJeff Garzik case 0x9: 2244c6fd2807SJeff Garzik hp_flags |= MV_HP_ERRATA_60X1C0; 2245c6fd2807SJeff Garzik break; 2246c6fd2807SJeff Garzik default: 2247c6fd2807SJeff Garzik dev_printk(KERN_WARNING, &pdev->dev, 2248c6fd2807SJeff Garzik "Applying B2 workarounds to unknown rev\n"); 2249c6fd2807SJeff Garzik hp_flags |= MV_HP_ERRATA_60X1B2; 2250c6fd2807SJeff Garzik break; 2251c6fd2807SJeff Garzik } 2252c6fd2807SJeff Garzik break; 2253c6fd2807SJeff Garzik 2254c6fd2807SJeff Garzik case chip_7042: 2255c6fd2807SJeff Garzik case chip_6042: 2256c6fd2807SJeff Garzik hpriv->ops = &mv6xxx_ops; 2257c6fd2807SJeff Garzik 2258c6fd2807SJeff Garzik hp_flags |= MV_HP_GEN_IIE; 2259c6fd2807SJeff Garzik 2260c6fd2807SJeff Garzik switch (rev_id) { 2261c6fd2807SJeff Garzik case 0x0: 2262c6fd2807SJeff Garzik hp_flags |= MV_HP_ERRATA_XX42A0; 2263c6fd2807SJeff Garzik break; 2264c6fd2807SJeff Garzik case 0x1: 2265c6fd2807SJeff Garzik hp_flags |= MV_HP_ERRATA_60X1C0; 2266c6fd2807SJeff Garzik break; 2267c6fd2807SJeff Garzik default: 2268c6fd2807SJeff Garzik dev_printk(KERN_WARNING, &pdev->dev, 2269c6fd2807SJeff Garzik "Applying 60X1C0 workarounds to unknown rev\n"); 2270c6fd2807SJeff Garzik hp_flags |= MV_HP_ERRATA_60X1C0; 2271c6fd2807SJeff Garzik break; 2272c6fd2807SJeff Garzik } 2273c6fd2807SJeff Garzik break; 2274c6fd2807SJeff Garzik 2275c6fd2807SJeff Garzik default: 2276c6fd2807SJeff Garzik printk(KERN_ERR DRV_NAME ": BUG: invalid board index %u\n", board_idx); 2277c6fd2807SJeff Garzik return 1; 2278c6fd2807SJeff Garzik } 2279c6fd2807SJeff Garzik 2280c6fd2807SJeff Garzik hpriv->hp_flags = hp_flags; 2281c6fd2807SJeff Garzik 2282c6fd2807SJeff Garzik return 0; 2283c6fd2807SJeff Garzik } 2284c6fd2807SJeff Garzik 2285c6fd2807SJeff Garzik /** 2286c6fd2807SJeff Garzik * mv_init_host - Perform some early initialization of the host. 22874447d351STejun Heo * @host: ATA host to initialize 22884447d351STejun Heo * @board_idx: controller index 2289c6fd2807SJeff Garzik * 2290c6fd2807SJeff Garzik * If possible, do an early global reset of the host. Then do 2291c6fd2807SJeff Garzik * our port init and clear/unmask all/relevant host interrupts. 2292c6fd2807SJeff Garzik * 2293c6fd2807SJeff Garzik * LOCKING: 2294c6fd2807SJeff Garzik * Inherited from caller. 2295c6fd2807SJeff Garzik */ 22964447d351STejun Heo static int mv_init_host(struct ata_host *host, unsigned int board_idx) 2297c6fd2807SJeff Garzik { 2298c6fd2807SJeff Garzik int rc = 0, n_hc, port, hc; 22994447d351STejun Heo struct pci_dev *pdev = to_pci_dev(host->dev); 23004447d351STejun Heo void __iomem *mmio = host->iomap[MV_PRIMARY_BAR]; 23014447d351STejun Heo struct mv_host_priv *hpriv = host->private_data; 2302c6fd2807SJeff Garzik 2303c6fd2807SJeff Garzik /* global interrupt mask */ 2304c6fd2807SJeff Garzik writel(0, mmio + HC_MAIN_IRQ_MASK_OFS); 2305c6fd2807SJeff Garzik 23064447d351STejun Heo rc = mv_chip_id(host, board_idx); 2307c6fd2807SJeff Garzik if (rc) 2308c6fd2807SJeff Garzik goto done; 2309c6fd2807SJeff Garzik 23104447d351STejun Heo n_hc = mv_get_hc_count(host->ports[0]->flags); 2311c6fd2807SJeff Garzik 23124447d351STejun Heo for (port = 0; port < host->n_ports; port++) 2313c6fd2807SJeff Garzik hpriv->ops->read_preamp(hpriv, port, mmio); 2314c6fd2807SJeff Garzik 2315c6fd2807SJeff Garzik rc = hpriv->ops->reset_hc(hpriv, mmio, n_hc); 2316c6fd2807SJeff Garzik if (rc) 2317c6fd2807SJeff Garzik goto done; 2318c6fd2807SJeff Garzik 2319c6fd2807SJeff Garzik hpriv->ops->reset_flash(hpriv, mmio); 2320c6fd2807SJeff Garzik hpriv->ops->reset_bus(pdev, mmio); 2321c6fd2807SJeff Garzik hpriv->ops->enable_leds(hpriv, mmio); 2322c6fd2807SJeff Garzik 23234447d351STejun Heo for (port = 0; port < host->n_ports; port++) { 2324c6fd2807SJeff Garzik if (IS_60XX(hpriv)) { 2325c6fd2807SJeff Garzik void __iomem *port_mmio = mv_port_base(mmio, port); 2326c6fd2807SJeff Garzik 2327c6fd2807SJeff Garzik u32 ifctl = readl(port_mmio + SATA_INTERFACE_CTL); 2328c6fd2807SJeff Garzik ifctl |= (1 << 7); /* enable gen2i speed */ 2329c6fd2807SJeff Garzik ifctl = (ifctl & 0xfff) | 0x9b1000; /* from chip spec */ 2330c6fd2807SJeff Garzik writelfl(ifctl, port_mmio + SATA_INTERFACE_CTL); 2331c6fd2807SJeff Garzik } 2332c6fd2807SJeff Garzik 2333c6fd2807SJeff Garzik hpriv->ops->phy_errata(hpriv, mmio, port); 2334c6fd2807SJeff Garzik } 2335c6fd2807SJeff Garzik 23364447d351STejun Heo for (port = 0; port < host->n_ports; port++) { 2337c6fd2807SJeff Garzik void __iomem *port_mmio = mv_port_base(mmio, port); 23384447d351STejun Heo mv_port_init(&host->ports[port]->ioaddr, port_mmio); 2339c6fd2807SJeff Garzik } 2340c6fd2807SJeff Garzik 2341c6fd2807SJeff Garzik for (hc = 0; hc < n_hc; hc++) { 2342c6fd2807SJeff Garzik void __iomem *hc_mmio = mv_hc_base(mmio, hc); 2343c6fd2807SJeff Garzik 2344c6fd2807SJeff Garzik VPRINTK("HC%i: HC config=0x%08x HC IRQ cause " 2345c6fd2807SJeff Garzik "(before clear)=0x%08x\n", hc, 2346c6fd2807SJeff Garzik readl(hc_mmio + HC_CFG_OFS), 2347c6fd2807SJeff Garzik readl(hc_mmio + HC_IRQ_CAUSE_OFS)); 2348c6fd2807SJeff Garzik 2349c6fd2807SJeff Garzik /* Clear any currently outstanding hc interrupt conditions */ 2350c6fd2807SJeff Garzik writelfl(0, hc_mmio + HC_IRQ_CAUSE_OFS); 2351c6fd2807SJeff Garzik } 2352c6fd2807SJeff Garzik 2353c6fd2807SJeff Garzik /* Clear any currently outstanding host interrupt conditions */ 2354c6fd2807SJeff Garzik writelfl(0, mmio + PCI_IRQ_CAUSE_OFS); 2355c6fd2807SJeff Garzik 2356c6fd2807SJeff Garzik /* and unmask interrupt generation for host regs */ 2357c6fd2807SJeff Garzik writelfl(PCI_UNMASK_ALL_IRQS, mmio + PCI_IRQ_MASK_OFS); 2358fb621e2fSJeff Garzik 2359fb621e2fSJeff Garzik if (IS_50XX(hpriv)) 2360fb621e2fSJeff Garzik writelfl(~HC_MAIN_MASKED_IRQS_5, mmio + HC_MAIN_IRQ_MASK_OFS); 2361fb621e2fSJeff Garzik else 2362c6fd2807SJeff Garzik writelfl(~HC_MAIN_MASKED_IRQS, mmio + HC_MAIN_IRQ_MASK_OFS); 2363c6fd2807SJeff Garzik 2364c6fd2807SJeff Garzik VPRINTK("HC MAIN IRQ cause/mask=0x%08x/0x%08x " 2365c6fd2807SJeff Garzik "PCI int cause/mask=0x%08x/0x%08x\n", 2366c6fd2807SJeff Garzik readl(mmio + HC_MAIN_IRQ_CAUSE_OFS), 2367c6fd2807SJeff Garzik readl(mmio + HC_MAIN_IRQ_MASK_OFS), 2368c6fd2807SJeff Garzik readl(mmio + PCI_IRQ_CAUSE_OFS), 2369c6fd2807SJeff Garzik readl(mmio + PCI_IRQ_MASK_OFS)); 2370c6fd2807SJeff Garzik 2371c6fd2807SJeff Garzik done: 2372c6fd2807SJeff Garzik return rc; 2373c6fd2807SJeff Garzik } 2374c6fd2807SJeff Garzik 2375c6fd2807SJeff Garzik /** 2376c6fd2807SJeff Garzik * mv_print_info - Dump key info to kernel log for perusal. 23774447d351STejun Heo * @host: ATA host to print info about 2378c6fd2807SJeff Garzik * 2379c6fd2807SJeff Garzik * FIXME: complete this. 2380c6fd2807SJeff Garzik * 2381c6fd2807SJeff Garzik * LOCKING: 2382c6fd2807SJeff Garzik * Inherited from caller. 2383c6fd2807SJeff Garzik */ 23844447d351STejun Heo static void mv_print_info(struct ata_host *host) 2385c6fd2807SJeff Garzik { 23864447d351STejun Heo struct pci_dev *pdev = to_pci_dev(host->dev); 23874447d351STejun Heo struct mv_host_priv *hpriv = host->private_data; 2388c6fd2807SJeff Garzik u8 rev_id, scc; 2389c1e4fe71SJeff Garzik const char *scc_s, *gen; 2390c6fd2807SJeff Garzik 2391c6fd2807SJeff Garzik /* Use this to determine the HW stepping of the chip so we know 2392c6fd2807SJeff Garzik * what errata to workaround 2393c6fd2807SJeff Garzik */ 2394c6fd2807SJeff Garzik pci_read_config_byte(pdev, PCI_REVISION_ID, &rev_id); 2395c6fd2807SJeff Garzik 2396c6fd2807SJeff Garzik pci_read_config_byte(pdev, PCI_CLASS_DEVICE, &scc); 2397c6fd2807SJeff Garzik if (scc == 0) 2398c6fd2807SJeff Garzik scc_s = "SCSI"; 2399c6fd2807SJeff Garzik else if (scc == 0x01) 2400c6fd2807SJeff Garzik scc_s = "RAID"; 2401c6fd2807SJeff Garzik else 2402c1e4fe71SJeff Garzik scc_s = "?"; 2403c1e4fe71SJeff Garzik 2404c1e4fe71SJeff Garzik if (IS_GEN_I(hpriv)) 2405c1e4fe71SJeff Garzik gen = "I"; 2406c1e4fe71SJeff Garzik else if (IS_GEN_II(hpriv)) 2407c1e4fe71SJeff Garzik gen = "II"; 2408c1e4fe71SJeff Garzik else if (IS_GEN_IIE(hpriv)) 2409c1e4fe71SJeff Garzik gen = "IIE"; 2410c1e4fe71SJeff Garzik else 2411c1e4fe71SJeff Garzik gen = "?"; 2412c6fd2807SJeff Garzik 2413c6fd2807SJeff Garzik dev_printk(KERN_INFO, &pdev->dev, 2414c1e4fe71SJeff Garzik "Gen-%s %u slots %u ports %s mode IRQ via %s\n", 2415c1e4fe71SJeff Garzik gen, (unsigned)MV_MAX_Q_DEPTH, host->n_ports, 2416c6fd2807SJeff Garzik scc_s, (MV_HP_FLAG_MSI & hpriv->hp_flags) ? "MSI" : "INTx"); 2417c6fd2807SJeff Garzik } 2418c6fd2807SJeff Garzik 2419c6fd2807SJeff Garzik /** 2420c6fd2807SJeff Garzik * mv_init_one - handle a positive probe of a Marvell host 2421c6fd2807SJeff Garzik * @pdev: PCI device found 2422c6fd2807SJeff Garzik * @ent: PCI device ID entry for the matched host 2423c6fd2807SJeff Garzik * 2424c6fd2807SJeff Garzik * LOCKING: 2425c6fd2807SJeff Garzik * Inherited from caller. 2426c6fd2807SJeff Garzik */ 2427c6fd2807SJeff Garzik static int mv_init_one(struct pci_dev *pdev, const struct pci_device_id *ent) 2428c6fd2807SJeff Garzik { 2429c6fd2807SJeff Garzik static int printed_version = 0; 2430c6fd2807SJeff Garzik unsigned int board_idx = (unsigned int)ent->driver_data; 24314447d351STejun Heo const struct ata_port_info *ppi[] = { &mv_port_info[board_idx], NULL }; 24324447d351STejun Heo struct ata_host *host; 24334447d351STejun Heo struct mv_host_priv *hpriv; 24344447d351STejun Heo int n_ports, rc; 2435c6fd2807SJeff Garzik 2436c6fd2807SJeff Garzik if (!printed_version++) 2437c6fd2807SJeff Garzik dev_printk(KERN_INFO, &pdev->dev, "version " DRV_VERSION "\n"); 2438c6fd2807SJeff Garzik 24394447d351STejun Heo /* allocate host */ 24404447d351STejun Heo n_ports = mv_get_hc_count(ppi[0]->flags) * MV_PORTS_PER_HC; 24414447d351STejun Heo 24424447d351STejun Heo host = ata_host_alloc_pinfo(&pdev->dev, ppi, n_ports); 24434447d351STejun Heo hpriv = devm_kzalloc(&pdev->dev, sizeof(*hpriv), GFP_KERNEL); 24444447d351STejun Heo if (!host || !hpriv) 24454447d351STejun Heo return -ENOMEM; 24464447d351STejun Heo host->private_data = hpriv; 24474447d351STejun Heo 24484447d351STejun Heo /* acquire resources */ 244924dc5f33STejun Heo rc = pcim_enable_device(pdev); 245024dc5f33STejun Heo if (rc) 2451c6fd2807SJeff Garzik return rc; 2452c6fd2807SJeff Garzik 24530d5ff566STejun Heo rc = pcim_iomap_regions(pdev, 1 << MV_PRIMARY_BAR, DRV_NAME); 24540d5ff566STejun Heo if (rc == -EBUSY) 245524dc5f33STejun Heo pcim_pin_device(pdev); 24560d5ff566STejun Heo if (rc) 245724dc5f33STejun Heo return rc; 24584447d351STejun Heo host->iomap = pcim_iomap_table(pdev); 2459c6fd2807SJeff Garzik 2460d88184fbSJeff Garzik rc = pci_go_64(pdev); 2461d88184fbSJeff Garzik if (rc) 2462d88184fbSJeff Garzik return rc; 2463d88184fbSJeff Garzik 2464c6fd2807SJeff Garzik /* initialize adapter */ 24654447d351STejun Heo rc = mv_init_host(host, board_idx); 246624dc5f33STejun Heo if (rc) 246724dc5f33STejun Heo return rc; 2468c6fd2807SJeff Garzik 2469c6fd2807SJeff Garzik /* Enable interrupts */ 24706a59dcf8STejun Heo if (msi && pci_enable_msi(pdev)) 2471c6fd2807SJeff Garzik pci_intx(pdev, 1); 2472c6fd2807SJeff Garzik 2473c6fd2807SJeff Garzik mv_dump_pci_cfg(pdev, 0x68); 24744447d351STejun Heo mv_print_info(host); 2475c6fd2807SJeff Garzik 24764447d351STejun Heo pci_set_master(pdev); 24774447d351STejun Heo return ata_host_activate(host, pdev->irq, mv_interrupt, IRQF_SHARED, 2478*c5d3e45aSJeff Garzik IS_GEN_I(hpriv) ? &mv5_sht : &mv6_sht); 2479c6fd2807SJeff Garzik } 2480c6fd2807SJeff Garzik 2481c6fd2807SJeff Garzik static int __init mv_init(void) 2482c6fd2807SJeff Garzik { 2483c6fd2807SJeff Garzik return pci_register_driver(&mv_pci_driver); 2484c6fd2807SJeff Garzik } 2485c6fd2807SJeff Garzik 2486c6fd2807SJeff Garzik static void __exit mv_exit(void) 2487c6fd2807SJeff Garzik { 2488c6fd2807SJeff Garzik pci_unregister_driver(&mv_pci_driver); 2489c6fd2807SJeff Garzik } 2490c6fd2807SJeff Garzik 2491c6fd2807SJeff Garzik MODULE_AUTHOR("Brett Russ"); 2492c6fd2807SJeff Garzik MODULE_DESCRIPTION("SCSI low-level driver for Marvell SATA controllers"); 2493c6fd2807SJeff Garzik MODULE_LICENSE("GPL"); 2494c6fd2807SJeff Garzik MODULE_DEVICE_TABLE(pci, mv_pci_tbl); 2495c6fd2807SJeff Garzik MODULE_VERSION(DRV_VERSION); 2496c6fd2807SJeff Garzik 2497c6fd2807SJeff Garzik module_param(msi, int, 0444); 2498c6fd2807SJeff Garzik MODULE_PARM_DESC(msi, "Enable use of PCI MSI (0=off, 1=on)"); 2499c6fd2807SJeff Garzik 2500c6fd2807SJeff Garzik module_init(mv_init); 2501c6fd2807SJeff Garzik module_exit(mv_exit); 2502