sata_mv.c revision f273827e2aadcf2f74a7bdc9ad715a1b20ea7dda
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 4) Add NCQ support (easy to intermediate, once new-EH support appears) 334a05e2091709dbb22b86a1b3343cd3fa3c0d7a6bJeff Garzik 344a05e2091709dbb22b86a1b3343cd3fa3c0d7a6bJeff Garzik 5) Investigate problems with PCI Message Signalled Interrupts (MSI). 354a05e2091709dbb22b86a1b3343cd3fa3c0d7a6bJeff Garzik 364a05e2091709dbb22b86a1b3343cd3fa3c0d7a6bJeff Garzik 6) Add port multiplier support (intermediate) 374a05e2091709dbb22b86a1b3343cd3fa3c0d7a6bJeff Garzik 384a05e2091709dbb22b86a1b3343cd3fa3c0d7a6bJeff Garzik 8) Develop a low-power-consumption strategy, and implement it. 394a05e2091709dbb22b86a1b3343cd3fa3c0d7a6bJeff Garzik 404a05e2091709dbb22b86a1b3343cd3fa3c0d7a6bJeff Garzik 9) [Experiment, low priority] See if ATAPI can be supported using 414a05e2091709dbb22b86a1b3343cd3fa3c0d7a6bJeff Garzik "unknown FIS" or "vendor-specific FIS" support, or something creative 424a05e2091709dbb22b86a1b3343cd3fa3c0d7a6bJeff Garzik like that. 434a05e2091709dbb22b86a1b3343cd3fa3c0d7a6bJeff Garzik 444a05e2091709dbb22b86a1b3343cd3fa3c0d7a6bJeff Garzik 10) [Experiment, low priority] Investigate interrupt coalescing. 454a05e2091709dbb22b86a1b3343cd3fa3c0d7a6bJeff Garzik Quite often, especially with PCI Message Signalled Interrupts (MSI), 464a05e2091709dbb22b86a1b3343cd3fa3c0d7a6bJeff Garzik the overhead reduced by interrupt mitigation is quite often not 474a05e2091709dbb22b86a1b3343cd3fa3c0d7a6bJeff Garzik worth the latency cost. 484a05e2091709dbb22b86a1b3343cd3fa3c0d7a6bJeff Garzik 494a05e2091709dbb22b86a1b3343cd3fa3c0d7a6bJeff Garzik 11) [Experiment, Marvell value added] Is it possible to use target 504a05e2091709dbb22b86a1b3343cd3fa3c0d7a6bJeff Garzik mode to cross-connect two Linux boxes with Marvell cards? If so, 514a05e2091709dbb22b86a1b3343cd3fa3c0d7a6bJeff Garzik creating LibATA target mode support would be very interesting. 524a05e2091709dbb22b86a1b3343cd3fa3c0d7a6bJeff Garzik 534a05e2091709dbb22b86a1b3343cd3fa3c0d7a6bJeff Garzik Target mode, for those without docs, is the ability to directly 544a05e2091709dbb22b86a1b3343cd3fa3c0d7a6bJeff Garzik connect two SATA controllers. 554a05e2091709dbb22b86a1b3343cd3fa3c0d7a6bJeff Garzik 564a05e2091709dbb22b86a1b3343cd3fa3c0d7a6bJeff Garzik 13) Verify that 7042 is fully supported. I only have a 6042. 574a05e2091709dbb22b86a1b3343cd3fa3c0d7a6bJeff Garzik 584a05e2091709dbb22b86a1b3343cd3fa3c0d7a6bJeff Garzik*/ 594a05e2091709dbb22b86a1b3343cd3fa3c0d7a6bJeff Garzik 604a05e2091709dbb22b86a1b3343cd3fa3c0d7a6bJeff Garzik 6120f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ#include <linux/kernel.h> 6220f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ#include <linux/module.h> 6320f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ#include <linux/pci.h> 6420f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ#include <linux/init.h> 6520f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ#include <linux/blkdev.h> 6620f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ#include <linux/delay.h> 6720f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ#include <linux/interrupt.h> 6820f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ#include <linux/dma-mapping.h> 69a9524a76f70f3343e4be27f95a7e92a8ba5f9009Jeff Garzik#include <linux/device.h> 7020f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ#include <scsi/scsi_host.h> 71193515d51ccb363165d6b09e9ba5c21089e34badJeff Garzik#include <scsi/scsi_cmnd.h> 726c08772e49622e90d39903e7ff0be1a0f463ac86Jeff Garzik#include <scsi/scsi_device.h> 7320f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ#include <linux/libata.h> 7420f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ 7520f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ#define DRV_NAME "sata_mv" 766c08772e49622e90d39903e7ff0be1a0f463ac86Jeff Garzik#define DRV_VERSION "1.01" 7720f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ 7820f733e7d75a16bffc34842b7682c9247dd5f954Brett Russenum { 7920f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ /* BAR's are enumerated in terms of pci_resource_start() terms */ 8020f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ MV_PRIMARY_BAR = 0, /* offset 0x10: memory space */ 8120f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ MV_IO_BAR = 2, /* offset 0x18: IO space */ 8220f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ MV_MISC_BAR = 3, /* offset 0x1c: FLASH, NVRAM, SRAM */ 8320f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ 8420f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ MV_MAJOR_REG_AREA_SZ = 0x10000, /* 64KB */ 8520f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ MV_MINOR_REG_AREA_SZ = 0x2000, /* 8KB */ 8620f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ 8720f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ MV_PCI_REG_BASE = 0, 8820f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ MV_IRQ_COAL_REG_BASE = 0x18000, /* 6xxx part only */ 89615ab95342f6245026d8974b9724f7ea57d9a184Mark Lord MV_IRQ_COAL_CAUSE = (MV_IRQ_COAL_REG_BASE + 0x08), 90615ab95342f6245026d8974b9724f7ea57d9a184Mark Lord MV_IRQ_COAL_CAUSE_LO = (MV_IRQ_COAL_REG_BASE + 0x88), 91615ab95342f6245026d8974b9724f7ea57d9a184Mark Lord MV_IRQ_COAL_CAUSE_HI = (MV_IRQ_COAL_REG_BASE + 0x8c), 92615ab95342f6245026d8974b9724f7ea57d9a184Mark Lord MV_IRQ_COAL_THRESHOLD = (MV_IRQ_COAL_REG_BASE + 0xcc), 93615ab95342f6245026d8974b9724f7ea57d9a184Mark Lord MV_IRQ_COAL_TIME_THRESHOLD = (MV_IRQ_COAL_REG_BASE + 0xd0), 94615ab95342f6245026d8974b9724f7ea57d9a184Mark Lord 9520f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ MV_SATAHC0_REG_BASE = 0x20000, 96522479fb98c6667f081e75f87e298e413c0b1db8Jeff Garzik MV_FLASH_CTL = 0x1046c, 97bca1c4eb9411533d613123618c0d127fae532595Jeff Garzik MV_GPIO_PORT_CTL = 0x104f0, 98bca1c4eb9411533d613123618c0d127fae532595Jeff Garzik MV_RESET_CFG = 0x180d8, 9920f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ 10020f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ MV_PCI_REG_SZ = MV_MAJOR_REG_AREA_SZ, 10120f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ MV_SATAHC_REG_SZ = MV_MAJOR_REG_AREA_SZ, 10220f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ MV_SATAHC_ARBTR_REG_SZ = MV_MINOR_REG_AREA_SZ, /* arbiter */ 10320f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ MV_PORT_REG_SZ = MV_MINOR_REG_AREA_SZ, 10420f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ 10531961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ MV_MAX_Q_DEPTH = 32, 10631961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ MV_MAX_Q_DEPTH_MASK = MV_MAX_Q_DEPTH - 1, 10731961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ 10831961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ /* CRQB needs alignment on a 1KB boundary. Size == 1KB 10931961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ * CRPB needs alignment on a 256B boundary. Size == 256B 11031961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ * SG count of 176 leads to MV_PORT_PRIV_DMA_SZ == 4KB 11131961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ * ePRD (SG) entries need alignment on a 16B boundary. Size == 16B 11231961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ */ 11331961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ MV_CRQB_Q_SZ = (32 * MV_MAX_Q_DEPTH), 11431961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ MV_CRPB_Q_SZ = (8 * MV_MAX_Q_DEPTH), 11531961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ MV_MAX_SG_CT = 176, 11631961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ MV_SG_TBL_SZ = (16 * MV_MAX_SG_CT), 11731961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ MV_PORT_PRIV_DMA_SZ = (MV_CRQB_Q_SZ + MV_CRPB_Q_SZ + MV_SG_TBL_SZ), 11831961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ 11920f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ MV_PORTS_PER_HC = 4, 12020f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ /* == (port / MV_PORTS_PER_HC) to determine HC from 0-7 port */ 12120f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ MV_PORT_HC_SHIFT = 2, 12231961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ /* == (port % MV_PORTS_PER_HC) to determine hard port from 0-7 port */ 12320f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ MV_PORT_MASK = 3, 12420f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ 12520f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ /* Host Flags */ 12620f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ MV_FLAG_DUAL_HC = (1 << 30), /* two SATA Host Controllers */ 12720f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ MV_FLAG_IRQ_COALESCE = (1 << 29), /* IRQ coalescing capability */ 128c5d3e45a2200a0905dc45b72714726b7aac3aaf1Jeff Garzik MV_COMMON_FLAGS = ATA_FLAG_SATA | ATA_FLAG_NO_LEGACY | 129bdd4dddee325a7dce3e84cf48201a06aa8508aa4Jeff Garzik ATA_FLAG_MMIO | ATA_FLAG_NO_ATAPI | 130bdd4dddee325a7dce3e84cf48201a06aa8508aa4Jeff Garzik ATA_FLAG_PIO_POLLING, 13147c2b677daeed9c79ecb7167c211ff36876ea611Jeff Garzik MV_6XXX_FLAGS = MV_FLAG_IRQ_COALESCE, 13220f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ 13331961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ CRQB_FLAG_READ = (1 << 0), 13431961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ CRQB_TAG_SHIFT = 1, 135c5d3e45a2200a0905dc45b72714726b7aac3aaf1Jeff Garzik CRQB_IOID_SHIFT = 6, /* CRQB Gen-II/IIE IO Id shift */ 136c5d3e45a2200a0905dc45b72714726b7aac3aaf1Jeff Garzik CRQB_HOSTQ_SHIFT = 17, /* CRQB Gen-II/IIE HostQueTag shift */ 13731961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ CRQB_CMD_ADDR_SHIFT = 8, 13831961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ CRQB_CMD_CS = (0x2 << 11), 13931961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ CRQB_CMD_LAST = (1 << 15), 14031961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ 14131961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ CRPB_FLAG_STATUS_SHIFT = 8, 142c5d3e45a2200a0905dc45b72714726b7aac3aaf1Jeff Garzik CRPB_IOID_SHIFT_6 = 5, /* CRPB Gen-II IO Id shift */ 143c5d3e45a2200a0905dc45b72714726b7aac3aaf1Jeff Garzik CRPB_IOID_SHIFT_7 = 7, /* CRPB Gen-IIE IO Id shift */ 14431961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ 14531961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ EPRD_FLAG_END_OF_TBL = (1 << 31), 14631961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ 14720f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ /* PCI interface registers */ 14820f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ 14931961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ PCI_COMMAND_OFS = 0xc00, 15031961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ 15120f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ PCI_MAIN_CMD_STS_OFS = 0xd30, 15220f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ STOP_PCI_MASTER = (1 << 2), 15320f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ PCI_MASTER_EMPTY = (1 << 3), 15420f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ GLOB_SFT_RST = (1 << 4), 15520f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ 156522479fb98c6667f081e75f87e298e413c0b1db8Jeff Garzik MV_PCI_MODE = 0xd00, 157522479fb98c6667f081e75f87e298e413c0b1db8Jeff Garzik MV_PCI_EXP_ROM_BAR_CTL = 0xd2c, 158522479fb98c6667f081e75f87e298e413c0b1db8Jeff Garzik MV_PCI_DISC_TIMER = 0xd04, 159522479fb98c6667f081e75f87e298e413c0b1db8Jeff Garzik MV_PCI_MSI_TRIGGER = 0xc38, 160522479fb98c6667f081e75f87e298e413c0b1db8Jeff Garzik MV_PCI_SERR_MASK = 0xc28, 161522479fb98c6667f081e75f87e298e413c0b1db8Jeff Garzik MV_PCI_XBAR_TMOUT = 0x1d04, 162522479fb98c6667f081e75f87e298e413c0b1db8Jeff Garzik MV_PCI_ERR_LOW_ADDRESS = 0x1d40, 163522479fb98c6667f081e75f87e298e413c0b1db8Jeff Garzik MV_PCI_ERR_HIGH_ADDRESS = 0x1d44, 164522479fb98c6667f081e75f87e298e413c0b1db8Jeff Garzik MV_PCI_ERR_ATTRIBUTE = 0x1d48, 165522479fb98c6667f081e75f87e298e413c0b1db8Jeff Garzik MV_PCI_ERR_COMMAND = 0x1d50, 166522479fb98c6667f081e75f87e298e413c0b1db8Jeff Garzik 16702a121da5a53d415b6596bc19cc6999d295d32a4Mark Lord PCI_IRQ_CAUSE_OFS = 0x1d58, 16802a121da5a53d415b6596bc19cc6999d295d32a4Mark Lord PCI_IRQ_MASK_OFS = 0x1d5c, 16920f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ PCI_UNMASK_ALL_IRQS = 0x7fffff, /* bits 22-0 */ 17020f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ 17102a121da5a53d415b6596bc19cc6999d295d32a4Mark Lord PCIE_IRQ_CAUSE_OFS = 0x1900, 17202a121da5a53d415b6596bc19cc6999d295d32a4Mark Lord PCIE_IRQ_MASK_OFS = 0x1910, 173646a4da514f2555298481cb00dc5b3eb02b21b72Mark Lord PCIE_UNMASK_ALL_IRQS = 0x40a, /* assorted bits */ 17402a121da5a53d415b6596bc19cc6999d295d32a4Mark Lord 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, 2130c58912e192fc3a4835d772aafa40b72552b819fMark Lord SATA_FIS_IRQ_CAUSE_OFS = 0x364, 21447c2b677daeed9c79ecb7167c211ff36876ea611Jeff Garzik PHY_MODE3 = 0x310, 215bca1c4eb9411533d613123618c0d127fae532595Jeff Garzik PHY_MODE4 = 0x314, 216bca1c4eb9411533d613123618c0d127fae532595Jeff Garzik PHY_MODE2 = 0x330, 217c9d39130123238ac18478a42e25cb7996eacfcc0Jeff Garzik MV5_PHY_MODE = 0x74, 218c9d39130123238ac18478a42e25cb7996eacfcc0Jeff Garzik MV5_LT_MODE = 0x30, 219c9d39130123238ac18478a42e25cb7996eacfcc0Jeff Garzik MV5_PHY_CTL = 0x0C, 220bca1c4eb9411533d613123618c0d127fae532595Jeff Garzik SATA_INTERFACE_CTL = 0x050, 221bca1c4eb9411533d613123618c0d127fae532595Jeff Garzik 222bca1c4eb9411533d613123618c0d127fae532595Jeff Garzik MV_M2_PREAMP_MASK = 0x7e0, 22320f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ 22420f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ /* Port registers */ 22520f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ EDMA_CFG_OFS = 0, 2260c58912e192fc3a4835d772aafa40b72552b819fMark Lord EDMA_CFG_Q_DEPTH = 0x1f, /* max device queue depth */ 2270c58912e192fc3a4835d772aafa40b72552b819fMark Lord EDMA_CFG_NCQ = (1 << 5), /* for R/W FPDMA queued */ 2280c58912e192fc3a4835d772aafa40b72552b819fMark Lord EDMA_CFG_NCQ_GO_ON_ERR = (1 << 14), /* continue on error */ 2290c58912e192fc3a4835d772aafa40b72552b819fMark Lord EDMA_CFG_RD_BRST_EXT = (1 << 11), /* read burst 512B */ 2300c58912e192fc3a4835d772aafa40b72552b819fMark Lord EDMA_CFG_WR_BUFF_LEN = (1 << 13), /* write buffer 512B */ 23120f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ 23220f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ EDMA_ERR_IRQ_CAUSE_OFS = 0x8, 23320f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ EDMA_ERR_IRQ_MASK_OFS = 0xc, 2346c1153e00af8de755ec278d873a97c9ce2a72d10Jeff Garzik EDMA_ERR_D_PAR = (1 << 0), /* UDMA data parity err */ 2356c1153e00af8de755ec278d873a97c9ce2a72d10Jeff Garzik EDMA_ERR_PRD_PAR = (1 << 1), /* UDMA PRD parity err */ 2366c1153e00af8de755ec278d873a97c9ce2a72d10Jeff Garzik EDMA_ERR_DEV = (1 << 2), /* device error */ 2376c1153e00af8de755ec278d873a97c9ce2a72d10Jeff Garzik EDMA_ERR_DEV_DCON = (1 << 3), /* device disconnect */ 2386c1153e00af8de755ec278d873a97c9ce2a72d10Jeff Garzik EDMA_ERR_DEV_CON = (1 << 4), /* device connected */ 2396c1153e00af8de755ec278d873a97c9ce2a72d10Jeff Garzik EDMA_ERR_SERR = (1 << 5), /* SError bits [WBDST] raised */ 240c5d3e45a2200a0905dc45b72714726b7aac3aaf1Jeff Garzik EDMA_ERR_SELF_DIS = (1 << 7), /* Gen II/IIE self-disable */ 241c5d3e45a2200a0905dc45b72714726b7aac3aaf1Jeff Garzik EDMA_ERR_SELF_DIS_5 = (1 << 8), /* Gen I self-disable */ 2426c1153e00af8de755ec278d873a97c9ce2a72d10Jeff Garzik EDMA_ERR_BIST_ASYNC = (1 << 8), /* BIST FIS or Async Notify */ 243c5d3e45a2200a0905dc45b72714726b7aac3aaf1Jeff Garzik EDMA_ERR_TRANS_IRQ_7 = (1 << 8), /* Gen IIE transprt layer irq */ 2446c1153e00af8de755ec278d873a97c9ce2a72d10Jeff Garzik EDMA_ERR_CRQB_PAR = (1 << 9), /* CRQB parity error */ 2456c1153e00af8de755ec278d873a97c9ce2a72d10Jeff Garzik EDMA_ERR_CRPB_PAR = (1 << 10), /* CRPB parity error */ 2466c1153e00af8de755ec278d873a97c9ce2a72d10Jeff Garzik EDMA_ERR_INTRL_PAR = (1 << 11), /* internal parity error */ 2476c1153e00af8de755ec278d873a97c9ce2a72d10Jeff Garzik EDMA_ERR_IORDY = (1 << 12), /* IORdy timeout */ 248646a4da514f2555298481cb00dc5b3eb02b21b72Mark Lord 2496c1153e00af8de755ec278d873a97c9ce2a72d10Jeff Garzik EDMA_ERR_LNK_CTRL_RX = (0xf << 13), /* link ctrl rx error */ 250646a4da514f2555298481cb00dc5b3eb02b21b72Mark Lord EDMA_ERR_LNK_CTRL_RX_0 = (1 << 13), /* transient: CRC err */ 251646a4da514f2555298481cb00dc5b3eb02b21b72Mark Lord EDMA_ERR_LNK_CTRL_RX_1 = (1 << 14), /* transient: FIFO err */ 252646a4da514f2555298481cb00dc5b3eb02b21b72Mark Lord EDMA_ERR_LNK_CTRL_RX_2 = (1 << 15), /* fatal: caught SYNC */ 253646a4da514f2555298481cb00dc5b3eb02b21b72Mark Lord EDMA_ERR_LNK_CTRL_RX_3 = (1 << 16), /* transient: FIS rx err */ 254646a4da514f2555298481cb00dc5b3eb02b21b72Mark Lord 2556c1153e00af8de755ec278d873a97c9ce2a72d10Jeff Garzik EDMA_ERR_LNK_DATA_RX = (0xf << 17), /* link data rx error */ 256646a4da514f2555298481cb00dc5b3eb02b21b72Mark Lord 2576c1153e00af8de755ec278d873a97c9ce2a72d10Jeff Garzik EDMA_ERR_LNK_CTRL_TX = (0x1f << 21), /* link ctrl tx error */ 258646a4da514f2555298481cb00dc5b3eb02b21b72Mark Lord EDMA_ERR_LNK_CTRL_TX_0 = (1 << 21), /* transient: CRC err */ 259646a4da514f2555298481cb00dc5b3eb02b21b72Mark Lord EDMA_ERR_LNK_CTRL_TX_1 = (1 << 22), /* transient: FIFO err */ 260646a4da514f2555298481cb00dc5b3eb02b21b72Mark Lord EDMA_ERR_LNK_CTRL_TX_2 = (1 << 23), /* transient: caught SYNC */ 261646a4da514f2555298481cb00dc5b3eb02b21b72Mark Lord EDMA_ERR_LNK_CTRL_TX_3 = (1 << 24), /* transient: caught DMAT */ 262646a4da514f2555298481cb00dc5b3eb02b21b72Mark Lord EDMA_ERR_LNK_CTRL_TX_4 = (1 << 25), /* transient: FIS collision */ 263646a4da514f2555298481cb00dc5b3eb02b21b72Mark Lord 2646c1153e00af8de755ec278d873a97c9ce2a72d10Jeff Garzik EDMA_ERR_LNK_DATA_TX = (0x1f << 26), /* link data tx error */ 265646a4da514f2555298481cb00dc5b3eb02b21b72Mark Lord 2666c1153e00af8de755ec278d873a97c9ce2a72d10Jeff Garzik EDMA_ERR_TRANS_PROTO = (1 << 31), /* transport protocol error */ 267c5d3e45a2200a0905dc45b72714726b7aac3aaf1Jeff Garzik EDMA_ERR_OVERRUN_5 = (1 << 5), 268c5d3e45a2200a0905dc45b72714726b7aac3aaf1Jeff Garzik EDMA_ERR_UNDERRUN_5 = (1 << 6), 269646a4da514f2555298481cb00dc5b3eb02b21b72Mark Lord 270646a4da514f2555298481cb00dc5b3eb02b21b72Mark Lord EDMA_ERR_IRQ_TRANSIENT = EDMA_ERR_LNK_CTRL_RX_0 | 271646a4da514f2555298481cb00dc5b3eb02b21b72Mark Lord EDMA_ERR_LNK_CTRL_RX_1 | 272646a4da514f2555298481cb00dc5b3eb02b21b72Mark Lord EDMA_ERR_LNK_CTRL_RX_3 | 273646a4da514f2555298481cb00dc5b3eb02b21b72Mark Lord EDMA_ERR_LNK_CTRL_TX, 274646a4da514f2555298481cb00dc5b3eb02b21b72Mark Lord 275bdd4dddee325a7dce3e84cf48201a06aa8508aa4Jeff Garzik EDMA_EH_FREEZE = EDMA_ERR_D_PAR | 276bdd4dddee325a7dce3e84cf48201a06aa8508aa4Jeff Garzik EDMA_ERR_PRD_PAR | 277bdd4dddee325a7dce3e84cf48201a06aa8508aa4Jeff Garzik EDMA_ERR_DEV_DCON | 278bdd4dddee325a7dce3e84cf48201a06aa8508aa4Jeff Garzik EDMA_ERR_DEV_CON | 279bdd4dddee325a7dce3e84cf48201a06aa8508aa4Jeff Garzik EDMA_ERR_SERR | 280bdd4dddee325a7dce3e84cf48201a06aa8508aa4Jeff Garzik EDMA_ERR_SELF_DIS | 2816c1153e00af8de755ec278d873a97c9ce2a72d10Jeff Garzik EDMA_ERR_CRQB_PAR | 282bdd4dddee325a7dce3e84cf48201a06aa8508aa4Jeff Garzik EDMA_ERR_CRPB_PAR | 283bdd4dddee325a7dce3e84cf48201a06aa8508aa4Jeff Garzik EDMA_ERR_INTRL_PAR | 284bdd4dddee325a7dce3e84cf48201a06aa8508aa4Jeff Garzik EDMA_ERR_IORDY | 285bdd4dddee325a7dce3e84cf48201a06aa8508aa4Jeff Garzik EDMA_ERR_LNK_CTRL_RX_2 | 286bdd4dddee325a7dce3e84cf48201a06aa8508aa4Jeff Garzik EDMA_ERR_LNK_DATA_RX | 287bdd4dddee325a7dce3e84cf48201a06aa8508aa4Jeff Garzik EDMA_ERR_LNK_DATA_TX | 288bdd4dddee325a7dce3e84cf48201a06aa8508aa4Jeff Garzik EDMA_ERR_TRANS_PROTO, 289bdd4dddee325a7dce3e84cf48201a06aa8508aa4Jeff Garzik EDMA_EH_FREEZE_5 = EDMA_ERR_D_PAR | 290bdd4dddee325a7dce3e84cf48201a06aa8508aa4Jeff Garzik EDMA_ERR_PRD_PAR | 291bdd4dddee325a7dce3e84cf48201a06aa8508aa4Jeff Garzik EDMA_ERR_DEV_DCON | 292bdd4dddee325a7dce3e84cf48201a06aa8508aa4Jeff Garzik EDMA_ERR_DEV_CON | 293bdd4dddee325a7dce3e84cf48201a06aa8508aa4Jeff Garzik EDMA_ERR_OVERRUN_5 | 294bdd4dddee325a7dce3e84cf48201a06aa8508aa4Jeff Garzik EDMA_ERR_UNDERRUN_5 | 295bdd4dddee325a7dce3e84cf48201a06aa8508aa4Jeff Garzik EDMA_ERR_SELF_DIS_5 | 2966c1153e00af8de755ec278d873a97c9ce2a72d10Jeff Garzik EDMA_ERR_CRQB_PAR | 297bdd4dddee325a7dce3e84cf48201a06aa8508aa4Jeff Garzik EDMA_ERR_CRPB_PAR | 298bdd4dddee325a7dce3e84cf48201a06aa8508aa4Jeff Garzik EDMA_ERR_INTRL_PAR | 299bdd4dddee325a7dce3e84cf48201a06aa8508aa4Jeff Garzik EDMA_ERR_IORDY, 30020f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ 30131961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ EDMA_REQ_Q_BASE_HI_OFS = 0x10, 30231961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ EDMA_REQ_Q_IN_PTR_OFS = 0x14, /* also contains BASE_LO */ 30331961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ 30431961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ EDMA_REQ_Q_OUT_PTR_OFS = 0x18, 30531961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ EDMA_REQ_Q_PTR_SHIFT = 5, 30631961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ 30731961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ EDMA_RSP_Q_BASE_HI_OFS = 0x1c, 30831961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ EDMA_RSP_Q_IN_PTR_OFS = 0x20, 30931961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ EDMA_RSP_Q_OUT_PTR_OFS = 0x24, /* also contains BASE_LO */ 31031961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ EDMA_RSP_Q_PTR_SHIFT = 3, 31131961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ 3120ea9e179f436f153fc19fdaef7abbc1e0da20762Jeff Garzik EDMA_CMD_OFS = 0x28, /* EDMA command register */ 3130ea9e179f436f153fc19fdaef7abbc1e0da20762Jeff Garzik EDMA_EN = (1 << 0), /* enable EDMA */ 3140ea9e179f436f153fc19fdaef7abbc1e0da20762Jeff Garzik EDMA_DS = (1 << 1), /* disable EDMA; self-negated */ 3150ea9e179f436f153fc19fdaef7abbc1e0da20762Jeff Garzik ATA_RST = (1 << 2), /* reset trans/link/phy */ 31620f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ 317c9d39130123238ac18478a42e25cb7996eacfcc0Jeff Garzik EDMA_IORDY_TMOUT = 0x34, 318bca1c4eb9411533d613123618c0d127fae532595Jeff Garzik EDMA_ARB_CFG = 0x38, 319bca1c4eb9411533d613123618c0d127fae532595Jeff Garzik 32031961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ /* Host private flags (hp_flags) */ 32131961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ MV_HP_FLAG_MSI = (1 << 0), 32247c2b677daeed9c79ecb7167c211ff36876ea611Jeff Garzik MV_HP_ERRATA_50XXB0 = (1 << 1), 32347c2b677daeed9c79ecb7167c211ff36876ea611Jeff Garzik MV_HP_ERRATA_50XXB2 = (1 << 2), 32447c2b677daeed9c79ecb7167c211ff36876ea611Jeff Garzik MV_HP_ERRATA_60X1B2 = (1 << 3), 32547c2b677daeed9c79ecb7167c211ff36876ea611Jeff Garzik MV_HP_ERRATA_60X1C0 = (1 << 4), 326e4e7b89280d1d666e2c09e5ad36cf071796c4c7eJeff Garzik MV_HP_ERRATA_XX42A0 = (1 << 5), 3270ea9e179f436f153fc19fdaef7abbc1e0da20762Jeff Garzik MV_HP_GEN_I = (1 << 6), /* Generation I: 50xx */ 3280ea9e179f436f153fc19fdaef7abbc1e0da20762Jeff Garzik MV_HP_GEN_II = (1 << 7), /* Generation II: 60xx */ 3290ea9e179f436f153fc19fdaef7abbc1e0da20762Jeff Garzik MV_HP_GEN_IIE = (1 << 8), /* Generation IIE: 6042/7042 */ 33002a121da5a53d415b6596bc19cc6999d295d32a4Mark Lord MV_HP_PCIE = (1 << 9), /* PCIe bus/regs: 7042 */ 33120f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ 33231961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ /* Port private flags (pp_flags) */ 3330ea9e179f436f153fc19fdaef7abbc1e0da20762Jeff Garzik MV_PP_FLAG_EDMA_EN = (1 << 0), /* is EDMA engine enabled? */ 334721091685f853ba4e6c49f26f989db0b1a811250Mark Lord MV_PP_FLAG_NCQ_EN = (1 << 1), /* is EDMA set up for NCQ? */ 3350ea9e179f436f153fc19fdaef7abbc1e0da20762Jeff Garzik MV_PP_FLAG_HAD_A_RESET = (1 << 2), /* 1st hard reset complete? */ 33620f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ}; 33720f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ 338ee9ccdf70163ca6408f6965e0fbc65baeac7312cJeff Garzik#define IS_GEN_I(hpriv) ((hpriv)->hp_flags & MV_HP_GEN_I) 339ee9ccdf70163ca6408f6965e0fbc65baeac7312cJeff Garzik#define IS_GEN_II(hpriv) ((hpriv)->hp_flags & MV_HP_GEN_II) 340e4e7b89280d1d666e2c09e5ad36cf071796c4c7eJeff Garzik#define IS_GEN_IIE(hpriv) ((hpriv)->hp_flags & MV_HP_GEN_IIE) 341bca1c4eb9411533d613123618c0d127fae532595Jeff Garzik 342095fec887eaa1c38d17c0c929a6733c744a9fa1fJeff Garzikenum { 343baf14aa14efcfdb5a74d5cf804691086c6bec743Jeff Garzik /* DMA boundary 0xffff is required by the s/g splitting 344baf14aa14efcfdb5a74d5cf804691086c6bec743Jeff Garzik * we need on /length/ in mv_fill-sg(). 345baf14aa14efcfdb5a74d5cf804691086c6bec743Jeff Garzik */ 346baf14aa14efcfdb5a74d5cf804691086c6bec743Jeff Garzik MV_DMA_BOUNDARY = 0xffffU, 347095fec887eaa1c38d17c0c929a6733c744a9fa1fJeff Garzik 3480ea9e179f436f153fc19fdaef7abbc1e0da20762Jeff Garzik /* mask of register bits containing lower 32 bits 3490ea9e179f436f153fc19fdaef7abbc1e0da20762Jeff Garzik * of EDMA request queue DMA address 3500ea9e179f436f153fc19fdaef7abbc1e0da20762Jeff Garzik */ 351095fec887eaa1c38d17c0c929a6733c744a9fa1fJeff Garzik EDMA_REQ_Q_BASE_LO_MASK = 0xfffffc00U, 352095fec887eaa1c38d17c0c929a6733c744a9fa1fJeff Garzik 3530ea9e179f436f153fc19fdaef7abbc1e0da20762Jeff Garzik /* ditto, for response queue */ 354095fec887eaa1c38d17c0c929a6733c744a9fa1fJeff Garzik EDMA_RSP_Q_BASE_LO_MASK = 0xffffff00U, 355095fec887eaa1c38d17c0c929a6733c744a9fa1fJeff Garzik}; 356095fec887eaa1c38d17c0c929a6733c744a9fa1fJeff Garzik 357522479fb98c6667f081e75f87e298e413c0b1db8Jeff Garzikenum chip_type { 358522479fb98c6667f081e75f87e298e413c0b1db8Jeff Garzik chip_504x, 359522479fb98c6667f081e75f87e298e413c0b1db8Jeff Garzik chip_508x, 360522479fb98c6667f081e75f87e298e413c0b1db8Jeff Garzik chip_5080, 361522479fb98c6667f081e75f87e298e413c0b1db8Jeff Garzik chip_604x, 362522479fb98c6667f081e75f87e298e413c0b1db8Jeff Garzik chip_608x, 363e4e7b89280d1d666e2c09e5ad36cf071796c4c7eJeff Garzik chip_6042, 364e4e7b89280d1d666e2c09e5ad36cf071796c4c7eJeff Garzik chip_7042, 365522479fb98c6667f081e75f87e298e413c0b1db8Jeff Garzik}; 366522479fb98c6667f081e75f87e298e413c0b1db8Jeff Garzik 36731961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ/* Command ReQuest Block: 32B */ 36831961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russstruct mv_crqb { 369e14698745dd0de1ddbf5cd0cca4313a90f8c1cc1Mark Lord __le32 sg_addr; 370e14698745dd0de1ddbf5cd0cca4313a90f8c1cc1Mark Lord __le32 sg_addr_hi; 371e14698745dd0de1ddbf5cd0cca4313a90f8c1cc1Mark Lord __le16 ctrl_flags; 372e14698745dd0de1ddbf5cd0cca4313a90f8c1cc1Mark Lord __le16 ata_cmd[11]; 37331961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ}; 37420f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ 375e4e7b89280d1d666e2c09e5ad36cf071796c4c7eJeff Garzikstruct mv_crqb_iie { 376e14698745dd0de1ddbf5cd0cca4313a90f8c1cc1Mark Lord __le32 addr; 377e14698745dd0de1ddbf5cd0cca4313a90f8c1cc1Mark Lord __le32 addr_hi; 378e14698745dd0de1ddbf5cd0cca4313a90f8c1cc1Mark Lord __le32 flags; 379e14698745dd0de1ddbf5cd0cca4313a90f8c1cc1Mark Lord __le32 len; 380e14698745dd0de1ddbf5cd0cca4313a90f8c1cc1Mark Lord __le32 ata_cmd[4]; 381e4e7b89280d1d666e2c09e5ad36cf071796c4c7eJeff Garzik}; 382e4e7b89280d1d666e2c09e5ad36cf071796c4c7eJeff Garzik 38331961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ/* Command ResPonse Block: 8B */ 38431961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russstruct mv_crpb { 385e14698745dd0de1ddbf5cd0cca4313a90f8c1cc1Mark Lord __le16 id; 386e14698745dd0de1ddbf5cd0cca4313a90f8c1cc1Mark Lord __le16 flags; 387e14698745dd0de1ddbf5cd0cca4313a90f8c1cc1Mark Lord __le32 tmstmp; 38820f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ}; 38920f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ 39031961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ/* EDMA Physical Region Descriptor (ePRD); A.K.A. SG */ 39131961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russstruct mv_sg { 392e14698745dd0de1ddbf5cd0cca4313a90f8c1cc1Mark Lord __le32 addr; 393e14698745dd0de1ddbf5cd0cca4313a90f8c1cc1Mark Lord __le32 flags_size; 394e14698745dd0de1ddbf5cd0cca4313a90f8c1cc1Mark Lord __le32 addr_hi; 395e14698745dd0de1ddbf5cd0cca4313a90f8c1cc1Mark Lord __le32 reserved; 39631961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ}; 39720f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ 39831961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russstruct mv_port_priv { 39931961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ struct mv_crqb *crqb; 40031961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ dma_addr_t crqb_dma; 40131961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ struct mv_crpb *crpb; 40231961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ dma_addr_t crpb_dma; 40331961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ struct mv_sg *sg_tbl; 40431961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ dma_addr_t sg_tbl_dma; 405bdd4dddee325a7dce3e84cf48201a06aa8508aa4Jeff Garzik 406bdd4dddee325a7dce3e84cf48201a06aa8508aa4Jeff Garzik unsigned int req_idx; 407bdd4dddee325a7dce3e84cf48201a06aa8508aa4Jeff Garzik unsigned int resp_idx; 408bdd4dddee325a7dce3e84cf48201a06aa8508aa4Jeff Garzik 40931961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ u32 pp_flags; 41031961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ}; 41131961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ 412bca1c4eb9411533d613123618c0d127fae532595Jeff Garzikstruct mv_port_signal { 413bca1c4eb9411533d613123618c0d127fae532595Jeff Garzik u32 amps; 414bca1c4eb9411533d613123618c0d127fae532595Jeff Garzik u32 pre; 415bca1c4eb9411533d613123618c0d127fae532595Jeff Garzik}; 416bca1c4eb9411533d613123618c0d127fae532595Jeff Garzik 41702a121da5a53d415b6596bc19cc6999d295d32a4Mark Lordstruct mv_host_priv { 41802a121da5a53d415b6596bc19cc6999d295d32a4Mark Lord u32 hp_flags; 41902a121da5a53d415b6596bc19cc6999d295d32a4Mark Lord struct mv_port_signal signal[8]; 42002a121da5a53d415b6596bc19cc6999d295d32a4Mark Lord const struct mv_hw_ops *ops; 42102a121da5a53d415b6596bc19cc6999d295d32a4Mark Lord u32 irq_cause_ofs; 42202a121da5a53d415b6596bc19cc6999d295d32a4Mark Lord u32 irq_mask_ofs; 42302a121da5a53d415b6596bc19cc6999d295d32a4Mark Lord u32 unmask_all_irqs; 42402a121da5a53d415b6596bc19cc6999d295d32a4Mark Lord}; 42502a121da5a53d415b6596bc19cc6999d295d32a4Mark Lord 42647c2b677daeed9c79ecb7167c211ff36876ea611Jeff Garzikstruct mv_hw_ops { 4272a47ce06d534692f9bd2bf4e90a20fc9b1054c39Jeff Garzik void (*phy_errata)(struct mv_host_priv *hpriv, void __iomem *mmio, 4282a47ce06d534692f9bd2bf4e90a20fc9b1054c39Jeff Garzik unsigned int port); 42947c2b677daeed9c79ecb7167c211ff36876ea611Jeff Garzik void (*enable_leds)(struct mv_host_priv *hpriv, void __iomem *mmio); 43047c2b677daeed9c79ecb7167c211ff36876ea611Jeff Garzik void (*read_preamp)(struct mv_host_priv *hpriv, int idx, 43147c2b677daeed9c79ecb7167c211ff36876ea611Jeff Garzik void __iomem *mmio); 432c9d39130123238ac18478a42e25cb7996eacfcc0Jeff Garzik int (*reset_hc)(struct mv_host_priv *hpriv, void __iomem *mmio, 433c9d39130123238ac18478a42e25cb7996eacfcc0Jeff Garzik unsigned int n_hc); 434522479fb98c6667f081e75f87e298e413c0b1db8Jeff Garzik void (*reset_flash)(struct mv_host_priv *hpriv, void __iomem *mmio); 435522479fb98c6667f081e75f87e298e413c0b1db8Jeff Garzik void (*reset_bus)(struct pci_dev *pdev, void __iomem *mmio); 43647c2b677daeed9c79ecb7167c211ff36876ea611Jeff Garzik}; 43747c2b677daeed9c79ecb7167c211ff36876ea611Jeff Garzik 43820f733e7d75a16bffc34842b7682c9247dd5f954Brett Russstatic void mv_irq_clear(struct ata_port *ap); 439da3dbb17a0e9a9ec7f5aed95f1fddadb790edc9dTejun Heostatic int mv_scr_read(struct ata_port *ap, unsigned int sc_reg_in, u32 *val); 440da3dbb17a0e9a9ec7f5aed95f1fddadb790edc9dTejun Heostatic int mv_scr_write(struct ata_port *ap, unsigned int sc_reg_in, u32 val); 441da3dbb17a0e9a9ec7f5aed95f1fddadb790edc9dTejun Heostatic int mv5_scr_read(struct ata_port *ap, unsigned int sc_reg_in, u32 *val); 442da3dbb17a0e9a9ec7f5aed95f1fddadb790edc9dTejun Heostatic int mv5_scr_write(struct ata_port *ap, unsigned int sc_reg_in, u32 val); 44331961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russstatic int mv_port_start(struct ata_port *ap); 44431961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russstatic void mv_port_stop(struct ata_port *ap); 44531961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russstatic void mv_qc_prep(struct ata_queued_cmd *qc); 446e4e7b89280d1d666e2c09e5ad36cf071796c4c7eJeff Garzikstatic void mv_qc_prep_iie(struct ata_queued_cmd *qc); 4479a3d9eb0177eb10500d49cd283b35576082a522dTejun Heostatic unsigned int mv_qc_issue(struct ata_queued_cmd *qc); 448bdd4dddee325a7dce3e84cf48201a06aa8508aa4Jeff Garzikstatic void mv_error_handler(struct ata_port *ap); 449bdd4dddee325a7dce3e84cf48201a06aa8508aa4Jeff Garzikstatic void mv_post_int_cmd(struct ata_queued_cmd *qc); 450bdd4dddee325a7dce3e84cf48201a06aa8508aa4Jeff Garzikstatic void mv_eh_freeze(struct ata_port *ap); 451bdd4dddee325a7dce3e84cf48201a06aa8508aa4Jeff Garzikstatic void mv_eh_thaw(struct ata_port *ap); 452f273827e2aadcf2f74a7bdc9ad715a1b20ea7ddaMark Lordstatic void mv6_dev_config(struct ata_device *dev); 45320f733e7d75a16bffc34842b7682c9247dd5f954Brett Russstatic int mv_init_one(struct pci_dev *pdev, const struct pci_device_id *ent); 45420f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ 4552a47ce06d534692f9bd2bf4e90a20fc9b1054c39Jeff Garzikstatic void mv5_phy_errata(struct mv_host_priv *hpriv, void __iomem *mmio, 4562a47ce06d534692f9bd2bf4e90a20fc9b1054c39Jeff Garzik unsigned int port); 45747c2b677daeed9c79ecb7167c211ff36876ea611Jeff Garzikstatic void mv5_enable_leds(struct mv_host_priv *hpriv, void __iomem *mmio); 45847c2b677daeed9c79ecb7167c211ff36876ea611Jeff Garzikstatic void mv5_read_preamp(struct mv_host_priv *hpriv, int idx, 45947c2b677daeed9c79ecb7167c211ff36876ea611Jeff Garzik void __iomem *mmio); 460c9d39130123238ac18478a42e25cb7996eacfcc0Jeff Garzikstatic int mv5_reset_hc(struct mv_host_priv *hpriv, void __iomem *mmio, 461c9d39130123238ac18478a42e25cb7996eacfcc0Jeff Garzik unsigned int n_hc); 462522479fb98c6667f081e75f87e298e413c0b1db8Jeff Garzikstatic void mv5_reset_flash(struct mv_host_priv *hpriv, void __iomem *mmio); 463522479fb98c6667f081e75f87e298e413c0b1db8Jeff Garzikstatic void mv5_reset_bus(struct pci_dev *pdev, void __iomem *mmio); 46447c2b677daeed9c79ecb7167c211ff36876ea611Jeff Garzik 4652a47ce06d534692f9bd2bf4e90a20fc9b1054c39Jeff Garzikstatic void mv6_phy_errata(struct mv_host_priv *hpriv, void __iomem *mmio, 4662a47ce06d534692f9bd2bf4e90a20fc9b1054c39Jeff Garzik unsigned int port); 46747c2b677daeed9c79ecb7167c211ff36876ea611Jeff Garzikstatic void mv6_enable_leds(struct mv_host_priv *hpriv, void __iomem *mmio); 46847c2b677daeed9c79ecb7167c211ff36876ea611Jeff Garzikstatic void mv6_read_preamp(struct mv_host_priv *hpriv, int idx, 46947c2b677daeed9c79ecb7167c211ff36876ea611Jeff Garzik void __iomem *mmio); 470c9d39130123238ac18478a42e25cb7996eacfcc0Jeff Garzikstatic int mv6_reset_hc(struct mv_host_priv *hpriv, void __iomem *mmio, 471c9d39130123238ac18478a42e25cb7996eacfcc0Jeff Garzik unsigned int n_hc); 472522479fb98c6667f081e75f87e298e413c0b1db8Jeff Garzikstatic void mv6_reset_flash(struct mv_host_priv *hpriv, void __iomem *mmio); 473522479fb98c6667f081e75f87e298e413c0b1db8Jeff Garzikstatic void mv_reset_pci_bus(struct pci_dev *pdev, void __iomem *mmio); 474c9d39130123238ac18478a42e25cb7996eacfcc0Jeff Garzikstatic void mv_channel_reset(struct mv_host_priv *hpriv, void __iomem *mmio, 475c9d39130123238ac18478a42e25cb7996eacfcc0Jeff Garzik unsigned int port_no); 476721091685f853ba4e6c49f26f989db0b1a811250Mark Lordstatic void mv_edma_cfg(struct mv_port_priv *pp, struct mv_host_priv *hpriv, 477721091685f853ba4e6c49f26f989db0b1a811250Mark Lord void __iomem *port_mmio, int want_ncq); 478721091685f853ba4e6c49f26f989db0b1a811250Mark Lordstatic int __mv_stop_dma(struct ata_port *ap); 47947c2b677daeed9c79ecb7167c211ff36876ea611Jeff Garzik 480c5d3e45a2200a0905dc45b72714726b7aac3aaf1Jeff Garzikstatic struct scsi_host_template mv5_sht = { 481c5d3e45a2200a0905dc45b72714726b7aac3aaf1Jeff Garzik .module = THIS_MODULE, 482c5d3e45a2200a0905dc45b72714726b7aac3aaf1Jeff Garzik .name = DRV_NAME, 483c5d3e45a2200a0905dc45b72714726b7aac3aaf1Jeff Garzik .ioctl = ata_scsi_ioctl, 484c5d3e45a2200a0905dc45b72714726b7aac3aaf1Jeff Garzik .queuecommand = ata_scsi_queuecmd, 485c5d3e45a2200a0905dc45b72714726b7aac3aaf1Jeff Garzik .can_queue = ATA_DEF_QUEUE, 486c5d3e45a2200a0905dc45b72714726b7aac3aaf1Jeff Garzik .this_id = ATA_SHT_THIS_ID, 487baf14aa14efcfdb5a74d5cf804691086c6bec743Jeff Garzik .sg_tablesize = MV_MAX_SG_CT / 2, 488c5d3e45a2200a0905dc45b72714726b7aac3aaf1Jeff Garzik .cmd_per_lun = ATA_SHT_CMD_PER_LUN, 489c5d3e45a2200a0905dc45b72714726b7aac3aaf1Jeff Garzik .emulated = ATA_SHT_EMULATED, 490c5d3e45a2200a0905dc45b72714726b7aac3aaf1Jeff Garzik .use_clustering = 1, 491c5d3e45a2200a0905dc45b72714726b7aac3aaf1Jeff Garzik .proc_name = DRV_NAME, 492c5d3e45a2200a0905dc45b72714726b7aac3aaf1Jeff Garzik .dma_boundary = MV_DMA_BOUNDARY, 4933be6cbd73f74b4a3da82cc7d6e1688a4ae595fc7Jeff Garzik .slave_configure = ata_scsi_slave_config, 494c5d3e45a2200a0905dc45b72714726b7aac3aaf1Jeff Garzik .slave_destroy = ata_scsi_slave_destroy, 495c5d3e45a2200a0905dc45b72714726b7aac3aaf1Jeff Garzik .bios_param = ata_std_bios_param, 496c5d3e45a2200a0905dc45b72714726b7aac3aaf1Jeff Garzik}; 497c5d3e45a2200a0905dc45b72714726b7aac3aaf1Jeff Garzik 498c5d3e45a2200a0905dc45b72714726b7aac3aaf1Jeff Garzikstatic struct scsi_host_template mv6_sht = { 49920f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ .module = THIS_MODULE, 50020f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ .name = DRV_NAME, 50120f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ .ioctl = ata_scsi_ioctl, 50220f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ .queuecommand = ata_scsi_queuecmd, 503c5d3e45a2200a0905dc45b72714726b7aac3aaf1Jeff Garzik .can_queue = ATA_DEF_QUEUE, 50420f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ .this_id = ATA_SHT_THIS_ID, 505baf14aa14efcfdb5a74d5cf804691086c6bec743Jeff Garzik .sg_tablesize = MV_MAX_SG_CT / 2, 50620f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ .cmd_per_lun = ATA_SHT_CMD_PER_LUN, 50720f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ .emulated = ATA_SHT_EMULATED, 508d88184fb2348a50f7c34f5d49a901c875b2e0114Jeff Garzik .use_clustering = 1, 50920f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ .proc_name = DRV_NAME, 51020f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ .dma_boundary = MV_DMA_BOUNDARY, 5113be6cbd73f74b4a3da82cc7d6e1688a4ae595fc7Jeff Garzik .slave_configure = ata_scsi_slave_config, 512ccf68c3405fca11386004674377d951b9b18e756Tejun Heo .slave_destroy = ata_scsi_slave_destroy, 51320f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ .bios_param = ata_std_bios_param, 51420f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ}; 51520f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ 516c9d39130123238ac18478a42e25cb7996eacfcc0Jeff Garzikstatic const struct ata_port_operations mv5_ops = { 517c9d39130123238ac18478a42e25cb7996eacfcc0Jeff Garzik .tf_load = ata_tf_load, 518c9d39130123238ac18478a42e25cb7996eacfcc0Jeff Garzik .tf_read = ata_tf_read, 519c9d39130123238ac18478a42e25cb7996eacfcc0Jeff Garzik .check_status = ata_check_status, 520c9d39130123238ac18478a42e25cb7996eacfcc0Jeff Garzik .exec_command = ata_exec_command, 521c9d39130123238ac18478a42e25cb7996eacfcc0Jeff Garzik .dev_select = ata_std_dev_select, 522c9d39130123238ac18478a42e25cb7996eacfcc0Jeff Garzik 523cffacd85bcf6fc652292001873119333555fe260Jeff Garzik .cable_detect = ata_cable_sata, 524c9d39130123238ac18478a42e25cb7996eacfcc0Jeff Garzik 525c9d39130123238ac18478a42e25cb7996eacfcc0Jeff Garzik .qc_prep = mv_qc_prep, 526c9d39130123238ac18478a42e25cb7996eacfcc0Jeff Garzik .qc_issue = mv_qc_issue, 5270d5ff566779f894ca9937231a181eb31e4adff0eTejun Heo .data_xfer = ata_data_xfer, 528c9d39130123238ac18478a42e25cb7996eacfcc0Jeff Garzik 529c9d39130123238ac18478a42e25cb7996eacfcc0Jeff Garzik .irq_clear = mv_irq_clear, 530246ce3b675843e0369643cceb4faeb6cf6d19a30Akira Iguchi .irq_on = ata_irq_on, 531c9d39130123238ac18478a42e25cb7996eacfcc0Jeff Garzik 532bdd4dddee325a7dce3e84cf48201a06aa8508aa4Jeff Garzik .error_handler = mv_error_handler, 533bdd4dddee325a7dce3e84cf48201a06aa8508aa4Jeff Garzik .post_internal_cmd = mv_post_int_cmd, 534bdd4dddee325a7dce3e84cf48201a06aa8508aa4Jeff Garzik .freeze = mv_eh_freeze, 535bdd4dddee325a7dce3e84cf48201a06aa8508aa4Jeff Garzik .thaw = mv_eh_thaw, 536bdd4dddee325a7dce3e84cf48201a06aa8508aa4Jeff Garzik 537c9d39130123238ac18478a42e25cb7996eacfcc0Jeff Garzik .scr_read = mv5_scr_read, 538c9d39130123238ac18478a42e25cb7996eacfcc0Jeff Garzik .scr_write = mv5_scr_write, 539c9d39130123238ac18478a42e25cb7996eacfcc0Jeff Garzik 540c9d39130123238ac18478a42e25cb7996eacfcc0Jeff Garzik .port_start = mv_port_start, 541c9d39130123238ac18478a42e25cb7996eacfcc0Jeff Garzik .port_stop = mv_port_stop, 542c9d39130123238ac18478a42e25cb7996eacfcc0Jeff Garzik}; 543c9d39130123238ac18478a42e25cb7996eacfcc0Jeff Garzik 544c9d39130123238ac18478a42e25cb7996eacfcc0Jeff Garzikstatic const struct ata_port_operations mv6_ops = { 545f273827e2aadcf2f74a7bdc9ad715a1b20ea7ddaMark Lord .dev_config = mv6_dev_config, 54620f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ .tf_load = ata_tf_load, 54720f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ .tf_read = ata_tf_read, 54820f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ .check_status = ata_check_status, 54920f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ .exec_command = ata_exec_command, 55020f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ .dev_select = ata_std_dev_select, 55120f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ 552cffacd85bcf6fc652292001873119333555fe260Jeff Garzik .cable_detect = ata_cable_sata, 55320f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ 55431961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ .qc_prep = mv_qc_prep, 55531961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ .qc_issue = mv_qc_issue, 5560d5ff566779f894ca9937231a181eb31e4adff0eTejun Heo .data_xfer = ata_data_xfer, 55720f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ 55820f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ .irq_clear = mv_irq_clear, 559246ce3b675843e0369643cceb4faeb6cf6d19a30Akira Iguchi .irq_on = ata_irq_on, 56020f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ 561bdd4dddee325a7dce3e84cf48201a06aa8508aa4Jeff Garzik .error_handler = mv_error_handler, 562bdd4dddee325a7dce3e84cf48201a06aa8508aa4Jeff Garzik .post_internal_cmd = mv_post_int_cmd, 563bdd4dddee325a7dce3e84cf48201a06aa8508aa4Jeff Garzik .freeze = mv_eh_freeze, 564bdd4dddee325a7dce3e84cf48201a06aa8508aa4Jeff Garzik .thaw = mv_eh_thaw, 565bdd4dddee325a7dce3e84cf48201a06aa8508aa4Jeff Garzik 56620f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ .scr_read = mv_scr_read, 56720f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ .scr_write = mv_scr_write, 56820f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ 56931961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ .port_start = mv_port_start, 57031961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ .port_stop = mv_port_stop, 57120f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ}; 57220f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ 573e4e7b89280d1d666e2c09e5ad36cf071796c4c7eJeff Garzikstatic const struct ata_port_operations mv_iie_ops = { 574e4e7b89280d1d666e2c09e5ad36cf071796c4c7eJeff Garzik .tf_load = ata_tf_load, 575e4e7b89280d1d666e2c09e5ad36cf071796c4c7eJeff Garzik .tf_read = ata_tf_read, 576e4e7b89280d1d666e2c09e5ad36cf071796c4c7eJeff Garzik .check_status = ata_check_status, 577e4e7b89280d1d666e2c09e5ad36cf071796c4c7eJeff Garzik .exec_command = ata_exec_command, 578e4e7b89280d1d666e2c09e5ad36cf071796c4c7eJeff Garzik .dev_select = ata_std_dev_select, 579e4e7b89280d1d666e2c09e5ad36cf071796c4c7eJeff Garzik 580cffacd85bcf6fc652292001873119333555fe260Jeff Garzik .cable_detect = ata_cable_sata, 581e4e7b89280d1d666e2c09e5ad36cf071796c4c7eJeff Garzik 582e4e7b89280d1d666e2c09e5ad36cf071796c4c7eJeff Garzik .qc_prep = mv_qc_prep_iie, 583e4e7b89280d1d666e2c09e5ad36cf071796c4c7eJeff Garzik .qc_issue = mv_qc_issue, 5840d5ff566779f894ca9937231a181eb31e4adff0eTejun Heo .data_xfer = ata_data_xfer, 585e4e7b89280d1d666e2c09e5ad36cf071796c4c7eJeff Garzik 586e4e7b89280d1d666e2c09e5ad36cf071796c4c7eJeff Garzik .irq_clear = mv_irq_clear, 587246ce3b675843e0369643cceb4faeb6cf6d19a30Akira Iguchi .irq_on = ata_irq_on, 588e4e7b89280d1d666e2c09e5ad36cf071796c4c7eJeff Garzik 589bdd4dddee325a7dce3e84cf48201a06aa8508aa4Jeff Garzik .error_handler = mv_error_handler, 590bdd4dddee325a7dce3e84cf48201a06aa8508aa4Jeff Garzik .post_internal_cmd = mv_post_int_cmd, 591bdd4dddee325a7dce3e84cf48201a06aa8508aa4Jeff Garzik .freeze = mv_eh_freeze, 592bdd4dddee325a7dce3e84cf48201a06aa8508aa4Jeff Garzik .thaw = mv_eh_thaw, 593bdd4dddee325a7dce3e84cf48201a06aa8508aa4Jeff Garzik 594e4e7b89280d1d666e2c09e5ad36cf071796c4c7eJeff Garzik .scr_read = mv_scr_read, 595e4e7b89280d1d666e2c09e5ad36cf071796c4c7eJeff Garzik .scr_write = mv_scr_write, 596e4e7b89280d1d666e2c09e5ad36cf071796c4c7eJeff Garzik 597e4e7b89280d1d666e2c09e5ad36cf071796c4c7eJeff Garzik .port_start = mv_port_start, 598e4e7b89280d1d666e2c09e5ad36cf071796c4c7eJeff Garzik .port_stop = mv_port_stop, 599e4e7b89280d1d666e2c09e5ad36cf071796c4c7eJeff Garzik}; 600e4e7b89280d1d666e2c09e5ad36cf071796c4c7eJeff Garzik 60198ac62defe529d04a192688f40d801a2d8fbcf98Arjan van de Venstatic const struct ata_port_info mv_port_info[] = { 60220f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ { /* chip_504x */ 603cca3974e48607c3775dc73b544a5700b2e37c21aJeff Garzik .flags = MV_COMMON_FLAGS, 60431961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ .pio_mask = 0x1f, /* pio0-4 */ 605bf6263a853c9c143bf03f0a6fdcc68ab714fb5f5Jeff Garzik .udma_mask = ATA_UDMA6, 606c9d39130123238ac18478a42e25cb7996eacfcc0Jeff Garzik .port_ops = &mv5_ops, 60720f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ }, 60820f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ { /* chip_508x */ 609c5d3e45a2200a0905dc45b72714726b7aac3aaf1Jeff Garzik .flags = MV_COMMON_FLAGS | MV_FLAG_DUAL_HC, 61031961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ .pio_mask = 0x1f, /* pio0-4 */ 611bf6263a853c9c143bf03f0a6fdcc68ab714fb5f5Jeff Garzik .udma_mask = ATA_UDMA6, 612c9d39130123238ac18478a42e25cb7996eacfcc0Jeff Garzik .port_ops = &mv5_ops, 61320f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ }, 61447c2b677daeed9c79ecb7167c211ff36876ea611Jeff Garzik { /* chip_5080 */ 615c5d3e45a2200a0905dc45b72714726b7aac3aaf1Jeff Garzik .flags = MV_COMMON_FLAGS | MV_FLAG_DUAL_HC, 61647c2b677daeed9c79ecb7167c211ff36876ea611Jeff Garzik .pio_mask = 0x1f, /* pio0-4 */ 617bf6263a853c9c143bf03f0a6fdcc68ab714fb5f5Jeff Garzik .udma_mask = ATA_UDMA6, 618c9d39130123238ac18478a42e25cb7996eacfcc0Jeff Garzik .port_ops = &mv5_ops, 61947c2b677daeed9c79ecb7167c211ff36876ea611Jeff Garzik }, 62020f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ { /* chip_604x */ 621c5d3e45a2200a0905dc45b72714726b7aac3aaf1Jeff Garzik .flags = MV_COMMON_FLAGS | MV_6XXX_FLAGS, 62231961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ .pio_mask = 0x1f, /* pio0-4 */ 623bf6263a853c9c143bf03f0a6fdcc68ab714fb5f5Jeff Garzik .udma_mask = ATA_UDMA6, 624c9d39130123238ac18478a42e25cb7996eacfcc0Jeff Garzik .port_ops = &mv6_ops, 62520f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ }, 62620f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ { /* chip_608x */ 627c5d3e45a2200a0905dc45b72714726b7aac3aaf1Jeff Garzik .flags = MV_COMMON_FLAGS | MV_6XXX_FLAGS | 628c5d3e45a2200a0905dc45b72714726b7aac3aaf1Jeff Garzik MV_FLAG_DUAL_HC, 62931961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ .pio_mask = 0x1f, /* pio0-4 */ 630bf6263a853c9c143bf03f0a6fdcc68ab714fb5f5Jeff Garzik .udma_mask = ATA_UDMA6, 631c9d39130123238ac18478a42e25cb7996eacfcc0Jeff Garzik .port_ops = &mv6_ops, 63220f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ }, 633e4e7b89280d1d666e2c09e5ad36cf071796c4c7eJeff Garzik { /* chip_6042 */ 634c5d3e45a2200a0905dc45b72714726b7aac3aaf1Jeff Garzik .flags = MV_COMMON_FLAGS | MV_6XXX_FLAGS, 635e4e7b89280d1d666e2c09e5ad36cf071796c4c7eJeff Garzik .pio_mask = 0x1f, /* pio0-4 */ 636bf6263a853c9c143bf03f0a6fdcc68ab714fb5f5Jeff Garzik .udma_mask = ATA_UDMA6, 637e4e7b89280d1d666e2c09e5ad36cf071796c4c7eJeff Garzik .port_ops = &mv_iie_ops, 638e4e7b89280d1d666e2c09e5ad36cf071796c4c7eJeff Garzik }, 639e4e7b89280d1d666e2c09e5ad36cf071796c4c7eJeff Garzik { /* chip_7042 */ 640c5d3e45a2200a0905dc45b72714726b7aac3aaf1Jeff Garzik .flags = MV_COMMON_FLAGS | MV_6XXX_FLAGS, 641e4e7b89280d1d666e2c09e5ad36cf071796c4c7eJeff Garzik .pio_mask = 0x1f, /* pio0-4 */ 642bf6263a853c9c143bf03f0a6fdcc68ab714fb5f5Jeff Garzik .udma_mask = ATA_UDMA6, 643e4e7b89280d1d666e2c09e5ad36cf071796c4c7eJeff Garzik .port_ops = &mv_iie_ops, 644e4e7b89280d1d666e2c09e5ad36cf071796c4c7eJeff Garzik }, 64520f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ}; 64620f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ 6473b7d697dfb7d03edb87e50b743a7ecff029618e9Jeff Garzikstatic const struct pci_device_id mv_pci_tbl[] = { 6482d2744fc8be620a2dc469cf48349e3e704119f1bJeff Garzik { PCI_VDEVICE(MARVELL, 0x5040), chip_504x }, 6492d2744fc8be620a2dc469cf48349e3e704119f1bJeff Garzik { PCI_VDEVICE(MARVELL, 0x5041), chip_504x }, 6502d2744fc8be620a2dc469cf48349e3e704119f1bJeff Garzik { PCI_VDEVICE(MARVELL, 0x5080), chip_5080 }, 6512d2744fc8be620a2dc469cf48349e3e704119f1bJeff Garzik { PCI_VDEVICE(MARVELL, 0x5081), chip_508x }, 652cfbf723eb7928879292ee71fa0d118fc4e37b8c9Alan Cox /* RocketRAID 1740/174x have different identifiers */ 653cfbf723eb7928879292ee71fa0d118fc4e37b8c9Alan Cox { PCI_VDEVICE(TTI, 0x1740), chip_508x }, 654cfbf723eb7928879292ee71fa0d118fc4e37b8c9Alan Cox { PCI_VDEVICE(TTI, 0x1742), chip_508x }, 6552d2744fc8be620a2dc469cf48349e3e704119f1bJeff Garzik 6562d2744fc8be620a2dc469cf48349e3e704119f1bJeff Garzik { PCI_VDEVICE(MARVELL, 0x6040), chip_604x }, 6572d2744fc8be620a2dc469cf48349e3e704119f1bJeff Garzik { PCI_VDEVICE(MARVELL, 0x6041), chip_604x }, 6582d2744fc8be620a2dc469cf48349e3e704119f1bJeff Garzik { PCI_VDEVICE(MARVELL, 0x6042), chip_6042 }, 6592d2744fc8be620a2dc469cf48349e3e704119f1bJeff Garzik { PCI_VDEVICE(MARVELL, 0x6080), chip_608x }, 6602d2744fc8be620a2dc469cf48349e3e704119f1bJeff Garzik { PCI_VDEVICE(MARVELL, 0x6081), chip_608x }, 6612d2744fc8be620a2dc469cf48349e3e704119f1bJeff Garzik 6622d2744fc8be620a2dc469cf48349e3e704119f1bJeff Garzik { PCI_VDEVICE(ADAPTEC2, 0x0241), chip_604x }, 6632d2744fc8be620a2dc469cf48349e3e704119f1bJeff Garzik 664d9f9c6bc91c14f53ffa782ffcd42259ecae1d38cFlorian Attenberger /* Adaptec 1430SA */ 665d9f9c6bc91c14f53ffa782ffcd42259ecae1d38cFlorian Attenberger { PCI_VDEVICE(ADAPTEC2, 0x0243), chip_7042 }, 666d9f9c6bc91c14f53ffa782ffcd42259ecae1d38cFlorian Attenberger 66702a121da5a53d415b6596bc19cc6999d295d32a4Mark Lord /* Marvell 7042 support */ 6686a3d586d8e8a50e4cfd7f8c36d82a53c5614e05bMorrison, Tom { PCI_VDEVICE(MARVELL, 0x7042), chip_7042 }, 6696a3d586d8e8a50e4cfd7f8c36d82a53c5614e05bMorrison, Tom 67002a121da5a53d415b6596bc19cc6999d295d32a4Mark Lord /* Highpoint RocketRAID PCIe series */ 67102a121da5a53d415b6596bc19cc6999d295d32a4Mark Lord { PCI_VDEVICE(TTI, 0x2300), chip_7042 }, 67202a121da5a53d415b6596bc19cc6999d295d32a4Mark Lord { PCI_VDEVICE(TTI, 0x2310), chip_7042 }, 67302a121da5a53d415b6596bc19cc6999d295d32a4Mark Lord 6742d2744fc8be620a2dc469cf48349e3e704119f1bJeff Garzik { } /* terminate list */ 67520f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ}; 67620f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ 67720f733e7d75a16bffc34842b7682c9247dd5f954Brett Russstatic struct pci_driver mv_pci_driver = { 67820f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ .name = DRV_NAME, 67920f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ .id_table = mv_pci_tbl, 68020f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ .probe = mv_init_one, 68120f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ .remove = ata_pci_remove_one, 68220f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ}; 68320f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ 68447c2b677daeed9c79ecb7167c211ff36876ea611Jeff Garzikstatic const struct mv_hw_ops mv5xxx_ops = { 68547c2b677daeed9c79ecb7167c211ff36876ea611Jeff Garzik .phy_errata = mv5_phy_errata, 68647c2b677daeed9c79ecb7167c211ff36876ea611Jeff Garzik .enable_leds = mv5_enable_leds, 68747c2b677daeed9c79ecb7167c211ff36876ea611Jeff Garzik .read_preamp = mv5_read_preamp, 68847c2b677daeed9c79ecb7167c211ff36876ea611Jeff Garzik .reset_hc = mv5_reset_hc, 689522479fb98c6667f081e75f87e298e413c0b1db8Jeff Garzik .reset_flash = mv5_reset_flash, 690522479fb98c6667f081e75f87e298e413c0b1db8Jeff Garzik .reset_bus = mv5_reset_bus, 69147c2b677daeed9c79ecb7167c211ff36876ea611Jeff Garzik}; 69247c2b677daeed9c79ecb7167c211ff36876ea611Jeff Garzik 69347c2b677daeed9c79ecb7167c211ff36876ea611Jeff Garzikstatic const struct mv_hw_ops mv6xxx_ops = { 69447c2b677daeed9c79ecb7167c211ff36876ea611Jeff Garzik .phy_errata = mv6_phy_errata, 69547c2b677daeed9c79ecb7167c211ff36876ea611Jeff Garzik .enable_leds = mv6_enable_leds, 69647c2b677daeed9c79ecb7167c211ff36876ea611Jeff Garzik .read_preamp = mv6_read_preamp, 69747c2b677daeed9c79ecb7167c211ff36876ea611Jeff Garzik .reset_hc = mv6_reset_hc, 698522479fb98c6667f081e75f87e298e413c0b1db8Jeff Garzik .reset_flash = mv6_reset_flash, 699522479fb98c6667f081e75f87e298e413c0b1db8Jeff Garzik .reset_bus = mv_reset_pci_bus, 70047c2b677daeed9c79ecb7167c211ff36876ea611Jeff Garzik}; 70147c2b677daeed9c79ecb7167c211ff36876ea611Jeff Garzik 70220f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ/* 703ddef9bb367b19383df627e388cb4c01c86ddba6cJeff Garzik * module options 704ddef9bb367b19383df627e388cb4c01c86ddba6cJeff Garzik */ 705ddef9bb367b19383df627e388cb4c01c86ddba6cJeff Garzikstatic int msi; /* Use PCI msi; either zero (off, default) or non-zero */ 706ddef9bb367b19383df627e388cb4c01c86ddba6cJeff Garzik 707ddef9bb367b19383df627e388cb4c01c86ddba6cJeff Garzik 708d88184fb2348a50f7c34f5d49a901c875b2e0114Jeff Garzik/* move to PCI layer or libata core? */ 709d88184fb2348a50f7c34f5d49a901c875b2e0114Jeff Garzikstatic int pci_go_64(struct pci_dev *pdev) 710d88184fb2348a50f7c34f5d49a901c875b2e0114Jeff Garzik{ 711d88184fb2348a50f7c34f5d49a901c875b2e0114Jeff Garzik int rc; 712d88184fb2348a50f7c34f5d49a901c875b2e0114Jeff Garzik 713d88184fb2348a50f7c34f5d49a901c875b2e0114Jeff Garzik if (!pci_set_dma_mask(pdev, DMA_64BIT_MASK)) { 714d88184fb2348a50f7c34f5d49a901c875b2e0114Jeff Garzik rc = pci_set_consistent_dma_mask(pdev, DMA_64BIT_MASK); 715d88184fb2348a50f7c34f5d49a901c875b2e0114Jeff Garzik if (rc) { 716d88184fb2348a50f7c34f5d49a901c875b2e0114Jeff Garzik rc = pci_set_consistent_dma_mask(pdev, DMA_32BIT_MASK); 717d88184fb2348a50f7c34f5d49a901c875b2e0114Jeff Garzik if (rc) { 718d88184fb2348a50f7c34f5d49a901c875b2e0114Jeff Garzik dev_printk(KERN_ERR, &pdev->dev, 719d88184fb2348a50f7c34f5d49a901c875b2e0114Jeff Garzik "64-bit DMA enable failed\n"); 720d88184fb2348a50f7c34f5d49a901c875b2e0114Jeff Garzik return rc; 721d88184fb2348a50f7c34f5d49a901c875b2e0114Jeff Garzik } 722d88184fb2348a50f7c34f5d49a901c875b2e0114Jeff Garzik } 723d88184fb2348a50f7c34f5d49a901c875b2e0114Jeff Garzik } else { 724d88184fb2348a50f7c34f5d49a901c875b2e0114Jeff Garzik rc = pci_set_dma_mask(pdev, DMA_32BIT_MASK); 725d88184fb2348a50f7c34f5d49a901c875b2e0114Jeff Garzik if (rc) { 726d88184fb2348a50f7c34f5d49a901c875b2e0114Jeff Garzik dev_printk(KERN_ERR, &pdev->dev, 727d88184fb2348a50f7c34f5d49a901c875b2e0114Jeff Garzik "32-bit DMA enable failed\n"); 728d88184fb2348a50f7c34f5d49a901c875b2e0114Jeff Garzik return rc; 729d88184fb2348a50f7c34f5d49a901c875b2e0114Jeff Garzik } 730d88184fb2348a50f7c34f5d49a901c875b2e0114Jeff Garzik rc = pci_set_consistent_dma_mask(pdev, DMA_32BIT_MASK); 731d88184fb2348a50f7c34f5d49a901c875b2e0114Jeff Garzik if (rc) { 732d88184fb2348a50f7c34f5d49a901c875b2e0114Jeff Garzik dev_printk(KERN_ERR, &pdev->dev, 733d88184fb2348a50f7c34f5d49a901c875b2e0114Jeff Garzik "32-bit consistent DMA enable failed\n"); 734d88184fb2348a50f7c34f5d49a901c875b2e0114Jeff Garzik return rc; 735d88184fb2348a50f7c34f5d49a901c875b2e0114Jeff Garzik } 736d88184fb2348a50f7c34f5d49a901c875b2e0114Jeff Garzik } 737d88184fb2348a50f7c34f5d49a901c875b2e0114Jeff Garzik 738d88184fb2348a50f7c34f5d49a901c875b2e0114Jeff Garzik return rc; 739d88184fb2348a50f7c34f5d49a901c875b2e0114Jeff Garzik} 740d88184fb2348a50f7c34f5d49a901c875b2e0114Jeff Garzik 741ddef9bb367b19383df627e388cb4c01c86ddba6cJeff Garzik/* 74220f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ * Functions 74320f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ */ 74420f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ 74520f733e7d75a16bffc34842b7682c9247dd5f954Brett Russstatic inline void writelfl(unsigned long data, void __iomem *addr) 74620f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ{ 74720f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ writel(data, addr); 74820f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ (void) readl(addr); /* flush to avoid PCI posted write */ 74920f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ} 75020f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ 75120f733e7d75a16bffc34842b7682c9247dd5f954Brett Russstatic inline void __iomem *mv_hc_base(void __iomem *base, unsigned int hc) 75220f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ{ 75320f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ return (base + MV_SATAHC0_REG_BASE + (hc * MV_SATAHC_REG_SZ)); 75420f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ} 75520f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ 756c9d39130123238ac18478a42e25cb7996eacfcc0Jeff Garzikstatic inline unsigned int mv_hc_from_port(unsigned int port) 757c9d39130123238ac18478a42e25cb7996eacfcc0Jeff Garzik{ 758c9d39130123238ac18478a42e25cb7996eacfcc0Jeff Garzik return port >> MV_PORT_HC_SHIFT; 759c9d39130123238ac18478a42e25cb7996eacfcc0Jeff Garzik} 760c9d39130123238ac18478a42e25cb7996eacfcc0Jeff Garzik 761c9d39130123238ac18478a42e25cb7996eacfcc0Jeff Garzikstatic inline unsigned int mv_hardport_from_port(unsigned int port) 762c9d39130123238ac18478a42e25cb7996eacfcc0Jeff Garzik{ 763c9d39130123238ac18478a42e25cb7996eacfcc0Jeff Garzik return port & MV_PORT_MASK; 764c9d39130123238ac18478a42e25cb7996eacfcc0Jeff Garzik} 765c9d39130123238ac18478a42e25cb7996eacfcc0Jeff Garzik 766c9d39130123238ac18478a42e25cb7996eacfcc0Jeff Garzikstatic inline void __iomem *mv_hc_base_from_port(void __iomem *base, 767c9d39130123238ac18478a42e25cb7996eacfcc0Jeff Garzik unsigned int port) 768c9d39130123238ac18478a42e25cb7996eacfcc0Jeff Garzik{ 769c9d39130123238ac18478a42e25cb7996eacfcc0Jeff Garzik return mv_hc_base(base, mv_hc_from_port(port)); 770c9d39130123238ac18478a42e25cb7996eacfcc0Jeff Garzik} 771c9d39130123238ac18478a42e25cb7996eacfcc0Jeff Garzik 77220f733e7d75a16bffc34842b7682c9247dd5f954Brett Russstatic inline void __iomem *mv_port_base(void __iomem *base, unsigned int port) 77320f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ{ 774c9d39130123238ac18478a42e25cb7996eacfcc0Jeff Garzik return mv_hc_base_from_port(base, port) + 7758b260248d9e0e8b64bb72fd4dee03ad86984c344Jeff Garzik MV_SATAHC_ARBTR_REG_SZ + 776c9d39130123238ac18478a42e25cb7996eacfcc0Jeff Garzik (mv_hardport_from_port(port) * MV_PORT_REG_SZ); 77720f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ} 77820f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ 77920f733e7d75a16bffc34842b7682c9247dd5f954Brett Russstatic inline void __iomem *mv_ap_base(struct ata_port *ap) 78020f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ{ 7810d5ff566779f894ca9937231a181eb31e4adff0eTejun Heo return mv_port_base(ap->host->iomap[MV_PRIMARY_BAR], ap->port_no); 78220f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ} 78320f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ 784cca3974e48607c3775dc73b544a5700b2e37c21aJeff Garzikstatic inline int mv_get_hc_count(unsigned long port_flags) 78531961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ{ 786cca3974e48607c3775dc73b544a5700b2e37c21aJeff Garzik return ((port_flags & MV_FLAG_DUAL_HC) ? 2 : 1); 78731961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ} 78831961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ 78931961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russstatic void mv_irq_clear(struct ata_port *ap) 79020f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ{ 79120f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ} 79220f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ 793c5d3e45a2200a0905dc45b72714726b7aac3aaf1Jeff Garzikstatic void mv_set_edma_ptrs(void __iomem *port_mmio, 794c5d3e45a2200a0905dc45b72714726b7aac3aaf1Jeff Garzik struct mv_host_priv *hpriv, 795c5d3e45a2200a0905dc45b72714726b7aac3aaf1Jeff Garzik struct mv_port_priv *pp) 796c5d3e45a2200a0905dc45b72714726b7aac3aaf1Jeff Garzik{ 797bdd4dddee325a7dce3e84cf48201a06aa8508aa4Jeff Garzik u32 index; 798bdd4dddee325a7dce3e84cf48201a06aa8508aa4Jeff Garzik 799c5d3e45a2200a0905dc45b72714726b7aac3aaf1Jeff Garzik /* 800c5d3e45a2200a0905dc45b72714726b7aac3aaf1Jeff Garzik * initialize request queue 801c5d3e45a2200a0905dc45b72714726b7aac3aaf1Jeff Garzik */ 802bdd4dddee325a7dce3e84cf48201a06aa8508aa4Jeff Garzik index = (pp->req_idx & MV_MAX_Q_DEPTH_MASK) << EDMA_REQ_Q_PTR_SHIFT; 803bdd4dddee325a7dce3e84cf48201a06aa8508aa4Jeff Garzik 804c5d3e45a2200a0905dc45b72714726b7aac3aaf1Jeff Garzik WARN_ON(pp->crqb_dma & 0x3ff); 805c5d3e45a2200a0905dc45b72714726b7aac3aaf1Jeff Garzik writel((pp->crqb_dma >> 16) >> 16, port_mmio + EDMA_REQ_Q_BASE_HI_OFS); 806bdd4dddee325a7dce3e84cf48201a06aa8508aa4Jeff Garzik writelfl((pp->crqb_dma & EDMA_REQ_Q_BASE_LO_MASK) | index, 807c5d3e45a2200a0905dc45b72714726b7aac3aaf1Jeff Garzik port_mmio + EDMA_REQ_Q_IN_PTR_OFS); 808c5d3e45a2200a0905dc45b72714726b7aac3aaf1Jeff Garzik 809c5d3e45a2200a0905dc45b72714726b7aac3aaf1Jeff Garzik if (hpriv->hp_flags & MV_HP_ERRATA_XX42A0) 810bdd4dddee325a7dce3e84cf48201a06aa8508aa4Jeff Garzik writelfl((pp->crqb_dma & 0xffffffff) | index, 811c5d3e45a2200a0905dc45b72714726b7aac3aaf1Jeff Garzik port_mmio + EDMA_REQ_Q_OUT_PTR_OFS); 812c5d3e45a2200a0905dc45b72714726b7aac3aaf1Jeff Garzik else 813bdd4dddee325a7dce3e84cf48201a06aa8508aa4Jeff Garzik writelfl(index, port_mmio + EDMA_REQ_Q_OUT_PTR_OFS); 814c5d3e45a2200a0905dc45b72714726b7aac3aaf1Jeff Garzik 815c5d3e45a2200a0905dc45b72714726b7aac3aaf1Jeff Garzik /* 816c5d3e45a2200a0905dc45b72714726b7aac3aaf1Jeff Garzik * initialize response queue 817c5d3e45a2200a0905dc45b72714726b7aac3aaf1Jeff Garzik */ 818bdd4dddee325a7dce3e84cf48201a06aa8508aa4Jeff Garzik index = (pp->resp_idx & MV_MAX_Q_DEPTH_MASK) << EDMA_RSP_Q_PTR_SHIFT; 819bdd4dddee325a7dce3e84cf48201a06aa8508aa4Jeff Garzik 820c5d3e45a2200a0905dc45b72714726b7aac3aaf1Jeff Garzik WARN_ON(pp->crpb_dma & 0xff); 821c5d3e45a2200a0905dc45b72714726b7aac3aaf1Jeff Garzik writel((pp->crpb_dma >> 16) >> 16, port_mmio + EDMA_RSP_Q_BASE_HI_OFS); 822c5d3e45a2200a0905dc45b72714726b7aac3aaf1Jeff Garzik 823c5d3e45a2200a0905dc45b72714726b7aac3aaf1Jeff Garzik if (hpriv->hp_flags & MV_HP_ERRATA_XX42A0) 824bdd4dddee325a7dce3e84cf48201a06aa8508aa4Jeff Garzik writelfl((pp->crpb_dma & 0xffffffff) | index, 825c5d3e45a2200a0905dc45b72714726b7aac3aaf1Jeff Garzik port_mmio + EDMA_RSP_Q_IN_PTR_OFS); 826c5d3e45a2200a0905dc45b72714726b7aac3aaf1Jeff Garzik else 827bdd4dddee325a7dce3e84cf48201a06aa8508aa4Jeff Garzik writelfl(index, port_mmio + EDMA_RSP_Q_IN_PTR_OFS); 828c5d3e45a2200a0905dc45b72714726b7aac3aaf1Jeff Garzik 829bdd4dddee325a7dce3e84cf48201a06aa8508aa4Jeff Garzik writelfl((pp->crpb_dma & EDMA_RSP_Q_BASE_LO_MASK) | index, 830c5d3e45a2200a0905dc45b72714726b7aac3aaf1Jeff Garzik port_mmio + EDMA_RSP_Q_OUT_PTR_OFS); 831c5d3e45a2200a0905dc45b72714726b7aac3aaf1Jeff Garzik} 832c5d3e45a2200a0905dc45b72714726b7aac3aaf1Jeff Garzik 83305b308e1df6d9d673daedb517969241f41278b52Brett Russ/** 83405b308e1df6d9d673daedb517969241f41278b52Brett Russ * mv_start_dma - Enable eDMA engine 83505b308e1df6d9d673daedb517969241f41278b52Brett Russ * @base: port base address 83605b308e1df6d9d673daedb517969241f41278b52Brett Russ * @pp: port private data 83705b308e1df6d9d673daedb517969241f41278b52Brett Russ * 838beec7dbc6ff003bbc94de62b3323519c878fb2acTejun Heo * Verify the local cache of the eDMA state is accurate with a 839beec7dbc6ff003bbc94de62b3323519c878fb2acTejun Heo * WARN_ON. 84005b308e1df6d9d673daedb517969241f41278b52Brett Russ * 84105b308e1df6d9d673daedb517969241f41278b52Brett Russ * LOCKING: 84205b308e1df6d9d673daedb517969241f41278b52Brett Russ * Inherited from caller. 84305b308e1df6d9d673daedb517969241f41278b52Brett Russ */ 8440c58912e192fc3a4835d772aafa40b72552b819fMark Lordstatic void mv_start_dma(struct ata_port *ap, void __iomem *port_mmio, 845721091685f853ba4e6c49f26f989db0b1a811250Mark Lord struct mv_port_priv *pp, u8 protocol) 84620f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ{ 847721091685f853ba4e6c49f26f989db0b1a811250Mark Lord int want_ncq = (protocol == ATA_PROT_NCQ); 848721091685f853ba4e6c49f26f989db0b1a811250Mark Lord 849721091685f853ba4e6c49f26f989db0b1a811250Mark Lord if (pp->pp_flags & MV_PP_FLAG_EDMA_EN) { 850721091685f853ba4e6c49f26f989db0b1a811250Mark Lord int using_ncq = ((pp->pp_flags & MV_PP_FLAG_NCQ_EN) != 0); 851721091685f853ba4e6c49f26f989db0b1a811250Mark Lord if (want_ncq != using_ncq) 852721091685f853ba4e6c49f26f989db0b1a811250Mark Lord __mv_stop_dma(ap); 853721091685f853ba4e6c49f26f989db0b1a811250Mark Lord } 854c5d3e45a2200a0905dc45b72714726b7aac3aaf1Jeff Garzik if (!(pp->pp_flags & MV_PP_FLAG_EDMA_EN)) { 8550c58912e192fc3a4835d772aafa40b72552b819fMark Lord struct mv_host_priv *hpriv = ap->host->private_data; 8560c58912e192fc3a4835d772aafa40b72552b819fMark Lord int hard_port = mv_hardport_from_port(ap->port_no); 8570c58912e192fc3a4835d772aafa40b72552b819fMark Lord void __iomem *hc_mmio = mv_hc_base_from_port( 8580c58912e192fc3a4835d772aafa40b72552b819fMark Lord ap->host->iomap[MV_PRIMARY_BAR], hard_port); 8590c58912e192fc3a4835d772aafa40b72552b819fMark Lord u32 hc_irq_cause, ipending; 8600c58912e192fc3a4835d772aafa40b72552b819fMark Lord 861bdd4dddee325a7dce3e84cf48201a06aa8508aa4Jeff Garzik /* clear EDMA event indicators, if any */ 862f630d562829fcd8160a118f98c1e5b9cdb4e703eMark Lord writelfl(0, port_mmio + EDMA_ERR_IRQ_CAUSE_OFS); 863bdd4dddee325a7dce3e84cf48201a06aa8508aa4Jeff Garzik 8640c58912e192fc3a4835d772aafa40b72552b819fMark Lord /* clear EDMA interrupt indicator, if any */ 8650c58912e192fc3a4835d772aafa40b72552b819fMark Lord hc_irq_cause = readl(hc_mmio + HC_IRQ_CAUSE_OFS); 8660c58912e192fc3a4835d772aafa40b72552b819fMark Lord ipending = (DEV_IRQ << hard_port) | 8670c58912e192fc3a4835d772aafa40b72552b819fMark Lord (CRPB_DMA_DONE << hard_port); 8680c58912e192fc3a4835d772aafa40b72552b819fMark Lord if (hc_irq_cause & ipending) { 8690c58912e192fc3a4835d772aafa40b72552b819fMark Lord writelfl(hc_irq_cause & ~ipending, 8700c58912e192fc3a4835d772aafa40b72552b819fMark Lord hc_mmio + HC_IRQ_CAUSE_OFS); 8710c58912e192fc3a4835d772aafa40b72552b819fMark Lord } 8720c58912e192fc3a4835d772aafa40b72552b819fMark Lord 873721091685f853ba4e6c49f26f989db0b1a811250Mark Lord mv_edma_cfg(pp, hpriv, port_mmio, want_ncq); 8740c58912e192fc3a4835d772aafa40b72552b819fMark Lord 8750c58912e192fc3a4835d772aafa40b72552b819fMark Lord /* clear FIS IRQ Cause */ 8760c58912e192fc3a4835d772aafa40b72552b819fMark Lord writelfl(0, port_mmio + SATA_FIS_IRQ_CAUSE_OFS); 8770c58912e192fc3a4835d772aafa40b72552b819fMark Lord 878f630d562829fcd8160a118f98c1e5b9cdb4e703eMark Lord mv_set_edma_ptrs(port_mmio, hpriv, pp); 879bdd4dddee325a7dce3e84cf48201a06aa8508aa4Jeff Garzik 880f630d562829fcd8160a118f98c1e5b9cdb4e703eMark Lord writelfl(EDMA_EN, port_mmio + EDMA_CMD_OFS); 881afb0edd922c7ed6e73678730921dfcccebec17e8Brett Russ pp->pp_flags |= MV_PP_FLAG_EDMA_EN; 882afb0edd922c7ed6e73678730921dfcccebec17e8Brett Russ } 883f630d562829fcd8160a118f98c1e5b9cdb4e703eMark Lord WARN_ON(!(EDMA_EN & readl(port_mmio + EDMA_CMD_OFS))); 88420f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ} 88520f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ 88605b308e1df6d9d673daedb517969241f41278b52Brett Russ/** 8870ea9e179f436f153fc19fdaef7abbc1e0da20762Jeff Garzik * __mv_stop_dma - Disable eDMA engine 88805b308e1df6d9d673daedb517969241f41278b52Brett Russ * @ap: ATA channel to manipulate 88905b308e1df6d9d673daedb517969241f41278b52Brett Russ * 890beec7dbc6ff003bbc94de62b3323519c878fb2acTejun Heo * Verify the local cache of the eDMA state is accurate with a 891beec7dbc6ff003bbc94de62b3323519c878fb2acTejun Heo * WARN_ON. 89205b308e1df6d9d673daedb517969241f41278b52Brett Russ * 89305b308e1df6d9d673daedb517969241f41278b52Brett Russ * LOCKING: 89405b308e1df6d9d673daedb517969241f41278b52Brett Russ * Inherited from caller. 89505b308e1df6d9d673daedb517969241f41278b52Brett Russ */ 8960ea9e179f436f153fc19fdaef7abbc1e0da20762Jeff Garzikstatic int __mv_stop_dma(struct ata_port *ap) 89720f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ{ 89831961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ void __iomem *port_mmio = mv_ap_base(ap); 89931961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ struct mv_port_priv *pp = ap->private_data; 90031961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ u32 reg; 901c5d3e45a2200a0905dc45b72714726b7aac3aaf1Jeff Garzik int i, err = 0; 90231961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ 9034537deb5e90b717a725b3d74b58b4bb1d28443d0Jeff Garzik if (pp->pp_flags & MV_PP_FLAG_EDMA_EN) { 904afb0edd922c7ed6e73678730921dfcccebec17e8Brett Russ /* Disable EDMA if active. The disable bit auto clears. 90531961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ */ 90631961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ writelfl(EDMA_DS, port_mmio + EDMA_CMD_OFS); 90731961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ pp->pp_flags &= ~MV_PP_FLAG_EDMA_EN; 908afb0edd922c7ed6e73678730921dfcccebec17e8Brett Russ } else { 909beec7dbc6ff003bbc94de62b3323519c878fb2acTejun Heo WARN_ON(EDMA_EN & readl(port_mmio + EDMA_CMD_OFS)); 9102dcb407e61458ded17503d6bd12b8c064965368bJeff Garzik } 9118b260248d9e0e8b64bb72fd4dee03ad86984c344Jeff Garzik 91231961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ /* now properly wait for the eDMA to stop */ 91331961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ for (i = 1000; i > 0; i--) { 91431961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ reg = readl(port_mmio + EDMA_CMD_OFS); 9154537deb5e90b717a725b3d74b58b4bb1d28443d0Jeff Garzik if (!(reg & EDMA_EN)) 91631961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ break; 9174537deb5e90b717a725b3d74b58b4bb1d28443d0Jeff Garzik 91831961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ udelay(100); 91931961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ } 92031961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ 921c5d3e45a2200a0905dc45b72714726b7aac3aaf1Jeff Garzik if (reg & EDMA_EN) { 922f15a1dafed22d5037e0feea7528e1eeb28a1a7a3Tejun Heo ata_port_printk(ap, KERN_ERR, "Unable to stop eDMA\n"); 923c5d3e45a2200a0905dc45b72714726b7aac3aaf1Jeff Garzik err = -EIO; 92431961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ } 925c5d3e45a2200a0905dc45b72714726b7aac3aaf1Jeff Garzik 926c5d3e45a2200a0905dc45b72714726b7aac3aaf1Jeff Garzik return err; 92720f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ} 92820f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ 9290ea9e179f436f153fc19fdaef7abbc1e0da20762Jeff Garzikstatic int mv_stop_dma(struct ata_port *ap) 9300ea9e179f436f153fc19fdaef7abbc1e0da20762Jeff Garzik{ 9310ea9e179f436f153fc19fdaef7abbc1e0da20762Jeff Garzik unsigned long flags; 9320ea9e179f436f153fc19fdaef7abbc1e0da20762Jeff Garzik int rc; 9330ea9e179f436f153fc19fdaef7abbc1e0da20762Jeff Garzik 9340ea9e179f436f153fc19fdaef7abbc1e0da20762Jeff Garzik spin_lock_irqsave(&ap->host->lock, flags); 9350ea9e179f436f153fc19fdaef7abbc1e0da20762Jeff Garzik rc = __mv_stop_dma(ap); 9360ea9e179f436f153fc19fdaef7abbc1e0da20762Jeff Garzik spin_unlock_irqrestore(&ap->host->lock, flags); 9370ea9e179f436f153fc19fdaef7abbc1e0da20762Jeff Garzik 9380ea9e179f436f153fc19fdaef7abbc1e0da20762Jeff Garzik return rc; 9390ea9e179f436f153fc19fdaef7abbc1e0da20762Jeff Garzik} 9400ea9e179f436f153fc19fdaef7abbc1e0da20762Jeff Garzik 9418a70f8dc08dd40b7f8ac77280eaa99a8c6bc46f4Jeff Garzik#ifdef ATA_DEBUG 94231961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russstatic void mv_dump_mem(void __iomem *start, unsigned bytes) 94320f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ{ 94431961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ int b, w; 94531961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ for (b = 0; b < bytes; ) { 94631961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ DPRINTK("%p: ", start + b); 94731961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ for (w = 0; b < bytes && w < 4; w++) { 9482dcb407e61458ded17503d6bd12b8c064965368bJeff Garzik printk("%08x ", readl(start + b)); 94931961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ b += sizeof(u32); 95031961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ } 95131961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ printk("\n"); 95231961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ } 95331961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ} 9548a70f8dc08dd40b7f8ac77280eaa99a8c6bc46f4Jeff Garzik#endif 9558a70f8dc08dd40b7f8ac77280eaa99a8c6bc46f4Jeff Garzik 95631961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russstatic void mv_dump_pci_cfg(struct pci_dev *pdev, unsigned bytes) 95731961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ{ 95831961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ#ifdef ATA_DEBUG 95931961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ int b, w; 96031961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ u32 dw; 96131961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ for (b = 0; b < bytes; ) { 96231961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ DPRINTK("%02x: ", b); 96331961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ for (w = 0; b < bytes && w < 4; w++) { 9642dcb407e61458ded17503d6bd12b8c064965368bJeff Garzik (void) pci_read_config_dword(pdev, b, &dw); 9652dcb407e61458ded17503d6bd12b8c064965368bJeff Garzik printk("%08x ", dw); 96631961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ b += sizeof(u32); 96731961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ } 96831961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ printk("\n"); 96931961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ } 97031961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ#endif 97131961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ} 97231961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russstatic void mv_dump_all_regs(void __iomem *mmio_base, int port, 97331961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ struct pci_dev *pdev) 97431961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ{ 97531961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ#ifdef ATA_DEBUG 9768b260248d9e0e8b64bb72fd4dee03ad86984c344Jeff Garzik void __iomem *hc_base = mv_hc_base(mmio_base, 97731961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ port >> MV_PORT_HC_SHIFT); 97831961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ void __iomem *port_base; 97931961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ int start_port, num_ports, p, start_hc, num_hcs, hc; 98031961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ 98131961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ if (0 > port) { 98231961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ start_hc = start_port = 0; 98331961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ num_ports = 8; /* shld be benign for 4 port devs */ 98431961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ num_hcs = 2; 98531961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ } else { 98631961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ start_hc = port >> MV_PORT_HC_SHIFT; 98731961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ start_port = port; 98831961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ num_ports = num_hcs = 1; 98931961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ } 9908b260248d9e0e8b64bb72fd4dee03ad86984c344Jeff Garzik DPRINTK("All registers for port(s) %u-%u:\n", start_port, 99131961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ num_ports > 1 ? num_ports - 1 : start_port); 99231961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ 99331961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ if (NULL != pdev) { 99431961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ DPRINTK("PCI config space regs:\n"); 99531961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ mv_dump_pci_cfg(pdev, 0x68); 99631961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ } 99731961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ DPRINTK("PCI regs:\n"); 99831961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ mv_dump_mem(mmio_base+0xc00, 0x3c); 99931961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ mv_dump_mem(mmio_base+0xd00, 0x34); 100031961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ mv_dump_mem(mmio_base+0xf00, 0x4); 100131961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ mv_dump_mem(mmio_base+0x1d00, 0x6c); 100231961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ for (hc = start_hc; hc < start_hc + num_hcs; hc++) { 1003d220c37e0a3c9a47ae00e87e044d963b3ea040bcDan Aloni hc_base = mv_hc_base(mmio_base, hc); 100431961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ DPRINTK("HC regs (HC %i):\n", hc); 100531961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ mv_dump_mem(hc_base, 0x1c); 100631961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ } 100731961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ for (p = start_port; p < start_port + num_ports; p++) { 100831961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ port_base = mv_port_base(mmio_base, p); 10092dcb407e61458ded17503d6bd12b8c064965368bJeff Garzik DPRINTK("EDMA regs (port %i):\n", p); 101031961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ mv_dump_mem(port_base, 0x54); 10112dcb407e61458ded17503d6bd12b8c064965368bJeff Garzik DPRINTK("SATA regs (port %i):\n", p); 101231961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ mv_dump_mem(port_base+0x300, 0x60); 101331961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ } 101431961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ#endif 101520f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ} 101620f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ 101720f733e7d75a16bffc34842b7682c9247dd5f954Brett Russstatic unsigned int mv_scr_offset(unsigned int sc_reg_in) 101820f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ{ 101920f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ unsigned int ofs; 102020f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ 102120f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ switch (sc_reg_in) { 102220f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ case SCR_STATUS: 102320f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ case SCR_CONTROL: 102420f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ case SCR_ERROR: 102520f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ ofs = SATA_STATUS_OFS + (sc_reg_in * sizeof(u32)); 102620f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ break; 102720f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ case SCR_ACTIVE: 102820f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ ofs = SATA_ACTIVE_OFS; /* active is not with the others */ 102920f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ break; 103020f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ default: 103120f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ ofs = 0xffffffffU; 103220f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ break; 103320f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ } 103420f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ return ofs; 103520f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ} 103620f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ 1037da3dbb17a0e9a9ec7f5aed95f1fddadb790edc9dTejun Heostatic int mv_scr_read(struct ata_port *ap, unsigned int sc_reg_in, u32 *val) 103820f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ{ 103920f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ unsigned int ofs = mv_scr_offset(sc_reg_in); 104020f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ 1041da3dbb17a0e9a9ec7f5aed95f1fddadb790edc9dTejun Heo if (ofs != 0xffffffffU) { 1042da3dbb17a0e9a9ec7f5aed95f1fddadb790edc9dTejun Heo *val = readl(mv_ap_base(ap) + ofs); 1043da3dbb17a0e9a9ec7f5aed95f1fddadb790edc9dTejun Heo return 0; 1044da3dbb17a0e9a9ec7f5aed95f1fddadb790edc9dTejun Heo } else 1045da3dbb17a0e9a9ec7f5aed95f1fddadb790edc9dTejun Heo return -EINVAL; 104620f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ} 104720f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ 1048da3dbb17a0e9a9ec7f5aed95f1fddadb790edc9dTejun Heostatic int mv_scr_write(struct ata_port *ap, unsigned int sc_reg_in, u32 val) 104920f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ{ 105020f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ unsigned int ofs = mv_scr_offset(sc_reg_in); 105120f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ 1052da3dbb17a0e9a9ec7f5aed95f1fddadb790edc9dTejun Heo if (ofs != 0xffffffffU) { 105320f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ writelfl(val, mv_ap_base(ap) + ofs); 1054da3dbb17a0e9a9ec7f5aed95f1fddadb790edc9dTejun Heo return 0; 1055da3dbb17a0e9a9ec7f5aed95f1fddadb790edc9dTejun Heo } else 1056da3dbb17a0e9a9ec7f5aed95f1fddadb790edc9dTejun Heo return -EINVAL; 105720f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ} 105820f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ 1059f273827e2aadcf2f74a7bdc9ad715a1b20ea7ddaMark Lordstatic void mv6_dev_config(struct ata_device *adev) 1060f273827e2aadcf2f74a7bdc9ad715a1b20ea7ddaMark Lord{ 1061f273827e2aadcf2f74a7bdc9ad715a1b20ea7ddaMark Lord /* 1062f273827e2aadcf2f74a7bdc9ad715a1b20ea7ddaMark Lord * We don't have hob_nsect when doing NCQ commands on Gen-II. 1063f273827e2aadcf2f74a7bdc9ad715a1b20ea7ddaMark Lord * See mv_qc_prep() for more info. 1064f273827e2aadcf2f74a7bdc9ad715a1b20ea7ddaMark Lord */ 1065f273827e2aadcf2f74a7bdc9ad715a1b20ea7ddaMark Lord if (adev->flags & ATA_DFLAG_NCQ) 1066f273827e2aadcf2f74a7bdc9ad715a1b20ea7ddaMark Lord if (adev->max_sectors > ATA_MAX_SECTORS) 1067f273827e2aadcf2f74a7bdc9ad715a1b20ea7ddaMark Lord adev->max_sectors = ATA_MAX_SECTORS; 1068f273827e2aadcf2f74a7bdc9ad715a1b20ea7ddaMark Lord} 1069f273827e2aadcf2f74a7bdc9ad715a1b20ea7ddaMark Lord 1070721091685f853ba4e6c49f26f989db0b1a811250Mark Lordstatic void mv_edma_cfg(struct mv_port_priv *pp, struct mv_host_priv *hpriv, 1071721091685f853ba4e6c49f26f989db0b1a811250Mark Lord void __iomem *port_mmio, int want_ncq) 1072e4e7b89280d1d666e2c09e5ad36cf071796c4c7eJeff Garzik{ 10730c58912e192fc3a4835d772aafa40b72552b819fMark Lord u32 cfg; 1074e4e7b89280d1d666e2c09e5ad36cf071796c4c7eJeff Garzik 1075e4e7b89280d1d666e2c09e5ad36cf071796c4c7eJeff Garzik /* set up non-NCQ EDMA configuration */ 10760c58912e192fc3a4835d772aafa40b72552b819fMark Lord cfg = EDMA_CFG_Q_DEPTH; /* always 0x1f for *all* chips */ 1077e4e7b89280d1d666e2c09e5ad36cf071796c4c7eJeff Garzik 10780c58912e192fc3a4835d772aafa40b72552b819fMark Lord if (IS_GEN_I(hpriv)) 1079e4e7b89280d1d666e2c09e5ad36cf071796c4c7eJeff Garzik cfg |= (1 << 8); /* enab config burst size mask */ 1080e4e7b89280d1d666e2c09e5ad36cf071796c4c7eJeff Garzik 10810c58912e192fc3a4835d772aafa40b72552b819fMark Lord else if (IS_GEN_II(hpriv)) 1082e4e7b89280d1d666e2c09e5ad36cf071796c4c7eJeff Garzik cfg |= EDMA_CFG_RD_BRST_EXT | EDMA_CFG_WR_BUFF_LEN; 1083e4e7b89280d1d666e2c09e5ad36cf071796c4c7eJeff Garzik 1084e4e7b89280d1d666e2c09e5ad36cf071796c4c7eJeff Garzik else if (IS_GEN_IIE(hpriv)) { 1085e728eabea110da90e69c05855e3a11174edb77efJeff Garzik cfg |= (1 << 23); /* do not mask PM field in rx'd FIS */ 1086e728eabea110da90e69c05855e3a11174edb77efJeff Garzik cfg |= (1 << 22); /* enab 4-entry host queue cache */ 1087e4e7b89280d1d666e2c09e5ad36cf071796c4c7eJeff Garzik cfg |= (1 << 18); /* enab early completion */ 1088e728eabea110da90e69c05855e3a11174edb77efJeff Garzik cfg |= (1 << 17); /* enab cut-through (dis stor&forwrd) */ 1089e4e7b89280d1d666e2c09e5ad36cf071796c4c7eJeff Garzik } 1090e4e7b89280d1d666e2c09e5ad36cf071796c4c7eJeff Garzik 1091721091685f853ba4e6c49f26f989db0b1a811250Mark Lord if (want_ncq) { 1092721091685f853ba4e6c49f26f989db0b1a811250Mark Lord cfg |= EDMA_CFG_NCQ; 1093721091685f853ba4e6c49f26f989db0b1a811250Mark Lord pp->pp_flags |= MV_PP_FLAG_NCQ_EN; 1094721091685f853ba4e6c49f26f989db0b1a811250Mark Lord } else 1095721091685f853ba4e6c49f26f989db0b1a811250Mark Lord pp->pp_flags &= ~MV_PP_FLAG_NCQ_EN; 1096721091685f853ba4e6c49f26f989db0b1a811250Mark Lord 1097e4e7b89280d1d666e2c09e5ad36cf071796c4c7eJeff Garzik writelfl(cfg, port_mmio + EDMA_CFG_OFS); 1098e4e7b89280d1d666e2c09e5ad36cf071796c4c7eJeff Garzik} 1099e4e7b89280d1d666e2c09e5ad36cf071796c4c7eJeff Garzik 110005b308e1df6d9d673daedb517969241f41278b52Brett Russ/** 110105b308e1df6d9d673daedb517969241f41278b52Brett Russ * mv_port_start - Port specific init/start routine. 110205b308e1df6d9d673daedb517969241f41278b52Brett Russ * @ap: ATA channel to manipulate 110305b308e1df6d9d673daedb517969241f41278b52Brett Russ * 110405b308e1df6d9d673daedb517969241f41278b52Brett Russ * Allocate and point to DMA memory, init port private memory, 110505b308e1df6d9d673daedb517969241f41278b52Brett Russ * zero indices. 110605b308e1df6d9d673daedb517969241f41278b52Brett Russ * 110705b308e1df6d9d673daedb517969241f41278b52Brett Russ * LOCKING: 110805b308e1df6d9d673daedb517969241f41278b52Brett Russ * Inherited from caller. 110905b308e1df6d9d673daedb517969241f41278b52Brett Russ */ 111031961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russstatic int mv_port_start(struct ata_port *ap) 111131961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ{ 1112cca3974e48607c3775dc73b544a5700b2e37c21aJeff Garzik struct device *dev = ap->host->dev; 1113cca3974e48607c3775dc73b544a5700b2e37c21aJeff Garzik struct mv_host_priv *hpriv = ap->host->private_data; 111431961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ struct mv_port_priv *pp; 111531961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ void __iomem *port_mmio = mv_ap_base(ap); 111631961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ void *mem; 111731961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ dma_addr_t mem_dma; 11180ea9e179f436f153fc19fdaef7abbc1e0da20762Jeff Garzik unsigned long flags; 111924dc5f33ea4b504cfbd23fa159a4cacba8e4d800Tejun Heo int rc; 112031961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ 112124dc5f33ea4b504cfbd23fa159a4cacba8e4d800Tejun Heo pp = devm_kzalloc(dev, sizeof(*pp), GFP_KERNEL); 11226037d6bbdff65eb5a84fe35e140f4da4f7cc103aJeff Garzik if (!pp) 112324dc5f33ea4b504cfbd23fa159a4cacba8e4d800Tejun Heo return -ENOMEM; 112431961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ 112524dc5f33ea4b504cfbd23fa159a4cacba8e4d800Tejun Heo mem = dmam_alloc_coherent(dev, MV_PORT_PRIV_DMA_SZ, &mem_dma, 112624dc5f33ea4b504cfbd23fa159a4cacba8e4d800Tejun Heo GFP_KERNEL); 11276037d6bbdff65eb5a84fe35e140f4da4f7cc103aJeff Garzik if (!mem) 112824dc5f33ea4b504cfbd23fa159a4cacba8e4d800Tejun Heo return -ENOMEM; 112931961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ memset(mem, 0, MV_PORT_PRIV_DMA_SZ); 113031961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ 11316037d6bbdff65eb5a84fe35e140f4da4f7cc103aJeff Garzik rc = ata_pad_alloc(ap, dev); 11326037d6bbdff65eb5a84fe35e140f4da4f7cc103aJeff Garzik if (rc) 113324dc5f33ea4b504cfbd23fa159a4cacba8e4d800Tejun Heo return rc; 11346037d6bbdff65eb5a84fe35e140f4da4f7cc103aJeff Garzik 11358b260248d9e0e8b64bb72fd4dee03ad86984c344Jeff Garzik /* First item in chunk of DMA memory: 113631961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ * 32-slot command request table (CRQB), 32 bytes each in size 113731961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ */ 113831961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ pp->crqb = mem; 113931961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ pp->crqb_dma = mem_dma; 114031961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ mem += MV_CRQB_Q_SZ; 114131961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ mem_dma += MV_CRQB_Q_SZ; 114231961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ 11438b260248d9e0e8b64bb72fd4dee03ad86984c344Jeff Garzik /* Second item: 114431961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ * 32-slot command response table (CRPB), 8 bytes each in size 114531961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ */ 114631961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ pp->crpb = mem; 114731961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ pp->crpb_dma = mem_dma; 114831961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ mem += MV_CRPB_Q_SZ; 114931961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ mem_dma += MV_CRPB_Q_SZ; 115031961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ 115131961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ /* Third item: 115231961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ * Table of scatter-gather descriptors (ePRD), 16 bytes each 115331961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ */ 115431961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ pp->sg_tbl = mem; 115531961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ pp->sg_tbl_dma = mem_dma; 115631961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ 11570ea9e179f436f153fc19fdaef7abbc1e0da20762Jeff Garzik spin_lock_irqsave(&ap->host->lock, flags); 11580ea9e179f436f153fc19fdaef7abbc1e0da20762Jeff Garzik 1159721091685f853ba4e6c49f26f989db0b1a811250Mark Lord mv_edma_cfg(pp, hpriv, port_mmio, 0); 1160e4e7b89280d1d666e2c09e5ad36cf071796c4c7eJeff Garzik 1161c5d3e45a2200a0905dc45b72714726b7aac3aaf1Jeff Garzik mv_set_edma_ptrs(port_mmio, hpriv, pp); 116231961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ 11630ea9e179f436f153fc19fdaef7abbc1e0da20762Jeff Garzik spin_unlock_irqrestore(&ap->host->lock, flags); 11640ea9e179f436f153fc19fdaef7abbc1e0da20762Jeff Garzik 116531961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ /* Don't turn on EDMA here...do it before DMA commands only. Else 116631961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ * we'll be unable to send non-data, PIO, etc due to restricted access 116731961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ * to shadow regs. 116831961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ */ 116931961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ ap->private_data = pp; 117031961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ return 0; 117131961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ} 117231961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ 117305b308e1df6d9d673daedb517969241f41278b52Brett Russ/** 117405b308e1df6d9d673daedb517969241f41278b52Brett Russ * mv_port_stop - Port specific cleanup/stop routine. 117505b308e1df6d9d673daedb517969241f41278b52Brett Russ * @ap: ATA channel to manipulate 117605b308e1df6d9d673daedb517969241f41278b52Brett Russ * 117705b308e1df6d9d673daedb517969241f41278b52Brett Russ * Stop DMA, cleanup port memory. 117805b308e1df6d9d673daedb517969241f41278b52Brett Russ * 117905b308e1df6d9d673daedb517969241f41278b52Brett Russ * LOCKING: 1180cca3974e48607c3775dc73b544a5700b2e37c21aJeff Garzik * This routine uses the host lock to protect the DMA stop. 118105b308e1df6d9d673daedb517969241f41278b52Brett Russ */ 118231961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russstatic void mv_port_stop(struct ata_port *ap) 118331961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ{ 118431961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ mv_stop_dma(ap); 118531961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ} 118631961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ 118705b308e1df6d9d673daedb517969241f41278b52Brett Russ/** 118805b308e1df6d9d673daedb517969241f41278b52Brett Russ * mv_fill_sg - Fill out the Marvell ePRD (scatter gather) entries 118905b308e1df6d9d673daedb517969241f41278b52Brett Russ * @qc: queued command whose SG list to source from 119005b308e1df6d9d673daedb517969241f41278b52Brett Russ * 119105b308e1df6d9d673daedb517969241f41278b52Brett Russ * Populate the SG list and mark the last entry. 119205b308e1df6d9d673daedb517969241f41278b52Brett Russ * 119305b308e1df6d9d673daedb517969241f41278b52Brett Russ * LOCKING: 119405b308e1df6d9d673daedb517969241f41278b52Brett Russ * Inherited from caller. 119505b308e1df6d9d673daedb517969241f41278b52Brett Russ */ 11966c08772e49622e90d39903e7ff0be1a0f463ac86Jeff Garzikstatic void mv_fill_sg(struct ata_queued_cmd *qc) 119731961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ{ 119831961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ struct mv_port_priv *pp = qc->ap->private_data; 1199972c26bdd6b58e7534473c4f7928584578cf43f4Jeff Garzik struct scatterlist *sg; 12003be6cbd73f74b4a3da82cc7d6e1688a4ae595fc7Jeff Garzik struct mv_sg *mv_sg, *last_sg = NULL; 1201ff2aeb1eb64c8a4770a6304f9addbae9f9828646Tejun Heo unsigned int si; 120231961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ 1203d88184fb2348a50f7c34f5d49a901c875b2e0114Jeff Garzik mv_sg = pp->sg_tbl; 1204ff2aeb1eb64c8a4770a6304f9addbae9f9828646Tejun Heo for_each_sg(qc->sg, sg, qc->n_elem, si) { 1205d88184fb2348a50f7c34f5d49a901c875b2e0114Jeff Garzik dma_addr_t addr = sg_dma_address(sg); 1206d88184fb2348a50f7c34f5d49a901c875b2e0114Jeff Garzik u32 sg_len = sg_dma_len(sg); 120722374677d18c5eeefd3a283431d312b8c44fef02Jeff Garzik 12084007b493ee6e4a52c2b618ab8361847fba5bf116Olof Johansson while (sg_len) { 12094007b493ee6e4a52c2b618ab8361847fba5bf116Olof Johansson u32 offset = addr & 0xffff; 12104007b493ee6e4a52c2b618ab8361847fba5bf116Olof Johansson u32 len = sg_len; 121122374677d18c5eeefd3a283431d312b8c44fef02Jeff Garzik 12124007b493ee6e4a52c2b618ab8361847fba5bf116Olof Johansson if ((offset + sg_len > 0x10000)) 12134007b493ee6e4a52c2b618ab8361847fba5bf116Olof Johansson len = 0x10000 - offset; 12144007b493ee6e4a52c2b618ab8361847fba5bf116Olof Johansson 12154007b493ee6e4a52c2b618ab8361847fba5bf116Olof Johansson mv_sg->addr = cpu_to_le32(addr & 0xffffffff); 12164007b493ee6e4a52c2b618ab8361847fba5bf116Olof Johansson mv_sg->addr_hi = cpu_to_le32((addr >> 16) >> 16); 12176c08772e49622e90d39903e7ff0be1a0f463ac86Jeff Garzik mv_sg->flags_size = cpu_to_le32(len & 0xffff); 12184007b493ee6e4a52c2b618ab8361847fba5bf116Olof Johansson 12194007b493ee6e4a52c2b618ab8361847fba5bf116Olof Johansson sg_len -= len; 12204007b493ee6e4a52c2b618ab8361847fba5bf116Olof Johansson addr += len; 12214007b493ee6e4a52c2b618ab8361847fba5bf116Olof Johansson 12223be6cbd73f74b4a3da82cc7d6e1688a4ae595fc7Jeff Garzik last_sg = mv_sg; 12234007b493ee6e4a52c2b618ab8361847fba5bf116Olof Johansson mv_sg++; 12244007b493ee6e4a52c2b618ab8361847fba5bf116Olof Johansson } 122531961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ } 12263be6cbd73f74b4a3da82cc7d6e1688a4ae595fc7Jeff Garzik 12273be6cbd73f74b4a3da82cc7d6e1688a4ae595fc7Jeff Garzik if (likely(last_sg)) 12283be6cbd73f74b4a3da82cc7d6e1688a4ae595fc7Jeff Garzik last_sg->flags_size |= cpu_to_le32(EPRD_FLAG_END_OF_TBL); 122931961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ} 123031961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ 12315796d1c4c89efff823259fda35b08ea66ebf8b23Jeff Garzikstatic void mv_crqb_pack_cmd(__le16 *cmdw, u8 data, u8 addr, unsigned last) 123231961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ{ 1233559eedad7f7764dacca33980127b4615011230e4Mark Lord u16 tmp = data | (addr << CRQB_CMD_ADDR_SHIFT) | CRQB_CMD_CS | 123431961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ (last ? CRQB_CMD_LAST : 0); 1235559eedad7f7764dacca33980127b4615011230e4Mark Lord *cmdw = cpu_to_le16(tmp); 123631961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ} 123731961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ 123805b308e1df6d9d673daedb517969241f41278b52Brett Russ/** 123905b308e1df6d9d673daedb517969241f41278b52Brett Russ * mv_qc_prep - Host specific command preparation. 124005b308e1df6d9d673daedb517969241f41278b52Brett Russ * @qc: queued command to prepare 124105b308e1df6d9d673daedb517969241f41278b52Brett Russ * 124205b308e1df6d9d673daedb517969241f41278b52Brett Russ * This routine simply redirects to the general purpose routine 124305b308e1df6d9d673daedb517969241f41278b52Brett Russ * if command is not DMA. Else, it handles prep of the CRQB 124405b308e1df6d9d673daedb517969241f41278b52Brett Russ * (command request block), does some sanity checking, and calls 124505b308e1df6d9d673daedb517969241f41278b52Brett Russ * the SG load routine. 124605b308e1df6d9d673daedb517969241f41278b52Brett Russ * 124705b308e1df6d9d673daedb517969241f41278b52Brett Russ * LOCKING: 124805b308e1df6d9d673daedb517969241f41278b52Brett Russ * Inherited from caller. 124905b308e1df6d9d673daedb517969241f41278b52Brett Russ */ 125031961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russstatic void mv_qc_prep(struct ata_queued_cmd *qc) 125131961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ{ 125231961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ struct ata_port *ap = qc->ap; 125331961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ struct mv_port_priv *pp = ap->private_data; 1254e14698745dd0de1ddbf5cd0cca4313a90f8c1cc1Mark Lord __le16 *cw; 125531961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ struct ata_taskfile *tf; 125631961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ u16 flags = 0; 1257a6432436c5e14b416f27c8f87c5bf0bc36771f49Mark Lord unsigned in_index; 125831961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ 12592dcb407e61458ded17503d6bd12b8c064965368bJeff Garzik if (qc->tf.protocol != ATA_PROT_DMA) 126031961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ return; 126120f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ 126231961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ /* Fill in command request block 126331961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ */ 1264e4e7b89280d1d666e2c09e5ad36cf071796c4c7eJeff Garzik if (!(qc->tf.flags & ATA_TFLAG_WRITE)) 126531961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ flags |= CRQB_FLAG_READ; 1266beec7dbc6ff003bbc94de62b3323519c878fb2acTejun Heo WARN_ON(MV_MAX_Q_DEPTH <= qc->tag); 126731961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ flags |= qc->tag << CRQB_TAG_SHIFT; 126831961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ 1269bdd4dddee325a7dce3e84cf48201a06aa8508aa4Jeff Garzik /* get current queue index from software */ 1270bdd4dddee325a7dce3e84cf48201a06aa8508aa4Jeff Garzik in_index = pp->req_idx & MV_MAX_Q_DEPTH_MASK; 1271a6432436c5e14b416f27c8f87c5bf0bc36771f49Mark Lord 1272a6432436c5e14b416f27c8f87c5bf0bc36771f49Mark Lord pp->crqb[in_index].sg_addr = 127331961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ cpu_to_le32(pp->sg_tbl_dma & 0xffffffff); 1274a6432436c5e14b416f27c8f87c5bf0bc36771f49Mark Lord pp->crqb[in_index].sg_addr_hi = 127531961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ cpu_to_le32((pp->sg_tbl_dma >> 16) >> 16); 1276a6432436c5e14b416f27c8f87c5bf0bc36771f49Mark Lord pp->crqb[in_index].ctrl_flags = cpu_to_le16(flags); 127731961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ 1278a6432436c5e14b416f27c8f87c5bf0bc36771f49Mark Lord cw = &pp->crqb[in_index].ata_cmd[0]; 127931961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ tf = &qc->tf; 128031961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ 128131961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ /* Sadly, the CRQB cannot accomodate all registers--there are 128231961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ * only 11 bytes...so we must pick and choose required 128331961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ * registers based on the command. So, we drop feature and 128431961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ * hob_feature for [RW] DMA commands, but they are needed for 128531961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ * NCQ. NCQ will drop hob_nsect. 128620f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ */ 128731961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ switch (tf->command) { 128831961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ case ATA_CMD_READ: 128931961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ case ATA_CMD_READ_EXT: 129031961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ case ATA_CMD_WRITE: 129131961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ case ATA_CMD_WRITE_EXT: 1292c15d85c8f3f73b5f20aae7928e25b6996f16b328Jens Axboe case ATA_CMD_WRITE_FUA_EXT: 129331961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ mv_crqb_pack_cmd(cw++, tf->hob_nsect, ATA_REG_NSECT, 0); 129431961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ break; 129531961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ#ifdef LIBATA_NCQ /* FIXME: remove this line when NCQ added */ 129631961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ case ATA_CMD_FPDMA_READ: 129731961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ case ATA_CMD_FPDMA_WRITE: 12988b260248d9e0e8b64bb72fd4dee03ad86984c344Jeff Garzik mv_crqb_pack_cmd(cw++, tf->hob_feature, ATA_REG_FEATURE, 0); 129931961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ mv_crqb_pack_cmd(cw++, tf->feature, ATA_REG_FEATURE, 0); 130031961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ break; 130131961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ#endif /* FIXME: remove this line when NCQ added */ 130231961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ default: 130331961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ /* The only other commands EDMA supports in non-queued and 130431961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ * non-NCQ mode are: [RW] STREAM DMA and W DMA FUA EXT, none 130531961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ * of which are defined/used by Linux. If we get here, this 130631961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ * driver needs work. 130731961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ * 130831961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ * FIXME: modify libata to give qc_prep a return value and 130931961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ * return error here. 131031961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ */ 131131961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ BUG_ON(tf->command); 131231961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ break; 131331961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ } 131431961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ mv_crqb_pack_cmd(cw++, tf->nsect, ATA_REG_NSECT, 0); 131531961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ mv_crqb_pack_cmd(cw++, tf->hob_lbal, ATA_REG_LBAL, 0); 131631961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ mv_crqb_pack_cmd(cw++, tf->lbal, ATA_REG_LBAL, 0); 131731961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ mv_crqb_pack_cmd(cw++, tf->hob_lbam, ATA_REG_LBAM, 0); 131831961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ mv_crqb_pack_cmd(cw++, tf->lbam, ATA_REG_LBAM, 0); 131931961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ mv_crqb_pack_cmd(cw++, tf->hob_lbah, ATA_REG_LBAH, 0); 132031961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ mv_crqb_pack_cmd(cw++, tf->lbah, ATA_REG_LBAH, 0); 132131961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ mv_crqb_pack_cmd(cw++, tf->device, ATA_REG_DEVICE, 0); 132231961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ mv_crqb_pack_cmd(cw++, tf->command, ATA_REG_CMD, 1); /* last */ 132331961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ 1324e4e7b89280d1d666e2c09e5ad36cf071796c4c7eJeff Garzik if (!(qc->flags & ATA_QCFLAG_DMAMAP)) 1325e4e7b89280d1d666e2c09e5ad36cf071796c4c7eJeff Garzik return; 1326e4e7b89280d1d666e2c09e5ad36cf071796c4c7eJeff Garzik mv_fill_sg(qc); 1327e4e7b89280d1d666e2c09e5ad36cf071796c4c7eJeff Garzik} 1328e4e7b89280d1d666e2c09e5ad36cf071796c4c7eJeff Garzik 1329e4e7b89280d1d666e2c09e5ad36cf071796c4c7eJeff Garzik/** 1330e4e7b89280d1d666e2c09e5ad36cf071796c4c7eJeff Garzik * mv_qc_prep_iie - Host specific command preparation. 1331e4e7b89280d1d666e2c09e5ad36cf071796c4c7eJeff Garzik * @qc: queued command to prepare 1332e4e7b89280d1d666e2c09e5ad36cf071796c4c7eJeff Garzik * 1333e4e7b89280d1d666e2c09e5ad36cf071796c4c7eJeff Garzik * This routine simply redirects to the general purpose routine 1334e4e7b89280d1d666e2c09e5ad36cf071796c4c7eJeff Garzik * if command is not DMA. Else, it handles prep of the CRQB 1335e4e7b89280d1d666e2c09e5ad36cf071796c4c7eJeff Garzik * (command request block), does some sanity checking, and calls 1336e4e7b89280d1d666e2c09e5ad36cf071796c4c7eJeff Garzik * the SG load routine. 1337e4e7b89280d1d666e2c09e5ad36cf071796c4c7eJeff Garzik * 1338e4e7b89280d1d666e2c09e5ad36cf071796c4c7eJeff Garzik * LOCKING: 1339e4e7b89280d1d666e2c09e5ad36cf071796c4c7eJeff Garzik * Inherited from caller. 1340e4e7b89280d1d666e2c09e5ad36cf071796c4c7eJeff Garzik */ 1341e4e7b89280d1d666e2c09e5ad36cf071796c4c7eJeff Garzikstatic void mv_qc_prep_iie(struct ata_queued_cmd *qc) 1342e4e7b89280d1d666e2c09e5ad36cf071796c4c7eJeff Garzik{ 1343e4e7b89280d1d666e2c09e5ad36cf071796c4c7eJeff Garzik struct ata_port *ap = qc->ap; 1344e4e7b89280d1d666e2c09e5ad36cf071796c4c7eJeff Garzik struct mv_port_priv *pp = ap->private_data; 1345e4e7b89280d1d666e2c09e5ad36cf071796c4c7eJeff Garzik struct mv_crqb_iie *crqb; 1346e4e7b89280d1d666e2c09e5ad36cf071796c4c7eJeff Garzik struct ata_taskfile *tf; 1347a6432436c5e14b416f27c8f87c5bf0bc36771f49Mark Lord unsigned in_index; 1348e4e7b89280d1d666e2c09e5ad36cf071796c4c7eJeff Garzik u32 flags = 0; 1349e4e7b89280d1d666e2c09e5ad36cf071796c4c7eJeff Garzik 13502dcb407e61458ded17503d6bd12b8c064965368bJeff Garzik if (qc->tf.protocol != ATA_PROT_DMA) 1351e4e7b89280d1d666e2c09e5ad36cf071796c4c7eJeff Garzik return; 1352e4e7b89280d1d666e2c09e5ad36cf071796c4c7eJeff Garzik 1353e4e7b89280d1d666e2c09e5ad36cf071796c4c7eJeff Garzik /* Fill in Gen IIE command request block 1354e4e7b89280d1d666e2c09e5ad36cf071796c4c7eJeff Garzik */ 1355e4e7b89280d1d666e2c09e5ad36cf071796c4c7eJeff Garzik if (!(qc->tf.flags & ATA_TFLAG_WRITE)) 1356e4e7b89280d1d666e2c09e5ad36cf071796c4c7eJeff Garzik flags |= CRQB_FLAG_READ; 1357e4e7b89280d1d666e2c09e5ad36cf071796c4c7eJeff Garzik 1358beec7dbc6ff003bbc94de62b3323519c878fb2acTejun Heo WARN_ON(MV_MAX_Q_DEPTH <= qc->tag); 1359e4e7b89280d1d666e2c09e5ad36cf071796c4c7eJeff Garzik flags |= qc->tag << CRQB_TAG_SHIFT; 13608c0aeb4a483334613336ef895f34cecc0ecbbfa6Mark Lord flags |= qc->tag << CRQB_HOSTQ_SHIFT; 1361e4e7b89280d1d666e2c09e5ad36cf071796c4c7eJeff Garzik 1362bdd4dddee325a7dce3e84cf48201a06aa8508aa4Jeff Garzik /* get current queue index from software */ 1363bdd4dddee325a7dce3e84cf48201a06aa8508aa4Jeff Garzik in_index = pp->req_idx & MV_MAX_Q_DEPTH_MASK; 1364a6432436c5e14b416f27c8f87c5bf0bc36771f49Mark Lord 1365a6432436c5e14b416f27c8f87c5bf0bc36771f49Mark Lord crqb = (struct mv_crqb_iie *) &pp->crqb[in_index]; 1366e4e7b89280d1d666e2c09e5ad36cf071796c4c7eJeff Garzik crqb->addr = cpu_to_le32(pp->sg_tbl_dma & 0xffffffff); 1367e4e7b89280d1d666e2c09e5ad36cf071796c4c7eJeff Garzik crqb->addr_hi = cpu_to_le32((pp->sg_tbl_dma >> 16) >> 16); 1368e4e7b89280d1d666e2c09e5ad36cf071796c4c7eJeff Garzik crqb->flags = cpu_to_le32(flags); 1369e4e7b89280d1d666e2c09e5ad36cf071796c4c7eJeff Garzik 1370e4e7b89280d1d666e2c09e5ad36cf071796c4c7eJeff Garzik tf = &qc->tf; 1371e4e7b89280d1d666e2c09e5ad36cf071796c4c7eJeff Garzik crqb->ata_cmd[0] = cpu_to_le32( 1372e4e7b89280d1d666e2c09e5ad36cf071796c4c7eJeff Garzik (tf->command << 16) | 1373e4e7b89280d1d666e2c09e5ad36cf071796c4c7eJeff Garzik (tf->feature << 24) 1374e4e7b89280d1d666e2c09e5ad36cf071796c4c7eJeff Garzik ); 1375e4e7b89280d1d666e2c09e5ad36cf071796c4c7eJeff Garzik crqb->ata_cmd[1] = cpu_to_le32( 1376e4e7b89280d1d666e2c09e5ad36cf071796c4c7eJeff Garzik (tf->lbal << 0) | 1377e4e7b89280d1d666e2c09e5ad36cf071796c4c7eJeff Garzik (tf->lbam << 8) | 1378e4e7b89280d1d666e2c09e5ad36cf071796c4c7eJeff Garzik (tf->lbah << 16) | 1379e4e7b89280d1d666e2c09e5ad36cf071796c4c7eJeff Garzik (tf->device << 24) 1380e4e7b89280d1d666e2c09e5ad36cf071796c4c7eJeff Garzik ); 1381e4e7b89280d1d666e2c09e5ad36cf071796c4c7eJeff Garzik crqb->ata_cmd[2] = cpu_to_le32( 1382e4e7b89280d1d666e2c09e5ad36cf071796c4c7eJeff Garzik (tf->hob_lbal << 0) | 1383e4e7b89280d1d666e2c09e5ad36cf071796c4c7eJeff Garzik (tf->hob_lbam << 8) | 1384e4e7b89280d1d666e2c09e5ad36cf071796c4c7eJeff Garzik (tf->hob_lbah << 16) | 1385e4e7b89280d1d666e2c09e5ad36cf071796c4c7eJeff Garzik (tf->hob_feature << 24) 1386e4e7b89280d1d666e2c09e5ad36cf071796c4c7eJeff Garzik ); 1387e4e7b89280d1d666e2c09e5ad36cf071796c4c7eJeff Garzik crqb->ata_cmd[3] = cpu_to_le32( 1388e4e7b89280d1d666e2c09e5ad36cf071796c4c7eJeff Garzik (tf->nsect << 0) | 1389e4e7b89280d1d666e2c09e5ad36cf071796c4c7eJeff Garzik (tf->hob_nsect << 8) 1390e4e7b89280d1d666e2c09e5ad36cf071796c4c7eJeff Garzik ); 1391e4e7b89280d1d666e2c09e5ad36cf071796c4c7eJeff Garzik 1392e4e7b89280d1d666e2c09e5ad36cf071796c4c7eJeff Garzik if (!(qc->flags & ATA_QCFLAG_DMAMAP)) 139331961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ return; 139431961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ mv_fill_sg(qc); 139531961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ} 139631961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ 139705b308e1df6d9d673daedb517969241f41278b52Brett Russ/** 139805b308e1df6d9d673daedb517969241f41278b52Brett Russ * mv_qc_issue - Initiate a command to the host 139905b308e1df6d9d673daedb517969241f41278b52Brett Russ * @qc: queued command to start 140005b308e1df6d9d673daedb517969241f41278b52Brett Russ * 140105b308e1df6d9d673daedb517969241f41278b52Brett Russ * This routine simply redirects to the general purpose routine 140205b308e1df6d9d673daedb517969241f41278b52Brett Russ * if command is not DMA. Else, it sanity checks our local 140305b308e1df6d9d673daedb517969241f41278b52Brett Russ * caches of the request producer/consumer indices then enables 140405b308e1df6d9d673daedb517969241f41278b52Brett Russ * DMA and bumps the request producer index. 140505b308e1df6d9d673daedb517969241f41278b52Brett Russ * 140605b308e1df6d9d673daedb517969241f41278b52Brett Russ * LOCKING: 140705b308e1df6d9d673daedb517969241f41278b52Brett Russ * Inherited from caller. 140805b308e1df6d9d673daedb517969241f41278b52Brett Russ */ 14099a3d9eb0177eb10500d49cd283b35576082a522dTejun Heostatic unsigned int mv_qc_issue(struct ata_queued_cmd *qc) 141031961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ{ 1411c5d3e45a2200a0905dc45b72714726b7aac3aaf1Jeff Garzik struct ata_port *ap = qc->ap; 1412c5d3e45a2200a0905dc45b72714726b7aac3aaf1Jeff Garzik void __iomem *port_mmio = mv_ap_base(ap); 1413c5d3e45a2200a0905dc45b72714726b7aac3aaf1Jeff Garzik struct mv_port_priv *pp = ap->private_data; 1414bdd4dddee325a7dce3e84cf48201a06aa8508aa4Jeff Garzik u32 in_index; 141531961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ 1416c5d3e45a2200a0905dc45b72714726b7aac3aaf1Jeff Garzik if (qc->tf.protocol != ATA_PROT_DMA) { 141731961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ /* We're about to send a non-EDMA capable command to the 141831961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ * port. Turn off EDMA so there won't be problems accessing 141931961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ * shadow block, etc registers. 142031961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ */ 14210ea9e179f436f153fc19fdaef7abbc1e0da20762Jeff Garzik __mv_stop_dma(ap); 142231961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ return ata_qc_issue_prot(qc); 142331961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ } 142431961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ 1425721091685f853ba4e6c49f26f989db0b1a811250Mark Lord mv_start_dma(ap, port_mmio, pp, qc->tf.protocol); 1426bdd4dddee325a7dce3e84cf48201a06aa8508aa4Jeff Garzik 1427bdd4dddee325a7dce3e84cf48201a06aa8508aa4Jeff Garzik in_index = pp->req_idx & MV_MAX_Q_DEPTH_MASK; 142831961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ 142931961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ /* until we do queuing, the queue should be empty at this point */ 1430a6432436c5e14b416f27c8f87c5bf0bc36771f49Mark Lord WARN_ON(in_index != ((readl(port_mmio + EDMA_REQ_Q_OUT_PTR_OFS) 1431a6432436c5e14b416f27c8f87c5bf0bc36771f49Mark Lord >> EDMA_REQ_Q_PTR_SHIFT) & MV_MAX_Q_DEPTH_MASK)); 143231961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ 1433bdd4dddee325a7dce3e84cf48201a06aa8508aa4Jeff Garzik pp->req_idx++; 143431961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ 1435bdd4dddee325a7dce3e84cf48201a06aa8508aa4Jeff Garzik in_index = (pp->req_idx & MV_MAX_Q_DEPTH_MASK) << EDMA_REQ_Q_PTR_SHIFT; 143631961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ 143731961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ /* and write the request in pointer to kick the EDMA to life */ 1438bdd4dddee325a7dce3e84cf48201a06aa8508aa4Jeff Garzik writelfl((pp->crqb_dma & EDMA_REQ_Q_BASE_LO_MASK) | in_index, 1439bdd4dddee325a7dce3e84cf48201a06aa8508aa4Jeff Garzik port_mmio + EDMA_REQ_Q_IN_PTR_OFS); 144031961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ 144131961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ return 0; 144231961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ} 144331961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ 144405b308e1df6d9d673daedb517969241f41278b52Brett Russ/** 144505b308e1df6d9d673daedb517969241f41278b52Brett Russ * mv_err_intr - Handle error interrupts on the port 144605b308e1df6d9d673daedb517969241f41278b52Brett Russ * @ap: ATA channel to manipulate 14479b358e305c1d783c8a4ebf00344e95deb9e38f3dMark Lord * @reset_allowed: bool: 0 == don't trigger from reset here 144805b308e1df6d9d673daedb517969241f41278b52Brett Russ * 144905b308e1df6d9d673daedb517969241f41278b52Brett Russ * In most cases, just clear the interrupt and move on. However, 145005b308e1df6d9d673daedb517969241f41278b52Brett Russ * some cases require an eDMA reset, which is done right before 145105b308e1df6d9d673daedb517969241f41278b52Brett Russ * the COMRESET in mv_phy_reset(). The SERR case requires a 145205b308e1df6d9d673daedb517969241f41278b52Brett Russ * clear of pending errors in the SATA SERROR register. Finally, 145305b308e1df6d9d673daedb517969241f41278b52Brett Russ * if the port disabled DMA, update our cached copy to match. 145405b308e1df6d9d673daedb517969241f41278b52Brett Russ * 145505b308e1df6d9d673daedb517969241f41278b52Brett Russ * LOCKING: 145605b308e1df6d9d673daedb517969241f41278b52Brett Russ * Inherited from caller. 145705b308e1df6d9d673daedb517969241f41278b52Brett Russ */ 1458bdd4dddee325a7dce3e84cf48201a06aa8508aa4Jeff Garzikstatic void mv_err_intr(struct ata_port *ap, struct ata_queued_cmd *qc) 145931961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ{ 146031961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ void __iomem *port_mmio = mv_ap_base(ap); 1461bdd4dddee325a7dce3e84cf48201a06aa8508aa4Jeff Garzik u32 edma_err_cause, eh_freeze_mask, serr = 0; 1462bdd4dddee325a7dce3e84cf48201a06aa8508aa4Jeff Garzik struct mv_port_priv *pp = ap->private_data; 1463bdd4dddee325a7dce3e84cf48201a06aa8508aa4Jeff Garzik struct mv_host_priv *hpriv = ap->host->private_data; 1464bdd4dddee325a7dce3e84cf48201a06aa8508aa4Jeff Garzik unsigned int edma_enabled = (pp->pp_flags & MV_PP_FLAG_EDMA_EN); 1465bdd4dddee325a7dce3e84cf48201a06aa8508aa4Jeff Garzik unsigned int action = 0, err_mask = 0; 14669af5c9c97dc9d599281778864c72b385f0c63341Tejun Heo struct ata_eh_info *ehi = &ap->link.eh_info; 146720f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ 1468bdd4dddee325a7dce3e84cf48201a06aa8508aa4Jeff Garzik ata_ehi_clear_desc(ehi); 146920f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ 1470bdd4dddee325a7dce3e84cf48201a06aa8508aa4Jeff Garzik if (!edma_enabled) { 1471bdd4dddee325a7dce3e84cf48201a06aa8508aa4Jeff Garzik /* just a guess: do we need to do this? should we 1472bdd4dddee325a7dce3e84cf48201a06aa8508aa4Jeff Garzik * expand this, and do it in all cases? 1473bdd4dddee325a7dce3e84cf48201a06aa8508aa4Jeff Garzik */ 1474936fd7328657884d5a69a55666c74a55aa83ca27Tejun Heo sata_scr_read(&ap->link, SCR_ERROR, &serr); 1475936fd7328657884d5a69a55666c74a55aa83ca27Tejun Heo sata_scr_write_flush(&ap->link, SCR_ERROR, serr); 147620f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ } 1477bdd4dddee325a7dce3e84cf48201a06aa8508aa4Jeff Garzik 1478bdd4dddee325a7dce3e84cf48201a06aa8508aa4Jeff Garzik edma_err_cause = readl(port_mmio + EDMA_ERR_IRQ_CAUSE_OFS); 1479bdd4dddee325a7dce3e84cf48201a06aa8508aa4Jeff Garzik 1480bdd4dddee325a7dce3e84cf48201a06aa8508aa4Jeff Garzik ata_ehi_push_desc(ehi, "edma_err 0x%08x", edma_err_cause); 1481bdd4dddee325a7dce3e84cf48201a06aa8508aa4Jeff Garzik 1482bdd4dddee325a7dce3e84cf48201a06aa8508aa4Jeff Garzik /* 1483bdd4dddee325a7dce3e84cf48201a06aa8508aa4Jeff Garzik * all generations share these EDMA error cause bits 1484bdd4dddee325a7dce3e84cf48201a06aa8508aa4Jeff Garzik */ 1485bdd4dddee325a7dce3e84cf48201a06aa8508aa4Jeff Garzik 1486bdd4dddee325a7dce3e84cf48201a06aa8508aa4Jeff Garzik if (edma_err_cause & EDMA_ERR_DEV) 1487bdd4dddee325a7dce3e84cf48201a06aa8508aa4Jeff Garzik err_mask |= AC_ERR_DEV; 1488bdd4dddee325a7dce3e84cf48201a06aa8508aa4Jeff Garzik if (edma_err_cause & (EDMA_ERR_D_PAR | EDMA_ERR_PRD_PAR | 14896c1153e00af8de755ec278d873a97c9ce2a72d10Jeff Garzik EDMA_ERR_CRQB_PAR | EDMA_ERR_CRPB_PAR | 1490bdd4dddee325a7dce3e84cf48201a06aa8508aa4Jeff Garzik EDMA_ERR_INTRL_PAR)) { 1491bdd4dddee325a7dce3e84cf48201a06aa8508aa4Jeff Garzik err_mask |= AC_ERR_ATA_BUS; 1492bdd4dddee325a7dce3e84cf48201a06aa8508aa4Jeff Garzik action |= ATA_EH_HARDRESET; 1493b64bbc39f2122a2276578e40144af69ef01decd4Tejun Heo ata_ehi_push_desc(ehi, "parity error"); 1494bdd4dddee325a7dce3e84cf48201a06aa8508aa4Jeff Garzik } 1495bdd4dddee325a7dce3e84cf48201a06aa8508aa4Jeff Garzik if (edma_err_cause & (EDMA_ERR_DEV_DCON | EDMA_ERR_DEV_CON)) { 1496bdd4dddee325a7dce3e84cf48201a06aa8508aa4Jeff Garzik ata_ehi_hotplugged(ehi); 1497bdd4dddee325a7dce3e84cf48201a06aa8508aa4Jeff Garzik ata_ehi_push_desc(ehi, edma_err_cause & EDMA_ERR_DEV_DCON ? 1498b64bbc39f2122a2276578e40144af69ef01decd4Tejun Heo "dev disconnect" : "dev connect"); 14993606a380692cf958355a40fc1aa336800c17baf1Mark Lord action |= ATA_EH_HARDRESET; 1500bdd4dddee325a7dce3e84cf48201a06aa8508aa4Jeff Garzik } 1501bdd4dddee325a7dce3e84cf48201a06aa8508aa4Jeff Garzik 1502ee9ccdf70163ca6408f6965e0fbc65baeac7312cJeff Garzik if (IS_GEN_I(hpriv)) { 1503bdd4dddee325a7dce3e84cf48201a06aa8508aa4Jeff Garzik eh_freeze_mask = EDMA_EH_FREEZE_5; 1504bdd4dddee325a7dce3e84cf48201a06aa8508aa4Jeff Garzik 1505bdd4dddee325a7dce3e84cf48201a06aa8508aa4Jeff Garzik if (edma_err_cause & EDMA_ERR_SELF_DIS_5) { 1506bdd4dddee325a7dce3e84cf48201a06aa8508aa4Jeff Garzik struct mv_port_priv *pp = ap->private_data; 1507bdd4dddee325a7dce3e84cf48201a06aa8508aa4Jeff Garzik pp->pp_flags &= ~MV_PP_FLAG_EDMA_EN; 1508b64bbc39f2122a2276578e40144af69ef01decd4Tejun Heo ata_ehi_push_desc(ehi, "EDMA self-disable"); 1509bdd4dddee325a7dce3e84cf48201a06aa8508aa4Jeff Garzik } 1510bdd4dddee325a7dce3e84cf48201a06aa8508aa4Jeff Garzik } else { 1511bdd4dddee325a7dce3e84cf48201a06aa8508aa4Jeff Garzik eh_freeze_mask = EDMA_EH_FREEZE; 1512bdd4dddee325a7dce3e84cf48201a06aa8508aa4Jeff Garzik 1513bdd4dddee325a7dce3e84cf48201a06aa8508aa4Jeff Garzik if (edma_err_cause & EDMA_ERR_SELF_DIS) { 1514bdd4dddee325a7dce3e84cf48201a06aa8508aa4Jeff Garzik struct mv_port_priv *pp = ap->private_data; 1515bdd4dddee325a7dce3e84cf48201a06aa8508aa4Jeff Garzik pp->pp_flags &= ~MV_PP_FLAG_EDMA_EN; 1516b64bbc39f2122a2276578e40144af69ef01decd4Tejun Heo ata_ehi_push_desc(ehi, "EDMA self-disable"); 1517bdd4dddee325a7dce3e84cf48201a06aa8508aa4Jeff Garzik } 1518bdd4dddee325a7dce3e84cf48201a06aa8508aa4Jeff Garzik 1519bdd4dddee325a7dce3e84cf48201a06aa8508aa4Jeff Garzik if (edma_err_cause & EDMA_ERR_SERR) { 1520936fd7328657884d5a69a55666c74a55aa83ca27Tejun Heo sata_scr_read(&ap->link, SCR_ERROR, &serr); 1521936fd7328657884d5a69a55666c74a55aa83ca27Tejun Heo sata_scr_write_flush(&ap->link, SCR_ERROR, serr); 1522bdd4dddee325a7dce3e84cf48201a06aa8508aa4Jeff Garzik err_mask = AC_ERR_ATA_BUS; 1523bdd4dddee325a7dce3e84cf48201a06aa8508aa4Jeff Garzik action |= ATA_EH_HARDRESET; 1524bdd4dddee325a7dce3e84cf48201a06aa8508aa4Jeff Garzik } 1525afb0edd922c7ed6e73678730921dfcccebec17e8Brett Russ } 152620f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ 152720f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ /* Clear EDMA now that SERR cleanup done */ 15283606a380692cf958355a40fc1aa336800c17baf1Mark Lord writelfl(~edma_err_cause, port_mmio + EDMA_ERR_IRQ_CAUSE_OFS); 152920f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ 1530bdd4dddee325a7dce3e84cf48201a06aa8508aa4Jeff Garzik if (!err_mask) { 1531bdd4dddee325a7dce3e84cf48201a06aa8508aa4Jeff Garzik err_mask = AC_ERR_OTHER; 1532bdd4dddee325a7dce3e84cf48201a06aa8508aa4Jeff Garzik action |= ATA_EH_HARDRESET; 1533bdd4dddee325a7dce3e84cf48201a06aa8508aa4Jeff Garzik } 1534bdd4dddee325a7dce3e84cf48201a06aa8508aa4Jeff Garzik 1535bdd4dddee325a7dce3e84cf48201a06aa8508aa4Jeff Garzik ehi->serror |= serr; 1536bdd4dddee325a7dce3e84cf48201a06aa8508aa4Jeff Garzik ehi->action |= action; 1537bdd4dddee325a7dce3e84cf48201a06aa8508aa4Jeff Garzik 1538bdd4dddee325a7dce3e84cf48201a06aa8508aa4Jeff Garzik if (qc) 1539bdd4dddee325a7dce3e84cf48201a06aa8508aa4Jeff Garzik qc->err_mask |= err_mask; 1540bdd4dddee325a7dce3e84cf48201a06aa8508aa4Jeff Garzik else 1541bdd4dddee325a7dce3e84cf48201a06aa8508aa4Jeff Garzik ehi->err_mask |= err_mask; 1542bdd4dddee325a7dce3e84cf48201a06aa8508aa4Jeff Garzik 1543bdd4dddee325a7dce3e84cf48201a06aa8508aa4Jeff Garzik if (edma_err_cause & eh_freeze_mask) 1544bdd4dddee325a7dce3e84cf48201a06aa8508aa4Jeff Garzik ata_port_freeze(ap); 1545bdd4dddee325a7dce3e84cf48201a06aa8508aa4Jeff Garzik else 1546bdd4dddee325a7dce3e84cf48201a06aa8508aa4Jeff Garzik ata_port_abort(ap); 1547bdd4dddee325a7dce3e84cf48201a06aa8508aa4Jeff Garzik} 1548bdd4dddee325a7dce3e84cf48201a06aa8508aa4Jeff Garzik 1549bdd4dddee325a7dce3e84cf48201a06aa8508aa4Jeff Garzikstatic void mv_intr_pio(struct ata_port *ap) 1550bdd4dddee325a7dce3e84cf48201a06aa8508aa4Jeff Garzik{ 1551bdd4dddee325a7dce3e84cf48201a06aa8508aa4Jeff Garzik struct ata_queued_cmd *qc; 1552bdd4dddee325a7dce3e84cf48201a06aa8508aa4Jeff Garzik u8 ata_status; 1553bdd4dddee325a7dce3e84cf48201a06aa8508aa4Jeff Garzik 1554bdd4dddee325a7dce3e84cf48201a06aa8508aa4Jeff Garzik /* ignore spurious intr if drive still BUSY */ 1555bdd4dddee325a7dce3e84cf48201a06aa8508aa4Jeff Garzik ata_status = readb(ap->ioaddr.status_addr); 1556bdd4dddee325a7dce3e84cf48201a06aa8508aa4Jeff Garzik if (unlikely(ata_status & ATA_BUSY)) 1557bdd4dddee325a7dce3e84cf48201a06aa8508aa4Jeff Garzik return; 1558bdd4dddee325a7dce3e84cf48201a06aa8508aa4Jeff Garzik 1559bdd4dddee325a7dce3e84cf48201a06aa8508aa4Jeff Garzik /* get active ATA command */ 15609af5c9c97dc9d599281778864c72b385f0c63341Tejun Heo qc = ata_qc_from_tag(ap, ap->link.active_tag); 1561bdd4dddee325a7dce3e84cf48201a06aa8508aa4Jeff Garzik if (unlikely(!qc)) /* no active tag */ 1562bdd4dddee325a7dce3e84cf48201a06aa8508aa4Jeff Garzik return; 1563bdd4dddee325a7dce3e84cf48201a06aa8508aa4Jeff Garzik if (qc->tf.flags & ATA_TFLAG_POLLING) /* polling; we don't own qc */ 1564bdd4dddee325a7dce3e84cf48201a06aa8508aa4Jeff Garzik return; 1565bdd4dddee325a7dce3e84cf48201a06aa8508aa4Jeff Garzik 1566bdd4dddee325a7dce3e84cf48201a06aa8508aa4Jeff Garzik /* and finally, complete the ATA command */ 1567bdd4dddee325a7dce3e84cf48201a06aa8508aa4Jeff Garzik qc->err_mask |= ac_err_mask(ata_status); 1568bdd4dddee325a7dce3e84cf48201a06aa8508aa4Jeff Garzik ata_qc_complete(qc); 1569bdd4dddee325a7dce3e84cf48201a06aa8508aa4Jeff Garzik} 1570bdd4dddee325a7dce3e84cf48201a06aa8508aa4Jeff Garzik 1571bdd4dddee325a7dce3e84cf48201a06aa8508aa4Jeff Garzikstatic void mv_intr_edma(struct ata_port *ap) 1572bdd4dddee325a7dce3e84cf48201a06aa8508aa4Jeff Garzik{ 1573bdd4dddee325a7dce3e84cf48201a06aa8508aa4Jeff Garzik void __iomem *port_mmio = mv_ap_base(ap); 1574bdd4dddee325a7dce3e84cf48201a06aa8508aa4Jeff Garzik struct mv_host_priv *hpriv = ap->host->private_data; 1575bdd4dddee325a7dce3e84cf48201a06aa8508aa4Jeff Garzik struct mv_port_priv *pp = ap->private_data; 1576bdd4dddee325a7dce3e84cf48201a06aa8508aa4Jeff Garzik struct ata_queued_cmd *qc; 1577bdd4dddee325a7dce3e84cf48201a06aa8508aa4Jeff Garzik u32 out_index, in_index; 1578bdd4dddee325a7dce3e84cf48201a06aa8508aa4Jeff Garzik bool work_done = false; 1579bdd4dddee325a7dce3e84cf48201a06aa8508aa4Jeff Garzik 1580bdd4dddee325a7dce3e84cf48201a06aa8508aa4Jeff Garzik /* get h/w response queue pointer */ 1581bdd4dddee325a7dce3e84cf48201a06aa8508aa4Jeff Garzik in_index = (readl(port_mmio + EDMA_RSP_Q_IN_PTR_OFS) 1582bdd4dddee325a7dce3e84cf48201a06aa8508aa4Jeff Garzik >> EDMA_RSP_Q_PTR_SHIFT) & MV_MAX_Q_DEPTH_MASK; 1583bdd4dddee325a7dce3e84cf48201a06aa8508aa4Jeff Garzik 1584bdd4dddee325a7dce3e84cf48201a06aa8508aa4Jeff Garzik while (1) { 1585bdd4dddee325a7dce3e84cf48201a06aa8508aa4Jeff Garzik u16 status; 15866c1153e00af8de755ec278d873a97c9ce2a72d10Jeff Garzik unsigned int tag; 1587bdd4dddee325a7dce3e84cf48201a06aa8508aa4Jeff Garzik 1588bdd4dddee325a7dce3e84cf48201a06aa8508aa4Jeff Garzik /* get s/w response queue last-read pointer, and compare */ 1589bdd4dddee325a7dce3e84cf48201a06aa8508aa4Jeff Garzik out_index = pp->resp_idx & MV_MAX_Q_DEPTH_MASK; 1590bdd4dddee325a7dce3e84cf48201a06aa8508aa4Jeff Garzik if (in_index == out_index) 1591bdd4dddee325a7dce3e84cf48201a06aa8508aa4Jeff Garzik break; 1592bdd4dddee325a7dce3e84cf48201a06aa8508aa4Jeff Garzik 1593bdd4dddee325a7dce3e84cf48201a06aa8508aa4Jeff Garzik /* 50xx: get active ATA command */ 15940ea9e179f436f153fc19fdaef7abbc1e0da20762Jeff Garzik if (IS_GEN_I(hpriv)) 15959af5c9c97dc9d599281778864c72b385f0c63341Tejun Heo tag = ap->link.active_tag; 1596bdd4dddee325a7dce3e84cf48201a06aa8508aa4Jeff Garzik 15976c1153e00af8de755ec278d873a97c9ce2a72d10Jeff Garzik /* Gen II/IIE: get active ATA command via tag, to enable 15986c1153e00af8de755ec278d873a97c9ce2a72d10Jeff Garzik * support for queueing. this works transparently for 15996c1153e00af8de755ec278d873a97c9ce2a72d10Jeff Garzik * queued and non-queued modes. 1600bdd4dddee325a7dce3e84cf48201a06aa8508aa4Jeff Garzik */ 16018c0aeb4a483334613336ef895f34cecc0ecbbfa6Mark Lord else 16028c0aeb4a483334613336ef895f34cecc0ecbbfa6Mark Lord tag = le16_to_cpu(pp->crpb[out_index].id) & 0x1f; 1603bdd4dddee325a7dce3e84cf48201a06aa8508aa4Jeff Garzik 16046c1153e00af8de755ec278d873a97c9ce2a72d10Jeff Garzik qc = ata_qc_from_tag(ap, tag); 1605bdd4dddee325a7dce3e84cf48201a06aa8508aa4Jeff Garzik 1606cb92441973ebd71d556fc7cdd9e597582327dd71Mark Lord /* For non-NCQ mode, the lower 8 bits of status 1607cb92441973ebd71d556fc7cdd9e597582327dd71Mark Lord * are from EDMA_ERR_IRQ_CAUSE_OFS, 1608cb92441973ebd71d556fc7cdd9e597582327dd71Mark Lord * which should be zero if all went well. 1609bdd4dddee325a7dce3e84cf48201a06aa8508aa4Jeff Garzik */ 1610bdd4dddee325a7dce3e84cf48201a06aa8508aa4Jeff Garzik status = le16_to_cpu(pp->crpb[out_index].flags); 1611cb92441973ebd71d556fc7cdd9e597582327dd71Mark Lord if ((status & 0xff) && !(pp->pp_flags & MV_PP_FLAG_NCQ_EN)) { 1612bdd4dddee325a7dce3e84cf48201a06aa8508aa4Jeff Garzik mv_err_intr(ap, qc); 1613bdd4dddee325a7dce3e84cf48201a06aa8508aa4Jeff Garzik return; 1614bdd4dddee325a7dce3e84cf48201a06aa8508aa4Jeff Garzik } 1615bdd4dddee325a7dce3e84cf48201a06aa8508aa4Jeff Garzik 1616bdd4dddee325a7dce3e84cf48201a06aa8508aa4Jeff Garzik /* and finally, complete the ATA command */ 1617bdd4dddee325a7dce3e84cf48201a06aa8508aa4Jeff Garzik if (qc) { 1618bdd4dddee325a7dce3e84cf48201a06aa8508aa4Jeff Garzik qc->err_mask |= 1619bdd4dddee325a7dce3e84cf48201a06aa8508aa4Jeff Garzik ac_err_mask(status >> CRPB_FLAG_STATUS_SHIFT); 1620bdd4dddee325a7dce3e84cf48201a06aa8508aa4Jeff Garzik ata_qc_complete(qc); 1621bdd4dddee325a7dce3e84cf48201a06aa8508aa4Jeff Garzik } 1622bdd4dddee325a7dce3e84cf48201a06aa8508aa4Jeff Garzik 16230ea9e179f436f153fc19fdaef7abbc1e0da20762Jeff Garzik /* advance software response queue pointer, to 1624bdd4dddee325a7dce3e84cf48201a06aa8508aa4Jeff Garzik * indicate (after the loop completes) to hardware 1625bdd4dddee325a7dce3e84cf48201a06aa8508aa4Jeff Garzik * that we have consumed a response queue entry. 1626bdd4dddee325a7dce3e84cf48201a06aa8508aa4Jeff Garzik */ 1627bdd4dddee325a7dce3e84cf48201a06aa8508aa4Jeff Garzik work_done = true; 1628bdd4dddee325a7dce3e84cf48201a06aa8508aa4Jeff Garzik pp->resp_idx++; 1629bdd4dddee325a7dce3e84cf48201a06aa8508aa4Jeff Garzik } 1630bdd4dddee325a7dce3e84cf48201a06aa8508aa4Jeff Garzik 1631bdd4dddee325a7dce3e84cf48201a06aa8508aa4Jeff Garzik if (work_done) 1632bdd4dddee325a7dce3e84cf48201a06aa8508aa4Jeff Garzik writelfl((pp->crpb_dma & EDMA_RSP_Q_BASE_LO_MASK) | 1633bdd4dddee325a7dce3e84cf48201a06aa8508aa4Jeff Garzik (out_index << EDMA_RSP_Q_PTR_SHIFT), 1634bdd4dddee325a7dce3e84cf48201a06aa8508aa4Jeff Garzik port_mmio + EDMA_RSP_Q_OUT_PTR_OFS); 163520f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ} 163620f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ 163705b308e1df6d9d673daedb517969241f41278b52Brett Russ/** 163805b308e1df6d9d673daedb517969241f41278b52Brett Russ * mv_host_intr - Handle all interrupts on the given host controller 1639cca3974e48607c3775dc73b544a5700b2e37c21aJeff Garzik * @host: host specific structure 164005b308e1df6d9d673daedb517969241f41278b52Brett Russ * @relevant: port error bits relevant to this host controller 164105b308e1df6d9d673daedb517969241f41278b52Brett Russ * @hc: which host controller we're to look at 164205b308e1df6d9d673daedb517969241f41278b52Brett Russ * 164305b308e1df6d9d673daedb517969241f41278b52Brett Russ * Read then write clear the HC interrupt status then walk each 164405b308e1df6d9d673daedb517969241f41278b52Brett Russ * port connected to the HC and see if it needs servicing. Port 164505b308e1df6d9d673daedb517969241f41278b52Brett Russ * success ints are reported in the HC interrupt status reg, the 164605b308e1df6d9d673daedb517969241f41278b52Brett Russ * port error ints are reported in the higher level main 164705b308e1df6d9d673daedb517969241f41278b52Brett Russ * interrupt status register and thus are passed in via the 164805b308e1df6d9d673daedb517969241f41278b52Brett Russ * 'relevant' argument. 164905b308e1df6d9d673daedb517969241f41278b52Brett Russ * 165005b308e1df6d9d673daedb517969241f41278b52Brett Russ * LOCKING: 165105b308e1df6d9d673daedb517969241f41278b52Brett Russ * Inherited from caller. 165205b308e1df6d9d673daedb517969241f41278b52Brett Russ */ 1653cca3974e48607c3775dc73b544a5700b2e37c21aJeff Garzikstatic void mv_host_intr(struct ata_host *host, u32 relevant, unsigned int hc) 165420f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ{ 16550d5ff566779f894ca9937231a181eb31e4adff0eTejun Heo void __iomem *mmio = host->iomap[MV_PRIMARY_BAR]; 165620f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ void __iomem *hc_mmio = mv_hc_base(mmio, hc); 165720f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ u32 hc_irq_cause; 1658c5d3e45a2200a0905dc45b72714726b7aac3aaf1Jeff Garzik int port, port0; 165920f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ 1660351772658a4d1acc0221a6e30676bb0594e74812Jeff Garzik if (hc == 0) 166120f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ port0 = 0; 1662351772658a4d1acc0221a6e30676bb0594e74812Jeff Garzik else 166320f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ port0 = MV_PORTS_PER_HC; 166420f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ 166520f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ /* we'll need the HC success int register in most cases */ 166620f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ hc_irq_cause = readl(hc_mmio + HC_IRQ_CAUSE_OFS); 1667bdd4dddee325a7dce3e84cf48201a06aa8508aa4Jeff Garzik if (!hc_irq_cause) 1668bdd4dddee325a7dce3e84cf48201a06aa8508aa4Jeff Garzik return; 1669bdd4dddee325a7dce3e84cf48201a06aa8508aa4Jeff Garzik 1670bdd4dddee325a7dce3e84cf48201a06aa8508aa4Jeff Garzik writelfl(~hc_irq_cause, hc_mmio + HC_IRQ_CAUSE_OFS); 167120f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ 167220f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ VPRINTK("ENTER, hc%u relevant=0x%08x HC IRQ cause=0x%08x\n", 16732dcb407e61458ded17503d6bd12b8c064965368bJeff Garzik hc, relevant, hc_irq_cause); 167420f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ 167520f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ for (port = port0; port < port0 + MV_PORTS_PER_HC; port++) { 1676cca3974e48607c3775dc73b544a5700b2e37c21aJeff Garzik struct ata_port *ap = host->ports[port]; 167763af2a5c5990d95f1e7d8795f1425fb976ea2b4bMark Lord struct mv_port_priv *pp = ap->private_data; 1678bdd4dddee325a7dce3e84cf48201a06aa8508aa4Jeff Garzik int have_err_bits, hard_port, shift; 167955d8ca4f8094246da6e71889a4e04bfafaa78b10Jeff Garzik 1680bdd4dddee325a7dce3e84cf48201a06aa8508aa4Jeff Garzik if ((!ap) || (ap->flags & ATA_FLAG_DISABLED)) 1681a2c91a8819e315e9fd1aef3ff57badb6c1be3f80Jeff Garzik continue; 1682a2c91a8819e315e9fd1aef3ff57badb6c1be3f80Jeff Garzik 168331961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ shift = port << 1; /* (port * 2) */ 168420f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ if (port >= MV_PORTS_PER_HC) { 168520f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ shift++; /* skip bit 8 in the HC Main IRQ reg */ 168620f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ } 1687bdd4dddee325a7dce3e84cf48201a06aa8508aa4Jeff Garzik have_err_bits = ((PORT0_ERR << shift) & relevant); 1688bdd4dddee325a7dce3e84cf48201a06aa8508aa4Jeff Garzik 1689bdd4dddee325a7dce3e84cf48201a06aa8508aa4Jeff Garzik if (unlikely(have_err_bits)) { 1690bdd4dddee325a7dce3e84cf48201a06aa8508aa4Jeff Garzik struct ata_queued_cmd *qc; 16918b260248d9e0e8b64bb72fd4dee03ad86984c344Jeff Garzik 16929af5c9c97dc9d599281778864c72b385f0c63341Tejun Heo qc = ata_qc_from_tag(ap, ap->link.active_tag); 1693bdd4dddee325a7dce3e84cf48201a06aa8508aa4Jeff Garzik if (qc && (qc->tf.flags & ATA_TFLAG_POLLING)) 1694bdd4dddee325a7dce3e84cf48201a06aa8508aa4Jeff Garzik continue; 1695bdd4dddee325a7dce3e84cf48201a06aa8508aa4Jeff Garzik 1696bdd4dddee325a7dce3e84cf48201a06aa8508aa4Jeff Garzik mv_err_intr(ap, qc); 1697bdd4dddee325a7dce3e84cf48201a06aa8508aa4Jeff Garzik continue; 1698bdd4dddee325a7dce3e84cf48201a06aa8508aa4Jeff Garzik } 1699bdd4dddee325a7dce3e84cf48201a06aa8508aa4Jeff Garzik 1700bdd4dddee325a7dce3e84cf48201a06aa8508aa4Jeff Garzik hard_port = mv_hardport_from_port(port); /* range 0..3 */ 1701bdd4dddee325a7dce3e84cf48201a06aa8508aa4Jeff Garzik 1702bdd4dddee325a7dce3e84cf48201a06aa8508aa4Jeff Garzik if (pp->pp_flags & MV_PP_FLAG_EDMA_EN) { 1703bdd4dddee325a7dce3e84cf48201a06aa8508aa4Jeff Garzik if ((CRPB_DMA_DONE << hard_port) & hc_irq_cause) 1704bdd4dddee325a7dce3e84cf48201a06aa8508aa4Jeff Garzik mv_intr_edma(ap); 1705bdd4dddee325a7dce3e84cf48201a06aa8508aa4Jeff Garzik } else { 1706bdd4dddee325a7dce3e84cf48201a06aa8508aa4Jeff Garzik if ((DEV_IRQ << hard_port) & hc_irq_cause) 1707bdd4dddee325a7dce3e84cf48201a06aa8508aa4Jeff Garzik mv_intr_pio(ap); 170820f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ } 170920f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ } 171020f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ VPRINTK("EXIT\n"); 171120f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ} 171220f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ 1713bdd4dddee325a7dce3e84cf48201a06aa8508aa4Jeff Garzikstatic void mv_pci_error(struct ata_host *host, void __iomem *mmio) 1714bdd4dddee325a7dce3e84cf48201a06aa8508aa4Jeff Garzik{ 171502a121da5a53d415b6596bc19cc6999d295d32a4Mark Lord struct mv_host_priv *hpriv = host->private_data; 1716bdd4dddee325a7dce3e84cf48201a06aa8508aa4Jeff Garzik struct ata_port *ap; 1717bdd4dddee325a7dce3e84cf48201a06aa8508aa4Jeff Garzik struct ata_queued_cmd *qc; 1718bdd4dddee325a7dce3e84cf48201a06aa8508aa4Jeff Garzik struct ata_eh_info *ehi; 1719bdd4dddee325a7dce3e84cf48201a06aa8508aa4Jeff Garzik unsigned int i, err_mask, printed = 0; 1720bdd4dddee325a7dce3e84cf48201a06aa8508aa4Jeff Garzik u32 err_cause; 1721bdd4dddee325a7dce3e84cf48201a06aa8508aa4Jeff Garzik 172202a121da5a53d415b6596bc19cc6999d295d32a4Mark Lord err_cause = readl(mmio + hpriv->irq_cause_ofs); 1723bdd4dddee325a7dce3e84cf48201a06aa8508aa4Jeff Garzik 1724bdd4dddee325a7dce3e84cf48201a06aa8508aa4Jeff Garzik dev_printk(KERN_ERR, host->dev, "PCI ERROR; PCI IRQ cause=0x%08x\n", 1725bdd4dddee325a7dce3e84cf48201a06aa8508aa4Jeff Garzik err_cause); 1726bdd4dddee325a7dce3e84cf48201a06aa8508aa4Jeff Garzik 1727bdd4dddee325a7dce3e84cf48201a06aa8508aa4Jeff Garzik DPRINTK("All regs @ PCI error\n"); 1728bdd4dddee325a7dce3e84cf48201a06aa8508aa4Jeff Garzik mv_dump_all_regs(mmio, -1, to_pci_dev(host->dev)); 1729bdd4dddee325a7dce3e84cf48201a06aa8508aa4Jeff Garzik 173002a121da5a53d415b6596bc19cc6999d295d32a4Mark Lord writelfl(0, mmio + hpriv->irq_cause_ofs); 1731bdd4dddee325a7dce3e84cf48201a06aa8508aa4Jeff Garzik 1732bdd4dddee325a7dce3e84cf48201a06aa8508aa4Jeff Garzik for (i = 0; i < host->n_ports; i++) { 1733bdd4dddee325a7dce3e84cf48201a06aa8508aa4Jeff Garzik ap = host->ports[i]; 1734936fd7328657884d5a69a55666c74a55aa83ca27Tejun Heo if (!ata_link_offline(&ap->link)) { 17359af5c9c97dc9d599281778864c72b385f0c63341Tejun Heo ehi = &ap->link.eh_info; 1736bdd4dddee325a7dce3e84cf48201a06aa8508aa4Jeff Garzik ata_ehi_clear_desc(ehi); 1737bdd4dddee325a7dce3e84cf48201a06aa8508aa4Jeff Garzik if (!printed++) 1738bdd4dddee325a7dce3e84cf48201a06aa8508aa4Jeff Garzik ata_ehi_push_desc(ehi, 1739bdd4dddee325a7dce3e84cf48201a06aa8508aa4Jeff Garzik "PCI err cause 0x%08x", err_cause); 1740bdd4dddee325a7dce3e84cf48201a06aa8508aa4Jeff Garzik err_mask = AC_ERR_HOST_BUS; 1741bdd4dddee325a7dce3e84cf48201a06aa8508aa4Jeff Garzik ehi->action = ATA_EH_HARDRESET; 17429af5c9c97dc9d599281778864c72b385f0c63341Tejun Heo qc = ata_qc_from_tag(ap, ap->link.active_tag); 1743bdd4dddee325a7dce3e84cf48201a06aa8508aa4Jeff Garzik if (qc) 1744bdd4dddee325a7dce3e84cf48201a06aa8508aa4Jeff Garzik qc->err_mask |= err_mask; 1745bdd4dddee325a7dce3e84cf48201a06aa8508aa4Jeff Garzik else 1746bdd4dddee325a7dce3e84cf48201a06aa8508aa4Jeff Garzik ehi->err_mask |= err_mask; 1747bdd4dddee325a7dce3e84cf48201a06aa8508aa4Jeff Garzik 1748bdd4dddee325a7dce3e84cf48201a06aa8508aa4Jeff Garzik ata_port_freeze(ap); 1749bdd4dddee325a7dce3e84cf48201a06aa8508aa4Jeff Garzik } 1750bdd4dddee325a7dce3e84cf48201a06aa8508aa4Jeff Garzik } 1751bdd4dddee325a7dce3e84cf48201a06aa8508aa4Jeff Garzik} 1752bdd4dddee325a7dce3e84cf48201a06aa8508aa4Jeff Garzik 175305b308e1df6d9d673daedb517969241f41278b52Brett Russ/** 1754c5d3e45a2200a0905dc45b72714726b7aac3aaf1Jeff Garzik * mv_interrupt - Main interrupt event handler 175505b308e1df6d9d673daedb517969241f41278b52Brett Russ * @irq: unused 175605b308e1df6d9d673daedb517969241f41278b52Brett Russ * @dev_instance: private data; in this case the host structure 175705b308e1df6d9d673daedb517969241f41278b52Brett Russ * 175805b308e1df6d9d673daedb517969241f41278b52Brett Russ * Read the read only register to determine if any host 175905b308e1df6d9d673daedb517969241f41278b52Brett Russ * controllers have pending interrupts. If so, call lower level 176005b308e1df6d9d673daedb517969241f41278b52Brett Russ * routine to handle. Also check for PCI errors which are only 176105b308e1df6d9d673daedb517969241f41278b52Brett Russ * reported here. 176205b308e1df6d9d673daedb517969241f41278b52Brett Russ * 17638b260248d9e0e8b64bb72fd4dee03ad86984c344Jeff Garzik * LOCKING: 1764cca3974e48607c3775dc73b544a5700b2e37c21aJeff Garzik * This routine holds the host lock while processing pending 176505b308e1df6d9d673daedb517969241f41278b52Brett Russ * interrupts. 176605b308e1df6d9d673daedb517969241f41278b52Brett Russ */ 17677d12e780e003f93433d49ce78cfedf4b4c52adc5David Howellsstatic irqreturn_t mv_interrupt(int irq, void *dev_instance) 176820f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ{ 1769cca3974e48607c3775dc73b544a5700b2e37c21aJeff Garzik struct ata_host *host = dev_instance; 177020f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ unsigned int hc, handled = 0, n_hcs; 17710d5ff566779f894ca9937231a181eb31e4adff0eTejun Heo void __iomem *mmio = host->iomap[MV_PRIMARY_BAR]; 1772646a4da514f2555298481cb00dc5b3eb02b21b72Mark Lord u32 irq_stat, irq_mask; 177320f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ 1774646a4da514f2555298481cb00dc5b3eb02b21b72Mark Lord spin_lock(&host->lock); 177520f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ irq_stat = readl(mmio + HC_MAIN_IRQ_CAUSE_OFS); 1776646a4da514f2555298481cb00dc5b3eb02b21b72Mark Lord irq_mask = readl(mmio + HC_MAIN_IRQ_MASK_OFS); 177720f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ 177820f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ /* check the cases where we either have nothing pending or have read 177920f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ * a bogus register value which can indicate HW removal or PCI fault 178020f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ */ 1781646a4da514f2555298481cb00dc5b3eb02b21b72Mark Lord if (!(irq_stat & irq_mask) || (0xffffffffU == irq_stat)) 1782646a4da514f2555298481cb00dc5b3eb02b21b72Mark Lord goto out_unlock; 178320f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ 1784cca3974e48607c3775dc73b544a5700b2e37c21aJeff Garzik n_hcs = mv_get_hc_count(host->ports[0]->flags); 178520f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ 1786bdd4dddee325a7dce3e84cf48201a06aa8508aa4Jeff Garzik if (unlikely(irq_stat & PCI_ERR)) { 1787bdd4dddee325a7dce3e84cf48201a06aa8508aa4Jeff Garzik mv_pci_error(host, mmio); 1788bdd4dddee325a7dce3e84cf48201a06aa8508aa4Jeff Garzik handled = 1; 1789bdd4dddee325a7dce3e84cf48201a06aa8508aa4Jeff Garzik goto out_unlock; /* skip all other HC irq handling */ 1790bdd4dddee325a7dce3e84cf48201a06aa8508aa4Jeff Garzik } 1791bdd4dddee325a7dce3e84cf48201a06aa8508aa4Jeff Garzik 179220f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ for (hc = 0; hc < n_hcs; hc++) { 179320f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ u32 relevant = irq_stat & (HC0_IRQ_PEND << (hc * HC_SHIFT)); 179420f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ if (relevant) { 1795cca3974e48607c3775dc73b544a5700b2e37c21aJeff Garzik mv_host_intr(host, relevant, hc); 1796bdd4dddee325a7dce3e84cf48201a06aa8508aa4Jeff Garzik handled = 1; 179720f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ } 179820f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ } 1799615ab95342f6245026d8974b9724f7ea57d9a184Mark Lord 1800bdd4dddee325a7dce3e84cf48201a06aa8508aa4Jeff Garzikout_unlock: 1801cca3974e48607c3775dc73b544a5700b2e37c21aJeff Garzik spin_unlock(&host->lock); 180220f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ 180320f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ return IRQ_RETVAL(handled); 180420f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ} 180520f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ 1806c9d39130123238ac18478a42e25cb7996eacfcc0Jeff Garzikstatic void __iomem *mv5_phy_base(void __iomem *mmio, unsigned int port) 1807c9d39130123238ac18478a42e25cb7996eacfcc0Jeff Garzik{ 1808c9d39130123238ac18478a42e25cb7996eacfcc0Jeff Garzik void __iomem *hc_mmio = mv_hc_base_from_port(mmio, port); 1809c9d39130123238ac18478a42e25cb7996eacfcc0Jeff Garzik unsigned long ofs = (mv_hardport_from_port(port) + 1) * 0x100UL; 1810c9d39130123238ac18478a42e25cb7996eacfcc0Jeff Garzik 1811c9d39130123238ac18478a42e25cb7996eacfcc0Jeff Garzik return hc_mmio + ofs; 1812c9d39130123238ac18478a42e25cb7996eacfcc0Jeff Garzik} 1813c9d39130123238ac18478a42e25cb7996eacfcc0Jeff Garzik 1814c9d39130123238ac18478a42e25cb7996eacfcc0Jeff Garzikstatic unsigned int mv5_scr_offset(unsigned int sc_reg_in) 1815c9d39130123238ac18478a42e25cb7996eacfcc0Jeff Garzik{ 1816c9d39130123238ac18478a42e25cb7996eacfcc0Jeff Garzik unsigned int ofs; 1817c9d39130123238ac18478a42e25cb7996eacfcc0Jeff Garzik 1818c9d39130123238ac18478a42e25cb7996eacfcc0Jeff Garzik switch (sc_reg_in) { 1819c9d39130123238ac18478a42e25cb7996eacfcc0Jeff Garzik case SCR_STATUS: 1820c9d39130123238ac18478a42e25cb7996eacfcc0Jeff Garzik case SCR_ERROR: 1821c9d39130123238ac18478a42e25cb7996eacfcc0Jeff Garzik case SCR_CONTROL: 1822c9d39130123238ac18478a42e25cb7996eacfcc0Jeff Garzik ofs = sc_reg_in * sizeof(u32); 1823c9d39130123238ac18478a42e25cb7996eacfcc0Jeff Garzik break; 1824c9d39130123238ac18478a42e25cb7996eacfcc0Jeff Garzik default: 1825c9d39130123238ac18478a42e25cb7996eacfcc0Jeff Garzik ofs = 0xffffffffU; 1826c9d39130123238ac18478a42e25cb7996eacfcc0Jeff Garzik break; 1827c9d39130123238ac18478a42e25cb7996eacfcc0Jeff Garzik } 1828c9d39130123238ac18478a42e25cb7996eacfcc0Jeff Garzik return ofs; 1829c9d39130123238ac18478a42e25cb7996eacfcc0Jeff Garzik} 1830c9d39130123238ac18478a42e25cb7996eacfcc0Jeff Garzik 1831da3dbb17a0e9a9ec7f5aed95f1fddadb790edc9dTejun Heostatic int mv5_scr_read(struct ata_port *ap, unsigned int sc_reg_in, u32 *val) 1832c9d39130123238ac18478a42e25cb7996eacfcc0Jeff Garzik{ 18330d5ff566779f894ca9937231a181eb31e4adff0eTejun Heo void __iomem *mmio = ap->host->iomap[MV_PRIMARY_BAR]; 18340d5ff566779f894ca9937231a181eb31e4adff0eTejun Heo void __iomem *addr = mv5_phy_base(mmio, ap->port_no); 1835c9d39130123238ac18478a42e25cb7996eacfcc0Jeff Garzik unsigned int ofs = mv5_scr_offset(sc_reg_in); 1836c9d39130123238ac18478a42e25cb7996eacfcc0Jeff Garzik 1837da3dbb17a0e9a9ec7f5aed95f1fddadb790edc9dTejun Heo if (ofs != 0xffffffffU) { 1838da3dbb17a0e9a9ec7f5aed95f1fddadb790edc9dTejun Heo *val = readl(addr + ofs); 1839da3dbb17a0e9a9ec7f5aed95f1fddadb790edc9dTejun Heo return 0; 1840da3dbb17a0e9a9ec7f5aed95f1fddadb790edc9dTejun Heo } else 1841da3dbb17a0e9a9ec7f5aed95f1fddadb790edc9dTejun Heo return -EINVAL; 1842c9d39130123238ac18478a42e25cb7996eacfcc0Jeff Garzik} 1843c9d39130123238ac18478a42e25cb7996eacfcc0Jeff Garzik 1844da3dbb17a0e9a9ec7f5aed95f1fddadb790edc9dTejun Heostatic int mv5_scr_write(struct ata_port *ap, unsigned int sc_reg_in, u32 val) 1845c9d39130123238ac18478a42e25cb7996eacfcc0Jeff Garzik{ 18460d5ff566779f894ca9937231a181eb31e4adff0eTejun Heo void __iomem *mmio = ap->host->iomap[MV_PRIMARY_BAR]; 18470d5ff566779f894ca9937231a181eb31e4adff0eTejun Heo void __iomem *addr = mv5_phy_base(mmio, ap->port_no); 1848c9d39130123238ac18478a42e25cb7996eacfcc0Jeff Garzik unsigned int ofs = mv5_scr_offset(sc_reg_in); 1849c9d39130123238ac18478a42e25cb7996eacfcc0Jeff Garzik 1850da3dbb17a0e9a9ec7f5aed95f1fddadb790edc9dTejun Heo if (ofs != 0xffffffffU) { 18510d5ff566779f894ca9937231a181eb31e4adff0eTejun Heo writelfl(val, addr + ofs); 1852da3dbb17a0e9a9ec7f5aed95f1fddadb790edc9dTejun Heo return 0; 1853da3dbb17a0e9a9ec7f5aed95f1fddadb790edc9dTejun Heo } else 1854da3dbb17a0e9a9ec7f5aed95f1fddadb790edc9dTejun Heo return -EINVAL; 1855c9d39130123238ac18478a42e25cb7996eacfcc0Jeff Garzik} 1856c9d39130123238ac18478a42e25cb7996eacfcc0Jeff Garzik 1857522479fb98c6667f081e75f87e298e413c0b1db8Jeff Garzikstatic void mv5_reset_bus(struct pci_dev *pdev, void __iomem *mmio) 1858522479fb98c6667f081e75f87e298e413c0b1db8Jeff Garzik{ 1859522479fb98c6667f081e75f87e298e413c0b1db8Jeff Garzik int early_5080; 1860522479fb98c6667f081e75f87e298e413c0b1db8Jeff Garzik 186144c10138fd4bbc4b6d6bff0873c24902f2a9da65Auke Kok early_5080 = (pdev->device == 0x5080) && (pdev->revision == 0); 1862522479fb98c6667f081e75f87e298e413c0b1db8Jeff Garzik 1863522479fb98c6667f081e75f87e298e413c0b1db8Jeff Garzik if (!early_5080) { 1864522479fb98c6667f081e75f87e298e413c0b1db8Jeff Garzik u32 tmp = readl(mmio + MV_PCI_EXP_ROM_BAR_CTL); 1865522479fb98c6667f081e75f87e298e413c0b1db8Jeff Garzik tmp |= (1 << 0); 1866522479fb98c6667f081e75f87e298e413c0b1db8Jeff Garzik writel(tmp, mmio + MV_PCI_EXP_ROM_BAR_CTL); 1867522479fb98c6667f081e75f87e298e413c0b1db8Jeff Garzik } 1868522479fb98c6667f081e75f87e298e413c0b1db8Jeff Garzik 1869522479fb98c6667f081e75f87e298e413c0b1db8Jeff Garzik mv_reset_pci_bus(pdev, mmio); 1870522479fb98c6667f081e75f87e298e413c0b1db8Jeff Garzik} 1871522479fb98c6667f081e75f87e298e413c0b1db8Jeff Garzik 1872522479fb98c6667f081e75f87e298e413c0b1db8Jeff Garzikstatic void mv5_reset_flash(struct mv_host_priv *hpriv, void __iomem *mmio) 1873522479fb98c6667f081e75f87e298e413c0b1db8Jeff Garzik{ 1874522479fb98c6667f081e75f87e298e413c0b1db8Jeff Garzik writel(0x0fcfffff, mmio + MV_FLASH_CTL); 1875522479fb98c6667f081e75f87e298e413c0b1db8Jeff Garzik} 1876522479fb98c6667f081e75f87e298e413c0b1db8Jeff Garzik 187747c2b677daeed9c79ecb7167c211ff36876ea611Jeff Garzikstatic void mv5_read_preamp(struct mv_host_priv *hpriv, int idx, 1878ba3fe8fb6a469390a14379519915f3c39a973d99Jeff Garzik void __iomem *mmio) 1879ba3fe8fb6a469390a14379519915f3c39a973d99Jeff Garzik{ 1880c9d39130123238ac18478a42e25cb7996eacfcc0Jeff Garzik void __iomem *phy_mmio = mv5_phy_base(mmio, idx); 1881c9d39130123238ac18478a42e25cb7996eacfcc0Jeff Garzik u32 tmp; 1882c9d39130123238ac18478a42e25cb7996eacfcc0Jeff Garzik 1883c9d39130123238ac18478a42e25cb7996eacfcc0Jeff Garzik tmp = readl(phy_mmio + MV5_PHY_MODE); 1884c9d39130123238ac18478a42e25cb7996eacfcc0Jeff Garzik 1885c9d39130123238ac18478a42e25cb7996eacfcc0Jeff Garzik hpriv->signal[idx].pre = tmp & 0x1800; /* bits 12:11 */ 1886c9d39130123238ac18478a42e25cb7996eacfcc0Jeff Garzik hpriv->signal[idx].amps = tmp & 0xe0; /* bits 7:5 */ 1887ba3fe8fb6a469390a14379519915f3c39a973d99Jeff Garzik} 1888ba3fe8fb6a469390a14379519915f3c39a973d99Jeff Garzik 188947c2b677daeed9c79ecb7167c211ff36876ea611Jeff Garzikstatic void mv5_enable_leds(struct mv_host_priv *hpriv, void __iomem *mmio) 1890ba3fe8fb6a469390a14379519915f3c39a973d99Jeff Garzik{ 1891522479fb98c6667f081e75f87e298e413c0b1db8Jeff Garzik u32 tmp; 1892522479fb98c6667f081e75f87e298e413c0b1db8Jeff Garzik 1893522479fb98c6667f081e75f87e298e413c0b1db8Jeff Garzik writel(0, mmio + MV_GPIO_PORT_CTL); 1894522479fb98c6667f081e75f87e298e413c0b1db8Jeff Garzik 1895522479fb98c6667f081e75f87e298e413c0b1db8Jeff Garzik /* FIXME: handle MV_HP_ERRATA_50XXB2 errata */ 1896522479fb98c6667f081e75f87e298e413c0b1db8Jeff Garzik 1897522479fb98c6667f081e75f87e298e413c0b1db8Jeff Garzik tmp = readl(mmio + MV_PCI_EXP_ROM_BAR_CTL); 1898522479fb98c6667f081e75f87e298e413c0b1db8Jeff Garzik tmp |= ~(1 << 0); 1899522479fb98c6667f081e75f87e298e413c0b1db8Jeff Garzik writel(tmp, mmio + MV_PCI_EXP_ROM_BAR_CTL); 1900ba3fe8fb6a469390a14379519915f3c39a973d99Jeff Garzik} 1901ba3fe8fb6a469390a14379519915f3c39a973d99Jeff Garzik 19022a47ce06d534692f9bd2bf4e90a20fc9b1054c39Jeff Garzikstatic void mv5_phy_errata(struct mv_host_priv *hpriv, void __iomem *mmio, 19032a47ce06d534692f9bd2bf4e90a20fc9b1054c39Jeff Garzik unsigned int port) 1904bca1c4eb9411533d613123618c0d127fae532595Jeff Garzik{ 1905c9d39130123238ac18478a42e25cb7996eacfcc0Jeff Garzik void __iomem *phy_mmio = mv5_phy_base(mmio, port); 1906c9d39130123238ac18478a42e25cb7996eacfcc0Jeff Garzik const u32 mask = (1<<12) | (1<<11) | (1<<7) | (1<<6) | (1<<5); 1907c9d39130123238ac18478a42e25cb7996eacfcc0Jeff Garzik u32 tmp; 1908c9d39130123238ac18478a42e25cb7996eacfcc0Jeff Garzik int fix_apm_sq = (hpriv->hp_flags & MV_HP_ERRATA_50XXB0); 1909c9d39130123238ac18478a42e25cb7996eacfcc0Jeff Garzik 1910c9d39130123238ac18478a42e25cb7996eacfcc0Jeff Garzik if (fix_apm_sq) { 1911c9d39130123238ac18478a42e25cb7996eacfcc0Jeff Garzik tmp = readl(phy_mmio + MV5_LT_MODE); 1912c9d39130123238ac18478a42e25cb7996eacfcc0Jeff Garzik tmp |= (1 << 19); 1913c9d39130123238ac18478a42e25cb7996eacfcc0Jeff Garzik writel(tmp, phy_mmio + MV5_LT_MODE); 1914c9d39130123238ac18478a42e25cb7996eacfcc0Jeff Garzik 1915c9d39130123238ac18478a42e25cb7996eacfcc0Jeff Garzik tmp = readl(phy_mmio + MV5_PHY_CTL); 1916c9d39130123238ac18478a42e25cb7996eacfcc0Jeff Garzik tmp &= ~0x3; 1917c9d39130123238ac18478a42e25cb7996eacfcc0Jeff Garzik tmp |= 0x1; 1918c9d39130123238ac18478a42e25cb7996eacfcc0Jeff Garzik writel(tmp, phy_mmio + MV5_PHY_CTL); 1919c9d39130123238ac18478a42e25cb7996eacfcc0Jeff Garzik } 1920c9d39130123238ac18478a42e25cb7996eacfcc0Jeff Garzik 1921c9d39130123238ac18478a42e25cb7996eacfcc0Jeff Garzik tmp = readl(phy_mmio + MV5_PHY_MODE); 1922c9d39130123238ac18478a42e25cb7996eacfcc0Jeff Garzik tmp &= ~mask; 1923c9d39130123238ac18478a42e25cb7996eacfcc0Jeff Garzik tmp |= hpriv->signal[port].pre; 1924c9d39130123238ac18478a42e25cb7996eacfcc0Jeff Garzik tmp |= hpriv->signal[port].amps; 1925c9d39130123238ac18478a42e25cb7996eacfcc0Jeff Garzik writel(tmp, phy_mmio + MV5_PHY_MODE); 1926bca1c4eb9411533d613123618c0d127fae532595Jeff Garzik} 1927bca1c4eb9411533d613123618c0d127fae532595Jeff Garzik 1928c9d39130123238ac18478a42e25cb7996eacfcc0Jeff Garzik 1929c9d39130123238ac18478a42e25cb7996eacfcc0Jeff Garzik#undef ZERO 1930c9d39130123238ac18478a42e25cb7996eacfcc0Jeff Garzik#define ZERO(reg) writel(0, port_mmio + (reg)) 1931c9d39130123238ac18478a42e25cb7996eacfcc0Jeff Garzikstatic void mv5_reset_hc_port(struct mv_host_priv *hpriv, void __iomem *mmio, 1932c9d39130123238ac18478a42e25cb7996eacfcc0Jeff Garzik unsigned int port) 1933c9d39130123238ac18478a42e25cb7996eacfcc0Jeff Garzik{ 1934c9d39130123238ac18478a42e25cb7996eacfcc0Jeff Garzik void __iomem *port_mmio = mv_port_base(mmio, port); 1935c9d39130123238ac18478a42e25cb7996eacfcc0Jeff Garzik 1936c9d39130123238ac18478a42e25cb7996eacfcc0Jeff Garzik writelfl(EDMA_DS, port_mmio + EDMA_CMD_OFS); 1937c9d39130123238ac18478a42e25cb7996eacfcc0Jeff Garzik 1938c9d39130123238ac18478a42e25cb7996eacfcc0Jeff Garzik mv_channel_reset(hpriv, mmio, port); 1939c9d39130123238ac18478a42e25cb7996eacfcc0Jeff Garzik 1940c9d39130123238ac18478a42e25cb7996eacfcc0Jeff Garzik ZERO(0x028); /* command */ 1941c9d39130123238ac18478a42e25cb7996eacfcc0Jeff Garzik writel(0x11f, port_mmio + EDMA_CFG_OFS); 1942c9d39130123238ac18478a42e25cb7996eacfcc0Jeff Garzik ZERO(0x004); /* timer */ 1943c9d39130123238ac18478a42e25cb7996eacfcc0Jeff Garzik ZERO(0x008); /* irq err cause */ 1944c9d39130123238ac18478a42e25cb7996eacfcc0Jeff Garzik ZERO(0x00c); /* irq err mask */ 1945c9d39130123238ac18478a42e25cb7996eacfcc0Jeff Garzik ZERO(0x010); /* rq bah */ 1946c9d39130123238ac18478a42e25cb7996eacfcc0Jeff Garzik ZERO(0x014); /* rq inp */ 1947c9d39130123238ac18478a42e25cb7996eacfcc0Jeff Garzik ZERO(0x018); /* rq outp */ 1948c9d39130123238ac18478a42e25cb7996eacfcc0Jeff Garzik ZERO(0x01c); /* respq bah */ 1949c9d39130123238ac18478a42e25cb7996eacfcc0Jeff Garzik ZERO(0x024); /* respq outp */ 1950c9d39130123238ac18478a42e25cb7996eacfcc0Jeff Garzik ZERO(0x020); /* respq inp */ 1951c9d39130123238ac18478a42e25cb7996eacfcc0Jeff Garzik ZERO(0x02c); /* test control */ 1952c9d39130123238ac18478a42e25cb7996eacfcc0Jeff Garzik writel(0xbc, port_mmio + EDMA_IORDY_TMOUT); 1953c9d39130123238ac18478a42e25cb7996eacfcc0Jeff Garzik} 1954c9d39130123238ac18478a42e25cb7996eacfcc0Jeff Garzik#undef ZERO 1955c9d39130123238ac18478a42e25cb7996eacfcc0Jeff Garzik 1956c9d39130123238ac18478a42e25cb7996eacfcc0Jeff Garzik#define ZERO(reg) writel(0, hc_mmio + (reg)) 1957c9d39130123238ac18478a42e25cb7996eacfcc0Jeff Garzikstatic void mv5_reset_one_hc(struct mv_host_priv *hpriv, void __iomem *mmio, 1958c9d39130123238ac18478a42e25cb7996eacfcc0Jeff Garzik unsigned int hc) 195947c2b677daeed9c79ecb7167c211ff36876ea611Jeff Garzik{ 1960c9d39130123238ac18478a42e25cb7996eacfcc0Jeff Garzik void __iomem *hc_mmio = mv_hc_base(mmio, hc); 1961c9d39130123238ac18478a42e25cb7996eacfcc0Jeff Garzik u32 tmp; 1962c9d39130123238ac18478a42e25cb7996eacfcc0Jeff Garzik 1963c9d39130123238ac18478a42e25cb7996eacfcc0Jeff Garzik ZERO(0x00c); 1964c9d39130123238ac18478a42e25cb7996eacfcc0Jeff Garzik ZERO(0x010); 1965c9d39130123238ac18478a42e25cb7996eacfcc0Jeff Garzik ZERO(0x014); 1966c9d39130123238ac18478a42e25cb7996eacfcc0Jeff Garzik ZERO(0x018); 1967c9d39130123238ac18478a42e25cb7996eacfcc0Jeff Garzik 1968c9d39130123238ac18478a42e25cb7996eacfcc0Jeff Garzik tmp = readl(hc_mmio + 0x20); 1969c9d39130123238ac18478a42e25cb7996eacfcc0Jeff Garzik tmp &= 0x1c1c1c1c; 1970c9d39130123238ac18478a42e25cb7996eacfcc0Jeff Garzik tmp |= 0x03030303; 1971c9d39130123238ac18478a42e25cb7996eacfcc0Jeff Garzik writel(tmp, hc_mmio + 0x20); 1972c9d39130123238ac18478a42e25cb7996eacfcc0Jeff Garzik} 1973c9d39130123238ac18478a42e25cb7996eacfcc0Jeff Garzik#undef ZERO 1974c9d39130123238ac18478a42e25cb7996eacfcc0Jeff Garzik 1975c9d39130123238ac18478a42e25cb7996eacfcc0Jeff Garzikstatic int mv5_reset_hc(struct mv_host_priv *hpriv, void __iomem *mmio, 1976c9d39130123238ac18478a42e25cb7996eacfcc0Jeff Garzik unsigned int n_hc) 1977c9d39130123238ac18478a42e25cb7996eacfcc0Jeff Garzik{ 1978c9d39130123238ac18478a42e25cb7996eacfcc0Jeff Garzik unsigned int hc, port; 1979c9d39130123238ac18478a42e25cb7996eacfcc0Jeff Garzik 1980c9d39130123238ac18478a42e25cb7996eacfcc0Jeff Garzik for (hc = 0; hc < n_hc; hc++) { 1981c9d39130123238ac18478a42e25cb7996eacfcc0Jeff Garzik for (port = 0; port < MV_PORTS_PER_HC; port++) 1982c9d39130123238ac18478a42e25cb7996eacfcc0Jeff Garzik mv5_reset_hc_port(hpriv, mmio, 1983c9d39130123238ac18478a42e25cb7996eacfcc0Jeff Garzik (hc * MV_PORTS_PER_HC) + port); 1984c9d39130123238ac18478a42e25cb7996eacfcc0Jeff Garzik 1985c9d39130123238ac18478a42e25cb7996eacfcc0Jeff Garzik mv5_reset_one_hc(hpriv, mmio, hc); 1986c9d39130123238ac18478a42e25cb7996eacfcc0Jeff Garzik } 1987c9d39130123238ac18478a42e25cb7996eacfcc0Jeff Garzik 1988c9d39130123238ac18478a42e25cb7996eacfcc0Jeff Garzik return 0; 198947c2b677daeed9c79ecb7167c211ff36876ea611Jeff Garzik} 199047c2b677daeed9c79ecb7167c211ff36876ea611Jeff Garzik 1991101ffae26c23ea928fce6d31a8b4901327d91a15Jeff Garzik#undef ZERO 1992101ffae26c23ea928fce6d31a8b4901327d91a15Jeff Garzik#define ZERO(reg) writel(0, mmio + (reg)) 1993101ffae26c23ea928fce6d31a8b4901327d91a15Jeff Garzikstatic void mv_reset_pci_bus(struct pci_dev *pdev, void __iomem *mmio) 1994101ffae26c23ea928fce6d31a8b4901327d91a15Jeff Garzik{ 199502a121da5a53d415b6596bc19cc6999d295d32a4Mark Lord struct ata_host *host = dev_get_drvdata(&pdev->dev); 199602a121da5a53d415b6596bc19cc6999d295d32a4Mark Lord struct mv_host_priv *hpriv = host->private_data; 1997101ffae26c23ea928fce6d31a8b4901327d91a15Jeff Garzik u32 tmp; 1998101ffae26c23ea928fce6d31a8b4901327d91a15Jeff Garzik 1999101ffae26c23ea928fce6d31a8b4901327d91a15Jeff Garzik tmp = readl(mmio + MV_PCI_MODE); 2000101ffae26c23ea928fce6d31a8b4901327d91a15Jeff Garzik tmp &= 0xff00ffff; 2001101ffae26c23ea928fce6d31a8b4901327d91a15Jeff Garzik writel(tmp, mmio + MV_PCI_MODE); 2002101ffae26c23ea928fce6d31a8b4901327d91a15Jeff Garzik 2003101ffae26c23ea928fce6d31a8b4901327d91a15Jeff Garzik ZERO(MV_PCI_DISC_TIMER); 2004101ffae26c23ea928fce6d31a8b4901327d91a15Jeff Garzik ZERO(MV_PCI_MSI_TRIGGER); 2005101ffae26c23ea928fce6d31a8b4901327d91a15Jeff Garzik writel(0x000100ff, mmio + MV_PCI_XBAR_TMOUT); 2006101ffae26c23ea928fce6d31a8b4901327d91a15Jeff Garzik ZERO(HC_MAIN_IRQ_MASK_OFS); 2007101ffae26c23ea928fce6d31a8b4901327d91a15Jeff Garzik ZERO(MV_PCI_SERR_MASK); 200802a121da5a53d415b6596bc19cc6999d295d32a4Mark Lord ZERO(hpriv->irq_cause_ofs); 200902a121da5a53d415b6596bc19cc6999d295d32a4Mark Lord ZERO(hpriv->irq_mask_ofs); 2010101ffae26c23ea928fce6d31a8b4901327d91a15Jeff Garzik ZERO(MV_PCI_ERR_LOW_ADDRESS); 2011101ffae26c23ea928fce6d31a8b4901327d91a15Jeff Garzik ZERO(MV_PCI_ERR_HIGH_ADDRESS); 2012101ffae26c23ea928fce6d31a8b4901327d91a15Jeff Garzik ZERO(MV_PCI_ERR_ATTRIBUTE); 2013101ffae26c23ea928fce6d31a8b4901327d91a15Jeff Garzik ZERO(MV_PCI_ERR_COMMAND); 2014101ffae26c23ea928fce6d31a8b4901327d91a15Jeff Garzik} 2015101ffae26c23ea928fce6d31a8b4901327d91a15Jeff Garzik#undef ZERO 2016101ffae26c23ea928fce6d31a8b4901327d91a15Jeff Garzik 2017101ffae26c23ea928fce6d31a8b4901327d91a15Jeff Garzikstatic void mv6_reset_flash(struct mv_host_priv *hpriv, void __iomem *mmio) 2018101ffae26c23ea928fce6d31a8b4901327d91a15Jeff Garzik{ 2019101ffae26c23ea928fce6d31a8b4901327d91a15Jeff Garzik u32 tmp; 2020101ffae26c23ea928fce6d31a8b4901327d91a15Jeff Garzik 2021101ffae26c23ea928fce6d31a8b4901327d91a15Jeff Garzik mv5_reset_flash(hpriv, mmio); 2022101ffae26c23ea928fce6d31a8b4901327d91a15Jeff Garzik 2023101ffae26c23ea928fce6d31a8b4901327d91a15Jeff Garzik tmp = readl(mmio + MV_GPIO_PORT_CTL); 2024101ffae26c23ea928fce6d31a8b4901327d91a15Jeff Garzik tmp &= 0x3; 2025101ffae26c23ea928fce6d31a8b4901327d91a15Jeff Garzik tmp |= (1 << 5) | (1 << 6); 2026101ffae26c23ea928fce6d31a8b4901327d91a15Jeff Garzik writel(tmp, mmio + MV_GPIO_PORT_CTL); 2027101ffae26c23ea928fce6d31a8b4901327d91a15Jeff Garzik} 2028101ffae26c23ea928fce6d31a8b4901327d91a15Jeff Garzik 2029101ffae26c23ea928fce6d31a8b4901327d91a15Jeff Garzik/** 2030101ffae26c23ea928fce6d31a8b4901327d91a15Jeff Garzik * mv6_reset_hc - Perform the 6xxx global soft reset 2031101ffae26c23ea928fce6d31a8b4901327d91a15Jeff Garzik * @mmio: base address of the HBA 2032101ffae26c23ea928fce6d31a8b4901327d91a15Jeff Garzik * 2033101ffae26c23ea928fce6d31a8b4901327d91a15Jeff Garzik * This routine only applies to 6xxx parts. 2034101ffae26c23ea928fce6d31a8b4901327d91a15Jeff Garzik * 2035101ffae26c23ea928fce6d31a8b4901327d91a15Jeff Garzik * LOCKING: 2036101ffae26c23ea928fce6d31a8b4901327d91a15Jeff Garzik * Inherited from caller. 2037101ffae26c23ea928fce6d31a8b4901327d91a15Jeff Garzik */ 2038c9d39130123238ac18478a42e25cb7996eacfcc0Jeff Garzikstatic int mv6_reset_hc(struct mv_host_priv *hpriv, void __iomem *mmio, 2039c9d39130123238ac18478a42e25cb7996eacfcc0Jeff Garzik unsigned int n_hc) 2040101ffae26c23ea928fce6d31a8b4901327d91a15Jeff Garzik{ 2041101ffae26c23ea928fce6d31a8b4901327d91a15Jeff Garzik void __iomem *reg = mmio + PCI_MAIN_CMD_STS_OFS; 2042101ffae26c23ea928fce6d31a8b4901327d91a15Jeff Garzik int i, rc = 0; 2043101ffae26c23ea928fce6d31a8b4901327d91a15Jeff Garzik u32 t; 2044101ffae26c23ea928fce6d31a8b4901327d91a15Jeff Garzik 2045101ffae26c23ea928fce6d31a8b4901327d91a15Jeff Garzik /* Following procedure defined in PCI "main command and status 2046101ffae26c23ea928fce6d31a8b4901327d91a15Jeff Garzik * register" table. 2047101ffae26c23ea928fce6d31a8b4901327d91a15Jeff Garzik */ 2048101ffae26c23ea928fce6d31a8b4901327d91a15Jeff Garzik t = readl(reg); 2049101ffae26c23ea928fce6d31a8b4901327d91a15Jeff Garzik writel(t | STOP_PCI_MASTER, reg); 2050101ffae26c23ea928fce6d31a8b4901327d91a15Jeff Garzik 2051101ffae26c23ea928fce6d31a8b4901327d91a15Jeff Garzik for (i = 0; i < 1000; i++) { 2052101ffae26c23ea928fce6d31a8b4901327d91a15Jeff Garzik udelay(1); 2053101ffae26c23ea928fce6d31a8b4901327d91a15Jeff Garzik t = readl(reg); 20542dcb407e61458ded17503d6bd12b8c064965368bJeff Garzik if (PCI_MASTER_EMPTY & t) 2055101ffae26c23ea928fce6d31a8b4901327d91a15Jeff Garzik break; 2056101ffae26c23ea928fce6d31a8b4901327d91a15Jeff Garzik } 2057101ffae26c23ea928fce6d31a8b4901327d91a15Jeff Garzik if (!(PCI_MASTER_EMPTY & t)) { 2058101ffae26c23ea928fce6d31a8b4901327d91a15Jeff Garzik printk(KERN_ERR DRV_NAME ": PCI master won't flush\n"); 2059101ffae26c23ea928fce6d31a8b4901327d91a15Jeff Garzik rc = 1; 2060101ffae26c23ea928fce6d31a8b4901327d91a15Jeff Garzik goto done; 2061101ffae26c23ea928fce6d31a8b4901327d91a15Jeff Garzik } 2062101ffae26c23ea928fce6d31a8b4901327d91a15Jeff Garzik 2063101ffae26c23ea928fce6d31a8b4901327d91a15Jeff Garzik /* set reset */ 2064101ffae26c23ea928fce6d31a8b4901327d91a15Jeff Garzik i = 5; 2065101ffae26c23ea928fce6d31a8b4901327d91a15Jeff Garzik do { 2066101ffae26c23ea928fce6d31a8b4901327d91a15Jeff Garzik writel(t | GLOB_SFT_RST, reg); 2067101ffae26c23ea928fce6d31a8b4901327d91a15Jeff Garzik t = readl(reg); 2068101ffae26c23ea928fce6d31a8b4901327d91a15Jeff Garzik udelay(1); 2069101ffae26c23ea928fce6d31a8b4901327d91a15Jeff Garzik } while (!(GLOB_SFT_RST & t) && (i-- > 0)); 2070101ffae26c23ea928fce6d31a8b4901327d91a15Jeff Garzik 2071101ffae26c23ea928fce6d31a8b4901327d91a15Jeff Garzik if (!(GLOB_SFT_RST & t)) { 2072101ffae26c23ea928fce6d31a8b4901327d91a15Jeff Garzik printk(KERN_ERR DRV_NAME ": can't set global reset\n"); 2073101ffae26c23ea928fce6d31a8b4901327d91a15Jeff Garzik rc = 1; 2074101ffae26c23ea928fce6d31a8b4901327d91a15Jeff Garzik goto done; 2075101ffae26c23ea928fce6d31a8b4901327d91a15Jeff Garzik } 2076101ffae26c23ea928fce6d31a8b4901327d91a15Jeff Garzik 2077101ffae26c23ea928fce6d31a8b4901327d91a15Jeff Garzik /* clear reset and *reenable the PCI master* (not mentioned in spec) */ 2078101ffae26c23ea928fce6d31a8b4901327d91a15Jeff Garzik i = 5; 2079101ffae26c23ea928fce6d31a8b4901327d91a15Jeff Garzik do { 2080101ffae26c23ea928fce6d31a8b4901327d91a15Jeff Garzik writel(t & ~(GLOB_SFT_RST | STOP_PCI_MASTER), reg); 2081101ffae26c23ea928fce6d31a8b4901327d91a15Jeff Garzik t = readl(reg); 2082101ffae26c23ea928fce6d31a8b4901327d91a15Jeff Garzik udelay(1); 2083101ffae26c23ea928fce6d31a8b4901327d91a15Jeff Garzik } while ((GLOB_SFT_RST & t) && (i-- > 0)); 2084101ffae26c23ea928fce6d31a8b4901327d91a15Jeff Garzik 2085101ffae26c23ea928fce6d31a8b4901327d91a15Jeff Garzik if (GLOB_SFT_RST & t) { 2086101ffae26c23ea928fce6d31a8b4901327d91a15Jeff Garzik printk(KERN_ERR DRV_NAME ": can't clear global reset\n"); 2087101ffae26c23ea928fce6d31a8b4901327d91a15Jeff Garzik rc = 1; 2088101ffae26c23ea928fce6d31a8b4901327d91a15Jeff Garzik } 2089101ffae26c23ea928fce6d31a8b4901327d91a15Jeff Garzikdone: 2090101ffae26c23ea928fce6d31a8b4901327d91a15Jeff Garzik return rc; 2091101ffae26c23ea928fce6d31a8b4901327d91a15Jeff Garzik} 2092101ffae26c23ea928fce6d31a8b4901327d91a15Jeff Garzik 209347c2b677daeed9c79ecb7167c211ff36876ea611Jeff Garzikstatic void mv6_read_preamp(struct mv_host_priv *hpriv, int idx, 2094ba3fe8fb6a469390a14379519915f3c39a973d99Jeff Garzik void __iomem *mmio) 2095ba3fe8fb6a469390a14379519915f3c39a973d99Jeff Garzik{ 2096ba3fe8fb6a469390a14379519915f3c39a973d99Jeff Garzik void __iomem *port_mmio; 2097ba3fe8fb6a469390a14379519915f3c39a973d99Jeff Garzik u32 tmp; 2098ba3fe8fb6a469390a14379519915f3c39a973d99Jeff Garzik 2099ba3fe8fb6a469390a14379519915f3c39a973d99Jeff Garzik tmp = readl(mmio + MV_RESET_CFG); 2100ba3fe8fb6a469390a14379519915f3c39a973d99Jeff Garzik if ((tmp & (1 << 0)) == 0) { 210147c2b677daeed9c79ecb7167c211ff36876ea611Jeff Garzik hpriv->signal[idx].amps = 0x7 << 8; 2102ba3fe8fb6a469390a14379519915f3c39a973d99Jeff Garzik hpriv->signal[idx].pre = 0x1 << 5; 2103ba3fe8fb6a469390a14379519915f3c39a973d99Jeff Garzik return; 2104ba3fe8fb6a469390a14379519915f3c39a973d99Jeff Garzik } 2105ba3fe8fb6a469390a14379519915f3c39a973d99Jeff Garzik 2106ba3fe8fb6a469390a14379519915f3c39a973d99Jeff Garzik port_mmio = mv_port_base(mmio, idx); 2107ba3fe8fb6a469390a14379519915f3c39a973d99Jeff Garzik tmp = readl(port_mmio + PHY_MODE2); 2108ba3fe8fb6a469390a14379519915f3c39a973d99Jeff Garzik 2109ba3fe8fb6a469390a14379519915f3c39a973d99Jeff Garzik hpriv->signal[idx].amps = tmp & 0x700; /* bits 10:8 */ 2110ba3fe8fb6a469390a14379519915f3c39a973d99Jeff Garzik hpriv->signal[idx].pre = tmp & 0xe0; /* bits 7:5 */ 2111ba3fe8fb6a469390a14379519915f3c39a973d99Jeff Garzik} 2112ba3fe8fb6a469390a14379519915f3c39a973d99Jeff Garzik 211347c2b677daeed9c79ecb7167c211ff36876ea611Jeff Garzikstatic void mv6_enable_leds(struct mv_host_priv *hpriv, void __iomem *mmio) 2114ba3fe8fb6a469390a14379519915f3c39a973d99Jeff Garzik{ 211547c2b677daeed9c79ecb7167c211ff36876ea611Jeff Garzik writel(0x00000060, mmio + MV_GPIO_PORT_CTL); 2116ba3fe8fb6a469390a14379519915f3c39a973d99Jeff Garzik} 2117ba3fe8fb6a469390a14379519915f3c39a973d99Jeff Garzik 2118c9d39130123238ac18478a42e25cb7996eacfcc0Jeff Garzikstatic void mv6_phy_errata(struct mv_host_priv *hpriv, void __iomem *mmio, 21192a47ce06d534692f9bd2bf4e90a20fc9b1054c39Jeff Garzik unsigned int port) 2120bca1c4eb9411533d613123618c0d127fae532595Jeff Garzik{ 2121c9d39130123238ac18478a42e25cb7996eacfcc0Jeff Garzik void __iomem *port_mmio = mv_port_base(mmio, port); 2122c9d39130123238ac18478a42e25cb7996eacfcc0Jeff Garzik 2123bca1c4eb9411533d613123618c0d127fae532595Jeff Garzik u32 hp_flags = hpriv->hp_flags; 212447c2b677daeed9c79ecb7167c211ff36876ea611Jeff Garzik int fix_phy_mode2 = 212547c2b677daeed9c79ecb7167c211ff36876ea611Jeff Garzik hp_flags & (MV_HP_ERRATA_60X1B2 | MV_HP_ERRATA_60X1C0); 2126bca1c4eb9411533d613123618c0d127fae532595Jeff Garzik int fix_phy_mode4 = 212747c2b677daeed9c79ecb7167c211ff36876ea611Jeff Garzik hp_flags & (MV_HP_ERRATA_60X1B2 | MV_HP_ERRATA_60X1C0); 212847c2b677daeed9c79ecb7167c211ff36876ea611Jeff Garzik u32 m2, tmp; 212947c2b677daeed9c79ecb7167c211ff36876ea611Jeff Garzik 213047c2b677daeed9c79ecb7167c211ff36876ea611Jeff Garzik if (fix_phy_mode2) { 213147c2b677daeed9c79ecb7167c211ff36876ea611Jeff Garzik m2 = readl(port_mmio + PHY_MODE2); 213247c2b677daeed9c79ecb7167c211ff36876ea611Jeff Garzik m2 &= ~(1 << 16); 213347c2b677daeed9c79ecb7167c211ff36876ea611Jeff Garzik m2 |= (1 << 31); 213447c2b677daeed9c79ecb7167c211ff36876ea611Jeff Garzik writel(m2, port_mmio + PHY_MODE2); 213547c2b677daeed9c79ecb7167c211ff36876ea611Jeff Garzik 213647c2b677daeed9c79ecb7167c211ff36876ea611Jeff Garzik udelay(200); 213747c2b677daeed9c79ecb7167c211ff36876ea611Jeff Garzik 213847c2b677daeed9c79ecb7167c211ff36876ea611Jeff Garzik m2 = readl(port_mmio + PHY_MODE2); 213947c2b677daeed9c79ecb7167c211ff36876ea611Jeff Garzik m2 &= ~((1 << 16) | (1 << 31)); 214047c2b677daeed9c79ecb7167c211ff36876ea611Jeff Garzik writel(m2, port_mmio + PHY_MODE2); 214147c2b677daeed9c79ecb7167c211ff36876ea611Jeff Garzik 214247c2b677daeed9c79ecb7167c211ff36876ea611Jeff Garzik udelay(200); 214347c2b677daeed9c79ecb7167c211ff36876ea611Jeff Garzik } 214447c2b677daeed9c79ecb7167c211ff36876ea611Jeff Garzik 214547c2b677daeed9c79ecb7167c211ff36876ea611Jeff Garzik /* who knows what this magic does */ 214647c2b677daeed9c79ecb7167c211ff36876ea611Jeff Garzik tmp = readl(port_mmio + PHY_MODE3); 214747c2b677daeed9c79ecb7167c211ff36876ea611Jeff Garzik tmp &= ~0x7F800000; 214847c2b677daeed9c79ecb7167c211ff36876ea611Jeff Garzik tmp |= 0x2A800000; 214947c2b677daeed9c79ecb7167c211ff36876ea611Jeff Garzik writel(tmp, port_mmio + PHY_MODE3); 2150bca1c4eb9411533d613123618c0d127fae532595Jeff Garzik 2151bca1c4eb9411533d613123618c0d127fae532595Jeff Garzik if (fix_phy_mode4) { 215247c2b677daeed9c79ecb7167c211ff36876ea611Jeff Garzik u32 m4; 2153bca1c4eb9411533d613123618c0d127fae532595Jeff Garzik 2154bca1c4eb9411533d613123618c0d127fae532595Jeff Garzik m4 = readl(port_mmio + PHY_MODE4); 215547c2b677daeed9c79ecb7167c211ff36876ea611Jeff Garzik 215647c2b677daeed9c79ecb7167c211ff36876ea611Jeff Garzik if (hp_flags & MV_HP_ERRATA_60X1B2) 215747c2b677daeed9c79ecb7167c211ff36876ea611Jeff Garzik tmp = readl(port_mmio + 0x310); 2158bca1c4eb9411533d613123618c0d127fae532595Jeff Garzik 2159bca1c4eb9411533d613123618c0d127fae532595Jeff Garzik m4 = (m4 & ~(1 << 1)) | (1 << 0); 2160bca1c4eb9411533d613123618c0d127fae532595Jeff Garzik 2161bca1c4eb9411533d613123618c0d127fae532595Jeff Garzik writel(m4, port_mmio + PHY_MODE4); 216247c2b677daeed9c79ecb7167c211ff36876ea611Jeff Garzik 216347c2b677daeed9c79ecb7167c211ff36876ea611Jeff Garzik if (hp_flags & MV_HP_ERRATA_60X1B2) 216447c2b677daeed9c79ecb7167c211ff36876ea611Jeff Garzik writel(tmp, port_mmio + 0x310); 2165bca1c4eb9411533d613123618c0d127fae532595Jeff Garzik } 2166bca1c4eb9411533d613123618c0d127fae532595Jeff Garzik 2167bca1c4eb9411533d613123618c0d127fae532595Jeff Garzik /* Revert values of pre-emphasis and signal amps to the saved ones */ 2168bca1c4eb9411533d613123618c0d127fae532595Jeff Garzik m2 = readl(port_mmio + PHY_MODE2); 2169bca1c4eb9411533d613123618c0d127fae532595Jeff Garzik 2170bca1c4eb9411533d613123618c0d127fae532595Jeff Garzik m2 &= ~MV_M2_PREAMP_MASK; 21712a47ce06d534692f9bd2bf4e90a20fc9b1054c39Jeff Garzik m2 |= hpriv->signal[port].amps; 21722a47ce06d534692f9bd2bf4e90a20fc9b1054c39Jeff Garzik m2 |= hpriv->signal[port].pre; 217347c2b677daeed9c79ecb7167c211ff36876ea611Jeff Garzik m2 &= ~(1 << 16); 2174bca1c4eb9411533d613123618c0d127fae532595Jeff Garzik 2175e4e7b89280d1d666e2c09e5ad36cf071796c4c7eJeff Garzik /* according to mvSata 3.6.1, some IIE values are fixed */ 2176e4e7b89280d1d666e2c09e5ad36cf071796c4c7eJeff Garzik if (IS_GEN_IIE(hpriv)) { 2177e4e7b89280d1d666e2c09e5ad36cf071796c4c7eJeff Garzik m2 &= ~0xC30FF01F; 2178e4e7b89280d1d666e2c09e5ad36cf071796c4c7eJeff Garzik m2 |= 0x0000900F; 2179e4e7b89280d1d666e2c09e5ad36cf071796c4c7eJeff Garzik } 2180e4e7b89280d1d666e2c09e5ad36cf071796c4c7eJeff Garzik 2181bca1c4eb9411533d613123618c0d127fae532595Jeff Garzik writel(m2, port_mmio + PHY_MODE2); 2182bca1c4eb9411533d613123618c0d127fae532595Jeff Garzik} 2183bca1c4eb9411533d613123618c0d127fae532595Jeff Garzik 2184c9d39130123238ac18478a42e25cb7996eacfcc0Jeff Garzikstatic void mv_channel_reset(struct mv_host_priv *hpriv, void __iomem *mmio, 2185c9d39130123238ac18478a42e25cb7996eacfcc0Jeff Garzik unsigned int port_no) 2186c9d39130123238ac18478a42e25cb7996eacfcc0Jeff Garzik{ 2187c9d39130123238ac18478a42e25cb7996eacfcc0Jeff Garzik void __iomem *port_mmio = mv_port_base(mmio, port_no); 2188c9d39130123238ac18478a42e25cb7996eacfcc0Jeff Garzik 2189c9d39130123238ac18478a42e25cb7996eacfcc0Jeff Garzik writelfl(ATA_RST, port_mmio + EDMA_CMD_OFS); 2190c9d39130123238ac18478a42e25cb7996eacfcc0Jeff Garzik 2191ee9ccdf70163ca6408f6965e0fbc65baeac7312cJeff Garzik if (IS_GEN_II(hpriv)) { 2192c9d39130123238ac18478a42e25cb7996eacfcc0Jeff Garzik u32 ifctl = readl(port_mmio + SATA_INTERFACE_CTL); 2193eb46d684600ac145501805a294c94675e82eab2eMark Lord ifctl |= (1 << 7); /* enable gen2i speed */ 2194eb46d684600ac145501805a294c94675e82eab2eMark Lord ifctl = (ifctl & 0xfff) | 0x9b1000; /* from chip spec */ 2195c9d39130123238ac18478a42e25cb7996eacfcc0Jeff Garzik writelfl(ifctl, port_mmio + SATA_INTERFACE_CTL); 2196c9d39130123238ac18478a42e25cb7996eacfcc0Jeff Garzik } 2197c9d39130123238ac18478a42e25cb7996eacfcc0Jeff Garzik 2198c9d39130123238ac18478a42e25cb7996eacfcc0Jeff Garzik udelay(25); /* allow reset propagation */ 2199c9d39130123238ac18478a42e25cb7996eacfcc0Jeff Garzik 2200c9d39130123238ac18478a42e25cb7996eacfcc0Jeff Garzik /* Spec never mentions clearing the bit. Marvell's driver does 2201c9d39130123238ac18478a42e25cb7996eacfcc0Jeff Garzik * clear the bit, however. 2202c9d39130123238ac18478a42e25cb7996eacfcc0Jeff Garzik */ 2203c9d39130123238ac18478a42e25cb7996eacfcc0Jeff Garzik writelfl(0, port_mmio + EDMA_CMD_OFS); 2204c9d39130123238ac18478a42e25cb7996eacfcc0Jeff Garzik 2205c9d39130123238ac18478a42e25cb7996eacfcc0Jeff Garzik hpriv->ops->phy_errata(hpriv, mmio, port_no); 2206c9d39130123238ac18478a42e25cb7996eacfcc0Jeff Garzik 2207ee9ccdf70163ca6408f6965e0fbc65baeac7312cJeff Garzik if (IS_GEN_I(hpriv)) 2208c9d39130123238ac18478a42e25cb7996eacfcc0Jeff Garzik mdelay(1); 2209c9d39130123238ac18478a42e25cb7996eacfcc0Jeff Garzik} 2210c9d39130123238ac18478a42e25cb7996eacfcc0Jeff Garzik 221105b308e1df6d9d673daedb517969241f41278b52Brett Russ/** 2212bdd4dddee325a7dce3e84cf48201a06aa8508aa4Jeff Garzik * mv_phy_reset - Perform eDMA reset followed by COMRESET 221305b308e1df6d9d673daedb517969241f41278b52Brett Russ * @ap: ATA channel to manipulate 221405b308e1df6d9d673daedb517969241f41278b52Brett Russ * 221505b308e1df6d9d673daedb517969241f41278b52Brett Russ * Part of this is taken from __sata_phy_reset and modified to 221605b308e1df6d9d673daedb517969241f41278b52Brett Russ * not sleep since this routine gets called from interrupt level. 221705b308e1df6d9d673daedb517969241f41278b52Brett Russ * 221805b308e1df6d9d673daedb517969241f41278b52Brett Russ * LOCKING: 221905b308e1df6d9d673daedb517969241f41278b52Brett Russ * Inherited from caller. This is coded to safe to call at 222005b308e1df6d9d673daedb517969241f41278b52Brett Russ * interrupt level, i.e. it does not sleep. 222131961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ */ 2222bdd4dddee325a7dce3e84cf48201a06aa8508aa4Jeff Garzikstatic void mv_phy_reset(struct ata_port *ap, unsigned int *class, 2223bdd4dddee325a7dce3e84cf48201a06aa8508aa4Jeff Garzik unsigned long deadline) 222420f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ{ 2225095fec887eaa1c38d17c0c929a6733c744a9fa1fJeff Garzik struct mv_port_priv *pp = ap->private_data; 2226cca3974e48607c3775dc73b544a5700b2e37c21aJeff Garzik struct mv_host_priv *hpriv = ap->host->private_data; 222720f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ void __iomem *port_mmio = mv_ap_base(ap); 222822374677d18c5eeefd3a283431d312b8c44fef02Jeff Garzik int retry = 5; 222922374677d18c5eeefd3a283431d312b8c44fef02Jeff Garzik u32 sstatus; 223020f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ 223120f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ VPRINTK("ENTER, port %u, mmio 0x%p\n", ap->port_no, port_mmio); 223220f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ 2233da3dbb17a0e9a9ec7f5aed95f1fddadb790edc9dTejun Heo#ifdef DEBUG 2234da3dbb17a0e9a9ec7f5aed95f1fddadb790edc9dTejun Heo { 2235da3dbb17a0e9a9ec7f5aed95f1fddadb790edc9dTejun Heo u32 sstatus, serror, scontrol; 2236da3dbb17a0e9a9ec7f5aed95f1fddadb790edc9dTejun Heo 2237da3dbb17a0e9a9ec7f5aed95f1fddadb790edc9dTejun Heo mv_scr_read(ap, SCR_STATUS, &sstatus); 2238da3dbb17a0e9a9ec7f5aed95f1fddadb790edc9dTejun Heo mv_scr_read(ap, SCR_ERROR, &serror); 2239da3dbb17a0e9a9ec7f5aed95f1fddadb790edc9dTejun Heo mv_scr_read(ap, SCR_CONTROL, &scontrol); 2240da3dbb17a0e9a9ec7f5aed95f1fddadb790edc9dTejun Heo DPRINTK("S-regs after ATA_RST: SStat 0x%08x SErr 0x%08x " 22412d79ab8fd7a7bf3a45d0e948ae27b3dd95ce95eaSaeed Bishara "SCtrl 0x%08x\n", sstatus, serror, scontrol); 2242da3dbb17a0e9a9ec7f5aed95f1fddadb790edc9dTejun Heo } 2243da3dbb17a0e9a9ec7f5aed95f1fddadb790edc9dTejun Heo#endif 224420f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ 224522374677d18c5eeefd3a283431d312b8c44fef02Jeff Garzik /* Issue COMRESET via SControl */ 224622374677d18c5eeefd3a283431d312b8c44fef02Jeff Garzikcomreset_retry: 2247936fd7328657884d5a69a55666c74a55aa83ca27Tejun Heo sata_scr_write_flush(&ap->link, SCR_CONTROL, 0x301); 2248bdd4dddee325a7dce3e84cf48201a06aa8508aa4Jeff Garzik msleep(1); 224922374677d18c5eeefd3a283431d312b8c44fef02Jeff Garzik 2250936fd7328657884d5a69a55666c74a55aa83ca27Tejun Heo sata_scr_write_flush(&ap->link, SCR_CONTROL, 0x300); 2251bdd4dddee325a7dce3e84cf48201a06aa8508aa4Jeff Garzik msleep(20); 225222374677d18c5eeefd3a283431d312b8c44fef02Jeff Garzik 225331961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ do { 2254936fd7328657884d5a69a55666c74a55aa83ca27Tejun Heo sata_scr_read(&ap->link, SCR_STATUS, &sstatus); 225562f1d0e6de138b91d55fbd7d579c837ed62e9e31Andres Salomon if (((sstatus & 0x3) == 3) || ((sstatus & 0x3) == 0)) 225631961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ break; 225722374677d18c5eeefd3a283431d312b8c44fef02Jeff Garzik 2258bdd4dddee325a7dce3e84cf48201a06aa8508aa4Jeff Garzik msleep(1); 2259c5d3e45a2200a0905dc45b72714726b7aac3aaf1Jeff Garzik } while (time_before(jiffies, deadline)); 226020f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ 226122374677d18c5eeefd3a283431d312b8c44fef02Jeff Garzik /* work around errata */ 2262ee9ccdf70163ca6408f6965e0fbc65baeac7312cJeff Garzik if (IS_GEN_II(hpriv) && 226322374677d18c5eeefd3a283431d312b8c44fef02Jeff Garzik (sstatus != 0x0) && (sstatus != 0x113) && (sstatus != 0x123) && 226422374677d18c5eeefd3a283431d312b8c44fef02Jeff Garzik (retry-- > 0)) 226522374677d18c5eeefd3a283431d312b8c44fef02Jeff Garzik goto comreset_retry; 2266095fec887eaa1c38d17c0c929a6733c744a9fa1fJeff Garzik 2267da3dbb17a0e9a9ec7f5aed95f1fddadb790edc9dTejun Heo#ifdef DEBUG 2268da3dbb17a0e9a9ec7f5aed95f1fddadb790edc9dTejun Heo { 2269da3dbb17a0e9a9ec7f5aed95f1fddadb790edc9dTejun Heo u32 sstatus, serror, scontrol; 2270da3dbb17a0e9a9ec7f5aed95f1fddadb790edc9dTejun Heo 2271da3dbb17a0e9a9ec7f5aed95f1fddadb790edc9dTejun Heo mv_scr_read(ap, SCR_STATUS, &sstatus); 2272da3dbb17a0e9a9ec7f5aed95f1fddadb790edc9dTejun Heo mv_scr_read(ap, SCR_ERROR, &serror); 2273da3dbb17a0e9a9ec7f5aed95f1fddadb790edc9dTejun Heo mv_scr_read(ap, SCR_CONTROL, &scontrol); 2274da3dbb17a0e9a9ec7f5aed95f1fddadb790edc9dTejun Heo DPRINTK("S-regs after PHY wake: SStat 0x%08x SErr 0x%08x " 2275da3dbb17a0e9a9ec7f5aed95f1fddadb790edc9dTejun Heo "SCtrl 0x%08x\n", sstatus, serror, scontrol); 2276da3dbb17a0e9a9ec7f5aed95f1fddadb790edc9dTejun Heo } 2277da3dbb17a0e9a9ec7f5aed95f1fddadb790edc9dTejun Heo#endif 227831961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ 2279936fd7328657884d5a69a55666c74a55aa83ca27Tejun Heo if (ata_link_offline(&ap->link)) { 2280bdd4dddee325a7dce3e84cf48201a06aa8508aa4Jeff Garzik *class = ATA_DEV_NONE; 228120f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ return; 228220f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ } 228320f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ 228422374677d18c5eeefd3a283431d312b8c44fef02Jeff Garzik /* even after SStatus reflects that device is ready, 228522374677d18c5eeefd3a283431d312b8c44fef02Jeff Garzik * it seems to take a while for link to be fully 228622374677d18c5eeefd3a283431d312b8c44fef02Jeff Garzik * established (and thus Status no longer 0x80/0x7F), 228722374677d18c5eeefd3a283431d312b8c44fef02Jeff Garzik * so we poll a bit for that, here. 228822374677d18c5eeefd3a283431d312b8c44fef02Jeff Garzik */ 228922374677d18c5eeefd3a283431d312b8c44fef02Jeff Garzik retry = 20; 229022374677d18c5eeefd3a283431d312b8c44fef02Jeff Garzik while (1) { 229122374677d18c5eeefd3a283431d312b8c44fef02Jeff Garzik u8 drv_stat = ata_check_status(ap); 229222374677d18c5eeefd3a283431d312b8c44fef02Jeff Garzik if ((drv_stat != 0x80) && (drv_stat != 0x7f)) 229322374677d18c5eeefd3a283431d312b8c44fef02Jeff Garzik break; 2294bdd4dddee325a7dce3e84cf48201a06aa8508aa4Jeff Garzik msleep(500); 229522374677d18c5eeefd3a283431d312b8c44fef02Jeff Garzik if (retry-- <= 0) 229622374677d18c5eeefd3a283431d312b8c44fef02Jeff Garzik break; 2297bdd4dddee325a7dce3e84cf48201a06aa8508aa4Jeff Garzik if (time_after(jiffies, deadline)) 2298bdd4dddee325a7dce3e84cf48201a06aa8508aa4Jeff Garzik break; 229922374677d18c5eeefd3a283431d312b8c44fef02Jeff Garzik } 230022374677d18c5eeefd3a283431d312b8c44fef02Jeff Garzik 2301bdd4dddee325a7dce3e84cf48201a06aa8508aa4Jeff Garzik /* FIXME: if we passed the deadline, the following 2302bdd4dddee325a7dce3e84cf48201a06aa8508aa4Jeff Garzik * code probably produces an invalid result 2303bdd4dddee325a7dce3e84cf48201a06aa8508aa4Jeff Garzik */ 230420f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ 2305bdd4dddee325a7dce3e84cf48201a06aa8508aa4Jeff Garzik /* finally, read device signature from TF registers */ 23063f19859ee95a38c066a0420eb8a30c76ecd67a42Tejun Heo *class = ata_dev_try_classify(ap->link.device, 1, NULL); 2307095fec887eaa1c38d17c0c929a6733c744a9fa1fJeff Garzik 2308095fec887eaa1c38d17c0c929a6733c744a9fa1fJeff Garzik writelfl(0, port_mmio + EDMA_ERR_IRQ_CAUSE_OFS); 2309095fec887eaa1c38d17c0c929a6733c744a9fa1fJeff Garzik 2310bdd4dddee325a7dce3e84cf48201a06aa8508aa4Jeff Garzik WARN_ON(pp->pp_flags & MV_PP_FLAG_EDMA_EN); 2311095fec887eaa1c38d17c0c929a6733c744a9fa1fJeff Garzik 2312bca1c4eb9411533d613123618c0d127fae532595Jeff Garzik VPRINTK("EXIT\n"); 231320f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ} 231420f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ 2315cc0680a580b5be81a1ca321b58f8e9b80b5c1052Tejun Heostatic int mv_prereset(struct ata_link *link, unsigned long deadline) 231622374677d18c5eeefd3a283431d312b8c44fef02Jeff Garzik{ 2317cc0680a580b5be81a1ca321b58f8e9b80b5c1052Tejun Heo struct ata_port *ap = link->ap; 2318bdd4dddee325a7dce3e84cf48201a06aa8508aa4Jeff Garzik struct mv_port_priv *pp = ap->private_data; 2319cc0680a580b5be81a1ca321b58f8e9b80b5c1052Tejun Heo struct ata_eh_context *ehc = &link->eh_context; 2320bdd4dddee325a7dce3e84cf48201a06aa8508aa4Jeff Garzik int rc; 23210ea9e179f436f153fc19fdaef7abbc1e0da20762Jeff Garzik 2322bdd4dddee325a7dce3e84cf48201a06aa8508aa4Jeff Garzik rc = mv_stop_dma(ap); 2323bdd4dddee325a7dce3e84cf48201a06aa8508aa4Jeff Garzik if (rc) 2324bdd4dddee325a7dce3e84cf48201a06aa8508aa4Jeff Garzik ehc->i.action |= ATA_EH_HARDRESET; 2325bdd4dddee325a7dce3e84cf48201a06aa8508aa4Jeff Garzik 2326bdd4dddee325a7dce3e84cf48201a06aa8508aa4Jeff Garzik if (!(pp->pp_flags & MV_PP_FLAG_HAD_A_RESET)) { 2327bdd4dddee325a7dce3e84cf48201a06aa8508aa4Jeff Garzik pp->pp_flags |= MV_PP_FLAG_HAD_A_RESET; 2328bdd4dddee325a7dce3e84cf48201a06aa8508aa4Jeff Garzik ehc->i.action |= ATA_EH_HARDRESET; 2329bdd4dddee325a7dce3e84cf48201a06aa8508aa4Jeff Garzik } 2330bdd4dddee325a7dce3e84cf48201a06aa8508aa4Jeff Garzik 2331bdd4dddee325a7dce3e84cf48201a06aa8508aa4Jeff Garzik /* if we're about to do hardreset, nothing more to do */ 2332bdd4dddee325a7dce3e84cf48201a06aa8508aa4Jeff Garzik if (ehc->i.action & ATA_EH_HARDRESET) 2333bdd4dddee325a7dce3e84cf48201a06aa8508aa4Jeff Garzik return 0; 2334bdd4dddee325a7dce3e84cf48201a06aa8508aa4Jeff Garzik 2335cc0680a580b5be81a1ca321b58f8e9b80b5c1052Tejun Heo if (ata_link_online(link)) 2336bdd4dddee325a7dce3e84cf48201a06aa8508aa4Jeff Garzik rc = ata_wait_ready(ap, deadline); 2337bdd4dddee325a7dce3e84cf48201a06aa8508aa4Jeff Garzik else 2338bdd4dddee325a7dce3e84cf48201a06aa8508aa4Jeff Garzik rc = -ENODEV; 2339bdd4dddee325a7dce3e84cf48201a06aa8508aa4Jeff Garzik 2340bdd4dddee325a7dce3e84cf48201a06aa8508aa4Jeff Garzik return rc; 234122374677d18c5eeefd3a283431d312b8c44fef02Jeff Garzik} 234222374677d18c5eeefd3a283431d312b8c44fef02Jeff Garzik 2343cc0680a580b5be81a1ca321b58f8e9b80b5c1052Tejun Heostatic int mv_hardreset(struct ata_link *link, unsigned int *class, 2344bdd4dddee325a7dce3e84cf48201a06aa8508aa4Jeff Garzik unsigned long deadline) 234531961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ{ 2346cc0680a580b5be81a1ca321b58f8e9b80b5c1052Tejun Heo struct ata_port *ap = link->ap; 2347bdd4dddee325a7dce3e84cf48201a06aa8508aa4Jeff Garzik struct mv_host_priv *hpriv = ap->host->private_data; 23480d5ff566779f894ca9937231a181eb31e4adff0eTejun Heo void __iomem *mmio = ap->host->iomap[MV_PRIMARY_BAR]; 234931961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ 2350bdd4dddee325a7dce3e84cf48201a06aa8508aa4Jeff Garzik mv_stop_dma(ap); 235131961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ 2352bdd4dddee325a7dce3e84cf48201a06aa8508aa4Jeff Garzik mv_channel_reset(hpriv, mmio, ap->port_no); 235331961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ 2354bdd4dddee325a7dce3e84cf48201a06aa8508aa4Jeff Garzik mv_phy_reset(ap, class, deadline); 2355bdd4dddee325a7dce3e84cf48201a06aa8508aa4Jeff Garzik 2356bdd4dddee325a7dce3e84cf48201a06aa8508aa4Jeff Garzik return 0; 2357bdd4dddee325a7dce3e84cf48201a06aa8508aa4Jeff Garzik} 2358bdd4dddee325a7dce3e84cf48201a06aa8508aa4Jeff Garzik 2359cc0680a580b5be81a1ca321b58f8e9b80b5c1052Tejun Heostatic void mv_postreset(struct ata_link *link, unsigned int *classes) 2360bdd4dddee325a7dce3e84cf48201a06aa8508aa4Jeff Garzik{ 2361cc0680a580b5be81a1ca321b58f8e9b80b5c1052Tejun Heo struct ata_port *ap = link->ap; 2362bdd4dddee325a7dce3e84cf48201a06aa8508aa4Jeff Garzik u32 serr; 2363bdd4dddee325a7dce3e84cf48201a06aa8508aa4Jeff Garzik 2364bdd4dddee325a7dce3e84cf48201a06aa8508aa4Jeff Garzik /* print link status */ 2365cc0680a580b5be81a1ca321b58f8e9b80b5c1052Tejun Heo sata_print_link_status(link); 236631961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ 2367bdd4dddee325a7dce3e84cf48201a06aa8508aa4Jeff Garzik /* clear SError */ 2368cc0680a580b5be81a1ca321b58f8e9b80b5c1052Tejun Heo sata_scr_read(link, SCR_ERROR, &serr); 2369cc0680a580b5be81a1ca321b58f8e9b80b5c1052Tejun Heo sata_scr_write_flush(link, SCR_ERROR, serr); 2370bdd4dddee325a7dce3e84cf48201a06aa8508aa4Jeff Garzik 2371bdd4dddee325a7dce3e84cf48201a06aa8508aa4Jeff Garzik /* bail out if no device is present */ 2372bdd4dddee325a7dce3e84cf48201a06aa8508aa4Jeff Garzik if (classes[0] == ATA_DEV_NONE && classes[1] == ATA_DEV_NONE) { 2373bdd4dddee325a7dce3e84cf48201a06aa8508aa4Jeff Garzik DPRINTK("EXIT, no device\n"); 2374bdd4dddee325a7dce3e84cf48201a06aa8508aa4Jeff Garzik return; 23759b358e305c1d783c8a4ebf00344e95deb9e38f3dMark Lord } 2376bdd4dddee325a7dce3e84cf48201a06aa8508aa4Jeff Garzik 2377bdd4dddee325a7dce3e84cf48201a06aa8508aa4Jeff Garzik /* set up device control */ 2378bdd4dddee325a7dce3e84cf48201a06aa8508aa4Jeff Garzik iowrite8(ap->ctl, ap->ioaddr.ctl_addr); 2379bdd4dddee325a7dce3e84cf48201a06aa8508aa4Jeff Garzik} 2380bdd4dddee325a7dce3e84cf48201a06aa8508aa4Jeff Garzik 2381bdd4dddee325a7dce3e84cf48201a06aa8508aa4Jeff Garzikstatic void mv_error_handler(struct ata_port *ap) 2382bdd4dddee325a7dce3e84cf48201a06aa8508aa4Jeff Garzik{ 2383bdd4dddee325a7dce3e84cf48201a06aa8508aa4Jeff Garzik ata_do_eh(ap, mv_prereset, ata_std_softreset, 2384bdd4dddee325a7dce3e84cf48201a06aa8508aa4Jeff Garzik mv_hardreset, mv_postreset); 2385bdd4dddee325a7dce3e84cf48201a06aa8508aa4Jeff Garzik} 2386bdd4dddee325a7dce3e84cf48201a06aa8508aa4Jeff Garzik 2387bdd4dddee325a7dce3e84cf48201a06aa8508aa4Jeff Garzikstatic void mv_post_int_cmd(struct ata_queued_cmd *qc) 2388bdd4dddee325a7dce3e84cf48201a06aa8508aa4Jeff Garzik{ 2389bdd4dddee325a7dce3e84cf48201a06aa8508aa4Jeff Garzik mv_stop_dma(qc->ap); 2390bdd4dddee325a7dce3e84cf48201a06aa8508aa4Jeff Garzik} 2391bdd4dddee325a7dce3e84cf48201a06aa8508aa4Jeff Garzik 2392bdd4dddee325a7dce3e84cf48201a06aa8508aa4Jeff Garzikstatic void mv_eh_freeze(struct ata_port *ap) 2393bdd4dddee325a7dce3e84cf48201a06aa8508aa4Jeff Garzik{ 2394bdd4dddee325a7dce3e84cf48201a06aa8508aa4Jeff Garzik void __iomem *mmio = ap->host->iomap[MV_PRIMARY_BAR]; 2395bdd4dddee325a7dce3e84cf48201a06aa8508aa4Jeff Garzik unsigned int hc = (ap->port_no > 3) ? 1 : 0; 2396bdd4dddee325a7dce3e84cf48201a06aa8508aa4Jeff Garzik u32 tmp, mask; 2397bdd4dddee325a7dce3e84cf48201a06aa8508aa4Jeff Garzik unsigned int shift; 2398bdd4dddee325a7dce3e84cf48201a06aa8508aa4Jeff Garzik 2399bdd4dddee325a7dce3e84cf48201a06aa8508aa4Jeff Garzik /* FIXME: handle coalescing completion events properly */ 2400bdd4dddee325a7dce3e84cf48201a06aa8508aa4Jeff Garzik 2401bdd4dddee325a7dce3e84cf48201a06aa8508aa4Jeff Garzik shift = ap->port_no * 2; 2402bdd4dddee325a7dce3e84cf48201a06aa8508aa4Jeff Garzik if (hc > 0) 2403bdd4dddee325a7dce3e84cf48201a06aa8508aa4Jeff Garzik shift++; 2404bdd4dddee325a7dce3e84cf48201a06aa8508aa4Jeff Garzik 2405bdd4dddee325a7dce3e84cf48201a06aa8508aa4Jeff Garzik mask = 0x3 << shift; 2406bdd4dddee325a7dce3e84cf48201a06aa8508aa4Jeff Garzik 2407bdd4dddee325a7dce3e84cf48201a06aa8508aa4Jeff Garzik /* disable assertion of portN err, done events */ 2408bdd4dddee325a7dce3e84cf48201a06aa8508aa4Jeff Garzik tmp = readl(mmio + HC_MAIN_IRQ_MASK_OFS); 2409bdd4dddee325a7dce3e84cf48201a06aa8508aa4Jeff Garzik writelfl(tmp & ~mask, mmio + HC_MAIN_IRQ_MASK_OFS); 2410bdd4dddee325a7dce3e84cf48201a06aa8508aa4Jeff Garzik} 2411bdd4dddee325a7dce3e84cf48201a06aa8508aa4Jeff Garzik 2412bdd4dddee325a7dce3e84cf48201a06aa8508aa4Jeff Garzikstatic void mv_eh_thaw(struct ata_port *ap) 2413bdd4dddee325a7dce3e84cf48201a06aa8508aa4Jeff Garzik{ 2414bdd4dddee325a7dce3e84cf48201a06aa8508aa4Jeff Garzik void __iomem *mmio = ap->host->iomap[MV_PRIMARY_BAR]; 2415bdd4dddee325a7dce3e84cf48201a06aa8508aa4Jeff Garzik unsigned int hc = (ap->port_no > 3) ? 1 : 0; 2416bdd4dddee325a7dce3e84cf48201a06aa8508aa4Jeff Garzik void __iomem *hc_mmio = mv_hc_base(mmio, hc); 2417bdd4dddee325a7dce3e84cf48201a06aa8508aa4Jeff Garzik void __iomem *port_mmio = mv_ap_base(ap); 2418bdd4dddee325a7dce3e84cf48201a06aa8508aa4Jeff Garzik u32 tmp, mask, hc_irq_cause; 2419bdd4dddee325a7dce3e84cf48201a06aa8508aa4Jeff Garzik unsigned int shift, hc_port_no = ap->port_no; 2420bdd4dddee325a7dce3e84cf48201a06aa8508aa4Jeff Garzik 2421bdd4dddee325a7dce3e84cf48201a06aa8508aa4Jeff Garzik /* FIXME: handle coalescing completion events properly */ 2422bdd4dddee325a7dce3e84cf48201a06aa8508aa4Jeff Garzik 2423bdd4dddee325a7dce3e84cf48201a06aa8508aa4Jeff Garzik shift = ap->port_no * 2; 2424bdd4dddee325a7dce3e84cf48201a06aa8508aa4Jeff Garzik if (hc > 0) { 2425bdd4dddee325a7dce3e84cf48201a06aa8508aa4Jeff Garzik shift++; 2426bdd4dddee325a7dce3e84cf48201a06aa8508aa4Jeff Garzik hc_port_no -= 4; 2427bdd4dddee325a7dce3e84cf48201a06aa8508aa4Jeff Garzik } 2428bdd4dddee325a7dce3e84cf48201a06aa8508aa4Jeff Garzik 2429bdd4dddee325a7dce3e84cf48201a06aa8508aa4Jeff Garzik mask = 0x3 << shift; 2430bdd4dddee325a7dce3e84cf48201a06aa8508aa4Jeff Garzik 2431bdd4dddee325a7dce3e84cf48201a06aa8508aa4Jeff Garzik /* clear EDMA errors on this port */ 2432bdd4dddee325a7dce3e84cf48201a06aa8508aa4Jeff Garzik writel(0, port_mmio + EDMA_ERR_IRQ_CAUSE_OFS); 2433bdd4dddee325a7dce3e84cf48201a06aa8508aa4Jeff Garzik 2434bdd4dddee325a7dce3e84cf48201a06aa8508aa4Jeff Garzik /* clear pending irq events */ 2435bdd4dddee325a7dce3e84cf48201a06aa8508aa4Jeff Garzik hc_irq_cause = readl(hc_mmio + HC_IRQ_CAUSE_OFS); 2436bdd4dddee325a7dce3e84cf48201a06aa8508aa4Jeff Garzik hc_irq_cause &= ~(1 << hc_port_no); /* clear CRPB-done */ 2437bdd4dddee325a7dce3e84cf48201a06aa8508aa4Jeff Garzik hc_irq_cause &= ~(1 << (hc_port_no + 8)); /* clear Device int */ 2438bdd4dddee325a7dce3e84cf48201a06aa8508aa4Jeff Garzik writel(hc_irq_cause, hc_mmio + HC_IRQ_CAUSE_OFS); 2439bdd4dddee325a7dce3e84cf48201a06aa8508aa4Jeff Garzik 2440bdd4dddee325a7dce3e84cf48201a06aa8508aa4Jeff Garzik /* enable assertion of portN err, done events */ 2441bdd4dddee325a7dce3e84cf48201a06aa8508aa4Jeff Garzik tmp = readl(mmio + HC_MAIN_IRQ_MASK_OFS); 2442bdd4dddee325a7dce3e84cf48201a06aa8508aa4Jeff Garzik writelfl(tmp | mask, mmio + HC_MAIN_IRQ_MASK_OFS); 244331961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ} 244431961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ 244505b308e1df6d9d673daedb517969241f41278b52Brett Russ/** 244605b308e1df6d9d673daedb517969241f41278b52Brett Russ * mv_port_init - Perform some early initialization on a single port. 244705b308e1df6d9d673daedb517969241f41278b52Brett Russ * @port: libata data structure storing shadow register addresses 244805b308e1df6d9d673daedb517969241f41278b52Brett Russ * @port_mmio: base address of the port 244905b308e1df6d9d673daedb517969241f41278b52Brett Russ * 245005b308e1df6d9d673daedb517969241f41278b52Brett Russ * Initialize shadow register mmio addresses, clear outstanding 245105b308e1df6d9d673daedb517969241f41278b52Brett Russ * interrupts on the port, and unmask interrupts for the future 245205b308e1df6d9d673daedb517969241f41278b52Brett Russ * start of the port. 245305b308e1df6d9d673daedb517969241f41278b52Brett Russ * 245405b308e1df6d9d673daedb517969241f41278b52Brett Russ * LOCKING: 245505b308e1df6d9d673daedb517969241f41278b52Brett Russ * Inherited from caller. 245605b308e1df6d9d673daedb517969241f41278b52Brett Russ */ 245731961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russstatic void mv_port_init(struct ata_ioports *port, void __iomem *port_mmio) 245820f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ{ 24590d5ff566779f894ca9937231a181eb31e4adff0eTejun Heo void __iomem *shd_base = port_mmio + SHD_BLK_OFS; 246031961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ unsigned serr_ofs; 246131961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ 24628b260248d9e0e8b64bb72fd4dee03ad86984c344Jeff Garzik /* PIO related setup 246331961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ */ 246431961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ port->data_addr = shd_base + (sizeof(u32) * ATA_REG_DATA); 24658b260248d9e0e8b64bb72fd4dee03ad86984c344Jeff Garzik port->error_addr = 246631961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ port->feature_addr = shd_base + (sizeof(u32) * ATA_REG_ERR); 246731961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ port->nsect_addr = shd_base + (sizeof(u32) * ATA_REG_NSECT); 246831961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ port->lbal_addr = shd_base + (sizeof(u32) * ATA_REG_LBAL); 246931961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ port->lbam_addr = shd_base + (sizeof(u32) * ATA_REG_LBAM); 247031961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ port->lbah_addr = shd_base + (sizeof(u32) * ATA_REG_LBAH); 247131961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ port->device_addr = shd_base + (sizeof(u32) * ATA_REG_DEVICE); 24728b260248d9e0e8b64bb72fd4dee03ad86984c344Jeff Garzik port->status_addr = 247331961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ port->command_addr = shd_base + (sizeof(u32) * ATA_REG_STATUS); 247431961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ /* special case: control/altstatus doesn't have ATA_REG_ address */ 247531961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ port->altstatus_addr = port->ctl_addr = shd_base + SHD_CTL_AST_OFS; 247631961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ 247731961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ /* unused: */ 24788d9db2d2fbae9e05022825c32f86e00c8e342860Randy Dunlap port->cmd_addr = port->bmdma_addr = port->scr_addr = NULL; 247920f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ 248031961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ /* Clear any currently outstanding port interrupt conditions */ 248131961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ serr_ofs = mv_scr_offset(SCR_ERROR); 248231961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ writelfl(readl(port_mmio + serr_ofs), port_mmio + serr_ofs); 248331961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ writelfl(0, port_mmio + EDMA_ERR_IRQ_CAUSE_OFS); 248431961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ 2485646a4da514f2555298481cb00dc5b3eb02b21b72Mark Lord /* unmask all non-transient EDMA error interrupts */ 2486646a4da514f2555298481cb00dc5b3eb02b21b72Mark Lord writelfl(~EDMA_ERR_IRQ_TRANSIENT, port_mmio + EDMA_ERR_IRQ_MASK_OFS); 248720f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ 24888b260248d9e0e8b64bb72fd4dee03ad86984c344Jeff Garzik VPRINTK("EDMA cfg=0x%08x EDMA IRQ err cause/mask=0x%08x/0x%08x\n", 248931961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ readl(port_mmio + EDMA_CFG_OFS), 249031961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ readl(port_mmio + EDMA_ERR_IRQ_CAUSE_OFS), 249131961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ readl(port_mmio + EDMA_ERR_IRQ_MASK_OFS)); 249220f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ} 249320f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ 24944447d35156169cf136e829eb6b5cac2d6370f2d9Tejun Heostatic int mv_chip_id(struct ata_host *host, unsigned int board_idx) 2495bca1c4eb9411533d613123618c0d127fae532595Jeff Garzik{ 24964447d35156169cf136e829eb6b5cac2d6370f2d9Tejun Heo struct pci_dev *pdev = to_pci_dev(host->dev); 24974447d35156169cf136e829eb6b5cac2d6370f2d9Tejun Heo struct mv_host_priv *hpriv = host->private_data; 2498bca1c4eb9411533d613123618c0d127fae532595Jeff Garzik u32 hp_flags = hpriv->hp_flags; 2499bca1c4eb9411533d613123618c0d127fae532595Jeff Garzik 25005796d1c4c89efff823259fda35b08ea66ebf8b23Jeff Garzik switch (board_idx) { 250147c2b677daeed9c79ecb7167c211ff36876ea611Jeff Garzik case chip_5080: 250247c2b677daeed9c79ecb7167c211ff36876ea611Jeff Garzik hpriv->ops = &mv5xxx_ops; 2503ee9ccdf70163ca6408f6965e0fbc65baeac7312cJeff Garzik hp_flags |= MV_HP_GEN_I; 250447c2b677daeed9c79ecb7167c211ff36876ea611Jeff Garzik 250544c10138fd4bbc4b6d6bff0873c24902f2a9da65Auke Kok switch (pdev->revision) { 250647c2b677daeed9c79ecb7167c211ff36876ea611Jeff Garzik case 0x1: 250747c2b677daeed9c79ecb7167c211ff36876ea611Jeff Garzik hp_flags |= MV_HP_ERRATA_50XXB0; 250847c2b677daeed9c79ecb7167c211ff36876ea611Jeff Garzik break; 250947c2b677daeed9c79ecb7167c211ff36876ea611Jeff Garzik case 0x3: 251047c2b677daeed9c79ecb7167c211ff36876ea611Jeff Garzik hp_flags |= MV_HP_ERRATA_50XXB2; 251147c2b677daeed9c79ecb7167c211ff36876ea611Jeff Garzik break; 251247c2b677daeed9c79ecb7167c211ff36876ea611Jeff Garzik default: 251347c2b677daeed9c79ecb7167c211ff36876ea611Jeff Garzik dev_printk(KERN_WARNING, &pdev->dev, 251447c2b677daeed9c79ecb7167c211ff36876ea611Jeff Garzik "Applying 50XXB2 workarounds to unknown rev\n"); 251547c2b677daeed9c79ecb7167c211ff36876ea611Jeff Garzik hp_flags |= MV_HP_ERRATA_50XXB2; 251647c2b677daeed9c79ecb7167c211ff36876ea611Jeff Garzik break; 251747c2b677daeed9c79ecb7167c211ff36876ea611Jeff Garzik } 251847c2b677daeed9c79ecb7167c211ff36876ea611Jeff Garzik break; 251947c2b677daeed9c79ecb7167c211ff36876ea611Jeff Garzik 2520bca1c4eb9411533d613123618c0d127fae532595Jeff Garzik case chip_504x: 2521bca1c4eb9411533d613123618c0d127fae532595Jeff Garzik case chip_508x: 252247c2b677daeed9c79ecb7167c211ff36876ea611Jeff Garzik hpriv->ops = &mv5xxx_ops; 2523ee9ccdf70163ca6408f6965e0fbc65baeac7312cJeff Garzik hp_flags |= MV_HP_GEN_I; 2524bca1c4eb9411533d613123618c0d127fae532595Jeff Garzik 252544c10138fd4bbc4b6d6bff0873c24902f2a9da65Auke Kok switch (pdev->revision) { 252647c2b677daeed9c79ecb7167c211ff36876ea611Jeff Garzik case 0x0: 252747c2b677daeed9c79ecb7167c211ff36876ea611Jeff Garzik hp_flags |= MV_HP_ERRATA_50XXB0; 252847c2b677daeed9c79ecb7167c211ff36876ea611Jeff Garzik break; 252947c2b677daeed9c79ecb7167c211ff36876ea611Jeff Garzik case 0x3: 253047c2b677daeed9c79ecb7167c211ff36876ea611Jeff Garzik hp_flags |= MV_HP_ERRATA_50XXB2; 253147c2b677daeed9c79ecb7167c211ff36876ea611Jeff Garzik break; 253247c2b677daeed9c79ecb7167c211ff36876ea611Jeff Garzik default: 253347c2b677daeed9c79ecb7167c211ff36876ea611Jeff Garzik dev_printk(KERN_WARNING, &pdev->dev, 253447c2b677daeed9c79ecb7167c211ff36876ea611Jeff Garzik "Applying B2 workarounds to unknown rev\n"); 253547c2b677daeed9c79ecb7167c211ff36876ea611Jeff Garzik hp_flags |= MV_HP_ERRATA_50XXB2; 253647c2b677daeed9c79ecb7167c211ff36876ea611Jeff Garzik break; 2537bca1c4eb9411533d613123618c0d127fae532595Jeff Garzik } 2538bca1c4eb9411533d613123618c0d127fae532595Jeff Garzik break; 2539bca1c4eb9411533d613123618c0d127fae532595Jeff Garzik 2540bca1c4eb9411533d613123618c0d127fae532595Jeff Garzik case chip_604x: 2541bca1c4eb9411533d613123618c0d127fae532595Jeff Garzik case chip_608x: 254247c2b677daeed9c79ecb7167c211ff36876ea611Jeff Garzik hpriv->ops = &mv6xxx_ops; 2543ee9ccdf70163ca6408f6965e0fbc65baeac7312cJeff Garzik hp_flags |= MV_HP_GEN_II; 254447c2b677daeed9c79ecb7167c211ff36876ea611Jeff Garzik 254544c10138fd4bbc4b6d6bff0873c24902f2a9da65Auke Kok switch (pdev->revision) { 254647c2b677daeed9c79ecb7167c211ff36876ea611Jeff Garzik case 0x7: 254747c2b677daeed9c79ecb7167c211ff36876ea611Jeff Garzik hp_flags |= MV_HP_ERRATA_60X1B2; 254847c2b677daeed9c79ecb7167c211ff36876ea611Jeff Garzik break; 254947c2b677daeed9c79ecb7167c211ff36876ea611Jeff Garzik case 0x9: 255047c2b677daeed9c79ecb7167c211ff36876ea611Jeff Garzik hp_flags |= MV_HP_ERRATA_60X1C0; 2551bca1c4eb9411533d613123618c0d127fae532595Jeff Garzik break; 2552bca1c4eb9411533d613123618c0d127fae532595Jeff Garzik default: 2553bca1c4eb9411533d613123618c0d127fae532595Jeff Garzik dev_printk(KERN_WARNING, &pdev->dev, 255447c2b677daeed9c79ecb7167c211ff36876ea611Jeff Garzik "Applying B2 workarounds to unknown rev\n"); 255547c2b677daeed9c79ecb7167c211ff36876ea611Jeff Garzik hp_flags |= MV_HP_ERRATA_60X1B2; 2556bca1c4eb9411533d613123618c0d127fae532595Jeff Garzik break; 2557bca1c4eb9411533d613123618c0d127fae532595Jeff Garzik } 2558bca1c4eb9411533d613123618c0d127fae532595Jeff Garzik break; 2559bca1c4eb9411533d613123618c0d127fae532595Jeff Garzik 2560e4e7b89280d1d666e2c09e5ad36cf071796c4c7eJeff Garzik case chip_7042: 256102a121da5a53d415b6596bc19cc6999d295d32a4Mark Lord hp_flags |= MV_HP_PCIE; 2562306b30f74d37f289033c696285e07ce0158a5d7bMark Lord if (pdev->vendor == PCI_VENDOR_ID_TTI && 2563306b30f74d37f289033c696285e07ce0158a5d7bMark Lord (pdev->device == 0x2300 || pdev->device == 0x2310)) 2564306b30f74d37f289033c696285e07ce0158a5d7bMark Lord { 25654e5200334e03e5620aa19d538300c13db270a063Mark Lord /* 25664e5200334e03e5620aa19d538300c13db270a063Mark Lord * Highpoint RocketRAID PCIe 23xx series cards: 25674e5200334e03e5620aa19d538300c13db270a063Mark Lord * 25684e5200334e03e5620aa19d538300c13db270a063Mark Lord * Unconfigured drives are treated as "Legacy" 25694e5200334e03e5620aa19d538300c13db270a063Mark Lord * by the BIOS, and it overwrites sector 8 with 25704e5200334e03e5620aa19d538300c13db270a063Mark Lord * a "Lgcy" metadata block prior to Linux boot. 25714e5200334e03e5620aa19d538300c13db270a063Mark Lord * 25724e5200334e03e5620aa19d538300c13db270a063Mark Lord * Configured drives (RAID or JBOD) leave sector 8 25734e5200334e03e5620aa19d538300c13db270a063Mark Lord * alone, but instead overwrite a high numbered 25744e5200334e03e5620aa19d538300c13db270a063Mark Lord * sector for the RAID metadata. This sector can 25754e5200334e03e5620aa19d538300c13db270a063Mark Lord * be determined exactly, by truncating the physical 25764e5200334e03e5620aa19d538300c13db270a063Mark Lord * drive capacity to a nice even GB value. 25774e5200334e03e5620aa19d538300c13db270a063Mark Lord * 25784e5200334e03e5620aa19d538300c13db270a063Mark Lord * RAID metadata is at: (dev->n_sectors & ~0xfffff) 25794e5200334e03e5620aa19d538300c13db270a063Mark Lord * 25804e5200334e03e5620aa19d538300c13db270a063Mark Lord * Warn the user, lest they think we're just buggy. 25814e5200334e03e5620aa19d538300c13db270a063Mark Lord */ 25824e5200334e03e5620aa19d538300c13db270a063Mark Lord printk(KERN_WARNING DRV_NAME ": Highpoint RocketRAID" 25834e5200334e03e5620aa19d538300c13db270a063Mark Lord " BIOS CORRUPTS DATA on all attached drives," 25844e5200334e03e5620aa19d538300c13db270a063Mark Lord " regardless of if/how they are configured." 25854e5200334e03e5620aa19d538300c13db270a063Mark Lord " BEWARE!\n"); 25864e5200334e03e5620aa19d538300c13db270a063Mark Lord printk(KERN_WARNING DRV_NAME ": For data safety, do not" 25874e5200334e03e5620aa19d538300c13db270a063Mark Lord " use sectors 8-9 on \"Legacy\" drives," 25884e5200334e03e5620aa19d538300c13db270a063Mark Lord " and avoid the final two gigabytes on" 25894e5200334e03e5620aa19d538300c13db270a063Mark Lord " all RocketRAID BIOS initialized drives.\n"); 2590306b30f74d37f289033c696285e07ce0158a5d7bMark Lord } 2591e4e7b89280d1d666e2c09e5ad36cf071796c4c7eJeff Garzik case chip_6042: 2592e4e7b89280d1d666e2c09e5ad36cf071796c4c7eJeff Garzik hpriv->ops = &mv6xxx_ops; 2593e4e7b89280d1d666e2c09e5ad36cf071796c4c7eJeff Garzik hp_flags |= MV_HP_GEN_IIE; 2594e4e7b89280d1d666e2c09e5ad36cf071796c4c7eJeff Garzik 259544c10138fd4bbc4b6d6bff0873c24902f2a9da65Auke Kok switch (pdev->revision) { 2596e4e7b89280d1d666e2c09e5ad36cf071796c4c7eJeff Garzik case 0x0: 2597e4e7b89280d1d666e2c09e5ad36cf071796c4c7eJeff Garzik hp_flags |= MV_HP_ERRATA_XX42A0; 2598e4e7b89280d1d666e2c09e5ad36cf071796c4c7eJeff Garzik break; 2599e4e7b89280d1d666e2c09e5ad36cf071796c4c7eJeff Garzik case 0x1: 2600e4e7b89280d1d666e2c09e5ad36cf071796c4c7eJeff Garzik hp_flags |= MV_HP_ERRATA_60X1C0; 2601e4e7b89280d1d666e2c09e5ad36cf071796c4c7eJeff Garzik break; 2602e4e7b89280d1d666e2c09e5ad36cf071796c4c7eJeff Garzik default: 2603e4e7b89280d1d666e2c09e5ad36cf071796c4c7eJeff Garzik dev_printk(KERN_WARNING, &pdev->dev, 2604e4e7b89280d1d666e2c09e5ad36cf071796c4c7eJeff Garzik "Applying 60X1C0 workarounds to unknown rev\n"); 2605e4e7b89280d1d666e2c09e5ad36cf071796c4c7eJeff Garzik hp_flags |= MV_HP_ERRATA_60X1C0; 2606e4e7b89280d1d666e2c09e5ad36cf071796c4c7eJeff Garzik break; 2607e4e7b89280d1d666e2c09e5ad36cf071796c4c7eJeff Garzik } 2608e4e7b89280d1d666e2c09e5ad36cf071796c4c7eJeff Garzik break; 2609e4e7b89280d1d666e2c09e5ad36cf071796c4c7eJeff Garzik 2610bca1c4eb9411533d613123618c0d127fae532595Jeff Garzik default: 26115796d1c4c89efff823259fda35b08ea66ebf8b23Jeff Garzik dev_printk(KERN_ERR, &pdev->dev, 26125796d1c4c89efff823259fda35b08ea66ebf8b23Jeff Garzik "BUG: invalid board index %u\n", board_idx); 2613bca1c4eb9411533d613123618c0d127fae532595Jeff Garzik return 1; 2614bca1c4eb9411533d613123618c0d127fae532595Jeff Garzik } 2615bca1c4eb9411533d613123618c0d127fae532595Jeff Garzik 2616bca1c4eb9411533d613123618c0d127fae532595Jeff Garzik hpriv->hp_flags = hp_flags; 261702a121da5a53d415b6596bc19cc6999d295d32a4Mark Lord if (hp_flags & MV_HP_PCIE) { 261802a121da5a53d415b6596bc19cc6999d295d32a4Mark Lord hpriv->irq_cause_ofs = PCIE_IRQ_CAUSE_OFS; 261902a121da5a53d415b6596bc19cc6999d295d32a4Mark Lord hpriv->irq_mask_ofs = PCIE_IRQ_MASK_OFS; 262002a121da5a53d415b6596bc19cc6999d295d32a4Mark Lord hpriv->unmask_all_irqs = PCIE_UNMASK_ALL_IRQS; 262102a121da5a53d415b6596bc19cc6999d295d32a4Mark Lord } else { 262202a121da5a53d415b6596bc19cc6999d295d32a4Mark Lord hpriv->irq_cause_ofs = PCI_IRQ_CAUSE_OFS; 262302a121da5a53d415b6596bc19cc6999d295d32a4Mark Lord hpriv->irq_mask_ofs = PCI_IRQ_MASK_OFS; 262402a121da5a53d415b6596bc19cc6999d295d32a4Mark Lord hpriv->unmask_all_irqs = PCI_UNMASK_ALL_IRQS; 262502a121da5a53d415b6596bc19cc6999d295d32a4Mark Lord } 2626bca1c4eb9411533d613123618c0d127fae532595Jeff Garzik 2627bca1c4eb9411533d613123618c0d127fae532595Jeff Garzik return 0; 2628bca1c4eb9411533d613123618c0d127fae532595Jeff Garzik} 2629bca1c4eb9411533d613123618c0d127fae532595Jeff Garzik 263005b308e1df6d9d673daedb517969241f41278b52Brett Russ/** 263147c2b677daeed9c79ecb7167c211ff36876ea611Jeff Garzik * mv_init_host - Perform some early initialization of the host. 26324447d35156169cf136e829eb6b5cac2d6370f2d9Tejun Heo * @host: ATA host to initialize 26334447d35156169cf136e829eb6b5cac2d6370f2d9Tejun Heo * @board_idx: controller index 263405b308e1df6d9d673daedb517969241f41278b52Brett Russ * 263505b308e1df6d9d673daedb517969241f41278b52Brett Russ * If possible, do an early global reset of the host. Then do 263605b308e1df6d9d673daedb517969241f41278b52Brett Russ * our port init and clear/unmask all/relevant host interrupts. 263705b308e1df6d9d673daedb517969241f41278b52Brett Russ * 263805b308e1df6d9d673daedb517969241f41278b52Brett Russ * LOCKING: 263905b308e1df6d9d673daedb517969241f41278b52Brett Russ * Inherited from caller. 264005b308e1df6d9d673daedb517969241f41278b52Brett Russ */ 26414447d35156169cf136e829eb6b5cac2d6370f2d9Tejun Heostatic int mv_init_host(struct ata_host *host, unsigned int board_idx) 264220f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ{ 264320f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ int rc = 0, n_hc, port, hc; 26444447d35156169cf136e829eb6b5cac2d6370f2d9Tejun Heo struct pci_dev *pdev = to_pci_dev(host->dev); 26454447d35156169cf136e829eb6b5cac2d6370f2d9Tejun Heo void __iomem *mmio = host->iomap[MV_PRIMARY_BAR]; 26464447d35156169cf136e829eb6b5cac2d6370f2d9Tejun Heo struct mv_host_priv *hpriv = host->private_data; 2647bca1c4eb9411533d613123618c0d127fae532595Jeff Garzik 264847c2b677daeed9c79ecb7167c211ff36876ea611Jeff Garzik /* global interrupt mask */ 264947c2b677daeed9c79ecb7167c211ff36876ea611Jeff Garzik writel(0, mmio + HC_MAIN_IRQ_MASK_OFS); 265047c2b677daeed9c79ecb7167c211ff36876ea611Jeff Garzik 26514447d35156169cf136e829eb6b5cac2d6370f2d9Tejun Heo rc = mv_chip_id(host, board_idx); 2652bca1c4eb9411533d613123618c0d127fae532595Jeff Garzik if (rc) 2653bca1c4eb9411533d613123618c0d127fae532595Jeff Garzik goto done; 2654bca1c4eb9411533d613123618c0d127fae532595Jeff Garzik 26554447d35156169cf136e829eb6b5cac2d6370f2d9Tejun Heo n_hc = mv_get_hc_count(host->ports[0]->flags); 2656bca1c4eb9411533d613123618c0d127fae532595Jeff Garzik 26574447d35156169cf136e829eb6b5cac2d6370f2d9Tejun Heo for (port = 0; port < host->n_ports; port++) 265847c2b677daeed9c79ecb7167c211ff36876ea611Jeff Garzik hpriv->ops->read_preamp(hpriv, port, mmio); 265920f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ 2660c9d39130123238ac18478a42e25cb7996eacfcc0Jeff Garzik rc = hpriv->ops->reset_hc(hpriv, mmio, n_hc); 266147c2b677daeed9c79ecb7167c211ff36876ea611Jeff Garzik if (rc) 266220f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ goto done; 266320f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ 2664522479fb98c6667f081e75f87e298e413c0b1db8Jeff Garzik hpriv->ops->reset_flash(hpriv, mmio); 2665522479fb98c6667f081e75f87e298e413c0b1db8Jeff Garzik hpriv->ops->reset_bus(pdev, mmio); 266647c2b677daeed9c79ecb7167c211ff36876ea611Jeff Garzik hpriv->ops->enable_leds(hpriv, mmio); 266720f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ 26684447d35156169cf136e829eb6b5cac2d6370f2d9Tejun Heo for (port = 0; port < host->n_ports; port++) { 2669ee9ccdf70163ca6408f6965e0fbc65baeac7312cJeff Garzik if (IS_GEN_II(hpriv)) { 2670c9d39130123238ac18478a42e25cb7996eacfcc0Jeff Garzik void __iomem *port_mmio = mv_port_base(mmio, port); 2671c9d39130123238ac18478a42e25cb7996eacfcc0Jeff Garzik 26722a47ce06d534692f9bd2bf4e90a20fc9b1054c39Jeff Garzik u32 ifctl = readl(port_mmio + SATA_INTERFACE_CTL); 2673eb46d684600ac145501805a294c94675e82eab2eMark Lord ifctl |= (1 << 7); /* enable gen2i speed */ 2674eb46d684600ac145501805a294c94675e82eab2eMark Lord ifctl = (ifctl & 0xfff) | 0x9b1000; /* from chip spec */ 26752a47ce06d534692f9bd2bf4e90a20fc9b1054c39Jeff Garzik writelfl(ifctl, port_mmio + SATA_INTERFACE_CTL); 26762a47ce06d534692f9bd2bf4e90a20fc9b1054c39Jeff Garzik } 26772a47ce06d534692f9bd2bf4e90a20fc9b1054c39Jeff Garzik 2678c9d39130123238ac18478a42e25cb7996eacfcc0Jeff Garzik hpriv->ops->phy_errata(hpriv, mmio, port); 26792a47ce06d534692f9bd2bf4e90a20fc9b1054c39Jeff Garzik } 26802a47ce06d534692f9bd2bf4e90a20fc9b1054c39Jeff Garzik 26814447d35156169cf136e829eb6b5cac2d6370f2d9Tejun Heo for (port = 0; port < host->n_ports; port++) { 2682cbcdd87593a1d85c5c4b259945a3a09eee12814dTejun Heo struct ata_port *ap = host->ports[port]; 26832a47ce06d534692f9bd2bf4e90a20fc9b1054c39Jeff Garzik void __iomem *port_mmio = mv_port_base(mmio, port); 2684cbcdd87593a1d85c5c4b259945a3a09eee12814dTejun Heo unsigned int offset = port_mmio - mmio; 2685cbcdd87593a1d85c5c4b259945a3a09eee12814dTejun Heo 2686cbcdd87593a1d85c5c4b259945a3a09eee12814dTejun Heo mv_port_init(&ap->ioaddr, port_mmio); 2687cbcdd87593a1d85c5c4b259945a3a09eee12814dTejun Heo 2688cbcdd87593a1d85c5c4b259945a3a09eee12814dTejun Heo ata_port_pbar_desc(ap, MV_PRIMARY_BAR, -1, "mmio"); 2689cbcdd87593a1d85c5c4b259945a3a09eee12814dTejun Heo ata_port_pbar_desc(ap, MV_PRIMARY_BAR, offset, "port"); 269020f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ } 269120f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ 269220f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ for (hc = 0; hc < n_hc; hc++) { 269331961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ void __iomem *hc_mmio = mv_hc_base(mmio, hc); 269431961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ 269531961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ VPRINTK("HC%i: HC config=0x%08x HC IRQ cause " 269631961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ "(before clear)=0x%08x\n", hc, 269731961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ readl(hc_mmio + HC_CFG_OFS), 269831961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ readl(hc_mmio + HC_IRQ_CAUSE_OFS)); 269931961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ 270031961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ /* Clear any currently outstanding hc interrupt conditions */ 270131961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ writelfl(0, hc_mmio + HC_IRQ_CAUSE_OFS); 270220f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ } 270320f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ 270431961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ /* Clear any currently outstanding host interrupt conditions */ 270502a121da5a53d415b6596bc19cc6999d295d32a4Mark Lord writelfl(0, mmio + hpriv->irq_cause_ofs); 270631961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ 270731961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ /* and unmask interrupt generation for host regs */ 270802a121da5a53d415b6596bc19cc6999d295d32a4Mark Lord writelfl(hpriv->unmask_all_irqs, mmio + hpriv->irq_mask_ofs); 2709fb621e2fde735abab854586d52c96c5624bcb5b8Jeff Garzik 2710ee9ccdf70163ca6408f6965e0fbc65baeac7312cJeff Garzik if (IS_GEN_I(hpriv)) 2711fb621e2fde735abab854586d52c96c5624bcb5b8Jeff Garzik writelfl(~HC_MAIN_MASKED_IRQS_5, mmio + HC_MAIN_IRQ_MASK_OFS); 2712fb621e2fde735abab854586d52c96c5624bcb5b8Jeff Garzik else 2713fb621e2fde735abab854586d52c96c5624bcb5b8Jeff Garzik writelfl(~HC_MAIN_MASKED_IRQS, mmio + HC_MAIN_IRQ_MASK_OFS); 271420f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ 271520f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ VPRINTK("HC MAIN IRQ cause/mask=0x%08x/0x%08x " 27168b260248d9e0e8b64bb72fd4dee03ad86984c344Jeff Garzik "PCI int cause/mask=0x%08x/0x%08x\n", 271720f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ readl(mmio + HC_MAIN_IRQ_CAUSE_OFS), 271820f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ readl(mmio + HC_MAIN_IRQ_MASK_OFS), 271902a121da5a53d415b6596bc19cc6999d295d32a4Mark Lord readl(mmio + hpriv->irq_cause_ofs), 272002a121da5a53d415b6596bc19cc6999d295d32a4Mark Lord readl(mmio + hpriv->irq_mask_ofs)); 2721bca1c4eb9411533d613123618c0d127fae532595Jeff Garzik 272231961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russdone: 272320f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ return rc; 272420f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ} 272520f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ 272605b308e1df6d9d673daedb517969241f41278b52Brett Russ/** 272705b308e1df6d9d673daedb517969241f41278b52Brett Russ * mv_print_info - Dump key info to kernel log for perusal. 27284447d35156169cf136e829eb6b5cac2d6370f2d9Tejun Heo * @host: ATA host to print info about 272905b308e1df6d9d673daedb517969241f41278b52Brett Russ * 273005b308e1df6d9d673daedb517969241f41278b52Brett Russ * FIXME: complete this. 273105b308e1df6d9d673daedb517969241f41278b52Brett Russ * 273205b308e1df6d9d673daedb517969241f41278b52Brett Russ * LOCKING: 273305b308e1df6d9d673daedb517969241f41278b52Brett Russ * Inherited from caller. 273405b308e1df6d9d673daedb517969241f41278b52Brett Russ */ 27354447d35156169cf136e829eb6b5cac2d6370f2d9Tejun Heostatic void mv_print_info(struct ata_host *host) 273631961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ{ 27374447d35156169cf136e829eb6b5cac2d6370f2d9Tejun Heo struct pci_dev *pdev = to_pci_dev(host->dev); 27384447d35156169cf136e829eb6b5cac2d6370f2d9Tejun Heo struct mv_host_priv *hpriv = host->private_data; 273944c10138fd4bbc4b6d6bff0873c24902f2a9da65Auke Kok u8 scc; 2740c1e4fe711a410a139095e6b3e3ce3f07f466063cJeff Garzik const char *scc_s, *gen; 274131961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ 274231961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ /* Use this to determine the HW stepping of the chip so we know 274331961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ * what errata to workaround 274431961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ */ 274531961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ pci_read_config_byte(pdev, PCI_CLASS_DEVICE, &scc); 274631961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ if (scc == 0) 274731961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ scc_s = "SCSI"; 274831961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ else if (scc == 0x01) 274931961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ scc_s = "RAID"; 275031961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ else 2751c1e4fe711a410a139095e6b3e3ce3f07f466063cJeff Garzik scc_s = "?"; 2752c1e4fe711a410a139095e6b3e3ce3f07f466063cJeff Garzik 2753c1e4fe711a410a139095e6b3e3ce3f07f466063cJeff Garzik if (IS_GEN_I(hpriv)) 2754c1e4fe711a410a139095e6b3e3ce3f07f466063cJeff Garzik gen = "I"; 2755c1e4fe711a410a139095e6b3e3ce3f07f466063cJeff Garzik else if (IS_GEN_II(hpriv)) 2756c1e4fe711a410a139095e6b3e3ce3f07f466063cJeff Garzik gen = "II"; 2757c1e4fe711a410a139095e6b3e3ce3f07f466063cJeff Garzik else if (IS_GEN_IIE(hpriv)) 2758c1e4fe711a410a139095e6b3e3ce3f07f466063cJeff Garzik gen = "IIE"; 2759c1e4fe711a410a139095e6b3e3ce3f07f466063cJeff Garzik else 2760c1e4fe711a410a139095e6b3e3ce3f07f466063cJeff Garzik gen = "?"; 276131961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ 2762a9524a76f70f3343e4be27f95a7e92a8ba5f9009Jeff Garzik dev_printk(KERN_INFO, &pdev->dev, 2763c1e4fe711a410a139095e6b3e3ce3f07f466063cJeff Garzik "Gen-%s %u slots %u ports %s mode IRQ via %s\n", 2764c1e4fe711a410a139095e6b3e3ce3f07f466063cJeff Garzik gen, (unsigned)MV_MAX_Q_DEPTH, host->n_ports, 276531961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ scc_s, (MV_HP_FLAG_MSI & hpriv->hp_flags) ? "MSI" : "INTx"); 276631961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ} 276731961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ 276805b308e1df6d9d673daedb517969241f41278b52Brett Russ/** 276905b308e1df6d9d673daedb517969241f41278b52Brett Russ * mv_init_one - handle a positive probe of a Marvell host 277005b308e1df6d9d673daedb517969241f41278b52Brett Russ * @pdev: PCI device found 277105b308e1df6d9d673daedb517969241f41278b52Brett Russ * @ent: PCI device ID entry for the matched host 277205b308e1df6d9d673daedb517969241f41278b52Brett Russ * 277305b308e1df6d9d673daedb517969241f41278b52Brett Russ * LOCKING: 277405b308e1df6d9d673daedb517969241f41278b52Brett Russ * Inherited from caller. 277505b308e1df6d9d673daedb517969241f41278b52Brett Russ */ 277620f733e7d75a16bffc34842b7682c9247dd5f954Brett Russstatic int mv_init_one(struct pci_dev *pdev, const struct pci_device_id *ent) 277720f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ{ 27782dcb407e61458ded17503d6bd12b8c064965368bJeff Garzik static int printed_version; 277920f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ unsigned int board_idx = (unsigned int)ent->driver_data; 27804447d35156169cf136e829eb6b5cac2d6370f2d9Tejun Heo const struct ata_port_info *ppi[] = { &mv_port_info[board_idx], NULL }; 27814447d35156169cf136e829eb6b5cac2d6370f2d9Tejun Heo struct ata_host *host; 27824447d35156169cf136e829eb6b5cac2d6370f2d9Tejun Heo struct mv_host_priv *hpriv; 27834447d35156169cf136e829eb6b5cac2d6370f2d9Tejun Heo int n_ports, rc; 278420f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ 2785a9524a76f70f3343e4be27f95a7e92a8ba5f9009Jeff Garzik if (!printed_version++) 2786a9524a76f70f3343e4be27f95a7e92a8ba5f9009Jeff Garzik dev_printk(KERN_INFO, &pdev->dev, "version " DRV_VERSION "\n"); 278720f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ 27884447d35156169cf136e829eb6b5cac2d6370f2d9Tejun Heo /* allocate host */ 27894447d35156169cf136e829eb6b5cac2d6370f2d9Tejun Heo n_ports = mv_get_hc_count(ppi[0]->flags) * MV_PORTS_PER_HC; 27904447d35156169cf136e829eb6b5cac2d6370f2d9Tejun Heo 27914447d35156169cf136e829eb6b5cac2d6370f2d9Tejun Heo host = ata_host_alloc_pinfo(&pdev->dev, ppi, n_ports); 27924447d35156169cf136e829eb6b5cac2d6370f2d9Tejun Heo hpriv = devm_kzalloc(&pdev->dev, sizeof(*hpriv), GFP_KERNEL); 27934447d35156169cf136e829eb6b5cac2d6370f2d9Tejun Heo if (!host || !hpriv) 27944447d35156169cf136e829eb6b5cac2d6370f2d9Tejun Heo return -ENOMEM; 27954447d35156169cf136e829eb6b5cac2d6370f2d9Tejun Heo host->private_data = hpriv; 27964447d35156169cf136e829eb6b5cac2d6370f2d9Tejun Heo 27974447d35156169cf136e829eb6b5cac2d6370f2d9Tejun Heo /* acquire resources */ 279824dc5f33ea4b504cfbd23fa159a4cacba8e4d800Tejun Heo rc = pcim_enable_device(pdev); 279924dc5f33ea4b504cfbd23fa159a4cacba8e4d800Tejun Heo if (rc) 280020f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ return rc; 280120f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ 28020d5ff566779f894ca9937231a181eb31e4adff0eTejun Heo rc = pcim_iomap_regions(pdev, 1 << MV_PRIMARY_BAR, DRV_NAME); 28030d5ff566779f894ca9937231a181eb31e4adff0eTejun Heo if (rc == -EBUSY) 280424dc5f33ea4b504cfbd23fa159a4cacba8e4d800Tejun Heo pcim_pin_device(pdev); 28050d5ff566779f894ca9937231a181eb31e4adff0eTejun Heo if (rc) 280624dc5f33ea4b504cfbd23fa159a4cacba8e4d800Tejun Heo return rc; 28074447d35156169cf136e829eb6b5cac2d6370f2d9Tejun Heo host->iomap = pcim_iomap_table(pdev); 280820f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ 2809d88184fb2348a50f7c34f5d49a901c875b2e0114Jeff Garzik rc = pci_go_64(pdev); 2810d88184fb2348a50f7c34f5d49a901c875b2e0114Jeff Garzik if (rc) 2811d88184fb2348a50f7c34f5d49a901c875b2e0114Jeff Garzik return rc; 2812d88184fb2348a50f7c34f5d49a901c875b2e0114Jeff Garzik 281320f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ /* initialize adapter */ 28144447d35156169cf136e829eb6b5cac2d6370f2d9Tejun Heo rc = mv_init_host(host, board_idx); 281524dc5f33ea4b504cfbd23fa159a4cacba8e4d800Tejun Heo if (rc) 281624dc5f33ea4b504cfbd23fa159a4cacba8e4d800Tejun Heo return rc; 281720f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ 281831961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ /* Enable interrupts */ 28196a59dcf8678cbc4106a8a6e158d7408a87691358Tejun Heo if (msi && pci_enable_msi(pdev)) 282031961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ pci_intx(pdev, 1); 282120f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ 282231961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ mv_dump_pci_cfg(pdev, 0x68); 28234447d35156169cf136e829eb6b5cac2d6370f2d9Tejun Heo mv_print_info(host); 282420f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ 28254447d35156169cf136e829eb6b5cac2d6370f2d9Tejun Heo pci_set_master(pdev); 2826ea8b4db97aa41a66c05daa4055a1974692ccd52dJeff Garzik pci_try_set_mwi(pdev); 28274447d35156169cf136e829eb6b5cac2d6370f2d9Tejun Heo return ata_host_activate(host, pdev->irq, mv_interrupt, IRQF_SHARED, 2828c5d3e45a2200a0905dc45b72714726b7aac3aaf1Jeff Garzik IS_GEN_I(hpriv) ? &mv5_sht : &mv6_sht); 282920f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ} 283020f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ 283120f733e7d75a16bffc34842b7682c9247dd5f954Brett Russstatic int __init mv_init(void) 283220f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ{ 2833b7887196e38da54ff893897b80875d632d1a1114Pavel Roskin return pci_register_driver(&mv_pci_driver); 283420f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ} 283520f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ 283620f733e7d75a16bffc34842b7682c9247dd5f954Brett Russstatic void __exit mv_exit(void) 283720f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ{ 283820f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ pci_unregister_driver(&mv_pci_driver); 283920f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ} 284020f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ 284120f733e7d75a16bffc34842b7682c9247dd5f954Brett RussMODULE_AUTHOR("Brett Russ"); 284220f733e7d75a16bffc34842b7682c9247dd5f954Brett RussMODULE_DESCRIPTION("SCSI low-level driver for Marvell SATA controllers"); 284320f733e7d75a16bffc34842b7682c9247dd5f954Brett RussMODULE_LICENSE("GPL"); 284420f733e7d75a16bffc34842b7682c9247dd5f954Brett RussMODULE_DEVICE_TABLE(pci, mv_pci_tbl); 284520f733e7d75a16bffc34842b7682c9247dd5f954Brett RussMODULE_VERSION(DRV_VERSION); 284620f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ 2847ddef9bb367b19383df627e388cb4c01c86ddba6cJeff Garzikmodule_param(msi, int, 0444); 2848ddef9bb367b19383df627e388cb4c01c86ddba6cJeff GarzikMODULE_PARM_DESC(msi, "Enable use of PCI MSI (0=off, 1=on)"); 2849ddef9bb367b19383df627e388cb4c01c86ddba6cJeff Garzik 285020f733e7d75a16bffc34842b7682c9247dd5f954Brett Russmodule_init(mv_init); 285120f733e7d75a16bffc34842b7682c9247dd5f954Brett Russmodule_exit(mv_exit); 2852