sata_mv.c revision 44c10138fd4bbc4b6d6bff0873c24902f2a9da65
120f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ/* 220f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ * sata_mv.c - Marvell SATA support 320f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ * 48b260248d9e0e8b64bb72fd4dee03ad86984c344Jeff Garzik * Copyright 2005: EMC Corporation, all rights reserved. 5e2b1be56c5656902744c2b52e8304126a40bb609Jeff Garzik * Copyright 2005 Red Hat, Inc. All rights reserved. 620f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ * 720f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ * Please ALWAYS copy linux-ide@vger.kernel.org on emails. 820f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ * 920f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ * This program is free software; you can redistribute it and/or modify 1020f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ * it under the terms of the GNU General Public License as published by 1120f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ * the Free Software Foundation; version 2 of the License. 1220f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ * 1320f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ * This program is distributed in the hope that it will be useful, 1420f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ * but WITHOUT ANY WARRANTY; without even the implied warranty of 1520f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 1620f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ * GNU General Public License for more details. 1720f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ * 1820f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ * You should have received a copy of the GNU General Public License 1920f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ * along with this program; if not, write to the Free Software 2020f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA 2120f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ * 2220f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ */ 2320f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ 244a05e2091709dbb22b86a1b3343cd3fa3c0d7a6bJeff Garzik/* 254a05e2091709dbb22b86a1b3343cd3fa3c0d7a6bJeff Garzik sata_mv TODO list: 264a05e2091709dbb22b86a1b3343cd3fa3c0d7a6bJeff Garzik 274a05e2091709dbb22b86a1b3343cd3fa3c0d7a6bJeff Garzik 1) Needs a full errata audit for all chipsets. I implemented most 284a05e2091709dbb22b86a1b3343cd3fa3c0d7a6bJeff Garzik of the errata workarounds found in the Marvell vendor driver, but 294a05e2091709dbb22b86a1b3343cd3fa3c0d7a6bJeff Garzik I distinctly remember a couple workarounds (one related to PCI-X) 304a05e2091709dbb22b86a1b3343cd3fa3c0d7a6bJeff Garzik are still needed. 314a05e2091709dbb22b86a1b3343cd3fa3c0d7a6bJeff Garzik 324a05e2091709dbb22b86a1b3343cd3fa3c0d7a6bJeff Garzik 2) Convert to LibATA new EH. Required for hotplug, NCQ, and sane 334a05e2091709dbb22b86a1b3343cd3fa3c0d7a6bJeff Garzik probing/error handling in general. MUST HAVE. 344a05e2091709dbb22b86a1b3343cd3fa3c0d7a6bJeff Garzik 354a05e2091709dbb22b86a1b3343cd3fa3c0d7a6bJeff Garzik 3) Add hotplug support (easy, once new-EH support appears) 364a05e2091709dbb22b86a1b3343cd3fa3c0d7a6bJeff Garzik 374a05e2091709dbb22b86a1b3343cd3fa3c0d7a6bJeff Garzik 4) Add NCQ support (easy to intermediate, once new-EH support appears) 384a05e2091709dbb22b86a1b3343cd3fa3c0d7a6bJeff Garzik 394a05e2091709dbb22b86a1b3343cd3fa3c0d7a6bJeff Garzik 5) Investigate problems with PCI Message Signalled Interrupts (MSI). 404a05e2091709dbb22b86a1b3343cd3fa3c0d7a6bJeff Garzik 414a05e2091709dbb22b86a1b3343cd3fa3c0d7a6bJeff Garzik 6) Add port multiplier support (intermediate) 424a05e2091709dbb22b86a1b3343cd3fa3c0d7a6bJeff Garzik 434a05e2091709dbb22b86a1b3343cd3fa3c0d7a6bJeff Garzik 7) Test and verify 3.0 Gbps support 444a05e2091709dbb22b86a1b3343cd3fa3c0d7a6bJeff Garzik 454a05e2091709dbb22b86a1b3343cd3fa3c0d7a6bJeff Garzik 8) Develop a low-power-consumption strategy, and implement it. 464a05e2091709dbb22b86a1b3343cd3fa3c0d7a6bJeff Garzik 474a05e2091709dbb22b86a1b3343cd3fa3c0d7a6bJeff Garzik 9) [Experiment, low priority] See if ATAPI can be supported using 484a05e2091709dbb22b86a1b3343cd3fa3c0d7a6bJeff Garzik "unknown FIS" or "vendor-specific FIS" support, or something creative 494a05e2091709dbb22b86a1b3343cd3fa3c0d7a6bJeff Garzik like that. 504a05e2091709dbb22b86a1b3343cd3fa3c0d7a6bJeff Garzik 514a05e2091709dbb22b86a1b3343cd3fa3c0d7a6bJeff Garzik 10) [Experiment, low priority] Investigate interrupt coalescing. 524a05e2091709dbb22b86a1b3343cd3fa3c0d7a6bJeff Garzik Quite often, especially with PCI Message Signalled Interrupts (MSI), 534a05e2091709dbb22b86a1b3343cd3fa3c0d7a6bJeff Garzik the overhead reduced by interrupt mitigation is quite often not 544a05e2091709dbb22b86a1b3343cd3fa3c0d7a6bJeff Garzik worth the latency cost. 554a05e2091709dbb22b86a1b3343cd3fa3c0d7a6bJeff Garzik 564a05e2091709dbb22b86a1b3343cd3fa3c0d7a6bJeff Garzik 11) [Experiment, Marvell value added] Is it possible to use target 574a05e2091709dbb22b86a1b3343cd3fa3c0d7a6bJeff Garzik mode to cross-connect two Linux boxes with Marvell cards? If so, 584a05e2091709dbb22b86a1b3343cd3fa3c0d7a6bJeff Garzik creating LibATA target mode support would be very interesting. 594a05e2091709dbb22b86a1b3343cd3fa3c0d7a6bJeff Garzik 604a05e2091709dbb22b86a1b3343cd3fa3c0d7a6bJeff Garzik Target mode, for those without docs, is the ability to directly 614a05e2091709dbb22b86a1b3343cd3fa3c0d7a6bJeff Garzik connect two SATA controllers. 624a05e2091709dbb22b86a1b3343cd3fa3c0d7a6bJeff Garzik 634a05e2091709dbb22b86a1b3343cd3fa3c0d7a6bJeff Garzik 13) Verify that 7042 is fully supported. I only have a 6042. 644a05e2091709dbb22b86a1b3343cd3fa3c0d7a6bJeff Garzik 654a05e2091709dbb22b86a1b3343cd3fa3c0d7a6bJeff Garzik*/ 664a05e2091709dbb22b86a1b3343cd3fa3c0d7a6bJeff Garzik 674a05e2091709dbb22b86a1b3343cd3fa3c0d7a6bJeff Garzik 6820f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ#include <linux/kernel.h> 6920f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ#include <linux/module.h> 7020f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ#include <linux/pci.h> 7120f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ#include <linux/init.h> 7220f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ#include <linux/blkdev.h> 7320f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ#include <linux/delay.h> 7420f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ#include <linux/interrupt.h> 7520f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ#include <linux/dma-mapping.h> 76a9524a76f70f3343e4be27f95a7e92a8ba5f9009Jeff Garzik#include <linux/device.h> 7720f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ#include <scsi/scsi_host.h> 78193515d51ccb363165d6b09e9ba5c21089e34badJeff Garzik#include <scsi/scsi_cmnd.h> 7920f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ#include <linux/libata.h> 8020f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ 8120f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ#define DRV_NAME "sata_mv" 828bc3fc470eb25af4d70c72485cbcb130cc657691Jeff Garzik#define DRV_VERSION "0.81" 8320f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ 8420f733e7d75a16bffc34842b7682c9247dd5f954Brett Russenum { 8520f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ /* BAR's are enumerated in terms of pci_resource_start() terms */ 8620f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ MV_PRIMARY_BAR = 0, /* offset 0x10: memory space */ 8720f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ MV_IO_BAR = 2, /* offset 0x18: IO space */ 8820f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ MV_MISC_BAR = 3, /* offset 0x1c: FLASH, NVRAM, SRAM */ 8920f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ 9020f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ MV_MAJOR_REG_AREA_SZ = 0x10000, /* 64KB */ 9120f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ MV_MINOR_REG_AREA_SZ = 0x2000, /* 8KB */ 9220f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ 9320f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ MV_PCI_REG_BASE = 0, 9420f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ MV_IRQ_COAL_REG_BASE = 0x18000, /* 6xxx part only */ 95615ab95342f6245026d8974b9724f7ea57d9a184Mark Lord MV_IRQ_COAL_CAUSE = (MV_IRQ_COAL_REG_BASE + 0x08), 96615ab95342f6245026d8974b9724f7ea57d9a184Mark Lord MV_IRQ_COAL_CAUSE_LO = (MV_IRQ_COAL_REG_BASE + 0x88), 97615ab95342f6245026d8974b9724f7ea57d9a184Mark Lord MV_IRQ_COAL_CAUSE_HI = (MV_IRQ_COAL_REG_BASE + 0x8c), 98615ab95342f6245026d8974b9724f7ea57d9a184Mark Lord MV_IRQ_COAL_THRESHOLD = (MV_IRQ_COAL_REG_BASE + 0xcc), 99615ab95342f6245026d8974b9724f7ea57d9a184Mark Lord MV_IRQ_COAL_TIME_THRESHOLD = (MV_IRQ_COAL_REG_BASE + 0xd0), 100615ab95342f6245026d8974b9724f7ea57d9a184Mark Lord 10120f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ MV_SATAHC0_REG_BASE = 0x20000, 102522479fb98c6667f081e75f87e298e413c0b1db8Jeff Garzik MV_FLASH_CTL = 0x1046c, 103bca1c4eb9411533d613123618c0d127fae532595Jeff Garzik MV_GPIO_PORT_CTL = 0x104f0, 104bca1c4eb9411533d613123618c0d127fae532595Jeff Garzik MV_RESET_CFG = 0x180d8, 10520f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ 10620f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ MV_PCI_REG_SZ = MV_MAJOR_REG_AREA_SZ, 10720f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ MV_SATAHC_REG_SZ = MV_MAJOR_REG_AREA_SZ, 10820f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ MV_SATAHC_ARBTR_REG_SZ = MV_MINOR_REG_AREA_SZ, /* arbiter */ 10920f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ MV_PORT_REG_SZ = MV_MINOR_REG_AREA_SZ, 11020f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ 11131961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ MV_USE_Q_DEPTH = ATA_DEF_QUEUE, 11220f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ 11331961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ MV_MAX_Q_DEPTH = 32, 11431961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ MV_MAX_Q_DEPTH_MASK = MV_MAX_Q_DEPTH - 1, 11531961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ 11631961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ /* CRQB needs alignment on a 1KB boundary. Size == 1KB 11731961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ * CRPB needs alignment on a 256B boundary. Size == 256B 11831961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ * SG count of 176 leads to MV_PORT_PRIV_DMA_SZ == 4KB 11931961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ * ePRD (SG) entries need alignment on a 16B boundary. Size == 16B 12031961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ */ 12131961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ MV_CRQB_Q_SZ = (32 * MV_MAX_Q_DEPTH), 12231961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ MV_CRPB_Q_SZ = (8 * MV_MAX_Q_DEPTH), 12331961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ MV_MAX_SG_CT = 176, 12431961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ MV_SG_TBL_SZ = (16 * MV_MAX_SG_CT), 12531961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ MV_PORT_PRIV_DMA_SZ = (MV_CRQB_Q_SZ + MV_CRPB_Q_SZ + MV_SG_TBL_SZ), 12631961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ 12720f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ MV_PORTS_PER_HC = 4, 12820f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ /* == (port / MV_PORTS_PER_HC) to determine HC from 0-7 port */ 12920f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ MV_PORT_HC_SHIFT = 2, 13031961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ /* == (port % MV_PORTS_PER_HC) to determine hard port from 0-7 port */ 13120f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ MV_PORT_MASK = 3, 13220f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ 13320f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ /* Host Flags */ 13420f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ MV_FLAG_DUAL_HC = (1 << 30), /* two SATA Host Controllers */ 13520f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ MV_FLAG_IRQ_COALESCE = (1 << 29), /* IRQ coalescing capability */ 13631961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ MV_COMMON_FLAGS = (ATA_FLAG_SATA | ATA_FLAG_NO_LEGACY | 13750630195bbdfe1ca775d94cd68a5f18bc1b717e4Jeff Garzik ATA_FLAG_SATA_RESET | ATA_FLAG_MMIO | 1381f3461a72619fcd70a0fcb563306c91f753b4620Albert Lee ATA_FLAG_NO_ATAPI | ATA_FLAG_PIO_POLLING), 13947c2b677daeed9c79ecb7167c211ff36876ea611Jeff Garzik MV_6XXX_FLAGS = MV_FLAG_IRQ_COALESCE, 14020f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ 14131961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ CRQB_FLAG_READ = (1 << 0), 14231961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ CRQB_TAG_SHIFT = 1, 14331961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ CRQB_CMD_ADDR_SHIFT = 8, 14431961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ CRQB_CMD_CS = (0x2 << 11), 14531961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ CRQB_CMD_LAST = (1 << 15), 14631961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ 14731961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ CRPB_FLAG_STATUS_SHIFT = 8, 14831961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ 14931961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ EPRD_FLAG_END_OF_TBL = (1 << 31), 15031961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ 15120f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ /* PCI interface registers */ 15220f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ 15331961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ PCI_COMMAND_OFS = 0xc00, 15431961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ 15520f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ PCI_MAIN_CMD_STS_OFS = 0xd30, 15620f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ STOP_PCI_MASTER = (1 << 2), 15720f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ PCI_MASTER_EMPTY = (1 << 3), 15820f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ GLOB_SFT_RST = (1 << 4), 15920f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ 160522479fb98c6667f081e75f87e298e413c0b1db8Jeff Garzik MV_PCI_MODE = 0xd00, 161522479fb98c6667f081e75f87e298e413c0b1db8Jeff Garzik MV_PCI_EXP_ROM_BAR_CTL = 0xd2c, 162522479fb98c6667f081e75f87e298e413c0b1db8Jeff Garzik MV_PCI_DISC_TIMER = 0xd04, 163522479fb98c6667f081e75f87e298e413c0b1db8Jeff Garzik MV_PCI_MSI_TRIGGER = 0xc38, 164522479fb98c6667f081e75f87e298e413c0b1db8Jeff Garzik MV_PCI_SERR_MASK = 0xc28, 165522479fb98c6667f081e75f87e298e413c0b1db8Jeff Garzik MV_PCI_XBAR_TMOUT = 0x1d04, 166522479fb98c6667f081e75f87e298e413c0b1db8Jeff Garzik MV_PCI_ERR_LOW_ADDRESS = 0x1d40, 167522479fb98c6667f081e75f87e298e413c0b1db8Jeff Garzik MV_PCI_ERR_HIGH_ADDRESS = 0x1d44, 168522479fb98c6667f081e75f87e298e413c0b1db8Jeff Garzik MV_PCI_ERR_ATTRIBUTE = 0x1d48, 169522479fb98c6667f081e75f87e298e413c0b1db8Jeff Garzik MV_PCI_ERR_COMMAND = 0x1d50, 170522479fb98c6667f081e75f87e298e413c0b1db8Jeff Garzik 171522479fb98c6667f081e75f87e298e413c0b1db8Jeff Garzik PCI_IRQ_CAUSE_OFS = 0x1d58, 172522479fb98c6667f081e75f87e298e413c0b1db8Jeff Garzik PCI_IRQ_MASK_OFS = 0x1d5c, 17320f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ PCI_UNMASK_ALL_IRQS = 0x7fffff, /* bits 22-0 */ 17420f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ 17520f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ HC_MAIN_IRQ_CAUSE_OFS = 0x1d60, 17620f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ HC_MAIN_IRQ_MASK_OFS = 0x1d64, 17720f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ PORT0_ERR = (1 << 0), /* shift by port # */ 17820f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ PORT0_DONE = (1 << 1), /* shift by port # */ 17920f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ HC0_IRQ_PEND = 0x1ff, /* bits 0-8 = HC0's ports */ 18020f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ HC_SHIFT = 9, /* bits 9-17 = HC1's ports */ 18120f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ PCI_ERR = (1 << 18), 18220f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ TRAN_LO_DONE = (1 << 19), /* 6xxx: IRQ coalescing */ 18320f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ TRAN_HI_DONE = (1 << 20), /* 6xxx: IRQ coalescing */ 184fb621e2fde735abab854586d52c96c5624bcb5b8Jeff Garzik PORTS_0_3_COAL_DONE = (1 << 8), 185fb621e2fde735abab854586d52c96c5624bcb5b8Jeff Garzik PORTS_4_7_COAL_DONE = (1 << 17), 18620f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ PORTS_0_7_COAL_DONE = (1 << 21), /* 6xxx: IRQ coalescing */ 18720f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ GPIO_INT = (1 << 22), 18820f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ SELF_INT = (1 << 23), 18920f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ TWSI_INT = (1 << 24), 19020f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ HC_MAIN_RSVD = (0x7f << 25), /* bits 31-25 */ 191fb621e2fde735abab854586d52c96c5624bcb5b8Jeff Garzik HC_MAIN_RSVD_5 = (0x1fff << 19), /* bits 31-19 */ 1928b260248d9e0e8b64bb72fd4dee03ad86984c344Jeff Garzik HC_MAIN_MASKED_IRQS = (TRAN_LO_DONE | TRAN_HI_DONE | 19320f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ PORTS_0_7_COAL_DONE | GPIO_INT | TWSI_INT | 19420f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ HC_MAIN_RSVD), 195fb621e2fde735abab854586d52c96c5624bcb5b8Jeff Garzik HC_MAIN_MASKED_IRQS_5 = (PORTS_0_3_COAL_DONE | PORTS_4_7_COAL_DONE | 196fb621e2fde735abab854586d52c96c5624bcb5b8Jeff Garzik HC_MAIN_RSVD_5), 19720f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ 19820f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ /* SATAHC registers */ 19920f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ HC_CFG_OFS = 0, 20020f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ 20120f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ HC_IRQ_CAUSE_OFS = 0x14, 20231961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ CRPB_DMA_DONE = (1 << 0), /* shift by port # */ 20320f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ HC_IRQ_COAL = (1 << 4), /* IRQ coalescing */ 20420f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ DEV_IRQ = (1 << 8), /* shift by port # */ 20520f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ 20620f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ /* Shadow block registers */ 20731961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ SHD_BLK_OFS = 0x100, 20831961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ SHD_CTL_AST_OFS = 0x20, /* ofs from SHD_BLK_OFS */ 20920f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ 21020f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ /* SATA registers */ 21120f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ SATA_STATUS_OFS = 0x300, /* ctrl, err regs follow status */ 21220f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ SATA_ACTIVE_OFS = 0x350, 21347c2b677daeed9c79ecb7167c211ff36876ea611Jeff Garzik PHY_MODE3 = 0x310, 214bca1c4eb9411533d613123618c0d127fae532595Jeff Garzik PHY_MODE4 = 0x314, 215bca1c4eb9411533d613123618c0d127fae532595Jeff Garzik PHY_MODE2 = 0x330, 216c9d39130123238ac18478a42e25cb7996eacfcc0Jeff Garzik MV5_PHY_MODE = 0x74, 217c9d39130123238ac18478a42e25cb7996eacfcc0Jeff Garzik MV5_LT_MODE = 0x30, 218c9d39130123238ac18478a42e25cb7996eacfcc0Jeff Garzik MV5_PHY_CTL = 0x0C, 219bca1c4eb9411533d613123618c0d127fae532595Jeff Garzik SATA_INTERFACE_CTL = 0x050, 220bca1c4eb9411533d613123618c0d127fae532595Jeff Garzik 221bca1c4eb9411533d613123618c0d127fae532595Jeff Garzik MV_M2_PREAMP_MASK = 0x7e0, 22220f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ 22320f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ /* Port registers */ 22420f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ EDMA_CFG_OFS = 0, 22531961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ EDMA_CFG_Q_DEPTH = 0, /* queueing disabled */ 22631961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ EDMA_CFG_NCQ = (1 << 5), 22731961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ EDMA_CFG_NCQ_GO_ON_ERR = (1 << 14), /* continue on error */ 22831961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ EDMA_CFG_RD_BRST_EXT = (1 << 11), /* read burst 512B */ 22931961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ EDMA_CFG_WR_BUFF_LEN = (1 << 13), /* write buffer 512B */ 23020f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ 23120f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ EDMA_ERR_IRQ_CAUSE_OFS = 0x8, 23220f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ EDMA_ERR_IRQ_MASK_OFS = 0xc, 23320f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ EDMA_ERR_D_PAR = (1 << 0), 23420f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ EDMA_ERR_PRD_PAR = (1 << 1), 23520f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ EDMA_ERR_DEV = (1 << 2), 23620f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ EDMA_ERR_DEV_DCON = (1 << 3), 23720f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ EDMA_ERR_DEV_CON = (1 << 4), 23820f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ EDMA_ERR_SERR = (1 << 5), 23920f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ EDMA_ERR_SELF_DIS = (1 << 7), 24020f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ EDMA_ERR_BIST_ASYNC = (1 << 8), 24120f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ EDMA_ERR_CRBQ_PAR = (1 << 9), 24220f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ EDMA_ERR_CRPB_PAR = (1 << 10), 24320f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ EDMA_ERR_INTRL_PAR = (1 << 11), 24420f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ EDMA_ERR_IORDY = (1 << 12), 24520f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ EDMA_ERR_LNK_CTRL_RX = (0xf << 13), 24620f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ EDMA_ERR_LNK_CTRL_RX_2 = (1 << 15), 24720f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ EDMA_ERR_LNK_DATA_RX = (0xf << 17), 24820f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ EDMA_ERR_LNK_CTRL_TX = (0x1f << 21), 24920f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ EDMA_ERR_LNK_DATA_TX = (0x1f << 26), 25020f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ EDMA_ERR_TRANS_PROTO = (1 << 31), 2518b260248d9e0e8b64bb72fd4dee03ad86984c344Jeff Garzik EDMA_ERR_FATAL = (EDMA_ERR_D_PAR | EDMA_ERR_PRD_PAR | 25220f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ EDMA_ERR_DEV_DCON | EDMA_ERR_CRBQ_PAR | 25320f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ EDMA_ERR_CRPB_PAR | EDMA_ERR_INTRL_PAR | 2548b260248d9e0e8b64bb72fd4dee03ad86984c344Jeff Garzik EDMA_ERR_IORDY | EDMA_ERR_LNK_CTRL_RX_2 | 25520f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ EDMA_ERR_LNK_DATA_RX | 2568b260248d9e0e8b64bb72fd4dee03ad86984c344Jeff Garzik EDMA_ERR_LNK_DATA_TX | 25720f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ EDMA_ERR_TRANS_PROTO), 25820f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ 25931961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ EDMA_REQ_Q_BASE_HI_OFS = 0x10, 26031961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ EDMA_REQ_Q_IN_PTR_OFS = 0x14, /* also contains BASE_LO */ 26131961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ 26231961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ EDMA_REQ_Q_OUT_PTR_OFS = 0x18, 26331961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ EDMA_REQ_Q_PTR_SHIFT = 5, 26431961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ 26531961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ EDMA_RSP_Q_BASE_HI_OFS = 0x1c, 26631961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ EDMA_RSP_Q_IN_PTR_OFS = 0x20, 26731961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ EDMA_RSP_Q_OUT_PTR_OFS = 0x24, /* also contains BASE_LO */ 26831961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ EDMA_RSP_Q_PTR_SHIFT = 3, 26931961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ 27020f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ EDMA_CMD_OFS = 0x28, 27120f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ EDMA_EN = (1 << 0), 27220f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ EDMA_DS = (1 << 1), 27320f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ ATA_RST = (1 << 2), 27420f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ 275c9d39130123238ac18478a42e25cb7996eacfcc0Jeff Garzik EDMA_IORDY_TMOUT = 0x34, 276bca1c4eb9411533d613123618c0d127fae532595Jeff Garzik EDMA_ARB_CFG = 0x38, 277bca1c4eb9411533d613123618c0d127fae532595Jeff Garzik 27831961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ /* Host private flags (hp_flags) */ 27931961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ MV_HP_FLAG_MSI = (1 << 0), 28047c2b677daeed9c79ecb7167c211ff36876ea611Jeff Garzik MV_HP_ERRATA_50XXB0 = (1 << 1), 28147c2b677daeed9c79ecb7167c211ff36876ea611Jeff Garzik MV_HP_ERRATA_50XXB2 = (1 << 2), 28247c2b677daeed9c79ecb7167c211ff36876ea611Jeff Garzik MV_HP_ERRATA_60X1B2 = (1 << 3), 28347c2b677daeed9c79ecb7167c211ff36876ea611Jeff Garzik MV_HP_ERRATA_60X1C0 = (1 << 4), 284e4e7b89280d1d666e2c09e5ad36cf071796c4c7eJeff Garzik MV_HP_ERRATA_XX42A0 = (1 << 5), 285e4e7b89280d1d666e2c09e5ad36cf071796c4c7eJeff Garzik MV_HP_50XX = (1 << 6), 286e4e7b89280d1d666e2c09e5ad36cf071796c4c7eJeff Garzik MV_HP_GEN_IIE = (1 << 7), 28720f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ 28831961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ /* Port private flags (pp_flags) */ 28931961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ MV_PP_FLAG_EDMA_EN = (1 << 0), 29031961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ MV_PP_FLAG_EDMA_DS_ACT = (1 << 1), 29120f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ}; 29220f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ 293c9d39130123238ac18478a42e25cb7996eacfcc0Jeff Garzik#define IS_50XX(hpriv) ((hpriv)->hp_flags & MV_HP_50XX) 294bca1c4eb9411533d613123618c0d127fae532595Jeff Garzik#define IS_60XX(hpriv) (((hpriv)->hp_flags & MV_HP_50XX) == 0) 295e4e7b89280d1d666e2c09e5ad36cf071796c4c7eJeff Garzik#define IS_GEN_I(hpriv) IS_50XX(hpriv) 296e4e7b89280d1d666e2c09e5ad36cf071796c4c7eJeff Garzik#define IS_GEN_II(hpriv) IS_60XX(hpriv) 297e4e7b89280d1d666e2c09e5ad36cf071796c4c7eJeff Garzik#define IS_GEN_IIE(hpriv) ((hpriv)->hp_flags & MV_HP_GEN_IIE) 298bca1c4eb9411533d613123618c0d127fae532595Jeff Garzik 299095fec887eaa1c38d17c0c929a6733c744a9fa1fJeff Garzikenum { 300d88184fb2348a50f7c34f5d49a901c875b2e0114Jeff Garzik MV_DMA_BOUNDARY = 0xffffffffU, 301095fec887eaa1c38d17c0c929a6733c744a9fa1fJeff Garzik 302095fec887eaa1c38d17c0c929a6733c744a9fa1fJeff Garzik EDMA_REQ_Q_BASE_LO_MASK = 0xfffffc00U, 303095fec887eaa1c38d17c0c929a6733c744a9fa1fJeff Garzik 304095fec887eaa1c38d17c0c929a6733c744a9fa1fJeff Garzik EDMA_RSP_Q_BASE_LO_MASK = 0xffffff00U, 305095fec887eaa1c38d17c0c929a6733c744a9fa1fJeff Garzik}; 306095fec887eaa1c38d17c0c929a6733c744a9fa1fJeff Garzik 307522479fb98c6667f081e75f87e298e413c0b1db8Jeff Garzikenum chip_type { 308522479fb98c6667f081e75f87e298e413c0b1db8Jeff Garzik chip_504x, 309522479fb98c6667f081e75f87e298e413c0b1db8Jeff Garzik chip_508x, 310522479fb98c6667f081e75f87e298e413c0b1db8Jeff Garzik chip_5080, 311522479fb98c6667f081e75f87e298e413c0b1db8Jeff Garzik chip_604x, 312522479fb98c6667f081e75f87e298e413c0b1db8Jeff Garzik chip_608x, 313e4e7b89280d1d666e2c09e5ad36cf071796c4c7eJeff Garzik chip_6042, 314e4e7b89280d1d666e2c09e5ad36cf071796c4c7eJeff Garzik chip_7042, 315522479fb98c6667f081e75f87e298e413c0b1db8Jeff Garzik}; 316522479fb98c6667f081e75f87e298e413c0b1db8Jeff Garzik 31731961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ/* Command ReQuest Block: 32B */ 31831961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russstruct mv_crqb { 319e14698745dd0de1ddbf5cd0cca4313a90f8c1cc1Mark Lord __le32 sg_addr; 320e14698745dd0de1ddbf5cd0cca4313a90f8c1cc1Mark Lord __le32 sg_addr_hi; 321e14698745dd0de1ddbf5cd0cca4313a90f8c1cc1Mark Lord __le16 ctrl_flags; 322e14698745dd0de1ddbf5cd0cca4313a90f8c1cc1Mark Lord __le16 ata_cmd[11]; 32331961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ}; 32420f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ 325e4e7b89280d1d666e2c09e5ad36cf071796c4c7eJeff Garzikstruct mv_crqb_iie { 326e14698745dd0de1ddbf5cd0cca4313a90f8c1cc1Mark Lord __le32 addr; 327e14698745dd0de1ddbf5cd0cca4313a90f8c1cc1Mark Lord __le32 addr_hi; 328e14698745dd0de1ddbf5cd0cca4313a90f8c1cc1Mark Lord __le32 flags; 329e14698745dd0de1ddbf5cd0cca4313a90f8c1cc1Mark Lord __le32 len; 330e14698745dd0de1ddbf5cd0cca4313a90f8c1cc1Mark Lord __le32 ata_cmd[4]; 331e4e7b89280d1d666e2c09e5ad36cf071796c4c7eJeff Garzik}; 332e4e7b89280d1d666e2c09e5ad36cf071796c4c7eJeff Garzik 33331961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ/* Command ResPonse Block: 8B */ 33431961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russstruct mv_crpb { 335e14698745dd0de1ddbf5cd0cca4313a90f8c1cc1Mark Lord __le16 id; 336e14698745dd0de1ddbf5cd0cca4313a90f8c1cc1Mark Lord __le16 flags; 337e14698745dd0de1ddbf5cd0cca4313a90f8c1cc1Mark Lord __le32 tmstmp; 33820f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ}; 33920f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ 34031961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ/* EDMA Physical Region Descriptor (ePRD); A.K.A. SG */ 34131961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russstruct mv_sg { 342e14698745dd0de1ddbf5cd0cca4313a90f8c1cc1Mark Lord __le32 addr; 343e14698745dd0de1ddbf5cd0cca4313a90f8c1cc1Mark Lord __le32 flags_size; 344e14698745dd0de1ddbf5cd0cca4313a90f8c1cc1Mark Lord __le32 addr_hi; 345e14698745dd0de1ddbf5cd0cca4313a90f8c1cc1Mark Lord __le32 reserved; 34631961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ}; 34720f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ 34831961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russstruct mv_port_priv { 34931961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ struct mv_crqb *crqb; 35031961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ dma_addr_t crqb_dma; 35131961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ struct mv_crpb *crpb; 35231961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ dma_addr_t crpb_dma; 35331961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ struct mv_sg *sg_tbl; 35431961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ dma_addr_t sg_tbl_dma; 35531961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ u32 pp_flags; 35631961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ}; 35731961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ 358bca1c4eb9411533d613123618c0d127fae532595Jeff Garzikstruct mv_port_signal { 359bca1c4eb9411533d613123618c0d127fae532595Jeff Garzik u32 amps; 360bca1c4eb9411533d613123618c0d127fae532595Jeff Garzik u32 pre; 361bca1c4eb9411533d613123618c0d127fae532595Jeff Garzik}; 362bca1c4eb9411533d613123618c0d127fae532595Jeff Garzik 36347c2b677daeed9c79ecb7167c211ff36876ea611Jeff Garzikstruct mv_host_priv; 36447c2b677daeed9c79ecb7167c211ff36876ea611Jeff Garzikstruct mv_hw_ops { 3652a47ce06d534692f9bd2bf4e90a20fc9b1054c39Jeff Garzik void (*phy_errata)(struct mv_host_priv *hpriv, void __iomem *mmio, 3662a47ce06d534692f9bd2bf4e90a20fc9b1054c39Jeff Garzik unsigned int port); 36747c2b677daeed9c79ecb7167c211ff36876ea611Jeff Garzik void (*enable_leds)(struct mv_host_priv *hpriv, void __iomem *mmio); 36847c2b677daeed9c79ecb7167c211ff36876ea611Jeff Garzik void (*read_preamp)(struct mv_host_priv *hpriv, int idx, 36947c2b677daeed9c79ecb7167c211ff36876ea611Jeff Garzik void __iomem *mmio); 370c9d39130123238ac18478a42e25cb7996eacfcc0Jeff Garzik int (*reset_hc)(struct mv_host_priv *hpriv, void __iomem *mmio, 371c9d39130123238ac18478a42e25cb7996eacfcc0Jeff Garzik unsigned int n_hc); 372522479fb98c6667f081e75f87e298e413c0b1db8Jeff Garzik void (*reset_flash)(struct mv_host_priv *hpriv, void __iomem *mmio); 373522479fb98c6667f081e75f87e298e413c0b1db8Jeff Garzik void (*reset_bus)(struct pci_dev *pdev, void __iomem *mmio); 37447c2b677daeed9c79ecb7167c211ff36876ea611Jeff Garzik}; 37547c2b677daeed9c79ecb7167c211ff36876ea611Jeff Garzik 37631961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russstruct mv_host_priv { 37731961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ u32 hp_flags; 378bca1c4eb9411533d613123618c0d127fae532595Jeff Garzik struct mv_port_signal signal[8]; 37947c2b677daeed9c79ecb7167c211ff36876ea611Jeff Garzik const struct mv_hw_ops *ops; 38020f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ}; 38120f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ 38220f733e7d75a16bffc34842b7682c9247dd5f954Brett Russstatic void mv_irq_clear(struct ata_port *ap); 38320f733e7d75a16bffc34842b7682c9247dd5f954Brett Russstatic u32 mv_scr_read(struct ata_port *ap, unsigned int sc_reg_in); 38420f733e7d75a16bffc34842b7682c9247dd5f954Brett Russstatic void mv_scr_write(struct ata_port *ap, unsigned int sc_reg_in, u32 val); 385c9d39130123238ac18478a42e25cb7996eacfcc0Jeff Garzikstatic u32 mv5_scr_read(struct ata_port *ap, unsigned int sc_reg_in); 386c9d39130123238ac18478a42e25cb7996eacfcc0Jeff Garzikstatic void mv5_scr_write(struct ata_port *ap, unsigned int sc_reg_in, u32 val); 38720f733e7d75a16bffc34842b7682c9247dd5f954Brett Russstatic void mv_phy_reset(struct ata_port *ap); 38822374677d18c5eeefd3a283431d312b8c44fef02Jeff Garzikstatic void __mv_phy_reset(struct ata_port *ap, int can_sleep); 38931961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russstatic int mv_port_start(struct ata_port *ap); 39031961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russstatic void mv_port_stop(struct ata_port *ap); 39131961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russstatic void mv_qc_prep(struct ata_queued_cmd *qc); 392e4e7b89280d1d666e2c09e5ad36cf071796c4c7eJeff Garzikstatic void mv_qc_prep_iie(struct ata_queued_cmd *qc); 3939a3d9eb0177eb10500d49cd283b35576082a522dTejun Heostatic unsigned int mv_qc_issue(struct ata_queued_cmd *qc); 39431961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russstatic void mv_eng_timeout(struct ata_port *ap); 39520f733e7d75a16bffc34842b7682c9247dd5f954Brett Russstatic int mv_init_one(struct pci_dev *pdev, const struct pci_device_id *ent); 39620f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ 3972a47ce06d534692f9bd2bf4e90a20fc9b1054c39Jeff Garzikstatic void mv5_phy_errata(struct mv_host_priv *hpriv, void __iomem *mmio, 3982a47ce06d534692f9bd2bf4e90a20fc9b1054c39Jeff Garzik unsigned int port); 39947c2b677daeed9c79ecb7167c211ff36876ea611Jeff Garzikstatic void mv5_enable_leds(struct mv_host_priv *hpriv, void __iomem *mmio); 40047c2b677daeed9c79ecb7167c211ff36876ea611Jeff Garzikstatic void mv5_read_preamp(struct mv_host_priv *hpriv, int idx, 40147c2b677daeed9c79ecb7167c211ff36876ea611Jeff Garzik void __iomem *mmio); 402c9d39130123238ac18478a42e25cb7996eacfcc0Jeff Garzikstatic int mv5_reset_hc(struct mv_host_priv *hpriv, void __iomem *mmio, 403c9d39130123238ac18478a42e25cb7996eacfcc0Jeff Garzik unsigned int n_hc); 404522479fb98c6667f081e75f87e298e413c0b1db8Jeff Garzikstatic void mv5_reset_flash(struct mv_host_priv *hpriv, void __iomem *mmio); 405522479fb98c6667f081e75f87e298e413c0b1db8Jeff Garzikstatic void mv5_reset_bus(struct pci_dev *pdev, void __iomem *mmio); 40647c2b677daeed9c79ecb7167c211ff36876ea611Jeff Garzik 4072a47ce06d534692f9bd2bf4e90a20fc9b1054c39Jeff Garzikstatic void mv6_phy_errata(struct mv_host_priv *hpriv, void __iomem *mmio, 4082a47ce06d534692f9bd2bf4e90a20fc9b1054c39Jeff Garzik unsigned int port); 40947c2b677daeed9c79ecb7167c211ff36876ea611Jeff Garzikstatic void mv6_enable_leds(struct mv_host_priv *hpriv, void __iomem *mmio); 41047c2b677daeed9c79ecb7167c211ff36876ea611Jeff Garzikstatic void mv6_read_preamp(struct mv_host_priv *hpriv, int idx, 41147c2b677daeed9c79ecb7167c211ff36876ea611Jeff Garzik void __iomem *mmio); 412c9d39130123238ac18478a42e25cb7996eacfcc0Jeff Garzikstatic int mv6_reset_hc(struct mv_host_priv *hpriv, void __iomem *mmio, 413c9d39130123238ac18478a42e25cb7996eacfcc0Jeff Garzik unsigned int n_hc); 414522479fb98c6667f081e75f87e298e413c0b1db8Jeff Garzikstatic void mv6_reset_flash(struct mv_host_priv *hpriv, void __iomem *mmio); 415522479fb98c6667f081e75f87e298e413c0b1db8Jeff Garzikstatic void mv_reset_pci_bus(struct pci_dev *pdev, void __iomem *mmio); 416c9d39130123238ac18478a42e25cb7996eacfcc0Jeff Garzikstatic void mv_channel_reset(struct mv_host_priv *hpriv, void __iomem *mmio, 417c9d39130123238ac18478a42e25cb7996eacfcc0Jeff Garzik unsigned int port_no); 418c9d39130123238ac18478a42e25cb7996eacfcc0Jeff Garzikstatic void mv_stop_and_reset(struct ata_port *ap); 41947c2b677daeed9c79ecb7167c211ff36876ea611Jeff Garzik 420193515d51ccb363165d6b09e9ba5c21089e34badJeff Garzikstatic struct scsi_host_template mv_sht = { 42120f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ .module = THIS_MODULE, 42220f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ .name = DRV_NAME, 42320f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ .ioctl = ata_scsi_ioctl, 42420f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ .queuecommand = ata_scsi_queuecmd, 42531961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ .can_queue = MV_USE_Q_DEPTH, 42620f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ .this_id = ATA_SHT_THIS_ID, 427d88184fb2348a50f7c34f5d49a901c875b2e0114Jeff Garzik .sg_tablesize = MV_MAX_SG_CT, 42820f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ .cmd_per_lun = ATA_SHT_CMD_PER_LUN, 42920f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ .emulated = ATA_SHT_EMULATED, 430d88184fb2348a50f7c34f5d49a901c875b2e0114Jeff Garzik .use_clustering = 1, 43120f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ .proc_name = DRV_NAME, 43220f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ .dma_boundary = MV_DMA_BOUNDARY, 43320f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ .slave_configure = ata_scsi_slave_config, 434ccf68c3405fca11386004674377d951b9b18e756Tejun Heo .slave_destroy = ata_scsi_slave_destroy, 43520f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ .bios_param = ata_std_bios_param, 43620f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ}; 43720f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ 438c9d39130123238ac18478a42e25cb7996eacfcc0Jeff Garzikstatic const struct ata_port_operations mv5_ops = { 439c9d39130123238ac18478a42e25cb7996eacfcc0Jeff Garzik .port_disable = ata_port_disable, 440c9d39130123238ac18478a42e25cb7996eacfcc0Jeff Garzik 441c9d39130123238ac18478a42e25cb7996eacfcc0Jeff Garzik .tf_load = ata_tf_load, 442c9d39130123238ac18478a42e25cb7996eacfcc0Jeff Garzik .tf_read = ata_tf_read, 443c9d39130123238ac18478a42e25cb7996eacfcc0Jeff Garzik .check_status = ata_check_status, 444c9d39130123238ac18478a42e25cb7996eacfcc0Jeff Garzik .exec_command = ata_exec_command, 445c9d39130123238ac18478a42e25cb7996eacfcc0Jeff Garzik .dev_select = ata_std_dev_select, 446c9d39130123238ac18478a42e25cb7996eacfcc0Jeff Garzik 447c9d39130123238ac18478a42e25cb7996eacfcc0Jeff Garzik .phy_reset = mv_phy_reset, 448cffacd85bcf6fc652292001873119333555fe260Jeff Garzik .cable_detect = ata_cable_sata, 449c9d39130123238ac18478a42e25cb7996eacfcc0Jeff Garzik 450c9d39130123238ac18478a42e25cb7996eacfcc0Jeff Garzik .qc_prep = mv_qc_prep, 451c9d39130123238ac18478a42e25cb7996eacfcc0Jeff Garzik .qc_issue = mv_qc_issue, 4520d5ff566779f894ca9937231a181eb31e4adff0eTejun Heo .data_xfer = ata_data_xfer, 453c9d39130123238ac18478a42e25cb7996eacfcc0Jeff Garzik 454c9d39130123238ac18478a42e25cb7996eacfcc0Jeff Garzik .eng_timeout = mv_eng_timeout, 455c9d39130123238ac18478a42e25cb7996eacfcc0Jeff Garzik 456c9d39130123238ac18478a42e25cb7996eacfcc0Jeff Garzik .irq_clear = mv_irq_clear, 457246ce3b675843e0369643cceb4faeb6cf6d19a30Akira Iguchi .irq_on = ata_irq_on, 458246ce3b675843e0369643cceb4faeb6cf6d19a30Akira Iguchi .irq_ack = ata_irq_ack, 459c9d39130123238ac18478a42e25cb7996eacfcc0Jeff Garzik 460c9d39130123238ac18478a42e25cb7996eacfcc0Jeff Garzik .scr_read = mv5_scr_read, 461c9d39130123238ac18478a42e25cb7996eacfcc0Jeff Garzik .scr_write = mv5_scr_write, 462c9d39130123238ac18478a42e25cb7996eacfcc0Jeff Garzik 463c9d39130123238ac18478a42e25cb7996eacfcc0Jeff Garzik .port_start = mv_port_start, 464c9d39130123238ac18478a42e25cb7996eacfcc0Jeff Garzik .port_stop = mv_port_stop, 465c9d39130123238ac18478a42e25cb7996eacfcc0Jeff Garzik}; 466c9d39130123238ac18478a42e25cb7996eacfcc0Jeff Garzik 467c9d39130123238ac18478a42e25cb7996eacfcc0Jeff Garzikstatic const struct ata_port_operations mv6_ops = { 46820f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ .port_disable = ata_port_disable, 46920f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ 47020f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ .tf_load = ata_tf_load, 47120f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ .tf_read = ata_tf_read, 47220f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ .check_status = ata_check_status, 47320f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ .exec_command = ata_exec_command, 47420f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ .dev_select = ata_std_dev_select, 47520f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ 47620f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ .phy_reset = mv_phy_reset, 477cffacd85bcf6fc652292001873119333555fe260Jeff Garzik .cable_detect = ata_cable_sata, 47820f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ 47931961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ .qc_prep = mv_qc_prep, 48031961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ .qc_issue = mv_qc_issue, 4810d5ff566779f894ca9937231a181eb31e4adff0eTejun Heo .data_xfer = ata_data_xfer, 48220f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ 48331961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ .eng_timeout = mv_eng_timeout, 48420f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ 48520f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ .irq_clear = mv_irq_clear, 486246ce3b675843e0369643cceb4faeb6cf6d19a30Akira Iguchi .irq_on = ata_irq_on, 487246ce3b675843e0369643cceb4faeb6cf6d19a30Akira Iguchi .irq_ack = ata_irq_ack, 48820f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ 48920f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ .scr_read = mv_scr_read, 49020f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ .scr_write = mv_scr_write, 49120f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ 49231961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ .port_start = mv_port_start, 49331961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ .port_stop = mv_port_stop, 49420f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ}; 49520f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ 496e4e7b89280d1d666e2c09e5ad36cf071796c4c7eJeff Garzikstatic const struct ata_port_operations mv_iie_ops = { 497e4e7b89280d1d666e2c09e5ad36cf071796c4c7eJeff Garzik .port_disable = ata_port_disable, 498e4e7b89280d1d666e2c09e5ad36cf071796c4c7eJeff Garzik 499e4e7b89280d1d666e2c09e5ad36cf071796c4c7eJeff Garzik .tf_load = ata_tf_load, 500e4e7b89280d1d666e2c09e5ad36cf071796c4c7eJeff Garzik .tf_read = ata_tf_read, 501e4e7b89280d1d666e2c09e5ad36cf071796c4c7eJeff Garzik .check_status = ata_check_status, 502e4e7b89280d1d666e2c09e5ad36cf071796c4c7eJeff Garzik .exec_command = ata_exec_command, 503e4e7b89280d1d666e2c09e5ad36cf071796c4c7eJeff Garzik .dev_select = ata_std_dev_select, 504e4e7b89280d1d666e2c09e5ad36cf071796c4c7eJeff Garzik 505e4e7b89280d1d666e2c09e5ad36cf071796c4c7eJeff Garzik .phy_reset = mv_phy_reset, 506cffacd85bcf6fc652292001873119333555fe260Jeff Garzik .cable_detect = ata_cable_sata, 507e4e7b89280d1d666e2c09e5ad36cf071796c4c7eJeff Garzik 508e4e7b89280d1d666e2c09e5ad36cf071796c4c7eJeff Garzik .qc_prep = mv_qc_prep_iie, 509e4e7b89280d1d666e2c09e5ad36cf071796c4c7eJeff Garzik .qc_issue = mv_qc_issue, 5100d5ff566779f894ca9937231a181eb31e4adff0eTejun Heo .data_xfer = ata_data_xfer, 511e4e7b89280d1d666e2c09e5ad36cf071796c4c7eJeff Garzik 512e4e7b89280d1d666e2c09e5ad36cf071796c4c7eJeff Garzik .eng_timeout = mv_eng_timeout, 513e4e7b89280d1d666e2c09e5ad36cf071796c4c7eJeff Garzik 514e4e7b89280d1d666e2c09e5ad36cf071796c4c7eJeff Garzik .irq_clear = mv_irq_clear, 515246ce3b675843e0369643cceb4faeb6cf6d19a30Akira Iguchi .irq_on = ata_irq_on, 516246ce3b675843e0369643cceb4faeb6cf6d19a30Akira Iguchi .irq_ack = ata_irq_ack, 517e4e7b89280d1d666e2c09e5ad36cf071796c4c7eJeff Garzik 518e4e7b89280d1d666e2c09e5ad36cf071796c4c7eJeff Garzik .scr_read = mv_scr_read, 519e4e7b89280d1d666e2c09e5ad36cf071796c4c7eJeff Garzik .scr_write = mv_scr_write, 520e4e7b89280d1d666e2c09e5ad36cf071796c4c7eJeff Garzik 521e4e7b89280d1d666e2c09e5ad36cf071796c4c7eJeff Garzik .port_start = mv_port_start, 522e4e7b89280d1d666e2c09e5ad36cf071796c4c7eJeff Garzik .port_stop = mv_port_stop, 523e4e7b89280d1d666e2c09e5ad36cf071796c4c7eJeff Garzik}; 524e4e7b89280d1d666e2c09e5ad36cf071796c4c7eJeff Garzik 52598ac62defe529d04a192688f40d801a2d8fbcf98Arjan van de Venstatic const struct ata_port_info mv_port_info[] = { 52620f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ { /* chip_504x */ 527cca3974e48607c3775dc73b544a5700b2e37c21aJeff Garzik .flags = MV_COMMON_FLAGS, 52831961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ .pio_mask = 0x1f, /* pio0-4 */ 529bf6263a853c9c143bf03f0a6fdcc68ab714fb5f5Jeff Garzik .udma_mask = ATA_UDMA6, 530c9d39130123238ac18478a42e25cb7996eacfcc0Jeff Garzik .port_ops = &mv5_ops, 53120f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ }, 53220f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ { /* chip_508x */ 533cca3974e48607c3775dc73b544a5700b2e37c21aJeff Garzik .flags = (MV_COMMON_FLAGS | MV_FLAG_DUAL_HC), 53431961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ .pio_mask = 0x1f, /* pio0-4 */ 535bf6263a853c9c143bf03f0a6fdcc68ab714fb5f5Jeff Garzik .udma_mask = ATA_UDMA6, 536c9d39130123238ac18478a42e25cb7996eacfcc0Jeff Garzik .port_ops = &mv5_ops, 53720f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ }, 53847c2b677daeed9c79ecb7167c211ff36876ea611Jeff Garzik { /* chip_5080 */ 539cca3974e48607c3775dc73b544a5700b2e37c21aJeff Garzik .flags = (MV_COMMON_FLAGS | MV_FLAG_DUAL_HC), 54047c2b677daeed9c79ecb7167c211ff36876ea611Jeff Garzik .pio_mask = 0x1f, /* pio0-4 */ 541bf6263a853c9c143bf03f0a6fdcc68ab714fb5f5Jeff Garzik .udma_mask = ATA_UDMA6, 542c9d39130123238ac18478a42e25cb7996eacfcc0Jeff Garzik .port_ops = &mv5_ops, 54347c2b677daeed9c79ecb7167c211ff36876ea611Jeff Garzik }, 54420f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ { /* chip_604x */ 545cca3974e48607c3775dc73b544a5700b2e37c21aJeff Garzik .flags = (MV_COMMON_FLAGS | MV_6XXX_FLAGS), 54631961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ .pio_mask = 0x1f, /* pio0-4 */ 547bf6263a853c9c143bf03f0a6fdcc68ab714fb5f5Jeff Garzik .udma_mask = ATA_UDMA6, 548c9d39130123238ac18478a42e25cb7996eacfcc0Jeff Garzik .port_ops = &mv6_ops, 54920f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ }, 55020f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ { /* chip_608x */ 551cca3974e48607c3775dc73b544a5700b2e37c21aJeff Garzik .flags = (MV_COMMON_FLAGS | MV_6XXX_FLAGS | 55231961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ MV_FLAG_DUAL_HC), 55331961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ .pio_mask = 0x1f, /* pio0-4 */ 554bf6263a853c9c143bf03f0a6fdcc68ab714fb5f5Jeff Garzik .udma_mask = ATA_UDMA6, 555c9d39130123238ac18478a42e25cb7996eacfcc0Jeff Garzik .port_ops = &mv6_ops, 55620f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ }, 557e4e7b89280d1d666e2c09e5ad36cf071796c4c7eJeff Garzik { /* chip_6042 */ 558cca3974e48607c3775dc73b544a5700b2e37c21aJeff Garzik .flags = (MV_COMMON_FLAGS | MV_6XXX_FLAGS), 559e4e7b89280d1d666e2c09e5ad36cf071796c4c7eJeff Garzik .pio_mask = 0x1f, /* pio0-4 */ 560bf6263a853c9c143bf03f0a6fdcc68ab714fb5f5Jeff Garzik .udma_mask = ATA_UDMA6, 561e4e7b89280d1d666e2c09e5ad36cf071796c4c7eJeff Garzik .port_ops = &mv_iie_ops, 562e4e7b89280d1d666e2c09e5ad36cf071796c4c7eJeff Garzik }, 563e4e7b89280d1d666e2c09e5ad36cf071796c4c7eJeff Garzik { /* chip_7042 */ 564e93f09dc2d49d8e98818a93ad17f3ede91533738Olof Johansson .flags = (MV_COMMON_FLAGS | MV_6XXX_FLAGS), 565e4e7b89280d1d666e2c09e5ad36cf071796c4c7eJeff Garzik .pio_mask = 0x1f, /* pio0-4 */ 566bf6263a853c9c143bf03f0a6fdcc68ab714fb5f5Jeff Garzik .udma_mask = ATA_UDMA6, 567e4e7b89280d1d666e2c09e5ad36cf071796c4c7eJeff Garzik .port_ops = &mv_iie_ops, 568e4e7b89280d1d666e2c09e5ad36cf071796c4c7eJeff Garzik }, 56920f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ}; 57020f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ 5713b7d697dfb7d03edb87e50b743a7ecff029618e9Jeff Garzikstatic const struct pci_device_id mv_pci_tbl[] = { 5722d2744fc8be620a2dc469cf48349e3e704119f1bJeff Garzik { PCI_VDEVICE(MARVELL, 0x5040), chip_504x }, 5732d2744fc8be620a2dc469cf48349e3e704119f1bJeff Garzik { PCI_VDEVICE(MARVELL, 0x5041), chip_504x }, 5742d2744fc8be620a2dc469cf48349e3e704119f1bJeff Garzik { PCI_VDEVICE(MARVELL, 0x5080), chip_5080 }, 5752d2744fc8be620a2dc469cf48349e3e704119f1bJeff Garzik { PCI_VDEVICE(MARVELL, 0x5081), chip_508x }, 5762d2744fc8be620a2dc469cf48349e3e704119f1bJeff Garzik 5772d2744fc8be620a2dc469cf48349e3e704119f1bJeff Garzik { PCI_VDEVICE(MARVELL, 0x6040), chip_604x }, 5782d2744fc8be620a2dc469cf48349e3e704119f1bJeff Garzik { PCI_VDEVICE(MARVELL, 0x6041), chip_604x }, 5792d2744fc8be620a2dc469cf48349e3e704119f1bJeff Garzik { PCI_VDEVICE(MARVELL, 0x6042), chip_6042 }, 5802d2744fc8be620a2dc469cf48349e3e704119f1bJeff Garzik { PCI_VDEVICE(MARVELL, 0x6080), chip_608x }, 5812d2744fc8be620a2dc469cf48349e3e704119f1bJeff Garzik { PCI_VDEVICE(MARVELL, 0x6081), chip_608x }, 5822d2744fc8be620a2dc469cf48349e3e704119f1bJeff Garzik 5832d2744fc8be620a2dc469cf48349e3e704119f1bJeff Garzik { PCI_VDEVICE(ADAPTEC2, 0x0241), chip_604x }, 5842d2744fc8be620a2dc469cf48349e3e704119f1bJeff Garzik 585d9f9c6bc91c14f53ffa782ffcd42259ecae1d38cFlorian Attenberger /* Adaptec 1430SA */ 586d9f9c6bc91c14f53ffa782ffcd42259ecae1d38cFlorian Attenberger { PCI_VDEVICE(ADAPTEC2, 0x0243), chip_7042 }, 587d9f9c6bc91c14f53ffa782ffcd42259ecae1d38cFlorian Attenberger 588e93f09dc2d49d8e98818a93ad17f3ede91533738Olof Johansson { PCI_VDEVICE(TTI, 0x2310), chip_7042 }, 589e93f09dc2d49d8e98818a93ad17f3ede91533738Olof Johansson 5906a3d586d8e8a50e4cfd7f8c36d82a53c5614e05bMorrison, Tom /* add Marvell 7042 support */ 5916a3d586d8e8a50e4cfd7f8c36d82a53c5614e05bMorrison, Tom { PCI_VDEVICE(MARVELL, 0x7042), chip_7042 }, 5926a3d586d8e8a50e4cfd7f8c36d82a53c5614e05bMorrison, Tom 5932d2744fc8be620a2dc469cf48349e3e704119f1bJeff Garzik { } /* terminate list */ 59420f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ}; 59520f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ 59620f733e7d75a16bffc34842b7682c9247dd5f954Brett Russstatic struct pci_driver mv_pci_driver = { 59720f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ .name = DRV_NAME, 59820f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ .id_table = mv_pci_tbl, 59920f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ .probe = mv_init_one, 60020f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ .remove = ata_pci_remove_one, 60120f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ}; 60220f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ 60347c2b677daeed9c79ecb7167c211ff36876ea611Jeff Garzikstatic const struct mv_hw_ops mv5xxx_ops = { 60447c2b677daeed9c79ecb7167c211ff36876ea611Jeff Garzik .phy_errata = mv5_phy_errata, 60547c2b677daeed9c79ecb7167c211ff36876ea611Jeff Garzik .enable_leds = mv5_enable_leds, 60647c2b677daeed9c79ecb7167c211ff36876ea611Jeff Garzik .read_preamp = mv5_read_preamp, 60747c2b677daeed9c79ecb7167c211ff36876ea611Jeff Garzik .reset_hc = mv5_reset_hc, 608522479fb98c6667f081e75f87e298e413c0b1db8Jeff Garzik .reset_flash = mv5_reset_flash, 609522479fb98c6667f081e75f87e298e413c0b1db8Jeff Garzik .reset_bus = mv5_reset_bus, 61047c2b677daeed9c79ecb7167c211ff36876ea611Jeff Garzik}; 61147c2b677daeed9c79ecb7167c211ff36876ea611Jeff Garzik 61247c2b677daeed9c79ecb7167c211ff36876ea611Jeff Garzikstatic const struct mv_hw_ops mv6xxx_ops = { 61347c2b677daeed9c79ecb7167c211ff36876ea611Jeff Garzik .phy_errata = mv6_phy_errata, 61447c2b677daeed9c79ecb7167c211ff36876ea611Jeff Garzik .enable_leds = mv6_enable_leds, 61547c2b677daeed9c79ecb7167c211ff36876ea611Jeff Garzik .read_preamp = mv6_read_preamp, 61647c2b677daeed9c79ecb7167c211ff36876ea611Jeff Garzik .reset_hc = mv6_reset_hc, 617522479fb98c6667f081e75f87e298e413c0b1db8Jeff Garzik .reset_flash = mv6_reset_flash, 618522479fb98c6667f081e75f87e298e413c0b1db8Jeff Garzik .reset_bus = mv_reset_pci_bus, 61947c2b677daeed9c79ecb7167c211ff36876ea611Jeff Garzik}; 62047c2b677daeed9c79ecb7167c211ff36876ea611Jeff Garzik 62120f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ/* 622ddef9bb367b19383df627e388cb4c01c86ddba6cJeff Garzik * module options 623ddef9bb367b19383df627e388cb4c01c86ddba6cJeff Garzik */ 624ddef9bb367b19383df627e388cb4c01c86ddba6cJeff Garzikstatic int msi; /* Use PCI msi; either zero (off, default) or non-zero */ 625ddef9bb367b19383df627e388cb4c01c86ddba6cJeff Garzik 626ddef9bb367b19383df627e388cb4c01c86ddba6cJeff Garzik 627d88184fb2348a50f7c34f5d49a901c875b2e0114Jeff Garzik/* move to PCI layer or libata core? */ 628d88184fb2348a50f7c34f5d49a901c875b2e0114Jeff Garzikstatic int pci_go_64(struct pci_dev *pdev) 629d88184fb2348a50f7c34f5d49a901c875b2e0114Jeff Garzik{ 630d88184fb2348a50f7c34f5d49a901c875b2e0114Jeff Garzik int rc; 631d88184fb2348a50f7c34f5d49a901c875b2e0114Jeff Garzik 632d88184fb2348a50f7c34f5d49a901c875b2e0114Jeff Garzik if (!pci_set_dma_mask(pdev, DMA_64BIT_MASK)) { 633d88184fb2348a50f7c34f5d49a901c875b2e0114Jeff Garzik rc = pci_set_consistent_dma_mask(pdev, DMA_64BIT_MASK); 634d88184fb2348a50f7c34f5d49a901c875b2e0114Jeff Garzik if (rc) { 635d88184fb2348a50f7c34f5d49a901c875b2e0114Jeff Garzik rc = pci_set_consistent_dma_mask(pdev, DMA_32BIT_MASK); 636d88184fb2348a50f7c34f5d49a901c875b2e0114Jeff Garzik if (rc) { 637d88184fb2348a50f7c34f5d49a901c875b2e0114Jeff Garzik dev_printk(KERN_ERR, &pdev->dev, 638d88184fb2348a50f7c34f5d49a901c875b2e0114Jeff Garzik "64-bit DMA enable failed\n"); 639d88184fb2348a50f7c34f5d49a901c875b2e0114Jeff Garzik return rc; 640d88184fb2348a50f7c34f5d49a901c875b2e0114Jeff Garzik } 641d88184fb2348a50f7c34f5d49a901c875b2e0114Jeff Garzik } 642d88184fb2348a50f7c34f5d49a901c875b2e0114Jeff Garzik } else { 643d88184fb2348a50f7c34f5d49a901c875b2e0114Jeff Garzik rc = pci_set_dma_mask(pdev, DMA_32BIT_MASK); 644d88184fb2348a50f7c34f5d49a901c875b2e0114Jeff Garzik if (rc) { 645d88184fb2348a50f7c34f5d49a901c875b2e0114Jeff Garzik dev_printk(KERN_ERR, &pdev->dev, 646d88184fb2348a50f7c34f5d49a901c875b2e0114Jeff Garzik "32-bit DMA enable failed\n"); 647d88184fb2348a50f7c34f5d49a901c875b2e0114Jeff Garzik return rc; 648d88184fb2348a50f7c34f5d49a901c875b2e0114Jeff Garzik } 649d88184fb2348a50f7c34f5d49a901c875b2e0114Jeff Garzik rc = pci_set_consistent_dma_mask(pdev, DMA_32BIT_MASK); 650d88184fb2348a50f7c34f5d49a901c875b2e0114Jeff Garzik if (rc) { 651d88184fb2348a50f7c34f5d49a901c875b2e0114Jeff Garzik dev_printk(KERN_ERR, &pdev->dev, 652d88184fb2348a50f7c34f5d49a901c875b2e0114Jeff Garzik "32-bit consistent DMA enable failed\n"); 653d88184fb2348a50f7c34f5d49a901c875b2e0114Jeff Garzik return rc; 654d88184fb2348a50f7c34f5d49a901c875b2e0114Jeff Garzik } 655d88184fb2348a50f7c34f5d49a901c875b2e0114Jeff Garzik } 656d88184fb2348a50f7c34f5d49a901c875b2e0114Jeff Garzik 657d88184fb2348a50f7c34f5d49a901c875b2e0114Jeff Garzik return rc; 658d88184fb2348a50f7c34f5d49a901c875b2e0114Jeff Garzik} 659d88184fb2348a50f7c34f5d49a901c875b2e0114Jeff Garzik 660ddef9bb367b19383df627e388cb4c01c86ddba6cJeff Garzik/* 66120f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ * Functions 66220f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ */ 66320f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ 66420f733e7d75a16bffc34842b7682c9247dd5f954Brett Russstatic inline void writelfl(unsigned long data, void __iomem *addr) 66520f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ{ 66620f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ writel(data, addr); 66720f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ (void) readl(addr); /* flush to avoid PCI posted write */ 66820f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ} 66920f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ 67020f733e7d75a16bffc34842b7682c9247dd5f954Brett Russstatic inline void __iomem *mv_hc_base(void __iomem *base, unsigned int hc) 67120f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ{ 67220f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ return (base + MV_SATAHC0_REG_BASE + (hc * MV_SATAHC_REG_SZ)); 67320f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ} 67420f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ 675c9d39130123238ac18478a42e25cb7996eacfcc0Jeff Garzikstatic inline unsigned int mv_hc_from_port(unsigned int port) 676c9d39130123238ac18478a42e25cb7996eacfcc0Jeff Garzik{ 677c9d39130123238ac18478a42e25cb7996eacfcc0Jeff Garzik return port >> MV_PORT_HC_SHIFT; 678c9d39130123238ac18478a42e25cb7996eacfcc0Jeff Garzik} 679c9d39130123238ac18478a42e25cb7996eacfcc0Jeff Garzik 680c9d39130123238ac18478a42e25cb7996eacfcc0Jeff Garzikstatic inline unsigned int mv_hardport_from_port(unsigned int port) 681c9d39130123238ac18478a42e25cb7996eacfcc0Jeff Garzik{ 682c9d39130123238ac18478a42e25cb7996eacfcc0Jeff Garzik return port & MV_PORT_MASK; 683c9d39130123238ac18478a42e25cb7996eacfcc0Jeff Garzik} 684c9d39130123238ac18478a42e25cb7996eacfcc0Jeff Garzik 685c9d39130123238ac18478a42e25cb7996eacfcc0Jeff Garzikstatic inline void __iomem *mv_hc_base_from_port(void __iomem *base, 686c9d39130123238ac18478a42e25cb7996eacfcc0Jeff Garzik unsigned int port) 687c9d39130123238ac18478a42e25cb7996eacfcc0Jeff Garzik{ 688c9d39130123238ac18478a42e25cb7996eacfcc0Jeff Garzik return mv_hc_base(base, mv_hc_from_port(port)); 689c9d39130123238ac18478a42e25cb7996eacfcc0Jeff Garzik} 690c9d39130123238ac18478a42e25cb7996eacfcc0Jeff Garzik 69120f733e7d75a16bffc34842b7682c9247dd5f954Brett Russstatic inline void __iomem *mv_port_base(void __iomem *base, unsigned int port) 69220f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ{ 693c9d39130123238ac18478a42e25cb7996eacfcc0Jeff Garzik return mv_hc_base_from_port(base, port) + 6948b260248d9e0e8b64bb72fd4dee03ad86984c344Jeff Garzik MV_SATAHC_ARBTR_REG_SZ + 695c9d39130123238ac18478a42e25cb7996eacfcc0Jeff Garzik (mv_hardport_from_port(port) * MV_PORT_REG_SZ); 69620f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ} 69720f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ 69820f733e7d75a16bffc34842b7682c9247dd5f954Brett Russstatic inline void __iomem *mv_ap_base(struct ata_port *ap) 69920f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ{ 7000d5ff566779f894ca9937231a181eb31e4adff0eTejun Heo return mv_port_base(ap->host->iomap[MV_PRIMARY_BAR], ap->port_no); 70120f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ} 70220f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ 703cca3974e48607c3775dc73b544a5700b2e37c21aJeff Garzikstatic inline int mv_get_hc_count(unsigned long port_flags) 70431961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ{ 705cca3974e48607c3775dc73b544a5700b2e37c21aJeff Garzik return ((port_flags & MV_FLAG_DUAL_HC) ? 2 : 1); 70631961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ} 70731961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ 70831961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russstatic void mv_irq_clear(struct ata_port *ap) 70920f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ{ 71020f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ} 71120f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ 71205b308e1df6d9d673daedb517969241f41278b52Brett Russ/** 71305b308e1df6d9d673daedb517969241f41278b52Brett Russ * mv_start_dma - Enable eDMA engine 71405b308e1df6d9d673daedb517969241f41278b52Brett Russ * @base: port base address 71505b308e1df6d9d673daedb517969241f41278b52Brett Russ * @pp: port private data 71605b308e1df6d9d673daedb517969241f41278b52Brett Russ * 717beec7dbc6ff003bbc94de62b3323519c878fb2acTejun Heo * Verify the local cache of the eDMA state is accurate with a 718beec7dbc6ff003bbc94de62b3323519c878fb2acTejun Heo * WARN_ON. 71905b308e1df6d9d673daedb517969241f41278b52Brett Russ * 72005b308e1df6d9d673daedb517969241f41278b52Brett Russ * LOCKING: 72105b308e1df6d9d673daedb517969241f41278b52Brett Russ * Inherited from caller. 72205b308e1df6d9d673daedb517969241f41278b52Brett Russ */ 723afb0edd922c7ed6e73678730921dfcccebec17e8Brett Russstatic void mv_start_dma(void __iomem *base, struct mv_port_priv *pp) 72420f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ{ 725afb0edd922c7ed6e73678730921dfcccebec17e8Brett Russ if (!(MV_PP_FLAG_EDMA_EN & pp->pp_flags)) { 726afb0edd922c7ed6e73678730921dfcccebec17e8Brett Russ writelfl(EDMA_EN, base + EDMA_CMD_OFS); 727afb0edd922c7ed6e73678730921dfcccebec17e8Brett Russ pp->pp_flags |= MV_PP_FLAG_EDMA_EN; 728afb0edd922c7ed6e73678730921dfcccebec17e8Brett Russ } 729beec7dbc6ff003bbc94de62b3323519c878fb2acTejun Heo WARN_ON(!(EDMA_EN & readl(base + EDMA_CMD_OFS))); 73020f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ} 73120f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ 73205b308e1df6d9d673daedb517969241f41278b52Brett Russ/** 73305b308e1df6d9d673daedb517969241f41278b52Brett Russ * mv_stop_dma - Disable eDMA engine 73405b308e1df6d9d673daedb517969241f41278b52Brett Russ * @ap: ATA channel to manipulate 73505b308e1df6d9d673daedb517969241f41278b52Brett Russ * 736beec7dbc6ff003bbc94de62b3323519c878fb2acTejun Heo * Verify the local cache of the eDMA state is accurate with a 737beec7dbc6ff003bbc94de62b3323519c878fb2acTejun Heo * WARN_ON. 73805b308e1df6d9d673daedb517969241f41278b52Brett Russ * 73905b308e1df6d9d673daedb517969241f41278b52Brett Russ * LOCKING: 74005b308e1df6d9d673daedb517969241f41278b52Brett Russ * Inherited from caller. 74105b308e1df6d9d673daedb517969241f41278b52Brett Russ */ 74231961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russstatic void mv_stop_dma(struct ata_port *ap) 74320f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ{ 74431961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ void __iomem *port_mmio = mv_ap_base(ap); 74531961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ struct mv_port_priv *pp = ap->private_data; 74631961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ u32 reg; 74731961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ int i; 74831961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ 749afb0edd922c7ed6e73678730921dfcccebec17e8Brett Russ if (MV_PP_FLAG_EDMA_EN & pp->pp_flags) { 750afb0edd922c7ed6e73678730921dfcccebec17e8Brett Russ /* Disable EDMA if active. The disable bit auto clears. 75131961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ */ 75231961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ writelfl(EDMA_DS, port_mmio + EDMA_CMD_OFS); 75331961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ pp->pp_flags &= ~MV_PP_FLAG_EDMA_EN; 754afb0edd922c7ed6e73678730921dfcccebec17e8Brett Russ } else { 755beec7dbc6ff003bbc94de62b3323519c878fb2acTejun Heo WARN_ON(EDMA_EN & readl(port_mmio + EDMA_CMD_OFS)); 756afb0edd922c7ed6e73678730921dfcccebec17e8Brett Russ } 7578b260248d9e0e8b64bb72fd4dee03ad86984c344Jeff Garzik 75831961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ /* now properly wait for the eDMA to stop */ 75931961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ for (i = 1000; i > 0; i--) { 76031961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ reg = readl(port_mmio + EDMA_CMD_OFS); 76131961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ if (!(EDMA_EN & reg)) { 76231961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ break; 76331961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ } 76431961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ udelay(100); 76531961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ } 76631961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ 76731961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ if (EDMA_EN & reg) { 768f15a1dafed22d5037e0feea7528e1eeb28a1a7a3Tejun Heo ata_port_printk(ap, KERN_ERR, "Unable to stop eDMA\n"); 769afb0edd922c7ed6e73678730921dfcccebec17e8Brett Russ /* FIXME: Consider doing a reset here to recover */ 77031961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ } 77120f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ} 77220f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ 7738a70f8dc08dd40b7f8ac77280eaa99a8c6bc46f4Jeff Garzik#ifdef ATA_DEBUG 77431961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russstatic void mv_dump_mem(void __iomem *start, unsigned bytes) 77520f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ{ 77631961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ int b, w; 77731961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ for (b = 0; b < bytes; ) { 77831961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ DPRINTK("%p: ", start + b); 77931961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ for (w = 0; b < bytes && w < 4; w++) { 78031961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ printk("%08x ",readl(start + b)); 78131961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ b += sizeof(u32); 78231961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ } 78331961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ printk("\n"); 78431961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ } 78531961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ} 7868a70f8dc08dd40b7f8ac77280eaa99a8c6bc46f4Jeff Garzik#endif 7878a70f8dc08dd40b7f8ac77280eaa99a8c6bc46f4Jeff Garzik 78831961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russstatic void mv_dump_pci_cfg(struct pci_dev *pdev, unsigned bytes) 78931961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ{ 79031961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ#ifdef ATA_DEBUG 79131961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ int b, w; 79231961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ u32 dw; 79331961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ for (b = 0; b < bytes; ) { 79431961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ DPRINTK("%02x: ", b); 79531961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ for (w = 0; b < bytes && w < 4; w++) { 79631961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ (void) pci_read_config_dword(pdev,b,&dw); 79731961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ printk("%08x ",dw); 79831961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ b += sizeof(u32); 79931961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ } 80031961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ printk("\n"); 80131961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ } 80231961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ#endif 80331961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ} 80431961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russstatic void mv_dump_all_regs(void __iomem *mmio_base, int port, 80531961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ struct pci_dev *pdev) 80631961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ{ 80731961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ#ifdef ATA_DEBUG 8088b260248d9e0e8b64bb72fd4dee03ad86984c344Jeff Garzik void __iomem *hc_base = mv_hc_base(mmio_base, 80931961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ port >> MV_PORT_HC_SHIFT); 81031961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ void __iomem *port_base; 81131961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ int start_port, num_ports, p, start_hc, num_hcs, hc; 81231961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ 81331961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ if (0 > port) { 81431961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ start_hc = start_port = 0; 81531961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ num_ports = 8; /* shld be benign for 4 port devs */ 81631961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ num_hcs = 2; 81731961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ } else { 81831961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ start_hc = port >> MV_PORT_HC_SHIFT; 81931961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ start_port = port; 82031961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ num_ports = num_hcs = 1; 82131961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ } 8228b260248d9e0e8b64bb72fd4dee03ad86984c344Jeff Garzik DPRINTK("All registers for port(s) %u-%u:\n", start_port, 82331961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ num_ports > 1 ? num_ports - 1 : start_port); 82431961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ 82531961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ if (NULL != pdev) { 82631961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ DPRINTK("PCI config space regs:\n"); 82731961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ mv_dump_pci_cfg(pdev, 0x68); 82831961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ } 82931961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ DPRINTK("PCI regs:\n"); 83031961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ mv_dump_mem(mmio_base+0xc00, 0x3c); 83131961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ mv_dump_mem(mmio_base+0xd00, 0x34); 83231961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ mv_dump_mem(mmio_base+0xf00, 0x4); 83331961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ mv_dump_mem(mmio_base+0x1d00, 0x6c); 83431961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ for (hc = start_hc; hc < start_hc + num_hcs; hc++) { 835d220c37e0a3c9a47ae00e87e044d963b3ea040bcDan Aloni hc_base = mv_hc_base(mmio_base, hc); 83631961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ DPRINTK("HC regs (HC %i):\n", hc); 83731961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ mv_dump_mem(hc_base, 0x1c); 83831961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ } 83931961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ for (p = start_port; p < start_port + num_ports; p++) { 84031961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ port_base = mv_port_base(mmio_base, p); 84131961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ DPRINTK("EDMA regs (port %i):\n",p); 84231961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ mv_dump_mem(port_base, 0x54); 84331961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ DPRINTK("SATA regs (port %i):\n",p); 84431961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ mv_dump_mem(port_base+0x300, 0x60); 84531961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ } 84631961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ#endif 84720f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ} 84820f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ 84920f733e7d75a16bffc34842b7682c9247dd5f954Brett Russstatic unsigned int mv_scr_offset(unsigned int sc_reg_in) 85020f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ{ 85120f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ unsigned int ofs; 85220f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ 85320f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ switch (sc_reg_in) { 85420f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ case SCR_STATUS: 85520f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ case SCR_CONTROL: 85620f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ case SCR_ERROR: 85720f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ ofs = SATA_STATUS_OFS + (sc_reg_in * sizeof(u32)); 85820f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ break; 85920f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ case SCR_ACTIVE: 86020f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ ofs = SATA_ACTIVE_OFS; /* active is not with the others */ 86120f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ break; 86220f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ default: 86320f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ ofs = 0xffffffffU; 86420f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ break; 86520f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ } 86620f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ return ofs; 86720f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ} 86820f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ 86920f733e7d75a16bffc34842b7682c9247dd5f954Brett Russstatic u32 mv_scr_read(struct ata_port *ap, unsigned int sc_reg_in) 87020f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ{ 87120f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ unsigned int ofs = mv_scr_offset(sc_reg_in); 87220f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ 873351772658a4d1acc0221a6e30676bb0594e74812Jeff Garzik if (0xffffffffU != ofs) 87420f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ return readl(mv_ap_base(ap) + ofs); 875351772658a4d1acc0221a6e30676bb0594e74812Jeff Garzik else 87620f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ return (u32) ofs; 87720f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ} 87820f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ 87920f733e7d75a16bffc34842b7682c9247dd5f954Brett Russstatic void mv_scr_write(struct ata_port *ap, unsigned int sc_reg_in, u32 val) 88020f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ{ 88120f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ unsigned int ofs = mv_scr_offset(sc_reg_in); 88220f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ 883351772658a4d1acc0221a6e30676bb0594e74812Jeff Garzik if (0xffffffffU != ofs) 88420f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ writelfl(val, mv_ap_base(ap) + ofs); 88520f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ} 88620f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ 887e4e7b89280d1d666e2c09e5ad36cf071796c4c7eJeff Garzikstatic void mv_edma_cfg(struct mv_host_priv *hpriv, void __iomem *port_mmio) 888e4e7b89280d1d666e2c09e5ad36cf071796c4c7eJeff Garzik{ 889e4e7b89280d1d666e2c09e5ad36cf071796c4c7eJeff Garzik u32 cfg = readl(port_mmio + EDMA_CFG_OFS); 890e4e7b89280d1d666e2c09e5ad36cf071796c4c7eJeff Garzik 891e4e7b89280d1d666e2c09e5ad36cf071796c4c7eJeff Garzik /* set up non-NCQ EDMA configuration */ 892e4e7b89280d1d666e2c09e5ad36cf071796c4c7eJeff Garzik cfg &= ~(1 << 9); /* disable equeue */ 893e4e7b89280d1d666e2c09e5ad36cf071796c4c7eJeff Garzik 894e728eabea110da90e69c05855e3a11174edb77efJeff Garzik if (IS_GEN_I(hpriv)) { 895e728eabea110da90e69c05855e3a11174edb77efJeff Garzik cfg &= ~0x1f; /* clear queue depth */ 896e4e7b89280d1d666e2c09e5ad36cf071796c4c7eJeff Garzik cfg |= (1 << 8); /* enab config burst size mask */ 897e728eabea110da90e69c05855e3a11174edb77efJeff Garzik } 898e4e7b89280d1d666e2c09e5ad36cf071796c4c7eJeff Garzik 899e728eabea110da90e69c05855e3a11174edb77efJeff Garzik else if (IS_GEN_II(hpriv)) { 900e728eabea110da90e69c05855e3a11174edb77efJeff Garzik cfg &= ~0x1f; /* clear queue depth */ 901e4e7b89280d1d666e2c09e5ad36cf071796c4c7eJeff Garzik cfg |= EDMA_CFG_RD_BRST_EXT | EDMA_CFG_WR_BUFF_LEN; 902e728eabea110da90e69c05855e3a11174edb77efJeff Garzik cfg &= ~(EDMA_CFG_NCQ | EDMA_CFG_NCQ_GO_ON_ERR); /* clear NCQ */ 903e728eabea110da90e69c05855e3a11174edb77efJeff Garzik } 904e4e7b89280d1d666e2c09e5ad36cf071796c4c7eJeff Garzik 905e4e7b89280d1d666e2c09e5ad36cf071796c4c7eJeff Garzik else if (IS_GEN_IIE(hpriv)) { 906e728eabea110da90e69c05855e3a11174edb77efJeff Garzik cfg |= (1 << 23); /* do not mask PM field in rx'd FIS */ 907e728eabea110da90e69c05855e3a11174edb77efJeff Garzik cfg |= (1 << 22); /* enab 4-entry host queue cache */ 908e4e7b89280d1d666e2c09e5ad36cf071796c4c7eJeff Garzik cfg &= ~(1 << 19); /* dis 128-entry queue (for now?) */ 909e4e7b89280d1d666e2c09e5ad36cf071796c4c7eJeff Garzik cfg |= (1 << 18); /* enab early completion */ 910e728eabea110da90e69c05855e3a11174edb77efJeff Garzik cfg |= (1 << 17); /* enab cut-through (dis stor&forwrd) */ 911e728eabea110da90e69c05855e3a11174edb77efJeff Garzik cfg &= ~(1 << 16); /* dis FIS-based switching (for now) */ 912e728eabea110da90e69c05855e3a11174edb77efJeff Garzik cfg &= ~(EDMA_CFG_NCQ | EDMA_CFG_NCQ_GO_ON_ERR); /* clear NCQ */ 913e4e7b89280d1d666e2c09e5ad36cf071796c4c7eJeff Garzik } 914e4e7b89280d1d666e2c09e5ad36cf071796c4c7eJeff Garzik 915e4e7b89280d1d666e2c09e5ad36cf071796c4c7eJeff Garzik writelfl(cfg, port_mmio + EDMA_CFG_OFS); 916e4e7b89280d1d666e2c09e5ad36cf071796c4c7eJeff Garzik} 917e4e7b89280d1d666e2c09e5ad36cf071796c4c7eJeff Garzik 91805b308e1df6d9d673daedb517969241f41278b52Brett Russ/** 91905b308e1df6d9d673daedb517969241f41278b52Brett Russ * mv_port_start - Port specific init/start routine. 92005b308e1df6d9d673daedb517969241f41278b52Brett Russ * @ap: ATA channel to manipulate 92105b308e1df6d9d673daedb517969241f41278b52Brett Russ * 92205b308e1df6d9d673daedb517969241f41278b52Brett Russ * Allocate and point to DMA memory, init port private memory, 92305b308e1df6d9d673daedb517969241f41278b52Brett Russ * zero indices. 92405b308e1df6d9d673daedb517969241f41278b52Brett Russ * 92505b308e1df6d9d673daedb517969241f41278b52Brett Russ * LOCKING: 92605b308e1df6d9d673daedb517969241f41278b52Brett Russ * Inherited from caller. 92705b308e1df6d9d673daedb517969241f41278b52Brett Russ */ 92831961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russstatic int mv_port_start(struct ata_port *ap) 92931961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ{ 930cca3974e48607c3775dc73b544a5700b2e37c21aJeff Garzik struct device *dev = ap->host->dev; 931cca3974e48607c3775dc73b544a5700b2e37c21aJeff Garzik struct mv_host_priv *hpriv = ap->host->private_data; 93231961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ struct mv_port_priv *pp; 93331961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ void __iomem *port_mmio = mv_ap_base(ap); 93431961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ void *mem; 93531961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ dma_addr_t mem_dma; 93624dc5f33ea4b504cfbd23fa159a4cacba8e4d800Tejun Heo int rc; 93731961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ 93824dc5f33ea4b504cfbd23fa159a4cacba8e4d800Tejun Heo pp = devm_kzalloc(dev, sizeof(*pp), GFP_KERNEL); 9396037d6bbdff65eb5a84fe35e140f4da4f7cc103aJeff Garzik if (!pp) 94024dc5f33ea4b504cfbd23fa159a4cacba8e4d800Tejun Heo return -ENOMEM; 94131961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ 94224dc5f33ea4b504cfbd23fa159a4cacba8e4d800Tejun Heo mem = dmam_alloc_coherent(dev, MV_PORT_PRIV_DMA_SZ, &mem_dma, 94324dc5f33ea4b504cfbd23fa159a4cacba8e4d800Tejun Heo GFP_KERNEL); 9446037d6bbdff65eb5a84fe35e140f4da4f7cc103aJeff Garzik if (!mem) 94524dc5f33ea4b504cfbd23fa159a4cacba8e4d800Tejun Heo return -ENOMEM; 94631961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ memset(mem, 0, MV_PORT_PRIV_DMA_SZ); 94731961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ 9486037d6bbdff65eb5a84fe35e140f4da4f7cc103aJeff Garzik rc = ata_pad_alloc(ap, dev); 9496037d6bbdff65eb5a84fe35e140f4da4f7cc103aJeff Garzik if (rc) 95024dc5f33ea4b504cfbd23fa159a4cacba8e4d800Tejun Heo return rc; 9516037d6bbdff65eb5a84fe35e140f4da4f7cc103aJeff Garzik 9528b260248d9e0e8b64bb72fd4dee03ad86984c344Jeff Garzik /* First item in chunk of DMA memory: 95331961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ * 32-slot command request table (CRQB), 32 bytes each in size 95431961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ */ 95531961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ pp->crqb = mem; 95631961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ pp->crqb_dma = mem_dma; 95731961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ mem += MV_CRQB_Q_SZ; 95831961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ mem_dma += MV_CRQB_Q_SZ; 95931961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ 9608b260248d9e0e8b64bb72fd4dee03ad86984c344Jeff Garzik /* Second item: 96131961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ * 32-slot command response table (CRPB), 8 bytes each in size 96231961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ */ 96331961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ pp->crpb = mem; 96431961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ pp->crpb_dma = mem_dma; 96531961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ mem += MV_CRPB_Q_SZ; 96631961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ mem_dma += MV_CRPB_Q_SZ; 96731961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ 96831961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ /* Third item: 96931961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ * Table of scatter-gather descriptors (ePRD), 16 bytes each 97031961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ */ 97131961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ pp->sg_tbl = mem; 97231961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ pp->sg_tbl_dma = mem_dma; 97331961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ 974e4e7b89280d1d666e2c09e5ad36cf071796c4c7eJeff Garzik mv_edma_cfg(hpriv, port_mmio); 97531961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ 97631961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ writel((pp->crqb_dma >> 16) >> 16, port_mmio + EDMA_REQ_Q_BASE_HI_OFS); 9778b260248d9e0e8b64bb72fd4dee03ad86984c344Jeff Garzik writelfl(pp->crqb_dma & EDMA_REQ_Q_BASE_LO_MASK, 97831961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ port_mmio + EDMA_REQ_Q_IN_PTR_OFS); 97931961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ 980e4e7b89280d1d666e2c09e5ad36cf071796c4c7eJeff Garzik if (hpriv->hp_flags & MV_HP_ERRATA_XX42A0) 981e4e7b89280d1d666e2c09e5ad36cf071796c4c7eJeff Garzik writelfl(pp->crqb_dma & 0xffffffff, 982e4e7b89280d1d666e2c09e5ad36cf071796c4c7eJeff Garzik port_mmio + EDMA_REQ_Q_OUT_PTR_OFS); 983e4e7b89280d1d666e2c09e5ad36cf071796c4c7eJeff Garzik else 984e4e7b89280d1d666e2c09e5ad36cf071796c4c7eJeff Garzik writelfl(0, port_mmio + EDMA_REQ_Q_OUT_PTR_OFS); 98531961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ 98631961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ writel((pp->crpb_dma >> 16) >> 16, port_mmio + EDMA_RSP_Q_BASE_HI_OFS); 987e4e7b89280d1d666e2c09e5ad36cf071796c4c7eJeff Garzik 988e4e7b89280d1d666e2c09e5ad36cf071796c4c7eJeff Garzik if (hpriv->hp_flags & MV_HP_ERRATA_XX42A0) 989e4e7b89280d1d666e2c09e5ad36cf071796c4c7eJeff Garzik writelfl(pp->crpb_dma & 0xffffffff, 990e4e7b89280d1d666e2c09e5ad36cf071796c4c7eJeff Garzik port_mmio + EDMA_RSP_Q_IN_PTR_OFS); 991e4e7b89280d1d666e2c09e5ad36cf071796c4c7eJeff Garzik else 992e4e7b89280d1d666e2c09e5ad36cf071796c4c7eJeff Garzik writelfl(0, port_mmio + EDMA_RSP_Q_IN_PTR_OFS); 993e4e7b89280d1d666e2c09e5ad36cf071796c4c7eJeff Garzik 9948b260248d9e0e8b64bb72fd4dee03ad86984c344Jeff Garzik writelfl(pp->crpb_dma & EDMA_RSP_Q_BASE_LO_MASK, 99531961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ port_mmio + EDMA_RSP_Q_OUT_PTR_OFS); 99631961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ 99731961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ /* Don't turn on EDMA here...do it before DMA commands only. Else 99831961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ * we'll be unable to send non-data, PIO, etc due to restricted access 99931961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ * to shadow regs. 100031961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ */ 100131961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ ap->private_data = pp; 100231961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ return 0; 100331961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ} 100431961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ 100505b308e1df6d9d673daedb517969241f41278b52Brett Russ/** 100605b308e1df6d9d673daedb517969241f41278b52Brett Russ * mv_port_stop - Port specific cleanup/stop routine. 100705b308e1df6d9d673daedb517969241f41278b52Brett Russ * @ap: ATA channel to manipulate 100805b308e1df6d9d673daedb517969241f41278b52Brett Russ * 100905b308e1df6d9d673daedb517969241f41278b52Brett Russ * Stop DMA, cleanup port memory. 101005b308e1df6d9d673daedb517969241f41278b52Brett Russ * 101105b308e1df6d9d673daedb517969241f41278b52Brett Russ * LOCKING: 1012cca3974e48607c3775dc73b544a5700b2e37c21aJeff Garzik * This routine uses the host lock to protect the DMA stop. 101305b308e1df6d9d673daedb517969241f41278b52Brett Russ */ 101431961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russstatic void mv_port_stop(struct ata_port *ap) 101531961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ{ 1016afb0edd922c7ed6e73678730921dfcccebec17e8Brett Russ unsigned long flags; 101731961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ 1018cca3974e48607c3775dc73b544a5700b2e37c21aJeff Garzik spin_lock_irqsave(&ap->host->lock, flags); 101931961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ mv_stop_dma(ap); 1020cca3974e48607c3775dc73b544a5700b2e37c21aJeff Garzik spin_unlock_irqrestore(&ap->host->lock, flags); 102131961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ} 102231961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ 102305b308e1df6d9d673daedb517969241f41278b52Brett Russ/** 102405b308e1df6d9d673daedb517969241f41278b52Brett Russ * mv_fill_sg - Fill out the Marvell ePRD (scatter gather) entries 102505b308e1df6d9d673daedb517969241f41278b52Brett Russ * @qc: queued command whose SG list to source from 102605b308e1df6d9d673daedb517969241f41278b52Brett Russ * 102705b308e1df6d9d673daedb517969241f41278b52Brett Russ * Populate the SG list and mark the last entry. 102805b308e1df6d9d673daedb517969241f41278b52Brett Russ * 102905b308e1df6d9d673daedb517969241f41278b52Brett Russ * LOCKING: 103005b308e1df6d9d673daedb517969241f41278b52Brett Russ * Inherited from caller. 103105b308e1df6d9d673daedb517969241f41278b52Brett Russ */ 1032d88184fb2348a50f7c34f5d49a901c875b2e0114Jeff Garzikstatic unsigned int mv_fill_sg(struct ata_queued_cmd *qc) 103331961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ{ 103431961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ struct mv_port_priv *pp = qc->ap->private_data; 1035d88184fb2348a50f7c34f5d49a901c875b2e0114Jeff Garzik unsigned int n_sg = 0; 1036972c26bdd6b58e7534473c4f7928584578cf43f4Jeff Garzik struct scatterlist *sg; 1037d88184fb2348a50f7c34f5d49a901c875b2e0114Jeff Garzik struct mv_sg *mv_sg; 103831961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ 1039d88184fb2348a50f7c34f5d49a901c875b2e0114Jeff Garzik mv_sg = pp->sg_tbl; 1040972c26bdd6b58e7534473c4f7928584578cf43f4Jeff Garzik ata_for_each_sg(sg, qc) { 1041d88184fb2348a50f7c34f5d49a901c875b2e0114Jeff Garzik dma_addr_t addr = sg_dma_address(sg); 1042d88184fb2348a50f7c34f5d49a901c875b2e0114Jeff Garzik u32 sg_len = sg_dma_len(sg); 104322374677d18c5eeefd3a283431d312b8c44fef02Jeff Garzik 1044d88184fb2348a50f7c34f5d49a901c875b2e0114Jeff Garzik mv_sg->addr = cpu_to_le32(addr & 0xffffffff); 1045d88184fb2348a50f7c34f5d49a901c875b2e0114Jeff Garzik mv_sg->addr_hi = cpu_to_le32((addr >> 16) >> 16); 1046d88184fb2348a50f7c34f5d49a901c875b2e0114Jeff Garzik mv_sg->flags_size = cpu_to_le32(sg_len & 0xffff); 104722374677d18c5eeefd3a283431d312b8c44fef02Jeff Garzik 1048d88184fb2348a50f7c34f5d49a901c875b2e0114Jeff Garzik if (ata_sg_is_last(sg, qc)) 1049d88184fb2348a50f7c34f5d49a901c875b2e0114Jeff Garzik mv_sg->flags_size |= cpu_to_le32(EPRD_FLAG_END_OF_TBL); 105022374677d18c5eeefd3a283431d312b8c44fef02Jeff Garzik 1051d88184fb2348a50f7c34f5d49a901c875b2e0114Jeff Garzik mv_sg++; 1052d88184fb2348a50f7c34f5d49a901c875b2e0114Jeff Garzik n_sg++; 105331961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ } 1054d88184fb2348a50f7c34f5d49a901c875b2e0114Jeff Garzik 1055d88184fb2348a50f7c34f5d49a901c875b2e0114Jeff Garzik return n_sg; 105631961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ} 105731961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ 1058a6432436c5e14b416f27c8f87c5bf0bc36771f49Mark Lordstatic inline unsigned mv_inc_q_index(unsigned index) 105931961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ{ 1060a6432436c5e14b416f27c8f87c5bf0bc36771f49Mark Lord return (index + 1) & MV_MAX_Q_DEPTH_MASK; 106131961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ} 106231961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ 1063e14698745dd0de1ddbf5cd0cca4313a90f8c1cc1Mark Lordstatic inline void mv_crqb_pack_cmd(__le16 *cmdw, u8 data, u8 addr, unsigned last) 106431961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ{ 1065559eedad7f7764dacca33980127b4615011230e4Mark Lord u16 tmp = data | (addr << CRQB_CMD_ADDR_SHIFT) | CRQB_CMD_CS | 106631961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ (last ? CRQB_CMD_LAST : 0); 1067559eedad7f7764dacca33980127b4615011230e4Mark Lord *cmdw = cpu_to_le16(tmp); 106831961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ} 106931961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ 107005b308e1df6d9d673daedb517969241f41278b52Brett Russ/** 107105b308e1df6d9d673daedb517969241f41278b52Brett Russ * mv_qc_prep - Host specific command preparation. 107205b308e1df6d9d673daedb517969241f41278b52Brett Russ * @qc: queued command to prepare 107305b308e1df6d9d673daedb517969241f41278b52Brett Russ * 107405b308e1df6d9d673daedb517969241f41278b52Brett Russ * This routine simply redirects to the general purpose routine 107505b308e1df6d9d673daedb517969241f41278b52Brett Russ * if command is not DMA. Else, it handles prep of the CRQB 107605b308e1df6d9d673daedb517969241f41278b52Brett Russ * (command request block), does some sanity checking, and calls 107705b308e1df6d9d673daedb517969241f41278b52Brett Russ * the SG load routine. 107805b308e1df6d9d673daedb517969241f41278b52Brett Russ * 107905b308e1df6d9d673daedb517969241f41278b52Brett Russ * LOCKING: 108005b308e1df6d9d673daedb517969241f41278b52Brett Russ * Inherited from caller. 108105b308e1df6d9d673daedb517969241f41278b52Brett Russ */ 108231961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russstatic void mv_qc_prep(struct ata_queued_cmd *qc) 108331961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ{ 108431961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ struct ata_port *ap = qc->ap; 108531961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ struct mv_port_priv *pp = ap->private_data; 1086e14698745dd0de1ddbf5cd0cca4313a90f8c1cc1Mark Lord __le16 *cw; 108731961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ struct ata_taskfile *tf; 108831961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ u16 flags = 0; 1089a6432436c5e14b416f27c8f87c5bf0bc36771f49Mark Lord unsigned in_index; 109031961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ 1091e4e7b89280d1d666e2c09e5ad36cf071796c4c7eJeff Garzik if (ATA_PROT_DMA != qc->tf.protocol) 109231961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ return; 109320f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ 109431961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ /* Fill in command request block 109531961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ */ 1096e4e7b89280d1d666e2c09e5ad36cf071796c4c7eJeff Garzik if (!(qc->tf.flags & ATA_TFLAG_WRITE)) 109731961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ flags |= CRQB_FLAG_READ; 1098beec7dbc6ff003bbc94de62b3323519c878fb2acTejun Heo WARN_ON(MV_MAX_Q_DEPTH <= qc->tag); 109931961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ flags |= qc->tag << CRQB_TAG_SHIFT; 110031961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ 1101a6432436c5e14b416f27c8f87c5bf0bc36771f49Mark Lord /* get current queue index from hardware */ 1102a6432436c5e14b416f27c8f87c5bf0bc36771f49Mark Lord in_index = (readl(mv_ap_base(ap) + EDMA_REQ_Q_IN_PTR_OFS) 1103a6432436c5e14b416f27c8f87c5bf0bc36771f49Mark Lord >> EDMA_REQ_Q_PTR_SHIFT) & MV_MAX_Q_DEPTH_MASK; 1104a6432436c5e14b416f27c8f87c5bf0bc36771f49Mark Lord 1105a6432436c5e14b416f27c8f87c5bf0bc36771f49Mark Lord pp->crqb[in_index].sg_addr = 110631961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ cpu_to_le32(pp->sg_tbl_dma & 0xffffffff); 1107a6432436c5e14b416f27c8f87c5bf0bc36771f49Mark Lord pp->crqb[in_index].sg_addr_hi = 110831961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ cpu_to_le32((pp->sg_tbl_dma >> 16) >> 16); 1109a6432436c5e14b416f27c8f87c5bf0bc36771f49Mark Lord pp->crqb[in_index].ctrl_flags = cpu_to_le16(flags); 111031961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ 1111a6432436c5e14b416f27c8f87c5bf0bc36771f49Mark Lord cw = &pp->crqb[in_index].ata_cmd[0]; 111231961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ tf = &qc->tf; 111331961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ 111431961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ /* Sadly, the CRQB cannot accomodate all registers--there are 111531961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ * only 11 bytes...so we must pick and choose required 111631961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ * registers based on the command. So, we drop feature and 111731961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ * hob_feature for [RW] DMA commands, but they are needed for 111831961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ * NCQ. NCQ will drop hob_nsect. 111920f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ */ 112031961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ switch (tf->command) { 112131961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ case ATA_CMD_READ: 112231961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ case ATA_CMD_READ_EXT: 112331961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ case ATA_CMD_WRITE: 112431961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ case ATA_CMD_WRITE_EXT: 1125c15d85c8f3f73b5f20aae7928e25b6996f16b328Jens Axboe case ATA_CMD_WRITE_FUA_EXT: 112631961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ mv_crqb_pack_cmd(cw++, tf->hob_nsect, ATA_REG_NSECT, 0); 112731961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ break; 112831961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ#ifdef LIBATA_NCQ /* FIXME: remove this line when NCQ added */ 112931961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ case ATA_CMD_FPDMA_READ: 113031961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ case ATA_CMD_FPDMA_WRITE: 11318b260248d9e0e8b64bb72fd4dee03ad86984c344Jeff Garzik mv_crqb_pack_cmd(cw++, tf->hob_feature, ATA_REG_FEATURE, 0); 113231961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ mv_crqb_pack_cmd(cw++, tf->feature, ATA_REG_FEATURE, 0); 113331961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ break; 113431961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ#endif /* FIXME: remove this line when NCQ added */ 113531961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ default: 113631961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ /* The only other commands EDMA supports in non-queued and 113731961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ * non-NCQ mode are: [RW] STREAM DMA and W DMA FUA EXT, none 113831961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ * of which are defined/used by Linux. If we get here, this 113931961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ * driver needs work. 114031961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ * 114131961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ * FIXME: modify libata to give qc_prep a return value and 114231961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ * return error here. 114331961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ */ 114431961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ BUG_ON(tf->command); 114531961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ break; 114631961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ } 114731961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ mv_crqb_pack_cmd(cw++, tf->nsect, ATA_REG_NSECT, 0); 114831961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ mv_crqb_pack_cmd(cw++, tf->hob_lbal, ATA_REG_LBAL, 0); 114931961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ mv_crqb_pack_cmd(cw++, tf->lbal, ATA_REG_LBAL, 0); 115031961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ mv_crqb_pack_cmd(cw++, tf->hob_lbam, ATA_REG_LBAM, 0); 115131961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ mv_crqb_pack_cmd(cw++, tf->lbam, ATA_REG_LBAM, 0); 115231961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ mv_crqb_pack_cmd(cw++, tf->hob_lbah, ATA_REG_LBAH, 0); 115331961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ mv_crqb_pack_cmd(cw++, tf->lbah, ATA_REG_LBAH, 0); 115431961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ mv_crqb_pack_cmd(cw++, tf->device, ATA_REG_DEVICE, 0); 115531961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ mv_crqb_pack_cmd(cw++, tf->command, ATA_REG_CMD, 1); /* last */ 115631961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ 1157e4e7b89280d1d666e2c09e5ad36cf071796c4c7eJeff Garzik if (!(qc->flags & ATA_QCFLAG_DMAMAP)) 1158e4e7b89280d1d666e2c09e5ad36cf071796c4c7eJeff Garzik return; 1159e4e7b89280d1d666e2c09e5ad36cf071796c4c7eJeff Garzik mv_fill_sg(qc); 1160e4e7b89280d1d666e2c09e5ad36cf071796c4c7eJeff Garzik} 1161e4e7b89280d1d666e2c09e5ad36cf071796c4c7eJeff Garzik 1162e4e7b89280d1d666e2c09e5ad36cf071796c4c7eJeff Garzik/** 1163e4e7b89280d1d666e2c09e5ad36cf071796c4c7eJeff Garzik * mv_qc_prep_iie - Host specific command preparation. 1164e4e7b89280d1d666e2c09e5ad36cf071796c4c7eJeff Garzik * @qc: queued command to prepare 1165e4e7b89280d1d666e2c09e5ad36cf071796c4c7eJeff Garzik * 1166e4e7b89280d1d666e2c09e5ad36cf071796c4c7eJeff Garzik * This routine simply redirects to the general purpose routine 1167e4e7b89280d1d666e2c09e5ad36cf071796c4c7eJeff Garzik * if command is not DMA. Else, it handles prep of the CRQB 1168e4e7b89280d1d666e2c09e5ad36cf071796c4c7eJeff Garzik * (command request block), does some sanity checking, and calls 1169e4e7b89280d1d666e2c09e5ad36cf071796c4c7eJeff Garzik * the SG load routine. 1170e4e7b89280d1d666e2c09e5ad36cf071796c4c7eJeff Garzik * 1171e4e7b89280d1d666e2c09e5ad36cf071796c4c7eJeff Garzik * LOCKING: 1172e4e7b89280d1d666e2c09e5ad36cf071796c4c7eJeff Garzik * Inherited from caller. 1173e4e7b89280d1d666e2c09e5ad36cf071796c4c7eJeff Garzik */ 1174e4e7b89280d1d666e2c09e5ad36cf071796c4c7eJeff Garzikstatic void mv_qc_prep_iie(struct ata_queued_cmd *qc) 1175e4e7b89280d1d666e2c09e5ad36cf071796c4c7eJeff Garzik{ 1176e4e7b89280d1d666e2c09e5ad36cf071796c4c7eJeff Garzik struct ata_port *ap = qc->ap; 1177e4e7b89280d1d666e2c09e5ad36cf071796c4c7eJeff Garzik struct mv_port_priv *pp = ap->private_data; 1178e4e7b89280d1d666e2c09e5ad36cf071796c4c7eJeff Garzik struct mv_crqb_iie *crqb; 1179e4e7b89280d1d666e2c09e5ad36cf071796c4c7eJeff Garzik struct ata_taskfile *tf; 1180a6432436c5e14b416f27c8f87c5bf0bc36771f49Mark Lord unsigned in_index; 1181e4e7b89280d1d666e2c09e5ad36cf071796c4c7eJeff Garzik u32 flags = 0; 1182e4e7b89280d1d666e2c09e5ad36cf071796c4c7eJeff Garzik 1183e4e7b89280d1d666e2c09e5ad36cf071796c4c7eJeff Garzik if (ATA_PROT_DMA != qc->tf.protocol) 1184e4e7b89280d1d666e2c09e5ad36cf071796c4c7eJeff Garzik return; 1185e4e7b89280d1d666e2c09e5ad36cf071796c4c7eJeff Garzik 1186e4e7b89280d1d666e2c09e5ad36cf071796c4c7eJeff Garzik /* Fill in Gen IIE command request block 1187e4e7b89280d1d666e2c09e5ad36cf071796c4c7eJeff Garzik */ 1188e4e7b89280d1d666e2c09e5ad36cf071796c4c7eJeff Garzik if (!(qc->tf.flags & ATA_TFLAG_WRITE)) 1189e4e7b89280d1d666e2c09e5ad36cf071796c4c7eJeff Garzik flags |= CRQB_FLAG_READ; 1190e4e7b89280d1d666e2c09e5ad36cf071796c4c7eJeff Garzik 1191beec7dbc6ff003bbc94de62b3323519c878fb2acTejun Heo WARN_ON(MV_MAX_Q_DEPTH <= qc->tag); 1192e4e7b89280d1d666e2c09e5ad36cf071796c4c7eJeff Garzik flags |= qc->tag << CRQB_TAG_SHIFT; 1193e4e7b89280d1d666e2c09e5ad36cf071796c4c7eJeff Garzik 1194a6432436c5e14b416f27c8f87c5bf0bc36771f49Mark Lord /* get current queue index from hardware */ 1195a6432436c5e14b416f27c8f87c5bf0bc36771f49Mark Lord in_index = (readl(mv_ap_base(ap) + EDMA_REQ_Q_IN_PTR_OFS) 1196a6432436c5e14b416f27c8f87c5bf0bc36771f49Mark Lord >> EDMA_REQ_Q_PTR_SHIFT) & MV_MAX_Q_DEPTH_MASK; 1197a6432436c5e14b416f27c8f87c5bf0bc36771f49Mark Lord 1198a6432436c5e14b416f27c8f87c5bf0bc36771f49Mark Lord crqb = (struct mv_crqb_iie *) &pp->crqb[in_index]; 1199e4e7b89280d1d666e2c09e5ad36cf071796c4c7eJeff Garzik crqb->addr = cpu_to_le32(pp->sg_tbl_dma & 0xffffffff); 1200e4e7b89280d1d666e2c09e5ad36cf071796c4c7eJeff Garzik crqb->addr_hi = cpu_to_le32((pp->sg_tbl_dma >> 16) >> 16); 1201e4e7b89280d1d666e2c09e5ad36cf071796c4c7eJeff Garzik crqb->flags = cpu_to_le32(flags); 1202e4e7b89280d1d666e2c09e5ad36cf071796c4c7eJeff Garzik 1203e4e7b89280d1d666e2c09e5ad36cf071796c4c7eJeff Garzik tf = &qc->tf; 1204e4e7b89280d1d666e2c09e5ad36cf071796c4c7eJeff Garzik crqb->ata_cmd[0] = cpu_to_le32( 1205e4e7b89280d1d666e2c09e5ad36cf071796c4c7eJeff Garzik (tf->command << 16) | 1206e4e7b89280d1d666e2c09e5ad36cf071796c4c7eJeff Garzik (tf->feature << 24) 1207e4e7b89280d1d666e2c09e5ad36cf071796c4c7eJeff Garzik ); 1208e4e7b89280d1d666e2c09e5ad36cf071796c4c7eJeff Garzik crqb->ata_cmd[1] = cpu_to_le32( 1209e4e7b89280d1d666e2c09e5ad36cf071796c4c7eJeff Garzik (tf->lbal << 0) | 1210e4e7b89280d1d666e2c09e5ad36cf071796c4c7eJeff Garzik (tf->lbam << 8) | 1211e4e7b89280d1d666e2c09e5ad36cf071796c4c7eJeff Garzik (tf->lbah << 16) | 1212e4e7b89280d1d666e2c09e5ad36cf071796c4c7eJeff Garzik (tf->device << 24) 1213e4e7b89280d1d666e2c09e5ad36cf071796c4c7eJeff Garzik ); 1214e4e7b89280d1d666e2c09e5ad36cf071796c4c7eJeff Garzik crqb->ata_cmd[2] = cpu_to_le32( 1215e4e7b89280d1d666e2c09e5ad36cf071796c4c7eJeff Garzik (tf->hob_lbal << 0) | 1216e4e7b89280d1d666e2c09e5ad36cf071796c4c7eJeff Garzik (tf->hob_lbam << 8) | 1217e4e7b89280d1d666e2c09e5ad36cf071796c4c7eJeff Garzik (tf->hob_lbah << 16) | 1218e4e7b89280d1d666e2c09e5ad36cf071796c4c7eJeff Garzik (tf->hob_feature << 24) 1219e4e7b89280d1d666e2c09e5ad36cf071796c4c7eJeff Garzik ); 1220e4e7b89280d1d666e2c09e5ad36cf071796c4c7eJeff Garzik crqb->ata_cmd[3] = cpu_to_le32( 1221e4e7b89280d1d666e2c09e5ad36cf071796c4c7eJeff Garzik (tf->nsect << 0) | 1222e4e7b89280d1d666e2c09e5ad36cf071796c4c7eJeff Garzik (tf->hob_nsect << 8) 1223e4e7b89280d1d666e2c09e5ad36cf071796c4c7eJeff Garzik ); 1224e4e7b89280d1d666e2c09e5ad36cf071796c4c7eJeff Garzik 1225e4e7b89280d1d666e2c09e5ad36cf071796c4c7eJeff Garzik if (!(qc->flags & ATA_QCFLAG_DMAMAP)) 122631961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ return; 122731961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ mv_fill_sg(qc); 122831961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ} 122931961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ 123005b308e1df6d9d673daedb517969241f41278b52Brett Russ/** 123105b308e1df6d9d673daedb517969241f41278b52Brett Russ * mv_qc_issue - Initiate a command to the host 123205b308e1df6d9d673daedb517969241f41278b52Brett Russ * @qc: queued command to start 123305b308e1df6d9d673daedb517969241f41278b52Brett Russ * 123405b308e1df6d9d673daedb517969241f41278b52Brett Russ * This routine simply redirects to the general purpose routine 123505b308e1df6d9d673daedb517969241f41278b52Brett Russ * if command is not DMA. Else, it sanity checks our local 123605b308e1df6d9d673daedb517969241f41278b52Brett Russ * caches of the request producer/consumer indices then enables 123705b308e1df6d9d673daedb517969241f41278b52Brett Russ * DMA and bumps the request producer index. 123805b308e1df6d9d673daedb517969241f41278b52Brett Russ * 123905b308e1df6d9d673daedb517969241f41278b52Brett Russ * LOCKING: 124005b308e1df6d9d673daedb517969241f41278b52Brett Russ * Inherited from caller. 124105b308e1df6d9d673daedb517969241f41278b52Brett Russ */ 12429a3d9eb0177eb10500d49cd283b35576082a522dTejun Heostatic unsigned int mv_qc_issue(struct ata_queued_cmd *qc) 124331961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ{ 124431961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ void __iomem *port_mmio = mv_ap_base(qc->ap); 124531961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ struct mv_port_priv *pp = qc->ap->private_data; 1246a6432436c5e14b416f27c8f87c5bf0bc36771f49Mark Lord unsigned in_index; 124731961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ u32 in_ptr; 124831961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ 124931961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ if (ATA_PROT_DMA != qc->tf.protocol) { 125031961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ /* We're about to send a non-EDMA capable command to the 125131961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ * port. Turn off EDMA so there won't be problems accessing 125231961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ * shadow block, etc registers. 125331961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ */ 125431961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ mv_stop_dma(qc->ap); 125531961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ return ata_qc_issue_prot(qc); 125631961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ } 125731961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ 1258a6432436c5e14b416f27c8f87c5bf0bc36771f49Mark Lord in_ptr = readl(port_mmio + EDMA_REQ_Q_IN_PTR_OFS); 1259a6432436c5e14b416f27c8f87c5bf0bc36771f49Mark Lord in_index = (in_ptr >> EDMA_REQ_Q_PTR_SHIFT) & MV_MAX_Q_DEPTH_MASK; 126031961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ 126131961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ /* until we do queuing, the queue should be empty at this point */ 1262a6432436c5e14b416f27c8f87c5bf0bc36771f49Mark Lord WARN_ON(in_index != ((readl(port_mmio + EDMA_REQ_Q_OUT_PTR_OFS) 1263a6432436c5e14b416f27c8f87c5bf0bc36771f49Mark Lord >> EDMA_REQ_Q_PTR_SHIFT) & MV_MAX_Q_DEPTH_MASK)); 126431961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ 1265a6432436c5e14b416f27c8f87c5bf0bc36771f49Mark Lord in_index = mv_inc_q_index(in_index); /* now incr producer index */ 126631961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ 1267afb0edd922c7ed6e73678730921dfcccebec17e8Brett Russ mv_start_dma(port_mmio, pp); 126831961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ 126931961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ /* and write the request in pointer to kick the EDMA to life */ 127031961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ in_ptr &= EDMA_REQ_Q_BASE_LO_MASK; 1271a6432436c5e14b416f27c8f87c5bf0bc36771f49Mark Lord in_ptr |= in_index << EDMA_REQ_Q_PTR_SHIFT; 127231961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ writelfl(in_ptr, port_mmio + EDMA_REQ_Q_IN_PTR_OFS); 127331961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ 127431961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ return 0; 127531961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ} 127631961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ 127705b308e1df6d9d673daedb517969241f41278b52Brett Russ/** 127805b308e1df6d9d673daedb517969241f41278b52Brett Russ * mv_get_crpb_status - get status from most recently completed cmd 127905b308e1df6d9d673daedb517969241f41278b52Brett Russ * @ap: ATA channel to manipulate 128005b308e1df6d9d673daedb517969241f41278b52Brett Russ * 128105b308e1df6d9d673daedb517969241f41278b52Brett Russ * This routine is for use when the port is in DMA mode, when it 128205b308e1df6d9d673daedb517969241f41278b52Brett Russ * will be using the CRPB (command response block) method of 1283beec7dbc6ff003bbc94de62b3323519c878fb2acTejun Heo * returning command completion information. We check indices 128405b308e1df6d9d673daedb517969241f41278b52Brett Russ * are good, grab status, and bump the response consumer index to 128505b308e1df6d9d673daedb517969241f41278b52Brett Russ * prove that we're up to date. 128605b308e1df6d9d673daedb517969241f41278b52Brett Russ * 128705b308e1df6d9d673daedb517969241f41278b52Brett Russ * LOCKING: 128805b308e1df6d9d673daedb517969241f41278b52Brett Russ * Inherited from caller. 128905b308e1df6d9d673daedb517969241f41278b52Brett Russ */ 129031961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russstatic u8 mv_get_crpb_status(struct ata_port *ap) 129131961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ{ 129231961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ void __iomem *port_mmio = mv_ap_base(ap); 129331961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ struct mv_port_priv *pp = ap->private_data; 1294a6432436c5e14b416f27c8f87c5bf0bc36771f49Mark Lord unsigned out_index; 129531961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ u32 out_ptr; 1296806a6e7a9904d4a1dfd3fd79d373bf31d71d34cbMark Lord u8 ata_status; 129731961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ 1298a6432436c5e14b416f27c8f87c5bf0bc36771f49Mark Lord out_ptr = readl(port_mmio + EDMA_RSP_Q_OUT_PTR_OFS); 1299a6432436c5e14b416f27c8f87c5bf0bc36771f49Mark Lord out_index = (out_ptr >> EDMA_RSP_Q_PTR_SHIFT) & MV_MAX_Q_DEPTH_MASK; 130031961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ 1301a6432436c5e14b416f27c8f87c5bf0bc36771f49Mark Lord ata_status = le16_to_cpu(pp->crpb[out_index].flags) 1302a6432436c5e14b416f27c8f87c5bf0bc36771f49Mark Lord >> CRPB_FLAG_STATUS_SHIFT; 1303806a6e7a9904d4a1dfd3fd79d373bf31d71d34cbMark Lord 130431961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ /* increment our consumer index... */ 1305a6432436c5e14b416f27c8f87c5bf0bc36771f49Mark Lord out_index = mv_inc_q_index(out_index); 13068b260248d9e0e8b64bb72fd4dee03ad86984c344Jeff Garzik 130731961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ /* and, until we do NCQ, there should only be 1 CRPB waiting */ 1308a6432436c5e14b416f27c8f87c5bf0bc36771f49Mark Lord WARN_ON(out_index != ((readl(port_mmio + EDMA_RSP_Q_IN_PTR_OFS) 1309a6432436c5e14b416f27c8f87c5bf0bc36771f49Mark Lord >> EDMA_RSP_Q_PTR_SHIFT) & MV_MAX_Q_DEPTH_MASK)); 131031961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ 131131961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ /* write out our inc'd consumer index so EDMA knows we're caught up */ 131231961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ out_ptr &= EDMA_RSP_Q_BASE_LO_MASK; 1313a6432436c5e14b416f27c8f87c5bf0bc36771f49Mark Lord out_ptr |= out_index << EDMA_RSP_Q_PTR_SHIFT; 131431961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ writelfl(out_ptr, port_mmio + EDMA_RSP_Q_OUT_PTR_OFS); 131531961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ 131631961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ /* Return ATA status register for completed CRPB */ 1317806a6e7a9904d4a1dfd3fd79d373bf31d71d34cbMark Lord return ata_status; 131831961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ} 131931961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ 132005b308e1df6d9d673daedb517969241f41278b52Brett Russ/** 132105b308e1df6d9d673daedb517969241f41278b52Brett Russ * mv_err_intr - Handle error interrupts on the port 132205b308e1df6d9d673daedb517969241f41278b52Brett Russ * @ap: ATA channel to manipulate 13239b358e305c1d783c8a4ebf00344e95deb9e38f3dMark Lord * @reset_allowed: bool: 0 == don't trigger from reset here 132405b308e1df6d9d673daedb517969241f41278b52Brett Russ * 132505b308e1df6d9d673daedb517969241f41278b52Brett Russ * In most cases, just clear the interrupt and move on. However, 132605b308e1df6d9d673daedb517969241f41278b52Brett Russ * some cases require an eDMA reset, which is done right before 132705b308e1df6d9d673daedb517969241f41278b52Brett Russ * the COMRESET in mv_phy_reset(). The SERR case requires a 132805b308e1df6d9d673daedb517969241f41278b52Brett Russ * clear of pending errors in the SATA SERROR register. Finally, 132905b308e1df6d9d673daedb517969241f41278b52Brett Russ * if the port disabled DMA, update our cached copy to match. 133005b308e1df6d9d673daedb517969241f41278b52Brett Russ * 133105b308e1df6d9d673daedb517969241f41278b52Brett Russ * LOCKING: 133205b308e1df6d9d673daedb517969241f41278b52Brett Russ * Inherited from caller. 133305b308e1df6d9d673daedb517969241f41278b52Brett Russ */ 13349b358e305c1d783c8a4ebf00344e95deb9e38f3dMark Lordstatic void mv_err_intr(struct ata_port *ap, int reset_allowed) 133531961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ{ 133631961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ void __iomem *port_mmio = mv_ap_base(ap); 133731961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ u32 edma_err_cause, serr = 0; 133820f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ 133920f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ edma_err_cause = readl(port_mmio + EDMA_ERR_IRQ_CAUSE_OFS); 134020f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ 134120f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ if (EDMA_ERR_SERR & edma_err_cause) { 134281952c5497b40ae56835bd0d6537f8c6bdea07e7Tejun Heo sata_scr_read(ap, SCR_ERROR, &serr); 134381952c5497b40ae56835bd0d6537f8c6bdea07e7Tejun Heo sata_scr_write_flush(ap, SCR_ERROR, serr); 134420f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ } 1345afb0edd922c7ed6e73678730921dfcccebec17e8Brett Russ if (EDMA_ERR_SELF_DIS & edma_err_cause) { 1346afb0edd922c7ed6e73678730921dfcccebec17e8Brett Russ struct mv_port_priv *pp = ap->private_data; 1347afb0edd922c7ed6e73678730921dfcccebec17e8Brett Russ pp->pp_flags &= ~MV_PP_FLAG_EDMA_EN; 1348afb0edd922c7ed6e73678730921dfcccebec17e8Brett Russ } 1349afb0edd922c7ed6e73678730921dfcccebec17e8Brett Russ DPRINTK(KERN_ERR "ata%u: port error; EDMA err cause: 0x%08x " 135044877b4e22f391d39c6589412106a3668e81a05bTejun Heo "SERR: 0x%08x\n", ap->print_id, edma_err_cause, serr); 135120f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ 135220f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ /* Clear EDMA now that SERR cleanup done */ 135320f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ writelfl(0, port_mmio + EDMA_ERR_IRQ_CAUSE_OFS); 135420f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ 135520f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ /* check for fatal here and recover if needed */ 13569b358e305c1d783c8a4ebf00344e95deb9e38f3dMark Lord if (reset_allowed && (EDMA_ERR_FATAL & edma_err_cause)) 1357c9d39130123238ac18478a42e25cb7996eacfcc0Jeff Garzik mv_stop_and_reset(ap); 135820f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ} 135920f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ 136005b308e1df6d9d673daedb517969241f41278b52Brett Russ/** 136105b308e1df6d9d673daedb517969241f41278b52Brett Russ * mv_host_intr - Handle all interrupts on the given host controller 1362cca3974e48607c3775dc73b544a5700b2e37c21aJeff Garzik * @host: host specific structure 136305b308e1df6d9d673daedb517969241f41278b52Brett Russ * @relevant: port error bits relevant to this host controller 136405b308e1df6d9d673daedb517969241f41278b52Brett Russ * @hc: which host controller we're to look at 136505b308e1df6d9d673daedb517969241f41278b52Brett Russ * 136605b308e1df6d9d673daedb517969241f41278b52Brett Russ * Read then write clear the HC interrupt status then walk each 136705b308e1df6d9d673daedb517969241f41278b52Brett Russ * port connected to the HC and see if it needs servicing. Port 136805b308e1df6d9d673daedb517969241f41278b52Brett Russ * success ints are reported in the HC interrupt status reg, the 136905b308e1df6d9d673daedb517969241f41278b52Brett Russ * port error ints are reported in the higher level main 137005b308e1df6d9d673daedb517969241f41278b52Brett Russ * interrupt status register and thus are passed in via the 137105b308e1df6d9d673daedb517969241f41278b52Brett Russ * 'relevant' argument. 137205b308e1df6d9d673daedb517969241f41278b52Brett Russ * 137305b308e1df6d9d673daedb517969241f41278b52Brett Russ * LOCKING: 137405b308e1df6d9d673daedb517969241f41278b52Brett Russ * Inherited from caller. 137505b308e1df6d9d673daedb517969241f41278b52Brett Russ */ 1376cca3974e48607c3775dc73b544a5700b2e37c21aJeff Garzikstatic void mv_host_intr(struct ata_host *host, u32 relevant, unsigned int hc) 137720f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ{ 13780d5ff566779f894ca9937231a181eb31e4adff0eTejun Heo void __iomem *mmio = host->iomap[MV_PRIMARY_BAR]; 137920f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ void __iomem *hc_mmio = mv_hc_base(mmio, hc); 138020f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ struct ata_queued_cmd *qc; 138120f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ u32 hc_irq_cause; 138231961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ int shift, port, port0, hard_port, handled; 1383a7dac447bb9cef27d4d29cdf63e2d7809c50b1f4Jeff Garzik unsigned int err_mask; 138420f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ 1385351772658a4d1acc0221a6e30676bb0594e74812Jeff Garzik if (hc == 0) 138620f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ port0 = 0; 1387351772658a4d1acc0221a6e30676bb0594e74812Jeff Garzik else 138820f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ port0 = MV_PORTS_PER_HC; 138920f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ 139020f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ /* we'll need the HC success int register in most cases */ 139120f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ hc_irq_cause = readl(hc_mmio + HC_IRQ_CAUSE_OFS); 1392351772658a4d1acc0221a6e30676bb0594e74812Jeff Garzik if (hc_irq_cause) 139331961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ writelfl(~hc_irq_cause, hc_mmio + HC_IRQ_CAUSE_OFS); 139420f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ 139520f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ VPRINTK("ENTER, hc%u relevant=0x%08x HC IRQ cause=0x%08x\n", 139620f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ hc,relevant,hc_irq_cause); 139720f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ 139820f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ for (port = port0; port < port0 + MV_PORTS_PER_HC; port++) { 1399cd85f6e2f58282186ad720fc18482be228f0b972Jeff Garzik u8 ata_status = 0; 1400cca3974e48607c3775dc73b544a5700b2e37c21aJeff Garzik struct ata_port *ap = host->ports[port]; 140163af2a5c5990d95f1e7d8795f1425fb976ea2b4bMark Lord struct mv_port_priv *pp = ap->private_data; 140255d8ca4f8094246da6e71889a4e04bfafaa78b10Jeff Garzik 1403e857f141945f29c16f72ffcfdbce097f8be6c4e9Mark Lord hard_port = mv_hardport_from_port(port); /* range 0..3 */ 140431961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ handled = 0; /* ensure ata_status is set if handled++ */ 140520f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ 140663af2a5c5990d95f1e7d8795f1425fb976ea2b4bMark Lord /* Note that DEV_IRQ might happen spuriously during EDMA, 1407e857f141945f29c16f72ffcfdbce097f8be6c4e9Mark Lord * and should be ignored in such cases. 1408e857f141945f29c16f72ffcfdbce097f8be6c4e9Mark Lord * The cause of this is still under investigation. 14098190bdb9291758f3b8c436ec1154c9923ddb57eaJeff Garzik */ 141063af2a5c5990d95f1e7d8795f1425fb976ea2b4bMark Lord if (pp->pp_flags & MV_PP_FLAG_EDMA_EN) { 141163af2a5c5990d95f1e7d8795f1425fb976ea2b4bMark Lord /* EDMA: check for response queue interrupt */ 141263af2a5c5990d95f1e7d8795f1425fb976ea2b4bMark Lord if ((CRPB_DMA_DONE << hard_port) & hc_irq_cause) { 141363af2a5c5990d95f1e7d8795f1425fb976ea2b4bMark Lord ata_status = mv_get_crpb_status(ap); 141463af2a5c5990d95f1e7d8795f1425fb976ea2b4bMark Lord handled = 1; 141563af2a5c5990d95f1e7d8795f1425fb976ea2b4bMark Lord } 141663af2a5c5990d95f1e7d8795f1425fb976ea2b4bMark Lord } else { 141763af2a5c5990d95f1e7d8795f1425fb976ea2b4bMark Lord /* PIO: check for device (drive) interrupt */ 141863af2a5c5990d95f1e7d8795f1425fb976ea2b4bMark Lord if ((DEV_IRQ << hard_port) & hc_irq_cause) { 14190d5ff566779f894ca9937231a181eb31e4adff0eTejun Heo ata_status = readb(ap->ioaddr.status_addr); 142063af2a5c5990d95f1e7d8795f1425fb976ea2b4bMark Lord handled = 1; 1421e857f141945f29c16f72ffcfdbce097f8be6c4e9Mark Lord /* ignore spurious intr if drive still BUSY */ 1422e857f141945f29c16f72ffcfdbce097f8be6c4e9Mark Lord if (ata_status & ATA_BUSY) { 1423e857f141945f29c16f72ffcfdbce097f8be6c4e9Mark Lord ata_status = 0; 1424e857f141945f29c16f72ffcfdbce097f8be6c4e9Mark Lord handled = 0; 1425e857f141945f29c16f72ffcfdbce097f8be6c4e9Mark Lord } 142663af2a5c5990d95f1e7d8795f1425fb976ea2b4bMark Lord } 142720f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ } 142820f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ 1429029f5468b5b5f93a09bf90326fdcb9124079658dJeff Garzik if (ap && (ap->flags & ATA_FLAG_DISABLED)) 1430a2c91a8819e315e9fd1aef3ff57badb6c1be3f80Jeff Garzik continue; 1431a2c91a8819e315e9fd1aef3ff57badb6c1be3f80Jeff Garzik 1432a7dac447bb9cef27d4d29cdf63e2d7809c50b1f4Jeff Garzik err_mask = ac_err_mask(ata_status); 1433a7dac447bb9cef27d4d29cdf63e2d7809c50b1f4Jeff Garzik 143431961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ shift = port << 1; /* (port * 2) */ 143520f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ if (port >= MV_PORTS_PER_HC) { 143620f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ shift++; /* skip bit 8 in the HC Main IRQ reg */ 143720f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ } 143820f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ if ((PORT0_ERR << shift) & relevant) { 14399b358e305c1d783c8a4ebf00344e95deb9e38f3dMark Lord mv_err_intr(ap, 1); 1440a7dac447bb9cef27d4d29cdf63e2d7809c50b1f4Jeff Garzik err_mask |= AC_ERR_OTHER; 144163af2a5c5990d95f1e7d8795f1425fb976ea2b4bMark Lord handled = 1; 144220f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ } 14438b260248d9e0e8b64bb72fd4dee03ad86984c344Jeff Garzik 144463af2a5c5990d95f1e7d8795f1425fb976ea2b4bMark Lord if (handled) { 144520f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ qc = ata_qc_from_tag(ap, ap->active_tag); 144663af2a5c5990d95f1e7d8795f1425fb976ea2b4bMark Lord if (qc && (qc->flags & ATA_QCFLAG_ACTIVE)) { 144720f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ VPRINTK("port %u IRQ found for qc, " 144820f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ "ata_status 0x%x\n", port,ata_status); 144920f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ /* mark qc status appropriately */ 1450701db69d6647f61e4660c9102d7f2fd5dffc203dJeff Garzik if (!(qc->tf.flags & ATA_TFLAG_POLLING)) { 1451a22e2eb0710798009b8e696ae911aef745089dd6Albert Lee qc->err_mask |= err_mask; 1452a22e2eb0710798009b8e696ae911aef745089dd6Albert Lee ata_qc_complete(qc); 1453a22e2eb0710798009b8e696ae911aef745089dd6Albert Lee } 145420f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ } 145520f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ } 145620f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ } 145720f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ VPRINTK("EXIT\n"); 145820f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ} 145920f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ 146005b308e1df6d9d673daedb517969241f41278b52Brett Russ/** 14618b260248d9e0e8b64bb72fd4dee03ad86984c344Jeff Garzik * mv_interrupt - 146205b308e1df6d9d673daedb517969241f41278b52Brett Russ * @irq: unused 146305b308e1df6d9d673daedb517969241f41278b52Brett Russ * @dev_instance: private data; in this case the host structure 146405b308e1df6d9d673daedb517969241f41278b52Brett Russ * @regs: unused 146505b308e1df6d9d673daedb517969241f41278b52Brett Russ * 146605b308e1df6d9d673daedb517969241f41278b52Brett Russ * Read the read only register to determine if any host 146705b308e1df6d9d673daedb517969241f41278b52Brett Russ * controllers have pending interrupts. If so, call lower level 146805b308e1df6d9d673daedb517969241f41278b52Brett Russ * routine to handle. Also check for PCI errors which are only 146905b308e1df6d9d673daedb517969241f41278b52Brett Russ * reported here. 147005b308e1df6d9d673daedb517969241f41278b52Brett Russ * 14718b260248d9e0e8b64bb72fd4dee03ad86984c344Jeff Garzik * LOCKING: 1472cca3974e48607c3775dc73b544a5700b2e37c21aJeff Garzik * This routine holds the host lock while processing pending 147305b308e1df6d9d673daedb517969241f41278b52Brett Russ * interrupts. 147405b308e1df6d9d673daedb517969241f41278b52Brett Russ */ 14757d12e780e003f93433d49ce78cfedf4b4c52adc5David Howellsstatic irqreturn_t mv_interrupt(int irq, void *dev_instance) 147620f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ{ 1477cca3974e48607c3775dc73b544a5700b2e37c21aJeff Garzik struct ata_host *host = dev_instance; 147820f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ unsigned int hc, handled = 0, n_hcs; 14790d5ff566779f894ca9937231a181eb31e4adff0eTejun Heo void __iomem *mmio = host->iomap[MV_PRIMARY_BAR]; 1480615ab95342f6245026d8974b9724f7ea57d9a184Mark Lord struct mv_host_priv *hpriv; 148120f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ u32 irq_stat; 148220f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ 148320f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ irq_stat = readl(mmio + HC_MAIN_IRQ_CAUSE_OFS); 148420f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ 148520f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ /* check the cases where we either have nothing pending or have read 148620f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ * a bogus register value which can indicate HW removal or PCI fault 148720f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ */ 1488351772658a4d1acc0221a6e30676bb0594e74812Jeff Garzik if (!irq_stat || (0xffffffffU == irq_stat)) 148920f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ return IRQ_NONE; 149020f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ 1491cca3974e48607c3775dc73b544a5700b2e37c21aJeff Garzik n_hcs = mv_get_hc_count(host->ports[0]->flags); 1492cca3974e48607c3775dc73b544a5700b2e37c21aJeff Garzik spin_lock(&host->lock); 149320f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ 149420f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ for (hc = 0; hc < n_hcs; hc++) { 149520f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ u32 relevant = irq_stat & (HC0_IRQ_PEND << (hc * HC_SHIFT)); 149620f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ if (relevant) { 1497cca3974e48607c3775dc73b544a5700b2e37c21aJeff Garzik mv_host_intr(host, relevant, hc); 149831961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ handled++; 149920f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ } 150020f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ } 1501615ab95342f6245026d8974b9724f7ea57d9a184Mark Lord 1502cca3974e48607c3775dc73b544a5700b2e37c21aJeff Garzik hpriv = host->private_data; 1503615ab95342f6245026d8974b9724f7ea57d9a184Mark Lord if (IS_60XX(hpriv)) { 1504615ab95342f6245026d8974b9724f7ea57d9a184Mark Lord /* deal with the interrupt coalescing bits */ 1505615ab95342f6245026d8974b9724f7ea57d9a184Mark Lord if (irq_stat & (TRAN_LO_DONE | TRAN_HI_DONE | PORTS_0_7_COAL_DONE)) { 1506615ab95342f6245026d8974b9724f7ea57d9a184Mark Lord writelfl(0, mmio + MV_IRQ_COAL_CAUSE_LO); 1507615ab95342f6245026d8974b9724f7ea57d9a184Mark Lord writelfl(0, mmio + MV_IRQ_COAL_CAUSE_HI); 1508615ab95342f6245026d8974b9724f7ea57d9a184Mark Lord writelfl(0, mmio + MV_IRQ_COAL_CAUSE); 1509615ab95342f6245026d8974b9724f7ea57d9a184Mark Lord } 1510615ab95342f6245026d8974b9724f7ea57d9a184Mark Lord } 1511615ab95342f6245026d8974b9724f7ea57d9a184Mark Lord 151220f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ if (PCI_ERR & irq_stat) { 151331961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ printk(KERN_ERR DRV_NAME ": PCI ERROR; PCI IRQ cause=0x%08x\n", 151431961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ readl(mmio + PCI_IRQ_CAUSE_OFS)); 151531961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ 1516afb0edd922c7ed6e73678730921dfcccebec17e8Brett Russ DPRINTK("All regs @ PCI error\n"); 1517cca3974e48607c3775dc73b544a5700b2e37c21aJeff Garzik mv_dump_all_regs(mmio, -1, to_pci_dev(host->dev)); 151820f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ 151931961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ writelfl(0, mmio + PCI_IRQ_CAUSE_OFS); 152031961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ handled++; 152131961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ } 1522cca3974e48607c3775dc73b544a5700b2e37c21aJeff Garzik spin_unlock(&host->lock); 152320f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ 152420f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ return IRQ_RETVAL(handled); 152520f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ} 152620f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ 1527c9d39130123238ac18478a42e25cb7996eacfcc0Jeff Garzikstatic void __iomem *mv5_phy_base(void __iomem *mmio, unsigned int port) 1528c9d39130123238ac18478a42e25cb7996eacfcc0Jeff Garzik{ 1529c9d39130123238ac18478a42e25cb7996eacfcc0Jeff Garzik void __iomem *hc_mmio = mv_hc_base_from_port(mmio, port); 1530c9d39130123238ac18478a42e25cb7996eacfcc0Jeff Garzik unsigned long ofs = (mv_hardport_from_port(port) + 1) * 0x100UL; 1531c9d39130123238ac18478a42e25cb7996eacfcc0Jeff Garzik 1532c9d39130123238ac18478a42e25cb7996eacfcc0Jeff Garzik return hc_mmio + ofs; 1533c9d39130123238ac18478a42e25cb7996eacfcc0Jeff Garzik} 1534c9d39130123238ac18478a42e25cb7996eacfcc0Jeff Garzik 1535c9d39130123238ac18478a42e25cb7996eacfcc0Jeff Garzikstatic unsigned int mv5_scr_offset(unsigned int sc_reg_in) 1536c9d39130123238ac18478a42e25cb7996eacfcc0Jeff Garzik{ 1537c9d39130123238ac18478a42e25cb7996eacfcc0Jeff Garzik unsigned int ofs; 1538c9d39130123238ac18478a42e25cb7996eacfcc0Jeff Garzik 1539c9d39130123238ac18478a42e25cb7996eacfcc0Jeff Garzik switch (sc_reg_in) { 1540c9d39130123238ac18478a42e25cb7996eacfcc0Jeff Garzik case SCR_STATUS: 1541c9d39130123238ac18478a42e25cb7996eacfcc0Jeff Garzik case SCR_ERROR: 1542c9d39130123238ac18478a42e25cb7996eacfcc0Jeff Garzik case SCR_CONTROL: 1543c9d39130123238ac18478a42e25cb7996eacfcc0Jeff Garzik ofs = sc_reg_in * sizeof(u32); 1544c9d39130123238ac18478a42e25cb7996eacfcc0Jeff Garzik break; 1545c9d39130123238ac18478a42e25cb7996eacfcc0Jeff Garzik default: 1546c9d39130123238ac18478a42e25cb7996eacfcc0Jeff Garzik ofs = 0xffffffffU; 1547c9d39130123238ac18478a42e25cb7996eacfcc0Jeff Garzik break; 1548c9d39130123238ac18478a42e25cb7996eacfcc0Jeff Garzik } 1549c9d39130123238ac18478a42e25cb7996eacfcc0Jeff Garzik return ofs; 1550c9d39130123238ac18478a42e25cb7996eacfcc0Jeff Garzik} 1551c9d39130123238ac18478a42e25cb7996eacfcc0Jeff Garzik 1552c9d39130123238ac18478a42e25cb7996eacfcc0Jeff Garzikstatic u32 mv5_scr_read(struct ata_port *ap, unsigned int sc_reg_in) 1553c9d39130123238ac18478a42e25cb7996eacfcc0Jeff Garzik{ 15540d5ff566779f894ca9937231a181eb31e4adff0eTejun Heo void __iomem *mmio = ap->host->iomap[MV_PRIMARY_BAR]; 15550d5ff566779f894ca9937231a181eb31e4adff0eTejun Heo void __iomem *addr = mv5_phy_base(mmio, ap->port_no); 1556c9d39130123238ac18478a42e25cb7996eacfcc0Jeff Garzik unsigned int ofs = mv5_scr_offset(sc_reg_in); 1557c9d39130123238ac18478a42e25cb7996eacfcc0Jeff Garzik 1558c9d39130123238ac18478a42e25cb7996eacfcc0Jeff Garzik if (ofs != 0xffffffffU) 15590d5ff566779f894ca9937231a181eb31e4adff0eTejun Heo return readl(addr + ofs); 1560c9d39130123238ac18478a42e25cb7996eacfcc0Jeff Garzik else 1561c9d39130123238ac18478a42e25cb7996eacfcc0Jeff Garzik return (u32) ofs; 1562c9d39130123238ac18478a42e25cb7996eacfcc0Jeff Garzik} 1563c9d39130123238ac18478a42e25cb7996eacfcc0Jeff Garzik 1564c9d39130123238ac18478a42e25cb7996eacfcc0Jeff Garzikstatic void mv5_scr_write(struct ata_port *ap, unsigned int sc_reg_in, u32 val) 1565c9d39130123238ac18478a42e25cb7996eacfcc0Jeff Garzik{ 15660d5ff566779f894ca9937231a181eb31e4adff0eTejun Heo void __iomem *mmio = ap->host->iomap[MV_PRIMARY_BAR]; 15670d5ff566779f894ca9937231a181eb31e4adff0eTejun Heo void __iomem *addr = mv5_phy_base(mmio, ap->port_no); 1568c9d39130123238ac18478a42e25cb7996eacfcc0Jeff Garzik unsigned int ofs = mv5_scr_offset(sc_reg_in); 1569c9d39130123238ac18478a42e25cb7996eacfcc0Jeff Garzik 1570c9d39130123238ac18478a42e25cb7996eacfcc0Jeff Garzik if (ofs != 0xffffffffU) 15710d5ff566779f894ca9937231a181eb31e4adff0eTejun Heo writelfl(val, addr + ofs); 1572c9d39130123238ac18478a42e25cb7996eacfcc0Jeff Garzik} 1573c9d39130123238ac18478a42e25cb7996eacfcc0Jeff Garzik 1574522479fb98c6667f081e75f87e298e413c0b1db8Jeff Garzikstatic void mv5_reset_bus(struct pci_dev *pdev, void __iomem *mmio) 1575522479fb98c6667f081e75f87e298e413c0b1db8Jeff Garzik{ 1576522479fb98c6667f081e75f87e298e413c0b1db8Jeff Garzik int early_5080; 1577522479fb98c6667f081e75f87e298e413c0b1db8Jeff Garzik 157844c10138fd4bbc4b6d6bff0873c24902f2a9da65Auke Kok early_5080 = (pdev->device == 0x5080) && (pdev->revision == 0); 1579522479fb98c6667f081e75f87e298e413c0b1db8Jeff Garzik 1580522479fb98c6667f081e75f87e298e413c0b1db8Jeff Garzik if (!early_5080) { 1581522479fb98c6667f081e75f87e298e413c0b1db8Jeff Garzik u32 tmp = readl(mmio + MV_PCI_EXP_ROM_BAR_CTL); 1582522479fb98c6667f081e75f87e298e413c0b1db8Jeff Garzik tmp |= (1 << 0); 1583522479fb98c6667f081e75f87e298e413c0b1db8Jeff Garzik writel(tmp, mmio + MV_PCI_EXP_ROM_BAR_CTL); 1584522479fb98c6667f081e75f87e298e413c0b1db8Jeff Garzik } 1585522479fb98c6667f081e75f87e298e413c0b1db8Jeff Garzik 1586522479fb98c6667f081e75f87e298e413c0b1db8Jeff Garzik mv_reset_pci_bus(pdev, mmio); 1587522479fb98c6667f081e75f87e298e413c0b1db8Jeff Garzik} 1588522479fb98c6667f081e75f87e298e413c0b1db8Jeff Garzik 1589522479fb98c6667f081e75f87e298e413c0b1db8Jeff Garzikstatic void mv5_reset_flash(struct mv_host_priv *hpriv, void __iomem *mmio) 1590522479fb98c6667f081e75f87e298e413c0b1db8Jeff Garzik{ 1591522479fb98c6667f081e75f87e298e413c0b1db8Jeff Garzik writel(0x0fcfffff, mmio + MV_FLASH_CTL); 1592522479fb98c6667f081e75f87e298e413c0b1db8Jeff Garzik} 1593522479fb98c6667f081e75f87e298e413c0b1db8Jeff Garzik 159447c2b677daeed9c79ecb7167c211ff36876ea611Jeff Garzikstatic void mv5_read_preamp(struct mv_host_priv *hpriv, int idx, 1595ba3fe8fb6a469390a14379519915f3c39a973d99Jeff Garzik void __iomem *mmio) 1596ba3fe8fb6a469390a14379519915f3c39a973d99Jeff Garzik{ 1597c9d39130123238ac18478a42e25cb7996eacfcc0Jeff Garzik void __iomem *phy_mmio = mv5_phy_base(mmio, idx); 1598c9d39130123238ac18478a42e25cb7996eacfcc0Jeff Garzik u32 tmp; 1599c9d39130123238ac18478a42e25cb7996eacfcc0Jeff Garzik 1600c9d39130123238ac18478a42e25cb7996eacfcc0Jeff Garzik tmp = readl(phy_mmio + MV5_PHY_MODE); 1601c9d39130123238ac18478a42e25cb7996eacfcc0Jeff Garzik 1602c9d39130123238ac18478a42e25cb7996eacfcc0Jeff Garzik hpriv->signal[idx].pre = tmp & 0x1800; /* bits 12:11 */ 1603c9d39130123238ac18478a42e25cb7996eacfcc0Jeff Garzik hpriv->signal[idx].amps = tmp & 0xe0; /* bits 7:5 */ 1604ba3fe8fb6a469390a14379519915f3c39a973d99Jeff Garzik} 1605ba3fe8fb6a469390a14379519915f3c39a973d99Jeff Garzik 160647c2b677daeed9c79ecb7167c211ff36876ea611Jeff Garzikstatic void mv5_enable_leds(struct mv_host_priv *hpriv, void __iomem *mmio) 1607ba3fe8fb6a469390a14379519915f3c39a973d99Jeff Garzik{ 1608522479fb98c6667f081e75f87e298e413c0b1db8Jeff Garzik u32 tmp; 1609522479fb98c6667f081e75f87e298e413c0b1db8Jeff Garzik 1610522479fb98c6667f081e75f87e298e413c0b1db8Jeff Garzik writel(0, mmio + MV_GPIO_PORT_CTL); 1611522479fb98c6667f081e75f87e298e413c0b1db8Jeff Garzik 1612522479fb98c6667f081e75f87e298e413c0b1db8Jeff Garzik /* FIXME: handle MV_HP_ERRATA_50XXB2 errata */ 1613522479fb98c6667f081e75f87e298e413c0b1db8Jeff Garzik 1614522479fb98c6667f081e75f87e298e413c0b1db8Jeff Garzik tmp = readl(mmio + MV_PCI_EXP_ROM_BAR_CTL); 1615522479fb98c6667f081e75f87e298e413c0b1db8Jeff Garzik tmp |= ~(1 << 0); 1616522479fb98c6667f081e75f87e298e413c0b1db8Jeff Garzik writel(tmp, mmio + MV_PCI_EXP_ROM_BAR_CTL); 1617ba3fe8fb6a469390a14379519915f3c39a973d99Jeff Garzik} 1618ba3fe8fb6a469390a14379519915f3c39a973d99Jeff Garzik 16192a47ce06d534692f9bd2bf4e90a20fc9b1054c39Jeff Garzikstatic void mv5_phy_errata(struct mv_host_priv *hpriv, void __iomem *mmio, 16202a47ce06d534692f9bd2bf4e90a20fc9b1054c39Jeff Garzik unsigned int port) 1621bca1c4eb9411533d613123618c0d127fae532595Jeff Garzik{ 1622c9d39130123238ac18478a42e25cb7996eacfcc0Jeff Garzik void __iomem *phy_mmio = mv5_phy_base(mmio, port); 1623c9d39130123238ac18478a42e25cb7996eacfcc0Jeff Garzik const u32 mask = (1<<12) | (1<<11) | (1<<7) | (1<<6) | (1<<5); 1624c9d39130123238ac18478a42e25cb7996eacfcc0Jeff Garzik u32 tmp; 1625c9d39130123238ac18478a42e25cb7996eacfcc0Jeff Garzik int fix_apm_sq = (hpriv->hp_flags & MV_HP_ERRATA_50XXB0); 1626c9d39130123238ac18478a42e25cb7996eacfcc0Jeff Garzik 1627c9d39130123238ac18478a42e25cb7996eacfcc0Jeff Garzik if (fix_apm_sq) { 1628c9d39130123238ac18478a42e25cb7996eacfcc0Jeff Garzik tmp = readl(phy_mmio + MV5_LT_MODE); 1629c9d39130123238ac18478a42e25cb7996eacfcc0Jeff Garzik tmp |= (1 << 19); 1630c9d39130123238ac18478a42e25cb7996eacfcc0Jeff Garzik writel(tmp, phy_mmio + MV5_LT_MODE); 1631c9d39130123238ac18478a42e25cb7996eacfcc0Jeff Garzik 1632c9d39130123238ac18478a42e25cb7996eacfcc0Jeff Garzik tmp = readl(phy_mmio + MV5_PHY_CTL); 1633c9d39130123238ac18478a42e25cb7996eacfcc0Jeff Garzik tmp &= ~0x3; 1634c9d39130123238ac18478a42e25cb7996eacfcc0Jeff Garzik tmp |= 0x1; 1635c9d39130123238ac18478a42e25cb7996eacfcc0Jeff Garzik writel(tmp, phy_mmio + MV5_PHY_CTL); 1636c9d39130123238ac18478a42e25cb7996eacfcc0Jeff Garzik } 1637c9d39130123238ac18478a42e25cb7996eacfcc0Jeff Garzik 1638c9d39130123238ac18478a42e25cb7996eacfcc0Jeff Garzik tmp = readl(phy_mmio + MV5_PHY_MODE); 1639c9d39130123238ac18478a42e25cb7996eacfcc0Jeff Garzik tmp &= ~mask; 1640c9d39130123238ac18478a42e25cb7996eacfcc0Jeff Garzik tmp |= hpriv->signal[port].pre; 1641c9d39130123238ac18478a42e25cb7996eacfcc0Jeff Garzik tmp |= hpriv->signal[port].amps; 1642c9d39130123238ac18478a42e25cb7996eacfcc0Jeff Garzik writel(tmp, phy_mmio + MV5_PHY_MODE); 1643bca1c4eb9411533d613123618c0d127fae532595Jeff Garzik} 1644bca1c4eb9411533d613123618c0d127fae532595Jeff Garzik 1645c9d39130123238ac18478a42e25cb7996eacfcc0Jeff Garzik 1646c9d39130123238ac18478a42e25cb7996eacfcc0Jeff Garzik#undef ZERO 1647c9d39130123238ac18478a42e25cb7996eacfcc0Jeff Garzik#define ZERO(reg) writel(0, port_mmio + (reg)) 1648c9d39130123238ac18478a42e25cb7996eacfcc0Jeff Garzikstatic void mv5_reset_hc_port(struct mv_host_priv *hpriv, void __iomem *mmio, 1649c9d39130123238ac18478a42e25cb7996eacfcc0Jeff Garzik unsigned int port) 1650c9d39130123238ac18478a42e25cb7996eacfcc0Jeff Garzik{ 1651c9d39130123238ac18478a42e25cb7996eacfcc0Jeff Garzik void __iomem *port_mmio = mv_port_base(mmio, port); 1652c9d39130123238ac18478a42e25cb7996eacfcc0Jeff Garzik 1653c9d39130123238ac18478a42e25cb7996eacfcc0Jeff Garzik writelfl(EDMA_DS, port_mmio + EDMA_CMD_OFS); 1654c9d39130123238ac18478a42e25cb7996eacfcc0Jeff Garzik 1655c9d39130123238ac18478a42e25cb7996eacfcc0Jeff Garzik mv_channel_reset(hpriv, mmio, port); 1656c9d39130123238ac18478a42e25cb7996eacfcc0Jeff Garzik 1657c9d39130123238ac18478a42e25cb7996eacfcc0Jeff Garzik ZERO(0x028); /* command */ 1658c9d39130123238ac18478a42e25cb7996eacfcc0Jeff Garzik writel(0x11f, port_mmio + EDMA_CFG_OFS); 1659c9d39130123238ac18478a42e25cb7996eacfcc0Jeff Garzik ZERO(0x004); /* timer */ 1660c9d39130123238ac18478a42e25cb7996eacfcc0Jeff Garzik ZERO(0x008); /* irq err cause */ 1661c9d39130123238ac18478a42e25cb7996eacfcc0Jeff Garzik ZERO(0x00c); /* irq err mask */ 1662c9d39130123238ac18478a42e25cb7996eacfcc0Jeff Garzik ZERO(0x010); /* rq bah */ 1663c9d39130123238ac18478a42e25cb7996eacfcc0Jeff Garzik ZERO(0x014); /* rq inp */ 1664c9d39130123238ac18478a42e25cb7996eacfcc0Jeff Garzik ZERO(0x018); /* rq outp */ 1665c9d39130123238ac18478a42e25cb7996eacfcc0Jeff Garzik ZERO(0x01c); /* respq bah */ 1666c9d39130123238ac18478a42e25cb7996eacfcc0Jeff Garzik ZERO(0x024); /* respq outp */ 1667c9d39130123238ac18478a42e25cb7996eacfcc0Jeff Garzik ZERO(0x020); /* respq inp */ 1668c9d39130123238ac18478a42e25cb7996eacfcc0Jeff Garzik ZERO(0x02c); /* test control */ 1669c9d39130123238ac18478a42e25cb7996eacfcc0Jeff Garzik writel(0xbc, port_mmio + EDMA_IORDY_TMOUT); 1670c9d39130123238ac18478a42e25cb7996eacfcc0Jeff Garzik} 1671c9d39130123238ac18478a42e25cb7996eacfcc0Jeff Garzik#undef ZERO 1672c9d39130123238ac18478a42e25cb7996eacfcc0Jeff Garzik 1673c9d39130123238ac18478a42e25cb7996eacfcc0Jeff Garzik#define ZERO(reg) writel(0, hc_mmio + (reg)) 1674c9d39130123238ac18478a42e25cb7996eacfcc0Jeff Garzikstatic void mv5_reset_one_hc(struct mv_host_priv *hpriv, void __iomem *mmio, 1675c9d39130123238ac18478a42e25cb7996eacfcc0Jeff Garzik unsigned int hc) 167647c2b677daeed9c79ecb7167c211ff36876ea611Jeff Garzik{ 1677c9d39130123238ac18478a42e25cb7996eacfcc0Jeff Garzik void __iomem *hc_mmio = mv_hc_base(mmio, hc); 1678c9d39130123238ac18478a42e25cb7996eacfcc0Jeff Garzik u32 tmp; 1679c9d39130123238ac18478a42e25cb7996eacfcc0Jeff Garzik 1680c9d39130123238ac18478a42e25cb7996eacfcc0Jeff Garzik ZERO(0x00c); 1681c9d39130123238ac18478a42e25cb7996eacfcc0Jeff Garzik ZERO(0x010); 1682c9d39130123238ac18478a42e25cb7996eacfcc0Jeff Garzik ZERO(0x014); 1683c9d39130123238ac18478a42e25cb7996eacfcc0Jeff Garzik ZERO(0x018); 1684c9d39130123238ac18478a42e25cb7996eacfcc0Jeff Garzik 1685c9d39130123238ac18478a42e25cb7996eacfcc0Jeff Garzik tmp = readl(hc_mmio + 0x20); 1686c9d39130123238ac18478a42e25cb7996eacfcc0Jeff Garzik tmp &= 0x1c1c1c1c; 1687c9d39130123238ac18478a42e25cb7996eacfcc0Jeff Garzik tmp |= 0x03030303; 1688c9d39130123238ac18478a42e25cb7996eacfcc0Jeff Garzik writel(tmp, hc_mmio + 0x20); 1689c9d39130123238ac18478a42e25cb7996eacfcc0Jeff Garzik} 1690c9d39130123238ac18478a42e25cb7996eacfcc0Jeff Garzik#undef ZERO 1691c9d39130123238ac18478a42e25cb7996eacfcc0Jeff Garzik 1692c9d39130123238ac18478a42e25cb7996eacfcc0Jeff Garzikstatic int mv5_reset_hc(struct mv_host_priv *hpriv, void __iomem *mmio, 1693c9d39130123238ac18478a42e25cb7996eacfcc0Jeff Garzik unsigned int n_hc) 1694c9d39130123238ac18478a42e25cb7996eacfcc0Jeff Garzik{ 1695c9d39130123238ac18478a42e25cb7996eacfcc0Jeff Garzik unsigned int hc, port; 1696c9d39130123238ac18478a42e25cb7996eacfcc0Jeff Garzik 1697c9d39130123238ac18478a42e25cb7996eacfcc0Jeff Garzik for (hc = 0; hc < n_hc; hc++) { 1698c9d39130123238ac18478a42e25cb7996eacfcc0Jeff Garzik for (port = 0; port < MV_PORTS_PER_HC; port++) 1699c9d39130123238ac18478a42e25cb7996eacfcc0Jeff Garzik mv5_reset_hc_port(hpriv, mmio, 1700c9d39130123238ac18478a42e25cb7996eacfcc0Jeff Garzik (hc * MV_PORTS_PER_HC) + port); 1701c9d39130123238ac18478a42e25cb7996eacfcc0Jeff Garzik 1702c9d39130123238ac18478a42e25cb7996eacfcc0Jeff Garzik mv5_reset_one_hc(hpriv, mmio, hc); 1703c9d39130123238ac18478a42e25cb7996eacfcc0Jeff Garzik } 1704c9d39130123238ac18478a42e25cb7996eacfcc0Jeff Garzik 1705c9d39130123238ac18478a42e25cb7996eacfcc0Jeff Garzik return 0; 170647c2b677daeed9c79ecb7167c211ff36876ea611Jeff Garzik} 170747c2b677daeed9c79ecb7167c211ff36876ea611Jeff Garzik 1708101ffae26c23ea928fce6d31a8b4901327d91a15Jeff Garzik#undef ZERO 1709101ffae26c23ea928fce6d31a8b4901327d91a15Jeff Garzik#define ZERO(reg) writel(0, mmio + (reg)) 1710101ffae26c23ea928fce6d31a8b4901327d91a15Jeff Garzikstatic void mv_reset_pci_bus(struct pci_dev *pdev, void __iomem *mmio) 1711101ffae26c23ea928fce6d31a8b4901327d91a15Jeff Garzik{ 1712101ffae26c23ea928fce6d31a8b4901327d91a15Jeff Garzik u32 tmp; 1713101ffae26c23ea928fce6d31a8b4901327d91a15Jeff Garzik 1714101ffae26c23ea928fce6d31a8b4901327d91a15Jeff Garzik tmp = readl(mmio + MV_PCI_MODE); 1715101ffae26c23ea928fce6d31a8b4901327d91a15Jeff Garzik tmp &= 0xff00ffff; 1716101ffae26c23ea928fce6d31a8b4901327d91a15Jeff Garzik writel(tmp, mmio + MV_PCI_MODE); 1717101ffae26c23ea928fce6d31a8b4901327d91a15Jeff Garzik 1718101ffae26c23ea928fce6d31a8b4901327d91a15Jeff Garzik ZERO(MV_PCI_DISC_TIMER); 1719101ffae26c23ea928fce6d31a8b4901327d91a15Jeff Garzik ZERO(MV_PCI_MSI_TRIGGER); 1720101ffae26c23ea928fce6d31a8b4901327d91a15Jeff Garzik writel(0x000100ff, mmio + MV_PCI_XBAR_TMOUT); 1721101ffae26c23ea928fce6d31a8b4901327d91a15Jeff Garzik ZERO(HC_MAIN_IRQ_MASK_OFS); 1722101ffae26c23ea928fce6d31a8b4901327d91a15Jeff Garzik ZERO(MV_PCI_SERR_MASK); 1723101ffae26c23ea928fce6d31a8b4901327d91a15Jeff Garzik ZERO(PCI_IRQ_CAUSE_OFS); 1724101ffae26c23ea928fce6d31a8b4901327d91a15Jeff Garzik ZERO(PCI_IRQ_MASK_OFS); 1725101ffae26c23ea928fce6d31a8b4901327d91a15Jeff Garzik ZERO(MV_PCI_ERR_LOW_ADDRESS); 1726101ffae26c23ea928fce6d31a8b4901327d91a15Jeff Garzik ZERO(MV_PCI_ERR_HIGH_ADDRESS); 1727101ffae26c23ea928fce6d31a8b4901327d91a15Jeff Garzik ZERO(MV_PCI_ERR_ATTRIBUTE); 1728101ffae26c23ea928fce6d31a8b4901327d91a15Jeff Garzik ZERO(MV_PCI_ERR_COMMAND); 1729101ffae26c23ea928fce6d31a8b4901327d91a15Jeff Garzik} 1730101ffae26c23ea928fce6d31a8b4901327d91a15Jeff Garzik#undef ZERO 1731101ffae26c23ea928fce6d31a8b4901327d91a15Jeff Garzik 1732101ffae26c23ea928fce6d31a8b4901327d91a15Jeff Garzikstatic void mv6_reset_flash(struct mv_host_priv *hpriv, void __iomem *mmio) 1733101ffae26c23ea928fce6d31a8b4901327d91a15Jeff Garzik{ 1734101ffae26c23ea928fce6d31a8b4901327d91a15Jeff Garzik u32 tmp; 1735101ffae26c23ea928fce6d31a8b4901327d91a15Jeff Garzik 1736101ffae26c23ea928fce6d31a8b4901327d91a15Jeff Garzik mv5_reset_flash(hpriv, mmio); 1737101ffae26c23ea928fce6d31a8b4901327d91a15Jeff Garzik 1738101ffae26c23ea928fce6d31a8b4901327d91a15Jeff Garzik tmp = readl(mmio + MV_GPIO_PORT_CTL); 1739101ffae26c23ea928fce6d31a8b4901327d91a15Jeff Garzik tmp &= 0x3; 1740101ffae26c23ea928fce6d31a8b4901327d91a15Jeff Garzik tmp |= (1 << 5) | (1 << 6); 1741101ffae26c23ea928fce6d31a8b4901327d91a15Jeff Garzik writel(tmp, mmio + MV_GPIO_PORT_CTL); 1742101ffae26c23ea928fce6d31a8b4901327d91a15Jeff Garzik} 1743101ffae26c23ea928fce6d31a8b4901327d91a15Jeff Garzik 1744101ffae26c23ea928fce6d31a8b4901327d91a15Jeff Garzik/** 1745101ffae26c23ea928fce6d31a8b4901327d91a15Jeff Garzik * mv6_reset_hc - Perform the 6xxx global soft reset 1746101ffae26c23ea928fce6d31a8b4901327d91a15Jeff Garzik * @mmio: base address of the HBA 1747101ffae26c23ea928fce6d31a8b4901327d91a15Jeff Garzik * 1748101ffae26c23ea928fce6d31a8b4901327d91a15Jeff Garzik * This routine only applies to 6xxx parts. 1749101ffae26c23ea928fce6d31a8b4901327d91a15Jeff Garzik * 1750101ffae26c23ea928fce6d31a8b4901327d91a15Jeff Garzik * LOCKING: 1751101ffae26c23ea928fce6d31a8b4901327d91a15Jeff Garzik * Inherited from caller. 1752101ffae26c23ea928fce6d31a8b4901327d91a15Jeff Garzik */ 1753c9d39130123238ac18478a42e25cb7996eacfcc0Jeff Garzikstatic int mv6_reset_hc(struct mv_host_priv *hpriv, void __iomem *mmio, 1754c9d39130123238ac18478a42e25cb7996eacfcc0Jeff Garzik unsigned int n_hc) 1755101ffae26c23ea928fce6d31a8b4901327d91a15Jeff Garzik{ 1756101ffae26c23ea928fce6d31a8b4901327d91a15Jeff Garzik void __iomem *reg = mmio + PCI_MAIN_CMD_STS_OFS; 1757101ffae26c23ea928fce6d31a8b4901327d91a15Jeff Garzik int i, rc = 0; 1758101ffae26c23ea928fce6d31a8b4901327d91a15Jeff Garzik u32 t; 1759101ffae26c23ea928fce6d31a8b4901327d91a15Jeff Garzik 1760101ffae26c23ea928fce6d31a8b4901327d91a15Jeff Garzik /* Following procedure defined in PCI "main command and status 1761101ffae26c23ea928fce6d31a8b4901327d91a15Jeff Garzik * register" table. 1762101ffae26c23ea928fce6d31a8b4901327d91a15Jeff Garzik */ 1763101ffae26c23ea928fce6d31a8b4901327d91a15Jeff Garzik t = readl(reg); 1764101ffae26c23ea928fce6d31a8b4901327d91a15Jeff Garzik writel(t | STOP_PCI_MASTER, reg); 1765101ffae26c23ea928fce6d31a8b4901327d91a15Jeff Garzik 1766101ffae26c23ea928fce6d31a8b4901327d91a15Jeff Garzik for (i = 0; i < 1000; i++) { 1767101ffae26c23ea928fce6d31a8b4901327d91a15Jeff Garzik udelay(1); 1768101ffae26c23ea928fce6d31a8b4901327d91a15Jeff Garzik t = readl(reg); 1769101ffae26c23ea928fce6d31a8b4901327d91a15Jeff Garzik if (PCI_MASTER_EMPTY & t) { 1770101ffae26c23ea928fce6d31a8b4901327d91a15Jeff Garzik break; 1771101ffae26c23ea928fce6d31a8b4901327d91a15Jeff Garzik } 1772101ffae26c23ea928fce6d31a8b4901327d91a15Jeff Garzik } 1773101ffae26c23ea928fce6d31a8b4901327d91a15Jeff Garzik if (!(PCI_MASTER_EMPTY & t)) { 1774101ffae26c23ea928fce6d31a8b4901327d91a15Jeff Garzik printk(KERN_ERR DRV_NAME ": PCI master won't flush\n"); 1775101ffae26c23ea928fce6d31a8b4901327d91a15Jeff Garzik rc = 1; 1776101ffae26c23ea928fce6d31a8b4901327d91a15Jeff Garzik goto done; 1777101ffae26c23ea928fce6d31a8b4901327d91a15Jeff Garzik } 1778101ffae26c23ea928fce6d31a8b4901327d91a15Jeff Garzik 1779101ffae26c23ea928fce6d31a8b4901327d91a15Jeff Garzik /* set reset */ 1780101ffae26c23ea928fce6d31a8b4901327d91a15Jeff Garzik i = 5; 1781101ffae26c23ea928fce6d31a8b4901327d91a15Jeff Garzik do { 1782101ffae26c23ea928fce6d31a8b4901327d91a15Jeff Garzik writel(t | GLOB_SFT_RST, reg); 1783101ffae26c23ea928fce6d31a8b4901327d91a15Jeff Garzik t = readl(reg); 1784101ffae26c23ea928fce6d31a8b4901327d91a15Jeff Garzik udelay(1); 1785101ffae26c23ea928fce6d31a8b4901327d91a15Jeff Garzik } while (!(GLOB_SFT_RST & t) && (i-- > 0)); 1786101ffae26c23ea928fce6d31a8b4901327d91a15Jeff Garzik 1787101ffae26c23ea928fce6d31a8b4901327d91a15Jeff Garzik if (!(GLOB_SFT_RST & t)) { 1788101ffae26c23ea928fce6d31a8b4901327d91a15Jeff Garzik printk(KERN_ERR DRV_NAME ": can't set global reset\n"); 1789101ffae26c23ea928fce6d31a8b4901327d91a15Jeff Garzik rc = 1; 1790101ffae26c23ea928fce6d31a8b4901327d91a15Jeff Garzik goto done; 1791101ffae26c23ea928fce6d31a8b4901327d91a15Jeff Garzik } 1792101ffae26c23ea928fce6d31a8b4901327d91a15Jeff Garzik 1793101ffae26c23ea928fce6d31a8b4901327d91a15Jeff Garzik /* clear reset and *reenable the PCI master* (not mentioned in spec) */ 1794101ffae26c23ea928fce6d31a8b4901327d91a15Jeff Garzik i = 5; 1795101ffae26c23ea928fce6d31a8b4901327d91a15Jeff Garzik do { 1796101ffae26c23ea928fce6d31a8b4901327d91a15Jeff Garzik writel(t & ~(GLOB_SFT_RST | STOP_PCI_MASTER), reg); 1797101ffae26c23ea928fce6d31a8b4901327d91a15Jeff Garzik t = readl(reg); 1798101ffae26c23ea928fce6d31a8b4901327d91a15Jeff Garzik udelay(1); 1799101ffae26c23ea928fce6d31a8b4901327d91a15Jeff Garzik } while ((GLOB_SFT_RST & t) && (i-- > 0)); 1800101ffae26c23ea928fce6d31a8b4901327d91a15Jeff Garzik 1801101ffae26c23ea928fce6d31a8b4901327d91a15Jeff Garzik if (GLOB_SFT_RST & t) { 1802101ffae26c23ea928fce6d31a8b4901327d91a15Jeff Garzik printk(KERN_ERR DRV_NAME ": can't clear global reset\n"); 1803101ffae26c23ea928fce6d31a8b4901327d91a15Jeff Garzik rc = 1; 1804101ffae26c23ea928fce6d31a8b4901327d91a15Jeff Garzik } 1805101ffae26c23ea928fce6d31a8b4901327d91a15Jeff Garzikdone: 1806101ffae26c23ea928fce6d31a8b4901327d91a15Jeff Garzik return rc; 1807101ffae26c23ea928fce6d31a8b4901327d91a15Jeff Garzik} 1808101ffae26c23ea928fce6d31a8b4901327d91a15Jeff Garzik 180947c2b677daeed9c79ecb7167c211ff36876ea611Jeff Garzikstatic void mv6_read_preamp(struct mv_host_priv *hpriv, int idx, 1810ba3fe8fb6a469390a14379519915f3c39a973d99Jeff Garzik void __iomem *mmio) 1811ba3fe8fb6a469390a14379519915f3c39a973d99Jeff Garzik{ 1812ba3fe8fb6a469390a14379519915f3c39a973d99Jeff Garzik void __iomem *port_mmio; 1813ba3fe8fb6a469390a14379519915f3c39a973d99Jeff Garzik u32 tmp; 1814ba3fe8fb6a469390a14379519915f3c39a973d99Jeff Garzik 1815ba3fe8fb6a469390a14379519915f3c39a973d99Jeff Garzik tmp = readl(mmio + MV_RESET_CFG); 1816ba3fe8fb6a469390a14379519915f3c39a973d99Jeff Garzik if ((tmp & (1 << 0)) == 0) { 181747c2b677daeed9c79ecb7167c211ff36876ea611Jeff Garzik hpriv->signal[idx].amps = 0x7 << 8; 1818ba3fe8fb6a469390a14379519915f3c39a973d99Jeff Garzik hpriv->signal[idx].pre = 0x1 << 5; 1819ba3fe8fb6a469390a14379519915f3c39a973d99Jeff Garzik return; 1820ba3fe8fb6a469390a14379519915f3c39a973d99Jeff Garzik } 1821ba3fe8fb6a469390a14379519915f3c39a973d99Jeff Garzik 1822ba3fe8fb6a469390a14379519915f3c39a973d99Jeff Garzik port_mmio = mv_port_base(mmio, idx); 1823ba3fe8fb6a469390a14379519915f3c39a973d99Jeff Garzik tmp = readl(port_mmio + PHY_MODE2); 1824ba3fe8fb6a469390a14379519915f3c39a973d99Jeff Garzik 1825ba3fe8fb6a469390a14379519915f3c39a973d99Jeff Garzik hpriv->signal[idx].amps = tmp & 0x700; /* bits 10:8 */ 1826ba3fe8fb6a469390a14379519915f3c39a973d99Jeff Garzik hpriv->signal[idx].pre = tmp & 0xe0; /* bits 7:5 */ 1827ba3fe8fb6a469390a14379519915f3c39a973d99Jeff Garzik} 1828ba3fe8fb6a469390a14379519915f3c39a973d99Jeff Garzik 182947c2b677daeed9c79ecb7167c211ff36876ea611Jeff Garzikstatic void mv6_enable_leds(struct mv_host_priv *hpriv, void __iomem *mmio) 1830ba3fe8fb6a469390a14379519915f3c39a973d99Jeff Garzik{ 183147c2b677daeed9c79ecb7167c211ff36876ea611Jeff Garzik writel(0x00000060, mmio + MV_GPIO_PORT_CTL); 1832ba3fe8fb6a469390a14379519915f3c39a973d99Jeff Garzik} 1833ba3fe8fb6a469390a14379519915f3c39a973d99Jeff Garzik 1834c9d39130123238ac18478a42e25cb7996eacfcc0Jeff Garzikstatic void mv6_phy_errata(struct mv_host_priv *hpriv, void __iomem *mmio, 18352a47ce06d534692f9bd2bf4e90a20fc9b1054c39Jeff Garzik unsigned int port) 1836bca1c4eb9411533d613123618c0d127fae532595Jeff Garzik{ 1837c9d39130123238ac18478a42e25cb7996eacfcc0Jeff Garzik void __iomem *port_mmio = mv_port_base(mmio, port); 1838c9d39130123238ac18478a42e25cb7996eacfcc0Jeff Garzik 1839bca1c4eb9411533d613123618c0d127fae532595Jeff Garzik u32 hp_flags = hpriv->hp_flags; 184047c2b677daeed9c79ecb7167c211ff36876ea611Jeff Garzik int fix_phy_mode2 = 184147c2b677daeed9c79ecb7167c211ff36876ea611Jeff Garzik hp_flags & (MV_HP_ERRATA_60X1B2 | MV_HP_ERRATA_60X1C0); 1842bca1c4eb9411533d613123618c0d127fae532595Jeff Garzik int fix_phy_mode4 = 184347c2b677daeed9c79ecb7167c211ff36876ea611Jeff Garzik hp_flags & (MV_HP_ERRATA_60X1B2 | MV_HP_ERRATA_60X1C0); 184447c2b677daeed9c79ecb7167c211ff36876ea611Jeff Garzik u32 m2, tmp; 184547c2b677daeed9c79ecb7167c211ff36876ea611Jeff Garzik 184647c2b677daeed9c79ecb7167c211ff36876ea611Jeff Garzik if (fix_phy_mode2) { 184747c2b677daeed9c79ecb7167c211ff36876ea611Jeff Garzik m2 = readl(port_mmio + PHY_MODE2); 184847c2b677daeed9c79ecb7167c211ff36876ea611Jeff Garzik m2 &= ~(1 << 16); 184947c2b677daeed9c79ecb7167c211ff36876ea611Jeff Garzik m2 |= (1 << 31); 185047c2b677daeed9c79ecb7167c211ff36876ea611Jeff Garzik writel(m2, port_mmio + PHY_MODE2); 185147c2b677daeed9c79ecb7167c211ff36876ea611Jeff Garzik 185247c2b677daeed9c79ecb7167c211ff36876ea611Jeff Garzik udelay(200); 185347c2b677daeed9c79ecb7167c211ff36876ea611Jeff Garzik 185447c2b677daeed9c79ecb7167c211ff36876ea611Jeff Garzik m2 = readl(port_mmio + PHY_MODE2); 185547c2b677daeed9c79ecb7167c211ff36876ea611Jeff Garzik m2 &= ~((1 << 16) | (1 << 31)); 185647c2b677daeed9c79ecb7167c211ff36876ea611Jeff Garzik writel(m2, port_mmio + PHY_MODE2); 185747c2b677daeed9c79ecb7167c211ff36876ea611Jeff Garzik 185847c2b677daeed9c79ecb7167c211ff36876ea611Jeff Garzik udelay(200); 185947c2b677daeed9c79ecb7167c211ff36876ea611Jeff Garzik } 186047c2b677daeed9c79ecb7167c211ff36876ea611Jeff Garzik 186147c2b677daeed9c79ecb7167c211ff36876ea611Jeff Garzik /* who knows what this magic does */ 186247c2b677daeed9c79ecb7167c211ff36876ea611Jeff Garzik tmp = readl(port_mmio + PHY_MODE3); 186347c2b677daeed9c79ecb7167c211ff36876ea611Jeff Garzik tmp &= ~0x7F800000; 186447c2b677daeed9c79ecb7167c211ff36876ea611Jeff Garzik tmp |= 0x2A800000; 186547c2b677daeed9c79ecb7167c211ff36876ea611Jeff Garzik writel(tmp, port_mmio + PHY_MODE3); 1866bca1c4eb9411533d613123618c0d127fae532595Jeff Garzik 1867bca1c4eb9411533d613123618c0d127fae532595Jeff Garzik if (fix_phy_mode4) { 186847c2b677daeed9c79ecb7167c211ff36876ea611Jeff Garzik u32 m4; 1869bca1c4eb9411533d613123618c0d127fae532595Jeff Garzik 1870bca1c4eb9411533d613123618c0d127fae532595Jeff Garzik m4 = readl(port_mmio + PHY_MODE4); 187147c2b677daeed9c79ecb7167c211ff36876ea611Jeff Garzik 187247c2b677daeed9c79ecb7167c211ff36876ea611Jeff Garzik if (hp_flags & MV_HP_ERRATA_60X1B2) 187347c2b677daeed9c79ecb7167c211ff36876ea611Jeff Garzik tmp = readl(port_mmio + 0x310); 1874bca1c4eb9411533d613123618c0d127fae532595Jeff Garzik 1875bca1c4eb9411533d613123618c0d127fae532595Jeff Garzik m4 = (m4 & ~(1 << 1)) | (1 << 0); 1876bca1c4eb9411533d613123618c0d127fae532595Jeff Garzik 1877bca1c4eb9411533d613123618c0d127fae532595Jeff Garzik writel(m4, port_mmio + PHY_MODE4); 187847c2b677daeed9c79ecb7167c211ff36876ea611Jeff Garzik 187947c2b677daeed9c79ecb7167c211ff36876ea611Jeff Garzik if (hp_flags & MV_HP_ERRATA_60X1B2) 188047c2b677daeed9c79ecb7167c211ff36876ea611Jeff Garzik writel(tmp, port_mmio + 0x310); 1881bca1c4eb9411533d613123618c0d127fae532595Jeff Garzik } 1882bca1c4eb9411533d613123618c0d127fae532595Jeff Garzik 1883bca1c4eb9411533d613123618c0d127fae532595Jeff Garzik /* Revert values of pre-emphasis and signal amps to the saved ones */ 1884bca1c4eb9411533d613123618c0d127fae532595Jeff Garzik m2 = readl(port_mmio + PHY_MODE2); 1885bca1c4eb9411533d613123618c0d127fae532595Jeff Garzik 1886bca1c4eb9411533d613123618c0d127fae532595Jeff Garzik m2 &= ~MV_M2_PREAMP_MASK; 18872a47ce06d534692f9bd2bf4e90a20fc9b1054c39Jeff Garzik m2 |= hpriv->signal[port].amps; 18882a47ce06d534692f9bd2bf4e90a20fc9b1054c39Jeff Garzik m2 |= hpriv->signal[port].pre; 188947c2b677daeed9c79ecb7167c211ff36876ea611Jeff Garzik m2 &= ~(1 << 16); 1890bca1c4eb9411533d613123618c0d127fae532595Jeff Garzik 1891e4e7b89280d1d666e2c09e5ad36cf071796c4c7eJeff Garzik /* according to mvSata 3.6.1, some IIE values are fixed */ 1892e4e7b89280d1d666e2c09e5ad36cf071796c4c7eJeff Garzik if (IS_GEN_IIE(hpriv)) { 1893e4e7b89280d1d666e2c09e5ad36cf071796c4c7eJeff Garzik m2 &= ~0xC30FF01F; 1894e4e7b89280d1d666e2c09e5ad36cf071796c4c7eJeff Garzik m2 |= 0x0000900F; 1895e4e7b89280d1d666e2c09e5ad36cf071796c4c7eJeff Garzik } 1896e4e7b89280d1d666e2c09e5ad36cf071796c4c7eJeff Garzik 1897bca1c4eb9411533d613123618c0d127fae532595Jeff Garzik writel(m2, port_mmio + PHY_MODE2); 1898bca1c4eb9411533d613123618c0d127fae532595Jeff Garzik} 1899bca1c4eb9411533d613123618c0d127fae532595Jeff Garzik 1900c9d39130123238ac18478a42e25cb7996eacfcc0Jeff Garzikstatic void mv_channel_reset(struct mv_host_priv *hpriv, void __iomem *mmio, 1901c9d39130123238ac18478a42e25cb7996eacfcc0Jeff Garzik unsigned int port_no) 1902c9d39130123238ac18478a42e25cb7996eacfcc0Jeff Garzik{ 1903c9d39130123238ac18478a42e25cb7996eacfcc0Jeff Garzik void __iomem *port_mmio = mv_port_base(mmio, port_no); 1904c9d39130123238ac18478a42e25cb7996eacfcc0Jeff Garzik 1905c9d39130123238ac18478a42e25cb7996eacfcc0Jeff Garzik writelfl(ATA_RST, port_mmio + EDMA_CMD_OFS); 1906c9d39130123238ac18478a42e25cb7996eacfcc0Jeff Garzik 1907c9d39130123238ac18478a42e25cb7996eacfcc0Jeff Garzik if (IS_60XX(hpriv)) { 1908c9d39130123238ac18478a42e25cb7996eacfcc0Jeff Garzik u32 ifctl = readl(port_mmio + SATA_INTERFACE_CTL); 1909eb46d684600ac145501805a294c94675e82eab2eMark Lord ifctl |= (1 << 7); /* enable gen2i speed */ 1910eb46d684600ac145501805a294c94675e82eab2eMark Lord ifctl = (ifctl & 0xfff) | 0x9b1000; /* from chip spec */ 1911c9d39130123238ac18478a42e25cb7996eacfcc0Jeff Garzik writelfl(ifctl, port_mmio + SATA_INTERFACE_CTL); 1912c9d39130123238ac18478a42e25cb7996eacfcc0Jeff Garzik } 1913c9d39130123238ac18478a42e25cb7996eacfcc0Jeff Garzik 1914c9d39130123238ac18478a42e25cb7996eacfcc0Jeff Garzik udelay(25); /* allow reset propagation */ 1915c9d39130123238ac18478a42e25cb7996eacfcc0Jeff Garzik 1916c9d39130123238ac18478a42e25cb7996eacfcc0Jeff Garzik /* Spec never mentions clearing the bit. Marvell's driver does 1917c9d39130123238ac18478a42e25cb7996eacfcc0Jeff Garzik * clear the bit, however. 1918c9d39130123238ac18478a42e25cb7996eacfcc0Jeff Garzik */ 1919c9d39130123238ac18478a42e25cb7996eacfcc0Jeff Garzik writelfl(0, port_mmio + EDMA_CMD_OFS); 1920c9d39130123238ac18478a42e25cb7996eacfcc0Jeff Garzik 1921c9d39130123238ac18478a42e25cb7996eacfcc0Jeff Garzik hpriv->ops->phy_errata(hpriv, mmio, port_no); 1922c9d39130123238ac18478a42e25cb7996eacfcc0Jeff Garzik 1923c9d39130123238ac18478a42e25cb7996eacfcc0Jeff Garzik if (IS_50XX(hpriv)) 1924c9d39130123238ac18478a42e25cb7996eacfcc0Jeff Garzik mdelay(1); 1925c9d39130123238ac18478a42e25cb7996eacfcc0Jeff Garzik} 1926c9d39130123238ac18478a42e25cb7996eacfcc0Jeff Garzik 1927c9d39130123238ac18478a42e25cb7996eacfcc0Jeff Garzikstatic void mv_stop_and_reset(struct ata_port *ap) 1928c9d39130123238ac18478a42e25cb7996eacfcc0Jeff Garzik{ 1929cca3974e48607c3775dc73b544a5700b2e37c21aJeff Garzik struct mv_host_priv *hpriv = ap->host->private_data; 19300d5ff566779f894ca9937231a181eb31e4adff0eTejun Heo void __iomem *mmio = ap->host->iomap[MV_PRIMARY_BAR]; 1931c9d39130123238ac18478a42e25cb7996eacfcc0Jeff Garzik 1932c9d39130123238ac18478a42e25cb7996eacfcc0Jeff Garzik mv_stop_dma(ap); 1933c9d39130123238ac18478a42e25cb7996eacfcc0Jeff Garzik 1934c9d39130123238ac18478a42e25cb7996eacfcc0Jeff Garzik mv_channel_reset(hpriv, mmio, ap->port_no); 1935c9d39130123238ac18478a42e25cb7996eacfcc0Jeff Garzik 193622374677d18c5eeefd3a283431d312b8c44fef02Jeff Garzik __mv_phy_reset(ap, 0); 193722374677d18c5eeefd3a283431d312b8c44fef02Jeff Garzik} 193822374677d18c5eeefd3a283431d312b8c44fef02Jeff Garzik 193922374677d18c5eeefd3a283431d312b8c44fef02Jeff Garzikstatic inline void __msleep(unsigned int msec, int can_sleep) 194022374677d18c5eeefd3a283431d312b8c44fef02Jeff Garzik{ 194122374677d18c5eeefd3a283431d312b8c44fef02Jeff Garzik if (can_sleep) 194222374677d18c5eeefd3a283431d312b8c44fef02Jeff Garzik msleep(msec); 194322374677d18c5eeefd3a283431d312b8c44fef02Jeff Garzik else 194422374677d18c5eeefd3a283431d312b8c44fef02Jeff Garzik mdelay(msec); 1945c9d39130123238ac18478a42e25cb7996eacfcc0Jeff Garzik} 1946c9d39130123238ac18478a42e25cb7996eacfcc0Jeff Garzik 194705b308e1df6d9d673daedb517969241f41278b52Brett Russ/** 194822374677d18c5eeefd3a283431d312b8c44fef02Jeff Garzik * __mv_phy_reset - Perform eDMA reset followed by COMRESET 194905b308e1df6d9d673daedb517969241f41278b52Brett Russ * @ap: ATA channel to manipulate 195005b308e1df6d9d673daedb517969241f41278b52Brett Russ * 195105b308e1df6d9d673daedb517969241f41278b52Brett Russ * Part of this is taken from __sata_phy_reset and modified to 195205b308e1df6d9d673daedb517969241f41278b52Brett Russ * not sleep since this routine gets called from interrupt level. 195305b308e1df6d9d673daedb517969241f41278b52Brett Russ * 195405b308e1df6d9d673daedb517969241f41278b52Brett Russ * LOCKING: 195505b308e1df6d9d673daedb517969241f41278b52Brett Russ * Inherited from caller. This is coded to safe to call at 195605b308e1df6d9d673daedb517969241f41278b52Brett Russ * interrupt level, i.e. it does not sleep. 195731961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ */ 195822374677d18c5eeefd3a283431d312b8c44fef02Jeff Garzikstatic void __mv_phy_reset(struct ata_port *ap, int can_sleep) 195920f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ{ 1960095fec887eaa1c38d17c0c929a6733c744a9fa1fJeff Garzik struct mv_port_priv *pp = ap->private_data; 1961cca3974e48607c3775dc73b544a5700b2e37c21aJeff Garzik struct mv_host_priv *hpriv = ap->host->private_data; 196220f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ void __iomem *port_mmio = mv_ap_base(ap); 196320f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ struct ata_taskfile tf; 196420f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ struct ata_device *dev = &ap->device[0]; 196531961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ unsigned long timeout; 196622374677d18c5eeefd3a283431d312b8c44fef02Jeff Garzik int retry = 5; 196722374677d18c5eeefd3a283431d312b8c44fef02Jeff Garzik u32 sstatus; 196820f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ 196920f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ VPRINTK("ENTER, port %u, mmio 0x%p\n", ap->port_no, port_mmio); 197020f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ 1971095fec887eaa1c38d17c0c929a6733c744a9fa1fJeff Garzik DPRINTK("S-regs after ATA_RST: SStat 0x%08x SErr 0x%08x " 197231961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ "SCtrl 0x%08x\n", mv_scr_read(ap, SCR_STATUS), 197331961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ mv_scr_read(ap, SCR_ERROR), mv_scr_read(ap, SCR_CONTROL)); 197420f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ 197522374677d18c5eeefd3a283431d312b8c44fef02Jeff Garzik /* Issue COMRESET via SControl */ 197622374677d18c5eeefd3a283431d312b8c44fef02Jeff Garzikcomreset_retry: 197781952c5497b40ae56835bd0d6537f8c6bdea07e7Tejun Heo sata_scr_write_flush(ap, SCR_CONTROL, 0x301); 197822374677d18c5eeefd3a283431d312b8c44fef02Jeff Garzik __msleep(1, can_sleep); 197922374677d18c5eeefd3a283431d312b8c44fef02Jeff Garzik 198081952c5497b40ae56835bd0d6537f8c6bdea07e7Tejun Heo sata_scr_write_flush(ap, SCR_CONTROL, 0x300); 198122374677d18c5eeefd3a283431d312b8c44fef02Jeff Garzik __msleep(20, can_sleep); 198222374677d18c5eeefd3a283431d312b8c44fef02Jeff Garzik 198322374677d18c5eeefd3a283431d312b8c44fef02Jeff Garzik timeout = jiffies + msecs_to_jiffies(200); 198431961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ do { 198581952c5497b40ae56835bd0d6537f8c6bdea07e7Tejun Heo sata_scr_read(ap, SCR_STATUS, &sstatus); 198662f1d0e6de138b91d55fbd7d579c837ed62e9e31Andres Salomon if (((sstatus & 0x3) == 3) || ((sstatus & 0x3) == 0)) 198731961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ break; 198822374677d18c5eeefd3a283431d312b8c44fef02Jeff Garzik 198922374677d18c5eeefd3a283431d312b8c44fef02Jeff Garzik __msleep(1, can_sleep); 199031961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ } while (time_before(jiffies, timeout)); 199120f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ 199222374677d18c5eeefd3a283431d312b8c44fef02Jeff Garzik /* work around errata */ 199322374677d18c5eeefd3a283431d312b8c44fef02Jeff Garzik if (IS_60XX(hpriv) && 199422374677d18c5eeefd3a283431d312b8c44fef02Jeff Garzik (sstatus != 0x0) && (sstatus != 0x113) && (sstatus != 0x123) && 199522374677d18c5eeefd3a283431d312b8c44fef02Jeff Garzik (retry-- > 0)) 199622374677d18c5eeefd3a283431d312b8c44fef02Jeff Garzik goto comreset_retry; 1997095fec887eaa1c38d17c0c929a6733c744a9fa1fJeff Garzik 1998095fec887eaa1c38d17c0c929a6733c744a9fa1fJeff Garzik DPRINTK("S-regs after PHY wake: SStat 0x%08x SErr 0x%08x " 199931961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ "SCtrl 0x%08x\n", mv_scr_read(ap, SCR_STATUS), 200031961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ mv_scr_read(ap, SCR_ERROR), mv_scr_read(ap, SCR_CONTROL)); 200131961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ 200281952c5497b40ae56835bd0d6537f8c6bdea07e7Tejun Heo if (ata_port_online(ap)) { 200331961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ ata_port_probe(ap); 200431961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ } else { 200581952c5497b40ae56835bd0d6537f8c6bdea07e7Tejun Heo sata_scr_read(ap, SCR_STATUS, &sstatus); 2006f15a1dafed22d5037e0feea7528e1eeb28a1a7a3Tejun Heo ata_port_printk(ap, KERN_INFO, 2007f15a1dafed22d5037e0feea7528e1eeb28a1a7a3Tejun Heo "no device found (phy stat %08x)\n", sstatus); 200831961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ ata_port_disable(ap); 200920f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ return; 201020f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ } 201120f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ 201222374677d18c5eeefd3a283431d312b8c44fef02Jeff Garzik /* even after SStatus reflects that device is ready, 201322374677d18c5eeefd3a283431d312b8c44fef02Jeff Garzik * it seems to take a while for link to be fully 201422374677d18c5eeefd3a283431d312b8c44fef02Jeff Garzik * established (and thus Status no longer 0x80/0x7F), 201522374677d18c5eeefd3a283431d312b8c44fef02Jeff Garzik * so we poll a bit for that, here. 201622374677d18c5eeefd3a283431d312b8c44fef02Jeff Garzik */ 201722374677d18c5eeefd3a283431d312b8c44fef02Jeff Garzik retry = 20; 201822374677d18c5eeefd3a283431d312b8c44fef02Jeff Garzik while (1) { 201922374677d18c5eeefd3a283431d312b8c44fef02Jeff Garzik u8 drv_stat = ata_check_status(ap); 202022374677d18c5eeefd3a283431d312b8c44fef02Jeff Garzik if ((drv_stat != 0x80) && (drv_stat != 0x7f)) 202122374677d18c5eeefd3a283431d312b8c44fef02Jeff Garzik break; 202222374677d18c5eeefd3a283431d312b8c44fef02Jeff Garzik __msleep(500, can_sleep); 202322374677d18c5eeefd3a283431d312b8c44fef02Jeff Garzik if (retry-- <= 0) 202422374677d18c5eeefd3a283431d312b8c44fef02Jeff Garzik break; 202522374677d18c5eeefd3a283431d312b8c44fef02Jeff Garzik } 202622374677d18c5eeefd3a283431d312b8c44fef02Jeff Garzik 20270d5ff566779f894ca9937231a181eb31e4adff0eTejun Heo tf.lbah = readb(ap->ioaddr.lbah_addr); 20280d5ff566779f894ca9937231a181eb31e4adff0eTejun Heo tf.lbam = readb(ap->ioaddr.lbam_addr); 20290d5ff566779f894ca9937231a181eb31e4adff0eTejun Heo tf.lbal = readb(ap->ioaddr.lbal_addr); 20300d5ff566779f894ca9937231a181eb31e4adff0eTejun Heo tf.nsect = readb(ap->ioaddr.nsect_addr); 203120f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ 203220f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ dev->class = ata_dev_classify(&tf); 2033e1211e3fa7fd05ff0d4f597fd37e40de8acc6784Tejun Heo if (!ata_dev_enabled(dev)) { 203420f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ VPRINTK("Port disabled post-sig: No device present.\n"); 203520f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ ata_port_disable(ap); 203620f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ } 2037095fec887eaa1c38d17c0c929a6733c744a9fa1fJeff Garzik 2038095fec887eaa1c38d17c0c929a6733c744a9fa1fJeff Garzik writelfl(0, port_mmio + EDMA_ERR_IRQ_CAUSE_OFS); 2039095fec887eaa1c38d17c0c929a6733c744a9fa1fJeff Garzik 2040095fec887eaa1c38d17c0c929a6733c744a9fa1fJeff Garzik pp->pp_flags &= ~MV_PP_FLAG_EDMA_EN; 2041095fec887eaa1c38d17c0c929a6733c744a9fa1fJeff Garzik 2042bca1c4eb9411533d613123618c0d127fae532595Jeff Garzik VPRINTK("EXIT\n"); 204320f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ} 204420f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ 204522374677d18c5eeefd3a283431d312b8c44fef02Jeff Garzikstatic void mv_phy_reset(struct ata_port *ap) 204622374677d18c5eeefd3a283431d312b8c44fef02Jeff Garzik{ 204722374677d18c5eeefd3a283431d312b8c44fef02Jeff Garzik __mv_phy_reset(ap, 1); 204822374677d18c5eeefd3a283431d312b8c44fef02Jeff Garzik} 204922374677d18c5eeefd3a283431d312b8c44fef02Jeff Garzik 205005b308e1df6d9d673daedb517969241f41278b52Brett Russ/** 205105b308e1df6d9d673daedb517969241f41278b52Brett Russ * mv_eng_timeout - Routine called by libata when SCSI times out I/O 205205b308e1df6d9d673daedb517969241f41278b52Brett Russ * @ap: ATA channel to manipulate 205305b308e1df6d9d673daedb517969241f41278b52Brett Russ * 205405b308e1df6d9d673daedb517969241f41278b52Brett Russ * Intent is to clear all pending error conditions, reset the 205505b308e1df6d9d673daedb517969241f41278b52Brett Russ * chip/bus, fail the command, and move on. 205605b308e1df6d9d673daedb517969241f41278b52Brett Russ * 205705b308e1df6d9d673daedb517969241f41278b52Brett Russ * LOCKING: 2058cca3974e48607c3775dc73b544a5700b2e37c21aJeff Garzik * This routine holds the host lock while failing the command. 205905b308e1df6d9d673daedb517969241f41278b52Brett Russ */ 206031961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russstatic void mv_eng_timeout(struct ata_port *ap) 206131961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ{ 20620d5ff566779f894ca9937231a181eb31e4adff0eTejun Heo void __iomem *mmio = ap->host->iomap[MV_PRIMARY_BAR]; 206331961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ struct ata_queued_cmd *qc; 20642f9719b61e1fcf7422a016ac4f2420a0cc6ba320Mark Lord unsigned long flags; 206531961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ 2066f15a1dafed22d5037e0feea7528e1eeb28a1a7a3Tejun Heo ata_port_printk(ap, KERN_ERR, "Entering mv_eng_timeout\n"); 206731961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ DPRINTK("All regs @ start of eng_timeout\n"); 20680d5ff566779f894ca9937231a181eb31e4adff0eTejun Heo mv_dump_all_regs(mmio, ap->port_no, to_pci_dev(ap->host->dev)); 206931961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ 207031961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ qc = ata_qc_from_tag(ap, ap->active_tag); 207131961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ printk(KERN_ERR "mmio_base %p ap %p qc %p scsi_cmnd %p &cmnd %p\n", 20720d5ff566779f894ca9937231a181eb31e4adff0eTejun Heo mmio, ap, qc, qc->scsicmd, &qc->scsicmd->cmnd); 207331961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ 2074cca3974e48607c3775dc73b544a5700b2e37c21aJeff Garzik spin_lock_irqsave(&ap->host->lock, flags); 20759b358e305c1d783c8a4ebf00344e95deb9e38f3dMark Lord mv_err_intr(ap, 0); 2076c9d39130123238ac18478a42e25cb7996eacfcc0Jeff Garzik mv_stop_and_reset(ap); 2077cca3974e48607c3775dc73b544a5700b2e37c21aJeff Garzik spin_unlock_irqrestore(&ap->host->lock, flags); 207831961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ 20799b358e305c1d783c8a4ebf00344e95deb9e38f3dMark Lord WARN_ON(!(qc->flags & ATA_QCFLAG_ACTIVE)); 20809b358e305c1d783c8a4ebf00344e95deb9e38f3dMark Lord if (qc->flags & ATA_QCFLAG_ACTIVE) { 20819b358e305c1d783c8a4ebf00344e95deb9e38f3dMark Lord qc->err_mask |= AC_ERR_TIMEOUT; 20829b358e305c1d783c8a4ebf00344e95deb9e38f3dMark Lord ata_eh_qc_complete(qc); 20839b358e305c1d783c8a4ebf00344e95deb9e38f3dMark Lord } 208431961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ} 208531961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ 208605b308e1df6d9d673daedb517969241f41278b52Brett Russ/** 208705b308e1df6d9d673daedb517969241f41278b52Brett Russ * mv_port_init - Perform some early initialization on a single port. 208805b308e1df6d9d673daedb517969241f41278b52Brett Russ * @port: libata data structure storing shadow register addresses 208905b308e1df6d9d673daedb517969241f41278b52Brett Russ * @port_mmio: base address of the port 209005b308e1df6d9d673daedb517969241f41278b52Brett Russ * 209105b308e1df6d9d673daedb517969241f41278b52Brett Russ * Initialize shadow register mmio addresses, clear outstanding 209205b308e1df6d9d673daedb517969241f41278b52Brett Russ * interrupts on the port, and unmask interrupts for the future 209305b308e1df6d9d673daedb517969241f41278b52Brett Russ * start of the port. 209405b308e1df6d9d673daedb517969241f41278b52Brett Russ * 209505b308e1df6d9d673daedb517969241f41278b52Brett Russ * LOCKING: 209605b308e1df6d9d673daedb517969241f41278b52Brett Russ * Inherited from caller. 209705b308e1df6d9d673daedb517969241f41278b52Brett Russ */ 209831961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russstatic void mv_port_init(struct ata_ioports *port, void __iomem *port_mmio) 209920f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ{ 21000d5ff566779f894ca9937231a181eb31e4adff0eTejun Heo void __iomem *shd_base = port_mmio + SHD_BLK_OFS; 210131961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ unsigned serr_ofs; 210231961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ 21038b260248d9e0e8b64bb72fd4dee03ad86984c344Jeff Garzik /* PIO related setup 210431961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ */ 210531961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ port->data_addr = shd_base + (sizeof(u32) * ATA_REG_DATA); 21068b260248d9e0e8b64bb72fd4dee03ad86984c344Jeff Garzik port->error_addr = 210731961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ port->feature_addr = shd_base + (sizeof(u32) * ATA_REG_ERR); 210831961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ port->nsect_addr = shd_base + (sizeof(u32) * ATA_REG_NSECT); 210931961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ port->lbal_addr = shd_base + (sizeof(u32) * ATA_REG_LBAL); 211031961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ port->lbam_addr = shd_base + (sizeof(u32) * ATA_REG_LBAM); 211131961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ port->lbah_addr = shd_base + (sizeof(u32) * ATA_REG_LBAH); 211231961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ port->device_addr = shd_base + (sizeof(u32) * ATA_REG_DEVICE); 21138b260248d9e0e8b64bb72fd4dee03ad86984c344Jeff Garzik port->status_addr = 211431961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ port->command_addr = shd_base + (sizeof(u32) * ATA_REG_STATUS); 211531961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ /* special case: control/altstatus doesn't have ATA_REG_ address */ 211631961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ port->altstatus_addr = port->ctl_addr = shd_base + SHD_CTL_AST_OFS; 211731961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ 211831961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ /* unused: */ 21198d9db2d2fbae9e05022825c32f86e00c8e342860Randy Dunlap port->cmd_addr = port->bmdma_addr = port->scr_addr = NULL; 212020f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ 212131961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ /* Clear any currently outstanding port interrupt conditions */ 212231961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ serr_ofs = mv_scr_offset(SCR_ERROR); 212331961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ writelfl(readl(port_mmio + serr_ofs), port_mmio + serr_ofs); 212431961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ writelfl(0, port_mmio + EDMA_ERR_IRQ_CAUSE_OFS); 212531961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ 212620f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ /* unmask all EDMA error interrupts */ 212731961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ writelfl(~0, port_mmio + EDMA_ERR_IRQ_MASK_OFS); 212820f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ 21298b260248d9e0e8b64bb72fd4dee03ad86984c344Jeff Garzik VPRINTK("EDMA cfg=0x%08x EDMA IRQ err cause/mask=0x%08x/0x%08x\n", 213031961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ readl(port_mmio + EDMA_CFG_OFS), 213131961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ readl(port_mmio + EDMA_ERR_IRQ_CAUSE_OFS), 213231961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ readl(port_mmio + EDMA_ERR_IRQ_MASK_OFS)); 213320f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ} 213420f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ 21354447d35156169cf136e829eb6b5cac2d6370f2d9Tejun Heostatic int mv_chip_id(struct ata_host *host, unsigned int board_idx) 2136bca1c4eb9411533d613123618c0d127fae532595Jeff Garzik{ 21374447d35156169cf136e829eb6b5cac2d6370f2d9Tejun Heo struct pci_dev *pdev = to_pci_dev(host->dev); 21384447d35156169cf136e829eb6b5cac2d6370f2d9Tejun Heo struct mv_host_priv *hpriv = host->private_data; 2139bca1c4eb9411533d613123618c0d127fae532595Jeff Garzik u32 hp_flags = hpriv->hp_flags; 2140bca1c4eb9411533d613123618c0d127fae532595Jeff Garzik 2141bca1c4eb9411533d613123618c0d127fae532595Jeff Garzik switch(board_idx) { 214247c2b677daeed9c79ecb7167c211ff36876ea611Jeff Garzik case chip_5080: 214347c2b677daeed9c79ecb7167c211ff36876ea611Jeff Garzik hpriv->ops = &mv5xxx_ops; 214447c2b677daeed9c79ecb7167c211ff36876ea611Jeff Garzik hp_flags |= MV_HP_50XX; 214547c2b677daeed9c79ecb7167c211ff36876ea611Jeff Garzik 214644c10138fd4bbc4b6d6bff0873c24902f2a9da65Auke Kok switch (pdev->revision) { 214747c2b677daeed9c79ecb7167c211ff36876ea611Jeff Garzik case 0x1: 214847c2b677daeed9c79ecb7167c211ff36876ea611Jeff Garzik hp_flags |= MV_HP_ERRATA_50XXB0; 214947c2b677daeed9c79ecb7167c211ff36876ea611Jeff Garzik break; 215047c2b677daeed9c79ecb7167c211ff36876ea611Jeff Garzik case 0x3: 215147c2b677daeed9c79ecb7167c211ff36876ea611Jeff Garzik hp_flags |= MV_HP_ERRATA_50XXB2; 215247c2b677daeed9c79ecb7167c211ff36876ea611Jeff Garzik break; 215347c2b677daeed9c79ecb7167c211ff36876ea611Jeff Garzik default: 215447c2b677daeed9c79ecb7167c211ff36876ea611Jeff Garzik dev_printk(KERN_WARNING, &pdev->dev, 215547c2b677daeed9c79ecb7167c211ff36876ea611Jeff Garzik "Applying 50XXB2 workarounds to unknown rev\n"); 215647c2b677daeed9c79ecb7167c211ff36876ea611Jeff Garzik hp_flags |= MV_HP_ERRATA_50XXB2; 215747c2b677daeed9c79ecb7167c211ff36876ea611Jeff Garzik break; 215847c2b677daeed9c79ecb7167c211ff36876ea611Jeff Garzik } 215947c2b677daeed9c79ecb7167c211ff36876ea611Jeff Garzik break; 216047c2b677daeed9c79ecb7167c211ff36876ea611Jeff Garzik 2161bca1c4eb9411533d613123618c0d127fae532595Jeff Garzik case chip_504x: 2162bca1c4eb9411533d613123618c0d127fae532595Jeff Garzik case chip_508x: 216347c2b677daeed9c79ecb7167c211ff36876ea611Jeff Garzik hpriv->ops = &mv5xxx_ops; 2164bca1c4eb9411533d613123618c0d127fae532595Jeff Garzik hp_flags |= MV_HP_50XX; 2165bca1c4eb9411533d613123618c0d127fae532595Jeff Garzik 216644c10138fd4bbc4b6d6bff0873c24902f2a9da65Auke Kok switch (pdev->revision) { 216747c2b677daeed9c79ecb7167c211ff36876ea611Jeff Garzik case 0x0: 216847c2b677daeed9c79ecb7167c211ff36876ea611Jeff Garzik hp_flags |= MV_HP_ERRATA_50XXB0; 216947c2b677daeed9c79ecb7167c211ff36876ea611Jeff Garzik break; 217047c2b677daeed9c79ecb7167c211ff36876ea611Jeff Garzik case 0x3: 217147c2b677daeed9c79ecb7167c211ff36876ea611Jeff Garzik hp_flags |= MV_HP_ERRATA_50XXB2; 217247c2b677daeed9c79ecb7167c211ff36876ea611Jeff Garzik break; 217347c2b677daeed9c79ecb7167c211ff36876ea611Jeff Garzik default: 217447c2b677daeed9c79ecb7167c211ff36876ea611Jeff Garzik dev_printk(KERN_WARNING, &pdev->dev, 217547c2b677daeed9c79ecb7167c211ff36876ea611Jeff Garzik "Applying B2 workarounds to unknown rev\n"); 217647c2b677daeed9c79ecb7167c211ff36876ea611Jeff Garzik hp_flags |= MV_HP_ERRATA_50XXB2; 217747c2b677daeed9c79ecb7167c211ff36876ea611Jeff Garzik break; 2178bca1c4eb9411533d613123618c0d127fae532595Jeff Garzik } 2179bca1c4eb9411533d613123618c0d127fae532595Jeff Garzik break; 2180bca1c4eb9411533d613123618c0d127fae532595Jeff Garzik 2181bca1c4eb9411533d613123618c0d127fae532595Jeff Garzik case chip_604x: 2182bca1c4eb9411533d613123618c0d127fae532595Jeff Garzik case chip_608x: 218347c2b677daeed9c79ecb7167c211ff36876ea611Jeff Garzik hpriv->ops = &mv6xxx_ops; 218447c2b677daeed9c79ecb7167c211ff36876ea611Jeff Garzik 218544c10138fd4bbc4b6d6bff0873c24902f2a9da65Auke Kok switch (pdev->revision) { 218647c2b677daeed9c79ecb7167c211ff36876ea611Jeff Garzik case 0x7: 218747c2b677daeed9c79ecb7167c211ff36876ea611Jeff Garzik hp_flags |= MV_HP_ERRATA_60X1B2; 218847c2b677daeed9c79ecb7167c211ff36876ea611Jeff Garzik break; 218947c2b677daeed9c79ecb7167c211ff36876ea611Jeff Garzik case 0x9: 219047c2b677daeed9c79ecb7167c211ff36876ea611Jeff Garzik hp_flags |= MV_HP_ERRATA_60X1C0; 2191bca1c4eb9411533d613123618c0d127fae532595Jeff Garzik break; 2192bca1c4eb9411533d613123618c0d127fae532595Jeff Garzik default: 2193bca1c4eb9411533d613123618c0d127fae532595Jeff Garzik dev_printk(KERN_WARNING, &pdev->dev, 219447c2b677daeed9c79ecb7167c211ff36876ea611Jeff Garzik "Applying B2 workarounds to unknown rev\n"); 219547c2b677daeed9c79ecb7167c211ff36876ea611Jeff Garzik hp_flags |= MV_HP_ERRATA_60X1B2; 2196bca1c4eb9411533d613123618c0d127fae532595Jeff Garzik break; 2197bca1c4eb9411533d613123618c0d127fae532595Jeff Garzik } 2198bca1c4eb9411533d613123618c0d127fae532595Jeff Garzik break; 2199bca1c4eb9411533d613123618c0d127fae532595Jeff Garzik 2200e4e7b89280d1d666e2c09e5ad36cf071796c4c7eJeff Garzik case chip_7042: 2201e4e7b89280d1d666e2c09e5ad36cf071796c4c7eJeff Garzik case chip_6042: 2202e4e7b89280d1d666e2c09e5ad36cf071796c4c7eJeff Garzik hpriv->ops = &mv6xxx_ops; 2203e4e7b89280d1d666e2c09e5ad36cf071796c4c7eJeff Garzik 2204e4e7b89280d1d666e2c09e5ad36cf071796c4c7eJeff Garzik hp_flags |= MV_HP_GEN_IIE; 2205e4e7b89280d1d666e2c09e5ad36cf071796c4c7eJeff Garzik 220644c10138fd4bbc4b6d6bff0873c24902f2a9da65Auke Kok switch (pdev->revision) { 2207e4e7b89280d1d666e2c09e5ad36cf071796c4c7eJeff Garzik case 0x0: 2208e4e7b89280d1d666e2c09e5ad36cf071796c4c7eJeff Garzik hp_flags |= MV_HP_ERRATA_XX42A0; 2209e4e7b89280d1d666e2c09e5ad36cf071796c4c7eJeff Garzik break; 2210e4e7b89280d1d666e2c09e5ad36cf071796c4c7eJeff Garzik case 0x1: 2211e4e7b89280d1d666e2c09e5ad36cf071796c4c7eJeff Garzik hp_flags |= MV_HP_ERRATA_60X1C0; 2212e4e7b89280d1d666e2c09e5ad36cf071796c4c7eJeff Garzik break; 2213e4e7b89280d1d666e2c09e5ad36cf071796c4c7eJeff Garzik default: 2214e4e7b89280d1d666e2c09e5ad36cf071796c4c7eJeff Garzik dev_printk(KERN_WARNING, &pdev->dev, 2215e4e7b89280d1d666e2c09e5ad36cf071796c4c7eJeff Garzik "Applying 60X1C0 workarounds to unknown rev\n"); 2216e4e7b89280d1d666e2c09e5ad36cf071796c4c7eJeff Garzik hp_flags |= MV_HP_ERRATA_60X1C0; 2217e4e7b89280d1d666e2c09e5ad36cf071796c4c7eJeff Garzik break; 2218e4e7b89280d1d666e2c09e5ad36cf071796c4c7eJeff Garzik } 2219e4e7b89280d1d666e2c09e5ad36cf071796c4c7eJeff Garzik break; 2220e4e7b89280d1d666e2c09e5ad36cf071796c4c7eJeff Garzik 2221bca1c4eb9411533d613123618c0d127fae532595Jeff Garzik default: 2222bca1c4eb9411533d613123618c0d127fae532595Jeff Garzik printk(KERN_ERR DRV_NAME ": BUG: invalid board index %u\n", board_idx); 2223bca1c4eb9411533d613123618c0d127fae532595Jeff Garzik return 1; 2224bca1c4eb9411533d613123618c0d127fae532595Jeff Garzik } 2225bca1c4eb9411533d613123618c0d127fae532595Jeff Garzik 2226bca1c4eb9411533d613123618c0d127fae532595Jeff Garzik hpriv->hp_flags = hp_flags; 2227bca1c4eb9411533d613123618c0d127fae532595Jeff Garzik 2228bca1c4eb9411533d613123618c0d127fae532595Jeff Garzik return 0; 2229bca1c4eb9411533d613123618c0d127fae532595Jeff Garzik} 2230bca1c4eb9411533d613123618c0d127fae532595Jeff Garzik 223105b308e1df6d9d673daedb517969241f41278b52Brett Russ/** 223247c2b677daeed9c79ecb7167c211ff36876ea611Jeff Garzik * mv_init_host - Perform some early initialization of the host. 22334447d35156169cf136e829eb6b5cac2d6370f2d9Tejun Heo * @host: ATA host to initialize 22344447d35156169cf136e829eb6b5cac2d6370f2d9Tejun Heo * @board_idx: controller index 223505b308e1df6d9d673daedb517969241f41278b52Brett Russ * 223605b308e1df6d9d673daedb517969241f41278b52Brett Russ * If possible, do an early global reset of the host. Then do 223705b308e1df6d9d673daedb517969241f41278b52Brett Russ * our port init and clear/unmask all/relevant host interrupts. 223805b308e1df6d9d673daedb517969241f41278b52Brett Russ * 223905b308e1df6d9d673daedb517969241f41278b52Brett Russ * LOCKING: 224005b308e1df6d9d673daedb517969241f41278b52Brett Russ * Inherited from caller. 224105b308e1df6d9d673daedb517969241f41278b52Brett Russ */ 22424447d35156169cf136e829eb6b5cac2d6370f2d9Tejun Heostatic int mv_init_host(struct ata_host *host, unsigned int board_idx) 224320f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ{ 224420f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ int rc = 0, n_hc, port, hc; 22454447d35156169cf136e829eb6b5cac2d6370f2d9Tejun Heo struct pci_dev *pdev = to_pci_dev(host->dev); 22464447d35156169cf136e829eb6b5cac2d6370f2d9Tejun Heo void __iomem *mmio = host->iomap[MV_PRIMARY_BAR]; 22474447d35156169cf136e829eb6b5cac2d6370f2d9Tejun Heo struct mv_host_priv *hpriv = host->private_data; 2248bca1c4eb9411533d613123618c0d127fae532595Jeff Garzik 224947c2b677daeed9c79ecb7167c211ff36876ea611Jeff Garzik /* global interrupt mask */ 225047c2b677daeed9c79ecb7167c211ff36876ea611Jeff Garzik writel(0, mmio + HC_MAIN_IRQ_MASK_OFS); 225147c2b677daeed9c79ecb7167c211ff36876ea611Jeff Garzik 22524447d35156169cf136e829eb6b5cac2d6370f2d9Tejun Heo rc = mv_chip_id(host, board_idx); 2253bca1c4eb9411533d613123618c0d127fae532595Jeff Garzik if (rc) 2254bca1c4eb9411533d613123618c0d127fae532595Jeff Garzik goto done; 2255bca1c4eb9411533d613123618c0d127fae532595Jeff Garzik 22564447d35156169cf136e829eb6b5cac2d6370f2d9Tejun Heo n_hc = mv_get_hc_count(host->ports[0]->flags); 2257bca1c4eb9411533d613123618c0d127fae532595Jeff Garzik 22584447d35156169cf136e829eb6b5cac2d6370f2d9Tejun Heo for (port = 0; port < host->n_ports; port++) 225947c2b677daeed9c79ecb7167c211ff36876ea611Jeff Garzik hpriv->ops->read_preamp(hpriv, port, mmio); 226020f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ 2261c9d39130123238ac18478a42e25cb7996eacfcc0Jeff Garzik rc = hpriv->ops->reset_hc(hpriv, mmio, n_hc); 226247c2b677daeed9c79ecb7167c211ff36876ea611Jeff Garzik if (rc) 226320f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ goto done; 226420f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ 2265522479fb98c6667f081e75f87e298e413c0b1db8Jeff Garzik hpriv->ops->reset_flash(hpriv, mmio); 2266522479fb98c6667f081e75f87e298e413c0b1db8Jeff Garzik hpriv->ops->reset_bus(pdev, mmio); 226747c2b677daeed9c79ecb7167c211ff36876ea611Jeff Garzik hpriv->ops->enable_leds(hpriv, mmio); 226820f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ 22694447d35156169cf136e829eb6b5cac2d6370f2d9Tejun Heo for (port = 0; port < host->n_ports; port++) { 22702a47ce06d534692f9bd2bf4e90a20fc9b1054c39Jeff Garzik if (IS_60XX(hpriv)) { 2271c9d39130123238ac18478a42e25cb7996eacfcc0Jeff Garzik void __iomem *port_mmio = mv_port_base(mmio, port); 2272c9d39130123238ac18478a42e25cb7996eacfcc0Jeff Garzik 22732a47ce06d534692f9bd2bf4e90a20fc9b1054c39Jeff Garzik u32 ifctl = readl(port_mmio + SATA_INTERFACE_CTL); 2274eb46d684600ac145501805a294c94675e82eab2eMark Lord ifctl |= (1 << 7); /* enable gen2i speed */ 2275eb46d684600ac145501805a294c94675e82eab2eMark Lord ifctl = (ifctl & 0xfff) | 0x9b1000; /* from chip spec */ 22762a47ce06d534692f9bd2bf4e90a20fc9b1054c39Jeff Garzik writelfl(ifctl, port_mmio + SATA_INTERFACE_CTL); 22772a47ce06d534692f9bd2bf4e90a20fc9b1054c39Jeff Garzik } 22782a47ce06d534692f9bd2bf4e90a20fc9b1054c39Jeff Garzik 2279c9d39130123238ac18478a42e25cb7996eacfcc0Jeff Garzik hpriv->ops->phy_errata(hpriv, mmio, port); 22802a47ce06d534692f9bd2bf4e90a20fc9b1054c39Jeff Garzik } 22812a47ce06d534692f9bd2bf4e90a20fc9b1054c39Jeff Garzik 22824447d35156169cf136e829eb6b5cac2d6370f2d9Tejun Heo for (port = 0; port < host->n_ports; port++) { 22832a47ce06d534692f9bd2bf4e90a20fc9b1054c39Jeff Garzik void __iomem *port_mmio = mv_port_base(mmio, port); 22844447d35156169cf136e829eb6b5cac2d6370f2d9Tejun Heo mv_port_init(&host->ports[port]->ioaddr, port_mmio); 228520f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ } 228620f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ 228720f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ for (hc = 0; hc < n_hc; hc++) { 228831961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ void __iomem *hc_mmio = mv_hc_base(mmio, hc); 228931961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ 229031961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ VPRINTK("HC%i: HC config=0x%08x HC IRQ cause " 229131961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ "(before clear)=0x%08x\n", hc, 229231961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ readl(hc_mmio + HC_CFG_OFS), 229331961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ readl(hc_mmio + HC_IRQ_CAUSE_OFS)); 229431961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ 229531961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ /* Clear any currently outstanding hc interrupt conditions */ 229631961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ writelfl(0, hc_mmio + HC_IRQ_CAUSE_OFS); 229720f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ } 229820f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ 229931961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ /* Clear any currently outstanding host interrupt conditions */ 230031961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ writelfl(0, mmio + PCI_IRQ_CAUSE_OFS); 230131961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ 230231961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ /* and unmask interrupt generation for host regs */ 230331961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ writelfl(PCI_UNMASK_ALL_IRQS, mmio + PCI_IRQ_MASK_OFS); 2304fb621e2fde735abab854586d52c96c5624bcb5b8Jeff Garzik 2305fb621e2fde735abab854586d52c96c5624bcb5b8Jeff Garzik if (IS_50XX(hpriv)) 2306fb621e2fde735abab854586d52c96c5624bcb5b8Jeff Garzik writelfl(~HC_MAIN_MASKED_IRQS_5, mmio + HC_MAIN_IRQ_MASK_OFS); 2307fb621e2fde735abab854586d52c96c5624bcb5b8Jeff Garzik else 2308fb621e2fde735abab854586d52c96c5624bcb5b8Jeff Garzik writelfl(~HC_MAIN_MASKED_IRQS, mmio + HC_MAIN_IRQ_MASK_OFS); 230920f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ 231020f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ VPRINTK("HC MAIN IRQ cause/mask=0x%08x/0x%08x " 23118b260248d9e0e8b64bb72fd4dee03ad86984c344Jeff Garzik "PCI int cause/mask=0x%08x/0x%08x\n", 231220f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ readl(mmio + HC_MAIN_IRQ_CAUSE_OFS), 231320f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ readl(mmio + HC_MAIN_IRQ_MASK_OFS), 231420f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ readl(mmio + PCI_IRQ_CAUSE_OFS), 231520f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ readl(mmio + PCI_IRQ_MASK_OFS)); 2316bca1c4eb9411533d613123618c0d127fae532595Jeff Garzik 231731961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russdone: 231820f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ return rc; 231920f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ} 232020f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ 232105b308e1df6d9d673daedb517969241f41278b52Brett Russ/** 232205b308e1df6d9d673daedb517969241f41278b52Brett Russ * mv_print_info - Dump key info to kernel log for perusal. 23234447d35156169cf136e829eb6b5cac2d6370f2d9Tejun Heo * @host: ATA host to print info about 232405b308e1df6d9d673daedb517969241f41278b52Brett Russ * 232505b308e1df6d9d673daedb517969241f41278b52Brett Russ * FIXME: complete this. 232605b308e1df6d9d673daedb517969241f41278b52Brett Russ * 232705b308e1df6d9d673daedb517969241f41278b52Brett Russ * LOCKING: 232805b308e1df6d9d673daedb517969241f41278b52Brett Russ * Inherited from caller. 232905b308e1df6d9d673daedb517969241f41278b52Brett Russ */ 23304447d35156169cf136e829eb6b5cac2d6370f2d9Tejun Heostatic void mv_print_info(struct ata_host *host) 233131961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ{ 23324447d35156169cf136e829eb6b5cac2d6370f2d9Tejun Heo struct pci_dev *pdev = to_pci_dev(host->dev); 23334447d35156169cf136e829eb6b5cac2d6370f2d9Tejun Heo struct mv_host_priv *hpriv = host->private_data; 233444c10138fd4bbc4b6d6bff0873c24902f2a9da65Auke Kok u8 scc; 2335c1e4fe711a410a139095e6b3e3ce3f07f466063cJeff Garzik const char *scc_s, *gen; 233631961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ 233731961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ /* Use this to determine the HW stepping of the chip so we know 233831961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ * what errata to workaround 233931961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ */ 234031961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ pci_read_config_byte(pdev, PCI_CLASS_DEVICE, &scc); 234131961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ if (scc == 0) 234231961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ scc_s = "SCSI"; 234331961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ else if (scc == 0x01) 234431961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ scc_s = "RAID"; 234531961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ else 2346c1e4fe711a410a139095e6b3e3ce3f07f466063cJeff Garzik scc_s = "?"; 2347c1e4fe711a410a139095e6b3e3ce3f07f466063cJeff Garzik 2348c1e4fe711a410a139095e6b3e3ce3f07f466063cJeff Garzik if (IS_GEN_I(hpriv)) 2349c1e4fe711a410a139095e6b3e3ce3f07f466063cJeff Garzik gen = "I"; 2350c1e4fe711a410a139095e6b3e3ce3f07f466063cJeff Garzik else if (IS_GEN_II(hpriv)) 2351c1e4fe711a410a139095e6b3e3ce3f07f466063cJeff Garzik gen = "II"; 2352c1e4fe711a410a139095e6b3e3ce3f07f466063cJeff Garzik else if (IS_GEN_IIE(hpriv)) 2353c1e4fe711a410a139095e6b3e3ce3f07f466063cJeff Garzik gen = "IIE"; 2354c1e4fe711a410a139095e6b3e3ce3f07f466063cJeff Garzik else 2355c1e4fe711a410a139095e6b3e3ce3f07f466063cJeff Garzik gen = "?"; 235631961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ 2357a9524a76f70f3343e4be27f95a7e92a8ba5f9009Jeff Garzik dev_printk(KERN_INFO, &pdev->dev, 2358c1e4fe711a410a139095e6b3e3ce3f07f466063cJeff Garzik "Gen-%s %u slots %u ports %s mode IRQ via %s\n", 2359c1e4fe711a410a139095e6b3e3ce3f07f466063cJeff Garzik gen, (unsigned)MV_MAX_Q_DEPTH, host->n_ports, 236031961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ scc_s, (MV_HP_FLAG_MSI & hpriv->hp_flags) ? "MSI" : "INTx"); 236131961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ} 236231961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ 236305b308e1df6d9d673daedb517969241f41278b52Brett Russ/** 236405b308e1df6d9d673daedb517969241f41278b52Brett Russ * mv_init_one - handle a positive probe of a Marvell host 236505b308e1df6d9d673daedb517969241f41278b52Brett Russ * @pdev: PCI device found 236605b308e1df6d9d673daedb517969241f41278b52Brett Russ * @ent: PCI device ID entry for the matched host 236705b308e1df6d9d673daedb517969241f41278b52Brett Russ * 236805b308e1df6d9d673daedb517969241f41278b52Brett Russ * LOCKING: 236905b308e1df6d9d673daedb517969241f41278b52Brett Russ * Inherited from caller. 237005b308e1df6d9d673daedb517969241f41278b52Brett Russ */ 237120f733e7d75a16bffc34842b7682c9247dd5f954Brett Russstatic int mv_init_one(struct pci_dev *pdev, const struct pci_device_id *ent) 237220f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ{ 237320f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ static int printed_version = 0; 237420f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ unsigned int board_idx = (unsigned int)ent->driver_data; 23754447d35156169cf136e829eb6b5cac2d6370f2d9Tejun Heo const struct ata_port_info *ppi[] = { &mv_port_info[board_idx], NULL }; 23764447d35156169cf136e829eb6b5cac2d6370f2d9Tejun Heo struct ata_host *host; 23774447d35156169cf136e829eb6b5cac2d6370f2d9Tejun Heo struct mv_host_priv *hpriv; 23784447d35156169cf136e829eb6b5cac2d6370f2d9Tejun Heo int n_ports, rc; 237920f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ 2380a9524a76f70f3343e4be27f95a7e92a8ba5f9009Jeff Garzik if (!printed_version++) 2381a9524a76f70f3343e4be27f95a7e92a8ba5f9009Jeff Garzik dev_printk(KERN_INFO, &pdev->dev, "version " DRV_VERSION "\n"); 238220f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ 23834447d35156169cf136e829eb6b5cac2d6370f2d9Tejun Heo /* allocate host */ 23844447d35156169cf136e829eb6b5cac2d6370f2d9Tejun Heo n_ports = mv_get_hc_count(ppi[0]->flags) * MV_PORTS_PER_HC; 23854447d35156169cf136e829eb6b5cac2d6370f2d9Tejun Heo 23864447d35156169cf136e829eb6b5cac2d6370f2d9Tejun Heo host = ata_host_alloc_pinfo(&pdev->dev, ppi, n_ports); 23874447d35156169cf136e829eb6b5cac2d6370f2d9Tejun Heo hpriv = devm_kzalloc(&pdev->dev, sizeof(*hpriv), GFP_KERNEL); 23884447d35156169cf136e829eb6b5cac2d6370f2d9Tejun Heo if (!host || !hpriv) 23894447d35156169cf136e829eb6b5cac2d6370f2d9Tejun Heo return -ENOMEM; 23904447d35156169cf136e829eb6b5cac2d6370f2d9Tejun Heo host->private_data = hpriv; 23914447d35156169cf136e829eb6b5cac2d6370f2d9Tejun Heo 23924447d35156169cf136e829eb6b5cac2d6370f2d9Tejun Heo /* acquire resources */ 239324dc5f33ea4b504cfbd23fa159a4cacba8e4d800Tejun Heo rc = pcim_enable_device(pdev); 239424dc5f33ea4b504cfbd23fa159a4cacba8e4d800Tejun Heo if (rc) 239520f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ return rc; 239620f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ 23970d5ff566779f894ca9937231a181eb31e4adff0eTejun Heo rc = pcim_iomap_regions(pdev, 1 << MV_PRIMARY_BAR, DRV_NAME); 23980d5ff566779f894ca9937231a181eb31e4adff0eTejun Heo if (rc == -EBUSY) 239924dc5f33ea4b504cfbd23fa159a4cacba8e4d800Tejun Heo pcim_pin_device(pdev); 24000d5ff566779f894ca9937231a181eb31e4adff0eTejun Heo if (rc) 240124dc5f33ea4b504cfbd23fa159a4cacba8e4d800Tejun Heo return rc; 24024447d35156169cf136e829eb6b5cac2d6370f2d9Tejun Heo host->iomap = pcim_iomap_table(pdev); 240320f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ 2404d88184fb2348a50f7c34f5d49a901c875b2e0114Jeff Garzik rc = pci_go_64(pdev); 2405d88184fb2348a50f7c34f5d49a901c875b2e0114Jeff Garzik if (rc) 2406d88184fb2348a50f7c34f5d49a901c875b2e0114Jeff Garzik return rc; 2407d88184fb2348a50f7c34f5d49a901c875b2e0114Jeff Garzik 240820f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ /* initialize adapter */ 24094447d35156169cf136e829eb6b5cac2d6370f2d9Tejun Heo rc = mv_init_host(host, board_idx); 241024dc5f33ea4b504cfbd23fa159a4cacba8e4d800Tejun Heo if (rc) 241124dc5f33ea4b504cfbd23fa159a4cacba8e4d800Tejun Heo return rc; 241220f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ 241331961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ /* Enable interrupts */ 24146a59dcf8678cbc4106a8a6e158d7408a87691358Tejun Heo if (msi && pci_enable_msi(pdev)) 241531961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ pci_intx(pdev, 1); 241620f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ 241731961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ mv_dump_pci_cfg(pdev, 0x68); 24184447d35156169cf136e829eb6b5cac2d6370f2d9Tejun Heo mv_print_info(host); 241920f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ 24204447d35156169cf136e829eb6b5cac2d6370f2d9Tejun Heo pci_set_master(pdev); 24214447d35156169cf136e829eb6b5cac2d6370f2d9Tejun Heo return ata_host_activate(host, pdev->irq, mv_interrupt, IRQF_SHARED, 24224447d35156169cf136e829eb6b5cac2d6370f2d9Tejun Heo &mv_sht); 242320f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ} 242420f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ 242520f733e7d75a16bffc34842b7682c9247dd5f954Brett Russstatic int __init mv_init(void) 242620f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ{ 2427b7887196e38da54ff893897b80875d632d1a1114Pavel Roskin return pci_register_driver(&mv_pci_driver); 242820f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ} 242920f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ 243020f733e7d75a16bffc34842b7682c9247dd5f954Brett Russstatic void __exit mv_exit(void) 243120f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ{ 243220f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ pci_unregister_driver(&mv_pci_driver); 243320f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ} 243420f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ 243520f733e7d75a16bffc34842b7682c9247dd5f954Brett RussMODULE_AUTHOR("Brett Russ"); 243620f733e7d75a16bffc34842b7682c9247dd5f954Brett RussMODULE_DESCRIPTION("SCSI low-level driver for Marvell SATA controllers"); 243720f733e7d75a16bffc34842b7682c9247dd5f954Brett RussMODULE_LICENSE("GPL"); 243820f733e7d75a16bffc34842b7682c9247dd5f954Brett RussMODULE_DEVICE_TABLE(pci, mv_pci_tbl); 243920f733e7d75a16bffc34842b7682c9247dd5f954Brett RussMODULE_VERSION(DRV_VERSION); 244020f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ 2441ddef9bb367b19383df627e388cb4c01c86ddba6cJeff Garzikmodule_param(msi, int, 0444); 2442ddef9bb367b19383df627e388cb4c01c86ddba6cJeff GarzikMODULE_PARM_DESC(msi, "Enable use of PCI MSI (0=off, 1=on)"); 2443ddef9bb367b19383df627e388cb4c01c86ddba6cJeff Garzik 244420f733e7d75a16bffc34842b7682c9247dd5f954Brett Russmodule_init(mv_init); 244520f733e7d75a16bffc34842b7682c9247dd5f954Brett Russmodule_exit(mv_exit); 2446